Spaces:
Sleeping
Sleeping
File size: 19,927 Bytes
14356bb | 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 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Genesis AI β System Flowchart</title>
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: 'Segoe UI', Arial, sans-serif; background: #f0f4f0; color: #1a1a2e; padding: 36px; }
h1 { font-size: 24px; font-weight: 700; color: #1a6b2f; padding-bottom: 10px;
border-bottom: 3px solid #1a6b2f; margin-bottom: 4px; }
.sub { font-size: 12px; color: #777; margin-bottom: 36px; }
/* ββ section card ββ */
.card { background: #fff; border-radius: 14px; box-shadow: 0 2px 16px rgba(0,0,0,.08);
padding: 28px 32px; margin-bottom: 30px; }
.card-title { font-size: 13px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase;
color: #1a6b2f; margin-bottom: 18px; }
/* ββ mermaid override ββ */
.mermaid { font-size: 13px; }
.mermaid svg { width: 100%; height: auto; }
/* ββ legend ββ */
.legend { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.leg { display: flex; align-items: center; gap: 6px; font-size: 11px; color: #555; }
.leg-dot { width: 14px; height: 14px; border-radius: 3px; flex-shrink: 0; }
/* ββ table ββ */
table { width: 100%; border-collapse: collapse; font-size: 12px; }
thead tr { background: #1a6b2f; color: #fff; }
thead th { padding: 10px 14px; text-align: left; font-weight: 600; }
tbody tr:nth-child(even) { background: #f5faf5; }
tbody td { padding: 9px 14px; border-bottom: 1px solid #e5ede5; vertical-align: top; }
td:first-child { font-weight: 700; color: #1a6b2f; white-space: nowrap; }
td code { font-family: Consolas, monospace; font-size: 11px; background: #eef4ee;
padding: 2px 6px; border-radius: 3px; }
.badge { display: inline-block; font-size: 10px; font-weight: 700; padding: 2px 7px;
border-radius: 10px; margin-right: 4px; }
.fe { background: #e3f2fd; color: #1565c0; }
.be { background: #fff3e0; color: #c84b00; }
.py { background: #e8f5e9; color: #1b5e20; }
.out { background: #f3e5f5; color: #6a1b9a; }
</style>
</head>
<body>
<h1>Genesis AI β Complete System Flowchart</h1>
<p class="sub">End-to-end flow: Excel upload → Python pipeline → JSON outputs → React dashboard</p>
<!-- ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
<!-- MASTER FLOW -->
<!-- ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
<div class="card">
<div class="card-title">Master Flow β Upload to Dashboard</div>
<div class="mermaid">
flowchart TD
A([" π€ User\nOpens Dashboard "]) --> B
subgraph FE [" REACT FRONTEND (localhost:5173) "]
B["Header.jsx\nShows file badge\n+ Upload button"]
B --> C["UploadModal.jsx\nUser picks .xlsx file"]
C --> D["POST /api/upload\nfetch() with FormData"]
D2["DataContext.jsx\nfetchKey() per tab"]
D3["Dashboard tabs render\nResults / PPA / Market / Recs β¦"]
D2 --> D3
end
subgraph BE [" FASTAPI BACKEND (localhost:8000) "]
E["upload_server.py\n@app.post('/api/upload')\nSaves .xlsx to _uploads/"]
F["background thread\n_run_pipeline()"]
E --> F
G["GET /api/data/{key}\n@app.get('/api/data/{key}')\nReads output/{key}.json"]
end
subgraph PY [" PYTHON PIPELINE (pipeline/) "]
P1["loader.py\nload_data()\nRead 1_Source_Data sheet\ncompute Price = Val/Vol"]
P2["run.py\nread_brand_config()\nFocal brand + competitors\nfrom 2_Brand_Config sheet"]
P3["modelling.py\nbuild_wide_pivot()\nOne table per CHΓRG grain"]
P4["diagnostics.py\nrun_diagnostics()\nCorrelation, CV, RPI checks"]
P5["modelling.py\nrun_elasticity_models()\nOLS regression per grain\nBest Adj-RΒ² spec selected"]
P6["proxies.py\nassign_proxies()\nWrong-sign grains get\nborrowed elasticity"]
P7["exporters/stats.py\nexporters/market.py\nexporters/ppa.py\nexporters/analytics.py\nexporters/recommendations.py"]
P1 --> P2 --> P3 --> P4 --> P5 --> P6 --> P7
end
subgraph OUT [" OUTPUT FILES (output/) "]
J1["models.json\nstats.json\nfreq_anchors.json"]
J2["trend.json Β· ms.json\nvol_salience.json\nval_share.json\ncomp_ms.json Β· vtm.json"]
J3["ppa_mt.json\nppa_tt.json"]
J4["interaction.json\ngrowth_decomp.json\npgi.json"]
J5["recs_full.json"]
end
D --> E
F --> P1
P7 --> J1
P7 --> J2
P7 --> J3
P7 --> J4
P7 --> J5
J1 & J2 & J3 & J4 & J5 --> G
G --> D2
style FE fill:#e3f2fd,stroke:#1565c0,color:#0d1b4b
style BE fill:#fff3e0,stroke:#c84b00,color:#3e2000
style PY fill:#e8f5e9,stroke:#2e7d32,color:#1b2e1b
style OUT fill:#f3e5f5,stroke:#7b1fa2,color:#2e0040
</div>
<div class="legend">
<div class="leg"><div class="leg-dot" style="background:#bbdefb;border:1.5px solid #1565c0"></div> React Frontend</div>
<div class="leg"><div class="leg-dot" style="background:#ffe0b2;border:1.5px solid #c84b00"></div> FastAPI Backend</div>
<div class="leg"><div class="leg-dot" style="background:#c8e6c9;border:1.5px solid #2e7d32"></div> Python Pipeline</div>
<div class="leg"><div class="leg-dot" style="background:#e1bee7;border:1.5px solid #7b1fa2"></div> JSON Outputs</div>
</div>
</div>
<!-- ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
<!-- API FLOW -->
<!-- ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
<div class="card">
<div class="card-title">API Sequence β Upload → Poll → Fetch Data</div>
<div class="mermaid">
sequenceDiagram
participant UI as React (browser)
participant API as FastAPI :8000
participant PL as Pipeline (subprocess)
participant FS as output/*.json
UI->>API: POST /api/upload (FormData: file.xlsx)
API-->>UI: 200 { ok:true, filename }
Note over API: background thread starts
loop every 2 s while status == "running"
UI->>API: GET /api/upload/status
API-->>UI: { status, message, elapsed_s }
end
Note over PL: loader β config β pivot β diag β OLS β proxies β export
API->>PL: subprocess python -m pipeline.run --input file.xlsx
PL-->>FS: writes 16 Γ *.json to output/
API-->>UI: status = "done"
loop for each of 16 data keys
UI->>API: GET /api/data/{key}
API->>FS: reads output/{key}.json
FS-->>API: JSON bytes
API-->>UI: JSON response
end
Note over UI: Dashboard tabs render with fresh data
</div>
</div>
<!-- ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
<!-- PIPELINE STEPS DETAIL -->
<!-- ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
<div class="card">
<div class="card-title">Pipeline Steps — Detailed Breakdown</div>
<div class="mermaid">
flowchart LR
classDef step fill:#e8f5e9,stroke:#2e7d32,color:#1b2e1b,rx:8
classDef json fill:#f3e5f5,stroke:#7b1fa2,color:#2e0040,rx:8
classDef file fill:#fff3e0,stroke:#c84b00,color:#3e2000,rx:4
S1["STEP 1\nloader.py\nload_data()"]:::step
S2["STEP 2\nrun.py\nread_brand_config()"]:::step
S3["STEP 3\nmodelling.py\nbuild_wide_pivot()"]:::step
S4["STEP 4\ndiagnostics.py\nrun_diagnostics()"]:::step
S5["STEP 5\nmodelling.py\nrun_elasticity_models()"]:::step
S6["STEP 6\nproxies.py\nassign_proxies()"]:::step
E1["stats.py\nexport_stats()"]:::step
E2["market.py\nexport_market()"]:::step
E3["ppa.py\nexport_ppa()"]:::step
E4["analytics.py\nexport_analytics()"]:::step
E5["recommendations.py\nexport_recs()"]:::step
J1["models.json\nstats.json\nfreq_anchors.json"]:::json
J2["trend.json\nms.json\nvol_salience.json\nval_share.json\ncomp_ms.json\nvtm.json"]:::json
J3["ppa_mt.json\nppa_tt.json"]:::json
J4["interaction.json\ngrowth_decomp.json\npgi.json"]:::json
J5["recs_full.json"]:::json
S1 --> S2 --> S3 --> S4 --> S5 --> S6
S6 --> E1 & E2 & E3 & E4 & E5
E1 --> J1
E2 --> J2
E3 --> J3
E4 --> J4
E5 --> J5
</div>
</div>
<!-- ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
<!-- STEP TABLE -->
<!-- ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
<div class="card">
<div class="card-title">Step-by-Step Reference Table</div>
<table>
<thead>
<tr>
<th>Step</th>
<th>Layer</th>
<th>File</th>
<th>Function / Endpoint</th>
<th>What it does</th>
<th>Output</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><span class="badge fe">FE</span></td>
<td><code>Header.jsx</code></td>
<td>Upload button click</td>
<td>Opens UploadModal; shows active filename badge from localStorage</td>
<td>β</td>
</tr>
<tr>
<td>2</td>
<td><span class="badge fe">FE</span></td>
<td><code>UploadModal.jsx</code></td>
<td><code>handleUpload()</code></td>
<td>Sends <code>POST /api/upload</code> with FormData; polls <code>/api/upload/status</code> every 2 s</td>
<td>Filename stored in localStorage</td>
</tr>
<tr>
<td>3</td>
<td><span class="badge be">BE</span></td>
<td><code>upload_server.py</code></td>
<td><code>POST /api/upload</code></td>
<td>Validates extension, saves .xlsx to <code>_uploads/</code>, spawns background thread</td>
<td><code>{ ok: true, filename }</code></td>
</tr>
<tr>
<td>4</td>
<td><span class="badge be">BE</span></td>
<td><code>upload_server.py</code></td>
<td><code>_run_pipeline()</code></td>
<td>Calls <code>python -m pipeline.run --input file.xlsx --output output/</code> via subprocess.Popen (streams live)</td>
<td>Terminal log</td>
</tr>
<tr>
<td>5</td>
<td><span class="badge py">PY</span></td>
<td><code>pipeline/loader.py</code></td>
<td><code>load_data()</code></td>
<td>Reads sheet <em>1_Source_Data</em>; computes Price = Value / Volume; drops nulls</td>
<td>DataFrame</td>
</tr>
<tr>
<td>6</td>
<td><span class="badge py">PY</span></td>
<td><code>pipeline/run.py</code></td>
<td><code>read_brand_config()</code></td>
<td>Reads sheet <em>2_Brand_Config</em>; extracts focal brand + competitors</td>
<td>brand config dict</td>
</tr>
<tr>
<td>7</td>
<td><span class="badge py">PY</span></td>
<td><code>pipeline/modelling.py</code></td>
<td><code>build_wide_pivot()</code></td>
<td>One wide table per Channel Γ Region grain with focal + competitor columns</td>
<td>wide DataFrame</td>
</tr>
<tr>
<td>8</td>
<td><span class="badge py">PY</span></td>
<td><code>pipeline/diagnostics.py</code></td>
<td><code>run_diagnostics()</code></td>
<td>Pearson correlation, CV, RPI checks per grain; writes Excel diagnostics file</td>
<td><code>*_Diagnostics.xlsx</code></td>
</tr>
<tr>
<td>9</td>
<td><span class="badge py">PY</span></td>
<td><code>pipeline/modelling.py</code></td>
<td><code>run_elasticity_models()</code></td>
<td>OLS regression on all spec combos; selects best Adj-RΒ² with correct sign; clamps to [β6, 0]</td>
<td>results DataFrame</td>
</tr>
<tr>
<td>10</td>
<td><span class="badge py">PY</span></td>
<td><code>pipeline/proxies.py</code></td>
<td><code>assign_proxies()</code></td>
<td>Wrong-sign grains borrow elasticity from adjacent/nearby grains</td>
<td>final elasticities</td>
</tr>
<tr>
<td>11</td>
<td><span class="badge py">PY</span></td>
<td><code>pipeline/exporters/stats.py</code></td>
<td><code>export_stats()</code></td>
<td>Writes elasticity results + brand KPIs</td>
<td><code>models.json, stats.json, freq_anchors.json</code></td>
</tr>
<tr>
<td>12</td>
<td><span class="badge py">PY</span></td>
<td><code>pipeline/exporters/market.py</code></td>
<td><code>export_market()</code></td>
<td>Writes time-series, market share, volume/value share</td>
<td><code>trend.json, ms.json, vol_salience.json, val_share.json, comp_ms.json, vtm.json</code></td>
</tr>
<tr>
<td>13</td>
<td><span class="badge py">PY</span></td>
<td><code>pipeline/exporters/ppa.py</code></td>
<td><code>export_ppa()</code></td>
<td>Reads sheets <em>3_PPA_MT</em> and <em>4_PPA_TT</em> from original xlsx</td>
<td><code>ppa_mt.json, ppa_tt.json</code></td>
</tr>
<tr>
<td>14</td>
<td><span class="badge py">PY</span></td>
<td><code>pipeline/exporters/analytics.py</code></td>
<td><code>export_analytics()</code></td>
<td>Cross-brand correlations, growth decomposition, price gradient index</td>
<td><code>interaction.json, growth_decomp.json, pgi.json</code></td>
</tr>
<tr>
<td>15</td>
<td><span class="badge py">PY</span></td>
<td><code>pipeline/exporters/recommendations.py</code></td>
<td><code>export_recs()</code></td>
<td>Builds pricing recommendation cards per pack using elasticities</td>
<td><code>recs_full.json</code></td>
</tr>
<tr>
<td>16</td>
<td><span class="badge be">BE</span></td>
<td><code>upload_server.py</code></td>
<td><code>GET /api/data/{key}</code></td>
<td>Reads <code>output/{key}.json</code> and returns as JSON response to React</td>
<td>JSON to browser</td>
</tr>
<tr>
<td>17</td>
<td><span class="badge fe">FE</span></td>
<td><code>DataContext.jsx</code></td>
<td><code>fetchKey()</code></td>
<td>Tries <code>/api/data/{key}</code> first; falls back to <code>/data/{key}.json</code> (static)</td>
<td>React state updated</td>
</tr>
<tr>
<td>18</td>
<td><span class="badge fe">FE</span></td>
<td><code>src/components/tabs/</code></td>
<td>All tab components</td>
<td>Read from DataContext and render charts, tables, recommendation cards</td>
<td>Dashboard UI</td>
</tr>
</tbody>
</table>
</div>
<!-- ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
<!-- DATA SERVING β TWO-TIER -->
<!-- ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
<div class="card">
<div class="card-title">Data Serving β Two-Tier Fallback</div>
<div class="mermaid">
flowchart TD
A["React: fetchKey(key)"] --> B{"FastAPI server\nreachable?"}
B -- Yes --> C["GET /api/data/{key}\nlocalhost:8000"]
B -- No --> D["GET /data/{key}.json\nVite static (public/data/)"]
C -- "200 OK" --> E["Use API response\n(always fresh)"]
C -- "404 / error" --> D
D -- "200 OK" --> F["Use static file\n(last pipeline run)"]
D -- "404 / error" --> G["null β tab shows empty state"]
style E fill:#e8f5e9,stroke:#2e7d32
style F fill:#fff3e0,stroke:#c84b00
style G fill:#fce4ec,stroke:#b71c1c
</div>
</div>
<!-- ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
<!-- FILE MAP -->
<!-- ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ -->
<div class="card">
<div class="card-title">Output File Map β JSON Key → Dashboard Tab</div>
<table>
<thead>
<tr>
<th>JSON file</th>
<th>API key</th>
<th>Pipeline exporter</th>
<th>Dashboard tab / component</th>
</tr>
</thead>
<tbody>
<tr><td><code>models.json</code></td><td><code>models</code></td><td>stats.py</td><td>Results β elasticity table</td></tr>
<tr><td><code>stats.json</code></td><td><code>stats</code></td><td>stats.py</td><td>Header KPIs, brand summary</td></tr>
<tr><td><code>freq_anchors.json</code></td><td><code>freq_anchors</code></td><td>stats.py</td><td>Results β frequency anchors</td></tr>
<tr><td><code>trend.json</code></td><td><code>trend</code></td><td>market.py</td><td>Trends tab β time-series chart</td></tr>
<tr><td><code>ms.json</code></td><td><code>ms</code></td><td>market.py</td><td>Market Share tab</td></tr>
<tr><td><code>vol_salience.json</code></td><td><code>vol_salience</code></td><td>market.py</td><td>Growth tab β pack salience</td></tr>
<tr><td><code>val_share.json</code></td><td><code>val_share</code></td><td>market.py</td><td>Growth tab β value share</td></tr>
<tr><td><code>comp_ms.json</code></td><td><code>comp_ms</code></td><td>market.py</td><td>Market Share β all brands</td></tr>
<tr><td><code>vtm.json</code></td><td><code>vtm</code></td><td>market.py</td><td>Results β volume-to-market</td></tr>
<tr><td><code>ppa_mt.json</code></td><td><code>ppa_mt</code></td><td>ppa.py</td><td>PPA tab β Modern Trade</td></tr>
<tr><td><code>ppa_tt.json</code></td><td><code>ppa_tt</code></td><td>ppa.py</td><td>PPA tab β Traditional Trade</td></tr>
<tr><td><code>interaction.json</code></td><td><code>interaction</code></td><td>analytics.py</td><td>Interaction tab β correlation matrix</td></tr>
<tr><td><code>growth_decomp.json</code></td><td><code>growth_decomp</code></td><td>analytics.py</td><td>Growth tab β decomposition chart</td></tr>
<tr><td><code>pgi.json</code></td><td><code>pgi</code></td><td>analytics.py</td><td>Methodology tab β price gradient</td></tr>
<tr><td><code>recs_full.json</code></td><td><code>recs / recs_full</code></td><td>recommendations.py</td><td>Recommendations tab β cards</td></tr>
</tbody>
</table>
</div>
<script>
mermaid.initialize({
startOnLoad: true,
theme: 'default',
themeVariables: {
primaryColor: '#e8f5e9',
primaryTextColor: '#1b2e1b',
primaryBorderColor: '#2e7d32',
lineColor: '#2e7d32',
secondaryColor: '#fff3e0',
tertiaryColor: '#f3e5f5',
fontSize: '13px',
},
flowchart: { curve: 'basis', padding: 20 },
sequence: { actorMargin: 80, messageMargin: 40, mirrorActors: false },
})
</script>
</body>
</html>
|