Skip to content

Instantly share code, notes, and snippets.

Created October 5, 2009 04:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/26362d5f62ecc8351a16 to your computer and use it in GitHub Desktop.
Save anonymous/26362d5f62ecc8351a16 to your computer and use it in GitHub Desktop.
=begin
Ruby Challenge
Submitted By: Sriram Varahan
Script to shift the timings of subtitle by an amount specified by the user.
The main algorithm used here is as follows:
1. The time associated with the subtitle is converted to milliseconds.
2. The shift time is also converted to milliseconds.
3. Now the two times are either added or subtracted based on the requirement and converted back to the required format.
=end
require 'optparse'
class Shift
def parse(argv)
# This hash will hold all of the options
# parsed from the command-line by
# OptionParser.
@options = {}
optparse = OptionParser.new do|opts|
# Set a banner, displayed at the top
# of the help screen.
opts.banner = "Usage: ruby-challenge.rb [options] input_file output_file"
opts.on( "-o", "--operation TYPE", 'Perform the desired operation. Valid options being add or sub' ) do |operation|
if %w[add sub].include?operation
@options[:operation] = operation
else
puts "Enter a valid operation.To know more use -h"
exit
end
end
@options[:time] = nil
opts.on( '-t', '--time TIME', 'Specify Shift time. Format is seconds,milliseconds' ) do |time|
seconds,milliseconds = time.split(",")
# Check the format of the input time entered by the user.
# The accepted format is xx,xxx
if (/^\d+$/.match(seconds).nil? || /^\d+$/.match(milliseconds).nil?)
puts "Check the input time. For Example: 12,345"
exit
end
@options[:time] = time
end
# This displays the help screen, all programs are
# assumed to have this option.
opts.on( '-h', '--help', 'Show the help menu' ) do
puts opts
exit
end
end
# Parse the command-line. Remember there are two forms
# of the parse method. The 'parse' method simply parses
# ARGV, while the 'parse!' method parses ARGV and removes
# any options found there, as well as any parameters for
# the options. What's left is the list of files to resize.
begin
optparse.parse!
rescue OptionParser::MissingArgument => e
puts e.to_str.capitalize.gsub("argument:", "value for:")
puts "That option requires a value. Please try with -h or --help to know more."
puts "Exiting.."
exit
rescue OptionParser::InvalidOption => e
puts e.to_str.capitalize.gsub("argument:", "value for:")
puts "That is an invalid option. Please try with -h or --help to know more."
puts "Exiting.."
exit
end
# Store the input and output in the options hash
%w(input output).each_with_index do |key,index|
if ARGV[index].nil?
puts "Please specify an #{key} file. To know more use -h"
exit
end
@options.store(key.to_sym,ARGV[index])
end
# Check if the input file exists or not.
# Exit if the file does not exist.
unless File.exists?(@options[:input])
puts "#{@options[:input]} file does not exist. Please check for typing or spelling errors."
exit
end
puts "Performing #{@options[:option]} operation on the input frames." if @options[:option]
# Invoke the shift method
self.perform_shift
end
##
# Perform the shift based on the operation specified.
def perform_shift
case @options[:operation]
when "add"
puts "Performing add on each of the frames"
self.open_file_and_shift("add")
when "sub"
puts "Performing sub on each of the frames"
self.open_file_and_shift("sub")
else
puts "Valid options are add or sub"
end
end
##
# Perform the required operation on each time frame.
def open_file_and_shift(operator)
input_file = @options[:input]
output_file = File.open(@options[:output],"w+")
File.open(input_file, "r") do |i_f|
while line = i_f.gets
if line =~ /-->/
start_time,end_time = line.split("-->")
start_time_seconds,start_time_milliseconds = start_time.split(",")
end_time_seconds,end_time_milliseconds = end_time.split(",")
# The time by which the shifting needs to be done
input_seconds,input_milliseconds = @options[:time].split(",")
# Convert to milliseconds.
input_milliseconds = input_milliseconds.to_i + (input_seconds.to_i * 1000)
output_file.puts "#{carry_out_operation(start_time_seconds,start_time_milliseconds,input_milliseconds,operator)} --> #{carry_out_operation(end_time_seconds,end_time_milliseconds,input_milliseconds,operator)} "
else
output_file.puts(line)
end
end
end
end
##
# Performs the actual operation.
def carry_out_operation(time,milliseconds,sub_milliseconds,operator)
time = time.split(":")
input_time = {}
input_time.store(:hr, time[0])
input_time.store(:min, time[1])
input_time.store(:sec , time[2])
# Convert the time to milliseconds.
# Perform subtraction and convert to the required output
time_in_seconds = (input_time[:hr].to_i*3600) + (input_time[:min].to_i* 60) + (input_time[:sec].to_i)
time_in_milliseconds = milliseconds.to_i + time_in_seconds.to_i * 1000
# Call the add or subtract method dynamically.
if self.respond_to?(operator)
operator = self.method(operator)
result = operator.call(time_in_milliseconds.to_i, sub_milliseconds.to_i)
end
if result > 0
# Call the method which will convert the reuired output in milliseconds to the time format required.
hours,minutes,seconds,milliseconds = convert_milliseconds_to_required_time_format(result)
else
# Return 0 is the result is a negative value.
hours,seconds,minutes,milliseconds = 00,00,00,000
end
hours,minutes,seconds,milliseconds = foramt_output_time(hours,minutes,seconds,milliseconds)
return "#{hours}:#{minutes}:#{seconds},#{milliseconds}"
end
##
# Perform addition
def add(a,b)
return a + b
end
##
# Perform subtraction.
def sub(a,b)
return a - b
end
##
# Append zeros in case of single digits.
def foramt_output_time(hours,minutes,seconds,milliseconds)
seconds = "0#{seconds}" if seconds < 10
minutes = "0#{minutes}" if minutes < 10
hours = "0#{hours}" if hours < 10
# Format the output as required.
# For example: if 9 print as 009.
if milliseconds < 10
milliseconds = "00#{milliseconds}"
elsif milliseconds < 100
milliseconds = "0#{milliseconds}"
end
return [hours,minutes,seconds,milliseconds]
end
##
# Converts time in milliseconds to hours, mins, seconds and milliseconds format.
def convert_milliseconds_to_required_time_format(input)
milliseconds = input % 1000
difference = (input - milliseconds) / 1000
seconds = difference % 60
difference = (difference - seconds) / 60
minutes = difference % 60
difference = (difference - minutes) / 60
hours = difference
return [hours,minutes,seconds,milliseconds]
end
end
# Create an object and invoke the parse method.
shift = Shift.new
shift.parse(ARGV)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment