From d7c466e9075f278045a4d21b6886f1bb74b4ccce Mon Sep 17 00:00:00 2001 From: Brendan Heywood Date: Fri, 5 Jun 2026 18:44:20 +1000 Subject: [PATCH] Cleanup page group charts into load adjusted flame charts --- lang/en/tool_excimer.php | 1 + page_group.php | 50 +++++++++++++++++++++++++++++++---- templates/page_group.mustache | 6 +++-- version.php | 4 +-- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/lang/en/tool_excimer.php b/lang/en/tool_excimer.php index 0b778be..b8e718c 100644 --- a/lang/en/tool_excimer.php +++ b/lang/en/tool_excimer.php @@ -79,6 +79,7 @@ $string['field_finished'] = 'Finished'; $string['field_fuzzycount'] = 'Approx. count'; $string['field_fuzzydurationcounts'] = 'Histogram'; +$string['field_estimatedduration'] = 'Est. duration (s)'; $string['field_fuzzydurationsum'] = 'Approx. total duration (s)'; $string['field_hostname'] = 'Host name'; $string['field_id'] = 'ID'; diff --git a/page_group.php b/page_group.php index 05dd74f..d4fc99a 100644 --- a/page_group.php +++ b/page_group.php @@ -23,7 +23,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -use core\chart_line; +use core\chart_bar; use core\chart_series; use tool_excimer\helper; use tool_excimer\monthint; @@ -57,6 +57,11 @@ $data->approxcount = pow(2, $data->fuzzycount - 1) . ' - ' . pow(2, $data->fuzzycount); $data->approxduration = pow(2, $data->fuzzydurationsum); $data->histogram = helper::make_histogram($data); +// Add estimated duration (count × upper bound) to each histogram row. +foreach ($data->histogram as &$row) { + $row['duration'] = $row['value'] * $row['high']; +} +unset($row); // Data for charts. // Each duration range forms its own line on the chart. @@ -101,21 +106,56 @@ for ($rangeindex = 0; $rangeindex < $highest; ++$rangeindex) { $value = 0; if (isset($histograms[$month][$rangeindex])) { - $value = $histograms[$month][$rangeindex]['value']; - $linelabels[$rangeindex] = get_string('fuzzydurationrange', 'tool_excimer', $histograms[$month][$rangeindex]); + $entry = $histograms[$month][$rangeindex]; + // Weight count by upper bound of duration range to represent total seconds. + $value = $entry['value'] * $entry['high']; + $linelabels[$rangeindex] = get_string('fuzzydurationrange', 'tool_excimer', $entry); } $durationseries[$rangeindex][] = $value; } $month = monthint::increment_month($month); } -$chart = new chart_line(); +$chart = new chart_bar(); +$chart->set_stacked(true); $chart->set_labels($labels); +// Colour stops from green to yellow to orange to red to purple. +$colorstops = [ + [0x2ecc71, 0], // Green. + [0xf1c40f, 25], // Yellow. + [0xe67e22, 50], // Orange. + [0xe74c3c, 75], // Red. + [0x8e44ad, 100], // Purple. +]; + +// Interpolate a hex colour along the defined stops given a 0-100 position. +$interpolatecolor = function (float $pct) use ($colorstops): string { + for ($i = 0; $i < count($colorstops) - 1; $i++) { + [$cola, $posa] = $colorstops[$i]; + [$colb, $posb] = $colorstops[$i + 1]; + if ($pct <= $posb) { + $t = ($posb === $posa) ? 0 : ($pct - $posa) / ($posb - $posa); + $r = (int) round((($cola >> 16) & 0xff) * (1 - $t) + (($colb >> 16) & 0xff) * $t); + $g = (int) round((($cola >> 8) & 0xff) * (1 - $t) + (($colb >> 8) & 0xff) * $t); + $b = (int) round(($cola & 0xff) * (1 - $t) + ($colb & 0xff) * $t); + return sprintf('#%02x%02x%02x', $r, $g, $b); + } + } + [$lastcol] = end($colorstops); + return sprintf('#%02x%02x%02x', ($lastcol >> 16) & 0xff, ($lastcol >> 8) & 0xff, $lastcol & 0xff); +}; + // Add each duration range to the chart, but only those that have non-zero counts. foreach ($durationseries as $idx => $series) { if (max($series) != 0) { - $chart->add_series(new chart_series($linelabels[$idx], $series)); + // Map colour by log base 16 of duration: each factor of 16 = one colour stop. + // idx is the duration exponent (high = 2^idx), so 4 idx steps = factor of 16. + // Colour stops: idx 0 = green, 4 = yellow, 8 = orange, 12 = red, 16+ = purple. + $pct = min(100.0, $idx * 100.0 / 16.0); + $s = new chart_series($linelabels[$idx], $series); + $s->set_color($interpolatecolor($pct)); + $chart->add_series($s); } } diff --git a/templates/page_group.mustache b/templates/page_group.mustache index 63925d9..b3350f8 100644 --- a/templates/page_group.mustache +++ b/templates/page_group.mustache @@ -49,7 +49,7 @@
- +
@@ -65,15 +65,17 @@
{{#str}}field_month, tool_excimer{{/str}} {{month}}
- +
+ {{#histogram}} + {{/histogram}}
{{#str}}field_fuzzydurationcounts, tool_excimer{{/str}} {{#str}}field_estimatedduration, tool_excimer{{/str}}
{{low}} - {{high}}s {{value}}{{duration}}s
diff --git a/version.php b/version.php index a20831f..e82db44 100644 --- a/version.php +++ b/version.php @@ -25,8 +25,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2026031703; -$plugin->release = 2026031703; +$plugin->version = 2026031704; +$plugin->release = 2026031704; $plugin->requires = 2023100900; // Moodle 4.3. $plugin->supported = [403, 405]; $plugin->component = 'tool_excimer';