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; }
private void HandleUpdateQuoteResponse(UpdateQuoteResponse obj) { _logger.LogInformation("HandleUpdateQuoteResponse Message={0}", obj); if (OnUpdateQuoteResponse != null) { OnUpdateQuoteResponse(obj); } }
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); } }
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); }