1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
require 'optparse'
module KnapsackSolver
# This class checks command line arguments provided to the knapsack_solver
# binary.
class CliOptionChecker
# Checks command-line options, their arguments and positional arguments
# provided to the CLI.
#
# @param opts [Hash] parsed command-line options
# @param args [Array<String>] command-line positional arguments
def self.check(opts, args)
if !opts[:branch_and_bound] && !opts[:dynamic_programming] &&
!opts[:fptas] && !opts[:heuristic]
raise StandardError, 'At least one method of solving must be requested'
end
check_fptas_options(opts)
check_directories(opts)
check_positional_arguments(args)
end
# Checks command-line options and arguments used by FPTAS solving method.
#
# @param opts [Hash] parsed command-line options
def self.check_fptas_options(opts)
return if !opts[:fptas] && !opts.key?(:fptas_epsilon)
check_incomplete_fptas_options(opts)
eps = opts[:fptas_epsilon].to_f
return unless eps <= 0 || eps >= 1 || eps.to_s != opts[:fptas_epsilon]
raise StandardError,
'FPTAS epsilon must be number from range (0,1)'
end
# Checks command-line options and arguments used by FPTAS solving
# method. Recignizes cases when mandatory FPTAS epsilon constant is
# missing or when it the constant is provided and FPTAS method is not
# requested.
#
# @param opts [Hash] parsed command-line options
def self.check_incomplete_fptas_options(opts)
raise StandardError, 'Missing FPTAS epsilon constant' if opts[:fptas] && !opts.key?(:fptas_epsilon)
return unless !opts[:fptas] && opts.key?(:fptas_epsilon)
raise StandardError,
'epsilon constant must not be provided when FPTAS is not selected'
end
# Checks directory for result and statistic output logs, and directory for
# graph files.
#
# @param opts [Hash] parsed command-line options
def self.check_directories(opts)
check_output_directory(opts[:output_dir]) if opts[:output_dir]
check_output_directory(opts[:graphs_dir]) if opts[:graphs_dir]
end
# Checks if at least one dataset input file was provided and if the input
# files are readable.
#
# @param args [Array<String>] positional arguments provided to the CLI
def self.check_positional_arguments(args)
raise StandardError, 'Missing datset file(s)' if args.empty?
args.each { |f| check_input_file(f) }
end
# Checks if an output directory exist and is writable.
#
# @param path [Path] path to output directory
def self.check_output_directory(path)
raise StandardError, "Directory '#{path}' does not exists" unless File.exist?(path)
raise StandardError, "'#{path}' is not a directory" unless File.directory?(path)
raise StandardError, "Directory '#{path}' is not writable" unless File.writable?(path)
end
# Checks if an input file exist and is readable.
#
# @param path [Path] path to input regular file
def self.check_input_file(path)
raise StandardError, "File '#{path}' does not exists" unless File.exist?(path)
raise StandardError, "'#{path}' is not a regular file" unless File.file?(path)
raise StandardError, "File '#{path}' is not readable" unless File.readable?(path)
end
end
end
|