001package com.studentgui.tools;
002
003import java.nio.file.Path;
004import java.time.LocalDate;
005import java.time.format.DateTimeFormatter;
006import java.util.ArrayList;
007import java.util.List;
008
009import com.studentgui.apphelpers.Helpers;
010import com.studentgui.apppages.JLineGraph;
011
012/**
013 * Automated smoke test for grouped chart rendering and multi-panel PNG export.
014 *
015 * <p>Verifies that {@link JLineGraph} correctly renders multiple stacked phase-grouped
016 * charts (as used by assessment pages like Braille, Abacus, etc.). Generates synthetic
017 * data with explicit phase prefixes (P1, P2, P3) and exports to PNG.</p>
018 *
019 * <p><b>Purpose:</b></p>
020 * <ul>
021 *   <li>Validates phase grouping logic in {@link JLineGraph#updateWithGroupedData}</li>
022 *   <li>Ensures each group renders as a separate stacked chart panel</li>
023 *   <li>Verifies PNG export of multi-chart layouts</li>
024 *   <li>Provides visual reference for chart appearance during development</li>
025 * </ul>
026 *
027 * <p><b>Usage:</b></p>
028 * <pre>{@code
029 * java -cp StudentDataGUI.jar com.studentgui.tools.GroupedSmoke
030 * }</pre>
031 *
032 * <p><b>Expected Output:</b></p>
033 * <pre>
034 * Grouped smoke wrote chart to: /path/to/app_home/StudentDataFiles/Grouped_Smoke/plots/GroupedSmoke-2024-01-15.png
035 * Exists: true
036 * </pre>
037 *
038 * <p><b>Test Data Structure:</b></p>
039 * <ul>
040 *   <li><b>Part codes:</b> 9 codes with prefixes: P1 (3 items), P2 (2 items), P3 (4 items)</li>
041 *   <li><b>Sessions:</b> 3 synthetic sessions with deterministic scores {@code (i + s) % 5}</li>
042 *   <li><b>Expected output:</b> 3 stacked chart panels (one per phase group) in a single 800×600px PNG</li>
043 * </ul>
044 *
045 * <p><b>Output Location:</b> {@code app_home/StudentDataFiles/Grouped_Smoke/plots/GroupedSmoke-<ISO_DATE>.png}</p>
046 *
047 * <p><b>Validation:</b> Inspect the generated PNG to verify:</p>
048 * <ol>
049 *   <li>Three distinct chart panels labeled "P1 - 3 items", "P2 - 2 items", "P3 - 4 items"</li>
050 *   <li>Each panel shows 3 line series (2 gray historical, 1 black latest)</li>
051 *   <li>Colored background bands visible in all panels</li>
052 * </ol>
053 *
054 * @see com.studentgui.apppages.JLineGraph#updateWithGroupedData
055 * @see com.studentgui.apppages.JLineGraph#saveChart
056 */
057public class GroupedSmoke {
058    /**
059     * Entry point for the grouped smoke utility.
060     *
061     * @param args ignored
062     * @throws Exception on unexpected IO or charting errors
063     */
064    public static void main(final String[] args) throws Exception {
065        Helpers.createFolderHierarchy();
066        JLineGraph graph = new JLineGraph();
067
068        // build part codes with P1_, P2_, P3_ groups (3+2+4 items)
069        String[] codes = new String[]{"P1_1","P1_2","P1_3","P2_1","P2_2","P3_1","P3_2","P3_3","P3_4"};
070
071        // Create sample data: 3 sessions
072        List<List<Integer>> data = new ArrayList<>();
073        for (int s = 0; s < 3; s++) {
074            List<Integer> row = new ArrayList<>();
075            for (int i = 0; i < codes.length; i++) {
076                row.add((i + s) % 5);
077            }
078            data.add(row);
079        }
080        graph.updateWithGroupedData(data, codes);
081
082        Path outDir = Helpers.APP_HOME.resolve("StudentDataFiles").resolve(Helpers.safeName("Grouped Smoke")).resolve("plots");
083        java.nio.file.Files.createDirectories(outDir);
084        DateTimeFormatter df = DateTimeFormatter.ISO_DATE;
085        Path outFile = outDir.resolve("GroupedSmoke-" + LocalDate.now().format(df) + ".png");
086        graph.saveChart(outFile, 800, 600);
087        System.out.println("Grouped smoke wrote chart to: " + outFile.toAbsolutePath());
088        System.out.println("Exists: " + java.nio.file.Files.exists(outFile));
089    }
090    /**
091     * Public no-arg constructor to document the utility nature of this class.
092     * Kept for completeness; all work is performed from {@link #main(String[])}.
093     */
094    public GroupedSmoke() {
095        // no state
096    }
097}