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
78module Duets.Entities.Song
open FSharp.Data.UnitSystems.SI.UnitNames
open Duets.Entities.Time
type SongNameValidationError =
| NameTooShort
| NameTooLong
type SongLengthValidationError =
| LengthTooShort
| LengthTooLong
let private TwentySeconds = 20<second>
let private ThirtyMinutes = 60<second> * 30
/// Validates that the name between 1 and 100 characters.
let validateName name =
match String.length name with
| l when l < 1 -> Error NameTooShort
| l when l > 100 -> Error NameTooLong
| _ -> Ok name
/// Validates that the length is more than 20 seconds and less than 30 minutes.
let validateLength length =
match Length.inSeconds length with
| l when l < TwentySeconds -> Error LengthTooShort
| l when l > ThirtyMinutes -> Error LengthTooLong
| _ -> Ok length
/// Creates a song given a name, length and vocal style, if possible.
let from (name: string) length vocalStyle =
{ Id = SongId <| Identity.create ()
Name = name
Length = length
VocalStyle = vocalStyle
Practice = 20<practice> }
/// Returns the song contained in an unfinished song.
let fromUnfinished (Unfinished(song, _, _)) = song
/// Returns the song contained in a finished song.
let fromFinished (Finished(song, _)) = song
/// Creates an empty song with all its fields set to a default value.
let empty =
{ Id = SongId <| Identity.create ()
Name = ""
Length = Length.empty
VocalStyle = VocalStyle.Instrumental
Practice = 0<practice> }
module Finished =
/// Returns the song contained in a finished song that has a status attached.
let fromFinishedWithStatus (FinishedWithMetadata(song, _, _)) = song
/// Returns a finished song with metadata about its recording status and
/// the date when the song was finished.
let attachMetadata recorded finishDate song =
FinishedWithMetadata(song, recorded, finishDate)
module Metadata =
/// Returns the recording status of a finished song.
let recorded (FinishedWithMetadata(_, recorded, _)) = recorded
/// Returns the date when a finished song was finished.
let finishDate (FinishedWithMetadata(_, _, finishDate)) = finishDate
module VocalStyle =
/// Returns a VocalStyle given its string representation. If no match is found,
/// normal is returned instead.
let from str =
match str with
| "Instrumental" -> Instrumental
| "Growl" -> Growl
| "Screamo" -> Screamo
| _ -> VocalStyle.Normal