Skip to main content

Implementation Guide

Algorithm pseudocode, integration plan, and remaining tasks. Status: Planning - Research complete, implementation pending


Plan Generation Algorithm

High-Level Flow

async function generatePlan(userId: string, wizardData: WizardData): Promise<Plan> {
// Phase 1: Validate and prepare inputs
const input = validateAndPrepare(wizardData);

// Phase 2: Apply the 10 Pillars
const planParameters = applyPillars(input);

// Phase 3: Build structure
const structure = buildPlanStructure(planParameters);

// Phase 4: Select exercises
const sessions = await buildSessions(structure, input);

// Phase 5: Apply periodization
const periodizedPlan = applyPeriodization(sessions, input);

// Phase 6: Add deloads
const finalPlan = scheduleDeloads(periodizedPlan, input);

// Phase 7: Save to database
return await savePlan(userId, finalPlan);
}

Phase 2: Apply the 10 Pillars

interface PlanParameters {
weeklyVolume: number; // Pillar 1
intensityRange: [number, number]; // Pillar 2
frequency: number; // Pillar 3
restPeriods: RestConfig; // Pillar 4
exerciseOrder: 'compound_first' | 'pre_exhaust'; // Pillar 5
progressionModel: ProgressionModel; // Pillar 6
defaultTempo: string; // Pillar 7
periodizationType: PeriodizationType; // Pillar 8
deloadFrequency: number; // Pillar 9
recoveryNotes: string[]; // Pillar 10
}

function applyPillars(input: PlanGenerationInput): PlanParameters {
return {
// Pillar 1: Volume
weeklyVolume: calculateVolume(input.experience, input.goal, input.recovery),

// Pillar 2: Intensity
intensityRange: getIntensityRange(input.goal),

// Pillar 3: Frequency
frequency: input.frequency,

// Pillar 4: Rest Periods
restPeriods: {
compounds: input.goal === 'strength' ? 180 : 120,
isolation: 60,
autoRegulated: true,
},

// Pillar 5: Exercise Order
exerciseOrder: 'compound_first',

// Pillar 6: Progressive Overload
progressionModel: selectProgressionModel(input.experience),

// Pillar 7: Tempo
defaultTempo: getDefaultTempo(input.goal),

// Pillar 8: Periodization
periodizationType: selectPeriodization(input.experience, input.goal),

// Pillar 9: Deload
deloadFrequency: getDeloadFrequency(input.experience, input.recovery),

// Pillar 10: External Factors
recoveryNotes: generateRecoveryNotes(input.recovery, input.assessment),
};
}

Helper Functions

// Pillar 1: Volume Calculator
function calculateVolume(
experience: ExperienceLevel,
goal: Goal,
recovery: RecoveryCapacity
): number {
const baseVolume: Record<ExperienceLevel, number> = {
beginner: 10,
intermediate: 14,
advanced: 18,
returning: 12,
};

const recoveryMultiplier: Record<RecoveryCapacity, number> = {
low: 0.8,
moderate: 1.0,
high: 1.1,
};

const goalModifier: Record<Goal, number> = {
body_recomposition: 1.0,
hypertrophy: 1.1,
strength: 0.9,
fat_loss: 0.85,
};

return Math.round(
baseVolume[experience] *
recoveryMultiplier[recovery] *
(goalModifier[goal] || 1.0)
);
}

// Pillar 2: Intensity Range
function getIntensityRange(goal: Goal): [number, number] {
const ranges: Record<Goal, [number, number]> = {
body_recomposition: [65, 80],
hypertrophy: [65, 75],
strength: [80, 90],
power: [30, 60],
fat_loss: [50, 70],
};
return ranges[goal] || [65, 75];
}

// Pillar 6: Progression Model
function selectProgressionModel(experience: ExperienceLevel): ProgressionModel {
if (experience === 'beginner') {
return {
type: 'linear',
weeklyIncrease: 2.5, // lbs
deloadOnMiss: 10, // % reduction
};
}
return {
type: 'double_progression',
repRange: [8, 12],
loadIncreasePercent: 5,
};
}

// Pillar 7: Default Tempo
function getDefaultTempo(goal: Goal): string {
const tempos: Record<Goal, string> = {
hypertrophy: '3-1-2-0',
strength: '2-1-X-0',
power: '1-0-X-0',
metabolic: '2-0-2-0',
body_recomposition: '3-1-2-0',
};
return tempos[goal] || '3-1-2-0';
}

// Pillar 8: Periodization Type
function selectPeriodization(
experience: ExperienceLevel,
goal: Goal
): PeriodizationType {
if (experience === 'beginner') {
return 'linear';
}
if (goal === 'strength') {
return 'daily_undulating';
}
return 'weekly_undulating';
}

// Pillar 9: Deload Frequency
function getDeloadFrequency(
experience: ExperienceLevel,
recovery: RecoveryCapacity
): number {
const base: Record<ExperienceLevel, number> = {
beginner: 8,
intermediate: 5,
advanced: 4,
returning: 6,
};

// Reduce frequency if recovery is low
const adjustment = recovery === 'low' ? -1 : 0;

return base[experience] + adjustment;
}

Split Selection Logic

type SplitType = 'full_body' | 'upper_lower' | 'ppl' | 'pplul';

interface Split {
type: SplitType;
sessions: SessionTemplate[];
daysPerWeek: number;
}

function selectSplit(frequency: number, goal: Goal): Split {
// 3 days: Full body
if (frequency <= 3) {
return {
type: 'full_body',
daysPerWeek: frequency,
sessions: [
{ name: 'Full Body A', muscleGroups: ['chest', 'back', 'legs', 'shoulders'] },
{ name: 'Full Body B', muscleGroups: ['chest', 'back', 'legs', 'arms'] },
{ name: 'Full Body C', muscleGroups: ['chest', 'back', 'legs', 'shoulders'] },
].slice(0, frequency),
};
}

// 4 days: Upper/Lower (most recommended for recomp)
if (frequency === 4) {
return {
type: 'upper_lower',
daysPerWeek: 4,
sessions: [
{ name: 'Upper A', muscleGroups: ['chest', 'shoulders', 'triceps', 'back', 'biceps'] },
{ name: 'Lower A', muscleGroups: ['quads', 'hamstrings', 'glutes', 'calves'] },
{ name: 'Upper B', muscleGroups: ['back', 'biceps', 'chest', 'shoulders', 'triceps'] },
{ name: 'Lower B', muscleGroups: ['glutes', 'hamstrings', 'quads', 'calves'] },
],
};
}

// 5 days: PPLUL
if (frequency === 5) {
return {
type: 'pplul',
daysPerWeek: 5,
sessions: [
{ name: 'Push', muscleGroups: ['chest', 'shoulders', 'triceps'] },
{ name: 'Pull', muscleGroups: ['back', 'biceps', 'rear_delts'] },
{ name: 'Legs', muscleGroups: ['quads', 'hamstrings', 'glutes', 'calves'] },
{ name: 'Upper', muscleGroups: ['chest', 'back', 'shoulders', 'arms'] },
{ name: 'Lower', muscleGroups: ['quads', 'hamstrings', 'glutes', 'calves'] },
],
};
}

// 6 days: PPL
return {
type: 'ppl',
daysPerWeek: 6,
sessions: [
{ name: 'Push A', muscleGroups: ['chest', 'shoulders', 'triceps'] },
{ name: 'Pull A', muscleGroups: ['back', 'biceps', 'rear_delts'] },
{ name: 'Legs A', muscleGroups: ['quads', 'hamstrings', 'glutes', 'calves'] },
{ name: 'Push B', muscleGroups: ['shoulders', 'chest', 'triceps'] },
{ name: 'Pull B', muscleGroups: ['back', 'biceps', 'rear_delts'] },
{ name: 'Legs B', muscleGroups: ['hamstrings', 'glutes', 'quads', 'calves'] },
],
};
}

