usps_flags 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +22 -11
  3. data/.travis.yml +1 -1
  4. data/Gemfile.lock +5 -2
  5. data/README.md +6 -0
  6. data/lib/usps_flags.rb +35 -44
  7. data/lib/usps_flags/config.rb +89 -87
  8. data/lib/usps_flags/core.rb +44 -42
  9. data/lib/usps_flags/core/ensign.rb +53 -49
  10. data/lib/usps_flags/core/field.rb +96 -92
  11. data/lib/usps_flags/core/footer.rb +9 -5
  12. data/lib/usps_flags/core/headers.rb +58 -48
  13. data/lib/usps_flags/core/icons.rb +11 -7
  14. data/lib/usps_flags/core/icons/anchor.rb +62 -56
  15. data/lib/usps_flags/core/icons/binoculars.rb +21 -15
  16. data/lib/usps_flags/core/icons/lighthouse.rb +28 -22
  17. data/lib/usps_flags/core/icons/star.rb +21 -15
  18. data/lib/usps_flags/core/icons/trident.rb +136 -127
  19. data/lib/usps_flags/core/icons/trident_parts/hashes.rb +62 -55
  20. data/lib/usps_flags/core/icons/trumpet.rb +34 -28
  21. data/lib/usps_flags/core/pennant.rb +50 -46
  22. data/lib/usps_flags/core/trident_spec.rb +135 -131
  23. data/lib/usps_flags/core/trident_specs.rb +11 -7
  24. data/lib/usps_flags/core/trident_specs/base.rb +36 -26
  25. data/lib/usps_flags/core/trident_specs/circle.rb +36 -30
  26. data/lib/usps_flags/core/trident_specs/delta.rb +41 -30
  27. data/lib/usps_flags/core/trident_specs/header.rb +56 -50
  28. data/lib/usps_flags/core/trident_specs/horizontal.rb +80 -0
  29. data/lib/usps_flags/core/trident_specs/long.rb +41 -25
  30. data/lib/usps_flags/core/trident_specs/overlay.rb +40 -0
  31. data/lib/usps_flags/core/trident_specs/short.rb +30 -156
  32. data/lib/usps_flags/core/trident_specs/vertical.rb +108 -0
  33. data/lib/usps_flags/core/tridents.rb +54 -50
  34. data/lib/usps_flags/core/us.rb +40 -44
  35. data/lib/usps_flags/core/wheel.rb +7 -3
  36. data/lib/usps_flags/errors.rb +25 -23
  37. data/lib/usps_flags/generate.rb +111 -107
  38. data/lib/usps_flags/generate/flag.rb +160 -157
  39. data/lib/usps_flags/generate/generator_methods.rb +139 -0
  40. data/lib/usps_flags/generate/helper_methods.rb +88 -0
  41. data/lib/usps_flags/helpers.rb +163 -165
  42. data/lib/usps_flags/helpers/builders.rb +92 -85
  43. data/lib/usps_flags/helpers/spec_arrows.rb +127 -123
  44. data/lib/usps_flags/helpers/valid_flags.rb +45 -41
  45. data/lib/usps_flags/rational.rb +35 -0
  46. data/spec/usps_flags/config_spec.rb +17 -10
  47. data/spec/usps_flags/core_spec.rb +31 -31
  48. data/spec/usps_flags/generate_spec.rb +76 -73
  49. data/spec/usps_flags/helpers_spec.rb +8 -8
  50. data/spec/usps_flags/rational_spec.rb +17 -0
  51. data/spec/usps_flags_spec.rb +19 -21
  52. data/usps_flags.gemspec +7 -6
  53. metadata +34 -10
  54. data/lib/rational.rb +0 -39
  55. data/lib/usps_flags/generate/private.rb +0 -199
  56. data/spec/rational_spec.rb +0 -19
@@ -4,61 +4,57 @@
4
4
  #
5
5
  # This class should never need to be called directly.
6
6
  # @private
7
- class USPSFlags::Core::US
8
- def svg
9
- @base_hoist = 2000.to_f
10
- @base_fly = @base_hoist * 1.91
7
+ class USPSFlags
8
+ class Core
9
+ class US
10
+ def svg
11
+ @base_hoist = 2000.to_f
12
+ @base_fly = @base_hoist * 1.91
11
13
 
12
- @canton_hoist = @base_hoist * 7 / 13
13
- @canton_fly = @canton_hoist * Math.sqrt(2)
14
+ @canton_hoist = @base_hoist * 7 / 13
15
+ @canton_fly = @canton_hoist * Math.sqrt(2)
14
16
 
