Esempio n. 1
0
        private static string GetReaderSettings(CollectionSettings currentCollectionSettings)
        {
            var settingsPath = DecodableReaderToolSettings.GetReaderToolsSettingsFilePath(currentCollectionSettings);

            // if file exists, return current settings
            if (RobustFile.Exists(settingsPath))
            {
                var result = RobustFile.ReadAllText(settingsPath, Encoding.UTF8);
                if (!string.IsNullOrWhiteSpace(result))
                {
                    return(result);
                }
            }

            // file does not exist, so make a new one
            // The literal string here defines our default reader settings for a collection.
            var settingsString = "{\"letters\":\"a b c d e f g h i j k l m n o p q r s t u v w x y z\","
                                 + "\"moreWords\":\"\","
                                 + "\"stages\":[{\"letters\":\"\",\"sightWords\":\"\"}],"
                                 + "\"levels\":[{\"maxWordsPerSentence\":2,\"maxWordsPerPage\":2,\"maxWordsPerBook\":20,\"maxUniqueWordsPerBook\":0,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":5,\"maxWordsPerPage\":5,\"maxWordsPerBook\":23,\"maxUniqueWordsPerBook\":8,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":7,\"maxWordsPerPage\":10,\"maxWordsPerBook\":72,\"maxUniqueWordsPerBook\":16,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":8,\"maxWordsPerPage\":18,\"maxWordsPerBook\":206,\"maxUniqueWordsPerBook\":32,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":12,\"maxWordsPerPage\":25,\"maxWordsPerBook\":500,\"maxUniqueWordsPerBook\":64,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":20,\"maxWordsPerPage\":50,\"maxWordsPerBook\":1000,\"maxUniqueWordsPerBook\":0,\"thingsToRemember\":[]}]}";

            RobustFile.WriteAllText(settingsPath, settingsString);

            return(settingsString);
        }
Esempio n. 2
0
        private static string GetReaderSettings(CollectionSettings currentCollectionSettings)
        {
            var settingsPath = DecodableReaderToolSettings.GetReaderToolsSettingsFilePath(currentCollectionSettings);
            var jsonSettings = "";

            // if file exists, return current settings
            if (RobustFile.Exists(settingsPath))
            {
                var result = RobustFile.ReadAllText(settingsPath, Encoding.UTF8);
                if (!string.IsNullOrWhiteSpace(result))
                {
                    jsonSettings = result;
                }
            }

            if (jsonSettings.Length > 0)
            {
                dynamic fixedSettings = JsonConvert.DeserializeObject(jsonSettings);
                fixedSettings.writingSystemTag = currentCollectionSettings.Language1.Iso639Code;
                return(JsonConvert.SerializeObject(fixedSettings));
            }
            // file does not exist, so make a new one
            // The literal string here defines our default reader settings for a collection.
            var settingsString = "{\"writingSystemTag\": \"" + currentCollectionSettings.Language1.Iso639Code + "\", "
                                 + "\"letters\":\"a b c d e f g h i j k l m n o p q r s t u v w x y z\","
                                 + $"\"lang\":\"{currentCollectionSettings.Language1Iso639Code}\","
                                 + "\"moreWords\":\"\","
                                 + "\"stages\":[{\"letters\":\"\",\"sightWords\":\"\"}],"
                                 + "\"levels\":[{\"maxWordsPerSentence\":2,\"maxWordsPerPage\":2,\"maxWordsPerBook\":20,\"maxUniqueWordsPerBook\":0,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":5,\"maxWordsPerPage\":5,\"maxWordsPerBook\":23,\"maxUniqueWordsPerBook\":8,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":7,\"maxWordsPerPage\":10,\"maxWordsPerBook\":72,\"maxUniqueWordsPerBook\":16,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":8,\"maxWordsPerPage\":18,\"maxWordsPerBook\":206,\"maxUniqueWordsPerBook\":32,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":12,\"maxWordsPerPage\":25,\"maxWordsPerBook\":500,\"maxUniqueWordsPerBook\":64,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":20,\"maxWordsPerPage\":50,\"maxWordsPerBook\":1000,\"maxUniqueWordsPerBook\":0,\"thingsToRemember\":[]}]}";

            RobustFile.WriteAllText(settingsPath, settingsString);

            return(settingsString);
        }
