astromapper 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +124 -0
- data/Rakefile +1 -0
- data/astromapper.gemspec +29 -0
- data/bin/astromapper +5 -0
- data/lib/astromapper.rb +54 -0
- data/lib/astromapper/builder.rb +43 -0
- data/lib/astromapper/builder/orbit.rb +370 -0
- data/lib/astromapper/builder/sector.rb +33 -0
- data/lib/astromapper/builder/star.rb +198 -0
- data/lib/astromapper/builder/volume.rb +38 -0
- data/lib/astromapper/cli.rb +60 -0
- data/lib/astromapper/exporter.rb +64 -0
- data/lib/astromapper/extensions/array.rb +5 -0
- data/lib/astromapper/extensions/float.rb +5 -0
- data/lib/astromapper/extensions/integer.rb +44 -0
- data/lib/astromapper/extensions/string.rb +11 -0
- data/lib/astromapper/generator.rb +31 -0
- data/lib/astromapper/svg.rb +303 -0
- data/lib/astromapper/version.rb +3 -0
- data/templates/config.erb +79 -0
- data/templates/names.yml +2050 -0
- metadata +183 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
module Astromapper
|
2
|
+
module Builder
|
3
|
+
class Sector < Astromapper::Builder::Base
|
4
|
+
def constitute
|
5
|
+
@volumes = []
|
6
|
+
40.times do |r|
|
7
|
+
32.times do |c|
|
8
|
+
next unless has_system?
|
9
|
+
v = Volume.new(c+1,r+1)
|
10
|
+
@volumes << v unless v.empty?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
self
|
14
|
+
end
|
15
|
+
def has_system?
|
16
|
+
case
|
17
|
+
when config['density'] == 'extra_galactic' then (1.d100 <= 1)
|
18
|
+
when config['density'] == 'rift' then (1.d100 <= 3)
|
19
|
+
when config['density'] == 'sparse' then (1.d100 <= 17)
|
20
|
+
when config['density'] == 'scattered' then (1.d100 <= 33)
|
21
|
+
when config['density'] == 'dense' then (1.d100 <= 66)
|
22
|
+
when config['density'] == 'cluster' then (1.d100 <= 83)
|
23
|
+
when config['density'] == 'core' then (1.d100 <= 91)
|
24
|
+
else (d100 <= 50) # Standard
|
25
|
+
end
|
26
|
+
end
|
27
|
+
def to_file
|
28
|
+
file = Astromapper.output_file('sector')
|
29
|
+
File.open(file,'w').write(@volumes.map{|v| v.to_ascii}.join("\n"))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
module Astromapper
|
2
|
+
module Builder
|
3
|
+
class Star < Astromapper::Builder::Base
|
4
|
+
attr_accessor :star_size, :mass, :bode_constant, :biozone, :type_dm, :size_dm, :orbits, :primary, :orbit, :id, :volume, :world, :companions
|
5
|
+
# @@stars = {}
|
6
|
+
STAR_CHART = {
|
7
|
+
#type => 0)example, 1)temp, 2)lux, 3)mass, 4)radius
|
8
|
+
'B0' => ['Becrux', 30000, 16000, 16.0, 5.70],
|
9
|
+
'B2' => ['Spica', 22000, 8300, 10.5, 5.10],
|
10
|
+
'B5' => ['Achernar', 15000, 750, 5.40, 3.70],
|
11
|
+
'B8' => ['Rigel', 12500, 130, 3.50, 2.70],
|
12
|
+
'A0' => ['Sirius A', 9500, 63, 2.60, 2.30],
|
13
|
+
'A2' => ['Fomalhaut', 9000, 40, 2.20, 2.00],
|
14
|
+
'A5' => ['Altair', 8700, 24, 1.90, 1.80],
|
15
|
+
'F0' => ['Gamma Virginis', 7400, 9.0, 1.60, 1.50],
|
16
|
+
'F2' => ['.', 7100, 6.3, 1.50, 1.30],
|
17
|
+
'F5' => ['Procyon A', 6400, 4.0, 1.35, 1.20],
|
18
|
+
'G0' => ['Alpha Centauri A', 5900, 1.45, 1.08, 1.05],
|
19
|
+
'G2' => ['The Sun', 5800, 1.00, 1.00, 1.00],
|
20
|
+
'G5' => ['Mu Cassiopeiae', 5600, 0.70, 0.95, 0.91],
|
21
|
+
'G8' => ['Tau Ceti', 5300, 0.44, 0.85, 0.87],
|
22
|
+
'K0' => ['Pollux', 5100, 0.36, 0.83, 0.83],
|
23
|
+
'K2' => ['Epsilon Eridani', 4830, 0.28, 0.78, 0.79],
|
24
|
+
'K5' => ['Alpha Centauri B', 4370, 0.18, 0.68, 0.74],
|
25
|
+
'M0' => ['Gliese 185', 3670, 0.075, 0.47, 0.63],
|
26
|
+
'M2' => ['Lalande 21185', 3400, 0.03, 0.33, 0.36],
|
27
|
+
'M4' => ['Ross 128', 3200, 0.0005, 0.20, 0.21],
|
28
|
+
'M6' => ['Wolf 359', 3000, 0.0002, 0.10, 0.12]
|
29
|
+
}
|
30
|
+
INNER_LIMIT = {
|
31
|
+
'O' => [ 16, 13, 10 ],
|
32
|
+
'B' => [ 10, 6.3, 5.0, 4.0, 3.8, 0.6, 0],
|
33
|
+
'A' => [ 4, 1, 0.4, 0, 0, 0, 0],
|
34
|
+
'F' => [ 4, 1, 0.3, 0.1, 0, 0, 0],
|
35
|
+
'G' => [ 3.1, 1, 0.3, 0.1, 0, 0, 0],
|
36
|
+
'K' => [ 2.5, 1, 0.3, 0.1, 0, 0, 0],
|
37
|
+
'M' => [ 2, 1, 0.3, 0.1, 0, 0, 0],
|
38
|
+
'D' => [ 0 ],
|
39
|
+
}
|
40
|
+
BIOZONE = {
|
41
|
+
'O' => [ [790,1190], [630,950], [500,750] ],
|
42
|
+
'B' => [ [500,700], [320,480], [250,375], [200,300], [180,270], [30,45] ],
|
43
|
+
'A' => [ [200,300], [50,75], [20,30], [5.0,7.5], [4.0,6.0], [3.1,4.7] ],
|
44
|
+
'F' => [ [200,300], [50,75], [13,19], [2.5,3.7], [2.0,3.0], [1.6,2.4], [0.5,0.8] ],
|
45
|
+
'G' => [ [200,300], [50,75], [13,19], [2.5,3.7], [2.0,3.0], [1.6,2.4], [0.5,0.8] ],
|
46
|
+
'K' => [ [125,190], [50,75], [13,19], [4.0,5.9], [1.0,1.5], [0.5,0.6], [0.2,0.3] ],
|
47
|
+
'M' => [ [100,150], [50,76], [16,24], [5.0,7.5], [0,0], [0.1,0.2], [0.1,0.1] ],
|
48
|
+
'D' => [ [0.03, 0.03] ],
|
49
|
+
}
|
50
|
+
SPECTRAL = {
|
51
|
+
'O' => [9],
|
52
|
+
'B' => [0,2,5,8],
|
53
|
+
'A' => [0,2,5],
|
54
|
+
'F' => [0,2,5],
|
55
|
+
'G' => [0,2,5,8],
|
56
|
+
'K' => [0,2,5],
|
57
|
+
'M' => [0,2,4,6]
|
58
|
+
}
|
59
|
+
MASS = {
|
60
|
+
'O' => [70, 60, 0, 0, 50, 0 ],
|
61
|
+
'B' => [50, 40, 35, 30, 20, 10],
|
62
|
+
'A' => [30, 16, 10, 6, 4, 3],
|
63
|
+
'F' => [15, 13, 8, 2.5, 2.2, 1.9],
|
64
|
+
'G' => [12, 10, 6, 2.7, 1.8, 1.1, 0.8],
|
65
|
+
'K' => [15, 12, 6, 3, 2.3, 0.9, 0.5],
|
66
|
+
'M' => [20, 16, 8, 4, 0.3, 0.2],
|
67
|
+
'D' => [0.8,0.8,0.8,0.8,0.8,0.8,]
|
68
|
+
}
|
69
|
+
COMPANION_SEPARATION = [[0.05]*2, [0.5]*3, [2.0]*2, [10.0]*3, [50.0] * 10].flatten
|
70
|
+
BODE_RATIO = [[0.3] * 4, [0.35] * 3, [0.4] * 4].flatten
|
71
|
+
def initialize(volume, primary=nil,ternary=0)
|
72
|
+
@volume = volume
|
73
|
+
@primary = primary
|
74
|
+
@orbits = []
|
75
|
+
@companions = []
|
76
|
+
@world = nil
|
77
|
+
|
78
|
+
@type_dm = 0
|
79
|
+
@size_dm = 0
|
80
|
+
@has_gg = false
|
81
|
+
|
82
|
+
if primary.nil?
|
83
|
+
@orbit = 0
|
84
|
+
@type_dm = (toss(2,0) + @volume.star_dm ).max(12)
|
85
|
+
@size_dm = (toss(2,0) + 0 ).max(12)
|
86
|
+
@star_type = %w{B B A M M M M M K G F F F}[@type_dm]
|
87
|
+
@star_size = %w{0 1 2 3 4 5 5 5 5 5 5 6 500}[@size_dm].to_i
|
88
|
+
else
|
89
|
+
separation = (toss(2,0) * COMPANION_SEPARATION[toss(3) + (4 * ternary) - 2]).round(2) # Gurps Space 4e p.105
|
90
|
+
|
91
|
+
@orbit = au_to_orbit(separation) - 1
|
92
|
+
@star_type = %w{X B A F F G G K K M M M M}[(toss(2,0) + primary.type_dm).max(12)]
|
93
|
+
@star_size = %w{0 1 2 3 4 500 500 5 5 6 500 500 500 500}[(toss(2,0) + primary.size_dm).max(12)].to_i
|
94
|
+
end
|
95
|
+
@spectral = @star_type + SPECTRAL[@star_type].sample.to_s
|
96
|
+
@star_size ||= 500
|
97
|
+
|
98
|
+
@bode_constant = (@star_type=='M' and @star_size==5) ? 0.2 : BODE_RATIO[toss]
|
99
|
+
|
100
|
+
if @star_size == 500
|
101
|
+
@star_subtype = (true) ? 'B' : @star_type
|
102
|
+
@star_type = 'D'
|
103
|
+
end
|
104
|
+
|
105
|
+
dm = 0
|
106
|
+
dm += 4 if @star_size == 3
|
107
|
+
dm += 8 if @star_size < 3
|
108
|
+
dm -= 4 if @star_type == 'M'
|
109
|
+
dm -= 2 if @star_type == 'K'
|
110
|
+
|
111
|
+
# Populate Orbits
|
112
|
+
(toss(2,0) + dm).whole.times do |i|
|
113
|
+
@orbits << Orbit.new(self,i).populate unless orbit_to_au(i) > outer_limit
|
114
|
+
@world = @orbits.last if @orbits.last.is_a?(World)
|
115
|
+
end
|
116
|
+
@world.gas_giant = (@orbits.map{|o| o.kid}.include?('G')) ? 'G' : '.' unless @world.nil?
|
117
|
+
prune!
|
118
|
+
end
|
119
|
+
def prune! # Ensure last orbits are not empty.
|
120
|
+
@orbits.each_index { |x| @orbits[x] = Orbit.new(self,x) if @orbits[x].nil?}
|
121
|
+
c = @orbits
|
122
|
+
# exit
|
123
|
+
tk = false
|
124
|
+
@orbits = @orbits.sort{|b,a| a.orbit_number <=> b.orbit_number}.map {|o| tk = true unless (o.kid == '.' or tk); o if tk }.reverse.compact
|
125
|
+
# @orbits.each_index { |x| @orbits[x] = Orbit.new(self,x) if @orbits[x].nil?}
|
126
|
+
|
127
|
+
return if @orbits.size < 2
|
128
|
+
@orbits.length.times do |i|
|
129
|
+
@orbits[i].orbit_number = i
|
130
|
+
@orbits[i].au = self.orbit_to_au(i)
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
def orbit_to_au(o)
|
135
|
+
inner_limit + (self.bode_constant * (2 ** o)).round(1)
|
136
|
+
end
|
137
|
+
def au_to_orbit(au)
|
138
|
+
constant = (@primary.nil?) ? @bode_constant : @primary.bode_constant
|
139
|
+
(Math.log(au / constant) / Math.log(2) ).round(2).abs - inner_limit
|
140
|
+
end
|
141
|
+
def companions=(star)
|
142
|
+
orbit = star.orbit.abs
|
143
|
+
companion = Companion.new(self, orbit, star)
|
144
|
+
|
145
|
+
# Gurps Space 4e p.107 - Clear Forbidden orbits
|
146
|
+
inner = au_to_orbit(companion.au * 0.67).floor
|
147
|
+
outer = au_to_orbit(companion.au * 3).ceil
|
148
|
+
@forbidden = (inner .. outer)
|
149
|
+
@forbidden.each { |x| @orbits[x] = nil }
|
150
|
+
@orbits[orbit - 1] = companion
|
151
|
+
@companions << star
|
152
|
+
prune!
|
153
|
+
end
|
154
|
+
def to_s; kid; end
|
155
|
+
def kid; 'C'; end
|
156
|
+
def radius; (155000 * Math.sqrt(luminosity)) ** 2; end # Gurps Space 4e p. 104
|
157
|
+
def snow_line; 4.85 * Math.sqrt(luminosity); end # Gurps Space 4e p. 106
|
158
|
+
def outer_limit; 40 * mass; end # Gurps Space 4e p. 107
|
159
|
+
def orbits_to_ascii
|
160
|
+
return '' if @orbits.empty?
|
161
|
+
"\n" + @orbits.map{|o| o.to_ascii}.join("\n") + "\n"
|
162
|
+
end
|
163
|
+
def crib
|
164
|
+
stars = [classification]
|
165
|
+
@companions.each { |s| stars << s.classification }
|
166
|
+
"%-17s %-16s" % [stars.join('/'), @orbits.map{|o| o.kid}.join('')]
|
167
|
+
end
|
168
|
+
def to_ascii
|
169
|
+
classification
|
170
|
+
end
|
171
|
+
def classification
|
172
|
+
return @star_type + @star_subtype if (@star_type == 'D')
|
173
|
+
"#{@spectral}#{@star_size.roman}"
|
174
|
+
end
|
175
|
+
def world?
|
176
|
+
return @orbits.join('').include?('W')
|
177
|
+
return false
|
178
|
+
end
|
179
|
+
def column; @volume.column; end
|
180
|
+
def row; @volume.row; end
|
181
|
+
def sector; @volume.sector; end
|
182
|
+
def location; @volume.location; end
|
183
|
+
def type; @star_type; end
|
184
|
+
def type=(s); @star_type = s; end
|
185
|
+
def size; @star_size; end
|
186
|
+
def size=(s); @star_size = s; end
|
187
|
+
def inner_limit; limit; end
|
188
|
+
def limit
|
189
|
+
return 0 if @star_size.nil?
|
190
|
+
INNER_LIMIT[@star_type][@star_size % 10]
|
191
|
+
end
|
192
|
+
def biozone; BIOZONE[@star_type][@star_size % 10] or []; end
|
193
|
+
def luminosity; STAR_CHART[@spectral][2]; end
|
194
|
+
def temperature; @temperature = STAR_CHART[@spectral][1].around(20) if @temperature.nil?; end
|
195
|
+
def mass; MASS[@star_type][@star_size] || 0.3; end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Astromapper
|
2
|
+
module Builder
|
3
|
+
class Volume < Astromapper::Builder::Base
|
4
|
+
|
5
|
+
attr_accessor :gas_giant, :name
|
6
|
+
|
7
|
+
def initialize(c,r)
|
8
|
+
@name = (config['named']) ? Astromapper.names.sample : "%02d%02d" % [c,r]
|
9
|
+
@column = c
|
10
|
+
@row = r
|
11
|
+
@star = Star.new(self)
|
12
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2][toss(2,0)].times do |i|
|
13
|
+
@star.companions = Star.new(self, @star,i)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def star_dm
|
18
|
+
return 0 if @atmo.nil? or @popx.nil?
|
19
|
+
((4..9).include?(@atmo) or @popx > 7) ? 4 : 0
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_ascii
|
23
|
+
w = @star.world
|
24
|
+
sumy = "%s %s %s %s %s\t%-15s\t%-8s\t%s\t%s" % [location, w.uwp, w.temp, w.bases, w.travel_code, w.trade_codes.join(','), w.factions.join(','), @star.crib, @name]
|
25
|
+
sumy += @star.orbits_to_ascii
|
26
|
+
return sumy
|
27
|
+
end
|
28
|
+
|
29
|
+
def empty?
|
30
|
+
return true if @star.world.nil? or @star.world.empty? or !@star.world?
|
31
|
+
end
|
32
|
+
|
33
|
+
def location
|
34
|
+
"%02d%02d" % [@column,@row]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'thor'
|
3
|
+
require 'Astromapper/version'
|
4
|
+
module Astromapper
|
5
|
+
class Cli < Thor
|
6
|
+
FORMATS = %w[pdf draft proof html epub mobi txt]
|
7
|
+
check_unknown_options!
|
8
|
+
|
9
|
+
def self.exit_on_failure?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
def initialize(args = [], options = {}, config = {})
|
13
|
+
# if (config[:current_task] || config[:current_command]).name == "new" && args.empty?
|
14
|
+
# raise Error, "The e-Book path is required. For details run: Astromapper help new"
|
15
|
+
# end
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "new", "Create Astromapper Directory"
|
20
|
+
map %w(-n new -c) => :create
|
21
|
+
def create(path)
|
22
|
+
say "Voices of billions cry out in terror at the creation of '#{path}'"
|
23
|
+
generator = Generator.new
|
24
|
+
generator.destination_root = path.squish.gsub(' ','-')
|
25
|
+
generator.invoke_all
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "build", "Generate a map of {sector / domain}"
|
29
|
+
map %w{-b --build generate} => :build
|
30
|
+
def build(type='sector')
|
31
|
+
say "Building #{type}: #{config['name'].inspect}"
|
32
|
+
Astromapper::Exporter.run(root_dir, options)
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "svg", "Convert ASCII output to SVG"
|
36
|
+
map %w{-s --svg} => :svg
|
37
|
+
def svg
|
38
|
+
source = Astromapper.output_file('sector')
|
39
|
+
say "Converting #{source} to SVG"
|
40
|
+
s = Svg.new(source)
|
41
|
+
s.convert
|
42
|
+
say "SVG available at #{Astromapper.output_file('svg')}"
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "version", "Prints the Astromapper's version information"
|
46
|
+
map %w(-v --version) => :version
|
47
|
+
def version
|
48
|
+
say "Astromapper version #{Astromapper::VERSION}"
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def config
|
53
|
+
# YAML.load_file(config_path).with_indifferent_access
|
54
|
+
Astromapper.config
|
55
|
+
end
|
56
|
+
def root_dir
|
57
|
+
@root ||= Pathname.new(Dir.pwd)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Astromapper
|
2
|
+
class Exporter
|
3
|
+
def self.run(root_dir, options)
|
4
|
+
exporter = new(root_dir, options)
|
5
|
+
exporter.export!
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_accessor :root_dir
|
9
|
+
attr_accessor :options
|
10
|
+
|
11
|
+
def initialize(root_dir, options)
|
12
|
+
@root_dir = root_dir
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def ui
|
17
|
+
@ui ||= Thor::Base.shell.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def export!
|
21
|
+
helper = root_dir.join("config/helper.rb")
|
22
|
+
load(helper) if helper.exist?
|
23
|
+
exported = []
|
24
|
+
|
25
|
+
sector = Builder::Sector.constitute(root_dir)
|
26
|
+
|
27
|
+
sector.to_file
|
28
|
+
|
29
|
+
# export_pdf = [nil, "pdf"].include?(options[:only])
|
30
|
+
# export_html = [nil, "html", "mobi", "epub"].include?(options[:only])
|
31
|
+
# export_epub = [nil, "mobi", "epub"].include?(options[:only])
|
32
|
+
# export_mobi = [nil, "mobi"].include?(options[:only])
|
33
|
+
# export_txt = [nil, "txt"].include?(options[:only])
|
34
|
+
|
35
|
+
# exported = []
|
36
|
+
# exported << Parser::PDF.parse(root_dir) if export_pdf && Dependency.xelatex?# && Dependency.prince?
|
37
|
+
# exported << Parser::HTML.parse(root_dir) if export_html
|
38
|
+
# epub_done = Parser::Epub.parse(root_dir) if export_epub
|
39
|
+
# exported << epub_done
|
40
|
+
# exported << Parser::Mobi.parse(root_dir) if export_mobi && epub_done && Dependency.kindlegen?
|
41
|
+
# exported << Parser::Txt.parse(root_dir) if export_txt && Dependency.html2text?
|
42
|
+
|
43
|
+
if exported.all?
|
44
|
+
color = :green
|
45
|
+
message = options[:auto] ? "exported!" : "** Map has been exported"
|
46
|
+
|
47
|
+
# Notifier.notify(
|
48
|
+
# # :image => Astromapper::ROOT.join("templates/ebook.png"),
|
49
|
+
# :title => "Astromapper",
|
50
|
+
# :message => "Your \"#{config[:title]}\" map has been exported!"
|
51
|
+
# )
|
52
|
+
else
|
53
|
+
color = :red
|
54
|
+
message = options[:auto] ? "could not be exported!" : "** e-book couldn't be exported"
|
55
|
+
end
|
56
|
+
|
57
|
+
ui.say message, color
|
58
|
+
end
|
59
|
+
|
60
|
+
def config
|
61
|
+
Astromapper.config(root_dir)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Integer
|
2
|
+
def dn(n)
|
3
|
+
(1..self).inject(0) { |a, e| a + rand(n) + 1 }
|
4
|
+
end
|
5
|
+
def d3
|
6
|
+
dn(3)
|
7
|
+
end
|
8
|
+
def d6
|
9
|
+
dn(6)
|
10
|
+
end
|
11
|
+
def d100
|
12
|
+
dn(100)
|
13
|
+
end
|
14
|
+
def hexd
|
15
|
+
return 'F' if self > 15
|
16
|
+
self.whole.to_s(16).upcase
|
17
|
+
end
|
18
|
+
def whole
|
19
|
+
return 0 if self < 0
|
20
|
+
return self
|
21
|
+
end
|
22
|
+
def natural
|
23
|
+
return 1 if self < 1
|
24
|
+
return self
|
25
|
+
end
|
26
|
+
def roman
|
27
|
+
return 'D' if self ==500
|
28
|
+
return %w{Ia Ib II III IV V VI VII VIII IX X}[self]
|
29
|
+
end
|
30
|
+
def max(n)
|
31
|
+
return n if self > n
|
32
|
+
return self
|
33
|
+
end
|
34
|
+
def min(n)
|
35
|
+
return n if self < n
|
36
|
+
return self
|
37
|
+
end
|
38
|
+
def tweak
|
39
|
+
return self
|
40
|
+
end
|
41
|
+
def to_string
|
42
|
+
return self.tweak
|
43
|
+
end
|
44
|
+
end
|