Skip to content

feat(matplotlib): implement campbell-basic#4246

Merged
github-actions[bot] merged 10 commits intomainfrom
implementation/campbell-basic/matplotlib
Feb 15, 2026
Merged

feat(matplotlib): implement campbell-basic#4246
github-actions[bot] merged 10 commits intomainfrom
implementation/campbell-basic/matplotlib

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: campbell-basic - matplotlib

Implements the matplotlib version of campbell-basic.

File: plots/campbell-basic/implementations/matplotlib.py

Parent Issue: #4241


🤖 impl-generate workflow

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Feb 15, 2026

AI Review - Attempt 1/3

Image Description

The plot displays a Campbell Diagram with 5 natural frequency mode curves plotted against Rotational Speed (RPM) on the x-axis and Frequency (Hz) on the y-axis. The mode curves are: 1st Bending (blue, ~18 Hz, rising slightly), 2nd Bending (orange, ~45 Hz, falling slightly), 1st Torsional (green, ~62 Hz, nearly flat), Axial (purple, ~78 Hz, falling slightly), and 3rd Bending (brown, ~95 Hz, rising slightly). Three gray dashed engine order lines (1x, 2x, 3x) radiate from the origin with increasing slopes. Red circular markers with white edges highlight critical speed intersections where engine order lines cross mode curves. The title reads "campbell-basic · matplotlib · pyplots.ai". Top and right spines are removed, with a subtle y-axis grid. A 9-item legend sits in the upper-left corner covering some of the data area.

Quality Score: 79/100

Criteria Checklist

Visual Quality (25/30)

  • VQ-01: Text Legibility (8/8) - All font sizes explicitly set: title 24pt, labels 20pt, ticks 16pt, legend 14pt
  • VQ-02: No Overlap (6/6) - No overlapping text elements
  • VQ-03: Element Visibility (5/6) - Lines at linewidth=3 and markers at s=250 are good; EO lines could be slightly more distinct
  • VQ-04: Color Accessibility (4/4) - Blue/orange/green/purple/brown palette is colorblind-safe; gray dashed EO lines provide additional distinction
  • VQ-05: Layout & Canvas (0/4) - Legend with 9 entries is oversized and covers the upper-left data area, partially obscuring the 3rd Bending and Axial mode curves in that region
  • VQ-06: Axis Labels & Title (2/2) - "Rotational Speed (RPM)" and "Frequency (Hz)" with proper units

Design Excellence (10/20)

  • DE-01: Aesthetic Sophistication (4/8) - Custom color palette, gray dashed EO lines, red markers with white edges — looks like a well-configured default but not publication-grade
  • DE-02: Visual Refinement (4/6) - Top/right spines removed, subtle y-grid (alpha=0.2), tight_layout; good but not exceptional
  • DE-03: Data Storytelling (2/6) - Data displayed without emphasis on which intersections are most critical; no operating range shading or annotations to guide the viewer

Spec Compliance (14/15)

  • SC-01: Plot Type (5/5) - Correct Campbell Diagram with all required components
  • SC-02: Required Features (3/4) - Mode curves, EO lines, critical speed markers, mode labels, EO labels all present; legend does not clearly separate modes from EO lines visually
  • SC-03: Data Mapping (3/3) - X=RPM, Y=Hz correctly mapped
  • SC-04: Title & Legend (3/3) - Title format correct, legend labels match data

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) - 5 modes with varying speed-dependent behavior, 3 engine orders, multiple intersections; gyroscopic effects are present but subtle
  • DQ-02: Realistic Context (5/5) - Realistic rotordynamics scenario with proper mode shape names and frequency ranges
  • DQ-03: Appropriate Scale (4/4) - 0-6000 RPM, 18-95 Hz range appropriate for rotating machinery

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) - Linear flow: imports → data → plot → save
  • CQ-02: Reproducibility (2/2) - Fully deterministic data from formulas
  • CQ-03: Clean Imports (2/2) - Only matplotlib.pyplot and numpy
  • CQ-04: Code Elegance (2/2) - Clean intersection-finding logic, appropriate complexity
  • CQ-05: Output & API (1/1) - Saves as plot.png, no deprecated functions