15
- @star_offset = 20 # Half of scaled star height
17
+ @star_offset = 20 # Half of scaled star height
16
18
 
17
- svg = defs
18
- svg << stripes
19
- svg << stars
19
+ defs + stripes + stars
20
+ end
20
21
 
21
- # star_diameter = base_hoist*4/5/13
22
- # svg << <<~SVG
23
- # <circle cx="#{@canton_fly*6/12}" cy="#{@canton_hoist*4/10-5}" r="#{star_diameter/2}" fill="#999999" fill-opacity="0.4" />
24
- # SVG
22
+ private
25
23
 
26
- svg
27
- end
24
+ def defs
25
+ File.read("#{File.dirname(__dir__)}/core/us_defs.svg.partial").gsub('STAR', USPSFlags::Core.star)
26
+ end
28
27
 
29
- private
28
+ def stars
29
+ rows = { odd: (1..9).step(2).to_a, even: (2..8).step(2).to_a }
30
+ columns = { odd: (1..11).step(2).to_a, even: (2..10).step(2).to_a }
30
31
 
31
- def defs
32
- File.read("#{File.dirname(__dir__)}/core/us_defs.svg.partial").gsub('STAR', USPSFlags::Core.star)
33
- end
32
+ svg = +''
33
+ %i[odd even].each { |type| svg << star_set(rows, columns, type) }
34
+ svg
35
+ end
34
36
 
35
- def stars
36
- rows = { odd: (1..9).step(2).to_a, even: (2..8).step(2).to_a }
37
- columns = { odd: (1..11).step(2).to_a, even: (2..10).step(2).to_a }
37
+ def star_set(rows, columns, type)
38
+ svg = +''
39
+ rows[type].each do |r|
40
+ columns[type].each do |c|
41
+ svg << <<~SVG
42
+ <g transform="translate(#{@canton_fly * c / 12}, #{@star_offset + @canton_hoist * r / 10})"><g><use href="#star" /></g></g>
43
+ SVG
44
+ end
45
+ end
46
+ svg
47
+ end
38
48
 
39
- svg = +''
40
- %i[odd even].each { |type| svg << star_set(rows, columns, type) }
41
- svg
42
- end
49
+ def stripes
50
+ s = (0..12).map do |i|
51
+ color = i.even? ? 'red' : 'white'
52
+ "<use href=\"##{color}-stripe\" y=\"#{@base_hoist * i / 13}\" />"
53
+ end
43
54
 
44
- def star_set(rows, columns, type)
45
- svg = +''
46
- rows[type].each do |r|
47
- columns[type].each do |c|
48
- svg << <<~SVG
49
- <g transform="translate(#{@canton_fly * c / 12}, #{@star_offset + @canton_hoist * r / 10})"><g><use href="#star" /></g></g>
50
- SVG
55
+ s.join("\n") + "\n<rect y=\"0\" width=\"#{@canton_fly}\" height=\"#{@canton_hoist}\" " \
56
+ "fill=\"#{USPSFlags::Config::OLD_GLORY_BLUE}\" />\n"
51
57
  end
52
58
  end
53
- svg
54
- end
55
-
56
- def stripes
57
- s = (0..12).map do |i|
58
- color = i.even? ? 'red' : 'white'
59
- "<use href=\"##{color}-stripe\" y=\"#{@base_hoist * i / 13}\" />"
60
- end
61
-
62
- s.join("\n") + "\n<rect y=\"0\" width=\"#{@canton_fly}\" height=\"#{@canton_hoist}\" fill=\"#{USPSFlags::Config::OLD_GLORY_BLUE}\" />\n"
63
59
  end
64
60
  end
@@ -4,8 +4,12 @@
4
4
  #
5
5
  # This class should never need to be called directly.
6
6
  # @private
7
- class USPSFlags::Core::Wheel
8
- def svg
9
- File.read("#{File.dirname(__dir__)}/core/wheel.svg.partial")
7
+ class USPSFlags
8
+ class Core
9
+ class Wheel
10
+ def svg
11
+ File.read("#{File.dirname(__dir__)}/core/wheel.svg.partial")
12
+ end
13
+ end
10
14
  end
11
15
  end
@@ -3,38 +3,40 @@
3
3
  # Custom errors.
4
4
  #
5
5
  # @private
