Skip to content

feat(ios): the whole plan in lanes, and a marked scale - #129

Merged
frahlg merged 2 commits into
mainfrom
ios-plan-whole-axis
Oct 29, 2026
Merged

frahlg merged 2 commits into
mainfrom
ios-plan-whole-axis

Conversation

@frahlg

@frahlg frahlg commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

Two things Anders Rauge sent from TestFlight on 28 October 2026, and one I saw in his screenshots.

"Saknar möjlighet att se planen i ett längre perspektiv"

The box plans over every published price, up to 48 h (mpc/service.go: "the plan covers the published prices"), and the app gets the whole plan. The lanes cut it at twelve hours (PlanGlance.horizonMs). At 20:23 his box had planned to midnight the next day, about 28 h, and he saw the first twelve.

  • The lanes now run to the plan's last slot or car window (PlanGlance.reach). The span is at least twelve hours and never runs past the end of tomorrow, so every clock on them reads as today or tomorrow. In the evening that is tomorrow's last priced quarter; before 13:00 it is about twelve hours, as before.
  • Moment carries toMs. Only the lanes ask for whole:; the dial (one turn), Now's strip, the widgets and the watch keep their spans.
  • The rows follow the lanes, still four and "N till senare", and name tomorrow where the clock alone would read as tonight (Moment.times). An end at midnight reads 24:00, as the plan's sentences already do.
  • The finger reads quarters from a PlanDial built untilMs: the lanes' end; the face stays 96 quarters.
  • The hours under the lanes count from midnight: 00 06 12 18 over a day, every three over twelve hours. A stride from now gave 23 02 05 08.

No new button, setting or data.

"Hade gärna sett några streck på y-skalan"

The charts marked only the two ends, and zero was a hairline with no figure, so "2 kW" at the foot of his chart did not read as 2 kW the other way.

  • Zero gets "0" in the gutter.
  • Up to two round rungs (1, 2, 2.5 or 5 × 10ⁿ) between the ends, dotted like the ends, none within half a step of an end and none whose label would touch another (YDomain.rungs, ChartAxes.draw). His −2…7.5 kW chart reads 7,5 · 5 · 2,5 · 0 · 2 kW; the demo battery's −3…5 kW reads 5 · 2,5 · 0 · 3 kW.
  • The gutter makes room for the rung labels (ChartGutter.scaleLabels).
  • Scale labels take the language's decimal mark: his chart said "7.5 kW" in Swedish (PowerFormat.scale, which the Grid today widget also uses).

The headline said "laddar batteriet ur" twice

"nu–20:45 laddar batteriet ur · 21:00–21:30 laddar batteriet ur" now reads "nu–20:45 och 21:00–21:30 laddar batteriet ur". Only two runs of the same kind next to each other merge; different moves keep a clause each.

Overlap

#107 (draft, line widths) edits other lines of PlanView.swift and HistoryCharts.swift: the legend, the level line's style and the ghost bars. No hunk here touches them.

Review

An agent read the diff and probed it. Fixed in b2199fc:

  • Tomorrow was not named at the same clock time (> for >=): at 20:00 a run 20:00–22:00 tomorrow read as now. The 12 h window hid it; the lanes reach it, and so does the price widget's 48 h, which shares the rule (PriceGlance.misleads).
  • The lanes' hours counted from the phone's midnight; now the household's, as the rows.
  • Past one turn the finger's tag says "I MORGON 21:00".
  • No rungs on a scale under 10 W, where they would round to the watt.
  • The watch's trace has no gutter (trailing: 0), so it draws no rungs and no "0".

Checked by the review with no fault: reach across both DST changes, toMs against every filter in a moment, the 12 h readers (all on the dial, Now, widgets, watch), DialMemo, the finger's span, and 1,179 domains for rungs (never more than two, never a loop).

Evidence (this Mac)

  • swift test in appleApp/FTWKit: 957 tests green after b2199fc, new ones: twoRunsOfTheSameKindAreSaidOnce, theLanesReachTheWholePlan, aRowNamesTomorrowWhereTheClockWouldMislead, aScaleIsMarkedAtUpToTwoRoundRungs, and the gutter test updated.
  • Built for the iPhone 17 simulator (iOS 27) and driven in the demo, Swedish, dark: the lanes run 07:16 to 07:00 the next morning with the car's 01:00–05:30 charge in view (outside the old twelve hours); hours 12 18 00 06; home use 15 · 10 · 5 · 0 kW; grid 20 · 10 · 0 kW; battery 5 · 2,5 · 0 · 3 kW. The dial and Now look as before.
  • The demo box plans 24 h whatever the prices; a real box plans to its last published price, so on a box the evening span is longer.

🤖 Generated with Claude Code

Anders' TestFlight feedback, 28 October 2026.

- The plan view's lanes show the whole plan the box sent, to its last
  slot or car window (PlanGlance.reach): at least twelve hours, never
  past the end of tomorrow. In the evening that is tomorrow's last
  priced quarter. The rows follow and name tomorrow where the clock
  would read as tonight. The dial, Now's strip and the widgets keep
  their spans.
- The lanes' hours count from midnight (00 06 12 18, or every three),
  not from whatever hour now is.
- Power charts mark zero with "0" and up to two round rungs between the
  ends (YDomain.rungs), none within half a step of an end. Scale labels
  take the language's decimal mark: "7,5 kW".
- Two battery runs of the same kind are said once:
  "nu–20:45 och 21:00–21:30 laddar batteriet ur".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-29T06:23:40.613783Z 12f19d6 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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: 12f19d653a

ℹ️ 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 on lines +78 to +79
let count = untilMs.map { max(Self.count, Int((($0 - first) / Self.quarterMs).rounded(.up))) } ?? Self.count
let grid = SlotGrid(firstMs: first, stepMs: Self.quarterMs, count: count, fromMs: first, toMs: first + Double(count) * Self.quarterMs)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reset the lane selection when the quarter count shrinks

When someone holds a finger over the last quarter of lanes spanning more than 24 hours, advancing into the next quarter can now shrink this array (for example, from 112 quarters to 111 for an unchanged plan end). PlanLanesCard preserves scrub.index when its dial changes, and LanesMark passes that index directly to dial.what(i), dial.time(i), and dial.price(i). The retained index 111 therefore becomes out of bounds and crashes the app on redraw. Clear or remap the selection when the grid changes, and bounds-check it before reading the new dial.

Useful? React with 👍 / 👎.

- Tomorrow is named at the same clock time too (>= not >): at 20:00 a
  run 20:00–22:00 tomorrow read as now. The 12 h window hid it; the
  lanes and the price widget's 48 h reach it. Same rule in PriceGlance.
- The lanes' hours count from the household's midnight, as the rows do,
  not the phone's.
- The finger's clock names the day past one turn: "I MORGON 21:00".
- No rungs under a 10 W span, where they would round to the watt; the
  search starts at the step that can win.
- The watch's trace has no gutter: no rungs and no "0" there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@frahlg
frahlg merged commit a3c3e85 into main Oct 29, 2026
1 check passed
@frahlg frahlg mentioned this pull request Oct 29, 2026
frahlg added a commit that referenced this pull request Oct 29, 2026
The whole plan in the lanes, a marked scale, one headline clause (#129), for TestFlight.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@frahlg
frahlg deleted the ios-plan-whole-axis branch October 29, 2026 07:24
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