From aa738495a92665f47f46101c019a49829b670891 Mon Sep 17 00:00:00 2001 From: Tyler Stephen Date: Fri, 31 Mar 2017 21:52:32 -0700 Subject: [PATCH] Display summary (mostly) - Nothing for AutoTX commands - Nothing for error / aborted TXs --- accounts.go | 48 ++++++++++++++++++++++++++++++++++++++ commands_add.go | 1 + commands_buy.go | 3 +++ commands_cancelBuy.go | 1 + commands_cancelSell.go | 1 + commands_commitBuy.go | 1 + commands_commitSell.go | 1 + commands_displaySummary.go | 13 ++++++++++- commands_dumplog.go | 5 ++++ commands_quote.go | 5 ++++ commands_sell.go | 5 +++- 11 files changed, 82 insertions(+), 2 deletions(-) diff --git a/accounts.go b/accounts.go index 8eab96d..8d37bcf 100644 --- a/accounts.go +++ b/accounts.go @@ -1,8 +1,11 @@ package main import ( + "container/ring" "errors" + "fmt" "sync" + "time" "github.com/distributeddesigns/currency" ) @@ -16,13 +19,22 @@ type account struct { portfolio portfolio pendingBuys txStack pendingSells txStack + summary *ring.Ring sync.Mutex } +const ( + summarySize = 20 +) + // newAccountForUser creates an empty account for the given user func newAccountForUser(userID string) *account { var ac = account{userID: userID} ac.portfolio = make(portfolio) + ac.summary = ring.New(summarySize) + + ac.AddSummaryItem("Created") + return &ac } @@ -31,6 +43,7 @@ func (ac *account) AddFunds(amount currency.Currency) { consoleLog.Debugf("Old balance for %s is %s", ac.userID, ac.balance) ac.balance.Add(amount) + ac.AddSummaryItem("Added " + amount.String()) consoleLog.Debugf("New balance for %s is %s", ac.userID, ac.balance) } @@ -40,6 +53,9 @@ func (ac *account) RemoveFunds(amount currency.Currency) error { consoleLog.Debugf("Old balance for %s is %s", ac.userID, ac.balance) err := ac.balance.Sub(amount) + if err != nil { + ac.AddSummaryItem("Removed " + amount.String()) + } consoleLog.Debugf("New balance for %s is %s", ac.userID, ac.balance) @@ -52,6 +68,7 @@ func (ac *account) AddStock(stock string, quantity uint64) { ac.userID, ac.portfolio[stock], stock) ac.portfolio[stock] += quantity + ac.AddSummaryItem(fmt.Sprintf("Added %dx%s", quantity, stock)) consoleLog.Debugf("New portfolio for %s: %d x %s", ac.userID, ac.portfolio[stock], stock) @@ -68,6 +85,7 @@ func (ac *account) RemoveStock(stock string, quantity uint64) error { ac.userID, ac.portfolio[stock], stock) ac.portfolio[stock] -= quantity + ac.AddSummaryItem(fmt.Sprintf("Removed %dx%s", quantity, stock)) consoleLog.Debugf("New portfolio for %s: %d x %s", ac.userID, ac.portfolio[stock], stock) @@ -78,6 +96,7 @@ func (ac *account) RemoveStock(stock string, quantity uint64) error { // PruneExpiredTxs will remove all pendingTxs that are expired func (ac *account) PruneExpiredTxs() { ac.Lock() + ac.AddSummaryItem("Starting expired TX cleanup") expiredBuys := ac.pendingBuys.SplitExpired() expiredSells := ac.pendingSells.SplitExpired() ac.Unlock() @@ -89,4 +108,33 @@ func (ac *account) PruneExpiredTxs() { for _, sell := range *expiredSells { sell.RollBack() } + + ac.AddSummaryItem("Finished expired TX cleanup") +} + +type summaryItem struct { + loggedAt time.Time + message string +} + +func (ac *account) AddSummaryItem(s string) { + // Since ring.Do() always goes _forward_ we want to make sure the forward + // order of elements is newest -> oldest. This saves us a reverse after + // we convert the ring to a slice. + ac.summary = ac.summary.Prev() + ac.summary.Value = summaryItem{time.Now(), s} +} + +// GetSummary returns a list of the user's most recent account activities, +// sorted newest to oldest +func (ac *account) GetSummary() []summaryItem { + s := make([]summaryItem, 0) + + ac.summary.Do(func(node interface{}) { + if node != nil { + s = append(s, node.(summaryItem)) + } + }) + + return s } diff --git a/commands_add.go b/commands_add.go index bd599b3..1088a6d 100644 --- a/commands_add.go +++ b/commands_add.go @@ -70,6 +70,7 @@ func (a addCmd) Execute() { consoleLog.Infof("Adding %s to %s", a.amount, a.userID) acct.Lock() acct.AddFunds(a.amount) + acct.AddSummaryItem("Finished " + a.Name()) acct.Unlock() consoleLog.Notice(" [✔] Finished", a.Name()) diff --git a/commands_buy.go b/commands_buy.go index fc94ec8..45124a0 100644 --- a/commands_buy.go +++ b/commands_buy.go @@ -117,6 +117,7 @@ func (b buyCmd) Execute() { abortTxOnError(err, "This should be impossible!") acct.pendingBuys.Push(b) + acct.AddSummaryItem("Finished " + b.Name()) consoleLog.Notice(" [✔] Finished", b.Name()) } @@ -125,6 +126,7 @@ func (b buyCmd) Commit() { acct := accountStore[b.userID] acct.Lock() acct.AddStock(b.stock, b.quantityToBuy) + acct.AddSummaryItem("Commited " + b.Name()) acct.Unlock() } @@ -133,6 +135,7 @@ func (b buyCmd) RollBack() { acct := accountStore[b.userID] acct.Lock() acct.AddFunds(b.purchaseAmount) + acct.AddSummaryItem("Rolled back " + b.Name()) acct.Unlock() } diff --git a/commands_cancelBuy.go b/commands_cancelBuy.go index 69634ac..29710aa 100644 --- a/commands_cancelBuy.go +++ b/commands_cancelBuy.go @@ -60,5 +60,6 @@ func (cb cancelBuyCmd) Execute() { pendingBuy.RollBack() + acct.AddSummaryItem("Finished " + cb.Name()) consoleLog.Notice(" [✔] Finished", cb.Name()) } diff --git a/commands_cancelSell.go b/commands_cancelSell.go index ce874bf..5b2afcf 100644 --- a/commands_cancelSell.go +++ b/commands_cancelSell.go @@ -60,5 +60,6 @@ func (cs cancelSellCmd) Execute() { pendingSell.RollBack() + acct.AddSummaryItem("Finished " + cs.Name()) consoleLog.Notice(" [✔] Finished", cs.Name()) } diff --git a/commands_commitBuy.go b/commands_commitBuy.go index 7b02514..c29ed48 100644 --- a/commands_commitBuy.go +++ b/commands_commitBuy.go @@ -65,5 +65,6 @@ func (cb commitBuyCmd) Execute() { pendingBuy.Commit() + acct.AddSummaryItem("Finished " + cb.Name()) consoleLog.Notice(" [✔] Finished", cb.Name()) } diff --git a/commands_commitSell.go b/commands_commitSell.go index e1cfef2..ecbc15b 100644 --- a/commands_commitSell.go +++ b/commands_commitSell.go @@ -65,5 +65,6 @@ func (cs commitSellCmd) Execute() { pendingSell.Commit() + acct.AddSummaryItem("Finished " + cs.Name()) consoleLog.Notice(" [✔] Finished", cs.Name()) } diff --git a/commands_displaySummary.go b/commands_displaySummary.go index 0d4f1b1..e423ca3 100644 --- a/commands_displaySummary.go +++ b/commands_displaySummary.go @@ -52,5 +52,16 @@ func (ds displaySummaryCmd) ToAuditEvent() types.AuditEvent { } func (ds displaySummaryCmd) Execute() { - consoleLog.Warning("Not implemented: DISPLAY_SUMMARY") + abortTxIfNoAccount(ds.userID) + + acct := accountStore[ds.userID] + acct.Lock() + defer acct.Unlock() + + _ = acct.GetSummary() + + // TODO: Send other account data. Format will depend on FE implementation. + + acct.AddSummaryItem("Finished " + ds.Name()) + consoleLog.Notice(" [✔] Finished", ds.Name()) } diff --git a/commands_dumplog.go b/commands_dumplog.go index 2e010f0..baa27fa 100644 --- a/commands_dumplog.go +++ b/commands_dumplog.go @@ -75,6 +75,8 @@ func (dl dumplogCmd) ToAuditEvent() types.AuditEvent { } func (dl dumplogCmd) Execute() { + abortTxIfNoAccount(dl.userID) + dlr := types.DumplogRequest{ UserID: dl.userID, Filename: dl.filename, @@ -98,6 +100,9 @@ func (dl dumplogCmd) Execute() { consoleLog.Debug("Dumplog requested as", dlr.Filename) + acct := accountStore[dl.userID] + acct.AddSummaryItem("Finished " + dl.Name()) + consoleLog.Notice(" [✔] Finished", dl.Name()) } diff --git a/commands_quote.go b/commands_quote.go index df1b605..7839037 100644 --- a/commands_quote.go +++ b/commands_quote.go @@ -55,6 +55,8 @@ func (q quoteCmd) ToAuditEvent() types.AuditEvent { } func (q quoteCmd) Execute() { + abortTxIfNoAccount(q.userID) + qr := types.QuoteRequest{ Stock: q.stock, UserID: q.userID, @@ -65,5 +67,8 @@ func (q quoteCmd) Execute() { // TODO: actually return a response _ = getQuote(qr) + acct := accountStore[q.userID] + acct.AddSummaryItem("Finished " + q.Name()) + consoleLog.Notice(" [✔] Finished", q.Name()) } diff --git a/commands_sell.go b/commands_sell.go index 3e35c1c..e949923 100644 --- a/commands_sell.go +++ b/commands_sell.go @@ -100,7 +100,7 @@ func (s sellCmd) Execute() { quantityToSell, profit := q.Price.FitsInto(s.amount) consoleLog.Debugf("Want to sell %d stock", quantityToSell) if quantityToSell < 1 { - abortTx(s.Name() + "Cannot sell less than one stock") + abortTx(s.Name() + " Cannot sell less than one stock") } // If yes... @@ -116,6 +116,7 @@ func (s sellCmd) Execute() { abortTxOnError(err, s.Name()) acct.pendingSells.Push(s) + acct.AddSummaryItem("Finished " + s.Name()) consoleLog.Notice(" [✔] Finished", s.Name()) } @@ -124,6 +125,7 @@ func (s sellCmd) Commit() { acct := accountStore[s.userID] acct.Lock() acct.AddFunds(s.profit) + acct.AddSummaryItem("Commited " + s.Name()) acct.Unlock() } @@ -132,6 +134,7 @@ func (s sellCmd) RollBack() { acct := accountStore[s.userID] acct.Lock() acct.AddStock(s.stock, s.quantityToSell) + acct.AddSummaryItem("Rolled back " + s.Name()) acct.Unlock() }