{"spec_id":"venn-basic","library":"makie","language":"julia","code":"# anyplot.ai\n# venn-basic: Venn Diagram\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 94/100 | Created: 2026-09-09\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 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\", colorant\"#C475FD\", colorant\"#4467A3\",\n]\n\n# --- Data: developer skill survey (n = 270 engineers) --------------------------\nset_labels = [\"Python\", \"SQL\", \"JavaScript\"]\nsize_python, size_sql, size_js = 145, 120, 95\noverlap_py_sql, overlap_py_js, overlap_sql_js = 45, 35, 25\noverlap_all = 15\n\nonly_python = size_python - overlap_py_sql - overlap_py_js + overlap_all\nonly_sql    = size_sql - overlap_py_sql - overlap_sql_js + overlap_all\nonly_js     = size_js - overlap_py_js - overlap_sql_js + overlap_all\nonly_py_sql = overlap_py_sql - overlap_all\nonly_py_js  = overlap_py_js - overlap_all\nonly_sql_js = overlap_sql_js - overlap_all\ntotal = only_python + only_sql + only_js + only_py_sql + only_py_js + only_sql_js + overlap_all\n\n# --- Circle geometry: radii scaled by sqrt(set size) for an area-proportional\n#     impression; centers pulled in toward the largest circle by the same\n#     ratio so the three circles keep overlapping cleanly. ---------------------\nbase_radius = 1.6\nradius_python = base_radius * sqrt(size_python / size_python)\nradius_sql    = base_radius * sqrt(size_sql / size_python)\nradius_js     = base_radius * sqrt(size_js / size_python)\n\ncenter_python = Point2f(-0.65, 0.55)\ncenter_sql    = Point2f(0.65, 0.55) * (radius_sql / base_radius)\ncenter_js     = Point2f(0.0, -0.55) * (radius_js / base_radius)\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           = \"venn-basic · julia · makie · anyplot.ai\",\n    titlesize       = 20,\n    titlecolor      = INK,\n    backgroundcolor = PAGE_BG,\n    aspect          = DataAspect(),\n)\nhidedecorations!(ax)\nhidespines!(ax)\nxlims!(ax, -2.5, 2.5)\nylims!(ax, -2.3, 2.5)\n\nfill_alpha = 0.55\npoly!(ax, Circle(center_python, radius_python);\n      color = (IMPRINT_PALETTE[1], fill_alpha), strokecolor = INK_SOFT, strokewidth = 2)\npoly!(ax, Circle(center_sql, radius_sql);\n      color = (IMPRINT_PALETTE[2], fill_alpha), strokecolor = INK_SOFT, strokewidth = 2)\npoly!(ax, Circle(center_js, radius_js);\n      color = (IMPRINT_PALETTE[3], fill_alpha), strokecolor = INK_SOFT, strokewidth = 2)\n\n# Set name labels, placed outside each circle\ntext!(ax, -1.55, 2.05; text = set_labels[1], color = INK, fontsize = 22,\n      font = :bold, align = (:center, :center))\ntext!(ax, 1.41, 1.86; text = set_labels[2], color = INK, fontsize = 22,\n      font = :bold, align = (:center, :center))\ntext!(ax, 0.0, -1.78; text = set_labels[3], color = INK, fontsize = 22,\n      font = :bold, align = (:center, :center))\n\n# Region count labels (count + percentage, inline — no helper functions)\ntext!(ax, -1.35, 1.05; text = \"$(only_python)\\n($(round(Int, 100 * only_python / total))%)\",\n      color = INK, fontsize = 17, align = (:center, :center))\ntext!(ax, 1.23, 0.96; text = \"$(only_sql)\\n($(round(Int, 100 * only_sql / total))%)\",\n      color = INK, fontsize = 17, align = (:center, :center))\ntext!(ax, 0.0, -1.25; text = \"$(only_js)\\n($(round(Int, 100 * only_js / total))%)\",\n      color = INK, fontsize = 17, align = (:center, :center))\ntext!(ax, -0.04, 0.88; text = \"$(only_py_sql)\\n($(round(Int, 100 * only_py_sql / total))%)\",\n      color = INK, fontsize = 17, align = (:center, :center))\ntext!(ax, -0.59, -0.08; text = \"$(only_py_js)\\n($(round(Int, 100 * only_py_js / total))%)\",\n      color = INK, fontsize = 17, align = (:center, :center))\ntext!(ax, 0.56, -0.12; text = \"$(only_sql_js)\\n($(round(Int, 100 * only_sql_js / total))%)\",\n      color = INK, fontsize = 17, align = (:center, :center))\n\n# Focal point: the triple overlap is the rarest — and most interesting —\n# combination, so it gets a soft halo backdrop plus a bolder, larger label.\npoly!(ax, Circle(Point2f(0.0, 0.20), 0.32);\n      color = (ELEVATED_BG, 0.9), strokecolor = INK_SOFT, strokewidth = 1)\ntext!(ax, 0.0, 0.20; text = \"$(overlap_all)\\n($(round(Int, 100 * overlap_all / total))%)\",\n      color = INK, fontsize = 19, font = :bold, align = (:center, :center))\n\n# Makie-distinctive touch: a grid-layout callout row (not axis text) that\n# turns the triple-overlap number into a short data story.\nLabel(\n    fig[2, 1],\n    \"$(overlap_all) engineers ($(round(Int, 100 * overlap_all / total))%) are full-stack — fluent in Python, SQL, and JavaScript alike, the rarest combination in the survey.\";\n    fontsize = 15,\n    color = INK_SOFT,\n    tellwidth = false,\n)\nrowgap!(fig.layout, 10)\n\n# --- Save -------------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}