diff --git a/README.md b/README.md index 572a180..51f03f9 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,363 @@ 스크린샷 2025-11-27 20 50 10 스크린샷 2025-11-27 20 50 11 스크린샷 2025-11-27 20 51 49 + + +# 주의 사항 리마인더 + +- 출석 확인은 크루가 캠퍼스에 들어 온 후 시스템에 출석 데이터가 저장된 시간 기준 → +- 시간 형식 24시간 제 +- 캠퍼스 운영 시간 08:00 ~ 23:00 +- 월 13:00~18:00 +- 화~ 금 10:00 18:00 +- 5분 : 지각, 30분 : 결석 +- 출석 기록 없음 : 결석 + - 출석을 18:00 이후에 하는 경우는? +- 주말, 공휴일은 출석 기능 자체가 불가 +- 크루, 출석 기록 → csv로 제공 +- 기능 선택 후 기능 선택해주세요 안내 메시지로 계속 돌아감 +- 종료 조건 : 기능에서 종료 선택 + +지각 및 결석 누적 조회 + +- 지각 3회 → 결석 1회 +- 결석 2회 : 경고 +- 결석 3회 : 면담 +- 결석 5회 : 제적 + +예상 필요 기능 + +캠퍼스 운영 시간, 근무 시간 기능 + +지각, 결석 누적 계산 기능 + +회원별 출석 기록 저장 기능 + +갑자기 든 생각 + +사람 마다 저장을 할 것인가 + +날짜 마다 저장을 할 것인가? + +캘린더니까 날짜마다가 맞지 않을 까? + +날짜마다 저장을 해주면 + +날짜 → 출석한 사람이름, 시간 만 저장하면 됨 + +- 출석 확인 + - 멤버 데이터 확인 + - 해당 날짜에 사람 이름, 시간, 출결 여부 저장 +- 출석 수정 + - 멤버 데이터 확인 + - 해당 날짜에 사람 이름, 시간, 출결 여부 덮어쓰기 +- 출석 기록 확인 + - 날짜 전체 순회 + - 사람이름이 입력 받은 값만 출력 + - 출격 여부 저장해가면서 출력 +- 제적 위험자 확인 + - 날짜 전체 순회 + - 결석,지각 이 있는 경우를 조회 + - 이름마다 누적시켜서 저장 + - + +# 서비스 흐름 구성 + +- 1차 설계 + - **파일 읽어오기** + + string, dateTIme- 날짜 시간 합친 형태 + + 1. 파일 한 줄 씩 읽기 + 2. 이름, 날짜 구분 + 3. 날짜에서 날짜, 출석 시간 구분 + 4. 날짜에서 요일 구별 + 5. 요일에 해당하는 출근 시간과 출석 시간을 비교 + 6. 출석, 결석, 지각 여부 판별 + 7. 출근 기록 데이터에 날짜, 요일, 시간, 출결 여부 저장 + - **출석 확인** + 1. 시스템 날짜와 요일 비교 + 1. 주말 및 공휴일 일 경우 에러 + 2. 이름 입력 받기(String) + 1. 이름이 멤버 데이터에 없으면 에러 + 2. 이름이 출석 기록 데이터에 있으면 에러 + 3. 형식 에러 + 3. 시간 입력 받기(String → DateTime) + 1. 시간이 캠퍼스 운영시간이 아닌 경우 에러 + 2. 형식 에러 + 4. 출석 기록 데이터에 날짜, 요일, 시간, 출결 여부 저장 + - **출석 수정** + 1. 이름 입력 받기(String) + 1. 이름이 멤버 데이터에 없으면 에러 + 2. 형식 에러 + 2. 날짜 입력 받기(String : 단일 날짜 → Integer → DateTime) + 1. 현재 날짜를 넘어가면 에러 + 2. 주말 및 공휴일 일 경우 에러 + 3. 형식 에러 + 3. 시간 입력 받기(String : 시간제 ex)09:58 → DateTime) + 1. 캠퍼스 운영시간이 아닌 경우 에러 + 4. 출석 기록 데이터에 날짜, 요일, 시간, 출결 여부 저장 + + - **크루별 출석 기록 확인** + 1. 이름 입력 받기(String) + 1. 이름이 멤버 데이터에 없으면 에러 + 2. 형식 에러 + 2. 출석 기록 데이터를 출력 + 1. 현재 날짜 전날 까지 출력 + 1. 날짜, 요일, 시간, 출결 여부 출력 + 2. 날짜 오름차순으로 출력 + 2. 총 출석, 지각, 결석 여부 출력 + 3. (옵션) 면담 대상자일 경우 출력 + - **제적 위험자 확인** + 1. 제적 위험자 출력 + + 출력 데이터 + + 1. 이름 + 2. 결석 횟수 + 3. 지각 횟수 + 4. 제적, 면담, 경고 여부 + 2. 정렬 기준 + 1. 제적, 면담, 경고 + 2. 결석, 지각 많은 순 + 3. 이름 순 + +- 2차 설계 + + **캘린더 List 생성하기** + + 1. 12월 1일 부터 12월 31일 까지 List로 빈 List<날짜, List> 생성하기 + + **파일 읽어오기** + + 1. 파일 한 줄 씩 읽기 + 2. 이름, 날짜, 요일, 시간 구분 + 3. 날짜에서 요일 구별 + 4. 요일에 해당하는 출근 시간과 입력 받은 출근 시간 비교 + 5. 출석,결석,지각 여부 판별 + 6. 해당 날짜에 이름, 시간, 출결 여부 저장 + + **출석 확인** + + 1. 출석 확인 진입 시 + 1. 현재 시간을 로컬로 계산 (반환) + 2. 캘린더에서 날짜를 조회(반환) + 3. 요일 조회 (반환) + 1. 요일이 (토-일, 공휴일) 인 경우 에러 발생 + 2. 이름 입력 받기 + 1. 형식 에러 + 2. 이름이 멤버 데이터에 없으면 에러 + 3. 캘린더에서 이름이 조회 되면 에러 + 3. 시간 입력 받기 + 1. 요일에 맞는 출석 시간이 아니면 에러 + 4. 캘린더 List에 새로운 데이터로 저장 + + **출석 수정** + + 1. 출석 수정 진입 시 + 1. 현재 시간을 로컬로 계산 (저장) + 2. 캘린더에서 날자 조회 (저장) + 3. 요일 조회 (저장) + 1. 요일이 (토-일, 공휴일) 인 경우 에러 발생 + 2. 이름 입력 받기 + 1. 형식 에러 + 2. 이름이 멤버 데이터에 없으면 에러 + 3. 날짜 입력 받기 + 1. 형식 에러 + 2. 로컬 날짜 이후인 경우 에러 + 4. 시간 입력 받기 + 1. 형식 에러 + 2. 캠퍼스 운영시간보다 이르거나 느리면 에러 발생 + 5. 캘린더 List에 새로운 데이터로 저장 + + **크루별 출석 기록 확인** + + 1. 크루별 출석 기록 확인 진입 시 + 1. 현재 시간을 로컬로 계산 + 2. 변수 저장 + 1. 총 출석 + 2. 총 지각 + 3. 총 결석 + 2. 이름 입력 받기 + 1. 형식 에러 + 2. 이름이 멤버 데이터에 없으면 에러 + 3. List 전체 순회 + 1. 현재 시간 전날 까지 List 조회 + 2. 이름을 fileter로 List Stream + 3. (옵션) 출석 있을 경우 출석에 저장 + 4. (옵션) 지각 있을 경우 지각에 저장 + 5. (옵션) 결석 있을 경우 결석에 저장 + 4. List 출력하기 + 5. 출결 기록 출력 + 6. (옵션) 면담 대상자 여부 출력 + + **제적 위험자 확인** + + 1. 제적 위험자 확인 진입 시 + 1. 현재 시간을 로컬로 계산(저장) + 2. 캘린더 List 전체 조회 + 1. 면담, 경고를 filter로 List Stream + 2. 정렬 + 1. 제적, 면담, 경고 + 2. 결석, 지각 + 3. 이름 + 3. List 출력하기 + +### 필요 데이터 + +- 1차 설계 + + **멤버 데이터** + + → 데이터 자료 구조 : List + + 필요한 데이터 + + - 이름 + + **출석 기록 데이터** + + → 데이터 자료 구조 : + + 추가(put)과 수정(update)가 쉬운 자료형일 것 + + 후보군 + + - Map + + → 이름을 key, 나머지 값들 객채로서 value로 저장하는 Map + + 이때 어떻게 할 것인가? + + - 추가 할 때 + 1. 이름 입력 받고 + + 예상 되는 단점 + + 출력할 때 정렬이 힘들 것 + + - List> + + → 이름을 하나로 갖는 이중 리스트 + + → 제일 가능성 있어보이긴함 + + - 추가할 때 + + 조회: 이름이 name인 자료로 fileter 스트림해서 list 반환 + + + + 필요한 데이터 + + - 이름 (대표) + - 출석 기록 + - 날짜 + - 요일 + - 시간 + - 출석, 지각, 결석 여부 + - 총 출석 + - 총 지각 + - 총 결석 +- 2차 설계 + + **멤버 데이터** + + → 데이터 자료 구조 : List + + 필요한 데이터 + + - 이름 + + **날짜별 출근 여부 데이터** + + → 데이터 자료 구조 : enum? list? + + 필요한 데이터 + + - 요일(월, 화-금, 토-일, 공휴일) + - 출근시간 + - 퇴근시간 + + **캘린더 데이터** + + → 데이터 자료 구조 + + List<날짜(dateTime), List<출석자(attendance)Object>> + + → hashmap으로 변경 + + 필요한 데이터 + + - 날짜(id) + - 요일 + - 출석자 + - 출석한 사람 이름 + - 출석 시간 + - 출결 여부 + +**개별 출석 데이터** + +→ 데이터 자료 구조 : Object + +필요한 데이터 + +- 이름 +- 출석 시간 +- 출결 여부 + +### 출력 형식 + +**기본 메시지** + +오늘은 {날짜 = 월, 일 요일} 입니다. 기능을 선택해주세요 + +1. 출석 확인 +2. 출석 수정 +3. 크루별 출석 기록 확인 +4. 제적 위험자 확인 + +Q. 종료 + +**출석 확인 메시지** + +- 닉네임을 입력해 주세요. +- 등교 시간을 입력해 주세요. +- {날짜 = 월, 일, 요일, 시간}, {출결 여부} + +**출석 수정 메시지** + +- 출석을 수정하려는 크루의 닉네임을 입력해 주세요. +- 수정하려는 날짜(일)를 입력해 주세요. +- 언제로 변경하겠습니까? +- {날짜 = 월, 일, 요일, 시간}, {출결 여부} → {날짜 = 월, 일, 요일, 시간}, {출결 여부} + +**크루별 출석 기록 확인 메시지** + +- 닉네임을 입력해주세요. +- 이번 달 {이름}의 출석 기록입니다. +- {날짜 = 월, 일, 요일, 시간}, {출결 여부} +- 출석 : {총 출석} 회 +- 지각 : {총 지각} 회 +- 결석: {총 결석} 회 +- (옵션) 면담 대상자 입니다. 경고 대상자 입니다. + +**제적 위험자 확인 메시지** + +- {이름} : 결석 {총 결석}회, 지각 {총 지각}회, {면담,경고 여부} + +### 에러 메시지 + +잘못된 형식을 입력하였습니다. + +등록되지 않은 닉네임입니다. + +{날짜 = 월, 일, 요일}은 등교일이 아닙니다. + +아직 수정할 수 없습니다. + +캠퍼스 운영 시간에만 출석이 가능합니다. + +이미 출석을 확인하였습니다. 필요한 경우 수정 기능을 이용해 주세요. + +# 기능 구성 (입,출력) \ No newline at end of file diff --git a/src/main/java/attendance/Application.java b/src/main/java/attendance/Application.java index e9b866e..a2c34fd 100644 --- a/src/main/java/attendance/Application.java +++ b/src/main/java/attendance/Application.java @@ -1,7 +1,408 @@ package attendance; +import attendance.domain.Attendance; +import attendance.util.ErrorMessage; +import camp.nextstep.edu.missionutils.Console; +import camp.nextstep.edu.missionutils.DateTimes; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.text.ParseException; +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.time.format.TextStyle; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + + // 캘린더 생성 (출석 기록) + HashMap> myCalender = new HashMap<>(); + TreeMap> sortedCalender = new TreeMap<>(); + + LocalTime mondayClassStartTime = null; + LocalTime classStartTime = null; + LocalTime classEndTime = null; + LocalTime campusStartTime = null; + LocalTime campusEndTime = null; + + DateTimeFormatter format = DateTimeFormatter.ofPattern("HH:mm"); + mondayClassStartTime = LocalTime.parse("13:00",format); + classStartTime =LocalTime.parse("10:00", format); + classEndTime = LocalTime.parse("18:00", format); + campusStartTime = LocalTime.parse("08:00", format); + campusEndTime = LocalTime.parse("23:00", format); + + // 멤버 데이터 저장 + Set memberSet = new HashSet<>(); + + // 파일 입력 받고 저장하기 + try { + String fileName = "src/main/resources/attendances.csv"; + FileReader file = new FileReader(fileName); + BufferedReader bufferedReader = new BufferedReader(file); + + bufferedReader.readLine(); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + while (true) { +// 1. 파일 한 줄 씩 읽기 + String line = bufferedReader.readLine(); + if (line == null) { + break; + } + // 2. 이름, 날짜, 요일, 시간 구분 + String[] input = line.split(","); + + // 이름 + String nickNameInput = input[0]; + + // 날짜만 yyyy-mm-dd + LocalDateTime dateTimeInput = LocalDateTime.parse(input[1], dateTimeFormatter); + // 날짜 + LocalDate date = dateTimeInput.toLocalDate(); + // 시간 + LocalTime time = dateTimeInput.toLocalTime(); + + // 디버깅 코드 +// System.out.println("Nickname: " + nickNameInput + " attendance time : " + dateTimeInput + " local date: " + date + " time: " + time2); + + + //3. 날짜에서 요일 구별 + String dateOfInput = dateTimeInput.getDayOfWeek().toString(); + + // 4. 요일에 해당하는 출근 시간과 입력 받은 출근 시간 비교 + Duration timeDiff = null; + if ( dateOfInput.equals("MONDAY") ) { + timeDiff = Duration.between(mondayClassStartTime,time); + }else{ + timeDiff = Duration.between(classStartTime,time); + } + + // 5. 출석,결석,지각 여부 판별 + String roll = ""; + + if(timeDiff.getSeconds() <= 5 * 60){ + roll = "출석"; + }else if(timeDiff.getSeconds() <= 30 * 60){ + roll = "지각"; + }else + { + roll = "결석"; + } + + // 6. 해당 날짜에 이름, 시간, 출결 여부 저장 + + Attendance attendance = new Attendance(nickNameInput,time,roll); + + //일단 조회 + List attendances = myCalender.get(date); + if (attendances == null || attendances.size() == 0) { + List newAttendances = new ArrayList<>(); + newAttendances.add(attendance); + myCalender.put(date,newAttendances); + }else{ + attendances.add(attendance); + myCalender.put(date,attendances); + } + memberSet.add(nickNameInput); + } + + + // 정렬 + sortedCalender = new TreeMap<>(myCalender); + + // 파일 끝 + bufferedReader.close(); + } catch (IOException e) { + System.out.println("[ERROR] 파일 불러오기에 실패했습니다."); + } + + // 로컬 시간 계산 + LocalDateTime systemTime = DateTimes.now(); +// LocalDateTime systemTime = LocalDateTime.of(2024,12,12,10,10); + LocalDate currentDateAndTime = systemTime.toLocalDate(); + int currentMonth = systemTime.getMonthValue(); + int currentDay = systemTime.getDayOfMonth(); + String currentDate = systemTime.getDayOfWeek().toString(); + String currentDateDisplay = systemTime.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.KOREAN); + + // 디버깅 코드 + Iterator>> iterator = sortedCalender.entrySet().iterator(); + while (iterator.hasNext()){ + Entry> entry = iterator.next(); + LocalDate localDate = entry.getKey(); + List attendances = entry.getValue(); + for(Attendance attendance : attendances){ + System.out.println("날짜 : " + localDate + "/ 출석자 이름 : " + attendance.getName() + "/ 출석 시간 : " + attendance.getAttendanceTime().toString() + "/ 출결 : " + attendance.getRoll()); + + } + } + + // 서비스 실행 (루프 시작) + while (true) { + + // 기본 안내 메시지 + System.out.printf("오늘은 %d월 %d일 %s입니다. 기능을 선택해주세요.\n", currentMonth, currentDay, currentDateDisplay); + System.out.println("1. 출석 확인\n" + + "2. 출석 수정\n" + + "3. 크루별 출석 기록 확인\n" + + "4. 제적 위험자 확인\n" + + "Q. 종료"); + + // 입력 받기 + + String command = Console.readLine(); + if(command.equals("1")){ +// 1. 출석 확인 진입 시 +// 1. 현재 시간을 로컬로 계산 (반환) +// 2. 캘린더에서 날짜를 조회(반환) +// 3. 요일 조회 (반환) +// 1. 요일이 (토-일, 공휴일) 인 경우 에러 발생 + if (currentDate.equals("SUNDAY") || currentDate.equals("SATURDAY")) { + String errorMessage = String.format("[ERROR] %d월 %d일 %s은 등교일이 아닙니다.\n ", currentMonth, currentDay, currentDateDisplay); + throw new IllegalArgumentException(errorMessage); + } + +// 2. 이름 입력 받기 + System.out.println("닉네임을 입력해 주세요."); + String nickNameInput = Console.readLine();; +// 1. 형식 에러 +// 2. 이름이 멤버 데이터에 없으면 에러 + if(!memberSet.contains(nickNameInput)){ + throw new IllegalArgumentException(ErrorMessage.NO_NICKNAME_MATCH_FOUND); + } +// 3. 캘린더에서 이름이 조회 되면 에러 + System.out.println("조회 날짜 형식 " + currentDateAndTime); + + //현재 날짜로 조회한 출석 부 + List attendancesResult = sortedCalender.get(currentDateAndTime); + + boolean isAlreadyAttendance = attendancesResult.stream() + .filter(attendance -> attendance.getName() == nickNameInput).findFirst().isPresent(); + + if(isAlreadyAttendance){ + throw new IllegalArgumentException(ErrorMessage.ALREADY_ATTENDACNED); + } + +// 3. 시간 입력 받기 + System.out.println("등교 시간을 입력해 주세요."); + String attendanceTimeInput = Console.readLine(); +// 0. 형식 에러 + checkTimeInputType(attendanceTimeInput); + LocalTime attendanceTime = LocalTime.parse(attendanceTimeInput, DateTimeFormatter.ofPattern("HH:mm")); +// 1. 캠퍼스 운영시간이 아니면 에러 + if(attendanceTime.isBefore(campusStartTime) || attendanceTime.isAfter(campusEndTime)){ + throw new IllegalArgumentException(ErrorMessage.NO_CAMPUS_RUNNINGTIME); + } + + String roll = checkRoll(currentDate,mondayClassStartTime,classStartTime,attendanceTime); + +// 4. 캘린더 List에 새로운 데이터로 저장 + Attendance newAttendance = new Attendance(nickNameInput,attendanceTime, roll); + attendancesResult.add(newAttendance); + sortedCalender.put(currentDateAndTime,attendancesResult); + System.out.printf("%d월 %d일 %s %s (%s)\n ", currentMonth, currentDay, currentDateDisplay, attendanceTimeInput, roll); + } + + +// 1. 출석 수정 진입 시 + if(command.equals("2")){ + +// 1. 현재 시간을 로컬로 계산 (저장) +// 2. 캘린더에서 날자 조회 (저장) +// 3. 요일 조회 (저장) +// 1. 요일이 (토-일, 공휴일) 인 경우 에러 발생 +// 2. 이름 입력 받기 + System.out.println("출석을 수정하려는 크루의 닉네임을 입력해 주세요."); + String nickNameInput = Console.readLine(); +// 1. 형식 에러 +// 2. 이름이 멤버 데이터에 없으면 에러 + if(!memberSet.contains(nickNameInput)){ + throw new IllegalArgumentException(ErrorMessage.NO_NICKNAME_MATCH_FOUND); + } +// 3. 날짜 입력 받기 + System.out.println("수정하려는 날짜(일) 을 입력해 주세요."); + String fixDateInput = Console.readLine(); + if(fixDateInput.length() == 1){ + fixDateInput = "0" +fixDateInput; + } + String prefixDateInput = "2024-12-"+fixDateInput; + LocalDate fixDate = LocalDate.parse(prefixDateInput, DateTimeFormatter.ofPattern("yyyy-MM-dd")); + String dateOfFixDate = fixDate.getDayOfWeek().toString(); +// 1. 형식 에러 +// 2. 로컬 날짜 이후인 경우 에러 + if(fixDate.isAfter(currentDateAndTime)){ + throw new IllegalArgumentException(ErrorMessage.CANNOT_FIX_TIME); + } +// 3. 공휴일 일 경우 에러 + if (dateOfFixDate.equals("SUNDAY") || dateOfFixDate.equals("SATURDAY")) { + String errorMessage = String.format("%d월 %d일 %s은 등교일이 아닙니다.\n ", currentMonth, currentDay, currentDateDisplay); + throw new IllegalArgumentException(errorMessage); + } +// 4. 시간 입력 받기 + System.out.println("언제로 변경하겠습니까?"); + String fixTimeInput = Console.readLine(); +// 1. 형식 에러 + checkTimeInputType(fixTimeInput); + LocalTime fixTime = LocalTime.parse(fixTimeInput, DateTimeFormatter.ofPattern("HH:mm")); +// 2. 캠퍼스 운영시간보다 이르거나 느리면 에러 발생 + if(fixTime.isBefore(campusStartTime) || fixTime.isAfter(campusEndTime)){ + throw new IllegalArgumentException(ErrorMessage.NO_CAMPUS_RUNNINGTIME); + } + + String roll = checkRoll(dateOfFixDate,mondayClassStartTime,classStartTime,fixTime); +// 5. 캘린더 List에 새로운 데이터로 저장 + List attendancesResult = sortedCalender.get(fixDate); + System.out.println("수정 목표 날짜" + fixDate + "수정 목표 이름 " + nickNameInput); +// for(Attendance attendance : attendancesResult){ +// System.out.println(attendance.getName() + " 이름 " ); +// } + Attendance oldAttendance = attendancesResult.stream() + .filter(attendance -> attendance.getName().equals(nickNameInput)) + .findFirst() + .orElse(null); + + LocalTime oldTime = oldAttendance.getAttendanceTime(); + String oldRoll = oldAttendance.getRoll(); + + int newMonth = fixDate.getMonthValue(); + int newDay = fixDate.getDayOfMonth(); + String newDate = fixDate.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.KOREAN); + + attendancesResult.remove(oldAttendance); + Attendance newAttendance = new Attendance(nickNameInput,fixTime, roll); + attendancesResult.add(newAttendance); + sortedCalender.put(fixDate,attendancesResult); + System.out.printf("%d월 %d일 %s %s (%s) -> %s (%s) 수정 완료!\n", + newMonth, newDay,newDate, oldTime.toString(),oldRoll, + fixTime.toString(), roll); + + } + + if(command.equals("3")){ + System.out.println("닉네임을 입력해 주세요."); + String nickNameInput = Console.readLine(); + if(!memberSet.contains(nickNameInput)){ + throw new IllegalArgumentException(ErrorMessage.NO_NICKNAME_MATCH_FOUND); + } + System.out.println("이번 달 " + nickNameInput +"의 출석 기록 입니다."); + + int attendanceCount = 0; + int lateCount = 0; + int absenceCount = 0; + + Iterator>> entries = sortedCalender.entrySet().iterator(); + while(entries.hasNext()){ + Entry> entry = entries.next(); + LocalDate currDate = entry.getKey(); + if(currDate.isEqual(currentDateAndTime)){ + continue; + } + List attendancesList = entry.getValue(); + Attendance attendanceResult = attendancesList.stream() + .filter(attendance -> attendance.getName().equals(nickNameInput)) + .findFirst() + .orElse(null); + String time = ""; + String roll = ""; + if(attendanceResult == null){ + time = "--:--"; + roll = "결석"; + }else{ + time = attendanceResult.getAttendanceTime().toString(); + roll = attendanceResult.getRoll(); + } + + if(roll == "출석"){ + attendanceCount++; + }else if(roll == "지각"){ + lateCount++; + }else{ + absenceCount++; + } + + int currMonth = currDate.getMonthValue(); + int currDay = currDate.getDayOfMonth(); + String formattedDay = String.format("%02d",currDay); + String currDateDisplay = currDate.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.KOREAN); + + System.out.println(currMonth + "월 " +formattedDay + "일 " + currDateDisplay +" " + time + " (" + roll + ")"); + + } + System.out.println("출석: " + attendanceCount + "회"); + System.out.println("지각: " + lateCount + "회"); + System.out.println("결석: " + absenceCount + "회"); + + if(lateCount >3){ + absenceCount += lateCount/3; + } + if(absenceCount >5){ + System.out.println("제적 대상자입니다."); + }else if(absenceCount >=3){ + System.out.println("면담 대상자입니다."); + }else if(absenceCount >=2){ + System.out.println("경고 대상자입니다."); + } + } + + if(command.equals("4")){ + System.out.println("제적 위험자 조회 결과"); + + } + + if(command.equals("Q")){ + return; + } + + + } + + + } + public static void checkTimeInputType(String timeInput){ + String[] times = timeInput.split(":"); + if(times.length != 2){ + throw new IllegalArgumentException(ErrorMessage.TYPE_ERROR); + } + int hour = Integer.parseInt(times[0]); + int minute = Integer.parseInt(times[1]); + if(hour < 0 || hour > 23 || minute < 0 || minute > 59){ + throw new IllegalArgumentException(ErrorMessage.TYPE_ERROR); + } + + } + public static String checkRoll(String dateOfInput, LocalTime mondayStartTime, LocalTime startTime, LocalTime time){ + // 4. 요일에 해당하는 출근 시간과 입력 받은 출근 시간 비교 + Duration timeDiff = null; + if ( dateOfInput.equals("MONDAY") ) { + timeDiff = Duration.between(mondayStartTime,time); + }else{ + timeDiff = Duration.between(startTime,time); + } + + // 5. 출석,결석,지각 여부 판별 + String roll = ""; + + if(timeDiff.getSeconds() <= 5 * 60){ + roll = "출석"; + }else if(timeDiff.getSeconds() <= 30 * 60){ + roll = "지각"; + }else + { + roll = "결석"; + } + return roll; } } diff --git a/src/main/java/attendance/domain/Attendance.java b/src/main/java/attendance/domain/Attendance.java new file mode 100644 index 0000000..c68b1bd --- /dev/null +++ b/src/main/java/attendance/domain/Attendance.java @@ -0,0 +1,37 @@ +package attendance.domain; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.Date; + +public class Attendance { + + private String name; + private LocalTime attendanceTime; + private String roll; + + /* + * 출결 결과 저장 객체 + * 이름, 출석 시간, 출결*/ + public Attendance(String name, LocalTime attendanceTime, String roll) { + this.name = name; + this.attendanceTime = attendanceTime; + this.roll = roll; + } + + public String getName() { + return name; + } + + public void setTime(LocalTime attendanceTime) { + this.attendanceTime = attendanceTime; + } + + public LocalTime getAttendanceTime() { + return attendanceTime; + } + + public String getRoll() { + return roll; + } +} diff --git a/src/main/java/attendance/util/ErrorMessage.java b/src/main/java/attendance/util/ErrorMessage.java new file mode 100644 index 0000000..89644dc --- /dev/null +++ b/src/main/java/attendance/util/ErrorMessage.java @@ -0,0 +1,9 @@ +package attendance.util; + +public class ErrorMessage { + public static String NO_NICKNAME_MATCH_FOUND = "[ERROR] 등록되지 않은 닉네임입니다."; + public static String TYPE_ERROR = "[ERROR] 잘못된 형식을 입력하였습니다."; + public static String CANNOT_FIX_TIME = "[ERROR] 아직 수정할 수 없습니다."; + public static String NO_CAMPUS_RUNNINGTIME = "[ERROR] 캠퍼스 운영 시간에만 출석이 가능합니다."; + public static String ALREADY_ATTENDACNED = "[ERROR] 이미 출석을 확인하였습니다. 필요한 경우 수정 기능을 이용해 주세요."; +}