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 }