module HRInfo exposing ( HRAPI , HRInfo , HRError , decoder , encoder , statsDecoder , strError , strExpiry ) import Json.Decode as D import Json.Encode as E import Json.Decode.Pipeline exposing (required) import Time exposing (Posix, Weekday, Zone) type alias HRAPI = Result HRError (Posix, HRInfo) type HRError = NotFound | InvalidCode | AdminMaintenance | ScheduledMaintenance | Unknown String type alias HRInfo = { hr : String , population : Int , engName : String , terseName : String , province : String , terseProv : String , last7 : Int , last14 : Int } translateError : String -> HRError translateError errString = case errString of "not-found" -> NotFound "invalid-code" -> InvalidCode "admin-maintenance" -> AdminMaintenance "scheduled-maintenance" -> ScheduledMaintenance any -> Unknown any errorDecoder : D.Decoder HRError errorDecoder = D.map translateError (D.field "error" D.string) timeDecoder : D.Decoder Posix timeDecoder = D.map (\ts -> Time.millisToPosix (ts * 1000)) D.int statsDecoder : D.Decoder HRInfo statsDecoder = D.succeed HRInfo |> required "hr" D.string |> required "population" D.int |> required "hr-full" D.string |> required "hr-terse" D.string |> required "province" D.string |> required "prov-terse" D.string |> required "last-7" D.int |> required "last-14" D.int apiDecoder : D.Decoder (Posix, HRInfo) apiDecoder = D.map2 Tuple.pair ( D.succeed identity |> required "expires" timeDecoder ) statsDecoder timeEncoder : Posix -> E.Value timeEncoder time = Time.toMillis Time.utc time |> E.int encoder : HRInfo -> E.Value encoder hrInfo = E.object [ ("hr", E.string hrInfo.hr) , ("population", E.int hrInfo.population) , ("hr-full", E.string hrInfo.engName) , ("hr-terse", E.string hrInfo.terseName) , ("province", E.string hrInfo.province) , ("prov-terse", E.string hrInfo.terseProv) , ("last-7", E.int hrInfo.last7) , ("last-14", E.int hrInfo.last14) ] decoder : D.Decoder HRAPI decoder = D.oneOf [ D.map Err errorDecoder , D.map Ok apiDecoder ] strError : HRError -> String strError err = case err of NotFound -> "Couldn't find that postal code in my data, try another nearby." InvalidCode -> "That doesn't look like valid fnord input, are you messing with validation?" AdminMaintenance -> "The database is being worked on, check back later." ScheduledMaintenance -> "The database is updating, check back in a few minutes." Unknown _ -> "An unknown error occurred." weekdayString : Time.Weekday -> String weekdayString wd = case wd of Time.Mon -> "Mon" Time.Tue -> "Tue" Time.Wed -> "Wed" Time.Thu -> "Thu" Time.Fri -> "Fri" Time.Sat -> "Sat" Time.Sun -> "Sun" strExpiry : Posix -> Zone -> String strExpiry info tz = List.foldr (++) "" [ String.fromInt (Time.toDay tz info) , "," , weekdayString (Time.toWeekday tz info) , " " , String.fromInt (Time.toHour tz info) , ":" , String.fromInt (Time.toMinute tz info) ]