The brief. The 2027 tower is on the live submission; the workbench below carries the same two layers with the premium function stubbed to 0. Implement Premium100 so every row and both derived totals go green — and read the tower while you do it: which layer carries more premium, the thick cheap one or the thin expensive one?

This is Lesson 1's core derivation: premium at 100% = rate on line × limit, per layer, summed across the tower. Nothing else. The battery also checks the blended rate on line — total premium over total limit — because that is the number the product's Economics area headlines.

The rules

  1. Premium100(layer) returns the layer's premium at 100% placement.
  2. Layer 1: 7m limit at 7.8% → must reach 546,000. Layer 2: 15m at 3.4% → 510,000.
  3. Total 1,056,000; blended rate on line 1,056,000 / 22,000,000 = 4.80%.

Your workbench

using MeshWeaver.Layout;
using MeshWeaver.Layout.Composition;
using MeshWeaver.Layout.DataGrid;
using MeshWeaver.Utils;

record Layer(string Name, double Attachment, double Limit, double RateOnLine);
record Row(string Layer, double Limit, double RateOnLine, double Premium100, double Expected, string Result);

// YOUR DERIVATION — the product computes premium at 100% as rate on line × limit.
static double Premium100(Layer l)
    => 0.0;   // TODO: derive the layer premium from its rate on line and limit.

// Alpina MTPL XL 2027 — the real tower off the submission node.
Layer[] tower =
[
    new("Layer 1 — 7m xs 3m",  3_000_000,  7_000_000, 0.078),
    new("Layer 2 — 15m xs 10m", 10_000_000, 15_000_000, 0.034),
];
double[] expected = [546_000, 510_000];

var rows = tower.Select((l, i) =>
{
    var p = Premium100(l);
    return new Row(l.Name, l.Limit, l.RateOnLine, p, expected[i], Math.Abs(p - expected[i]) < 0.5 ? "✓" : "✗");
}).ToArray();

var total = rows.Sum(r => r.Premium100);
var blended = tower.Sum(l => l.Limit) > 0 ? total / tower.Sum(l => l.Limit) : 0;
var totalOk = Math.Abs(total - 1_056_000) < 0.5;
var blendedOk = Math.Abs(blended - 0.048) < 1e-6;

Controls.Stack
    .WithView(Controls.H4($"Tower battery — {rows.Count(r => r.Result == "✓")}/{rows.Length} layers green"))
    .WithView(Controls.DataGrid(rows)
        .WithColumn(new PropertyColumnControl<string> { Property = nameof(Row.Layer).ToCamelCase() }.WithTitle("Layer"))
        .WithColumn(new PropertyColumnControl<double> { Property = nameof(Row.Limit).ToCamelCase() }.WithTitle("Limit").WithFormat("N0").WithAlign("end"))
        .WithColumn(new PropertyColumnControl<double> { Property = nameof(Row.RateOnLine).ToCamelCase() }.WithTitle("RoL").WithFormat("P1").WithAlign("end"))
        .WithColumn(new PropertyColumnControl<double> { Property = nameof(Row.Premium100).ToCamelCase() }.WithTitle("Premium @100%").WithFormat("N0").WithAlign("end"))
        .WithColumn(new PropertyColumnControl<double> { Property = nameof(Row.Expected).ToCamelCase() }.WithTitle("Must be").WithFormat("N0").WithAlign("end"))
        .WithColumn(new PropertyColumnControl<string> { Property = nameof(Row.Result).ToCamelCase() }.WithTitle("Result"))
        .Resizable(false))
    .WithView(Controls.Markdown(
        $"**Total premium @100%** {total:N0} (must be 1,056,000) {(totalOk ? "✓" : "✗")} · **blended RoL** {blended:P2} (must be 4.80%) {(blendedOk ? "✓" : "✗")}"))

Note the answer to the reading question: the thick cheap Layer 2 (15m at 3.4%) carries 510,000 — almost as much premium as the thin expensive Layer 1's 546,000. Rate on line is a price per unit of limit, not a size.


Battery green — or stuck? Reveal the solution — the one-line derivation and what the blend actually says.

← Lesson 1 exercises · Lesson 1 — The submission

Reconnecting…
The connection to the server was interrupted. Trying to restore it…
Trying again…
The connection could not be restored. Reloading the page…
The server was updated. Reloading the page to pick up the latest version.