/// <summary> /// Retrieve the best chess draw for the given situation (board + previous draw) from the cache. If the situation is not in the cache, null is returned. /// </summary> /// <param name="board">The chess board representing the situation.</param> /// <param name="predecedingDraw">The previous draw made by the enemy.</param> /// <returns>The best chess draw (if there is one in the cache)</returns> public ChessDraw?GetBestDraw(IChessBoard board, ChessDraw?predecedingDraw) { // get possible draws from database (with win rate) var drawingSide = predecedingDraw?.DrawingSide.Opponent() ?? ChessColor.White; string sql = $"WITH Situation AS( " + $" SELECT " + $" DrawHash, " + $" WinRate, " + $" AnalyzedGames, " + $" WinRate * AnalyzedGames AS Score " + $" FROM WinRateInfo " + $" WHERE DrawingSide = '{ char.ToLower(drawingSide.ToChar()) }' AND BoardBeforeHash = '{ board.ToHash() }' " + $") " + $"SELECT " + $" DrawHash, " + $" Score " + $"FROM Situation " + $"WHERE Score = (SELECT MAX(Score) FROM Situation)"; var bestDraws = queryItems(sql).Select(x => new Tuple <ChessDraw, double>(new ChessDraw(int.Parse(x["DrawHash"] as string, NumberStyles.HexNumber)), (double)x["Score"])).ToList(); return(bestDraws?.Count > 0 ? (ChessDraw?)bestDraws.ChooseRandom().Item1 : null); // query for testing // ==================================== // WITH Situation AS( // SELECT // DrawHashMetadata.*, // WinRate, // AnalyzedGames // FROM WinRateInfo // INNER JOIN DrawHashMetadata ON WinRateInfo.DrawHash = DrawHashMetadata.DrawHash // WHERE WinRateInfo.DrawingSide = 'w' AND BoardBeforeHash = '19482090A3318C6318C60000000000000000000000000000000000000000B5AD6B5AD69D6928D2B3' // ) // // SELECT // *, // WinRate* AnalyzedGames AS Score // FROM Situation // ORDER BY Score DESC }