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
100module Duets.Entities.Album
open Duets.Common
open FSharp.Data.UnitSystems.SI.UnitNames
let private twentyFiveMinutes = 25 * 60<second>
/// Determines the length of the given track list.
let lengthInSeconds (trackList: TrackList) =
List.fold
(fun albumLength (Recorded(song, _)) ->
albumLength + Time.Length.inSeconds song.Length)
0<second>
trackList
type NameError =
| NameTooShort
| NameTooLong
type RecordTypeError = EmptyTrackList
/// Determines the record type of an album given its track list.
let recordType trackList =
if List.length trackList = 0 then
Error EmptyTrackList
else if List.length trackList = 1 then
Ok Single
else
match lengthInSeconds trackList with
| l when l <= twentyFiveMinutes -> Ok EP
| _ -> Ok LP
/// Validates that the record name is not below 1 character or more
/// than 100.
let validateName name =
match String.length name with
| l when l < 1 -> Error NameTooShort
| l when l > 100 -> Error NameTooLong
| _ -> Ok name
/// Creates an album given its name and the initial song of the track-list.
let from (band: Band) name initialSong =
{ Id = AlbumId <| Identity.create ()
BandId = band.Id
Name = name
Genre = band.Genre
TrackList = [ initialSong ]
Type = Single }
/// Adds the given song to the album and recomputes the album type.
let updateTrackList album (trackList: TrackList) =
let updatedTrackList =
trackList
|> List.map (fun (Recorded(song, quality)) ->
Recorded(song.Id, quality))
{ album with
TrackList = updatedTrackList
Type = recordType trackList |> Result.unwrap }
/// Returns the inner album of an unreleased album.
let fromUnreleased (unreleasedAlbum: UnreleasedAlbum) = unreleasedAlbum.Album
/// Returns the inner album of a released album.
let fromReleased releasedAlbum = releasedAlbum.Album
module Unreleased =
/// Creates an unreleased album given a name and a track list.
let from band name trackList producer =
{ Album = from band name trackList
SelectedProducer = producer }
/// Modifies the name of the given album validating that it's correct.
let modifyName (unreleasedAlbum: UnreleasedAlbum) name =
{ unreleasedAlbum with
UnreleasedAlbum.Album.Name = name }
module Released =
/// Updates an already released album with the new amount of streams and
/// hype.
let update album streams hype =
{ album with
Streams = streams
Hype = hype }
/// Transforms a given unreleased album into its released status.
let fromUnreleased (unreleasedAlbum: UnreleasedAlbum) releaseDate hype =
{ Album = unreleasedAlbum.Album
ReleaseDate = releaseDate
Streams = 0
Hype = hype
Reviews = [] }
module Review =
/// Creates a review given a reviewer and a score, making sure the score
/// stays between 0 and 100.
let create reviewer score =
{ Reviewer = reviewer
Score = score |> Math.clamp 0 100 }