using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; using GameOfLife.Entities; using GameOfLife.IO; namespace GameOfLife { public class PatternLibrary { public const int PatternLoadLimit = 100; public const int OscillationMaxPeriod = 50; public IReadOnlyList> PatternProjections; public IReadOnlyList> Patterns; public IReadOnlyDictionary PatternToMetadata; public PatternLibrary() { Patterns = ExtractPatterns(GetPatternFileLines()).AsReadOnly(); PatternProjections = ExtractOscillationsAndProjections(Patterns); PatternToMetadata = Patterns.ToDictionary(t => t.Item2, t => t.Item1); } private static List> ExtractOscillationsAndProjections(IEnumerable> patterns) { var results = from pattern in patterns.AsParallel() let life = new LifeHashSet(pattern.Item2) let oscillation = life.FindOscillation(OscillationMaxPeriod) let variations = new Projections(oscillation) select Tuple.Create(pattern.Item1, variations); return results.ToList(); } private static List> ExtractPatterns(IEnumerable fileLines) { // first line is the header var pattern = from line in fileLines.Skip(1).Take(PatternLoadLimit) select line.Split(',') into split let name = split[0].Trim() let apgCode = split[1].Trim() select new ApgcodeDecoder(apgCode, name) into decoder select Tuple.Create(decoder.Metadata, decoder.Pattern.Normalize()); var extractPatterns = pattern.ToList(); // ensure this patterns are all unique var duplicates = string.Join(", ", extractPatterns .GroupBy(tuple => tuple) .Where(tuples => tuples.Count() > 1) .Select(t => t.Key.Item1.Name)); if (duplicates.Length > 0) throw new Exception($"Duplicate patterns: " + duplicates); return extractPatterns; } private static IEnumerable GetPatternFileLines() { var assembly = Assembly.GetExecutingAssembly(); //Getting names of all embedded resources var allResourceNames = assembly.GetManifestResourceNames(); var resourceName = allResourceNames.First(n => n.Contains("CommonPatterns.csv")); var fileLines = new List(); using (var stream = assembly.GetManifestResourceStream(resourceName)) if (stream != null) using (var tx = new StreamReader(stream)) { while (!tx.EndOfStream) fileLines.Add(tx.ReadLine()); } return fileLines; } } }