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
236 changes: 81 additions & 155 deletions README.md

Large diffs are not rendered by default.

13 changes: 11 additions & 2 deletions src/main/java/oncall/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
package oncall;

import oncall.config.AppConfig;
import oncall.controller.Controller;

/**
* 프로그램 진입점을 담당하는 클래스
*/
public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
AppConfig appConfig = AppConfig.getInstance();

Controller controller = appConfig.controller();
controller.run();
}
}
}
29 changes: 29 additions & 0 deletions src/main/java/oncall/config/AppConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package oncall.config;

import oncall.controller.Controller;
import oncall.view.InputView;
import oncall.view.OutputView;

/**
* 애플리케이션의 실행에 필요한 모든 객체를 생성하고 서로 연결하는 설정 클래스
*/
public class AppConfig {
private static class LazyHolder {
public static final AppConfig INSTANCE = new AppConfig();

public static final InputView INPUT_VIEW = new InputView();
public static final OutputView OUTPUT_VIEW = new OutputView();

public static final Controller CONTROLLER = new Controller(INPUT_VIEW, OUTPUT_VIEW);
}

private AppConfig() {}

public static AppConfig getInstance() {
return LazyHolder.INSTANCE;
}

public Controller controller() {
return LazyHolder.CONTROLLER;
}
}
62 changes: 62 additions & 0 deletions src/main/java/oncall/controller/Controller.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package oncall.controller;

import oncall.model.Calendar;
import oncall.model.Scheduler;
import oncall.model.Workers;
import oncall.util.InputParser;
import oncall.view.InputView;
import oncall.view.OutputView;

import java.util.List;