6
- module USPSFlags::Errors
7
- class PNGGenerationError < StandardError
8
- attr_reader :svg
6
+ class USPSFlags
7
+ class Errors
8
+ class PNGGenerationError < StandardError
9
+ attr_reader :svg
9
10
 
10
- def initialize(msg = 'There was an error generating the PNG file.', svg: '')
11
- super(msg)
12
- @svg = svg
11
+ def initialize(msg = 'There was an error generating the PNG file.', svg: '')
12
+ super(msg)
13
+ @svg = svg
14
+ end
13
15
  end
14
- end
15
16
 
16
- class PNGConversionError < StandardError
17
- def initialize(msg = 'There was an error converting the PNG file.')
18
- super(msg)
17
+ class PNGConversionError < StandardError
18
+ def initialize(msg = 'There was an error converting the PNG file.')
19
+ super(msg)
20
+ end
19
21
  end
20
- end
21
22
 
22
- class StaticFilesGenerationError < StandardError
23
- attr_reader :cause
23
+ class StaticFilesGenerationError < StandardError
24
+ attr_reader :cause
24
25
 
25
- def initialize(msg = 'There was an error generating the static files.', cause: nil)
26
- super(msg)
27
- @cause = cause
26
+ def initialize(msg = 'There was an error generating the static files.', cause: nil)
27
+ super(msg)
28
+ @cause = cause
29
+ end
28
30
  end
29
- end
30
31
 
31
- class ZipGenerationError < StandardError
32
- attr_reader :type, :cause
32
+ class ZipGenerationError < StandardError
33
+ attr_reader :type, :cause
33
34
 
34
- def initialize(msg = 'There was an error generating the zip file.', type: nil, cause: nil)
35
- super(msg)
36
- @type = type
37
- @cause = cause
35
+ def initialize(msg = 'There was an error generating the zip file.', type: nil, cause: nil)
36
+ super(msg)
37
+ @type = type
38
+ @cause = cause
39
+ end
38
40
  end
39
41
  end
40
42
  end
@@ -1,127 +1,131 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  # Controller class for generating files.
4
- class USPSFlags::Generate
5
- require 'usps_flags/generate/private'
6
-
7
- class << self
8
- include USPSFlags::Generate::Private
9
- # The primary controller method. Generates an SVG file or SVG data.
10
- #
11
- # @param [String] flag The flag type to generate.
12
- # @param [String] outfile The path to save the SVG file to. If not set, prints to console.
13
- # @param [Boolean] field Whether to generate the flag field (including any border).
14
- # @param [String] scale The image scale divisor factor.
15
- # @return [String] Returns the SVG data.
16
- def svg(flag, outfile: nil, scale: nil, field: true)
17
- flag = flag.upcase.delete('/', '_', 'PENNANT')
18
-
19
- USPSFlags::Helpers.ensure_dir_for_file(outfile)
20
-
21
- output = special_flag(flag, outfile, scale)
22
- output ||= USPSFlags::Generate::Flag.officer(rank: flag, outfile: outfile, scale: scale, field: field)
23
- output
24
- end
25
-
26
- # Convert SVG data into a PNG file.
27
- #
28
- # @param [String] svg The SVG data.
29
- # @param [String] outfile The path to save the PNG file to. (Required because the file is not accessible if this is left blank.)
30
- # @param [Boolean] trim Whether to trim the generated PNG file of excess transparency.
31
- # @param [String] background Background color. Defaults to 'none' (transparent).
32
- def png(svg, outfile: nil, trim: false, background: 'none')
33
- raise USPSFlags::Errors::PNGGenerationError.new(svg: svg) if outfile.nil? || outfile.empty?
4
+ class USPSFlags
5
+ class Generate
6
+ require 'usps_flags/generate/helper_methods'
7
+ require 'usps_flags/generate/generator_methods'
8
+
9
+ class << self
10
+ include USPSFlags::Generate::HelperMethods
11
+ include USPSFlags::Generate::GeneratorMethods
12
+ # The primary controller method. Generates an SVG file or SVG data.
13
+ #
14
+ # @param [String] flag The flag type to generate.
15
+ # @param [String] outfile The path to save the SVG file to. If not set, prints to console.
16
+ # @param [Boolean] field Whether to generate the flag field (including any border).
17
+ # @param [String] scale The image scale divisor factor.
18
+ # @return [String] Returns the SVG data.
19
+ def svg(flag, outfile: nil, scale: nil, field: true)
20
+ flag = flag.upcase.delete('/', '_', 'PENNANT')
21
+
22
+ USPSFlags::Helpers.ensure_dir_for_file(outfile)
23
+
24
+ output = special_flag(flag, outfile, scale)
25
+ output ||= USPSFlags::Generate::Flag.officer(rank: flag, outfile: outfile, scale: scale, field: field)
26
+ output
27
+ end
34
28
 
