Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions readable-code/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ repositories {
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
testImplementation("org.assertj:assertj-core:3.25.3")
testImplementation("org.mockito:mockito-inline:5.2.0")
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package cleancode.studycafe.misson7;

import cleancode.studycafe.misson7.config.StudyCafeConfig;
import cleancode.studycafe.misson7.io.handler.ConsoleInputHandler;
import cleancode.studycafe.misson7.io.handler.ConsoleOutputHandler;
import cleancode.studycafe.misson7.io.provider.LockerPassFileProvider;
import cleancode.studycafe.misson7.io.provider.SeatPassFileProvider;

public class StudyCafeApplication {

public static void main(String[] args) {
StudyCafeConfig config = new StudyCafeConfig(
new ConsoleInputHandler(),
new ConsoleOutputHandler(),
new SeatPassFileProvider(),
new LockerPassFileProvider()
);

StudyCafePassMachine studyCafePassMachine = new StudyCafePassMachine(config);
studyCafePassMachine.run();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package cleancode.studycafe.misson7;

import cleancode.studycafe.misson7.config.StudyCafeConfig;
import cleancode.studycafe.misson7.exception.AppException;
import cleancode.studycafe.misson7.exception.ProvideException;
import cleancode.studycafe.misson7.io.handler.InputHandler;
import cleancode.studycafe.misson7.io.handler.OutputHandler;
import cleancode.studycafe.misson7.model.pass.StudyCafePassType;
import cleancode.studycafe.misson7.model.pass.locker.StudyCafeLockerPass;
import cleancode.studycafe.misson7.model.pass.locker.StudyCafeLockerPasses;
import cleancode.studycafe.misson7.model.pass.order.StudyCafePassOrder;
import cleancode.studycafe.misson7.model.pass.seat.StudyCafeSeatPass;
import cleancode.studycafe.misson7.model.pass.seat.StudyCafeSeatPasses;
import cleancode.studycafe.misson7.provider.LockerPassProvider;
import cleancode.studycafe.misson7.provider.SeatPassProvider;

import java.util.Optional;

public class StudyCafePassMachine {

private final InputHandler inputHandler;
private final OutputHandler outputHandler;
private final SeatPassProvider seatPassProvider;
private final LockerPassProvider lockerPassProvider;

public StudyCafePassMachine(StudyCafeConfig config) {
this.inputHandler = config.getInputHandler();
this.outputHandler = config.getOutputHandler();
this.seatPassProvider = config.getSeatPassProvider();
this.lockerPassProvider = config.getLockerPassProvider();
}

public void run() {
try {
outputHandler.showWelcomeMessage();
outputHandler.showAnnouncement();

StudyCafeSeatPass selectedSeatPass = selectedSeatPass();
Optional<StudyCafeLockerPass> selectedLockerPass = selectedLockerPass(selectedSeatPass);

StudyCafePassOrder order = StudyCafePassOrder.of(
selectedSeatPass,
selectedLockerPass.orElse(null)
);
outputHandler.showPassOrderSummary(order);
} catch (AppException e) {
outputHandler.showSimpleMessage(e.getMessage());
} catch (ProvideException e) {
outputHandler.showSimpleMessage("이용권을 제공받을 수 없습니다.");
} catch (Exception e) {
outputHandler.showSimpleMessage("알 수 없는 오류가 발생했습니다.");
}
}

private StudyCafeSeatPass selectedSeatPass() {
StudyCafePassType passType = selectedPassType();
StudyCafeSeatPasses seatPassCandidates = findSeatPassCandidates(passType);

outputHandler.showSeatPassListForSelection(seatPassCandidates);
return inputHandler.getSelectSeatPass(seatPassCandidates);
}

private StudyCafePassType selectedPassType() {
outputHandler.askPassTypeSelection();
return inputHandler.getPassTypeSelectingUserAction();
}

private StudyCafeSeatPasses findSeatPassCandidates(StudyCafePassType passType) {
StudyCafeSeatPasses allPass = seatPassProvider.provide();
return allPass.findCandidatesBy(passType);
}

private Optional<StudyCafeLockerPass> selectedLockerPass(StudyCafeSeatPass seatPass) {
if (seatPass.cannotSelectLockerPass()) {
return Optional.empty();
}

Optional<StudyCafeLockerPass> lockerPassCandidate = findLockerPassCandidate(seatPass);
return lockerPassCandidate
.filter(this::isSelectedLockerPass);
}

private Optional<StudyCafeLockerPass> findLockerPassCandidate(StudyCafeSeatPass seatPass) {
StudyCafeLockerPasses lockerPasses = lockerPassProvider.provide();
return lockerPasses.findCandidateBy(seatPass);
}

private boolean isSelectedLockerPass(StudyCafeLockerPass lockerPass) {
outputHandler.askLockerPass(lockerPass);
return inputHandler.getLockerSelection();
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package cleancode.studycafe.tobe.config;
package cleancode.studycafe.misson7.config;

import cleancode.studycafe.tobe.io.handler.InputHandler;
import cleancode.studycafe.tobe.io.handler.OutputHandler;
import cleancode.studycafe.tobe.provider.LockerPassProvider;
import cleancode.studycafe.tobe.provider.SeatPassProvider;
import cleancode.studycafe.misson7.io.handler.InputHandler;
import cleancode.studycafe.misson7.io.handler.OutputHandler;
import cleancode.studycafe.misson7.provider.LockerPassProvider;
import cleancode.studycafe.misson7.provider.SeatPassProvider;

public class StudyCafeConfig {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package cleancode.studycafe.misson7.exception;

public class AppException extends RuntimeException {

public AppException(String message) {
super(message);
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cleancode.studycafe.tobe.exception;
package cleancode.studycafe.misson7.exception;

public class ProvideException extends RuntimeException {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package cleancode.studycafe.misson7.format;

import cleancode.studycafe.misson7.model.pass.StudyCafePass;

public interface PassTypeFormatter {

String format(StudyCafePass pass);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package cleancode.studycafe.tobe.io.handler;
package cleancode.studycafe.misson7.io.handler;

import cleancode.studycafe.tobe.model.pass.StudyCafePassType;
import cleancode.studycafe.tobe.model.pass.seat.StudyCafeSeatPass;
import cleancode.studycafe.tobe.model.pass.seat.StudyCafeSeatPasses;
import cleancode.studycafe.misson7.model.pass.StudyCafePassType;
import cleancode.studycafe.misson7.model.pass.seat.StudyCafeSeatPass;
import cleancode.studycafe.misson7.model.pass.seat.StudyCafeSeatPasses;

import java.util.Scanner;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package cleancode.studycafe.tobe.io.handler;

import cleancode.studycafe.tobe.model.pass.StudyCafePass;
import cleancode.studycafe.tobe.model.pass.StudyCafePassType;
import cleancode.studycafe.tobe.model.pass.locker.StudyCafeLockerPass;
import cleancode.studycafe.tobe.model.pass.order.StudyCafePassOrder;
import cleancode.studycafe.tobe.model.pass.seat.StudyCafeSeatPass;
import cleancode.studycafe.tobe.model.pass.seat.StudyCafeSeatPasses;
package cleancode.studycafe.misson7.io.handler;

import cleancode.studycafe.misson7.model.pass.StudyCafePass;
import cleancode.studycafe.misson7.model.pass.StudyCafePassType;
import cleancode.studycafe.misson7.model.pass.locker.StudyCafeLockerPass;
import cleancode.studycafe.misson7.model.pass.order.StudyCafePassOrder;
import cleancode.studycafe.misson7.model.pass.seat.StudyCafeSeatPass;
import cleancode.studycafe.misson7.model.pass.seat.StudyCafeSeatPasses;

import java.util.Optional;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package cleancode.studycafe.misson7.io.handler;

import cleancode.studycafe.misson7.model.pass.StudyCafePassType;
import cleancode.studycafe.misson7.model.pass.seat.StudyCafeSeatPass;
import cleancode.studycafe.misson7.model.pass.seat.StudyCafeSeatPasses;

public interface InputHandler {

StudyCafePassType getPassTypeSelectingUserAction();

StudyCafeSeatPass getSelectSeatPass(StudyCafeSeatPasses seatPasses);

boolean getLockerSelection();

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package cleancode.studycafe.tobe.io.handler;
package cleancode.studycafe.misson7.io.handler;

import cleancode.studycafe.tobe.model.pass.locker.StudyCafeLockerPass;
import cleancode.studycafe.tobe.model.pass.order.StudyCafePassOrder;
import cleancode.studycafe.tobe.model.pass.seat.StudyCafeSeatPasses;
import cleancode.studycafe.misson7.model.pass.locker.StudyCafeLockerPass;
import cleancode.studycafe.misson7.model.pass.order.StudyCafePassOrder;
import cleancode.studycafe.misson7.model.pass.seat.StudyCafeSeatPasses;

public interface OutputHandler {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package cleancode.studycafe.tobe.io.provider;
package cleancode.studycafe.misson7.io.provider;

import cleancode.studycafe.tobe.exception.ProvideException;
import cleancode.studycafe.tobe.io.provider.support.CsvFileReadSupport;
import cleancode.studycafe.tobe.model.pass.locker.StudyCafeLockerPasses;
import cleancode.studycafe.tobe.model.provider.ReadLockerPasses;
import cleancode.studycafe.tobe.provider.LockerPassProvider;
import cleancode.studycafe.misson7.exception.ProvideException;
import cleancode.studycafe.misson7.io.provider.support.CsvFileReadSupport;
import cleancode.studycafe.misson7.model.pass.locker.StudyCafeLockerPasses;
import cleancode.studycafe.misson7.model.provider.ReadLockerPasses;
import cleancode.studycafe.misson7.provider.LockerPassProvider;

import java.io.IOException;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package cleancode.studycafe.tobe.io.provider;
package cleancode.studycafe.misson7.io.provider;

import cleancode.studycafe.tobe.exception.ProvideException;
import cleancode.studycafe.tobe.io.provider.support.CsvFileReadSupport;
import cleancode.studycafe.tobe.model.pass.seat.StudyCafeSeatPasses;
import cleancode.studycafe.tobe.model.provider.ReadSeatPasses;
import cleancode.studycafe.tobe.provider.SeatPassProvider;
import cleancode.studycafe.misson7.exception.ProvideException;
import cleancode.studycafe.misson7.io.provider.support.CsvFileReadSupport;
import cleancode.studycafe.misson7.model.pass.seat.StudyCafeSeatPasses;
import cleancode.studycafe.misson7.model.provider.ReadSeatPasses;
import cleancode.studycafe.misson7.provider.SeatPassProvider;

import java.io.IOException;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cleancode.studycafe.tobe.io.provider.support;
package cleancode.studycafe.misson7.io.provider.support;

import java.io.IOException;
import java.nio.file.Files;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package cleancode.studycafe.misson7.model.pass;

public interface StudyCafePass {

StudyCafePassType getPassType();

int getDuration();

int getPrice();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package cleancode.studycafe.misson7.model.pass;

import cleancode.studycafe.misson7.exception.AppException;
import cleancode.studycafe.misson7.format.PassTypeFormatter;
import cleancode.studycafe.misson7.model.pass.seat.StudyCafeSeatPass;
import cleancode.studycafe.misson7.select.PassTypeSelectable;

import java.util.Arrays;

public enum StudyCafePassType implements PassTypeSelectable, PassTypeFormatter {

HOURLY("시간 단위 이용권") {
@Override
public boolean selected(String userInput) {
return "1".equals(userInput);
}

@Override
public String format(StudyCafePass pass) {
return String.format("%s시간권 - %d원", pass.getDuration(), pass.getPrice());
}
},
WEEKLY("주 단위 이용권") {
@Override
public boolean selected(String userInput) {
return "2".equals(userInput);
}

@Override
public String format(StudyCafePass pass) {
return String.format("%s주권 - %d원", pass.getDuration(), pass.getPrice());
}
},
FIXED("1인 고정석") {
@Override
public boolean selected(String userInput) {
return "3".equals(userInput);
}

@Override
public String format(StudyCafePass pass) {
return String.format("%s주권 - %d원", pass.getDuration(), pass.getPrice());
}
};

private final String description;

StudyCafePassType(String description) {
this.description = description;
}

public static StudyCafePassType findBy(String userInput) {
return Arrays.stream(values())
.filter(passType -> passType.selected(userInput))
.findFirst()
.orElseThrow(() -> new AppException("잘못된 입력입니다."));
}

public boolean isSamePassType(StudyCafeSeatPass pass) {
return this.equals(pass.getPassType());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package cleancode.studycafe.misson7.model.pass.locker;

import cleancode.studycafe.misson7.model.pass.StudyCafePass;
import cleancode.studycafe.misson7.model.pass.StudyCafePassType;

public class StudyCafeLockerPass implements StudyCafePass {

private final StudyCafePassType passType;
private final int duration;
private final int price;

private StudyCafeLockerPass(StudyCafePassType passType, int duration, int price) {
this.passType = passType;
this.duration = duration;
this.price = price;
}

public static StudyCafeLockerPass of(StudyCafePassType passType, int duration, int price) {
return new StudyCafeLockerPass(passType, duration, price);
}

public boolean isSamePassType(StudyCafePassType passType) {
return passType == this.passType;
}

public boolean isSameDuration(int duration) {
return duration == this.duration;
}

@Override
public StudyCafePassType getPassType() {
return passType;
}

@Override
public int getDuration() {
return duration;
}

@Override
public int getPrice() {
return price;
}

}
Loading