Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
df9326e
docs: ๊ธฐ๋Šฅ๋ชฉ๋ก ์ž‘์„ฑ
ghkdtjfxkd Mar 25, 2026
a011878
feat: ์ด๋™ ์ „๋žต ๋„๋ฉ”์ธ ์Šค์ผˆ๋ ˆํ†ค ์ƒ์„ฑ
ghkdtjfxkd Mar 25, 2026
cf2c421
merge: step1-pre into step1
ghkdtjfxkd Mar 25, 2026
f9f48d0
feat: ์ด๋™ ์ „๋žต ์žฅ๊ตฐ -> ๋ชฉ์ ์ง€ ์ด๋™ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ๊ตฌํ˜„
yj9107v Mar 25, 2026
bb0c9a5
refactor: ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ•„๋“œ ์ œ๊ฑฐ
ghkdtjfxkd Mar 25, 2026
711297d
feat: ์‚ฌ ์ด๋™ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ํ™•์ธ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
ghkdtjfxkd Mar 25, 2026
4d33f90
feat: ์ด๋™ ์ „๋žต ์กธ(์ดˆ/ํ•œ) -> ๋ชฉ์ ์ง€ ์ด๋™ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ๊ตฌํ˜„
yj9107v Mar 25, 2026
1d59f24
wip: ์š”๊ตฌ ์‚ฌํ•ญ ๋ฐ˜์˜์„ ์œ„ํ•œ ์ž„์‹œ ์ €์žฅ
ghkdtjfxkd Mar 25, 2026
4603de9
feat: ์žฅ๊ธฐํŒ ๊ธฐ๋ฌผ ์ดˆ๊ธฐํ™” ๊ธฐ๋Šฅ ์ถ”๊ฐ€
ghkdtjfxkd Mar 25, 2026
86078f8
wip: ๋งˆ ์ด๋™ ๊ตฌํ˜„ ์ค‘ ๋“œ๋ผ์ด๋ฒ„ ๋ณ€๊ฒฝ
yj9107v Mar 25, 2026
6f8377b
feat: ๋งˆ ์ด๋™ ๊ทœ์น™ ์ถ”๊ฐ€
ghkdtjfxkd Mar 26, 2026
1372e03
merge: step1-personal into step1
ghkdtjfxkd Mar 26, 2026
3f33629
feat: ์ƒ ๊ธฐ๋ฌผ ์ด๋™ ๊ตฌํ˜„
yj9107v Mar 26, 2026
b5fb478
docs: ์ƒ ๊ธฐ๋ฌผ ์ด๋™ ๊ตฌํ˜„ ์™„๋ฃŒ
yj9107v Mar 26, 2026
774073a
feat: ์ฐจ ๊ธฐ๋ฌผ ์ด๋™ ๊ตฌํ˜„ ์™„๋ฃŒ
yj9107v Mar 26, 2026
4b689ae
refactor: MoveStrategy API ๋ฉ”์„œ๋“œ ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ
ghkdtjfxkd Mar 26, 2026
aeea4d3
feat: ํฌ ์ด๋™ ์ „๋žต ์ถ”๊ฐ€
ghkdtjfxkd Mar 26, 2026
cf1f512
docs: ๋ˆ„๋ฝ๋œ ํ•ญ๋ชฉ๋“ค ๋ฐ˜์˜
ghkdtjfxkd Mar 26, 2026
ccfede6
feat: ์žฅ๊ธฐํŒ ๊ธฐ๋ฌผ์ด ์ด๋™ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ํ™•์ธ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
yj9107v Mar 26, 2026
5c6426a
feat: ๊ธฐ๋ฌผ ์ด๋™ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
ghkdtjfxkd Mar 26, 2026
dabf867
feat: ์žฅ๊ธฐ ๊ฒŒ์ž„ ํ”Œ๋ ˆ์ด์–ด ์„ ํƒ ๊ธฐ๋ฌผ ๋ฐ ๋ชฉ์ ์ง€ ์ด๋™ ๊ฒ€์ฆ ์ถ”๊ฐ€
yj9107v Mar 27, 2026
641e6a0
wip: ๋ฆฌํŒฉํ† ๋ง ์ „ ์ž„์‹œ ์ €์žฅ
ghkdtjfxkd Mar 27, 2026
a83b41d
refactor: ๊ธฐ๋ฌผ ๋‹คํ˜•์„ฑ ๋ณ€๊ฒฝ
ghkdtjfxkd Mar 27, 2026
c783237
test: ๊ธฐ๋ฌผ ์›€์ง์ž„ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
ghkdtjfxkd Mar 27, 2026
cef2f61
merge: refactor-piece into step1
ghkdtjfxkd Mar 27, 2026
e20dd87
fix: ๊ธฐ๋ฌผ์ด ์ด๋™์— ์„ฑ๊ณตํ•˜๋ฉด ๊ธฐ๋ฌผ์˜ ์œ„์น˜๊ฐ€ ๋ณ€๊ฒฝ๋˜๊ฒŒ ์ˆ˜์ •
yj9107v Mar 27, 2026
3f2b921
feat: ํฌ๋Š” ํฌ๋ฅผ ๋„˜์ง€ ๋ชปํ•˜๋Š” ๊ธฐ๋Šฅ ์ถ”๊ฐ€
ghkdtjfxkd Mar 27, 2026
1713fac
feat: ํฌ์˜ ์ด๋™ ๊ทœ์น™ ์ถ”๊ฐ€
yj9107v Mar 27, 2026
59979cb
feat: ํฌ์˜ ์ด๋™ ๊ทœ์น™ ์ถ”๊ฐ€
yj9107v Mar 27, 2026
ca34273
chore: ์ปจํŠธ๋กค๋Ÿฌ ์Šค์ผˆ๋ ˆํ†ค ์ถ”๊ฐ€
ghkdtjfxkd Mar 27, 2026
d22822c
feat: ์ปจํŠธ๋กค๋Ÿฌ ์ถ”๊ฐ€ ๋ฐ ๊ฒŒ์ž„ ์ง„ํ–‰ ๊ตฌํ˜„
ghkdtjfxkd Mar 28, 2026
35f8a1d
refactor: JanggiGame ์˜ˆ์™ธ ์ˆ˜์ • ๋ฐ ํŒจํ‚ค์ง€ ๊ตฌ์กฐ ๋ณ€๊ฒฝ
ghkdtjfxkd Mar 28, 2026
10943e7
refactor: JanggiGame ๊ตฌ์กฐ ์ผ๋ถ€ ๋ณ€๊ฒฝ
ghkdtjfxkd Mar 28, 2026
39c82d0
refactor: PieceProperty ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ์ด๋™ ์ „๋žต ๋‚ด๋ถ€ ๋ณ€๊ฒฝ
ghkdtjfxkd Mar 28, 2026
9fd033a
refactor: ๊ถ ์ด๋™ ์ „๋žต ๋‚ด๋ถ€ ๋ณ€๊ฒฝ
ghkdtjfxkd Mar 28, 2026
aa1ba94
refactor: ์ด๋™ ๊ทœ์น™ ๋ฆฌํŒฉํ† ๋ง
ghkdtjfxkd Mar 28, 2026
33dc115
refactor: ์žฅ๊ธฐํŒ ๋ฒ”์œ„ ์ ๊ฒ€ ์ฑ…์ž„ ์ด๋™
ghkdtjfxkd Mar 28, 2026
6a9dfe4
refactor: ์กธ ์ด๋™ ์ „๋žต ๋‚ด๋ถ€ ๋ฆฌํŒฉํ† ๋ง
ghkdtjfxkd Mar 28, 2026
63349a6
refactor: ์ƒ ์ด๋™ ์ „๋žต ๋‚ด๋ถ€ ๋ณ€๊ฒฝ
ghkdtjfxkd Mar 28, 2026
73f2ac4
refactor: Board ๋‚ด๋ถ€ ์ •๋ฆฌ
ghkdtjfxkd Mar 28, 2026
64f0661
refactor: ํฌ ๋‚ด๋ถ€ ์ •๋ฆฌ
ghkdtjfxkd Mar 30, 2026
64206c8
merge: step1-refactor into step1
ghkdtjfxkd Mar 30, 2026
554b18b
refactor: ์˜ˆ์™ธ ํ˜•์‹ ์ถ”๊ฐ€
ghkdtjfxkd Mar 30, 2026
a874f60
refactor: Controller์˜ ์ถœ๋ ฅ ์ฑ…์ž„ ์ด๋™
ghkdtjfxkd Mar 30, 2026
939e21f
refactor: ์ฐจ ์ด๋™๋กœ์ง ๋‚ด๋ถ€ ๋ฆฌํŒฉํ† ๋ง
ghkdtjfxkd Mar 30, 2026
fa4c5e1
refactor: cleanup
ghkdtjfxkd Mar 30, 2026
1b21a22
docs: README.md ๋ˆ„๋ฝ๋œ ํ•ญ๋ชฉ ๋ฐ˜์˜
ghkdtjfxkd Mar 30, 2026
ba3e25a
chore: ์‚ฌ์†Œํ•œ ์ˆ˜์ •
ghkdtjfxkd Mar 30, 2026
597c980
feat: ๊ถ์„ฑ ์œ„์น˜ ํ™•์ธ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
ghkdtjfxkd Mar 31, 2026
5720588
merge: step1-refactor into step1
ghkdtjfxkd Apr 1, 2026
8010683
wip: rebase ์ „ ์ž„์‹œ ์ €์žฅ
ghkdtjfxkd Apr 2, 2026
2ea99a6
fix: merge ์ถฉ๋Œ ํ•ด๊ฒฐ
ghkdtjfxkd Apr 2, 2026
6d6c1e2
feat: ๊ถ์„ฑ ๊ธฐ๋ฌผ ์ด๋™ ์ „๋žต ์ถ”๊ฐ€
ghkdtjfxkd Apr 2, 2026
a6a9540
refactor: cleanup
ghkdtjfxkd Apr 2, 2026
6260fc7
feat: ์ดˆ๋‚˜๋ผ ์กธ์˜ ๊ถ์„ฑ ๋‚ด๋ถ€ ์ด๋™ ๊ทœ์น™ ์ถ”๊ฐ€
ghkdtjfxkd Apr 2, 2026
23b94d9
feat: ํ•œ๋‚˜๋ผ ์กธ์˜ ๊ถ์„ฑ ๋‚ด๋ถ€ ์ด๋™ ๊ทœ์น™ ์ถ”๊ฐ€
ghkdtjfxkd Apr 2, 2026
b0b18ca
merge: step2-soldier into step2
ghkdtjfxkd Apr 2, 2026
96fb026
feat: ํฌ์˜ ๊ถ์„ฑ ๋‚ด๋ถ€ ์ด๋™ ๊ทœ์น™ ์ถ”๊ฐ€
ghkdtjfxkd Apr 3, 2026
ba584ad
feat: ํฌ์™€ ์ฐจ์˜ ๊ถ์„ฑ ์ด๋™ ๊ทœ์น™ ์ถ”๊ฐ€
ghkdtjfxkd Apr 3, 2026
12c191c
refactor: ์ƒ๊ณผ ๋งˆ ๋‚ด๋ถ€ ๋ฆฌํŒฉํ† ๋ง
ghkdtjfxkd Apr 3, 2026
e49ec2e
feat: ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์€ ํ˜•์‹ ์ž…๋ ฅ ์‹œ ์˜ˆ์™ธ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
ghkdtjfxkd Apr 3, 2026
ab9fc0a
refactor: DB ๋„์ž… ์ „ ์Šค์ผˆ๋ ˆํ†ค ์ƒ์„ฑ
ghkdtjfxkd Apr 3, 2026
6c1bdcb
refactor: Jdbc ์ €์žฅ์†Œ ์ถ”๊ฐ€ ๋ฐ HikariCP ์˜์กด์„ฑ ์ถ”๊ฐ€
ghkdtjfxkd Apr 3, 2026
1e08a60
feat: DB ๊ธฐ๋Šฅ ์ถ”๊ฐ€
ghkdtjfxkd Apr 8, 2026
de4c844
merge: step2-db into step2
ghkdtjfxkd Apr 8, 2026
ad52e57
feat: ์ข…๋ฃŒ๋˜์ง€ ์•Š์€ ๊ฒŒ์ž„ ์„ ํƒ ๋ฐ ์ด์–ดํ•˜๊ธฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
ghkdtjfxkd Apr 9, 2026
2a95f16
merge: step2-db into step2
ghkdtjfxkd Apr 9, 2026
19a46d9
feat: ์ ์ˆ˜ ํ•ฉ ๊ณ„์‚ฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
ghkdtjfxkd Apr 9, 2026
55c7232
merge: step2-point into step2
ghkdtjfxkd Apr 9, 2026
d78521b
fix: gameSnapshot์ด ์Œ“์ด๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ
ghkdtjfxkd Apr 13, 2026
0c16b29
refactor: ๊ฒŒ์ž„ ID ์ž…๋ ฅ์‹œ Dto๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ
ghkdtjfxkd Apr 13, 2026
efcaef8
refactor: ๊ฒŒ์ž„ id ์กฐํšŒ ์ฒ˜๋ฆฌ
ghkdtjfxkd Apr 13, 2026
eac763b
test: repository, service ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
ghkdtjfxkd Apr 13, 2026
65b9aa5
refactor: cleanup
ghkdtjfxkd Apr 13, 2026
cad20bd
merge: step2-feedback into step2
ghkdtjfxkd Apr 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ repositories {
}

