File size: 14,767 Bytes
58e6885
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
You are refactoring a single JavaScript (typically D3.js) function for data visualization. Your goal is to improve its organization, enforce strict configuration adherence, standardize practices, streamline code, and meet specific output constraints, while **preserving the core visual output and functionality of the original chart when provided with valid data**. Apply directives meticulously.

**I. Input Code Assumptions:**
*   Input: a single JavaScript function, typically named `makeChart(containerSelector, data)`.
*   The `data` argument is an object usually structured as:
    *   `jsonData = data;` (or simply use `data` directly)
    *   `chartData = data.data.data;` (array of data points)
    *   `variables = data.variables || {};` (chart-specific settings)
    *   `typography = data.typography || {};` The `typography` object is expected to have the following structure if present:
        ```json
        {
            "title": { "font_family": "Arial, sans-serif", "font_size": "16px", "font_weight": "bold" },
            "label": { "font_family": "Arial, sans-serif", "font_size": "12px", "font_weight": "normal" },
            "annotation": { "font_family": "Arial, sans-serif", "font_size": "10px", "font_weight": "normal" }
        }
        ```
        If `data.typography` is not provided or is missing keys, the chart should use sensible hardcoded defaults for font properties.
    *   `colors = data.colors || {};` (or `data.colors_dark || {}` for dark themes). The `colors` object is expected to have the following structure if present:
        ```json
        {
            "field": { "Category1": "#1f77b4", "Category2": "#ff7f0e" },
            "other": { "primary": "#1f77b4", "secondary": "#ff7f0e" },
            "available_colors": ["#1f77b4", "#ff7f0e", "#2ca02c"],
            "background_color": "#FFFFFF",
            "text_color": "#0f223b"
        }
        ```
        If `data.colors` (or `data.colors_dark`) is not provided or is missing keys, the chart should use sensible hardcoded default colors (e.g., a default `text_color`, a default `primary` color, or a categorical color scheme like `d3.schemeCategory10` if `available_colors` or `field` mappings are missing).
    *   `images = data.images || {};` The `images` object is expected to have the following structure if present (URLs can be data URIs):
        ```json
        {
            "field": { "France": "data:image/svg+xml;base64,...", "Germany": "data:image/svg+xml;base64,..." },
            "other": { "primary": "data:image/svg+xml;base64,..." }
        }
        ```
        If `data.images` is not provided or is missing keys, image elements should not be rendered or should use a placeholder if absolutely critical and a default placeholder makes sense.
    *   `dataColumns = data.data.columns || [];` (definitions for data fields, roles, and units)
*   The `/* REQUIREMENTS_BEGIN ... REQUIREMENTS_END */` block (detailed in Section XII) **MUST** be placed immediately before the JavaScript function. It should not be part of the function\'s internal comments.

**II. Code Reorganization (Internal Structure):**
1.  **Mandatory Logical Blocks:** Restructure into these sequential, commented blocks. If not applicable, note with a comment.
    *   `// Block 0: Metadata & Other Function-Level Comments (The /* REQUIREMENTS_BEGIN... */ block is now external to the function)`
    *   `// Block 1: Configuration Parsing & Validation`
        *   Extract `chartData`, `variables`, `typography`, `colors`, `images`, `dataColumns` from the input `data` object as described in Section I.
        *   Determine critical field names (e.g., `xField`, `yField`, `groupField`) and their units from `dataColumns` based on roles (e.g., `col.role === "x"`).
        *   Perform critical identifier validation (see Section VI.3).
        *   Clear the `containerSelector` (e.g., `d3.select(containerSelector).html("");`).
    *   `// Block 2: Style Configuration & Helper Definitions`
    *   `// Block 3: Initial SVG Setup & Global Utilities Definition`
    *   `// Block 4: Core Chart Dimensions & Layout Calculation`
    *   `// Block 5: Data Preprocessing & Transformation`
    *   `// Block 6: Scale Definition & Configuration`
    *   `// Block 7: Chart Component Rendering (e.g., Axes, Gridlines, Legend - NO Main Titles/Subtitles)`
    *   `// Block 8: Main Data Visualization Rendering (e.g., Bars, Lines, Points, Areas)`
    *   `// Block 9: Optional Enhancements & Post-Processing (e.g., Annotations, Icons, Interactive Elements)`
    *   `// Block 10: Cleanup & SVG Node Return`
2.  **Helper Function Placement:** Group internal helpers (text measurement, color math, path generation) in `// Block 2`, or just before first dominant use if highly block-specific.

