---
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: []
---
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.
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
@.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
Task 1: Create SortOrderProvider utility
SportsTime/Core/Models/Domain/SortOrderProvider.swift
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.
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
```
SortOrderProvider.swift exists with all 6 static methods, project builds without errors
Task 2: Add day derivation methods to Trip
SportsTime/Core/Models/Domain/Trip.swift
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.
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
```
Trip.swift has dayNumber(for:) and date(forDay:) methods, project builds without errors
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
- 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)