|
| 1 | +// |
| 2 | +// AppDelegate.swift |
| 3 | +// Resolute Fitness |
| 4 | +// |
| 5 | +// Created by Hunter North on 7/20/18. |
| 6 | +// Copyright © 2018 Hunter North. All rights reserved. |
| 7 | +// |
| 8 | + |
| 9 | +import UIKit |
| 10 | + |
| 11 | +@UIApplicationMain |
| 12 | +class AppDelegate: UIResponder, UIApplicationDelegate { |
| 13 | + |
| 14 | + var window: UIWindow? |
| 15 | + |
| 16 | + //Variables used to deal with random events |
| 17 | + var randomInt : Int = 0 |
| 18 | + var randomIntRep : Int = 0 |
| 19 | + |
| 20 | + //struct variables are updated throughout all classes and are accessible in all other classes |
| 21 | + struct GVar { |
| 22 | + //All Possible exercises |
| 23 | + static var totEx: [[String]] = [["Bench Press", "Incline Bench Press", "Decline Bench Press", "Dumbbell Bench Press", "Incline Dumbell Bench Press", "Dumbbell Pullover", "Dumbbell Flies", "Incline Dumbbell Flies", "Cable Flies", "Skull Crushers", "Dips", "Overhead Dumbbell Extension", "Tricep Cable Extension"], |
| 24 | + ["Deadlift", "Deficit Deadlift", "Snatch Grip Deadlift", "Speed Deadlift", "Hex Bar Deadlift", "Lat Pulldown", "Bent Over Dumbell Row", "Cable Row", "T-Bar Row", "Wide Grip Pullups", "Reversed Grip Pullups", "Barbell Bicep Curls", "Dumbbell Bicep Curls", "Preacher Curls", "Cable Curls"], |
| 25 | + ["Back Squat", "Pause Squat", "Box Squat", "Split Squat", "Leg Press", "Hack Squat", "Weighted Lunge", "Leg Extension", "Leg Curl", "Calf Press", "Heel Raise"]] |
| 26 | + //All possible reps |
| 27 | + static var totRep: [[Int]] = [[0,1,2], [0,1,2], [0,1,2]] |
| 28 | + |
| 29 | + //Arrays that hold information of current workout |
| 30 | + static var currEx : [[String]] = [[],[],[]] |
| 31 | + static var currRep: [[Int]] = [[],[],[]] |
| 32 | + |
| 33 | + static var repHigh: [Int] = [12, 10, 8, 6, 10] |
| 34 | + static var repMedium: [Int] = [10, 6, 5, 4, 6] |
| 35 | + static var repLow: [Int] = [8, 6, 4, 2, 4] |
| 36 | + |
| 37 | + //arrays that hold probabilities for each event |
| 38 | + static var probEx: [[Double]] = [[],[],[]] |
| 39 | + static var probRep: [[Double]] = [[0.2,0.2,0.2],[0.2,0.2,0.2],[0.2,0.2,0.2]] |
| 40 | + |
| 41 | + //array that keeps record of how many workouts have been completed |
| 42 | + static var workoutDayRemaining: [Int] = [5,5,5] |
| 43 | + |
| 44 | + //What type of workout is today? |
| 45 | + //0: Push |
| 46 | + //1: Pull |
| 47 | + //2: Legs |
| 48 | + //3: One Rep |
| 49 | + static var todaysWorkout: Int = 5 |
| 50 | + |
| 51 | + //string that holds the most recent date |
| 52 | + static var currDate: Date? = nil |
| 53 | + |
| 54 | + //array that holds the stats of each label on overviewStats page |
| 55 | + static var allStats : [[Int]] = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]] |
| 56 | + static var consecutiveWorkouts : Int = 0 |
| 57 | + |
| 58 | + //Variables that track the status of todays workout |
| 59 | + static var workoutBegun: Bool = false |
| 60 | + static var workoutComp: Bool = false |
| 61 | + static var exNumber: Int = 0 |
| 62 | + static var exProgress: [Bool] = [false, false, false, false, false] |
| 63 | + |
| 64 | + //array to manage what exercises improved during the workout |
| 65 | + static var passFailBoolArray: [Bool] = [false, false, false] |
| 66 | + |
| 67 | + //Count of how many workout cycles have been completed |
| 68 | + static var cyclesCompleted : Int = 0 |
| 69 | + |
| 70 | + //Boolean to keep track of whether or not user has entered inital stats |
| 71 | + static var initStatsEntered : Bool = false |
| 72 | + |
| 73 | + } |
| 74 | + |
| 75 | + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { |
| 76 | + // Override point for customization after application launch. |
| 77 | + |
| 78 | + //restore the variable for if the user has entered stats |
| 79 | + GVar.initStatsEntered = UserDefaults.standard.bool(forKey: "initStatsEntered") |
| 80 | + |
| 81 | + //If the app hasnt been run before then initialize a workout |
| 82 | + //Otherwise reload all the old data |
| 83 | + if (!GVar.initStatsEntered) { |
| 84 | + //fill probability arrays |
| 85 | + fillProbEx() |
| 86 | + |
| 87 | + //create a workout |
| 88 | + createWorkout() |
| 89 | + |
| 90 | + //set value of currDate |
| 91 | + setCurrDate() |
| 92 | + } else { |
| 93 | + restoreVariablesFromUserDefaults() |
| 94 | + } |
| 95 | + |
| 96 | + return true |
| 97 | + } |
| 98 | + |
| 99 | + func applicationWillResignActive(_ application: UIApplication) { |
| 100 | + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. |
| 101 | + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. |
| 102 | + } |
| 103 | + |
| 104 | + func applicationDidEnterBackground(_ application: UIApplication) { |
| 105 | + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. |
| 106 | + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. |
| 107 | + loadVariablesToUserDefaults() |
| 108 | + } |
| 109 | + |
| 110 | + func applicationWillEnterForeground(_ application: UIApplication) { |
| 111 | + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. |
| 112 | + } |
| 113 | + |
| 114 | + func applicationDidBecomeActive(_ application: UIApplication) { |
| 115 | + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. |
| 116 | + } |
| 117 | + |
| 118 | + func applicationWillTerminate(_ application: UIApplication) { |
| 119 | + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. |
| 120 | + loadVariablesToUserDefaults() |
| 121 | + } |
| 122 | + |
| 123 | + //Load variables to user defaults |
| 124 | + func loadVariablesToUserDefaults(){ |
| 125 | + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. |
| 126 | + UserDefaults.standard.set(GVar.initStatsEntered, forKey: "initStatsEntered") |
| 127 | + UserDefaults.standard.set(GVar.currEx, forKey: "currEx") |
| 128 | + UserDefaults.standard.set(GVar.currRep, forKey: "currRep") |
| 129 | + UserDefaults.standard.set(GVar.probEx, forKey: "probEx") |
| 130 | + UserDefaults.standard.set(GVar.probRep, forKey: "probRep") |
| 131 | + UserDefaults.standard.set(GVar.workoutDayRemaining, forKey: "workoutDayRemaining") |
| 132 | + UserDefaults.standard.set(GVar.todaysWorkout, forKey: "todaysWorkout") |
| 133 | + UserDefaults.standard.set(GVar.currDate, forKey: "currDate") |
| 134 | + UserDefaults.standard.set(GVar.allStats, forKey: "allStats") |
| 135 | + UserDefaults.standard.set(GVar.consecutiveWorkouts, forKey: "consecutiveWorkouts") |
| 136 | + UserDefaults.standard.set(GVar.workoutBegun, forKey: "workoutBegun") |
| 137 | + UserDefaults.standard.set(GVar.workoutComp, forKey: "workoutComp") |
| 138 | + UserDefaults.standard.set(GVar.exNumber, forKey: "exNumber") |
| 139 | + UserDefaults.standard.set(GVar.exProgress, forKey: "exProgress") |
| 140 | + UserDefaults.standard.set(GVar.passFailBoolArray, forKey: "passFailBoolArray") |
| 141 | + UserDefaults.standard.set(GVar.cyclesCompleted, forKey: "cyclesCompleted") |
| 142 | + } |
| 143 | + |
| 144 | + |
| 145 | + //Restore variables from user defaults |
| 146 | + func restoreVariablesFromUserDefaults(){ |
| 147 | + GVar.currEx = (UserDefaults.standard.object(forKey: "currEx") as? [[String]])! |
| 148 | + GVar.currRep = (UserDefaults.standard.object(forKey: "currRep") as? [[Int]])! |
| 149 | + GVar.probEx = (UserDefaults.standard.object(forKey: "probEx") as? [[Double]])! |
| 150 | + GVar.probRep = (UserDefaults.standard.object(forKey: "probRep") as? [[Double]])! |
| 151 | + GVar.workoutDayRemaining = (UserDefaults.standard.object(forKey: "workoutDayRemaining") as? [Int])! |
| 152 | + GVar.todaysWorkout = (UserDefaults.standard.object(forKey: "todaysWorkout") as? Int)! |
| 153 | + GVar.currDate = (UserDefaults.standard.object(forKey: "currDate") as? Date)! |
| 154 | + GVar.allStats = (UserDefaults.standard.object(forKey: "allStats") as? [[Int]])! |
| 155 | + GVar.consecutiveWorkouts = (UserDefaults.standard.object(forKey: "consecutiveWorkouts") as? Int)! |
| 156 | + GVar.workoutBegun = (UserDefaults.standard.object(forKey: "workoutBegun") as? Bool)! |
| 157 | + GVar.workoutComp = (UserDefaults.standard.object(forKey: "workoutComp") as? Bool)! |
| 158 | + GVar.exNumber = (UserDefaults.standard.object(forKey: "exNumber") as? Int)! |
| 159 | + GVar.exProgress = (UserDefaults.standard.object(forKey: "exProgress") as? [Bool])! |
| 160 | + GVar.passFailBoolArray = (UserDefaults.standard.object(forKey: "passFailBoolArray") as? [Bool])! |
| 161 | + GVar.cyclesCompleted = (UserDefaults.standard.object(forKey: "cyclesCompleted") as? Int)! |
| 162 | + |
| 163 | + } |
| 164 | + |
| 165 | + //function changing the value of randomInt to a new random integer |
| 166 | + func randInt(max: Int){ |
| 167 | + randomInt = Int(arc4random_uniform(UInt32(max))) |
| 168 | + } |
| 169 | + |
| 170 | + //returns a random double between 0 and 1 |
| 171 | + func randDouble() -> Double{ |
| 172 | + return drand48() |
| 173 | + } |
| 174 | + |
| 175 | + //Fills an array with probabilites corresponding to each exercise |
| 176 | + func fillProbEx(){ |
| 177 | + for x in 0...2{ |
| 178 | + for _ in 0...(GVar.totEx[x].count-1){ |
| 179 | + GVar.probEx[x].append(0.2) |
| 180 | + } |
| 181 | + } |
| 182 | + } |
| 183 | + |
| 184 | + //creates a new set of workouts for the user |
| 185 | + func createWorkout(){ |
| 186 | + for x in 0...2 { |
| 187 | + //clear current exercise |
| 188 | + if (GVar.currEx[x].count != 0) { |
| 189 | + GVar.currEx[x].removeAll() |
| 190 | + } |
| 191 | + //clear current reps |
| 192 | + if (GVar.currRep[x].count != 0){ |
| 193 | + GVar.currRep[x].removeAll() |
| 194 | + } |
| 195 | + } |
| 196 | + |
| 197 | + for x in 0...2 { |
| 198 | + for y in 0...4{ |
| 199 | + //first exercise is always the same: main exercise (bench press, deadlift, backsquat) |
| 200 | + if (y == 0){ |
| 201 | + GVar.currEx[x].append(GVar.totEx[x][0]) |
| 202 | + addRep(index: x) |
| 203 | + } else { |
| 204 | + //funciton that searches for a random exerise |
| 205 | + lookForNewExercise(index: x) |
| 206 | + } |
| 207 | + } |
| 208 | + } |
| 209 | + |
| 210 | + orderWorkout() |
| 211 | + } |
| 212 | + |
| 213 | + |
| 214 | + func lookForNewExercise(index: Int){ |
| 215 | + randInt(max: GVar.totEx[index].count) |
| 216 | + //if the new workout plan doesnt already contain the random selected one and then passes the probability test function then it is addded to the current workout and a random rep range is generated with it |
| 217 | + if (GVar.currEx[index].contains(GVar.totEx[index][randomInt]) || !passesProbTest(ex: GVar.totEx[index][randomInt], index: index, exercise: randomInt) ){ |
| 218 | + lookForNewExercise(index: index) |
| 219 | + } else { |
| 220 | + GVar.currEx[index].append(GVar.totEx[index][randomInt]) |
| 221 | + addRep(index: index) |
| 222 | + } |
| 223 | + } |
| 224 | + |
| 225 | + //Probablity test generates a random double... |
| 226 | + //If the random double is less than the corressponding double stored in the proability array then it passes the probTest |
| 227 | + func passesProbTest(ex: String, index: Int, exercise: Int) -> Bool { |
| 228 | + if(randDouble() < GVar.probEx[index][exercise]){ |
| 229 | + return true; |
| 230 | + } |
| 231 | + return false |
| 232 | + } |
| 233 | + |
| 234 | + //function that adds a random rep range to workout |
| 235 | + func addRep(index: Int){ |
| 236 | + //generates a random int |
| 237 | + randomIntRep = Int(arc4random_uniform(UInt32(3))) |
| 238 | + //if statement below is another proability test |
| 239 | + //if passed then added to corresponding rep within current workout |
| 240 | + //if it doesn't pass, generate a new rep by recalling function |
| 241 | + if (randDouble() < GVar.probRep[index][randomIntRep]){ |
| 242 | + GVar.currRep[index].append(GVar.totRep[index][randomIntRep]) |
| 243 | + } else { |
| 244 | + addRep(index: index) |
| 245 | + } |
| 246 | + } |
| 247 | + |
| 248 | + //function that orders the array holding the current workout so that exercises are done/displayed in an order that follows exerise rule of ordering exercises from largest muscle group to smallest |
| 249 | + //Sorted with bubblesort |
| 250 | + func orderWorkout(){ |
| 251 | + for x in 0...2{ |
| 252 | + for _ in 0...GVar.currEx[x].count { |
| 253 | + for value in 1...GVar.currEx[x].count - 1 { |
| 254 | + if (findIndex(of: GVar.currEx[x][value - 1], arr: GVar.totEx[x]) > findIndex(of: GVar.currEx[x][value], arr: GVar.totEx[x])) { |
| 255 | + let largerValue = GVar.currEx[x][value-1] |
| 256 | + GVar.currEx[x][value-1] = GVar.currEx[x][value] |
| 257 | + GVar.currEx[x][value] = largerValue |
| 258 | + } |
| 259 | + } |
| 260 | + } |
| 261 | + } |
| 262 | + } |
| 263 | + |
| 264 | + //function used to find if the randomly selected workout has already been selected |
| 265 | + func findIndex(of: String, arr: [String]) -> Int { |
| 266 | + for x in 0...arr.count { |
| 267 | + if (arr[x] == of){ |
| 268 | + return x |
| 269 | + } |
| 270 | + } |
| 271 | + return -1 |
| 272 | + } |
| 273 | + |
| 274 | + func setCurrDate(){ |
| 275 | + if (GVar.currDate == nil){ |
| 276 | + GVar.currDate = Date() |
| 277 | + } |
| 278 | + } |
| 279 | +} |
0 commit comments