TIS (Teaching Information System)¶
教学信息管理系统 — exam schedule, grades, course info, campus schedule, timetable solver.
Auth: TISAuth — CAS-authenticated session via sustech_survival.sso. See SSO for credential setup.
⚠️ Access levels: Student (学生(本)) vs teacher. Some endpoints are 403 for students.
Authentication¶
from sustech_survival.sso import TISAuth
auth = TISAuth() # singleton-per-class
ok, reason = auth.ensure() # check + auto-refresh if expired
if not ok:
raise RuntimeError(reason)
# Use the authenticated session for all TIS calls
r = auth.get("/xszykb/queryxszykbzhou", json={"xn": "2025-2026", "xq": "2", "zc": 1})
Or with the decorator:
from sustech_survival.sso import require_auth, TISAuth
@require_auth(TISAuth)
def fetch_exams(auth=None):
return auth.get("/component/queryKsxxByXs", json={}).json()
# CLI — auth is automatic (ensure()); diagnose only when something fails
sustech sso check # verify credentials against CAS
sustech sso creds set # write / update the credentials file
CLI Overview¶
sustech tis courses # list current in-progress term's enrolled courses (timetable)
sustech tis courses --all # list every term: current (timetable) + past terms with posted grades
sustech tis courses --semester 2026春季 # list one specific past term (grade records)
sustech tis grades # show grades + GPA
sustech tis grades --csv path/to/file # export CSV
sustech tis evals # list pending evaluations
sustech tis evals --pending # only unsubmitted
sustech tis query /component/querydangqianzc # raw API query
User Profile¶
Returns:studentId, id (internal), name, department, pylx (student type), 50+ auth codes.
Access: ✅ Student
Grades¶
POST https://tis.sustech.edu.cn/cjgl/grcjcx/grcjcx
Content-Type: application/json
Body: {"xn":null,"xq":null,"kcmc":null,"cxbj":"-1","pylx":"1","current":1,"pageSize":500}
content.list[] with kcmc, kcmc_en, kcdm, xscj (letter grade), zzcj (numeric score), xf (credits), xnxqmc (semester), kcxz (nature), yxmc (department).
Access: ✅ Student
Python API¶
from sustech_survival.tis.grades import run
run() # all semesters, table output
run(semester='2025秋季') # one semester
run(export='csv') # ~/.sustech_survival/exports/grades.csv
GPA is calculated using SUSTech's official 4.0 scale (A=3.94, A-=3.67, ...). See grades.md for the full GPA table.
Courses¶
from sustech_survival.tis.courses import run
run() # all semesters, table output
run(semester='2026春季')
run(format='csv') # exports to courses_tis.csv
Uses the same TIS grade API as grades (returns all course records including ungraded ones). Groups by semester and prints instructor, credits, course type.
| Field | Meaning |
|---|---|
kcdm |
Course code |
kcmc |
Course name |
xf |
Credits |
dgjsmc |
Instructor |
kcxz |
Course type |
yxmc |
Department |
Personal Weekly Schedule¶
REST API — xszykb endpoints (no browser):
POST https://tis.sustech.edu.cn/xszykb/queryxszykbzhou # one week
POST https://tis.sustech.edu.cn/xszykb/queryxszykbzong # full semester
GET https://tis.sustech.edu.cn/component/querydangqianzc # current week number
| Endpoint | Params | Returns |
|---|---|---|
/xszykb/queryxszykbzhou |
xn, xq, zc |
Personal schedule for week zc |
/xszykb/queryxszykbzong |
xn, xq |
Full semester (all weeks), includes ZC bitmap |
/component/querydangqianzc |
— | Current week number (int, 1-18) |
/component/querydangqianxnxq |
— | Current semester: XN, XQ, XNXQ, XNXQ_EN |
Key fields in each entry:
| Field | Meaning |
|---|---|
SKSJ |
Course + teacher + class + weeks + room + periods (Chinese) |
SKSJ_EN |
Same as above in English |
KEY |
"xq{weekday}_jc{period}" e.g. "xq2_jc3" = Tuesday period 3 |
KSJC / JSJC |
Start / end period number (1-12, 13=evening) |
ZC |
36-char bitmap — which weeks the course runs (full semester only) |
XB |
Number of periods per week for this entry |
RWH |
Course record ID: {xn}-{xq}-{kcdm}-{section} |
Python API¶
from sustech_survival.tis.schedule import (
current_semester, current_week, week_schedule,
semester_schedule, week_list
)
sem = current_semester() # {'XN': '2025-2026', 'XQ': '2', 'XNXQ': '2026春季', ...}
zc = current_week() # 14
wk = week_schedule(zc) # list of course entries for this week
all = semester_schedule() # full semester
⚠️ Why not kebiaoshow component: The inco.component.kebiaoshow Vue component renders the schedule grid but does not fetch course data itself — it receives kbjg as a prop from a parent. The actual data source is the xszykb API.
Exam Schedule¶
Returns: current semester exam entries. Key fields:KCMC (course), KCDM (code), KSRQ (date), KSJTSJ (time), JXLMC (building), JXCDMC (room), XQJMC (weekday), KSSJDMC (type), XNXQMC (semester).
Note: Returns the active semester only. Body xn/xq params are accepted but ignored.
Access: ✅ Student
from sustech_survival.tis.exams import run
run() # display exam schedule
run(export='csv') # export to CSV
Campus-wide Course Schedule (全校课表)¶
POST https://tis.sustech.edu.cn/Xsxktz/queryRwxxcxList
Content-Type: application/x-www-form-urlencoded
Form data:
p_xn=2025-2026 academic year
p_xq=2 semester (1=fall, 2=spring)
p_chaxunpylx= cultivation type filter:
'' = default filtered view (~188/sem)
'1' = undergrad only (~1200/sem for Spr2026)
'2' = grad only (~445/sem)
'3' = full campus list (1488 for Spr2026, paginate)
p_xiaoqu= campus ("一期校区", "二期校区", etc.)
p_kkyx= college code
p_kclb= course category code (from queryKclb)
p_kcxz= course nature ("必修", "选修")
p_gjz= keyword search
p_rwlx= task type
pageNum=1
pageSize=500 max per page; use full=True in code to auto-paginate
Returns: {total: N, pageSize: 500, rwList: {list: [courses]}}
Key course fields:
- kcmc / kcmc_en — course name (Chinese / English)
- kcdm — course code (e.g. MSE306)
- kkyxmc — college/department
- dgjsmc — instructor
- sksj — time slots (e.g. "1-15周,星期三第3-4节")
- xf — credits
- kclbmc — category (培养环节, 专业基础课, 专业必修课, etc.)
- kcxzmc — nature (必修/选修)
- xiaoqumc — campus
- nj — grade level
- pylx — student type (1=undergrad, 2=grad)
from sustech_survival.tis.campus_schedule import get_campus_schedule, get_semester_courses
courses = get_semester_courses(semester="2025-2026-2", full=True)
Course Category Tree (培养环节 etc.)¶
Returns: 26-node category hierarchy. Top-level categories:| Code | Name | Subcategories |
|---|---|---|
| 01 | 培养环节 | 劳动教育, 军事理论, 创业创新, ... |
| 03 | 专业基础课 | (理科大类, 工科大类 etc.) |
| 04 | 专业必修课 | |
| 05 | 专业选修课 | |
| 06 | 专业核心课 | |
| 07 | 通识必修课 | 思政类, 体育类, 外语类, 军理类, 计算机类 |
| 08 | 通识选修课 | 人文类, 社科类, 艺术类, 生命健康类, 工程认证类 |
Access: ✅ Student
Timetable Conflict Solver¶
Given a list of course codes, finds all non-conflicting section combinations for a semester.
Usage¶
python -m sustech_survival.tis.timetable MSE306 MSE202 MSE210 --max 5
python -m sustech_survival.tis.timetable MSE306 EAP --exclude SS143 --semester 2025-2026-2
Flags:
- --exclude CODE — remove a course from the search (e.g. already taken)
- --codes-file F — read course codes from file (one per line)
- --semester Y-Q — academic year and quarter (default: 2025-2026-2)
- --max N — max schedules to show (default: 100)
- --json — output as JSON
How it works¶
- Authenticates via
TISAuth().ensure() - For each course code, queries
POST /Xsxktz/queryRwxxcxListwithp_gjz=<code>+p_chaxunpylx=1(undergrad) - Parses
pkjgmx_enHTML field — extracts plain text from<p>tags, then regex-matches English slot format:1-15单Week,Mon. 5-6 一教321 - Backtracking solver: tries all combinations, skips any with time slot conflicts
- Renders ASCII grid or JSON
Slot format (pkjgmx_en English HTML)¶
Regex: (\d[\d,-]+)(单|双)?Week,(Mon|Tue|Wed|Thu|Fri|Sat|Sun)\.? (\d+-\d+|\d+) (.+)
Blocked (FineReport — browser-only)¶
These pages render entirely in-browser via FineReport JS. No REST equivalent found.
| Page | URL | Contains |
|---|---|---|
| 学业修读情况 | /browserRedirect/queryReport?viewlet=byyt/xsxy/学业修读情况.cpt |
Per-category credit totals |
| 培养方案 | /browserRedirect/queryReport?viewlet=byyt/pyfa/培养方案.cpt |
Curriculum requirements |
| 学分绩查询 | /cjgl/xscjgl/xsgrcjcx/xspjxfjcx |
GPA details |
Access: ❌ CLI (browser-only)
See also¶
- SSO — credential setup and auth infrastructure
- Courses — enrolled course data fields
- Grades — grade records and GPA calculation
Python run() CSV exports use ~/.sustech_survival/exports/ (or the relocated SUSTECH_HOME root). Classroom commands use the current term unless --xn / --xq is given; --json emits JSON only.