=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