Vue.js Quiz: Stake less Clamp
by Pasit R
HTML
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bignumber.js/3.0.1/bignumber.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.min.js"></script>
<div class="container">
<div id="app">
<div class="board row">
<resistor v-for="r in resistors" v-bind:value="r" v-on:click="setAnswer"></resistor>
</div>
<div class="block">
<button class="btn btn-info btn-block" v-on:click="randomSerie">Random</button>
</div>
<div class="block">
<div v-if="question">
<h2>{{question.text}}</h2>
<code>TODO: finding {{question.key}} R</code>
</div>
<div v-if="answer != 0">
<pre>
Your answer: {{answer}}
selected R: {{selected}}
expected: {{expected}}
</pre>
<div v-if="isCorrect" class="block bg-success">Correct!</div>
<div v-if="!isCorrect" class="block bg-warning">Wrong!</div>
</div>
</div>
</div>
</div>
SCSS
.board {
border: 1px solid #888;
height: 150px;
padding: 20px 0;
}
.resistor {
background-color: rgba(0, 100, 200, .5);
border: 1px solid #888;
cursor: pointer;
line-height: 80px;
height: 80px;
width: 40px;
text-align: center;
vertical-align: bottom;
&:hover {
background-color: rgba(200, 200, 0, 1)
}
}
.block {
padding: 10px;
}
Babel + JSX
const initialState = {
answer: 0,
availableResistor: [5, 5, 5, 5, 5, 10, 10, 10, 50, 50],
availableQuestions: [{
text: 'which one has Maximum resistance?',
key: 'max'
}, {
text: 'which one has Minimum resistance?',
key: 'min'
}],
question: null,
resistors: [],
selected: 0,
expected: 0,
isCorrect: false
}
const getTotalResistance = function (resistors, selectedR) {
const allR = Immutable.List(resistors)
const index = allR.findKey(r => r === selectedR)
if (index < 0) {
throw new Error('selected R not found', selectedR)
}
const sumOfParallelR = (prev, r) => new BigNumber(1 / r).add(prev).toNumber() // adding previous R + 1/Rn
const remainingR = allR.remove(index) // exclude selected R
return remainingR.reduce(sumOfParallelR, selectedR) // sum [n: 1/Rn for n in remain] + selected
}
const getResistanceList = function (resistors) {
return resistors.map(r => getTotalResistance(resistors, r))
}
const max = function (values) {
const whichIsGreater = (a, b) => (a > b) ? a : b // get greater value
return values.reduce(whichIsGreater)
}
const min = function (values) {
const whichIsLesser = (a, b) => (a < b) ? a : b // get lesser value
return values.reduce(whichIsLesser)
}
Vue.component('resistor', {
props: ['value'],
template: `
<div class="col-xs-1">
<div class="resistor" v-on:click="handleClick">{{value}}Ω</div>
</div>
`,
methods: {
handleClick: function() {
this.$emit('click', this.value)
}
}
})
new Vue({
el: '#app',
data: function() {
return initialState
},
methods: {
randomSerie: function() {
const numberOfR = _.random(4, 9) // 4-9 R
this.resistors = _.sampleSize(this.availableResistor, numberOfR)
this.question = _.sample(this.availableQuestions)
this.answer = 0
},
setAnswer: function(value) {
// check if value is correct answer?
const allR = getResistanceList(this.resistors)
const answerMap = {
...