{
  "name": "Setup: Generate Topic Buffet",
  "nodes": [
    {
      "parameters": {},
      "id": "manual-trigger",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        250,
        300
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "filePath": "e:/repos/golearn/.archive/weeks/quarter1_weeks.json",
        "options": {}
      },
      "id": "read-q1",
      "name": "Read Q1 Weeks",
      "type": "n8n-nodes-base.readBinaryFile",
      "position": [
        450,
        200
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "filePath": "e:/repos/golearn/.archive/weeks/quarter2_weeks.json",
        "options": {}
      },
      "id": "read-q2",
      "name": "Read Q2 Weeks",
      "type": "n8n-nodes-base.readBinaryFile",
      "position": [
        450,
        300
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "filePath": "e:/repos/golearn/.archive/weeks/quarter3_weeks.json",
        "options": {}
      },
      "id": "read-q3",
      "name": "Read Q3 Weeks",
      "type": "n8n-nodes-base.readBinaryFile",
      "position": [
        450,
        400
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "filePath": "e:/repos/golearn/.archive/weeks/quarter4_weeks.json",
        "options": {}
      },
      "id": "read-q4",
      "name": "Read Q4 Weeks",
      "type": "n8n-nodes-base.readBinaryFile",
      "position": [
        450,
        500
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "mode": "mergeByIndex",
        "options": {}
      },
      "id": "merge-files",
      "name": "Merge All Quarters",
      "type": "n8n-nodes-base.merge",
      "position": [
        650,
        300
      ],
      "typeVersion": 2.1
    },
    {
      "parameters": {
        "jsCode": "// Combine all JSON files into one string\nconst items = $input.all();\nconst files = items.map(item => {\n  if (item.binary && item.binary.data) {\n    const buffer = Buffer.from(item.binary.data.data);\n    return JSON.parse(buffer.toString('utf8'));\n  }\n  return item.json;\n});\n\nconst combined = JSON.stringify(files, null, 2);\n\nreturn {\n  json: {\n    allWeeks: combined\n  }\n};",
        "mode": "runOnceForAllItems"
      },
      "id": "combine-json",
      "name": "Combine JSON",
      "type": "n8n-nodes-base.code",
      "position": [
        850,
        300
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "model": "gpt-4-turbo-preview",
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are a curriculum data extractor. Extract structured learning concepts from curriculum data."
            },
            {
              "role": "user",
              "content": "=Extract 52 weeks from this curriculum data into a JSON array.\n\nSTRICT FORMAT (no markdown, no explanation, ONLY the JSON array):\n\n[{\n  \"week_id\": int (1-52),\n  \"title\": string,\n  \"quarter\": int (1-4),\n  \"concepts\": [array of 3-5 strings describing actionable skills like \"implement connection pooling\" or \"write table-driven tests\"],\n  \"prerequisite_week_ids\": [int array of weeks that should be learned first]\n}]\n\nRULES:\n- Concepts must be specific verbs + objects (e.g., \"implement connection pooling\", \"write prepared statements\")\n- NOT vague nouns (e.g., NOT \"databases\" or \"testing\")\n- prerequisite_week_ids should reference earlier weeks that teach foundational skills\n- Week 1-4 have no prerequisites\n- Return ONLY valid JSON array, no markdown backticks\n\nCURRICULUM DATA:\n{{ $json.allWeeks }}"
            }
          ]
        },
        "options": {
          "temperature": 0.3,
          "maxTokens": 4000
        },
        "jsonOutput": true
      },
      "id": "openai-extract",
      "name": "OpenAI Extract Concepts",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1050,
        300
      ],
      "typeVersion": 1.3
    },
    {
      "parameters": {
        "filePath": "e:/repos/golearn/data/topic_buffet.json",
        "options": {
          "encoding": "utf8"
        }
      },
      "id": "write-buffet",
      "name": "Write Topic Buffet",
      "type": "n8n-nodes-base.writeBinaryFile",
      "position": [
        1250,
        300
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "jsCode": "// Parse response and seed database\nconst Database = require('better-sqlite3');\nconst db = new Database('e:/repos/golearn/data/curriculum.db');\n\nconst buffet = JSON.parse($json.message.content);\n\n// Extract all unique concepts\nconst allConcepts = new Set();\nbuffet.forEach(week => {\n  week.concepts.forEach(concept => {\n    allConcepts.add(concept.toLowerCase().trim());\n  });\n});\n\n// Insert concepts into database\nconst stmt = db.prepare('INSERT OR IGNORE INTO concept_mastery (concept_name, current_score, times_seen) VALUES (?, 0, 0)');\n\nlet inserted = 0;\nfor (const concept of allConcepts) {\n  const result = stmt.run(concept);\n  if (result.changes > 0) inserted++;\n}\n\ndb.close();\n\nreturn {\n  json: {\n    total_concepts: allConcepts.size,\n    inserted: inserted,\n    buffet: buffet\n  }\n};"
      },
      "id": "seed-db",
      "name": "Seed Database",
      "type": "n8n-nodes-base.code",
      "position": [
        1450,
        300
      ],
      "typeVersion": 2
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Read Q1 Weeks",
            "type": "main",
            "index": 0
          },
          {
            "node": "Read Q2 Weeks",
            "type": "main",
            "index": 0
          },
          {
            "node": "Read Q3 Weeks",
            "type": "main",
            "index": 0
          },
          {
            "node": "Read Q4 Weeks",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Q1 Weeks": {
      "main": [
        [
          {
            "node": "Merge All Quarters",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Q2 Weeks": {
      "main": [
        [
          {
            "node": "Merge All Quarters",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Read Q3 Weeks": {
      "main": [
        [
          {
            "node": "Merge All Quarters",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Read Q4 Weeks": {
      "main": [
        [
          {
            "node": "Merge All Quarters",
            "type": "main",
            "index": 3
          }
        ]
      ]
    },
    "Merge All Quarters": {
      "main": [
        [
          {
            "node": "Combine JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine JSON": {
      "main": [
        [
          {
            "node": "OpenAI Extract Concepts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Extract Concepts": {
      "main": [
        [
          {
            "node": "Write Topic Buffet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write Topic Buffet": {
      "main": [
        [
          {
            "node": "Seed Database",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionTimeout": 300
  }
}