initial commit

This commit is contained in:
2021-07-18 13:57:08 -06:00
commit f258a8e619
9 changed files with 1290 additions and 0 deletions

237
build/mockProcess.js Normal file
View File

@ -0,0 +1,237 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const mockdata_1 = require("./mockdata");
const cryptoRandomString = require("crypto-random-string");
const unique_names_generator_1 = require("unique-names-generator");
function handleEvent(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) {
for (let i in mockdata_1.default.players) {
let player = mockdata_1.default.players[i];
for (let j in player.vendingMachines) {
if (player.vendingMachines[i].id === id) {
return player.vendingMachines[i];
}
}
}
}
function personPassesByVendingMachine(person, machine) {
let isThursty = Math.random() < person.thirst;
let availableSelections = machine.selections.filter((selection) => {
return !!selection.current;
});
if (isThursty) {
if (!availableSelections.length) {
return wontBuy('NoneAvailable');
}
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) {
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) {
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) {
return `${prefix}-${cryptoRandomString({ length: 6, type: 'distinguishable' })}`;
}
function genPersonName() {
const config = {
dictionaries: [unique_names_generator_1.names, unique_names_generator_1.names],
length: 2,
separator: ' '
};
return unique_names_generator_1.uniqueNamesGenerator(config);
}
function genDrinkName() {
const config = {
dictionaries: [unique_names_generator_1.adjectives, unique_names_generator_1.colors],
length: 2,
separator: ' ',
style: 'capital'
};
return unique_names_generator_1.uniqueNamesGenerator(config);
}
function genStoreName() {
const stores = [
'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 = {
dictionaries: [unique_names_generator_1.names, stores],
length: 2,
separator: '\'s ',
style: 'capital'
};
return unique_names_generator_1.uniqueNamesGenerator(config);
}
function genCityName() {
const places = [
'town',
'city',
'township',
'borough',
'seat',
'metropolis',
'burg',
'municipality',
'hamlet',
];
const config = {
dictionaries: [Math.random() > 0.5 ? unique_names_generator_1.colors : unique_names_generator_1.names, places],
length: 2,
separator: ' ',
style: 'capital'
};
return unique_names_generator_1.uniqueNamesGenerator(config);
}
function clamp(value, max = 1, min = 0) {
if (value > max) {
return max;
}
if (value < min) {
return min;
}
return value;
}
function genPreferences() {
const availableDrinks = mockdata_1.default.drinks;
let prefCount = Math.floor(Math.random() * availableDrinks.length);
prefCount = prefCount === 0 ? prefCount + 1 : prefCount;
let preferences = [];
while (preferences.length < prefCount) {
let newPref = pick(availableDrinks);
if (preferences.indexOf(newPref.id) === -1) {
preferences.push(newPref.id);
}
}
return preferences;
}
function getSelectionType(typeName) {
return mockdata_1.default.selectionTypes.find((type) => {
return type.type === typeName;
});
}
function randomNumber(min, max) {
return Math.random() * (max - min) + min;
}
function pick(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
function getStatsFromEvents(events) {
let purchaseCount = 0;
let offerEventCount = 0;
let amountEarned = 0;
let ozSold = 0;
let popularity = {};
let eventReasons = {};
for (let i in events) {
let 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
});
}
let events = [];
let traffic = randomNumber(mockdata_1.default.locations[0].dailyTraffic.min, mockdata_1.default.locations[0].dailyTraffic.max);
for (let i = 0; i < traffic; i++) {
let curEvent = personPassesByVendingMachine(generatePerson(mockdata_1.default.locations[0]), mockdata_1.default.players[0].vendingMachines[0]);
console.log(genCityName());
events.push(curEvent);
handleEvent(curEvent);
}
getStatsFromEvents(events);

220
build/mockdata.js Normal file
View File

@ -0,0 +1,220 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
let dataDefinition = {
players: [
{
id: 'player-01',
name: 'payne8',
balance: 4000.00,
vendingMachines: [
{
id: 'vend-01',
name: "First One!",
location: 'loc-01',
placement: 'plac-01',
compatibleSelectionTypes: ['can', 'bottle'],
selections: [
{
id: 'sel-01',
name: 'Diet Mtn. Dew',
drink: 'drink-01',
max: 56,
current: 24,
price: 3.00,
type: 'can'
},
{
id: 'sel-02',
name: 'Mtn. Dew',
drink: 'drink-02',
max: 56,
current: 24,
price: 2.00,
type: 'can'
},
{
id: 'sel-03',
name: 'Dr. Pepper',
drink: 'drink-03',
max: 56,
current: 24,
price: 1.50,
type: 'can'
},
{
id: 'sel-04',
name: 'Sprite',
drink: 'drink-04',
max: 56,
current: 24,
price: 0.75,
type: 'can'
},
{
id: 'sel-05',
name: 'Coke',
drink: 'drink-05',
max: 56,
current: 24,
price: 1.00,
type: 'can'
},
{
id: 'sel-06',
name: 'Diet Coke',
drink: 'drink-06',
max: 56,
current: 24,
price: 1.50,
type: 'can'
},
{
id: 'sel-07',
name: 'Orange Soda',
drink: 'drink-07',
max: 56,
current: 24,
price: 2.00,
type: 'can'
},
{
id: 'sel-08',
name: 'Grape Soda',
drink: 'drink-08',
max: 56,
current: 24,
price: 0.50,
type: 'can'
},
],
agreement: 0.0,
}
],
deals: [
{
id: 'deal-01',
location: 'loc-01',
selections: [
{
id: 'sel-09',
name: 'Diet Mtn. Dew - Dozen Cans',
drink: 'drink-01',
max: 56,
current: 24,
price: 7.00,
type: 'dozen-box'
},
],
agreement: 0.4,
},
]
}
],
selectionTypes: [
{
type: 'can',
oz: 12,
},
{
type: 'dozen-box',
os: 144
}
],
drinks: [
{
id: 'drink-01',
name: 'Diet Mtn. Dew',
costPerOz: 0.005,
},
{
id: 'drink-02',
name: 'Mtn. Dew',
costPerOz: 0.005,
},
{
id: 'drink-03',
name: 'Dr. Pepper',
costPerOz: 0.005,
},
{
id: 'drink-04',
name: 'Sprite',
costPerOz: 0.005,
},
{
id: 'drink-05',
name: 'Coke',
costPerOz: 0.005,
},
{
id: 'drink-06',
name: 'Diet Coke',
costPerOz: 0.005,
},
{
id: 'drink-07',
name: 'Orange Soda',
costPerOz: 0.005,
},
{
id: 'drink-08',
name: 'Grape Soda',
costPerOz: 0.005,
},
],
locations: [
{
id: 'loc-01',
name: 'General Store',
city: 'city-01',
dailyTraffic: {
max: 2000,
min: 400,
thirstBonus: 0.05,
},
deals: {
count: 2,
traffic: 0.4,
list: [
'deal-01'
]
},
placements: [
{
id: 'plac-01',
traffic: 0.5,
},
{
id: 'plac-02',
traffic: 0.6,
},
]
}
],
cities: [
{
id: 'city-01',
name: 'Hometown',
population: 15000
}
],
people: [
{
id: 'person-01',
name: 'Steve Klemm',
preferences: [
'drink-01',
'drink-04',
'drink-08',
],
highestPrice: 2.00,
wallet: {
cc: 500.00,
cash: 10.00,
coins: 1.25,
},
thirst: 0.8,
}
]
};
exports.default = dataDefinition;