fuzzyworld

nordic-skating / commit

docs: a plan for what is left, and an MIT licence

e3bfc7148f82c4a0cf565d774906ae96acfb5d5a · Pavel Safronov · 2026-10-09 20:56:46 -0700 · parents 95f8bb948ce1

Claude Code usage: this commit ~29.5K out / ~3.9M cached · cost unknown (no per-model trailer) · session 1 tally 520 in / 431.5K out / 34.5M cached · usage by commit and session

docs: a plan for what is left, and an MIT licence

PLAN.md has every open concern in the order it is meant to be picked up,
with what has been decided about each: motion first, then the screen
wake lock, an installable app, the patch of grass to skate round, and
checking the chirps against the film. Controller and multiplayer are
postponed behind them.

The credit for the paper the sound's physics is from was checked against
the journal's page and stands as written.

Usage: 520 in / 431.5K out / 34.5M cached (session tally)
rtk:   1.7M saved, 25.3% over 2657 cmds (global/lifetime)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
 LICENSE      |  21 +++++++++
 PLAN.md      | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 README.md    |   6 ++-
 package.json |   3 +-
 4 files changed, 177 insertions(+), 2 deletions(-)

diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..88e06c2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 Pavel Safronov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/PLAN.md b/PLAN.md
new file mode 100644
index 0000000..df269ba
--- /dev/null
+++ b/PLAN.md
@@ -0,0 +1,149 @@
+# Plan
+
+What is left to do on Nordic Skating, in the order it is meant to be picked up, with what
+has been decided about each item and what is still open. The README says what the app
+does today; this says what it does not do yet.
+
+Last brought up to date 2026-10-09.
+
+## Where things stand
+
+Built and live: the endless lake, autopilot and steering, the synthesized sound, thin
+ice and falling through, forks, narrow passes and open sea, the sound button, and the
+links to the README and source.
+
+Postponed until the items below are ironed out: **game controller**, then
+**multiplayer** (the last step of the original six).
+
+## Next
+
+### 1. Motion
+
+**The problem.** The motion is awkward. Each stride moves the view from one side to the
+other and tilts it, on a sine wave, so the skater seems to be shaken from leg to leg
+rather than to glide. The speed never changes. Steering moves the skater sideways at a
+fixed 4 m/s the instant it is touched, with no weight to it.
+
+**Pavel's idea.** Stop alternating the direction of motion; pick a Bezier curve or
+similar and follow it, for smoother motion. Speed is part of this too.
+
+**Proposal** (not yet agreed; see the conversation of 2026-10-09). Four changes, in the
+order they are expected to matter:
+
+1. **A speed that breathes with the stride.** A push speeds the skater up over about
+   half a second, and the glide after it slows them, by 10 to 15% each way around the
+   present 7 m/s. This is the main thing a skater feels, and it gives the long strides a
+   reason to be long.
+2. **Steering that turns the skater instead of sliding them.** The skater gets a
+   direction and a limit on how sharply it can change. Input bends the path; letting go
+   lets it straighten. Paths become arcs by construction, which is what a curve fitted
+   through points would give, without the joins between curves.
+3. **An autopilot that carves.** Rather than sitting exactly on the middle line, it
+   aims at a point some way ahead on a line that wanders gently across the channel, and
+   steers towards it with the same turning limit. Long, lazy S-curves down the lake.
+4. **A head that stays level.** Take out the side-to-side sway and the tilt on every
+   stride: a skater's head is the stillest part of them. Keep a small lean into real
+   turns, and a slight rise on the push and sink through the glide.
+
+**Open questions.**
+- Should the stride length follow the speed, or stay independent of it?
+- Should thin ice or a narrow pass slow the skater down?
+- How far may the autopilot's line wander from the middle, given that only the middle
+  3 m of a channel is guaranteed to be sound ice? Either the wander stays inside that
+  strip, or the strip of sound ice follows the wandering line.
+
+### 2. Screen wake lock
+
+**Decided: add it.** On autopilot nobody touches the screen, so a phone dims and sleeps.
+Ask the browser to keep the screen on while the page is visible, and ask again each time
+the page comes back, since the lock is dropped when it is hidden. Earlier project to
+copy from: `~/code/galaxy-z-flip7-butterchurn`.
+
+### 3. Installable app
+
+**Decided: add it.** A home-screen icon, a full-screen launch with no browser bars, and
+working offline. Needs a web manifest, icons in several sizes, and a service worker.
+Earlier project to copy from: `~/code/galaxy-z-flip7-butterchurn`, which uses
+`vite-plugin-pwa`.
+
+**Open questions.**
+- What is the icon? (A skate, a crack in black ice, the island?)
+- Should it lock to one orientation when installed, or keep both as now?
+
+### 4. An obstacle to loop around: the patch of grass
+
+**Pavel's idea.** In the film the skater does a loop around a patch of grass and then
+carries on. Add that, as a kind of fork or obstacle. More complex forks are also welcome.
+
+**Sketch.** A small island of reeds or grass standing in the ice in the middle of a
+channel, a few metres across. It is the fork that already exists made very short: the
+channel parts round it and joins again 20 to 40 m later. The autopilot goes round one
+side; the skater may choose the other, or circle it.
+
+**Open questions.**
+- Circling it means turning back, and today the lake only runs forward: distance skated
+  can only grow. Either "a loop" means a wide swerve round it and on, or the lake needs
+  a way to hold a skater who is, for a moment, going backwards. This depends on how the
+  motion work (item 1) comes out, so it follows it.
+- The film has not been looked at for this: find the scene and see what the skater
+  actually does, and how big the patch is.
+- Channels that fork and later rejoin, and three-way forks, would both come from the
+  same work. Worth doing together?
+
+### 5. Check the chirps against the film
+
+**Pavel's request.** The falling "pew" of a distant crack is the one part of the sound
+that comes from the model alone. The first attempt to fit the film's chirps to the model
+failed: 3 of 124 bursts fitted, because the film's soundtrack is edited and its sounds
+overlap.
+
+**What to try.**
+- Pick a handful of the clearest chirps by eye from the spectrogram, instead of
+  detecting them automatically, and fit only those.
+- Follow the ridge of the chirp with a method made for sweeping tones (a reassigned
+  spectrogram), rather than taking the loudest frequency in each short window.
+- Fit the distance and the ice thickness together, and see whether the thickness that
+  comes out agrees with the 4.1 cm that the note gives.
+- If the film will not give it up, say so in the README, and look for a second source:
+  the paper's own recordings, or another recording of thin ice with a known thickness.
+
+### 6. Phone controls
+
+**Waiting on Pavel**, who is still trying the touch steering and will send feedback.
+Nothing to do until then. Steering and choosing a fork have only been checked with the
+keyboard, never with a finger. Item 1 will change how steering feels, so feedback given
+before it lands may need giving again.
+
+## Later
+
+### Competitive mode
+
+**Decided: low stakes for now.** The aim at present is something fun and relaxing: falling
+through costs four seconds and nothing is scored. A competitive mode for people who want
+one is a maybe, as an option beside the relaxed one and never instead of it. Ideas: time
+spent on singing ice, distance without falling, a set course against the clock.
+
+### Game controller
+
+Postponed. `~/code/flight/src/utils/input.ts` already reads gamepads and is the place to
+start.
+
+### Multiplayer
+
+Postponed. The lake is the same for everyone given the same seed, so players need only
+share a seed and send each other where they are. `~/code/touch` and
+`~/code/cat-playground` do this peer to peer with peerjs, with no server.
+
+## Settled
+
+Raised, answered, and needing nothing more.
+
+| Item | Outcome |
+|---|---|
+| Repository was private, so the in-app links led to a sign-in page | Made public by Pavel, 2026-10-09 |
+| No licence | MIT, in `LICENSE` |
+| The credit for the paper the sound's physics is from was partly from memory | Checked against the journal's page on 2026-10-09: authors, title, volume, pages, DOI and CC BY 4.0 licence are all as the README has them |
+| Forks are two-way, not "multiple" | Fine as they are for now; more complex forks are part of item 4 |
+| Thick ice does not sound "bad"; the bad ice is the thin end | Fine as it is |
+| Frame rate on a phone, including at sea | Good, by Pavel's testing |
+| Falling through has no cost and nothing is scored | Intended for now; see Competitive mode |
diff --git a/README.md b/README.md
index a45d681..0814be1 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@ and at its thinnest gives way.
 3. ✅ Measure the reference video, then synthesize the ice sound from the ice's thickness.
 4. ✅ Ice zones that fall out of the physics, and falling through.
 5. ✅ Forks in the lake, narrow passes, and stretches of open sea.
-6. Game controller, then multiplayer.
+6. Game controller, then multiplayer. Postponed: [PLAN.md](PLAN.md) has what comes first.
 
 ## Controls
 
@@ -197,6 +197,10 @@ GitLab Pages. Asset paths are relative (`vite.config.ts`), so the build works at
 Static files go in `static/`, not `public/`: GitLab Pages needs its artifact to be
 named `public`, and a `public/` already in the repository would collide with it.
 
+## Licence
+
+[MIT](LICENSE). What it builds on is credited below.
+
 ## Attribution
 
 - [three.js](https://threejs.org/) — MIT licence.
diff --git a/package.json b/package.json
index b8fac0e..5300deb 100644
--- a/package.json
+++ b/package.json
@@ -25,5 +25,6 @@
     "vite": "^8.2.2",
     "vite-plugin-qrcode": "^0.4.1",
     "vitest": "^5.0.0"
-  }
+  },
+  "license": "MIT"
 }