dependencies {

implementation 'com.zaxxer:HikariCP:7.0.2'
// implementation 'ch.qos.logback:logback-classic:1.4.14'
implementation 'com.h2database:h2:2.2.224'
testImplementation platform('org.junit:junit-bom:5.11.4')
testImplementation platform('org.assertj:assertj-bom:3.27.3')
testImplementation('org.junit.jupiter:junit-jupiter')
Expand All @@ -21,6 +25,18 @@ java {
}
}

tasks.withType(JavaCompile) {
options.compilerArgs += ['--enable-preview']
}

tasks.withType(Test) {
jvmArgs(['--enable-preview'])
}

tasks.withType(JavaExec) {
jvmArgs(['--enable-preview'])
}

test {
useJUnitPlatform()
}
Binary file added janggi_db.mv.db
Binary file not shown.
447 changes: 447 additions & 0 deletions janggi_db.trace.db

Large diffs are not rendered by default.

12 changes: 2 additions & 10 deletions src/main/java/Application.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
import config.JanggiConfig;
import controller.JanggiController;
import domain.Board;
import domain.GameStatus;
import domain.JanggiGame;
import factory.JanggiBoardFactory;

public class Application {
public static void main(String[] args) {
JanggiBoardFactory janggiBoardFactory = new JanggiBoardFactory();
Board board = Board.of(janggiBoardFactory.initialBoard());

JanggiGame janggiGame = new JanggiGame(board, GameStatus.GREEN_PLAYER_TURN);
JanggiController janggiController = new JanggiController(janggiGame);

JanggiController janggiController = JanggiConfig.setupController();
janggiController.run();
}
}
57 changes: 57 additions & 0 deletions src/main/java/config/JanggiConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package config;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import controller.JanggiController;
import dao.JanggiGameDao;
import dao.JanggiGameStateDao;
import infrastructure.TransactionContext;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import repository.JanggiRepository;
import repository.JdbcJanggiRepository;
import service.JanggiCommandService;
import service.JanggiQueryService;

