Skip to content

Commit

Permalink
Merge pull request #98 from Game-as-a-Service/feature/add-create-game…
Browse files Browse the repository at this point in the history
…-usecase

✨ add create game usecase
  • Loading branch information
keytsai authored Sep 27, 2023
2 parents 89d9484 + c913085 commit 976cdb0
Show file tree
Hide file tree
Showing 26 changed files with 259 additions and 94 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package app.output;
package app.repositories;

import domain.Game;

Expand Down
8 changes: 1 addition & 7 deletions src/main/java/app/usecase/BuyCardUseCase.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package app.usecase;

import app.exception.NotFoundException;
import app.output.GameRepository;
import app.repositories.GameRepository;
import domain.Game;
import domain.events.DomainEvent;
import lombok.AllArgsConstructor;
Expand Down Expand Up @@ -38,10 +38,4 @@ public static class Request {
private String cardName;

}

public interface Presenter {
void present(List<DomainEvent> events);
}


}
33 changes: 33 additions & 0 deletions src/main/java/app/usecase/CreateGameUseCase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package app.usecase;

import app.repositories.GameRepository;
import domain.Game;
import domain.Player;
import lombok.*;

import javax.inject.Named;
import java.util.List;

@Named
@RequiredArgsConstructor
public class CreateGameUseCase {
private final GameRepository gameRepository;

public void execute(Request request, Presenter presenter) {

Player player = request.toPlayer();
Game game = new Game(List.of(player));

// 存
gameRepository.save(game);

// 推
presenter.present(game.toCreateGameEvent());
}

public record Request(String playerId, String playerName) {
private Player toPlayer() {
return new Player(playerId, playerName);
}
}
}
10 changes: 2 additions & 8 deletions src/main/java/app/usecase/FlipLandMarkUseCase.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package app.usecase;

import app.exception.NotFoundException;
import app.output.GameRepository;
import app.repositories.GameRepository;
import domain.Game;
import domain.events.DomainEvent;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import spring.presenter.BuyCardPresenter;
import spring.presenter.FlipLandMarkPresenter;

