2020-04-18 15:58:16 +02:00
|
|
|
module State exposing (..)
|
|
|
|
|
|
|
|
import Random
|
|
|
|
import Random.List
|
|
|
|
import Theory
|
|
|
|
|
|
|
|
|
|
|
|
type Msg
|
|
|
|
= NextChord
|
|
|
|
| NewChord Theory.Chord
|
|
|
|
| Play
|
|
|
|
| Pause
|
|
|
|
| SetTempo String
|
|
|
|
| ToggleInversion Theory.ChordInversion
|
|
|
|
| ToggleKey Theory.Key
|
|
|
|
| DoNothing
|
|
|
|
| SetView View
|
2020-04-19 16:32:20 +02:00
|
|
|
| ToggleFlashCard
|
2020-04-18 15:58:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
type View
|
|
|
|
= Preferences
|
|
|
|
| Practice
|
|
|
|
| Overview
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
, view : View
|
2020-04-19 16:32:20 +02:00
|
|
|
, showFlashCard : Bool
|
2020-04-18 15:58:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{-| The initial state for the application.
|
|
|
|
-}
|
|
|
|
init : Model
|
|
|
|
init =
|
|
|
|
let
|
|
|
|
( firstNote, lastNote ) =
|
|
|
|
( Theory.C3, Theory.C6 )
|
|
|
|
|
|
|
|
inversions =
|
2020-04-19 19:36:22 +02:00
|
|
|
[ Theory.Root ]
|
2020-04-18 15:58:16 +02:00
|
|
|
|
|
|
|
chordTypes =
|
|
|
|
Theory.allChordTypes
|
|
|
|
|
|
|
|
pitchClasses =
|
|
|
|
Theory.allPitchClasses
|
|
|
|
|
|
|
|
keys =
|
|
|
|
[ { pitchClass = Theory.C, mode = Theory.MajorMode } ]
|
|
|
|
in
|
2020-04-19 19:23:01 +02:00
|
|
|
{ whitelistedChords =
|
2020-04-19 19:56:51 +02:00
|
|
|
keys
|
|
|
|
|> List.concatMap Theory.chordsForKey
|
|
|
|
|> List.filter (\chord -> List.member chord.chordInversion inversions)
|
2020-04-18 15:58:16 +02:00
|
|
|
, whitelistedChordTypes = chordTypes
|
|
|
|
, whitelistedInversions = inversions
|
|
|
|
, whitelistedPitchClasses = pitchClasses
|
|
|
|
, whitelistedKeys = keys
|
|
|
|
, selectedChord = Nothing
|
|
|
|
, isPaused = True
|
2020-04-19 16:32:20 +02:00
|
|
|
, tempo = 10
|
2020-04-18 15:58:16 +02:00
|
|
|
, firstNote = firstNote
|
|
|
|
, lastNote = lastNote
|
2020-04-19 20:49:15 +02:00
|
|
|
, view = Overview
|
2020-04-19 16:32:20 +02:00
|
|
|
, showFlashCard = True
|
2020-04-18 15:58:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{-| 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 )
|
|
|
|
|
|
|
|
SetView x ->
|
|
|
|
( { model
|
|
|
|
| view = x
|
|
|
|
, isPaused = True
|
|
|
|
}
|
|
|
|
, 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
|
|
|
|
)
|
|
|
|
|
|
|
|
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 =
|
2020-04-19 19:36:22 +02:00
|
|
|
model.whitelistedKeys
|
|
|
|
|> List.concatMap Theory.chordsForKey
|
|
|
|
|> List.filter (\chord -> List.member chord.chordInversion inversions)
|
2020-04-18 15:58:16 +02:00
|
|
|
}
|
|
|
|
, 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 =
|
2020-04-19 19:56:51 +02:00
|
|
|
keys
|
|
|
|
|> List.concatMap Theory.chordsForKey
|
|
|
|
|> List.filter (\chord -> List.member chord.chordInversion model.whitelistedInversions)
|
2020-04-19 01:31:42 +02:00
|
|
|
, selectedChord = Nothing
|
2020-04-18 15:58:16 +02:00
|
|
|
}
|
|
|
|
, Cmd.none
|
|
|
|
)
|
|
|
|
|
|
|
|
SetTempo tempo ->
|
|
|
|
( { model
|
|
|
|
| tempo =
|
|
|
|
case String.toInt tempo of
|
|
|
|
Just x ->
|
|
|
|
x
|
|
|
|
|
|
|
|
Nothing ->
|
|
|
|
model.tempo
|
|
|
|
}
|
|
|
|
, Cmd.none
|
|
|
|
)
|
2020-04-19 16:32:20 +02:00
|
|
|
|
|
|
|
ToggleFlashCard ->
|
|
|
|
( { model | showFlashCard = not model.showFlashCard }, Cmd.none )
|