Library Mastery (6/10)

  • LM-01: Idiomatic Usage (4/5) - Good Axes API usage, proper zorder layering for visual depth
  • LM-02: Distinctive Features (2/5) - Zorder layering is somewhat distinctive, but overall generic line/scatter plotting

Strengths

  • Correct and complete Campbell Diagram with all key components (mode curves, EO lines, critical speed markers)
  • Clean, deterministic data generation with realistic rotordynamics context and proper mode shape naming
  • Good use of zorder for visual layering (modes on top of EO lines, markers on top of everything)
  • Smart intersection-finding algorithm using sign changes with linear interpolation
  • Proper explicit font sizing throughout, following matplotlib library rules exactly

Weaknesses

  • Legend is too large (9 entries) and placed in upper-left where it covers mode curves; consider placing it outside the plot or using a more compact layout
  • No visual storytelling — critical speed intersections are marked but there's no emphasis on which are most significant (e.g., operating range shading, annotation of the most dangerous crossings)
  • Mode curves have very subtle speed-dependent variation (slopes ±0.0003-0.0008), making the diagram look like mostly horizontal lines with diagonal EO lines; more pronounced gyroscopic effects would make the diagram more visually interesting and educational
  • EO line labels ("1x", "2x", "3x") could be positioned more carefully to avoid visual clutter near the plot edge

Verdict: REJECTED

@github-actions github-actions Bot added quality:79 Quality score 79/100 ai-rejected Quality not OK, triggers update labels Feb 15, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Feb 15, 2026
Attempt 1/3 - fixes based on AI review
@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 Feb 15, 2026

AI Review - Attempt 2/3

Image Description

The plot displays a Campbell Diagram with rotational speed (0–6000 RPM) on the x-axis and frequency (0–110 Hz) on the y-axis. Five natural frequency mode curves are plotted: 1st Bending (blue, rising), 2nd Bending (orange, declining), 1st Torsional (green, nearly flat ~62 Hz), Axial (purple, declining), and 3rd Bending (brown/dark orange, rising then flattening). Three dashed gray engine order lines (1×, 2×, 3×) radiate diagonally from the origin. Critical speed intersections outside the operating range are shown as faded pink circles, while those inside the operating range (2500–4500 RPM, shaded light blue with dotted vertical boundaries) are emphasized with larger red diamond markers. Annotations in dark red bordered boxes label the critical modes in the operating range: "3rd Bending," "2nd Bending," "1st Torsional," and "Axial." A comprehensive legend is positioned outside the plot to the right, listing all mode curves, engine order lines, critical speed markers, and the operating range. The title reads "campbell-basic · matplotlib · pyplots.ai." The overall layout is clean with subtle gridlines and removed top/right spines.

Quality Score: 87/100

Criteria Checklist