35
- set_temp_svg(svg)
29
+ # Convert SVG data into a PNG file.
30
+ #
31
+ # @param [String] svg The SVG data.
32
+ # @param [String] outfile The path to save the PNG file to. (Required because the file isn't accessible if blank.)
33
+ # @param [Boolean] trim Whether to trim the generated PNG file of excess transparency.
34
+ # @param [String] background Background color. Defaults to 'none' (transparent).
35
+ def png(svg, outfile: nil, trim: false, background: 'none')
36
+ raise USPSFlags::Errors::PNGGenerationError.new(svg: svg) if outfile.nil? || outfile.empty?
36
37
 
37
- USPSFlags::Helpers.ensure_dir_for_file(outfile)
38
+ set_temp_svg(svg)
38
39
 
39
- generate_png(background, trim, outfile)
40
- ensure
41
- ::File.delete(@temp_svg_path) if delete_temp_svg?
42
- end
40
+ USPSFlags::Helpers.ensure_dir_for_file(outfile)
43
41
 
44
- # Generate all static SVG and PNG files, and automaticall generates zip archives for download.
45
- #
46
- # @param [Boolean] svg Whether to generate SVG images.
47
- # @param [Boolean] png Whether to generate PNG images.
48
- # @param [Boolean] zips Whether to create zip archives for all images created. Does not create a zip for skipped formats.
49
- # @param [Boolean] reset Whether to delete all previous files before generating new files.
50
- def all(svg: true, png: true, zips: true, reset: true)
51
- all_arg_error unless any_all_arg?(svg, png, zips, reset)
52
-
53
- track_time do
54
- remove_static_files if reset
55
- images(svg: svg, png: png) if svg || png
56
- zips(svg: svg, png: png) if zips
42
+ generate_png(background, trim, outfile)
43
+ ensure
44
+ ::File.delete(@temp_svg_path) if delete_temp_svg?
57
45
  end
58
- end
59
46
 
60
- # Generate zip archives of current static image files.
61
- #
62
- # @param [Boolean] svg Generate zip archive of SVG images.
63
- # @param [Boolean] png Generate zip archive of PNG images.
64
- def zips(svg: true, png: true)
65
- unless svg || png
66
- raise(
67
- USPSFlags::Errors::ZipGenerationError,
68
- 'At least one argument switch must be true out of [svg, png].'
69
- )
47
+ # Generate all static SVG and PNG files, and automaticall generates zip archives for download.
48
+ #
49
+ # @param [Boolean] svg Whether to generate SVG images.
50
+ # @param [Boolean] png Whether to generate PNG images.
51
+ # @param [Boolean] zips Whether to create zip archives for all images created.
52
+ # @param [Boolean] reset Whether to delete all previous files before generating new files.
53
+ def all(svg: true, png: true, zips: true, reset: true)
54
+ all_arg_error unless any_all_arg?(svg, png, zips, reset)
55
+
56
+ track_time do
57
+ remove_static_files if reset
58
+ images(svg: svg, png: png) if svg || png
59
+ zips(svg: svg, png: png) if zips
60
+ end
70
61
  end
71
62
 
72
- generate_zip('svg') if svg
73
- generate_zip('png') if png
74
- end
63
+ # Generate zip archives of current static image files.
64
+ #
65
+ # @param [Boolean] svg Generate zip archive of SVG images.
66
+ # @param [Boolean] png Generate zip archive of PNG images.
67
+ def zips(svg: true, png: true)
68
+ unless svg || png
69
+ raise(
70
+ USPSFlags::Errors::ZipGenerationError,
71
+ 'At least one argument switch must be true out of [svg, png].'
72
+ )
73
+ end
74
+
75
+ generate_zip('svg') if svg
76
+ generate_zip('png') if png
77
+ end
75
78
 
76
- # Generate static image files.
77
- #
78
- # @param [Boolean] svg Generate static SVG images.
79
- # @param [Boolean] png Generate static PNG images.
80
- def images(svg: true, png: true)
81
- static_generation_header
82
- USPSFlags::Helpers.valid_flags(:all).each do |flag|
83
- generate_static_images_for(flag, svg: svg, png: png)
79
+ # Generate static image files.
80
+ #
81
+ # @param [Boolean] svg Generate static SVG images.
82
+ # @param [Boolean] png Generate static PNG images.
83
+ def images(svg: true, png: true)
84
+ static_generation_header
85
+ USPSFlags::Helpers.valid_flags(:all).each do |flag|
86
+ generate_static_images_for(flag, svg: svg, png: png)
87
+ end
84
88
  end
85
- end
86
89
 
87
- # Generate trident spec sheet as an SVG image.
88
- #
89
- # @param [String] outfile The path to save the SVG file to. If not set, prints to console.
90
- # @param [Integer] fly The nominal fly length of an appropriate flag field for the generated tridents. Size labels scale to this size.
91
- # @param [String] outfile The unit to append to all trident measurements.
92
- # @param [String] scale The image scale divisor factor.
93
- # @return [String] Returns the SVG data.
94
- def spec(outfile: nil, fly: USPSFlags::Config::BASE_FLY, unit: nil, scale: nil, scaled_border: false)
95
- svg = +''
96
- svg << USPSFlags::Core.headers(scale: scale, title: 'USPS Trident Specifications')
97
- svg << USPSFlags::Core.trident_spec(fly: fly, unit: unit, scaled_border: scaled_border)
98
- svg << USPSFlags::Core.footer
99
-
100
- USPSFlags::Helpers.output(svg, outfile: outfile)
101
- end
90
+ # Generate trident spec sheet as an SVG image.
91
+ #
92
+ # @param [String] outfile The path to save the SVG file to. If not set, prints to console.
93
+ # @param [Integer] fly The nominal fly length of an appropriate flag field for the generated tridents.
94
+ # @param [String] outfile The unit to append to all trident measurements.
95
+ # @param [String] scale The image scale divisor factor.
96
+ # @return [String] Returns the SVG data.
97
+ def spec(outfile: nil, fly: USPSFlags::Config::BASE_FLY, unit: nil, scale: nil, scaled_border: false)
98
+ svg = +''
99
+ svg << USPSFlags::Core.headers(scale: scale, title: 'USPS Trident Specifications')
100
+ svg << USPSFlags::Core.trident_spec(fly: fly, unit: unit, scaled_border: scaled_border)
101
+ svg << USPSFlags::Core.footer
102
+
103
+ USPSFlags::Helpers.output(svg, outfile: outfile)
104
+ end
102
105
 
103
- private
104
-
105
- def special_flag(flag, outfile, scale)
106
- case flag
107
- when 'CRUISE', 'OIC'
108
- USPSFlags::Generate::Flag.pennant(type: flag, outfile: outfile, scale: scale)
109
- when 'ENSIGN'
110
- USPSFlags::Generate::Flag.ensign(outfile: outfile, scale: scale)
111
- when 'US'
112
- USPSFlags::Generate::Flag.us(outfile: outfile, scale: scale)
113
- when 'WHEEL'
114
- USPSFlags::Generate::Flag.wheel(outfile: outfile, scale: scale)
106
+ private
107
+
108
+ def special_flag(flag, outfile, scale)
109
+ case flag
110
+ when 'CRUISE', 'OIC'
111
+ USPSFlags::Generate::Flag.pennant(type: flag, outfile: outfile, scale: scale)
112
+ when 'ENSIGN'
113
+ USPSFlags::Generate::Flag.ensign(outfile: outfile, scale: scale)
114
+ when 'US'
115
+ USPSFlags::Generate::Flag.us(outfile: outfile, scale: scale)
116
+ when 'WHEEL'
117
+ USPSFlags::Generate::Flag.wheel(outfile: outfile, scale: scale)
118
+ end
115
119
  end
116
- end
117
120
 
118
- def generate_png(background, trim, outfile)
119
- MiniMagick::Tool::Convert.new do |convert|
120
- convert << '-background' << background
121
- convert << '-format' << 'png'
122
- convert << '-trim' if trim
123
- convert << @temp_svg_path
124
- convert << outfile
121
+ def generate_png(background, trim, outfile)
122
+ MiniMagick::Tool::Convert.new do |convert|
123
+ convert << '-background' << background
124
+ convert << '-format' << 'png'
125
+ convert << '-trim' if trim
126
+ convert << @temp_svg_path
127
+ convert << outfile
128
+ end
125
129
  end
126
130
  end
127
131
  end
@@ -4,164 +4,167 @@
4
4
  #
5
5
  # These methods should never need to be called directly.
6
6
  # @private
7
- class USPSFlags::Generate::Flag
8
- class << self
9
- def officer(rank: nil, outfile: nil, scale: nil, field: true)
10
- raise ArgumentError, 'No rank specified.' if rank.nil?
11
-
12
- @rank = rank.to_s.upcase
13
- @field = field
14
-
15
- svg = +''
16
- svg << USPSFlags::Core.headers(scale: scale, title: @rank)
17
- modify_rank_for_insignia
18
- @flag_details = USPSFlags::Helpers.flag_details(@rank)
19
- @trident_color = @field ? :white : @flag_details[:color]
20
- svg << officer_flag_body(@flag_details[:style])
21
-
22
- USPSFlags::Helpers.output(svg, outfile: outfile)
23
- end
24
-
25
- def special(type, level:, field: true)
26
- # Paths were designed for a base fly of 3000 pixels, but the base was changed for more useful fractions.
27
- svg = +''
28
- svg << "<g transform=\"translate(#{USPSFlags::Config::BASE_FLY / 10})\">" unless field
29
- svg << "<g transform=\"scale(#{Rational(USPSFlags::Config::BASE_FLY, 3000).to_f})\">"
30
- svg << special_icon(type, level)
31
- svg << '</g>'
32
- svg << '</g>' unless field
33
-
34
- svg
35
- end
36
-
37
- def pennant(type: 'CRUISE', outfile: nil, scale: nil)
38
- type = type.upcase
39
- svg = +''
40
- title = { 'CRUISE' => 'Cruise Pennant', 'OIC' => 'Officer-in-Charge Pennant' }[type]
41
- svg << USPSFlags::Core.headers(pennant: true, scale: scale, title: title)
42
- svg << USPSFlags::Core.pennant(type)
43
- svg << USPSFlags::Core.footer
44
-
45
- USPSFlags::Helpers.output(svg, outfile: outfile)
46
- end
47
-
48
- def ensign(outfile: nil, scale: nil)
49
- svg = +''
50
- svg << USPSFlags::Core.headers(scale: scale, title: 'USPS Ensign')
51
- svg << USPSFlags::Core.ensign
52
- svg << USPSFlags::Core.footer
53
-
54
- USPSFlags::Helpers.output(svg, outfile: outfile)
55
- end
56
-
57
- def wheel(outfile: nil, scale: nil)
58
- width = 4327.4667
59
- height = 4286.9333
60
- svg = +''
61
- svg << USPSFlags::Core.headers(width: width, height: height, scale: scale, title: 'USPS Ensign Wheel')
62
- svg << USPSFlags::Core.wheel
63
- svg << USPSFlags::Core.footer
64
-
65
- USPSFlags::Helpers.output(svg, outfile: outfile)
66
- end
67
-
68
- def us(outfile: nil, scale: nil)
69
- base_hoist = 2000.to_f
70
- hoist = scale.nil? ? base_hoist : (base_hoist / scale)
71
- fly = hoist * 1.91
72
- svg = +''
73
- svg << USPSFlags::Core.headers(width: fly, height: hoist, scale: scale, title: 'US Ensign')
74
- svg << USPSFlags::Core.us
75
- svg << USPSFlags::Core.footer
76
-
77
- USPSFlags::Helpers.output(svg, outfile: outfile)
78
- end
79
-
80
- private
81
-
82
- def special_icon(type, level)
83
- {
84
- a: USPSFlags::Core.binoculars(level), f: USPSFlags::Core.trumpet(level),
85
- fc: USPSFlags::Core.anchor, pc: USPSFlags::Core.lighthouse
86
- }[type]
87
- end
88
-
89
- def get_officer_flag
90
- [
91
- get_national_bridge_flag, get_bridge_flag, get_offset_flag, get_special_flag
92
- ].compact.first || get_trident_flag
93
- end
94
-
95
- def get_national_bridge_flag
96
- return unless cc? || vc?
97
-
98
- return USPSFlags::Core::Tridents.cc(@flag_details[:type], trident_color: @trident_color) if cc?
99
- return USPSFlags::Core::Tridents.vc(@flag_details[:type], trident_color: @trident_color) if vc?
100
- end
101
-
102
- def get_bridge_flag
103
- return unless three? || two?
104
-
105
- if three?
106
- USPSFlags::Core::Tridents.three(@flag_details[:type], trident_color: @trident_color, field_color: @flag_details[:color])
107
- elsif two?
108
- USPSFlags::Core::Tridents.two(@flag_details[:type], trident_color: @trident_color, field_color: @flag_details[:color])
7
+ class USPSFlags
8
+ class Generate
9
+ class Flag
10
+ class << self
11
+ def officer(rank: nil, outfile: nil, scale: nil, field: true)
12
+ raise ArgumentError, 'No rank specified.' if rank.nil?
13
+
14
+ @rank = rank.to_s.upcase
15
+ @field = field
16
+
17
+ svg = USPSFlags::Core.headers(scale: scale, title: @rank)
18
+ modify_rank_for_insignia
19
+ @flag_details = USPSFlags::Helpers.flag_details(@rank)
20
+ @trident_color = @field ? :white : @flag_details[:color]
21
+ svg << officer_flag_body(@flag_details[:style])
22
+
23
+ USPSFlags::Helpers.output(svg, outfile: outfile)
24
+ end
25
+
26
+ def special(type, level:, field: true)
27
+ # Paths were designed for a base fly of 3000 pixels, but the base was changed for more useful fractions.
28
+ svg = +''
29
+ svg << "<g transform=\"translate(#{USPSFlags::Config::BASE_FLY / 10})\">" unless field
30
+ svg << "<g transform=\"scale(#{Rational(USPSFlags::Config::BASE_FLY, 3000).to_f})\">"
31
+ svg << special_icon(type, level)
32
+ svg << '</g>'
33
+ svg << '</g>' unless field
34
+
35
+ svg
36
+ end
37
+
38
+ def pennant(type: 'CRUISE', outfile: nil, scale: nil)
39
+ type = type.upcase
40
+ title = { 'CRUISE' => 'Cruise Pennant', 'OIC' => 'Officer-in-Charge Pennant' }[type]
41
+ svg = USPSFlags::Core.headers(pennant: true, scale: scale, title: title)
42
+ svg << USPSFlags::Core.pennant(type)
43
+ svg << USPSFlags::Core.footer
44
+
45
+ USPSFlags::Helpers.output(svg, outfile: outfile)
46
+ end
47
+
48
+ def ensign(outfile: nil, scale: nil)
49
+ svg = USPSFlags::Core.headers(scale: scale, title: 'USPS Ensign')
50
+ svg << USPSFlags::Core.ensign
51
+ svg << USPSFlags::Core.footer
52
+
53
+ USPSFlags::Helpers.output(svg, outfile: outfile)
54
+ end
55
+
56
+ def wheel(outfile: nil, scale: nil)
57
+ width = 4327.4667
58
+ height = 4286.9333
59
+ svg = USPSFlags::Core.headers(width: width, height: height, scale: scale, title: 'USPS Ensign Wheel')
60
+ svg << USPSFlags::Core.wheel
61
+ svg << USPSFlags::Core.footer
62
+
63
+ USPSFlags::Helpers.output(svg, outfile: outfile)
64
+ end
65
+
66
+ def us(outfile: nil, scale: nil)
67
+ base_hoist = 2000.to_f
68
+ hoist = scale.nil? ? base_hoist : (base_hoist / scale)
69
+ fly = hoist * 1.91
70
+ svg = USPSFlags::Core.headers(width: fly, height: hoist, scale: scale, title: 'US Ensign')
71
+ svg << USPSFlags::Core.us
72
+ svg << USPSFlags::Core.footer
73
+
74
+ USPSFlags::Helpers.output(svg, outfile: outfile)
75
+ end
76
+
77
+ private
78
+
79
+ def special_icon(type, level)
80
+ {
81
+ a: USPSFlags::Core.binoculars(level), f: USPSFlags::Core.trumpet(level),
82
+ fc: USPSFlags::Core.anchor, pc: USPSFlags::Core.lighthouse
83
+ }[type]
84
+ end
85
+
86
+ def get_officer_flag
87
+ [
88
+ get_national_bridge_flag, get_bridge_flag, get_offset_flag, get_special_flag
89
+ ].compact.first || get_trident_flag
90
+ end
91
+
92
+ def get_national_bridge_flag
93
+ return unless cc? || vc?
94
+
95
+ return USPSFlags::Core::Tridents.cc(@flag_details[:type], trident_color: @trident_color) if cc?
96
+ return USPSFlags::Core::Tridents.vc(@flag_details[:type], trident_color: @trident_color) if vc?
97
+ end
98
+
99
+ def get_bridge_flag
100
+ return unless three? || two?
101
+
102
+ if three?
103
+ USPSFlags::Core::Tridents.three(
104
+ @flag_details[:type], trident_color: @trident_color, field_color: @flag_details[:color]
105
+ )
106
+ elsif two?
107
+ USPSFlags::Core::Tridents.two(
108
+ @flag_details[:type], trident_color: @trident_color, field_color: @flag_details[:color]
109
+ )
110
+ end
111
+ end
112
+
113
+ def get_offset_flag
114
+ return unless offset?
115
+
116
+ USPSFlags::Core::Tridents.offset(@flag_details[:type], field_color: @flag_details[:color], field: @field)
117
+ end
118
+
119
+ def get_special_flag
120
+ return unless special?
121
+
122
+ special(@flag_details[:type], level: @flag_details[:level], field: @field)
123
+ end
124
+
125
+ def get_trident_flag
126
+ USPSFlags::Core.trident(@flag_details[:type], field_color: @flag_details[:color])
127
+ end
128
+
129
+ def officer_flag_body(style)
130
+ svg = +''
131
+ svg << USPSFlags::Core.field(style: style, color: @flag_details[:color]) if @field
132
+ svg << '<g transform="translate(-150, 400)"><g transform="scale(0.58333)">' if style == :past
133
+ svg << get_officer_flag
134
+ svg << '</g></g>' if style == :past
135
+ svg << USPSFlags::Core.footer
136
+ svg
137
+ end
138
+
139
+ def modify_rank_for_insignia
140
+ @rank.slice!(0) if !@field && USPSFlags::Helpers.valid_flags(:past).include?(@rank)
141
+ @rank = 'CDR' if @rank == 'C'
142
+ end
143
+
144
+ def cc?
145
+ @flag_details[:type] == :n && @flag_details[:count] == 3
146
+ end
147
+
148
+ def vc?
149
+ @flag_details[:type] == :n && @flag_details[:count] == 2
150
+ end
151
+
152
+ def three?
153
+ %i[s d].include?(@flag_details[:type]) && @flag_details[:count] == 3
154
+ end
155
+
156
+ def two?
157
+ %i[s d].include?(@flag_details[:type]) && @flag_details[:count] == 2
158
+ end
159
+
160
+ def offset?
161
+ %w[LT DLT].include?(@rank)
162
+ end
163
+
164
+ def special?
165
+ %i[a f fc pc].include?(@flag_details[:type])
166
+ end
109
167
  end
