Refactored scoring logic

This commit is contained in:
Moritz Kröger 2017-08-13 23:11:48 +02:00
parent b21fe3f9df
commit af58bd298a
4 changed files with 112 additions and 44 deletions

View file

@ -40,9 +40,9 @@
methods: {
addThesisEmphasis (thesis, event) {
if (event.target.checked) {
this.emphasized.push({ id: thesis.id })
this.emphasized.push({ thesis: thesis.id })
} else {
const index = this.emphasized.findIndex(item => item.id === thesis.id)
const index = this.emphasized.findIndex(item => item.thesis === thesis.id)
this.emphasized.splice(index, 1)
}
},

View file

@ -5,11 +5,11 @@
</header>
<ul class="party-results">
<li v-for="item of results">
<h2>{{ item.token }} ({{ getScorePercentage(item.score) }} %)</h2>
<li v-for="party of parties">
<h2>{{ party.token }} ({{ getScorePercentage(party.score) }} %)</h2>
<!-- <svgicon :name="getPartyLogoName(item.token)" width="50" height="50" /> -->
<party-percentage
:value="getScorePercentage(item.score)"
:value="getScorePercentage(party.score)"
:max="totalScoredPoints" />
</li>
</ul>
@ -17,8 +17,14 @@
</template>
<script>
import * as SCORING from '@/app/euromat/scoring'
import { getParties, getThesesCount } from '@/data'
import {
MAX_POINTS,
BASE_POINTS,
MIN_POINTS,
EMPHASIS_POINTS,
getScoringGrid
} from '@/app/euromat/scoring'
import { getParties } from '@/data'
import Progress from '@/components/progress'
import '@/assets/icons'
@ -26,6 +32,8 @@
// We have 43 theses now, but only 42 are stored. Hence I check if
// answers is even an object.
const addUp = (a, b) => a + b
export default {
name: 'Results',
@ -35,10 +43,10 @@
data () {
return {
scoringGrid: [],
answers: [],
emphasized: [],
results: [],
thesesCount: getThesesCount(),
scores: [],
parties: getParties(),
totalScoredPoints: 0
}
@ -49,51 +57,64 @@
return `${token.toLowerCase()}-logo`
},
getScorePercentage (score) {
console.log(score, this.totalScoredPoints)
return (score / this.totalScoredPoints * 100).toFixed(2)
},
sortResults () {
return this.parties
.map(party => ({
token: party.token,
score: party.positions
.map(this.countScoring)
.reduce((a, b) => a + b, 0)
}))
.sort((a, b) => a.score - b.score)
.reverse()
},
countScoring (partyConfig) {
const answer = this.answers.find(answer => answer.thesis === partyConfig.thesis)
if (!answer || answer.position === 'skipped') {
return SCORING.MIN_POINTS
}
evalPoints (party, user, emphasis) {
let score = 0
const hasEmphasis = !!this.emphasized.find(e => e.id === answer.thesis)
const user = answer.position
const party = partyConfig.position
if (user === party) {
score = SCORING.MAX_POINTS
if (user.position === party.position) {
score = MAX_POINTS
} else if (
(user === 'positive' && party === 'neutral') ||
(user === 'neutral' && party === 'positive') ||
(user === 'negative' && party === 'neutral')
(user.position === 'positive' && party.position === 'neutral') ||
(user.position === 'neutral' && party.position === 'positive') ||
(user.position === 'negative' && party.position === 'neutral')
) {
score = SCORING.BASE_POINTS
score = BASE_POINTS
} else if (
(user === 'positive' && party === 'negative') ||
(user === 'neutral' && party === 'negative') ||
(user === 'negative' && party === 'positive')
(user.position === 'positive' && party.position === 'negative') ||
(user.position === 'neutral' && party.position === 'negative') ||
(user.position === 'negative' && party.position === 'positive')
) {
score = SCORING.MIN_POINTS
score = MIN_POINTS
}
score = hasEmphasis ? score * SCORING.EMPHASIS_POINTS : score
this.totalScoredPoints += score
return {
party: party.party,
score: emphasis ? score * EMPHASIS_POINTS : score
}
},
getHighestScore (scores) {
const highestScore = Math.max(...scores.map(s => s.score))
return score
if (!highestScore) {
return MIN_POINTS
}
return highestScore === 1
? MAX_POINTS
: highestScore
},
getScorePoints (grid) {
// 1. Iterate over scoringGrid
// 2. Get user and party positions of each thesis
// 3. Evaluate points based on calculation model for each party
// 4. Count the highest score per thesis
// 5. Return a new object for each thesis row with results
return grid.map(row => {
const parties = row.positions.filter(p => p.type === 'party')
const user = row.positions[row.positions.length - 1]
const scores = parties.map(party => this.evalPoints(party, user, row.emphasis))
const highestScore = this.getHighestScore(scores)
return { thesis: row.thesis, highestScore, scores }
})
},
getScorePerParty (party) {
return {
token: party.token,
score: this.scores
.map(t => t.scores.find(s => s.party === party.id).score)
.reduce(addUp, 0)
}
}
},
@ -104,7 +125,15 @@
if (emphasized) this.emphasized = emphasized
if (answers) this.answers = answers
this.results = this.sortResults()
this.scoringGrid = getScoringGrid(this.answers, this.emphasized)
this.scores = this.getScorePoints(this.scoringGrid)
this.parties = this.parties
.map(this.getScorePerParty)
.sort((a, b) => a.score - b.score)
.reverse()
this.totalScoredPoints = this.scores
.map(s => s.highestScore)
.reduce(addUp, 0)
}
}
</script>

View file

@ -1,4 +1,37 @@
import { getPartyPositions } from '@/data'
export const MAX_POINTS = 2
export const BASE_POINTS = 1
export const MIN_POINTS = 0
export const EMPHASIS_POINTS = 2
// Grid example:
// [
// {
// thesis: 0,
// emphasis: true,
// positions: [
// {type: 'party', party: 0, position: 'neutral'},
// {type: 'party', party: 1, position: 'positive'},
// {type: 'party', party: 2, position: 'negative'},
// {type: 'party', party: 3, position: 'positive'},
// {type: 'party', party: 4, position: 'positive'},
// {type: 'party', party: 5, position: 'positive'},
// {type: 'user', position: 'positive'}
// ]
// },
// ...
// ]
export function getScoringGrid (userAnswers, emphasizedTheses) {
return userAnswers.map(answer => (
{
thesis: answer.thesis,
emphasis: emphasizedTheses.filter(e => e.thesis === answer.thesis).length >= 1,
positions: [
...getPartyPositions(answer.thesis),
...[{ type: 'user', position: answer.position }]
]
}
))
}

View file

@ -20,5 +20,11 @@ export const getThesesCount = () =>
export const getParty = token =>
parties.find(p => p.token === token)
export const getPartyPositions = (thesis) =>
parties.map(party => {
const { position } = party.positions.find(p => p.thesis === thesis)
return { type: 'party', party: party.id, position }
})
export const getParties = () =>
parties