Esempio n. 3
0
        public void HandleRequest(ApiRequest request)
        {
            if (CurrentBook == null)
            {
                Debug.Fail("BL-836 reproduction?");
                // ReSharper disable once HeuristicUnreachableCode
                request.Failed("CurrentBook is null");
                return;
            }
            if (request.CurrentCollectionSettings == null)
            {
                Debug.Fail("BL-836 reproduction?");
                // ReSharper disable once HeuristicUnreachableCode
                request.Failed("CurrentBook.CollectionSettings is null");
                return;
            }

            var lastSegment = request.LocalPath().Split(new char[] { '/' }).Last();

            switch (lastSegment)
            {
            case "test":
                request.PostSucceeded();
                break;

            case "readerToolSettings":
                if (request.HttpMethod == HttpMethods.Get)
                {
                    request.ReplyWithJson(GetReaderSettings(request.CurrentCollectionSettings));
                }
                else
                {
                    var path    = DecodableReaderToolSettings.GetReaderToolsSettingsFilePath(request.CurrentCollectionSettings);
                    var content = request.RequiredPostJson();
                    RobustFile.WriteAllText(path, content, Encoding.UTF8);
                    request.PostSucceeded();
                }
                break;


            //note, this endpoint is confusing because it appears that ultimately we only use the word list out of this file (see "sampleTextsList").
            //This ends up being written to a ReaderToolsWords-xyz.json (matching its use, if not it contents).
            case "synphonyLanguageData":
                //This is the "post". There is no direct "get", but the name of the file is given in the "sampleTextList" reply, below.
                // We've had situations (BL-4313 and friends) where reading the posted data fails. This seems to be due to situations
                // where we have a very large block of data and are rapidly switching between books. But as far as I can tell, the only
                // case where it's at all important to capture the new language data is if the user has been changing settings and
                // in particular editing the word list. Timing out the save in that situation seems very unlikely to fail.
                // So, in the interests of preventing the crash when switching books fast, we will ignore failure to read all the
                // json, and just not update the file. We would in any case keep only the version of the data sent to us by
                // the last book which sends it, and that one is unlikely to get interrupted.
                string langdata;
                try
                {
                    langdata = request.RequiredPostJson();
                }
                catch (IOException e)
                {
                    SIL.Reporting.Logger.WriteError("Saving synphonyLanguageData failed to get Json", e);
                    break;
                }

                SaveSynphonyLanguageData(langdata);
                request.PostSucceeded();
                break;

            case "sampleTextsList":
                //note, as part of this reply, we send the path of the "ReaderToolsWords-xyz.json" which is *written* by the "synphonyLanguageData" endpoint above
                request.ReplyWithText(GetSampleTextsList(request.CurrentCollectionSettings.SettingsFilePath));
                break;

            case "sampleFileContents":
                request.ReplyWithText(GetTextFileContents(request.RequiredParam("fileName"), WordFileType.SampleFile));
                break;

            case "textOfContentPages":
                request.ReplyWithText(GetTextOfContentPagesAsJson());
                break;

            case "makeLetterAndWordList":
                MakeLetterAndWordList(request.RequiredPostValue("settings"), request.RequiredPostValue("allWords"));
                request.PostSucceeded();
                break;

            case "openTextsFolder":
                OpenTextsFolder();
                request.PostSucceeded();
                break;

            case "chooseAllowedWordsListFile":
                lock (request)
                {
                    request.ReplyWithText(ShowSelectAllowedWordsFileDialog());
                }
                break;

            case "allowedWordsList":
                switch (request.HttpMethod)
                {
                case HttpMethods.Delete:
                    RecycleAllowedWordListFile(request.RequiredParam("fileName"));
                    request.PostSucceeded();
                    break;

                case HttpMethods.Get:
                    var fileName = request.RequiredParam("fileName");
                    request.ReplyWithText(RemoveEmptyAndDupes(GetTextFileContents(fileName, WordFileType.AllowedWordsFile)));
                    break;

                default:
                    request.Failed("Http verb not handled");
                    break;
                }
                break;

            case "defaultLevel":
                if (request.HttpMethod == HttpMethods.Get)
                {
                    request.ReplyWithText(Settings.Default.CurrentLevel.ToString());
                }
                else
                {
                    int level;
                    if (int.TryParse(request.RequiredParam("level"), out level))
                    {
                        Settings.Default.CurrentLevel = level;
                        Settings.Default.Save();
                    }
                    else
                    {
                        // Don't think any sort of runtime failure is worthwhile here.
                        Debug.Fail("could not parse level number");
                    }
                    request.PostSucceeded();                             // technically it didn't if we didn't parse the number
                }
                break;

            case "defaultStage":
                if (request.HttpMethod == HttpMethods.Get)
                {
                    request.ReplyWithText(Settings.Default.CurrentStage.ToString());
                }
                else
                {
                    int stage;
                    if (int.TryParse(request.RequiredParam("stage"), out stage))
                    {
                        Settings.Default.CurrentStage = stage;
                        Settings.Default.Save();
                    }
                    else
                    {
                        // Don't think any sort of runtime failure is worthwhile here.
                        Debug.Fail("could not parse stage number");
                    }
                    request.PostSucceeded();                             // technically it didn't if we didn't parse the number
                }
                break;

            default:
                request.Failed("Don't understand '" + lastSegment + "' in " + request.LocalPath());
                break;
            }
        }
