All files / web/src/lib/flowcharts/definitions index.ts

86% Statements 467/543
100% Branches 0/0
0% Functions 0/4
86% Lines 467/543

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 5441x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x     1x 1x 1x 1x 1x 1x     1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                                                                   1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                                                
/**
 * Flowchart Definitions Registry
 *
 * **THIS FILE CONTAINS EMBEDDED MERMAID CONTENT!**
 *
 * Each flowchart has two parts:
 * 1. **JSON definition** (`.flow.json`): Behavior, validation, variables
 * 2. **Mermaid content**: Visual presentation, node text, phases
 *
 * ## Where is the Mermaid content?
 *
 * | Flowchart | Mermaid Location |
 * |-----------|------------------|
 * | subtraction-regrouping | Embedded below as `SUBTRACTION_MERMAID` |
 * | fraction-add-sub | Embedded below as `FRACTION_MERMAID` |
 * | linear-equations | Embedded below as `LINEAR_EQUATIONS_MERMAID` |
 * | sentence-type | Embedded below as `SENTENCE_TYPE_MERMAID` (uses transforms) |
 * | order-of-operations | Embedded below as `ORDER_OF_OPERATIONS_MERMAID` (uses transforms) |
 *
 * **To find node content**: Search this file for the node ID (e.g., `READY1`) in
 * the appropriate `*_MERMAID` constant.
 *
 * ## Why Embed Mermaid?
 *
 * Next.js doesn't support `?raw` imports for loading text files.
 * Embedding the mermaid content as template strings is the simplest solution.
 *
 * ## Adding a New Flowchart
 *
 * 1. Create `my-flowchart.flow.json` in this directory
 * 2. Add `const MY_FLOWCHART_MERMAID = \`...\`` below
 * 3. Import the JSON and add to `FLOWCHARTS` registry
 *
 * @see {@link ../README.md} for complete system documentation
 * @module flowcharts/definitions
 */
 
import type { FlowchartDefinition } from '../schema'
import subtractionDefinition from './subtraction-regrouping.flow.json'
import fractionDefinition from './fraction-add-sub.flow.json'
import linearEquationsDefinition from './linear-equations.flow.json'
import sentenceTypeDefinition from './sentence-type.flow.json'
import orderOfOperationsDefinition from './order-of-operations.flow.json'
 
// =============================================================================
// EMBEDDED MERMAID CONTENT
// =============================================================================
// These constants contain the visual content for each flowchart.
// Search for node IDs (e.g., "READY1", "STEP0") to find their content.
 
/**
 * Mermaid content for subtraction-regrouping flowchart.
 * Nodes: START, COMPARE, HAPPY, SAD, CHECK1, CHECK1B, NEEDIT, SKIP, TENS,
 *        TAKEONE, BREAK, ADDTEN, CHECK2, DOONES, DOTENS, DONE
 */
