From 094fe8cc78080bb644097af8441f68df9a534a97 Mon Sep 17 00:00:00 2001 From: Kimsangwon Date: Tue, 28 May 2024 20:26:10 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=EA=B8=B0=EC=97=AC=EB=8F=84=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C(1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit organization 멤버들의 퀴즈 생성과 퀴즈 푼 내역을 기준으로 점수를 반환 --- .../ContributionResultDTO.java | 11 +++ .../controller/ContributeController.java | 20 +++++ .../service/ContributionService.java | 74 +++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/DTOs/contributiondto/ContributionResultDTO.java create mode 100644 backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/controller/ContributeController.java create mode 100644 backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/service/ContributionService.java diff --git a/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/DTOs/contributiondto/ContributionResultDTO.java b/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/DTOs/contributiondto/ContributionResultDTO.java new file mode 100644 index 00000000..540eba94 --- /dev/null +++ b/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/DTOs/contributiondto/ContributionResultDTO.java @@ -0,0 +1,11 @@ +package com.Backend.shareNote.domain.Oraganization.DTOs.contributiondto; + +import lombok.Data; + +@Data +public class ContributionResultDTO { + private String userId; + private String nickname; + private Integer quizScore; + private Integer likeScore; +} diff --git a/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/controller/ContributeController.java b/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/controller/ContributeController.java new file mode 100644 index 00000000..6bb9e837 --- /dev/null +++ b/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/controller/ContributeController.java @@ -0,0 +1,20 @@ +package com.Backend.shareNote.domain.Oraganization.controller; + +import com.Backend.shareNote.domain.Oraganization.service.ContributionService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@Slf4j +@RequiredArgsConstructor +@RequestMapping("/api") +public class ContributeController { + private final ContributionService contributionService; + @GetMapping("/contribute/{organizationId}") + public ResponseEntity getContribution(@PathVariable String organizationId){ + return contributionService.getContribution(organizationId); + + } +} diff --git a/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/service/ContributionService.java b/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/service/ContributionService.java new file mode 100644 index 00000000..b40ea96f --- /dev/null +++ b/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/service/ContributionService.java @@ -0,0 +1,74 @@ +package com.Backend.shareNote.domain.Oraganization.service; + +import com.Backend.shareNote.domain.Oraganization.DTOs.contributiondto.ContributionResultDTO; +import com.Backend.shareNote.domain.Oraganization.entity.Organization; +import com.Backend.shareNote.domain.Oraganization.repository.OrganizationRepository; +import com.Backend.shareNote.domain.User.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class ContributionService { + private final OrganizationRepository organizationRepository; + + private final UserRepository userRepository; + + public ResponseEntity getContribution(String organizationId) { + try { + // organization 찾기 + Organization organization = organizationRepository.findById(organizationId) + .orElseThrow(() -> new IllegalArgumentException("해당하는 organization이 없습니다.")); + + + // 우선 organization의 멤버들의 우선 quiz 맞춘게 있으면 +1을 하자 + List resultlist = new ArrayList<>(); + + HashMap quizMap = new HashMap<>(); + // quizMap 초기화 + organization.getMembers().forEach(member -> { + quizMap.put(member, 0); + }); + + // 노트 조회 하면서 퀴즈의 맞춘 목록을 뒤지면서 quizMap 완성하기 + organization.getNotes().forEach(note -> { + note.getQuiz().forEach(quiz -> { + for (String key : quiz.getCorrectUser()) { + quizMap.put(key, quizMap.get(key) + 1); + } + // 퀴즈 출제자도 1점 추가 + quizMap.put(quiz.getUserId(), quizMap.get(quiz.getUserId()) + 1); + }); + }); + + organization.getMembers().forEach(member -> { + // 모든 유저에 대해서 닉네임, id, quizScore, (likeScore)를 넣어주자 + ContributionResultDTO contributionResultDTO = new ContributionResultDTO(); + contributionResultDTO.setUserId(member); + + // 닉네임 추가하기 + userRepository.findById(member).ifPresent(user -> { + contributionResultDTO.setNickname(user.getNickname()); + }); + + // quiz 점수 추가 + contributionResultDTO.setQuizScore(quizMap.get(member)); + + // like 점수 추가 (추후에 추가 예정) + contributionResultDTO.setLikeScore(0); + + resultlist.add(contributionResultDTO); + }); + + return ResponseEntity.ok().body(resultlist); + } catch (Exception e) { + return ResponseEntity.badRequest().body(e.getMessage()); + } + } + +} From edfbd96edf1c74c5194ab8cc56d4b2d7624e6985 Mon Sep 17 00:00:00 2001 From: Kimsangwon Date: Tue, 28 May 2024 20:55:12 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat=20:=20nodeserver=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nodejs/server.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nodejs/server.js b/nodejs/server.js index f83b0766..60d8fe16 100644 --- a/nodejs/server.js +++ b/nodejs/server.js @@ -24,8 +24,8 @@ const databaseName = 'shareDB'; function createConnectionString(databaseName) { logger.info(`@@@@@@@@@@@mongodb://root:1234@localhost:27017/${databaseName}?authSource=admin`); - return `mongodb://root:1234@localhost:27017/${databaseName}?authSource=admin`; - //return `mongodb://root:1234@mongodbService:27017/${databaseName}?authSource=admin`; + //return `mongodb://root:1234@localhost:27017/${databaseName}?authSource=admin`; + return `mongodb://root:1234@mongodbService:27017/${databaseName}?authSource=admin`; } const server = http.createServer((req, res) => { From efb57f932b890876039fe81192a333b8f71a8ad1 Mon Sep 17 00:00:00 2001 From: Kimsangwon Date: Wed, 29 May 2024 14:48:15 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=EC=A2=8B=EC=95=84=EC=9A=94=20api?= =?UTF-8?q?=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 너무 복잡해서 최근에 배운 Set을 통해서 간단하게 구현함 --- .../Oraganization/entity/Organization.java | 61 ++++++++++--------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/entity/Organization.java b/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/entity/Organization.java index 1ba9d2f6..02b18860 100644 --- a/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/entity/Organization.java +++ b/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/entity/Organization.java @@ -10,10 +10,7 @@ import org.springframework.data.mongodb.core.mapping.Document; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; @Document(collection = "organizations") @Builder @@ -115,7 +112,7 @@ public static class Quiz { @Getter @Slf4j public static class LikesInfo { - private Map userLikes = new HashMap<>(); + private Map> userLikes = new HashMap<>(); /** * 좋아요를 추가하거나 취소합니다. @@ -129,46 +126,52 @@ public Boolean addLike(String userUuid, String blockId, String likerUuid) { if(userUuid.equals(likerUuid)) { throw new SelfLikedException("자기 블록에 좋아요를 누를 수 없습니다."); } - return userLikes.computeIfAbsent(userUuid, k -> new UserLike()) - .addBlockLike(blockId, likerUuid); + BlockLike blockLike = new BlockLike(blockId, likerUuid); + userLikes.putIfAbsent(userUuid, new HashSet<>()); + if(userLikes.get(userUuid).contains(blockLike)) { + log.info("이미 좋아요를 누른 상태입니다."); + userLikes.get(userUuid).remove(blockLike); + return false; + }else { + userLikes.get(userUuid).add(blockLike); + return true; + } } - // 필요한 메서드 추가... - } - @Getter - public static class UserLike { - private Map blockLikes = new HashMap<>(); - - public Boolean addBlockLike(String blockId, String likerUuid) { - return blockLikes.computeIfAbsent(blockId, k -> new BlockLike()) - .addLiker(likerUuid); + // 기여도에서 좋아요 개수를 가져오기 위한 메서드 + public int getLikeCount(String userUuid){ + return userLikes.get(userUuid).size(); } // 필요한 메서드 추가... } @Getter public static class BlockLike { - private List likers = new ArrayList<>(); - - public Boolean addLiker(String likerUuid) { - // 좋아요 취소 로직 구현 및 좋아요 여부 확인 - if(likers.contains(likerUuid)){ - likers.remove(likerUuid); - return false; - } - else{ - likers.add(likerUuid); - return true; - } + private String blockId; + private String likerUuid; + public BlockLike(String blockId, String likerUuid) { + this.blockId = blockId; + this.likerUuid = likerUuid; + } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + BlockLike blockLike = (BlockLike) o; + return Objects.equals(blockId, blockLike.blockId) && Objects.equals(likerUuid, blockLike.likerUuid); } - // 필요한 메서드 추가... + @Override + public int hashCode() { + return Objects.hash(blockId, likerUuid); + } } + public void addPageToNote(String noteId, Page newPage) { for (Note note : this.notes) { if (note.getId().equals(noteId)) { From 5e54a35e0d8b447c789ed4bfe61b99fa65e016ba Mon Sep 17 00:00:00 2001 From: Kimsangwon Date: Wed, 29 May 2024 18:02:14 +0900 Subject: [PATCH 4/4] =?UTF-8?q?feat=20:=20=EA=B8=B0=EC=97=AC=EB=8F=84=20ap?= =?UTF-8?q?i=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ContributionService.java | 16 ++++++++++++---- .../utils/editor/plugin/generateBlockIdPlugin.js | 7 ++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/service/ContributionService.java b/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/service/ContributionService.java index b40ea96f..a2053e13 100644 --- a/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/service/ContributionService.java +++ b/backend/shareNote/src/main/java/com/Backend/shareNote/domain/Oraganization/service/ContributionService.java @@ -8,9 +8,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; +import java.util.*; @Service @RequiredArgsConstructor @@ -30,6 +28,8 @@ public ResponseEntity getContribution(String organizationId) { List resultlist = new ArrayList<>(); HashMap quizMap = new HashMap<>(); + HashMap likeMap = new HashMap<>(); + // quizMap 초기화 organization.getMembers().forEach(member -> { quizMap.put(member, 0); @@ -37,6 +37,14 @@ public ResponseEntity getContribution(String organizationId) { // 노트 조회 하면서 퀴즈의 맞춘 목록을 뒤지면서 quizMap 완성하기 organization.getNotes().forEach(note -> { + //note의 like 정보를 갖고 있는 맵 + Map> userLikes = note.getLikesInfo().getUserLikes(); + + for (String uuid :note.getLikesInfo().getUserLikes().keySet()) { + likeMap.put(uuid, likeMap.getOrDefault(uuid,0) + userLikes.get(uuid).size() ); + } + + note.getQuiz().forEach(quiz -> { for (String key : quiz.getCorrectUser()) { quizMap.put(key, quizMap.get(key) + 1); @@ -60,7 +68,7 @@ public ResponseEntity getContribution(String organizationId) { contributionResultDTO.setQuizScore(quizMap.get(member)); // like 점수 추가 (추후에 추가 예정) - contributionResultDTO.setLikeScore(0); + contributionResultDTO.setLikeScore(likeMap.getOrDefault(member,0)); resultlist.add(contributionResultDTO); }); diff --git a/frontend/src/Component/Page/utils/editor/plugin/generateBlockIdPlugin.js b/frontend/src/Component/Page/utils/editor/plugin/generateBlockIdPlugin.js index 0ba4a252..f28450a7 100644 --- a/frontend/src/Component/Page/utils/editor/plugin/generateBlockIdPlugin.js +++ b/frontend/src/Component/Page/utils/editor/plugin/generateBlockIdPlugin.js @@ -1,3 +1,4 @@ +import { localStorageCache } from "prosemirror-image-plugin"; import { Plugin } from "prosemirror-state"; import { v4 as uuidv4 } from "uuid"; @@ -22,7 +23,7 @@ export const generateBlockIdPlugin = (guidGenerator = uuidv4) => { newGuid = guidGenerator(); } while (generatedIds.has(newGuid)); generatedIds.add(newGuid); - tr.setNodeMarkup(pos, undefined, {...node.attrs, 'data-guid': newGuid}); + tr.setNodeMarkup(pos, undefined, {...node.attrs, 'data-guid': newGuid, 'data-writer': localStorage.getItem('userId')}); modified = true; } else { generatedIds.add(currentGuid); @@ -41,7 +42,7 @@ export const generateBlockIdPlugin = (guidGenerator = uuidv4) => { newGuid = guidGenerator(); } while (generatedIds.has(newGuid)); generatedIds.add(newGuid); - tr.setNodeMarkup(pos, undefined, {...node.attrs, guid: newGuid}); + tr.setNodeMarkup(pos, undefined, {...node.attrs, guid: newGuid, writer: localStorage.getItem('userId')}); modified = true; } } else { @@ -53,7 +54,7 @@ export const generateBlockIdPlugin = (guidGenerator = uuidv4) => { newGuid = guidGenerator(); } while (generatedIds.has(newGuid)); generatedIds.add(newGuid); - tr.setNodeMarkup(pos, undefined, {...node.attrs, guid: newGuid}); + tr.setNodeMarkup(pos, undefined, {...node.attrs, guid: newGuid, writer: localStorage.getItem('userId')}); modified = true; } else { generatedIds.add(currentGuid);