Generate CASTLE timesheet TSVs for UNSW casual tutor payments.
CASTLE is UNSW's timesheet/payment platform. This library provides a
Python API that makes generating the required TSV imports straightforward:
declare tutors, register their activities, and flush() to emit the TSV.
The library automatically handles:
- Prep-hour logic: TUT_STD absorbs a prep hour; workshops get an explicit DMPR_STD row only when needed.
- Repeat detection: second tutorial in a week → TUT_RPT (no prep); second workshop → no separate prep row.
- Cross-type optimisation: if a tutor has both a TLB (primary) and a workshop in the same week, the TUT_STD prep covers both — no DMPR_STD.
pip install castle_tsv/ # from the repo root
pip install -e castle_tsv/ # editable/dev mode (if pip supports it)
# or just set PYTHONPATH:
PYTHONPATH=castle_tsv python3 my_script.pyRequires Python 3.9+. No runtime dependencies.
from castle_tsv import init, tutor, all_tutors, workshop, meeting, marking, flush
WEEKS = [1, 2, 3, 4, 5, 7, 8, 9, 10]
init("COMP1234", WEEKS)
alice = tutor("Alice Smith", "z1111111")
bob = tutor("Bob Jones", "z2222222")
workshop("T16A", alice, bob)
workshop("W13A", alice, bob)
meeting("Weekly meeting", all_tutors(), hours=1)
marking("Assign1 marking", all_tutors(), weeks=[7, 8], hours=3)
flush() # writes TSV to stdoutpython3 my_script.py > castle_import.tsv| Function | Description |
|---|---|
init(course_code, default_weeks=None) |
Initialise (or reset) for a new run. default_weeks is the list of week numbers used when activities don't specify their own. |
tutor(name, zid) → Tutor |
Register a tutor. The z prefix is stripped for the TSV output. |
all_tutors() → list[Tutor] |
Returns a copy of all tutors registered via tutor(). |
| Function | Signature | Paycodes emitted |
|---|---|---|
tlb |
(class_id, primary, assistant, *, weeks, tut_hours=1, demo_hours=2) |
Primary: TUT_STD or TUT_RPT + DEMO. Assistant: DEMO (+ DMPR_STD if first). |
workshop |
(class_id, tutor_a, tutor_b, *, weeks, hours=2) |
Both tutors: DEMO (+ DMPR_STD for first workshop that week). |
demo |
(class_id, tutors, *, weeks, hours=2) |
DEMO for each tutor (+ DMPR_STD for first). Same prep rules as workshop. |
| Function | Paycode |
|---|---|
marking(description, tutors, *, weeks, hours) |
PAY MARK STD |
meeting(description, tutors, *, weeks, hours) |
PAY MTG STD |
student_consultation(description, tutors, *, weeks, hours) |
PAY SCO STD |
course_dev(description, tutors, *, weeks, hours) |
PAY CRDV STD |
training(description, tutors, *, weeks, hours) |
PAY TRN STD |
prep(description, tutors, *, weeks, hours) |
PAY DMPR STD |
custom(description, tutors, *, weeks, hours, paycode) |
Any paycode |
| Function | Description |
|---|---|
flush(out=None) |
Resolve prep/repeat logic and emit the TSV. Writes to out (default: stdout). |
Per tutor, per week:
- Has TLB primary role: first gets
TUT_STD(includes prep), rest getTUT_RPT. All DEMO rows have no separate prep —TUT_STDcovers it. - No TLB primary (workshops/assistants only): all get
DEMO, first gets aDMPR_STDprep row. - Mixed TLB primary + workshops:
TUT_STDabsorbs prep for everything.
This means registration order doesn't matter — the system sees all activities before resolving.
| Column | Description |
|---|---|
| COURSE_CODE | From init() |
| CASUAL_ZID | Numeric zID (no z prefix) |
| CASUAL_NAME | Tutor's name |
| ACTIVITY_DESCRIPTION | e.g. T16A workshop, Assign1 marking, Prep |
| WEEKS | Week number (not count) |
| VARIATION_HOURS | e.g. 2 hours, 1.5 hours |
| PAYCODE | CASTLE paycode string |
Rows are sorted by tutor name → week → paycode → description.
All 76 CASTLE paycodes are available as constants:
from castle_tsv import PAY_DEMO, PAY_TUT_STD, PAY_MARK_PHD, ...The convenience functions use Std-tier paycodes. For PhD/CCO tiers or
uncommon duty types, use custom():
from castle_tsv import custom, PAY_DEMO_PHD
custom("W09A lab", [phd_tutor], weeks=[1,2,3], hours=2, paycode=PAY_DEMO_PHD)Full paycode list
| Constant | CASTLE code | Description |
|---|---|---|
PAY_LECT_STD |
PAY LECT STD | Lecture Standard |
PAY_LECT3AWT |
PAY LECT3AWT | Lecture - 3 hours AWT |
PAY_LECT4AWT |
PAY LECT4AWT | Lecture - 4 hours AWT |
PAY_LECTSPEX |
PAY LECTSPEX | Lecture - Special expertise |
PAY_LECT_SIG |
PAY LECT SIG | Lecture with Planning+Development |
PAY_LECT_DIS |
PAY LECT DIS | Lecture Distinguished |
PAY_LECT_RPT |
PAY LECT RPT | Repeat Lecture within 7 days |
PAY_SEM_STD |
PAY SEM STD | Seminar Primary |
PAY_SEM3AWT |
PAY SEM3AWT | Seminar - 3 hours AWT |
PAY_SEM4AWT |
PAY SEM4AWT | Seminar - 4 hours AWT |
PAY_SEMSPEX |
PAY SEMSPEX | Seminar - Special expertise |
PAY_SEM_SIG |
PAY SEM SIG | Seminar with Planning+Development |
PAY_SEM_DIS |
PAY SEM DIS | Seminar Distinguished |
PAY_SEM_RPT |
PAY SEM RPT | Repeat Seminar within 7 days |
PAYSEMSU_STD |
PAYSEMSU STD | Seminar Supplementary (Std) |
PAYSEMSUPHD |
PAYSEMSUPHD | Seminar Supplementary (PhD) |
PAY_SEMSUCCO |
PAY SEMSUCCO | Seminar Supplementary (CCO) |
PAYSEMSURPT |
PAYSEMSURPT | Repeat Seminar Supplementary (Std) |
PAYSEMSPHDRP |
PAYSEMSPHDRP | Repeat Seminar Supplementary (PhD) |
PAYSEMSUCRP |
PAYSEMSUCRP | Repeat Seminar Supplementary (CCO) |
PAY_CLSESS |
PAY CLSESS | Clinical Sessions - Medicine |
PAY_TUT_STD |
PAY TUT STD | Tutorial Standard |
PAY_TUTPHD |
PAY TUTPHD | Tutorial (PhD) |
PAY_TUT_CCO |
PAY TUT CCO | Tutorial (CCO) |
PAY_TUT_RPT |
PAY TUT RPT | Repeat Tutorial within 7 days |
PAY_TUTPHDRP |
PAY TUTPHDRP | Repeat Tutorial (PhD) |
PAY_TUTCCORP |
PAY TUTCCORP | Repeat Tutorial (CCO) |
PAY_MARK_STD |
PAY MARK STD | Marking Routine |
PAY_MARK_PHD |
PAY MARK PHD | Marking Routine (PhD) |
PAY_MARK_SUP |
PAY MARK SUP | Marking - Significant Academic Judgement |
PAY_MUSACC1 |
PAY MUSACC1 | Music Accompanying (Std) |
PAY_MUSACC2 |
PAY MUSACC2 | Music Accompanying (PhD/CCO) |
PAY_DEMO |
PAY DEMO | Practical Class Delivery |
PAY_DEMO_PHD |
PAY DEMO PHD | Practical Class Delivery (PhD) |
PAY_DEMO_CCO |
PAY DEMO CCO | Practical Class Delivery (CCO) |
PAYPRCLSDELD |
PAYPRCLSDELD | Practical Class Delivery Lead |
PAYPRCLSLDPD |
PAYPRCLSLDPD | Practical Class Delivery Lead (PhD) |
PAYPRCLSLDCC |
PAYPRCLSLDCC | Practical Class Delivery Lead (CCO) |
PAY_DMPR_STD |
PAY DMPR STD | Practical Class Preparation |
PAY_DMPR_PHD |
PAY DMPR PHD | Practical Class Preparation (PhD) |
PAY_DMPR_CCO |
PAY DMPR CCO | Practical Class Preparation (CCO) |
PAY_LATT_STD |
PAY LATT STD | Lecture Attendance |
PAY_LATT_PHD |
PAY LATT PHD | Lecture Attendance (PhD) |
PAY_LATT_CCO |
PAY LATT CCO | Lecture Attendance (CCO) |
PAY_SCO_STD |
PAY SCO STD | Student Consultation |
PAY_SCO_PHD |
PAY SCO PHD | Student Consultation (PhD) |
PAY_SCO_CCO |
PAY SCO CCO | Student Consultation (CCO) |
PAY_SSUP_STD |
PAY SSUP STD | Student Supervision |
PAY_SSUP_PHD |
PAY SSUP PHD | Student Supervision (PhD) |
PAY_SSUP_CCO |
PAY SSUP CCO | Student Supervision (CCO) |
PAY_MTG_STD |
PAY MTG STD | Meeting Attendance |
PAY_MTG_PHD |
PAY MTG PHD | Meeting Attendance (PhD) |
PAY_MTG_CCO |
PAY MTG CCO | Meeting Attendance (CCO) |
PAYTCHASSSTD |
PAYTCHASSSTD | Assistance Lect/Tutor/Seminar |
PAYTCHASSPHD |
PAYTCHASSPHD | Assistance Lect/Tutor/Seminar (PhD) |
PAYTCHASSCCO |
PAYTCHASSCCO | Assistance Lect/Tutor/Seminar (CCO) |
PAY_TRN_STD |
PAY TRN STD | Training |
PAY_TRN_PHD |
PAY TRN PHD | Training (PhD) |
PAY_TRN_CCO |
PAY TRN CCO | Training (CCO) |
PAYSTUFLDSTD |
PAYSTUFLDSTD | Student Field Excursion |
PAYSTUFLDPHD |
PAYSTUFLDPHD | Student Field Excursion (PhD) |
PAYSTUFLDCCO |
PAYSTUFLDCCO | Student Field Excursion (CCO) |
PAYNONMEDSTD |
PAYNONMEDSTD | Non-MED Clinical Sessions |
PAYNONMEDPHD |
PAYNONMEDPHD | Non-MED Clinical Sessions (PhD) |
PAYNONMEDCCO |
PAYNONMEDCCO | Non-MED Clinical Sessions (CCO) |
PAYPRFVASSTD |
PAYPRFVASSTD | Performing & Visual Art Studio |
PAYPRFVASPHD |
PAYPRFVASPHD | Performing & Visual Art Studio (PhD) |
PAYPRFVASCCO |
PAYPRFVASCCO | Performing & Visual Art Studio (CCO) |
PAY_CCO_CCO |
PAY CCO CCO | Course Coordination Duties |
PAY_MSC_STD |
PAY MSC STD | Music Coach/Repetiteur/Accompanist |
PAY_MSC_PHD |
PAY MSC PHD | Music Coach/Repetiteur/Accompanist (PhD) |
PAY_MSC_CCO |
PAY MSC CCO | Music Coach/Repetiteur/Accompanist (CCO) |
PAY_CRDV_STD |
PAY CRDV STD | Course Development |
PAY_CRDV_PHD |
PAY CRDV PHD | Course Development (PhD) |
PAY_CRDV_CCO |
PAY CRDV CCO | Course Development (CCO) |
PAY_COPSUP |
PAY COPSUP | Course Operations Support |
PAYCOPSUPPHD |
PAYCOPSUPPHD | Course Operations Support (PhD) |
PAYCOPSUPCCO |
PAYCOPSUPCCO | Course Operations Support (CCO) |
PAY_OTH_DUTY |
PAY OTH DUTY | Other Duties |
cd castle_tsv
PYTHONPATH=. python3 -m pytest tests/ -vTests use snapshot/golden-file comparison. Each tests/fixtures/*.py script
has a corresponding .tsv file with expected output. To regenerate after
intentional changes:
PYTHONPATH=. python3 -m pytest tests/ --update-snapshotsSee examples/ for complete scripts:
workshops_only.py— course with workshop-style classestlb_course.py— course with tutorial-laboratory sessionsmixed_course.py— kitchen-sink example with all activity types