const SUBTRACTION_MERMAID = `%%{init: {'theme': 'base', 'themeVariables': { 'fontSize': '18px', 'primaryColor': '#e3f2fd', 'primaryTextColor': '#1a1a1a', 'primaryBorderColor': '#90caf9', 'lineColor': '#444444'}, 'flowchart': {'curve': 'basis', 'nodeSpacing': 30, 'rankSpacing': 50, 'padding': 20}}}%%
flowchart TB
    subgraph PHASE1["<b>1. ๐Ÿ‘€ LOOK</b>"]
        direction LR
        START["๐Ÿ”ข<br/>โ”€โ”€โ”€<br/>Look at the<br/><b>ONES</b><br/>โ”€โ”€โ”€<br/>๐Ÿ‘‰ Right side"]
        START e_start_compare@--> COMPARE{"<b>TOP</b><br/>bigger?<br/>โ”€โ”€โ”€<br/>๐Ÿ” โ‰ฅ ๐Ÿ”ฝ ?"}
        COMPARE e_compare_yes@-->|"โœ“ YES"| HAPPY(("๐Ÿ˜Š"))
        COMPARE e_compare_no@-->|"โœ— NO"| SAD(("๐Ÿ˜ข"))
        HAPPY e_happy_check@--> CHECK1["โœ…<br/>โ”€โ”€โ”€<br/>Top is BIG<br/>Go subtract!"]
        SAD e_sad_check@--> CHECK1B["โš ๏ธ<br/>โ”€โ”€โ”€<br/>Top is SMALL<br/>Need to BORROW"]
    end
 
    subgraph PHASE2["<b>2. ๐Ÿฆ BORROW</b>"]
        direction LR
        NEEDIT{"๐Ÿ˜Š or ๐Ÿ˜ข?<br/>โ”€โ”€โ”€<br/>Was TOP<br/>big enough?"}
        NEEDIT e_needit_yes@-->|"๐Ÿ˜Š YES"| SKIP(("๐Ÿ‘"))
        NEEDIT e_needit_no@-->|"๐Ÿ˜ข NO"| TENS["๐Ÿ‘ˆ <b>TENS</b><br/>โ”€โ”€โ”€<br/>Go LEFT<br/>one spot<br/>โ”€โ”€โ”€<br/>๐Ÿ”Ÿ๐Ÿ”Ÿ๐Ÿ”Ÿ"]
        TENS e_tens_take@--> TAKEONE["<b>TAKE 1</b><br/>โ”€โ”€โ”€<br/>Cross out<br/>Write 1 LESS<br/>โ”€โ”€โ”€<br/>โŒ๐Ÿ”Ÿ โ†’ โœ๏ธ"]
        TAKEONE e_take_break@--> BREAK["โœ‚๏ธ <b>BREAK IT!</b><br/>โ”€โ”€โ”€<br/>1 ten =<br/>10 ones!<br/>โ”€โ”€โ”€<br/>๐Ÿ”Ÿ โ†’ โšซโšซโšซโšซโšซ<br/>      โšซโšซโšซโšซโšซ"]
        BREAK e_break_add@--> ADDTEN["<b>+10</b> ONES<br/>โ”€โ”€โ”€<br/>Add 10 to<br/>TOP number<br/>โ”€โ”€โ”€<br/>3 โ†’ <b>13</b>"]
        ADDTEN e_add_check@--> CHECK2["โœ…<br/>โ”€โ”€โ”€<br/>Now TOP<br/>is BIG!"]
        SKIP e_skip_check@--> CHECK2
    end
 
    subgraph PHASE3["<b>3. โž– SUBTRACT</b>"]
        direction LR
        DOONES["<b>ONES</b> ๐Ÿ‘‰<br/>โ”€โ”€โ”€<br/>TOP โˆ’ BOTTOM<br/>โ”€โ”€โ”€<br/>Write answer"]
        DOONES e_ones_tens@--> DOTENS["<b>TENS</b> ๐Ÿ‘ˆ<br/>โ”€โ”€โ”€<br/>TOP โˆ’ BOTTOM<br/>โ”€โ”€โ”€<br/>Write answer"]
        DOTENS e_tens_done@--> DONE(["๐ŸŽ‰ DONE!"])
    end
 
    PHASE1 --> PHASE2
    PHASE2 --> PHASE3
 
    style PHASE1 fill:#e3f2fd,stroke:#1976d2,stroke-width:3px
    style PHASE2 fill:#fff8e1,stroke:#f9a825,stroke-width:3px
    style PHASE3 fill:#e8f5e9,stroke:#388e3c,stroke-width:3px
 
    style START fill:#bbdefb,stroke:#1976d2
    style COMPARE fill:#fffde7,stroke:#fbc02d,stroke-width:2px
    style HAPPY fill:#81c784,stroke:#388e3c
    style SAD fill:#ffcdd2,stroke:#d32f2f
    style CHECK1 fill:#a5d6a7,stroke:#388e3c
    style CHECK1B fill:#ffcdd2,stroke:#d32f2f,stroke-width:2px
 
    style NEEDIT fill:#fffde7,stroke:#fbc02d,stroke-width:2px
    style SKIP fill:#81c784,stroke:#388e3c
    style TENS fill:#bbdefb,stroke:#1976d2
    style TAKEONE fill:#e1bee7,stroke:#8e24aa
    style BREAK fill:#ffe0b2,stroke:#f57c00,stroke-width:2px
    style ADDTEN fill:#e1bee7,stroke:#8e24aa
    style CHECK2 fill:#a5d6a7,stroke:#388e3c
 
    style DOONES fill:#a5d6a7,stroke:#388e3c
    style DOTENS fill:#a5d6a7,stroke:#388e3c
    style DONE fill:#66bb6a,stroke:#2e7d32,stroke-width:2px
`
 
