Skip to content

Commit

Permalink
Merge pull request #343 from 6QuizOnTheBlock/be/feat/#327-isolation_cโ€ฆ
Browse files Browse the repository at this point in the history
โ€ฆalculation

feat: ํ•™์ƒ ์†Œ์™ธ๋„ ์ ์ˆ˜ ๊ณ„์‚ฐ
  • Loading branch information
HABINOH authored May 17, 2024
2 parents 4b84dd4 + 26fc585 commit d774d07
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,8 @@ public void updateChallengeCount() {
public void updateRelayCount() {
this.relayCount += 1;
}

public void updateIsolationPoint(double isolationPoint) {
this.isolationPoint = isolationPoint;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ Optional<MemberOrganization> findByMemberIdAndOrganizationId(Long memberId,

Optional<MemberOrganization> findByOrganizationAndMember(Organization organization,
Member member);

List<MemberOrganization> findAllByOrganizationOrderByMemberId(Organization organization);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.quiz.ourclass.domain.organization.repository;

import com.quiz.ourclass.domain.organization.entity.Organization;
import com.quiz.ourclass.domain.member.entity.Member;
import com.quiz.ourclass.domain.organization.entity.Relationship;
import java.util.List;
import java.util.Optional;
Expand All @@ -15,4 +16,6 @@ Optional<Relationship> findByOrganizationIdAndMember1IdAndMember2Id(
List<Relationship> findAllByOrganization(Organization organization);

List<Relationship> findAllByOrganizationIdOrderByMember1(Long orgId);

List<Relationship> findByMember1(Member member);
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
package com.quiz.ourclass.global.util.scheduler;

import com.quiz.ourclass.domain.organization.entity.MemberOrganization;
import com.quiz.ourclass.domain.organization.entity.Organization;
import com.quiz.ourclass.domain.organization.entity.Relationship;
import com.quiz.ourclass.domain.organization.repository.MemberOrganizationRepository;
import com.quiz.ourclass.domain.organization.repository.OrganizationRepository;
import com.quiz.ourclass.domain.organization.repository.RelationshipRepository;
import com.quiz.ourclass.domain.relay.repository.RelayMemberRepository;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

@Slf4j
@EnableScheduling
@RequiredArgsConstructor
@Service
Expand All @@ -25,6 +33,8 @@ public class SchedulingService {
private final TransactionTemplate transactionTemplate;
private final RelationshipRepository relationshipRepository;
private final RelayMemberRepository relayMemberRepository;
private final MemberOrganizationRepository memberOrganizationRepository;
private final OrganizationRepository organizationRepository;

public <T> void scheduleTask(T target, Consumer<T> action, LocalDateTime executionTime) {
SchedulingTask<T> task = new SchedulingTask<>(target, action, transactionTemplate);
Expand All @@ -36,16 +46,99 @@ public <T> void scheduleTask(T target, Consumer<T> action, LocalDateTime executi
@Transactional
@Scheduled(cron = "0 0 3 * * *")
protected void relationShipScore() {
List<Relationship> relationshipList =
relationshipRepository.findAllByOrganizationIdOrderByMember1(1L);
List<Organization> organizations =
organizationRepository.findAll();

if (!relationshipList.isEmpty()) {
relationshipList.stream()
.map(this::updateRelationShipScore)
.forEach(relationshipRepository::save);
for (Organization organization : organizations) {
List<Relationship> relationshipList =
relationshipRepository.findAllByOrganizationIdOrderByMember1(organization.getId());

if (!relationshipList.isEmpty()) {
relationshipList.stream()
.map(this::updateRelationShipScore)
.forEach(relationshipRepository::save);
}
}
}

@Transactional
@Scheduled(cron = "0 30 3 * * *")
protected void isolationScore() {
List<Organization> organizations = organizationRepository.findAll();

for (Organization organization : organizations) {
List<MemberOrganization> memberOrganizations =
memberOrganizationRepository.findAllByOrganizationOrderByMemberId(organization);
List<Double> allScores = new ArrayList<>();

// ์ „์ฒด ์ ์ˆ˜ ์ˆ˜์ง‘
for (MemberOrganization member : memberOrganizations) {
allScores.addAll(retrieveScores(member, memberOrganizations, organization));
}

// ์ „์ฒด ์ ์ˆ˜์˜ ํ‰๊ท ๊ณผ ํ‘œ์ค€ํŽธ์ฐจ ๊ณ„์‚ฐ
double mean = allScores.stream()
.mapToDouble(Double::doubleValue)
.average()
.orElse(0.0);

double stdDev = calculateStandardDeviation(allScores, mean);

// ๊ฐ ๋ฉค๋ฒ„์˜ ์ ์ˆ˜ ์ •๊ทœํ™” ๋ฐ ์†Œ์™ธ๋„ ๊ณ„์‚ฐ
for (MemberOrganization member : memberOrganizations) {
List<Double> scores = retrieveScores(member, memberOrganizations, organization);

List<Double> normalizedScores;
if (stdDev < 1e-10) { // ๋งค์šฐ ์ž‘์€ ํ‘œ์ค€ํŽธ์ฐจ ์ฒ˜๋ฆฌ
// ํ‘œ์ค€ํŽธ์ฐจ๊ฐ€ 0์ผ ๋•Œ, ์ฆ‰ ๋ชจ๋“  ์ ์ˆ˜๊ฐ€ ๊ฐ™์„ ๋•Œ
// ๋ชจ๋“  ์ •๊ทœํ™” ์ ์ˆ˜๋ฅผ 0์œผ๋กœ ์„ค์ •
normalizedScores = Collections.nCopies(scores.size(), 0.0);
} else { // ์ •๊ทœํ™”
normalizedScores = scores.stream()
.map(score -> (score - mean) / stdDev)
.toList();
}
// ์†Œ์™ธ๋„ ์ ์ˆ˜ ๋„์ถœ
double isolationScore = normalizedScores.stream()
.mapToDouble(Double::doubleValue)
.average()
.orElse(0.0);

updateIsolationScore(member, isolationScore);
}
}
}

private List<Double> retrieveScores(
MemberOrganization member, List<MemberOrganization> memberOrganizations,
Organization organization
) {
List<Double> scores = new ArrayList<>();
for (MemberOrganization otherMember : memberOrganizations) {
if (!member.equals(otherMember)) {
relationshipRepository.findByOrganizationIdAndMember1IdAndMember2Id(
organization.getId(),
member.getMember().getId(),
otherMember.getMember().getId()
).ifPresent(rel -> scores.add(rel.getRelationPoint()));
}
}
return scores;
}

private double calculateStandardDeviation(List<Double> scores, double mean) {
double variance = scores.stream()
.mapToDouble(score -> Math.pow(score - mean, 2))
.average()
.orElse(0.0);
return Math.sqrt(variance);
}

private void updateIsolationScore(MemberOrganization member, double isolationScore) {
member.updateIsolationPoint(isolationScore);
memberOrganizationRepository.save(member);
}

private Relationship updateRelationShipScore(Relationship relationship) {
double newScore = calculateScore(relationship);
relationship.updateRelationPoint(newScore);
Expand Down

0 comments on commit d774d07

Please sign in to comment.