diff --git a/backend/main.go b/backend/main.go index 920c4fa..953f78d 100644 --- a/backend/main.go +++ b/backend/main.go @@ -42,7 +42,7 @@ var ( startMoney float64 = 1000.0 roundDuration time.Duration = 10 * time.Minute - matcherUpdateInterval time.Duration = time.Millisecond * 2000 + matcherUpdateInterval time.Duration = time.Second ) type ServiceHandler struct { @@ -222,6 +222,7 @@ func main() { ) defer match.Close() + go match.Start() // create some bots so the market has some actual movement bots := make([]bot.Bot, 0, 40) diff --git a/backend/matcher/matcher.go b/backend/matcher/matcher.go index 687411f..c37b665 100644 --- a/backend/matcher/matcher.go +++ b/backend/matcher/matcher.go @@ -68,8 +68,11 @@ func (m *Matcher) Start() { m.l.Info("shutting down") return case <-ticker.C: + //m.l.Info("running matcher") + allMatches := m.matchStonks() if len(allMatches) > 0 { + m.l.Info("matcher found new matches") // NOTE: blocking, but the channel is buffered m.matchUpdateCh <- allMatches } @@ -78,11 +81,18 @@ func (m *Matcher) Start() { } func (m *Matcher) matchStonks() []*store.Match { + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() var allMatches []*store.Match for _, stonk := range m.stonks { // Run the matching process - orders, _ := m.orderP.GetOrders(m.ctx, stonk, nil) + orders, err := m.orderP.GetOrders(ctx, stonk, nil) + if err != nil { + m.l.Error("matcher run failed") + return nil + } + // sort in ascending order w.r.t. time sort.Slice(orders, func(i, j int) bool { return orders[i].Time.Before(orders[j].Time) @@ -96,25 +106,41 @@ func (m *Matcher) matchStonks() []*store.Match { buyOrders = append(buyOrders, o) } } + + m.l.Debug("got order", + zap.Int("len", len(orders)), + zap.Int("buy_len", len(buyOrders)), + zap.Int("sell_len", len(sellOrders)), + ) + // sort sell price low-high sort.Slice(sellOrders, func(i, j int) bool { return orders[i].Price < orders[j].Price }) + // sort buy price high-low + sort.Slice(buyOrders, func(i, j int) bool { + return orders[i].Price > orders[j].Price + }) + m.l.Debug("11", zap.Int("len_matches", len(allMatches))) for _, sellOrder := range sellOrders { - if len(buyOrders) == 0 || sellOrder.Price > buyOrders[0].Price { - // no possible match - break - } - - qty := sellOrder.Quantity - // sort buy price high-low sort.Slice(buyOrders, func(i, j int) bool { return orders[i].Price > orders[j].Price }) + m.l.Debug("23", zap.Int("len_matches", len(allMatches))) + // if len(buyOrders) == 0 || sellOrder.Price > buyOrders[0].Price { + // // no possible match + // m.l.Info("skipping further checks") + // break + // } + m.l.Debug("42", zap.Int("len_matches", len(allMatches))) + + qty := sellOrder.Quantity newBuyOrders := make([]*store.Order, 0, len(buyOrders)) + m.l.Debug("69", zap.Int("len_matches", len(allMatches))) for _, buyOrder := range buyOrders { + m.l.Debug("180", zap.Int("len_matches", len(allMatches))) match := &store.Match{ Id: uuid.New().String(), Stonk: sellOrder.Stonk, @@ -124,6 +150,8 @@ func (m *Matcher) matchStonks() []*store.Match { Quantity: min(qty, buyOrder.Quantity), } allMatches = append(allMatches, match) + m.l.Debug("added new match", zap.Int("len_matches", len(allMatches))) + m.matchP.AddMatch(m.ctx, match) qty -= buyOrder.Quantity @@ -172,5 +200,7 @@ func (m *Matcher) matchStonks() []*store.Match { } } + m.l.Debug("finished matchin", zap.Int("len_matches", len(allMatches))) + return allMatches } diff --git a/backend/services/stonks/service.go b/backend/services/stonks/service.go index 46cf02c..9ff5111 100644 --- a/backend/services/stonks/service.go +++ b/backend/services/stonks/service.go @@ -315,13 +315,16 @@ func (s *StonksService) GetStonkInfo(w http.ResponseWriter, r *http.Request, sto // update the prices before we retrieve them updated := s.update() if updated { - state := State{ - Start: nil, - Reload: true, - Finish: nil, - } + go func() { + time.Sleep(time.Millisecond * 500) + state := State{ + Start: nil, + Reload: true, + Finish: nil, + } - s.sseCh <- state + s.sseCh <- state + }() } ts, ok := s.prices[stonk] diff --git a/backend/services/stonks/stonks.go b/backend/services/stonks/stonks.go index 2d09fcb..a7fa2ea 100644 --- a/backend/services/stonks/stonks.go +++ b/backend/services/stonks/stonks.go @@ -3,7 +3,6 @@ package stonks type StonkName string const ( - stonkEmpty StonkName = "" // INVALID! StonkPaperClip StonkName = "paperClip" StonkScissors StonkName = "scissors" StonkPencil StonkName = "pencil" diff --git a/backend/services/stonks/utils.go b/backend/services/stonks/utils.go index 14a5d46..d9feec3 100644 --- a/backend/services/stonks/utils.go +++ b/backend/services/stonks/utils.go @@ -11,6 +11,8 @@ import ( ) func (s *StonksService) update() bool { + s.l.Debug("initiating update") + defer s.l.Debug("finished update") // drain the updates chanel until it is empty updated := false for { @@ -29,17 +31,18 @@ func (s *StonksService) update() bool { Time: time, Value: value, }) + s.l.Warn("newest timestamp", zap.Int("ts", time)) } // Add a new entry to the users NetWorthTimeSeries-DataPoints for userId, user := range s.activeUsers { - user.mu.Lock() + //user.mu.Lock() user.NetWorthTimeSeries = append(user.NetWorthTimeSeries, DataPoint{ Time: user.NetWorthTimeSeries.LatestTime() + 1, Value: user.NetWorthTimeSeries.LatestValue(), }) s.activeUsers[userId] = user - user.mu.Unlock() + //user.mu.Unlock() } // update the value to the actual new on if there is a match for this stock @@ -51,7 +54,7 @@ func (s *StonksService) update() bool { // update the users stock position for userId, user := range s.activeUsers { - user.mu.Lock() + //user.mu.Lock() if userId == match.BuyOrder.User.ID { // if buyer user.Stonks[stonkName] += match.Quantity user.ReservedStonks[stonkName] -= match.Quantity @@ -61,7 +64,7 @@ func (s *StonksService) update() bool { user.Stonks[stonkName] -= match.Quantity user.Money += float64(match.Quantity) * match.SellOrder.Price } else { - user.mu.Unlock() + //user.mu.Unlock() continue } @@ -75,7 +78,7 @@ func (s *StonksService) update() bool { user.NetWorthTimeSeries[len(user.NetWorthTimeSeries)-1].Value = user.NetWorth s.activeUsers[userId] = user - user.mu.Unlock() + //user.mu.Unlock() } } diff --git a/backend/store/memorymatch.go b/backend/store/memorymatch.go index 9d4de5e..a1125e0 100644 --- a/backend/store/memorymatch.go +++ b/backend/store/memorymatch.go @@ -39,11 +39,13 @@ func (p *MemoryMatchPersistor) GetMatches(ctx context.Context, stonk string) ([] filter := bson.D{} if stonk != "" { filter = append(filter, bson.E{Key: "stonk", Value: string(stonk)}) + } else { + filter = append(filter, bson.E{}) } cur, err := p.col.Find(ctx, filter) if errors.Is(err, mongo.ErrNoDocuments) { - return []*Match{}, nil + return nil, mongo.ErrNoDocuments } else if err != nil { p.l.Error("Unable to find matches", zap.Error(err)) } diff --git a/frontend/src/model/store.ts b/frontend/src/model/store.ts index a31ca5e..b652a22 100644 --- a/frontend/src/model/store.ts +++ b/frontend/src/model/store.ts @@ -186,7 +186,7 @@ export const vanillaStore = vanillaCreate( } // filter out empty infos - resp = resp.filter((r) => r.ret.Name !== ""); + //resp = resp.filter((r) => r.ret.Name !== ""); set({ stonkInfos: resp.map((resp) => { diff --git a/frontend/src/services/vo-stonks.ts b/frontend/src/services/vo-stonks.ts index 6db9da4..1a2123b 100644 --- a/frontend/src/services/vo-stonks.ts +++ b/frontend/src/services/vo-stonks.ts @@ -55,7 +55,6 @@ export enum StonkName { StonkPaperClip = "paperClip", StonkPencil = "pencil", StonkScissors = "scissors", - StonkEmpty = "", } // github.com/hackaTUM/GameOfStonks/services/stonks.UpdateOrderCmd export interface UpdateOrderCmd { diff --git a/frontend/src/views/Search.tsx b/frontend/src/views/Search.tsx index 2c7dc8e..046088c 100644 --- a/frontend/src/views/Search.tsx +++ b/frontend/src/views/Search.tsx @@ -55,7 +55,7 @@ function Search() { val.valueOf().includes(query) && val !== "") + //.filter((val) => val.valueOf().includes(query) && val !== "") .reduce((acc, entry) => { acc[entry] = -1; return acc;