Created
May 14, 2022 23:58
-
-
Save tvoklov/38437df4f4a5cf36cf58570fe02ea16a to your computer and use it in GitHub Desktop.
a pretty basic elm calculator i wrote because the one windows has was too slow for me
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module InstantCalc exposing (..) | |
import Browser | |
import Html exposing (..) | |
import Html.Attributes exposing (..) | |
import Html.Events exposing (onClick, onInput) | |
main : Program () Model Msg | |
main = | |
Browser.sandbox { init = init, view = view, update = update } | |
type alias Model = | |
{ operationType : Operation | |
, left : String | |
, right : String | |
, mResult : Maybe Float | |
} | |
type Msg | |
= SetOperation Operation | |
| InputL String | |
| InputR String | |
| Swap | |
| SetResultAsLeft | |
| SetResultAsRight | |
| Clear | |
type Operation | |
= Add | |
| Subtract | |
| Divide | |
| Multiply | |
| Exponent | |
calculate : Operation -> Float -> Float -> Float | |
calculate opType left right = | |
case opType of | |
Add -> | |
left + right | |
Subtract -> | |
left - right | |
Multiply -> | |
left * right | |
Divide -> | |
left / right | |
Exponent -> | |
left ^ right | |
init : Model | |
init = | |
Model Add "0" "0" (Just 0.0) | |
view : Model -> Html Msg | |
view model = | |
let | |
mLeft = | |
toFloat model.left | |
mRight = | |
toFloat model.right | |
colorLeft = | |
colorFunc mLeft | |
colorRight = | |
colorFunc mRight | |
resGood = | |
mFold (\_ -> True) False model.mResult | |
( phLeft, phRight ) = | |
placeholderFunc model.operationType | |
in | |
div [ style "display" "flex", style "align-items" "center", style "justify-content" "center", style "gap" "1em", style "margin" "1em" ] | |
[ input [ onInput InputL, value model.left, style "color" colorLeft, style "border-color" colorLeft, style "text-align" "center", placeholder phLeft ] [] | |
, div [ style "display" "flex", style "flex-direction" "column", style "align-content" "stretch", style "gap" "0.75em" ] | |
[ input [ type_ "button", name "clear", value "clear", onClick Clear ] [] | |
, div [] | |
[ input [ type_ "radio", name "op_type", value "+", checked (model.operationType == Add), onClick (SetOperation Add) ] [] | |
, label [ for "+" ] [ text " + " ] | |
, input [ type_ "radio", name "op_type", value "-", checked (model.operationType == Subtract), onClick (SetOperation Subtract) ] [] | |
, label [ for "-" ] [ text " - " ] | |
] | |
, div [] | |
[ input [ type_ "radio", name "op_type", value "*", checked (model.operationType == Multiply), onClick (SetOperation Multiply) ] [] | |
, label [ for "*" ] [ text " * " ] | |
, input [ type_ "radio", name "op_type", value "/", checked (model.operationType == Divide), onClick (SetOperation Divide) ] [] | |
, label [ for "/" ] [ text " / " ] | |
] | |
, div [] | |
[ input [ type_ "radio", name "op_type", value "^", checked (model.operationType == Exponent), onClick (SetOperation Exponent) ] [] | |
, label [ for "^" ] [ text " ^ " ] | |
] | |
, input [ type_ "button", name "swap", value "swap", onClick Swap ] [] | |
] | |
, input [ onInput InputR, value model.right, style "color" colorRight, style "border-color" colorRight, style "text-align" "center", placeholder phRight ] [] | |
, p [] [ text " = " ] | |
, p [] [ text (mFold String.fromFloat "???" model.mResult) ] | |
, div [ style "display" "flex", style "flex-direction" "column", style "gap" "0.1em" ] | |
[ text "Set as:" | |
, input [ type_ "button", disabled (not resGood), name "setAsLeft", value phLeft, onClick SetResultAsLeft ] [] | |
, input [ type_ "button", disabled (not resGood), name "setAsRight", value phRight, onClick SetResultAsRight ] [] | |
] | |
] | |
placeholderFunc : Operation -> ( String, String ) | |
placeholderFunc op = | |
case op of | |
Add -> | |
( "Left Addend", "Right Addend" ) | |
Subtract -> | |
( "Minuend", "Subtrahend" ) | |
Divide -> | |
( "Dividend", "Divider" ) | |
Multiply -> | |
( "Left Factor", "Right Factor" ) | |
Exponent -> | |
( "Base", "Exponent" ) | |
colorFunc : Maybe Float -> String | |
colorFunc f = | |
case f of | |
Just _ -> | |
"black" | |
Nothing -> | |
"red" | |
mZip : Maybe a -> Maybe b -> Maybe ( a, b ) | |
mZip a b = | |
Maybe.andThen (\r -> Maybe.map (\l -> ( l, r )) a) b | |
mFold : (a -> b) -> b -> Maybe a -> b | |
mFold f z m = | |
case m of | |
Just a -> | |
f a | |
Nothing -> | |
z | |
update : Msg -> Model -> Model | |
update msg model = | |
case msg of | |
SetOperation op -> | |
let | |
newModel = | |
{ model | operationType = op } | |
in | |
{ newModel | mResult = calculateModel newModel } | |
InputL l -> | |
let | |
newModel = | |
{ model | left = l } | |
in | |
{ newModel | mResult = calculateModel newModel } | |
InputR r -> | |
let | |
newModel = | |
{ model | right = r } | |
in | |
{ newModel | mResult = calculateModel newModel } | |
Swap -> | |
let | |
newModel = | |
{ model | right = model.left, left = model.right } | |
in | |
{ newModel | mResult = calculateModel newModel } | |
SetResultAsLeft -> | |
let | |
mNewModel = | |
Maybe.map (\res -> { model | left = String.fromFloat res }) model.mResult | |
in | |
Maybe.map (\m -> { m | mResult = calculateModel m }) mNewModel |> Maybe.withDefault model | |
SetResultAsRight -> | |
let | |
mNewModel = | |
Maybe.map (\res -> { model | right = String.fromFloat res }) model.mResult | |
in | |
Maybe.map (\m -> { m | mResult = calculateModel m }) mNewModel |> Maybe.withDefault model | |
Clear -> | |
{ model | left = "0", right = "0", mResult = Just 0 } | |
calculateModel : Model -> Maybe Float | |
calculateModel model = | |
mZip (toFloat model.left) (toFloat model.right) | |
|> Maybe.map (\( l, r ) -> calculate model.operationType l r) | |
toFloat : String -> Maybe Float | |
toFloat s = | |
String.replace "," "." s |> String.toFloat |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment