diff --git a/src/App.vue b/src/App.vue index 41c3a8a..3f07790 100644 --- a/src/App.vue +++ b/src/App.vue @@ -26,6 +26,7 @@ + v{{ version }} @@ -45,9 +46,11 @@ import Vote from "./components/Vote"; import Gradients from "./components/Gradients"; import NightOrderModal from "./components/modals/NightOrderModal"; import FabledModal from "@/components/modals/FabledModal"; +import VoteHistoryModal from "@/components/modals/VoteHistoryModal"; export default { components: { + VoteHistoryModal, FabledModal, NightOrderModal, Vote, diff --git a/src/components/Menu.vue b/src/components/Menu.vue index 2cd1911..74b622a 100644 --- a/src/components/Menu.vue +++ b/src/components/Menu.vue @@ -108,6 +108,13 @@ Copy player link +
  • + Nomination history + +
  • Leave Session {{ session.sessionId }} @@ -223,6 +230,7 @@ export default { Math.round(Math.random() * 10000) ); if (sessionId) { + this.$store.commit("session/clearHistory"); this.$store.commit("session/setSpectator", false); this.$store.commit( "session/setSessionId", @@ -251,6 +259,7 @@ export default { "Enter the channel number / name of the session you want to join" ); if (sessionId) { + this.$store.commit("session/clearHistory"); this.$store.commit("session/setSpectator", true); this.$store.commit("toggleGrimoire", false); this.$store.commit( diff --git a/src/components/Vote.vue b/src/components/Vote.vue index d27a842..b4181da 100644 --- a/src/components/Vote.vue +++ b/src/components/Vote.vue @@ -206,6 +206,7 @@ export default { }, finish() { clearInterval(this.voteTimer); + this.$store.commit("session/addHistory", this.players); this.$store.commit("session/nomination"); }, vote(vote) { diff --git a/src/components/modals/Modal.vue b/src/components/modals/Modal.vue index aace5f2..c111185 100644 --- a/src/components/modals/Modal.vue +++ b/src/components/modals/Modal.vue @@ -53,6 +53,11 @@ export default { max-width: 80%; overflow-y: auto; } + .vote-history & { + max-height: 80%; + max-width: 80%; + overflow-y: auto; + } ul { list-style-type: none; diff --git a/src/components/modals/VoteHistoryModal.vue b/src/components/modals/VoteHistoryModal.vue new file mode 100644 index 0000000..c92ee60 --- /dev/null +++ b/src/components/modals/VoteHistoryModal.vue @@ -0,0 +1,103 @@ + + + + + diff --git a/src/store/index.js b/src/store/index.js index e8f057e..65881e7 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -66,7 +66,8 @@ export default new Vuex.Store({ reference: false, reminder: false, role: false, - roles: false + roles: false, + voteHistory: false }, edition: "tb", roles: getRolesByEdition(), diff --git a/src/store/modules/session.js b/src/store/modules/session.js index 8539901..3afc7f2 100644 --- a/src/store/modules/session.js +++ b/src/store/modules/session.js @@ -9,7 +9,6 @@ const set = key => (state, val) => { * @param state session state * @param index seat of the player in the circle * @param vote true or false - * @param indexAdjusted seat of the player counted from the nominated player */ const handleVote = (state, [index, vote]) => { if (!state.nomination) return; @@ -29,7 +28,8 @@ const state = () => ({ votes: [], lockedVote: 0, votingSpeed: 3000, - isVoteInProgress: false + isVoteInProgress: false, + voteHistory: [] }); const getters = {}; @@ -56,6 +56,30 @@ const mutations = { state.lockedVote = lockedVote || 0; state.isVoteInProgress = isVoteInProgress || false; }, + /** + * Create an entry in the vote history log. Requires current player array because it might change later in the game. + * Only stores votes that were completed. + * @param state + * @param players + */ + addHistory(state, players) { + if (!state.nomination || state.lockedVote <= players.length) return; + const isBanishment = players[state.nomination[1]].team === "traveler"; + state.voteHistory.push({ + nominator: players[state.nomination[0]].name, + nominee: players[state.nomination[1]].name, + type: isBanishment ? "Banishment" : "Execution", + majority: Math.ceil( + players.filter(player => !player.isDead || isBanishment).length / 2 + ), + votes: players + .filter((player, index) => state.votes[index]) + .map(({ name }) => name) + }); + }, + clearHistory(state) { + state.voteHistory = []; + }, /** * Store a vote with and without syncing it to the live session. * This is necessary in order to prevent infinite voting loops. diff --git a/src/store/socket.js b/src/store/socket.js index 38d9466..dedb059 100644 --- a/src/store/socket.js +++ b/src/store/socket.js @@ -128,6 +128,13 @@ class LiveSession { break; case "nomination": if (!this._isSpectator) return; + if (!params) { + // create vote history record + this._store.commit( + "session/addHistory", + this._store.state.players.players + ); + } this._store.commit("session/nomination", { nomination: params }); break; case "swap": @@ -245,7 +252,7 @@ class LiveSession { isVoteInProgress, fabled } = data; - this._store.commit("toggleNight", isNight); + this._store.commit("toggleNight", !!isNight); this._store.commit("session/nomination", { nomination, votes,