...
 
Commits (2)
  • Ryan Frazier's avatar
    Add decimal support · 7505b56c
    Ryan Frazier authored
    PROBLEM!
    The decimal input introduces float rounding errors. Need to fix this.
    7505b56c
  • Ryan Frazier's avatar
    Refactor decimals · 0d589ed1
    Ryan Frazier authored
    Needed to change the current number model to a string.
    This introduced some parsing and thus need to now handle parse errors.
    0d589ed1
module Main exposing (main)
import Browser
import Html exposing (Html, button, div, h1, text)
import Html exposing (Html, button, div, h1, span, text)
import Html.Attributes exposing (class)
import Html.Events exposing (onClick)
......@@ -12,14 +12,16 @@ import Html.Events exposing (onClick)
type alias Model =
{ stack : List Float
, currentNum : Float
, currentNum : String
, error : Maybe String
}
initialModel : Model
initialModel =
{ stack = []
, currentNum = 0
, currentNum = "0"
, error = Nothing
}
......@@ -69,31 +71,55 @@ operatorFunction op =
type Msg
= InputOperator Operator
| InputNumber Float
| InputDecimal
| Clear
| ClearAll
| Back
| Enter
| SetDecimal
update : Msg -> Model -> Model
update msg model =
case msg of
SetDecimal ->
if String.contains "." model.currentNum then
model
else
{ model | currentNum = model.currentNum ++ "." }
ClearAll ->
{ model | currentNum = 0, stack = [] }
initialModel
Clear ->
{ model | currentNum = 0 }
{ model | currentNum = "0" }
Back ->
{ model | currentNum = toFloat <| floor <| model.currentNum / 10 }
Enter ->
let
newNum =
String.dropRight 1 model.currentNum
in
{ model
| stack = model.currentNum :: model.stack
, currentNum = 0
| currentNum =
if String.isEmpty newNum then
"0"
else
newNum
}
Enter ->
let
maybeNumber =
String.toFloat model.currentNum
in
case maybeNumber of
Nothing ->
{ model | error = Just "PARSE ERR" }
Just num ->
{ model | stack = num :: model.stack, currentNum = "0" }
InputOperator operator ->
case model.stack of
[] ->
......@@ -104,19 +130,29 @@ update msg model =
op =
operatorFunction operator
newNum =
op model.currentNum x
maybeNumber =
String.toFloat model.currentNum
in
{ model
| stack = xs
, currentNum = newNum
}
case maybeNumber of
Nothing ->
{ model | error = Just "PARSE ERR" }
Just num ->
let
newNum =
op num x
in
{ model
| stack = xs
, currentNum = String.fromFloat newNum
}
InputNumber num ->
{ model | currentNum = (model.currentNum * 10) + num }
if model.currentNum == "0" then
{ model | currentNum = String.fromFloat num }
InputDecimal ->
model
else
{ model | currentNum = model.currentNum ++ String.fromFloat num }
......@@ -192,13 +228,13 @@ section =
, cell (onClick <| InputNumber 3) Single White "3"
, cell (onClick <| InputOperator Add) Single Yellow "+"
, cell (onClick <| InputNumber 0) Single White "0"
, cell (onClick InputDecimal) Single White "."
, cell (onClick SetDecimal) Single White "."
, cell (onClick <| Enter) Double Yellow "Enter"
]
inputBox : Float -> Html Msg
inputBox num =
stackBox : Float -> Html Msg
stackBox num =
div
[ class "input-box"
]
......@@ -206,14 +242,29 @@ inputBox num =
]
inputBox : Html Msg -> Html Msg
inputBox num =
div
[ class "input-box"
]
[ num
]
view : Model -> Html Msg
view model =
div []
[ h1 [ class "h1" ] [ text "RPN Calculator" ]
, div
[ class "calculator" ]
(List.map inputBox (List.reverse model.stack)
++ [ inputBox model.currentNum
(List.map stackBox (List.reverse model.stack)
++ [ inputBox <|
case model.error of
Nothing ->
text model.currentNum
Just err ->
span [ class "error" ] [ text err ]
, section
]
)
......