Visual Quality (26/30)

  • VQ-01: Text Legibility (8/8) - All font sizes explicitly set: title 24, labels 20, ticks 16, legend 13, annotations 11-14. All perfectly readable.
  • VQ-02: No Overlap (5/6) - The "1st Torsional" and "Axial" annotations are very close together near 60-63 Hz around 3500-3800 RPM, creating near-overlap.
  • VQ-03: Element Visibility (6/6) - Lines well-sized at 2.8 lw, markers appropriately differentiated (200 outside, 350 inside operating range).
  • VQ-04: Color Accessibility (3/4) - Generally good palette, but green (#4DAF4A) and orange (#E8833A) may be challenging for some deuteranopia cases.
  • VQ-05: Layout Balance (2/4) - External legend consumes significant right-side space (right margin at 0.78). Plot area is about 50-55% of canvas width.
  • VQ-06: Axis Labels & Title (2/2) - "Rotational Speed (RPM)" and "Frequency (Hz)" with units.

Design Excellence (16/20)

  • DE-01: Aesthetic Sophistication (6/8) - Strong design with custom palette, intentional visual hierarchy (faded vs emphasized markers), operating range shading, clean spine removal. Clearly above defaults but not quite publication-level polish.
  • DE-02: Visual Refinement (5/6) - Refined spine styling (#555555, 0.6 lw), very subtle differentiated grid (y alpha 0.15, x alpha 0.08). Minor annotation crowding in operating range.
  • DE-03: Data Storytelling (5/6) - Excellent narrative: operating range shading immediately draws the eye to the danger zone, diamond vs circle markers differentiate operational risk, annotations identify at-risk modes. Viewer instantly understands which resonances matter.

Spec Compliance (14/15)

  • SC-01: Plot Type (5/5) - Correct Campbell Diagram with frequency vs rotational speed.
  • SC-02: Required Features (3/4) - All major features present (5 modes, 3 EO lines, critical markers, labels, legend). The spec's optional critical speed zone shading around individual intersections is not implemented.
  • SC-03: Data Mapping (3/3) - X=RPM, Y=Hz correctly mapped. Engine order slopes = order/60.
  • SC-04: Title & Legend (3/3) - Title format correct. Legend comprehensive with all element categories.

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) - Shows forward whirl, backward whirl, flat torsional, and mixed modes. Multiple EO crossings visible. Some modes (1st Torsional, Axial) are close in frequency, reducing visual separation.
  • DQ-02: Realistic Context (5/5) - Authentic rotordynamic scenario with proper mode nomenclature, realistic RPM range, and plausible frequencies.
  • DQ-03: Appropriate Scale (4/4) - Frequencies 18-100 Hz, operating range 2500-4500 RPM — all realistic for industrial rotating machinery.

Code Quality (9/10)

  • CQ-01: KISS Structure (3/3) - Clean imports → data → plot → save flow, no functions or classes.
  • CQ-02: Reproducibility (2/2) - All data is deterministic (mathematical formulas, no random components).
  • CQ-03: Clean Imports (2/2) - All imports used: matplotlib.pyplot, numpy, Line2D (legend handles), Patch (legend entry).
  • CQ-04: Code Elegance (1/2) - Well-structured but verbose annotation logic with alternating directions and manual angle calculations. Not over-engineered, but could be cleaner.
  • CQ-05: Output & API (1/1) - Saves as plot.png, dpi=300, bbox_inches='tight'. No deprecated functions.

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (4/5) - Good idiomatic matplotlib: axes methods throughout, custom legend with Line2D/Patch, annotate with arrowprops/bbox, axvspan, subplots_adjust.
  • LM-02: Distinctive Features (4/5) - Uses distinctly matplotlib features: custom legend handles (Line2D, Patch), annotate with rotation_mode='anchor', axvspan shading, fine spine control.

Strengths

  • Excellent data storytelling through the operating range shading and differentiated critical speed markers (faded circles vs emphasized diamonds)
  • Comprehensive, well-organized legend that clearly distinguishes all element types (modes, EO lines, critical speeds, operating range)
  • Engine order labels positioned along their lines with correct rotation angles, using white background boxes for readability
  • Realistic rotordynamic data with proper mode naming and physically plausible frequency behavior (gyroscopic effects)
  • Clean visual hierarchy with subtle gridlines, refined spines, and intentional color choices

Weaknesses

  • The "1st Torsional" and "Axial" critical speed annotations in the operating range are very close together (~60-63 Hz), risking visual overlap — consider increasing vertical offset separation between them
  • Layout balance could be improved: the external legend takes ~22% of canvas width, compressing the plot area — consider placing the legend below the plot or making it more compact
  • The green (1st Torsional) and orange (2nd Bending) colors could be better distinguished for deuteranopia accessibility — consider using a more blue-shifted alternative for one of them

Verdict: REJECTED

@github-actions github-actions Bot added quality:87 Quality score 87/100 ai-rejected Quality not OK, triggers update labels Feb 15, 2026
@github-actions github-actions Bot added ai-attempt-2 Second repair attempt and removed ai-rejected Quality not OK, triggers update labels Feb 15, 2026
Attempt 2/3 - fixes based on AI review
@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 Feb 15, 2026

AI Review - Attempt 3/3

Image Description

The plot displays a Campbell Diagram with 5 natural frequency mode curves plotted against rotational speed (0–6000 RPM) on the x-axis and frequency (0–120 Hz) on the y-axis. The mode curves are: 1st Bending (dark blue, rising gently then leveling), 2nd Bending (orange, declining slightly), 1st Torsional (cyan, nearly flat ~58 Hz), Axial (purple, declining), and 3rd Bending (brown, rising then flattening). Three gray dashed engine order lines (1×, 2×, 3×) radiate from the origin with rotated labels. Critical speed intersections outside the operating range are shown as semi-transparent red circles (about 10 markers), while intersections inside the operating range (2500–4500 RPM, shaded light blue with dotted vertical boundaries) are displayed as large red diamond markers with labeled annotations connected by thin lines (2nd Bending, 3rd Bending, 1st Torsional, Axial). An italic "Operating Range" label sits near the bottom of the shaded region. A comprehensive legend in the upper left lists all 9 element types. Top and right spines are removed, subtle grid lines are present, and the title reads "campbell-basic · matplotlib · pyplots.ai".

Quality Score: 88/100

Criteria Checklist

Visual Quality (27/30)

  • VQ-01: Text Legibility (8/8) - All font sizes explicitly set: title 24pt, axis labels 20pt, ticks 16pt, legend 12pt, annotations 11-14pt
  • VQ-02: No Overlap (5/6) - Minor proximity between "1st Torsional" and "Axial" annotations in operating range; not severely overlapping but close
  • VQ-03: Element Visibility (6/6) - Line widths 2.8 for modes, markers s=200/350 for critical speeds, well-adapted to data density
  • VQ-04: Color Accessibility (4/4) - Blue, orange, cyan, purple, brown palette; no red-green as sole distinguisher
  • VQ-05: Layout Balance (2/4) - Large 9-item legend in upper left covers data area; some lost space
  • VQ-06: Axis Labels & Title (2/2) - "Rotational Speed (RPM)" and "Frequency (Hz)" with units

Design Excellence (15/20)

  • DE-01: Aesthetic Sophistication (6/8) - Custom palette, intentional visual hierarchy with operating range shading and differentiated marker styles; clearly above defaults
  • DE-02: Visual Refinement (5/6) - Top/right spines removed, subtle grid with differentiated x/y alpha, spine colors customized, generous whitespace
  • DE-03: Data Storytelling (4/6) - Good visual hierarchy: operating range highlighted, critical speeds inside emphasized with large diamonds + annotations vs. small faded circles outside; viewer quickly sees where dangerous resonances lie

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) - Correct Campbell Diagram with natural frequency curves overlaid on engine order excitation lines
  • SC-02: Required Features (4/4) - All spec features present: 5 modes, 3 engine orders, critical speed markers, mode labels, EO labels, clean legend, operating range shading
  • SC-03: Data Mapping (3/3) - X=RPM, Y=Hz; engine order slopes correctly computed as order/60
  • SC-04: Title & Legend (3/3) - Title format "campbell-basic · matplotlib · pyplots.ai" correct; legend labels accurately describe all element types

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) - 5 modes with varied behaviors (rising, falling, flat) demonstrating gyroscopic effects; multiple EO crossings at different frequencies
  • DQ-02: Realistic Context (5/5) - Authentic rotordynamics scenario with plausible mode names, frequency ranges, and operating RPM band
  • DQ-03: Appropriate Scale (4/4) - Realistic values: 18–92 Hz base frequencies, 0–6000 RPM range, 2500–4500 RPM operating range

