Maps page initial

This commit is contained in:
Kalle 2022-10-05 19:36:25 +03:00
parent 36280db0b1
commit 87bca7aa44
19 changed files with 321 additions and 3 deletions

View File

@ -51,3 +51,4 @@ export type {
SpecialWeaponId,
} from "./types";
export { isAbility } from "./utils";
export { stageIds } from "./stage-ids";

View File

@ -0,0 +1,15 @@
// when adding new stage id also create new language dicts via create-misc.json.ts
export const stageIds = [
0, // Scorch Gorge
1, // Eeltail Alley
2, // Hagglefish Market
3, // Undertow Spillway
4, // Mincemeat Metalworks
5, // Hammerhead Bridge
6, // Museum d'Alfonsino
7, // Mahi-Mahi Resort
8, // Inkblot Art Academy
9, // Sturgeon Shipyard
10, // MakoMart
11, // Wahoo World
] as const;

55
app/routes/maps.tsx Normal file
View File

@ -0,0 +1,55 @@
import type { LinksFunction } from "@remix-run/node";
import { useTranslation } from "react-i18next";
import { Image } from "~/components/Image";
import { Main } from "~/components/Main";
import { modes, stageIds } from "~/modules/in-game-lists";
import styles from "~/styles/maps.css";
import { modeImageUrl } from "~/utils/urls";
export const links: LinksFunction = () => {
return [{ rel: "stylesheet", href: styles }];
};
export const handle = {
i18n: "game-misc",
};
export default function MapListPage() {
return (
<Main halfWidth>
<MapPoolSelector />
</Main>
);
}
function MapPoolSelector() {
const { t } = useTranslation(["game-misc"]);
return (
<div className="stack md">
{stageIds.map((stageId) => (
<div key={stageId} className="maps__stage-row">
<div>{t(`game-misc:STAGE_${stageId}`)}</div>
<div className="stack horizontal sm">
{modes
.filter((mode) => mode.short !== "TW")
.map((mode) => (
<button
key={mode.short}
className="maps__mode-button outline-theme"
type="button"
>
<Image
alt={mode.long}
path={modeImageUrl(mode.short)}
width={20}
height={20}
/>
</button>
))}
</div>
</div>
))}
</div>
);
}

22
app/styles/maps.css Normal file
View File

@ -0,0 +1,22 @@
.maps__stage-row {
display: flex;
align-items: center;
justify-content: space-between;
background-color: var(--bg-lighter);
border-radius: var(--rounded);
font-size: var(--fonts-xs);
font-weight: var(--semi-bold);
gap: var(--s-0-5);
padding-block: var(--s-1-5);
padding-inline: var(--s-3);
}
.maps__mode-button {
padding: 0;
padding: var(--s-1-5);
border: none;
background-color: var(--bg-darker);
border-radius: var(--rounded);
color: var(--theme);
outline: initial;
}

View File

@ -15,6 +15,7 @@
"rename-badge": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/rename-badge.ts",
"create-weapon-json": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/create-weapon-json.ts",
"create-gear-json": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/create-gear-json.ts",
"create-misc-json": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/create-misc-json.ts",
"create-analyzer-json": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/create-analyzer-json.ts",
"check-translation-jsons": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/check-translation-jsons.ts && npm run prettier:write",
"replace-img-names": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/replace-img-names.ts",

View File

@ -0,0 +1,14 @@
{
"STAGE_0": "Scorch Gorge",
"STAGE_1": "Eeltail Alley",
"STAGE_2": "Hagglefish Market",
"STAGE_3": "Undertow Spillway",
"STAGE_4": "Mincemeat Metalworks",
"STAGE_5": "Hammerhead Bridge",
"STAGE_6": "Museum d'Alfonsino",
"STAGE_7": "Mahi-Mahi Resort",
"STAGE_8": "Inkblot Art Academy",
"STAGE_9": "Sturgeon Shipyard",
"STAGE_10": "MakoMart",
"STAGE_11": "Wahoo World"
}

View File

@ -0,0 +1,14 @@
{
"STAGE_0": "Sengkluft",
"STAGE_1": "Streifenaal-Straße",
"STAGE_2": "Schnapperchen-Basar",
"STAGE_3": "Schwertmuschel-Reservoir",
"STAGE_4": "Aalstahl-Metallwerk",
"STAGE_5": "Makrelenbrücke",
"STAGE_6": "Pinakoithek",
"STAGE_7": "Mahi-Mahi-Resort",
"STAGE_8": "Perlmutt-Akademie",
"STAGE_9": "Störwerft",
"STAGE_10": "Cetacea-Markt",
"STAGE_11": "Flunder-Funpark"
}

View File

@ -0,0 +1,14 @@
{
"STAGE_0": "Scorch Gorge",
"STAGE_1": "Eeltail Alley",
"STAGE_2": "Hagglefish Market",
"STAGE_3": "Undertow Spillway",
"STAGE_4": "Mincemeat Metalworks",
"STAGE_5": "Hammerhead Bridge",
"STAGE_6": "Museum d'Alfonsino",
"STAGE_7": "Mahi-Mahi Resort",
"STAGE_8": "Inkblot Art Academy",
"STAGE_9": "Sturgeon Shipyard",
"STAGE_10": "MakoMart",
"STAGE_11": "Wahoo World"
}

View File

@ -0,0 +1,14 @@
{
"STAGE_0": "Desfiladero Fumarola",
"STAGE_1": "Callejones Crustáceo",
"STAGE_2": "Mercado Lenguado",
"STAGE_3": "Cisterna Navajuela",
"STAGE_4": "Desguace Mero",
"STAGE_5": "Puente Salmón",
"STAGE_6": "Museo del Pargo",
"STAGE_7": "Spa Cala Bacalao",
"STAGE_8": "Instituto Coralino",
"STAGE_9": "Astillero Beluga",
"STAGE_10": "Ultramarinos Orca",
"STAGE_11": "Pirañalandia"
}

View File

@ -0,0 +1,14 @@
{
"STAGE_0": "Canyon aux colonnes",
"STAGE_1": "Banlieue Balibot",
"STAGE_2": "Marché Grefin",
"STAGE_3": "Réservoir Rigadelle",
"STAGE_4": "Casse Rascasse",
"STAGE_5": "Pont Esturgeon",
"STAGE_6": "Galeries Guppy",
"STAGE_7": "Club Ca$halot",
"STAGE_8": "Institut Calam'arts",
"STAGE_9": "Chantier Narval",
"STAGE_10": "Supermarché Cétacé",
"STAGE_11": "Parc Carapince"
}

View File

@ -0,0 +1,14 @@
{
"STAGE_0": "Grank Canyon",
"STAGE_1": "Sobborgo Siluriano",
"STAGE_2": "Mercato Fruttato",
"STAGE_3": "Cisterna Cernia",
"STAGE_4": "Discarica Tritatutto",
"STAGE_5": "Ponte Sgombro",
"STAGE_6": "Museo di Cefalò",
"STAGE_7": "Villanguilla",
"STAGE_8": "Campus Hippocampus",
"STAGE_9": "Cantiere Pinnenere",
"STAGE_10": "Mercatotano",
"STAGE_11": "Soglioland"
}

View File

@ -0,0 +1,14 @@
{
"STAGE_0": "ユノハナ大渓谷",
"STAGE_1": "ゴンズイ地区",
"STAGE_2": "ヤガラ市場",
"STAGE_3": "マテガイ放水路",
"STAGE_4": "ナメロウ金属",
"STAGE_5": "マサバ海峡大橋",
"STAGE_6": "キンメダイ美術館",
"STAGE_7": "マヒマヒリゾート&スパ",
"STAGE_8": "海女美術大学",
"STAGE_9": "チョウザメ造船",
"STAGE_10": "ザトウマーケット",
"STAGE_11": "スメーシーワールド"
}

View File

@ -0,0 +1,14 @@
{
"STAGE_0": "석순 대협곡",
"STAGE_1": "메기 지구",
"STAGE_2": "대치 시장",
"STAGE_3": "맛조개 방수로",
"STAGE_4": "나메로우 금속",
"STAGE_5": "고등어 해협 대교",
"STAGE_6": "도미 미술관",
"STAGE_7": "만새기 리조트&스파",
"STAGE_8": "해녀 미술 대학",
"STAGE_9": "철갑상어 조선소",
"STAGE_10": "혹등 마켓",
"STAGE_11": "초밥 월드"
}

View File

@ -0,0 +1,14 @@
{
"STAGE_0": "Roggentrog",
"STAGE_1": "Forelviaduct",
"STAGE_2": "Boter-bij-de-vismarkt",
"STAGE_3": "Baarsreservoir",
"STAGE_4": "Zilversmelt-hoogovens",
"STAGE_5": "Brandingbrug",
"STAGE_6": "Galerie Le Guppy",
"STAGE_7": "El Dorade-resort",
"STAGE_8": "Koraalcampus",
"STAGE_9": "Walruswerf",
"STAGE_10": "Bultrugbazaar",
"STAGE_11": "Waterwonderland"
}

