Add fan group entry on live room; update planet matching with 4 type buttons. Co-authored-by: undefined <undefined+undefined@users.noreply.github.com>
134 lines
4.1 KiB
TypeScript
134 lines
4.1 KiB
TypeScript
import { GAME_DATA } from "@/lib/data/game-data"
|
|
|
|
export type EvaluationInput = {
|
|
gameName: string
|
|
serverType: string // "热门服" | "普通服" | "鬼服"
|
|
currentLevel: number
|
|
maxLevel: number
|
|
rankName: string
|
|
|
|
// Assets
|
|
assetCounts: {
|
|
legendary: number // 传说级
|
|
epic: number // 史诗级
|
|
rare: number // 优质级
|
|
common: number // 普通级
|
|
}
|
|
|
|
// Bonus
|
|
registrationMonths: number
|
|
rechargeAmount6Months: number
|
|
mallConsumption?: number // Added mall consumption parameter
|
|
|
|
// Risk
|
|
isRealNameVerified: boolean
|
|
isRealNameOwner: boolean
|
|
hasBanRecord: boolean
|
|
}
|
|
|
|
export type EvaluationResult = {
|
|
totalScore: number
|
|
valuation: number // Preliminary valuation
|
|
loanAmount: number // Loan amount
|
|
details: {
|
|
baseScore: number
|
|
assetScore: number
|
|
bonusScore: number
|
|
riskCoefficient: number
|
|
consumptionMultiplier: number // Added consumption multiplier to result
|
|
}
|
|
}
|
|
|
|
export function evaluateAccount(input: EvaluationInput): EvaluationResult {
|
|
const gameConfig = GAME_DATA.games[input.gameName] || { score: 20, ranks: {} }
|
|
|
|
// 1. Base Value Score (Max 50)
|
|
// Game Score (Max 30)
|
|
const gameScore = gameConfig.score
|
|
|
|
// Server Score (Max 10)
|
|
const serverScore = GAME_DATA.server_scores[input.serverType] || 8
|
|
|
|
// Level Score (Max 10)
|
|
// Score = (Current / Max) * 10
|
|
const levelRatio = Math.min(input.currentLevel / (input.maxLevel || 100), 1)
|
|
const levelScore = Number.parseFloat((levelRatio * 10).toFixed(1))
|
|
|
|
const baseScore = gameScore + serverScore + levelScore
|
|
|
|
// 2. Core Asset Score (Max 30)
|
|
// Asset Score = Sum(Count * Weight)
|
|
// Cap count at 20 to avoid outliers as per requirements
|
|
const getAssetScore = (count: number, weight: number) => Math.min(count, 20) * weight
|
|
|
|
const assetBaseScore =
|
|
getAssetScore(input.assetCounts.legendary, GAME_DATA.asset_weights["传说级"]) +
|
|
getAssetScore(input.assetCounts.epic, GAME_DATA.asset_weights["史诗级"]) +
|
|
getAssetScore(input.assetCounts.rare, GAME_DATA.asset_weights["优质级"]) +
|
|
getAssetScore(input.assetCounts.common, GAME_DATA.asset_weights["普通级"])
|
|
|
|
// Rank Bonus
|
|
const rankBonus = gameConfig.ranks ? gameConfig.ranks[input.rankName] || 0 : 0
|
|
|
|
const coreAssetScore = Math.min(assetBaseScore + rankBonus, 30)
|
|
|
|
// 3. Bonus Score (Max 20)
|
|
let timeScore = 0
|
|
if (input.registrationMonths >= 25) timeScore = 10
|
|
else if (input.registrationMonths >= 13) timeScore = 8
|
|
else if (input.registrationMonths >= 7) timeScore = 5
|
|
else timeScore = 3
|
|
|
|
// Recharge Amount (Max 10)
|
|
// Score = min(Amount * 0.001, 10)
|
|
const rechargeScore = Math.min(input.rechargeAmount6Months * 0.001, 10)
|
|
|
|
const bonusScore = timeScore + rechargeScore
|
|
|
|
// 4. Risk Correction Coefficient
|
|
let riskKey = "未实名"
|
|
if (input.isRealNameVerified) {
|
|
if (input.isRealNameOwner) {
|
|
riskKey = input.hasBanRecord ? "本人_有封号" : "本人_无封号"
|
|
} else {
|
|
riskKey = input.hasBanRecord ? "非本人_有封号" : "非本人_无封号"
|
|
}
|
|
}
|
|
|
|
const riskCoefficient = GAME_DATA.correction_coeffs[riskKey] || 0.7
|
|
|
|
let consumptionMultiplier = 1.0
|
|
const consumption = input.mallConsumption || 0
|
|
if (consumption >= 2000) {
|
|
consumptionMultiplier = GAME_DATA.consumption_weights.level4
|
|
} else if (consumption >= 500) {
|
|
consumptionMultiplier = GAME_DATA.consumption_weights.level3
|
|
} else if (consumption >= 100) {
|
|
consumptionMultiplier = GAME_DATA.consumption_weights.level2
|
|
} else {
|
|
consumptionMultiplier = 1.0
|
|
}
|
|
|
|
// Final Calculation
|
|
const totalScore = Number.parseFloat(((baseScore + coreAssetScore + bonusScore) * riskCoefficient).toFixed(2))
|
|
const valuation = Math.floor(totalScore * GAME_DATA.base_multiple)
|
|
|
|
let loanAmount = Math.floor(valuation * 0.6 * consumptionMultiplier)
|
|
if (loanAmount < 500) {
|
|
loanAmount = 0
|
|
}
|
|
|
|
return {
|
|
totalScore,
|
|
valuation,
|
|
loanAmount,
|
|
details: {
|
|
baseScore: Number.parseFloat(baseScore.toFixed(1)),
|
|
assetScore: Number.parseFloat(coreAssetScore.toFixed(1)),
|
|
bonusScore: Number.parseFloat(bonusScore.toFixed(1)),
|
|
riskCoefficient,
|
|
consumptionMultiplier, // Return multiplier for UI display
|
|
},
|
|
}
|
|
}
|