**III. SVG Element & Utility Setup (Primarily Block 2 & 3):**
1.  **SVG Root (Block 3):**
    *   **Fixed Dimensions:**
        *   The main SVG element **MUST** be appended to `containerSelector`.
        *   The `width` and `height` attributes of the main SVG element **MUST** be set to absolute pixel values derived from `variables.width` and `variables.height` (e.g., `svg.attr(\'width\', variables.width || 800).attr(\'height\', variables.height || 600)`).
        *   The main SVG element **MUST NOT** have a `viewBox` attribute.
        *   Responsive attributes such as `width="100%"` or `height="auto"` **MUST NOT** be used. The chart dimensions must be precise and fixed.
2.  **In-Memory Text Measurement (Helper in Block 2):**
    *   The `estimateTextWidth` utility (or similar) **MUST** use an in-memory SVG structure.
    *   This temporary SVG **MUST NOT** be appended to the document DOM.
    *   *Example:* `document.createElementNS('http://www.w3.org/2000/svg', 'svg')`, append text, style, measure with `getBBox().width`, then discard.

**IV. Centralized Style Configuration (Block 2):**
1.  **Style Token Object:**
    *   Populate a `fillStyle` object (or similar) by mapping semantic tokens (e.g., `barPrimary`, `gridSubtle`, `axisLine`) to actual color values.
    *   Color values **MUST** be sourced primarily from the `colors` object (extracted from `data.colors` or `data.colors_dark`, structured as per Section I). For example:
        *   `fillStyle.barCategoryColor = colors.field && colors.field[categoryName] ? colors.field[categoryName] : (colors.available_colors ? colors.available_colors[i % colors.available_colors.length] : '#defaultCategoryColor');`
        *   `fillStyle.primaryAccent = colors.other && colors.other.primary ? colors.other.primary : '#defaultPrimaryAccent';`
        *   `fillStyle.chartBackground = colors.background_color || '#FFFFFF';`
    *   Image URLs for use with `xlink:href` (e.g., for icons or image fills) **MUST** be sourced from the `images` object (extracted from `data.images`, structured as per Section I). These can also be organized within `fillStyle` if appropriate (e.g., `fillStyle.iconUrl = images.field && images.field[itemName] ? images.field[itemName] : (images.other && images.other.primary ? images.other.primary : null);`). If an image is not found for a specific key, the corresponding image element should typically not be rendered, or a non-image fallback (e.g., text) should be used.
    *   Avoid hardcoded style values outside `fillStyle` definitions in `// Block 2` unless they are true, unconfigurable defaults as last resort.
2.  **Typography Tokens:**
    *   Define `fillStyle.typography` by sourcing values from the `typography` object (extracted from `data.typography`, structured as per Section I). Example:
        *   `fillStyle.typography.titleFontFamily = typography.title && typography.title.font_family ? typography.title.font_family : 'Arial, sans-serif';`
        *   `fillStyle.typography.labelFontSize = typography.label && typography.label.font_size ? typography.label.font_size : '12px';`
        *   `fillStyle.typography.annotationFontWeight = typography.annotation && typography.annotation.font_weight ? typography.annotation.font_weight : 'normal';`
    *   All text elements **MUST** use these tokens for font properties (family, size, weight). Text color **MUST** be sourced from `colors.text_color` (via `fillStyle.textColor = colors.text_color || '#defaultTextColor';`) or a more specific semantic color from `fillStyle` if appropriate (e.g., an axis label might use a general text color, while a data value label inside a bar might use a contrasting color).
    *   No inline numeric font sizes or hardcoded font families/weights outside `fillStyle.typography` definitions, unless they are true, unconfigurable defaults as a last resort.
3.  **Usage:** Access via `fillStyle.tokenName` or `fillStyle.typography.tokenName`. Omit unused optional tokens.

**V. Chart Content Restrictions:**
1.  **No Main Titles/Subtitles:** Code **MUST NOT** render main chart titles/subtitles. Remove existing logic for this (affects `// Block 7` and `// Block 8` primarily).
2.  **No Complex Visual Effects:** Remove all gradients, patterns, shadows, and other complex visual effects. Keep the chart styling clean and simple with solid colors only.
3.  **Configuration Simplification:**
    *   Remove conditional logic for optional visual effects and minor, non-standard configurations (e.g., `variables.has_rounded_corners`).
    *   Retain only essential, unconditionally applied styling. The goal is to standardize and streamline, not to support every possible variation via `variables`.

