I work on GTU Hero, a site that organises GTU (Gujarat Technological University) exam papers. This is a small data-modelling note from that work, and it applies to any project that indexes exam papers or course material.
The problem: subject name is not a safe key
GTU Maths 1 exists under three subject codes: 3110014, BE01000041 and BE01R00041. They are all "Maths 1" by name, but the modules are not the same:
- 3110014: calculus, sequences and series, Fourier series, multivariable calculus, multiple integrals, matrices. 5 credits.
- BE01000041 (w.e.f. 2024-25): no Fourier series, no matrices. 4 credits.
- BE01R00041 (w.e.f. 2025-26): the same five modules as BE01000041, only the hours and weightage differ.
If you key papers by subject name, a student on BE01000041 can end up solving a 3110014 paper and spending time on Fourier series, which is not in their syllabus. Keying by subject code keeps each paper attached to the syllabus version it was set for.
A tiny model
A dictionary from code to modules is enough to start with:
SYLLABUS = { "3110014": { "calculus", "sequences and series", "fourier series", "multivariable calculus", "multiple integrals", "matrices", }, "BE01000041": { "calculus", "sequences and series", "multivariable calculus", "multiple integrals", }, "BE01R00041": { "calculus", "sequences and series", "multivariable calculus", "multiple integrals", }, } Note that BE01R00041 has the same module set as BE01000041. The differences (hours, weightage) would live in separate fields, so I keep modules as their own set.
Flagging out-of-syllabus questions
Each question in an old paper is tagged with a module. Given the student's current code, we can flag the questions that are out of syllabus:
def out_of_syllabus(paper_questions, student_code): """paper_questions: list of (question_id, module) from an old paper.""" allowed = SYLLABUS[student_code] return [qid for qid, module in paper_questions if module not in allowed] old_paper = [ ("Q1", "calculus"), ("Q2", "fourier series"), ("Q3", "matrices"), ("Q4", "multiple integrals"), ] print(out_of_syllabus(old_paper, "BE01000041")) # ['Q2', 'Q3'] The same function works the other way round too. If a student on 3110014 opens a newer paper, you can compare module sets and see what is missing.
Why this is worth doing early
- Subject codes are stable identifiers. Names get reused across syllabus versions.
- Storing modules per code lets you answer "is this question still relevant?" with a set lookup instead of manual checking.
- When a new code appears, you add one entry instead of reworking your data.
Takeaway
Key by subject code, store modules per code, and compute relevance instead of assuming that same name means same syllabus. That is the whole idea, and it is a good first data-modelling exercise if you are learning Python.
If you want to see the papers this applies to, they are here: GTU Hero.



