Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions backend/ongi/src/main/java/ongi/OngiApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableJpaAuditing
@EnableScheduling
public class OngiApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ public interface TemperatureRepository extends JpaRepository<Temperature, Long>
@Query("SELECT COUNT(t) > 0 FROM Temperature t WHERE t.userId = :userId AND t.familyId = :familyId AND t.reason = :reason AND FUNCTION('DATE', t.createdAt) = :date")
boolean existsByUserIdAndFamilyIdAndReasonAndDate(@Param("userId") java.util.UUID userId, @Param("familyId") String familyId, @Param("reason") String reason, @Param("date") java.time.LocalDate date);

// 최근 N일간 해당 유저가 가족 내에서 활동(온도 변화)이 있었는지
@Query("SELECT COUNT(t) > 0 FROM Temperature t WHERE t.userId = :userId AND t.familyId = :familyId AND t.createdAt >= :since")
// 최근 N일간 해당 유저가 가족 내에서 활동(온도 변화)이 있었는지 (만보기 제외)
@Query("SELECT COUNT(t) > 0 FROM Temperature t WHERE t.userId = :userId AND t.familyId = :familyId AND t.reason != 'STEP_GOAL' AND t.createdAt >= :since")
boolean existsByUserIdAndFamilyIdAndCreatedAtAfter(@Param("userId") java.util.UUID userId, @Param("familyId") String familyId, @Param("since") java.time.LocalDateTime since);

// 최근 N일간 가족 내에서 아무나 활동(온도 변화)이 있었는지
@Query("SELECT COUNT(t) > 0 FROM Temperature t WHERE t.familyId = :familyId AND t.createdAt >= :since")
// 최근 N일간 가족 내에서 아무나 활동(온도 변화)이 있었는지 (만보기 제외)
@Query("SELECT COUNT(t) > 0 FROM Temperature t WHERE t.familyId = :familyId AND t.reason != 'STEP_GOAL' AND t.createdAt >= :since")
boolean existsByFamilyIdAndCreatedAtAfter(@Param("familyId") String familyId, @Param("since") java.time.LocalDateTime since);

