feat(minigames): format OPORD Recall grids Arma style as 034-672
This commit is contained in:
parent
3daa7a3601
commit
4594912325
1 changed files with 24 additions and 15 deletions
|
|
@ -188,7 +188,7 @@ export interface OpordScenario {
|
||||||
readonly operationName: string;
|
readonly operationName: string;
|
||||||
/** e.g. "TRIDENT" */
|
/** e.g. "TRIDENT" */
|
||||||
readonly objective: string;
|
readonly objective: string;
|
||||||
/** Eight-digit grid as digits only, e.g. "03467219". */
|
/** Six-digit grid as digits only, e.g. "034672". */
|
||||||
readonly grid: string;
|
readonly grid: string;
|
||||||
/** Three-digit degrees, e.g. 47. */
|
/** Three-digit degrees, e.g. 47. */
|
||||||
readonly azimuth: number;
|
readonly azimuth: number;
|
||||||
|
|
@ -217,9 +217,9 @@ export interface OpordScenario {
|
||||||
readonly enRouteMin: number;
|
readonly enRouteMin: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Formats an 8-digit grid as two 4-digit halves, e.g. "0346 7219". */
|
/** Formats a 6-digit grid Arma map style: three digits, hyphen, three digits, e.g. "034-672". */
|
||||||
export function formatOpordGrid(grid: string): string {
|
export function formatOpordGrid(grid: string): string {
|
||||||
return grid.length === 8 ? `${grid.slice(0, 4)} ${grid.slice(4)}` : grid;
|
return grid.length === 6 ? `${grid.slice(0, 3)}-${grid.slice(3)}` : grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Buckets a 1-359 azimuth onto the eight winds; 359 and 1 both resolve to NORTH. */
|
/** Buckets a 1-359 azimuth onto the eight winds; 359 and 1 both resolve to NORTH. */
|
||||||
|
|
@ -231,7 +231,7 @@ export function generateOpordScenario(seed: number): OpordScenario {
|
||||||
const rng = mulberry32(seed);
|
const rng = mulberry32(seed);
|
||||||
const operationName = `${pick(rng, OPERATION_ADJECTIVES)} ${pick(rng, OPERATION_NOUNS)}`;
|
const operationName = `${pick(rng, OPERATION_ADJECTIVES)} ${pick(rng, OPERATION_NOUNS)}`;
|
||||||
const objective = pick(rng, OBJECTIVE_NAMES);
|
const objective = pick(rng, OBJECTIVE_NAMES);
|
||||||
const grid = Array.from({ length: 8 }, () => Math.floor(rng() * 10)).join("");
|
const grid = Array.from({ length: 6 }, () => Math.floor(rng() * 10)).join("");
|
||||||
const azimuth = pickInt(rng, 1, 359);
|
const azimuth = pickInt(rng, 1, 359);
|
||||||
const distanceKm = pickInt(rng, 4, 24);
|
const distanceKm = pickInt(rng, 4, 24);
|
||||||
const hHourMinutes = pickInt(rng, 0, 23) * 100 + pick(rng, [0, 15, 30, 45]);
|
const hHourMinutes = pickInt(rng, 0, 23) * 100 + pick(rng, [0, 15, 30, 45]);
|
||||||
|
|
@ -327,22 +327,31 @@ export function buildOpordQuestions(
|
||||||
CODEWORDS.filter((word) => word !== scenario.codeword && word !== scenario.abortCodeword),
|
CODEWORDS.filter((word) => word !== scenario.codeword && word !== scenario.abortCodeword),
|
||||||
).slice(0, 3);
|
).slice(0, 3);
|
||||||
|
|
||||||
|
const gridVariants = [
|
||||||
|
scenario.grid.split("").reverse().join(""),
|
||||||
|
scenario.grid.slice(3) + scenario.grid.slice(0, 3),
|
||||||
|
scenario.grid
|
||||||
|
.split("")
|
||||||
|
.map((digit) => String((Number(digit) + 1) % 10))
|
||||||
|
.join(""),
|
||||||
|
scenario.grid
|
||||||
|
.split("")
|
||||||
|
.map((digit) => String((Number(digit) + 2) % 10))
|
||||||
|
.join(""),
|
||||||
|
];
|
||||||
|
// A palindrome or half-repeating grid collapses one variant onto the answer;
|
||||||
|
// dedupe first so the question always shows four distinct options.
|
||||||
|
const gridDistractors = gridVariants
|
||||||
|
.filter((value, index) => value !== scenario.grid && gridVariants.indexOf(value) === index)
|
||||||
|
.slice(0, 3);
|
||||||
|
|
||||||
const gridBuilder = () =>
|
const gridBuilder = () =>
|
||||||
// The objective grid is the core skill: always asked first.
|
// The objective grid is the core skill: always asked first.
|
||||||
choiceQuestion(
|
choiceQuestion(
|
||||||
"grid",
|
"grid",
|
||||||
"What is the 8-digit grid of the objective?",
|
"What is the 6-digit grid of the objective?",
|
||||||
formatOpordGrid(scenario.grid),
|
formatOpordGrid(scenario.grid),
|
||||||
[
|
gridDistractors.map((value) => formatOpordGrid(value)),
|
||||||
formatOpordGrid(scenario.grid.split("").reverse().join("")),
|
|
||||||
formatOpordGrid(scenario.grid.slice(4) + scenario.grid.slice(0, 4)),
|
|
||||||
formatOpordGrid(
|
|
||||||
scenario.grid
|
|
||||||
.split("")
|
|
||||||
.map((digit) => String((Number(digit) + 1) % 10))
|
|
||||||
.join(""),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
rng,
|
rng,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue