package ana import ( "maps" "testing" "time" "gogs.inhome.blapointe.com/ana-ledger/ledger" ) func TestPredictionPredict(t *testing.T) { inc := func(b ledger.Balances, _ time.Duration) ledger.Balances { result := make(ledger.Balances) for k, v := range b { result[k] = maps.Clone(v) for k2, v2 := range result[k] { result[k][k2] = v2 + 1 } } return result } double := func(b ledger.Balances, _ time.Duration) ledger.Balances { result := make(ledger.Balances) for k, v := range b { result[k] = maps.Clone(v) for k2, v2 := range result[k] { result[k][k2] = v2 * 2 } } return result } from := time.Now() month := time.Hour * 24 * 365 / 12 these := []time.Time{time.Now().Add(time.Hour * 24 * 365 / 12)} theseK := these[0].Format("2006-01") thisMonth := time.Now().Add(-1 * time.Duration(time.Now().Day()) * time.Hour * 24) monthsAgo1 := thisMonth.Add(-1 * month).Format("2006-01") monthsAgo2 := thisMonth.Add(-2 * month).Format("2006-01") _, _ = inc, double cases := map[string]struct { prediction Prediction given ledger.Balances want ledger.Register }{ "empty": { want: ledger.Register{theseK: {}}, }, "double": { prediction: Prediction{double}, given: ledger.Balances{"X": ledger.Balance{"X": 2}}, want: ledger.Register{theseK: ledger.Balances{"X": ledger.Balance{"X": 4}}}, }, "inc": { prediction: Prediction{inc}, given: ledger.Balances{"X": ledger.Balance{"X": 2}}, want: ledger.Register{theseK: ledger.Balances{"X": ledger.Balance{"X": 3}}}, }, "inc, double": { prediction: Prediction{inc, double}, given: ledger.Balances{"X": ledger.Balance{"X": 5}}, want: ledger.Register{theseK: ledger.Balances{"X": ledger.Balance{"X": 12}}}, }, "double, inc": { prediction: Prediction{double, inc}, given: ledger.Balances{"X": ledger.Balance{"X": 5}}, want: ledger.Register{theseK: ledger.Balances{"X": ledger.Balance{"X": 11}}}, }, "contribution": { prediction: Prediction{ NewContributionPredictor(ledger.Register{ "2001-01": ledger.Balances{"X": ledger.Balance{"X": 100}}, // too old "2001-02": ledger.Balances{"X": ledger.Balance{"X": 10000}}, // too old monthsAgo2: ledger.Balances{"X": ledger.Balance{"X": 100}}, monthsAgo1: ledger.Balances{"X": ledger.Balance{"X": 600}}, // +500 once in 6 months }), }, given: ledger.Balances{"X": ledger.Balance{"X": 5}}, want: ledger.Register{theseK: ledger.Balances{"X": ledger.Balance{"X": 105}}}, }, "interest": { prediction: Prediction{ NewInterestPredictor("X", "X", 12), }, given: ledger.Balances{"X": ledger.Balance{"X": 5}}, want: ledger.Register{theseK: ledger.Balances{"X": ledger.Balance{"X": 10}}}, }, "interest, contribution": { prediction: Prediction{ NewInterestPredictor("X", "X", 12), NewContributionPredictor(ledger.Register{ monthsAgo2: ledger.Balances{"X": ledger.Balance{"X": 100}}, monthsAgo1: ledger.Balances{"X": ledger.Balance{"X": 600}}, }), }, given: ledger.Balances{"X": ledger.Balance{"X": 5}}, want: ledger.Register{theseK: ledger.Balances{"X": ledger.Balance{"X": 110}}}, }, "contribution, interest": { prediction: Prediction{ NewContributionPredictor(ledger.Register{ monthsAgo2: ledger.Balances{"X": ledger.Balance{"X": 100}}, monthsAgo1: ledger.Balances{"X": ledger.Balance{"X": 600}}, }), NewInterestPredictor("X", "X", 12), }, given: ledger.Balances{"X": ledger.Balance{"X": 5}}, want: ledger.Register{theseK: ledger.Balances{"X": ledger.Balance{"X": 210}}}, }, } for name, d := range cases { c := d t.Run(name, func(t *testing.T) { got := c.prediction.predict(c.given, from, these) if got.Debug() != c.want.Debug() { t.Errorf("want\n\t%+v, got\n\t%+v", c.want.Debug(), got.Debug()) } }) } }