Esempio n. 4
0
        public void HandleRequest(ApiRequest request)
        {
            if (CurrentBook == null)
            {
                Debug.Fail("BL-836 reproduction?");
                // ReSharper disable once HeuristicUnreachableCode
                request.Failed("CurrentBook is null");
                return;
            }
            if (request.CurrentCollectionSettings == null)
            {
                Debug.Fail("BL-836 reproduction?");
                // ReSharper disable once HeuristicUnreachableCode
                request.Failed("CurrentBook.CollectionSettings is null");
                return;
            }

            var lastSegment = request.LocalPath().Split(new char[] { '/' }).Last();

            switch (lastSegment)
            {
            case "test":
                request.PostSucceeded();
                break;

            case "readerSettingsEditForbidden":
                request.ReplyWithText(_tcManager.OkToEditCollectionSettings
                                                ? ""
                                                : WorkspaceView.MustBeAdminMessage);
                break;

            case "readerToolSettings":
                if (request.HttpMethod == HttpMethods.Get)
                {
                    request.ReplyWithJson(GetReaderSettings(request.CurrentBook.BookData));
                }
                else
                {
                    var path    = DecodableReaderToolSettings.GetReaderToolsSettingsFilePath(request.CurrentCollectionSettings);
                    var content = request.RequiredPostJson();
                    RobustFile.WriteAllText(path, content, Encoding.UTF8);
                    request.PostSucceeded();
                }
                break;


            //note, this endpoint is confusing because it appears that ultimately we only use the word list out of this file (see "sampleTextsList").
            //This ends up being written to a ReaderToolsWords-xyz.json (matching its use, if not it contents).
            case "synphonyLanguageData":
                //This is the "post". There is no direct "get", but the name of the file is given in the "sampleTextList" reply, below.
                // We've had situations (BL-4313 and friends) where reading the posted data fails. This seems to be due to situations
                // where we have a very large block of data and are rapidly switching between books. But as far as I can tell, the only
                // case where it's at all important to capture the new language data is if the user has been changing settings and
                // in particular editing the word list. Timing out the save in that situation seems very unlikely to fail.
                // So, in the interests of preventing the crash when switching books fast, we will ignore failure to read all the
                // json, and just not update the file. We would in any case keep only the version of the data sent to us by
                // the last book which sends it, and that one is unlikely to get interrupted.
                string langdata;
                try
                {
                    langdata = request.RequiredPostJson();
                }
                catch (IOException e)
                {
                    SIL.Reporting.Logger.WriteError("Saving synphonyLanguageData failed to get Json", e);
                    break;
                }

                SaveSynphonyLanguageData(langdata);
                request.PostSucceeded();
                break;

            case "sampleTextsList":
                //note, as part of this reply, we send the path of the "ReaderToolsWords-xyz.json" which is *written* by the "synphonyLanguageData" endpoint above
                request.ReplyWithText(GetSampleTextsList(request.CurrentCollectionSettings.SettingsFilePath));
                break;

            case "sampleFileContents":
                request.ReplyWithText(GetTextFileContents(request.RequiredParam("fileName"), WordFileType.SampleFile));
                break;

            case "textOfContentPages":
                request.ReplyWithText(GetTextOfContentPagesAsJson());
                break;

            case "makeLetterAndWordList":
                MakeLetterAndWordList(request.RequiredPostString("settings"), request.RequiredPostString("allWords"));
                request.PostSucceeded();
                break;

            case "openTextsFolder":
                OpenTextsFolder();
                request.PostSucceeded();
                break;

            case "chooseAllowedWordsListFile":
                lock (request)
                {
                    request.ReplyWithText(ShowSelectAllowedWordsFileDialog());
                }
                break;

            case "allowedWordsList":
                switch (request.HttpMethod)
                {
                case HttpMethods.Delete:
                    RecycleAllowedWordListFile(request.RequiredParam("fileName"));
                    request.PostSucceeded();
                    break;

                case HttpMethods.Get:
                    var fileName = request.RequiredParam("fileName");
                    request.ReplyWithText(RemoveEmptyAndDupes(GetTextFileContents(fileName, WordFileType.AllowedWordsFile)));
                    break;

                default:
                    request.Failed("Http verb not handled");
                    break;
                }
                break;

            case "defaultLevel":
                if (request.HttpMethod == HttpMethods.Get)
                {
                    request.ReplyWithText(Settings.Default.CurrentLevel.ToString());
                }
                else
                {
                    int level;
                    if (int.TryParse(request.RequiredParam("level"), out level))
                    {
                        Settings.Default.CurrentLevel = level;
                        Settings.Default.Save();
                    }
                    else
                    {
                        // Don't think any sort of runtime failure is worthwhile here.
                        Debug.Fail("could not parse level number");
                    }
                    request.PostSucceeded();                             // technically it didn't if we didn't parse the number
                }
                break;

            case "defaultStage":
                if (request.HttpMethod == HttpMethods.Get)
                {
                    request.ReplyWithText(Settings.Default.CurrentStage.ToString());
                }
                else
                {
                    int stage;
                    if (int.TryParse(request.RequiredParam("stage"), out stage))
                    {
                        Settings.Default.CurrentStage = stage;
                        Settings.Default.Save();
                    }
                    else
                    {
                        // Don't think any sort of runtime failure is worthwhile here.
                        Debug.Fail("could not parse stage number");
                    }
                    request.PostSucceeded();                             // technically it didn't if we didn't parse the number
                }
                break;

            case "copyBookStatsToClipboard":
                // See https://issues.bloomlibrary.org/youtrack/issue/BL-10018.
                string bookStatsString;
                try
                {
                    bookStatsString = request.RequiredPostJson();
                    dynamic bookStats  = DynamicJson.Parse(bookStatsString);
                    var     headerBldr = new StringBuilder();
                    var     dataBldr   = new StringBuilder();
                    headerBldr.Append("Book Title");
                    var title = _bookSelection.CurrentSelection.Title;
                    title = title.Replace("\"", "\"\"");                                // Double double quotes to get Excel to recognize them.
                    dataBldr.AppendFormat("\"{0}\"", title);
                    headerBldr.Append("\tLevel");
                    dataBldr.AppendFormat("\t\"Level {0}\"", bookStats["levelNumber"]);
                    headerBldr.Append("\tNumber of Pages with Text");
                    dataBldr.AppendFormat("\t{0}", bookStats["pageCount"]);
                    headerBldr.Append("\tTotal Number of Words");
                    dataBldr.AppendFormat("\t{0}", bookStats["actualWordCount"]);
                    headerBldr.Append("\tTotal Number of Sentences");
                    dataBldr.AppendFormat("\t{0}", bookStats["actualSentenceCount"]);
                    headerBldr.Append("\tAverage No of Words per Page with Text");
                    dataBldr.AppendFormat("\t{0:0.#}", bookStats["actualAverageWordsPerPage"]);
                    headerBldr.Append("\tAverage No of Sentences per Page with Text");
                    dataBldr.AppendFormat("\t{0:0.#}", bookStats["actualAverageSentencesPerPage"]);
                    headerBldr.Append("\tNumber of Unique Words");
                    dataBldr.AppendFormat("\t{0}", bookStats["actualUniqueWords"]);
                    headerBldr.Append("\tAverage Word Length");
                    dataBldr.AppendFormat("\t{0:0.#}", bookStats["actualAverageGlyphsPerWord"]);
                    headerBldr.Append("\tAverage Sentence Length");
                    dataBldr.AppendFormat("\t{0:0.#}", bookStats["actualAverageWordsPerSentence"]);
                    headerBldr.Append("\tMaximum Word Length");
                    dataBldr.AppendFormat("\t{0}", bookStats["actualMaxGlyphsPerWord"]);
                    headerBldr.Append("\tMaximum Sentence Length");
                    dataBldr.AppendFormat("\t{0}", bookStats["actualMaxWordsPerSentence"]);
                    // "actualWordsPerPageBook" is the maximum number of words on a page in the book
                    // It's in the json data, but not asked for in the clipboard copying.
                    var stringToSave = headerBldr.ToString() + Environment.NewLine + dataBldr.ToString();
                    PortableClipboard.SetText(stringToSave);
                }
                catch (IOException e)
                {
                    SIL.Reporting.Logger.WriteError("Copying book statistics to clipboard failed to get Json", e);
                    break;
                }
                request.PostSucceeded();
                break;

            default:
                request.Failed("Don't understand '" + lastSegment + "' in " + request.LocalPath());
                break;
            }
        }