/// m11 pong app: the same wiring as App.fs (streams in, drawings out), reusing the course's modules. module Snake.Pong.App open Snake open Snake.IO open Snake.Stream open Snake.Pong.Model open Snake.Pong.Rules open Snake.Pong.View /// Milliseconds between frames of the match. let FRAME_MS_PONG = 30L /// Translate a key event into a `PongAction`, if any. `isDown` is true for a key press, false for a release. /// "ArrowUp"/"w"/"W" -> `Press Paddle.Up` / `Release Paddle.Up`, "ArrowDown"/"s"/"S" -> `Press Paddle.Down` / /// `Release Paddle.Down`, "r"/"R" -> `Restart` (on press only; releasing r does nothing). Any other key -> `None`. let pongKey (isDown: bool) (key: string) : PongAction option = failwith "TODO m11" /// Everything that can happen in a match: `Frame` every FRAME_MS_PONG (from `Stream.interval`), merged with the /// `pongKey true key` of every key press and the `pongKey false key` of every key release. /// (The stub is wrapped in `Stream` so the TODO only fires when the stream is stepped.) let pongActions: Stream = Stream(fun _ -> failwith "TODO m11") /// Fold the actions into a stream of states: start from `initialPong seed`, `pongUpdate` for each action, emit the initial state first. let pongStates (seed: uint32) (actions: Stream) : Stream = failwith "TODO m11" /// The whole program as a value, like `App.main`: ask for a seed, turn the stream of states into a stream of drawings /// of `pongView`. A function of `unit`, like `App.main`. let pongMain () : IO>> = failwith "TODO m11"