Skip to content

Enhance statistics view - #18

Merged
austin-smith merged 9 commits into
mainfrom
improve-stats-view
Feb 23, 2026
Merged

austin-smith merged 9 commits into
mainfrom
improve-stats-view

Conversation

@austin-smith

Copy link
Copy Markdown
Owner
  • Statistics screen now opens with a highlights row showing win rate, best time, and games won at a glance
  • A win/loss bar visualizes the ratio inline, with hover tooltips showing exact counts
  • Clean wins (wins completed without using hints, undos, or redeals) are now tracked shown with an info popover explaining the criteria
  • High scores now display "-" when no games of that draw mode have been played, instead of 0
  • A Reset Statistics button lets users clear all stats, with a destructive confirmation dialog
  • A "Tracked since" date is shown at the bottom of the stats sheet

Add Highlights section to stats view and break out stats view into dedicated file, instead of being intermixed with settings
Render a visual win/loss bar in StatisticsView and show counts on hover. Adds a barHoverState @State, a winLossBar view that computes win/loss widths via GeometryReader, and a reusable barSegment helper that updates hover state with onContinuousHover. Integrates the bar below the Win Rate row when games have been played to give a quick visual summary of wins vs losses.
Replace the stats value font in StatisticsView.swift from a rounded subheadline to a monospaced headline with bold weight. This increases prominence and improves alignment/readability of numeric values in the statistics UI.
Change GameStatistics.highScoreDrawThree and highScoreDrawOne from Int to Int? to represent unset scores. Update initializer and sanitization to use optional mapping, and use nil-coalescing when computing new highs. Update StatisticsView to display "-" when a high score is nil instead of printing 0, making it clear when no score is set.
Add tracking for hint requests, undos and redeal usage across a game and persist those metrics in SavedGamePayload. Introduce cleanWins to GameStatistics with decoding/sanitization, a cleanWinRate, and update recordCompletedGame to accept hints/undos/redeal and increment cleanWins for wins with no hints, undos or redeals. Wire up SolitaireViewModel to record/reset these counters, include them in saved/restored payloads, and pass them when finalizing a game. Update StatisticsView to show a "Clean Wins" row with an info popover and formatting. Add unit tests (GameStatisticsCleanWinTests) covering clean-win behavior and legacy decoding.
Introduce an optional trackedSince Date to GameStatistics (with CodingKey, init, decoding) to record when stats tracking began. Add helper methods markTrackingStarted(at:) and reset(at:) and expose store APIs (GameStatisticsStore.markTrackingStarted / reset). Update SolitaireViewModel to mark tracking started when a new session is created. Enhance StatisticsView with a Reset Stats button, confirmation dialog, trackedSince label, and resetStatistics() handler to clear stats. These changes allow tracking the statistics start date and provide a safe UI flow to reset statistics.
Fix tracking initialization by setting hasStartedTrackedGame to false so the bootstrap startup does not count as an active tracked game. This prevents the initial app launch from being immediately finalized as a played game while still recording the trackedSince timestamp.

Add GameSessionTrackingTests.swift with comprehensive unit tests covering startup, first and second New Game behavior, redeal handling, and restore behavior for active/finalized/untracked saved payloads. Tests exercise GameStatisticsStore and unfinalized elapsed-time reporting to validate the game session tracking lifecycle.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 88a39b7080

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ComputerSolitaire/Game/GamePersistence.swift
Comment thread ComputerSolitaire/Views/StatisticsView.swift
Add resetStatisticsTracking() to SolitaireViewModel to clear in-memory tracking state (hasStartedTrackedGame, isCurrentGameFinalized, hintRequestsInCurrentGame, undosUsedInCurrentGame, usedRedealInCurrentGame). Invoke this from StatisticsView.resetStatistics so clearing persistent GameStatisticsStore also untracks the active session and prevents pre-reset progress from being counted. Add a unit test to verify that a reset untracks the current session until a new game starts and that gamesPlayed only increments after the next new game.
@austin-smith

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 83dbfb6e9c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ComputerSolitaire/Views/StatisticsView.swift
Add SwiftData modelContext to StatisticsView and persist the tracking-reset payload when statistics are reset. Introduces persistTrackingResetIfNeeded() which saves viewModel.persistencePayload() into the modelContext and logs errors in DEBUG builds. Updates tests to assert the reset payload reflects no started tracked game and a finalized current game. This ensures a statistics reset is stored so app state remains consistent across launches.
@austin-smith

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1aa1906e1c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ComputerSolitaire/Game/GamePersistence.swift
@austin-smith
austin-smith merged commit 3cbb180 into main Feb 23, 2026
2 checks passed
@austin-smith
austin-smith deleted the improve-stats-view branch February 23, 2026 05:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant