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); }
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); }
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; } }
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; } }