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 @@
+
+
+
+
+ Nomination history
+
+
+
+ Nominator |
+ Nominee |
+ Type |
+ Majority |
+ Hand up |
+
+
+
+
+ {{ vote.nominator }} |
+ {{ vote.nominee }} |
+ {{ vote.type }} |
+ {{ vote.majority }} |
+
+ {{ vote.votes.length }}
+
+ {{ vote.votes.join(", ") }}
+ |
+
+
+
+
+
+
+
+
+
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,