@Query("SELECT SUM(t.temperature) FROM Temperature t WHERE t.familyId = :familyId AND t.createdAt < :fromDate")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public class TemperatureService {
private final UserRepository userRepository;
private final StepRepository stepRepository;
private static final double BASE_TEMPERATURE = 36.5;

// 가족 전체 온도 변화를 나타내는 가상 사용자 ID
private static final UUID FAMILY_WIDE_USER_ID = UUID.fromString("00000000-0000-0000-0000-000000000000");

// 소수점 1자리 반올림 유틸
private static double round(double value, int places) {
Expand Down Expand Up @@ -137,7 +140,12 @@ public FamilyTemperatureContributionResponse getFamilyTemperatureContributions(S
List<FamilyTemperatureContributionResponse.Contribution> contributions = temps.stream()
.map(t -> {
User user = userMap.get(t.getUserId());
String userName = user != null ? user.getName() : "우리 가족";
String userName;
if (t.getUserId().equals(FAMILY_WIDE_USER_ID)) {
userName = "우리 가족";
} else {
userName = user.getName();
}
return new FamilyTemperatureContributionResponse.Contribution(
t.getCreatedAt(),
userName,
Expand All @@ -156,8 +164,8 @@ public FamilyTemperatureContributionResponse getFamilyTemperatureContributions(S

// 활동별 reason 상수 정의
private static final String REASON_EMOTION_UPLOAD = "EMOTION_UPLOAD";
private static final String REASON_ALL_EMOTION_UPLOAD = "ALL_EMOTION_UPLOAD";
private static final String REASON_STEP_GOAL = "STEP_GOAL";
private static final String REASON_ALL_EMOTION_UPLOAD = "ALL_FAMILY_EMOTION_UPLOAD";
private static final String REASON_STEP_GOAL = "FAMILY_STEP_GOAL";
private static final String REASON_PARENT_PAIN_INPUT = "PARENT_PAIN_INPUT";
private static final String REASON_PARENT_MED_INPUT = "PARENT_MED_INPUT";
private static final String REASON_PARENT_EXERCISE_INPUT = "PARENT_EXERCISE_INPUT";
Expand Down Expand Up @@ -271,7 +279,7 @@ public void increaseTemperatureForChildExerciseView(UUID userId, String familyId


// 매일 23:59:59에 당일의 가족별 보너스 온도 상승 처리
@Scheduled(cron = "59 59 23 * * *")
@Scheduled(cron = "59 37 15 * * *")
@Transactional
public void processFamilyBonusTemperature() {
var families = familyRepository.findAll();
Expand All @@ -286,13 +294,13 @@ public void processFamilyBonusTemperature() {
// 모든 구성원이 감정기록 업로드 시 보너스 지급
private void processEmotionBonus(ongi.family.entity.Family family, String familyId, LocalDate targetDate) {
var memberIds = family.getMembers();
boolean alreadyEmotionBonus = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(null, familyId, REASON_ALL_EMOTION_UPLOAD, targetDate);
boolean alreadyEmotionBonus = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(FAMILY_WIDE_USER_ID, familyId, REASON_ALL_EMOTION_UPLOAD, targetDate);
boolean allEmotionUploaded = memberIds.stream().allMatch(
userId -> temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(userId, familyId, REASON_EMOTION_UPLOAD, targetDate)
);
if (allEmotionUploaded && !alreadyEmotionBonus) {
Temperature temp = Temperature.builder()
.userId(null)
.userId(FAMILY_WIDE_USER_ID)
.familyId(familyId)
.temperature(0.1)
.reason(REASON_ALL_EMOTION_UPLOAD)
Expand All @@ -310,11 +318,11 @@ private void processStepGoalBonus(ongi.family.entity.Family family, String famil
int goal = (int)(parentCount * 7000 + childCount * 10000);
List<Step> steps = stepRepository.findByFamilyAndDate(family, targetDate);
int totalSteps = steps.stream().mapToInt(Step::getSteps).sum();
boolean alreadyStepBonus = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(null, familyId, REASON_STEP_GOAL, targetDate);
boolean alreadyStepBonus = temperatureRepository.existsByUserIdAndFamilyIdAndReasonAndDate(FAMILY_WIDE_USER_ID, familyId, REASON_STEP_GOAL, targetDate);
boolean stepGoalMet = totalSteps >= goal;
if (stepGoalMet && !alreadyStepBonus) {
Temperature temp = Temperature.builder()
.userId(null)
.userId(FAMILY_WIDE_USER_ID)
.familyId(familyId)
.temperature(0.2)
.reason(REASON_STEP_GOAL)
Expand All @@ -324,26 +332,24 @@ private void processStepGoalBonus(ongi.family.entity.Family family, String famil
}


// 매주 일요일 23:59:59 에 만보기 경쟁 결과 보너스 온도 상승 처리 (후순위! 일단 안만들어도 됨)
// 매주 일요일 23:59:59 에 만보기 가족 경쟁 결과 보너스 온도 상승 처리 (후순위! 일단 안만들어도 됨)
// TODO: 만보기 전체 경쟁 상위 10% -> +3도
// TODO: 만보기 전체 경쟁 상위 20% -> +1도



// 매일 23:59:59에 당일의 가족별 온도 하락 처리
@Scheduled(cron = "59 59 23 * * *")
//// 매주 일요일 23:59:59에 일주일 미접속 온도 하락 처리
@Scheduled(cron = "59 59 23 * * 0")
@Transactional
public void processFamilyTemperatureDecrease() {
public void processWeeklyTemperatureDecrease() {
var families = familyRepository.findAll();
for (var family : families) {
String familyId = family.getCode();
decreaseTemperatureForInactiveParent(familyId);
decreaseTemperatureForInactiveChild(familyId);
decreaseTemperatureForNoLogin(familyId);
}
}

// 부모 1명 이상 일주일 동안안 아무 활동 없을 시 온도 하락
// 부모 1명 이상 일주일 동안 아무 활동 없을 시 온도 하락
public void decreaseTemperatureForInactiveParent(String familyId) {

List<UUID> memberIds = familyRepository.findById(familyId).get().getMembers();
Expand All @@ -357,15 +363,14 @@ public void decreaseTemperatureForInactiveParent(String familyId) {

if (parentInactive) {
Temperature temp = Temperature.builder()
.userId(null)
.userId(FAMILY_WIDE_USER_ID)
.familyId(familyId)
.temperature(-10.0)
.reason("INACTIVE_PARENT")
.reason("INACTIVE_PARENT_7DAY")
.build();
temperatureRepository.save(temp);
}
}

// 자녀 1명 이상 일주일 동안 아무 활동 없을 시 온도 하락
public void decreaseTemperatureForInactiveChild(String familyId) {

Expand All @@ -379,26 +384,38 @@ public void decreaseTemperatureForInactiveChild(String familyId) {
.anyMatch(child -> !temperatureRepository.existsByUserIdAndFamilyIdAndCreatedAtAfter(child.getUuid(), familyId, since));
if (childInactive) {
Temperature temp = Temperature.builder()
.userId(null)
.userId(FAMILY_WIDE_USER_ID)
.familyId(familyId)
.temperature(-10.0)
.reason("INACTIVE_CHILD")
.reason("INACTIVE_CHILD_7DAY")
.build();
temperatureRepository.save(temp);
}
}

// 하루 동안 아무도 활동 없을 시 시 온도 하락

//// 매일 23:59:59에 하루 미접속 온도 하락 처리
@Scheduled(cron = "59 59 23 * * *")
@Transactional
public void processDailyTemperatureDecrease() {
var families = familyRepository.findAll();
for (var family : families) {
String familyId = family.getCode();
decreaseTemperatureForNoLogin(familyId);
}
}
// 하루 동안 아무도 활동 없을 시 온도 하락
public void decreaseTemperatureForNoLogin(String familyId) {

LocalDateTime since = LocalDate.now().atStartOfDay(); // 오늘 00:00~
// 만보기(STEP_GOAL)를 제외한 가족 전체 활동 체크
boolean noLogin = !temperatureRepository.existsByFamilyIdAndCreatedAtAfter(familyId, since);
if (noLogin) {
Temperature temp = Temperature.builder()
.userId(null)
.userId(FAMILY_WIDE_USER_ID)
.familyId(familyId)
.temperature(-0.5)
.reason("NO_LOGIN")
.reason("INACTIVE_ALL_FAMILY_TODAY")
.build();
temperatureRepository.save(temp);
}
Expand Down
Loading