daily pastebin goal
31%
SHARE
TWEET

Untitled

a guest Mar 26th, 2019 67 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import loglevel from 'loglevel';
  2. import { gaussian, randomBetweenMinAndMax } from './random-utils';
  3.  
  4. interface IPeriodEntry {
  5.   calories: number;
  6.   workout: boolean;
  7. }
  8. interface ISimEntry {
  9.   correctnessFactor: number;
  10.   period: IPeriodEntry[];
  11. }
  12.  
  13. interface IConfig {
  14.   periodLength: number;
  15.   fastingDays: number;
  16.   targetWorkoutDays: number;
  17.   simulationCount: number;
  18.   dailyTargetCalories: number;
  19. }
  20.  
  21. const selectPeriodDays = (
  22.   targetDays: number,
  23.   periodLength: number
  24. ): number[] => {
  25.   const realizedTarget = Math.floor(gaussian(targetDays, targetDays)());
  26.   if (realizedTarget < 1) {
  27.     return [];
  28.   } else {
  29.     return Array(realizedTarget)
  30.       .fill(false)
  31.       .map(() => randomBetweenMinAndMax(1, periodLength) - 1);
  32.   }
  33. };
  34.  
  35. const generatePeriodWorkouts = (config: IConfig): number[] =>
  36.   selectPeriodDays(config.targetWorkoutDays, config.periodLength);
  37. const generatePeriodFastingDays = (config: IConfig): number[] =>
  38.   selectPeriodDays(config.fastingDays, config.periodLength);
  39.  
  40. const generatePeriodCalories = (config: IConfig): number[] => {
  41.   // make a standard gaussian variable.
  42.   const standardDistribution = gaussian(
  43.     config.dailyTargetCalories,
  44.     config.dailyTargetCalories
  45.   );
  46.  
  47.   return Array(config.periodLength)
  48.     .fill(0)
  49.     .map(() => Math.floor(standardDistribution()));
  50. };
  51.  
  52. const sumPeriodCalories = (week: IPeriodEntry[]): number =>
  53.   week.reduce((acc, current) => acc + current.calories, 0);
  54.  
  55. const sumPeriodWorkouts = (week: IPeriodEntry[]): number =>
  56.   week.reduce((acc, current) => {
  57.     if (current.workout) {
  58.       return acc + 1;
  59.     } else {
  60.       return acc;
  61.     }
  62.   }, 0);
  63.  
  64. const mergeFastingAndWorkouts = (
  65.   calories: number[],
  66.   fastingDays: number[],
  67.   workoutDays: number[]
  68. ): IPeriodEntry[] => {
  69.   return calories.map(
  70.     (caloriesInstance: number, index: number): IPeriodEntry => {
  71.       const calIntstanceFastAdjusted = fastingDays.includes(index)
  72.         ? 0
  73.         : caloriesInstance;
  74.       const workout = workoutDays.includes(index);
  75.       return { calories: calIntstanceFastAdjusted, workout };
  76.     }
  77.   );
  78. };
  79.  
  80. const generatePeriodWithMetadata = (
  81.   config: IConfig,
  82.   periodTarget: number
  83. ): ISimEntry => {
  84.   const periodCalories = generatePeriodCalories(config);
  85.   const fastingDays = generatePeriodFastingDays(config);
  86.   const periodWorkouts = generatePeriodWorkouts(config);
  87.   const period = mergeFastingAndWorkouts(
  88.     periodCalories,
  89.     fastingDays,
  90.     periodWorkouts
  91.   );
  92.   const workoutDiff = Math.abs(
  93.     config.targetWorkoutDays - sumPeriodWorkouts(period)
  94.   );
  95.   const calorieDiff = Math.abs(periodTarget - sumPeriodCalories(period));
  96.   return {
  97.     correctnessFactor: workoutDiff + calorieDiff,
  98.     period
  99.   };
  100. };
  101.  
  102. const generatePeriodSimulations = (config: IConfig): ISimEntry[] => {
  103.   const periodTarget = config.dailyTargetCalories * config.periodLength;
  104.   const periods = [];
  105.  
  106.   for (let i = 0; i < config.simulationCount; i++) {
  107.     periods.push(generatePeriodWithMetadata(config, periodTarget));
  108.   }
  109.   return periods;
  110. };
  111.  
  112. const main = (config: IConfig) => {
  113.   const sims = generatePeriodSimulations(config);
  114.   const result = sims.reduce(
  115.     (p: ISimEntry, c: ISimEntry): ISimEntry => {
  116.       if (p.correctnessFactor < c.correctnessFactor) {
  117.         return p;
  118.       } else {
  119.         return c;
  120.       }
  121.     }
  122.   );
  123.   loglevel.error(JSON.stringify(result, null, 2));
  124. };
  125. main({
  126.   dailyTargetCalories: 1800,
  127.   fastingDays: 2,
  128.   periodLength: 7,
  129.   simulationCount: 10000,
  130.   targetWorkoutDays: 5
  131. });
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top