Forum teuk.org

πŸ…πŸŽ¨ Mediabot v3 β€” The Great Hall Gets a Proper Scoreboard

in Mediabot Β· started by TeuK Β· 1w ago

TeuK Β· 1w ago

Development chronicle β€” mb629 to mb630 Β· Administrator-only leaderboard, compact IRC layout, dashboard colours and truthful dispatch tests

This round started with a simple usability request: make the leaderboard smaller, more readable and more colourful.

It ended up improving three separate contracts at once:

  • who is allowed to call the leaderboard;
  • how dense IRC statistics should be presented;
  • and whether a green dispatch test genuinely proves anything.

The visible result is a cleaner Great Hall.

The less visible result is just as important: an old test can no longer report success after its regular expression has actually failed.

No database schema change was required.


πŸ” mb629 β€” The leaderboard becomes an Administrator command

leaderboard and its alias lb are no longer unrestricted public commands.

Both now require:

Administrator

The permission gate is placed before the async worker starts.

Conceptually:

m lb
  |
  v
permission check
  |
  +-- denied --> parent replies immediately
  |
  +-- allowed
        |
        v
   CommandAsync
        |
        v
   leaderboard work

This matters because an unauthorized request should not consume a worker process merely to discover that it was unauthorized.

Both help entries advertise the requirement.


πŸ… The leaderboard stops covering the whole wall

The historical presentation used one line per category.

A normal response could therefore look like a small wall of statistics:

Leaderboard #channel
messages ...
karma ...
trivia ...
duels ...
achievements ...

The new default is compact.

A typical structure is closer to:

πŸ… Leaderboard #channel
  πŸ’¬ msgs ...   🌟 karma ...   🧠 trivia ...
  βš”οΈ duels ...  πŸ† achievs ...

Five categories are packed into roughly two useful IRC lines instead of five.

The goal is not maximal compression.

It is to keep the result readable without flooding the channel.


🎨 One visual identity per category

Each leaderboard category receives its own IRC colour.

The palette deliberately avoids pure white and black so it remains useful on both dark and light IRC themes.

The first place keeps the stronger podium treatment:

πŸ₯‡ + bold

while following entries stay deliberately calmer.

Too much decoration would defeat the point of making the block easier to read.


↔️ Compact is the default, full remains available

The old layout was not deleted.

Users with access can explicitly request it:

m lb full

To return to the normal compact presentation:

m lb compact

Existing category/window requests remain available, for example:

m lb karma 7d

The feature therefore gains a better default without removing the historical detailed view.


πŸ“ IRC width is measured in bytes, not wishful thinking

Compact rendering introduces a real protocol concern.

An IRC line is constrained by its byte size on the wire, not by the number of Perl characters displayed in the source.

That distinction matters for:

Γ©
Β·
πŸ†

A character can require multiple UTF-8 bytes.

The leaderboard now measures the actual UTF-8 wire size before deciding whether another category can fit on the current line.

Conceptually:

visible characters
       |
       v
UTF-8 byte count
       |
       +-- fits --> append category
       |
       +-- too large --> begin next IRC line

This reduces the risk of the IRC server truncating a line in the middle of a colour sequence or a multibyte character.


Β· A tiny separator exposed a real encoding mistake

During the visual work, the category separator was initially written as a literal-looking escape sequence inside single quotes.

Instead of producing:

Β·

IRC could receive the characters describing the escape itself.

Because the module already declares UTF-8 source, the correct solution is straightforward:

use the real middle-dot character

rather than pretending the source is an escape parser.

The regression test locks that distinction.


πŸ“Š Dashboard β€” colour without rewriting the content

The dashboard was already considered useful as-is.

So this round intentionally does not redesign it.

Its words, ordering and values stay unchanged.

Only colour is added to improve visual separation.

The test explicitly locks the six existing dashboard lines so that a later visual cleanup cannot accidentally rewrite or remove their content.

This is a useful design rule for mature IRC commands:

improve presentation
        β‰ 
silently change information

⚑ Async behaviour stays part of the command contract

An older regression test assumed that run_ctx_async had to be the very first operation inside the command dispatch block.

That stopped being true once the Administrator permission check was correctly moved before the worker.

The real contract is now expressed accurately:

permission gate may happen first
            |
            v
authorized execution still enters worker

The regression test was updated to care about the behaviour rather than the exact superficial shape of the source.


πŸ§ͺ mb630 β€” A green test must actually be green

The final pre-commit audit uncovered a much older Perl testing trap in:

383_dispatch_integrity.t

Several regular-expression checks were passed directly to ok().

In Perl, a failed match evaluated in list context can produce an empty list.

That means an expression conceptually like:

ok($text =~ /expected/, 'description');

can become dangerous depending on how the surrounding call receives its arguments.

When the match returned an empty list, the test description could slide into the first argument position.

A non-empty description is true.

The test could therefore print:

ok ... - unnamed test

even though the regular expression that was supposed to prove the dispatch mapping had failed.

That is not merely an ugly test name.

It is a false green.


πŸ” mb629 exposed the false positive

The old test expected the leaderboard dispatch to look roughly like:

leaderboard => sub { mbLeaderboard_ctx($ctx) }

But mb629 correctly changed the route to include:

Administrator gate
       +
CommandAsync
       +
mbLeaderboard_ctx

The historical regex should therefore have failed.

Instead, the test suite could still display success.

That contradiction is what revealed the old test bug.


βœ… Dispatch assertions now use scalar truth

mb630 makes the intention explicit.

Regular-expression assertions are evaluated as one boolean value rather than as a potentially empty list.

The updated dispatch checks also understand the current execution architecture.

Commands such as:

top
leaderboard
lb
chronos

may be wrapped in async infrastructure, but the test still requires them to reach the correct final handler.

The contract becomes:

wrapper may evolve
handler must remain correct
test failure must really fail

🧹 One dependency becomes explicit too

The same audit noticed that UserCommands.pm uses Encode for IRC byte-size handling while relying on another module to have loaded it first.

That transitive assumption is removed.

The module now declares the dependency it actually uses.

This does not change IRC behaviour; it makes the module safer to load and test independently.


πŸ§ͺ Regression map

The final commit is mainly protected by:

383  dispatch integrity β€” false-green bug removed
769  async career-command contract
812  mb629 leaderboard access, layout, byte width and dashboard colours

Test 812 covers, among other things:

  • both leaderboard and lb;
  • Administrator gating;
  • gate-before-worker ordering;
  • compact/default/full modes;
  • actual UTF-8 byte sizes;
  • bounded IRC lines;
  • distinct category colours;
  • the real middle-dot separator;
  • preserved dashboard content.

mb630 then makes sure the older dispatch test is capable of genuinely detecting a regression in those routes.


🏰 Final parchment

The Great Hall still has the same scores.

It simply no longer needs an entire wall to display them.

Only the people carrying the right key can open the leaderboard, every house has a readable colour, and the old full parchment remains available when someone wants every category on its own line.

But the most important repair happened behind the paintings.

The castle inspector used to stamp PASS even when he had failed to find the door he was checking.

Now, when the dispatch test says the passage exists, it has actually looked through it.

A smaller scoreboard is nice.

A test suite that tells the truth is better.

You must be logged in to reply.