Code Quality (9/10)

  • CQ-01: KISS Structure (3/3) - Linear imports → data → plot → save structure, no functions/classes
  • CQ-02: Reproducibility (2/2) - Fully deterministic data (mathematical functions, no randomness)
  • CQ-03: Clean Imports (2/2) - All imports used: plt, np, Line2D for legend handles, Patch for operating range handle
  • CQ-04: Code Elegance (1/2) - Clean overall but the annotation spread logic and intersection-finding algorithm add moderate complexity
  • CQ-05: Output & API (1/1) - Saves as plot.png with dpi=300

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (5/5) - Proper Axes-level API throughout, annotate with arrowprops/textcoords, axvspan/axvline, scatter with distinct markers
  • LM-02: Distinctive Features (3/5) - Custom legend via proxy artists (Line2D, Patch), annotate with rotation_mode="anchor", axvspan shading — distinctly matplotlib patterns

Strengths

  • Excellent spec compliance: all required features implemented including optional operating range shading
  • Strong data storytelling through visual differentiation of critical speeds inside vs. outside operating range (diamond vs. circle markers, opacity contrast, labeled annotations)
  • Realistic rotordynamics data with physically plausible mode behaviors and frequencies
  • Clean visual design with removed spines, subtle grid, and custom color palette
  • Well-constructed custom legend that clearly explains all 9 element types

