Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2단계 - 출석 다시 구현하기] 다로(이정민) 미션 제출합니다. #122

Merged
merged 132 commits into from
Mar 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
132 commits
Select commit Hold shift + click to select a range
18ad75e
fix : step2를 위한 클래스 삭제
eueo8259 Feb 26, 2025
74fe30b
feat : 요일별 등교 시간을 기반으로 출석, 지각, 결석 파악
eueo8259 Feb 26, 2025
03fa4f3
feat : 요일별 등교 시간 확인 구현 클래스 생성
eueo8259 Feb 26, 2025
94e51a3
test : 요일별 등교 시간 확인 테스트
eueo8259 Feb 26, 2025
d7914a3
refactor : 시간 확인 하는 중복되는 부분 수정
eueo8259 Feb 26, 2025
28626d3
docs : README.md 수정
eueo8259 Feb 26, 2025
d766f2c
refactor : 주말 및 크리스마스의 경우 등교 불가하도록 검증로직 구현
eueo8259 Feb 26, 2025
bf64f0a
test : 주말 및 크리스마스의 경우 등교 불가 테스트 추가
eueo8259 Feb 26, 2025
b48bd93
docs : 주말 및 공휴일 출석 예외 처리 구현 체크
eueo8259 Feb 26, 2025
e044eaf
docs : README.md 읽기 쉽게 위치 변경
eueo8259 Feb 26, 2025
d5b5115
feat : 출석 등록 기능 구현
eueo8259 Feb 26, 2025
c4318f8
test : 출석 등록 기능 후 출결 시간 및 출석 상태 테스트
eueo8259 Feb 26, 2025
117d924
docs : 출결 정보 등록 구현 체크
eueo8259 Feb 26, 2025
48e6e7e
feat : 출결 정보 수정 기능 구현
eueo8259 Feb 26, 2025
07aea70
test : 출결 정보 수정 후 출결 시간 및 출결 상태 테스트
eueo8259 Feb 26, 2025
556006c
docs : 정보 수정 기능 구현 체크
eueo8259 Feb 26, 2025
ab672a6
feat : 출결 횟수 업데이트 구현
eueo8259 Feb 26, 2025
20aa4e1
test : 출결 횟수 업데이트 테스트
eueo8259 Feb 26, 2025
72833e0
docs : 출결 기록 횟수 계산 체크
eueo8259 Feb 26, 2025
fd18a82
refactor : 중복 로직 수정
eueo8259 Feb 27, 2025
3fc8d27
feat : 지각 3회시 결석 1회로 계산하는 기능 구현
eueo8259 Feb 27, 2025
f8c91a1
feat : 지각 3회시 결석 1회로 계산하는 기능 구현 테스트
eueo8259 Feb 27, 2025
1a48621
docs : 지각 3회시 결석 1회로 계산하는 기능 구현 체크
eueo8259 Feb 27, 2025
840c95c
feat : 파일 정보 읽어오는 클래스 생성 및 Map<String, List<LocalDateTime>> 으로 반환하는 메…
eueo8259 Feb 28, 2025
338204e
test : 파일 정보를 가져온 후 제대로 가져왔는지 확인 테스트
eueo8259 Feb 28, 2025
720d0e7
docs : 파일을 이용하여 필요한 정보 가져오기 체크
eueo8259 Feb 28, 2025
e3ac17e
feat : 출석 하지 않아 존재하지 않는 기록의 경우 결석으로 처리 기능 구현
eueo8259 Feb 28, 2025
ef568fd
test : 출석 하지 않아 존재하지 않는 기록의 경우 결석으로 처리 테스트
eueo8259 Feb 28, 2025
3e5adcc
docs : 필요없는 문서 삭제
eueo8259 Feb 28, 2025
7ba675e
feat : 이미 출석기록이 존재한데 출석 할 경우 예외처리 기능 구현
eueo8259 Feb 28, 2025
b49944b
test : 이미 출석 기록이 존재한 경우 출석 시도 시 예외 테스트
eueo8259 Feb 28, 2025
c8b1beb
docs : 이미 출석 기록이 존재한 경우 출석 시도 시 예외 체크
eueo8259 Feb 28, 2025
377033b
refactor : 일급 컬렉션 분리 및 Student 클래스에 name 변수 추가
eueo8259 Feb 28, 2025
864dc70
refactor : 일급 컬렉션 분리에 따른 테스트 수정
eueo8259 Feb 28, 2025
3ac6d1e
refactor : 일급 컬렉션 분리에 따른 메서드 분리 및 추가
eueo8259 Feb 28, 2025
9c6301d
refactor : 변수 private로 변경 및 getter 생성 후 관련 로직 수정
eueo8259 Feb 28, 2025
f2369ec
feat : 학생들을 관리하는 출석부 클래스 생성 및 특정 학생의 지각 기록 찾는 메서드 구현
eueo8259 Feb 28, 2025
51d8d76
feat : 특정 학생의 출결 시간 기록 찾기 테스트
eueo8259 Feb 28, 2025
fc4d3f4
feat : 제적 위험 학생 찾는 메서드 구현
eueo8259 Mar 1, 2025
3aa3db0
feat : 메서드 읽기 쉽게 수정 및 제적 위험 관련 계산 메서드 구현
eueo8259 Mar 1, 2025
5c60b8d
test : 제적 위험자 조건에 맞는 크루 찾기 테스트
eueo8259 Mar 1, 2025
bf76cdb
docs : 제적 위험자 조건에 맞는 크루 찾기 구현 체크 및 세세한 요구사항 추가
eueo8259 Mar 1, 2025
2da2aa9
refactor : 출석 기록 업데이트 메서드를 12월 1일 부터 오늘날짜까지로 범위 설정 수정
eueo8259 Mar 1, 2025
100c029
docs : 12월 중 오늘을 기준으로 출석 기록이 없으면 결석으로 처리 체크
eueo8259 Mar 1, 2025
7af8852
refactor : 메서드 수정에 따른 테스트 수정
eueo8259 Mar 1, 2025
23893e0
fix : 코드 가독성을 위한 코드 정렬
eueo8259 Mar 1, 2025
f12569a
fix : model 패키지 생성 후 클래스들 위치 변경
eueo8259 Mar 1, 2025
33b358a
feat : MenuOption enum 생성 및 입력값 validate 메서드 구현
eueo8259 Mar 1, 2025
02f9c77
feat : 메뉴 선택 기능 구현
eueo8259 Mar 1, 2025
03b4320
feat : 출석 메뉴 출력 및 닉네임 입력 출력 메서드 구현
eueo8259 Mar 1, 2025
3fd4083
docs : 닉네임 입력 및 메뉴 선택 에러 처리 체크
eueo8259 Mar 1, 2025
5213eaa
feat : 출석 기록 확인 출력 메서드 구현
eueo8259 Mar 1, 2025
3c9ecf8
feat : 필드 추가 및 getter생성
eueo8259 Mar 1, 2025
ab6a510
feat : filePath 수정
eueo8259 Mar 1, 2025
ff0dc0c
feat : 특정 학생의 출석 상태 가져오는 로직 추가
eueo8259 Mar 1, 2025
ed8b170
test : 특정 학생의 출석 상태 가져오는 로직 테스트
eueo8259 Mar 1, 2025
54f4530
feat : 출력을 위한 AttendanceRecordFormatter 클래스 추가 및 출석 기록 출력 메서드 구현
eueo8259 Mar 1, 2025
dcdc861
fix : 패키지 위치 변경
eueo8259 Mar 1, 2025
b5b1310
feat : attendanceFormatter 구현 후 로직 수정 및 수정 했을 경우 출력 메서드 구현
eueo8259 Mar 1, 2025
97f00b1
refactor : 사용하지 않는 메서드 삭제
eueo8259 Mar 1, 2025
ed846e1
fix : 메서드 static으로 변경
eueo8259 Mar 1, 2025
2ef0cba
fix: 출석 기록 수정 메서드 날짜 타입 유연성 개선
eueo8259 Mar 1, 2025
7563597
fix: 출석 기록 수정 메서드 날짜 타입 유연성 개선에 따른 테스트 수정
eueo8259 Mar 1, 2025
5f908e2
feat: 출석 시간 및 검증 관련 로직 추가
eueo8259 Mar 1, 2025
2069ad2
feat: 출석 기록 출력 메서드 추가
eueo8259 Mar 1, 2025
27e6aeb
feat: 작동 메서드 및 기능 1번 메서드 구현
eueo8259 Mar 1, 2025
b402896
reafactor: 출석 기록이 없는 경우 --:--로 바꿔서 출력하도록 수정
eueo8259 Mar 1, 2025
6929bea
feat : 출석 수정 기능 메서드 구현
eueo8259 Mar 1, 2025
6c9db2c
refactor : 메서드 분리
eueo8259 Mar 1, 2025
5b1d6b1
feat 출석 기록 조회 및 제적 위험자 확인 메서드 구현
eueo8259 Mar 1, 2025
028b19b
feat 출석 기록 조회 및 제적 위험자 확인 기능 구현
eueo8259 Mar 1, 2025
80fae0a
docs : 해결한 기능들 체크
eueo8259 Mar 1, 2025
efe17df
feat : 재적 위험자들 출력 기능 구현
eueo8259 Mar 1, 2025
afc8f2f
refactor : 결석 횟수 계산하는 메서드명 수정 및 추가
eueo8259 Mar 1, 2025
7e6d235
refactor : 지각 횟수 가져오는 getter 추가
eueo8259 Mar 1, 2025
2ae9fa0
feat : 제적 위험자 출력 로직 구현
eueo8259 Mar 1, 2025
7013e72
feat : 출결 패널티 관리하는 클래스 추가
eueo8259 Mar 1, 2025
78f1b66
feat : 출결 등록 안 되어있는 경우 결석 처리하는 메서드 구현
eueo8259 Mar 1, 2025
772794a
feat : Q누르기 전까지 계속 반복하여 실행되도록 수정
eueo8259 Mar 1, 2025
1247f5a
feat : Main 클래스 추가
eueo8259 Mar 1, 2025
3a5c401
refactor : 코드 정렬
eueo8259 Mar 1, 2025
56307ae
docs : gitignore 수정
eueo8259 Mar 2, 2025
7296f80
docs : README.md 해결한 부분들 체크
eueo8259 Mar 2, 2025
8d58a02
refactor : 불필요한 줄바꿈 및 handleMenuChoice 메서드 가독성 좋게 수정
eueo8259 Mar 2, 2025
fddd6ff
refactor : 메서드 명 자바 코딩 컨벤션에 따라 동사구로 네이밍 수정
eueo8259 Mar 2, 2025
c189db3
refactor : 불필요한 변수 선언 수정
eueo8259 Mar 2, 2025
b022aba
refactor : 람다 파라미터 네이밍 수정 및 매직넘버 관리
eueo8259 Mar 2, 2025
47a7dac
refactor : AttendancePenalty NONE 값 추가 후 관련 로직 수정
eueo8259 Mar 2, 2025
2a0da30
refactor : penaltyCount를 thresholdAbsenceCount로 변수명 변경
eueo8259 Mar 2, 2025
de68d49
refactor : findPenaltyByAbsentCount 메서드의 파라미터 이름을 absentCount로 수정
eueo8259 Mar 2, 2025
4adde34
refactor : 각 상태별 기준값을 enum에 추가하고 메서드 명 변경 및 로직 수정
eueo8259 Mar 2, 2025
05b70c0
refactor : attendanceStatusCalculate메서드명 calculateAttendanceStatus로 변…
eueo8259 Mar 2, 2025
06fdbd8
refactor : 상태값들의 접근 제한자를 지정 후 관련 로직 수정
eueo8259 Mar 2, 2025
cf6313d
refactor : 코드 가독성을 위한 코드 정렬
eueo8259 Mar 2, 2025
0eceb25
refactor : 캠퍼스 운영 시간이 아닌 경우 예외 처리
eueo8259 Mar 2, 2025
198dba0
docs : 캠퍼스 운영 시간이 아닌 경우 예외 처리 체크
eueo8259 Mar 2, 2025
3e1320c
refactor : 사용하지 않는 메서드 삭제
eueo8259 Mar 2, 2025
c9d782e
test : 학생 이름으로 학생 찾기 구현 테스트 추가
eueo8259 Mar 2, 2025
9598844
refactor : findPenaltyByAbsentCount 메서드 stream 로직으로 수정
eueo8259 Mar 2, 2025
28f8508
test : 결석 횟수에 따른 출결 패널티 상태값 가져오기 테스트
eueo8259 Mar 2, 2025
0115fdb
test : 지각 및 결석 횟수 확인 테스트 추가
eueo8259 Mar 2, 2025
f19b1ff
test : 출결 기록이 없는 경우 결석 처리하는 테스트 추가
eueo8259 Mar 2, 2025
962da75
test : AttendanceStatusRecordTest 메서드들 테스트
eueo8259 Mar 2, 2025
722faa5
test : AttendanceTimeRecord 메서드들 테스트
eueo8259 Mar 2, 2025
9d0a2fc
test : 캠퍼스 운영 시간 예외 처리 테스트
eueo8259 Mar 2, 2025
94e8f54
refactor : TimeRecord 만 저장하되, 추후 StatusRecord나 StatusCount가 필요한 시점에 계…
eueo8259 Mar 2, 2025
74e3964
refactor : 출석 상태 로직 수정 및 출석 기록을 기반으로 특정 출석 상태의 개수를 계산하는 메서드 추가
eueo8259 Mar 2, 2025
c2f26a7
refactor : findExpulsionRiskStudents 메서드의 filter 기준 오류 수정
eueo8259 Mar 2, 2025
fb67d5a
refactor : findPenaltyByAbsentCount 파라미터명 더 알아보기 쉽게 수정
eueo8259 Mar 2, 2025
e6480c5
refactor : AttendanceStatus 값 가져오는 로직 수정
eueo8259 Mar 2, 2025
3373dfd
refactor : TimeRecord 만 저장하되, 추후 StatusRecord나 StatusCount가 필요한 시점에 계…
eueo8259 Mar 2, 2025
94e62a3
refactor: 프로덕트 코드 수정에 따른 테스트 코드 삭제 및 수정
eueo8259 Mar 2, 2025
484ea72
refactor: 공휴일의 경우 출결 처리 건너뛰도록 수정
eueo8259 Mar 2, 2025
3aaa3e8
refactor: 공휴일 체크하는 메서드 구현
eueo8259 Mar 2, 2025
9c129c2
test: 공휴일 체크하는 메서드 테스트
eueo8259 Mar 2, 2025
49d4302
docs: README.md 출석 정보 파일 주소 수정
eueo8259 Mar 2, 2025
c69be2d
refactor: 코드 가독성을 위한 메서드 위치 수정
eueo8259 Mar 2, 2025
def2c79
refactor: 출결 위험군 체크하는 메서드 추가
eueo8259 Mar 3, 2025
d6ff8fa
refactor: 출결 위험군 체크하는 메서드 추가에 따른 스트림 수정
eueo8259 Mar 3, 2025
23c865b
refactor: findPenaltyByAbsentCount 메서드 수정
eueo8259 Mar 3, 2025
1a62a94
test: 출결 횟수 계산하는 로직 테스트 추가
eueo8259 Mar 3, 2025
93a8dbe
refactor: Parameterized Test를 이용해서 테스트 코드들 수정
eueo8259 Mar 3, 2025
95411d6
refactor: findAttendanceScheduleByLocalDate 메서드에 예외 메시지 추가
eueo8259 Mar 3, 2025
17d3bd5
refactor: 출석기록 확인 검증 메서드 AttendanceTimeRecord 로 이동
eueo8259 Mar 3, 2025
b10bd84
refactor: 출석기록 확인 검증 메서드 AttendanceTimeRecord 로 이동
eueo8259 Mar 3, 2025
65cb3d5
feat: 휴일을 관리하는 enum 추가 및 휴일 체크 메서드 구현
eueo8259 Mar 3, 2025
faf6166
test: 휴일 체크 및 예외처리 메서드 테스트
eueo8259 Mar 3, 2025
ff46395
refactor: Holiday enum추가하며 휴일 관련 메서드 삭제 및 수정
eueo8259 Mar 3, 2025
4301473
refactor: 같은 기능을 하는 중복 로직 처리
eueo8259 Mar 3, 2025
ad1dfd3
refactor: attendanceTimeRecord의 메서드 변경에 따른 수정
eueo8259 Mar 3, 2025
c8f51c4
refactor: attendanceTimeRecord의 메서드 삭제에의한 테스트 삭제
eueo8259 Mar 3, 2025
38999ea
refactor: 패널티 기준 수정
eueo8259 Mar 3, 2025
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
56 changes: 44 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,66 @@
# java-attendance

## 기능 목록
- [X] src/main/resources/attendances.csv 파일을 이용하여 필요한 정보를 가져와 저장한다.
Copy link

Choose a reason for hiding this comment

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

(질문)
다시 여기에 작성해서 여쭤보자면 항상 요구사항을 다 읽고 클래스 설계를 먼저 한 후 작업을 들어가는 방식으로만 진행하였으나, 이번에 TDD로 코드를 짜면서 README.md에 기능명세서를 자세하게 작성하고 기능들을 하나하나 TDD로 만들면서 자연스럽게 객체들을 생성하고 분리하는 식으로 step2를 진행했습니다.
이런 방식은 처음이다보니 TDD를 통한 여러 기능을 구현하면서 클래스 분리하는 과정에서 클래스 설계가 자꾸 이상하게 꼬인다는 생각이 자꾸 들었습니다.
이 부분에 대하여 다른 크루들이랑도 이야기를 나눠보니 어떤 크루는 미리 기능명세서를 작성하고 클래스 설계까지 끝낸 다음 그 이후에 TDD를 진행하였고, 어떤 크루는 저와 비슷하게 TDD를 하며 red-green 이후 refactor 과정에서 클래스 분리를 진행한다는 이야기를 들었습니다.
여러가지 의견들이 있어 현재 TDD 와 클래스 설계 부분에서 갈피를 못 잡는 중인데 이와 관련해서 조언해주실게 있으시다면 부탁드리겠습니다!

개인적인 생각으로는 두 가지 방식 모두 가능한 접근 방식이라 생각해요.

그래서 상황에 따라서 유동적으로 두 가지 방식중 하나를 선택하는게 맞다고 생각하지만
도메인이 처음부터 명확하지 않거나, 작은 기능부터 점진적으로 개발하는 경우에 TDD를 진행하면서 객체 설계를 발전시켜나가는 방식이 어울린다고 생각하는데, 보통은 이 경우가 많다고 생각합니다.

레거시 코드를 갈아 엎는 작업을 한다거나한다면 주요 도메인 객체를 먼저 정의하고, 이후에 세부적인 로직을 TDD로 채워나가는 방식으로 진행해볼 수도있을 것 같아요.

PR보낼 때 원래 어떤 부분에 집중하여 리뷰해야 할까요? 아래에 TDD 관련 설계에 대한 내용들을 다 적었었는데 제가 잘못눌러서 삭제되었는지 안 보이네요..

어떤 부분에 집중하여 리뷰해야 할까요? 아래에 작성을 하셨는데 삭제가 된 것 같다는 말씀이신거죠?
이 부분은 저도 원인을 잘 모르겠네요... 🤔

- [X] 1번을 눌렀을 경우
- [X] 닉네임을 입력받는다.
- [X] 등교 시간을 입력받는다. (등교시간의 경우 오늘 등교를 하는 것이나 12월 이라는 조건으로 오늘을 2024.12.13 으로 설정하였습니다)
- [X] 정보를 업데이트 하고, 출력한다.
- [X] 요일별 등교 시간을 확인한다.
- [X] 요일별 등교 시간을 기반으로 입력 받은 등교 시간과 비교하여 출석, 지각, 결석을 판단한다.
- [X] 출결 정보를 등록
- [X] 등록한 정보 출력한다.
- [X] 2번을 눌렀을 경우
- [X] 닉네임을 입력받는다.
- [X] 날짜를 입력받는다.
- [X] 변경할 시간을 입력받는다.
- [X] 정보를 업데이트 하고, 출력한다.
- [X] 변경한 시간을 기반으로 출석, 지각, 결석을 판단한다.
- [X] 정보를 수정한다.
- [X] 바뀐 정보를 출력한다.
- [X] 3번을 눌렀을 경우
- [X] 닉네임을 입력받는다.
- [X] 출석 기록을 출력한다.
- [X] 오늘을 기준으로 그 전 날짜들의 출석 기록이 없는 경우 결석으로 처리한다.
- [X] 입력 받은 크루의 출석 기록을 출력한다.
- [X] 4번을 눌렀을 경우
- [X] 제적 위험자를 출력한다.
- [X] 크루들의 출석 기록들을 확인한다.
- [X] 크루들의 출결 기록 횟수들을 계산한다.
- [X] 지각 3회는 결석 1회로 간주하여 계산한다.
- [X] 제적 위험자 조건에 맞는 크루들을 찾는다.
- [X] 출력한다.
- [X] Q를 눌렀을 경우
- [X] 프로그램을 종료한다.
---
## 예외 처리
- [X] 존재하지 않는 닉네임을 입력한 경우
- [X] 존재하지 않는 기록을 수정하려고 할 경우
- [X] 메뉴 선택이 잘못된 경우
- [X] 등교 시간을 잘못 적은
- [X] 잘못된 형식으로 입력한 경우
- [X] 캠퍼스 운영 시간이 아닌 경우
- [X] 주말 및 공휴일에 출석을 한 경우
- [X] 이미 출석한 경우
---
## 요구 사항
- 2024년 12월 한 달 동안 시범적으로 최소한의 기능을 갖춘 출석 시스템입니다.
- 교육 시작 시간으로부터 5분 초과 시 지각
- 교육 시작 시간으로부터 30분 초과 시 결석
- 지각 3회는 결석 1회로 간주한다.
- 결석 5회 초과는 제적 대상자.
---
## 예외 처리
- [X] 존재하지 않는 닉네임을 입력한 경우 -
- [X] 등교 시간을 잘못 적은 경우
- [X] 잘못된 형식으로 입력한 경우
- [X] 캠퍼스 운영 시간이 아닌 경우
- [X] 주말 및 공휴일에 출석을 한 경우
- 경고 대상자: 결석 2회 이상
- 면담 대상자: 결석 3회 이상
- 제적 대상자: 결석 5회 초과
- 구현 요구사항을 만족하는 최소한의 설계를 한다.
---
## 프로그래밍 요구 사항
- 자바 코드 컨벤션을 지키면서 프로그래밍한다. (기본적으로 Java Style Guide을 원칙으로 한다.)
- indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다.
- 3항 연산자를 쓰지 않는다.
- else 예약어를 쓰지 않는다. (else 예약어를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.)
- 모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다. 단, UI(System.out, System.in) 로직은 제외
- 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다.
- UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다.
- 함수(또는 메서드)의 길이가 10라인을 넘어가지 않도록 구현한다.
- 함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어라.
- 배열 대신 컬렉션을 사용한다.
- Java Enum을 적용한다.
- 모든 원시 값과 문자열을 포장한다
- 줄여 쓰지 않는다(축약 금지).
- 일급 컬렉션을 쓴다.
Empty file removed src/main/java/.gitkeep
Empty file.
9 changes: 9 additions & 0 deletions src/main/java/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import controller.Controller;
import java.io.IOException;

