|
@@ -83,13 +83,13 @@ export function collectWeights(
|
|
|
return out
|
|
return out
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/** Build ascending-sorted unique values for percentile lookup. */
|
|
|
|
|
|
|
+/** Build ascending-sorted values for percentile / min-max lookup in this tab. */
|
|
|
export function buildWeightScale(values: number[]): number[] {
|
|
export function buildWeightScale(values: number[]): number[] {
|
|
|
if (!values.length) return []
|
|
if (!values.length) return []
|
|
|
return values.slice().sort((a, b) => a - b)
|
|
return values.slice().sort((a, b) => a - b)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/** Percentile of avg among nodes with data; null when no scale. */
|
|
|
|
|
|
|
+/** Percentile heat t in [0, 1] among nodes with data in this tab. */
|
|
|
export function weightHeatT(weight: number, sortedScale: number[]): number | null {
|
|
export function weightHeatT(weight: number, sortedScale: number[]): number | null {
|
|
|
if (!sortedScale.length) return null
|
|
if (!sortedScale.length) return null
|
|
|
const n = sortedScale.length
|
|
const n = sortedScale.length
|
|
@@ -104,14 +104,23 @@ export function weightHeatT(weight: number, sortedScale: number[]): number | nul
|
|
|
return Math.min(1, Math.max(0, lo / n))
|
|
return Math.min(1, Math.max(0, lo / n))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/** Global score is the sum of four [0, 1] rank scores, so its fixed range is [0, 4]. */
|
|
|
|
|
|
|
+/** Linear heat t in [0, 1]: min→0, max→1 (used by 全局热度 tab). */
|
|
|
|
|
+export function weightHeatTLinear(weight: number, sortedScale: number[]): number | null {
|
|
|
|
|
+ if (!sortedScale.length) return null
|
|
|
|
|
+ const min = sortedScale[0]
|
|
|
|
|
+ const max = sortedScale[sortedScale.length - 1]
|
|
|
|
|
+ if (max === min) return 0.5
|
|
|
|
|
+ return Math.min(1, Math.max(0, (weight - min) / (max - min)))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** Heat t for the active dim; scale is built per tab. */
|
|
|
export function scoreHeatT(
|
|
export function scoreHeatT(
|
|
|
dim: WeightDimKey,
|
|
dim: WeightDimKey,
|
|
|
weight: number,
|
|
weight: number,
|
|
|
sortedScale: number[],
|
|
sortedScale: number[],
|
|
|
): number | null {
|
|
): number | null {
|
|
|
if (dim === 'total_score') {
|
|
if (dim === 'total_score') {
|
|
|
- return Math.min(1, Math.max(0, weight / 4))
|
|
|
|
|
|
|
+ return weightHeatTLinear(weight, sortedScale)
|
|
|
}
|
|
}
|
|
|
return weightHeatT(weight, sortedScale)
|
|
return weightHeatT(weight, sortedScale)
|
|
|
}
|
|
}
|