aboutsummaryrefslogtreecommitdiff
path: root/src/client/Model/Income.elm
diff options
context:
space:
mode:
authorJoris2017-03-26 21:10:42 +0200
committerJoris2017-03-26 21:10:42 +0200
commit1e47a7754ca38bd1a6c74765d8378caf68ce4619 (patch)
treed0d9238479dc2529a1b558bbbcde346e7e8c2935 /src/client/Model/Income.elm
parentc0ac16a713c4e53cf6af8e72a6d5f6b8ac5d6456 (diff)
downloadbudget-1e47a7754ca38bd1a6c74765d8378caf68ce4619.tar.gz
budget-1e47a7754ca38bd1a6c74765d8378caf68ce4619.tar.bz2
budget-1e47a7754ca38bd1a6c74765d8378caf68ce4619.zip
Separate client and server watch
Diffstat (limited to 'src/client/Model/Income.elm')
-rw-r--r--src/client/Model/Income.elm102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/client/Model/Income.elm b/src/client/Model/Income.elm
new file mode 100644
index 0000000..34578c6
--- /dev/null
+++ b/src/client/Model/Income.elm
@@ -0,0 +1,102 @@
+module Model.Income exposing
+ ( Incomes
+ , Income
+ , IncomeId
+ , incomesDecoder
+ , incomeIdDecoder
+ , incomeDefinedForAll
+ , userCumulativeIncomeSince
+ , cumulativeIncomesSince
+ )
+
+import Json.Decode as Decode exposing (Decoder)
+import Utils.Json as Json
+import Time exposing (Time, hour)
+import List exposing (..)
+import Dict exposing (Dict)
+
+import Model.Date exposing (timeDecoder)
+import Model.User exposing (UserId, userIdDecoder)
+
+import Utils.Maybe as Maybe
+
+type alias Incomes = Dict IncomeId Income
+
+type alias IncomeId = Int
+
+type alias Income =
+ { userId : UserId
+ , time : Float
+ , amount : Int
+ }
+
+incomesDecoder : Decoder Incomes
+incomesDecoder =
+ Json.dictDecoder (Decode.field "id" incomeIdDecoder) <|
+ Decode.map3 Income
+ (Decode.field "userId" userIdDecoder)
+ (Decode.field "date" timeDecoder)
+ (Decode.field "amount" Decode.int)
+
+incomeIdDecoder : Decoder IncomeId
+incomeIdDecoder = Decode.int
+
+incomeDefinedForAll : List UserId -> Incomes -> Maybe Time
+incomeDefinedForAll userIds incomes =
+ let userIncomes = List.map (\userId -> List.filter ((==) userId << .userId) << Dict.values <| incomes) userIds
+ firstIncomes = map (head << sortBy .time) userIncomes
+ in if all Maybe.isJust firstIncomes
+ then head << reverse << List.sort << map .time << Maybe.cat <| firstIncomes
+ else Nothing
+
+userCumulativeIncomeSince : Time -> Time -> Incomes -> UserId -> Int
+userCumulativeIncomeSince currentTime since incomes userId =
+ incomes
+ |> Dict.values
+ |> List.filter (\income -> income.userId == userId)
+ |> cumulativeIncomesSince currentTime since
+
+cumulativeIncomesSince : Time -> Time -> (List Income) -> Int
+cumulativeIncomesSince currentTime since incomes =
+ cumulativeIncome currentTime (getOrderedIncomesSince since incomes)
+
+getOrderedIncomesSince : Time -> List Income -> List Income
+getOrderedIncomesSince time incomes =
+ let mbStarterIncome = getIncomeAt time incomes
+ orderedIncomesSince = filter (\income -> income.time >= time) incomes
+ in (Maybe.toList mbStarterIncome) ++ orderedIncomesSince
+
+getIncomeAt : Time -> List Income -> Maybe Income
+getIncomeAt time incomes =
+ case incomes of
+ [x] ->
+ if x.time < time
+ then Just { userId = x.userId, time = time, amount = x.amount }
+ else Nothing
+ x1 :: x2 :: xs ->
+ if x1.time < time && x2.time >= time
+ then Just { userId = x1.userId, time = time, amount = x1.amount }
+ else getIncomeAt time (x2 :: xs)
+ [] ->
+ Nothing
+
+cumulativeIncome : Time -> List Income -> Int
+cumulativeIncome currentTime incomes =
+ getIncomesWithDuration currentTime (List.sortBy .time incomes)
+ |> map durationIncome
+ |> sum
+
+getIncomesWithDuration : Time -> List Income -> List (Float, Int)
+getIncomesWithDuration currentTime incomes =
+ case incomes of
+ [] ->
+ []
+ [income] ->
+ [(currentTime - income.time, income.amount)]
+ (income1 :: income2 :: xs) ->
+ (income2.time - income1.time, income1.amount) :: (getIncomesWithDuration currentTime (income2 :: xs))
+
+durationIncome : (Float, Int) -> Int
+durationIncome (duration, income) =
+ duration * toFloat income / (hour * 24 * 365 / 12)
+ |> truncate