313 lines
11 KiB
Ruby
313 lines
11 KiB
Ruby
=begin
|
|
|
|
require 'spec_helper'
|
|
|
|
describe LessonSessionAnalyser do
|
|
|
|
let(:user) { FactoryGirl.create(:user, remaining_test_drives: 1) }
|
|
let(:teacher) { FactoryGirl.create(:teacher_user) }
|
|
let(:start) { Time.now }
|
|
let(:lesson_booking_slot_single1) { FactoryGirl.build(:lesson_booking_slot_single) }
|
|
let(:lesson_booking_slot_single2) { FactoryGirl.build(:lesson_booking_slot_single) }
|
|
let(:lesson_booking_slot_recurring1) { FactoryGirl.build(:lesson_booking_slot_recurring) }
|
|
let(:lesson_booking_slot_recurring2) { FactoryGirl.build(:lesson_booking_slot_recurring) }
|
|
let(:valid_single_slots) { [lesson_booking_slot_single1, lesson_booking_slot_single2] }
|
|
let(:valid_recurring_slots) { [lesson_booking_slot_recurring1, lesson_booking_slot_recurring2] }
|
|
|
|
describe "analyse" do
|
|
|
|
after{
|
|
Timecop.return
|
|
}
|
|
it "neither show" do
|
|
lesson = testdrive_lesson(user, teacher)
|
|
music_session = lesson.music_session
|
|
|
|
Timecop.freeze((lesson.music_session.scheduled_start + lesson.duration * 60) + 1)
|
|
|
|
analysis = LessonSessionAnalyser.analyse(lesson)
|
|
analysis[:reason].should eql LessonSessionAnalyser::TEACHER_FAULT
|
|
analysis[:student].should eql nil
|
|
analysis[:bill].should be false
|
|
|
|
student = analysis[:student_analysis]
|
|
student[:joined_on_time].should be false
|
|
student[:joined_late].should be false
|
|
student[:waited_correctly].should be false
|
|
student[:initial_waiting_pct].should eql nil
|
|
student[:potential_waiting_time].should eql nil
|
|
|
|
together = analysis[:together_analysis]
|
|
together[:session_time].should eql 0
|
|
end
|
|
|
|
it "teacher joined on time, waited, student no show" do
|
|
lesson = testdrive_lesson(user, teacher)
|
|
music_session = lesson.music_session
|
|
|
|
# create some bogus, super-perfect teacher/student times
|
|
start = lesson.scheduled_start
|
|
end_time = lesson.scheduled_start + (60 * lesson.duration)
|
|
uh2 = FactoryGirl.create(:music_session_user_history, user: teacher, history: music_session, created_at: start, session_removed_at: end_time)
|
|
Timecop.travel(end_time + 1)
|
|
|
|
|
|
analysis = LessonSessionAnalyser.analyse(lesson)
|
|
analysis[:reason].should eql LessonSessionAnalyser::STUDENT_FAULT
|
|
analysis[:student].should eql LessonSessionAnalyser::NO_SHOW
|
|
analysis[:bill].should be true
|
|
|
|
student = analysis[:student_analysis]
|
|
student[:joined_on_time].should be false
|
|
student[:joined_late].should be false
|
|
student[:waited_correctly].should be false
|
|
student[:initial_waiting_pct].should eql nil
|
|
student[:potential_waiting_time].should eql nil
|
|
|
|
together = analysis[:together_analysis]
|
|
together[:session_time].should eql 0
|
|
end
|
|
|
|
it "student joined 1 min before start time, is waiting for 12 minutes" do
|
|
lesson = testdrive_lesson(user, teacher)
|
|
music_session = lesson.music_session
|
|
|
|
# create some bogus, super-perfect teacher/student times
|
|
start = lesson.scheduled_start
|
|
end_time = lesson.scheduled_start + (60 * lesson.duration)
|
|
uh2 = FactoryGirl.create(:music_session_user_history, user: user, history: music_session, created_at: start - 60, session_removed_at: nil)
|
|
|
|
Timecop.freeze(start + 11 * 60)
|
|
|
|
analysis = LessonSessionAnalyser.analyse(lesson, true)
|
|
analysis[:reason].should eql LessonSessionAnalyser::TEACHER_FAULT
|
|
analysis[:teacher].should eql LessonSessionAnalyser::NO_SHOW
|
|
analysis[:student].should be_nil
|
|
analysis[:bill].should be false
|
|
|
|
student = analysis[:student_analysis]
|
|
student[:joined_on_time].should be true
|
|
student[:joined_late].should be false
|
|
student[:waited_correctly].should be true
|
|
student[:initial_waiting_pct].should eql 1.0
|
|
student[:potential_waiting_time].should eql 600.0
|
|
|
|
student[:session_time].should eql (11 * 60).to_f
|
|
|
|
together = analysis[:together_analysis]
|
|
together[:session_time].should eql 0
|
|
end
|
|
|
|
it "teacher joined on time, waited, student joined late" do
|
|
lesson = testdrive_lesson(user, teacher)
|
|
music_session = lesson.music_session
|
|
|
|
# create some bogus, super-perfect teacher/student times
|
|
start = lesson.scheduled_start
|
|
end_time = lesson.scheduled_start + (60 * lesson.duration)
|
|
late_start = start + (7 * 60)
|
|
uh1 = FactoryGirl.create(:music_session_user_history, user: user, history: music_session, created_at: late_start, session_removed_at: late_start + 4 * 60)
|
|
uh2 = FactoryGirl.create(:music_session_user_history, user: teacher, history: music_session, created_at: start, session_removed_at: end_time)
|
|
|
|
Timecop.travel(end_time + 1)
|
|
|
|
|
|
analysis = LessonSessionAnalyser.analyse(lesson)
|
|
analysis[:reason].should eql LessonSessionAnalyser::STUDENT_FAULT
|
|
analysis[:student].should eql LessonSessionAnalyser::JOINED_LATE
|
|
analysis[:bill].should be true
|
|
|
|
student = analysis[:student_analysis]
|
|
student[:joined_on_time].should be false
|
|
student[:joined_late].should be true
|
|
student[:waited_correctly].should be false
|
|
student[:initial_waiting_pct].should eql nil
|
|
student[:potential_waiting_time].should eql nil
|
|
|
|
together = analysis[:together_analysis]
|
|
together[:session_time].should eql (4 * 60.to_f)
|
|
end
|
|
|
|
it "together 5 minutes" do
|
|
|
|
lesson = testdrive_lesson(user, teacher)
|
|
music_session = lesson.music_session
|
|
|
|
analysis = LessonSessionAnalyser.analyse(lesson)
|
|
analysis[:reason].should eql LessonSessionAnalyser::SESSION_ONGOING
|
|
|
|
|
|
# create some bogus, super-perfect teacher/student times
|
|
start = lesson.scheduled_start
|
|
end_time = lesson.scheduled_start + (60 * lesson.duration)
|
|
uh1 = FactoryGirl.create(:music_session_user_history, user: user, history: music_session, created_at: start, session_removed_at: end_time)
|
|
uh2 = FactoryGirl.create(:music_session_user_history, user: teacher, history: music_session, created_at: start, session_removed_at: end_time)
|
|
|
|
|
|
analysis = LessonSessionAnalyser.analyse(lesson)
|
|
analysis[:reason].should eql LessonSessionAnalyser::SESSION_ONGOING
|
|
|
|
Timecop.travel(end_time + 1)
|
|
|
|
analysis = LessonSessionAnalyser.analyse(lesson)
|
|
analysis[:reason].should eql LessonSessionAnalyser::SUCCESS
|
|
analysis[:bill].should be true
|
|
|
|
teacher = analysis[:teacher_analysis]
|
|
teacher[:joined_on_time].should be true
|
|
teacher[:waited_correctly].should be true
|
|
teacher[:initial_waiting_pct].should eql 1.0
|
|
teacher[:potential_waiting_time].should eql 600.0
|
|
|
|
together = analysis[:together_analysis]
|
|
together[:session_time].should eql 1800.0
|
|
end
|
|
end
|
|
|
|
describe "intersecting_ranges" do
|
|
|
|
let(:lesson) { testdrive_lesson(user, teacher) }
|
|
let(:music_session) { lesson.music_session }
|
|
|
|
it "empty" do
|
|
LessonSessionAnalyser.intersecting_ranges([], []).should eql []
|
|
end
|
|
|
|
it "one specified, other empty" do
|
|
|
|
uh1Begin = start
|
|
uh1End = start + 1
|
|
|
|
LessonSessionAnalyser.intersecting_ranges([], [Range.new(uh1Begin, uh1End)]).should eql []
|
|
LessonSessionAnalyser.intersecting_ranges([Range.new(uh1Begin, uh1End)], []).should eql []
|
|
end
|
|
|
|
it "both identical" do
|
|
uh1Begin = start
|
|
uh1End = start + 1
|
|
|
|
LessonSessionAnalyser.intersecting_ranges([Range.new(uh1Begin, uh1End)], [Range.new(uh1Begin, uh1End)]).should eql [Range.new(uh1Begin, uh1End)]
|
|
end
|
|
|
|
it "one intersect" do
|
|
uh1Begin = start
|
|
uh1End = start + 4
|
|
|
|
uh2Begin = start + 1
|
|
uh2End = start + 3
|
|
|
|
LessonSessionAnalyser.intersecting_ranges([Range.new(uh1Begin, uh1End)], [Range.new(uh2Begin, uh2End)]).should eql [Range.new(uh2Begin, uh2End)]
|
|
end
|
|
|
|
it "overlapping intersect" do
|
|
uh1Begin = start
|
|
uh1End = start + 4
|
|
|
|
uh2Begin = start + -1
|
|
uh2End = start + 2
|
|
|
|
uh3Begin = start + 3
|
|
uh3End = start + 5
|
|
|
|
LessonSessionAnalyser.intersecting_ranges([Range.new(uh2Begin, uh2End), Range.new(uh3Begin, uh3End)], [Range.new(uh1Begin, uh1End)]).should eql [Range.new(uh1Begin, uh2End), Range.new(uh3Begin, uh1End)]
|
|
end
|
|
|
|
it "no overlap" do
|
|
uh1Begin = start
|
|
uh1End = start + 4
|
|
|
|
uh2Begin = start + 5
|
|
uh2End = start + 6
|
|
|
|
LessonSessionAnalyser.intersecting_ranges([Range.new(uh1Begin, uh1End)], [Range.new(uh2Begin, uh2End)]).should eql []
|
|
end
|
|
end
|
|
|
|
describe "merge_overlapping_ranges" do
|
|
|
|
let(:lesson) { testdrive_lesson(user, teacher) }
|
|
let(:music_session) { lesson.music_session }
|
|
|
|
|
|
it "empty" do
|
|
LessonSessionAnalyser.merge_overlapping_ranges([]).should eql []
|
|
end
|
|
|
|
it "one item" do
|
|
uh1Begin = start
|
|
uh1End = start + 1
|
|
|
|
uh1 = FactoryGirl.build(:music_session_user_history, user: user, history: music_session, created_at: uh1Begin, session_removed_at: uh1End)
|
|
|
|
ranges = LessonSessionAnalyser.time_ranges [uh1]
|
|
|
|
LessonSessionAnalyser.merge_overlapping_ranges(ranges).should eql [Range.new(uh1Begin, uh1End)]
|
|
end
|
|
|
|
it "two identical items" do
|
|
uh1Begin = start
|
|
uh1End = start + 1
|
|
|
|
uh2Begin = uh1Begin
|
|
uh2End = uh1End
|
|
|
|
uh1 = FactoryGirl.build(:music_session_user_history, user: user, history: music_session, created_at: uh1Begin, session_removed_at: uh1End)
|
|
uh2 = FactoryGirl.build(:music_session_user_history, user: user, history: music_session, created_at: uh2Begin, session_removed_at: uh2End)
|
|
|
|
ranges = LessonSessionAnalyser.time_ranges [uh1, uh2]
|
|
|
|
LessonSessionAnalyser.merge_overlapping_ranges(ranges).should eql [Range.new(uh1Begin, uh1End)]
|
|
end
|
|
|
|
it "two separate times" do
|
|
uh1Begin = start
|
|
uh1End = start + 1
|
|
|
|
uh2Begin = start + 3
|
|
uh2End = start + 5
|
|
|
|
uh1 = FactoryGirl.build(:music_session_user_history, user: user, history: music_session, created_at: uh1Begin, session_removed_at: uh1End)
|
|
uh2 = FactoryGirl.build(:music_session_user_history, user: user, history: music_session, created_at: uh2Begin, session_removed_at: uh2End)
|
|
|
|
ranges = LessonSessionAnalyser.time_ranges [uh1, uh2]
|
|
|
|
LessonSessionAnalyser.merge_overlapping_ranges(ranges).should eql [Range.new(uh1Begin, uh1End), Range.new(uh2Begin, uh2End)]
|
|
end
|
|
|
|
it "two overlapping times" do
|
|
uh1Begin = start
|
|
uh1End = start + 1
|
|
|
|
uh2Begin = start + 0.5
|
|
uh2End = start + 5
|
|
|
|
uh1 = FactoryGirl.build(:music_session_user_history, user: user, history: music_session, created_at: uh1Begin, session_removed_at: uh1End)
|
|
uh2 = FactoryGirl.build(:music_session_user_history, user: user, history: music_session, created_at: uh2Begin, session_removed_at: uh2End)
|
|
|
|
ranges = LessonSessionAnalyser.time_ranges [uh1, uh2]
|
|
|
|
LessonSessionAnalyser.merge_overlapping_ranges(ranges).should eql [Range.new(uh1Begin, uh2End)]
|
|
end
|
|
|
|
it "three overlapping times" do
|
|
uh1Begin = start
|
|
uh1End = start + 1
|
|
|
|
uh2Begin = start + 0.5
|
|
uh2End = start + 5
|
|
|
|
uh3Begin = start + 0.1
|
|
uh3End = start + 6
|
|
|
|
uh1 = FactoryGirl.build(:music_session_user_history, user: user, history: music_session, created_at: uh1Begin, session_removed_at: uh1End)
|
|
uh2 = FactoryGirl.build(:music_session_user_history, user: user, history: music_session, created_at: uh2Begin, session_removed_at: uh2End)
|
|
uh3 = FactoryGirl.build(:music_session_user_history, user: user, history: music_session, created_at: uh3Begin, session_removed_at: uh3End)
|
|
|
|
ranges = LessonSessionAnalyser.time_ranges [uh1, uh2, uh3]
|
|
|
|
LessonSessionAnalyser.merge_overlapping_ranges(ranges).should eql [Range.new(uh1Begin, uh3End)]
|
|
end
|
|
end
|
|
end
|
|
|
|
=end |