This commit is contained in:
Miodec 2022-03-13 20:32:36 +01:00
commit 622e016db2
9 changed files with 214 additions and 108 deletions

View file

@ -0,0 +1,156 @@
import { shuffle } from "../utils/misc";
import { subscribe } from "../observables/config-event";
interface Quote {
text: string;
source: string;
length: number;
id: number;
}
interface QuoteData {
language: string;
quotes: Quote[];
groups: number[][];
}
interface QuoteCollection {
quotes: MonkeyTypes.Quote[];
length: number;
language: string | null;
groups: MonkeyTypes.Quote[][];
}
const defaultQuoteCollection: QuoteCollection = {
quotes: [],
length: 0,
language: null,
groups: [],
};
class QuotesController {
private quoteCollection: QuoteCollection = defaultQuoteCollection;
private quoteQueue: MonkeyTypes.Quote[] = [];
private queueIndex = 0;
async getQuotes(
language: string,
quoteLengths?: number[]
): Promise<QuoteCollection> {
const normalizedLanguage = language.replace(/_\d*k$/g, "");
if (this.quoteCollection.language !== normalizedLanguage) {
try {
const data: QuoteData = await $.getJSON(`quotes/${language}.json`);
if (data.quotes === undefined || data.quotes.length === 0) {
return defaultQuoteCollection;
}
this.quoteCollection = {
quotes: [],
length: data.quotes.length,
groups: [],
language: data.language,
};
// Transform JSON Quote schema to MonkeyTypes Quote schema
data.quotes.forEach((quote: Quote) => {
const monkeyTypeQuote: MonkeyTypes.Quote = {
text: quote.text,
source: quote.source,
length: quote.length,
id: quote.id,
language: language,
};
this.quoteCollection.quotes.push(monkeyTypeQuote);
});
data.groups.forEach((quoteGroup, groupIndex) => {
const lower = quoteGroup[0];
const upper = quoteGroup[1];
this.quoteCollection.groups[groupIndex] =
this.quoteCollection.quotes.filter((quote) => {
if (quote.length >= lower && quote.length <= upper) {
quote.group = groupIndex;
return true;
}
return false;
});
});
if (quoteLengths !== undefined) {
this.updateQuoteQueue(quoteLengths);
}
} catch {
return defaultQuoteCollection;
}
}
return this.quoteCollection;
}
getQuoteById(id: number): MonkeyTypes.Quote | undefined {
const targetQuote = this.quoteCollection.quotes.find(
(quote: MonkeyTypes.Quote) => {
return quote.id === id;
}
);
return targetQuote;
}
updateQuoteQueue(quoteGroups: number[]): void {
this.quoteQueue = [];
quoteGroups.forEach((group) => {
if (group < 0) {
return;
}
this.quoteCollection.groups[group]?.forEach((quote) => {
this.quoteQueue.push(quote);
});
});
shuffle(this.quoteQueue);
this.queueIndex = 0;
}
getRandomQuote(): MonkeyTypes.Quote | null {
if (this.quoteQueue.length === 0) {
return null;
}
if (this.queueIndex >= this.quoteQueue.length) {
this.queueIndex = 0;
shuffle(this.quoteQueue);
}
const randomQuote = this.quoteQueue[this.queueIndex];
this.queueIndex += 1;
return randomQuote;
}
getCurrentQuote(): MonkeyTypes.Quote | null {
if (this.quoteQueue.length === 0) {
return null;
}
return this.quoteQueue[this.queueIndex];
}
}
const quoteController = new QuotesController();
subscribe((key, newValue) => {
if (key === "quoteLength") {
quoteController.updateQuoteQueue(newValue as number[]);
}
});
export default quoteController;

View file

