module Main exposing (main) import Browser import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (..) import Random import Random.List import Piano import Theory type State = State { whitelistedChords : List Theory.Chord , selectedChord : Theory.Chord } type Msg = NextChord | NewChord Theory.Chord viewChord : Theory.Chord -> String viewChord (Theory.Chord (note, chordType, chordPosition)) = viewNote note ++ " " ++ (case chordType of Theory.Major -> "major" Theory.Major7 -> "major 7th" Theory.MajorDominant7 -> "major dominant 7th" Theory.Minor -> "minor" Theory.Minor7 -> "minor 7th" Theory.MinorDominant7 -> "minor dominant 7th" Theory.Augmented -> "augmented" Theory.Augmented7 -> "augmented 7th" Theory.Diminished -> "diminished" Theory.Diminished7 -> "diminished 7th") ++ " " ++ (case chordPosition of Theory.First -> "root position" Theory.Second -> "2nd position" Theory.Third -> "3rd position" Theory.Fourth -> "4th position") {-| Serialize a human-readable format of `note` -} viewNote : Theory.Note -> String viewNote note = case note of Theory.C -> "C" Theory.C_sharp -> "C♯/D♭" Theory.D -> "D" Theory.D_sharp -> "D♯/E♭" Theory.E -> "E" Theory.F -> "F" Theory.F_sharp -> "F♯/G♭" Theory.G -> "G" Theory.G_sharp -> "G♯/A♭" Theory.A -> "A" Theory.A_sharp -> "A♯/B♭" Theory.B -> "B" cmajor : Theory.Chord cmajor = Theory.Chord (Theory.C, Theory.Major, Theory.First) {-| The initial state for the application. -} initialState : State initialState = State { whitelistedChords = Theory.allChords , selectedChord = cmajor } {-| Now that we have state, we need a function to change the state. -} update : Msg -> State -> (State, Cmd Msg) update msg (State {whitelistedChords, selectedChord}) = case msg of NewChord chord -> ( State { whitelistedChords = whitelistedChords , selectedChord = chord } , Cmd.none ) NextChord -> ( State { whitelistedChords = whitelistedChords , selectedChord = selectedChord } , Random.generate (\x -> case x of (Just chord, _) -> NewChord chord (Nothing, _) -> NewChord cmajor) (Random.List.choose whitelistedChords) ) view : State -> Html Msg view (State {selectedChord}) = div [] [ p [] [ text (viewChord selectedChord) ] , button [ onClick NextChord ] [ text "Next Chord" ] , Piano.render { highlight = Theory.notesForChord selectedChord } ] {-| For now, I'm just dumping things onto the page to sketch ideas. -} main = Browser.element { init = \() -> (initialState, Cmd.none) , subscriptions = \_ -> Sub.none , update = update , view = view }