Show full Gaussian probability tooltip
This commit is contained in:
@@ -77,8 +77,8 @@ export function TemperatureTooltipContent({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{probabilityRows.length > 0 && (
|
{probabilityRows.length > 0 && (
|
||||||
<div className={rows.length > 0 ? "mt-1.5 grid gap-1 border-t border-slate-100 pt-1.5" : "grid gap-1"}>
|
<div className={rows.length > 0 ? "mt-1.5 grid max-h-[260px] gap-1 overflow-y-auto border-t border-slate-100 pt-1.5 pr-1" : "grid max-h-[260px] gap-1 overflow-y-auto pr-1"}>
|
||||||
{probabilityRows.slice(0, 8).map((item) => (
|
{probabilityRows.map((item) => (
|
||||||
<div key={item.key} className="flex min-w-[160px] items-center justify-between gap-4">
|
<div key={item.key} className="flex min-w-[160px] items-center justify-between gap-4">
|
||||||
<span className="inline-flex items-center gap-1.5 text-violet-700">
|
<span className="inline-flex items-center gap-1.5 text-violet-700">
|
||||||
<span className="h-2 w-2 rounded-full" style={{ backgroundColor: item.color }} />
|
<span className="h-2 w-2 rounded-full" style={{ backgroundColor: item.color }} />
|
||||||
@@ -118,6 +118,18 @@ function buildTooltipRows(
|
|||||||
.filter((item): item is TooltipRow => item !== null);
|
.filter((item): item is TooltipRow => item !== null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatProbabilityRangeValue(value: number) {
|
||||||
|
return Number(value.toFixed(1)).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatProbabilityRangeLabel(
|
||||||
|
lower: number,
|
||||||
|
upper: number,
|
||||||
|
tempSymbol: string,
|
||||||
|
) {
|
||||||
|
return `${formatProbabilityRangeValue(lower)}-${formatProbabilityRangeValue(upper)}${tempSymbol}`;
|
||||||
|
}
|
||||||
|
|
||||||
function buildTooltipProbabilityRows(
|
function buildTooltipProbabilityRows(
|
||||||
probabilityOverlay: ProbabilityOverlay | null | undefined,
|
probabilityOverlay: ProbabilityOverlay | null | undefined,
|
||||||
tempSymbol: string,
|
tempSymbol: string,
|
||||||
@@ -135,18 +147,20 @@ function buildTooltipProbabilityRows(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const topBand = [...probabilityOverlay.bands]
|
rows.push(
|
||||||
.filter((band) => validNumber(band.probability) !== null)
|
...[...probabilityOverlay.bands]
|
||||||
.sort((a, b) => b.probability - a.probability)[0];
|
.filter((band) => validNumber(band.probability) !== null && band.probability > 0)
|
||||||
if (topBand) {
|
.sort((a, b) => a.lower - b.lower)
|
||||||
const probabilityPct = Math.round(topBand.probability * 100);
|
.map((band) => {
|
||||||
rows.push({
|
const probabilityPct = Math.round(band.probability * 100);
|
||||||
key: topBand.key,
|
return {
|
||||||
label: topBand.label,
|
key: band.key,
|
||||||
value: `${probabilityPct}%`,
|
label: formatProbabilityRangeLabel(band.lower, band.upper, tempSymbol),
|
||||||
color: "#a78bfa",
|
value: `${probabilityPct}%`,
|
||||||
});
|
color: "#a78bfa",
|
||||||
}
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+24
-4
@@ -61,6 +61,15 @@ export function runTests() {
|
|||||||
engine: "legacy",
|
engine: "legacy",
|
||||||
muLine: { value: 27.4, label: "Gaussian μ 27.4°C" },
|
muLine: { value: 27.4, label: "Gaussian μ 27.4°C" },
|
||||||
bands: [
|
bands: [
|
||||||
|
{
|
||||||
|
key: "legacy_probability_26_0",
|
||||||
|
value: 26,
|
||||||
|
lower: 25.5,
|
||||||
|
upper: 26.5,
|
||||||
|
probability: 0.18,
|
||||||
|
label: "26°C 18%",
|
||||||
|
opacity: 0.08,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: "legacy_probability_27_0",
|
key: "legacy_probability_27_0",
|
||||||
value: 27,
|
value: 27,
|
||||||
@@ -70,6 +79,15 @@ export function runTests() {
|
|||||||
label: "27°C 42%",
|
label: "27°C 42%",
|
||||||
opacity: 0.13,
|
opacity: 0.13,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "legacy_probability_28_0",
|
||||||
|
value: 28,
|
||||||
|
lower: 27.5,
|
||||||
|
upper: 28.5,
|
||||||
|
probability: 0.31,
|
||||||
|
label: "28°C 31%",
|
||||||
|
opacity: 0.11,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"°C",
|
"°C",
|
||||||
@@ -77,13 +95,15 @@ export function runTests() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
probabilityRows.length === 2,
|
probabilityRows.length === 4,
|
||||||
"temperature tooltip should show Gaussian μ and the leading probability bucket as compact context",
|
"temperature tooltip should show Gaussian μ and every available probability bucket as compact context",
|
||||||
);
|
);
|
||||||
assert(
|
assert(
|
||||||
probabilityRows.some((row) => row.key === "legacy_probability_mu" && row.value === "27.4°C") &&
|
probabilityRows.some((row) => row.key === "legacy_probability_mu" && row.value === "27.4°C") &&
|
||||||
probabilityRows.some((row) => row.key === "legacy_probability_27_0" && row.value === "42%"),
|
probabilityRows.some((row) => row.key === "legacy_probability_26_0" && row.label === "25.5-26.5°C" && row.value === "18%") &&
|
||||||
"temperature tooltip should format Gaussian μ and probability values without drawing a full probability band on the main chart",
|
probabilityRows.some((row) => row.key === "legacy_probability_27_0" && row.label === "26.5-27.5°C" && row.value === "42%") &&
|
||||||
|
probabilityRows.some((row) => row.key === "legacy_probability_28_0" && row.label === "27.5-28.5°C" && row.value === "31%"),
|
||||||
|
"temperature tooltip should format the full Gaussian probability distribution by temperature range without drawing it on the main chart",
|
||||||
);
|
);
|
||||||
|
|
||||||
const projectRoot = process.cwd();
|
const projectRoot = process.cwd();
|
||||||
|
|||||||
Reference in New Issue
Block a user