diff --git a/ruby/lib/jam_ruby/connection_manager.rb b/ruby/lib/jam_ruby/connection_manager.rb index 64b84ddbb..92d960b22 100644 --- a/ruby/lib/jam_ruby/connection_manager.rb +++ b/ruby/lib/jam_ruby/connection_manager.rb @@ -419,7 +419,7 @@ SQL end connection.join_the_session(music_session, as_musician, tracks, user, audio_latency, video_sources) - JamRuby::MusicSessionUserHistory.join_music_session(user.id, music_session.id) + JamRuby::MusicSessionUserHistory.join_music_session(user.id, music_session.id, client_id) # connection.music_session_id = music_session.id # connection.as_musician = as_musician # connection.joining_session = true diff --git a/ruby/lib/jam_ruby/models/lesson_session.rb b/ruby/lib/jam_ruby/models/lesson_session.rb index 113b608da..cd35d803d 100644 --- a/ruby/lib/jam_ruby/models/lesson_session.rb +++ b/ruby/lib/jam_ruby/models/lesson_session.rb @@ -447,6 +447,10 @@ module JamRuby music_session.creator end + def student_id + music_session.creator.id + end + def self.index(user, params = {}) limit = params[:per_page] limit ||= 100 diff --git a/ruby/lib/jam_ruby/models/lesson_session_analyser.rb b/ruby/lib/jam_ruby/models/lesson_session_analyser.rb index d217ae4c4..74f23b5f3 100644 --- a/ruby/lib/jam_ruby/models/lesson_session_analyser.rb +++ b/ruby/lib/jam_ruby/models/lesson_session_analyser.rb @@ -69,7 +69,7 @@ module JamRuby # spec: https://jamkazam.atlassian.net/wiki/display/PS/Product+Specification+-+JamClass#ProductSpecification-JamClass-TeacherReceives&RespondstoLessonBookingRequest - if !force && (music_session.session_removed_at.nil? && !((music_session.scheduled_start + (lesson_session.duration * 60)) < Time.now)) + if !force && (!((music_session.scheduled_start + (lesson_session.duration * 60)) < Time.now)) reason = SESSION_ONGOING bill = false else @@ -98,8 +98,17 @@ module JamRuby student = JOINED_LATE bill = true end + else + if teacher_analysis[:no_show] + teacher = NO_SHOW + elsif !teacher_analysis[:joined_on_time] + teacher = JOINED_LATE + elsif !teacher_analysis[:waited_correctly] + teacher = MINIMUM_TIME_NOT_MET + end end + end if reason.nil? diff --git a/ruby/lib/jam_ruby/models/music_session_user_history.rb b/ruby/lib/jam_ruby/models/music_session_user_history.rb index 07daa6215..c9b042d8b 100644 --- a/ruby/lib/jam_ruby/models/music_session_user_history.rb +++ b/ruby/lib/jam_ruby/models/music_session_user_history.rb @@ -40,9 +40,9 @@ module JamRuby end def self.save(music_session_id, user_id, client_id, tracks) - return true if 0 < self.where(:music_session_id => music_session_id, - :user_id => user_id, - :client_id => client_id).count + return true if 0 < self.where(:music_session_id => music_session_id, + :user_id => user_id, + :client_id => client_id).where('session_removed_at is NULL').count session_user_history = MusicSessionUserHistory.new session_user_history.music_session_id = music_session_id session_user_history.user_id = user_id @@ -60,10 +60,12 @@ module JamRuby (end_time - self.created_at) / 60.0 end - def self.join_music_session(user_id, session_id) + def self.join_music_session(user_id, session_id, client_id) hist = self .where(:user_id => user_id) .where(:music_session_id => session_id) + .where(:client_id => client_id) + .where('session_removed_at IS NULL') .limit(1) .first hist.start_history if hist diff --git a/ruby/spec/jam_ruby/models/lesson_session_analyser_spec.rb b/ruby/spec/jam_ruby/models/lesson_session_analyser_spec.rb index 8478a0500..29fe366a1 100644 --- a/ruby/spec/jam_ruby/models/lesson_session_analyser_spec.rb +++ b/ruby/spec/jam_ruby/models/lesson_session_analyser_spec.rb @@ -24,7 +24,7 @@ describe LessonSessionAnalyser do Timecop.freeze((lesson.music_session.scheduled_start + lesson.duration * 60) + 1) analysis = LessonSessionAnalyser.analyse(lesson) - analysis[:reason].should eql LessonSessionAnalyser::NEITHER_SHOW + analysis[:reason].should eql LessonSessionAnalyser::TEACHER_FAULT analysis[:student].should eql nil analysis[:bill].should be false @@ -47,8 +47,7 @@ describe LessonSessionAnalyser do 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) - lesson.music_session.session_removed_at = end_time - lesson.music_session.save! + Timecop.travel(end_time + 1) analysis = LessonSessionAnalyser.analyse(lesson) @@ -67,6 +66,36 @@ describe LessonSessionAnalyser do 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 @@ -78,8 +107,7 @@ describe LessonSessionAnalyser do 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) - lesson.music_session.session_removed_at = end_time - lesson.music_session.save! + Timecop.travel(end_time + 1) analysis = LessonSessionAnalyser.analyse(lesson) @@ -117,8 +145,7 @@ describe LessonSessionAnalyser do analysis = LessonSessionAnalyser.analyse(lesson) analysis[:reason].should eql LessonSessionAnalyser::SESSION_ONGOING - lesson.music_session.session_removed_at = end_time - lesson.music_session.save! + Timecop.travel(end_time + 1) analysis = LessonSessionAnalyser.analyse(lesson) analysis[:reason].should eql LessonSessionAnalyser::SUCCESS diff --git a/web/app/assets/javascripts/layout.js b/web/app/assets/javascripts/layout.js index 6592fcdb7..50d9a2fe6 100644 --- a/web/app/assets/javascripts/layout.js +++ b/web/app/assets/javascripts/layout.js @@ -237,7 +237,7 @@ }, opts.animationDuration); }); - var broadcastWidth = findCardLayout.width + feedCardLayout.width; + var broadcastWidth = findCardLayout.width + feedCardLayout.width; //+ opts.gridPadding * 2; layoutBroadcast(broadcastWidth, findCardLayout.left); } diff --git a/web/app/assets/javascripts/react-components/InLessonBroadcast.js.jsx.coffee b/web/app/assets/javascripts/react-components/InLessonBroadcast.js.jsx.coffee index 9afff73ef..1073f830b 100644 --- a/web/app/assets/javascripts/react-components/InLessonBroadcast.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/InLessonBroadcast.js.jsx.coffee @@ -3,16 +3,38 @@ context = window @InLessonBroadcast = React.createClass({ displayName: 'In Lesson Broadcast' - displayTime: (minuteOffset = 0) -> - untilTime = @props.lessonSession.until + getTimeRemaining: (t) -> + if t < 0 + t = -t + + seconds = Math.floor( (t/1000) % 60 ); + minutes = Math.floor( (t/1000/60) % 60 ); + hours = Math.floor( (t/(1000*60*60)) % 24 ); + days = Math.floor( t/(1000*60*60*24) ); + + return { + 'total': t, + 'days': days, + 'hours': hours, + 'minutes': minutes, + 'seconds': seconds + }; + + + displayTime: () -> + if @props.lessonSession.initialWindow + # offset time by 10 minutes to get the 'you need to wait message' in + untilTime = @getTimeRemaining(@props.lessonSession.until.total + (10 * 60 * 1000)) + else + untilTime = @props.lessonSession.until timeString = '' if untilTime.days != 0 timeString += "#{untilTime.days} days, " if untilTime.hours != 0 || timeString.length > 0 timeString += "#{untilTime.hours} hours, " if untilTime.minutes != 0 || timeString.length > 0 - timeString += "#{untilTime.minutes + minuteOffset} minutes, " + timeString += "#{untilTime.minutes} minutes, " if untilTime.seconds != 0 || timeString.length > 0 timeString += "#{untilTime.seconds} seconds" @@ -39,14 +61,14 @@ context = window else if @props.lessonSession.initialWindow content = `
You need to wait in this session for
-{this.displayTime(10)}
+{this.displayTime()}
to allow time for your teacher to join you. If you leave before this timer reaches zero, and your teacher joins this session, you will be marked absent and charged for the lesson.
You may now leave the session. However, if you choose to stay in the session with the teacher, after 5 minutes together the session will be considered a success, and you will be billed.
-If the two of you do not spend at least 5 minutes together in the session, your teacher will be marked absent and penalized for missing the lesson. You will not be charged for this lesson.
+Because your teacher was late, you may now leave the session. However, if you choose to stay in the session with the teacher, after 5 minutes together the session will be considered a success, and you will be billed.
+If the two of you do not spend at least 5 minutes together in the session, your teacher will be marked absent and penalized for missing the lesson, and you will not be charged for this lesson.