/**
 * Mermaid content for fraction-add-sub flowchart.
 * Nodes: STEP0, STEP1, READY1, READY2, READY3, STEP2, CONV1A, CONV1B, CONV1C,
 *        STEP3, STEP3B, CHECK1, REMIND, ADDSUB, GOSTEP4, GOSTEP4B, GOSTEP4C,
 *        BORROWCHECK, BORROW, CHECK2, STEP4, CALC_DENOM, CALC_WHOLE,
 *        SIMPLIFY_Q, SIMPLIFY_HOW, IMPROPER_Q, MIXED_HOW, CHECK3, DONE
 *
 * NOTE: Milestone nodes (READY1, READY2, READY3, GOSTEP4, etc.) only contain
 * emoji like (("๐Ÿ‘")) - they display briefly before auto-advancing.
 */
const FRACTION_MERMAID = `%%{init: {'theme': 'base', 'themeVariables': { 'fontSize': '14px', 'primaryColor': '#e3f2fd', 'primaryTextColor': '#1a1a1a', 'primaryBorderColor': '#90caf9', 'lineColor': '#444444'}, 'flowchart': {'curve': 'basis', 'nodeSpacing': 25, 'rankSpacing': 40, 'padding': 15}}}%%
flowchart TB
    subgraph PHASE1["<b>1. ๐Ÿ” MAKE THE BOTTOMS MATCH</b>"]
        direction LR
        STEP0["<b>๐Ÿ‘€ LOOK AT BOTTOMS</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Find the bottom numbers<br/>(denominators) of both fractions<br/>and enter them below."]
        STEP0 e_step0_step1@--> STEP1{"<b>SAME?</b><br/>โ”€โ”€โ”€โ”€โ”€<br/>Are they the<br/>same number?"}
        STEP1 e_step1_yes@-->|"YES โœ“"| READY1(("๐Ÿ‘"))
        STEP1 e_step1_no@-->|"NO"| STEP2{"<b>ONE FITS IN OTHER?</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Divide BIG bottom<br/>by SMALL bottom.<br/>Whole number?"}
        STEP2 e_step2_yes@-->|"YES"| CONV1A["<b>STEP A: FIND THE MULTIPLIER</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>What number ร— small bottom<br/>= big bottom?"]
        CONV1A e_conv1a_b@--> CONV1B["<b>STEP B: MULTIPLY BOTH!</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Multiply the TOP by that number.<br/>Multiply the BOTTOM by that number."]
        CONV1B e_conv1b_c@--> CONV1C["๐Ÿ’ก <b>WHY?</b> Because 2/2 = 1<br/>You're multiplying by 1!"]
        CONV1C e_conv1c_ready@--> READY2(("๐Ÿ‘"))
        STEP2 e_step2_no@-->|"NO"| STEP3["<b>CROSS MULTIPLY BOTTOMS</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>New bottom = left ร— right"]
        STEP3 e_step3_3b@--> STEP3B["<b>CONVERT BOTH FRACTIONS</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>For EACH fraction:<br/>What ร— old bottom = LCD?"] e_step3b_ready@--> READY3(("๐Ÿ‘"))
        READY1 e_ready1_check@--> CHECK1["<b>โœ… READY CHECK</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>โ˜ Both bottoms are<br/>   the SAME number<br/>โ˜ I wrote the new fractions down"]
        READY2 e_ready2_check@--> CHECK1
        READY3 e_ready3_check@--> CHECK1
    end
 
    subgraph PHASE2["<b>2. โš ๏ธ DO YOU NEED TO BORROW?</b>"]
        direction LR
        REMIND["<b>โš ๏ธ BOTTOMS MUST MATCH FIRST!</b>"]
        REMIND e_remind_addsub@--> ADDSUB{"<b>ADDING OR<br/>SUBTRACTING?</b>"}
        ADDSUB e_addsub_add@-->|"โž• Adding"| GOSTEP4(("๐Ÿ˜Ž"))
        ADDSUB e_addsub_sub@-->|"โž– Subtracting"| BORROWCHECK{"<b>COMPARE TOPS</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Is the LEFT top<br/>โ‰ฅ the RIGHT top?"}
        BORROWCHECK e_borrow_yes@-->|"YES โœ“"| GOSTEP4B(("๐Ÿ˜Ž"))
        BORROWCHECK e_borrow_no@-->|"๐Ÿ˜ฑ NO!"| BORROW["<b>๐Ÿฆ BORROW 1 FROM WHOLE</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>1. Whole number GOES DOWN by 1<br/>2. Add the MATCHING BOTTOM to top"]
        BORROW e_borrow_go@--> GOSTEP4C(("๐Ÿ’ช"))
        GOSTEP4 e_go4_check@--> CHECK2["<b>โœ… READY CHECK</b>"]
        GOSTEP4B e_go4b_check@--> CHECK2
        GOSTEP4C e_go4c_check@--> CHECK2
    end
 
    subgraph PHASE3["<b>3. ๐ŸŽฏ DO THE MATH!</b>"]
        direction LR
        STEP4["<b>๐Ÿ”ข NUMERATOR</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Add or subtract<br/>the TOP numbers"]
        STEP4 e_step4_denom@--> CALC_DENOM["<b>๐Ÿ”ข DENOMINATOR</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>The bottom number<br/>stays the same!"]
        CALC_DENOM e_denom_whole@--> CALC_WHOLE["<b>๐Ÿ”ข WHOLE NUMBER</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Add or subtract<br/>the whole numbers<br/>(0 if none)"]
        CALC_WHOLE e_whole_simplify@--> SIMPLIFY_Q{"<b>SIMPLIFY?</b>"}
        SIMPLIFY_Q e_simplify_no@-->|"NO โœ“"| IMPROPER_Q
        SIMPLIFY_Q e_simplify_yes@-->|"YES"| SIMPLIFY_HOW["<b>๐Ÿชœ FRACTION LADDER</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Keep dividing by small numbers"]
        SIMPLIFY_HOW e_how_improper@--> IMPROPER_Q{"<b>TOP > BOTTOM?</b>"}
        IMPROPER_Q e_improper_no@-->|"NO โœ“"| CHECK3
        IMPROPER_Q e_improper_yes@-->|"YES"| MIXED_HOW["<b>โž— IT'S JUST DIVISION!</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>TOP รท BOTTOM = ? R ?"]
        MIXED_HOW e_mixed_check@--> CHECK3["<b>โœ… FINAL CHECK</b>"]
        CHECK3 e_check3_done@--> DONE(["๐ŸŽ‰ DONE!"])
    end
 
    PHASE1 --> PHASE2
    PHASE2 --> PHASE3
 
    style PHASE1 fill:#e3f2fd,stroke:#1976d2,stroke-width:3px
    style PHASE2 fill:#fff8e1,stroke:#f9a825,stroke-width:3px
    style PHASE3 fill:#e8f5e9,stroke:#388e3c,stroke-width:3px
`
 
/**
 * Mermaid content for linear-equations flowchart.
 * Nodes: INTRO, BALANCE, FIND_OP, STUCK_ADD, STUCK_MUL, CHECK1, GOAL,
 *        HOWSTUCK, ZERO, ONE, MAKEZ, MAKEONE, EX_ADD, EX_MUL, REMIND,
 *        CHECK2, PLUG, MATCH, DONE, RETRY
 */
const LINEAR_EQUATIONS_MERMAID = `%%{init: {'theme': 'base', 'themeVariables': { 'fontSize': '14px', 'primaryColor': '#e3f2fd', 'primaryTextColor': '#1a1a1a', 'primaryBorderColor': '#90caf9', 'lineColor': '#444444'}, 'flowchart': {'curve': 'basis', 'nodeSpacing': 25, 'rankSpacing': 40, 'padding': 15}}}%%
flowchart TB
    subgraph PHASE1["<b>1. ๐Ÿ” UNDERSTAND THE EQUATION</b>"]
        direction LR
        INTRO["<b>๐ŸŽ WHAT IS x?</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>x is a mystery number<br/>hiding in a box!"]
        INTRO e_intro_balance@--> BALANCE["<b>โš–๏ธ THE BALANCE RULE</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Both sides must be EQUAL.<br/>Whatever you do to one side,<br/>you MUST do to the other!"]
        BALANCE e_balance_find@--> FIND_OP{"<b>๐Ÿ” HOW IS x TRAPPED?</b>"}
        FIND_OP e_find_add@-->|"ADDED ON"| STUCK_ADD(("โž•โž–"))
        FIND_OP e_find_mul@-->|"MULTIPLIED IN"| STUCK_MUL(("โœ–๏ธโž—"))
        STUCK_ADD e_add_check@--> CHECK1["<b>โœ… I FOUND IT</b>"]
        STUCK_MUL e_mul_check@--> CHECK1
    end
 
    subgraph PHASE2["<b>2. โœจ SET x FREE!</b>"]
        direction LR
        GOAL["<b>๐ŸŽฏ x WANTS TO BE ALONE!</b>"]
        GOAL e_goal_how@--> HOWSTUCK{"<b>๐Ÿ” HOW IS THE<br/>NUMBER STUCK?</b>"}
        HOWSTUCK e_stuck_addsub@-->|"Added/Subtracted"| ZERO["<b>0๏ธโƒฃ YOU NEED A ZERO!</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>x + 0 = x<br/>Zero sets x FREE!"]
        HOWSTUCK e_stuck_muldiv@-->|"Multiplied/Divided"| ONE["<b>1๏ธโƒฃ YOU NEED A ONE!</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>x ร— 1 = x<br/>One sets x FREE!"]
        ZERO e_zero_make@--> MAKEZ["<b>๐Ÿ’ก HOW TO MAKE ZERO</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Add the OPPOSITE!"]
        ONE e_one_make@--> MAKEONE["<b>๐Ÿ’ก HOW TO MAKE ONE</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>DIVIDE it away!"]
        MAKEZ e_makez_ex@--> EX_ADD["<b>๐Ÿ“ EXAMPLE</b>"]
        MAKEONE e_makeone_ex@--> EX_MUL["<b>๐Ÿ“ EXAMPLE</b>"]
        EX_ADD e_exadd_remind@--> REMIND["<b>โš ๏ธ BOTH SIDES!</b>"]
        EX_MUL e_exmul_remind@--> REMIND
        REMIND e_remind_check@--> CHECK2["<b>โœ… IS x FREE?</b>"]
    end
 
    subgraph PHASE3["<b>3. โœ”๏ธ CHECK YOUR ANSWER!</b>"]
        direction LR
        PLUG["<b>๐Ÿ”Œ PLUG IT BACK IN</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Put your answer where x was."]
        PLUG e_plug_match@--> MATCH{"<b>DOES IT MATCH?</b>"}
        MATCH e_match_yes@-->|"YES โœ“"| DONE(["๐ŸŽ‰ YOU SOLVED IT!"])
        MATCH e_match_no@-->|"NO ๐Ÿ˜•"| RETRY["<b>๐Ÿ” TRY AGAIN</b>"]
    end
 
    PHASE1 --> PHASE2
    PHASE2 --> PHASE3
 
    style PHASE1 fill:#e3f2fd,stroke:#1976d2,stroke-width:3px
    style PHASE2 fill:#fff8e1,stroke:#f9a825,stroke-width:3px
    style PHASE3 fill:#e8f5e9,stroke:#388e3c,stroke-width:3px
`
 
