Skip to content

Update external_data submodule to 0a53315 (XWA 50pt data + new expansions, legacy -> Darker333 master) - #131

Open
Franc3s-bot wants to merge 192 commits into
Francespo:mainfrom
Franc3s-bot:slim-parrot
Open

Update external_data submodule to 0a53315 (XWA 50pt data + new expansions, legacy -> Darker333 master)#131
Franc3s-bot wants to merge 192 commits into
Francespo:mainfrom
Franc3s-bot:slim-parrot

Conversation

@Franc3s-bot

Copy link
Copy Markdown
Contributor

Updates the external_data submodule pointer to Francespo/xwing-unified-data commit 0a53315.

Includes:

  • xwing-data2 bumped to 26501161: gregkash16 master base + 36 open J1mBob PRs (fixes, new cards, image links) + fork history preserved. Ric Olié now 11 pts / 16 loadout (50-point scale, was 4/12 on 20-pt scale).
  • xwing-data2-legacy pointed to Darker333/xwing-data2-legacy master (dbb1dd6) with branch = master tracking instead of a pinned commit.

Verification: JSON valid, merge conflicts resolved, working tree clean.

Francespo and others added 30 commits March 4, 2026 19:28
…cespo#46)

Fixed the backend import issues with faction char and improved the
startup script to avoid opening new windows and handle dynamic ports.
…provements

# Conflicts:
#	backend/analytics/factions.py
#	backend/analytics/ships.py
… with search bar

- Add GET /api/tournaments/locations endpoint returning distinct locations
- Split location filter into 3 dynamic sub-filters (Continent, Country, City)
- Countries update based on selected Continents, Cities based on selected Countries
- Add mini search bar to filter location entries
- Remove duplicate Unknown entries from continent list
…tructure

- Move ShipChassisFilter below Faction on ships, cards, lists, squadrons pages
- Remove accordion expand/collapse; make it a flat static section
- Ship icons in filter inherit text color (uncolored)
- Faction symbols remain colored next to ship names
- Respects specificity hierarchy: Sort By > Faction > Ship Chassis
Closes Francespo#37. This PR fixes three critical bugs in the analytics modules:

1. **Tournament filters ignored**: Added centralized location filtering
via �pply_tournament_filters() and updated SQL filters.
2. **Lists count 0**: Added lists aggregation to core.py.
3. **Frontend filters ignored**: Merged main, resolved UI conflicts, and
fixed a Svelte a11y bug (�11y_consider_explicit_label) that caused a 500
error.
# Conflicts:
#	backend/analytics/factions.py
#	backend/analytics/ships.py
…provements

