Skip to content

Commit

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

Feature/add player buy card usecase
  • Loading branch information
keytsai authored Sep 20, 2023
2 parents 1ef8f38 + a805747 commit 4717774
Show file tree
Hide file tree
Showing 33 changed files with 852 additions and 215 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok:1.18.26'
testCompileOnly 'org.projectlombok:lombok:1.18.26'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.26'

// https://mvnrepository.com/artifact/javax.inject/javax.inject
implementation group: 'javax.inject', name: 'javax.inject', version: '1'
}

test {
Expand Down
47 changes: 47 additions & 0 deletions src/main/java/app/usecase/BuyCardUseCase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package app.usecase;

import app.exception.NotFoundException;
import app.output.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 BuyCardUseCase {
private final GameRepository gameRepository;

public void execute(Request request, Presenter presenter) {
Game game = findGameById(request.gameId);
List<DomainEvent> events = game.turnPlayerBuyCard(request.getPlayerId(), request.getCardName());
gameRepository.save(game);
presenter.present(events);
}

private Game findGameById(String gameId) {
return gameRepository.findById(gameId).orElseThrow(NotFoundException::new);
}


@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Request {
private String gameId;
private String playerId;
private String cardName;

}

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


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

import app.exception.NotFoundException;
import app.output.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;

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

public void execute(FlipLandMarkUseCase.Request request, FlipLandMarkPresenter presenter) {
Game game = findGameById(request.gameId);
List<DomainEvent> events = game.turnPlayerFlipLandMark(request.getPlayerId(), request.getCardName());
gameRepository.save(game);
presenter.present(events);
}

private Game findGameById(String gameId) {
return gameRepository.findById(gameId).orElseThrow(NotFoundException::new);
}

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

@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Request {
private String gameId;
private String playerId;
private String cardName;
}
}
5 changes: 2 additions & 3 deletions src/main/java/app/usecase/RollDiceUseCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.hibernate.annotations.NotFound;
import org.springframework.stereotype.Service;

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

@Service
@Named
@RequiredArgsConstructor
public class RollDiceUseCase {
private final GameRepository gameRepository;
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/domain/EffectHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ public void takeEffectGreen(Player turnPlayer, Bank bank, Establishment establis
}

// green: 當你自己骰出這個數字時,可以從銀行獲得x元
if (turnPlayer.hasLandmarkFlipped(ShoppingMall.class)) {
if (turnPlayer.hasLandmarkFlipped(ShoppingMall.class) && establishment.getCardType() == CardType.SHOP) {
effectCoins += 1;
}

turnPlayer.gainCoin(effectCoins);
bank.payCoin(effectCoins);
}
Expand Down
57 changes: 51 additions & 6 deletions src/main/java/domain/Game.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package domain;

import domain.card.establishment.Bakery;
import domain.card.establishment.Establishment;
import domain.card.establishment.IndustryColor;
import domain.card.establishment.WheatField;
import domain.card.landmark.Landmark;
import domain.card.landmark.TrainStation;
import domain.events.DomainEvent;
import domain.events.RollDiceEvent;
import domain.events.*;
import domain.exceptions.MachiKoroException;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

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

@Builder
@Data
Expand Down Expand Up @@ -57,7 +60,6 @@ public Bank getBank() {
}

public void setUp() {

for (Player player : players) {
player.gainCoin(3);
bank.payCoin(3);
Expand All @@ -67,6 +69,10 @@ public void setUp() {
}
}

public Player getPlayer(String playerId) {
return players.stream().filter(player -> playerId.equals(player.getId())).findFirst().orElseThrow();
}

public List<Player> getPlayers() {
return players;
}
Expand Down Expand Up @@ -107,9 +113,8 @@ public List<Player> getPlayersExcludeTurnPlayer() {
}

public List<DomainEvent> rollDice(String playerId, int diceCount) {
if (!playerId.equals(turnPlayer.getId())) {
throw new IllegalArgumentException("Turn player id is incorrect");
}
// TODO : diceCount 可以用 true or false 判斷,因為我們只有一顆骰子或兩顆骰子的情況
checkIsTurnPlayer(playerId);

if ((diceCount > 1 && !turnPlayer.hasLandmarkFlipped(TrainStation.class)) || diceCount > 2 || diceCount < 1) {
throw new IllegalArgumentException("Invalid quantity of dice");
Expand All @@ -122,4 +127,44 @@ public List<DomainEvent> rollDice(String playerId, int diceCount) {
takeAllPlayersEffect();
return List.of(event);
}

public List<DomainEvent> turnPlayerBuyCard(String playerId, String cardName) {
checkIsTurnPlayer(playerId);
Establishment establishment = marketplace.findEstablishmentByName(cardName);
turnPlayer.buyEstablishment(establishment, bank);
marketplace.removeEstablishment(establishment);
DomainEvent buyEstablishmentEvent = new BuyCardEvent(String.format("玩家 %s 花費了 %d 元 建造了 %s", turnPlayer.getId(), establishment.getConstructionCost(), establishment.getName()));
updateTurnPlayerToNextOne();
return List.of(buyEstablishmentEvent);
}


private void checkIsTurnPlayer(String playerId) {
if (!playerId.equals(turnPlayer.getId())) {
throw new MachiKoroException("Turn player id is incorrect");
}
}

public List<DomainEvent> turnPlayerFlipLandMark(String playerId, String cardName) {
checkIsTurnPlayer(playerId);
Landmark landmark = turnPlayer.getHandCard().getLandmarks().stream().filter(lm -> cardName.equals(lm.getName())).findFirst().orElseThrow(NoSuchElementException::new);
turnPlayer.flipLandMark(landmark, bank);
if (isGameOver(turnPlayer)) {
DomainEvent GameOverEvent = new GameOverEvent(String.format("玩家 %s 勝利", turnPlayer.getId()));
return List.of(GameOverEvent);
} else {
DomainEvent flipLandMarkEvent = new FlipLandMarkEvent(String.format("玩家 %s 花費了 %d 元 建造了 %s", turnPlayer.getId(), landmark.getConstructionCost(), landmark.getName()));
updateTurnPlayerToNextOne();
return List.of(flipLandMarkEvent);
}
}

private boolean isGameOver(Player turnPlayer) {
return turnPlayer.getLandmarks().stream().allMatch(Landmark::isFlipped);
}

private void updateTurnPlayerToNextOne() {
int index = players.indexOf(turnPlayer);
turnPlayer = players.get((index + 1) % players.size());
}
}
7 changes: 6 additions & 1 deletion src/main/java/domain/HandCard.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;

public class HandCard {

Expand Down Expand Up @@ -52,12 +53,16 @@ public List<Landmark> getLandmarks() {
public void flipLandMark(Class<? extends Landmark> landmark) {
landmarks
.stream()
.filter(l -> l.getClass() == landmark && !l.isFlipped())
.filter(l -> l.getClass() == landmark && !l.isFlipped())
.findFirst()
.map(targetlandmark -> {
targetlandmark.flipped();
return targetlandmark;
})
.orElseThrow(() -> new NoSuchElementException("This LandMark has been flipped"));
}

public List<Establishment> getEstablishments(Class<? extends Establishment> establishment) {
return establishments.stream().filter(e -> e.getClass() == establishment).collect(Collectors.toList());
}
}
63 changes: 40 additions & 23 deletions src/main/java/domain/Marketplace.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,42 +16,45 @@
import domain.card.establishment.Stadium;
import domain.card.establishment.TvStation;
import domain.card.establishment.WheatField;
import domain.exceptions.MachiKoroException;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;
import org.apache.logging.log4j.util.Supplier;

import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Marketplace {
private final int IMPORTANT_ESTABLISHMENT_QUANTITY = 4;
private final int ESTABLISHMENT_QUANTITY = 6;

@Builder.Default
private List<Establishment> establishments = new ArrayList<>();
private Map<String, List<Establishment>> establishmentMap = new HashMap<>();

public void initial() {
establishments.addAll(generateCards(10, Bakery::new));
establishments.addAll(generateCards(10, WheatField::new));
establishments.addAll(generateCards(6, Cafe::new));
establishments.addAll(generateCards(6, AppleOrchard::new));
establishments.addAll(generateCards(6, CheeseFactory::new));
establishments.addAll(generateCards(6, ConvenienceStore::new));
establishments.addAll(generateCards(6, FamilyRestaurant::new));
establishments.addAll(generateCards(6, Forest::new));
establishments.addAll(generateCards(6, FruitAndVegetableMarket::new));
establishments.addAll(generateCards(6, FurnitureFactory::new));
establishments.addAll(generateCards(6, Mine::new));
establishments.addAll(generateCards(6, Ranch::new));
public Marketplace() {
establishmentMap = new HashMap<>();
initial();
}

establishments.addAll(generateCards(4, Stadium::new));
establishments.addAll(generateCards(4, TvStation::new));
establishments.addAll(generateCards(4, BusinessCenter::new));
public void initial() {
establishmentMap.put(Bakery.class.getSimpleName(), generateCards(10, Bakery::new));
establishmentMap.put(WheatField.class.getSimpleName(), generateCards(10, WheatField::new));
establishmentMap.put(Cafe.class.getSimpleName(), generateCards(6, Cafe::new));
establishmentMap.put(AppleOrchard.class.getSimpleName(), generateCards(6, AppleOrchard::new));
establishmentMap.put(CheeseFactory.class.getSimpleName(), generateCards(6, CheeseFactory::new));
establishmentMap.put(ConvenienceStore.class.getSimpleName(), generateCards(6, ConvenienceStore::new));
establishmentMap.put(FamilyRestaurant.class.getSimpleName(), generateCards(6, FamilyRestaurant::new));
establishmentMap.put(Forest.class.getSimpleName(), generateCards(6, Forest::new));
establishmentMap.put(FruitAndVegetableMarket.class.getSimpleName(), generateCards(6, FruitAndVegetableMarket::new));
establishmentMap.put(FurnitureFactory.class.getSimpleName(), generateCards(6, FurnitureFactory::new));
establishmentMap.put(Mine.class.getSimpleName(), generateCards(6, Mine::new));
establishmentMap.put(Ranch.class.getSimpleName(), generateCards(6, Ranch::new));
establishmentMap.put(Stadium.class.getSimpleName(), generateCards(4, Stadium::new));
establishmentMap.put(TvStation.class.getSimpleName(), generateCards(4, TvStation::new));
establishmentMap.put(BusinessCenter.class.getSimpleName(), generateCards(4, BusinessCenter::new));
}

private <T> List<T> generateCards(int amount, Supplier<T> cardSupplier) {
Expand All @@ -60,7 +63,21 @@ private <T> List<T> generateCards(int amount, Supplier<T> cardSupplier) {
.collect(Collectors.toList());
}

public List<Establishment> getEstablishments() {
return establishments;

public Map<String, List<Establishment>> getEstablishmentMap() {
return establishmentMap;
}

public Establishment findEstablishmentByName(String cardName) {
List<Establishment> matchEstablishments = establishmentMap.get(cardName);
if (matchEstablishments.isEmpty()) {
throw new MachiKoroException("建築藍圖已經沒有此建築物了,購買失敗");
} else
return matchEstablishments.get(0);
}

public void removeEstablishment(Establishment establishment) {
List<Establishment> establishments = establishmentMap.get(establishment.getClass().getSimpleName());
establishments.remove(establishment);
}
}
Loading

0 comments on commit 4717774

Please sign in to comment.