software_challenge_client 20.2.1 → 21.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 +4 -4
- data/.rubocop.yml +1 -0
- data/.ruby-version +1 -1
- data/.vscode/launch.json +41 -0
- data/.vscode/settings.json +10 -0
- data/Dockerfile +1 -1
- data/Gemfile +1 -0
- data/Guardfile +1 -0
- data/README.md +4 -3
- data/RELEASES.md +20 -0
- data/Rakefile +4 -4
- data/example/client.rb +6 -9
- data/example/main.rb +9 -9
- data/lib/software_challenge_client.rb +26 -23
- data/lib/software_challenge_client/board.rb +99 -34
- data/lib/software_challenge_client/client_interface.rb +1 -0
- data/lib/software_challenge_client/color.rb +16 -0
- data/lib/software_challenge_client/condition.rb +4 -1
- data/lib/software_challenge_client/coordinate_set.rb +92 -0
- data/lib/software_challenge_client/coordinates.rb +45 -0
- data/lib/software_challenge_client/debug_hint.rb +1 -0
- data/lib/software_challenge_client/field.rb +21 -53
- data/lib/software_challenge_client/game_rule_logic.rb +257 -328
- data/lib/software_challenge_client/game_state.rb +86 -68
- data/lib/software_challenge_client/has_hints.rb +1 -1
- data/lib/software_challenge_client/invalid_move_exception.rb +1 -0
- data/lib/software_challenge_client/logging.rb +1 -0
- data/lib/software_challenge_client/network.rb +1 -1
- data/lib/software_challenge_client/piece.rb +43 -14
- data/lib/software_challenge_client/piece_shape.rb +109 -0
- data/lib/software_challenge_client/player.rb +7 -6
- data/lib/software_challenge_client/player_type.rb +14 -0
- data/lib/software_challenge_client/protocol.rb +82 -76
- data/lib/software_challenge_client/rotation.rb +22 -0
- data/lib/software_challenge_client/runner.rb +2 -1
- data/lib/software_challenge_client/set_move.rb +13 -4
- data/lib/software_challenge_client/skip_move.rb +5 -0
- data/lib/software_challenge_client/util/constants.rb +3 -4
- data/lib/software_challenge_client/version.rb +2 -1
- data/lib/update_client_module.sh +15 -0
- data/software_challenge_client.gemspec +15 -13
- metadata +54 -36
- data/lib/software_challenge_client/cube_coordinates.rb +0 -23
- data/lib/software_challenge_client/direction.rb +0 -55
- data/lib/software_challenge_client/drag_move.rb +0 -19
- data/lib/software_challenge_client/line_direction.rb +0 -15
- data/lib/software_challenge_client/piece_type.rb +0 -18
- data/lib/software_challenge_client/player_color.rb +0 -25
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
# Ein Spieler
|
|
4
5
|
class Player
|
|
@@ -6,15 +7,15 @@ class Player
|
|
|
6
7
|
# @return [String] der Name des Spielers, hat keine Auswirkungen auf das Spiel
|
|
7
8
|
attr_reader :name
|
|
8
9
|
|
|
9
|
-
# @!attribute [r]
|
|
10
|
-
# @return [
|
|
11
|
-
attr_reader :
|
|
10
|
+
# @!attribute [r] type
|
|
11
|
+
# @return [PlayerType] erster (PlayerType::ONE) oder zweiter (PlayerType::TWO) Spieler
|
|
12
|
+
attr_reader :type
|
|
12
13
|
|
|
13
14
|
# Konstruktor
|
|
14
|
-
# @param
|
|
15
|
+
# @param type [PlayerType] Erster oder zweiter
|
|
15
16
|
# @param name [String] Name
|
|
16
|
-
def initialize(
|
|
17
|
-
@
|
|
17
|
+
def initialize(type, name)
|
|
18
|
+
@type = type
|
|
18
19
|
@name = name
|
|
19
20
|
end
|
|
20
21
|
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
require 'socket'
|
|
4
4
|
require_relative 'board'
|
|
5
5
|
require_relative 'set_move'
|
|
6
|
-
require_relative 'drag_move'
|
|
7
6
|
require_relative 'skip_move'
|
|
8
7
|
require_relative 'player'
|
|
9
8
|
require_relative 'network'
|
|
@@ -41,7 +40,7 @@ class Protocol
|
|
|
41
40
|
#
|
|
42
41
|
# @param text [String] the xml-string that will be parsed
|
|
43
42
|
def process_string(text)
|
|
44
|
-
logger.debug "Parse XML:\n#{text}\n----END XML"
|
|
43
|
+
#logger.debug "Parse XML:\n#{text}\n----END XML"
|
|
45
44
|
begin
|
|
46
45
|
REXML::Document.parse_stream(text, self)
|
|
47
46
|
rescue REXML::ParseException => e
|
|
@@ -50,7 +49,6 @@ class Protocol
|
|
|
50
49
|
end
|
|
51
50
|
end
|
|
52
51
|
|
|
53
|
-
|
|
54
52
|
# called when text is encountered
|
|
55
53
|
def text(text)
|
|
56
54
|
@context[:last_text] = text
|
|
@@ -63,6 +61,33 @@ class Protocol
|
|
|
63
61
|
case name
|
|
64
62
|
when 'board'
|
|
65
63
|
logger.debug @gamestate.board.to_s
|
|
64
|
+
when 'color'
|
|
65
|
+
if @context[:color] == :ordered_colors
|
|
66
|
+
@gamestate.ordered_colors << Color.to_a.find {|s| s.key == @context[:last_text].to_sym }
|
|
67
|
+
end
|
|
68
|
+
when 'shape'
|
|
69
|
+
case @context[:piece_target]
|
|
70
|
+
when :blue_shapes
|
|
71
|
+
last = @context[:last_text]
|
|
72
|
+
arr = PieceShape.to_a
|
|
73
|
+
shape = arr.find {|s| s.key == @context[:last_text].to_sym }
|
|
74
|
+
@gamestate.undeployed_blue_pieces << shape
|
|
75
|
+
when :yellow_shapes
|
|
76
|
+
shape = PieceShape.to_a.find {|s| s.key == @context[:last_text].to_sym }
|
|
77
|
+
@gamestate.undeployed_yellow_pieces << shape
|
|
78
|
+
when :red_shapes
|
|
79
|
+
shape = PieceShape.to_a.find {|s| s.key == @context[:last_text].to_sym }
|
|
80
|
+
@gamestate.undeployed_red_pieces << shape
|
|
81
|
+
when :green_shapes
|
|
82
|
+
shape = PieceShape.to_a.find {|s| s.key == @context[:last_text].to_sym }
|
|
83
|
+
@gamestate.undeployed_green_pieces << shape
|
|
84
|
+
end
|
|
85
|
+
when 'yellowShapes'
|
|
86
|
+
|
|
87
|
+
when 'redShapes'
|
|
88
|
+
|
|
89
|
+
when 'greenShapes'
|
|
90
|
+
|
|
66
91
|
end
|
|
67
92
|
end
|
|
68
93
|
|
|
@@ -97,59 +122,69 @@ class Protocol
|
|
|
97
122
|
when 'state'
|
|
98
123
|
logger.debug 'new gamestate'
|
|
99
124
|
@gamestate = GameState.new
|
|
125
|
+
@gamestate.current_color_index = attrs['currentColorIndex'].to_i
|
|
100
126
|
@gamestate.turn = attrs['turn'].to_i
|
|
101
|
-
@gamestate.
|
|
102
|
-
@gamestate.
|
|
103
|
-
logger.debug "Turn: #{@gamestate.turn}"
|
|
104
|
-
when '
|
|
105
|
-
logger.debug 'new
|
|
106
|
-
player =
|
|
107
|
-
if player.color != PlayerColor::RED
|
|
108
|
-
throw new IllegalArgumentException("expected #{PlayerColor::RED} Player but got #{player.color}")
|
|
109
|
-
end
|
|
127
|
+
@gamestate.round = attrs['round'].to_i
|
|
128
|
+
@gamestate.start_piece = PieceShape.to_a.find {|s| s.key == attrs['startPiece'].to_sym }
|
|
129
|
+
logger.debug "Round: #{@gamestate.round}, Turn: #{@gamestate.turn}"
|
|
130
|
+
when 'first'
|
|
131
|
+
logger.debug 'new first player'
|
|
132
|
+
player = Player.new(PlayerType::ONE, attrs['displayName'])
|
|
110
133
|
@gamestate.add_player(player)
|
|
111
134
|
@context[:player] = player
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
throw new IllegalArgumentException("expected #{PlayerColor::BLUE} Player but got #{player.color}")
|
|
117
|
-
end
|
|
135
|
+
@context[:color] = :one
|
|
136
|
+
when 'second'
|
|
137
|
+
logger.debug 'new second player'
|
|
138
|
+
player = Player.new(PlayerType::TWO, attrs['displayName'])
|
|
118
139
|
@gamestate.add_player(player)
|
|
119
140
|
@context[:player] = player
|
|
141
|
+
@context[:color] = :two
|
|
142
|
+
when 'orderedColors'
|
|
143
|
+
@context[:color] = :ordered_colors
|
|
144
|
+
@gamestate.ordered_colors = []
|
|
120
145
|
when 'board'
|
|
121
146
|
logger.debug 'new board'
|
|
122
|
-
@gamestate.board = Board.new
|
|
147
|
+
@gamestate.board = Board.new()
|
|
123
148
|
when 'field'
|
|
124
149
|
x = attrs['x'].to_i
|
|
125
150
|
y = attrs['y'].to_i
|
|
126
|
-
|
|
127
|
-
field = Field.new(x, y,
|
|
151
|
+
color = Color.find_by_key(attrs['content'].to_sym)
|
|
152
|
+
field = Field.new(x, y, color)
|
|
128
153
|
@gamestate.board.add_field(field)
|
|
129
154
|
@context[:piece_target] = :field
|
|
130
155
|
@context[:field] = field
|
|
156
|
+
when 'blueShapes'
|
|
157
|
+
@context[:piece_target] = :blue_shapes
|
|
158
|
+
@gamestate.undeployed_blue_pieces = []
|
|
159
|
+
when 'yellowShapes'
|
|
160
|
+
@context[:piece_target] = :yellow_shapes
|
|
161
|
+
@gamestate.undeployed_yellow_pieces = []
|
|
162
|
+
when 'redShapes'
|
|
163
|
+
@context[:piece_target] = :red_shapes
|
|
164
|
+
@gamestate.undeployed_red_pieces = []
|
|
165
|
+
when 'greenShapes'
|
|
166
|
+
@context[:piece_target] = :green_shapes
|
|
167
|
+
@gamestate.undeployed_green_pieces = []
|
|
131
168
|
when 'piece'
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
169
|
+
color = Color.find_by_key(attrs['color'].to_sym)
|
|
170
|
+
kind = PieceShape.find_by_key(attrs['kind'].to_sym)
|
|
171
|
+
rotation = Rotation.find_by_key(attrs['rotation'].to_sym)
|
|
172
|
+
is_flipped = attrs['isFlipped'].downcase == "true"
|
|
173
|
+
piece = Piece.new(color, kind, rotation, is_flipped, Coordinates.origin)
|
|
135
174
|
case @context[:piece_target]
|
|
136
|
-
when :
|
|
137
|
-
@context[:field].add_piece(piece)
|
|
138
|
-
when :undeployed_red_pieces
|
|
139
|
-
@gamestate.undeployed_red_pieces << piece
|
|
140
|
-
when :undeployed_blue_pieces
|
|
175
|
+
when :blue_shapes
|
|
141
176
|
@gamestate.undeployed_blue_pieces << piece
|
|
177
|
+
when :yellow_shapes
|
|
178
|
+
@gamestate.undeployed_yellow_pieces << piece
|
|
179
|
+
when :red_shapes
|
|
180
|
+
@gamestate.green_red_pieces << piece
|
|
181
|
+
when :green_shapes
|
|
182
|
+
@gamestate.undeployed_green_pieces << piece
|
|
142
183
|
when :last_move
|
|
143
184
|
@context[:last_move_piece] = piece
|
|
144
185
|
else
|
|
145
186
|
raise "unknown piece target #{@context[:piece_target]}"
|
|
146
187
|
end
|
|
147
|
-
when 'undeployedRedPieces'
|
|
148
|
-
@context[:piece_target] = :undeployed_red_pieces
|
|
149
|
-
@gamestate.undeployed_red_pieces = []
|
|
150
|
-
when 'undeployedBluePieces'
|
|
151
|
-
@context[:piece_target] = :undeployed_blue_pieces
|
|
152
|
-
@gamestate.undeployed_blue_pieces = []
|
|
153
188
|
when 'lastMove'
|
|
154
189
|
type = attrs['class']
|
|
155
190
|
if type == 'skipmove'
|
|
@@ -158,24 +193,16 @@ class Protocol
|
|
|
158
193
|
@context[:last_move_type] = type
|
|
159
194
|
@context[:piece_target] = :last_move
|
|
160
195
|
end
|
|
161
|
-
when '
|
|
162
|
-
@
|
|
163
|
-
when 'destination'
|
|
164
|
-
destination = CubeCoordinates.new(attrs['x'].to_i, attrs['y'].to_i, attrs['z'].to_i)
|
|
165
|
-
case @context[:last_move_type]
|
|
166
|
-
when 'setmove'
|
|
167
|
-
@gamestate.last_move = SetMove.new(@context[:last_move_piece], destination)
|
|
168
|
-
when 'dragmove'
|
|
169
|
-
@gamestate.last_move = SetMove.new(@context[:last_move_start], destination)
|
|
170
|
-
end
|
|
196
|
+
when 'startColor'
|
|
197
|
+
@gamestate.start_color = Color::BLUE
|
|
171
198
|
when 'winner'
|
|
172
|
-
|
|
173
|
-
#winning_player = parsePlayer(attrs)
|
|
174
|
-
|
|
199
|
+
# TODO
|
|
200
|
+
# winning_player = parsePlayer(attrs)
|
|
201
|
+
# @gamestate.condition = Condition.new(winning_player, @gamestate.condition.reason)
|
|
175
202
|
when 'score'
|
|
176
203
|
# TODO
|
|
177
204
|
# there are two score tags in the result, but reason attribute should be equal on both
|
|
178
|
-
|
|
205
|
+
# @gamestate.condition = Condition.new(@gamestate.condition.winner, attrs['reason'])
|
|
179
206
|
when 'left'
|
|
180
207
|
logger.debug 'got left event, terminating'
|
|
181
208
|
@network.disconnect
|
|
@@ -185,17 +212,6 @@ class Protocol
|
|
|
185
212
|
end
|
|
186
213
|
end
|
|
187
214
|
|
|
188
|
-
# Converts XML attributes for a Player to a new Player object
|
|
189
|
-
#
|
|
190
|
-
# @param attributes [Hash] Attributes for the new Player.
|
|
191
|
-
# @return [Player] The created Player object.
|
|
192
|
-
def parsePlayer(attributes)
|
|
193
|
-
Player.new(
|
|
194
|
-
PlayerColor.find_by_key(attributes['color'].to_sym),
|
|
195
|
-
attributes['displayName']
|
|
196
|
-
)
|
|
197
|
-
end
|
|
198
|
-
|
|
199
215
|
# send a xml document
|
|
200
216
|
#
|
|
201
217
|
# @param document [REXML::Document] the document, that will be send to the connected server
|
|
@@ -205,7 +221,7 @@ class Protocol
|
|
|
205
221
|
|
|
206
222
|
# send a string
|
|
207
223
|
#
|
|
208
|
-
# @param
|
|
224
|
+
# @param string [String] The string that will be send to the connected server.
|
|
209
225
|
def sendString(string)
|
|
210
226
|
@network.sendString("<room roomId=\"#{@roomId}\">#{string}</room>")
|
|
211
227
|
end
|
|
@@ -228,26 +244,17 @@ class Protocol
|
|
|
228
244
|
# structures.
|
|
229
245
|
case move
|
|
230
246
|
when SetMove
|
|
231
|
-
builder.data(class: '
|
|
232
|
-
data.piece(
|
|
233
|
-
|
|
234
|
-
data.destination(x: d.x, y: d.y, z: d.z)
|
|
235
|
-
move.hints.each do |hint|
|
|
236
|
-
data.hint(content: hint.content)
|
|
247
|
+
builder.data(class: 'sc.plugin2021.SetMove') do |data|
|
|
248
|
+
data.piece(color: move.piece.color, kind: move.piece.kind, rotation: move.piece.rotation, isFlipped: move.piece.is_flipped) do |piece|
|
|
249
|
+
piece.position(x: move.piece.position.x, y: move.piece.position.y)
|
|
237
250
|
end
|
|
238
|
-
end
|
|
239
|
-
when DragMove
|
|
240
|
-
builder.data(class: 'dragmove') do |data|
|
|
241
|
-
s = move.start
|
|
242
|
-
data.start(x: s.x, y: s.y, z: s.z)
|
|
243
|
-
d = move.destination
|
|
244
|
-
data.destination(x: d.x, y: d.y, z: d.z)
|
|
245
251
|
move.hints.each do |hint|
|
|
246
252
|
data.hint(content: hint.content)
|
|
247
253
|
end
|
|
248
254
|
end
|
|
249
255
|
when SkipMove
|
|
250
|
-
builder.data(class: '
|
|
256
|
+
builder.data(class: 'sc.plugin2021.SkipMove') do |data|
|
|
257
|
+
data.color(@gamestate.current_color.key.to_s)
|
|
251
258
|
move.hints.each do |hint|
|
|
252
259
|
data.hint(content: hint.content)
|
|
253
260
|
end
|
|
@@ -255,5 +262,4 @@ class Protocol
|
|
|
255
262
|
end
|
|
256
263
|
builder.target!
|
|
257
264
|
end
|
|
258
|
-
|
|
259
265
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'typesafe_enum'
|
|
4
|
+
|
|
5
|
+
# Die Drehung eines Steins
|
|
6
|
+
class Rotation < TypesafeEnum::Base
|
|
7
|
+
new :NONE, 0
|
|
8
|
+
new :RIGHT, 1
|
|
9
|
+
new :MIRROR, 2
|
|
10
|
+
new :LEFT, 3
|
|
11
|
+
|
|
12
|
+
# Summiere beide Rotationen auf.
|
|
13
|
+
# (Die resultierende Rotation hat den gleichen Effekt wie die beiden Rotationen einzeln).
|
|
14
|
+
def rotate(rotation)
|
|
15
|
+
Rotation.to_a[(value + rotation.value) % Rotation.size]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Gibt den rotation namen zurück
|
|
19
|
+
def to_s
|
|
20
|
+
self.key.to_s
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
require_relative 'board'
|
|
3
4
|
require_relative 'client_interface'
|
|
4
5
|
require_relative 'network'
|
|
@@ -8,7 +9,7 @@ class Runner
|
|
|
8
9
|
include Logging
|
|
9
10
|
|
|
10
11
|
def initialize(host, port, client, reservation = nil)
|
|
11
|
-
logger.info 'Software Challenge
|
|
12
|
+
logger.info 'Software Challenge 2021'
|
|
12
13
|
logger.info 'Ruby Client'
|
|
13
14
|
logger.info "Host: #{host}"
|
|
14
15
|
logger.info "Port: #{port}"
|
|
@@ -1,15 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require_relative 'has_hints'
|
|
2
4
|
|
|
5
|
+
# Ein SetMove platziert einen Stein auf dem Spielbrett
|
|
3
6
|
class SetMove
|
|
4
|
-
|
|
5
7
|
include HasHints
|
|
6
8
|
|
|
7
9
|
attr_reader :piece
|
|
8
|
-
attr_reader :destination
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
# Erstellt ein neuen leeren Legezug.
|
|
12
|
+
def initialize(piece)
|
|
11
13
|
@piece = piece
|
|
12
|
-
@destination = destination
|
|
13
14
|
@hints = []
|
|
14
15
|
end
|
|
16
|
+
|
|
17
|
+
def ==(other)
|
|
18
|
+
piece == other.piece
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def to_s
|
|
22
|
+
"SetMove(#{piece}"
|
|
23
|
+
end
|
|
15
24
|
end
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require_relative 'has_hints'
|
|
4
|
+
|
|
5
|
+
# Ein SkipMove ziegt an, dass die aktuelle Farbe keinen Stein platzieren will
|
|
2
6
|
class SkipMove
|
|
3
7
|
include HasHints
|
|
4
8
|
|
|
9
|
+
# Erstellt ein neuen leeren Aussetzzug.
|
|
5
10
|
def initialize
|
|
6
11
|
@hints = []
|
|
7
12
|
end
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
# Konstanten zum aktuellen Spiel.
|
|
5
5
|
module Constants
|
|
6
6
|
ROUND_LIMIT = 30 # Rundenbegrenzung. Nach Ende der angegebenen Runde endet auch das Spiel.
|
|
7
|
-
GAME_IDENTIFIER = '
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
SHIFT = ((BOARD_SIZE - 1) / 2)
|
|
7
|
+
GAME_IDENTIFIER = 'swc_2021_blokus' # Der Identifikator des Spiels. Für die Kommunikation mit dem Spielserver.
|
|
8
|
+
BOARD_SIZE = 20 # Seitenlänge des Spielbretts in Feldern
|
|
9
|
+
TOTAL_PIECE_SHAPES = 21
|
|
11
10
|
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# This creates a entrypoint for the gem named 'software_challenge_client.rb'
|
|
3
|
+
# which includes all ruby files under lib. Making sure that everthing is
|
|
4
|
+
# included after some files were added or removed (in the process of updating
|
|
5
|
+
# the gem for a new game).
|
|
6
|
+
shopt -s globstar || exit 1
|
|
7
|
+
cd lib || exit 1
|
|
8
|
+
FILENAME='software_challenge_client.rb'
|
|
9
|
+
|
|
10
|
+
echo "# frozen_string_literal: true
|
|
11
|
+
module SoftwareChallengeClient" > $FILENAME
|
|
12
|
+
for file in software_challenge_client/**/*.rb; do
|
|
13
|
+
echo " require '${file}'"
|
|
14
|
+
done >> $FILENAME;
|
|
15
|
+
echo "end" >> $FILENAME
|
|
@@ -1,39 +1,41 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
5
|
require 'software_challenge_client/version'
|
|
5
6
|
|
|
6
7
|
Gem::Specification.new do |spec|
|
|
7
|
-
spec.name =
|
|
8
|
+
spec.name = 'software_challenge_client'
|
|
8
9
|
spec.version = SoftwareChallengeClient::VERSION
|
|
9
10
|
spec.authors = File.readlines('AUTHORS').select { |l| l[' <'] }.map { |l| l.match(/^(.*) *</)[1] }
|
|
10
11
|
spec.email = File.readlines('AUTHORS').select { |l| l[' <'] }.map { |l| l.match(/<(.*)>/)[1] }
|
|
11
12
|
|
|
12
|
-
spec.summary = '
|
|
13
|
+
spec.summary = 'Provides functions to build a client for the coding competition Software-Challenge Germany.'
|
|
13
14
|
spec.description = ''
|
|
14
15
|
spec.homepage = 'http://www.software-challenge.de'
|
|
15
16
|
|
|
16
17
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
17
|
-
spec.bindir =
|
|
18
|
+
spec.bindir = 'exe'
|
|
18
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
19
|
-
spec.require_paths = [
|
|
20
|
+
spec.require_paths = ['lib']
|
|
20
21
|
|
|
21
|
-
spec.required_ruby_version = '>= 2.
|
|
22
|
-
spec.add_dependency 'typesafe_enum'
|
|
22
|
+
spec.required_ruby_version = '>= 2.5.5'
|
|
23
23
|
spec.add_dependency 'builder'
|
|
24
|
+
spec.add_dependency 'typesafe_enum'
|
|
24
25
|
|
|
25
26
|
spec.add_development_dependency 'bundler', '>= 1.10'
|
|
26
|
-
spec.add_development_dependency 'rake', '>= 10.0'
|
|
27
|
-
spec.add_development_dependency 'yard', '>= 0.8'
|
|
28
|
-
spec.add_development_dependency 'rspec'
|
|
29
27
|
spec.add_development_dependency 'fuubar'
|
|
30
|
-
spec.add_development_dependency 'rubocop'
|
|
31
|
-
spec.add_development_dependency 'rubocop-rspec'
|
|
32
28
|
spec.add_development_dependency 'guard'
|
|
33
29
|
spec.add_development_dependency 'guard-rspec'
|
|
34
30
|
spec.add_development_dependency 'guard-rubocop'
|
|
35
31
|
spec.add_development_dependency 'pry'
|
|
36
|
-
spec.add_development_dependency 'pry-rescue'
|
|
37
|
-
spec.add_development_dependency 'pry-coolline'
|
|
38
32
|
spec.add_development_dependency 'pry-byebug'
|
|
33
|
+
spec.add_development_dependency 'pry-coolline'
|
|
34
|
+
spec.add_development_dependency 'pry-rescue'
|
|
35
|
+
spec.add_development_dependency 'rake', '>= 10.0'
|
|
36
|
+
spec.add_development_dependency 'rspec'
|
|
37
|
+
spec.add_development_dependency 'rubocop'
|
|
38
|
+
spec.add_development_dependency 'rubocop-rspec'
|
|
39
|
+
spec.add_development_dependency 'solargraph'
|
|
40
|
+
spec.add_development_dependency 'yard', '>= 0.8'
|
|
39
41
|
end
|