Skip to content

Instantly share code, notes, and snippets.

@leegcc
Created June 15, 2016 15:26
Show Gist options
  • Save leegcc/4882a42cddb97bd631636b51efcea10f to your computer and use it in GitHub Desktop.
Save leegcc/4882a42cddb97bd631636b51efcea10f to your computer and use it in GitHub Desktop.

Revisions

  1. aqxa created this gist Jun 15, 2016.
    120 changes: 120 additions & 0 deletions lucky-draw.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,120 @@
    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());