{
  "id": "sz0OoW5pAdSjMHvD",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI-powered IELTS Practice Bot that automatically delivers Grammar, Writing, and Reading exercises via Telegram.",
  "tags": [],
  "nodes": [
    {
      "id": "b9aaaaa5-6d7e-4359-8545-a163026ec006",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -656,
        272
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "30e8a8a9-75b4-4ae6-bc3e-508df0237649",
      "name": "Parse Grammar JSON",
      "type": "n8n-nodes-base.code",
      "position": [
        496,
        32
      ],
      "parameters": {
        "jsCode": "const raw = $input.first().json.content.parts[0].text;\n\nlet parsed;\n\ntry {\n  parsed = JSON.parse(raw);\n} catch (e) {\n  throw new Error(\"Invalid JSON from Gemini\");\n}\n\nreturn [{\n  json: parsed\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "27926908-a37c-417f-b170-5b99cb1bb579",
      "name": "Parse Writing JSON",
      "type": "n8n-nodes-base.code",
      "position": [
        496,
        272
      ],
      "parameters": {
        "jsCode": "const raw = $input.first().json.content.parts[0].text;\n\nlet parsed;\n\ntry {\n  parsed = JSON.parse(raw);\n} catch (e) {\n  throw new Error(\"Invalid JSON from Gemini\");\n}\n\nreturn [{\n  json: parsed\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "90baa690-58e6-44f4-91e8-5ea77e80c736",
      "name": "Parse Reading JSON",
      "type": "n8n-nodes-base.code",
      "position": [
        512,
        496
      ],
      "parameters": {
        "jsCode": "const raw = $input.first().json.content.parts[0].text;\n\nlet parsed;\n\ntry {\n  parsed = JSON.parse(raw);\n} catch (e) {\n  throw new Error(\"Invalid JSON from Gemini\");\n}\n\nreturn [{\n  json: parsed\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "70220773-c31e-4282-8f65-c99005cc52ef",
      "name": "Format Grammar Message",
      "type": "n8n-nodes-base.code",
      "position": [
        768,
        32
      ],
      "parameters": {
        "jsCode": "const data = $input.first().json;\n\nlet message = `<b>\ud83d\udcd8 ${data.title}</b>\\n\\n`;\nmessage += `<b>\ud83d\udccc Topic:</b> ${data.topic}\\n\\n`;\n\nif (data.grammar_focus && data.grammar_focus.length) {\n  message += `<b>\ud83c\udfaf Grammar Focus:</b>\\n`;\n  data.grammar_focus.forEach((item) => {\n    message += `\u2022 ${item}\\n`;\n  });\n  message += `\\n`;\n}\n\nmessage += `<b>\ud83d\udcdd Questions</b>\\n`;\n\nif (data.questions && data.questions.length) {\n  data.questions.forEach((q) => {\n    message += `\\n<b>${q.number}. [${q.type}]</b>\\n`;\n    message += `${q.question}\\n`;\n\n    if (q.options && q.options.length) {\n      q.options.forEach((opt, i) => {\n        const label = String.fromCharCode(65 + i); // A, B, C, D\n        message += `${label}. ${opt}\\n`;\n      });\n    }\n\n    if (q.instruction) {\n      message += `<i>${q.instruction}</i>\\n`;\n    }\n  });\n} else {\n  message += `No questions available.\\n`;\n}\n\nreturn [\n  {\n    json: {\n      telegram_message: message\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "7bb780af-c504-4b61-a39f-bd438308be10",
      "name": "Format Writing Message",
      "type": "n8n-nodes-base.code",
      "position": [
        768,
        272
      ],
      "parameters": {
        "jsCode": "const data = $input.first().json;\n\nfunction esc(str = '') {\n  return String(str)\n    .replace(/&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;');\n}\n\nlet message = `<b>\u270d\ufe0f ${esc(data.title || 'IELTS Writing Practice')}</b>\\n\\n`;\n\nif (data.task_type) {\n  message += `<b>\ud83d\uddc2 Task Type:</b> ${esc(data.task_type)}\\n\\n`;\n}\n\nif (data.question) {\n  const cleanQuestion = String(data.question).replace(/\\n{3,}/g, '\\n\\n').trim();\n  message += `<b>\ud83d\udccc Question</b>\\n${esc(cleanQuestion)}\\n\\n`;\n}\n\nif (data.instructions) {\n  message += `<b>\ud83d\udccf Instructions:</b> ${esc(data.instructions)}\\n\\n`;\n}\n\nif (data.tips && data.tips.length) {\n  message += `<b>\ud83d\udca1 Tips</b>\\n`;\n  data.tips.forEach((tip, index) => {\n    message += `${index + 1}. ${esc(tip)}\\n`;\n  });\n  message += `\\n`;\n}\n\nmessage += `<b>\ud83d\udcdd Your Task</b>\\nWrite your answer and send it back to the bot for review.`;\n\nreturn [\n  {\n    json: {\n      telegram_message: message\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "c822a6c3-b9cc-4895-b3c3-38a2ad7448ef",
      "name": "Format Reading Message",
      "type": "n8n-nodes-base.code",
      "position": [
        784,
        496
      ],
      "parameters": {
        "jsCode": "const data = $input.first().json;\n\nlet message = `<b>\ud83d\udcd8 ${data.title}</b>\\n\\n`;\nmessage += `<b>\ud83d\udccc Topic:</b> ${data.topic}\\n\\n`;\n\n// Passage (dipotong biar tidak terlalu panjang)\nmessage += `<b>\ud83d\udcd6 Passage</b>\\n`;\nmessage += `${data.passage.slice(0, 800)}...\\n\\n`;\n\nmessage += `<b>\ud83d\udcdd Questions</b>\\n`;\n\ndata.questions.forEach(q => {\n  message += `\\n${q.number}. ${q.question}\\n`;\n});\n\nreturn [{\n  json: {\n    telegram_message: message\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "c88c8292-ad89-4028-8969-883021f1fa5e",
      "name": "Split Grammar Message",
      "type": "n8n-nodes-base.code",
      "position": [
        1024,
        32
      ],
      "parameters": {
        "jsCode": "const text = $input.first().json.telegram_message;\nconst chunkSize = 3500;\n\nconst chunks = [];\n\nfor (let i = 0; i < text.length; i += chunkSize) {\n  chunks.push({\n    json: {\n      telegram_message: text.slice(i, i + chunkSize)\n    }\n  });\n}\n\nreturn chunks;"
      },
      "typeVersion": 2
    },
    {
      "id": "e48d61df-e86d-47c3-83b7-0925b290990a",
      "name": "Split Writing Message",
      "type": "n8n-nodes-base.code",
      "position": [
        1024,
        272
      ],
      "parameters": {
        "jsCode": "const text = $input.first().json.telegram_message;\nconst chunkSize = 3500;\n\nconst chunks = [];\n\nfor (let i = 0; i < text.length; i += chunkSize) {\n  chunks.push({\n    json: {\n      telegram_message: text.slice(i, i + chunkSize)\n    }\n  });\n}\n\nreturn chunks;"
      },
      "typeVersion": 2
    },
    {
      "id": "e70875a8-ba2c-4812-88bd-8b8b26da0604",
      "name": "Split Reading Message",
      "type": "n8n-nodes-base.code",
      "position": [
        1040,
        496
      ],
      "parameters": {
        "jsCode": "const text = $input.first().json.telegram_message;\nconst chunkSize = 3500;\n\nconst chunks = [];\n\nfor (let i = 0; i < text.length; i += chunkSize) {\n  chunks.push({\n    json: {\n      telegram_message: text.slice(i, i + chunkSize)\n    }\n  });\n}\n\nreturn chunks;"
      },
      "typeVersion": 2
    },
    {
      "id": "1521f1e7-c531-46fb-b79c-8d27be4ea2fa",
      "name": "Send Grammar",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1264,
        32
      ],
      "parameters": {
        "text": "={{ $json.telegram_message }}",
        "chatId": "=REPLACE_WITH_YOUR_CHAT_ID",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "07002824-e293-4d19-b801-2edc7290e0c2",
      "name": "Send Writing",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1264,
        272
      ],
      "parameters": {
        "text": "={{ $json.telegram_message }}",
        "chatId": "=REPLACE_WITH_YOUR_CHAT_ID",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "19aad316-6aab-4963-810f-bf0dadff7e65",
      "name": "Send Reading",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1264,
        496
      ],
      "parameters": {
        "text": "={{ $json.telegram_message }}",
        "chatId": "=REPLACE_WITH_YOUR_CHAT_ID",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a7fcad5c-8273-4076-bf91-6e7026691f30",
      "name": "Select Test by Day",
      "type": "n8n-nodes-base.switch",
      "position": [
        -256,
        256
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Monday",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "9f245046-bd87-48d1-a3d4-f4d73e7d5c40",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json['Day of week'] }}",
                    "rightValue": "Monday"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Wednesday",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "4639f1b3-3d10-43f5-92a4-29c03ae90100",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json['Day of week'] }}",
                    "rightValue": "Wednesday"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Friday",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "ba76c005-4b7b-4774-bf3c-8db82ff17089",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json['Day of week'] }}",
                    "rightValue": "Friday"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "4267c86d-d14d-445c-a775-1cfb51864e84",
      "name": "Generate Grammar",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        64,
        32
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=You are an expert IELTS examiner with Band 9 proficiency, specializing in English grammar assessment.\n\nYour task is to generate a complete IELTS-style grammar practice exercise.\n\nTOPIC:\n[INSERT TOPIC HERE]\n\n========================\nGRAMMAR FOCUS\n========================\nFocus on common IELTS grammar areas such as:\n- Tenses (past, present, perfect)\n- Subject-verb agreement\n- Articles (a, an, the)\n- Prepositions\n- Conditionals\n- Passive voice\n- Relative clauses\n- Modals\n- Sentence structure\n\n========================\nEXERCISE REQUIREMENTS\n========================\nCreate EXACTLY 10 questions.\n\nInclude a mix of these types:\n- Fill in the blanks\n- Error correction\n- Sentence transformation\n- Multiple choice (grammar-based)\n- Sentence rewriting\n\nEach question must:\n- Be clear and unambiguous\n- Focus on ONE grammar concept\n- Be suitable for Band 6.0\u20137.5 level\n- Use natural English (not robotic)\n\n========================\nOUTPUT RULES (VERY IMPORTANT)\n========================\n- Return ONLY valid JSON\n- Do NOT include any explanation outside JSON\n- Do NOT include markdown formatting\n\n========================\nOUTPUT FORMAT\n========================\n\n{\n  \"title\": \"IELTS Grammar Practice\",\n  \"topic\": \"[INSERT TOPIC HERE]\",\n  \"grammar_focus\": [\"Tenses\", \"Articles\", \"Prepositions\"],\n  \"questions\": [\n    {\n      \"number\": 1,\n      \"type\": \"Fill in the blank\",\n      \"question\": \"She _____ (go) to the market yesterday.\",\n      \"options\": [],\n      \"instruction\": \"Write the correct form of the verb\"\n    },\n    {\n      \"number\": 2,\n      \"type\": \"Multiple Choice\",\n      \"question\": \"He has lived here _____ 2010.\",\n      \"options\": [\"since\", \"for\", \"during\", \"at\"],\n      \"instruction\": \"Choose the correct answer\"\n    }\n  ],\n  \"answer_key\": [\n    {\n      \"number\": 1,\n      \"answer\": \"went\"\n    },\n    {\n      \"number\": 2,\n      \"answer\": \"since\"\n    }\n  ],\n  \"explanations\": [\n    {\n      \"number\": 1,\n      \"explanation\": \"Past simple is used because the action happened yesterday.\"\n    },\n    {\n      \"number\": 2,\n      \"explanation\": \"'Since' is used with a specific point in time.\"\n    }\n  ],\n  \"next_exercise\": \"Create 3 similar sentences using past tense and time expressions.\"\n}"
            }
          ]
        },
        "jsonOutput": true
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "1aa2d22d-681e-4b72-9184-73242cb72eab",
      "name": "Generate Writing",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        64,
        272
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=You are an expert IELTS Writing examiner.\n\nGenerate one IELTS Writing task.\n\n========================\nREQUIREMENTS\n========================\n- Task type: Task 1 or Task 2\n- Use realistic IELTS question style\n- Clear instructions\n- Suitable for Band 6\u20137.5\n\n========================\nOUTPUT RULES\n========================\n- Return ONLY valid JSON\n- No markdown\n\n========================\nOUTPUT FORMAT\n========================\n\n{\n  \"title\": \"IELTS Writing Practice\",\n  \"task_type\": \"Task 2\",\n  \"question\": \"Some people believe that technology makes life easier, while others think it creates more problems. Discuss both views and give your opinion.\",\n  \"instructions\": \"Write at least 250 words.\",\n  \"tips\": [\n    \"State your opinion clearly\",\n    \"Use examples to support your ideas\",\n    \"Organize your essay into clear paragraphs\"\n  ]\n}"
            }
          ]
        }
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "bf1f34e2-a3e5-4dcb-a3be-ff7d066a1623",
      "name": "Generate Reading",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        64,
        496
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=You are an expert IELTS Academic Reading examiner with Band 9 proficiency.\n\nYour task is to generate a complete IELTS Academic Reading practice set.\n\nTOPIC:\n[INSERT TOPIC HERE]\n\n========================\nPASSAGE REQUIREMENTS\n========================\n- Length: 650\u2013850 words\n- Use formal academic tone\n- Use natural and varied academic vocabulary\n- Organize into clear paragraphs (3\u20135 paragraphs)\n- Match the style and difficulty of Cambridge IELTS tests\n\n========================\nQUESTION REQUIREMENTS\n========================\nCreate EXACTLY 13 questions.\n\n- Include at least 5 different IELTS question types:\n  \u2022 Matching Headings  \n  \u2022 True / False / Not Given  \n  \u2022 Multiple Choice  \n  \u2022 Sentence Completion  \n  \u2022 Summary Completion  \n  \u2022 Short Answer Questions  \n  \u2022 Matching Information / Features / Sentence Endings  \n  \u2022 Table / Flow-chart / Note Completion  \n\n- Questions must:\n  \u2022 Be fair and not ambiguous  \n  \u2022 Follow official IELTS format  \n  \u2022 Avoid trick questions  \n  \u2022 Be aligned with passage content  \n  \u2022 Target difficulty: Band 6.5\u20137.5  \n\n========================\nOUTPUT RULES (VERY IMPORTANT)\n========================\n- Return ONLY valid JSON\n- Do NOT include any explanation outside JSON\n- Do NOT include markdown formatting (no **, no #, no ```)\n\n========================\nOUTPUT FORMAT\n========================\n\n{\n  \"title\": \"IELTS Academic Reading Practice\",\n  \"topic\": \"[INSERT TOPIC HERE]\",\n  \"passage\": \"Full reading passage here...\",\n  \"questions\": [\n    {\n      \"number\": 1,\n      \"type\": \"Matching Headings\",\n      \"question\": \"Question text...\",\n      \"options\": [\"A\", \"B\", \"C\", \"D\"],\n      \"answer_format\": \"Write the correct letter...\"\n    }\n  ],\n  \"answer_key\": [\n    {\n      \"number\": 1,\n      \"answer\": \"B\"\n    }\n  ],\n  \"explanations\": [\n    {\n      \"number\": 1,\n      \"explanation\": \"Brief explanation for difficult questions...\"\n    }\n  ]\n}"
            }
          ]
        },
        "jsonOutput": true
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a511d3aa-ebeb-49d9-9b7b-1918f466516a",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1456,
        16
      ],
      "parameters": {
        "width": 624,
        "height": 784,
        "content": "\ud83d\udcd8 IELTS Practice Bot (Telegram + AI)\n\nThis workflow automatically generates IELTS practice content:\n- Monday \u2192 Grammar Practice\n- Wednesday \u2192 Writing Task\n- Friday \u2192 Reading Practice\n\nThe content is generated using AI and delivered via Telegram.\n\nFlow:\nSchedule Trigger \u2192 Select Test by Day \u2192 AI \u2192 Parse \u2192 Format \u2192 Split \u2192 Send Telegram\n\n\n\u2699\ufe0f Create Telegram BOT\n\n1. Create a Telegram Bot using @BotFather\n2. Copy your Bot Token\n3. Add Telegram credentials in n8n\n4. Add your AI (Gemini/OpenAI) credentials\n5. Activate the workflow\n\nMake sure your bot has started and received at least one message.\n\n\u26a0\ufe0f Important:\n\nYou must replace the Chat ID in the Send nodes.\n\nExample:\n- Find: REPLACE_WITH_YOUR_CHAT_ID\n- Replace with your own Chat ID\n\nTo get your Chat ID:\n1. Send a message to your bot\n2. Open:\nhttps://api.telegram.org/bot<TOKEN>/getUpdates\n3. Copy \"chat.id\""
      },
      "typeVersion": 1
    },
    {
      "id": "056ff272-7f0a-4ac4-a808-216bd3b3e3f2",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -736,
        144
      ],
      "parameters": {
        "color": 7,
        "width": 688,
        "height": 336,
        "content": "## Schedule Triggered\n\nThis workflow runs every day on a schedule. The output type changes depending on the day."
      },
      "typeVersion": 1
    },
    {
      "id": "f1113c60-7602-45f8-80b9-4f750c5c9199",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        16,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 336,
        "height": 896,
        "content": "## AI Generated\n\nThis workflow uses AI to generate IELTS content.\n\nMake sure to Connect your AI credentials (Gemini / OpenAI)"
      },
      "typeVersion": 1
    },
    {
      "id": "6ee4a005-5e8b-411d-97f5-d1b6e0b62035",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 272,
        "height": 896,
        "content": "## Parse\n\nParse AI output (Gemini) from raw text into valid JSON.\nThrows error if the response is not valid JSON"
      },
      "typeVersion": 1
    },
    {
      "id": "86bdc87d-a5b3-4c42-9b47-c7f477ffe337",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        704,
        -208
      ],
      "parameters": {
        "color": 7,
        "height": 896,
        "content": "## Format Data into Telegram Message\n\nConvert AI output into a readable Telegram message with formatting and question list"
      },
      "typeVersion": 1
    },
    {
      "id": "6096e460-6bfa-4059-b808-61d764734645",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        960,
        -208
      ],
      "parameters": {
        "color": 7,
        "height": 896,
        "content": "## Split Long Data\n\nSplit long Telegram message into smaller chunks to avoid message length limits."
      },
      "typeVersion": 1
    },
    {
      "id": "42f41d9f-389f-409f-b7e8-4a2b8942af22",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1216,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 896,
        "content": "## Send data to Telegram\n\nSend the formatted grammar message to Telegram.\n\nDon't forget to replace the Chat ID in the Send nodes.\n\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "21019972-bf5a-4f89-bc5b-ea5d0ee1a9c3",
  "connections": {
    "Send Reading": {
      "main": [
        []
      ]
    },
    "Generate Grammar": {
      "main": [
        [
          {
            "node": "Parse Grammar JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Reading": {
      "main": [
        [
          {
            "node": "Parse Reading JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Writing": {
      "main": [
        [
          {
            "node": "Parse Writing JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Select Test by Day",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Grammar JSON": {
      "main": [
        [
          {
            "node": "Format Grammar Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Reading JSON": {
      "main": [
        [
          {
            "node": "Format Reading Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Writing JSON": {
      "main": [
        [
          {
            "node": "Format Writing Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Select Test by Day": {
      "main": [
        [
          {
            "node": "Generate Grammar",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Generate Writing",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Generate Reading",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Grammar Message": {
      "main": [
        [
          {
            "node": "Send Grammar",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Reading Message": {
      "main": [
        [
          {
            "node": "Send Reading",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Writing Message": {
      "main": [
        [
          {
            "node": "Send Writing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Grammar Message": {
      "main": [
        [
          {
            "node": "Split Grammar Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Reading Message": {
      "main": [
        [
          {
            "node": "Split Reading Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Writing Message": {
      "main": [
        [
          {
            "node": "Split Writing Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}