๐Ÿ“ฆ sleepyfran / duets

๐Ÿ“„ TravelByMetro.Command.fs ยท 70 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70namespace Duets.Cli.Components.Commands

open Duets.Agents
open Duets.Cli
open Duets.Cli.Components
open Duets.Cli.SceneIndex
open Duets.Cli.Text
open Duets.Entities
open Duets.Simulation
open Duets.Simulation.Navigation
open Microsoft.FSharp.Data.UnitSystems.SI.UnitNames

[<RequireQualifiedAccess>]
module TravelByMetroCommand =
    /// Command that allows the user to travel by metro to a specific destination.
    let create
        (availableConnections: (MetroStationConnections * MetroLine) list)
        =
        { Name = "travel"
          Description =
            "Allows you to travel to another metro station that connects to this one."
          Handler =
            fun _ ->
                let state = State.get ()

                let destinations =
                    availableConnections
                    |> List.fold
                        (fun acc (connections, line) ->
                            match connections with
                            | OnlyPreviousCoords previous ->
                                (previous, line) :: acc
                            | PreviousAndNextCoords(previous, next) ->
                                (previous, line) :: (next, line) :: acc
                            | OnlyNextCoords next -> (next, line) :: acc)
                        []

                let selectedDestination =
                    showOptionalChoicePrompt
                        (Styles.prompt
                            "You can travel to these stations, where would you like to go?")
                        Generic.cancel
                        (fun ((place: Place, zone: Zone, _), line: MetroLine) ->
                            $"{place.Name |> Styles.place} in {zone.Name |> Styles.faded} through {line.Id |> Styles.line} line")
                        destinations

                match selectedDestination with
                | Some(option) ->
                    let (targetPlace, _, _), _ = option

                    let currentDayMoment =
                        Queries.Calendar.today state
                        |> Calendar.Query.dayMomentOf

                    showProgressBarSync
                        [ Travel.blindlyStaringAtPhone ]
                        2<second>

                    // Moving to metro stations should not yield any entrance errors,
                    // so ignore the error for now.
                    Navigation.moveTo targetPlace.Id state
                    |> Result.iter Effect.apply

                    Travel.arrivedAtStation currentDayMoment |> showMessage

                    Scene.WorldAfterMovement
                | None ->
                    // TODO: Exit the train!
                    Scene.World }