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
|
|
|
|
| ToggleChordType Theory.ChordType
|
|
|
|
| TogglePitchClass Theory.PitchClass
|
|
|
|
| ToggleKey Theory.Key
|
|
|
|
| DoNothing
|
|
|
|
| SetPracticeMode PracticeMode
|
|
|
|
| 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
|
2020-04-18 20:51:57 +02:00
|
|
|
, view = Overview
|
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 )
|
|
|
|
|
|
|
|
SetPracticeMode practiceMode ->
|
|
|
|
( { model
|
|
|
|
| practiceMode = practiceMode
|
|
|
|
, isPaused = True
|
|
|
|
}
|
|
|
|
, 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
|
|
|
|
)
|
|
|
|
|
|
|
|
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
|
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
|
|
|
|
)
|