Skip to content

Commit bad684c

Browse files
committed
fix
1 parent 5d392e0 commit bad684c

8 files changed

+101
-106
lines changed

src/ch/epfl/chacun/gui/ActionsUI.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.util.List;
1212
import java.util.StringJoiner;
1313
import java.util.function.Consumer;
14+
import java.util.stream.Collectors;
1415

1516
/**
1617
* This class represents the graphical representation
@@ -72,10 +73,10 @@ public static Node create(ObservableValue<List<String>> actionsO, Consumer<Strin
7273
*/
7374
private static String cleanupInput(String input) {
7475
return input.toUpperCase()
75-
.chars()
76-
.filter(c -> Base32.isValid(Character.toString(c)))
77-
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
78-
.toString();
76+
.chars()
77+
.mapToObj(Character::toString)
78+
.filter(Base32::isValid)
79+
.collect(Collectors.joining());
7980
}
8081

8182
/**

src/ch/epfl/chacun/gui/BoardUI.java

+39-35
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ public final class BoardUI {
3737
*/
3838
private static final Map<Integer, Image> cachedImages = new HashMap<>();
3939

40+
private static final double H_SCROLL_CENTER = .5;
41+
private static final double V_SCROLL_CENTER = .5;
42+
private static final double VEIl_OPACITY = .5;
43+
4044
/**
4145
* This is a utility class and therefore is not instantiable
4246
*/
@@ -50,7 +54,7 @@ private BoardUI() {
5054
* for a certain message when the player hovers over it. It also handles some graphical effects to
5155
* render the positions where a tile can be placed in the next turn and the mouse interactions.
5256
*
53-
* @param range the range of the board (the distance from the center to the borders),
57+
* @param reach the reach of the board (the distance from the center to the borders),
5458
* the board will be a square of size (2*range+1)²
5559
* @param gameStateO the observable value of the current game state
5660
* @param rotationO the observable value of the current rotation of the tile to be placed
@@ -62,18 +66,18 @@ private BoardUI() {
6266
* @return a graphical node representing the board of the game
6367
*/
6468
public static Node create(
65-
int range,
66-
ObservableValue<GameState> gameStateO,
67-
ObservableValue<Rotation> rotationO,
68-
ObservableValue<Set<Occupant>> occupantsO,
69-
ObservableValue<Set<Integer>> highlightedTilesO,
70-
71-
Consumer<Rotation> rotationConsumer,
72-
Consumer<Pos> posConsumer,
73-
Consumer<Occupant> occupantConsumer
69+
int reach,
70+
ObservableValue<GameState> gameStateO,
71+
ObservableValue<Rotation> rotationO,
72+
ObservableValue<Set<Occupant>> occupantsO,
73+
ObservableValue<Set<Integer>> highlightedTilesO,
74+
75+
Consumer<Rotation> rotationConsumer,
76+
Consumer<Pos> posConsumer,
77+
Consumer<Occupant> occupantConsumer
7478
) {
7579

76-
Preconditions.checkArgument(range > 0);
80+
Preconditions.checkArgument(reach > 0);
7781

7882
ScrollPane scrollPane = new ScrollPane();
7983
scrollPane.setId("board-scroll-pane");
@@ -86,24 +90,24 @@ public static Node create(
8690
ObservableValue<Set<Animal>> cancelledAnimalsO = boardO.map(Board::cancelledAnimals);
8791
// the fringe only exists when the next action is to place a tile
8892
ObservableValue<Set<Pos>> fringeTilesO = gameStateO.map(
89-
state -> state.nextAction() == GameState.Action.PLACE_TILE
90-
// important to understand
91-
// we can not use boardO.getValue() here!
92-
// because this map may be triggered before boardO gets updated!
93-
// therefore we would be using the old board
94-
? state.board().insertionPositions()
95-
: Set.of()
93+
state -> state.nextAction() == GameState.Action.PLACE_TILE
94+
// important to understand
95+
// we can not use boardO.getValue() here!
96+
// because this map may be triggered before boardO gets updated!
97+
// therefore we would be using the old board
98+
? state.board().insertionPositions()
99+
: Set.of()
96100
);
97101

98-
for (int x = -range; x <= range; x++) {
99-
for (int y = -range; y <= range; y++) {
102+
for (int x = -reach; x <= reach; x++) {
103+
for (int y = -reach; y <= reach; y++) {
100104
//each cell of the grid contains a tile
101105
ImageView imageView = new ImageView();
102106
imageView.setFitWidth(ImageLoader.NORMAL_TILE_FIT_SIZE);
103107
imageView.setFitHeight(ImageLoader.NORMAL_TILE_FIT_SIZE);
104108
Blend blend = new Blend();
105109
blend.setMode(BlendMode.SRC_OVER);
106-
blend.setOpacity(0.5);
110+
blend.setOpacity(VEIl_OPACITY);
107111
blend.setBottomInput(null);
108112

109113
Group group = new Group(imageView);
@@ -167,7 +171,7 @@ public static Node create(
167171
blend.topInputProperty().bind(cellDataO.map(CellData::blendTopInput));
168172

169173
// we add range and position in order to translate our tile from the left corner to the center
170-
grid.add(group, x + range, y + range);
174+
grid.add(group, x + reach, y + reach);
171175
// when a tile is placed, we add the animals and the occupants on it
172176
placedTileO.addListener((_, oldPlacedTile, placedTile) -> {
173177
if (oldPlacedTile != null || placedTile == null) return;
@@ -176,26 +180,26 @@ public static Node create(
176180

177181
// handle "jeton d'annulation", a marker that signals that an animal is cancelled
178182
List<Node> cancelledAnimalsNodes = placedTile.meadowZones().stream()
179-
.flatMap(meadow -> meadow.animals().stream())
180-
.map(animal -> getCancelledAnimalNode(animal, cancelledAnimalsO, negatedTileRotation))
181-
.toList();
183+
.flatMap(meadow -> meadow.animals().stream())
184+
.map(animal -> getCancelledAnimalNode(animal, cancelledAnimalsO, negatedTileRotation))
185+
.toList();
182186
group.getChildren().addAll(cancelledAnimalsNodes);
183187
// here we handle the graphical representation of the occupants
184188
List<Node> potentialOccupantsNodes = placedTile.potentialOccupants()
185-
.stream()
186-
.map(occupant -> getOccupantNode(
187-
placedTile.placer(), occupant,
188-
occupantsO, occupantConsumer, negatedTileRotation
189-
))
190-
.toList();
189+
.stream()
190+
.map(occupant -> getOccupantNode(
191+
placedTile.placer(), occupant,
192+
occupantsO, occupantConsumer, negatedTileRotation
193+
))
194+
.toList();
191195

192196
group.getChildren().addAll(potentialOccupantsNodes);
193197
});
194198
}
195199
}
196200

197-
scrollPane.setHvalue(.5);
198-
scrollPane.setVvalue(.5);
201+
scrollPane.setHvalue(H_SCROLL_CENTER);
202+
scrollPane.setVvalue(V_SCROLL_CENTER);
199203

200204
scrollPane.setContent(grid);
201205
return scrollPane;
@@ -252,8 +256,8 @@ private record CellData(Image tileImage, Rotation tileRotation, Color veilColor)
252256
*/
253257
public CellData(PlacedTile placedTile, Color veilColor) {
254258
this(
255-
cachedImages.computeIfAbsent(placedTile.id(), ImageLoader::normalImageForTile),
256-
placedTile.rotation(), veilColor
259+
cachedImages.computeIfAbsent(placedTile.id(), ImageLoader::normalImageForTile),
260+
placedTile.rotation(), veilColor
257261
);
258262
}
259263

src/ch/epfl/chacun/gui/ColorMap.java

+15-16
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,10 @@ private ColorMap() {
2727
PlayerColor.YELLOW, Color.YELLOW,
2828
PlayerColor.PURPLE, Color.PURPLE
2929
);
30-
/**
31-
* A map associating each player color to its stroke color
32-
*/
33-
private final static Map<PlayerColor, Color> strokeColorMap = Map.of(
34-
PlayerColor.RED, Color.WHITE,
35-
PlayerColor.BLUE, Color.WHITE,
36-
PlayerColor.PURPLE, Color.WHITE,
37-
PlayerColor.GREEN, fillColor(PlayerColor.GREEN).deriveColor(
38-
0, 1, STROKE_BRIGHTNESS_FACTOR, 1
39-
),
40-
PlayerColor.YELLOW, fillColor(PlayerColor.YELLOW).deriveColor(
41-
0, 1, STROKE_BRIGHTNESS_FACTOR, 1
42-
)
43-
);
30+
31+
private static Color deriveStrokePlayerColor(PlayerColor playerColor) {
32+
return fillColor(playerColor).deriveColor(0, 1, STROKE_BRIGHTNESS_FACTOR, 1);
33+
}
4434

4535
/**
4636
* Returns the fill color for the given player color
@@ -49,7 +39,13 @@ PlayerColor.YELLOW, fillColor(PlayerColor.YELLOW).deriveColor(
4939
* @return the fill color for the given player color
5040
*/
5141
public static Color fillColor(PlayerColor playerColor) {
52-
return fillColorMap.get(playerColor);
42+
return switch (playerColor) {
43+
case RED -> Color.RED;
44+
case BLUE -> Color.BLUE;
45+
case GREEN -> Color.LIME;
46+
case YELLOW -> Color.YELLOW;
47+
case PURPLE -> Color.PURPLE;
48+
};
5349
}
5450

5551
/**
@@ -59,7 +55,10 @@ public static Color fillColor(PlayerColor playerColor) {
5955
* @return the stroke color for the given player color
6056
*/
6157
public static Color strokeColor(PlayerColor playerColor) {
62-
return strokeColorMap.get(playerColor);
58+
return switch (playerColor) {
59+
case RED, BLUE, PURPLE -> Color.WHITE;
60+
case GREEN, YELLOW -> deriveStrokePlayerColor(playerColor);
61+
};
6362
}
6463

6564
}

src/ch/epfl/chacun/gui/DecksUI.java

+7-14
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,7 @@ public static Node create(
5252

5353
// ImageView of the next tile to place, which has to be shown in large size
5454
ImageView view = new ImageView();
55-
view.imageProperty().bind(tileO.map(t ->
56-
t == null
57-
? ImageLoader.EMPTY_IMAGE
58-
: ImageLoader.largeImageForTile(t.id())));
55+
view.imageProperty().bind(tileO.map(t -> ImageLoader.largeImageForTile(t.id())));
5956
view.setFitHeight(ImageLoader.LARGE_TILE_FIT_SIZE);
6057
view.setFitWidth(ImageLoader.LARGE_TILE_FIT_SIZE);
6158
// Text, occupy tile (only visible if textToDisplay is not empty,
@@ -68,14 +65,10 @@ public static Node create(
6865
text.setWrappingWidth(WRAPPING_WIDTH * ImageLoader.LARGE_TILE_FIT_SIZE);
6966
stackPane.getChildren().setAll(view, text);
7067
// we bind the graphical view of the tile to place to the tile itself
71-
view.imageProperty().bind(tileO.map(t ->
72-
t == null
73-
? ImageLoader.EMPTY_IMAGE
74-
: ImageLoader.largeImageForTile(t.id()))
75-
);
68+
view.imageProperty().bind(tileO.map(t -> ImageLoader.largeImageForTile(t.id())));
7669
// here we handle the decks containing the remaining cards
77-
Node menhirNode = getDeckNode("MENHIR", leftMenhirTilesO);
78-
Node normalNode = getDeckNode("NORMAL", leftNormalTilesO);
70+
Node normalNode = getDeckNode(Tile.Kind.NORMAL, leftNormalTilesO);
71+
Node menhirNode = getDeckNode(Tile.Kind.MENHIR, leftMenhirTilesO);
7972
HBox hBox = new HBox(normalNode, menhirNode);
8073
hBox.setAlignment(Pos.CENTER);
8174

@@ -89,13 +82,13 @@ public static Node create(
8982
/**
9083
* This method creates a node representing a deck containing the remaining tiles
9184
*
92-
* @param name the name of the deck, which represents the kind of tiles it contains
85+
* @param kind the kind of the deck, which represents the kind of tiles it contains
9386
* @param leftTiles the updating number of tiles left in the deck
9487
* @return a node representing the deck
9588
*/
96-
private static Node getDeckNode(String name, ObservableValue<Integer> leftTiles) {
89+
private static Node getDeckNode(Tile.Kind kind, ObservableValue<Integer> leftTiles) {
9790
ImageView image = new ImageView();
98-
image.setId(name);
91+
image.setId(kind.toString());
9992
image.setFitHeight(ImageLoader.NORMAL_TILE_FIT_SIZE);
10093
image.setFitWidth(ImageLoader.NORMAL_TILE_FIT_SIZE);
10194
Text text = new Text();

src/ch/epfl/chacun/gui/Icon.java

+4-10
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import javafx.scene.Node;
66
import javafx.scene.shape.SVGPath;
77

8-
import java.util.Map;
9-
108
/**
119
* This class provides utility methods to create occupants' graphical representations
1210
*
@@ -28,13 +26,6 @@ private Icon() {
2826
* The SVG path for a hut
2927
*/
3028
private final static String HUT_SVG = "M -8 10 H 8 V 2 H 12 L 0 -10 L -12 2 H -8 Z";
31-
/**
32-
* A map associating each kind of occupant to its SVG path
33-
*/
34-
private final static Map<Occupant.Kind, String> SVG_MAP = Map.of(
35-
Occupant.Kind.PAWN, PAWN_SVG,
36-
Occupant.Kind.HUT, HUT_SVG
37-
);
3829

3930
/**
4031
* Creates a new node representing an occupant of the given kind and player
@@ -45,7 +36,10 @@ private Icon() {
4536
*/
4637
public static Node newFor(PlayerColor playerColor, Occupant.Kind kind) {
4738
SVGPath svgPath = new SVGPath();
48-
svgPath.setContent(SVG_MAP.get(kind));
39+
svgPath.setContent(switch (kind) {
40+
case PAWN -> PAWN_SVG;
41+
case HUT -> HUT_SVG;
42+
});
4943
svgPath.setFill(ColorMap.fillColor(playerColor));
5044
svgPath.setStroke(ColorMap.strokeColor(playerColor));
5145
return svgPath;

src/ch/epfl/chacun/gui/Main.java

+17-21
Original file line numberDiff line numberDiff line change
@@ -97,21 +97,19 @@ public void start(Stage primaryStage) {
9797

9898
Consumer<Occupant> onOccupantClick = occupant -> {
9999
GameState currentGameState = gameStateO.getValue();
100-
if (currentGameState.nextAction() == GameState.Action.OCCUPY_TILE) {
101-
assert currentGameState.board().lastPlacedTile() != null;
102-
int lastPlacedTileId = currentGameState.board().lastPlacedTile().id();
103-
if (occupant != null && Zone.tileId(occupant.zoneId()) != lastPlacedTileId) return;
104-
ActionEncoder.StateAction stateAction = ActionEncoder.withNewOccupant(currentGameState, occupant);
105-
saveState(stateAction, gameStateO, actionsO);
106-
} else if (currentGameState.nextAction() == GameState.Action.RETAKE_PAWN) {
107-
// todo this code is duplicated from ActionEncoder
108-
// ask an assistant
109-
if (occupant.kind() != Occupant.Kind.PAWN) return;
110-
PlayerColor currentPlayer = gameState.currentPlayer();
111-
PlayerColor occupantPlacer = gameState.board().tileWithId(Zone.tileId(occupant.zoneId())).placer();
112-
if (currentPlayer != occupantPlacer) return;
113-
ActionEncoder.StateAction stateAction = ActionEncoder.withOccupantRemoved(currentGameState, occupant);
114-
saveState(stateAction, gameStateO, actionsO);
100+
Board board = currentGameState.board();
101+
int tileId = Zone.tileId(occupant.zoneId());
102+
switch (currentGameState.nextAction()) {
103+
case OCCUPY_TILE -> {
104+
if (occupant != null && tileId != board.lastPlacedTile().id()) return;
105+
saveState(ActionEncoder.withNewOccupant(currentGameState, occupant), gameStateO, actionsO);
106+
}
107+
case RETAKE_PAWN -> {
108+
// todo or
109+
if (occupant.kind() != Occupant.Kind.PAWN) return;
110+
if (currentGameState.currentPlayer() != board.tileWithId(tileId).placer()) return;
111+
saveState(ActionEncoder.withOccupantRemoved(currentGameState, occupant), gameStateO, actionsO);
112+
}
115113
}
116114
};
117115

@@ -139,9 +137,7 @@ public void start(Stage primaryStage) {
139137
nextRotationO.getValue(), pos
140138
);
141139
if (!currentGameState.board().canAddTile(placedTile)) return;
142-
ActionEncoder.StateAction stateAction = ActionEncoder.withPlacedTile(currentGameState, placedTile);
143-
saveState(stateAction, gameStateO, actionsO);
144-
140+
saveState(ActionEncoder.withPlacedTile(currentGameState, placedTile), gameStateO, actionsO);
145141
nextRotationO.setValue(Rotation.NONE);
146142
};
147143

@@ -154,9 +150,9 @@ public void start(Stage primaryStage) {
154150
});
155151

156152
Node boardNode = BoardUI.create(
157-
Board.REACH, gameStateO, nextRotationO, visibleOccupants, highlightedTilesO,
158-
// consumers
159-
onRotationClick, onPosClick, onOccupantClick
153+
Board.REACH, gameStateO, nextRotationO, visibleOccupants, highlightedTilesO,
154+
// consumers
155+
onRotationClick, onPosClick, onOccupantClick
160156
);
161157

162158
// actions and decks border pane

src/ch/epfl/chacun/gui/MessageBoardUI.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package ch.epfl.chacun.gui;
22

33
import ch.epfl.chacun.MessageBoard;
4-
import javafx.application.Platform;
54
import javafx.beans.property.ObjectProperty;
65
import javafx.beans.value.ObservableValue;
76
import javafx.scene.Node;
@@ -41,6 +40,8 @@ public static Node create(
4140
) {
4241
VBox vBox = new VBox();
4342

43+
// todo scrollbar
44+
4445
ScrollPane scrollPane = new ScrollPane(vBox);
4546
scrollPane.getStylesheets().add("message-board.css");
4647
scrollPane.setId("message-board");

0 commit comments

Comments
 (0)