{"spec_id":"radar-basic","library":"makie","language":"julia","code":"# anyplot.ai\n# radar-basic: Basic Radar Chart\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 87/100 | Created: 2026-07-24\n\nusing CairoMakie\nusing Colors\n\n# --- Theme tokens -----------------------------------------------------------\nconst THEME    = get(ENV, \"ANYPLOT_THEME\", \"light\")\nconst PAGE_BG  = THEME == \"light\" ? colorant\"#FAF8F1\" : colorant\"#1A1A17\"\nconst INK      = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nconst INK_SOFT = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\nconst GRID     = RGBAf(INK.r, INK.g, INK.b, 0.15)\nconst IMPRINT_PALETTE = [\n    colorant\"#009E73\",  # 1 — first categorical series (anyplot brand green)\n    colorant\"#C475FD\",  # 2 — lavender (second series)\n]\n\n# --- Data ---------------------------------------------------------------\n# Two soccer players compared across six performance attributes (0-100 scale)\ncategories = [\"Speed\", \"Passing\", \"Shooting\", \"Defense\", \"Stamina\", \"Vision\"]\nplayer_a = [88.0, 72.0, 90.0, 65.0, 78.0, 82.0]\nplayer_b = [75.0, 85.0, 68.0, 88.0, 90.0, 70.0]\n\nn = length(categories)\nangles = [pi / 2 - 2 * pi * (i - 1) / n for i in 1:n]\ngrid_levels = [20, 40, 60, 80, 100]\n\n# Largest gap between the two players — used to anchor a focal-point annotation\ngaps = abs.(player_a .- player_b)\nfocus_idx = argmax(gaps)\nfocus_angle = angles[focus_idx]\nfocus_lo, focus_hi = extrema((player_a[focus_idx], player_b[focus_idx]))\n\n# --- Plot -----------------------------------------------------------------\nfig = Figure(\n    size            = (1200, 1200),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis(\n    fig[1, 1];\n    title           = \"radar-basic · julia · makie · anyplot.ai\",\n    titlesize       = 20,\n    titlecolor      = INK,\n    aspect          = DataAspect(),\n    backgroundcolor = PAGE_BG,\n)\nhidedecorations!(ax)\nhidespines!(ax)\nlimits!(ax, -145, 145, -134, 148)\n\n# Concentric gridline polygons at 20/40/60/80/100\nfor level in grid_levels\n    xs = [level * cos(a) for a in angles]\n    ys = [level * sin(a) for a in angles]\n    lines!(ax, [xs; xs[1]], [ys; ys[1]]; color = GRID, linewidth = 1.2)\nend\n\n# Radial spokes, one per category\nfor a in angles\n    lines!(ax, [0.0, 100 * cos(a)], [0.0, 100 * sin(a)]; color = GRID, linewidth = 1.2)\nend\n\n# Gridline value labels along the top spoke\nfor level in grid_levels\n    text!(ax, 6, Float64(level); text = string(level), fontsize = 13,\n          color = INK_SOFT, align = (:left, :center), font = :bold)\nend\n\n# Category labels at the outer edge\nlabel_radius = 118\nfor (i, cat) in enumerate(categories)\n    a = angles[i]\n    halign = cos(a) > 0.3 ? :left : (cos(a) < -0.3 ? :right : :center)\n    text!(ax, label_radius * cos(a), label_radius * sin(a); text = cat,\n          fontsize = 15, color = INK, align = (halign, :center))\nend\n\n# Series polygons — filled with transparency, closed back to the first point\nfor (values, color, name) in (\n    (player_a, IMPRINT_PALETTE[1], \"Player A\"),\n    (player_b, IMPRINT_PALETTE[2], \"Player B\"),\n)\n    xs = [v * cos(a) for (v, a) in zip(values, angles)]\n    ys = [v * sin(a) for (v, a) in zip(values, angles)]\n    poly!(ax, Point2f.([xs; xs[1]], [ys; ys[1]]);\n          color = (color, 0.25), strokecolor = color, strokewidth = 3, label = name)\n    scatter!(ax, xs, ys; color = color, markersize = 14, strokewidth = 0)\nend\n\n# Focal-point annotation: bracket the widest gap between the two players\nbracket!(\n    ax,\n    focus_lo * cos(focus_angle), focus_lo * sin(focus_angle),\n    focus_hi * cos(focus_angle), focus_hi * sin(focus_angle);\n    text = \"largest gap · $(round(Int, gaps[focus_idx])) pts\",\n    fontsize = 13,\n    color = INK_SOFT,\n    textcolor = INK,\n    offset = 14,\n    orientation = :down,\n    style = :curly,\n)\n\naxislegend(ax, position = :lb, labelsize = 14, labelcolor = INK,\n           framevisible = false, backgroundcolor = (PAGE_BG, 0.0))\n\n# --- Save -------------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}