private static TSettings deserialize <TSettings>(string filename, SettingsSerializer serializer) where TSettings : SettingsBase, new() { return(Ut.WaitSharingVio(maximum: TimeSpan.FromSeconds(5), func: () => { switch (serializer) { case SettingsSerializer.ClassifyXml: return ClassifyXml.DeserializeFile <TSettings>(filename); case SettingsSerializer.ClassifyJson: return ClassifyJson.DeserializeFile <TSettings>(filename); case SettingsSerializer.ClassifyBinary: return ClassifyBinary.DeserializeFile <TSettings>(filename); case SettingsSerializer.DotNetBinary: var bf = new BinaryFormatter(); using (var fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read)) return (TSettings)bf.Deserialize(fs); default: throw new InternalErrorException("6843184"); } })); }
private static void RetrievePonyCoatColorsFromMlpWikia() { var ponyColors = ClassifyJson.DeserializeFile <Dictionary <string, string> >(_poniesJson); ponyColors.Where(kvp => kvp.Value == null).ParallelForEach(kvp => { var pony = kvp.Key; try { var client = new HClient(); var response = client.Get(@"http://mlp.wikia.com/wiki/" + pony.Replace(' ', '_')); var str = response.DataString; var doc = CQ.CreateDocument(str); var infoboxes = doc["table.infobox"]; string color = null; for (int i = 0; i < infoboxes.Length - 1; i++) { if (infoboxes[i].Cq()["th[colspan='2']"].FirstOrDefault()?.InnerText.Contains(pony) != true) { continue; } var colorTr = infoboxes[i + 1].Cq().Find("tr").Where(tr => tr.Cq().Find("td>b").Any(td => td.InnerText == "Coat")).ToArray(); if (colorTr.Length == 0 || colorTr[0].Cq().Find("td").Length != 2) { continue; } var colorSpan = colorTr[0].Cq().Find("td>span"); var styleAttr = colorSpan[0]["style"]; var m = Regex.Match(styleAttr, @"background-color\s*:\s*#([A-F0-9]{3,6})"); if (m.Success) { color = m.Groups[1].Value; } } lock (ponyColors) { ConsoleUtil.WriteLine($"{pony.Color(ConsoleColor.Cyan)} = {(color == null ? "<nope>".Color(ConsoleColor.Red) : color.Color(ConsoleColor.Green))}", null); //if (color != null) ponyColors[pony] = color ?? "?"; } } catch (Exception e) { lock (ponyColors) ConsoleUtil.WriteLine($"{pony.Color(ConsoleColor.Cyan)} = {e.Message.Color(ConsoleColor.Red)} ({e.GetType().FullName.Color(ConsoleColor.DarkRed)})", null); } }); ClassifyJson.SerializeToFile(ponyColors, _poniesJson); }
public static void DoStuff() { var jsonFile = @"D:\c\KTANE\KtaneStuff\DataFiles\Hexamaze\Hexamaze.json"; var maze = ClassifyJson.DeserializeFile <HexamazeInfo>(jsonFile); Console.WriteLine(areMarkingsUnique(maze, saveFiles: true)); //var dic = new Dictionary<string, int>(); //var triangles = new[] { Marking.TriangleDown, Marking.TriangleLeft, Marking.TriangleRight, Marking.TriangleUp }; //var trianglesV = new[] { Marking.TriangleLeft, Marking.TriangleRight }; //var trianglesE = new[] { Marking.TriangleDown, Marking.TriangleUp }; //foreach (var center in Hex.LargeHexagon(9)) //{ // var countC = Hex.LargeHexagon(4).Select(h => maze.Markings.Get(center + h, Marking.None)).Count(m => m == Marking.Circle); // var countH = Hex.LargeHexagon(4).Select(h => maze.Markings.Get(center + h, Marking.None)).Count(m => m == Marking.Hexagon); // var countTV = Hex.LargeHexagon(4).Select(h => maze.Markings.Get(center + h, Marking.None)).Count(m => trianglesV.Contains(m)); // var countTE = Hex.LargeHexagon(4).Select(h => maze.Markings.Get(center + h, Marking.None)).Count(m => trianglesE.Contains(m)); // dic.IncSafe(new[] { countC != 0 ? countC + " circles" : null, countH != 0 ? countH + " hexagons" : null, countTV != 0 ? countTV + " vertex triangles" : null, countTE != 0 ? countTE + " edge triangles" : null }.Where(x => x != null).JoinString(", ")); //} //foreach (var kvp in dic.OrderBy(k => k.Value)) // Console.WriteLine($"{kvp.Key} = {kvp.Value} times ({kvp.Value / (double) 217 * 100:0.00}%)"); //// Create the PNG for the Paint.NET layer //const double hexWidth = 72; //var lhw = Hex.LargeWidth(4) * hexWidth; //var lhh = Hex.LargeHeight(4) * hexWidth * Hex.WidthToHeight; //GraphicsUtil.DrawBitmap((int) lhw, (int) lhh, g => //{ // g.Clear(Color.Transparent); // g.FillPolygon(new SolidBrush(Color.FromArgb(10, 104, 255)), Hex.LargeHexagonOutline(4, hexWidth).Select(p => new PointD(p.X + lhw / 2, p.Y + lhh / 2).ToPointF()).ToArray()); //}).Save(@"D:\temp\temp.png"); maze = GenerateMarkings(maze); WriteMazeInManual(maze); // Save the JSON //ClassifyJson.SerializeToFile(maze, jsonFile); }
static int DoMain(string[] args) { // Parse command-line arguments Args = CommandLineParser.ParseOrWriteUsageToConsole <CmdLine>(args); if (Args == null) { return(-1); } // Load settings file if (Args.SettingsPath != null) { if (File.Exists(Args.SettingsPath)) { Settings = ClassifyJson.DeserializeFile <Settings>(Args.SettingsPath); } else { Settings = new Settings(); ClassifyJson.SerializeToFile(Settings, Args.SettingsPath); } RefreshAccessControl = Settings.SkipRefreshAccessControlDays == null || (Settings.LastRefreshAccessControl + TimeSpan.FromDays((double)Settings.SkipRefreshAccessControlDays) < DateTime.UtcNow); Console.WriteLine($"Refresh access control: {RefreshAccessControl}"); Console.WriteLine($"Update metadata: {UpdateMetadata}"); } // Initialise log files var startTime = DateTime.UtcNow; if (Args.LogPath != null) { if (Args.LogPath == "") { Args.LogPath = PathUtil.AppPath; } var enc = new UTF8Encoding(false, throwOnInvalidBytes: false); // allows us to log filenames that are not valid UTF-16 (unpaired surrogates) ActionLog = new IO.StreamWriter(IO.File.Open(Path.Combine(Args.LogPath, $"HoboMirror-Actions.{DateTime.Today:yyyy-MM-dd}.txt"), IO.FileMode.Append, IO.FileAccess.Write, IO.FileShare.Read), enc); ChangeLog = new IO.StreamWriter(IO.File.Open(Path.Combine(Args.LogPath, $"HoboMirror-Changes.{DateTime.Today:yyyy-MM-dd}.txt"), IO.FileMode.Append, IO.FileAccess.Write, IO.FileShare.Read), enc); ErrorLog = new IO.StreamWriter(IO.File.Open(Path.Combine(Args.LogPath, $"HoboMirror-Errors.{DateTime.Today:yyyy-MM-dd}.txt"), IO.FileMode.Append, IO.FileAccess.Write, IO.FileShare.Read), enc); CriticalErrorLog = new IO.StreamWriter(IO.File.Open(Path.Combine(Args.LogPath, $"HoboMirror-ErrorsCritical.{DateTime.Today:yyyy-MM-dd}.txt"), IO.FileMode.Append, IO.FileAccess.Write, IO.FileShare.Read), enc); DebugLog = new IO.StreamWriter(IO.File.Open(Path.Combine(Args.LogPath, $"HoboMirror-Debug.{DateTime.Today:yyyy-MM-dd}.txt"), IO.FileMode.Append, IO.FileAccess.Write, IO.FileShare.Read), enc); } try { // Parse volumes to be snapshotted var tasks = Args.FromPath.Zip(Args.ToPath, (from, to) => new { FromPath = from, ToPath = to, ToGuard = Path.Combine(to, "__HoboMirrorTarget__.txt"), FromVolume = Regex.Match(from, @"^\\\\\?\\Volume{[^}]+}\\").Apply(match => match.Success ? match.Groups[0].Value : null) ?? Regex.Match(from, @"^\w:\\").Apply(match => match.Success ? match.Groups[0].Value : null) ?? Ut.Throw <string>(new InvalidOperationException($"Expected absolute path: {from}")) // this should be taken care of by the CmdLine specification, so throw here }); // Log header LogAll("=============="); LogAll($"Started at {DateTime.Now}"); // Refuse to mirror without a guard file foreach (var task in tasks) { if (!File.Exists(task.ToGuard) || !File.ReadAllText(task.ToGuard).ToLower().Contains("allow")) { LogError($"Target path is not marked with a guard file: {task.ToPath}"); LogError($"Due to the potentially destructive nature of mirroring, every mirror destination must contain a guard file. This path does not. Mirroring aborted."); LogError($"To allow mirroring to this path, please create a file at {task.ToGuard}. The file must contain the word “allow”."); LogError($"Remember that HoboMirror will delete files at this path without confirmation."); return(-1); } } // Enable the necessary privilege to read and write everything try { WinAPI.ModifyPrivilege(PrivilegeName.SeBackupPrivilege, true); WinAPI.ModifyPrivilege(PrivilegeName.SeRestorePrivilege, true); //WinAPI.ModifyPrivilege(PrivilegeName.SeSecurityPrivilege, true); //WinAPI.ModifyPrivilege(PrivilegeName.SeTakeOwnershipPrivilege, true); } catch (Win32Exception e) { LogError("Unable to obtain the necessary privileges. Some files and/or attributes will not be replicated."); LogError(e.Message); } // Perform the mirroring var volumes = tasks.GroupBy(t => t.FromVolume).Select(g => g.Key).ToArray(); using (var vsc = UseVolumeShadowCopy ? new VolumeShadowCopy(volumes) : null) { var vscVolumes = UseVolumeShadowCopy ? vsc.Volumes : new ReadOnlyDictionary <string, VolumeShadowCopyVol>(volumes.ToDictionary(vol => vol, vol => new VolumeShadowCopyVol { Path = vol, SnapshotPath = vol })); foreach (var task in tasks) { var fromPath = Path.Combine(vscVolumes[task.FromVolume].SnapshotPath, task.FromPath.Substring(task.FromVolume.Length)); LogAll($" Mirror task: from “{task.FromPath}” to “{task.ToPath}” (volume snapshot path: {fromPath})"); } foreach (var ignore in Args.IgnorePath.Concat(Settings.IgnorePaths).Order()) { LogAll($" Ignore path: “{ignore}”"); } foreach (var ignore in Settings.IgnoreDirNames) { LogAll($" Ignore directory name: “{ignore}”"); } foreach (var task in tasks) { GetOriginalSrcPath = str => str.Replace(vscVolumes[task.FromVolume].SnapshotPath, task.FromVolume).Replace(@"\\", @"\"); if (!Directory.Exists(task.ToPath)) { ActCreateDirectory(task.ToPath); } var srcItem = new Item(new DirectoryInfo(Path.Combine(vscVolumes[task.FromVolume].SnapshotPath, task.FromPath.Substring(task.FromVolume.Length))), ItemType.Dir); var tgtItem = CreateItem(new DirectoryInfo(task.ToPath)); if (tgtItem != null) { SyncDir(srcItem, tgtItem); } else { LogError($"Unable to execute mirror task: {task.FromPath}"); } } } // List changed directories and update change counts LogChange("", null); LogChange("DIRECTORIES WITH AT LEAST ONE CHANGE:", null); if (Settings == null) { foreach (var chg in ChangedDirs.Order()) { LogChange(" " + chg, null); } } else { foreach (var dir in ChangedDirs) { Settings.DirectoryChangeCount[dir].TimesChanged++; } LogChange("(sorted from rarely changing to frequently changing)", null); var changes = from dir in ChangedDirs let match = Settings.GroupDirectoriesForChangeReport.Select(dg => dg.GetMatch(dir)).Where(m => m != null).MinElementOrDefault(s => s.Length) group dir by match ?? dir into grp let changeCounts = grp.Select(p => Settings.DirectoryChangeCount[p]) select new { path = grp.Key, changeFreq = changeCounts.Sum(ch => ch.TimesChanged) / (double)changeCounts.Sum(ch => ch.TimesScanned) }; foreach (var chg in changes.OrderBy(ch => ch.changeFreq)) { LogChange($" {chg.path} — {chg.changeFreq:0.0%}", null); } } if (RefreshAccessControl) { Settings.LastRefreshAccessControl = DateTime.UtcNow; } // Save settings file if (Args.SettingsPath != null) { ClassifyJson.SerializeToFile(Settings, Args.SettingsPath); } return(CriticalErrors > 0 ? 2 : Errors > 0 ? 1 : 0); } #if !DEBUG catch (Exception e) { LogCriticalError($"Unhandled exception ({e.GetType().Name}): {e.Message}"); LogCriticalError(e.StackTrace); return(1); } #endif finally { // Close log files if (Args.LogPath != null) { foreach (var log in new[] { ActionLog, ChangeLog, ErrorLog, CriticalErrorLog, DebugLog }) { log.WriteLine($"Ended at {DateTime.Now}. Time taken: {(DateTime.UtcNow - startTime).TotalMinutes:#,0.0} minutes"); log.Dispose(); } } } }
public override HttpResponse Handle(HttpRequest req) { if (Settings.DataDir == null || !Directory.Exists(Settings.DataDir)) { return(HttpResponse.Html($@"<h1>Data folder not configured.</h1>", HttpStatusCode._500_InternalServerError)); } if (req.Method == HttpMethod.Post) { return(processPost(req)); } if (req.Url["set"] != null) { var filePath = Path.Combine(Settings.DataDir, $"set-{req.Url["set"]}.json"); if (!File.Exists(filePath)) { return(HttpResponse.PlainText("That set does not exist.", HttpStatusCode._404_NotFound)); } var set = ClassifyJson.DeserializeFile <RankSet>(filePath); return(HttpResponse.Html(new HTML( new HEAD( new TITLE("Rank"), new META { name = "viewport", content = "width=device-width,initial-scale=1.0" }, new META { charset = "utf-8" }, new STYLELiteral(Resources.RankCss)), new BODY( new H1(set.Name), set.ListRankings.Count == 0 ? null : Ut.NewArray <object>( new H2($"Existing rankings"), new UL(set.ListRankings.Select(ranking => new LI(new A { href = req.Url.WithoutQuery().WithQuery("ranking", ranking.PublicToken).ToHref() }._(ranking.Title), ranking.Finished ? null : " (unfinished)")))), new FORM { action = req.Url.ToHref(), method = method.post }._( new INPUT { type = itype.hidden, name = "fnc", value = "start" }, new INPUT { type = itype.hidden, name = "set", value = set.Hash }, new H2($"Start a new ranking"), new P("Enter the title for this ranking. Preferably start with your name and specify the ranking criterion. For example: “Brian, by preference” or “Thomas, by difficulty”."), new DIV(new INPUT { name = "title", value = "Brian, by preference", accesskey = "," }), new P("Enter the question to ask for comparing each pair of items (examples: “Which do you like better?” (ranking by preference), “Which do you find harder?” (ranking by difficulty), etc.)"), new DIV(new INPUT { name = "question", value = "Which do you like better?" }), new DIV(new BUTTON { type = btype.submit, accesskey = "g" }._(new KBD("G"), "o"))))))); } if (req.Url["ranking"] != null) { var filePath = rankingPath(req.Url["ranking"]); if (!File.Exists(filePath)) { return(HttpResponse.PlainText("That ranking does not exist.", HttpStatusCode._404_NotFound)); } var ranking = ClassifyJson.DeserializeFile <RankRanking>(filePath); var setFilePath = setPath(ranking.SetHash); if (!File.Exists(setFilePath)) { return(HttpResponse.PlainText("The set does not exist.", HttpStatusCode._404_NotFound)); } var set = ClassifyJson.DeserializeFile <RankSet>(setFilePath); var canEdit = false; if (req.Url["secret"] != null) { if (req.Url["secret"] != ranking.PrivateToken) { return(HttpResponse.Redirect(req.Url.WithoutQuery("secret"))); } canEdit = true; } var(ix1, ix2, ranked) = attemptRanking(ranking, set); return(HttpResponse.Html(new HTML( new HEAD( new TITLE("Rank"), new META { name = "viewport", content = "width=device-width,initial-scale=1.0" }, new META { charset = "utf-8" }, new STYLELiteral(Resources.RankCss)), new BODY( new H1(set.Name), new H2(ranking.Title), ix1 == -1 || !canEdit ? null : new FORM { action = req.Url.ToHref(), method = method.post }._( new INPUT { type = itype.hidden, name = "fnc", value = "rank" }, new INPUT { type = itype.hidden, name = "ranking", value = ranking.PublicToken }, new INPUT { type = itype.hidden, name = "secret", value = ranking.PrivateToken }, new INPUT { type = itype.hidden, name = "ix1", value = ix1.ToString() }, new INPUT { type = itype.hidden, name = "ix2", value = ix2.ToString() }, new P { class_ = "comparison" }._(ranking.Question), new DIV { class_ = "comparison" }._(new BUTTON { type = btype.submit, name = "more", value = ix1.ToString() }._(set.Items[ix1])), new DIV { class_ = "comparison" }._(new BUTTON { type = btype.submit, name = "more", value = ix2.ToString() }._(set.Items[ix2]))), new UL(ranked.Select(ix => new LI { class_ = ranked.All(rIx => rIx == ix || ranking.Comparisons.Any(rc => (rc.Less == ix && rc.More == rIx) || (rc.Less == rIx && rc.More == ix))) ? "complete" : "incomplete" }._(set.Items[ix]))))))); } return(HttpResponse.Html(new HTML( new HEAD( new TITLE("Rank"), new META { name = "viewport", content = "width=device-width,initial-scale=1.0" }, new META { charset = "utf-8" }, new STYLELiteral(Resources.RankCss)), new BODY( new FORM { action = req.Url.ToHref(), method = method.post }._( new INPUT { type = itype.hidden, name = "fnc", value = "create" }, new H1("Rank what?"), new P("Choose a set to rank."), new UL(_setsList.Select(s => new LI(new A { href = req.Url.WithQuery("set", s.Hash).ToHref() }._(s.Name)))), new P("Or enter/paste the items that need ranking (one item per line)."), new DIV(new TEXTAREA { name = "items", accesskey = "," }), new P("Give it a name (e.g.: Episodes of “Best Show Evar”)."), new DIV(new INPUT { type = itype.text, name = "title", value = "Episodes of “Best Show Evar”" }), new DIV(new BUTTON { type = btype.submit, accesskey = "g" }._(new KBD("G"), "o"))))))); }
public override void Init(LoggerBase log) { base.Init(log); if (Settings.DataDir != null && Directory.Exists(Settings.DataDir)) { _setsList.Clear(); _setsList.AddRange(new DirectoryInfo(Settings.DataDir).EnumerateFiles("set-*.json").Select(f => ClassifyJson.DeserializeFile <RankSet>(f.FullName).ToSlim())); _setsDic = _setsList.ToDictionary(set => set.Hash); } }
private HttpResponse processPost(HttpRequest req) { switch (req.Post["fnc"].Value) { case "create": var items = req.Post["items"].Value.Replace("\r", "").Trim().Split('\n').Select(line => line.Trim()).ToArray(); var hash = MD5.Create().ComputeHash(items.JoinString("\n").ToUtf8()).ToHex(); var newSet = new RankSet { Hash = hash, Items = items, Name = req.Post["title"].Value }; if (!_setsDic.ContainsKey(hash)) { lock (this) if (!_setsDic.ContainsKey(hash)) { var newSetSlim = newSet.ToSlim(); _setsDic[hash] = newSetSlim; _setsList.Add(newSetSlim); ClassifyJson.SerializeToFile(newSet, setPath(hash)); } } return(HttpResponse.Redirect(req.Url.WithQuery("set", hash))); case "start": lock (this) { var currentSetHash = req.Post["set"].Value; var setFilePath = setPath(currentSetHash); if (!File.Exists(setFilePath)) { return(HttpResponse.PlainText("That set does not exist.", HttpStatusCode._404_NotFound)); } var currentSet = ClassifyJson.DeserializeFile <RankSet>(setFilePath); retry: var publicToken = Rnd.GenerateString(32); var privateToken = Rnd.GenerateString(32); var path = rankingPath(publicToken); if (File.Exists(path) || currentSet.DicRankings.ContainsKey(publicToken)) { goto retry; } var newRanking = new RankRanking { Finished = false, PublicToken = publicToken, PrivateToken = privateToken, SetHash = currentSetHash, Title = req.Post["title"].Value, Question = req.Post["question"].Value }; var newRankingSlim = newRanking.ToSlim(); currentSet.DicRankings[publicToken] = newRankingSlim; currentSet.ListRankings.Add(newRankingSlim); ClassifyJson.SerializeToFile(newRanking, path); ClassifyJson.SerializeToFile(currentSet, setFilePath); return(HttpResponse.Redirect(req.Url.WithoutQuery().WithQuery("ranking", publicToken).WithQuery("secret", privateToken))); } case "rank": lock (this) { var publicToken = req.Post["ranking"].Value; var privateToken = req.Post["secret"].Value; var rankingFilePath = rankingPath(publicToken); if (!File.Exists(rankingFilePath)) { return(HttpResponse.PlainText("That ranking does not exist.", HttpStatusCode._404_NotFound)); } var currentRanking = ClassifyJson.DeserializeFile <RankRanking>(rankingFilePath); if (privateToken != currentRanking.PrivateToken) { return(HttpResponse.PlainText("You cannot vote in this ranking.", HttpStatusCode._404_NotFound)); } var setFilePath = setPath(currentRanking.SetHash); if (!File.Exists(setFilePath)) { return(HttpResponse.PlainText("That set does not exist.", HttpStatusCode._404_NotFound)); } var currentSet = ClassifyJson.DeserializeFile <RankSet>(setFilePath); if (!int.TryParse(req.Post["ix1"].Value, out var ix1) || !int.TryParse(req.Post["ix2"].Value, out var ix2) || !int.TryParse(req.Post["more"].Value, out var more) || (more != ix1 && more != ix2)) { return(HttpResponse.PlainText("Invalid integers.", HttpStatusCode._404_NotFound)); } var newComparison = new RankComparison(more == ix1 ? ix2 : ix1, more == ix1 ? ix1 : ix2); // Transitive closure var ancestorLesses = currentRanking.Comparisons.Where(c => c.More == newComparison.Less).Select(c => c.Less).ToList(); ancestorLesses.Add(newComparison.Less); var descendantMores = currentRanking.Comparisons.Where(c => c.Less == newComparison.More).Select(c => c.More).ToList(); descendantMores.Add(newComparison.More); for (int i = 0; i < ancestorLesses.Count; i++) { for (int j = 0; j < descendantMores.Count; j++) { currentRanking.Comparisons.Add(new RankComparison(ancestorLesses[i], descendantMores[j])); } } var result = attemptRanking(currentRanking, currentSet); if (result.ix1 == -1) { currentRanking.Finished = true; // This relies on reference equality, i.e. that currentSet.ListRankings contains the same object currentSet.DicRankings[publicToken].Finished = true; ClassifyJson.SerializeToFile(currentSet, setFilePath); } ClassifyJson.SerializeToFile(currentRanking, rankingFilePath); return(HttpResponse.Redirect(req.Url.WithoutQuery().WithQuery("ranking", publicToken).WithQuery("secret", privateToken))); } } return(HttpResponse.PlainText("What?", HttpStatusCode._500_InternalServerError)); }
private static void GenerateNumerals() { var oldNumberData = new Dictionary<string, double>(); try { oldNumberData = ClassifyJson.DeserializeFile<Dictionary<string, double>>(@"D:\temp\TheClockNumberData.json"); } catch { } var numberData = new Dictionary<string, double>() { { "AAgency FB", 1.2 }, { "RAgency FB", 1.0 }, { "ABaskerville Old Face|.1|.09", 1.2 }, { "RBaskerville Old Face", 0.7 }, { "ABodoni MT Condensed|.07|.06", 1.6 }, { "RBodoni MT Condensed", 1.2 }, { "ACentury|.11|.1", 1.1 }, { "RCentury", 0.7 }, { "ACentury Gothic|.1|.07", 1.1 }, { "RCentury Gothic", 0.9 }, { "AHarrington|.09|.06", 1.4 }, { "RCopperplate Gothic Light", 0.9 }, { "AEdwardian Script ITC|.09|.06", 1.4 }, { "RDejaVu Serif", 0.7 }, { "AFelix Titling", 1.25 }, { "RFelix Titling", 0.85 }, { "AGill Sans MT Ext Condensed Bold", 1.4 }, { "RGill Sans MT Ext Condensed Bold", 1.1 }, { "AJokerman", 0.9 }, { "RKlotz", 0.943 }, { "AModern No. 20|.1|.08", 1.27 }, { "RModern No. 20", 0.7 }, { "ANiagara Solid", 1.6 }, { "RNiagara Solid", 1.35 }, { "AOld English Text MT|.1|.075", 1.2 }, { "ROstrich Sans Heavy", 1.15 }, { "AOnyx", 1.5 }, { "ROnyx", 1.136 }, { "AP22 Johnston Underground|.08|.05", 1.5 }, { "RP22 Johnston Underground", 0.9 }, { "AParchment", 2.75 }, { "APoor Richard", 1.184 }, { "RPoor Richard", 0.85 }, { "AProxima Nova ExCn Th|.06|.05", 1.6 }, { "RProxima Nova ExCn Th", 1.2 }, { "AStencil|.11|.09", 1.0 }, { "RStencil", 0.8 }, { "AVladimir Script|.08|.06", 1.25 }, { "RBauhaus 93", 0.9 } }; var indexes = new Dictionary<string, int>(); var arabicIx = 0; var romanIx = 0; foreach (var key in numberData.Keys) if (key.StartsWith("A")) indexes[key] = arabicIx++; else indexes[key] = romanIx++; numberData.ParallelForEach(1, kvp => { if (oldNumberData != null && oldNumberData.ContainsKey(kvp.Key) && kvp.Value == oldNumberData[kvp.Key]) return; var arabic = kvp.Key.StartsWith("A"); var fontFamily = kvp.Key.Substring(1); double[] spacing = null; var pieces = fontFamily.Split('|'); if (pieces.Length == 3) { fontFamily = pieces[0]; spacing = pieces.Skip(1).Select(double.Parse).ToArray(); } var factor = kvp.Value; var objName = $"{(arabic ? "Arabic" : "Roman")}{indexes[kvp.Key]}"; File.WriteAllText($@"D:\c\KTANE\TheClock\Assets\Models\{objName}.obj", GenerateObjFile(Numbers(fontFamily, arabic, factor, spacing), objName)); lock (indexes) Console.WriteLine($"{fontFamily} {(arabic ? "Arabic" : "Roman")} done"); }); ClassifyJson.SerializeToFile(numberData, @"D:\temp\TheClockNumberData.json"); }
public static void RenderFriendshipSymbols() { var ponyColors = ClassifyJson.DeserializeFile <Dictionary <string, string> >(_poniesJson); var filesButNoPonyColor = new DirectoryInfo(_poniesDir).EnumerateFiles("*.png").Where(f => !ponyColors.ContainsKey(Path.GetFileNameWithoutExtension(f.Name))).ToArray(); if (filesButNoPonyColor.Length > 0) { Console.WriteLine("Files but no pony color:"); foreach (var file in filesButNoPonyColor) { Console.WriteLine(Path.GetFileNameWithoutExtension(file.Name)); } Console.WriteLine(); } //ClassifyJson.SerializeToFile(ponyColors, _poniesJson); ponyColors.Where(kvp => File.Exists(Path.Combine(_poniesDir, $"{kvp.Key}.png"))).ParallelForEach(4, kvp => { var pony = kvp.Key; var newFilename = $"{kvp.Key}.png"; lock (ponyColors) Console.WriteLine("Starting " + newFilename); var color = Color.FromArgb(Convert.ToInt32(kvp.Value.Substring(0, 2), 16), Convert.ToInt32(kvp.Value.Substring(2, 2), 16), Convert.ToInt32(kvp.Value.Substring(4, 2), 16)); var newCutieMark = GraphicsUtil.MakeSemitransparentImage(200, 200, g => { g.SetHighQuality(); }, g => { g.Clear(color); using (var bmp = new Bitmap(Path.Combine(_poniesDir, $"{pony}.png"))) { var width = bmp.Width; var height = bmp.Height; var pts = new List <PointD>(); unsafe { var bits = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); for (int y = 0; y < height; y++) { byte *readFrom = (byte *)bits.Scan0 + y * bits.Stride; for (int x = 0; x < width; x++) { if (readFrom[4 * x + 3] != 0) { pts.Add(new PointD(x, y)); } } } bmp.UnlockBits(bits); } var circum = CircleD.GetCircumscribedCircle(pts); using (var tr = new GraphicsTransformer(g).Translate(-circum.Center.X, -circum.Center.Y).Scale(90 / circum.Radius, 90 / circum.Radius).Translate(100, 100)) { g.DrawImage(bmp, 0, 0); //g.DrawEllipse(Pens.Black, circum.ToRectangle().ToRectangleF()); } } }, g => { g.Clear(Color.Transparent); g.FillEllipse(Brushes.Black, 1, 1, 197, 197); }); //* var tmp = $@"D:\c\KTANE\Public\HTML\img\Friendship\tmp_{newFilename}"; var final = $@"D:\c\KTANE\Public\HTML\img\Friendship\{newFilename}"; newCutieMark.Save(tmp, ImageFormat.Png); CommandRunner.Run("pngcr", tmp, final).OutputNothing().Go(); File.Delete(tmp); /*/ * var final = $@"D:\c\KTANE\Friendship\Manual\img\Friendship\{newFilename}"; * newCutieMark.Save(final, ImageFormat.Png); * /**/ lock (ponyColors) Console.WriteLine("Saved " + newFilename); }); }