/**
 * Mermaid content for sentence-type flowchart.
 * Demonstrates the new unified computation model with transforms on nodes.
 * Nodes: START, CHECK_END, IS_QUESTION, RESULT_INTERROGATIVE, CHECK_COMMAND,
 *        RESULT_IMPERATIVE_EXCLAIM, RESULT_EXCLAMATORY, CHECK_STATEMENT,
 *        RESULT_DECLARATIVE, RESULT_IMPERATIVE_POLITE, DONE
 */
const SENTENCE_TYPE_MERMAID = `%%{init: {'theme': 'base', 'themeVariables': { 'fontSize': '16px', 'primaryColor': '#e3f2fd', 'primaryTextColor': '#1a1a1a', 'primaryBorderColor': '#90caf9', 'lineColor': '#444444'}, 'flowchart': {'curve': 'basis', 'nodeSpacing': 30, 'rankSpacing': 50, 'padding': 20}}}%%
flowchart TB
    subgraph PHASE1["<b>1. ๐Ÿ“ READ THE SENTENCE</b>"]
        direction LR
        START["<b>LOOK AT THE SENTENCE</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Read the sentence carefully.<br/>Notice how it ends!"]
        START e_start_check@--> CHECK_END{"<b>WHAT'S AT THE END?</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Find the punctuation mark."}
    end
 
    subgraph PHASE2["<b>2. ๐Ÿ” CLASSIFY IT</b>"]
        direction TB
        CHECK_END e_end_question@-->|"?"| IS_QUESTION["<b>IT'S A QUESTION!</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Questions ask for<br/>information."]
        IS_QUESTION e_question_result@--> RESULT_INTERROGATIVE(("โ“"))
 
        CHECK_END e_end_exclaim@-->|"!"| CHECK_COMMAND{"<b>WHAT KIND?</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Is it giving an order<br/>or expressing feeling?"}
        CHECK_COMMAND e_cmd_order@-->|"Order/Command"| RESULT_IMPERATIVE_EXCLAIM["<b>IT'S A COMMAND!</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Commands tell someone<br/>to do something."]
        CHECK_COMMAND e_cmd_feeling@-->|"Strong Feeling"| RESULT_EXCLAMATORY["<b>IT'S AN EXCLAMATION!</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Exclamations express<br/>strong emotions."]
 
        CHECK_END e_end_period@-->|"."| CHECK_STATEMENT{"<b>WHAT KIND?</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Is it stating facts<br/>or making a request?"}
        CHECK_STATEMENT e_stmt_fact@-->|"Statement"| RESULT_DECLARATIVE["<b>IT'S A STATEMENT!</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Statements tell us<br/>facts or opinions."]
        CHECK_STATEMENT e_stmt_request@-->|"Request"| RESULT_IMPERATIVE_POLITE["<b>IT'S A POLITE COMMAND!</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Some commands are<br/>gentle and use periods."]
    end
 
    subgraph PHASE3["<b>3. ๐ŸŽฏ RESULT</b>"]
        RESULT_INTERROGATIVE e_interrog_done@--> DONE(["๐ŸŽ‰ <b>INTERROGATIVE</b>"])
        RESULT_IMPERATIVE_EXCLAIM e_impexcl_done@--> DONE
        RESULT_EXCLAMATORY e_exclam_done@--> DONE
        RESULT_DECLARATIVE e_declar_done@--> DONE
        RESULT_IMPERATIVE_POLITE e_imppol_done@--> DONE
    end
 
    PHASE1 --> PHASE2
    PHASE2 --> PHASE3
 
    style PHASE1 fill:#e3f2fd,stroke:#1976d2,stroke-width:3px
    style PHASE2 fill:#fff8e1,stroke:#f9a825,stroke-width:3px
    style PHASE3 fill:#e8f5e9,stroke:#388e3c,stroke-width:3px
`
 
/**
 * Mermaid content for order-of-operations flowchart.
 * Full PEMDAS support with up to 3 operations.
 * Nodes: START, EXPLAIN_PEMDAS, IDENTIFY_STEP1, DO_STEP1, CHECK_STEP1,
 *        AFTER_STEP1, CHECK_MORE_STEPS1, IDENTIFY_STEP2, DO_STEP2, CHECK_STEP2,
 *        AFTER_STEP2, CHECK_MORE_STEPS2, IDENTIFY_STEP3, DO_STEP3, CHECK_STEP3, DONE
 */
const ORDER_OF_OPERATIONS_MERMAID = `%%{init: {'theme': 'base', 'themeVariables': { 'fontSize': '16px', 'primaryColor': '#e3f2fd', 'primaryTextColor': '#1a1a1a', 'primaryBorderColor': '#90caf9', 'lineColor': '#444444'}, 'flowchart': {'curve': 'basis', 'nodeSpacing': 30, 'rankSpacing': 50, 'padding': 20}}}%%
flowchart TB
    subgraph INTRO_PHASE["<b>๐Ÿ“– PEMDAS</b>"]
        START["<b>ORDER OF OPERATIONS</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Solve: {{expr}}"]
        START e_start_explain@--> EXPLAIN_PEMDAS["<b>REMEMBER PEMDAS!</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>P - Parentheses first<br/>E - Exponents<br/>MD - Multiply/Divide (Lโ†’R)<br/>AS - Add/Subtract (Lโ†’R)"]
    end
 
    subgraph STEP1_PHASE["<b>โญ STEP 1</b>"]
        EXPLAIN_PEMDAS e_explain_id1@--> IDENTIFY_STEP1{"<b>WHAT'S FIRST?</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>Which operation<br/>has highest priority?"}
        IDENTIFY_STEP1 e_id1_p@-->|"P"| DO_STEP1
        IDENTIFY_STEP1 e_id1_e@-->|"E"| DO_STEP1
        IDENTIFY_STEP1 e_id1_md@-->|"MD"| DO_STEP1
        IDENTIFY_STEP1 e_id1_as@-->|"AS"| DO_STEP1
        DO_STEP1["<b>CALCULATE</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>{{opDisplay}}"]
        DO_STEP1 e_do1_check@--> CHECK_STEP1["โœ… Enter result"]
        CHECK_STEP1 e_check1_after@--> AFTER_STEP1["<b>SIMPLIFIED</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>{{showExpr}}"]
        AFTER_STEP1 e_after1_more@--> CHECK_MORE_STEPS1[" "]
    end
 
    subgraph STEP2_PHASE["<b>โญ STEP 2</b>"]
        CHECK_MORE_STEPS1 e_more1_id2@--> IDENTIFY_STEP2{"<b>NEXT OPERATION?</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>What's the priority?"}
        IDENTIFY_STEP2 e_id2_p@-->|"P"| DO_STEP2
        IDENTIFY_STEP2 e_id2_e@-->|"E"| DO_STEP2
        IDENTIFY_STEP2 e_id2_md@-->|"MD"| DO_STEP2
        IDENTIFY_STEP2 e_id2_as@-->|"AS"| DO_STEP2
        DO_STEP2["<b>CALCULATE</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>{{opDisplay}}"]
        DO_STEP2 e_do2_check@--> CHECK_STEP2["โœ… Enter result"]
        CHECK_STEP2 e_check2_after@--> AFTER_STEP2["<b>SIMPLIFIED</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>{{showExpr}}"]
        AFTER_STEP2 e_after2_more@--> CHECK_MORE_STEPS2[" "]
    end
 
    subgraph STEP3_PHASE["<b>โญ STEP 3</b>"]
        CHECK_MORE_STEPS2 e_more2_id3@--> IDENTIFY_STEP3{"<b>FINAL OPERATION?</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>What's the priority?"}
        IDENTIFY_STEP3 e_id3_p@-->|"P"| DO_STEP3
        IDENTIFY_STEP3 e_id3_e@-->|"E"| DO_STEP3
        IDENTIFY_STEP3 e_id3_md@-->|"MD"| DO_STEP3
        IDENTIFY_STEP3 e_id3_as@-->|"AS"| DO_STEP3
        DO_STEP3["<b>CALCULATE</b><br/>โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€<br/>{{opDisplay}}"]
        DO_STEP3 e_do3_check@--> CHECK_STEP3["โœ… Enter result"]
    end
 
    CHECK_MORE_STEPS1 -.->|"done"| DONE
    CHECK_MORE_STEPS2 -.->|"done"| DONE
    CHECK_STEP3 e_check3_done@--> DONE(["๐ŸŽ‰ DONE!"])
 
    style INTRO_PHASE fill:#e3f2fd,stroke:#1976d2,stroke-width:3px
    style STEP1_PHASE fill:#fff8e1,stroke:#f9a825,stroke-width:3px
    style STEP2_PHASE fill:#e8f5e9,stroke:#388e3c,stroke-width:3px
    style STEP3_PHASE fill:#fce4ec,stroke:#c2185b,stroke-width:3px
`
 
/**
 * Built-in flowchart seeds.
 *
 * These are the canonical definitions for built-in flowcharts.
 * Use the Seed Manager (debug mode on /flowchart) to populate the database.
 * After seeding, flowcharts are loaded from the database, not from here.
 */
export const FLOWCHART_SEEDS: Record<
  string,
  { definition: FlowchartDefinition; mermaid: string; meta: FlowchartMeta }
> = {
  'subtraction-regrouping': {
    definition: subtractionDefinition as unknown as FlowchartDefinition,
    mermaid: SUBTRACTION_MERMAID,
    meta: {
      id: 'subtraction-regrouping',
      title: 'Subtraction with Regrouping',
      description: 'Learn when and how to borrow in subtraction',
      emoji: 'โž–',
      difficulty: 'Beginner',
    },
  },
  'fraction-add-sub': {
    definition: fractionDefinition as FlowchartDefinition,
    mermaid: FRACTION_MERMAID,
    meta: {
      id: 'fraction-add-sub',
      title: 'Fraction Addition & Subtraction',
      description: 'Add and subtract fractions with different denominators',
      emoji: 'โž•',
      difficulty: 'Intermediate',
    },
  },
  'linear-equations': {
    definition: linearEquationsDefinition as FlowchartDefinition,
    mermaid: LINEAR_EQUATIONS_MERMAID,
    meta: {
      id: 'linear-equations',
      title: 'Solving Linear Equations',
      description: 'Solve equations like 3x + 5 = 17',
      emoji: '๐Ÿ”ข',
      difficulty: 'Intermediate',
    },
  },
  'sentence-type': {
    definition: sentenceTypeDefinition as FlowchartDefinition,
    mermaid: SENTENCE_TYPE_MERMAID,
    meta: {
      id: 'sentence-type',
      title: 'Identify Sentence Types',
      description:
        'Learn to classify declarative, interrogative, imperative, and exclamatory sentences',
      emoji: '๐Ÿ“',
      difficulty: 'Beginner',
    },
  },
  'order-of-operations': {
    definition: orderOfOperationsDefinition as FlowchartDefinition,
    mermaid: ORDER_OF_OPERATIONS_MERMAID,
    meta: {
      id: 'order-of-operations',
      title: 'Order of Operations (PEMDAS)',
      description: 'Learn to solve expressions like 3 + 4 ร— 2 step by step',
      emoji: '๐Ÿ”ข',
      difficulty: 'Beginner',
    },
  },
}
 