Weaknesses

  • Legend is large (9 items) and positioned in the upper-left corner where it covers some data area; could use a more compact layout or external positioning
  • Annotation labels for critical speeds inside the operating range are close together, particularly "1st Torsional" and "Axial" around 58-65 Hz at 3500-4000 RPM
  • Code complexity could be slightly reduced in the intersection-finding and annotation-spreading sections

Verdict: APPROVED

@github-actions github-actions Bot added quality:88 Quality score: 88/100 ai-rejected Quality not OK, triggers update labels Feb 15, 2026
@github-actions github-actions Bot added ai-attempt-3 Third/final repair attempt and removed ai-rejected Quality not OK, triggers update labels Feb 15, 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 Feb 15, 2026

AI Review - Attempt 3/3

Image Description

The plot displays a Campbell Diagram with 5 natural frequency mode curves (1st Bending in dark blue, 2nd Bending in orange, 1st Torsional in cyan, Axial in purple, 3rd Bending in brown) plotted against rotational speed from 0 to 6,000 RPM on the x-axis and frequency from 0 to 120 Hz on the y-axis. Three dashed gray engine order lines (1×, 2×, 3×) extend diagonally from the origin with rotated labels on white background boxes. A light blue shaded band marks the operating range (2,500–4,500 RPM) with dotted vertical boundary lines and an italic "Operating Range" label at the bottom. Critical speed intersections outside the operating range appear as semi-transparent red circles, while those inside appear as larger red diamond markers with annotated mode labels in red-bordered boxes connected by arrow lines. End-of-line mode labels in bold matching colors appear at the right edge with vertical de-collision. The title reads "campbell-basic · matplotlib · pyplots.ai" in medium weight. A two-column legend in the upper-left distinguishes all element types. Top and right spines are removed, subtle grids are applied, and the x-axis uses thousand separators.

Quality Score: 90/100

Criteria Checklist

Visual Quality (27/30)

  • VQ-01: Text Legibility (8/8) - All font sizes explicitly set: title 24pt, labels 20pt, ticks 16pt, legend 11pt, annotations 10-14pt
  • VQ-02: No Overlap (5/6) - De-collision logic for end-of-line labels works well; "Axial" and "1st Torsional" right-edge labels are close but readable; minor tightness in operating range annotations
  • VQ-03: Element Visibility (6/6) - Line widths of 2.8 well-suited; critical markers appropriately sized (s=200/350); engine order lines visible but subdued
  • VQ-04: Color Accessibility (4/4) - Blue, orange, cyan, purple, brown palette is colorblind-distinguishable; no red-green sole distinction
  • VQ-05: Layout & Canvas (3/4) - Good canvas utilization; right-edge labels extend slightly beyond plot; legend is somewhat large but not blocking data
  • VQ-06: Axis Labels & Title (2/2) - "Rotational Speed (RPM)" and "Frequency (Hz)" with units

