Last active
April 9, 2017 12:24
-
-
Save IISResetMe/1cb193f9473906d03277 to your computer and use it in GitHub Desktop.
Parallel PGN result parser with minimal error handling
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param( | |
[parameter(Position=0)] | |
$ChessFolder = 'D:\iisresetme\ChessData\' | |
) | |
# Prepare C# method to read and process the files | |
$Challenge = @{ | |
Name = 'ResultCounter' | |
Namespace = 'ChessData' | |
PassThru = $true | |
UsingNamespace = @( | |
'System.Collections', | |
'System.Collections.Concurrent', | |
'System.Collections.Generic', | |
'System.IO', | |
'System.Threading.Tasks' | |
) | |
MemberDefinition = @' | |
public static Hashtable CountChessResults(string folder) | |
{ | |
// Use a ConcurrentDictionary to avoid concurrent updates from Parallel.ForEach() overwriting each other | |
ConcurrentDictionary<string, int> winners = new ConcurrentDictionary<string, int>(new Dictionary<string, int>() { { "Draw", 0 }, { "Black", 0 }, { "White", 0 } }); | |
Parallel.ForEach<string>(Directory.EnumerateFiles(folder, "*.pgn", SearchOption.AllDirectories), fileName => | |
{ | |
// StreamReader.ReadLine() seems to be the fastest text reader | |
using (StreamReader reader = new StreamReader(fileName)) | |
{ | |
string line; | |
while ((line = reader.ReadLine()) != null) | |
{ | |
if (line.StartsWith("[Result ")) | |
{ | |
if(line.Contains("1/2")) | |
winners.AddOrUpdate("Draw", 1, (k, v) => v + 1); | |
else if(line.Contains("1-0")) | |
winners.AddOrUpdate("Black", 1, (k, v) => v + 1); | |
else if(line.Contains("0-1")) | |
winners.AddOrUpdate("White", 1, (k, v) => v + 1); | |
} | |
} | |
} | |
}); | |
// return a hashtable, easily converted to an object in PowerShell | |
return new Hashtable(winners); | |
} | |
'@ | |
} | |
$CompilerParams = [System.CodeDom.Compiler.CompilerParameters]::new() | |
$CompilerParams.CompilerOptions = "/optimize+ /warn:0" | |
# Don't try to re-add assembly if it already exists (ie. someone already ran the script once before) | |
try { | |
$ChallengeModule = [ChessData.ResultCounter] -as [type] | |
} | |
catch{ | |
$ChallengeModule = Add-Type @Challenge -CompilerParameters $CompilerParams |Select-Object -First 1 | |
} | |
# wrapper function that takes a path to the root folder containing *.pgn files | |
function Measure-PGNResult | |
{ | |
param($path) | |
return New-Object psobject -Property $ChallengeModule::CountChessResults($(Resolve-Path $path).Path) | |
} | |
Measure-Command { | |
$Results = Measure-PGNResult $ChessFolder | |
} | |
$Results |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment