\ No newline at end of file
diff --git a/chapter2/.gitignore b/trainer/.gitignore
similarity index 100%
rename from chapter2/.gitignore
rename to trainer/.gitignore
diff --git a/trainer/app/content/15seconds.wav b/trainer/app/content/15seconds.wav
new file mode 100644
index 0000000..c7a0329
Binary files /dev/null and b/trainer/app/content/15seconds.wav differ
diff --git a/trainer/app/content/321.wav b/trainer/app/content/321.wav
new file mode 100644
index 0000000..e9a807d
Binary files /dev/null and b/trainer/app/content/321.wav differ
diff --git a/trainer/app/content/crunches.wav b/trainer/app/content/crunches.wav
new file mode 100644
index 0000000..0a5d40a
Binary files /dev/null and b/trainer/app/content/crunches.wav differ
diff --git a/trainer/app/content/highknees.wav b/trainer/app/content/highknees.wav
new file mode 100644
index 0000000..f9530dd
Binary files /dev/null and b/trainer/app/content/highknees.wav differ
diff --git a/trainer/app/content/jumpingjacks.wav b/trainer/app/content/jumpingjacks.wav
new file mode 100644
index 0000000..43682af
Binary files /dev/null and b/trainer/app/content/jumpingjacks.wav differ
diff --git a/trainer/app/content/lunge.wav b/trainer/app/content/lunge.wav
new file mode 100644
index 0000000..fc20d9c
Binary files /dev/null and b/trainer/app/content/lunge.wav differ
diff --git a/trainer/app/content/nextup.mp3 b/trainer/app/content/nextup.mp3
new file mode 100644
index 0000000..b6f76ca
Binary files /dev/null and b/trainer/app/content/nextup.mp3 differ
diff --git a/trainer/app/content/nextup.wav b/trainer/app/content/nextup.wav
new file mode 100644
index 0000000..fb96f74
Binary files /dev/null and b/trainer/app/content/nextup.wav differ
diff --git a/trainer/app/content/plank.wav b/trainer/app/content/plank.wav
new file mode 100644
index 0000000..d04f808
Binary files /dev/null and b/trainer/app/content/plank.wav differ
diff --git a/trainer/app/content/pushupandrotate.wav b/trainer/app/content/pushupandrotate.wav
new file mode 100644
index 0000000..9c613c3
Binary files /dev/null and b/trainer/app/content/pushupandrotate.wav differ
diff --git a/trainer/app/content/pushups.wav b/trainer/app/content/pushups.wav
new file mode 100644
index 0000000..9b34f19
Binary files /dev/null and b/trainer/app/content/pushups.wav differ
diff --git a/trainer/app/content/sideplank.wav b/trainer/app/content/sideplank.wav
new file mode 100644
index 0000000..e361611
Binary files /dev/null and b/trainer/app/content/sideplank.wav differ
diff --git a/trainer/app/content/squats.wav b/trainer/app/content/squats.wav
new file mode 100644
index 0000000..4531335
Binary files /dev/null and b/trainer/app/content/squats.wav differ
diff --git a/trainer/app/content/stepup.wav b/trainer/app/content/stepup.wav
new file mode 100644
index 0000000..f5ec2c6
Binary files /dev/null and b/trainer/app/content/stepup.wav differ
diff --git a/trainer/app/content/tick.mp3 b/trainer/app/content/tick.mp3
new file mode 100644
index 0000000..5e71431
Binary files /dev/null and b/trainer/app/content/tick.mp3 differ
diff --git a/trainer/app/content/tick10s.mp3 b/trainer/app/content/tick10s.mp3
new file mode 100644
index 0000000..b8811c8
Binary files /dev/null and b/trainer/app/content/tick10s.mp3 differ
diff --git a/trainer/app/content/tricepdips.wav b/trainer/app/content/tricepdips.wav
new file mode 100644
index 0000000..7d7c9e8
Binary files /dev/null and b/trainer/app/content/tricepdips.wav differ
diff --git a/trainer/app/content/wallsit.wav b/trainer/app/content/wallsit.wav
new file mode 100644
index 0000000..23ff40b
Binary files /dev/null and b/trainer/app/content/wallsit.wav differ
diff --git a/trainer/app/css/app.css b/trainer/app/css/app.css
new file mode 100644
index 0000000..ef55b1a
--- /dev/null
+++ b/trainer/app/css/app.css
@@ -0,0 +1,144 @@
+/* app css stylesheet */
+
+html{
+ height:100%;
+}
+
+body {
+ padding-top: 70px;
+ padding-bottom: 20px;
+ min-height: 100%;
+ font-size: 13px;
+ font-family: 'Roboto Slab';
+ font-style: normal;
+ font-weight: 400;
+}
+
+/* Set padding to keep content from hitting the edges */
+.body-content {
+ padding-left: 15px;
+ padding-right: 15px;
+}
+
+/* Set width on the form input elements since they're 100% wide by default */
+input,
+select,
+textarea {
+ max-width: 280px;
+}
+
+/* styles for validation helpers - start*/
+.field-validation-error {
+ color: #b94a48;
+}
+
+.field-validation-valid {
+ display: none;
+}
+
+input.input-validation-error {
+ border: 1px solid #b94a48;
+}
+
+input[type="checkbox"].input-validation-error {
+ border: 0 none;
+}
+
+.validation-summary-errors {
+ color: #b94a48;
+}
+
+.validation-summary-valid {
+ display: none;
+}
+/* styles for validation helpers - end */
+
+/*styles for top nav bar - start*/
+.navbar-default.top-navbar {
+ background-color: #4eaded;
+ border-color: #4eaded;
+}
+
+.navbar-default.top-navbar h1 {
+ color: white;
+ margin-top: 15px;
+ margin-bottom: 15px;
+}
+/*styles for top nav bar - end*/
+
+/*styles for container - start*/
+.container.app-container{
+ width:100%;
+ max-width:100%;
+}
+.workout-display-div{
+ text-align:center;
+ padding:40px;
+}
+.workout-display-div .img-responsive{
+ margin: 25px auto;
+ width:540px;
+ height:360px;
+ cursor:pointer;
+}
+.workout-display-div .time-progress{
+ margin-top:40px;
+}
+/*styles for container - end*/
+
+/*Styles for start page - start*/
+.text-center{
+ color:#4eaded;
+}
+#start{
+ text-align:center;
+ margin-top:25px;
+}
+#start a {
+ text-decoration: none;
+ font-size: 67px;
+ color:#4eaded;
+}
+#start a:hover{
+ color:#4eaded;
+}
+#start a .glyphicon {
+ top:8px;
+}
+/*Styles for start page - end*/
+
+/*Styles for workout page - start*/
+.workout-app-container{
+ padding-top:15px;
+}
+
+#video-panel .panel-body{
+ max-height:650px;
+ overflow:auto;
+}
+#pause-overlay {
+ position:absolute;
+ top:0px;
+ width:100%;
+ height:100%;
+ opacity:0; /*Comment this line to try our mouse event based pause and resume. */
+ z-index:10;
+
+}
+
+/*Comment this style to try our mouse event based pause and resume. */
+#pause-overlay:hover {
+ opacity:.8;
+}
+#pause-overlay .pause{
+ font-size:120pt;
+ width:140px;
+ height:140px;
+ color:#4eaded;
+}
+.absolute-center {
+ margin: auto;
+ position: absolute;
+ top: 0; left: 0; bottom: 0; right: 0;
+}
+/*Styles for workout page - end*/
\ No newline at end of file
diff --git a/trainer/app/img/JumpingJacks.png b/trainer/app/img/JumpingJacks.png
new file mode 100644
index 0000000..aaed124
Binary files /dev/null and b/trainer/app/img/JumpingJacks.png differ
diff --git a/trainer/app/img/Plank.png b/trainer/app/img/Plank.png
new file mode 100644
index 0000000..fabc051
Binary files /dev/null and b/trainer/app/img/Plank.png differ
diff --git a/trainer/app/img/Pushup.png b/trainer/app/img/Pushup.png
new file mode 100644
index 0000000..b1c1b7d
Binary files /dev/null and b/trainer/app/img/Pushup.png differ
diff --git a/trainer/app/img/crunches.png b/trainer/app/img/crunches.png
new file mode 100644
index 0000000..208957e
Binary files /dev/null and b/trainer/app/img/crunches.png differ
diff --git a/trainer/app/img/finish.png b/trainer/app/img/finish.png
new file mode 100644
index 0000000..e1c890e
Binary files /dev/null and b/trainer/app/img/finish.png differ
diff --git a/trainer/app/img/highknees.png b/trainer/app/img/highknees.png
new file mode 100644
index 0000000..3e83196
Binary files /dev/null and b/trainer/app/img/highknees.png differ
diff --git a/trainer/app/img/lunges.png b/trainer/app/img/lunges.png
new file mode 100644
index 0000000..7a4a0fe
Binary files /dev/null and b/trainer/app/img/lunges.png differ
diff --git a/trainer/app/img/pushupNRotate.png b/trainer/app/img/pushupNRotate.png
new file mode 100644
index 0000000..50f58a1
Binary files /dev/null and b/trainer/app/img/pushupNRotate.png differ
diff --git a/trainer/app/img/rest.png b/trainer/app/img/rest.png
new file mode 100644
index 0000000..4c89bd1
Binary files /dev/null and b/trainer/app/img/rest.png differ
diff --git a/trainer/app/img/sideplank.png b/trainer/app/img/sideplank.png
new file mode 100644
index 0000000..91017c8
Binary files /dev/null and b/trainer/app/img/sideplank.png differ
diff --git a/trainer/app/img/squat.png b/trainer/app/img/squat.png
new file mode 100644
index 0000000..e368e92
Binary files /dev/null and b/trainer/app/img/squat.png differ
diff --git a/trainer/app/img/start.png b/trainer/app/img/start.png
new file mode 100644
index 0000000..0427b0c
Binary files /dev/null and b/trainer/app/img/start.png differ
diff --git a/trainer/app/img/stepUpOntoChair.png b/trainer/app/img/stepUpOntoChair.png
new file mode 100644
index 0000000..37a4710
Binary files /dev/null and b/trainer/app/img/stepUpOntoChair.png differ
diff --git a/trainer/app/img/tricepdips.png b/trainer/app/img/tricepdips.png
new file mode 100644
index 0000000..946d6ab
Binary files /dev/null and b/trainer/app/img/tricepdips.png differ
diff --git a/trainer/app/img/wallsit.png b/trainer/app/img/wallsit.png
new file mode 100644
index 0000000..bbced2b
Binary files /dev/null and b/trainer/app/img/wallsit.png differ
diff --git a/trainer/app/index.html b/trainer/app/index.html
new file mode 100644
index 0000000..b041b40
--- /dev/null
+++ b/trainer/app/index.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+ 7 Minute Workout
+
+
+
+
+
+
+
+
+
+
+
7 Minute Workout
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trainer/app/js/7MinWorkout/directives.js b/trainer/app/js/7MinWorkout/directives.js
new file mode 100644
index 0000000..057ae55
--- /dev/null
+++ b/trainer/app/js/7MinWorkout/directives.js
@@ -0,0 +1,3 @@
+'use strict';
+
+/* Directives */
\ No newline at end of file
diff --git a/trainer/app/js/7MinWorkout/filters.js b/trainer/app/js/7MinWorkout/filters.js
new file mode 100644
index 0000000..78b2ee0
--- /dev/null
+++ b/trainer/app/js/7MinWorkout/filters.js
@@ -0,0 +1,17 @@
+'use strict';
+
+/* Filters */
+angular.module('7minWorkout').filter('secondsToTime', function () {
+ return function (input) {
+ var sec = parseInt(input, 10);
+ if (isNaN(sec)) return "00:00:00";
+
+ var hours = Math.floor(sec / 3600);
+ var minutes = Math.floor((sec - (hours * 3600)) / 60);
+ var seconds = sec - (hours * 3600) - (minutes * 60);
+
+ return ("0" + hours).substr(-2) + ':'
+ + ("0" + minutes).substr(-2) + ':'
+ + ("0" + seconds).substr(-2);
+ }
+});
\ No newline at end of file
diff --git a/trainer/app/js/7MinWorkout/services.js b/trainer/app/js/7MinWorkout/services.js
new file mode 100644
index 0000000..6b7e2aa
--- /dev/null
+++ b/trainer/app/js/7MinWorkout/services.js
@@ -0,0 +1,3 @@
+'use strict';
+
+/* Services */
\ No newline at end of file
diff --git a/trainer/app/js/7MinWorkout/workout.js b/trainer/app/js/7MinWorkout/workout.js
new file mode 100644
index 0000000..0d20860
--- /dev/null
+++ b/trainer/app/js/7MinWorkout/workout.js
@@ -0,0 +1,385 @@
+'use strict';
+
+/* Controllers */
+
+angular.module('7minWorkout')
+ .controller('WorkoutController', ['$scope', '$interval', '$location', function ($scope, $interval, $location) {
+ function WorkoutPlan(args) {
+ this.exercises = [];
+ this.name = args.name;
+ this.title = args.title;
+ this.restBetweenExercise = args.restBetweenExercise;
+ this.totalWorkoutDuration = function () {
+ if (this.exercises.length == 0) return 0;
+ var total = 0;
+ angular.forEach(this.exercises, function (exercise) {
+ total = total + exercise.duration;
+ });
+ return this.restBetweenExercise * (this.exercises.length - 1) + total;
+ }
+ };
+
+ function Exercise(args) {
+ this.name = args.name;
+ this.title = args.title;
+ this.description = args.description;
+ this.image = args.image;
+ this.related = {};
+ this.related.videos = args.videos;
+ this.nameSound = args.nameSound;
+ this.procedure = args.procedure;
+ }
+
+ var restExercise;
+ var exerciseIntervalPromise;
+ var startWorkout = function () {
+ $scope.workoutPlan = createWorkout();
+ $scope.workoutTimeRemaining = $scope.workoutPlan.totalWorkoutDuration();
+ restExercise = {
+ details: new Exercise({
+ name: "rest",
+ title: "Relax!",
+ description: "Relax a bit!",
+ image: "img/rest.png",
+ }),
+ duration: $scope.workoutPlan.restBetweenExercise
+ };
+
+ $scope.currentExerciseIndex = -1;
+ startExercise($scope.workoutPlan.exercises[0]);
+ };
+
+ var startExercise = function (exercisePlan) {
+ $scope.currentExercise = exercisePlan;
+ $scope.currentExerciseDuration = 0;
+
+ if (exercisePlan.details.name != 'rest') {
+ $scope.currentExerciseIndex++;
+ }
+
+ exerciseIntervalPromise = startExerciseTimeTracking();
+ };
+
+ var getNextExercise = function (currentExercisePlan) {
+ var nextExercise = null;
+ if (currentExercisePlan === restExercise) {
+ nextExercise = $scope.workoutPlan.exercises[$scope.currentExerciseIndex + 1];
+ }
+ else {
+ if ($scope.currentExerciseIndex < $scope.workoutPlan.exercises.length - 1) {
+ nextExercise = restExercise;
+ }
+ }
+ return nextExercise;
+ };
+
+ $scope.pauseWorkout = function () {
+ $interval.cancel(exerciseIntervalPromise);
+ $scope.workoutPaused = true;
+ };
+
+ $scope.resumeWorkout = function () {
+ exerciseIntervalPromise = startExerciseTimeTracking();
+ $scope.workoutPaused = false;
+ };
+
+ $scope.pauseResumeToggle = function () {
+ if ($scope.workoutPaused) {
+ $scope.resumeWorkout();
+ }
+ else {
+ $scope.pauseWorkout();
+ }
+ }
+
+ var startExerciseTimeTracking = function () {
+ var promise = $interval(function () {
+ ++$scope.currentExerciseDuration;
+ --$scope.workoutTimeRemaining;
+ }, 1000, $scope.currentExercise.duration - $scope.currentExerciseDuration);
+
+ promise.then(function () {
+ var next = getNextExercise($scope.currentExercise);
+ if (next) {
+ startExercise(next);
+ }
+ else {
+ $location.path('/finish');
+ }
+ }, function (error) {
+ console.log('Inteval promise cancelled. Error reason -' + error);
+ });
+ return promise;
+ }
+
+ $scope.onKeyPressed = function (event) {
+ if (event.which == 80 || event.which == 112) { // 'p' or 'P' key to toggle pause and resume.
+ $scope.pauseResumeToggle();
+ }
+ };
+
+ //$scope.$watch('currentExerciseDuration', function (nVal) {
+ // if (nVal == $scope.currentExercise.duration) {
+ // var next = getNextExercise($scope.currentExercise);
+ // if (next) {
+ // startExercise(next);
+ // } else {
+ // console.log("Workout complete!")
+ // }
+ // }
+ //});
+
+ var createWorkout = function () {
+ var workout = new WorkoutPlan({
+ name: "7minWorkout",
+ title: "7 Minute Workout",
+ restBetweenExercise: 10
+ });
+
+ workout.exercises.push({
+ details: new Exercise({
+ name: "jumpingJacks",
+ title: "Jumping Jacks",
+ description: "A jumping jack or star jump, also called side-straddle hop is a physical jumping exercise.",
+ image: "img/JumpingJacks.png",
+ nameSound: "content/jumpingjacks.wav",
+ videos: ["//www.youtube.com/embed/dmYwZH_BNd0", "//www.youtube.com/embed/BABOdJ-2Z6o", "//www.youtube.com/embed/c4DAnQ6DtF8"],
+ procedure: "Assume an erect position, with feet together and arms at your side.\
+ Slightly bend your knees, and propel yourself a few inches into the air.\
+ While in air, bring your legs out to the side about shoulder width or slightly wider.\
+ As you are moving your legs outward, you should raise your arms up over your head; arms should be slightly bent throughout the entire in-air movement.\
+ Your feet should land shoulder width or wider as your hands meet above your head with arms slightly bent"
+ }),
+ duration: 30
+ });
+ workout.exercises.push({
+ details: new Exercise({
+ name: "wallSit",
+ title: "Wall Sit",
+ description: "A wall sit, also known as a Roman Chair, is an exercise done to strengthen the quadriceps muscles.",
+ image: "img/wallsit.png",
+ nameSound: "content/wallsit.wav",
+ videos: ["//www.youtube.com/embed/y-wV4Venusw", "//www.youtube.com/embed/MMV3v4ap4ro"],
+ procedure: "Place your back against a wall with your feet shoulder width apart and a little ways out from the wall.\
+ Then, keeping your back against the wall, lower your hips until your knees form right angles. "
+ }),
+ duration: 30
+ });
+ workout.exercises.push({
+ details: new Exercise({
+ name: "pushUp",
+ title: "Push Up",
+ description: "A push-up is a common exercise performed in a prone position by raising and lowering the body using the arms",
+ image: "img/Pushup.png",
+ nameSound: "content/pushups.wav",
+ videos: ["//www.youtube.com/embed/Eh00_rniF8E", "//www.youtube.com/embed/ZWdBqFLNljc", "//www.youtube.com/embed/UwRLWMcOdwI", "//www.youtube.com/embed/ynPwl6qyUNM", "//www.youtube.com/embed/OicNTT2xzMI"],
+ procedure: "Lie prone on the ground with hands placed as wide or slightly wider than shoulder width. \
+ Keeping the body straight, lower body to the ground by bending arms at the elbows. \
+ Raise body up off the ground by extending the arms."
+ }),
+ duration: 30
+ });
+ workout.exercises.push({
+ details: new Exercise({
+ name: "crunches",
+ title: "Abdominal Crunches",
+ description: "The basic crunch is a abdominal exercise in a strength-training program.",
+ image: "img/crunches.png",
+ nameSound: "content/crunches.wav",
+ videos: ["//www.youtube.com/embed/Xyd_fa5zoEU", "//www.youtube.com/embed/MKmrqcoCZ-M"],
+ procedure: "Lie on your back with your knees bent and feet flat on the floor, hip-width apart.\
+ Place your hands behind your head so your thumbs are behind your ears.\
+ Hold your elbows out to the sides but rounded slightly in.\
+ Gently pull your abdominals inward.\
+ Curl up and forward so that your head, neck, and shoulder blades lift off the floor.\
+ Hold for a moment at the top of the movement and then lower slowly back down."
+ }),
+ duration: 30
+ });
+ workout.exercises.push({
+ details: new Exercise({
+ name: "stepUpOntoChair",
+ title: "Step Up Onto Chair",
+ description: "Step exercises are ideal for building muscle in your lower body.",
+ image: "img/stepUpOntoChair.png",
+ nameSound: "content/stepup.wav",
+ videos: ["//www.youtube.com/embed/aajhW7DD1EA"],
+ procedure: "Position your chair in front of you.\
+ Stand with your feet about hip width apart, arms at your sides.\
+ Step up onto the seat with one foot, pressing down while bringing your other foot up next to it. \
+ Step back with the leading foot and bring the trailing foot down to finish one step-up."
+ }),
+ duration: 30
+ });
+ workout.exercises.push({
+ details: new Exercise({
+ name: "squat",
+ title: "Squat",
+ description: "The squat is a compound, full body exercise that trains primarily the muscles of the thighs, hips, buttocks and quads.",
+ image: "img/squat.png",
+ nameSound: "content/squats.wav",
+ videos: ["//www.youtube.com/embed/QKKZ9AGYTi4", "//www.youtube.com/embed/UXJrBgI2RxA"],
+ procedure: "Stand with your head facing forward and your chest held up and out.\
+ Place your feet shoulder-width apart or little wider. Extend your hands straight out in front of you.\
+ Sit back and down like you're sitting into a chair. Keep your head facing straight as your upper body bends forward a bit. Rather than allowing your back to round, let your lower back arch slightly as you go down.\
+ Lower down so your thighs are parallel to the floor, with your knees over your ankles. Press your weight back into your heels.\
+ Keep your body tight, and push through your heels to bring yourself back to the starting position."
+ }),
+ duration: 30
+ });
+ workout.exercises.push({
+ details: new Exercise({
+ name: "tricepdips",
+ title: "Tricep Dips On Chair",
+ description: "A body weight exercise that targets triceps.",
+ image: "img/tricepdips.png",
+ nameSound: "content/tricepdips.wav",
+ videos: ["//www.youtube.com/embed/tKjcgfu44sI", "//www.youtube.com/embed/jox1rb5krQI"],
+ procedure: "Sit up on a chair. Your legs should be slightly extended, with your feet flat on the floor.\
+ Place your hands edges of the chair. Your palms should be down, fingertips pointing towards the floor.\
+ Without moving your legs, bring your glutes forward off the chair.\
+ Steadily lower yourself. When your elbows form 90 degrees angles, push yourself back up to starting position."
+ }),
+ duration: 30
+ });
+ workout.exercises.push({
+ details: new Exercise({
+ name: "plank",
+ title: "Plank",
+ description: "The plank (also called a front hold, hover, or abdominal bridge) is an isometric core strength exercise that involves maintaining a difficult position for extended periods of time. ",
+ image: "img/Plank.png",
+ nameSound: "content/plank.wav",
+ videos: ["//www.youtube.com/embed/pSHjTRCQxIw", "//www.youtube.com/embed/TvxNkmjdhMM"],
+ procedure: "Get into pushup position on the floor.\
+ Bend your elbows 90 degrees and rest your weight on your forearms.\
+ Your elbows should be directly beneath your shoulders, and your body should form a straight line from head to feet.\
+ Hold this position."
+ }),
+ duration: 30
+ });
+ workout.exercises.push({
+ details: new Exercise({
+ name: "highKnees",
+ title: "High Knees",
+ description: "A form exercise that develops strength and endurance of the hip flexors and quads and stretches the hip extensors.",
+ image: "img/highknees.png",
+ nameSound: "content/highknees.wav",
+ videos: ["//www.youtube.com/embed/OAJ_J3EZkdY", "//www.youtube.com/embed/8opcQdC-V-U"],
+ procedure: "Start standing with feet hip-width apart. \
+ Do inplace jog with your knees lifting as much as possible towards your chest."
+ }),
+ duration: 30
+ });
+ workout.exercises.push({
+ details: new Exercise({
+ name: "lunges",
+ title: "Lunges",
+ description: "Lunges are a good exercise for strengthening, sculpting and building several muscles/muscle groups, including the quadriceps (or thighs), the gluteus maximus (or buttocks) as well as the hamstrings. ",
+ image: "img/lunges.png",
+ nameSound: "content/lunge.wav",
+ videos: ["//www.youtube.com/embed/Z2n58m2i4jg"],
+ procedure: "Stand erect with your feet about one shoulder width apart.\
+ Put your hands on your hips, keep your back as straight as possible, relax your shoulders and keep your eyes facing directly ahead.\
+ Take a large step forward with one leg.\
+ As you step forward, lower your hips and bend your knees until they both form 90 degree angles.\
+ Return to starting position.\
+ Repeat with your alternate leg."
+ }),
+ duration: 30
+ });
+ workout.exercises.push({
+ details: new Exercise({
+ name: "pushupNRotate",
+ title: "Pushup And Rotate",
+ description: "A variation of pushup that requires you to rotate.",
+ image: "img/pushupNRotate.png",
+ nameSound: "content/pushupandrotate.wav",
+ videos: ["//www.youtube.com/embed/qHQ_E-f5278"],
+ procedure: "Assume the classic pushup position, but as you come up, rotate your body so your right arm lifts up and extends overhead.\
+ Return to the starting position, lower yourself, then push up and rotate till your left hand points toward the ceiling."
+ }),
+ duration: 30
+ });
+ workout.exercises.push({
+ details: new Exercise({
+ name: "sidePlank",
+ title: "Side Plank",
+ description: "A variation to Plank done using one hand only",
+ image: "img/sideplank.png",
+ nameSound: "content/sideplank.wav",
+ videos: ["//www.youtube.com/embed/wqzrb67Dwf8", "//www.youtube.com/embed/_rdfjFSFKMY"],
+ procedure: "Lie on your side, in a straight line from head to feet, resting on your forearm.\
+ Your elbow should be directly under your shoulder.\
+ With your abdominals gently contracted, lift your hips off the floor, maintaining the line.\
+ Keep your hips square and your neck in line with your spine. Hold the position."
+ }),
+ duration: 30
+ });
+ return workout;
+ }
+
+ var init = function () {
+ startWorkout();
+ };
+
+ init();
+ }]);
+
+angular.module('7minWorkout')
+ .controller('WorkoutAudioController', ['$scope', '$interval', '$location', '$timeout', function ($scope, $interval, $location, $timeout) {
+ $scope.exercisesAudio = [];
+
+ var workoutPlanwatch = $scope.$watch('workoutPlan', function (newValue, oldValue) {
+ if (newValue) {
+ angular.forEach($scope.workoutPlan.exercises, function (exercise) {
+ $scope.exercisesAudio.push({ src: exercise.details.nameSound, type: "audio/wav" });
+ });
+ workoutPlanwatch(); //unbind the watch.
+ }
+ });
+
+ $scope.$watch('currentExercise', function (newValue, oldValue) {
+ if (newValue && newValue != oldValue) {
+ if ($scope.currentExercise.details.name == 'rest') {
+ $timeout(function () {
+ $scope.nextUpAudio.play();
+ }, 2000);
+ $timeout(function () {
+ $scope.nextUpExerciseAudio.play($scope.currentExerciseIndex + 1, true);
+ }, 3000);
+ }
+ }
+ });
+
+ $scope.$watch('currentExerciseDuration', function (newValue, oldValue) {
+ if (newValue) {
+ if (newValue == Math.floor($scope.currentExercise.duration / 2) && $scope.currentExercise.details.name != 'rest') {
+ $scope.halfWayAudio.play();
+ }
+ else if (newValue == $scope.currentExercise.duration - 3) {
+ $scope.aboutToCompleteAudio.play();
+ }
+ }
+ });
+
+ $scope.$watch('workoutPaused', function (newValue, oldValue) {
+ if (newValue) {
+ $scope.ticksAudio.pause();
+ $scope.nextUpAudio.pause();
+ $scope.nextUpExerciseAudio.pause();
+ $scope.halfWayAudio.pause();
+ $scope.aboutToCompleteAudio.pause();
+ }
+ else {
+ $scope.ticksAudio.play();
+ if ($scope.halfWayAudio.currentTime > 0 && $scope.halfWayAudio.currentTime < $scope.halfWayAudio.duration) $scope.halfWayAudio.play();
+ if ($scope.aboutToCompleteAudio.currentTime > 0 && $scope.aboutToCompleteAudio.currentTime < $scope.aboutToCompleteAudio.duration) $scope.aboutToCompleteAudio.play();
+ }
+ });
+
+ var init = function () {
+ }
+
+ init();
+
+ }]);
\ No newline at end of file
diff --git a/trainer/app/js/app.js b/trainer/app/js/app.js
new file mode 100644
index 0000000..40fce52
--- /dev/null
+++ b/trainer/app/js/app.js
@@ -0,0 +1,17 @@
+'use strict';
+
+angular.module('app', ['ngRoute', 'ngSanitize', '7minWorkout', 'mediaPlayer']).
+config(function ($routeProvider, $sceDelegateProvider) {
+ $routeProvider.when('/start', { templateUrl: 'partials/start.html' });
+ $routeProvider.when('/workout', { templateUrl: 'partials/workout.html', controller: 'WorkoutController' });
+ $routeProvider.when('/finish', { templateUrl: 'partials/finish.html' });
+ $routeProvider.otherwise({ redirectTo: '/start' });
+
+ $sceDelegateProvider.resourceUrlWhitelist([
+ // Allow same origin resource loads.
+ 'self',
+ // Allow loading from our assets domain. Notice the difference between * and **.
+ 'http://*.youtube.com/**']);
+});
+
+angular.module('7minWorkout', []);
\ No newline at end of file
diff --git a/trainer/app/js/vendor/angular-media-player.js b/trainer/app/js/vendor/angular-media-player.js
new file mode 100644
index 0000000..ed55d34
--- /dev/null
+++ b/trainer/app/js/vendor/angular-media-player.js
@@ -0,0 +1,511 @@
+/**
+ * MDN references for hackers:
+ * ===========================
+ * Media events on