private void HandleUpdateQuoteResponse(UpdateQuoteResponse obj)
        {
            if (!String.IsNullOrWhiteSpace(obj.Message))
            {
                InvokeStateChanged(new GameAlertEventArgs()
                {
                    Title   = "Issues with Update Quote",
                    Message = obj.Message
                });
            }

            if (!obj.IsSuccess)
            {
                InvokeStateChanged(new GameAlertEventArgs()
                {
                    IsModal = true,
                    IsError = true,
                    Title   = "Failed to Update Quote",
                    Message = $"Error: {obj.ErrorMessage}"
                });
                return;
            }

            this.BidPrice = obj.BidPrice ?? this.BidPrice;
            this.AskPrice = obj.AskPrice ?? this.AskPrice;
        }
Exemplo n.º 2
0
 private void HandleUpdateQuoteResponse(UpdateQuoteResponse obj)
 {
     _logger.LogInformation("HandleUpdateQuoteResponse Message={0}", obj);
     if (OnUpdateQuoteResponse != null)
     {
         OnUpdateQuoteResponse(obj);
     }
 }
Exemplo n.º 3
0
        public async Task UpdateQuoteAsync(UpdateQuoteRequest request, Func <UpdateQuoteResponse, Task> responseHandler)
        {
            _logger.LogInformation("UpdateQuote {}", request);

            var resp = new UpdateQuoteResponse()
            {
                RequestId = request.RequestId
            };

            try
            {
                if (!await AcquireGameLock(request.GameId, request.RequestId, TimeSpan.FromSeconds(30)))
                {
                    resp.ErrorMessage = "Timed out while acquiring game lock";
                    await responseHandler(resp);

                    return;
                }

                var gameState = await _dbContext.GameStates
                                .FirstOrDefaultAsync(x => x.GameId == request.GameId);

                if (gameState == null)
                {
                    resp.ErrorMessage = "GameId not found";
                    await responseHandler(resp);

                    return;
                }

                var gameEngine = new GameEngine(_loggerProvider, _dbContext, _cardRepo);
                gameEngine.GameState = gameState;

                if (gameEngine.GameState.IsFinished)
                {
                    resp.ErrorMessage = "Game is finished";
                    await responseHandler(resp);

                    return;
                }

                var(engineResp, trades) = await gameEngine.UpdateQuote(request);
                await responseHandler(engineResp);

                if (engineResp.IsSuccess)
                {
                    InvokeOnGameUpdate(MakeGameUpdateResponse(gameEngine.GameState));
                    InvokeOnTradeUpdate(null, MakeTradeUpdateResponse(gameEngine.GameState.GameId, trades));
                }
            }
            finally
            {
                ReleaseGameLock(request.GameId, request.RequestId);
            }
        }
Exemplo n.º 4
0
        public async Task <(UpdateQuoteResponse, List <Trade>)> UpdateQuote(UpdateQuoteRequest request)
        {
            var resp = new UpdateQuoteResponse()
            {
                RequestId = request.RequestId, Message = string.Empty
            };
            var trades = new List <Trade>();

            if (GameState.IsFinished)
            {
                resp.ErrorMessage = "Game is Finished";
                return(resp, trades);
            }

            var initiatorPlayer = GameState.PlayerStates
                                  .FirstOrDefault(x => x.PlayerId == request.PlayerId);

            if (initiatorPlayer == null)
            {
                resp.ErrorMessage = "PlayerId not found";
                return(resp, trades);
            }

            var currentAsk = initiatorPlayer.CurrentAsk;
            var currentBid = initiatorPlayer.CurrentBid;
            var newAsk     = request.CurrentAsk ?? currentAsk;
            var newBid     = request.CurrentBid ?? currentBid;

            if (!(newAsk.HasValue && newBid.HasValue))
            {
                resp.ErrorMessage = "Need to quote both Bid and Ask";
                return(resp, trades);
            }

            var quoteWidth = newAsk.Value - newBid.Value;

            if (quoteWidth > GameState.Game.MaxQuoteWidth)
            {
                resp.ErrorMessage = $"Quote width should be less than {GameState.Game.MaxQuoteWidth}";
                return(resp, trades);
            }

            if (quoteWidth < GameState.Game.MinQuoteWidth)
            {
                resp.ErrorMessage = $"Quote width should be less than {GameState.Game.MinQuoteWidth}";
                return(resp, trades);
            }

            if (GameState.IsTradingLocked)
            {
                var otherPlayers  = GameState.PlayerStates.Where(x => x.PlayerStateId != initiatorPlayer.PlayerStateId);
                var bestBidOthers = otherPlayers.Select(x => x.CurrentBid).Max();
                if (bestBidOthers.HasValue && newAsk <= bestBidOthers)
                {
                    resp.ErrorMessage = "Trading is currently disabled and New Ask will cross Current Bid";
                    return(resp, trades);
                }

                var bestAskOthers = otherPlayers.Select(x => x.CurrentAsk).Min();
                if (bestAskOthers.HasValue && newBid >= bestAskOthers)
                {
                    resp.ErrorMessage = "Trading is currently disabled and New Bid will cross Current Ask";
                    return(resp, trades);
                }
            }

            initiatorPlayer.CurrentAsk = null;
            initiatorPlayer.CurrentBid = null;
            UpdateBestBidAndAsk();

            while (GameState.BestCurrentBid.HasValue && newAsk <= GameState.BestCurrentBid)
            {
                var tradeReq = new TradeRequest()
                {
                    RequestId = request.RequestId,
                    GameId    = request.GameId,
                    PlayerId  = request.PlayerId,
                    IsBuy     = false,
                    Price     = GameState.BestCurrentBid.Value
                };

                var tradeResp = TradeInternal(tradeReq, true);
                if (!tradeResp.IsSuccess)
                {
                    initiatorPlayer.CurrentAsk = currentAsk;
                    initiatorPlayer.CurrentBid = currentBid;
                    resp.ErrorMessage          = tradeResp.ErrorMessage;
                    return(resp, trades);
                }
                else
                {
                    trades.AddRange(tradeResp.Trades);
                }
            }

            while (GameState.BestCurrentAsk.HasValue && newBid >= GameState.BestCurrentAsk)
            {
                var tradeReq = new TradeRequest()
                {
                    RequestId = request.RequestId,
                    GameId    = request.GameId,
                    PlayerId  = request.PlayerId,
                    IsBuy     = true,
                    Price     = GameState.BestCurrentAsk.Value
                };

                var tradeResp = TradeInternal(tradeReq, true);
                if (!tradeResp.IsSuccess)
                {
                    initiatorPlayer.CurrentAsk = currentAsk;
                    initiatorPlayer.CurrentBid = currentBid;
                    resp.ErrorMessage          = tradeResp.ErrorMessage;
                    return(resp, trades);
                }
                else
                {
                    trades.AddRange(tradeResp.Trades);
                }
            }

            initiatorPlayer.CurrentAsk = newAsk;
            initiatorPlayer.CurrentBid = newBid;
            UpdateBestBidAndAsk();

            await _dbContext.SaveChangesAsync();

            resp.BidPrice  = newBid;
            resp.AskPrice  = newAsk;
            resp.IsSuccess = true;
            return(resp, trades);
        }