diff options
Diffstat (limited to 'src/client/Model/Income.elm')
| -rw-r--r-- | src/client/Model/Income.elm | 102 | 
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 | 