import javax.inject.Named;
import java.util.List;
Expand All @@ -19,7 +17,7 @@
public class FlipLandMarkUseCase {
private final GameRepository gameRepository;

public void execute(FlipLandMarkUseCase.Request request, FlipLandMarkPresenter presenter) {
public void execute(FlipLandMarkUseCase.Request request, Presenter presenter) {
Game game = findGameById(request.gameId);
List<DomainEvent> events = game.turnPlayerFlipLandMark(request.getPlayerId(), request.getCardName());
gameRepository.save(game);
Expand All @@ -30,10 +28,6 @@ private Game findGameById(String gameId) {
return gameRepository.findById(gameId).orElseThrow(NotFoundException::new);
}

public interface Presenter {
void present(List<DomainEvent> events);
}

@Data
@NoArgsConstructor
@AllArgsConstructor
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/app/usecase/Presenter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package app.usecase;

import domain.events.DomainEvent;

import java.util.List;

public interface Presenter {
void present(List<DomainEvent> events);
}
14 changes: 3 additions & 11 deletions src/main/java/app/usecase/RollDiceUseCase.java
Original file line number Diff line number Diff line change
@@ -1,36 +1,32 @@
package app.usecase;

import app.exception.NotFoundException;
import app.output.GameRepository;
import app.repositories.GameRepository;
import domain.Game;
import domain.events.DomainEvent;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;

import javax.inject.Named;
import java.util.List;

@Named
@RequiredArgsConstructor
public class RollDiceUseCase {
private final GameRepository gameRepository;

public void execute(Request request, Presenter presenter) {

// 查
Game game = findGame(request);

// 改
var events = game.rollDice(request.playerId, request.diceCount);
var events = game.rollDice(request.playerId, request.isTwoDices);

// 存
gameRepository.save(game);

// 推
presenter.present(events);

}

private Game findGame(Request request) {
Expand All @@ -44,12 +40,8 @@ private Game findGame(Request request) {
public static class Request {
private String gameId;
private String playerId;
private int diceCount;
}

public interface Presenter {
void present(List<DomainEvent> events);
private boolean isTwoDices;
}

}

2 changes: 0 additions & 2 deletions src/main/java/domain/Dice.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import java.util.Random;

public class Dice {

private int point;
private static final Random RANDOM = new Random();

public int throwDice() {
Expand Down
42 changes: 32 additions & 10 deletions src/main/java/domain/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,36 @@
import lombok.Builder;
import lombok.Data;

import java.util.List;
import java.util.NoSuchElementException;
import java.util.*;

import static java.util.Collections.singletonList;

@Builder
@Data
@AllArgsConstructor
public class Game {
private String id;
private final Bank bank;
private Bank bank;
private final List<Player> players;
@Builder.Default
private List<Dice> dices = List.of(new Dice(), new Dice());
private int currentDicePoint;
private int currentDicePoint = 0;
private Player turnPlayer;
private final Marketplace marketplace;
private Marketplace marketplace;

public Game(List<Player> players) {
this(UUID.randomUUID().toString(), players);
}

public Game(String id, List<Player> players) {
players = Objects.requireNonNullElseGet(players, ArrayList::new);
this.id = id;
this.players = players;
this.bank = new Bank();
this.marketplace = new Marketplace();
this.dices = List.of(new Dice(), new Dice());
this.turnPlayer = !players.isEmpty() ? players.get(0) : null;
}

public Game(Bank bank, List<Player> players, Marketplace marketplace) {
this.bank = bank;
Expand Down Expand Up @@ -65,7 +80,6 @@ public void setUp() {
bank.payCoin(3);
player.addCardToHandCard(new Bakery());
player.addCardToHandCard(new WheatField());
marketplace.initial();
}
}

Expand Down Expand Up @@ -112,15 +126,23 @@ public List<Player> getPlayersExcludeTurnPlayer() {
return players.stream().filter(player -> !player.equals(turnPlayer)).toList();
}

public List<DomainEvent> rollDice(String playerId, int diceCount) {
// TODO : diceCount 可以用 true or false 判斷,因為我們只有一顆骰子或兩顆骰子的情況
public List<DomainEvent> toCreateGameEvent() {
return singletonList(new CreateGameEvent(id));
}

public List<DomainEvent> rollDice(String playerId, boolean isTwoDices) {
// TODO : isTwoDices 可以用 true or false 判斷,因為我們只有一顆骰子或兩顆骰子的情況
checkIsTurnPlayer(playerId);

if ((diceCount > 1 && !turnPlayer.hasLandmarkFlipped(TrainStation.class)) || diceCount > 2 || diceCount < 1) {
if (isTwoDices && !turnPlayer.hasLandmarkFlipped(TrainStation.class)) {
throw new IllegalArgumentException("Invalid quantity of dice");
}

currentDicePoint = dices.stream().limit(diceCount).mapToInt(Dice::throwDice).sum();
if (isTwoDices) {
currentDicePoint = dices.stream().mapToInt(Dice::throwDice).sum();
}else {
currentDicePoint = dices.get(0).throwDice();
}

var event = RollDiceEvent.builder().dicePoint(currentDicePoint).build();

Expand Down
9 changes: 3 additions & 6 deletions src/main/java/domain/HandCard.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,15 @@

import domain.card.Card;
import domain.card.establishment.Establishment;
import domain.card.landmark.AmusementPark;
import domain.card.landmark.Landmark;
import domain.card.landmark.RadioTower;
import domain.card.landmark.ShoppingMall;
import domain.card.landmark.TrainStation;
import domain.card.landmark.*;
import lombok.EqualsAndHashCode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;

@EqualsAndHashCode
public class HandCard {

private List<Establishment> establishments = new ArrayList<>();
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/domain/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
import domain.exceptions.MachiKoroException;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;

import java.util.List;
import java.util.stream.Collectors;

@Builder
@EqualsAndHashCode
@AllArgsConstructor
public class Player {
private String id;
Expand All @@ -21,6 +23,11 @@ public class Player {
@Builder.Default
private HandCard handCard = new HandCard();

public Player(String id, String name) {
this(name);
this.id = id;
}

public Player(String name) {
this.name = name;
this.handCard = new HandCard();
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/domain/events/CreateGameEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package domain.events;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CreateGameEvent extends DomainEvent {
private String gameId;
}
5 changes: 3 additions & 2 deletions src/main/java/domain/events/RollDiceEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RollDiceEvent extends DomainEvent {
public int dicePoint;
private int dicePoint;
}
25 changes: 18 additions & 7 deletions src/main/java/spring/controllers/GameController.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package spring.controllers;

import app.usecase.BuyCardUseCase;
import app.usecase.CreateGameUseCase;
import app.usecase.FlipLandMarkUseCase;
import app.usecase.RollDiceUseCase;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import spring.presenter.BuyCardPresenter;
import spring.presenter.CreateGamePresenter;
import spring.presenter.FlipLandMarkPresenter;
import spring.presenter.RollDicePresenter;
import spring.requests.CreateGameRequest;

import static org.springframework.http.ResponseEntity.noContent;

Expand All @@ -23,6 +23,7 @@ public class GameController {
private final RollDiceUseCase rollDiceUseCase;
private final BuyCardUseCase buyCardUseCase;
private final FlipLandMarkUseCase flipLandMarkUseCase;
private final CreateGameUseCase createGameUseCase;

@PostMapping("/{gameId}/roll-dice")
public ResponseEntity<?> rollTheDice(@PathVariable String gameId, @RequestBody RollDiceRequest request) {
Expand Down Expand Up @@ -54,10 +55,20 @@ public ResponseEntity<?> flipLandMark(@PathVariable String gameId, @RequestBody
.orElse(noContent().build());
}

@PostMapping("/createGame")
public ResponseEntity<?> createGame(@RequestBody CreateGameRequest request) {
var presenter = new CreateGamePresenter();
createGameUseCase.execute(request.toRequest(), presenter);

public record RollDiceRequest(String playerId, int diceCount) {
return presenter.getViewModel()
.map(ResponseEntity::ok)
.orElse(ResponseEntity.status(HttpStatus.BAD_REQUEST).build());
}


public record RollDiceRequest(String playerId, boolean isTwoDices) {
public RollDiceUseCase.Request toRequest(String gameId) {
return new RollDiceUseCase.Request(gameId, playerId, diceCount);
return new RollDiceUseCase.Request(gameId, playerId, isTwoDices);
}
}

Expand Down
18 changes: 18 additions & 0 deletions src/main/java/spring/presenter/AbstractPresenter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package spring.presenter;

import app.usecase.Presenter;
import domain.events.DomainEvent;

import java.util.List;
import java.util.Optional;

public abstract class AbstractPresenter implements Presenter {
@SuppressWarnings("unchecked")
public static <T extends DomainEvent> Optional<T> getEvent(List<DomainEvent> events,
Class<T> type) {
return events.stream()
.filter(e -> type.isAssignableFrom(e.getClass()))
.map(e -> (T) e)
.findFirst();
}
}
Loading

0 comments on commit 976cdb0

Please sign in to comment.