textflight-client 1.0.1
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +4 -0
- data/LICENSE.md +675 -0
- data/README.md +160 -0
- data/Rakefile +29 -0
- data/bin/client.rb +291 -0
- data/lib/textflight-client.rb +33 -0
- data/lib/textflight-client/command_parser.rb +42 -0
- data/lib/textflight-client/dot_dir.rb +21 -0
- data/lib/textflight-client/environment.rb +55 -0
- data/lib/textflight-client/logging.rb +58 -0
- data/lib/textflight-client/models/local.rb +69 -0
- data/lib/textflight-client/models/model.rb +55 -0
- data/lib/textflight-client/models/nav.rb +293 -0
- data/lib/textflight-client/models/scan.rb +222 -0
- data/lib/textflight-client/models/status.rb +191 -0
- data/lib/textflight-client/models/status_report.rb +26 -0
- data/lib/textflight-client/response_parser.rb +200 -0
- data/lib/textflight-client/string_utils.rb +15 -0
- data/lib/textflight-client/tfprompt.rb +30 -0
- data/lib/textflight-client/version.rb +3 -0
- metadata +325 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
require "textflight-client/version"
|
2
|
+
require "textflight-client/logging"
|
3
|
+
require "textflight-client/environment"
|
4
|
+
require "textflight-client/dot_dir"
|
5
|
+
require "textflight-client/string_utils"
|
6
|
+
require "textflight-client/command_parser"
|
7
|
+
require "textflight-client/response_parser"
|
8
|
+
require "textflight-client/models/model"
|
9
|
+
require "textflight-client/models/nav"
|
10
|
+
require "textflight-client/models/scan"
|
11
|
+
require "textflight-client/models/status_report"
|
12
|
+
require "textflight-client/models/status"
|
13
|
+
require "textflight-client/models/local"
|
14
|
+
require "textflight-client/tfprompt"
|
15
|
+
|
16
|
+
module TFClient
|
17
|
+
|
18
|
+
# Prints a deprecated message that includes the line number.
|
19
|
+
#
|
20
|
+
# @param [String] version Indicates when the feature was deprecated.
|
21
|
+
# @param [String] msg Deprecation message (possibly suggesting alternatives)
|
22
|
+
# @return [void]
|
23
|
+
def self.deprecated(version, msg)
|
24
|
+
|
25
|
+
stack = Kernel.caller(0, 6)[1..-1].join("\n")
|
26
|
+
|
27
|
+
msg = "deprecated '#{version}' - #{msg}\n#{stack}"
|
28
|
+
|
29
|
+
$stderr.puts "\033[34mWARN: #{msg}\033[0m"
|
30
|
+
$stderr.flush
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module TFClient
|
2
|
+
class CommandParser
|
3
|
+
|
4
|
+
DIRECTION_MAP = {
|
5
|
+
n: "6",
|
6
|
+
ne: "7",
|
7
|
+
e: "4",
|
8
|
+
se: "2",
|
9
|
+
s: "1",
|
10
|
+
sw: "0",
|
11
|
+
w: "3",
|
12
|
+
nw: "5"
|
13
|
+
}
|
14
|
+
|
15
|
+
# 0: 315 degrees, X=-1, Y=-1 (northwest)
|
16
|
+
# 1: 0 degrees, X=0, Y=-1 (north)
|
17
|
+
# 2: 45 degrees, X=1, Y=-1 (northeast)
|
18
|
+
# 3: 270 degrees, X=-1, Y=0 (west)
|
19
|
+
# 4: 90 degrees, X=1, Y=0 (east)
|
20
|
+
# 5: 225 degrees, X=-1, Y=1 (southwest)
|
21
|
+
# 6: 180 degrees, X=0, Y=-1 (south)
|
22
|
+
# 7: 135 degrees, X=1, Y=-1 (southeast)
|
23
|
+
|
24
|
+
attr_reader :command
|
25
|
+
def initialize(command:)
|
26
|
+
@command = command
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse
|
30
|
+
if @command == "quit" || @command == "exit"
|
31
|
+
return "exit"
|
32
|
+
end
|
33
|
+
|
34
|
+
direction = DIRECTION_MAP[@command.to_sym]
|
35
|
+
if direction
|
36
|
+
"jump #{direction}"
|
37
|
+
else
|
38
|
+
@command
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
module TFClient::DotDir
|
3
|
+
|
4
|
+
def self.directory
|
5
|
+
home = TFClient::Environment.user_home_directory
|
6
|
+
dir = File.join(home, ".textflight", "client")
|
7
|
+
if !File.exist?(dir)
|
8
|
+
FileUtils.mkdir_p(dir)
|
9
|
+
end
|
10
|
+
dir
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.local_database_file(dev:)
|
14
|
+
if dev
|
15
|
+
File.expand_path(File.join(self.directory,"development.db"))
|
16
|
+
else
|
17
|
+
File.expand_path(File.join(self.directory,"production.db"))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
module TFClient
|
3
|
+
class Environment
|
4
|
+
|
5
|
+
# Returns the user home directory
|
6
|
+
def self.user_home_directory
|
7
|
+
require 'etc'
|
8
|
+
# If uid is omitted, the value from Passwd[:uid] is returned instead.
|
9
|
+
#noinspection RubyArgCount
|
10
|
+
Etc.getpwuid.dir
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns true if Windows environment
|
14
|
+
def self.windows_env?
|
15
|
+
if @@windows_env.nil?
|
16
|
+
@@windows_env = Environment.host_os_is_win?
|
17
|
+
end
|
18
|
+
|
19
|
+
@@windows_env
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns true if debugging is enabled.
|
23
|
+
def self.debug?
|
24
|
+
ENV['DEBUG'] == '1'
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# !@visibility private
|
30
|
+
def self.ci_var_defined?
|
31
|
+
value = ENV["CI"]
|
32
|
+
!!value && value != ''
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
# @visibility private
|
37
|
+
WIN_PATTERNS = [
|
38
|
+
/bccwin/i,
|
39
|
+
/cygwin/i,
|
40
|
+
/djgpp/i,
|
41
|
+
/mingw/i,
|
42
|
+
/mswin/i,
|
43
|
+
/wince/i,
|
44
|
+
]
|
45
|
+
|
46
|
+
# @!visibility private
|
47
|
+
@@windows_env = nil
|
48
|
+
|
49
|
+
# @!visibility private
|
50
|
+
def self.host_os_is_win?
|
51
|
+
ruby_platform = RbConfig::CONFIG["host_os"]
|
52
|
+
!!WIN_PATTERNS.find { |r| ruby_platform =~ r }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
|
2
|
+
module TFClient
|
3
|
+
|
4
|
+
# cyan
|
5
|
+
def self.log_unix_cmd(msg)
|
6
|
+
if ENV["DEBUG"] == "1"
|
7
|
+
puts Color.cyan("SHELL: #{msg}") if msg
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# blue
|
12
|
+
def self.warn(msg)
|
13
|
+
puts Color.blue(" WARN: #{msg}") if msg
|
14
|
+
end
|
15
|
+
|
16
|
+
# magenta
|
17
|
+
def self.debug(msg)
|
18
|
+
if ENV["DEBUG"] == "1"
|
19
|
+
puts Color.magenta("DEBUG: #{msg}") if msg
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# green
|
24
|
+
def self.info(msg)
|
25
|
+
puts Color.green(" INFO: #{msg}") if msg
|
26
|
+
end
|
27
|
+
|
28
|
+
# red
|
29
|
+
def self.error(msg)
|
30
|
+
puts Color.red("ERROR: #{msg}") if msg
|
31
|
+
end
|
32
|
+
|
33
|
+
module Color
|
34
|
+
def self.colorize(string, color)
|
35
|
+
"\033[#{color}m#{string}\033[0m"
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.red(string)
|
39
|
+
colorize(string, 31)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.blue(string)
|
43
|
+
colorize(string, 34)
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.magenta(string)
|
47
|
+
colorize(string, 35)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.cyan(string)
|
51
|
+
colorize(string, 36)
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.green(string)
|
55
|
+
colorize(string, 32)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
|
2
|
+
module TFClient
|
3
|
+
module Models
|
4
|
+
module Local
|
5
|
+
require "sequel"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module TFClient::Models::Local
|
11
|
+
|
12
|
+
require_relative "../../textflight-client/logging.rb"
|
13
|
+
require "json"
|
14
|
+
|
15
|
+
class Database
|
16
|
+
|
17
|
+
attr_reader :connection, :path
|
18
|
+
|
19
|
+
def initialize(path:)
|
20
|
+
@connection = Sequel.connect("sqlite://#{path}")
|
21
|
+
|
22
|
+
if !@connection.table_exists?(:systems)
|
23
|
+
@connection.create_table(:systems) do
|
24
|
+
primary_key :id
|
25
|
+
column :x, Integer
|
26
|
+
column :y, Integer
|
27
|
+
column :claimed_by, String
|
28
|
+
column :brightness, Integer
|
29
|
+
column :asteroid_ore, String
|
30
|
+
column :asteroid_density, Integer
|
31
|
+
column :links, String
|
32
|
+
column :planets, String
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def system_for_id(id:)
|
38
|
+
table = @connection[:systems]
|
39
|
+
table.where(id: id)
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_system(id:, nav:)
|
43
|
+
TFClient.info("creating a new system with id: #{id}")
|
44
|
+
|
45
|
+
links = nav.links.items.map do |link|
|
46
|
+
[link[:index], link[:direction], link[:drag], link[:faction]]
|
47
|
+
end
|
48
|
+
|
49
|
+
planets = nav.planets.items.map do |planet|
|
50
|
+
[planet[:index], planet[:type], planet[:name], planet[:faction]]
|
51
|
+
end
|
52
|
+
|
53
|
+
table = @connection[:systems]
|
54
|
+
table.insert(
|
55
|
+
{
|
56
|
+
id: id,
|
57
|
+
x: nav.coordinates.x,
|
58
|
+
y: nav.coordinates.y,
|
59
|
+
claimed_by: nav.claimed_by ? nav.claimed_by.faction : "",
|
60
|
+
brightness: nav.brightness.value,
|
61
|
+
asteroid_ore: nav.asteroids.ore,
|
62
|
+
asteroid_density: nav.asteroids.density,
|
63
|
+
links: JSON.generate(links),
|
64
|
+
planets: JSON.generate(planets)
|
65
|
+
}
|
66
|
+
)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
module TFClient
|
3
|
+
module Models
|
4
|
+
require "cousin_roman"
|
5
|
+
|
6
|
+
TABLE_OPTIONS = { padding: [0,1,0,1], width: 80, resize: true }
|
7
|
+
|
8
|
+
class Response
|
9
|
+
attr_accessor :lines, :response
|
10
|
+
|
11
|
+
def initialize(lines:)
|
12
|
+
@lines = lines.dup
|
13
|
+
@response = []
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Model
|
18
|
+
attr_accessor :label, :translation, :values_hash
|
19
|
+
|
20
|
+
def initialize(line:)
|
21
|
+
tokens = ResponseParser.tokenize_line(line: line)
|
22
|
+
tokens_hash = ResponseParser.label_and_translation(tokens: tokens)
|
23
|
+
@label = tokens_hash[:label]
|
24
|
+
@translation = tokens_hash[:translation]
|
25
|
+
@values_hash = ResponseParser.hash_from_line_values(line: line)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class ModelWithItems < Model
|
30
|
+
require "tty-table"
|
31
|
+
|
32
|
+
attr_reader :items
|
33
|
+
|
34
|
+
def count
|
35
|
+
@items.count
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
"#{@translation}: #{@items.map { |item| item[:string]}}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def items_to_s
|
43
|
+
@items.map { |item| "\t#{item[:string]}" }
|
44
|
+
end
|
45
|
+
|
46
|
+
def response_str
|
47
|
+
"#{@translation}:\n#{items_to_s.join("\n")}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def lines_offset
|
51
|
+
@items.length + 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,293 @@
|
|
1
|
+
|
2
|
+
module TFClient
|
3
|
+
module Models
|
4
|
+
class Nav < Response
|
5
|
+
|
6
|
+
GAME_LINK_TO_COMPASS_MAP = {
|
7
|
+
"0" => "sw",
|
8
|
+
"1" => "s",
|
9
|
+
"2" => "se",
|
10
|
+
"3" => "w",
|
11
|
+
"4" => "e",
|
12
|
+
"5" => "nw",
|
13
|
+
"6" => "n",
|
14
|
+
"7" => "ne"
|
15
|
+
}
|
16
|
+
|
17
|
+
COMPASS_TO_GAME_LINK_MAP = {
|
18
|
+
"n" => 6,
|
19
|
+
"ne" => 7,
|
20
|
+
"e" => 4,
|
21
|
+
"se" => 2,
|
22
|
+
"s" => 1,
|
23
|
+
"sw" => 0,
|
24
|
+
"w" => 3,
|
25
|
+
"nw" => 5
|
26
|
+
}
|
27
|
+
|
28
|
+
COMPASS_ORDER = {
|
29
|
+
"n" => 0,
|
30
|
+
"ne" => 1,
|
31
|
+
"e" => 2,
|
32
|
+
"se" => 3,
|
33
|
+
"s" => 4,
|
34
|
+
"sw" => 5,
|
35
|
+
"w" => 6,
|
36
|
+
"nw" => 7
|
37
|
+
}
|
38
|
+
|
39
|
+
LINE_IDENTIFIER = [
|
40
|
+
"Coordinates",
|
41
|
+
"Claimed by",
|
42
|
+
"Brightness",
|
43
|
+
"Asteroids",
|
44
|
+
"Links",
|
45
|
+
"Planets",
|
46
|
+
"Structures"
|
47
|
+
].freeze
|
48
|
+
|
49
|
+
attr_reader :coordinates, :claimed_by, :brightness, :asteroids
|
50
|
+
attr_reader :links, :planets, :structures
|
51
|
+
|
52
|
+
def initialize(lines:)
|
53
|
+
super(lines: lines)
|
54
|
+
|
55
|
+
LINE_IDENTIFIER.each_with_index do |label, label_index|
|
56
|
+
var_name = ResponseParser.snake_case_sym_from_string(string: label)
|
57
|
+
class_name = ResponseParser.camel_case_from_string(string: label)
|
58
|
+
|
59
|
+
clazz = ResponseParser.model_class_from_string(string: class_name)
|
60
|
+
if clazz.nil?
|
61
|
+
raise "could not find class name: #{class_name}"
|
62
|
+
end
|
63
|
+
|
64
|
+
line, _ = ResponseParser.line_and_index_for_beginning_with(lines: @lines,
|
65
|
+
string: label)
|
66
|
+
|
67
|
+
next if line.nil?
|
68
|
+
|
69
|
+
if label_index < 4
|
70
|
+
var = clazz.new(line: line)
|
71
|
+
else
|
72
|
+
var = clazz.new(lines: @lines)
|
73
|
+
end
|
74
|
+
|
75
|
+
instance_variable_set("@#{var_name}", var)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def response
|
80
|
+
puts @planets
|
81
|
+
|
82
|
+
puts @links
|
83
|
+
table = TTY::Table.new(rows: [[
|
84
|
+
"#{@brightness.to_s}",
|
85
|
+
"#{@asteroids.to_s}",
|
86
|
+
"#{@coordinates}"]
|
87
|
+
])
|
88
|
+
|
89
|
+
puts table.render(:ascii, Models::TABLE_OPTIONS) do |renderer|
|
90
|
+
renderer.alignments= [:left, :center, :right]
|
91
|
+
end
|
92
|
+
|
93
|
+
puts @structures
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_s
|
97
|
+
"#<Nav: #{@coordinates.to_s}>"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class Coordinates < Model
|
102
|
+
attr_reader :x, :y
|
103
|
+
|
104
|
+
def initialize(line:)
|
105
|
+
super(line: line)
|
106
|
+
@x = @values_hash[:x].to_i
|
107
|
+
@y = @values_hash[:y].to_i
|
108
|
+
end
|
109
|
+
|
110
|
+
def to_s
|
111
|
+
%Q[#{@translation}: (#{@x},#{@y})]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class ClaimedBy < Model
|
116
|
+
attr_reader :faction
|
117
|
+
|
118
|
+
def initialize(line:)
|
119
|
+
super(line: line)
|
120
|
+
@faction = @values_hash[:faction]
|
121
|
+
end
|
122
|
+
|
123
|
+
def to_s
|
124
|
+
%Q[#{@translation} '#{@faction}']
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class Brightness < Model
|
129
|
+
attr_reader :value, :percent
|
130
|
+
|
131
|
+
def initialize(line:)
|
132
|
+
super(line: line)
|
133
|
+
@value = @values_hash[:brightness].to_i
|
134
|
+
@percent = ((@value/255.0) * 100).round
|
135
|
+
end
|
136
|
+
|
137
|
+
def to_s
|
138
|
+
%Q[#{@translation}: #{@value} => #{@percent}%]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
class Asteroids < Model
|
143
|
+
attr_reader :ore, :density, :percent
|
144
|
+
|
145
|
+
def initialize(line:)
|
146
|
+
super(line: line)
|
147
|
+
@ore = @values_hash[:asteroid_type]
|
148
|
+
@density = @values_hash[:asteroid_density].to_i
|
149
|
+
@percent = ((@density/7.0) * 100).round
|
150
|
+
end
|
151
|
+
|
152
|
+
def to_s
|
153
|
+
%Q[#{@translation}: #{@ore} (#{@density}) => #{@percent}%]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class Links < ModelWithItems
|
158
|
+
def initialize(lines:)
|
159
|
+
line, index = ResponseParser.line_and_index_for_beginning_with(lines: lines,
|
160
|
+
string: "Links")
|
161
|
+
super(line: line)
|
162
|
+
items = ResponseParser.collect_list_items(lines: lines, start_index: index + 1)
|
163
|
+
@items = items.map do |item|
|
164
|
+
line = item.strip
|
165
|
+
hash = ResponseParser.hash_from_line_values(line: line)
|
166
|
+
|
167
|
+
index = hash[:index].to_i
|
168
|
+
faction = hash[:faction]
|
169
|
+
drag = hash[:link_drag].to_i
|
170
|
+
|
171
|
+
# direction is WIP
|
172
|
+
direction = Nav::GAME_LINK_TO_COMPASS_MAP[index.to_s]
|
173
|
+
{
|
174
|
+
index: index, drag: drag, direction: direction, faction: faction
|
175
|
+
}
|
176
|
+
end.sort do |a, b|
|
177
|
+
Nav::COMPASS_ORDER[a[:direction]] <=> Nav::COMPASS_ORDER[b[:direction]]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def to_s
|
182
|
+
table = TTY::Table.new(header: [
|
183
|
+
{value: "#{@translation}", alignment: :right},
|
184
|
+
{value: "drag", alignment: :center},
|
185
|
+
{value: "faction", alignment: :center},
|
186
|
+
{value: "original", alignment: :center},
|
187
|
+
{value: "direction", alignment: :center}
|
188
|
+
])
|
189
|
+
|
190
|
+
@items.each do |item|
|
191
|
+
table << [
|
192
|
+
"#{item[:direction]}",
|
193
|
+
item[:drag],
|
194
|
+
item[:faction],
|
195
|
+
"[#{item[:index]}]",
|
196
|
+
"#{item[:direction]}"
|
197
|
+
]
|
198
|
+
end
|
199
|
+
|
200
|
+
table.render(:ascii, Models::TABLE_OPTIONS) do |renderer|
|
201
|
+
renderer.alignments= [:right, :right, :center, :center, :center, :center]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
class Planets < ModelWithItems
|
207
|
+
|
208
|
+
def initialize(lines:)
|
209
|
+
line, index = ResponseParser.line_and_index_for_beginning_with(lines: lines,
|
210
|
+
string: "Planets")
|
211
|
+
super(line: line)
|
212
|
+
|
213
|
+
items = ResponseParser.collect_list_items(lines: lines, start_index: index + 1)
|
214
|
+
@items = items.map do |item|
|
215
|
+
line = item.strip
|
216
|
+
|
217
|
+
hash = ResponseParser.hash_from_line_values(line: line)
|
218
|
+
|
219
|
+
index = hash[:index].to_i
|
220
|
+
type = hash[:planet_type]
|
221
|
+
name = hash[:name]
|
222
|
+
faction = hash[:faction]
|
223
|
+
|
224
|
+
{ index: index, type: type, name: name, faction: faction }
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def to_s
|
229
|
+
return "" if @items.empty?
|
230
|
+
table = TTY::Table.new(header: [
|
231
|
+
{value: "#{@translation}", alignment: :right},
|
232
|
+
{value: "type", alignment: :center},
|
233
|
+
{value: "name", alignment: :center},
|
234
|
+
{value: "faction", alignment: :center},
|
235
|
+
{value: "index", alignment: :center}
|
236
|
+
])
|
237
|
+
|
238
|
+
@items.each do |item|
|
239
|
+
table << [
|
240
|
+
"[#{item[:index]}]",
|
241
|
+
item[:type],
|
242
|
+
item[:name],
|
243
|
+
item[:faction],
|
244
|
+
"[#{item[:index]}]"
|
245
|
+
]
|
246
|
+
end
|
247
|
+
|
248
|
+
table.render(:ascii, Models::TABLE_OPTIONS) do |renderer|
|
249
|
+
renderer.alignments= [:right, :right, :center, :center, :center]
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
class Structures < ModelWithItems
|
255
|
+
|
256
|
+
def initialize(lines:)
|
257
|
+
line, index = ResponseParser.line_and_index_for_beginning_with(lines: lines,
|
258
|
+
string: "Structures")
|
259
|
+
super(line: line)
|
260
|
+
|
261
|
+
items = ResponseParser.collect_list_items(lines: lines, start_index: index + 1)
|
262
|
+
@items = items.map do |item|
|
263
|
+
line = item.strip
|
264
|
+
|
265
|
+
hash = ResponseParser.hash_from_line_values(line: line)
|
266
|
+
|
267
|
+
id = hash[:id].to_i
|
268
|
+
name = hash[:name]
|
269
|
+
# TODO: distinguish shipyards from bases
|
270
|
+
type = hash[:sclass] || "base"
|
271
|
+
{ id: id, name: name, type: type }
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def to_s
|
276
|
+
table = TTY::Table.new(header: [
|
277
|
+
{value: "#{@translation}", alignment: :right},
|
278
|
+
{value: "name", alignment: :center},
|
279
|
+
{value: "ship class", alignment: :center},
|
280
|
+
{value: "id", alignment: :center }
|
281
|
+
])
|
282
|
+
|
283
|
+
@items.each do |item|
|
284
|
+
table << ["[#{item[:id]}]", item[:name], item[:type], "[#{item[:id]}]"]
|
285
|
+
end
|
286
|
+
|
287
|
+
table.render(:ascii, Models::TABLE_OPTIONS) do |renderer|
|
288
|
+
renderer.alignments= [:right, :right, :center, :center]
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|