Portrait Table
This commit is contained in:
parent
39f813bec3
commit
5768a15876
7 changed files with 169 additions and 55 deletions
|
@ -1,10 +1,7 @@
|
||||||
import { writable, type Writable } from "svelte/store";
|
import { writable, type Writable } from "svelte/store";
|
||||||
import type { ChellarisInfo } from '../types/chellaris';
|
import type { ChellarisInfo } from '../types/chellaris';
|
||||||
|
import { createChellarisInfo } from '../types/chellaris';
|
||||||
|
|
||||||
const ChellarisDataStore: Writable<ChellarisInfo> = writable({
|
const ChellarisDataStore: Writable<ChellarisInfo> = writable(createChellarisInfo());
|
||||||
games: new Map(),
|
|
||||||
ethics: [],
|
|
||||||
portraits: []
|
|
||||||
});
|
|
||||||
|
|
||||||
export default ChellarisDataStore;
|
export default ChellarisDataStore;
|
|
@ -1,8 +1,8 @@
|
||||||
import type { Ethic } from './stellaris';
|
import type { Ethic, Species } from './stellaris';
|
||||||
export interface ChellarisInfo {
|
export interface ChellarisInfo {
|
||||||
games: Map<number, ChellarisGame>, // Key is Game Id
|
games: Map<number, ChellarisGame>, // Key is Game Id
|
||||||
ethics: Map<number, Ethic>, // TODO implement
|
ethics: Map<number, Ethic>, // Key is Ethic Id
|
||||||
portraits: Array<null>, // TODO implement
|
species: Map<number, Species>, // Key is Species Group Id
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ChellarisGame = {
|
export type ChellarisGame = {
|
||||||
|
@ -29,7 +29,7 @@ export const createChellarisInfo = (): ChellarisInfo => {
|
||||||
const newChellarisInfo = {
|
const newChellarisInfo = {
|
||||||
games: new Map(),
|
games: new Map(),
|
||||||
ethics: new Map(),
|
ethics: new Map(),
|
||||||
portraits: []
|
species: new Map(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return newChellarisInfo;
|
return newChellarisInfo;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export enum Species {
|
export enum SpeciesLegacy {
|
||||||
Humanoid = 0,
|
Humanoid = 0,
|
||||||
Mammalian = 1,
|
Mammalian = 1,
|
||||||
Reptilian = 2,
|
Reptilian = 2,
|
||||||
|
@ -31,13 +31,7 @@ export enum LegacyEthics {
|
||||||
Industrialist = 13,
|
Industrialist = 13,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Ethic = {
|
export enum LegacyEthicsScale {
|
||||||
displayName: string,
|
|
||||||
machine: boolean
|
|
||||||
fanatic?: boolean,
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum Scale {
|
|
||||||
normal = 1,
|
normal = 1,
|
||||||
fanatic = 2,
|
fanatic = 2,
|
||||||
}
|
}
|
||||||
|
@ -47,8 +41,8 @@ export class EthicsDataLegacy {
|
||||||
private data: Array<number> = [0]
|
private data: Array<number> = [0]
|
||||||
|
|
||||||
constructor(data: Array<number>) {
|
constructor(data: Array<number>) {
|
||||||
this.data[Scale.normal] = data[0],
|
this.data[LegacyEthicsScale.normal] = data[0],
|
||||||
this.data[Scale.fanatic] = data[1]
|
this.data[LegacyEthicsScale.fanatic] = data[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
sum(weigthed: boolean): number {
|
sum(weigthed: boolean): number {
|
||||||
|
@ -66,6 +60,22 @@ export class EthicsDataLegacy {
|
||||||
}
|
}
|
||||||
|
|
||||||
sumRegular(): number {
|
sumRegular(): number {
|
||||||
return this.data[Scale.normal];
|
return this.data[LegacyEthicsScale.normal];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Ethic = {
|
||||||
|
displayName: string,
|
||||||
|
machine: boolean,
|
||||||
|
fanatic?: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Species = {
|
||||||
|
displayName: string,
|
||||||
|
portraits: Map<number, Portrait>, // Key is Portrait Id
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Portrait = {
|
||||||
|
imageLink: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,36 @@ export const load: LayoutLoad = async () => {
|
||||||
empireData.ethics.set(empireEthic.ethics_id, tmpEthic);
|
empireData.ethics.set(empireEthic.ethics_id, tmpEthic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const portraitGroups: {
|
||||||
|
id: number,
|
||||||
|
name: string
|
||||||
|
}[] = await (await fetch(apiBaseUrl + '/portrait_groups')).json();
|
||||||
|
|
||||||
|
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 portraits: {
|
||||||
|
id: number,
|
||||||
|
href: string,
|
||||||
|
group_id: number
|
||||||
|
}[] = await (await fetch(apiBaseUrl + '/portraits')).json();
|
||||||
|
|
||||||
|
portraits.sort((a, b) => (a.id < b.id ? -1 : 1));
|
||||||
|
|
||||||
|
portraits.forEach(portrait => {
|
||||||
|
const portraitGroupData = chellarisData.species.get(portrait.group_id);
|
||||||
|
|
||||||
|
if (typeof portraitGroupData !== "undefined") {
|
||||||
|
const newPortraitData = { imageLink: portrait.href };
|
||||||
|
|
||||||
|
portraitGroupData.portraits.set(portrait.id, newPortraitData);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
ChellarisDataStore.set(chellarisData);
|
ChellarisDataStore.set(chellarisData);
|
||||||
|
|
|
@ -34,10 +34,12 @@
|
||||||
fanatic: number;
|
fanatic: number;
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
|
takenPortraits: Map<number, Map<number, number>>;
|
||||||
} = {
|
} = {
|
||||||
empireCount: 0,
|
empireCount: 0,
|
||||||
gestaltCount: { total: 0, machines: 0 },
|
gestaltCount: { total: 0, machines: 0 },
|
||||||
ethicsData: new Map()
|
ethicsData: new Map(),
|
||||||
|
takenPortraits: new Map(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Save Tab to Store
|
// Save Tab to Store
|
||||||
|
@ -62,22 +64,23 @@
|
||||||
if (typeof tmpGameData !== 'undefined') {
|
if (typeof tmpGameData !== 'undefined') {
|
||||||
const groupEmpires: Map<number, ChellarisEmpire> = new Map();
|
const groupEmpires: Map<number, ChellarisEmpire> = new Map();
|
||||||
pageData.ethicsData = new Map();
|
pageData.ethicsData = new Map();
|
||||||
|
pageData.takenPortraits = new Map();
|
||||||
pageData.gestaltCount = { total: 0, machines: 0 };
|
pageData.gestaltCount = { total: 0, machines: 0 };
|
||||||
|
|
||||||
chellarisData.ethics.forEach((ethic, id) => {
|
chellarisData.ethics.forEach((ethic, id) => {
|
||||||
const newEthicsData: {
|
const newEthicsData: {
|
||||||
machine: boolean;
|
machine: boolean;
|
||||||
displayName: string;
|
displayName: string;
|
||||||
regular: number;
|
regular: number;
|
||||||
fanatic: number;
|
fanatic: number;
|
||||||
} = {
|
} = {
|
||||||
machine: ethic.machine,
|
machine: ethic.machine,
|
||||||
displayName: ethic.displayName,
|
displayName: ethic.displayName,
|
||||||
regular: 0,
|
regular: 0,
|
||||||
fanatic: 0
|
fanatic: 0
|
||||||
};
|
};
|
||||||
pageData.ethicsData.set(id, newEthicsData);
|
pageData.ethicsData.set(id, newEthicsData);
|
||||||
})
|
});
|
||||||
|
|
||||||
tmpGameData.empires.forEach((empire, index) => {
|
tmpGameData.empires.forEach((empire, index) => {
|
||||||
if (selectedGameGroups.includes(empire.group)) {
|
if (selectedGameGroups.includes(empire.group)) {
|
||||||
|
@ -87,7 +90,7 @@
|
||||||
pageData.gestaltCount.total = pageData.gestaltCount.total + 1;
|
pageData.gestaltCount.total = pageData.gestaltCount.total + 1;
|
||||||
|
|
||||||
let machine = false;
|
let machine = false;
|
||||||
empire.ethics.forEach(ethic => {
|
empire.ethics.forEach((ethic) => {
|
||||||
if (ethic.machine) {
|
if (ethic.machine) {
|
||||||
machine = true;
|
machine = true;
|
||||||
}
|
}
|
||||||
|
@ -132,6 +135,25 @@
|
||||||
pageData.ethicsData.set(id, newEthicsData);
|
pageData.ethicsData.set(id, newEthicsData);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!pageData.takenPortraits.has(empire.empire_portrait_group)) {
|
||||||
|
pageData.takenPortraits.set(empire.empire_portrait_group, new Map());
|
||||||
|
}
|
||||||
|
const portraitGroupData = pageData.takenPortraits.get(empire.empire_portrait_group);
|
||||||
|
|
||||||
|
if (typeof portraitGroupData !== "undefined") {
|
||||||
|
if (!portraitGroupData.has(empire.empire_portrait)) {
|
||||||
|
portraitGroupData.set(empire.empire_portrait, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let portraitData = portraitGroupData.get(empire.empire_portrait);
|
||||||
|
|
||||||
|
if (typeof portraitData !== "undefined") {
|
||||||
|
portraitData = portraitData + 1;
|
||||||
|
portraitGroupData.set(empire.empire_portrait, portraitData);
|
||||||
|
pageData.takenPortraits.set(empire.empire_portrait_group, portraitGroupData);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
pageData.empireCount = groupEmpires.size;
|
pageData.empireCount = groupEmpires.size;
|
||||||
|
@ -230,25 +252,34 @@
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<div class="text-column">
|
<section>
|
||||||
<div class="row">
|
<div class="text-column">
|
||||||
<p>Portrait 1</p>
|
<table>
|
||||||
<p>Portrait 2</p>
|
<tr>
|
||||||
<p>Portrait 3</p>
|
<th>Species</th>
|
||||||
|
{#each Array(18) as _, index (index)}
|
||||||
|
<th>{index + 1}</th>
|
||||||
|
{/each}
|
||||||
|
</tr>
|
||||||
|
{#each chellarisData.species as portraitGroup}
|
||||||
|
<tr>
|
||||||
|
<td>{portraitGroup[1].displayName}</td>
|
||||||
|
{#each portraitGroup[1].portraits as portrait}
|
||||||
|
<td class="image-box" style="--color-hovered-portrait: {
|
||||||
|
(gameGroups.size - 1) - (pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) || 0) == 0 ? "var(--color-warn-2)" :
|
||||||
|
(gameGroups.size - 1) - (pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) || 0) != (gameGroups.size - 1) ? "var(--color-warn-1)" : "var(--color-bg)"}">
|
||||||
|
<input id={portraitGroup[0] + "-" + portrait[0]} type="image" src={portrait[1].imageLink} alt={portraitGroup[1].displayName + "-" + portrait[0]}>
|
||||||
|
<label for={portraitGroup[0] + "-" + portrait[0]}>{pageData.takenPortraits.get(portraitGroup[0])?.get(portrait[0]) || 0}/{gameGroups.size - 1}</label>
|
||||||
|
</td>
|
||||||
|
{/each}
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
</section>
|
||||||
<p>Portrait 1</p>
|
|
||||||
<p>Portrait 2</p>
|
|
||||||
<p>Portrait 3</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
table {
|
|
||||||
border: 1px solid var(--color-text);
|
|
||||||
}
|
|
||||||
|
|
||||||
th,
|
th,
|
||||||
td {
|
td {
|
||||||
padding: 0.3rem 0.5rem;
|
padding: 0.3rem 0.5rem;
|
||||||
|
@ -275,8 +306,52 @@
|
||||||
.ethics-column {
|
.ethics-column {
|
||||||
min-width: fit-content;
|
min-width: fit-content;
|
||||||
}
|
}
|
||||||
.row {
|
|
||||||
display: flex;
|
.image-box input {
|
||||||
flex-direction: row;
|
padding-top: 0.3rem;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
object-fit: contain;
|
||||||
|
top: 0px;
|
||||||
|
left: -0.25rem;
|
||||||
|
width: 2.5rem;
|
||||||
|
height: 2.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image-box label {
|
||||||
|
position: relative;
|
||||||
|
top: 25%;
|
||||||
|
cursor: pointer;
|
||||||
|
text-shadow: 0 0 2px var(--color-bg), 0 0 0px var(--color-text);
|
||||||
|
font-size: medium;
|
||||||
|
font-weight: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-box {
|
||||||
|
padding: 0;
|
||||||
|
position: relative;
|
||||||
|
background-color: var(--color-hovered-portrait);
|
||||||
|
border: 1px solid var(--color-text);
|
||||||
|
min-width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-box:hover {
|
||||||
|
z-index: 100;
|
||||||
|
transform: scale(170%);
|
||||||
|
transition-property: transform border-color;
|
||||||
|
transition-duration: 0.1s;
|
||||||
|
transition-timing-function: linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-box:hover label {
|
||||||
|
font-size: small;
|
||||||
|
font-weight: 100;
|
||||||
|
top: 20%;
|
||||||
|
transition-property: font-size top color;
|
||||||
|
transition-duration: 0.1s;
|
||||||
|
transition-timing-function: linear;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Pie } from 'svelte-chartjs';
|
import { Pie } from 'svelte-chartjs';
|
||||||
import { Species } from '$lib/types/stellaris';
|
import { SpeciesLegacy } from '$lib/types/stellaris';
|
||||||
|
|
||||||
import { Chart as ChartJS, registerables } from 'chart.js';
|
import { Chart as ChartJS, registerables } from 'chart.js';
|
||||||
import ChartDataLabels from 'chartjs-plugin-datalabels';
|
import ChartDataLabels from 'chartjs-plugin-datalabels';
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
const chart_data = {
|
const chart_data = {
|
||||||
labels: data.popsData.map((_elem: any, idx: number) => {
|
labels: data.popsData.map((_elem: any, idx: number) => {
|
||||||
return Species[idx];
|
return SpeciesLegacy[idx];
|
||||||
}),
|
}),
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
datalabels: {
|
datalabels: {
|
||||||
formatter: (value: number, context: any) => {
|
formatter: (value: number, context: any) => {
|
||||||
if (value > 0) {
|
if (value > 0) {
|
||||||
return Species[context.dataIndex];
|
return SpeciesLegacy[context.dataIndex];
|
||||||
} else {
|
} else {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
--color-bg: #1a1a1a;
|
--color-bg: #1a1a1a;
|
||||||
--color-active-1: #00c4a3;
|
--color-active-1: #00c4a3;
|
||||||
--color-active-2: #4075a6;
|
--color-active-2: #4075a6;
|
||||||
|
--color-warn-1: #FF9900;
|
||||||
|
--color-warn-2: #EA4335;
|
||||||
--color-text: rgba(255, 255, 255, 0.7);
|
--color-text: rgba(255, 255, 255, 0.7);
|
||||||
--column-width: 42rem;
|
--column-width: 42rem;
|
||||||
--column-margin-top: 4rem;
|
--column-margin-top: 4rem;
|
||||||
|
|
Reference in a new issue