Spaces:
Sleeping
Sleeping
File size: 3,344 Bytes
18911ed 5ba47e2 18911ed 5ba47e2 18911ed 5ba47e2 18911ed | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | # Encyclopedia tab
The `encyclopedia` tab in `app/ui.py:build_demo()` is the break browser.
It reads the generated knowledge base, filters it, plots it, and feeds
the selected break to the `surf forecast` tab via shared `gr.State`.
## Data source
- `data/australia-surf-breaks-enriched.json` β `load_breaks()` (`app/breaks_data.py`)
into `DF`. Legacy `{"name | state | region": {...}}` dict format is
accepted; rows with an `error` column are dropped.
- Derived at import time: `STATES`, `REGIONS_BY_STATE`, `ALL_REGIONS`,
`SKILLS` (filtered to `SKILL_ORDER`: beginner β intermediate β
advanced β expert β pro-only).
- Enriched `id` is `"<name> | <state> | <region>"`. Canonical
`state`/`region` come from the input list, never the model.
## Filtering
`filter_breaks(df, state, region, skill)` β `"All"` / `None` means no
filter, comparison is case-insensitive on `state` / `region` /
`skillLevel`.
- `state_dd.change` β `update_region_choices` (narrows region list) β
`update_map` β `sync_custom_from_filters` (pushes map State/Region
into the generation form; `All` leaves the field untouched via
`gr.skip()`).
- `region_dd` / `skill_dd` β `update_map`.
`update_map` returns `(map fig, break choices, records, count, empty
details)`. Unfiltered view frames the whole of Australia
(`AUSTRALIA_CENTER`, zoom 3.5); otherwise the map auto-centers/zooms via
`_zoom_for_span()`.
## Map
- `build_map(records, default_view)` β Plotly `Scattermap`,
`open-street-map` style, marker colour by `SKILL_COLORS`. Point order
matches records order so the break list lines up.
- `build_map_with_custom(base_records, custom)` β adds the gold star
(`#FFD700`) marker for the session break.
- `_lat()` / `_lng()` return `None` on missing coords; those points are
skipped for centering.
## Details + selection
- `break_dd` (Radio, `.break-list`) β `on_break_pick` β
`break_to_table(record)`, a 16-row Field/Value dataframe
(name/state/region/description/skill/break+peak type/coords/ideal
swell+wind+tide/season/hazards/crowd).
- `_resolve_pick(label, base_records, custom)` maps the label back to its
record; the custom break carries a `β (your break)` suffix and matches
by suffix, base records match by `name`.
- `on_break_pick` also sets shared `selected_break` state and updates the
forecast tab header + skill default (break's own `skillLevel`,
validated against `SKILL_ORDER`, fallback `intermediate`).
## Session-only custom break
- `generate_custom_break()` (in `app/custom_break.py`) streams `(telemetry, details, map, dropdown,
state)` tuples via `yield`. Lazy `from app import generate_surf_break`
(direct package import, no `importlib` shims).
- Empty custom state/region fields fall back to the main map filters;
explicit values win. Exactly one custom break per session (`gr.State`,
never written to disk); regeneration replaces it.
- `clear_custom_break(base_records, selected)` deletes it; if the deleted
break was the forecast selection, the forecast header/skill reset too.
- `clear` / `generate` do not auto-select the forecast state β pick the
break in the list first, then fetch on tab 2.
## Theme
Lo-fi via `APP_CSS`: light blue bg `#d6e9f8`, dark blue `#0b2c5c`,
Courier. Don't restyle without asking. Callbacks stay wired in
`build_demo()`.
|