Initial commit
This commit is contained in:
270
app/presenters/matches_presenter.rb
Normal file
270
app/presenters/matches_presenter.rb
Normal file
@@ -0,0 +1,270 @@
|
||||
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_(?<id>\d*)/)
|
||||
Regexp.last_match(:id) || uid
|
||||
end
|
||||
|
||||
def release_klass
|
||||
release_name.classify.constantize
|
||||
end
|
||||
|
||||
def release_name
|
||||
uid.match(/(?<type>\w*_release)_\d/)
|
||||
Regexp.last_match(:type) || "appearance_release"
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user