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
, view = Overview
}
{-| 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
}
, Cmd.none
)
SetTempo tempo ->
( { model
| tempo =
case String.toInt tempo of
Just x ->
x
Nothing ->
model.tempo
}
, Cmd.none
)