Created
June 15, 2016 15:26
-
-
Save leegcc/4882a42cddb97bd631636b51efcea10f to your computer and use it in GitHub Desktop.
抽奖
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
const AsciiTable = require("ascii-table"); | |
class LuckyDraw { | |
constructor(gifts) { | |
this.gifts = gifts; | |
} | |
analyzeOdds() { | |
const totalOfPriority = this.gifts.reduce((memo, gift) => memo + gift.priority, 0); | |
return this.gifts.map(({name, quantity, priority}) => { | |
const odds = priority / totalOfPriority * 100; | |
return { | |
name, | |
quantity, | |
priority, | |
odds | |
} | |
}); | |
} | |
luck() { | |
const remainingGifts = this.gifts.filter(gift => gift.quantity !== 0); | |
const totalOfPriority = remainingGifts.reduce((memo, gift) => memo + gift.priority, 0); | |
const randomNumber = ~~(Math.random() * totalOfPriority); | |
let priority = 0, luckyGift = null; | |
remainingGifts.some((gift) => { | |
priority += gift.priority; | |
if (priority < randomNumber) { | |
return false; | |
} | |
luckyGift = gift; | |
if (luckyGift.quantity > 0) { | |
luckyGift.quantity--; | |
} | |
return true; | |
}); | |
return luckyGift; | |
} | |
} | |
var luckyDraw = new LuckyDraw([ | |
{ | |
name: '1000', | |
quantity: 1, | |
priority: 1 | |
}, | |
{ | |
name: '100', | |
quantity: -1, | |
priority: 100 | |
}, | |
{ | |
name: '50', | |
quantity: -1, | |
priority: 200 | |
}, | |
{ | |
name: '30', | |
quantity: -1, | |
priority: 300 | |
}, | |
{ | |
name: '20', | |
quantity: -1, | |
priority: 300 | |
}, | |
{ | |
name: '10', | |
quantity: -1, | |
priority: 99 | |
} | |
]); | |
const comparator = (a, b) => parseFloat(b) > parseFloat(a); | |
const analyzedOdds = luckyDraw.analyzeOdds(); | |
let table = new AsciiTable(); | |
table.setHeading('Name', 'Quantity', 'Priority', 'Odds') | |
.setAlign(1, AsciiTable.RIGHT) | |
.setAlign(2, AsciiTable.RIGHT) | |
.setAlign(3, AsciiTable.RIGHT); | |
analyzedOdds.forEach(({name, quantity, priority, odds}) => { | |
table.addRow(name, quantity, priority, odds + '%'); | |
}); | |
table.sortColumn(3, comparator); | |
console.log(table.toString()); | |
let totalOfCount = 0; | |
const countByName = {}; | |
for (let i = 0; i < 2000; i++) { | |
const {name} = luckyDraw.luck(); | |
if (!countByName.hasOwnProperty(name)) { | |
countByName[name] = 0; | |
} | |
countByName[name]++; | |
totalOfCount++; | |
} | |
table = new AsciiTable(); | |
table.setHeading('Name', 'Quantity', 'Odds', 'Offset') | |
.setAlign(1, AsciiTable.RIGHT) | |
.setAlign(2, AsciiTable.RIGHT) | |
.setAlign(3, AsciiTable.RIGHT); | |
const names = Object.keys(countByName); | |
names.forEach((key) => { | |
const count = countByName[key]; | |
const odds = count / totalOfCount * 100; | |
const {odds: expectedOdds} = analyzedOdds.find(({name}) => name === key); | |
const offset = expectedOdds - odds; | |
table.addRow(key, count, odds + '%', offset + '%'); | |
}); | |
table.sortColumn(1, comparator); | |
console.log(table.toString()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment