checking if result funboxes are unique

checking if result funboxes are compatible with each other
This commit is contained in:
Miodec 2023-06-05 13:11:16 +02:00
parent f8f80fbeb0
commit 2e7179df8e
2 changed files with 168 additions and 6 deletions

View file

@ -20,7 +20,7 @@ import Logger from "../../utils/logger";
import "dotenv/config";
import { MonkeyResponse } from "../../utils/monkey-response";
import MonkeyError from "../../utils/error";
import { isTestTooShort } from "../../utils/validation";
import { areFunboxesCompatible, isTestTooShort } from "../../utils/validation";
import {
implemented as anticheatImplemented,
validateResult,
@ -36,7 +36,7 @@ import { getDailyLeaderboard } from "../../utils/daily-leaderboards";
import AutoRoleList from "../../constants/auto-roles";
import * as UserDAL from "../../dal/user";
import { buildMonkeyMail } from "../../utils/monkey-mail";
import FunboxesMetadata from "../../constants/funbox";
import FunboxList from "../../constants/funbox-list";
import _ from "lodash";
import * as WeeklyXpLeaderboard from "../../services/weekly-xp-leaderboard";
import { UAParser } from "ua-parser-js";
@ -175,6 +175,17 @@ export async function addResult(
}
}
if (result.funbox) {
const funboxes = result.funbox.split("#");
if (funboxes.length !== _.uniq(funboxes).length) {
throw new MonkeyError(400, "Duplicate funboxes");
}
}
if (!areFunboxesCompatible(result.funbox)) {
throw new MonkeyError(400, "Impossible funbox combination");
}
try {
result.keySpacingStats = {
average:
@ -625,9 +636,8 @@ async function calculateXp(
}
if (funboxBonusConfiguration > 0) {
const resultFunboxes = _.uniq(funbox.split("#"));
const funboxModifier = _.sumBy(resultFunboxes, (funboxName) => {
const funbox = FunboxesMetadata[funboxName as string];
const funboxModifier = _.sumBy(funbox.split("#"), (funboxName) => {
const funbox = FunboxList.find((f) => f.name === funboxName);
const difficultyLevel = funbox?.difficultyLevel ?? 0;
return Math.max(difficultyLevel * funboxBonusConfiguration, 0);
});

View file

@ -1,7 +1,8 @@
import _ from "lodash";
import { replaceHomoglyphs } from "../constants/homoglyphs";
import { profanities, regexProfanities } from "../constants/profanities";
import { matchesAPattern, sanitizeString } from "./misc";
import { intersect, matchesAPattern, sanitizeString } from "./misc";
import { default as FunboxList } from "../constants/funbox-list";
export function inRange(value: number, min: number, max: number): boolean {
return value >= min && value <= max;
@ -105,3 +106,154 @@ export function isTestTooShort(result: MonkeyTypes.CompletedEvent): boolean {
return false;
}
export function areFunboxesCompatible(funboxesString: string): boolean {
const funboxes = funboxesString.split("#").filter((f) => f !== "none");
const funboxesToCheck = FunboxList.filter((f) => funboxes.includes(f.name));
console.log(funboxesToCheck);
console.log(funboxes);
const allFunboxesAreValid = funboxesToCheck.length === funboxes.length;
const oneWordModifierMax =
funboxesToCheck.filter(
(f) =>
f.frontendFunctions?.includes("getWord") ||
f.frontendFunctions?.includes("pullSection") ||
f.frontendFunctions?.includes("withWords")
).length <= 1;
const layoutUsability =
funboxesToCheck.filter((f) =>
f.properties?.find((fp) => fp === "changesLayout")
).length === 0 ||
funboxesToCheck.filter((f) =>
f.properties?.find((fp) => fp === "ignoresLayout" || fp === "usesLayout")
).length === 0;
const oneNospaceOrToPushMax =
funboxesToCheck.filter((f) =>
f.properties?.find((fp) => fp === "nospace" || fp.startsWith("toPush"))
).length <= 1;
const oneChangesWordsVisibilityMax =
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 ||
funboxesToCheck.filter((f) =>
f.properties?.find((fp) => fp === "changesCapitalisation")
).length === 0;
const noConflictsWithSymmetricChars =
funboxesToCheck.filter((f) =>
f.properties?.find((fp) => fp === "conflictsWithSymmetricChars")
).length === 0 ||
funboxesToCheck.filter((f) =>
f.properties?.find((fp) => fp === "symmetricChars")
).length === 0;
const canSpeak =
funboxesToCheck.filter((f) =>
f.properties?.find((fp) => fp === "speaks" || fp === "unspeakable")
).length <= 1;
const hasLanguageToSpeak =
funboxesToCheck.filter((f) => f.properties?.find((fp) => fp === "speaks"))
.length === 0 ||
funboxesToCheck.filter((f) =>
f.properties?.find((fp) => fp === "ignoresLanguage")
).length === 0;
const oneToPushOrPullSectionMax =
funboxesToCheck.filter(
(f) =>
f.properties?.find((fp) => fp.startsWith("toPush:")) ||
f.frontendFunctions?.includes("pullSection")
).length <= 1;
const oneApplyCSSMax =
funboxesToCheck.filter((f) => f.frontendFunctions?.includes("applyCSS"))
.length <= 1;
const onePunctuateWordMax =
funboxesToCheck.filter((f) =>
f.frontendFunctions?.includes("punctuateWord")
).length <= 1;
const oneCharCheckerMax =
funboxesToCheck.filter((f) =>
f.frontendFunctions?.includes("isCharCorrect")
).length <= 1;
const oneCharReplacerMax =
funboxesToCheck.filter((f) => f.frontendFunctions?.includes("getWordHtml"))
.length <= 1;
const allowedConfig = {} as Record<string, string[] | boolean[]>;
let noConfigConflicts = true;
for (const f of funboxesToCheck) {
if (!f.frontendForcedConfig) continue;
for (const key in f.frontendForcedConfig) {
if (allowedConfig[key]) {
if (
intersect<string | boolean>(
allowedConfig[key],
f.frontendForcedConfig[key],
true
).length === 0
) {
noConfigConflicts = false;
break;
}
} else {
allowedConfig[key] = f.frontendForcedConfig[key];
}
}
}
console.log(allowedConfig);
console.log(
allFunboxesAreValid,
oneWordModifierMax,
layoutUsability,
oneNospaceOrToPushMax,
oneChangesWordsVisibilityMax,
oneFrequencyChangesMax,
noFrequencyChangesConflicts,
capitalisationChangePosibility,
noConflictsWithSymmetricChars,
canSpeak,
hasLanguageToSpeak,
oneToPushOrPullSectionMax,
oneApplyCSSMax,
onePunctuateWordMax,
oneCharCheckerMax,
oneCharReplacerMax,
noConfigConflicts
);
return (
allFunboxesAreValid &&
oneWordModifierMax &&
layoutUsability &&
oneNospaceOrToPushMax &&
oneChangesWordsVisibilityMax &&
oneFrequencyChangesMax &&
noFrequencyChangesConflicts &&
capitalisationChangePosibility &&
noConflictsWithSymmetricChars &&
canSpeak &&
hasLanguageToSpeak &&
oneToPushOrPullSectionMax &&
oneApplyCSSMax &&
onePunctuateWordMax &&
oneCharCheckerMax &&
oneCharReplacerMax &&
noConfigConflicts
);
}