๐Ÿ“ฆ sleepyfran / duets

๐Ÿ“„ Map.Command.fs ยท 82 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
70
71
72
73
74
75
76
77
78
79
80
81
82namespace Duets.Cli.Components.Commands

open Duets.Agents
open Duets.Cli.Components
open Duets.Cli.Text
open Duets.Cli.SceneIndex
open Duets.Entities
open Duets.Simulation
open Duets.Simulation.Navigation

[<RequireQualifiedAccess>]
module rec MapCommand =
    /// Shows directions from the current place to the destination.
    let private showDirectionsToPlace (city: City) (destination: Place) =
        let currentPlace = Queries.World.currentPlace (State.get ())

        let directionsToPlace =
            Pathfinding.directionsToNode city.Id currentPlace.Id destination.Id

        let directions = directionsToPlace |> Option.defaultValue []

        match directions with
        | [] -> ()
        | directions ->
            $"Directions to {destination.Name |> Styles.place}:"
            |> Styles.header
            |> showMessage

            showSeparator None

            directions
            |> List.indexed
            |> List.iter (fun (index, direction) ->
                let isLast = index = (List.length directions - 1)
                let prefix = if isLast then "โ””โ”€" else "โ”œโ”€"

                match direction with
                | Pathfinding.GoOut(fromPlace, toStreet) ->
                    $"""{prefix} {Styles.action "Leave"} {fromPlace.Name |> Styles.place} and {Styles.action "walk"} to {toStreet.Name |> Styles.place}"""
                | Pathfinding.Enter(fromStreet, toPlace) ->
                    $"""{prefix} {Styles.action "Enter"} {toPlace.Name |> Styles.place} from {fromStreet.Name |> Styles.place}"""
                | Pathfinding.TakeMetro(fromStation, toStation, throughLine) ->
                    let fromStation =
                        Queries.World.placeInCityById
                            city.Id
                            fromStation.PlaceId

                    let toStation =
                        Queries.World.placeInCityById city.Id toStation.PlaceId

                    $"""{prefix} {Styles.action "Take the metro"} from {fromStation.Name |> Styles.place} to {toStation.Name |> Styles.place} through the {Styles.line throughLine} line"""
                | Pathfinding.Walk(fromStreet, toStreet, _) ->
                    $"""{prefix} {Styles.action "Walk"} from {fromStreet.Name |> Styles.place} to {toStreet.Name |> Styles.place}"""
                |> showMessage)

        let estimatedTravelTime = TravelTime.byPublicTransport directions

        $"Estimated travel time: ~{estimatedTravelTime |> Styles.time} minutes"
        |> showMessage

    /// Creates a command that allows the player to get directions to other
    /// places inside the current city.
    let get =
        { Name = "map"
          Description = Command.mapDescription
          Handler =
            fun _ ->
                let currentCity = Queries.World.currentCity (State.get ())

                currentCity.Id |> Command.mapCurrentCity |> showMessage

                Command.mapTip |> showMessage
                lineBreak ()

                match showMap () with
                | Some place ->
                    showDirectionsToPlace currentCity place
                    lineBreak ()
                | None -> ()

                Scene.WorldAfterMovement }