Skip to content

Commit

Permalink
1) Added new game for distributing trivia questions randomly with
Browse files Browse the repository at this point in the history
   `RandomTriviaRound`.
2) Added new component for picking multiple items `ItemMultiSelect`.
3) Added ability to submit own player list to `GameContentWithSidebar`.
4) Added test coverage for all above
  • Loading branch information
RobSpectre committed Jan 24, 2023
1 parent ba44a9b commit 5bbad4f
Show file tree
Hide file tree
Showing 7 changed files with 653 additions and 8 deletions.
97 changes: 97 additions & 0 deletions src/components/RandomTrivia/RandomTriviaRound.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<template lang="pug">
ItemGuess(
v-for='round in rounds'
:items='round.items'
:winnerIndex='round.winnerIndex'
:prize='prize'
:question='question'
:denomination='denomination'
:headerImage='headerImage'
:fragmentItemReveal='fragmentItemReveal'
)
</template>

<script>
import ItemGuess from '@/components/WhichIsWhich/ItemGuess.vue'
export default {
name: 'RandomTriviaRound',
components: {
ItemGuess
},
props: {
wrongAnswers: Array,
rightAnswers: Array,
question: String,
answersLength: {
type: Number,
default: 3
},
prize: {
type: Number,
default: 1
},
denomination: {
default: '$',
type: String
},
headerImage: {
default: '/images/which_is_which_cover.jpg',
type: String
},
fragmentItemReveal: {
type: Boolean,
default: false
}
},
computed: {
rounds () {
const rounds = []
const shuffledRightAnswers = this.shuffle(this.rightAnswers)
const shuffledWrongAnswers = this.shuffle(this.wrongAnswers)
const roundTotal = Math.floor(
(this.rightAnswers.length + this.wrongAnswers.length) / this.answersLength
)
for (let i = 0; i < roundTotal; i++) {
const round = {
items: [],
winnerIndex: 0
}
round.winnerIndex = this.getRandomInt(this.answersLength)
for (let x = 0; x < this.answersLength; x++) {
if (x === round.winnerIndex) {
round.items.push(shuffledRightAnswers.pop())
} else {
round.items.push(shuffledWrongAnswers.pop())
}
}
rounds.push(round)
}
return rounds
}
},
methods: {
shuffle (array) {
let currentIndex = array.length; let randomIndex
while (currentIndex !== 0) {
randomIndex = Math.floor(Math.random() * currentIndex)
currentIndex--
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]]
}
return array
},
getRandomInt (max) {
return Math.floor(Math.random() * max)
}
}
}
</script>
201 changes: 201 additions & 0 deletions src/components/WhichIsWhich/ItemMultiSelect.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
<template lang='pug'>
GameContentWithSidebar(:players='players')
template(v-slot:header)
slot(name='header')
template(v-slot:content)
slot(name='content')
ChooseItemModal(
v-if='!complete'
:items='items'
:fragmentItemReveal='fragmentItemReveal'
:question='question'
:headerImage='headerImage'
@guess='onGuess'
)
ActionButton(
v-else
label='Find Winners'
@clicked='findWinners'
accesskey='z'
)
template(v-slot:footer)
WinnerCard(
v-if='winners.length > 0'
:winners='winners'
:answerName='correctGuess'
:answerValue='denominate(items[0].value)'
)
LoserCard(
v-if='losers.length > 0'
:losers='losers'
:answerName='correctGuess'
:answerValue='denominate(items[0].value)'
)
</template>

