add vote history

This commit is contained in:
Steffen 2020-12-06 22:27:52 +01:00
parent 7caa0e7a4b
commit 15ced66b42
8 changed files with 157 additions and 4 deletions

View File

@ -26,6 +26,7 @@
<RolesModal />
<ReferenceModal />
<NightOrderModal />
<VoteHistoryModal />
<Gradients />
<span id="version">v{{ version }}</span>
</div>
@ -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,

View File

@ -108,6 +108,13 @@
Copy player link
<em><font-awesome-icon icon="copy"/></em>
</li>
<li
v-if="session.voteHistory.length"
@click="toggleModal('voteHistory')"
>
Nomination history
<em><font-awesome-icon icon="hand-paper"/></em>
</li>
<li @click="leaveSession" v-if="session.sessionId">
Leave Session
<em>{{ session.sessionId }}</em>
@ -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(

View File

@ -206,6 +206,7 @@ export default {
},
finish() {
clearInterval(this.voteTimer);
this.$store.commit("session/addHistory", this.players);
this.$store.commit("session/nomination");
},
vote(vote) {

View File

@ -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;

View File

@ -0,0 +1,103 @@
<template>
<Modal
class="vote-history"
v-show="modals.voteHistory"
@close="toggleModal('voteHistory')"
v-if="session.voteHistory"
>
<font-awesome-icon
@click="clearHistory"
icon="trash-alt"
class="clear"
title="Clear history"
/>
<h3>Nomination history</h3>
<table>
<thead>
<tr>
<td>Nominator</td>
<td>Nominee</td>
<td>Type</td>
<td>Majority</td>
<td><font-awesome-icon icon="hand-paper" /> Hand up</td>
</tr>
</thead>
<tbody>
<tr v-for="(vote, index) in session.voteHistory" :key="index">
<td>{{ vote.nominator }}</td>
<td>{{ vote.nominee }}</td>
<td>{{ vote.type }}</td>
<td>{{ vote.majority }}</td>
<td>
{{ vote.votes.length }}
<font-awesome-icon icon="user-friends" />
{{ vote.votes.join(", ") }}
</td>
</tr>
</tbody>
</table>
</Modal>
</template>
<script>
import Modal from "./Modal";
import { mapMutations, mapState } from "vuex";
export default {
components: {
Modal
},
computed: {
...mapState(["session", "modals"])
},
methods: {
...mapMutations(["toggleModal"]),
...mapMutations("session", ["clearHistory"])
}
};
</script>
<style lang="scss" scoped>
@import "../../vars.scss";
.clear {
position: absolute;
left: 20px;
top: 20px;
cursor: pointer;
&:hover {
color: red;
}
}
h3 {
margin: 0 40px;
svg {
vertical-align: middle;
}
}
table {
border-spacing: 10px 0;
}
thead td {
font-weight: bold;
border-bottom: 1px solid white;
text-align: center;
padding: 0 3px;
}
tbody {
td:nth-child(1) {
color: $townsfolk;
}
td:nth-child(2) {
color: $demon;
}
td:nth-child(4) {
text-align: center;
}
}
</style>

View File

@ -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(),

View File

@ -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.

View File

@ -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,