# frozen_string_literal: true module ThinkFeelDoEngine module Reports # Scenario: a Participant plays a video. class VideoSession def self.columns %w( participant_id video_title video_started_at video_stopped_at stopping_action ) end def self.all Participant.not_moderator.select(:id, :study_id).map do |participant| video_play_events(participant.id).map do |e| m = e.current_url.match(%r{.*\/providers\/(\d+)\/(\d+)$}) provider_id = m ? m[1] : -1 position = m ? m[2] : -1 video = BitCore::ContentProvider .find_by(id: provider_id) .try(:source_content) .try(:slides) .try(:find_by_position, position) next_e = next_event(e) { participant_id: participant.study_id, video_title: video.try(:title), video_started_at: e.emitted_at.iso8601, video_stopped_at: next_e.try(:emitted_at).try(:iso8601), stopping_action: next_e.try(:kind) } end end.flatten end def self.video_play_events(participant_id) EventCapture::Event .where(participant_id: participant_id, kind: "videoPlay") .select(:participant_id, :kind, :emitted_at, :payload) .order(:emitted_at) end # Return the immediately following Event for the Participant that is not a # video play event, or nil if none exist. def self.next_event(event) event = EventCapture::Event.next_event_for(event) return if event.nil? return event if event && event.kind != "videoPause" # if the event is a pause and there's an immediately following finish, # return the finish event finish_event = EventCapture::Event .where(participant_id: event.participant_id) .where("emitted_at > ? AND emitted_at < ?", event.emitted_at, event.emitted_at + 2.seconds) .order(:emitted_at) .limit(1) .first finish_event.try(:kind) == "videoFinish" ? finish_event : event end end end end