diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index d843f34..35eb1dd 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -1,4 +1,6 @@
-
+
+
+
\ No newline at end of file
diff --git a/src/main/java/org/sopt/seminar1/Diary.java b/src/main/java/org/sopt/seminar1/Diary.java
new file mode 100644
index 0000000..c56b161
--- /dev/null
+++ b/src/main/java/org/sopt/seminar1/Diary.java
@@ -0,0 +1,38 @@
+package org.sopt.seminar1;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+public class Diary {
+ private Long id;
+ private final String body;
+ private boolean isDeleted = false;
+ private LocalDateTime lastEditedDateTime;
+
+ public Diary(Long id, String body) {
+ this.id = id;
+ this.body = body;
+ this.lastEditedDateTime = LocalDateTime.now();
+ }
+
+ public Long getId() {
+ return id;
+ }
+ public String getBody() {
+ return body;
+ }
+
+ public boolean isDeleted() {
+ return isDeleted;
+ }
+ public void setDeleted(boolean deleted) {
+ this.isDeleted = deleted;
+ }
+
+ public LocalDateTime getLastEditedDateTime() {
+ return lastEditedDateTime;
+ }
+ public void setLastEditedDateTime(LocalDateTime lastEditedDateTime) {
+ this.lastEditedDateTime = lastEditedDateTime;
+ }
+}
diff --git a/src/main/java/org/sopt/seminar1/DiaryController.java b/src/main/java/org/sopt/seminar1/DiaryController.java
new file mode 100644
index 0000000..a1b71cf
--- /dev/null
+++ b/src/main/java/org/sopt/seminar1/DiaryController.java
@@ -0,0 +1,63 @@
+package org.sopt.seminar1;
+
+import java.util.List;
+
+public class DiaryController {
+ private Status status = Status.READY;
+ private final DiaryService diaryService = new DiaryService();
+
+ Status getStatus() {
+ return status;
+ }
+
+ void boot() {
+ this.status = Status.RUNNING;
+ }
+
+ void finish() {
+ this.status = Status.FINISHED;
+ }
+
+ // APIS
+ final List getList() {
+ return diaryService.getDiaryList();
+ }
+
+ final void post(final String body) {
+ diaryService.writeDiary(body);
+ }
+
+ final void delete(final String id) {
+ long longId = validateAndConvertId(id);
+ diaryService.deleteDiary(longId);
+ }
+
+ final void patch(final String id, final String body) {
+ long longId = validateAndConvertId(id);
+ diaryService.updateDiary(longId, body);
+ }
+
+ final void restore(final String id) {
+ long longId = validateAndConvertId(id);
+ diaryService.restoreDiary(longId);
+ }
+
+ enum Status {
+ READY,
+ RUNNING,
+ FINISHED,
+ ERROR,
+ }
+
+ private long validateAndConvertId(final String id) {
+ if (!id.matches("^[1-9][0-9]*$")) {
+ throw new Main.UI.InvalidInputException();
+ }
+
+ try {
+ return Long.parseLong(id);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("유효한 long 형식의 ID여야 합니다.");
+ }
+ }
+}
diff --git a/src/main/java/org/sopt/seminar1/DiaryRepository.java b/src/main/java/org/sopt/seminar1/DiaryRepository.java
new file mode 100644
index 0000000..6cd51c7
--- /dev/null
+++ b/src/main/java/org/sopt/seminar1/DiaryRepository.java
@@ -0,0 +1,67 @@
+package org.sopt.seminar1;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class DiaryRepository {
+ private final Map storage = new ConcurrentHashMap<>();
+ private final AtomicLong numbering = new AtomicLong();
+ private int updateCount = 0;
+
+ void save(Diary diary) {
+ final long id = numbering.addAndGet(1);
+ diary.setDeleted(false);
+ diary = new Diary(id, diary.getBody());
+ storage.put(id, diary); // Diary 객체를 저장
+ }
+
+ List findAll() {
+ final List diaryList = new ArrayList<>();
+ for (long index = 1; index <= numbering.longValue(); index++) {
+ final Diary diary = storage.get(index);
+ if (diary != null && !diary.isDeleted()) {
+ diaryList.add(diary);
+ }
+ }
+ return diaryList;
+ }
+
+ void delete(final long id) {
+ Diary diary = storage.get(id);
+ if (diary != null) {
+ diary.setDeleted(true);
+ }
+ }
+
+ void update(final long id, final String newBody) {
+ Diary diary = storage.get(id);
+ if (diary != null && !diary.isDeleted()) {
+ LocalDateTime now = LocalDateTime.now();
+ LocalDateTime lastEditedDateTime = diary.getLastEditedDateTime();
+
+ if (!(lastEditedDateTime.toLocalDate().equals(now.toLocalDate()))) {
+ updateCount = 0;
+ diary.setLastEditedDateTime(now);
+ }
+
+ if (updateCount <2){
+ updateCount++;
+ diary.setDeleted(false);
+ storage.replace(id, new Diary(id, newBody));
+ } else {
+ throw new Main.UI.InvalidInputException();
+ }
+ }
+ }
+
+ void restore(final long id) {
+ Diary diary = storage.get(id);
+ if (diary != null && diary.isDeleted()) {
+ diary.setDeleted(false);
+ }
+ }
+}
diff --git a/src/main/java/org/sopt/seminar1/DiaryService.java b/src/main/java/org/sopt/seminar1/DiaryService.java
new file mode 100644
index 0000000..b95e646
--- /dev/null
+++ b/src/main/java/org/sopt/seminar1/DiaryService.java
@@ -0,0 +1,24 @@
+package org.sopt.seminar1;
+
+import java.util.List;
+
+public class DiaryService {
+ private final DiaryRepository diaryRepository = new DiaryRepository();
+
+ void writeDiary(String body){
+ final Diary diary = new Diary(null, body);
+ diaryRepository.save(diary);
+ }
+ List getDiaryList(){
+ return diaryRepository.findAll();
+ }
+ void deleteDiary(long id){
+ diaryRepository.delete(id);
+ }
+ void updateDiary(long id, String body){
+ diaryRepository.update(id ,body);
+ }
+ void restoreDiary(long id) { // 복구 기능 추가
+ diaryRepository.restore(id);
+ }
+}
diff --git a/src/main/java/org/sopt/seminar1/Main.java b/src/main/java/org/sopt/seminar1/Main.java
new file mode 100644
index 0000000..b49025b
--- /dev/null
+++ b/src/main/java/org/sopt/seminar1/Main.java
@@ -0,0 +1,188 @@
+package org.sopt.seminar1;
+
+import java.io.*;
+
+public class Main {
+ public static void main(String[] args) {
+ final UI ui;
+ try {
+ ui = new DiaryUI(new DiaryController());
+ ui.runRepeatedly();
+ } catch (Throwable t) {
+
+ }
+ }
+
+ interface UI {
+ void runRepeatedly() throws IOException;
+
+ class UIException extends RuntimeException {
+ }
+
+ class InvalidInputException extends UIException {
+ }
+ }
+
+ static class DiaryUI implements UI {
+ private final DiaryController server;
+ private String selected;
+
+ public DiaryUI(DiaryController server) throws IOException {
+ this.server = server;
+ server.boot();
+ ConsoleIO.printLine(getStartMessage());
+ }
+
+ public void runRepeatedly() throws IOException {
+
+ do {
+ if (onMenu()) {
+ ConsoleIO.printLine("");
+ ConsoleIO.printLine(getMenu());
+ selected = ConsoleIO.readLine().trim().toUpperCase();
+ }
+
+ try {
+ run();
+ } catch (InvalidInputException e) {
+ ConsoleIO.printLine("잘못된 값을 입력하였습니다.");
+ }
+
+ if (isFinished()) {
+ ConsoleIO.printLine(getFinishMessage());
+ break;
+ }
+
+ selected = null;
+ } while (isRunning());
+ }
+
+ //30글자 제한
+ private void validateInputLength(final String input) throws InvalidInputException, IOException {
+ if (input.length() > 30) {
+ ConsoleIO.printLine("일기는 최대 30글자까지만 입력할 수 있습니다. 다시 입력해주세요.");
+ throw new InvalidInputException();
+ }
+ }
+
+ private void run() throws IOException {
+ switch (server.getStatus()) {
+ case READY, FINISHED, ERROR -> throw new UIException();
+
+ case RUNNING -> {
+ switch (selected) {
+ case "GET" -> {
+ server.getList().forEach(diary -> {
+ try {
+ ConsoleIO.printLine(diary.getId()+" : "+diary.getBody());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+ case "POST" -> {
+ ConsoleIO.printLine("한 줄 일기를 작성해주세요!");
+ final String input = ConsoleIO.readLine();
+ validateInputLength(input);
+ server.post(input);
+ }
+
+ case "DELETE" -> {
+ ConsoleIO.printLine("삭제할 id 를 입력하세요!");
+ final String input = ConsoleIO.readLine();
+ server.delete(input);
+ }
+ case "PATCH" -> {
+ ConsoleIO.printLine("수정할 id 를 입력하세요!");
+ final String inputId = ConsoleIO.readLine();
+
+ ConsoleIO.printLine("수정 body 를 입력하세요!");
+ final String inputBody = ConsoleIO.readLine();
+ validateInputLength(inputBody);
+ server.patch(inputId, inputBody);
+ }
+ case "RESTORE" -> {
+ ConsoleIO.printLine("복구할 id 를 입력하세요!");
+ final String input = ConsoleIO.readLine();
+ server.restore(input); // 복구 기능 호출
+ }
+ case "FINISH" -> {
+ server.finish();
+ }
+ default -> {
+ throw new InvalidInputException();
+ }
+ }
+ }
+
+ }
+ }
+
+ private boolean isRunning() {
+ return server.getStatus() == DiaryController.Status.RUNNING;
+ }
+
+ private boolean isFinished() {
+ return server.getStatus() == DiaryController.Status.FINISHED;
+ }
+
+ private boolean onMenu() {
+ return selected == null;
+ }
+
+ private String getMenu() {
+ return """
+ ============================
+ - GET : 일기 불러오기
+ - POST : 일기 작성하기
+ - DELETE : 일기 제거하기
+ - PATCH : 일기 수정하기
+ - RESTORE : 일기 복구하기
+ """;
+
+ }
+
+ private String getStartMessage() {
+ return "시작합니다 :)";
+ }
+
+ private String getFinishMessage() {
+ return "종료됩니다 :)";
+ }
+ }
+
+ // not thread safe
+ private static class ConsoleIO {
+ private final static BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(System.out));
+ private final static BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
+ private final static StringBuilder sb = new StringBuilder();
+
+ public static void printLine(final String toPrint) throws IOException {
+ if (toPrint == null) {
+ throw new IllegalArgumentException("console can not print null");
+ }
+
+ appendLine(toPrint);
+ print();
+ clearStringBuilder();
+ }
+
+ public static String readLine() throws IOException {
+ return bufferedReader.readLine();
+ }
+
+ private static void appendLine(final String toPrint) {
+ sb.append(toPrint);
+ sb.append("\n");
+ }
+
+ private static void print() throws IOException {
+ bufferedWriter.write(sb.toString());
+ bufferedWriter.flush();
+ }
+
+ private static void clearStringBuilder() {
+ sb.setLength(0);
+ }
+ }
+}