software_challenge_client 20.2.4 → 21.2.0
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 -3
- 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 +94 -37
- 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 +2 -0
- 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 -56
- data/lib/software_challenge_client/game_rule_logic.rb +258 -335
- data/lib/software_challenge_client/game_state.rb +106 -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 +71 -13
- 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 +81 -74
- 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 -25
- data/lib/software_challenge_client/direction.rb +0 -55
- data/lib/software_challenge_client/drag_move.rb +0 -22
- 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,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
require_relative './util/constants'
|
@@ -15,36 +14,62 @@ class GameState
|
|
15
14
|
# @!attribute [rw] turn
|
16
15
|
# @return [Integer] Aktuelle Zugnummer (von 0 beginnend)
|
17
16
|
attr_accessor :turn
|
18
|
-
# @!attribute [rw] start_player_color
|
19
|
-
# @return [PlayerColor] Die Farbe des Spielers, der den ersten Zug im Spiel
|
20
|
-
# machen darf.
|
21
|
-
attr_accessor :start_player_color
|
22
|
-
# @!attribute [rw] current_player_color
|
23
|
-
# @return [PlayerColor] Die Farbe des Spielers, der den nächsten Zug machen
|
24
|
-
# darf, der also gerade an der Reihe ist.
|
25
|
-
attr_accessor :current_player_color
|
26
17
|
|
27
|
-
# @!attribute [
|
28
|
-
# @return [
|
29
|
-
attr_accessor :
|
18
|
+
# @!attribute [rw] round
|
19
|
+
# @return [Integer] Aktuelle Rundennummer (von 1 beginnend)
|
20
|
+
attr_accessor :round
|
21
|
+
|
22
|
+
# @!attribute [rw] startColor
|
23
|
+
# @return [Color] Die Farbe, die zuerst legen darf
|
24
|
+
attr_accessor :start_color
|
25
|
+
|
26
|
+
# @!attribute [rw] valid_colors
|
27
|
+
# @return [Array<Color>] Ein Array aller Farben die ziehen können in
|
28
|
+
# der Reihenfolge in der sie drankommen
|
29
|
+
attr_accessor :valid_colors
|
30
|
+
|
31
|
+
# @!attribute [rw] ordered_colors
|
32
|
+
# @return [Array<Color>] Ein Array aller Farben in
|
33
|
+
# der Reihenfolge in der sie drankommen
|
34
|
+
attr_accessor :ordered_colors
|
30
35
|
|
31
36
|
# @!attribute [r] undeployed_blue_pieces
|
32
|
-
# @return [
|
37
|
+
# @return [Array<PieceShape>] Die blauen, nicht gesetzten Spielsteine
|
33
38
|
attr_accessor :undeployed_blue_pieces
|
34
39
|
|
35
|
-
# @!attribute [r]
|
36
|
-
# @return [
|
37
|
-
|
38
|
-
|
39
|
-
#
|
40
|
-
|
40
|
+
# @!attribute [r] undeployed_yellow_pieces
|
41
|
+
# @return [Array<PieceShape>] Die gelben, nicht gesetzten Spielsteine
|
42
|
+
attr_accessor :undeployed_yellow_pieces
|
43
|
+
|
44
|
+
# @!attribute [r] undeployed_red_pieces
|
45
|
+
# @return [Array<PieceShape>] Die roten, nicht gesetzten Spielsteine
|
46
|
+
attr_accessor :undeployed_red_pieces
|
47
|
+
|
48
|
+
# @!attribute [r] undeployed_green_pieces
|
49
|
+
# @return [Array<PieceShape>] Die grünen, nicht gesetzten Spielsteine
|
50
|
+
attr_accessor :undeployed_green_pieces
|
51
|
+
|
52
|
+
# @!attribute [r] player_one
|
53
|
+
# @return [Player] Der erste Spieler
|
54
|
+
attr_reader :player_one
|
55
|
+
|
56
|
+
# @!attribute [r] player_two
|
57
|
+
# @return [Player] Der zweite Spieler
|
58
|
+
attr_reader :player_two
|
59
|
+
|
41
60
|
# @!attribute [rw] board
|
42
61
|
# @return [Board] Das aktuelle Spielbrett
|
43
62
|
attr_accessor :board
|
63
|
+
|
64
|
+
# @!attribute [rw] startPiece
|
65
|
+
# @return [PieceShape] Der Stein, der im ersten Zug von allen Farben gelegt werden muss
|
66
|
+
attr_accessor :start_piece
|
67
|
+
|
44
68
|
# @!attribute [rw] last_move
|
45
69
|
# @return [Move] Der zuletzt gemachte Zug (ist nil vor dem ersten Zug, also
|
46
70
|
# bei turn == 0)
|
47
71
|
attr_accessor :last_move
|
72
|
+
|
48
73
|
# @!attribute [rw] condition
|
49
74
|
# @return [Condition] Gewinner und Gewinngrund, falls das Spiel bereits
|
50
75
|
# entschieden ist, sonst nil.
|
@@ -54,78 +79,86 @@ class GameState
|
|
54
79
|
def field(x, y)
|
55
80
|
board.field(x, y)
|
56
81
|
end
|
57
|
-
def self.parse_pieces_string(string, color)
|
58
|
-
string.chars.map do |c|
|
59
|
-
case c
|
60
|
-
when 'Q'
|
61
|
-
Piece.new(color, PieceType::BEE)
|
62
|
-
when 'S'
|
63
|
-
Piece.new(color, PieceType::SPIDER)
|
64
|
-
when 'G'
|
65
|
-
Piece.new(color, PieceType::GRASSHOPPER)
|
66
|
-
when 'B'
|
67
|
-
Piece.new(color, PieceType::BEETLE)
|
68
|
-
when 'A'
|
69
|
-
Piece.new(color, PieceType::ANT)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
82
|
|
83
|
+
# Erstellt einen neuen leeren Spielstand.
|
74
84
|
def initialize
|
75
|
-
@
|
76
|
-
@start_player_color = PlayerColor::RED
|
85
|
+
@ordered_colors = [Color::BLUE, Color::YELLOW, Color::RED, Color::GREEN]
|
77
86
|
@board = Board.new
|
78
87
|
@turn = 0
|
79
|
-
@
|
80
|
-
@
|
88
|
+
@undeployed_blue_pieces = PieceShape.to_a
|
89
|
+
@undeployed_yellow_pieces = PieceShape.to_a
|
90
|
+
@undeployed_red_pieces = PieceShape.to_a
|
91
|
+
@undeployed_green_pieces = PieceShape.to_a
|
92
|
+
@start_piece = GameRuleLogic.get_random_pentomino
|
93
|
+
@start_color = Color::BLUE
|
81
94
|
end
|
82
95
|
|
83
96
|
# Fügt einen Spieler zum Spielzustand hinzu.
|
84
97
|
#
|
85
98
|
# @param player [Player] Der hinzuzufügende Spieler.
|
86
99
|
def add_player(player)
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
100
|
+
case player.type
|
101
|
+
when PlayerType::ONE
|
102
|
+
@player_one = player
|
103
|
+
when PlayerType::TWO
|
104
|
+
@player_two = player
|
91
105
|
end
|
92
106
|
end
|
93
107
|
|
94
108
|
# @return [Player] Spieler, der gerade an der Reihe ist.
|
95
109
|
def current_player
|
96
|
-
|
97
|
-
return blue if current_player_color == PlayerColor::BLUE
|
110
|
+
turn.even? ? player_one : player_two
|
98
111
|
end
|
99
112
|
|
100
113
|
# @return [Player] Spieler, der gerade nicht an der Reihe ist.
|
101
114
|
def other_player
|
102
|
-
|
103
|
-
return red if current_player_color == PlayerColor::BLUE
|
115
|
+
turn.even? ? player_two : player_one
|
104
116
|
end
|
105
117
|
|
106
|
-
# @return [
|
107
|
-
def
|
108
|
-
|
118
|
+
# @return [PlayerType] Typ des Spielers, der gerade nicht an der Reihe ist.
|
119
|
+
def other_player_type
|
120
|
+
other_player.type
|
109
121
|
end
|
110
122
|
|
111
|
-
# @return [
|
112
|
-
def
|
113
|
-
turn
|
123
|
+
# @return [Color] Der jetzige Index in der Zug Reihenfolge der Farben.
|
124
|
+
def current_color_index
|
125
|
+
turn % 4
|
114
126
|
end
|
115
127
|
|
128
|
+
# @return [Color] Farbe, der gerade an der Reihe ist.
|
129
|
+
def current_color
|
130
|
+
ordered_colors[current_color_index]
|
131
|
+
end
|
132
|
+
|
133
|
+
# @return [Color] Farbe des aktuellen Spielers, die gerade nicht an der Reihe ist.
|
134
|
+
def other_color
|
135
|
+
Color.find_by_ord((current_color.ord + 2) % 4)
|
136
|
+
end
|
137
|
+
|
138
|
+
# @return [Array<PieceShape>] Array aller Shapes, der gegebenen Farbe, die noch nicht gelegt wurden
|
116
139
|
def undeployed_pieces(color)
|
117
140
|
case color
|
118
|
-
when
|
141
|
+
when Color::RED
|
119
142
|
undeployed_red_pieces
|
120
|
-
when
|
143
|
+
when Color::BLUE
|
121
144
|
undeployed_blue_pieces
|
145
|
+
when Color::YELLOW
|
146
|
+
undeployed_yellow_pieces
|
147
|
+
when Color::GREEN
|
148
|
+
undeployed_green_pieces
|
122
149
|
end
|
123
150
|
end
|
124
151
|
|
152
|
+
# @return [Array<PieceShape>] Array aller Shapes, der gegebenen Farbe, die schon gelegt wurden
|
125
153
|
def deployed_pieces(color)
|
126
154
|
board.deployed_pieces(color)
|
127
155
|
end
|
128
156
|
|
157
|
+
# @return [Bool] Ob diese gamestate in der ersten Runde ist
|
158
|
+
def is_first_move?
|
159
|
+
round == 1
|
160
|
+
end
|
161
|
+
|
129
162
|
# Führt einen Zug auf dem Spielzustand aus. Das Spielbrett wird entsprechend
|
130
163
|
# modifiziert.
|
131
164
|
#
|
@@ -140,6 +173,11 @@ class GameState
|
|
140
173
|
!condition.nil?
|
141
174
|
end
|
142
175
|
|
176
|
+
# Entfernt die jetzige Farbe aus der Farbrotation
|
177
|
+
def remove_active_color
|
178
|
+
ordered_colors.delete current_color
|
179
|
+
end
|
180
|
+
|
143
181
|
# @return [Player] Der Spieler, der das Spiel gewonnen hat, falls dies schon
|
144
182
|
# entschieden ist. Sonst false.
|
145
183
|
def winner
|
@@ -156,22 +194,23 @@ class GameState
|
|
156
194
|
# Rundenlimits beendet wird, hat der Spieler mit den meisten Punkten gewonnen.
|
157
195
|
#
|
158
196
|
# @param player [Player] Der Spieler, dessen Punkte berechnet werden sollen.
|
159
|
-
# @return [Integer] Die Punkte des Spielers
|
160
|
-
|
161
|
-
def points_for_player(player)
|
197
|
+
# @return [Integer] Die Punkte des Spielers
|
198
|
+
def points_for_player(_player)
|
162
199
|
# TODO
|
163
200
|
-1
|
164
201
|
end
|
165
202
|
|
166
203
|
def ==(other)
|
167
204
|
turn == other.turn &&
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
205
|
+
start_color == other.start_color &&
|
206
|
+
current_color == other.current_color &&
|
207
|
+
blue == other.blue &&
|
208
|
+
yellow == other.yellow &&
|
209
|
+
red == other.red &&
|
210
|
+
green == other.green &&
|
211
|
+
board == other.board &&
|
212
|
+
lastMove == other.lastMove &&
|
213
|
+
condition == other.condition
|
175
214
|
end
|
176
215
|
|
177
216
|
# Erzeugt eine Kopie des Spielzustandes. Änderungen an dieser Kopie
|
@@ -186,9 +225,8 @@ class GameState
|
|
186
225
|
@current_player_color = other_player_color
|
187
226
|
end
|
188
227
|
|
189
|
-
# @return [Array<Field>] Alle Felder mit
|
228
|
+
# @return [Array<Field>] Alle Felder mit Blöcken des Spielers, der gerade an der Reihe ist.
|
190
229
|
def own_fields
|
191
|
-
board.fields_of_color(
|
230
|
+
board.fields_of_color(current_color)
|
192
231
|
end
|
193
|
-
|
194
232
|
end
|
@@ -1,31 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Ein Spielstein mit Ausrichtung, Koordinaten und Farbe
|
1
4
|
class Piece
|
5
|
+
# @!attribute [r] Farbe
|
6
|
+
# @return [Color]
|
7
|
+
attr_reader :color
|
2
8
|
|
3
|
-
# @!attribute [r]
|
4
|
-
# @return [
|
5
|
-
attr_reader :
|
9
|
+
# @!attribute [r] Form
|
10
|
+
# @return [PieceShape]
|
11
|
+
attr_reader :kind
|
6
12
|
|
7
|
-
# @!attribute [r]
|
8
|
-
# @return [
|
9
|
-
attr_reader :
|
13
|
+
# @!attribute [r] Drehung
|
14
|
+
# @return [Rotation]
|
15
|
+
attr_reader :rotation
|
16
|
+
|
17
|
+
# @!attribute [r] Ob der Stein an der Y-Achse gespiegelt ist
|
18
|
+
# @return [Boolean]
|
19
|
+
attr_reader :is_flipped
|
20
|
+
|
21
|
+
# @!attribute [r] Koordinaten
|
22
|
+
# @return [Coordinates]
|
23
|
+
attr_reader :position
|
10
24
|
|
11
|
-
|
12
|
-
|
25
|
+
# @!attribute [r] Ein Array der Positionsdaten aller Bestandteile von dem Stein in Board Koordinaten, also schon ggf. gedreht und um position versetzt.
|
26
|
+
# return [Array<Coordinates>]
|
27
|
+
attr_reader :coords
|
28
|
+
|
29
|
+
# Erstellt einen neuen leeren Spielstein.
|
30
|
+
def initialize(color, kind, rotation = Rotation::NONE, is_flipped = false, position = Coordinates.origin)
|
13
31
|
@color = color
|
32
|
+
@kind = kind
|
33
|
+
@rotation = rotation
|
34
|
+
@is_flipped = is_flipped
|
35
|
+
@position = position
|
36
|
+
|
37
|
+
@coords = coords_priv
|
14
38
|
end
|
15
39
|
|
16
|
-
|
17
|
-
|
40
|
+
# Dreht den Stein
|
41
|
+
def rotate!(rotation)
|
42
|
+
@rotation = @rotation.rotate(rotation)
|
43
|
+
@coords = coords_priv
|
44
|
+
end
|
45
|
+
|
46
|
+
# Flipped den Stein
|
47
|
+
def flip!(f = true)
|
48
|
+
@is_flipped = @is_flipped ^ f
|
49
|
+
@coords = coords_priv
|
18
50
|
end
|
19
51
|
|
20
|
-
|
21
|
-
|
52
|
+
# Setzt den Stein auf eine Position
|
53
|
+
def locate!(position)
|
54
|
+
@position = position
|
55
|
+
@coords = coords_priv
|
56
|
+
end
|
57
|
+
|
58
|
+
# Verschiebt den Stein
|
59
|
+
def move!(shift)
|
60
|
+
@position = position + shift
|
61
|
+
@coords = coords_priv
|
62
|
+
end
|
63
|
+
|
64
|
+
# Gibt die Fläche der transformierten Steinform von diesem Stein zurück
|
65
|
+
def area()
|
66
|
+
CoordinateSet.new(coords).area
|
67
|
+
end
|
68
|
+
|
69
|
+
def ==(other)
|
70
|
+
color == other.color &&
|
71
|
+
coords == other.coords
|
22
72
|
end
|
23
73
|
|
24
74
|
def to_s
|
25
|
-
color.
|
75
|
+
"#{color.key} #{kind.key} at #{position} rotation #{rotation.key}#{is_flipped ? ' (flipped)' : ''}"
|
26
76
|
end
|
27
77
|
|
28
78
|
def inspect
|
29
79
|
to_s
|
30
80
|
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def coords_priv
|
85
|
+
kind.transform(@rotation, @is_flipped).transform do |it|
|
86
|
+
Coordinates.new(it.x + @position.x, it.y + @position.y)
|
87
|
+
end.coordinates
|
88
|
+
end
|
31
89
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'typesafe_enum'
|
4
|
+
|
5
|
+
require_relative 'coordinates'
|
6
|
+
require_relative 'coordinate_set'
|
7
|
+
|
8
|
+
# Die Form eines Spielsteins. Es gibt folgende Formen:
|
9
|
+
#
|
10
|
+
# MONO
|
11
|
+
# DOMINO
|
12
|
+
# TRIO_L
|
13
|
+
# TRIO_I
|
14
|
+
# TETRO_O
|
15
|
+
# TETRO_T
|
16
|
+
# TETRO_I
|
17
|
+
# TETRO_L
|
18
|
+
# TETRO_Z
|
19
|
+
# PENTO_L
|
20
|
+
# PENTO_T
|
21
|
+
# PENTO_V
|
22
|
+
# PENTO_S
|
23
|
+
# PENTO_Z
|
24
|
+
# PENTO_I
|
25
|
+
# PENTO_P
|
26
|
+
# PENTO_W
|
27
|
+
# PENTO_U
|
28
|
+
# PENTO_R
|
29
|
+
# PENTO_X
|
30
|
+
# PENTO_Y
|
31
|
+
#
|
32
|
+
# Zugriff z.B. mit PieceShape::PENTO_S
|
33
|
+
class PieceShape < TypesafeEnum::Base
|
34
|
+
def self.c(x, y)
|
35
|
+
Coordinates.new(x, y)
|
36
|
+
end
|
37
|
+
new :MONO, [c(0, 0)]
|
38
|
+
new :DOMINO, [c(0, 0), c(1, 0)]
|
39
|
+
new :TRIO_L, [c(0, 0), c(0, 1), c(1, 1)]
|
40
|
+
new :TRIO_I, [c(0, 0), c(0, 1), c(0, 2)]
|
41
|
+
new :TETRO_O, [c(0, 0), c(1, 0), c(0, 1), c(1, 1)]
|
42
|
+
new :TETRO_T, [c(0, 0), c(1, 0), c(2, 0), c(1, 1)]
|
43
|
+
new :TETRO_I, [c(0, 0), c(0, 1), c(0, 2), c(0, 3)]
|
44
|
+
new :TETRO_L, [c(0, 0), c(0, 1), c(0, 2), c(1, 2)]
|
45
|
+
new :TETRO_Z, [c(0, 0), c(1, 0), c(1, 1), c(2, 1)]
|
46
|
+
new :PENTO_L, [c(0, 0), c(0, 1), c(0, 2), c(0, 3), c(1, 3)]
|
47
|
+
new :PENTO_T, [c(0, 0), c(1, 0), c(2, 0), c(1, 1), c(1, 2)]
|
48
|
+
new :PENTO_V, [c(0, 0), c(0, 1), c(0, 2), c(1, 2), c(2, 2)]
|
49
|
+
new :PENTO_S, [c(1, 0), c(2, 0), c(3, 0), c(0, 1), c(1, 1)]
|
50
|
+
new :PENTO_Z, [c(0, 0), c(1, 0), c(1, 1), c(1, 2), c(2, 2)]
|
51
|
+
new :PENTO_I, [c(0, 0), c(0, 1), c(0, 2), c(0, 3), c(0, 4)]
|
52
|
+
new :PENTO_P, [c(0, 0), c(1, 0), c(0, 1), c(1, 1), c(0, 2)]
|
53
|
+
new :PENTO_W, [c(0, 0), c(0, 1), c(1, 1), c(1, 2), c(2, 2)]
|
54
|
+
new :PENTO_U, [c(0, 0), c(0, 1), c(1, 1), c(2, 1), c(2, 0)]
|
55
|
+
new :PENTO_R, [c(0, 1), c(1, 1), c(1, 2), c(2, 1), c(2, 0)]
|
56
|
+
new :PENTO_X, [c(1, 0), c(0, 1), c(1, 1), c(2, 1), c(1, 2)]
|
57
|
+
new :PENTO_Y, [c(0, 1), c(1, 0), c(1, 1), c(1, 2), c(1, 3)]
|
58
|
+
|
59
|
+
@transformations
|
60
|
+
Transform = Struct.new(:r, :f, :coords)
|
61
|
+
|
62
|
+
# Anzahl Felder, die der Stein belegt
|
63
|
+
def size
|
64
|
+
value.size
|
65
|
+
end
|
66
|
+
|
67
|
+
# Die Felder, die der Stein belegt
|
68
|
+
def coordinates
|
69
|
+
CoordinateSet.new(value)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Eine Koordinate, die das kleinstmögliche Rechteck beschreibt, welches alle Felder umfasst.
|
73
|
+
def dimension
|
74
|
+
coordinates.area
|
75
|
+
end
|
76
|
+
|
77
|
+
# Erzeugt eine nach Rotation und Flip transformierte Form
|
78
|
+
def transform(rotation, flip)
|
79
|
+
coordinates.rotate(rotation).flip(flip)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Gibt alle Kombinationen aus Rotation und Flipping zurück, welche zu einzigartigen
|
83
|
+
# Koordinatenmengen dieser Form führen.
|
84
|
+
# @return [Array<Transform>] Transform Structs mit Rotation r, Boolean f
|
85
|
+
def unique_transforms()
|
86
|
+
if not defined? @transformations then
|
87
|
+
existing_transforms = []
|
88
|
+
|
89
|
+
Rotation.each do |r|
|
90
|
+
[true, false].each do |f|
|
91
|
+
new_transform = Transform.new(r, f, transform(r, f))
|
92
|
+
|
93
|
+
if existing_transforms.none? { |t| t.coords == new_transform.coords } then
|
94
|
+
existing_transforms << new_transform
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
@transformations = existing_transforms
|
100
|
+
end
|
101
|
+
|
102
|
+
@transformations
|
103
|
+
end
|
104
|
+
|
105
|
+
# Gibt den Form Namen zurück
|
106
|
+
def to_s
|
107
|
+
self.key.to_s
|
108
|
+
end
|
109
|
+
end
|