townsquare/src/store/index.js

233 lines
6.4 KiB
JavaScript
Raw Normal View History

2020-05-02 19:11:20 +00:00
import Vue from "vue";
import Vuex from "vuex";
2020-05-02 19:46:51 +00:00
import persistence from "./persistence";
2020-05-30 20:47:42 +00:00
import socket from "./socket";
2020-05-02 20:23:05 +00:00
import players from "./modules/players";
2020-05-30 20:47:42 +00:00
import session from "./modules/session";
2020-05-02 19:11:20 +00:00
import editionJSON from "../editions.json";
import rolesJSON from "../roles.json";
2020-07-23 11:52:53 +00:00
import fabledJSON from "../fabled.json";
2020-05-02 19:11:20 +00:00
Vue.use(Vuex);
2021-02-01 21:33:59 +00:00
// global data maps
const editionJSONbyId = new Map(
editionJSON.map(edition => [edition.id, edition])
);
2020-06-24 12:32:08 +00:00
const rolesJSONbyId = new Map(rolesJSON.map(role => [role.id, role]));
2020-07-23 11:52:53 +00:00
const fabled = new Map(fabledJSON.map(role => [role.id, role]));
2020-06-24 12:32:08 +00:00
2021-02-01 21:33:59 +00:00
// helper functions
const getRolesByEdition = (edition = editionJSON[0]) => {
2020-05-02 19:11:20 +00:00
return new Map(
rolesJSON
.filter(r => r.edition === edition.id || edition.roles.includes(r.id))
2020-05-02 19:11:20 +00:00
.sort((a, b) => b.team.localeCompare(a.team))
.map(role => [role.id, role])
);
};
const getTravelersNotInEdition = (edition = editionJSON[0]) => {
return new Map(
rolesJSON
.filter(
r =>
r.team === "traveler" &&
r.edition !== edition.id &&
!edition.roles.includes(r.id)
)
.map(role => [role.id, role])
);
};
2021-02-01 21:33:59 +00:00
const set = key => ({ grimoire }, val) => {
grimoire[key] = val;
};
const toggle = key => ({ grimoire }, val) => {
if (val === true || val === false) {
grimoire[key] = val;
} else {
grimoire[key] = !grimoire[key];
}
};
// base definition for custom roles
const customRole = {
id: "",
name: "",
image: "",
ability: "",
edition: "custom",
firstNight: 0,
firstNightReminder: "",
otherNight: 0,
otherNightReminder: "",
reminders: [],
remindersGlobal: [],
setup: false,
team: "townsfolk",
isCustom: true
};
2020-05-02 19:11:20 +00:00
export default new Vuex.Store({
2020-05-02 20:23:05 +00:00
modules: {
2020-05-30 20:47:42 +00:00
players,
session
2020-05-02 20:23:05 +00:00
},
2020-05-02 19:11:20 +00:00
state: {
grimoire: {
2020-12-02 19:39:12 +00:00
isNight: false,
2020-05-02 19:11:20 +00:00
isNightOrder: true,
isPublic: true,
2020-05-02 19:33:44 +00:00
isMenuOpen: false,
isMuted: false,
2021-02-01 21:33:59 +00:00
isImageOptIn: false,
zoom: 0,
background: ""
2020-05-12 17:59:48 +00:00
},
2020-05-02 19:11:20 +00:00
modals: {
edition: false,
2020-08-09 19:28:38 +00:00
fabled: false,
gameState: false,
2020-08-09 19:28:38 +00:00
nightOrder: false,
reference: false,
reminder: false,
2020-08-09 19:28:38 +00:00
role: false,
2020-12-06 21:27:52 +00:00
roles: false,
voteHistory: false
2020-05-02 19:11:20 +00:00
},
edition: editionJSONbyId.get("tb"),
2020-07-23 11:52:53 +00:00
roles: getRolesByEdition(),
otherTravelers: getTravelersNotInEdition(),
2020-07-23 11:52:53 +00:00
fabled
2020-05-02 19:11:20 +00:00
},
getters: {
/**
2021-02-03 21:12:38 +00:00
* Return all custom roles, with default values and non-essential data stripped.
* Role object keys will be replaced with a numerical index to conserve bandwidth.
* @param roles
* @returns {[]}
*/
2021-02-03 21:12:38 +00:00
customRolesStripped: ({ roles }) => {
const customRoles = [];
const customKeys = Object.keys(customRole);
const strippedProps = [
"firstNightReminder",
"otherNightReminder",
"isCustom"
];
roles.forEach(role => {
if (!role.isCustom) {
customRoles.push({ id: role.id });
} else {
const strippedRole = {};
for (let prop in role) {
2021-02-03 21:12:38 +00:00
if (strippedProps.includes(prop)) {
continue;
}
2021-02-03 21:12:38 +00:00
const value = role[prop];
if (customKeys.includes(prop) && value !== customRole[prop]) {
strippedRole[customKeys.indexOf(prop)] = value;
}
}
customRoles.push(strippedRole);
}
});
return customRoles;
},
rolesJSONbyId: () => rolesJSONbyId
},
2020-05-02 19:11:20 +00:00
mutations: {
2021-02-01 21:33:59 +00:00
setZoom: set("zoom"),
setBackground: set("background"),
toggleMuted: toggle("isMuted"),
toggleMenu: toggle("isMenuOpen"),
toggleNightOrder: toggle("isNightOrder"),
toggleNight: toggle("isNight"),
toggleGrimoire: toggle("isPublic"),
toggleImageOptIn: toggle("isImageOptIn"),
2020-05-02 19:11:20 +00:00
toggleModal({ modals }, name) {
2020-06-04 19:56:07 +00:00
if (name) {
modals[name] = !modals[name];
}
for (let modal in modals) {
if (modal === name) continue;
modals[modal] = false;
2020-05-27 19:42:09 +00:00
}
2020-05-02 19:11:20 +00:00
},
/**
* Store custom roles
* @param state
* @param roles Array of role IDs or full role definitions
*/
setCustomRoles(state, roles) {
state.roles = new Map(
roles
// replace numerical role object keys with matching key names
.map(role => {
if (role[0]) {
const customKeys = Object.keys(customRole);
const mappedRole = {};
for (let prop in role) {
if (customKeys[prop]) {
mappedRole[customKeys[prop]] = role[prop];
}
}
return mappedRole;
} else {
return role;
}
})
2021-03-14 19:42:39 +00:00
// clean up role.id
.map(role => {
role.id = role.id.toLocaleLowerCase().replace(/[^a-z0-9]/g, "");
return role;
})
// map existing roles to base definition or pre-populate custom roles to ensure all properties
.map(
role =>
rolesJSONbyId.get(role.id) ||
state.roles.get(role.id) ||
Object.assign({}, customRole, role)
)
// default empty icons and placeholders
.map(role => {
2020-07-03 19:28:42 +00:00
if (rolesJSONbyId.get(role.id)) return role;
role.imageAlt = // map team to generic icon
{
townsfolk: "good",
outsider: "outsider",
minion: "minion",
demon: "evil"
}[role.team] || "custom";
return role;
})
// filter out roles that don't match an existing role and also don't have name/ability/team
.filter(role => role.name && role.ability && role.team)
// sort by team
.sort((a, b) => b.team.localeCompare(a.team))
// convert to Map
.map(role => [role.id, role])
);
2021-01-25 15:53:35 +00:00
// update extraTravelers map to only show travelers not in this script
state.otherTravelers = new Map(
rolesJSON
.filter(r => r.team === "traveler" && !roles.some(i => i.id === r.id))
.map(role => [role.id, role])
);
},
2020-05-02 19:11:20 +00:00
setEdition(state, edition) {
if (editionJSONbyId.has(edition.id)) {
state.edition = editionJSONbyId.get(edition.id);
state.roles = getRolesByEdition(state.edition);
state.otherTravelers = getTravelersNotInEdition(state.edition);
} else {
state.edition = edition;
}
state.modals.edition = false;
2020-05-02 19:11:20 +00:00
}
2020-05-02 19:46:51 +00:00
},
2020-05-30 20:47:42 +00:00
plugins: [persistence, socket]
2020-05-02 19:11:20 +00:00
});