-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1) Added new game for distributing trivia questions randomly with
`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
1 parent
ba44a9b
commit 5bbad4f
Showing
7 changed files
with
653 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
}) | ||
}) |
Oops, something went wrong.