public class JanggiConfig {

public static JanggiController setupController() {
JanggiRepository janggiRepository = setupJanggiRepository();

JanggiCommandService janggiCommandService = new JanggiCommandService(janggiRepository);
JanggiQueryService janggiQueryService = new JanggiQueryService(janggiRepository);

return new JanggiController(janggiCommandService, janggiQueryService);
}

private static DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:h2:file:./janggi_db;MODE=MySQL");
config.setUsername("root");
config.setPassword("password");
return new HikariDataSource(config);
}

private static JdbcJanggiRepository setupJanggiRepository() {
DataSource dataSource = dataSource();
try {
initSchema(dataSource);
} catch (SQLException e) {
throw new RuntimeException("์Šคํ‚ค๋งˆ ์ดˆ๊ธฐํ™” ์‹คํŒจ", e);
}
TransactionContext.init(dataSource);
return new JdbcJanggiRepository(
new JanggiGameDao(),
new JanggiGameStateDao()
);
}

private static void initSchema(DataSource dataSource) throws SQLException {
try (Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement()) {
stmt.execute("RUNSCRIPT FROM 'classpath:schema.sql'");
}
}
}
4 changes: 3 additions & 1 deletion src/main/java/controller/ExecutableTask.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package controller;

import exception.JanggiGameException;

