public static async Task <Dictionary <string, string> > LoadSectionsFromFile(StorageFolder folder, string filename) { var file = await folder.GetFileAsync(filename); string contents = await FileIO.ReadTextAsync(file); contents = contents.Replace('\r', '\n'); Dictionary <string, string> sectionsDict = null; try { sectionsDict = StaticHelpers.GetSections(contents); } catch (Exception e) { string content = String.Format($"Error parsing file {filename}.\nIn File: {folder.Path}\n\nSuggest deleting it.\n\nError parsing sections.\nException info: {e.ToString()}"); MessageDialog dlg = new MessageDialog(content); await dlg.ShowAsync(); } return(sectionsDict); }
/// <summary> /// used by KeyDown handlers to filter out invalid rolls and keys that aren't on the NumPad /// </summary> /// <param name="key"></param> /// <param name="chars"></param> /// <returns> returns the value to pass in e.Handled </returns> public static bool FilterNumpadKeys(VirtualKey key, char[] chars) { // // filter out everythign not on Keypad (but other keyboard works too) if (!StaticHelpers.IsOnKeyPad(key)) { return(false); } if (chars.Length == 0) // first char { if (key == VirtualKey.Number0 || key == VirtualKey.NumberPad0) { return(true); } } if (chars.Length == 1) { if (chars[0] != '1') { return(true); } if (key == VirtualKey.Number0 || key == VirtualKey.Number1 || key == VirtualKey.Number2 || key == VirtualKey.NumberPad0 || key == VirtualKey.NumberPad1 || key == VirtualKey.NumberPad2) { // allow 10, 11, 12 return(false); } return(true); } return(false); }
public static void DeserializeObject <T>(this T t, string s, string kvpSep = kvpSeperatorOneLine, string propSep = propertySeperator) { string[] properties = s.Split(propSep.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); KeyValuePair kvp = null; foreach (string line in properties) { kvp = StaticHelpers.GetKeyValue(line, kvpSep[0]); PropertyInfo propInfo = t.GetType().GetTypeInfo().GetDeclaredProperty(kvp.Key); if (propInfo == null) { t.TraceMessage($"No property named {kvp.Key} in DeserializeObject"); continue; } TypeInfo typeInfo = propInfo.PropertyType.GetTypeInfo(); if (typeInfo.Name == "Guid") { // typeInfo.TraceMessage("Need to support Guid in deserializer!"); continue; } if (typeInfo.IsEnum) { propInfo.SetValue(t, Enum.Parse(propInfo.PropertyType, kvp.Value)); } else if (typeInfo.IsPrimitive) { propInfo.SetValue(t, Convert.ChangeType(kvp.Value, propInfo.PropertyType)); } else if (propInfo.PropertyType == typeof(System.TimeSpan)) { propInfo.SetValue(t, TimeSpan.Parse(kvp.Value)); } else if (propInfo.PropertyType == typeof(string)) { propInfo.SetValue(t, kvp.Value); } else if (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(List <>)) { Type elementType = typeInfo.GenericTypeArguments[0]; string[] arrayValues = kvp.Value.Split(listSeperator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); Type listType = typeof(List <>).MakeGenericType(typeInfo.GenericTypeArguments); IList listInstance = (IList)Activator.CreateInstance(listType); bool isPrimitive = elementType.GetTypeInfo().IsPrimitive; bool isEnum = elementType.GetTypeInfo().IsEnum; foreach (string val in arrayValues) { if (isPrimitive) { object o = Convert.ChangeType(val, elementType); listInstance.Add(o); } else if (isEnum) { object e = Enum.Parse(elementType, val); listInstance.Add(e); } else { t.TraceMessage($"Can't deserialize list of type {elementType.GetTypeInfo()}"); break; } } propInfo.SetValue(t, listInstance); } else { string error = String.Format($"need to support {propInfo.PropertyType.ToString()} in the deserilizer to load {kvp.Key} whose value is {kvp.Value}"); t.TraceMessage(error); throw new Exception(error); } } }
/// <summary> /// Create and run each of the games. Keep track of how long it takes. return the stats. /// </summary> /// <param name="iterations"></param> /// <param name="logger"></param> /// <param name="playerOne"></param> /// <param name="playerTwo"></param> /// <returns></returns> private async Task <GameStats> RunGames(int iterations, bool useLog, AvailablePlayer playerOne, AvailablePlayer playerTwo) { var watch = System.Diagnostics.Stopwatch.StartNew(); ConcurrentBag <Game> gameBag = new ConcurrentBag <Game>(); ConcurrentBag <Task> taskBag = new ConcurrentBag <Task>(); bool playerOneStarts = true; if (useLog) { // // this has to happen on the main thread, so it can't happen inside the worker threads // // this lets us put the documents in whatever location we want instead of inside the private storage area for the app, which is burried pretty deep in the // disk heirarchy and hard to get to. You only have to do this once per machine though. string content = "After clicking on \"Close\" pick the default location for all your CribbageAi saved state"; _saveDirectory = await StaticHelpers.GetSaveFolder(content, "CribbageAI"); _saveDirectory = await _saveDirectory.CreateFolderAsync(DateTime.Now.ToString("hh_mm_ss dd_MM_yyyy")); SaveDirectory = _saveDirectory.Path; } else { _saveDirectory = null; SaveDirectory = ""; } NotifyPropertyChanged("SaveDirectory"); // // this uses Parallel.For to create 1 thread per processor. Each thread creates a tasks and starts running it. // The task runs a game to completion, logging everything to a file. I do it this way so that I can wait for the // logs to finish writing -- I found that if I did it outside of a Task list, it would finish the log writes async Parallel.For(0, iterations, i => { taskBag.Add(Task.Run(async() => { Player player1 = (Player)Activator.CreateInstance(playerOne.GameType); player1.Init(playerOne.Parameters); player1.PlayerAlgorithm = playerOne.PlayerAlgorithm; Player player2 = (Player)Activator.CreateInstance(playerTwo.GameType); player2.Init(playerTwo.Parameters); player2.PlayerAlgorithm = playerTwo.PlayerAlgorithm; Game game = new Game(i, player1, player2, playerOneStarts); await game.Init(useLog, _saveDirectory); // // alternate who deals - looks like if you use the same algorithm, dealer *loses* 60% of the time! if ((bool)AlternateWhoStarts) { if (playerOneStarts) { playerOneStarts = false; } else { playerOneStarts = true; } } gameBag.Add(game); await game.PlayGame(); } )); }); // // wait for all the games to complete -- this includes the log writes Task.WaitAll(taskBag.ToArray()); watch.Stop(); // // add up some stats GameStats stats = new GameStats(); int totalP1LostScore = 0; int totalP2LostScore = 0; stats.WallClocktime = watch.ElapsedMilliseconds; stats.MSPerGame = stats.WallClocktime / (double)iterations; foreach (var game in gameBag) { if (game == null) { continue; } // // this calculates the number of times each player one and the average of their *losing* score // if (game.PlayerOne.Winner) { totalP2LostScore += game.PlayerTwo.Score; stats.PlayerOneWin++; } else { stats.PlayerTwoWin++; totalP1LostScore += game.PlayerOne.Score; } stats.AverageCountPointsPlayerOne += game.AverageScore(PlayerName.PlayerOne, ScoreType.Count); stats.AverageCountPointsPlayerTwo += game.AverageScore(PlayerName.PlayerTwo, ScoreType.Count); stats.AverageHandPointsPlayerOne += game.AverageScore(PlayerName.PlayerOne, ScoreType.Hand); stats.AverageHandPointsPlayerTwo += game.AverageScore(PlayerName.PlayerTwo, ScoreType.Hand); stats.AverageCribPointsPlayerOne += game.AverageScore(PlayerName.PlayerOne, ScoreType.Crib); stats.AverageCribPointsPlayerTwo += game.AverageScore(PlayerName.PlayerTwo, ScoreType.Crib); } stats.AverageCountPointsPlayerOne /= gameBag.Count; stats.AverageCountPointsPlayerTwo /= gameBag.Count; stats.AverageHandPointsPlayerOne /= gameBag.Count; stats.AverageHandPointsPlayerTwo /= gameBag.Count; stats.AverageCribPointsPlayerOne /= gameBag.Count; stats.AverageCribPointsPlayerTwo /= gameBag.Count; stats.PlayerOneWinPercent = Math.Round((double)stats.PlayerOneWin / (double)(iterations) * 100, 2); stats.PlayerTwoWinPercent = Math.Round((double)stats.PlayerTwoWin / (double)(iterations) * 100, 2); stats.AverageScorePlayerOne = Math.Round(totalP1LostScore / (double)(stats.PlayerTwoWin), 2); stats.AverageScorePlayerTwo = Math.Round(totalP2LostScore / (double)(stats.PlayerOneWin), 2); return(stats); }