-
-
Save anonymous/26362d5f62ecc8351a16 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=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