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 544 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 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,
}))
}
|