From 75afe1122a87c4508d4a134cea697bf334e80850 Mon Sep 17 00:00:00 2001 From: Akshay Date: Sun, 22 Nov 2020 16:33:45 +0530 Subject: refactor main into modules --- src/Base.elm | 28 ++++++++++++ src/Main.elm | 137 +++------------------------------------------------------- src/Utils.elm | 42 ++++++++++++++++++ src/Views.elm | 71 ++++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+), 130 deletions(-) create mode 100644 src/Base.elm create mode 100644 src/Utils.elm create mode 100644 src/Views.elm diff --git a/src/Base.elm b/src/Base.elm new file mode 100644 index 0000000..c3557d3 --- /dev/null +++ b/src/Base.elm @@ -0,0 +1,28 @@ +module Base exposing (..) + +import Array exposing (Array) +import Time exposing (Posix) + + +type WordStatus + = Correct + | Wrong + | Todo + | CurrentWord + + +type alias Word = + { content : String + , status : WordStatus + } + + +type alias Model = + { begin : Maybe Posix + , end : Maybe Posix + , words : Array Word + , accuracy : Maybe Float + , length : Int + , currentWord : Int + , inputBox : String + } diff --git a/src/Main.elm b/src/Main.elm index 9a35631..a91e12b 100644 --- a/src/Main.elm +++ b/src/Main.elm @@ -1,12 +1,15 @@ module Main exposing (..) import Array exposing (..) +import Base exposing (..) import Browser import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onInput) import Task import Time +import Utils exposing (isJust, isNothing) +import Views exposing (..) main = @@ -18,30 +21,6 @@ main = } -type WordStatus - = Correct - | Wrong - | Todo - | CurrentWord - - -type alias Word = - { content : String - , status : WordStatus - } - - -type alias Model = - { begin : Maybe Time.Posix - , end : Maybe Time.Posix - , words : Array Word - , accuracy : Maybe Float - , length : Int - , currentWord : Int - , inputBox : String - } - - type Msg = Started Time.Posix | Finished Time.Posix @@ -137,26 +116,6 @@ handleWordEnded model = ( newModel, cmd ) -isNothing : Maybe a -> Bool -isNothing p = - case p of - Nothing -> - True - - Just a -> - False - - -isJust : Maybe a -> Bool -isJust p = - not (isNothing p) - - -flip : (a -> b -> c) -> (b -> a -> c) -flip f = - \x y -> f y x - - update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of @@ -199,21 +158,6 @@ update msg model = ) -displayTime : Time.Posix -> String -displayTime t = - let - hh = - Time.toHour Time.utc t - - mm = - Time.toMinute Time.utc t - - ss = - Time.toSecond Time.utc t - in - String.join ":" (List.map String.fromInt [ hh, mm, ss ]) - - wordStyle : WordStatus -> Attribute msg wordStyle w = case w of @@ -246,83 +190,16 @@ currentContents model = |> Maybe.withDefault "" -diffDuration : Time.Posix -> Time.Posix -> Float -diffDuration t1 t2 = - let - m1 = - Time.posixToMillis t1 - - m2 = - Time.posixToMillis t2 - in - toFloat (m2 - m1) / 1000 - - -viewWpm : Model -> String -viewWpm model = - let - t1 = - model.begin - - t2 = - model.end - - duration = - Maybe.map2 diffDuration t1 t2 - - correctWords = - wordCount model.words ((==) Correct) - - wpm = - Maybe.map (String.fromInt << truncate << (*) 60 << (/) (toFloat correctWords)) duration - in - Maybe.withDefault "XX" wpm - - -wordCount : Array Word -> (WordStatus -> Bool) -> Int -wordCount words predicate = - words |> Array.map .status |> Array.filter predicate |> Array.length - - -viewProgress : Model -> String -viewProgress model = - String.fromInt model.currentWord ++ "/" ++ String.fromInt model.length - - -viewAccuracy : Model -> String -viewAccuracy model = - let - wordsAttempted = - toFloat <| wordCount model.words ((/=) Todo) - - correctCount = - toFloat <| wordCount model.words ((==) Correct) - - accuracy = - if wordsAttempted == 0.0 then - Nothing - - else - Just <| correctCount / wordsAttempted * 100 - in - case accuracy of - Nothing -> - "XX" - - Just a -> - String.fromInt <| truncate a - - view : Model -> Html Msg view model = - div [] - [ p [] [ text (String.fromInt model.currentWord) ] - , toPara model.words model.currentWord (currentContents model) + pre [] + [ toPara model.words model.currentWord (currentContents model) -- , p [] [ text (Maybe.withDefault "XX" (Maybe.map displayTime model.begin)) ] -- , p [] [ text (Maybe.withDefault "XX" (Maybe.map displayTime model.end)) ] + , p [] [ text ("POS: " ++ viewProgress (model.currentWord + 1) model.length) ] , p [] [ text ("WPM: " ++ viewWpm model) ] - , p [] [ text ("ACC: " ++ viewAccuracy model) ] + , p [] [ text ("ACC: " ++ viewAccuracy model.words) ] , input [ onInput handleInputChanged, value model.inputBox ] [] ] diff --git a/src/Utils.elm b/src/Utils.elm new file mode 100644 index 0000000..0f3164f --- /dev/null +++ b/src/Utils.elm @@ -0,0 +1,42 @@ +module Utils exposing (..) + +import Array as A exposing (..) +import Base exposing (Word, WordStatus(..)) +import Time exposing (Posix, posixToMillis) + + +isNothing : Maybe a -> Bool +isNothing p = + case p of + Nothing -> + True + + Just a -> + False + + +isJust : Maybe a -> Bool +isJust p = + not (isNothing p) + + +flip : (a -> b -> c) -> (b -> a -> c) +flip f = + \x y -> f y x + + +diffDuration : Posix -> Posix -> Float +diffDuration t1 t2 = + let + m1 = + posixToMillis t1 + + m2 = + posixToMillis t2 + in + toFloat (m2 - m1) / 1000 + + +wordCountWith : Array Word -> (WordStatus -> Bool) -> Int +wordCountWith words predicate = + words |> A.map .status |> A.filter predicate |> A.length diff --git a/src/Views.elm b/src/Views.elm new file mode 100644 index 0000000..c5cc159 --- /dev/null +++ b/src/Views.elm @@ -0,0 +1,71 @@ +module Views exposing (viewAccuracy, viewProgress, viewWpm) + +import Array exposing (..) +import Base exposing (..) +import Time exposing (Posix, toHour, toMinute, toSecond, utc) +import Utils exposing (diffDuration, wordCountWith) + + +viewTime : Posix -> String +viewTime t = + let + hh = + toHour utc t + + mm = + toMinute utc t + + ss = + toSecond utc t + in + String.join ":" (List.map String.fromInt [ hh, mm, ss ]) + + +viewWpm : Model -> String +viewWpm model = + let + t1 = + model.begin + + t2 = + model.end + + duration = + Maybe.map2 diffDuration t1 t2 + + correctWords = + wordCountWith model.words ((==) Correct) + + wpm = + Maybe.map (String.fromInt << truncate << (*) 60 << (/) (toFloat correctWords)) duration + in + Maybe.withDefault "XX" wpm + + +viewProgress : Int -> Int -> String +viewProgress soFar total = + String.fromInt soFar ++ "/" ++ String.fromInt total + + +viewAccuracy : Array Word -> String +viewAccuracy words = + let + wordsAttempted = + toFloat <| wordCountWith words ((/=) Todo) + + correctCount = + toFloat <| wordCountWith words ((==) Correct) + + accuracy = + if wordsAttempted == 0.0 then + Nothing + + else + Just <| correctCount / wordsAttempted * 100 + in + case accuracy of + Nothing -> + "XX" + + Just a -> + String.fromInt <| truncate a -- cgit v1.2.3