public class Main {
public static void main(String[] args) throws IOException {
Controller controller = new Controller();
controller.run();
}
}
6 changes: 0 additions & 6 deletions src/main/java/constant/DateFormatInformation.java

This file was deleted.

28 changes: 28 additions & 0 deletions src/main/java/constant/MenuOption.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package constant;

import java.util.Arrays;

public enum MenuOption {
ATTENDANCE_REGISTER("1"),
ATTENDANCE_MODIFY("2"),
CREW_ATTENDANCE_CHECK("3"),
EXPULSION_RISK("4"),
QUIT("Q");

private final String inputMenuValue;

MenuOption(String inputMenuValue) {
this.inputMenuValue = inputMenuValue;
}

public static MenuOption validateSelectMenuOption(String input) {
return Arrays.stream(MenuOption.values())
.filter(option -> option.getInputMenuValue().equals(input))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("[ERROR] 유효하지 않은 선택입니다." + input));
}

public String getInputMenuValue() {
return inputMenuValue;
}
}
215 changes: 93 additions & 122 deletions src/main/java/controller/Controller.java
Original file line number Diff line number Diff line change
@@ -1,163 +1,134 @@
package controller;

import constant.DateFormatInformation;
import constant.MenuOption;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.LocalTime;
import java.util.List;
import model.Student;
import model.AttendanceBook;
import util.FileInput;
import util.LocalDateTimePrintFormatter;
import model.Student;
import util.AttendanceRecordFormatter;
import util.FileInformationProvider;
import view.InputView;
import view.OutputView;
import view.OutPutView;

