mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-10-08 22:50:00 +08:00
added zipf funbox
This commit is contained in:
parent
e36c57c047
commit
6ed5a9422d
9 changed files with 78 additions and 10 deletions
|
@ -123,6 +123,10 @@ const Funboxes: Record<string, MonkeyTypes.FunboxMetadata> = {
|
|||
canGetPb: false,
|
||||
difficultyLevel: 1,
|
||||
},
|
||||
zipf: {
|
||||
canGetPb: false,
|
||||
difficultyLevel: 1,
|
||||
},
|
||||
};
|
||||
|
||||
export default Funboxes;
|
||||
|
|
|
@ -214,6 +214,12 @@ const list: MonkeyTypes.FunboxMetadata[] = [
|
|||
punctuation: [false],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "zipf",
|
||||
alias: "frequency",
|
||||
info: "Words are generated according to Zipf's law. (not all languages will produce Zipfy results, use with caution)",
|
||||
properties: ["changesWordsFrequency"],
|
||||
},
|
||||
];
|
||||
|
||||
export function getAll(): MonkeyTypes.FunboxMetadata[] {
|
||||
|
|
|
@ -98,7 +98,8 @@ export function canSetConfigWithCurrentFunboxes(
|
|||
f.properties?.find((fp) => fp.startsWith("toPush:")) ||
|
||||
f.properties?.includes("changesWordsVisibility") ||
|
||||
f.properties?.includes("speaks") ||
|
||||
f.properties?.includes("changesLayout")
|
||||
f.properties?.includes("changesLayout") ||
|
||||
f.properties?.includes("changesWordsFrequency")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -108,7 +109,8 @@ export function canSetConfigWithCurrentFunboxes(
|
|||
(f) =>
|
||||
f.functions?.getWord ||
|
||||
f.functions?.pullSection ||
|
||||
f.functions?.withWords
|
||||
f.functions?.withWords ||
|
||||
f.properties?.includes("changesWordsFrequency")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -222,6 +224,17 @@ export function areFunboxesCompatible(
|
|||
funboxesToCheck.filter((f) =>
|
||||
f.properties?.find((fp) => fp == "changesWordsVisibility")
|
||||
).length <= 1;
|
||||
const oneFrequencyChangesMax =
|
||||
funboxesToCheck.filter((f) =>
|
||||
f.properties?.find((fp) => fp == "changesWordsFrequency")
|
||||
).length <= 1;
|
||||
const noFrequencyChangesConflicts =
|
||||
funboxesToCheck.filter((f) =>
|
||||
f.properties?.find((fp) => fp == "changesWordsFrequency")
|
||||
).length == 0 ||
|
||||
funboxesToCheck.filter((f) =>
|
||||
f.properties?.find((fp) => fp == "ignoresLanguage")
|
||||
).length == 0;
|
||||
const capitalisationChangePosibility =
|
||||
funboxesToCheck.filter((f) => f.properties?.find((fp) => fp == "noLetters"))
|
||||
.length == 0 ||
|
||||
|
@ -284,6 +297,8 @@ export function areFunboxesCompatible(
|
|||
layoutUsability &&
|
||||
oneNospaceOrToPushMax &&
|
||||
oneChangesWordsVisibilityMax &&
|
||||
oneFrequencyChangesMax &&
|
||||
noFrequencyChangesConflicts &&
|
||||
capitalisationChangePosibility &&
|
||||
noConflictsWithSymmetricChars &&
|
||||
canSpeak &&
|
||||
|
|
|
@ -526,6 +526,12 @@ FunboxList.setFunboxFunctions("binary", {
|
|||
},
|
||||
});
|
||||
|
||||
FunboxList.setFunboxFunctions("zipf", {
|
||||
getWordsFrequencyMode(): MonkeyTypes.FunboxWordsFrequency {
|
||||
return "zipf";
|
||||
},
|
||||
});
|
||||
|
||||
export function toggleScript(...params: string[]): void {
|
||||
FunboxList.get(Config.funbox).forEach((funbox) => {
|
||||
if (funbox.functions?.toggleScript) funbox.functions.toggleScript(params);
|
||||
|
|
|
@ -677,6 +677,18 @@ export function restart(options = {} as RestartOptions): void {
|
|||
);
|
||||
}
|
||||
|
||||
function getFunboxWordsFrequency():
|
||||
| MonkeyTypes.FunboxWordsFrequency
|
||||
| undefined {
|
||||
const wordFunbox = FunboxList.get(Config.funbox).find(
|
||||
(f) => f.functions?.getWordsFrequencyMode
|
||||
);
|
||||
if (wordFunbox?.functions?.getWordsFrequencyMode) {
|
||||
return wordFunbox.functions.getWordsFrequencyMode();
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getFunboxWord(word: string, wordset?: Misc.Wordset): string {
|
||||
const wordFunbox = FunboxList.get(Config.funbox).find(
|
||||
(f) => f.functions?.getWord
|
||||
|
@ -718,7 +730,9 @@ async function getNextWord(
|
|||
language: MonkeyTypes.LanguageObject,
|
||||
wordsBound: number
|
||||
): Promise<string> {
|
||||
let randomWord = wordset.randomWord();
|
||||
const funboxFrequency = getFunboxWordsFrequency() ?? "normal";
|
||||
|
||||
let randomWord = wordset.randomWord(funboxFrequency);
|
||||
const previousWord = TestWords.words.get(TestWords.words.length - 1, true);
|
||||
const previousWord2 = TestWords.words.get(TestWords.words.length - 2, true);
|
||||
if (Config.mode === "quote") {
|
||||
|
@ -735,7 +749,7 @@ async function getNextWord(
|
|||
(CustomText.isWordRandom || CustomText.isTimeRandom) &&
|
||||
(wordset.length < 4 || PractiseWords.before.mode !== null)
|
||||
) {
|
||||
randomWord = wordset.randomWord();
|
||||
randomWord = wordset.randomWord(funboxFrequency);
|
||||
} else {
|
||||
let regenarationCount = 0; //infinite loop emergency stop button
|
||||
while (
|
||||
|
@ -754,12 +768,12 @@ async function getNextWord(
|
|||
/[0-9]/i.test(randomWord)))
|
||||
) {
|
||||
regenarationCount++;
|
||||
randomWord = wordset.randomWord();
|
||||
randomWord = wordset.randomWord(funboxFrequency);
|
||||
}
|
||||
}
|
||||
|
||||
if (randomWord === undefined) {
|
||||
randomWord = wordset.randomWord();
|
||||
randomWord = wordset.randomWord(funboxFrequency);
|
||||
}
|
||||
|
||||
if (
|
||||
|
|
|
@ -63,7 +63,7 @@ export function getWord(wordset: Wordset): string {
|
|||
let highScore;
|
||||
let randomWord = "";
|
||||
for (let i = 0; i < wordSamples; i++) {
|
||||
const newWord = wordset.randomWord();
|
||||
const newWord = wordset.randomWord("normal");
|
||||
const newScore = score(newWord);
|
||||
if (i == 0 || highScore === undefined || newScore > highScore) {
|
||||
randomWord = newWord;
|
||||
|
|
6
frontend/src/ts/types/types.d.ts
vendored
6
frontend/src/ts/types/types.d.ts
vendored
|
@ -187,6 +187,8 @@ declare namespace MonkeyTypes {
|
|||
display?: string;
|
||||
}
|
||||
|
||||
type FunboxWordsFrequency = "normal" | "zipf";
|
||||
|
||||
type FunboxProperty =
|
||||
| "symmetricChars"
|
||||
| "conflictsWithSymmetricChars"
|
||||
|
@ -202,7 +204,8 @@ declare namespace MonkeyTypes {
|
|||
| "changesCapitalisation"
|
||||
| "nospace"
|
||||
| `toPush:${number}`
|
||||
| "noInfiniteDuration";
|
||||
| "noInfiniteDuration"
|
||||
| "changesWordsFrequency";
|
||||
|
||||
interface FunboxFunctions {
|
||||
getWord?: (wordset?: Misc.Wordset) => string;
|
||||
|
@ -227,6 +230,7 @@ declare namespace MonkeyTypes {
|
|||
start?: () => void;
|
||||
restart?: () => void;
|
||||
getWordHtml?: (char: string, letterTag?: boolean) => string;
|
||||
getWordsFrequencyMode?: () => FunboxWordsFrequency;
|
||||
}
|
||||
|
||||
interface FunboxForcedConfig {
|
||||
|
|
|
@ -1309,8 +1309,12 @@ export class Wordset {
|
|||
this.length = this.words.length;
|
||||
}
|
||||
|
||||
public randomWord(): string {
|
||||
return randomElementFromArray(this.words);
|
||||
public randomWord(mode: MonkeyTypes.FunboxWordsFrequency): string {
|
||||
if (mode === "zipf") {
|
||||
return this.words[dreymarIndex(this.words.length)];
|
||||
} else {
|
||||
return randomElementFromArray(this.words);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1388,3 +1392,13 @@ export function getBinary(): string {
|
|||
const ret = Math.floor(Math.random() * 256).toString(2);
|
||||
return ret.padStart(8, "0");
|
||||
}
|
||||
|
||||
export function dreymarIndex(arrayLength: number): number {
|
||||
const n = arrayLength;
|
||||
const g = 0.5772156649;
|
||||
const M = Math.log(n) + g;
|
||||
const r = Math.random();
|
||||
const h = Math.exp(r * M - g);
|
||||
const W = Math.ceil(h);
|
||||
return W - 1;
|
||||
}
|
||||
|
|
|
@ -155,5 +155,10 @@
|
|||
"name": "binary",
|
||||
"info": "01000010 01100101 01100101 01110000 00100000 01100010 01101111 01101111 01110000 00101110",
|
||||
"canGetPb": false
|
||||
},
|
||||
{
|
||||
"name": "zipf",
|
||||
"info": "Words are generated according to Zipf's law. (not all languages will produce Zipfy results, use with caution)",
|
||||
"canGetPb": false
|
||||
}
|
||||
]
|
||||
|
|
Loading…
Add table
Reference in a new issue