aboutsummaryrefslogtreecommitdiff
path: root/src/client/elm/Model/Income.elm
blob: 97a565247adccb99c62d415840ec8d7e5a9b8063 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
module Model.Income
  ( Income
  , incomeDecoder
  , incomeDefinedForAll
  , cumulativeIncomesSince
  ) where

import Json.Decode as Json exposing ((:=))
import Time exposing (Time, hour)
import List exposing (..)

import Model.Date exposing (timeDecoder)
import Model.User exposing (UserId)

import Utils.Maybe exposing (isJust, catMaybes, maybeToList)

type alias Income =
  { creation : Time
  , amount : Int
  }

incomeDecoder : Json.Decoder Income
incomeDecoder =
  Json.object2 Income
    ("creation" := timeDecoder)
    ("amount" := Json.int)

incomeDefinedForAll : List (List Income) -> Maybe Time
incomeDefinedForAll usersIncomes =
  let firstIncomes = map (head << sortBy .creation) usersIncomes
  in  if all isJust firstIncomes
        then head << reverse << List.sort << map .creation << catMaybes <| firstIncomes
        else Nothing

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 = getIncomesAt time incomes
      orderedIncomesSince = filter (\income -> income.creation >= time) incomes
  in  (maybeToList mbStarterIncome) ++ orderedIncomesSince

getIncomesAt : Time -> List Income -> Maybe Income
getIncomesAt time incomes =
  case incomes of
    [x] ->
      if x.creation < time
        then Just { creation = time, amount = x.amount }
        else Nothing
    x1 :: x2 :: xs ->
      if x1.creation < time && x2.creation > time
        then Just { creation = time, amount = x2.amount }
        else getIncomesAt time (x2 :: xs)
    [] ->
      Nothing

cumulativeIncome : Time -> List Income -> Int
cumulativeIncome currentTime incomes =
  getIncomesWithDuration (incomes ++ [{ creation = currentTime, amount = 0 }])
    |> map durationIncome
    |> sum

getIncomesWithDuration : List Income -> List (Float, Int)
getIncomesWithDuration incomes =
  case incomes of
    (income1 :: income2 :: xs) ->
      (income2.creation - income1.creation, income1.amount) :: (getIncomesWithDuration (income2 :: xs))
    _ ->
      []

durationIncome : (Float, Int) -> Int
durationIncome (duration, income) =
  duration * toFloat income / (hour * 24 * 365 / 12)
    |> truncate