Merge branch 'battle-result'
This commit is contained in:
commit
834b317b2f
@ -2,5 +2,6 @@ import { defineConfig } from 'histoire';
|
|||||||
import { HstSvelte } from '@histoire/plugin-svelte';
|
import { HstSvelte } from '@histoire/plugin-svelte';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
setupFile: '/src/histoire.setup.js',
|
||||||
plugins: [HstSvelte()],
|
plugins: [HstSvelte()],
|
||||||
});
|
});
|
||||||
|
1
src/histoire.setup.js
Normal file
1
src/histoire.setup.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
//global?.__SVELTEKIT_APP_VERSION_POLL_INTERVAL__ = 1000;
|
@ -1,5 +0,0 @@
|
|||||||
<script>
|
|
||||||
import 'beercss';
|
|
||||||
</script>
|
|
||||||
|
|
||||||
; // import 'material-dynamic-colors';
|
|
25
src/lib/components/Battle.story.svelte
Normal file
25
src/lib/components/Battle.story.svelte
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<Beer />
|
||||||
|
<Hst.Story>
|
||||||
|
<Battle {status} />
|
||||||
|
|
||||||
|
<svelte:fragment slot="controls">
|
||||||
|
<Hst.Select
|
||||||
|
bind:value={status}
|
||||||
|
title="status"
|
||||||
|
options={Object.fromEntries(statuses.map((s) => [s, s]))}
|
||||||
|
/>
|
||||||
|
<Hst.Number bind:value={wave} title="wave" />
|
||||||
|
</svelte:fragment>
|
||||||
|
</Hst.Story>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/** @type any */
|
||||||
|
export let Hst;
|
||||||
|
import Beer from './Beer.svelte';
|
||||||
|
import Battle from './Battle.svelte';
|
||||||
|
|
||||||
|
let status = 'upcoming';
|
||||||
|
let wave = '1';
|
||||||
|
|
||||||
|
let statuses = ['upcoming', 'prep', 'ongoing', 'won', 'lost'];
|
||||||
|
</script>
|
124
src/lib/components/Battle.svelte
Normal file
124
src/lib/components/Battle.svelte
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<h5><a href={`#/campaign/${params.campaignId}`}>{$activeCampaign?.name}</a></h5>
|
||||||
|
<h6>Chapter {chapter}, battle {chapterBattle} -- {status}</h6>
|
||||||
|
<dl>
|
||||||
|
{#if status === 'ongoing'}
|
||||||
|
<dt>wave</dt>
|
||||||
|
<dd>{wave === 2 ? 'second' : 'first'}</dd>
|
||||||
|
{/if}
|
||||||
|
<dt>city</dt>
|
||||||
|
<dd>{city}</dd>
|
||||||
|
<dt>scenario</dt>
|
||||||
|
<dd>{scenario}</dd>
|
||||||
|
<dt>character</dt>
|
||||||
|
<dd>{character}</dd>
|
||||||
|
|
||||||
|
<dt>difficulty</dt>
|
||||||
|
<dd>
|
||||||
|
<div class="field border">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.5"
|
||||||
|
value={difficulty}
|
||||||
|
on:change={({ target: { value } }) =>
|
||||||
|
event.setBattleDifficulty(params.battleId, value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<Stars
|
||||||
|
on:change={(e) => (difficulty = e.target.value)}
|
||||||
|
config={{
|
||||||
|
readOnly: false, //status !== 'preparation',
|
||||||
|
countStars: 5,
|
||||||
|
score: difficulty,
|
||||||
|
showScore: false,
|
||||||
|
starConfig: {
|
||||||
|
size: 15,
|
||||||
|
fillColor: '#F9ED4F',
|
||||||
|
strokeColor: '#BB8511',
|
||||||
|
unfilledColor: '#FFF',
|
||||||
|
strokeUnfilledColor: '#000',
|
||||||
|
},
|
||||||
|
range: { min: 0, max: 5, step: 0.5 },
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{difficulty}
|
||||||
|
-->
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
{#if status === 'upcoming'}
|
||||||
|
<button>Start battle</button>
|
||||||
|
{:else if status === 'ongoing'}
|
||||||
|
<button on:click={battleVerdict('won')}>Battle won</button>
|
||||||
|
<button on:click={battleVerdict('lost')}>Battle lost</button>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getContext } from 'svelte';
|
||||||
|
import Stars from '@ernane/svelte-star-rating';
|
||||||
|
|
||||||
|
export let params;
|
||||||
|
|
||||||
|
const { activeCampaign, event } = getContext('api');
|
||||||
|
|
||||||
|
event.setActiveCampaign(params.campaignId);
|
||||||
|
|
||||||
|
$: battles = $activeCampaign?.battles;
|
||||||
|
$: battle = battles && battles[params.battleId - 1];
|
||||||
|
$: console.log($activeCampaign);
|
||||||
|
$: scenario = battle?.scenario;
|
||||||
|
$: status = battle?.status;
|
||||||
|
$: wave = battle?.wave;
|
||||||
|
$: difficulty = battle?.difficulty ?? 0;
|
||||||
|
$: character = battle?.character;
|
||||||
|
$: city = battle?.city;
|
||||||
|
|
||||||
|
$: console.log(battle);
|
||||||
|
|
||||||
|
let chapter = 1 + parseInt(params.battleId / 2);
|
||||||
|
let chapterBattle = params.battleId % 2;
|
||||||
|
|
||||||
|
const battleVerdict = (verdict) =>
|
||||||
|
event.setBattleVerdict(params.battleId, verdict);
|
||||||
|
|
||||||
|
// $: event.setBattleDifficulty(params.battleId, difficulty);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
article {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
h5 {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
h6 {
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
dl {
|
||||||
|
width: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 8em auto;
|
||||||
|
grid-row-gap: 0.75em;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
dt {
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 2em;
|
||||||
|
}
|
||||||
|
dd {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
article :global(.stars-container) {
|
||||||
|
justify-content: left !important;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
width: 5em;
|
||||||
|
}
|
||||||
|
</style>
|
64
src/lib/components/Campaign.svelte
Normal file
64
src/lib/components/Campaign.svelte
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<article>
|
||||||
|
{#if $activeCampaign}
|
||||||
|
<h5>{$activeCampaign.name}</h5>
|
||||||
|
<h6>Chapter 1</h6>
|
||||||
|
<Battle {...battles[0]} {campaignId} chapter={1} chapterBattle={1} />
|
||||||
|
<div class="medium-divider" />
|
||||||
|
<Battle {...battles[1]} {campaignId} chapter={1} chapterBattle={2} />
|
||||||
|
<div class="medium-divider" {campaignId} />
|
||||||
|
<h6>Chapter 2</h6>
|
||||||
|
<Battle {...battles[2]} {campaignId} chapter={2} chapterBattle={1} />
|
||||||
|
<div class="medium-divider" />
|
||||||
|
<Battle {...battles[3]} {campaignId} chapter={2} chapterBattle={2} />
|
||||||
|
<div class="medium-divider" />
|
||||||
|
<h6>Chapter 3</h6>
|
||||||
|
<Battle {...battles[4]} {campaignId} chapter={3} chapterBattle={1} />
|
||||||
|
<div class="medium-divider" />
|
||||||
|
<Battle {...battles[5]} {campaignId} chapter={3} chapterBattle={2} />
|
||||||
|
<div class="medium-divider" />
|
||||||
|
<h6>Chapter 4</h6>
|
||||||
|
<Battle {...battles[6]} {campaignId} chapter={4} chapterBattle={1} />
|
||||||
|
<div class="medium-divider" />
|
||||||
|
<Battle {...battles[7]} {campaignId} chapter={4} chapterBattle={2} />
|
||||||
|
<div class="medium-divider" />
|
||||||
|
<Battle {...battles[8]} {campaignId} chapter={4} chapterBattle={3} />
|
||||||
|
<div class="medium-divider" />
|
||||||
|
<Battle {...battles[9]} {campaignId} chapter={4} chapterBattle={4} />
|
||||||
|
<div class="medium-divider" />
|
||||||
|
<Battle {...battles[10]} {campaignId} chapter={4} chapterBattle={5} />
|
||||||
|
<div class="medium-divider" />
|
||||||
|
<Battle {...battles[11]} {campaignId} chapter={4} chapterBattle={6} />
|
||||||
|
<div class="medium-divider" />
|
||||||
|
{/if}
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import * as R from 'remeda';
|
||||||
|
import Battle from './Campaign/Battle.svelte';
|
||||||
|
|
||||||
|
import { getContext } from 'svelte';
|
||||||
|
|
||||||
|
export let params;
|
||||||
|
|
||||||
|
const api = getContext('api');
|
||||||
|
|
||||||
|
api.event.setActiveCampaign(params.campaignId);
|
||||||
|
|
||||||
|
const { activeCampaign } = getContext('api');
|
||||||
|
|
||||||
|
$: battles = $activeCampaign?.battles ?? [];
|
||||||
|
|
||||||
|
$: while (battles.length <= 12) battles.push({ notYet: true });
|
||||||
|
|
||||||
|
const campaignId = params.campaignId;
|
||||||
|
|
||||||
|
$: byChapter = R.pipe(
|
||||||
|
$activeCampaign?.battles ?? [],
|
||||||
|
R.groupBy(({ id }) => R.clamp(1 + parseInt(id / 2), { max: 4 })),
|
||||||
|
);
|
||||||
|
|
||||||
|
$: console.log(byChapter);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
24
src/lib/components/Campaign/Battle.svelte
Normal file
24
src/lib/components/Campaign/Battle.svelte
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<div class="row">
|
||||||
|
<p>
|
||||||
|
{#if notYet}
|
||||||
|
???
|
||||||
|
{:else}
|
||||||
|
<a href={`#/campaign/${campaignId}/battle/${id}`}>
|
||||||
|
Battle of {city}</a
|
||||||
|
><span>, {status}</span>
|
||||||
|
{/if}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export let city = '';
|
||||||
|
export let status = '';
|
||||||
|
export let id = 0;
|
||||||
|
export let notYet = false;
|
||||||
|
export let campaignId;
|
||||||
|
export let chapter;
|
||||||
|
export let chapterBattle;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
@ -5,9 +5,21 @@
|
|||||||
</Hst.Story>
|
</Hst.Story>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { setContext } from 'svelte';
|
||||||
|
|
||||||
export let Hst;
|
export let Hst;
|
||||||
import Beer from './Beer.svelte';
|
import Beer from './Beer.svelte';
|
||||||
import Campaigns from './Campaigns.svelte';
|
import Campaigns from './Campaigns.svelte';
|
||||||
|
import { genApi } from '$lib/store/api.js';
|
||||||
|
|
||||||
|
global.__SVELTEKIT_APP_VERSION_POLL_INTERVAL__ = 1000;
|
||||||
|
|
||||||
const campaigns = [{ name: 'Earth 613' }];
|
const campaigns = [{ name: 'Earth 613' }];
|
||||||
|
|
||||||
|
setContext(
|
||||||
|
'api',
|
||||||
|
genApi({
|
||||||
|
local: campaigns,
|
||||||
|
}),
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
<button on:click={newCampaign}>new campaign</button>
|
<button on:click={newCampaign}>new campaign</button>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{#each campaigns as campaign (campaign.id)}
|
{#each $campaigns as campaign (campaign.id)}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<i class="light-green-text">south_america</i>
|
<i class="light-green-text">south_america</i>
|
||||||
<div class="max">
|
<div class="max">
|
||||||
<h6>
|
<h6>
|
||||||
<a href={`/campaign/${campaign.id}`}>
|
<a href={`#/campaign/${campaign._id}`}>
|
||||||
{campaign.name}
|
{campaign.name}
|
||||||
</a>
|
</a>
|
||||||
</h6>
|
</h6>
|
||||||
@ -50,10 +50,11 @@
|
|||||||
<script>
|
<script>
|
||||||
import * as R from 'remeda';
|
import * as R from 'remeda';
|
||||||
import { getContext } from 'svelte';
|
import { getContext } from 'svelte';
|
||||||
import { goto } from '$app/navigation';
|
// import { goto } from '$app/navigation';
|
||||||
|
const goto = () => {};
|
||||||
|
|
||||||
export let campaigns = [];
|
|
||||||
export let api = getContext('api');
|
export let api = getContext('api');
|
||||||
|
export let campaigns = api?.campaigns;
|
||||||
|
|
||||||
let showNewCampaign = false;
|
let showNewCampaign = false;
|
||||||
let newCampaignName = '';
|
let newCampaignName = '';
|
||||||
|
@ -1,47 +1,124 @@
|
|||||||
|
import PouchDB from 'pouchdb-browser';
|
||||||
import * as R from 'remeda';
|
import * as R from 'remeda';
|
||||||
import Dexie, { liveQuery } from 'dexie';
|
import Dexie, { liveQuery } from 'dexie';
|
||||||
import { writable, derived } from 'svelte/store';
|
import { writable, derived, get } from 'svelte/store';
|
||||||
import { genNextBattle } from './genNextBattle.js';
|
import { genNextBattle } from './genNextBattle.js';
|
||||||
|
import u from '@yanick/updeep-remeda';
|
||||||
|
|
||||||
const seedCampaign = {
|
const seedCampaign = {
|
||||||
battles: [],
|
battles: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
export function genApi(options = {}) {
|
export function genApi(options = {}) {
|
||||||
const storage = new Dexie('Campaigns', options.dexie ?? {});
|
const pouchdb = new PouchDB(
|
||||||
|
'Campaigns',
|
||||||
|
options.local
|
||||||
|
? {
|
||||||
|
adapter: 'memory',
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
);
|
||||||
|
|
||||||
storage.version(1).stores({
|
const campaignsCore = writable([]);
|
||||||
campaigns: '++id,name',
|
|
||||||
|
pouchdb
|
||||||
|
.allDocs({ include_docs: true })
|
||||||
|
.then((r) => r.rows.map(({ id, doc }) => [id, doc]))
|
||||||
|
.then(Object.fromEntries)
|
||||||
|
.then(campaignsCore.set);
|
||||||
|
|
||||||
|
pouchdb
|
||||||
|
.changes({ since: 'now', live: true, include_docs: true })
|
||||||
|
.on('change', (change) => {
|
||||||
|
console.log({ change });
|
||||||
|
if (change.deleted) {
|
||||||
|
campaignsCore.update(u.skip(change.id));
|
||||||
|
} else {
|
||||||
|
campaignsCore.update(u.updateIn(change.id, change.doc));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const campaigns = writable([]);
|
const campaigns = derived(campaignsCore, Object.values);
|
||||||
storage.campaigns.toArray().then((c) => campaigns.set(c));
|
campaigns.subscribe((c) => console.log(c));
|
||||||
|
|
||||||
const activeCampaignId = writable();
|
const addCampaign = (name) =>
|
||||||
|
pouchdb.post({
|
||||||
|
name,
|
||||||
|
...seedCampaign,
|
||||||
|
battles: [{ id: 1, ...genNextBattle() }],
|
||||||
|
});
|
||||||
|
|
||||||
|
const activeCampaignId = writable(0);
|
||||||
|
|
||||||
|
const setActiveCampaign = activeCampaignId.set;
|
||||||
|
|
||||||
const activeCampaign = derived(
|
const activeCampaign = derived(
|
||||||
[activeCampaignId, campaigns],
|
[campaignsCore, activeCampaignId],
|
||||||
async ([id, campaigns], set) => {
|
([$c, $id]) => $c[$id],
|
||||||
const x = campaigns.find((c) => c.id === id);
|
|
||||||
set(x);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const setBattleDifficulty = (battleId, difficulty) => {
|
||||||
|
pouchdb
|
||||||
|
.put(
|
||||||
|
u.updateIn(get(activeCampaign), `battles.${battleId - 1}`, {
|
||||||
|
difficulty,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.catch((e) => console.error(e));
|
||||||
|
};
|
||||||
|
|
||||||
|
const setBattleVerdict = (battleId, status) => {
|
||||||
|
let campaign = get(activeCampaign);
|
||||||
|
|
||||||
|
campaign = u.updateIn(campaign, `battles.${battleId - 1}`, {
|
||||||
|
status,
|
||||||
|
});
|
||||||
|
|
||||||
|
campaign = u(campaign, {
|
||||||
|
battles: (battles) => [
|
||||||
|
...battles,
|
||||||
|
u(genNextBattle(campaign.battles), {
|
||||||
|
id: battles.length + 1,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
pouchdb.put(campaign).catch((e) => console.error(e));
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
campaigns,
|
campaigns,
|
||||||
activeCampaign,
|
activeCampaign,
|
||||||
storage,
|
|
||||||
event: {
|
event: {
|
||||||
|
addCampaign,
|
||||||
|
setActiveCampaign,
|
||||||
|
setBattleVerdict,
|
||||||
|
setBattleDifficulty,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
const activeCampaign = writeable();
|
||||||
|
|
||||||
addCampaign: (name) =>
|
addCampaign: (name) =>
|
||||||
storage.campaigns.add({
|
storage.campaigns.add({
|
||||||
name,
|
name,
|
||||||
...seedCampaign,
|
...seedCampaign,
|
||||||
battles: [genNextBattle()],
|
battles: [{ id: 1, ...genNextBattle() }],
|
||||||
|
}),
|
||||||
|
|
||||||
|
return {
|
||||||
|
campaigns,
|
||||||
|
event: {
|
||||||
|
,
|
||||||
|
addCampaign: (name) =>
|
||||||
|
storage.campaigns.add({
|
||||||
|
name,
|
||||||
|
...seedCampaign,
|
||||||
|
battles: [{ id: 1, ...genNextBattle() }],
|
||||||
}),
|
}),
|
||||||
deleteCampaign: (id) => storage.campaigns.delete(id),
|
deleteCampaign: (id) => storage.campaigns.delete(id),
|
||||||
setActiveCampaign: async (id) => {
|
|
||||||
activeCampaignId.set(id);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,6 @@ export function genNextBattle(battles = []) {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return { scenario, character, city, status: 'upcoming' };
|
return { scenario, character, city, status: 'ongoing', wave: 1 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export const ssr = false;
|
|
@ -1,15 +0,0 @@
|
|||||||
<article>
|
|
||||||
{#if $activeCampaign}
|
|
||||||
<h5>{$activeCampaign.name}</h5>
|
|
||||||
<h6>Chapter 1</h6>
|
|
||||||
<ul>
|
|
||||||
<li>Battle of New York, ongoing</li>
|
|
||||||
</ul>
|
|
||||||
{/if}
|
|
||||||
</article>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { getContext } from 'svelte';
|
|
||||||
|
|
||||||
const { activeCampaign } = getContext('api');
|
|
||||||
</script>
|
|
Loading…
Reference in New Issue
Block a user