about summary refs log tree commit diff
path: root/website/sandbox/learnpianochords/src/State.elm
diff options
context:
space:
mode:
Diffstat (limited to 'website/sandbox/learnpianochords/src/State.elm')
-rw-r--r--website/sandbox/learnpianochords/src/State.elm271
1 files changed, 271 insertions, 0 deletions
diff --git a/website/sandbox/learnpianochords/src/State.elm b/website/sandbox/learnpianochords/src/State.elm
new file mode 100644
index 000000000000..2588d8566ff1
--- /dev/null
+++ b/website/sandbox/learnpianochords/src/State.elm
@@ -0,0 +1,271 @@
+module State exposing (..)
+
+import Random
+import Random.List
+import Theory
+
+
+type Msg
+    = NextChord
+    | NewChord Theory.Chord
+    | Play
+    | Pause
+    | SetTempo String
+    | ToggleInversion Theory.ChordInversion
+    | ToggleChordType Theory.ChordType
+    | TogglePitchClass Theory.PitchClass
+    | ToggleKey Theory.Key
+    | DoNothing
+    | SetPracticeMode PracticeMode
+    | SelectAllKeys
+    | DeselectAllKeys
+    | SetView View
+
+
+type View
+    = Preferences
+    | Practice
+    | Overview
+
+
+{-| Control the type of practice you'd like.
+-}
+type PracticeMode
+    = KeyMode
+    | FineTuneMode
+
+
+type alias Model =
+    { whitelistedChords : List Theory.Chord
+    , whitelistedChordTypes : List Theory.ChordType
+    , whitelistedInversions : List Theory.ChordInversion
+    , whitelistedPitchClasses : List Theory.PitchClass
+    , whitelistedKeys : List Theory.Key
+    , selectedChord : Maybe Theory.Chord
+    , isPaused : Bool
+    , tempo : Int
+    , firstNote : Theory.Note
+    , lastNote : Theory.Note
+    , practiceMode : PracticeMode
+    , view : View
+    }
+
+
+{-| The initial state for the application.
+-}
+init : Model
+init =
+    let
+        ( firstNote, lastNote ) =
+            ( Theory.C3, Theory.C6 )
+
+        inversions =
+            Theory.allInversions
+
+        chordTypes =
+            Theory.allChordTypes
+
+        pitchClasses =
+            Theory.allPitchClasses
+
+        keys =
+            [ { pitchClass = Theory.C, mode = Theory.MajorMode } ]
+
+        practiceMode =
+            KeyMode
+    in
+    { practiceMode = practiceMode
+    , whitelistedChords =
+        case practiceMode of
+            KeyMode ->
+                keys |> List.concatMap Theory.chordsForKey
+
+            FineTuneMode ->
+                Theory.allChords
+                    { start = firstNote
+                    , end = lastNote
+                    , inversions = inversions
+                    , chordTypes = chordTypes
+                    , pitchClasses = pitchClasses
+                    }
+    , whitelistedChordTypes = chordTypes
+    , whitelistedInversions = inversions
+    , whitelistedPitchClasses = pitchClasses
+    , whitelistedKeys = keys
+    , selectedChord = Nothing
+    , isPaused = True
+    , tempo = 20
+    , firstNote = firstNote
+    , lastNote = lastNote
+    , view = Preferences
+    }
+
+
+{-| Now that we have state, we need a function to change the state.
+-}
+update : Msg -> Model -> ( Model, Cmd Msg )
+update msg model =
+    case msg of
+        DoNothing ->
+            ( model, Cmd.none )
+
+        SetPracticeMode practiceMode ->
+            ( { model
+                | practiceMode = practiceMode
+                , isPaused = True
+              }
+            , Cmd.none
+            )
+
+        SetView x ->
+            ( { model
+                | view = x
+                , isPaused = True
+              }
+            , Cmd.none
+            )
+
+        SelectAllKeys ->
+            ( { model
+                | whitelistedKeys = Theory.allKeys
+                , whitelistedChords =
+                    Theory.allKeys |> List.concatMap Theory.chordsForKey
+              }
+            , Cmd.none
+            )
+
+        DeselectAllKeys ->
+            ( { model
+                | whitelistedKeys = []
+                , whitelistedChords = []
+              }
+            , Cmd.none
+            )
+
+        NewChord chord ->
+            ( { model | selectedChord = Just chord }
+            , Cmd.none
+            )
+
+        NextChord ->
+            ( model
+            , Random.generate
+                (\x ->
+                    case x of
+                        ( Just chord, _ ) ->
+                            NewChord chord
+
+                        ( Nothing, _ ) ->
+                            DoNothing
+                )
+                (Random.List.choose model.whitelistedChords)
+            )
+
+        Play ->
+            ( { model | isPaused = False }
+            , Cmd.none
+            )
+
+        Pause ->
+            ( { model | isPaused = True }
+            , Cmd.none
+            )
+
+        ToggleChordType chordType ->
+            let
+                chordTypes =
+                    if List.member chordType model.whitelistedChordTypes then
+                        List.filter ((/=) chordType) model.whitelistedChordTypes
+
+                    else
+                        chordType :: model.whitelistedChordTypes
+            in
+            ( { model
+                | whitelistedChordTypes = chordTypes
+                , whitelistedChords =
+                    Theory.allChords
+                        { start = model.firstNote
+                        , end = model.lastNote
+                        , inversions = model.whitelistedInversions
+                        , chordTypes = chordTypes
+                        , pitchClasses = model.whitelistedPitchClasses
+                        }
+              }
+            , Cmd.none
+            )
+
+        ToggleInversion inversion ->
+            let
+                inversions =
+                    if List.member inversion model.whitelistedInversions then
+                        List.filter ((/=) inversion) model.whitelistedInversions
+
+                    else
+                        inversion :: model.whitelistedInversions
+            in
+            ( { model
+                | whitelistedInversions = inversions
+                , whitelistedChords =
+                    Theory.allChords
+                        { start = model.firstNote
+                        , end = model.lastNote
+                        , inversions = inversions
+                        , chordTypes = model.whitelistedChordTypes
+                        , pitchClasses = model.whitelistedPitchClasses
+                        }
+              }
+            , Cmd.none
+            )
+
+        TogglePitchClass pitchClass ->
+            let
+                pitchClasses =
+                    if List.member pitchClass model.whitelistedPitchClasses then
+                        List.filter ((/=) pitchClass) model.whitelistedPitchClasses
+
+                    else
+                        pitchClass :: model.whitelistedPitchClasses
+            in
+            ( { model
+                | whitelistedPitchClasses = pitchClasses
+                , whitelistedChords =
+                    Theory.allChords
+                        { start = model.firstNote
+                        , end = model.lastNote
+                        , inversions = model.whitelistedInversions
+                        , chordTypes = model.whitelistedChordTypes
+                        , pitchClasses = pitchClasses
+                        }
+              }
+            , Cmd.none
+            )
+
+        ToggleKey key ->
+            let
+                keys =
+                    if List.member key model.whitelistedKeys then
+                        List.filter ((/=) key) model.whitelistedKeys
+
+                    else
+                        key :: model.whitelistedKeys
+            in
+            ( { model
+                | whitelistedKeys = keys
+                , whitelistedChords =
+                    keys |> List.concatMap Theory.chordsForKey
+              }
+            , Cmd.none
+            )
+
+        SetTempo tempo ->
+            ( { model
+                | tempo =
+                    case String.toInt tempo of
+                        Just x ->
+                            x
+
+                        Nothing ->
+                            model.tempo
+              }
+            , Cmd.none
+            )