110
168
  end
111
-
112
- def get_offset_flag
113
- return unless offset?
114
-
115
- USPSFlags::Core::Tridents.offset(@flag_details[:type], field_color: @flag_details[:color], field: @field)
116
- end
117
-
118
- def get_special_flag
119
- return unless special?
120
-
121
- special(@flag_details[:type], level: @flag_details[:level], field: @field)
122
- end
123
-
124
- def get_trident_flag
125
- USPSFlags::Core.trident(@flag_details[:type], field_color: @flag_details[:color])
126
- end
127
-
128
- def officer_flag_body(style)
129
- svg = +''
130
- svg << USPSFlags::Core.field(style: style, color: @flag_details[:color]) if @field
131
- svg << '<g transform="translate(-150, 400)"><g transform="scale(0.58333)">' if style == :past
132
- svg << get_officer_flag
133
- svg << '</g></g>' if style == :past
134
- svg << USPSFlags::Core.footer
135
- svg
136
- end
137
-
138
- def modify_rank_for_insignia
139
- @rank.slice!(0) if !@field && USPSFlags::Helpers.valid_flags(:past).include?(@rank)
140
- @rank = 'CDR' if @rank == 'C'
141
- end
142
-
143
- def cc?
144
- @flag_details[:type] == :n && @flag_details[:count] == 3
145
- end
146
-
147
- def vc?
148
- @flag_details[:type] == :n && @flag_details[:count] == 2
149
- end
150
-
151
- def three?
152
- [:s, :d].include?(@flag_details[:type]) && @flag_details[:count] == 3
153
- end
154
-
155
- def two?
156
- [:s, :d].include?(@flag_details[:type]) && @flag_details[:count] == 2
157
- end
158
-
159
- def offset?
160
- %w[LT DLT].include?(@rank)
161
- end
162
-
163
- def special?
164
- [:a, :f, :fc, :pc].include?(@flag_details[:type])
165
- end
166
169
  end
167
170
  end