Esempio n. 1
0
        public static JsonValue GenerateGraph()
        {
            var nodes = Ut.NewArray(1 << _numSwitches, ix => new Node {
                SwitchStates = ix
                });
            var edges = new List <Edge>();

            foreach (var node in nodes)
            {
                foreach (var node2 in nodes)
                {
                    if (node2 != node && isPowerOf2(node.SwitchStates ^ node2.SwitchStates))
                    {
                        for (int c = 0; c < _numColors; c++)
                        {
                            edges.Add(new Edge(node, node2, c));
                        }
                    }
                }
            }

            // Remove as many edges as possible without compromising reachability
            edges.Shuffle();
            var reducedEdges = Ut.ReduceRequiredSet(edges, skipConsistencyTest: true, test: state => allNodesReachable(nodes, state.SetToTest));

            return(ClassifyJson.Serialize(reducedEdges.ToList()));
        }
Esempio n. 2
0
        private static TranslationInfo makeDefault()
        {
            var ti = new TranslationInfo();

            ti.Json = ClassifyJson.Serialize(ti).ToString();
            return(ti);
        }
Esempio n. 3
0
        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");
                }
            }));
        }
Esempio n. 4
0
        private void saveCore()
        {
            _file.HexagonySource = _file.Grid.ToString();
            File.WriteAllText(_currentFilePath, ClassifyJson.Serialize(_file).ToStringIndented());
            File.WriteAllText(sourceFilePath(), _file.HexagonySource);

            // _lastFileTime = File.GetLastWriteTimeUtc(_currentFilePath);
            _anyChanges = false;
        }
