Skip to content

Commit 59cd9a7

Browse files
committed
Merge branch 'develop'
2 parents 6b0877d + 32315a3 commit 59cd9a7

File tree

4 files changed

+139
-11
lines changed

4 files changed

+139
-11
lines changed

public/locales/en/apfront.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"AcceptDraw": "Accept draw offer",
77
"Accepted": "Accepted!",
88
"All": "All",
9+
"AlternativeDisplays": "Alternative display options",
910
"and": "and",
1011
"Annotate": "Show last move indicators",
1112
"AnnotationLevel": "Where would you like this choice applied?",
@@ -887,4 +888,4 @@
887888
"YourGames": "Your games",
888889
"YourMove": "Your move",
889890
"EnableZoom": "Enable zoom"
890-
}
891+
}

src/components/GameDisplays.js

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import React, { useEffect, useState } from "react";
2+
import { gameinfo, GameFactory, addResource } from "@abstractplay/gameslib";
3+
import { useTranslation } from "react-i18next";
4+
5+
/**
6+
* This component parses a metaGame's displays definition and displays them.
7+
* Selection is done in RenderOptionsModal.js.
8+
* Give it the metaGame.
9+
*/
10+
function GameDisplays({ metaGame }) {
11+
const [displays, displaysSetter] = useState([]);
12+
const { t, i18n } = useTranslation();
13+
14+
useEffect(() => {
15+
addResource(i18n.language);
16+
}, [i18n.language]);
17+
18+
// This does the initial parse of the data
19+
useEffect(() => {
20+
if (metaGame !== undefined && metaGame !== null && metaGame !== "") {
21+
// load game info
22+
// need an engine if we want to translate the strings
23+
const info = gameinfo.get(metaGame);
24+
if (info !== undefined) {
25+
let gameEngine;
26+
if (info.playercounts.length > 1) {
27+
gameEngine = GameFactory(info.uid, 2);
28+
} else {
29+
gameEngine = GameFactory(info.uid);
30+
}
31+
32+
// Don't need to filter out `experimental` displays unless that gets implemented.
33+
let displays = gameEngine.alternativeDisplays();
34+
35+
// Don't need to deal with grouping.
36+
if (displays && displays !== undefined) {
37+
displaysSetter(displays);
38+
} else {
39+
displaysSetter([]);
40+
}
41+
} else {
42+
displaysSetter([]);
43+
}
44+
} else {
45+
displaysSetter([]);
46+
}
47+
}, [metaGame]);
48+
49+
if ( displays.length === 0 ) {
50+
return null;
51+
} else {
52+
return (
53+
<>
54+
<div className="field">
55+
<label className="label">
56+
{t("AlternativeDisplays")}
57+
</label>
58+
</div>
59+
<div className="indentedContainer">
60+
{displays.map((v) => (
61+
<div className="control" key={v.uid}>
62+
<label className="radio">
63+
<input
64+
type="radio"
65+
id={v.uid}
66+
value={v.uid}
67+
disabled="disabled"
68+
/>
69+
{v.description === undefined ||
70+
v.description.length === 0 ? (
71+
v.name
72+
) : (
73+
v.description
74+
)}
75+
</label>
76+
</div>
77+
))}
78+
</div>
79+
</>
80+
);
81+
}
82+
}
83+
84+
export default GameDisplays;

src/components/MetaContainer/MetaItem.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Ratings from "../Ratings";
1414
import StandingChallenges from "../StandingChallenges";
1515
import ListGames from "../ListGames";
1616
import Tournaments from "../Tournaments/Tournaments";
17+
import GameDisplays from "../GameDisplays";
1718
import GameVariants from "../GameVariants";
1819
import Thumbnail from "../Thumbnail";
1920

@@ -227,6 +228,9 @@ const MetaItem = React.forwardRef(
227228
variantsSetter={setSelectedVariants}
228229
disableFields={true}
229230
/>
231+
<GameDisplays
232+
metaGame={game.uid}
233+
/>
230234
<ReactMarkdown
231235
rehypePlugins={[rehypeRaw]}
232236
className="content"

src/components/StandingChallenges.js

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useEffect, useContext, useMemo } from "react";
1+
import React, { useState, useEffect, useContext, useMemo, useCallback } from "react";
22
import { useTranslation } from "react-i18next";
33
import { useParams, Link } from "react-router-dom";
44
import { gameinfo, GameFactory } from "@abstractplay/gameslib";
@@ -228,7 +228,12 @@ function StandingChallenges(props) {
228228
const metaGameName = gameinfo.get(metaGame).name;
229229
console.log(metaGame);
230230
const showRespond = loggedin && challenges;
231-
const variantMap = useMemo(() => {
231+
232+
const [variantMap, setVariantMap] = useState(new Map());
233+
const [variantGroups, setVariantGroups] = useState(new Set());
234+
const [varId2Group, setVarId2Group] = useState(new Map());
235+
236+
useEffect(() => {
232237
const info = gameinfo.get(metaGame);
233238
let gameEngine;
234239
if (info.playercounts.length > 1) {
@@ -238,14 +243,50 @@ function StandingChallenges(props) {
238243
}
239244
const all = gameEngine.allvariants();
240245
if (all !== undefined) {
241-
return new Map(
242-
gameEngine.allvariants().map((rec) => [rec.uid, rec.name])
243-
);
246+
setVariantMap(new Map(
247+
all.map((rec) => [rec.uid, rec.name])
248+
));
249+
setVariantGroups(new Set(
250+
all.map((rec) => rec.group).filter(Boolean)
251+
));
252+
setVarId2Group(new Map(
253+
all.map((rec) => [rec.uid, rec.group])
254+
));
244255
} else {
245-
return new Map();
256+
setVariantMap(new Map());
257+
setVariantGroups(new Set());
258+
setVarId2Group(new Map());
246259
}
247260
}, [metaGame]);
248261

262+
263+
const vars2string = useCallback((vars) => {
264+
// if the string is empty, return all the group defaults
265+
if (vars.length === 0) {
266+
return [...variantMap.entries()]
267+
.filter(([k]) => k.startsWith("#"))
268+
.map(([, v]) => v)
269+
.filter(Boolean);
270+
}
271+
// otherwise add any missing defaults and just look up the rest
272+
else {
273+
const groups = new Set([...variantGroups]);
274+
for (const v of vars) {
275+
const g = varId2Group.get(v);
276+
if (g !== undefined) {
277+
groups.delete(g);
278+
}
279+
}
280+
console.log(`Some groups not defined: ${[...groups]}`);
281+
// if any groups are not defined, add the defaults to vars
282+
for (const g of groups) {
283+
vars.push(`#${g}`);
284+
}
285+
console.log(`About to return: ${vars}`);
286+
return vars.map((v) => variantMap.get(v)).filter(Boolean);
287+
}
288+
}, [variantMap, variantGroups, varId2Group]);
289+
249290
const data = useMemo(
250291
() =>
251292
challenges.map((rec) => {
@@ -270,13 +311,11 @@ function StandingChallenges(props) {
270311
players: rec.players.filter((p) => p.id !== rec.challenger?.id),
271312
rated: rec.rated,
272313
seating: rec.seating,
273-
variants: rec.variants.map((id) =>
274-
variantMap.has(id) ? variantMap.get(id) : id
275-
),
314+
variants: vars2string(rec.variants),
276315
comment: rec.comment,
277316
};
278317
}),
279-
[challenges, allUsers, variantMap]
318+
[challenges, allUsers, vars2string]
280319
);
281320

282321
const columnHelper = createColumnHelper();

0 commit comments

Comments
 (0)