Merge branch 'chapter4'
This commit is contained in:
commit
1919ef3850
@ -15,7 +15,6 @@
|
|||||||
const api = genApi();
|
const api = genApi();
|
||||||
|
|
||||||
setContext('api', api);
|
setContext('api', api);
|
||||||
console.log('api set, sucka');
|
|
||||||
|
|
||||||
const routes = {
|
const routes = {
|
||||||
// Exact path
|
// Exact path
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<article class="scroll">
|
<article class="scroll">
|
||||||
<header class="fixed">
|
<header class="fixed fill">
|
||||||
<nav>
|
<nav>
|
||||||
<a href="#/">
|
<a href="#/">
|
||||||
<button class="circle transparent">
|
<button class="circle transparent">
|
||||||
<i>menu</i>
|
<i>menu</i>
|
||||||
</button></a
|
</button></a
|
||||||
>
|
>
|
||||||
<h5 class="max center-align">
|
<h5 class="max right-align">
|
||||||
{#if $activeCampaign}
|
{#if $activeCampaign}
|
||||||
<a href={`#/campaign/${$activeCampaign._id}`}>
|
<a href={`#/campaign/${$activeCampaign._id}`}>
|
||||||
{$activeCampaign.name}
|
{$activeCampaign.name}
|
||||||
@ -16,25 +16,42 @@
|
|||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
<h6>
|
<h6>
|
||||||
Chapter {chapter},
|
<span
|
||||||
<span class="battleNbr">battle {chapterBattle}</span>
|
>Chapter {chapter},
|
||||||
-- {status}
|
<span class="battleNbr">battle {chapterBattle}</span></span
|
||||||
|
>
|
||||||
|
<span class="status">{status}</span>
|
||||||
</h6>
|
</h6>
|
||||||
<dl>
|
<dl>
|
||||||
{#if status === 'ongoing'}
|
{#if status === 'ongoing' && chapter !== 4}
|
||||||
<dt>wave</dt>
|
<dt>wave</dt>
|
||||||
<dd>{wave === 2 ? 'second' : 'first'}</dd>
|
<dd>{wave === 2 ? 'second' : 'first'}</dd>
|
||||||
{/if}
|
{/if}
|
||||||
<dt>city</dt>
|
<dt><i>home</i></dt>
|
||||||
<dd>{city}</dd>
|
<dd>
|
||||||
<dt>scenario</dt>
|
{#if typeof city === 'string'}
|
||||||
|
{city}
|
||||||
|
{:else}
|
||||||
|
<AdditionalCharacter
|
||||||
|
on:change={changeCity}
|
||||||
|
selection={city.selection}
|
||||||
|
choices={status !== 'ongoing'
|
||||||
|
? []
|
||||||
|
: city.choices.filter((c) => c !== city.selection)}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</dd>
|
||||||
|
<dt><i>view_kanban</i></dt>
|
||||||
<dd>{scenario}</dd>
|
<dd>{scenario}</dd>
|
||||||
<dt>character</dt>
|
|
||||||
|
{#if character}
|
||||||
|
<dt><i>person</i></dt>
|
||||||
<dd>{character}</dd>
|
<dd>{character}</dd>
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if additionalCharacters}
|
{#if additionalCharacters}
|
||||||
{#each additionalCharacters as c, i (c.selection)}
|
{#each additionalCharacters as c, i (c.selection)}
|
||||||
<dt>add. character</dt>
|
<dt><i>person</i><i>star</i></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<AdditionalCharacter
|
<AdditionalCharacter
|
||||||
on:change={changeCharacter(i)}
|
on:change={changeCharacter(i)}
|
||||||
@ -49,7 +66,7 @@
|
|||||||
|
|
||||||
<dt>difficulty</dt>
|
<dt>difficulty</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<div class="field border">
|
<div class="field ">
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
step="0.5"
|
step="0.5"
|
||||||
@ -82,12 +99,16 @@
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
<div class="actions">
|
||||||
{#if status === 'upcoming'}
|
{#if status === 'upcoming'}
|
||||||
<button>Start battle</button>
|
<button>Start battle</button>
|
||||||
{:else if status === 'ongoing'}
|
{:else if status === 'ongoing'}
|
||||||
<button on:click={battleVerdict('won')}>Battle won</button>
|
<button on:click={battleVerdict('won')}>Battle won</button>
|
||||||
<button on:click={battleVerdict('lost')}>Battle lost</button>
|
<button class="tertiary" on:click={battleVerdict('lost')}
|
||||||
|
>Battle lost</button
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
<footer class="fixed">
|
<footer class="fixed">
|
||||||
<nav>
|
<nav>
|
||||||
@ -159,24 +180,30 @@
|
|||||||
const changeCharacter =
|
const changeCharacter =
|
||||||
(index) =>
|
(index) =>
|
||||||
({ target: { value } }) => {
|
({ target: { value } }) => {
|
||||||
event?.setCharacter(params.battleId, index, value);
|
event?.setCharacter(params?.battleId, index, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeCity = ({ target: { value } }) => {
|
||||||
|
event?.setCity(params.battleId, value);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
article {
|
article {
|
||||||
width: 500px;
|
height: 100vh;
|
||||||
}
|
min-height: 100vh;
|
||||||
header {
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
}
|
}
|
||||||
h5 {
|
h5 {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
h6 {
|
h6 {
|
||||||
font-style: italic;
|
display: flex;
|
||||||
font-size: 1.25rem;
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
h6 .status {
|
||||||
|
flex: 1;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 1em;
|
||||||
}
|
}
|
||||||
dl {
|
dl {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -203,4 +230,13 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
nav h5 {
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
header nav {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
.actions {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
{#if choices.length === 0}
|
{#if choices.length === 0}
|
||||||
{selection}
|
{selection}
|
||||||
{:else}
|
{:else}
|
||||||
|
<div class="field suffix">
|
||||||
<select on:change>
|
<select on:change>
|
||||||
<option>{selection}</option>
|
<option>{selection}</option>
|
||||||
{#each choices as c (c)}
|
{#each choices as c (c)}
|
||||||
<option>{c}</option>
|
<option>{c}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
|
<i>arrow_drop_down</i>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -14,3 +17,12 @@
|
|||||||
export let choices;
|
export let choices;
|
||||||
$: console.log(choices);
|
$: console.log(choices);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
select {
|
||||||
|
/*width: 90%;*/
|
||||||
|
}
|
||||||
|
.field {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
59
src/lib/components/Battle/Chapter4.story.svelte
Normal file
59
src/lib/components/Battle/Chapter4.story.svelte
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<Beer />
|
||||||
|
<Hst.Story>
|
||||||
|
<Battle {status} params={{ battleId: 7 }} {api} />
|
||||||
|
|
||||||
|
<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 { logEvent } from 'histoire/client';
|
||||||
|
import { readable } from 'svelte/store';
|
||||||
|
import Beer from '../Beer.svelte';
|
||||||
|
import Battle from '../Battle.svelte';
|
||||||
|
|
||||||
|
let status = 'upcoming';
|
||||||
|
let wave = '1';
|
||||||
|
|
||||||
|
const choices = ['one', 'two', 'three', 'four'];
|
||||||
|
const api = {
|
||||||
|
event: {
|
||||||
|
setCharacter: (...e) => logEvent('setCharacter', e),
|
||||||
|
setActiveCampaign: () => {},
|
||||||
|
},
|
||||||
|
activeCampaign: readable({
|
||||||
|
battles: [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
status: 'ongoing',
|
||||||
|
wave: 1,
|
||||||
|
scenario: 'The Last Battle',
|
||||||
|
city: {
|
||||||
|
choices: ['a', 'b'],
|
||||||
|
selection: 'a',
|
||||||
|
},
|
||||||
|
additionalCharacters: [
|
||||||
|
{ choices, selection: 'one' },
|
||||||
|
{ choices, selection: 'three' },
|
||||||
|
{ choices, selection: 'two' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
let statuses = ['upcoming', 'prep', 'ongoing', 'won', 'lost'];
|
||||||
|
</script>
|
@ -1,12 +1,12 @@
|
|||||||
<article class="scroll">
|
<article class="scroll">
|
||||||
<header class="fixed">
|
<header class="fixed fill">
|
||||||
<nav>
|
<nav>
|
||||||
<a href="#/">
|
<a href="#/">
|
||||||
<button class="circle transparent">
|
<button class="circle transparent">
|
||||||
<i>menu</i>
|
<i>menu</i>
|
||||||
</button></a
|
</button></a
|
||||||
>
|
>
|
||||||
<h5 class="max center-align">
|
<h5 class="max right-align">
|
||||||
{#if $activeCampaign}
|
{#if $activeCampaign}
|
||||||
{$activeCampaign.name}
|
{$activeCampaign.name}
|
||||||
{/if}
|
{/if}
|
||||||
@ -15,6 +15,14 @@
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
{#if $activeCampaign}
|
{#if $activeCampaign}
|
||||||
|
{#if status !== 'ongoing'}
|
||||||
|
<h6>{status}</h6>{/if}
|
||||||
|
|
||||||
|
<div class="score">
|
||||||
|
score {#if status !== 'ongoing'}so far{/if}: {score}
|
||||||
|
<i>star</i>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h6>Chapter 1</h6>
|
<h6>Chapter 1</h6>
|
||||||
<Battle {...battles[0]} {campaignId} chapter={1} chapterBattle={1} />
|
<Battle {...battles[0]} {campaignId} chapter={1} chapterBattle={1} />
|
||||||
<div class="medium-divider" />
|
<div class="medium-divider" />
|
||||||
@ -101,7 +109,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
<footer class="fixed">
|
<footer class="fixed">
|
||||||
<nav>
|
<nav>
|
||||||
<a href={`#/campaign/${$activeCampaign._id}/battle/1`}>
|
<a href={`#/campaign/${$activeCampaign?._id}/battle/1`}>
|
||||||
<button class="circle transparent">
|
<button class="circle transparent">
|
||||||
<i>arrow_forward</i>
|
<i>arrow_forward</i>
|
||||||
</button>
|
</button>
|
||||||
@ -128,6 +136,9 @@
|
|||||||
|
|
||||||
const campaignId = params.campaignId;
|
const campaignId = params.campaignId;
|
||||||
|
|
||||||
|
$: score = $activeCampaign?.score;
|
||||||
|
$: status = $activeCampaign?.status;
|
||||||
|
|
||||||
$: byChapter = R.pipe(
|
$: byChapter = R.pipe(
|
||||||
$activeCampaign?.battles ?? [],
|
$activeCampaign?.battles ?? [],
|
||||||
R.groupBy(({ id }) => R.clamp(1 + parseInt(id / 2), { max: 4 })),
|
R.groupBy(({ id }) => R.clamp(1 + parseInt(id / 2), { max: 4 })),
|
||||||
@ -137,6 +148,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.score {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
article {
|
article {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
@ -147,4 +161,7 @@
|
|||||||
footer nav {
|
footer nav {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
nav h5 {
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -4,8 +4,20 @@
|
|||||||
???
|
???
|
||||||
{:else}
|
{:else}
|
||||||
<a href={`#/campaign/${campaignId}/battle/${id}`}>
|
<a href={`#/campaign/${campaignId}/battle/${id}`}>
|
||||||
Battle of {city}</a
|
Battle of {typeof city === 'string' ? city : city.selection}</a
|
||||||
><span>, {status}</span>
|
>
|
||||||
|
<div>
|
||||||
|
{#if status === 'ongoing' && wave == 2}
|
||||||
|
<i style="color: yellow">mood_bad</i>
|
||||||
|
{:else if status === 'ongoing' && wave == 1}
|
||||||
|
<i style="color: blue">sentiment_neutral</i>
|
||||||
|
{:else if status === 'lost'}
|
||||||
|
<i style="color: red">sentiment_very_dissatisfied</i>
|
||||||
|
{:else if status === 'won'}
|
||||||
|
<i style="color: green">mood</i>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="difficulty">{difficulty} <i>star</i></div>
|
||||||
{/if}
|
{/if}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -14,10 +26,23 @@
|
|||||||
export let city = '';
|
export let city = '';
|
||||||
export let status = '';
|
export let status = '';
|
||||||
export let id = 0;
|
export let id = 0;
|
||||||
|
export let wave = 1;
|
||||||
export let campaignId;
|
export let campaignId;
|
||||||
export let chapter;
|
export let chapter;
|
||||||
export let chapterBattle;
|
export let chapterBattle;
|
||||||
|
export let difficulty = 0;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.row p {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.row p a {
|
||||||
|
display: inline-block;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.difficulty {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<header>
|
<header class="fixed fill">
|
||||||
<nav>
|
<nav>
|
||||||
<h5 class="max center-align">Campaigns</h5>
|
<h5 class="max center-align">Campaigns</h5>
|
||||||
<button class="circle small" on:click={newCampaign}>
|
<button class="circle small" on:click={newCampaign}>
|
||||||
@ -19,9 +19,11 @@
|
|||||||
</h6>
|
</h6>
|
||||||
<p>
|
<p>
|
||||||
{#if campaign.battles}
|
{#if campaign.battles}
|
||||||
|
<a href={`#/campaign/${campaign._id}`}>
|
||||||
chapter {currentChapter(campaign)}, battle of {currentCity(
|
chapter {currentChapter(campaign)}, battle of {currentCity(
|
||||||
campaign,
|
campaign,
|
||||||
)}.
|
)}.
|
||||||
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -32,11 +34,14 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<div class="modal" class:active={showNewCampaign}>
|
{#if showNewCampaign}
|
||||||
|
<div class="modal active">
|
||||||
|
<form>
|
||||||
<h5>New campaign</h5>
|
<h5>New campaign</h5>
|
||||||
<div>
|
<div>
|
||||||
<div class="field border">
|
<div class="field border">
|
||||||
<input
|
<input
|
||||||
|
autofocus
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={newCampaignName}
|
bind:value={newCampaignName}
|
||||||
placeholder="Campaign name"
|
placeholder="Campaign name"
|
||||||
@ -44,12 +49,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<nav class="right-align">
|
<nav class="right-align">
|
||||||
<button class="border" on:click={() => (showNewCampaign = false)}
|
<button
|
||||||
>Cancel</button
|
class="border"
|
||||||
|
on:click={() => (showNewCampaign = false)}>Cancel</button
|
||||||
>
|
>
|
||||||
<button on:click={saveNewCampaign}>Create</button>
|
<button on:click={saveNewCampaign}>Create</button>
|
||||||
</nav>
|
</nav>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import * as R from 'remeda';
|
import * as R from 'remeda';
|
||||||
@ -65,7 +73,10 @@
|
|||||||
|
|
||||||
const currentChapter = ({ battles }) =>
|
const currentChapter = ({ battles }) =>
|
||||||
R.clamp(1 + parseInt(battles?.length / 2), { max: 4 });
|
R.clamp(1 + parseInt(battles?.length / 2), { max: 4 });
|
||||||
const currentCity = ({ battles }) => R.last(battles).city;
|
const currentCity = ({ battles }) => {
|
||||||
|
const c = R.last(battles).city;
|
||||||
|
return typeof c === 'string' ? c : c.selection;
|
||||||
|
};
|
||||||
|
|
||||||
async function deleteCampaign({ name, _id }) {
|
async function deleteCampaign({ name, _id }) {
|
||||||
if (!window.confirm(`delete campaign ${name}?`)) return;
|
if (!window.confirm(`delete campaign ${name}?`)) return;
|
||||||
@ -77,6 +88,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const saveNewCampaign = () => {
|
const saveNewCampaign = () => {
|
||||||
|
console.log('sent');
|
||||||
api.event.addCampaign(newCampaignName);
|
api.event.addCampaign(newCampaignName);
|
||||||
newCampaignName = '';
|
newCampaignName = '';
|
||||||
showNewCampaign = false;
|
showNewCampaign = false;
|
||||||
|
@ -1,15 +1,41 @@
|
|||||||
|
import * as R from 'remeda';
|
||||||
import PouchDB from 'pouchdb';
|
import PouchDB from 'pouchdb';
|
||||||
import { writable, derived, get } 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';
|
import u from '@yanick/updeep-remeda';
|
||||||
|
|
||||||
const seedCampaign = {
|
const seedCampaign = {
|
||||||
|
status: 'ongoing', // win, lost
|
||||||
|
score: 0,
|
||||||
battles: [],
|
battles: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function campaignStatus(campaign) {
|
||||||
|
if (campaign.battles.length <= 6) return 'ongoing';
|
||||||
|
|
||||||
|
if (R.last(campaign.battles).status === 'won') return 'won';
|
||||||
|
|
||||||
|
if (
|
||||||
|
campaign.battles.length - 6 >=
|
||||||
|
campaign.battles.slice(0, 6).filter(({ status }) => status === 'won')
|
||||||
|
)
|
||||||
|
return 'lost';
|
||||||
|
|
||||||
|
return 'ongoing';
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateScore(campaign) {
|
||||||
|
return [
|
||||||
|
// -campaign.battles.slice(0, 6).filter(({ wave }) => wave === 2).length,
|
||||||
|
// -campaign.battles.slice(6).filter(({ status }) => status === 'lost')
|
||||||
|
// .length,
|
||||||
|
...campaign.battles.map(({ difficulty }) => parseInt(difficulty)),
|
||||||
|
].reduce((a, b) => a + b, 0);
|
||||||
|
}
|
||||||
|
|
||||||
export function updateBattle(campaign, battleId, status) {
|
export function updateBattle(campaign, battleId, status) {
|
||||||
const battle = campaign.battles[battleId - 1];
|
const battle = campaign.battles[battleId - 1];
|
||||||
if (status === 'lost' && battle.wave == 1) {
|
if (status === 'lost' && (battle.wave == 1 || battle.id < 7)) {
|
||||||
return u.updateIn(campaign, `battles.${battleId - 1}`, {
|
return u.updateIn(campaign, `battles.${battleId - 1}`, {
|
||||||
wave: 2,
|
wave: 2,
|
||||||
});
|
});
|
||||||
@ -17,6 +43,14 @@ export function updateBattle(campaign, battleId, status) {
|
|||||||
campaign = u.updateIn(campaign, `battles.${battleId - 1}`, {
|
campaign = u.updateIn(campaign, `battles.${battleId - 1}`, {
|
||||||
status,
|
status,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
campaign = u.updateIn(campaign, 'score', calculateScore(campaign));
|
||||||
|
console.log(campaign);
|
||||||
|
|
||||||
|
campaign = u(campaign, {
|
||||||
|
status: campaignStatus(campaign),
|
||||||
|
});
|
||||||
|
if (campaign.status === 'ongoing') {
|
||||||
campaign = u(campaign, {
|
campaign = u(campaign, {
|
||||||
battles: (battles) => [
|
battles: (battles) => [
|
||||||
...battles,
|
...battles,
|
||||||
@ -25,6 +59,7 @@ export function updateBattle(campaign, battleId, status) {
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return campaign;
|
return campaign;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,10 +140,21 @@ export function genApi(options = {}) {
|
|||||||
pouchdb.put(campaign);
|
pouchdb.put(campaign);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setCity = (battleId, value) => {
|
||||||
|
const campaign = u.updateIn(
|
||||||
|
get(activeCampaign),
|
||||||
|
['battles', battleId, 'city', 'selection'],
|
||||||
|
value,
|
||||||
|
);
|
||||||
|
|
||||||
|
pouchdb.put(campaign);
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
campaigns,
|
campaigns,
|
||||||
activeCampaign,
|
activeCampaign,
|
||||||
event: {
|
event: {
|
||||||
|
setCity,
|
||||||
setCharacter,
|
setCharacter,
|
||||||
deleteCampaign,
|
deleteCampaign,
|
||||||
addCampaign,
|
addCampaign,
|
||||||
|
@ -102,6 +102,33 @@ export function genChapter3Battle(battles) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function genChapter4Battle(battles) {
|
||||||
|
const chapter = 4;
|
||||||
|
|
||||||
|
const scenario = 'The Last Battle';
|
||||||
|
|
||||||
|
const cities = R.difference(
|
||||||
|
battles
|
||||||
|
.slice(0, 6)
|
||||||
|
.filter(({ status }) => status !== 'lost')
|
||||||
|
.map(R.prop('city')),
|
||||||
|
battles.slice(6).map((b) => b.city?.selection),
|
||||||
|
);
|
||||||
|
|
||||||
|
const characters = battles.slice(0, 6).map(R.prop('character'));
|
||||||
|
|
||||||
|
return {
|
||||||
|
wave: 1,
|
||||||
|
scenario,
|
||||||
|
city: { choices: cities, selection: R.first(cities) },
|
||||||
|
status: 'ongoing',
|
||||||
|
additionalCharacters: R.range(0, 3).map((i) => ({
|
||||||
|
choices: characters,
|
||||||
|
selection: characters[i],
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function genNextBattle(battles = []) {
|
export function genNextBattle(battles = []) {
|
||||||
let chapter = R.clamp(1 + parseInt(battles.length / 2), { min: 1, max: 4 });
|
let chapter = R.clamp(1 + parseInt(battles.length / 2), { min: 1, max: 4 });
|
||||||
|
|
||||||
@ -110,4 +137,6 @@ export function genNextBattle(battles = []) {
|
|||||||
if (chapter === 2) return genChapter2Battle(battles);
|
if (chapter === 2) return genChapter2Battle(battles);
|
||||||
|
|
||||||
if (chapter === 3) return genChapter3Battle(battles);
|
if (chapter === 3) return genChapter3Battle(battles);
|
||||||
|
|
||||||
|
return genChapter4Battle(battles);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
genNextBattle,
|
genNextBattle,
|
||||||
genChapter2Battle,
|
genChapter2Battle,
|
||||||
genChapter3Battle,
|
genChapter3Battle,
|
||||||
|
genChapter4Battle,
|
||||||
} from './genNextBattle.js';
|
} from './genNextBattle.js';
|
||||||
|
|
||||||
test('generate for the first chapter', () => {
|
test('generate for the first chapter', () => {
|
||||||
@ -66,3 +67,20 @@ test('chapter 3, second battle', () => {
|
|||||||
expect(result.additionalCharacters[0].selection).toEqual('two');
|
expect(result.additionalCharacters[0].selection).toEqual('two');
|
||||||
expect(result.additionalCharacters[1].selection).toEqual('four');
|
expect(result.additionalCharacters[1].selection).toEqual('four');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test.only('chapter 4, first battle', () => {
|
||||||
|
const result = genChapter4Battle([
|
||||||
|
{ character: 'one', city: 'a' },
|
||||||
|
{ character: 'two', city: 'b', status: 'lost' },
|
||||||
|
{ character: 'three', city: 'c' },
|
||||||
|
{ character: 'four', city: 'd' },
|
||||||
|
{ character: 'five', city: 'e' },
|
||||||
|
{ character: 'six', city: 'f' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(result.additionalCharacters[0].selection).toEqual('one');
|
||||||
|
expect(result.additionalCharacters[1].selection).toEqual('two');
|
||||||
|
expect(result.additionalCharacters[2].selection).toEqual('three');
|
||||||
|
|
||||||
|
expect(result.city.choices).not.toContain('b');
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user