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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138[<AutoOpen>]
module rec Duets.Cli.Components.Map
open Duets.Agents
open Duets.Cli.Text
open Duets.Cli.Text.World
open Duets.Common
open Duets.Entities
open Duets.Simulation
type private PlaceSpecialProperty =
| Rented
| ConcertScheduled
let private placesWithSpecialProperties state =
let band = Queries.Bands.currentBand state
let currentDate = Queries.Calendar.today state
let scheduledConcert =
Queries.Concerts.scheduleForDay state band.Id currentDate
|> Option.map (fun scheduledConcert ->
let concert = Concert.fromScheduled scheduledConcert
[ concert.VenueId, PlaceSpecialProperty.ConcertScheduled ]
|> Map.ofList)
|> Option.defaultValue Map.empty
let rentedPlaces =
Queries.Rentals.all state
|> List.collect (fun rental ->
let _, placeId = rental.Coords
[ placeId, PlaceSpecialProperty.Rented ])
|> Map.ofList
Map.merge rentedPlaces scheduledConcert
let private placeWithInfo (city: City) (place: Place) specialProperties =
let state = State.get ()
let currentlyOpen = Queries.World.placeCurrentlyOpen' state place
let placeSpecialProperties = specialProperties |> Map.tryFind place.Id
let zone = Queries.World.zoneInCityById city.Id place.ZoneId
let zonePrefix = $"{zone.Name |> Styles.place},"
let placeDetails =
match placeSpecialProperties with
| Some Rented ->
$"""{zonePrefix} {place.Name} ({"Rented" |> Styles.highlight})"""
| Some ConcertScheduled ->
$"""{zonePrefix} {place.Name} ({"Concert scheduled" |> Styles.highlight})"""
| None -> $"{zonePrefix} {place.Name}"
World.placeNameWithOpeningInfo placeDetails currentlyOpen
let private showPlaceChoice city placesInCity places =
let specialProperties = placesWithSpecialProperties (State.get ())
let selectedPlace =
showCancellableChoicePrompt
Command.mapChoosePlace
Generic.back
(fun place -> placeWithInfo city place specialProperties)
places
match selectedPlace with
| Some place -> Some place
| None -> showPlaceTypeChoice city placesInCity
let private showPlaceTypeChoice
city
(placesInCity: Map<PlaceTypeIndex, Place list>)
=
let availablePlaceTypes = placesInCity |> List.ofSeq |> List.map _.Key
showCancellableChoicePrompt
Command.mapChoosePlaceTypePrompt
Generic.cancel
World.placeTypeName
availablePlaceTypes
|> Option.bind (fun placeType ->
placesInCity |> Map.find placeType |> showPlaceChoice city placesInCity)
let private changePlace idxType fn (places: Map<PlaceTypeIndex, Place list>) =
Map.change idxType (Option.bind (fn >> Option.ofList)) places
let private filterRentedHomePlaces (currentCity: City) rentedPlaces =
changePlace
PlaceTypeIndex.Home
(List.filter (fun (place: Place) ->
rentedPlaces |> Map.containsKey (currentCity.Id, place.Id)))
let private filterStreets =
changePlace PlaceTypeIndex.Street (List.filter (fun _ -> false))
let private sortHotels (currentCity: City) rentedPlaces =
changePlace
PlaceTypeIndex.Hotel
(List.sortByDescending (fun (place: Place) ->
rentedPlaces |> Map.containsKey (currentCity.Id, place.Id)))
let private sortConcertSpaces state =
let band = Queries.Bands.currentBand state
let currentDate = Queries.Calendar.today state
let scheduledConcert =
Queries.Concerts.scheduleForDay state band.Id currentDate
match scheduledConcert with
| Some scheduledConcert ->
let concert = Concert.fromScheduled scheduledConcert
changePlace
PlaceTypeIndex.ConcertSpace
(List.sortByDescending (fun (place: Place) ->
place.Id = concert.VenueId))
| None -> id
/// Shows a list of all the place types in the current city and, upon selecting
/// one type, shows all the places of that specific type in the current city.
/// Returns the selected place if one was chosen, or None if the user cancelled.
let showMap () =
let state = State.get ()
let rentedPlaces = Queries.Rentals.allAsMap state
let currentCity = Queries.World.currentCity state
(* Filter out homes that are not rented to not pollute the map. *)
let allAvailablePlaces =
Queries.World.allPlacesInCurrentCity state
|> filterRentedHomePlaces currentCity rentedPlaces
|> filterStreets
|> sortHotels currentCity rentedPlaces
|> sortConcertSpaces state
allAvailablePlaces |> showPlaceTypeChoice currentCity