diff --git a/ana/predictor.go b/ana/predictor.go index 93ecbca..7f2aed7 100644 --- a/ana/predictor.go +++ b/ana/predictor.go @@ -38,18 +38,33 @@ func NewInterestPredictor(namePattern string, currencyPattern string, apy float6 } func NewContributionPredictor(reg ledger.Register) Predictor { - monthlyRate := getMonthlyContributionRate(reg) + monthlyRate := getMonthlyContributionRates(reg) _ = monthlyRate return func(given ledger.Balances, delta time.Duration) ledger.Balances { panic(nil) } } -func getMonthlyContributionRate(reg ledger.Register) map[string]ledger.Balance { +func getMonthlyContributionRates(reg ledger.Register) map[string]ledger.Balance { contributions := getRecentContributions(reg) result := make(map[string]ledger.Balance) for name := range contributions { - panic(nil) + result[name] = getMonthlyContributionRate(contributions[name]) + } + return result +} + +// TODO better than average +func getMonthlyContributionRate(contributions []ledger.Balance) ledger.Balance { + sumPerCurrency := map[ledger.Currency]float64{} + for _, balance := range contributions { + for currency, v := range balance { + sumPerCurrency[currency] += v + } + } + result := make(ledger.Balance) + for currency, summed := range sumPerCurrency { + result[currency] = summed / float64(len(contributions)) } return result } @@ -62,10 +77,20 @@ func getContributions(reg ledger.Register) map[string][]ledger.Balance { contributions := make(map[string][]ledger.Balance) for _, date := range reg.Dates() { for name := range reg[date] { - contributions[name] = append(contributions[name], maps.Clone(reg[date][name])) - if a := contributions[name]; len(a) > 1 { - for k := range a[len(a)-2] { - a[len(a)-1][k] -= a[len(a)-2][k] + contributions[name] = append(contributions[name], make(ledger.Balance)) + if len(contributions[name]) > 1 { + for k := range contributions[name][len(contributions[name])-2] { + contributions[name][len(contributions[name])-1][k] = 0 + } + } + balance := contributions[name][len(contributions[name])-1] + for currency, value := range reg[date][name] { + balance[currency] = value + } + if forName := contributions[name]; len(forName) > 1 { + lastBalance := forName[len(forName)-2] + for currency := range lastBalance { + balance[currency] -= lastBalance[currency] } } } diff --git a/ana/predictor_test.go b/ana/predictor_test.go index bf8d486..77e7429 100644 --- a/ana/predictor_test.go +++ b/ana/predictor_test.go @@ -52,11 +52,12 @@ func TestGetContributions(t *testing.T) { "a": ledger.Balance{"y": 1}, }, "2001-03": ledger.Balances{ - "b": ledger.Balance{"z": 2}, + "b": ledger.Balance{"z": 4}, }, } got := getContributions(input) + t.Logf("%+v", got) if len(got) != 2 { t.Error(len(got)) } @@ -69,9 +70,9 @@ func TestGetContributions(t *testing.T) { } else if len(got["a"][1]) != 2 { t.Error(got["a"][1]) } else if got["a"][1]["x"] != -1 { - t.Error(got["a"][1]["x"]) + t.Error(got["a"][1]) } else if got["a"][1]["y"] != 1 { - t.Error(got["a"][1]["y"]) + t.Error(got["a"][1]) } if len(got["b"]) != 2 { @@ -81,8 +82,26 @@ func TestGetContributions(t *testing.T) { } else if got["b"][0]["z"] != 1 { t.Error(got["b"][0]) } else if len(got["b"][1]) != 1 { + t.Error(got["b"]) + } else if got["b"][1]["z"] != 3 { t.Error(got["b"][1]) - } else if got["b"][1]["z"] != 1 { - t.Error(got["b"][1]["z"]) + } +} + +func TestGetMonthlyContributionRate(t *testing.T) { + input := []ledger.Balance{ + ledger.Balance{"x": 2}, + ledger.Balance{"x": 4}, + ledger.Balance{"y": 3}, + } + got := getMonthlyContributionRate(input) + if len(got) != 2 { + t.Error(got) + } + if got["x"] != 2 { + t.Error(got["x"]) + } + if got["y"] != 1 { + t.Error(got["y"]) } }