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 @@
-
+
| {{#str}}field_month, tool_excimer{{/str}} |
{{month}} |
@@ -65,15 +65,17 @@
-
+
| {{#str}}field_fuzzydurationcounts, tool_excimer{{/str}} |
|
+ {{#str}}field_estimatedduration, tool_excimer{{/str}} |
{{#histogram}}
| {{low}} - {{high}}s |
{{value}} |
+ {{duration}}s |
{{/histogram}}
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';