<script>
import { mapState, mapActions } from 'pinia'
import { useGameStore } from '@/store'
import GameContentWithSidebar from '@/components/base/GameContentWithSidebar.vue'
import WinnerCard from '@/components/base/WinnerCard.vue'
import LoserCard from '@/components/base/LoserCard.vue'
import ChooseItemModal from '@/components/base/ChooseItemModal.vue'
import ActionButton from '@/components/base/ActionButton.vue'
export default {
name: 'ItemMultiSelect',
components: {
GameContentWithSidebar,
WinnerCard,
LoserCard,
ChooseItemModal,
ActionButton
},
props: {
items: Array,
winnerIndice: Array,
question: String,
prize: {
default: 1,
type: Number
},
totalSelections: {
default: 2,
type: Number
},
denomination: {
default: '$',
type: String
},
headerImage: {
default: '/images/which_is_which_cover.jpg',
type: String
},
fragmentItemReveal: {
default: false,
type: Boolean
}
},
data () {
return {
guesses: {},
complete: false,
winners: [],
losers: []
}
},
computed: {
currentPlayer () {
if (this.game.players.length > 0) {
return this.game.players[this.game.playerIndex].name
} else {
return ''
}
},
players () {
const players = []
for (const player in this.guesses) {
players.push({
name: player,
value: this.guesses[player].items.map(x => x.emoji).toString().replace(',', ' ')
})
}
return players
},
correctGuess () {
return this.winnerIndice.map(x => this.items[x].name).toString().replace(',', ' and ')
},
...mapState(useGameStore, ['game'])
},
methods: {
onGuess (guess) {
if (typeof this.guesses[guess.playerName] === 'undefined') {
this.guesses[guess.playerName] = {
items: []
}
}
this.guesses[guess.playerName].items.push({
value: guess.value,
emoji: guess.emoji
})
if (this.guesses[guess.playerName].items.length >= this.totalSelections) {
this.nextPlayer()
}
},
nextPlayer () {
this.guess = ''
this.increasePlayerIndex()
if (this.game.playerIndex === this.game.playerButton) {
this.complete = true
}
},
findWinners () {
const winners = []
for (const player in this.guesses) {
const correct = []
this.guesses[player].items.forEach(item => {
if (this.winnerIndice.includes(item.value)) {
correct.push(item)
}
})
if (correct.length === this.totalSelections) {
winners.push(player)
this.increasePlayerScore(player, this.prize)
}
}
if (winners.length === 1) {
this.increasePlayerScore(winners[0], this.prize)
const audio = new Audio('/sounds/sorry_for_party_rocking.mp3')
audio.volume = 0.2
audio.play()
this.winners = winners
} else if (winners.length > 0) {
const audio = new Audio('/sounds/fanfare.mp3')
audio.volume = 0.2
audio.play()
this.winners = winners
} else {
const audio = new Audio('/sounds/loser_sound.mp3')
audio.volume = 0.2
audio.play()
this.losers = this.players.map(player => player.name)
}
this.increasePlayerButton()
},
denominate (value) {
return this.denomination + value
},
...mapActions(useGameStore, ['increasePlayerScore',
'increasePlayerButton',
'increasePlayerIndex'])
}
}
</script>

<style lang="scss">
.actionButton {
@apply inline-flex justify-center px-6 py-3 border border-transparent leading-6 font-medium rounded-md text-white text-2xl uppercase bg-darkgray transition ease-in-out duration-150 my-2 hover:bg-slate-300 focus:outline-none focus:border-slate-300 active:bg-slate-300;
}
.reveal img {
margin: 0 !important;
@apply max-w-full;
}
</style>
22 changes: 15 additions & 7 deletions src/components/base/GameContentWithSidebar.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template lang='pug'>
GameSlide(:dataState='dataState')
PlayersSidebar(:players='players')
PlayersSidebar(:players='playersToDisplay')
GameContent
template(v-slot:header)
slot(name='header')
Expand All @@ -26,21 +26,29 @@ export default {
GameContent
},
props: {
players: {
type: Array,
default: null
},
dataState: {
type: String,
default: null
}
},
computed: {
...mapGetters(useGameStore, ['getPlayersByScore']),
players () {
const players = this.getPlayersByScore
playersToDisplay () {
if (this.players === null) {
const players = this.getPlayersByScore
players.forEach((player) => {
player.value = player.score
})
players.forEach((player) => {
player.value = player.score
})
return players
return players
} else {
return this.players
}
}
}
}
Expand Down
31 changes: 31 additions & 0 deletions tests/unit/RandomTrivia/RandomTriviaRound.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { mount } from '@vue/test-utils'

import { createTestingPinia } from '@pinia/testing'

import RandomTriviaRound from '@/components/RandomTrivia/RandomTriviaRound.vue'

describe('RandomTriviaRound Empty', () => {
let wrapper

beforeEach(() => {
wrapper = mount(RandomTriviaRound, {
props: {
wrongAnswers: [
{ name: 'Merc' },
{ name: 'Ferrari' }
],
rightAnswers: [
{ name: 'Red Bull' }
],
question: 'Which is the fastest car?'
},
global: {
plugins: [createTestingPinia()]
}
})
})

it('renders with no players', async () => {
expect(wrapper.vm.rounds.length).toBe(1)
})
})
Loading

0 comments on commit 5bbad4f

Please sign in to comment.