# Conflicts:
#	backend/analytics/ships.py
#	backend/api/ships.py
#	frontend/src/routes/lists/+page.svelte
#	frontend/src/routes/ships/+page.svelte
…ion bugs (Francespo#45)

Closes Francespo#42.

## Technical Changes
- Replaced SSR data loading in `+page.ts` with reactive client-side
`$effect` fetching to resolve route navigation desync and crashes.
- Replaced hardcoded 'XWA / Analysis Mode' title with the
`<ContentSourceToggle />` component in the header.
- Implemented reactive data fetching based on the global
`filters.dataSource` state to seamlessly switch between XWA and Legacy
data sets without requiring a page reload.
Closes Francespo#38

## Summary

Adds the Ships / Chassis page with filtering capabilities and fixes the
hover scaling behavior on ship cards.

## Changes

### Backend
- **New** `backend/routers/ships.py`: FastAPI router exposing `GET
/api/ships` with optional `faction` and `source` query params.
- **Modified** `backend/main.py`: Registers the ships router under
`/api` prefix.
- **Fixed** `backend/utils/xwing_data/core.py`: Corrected `ROOT_DIR`
path (`parents[4]` to `parents[3]`).

### Frontend
- **New** `frontend/src/routes/ships/+page.svelte`: Ships page with
chassis filter dropdown, faction filter, responsive card grid, and
**hover scale on entire card container** (not inner icon).
- **Modified** `frontend/src/routes/+layout.svelte`: Added navigation
bar with Ships link.
- **Modified** `frontend/vite.config.js`: API proxy to FastAPI backend.

## Technical Rationale

The hover scaling fix places `transform: scale(1.06)` on the outer
`.ship-card` container rather than inner icon wrappers, ensuring the
entire card elevates uniformly on hover.
# Conflicts:
#	frontend/src/routes/squadrons/+page.svelte
Closes Francespo#43.

- Alphabetized SortSelector options list.
- Changed SVG arrows to use distinct upward/downward pointing icons.
- Updated Squadrons page to use SortSelector component.
- Used getFactionLabel instead of raw faction key in SquadronRowCard.
Removes remaining garbage files and logs from main.
Closes Francespo#44. Identified 6 missing ship icons in xwing-miniatures.css by
comparing with JSON data. Added mappings for ieininterceptor,
delta7baethersprite, cr90corelliancorvette, iesebomber, and
upsilonclassshuttle. Trident remains without icon as per user feedback.

---------

Co-authored-by: Francesco Esposito <95753785+Francespo@users.noreply.github.com>
…rancespo#57)

## Description
This PR fixes the accidental creation of a local font directory in the
frontend and establishes a single source of truth using a symlink.

- Migrated centered xwing-miniatures.css to
external_data/xwing-miniatures-font/dist/.
- Removed local rontend/static/fonts/xwing-miniatures-font/ directory.
- Created a directory junction (symlink) pointing to the source in
external_data.
- Squashed branch history into a single clean commit.

Co-authored-by: Francesco Esposito <95753785+Francespo@users.noreply.github.com>
Closes Francespo#52. \n\n### Changes Made:\n- **Standardized Labeling**: All
unknown tournament formats and scenarios now use the label 'Unknown'.\n-
**Fixed UNK Badges**: Verified that unknown formats correctly display
the 'UNK' badge in the Tournament Browser list.\n- **Sidebar UI
Polish**:\n - Restored horizontal dividers between all major filter
sections.\n - Fixed double divider issue when Active Filters list is
empty.\n - Restored bottom borders for accordion items.\n - Standardized
vertical spacing across all sections (Date, Location, Format, Platform,
Search, and Sort) by removing redundant margins and padding for a clean,
contiguous look.

---------

Co-authored-by: Francesco Esposito <95753785+Francespo@users.noreply.github.com>
Franc3s-bot and others added 28 commits June 25, 2026 19:30
Resolve pre-existing LSP/static-analysis warnings across 4 files:
- backend/api/tournaments.py (34 errors)
- backend/scripts/scrape_tournaments.py (17 errors)
- backend/api/formatters.py + backend/api/schemas.py (10 errors)
- frontend/vite.config.js (3 implicit-any errors)

Includes two real bug fixes surfaced during type cleanup:
- Match(...) and PlayerStanding(...) constructors in scrape_tournaments.py
  were missing tournament_id, silently writing NULL FKs in the dict-based
  save path and the _write_sqlite artifact path.
Replaces PR Francespo#92's partial fix with a from-scratch mobile shell, a
centralized filter URL-sync layer, and a stack of targeted perf and
responsiveness fixes. The 5 filterable routes no longer maintain
their own URL-building logic; the store owns it.

Mobile shell (new components):
- MobileTopBar: sticky top chrome for <md viewports (hamburger + brand)
- MobileNavDrawer: left-edge nav drawer, focus-trapped, ARIA dialog,
  sourced from Sidebar.NAV_LINKS module export
- MobileFilterDrawer: right-edge filter sheet accepting a children +
  optional footer snippet
- MobileFilterTrigger: FAB with active-filter count badge, <lg only
- DebouncedTextInput: 250ms-debounced search input

Filter system (filters.svelte.ts):
- toSearchParams(routeId): per-route whitelist serializer with
  deterministic key order (round-trip identity for the echo guard)
- applyFromSearchParams(params): URL -> store, partial-update only
- selectedFactions / sortBy / sortDirection: moved from route-local
  state into the store
- activeChips:  (was a getter that re-ran per access)

URL sync (lib/sync/urlSync.svelte.ts):
- scheduleSync(delayMs?, overlay?): debounced goto() with echo guard,
  URL-key round-trip identity, replaceState + keepFocus + noScroll
- clearPendingSync(): called by onNavigate in +layout.svelte so
  fast route switches do not corrupt the destination URL

Route rewrites (cards, lists, ships, squadrons, tournaments):
- Per-field URL-building  (20-64 lines each) replaced with
  5-10 line thin effect using filters.toSearchParams + scheduleSync
- route-local selectedFactions / sortBy / sortDirection removed
- echo-guard logic lives in urlSync, not in each route
- ~200 lines of duplicated URL plumbing deleted across 5 files

Per-route perf + responsive fixes:
- ships: 5 inline style attributes per card collapsed to 1 (with
  CSS custom properties); font-size: 10rem -> clamp(3rem, 18vw, 8rem)
- squadron/[signature]: 6-col pilot table collapses to stacked
  card layout on <sm
- ship/[xws]: right-edge gradient fade hints at horizontal scroll
  on <sm
- cards: dynamic import('$app/navigation') -> static goto import
  in tab handlers
- +page.svelte (dashboard): chartAction uses chart.update(newConfig)
  instead of destroy/recreate; chart.js auto-import hoisted to module
- TournamentFilters: $derived(() => fn()) misuse -> $derived.by

Misc:
- Sidebar: NAV_LINKS exported as the single source of truth for
  nav entries (consumed by both desktop sidebar and mobile drawer)
- FilterPanel: rewritten to desktop-only with a children snippet;
  routes pass the same snippet to MobileFilterDrawer for mobile
- MobileFilterDrawer / MobileNavDrawer: migrated from deprecated
  $app/stores to $app/state
- +layout.svelte: client-only $effect calls
  filters.applyFromSearchParams on mount, onNavigate cancels
  pending syncs

Touch targets: hamburger, nav links, FAB, sort direction button,
content-source toggle, drawer close buttons all >= 44x44. Active
filter count visible on the FAB badge and the drawer header.

Behavior: empty filters.sortBy / sortDirection produce empty URL
params which the backend fills with its own Query() defaults
(cards/ships/squadrons/lists: 'Popularity' or 'Games'; tournaments:
'Date'), so first-visit sort order is preserved.
The backend's startup cache prewarm was racing with db-seed's
pg_restore. The backend depends_on db-seed used condition:
service_started, which fires as soon as the db-seed container
starts (before the dump is actually loaded). The prewarm then
computed analytics against an empty database and cached empty
results, which the cache never invalidated (scrape_meta is
missing from the dump, so the version-based invalidation never
fires).

Add a healthcheck to db-seed that polls the `list` table for a
non-zero row count, and change the backend to depend on
service_healthy. This ensures the dump is fully restored before
the backend (and its prewarm) starts, so the cache is seeded
with real data on the first run.
Allows choosing the Vite dev server port on startup:
  bash scripts/local_dev/up.sh --port 4444
  bash scripts/local_dev/up.sh --port=4444

Default is unchanged (3333). Validates the port is a number
between 1 and 65535 and rejects unknown arguments. Also adds
--help / -h.

The four hardcoded 3333 references (ORIGIN, vite --port,
healthcheck URL, log-parser fallback) now use $VITE_PORT /
$DEFAULT_PORT.
- Add min-w-0 to main and card to prevent flex overflow on mobile
- Split layout into mobile (2-row) and desktop (3-column) at sm breakpoint
- Mobile: title + format chip + player count inline, date + location below
- Desktop: format badge column, info column, player count column
- Format label/color hoisted to @const per iteration for clarity
- Ensure 44px min tap target, proper truncation, no horizontal scroll
…tion, stats fix, upgrades

Round 13–22 frontend improvements:

Browser pages (tournaments, squadrons, lists, cards, ships):
- Remove DATE label from tournament rows; wrap location in styled pill
- Replace boxed 'N x FOUND' pills with faded-text below title (no box)
- Remove ActiveChips from main content; active filters only in sidebar
- Fix squadron count to show backend total (8663) instead of page capacity
- Apply custom Toggle to all checkboxes (squadrons, lists, cards, ships)
- Add SortBy component to every list section across all browser pages

Filter system:
- Create Toggle component (squared, 2px-radius, black bg, white check)
- Fix multi-select format bug (isFormatsAtDefault URL round-trip)
- Fix urlSync echo loop and stale-URL race condition
- Fix overlay-merge loop in urlSync (params.set multi-value bug)
- Add Format count badge to TournamentFilters label
- Add overflow-x-hidden to FilterPanel, MobileFilterDrawer, layout

Ship detail page:
- Add FactionIcon component (plain '?' for unknown factions, XWing glyph for known)
- Replace 21 callsites with FactionIcon across 14 files
- Fix match score colors (winner green pill, loser red, tie grey)
- Fix Gauntlet 5-color gradient (start%/end% hard-stop syntax)
- Fix ships page filter to honor selectedChips (frontend bug)
- Remove all glows from ship detail hero card

Sort and layout:
- Remove SortSelector from filter panels (replaced by inline SortBy)
- Add SortBy to dashboard sections, pilot detail, upgrade detail, etc.
- Fix SortBy labels: 'Popularity' → 'Games'/'Lists'
- Remove rounded rectangle wrapper from dashboard SortBy
- Fix Cards page SortBy to match filter dropdown options
- Remove 'Compatibility' option from pilot detail Top Configurations

Back navigation:
- BackLink uses history.back() with href fallback for fresh tabs
- All 6 detail pages benefit automatically (useHistory=true default)

Stats and data:
- Backend: fix ship_list_filter_clause with mode=all for AND semantics
- Backend: add list_id to PlayerStandingData schema
- Backend: add win_rate to aggregate_list_stats output
- Backend: clamp swiss_wins/losses/rank default from -1 to 0
- Data migration script for clamping negative stats
- Fix squadron win rate (was always 0% — use backend win_rate field)

Miscellaneous:
- Fix multi-faction ship gradient on ships browser page
- Fix content-source filter on pilot detail page
- Mobile: add Epic toggle to top bar, TournamentFilters to drawer
- Desktop sidebar: XWA/LEGACY/Epic compact toggle
- Add info tooltip to Tournament Filters label
- Fix horizontal scrollbar in filter column
- Remove all glows from ship detail hero card
All conflicts resolved in favor of dev (HEAD) which has the superior
architecture: normalized list table, SQL GROUP BY queries, filter_helpers,
ScrapeMeta model, BaseScraper type hints, coerce_list_json, pool tuning,
and the full mobile-first UI rebuild.

Upstream changes (minor: duplicate imports, pyright annotations already
present in dev) are subsets of what dev already contains.

Conflict files:
- .devcontainer/ (2): node feature versions, gemini-cli vs sshd
- .gitignore: slim/deepwork + playwright paths vs duplicate node_modules
- backend/analytics/ (5): SQL GROUP BY vs Python-loop aggregation
- backend/api/ (4): normalized list table queries vs legacy Python loops
- backend/infra (3): ScrapeMeta model, pool_size, coerce_list_json import
- backend/scripts/ (2): list table persistence, BaseScraper types
- frontend/+page.svelte: meta-snapshot URL builder (HEAD's params approach)
Co-authored-by: GitHub Copilot <copilot@users.noreply.github.com>
Co-authored-by: Frances-bot <263591795+Franc3s-bot@users.noreply.github.com>
58,603 playerstanding rows had swiss_wins=-1, swiss_losses=-1 as
scraper sentinels (rollbetter). COALESCE(..., 0) does not help since
-1 is not NULL, causing negative game counts and broken winrates.

Wrap all COALESCE in SUM() with GREATEST(0, ...) across:
- core.py (pilots + upgrades queries)
- ships.py
- squadrons.py
- lists.py
- factions.py (Python-side max(0, ...))

Database rows also cleaned to 0.
Preview deployments were failing because the SSR API routes used the
public backend URL (e.g. https://127.api.dev.m3tacron.com/api) which:
1. Requires DNS wildcard records that may not match Coolify's generated
   domain pattern (127.dev.api.m3tacron.com vs 127.api.dev.m3tacron.com)
2. Causes HTTP->HTTPS redirect loops when url.protocol is http: behind
   a reverse proxy (Traefik)

Now preview deployments talk directly to the backend container via the
internal Docker Compose network (http://backend:8888/api), which is
faster, simpler, and works regardless of external DNS configuration.
SvelteKit's url.hostname is derived from the ORIGIN env var, not the
actual request Host header. When ORIGIN=https://dev.m3tacron.com is set
for preview deployments, url.hostname resolves to dev.m3tacron.com
instead of 127.dev.m3tacron.com, causing the host-based preview URL
matching to fail.

Now we check ENV_VAR_SOURCE=preview or COOLIFY_BRANCH.startsWith('pull/')
to detect preview deployments and route API calls to the internal
Docker network (http://backend:8888/api) before host matching.
- docker-compose.local.yml: use ${POSTGRES_PORT:-5435} and ${BACKEND_PORT:-8890} env vars
- up.sh: read BACKEND_PORT/POSTGRES_PORT/VITE_PORT from env, pass through to healthcheck and Vite
- status.sh: health probes use env vars instead of hardcoded ports
- pyproject.toml: set explicit setuptools package discovery (include backend* only)
- Retry submodule init once on failure
- Fall back to copying external_data/ from source checkout if clone fails twice
- Clean error reporting at each step
- Remove verify*.png screenshots, commit_message.json, .slim/codemap.json
- Expand .gitignore: .slim/ (not just deepwork), verify*.png, commit_message.json
- Starts Docker stack (postgres + backend), waits for health, then Vite in foreground
- Configurable ports via --port, --backend-port, --postgres-port or env vars
- Registered as 'launch' service in paseo.json
Preview deployments set COOLIFY_URL to the correct PR-specific URL
(e.g. https://128.dev.m3tacron.com). By using ORIGIN=,
production uses its explicit ORIGIN value while previews automatically
get the correct PR URL from COOLIFY_URL.
- Add launch.sh as primary quick start (foreground, agent-friendly)
- Document parameterized ports (BACKEND_PORT, POSTGRES_PORT, VITE_PORT)
- Add Paseo worktree integration section (worktree_setup.sh, parallel worktrees)
- Add submodule fallback troubleshooting
- Fix statement_timeout (120s, not 60s)
- Reorder helper commands table
…endent

- ensure-setup.sh: single source of truth for dependency setup (submodules, venv, npm, dump, SSH key)
- launch.sh: calls ensure-setup.sh then launches stack
- worktree_setup.sh: thin wrapper around ensure-setup.sh
- Paseo hook and launch both share the same setup logic
- Removed .agents/skills/m3tacron/ssh_key from git tracking
- Added ssh_key and ssh_key.pub to .gitignore secrets section
- Key was exposed in git history — MUST be rotated on the server
- seed.sh: default key path ~/.ssh/m3tacron_audit_bot
- ensure-setup.sh: remove SSH key copy logic
- paseo.json: remove key override from seed, remove .ssh from teardown
- m3tacron skill: document key setup as machine prerequisite
- local-dev skill: update prereqs and data locations
- launch.sh/up.sh: auto-detect tailnet hostname via tailscale CLI
- VITE_ALLOWED_HOSTS includes tailnet hostname for CORS
- ORIGIN set to tailnet URL so SvelteKit works for other users
- Banner shows both local and tailnet URLs
- status.sh: show tailnet access URLs
- local-dev skill: document tailnet access section
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

2 participants