/// 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 let FRAME_MS_PONG = 30L let private paddleKey (key: string) : Paddle option = match key with | "ArrowUp" | "w" | "W" -> Some Paddle.Up | "ArrowDown" | "s" | "S" -> Some Paddle.Down | _ -> None let pongKey (isDown: bool) (key: string) : PongAction option = match paddleKey key with | Some p -> Some(if isDown then PongAction.Press p else PongAction.Release p) | None -> if isDown && (key = "r" || key = "R") then Some PongAction.Restart else None let pongActions: Stream = Stream.merge (Stream.merge (Stream.interval FRAME_MS_PONG |> Stream.map (fun _ -> PongAction.Frame)) (Stream.keyDowns |> Stream.choose (pongKey true))) (Stream.keyUps |> Stream.choose (pongKey false)) let pongStates (seed: uint32) (actions: Stream) : Stream = actions |> Stream.scan pongUpdate (initialPong seed) |> Stream.startWith (initialPong seed) let pongMain () : IO>> = IO.randomSeed () |> IO.map (fun seed -> pongStates seed pongActions |> Stream.map (fun state -> IO.drawScene (pongView state)))