diff --git a/app.js b/app.js
index 3fa1f88..6715e16 100644
--- a/app.js
+++ b/app.js
@@ -1322,6 +1322,163 @@ class VitruvianApp {
}
}
}
+// --- BEGIN Exercise Library with Demos ---
+
+const EXERCISES = {
+ chest: ["Bench Press","Incline Press","Chest Fly","Push-Ups","Cable Crossover","Dips","Decline Press"],
+ back: ["Pull-Ups","Lat Pulldown","Bent Row","Seated Row","Deadlift","Face Pulls","T-Bar Row"],
+ legs: ["Squats","Lunges","Leg Press","Leg Curl","Leg Extension","Calf Raises","Bulgarian Split Squat"],
+ shoulders: ["Overhead Press","Lateral Raise","Front Raise","Rear Delt Fly","Arnold Press","Upright Row"],
+ arms: ["Bicep Curl","Tricep Extension","Hammer Curl","Skull Crushers","Preacher Curl","Tricep Pushdown"],
+ core: ["Plank","Crunches","Russian Twist","Leg Raises","Cable Woodchop","Bicycle Crunches","Mountain Climbers"]
+};
+
+const EXERCISE_EMOJIS = {
+ 'Bench Press': '🏋️',
+ 'Incline Press': '🏋️',
+ 'Chest Fly': '💪',
+ 'Push-Ups': '💪',
+ 'Pull-Ups': '🤸',
+ 'Lat Pulldown': '💪',
+ 'Squats': '🦵',
+ 'Lunges': '🏃',
+ 'Bicep Curl': '💪',
+ 'Tricep Extension': '💪',
+ 'Overhead Press': '🏋️',
+ 'Plank': '🧘'
+};
+
+let selectedExercise = null;
+let personalBests = JSON.parse(localStorage.getItem('vitruvian_pbs') || '{}');
+let leaderboard = JSON.parse(localStorage.getItem('vitruvian_leaderboard') || '[]');
+
+function initSidebarFeatures() {
+ if (!document.getElementById('exerciseList')) return; // Skip if sidebar not in HTML
+ renderExercises();
+ renderPersonalBests();
+ renderLeaderboard();
+
+ document.getElementById('exerciseSearch').oninput = renderExercises;
+ document.getElementById('muscleFilter').onchange = renderExercises;
+ if (document.getElementById('startBtn')) {
+ document.getElementById('startBtn').onclick = startWorkoutFromSidebar;
+ }
+}
+
+function renderExercises() {
+ const search = document.getElementById('exerciseSearch').value.toLowerCase();
+ const muscle = document.getElementById('muscleFilter').value;
+ const listEl = document.getElementById('exerciseList');
+ let exercises = [];
+
+ if (muscle === 'all') {
+ Object.values(EXERCISES).forEach(list => exercises.push(...list));
+ } else {
+ exercises = EXERCISES[muscle] || [];
+ }
+ exercises = exercises.filter(ex => ex.toLowerCase().includes(search));
+
+ listEl.innerHTML = exercises.map(ex => {
+ const emoji = EXERCISE_EMOJIS[ex] || '🏃';
+ return `
+ ${emoji}
+ ${ex}
+
`;
+ }).join('');
+}
+
+window.selectExercise = function(name) {
+ selectedExercise = name;
+ if (document.getElementById('selectedExercise')) {
+ document.getElementById('selectedExercise').textContent = `Selected: ${name}`;
+ }
+ document.querySelectorAll('.exercise-item').forEach(item => {
+ const exerciseName = item.querySelector('span:last-child').textContent;
+ if (exerciseName === name) {
+ item.style.background = '#667eea';
+ item.style.color = 'white';
+ } else {
+ item.style.background = '#f5f5f5';
+ item.style.color = 'black';
+ }
+ });
+ updateMuscleHeatmap(name);
+};
+
+function startWorkoutFromSidebar() {
+ if (!document.getElementById('mode')) return;
+ let mode = document.getElementById('mode').value;
+ let weight = parseFloat(document.getElementById('weight').value);
+ let reps = parseInt(document.getElementById('reps').value, 10);
+
+ localStorage.setItem('vitruvian_lastworkout',
+ JSON.stringify({ exercise: selectedExercise, mode, weight, reps })
+ );
+
+ console.log('Workout started:', { exercise: selectedExercise, mode, weight, reps });
+}
+
+function renderPersonalBests() {
+ const pbList = document.getElementById('pbList');
+ if (!pbList) return;
+ const pbs = Object.entries(personalBests).slice(0, 5);
+ if (pbs.length === 0) {
+ pbList.innerHTML = 'Complete workouts to track PRs
';
+ return;
+ }
+ pbList.innerHTML = pbs.map(([exercise, weight]) =>
+ `
+ ${exercise}
+ ${weight}kg
+
`
+ ).join('');
+}
+
+function renderLeaderboard() {
+ const lbList = document.getElementById('leaderboardList');
+ if (!lbList) return;
+ const sorted = leaderboard.sort((a,b) => b.score - a.score).slice(0,5);
+ if (sorted.length === 0) {
+ lbList.innerHTML = 'No entries yet
';
+ return;
+ }
+ lbList.innerHTML = sorted.map((entry, i) =>
+ `
+ ${i+1}
+ ${entry.name}
+ ${entry.score}
+
`
+ ).join('');
+}
+
+function updateMuscleHeatmap(selected) {
+ ['chest','shoulders-l','shoulders-r','arms-l','arms-r','core','legs-l','legs-r'].forEach(id => {
+ let el = document.getElementById('m-'+id);
+ if (el) el.setAttribute('fill', '#ddd');
+ });
+ if (!selected) return;
+
+ const ex = selected.toLowerCase();
+ if (ex.match(/chest|press|fly|push/)) highlight(['chest']);
+ else if (ex.match(/shoulder|overhead|lateral|arnold/)) highlight(['shoulders-l','shoulders-r']);
+ else if (ex.match(/bicep|tricep|curl|skull|hammer/)) highlight(['arms-l','arms-r']);
+ else if (ex.match(/core|plank|crunch|twist|woodchop/)) highlight(['core']);
+ else if (ex.match(/squat|lunge|leg|calf/)) highlight(['legs-l','legs-r']);
+ else if (ex.match(/pull|row|deadlift/)) highlight(['shoulders-l','shoulders-r','arms-l','arms-r']);
+
+ function highlight(ids) {
+ ids.forEach(id => {
+ let el = document.getElementById('m-'+id);
+ if (el) el.setAttribute('fill', '#f88');
+ });
+ }
+}
+
+window.addEventListener('DOMContentLoaded', () => {
+ initSidebarFeatures();
+});
+
+// --- END Exercise Library with Demos ---
// Create global app instance
const app = new VitruvianApp();
@@ -1334,3 +1491,160 @@ app.addLogEntry("Requirements:", "info");
app.addLogEntry("- Chrome, Edge, or Opera browser", "info");
app.addLogEntry("- HTTPS connection (or localhost)", "info");
app.addLogEntry("- Bluetooth enabled on your device", "info");
+// --- BEGIN Exercise Library with Demos ---
+
+const EXERCISES = {
+ chest: ["Bench Press","Incline Press","Chest Fly","Push-Ups","Cable Crossover","Dips","Decline Press"],
+ back: ["Pull-Ups","Lat Pulldown","Bent Row","Seated Row","Deadlift","Face Pulls","T-Bar Row"],
+ legs: ["Squats","Lunges","Leg Press","Leg Curl","Leg Extension","Calf Raises","Bulgarian Split Squat"],
+ shoulders: ["Overhead Press","Lateral Raise","Front Raise","Rear Delt Fly","Arnold Press","Upright Row"],
+ arms: ["Bicep Curl","Tricep Extension","Hammer Curl","Skull Crushers","Preacher Curl","Tricep Pushdown"],
+ core: ["Plank","Crunches","Russian Twist","Leg Raises","Cable Woodchop","Bicycle Crunches","Mountain Climbers"]
+};
+
+const EXERCISE_EMOJIS = {
+ 'Bench Press': '🏋️',
+ 'Incline Press': '🏋️',
+ 'Chest Fly': '💪',
+ 'Push-Ups': '💪',
+ 'Pull-Ups': '🤸',
+ 'Lat Pulldown': '💪',
+ 'Squats': '🦵',
+ 'Lunges': '🏃',
+ 'Bicep Curl': '💪',
+ 'Tricep Extension': '💪',
+ 'Overhead Press': '🏋️',
+ 'Plank': '🧘'
+};
+
+let selectedExercise = null;
+let personalBests = JSON.parse(localStorage.getItem('vitruvian_pbs') || '{}');
+let leaderboard = JSON.parse(localStorage.getItem('vitruvian_leaderboard') || '[]');
+
+function initSidebarFeatures() {
+ if (!document.getElementById('exerciseList')) return; // Skip if sidebar not in HTML
+ renderExercises();
+ renderPersonalBests();
+ renderLeaderboard();
+
+ document.getElementById('exerciseSearch').oninput = renderExercises;
+ document.getElementById('muscleFilter').onchange = renderExercises;
+ if (document.getElementById('startBtn')) {
+ document.getElementById('startBtn').onclick = startWorkoutFromSidebar;
+ }
+}
+
+function renderExercises() {
+ const search = document.getElementById('exerciseSearch').value.toLowerCase();
+ const muscle = document.getElementById('muscleFilter').value;
+ const listEl = document.getElementById('exerciseList');
+ let exercises = [];
+
+ if (muscle === 'all') {
+ Object.values(EXERCISES).forEach(list => exercises.push(...list));
+ } else {
+ exercises = EXERCISES[muscle] || [];
+ }
+ exercises = exercises.filter(ex => ex.toLowerCase().includes(search));
+
+ listEl.innerHTML = exercises.map(ex => {
+ const emoji = EXERCISE_EMOJIS[ex] || '🏃';
+ return `
+ ${emoji}
+ ${ex}
+
`;
+ }).join('');
+}
+
+window.selectExercise = function(name) {
+ selectedExercise = name;
+ if (document.getElementById('selectedExercise')) {
+ document.getElementById('selectedExercise').textContent = `Selected: ${name}`;
+ }
+ document.querySelectorAll('.exercise-item').forEach(item => {
+ const exerciseName = item.querySelector('span:last-child').textContent;
+ if (exerciseName === name) {
+ item.style.background = '#667eea';
+ item.style.color = 'white';
+ } else {
+ item.style.background = '#f5f5f5';
+ item.style.color = 'black';
+ }
+ });
+ updateMuscleHeatmap(name);
+};
+
+function startWorkoutFromSidebar() {
+ if (!document.getElementById('mode')) return;
+ let mode = document.getElementById('mode').value;
+ let weight = parseFloat(document.getElementById('weight').value);
+ let reps = parseInt(document.getElementById('reps').value, 10);
+
+ localStorage.setItem('vitruvian_lastworkout',
+ JSON.stringify({ exercise: selectedExercise, mode, weight, reps })
+ );
+
+ console.log('Workout started:', { exercise: selectedExercise, mode, weight, reps });
+}
+
+function renderPersonalBests() {
+ const pbList = document.getElementById('pbList');
+ if (!pbList) return;
+ const pbs = Object.entries(personalBests).slice(0, 5);
+ if (pbs.length === 0) {
+ pbList.innerHTML = 'Complete workouts to track PRs
';
+ return;
+ }
+ pbList.innerHTML = pbs.map(([exercise, weight]) =>
+ `
+ ${exercise}
+ ${weight}kg
+
`
+ ).join('');
+}
+
+function renderLeaderboard() {
+ const lbList = document.getElementById('leaderboardList');
+ if (!lbList) return;
+ const sorted = leaderboard.sort((a,b) => b.score - a.score).slice(0,5);
+ if (sorted.length === 0) {
+ lbList.innerHTML = 'No entries yet
';
+ return;
+ }
+ lbList.innerHTML = sorted.map((entry, i) =>
+ `
+ ${i+1}
+ ${entry.name}
+ ${entry.score}
+
`
+ ).join('');
+}
+
+function updateMuscleHeatmap(selected) {
+ ['chest','shoulders-l','shoulders-r','arms-l','arms-r','core','legs-l','legs-r'].forEach(id => {
+ let el = document.getElementById('m-'+id);
+ if (el) el.setAttribute('fill', '#ddd');
+ });
+ if (!selected) return;
+
+ const ex = selected.toLowerCase();
+ if (ex.match(/chest|press|fly|push/)) highlight(['chest']);
+ else if (ex.match(/shoulder|overhead|lateral|arnold/)) highlight(['shoulders-l','shoulders-r']);
+ else if (ex.match(/bicep|tricep|curl|skull|hammer/)) highlight(['arms-l','arms-r']);
+ else if (ex.match(/core|plank|crunch|twist|woodchop/)) highlight(['core']);
+ else if (ex.match(/squat|lunge|leg|calf/)) highlight(['legs-l','legs-r']);
+ else if (ex.match(/pull|row|deadlift/)) highlight(['shoulders-l','shoulders-r','arms-l','arms-r']);
+
+ function highlight(ids) {
+ ids.forEach(id => {
+ let el = document.getElementById('m-'+id);
+ if (el) el.setAttribute('fill', '#f88');
+ });
+ }
+}
+
+window.addEventListener('DOMContentLoaded', () => {
+ initSidebarFeatures();
+});
+
+// --- END Exercise Library with Demos ---
diff --git a/images/images_bench-press_Version3.svg b/images/images_bench-press_Version3.svg
new file mode 100644
index 0000000..95572b1
--- /dev/null
+++ b/images/images_bench-press_Version3.svg
@@ -0,0 +1,11 @@
+
+
\ No newline at end of file
diff --git a/images/images_bicep-curl_Version2.svg b/images/images_bicep-curl_Version2.svg
new file mode 100644
index 0000000..b49b68f
--- /dev/null
+++ b/images/images_bicep-curl_Version2.svg
@@ -0,0 +1,11 @@
+
+
\ No newline at end of file
diff --git a/images/images_chest-fly_Version2.svg b/images/images_chest-fly_Version2.svg
new file mode 100644
index 0000000..e142815
--- /dev/null
+++ b/images/images_chest-fly_Version2.svg
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/images/images_incline-press_Version2.svg b/images/images_incline-press_Version2.svg
new file mode 100644
index 0000000..9c4f45d
--- /dev/null
+++ b/images/images_incline-press_Version2.svg
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/images/images_lat-pulldown_Version1.svg b/images/images_lat-pulldown_Version1.svg
new file mode 100644
index 0000000..bf15fe8
--- /dev/null
+++ b/images/images_lat-pulldown_Version1.svg
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/images/images_lateral-raise_Version1.svg b/images/images_lateral-raise_Version1.svg
new file mode 100644
index 0000000..8ff8c36
--- /dev/null
+++ b/images/images_lateral-raise_Version1.svg
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/images/images_leg-press_Version1.svg b/images/images_leg-press_Version1.svg
new file mode 100644
index 0000000..b54b739
--- /dev/null
+++ b/images/images_leg-press_Version1.svg
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/images/images_lunge_Version1.svg b/images/images_lunge_Version1.svg
new file mode 100644
index 0000000..2e91cd3
--- /dev/null
+++ b/images/images_lunge_Version1.svg
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/images/images_overhead-press_Version1.svg b/images/images_overhead-press_Version1.svg
new file mode 100644
index 0000000..06f41a2
--- /dev/null
+++ b/images/images_overhead-press_Version1.svg
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/images/images_plank_Version2.svg b/images/images_plank_Version2.svg
new file mode 100644
index 0000000..37d18dd
--- /dev/null
+++ b/images/images_plank_Version2.svg
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/images/images_pull-ups_Version2.svg b/images/images_pull-ups_Version2.svg
new file mode 100644
index 0000000..b9ee338
--- /dev/null
+++ b/images/images_pull-ups_Version2.svg
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/images/images_russian-twist_Version1.svg b/images/images_russian-twist_Version1.svg
new file mode 100644
index 0000000..c067753
--- /dev/null
+++ b/images/images_russian-twist_Version1.svg
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/images/images_seated-row_Version1.svg b/images/images_seated-row_Version1.svg
new file mode 100644
index 0000000..98c4190
--- /dev/null
+++ b/images/images_seated-row_Version1.svg
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/images/images_squat_Version2.svg b/images/images_squat_Version2.svg
new file mode 100644
index 0000000..eef5867
--- /dev/null
+++ b/images/images_squat_Version2.svg
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/images/images_tricep-pushdown_Version1.svg b/images/images_tricep-pushdown_Version1.svg
new file mode 100644
index 0000000..4160da6
--- /dev/null
+++ b/images/images_tricep-pushdown_Version1.svg
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/images/placeholder.txt b/images/placeholder.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/images/placeholder.txt
@@ -0,0 +1 @@
+
diff --git a/index.html b/index.html
index 623a67d..cfcaca9 100644
--- a/index.html
+++ b/index.html
@@ -67,6 +67,56 @@
padding-bottom: 25px;
border-bottom: 1px solid #e0e0e0;
}
+
+
+
Exercise Library 💪
+
+
+
+
+
+
+
+
Workout Setup
+
Select an exercise above
+
+
+
+
+
+
+
+
+
+
+
+
Muscle Activity Map 🔥
+
+
.section:last-child {
border-bottom: none;
diff --git a/workoutmachineappfree.github.io/app.js b/workoutmachineappfree.github.io/app.js
new file mode 100644
index 0000000..f870353
--- /dev/null
+++ b/workoutmachineappfree.github.io/app.js
@@ -0,0 +1,51 @@
+// --- BEGIN Sidebar Features and Logic ---
+
+const EXERCISES = {
+ chest: [
+ { name: "Bench Press", image: "images/bench-press.gif" },
+ { name: "Incline Press", image: "images/incline-press.gif" },
+ { name: "Chest Fly", image: "images/chest-fly.gif" }
+ ],
+ back: [
+ { name: "Pull-Ups", image: "images/pull-ups.gif" },
+ { name: "Lat Pulldown", image: "images/lat-pulldown.gif" },
+ { name: "Seated Row", image: "images/seated-row.gif" }
+ ],
+ legs: [
+ { name: "Squats", image: "images/squat.gif" },
+ { name: "Lunges", image: "images/lunge.gif" },
+ { name: "Leg Press", image: "images/leg-press.gif" }
+ ],
+ shoulders: [
+ { name: "Overhead Press", image: "images/overhead-press.gif" },
+ { name: "Lateral Raise", image: "images/lateral-raise.gif" }
+ ],
+ arms: [
+ { name: "Bicep Curl", image: "images/bicep-curl.gif" },
+ { name: "Tricep Pushdown", image: "images/tricep-pushdown.gif" }
+ ],
+ core: [
+ { name: "Plank", image: "images/plank.gif" },
+ { name: "Russian Twist", image: "images/russian-twist.gif" }
+ ]
+};
+
+let selectedExercise = null;
+let personalBests = JSON.parse(localStorage.getItem('vitruvian_pbs') || '{}');
+let leaderboard = JSON.parse(localStorage.getItem('vitruvian_leaderboard') || '[]');
+
+function initSidebarFeatures() {
+ renderExercises();
+ renderPersonalBests();
+ renderLeaderboard();
+
+ const searchEl = document.getElementById('exerciseSearch');
+ const filterEl = document.getElementById('muscleFilter');
+ const startBtn = document.getElementById('startBtn');
+
+ if (searchEl) searchEl.oninput = renderExercises;
+ if (filterEl) filterEl.onchange = renderExercises;
+ if (startBtn) startBtn.onclick = startWorkoutFromSidebar;
+}
+
+function escapeHtml(s){ return (s||'').toString().replace(/[&<>\
\ No newline at end of file