Files
SportstimeAPI/.planning/phases/01-semantic-position-model/01-01-PLAN.md
Trey t a7d0e7f049 fix(01): revise plans based on checker feedback
- 01-01: Reframe must_haves.truths to user-observable behaviors
- 01-01: Remove unimplemented key_link (wiring happens in later phases)
- 01-02: Add test case for DATA-04 (custom items at any position)
- 01-02: Add must_haves.truths entry for custom item flexibility
- 01-02: Document LocalItineraryItem is standalone (no sibling models needed)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 13:47:12 -06:00

152 lines
5.4 KiB
Markdown

---
phase: 01-semantic-position-model
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- SportsTime/Core/Models/Domain/SortOrderProvider.swift
- SportsTime/Core/Models/Domain/Trip.swift
autonomous: true
must_haves:
truths:
- "Games sort by schedule time within each day"
- "Items can be inserted at any position (before, between, after existing items)"
- "Items can be assigned to any trip day by date calculation"
artifacts:
- path: "SportsTime/Core/Models/Domain/SortOrderProvider.swift"
provides: "sortOrder calculation utilities"
exports: ["initialSortOrder(forGameTime:)", "sortOrderBetween(_:_:)", "sortOrderBefore(_:)", "sortOrderAfter(_:)", "needsNormalization(_:)", "normalize(_:)"]
- path: "SportsTime/Core/Models/Domain/Trip.swift"
provides: "Day derivation methods"
contains: "func dayNumber(for date: Date) -> Int"
key_links: []
---
<objective>
Create the sortOrder calculation utilities and day derivation methods that Phase 1 depends on.
Purpose: Establish the foundational utilities for semantic position assignment. Games need sortOrder derived from time, travel/custom items need midpoint insertion, and items need day derivation from trip dates.
Output: `SortOrderProvider.swift` with all sortOrder utilities, `Trip.swift` extended with day derivation methods.
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/01-semantic-position-model/01-RESEARCH.md
# Existing source files
@SportsTime/Core/Models/Domain/ItineraryItem.swift
@SportsTime/Core/Models/Domain/Trip.swift
</context>
<tasks>
<task type="auto">
<name>Task 1: Create SortOrderProvider utility</name>
<files>SportsTime/Core/Models/Domain/SortOrderProvider.swift</files>
<action>
Create a new file `SortOrderProvider.swift` with an enum containing static methods for sortOrder calculation.
Include these methods (as specified in 01-RESEARCH.md):
1. `initialSortOrder(forGameTime: Date) -> Double`
- Extract hour and minute from game time
- Calculate minutes since midnight
- Return 100.0 + minutesSinceMidnight (range: 100-1540)
- This ensures games sort by time and leaves room for negative sortOrder items
2. `sortOrderBetween(_ above: Double, _ below: Double) -> Double`
- Return (above + below) / 2.0
- Simple midpoint calculation
3. `sortOrderBefore(_ first: Double) -> Double`
- Return first - 1.0
- Creates space before the first item
4. `sortOrderAfter(_ last: Double) -> Double`
- Return last + 1.0
- Creates space after the last item
5. `needsNormalization(_ items: [ItineraryItem]) -> Bool`
- Sort items by sortOrder
- Check if any adjacent gap is less than 1e-10
- Return true if normalization needed
6. `normalize(_ items: inout [ItineraryItem])`
- Sort by current sortOrder
- Reassign sortOrder as 1.0, 2.0, 3.0... (integer spacing)
- Updates items in place
Use `Calendar.current` for date component extraction. Import Foundation only.
</action>
<verify>
File exists at `SportsTime/Core/Models/Domain/SortOrderProvider.swift` with all 6 methods. Build succeeds:
```bash
xcodebuild -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' build 2>&1 | tail -20
```
</verify>
<done>SortOrderProvider.swift exists with all 6 static methods, project builds without errors</done>
</task>
<task type="auto">
<name>Task 2: Add day derivation methods to Trip</name>
<files>SportsTime/Core/Models/Domain/Trip.swift</files>
<action>
Extend the existing Trip struct with day derivation methods in a new extension at the bottom of the file.
Add these methods:
1. `func dayNumber(for date: Date) -> Int`
- Use Calendar.current to get startOfDay for both startDate and target date
- Calculate days between using dateComponents([.day], from:to:)
- Return days + 1 (1-indexed)
2. `func date(forDay dayNumber: Int) -> Date?`
- Use Calendar.current to add (dayNumber - 1) days to startDate
- Return the resulting date
Add a comment block explaining:
- Day 1 = trip.startDate
- Day 2 = startDate + 1 calendar day
- Games belong to their start date (even if running past midnight)
These methods complement the existing `itineraryDays()` method but work with raw Date values rather than the Trip's stops structure.
</action>
<verify>
Build succeeds and new methods are callable:
```bash
xcodebuild -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' build 2>&1 | tail -20
```
</verify>
<done>Trip.swift has dayNumber(for:) and date(forDay:) methods, project builds without errors</done>
</task>
</tasks>
<verification>
1. Both files exist and contain expected methods
2. `xcodebuild build` succeeds with no errors
3. SortOrderProvider methods are static and accessible as `SortOrderProvider.methodName()`
4. Trip extension methods are instance methods callable on any Trip value
</verification>
<success_criteria>
- SortOrderProvider.swift exists with 6 static methods for sortOrder calculation
- Trip.swift extended with dayNumber(for:) and date(forDay:) methods
- Project builds successfully
- No changes to existing ItineraryItem.swift (model already has correct fields)
</success_criteria>
<output>
After completion, create `.planning/phases/01-semantic-position-model/01-01-SUMMARY.md`
</output>