public class Controller {
private static final LocalDateTime TODAY = LocalDateTime.of(2024, 12, 13, 10, 0);
private static final int CHECK_IN = 1;
private static final int MODIFY_ATTENDANCE = 2;
private static final int CHECK_BY_CREW = 3;
private static final int CHECK_DROPOUT_RISK = 4;


private AttendanceBook readFileAndCreateStudentRepository() throws IOException {
FileInput fileInput = new FileInput();
List<Student> students = fileInput.createStudents();
return new AttendanceBook(students);
}

public AttendanceBook createStudentRepository() {
try {
return readFileAndCreateStudentRepository();
} catch (IOException e) {
return createStudentRepository();
}
}

public void attendanceStart() {
LocalDate todayDate = LocalDate.from(TODAY);
InputView.printTodayAndSelectFunction(todayDate);
AttendanceBook studentRepository = createStudentRepository();

for (Student student : studentRepository.getStudents()) {
student.getAttendanceRecords().updateStateNotExistInFile(todayDate);
}
private static final LocalDate TODAY = LocalDate.of(2024, 12, 13);

public void run() throws IOException {
AttendanceBook attendanceBook = new AttendanceBook(FileInformationProvider.loadStudentAttendance());
attendanceBook.updateNonExistentAttendanceRecords(TODAY);
while (true) {
String selectFunction = InputView.getUserInputString();
if (selectFunction.equals("Q")) {
break;
}
if (Integer.parseInt(selectFunction) == CHECK_IN) {
functionForMenuOne(studentRepository, todayDate);
}
if (Integer.parseInt(selectFunction) == MODIFY_ATTENDANCE) {
functionForMenuTwo(studentRepository);
}
if (Integer.parseInt(selectFunction) == CHECK_BY_CREW) {
functionForMenuThree(studentRepository);
}
if (Integer.parseInt(selectFunction) == CHECK_DROPOUT_RISK) {
functionForMenuFour(studentRepository);
if (handleMenuChoice(attendanceBook)) {
return;
}
}

}

private static void functionForMenuFour(AttendanceBook studentRepository) {
OutputView.printEveryStudentPunishmentLabel(studentRepository);
}

private void functionForMenuThree(AttendanceBook studentRepository) {
String studentName = getStudentForAttendanceCheckUntilExist(studentRepository);
OutputView.printAttendanceRecord(studentRepository
.findStudentByName(studentName).getAttendanceRecords().getRecord());
studentRepository.findStudentByName(studentName).calculateAbsent();
OutputView.printStudentState(studentRepository.findStudentByName(studentName));
OutputView.printStudentPunishmentLabel(studentRepository.findStudentByName(studentName));
}

private void functionForMenuTwo(AttendanceBook studentRepository) {
String studentName = getStudentNameForModifyUntilValidate(studentRepository);
Student student = studentRepository.findStudentByName(studentName);
LocalDateTime modifyLocalDateTime = getLocalDateTimeToModify();
LocalDate modifyLocalDate = LocalDate.from(modifyLocalDateTime);
String recordBeforeModify = LocalDateTimePrintFormatter
.LocalDateTimeToLocalTime(modifyLocalDate,
student.getAttendanceRecords().getRecord().get(modifyLocalDate)) +
student.findStateByLocalDateTime(modifyLocalDateTime);

student.modifyAttendanceRecord(modifyLocalDateTime);
String recordAfterModify = student.findStateByLocalDateTime(modifyLocalDateTime);

String localDateTimeFormat = modifyLocalDateTime.format(DateTimeFormatter.ofPattern(
DateFormatInformation.LOCAL_TIME_FORMATTER + " (" + recordAfterModify + ") 수정 완료!"));

OutputView.printSecondMenu(recordBeforeModify, localDateTimeFormat);
}

private LocalDateTime getLocalDateTimeToModify() {
int modifyDate = InputView.inputDateForModify();
InputView.printTimeForModify();
LocalDate localDate = LocalDate.of(2024, 12, modifyDate);
return getTimeUntilValidate(localDate);
}

private void functionForMenuOne(AttendanceBook studentRepository, LocalDate todayDate) {
String studentName = getStudentForAttendanceCheckUntilExist(studentRepository);
LocalDateTime localDateTime = getLocalDateTimeUntilValidate(todayDate);
Student student = studentRepository.findStudentByName(studentName);
student.attendanceRegister(localDateTime);
OutputView.printTodayAttendanceResult(student, localDateTime);
private boolean handleMenuChoice(AttendanceBook attendanceBook) {
OutPutView.displayAttendanceMenu(TODAY);
MenuOption menuOption = chooseMenuOption();
if (menuOption.equals(MenuOption.ATTENDANCE_REGISTER)) {
registerAttendance(attendanceBook);
}
if (menuOption.equals(MenuOption.ATTENDANCE_MODIFY)) {
modifyAttendance(attendanceBook);
}
if (menuOption.equals(MenuOption.CREW_ATTENDANCE_CHECK)) {
checkCrewAttendance(attendanceBook);
}
if (menuOption.equals(MenuOption.EXPULSION_RISK)) {
checkExpulsionRisk(attendanceBook);
}
return menuOption.equals(MenuOption.QUIT);
}

private String getStudentNameForModifyUntilValidate(AttendanceBook studentRepository) {
private MenuOption chooseMenuOption() {
try {
InputView.printStudentNameForModify();
return getStudentNameUntilExist(studentRepository);
return InputView.inputChooseFunctionOption();
} catch (IllegalArgumentException e) {
return getStudentNameForModifyUntilValidate(studentRepository);
System.out.println(e.getMessage());
return chooseMenuOption();
}
}

private LocalDateTime getLocalDateTimeUntilValidate(LocalDate todayDate) {
private void registerAttendance(AttendanceBook attendanceBook) {
try {
InputView.printStartTime();
return getTimeUntilValidate(todayDate);
String nickName = requestNickName();
LocalTime attendanceTime = requestAttendanceTime();
Student student = attendanceBook.findStudentByNickName(nickName);
student.registerAttendanceRecord(TODAY, attendanceTime);
OutPutView.displayRegisterAttendanceRecord(AttendanceRecordFormatter.attendanceRecordFormatter(
student, TODAY));
} catch (IllegalArgumentException e) {
return getLocalDateTimeUntilValidate(todayDate);
System.out.println(e.getMessage());
registerAttendance(attendanceBook);
}
}

private String getStudentForAttendanceCheckUntilExist(AttendanceBook studentRepository) {
InputView.printInputNicName();
try {
return getStudentNameUntilExist(studentRepository);
} catch (IllegalArgumentException e) {
return getStudentForAttendanceCheckUntilExist(studentRepository);
}
private static LocalTime requestAttendanceTime() {
OutPutView.requestAttendanceTime();
return InputView.inputAttendanceTime();
}

private String getStudentNameUntilExist(AttendanceBook studentRepository) {
String userName = InputView.userInput();
private void modifyAttendance(AttendanceBook attendanceBook) {
try {
studentRepository.notExistStudent(userName);
return userName;
String nickName = requestModifyNickName();
int modifyDate = requestModifyDate();
Student student = attendanceBook.findStudentByNickName(nickName);
modifyAttendanceRecord(student, modifyDate);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
throw new IllegalArgumentException();
modifyAttendance(attendanceBook);
}
}

private LocalDateTime getTimeUntilValidate(LocalDate localDate) {
private void checkCrewAttendance(AttendanceBook attendanceBook) {
try {
LocalDateTime localDateTimeToAttendanceCheck = InputView.makeLocalDateToLocalDateTime(localDate);
InputView.isNotOpeningHour(localDateTimeToAttendanceCheck);
return localDateTimeToAttendanceCheck;
String nickName = requestNickName();
Student student = attendanceBook.findStudentByNickName(nickName);
OutPutView.displayTotalAttendanceRecord(student);
OutPutView.displayTotalAttendanceCount(student);
OutPutView.displayCounselingCandidate(student);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
throw new IllegalArgumentException();
checkCrewAttendance(attendanceBook);
}
}

private void checkExpulsionRisk(AttendanceBook attendanceBook) {
List<Student> expulsionRiskStudents = attendanceBook.findExpulsionRiskStudents();
OutPutView.displayExpulsionRiskStudents(expulsionRiskStudents);
}

private void modifyAttendanceRecord(Student student, int modifyDate) {
LocalDate date = LocalDate.of(2024, 12, modifyDate);
String beforeRecord = AttendanceRecordFormatter.attendanceRecordFormatter(student, date);

LocalTime modifyTime = requestModifyTime();
student.modifyAttendanceRecord(modifyDate, modifyTime);

String afterRecord = AttendanceRecordFormatter.attendanceRecordFormatter(student, date);
OutPutView.displayModifyAttendanceRecord(beforeRecord, afterRecord);
}

private static String requestNickName() {
OutPutView.requestNickName();
return InputView.input();
}

private String requestModifyNickName() {
OutPutView.requestModifyNickName();
return InputView.input();
}

private int requestModifyDate() {
OutPutView.requestModifyDate();
return InputView.validateDateFormat(InputView.input());
}

private LocalTime requestModifyTime() {
OutPutView.requestModifyTime();
return InputView.validateTimeFormat(InputView.input());
}
}
8 changes: 0 additions & 8 deletions src/main/java/main.java

This file was deleted.

Loading