{- - This file is part of `typers`. - - `typers` is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - `typers` is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero Public License for more details. - - You should have received a copy of the GNU Affero Public License - along with `typers`. If not, see . -} module Views exposing (..) import Array exposing (..) import Base exposing (..) import Css exposing (..) import Html import Html.Styled exposing (..) import Html.Styled.Attributes exposing (css, href) import Html.Styled.Events exposing (onClick) import Styles exposing (..) import Time exposing (Posix, toHour, toMinute, toSecond, utc) import Utils exposing (diffDuration, isNothing, 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 -> Maybe String viewWpm model = let t1 = model.begin t2 = model.end duration = Maybe.map2 diffDuration t1 t2 correctWords = wordCountWith model.words ((==) Correct) in Maybe.map (String.fromInt << truncate << (*) 60 << (/) (toFloat correctWords)) duration viewProgress : Model -> String viewProgress model = let soFar = model.currentWord + 1 total = model.config.length in String.fromInt soFar ++ ":" ++ String.fromInt total viewAccuracy : Model -> Maybe String viewAccuracy model = if isNothing model.end then Nothing else let words = model.words wordsAttempted = toFloat <| wordCountWith words ((/=) Todo) correctCount = toFloat <| wordCountWith words ((==) Correct) accuracy = if wordsAttempted == 0.0 then Nothing else Just <| String.fromInt <| truncate <| correctCount / wordsAttempted * 100 in accuracy viewWordLengthOptions : Base.Config -> Html Msg viewWordLengthOptions config = let wl = [ 10, 25, 50, 100 ] in ul [ css [ margin zero , listStyle Css.none , display inlineBlock , paddingLeft (px 0) ] ] (List.map (\len -> li [ css [ display inline ] ] [ styledButton [ onClick (Base.WordLengthChanged len) , css <| List.singleton <| if config.length == len then textDecoration underline else textDecoration Css.none ] [ text <| String.fromInt len ] ] ) wl ) viewStats : Model -> Html Msg viewStats model = let wpm = viewWpm model acc = viewAccuracy model stats = Maybe.map2 (\w a -> w ++ " words per minute ยท " ++ a ++ "% accuracy") wpm acc in p [] [ text (Maybe.withDefault "" stats) ] viewFooter : Html Msg viewFooter = let footerItems = [ ( "src", "https://git.peppe.rs/web/typers/about" ) , ( "license", "https://git.peppe.rs/web/typers/tree/COPYING" ) ] in styledUnorderedList [] (List.map (\( inner, hr ) -> styledListItem [] [ styledExternalLink [ href hr ] [ text inner ] ] ) footerItems )