**VI. Error Handling & Configuration Dependency:**
1.  **Error Traps:** Remove `try...catch` for individual data points in loops.
2.  **Data Value Checks:** Avoid explicit `isNaN()` or `typeof value !== 'number'` before D3 scale/attribute usage.
3.  **Configured Identifiers & Labels:**
    *   Data accessor keys (field names) **MUST** be derived from `data.data.columns` (e.g., `const valueField = dataColumns.find(col => col.role === "y").name;`).
    *   **No Hardcoded Fallbacks** for data accessor keys or essential labels/titles expected from `variables` or `dataColumns`.
    *   **Critical Identifier Validation (Block 1 - Early Exit):** If critical fields derived field names from `data.data.columns` for data access/scales are `undefined` or missing:
        1. `console.error("Critical chart config missing: [specific missing field names]. Cannot render.");`
        2. If `containerSelector`, update DOM: `d3.select(containerSelector).html("<div style='color:red;'>...Error...</div>");`
        3. `return null;`
    *   **Non-Critical Text:** If optional `config` text (e.g., `columnTitleText`) is `undefined`/empty, skip rendering that element. Utilities handle `undefined`/empty `textContent` gracefully (no "undefined" text).

**VII. Standardized Class Attributes:**
*   On SVG element creation, **MUST** add `class` with a standard role: `value`, `label`, `text`, `icon`, `image`, `mark`, `axis` (e.g. `axis x-axis`), `other`.
*   Apply to main group for complex components (e.g., `xAxisGroup.attr("class", "axis x-axis")`).

**VIII. Variable Naming Standardization (Examples):**
`config`, `chartDataArray`, `svgRoot`, `mainChartGroup`, `barElements`, `xAxisGroup`, `xScale`, `yScale`, `colorScale`, `chartMargins = { top: ..., ... }`, `containerWidth`, `containerHeight`, `innerWidth`, `innerHeight`, `categoryFieldName`, `category = d[categoryFieldName]`. Iterators: `d`, `i`. Helpers: `calculateScales()`.

**IX. Commenting Style:**
*   Use mandated block comments (Section II.1).
*   Preserve essential comments for complex/non-obvious logic. Focus on "why," not "what," if clear. Avoid over-commenting.

**X. Visual/Behavioral Defaults:**
*   May retain sensible visual (e.g., `defaultBarColor`) or behavioral defaults if not masking data issues.

**XI. Code Simplification & Conciseness:**
1.  Reduce line count if functionality and readability are preserved.
2.  Consolidate redundant code/utilities.
3.  Employ concise, efficient coding style.

**XII. Metadata Requirements Block (JSON in `/* REQUIREMENTS_BEGIN ... */`):**
This entire block, starting with `/* REQUIREMENTS_BEGIN` and ending with `REQUIREMENTS_END */`, **MUST** be placed as a comment block *immediately before* the JavaScript function that is being refactored. It **MUST NOT** be inside the function body.

1.  The block **MUST** contain the exact JSON structure and keys provided below.
2.  Populate each of the enumerated properties (e.g., `elementAlignment`, `xAxis`) with **one** value that best describes the final rendered chart. Values **MUST** come from their respective option lists (shown as comments in the template below) exactly as spelled (case-sensitive). Use `"none"` or the most appropriate default if a feature is not explicitly implemented.
3.  Do **NOT** insert additional keys or comments *within* the JSON object itself, beyond the example values. The surrounding `/* REQUIREMENTS_BEGIN` and `REQUIREMENTS_END */` delimiters must remain unchanged.

    ```json
    {
      "chart_type": "Grouped Circular Bar Chart",
      "chart_name": "grouped_circular_bar_chart_01",
      "is_composite": false,
      "required_fields": ["x", "y", "group"],
      "hierarchy": ["group"],
      "required_fields_type": [["categorical"], ["numerical"], ["categorical"]],
      "required_fields_range": [[2, 20], [0, "inf"], [2, 5]],
      "required_fields_icons": ["group"],
      "required_other_icons": [],
      "required_fields_colors": ["group"],
      "required_other_colors": ["primary"],
      "min_height": 400,
      "min_width": 400,
      "background": "no",

      "elementAlignment": "none",            // One of: left | center | right | top | bottom
      "xAxis": "none",                        // One of: visible | minimal | none
      "yAxis": "none",                        // One of: visible | minimal | none
      "gridLineType": "none",                // One of: subtle | prominent | none
      "legend": "none",                       // One of: normal | compact | detailed | none
      "dataLabelPosition": "none",            // One of: outside | inside | center_element | auto | none
      "artisticStyle": "clean",               // One of: clean | hand_drawn | gradient_gloss | shadow
      "valueSortDirection": "none",           // One of: ascending | descending | none
      "iconographyUsage": "none"              // One of: none | categorical_markers_overlay_internal | categorical_markers_overlay_edge | element_replacement | background_contextual | adjacent_indicator
    }
    ```

**XIII. Output:**
*   The refactored single JavaScript function, named `makeChart`.
*   The function **MUST** remain functional with valid and complete configuration provided via the `data` object (structured as per Section I), preserving the original chart's core visual output.