Migration away from maps since they cannot be easily de-/serialized

This commit is contained in:
Neshura 2023-08-24 05:04:27 +02:00
parent ef7bb99f41
commit 40dee1e8f8
Signed by: Neshura
GPG key ID: B6983AAA6B9A7A6C
14 changed files with 321 additions and 372 deletions

View file

@ -2,7 +2,7 @@
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"printWidth": 160,
"plugins": ["prettier-plugin-svelte"],
"pluginSearchDirs": ["."],
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]

3
src/app.d.ts vendored
View file

@ -6,6 +6,9 @@ declare global {
// interface Locals {}
// interface PageData {}
// interface Platform {}
interface Locals {
authenticated: boolean | null
}
}
}

13
src/hooks.server.ts Normal file
View file

@ -0,0 +1,13 @@
import { redirect } from "@sveltejs/kit";
export async function handle({ event, resolve }) {
event.locals.authenticated = true;
if (event.url.pathname.startsWith('/admin')) {
if (!event.locals.authenticated) {
throw redirect(303, '/401');
}
}
return await resolve(event);
}

View file

@ -1,5 +1,10 @@
import { writable, type Writable } from "svelte/store";
const SelectedGameGroupsStore: Writable<Map<number, Array<number>>> = writable(new Map());
export type SelectedChellarisGroups = {
gameId: number,
selectedGroups: Array<number>,
}
const SelectedGameGroupsStore: Writable<Array<SelectedChellarisGroups>> = writable([]); // Key should always be the same as gameId
export default SelectedGameGroupsStore;

View file

@ -1,35 +1,38 @@
import type { Ethic, Species } from './stellaris';
export interface ChellarisInfo {
games: Map<number, ChellarisGame>, // Key is Game Id
ethics: Map<number, Ethic>, // Key is Ethic Id
species: Map<number, Species>, // Key is Species Group Id
games: Array<ChellarisGame>, // Key is Game Id
ethics: Array<Ethic>, // Key is Ethic Id
species: Array<Species>, // Key is Species Group Id
}
export type ChellarisGame = {
id: number,
name: string,
groups: Map<number, ChellarisGameGroup>, // Key is Group Id
empires: Map<number, ChellarisEmpire>, // Key is Empire Id
groups: Array<ChellarisGameGroup>, // Key is Group Id
empires: Array<ChellarisEmpire>, // Key is Empire Id
}
export type ChellarisGameGroup = {
id: number,
name: string,
}
export type ChellarisEmpire = {
id: number,
gestalt: boolean,
machine: boolean,
group: number,
empire_portrait: number, // TODO replace with Enum?
empire_portrait_group: number, // TODO replace with Enum?
discord_user?: string,
ethics: Map<number, Ethic>,
ethics: Array<Ethic>,
}
export const createChellarisInfo = (): ChellarisInfo => {
const newChellarisInfo = {
games: new Map(),
ethics: new Map(),
species: new Map(),
games: [],
ethics: [],
species: [],
};
return newChellarisInfo;
@ -37,9 +40,10 @@ export const createChellarisInfo = (): ChellarisInfo => {
export const createChellarisGame = (): ChellarisGame => {
const newChellarisGame = {
id: 0,
name: "",
groups: new Map(),
empires: new Map(),
groups: [],
empires: [],
};
return newChellarisGame;
@ -47,6 +51,7 @@ export const createChellarisGame = (): ChellarisGame => {
export const createChellarisGameGroup = (): ChellarisGameGroup => {
const newChellarisGameGroup = {
id: 0,
name: "",
};
@ -55,8 +60,9 @@ export const createChellarisGameGroup = (): ChellarisGameGroup => {
export const createChellarisEmpire = (
{
discord_user, group_id, gestalt, empire_portrait_id, empire_portrait_group_id
id, discord_user, group_id, gestalt, empire_portrait_id, empire_portrait_group_id
}: {
id: number,
discord_user?: string,
group_id: number,
gestalt: boolean,
@ -64,12 +70,13 @@ export const createChellarisEmpire = (
empire_portrait_group_id: number,
}): ChellarisEmpire => {
const newChellarisEmpire = {
id: id,
gestalt: gestalt,
machine: false,
group: group_id,
empire_portrait: empire_portrait_id,
empire_portrait_group: empire_portrait_group_id,
ethics: new Map(),
ethics: [],
discord_user: discord_user,
};

View file

@ -65,17 +65,20 @@ export class EthicsDataLegacy {
}
export type Ethic = {
id: number,
displayName: string,
machine: boolean,
fanatic?: boolean,
}
export type Species = {
id: number,
displayName: string,
portraits: Map<number, Portrait>, // Key is Portrait Id
portraits: Array<Portrait>, // Key is Portrait Id
}
export type Portrait = {
id: number,
hires: string,
lores: string,
}

View file

@ -0,0 +1,12 @@
<svelte:head>
<title>About</title>
<meta name="description" content="401: Unauthorized" />
</svelte:head>
<div class="text-column">
<h1>Unauthorized</h1>
<p>
Your request was denied, the authentication token in your settings seems to be invalid.
</p>
</div>

View file

@ -21,9 +21,9 @@
<li aria-current={$page.url.pathname === '/legacy-graphs' ? 'page' : undefined}>
<a href="/legacy-graphs">Game 15 Graphs</a>
</li>
<li aria-current={$page.url.pathname.startsWith('/sign-up') ? 'page' : undefined}>
<!--<li aria-current={$page.url.pathname.startsWith('/sign-up') ? 'page' : undefined}>
<a href="/sign-up">Empire Sign-Up</a>
</li>
</li>-->
<li aria-current={$page.url.pathname.startsWith('/admin') ? 'page' : undefined}>
<a href="/admin">Admin Menu</a>
</li>

View file

@ -1,6 +1,6 @@
import ChellarisDataStore from '$lib/stores/ChellarisData';
import SelectedGameStore from '$lib/stores/GameFilter';
import SelectedGameGroupsStore from "$lib/stores/GameGroupFilter";
import SelectedGameGroupsStore, { type SelectedChellarisGroups } from "$lib/stores/GameGroupFilter";
import GraphsTabStore from '$lib/stores/GraphsTab';
import { createChellarisInfo, type ChellarisGame, createChellarisGame, createChellarisGameGroup, createChellarisEmpire } from "$lib/types/chellaris";
import type { LayoutLoad } from "./$types";
@ -13,26 +13,27 @@ export const load: LayoutLoad = async ({ fetch }) => {
// Chellaris Data Code
const games: {id: number, name: string}[] = await (await fetch(apiBaseUrl + '/games')).json();
const games: { id: number, name: string }[] = await (await fetch(apiBaseUrl + '/games')).json();
games.sort((a, b) => (a.name < b.name ? -1 : 1));
games.forEach(game => {
const newGame: ChellarisGame = createChellarisGame();
newGame.id = game.id;
newGame.name = game.name;
chellarisData.games.set(game.id, newGame);
chellarisData.games[game.id] = newGame;
});
const groups: {id: number, name: string, game_id: number}[] = await (await fetch(apiBaseUrl + '/game_groups')).json();
const groups: { id: number, name: string, game_id: number }[] = await (await fetch(apiBaseUrl + '/game_groups')).json();
groups.sort((a, b) => (a.name < b.name ? -1 : 1));
groups.forEach(group => {
const gameData = chellarisData.games.get(group.game_id);
const gameData = chellarisData.games[group.game_id];
if (typeof gameData !== "undefined") {
const newGroup = createChellarisGameGroup();
newGroup.id = group.id;
newGroup.name = group.name;
gameData.groups.set(group.id, newGroup)
chellarisData.games.set(group.game_id, gameData);
chellarisData.games[group.game_id].groups[group.id] = newGroup;
}
})
@ -43,25 +44,26 @@ export const load: LayoutLoad = async ({ fetch }) => {
gestalt: boolean,
empire_portrait_id: number,
empire_portrait_group_id: number,
group_game_id: number}[] = await (await fetch(apiBaseUrl + '/empires')).json();
group_game_id: number
}[] = await (await fetch(apiBaseUrl + '/empires')).json();
empires.sort((a, b) => (a.id < b.id ? -1 : 1));
empires.forEach(empire => {
const gameData = chellarisData.games.get(empire.group_game_id);
const gameData = chellarisData.games[empire.group_game_id];
if (typeof gameData !== "undefined") {
const newEmpire = createChellarisEmpire(empire);
gameData.empires.set(empire.id, newEmpire);
chellarisData.games[empire.group_game_id].empires[empire.id] = newEmpire;
}
});
const ethics: {id: number, name: string, machine_ethic: boolean}[] = await (await fetch(apiBaseUrl + '/ethics')).json();
const ethics: { id: number, name: string, machine_ethic: boolean }[] = await (await fetch(apiBaseUrl + '/ethics')).json();
ethics.sort((a, b) => (a.id < b.id ? -1 : 1));
ethics.forEach(ethic => {
const newEthic: Ethic = {displayName: ethic.name, machine: ethic.machine_ethic};
const newEthic: Ethic = { id: ethic.id, displayName: ethic.name, machine: ethic.machine_ethic };
chellarisData.ethics.set(ethic.id, newEthic);
chellarisData.ethics[ethic.id] = newEthic;
});
const empireEthics: {
@ -69,20 +71,21 @@ export const load: LayoutLoad = async ({ fetch }) => {
empires_group_id: number,
empires_group_game_id: number,
ethics_id: number,
ethics_fanatic: boolean}[] = await (await fetch(apiBaseUrl + '/empire_ethics')).json();
ethics_fanatic: boolean
}[] = await (await fetch(apiBaseUrl + '/empire_ethics')).json();
empireEthics.forEach(empireEthic => {
const gameData = chellarisData.games.get(empireEthic.empires_group_game_id);
const ethic = chellarisData.ethics.get(empireEthic.ethics_id);
const gameData = chellarisData.games[empireEthic.empires_group_game_id];
const ethic = chellarisData.ethics[empireEthic.ethics_id];
if (typeof gameData !== "undefined" && typeof ethic !== "undefined") {
const empireData = gameData.empires.get(empireEthic.empires_id);
const empireData = gameData.empires[empireEthic.empires_id];
if (typeof empireData !== "undefined") {
const tmpEthic: Ethic = {machine: ethic.machine, displayName: ethic.displayName, fanatic: empireEthic.ethics_fanatic};
const tmpEthic: Ethic = { id: ethic.id, machine: ethic.machine, displayName: ethic.displayName, fanatic: empireEthic.ethics_fanatic };
if (tmpEthic.machine) {
empireData.machine = true;
}
empireData.ethics.set(empireEthic.ethics_id, tmpEthic);
empireData.ethics[empireEthic.ethics_id] = tmpEthic;
}
}
});
@ -95,8 +98,8 @@ export const load: LayoutLoad = async ({ fetch }) => {
portraitGroups.sort((a, b) => (a.id < b.id ? -1 : 1));
portraitGroups.forEach(portraitGroup => {
const newPortraitGroup = { displayName: portraitGroup.name, portraits: new Map() };
chellarisData.species.set(portraitGroup.id, newPortraitGroup);
const newPortraitGroup = { id: portraitGroup.id, displayName: portraitGroup.name, portraits: [] };
chellarisData.species[portraitGroup.id] = newPortraitGroup;
});
const portraits: {
@ -109,56 +112,81 @@ export const load: LayoutLoad = async ({ fetch }) => {
portraits.sort((a, b) => (a.id < b.id ? -1 : 1));
portraits.forEach(portrait => {
const portraitGroupData = chellarisData.species.get(portrait.group_id);
const portraitGroupData = chellarisData.species[portrait.group_id];
if (typeof portraitGroupData !== "undefined") {
const newPortraitData = { hires: portrait.hires, lores: portrait.lores };
const newPortraitData = { id: portrait.id, hires: portrait.hires, lores: portrait.lores };
portraitGroupData.portraits.set(portrait.id, newPortraitData);
portraitGroupData.portraits[portrait.id] = newPortraitData;
}
})
ChellarisDataStore.set(chellarisData);
// Local Storage Code
let gameGroupSelections: Array<SelectedChellarisGroups> = [];
let gameSelection: number | undefined;
if (typeof localStorage !== 'undefined') {
// Tab Selection
store = localStorage.getItem('graphsTab');
if (typeof store == 'string') {
if (typeof store === 'string') {
GraphsTabStore.set(store);
}
// Game Selection
store = localStorage.getItem('gameSelection');
let selectedGame = 1;
if (typeof store == 'string' && store != "\"\"") {
selectedGame = JSON.parse(store);
if (typeof store === 'string' && store != "\"\"") {
gameSelection = JSON.parse(store);
}
if (typeof gameSelection === 'undefined') {
gameSelection = chellarisData.games[0].id;
}
SelectedGameStore.set(selectedGame);
// Game Groups Selection
store = localStorage.getItem('gameGroupSelection');
if (typeof store == 'string') {
let selectedGameGroups: Array<number> = [];
const gameGroupSelectionMap = new Map<number, Array<number>>(JSON.parse(store));
const tmp = gameGroupSelectionMap.get(selectedGame);
if (typeof store === 'string') {
gameGroupSelections = JSON.parse(store);
if (typeof tmp !== 'undefined') {
selectedGameGroups = tmp;
} else {
const tmpGameData = chellarisData.games.get(selectedGame);
// If this fails an empty array is precisely what we want
if (typeof tmpGameData !== "undefined") {
if (typeof gameGroupSelections[gameSelection] === 'undefined') {
// Default to all available groups
selectedGameGroups = [...tmpGameData.groups.keys()];
gameGroupSelections[gameSelection] = { gameId: gameSelection, selectedGroups: chellarisData.games[gameSelection].groups.map(group => group.id) };
// Set Local Storage to default Values if not previously defined
localStorage.setItem('gameGroupSelection', JSON.stringify(Array.from(selectedGameGroups.entries())));
localStorage.setItem('gameGroupSelection', JSON.stringify(gameGroupSelections));
}
else {
Object.keys(gameGroupSelections).forEach(
gKey => {
if (gameGroupSelections[+gKey] == null) {
delete gameGroupSelections[+gKey];
}
else {
Object.keys(gameGroupSelections[+gKey].selectedGroups).forEach(
key => gameGroupSelections[+gKey].selectedGroups[+key] != null || delete gameGroupSelections[+gKey].selectedGroups[+key]
)
}
});
}
}
gameGroupSelectionMap.set(selectedGame, selectedGameGroups);
SelectedGameGroupsStore.set(gameGroupSelectionMap);
}
if (typeof gameSelection === 'undefined') {
gameSelection = chellarisData.games[0].id;
}
SelectedGameStore.set(gameSelection);
if (typeof gameGroupSelections[gameSelection] === 'undefined') {
// Default to all available groups
gameGroupSelections[gameSelection] = { gameId: gameSelection, selectedGroups: chellarisData.games[gameSelection].groups.map(group => group.id) };
}
SelectedGameGroupsStore.set(gameGroupSelections);
gameGroupSelections = []; // TODO: actually assing a value
return { chellarisData }
}

View file

@ -4,88 +4,54 @@
import SelectedGameGroupsStore from '$lib/stores/GameGroupFilter';
import SelectedGameStore from '$lib/stores/GameFilter';
import ChellarisDataStore from '$lib/stores/ChellarisData';
import { createChellarisInfo, type ChellarisGame, type ChellarisGameGroup, type ChellarisInfo } from '$lib/types/chellaris';
let selectedGame: number;
let selectedGameGroups: Array<number> = [];
let selectedGameGroupsMap: Map<number, Array<number>> = new Map();
let gameGroups: Map<number, ChellarisGameGroup> = new Map();
let chellarisData: ChellarisInfo = createChellarisInfo();
// Chellaris Data Code
const updateGameGroups = () => {
let tmpData;
if (!selectedGame) {
tmpData = chellarisData.games.get(chellarisData.games.keys().next().value);
}
else {
tmpData = chellarisData.games.get(selectedGame);
}
if (typeof tmpData !== 'undefined') {
gameGroups = tmpData.groups;
}
}
ChellarisDataStore.subscribe((data) => {
chellarisData = data;
updateGameGroups();
// TODO Update selection if Groups Differ? Does this value ever even update without a full page reload?
});
// Group Selection Code
const updateSelectedGroups = () => {
const tmp = selectedGameGroupsMap.get(selectedGame);
if (typeof tmp !== 'undefined') {
selectedGameGroups = [...tmp.values()];
} else {
selectedGameGroups = [...gameGroups.keys()];
selectedGameGroupsMap.set(selectedGame, selectedGameGroups);
SelectedGameGroupsStore.set(selectedGameGroupsMap);
}
};
// Game Selection Code
SelectedGameStore.subscribe((selection) => {
selectedGame = selection;
updateGameGroups();
if (selectedGameGroupsMap.size != 0) {
updateSelectedGroups();
if (typeof $SelectedGameGroupsStore[selection] === 'undefined') {
// Default to all available groups
$SelectedGameGroupsStore[selection] = { gameId: $SelectedGameStore, selectedGroups: $ChellarisDataStore.games[$SelectedGameStore].groups.map((group) => group.id) };
SelectedGameGroupsStore.update(() => $SelectedGameGroupsStore);
}
});
SelectedGameGroupsStore.subscribe((selection) => {
selectedGameGroupsMap = selection;
updateSelectedGroups();
})
// Game Group Selection Code
$: {
if (typeof localStorage !== 'undefined') {
localStorage.setItem('gameGroupSelection', JSON.stringify(Array.from(selection.entries())));
localStorage.setItem('gameGroupSelection', JSON.stringify($SelectedGameGroupsStore));
}
}
});
const updateGameGroupSelection = () => {
SelectedGameGroupsStore.update((selection) => selection.set(selectedGame, selectedGameGroups));
};
$: selectedGameData = $SelectedGameGroupsStore[$SelectedGameStore];
$: groupJoiner = selectedGameData.selectedGroups.length > 2 ? ', ' : ' & ';
const updateGroupStore = () => {
SelectedGameGroupsStore.update(() => $SelectedGameGroupsStore);
}
const dropdownId = crypto.randomUUID();
</script>
<DropDown {dropdownId} dropdownTitle={(selectedGameGroups.length > 1 ? "Groups " : "Group ") + selectedGameGroups.map((selection) => gameGroups.get(selection)?.name).join(", ")}>
{#each gameGroups as group}
<DropDown
{dropdownId}
dropdownTitle={(selectedGameData.selectedGroups.length > 1 ? 'Groups ' : 'Group ') +
selectedGameData.selectedGroups
.map((selection) => $ChellarisDataStore.games[$SelectedGameStore].groups[selection]?.name)
.join(groupJoiner)}
>
{#each $ChellarisDataStore.games[$SelectedGameStore].groups as group}
{#if group}
<DropDownElement {dropdownId}>
<input
id={'checkbox' + group[0]}
id={'checkbox' + group.id}
data-dropdown={dropdownId}
type="checkbox"
bind:group={selectedGameGroups}
on:change={updateGameGroupSelection}
value={group[0]}
bind:group={selectedGameData.selectedGroups}
on:change={updateGroupStore}
value={group.id}
/>
<label for={'checkbox' + group[0]} data-dropdown={dropdownId}>{group[1].name}</label>
<label for={'checkbox' + group.id} data-dropdown={dropdownId}>{group.name}</label>
</DropDownElement>
{/if}
{/each}
</DropDown>

View file

@ -3,45 +3,29 @@
import DropDownElement from '$lib/components/DropDownElement.svelte';
import SelectedGameStore from '$lib/stores/GameFilter';
import ChellarisDataStore from '$lib/stores/ChellarisData';
import type { ChellarisGame } from '$lib/types/chellaris';
let selectedGame: number;
let gameList: Map<number, ChellarisGame> = new Map();
// Chellaris Data Code
ChellarisDataStore.subscribe((data) => {
gameList = data.games;
});
// Game Selection Code
SelectedGameStore.subscribe((selection) => {
selectedGame = selection;
$: {
if (typeof localStorage !== 'undefined') {
localStorage.setItem('gameSelection', JSON.stringify(selectedGame));
localStorage.setItem('gameSelection', JSON.stringify($SelectedGameStore));
}
});
const updateGameSelection = () => {
SelectedGameStore.update(() => selectedGame);
};
// Dropdown UUID to make the Click Event work properly
const dropdownId = crypto.randomUUID();
</script>
<DropDown {dropdownId} dropdownTitle={gameList.get(selectedGame)?.name}>
{#each gameList as game}
<DropDown {dropdownId} dropdownTitle={$ChellarisDataStore.games[$SelectedGameStore]?.name}>
{#each $ChellarisDataStore.games as game}
<DropDownElement {dropdownId}>
<input
id={'checkbox' + game[0]}
id={'checkbox' + game.id}
data-dropdown={dropdownId}
type="radio"
bind:group={selectedGame}
on:change={updateGameSelection}
value={game[0]}
bind:group={$SelectedGameStore}
value={game.id}
/>
<label for={'checkbox' + game[0]} data-dropdown={dropdownId}>{game[1].name}</label>
<label for={'checkbox' + game.id} data-dropdown={dropdownId}>{game.name}</label>
</DropDownElement>
{/each}
</DropDown>

View file

@ -12,12 +12,12 @@
<path d="M0,0 L1,2 C1.5,3 1.5,3 2,3 L2,0 Z" />
</svg>
<ul>
<li aria-current={$page.url.pathname === '/graphs/tab' ? 'page' : undefined}>
<!--<li aria-current={$page.url.pathname === '/graphs/tab' ? 'page' : undefined}>
<a href="/graphs/tab">Tab 1</a>
</li>
<li aria-current={$page.url.pathname === '/graphs/tab2' ? 'page' : undefined}>
<a href="/graphs/tab2">Tab 2</a>
</li>
</li>-->
<li aria-current={$page.url.pathname === '/graphs/excel-style' ? 'page' : undefined}>
<a href="/graphs/excel-style">Excel Style</a>
</li>

View file

@ -1,96 +1,88 @@
<script lang="ts">
import SelectedGameGroupsStore from '$lib/stores/GameGroupFilter';
import SelectedGameStore from '$lib/stores/GameFilter';
import {
createChellarisInfo,
type ChellarisGameGroup,
type ChellarisInfo,
type ChellarisGame,
createChellarisGame,
type ChellarisEmpire
} from '$lib/types/chellaris';
import type { ChellarisGameGroup, ChellarisInfo, ChellarisEmpire, ChellarisGame } from '$lib/types/chellaris';
import ChellarisDataStore from '$lib/stores/ChellarisData';
import GraphsTabStore from '$lib/stores/GraphsTab';
import type { LayoutData } from '../$types';
import type { Ethic } from '$lib/types/stellaris';
import { page } from '$app/stores';
import LoadingSpinner from '$lib/components/LoadingSpinner.svelte';
export let data: LayoutData;
let selectedGameGroups: Array<number> = [];
let selectedGameGroupsMap: Map<number, Array<number>> = new Map();
let gameGroups: Map<number, ChellarisGameGroup> = new Map();
let chellarisData: ChellarisInfo = data.chellarisData;
let selectedGameIdx: number;
let selectedGame: ChellarisGame = createChellarisGame();
$: selectedGame = $ChellarisDataStore.games[$SelectedGameStore];
$: selectedGameGroupData = $SelectedGameGroupsStore[$SelectedGameStore];
$: groupNoun = selectedGameGroupData.selectedGroups.length > 1 ? 'Groups' : 'Group';
$: groupJoiner = selectedGameGroupData.selectedGroups.length > 2 ? ', ' : ' & ';
let groupPortraitLimit: number;
$: {
let containsNA = false;
selectedGameGroupData.selectedGroups.forEach((selection) => {
if ($ChellarisDataStore.games[$SelectedGameStore].groups[selection]?.name == 'N/A') {
containsNA = true;
}
});
groupPortraitLimit = containsNA ? $ChellarisDataStore.games[$SelectedGameStore].groups.length - 1 : selectedGameGroupData.selectedGroups.length;
}
let pageData: {
init: boolean;
empireCount: number;
gestaltCount: { total: number; machines: number };
ethicsData: Map<
number,
{
ethicsData: Array<{
id: number;
machine: boolean;
displayName: string;
regular: number;
fanatic: number;
}
>;
takenPortraits: Map<number, Map<number, number>>;
}>;
takenPortraits: Array<Array<[number, Array<number>]>>; // <SpeciesGroup, <Portrait, <SumTaken, <GroupsTaken>>>>
};
$: {
console.log('Reran'); // DEBUG
let newPageData: {
init: boolean;
empireCount: number;
gestaltCount: { total: number; machines: number };
ethicsData: Array<{
id: number;
machine: boolean;
displayName: string;
regular: number;
fanatic: number;
}>;
takenPortraits: Array<Array<[number, Array<number>]>>; // <SpeciesGroup, <Portrait, <SumTaken, <GroupsTaken>>>>
} = {
init: false,
empireCount: 0,
gestaltCount: { total: 0, machines: 0 },
ethicsData: new Map(),
takenPortraits: new Map()
ethicsData: [],
takenPortraits: []
};
// Save Tab to Store
GraphsTabStore.update(() => 'excel-style');
const updateGameGroups = () => {
let tmpData;
if (!selectedGame) {
tmpData = chellarisData.games.get(chellarisData.games.keys().next().value);
} else {
tmpData = chellarisData.games.get(selectedGameIdx);
}
if (typeof tmpData !== 'undefined') {
gameGroups = tmpData.groups;
}
};
const updatePageData = () => {
const tmpGameData = chellarisData.games.get(selectedGameIdx);
if (typeof tmpGameData !== 'undefined') {
const groupEmpires: Map<number, ChellarisEmpire> = new Map();
pageData.ethicsData = new Map();
pageData.takenPortraits = new Map();
pageData.gestaltCount = { total: 0, machines: 0 };
chellarisData.ethics.forEach((ethic, id) => {
if (selectedGame) {
// Empty init of Ethics Data
$ChellarisDataStore.ethics.forEach((ethic) => {
const newEthicsData: {
id: number;
machine: boolean;
displayName: string;
regular: number;
fanatic: number;
} = {
id: ethic.id,
machine: ethic.machine,
displayName: ethic.displayName,
regular: 0,
fanatic: 0
};
pageData.ethicsData.set(id, newEthicsData);
newPageData.ethicsData[ethic.id] = newEthicsData;
});
tmpGameData.empires.forEach((empire, index) => {
if (selectedGameGroups.includes(empire.group)) {
groupEmpires.set(index, empire);
selectedGame.empires.forEach((empire, index) => {
if (selectedGameGroupData.selectedGroups.includes(empire.group)) {
newPageData.empireCount = newPageData.empireCount + 1;
if (empire.gestalt) {
pageData.gestaltCount.total = pageData.gestaltCount.total + 1;
newPageData.gestaltCount.total = newPageData.gestaltCount.total + 1;
let machine = false;
empire.ethics.forEach((ethic) => {
@ -100,12 +92,12 @@
});
if (machine) {
pageData.gestaltCount.machines = pageData.gestaltCount.machines + 1;
newPageData.gestaltCount.machines = newPageData.gestaltCount.machines + 1;
}
}
empire.ethics.forEach((ethic, id) => {
const tmpEthicPageData = pageData.ethicsData.get(id);
const tmpEthicPageData = newPageData.ethicsData[id];
if (typeof tmpEthicPageData !== 'undefined') {
tmpEthicPageData.displayName = ethic.displayName;
@ -115,14 +107,16 @@
tmpEthicPageData.fanatic = tmpEthicPageData.fanatic + 1;
}
pageData.ethicsData.set(id, tmpEthicPageData);
newPageData.ethicsData[id] = tmpEthicPageData;
} else {
let newEthicsData: {
id: number;
machine: boolean;
displayName: string;
regular: number;
fanatic: number;
} = {
id: ethic.id,
machine: ethic.machine,
displayName: ethic.displayName,
regular: 0,
@ -135,72 +129,53 @@
newEthicsData.fanatic = 1;
}
pageData.ethicsData.set(id, newEthicsData);
newPageData.ethicsData[id] = newEthicsData;
}
});
if (!pageData.takenPortraits.has(empire.empire_portrait_group)) {
pageData.takenPortraits.set(empire.empire_portrait_group, new Map());
if (typeof newPageData.takenPortraits[empire.empire_portrait_group] === 'undefined') {
newPageData.takenPortraits[empire.empire_portrait_group] = [];
}
const portraitGroupData = pageData.takenPortraits.get(empire.empire_portrait_group);
const portraitGroupData = newPageData.takenPortraits[empire.empire_portrait_group];
if (typeof portraitGroupData !== 'undefined') {
if (!portraitGroupData.has(empire.empire_portrait)) {
portraitGroupData.set(empire.empire_portrait, 0);
if (typeof portraitGroupData[empire.empire_portrait] === 'undefined') {
portraitGroupData[empire.empire_portrait] = [0, []];
}
let portraitData = portraitGroupData.get(empire.empire_portrait);
let portraitData = portraitGroupData[empire.empire_portrait];
if (typeof portraitData !== 'undefined') {
portraitData = portraitData + 1;
portraitGroupData.set(empire.empire_portrait, portraitData);
pageData.takenPortraits.set(empire.empire_portrait_group, portraitGroupData);
portraitData[0] = portraitData[0] + 1;
portraitData[1].push(empire.group);
portraitGroupData[empire.empire_portrait] = portraitData;
newPageData.takenPortraits[empire.empire_portrait_group] = portraitGroupData;
}
}
}
});
pageData.empireCount = groupEmpires.size;
pageData.init = true;
}
};
ChellarisDataStore.subscribe((data) => {
chellarisData = data;
updateGameGroups();
// TODO Update selection if Groups Differ? Does this value ever even update without a full page reload?
});
SelectedGameStore.subscribe((selection) => {
selectedGameIdx = selection;
const tmpGameData = chellarisData.games.get(selectedGameIdx);
if (typeof tmpGameData !== 'undefined') {
selectedGame = tmpGameData;
// Fill undefined Portrait Info with default information.
for (let i = 0; i < $ChellarisDataStore.species.length; i++) {
if (typeof newPageData.takenPortraits[i] === 'undefined') {
newPageData.takenPortraits[i] = [];
}
updateGameGroups();
if (selectedGameGroupsMap.size != 0) {
const tmp = selectedGameGroupsMap.get(selectedGameIdx);
if (typeof tmp !== 'undefined') {
selectedGameGroups = [...tmp.values()];
for (let ii = 0; ii < $ChellarisDataStore.species[i].portraits.length; ii++) {
if (typeof newPageData.takenPortraits[i][ii] === 'undefined') {
newPageData.takenPortraits[i][ii] = [0, []];
}
}
}
updatePageData();
});
SelectedGameGroupsStore.subscribe((selection) => {
selectedGameGroupsMap = selection;
const tmp = selection.get(selectedGameIdx);
if (typeof tmp !== 'undefined') {
selectedGameGroups = [...tmp.values()];
newPageData.init = true;
}
updatePageData();
});
const groupNoun = selectedGameGroups.length > 1 ? 'Groups' : 'Group';
const groupJoiner = selectedGameGroups.length > 2 ? ', ' : ' & ';
pageData = newPageData;
}
// Save Tab to Store
GraphsTabStore.update(() => 'excel-style');
</script>
<svelte:head>
@ -211,7 +186,7 @@
{#if pageData.init}
<h1>
{selectedGame.name} Sign-Up Info for {groupNoun}
{selectedGameGroups.map((selection) => gameGroups.get(selection)?.name).join(groupJoiner)}
{selectedGameGroupData.selectedGroups.map((selection) => $ChellarisDataStore.games[$SelectedGameStore].groups[selection]?.name).join(groupJoiner)}
</h1>
<div class="text-column">
@ -227,11 +202,11 @@
<th># Fanatic</th>
</tr>
{#each pageData.ethicsData as ethicData}
{#if !ethicData[1].machine}
{#if ethicData && !ethicData.machine}
<tr>
<td class="table-label">{ethicData[1].displayName}</td>
<td>{ethicData[1].regular}</td>
<td>{ethicData[1].fanatic}</td>
<td class="table-label">{ethicData.displayName}</td>
<td>{ethicData.regular}</td>
<td>{ethicData.fanatic}</td>
</tr>
{/if}
{/each}
@ -247,10 +222,10 @@
<th>#</th>
</tr>
{#each pageData.ethicsData as ethicData}
{#if ethicData[1].machine}
{#if ethicData && ethicData.machine}
<tr>
<td class="table-label">{ethicData[1].displayName}</td>
<td>{ethicData[1].regular}</td>
<td class="table-label">{ethicData.displayName}</td>
<td>{ethicData.regular}</td>
</tr>
{/if}
{/each}
@ -266,37 +241,32 @@
<th>{index + 1}</th>
{/each}
</tr>
{#each chellarisData.species as portraitGroup}
{#each $ChellarisDataStore.species ?? false as portraitGroup}
{#if portraitGroup}
<tr>
<td>{portraitGroup[1].displayName}</td>
{#each portraitGroup[1].portraits as portrait}
<td>{portraitGroup.displayName}</td>
{#each portraitGroup.portraits ?? false as portrait}
{#if portrait}
<td
class="image-box"
style="--color-hovered-portrait: {gameGroups.size -
1 -
(pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) || 0) ==
0
style="--color-hovered-portrait: {groupPortraitLimit - pageData.takenPortraits[portraitGroup.id][portrait.id][0] == 0
? 'var(--color-warn-2)'
: gameGroups.size -
1 -
(pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) || 0) !=
gameGroups.size - 1
: groupPortraitLimit - pageData.takenPortraits[portraitGroup.id][portrait.id][0] != groupPortraitLimit
? 'var(--color-warn-1)'
: 'var(--color-bg)'}"
>
<input
id={portraitGroup[0] + '-' + portrait[0]}
id={portraitGroup.id + '-' + portrait.id}
type="image"
src={"../"+ portrait[1].lores}
alt={portraitGroup[1].displayName + '-' + portrait[0]}
src={'../' + portrait.lores}
alt={portraitGroup.displayName + '-' + portrait.id}
/>
<label for={portraitGroup[0] + '-' + portrait[0]}
>{pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) ||
0}/{gameGroups.size - 1}</label
>
<label for={portraitGroup.id + '-' + portrait.id}>{pageData.takenPortraits[portraitGroup.id][portrait.id][0]}/{groupPortraitLimit}</label>
</td>
{/if}
{/each}
</tr>
{/if}
{/each}
</table>
</div>

View file

@ -1,56 +1,14 @@
<script lang="ts">
import SelectedGameGroupsStore from '$lib/stores/GameGroupFilter';
import SelectedGameStore from '$lib/stores/GameFilter';
import { createChellarisInfo, type ChellarisGameGroup, type ChellarisInfo } from '$lib/types/chellaris';
import ChellarisDataStore from '$lib/stores/ChellarisData';
import GraphsTabStore from '$lib/stores/GraphsTab';
let selectedGameGroups: Array<string> = [];
let selectedGameGroupsMap: Map<string, Array<string>> = new Map();
let gameGroups: Map<string, ChellarisGameGroup> = new Map();
let chellarisData = createChellarisInfo();
let selectedGame = '';
// Save Tab to Store
GraphsTabStore.update(() => 'tab');
const updateGameGroups = () => {
let tmpData;
if (selectedGame == '') {
tmpData = chellarisData.games.get(chellarisData.games.keys().next().value);
} else {
tmpData = chellarisData.games.get(selectedGame);
}
if (typeof tmpData !== 'undefined') {
gameGroups = tmpData.groups;
}
};
ChellarisDataStore.subscribe((data) => {
chellarisData = data;
updateGameGroups();
// TODO Update selection if Groups Differ? Does this value ever even update without a full page reload?
});
SelectedGameStore.subscribe((selection) => {
selectedGame = selection;
if (selectedGameGroupsMap.size != 0) {
const tmp = selectedGameGroupsMap.get(selectedGame);
if (typeof tmp !== 'undefined') {
selectedGameGroups = [...tmp.values()];
}
}
});
SelectedGameGroupsStore.subscribe((selection) => {
selectedGameGroupsMap = selection;
const tmp = selection.get(selectedGame);
if (typeof tmp !== 'undefined') {
selectedGameGroups = [...tmp.values()];
}
});
$: selectedGroups = $SelectedGameGroupsStore[$SelectedGameStore].selectedGroups;
$: groupJoiner = selectedGroups.length > 2 ? ', ' : ' & ';
</script>
<svelte:head>
@ -61,7 +19,7 @@
<h1>Example Tab</h1>
<p>
{selectedGameGroups.length > 1 ? 'Groups' : 'Group'}
{selectedGameGroups.map((selection) => gameGroups.get(selection)?.name).join(', ')}
{selectedGameGroups.length > 1 ? 'are' : 'is'} selected
{selectedGroups.length > 1 ? 'Groups' : 'Group'}
{selectedGroups.map((selection) => $ChellarisDataStore.games[$SelectedGameStore].groups[selection]?.name).join(groupJoiner)}
{selectedGroups.length > 1 ? 'are' : 'is'} selected
</p>