Design Excellence (16/20)

  • DE-01: Aesthetic Sophistication (7/8) - Near publication-ready: custom palette, rotated EO labels with white boxes, differentiated critical speed markers, tasteful operating range shading
  • DE-02: Visual Refinement (5/6) - Subtle grids (y alpha=0.15, x alpha=0.08), spines removed/thinned, generous whitespace, operating range shading is elegant
  • DE-03: Data Storytelling (4/6) - Clear visual hierarchy: diamond markers + annotations emphasize critical speeds in operating range vs translucent circles outside; viewer immediately sees engineering risk zones

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) - Correct Campbell Diagram with frequency vs RPM overlay
  • SC-02: Required Features (4/4) - All spec features: 5 modes, 3 engine orders, critical speed markers, mode/EO labels, legend, operating range shading
  • SC-03: Data Mapping (3/3) - X=RPM, Y=Hz correctly assigned
  • SC-04: Title & Legend (3/3) - Title format correct; comprehensive legend with all element types

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) - Shows modes with varied gyroscopic behavior (increasing, decreasing, flat); both in-range and out-of-range critical speeds visible
  • DQ-02: Realistic Context (5/5) - Authentic rotordynamics scenario with standard engineering mode names and realistic frequency/RPM ranges
  • DQ-03: Appropriate Scale (4/4) - Baseline frequencies 18-92 Hz and 0-6000 RPM are realistic for rotating machinery

Code Quality (9/10)

  • CQ-01: KISS Structure (3/3) - Flat script: imports → data → plot → save
  • CQ-02: Reproducibility (2/2) - Deterministic data from formulas, no randomness
  • CQ-03: Clean Imports (1/2) - All imports used; minor verbosity importing from separate matplotlib submodules
  • CQ-04: Code Elegance (2/2) - Clean intersection-finding with linear interpolation; Pythonic loops
  • CQ-05: Output & API (1/1) - Saves as plot.png, dpi=300, bbox_inches='tight'

Library Mastery (9/10)

  • LM-01: Idiomatic Usage (5/5) - Axes methods throughout, FuncFormatter, axvspan, proper tight_layout
  • LM-02: Distinctive Features (4/5) - Custom legend with Line2D/Patch handles, FuncFormatter for thousands, rotation_mode="anchor", axvspan — distinctively matplotlib

Strengths

  • Excellent differentiation between critical speeds inside vs outside operating range using marker shape, size, opacity, and annotation styling — creates strong visual hierarchy
  • Sophisticated end-of-line label de-collision algorithm prevents overlap at the right edge
  • Rotated engine order labels with white background boxes are elegant and readable
  • Operating range shading with dotted boundaries is tasteful and informative
  • Linear interpolation for finding exact intersection points is mathematically sound
  • Comprehensive two-column legend covers all visual elements without cluttering

Weaknesses

  • Right-edge mode labels for "Axial" and "1st Torsional" are vertically close despite de-collision logic — the minimum gap could be slightly larger
  • Legend font size (11pt) is smaller than the recommended 16pt in library rules, though appropriate given 9 legend entries
  • CQ-03: imports from three separate matplotlib submodules (lines, patches, ticker) adds minor verbosity

Verdict: APPROVED

@github-actions github-actions Bot added quality:90 Quality score 90/100 ai-approved Quality OK, ready for merge labels Feb 15, 2026
@github-actions github-actions Bot merged commit 5f00b9f into main Feb 15, 2026
3 checks passed
@github-actions github-actions Bot deleted the implementation/campbell-basic/matplotlib branch February 15, 2026 21:36
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:79 Quality score 79/100 quality:87 Quality score 87/100 quality:88 Quality score: 88/100 quality:90 Quality score 90/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants