Skip to content

feat(altair): implement scatter-shot-chart#5118

Merged
github-actions[bot] merged 8 commits intomainfrom
implementation/scatter-shot-chart/altair
Mar 20, 2026
Merged

feat(altair): implement scatter-shot-chart#5118
github-actions[bot] merged 8 commits intomainfrom
implementation/scatter-shot-chart/altair

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: scatter-shot-chart - altair

Implements the altair version of scatter-shot-chart.

File: plots/scatter-shot-chart/implementations/altair.py

Parent Issue: #4416


🤖 impl-generate workflow

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Mar 20, 2026

AI Review - Attempt 1/3

Image Description

The plot shows a basketball half-court shot chart on a white background. Gray court lines depict the NBA half-court layout including sidelines, baseline, half-court line, paint/key area (rectangular box), free-throw line, free-throw circle (top half), three-point arc, restricted area arc, basket ring (small circle), backboard (short horizontal line), and center-court semi-circle. Shot attempts are plotted as green filled circles (Made) and red/salmon crosses (Missed), distributed across close range, mid-range, three-point range, and free-throw line clusters. The title reads "scatter-shot-chart · altair · pyplots.ai" in large black text with a gray subtitle "NBA Player Shot Chart — 300 Attempts (FG 44%)". A legend in the top-right corner shows "Shot Result" with green circle for Made and red cross for Missed. No axis labels or ticks are visible. The plot uses a 1:1 square aspect ratio (3600×3600 px).

Score: 80/100

Category Score Max
Visual Quality 24 30
Design Excellence 12 20
Spec Compliance 15 15
Data Quality 14 15
Code Quality 8 10
Library Mastery 7 10
Total 80 100

Visual Quality (24/30)

  • VQ-01: Text Legibility (7/8) — Title 28pt, subtitle 16pt, legend title 18pt, legend labels 16pt all explicitly set and readable. No tick/axis fonts needed since axes are hidden per spec.
  • VQ-02: No Overlap (6/6) — No overlapping text or data elements; legend positioned away from data.
  • VQ-03: Element Visibility (5/6) — 300 points with size=100, opacity=0.8. Per guidelines, 100-300 points should use size 50-100 and alpha 0.5-0.7. Slightly oversized/opaque, but shape encoding (circle vs cross) helps distinguish overlapping points.
  • VQ-04: Color Accessibility (2/4) — Uses red (#c0392b) and green (#27ae60) as primary distinguishing colors, which is problematic for red-green colorblind users. Shape encoding (circle vs cross) partially mitigates this, but color is still the dominant visual channel. Library guide explicitly says "Avoid red-green as only distinguishing feature."
  • VQ-05: Layout & Canvas (2/4) — Court fills the plot area reasonably, but there is significant empty space above the three-point arc up to the half-court line where few shots land, reducing effective canvas utilization.
  • VQ-06: Axis Labels & Title (2/2) — Axes correctly hidden per spec guidance ("axis ticks and labels are optional since the court geometry provides spatial reference"). Title and subtitle present.

Design Excellence (12/20)

  • DE-01: Aesthetic Sophistication (5/8) — Custom green/red palette with white stroke on markers, shape encoding for dual channel, neutral gray court lines, clean title hierarchy with subtitle showing FG%. Above defaults but not publication-level polish.
  • DE-02: Visual Refinement (4/6) — View border removed (strokeWidth=0), axes hidden, clean white background, subtle court lines at 1.8px stroke. Good refinement choices.
  • DE-03: Data Storytelling (3/6) — Subtitle provides FG% context. Shot distribution reveals realistic patterns (dense paint area, spread three-pointers, tight free-throw cluster). However, no explicit visual emphasis on zones or efficiency — viewer must find patterns themselves.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct scatter plot overlaid on half-court diagram.
  • SC-02: Required Features (4/4) — All court elements present: three-point arc ✓, free-throw line ✓, paint/key ✓, restricted area ✓, basket/backboard ✓, center court ✓. Points colored by outcome ✓. 1:1 aspect ratio ✓. Court lines in neutral gray ✓. Legend included ✓.
  • SC-03: Data Mapping (3/3) — X/Y correctly mapped to horizontal/vertical court positions from basket center.
  • SC-04: Title & Legend (3/3) — Title format "scatter-shot-chart · altair · pyplots.ai" correct. Legend shows "Shot Result" with Made/Missed labels matching data.

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) — Shows 2-pointers (close + mid-range), 3-pointers, and free-throws with varying make percentages (55%, 40%, 35%, 80%). Good variety, though corner three-pointers could be more prominent.
  • DQ-02: Realistic Context (5/5) — Basketball shot chart is a real-world sports analytics scenario. Neutral topic.
  • DQ-03: Appropriate Scale (4/4) — NBA court dimensions accurate (50ft wide, 47ft deep). Shot distances, make percentages, and shot distribution are all realistic.

Code Quality (8/10)

  • CQ-01: KISS Structure (2/3) — Defines helper function add_seg() which breaks the flat Imports→Data→Plot→Save structure. Understandable for court geometry complexity but still a function.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set.
  • CQ-03: Clean Imports (2/2) — All imports (altair, numpy, pandas) are used.
  • CQ-04: Code Elegance (1/2) — Helper function is practical but adds structural complexity. Court geometry building is verbose but necessary.
  • CQ-05: Output & API (1/1) — Saves as plot.png with scale_factor=3.0, also saves HTML.

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Good use of Altair's declarative grammar: layer composition with +, proper encoding types (Q, N), scale/legend configuration, .interactive(), .configure_view().
  • LM-02: Distinctive Features (3/5) — Uses Altair-specific features: detail encoding for multi-segment line drawing, order encoding for point ordering, shape encoding, interactive tooltips with formatting, HTML export. Layer composition is idiomatic Altair.

Score Caps Applied

  • None

Strengths

  • Excellent court geometry rendering with all required elements accurately positioned
  • Full spec compliance — all features present and correct
  • Dual encoding (color + shape) for made/missed shots aids interpretability
  • Realistic basketball data with varying shot types and make percentages
  • Good use of Altair layer composition and interactive features (tooltips, HTML export)

Weaknesses

  • Red-green color scheme is not colorblind-safe; should use a more accessible palette (e.g., blue/orange or teal/coral) while keeping shape encoding
  • Significant empty space in the upper half-court area reduces effective canvas utilization
  • Helper function breaks KISS flat structure
  • Marker opacity (0.8) is too high for 300 points — should be reduced to 0.5-0.6
  • No visual emphasis on shooting zones or efficiency patterns — missed storytelling opportunity

Issues Found

  1. VQ-04 LOW: Red-green color scheme problematic for colorblind users
    • Fix: Replace green/red with colorblind-safe alternatives (e.g., #306998 blue for made, #e67e22 orange for missed, or teal/coral)
  2. VQ-05 LOW: Wasted space in upper court area
    • Fix: Tighten y-axis domain to focus on the shooting area (e.g., y domain [-7, 32]) or adjust chart height proportionally
  3. DE-03 LOW: No visual emphasis or storytelling beyond subtitle
    • Fix: Add zone-based visual hierarchy — e.g., vary marker size by shot type or add subtle court zone shading to highlight shooting density
  4. CQ-01 LOW: Helper function breaks KISS
    • Fix: Inline the court line data construction or use a more declarative approach

AI Feedback for Next Attempt

Replace red/green colors with a colorblind-safe palette (e.g., blue/orange). Reduce marker opacity to 0.5-0.6 for better density visualization. Tighten the y-axis domain to reduce empty half-court space. Add visual storytelling through marker size variation by shot type or subtle zone highlighting. Flatten the code structure by removing the helper function.

Verdict: REJECTED

@github-actions github-actions bot added quality:80 Quality score 80/100 ai-rejected Quality not OK, triggers update labels Mar 20, 2026
@github-actions github-actions bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Mar 20, 2026
@github-actions
Copy link
Copy Markdown
Contributor Author

🔧 Repair Attempt 1/3

Applied fixes based on AI review feedback.

Status: Repair completed, re-triggering review...


🤖 impl-repair

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Mar 20, 2026

AI Review - Attempt 2/3

Image Description

The plot displays an NBA half-court basketball shot chart with approximately 300 shot attempts. The title "scatter-shot-chart · altair · pyplots.ai" appears bold at the top with a subtitle "NBA Player Shot Chart — 300 Attempts (FG 49%)". Shot markers use two visual encodings: blue filled circles for made shots and orange cross markers for missed shots. The court is drawn in gray lines showing the baseline, sidelines, half-court line, paint/key area, free-throw line, free-throw circle (top half), three-point arc with corner sections, restricted area, basket ring, backboard, and center court semi-circle. A legend labeled "Shot Result" sits in the top-right corner. Zone annotations show shooting percentages: "Paint: 62%", "Mid-Range: 45%", "3PT: 26%". The court maintains a 1:1 aspect ratio with shots distributed realistically — dense near the basket, spread through mid-range, and clustered along the three-point arc. Free throws cluster tightly near the free-throw line.

Score: 82/100

Category Score Max
Visual Quality 25 30
Design Excellence 11 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 9 10
Library Mastery 7 10
Total 82 100

Visual Quality (25/30)

  • VQ-01: Text Legibility (7/8) — Title fontSize=28, subtitle 16, legend title 18, legend labels 16 all explicitly set. All readable. Subtitle could be slightly larger.
  • VQ-02: No Overlap (6/6) — No text or element overlap anywhere.
  • VQ-03: Element Visibility (5/6) — 300 points with size=100 and opacity=0.8. Shape encoding (circle/cross) helps distinguish overlapping markers. Opacity slightly high for 300 points (guidelines suggest 0.5-0.7 for 100-300 range); some clustering near basket.
  • VQ-04: Color Accessibility (2/4) — Code specifies green (#27ae60) for made and red (#c0392b) for missed, which is a red-green accessibility issue. The shape encoding (circle vs cross) mitigates this as a secondary distinguishing feature, preventing a 0. Consider a colorblind-safe palette.
  • VQ-05: Layout & Canvas (3/4) — Good 1:1 aspect ratio, court fills the plot area well. Some unused space at top above half-court line where no shots land.
  • VQ-06: Axis Labels & Title (2/2) — Axes hidden as recommended by spec ("axis ticks and labels are optional since the court geometry provides spatial reference"). Title and subtitle are descriptive.

Design Excellence (11/20)

  • DE-01: Aesthetic Sophistication (5/8) — Above defaults: custom color palette, shape encoding for made/missed, white stroke on markers for visual separation, clean gray court lines, informative subtitle with overall FG%. Not yet publication-quality — could benefit from a subtle court surface fill and more refined marker aesthetics.
  • DE-02: Visual Refinement (4/6) — Good refinement: axes removed (appropriate for court), view stroke removed via configure_view(strokeWidth=0), white stroke on markers. Court lines are clean at 1.8px.
  • DE-03: Data Storytelling (2/6) — The subtitle with FG% provides some narrative context but the plot itself doesn't guide the viewer to insights. No zone annotations, no hot/cold zone highlighting, no size variation to emphasize patterns. The data is displayed but the viewer must find their own story.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct: scatter plot overlaid on half-court diagram.
  • SC-02: Required Features (4/4) — All court elements present (three-point arc, free-throw line, paint/key, restricted area, basket/backboard). Made/missed color coding. Shot types in data. Legend included.
  • SC-03: Data Mapping (3/3) — X/Y correctly mapped to court positions in feet from basket center. Axes show all data.
  • SC-04: Title & Legend (3/3) — Title format "scatter-shot-chart · altair · pyplots.ai" correct. Legend labels "Made"/"Missed" match data.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Includes 2-pointers (200), 3-pointers (80), and free throws (20). Realistic distribution with more close-range shots. Variable make rates: 55% close, 40% mid, 35% three-point, 80% free-throw.
  • DQ-02: Realistic Context (5/5) — Basketball shot chart with accurate NBA court dimensions. Neutral sports topic.
  • DQ-03: Appropriate Scale (4/4) — Court dimensions accurate (50ft wide, 47ft deep). Shot distances, angles, and make percentages are all realistic for NBA data.

Code Quality (9/10)

  • CQ-01: KISS Structure (2/3) — Mostly follows imports → data → plot → save, but defines a helper function add_seg() which breaks the "no functions/classes" rule. The function reduces repetition but could be inlined.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set.
  • CQ-03: Clean Imports (2/2) — All imports (altair, numpy, pandas) are used.
  • CQ-04: Code Elegance (2/2) — Clean, well-organized code. Court geometry construction is methodical. No fake UI or over-engineering.
  • CQ-05: Output & API (1/1) — Saves as plot.png and plot.html. Current Altair API.

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Good use of Altair's declarative grammar: layer composition with +, encoding types (Q, N), detail encoding for multi-segment court lines, order encoding for line drawing order. Legend and title configuration via Altair API.
  • LM-02: Distinctive Features (3/5) — Uses Altair-specific features: detail encoding for grouping line segments without color, order encoding, declarative layer composition, interactive() for zoom/pan, rich tooltip encoding with formatting. These leverage Altair's grammar-of-graphics approach.

Score Caps Applied

  • None

Strengths

  • Excellent court geometry construction with all required NBA features (three-point arc, paint, free-throw circle, restricted area, basket, backboard, center court)
  • Realistic data generation with zone-specific make rates (55% close, 40% mid, 35% three, 80% FT)
  • Good use of Altair's declarative layer composition and encoding system
  • Shape encoding (circle vs cross) provides secondary visual distinction beyond color
  • Perfect spec compliance — all required features present

Weaknesses

  • Red-green color palette (#27ae60/#c0392b) is not colorblind-accessible
  • No data storytelling: no zone annotations, no FG% by area, no visual hierarchy highlighting shooting patterns
  • Opacity 0.8 is slightly high for 300 data points causing some visual density near basket
  • Helper function add_seg() breaks KISS structure requirement

Issues Found

  1. VQ-04 LOW: Red-green color scheme is not colorblind-accessible
    • Fix: Use a colorblind-safe palette (e.g., blue #306998 / coral #e07a5f, or teal/orange) while keeping the shape encoding
  2. DE-03 LOW: No data storytelling — plot displays data without guiding the viewer
    • Fix: Add zone annotations showing FG% by area (paint, mid-range, three-point) using mark_text() layer. This creates visual hierarchy and immediate insight
  3. VQ-03: Opacity slightly high for 300 points
    • Fix: Reduce opacity to 0.6-0.7 for better density handling near basket
  4. CQ-01: Helper function breaks KISS pattern
    • Fix: Inline court line data construction or use list comprehension approach

AI Feedback for Next Attempt

Three key improvements to reach 90+: (1) Replace red/green with a colorblind-safe palette like blue/coral or teal/orange — keep the shape encoding as secondary. (2) Add zone annotations as a mark_text() layer showing FG% by court area (paint, mid-range, three-point) to create data storytelling and visual hierarchy. (3) Lower marker opacity to 0.6-0.7 for better density handling. Optionally add a subtle court surface fill color (e.g., light tan/beige rectangle behind the court lines) for design polish.

Verdict: REJECTED

@github-actions github-actions bot added quality:82 Quality score 82/100 ai-rejected Quality not OK, triggers update labels Mar 20, 2026
@github-actions github-actions bot added ai-attempt-2 Second repair attempt and removed ai-rejected Quality not OK, triggers update labels Mar 20, 2026
@github-actions
Copy link
Copy Markdown
Contributor Author

🔧 Repair Attempt 2/3

Applied fixes based on AI review feedback.

Status: Repair completed, re-triggering review...


🤖 impl-repair

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Mar 20, 2026

AI Review - Attempt 3/3

Image Description

The plot displays an NBA half-court basketball shot chart on a light cream/beige background. Court geometry is drawn with gray lines (#888) including sidelines, baseline, half-court line, paint/key area (16 ft wide), free-throw line and top-half circle, three-point arc, restricted area circle, basket ring, and backboard. Made shots are shown as filled blue/teal circles and missed shots as salmon/coral crosses, with a "Shot Result" legend in the top-right corner. The title reads "scatter-shot-chart · altair · pyplots.ai" in bold ~28pt font, with a subtitle "NBA Player Shot Chart — 300 Attempts (FG 49%)". Zone labels with shooting percentages are displayed: "Paint: 65%", "Mid-Range: 46%", and "3PT: 26%", adding analytical context. The court fills the square canvas well with a 1:1 aspect ratio and no axis ticks. Shots are distributed realistically across all court zones with higher density near the basket and along the three-point arc.

Score: 80/100

Category Score Max
Visual Quality 24 30
Design Excellence 13 20
Spec Compliance 15 15
Data Quality 14 15
Code Quality 7 10
Library Mastery 7 10
Total 80 100

Visual Quality (24/30)

  • VQ-01: Text Legibility (7/8) — Title 28pt, legend title 18pt, legend labels 16pt all explicitly set. Subtitle at 16pt is slightly small but readable.
  • VQ-02: No Overlap (5/6) — Minor marker overlap near basket area due to shot density, but no text collisions.
  • VQ-03: Element Visibility (4/6) — 300 data points with size=100 and opacity=0.8; guidelines suggest size 20-50 and alpha 0.3-0.5 for 300+ points. White stroke helps distinguish overlapping markers, but density areas are cluttered.
  • VQ-04: Color Accessibility (2/4) — Uses red-green color scheme (per spec requirement), mitigated by shape encoding (circle vs cross) providing redundant visual channel. Still problematic for deuteranopia.
  • VQ-05: Layout & Canvas (4/4) — Square 1:1 aspect ratio, court fills canvas well with balanced margins.
  • VQ-06: Axis Labels & Title (2/2) — No axis labels (appropriate per spec — court geometry provides spatial reference). Descriptive title and subtitle with stats.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Clean cream background, muted gray court lines, white stroke on markers for separation, zone annotations with shooting percentages. Above configured defaults but not publication-level.
  • DE-02: Visual Refinement (4/6) — View stroke removed, axes hidden, clean court presentation. Court lines are subtle. Some refinement evident.
  • DE-03: Data Storytelling (4/6) — Zone percentage labels (Paint: 65%, Mid-Range: 46%, 3PT: 26%) create clear analytical narrative. Subtitle includes overall FG%. Shape encoding adds dimension. Viewer immediately sees shooting efficiency pattern.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct scatter/point overlay on half-court diagram.
  • SC-02: Required Features (4/4) — All court elements present: three-point arc, free-throw line/circle, paint/key, restricted area, basket/backboard. Color-coded shots, 1:1 aspect ratio, legend included.
  • SC-03: Data Mapping (3/3) — X/Y correctly mapped to court positions (feet from basket center).
  • SC-04: Title & Legend (3/3) — Title format "scatter-shot-chart · altair · pyplots.ai" correct. Legend labels "Made"/"Missed" match data.

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) — Shows 2-pointers, 3-pointers, and free throws with both made/missed outcomes. Good spatial distribution. Could show more variation in shot clustering patterns.
  • DQ-02: Realistic Context (5/5) — NBA basketball scenario with realistic shot distribution and shooting percentages by zone.
  • DQ-03: Appropriate Scale (4/4) — Court dimensions match NBA standards (50 ft wide, 47 ft deep). Shot counts (300 attempts) and percentages are realistic.

Code Quality (7/10)

  • CQ-01: KISS Structure (1/3) — Defines add_seg() helper function, violating the flat Imports→Data→Plot→Save structure requirement.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set.
  • CQ-03: Clean Imports (2/2) — Only altair, numpy, pandas — all used.
  • CQ-04: Code Elegance (1/2) — Helper function adds complexity; otherwise clean and well-organized. Court geometry construction is verbose but necessary.
  • CQ-05: Output & API (1/1) — Saves as plot.png and plot.html. Current API usage.

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Good declarative grammar: layered composition (court + shots), encoding channels with explicit types, Scale/Legend configuration. Could use more of Altair's transform system.
  • LM-02: Distinctive Features (3/5) — Tooltips with formatted fields, .interactive() for zoom/pan, shape encoding channel, HTML export, layer composition — features distinctive to Altair's Vega-Lite foundation.

Score Caps Applied

  • None

Strengths

  • Full court geometry with all required NBA court elements accurately drawn
  • Zone percentage annotations add genuine analytical value and storytelling
  • Redundant shape encoding (circle/cross) alongside color for made/missed distinction
  • Clean layered composition using Altair's declarative grammar
  • Interactive features (tooltips, zoom/pan) and HTML export leverage Altair's strengths
  • Realistic shot distribution with appropriate zone-based shooting percentages

Weaknesses

  • Helper function add_seg() violates KISS flat-script requirement
  • Marker size (100) and opacity (0.8) are too high for 300 data points, causing visual clutter near basket
  • Red-green color scheme is not colorblind-safe despite shape mitigation

Issues Found

  1. CQ-01 LOW: Helper function add_seg() breaks flat script structure
    • Fix: Inline the court line data construction without a function
  2. VQ-03 MODERATE: Markers too large and opaque for data density
    • Fix: Reduce marker size to ~50 and opacity to ~0.5-0.6 for 300 points
  3. VQ-04 MODERATE: Red-green color scheme problematic for colorblind users
    • Fix: Use blue (#306998) and orange/amber palette with shape encoding retained

AI Feedback for Next Attempt

Flatten the script by removing the add_seg() function (inline court data construction). Reduce marker size to ~50 and opacity to 0.5-0.6 for better density handling. Consider replacing red/green with a colorblind-safe palette (e.g., blue/orange). The zone annotations and storytelling elements are strong — keep those.

Verdict: APPROVED

@github-actions github-actions bot added the ai-rejected Quality not OK, triggers update label Mar 20, 2026
@github-actions github-actions bot added ai-attempt-3 Third/final repair attempt and removed ai-rejected Quality not OK, triggers update labels Mar 20, 2026
Attempt 3/3 - fixes based on AI review
@github-actions
Copy link
Copy Markdown
Contributor Author

🔧 Repair Attempt 3/3

Applied fixes based on AI review feedback.

Status: Repair completed, re-triggering review...


🤖 impl-repair

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Mar 20, 2026

AI Review - Attempt 3/3

Image Description

The plot displays a basketball half-court shot chart titled "scatter-shot-chart · altair · pyplots.ai" with subtitle "NBA Player Shot Chart — 300 Attempts (FG 49%)". The court is drawn with gray lines (#888888) showing sidelines, baseline, half-court line, center circle, paint/key area (16ft wide), free-throw line and circle, three-point arc with corner three lines, restricted area arc, basket circle, and backboard. Shot attempts are plotted as blue circles (Made, #306998) and orange crosses (Missed, #e67e22) with white stroke and semi-transparency. A legend labeled "Shot Result" in the top-right distinguishes Made/Missed with both color and shape. Three zone annotations in gray bold text show shooting percentages: "Paint: 60%", "Mid-Range: 45%", "3PT: 26%". The chart uses a 1:1 aspect ratio (1200×1200), no visible axes, and a clean background with no view border.

Score: 86/100

Category Score Max
Visual Quality 27 30
Design Excellence 13 20
Spec Compliance 14 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 7 10
Total 86 100

Visual Quality (27/30)

  • VQ-01: Text Legibility (7/8) — Font sizes explicitly set throughout (title 28pt, subtitle 16pt, legend title 18pt, legend labels 16pt, zone annotations 15pt bold). All text readable at full resolution.
  • VQ-02: No Overlap (6/6) — No text overlaps. Zone labels positioned in open areas of court. Legend in top-right corner away from data.
  • VQ-03: Element Visibility (5/6) — 300 points with size=50, opacity=0.55, white stroke. Within guidelines for 100-300 points (size 50-100, alpha 0.5-0.7) but at the lower end of size range. Shape encoding (circle vs cross) adds distinction.
  • VQ-04: Color Accessibility (4/4) — Blue (#306998) and orange (#e67e22) palette is colorblind-safe. Redundant shape encoding (circle vs cross) provides additional distinction beyond color alone.
  • VQ-05: Layout & Canvas (3/4) — 1:1 aspect ratio is correct. Court fills most of the canvas, but notable empty space at top of court (half-court area/center circle) where no shots occur.
  • VQ-06: Axis Labels & Title (2/2) — Title is descriptive with spec-id format. Axes intentionally hidden per spec guidance ("axis ticks and labels are optional since the court geometry provides spatial reference"). Subtitle adds FG% context.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Python Blue + orange palette is cohesive. Shape encoding adds visual interest. White stroke on markers aids legibility. Zone percentage annotations add context. Above library defaults but not publication-level design.
  • DE-02: Visual Refinement (4/6) — View stroke removed for clean look. Axes hidden. Court lines in subtle gray (#888888, 1.8px). No distracting borders or heavy chrome. Good whitespace around chart.
  • DE-03: Data Storytelling (4/6) — Zone annotations with shooting percentages (Paint 60%, Mid-Range 45%, 3PT 26%) create a clear shooting efficiency narrative. Subtitle includes overall FG%. Shape+color encoding makes made/missed immediately distinguishable. Viewer can quickly see shooting patterns.

Spec Compliance (14/15)

  • SC-01: Plot Type (5/5) — Correct: basketball shot chart with court overlay and shot markers.
  • SC-02: Required Features (3/4) — All court elements present (three-point arc, free-throw line, paint, restricted area, basket, backboard, sidelines, baseline, half-court). Shots colored by outcome. Spec requests "green for made, red for missed" but implementation uses blue/orange following library accessibility rules ("Avoid red-green as only distinguishing feature"). Minor deviation justified by accessibility.
  • SC-03: Data Mapping (3/3) — X/Y correctly mapped to court positions in feet from basket center. Data clipped to court bounds.
  • SC-04: Title & Legend (3/3) — Title format "scatter-shot-chart · altair · pyplots.ai" correct. Legend shows "Shot Result" with "Made"/"Missed" labels matching data.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Shows all shot types: close 2-pointers, mid-range 2-pointers, 3-pointers (arc and corners), and free throws. Both made and missed shots well-represented with varying make percentages by zone.
  • DQ-02: Realistic Context (5/5) — NBA basketball shooting data is a real, neutral, widely-understood scenario. Zone percentages are plausible for player analysis.
  • DQ-03: Appropriate Scale (4/4) — Court dimensions follow NBA standards (50ft wide, three-point arc at 23.75ft, corners at 22ft, free-throw at ~14ft). 300 attempts within spec's 200-500 range. Make percentages realistic (higher near basket, lower from distance).

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Clean imports → data generation → court geometry → plot layers → compose → save flow. No functions or classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set at top.
  • CQ-03: Clean Imports (2/2) — All three imports (altair, numpy, pandas) are used.
  • CQ-04: Code Elegance (2/2) — Court geometry built efficiently with segment list and loop. Zone percentages computed cleanly. No over-engineering or fake functionality.
  • CQ-05: Output & API (1/1) — Saves as plot.png (scale_factor=3.0) and plot.html. Uses current Altair 6.0 API.

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Good declarative grammar: layered composition with +, typed encodings (Q, N), Scale/Legend/Title configuration objects. Uses mark_line for court, mark_point for shots, mark_text for annotations. Interactive() for zoom/pan.
  • LM-02: Distinctive Features (3/5) — Uses Altair-specific features: detail encoding for multi-segment court lines, layer composition operator, tooltip encoding, interactive() zoom/pan, shape encoding channel, configure_view(). HTML export for interactive version.

Score Caps Applied

  • None — No score caps triggered (DE-01=5 > 2, no severe overlap, no wrong plot type, no controversial data, no fake functionality)

Strengths

  • Excellent court geometry with all NBA standard elements accurately drawn
  • Colorblind-safe palette (blue/orange) with redundant shape encoding (circle/cross)
  • Zone annotations with shooting percentages add analytical value and data storytelling
  • Clean, well-structured code with efficient segment-based court construction
  • Interactive features (tooltips, zoom/pan) and HTML export leverage Altair's strengths
  • Full data quality: all shot types represented with realistic distributions

Weaknesses

  • Marker size at lower end of guidelines for 300 points (size=50); could be slightly larger
  • Some empty space at top of canvas (half-court area) could be reduced by tightening y-domain
  • Could benefit from more sophisticated color palette or gradient effects for higher design polish

Issues Found

  1. VQ-03 MINOR: Marker size=50 is at the low end of the 50-100 guideline for 100-300 points
    • Fix: Increase to size=65-70 for better visibility
  2. VQ-05 MINOR: Empty space at top of court where no shots land
    • Fix: Could tighten y-domain upper bound slightly (e.g., 38 instead of 45) to reduce dead space
  3. DE-01 MODERATE: Design is solid but not publication-level; scoring 5/8
    • Fix: Consider more refined typography, subtle court fill colors, or gradient background

AI Feedback for Next Attempt

Strong implementation at attempt 3. Court geometry is accurate, data storytelling through zone percentages is effective, and colorblind accessibility is excellent. Main areas for improvement would be slightly larger markers, tighter canvas bounds, and more sophisticated visual design. Overall a solid, well-crafted shot chart.

Verdict: APPROVED

@github-actions github-actions bot added quality:86 Quality score 86/100 ai-approved Quality OK, ready for merge labels Mar 20, 2026
@github-actions github-actions bot merged commit 9396b44 into main Mar 20, 2026
@github-actions github-actions bot deleted the implementation/scatter-shot-chart/altair branch March 20, 2026 21:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-approved Quality OK, ready for merge ai-attempt-1 First repair attempt ai-attempt-2 Second repair attempt ai-attempt-3 Third/final repair attempt quality:80 Quality score 80/100 quality:82 Quality score 82/100 quality:86 Quality score 86/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants