Presentation Layer - gregw/sailing-pf GitHub Wiki
Presentation Layer
Architecture
The presentation layer is a browser-based admin webapp consuming a RESTful JSON API served by Jetty 12.1 embedded servlets. There is no server-side HTML rendering β the backend serves data only; the frontend handles all display and interaction.
This architecture serves two goals:
- A rich, interactive admin experience with client-side charting and data management
- An openly accessible JSON API that third parties can consume directly to build their own tools on top of the project's derived data
Backend: Jetty Servlets
The server runs on port 8080 via HpfServer.main(). Three servlets handle all requests:
AdminApiServlet β /api/*
REST API for data access and management. Supports paginated responses (default page size 50).
GET endpoints:
/api/boatsβ paginated boat list with optional search/filter query parameters/api/boats/{id}β single boat detail (certificates, aliases, sources)/api/designsβ paginated design list with boat counts/api/designs/{id}β single design detail/api/racesβ paginated race list with date/club filtering/api/races/{id}β single race detail (divisions, finishers)/api/importersβ list configured importers and their schedule/api/statsβ summary statistics (boat/design/race counts, reference factor coverage)
POST endpoints:
/api/importers/{name}/runβ trigger an importer run/api/importers/stopβ request stop of running import/api/configβ update admin configuration (schedule, thresholds)/api/exclusionsβ manage excluded boat/design/race IDs/api/mergeβ merge duplicate boats or designs (updates aliases.yaml)
AnalysisServlet β /api/analyse/*
REST API for analysis results from AnalysisCache:
/api/analyse/comparisonsβ list all available comparison keys/api/analyse/comparisons/{id}β get comparison result (pairs, fit, outliers) for a specific key/api/analyse/reference-factorsβ per-boat reference factors/api/analyse/design-factorsβ per-design aggregated factors
StaticResourceServlet β /*
Serves the admin frontend HTML, JavaScript, and CSS from classpath resources (src/main/resources/content/).
Frontend: Admin Webapp
A static single-page application (HTML + JavaScript), served as classpath resources. Charts rendered client-side using Plotly.js. No React, no build pipeline β plain JavaScript with DOM manipulation.
Pages
Data Browser (data.html + data.js):
- Paginated tables for boats, designs, and races with search/filter
- Drill-down to individual entity details (certificates, race history, design members)
- Manual merge interface for duplicate boats and designs
- Exclusion management (mark boats/designs/races as excluded from analysis)
Analysis (analysis.html + analysis.js):
- Dropdown selection of comparison type (systemΓyearΓvariant pairs)
- Plotly.js scatter plots showing paired observations with linear fit overlay
- Reference factor inspection per boat (spin, non-spin, two-handed with generation info)
- Design-level factor display
Import Management (import.html + import.js):
- Run individual importers (sailsys-races, orc, ams, topyacht, bwps, analysis, reference-factors, build-indexes)
- Configure scheduled runs (days of week, time)
- Live progress display for running imports
- Stop button for running imports
Chart Types (Implemented)
- Scatter plots β paired handicap observations (x=system A TCF, y=system B TCF) with least-squares fit line
- Residual highlights β outlier pairs shown in different colour after sigma trimming
Chart Types (Future β requires Phase 2)
- Time series / scatter β PF estimates per boat per race within a series
- Box plots or violin plots β PF distribution per boat or per design across a season
- Comparison overlays β two or more boats or designs on the same axes
Configuration
Admin configuration is stored in hpf-data/config/admin.yaml and managed via the admin webapp
or direct file editing. Key settings:
importers: # list of importers with name, mode, includeInSchedule
schedule:
days: [MONDAY, SUNDAY] # days to run scheduled imports
time: "09:45:00" # time of day for scheduled runs
sailsysNextRaceId: 32638 # resume point for SailSys race scanning
targetIrcYear: 2025 # target year for reference factor DFS
outlierSigma: null # outlier trimming threshold (null = default 2.5)
clubCertificateWeight: 0.9 # weight multiplier for club-level certificates
sailsysCacheMaxAgeDays: 7
sailsysHttpDelayMs: 200
sailsysRecentRaceDays: 14