NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// Merged from __tampermonkey__\HeaderStart.tampermonkey
// ==UserScript==
// Merged from __tampermonkey__\HeaderName.tampermonkey
// @name Majoryzator
// Merged from __tampermonkey__\HeaderEnd.tampermonkey
// @namespace https://gitlab.com/sukhoi191/majoryzator
// @version 1.4.6-beta
// @license MIT
// @description Spraw, aby dowolna strona internetowa stała się wypowiedzią Majora Suchodolskiego.
// @author sukhoi191
// @match *://*/*
// @updateURL https://openuserjs.org/meta/sukhoi191/Majoryzator.meta.js
// @downloadURL https://openuserjs.org/install/sukhoi191/Majoryzator.user.js
// @copyright 2019, sukhoi191 (https://openuserjs.org/users/sukhoi191)
// @resource css https://gitlab.com/sukhoi191/majoryzator/raw/master/Majoryzator.css
// @resource knownAbbreviationsJson https://gitlab.com/sukhoi191/majoryzator/raw/master/__data__/KnownAbbreviations.json
// @resource conjunctionAfterBlacklistJson https://gitlab.com/sukhoi191/majoryzator/raw/master/__data__/ConjunctionAfterBlacklist.json
// @resource conjunctionBeforeBlacklistJson https://gitlab.com/sukhoi191/majoryzator/raw/master/__data__/ConjunctionBeforeBlacklist.json
// @resource tentativeEndsJson https://gitlab.com/sukhoi191/majoryzator/raw/master/__data__/TentativeEnds.json
// @resource kononSentencesJson https://gitlab.com/sukhoi191/majoryzator/raw/master/__data__/Konon_Sentences.json
// @resource kononWordsJson https://gitlab.com/sukhoi191/majoryzator/raw/master/__data__/Konon_Words.json
// @resource kononFarewellsJson https://gitlab.com/sukhoi191/majoryzator/raw/master/__data__/Konon_Farewells.json
// @resource kononWelcomesJson https://gitlab.com/sukhoi191/majoryzator/raw/master/__data__/Konon_Welcomes.json
// @resource kononTranslationsJson https://gitlab.com/sukhoi191/majoryzator/raw/master/__data__/Konon_Translations.json
// @resource majorSentencesJson https://gitlab.com/sukhoi191/majoryzator/raw/master/__data__/Major_Sentences.json
// @resource majorWordsJson https://gitlab.com/sukhoi191/majoryzator/raw/master/__data__/Major_Words.json
// @resource majorFarewellsJson https://gitlab.com/sukhoi191/majoryzator/raw/master/__data__/Major_Farewells.json
// @resource majorWelcomesJson https://gitlab.com/sukhoi191/majoryzator/raw/master/__data__/Major_Welcomes.json
// @resource majorTranslationsJson https://gitlab.com/sukhoi191/majoryzator/raw/master/__data__/Major_Translations.json
// @require https://raw.githubusercontent.com/lodash/lodash/4.17.15-npm/lodash.js
// @grant GM_getResourceText
// @run-at document-end
// ==/UserScript==
(function() {
// Merged from __modules__\UseStrict.js
'use strict';
// Merged from __modules__\TranslationType.js
/**
* Enumeracja dla typu tłumaczenia.
*/
const TranslationType = {
ANY: 1,
BEGIN_ONLY: 2,
INSIDE_ONLY: 3,
END_ONLY: 4
};
// Merged from __modules__\TranslationCapitalizationType.js
/**
* Enumeracja dla typu indeksu tłumaczenia.
*/
const TranslationCapitalizationType = {
UPPERCASE: 1,
LOWERCASE: 2,
TITLECASE: 3,
UNKNOWN: 4,
NOT_FOUND: 5
};
// Merged from __modules__\SplittedTextPart.js
class SplittedTextPart {
constructor(text, splitter) {
this.text = text;
this.splitter = splitter;
}
getText() {
return this.text;
}
setText(text) {
this.text = text;
}
getSplitter() {
return this.splitter;
}
setSplitter(splitter) {
this.splitter = splitter;
}
removeSplitter() {
this.setSplitter(null);
}
getJoined() {
return this.getText() + (this.getSplitter() != null ? this.getSplitter() : "");
}
toString() {
return 'text: "' + this.getText() + '" | splitter: "' + this.getSplitter() + '"';
}
}
// Merged from __modules__\Placeholder.js
class Placeholder {
constructor(content, func) {
this.content = content;
this.func = func;
}
swap(textArray) {
for (let i = 0; i < textArray.length; i++) {
textArray[i] = textArray[i].replace(this.content, this.func());
}
return textArray;
}
}
// Merged from __modules__\Person.js
/**
* Reprezentuje osobę.
*/
class Person {
constructor(name) {
this.name = name;
this.welcomeSwaps = [
new Placeholder("{PrzywitaniePoraDnia}", () => this.getCorrectWelcomeForTime(new Date())),
new Placeholder("{DzienTygodnia}", () => this.getDayOfWeek(new Date())),
new Placeholder("{Data}", () => this.getDateAsString(new Date())),
new Placeholder("{Godzina}", () => this.getTimeAsString(new Date()))
];
}
/**
* Imię i nazwisko osoby.
*/
getName() {
return this.name;
}
/**
* Słowa ("spójniki") do wstawienia.
*/
getWords() {
throw new Error('Method is not implemented.');
}
/**
* Pełne zdania do wstawienia.
*/
getFullSentences() {
throw new Error('Method is not implemented.');
}
/**
* Powitania.
*/
getWelcomes() {
throw new Error('Method is not implemented.');
}
/**
* Pożegnania.
*/
getFarewells() {
throw new Error('Method is not implemented.');
}
/**
* Prawdopodobieństwo, że po dotarciu do miejsca, w którym można dodać nowe słowo,
* zostanie ono wstawione.
* 0 oznacza 0% szansy, 100 oznacza 100% szansy.
*/
getProbabilityOfAddingNewWord() {
throw new Error('Method is not implemented.');
}
/**
* Prawdopodobieństwo, że po dotarciu do miejsca, w którym można dodać nowe zdanie,
* zostanie ono wstawione.
* 0 oznacza 0% szansy, 100 oznacza 100% szansy.
*/
getProbabilityOfAddingNewSentence() {
throw new Error('Method is not implemented.');
}
/**
* Lista tłumaczeń.
* Każdy element listy składa się z kilku informacji:
*
* [słowo do znalezienia, funkcja zamieniająca słowo]
*
* Funkcja zamieniająca słowo przyjmuje jako parametr tekst do przetłumaczenia
* oraz instancję translatora.
*
* Standardową implementacją funkcji jest zamiana poszczególnych liter w słowie.
* Dla przykładu, jeśli element poniższej listy będzie wyglądał tak:
*
* ["Cześć", function(str, instane) {
* return instance.replaceWithCasing(str, [["ś", "si"], ["ć", "ci"]])
* }]
*
* W tej sytuacji każde wystąpienie litery "ś" zostanie zmienione na "si", a każde
* wystąpienie litery "ć" zostanie zmienione na "ci", co da nam jako wynik "czesici"
* (tak, to cudny przykład).
*
* Użycie metody replaceWithCasing() pozwala na uporanie się z możliwością otrzymania
* stringa z różnymi wielkościami liter. Dzięki temu przetłumaczone zostaną wszelkie
* możliwe opcje:
* - Cześć
* - cześć
* - cZeŚĆ
* - CZEŚĆ
* - itd.
*/
getTranslations() {
throw new Error('Method is not implemented.');
}
getCorrectWelcomeForTime(date) {
if (date.getHours() >= 19 || (date.getHours() >= 0 && date.getHours() <= 4)) {
return "dobry wieczór";
} else {
return "dzień dobry";
}
}
swapPlaceholders(textArray) {
for (let i = 0; i < this.welcomeSwaps.length; i++) {
textArray = this.welcomeSwaps[i].swap(textArray);
}
return textArray;
}
getTimeAsString(date) {
// https://stackoverflow.com/a/12230363/3470545
return ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2);
}
getDateAsString(date) {
let month = '';
switch (date.getMonth()) {
case 0:
month = "stycznia";
break;
case 1:
month = "lutego";
break;
case 2:
month = "marca";
break;
case 3:
month = "kwietnia";
break;
case 4:
month = "maja";
break;
case 5:
month = "czerwca";
break;
case 6:
month = "lipca";
break;
case 7:
month = "sierpnia";
break;
case 8:
month = "września";
break;
case 9:
month = "października";
break;
case 10:
month = "listopada";
break;
case 11:
month = "grudnia";
break;
}
return date.getDate() + " " + month;
}
getDayOfWeek(date) {
switch (date.getDay()) {
case 0:
return "niedzielę";
case 1:
return "poniedziałek";
case 2:
return "wtorek";
case 3:
return "środę";
case 4:
return "czwartek";
case 5:
return "piątek";
case 6:
return "sobotę";
default:
return "chuj wie co";
}
}
}
// Merged from __modules__\PersonMajor.js
class PersonMajor extends Person {
constructor() {
super('Major Wojciech Suchodoski');
}
getWords() {
return this.swapPlaceholders(JSON.parse(GM_getResourceText("majorWordsJson")).words);
}
getFullSentences() {
return this.swapPlaceholders(JSON.parse(GM_getResourceText("majorSentencesJson")).sentences);
}
getWelcomes() {
return this.swapPlaceholders(JSON.parse(GM_getResourceText("majorWelcomesJson")).welcomes);
}
getFarewells() {
return this.swapPlaceholders(JSON.parse(GM_getResourceText("majorFarewellsJson")).farewells);
}
getTranslations() {
return JSON.parse(GM_getResourceText("majorTranslationsJson")).translations;
}
getProbabilityOfAddingNewWord() {
return 35;
}
getProbabilityOfAddingNewSentence() {
return 30;
}
}
// Merged from __modules__\PersonKonon.js
class PersonKonon extends Person {
constructor() {
super('Krzysztof Kononowicz');
}
getWords() {
return this.swapPlaceholders(JSON.parse(GM_getResourceText("kononWordsJson")).words);
}
getFullSentences() {
return this.swapPlaceholders(JSON.parse(GM_getResourceText("kononSentencesJson")).sentences);
}
getWelcomes() {
return this.swapPlaceholders(JSON.parse(GM_getResourceText("kononWelcomesJson")).welcomes);
}
getFarewells() {
return this.swapPlaceholders(JSON.parse(GM_getResourceText("kononFarewellsJson")).farewells);
}
getTranslations() {
return JSON.parse(GM_getResourceText("kononTranslationsJson")).translations;
}
getProbabilityOfAddingNewWord() {
return 1;
}
getProbabilityOfAddingNewSentence() {
return 40;
}
getCorrectWelcomeForTime(date) {
let welcome = super.getCorrectWelcomeForTime(date);
welcome = welcome[0].toUpperCase() + welcome.substr(1);
return welcome + " państwu";
}
}
// Merged from __modules__\Configuration.Functional.js
/**
* Tłumaczymy?
*/
const TRANSLATE = true;
/**
* Wstawiamy pełne zdania?
*/
const ADD_SENTENCES = true;
/**
* Wstawiamy spójniki?
*/
const ADD_WORDS = true;
/**
* Wstawiamy powitanie?
*/
const ADD_WELCOME = true;
/**
* Wstawiamy pożegnanie?
*/
const ADD_FAREWELL = true;
/**
* Fragment wyrażenia regularnego dla wyszukiwania liter.
*/
const REGEX_LETTERS = "a-zA-ZąćęłńóśźżĄĆĘŁŃÓŚŹŻ";
// Merged from __modules__\Translator.js
/**
* Translator.
*/
class Translator {
constructor(translations) {
this.translations = translations;
}
/**
* Podmienia podane stringi w tekście, dodatkowo podmieniając wersje lowercase
* i uppercase podanych stringów.
* @param {string} str String do zmiany.
* @param {string} originalWord Oryginalne słowo do zamiany.
* @param {string} findReplace Dane zmiany.
* @param {TranslationType} translationType Określa typ tłumaczenia.
* @param {boolean} matchWholeWord Czy wykonać tłumaczenie tylko w przypadku znalezienia całego słowa?
*/
replaceWithCasing(str, originalWord, findReplace, translationType = TranslationType.ANY,
matchWholeWord = false) {
if (matchWholeWord && str.toLowerCase() != originalWord.toLowerCase()) {
return str;
}
let indexSearchResult = this.findIndex(str, originalWord);
let index = indexSearchResult[0];
if (index == -1) {
return str;
}
if (translationType == TranslationType.BEGIN_ONLY && index > 0) {
return str;
}
if (translationType == TranslationType.INSIDE_ONLY && (index == 0 || index + originalWord.length == str.length)) {
return str;
}
if (translationType == TranslationType.END_ONLY && index + originalWord.length != str.length) {
return str;
}
let swapped = originalWord;
let find = findReplace[0];
let replace = findReplace[1];
swapped = this.replaceExact(swapped, find, replace);
swapped = this.replaceExact(swapped, find.toLowerCase(), replace.toLowerCase());
swapped = this.replaceExact(swapped, find.toUpperCase(), replace.toUpperCase());
if (indexSearchResult[1] == TranslationCapitalizationType.LOWERCASE) {
swapped = swapped.toLowerCase();
} else if (indexSearchResult[1] == TranslationCapitalizationType.UPPERCASE) {
swapped = swapped.toUpperCase();
} else if (indexSearchResult[1] == TranslationCapitalizationType.TITLECASE) {
swapped = this.capitalizeFirstLetter(swapped);
}
return str.substring(0, index) + swapped + str.substring(index + originalWord.length);
}
/**
* Wyszukuje indeks wystąpienia podanego tekstu w innym tekście.
* Sprawdza różne możliwości wielkości liter.
* @param {string} str Tekst do przeszukania.
* @param {string} originalWord Tekst do znalezienia.
* @returns Lista elementów - pierwszy to indeks, drugi określa sposób,
* w jaki znaleziono tekst: N = bez zmian, L = lowercase, U = uppercase,
* ? = nie znaleziono.
*/
findIndex(str, originalWord) {
let index = str.indexOf(originalWord);
if (index != -1) {
return [index, TranslationCapitalizationType.NOT_FOUND];
}
index = str.indexOf(originalWord.toLowerCase());
if (index != -1) {
return [index, TranslationCapitalizationType.LOWERCASE];
}
index = str.indexOf(originalWord.toUpperCase());
if (index != -1) {
return [index, TranslationCapitalizationType.UPPERCASE];
}
index = str.indexOf(this.capitalizeFirstLetter(originalWord));
if (index != -1) {
return [index, TranslationCapitalizationType.TITLECASE];
}
return [index, TranslationCapitalizationType.UNKNOWN];
}
/**
* Zmienia pierwszą literę tekstu na wielką.
* @param {string} str Tekst do zmiany.
*/
capitalizeFirstLetter(str) {
return str[0].toLocaleUpperCase() + str.substring(1);
}
/**
* Dokonuje dokładną zamianę, bez rozróżnienia na wielkość liter.
* @param {string} str String do zmiany.
* @param {string} find String do znalezienia.
* @param {string} replaceWord Tekst do wstawienia.
*/
replaceExact(str, find, replaceWord) {
return str.replace(new RegExp(find, "g"), replaceWord);
}
/**
* Wykonuje tłumaczenie.
* @param {array} textArray Tablica tekstu do przetłumaczenia.
*/
translate(textArray) {
textArray.forEach(function (text) {
this.translations.forEach(function (translation) {
let sourceWord = translation["sourceWord"];
if (!new RegExp(translation["sourceWord"], "i").test(text.getText())) {
return;
}
let translatedWord = sourceWord;
translation["operations"].forEach(function (operation) {
if (operation["method"] == "replaceWithCasing") {
let stringToReplace = operation["stringToReplace"];
let replacementString = operation["replacementString"];
let type = TranslationType.ANY;
let matchWholeWord = false;
if ("type" in operation) {
switch (operation["type"]) {
case "any":
type = TranslationType.ANY;
break;
case "begin_only":
type = TranslationType.BEGIN_ONLY;
break;
case "inside_only":
type = TranslationType.INSIDE_ONLY;
break;
case "end_only":
type = TranslationType.END_ONLY;
break;
}
}
if ("matchWholeWord" in operation) {
matchWholeWord = operation["matchWholeWord"];
}
text.setText(this.replaceWithCasing(text.getText(), translatedWord, [stringToReplace, replacementString], type, matchWholeWord));
translatedWord = text.getText();
}
}.bind(this));
}.bind(this));
}.bind(this));
return textArray;
}
}
// Merged from __modules__\Generator.js
/**
* Generator majorowych wstawek w tekście.
*/
class Generator {
/**
* Tworzy nową instancję.
* @param {Person} person Osoba.
* @param {string} knownAbbreviationsJson Znane skróty.
* @param {string} tentativeEndsJson Niepewne końcówki.
*/
constructor(person, knownAbbreviationsJson, tentativeEndsJson) {
this.person = person;
this.wordsArray = person.getWords();
this.sentencesArray = person.getFullSentences();
this.textSplitters = [' ', '\n'];
this.knownAbbreviations = JSON.parse(knownAbbreviationsJson).abbreviations;
this.tentativeEnds = JSON.parse(tentativeEndsJson).ends;
this.createWordsQueue();
this.createSentencesQueue();
}
/**
* Tworzy kolejkę spójników.
*/
createWordsQueue() {
this.wordsQueue = this.wordsArray.slice(0);
this.shuffleArray(this.wordsQueue);
}
/**
* Tworzy kolejkę zdań.
*/
createSentencesQueue() {
this.sentencesQueue = this.sentencesArray.slice(0);
this.shuffleArray(this.sentencesQueue);
}
/**
* Miesza elementy w tablicy (generuje losową permutację).
* Kod z https://stackoverflow.com/a/12646864/3470545 (a co, ja też jestem
* czasem leniwy).
* @param {array} array Tablica do wymieszania.
*/
shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
/**
* Losowo wstawia słowa / zdania do tekstu.
* @param {string} text Tekst do zmiany.
* @param {boolean} addWelcomeNow Czy wstawiamy powitanie na początku podanego tekstu?
* @param {boolean} addFarewellNow Czy wstawiamy pożegnanie na końcu podanego tekstu?
* @param {string} conjunctionBeforeBlacklist Czarna lista słów, przed którymi nie można wstawić spójnika.
* @param {string} conjunctionAfterBlacklistJson Czarna lista słów, po których nie można wstawić spójnika.
*/
generate(text, addWelcomeNow, addFarewellNow, conjunctionBeforeBlacklistJson, conjunctionAfterBlacklistJson) {
let splittedText = this.splitText(text, this.textSplitters);
let conjunctionBeforeBlacklist = JSON.parse(conjunctionBeforeBlacklistJson).blacklist;
let conjunctionAfterBlacklist = JSON.parse(conjunctionAfterBlacklistJson).blacklist;
this.joinNonSplittableParts(splittedText);
this.majorizeTextArray(splittedText, conjunctionBeforeBlacklist, conjunctionAfterBlacklist);
if (addWelcomeNow && ADD_WELCOME) {
this.addWelcome(splittedText, this.person.getWelcomes());
}
if (addFarewellNow && ADD_FAREWELL) {
this.addFarewell(splittedText, this.person.getFarewells());
}
if (TRANSLATE) {
this.translate(splittedText);
}
return this.joinStringArray(splittedText);
}
/**
* Tłumaczy podaną tablicę tekstu.
* @param {array} textArray Tablica ze słowami do przetłumaczenia.
*/
translate(textArray) {
textArray = new Translator(this.person.getTranslations()).translate(textArray);
}
/**
* Dzieli tekst w miejcach wystąpienia podanych znaków.
* @param {string} text Tekst do podzielenia.
* @param {array} splittersArray Tablica z tekstami dzielącymi.
*/
splitText(text, splittersArray) {
if (text == null) {
return [];
}
let result = [new SplittedTextPart(text, '')];
splittersArray.forEach(function (splitter) {
result = this.splitTextWith(result, splitter);
}.bind(this));
return result;
}
/**
* Dzieli elementy na tablicy tekstowej w miejscach wystąpienia podanego tekstu.
* @param {string} textArray Tablica z tekstem.
* @param {string} splitter Tekst dzielący.
*/
splitTextWith(textArray, splitter) {
let newArray = [];
textArray.forEach(splittedTextPart => {
let splitted = splittedTextPart.getText().split(splitter);
if (splitted.length <= 1) {
newArray.push(splittedTextPart);
} else {
splitted.forEach(element => newArray.push(new SplittedTextPart(element, splitter)));
newArray[newArray.length - 1].setSplitter(splittedTextPart.getSplitter());
}
});
if (newArray.length > 0) {
newArray[newArray.length - 1].removeSplitter();
}
return newArray;
}
/**
* Dokonuje majoryzacji tekstu.
* @param {array} textArray Tablica ze słowami do majoryzacji.
* @param {array} conjunctionBeforeBlacklist Czarna lista słów, przed którymi nie można wstawić spójnika.
* @param {array} conjunctionAfterBlacklist Czarna lista słów, po których nie można wstawić spójnika.
*/
majorizeTextArray(textArray, conjunctionBeforeBlacklist, conjunctionAfterBlacklist) {
for (let i = 1; i <= textArray.length; i++) {
if (i < textArray.length &&
(this.isWhitespaceOnly(textArray[i].getText()) ||
this.isEndingWithTentativeText(textArray[i].getText(), this.tentativeEnds))) {
continue;
}
let addNewSentence = false;
let addNewWord = false;
addNewSentence = this.shouldAddNewSentence(this.person.getProbabilityOfAddingNewSentence()) &&
this.isEndOfSentence(textArray[i - 1].getText());
if (!addNewSentence) {
addNewWord = this.shouldAddNewWord(this.person.getProbabilityOfAddingNewWord());
}
if (ADD_SENTENCES && addNewSentence) {
if (this.sentencesQueue.length == 0) {
this.createSentencesQueue();
}
let addedWordsCount = this.addNewSentence(textArray, i, this.sentencesQueue);
i += addedWordsCount;
} else if (ADD_WORDS && addNewWord) {
if (this.wordsQueue.length == 0) {
this.createWordsQueue();
}
if (!this.canAddWordBetweenWords(textArray, i, conjunctionAfterBlacklist, conjunctionBeforeBlacklist)) {
continue;
}
let addedWordsCount = this.addNewWord(textArray, i, this.wordsQueue);
this.addCommaBeforePositionIfNecessary(textArray, i);
i += addedWordsCount;
}
}
}
/**
* Sprawdza, czy w podanym miejscu można wstawić nowe słowo, biorąc pod uwagę
* słowa znajdujące się bezpośrednio po i przed obecnie wstawianym.
* @param {array} textArray Tablica ze słowami do majoryzacji.
* @param {number} position Pozycja nowego słowa.
* @param {array} conjunctionBeforeBlacklist Czarna lista słów, przed którymi nie można wstawić spójnika.
* @param {array} conjunctionAfterBlacklist Czarna lista słów, po których nie można wstawić spójnika.
*/
canAddWordBetweenWords(textArray, position, conjunctionAfterBlacklist, conjunctionBeforeBlacklist) {
if (position == 0 || position >= textArray.length) {
return false;
}
return this.canAddConjunctionAfter(textArray[position - 1].getText(), conjunctionAfterBlacklist) &&
this.canAddConjunctionBefore(textArray[position].getText(), conjunctionBeforeBlacklist);
}
/**
* Sprawdza, czy podany tekst składa się tylko z białych znaków.
* @param {string} str Tekst do sprawdzenia.
*/
isWhitespaceOnly(str) {
return str == "" || /^\s*$/.test(str);
}
/**
* Biorąc pod uwagę prawdopodobieństwo dodania nowego słowa, generuje liczbę informującą o tym,
* czy zostanie ono dodane.
* @param {number} probabilityOfNewWord Prawdopodobieństwo dodania nowego słowa.
*/
shouldAddNewWord(probabilityOfNewWord) {
return _.random(0, 100, false) < probabilityOfNewWord;
}
/**
* Biorąc pod uwagę prawdopodobieństwo dodania nowego zdania, generuje liczbę informującą o tym,
* czy zostanie ono dodane.
* @param {number} probabilityOfNewSentence Prawdopodobieństwo dodania nowego zdania.
*/
shouldAddNewSentence(probabilityOfNewSentence) {
return _.random(0, 100, false) < probabilityOfNewSentence;
}
/**
* Biorąc pod uwagę prawdopodobieństwo dodania nowej czynności, generuje liczbę informującą o tym,
* czy zostanie ona dodana.
* @param {number} probabilityOfNewAction Prawdopodobieństwo dodania nowej czynności.
*/
shouldAddNewAction(probabilityOfNewAction) {
return _.random(0, 100, false) < probabilityOfNewAction;
}
/**
* Dodaje losowe powitanie.
* @param {array} textArray Tablica ze słowami.
* @param {array} welcomes Tablica z dostępnymi powitaniami.
*/
addWelcome(textArray, welcomes) {
let splittedWelcome = this.splitText(_.sample(welcomes), this.textSplitters);
splittedWelcome[splittedWelcome.length - 1].setSplitter(' ');
Array.prototype.unshift.apply(textArray, [].concat(splittedWelcome));
}
/**
* Dodaje losowe pożegnanie.
* @param {array} textArray Tablica ze słowami.
* @param {array} farewells Tablica z dostępnymi pożegnaniami.
*/
addFarewell(textArray, farewells) {
textArray[textArray.length - 1].setSplitter(' ');
let splittedFarewell = this.splitText(_.sample(farewells), this.textSplitters);
splittedFarewell[splittedFarewell.length - 1].setSplitter(' ');
Array.prototype.push.apply(textArray, [].concat(splittedFarewell));
}
/**
* Wstawia losowe zdanie na podanej pozycji.
* @param {array} textArray Tablica ze słowami.
* @param {number} position Pozycja do wstawienia nowego zdania.
* @param {array} sentencesQueue Kolejka z dostępnymi zdaniami.
* @returns Ilość słów w dodanej tablicy.
*/
addNewSentence(textArray, position, sentencesQueue) {
if (position == textArray.length) {
textArray[position - 1].setSplitter(' ');
}
let splittedSentence = this.splitText(sentencesQueue.shift(), this.textSplitters);
splittedSentence[splittedSentence.length - 1].setSplitter(' ');
Array.prototype.splice.apply(textArray, [position, 0].concat(splittedSentence));
return splittedSentence.length;
}
/**
* Wstawia nowe losowe słowo na podanej pozycji i dopisuje przecinek.
* @param {array} textArray Tablica ze słowami.
* @param {number} position Pozycja do wstawienia nowego zdania.
* @param {array} wordsQueue Kolejka z dostępnymi słowami.
* @returns Ilość słów w dodanej tablicy.
*/
addNewWord(textArray, position, wordsQueue) {
let splittedWord = this.splitText(wordsQueue.shift() + ",", this.textSplitters);
splittedWord[splittedWord.length - 1].setSplitter(' ');
Array.prototype.splice.apply(textArray, [position, 0].concat(splittedWord));
return splittedWord.length;
}
/**
* Sprawdza, czy można wstawić spójnik przed podanym tekstem.
* @param {string} text Tekst do sprawdzenia.
* @param {array} conjunctionBeforeBlacklist Czarna lista słów, przed którymi nie można wstawić spójnika.
*/
canAddConjunctionBefore(text, conjunctionBeforeBlacklist = []) {
return !/[\[|\(|\{|\-|–].*/.test(text) &&
!this.isConjunctionOnBlacklist(text, conjunctionBeforeBlacklist);
}
/**
* Sprawdza, czy można wstawić spójnik za podanym tekstem.
* @param {string} text Tekst do sprawdzenia.
* @param {array} conjunctionBeforeBlacklist Czarna lista słów, po których nie można wstawić spójnika.
*/
canAddConjunctionAfter(text, conjunctionAfterBlacklist = []) {
return !this.isWhitespaceOnly(text) &&
!this.isEndOfSentence(text) &&
!/.*[;|:|\-|–|\)\]\}]$/.test(text) &&
!this.isConjunctionOnBlacklist(text, conjunctionAfterBlacklist) &&
!this.isEndingWithTentativeText(text, this.tentativeEnds);
}
/**
* Sprawdza, czy podany tekst jest na czarnej liście słów.
* @param {string} text Tekst do sprawdzenia.
*/
isConjunctionOnBlacklist(text, blacklist) {
for (let i = 0; i < blacklist.length; i++) {
if (new RegExp('^[ "\'\\(\\[\\{]*(' + blacklist[i].toLowerCase() + ')$').test(text.toLowerCase())) {
return true;
}
}
return false;
}
/**
* Dodaje przecinek przed podaną pozycję, o ile jest to potrzebne.
* @param {array} textArray Tablica ze słowami.
* @param {number} position Pozycja do sprawdzenia.
*/
addCommaBeforePositionIfNecessary(textArray, position) {
if (position > 0 && position <= textArray.length && !textArray[position - 1].getText().endsWith(",")) {
textArray[position - 1].setText(textArray[position - 1].getText() + ",");
}
}
addSpaceIfNecessary(textArray, position) {
if (position > 0 && position <= textArray.length && textArray[position - 1].getSplitter() == null) {
textArray[position - 1].setText(textArray[position - 1].getText() + " ");
}
}
/**
* Łączy te części tekstu, które nie powinny być podzielone.
* @param {array} textArray Tablica z tekstem.
*/
joinNonSplittableParts(textArray) {
let nonSplitabbleParts = [
"-", "–", ""
];
for (let i = 0; i < textArray.length; i++) {
let startIndex = -1;
if (nonSplitabbleParts.includes(textArray[i].getText())) {
startIndex = i;
}
while (i < textArray.length && nonSplitabbleParts.includes(textArray[i].getText())) {
// Znajdujemy następny dozwolony znak.
i++;
}
if (i == textArray.length) {
i--;
}
if (startIndex != -1) {
let slice = textArray.slice(startIndex, i + 1);
let newElement = '';
let lastSplitter = '';
slice.forEach(function (element) {
newElement += element.getJoined();
lastSplitter = element.getSplitter();
});
if (lastSplitter != null) {
newElement = newElement.slice(0, -lastSplitter.length);
}
textArray.splice(startIndex, i - startIndex);
textArray[startIndex].setText(newElement);
textArray[startIndex].setSplitter(lastSplitter);
i -= (i - startIndex);
}
}
}
/**
* Łączy tablicę tekstu do stringa, używając podanego znaku lub tekstu do połączenia
* kolejnych elementów.
* @param {array} textArray Tablica ze słowami.
*/
joinStringArray(textArray) {
if (textArray == null) {
return '';
}
let str = "";
let lastSplitter = '';
textArray.forEach(element => {
str += element.getJoined();
lastSplitter = element.getSplitter();
});
if (lastSplitter == null) {
return str;
}
return str.length > 0 && lastSplitter.length > 0 ? str.slice(0, -lastSplitter.length) : str;
}
/**
* Określa, czy podany string jest końcem zdania.
* @param {string} str Tekst do sprawdzenia.
*/
isEndOfSentence(str) {
if (this.isAbbreviation(str, this.knownAbbreviations)) {
return false;
}
let endOfSentence = new RegExp('[' + REGEX_LETTERS + '0-9 \\[\\{\\(\\]\\}\\)"\']+(\\.|[!|?]+)$').test(str);
if (endOfSentence) {
return true;
}
if (this.isPunctuationMarksOnlyEndOfSentence(str)) {
return true;
}
return false;
}
/**
* Sprawdza, czy podany tekst zawiera tylko znaki interpunkcyjne, które określają koniec zdania,
* np. kropka, wykrzyknik (lub więcej) itd.
* @param {string} str Tekst do sprawdzenia.
*/
isPunctuationMarksOnlyEndOfSentence(str) {
if (str.length == 0) {
return false;
}
if (str.length == 1 && str[0] == '.') {
return true;
}
for (let i = 0; i < str.length; i++) {
if (str[i] != '!' && str[i] != '?') {
return false;
}
}
return true;
}
/**
* Sprawdza, czy podany tekst jest znanym skrótem.
* @param {string} str Tekst do sprawdzenia.
* @param {array} abbreviations Tablica znanych skrótów.
*/
isAbbreviation(str, abbreviations) {
for (let i = 0; i < abbreviations.length; i++) {
let abbreviation = abbreviations[i];
if (new RegExp('^[ "\'\\(\\[\\{]*(' + abbreviation.toLowerCase() + ')$').test(str.toLowerCase())) {
return true;
}
}
return false;
}
/**
* Sprawdza, czy podany tekst kończy się znakami, które nie dają pewności
* pod względem tego, czy mamy do czynienia z końcem zdania, czy nie.
* @param {string} str Tekst do sprawdzenia.
* @param {array} tentativeEndsArray Tablica niepewnych zakończeń.
*/
isEndingWithTentativeText(str, tentativeEndsArray) {
for (let i = 0; i < tentativeEndsArray.length; i++) {
if (str.toLowerCase().endsWith(tentativeEndsArray[i])) {
return true;
}
}
return false;
}
}
// Merged from __modules__\WebsiteMajorizator.js
/**
* Majoryzator stron internetowych.
*/
class WebsiteMajorizator {
/**
* Tworzy nową instancję.
* @param {Person} person Osoba.
*/
constructor(person) {
this.nodesToMajorize = [];
this.person = person;
}
/**
* Sprawdza, czy dzieci podanego węzła mogą
* zostać poddane edycji.
* @param {Node} node Węzeł do sprawdzenia.
*/
areNodeChildrenMajorizable(node) {
let tagsToOmmit = [
"SCRIPT",
"STYLE"
];
return node != null && !tagsToOmmit.includes(node.tagName) && node.nodeType == 1;
}
/**
* Sprawdza, czy węzeł może zostać poddany modyfikacji.
* @param {Node} node Węzeł do sprawdzenia.
*/
isNodeEditable(node) {
if (node == null || typeof node != "object") {
return false;
}
if (node.data === undefined || node.data == null || node.data == "" || !new RegExp('[' + REGEX_LETTERS + ']+').test(node.data)) {
return false;
}
if (node.nodeType === undefined || node.nodeType != 3) {
return false;
}
if (node.childNodes === undefined || typeof node.childNodes != "object") {
return false;
}
return true;
}
/**
* Dokonuje rekursywnej majoryzacji podanego węzła ze strony internetowej.
* @param {Node} node Węzeł, dla którego wykonujemy majoryzację.
*/
findNodesToMajorize(node) {
if (this.isNodeEditable(node)) {
this.nodesToMajorize.push(node);
}
if (this.areNodeChildrenMajorizable(node)) {
node.childNodes.forEach(function (child) {
this.findNodesToMajorize(child);
}.bind(this));
}
}
/**
* Majoryzuje znalezione węzły.
* @param {Generator} generator Instanacja Generatora.
* @param {string} conjunctionBeforeBlacklistJson Czarna lista słów, po których nie można wstawić spójnika.
* @param {string} conjunctionAfterBlacklistJson Czarna lista słów, przed którymi nie można wstawić spójnika.
*/
majorizeNodes(generator, conjunctionBeforeBlacklistJson, conjunctionAfterBlacklistJson) {
for (let i = 0; i < this.nodesToMajorize.length; i++) {
let node = this.nodesToMajorize[i];
node.data = generator.generate(node.data, i == 0, i == this.nodesToMajorize.length - 1,
conjunctionBeforeBlacklistJson,
conjunctionAfterBlacklistJson);
}
}
/**
* Uruchamia majoryzację całej strony.
*/
majorizeWholeWebsite(conjunctionBeforeBlacklistJson, conjunctionAfterBlacklistJson,
knownAbbreviationsJson, tentativeEndsJson) {
this.findNodesToMajorize(document.body);
this.majorizeNodes(new Generator(this.person,
knownAbbreviationsJson,
tentativeEndsJson),
conjunctionBeforeBlacklistJson,
conjunctionAfterBlacklistJson);
}
}
// Merged from __modules__\Launcher.js
class Launcher {
addCss() {
let style = document.createElement("style");
style.innerHTML = GM_getResourceText("css");
document.body.appendChild(style);
}
createButton(person, text, buttonId) {
let button = document.createElement("input");
button.type = "button";
button.value = text;
button.classList.add("majoryzator-button");
button.id = buttonId;
button.onclick = () => new WebsiteMajorizator(person).majorizeWholeWebsite(
GM_getResourceText("conjunctionBeforeBlacklistJson"),
GM_getResourceText("conjunctionAfterBlacklistJson"),
GM_getResourceText("knownAbbreviationsJson"),
GM_getResourceText("tentativeEndsJson")
);
document.body.appendChild(button);
}
launch() {
this.addCss();
this.createButton(new PersonMajor(), "M", "majoryzator-suchodolski");
this.createButton(new PersonKonon(), "K", "majoryzator-kononowicz");
}
}
new Launcher().launch();
// Merged from __tampermonkey__\Footer.tampermonkey
})();