export interface FlowchartMeta {
  id: string
  title: string
  description: string
  emoji: string
  difficulty: 'Beginner' | 'Intermediate' | 'Advanced'
}
 
/**
 * Extended metadata for flowcharts from the database
 */
export interface FlowchartMetaWithSource extends FlowchartMeta {
  source: 'hardcoded' | 'database'
  authorId?: string
  publishedAt?: Date | null
}
 
/**
 * Full flowchart data with definition and mermaid content
 */
export interface FlowchartData {
  definition: FlowchartDefinition
  mermaid: string
  meta: FlowchartMeta
  source: 'hardcoded' | 'database'
  authorId?: string
  version?: number
  publishedAt?: Date | null
}
 
/**
 * Get list of all seed flowcharts (sync).
 * Use this only for the Seed Manager - not for loading flowcharts.
 */
export function getSeedList(): FlowchartMeta[] {
  return Object.values(FLOWCHART_SEEDS).map((f) => f.meta)
}
 
/**
 * Get a specific seed flowchart by ID (sync).
 * Use this only for the Seed Manager - not for loading flowcharts.
 */
export function getSeed(id: string) {
  return FLOWCHART_SEEDS[id] ?? null
}
 
// =============================================================================
// ASYNC LOADERS (database only)
// =============================================================================
 
/**
 * Get a flowchart by ID from the database.
 * Use this in API routes and server components.
 *
 * NOTE: Flowcharts must be seeded to the database first using the Seed Manager
 * (debug mode on /flowchart) before they can be loaded.
 *
 * @param id - The flowchart ID
 * @returns The flowchart data or null if not found
 */
export async function getFlowchartByIdAsync(id: string): Promise<FlowchartData | null> {
  // Dynamic import to avoid circular dependencies
  const { db, schema } = await import('@/db')
  const { and, eq } = await import('drizzle-orm')

  // Load from database only
  const dbFlowchart = await db.query.teacherFlowcharts.findFirst({
    where: and(
      eq(schema.teacherFlowcharts.id, id),
      eq(schema.teacherFlowcharts.status, 'published')
    ),
  })

  if (dbFlowchart) {
    let definition: FlowchartDefinition
    try {
      definition = JSON.parse(dbFlowchart.definitionJson)
    } catch {
      console.error(`Invalid definition JSON for flowchart ${id}`)
      return null
    }

    return {
      definition,
      mermaid: dbFlowchart.mermaidContent,
      meta: {
        id: dbFlowchart.id,
        title: dbFlowchart.title,
        description: dbFlowchart.description || '',
        emoji: dbFlowchart.emoji || '๐Ÿ“Š',
        difficulty: (dbFlowchart.difficulty as FlowchartMeta['difficulty']) || 'Beginner',
      },
      source: 'database',
      authorId: dbFlowchart.userId,
      version: dbFlowchart.version,
      publishedAt: dbFlowchart.publishedAt,
    }
  }

  return null
}
 
/**
 * Get list of all published flowcharts from the database.
 * Use this in API routes and server components.
 *
 * NOTE: Flowcharts must be seeded to the database first using the Seed Manager
 * (debug mode on /flowchart) before they appear in this list.
 *
 * @returns List of all published flowchart metadata
 */
export async function getFlowchartListAsync(): Promise<FlowchartMetaWithSource[]> {
  // Dynamic import to avoid circular dependencies
  const { db, schema } = await import('@/db')
  const { desc, eq } = await import('drizzle-orm')

  // Get published flowcharts from database only
  const dbFlowcharts = await db.query.teacherFlowcharts.findMany({
    where: eq(schema.teacherFlowcharts.status, 'published'),
    orderBy: [desc(schema.teacherFlowcharts.publishedAt)],
    columns: {
      id: true,
      title: true,
      description: true,
      emoji: true,
      difficulty: true,
      userId: true,
      publishedAt: true,
    },
  })

  return dbFlowcharts.map((fc) => ({
    id: fc.id,
    title: fc.title,
    description: fc.description || '',
    emoji: fc.emoji || '๐Ÿ“Š',
    difficulty: (fc.difficulty as FlowchartMeta['difficulty']) || 'Beginner',
    source: 'database' as const,
    authorId: fc.userId,
    publishedAt: fc.publishedAt,
  }))
}