public async Task HandleRequest(IOwinContext context) { var pocket = context.Request.Query["pocket"]; var board = context.Request.Query["board"]; var callback = context.Request.Query["callback"]; if (string.IsNullOrWhiteSpace(board)) { board = string.Empty; } var odds = new TexasHoldemOdds { Pocket = HoldemOddsCalculator.SortCards(pocket), Board = HoldemOddsCalculator.SortCards(board) }; var cacheOdds = Cache.Get(odds.GetCacheKey()) as TexasHoldemOdds; if (cacheOdds == null) { Cache.Add(odds.GetCacheKey(), odds, _policy); var calculator = new HoldemOddsCalculator(); cacheOdds = await calculator.Calculate(odds, o => Cache.Set(odds.GetCacheKey(), odds, _policy)); } //check If-None-Match header etag to see if it matches our data hash else if (context.Request.Headers["If-None-Match"] == cacheOdds.GetETag()) { //if it does return 304 Not Modified context.Response.StatusCode = 304; return; } var jsonData = await Task.Factory.StartNew(() => JsonConvert.SerializeObject(cacheOdds)); var result = string.Empty; if (string.IsNullOrWhiteSpace(callback)) { context.Response.ContentType = "application/json"; result = jsonData; } else { context.Response.ContentType = "application/javascript"; result = callback + "(" + jsonData + ");"; } //set the response as cached for cache duration context.Response.Headers["Cache-Control"] = string.Format("max-age={0}", CACHE_DURATION_SECS); //set etag context.Response.ETag = cacheOdds.GetETag(); //Just in case, handle CORS context.Response.Headers["Access-Control-Allow-Origin"] = "*"; await context.Response.WriteAsync(result); }
public async Task <TexasHoldemOdds> Calculate(TexasHoldemOdds odds, Action <TexasHoldemOdds> saveState) { var outcomes = new List <PokerOutcome>(); for (var index = 0; index < Enum.GetNames(typeof(Hand.HandTypes)).Length; index++) { outcomes.Add(new PokerOutcome { HandType = ((Hand.HandTypes)index).ToString(), WinChance = 0 }); } odds.Outcomes = outcomes; if (saveState != null) { saveState(odds); } return(await Task <TexasHoldemOdds> .Run(() => { ulong playerMask = Hand.ParseHand(odds.Pocket); // Player Pocket Cards ulong partialBoard = Hand.ParseHand(odds.Board); // Partial Board // Calculate values for each hand type double[] playerWins = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; double[] opponentWins = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; // Count of total hands examined. long count = 0; // Iterate through all possible opponent hands foreach (ulong opponentMask in Hand.Hands(0UL, partialBoard | playerMask, 2).AsParallel()) { // Iterate through all possible boards foreach (ulong boardMask in Hand.Hands(partialBoard, opponentMask | playerMask, 5).AsParallel()) { // Create a hand value for each player uint playerHandValue = Hand.Evaluate(boardMask | playerMask, 7); uint opponentHandValue = Hand.Evaluate(boardMask | opponentMask, 7); // Calculate Winners if (playerHandValue > opponentHandValue) { // Player Win playerWins[Hand.HandType(playerHandValue)] += 1.0; } else if (playerHandValue < opponentHandValue) { // Opponent Win opponentWins[Hand.HandType(opponentHandValue)] += 1.0; } else if (playerHandValue == opponentHandValue) { // Give half credit for ties. playerWins[Hand.HandType(playerHandValue)] += 0.5; opponentWins[Hand.HandType(opponentHandValue)] += 0.5; } count++; } for (var index = 0; index < playerWins.Length; index++) { outcomes[index].WinChance = playerWins[index] / ((double)count); } if (saveState != null) { saveState(odds); } } odds.OverallWinSplitChance = odds.Outcomes.Sum(o => o.WinChance); odds.Completed = true; if (saveState != null) { saveState(odds); } return odds; })); }
static void Main(string[] args) { Console.WriteLine(Assembly.GetExecutingAssembly().GetName().FullName); Console.WriteLine(); if (args.Length < 1) { Console.WriteLine("Please specifiy output folder path"); return; } _outputPath = args[0]; Directory.CreateDirectory(_outputPath); bool overwrite = false; if (args.Length > 1) { if (args[1].Equals("/overwrite", StringComparison.InvariantCultureIgnoreCase)) { overwrite = true; } } var deck = GenerateDeck(); var calculator = new HoldemOddsCalculator(); var tasks = new List<Task>(); for (int i = 0; i < deck.Count; i++) { for (int j = 0; j < deck.Count; j++) { //must be different cards if (i != j) { var odds = new TexasHoldemOdds { Pocket = HoldemOddsCalculator.SortCards(string.Format("{0} {1}", deck[i], deck[j])), Board = String.Empty }; //if the file exists, and we are not overwriting, skip these cards if (!overwrite && File.Exists(Path.Combine(_outputPath, string.Format("{0}.json", odds.GetCacheKey())))) { Console.WriteLine("Skipping odds for pocket {0}", odds.Pocket); continue; } Console.WriteLine("Generating odds for pocket {0}", odds.Pocket); var calculateTask = calculator.Calculate(odds, o => Console.WriteLine("Updated odds for pocket {0}", o.Pocket)); calculateTask.ContinueWith(t => SaveOdds(t.Result)); tasks.Add(calculateTask); //if we've got enough tasks to keep the processors busy if (tasks.Count >= Environment.ProcessorCount) { //wait for any of them to finish Task.WaitAny(tasks.ToArray(), Timeout.Infinite); //remove any completed tasks int k = 0; while ( k < tasks.Count) { if (tasks[k].IsCompleted) { tasks.RemoveAt(k); } else { k++; } } } } } } if (tasks.Count > 0) { //wait for the remainder to complete Task.WaitAll(tasks.ToArray(), Timeout.Infinite); } var outPath = Path.Combine(_outputPath, "PrimeCache.json"); if (File.Exists(outPath)) { File.Delete(outPath); } using (var outputArchive = new StreamWriter(outPath)) { bool firstItem = true; Directory.GetFiles(_outputPath, "*.json") .Where(filePath => !filePath.Equals(outPath, StringComparison.InvariantCultureIgnoreCase)) .ToList().ForEach(filePath => { if (firstItem) { outputArchive.Write("["); firstItem = false; } else { outputArchive.WriteLine(","); } using (var inputStream = new StreamReader(filePath)) { outputArchive.Write(inputStream.ReadToEnd()); } }); outputArchive.WriteLine("]"); } Console.WriteLine("Job Done"); }
public async Task<TexasHoldemOdds> Calculate(TexasHoldemOdds odds, Action<TexasHoldemOdds> saveState) { var outcomes = new List<PokerOutcome>(); for (var index = 0; index < Enum.GetNames(typeof(Hand.HandTypes)).Length; index++) { outcomes.Add(new PokerOutcome { HandType = ((Hand.HandTypes)index).ToString(), WinChance = 0 }); } odds.Outcomes = outcomes; if (saveState != null) { saveState(odds); } return await Task<TexasHoldemOdds>.Run(() => { ulong playerMask = Hand.ParseHand(odds.Pocket); // Player Pocket Cards ulong partialBoard = Hand.ParseHand(odds.Board); // Partial Board // Calculate values for each hand type double[] playerWins = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; double[] opponentWins = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; // Count of total hands examined. long count = 0; // Iterate through all possible opponent hands foreach (ulong opponentMask in Hand.Hands(0UL, partialBoard | playerMask, 2).AsParallel()) { // Iterate through all possible boards foreach (ulong boardMask in Hand.Hands(partialBoard, opponentMask | playerMask, 5).AsParallel()) { // Create a hand value for each player uint playerHandValue = Hand.Evaluate(boardMask | playerMask, 7); uint opponentHandValue = Hand.Evaluate(boardMask | opponentMask, 7); // Calculate Winners if (playerHandValue > opponentHandValue) { // Player Win playerWins[Hand.HandType(playerHandValue)] += 1.0; } else if (playerHandValue < opponentHandValue) { // Opponent Win opponentWins[Hand.HandType(opponentHandValue)] += 1.0; } else if (playerHandValue == opponentHandValue) { // Give half credit for ties. playerWins[Hand.HandType(playerHandValue)] += 0.5; opponentWins[Hand.HandType(opponentHandValue)] += 0.5; } count++; } for (var index = 0; index < playerWins.Length; index++) { outcomes[index].WinChance = playerWins[index] / ((double)count); } if (saveState != null) { saveState(odds); } } odds.OverallWinSplitChance = odds.Outcomes.Sum(o => o.WinChance); odds.Completed = true; if (saveState != null) { saveState(odds); } return odds; }); }
private static void SaveOdds(TexasHoldemOdds odds) { Console.WriteLine("Saving generated odds for pocket {0}", odds.Pocket); var json = JsonConvert.SerializeObject(odds); File.WriteAllText(Path.Combine(_outputPath, string.Format("{0}.json", odds.GetCacheKey())), json); }