I'm building a simple iOS app using Swift that calculates the One Rep Max weight a user can theoretically lift. User inputs a weight lifted, the number of repetitions and the app uses one of several formulas to calculate the maximum weight they should be able to lift one time.
I'm skeptical about the way I'm implementing this whole thing because I'm using enum for the formula names but because I'm also providing the ability to save lift events in a log using Core Data, I have an entity called Formula with a relationship to a LiftEvent.
It works, but I think it smells and I would really appreciate some direction from someone who can tell me if it's a bad idea to be using both an enum and an entity for these formulas. If I'm headed down the wrong path, I want someone to set me straight.
Here's the LiftEvent:
import Foundation
import CoreData
extension LiftEvent {
@NSManaged var date: NSDate
@NSManaged var liftEventUid: NSNumber
@NSManaged var maxAmount: NSNumber
@NSManaged var repetitions: NSNumber
@NSManaged var weightLifted: NSNumber
@NSManaged var calculation: Formula
@NSManaged var lift: Lift
}
and the Formula entity:
import Foundation
import CoreData
extension Formula {
@NSManaged var formulaName: String
@NSManaged var formulaUid: NSNumber
@NSManaged var used: NSSet
}
Here's the CalculatorBrain.swift containing the enum for the formula names and the calculation function:
import Foundation
let formulas = ["Epley", "Brzychi", "Baechle", "Lander", "Lombardi", "Mayhew Et.Al.", "O'Conner Et.Al."]
enum CalculationFormula: Int {
case Epley
case Brzychi
case Baechle
case Lander
case Lombardi
case MayhewEtAl
case OConnerEtAl
case TotalFormulas
var formulaName: String {
switch self {
case .Epley:
return "Epley"
case .Brzychi:
return "Brzychi"
case .Baechle:
return "Baechle"
case .Lander:
return "Lander"
case .Lombardi:
return "Lombardi"
case .MayhewEtAl:
return "Mayhew Et.Al."
case .OConnerEtAl:
return "O'Conner Et.Al."
default:
return "Not Found"
}
}
}
class CalculatorBrain: NSObject {
var weightLifted: Double?
var repetitions: Double?
var oneRepMax: Double?
var preferredFormula: CalculationFormula
override init() {
let userDefaults = NSUserDefaults.standardUserDefaults()
let tempDefault = userDefaults.objectForKey("preferredFormula") as! Int?
self.preferredFormula = CalculationFormula.Epley
if(tempDefault != nil) {
self.preferredFormula = CalculationFormula(rawValue: tempDefault!)!
}
}
func calculateOneRepMax(weightLifted: Double, repetitions: Double, formula: CalculationFormula ) -> Double {
switch formula {
case .Epley:
oneRepMax = weightLifted * (1 + (repetitions)/30)
return oneRepMax!
case .Brzychi:
oneRepMax = weightLifted * (36/(37 - repetitions))
return oneRepMax!
case .Baechle:
oneRepMax = weightLifted * ( 1 + ( 0.033 * repetitions ) )
return oneRepMax!
case .Lander:
oneRepMax = 100 * weightLifted / (101.3 - (2.67123 * repetitions))
return oneRepMax!
case .Lombardi:
//oneRepMax = weightLifted * Double((Int(repetitions) ^^ Int(0.10)))
//return oneRepMax! //formula doesn't work
return 1
case .MayhewEtAl:
oneRepMax = 100 * weightLifted / (101.3 - (2.67123 * repetitions))
return oneRepMax!
case .OConnerEtAl:
oneRepMax = weightLifted * (1 + 0.025 * repetitions)
return oneRepMax!
default:
return 1
}
}
}
Notice the raw value type of the enum is Int. I've chosen to do that because a) I need to use it to populate the table view below where the users can select one of them as the user default and I could only get the override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
to work as an Int and b) I also was only able to get the loop in the refresh()
function to work if I made it an Int. This function is called when the user selects a formula and it places a checkmark on that selected formula. The selected formula is then set as the new default value and will be included in the lift log if the user chooses to save a lift in the lift log (this is done in another view).
Here's the table view controller where I use the enum as just described:
import UIKit
class FormulasTableViewController: UITableViewController {
func refresh() {
for index in 0 ... CalculationFormula.TotalFormulas.rawValue {
let indexPath = NSIndexPath(forItem: index, inSection: 0)
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = calculator.preferredFormula.rawValue == index ? .Checkmark : .None
print(cell.accessoryType.rawValue)
}
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
guard let theFormula = CalculationFormula(rawValue: indexPath.row) else {
return
}
calculator.preferredFormula = theFormula
let newPreferredFormula = calculator.preferredFormula
savePreferences(newPreferredFormula)
refresh()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
refresh()
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return formulas.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("formulasCell", forIndexPath: indexPath)
let currentFormula = formulas[indexPath.row]
cell.textLabel?.text = currentFormula
return cell
}
func savePreferences(formula: CalculationFormula) {
let userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setObject(formula.formulaName, forKey: "preferredFormula")
}
var currentFormula: String {
get {
let userDefaults = NSUserDefaults.standardUserDefaults()
if let returnValue = userDefaults.objectForKey("preferredFormula") as? String {
return returnValue
} else {
return "Epley"
}
}
set {
NSUserDefaults.standardUserDefaults().setObject(newValue, forKey: "preferredFormula")
NSUserDefaults.standardUserDefaults().synchronize()
}
}
}