Esempio n. 5
0
        private void ensureModuleInfoCache()
        {
            if (_moduleInfoCache == null)
            {
                lock (this)
                    if (_moduleInfoCache == null)
                    {
                        const int cols = 20; // number of icons per row
                        const int w    = 32; // width of an icon in pixels
                        const int h    = 32; // height of an icon in pixels

                        var iconFiles = new DirectoryInfo(_config.ModIconDir).EnumerateFiles("*.png", SearchOption.TopDirectoryOnly).OrderBy(file => file.Name != "blank.png").ToArray();
                        var rows      = (iconFiles.Length + cols - 1) / cols;
                        var coords    = new Dictionary <string, (int x, int y)>();

                        using (var bmp = new Bitmap(w * cols, h * rows))
                        {
                            using (var g = Graphics.FromImage(bmp))
                            {
                                for (int i = 0; i < iconFiles.Length; i++)
                                {
                                    using (var icon = new Bitmap(iconFiles[i].FullName))
                                        g.DrawImage(icon, w * (i % cols), h * (i / cols));
                                    coords.Add(Path.GetFileNameWithoutExtension(iconFiles[i].Name), (i % cols, i / cols));
                                }
                            }
                            using (var mem = new MemoryStream())
                            {
                                bmp.Save(mem, ImageFormat.Png);
                                _moduleInfoCache = new ModuleInfoCache {
                                    IconSpritePng = mem.ToArray()
                                };
                                _moduleInfoCache.IconSpriteMd5 = MD5.Create().ComputeHash(_moduleInfoCache.IconSpritePng).ToHex();

                                var modules = new DirectoryInfo(_config.ModJsonDir)
                                              .EnumerateFiles("*.json", SearchOption.TopDirectoryOnly)
                                              .ParallelSelect(4, file =>
                                {
                                    try
                                    {
                                        var origFile = File.ReadAllText(file.FullName);
                                        var modJson  = JsonDict.Parse(origFile);
                                        var mod      = ClassifyJson.Deserialize <KtaneModuleInfo>(modJson);

#if DEBUG
                                        var newJson    = (JsonDict)ClassifyJson.Serialize(mod);
                                        var newJsonStr = newJson.ToStringIndented();
                                        if (newJsonStr != origFile)
                                        {
                                            File.WriteAllText(file.FullName, newJsonStr);
                                        }
                                        modJson = newJson;
#endif

                                        return((modJson, mod, file.LastWriteTimeUtc).Nullable());
                                    }
Esempio n. 6
0
            private object translate(Type targetType, JsonValue value)
            {
                var remoteId = value.Safe[":remoteid"].GetIntSafe();

                if (remoteId != null)
                {
                    return(new proxy(targetType, _url, remoteId.Value).GetTransparentProxy());
                }
                return(ClassifyJson.Deserialize(targetType, value));
            }
Esempio n. 7
0
        public override void Init(LoggerBase log)
        {
            var original = File.ReadAllText(Settings.ConfigFile);

            _config = ClassifyJson.Deserialize <KtaneWebConfig>(JsonValue.Parse(original));
            var rewrite = serializeConfig();

            if (rewrite != original)
            {
                File.WriteAllText(Settings.ConfigFile, rewrite);
            }
            base.Init(log);
            _logger = log;
        }
Esempio n. 8
0
 private void openCore(string filePath)
 {
     if (!File.Exists(filePath))
     {
         DlgMessage.Show("The specified file does not exist.", "Error", DlgType.Error);
         return;
     }
     _currentFilePath = filePath;
     _file            = ClassifyJson.Deserialize <HCFile>(JsonValue.Parse(File.ReadAllText(_currentFilePath)));
     _anyChanges      = false;
     // _lastFileTime = File.GetLastWriteTimeUtc(_currentFilePath);
     updateList();
     rerender();
 }
Esempio n. 9
0
        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);
        }
Esempio n. 10
0
            public override IMessage Invoke(IMessage rawMsg)
            {
                var msg    = (IMethodCallMessage)rawMsg;
                var method = msg.MethodBase as MethodInfo;
                var args   = msg.Args;

                if (method == null || args == null)
                {
                    throw new InternalErrorException("The transparent proxy received an invalid message.");
                }

                var parameters = method.GetParameters();

                var hArgs = new List <HArg> {
                    new HArg("Method", mangledMethodName(method)),
                    new HArg("Arguments", new JsonList(args.Select((arg, i) =>
                                                                   parameters[i].IsOut ? null :
                                                                   arg is Delegate ? new JsonDict {
                        { ":delegate", true }
                    } :
                                                                   ClassifyJson.Serialize(parameters[i].ParameterType, arg))))
                };

                if (_objectId != -1)
                {
                    hArgs.Add(new HArg("ObjectID", _objectId));
                }
                var responseRaw = _client.Post(_url, hArgs.ToArray());
                var response    = ClassifyJson.Deserialize <CommunicatorResult>(responseRaw.DataJson);

                var responseRet = response as CommunicatorResultReturn;

                if (responseRet != null)
                {
                    var refOut = Enumerable.Range(0, parameters.Length)
                                 .Where(i => parameters[i].ParameterType.IsByRef)
                                 .Select(i => translate(parameters[i].ParameterType.GetElementType(), responseRet.RefOutArguments[i]))
                                 .ToArray();
                    return(new ReturnMessage(
                               translate(method.ReturnType, responseRet.ReturnValue),
                               refOut,
                               refOut.Length,
                               msg.LogicalCallContext,
                               msg));
                }

                throw new NotImplementedException();
            }
Esempio n. 11
0
 void IPropellerModule.Init(LoggerBase log, JsonValue settings, ISettingsSaver saver)
 {
     SettingsSaver = saver;
     Log           = log;
     try
     {
         Settings = ClassifyJson.Deserialize <TSettings>(settings) ?? new TSettings();
     }
     catch (Exception e)
     {
         Log.Exception(e);
         Settings = new TSettings();
     }
     SaveSettings();
     Init();
 }
Esempio n. 12
0
        public static void DoGraph()
        {
            const string name = "Candidate 1";
            //*
            var graphJson = GenerateGraph();

            File.WriteAllText($@"D:\temp\Colored Switches\{name}.json", graphJson.ToStringIndented());

            /*/
             * var graphJson = JsonValue.Parse(File.ReadAllText($@"D:\temp\Colored Switches\{name}.json"));
             * /**/

            var edges     = ClassifyJson.Deserialize <List <Edge> >(graphJson);
            var nodes     = edges.Select(e => e.To).Distinct().ToArray();
            var edgesFrom = nodes.ToDictionary(node => node, node => new List <Edge>());

            foreach (var node in nodes)
            {
                edgesFrom[node] = edges.Where(e => e.From == node).ToList();
            }

            var covered = new bool[_numSwitches];

            foreach (var edge in edges)
            {
                var b   = edge.From.SwitchStates ^ edge.To.SwitchStates;
                var bit = 0;
                while (b > 1)
                {
                    bit++;
                    b >>= 1;
                }
                if (covered[bit])
                {
                    continue;
                }
                if (Enumerable.Range(0, _numColors).All(c => edges.Any(e => e.Color == c && e.From == edge.From && e.To == edge.To)))
                {
                    continue;
                }
                covered[bit] = true;
            }
            Console.WriteLine(covered.JoinString(", "));

            Console.WriteLine(nodes.Select(n => $"{n.SwitchStates}={edgesFrom[n].Select(e => $"{e.Color}>{e.To.SwitchStates}").JoinString("|")}").JoinString("\n"));
            //JsonGraphToGraphML(graphJson, name);
        }
Esempio n. 13
0
        /// <summary>
        ///     Constructs a new instance of <see cref="AjaxHandler{TApi}"/>.</summary>
        /// <param name="options">
        ///     Specifies <see cref="AjaxHandler{TApi}"/>’s exception behaviour.</param>
        public AjaxHandler(AjaxHandlerOptions options = AjaxHandlerOptions.ReturnExceptionsWithoutMessages)
        {
            _apiFunctions = new Dictionary <string, Func <HttpRequest, TApi, JsonValue> >();
            _options      = options;

            var typeContainingAjaxMethods = typeof(TApi);

            foreach (var method in typeContainingAjaxMethods.GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(m => m.IsDefined <AjaxMethodAttribute>()))
            {
                var parameters = method.GetParameters();
                var returnType = method.ReturnType;

                _apiFunctions.Add(method.Name, (req, api) =>
                {
                    JsonDict json;
                    var rawJson = req.Post["data"].Value;
                    try { json = JsonDict.Parse(rawJson); }
                    catch (Exception e) { throw new AjaxInvalidParameterDataException(rawJson, e); }
                    var arr = new object[parameters.Length];
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        var paramName = parameters[i].Name;
                        if (parameters[i].IsOptional && !json.ContainsKey(paramName))
                        {
                            arr[i] = parameters[i].DefaultValue;
                        }
                        else
                        {
                            try { arr[i] = ClassifyJson.Deserialize(parameters[i].ParameterType, json[paramName]); }
                            catch (Exception e) { throw new AjaxInvalidParameterException(paramName, e); }
                        }
                    }

                    object result;
                    try { result = method.Invoke(api, arr); }
                    catch (Exception e) { throw new AjaxException("Error invoking the AJAX method.", e); }

                    if (result is JsonValue)
                    {
                        return((JsonValue)result);
                    }

                    try { return(ClassifyJson.Serialize(returnType, result)); }
                    catch (Exception e) { throw new AjaxInvalidReturnValueException(result, returnType, e); }
                });
            }
        }
Esempio n. 14
0
        // This method is called in Init() (when the server is initialized) and in pull() (when the repo is updated due to a new git commit).
        private void generateTranslationCache()
        {
            var path = Path.Combine(_config.BaseDir, "Translations");

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

#if DEBUG
            ClassifyJson.SerializeToFile(TranslationInfo.Default, Path.Combine(path, "en.json"));
#endif

            _translationCache = new DirectoryInfo(path)
                                .EnumerateFiles("*.json", SearchOption.TopDirectoryOnly)
                                .ParallelSelect(Environment.ProcessorCount, file =>
            {
                try
                {
                    var translationJson  = File.ReadAllText(file.FullName);
                    var translation      = ClassifyJson.Deserialize <TranslationInfo>(JsonDict.Parse(translationJson));
                    translation.langCode = file.Name.Remove(file.Name.Length - 5);
                    var newJson          = ClassifyJson.Serialize(translation);
                    translation.Json     = newJson.ToString();

#if DEBUG
                    var newJsonIndented = newJson.ToStringIndented();
                    if (translationJson != newJsonIndented)
                    {
                        File.WriteAllText(file.FullName, newJsonIndented);
                    }
#endif

                    return(translation);
                }
                catch (Exception e)
                {
#if DEBUG
                    Console.WriteLine(e.Message);
                    Console.WriteLine(e.GetType().FullName);
                    Console.WriteLine(e.StackTrace);
#endif
                    Log.Exception(e);
                    return(null);
                }
            }).ToDictionary(t => t.langCode, t => t);
        }
Esempio n. 15
0
        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);
        }
Esempio n. 16
0
        internal static void serialize(object settings, Type settingsType, string filename, SettingsSerializer serializer)
        {
            var tempname = filename + ".~tmp";

            Ut.WaitSharingVio(() =>
            {
                switch (serializer)
                {
                case SettingsSerializer.ClassifyXml:
                    // SerializeToFile automatically creates the folder if necessary
                    ClassifyXml.SerializeToFile(settingsType, settings, tempname, format: ClassifyXmlFormat.Create("Settings"));
                    break;

                case SettingsSerializer.ClassifyJson:
                    // SerializeToFile automatically creates the folder if necessary
                    ClassifyJson.SerializeToFile(settingsType, settings, tempname);
                    break;

                case SettingsSerializer.ClassifyBinary:
                    // SerializeToFile automatically creates the folder if necessary
                    ClassifyBinary.SerializeToFile(settingsType, settings, tempname);
                    break;

                case SettingsSerializer.DotNetBinary:
                    PathUtil.CreatePathToFile(tempname);
                    var bf = new BinaryFormatter();
                    using (var fs = File.Open(tempname, FileMode.Create, FileAccess.Write, FileShare.Read))
                        bf.Serialize(fs, settings);
                    break;

                default:
                    throw new InternalErrorException("4968453");
                }
                File.Delete(filename);
                File.Move(tempname, filename);
            }, TimeSpan.FromSeconds(5));
        }
Esempio n. 17
0
        private ModuleInfoCache getModuleInfoCache()
        {
            ModuleInfoCache mic = null;

            do
            {
                if (_moduleInfoCache == null)
                {
                    lock (this)
                        if (_moduleInfoCache == null)
                        {
                            const int cols = 20; // number of icons per row
                            const int w    = 32; // width of an icon in pixels
                            const int h    = 32; // height of an icon in pixels

                            var iconFiles = new DirectoryInfo(Path.Combine(_config.BaseDir, "Icons")).EnumerateFiles("*.png", SearchOption.TopDirectoryOnly).OrderBy(file => file.Name != "blank.png").ToArray();
                            var rows      = (iconFiles.Length + cols - 1) / cols;
                            var coords    = new Dictionary <string, (int x, int y)>();

                            using var bmp = new Bitmap(w * cols, h * rows);
                            using (var g = Graphics.FromImage(bmp))
                            {
                                for (int i = 0; i < iconFiles.Length; i++)
                                {
                                    using (var icon = new Bitmap(iconFiles[i].FullName))
                                        g.DrawImage(icon, w * (i % cols), h * (i / cols));
                                    coords.Add(Path.GetFileNameWithoutExtension(iconFiles[i].Name), (i % cols, i / cols));
                                }
                            }
                            using var mem = new MemoryStream();
                            bmp.Save(mem, ImageFormat.Png);

                            // This needs to be a separate variable (don’t use _moduleInfoCache itself) because that field needs to stay null until it is fully initialized
                            var moduleInfoCache = new ModuleInfoCache {
                                IconSpritePng = mem.ToArray()
                            };
                            moduleInfoCache.IconSpriteMd5 = MD5.Create().ComputeHash(moduleInfoCache.IconSpritePng).ToHex();

                            // Load TP data from the spreadsheet
                            JsonList entries;
                            try
                            {
                                entries = new HClient().Get("https://spreadsheets.google.com/feeds/list/1G6hZW0RibjW7n72AkXZgDTHZ-LKj0usRkbAwxSPhcqA/1/public/values?alt=json").DataJson["feed"]["entry"].GetList();
                            }
                            catch (Exception e)
                            {
                                Log.Exception(e);
                                entries = new JsonList();
                            }

                            var moduleLoadExceptions = new JsonList();
                            var modules = new DirectoryInfo(Path.Combine(_config.BaseDir, "JSON"))
                                          .EnumerateFiles("*.json", SearchOption.TopDirectoryOnly)
                                          .ParallelSelect(Environment.ProcessorCount, file =>
                            {
                                try
                                {
                                    var origFile = File.ReadAllText(file.FullName);
                                    var modJson  = JsonDict.Parse(origFile);
                                    var mod      = ClassifyJson.Deserialize <KtaneModuleInfo>(modJson);

#if DEBUG
                                    var newJson    = (JsonDict)ClassifyJson.Serialize(mod);
                                    var newJsonStr = newJson.ToStringIndented();
                                    if (newJsonStr != origFile)
                                    {
                                        File.WriteAllText(file.FullName, newJsonStr);
                                    }
                                    modJson = newJson;
Esempio n. 18
0
        private HttpResponse generateJson(HttpRequest req)
        {
            if (req.Method != HttpMethod.Post)
            {
                return(HttpResponse.PlainText("Only POST requests allowed.", HttpStatusCode._405_MethodNotAllowed));
            }

            void populateObject(object obj, Type type)
            {
                foreach (var f in type.GetFields())
                {
                    var attr = f.GetCustomAttribute <EditableFieldAttribute>();
                    if (attr == null)
                    {
                        continue;
                    }

                    var fType = f.FieldType;
                    if (f.FieldType.TryGetGenericParameters(typeof(Nullable <>), out var fTypes))
                    {
                        fType = fTypes[0];
                    }

                    var val = req.Post[f.Name].Value;
                    try
                    {
                        if (f.GetCustomAttribute <EditableNestedAttribute>() != null)
                        {
                            if (val != "on")
                            {
                                f.SetValue(obj, null);
                            }
                            else
                            {
                                var nestedObj = Activator.CreateInstance(f.FieldType);
                                populateObject(nestedObj, f.FieldType);
                                f.SetValue(obj, nestedObj);
                            }
                            continue;
                        }

                        if (fType == typeof(string))
                        {
                            f.SetValue(obj, string.IsNullOrWhiteSpace(val) ? null : val.Trim());
                        }
                        else if (fType.IsEnum)
                        {
                            var enumVal = val == null ? null : Enum.Parse(fType, val);
                            if (enumVal != null)
                            {
                                f.SetValue(obj, enumVal);
                            }
                        }
                        else if (fType == typeof(DateTime))
                        {
                            f.SetValue(obj, DateTime.ParseExact(val, "yyyy-MM-dd", null));
                        }
                        else if (fType == typeof(string[]))
                        {
                            f.SetValue(obj, val.Split(';').Select(str => str.Trim()).ToArray());
                        }
                        else if (fType == typeof(int))
                        {
                            f.SetValue(obj, string.IsNullOrWhiteSpace(val) ? 0 : int.Parse(val));
                        }
                        else if (fType == typeof(decimal))
                        {
                            f.SetValue(obj, string.IsNullOrWhiteSpace(val) ? 0m : decimal.Parse(val));
                        }
                        else if (fType == typeof(bool))
                        {
                            f.SetValue(obj, val == "on");
                        }
                        else
                        {
                            throw new InvalidOperationException($"Unrecognized field type: {fType.FullName}");
                        }
                    }
                    catch (Exception e)
                    {
                        _logger.Warn($"Generate JSON: unrecognized value. Field: {f.Name}, Type: {fType}, Value: “{val ?? "<null>"}”, Exception: {e.Message} ({e.GetType().FullName})");
                    }
                }
            }

            var m = new KtaneModuleInfo();

            populateObject(m, typeof(KtaneModuleInfo));
            var json = ClassifyJson.Serialize(m);
            // Now deserialize and then re-serialize this to force KtaneModuleInfo to perform some sanity things
            var m2 = ClassifyJson.Deserialize <KtaneModuleInfo>(json);

            return(HttpResponse.PlainText(ClassifyJson.Serialize(m2).ToStringIndented()));
        }
Esempio n. 19
0
        public bool IsSolved(string json)
        {
            var state        = JsonValue.Parse(json);
            var kyudokuGrids = KyudokuGrids.Split(36).Select(grid => grid.Select(ch => ch - '0').ToArray()).ToArray();
            var constraints  = Constraints == null ? new SvgConstraint[0] : ClassifyJson.Deserialize <SvgConstraint[]>(JsonValue.Parse(Constraints));

            // Check that all cells in the Sudoku grid have a digit
            var sudokuDigits = new int[81];

            for (int cell = 0; cell < 81; cell++)
            {
                var kyCells = Enumerable.Range(0, 4)
                              .Where(c => cell % 9 >= 3 * (c % 2) && cell % 9 < 6 + 3 * (c % 2) && cell / 9 >= 3 * (c / 2) && cell / 9 < 6 + 3 * (c / 2))
                              .Select(c => (corner: c, kyCell: cell % 9 - 3 * (c % 2) + 6 * ((cell / 9) - 3 * (c / 2))))
                              .Where(inf => state["circledDigits"][inf.corner][inf.kyCell].Apply(v => v != null && v.GetBool()))
                              .ToArray();
                if (kyCells.Length > 1 && kyCells.Any(inf => kyudokuGrids[inf.corner][inf.kyCell] != kyudokuGrids[kyCells[0].corner][kyCells[0].kyCell]))
                {
                    return(false);
                }
                else if (kyCells.Length >= 1)
                {
                    sudokuDigits[cell] = kyudokuGrids[kyCells[0].corner][kyCells[0].kyCell];
                }
                else if (state["enteredDigits"][cell] != null)
                {
                    sudokuDigits[cell] = state["enteredDigits"][cell].GetInt();
                }
                else
                {
                    return(false);
                }
            }

            // Check the Sudoku rules (rows, columns and regions)
            for (var i = 0; i < 9; i++)
            {
                for (var colA = 0; colA < 9; colA++)
                {
                    for (var colB = colA + 1; colB < 9; colB++)
                    {
                        if (sudokuDigits[colA + 9 * i] == sudokuDigits[colB + 9 * i])
                        {
                            return(false);
                        }
                    }
                }
                for (var rowA = 0; rowA < 9; rowA++)
                {
                    for (var rowB = rowA + 1; rowB < 9; rowB++)
                    {
                        if (sudokuDigits[i + 9 * rowA] == sudokuDigits[i + 9 * rowB])
                        {
                            return(false);
                        }
                    }
                }
                for (var cellA = 0; cellA < 9; cellA++)
                {
                    for (var cellB = cellA + 1; cellB < 9; cellB++)
                    {
                        if (sudokuDigits[cellA % 3 + 3 * (i % 3) + 9 * ((cellA / 3) + 3 * (i / 3))] == sudokuDigits[cellB % 3 + 3 * (i % 3) + 9 * ((cellB / 3) + 3 * (i / 3))])
                        {
                            return(false);
                        }
                    }
                }
            }

            // Check the Sudoku constraints
            foreach (var constr in constraints)
            {
                if (!constr.Verify(sudokuDigits))
                {
                    return(false);
                }
            }

            // Check all of the Kyudokus
            for (var corner = 0; corner < 4; corner++)
            {
                var digitCounts = new int[9];
                var rowSums     = new int[6];
                var colSums     = new int[6];
                for (var cell = 0; cell < 36; cell++)
                {
                    if (state["circledDigits"][corner][cell].Apply(v => v != null && v.GetBool()))
                    {
                        digitCounts[kyudokuGrids[corner][cell] - 1]++;
                        rowSums[cell / 6] += kyudokuGrids[corner][cell];
                        colSums[cell % 6] += kyudokuGrids[corner][cell];
                    }
                }
                if (rowSums.Any(r => r > 9) || colSums.Any(c => c > 9) || digitCounts.Any(c => c != 1))
                {
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 20
0
        public override void Init(LoggerBase log)
        {
#if DEBUG
            if (string.IsNullOrWhiteSpace(Settings.ConfigFile))
            {
                var config = new KtaneWebConfig();
                Console.WriteLine();
                ConsoleUtil.WriteLine("It appears that you are running KtaneWeb for the first time.".Color(ConsoleColor.White));
tryAgain1:
                ConsoleUtil.WriteLine(@"Please provide a location for the JSON settings file (for example: {0/DarkCyan}):".Color(ConsoleColor.Gray).Fmt(@"C:\Path\KtaneWeb.settings.json"));
                var path = Console.ReadLine();
                try
                {
                    ClassifyJson.SerializeToFile(config, path);
                }
                catch (Exception e)
                {
                    ConsoleUtil.WriteLine($"{"Problem:".Color(ConsoleColor.Magenta)} {e.Message.Color(ConsoleColor.Red)} {$"({e.GetType().FullName})".Color(ConsoleColor.DarkRed)}", null);
                    goto tryAgain1;
                }

                Console.WriteLine();
tryAgain2:
                ConsoleUtil.WriteLine("Do you already have a local clone of the KtaneContent repository that you want the website to use?".Color(ConsoleColor.White));
                Console.WriteLine("If yes, please type the full path to that repository. If no, just press Enter.");
                var ktaneContent       = Console.ReadLine();
                var expectedSubfolders = "HTML,More,JSON,Icons".Split(',');
                if (string.IsNullOrWhiteSpace(ktaneContent))
                {
                    ConsoleUtil.WriteLine(@"In that case we will create a new clone. I can do that automatically if you have git installed (if you don’t, please abort now).".Color(ConsoleColor.White));
                    ConsoleUtil.WriteLine("This will take a long time as the repository is large.".Color(ConsoleColor.White));
                    Console.WriteLine();
tryAgain3:
                    ConsoleUtil.WriteLine("Please choose a path where you would like all the data stored (for example: {0/DarkCyan}):".Color(ConsoleColor.Gray).Fmt(@"C:\Path\KtaneContent"));
                    var cloneFolder = Console.ReadLine();
                    try
                    {
                        Directory.CreateDirectory(cloneFolder);
                    }
                    catch (Exception e)
                    {
                        ConsoleUtil.WriteLine($"{"Problem:".Color(ConsoleColor.Magenta)} {e.Message.Color(ConsoleColor.Red)} {$"({e.GetType().FullName})".Color(ConsoleColor.DarkRed)}", null);
                        goto tryAgain3;
                    }
                    try
                    {
                        config.BaseDir = Path.Combine(cloneFolder, "Public");
                        CommandRunner.Run("git", "clone", "https://github.com/Timwi/KtaneContent.git", config.BaseDir).Go();
                        config.MergedPdfsDir = Path.Combine(cloneFolder, "MergedPdfs");
                        Directory.CreateDirectory(config.MergedPdfsDir);
                        config.LogfilesDir = Path.Combine(cloneFolder, "Logfiles");
                        Directory.CreateDirectory(config.LogfilesDir);
                    }
                    catch (Exception e)
                    {
                        ConsoleUtil.WriteLine($"{"Problem:".Color(ConsoleColor.Magenta)} {e.Message.Color(ConsoleColor.Red)} {$"({e.GetType().FullName})".Color(ConsoleColor.DarkRed)}", null);
                        goto tryAgain2;
                    }
                }
                else if (expectedSubfolders.Any(s => !Directory.Exists(Path.Combine(ktaneContent, s))))
                {
                    ConsoleUtil.WriteLine($"{"Problem:".Color(ConsoleColor.Magenta)} {"That folder does not appear to contain KtaneContent.".Color(ConsoleColor.Red)}", null);
                    ConsoleUtil.WriteLine("(We’re looking for a folder that contains subfolders named: {0/DarkMagenta})".Color(ConsoleColor.Magenta).Fmt(expectedSubfolders.JoinString(", ")));
                    goto tryAgain2;
                }
                else
                {
                    var p = ktaneContent;
                    while (p.EndsWith("\""))
                    {
                        p = Path.GetDirectoryName(p);
                    }
                    config.BaseDir = p;
                    p = Path.GetDirectoryName(p);

                    Console.WriteLine();
tryAgain4:
                    var logfiles = Path.Combine(p, "Logfiles");
                    ConsoleUtil.WriteLine("Please choose a path where you would like KtaneWeb to store logfiles uploaded through the Logfile Analyzer, or just press Enter to use the default ({0/DarkCyan}):".Color(ConsoleColor.Gray).Fmt(logfiles));
                    config.LogfilesDir = Console.ReadLine();
                    if (string.IsNullOrWhiteSpace(config.LogfilesDir))
                    {
                        ConsoleUtil.WriteLine("Using default: {0/DarkCyan}".Color(ConsoleColor.Gray).Fmt(logfiles));
                        config.LogfilesDir = logfiles;
                    }
                    try
                    {
                        Directory.CreateDirectory(config.LogfilesDir);
                    }
                    catch (Exception e)
                    {
                        ConsoleUtil.WriteLine($"{"Problem:".Color(ConsoleColor.Magenta)} {e.Message.Color(ConsoleColor.Red)} {$"({e.GetType().FullName})".Color(ConsoleColor.DarkRed)}", null);
                        goto tryAgain4;
                    }

                    Console.WriteLine();
tryAgain5:
                    var mergedPdfs = Path.Combine(p, "MergedPdfs");
                    ConsoleUtil.WriteLine("Please choose a path where you would like KtaneWeb to store merged PDFs, or just press Enter to use the default ({0/DarkCyan}):".Color(ConsoleColor.Gray).Fmt(mergedPdfs));

                    config.MergedPdfsDir = Console.ReadLine();
                    if (string.IsNullOrWhiteSpace(config.MergedPdfsDir))
                    {
                        ConsoleUtil.WriteLine("Using default: {0/DarkCyan}".Color(ConsoleColor.Gray).Fmt(mergedPdfs));
                        config.MergedPdfsDir = mergedPdfs;
                    }
                    try
                    {
                        Directory.CreateDirectory(config.MergedPdfsDir);
                    }
                    catch (Exception e)
                    {
                        ConsoleUtil.WriteLine($"{"Problem:".Color(ConsoleColor.Magenta)} {e.Message.Color(ConsoleColor.Red)} {$"({e.GetType().FullName})".Color(ConsoleColor.DarkRed)}", null);
                        goto tryAgain5;
                    }

                    var appPath = PathUtil.AppPathCombine(@"..\..");
                    config.JavaScriptFile = Path.Combine(appPath, @"Src\Resources\KtaneWeb.js");
                    config.CssFile        = Path.Combine(appPath, @"Src\Resources\KtaneWeb.css");
                    if (!File.Exists(config.JavaScriptFile) || !File.Exists(config.CssFile))
                    {
                        Console.WriteLine();
tryAgain6:
                        ConsoleUtil.WriteLine("Finally, please let me know where you placed the KtaneWeb source code (what you’re running right now):".Color(ConsoleColor.Gray));
                        appPath = Console.ReadLine();
                        config.JavaScriptFile = Path.Combine(appPath, @"Src\Resources\KtaneWeb.js");
                        config.CssFile        = Path.Combine(appPath, @"Src\Resources\KtaneWeb.css");
                        if (!File.Exists(config.JavaScriptFile) || !File.Exists(config.CssFile))
                        {
                            ConsoleUtil.WriteLine($"{"Problem:".Color(ConsoleColor.Magenta)} {"That does not look like the KtaneWeb source code folder.".Color(ConsoleColor.Red)}", null);
                            goto tryAgain6;
                        }
                    }
                }

                try
                {
                    ClassifyJson.SerializeToFile(config, path);
                    Settings.ConfigFile = path;
                    SaveSettings();
                }
                catch (Exception e)
                {
                    ConsoleUtil.WriteLine($"{"Problem:".Color(ConsoleColor.Magenta)} {e.Message.Color(ConsoleColor.Red)} {$"({e.GetType().FullName})".Color(ConsoleColor.DarkRed)}", null);
                    goto tryAgain1;
                }

                Console.WriteLine();
                ConsoleUtil.WriteLine("That should be all set up for you now!".Color(ConsoleColor.Green));
                ConsoleUtil.WriteLine("Feel free to browse the settings file we just created if you’re curious.".Color(ConsoleColor.DarkGreen));
                ConsoleUtil.WriteLine(@"For automatic PDF generation, we are assuming that Google Chrome is at its default location; if not, please change it manually in the JSON file.".Color(ConsoleColor.DarkGreen));
                Console.WriteLine();
                Console.WriteLine();
            }
#endif
            var original = File.ReadAllText(Settings.ConfigFile);
            _config = ClassifyJson.Deserialize <KtaneWebConfig>(JsonValue.Parse(original));
            var rewrite = serializeConfig();
            if (rewrite != original)
            {
                File.WriteAllText(Settings.ConfigFile, rewrite);
            }
            base.Init(log);
            _logger = log;
        }
Esempio n. 21
0
 private string serializeConfig()
 {
     return(ClassifyJson.Serialize(_config, new ClassifyOptions {
         SerializationEqualityComparer = new CustomEqualityComparer <object>(customComparison)
     }).ToStringIndented());
 }
Esempio n. 22
0
        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")))))));
        }
Esempio n. 23
0
        private void ensureModuleInfoCache()
        {
            if (_moduleInfoCache == null)
            {
                lock (this)
                    if (_moduleInfoCache == null)
                    {
                        const int cols = 20; // number of icons per row
                        const int w    = 32; // width of an icon in pixels
                        const int h    = 32; // height of an icon in pixels

                        var iconFiles = new DirectoryInfo(_config.ModIconDir).EnumerateFiles("*.png", SearchOption.TopDirectoryOnly).OrderBy(file => file.Name != "blank.png").ToArray();
                        var rows      = (iconFiles.Length + cols - 1) / cols;
                        var coords    = new Dictionary <string, (int x, int y)>();

                        using var bmp = new Bitmap(w * cols, h * rows);
                        using (var g = Graphics.FromImage(bmp))
                        {
                            for (int i = 0; i < iconFiles.Length; i++)
                            {
                                using (var icon = new Bitmap(iconFiles[i].FullName))
                                    g.DrawImage(icon, w * (i % cols), h * (i / cols));
                                coords.Add(Path.GetFileNameWithoutExtension(iconFiles[i].Name), (i % cols, i / cols));
                            }
                        }
                        using var mem = new MemoryStream();
                        bmp.Save(mem, ImageFormat.Png);
                        _moduleInfoCache = new ModuleInfoCache {
                            IconSpritePng = mem.ToArray()
                        };
                        _moduleInfoCache.IconSpriteMd5 = MD5.Create().ComputeHash(_moduleInfoCache.IconSpritePng).ToHex();

                        // Load TP data from the spreadsheet
                        JsonList entries;
                        try
                        {
                            entries = new HClient().Get("https://spreadsheets.google.com/feeds/list/1WEzVOKxOO5CDGoqAHjJKrC-c-ZGgsTPRLXBCs8RrAwU/1/public/values?alt=json").DataJson["feed"]["entry"].GetList();
                        }
                        catch (Exception e)
                        {
                            _logger.Exception(e);
                            entries = new JsonList();
                        }

                        var modules = new DirectoryInfo(_config.ModJsonDir)
                                      .EnumerateFiles("*.json", SearchOption.TopDirectoryOnly)
                                      .ParallelSelect(4, file =>
                        {
                            try
                            {
                                var origFile = File.ReadAllText(file.FullName);
                                var modJson  = JsonDict.Parse(origFile);
                                var mod      = ClassifyJson.Deserialize <KtaneModuleInfo>(modJson);

#if DEBUG
                                var newJson    = (JsonDict)ClassifyJson.Serialize(mod);
                                var newJsonStr = newJson.ToStringIndented();
                                if (newJsonStr != origFile)
                                {
                                    File.WriteAllText(file.FullName, newJsonStr);
                                }
                                modJson = newJson;
Esempio n. 24
0
        void IPropellerModule.Init(LoggerBase log, JsonValue settings, ISettingsSaver saver)
        {
            _log      = log;
            _saver    = saver;
            _settings = ClassifyJson.Deserialize <Settings>(settings) ?? new Settings();

            var validPaths = new List <string>();

            foreach (var path in _settings.Paths)
            {
                if (!Directory.Exists(path))
                {
                    _log.Warn(@"DocGen: Warning: The folder ""{0}"" specified in the settings does not exist. Ignoring path.".Fmt(path));
                }
                else
                {
                    validPaths.Add(path);
                }
            }
            _settings.Paths = validPaths.ToArray();

            saver.SaveSettings(ClassifyJson.Serialize(_settings));

            string copyToPath = null;

            if (_settings.DllTempPath != null)
            {
                // Try to clean up old folders we've created before
                var tempPath = _settings.DllTempPath;
                Directory.CreateDirectory(tempPath);
                foreach (var path in Directory.GetDirectories(tempPath, "docgen-tmp-*"))
                {
                    try { Directory.Delete(path, true); }
                    catch { }
                }

                // Find a new folder to put the DLL files into
                int j = 1;
                copyToPath = Path.Combine(tempPath, "docgen-tmp-" + j);
                while (Directory.Exists(copyToPath))
                {
                    j++;
                    copyToPath = Path.Combine(tempPath, "docgen-tmp-" + j);
                }
                Directory.CreateDirectory(copyToPath);
            }

            _docGen = new DocumentationGenerator(_settings.Paths, _settings.RequireAuthentication ? _settings.UsernamePasswordFile ?? "" : null, copyToPath);
            lock (_log)
            {
                _log.Info("DocGen initialised with {0} assemblies: {1}".Fmt(_docGen.AssembliesLoaded.Count, _docGen.AssembliesLoaded.JoinString(", ")));
                if (_docGen.AssemblyLoadErrors.Count > 0)
                {
                    _log.Warn("{0} assembly load errors:".Fmt(_docGen.AssemblyLoadErrors.Count));
                    foreach (var tuple in _docGen.AssemblyLoadErrors)
                    {
                        _log.Warn("{0} error: {1}".Fmt(tuple.Item1, tuple.Item2));
                    }
                }
            }
        }
Esempio n. 25
0
        private HttpResponse generateJson(HttpRequest req)
        {
            if (req.Method != HttpMethod.Post)
            {
                return(HttpResponse.PlainText("Only POST requests allowed.", HttpStatusCode._405_MethodNotAllowed));
            }

            void populateObject(object obj, Type type)
            {
                foreach (var f in type.GetFields())
                {
                    var attr = f.GetCustomAttribute <EditableFieldAttribute>();
                    if (attr == null || attr.ReadableName == null)
                    {
                        continue;
                    }

                    var fType = f.FieldType;
                    if (f.FieldType.TryGetGenericParameters(typeof(Nullable <>), out var fTypes))
                    {
                        fType = fTypes[0];
                    }

                    var val = req.Post[f.Name].Value;
                    try
                    {
                        if (f.GetCustomAttribute <EditableNestedAttribute>() != null)
                        {
                            if (val != "on")
                            {
                                f.SetValue(obj, null);
                            }
                            else
                            {
                                var nestedObj = Activator.CreateInstance(f.FieldType);
                                populateObject(nestedObj, f.FieldType);
                                f.SetValue(obj, nestedObj);
                            }
                            continue;
                        }

                        if (fType == typeof(string))
                        {
                            f.SetValue(obj, string.IsNullOrWhiteSpace(val) ? null : val.Trim());
                        }
                        else if (fType.IsEnum && fType.GetCustomAttribute <FlagsAttribute>() != null)
                        {
                            var intVal = 0;
                            foreach (var value in Enum.GetValues(fType))
                            {
                                if (req.Post[$"{f.Name}-{value}"].Value != null)
                                {
                                    intVal |= (int)value;
                                }
                            }
                            f.SetValue(obj, intVal);
                        }
                        else if (fType.IsEnum)
                        {
                            var enumVal = val == null ? null : Enum.Parse(fType, val);
                            if (enumVal != null)
                            {
                                f.SetValue(obj, enumVal);
                            }
                        }
                        else if (fType == typeof(DateTime))
                        {
                            f.SetValue(obj, DateTime.ParseExact(val, "yyyy-MM-dd", null));
                        }
                        else if (fType == typeof(string[]))
                        {
                            f.SetValue(obj, val.Split(attr.AllowedSeparators).Select(str => str.Trim()).ToArray().Apply(list => list.Length == 0 || (list.Length == 1 && string.IsNullOrWhiteSpace(list[0])) ? null : list));
                        }
                        else if (fType == typeof(Dictionary <string, string>))
                        {
                            if (val.Trim() == "")
                            {
                                continue;
                            }
                            else if (!attr.AllowedDictSeparators.Any(sep => val.Contains(sep)))
                            {
                                f.SetValue(obj, new Dictionary <string, string>()
                                {
                                    { attr.DefaultKey, string.IsNullOrWhiteSpace(val) ? null : val.Trim() }
                                });
                            }
                            else
                            {
                                f.SetValue(obj, val.Split(attr.AllowedSeparators).Select(str => str.Split(attr.AllowedDictSeparators)).ToDictionary(x => x[0].Trim(), x => x[1].Trim()));
                            }
                        }
                        else if (fType == typeof(int))
                        {
                            f.SetValue(obj, string.IsNullOrWhiteSpace(val) ? 0 : int.Parse(val));
                        }
                        else if (fType == typeof(decimal))
                        {
                            f.SetValue(obj, string.IsNullOrWhiteSpace(val) ? 0m : decimal.Parse(val));
                        }
                        else if (fType == typeof(bool))
                        {
                            f.SetValue(obj, val == "on");
                        }
                        else if (fType == typeof(TutorialVideoInfo[]))
                        {
                            f.SetValue(obj, ClassifyJson.Deserialize <TutorialVideoInfo[]>(val));
                        }
                        else
                        {
                            throw new InvalidOperationException($"Unrecognized field type: {fType.FullName}");
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Warn($"Generate JSON: unrecognized value. Field: {f.Name}, Type: {fType}, Value: “{val ?? "<null>"}”, Exception: {e.Message} ({e.GetType().FullName})");
                    }
                }
            }

            var m = new KtaneModuleInfo();

            populateObject(m, typeof(KtaneModuleInfo));
            if (string.IsNullOrWhiteSpace(m.Name))
            {
                return(HttpResponse.PlainText("You did not specify a module name."));
            }
            var json = ClassifyJson.Serialize(m);
            // Now deserialize and then re-serialize this to force KtaneModuleInfo to perform some sanity things
            var m2 = ClassifyJson.Deserialize <KtaneModuleInfo>(json);

            return(HttpResponse.PlainText(ClassifyJson.Serialize(m2).ToStringIndented()));
        }
Esempio n. 26
0
        private HttpResponse PuzzlePage(HttpRequest req, DbSession session, Db db)
        {
            Match m;

            if ((m = Regex.Match(req.Url.Path, @"^/db-update/(\d+)$")).Success && req.Method == HttpMethod.Post)
            {
                return(dbUpdate(req, session, db, int.Parse(m.Groups[1].Value)));
            }

            var puzzleIdStr = req.Url.Path.Length == 0 ? "" : req.Url.Path.Substring(1);

            if (!int.TryParse(puzzleIdStr, out int puzzleId) || puzzleId < 0)
            {
                return(page404(req));
            }

            var dbPuzzle = db.Puzzles.FirstOrDefault(p => p.PuzzleID == puzzleId);

            if (dbPuzzle == null || dbPuzzle.Invalid)
            {
                return(page404(req));
            }

            var puzzle = new Kyudosudoku(dbPuzzle.KyudokuGrids.Split(36).Select(subgrid => subgrid.Select(ch => ch - '0').ToArray()).ToArray(),
                                         dbPuzzle.Constraints == null ? new SvgConstraint[0] : ClassifyJson.Deserialize <SvgConstraint[]>(JsonValue.Parse(dbPuzzle.Constraints)));

            var userPuzzle = session.User == null ? null : db.UserPuzzles.FirstOrDefault(up => up.UserID == session.User.UserID && up.PuzzleID == puzzleId);

            var extraTop   = puzzle.Constraints.MaxOrDefault(c => c.ExtraTop, 0);
            var extraRight = puzzle.Constraints.MaxOrDefault(c => c.ExtraRight, 0);
            var extraLeft  = puzzle.Constraints.MaxOrDefault(c => c.ExtraLeft, 0);

            var helpSvg = @"<g transform='translate(.05, .05) scale(.008)'>
                <path fill='#fcedca' stroke='black' stroke-width='2' d='M12.5 18.16h75v25h-75z'/>
                <text class='label' x='50' y='33.4' font-size='24' text-anchor='middle' transform='translate(0 5.66)'>???</text>
                <path fill='white' stroke='black' stroke-width='2' d='M53.238 33.237V73.17l9.513-9.513 7.499 18.106 5.272-2.184-7.38-17.818h13.62z'/>
            </g>";
            var fillSvg = @"<text x='.45' y='.4' font-size='.25'>Auto</text><text x='.45' y='.65' font-size='.25' fill='hsl(217, 80%, 50%)'>123</text>";

            var buttonsRight = Ut.NewArray <(string label, bool isSvg, string id, double width, int row)>(9, btn => ((btn + 1).ToString(), false, (btn + 1).ToString(), .9, 0))
                               .Concat(Ut.NewArray <(string label, bool isSvg, string id, double width, int row)>(
                                           ("Normal", false, "normal", 2.6, 1),
                                           ("Corner", false, "corner", 2.6, 1),
                                           ("Center", false, "center", 2.6, 1),
                                           (fillSvg, true, "fill", .9, 1),

                                           ("<path d='m 0.65,0.25 v 0.4 l -0.4,-0.2 z' />", true, "switch", .9, 2),
                                           ("Clear", false, "clear", 2.55, 2),
                                           ("Undo", false, "undo", 2.1, 2),
                                           ("Redo", false, "redo", 2.1, 2),
                                           (helpSvg, true, "help", .9, 2)));

            var buttonsLeft = Ut.NewArray <(string label, bool isSvg, string id, double width, int row)>(9, btn => ((btn + 1).ToString(), false, $"{btn + 1}-left", .85, 0))
                              .Concat(Ut.NewArray <(string label, bool isSvg, string id, double width, int row)>(
                                          ("Clear", false, "clear-left", 2.45, 1),
                                          ("Undo", false, "undo-left", 2.45, 1),
                                          ("Redo", false, "redo-left", 2.45, 1),
                                          ("<path d='m 0.25,0.25 v 0.4 l 0.4,-0.2 z' />", true, "switch-left", .9, 1)));

            string renderButton(string id, double x, double y, double width, string label, bool isSvg = false) => $@"
                <g class='button' id='{id}' transform='translate({x}, {y})'>
                    <rect class='clickable' x='0' y='0' width='{width}' height='.9' stroke-width='.025' rx='.08' ry='.08'/>
                    {(isSvg ? label : $"<text class='label' x='{width / 2}' y='.65' font-size='.55' text-anchor='middle'>{label}</text>")}
Esempio n. 27
0
        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));
        }
Esempio n. 28
0
 /// <summary>Saves the settings stored in <see cref="Settings"/>.</summary>
 protected void SaveSettings()
 {
     SettingsSaver.SaveSettings(ClassifyJson.Serialize(Settings));
 }
Esempio n. 29
0
        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();
                    }
                }
            }
        }
Esempio n. 30
0
        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);
            }
        }