From d1f0ef6dfec851a78d3e42a71595144834faace3 Mon Sep 17 00:00:00 2001 From: junlu592 Date: Sun, 14 Dec 2025 10:56:04 +0100 Subject: [PATCH] suggested changes to minimize difference from main --- ts/routes/graphs/reviews.ts | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/ts/routes/graphs/reviews.ts b/ts/routes/graphs/reviews.ts index d66496687..b33232b25 100644 --- a/ts/routes/graphs/reviews.ts +++ b/ts/routes/graphs/reviews.ts @@ -108,36 +108,32 @@ export function renderReviews( break; } const desiredBars = Math.min(70, Math.abs(xMin!)); - const shouldCapRange = range !== GraphRange.AllTime; + const unboundRange = range == GraphRange.AllTime; const originalXMin = xMin!; // Create initial scale to determine tick spacing let x = scaleLinear().domain([xMin!, xMax]); - // Generate thresholds: these define where bins are split (e.g., [-5, -10, -15, ...]) - // D3's bin() will create bins between consecutive thresholds: [threshold[i], threshold[i+1]) let thresholds = x.ticks(desiredBars); - // Adjust xMin to align with tick spacing so the oldest bin has the same width as others - if (thresholds.length >= 2) { + // For unbound ranges, extend xMin backward so that the oldest bin has the same width as others + if (unboundRange && thresholds.length >= 2) { const spacing = thresholds[1] - thresholds[0]; const partial = thresholds[0] - xMin!; if (spacing > 0 && partial > 0 && partial < spacing) { - // Extend xMin backward to align with tick spacing, but cap at originalXMin for fixed ranges - xMin = Math.max(thresholds[0] - spacing, shouldCapRange ? originalXMin! : -Infinity); + xMin = thresholds[0] - spacing; x = scaleLinear().domain([xMin, xMax]); thresholds = x.ticks(desiredBars); } } - // For Year, shift thresholds forward by one day to make first bin 0-4 instead of 0-5 + // For Year & All Time, shift thresholds forward by one day to make first bin 0-4 instead of 0-5 if (range === GraphRange.Year || range === GraphRange.AllTime) { thresholds = [...new Set(thresholds.map(t => Math.min(t + 1, 1)))].sort((a, b) => a - b); } const sourceMap = showTime ? sourceData.reviewTime : sourceData.reviewCount; - // Create bins using the thresholds: each bin contains data points between consecutive thresholds const bins = bin() - .value((m) => m[0]) // Extract the day number from each map entry [day, data] - .domain(x.domain() as any) // Bins are constrained to this domain [xMin, xMax] - .thresholds(thresholds)(sourceMap.entries() as any); // Use computed thresholds to split data into bins + .value((m) => m[0]) + .domain(x.domain() as any) + .thresholds(thresholds)(sourceMap.entries() as any); // empty graph? const totalDays = sum(bins, (bin) => bin.length); @@ -232,9 +228,7 @@ export function renderReviews( // If bin ends at 0, treat it as crossing zero so day 0 is included // For the first (oldest) bin, use the original xMin to ensure labels match the intended range const isFirstBin = bins.length > 0 && d.x0 === bins[0].x0; - const startDay = isFirstBin - ? originalXMin - : Math.floor(d.x0!); + const startDay = isFirstBin ? originalXMin : Math.floor(d.x0!); const endDay = d.x1! === 0 ? 1 : d.x1!; const day = dayLabel(startDay, endDay); const totals = totalsForBin(d); @@ -351,10 +345,9 @@ export function renderReviews( }) .on("mouseout", hideTooltip); - // Calculate periodDays from the actual data range, not the adjusted xMin - // For AllTime, xMin might be extended for bin alignment, so use the original xMin (actual oldest data) - // For fixed ranges, use the original xMin before adjustment (which matches the displayed range) - const periodDays = -originalXMin + 1; + // The xMin might be extended for bin alignment, so use the original xMin + const actualXMin = originalXMin; + const periodDays = -actualXMin + 1; const studiedDays = sum(bins, (bin) => bin.length); const studiedPercent = (studiedDays / periodDays) * 100; const total = yCumMax;