@ -3,7 +3,7 @@ import Config from "../config";
import * as TestWords from "../test/test-words";
import * as Loader from "../elements/loader";
import * as Notifications from "../elements/notifications";
import * as Misc from "../utils/misc";
import QuotesController from "../controllers/quotes-controller";
const CAPTCHA_ID = 1;
@ -37,7 +37,7 @@ export async function show(options = defaultOptions): Promise<void> {
state.previousPopupShowCallback = previousPopupShowCallback;
const { quotes } = await Misc.getQuotes(Config.language);
const { quotes } = await QuotesController.getQuotes(Config.language);
state.quoteToReport = quotes.find((quote) => {
return quote.id === quoteId;
});

View file

@ -6,7 +6,6 @@ import * as Notifications from "../elements/notifications";
import * as QuoteSubmitPopup from "./quote-submit-popup";
import * as QuoteApprovePopup from "./quote-approve-popup";
import * as QuoteReportPopup from "./quote-report-popup";
import * as Misc from "../utils/misc";
import {
buildSearchService,
SearchService,
@ -14,6 +13,7 @@ import {
} from "../utils/search-service";
import { debounce } from "../utils/debounce";
import { splitByAndKeep } from "../utils/strings";
import QuotesController from "../controllers/quotes-controller";
export let selectedId = 1;
@ -55,7 +55,7 @@ function highlightMatches(text: string, matchedText: string[]): string {
}
async function updateResults(searchText: string): Promise<void> {
const { quotes } = await Misc.getQuotes(Config.language);
const { quotes } = await QuotesController.getQuotes(Config.language);
const quoteSearchService = getSearchService<MonkeyTypes.Quote>(
Config.language,

View file

@ -3,6 +3,7 @@ import * as TestUI from "./test-ui";
import * as ManualRestart from "./manual-restart-tracker";
import Config, * as UpdateConfig from "../config";
import * as Misc from "../utils/misc";
import QuotesController from "../controllers/quotes-controller";
import * as Notifications from "../elements/notifications";
import * as CustomText from "./custom-text";
import * as TestStats from "./test-stats";
@ -881,12 +882,13 @@ export async function init(): Promise<void> {
}
}
}
} else if (Config.mode == "quote") {
// setLanguage(Config.language.replace(/_\d*k$/g, ""), true);
} else if (Config.mode === "quote") {
const quotesCollection = await QuotesController.getQuotes(
Config.language,
Config.quoteLength
);
const quotes = await Misc.getQuotes(Config.language.replace(/_\d*k$/g, ""));
if (quotes.length === 0) {
if (quotesCollection.length === 0) {
TestUI.setTestRestarting(false);
Notifications.add(
`No ${Config.language.replace(/_\d*k$/g, "")} quotes found`,
@ -902,49 +904,24 @@ export async function init(): Promise<void> {
let rq: MonkeyTypes.Quote | undefined = undefined;
if (Config.quoteLength.includes(-2) && Config.quoteLength.length == 1) {
quotes.groups.forEach((group) => {
const filtered = (<MonkeyTypes.Quote[]>group).filter(
(quote) => quote.id == QuoteSearchPopup.selectedId
);
if (filtered.length > 0) {
rq = filtered[0];
}
});
if (rq === undefined) {
rq = <MonkeyTypes.Quote>quotes.groups[0][0];
const targetQuote = QuotesController.getQuoteById(
QuoteSearchPopup.selectedId
);
if (targetQuote === undefined) {
rq = <MonkeyTypes.Quote>quotesCollection.groups[0][0];
Notifications.add("Quote Id Does Not Exist", 0);
} else {
rq = targetQuote;
}
} else {
const quoteLengths = Config.quoteLength;
let groupIndex;
if (quoteLengths.length > 1) {
groupIndex =
quoteLengths[Math.floor(Math.random() * quoteLengths.length)];
while (quotes.groups[groupIndex].length === 0) {
groupIndex =
quoteLengths[Math.floor(Math.random() * quoteLengths.length)];
}
} else {
groupIndex = quoteLengths[0];
if (quotes.groups[groupIndex].length === 0) {
Notifications.add("No quotes found for selected quote length", 0);
TestUI.setTestRestarting(false);
return;
}
const randomQuote = QuotesController.getRandomQuote();
if (randomQuote === null) {
Notifications.add("No quotes found for selected quote length", 0);
TestUI.setTestRestarting(false);
return;
}
rq = quotes.groups[groupIndex][
Math.floor(Math.random() * quotes.groups[groupIndex].length)
] as MonkeyTypes.Quote;
if (
TestWords.randomQuote != null &&
typeof rq !== "number" &&
rq.id === TestWords.randomQuote.id
) {
rq = quotes.groups[groupIndex][
Math.floor(Math.random() * quotes.groups[groupIndex].length)
] as MonkeyTypes.Quote;
}
rq = randomQuote;
}
if (rq === undefined) return;

View file

@ -57,6 +57,7 @@ class Words {
}
}
}
export const words = new Words();
export let hasTab = false;
export let randomQuote = null as unknown as MonkeyTypes.Quote;

View file

@ -132,60 +132,6 @@ export async function getFunbox(
});
}
type QuoteCollection = {
quotes: MonkeyTypes.Quote[];
length?: number;
language?: string;
groups: number[][] | MonkeyTypes.Quote[][];
};
let quotes: QuoteCollection;
export async function getQuotes(language: string): Promise<QuoteCollection> {
if (
quotes === undefined ||
quotes.language !== language.replace(/_\d*k$/g, "")
) {
Loader.show();
try {
const data: QuoteCollection = await $.getJSON(`quotes/${language}.json`);
Loader.hide();
if (data.quotes === undefined || data.quotes.length === 0) {
quotes = {
quotes: [],
length: 0,
groups: [],
};
return quotes;
}
quotes = data;
quotes.length = data.quotes.length;
quotes.groups?.forEach((qg, i) => {
const lower = qg[0];
const upper = qg[1];
quotes.groups[i] = quotes.quotes.filter((q) => {
if (q.length >= lower && q.length <= upper) {
q.group = i;
return true;
} else {
return false;
}
});
});
return quotes;
} catch {
Loader.hide();
quotes = {
quotes: [],
length: 0,
groups: [],
};
return quotes;
}
} else {
return quotes;
}
}
let layoutsList: MonkeyTypes.Layouts = {};
export async function getLayoutsList(): Promise<MonkeyTypes.Layouts> {
if (Object.keys(layoutsList).length === 0) {
@ -1025,3 +971,29 @@ export async function downloadResultsCSV(
link.remove();
Loader.hide();
}
/**
* Gets an integer between min and max, both are inclusive.
* @param min
* @param max
* @returns Random integer betwen min and max.
*/
export function randomIntFromRange(min: number, max: number): number {
const minNorm = Math.ceil(min);
const maxNorm = Math.floor(max);
return Math.floor(Math.random() * (maxNorm - minNorm + 1) + minNorm);
}
/**
* Shuffle an array of elements using the FisherYates algorithm.
* This function mutates the input array.
* @param elements
*/
export function shuffle<T>(elements: T[]): void {
for (let i = elements.length - 1; i > 0; --i) {
const j = randomIntFromRange(0, i);
const temp = elements[j];
elements[j] = elements[i];
elements[i] = temp;
}
}

View file

@ -4179,7 +4179,7 @@
</div>
</div>
</div>
<div class="section apeKeys needsAccount">
<div class="section apeKeys needsAccount hidden">
<h1>ape keys</h1>
<div class="text">
Generate Ape Keys to access certain API endpoints.

View file

@ -621,7 +621,7 @@
"keys": {
"row1": ["ॊऒ", "1ऍ", "2ॅ", "3", "4", "5", "6", "7", "8", "9(", "0)", "-", "ऋृ"],
"row2": ["ौऔ", "ैऐ", "ाआ", "ीई", "ूऊ", "बभ", "हङ", "गघ", "दध", "जझ", "डढ", "़ञ", "ॉऑ"],
"row3": ["ोओ", "ेए", "्अ", "िइ", "ुउ", "पफ", "रऱ", "कख", "તથ", "ચછ", "टठ"],
"row3": ["ोओ", "ेए", "्अ", "िइ", "ुउ", "पफ", "रऱ", "कख", "तथ", "चछ", "टठ"],
"row4": ["ॆऎ", "ंँ", "मण", "न", "व", "लळ", "सश", ",ष", ".।", "यय़"],
"row5": [" "]
}

View file

@ -34796,15 +34796,15 @@
"id": 5903
},
{
"text": "He gazed up at the enormous face. Forty years it had taken him to learn what kind of smile was hidden beneath the dark moustache. O cruel, needless misunderstanding! O stubborn, self-willed exile from the loving breast!",
"text": "He gazed up at the enormous face. Forty years it had taken him to learn what kind of smile was hidden beneath the dark moustache. O cruel, needless misunderstanding! O stubborn, self-willed exile from the loving breast! But it was all right, everything was all right, the struggle was finished. He had won the victory over himself. He loved Big Brother.",
"source": "Nineteen Eighty-Four",
"length": 219,
"length": 353,
"id": 5904
},
{
"text": "But it was all right, everything was all right, the struggle was finished. He had won the victory over himself. He loved Big Brother.",
"source": "Nineteen Eighty-Four",
"length": 133,
"text": "He put his hands in his coat pockets and turned back eagerly to his scrutiny of the house, as though my presence marred the sacredness of the vigil. So I walked away and left him standing there in the moonlight - watching over nothing.",
"source": "The Great Gatsby",
"length": 236,
"id": 5905
},
{