Periodization Implementation

interface Phase {
name: string;
weekStart: number;
weekEnd: number;
volumeMultiplier: number;
intensityMultiplier: number;
rpeTarget: number;
focus: string;
}

function buildPeriodization(
totalWeeks: number,
type: PeriodizationType,
goal: Goal
): Phase[] {
if (type === 'linear') {
return buildLinearPeriodization(totalWeeks);
}

if (type === 'daily_undulating') {
return buildDUP(totalWeeks);
}

// Block periodization for body recomp
if (goal === 'body_recomposition') {
return buildRecompPeriodization(totalWeeks);
}

return buildWeeklyUndulating(totalWeeks);
}

function buildRecompPeriodization(totalWeeks: number): Phase[] {
// 16-week recomp structure from research
return [
{
name: 'Foundation',
weekStart: 1,
weekEnd: 4,
volumeMultiplier: 0.8,
intensityMultiplier: 0.9,
rpeTarget: 6.5,
focus: 'Build work capacity, establish baseline',
},
{
name: 'Accumulation',
weekStart: 5,
weekEnd: 8,
volumeMultiplier: 1.1,
intensityMultiplier: 1.0,
rpeTarget: 7.5,
focus: 'Maximize muscle stimulus, initiate fat loss',
},
{
name: 'Intensification',
weekStart: 9,
weekEnd: 12,
volumeMultiplier: 1.0,
intensityMultiplier: 1.1,
rpeTarget: 8.5,
focus: 'Strength expression, accelerate fat loss',
},
{
name: 'Realization',
weekStart: 13,
weekEnd: totalWeeks,
volumeMultiplier: 0.8,
intensityMultiplier: 0.95,
rpeTarget: 7.5,
focus: 'Lock in gains, recover, assess progress',
},
];
}

Implementation Order

Phase 1: Database (Week 1)

  • Create Drizzle schema for exercise database
  • Run migrations
  • Create seed data for ~50 initial exercises
  • Create seed data for intensity techniques

Phase 2: Core Algorithm (Week 2)

  • Implement calculateVolume() function
  • Implement selectSplit() function
  • Implement exercise selection logic
  • Implement session builder

Phase 3: Periodization (Week 3)

  • Implement periodization builder
  • Implement deload scheduler
  • Implement progression model

Phase 4: API Endpoints (Week 4)

  • /api/v1/plans/generate - Generate plan options
  • /api/v1/plans/[planId]/sessions - Get session details
  • /api/v1/exercises - Exercise CRUD
  • /api/v1/exercises/[exerciseId]/modes - Execution modes

Phase 5: UI Integration (Week 5)

  • Step 7: Summary & Confirmation UI
  • Step 8: Coach Collaboration UI
  • Step 9: Full Session Preview UI
  • Exercise detail modal

Completed Research

  • The 10 Pillars of science-based plan design
  • Body recomposition in depth (timeline, nutrition, training)
  • Execution modes (20+ modes and techniques)
  • Tempo and time under tension
  • Volume guidelines by experience level
  • Intensity/RPE/RIR research
  • Training frequency and MPS
  • Rest period optimization
  • Exercise selection and order
  • Progressive overload methods
  • Periodization models comparison
  • Deload protocols and triggers
  • External factors (sleep, nutrition, stress)
  • Push:pull ratio and muscle balance

Remaining Tasks

Database

  • Finalize complete exercise list (~100 exercises)
  • Determine video/image sources for exercise demos
  • Define intensity technique compatibility matrix
  • Create seed data for all tables

Algorithm

  • Implement all pillar functions
  • Implement split selection
  • Implement session builder
  • Implement periodization
  • Add workout progression tracking

API

  • Plan generation endpoints
  • Exercise management endpoints
  • Session detail endpoints

UI

  • Step 7-9 redesign
  • Exercise detail components
  • Coach collaboration streaming


Last Updated: 2025-12-08