@FunctionalInterface
interface ExecutableTask {
void execute() throws IllegalArgumentException;
void execute() throws JanggiGameException;
}
99 changes: 83 additions & 16 deletions src/main/java/controller/JanggiController.java
Original file line number Diff line number Diff line change
@@ -1,50 +1,104 @@
package controller;

import domain.JanggiGame;
import domain.Position;
import dto.SelectResumeOptionRequest;
import dto.SelectPositionRequest;
import dto.SelectSavedGameRequest;
import exception.JanggiGameException;
import java.util.function.Supplier;
import service.JanggiCommandService;
import service.JanggiQueryService;
import view.InputView;
import view.OutputView;

public class JanggiController {

private final JanggiGame janggiGame;
private final JanggiCommandService commandService;
private final JanggiQueryService queryService;

public JanggiController(JanggiGame janggiGame) {
this.janggiGame = janggiGame;
private long currentGameId = 0L;

public JanggiController(JanggiCommandService commandService, JanggiQueryService queryService) {
this.commandService = commandService;
this.queryService = queryService;
}

public void run() {
while (!janggiGame.isGameFinished()) {
runPlayingPhase();
if(executeWithReturn(this::isPlayerWantPlayingUnfinishedGame)) {
runSavedGame();
return;
}
runNewGame();
}

private void runSavedGame() {
execute(this::setupSavedGameId);
runGame();
}

private void setupSavedGameId() {
SelectSavedGameRequest request = InputView.selectSavedGameId(queryService.findUnfinishedGameInfos());
queryService.isInProgress(request.gameId());
currentGameId = request.gameId();
}

private boolean isPlayerWantPlayingUnfinishedGame() {
if(queryService.hasUnfinishedGameId()) {
SelectResumeOptionRequest request = InputView.selectLoadGameOrNewGame();
return request.select();
}
return false;
}

private void runNewGame() {
setupNewGameId();
runGame();
}

private void runGame() {
runPlayingPhase();
runResultPhase();
}

private void setupNewGameId() {
currentGameId = commandService.setupGame();
}

private void runPlayingPhase() {
displayCurrentGameState();
execute(this::movePiece);
while (queryService.isInProgress(currentGameId)) {
displayCurrentGameState();
execute(this::movePiece);
}
}

private void displayCurrentGameState() {
OutputView.printBoard(janggiGame.allFactors());
OutputView.printCurrentPlayerTurn(janggiGame.currentPlayerTurn());
OutputView.printBoard(queryService.allFactors(currentGameId));
OutputView.printCurrentPlayerTurn(queryService.currentPlayerTurn(currentGameId));
OutputView.printCurrentPlayerPiecesPointSum(queryService.currentPlayerPiecesPointSum(currentGameId));
}

private void movePiece() {
Position selected = selectPiecePositionToMove();
Position target = selectPiecePositionToGoFrom(selected);

commandService.move(currentGameId, selected, target);
}

private Position selectPiecePositionToMove() {
SelectPositionRequest selectRequest = InputView.selectPiecePosition();
Position selected = Position.of(selectRequest.row(), selectRequest.col());
return Position.of(selectRequest.row(), selectRequest.col());
}

SelectPositionRequest targetRequest = InputView.selectTargetPositionOf(janggiGame.findPieceInfoAt(selected));
Position target = Position.of(targetRequest.row(), targetRequest.col());
private Position selectPiecePositionToGoFrom(Position selected) {
SelectPositionRequest targetRequest =
InputView.selectTargetPositionWith(queryService.findPieceInfoAt(currentGameId, selected));

janggiGame.move(selected, target);
return Position.of(targetRequest.row(), targetRequest.col());
}

private void runResultPhase() {
OutputView.printBoard(janggiGame.allFactors());
OutputView.printResult(janggiGame.gameStatus());
OutputView.printBoard(queryService.allFactors(currentGameId));
OutputView.printResult(queryService.gameStatus(currentGameId));
}

private void execute(ExecutableTask task) {
Expand All @@ -59,4 +113,17 @@ private void execute(ExecutableTask task) {
}
}
}

private <T> T executeWithReturn(Supplier<T> task) {
while (true) {
try {
T result = task.get();
OutputView.printTaskDivider();
return result;
} catch (JanggiGameException e) {
OutputView.printError(e.getMessage());
OutputView.printTaskDivider();
}
}
}
}
113 changes: 113 additions & 0 deletions src/main/java/dao/JanggiGameDao.java
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ด ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ํŒจํ‚ค์ง€ ๊ตฌ์กฐ์— ๋Œ€ํ•œ ํ”ผ๋“œ๋ฐฑ์ž…๋‹ˆ๋‹ค.

๊ฐ™์€ ์œ„๊ณ„์— ๋ชจ๋“  ์œ ํ˜•์˜ ํŒจํ‚ค์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ถ”์ƒํ™” ๋‹จ๊ณ„์— ๋”ฐ๋ผ ํŒจํ‚ค์ง€๋ฅผ ๊ทธ์— ๋งž์ถฐ ์ด๋™ํ•˜๋Š”๊ฑด ์–ด๋–จ๊นŒ์š”?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์‚ฌ์‹ค ์ œ๊ฐ€ ๋ง์”€ํ•ด์ฃผ์‹  ๋ถ€๋ถ„์„ ์ž˜ ์ดํ•ด ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค...

์ถ”์ƒํ™” ๋‹จ๊ณ„์— ๋”ฐ๋ผ ๋ฌถ๋Š”๋‹ค๋ฉด presentation, application, domain, infrastructure ๊ฐ™์€ ๊ณ„์ธต ๊ธฐ์ค€์œผ๋กœ ์žฌ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉํ–ฅ์„ ๋ง์”€ํ•˜์‹œ๋Š” ๊ฑธ๊นŒ์š”?!

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ถ”์ƒํ™” ๋‹จ๊ณ„์— ๋”ฐ๋ผ ๋ฌถ๋Š”๋‹ค๋ฉด presentation, application, domain, infrastructure ๊ฐ™์€ ๊ณ„์ธต ๊ธฐ์ค€์œผ๋กœ ์žฌ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉํ–ฅ์„ ๋ง์”€ํ•˜์‹œ๋Š” ๊ฑธ๊นŒ์š”?!

๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๊ณ  ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ์„๊ฑฐ ๊ฐ™์•„์š”! ์ œ๊ฐ€ ๋ง์”€๋“œ๋ฆฐ ํฌ์ธํŠธ๋Š” repository ํ•˜์œ„์— dao๊ฐ€ ์ž‡์–ด์•ผํ• ๊ฑฐ ๊ฐ™์€๋ฐ ๊ฐ™์€ ์œ„๊ณ„์— ์žˆ๋Š”๊ฑธ ์ˆ˜์ •ํ•ด๋‹ฌ๋ผ๋Š” ๋ง์ด์—ˆ์Šต๋‹ˆ๋‹ค!

Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package dao;

import dto.PieceSnapshot;
import dto.UnfinishedGameInfo;
import infrastructure.TransactionContext;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class JanggiGameDao {

public long insertGame(List<PieceSnapshot> pieces) throws SQLException {
long gameId = insert();
insertPieces(gameId, pieces);
return gameId;
}

public long updateGame(long gameId, List<PieceSnapshot> pieces) throws SQLException {
deletePieces(gameId);
insertPieces(gameId, pieces);
return gameId;
}

private long insert() throws SQLException {
String sql = "INSERT INTO game (created_at) VALUES (NOW())";

try (PreparedStatement ps = TransactionContext.getPreparedStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
ps.executeUpdate();

ResultSet keys = ps.getGeneratedKeys();
if (keys.next()) {
return keys.getLong(1);
}
throw new SQLException("game INSERT ํ›„ id ํš๋“ ์‹คํŒจ");
}
}

private void deletePieces(long gameId) throws SQLException {
String sql = "DELETE FROM piece WHERE game_id = ?";
try (PreparedStatement ps = TransactionContext.getPreparedStatement(sql)) {
ps.setLong(1, gameId);
ps.executeUpdate();
}
}

private void insertPieces(long gameId, List<PieceSnapshot> pieces) throws SQLException {
String sql = "INSERT INTO piece (game_id, pos_row, pos_col, piece_name, team) VALUES (?, ?, ?, ?, ?)";

try (PreparedStatement ps = TransactionContext.getPreparedStatement(sql)) {
for (PieceSnapshot piece : pieces) {
ps.setLong(1, gameId);
ps.setInt(2, piece.row());
ps.setInt(3, piece.col());
ps.setString(4, piece.name());
ps.setString(5, piece.team());
ps.addBatch();
}
ps.executeBatch();
}
}

public List<PieceSnapshot> findAllPieces(long gameId) throws SQLException {
String sql = "SELECT pos_row, pos_col, piece_name, team FROM piece WHERE game_id = ?";

try (PreparedStatement ps = TransactionContext.getPreparedStatement(sql)) {
ps.setLong(1, gameId);

ResultSet rs = ps.executeQuery();
List<PieceSnapshot> pieces = new ArrayList<>();
while (rs.next()) {
pieces.add(PieceSnapshot.from(
rs.getInt("pos_row"),
rs.getInt("pos_col"),
rs.getString("piece_name"),
rs.getString("team")
));
}
return pieces;
}
}

public Optional<Long> findLatestUnfinishedGameId() throws SQLException {
String sql = "SELECT game_id FROM game_state WHERE is_finished = false ORDER BY last_played_at DESC LIMIT 1";

try (PreparedStatement ps = TransactionContext.getPreparedStatement(sql);
ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
return Optional.of(rs.getLong("game_id"));
}
return Optional.empty();
}
}

public List<UnfinishedGameInfo> findUnfinishedGameInfos() throws SQLException {
String sql = "SELECT game_id, last_played_at FROM game_state WHERE is_finished = false ORDER BY last_played_at ASC";

try (PreparedStatement ps = TransactionContext.getPreparedStatement(sql)){
ResultSet rs = ps.executeQuery();
List<UnfinishedGameInfo> unfinishedGames = new ArrayList<>();
while (rs.next()) {
unfinishedGames.add(UnfinishedGameInfo.from(
rs.getLong("game_id"),
rs.getTimestamp("last_played_at").toLocalDateTime()
));
}
return unfinishedGames;
}
}
}
Loading