I've finally got a solution for a "weekly streak" bucketing system I've been working on but unfortunately it's resulted in a very large switch statement.
I'm running through a handful of dates and determining by a range of seconds (the length of a week) which bucket that date belongs to.
It's obvious to me that this could be refactored in a programmatic way because of the amount of repetition but I'm not sure where to start. Dictionary? Some kind of sorting algorithm? Recursion?
open func weeklyStreakCount(weeklyGoal target: Int) -> Int {
let endDate = Date()
let startDate = endDate.startOfWeek!
let startDateInterval = Double(startDate.timeIntervalSinceNow)
var workoutsPerWeek = [Int: Int]()
let userWorkouts: [UserWorkoutEntity] = self.userWorkouts(completed: true)
var numberOfGoodBuckets = 0
for i in 0...100 {
workoutsPerWeek.updateValue(0, forKey: i)
}
// calculate the time from now to seconds in a week and round to the nearest hundreths to create a bucket for that week
for userWorkout in userWorkouts {
let workoutTimeInterval = Double((userWorkout.completionDate?.timeIntervalSinceNow)!)
let rawBucket = (startDateInterval - workoutTimeInterval) / numberOfSecondsInAWeek
let bucket = Int(rawBucket * 1000)
let abbrNumberOfSecondsInAWeek = 604
switch bucket {
case 0 ... abbrNumberOfSecondsInAWeek:
workoutsPerWeek[0]! += 1
case abbrNumberOfSecondsInAWeek ... (abbrNumberOfSecondsInAWeek * 2):
workoutsPerWeek[1]! += 1
case abbrNumberOfSecondsInAWeek * 2 ... (abbrNumberOfSecondsInAWeek * 3):
workoutsPerWeek[2]! += 1
case abbrNumberOfSecondsInAWeek * 3 ... (abbrNumberOfSecondsInAWeek * 4):
workoutsPerWeek[3]! += 1
case abbrNumberOfSecondsInAWeek * 4 ... (abbrNumberOfSecondsInAWeek * 5):
workoutsPerWeek[4]! += 1
case abbrNumberOfSecondsInAWeek * 5 ... (abbrNumberOfSecondsInAWeek * 6):
workoutsPerWeek[5]! += 1
case abbrNumberOfSecondsInAWeek * 6 ... (abbrNumberOfSecondsInAWeek * 7):
workoutsPerWeek[6]! += 1
case abbrNumberOfSecondsInAWeek * 7 ... (abbrNumberOfSecondsInAWeek * 8):
workoutsPerWeek[7]! += 1
case abbrNumberOfSecondsInAWeek * 8 ... (abbrNumberOfSecondsInAWeek * 9):
workoutsPerWeek[8]! += 1
case abbrNumberOfSecondsInAWeek * 9 ... (abbrNumberOfSecondsInAWeek * 10):
workoutsPerWeek[9]! += 1
default:
break
}
}
// Run through each bucket and see how many times the user hit their goal
for i in 0...10 {
if(workoutsPerWeek[i]! > target) {
numberOfGoodBuckets += 1
} else {
break
}
}
return numberOfGoodBuckets
}
times
array defined? How is numberOfSecondsInAWeek calculated? – A self-contained compiling example would be helpful. \$\endgroup\$ – Martin R Jul 24 '17 at 6:53abbrNumberOfSecondsInAWeek
the value ofbucket
falls. If I'm right, then why don't you just dividebucket
byabbrNumberOfSecondsInAWeek
and truncate the result to the nearest lower integer? \$\endgroup\$ – CiaPan Jul 24 '17 at 7:39