astromapper 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|