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
96module Duets.Entities.Item
open Microsoft.FSharp.Reflection
module Property =
/// Attempts to retrieve the main property of the given item, if any.
let tryMain item = item.Properties |> List.tryHead
/// Attempts to pick a property from the given item.
let tryPick fn item = item.Properties |> List.tryPick fn
/// Checks if the given item has a property that satisfies the given function.
let has fn item = item.Properties |> List.exists fn
/// Removes the current given property from the item and re-adds the updated
/// one, returning the updated item. The matching of the property is done
/// against the name of the case via reflection, so it'd match even if
/// the values inside the property are different.
let update property item =
let updatedPropertyInfo, _ =
FSharpValue.GetUnionFields(property, property.GetType())
item.Properties
|> List.filter (fun currentProperty ->
let currentPropertyInfo, _ =
FSharpValue.GetUnionFields(
currentProperty,
currentProperty.GetType()
)
currentPropertyInfo.Name <> updatedPropertyInfo.Name)
|> (@) [ property ]
/// Updates the given item by removing the current property that matches
/// the given one, and re-adds the updated property returning the updated item.
let updateProperty property item =
let updatedProperties = Property.update property item
{ item with
Properties = updatedProperties }
module Beer =
/// Creates a beer item.
let create brand amount alcoholContent =
{ Brand = brand
Name = "beer"
Properties =
[ Drinkable(
{ Amount = amount
DrinkType = Beer(alcoholContent) }
) ] }
module Key =
/// Creates a chip to access a place in a city.
let createGymChipFor cityId placeId =
{ Brand = "DuetsCorp"
Name = "Chip"
Properties = [ TemporaryChip(cityId, placeId) |> Key ] }
/// Creates an entrance card to access a place in a city.
let createEntranceCardFor cityId placeId =
{ Brand = "DuetsCorp"
Name = "EntranceCard"
Properties = [ EntranceCard(cityId, placeId) |> Key ] }
module Coffee =
/// Creates a coffee item.
let create name amount caffeineAmount =
{ Brand = "DuetsBeans"
Name = name
Properties =
[ Drinkable(
{ Amount = amount
DrinkType = Coffee(caffeineAmount) }
) ] }
module Food =
/// Creates a food item.
let create name amount foodType cookingSkillRequired =
{ Brand = "DuetsFoods"
Name = name
Properties =
[ Edible(
{ Amount = amount
FoodType = foodType
CookingSkillRequired = cookingSkillRequired }
)
PlaceableInStorage(Fridge) ] }
module Soda =
/// Creates a soda item.
let create brand amount =
{ Brand = brand
Name = brand
Properties = [ Drinkable({ Amount = amount; DrinkType = Soda }) ] }