app/models/curriculum_day.rb
# Not an ActiveRecord model
class CurriculumDay
attr_reader :date
attr_reader :raw_date
include Comparable
def initialize(date, cohort)
@raw_date = date
@date = date
@cohort = cohort
@date = @date.to_s if @date.is_a?(CurriculumDay)
if @date.is_a?(String) && @cohort && @date != 'setup'
@date = calculate_date
end
end
def to_s
return "setup" if @date == "setup"
return @to_s if @to_s
days = (@date.to_date - @cohort.start_date).to_i
w = (days / 7) + 1
@to_s = if w > 8
"w8e"
elsif @date.sunday? || @date.saturday?
"w#{w}e"
else
d = determine_d
"w#{w}d#{d}"
end
end
def <=>(other)
self.date <=> other.date
end
def unlocked?
return true if @date == 'setup'
return true if unlock_weekend_on_friday
return false unless @cohort
return false if @cohort.start_date > Date.current
if CURRICULUM_UNLOCKING == 'weekly'
self.date.cweek <= today.date.cweek || self.date.year < today.date.year
# 53rd week can roll over into the new year, preventing access from remaining days of that week.
# if Jan 1st is a thursday, it will prevent access until the week ends.
else # assume daily
self.date <= today.date
end
end
def today?
self.to_s == today.to_s
end
def info
DayInfo.where(day: self.to_s).first
end
private
def today
@today ||= CurriculumDay.new(Date.current, @cohort)
end
def friday?
!!(today.to_s =~ /[w][1-8][d][5]/)
end
def weekend?
!!(self.to_s =~ /(?<=w\d)e$/)
end
def unlock_weekend_on_friday
(friday? && weekend?) && (self.to_s[1] == today.to_s[1])
end
def determine_d
return @date.wday if DAYS_PER_WEEK == 5
# "d1" would normally be monday, right?
# Well now it could also be tuesday
# Eg Given `WEEKDAYS = [2, 4]` (tuesdays and thursdays)
# then d1 = tuesday, d2 = thursday
wday = @date.wday # 1,2,3,4 or 5 (eg: 3 for 'wednesday')
# 1 (mon) - 1,3 => 1
# 2 (tue) - 1,3 => 1
# 3 (wed) - 1,3 => 3
# 4 (thu) - 1,3 => 3
# 5 (fri) - 1,3 => 3
# 6 (sat) - 1,3 => 3
# 7 (sun) - 1,3 => 3
wday = (WEEKDAYS.reverse.detect {|d| d.to_i <= wday } || WEEKDAYS.first)
WEEKDAYS.index(wday) + 1
end
def calculate_date
date_parts = @date.match(/w(\d+)((d(\d))|e)/).to_a.compact # eg: w5d1 or w4e
# dow = day of week
week, dow = date_parts[1].to_i, date_parts.last
dow = dow == 'e' ? 6 : dow.to_i # weekend is day 6 (saturday)
# limitation: assume start date is always a monday
# for monday dow = 1 so advance by 0 (no advance) if dow = 1. Hence the -1 offset on dow
date = @cohort.start_date.monday.advance(weeks: week - 1)
if DAYS_PER_WEEK == 5
date = date.advance(days: dow - 1)
else
# dow of 2 (d2) may be Tuesday ... but could also be Thursday if we don't have 5 day weeks
# This would happen if WEEKDAYS = [2, 4]
# In the example above, d1 = Tuesday, d2 = Thursday
d = WEEKDAYS[dow - 1].to_i
date = date.advance(days: d - 1)
end
date
end
end