under-falling-skies/src/lib/store/api.js

198 lines
4.6 KiB
JavaScript

import * as R from 'remeda';
import PouchDB from 'pouchdb';
import { writable, derived, get } from 'svelte/store';
import { genNextBattle } from './genNextBattle.js';
import u from '@yanick/updeep-remeda';
const seedCampaign = {
status: 'ongoing', // win, lost
score: 0,
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) {
const values = [
-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))
.map((x) => (Number.isNaN(x) ? 0 : x)),
];
return values.reduce((a, b) => a + b, 0);
}
export function updateBattle(campaign, battleId, status) {
const battle = campaign.battles[battleId - 1];
if (status === 'lost' && battle.wave == 1 && battle.id < 7) {
campaign = u.updateIn(campaign, `battles.${battleId - 1}`, {
wave: 2,
});
campaign = u.updateIn(campaign, 'score', calculateScore(campaign));
return campaign;
}
campaign = u.updateIn(campaign, `battles.${battleId - 1}`, {
status,
});
campaign = u.updateIn(campaign, 'score', calculateScore(campaign));
campaign = u(campaign, {
status: campaignStatus(campaign),
});
if (campaign.status === 'ongoing') {
campaign = u(campaign, {
battles: (battles) => [
...battles,
u(genNextBattle(battles), {
id: battles.length + 1,
}),
],
});
}
return campaign;
}
export function genApi(options = {}) {
// if (options.local) MyPouch.plugin(pouchMem);
if (options.pouch) options.pouch(PouchDB);
const pouchdb = new PouchDB(
'Campaigns',
options.local
? {
adapter: 'memory',
}
: {},
);
const campaignsCore = writable([]);
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) => {
if (change.deleted) {
campaignsCore.update(u.updateIn(change.id, u.skip));
} else {
campaignsCore.update(u.updateIn(change.id, change.doc));
}
});
const campaigns = derived(campaignsCore, Object.values);
const addCampaign = (name) =>
pouchdb.post({
name,
...seedCampaign,
battles: [{ id: 1, ...genNextBattle() }],
});
const activeCampaignId = writable(0);
const setActiveCampaign = activeCampaignId.set;
const activeCampaign = derived(
[campaignsCore, activeCampaignId],
([$c, $id]) => $c[$id],
);
const setBattleDifficulty = (battleId, difficulty) => {
pouchdb
.put(
u.updateIn(get(activeCampaign), `battles.${battleId - 1}`, {
difficulty,
}),
)
.catch((e) => console.error(e)); // eslint-disable-line
};
const setBattleVerdict = (battleId, status) => {
const campaign = updateBattle(get(activeCampaign), battleId, status);
// eslint-disable-next-line
pouchdb.put(campaign).catch((e) => console.error(e));
};
const deleteCampaign = (_id) =>
pouchdb.remove(get(campaigns).find(u.matches({ _id })));
const setCharacter = (battleId, characterId, value) => {
const campaign = u.updateIn(
get(activeCampaign),
['battles', battleId, 'additionalCharacters', 'selection'],
value,
);
pouchdb.put(campaign);
};
const setCity = (battleId, value) => {
const campaign = u.updateIn(
get(activeCampaign),
['battles', battleId, 'city', 'selection'],
value,
);
pouchdb.put(campaign);
};
return {
campaigns,
activeCampaign,
event: {
setCity,
setCharacter,
deleteCampaign,
addCampaign,
setActiveCampaign,
setBattleVerdict,
setBattleDifficulty,
},
};
/*
const activeCampaign = writeable();
addCampaign: (name) =>
storage.campaigns.add({
name,
...seedCampaign,
battles: [{ id: 1, ...genNextBattle() }],
}),
return {
campaigns,
event: {
,
addCampaign: (name) =>
storage.campaigns.add({
name,
...seedCampaign,
battles: [{ id: 1, ...genNextBattle() }],
}),
deleteCampaign: (id) => storage.campaigns.delete(id),
},
};
*/
}