import mockData from './mockdata'; import * as cryptoRandomString from 'crypto-random-string'; import { uniqueNamesGenerator, Config, adjectives, names, colors } from 'unique-names-generator'; // function calculateBusinessDay(player: any) { // let lineItems = []; // for (let i in player.vendingMachines) { // let machine = player.vendingMachines[i]; // // } // } function handleEvent(eventLog: EventLog) { if (eventLog.eventName === 'bought') { let vendingMachine = findVendingMachine(eventLog.data.offer); let selection = vendingMachine.selections.find((sel) => { return sel.id === eventLog.data.selection; }); selection.current = selection.current - 1; } } function findVendingMachine(id: string) { for (let i in mockData.players) { let player = mockData.players[i]; for (let j in player.vendingMachines) { if (player.vendingMachines[i].id === id) { return player.vendingMachines[i]; } } } } function personPassesByVendingMachine(person: Person, machine): EventLog { let isThursty: boolean = Math.random() < person.thirst; let availableSelections = machine.selections.filter((selection) => { return !!selection.current; }); if (isThursty) { if (!availableSelections.length) { return wontBuy('NoneAvailable'); } // pick a drink let acceptableOptions = availableSelections.filter((option) => { return person.preferences.indexOf(option.drink) !== -1; }); if (!acceptableOptions.length) { return wontBuy('NoPreferredDrinks'); } let options = acceptableOptions.filter((selection) => { return selection.price <= person.highestPrice; }); if (!options.length) { return wontBuy('HighPrice'); } let picked = pick(acceptableOptions); let selectionTypeData = getSelectionType(picked.type); return { eventName: 'bought', data: { reason: 'Thirsty', amount: picked.price, drink: picked.drink, selection: picked.id, selectionType: picked.type, oz: selectionTypeData ? selectionTypeData.oz : 12, person: person.id, offer: machine.id, } }; } else { return wontBuy('NotThirsty'); } function wontBuy(reason): EventLog { return { eventName: 'wontBuy', data: { reason: reason, amount: 0, drink: 'none', selection: 'none', selectionType: 'none', oz: 0, person: person.id, offer: machine.id, } }; } } function generatePerson(location: Location): Person { let money = Math.random() * 100; return { id: genId('person'), name: genPersonName(), preferences: genPreferences(), highestPrice: (money / 20), money: money, thirst: clamp(location.dailyTraffic.thirstBonus + (Math.random() / 10)) } } function genId(prefix: string): string { return `${prefix}-${cryptoRandomString({length: 6, type: 'distinguishable'})}`; } function genPersonName(): string { const config: Config = { dictionaries: [names, names], length: 2, separator: ' ' }; return uniqueNamesGenerator(config); } function genDrinkName(): string { const config: Config = { dictionaries: [adjectives, colors], length: 2, separator: ' ', style: 'capital' }; return uniqueNamesGenerator(config); } function genStoreName(): string { const stores: string[] = [ 'shop', 'reseller', 'department Store', 'chain Store', 'emporium', 'supermarket', 'hypermarket', 'superstore', 'mart', 'shed', 'big Box', 'convenience Store', 'corner Store', 'food Store', 'market', 'food Mart', 'bodega', ]; const config: Config = { dictionaries: [names, stores], length: 2, separator: '\'s ', style: 'capital' }; return uniqueNamesGenerator(config); } function genCityName(): string { const places: string[] = [ 'town', 'city', 'township', 'borough', 'seat', 'metropolis', 'burg', 'municipality', 'hamlet', ]; const config: Config = { dictionaries: [Math.random() > 0.5 ? colors : names, places], length: 2, separator: ' ', style: 'capital' }; return uniqueNamesGenerator(config); } function clamp(value: number, max: number = 1, min: number = 0) { if (value > max) { return max; } if (value < min) { return min; } return value; } function genPreferences(): string[] { const availableDrinks: string[] = mockData.drinks; let prefCount = Math.floor(Math.random() * availableDrinks.length); prefCount = prefCount === 0 ? prefCount + 1 : prefCount; // have at least one preference let preferences: string[] = []; while (preferences.length < prefCount) { let newPref: Drink = pick(availableDrinks); if (preferences.indexOf(newPref.id) === -1) { preferences.push(newPref.id); } } return preferences; } function getSelectionType(typeName: string) { return mockData.selectionTypes.find((type) => { return type.type === typeName; }); } function randomNumber(min: number, max: number): number { return Math.random() * (max - min) + min; } function pick(arr: any[]) { return arr[Math.floor(Math.random() * arr.length)]; } function getStatsFromEvents(events: EventLog[]) { let purchaseCount: number = 0; let offerEventCount: number = 0; let amountEarned: number = 0; let ozSold: number = 0; let popularity: {[drink: string]: number} = {}; let eventReasons: {[reason: string]: number} = {}; for (let i in events) { let eventLog: EventLog = events[i]; if (!eventReasons[eventLog.data.reason]) { eventReasons[eventLog.data.reason] = 0; } eventReasons[eventLog.data.reason] = eventReasons[eventLog.data.reason] + 1; if (eventLog.eventName === 'bought' || eventLog.eventName === 'wontBuy') { offerEventCount = offerEventCount + 1; if (eventLog.eventName === 'bought') { purchaseCount = purchaseCount + 1; if (!popularity[eventLog.data.drink]) { popularity[eventLog.data.drink] = 0; } popularity[eventLog.data.drink] = popularity[eventLog.data.drink] + 1; amountEarned = amountEarned + eventLog.data.amount; ozSold = ozSold + eventLog.data.oz; } } } console.log({ purchaseCount, purchaseRate: purchaseCount / offerEventCount, offerEventCount, amountEarned, ozSold, popularity, eventReasons }); } interface Drink { id: string; name: string; costPerOz: number; } interface DailyTraffic { max: number; min: number; thirstBonus: number; } interface Placement { id: string; name: string; traffic: number; } interface Location { id: string; name: string; city: string; dailyTraffic: DailyTraffic; placements: Placement[]; } interface Person { id: string; name: string; preferences: string[]; highestPrice: number; money: number; thirst: number; } interface EventLog { eventName: string; data: any; } interface PersonEvent { reason: string; amount: number; drink: string; selection: string; selectionType: string; oz: number; person: string; // person involved in the event offer: string; // id of deal or vending machine } let events: EventLog[] = []; let traffic: number = randomNumber(mockData.locations[0].dailyTraffic.min, mockData.locations[0].dailyTraffic.max) for (let i = 0; i < traffic; i++) { // console.log(generatePerson(mockData.locations[0])); let curEvent: EventLog = personPassesByVendingMachine(generatePerson(mockData.locations[0]), mockData.players[0].vendingMachines[0]) // console.log(genDrinkName()); // console.log(genStoreName()); console.log(genCityName()); events.push(curEvent); handleEvent(curEvent); } getStatsFromEvents(events);