class MatchesPresenter def initialize(video, video_analysis, audio_analysis, edl_events, graphics_edl_events) @video = video @video_analysis = video_analysis @audio_analysis = audio_analysis @edl_events = edl_events @graphics_edl_events = graphics_edl_events end def build_chronological_matches if video.analysis_success? sort_matches(first_appearances_with_images) else [] end end def build_chronological_audio_matches if video.audio_analysis_success? sort_matches(audio_matches) else [] end end def build_graphics_matches if video.analysis_success? confirmed_graphics = video.graphics_elements sort_matches( graphics_edl_events. reject { |edl_event| edl_event.source_file_name.blank? }. map do |edl_event| GraphicsMatch.new( edl_event.source_file_name, edl_event.start_time, already_confirmed?(confirmed_graphics, edl_event), edl_event.timecode_in ) end. compact ) else [] end end def all_tracks_edl_events edl_events end private def audio_events if ENV["DISABLE_EDL_CHANNEL_FILTER"] edl_events else edl_events.find_all { |event| event.channel.include? "A" } end end def video_events if ENV["DISABLE_EDL_CHANNEL_FILTER"] edl_events else edl_events.find_all { |event| event.channel == "V" } end end def already_confirmed?(confirmation, edl_event) confirmation.any? { |confirmed| confirmed.source_file_name == edl_event.source_file_name && confirmed.timecode_in == edl_event.timecode_in } end attr_reader :video, :video_analysis, :audio_analysis, :edl_events, :graphics_edl_events def sort_matches(matches) matches. sort_by(&:start_time). reverse end def first_appearances_with_images video_analysis.first_appearances. reject { |appearance| appearance.external_image_id.blank? }. map { |appearance| SuggestedMatch.build_from_first_appearance(appearance, appearance.start_time) } end def audio_matches audio_analysis.results.map do |result| # If it's a library match, use the provided composer and publisher info # If it's an original music match, use the composer and publisher info we have # If it's an acquired media match, don't provide any composer and publisher info if result.type == "acquired_media" composers = "" publishers = "" elsif result.type == "original_music" file_info = FileInfo.find(result.uid) composers = file_info.releasable.composers.map { |composer| "#{composer.name}, #{composer.affiliation}, #{composer.percentage}%" }.join("|") publishers = file_info.releasable.publishers.map { |publisher| "#{publisher.name}, #{publisher.affiliation}, #{publisher.percentage}%" }.join("|") else composers = result.audio_data.composers.map { |composer| "#{composer.name}, #{composer.affiliation}, #{composer.percentage}" }.join("|") publishers = result.audio_data.publishers.map { |publisher| "#{publisher.name}, #{publisher.affiliation}, #{publisher.percentage}" }.join("|") end result.edl.map do |edl_event| is_confirmed = video.audio_confirmations.any? do |confirmation| # TODO: Use EDL ID in the future to determine this confirmation.source_file_name == result.requested_filename && confirmation.timecode_in == edl_event.timecode_in end result_type = result.type == "library" ? "library_music" : result.type AudioSuggestedMatch.new( AudioData.new( result.audio_data.filename, result.requested_filename, composers, publishers, result.audio_data.catalog, result.audio_data.title, ), edl_event.start_time.to_i, is_confirmed, edl_event.timecode_in, result_type, video.audio_only_edl_file.attached? ) end end.flatten end class GraphicsMatch attr_reader :appears_at_timecode, :start_time, :filename, :confirmed, :timecode_in def initialize(filename, start_time, confirmed, timecode_in) @filename = filename @start_time = start_time @appears_at_timecode = Timecode.from_seconds(start_time.to_f / 1000) @confirmed = confirmed @timecode_in = timecode_in end def elapsed_time_until_appearance appears_at_timecode.to_seconds end end class AudioSuggestedMatch attr_reader :appears_at_timecode, :start_time, :confirmed, :timecode_in, :confirmation_type, :edl_type def initialize(audio_data, start_time, confirmed, timecode_in, confirmation_type, audio_edl_attached) @audio_data = audio_data @start_time = start_time @confirmed = confirmed @appears_at_timecode = Timecode.from_seconds(start_time.to_f / 1000) @timecode_in = timecode_in @confirmation_type = confirmation_type @edl_type = audio_edl_attached ? "audio" : "all_tracks" end def presented_filename if confirmation_type == "original_music" "(O) #{audio_data.requested_filename}" else "(L) #{audio_data.requested_filename}" end end def filename audio_data.requested_filename end def composer_info audio_data.composer end def publisher_info audio_data.publisher end def catalog audio_data.catalog end def title audio_data.title end def elapsed_time_until_appearance appears_at_timecode.to_seconds end private attr_reader :audio_data end class FileInfoSuggestedMatch < SimpleDelegator attr_reader :appears_at_timecode, :start_time, :file_info, :timecode_in def self.build(file_info, start_time, timecode_in) release = file_info.releasable new(release, file_info, start_time, timecode_in) end def initialize(release, file_info, start_time, timecode_in) super(release) @file_info = file_info @start_time = start_time @appears_at_timecode = Timecode.from_seconds(start_time.to_f / 1000) @timecode_in = timecode_in end def elapsed_time_until_appearance appears_at_timecode.to_seconds end end class SuggestedMatch < SimpleDelegator attr_reader :appears_at_timecode, :start_time def self.build_from_first_appearance(appearance, start_time) release = ExternalImage.new(appearance.external_image_id).release new(release, start_time) end def initialize(release, start_time) super(release) @start_time = start_time @appears_at_timecode = Timecode.from_seconds(start_time.to_f / 1000) end def elapsed_time_until_appearance appears_at_timecode.to_seconds end end class ExternalImage attr_reader :uid def initialize(uid) @uid = uid end def release release_klass.find(id) end private def id uid.match(/.*_release_(?\d*)/) Regexp.last_match(:id) || uid end def release_klass release_name.classify.constantize end def release_name uid.match(/(?\w*_release)_\d/) Regexp.last_match(:type) || "appearance_release" end end end