{"spec_id":"donut-basic","library":"makie","language":"julia","code":"# anyplot.ai\n# donut-basic: Basic Donut Chart\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 87/100 | Created: 2026-06-25\n\nusing CairoMakie\nusing Colors\nusing Random\n\nRandom.seed!(42)\n\n# Theme tokens\nconst THEME       = get(ENV, \"ANYPLOT_THEME\", \"light\")\nconst PAGE_BG     = THEME == \"light\" ? colorant\"#FAF8F1\" : colorant\"#1A1A17\"\nconst ELEVATED_BG = THEME == \"light\" ? colorant\"#FFFDF6\" : colorant\"#242420\"\nconst INK         = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nconst INK_SOFT    = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\nconst IMPRINT_PALETTE = [\n    colorant\"#009E73\",  # 1 — brand green\n    colorant\"#C475FD\",  # 2 — lavender\n    colorant\"#4467A3\",  # 3 — blue\n    colorant\"#BD8233\",  # 4 — ochre\n    colorant\"#AE3030\",  # 5 — matte red\n    colorant\"#2ABCCD\",  # 6 — cyan\n]\n\n# Data: annual R&D budget allocation by division\nconst categories = [\"Software\", \"Hardware\", \"Research\", \"Testing\", \"Design\", \"Support\"]\nconst values     = [34.0, 19.0, 21.0, 10.0, 10.0, 6.0]\nconst n          = length(categories)\nconst proportions = values ./ sum(values)\n\n# Segment angles — start from top (−π/2), clockwise\nconst cum_props    = cumsum(proportions)\nconst angles_end   = cum_props .* 2π .- π/2\nconst angles_start = vcat(-π/2, angles_end[1:end-1])\n\n# Figure — square canvas → 2400×2400 px (size × px_per_unit = 1200 × 2)\nfig = Figure(\n    size            = (1200, 1200),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis(\n    fig[1, 1];\n    title              = \"R&D Budget Allocation · donut-basic · julia · makie · anyplot.ai\",\n    titlesize          = 16,\n    titlecolor         = INK,\n    titlegap           = 10,\n    backgroundcolor    = PAGE_BG,\n    aspect             = DataAspect(),\n)\nhidespines!(ax)\nhidedecorations!(ax)\nlimits!(ax, -1.35, 1.35, -1.35, 1.35)\n\n# Donut ring geometry\nconst OUTER_R = 1.0\nconst INNER_R = 0.50\nconst N_ARC   = 220\n\n# Draw annular segments as polygons\nfor i in 1:n\n    θs = range(angles_start[i], angles_end[i]; length=N_ARC)\n    ox = OUTER_R .* cos.(θs)\n    oy = OUTER_R .* sin.(θs)\n    ix = INNER_R .* cos.(reverse(θs))\n    iy = INNER_R .* sin.(reverse(θs))\n    pts = Point2f.(vcat(ox, ix), vcat(oy, iy))\n    poly!(ax, pts; color=IMPRINT_PALETTE[i], strokecolor=PAGE_BG, strokewidth=3.0)\nend\n\n# Percentage labels inside segments (skip very small slices)\nconst dominant_i = argmax(proportions)\nfor i in 1:n\n    proportions[i] < 0.07 && continue\n    θ_mid = (angles_start[i] + angles_end[i]) / 2\n    r_mid = (OUTER_R + INNER_R) / 2\n    pct   = round(Int, proportions[i] * 100)\n    is_dominant = (i == dominant_i)\n    text!(ax, \"$(pct)%\";\n          position = Point2f(r_mid * cos(θ_mid), r_mid * sin(θ_mid)),\n          align    = (:center, :center),\n          fontsize = is_dominant ? 20 : 16,\n          font     = is_dominant ? :bold : :regular,\n          color    = RGBf(1.0, 1.0, 1.0))\nend\n\n# Center annotation — total budget and label\ntext!(ax, \"\\$4.8M\";\n      position = Point2f(0.0, 0.12),\n      align    = (:center, :center),\n      fontsize = 24,\n      color    = INK)\ntext!(ax, \"Total Budget\";\n      position = Point2f(0.0, -0.14),\n      align    = (:center, :center),\n      fontsize = 13,\n      color    = INK_SOFT)\n\n# Legend\nelems = [PolyElement(color=IMPRINT_PALETTE[i], strokecolor=:transparent, strokewidth=0)\n         for i in 1:n]\nLegend(fig[1, 2], elems, categories;\n       labelsize       = 14.0f0,\n       labelcolor      = INK,\n       framevisible    = false,\n       framecolor      = INK_SOFT,\n       backgroundcolor = ELEVATED_BG,\n       patchsize       = (20.0f0, 16.0f0),\n       rowgap          = 10,\n       padding         = (12, 12, 12, 12))\n\ncolsize!(fig.layout, 1, Relative(0.72))\ncolgap!(fig.layout, 8)\n\nsave(\"plot-$(THEME).png\", fig; px_per_unit=2)\n"}