Skip to content

Commit 15c211d

Browse files
committed
기온&자외선 알고리즘 수정
1 parent 80a28c3 commit 15c211d

2 files changed

Lines changed: 65 additions & 1 deletion

File tree

backend/src/domain/useCases/getRunningIndex.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,10 @@ function calculateScore(m: AirQualityMetrics, w?: WeatherInfo, hour?: number): n
9797
// 강수 강제 감점 (가중치와 별개로 적용)
9898
const precipBonus = precipitationForcePenalty(w.precipitation)
9999

100-
return Math.max(0, Math.min(100, Math.round(100 - compoundPenalty - precipBonus)))
100+
// UV-열 복합 강제 감점 (가중치와 별개로 적용)
101+
const uvHeatBonus = uvHeatForcePenalty(w.temperature, w.uvIndex, w.humidity, hour)
102+
103+
return Math.max(0, Math.min(100, Math.round(100 - compoundPenalty - precipBonus - uvHeatBonus)))
101104
}
102105

103106
/**
@@ -197,6 +200,33 @@ function uvPenalty(uv: number, hour?: number): number {
197200
return 100 // 11+
198201
}
199202

203+
/**
204+
* UV-열 복합 강제 감점.
205+
* UV가 높은(≥6) 날 기온이 20°C 이상이면 피부 온도 상승으로 체온 조절 부담이 커져
206+
* 체감 더위가 기온 수치 이상으로 올라간다.
207+
* 고습(>70%)이면 땀 증발이 억제돼 체온 조절이 더 어려워지므로 추가 증폭한다.
208+
* 가중치 시스템과 별개로 직접 차감해 체감을 반영한다.
209+
*
210+
* UV 등급(높음/매우높음/위험) × 20°C 초과분 선형 증가 × 습도 증폭(최대 1.5배).
211+
*/
212+
function uvHeatForcePenalty(temp: number, uvIndex?: number, humidity?: number, hour?: number): number {
213+
if (uvIndex == null || uvIndex < 6) return 0
214+
if (temp < 17) return 0
215+
// 야간에는 UV 없음
216+
if (hour !== undefined && (hour >= 20 || hour < 6)) return 0
217+
218+
// UV 심각도 단계: 높음(6~7)=1, 매우높음(8~10)=2, 위험(11+)=3
219+
const uvTier = uvIndex <= 7 ? 1 : uvIndex <= 10 ? 2 : 3
220+
// 17°C 초과분 (32°C 기준 최대 15°C 캡)
221+
const tempExcess = Math.min(temp - 17, 15)
222+
// 습도 증폭: 70% 초과 시 최대 1.5배 (70~100% → 1.0~1.5배)
223+
const humFactor = humidity != null && humidity > 70
224+
? 1 + Math.min((humidity - 70) / 60, 0.5)
225+
: 1.0
226+
227+
return Math.round(uvTier * tempExcess * 2.5 * humFactor)
228+
}
229+
200230
/** 비/눈이면 큰 감점 */
201231
function precipitationPenalty(precip: 'none' | 'rain' | 'snow' | 'sleet'): number {
202232
switch (precip) {

running-index-algorithm.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,40 @@ if (hour >= 20 || hour < 7) penalty = basePenalty × 0.3
148148
>
149149
> 데이터 출처: 기상청 생활기상지수 조회서비스 3.0 (`getUVIdxV4`), 매일 06시/18시 발표, `UV_API_KEY` 필요.
150150
151+
### UV-열·습 복합 강제 감점
152+
153+
UV가 높은 날 기온이 20°C 이상이면 피부 온도 상승으로 체온 조절 부담이 커져 체감 더위가 기온 수치 이상으로 올라간다. 여기에 고습(>70%)이 더해지면 땀 증발이 억제돼 체온 조절이 더욱 어려워지므로 최대 1.5배까지 추가 증폭한다. 가중치 시스템과 별개로 직접 차감해 체감을 반영한다.
154+
155+
발동 조건: **UV ≥ 6 AND 기온 ≥ 17°C AND 주간(06~20시)**
156+
157+
```
158+
uvTier = UV 6~7 → 1 / UV 8~10 → 2 / UV 11+ → 3
159+
tempExcess = min(기온 - 17, 15)
160+
humFactor = 습도 > 70% → 1 + min((습도 - 70) / 60, 0.5) [1.0 ~ 1.5배]
161+
= 습도 ≤ 70% → 1.0
162+
강제 감점 = round(uvTier × tempExcess × 2.5 × humFactor)
163+
```
164+
165+
**습도 70% 이하 (humFactor = 1.0)**
166+
167+
| UV 등급 | 22°C | 25°C | 28°C |
168+
|---|---|---|---|
169+
| 높음 (6~7) | 13점 | 20점 | 28점 |
170+
| 매우높음 (8~10) | 25점 | 40점 | 55점 |
171+
| 위험 (11+) | 38점 | 60점 | 83점 |
172+
173+
**습도 85% (humFactor = 1.25)**
174+
175+
| UV 등급 | 22°C | 25°C | 28°C |
176+
|---|---|---|---|
177+
| 높음 (6~7) | 16점 | 25점 | 34점 |
178+
| 매우높음 (8~10) | 31점 | 50점 | 69점 |
179+
| 위험 (11+) | 47점 | 75점 | 103점 |
180+
181+
> 강수 강제 감점과 마찬가지로 가중치 곱셈 이후 최종 점수에서 직접 차감합니다.
182+
> UV가 없거나(`uvIndex === undefined`) 기온 20°C 미만이면 0점입니다.
183+
> 습도 데이터가 없으면 humFactor = 1.0 (증폭 없음)으로 처리됩니다.
184+
151185
---
152186

153187
## 복합 악화 보정

0 commit comments

Comments
 (0)