feat: improve recommendation diversity and KRW rounding

- Add spec diversity: recommend Budget/Balanced/Premium tiers instead of same spec
- Add bandwidth-based filtering: prioritize servers with adequate transfer allowance
- Fix KRW rounding: server price 500원, TB cost 500원, GB cost 1원
- Add bandwidth warning to infrastructure_tips when traffic exceeds 2x included

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-27 14:44:34 +09:00
parent 23abd0e64e
commit 8c543eeaa5
4 changed files with 116 additions and 32 deletions

View File

@@ -348,14 +348,15 @@ export function calculateBandwidthInfo(
const isKorean = lang === 'ko';
const currency: 'USD' | 'KRW' = isKorean ? 'KRW' : 'USD';
// KRW: GB당 1원 단위, TB당/총 비용 100원 단위 반올림
const roundKrw100 = (usd: number) => Math.round((usd * exchangeRate) / 100) * 100;
const toKrw = (usd: number) => Math.round(usd * exchangeRate);
// KRW 반올림: GB당 1원, TB당 500원, 총 비용 1
const toKrw = (usd: number) => Math.round(usd * exchangeRate); // 1원 단위
const toKrw500 = (usd: number) => Math.round((usd * exchangeRate) / 500) * 500; // 500원 단위
const overagePerGb = isKorean ? toKrw(overagePerGbUsd) : overagePerGbUsd;
const overagePerTb = isKorean ? roundKrw100(overagePerTbUsd) : overagePerTbUsd;
const overageCost = isKorean ? roundKrw100(overageCostUsd) : Math.round(overageCostUsd * 100) / 100;
const totalCost = isKorean ? roundKrw100(totalCostUsd) : Math.round(totalCostUsd * 100) / 100;
const overagePerTb = isKorean ? toKrw500(overagePerTbUsd) : overagePerTbUsd; // 500원 단위
const overageCost = isKorean ? toKrw500(overageCostUsd) : overageCostUsd; // 500원 단위
// totalCost: 서버 가격(500원) + 초과 비용(500원)
const totalCost = isKorean ? server.monthly_price + toKrw500(overageCostUsd) : totalCostUsd;
// CDN savings calculation
const cdnEnabled = bandwidthEstimate.cdn_enabled;
@@ -363,7 +364,7 @@ export function calculateBandwidthInfo(
const grossMonthlyTb = bandwidthEstimate.gross_monthly_tb;
const cdnSavingsTb = cdnEnabled ? grossMonthlyTb - estimatedTb : 0;
const cdnSavingsCostUsd = cdnSavingsTb * overagePerTbUsd;
const cdnSavingsCost = isKorean ? roundKrw100(cdnSavingsCostUsd) : Math.round(cdnSavingsCostUsd * 100) / 100;
const cdnSavingsCost = isKorean ? toKrw500(cdnSavingsCostUsd) : cdnSavingsCostUsd; // 500원 단위
let warning: string | undefined;
if (overageTb > includedTb) {
@@ -380,12 +381,12 @@ export function calculateBandwidthInfo(
return {
included_transfer_tb: includedTb,
overage_cost_per_gb: isKorean ? Math.round(overagePerGb) : Math.round(overagePerGb * 10000) / 10000,
overage_cost_per_tb: isKorean ? Math.round(overagePerTb) : Math.round(overagePerTb * 100) / 100,
overage_cost_per_gb: overagePerGb, // 반올림 없음
overage_cost_per_tb: overagePerTb, // 반올림 없음
estimated_monthly_tb: Math.round(estimatedTb * 10) / 10,
estimated_overage_tb: Math.round(overageTb * 10) / 10,
estimated_overage_cost: overageCost,
total_estimated_cost: totalCost,
estimated_overage_cost: overageCost, // 반올림 없음
total_estimated_cost: totalCost, // 서버 가격(반올림) + 초과 비용(반올림 X)
currency,
warning,
// CDN breakdown
@@ -393,6 +394,6 @@ export function calculateBandwidthInfo(
cdn_cache_hit_rate: cdnCacheHitRate,
gross_monthly_tb: Math.round(grossMonthlyTb * 10) / 10,
cdn_savings_tb: Math.round(cdnSavingsTb * 10) / 10,
cdn_savings_cost: cdnSavingsCost
cdn_savings_cost: cdnSavingsCost // 반올림 없음
};
}