diff --git a/src/views/projections.zig b/src/views/projections.zig index ddeb95e..ca4b506 100644 --- a/src/views/projections.zig +++ b/src/views/projections.zig @@ -111,15 +111,15 @@ pub const AllocationNote = struct { /// Returns null if no target is configured. /// /// Drift thresholds: -/// - Within 2%: "on target" (muted) -/// - 2–5% off: warning -/// - Over 5% off: negative +/// - Within 5%: "on target" (muted) +/// - 5–10% off: warning +/// - Over 10% off: negative pub fn fmtAllocationNote(buf: []u8, target_stock_pct: ?f64, current_stock_pct: f64) ?AllocationNote { const target = target_stock_pct orelse return null; const current = current_stock_pct * 100; const drift = @abs(current - target); - const style: StyleIntent = if (drift < 2.0) .muted else if (drift < 5.0) .warning else .negative; - const text = if (drift < 2.0) + const style: StyleIntent = if (drift < 5.0) .muted else if (drift < 10.0) .warning else .negative; + const text = if (drift < 5.0) std.fmt.bufPrint(buf, "Target allocation: {d:.0}% stocks / {d:.0}% bonds (current: {d:.1}% \u{2014} on target)", .{ target, 100.0 - target, current, }) catch return null @@ -435,17 +435,17 @@ test "fmtAllocationNote on target" { test "fmtAllocationNote off target" { var buf: [128]u8 = undefined; - const note = fmtAllocationNote(&buf, 77, 0.85); + const note = fmtAllocationNote(&buf, 77, 0.90); try std.testing.expect(note != null); - try std.testing.expect(note.?.style == .negative); // >5% drift + try std.testing.expect(note.?.style == .negative); // 13% drift, >10% try std.testing.expect(std.mem.indexOf(u8, note.?.text, "on target") == null); } test "fmtAllocationNote warning range" { var buf: [128]u8 = undefined; - const note = fmtAllocationNote(&buf, 77, 0.80); + const note = fmtAllocationNote(&buf, 77, 0.84); try std.testing.expect(note != null); - try std.testing.expect(note.?.style == .warning); // 3% drift, in 2-5% range + try std.testing.expect(note.?.style == .warning); // 7% drift, in 5-10% range } test "fmtAllocationNote no target" {