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
Premium100so 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
Premium100(layer)returns the layer's premium at 100% placement.- Layer 1: 7m limit at 7.8% → must reach 546,000. Layer 2: 15m at 3.4% → 510,000.
- 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.