View File

@ -0,0 +1,14 @@
{
"STAGE_0": "Опаленное ущелье",
"STAGE_1": "Угрево-Скатово",
"STAGE_2": "Рынок «Свисторыб»",
"STAGE_3": "Приливослив",
"STAGE_4": "Цех «Тартар»",
"STAGE_5": "Акулий мост",
"STAGE_6": "Галерея «Де Берикс»",
"STAGE_7": "Спа-курорт «Золотая рыбка»",
"STAGE_8": "Академия «Лепота»",
"STAGE_9": "Осетровые верфи",
"STAGE_10": "«Горбуша-Маркет»",
"STAGE_11": "Луна-парк «Язь»"
}

View File

@ -0,0 +1,14 @@
{
"STAGE_0": "温泉花大峡谷",
"STAGE_1": "鳗鲶区",
"STAGE_2": "烟管鱼市场",
"STAGE_3": "竹蛏疏洪道",
"STAGE_4": "鱼肉碎金属",
"STAGE_5": "真鲭跨海大桥",
"STAGE_6": "金眼鲷美术馆",
"STAGE_7": "鬼头刀SPA度假区",
"STAGE_8": "海女美术大学",
"STAGE_9": "鲟鱼造船厂",
"STAGE_10": "座头购物中心",
"STAGE_11": "醋饭海洋世界"
}

View File

@ -0,0 +1,69 @@
import { LANG_JSONS_TO_CREATE, loadLangDicts } from "./utils";
import fs from "fs";
import path from "path";
import invariant from "tiny-invariant";
// ⚠️ keep same order as https://github.com/IPLSplatoon/IPLMapGen2/blob/splat3/data.js
const stages = [
"Scorch Gorge",
"Eeltail Alley",
"Hagglefish Market",
"Undertow Spillway",
"Mincemeat Metalworks",
"Hammerhead Bridge",
"Museum d'Alfonsino",
"Mahi-Mahi Resort",
"Inkblot Art Academy",
"Sturgeon Shipyard",
"MakoMart",
"Wahoo World",
] as const;
async function main() {
const langDicts = await loadLangDicts();
const englishLangDict = langDicts.find(
([langCode]) => langCode === "EUen"
)?.[1];
invariant(englishLangDict);
const codeNames = stages.map((stage) => {
const codeName = Object.entries(
englishLangDict["CommonMsg/VS/VSStageName"]
).find(([_key, value]) => value === stage)?.[0];
invariant(codeName, `Could not find code name for stage ${stage}`);
return codeName;
});
for (const langCode of LANG_JSONS_TO_CREATE) {
const langDict = langDicts.find(([code]) => code === langCode)?.[1];
invariant(langDict, `Missing translations for ${langCode}`);
const translationsMap = Object.fromEntries(
stages.map((_, i) => {
const codeName = codeNames[
i
] as keyof typeof langDict["CommonMsg/VS/VSStageName"];
invariant(codeName);
return [`STAGE_${i}`, langDict["CommonMsg/VS/VSStageName"][codeName]];
})
);
fs.writeFileSync(
path.join(
__dirname,
"..",
"public",
"locales",
langCode.slice(2),
`game-misc.json`
),
JSON.stringify(translationsMap, null, 2) + "\n"
);
}
}
void main();

View File

@ -1,5 +1,6 @@
import path from "node:path";
import fs from "node:fs";
import type euEn from "./dicts/langs/EUen.json";
const LANG_DICTS_PATH = path.join(__dirname, "dicts", "langs");
@ -17,9 +18,7 @@ export const LANG_JSONS_TO_CREATE = [
];
export async function loadLangDicts() {
const result: Array<
[langCode: string, translations: Record<string, Record<string, string>>]
> = [];
const result: Array<[langCode: string, translations: typeof euEn]> = [];
const files = await fs.promises.readdir(LANG_DICTS_PATH);
for (const file of files) {

View File

@ -11,6 +11,7 @@ import type weapons from "../public/locales/en/weapons.json";
import type gear from "../public/locales/en/gear.json";
import type builds from "../public/locales/en/builds.json";
import type analyzer from "../public/locales/en/analyzer.json";
import type gameMisc from "../public/locales/en/game-misc.json";
declare module "react-i18next" {
interface CustomTypeOptions {
@ -27,6 +28,7 @@ declare module "react-i18next" {
gear: typeof gear;
builds: typeof builds;
analyzer: typeof analyzer;
"game-misc": typeof gameMisc;
};
}
}