Add 'Return Tiles' button
This commit is contained in:
parent
ca5ab097c5
commit
e8cff060b0
2 changed files with 57 additions and 42 deletions
|
@ -2,7 +2,7 @@ import * as React from "react";
|
|||
import {GameWasm, Letter as LetterData, MyResult, PlayedTile, PlayerAndScore, Tray, WordResult} from "word_grid";
|
||||
import {ChangeEvent, JSX, useEffect, useMemo, useReducer, useRef, useState} from "react";
|
||||
import {Modal} from "./Modal";
|
||||
import {addNTimes} from "./utils";
|
||||
import {addNTimes, mergeTrays} from "./utils";
|
||||
|
||||
export interface Settings {
|
||||
trayLength: number;
|
||||
|
@ -82,6 +82,7 @@ enum TileDispatchActionType {
|
|||
MOVE,
|
||||
RETRIEVE,
|
||||
SET_BLANK,
|
||||
RETURN,
|
||||
}
|
||||
type TileDispatchAction = {action: TileDispatchActionType, start?: CoordinateData, end?: CoordinateData, newBlankValue?: string, blankIndex?: number};
|
||||
type TileDispatch = React.Dispatch<TileDispatchAction>;
|
||||
|
@ -103,49 +104,10 @@ export function Game(props: {wasm: GameWasm, settings: Settings}) {
|
|||
function movePlayableLetters(playerLetters: PlayableLetterData[], update: TileDispatchAction) {
|
||||
|
||||
if(update.action === TileDispatchActionType.RETRIEVE) {
|
||||
|
||||
let tray: Tray = props.wasm.get_tray("Player");
|
||||
|
||||
|
||||
// we may need to check against the existing tray to retain whatever user reorderings there are
|
||||
const freeSpots = new Array<number | null>();
|
||||
for (let i = 0; i<props.settings.trayLength; i++) {
|
||||
freeSpots.push(i);
|
||||
}
|
||||
|
||||
playerLetters.filter((x) => {
|
||||
return x !== undefined && x !== null;
|
||||
}).forEach((x) => {
|
||||
if (x.location === LocationType.TRAY) {
|
||||
freeSpots[x.index] = null;
|
||||
}
|
||||
});
|
||||
|
||||
const firstNotNull = (): number => {
|
||||
for (let i of freeSpots) {
|
||||
if (i !== null) {
|
||||
freeSpots[i] = null;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// initial state
|
||||
let letters: PlayableLetterData[] = tray.letters.map((ld, i) => {
|
||||
if(ld !== undefined) {
|
||||
ld["location"] = LocationType.TRAY;
|
||||
|
||||
if (playerLetters[i] !== undefined && playerLetters[i] !== null && playerLetters[i].location === LocationType.TRAY) {
|
||||
ld["index"] = playerLetters[i].index;
|
||||
} else {
|
||||
ld["index"] = firstNotNull();
|
||||
}
|
||||
}
|
||||
return ld as PlayableLetterData;
|
||||
});
|
||||
|
||||
return letters;
|
||||
return mergeTrays(playerLetters, tray.letters);
|
||||
} else if (update.action === TileDispatchActionType.MOVE) {
|
||||
|
||||
let startIndex = matchCoordinate(playerLetters, update.start);
|
||||
|
@ -175,6 +137,8 @@ export function Game(props: {wasm: GameWasm, settings: Settings}) {
|
|||
}
|
||||
}
|
||||
return playerLetters.slice();
|
||||
} else if (update.action === TileDispatchActionType.RETURN) {
|
||||
return mergeTrays(playerLetters, playerLetters);
|
||||
} else {
|
||||
console.error("Unknown tray update");
|
||||
console.error({update});
|
||||
|
@ -182,6 +146,8 @@ export function Game(props: {wasm: GameWasm, settings: Settings}) {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const [playerLetters, trayDispatch] = useReducer(movePlayableLetters, []);
|
||||
const [logInfo, logDispatch] = useReducer(addLogInfo, []);
|
||||
|
||||
|
@ -302,6 +268,9 @@ export function Game(props: {wasm: GameWasm, settings: Settings}) {
|
|||
<button
|
||||
onClick={(e) => {setIsTileExchangeOpen(true);}}
|
||||
>Open Tile Exchange</button>
|
||||
<button onClick={(e) => {
|
||||
trayDispatch({action: TileDispatchActionType.RETURN});
|
||||
}}>Return Tiles</button>
|
||||
</>;
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,52 @@
|
|||
import {Letter} from "word_grid";
|
||||
import {LocationType, PlayableLetterData} from "./elements";
|
||||
|
||||
export function addNTimes<T>(array: T[], toAdd: T, times: number) {
|
||||
for (let i=0; i<times; i++) {
|
||||
array.push(toAdd);
|
||||
}
|
||||
}
|
||||
|
||||
export function mergeTrays(existing: PlayableLetterData[], newer: (Letter | undefined)[]): PlayableLetterData[] {
|
||||
|
||||
let trayLength = Math.max(existing.length, newer.length);
|
||||
|
||||
// we may need to check against the existing tray to retain whatever user reorderings there are
|
||||
const freeSpots = new Array<number | null>();
|
||||
for (let i = 0; i<trayLength; i++) {
|
||||
freeSpots.push(i);
|
||||
}
|
||||
|
||||
existing.filter((x) => {
|
||||
return x !== undefined && x !== null;
|
||||
}).forEach((x) => {
|
||||
if (x.location === LocationType.TRAY) {
|
||||
freeSpots[x.index] = null;
|
||||
}
|
||||
});
|
||||
|
||||
const firstNotNull = (): number => {
|
||||
for (let i of freeSpots) {
|
||||
if (i !== null) {
|
||||
freeSpots[i] = null;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return newer.map((ld, i) => {
|
||||
if (ld !== undefined) {
|
||||
|
||||
if (existing[i] !== undefined && existing[i] !== null && existing[i].location === LocationType.TRAY) {
|
||||
ld["index"] = existing[i].index;
|
||||
} else {
|
||||
ld["index"] = firstNotNull();
|
||||
}
|
||||
ld["location"] = LocationType.TRAY;
|
||||
}
|
||||
return ld as PlayableLetterData;
|
||||
});
|
||||
|
||||
}
|
Loading…
Reference in a new issue