diff --git a/package.json b/package.json index 2738666..f00c725 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "@formkit/auto-animate": "^1.0.0-beta.1", "@fortawesome/fontawesome-free": "^5.15.4", "@lingdocs/lingdocs-main": "^0.3.3", - "@lingdocs/ps-react": "^5.3.3", + "@lingdocs/ps-react": "^5.4.1", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", diff --git a/src/games/games.tsx b/src/games/games.tsx index 73a90f1..20d9c88 100644 --- a/src/games/games.tsx +++ b/src/games/games.tsx @@ -427,6 +427,13 @@ export const npWithAdjectivesNoHints = makeGameRecord({ level: "no-hints", SubCore: NPAdjWriting, }); +export const npWithAdjectivesInSandwiches = makeGameRecord({ + title: "Write the adjective and noun togehter in sandwiches 🥪", + id: "adjective-nps-in-sandwiches", + link: "/phrase-structure/ap/#sandwich-", + level: "sandwiches", + SubCore: NPAdjWriting, +}); const games: { chapter: string, items: GameRecord[] }[] = [ { @@ -512,6 +519,7 @@ const games: { chapter: string, items: GameRecord[] }[] = [ epWithAdjectives, npWithAdjectivesHints, npWithAdjectivesNoHints, + npWithAdjectivesInSandwiches, ], }, ]; diff --git a/src/games/sub-cores/NPAdjGame.tsx b/src/games/sub-cores/NPAdjGame.tsx index 4240bfd..f0349fb 100644 --- a/src/games/sub-cores/NPAdjGame.tsx +++ b/src/games/sub-cores/NPAdjGame.tsx @@ -3,6 +3,11 @@ import { Types as T, renderNPSelection, getEnglishFromRendered, + randFromArray, + getPashtoFromRendered, + renderAPSelection, + InlinePs, + defaultTextOptions as opts, concatPsString, } from "@lingdocs/ps-react"; import { makeNPAdjGenerator } from "../../lib/np-adj-generator"; @@ -14,12 +19,82 @@ const amount = 15; const timeLimit = 230; type Question = { - selection: T.NPSelection, + selection: T.NPSelection | T.APSelection, answer: T.PsString[], english: string, }; -type Level = "hints" | "no-hints"; +type Level = "hints" | "no-hints" | "sandwiches"; + +export const sandwiches: T.Sandwich[] = [ + { + type: "sandwich", + before: { p: "له", f: "la" }, + after: { p: "نه", f: "na" }, + e: "from", + }, + { + type: "sandwich", + before: { p: "له", f: "la" }, + after: { p: "څخه", f: "tsuxa" }, + e: "from", + }, + { + type: "sandwich", + before: { p: "له", f: "la" }, + after: { p: "سره", f: "sara" }, + e: "with", + }, + { + type: "sandwich", + before: undefined, + after: { p: "ته", f: "ta" }, + e: "to", + }, + { + type: "sandwich", + before: { p: "د", f: "du" }, + after: { p: "لپاره", f: "lapaara" }, + e: "for", + }, + { + type: "sandwich", + before: { p: "د", f: "du" }, + after: { p: "په څانګ", f: "pu tsaang" }, + e: "beside", + }, + // { + // type: "sandwich", + // before: { p: "په", f: "pu" }, + // after: { p: "کې", f: "ke" }, + // e: "in", + // }, + { + type: "sandwich", + before: { p: "د", f: "du" }, + after: { p: "لاندې", f: "laande" }, + e: "under", + }, + { + type: "sandwich", + before: { p: "د", f: "du" }, + after: { p: "په شان", f: "pu shaan" }, + e: "like", + }, + { + type: "sandwich", + before: { p: "د", f: "du" }, + after: { p: "غوندې", f: "ghwunde" }, + e: "like", + }, + // { + // type: "sandwich", + // before: { p: "د", f: "du" }, + // after: { p: "په اړه", f: "pu aRa" }, + // e: "about", + // }, +]; + // LEVELS // - without plurals @@ -35,18 +110,20 @@ const NPAdjWriting: GameSubCore = ({ inChapter, id, link, level }: { function getQuestion(): Question { const np = npPool(); - const rendered = renderNPSelection(np, false, false, "subject", "none", false); - const renderedAdj: T.Rendered | undefined = rendered.selection.adjectives && rendered.selection.adjectives[0]; - if (!renderedAdj) { - throw new Error("error getting rendered adjective"); - } - const answer = renderedAdj.ps.flatMap((adjPs) => ( - rendered.selection.ps.map((nounPs) => ( - concatPsString(adjPs, " ", nounPs) - )) - )); + const selection: T.NPSelection | T.APSelection = level === "sandwiches" + ? { + type: "AP", + selection: { + ...randFromArray(sandwiches), + inside: np, + }, + } : np; + const rendered: T.Rendered | T.Rendered = selection.type === "AP" + ? renderAPSelection(selection, 0) // WOULD BE CLEANER IF THIS WAS JUST A PURE SANDWICH, NOT AT AP + : renderNPSelection(np, false, false, "subject", "none", false); + const answer = getPashtoFromRendered(rendered, false); return { - selection: np, + selection, answer, english: getEnglishFromRendered(rendered) || "ERROR", }; @@ -62,20 +139,29 @@ const NPAdjWriting: GameSubCore = ({ inChapter, id, link, level }: { } callback(correct); } - if (question.selection.type !== "NP" || question.selection.selection.type !== "noun") { - throw new Error("QUESTION ERROR"); + if (!( + (question.selection.type === "AP" && question.selection.selection.type === "sandwich" && question.selection.selection.inside.selection.type === "noun") + || + (question.selection.type === "NP" && question.selection.selection.type === "noun") + )) { + throw new Error("QUESTION ERROR - BAD SELECTION") } - const nounEntry = question.selection.selection.entry; - const adjEntry: T.AdjectiveEntry | undefined = question.selection.selection.adjectives[0]?.entry; + const nounSelection: T.NounSelection = question.selection.type === "AP" + ? question.selection.selection.inside.selection as T.NounSelection // ts being dumb + : question.selection.selection; + const adjEntry: T.AdjectiveEntry | undefined = nounSelection.adjectives[0]?.entry; if (!adjEntry) { throw new Error("QUESTION ERROR - MISSING ADJECTIVE"); } const handleInput = ({ target: { value }}: React.ChangeEvent) => { setAnswer(value); } + const sandwich = question.selection.type === "AP" + ? question.selection.selection + : undefined; return
-
+
= ({ inChapter, id, link, level }: { />
+ {sandwich &&
+ + {concatPsString(sandwich.before, " ... ", sandwich.after)} + +
}
{question.english}
@@ -113,7 +204,7 @@ const NPAdjWriting: GameSubCore = ({ inChapter, id, link, level }: { function Instructions() { return
-

Write the adjective and noun together with the proper inflections.

+

Write the {level === "sandwiches" ? "sandwich including the" : ""} adjective and noun together with the proper inflections.

} diff --git a/src/lib/game-utils.ts b/src/lib/game-utils.ts index 1139f9d..362b8d3 100644 --- a/src/lib/game-utils.ts +++ b/src/lib/game-utils.ts @@ -29,7 +29,10 @@ export function compareF(input: string, answer: string): boolean { } export function comparePs(inputRaw: string, answer: T.SingleOrLengthOpts): boolean { - const input = inputRaw.replace(/\s+/g, " "); + function cleanSpaces(s: string): string { + return s.replace(/\s+/g, " "); + } + const input = cleanSpaces(inputRaw); if ("long" in answer) { return comparePs(input, flattenLengths(answer)); } @@ -39,5 +42,5 @@ export function comparePs(inputRaw: string, answer: T.SingleOrLengthOpts