/**
* 프로그램의 전체 흐름 조율, 입출력과 로직을 연결하는 클래스
*/
public class Controller {
private final InputView inputView;
private final OutputView outputView;

public Controller(InputView inputView, OutputView outputView) {
this.inputView = inputView;
this.outputView = outputView;
}

public void run() {
Calendar calendar = createCalendar();
Scheduler scheduler = createScheduler(calendar);
outputView.printWorkSchedules(calendar, scheduler);
}

private Calendar createCalendar() {
while (true) {
try {
outputView.printCalendarPropertyPrompt();
String calendarProperty = inputView.readCalendarProperty();
List<String> properties = InputParser.parseToStrings(calendarProperty);
int monthNum = InputParser.parseToInt(properties.get(0));
String firstDayOfMonth = properties.get(1);
return Calendar.of(monthNum, firstDayOfMonth);
} catch (IllegalArgumentException e) {
outputView.printErrorMessage();
}
}
}

private Scheduler createScheduler(Calendar calendar) {
while(true) {
try {
outputView.printWeekdayWorkerNamesPrompt();
String weekdayWorkerNames = inputView.readWeekdayWorkersPrompt();
Workers weekdayWorkers = Workers.from(InputParser.parseToStrings(weekdayWorkerNames));

outputView.printHolidayWorkerNamesPrompt();
String holidayWorkerNames = inputView.readHolidayWorkersPrompt();
Workers holidayWorkers = Workers.from(InputParser.parseToStrings(holidayWorkerNames));

return Scheduler.of(calendar, weekdayWorkers, holidayWorkers);
} catch (IllegalArgumentException e) {
outputView.printErrorMessage();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package oncall.exception;

public class DuplicatedNicknameException extends IllegalArgumentException {
public DuplicatedNicknameException() {
super();
}
}
7 changes: 7 additions & 0 deletions src/main/java/oncall/exception/InvalidDayOfWeekException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package oncall.exception;

public class InvalidDayOfWeekException extends IllegalArgumentException {
public InvalidDayOfWeekException() {
super();
}
}
7 changes: 7 additions & 0 deletions src/main/java/oncall/exception/InvalidMonthException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package oncall.exception;

public class InvalidMonthException extends IllegalArgumentException {
public InvalidMonthException() {
super();
}
}
7 changes: 7 additions & 0 deletions src/main/java/oncall/exception/InvalidNicknameException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package oncall.exception;

public class InvalidNicknameException extends IllegalArgumentException {
public InvalidNicknameException() {
super();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package oncall.exception;

public class WorkersLessThanMinimumException extends IllegalArgumentException {
public WorkersLessThanMinimumException() {
super();
}
}
7 changes: 7 additions & 0 deletions src/main/java/oncall/exception/WorkersOverMaximum.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package oncall.exception;

public class WorkersOverMaximum extends IllegalArgumentException {
public WorkersOverMaximum() {
super();
}
}
49 changes: 49 additions & 0 deletions src/main/java/oncall/model/Calendar.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package oncall.model;

import java.util.ArrayList;
import java.util.List;

/**
* 설정 날짜(월, 시작 요일) 정보를 저장하는 클래스
*/
public class Calendar {
private final MonthKOR month;
private final List<DayOfWeekKOR> dayOfMonth;

private Calendar(MonthKOR month, DayOfWeekKOR firstDayOfMonth) {
this.month = month;
this.dayOfMonth = matchDayWithDate(firstDayOfMonth);
}

public static Calendar of(int monthNum, String firstDayOfMonth) {
MonthKOR month = MonthKOR.of(monthNum);
DayOfWeekKOR dayOfWeek = DayOfWeekKOR.of(firstDayOfMonth);
return new Calendar(month, dayOfWeek);
}

public int getMonth() {
return month.ordinal() + 1;
}

public DayOfWeekKOR getDayOfMonth(int date) {
return dayOfMonth.get(date - 1);
}

public int getLastDateOfMonth() {
return month.lastDateOfMonth();
}

public boolean isHoliday(int date) {
return month.isHoliday(date);
}

private List<DayOfWeekKOR> matchDayWithDate(DayOfWeekKOR firstDayOfMonth) {
List<DayOfWeekKOR> daysOfMonth = new ArrayList<>();
List<DayOfWeekKOR> dayOfWeek = List.of(DayOfWeekKOR.values());
int indexOfFirstDay = firstDayOfMonth.ordinal();
for (int i = 0; i < month.lastDateOfMonth(); i++) {
daysOfMonth.add(dayOfWeek.get((i + indexOfFirstDay)%7));
}
return daysOfMonth;
}
}
42 changes: 42 additions & 0 deletions src/main/java/oncall/model/DayOfWeekKOR.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package oncall.model;

import oncall.exception.InvalidDayOfWeekException;

/**
* 요일 Enum
*/
public enum DayOfWeekKOR {
MON("월", false),
TUES("화", false),
WEDS("수", false),
THURS("목", false),
FRI("금", false),
SAT("토", true),
SUN("일", true);

private final String dayOfWeek;
private final boolean isHoliday;

DayOfWeekKOR(String dayOfWeek, boolean isHoliday) {
this.dayOfWeek = dayOfWeek;
this.isHoliday = isHoliday;
}

public static DayOfWeekKOR of(String dayOfWeek) {
for (DayOfWeekKOR day : DayOfWeekKOR.values()) {
if (dayOfWeek.equals(day.dayOfWeek)) {
return day;
}
}
throw new InvalidDayOfWeekException();
}

@Override
public String toString() {
return this.dayOfWeek;
}

public boolean isHoliday() {
return this.isHoliday;
}
}
49 changes: 49 additions & 0 deletions src/main/java/oncall/model/MonthKOR.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package oncall.model;

import oncall.exception.InvalidMonthException;

import java.util.List;

public enum MonthKOR {
JANUARY(31, List.of(1)),
FEBRUARY(28, null),
MARCH(31, List.of(1)),
APRIL(30, null),
MAY(31, List.of(5)),
JUNE(30, List.of(6)),
JULY(31, null),
AUGUST(31, List.of(15)),
SEPTEMBER(30, null),
OCTOBER(31, List.of(3, 9)),
NOVEMBER(30, null),
DECEMBER(31, List.of(25));

private final int finalDate;
private final List<Integer> publicHolidays;

MonthKOR(int finalDate, List<Integer> publicHolidays) {
this.finalDate = finalDate;
this.publicHolidays = publicHolidays;
}

public static MonthKOR of(int monthNum) {
int indexOfMonth = monthNum - 1;
for (MonthKOR month : MonthKOR.values()) {
if (month.ordinal() == indexOfMonth) {
return month;
}
}
throw new InvalidMonthException();
}

public int lastDateOfMonth() {
return finalDate;
}

public boolean isHoliday(int date) {
if (publicHolidays == null) {
return false;
}
return publicHolidays.contains(date);
}
}
64 changes: 64 additions & 0 deletions src/main/java/oncall/model/Scheduler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package oncall.model;

import java.util.*;

/**
* 비상 근무표, 근무자 배정 로직 담당
*/
public class Scheduler {
private final List<Worker> workSchedule;

private Scheduler(List<Worker> workSchedule) {
this.workSchedule = workSchedule;
}

public static Scheduler of(Calendar calendar, Workers weekdayWorkers, Workers holidayWorkers) {
List<Worker> workSchedule = new ArrayList<>();
workSchedule.add(null);
Deque<Worker> weekdayWorkersNotAssigned = new LinkedList<>();
Deque<Worker> holidayWorkersNotAssigned = new LinkedList<>();
for (int i = 1; i <= calendar.getLastDateOfMonth(); i++) {
DayOfWeekKOR dayOfWeek = calendar.getDayOfMonth(i);
Worker worker = null;
boolean isHoliday = dayOfWeek.isHoliday() || calendar.isHoliday(i);
if (!isHoliday) {
worker = assignWorker(weekdayWorkersNotAssigned, weekdayWorkers);
}
if (isHoliday) {
worker = assignWorker(holidayWorkersNotAssigned, holidayWorkers);
}
if (i > 1) {
if (worker.isSame(workSchedule.get(i - 1))) {
Worker workerOnDutyInARow = worker;
if (!isHoliday) {
worker = assignWorker(weekdayWorkersNotAssigned, weekdayWorkers);
weekdayWorkersNotAssigned.push(workerOnDutyInARow);
}
if (isHoliday) {
worker = assignWorker(holidayWorkersNotAssigned, holidayWorkers);
holidayWorkersNotAssigned.push(workerOnDutyInARow);
}
}
}
workSchedule.add(worker);
}
return new Scheduler(workSchedule);
}

public Worker getWorkerOnDuty(int date) {
return workSchedule.get(date);
}

private static void fillWorkers(Deque<Worker> workersNotAssigned, Workers workers) {
for (int i = 0; i < workers.size(); i++) {
workersNotAssigned.add(workers.get(i));
}
}

private static Worker assignWorker(Deque<Worker> workersNotAssigned, Workers workers) {
if (workersNotAssigned.isEmpty()) {
fillWorkers(workersNotAssigned, workers);
}
return workersNotAssigned.pop();
}
}
Loading