Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import loglevel from 'loglevel';
- import { gaussian, randomBetweenMinAndMax } from './random-utils';
- interface IPeriodEntry {
- calories: number;
- workout: boolean;
- }
- interface ISimEntry {
- correctnessFactor: number;
- period: IPeriodEntry[];
- }
- interface IConfig {
- periodLength: number;
- fastingDays: number;
- targetWorkoutDays: number;
- simulationCount: number;
- dailyTargetCalories: number;
- }
- const selectPeriodDays = (
- targetDays: number,
- periodLength: number
- ): number[] => {
- const realizedTarget = Math.floor(gaussian(targetDays, targetDays)());
- if (realizedTarget < 1) {
- return [];
- } else {
- return Array(realizedTarget)
- .fill(false)
- .map(() => randomBetweenMinAndMax(1, periodLength) - 1);
- }
- };
- const generatePeriodWorkouts = (config: IConfig): number[] =>
- selectPeriodDays(config.targetWorkoutDays, config.periodLength);
- const generatePeriodFastingDays = (config: IConfig): number[] =>
- selectPeriodDays(config.fastingDays, config.periodLength);
- const generatePeriodCalories = (config: IConfig): number[] => {
- // make a standard gaussian variable.
- const standardDistribution = gaussian(
- config.dailyTargetCalories,
- config.dailyTargetCalories
- );
- return Array(config.periodLength)
- .fill(0)
- .map(() => Math.floor(standardDistribution()));
- };
- const sumPeriodCalories = (week: IPeriodEntry[]): number =>
- week.reduce((acc, current) => acc + current.calories, 0);
- const sumPeriodWorkouts = (week: IPeriodEntry[]): number =>
- week.reduce((acc, current) => {
- if (current.workout) {
- return acc + 1;
- } else {
- return acc;
- }
- }, 0);
- const mergeFastingAndWorkouts = (
- calories: number[],
- fastingDays: number[],
- workoutDays: number[]
- ): IPeriodEntry[] => {
- return calories.map(
- (caloriesInstance: number, index: number): IPeriodEntry => {
- const calIntstanceFastAdjusted = fastingDays.includes(index)
- ? 0
- : caloriesInstance;
- const workout = workoutDays.includes(index);
- return { calories: calIntstanceFastAdjusted, workout };
- }
- );
- };
- const generatePeriodWithMetadata = (
- config: IConfig,
- periodTarget: number
- ): ISimEntry => {
- const periodCalories = generatePeriodCalories(config);
- const fastingDays = generatePeriodFastingDays(config);
- const periodWorkouts = generatePeriodWorkouts(config);
- const period = mergeFastingAndWorkouts(
- periodCalories,
- fastingDays,
- periodWorkouts
- );
- const workoutDiff = Math.abs(
- config.targetWorkoutDays - sumPeriodWorkouts(period)
- );
- const calorieDiff = Math.abs(periodTarget - sumPeriodCalories(period));
- return {
- correctnessFactor: workoutDiff + calorieDiff,
- period
- };
- };
- const generatePeriodSimulations = (config: IConfig): ISimEntry[] => {
- const periodTarget = config.dailyTargetCalories * config.periodLength;
- const periods = [];
- for (let i = 0; i < config.simulationCount; i++) {
- periods.push(generatePeriodWithMetadata(config, periodTarget));
- }
- return periods;
- };
- const main = (config: IConfig) => {
- const sims = generatePeriodSimulations(config);
- const result = sims.reduce(
- (p: ISimEntry, c: ISimEntry): ISimEntry => {
- if (p.correctnessFactor < c.correctnessFactor) {
- return p;
- } else {
- return c;
- }
- }
- );
- loglevel.error(JSON.stringify(result, null, 2));
- };
- main({
- dailyTargetCalories: 1800,
- fastingDays: 2,
- periodLength: 7,
- simulationCount: 10000,
- targetWorkoutDays: 5
- });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement