61114ea31b
Creates the 9-project .NET 8 solution (5 src + 4 test) with Marathon.Domain fully implemented: value objects (SportCode, EventId, OddsRate, OddsValue, BetScope hierarchy), enums (Side, BetType, OddsSource, AnomalyKind), and entities (Sport, Country, League, Event, Bet, OddsSnapshot, EventResult, Anomaly) with all invariants enforced in constructors. 96 domain tests pass (FluentAssertions + xUnit). Directory.Build.props and Directory.Packages.props centralise build settings and NuGet versions. Both Marathon.sln and Marathon.slnx are committed; dotnet build Marathon.sln succeeds with 0 warnings/errors.
113 lines
5.9 KiB
Markdown
113 lines
5.9 KiB
Markdown
# Feature: Initial Implementation (maraphon-app)
|
||
|
||
**Branch:** `feature/initial-implementation`
|
||
**Base branch:** `main`
|
||
**Created:** 2026-05-05
|
||
**Status:** 🟡 In Progress
|
||
**Strategy:** Big Bang
|
||
**Mode:** Automated
|
||
**Execution:** Orchestrator
|
||
**Implementer models:** Sonnet 4.6 (backend) · Opus (frontend, with frontend-design skill)
|
||
**Reviewer model:** Sonnet 4.6
|
||
|
||
## Summary
|
||
|
||
Build the maraphon-app end-to-end: a Blazor Hybrid (.NET 8 + WPF) sports-betting odds
|
||
analyzer that scrapes marathonbet.by, persists snapshots in SQLite, exports to Excel
|
||
matching the customer spec, and detects coefficient-flip anomalies. Architecture is
|
||
Clean Architecture with all UI in a Razor Class Library so the host can later swap to
|
||
ASP.NET Core Blazor Server with no UI rewrite. RU + EN localization, every variable
|
||
parameter configurable.
|
||
|
||
## Build & Test Commands
|
||
|
||
- **Build:** `dotnet build Marathon.sln`
|
||
- **Test:** `dotnet test Marathon.sln`
|
||
- **Lint:** `dotnet format Marathon.sln --verify-no-changes`
|
||
- **Run:** `dotnet run --project src/Marathon.Hosts.WpfBlazor`
|
||
|
||
> **Big Bang strategy:** Build/tests are NOT run for intermediate phases (Phases 0–8).
|
||
> The full build + test suite must pass at Phase 9 before final review.
|
||
> An exception: a `dotnet build` *compile-only smoke check* is allowed after each
|
||
> phase to catch syntax/type errors early — this is faster than running tests and
|
||
> consistent with Big Bang ("we don't run tests until the end").
|
||
|
||
## Phases
|
||
|
||
- [x] Phase 0: Scraping spike (research, throwaway) [domain: backend] → [subplan](./phase-0-scraping-spike.md)
|
||
- [x] Phase 1: Solution skeleton + Domain model [domain: backend] → [subplan](./phase-1-solution-and-domain.md)
|
||
- [ ] Phase 2: Infrastructure — Storage [domain: backend] → [subplan](./phase-2-storage.md)
|
||
- [ ] Phase 3: Infrastructure — Scraping [domain: backend] → [subplan](./phase-3-scraping.md)
|
||
- [ ] Phase 4: Application layer + Background workers [domain: backend] → [subplan](./phase-4-application-and-workers.md)
|
||
- [ ] Phase 5: Blazor Hybrid host + Theme + i18n [domain: frontend] → [subplan](./phase-5-host-theme-i18n.md)
|
||
- [ ] Phase 6: Event browsing UI [domain: frontend] → [subplan](./phase-6-event-browsing-ui.md)
|
||
- [ ] Phase 7: Anomaly detection [domain: fullstack] → [subplan](./phase-7-anomaly-detection.md)
|
||
- [ ] Phase 8: Results loader [domain: fullstack] → [subplan](./phase-8-results-loader.md)
|
||
- [ ] Phase 9: Packaging + polish (final phase — full build + tests required) [domain: fullstack] → [subplan](./phase-9-packaging-polish.md)
|
||
|
||
## Parallelization Plan (Orchestrator mode)
|
||
|
||
| Round | Phases | Notes |
|
||
|---|---|---|
|
||
| 1 | Phase 0 | Spike — gating research, no parallelism |
|
||
| 2 | Phase 1 | Domain — must finish before Phases 2/3/5 |
|
||
| 3 | **Phases 2, 3, 5 in parallel** | Storage, Scraping, UI Shell — disjoint files |
|
||
| 4 | Phase 4 | Application + Workers — depends on 2 + 3 |
|
||
| 5 | Phase 6 | Event UI — depends on 4 + 5 |
|
||
| 6 | Phase 7 | Anomaly detection — depends on 6 |
|
||
| 7 | Phase 8 | Results loader — depends on 6 |
|
||
| 8 | Phase 9 | Packaging — final, runs full build + tests |
|
||
|
||
## Phase Progress Log
|
||
|
||
| Phase | Domain | Status | Review | Build | Committed |
|
||
|---|---|---|---|---|---|
|
||
| Phase 0: Scraping spike | backend | ✅ Done | ⚠️ Pass with notes (Sonnet) | ⏭️ N/A (research) | ✅ 070e34b |
|
||
| Phase 1: Solution + Domain | backend | ✅ Done | ⬜ | ✅ Build OK | ⬜ |
|
||
| Phase 2: Storage | backend | ⬜ Not Started | ⬜ | ⏭️ Big Bang | ⬜ |
|
||
| Phase 3: Scraping | backend | ⬜ Not Started | ⬜ | ⏭️ Big Bang | ⬜ |
|
||
| Phase 4: Application + Workers | backend | ⬜ Not Started | ⬜ | ⏭️ Big Bang | ⬜ |
|
||
| Phase 5: Host + Theme + i18n | frontend | ⬜ Not Started | ⬜ | ⏭️ Big Bang | ⬜ |
|
||
| Phase 6: Event browsing UI | frontend | ⬜ Not Started | ⬜ | ⏭️ Big Bang | ⬜ |
|
||
| Phase 7: Anomaly detection | fullstack | ⬜ Not Started | ⬜ | ⏭️ Big Bang | ⬜ |
|
||
| Phase 8: Results loader | fullstack | ⬜ Not Started | ⬜ | ⏭️ Big Bang | ⬜ |
|
||
| Phase 9: Packaging + polish | fullstack | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
|
||
|
||
## Final Review
|
||
|
||
- [ ] Comprehensive code review (final-reviewer agent)
|
||
- [ ] Security review (auth N/A, but covers scraping HttpClient, file I/O, user input)
|
||
- [ ] Full build passes
|
||
- [ ] Full test suite passes
|
||
- [ ] User merge approval
|
||
- [ ] Merged to `main`
|
||
|
||
## Amendment Log
|
||
|
||
### Amendment 1 — 2026-05-05 — Phase 8 strategy change (deferred — formal approval will be requested when Phase 8 begins)
|
||
|
||
**Type:** Modify upcoming phase (Phase 8 — Results loader)
|
||
**What changed:** Phase 8's original subplan assumed marathonbet.by exposes a public
|
||
results / archive page that we can scrape to back-fill `EventResult`s. Phase 0 spike
|
||
proved this endpoint does NOT exist (`/su/results` returns 404).
|
||
|
||
**Why:** Spike findings — see `spike/SCRAPE_FINDINGS.md` and the deviation note in
|
||
`plans/initial-implementation/phase-0-scraping-spike.md` (Handoff section).
|
||
|
||
**New approach (to be formalised when Phase 8 begins):** Maintain a "watch list" of
|
||
events whose `ScheduledAt + EstimatedDuration` is in the past but whose status is not
|
||
`Completed`. Poll those event-detail URLs every 5 min until either
|
||
`eventJsonInfo.matchIsComplete=true` (capture `resultDescription`, mark complete) or
|
||
the URL 404s (mark `ResultUnknown`). Optional fallback to flashscore/sofascore is a
|
||
Phase 8 design decision.
|
||
|
||
**Impact on existing phases:** Phase 4 (Application + Workers) may need a new
|
||
`ResultsWatchListPoller : BackgroundService` in addition to the previously planned
|
||
`UpcomingEventsPoller` and `LiveOddsPoller`. Phase 2 schema may need a `WatchStatus`
|
||
field on `Event` (`Pending | InWatchList | Completed | ResultUnknown`). Both will be
|
||
re-evaluated when Phase 8 starts.
|
||
|
||
**Status:** Logged — formal subplan revision and user approval will be requested at the
|
||
start of Phase 8 (per skill rule: "All amendments require explicit user approval before
|
||
taking effect"). Phases 1–7 do not depend on Phase 8's tactical implementation.
|