Implement extra (non-IB) subject support, update README.md and TODO.md
This commit is contained in:
parent
e8f51079d7
commit
1a309834af
28
README.md
28
README.md
@ -1,6 +1,6 @@
|
|||||||
# ib-clearance
|
# ib-clearance
|
||||||
|
|
||||||
ib-clearance is a program which helps schools manage the entrance and exiting of their IB students. Due to the unique nature of IB students' timetables, the program helps check individual timetables and give clearance to students who have finished for the day.
|
ib-clearance is a program which helps schools manage the entrance and exiting of their IBDP students. Due to the unique nature of IB students' timetables, the program helps check individual timetables and give clearance to students who have finished for the day.
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
@ -10,44 +10,42 @@ I recommend building executables with `pyinstaller` with `pyinstaller --onefile
|
|||||||
|
|
||||||
## Database specification
|
## Database specification
|
||||||
|
|
||||||
The program requires SQLite databases for each IB class.
|
The program requires a SQLite database `database.db` in the working directory, containing info for all classes.
|
||||||
|
|
||||||
Each database must contain:
|
`database.db` must contain:
|
||||||
|
|
||||||
| Table | Description |
|
| Table | Description |
|
||||||
| ----------- | ---------------------------------------------------------- |
|
| ----------- | ------------------------------------------------------------ |
|
||||||
| `students` | Contains students' names, ID numbers and class preferences |
|
| `students` | Contains students' names, ID numbers and subject preferences |
|
||||||
| `timetable` | Timetable information for class |
|
| `timetable` | Timetable information (lessons) |
|
||||||
|
|
||||||
### `students`
|
### `students`
|
||||||
|
|
||||||
| Column | Data type | Description |
|
| Column | Data type | Description |
|
||||||
| ------ | --------- | --------------------------------- |
|
| --------------- | --------- | ----------------------------------------------- |
|
||||||
| `id` | `INTEGER` | Student ID number used in program |
|
| `id` | `INTEGER` | Student ID number used in program |
|
||||||
|
| `student_class` | `INTEGER` | IB class number (e.g. `1`, `2`) |
|
||||||
|
| `name` | `TEXT` | Full name of student |
|
||||||
| `g1` | `TEXT` | Group 1 subject ID |
|
| `g1` | `TEXT` | Group 1 subject ID |
|
||||||
| `g2` | `TEXT` | Group 2 subject ID |
|
| `g2` | `TEXT` | Group 2 subject ID |
|
||||||
| `g3` | `TEXT` | Group 3 subject ID |
|
| `g3` | `TEXT` | Group 3 subject ID |
|
||||||
| `g4` | `TEXT` | Group 4 subject ID |
|
| `g4` | `TEXT` | Group 4 subject ID |
|
||||||
| `g5` | `TEXT` | Group 5 subject ID |
|
| `g5` | `TEXT` | Group 5 subject ID |
|
||||||
| `g6` | `TEXT` | Group 6 subject ID |
|
| `g6` | `TEXT` | Group 6 subject ID |
|
||||||
| `name` | `TEXT` | Full name of student |
|
| `other` | `TEXT` | ID(s) of other class(es) taken, space seperated |
|
||||||
|
|
||||||
### `timetable`
|
### `timetable`
|
||||||
|
|
||||||
| Column | Data type | Description |
|
| Column | Data type | Description |
|
||||||
| ----------- | --------- | --------------------------------------------- |
|
| -------------- | --------- | --------------------------------------------- |
|
||||||
|
| `lesson_class` | `INTEGER` | IB class which takes lesson (e.g. `1`) |
|
||||||
| `day` | `TEXT` | Day of the week (e.g. `monday`) |
|
| `day` | `TEXT` | Day of the week (e.g. `monday`) |
|
||||||
| `end_time` | `TEXT` | Ending time of lesson (e.g. `09:55`, `13:05`) |
|
| `end_time` | `TEXT` | Ending time of lesson (e.g. `09:55`, `13:05`) |
|
||||||
| `lesson_id` | `TEXT` | Subject ID of the lesson (e.g. `tok`) |
|
| `lesson_id` | `TEXT` | Subject ID of the lesson (e.g. `tok`) |
|
||||||
|
|
||||||
#### Subject IDs
|
#### Subject IDs
|
||||||
|
|
||||||
Subject IDs may be anything, as long as consistency is maintained throughout the tables. There are two hard-coded IDs that are always taken by every student:
|
Subject IDs may be anything, as long as consistency is maintained throughout the tables.
|
||||||
|
|
||||||
| Subject | ID |
|
|
||||||
| ------------------- | ----- |
|
|
||||||
| Theory of Knowledge | `tok` |
|
|
||||||
| Guidance | `gu` |
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
2
TODO.md
2
TODO.md
@ -4,7 +4,7 @@ To-Do List
|
|||||||
## v0.2
|
## v0.2
|
||||||
- [x] Error handling (when entering invalid data types)
|
- [x] Error handling (when entering invalid data types)
|
||||||
- [x] Make database contain data for all classes
|
- [x] Make database contain data for all classes
|
||||||
- [ ] Flexible mandatory subjects
|
- [x] Flexible mandatory subjects
|
||||||
|
|
||||||
## v0.3
|
## v0.3
|
||||||
- [x] make script functional (sorta)
|
- [x] make script functional (sorta)
|
||||||
|
@ -31,34 +31,36 @@ def connect_database(file):
|
|||||||
def get_data(conn):
|
def get_data(conn):
|
||||||
"""
|
"""
|
||||||
Requests student ID and returns integer tuple (id, class) with valid
|
Requests student ID and returns integer tuple (id, class) with valid
|
||||||
student id and corresponding class no.
|
student id, corresponding class no. (1 or 2) and extra subject IDs.
|
||||||
:param conn: Connection object
|
:param conn: Connection object
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
id = int(input("Please enter student ID: "))
|
id = int(input("Please enter student ID: "))
|
||||||
|
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute("SELECT id, student_class FROM students")
|
cur.execute("SELECT id, student_class, other FROM students")
|
||||||
ids = cur.fetchall()
|
ids = cur.fetchall()
|
||||||
|
|
||||||
for x in ids:
|
for tup in ids:
|
||||||
# ids is list with single value tuples
|
# ids is list of tuples
|
||||||
if id == x[0]:
|
if id == tup[0]:
|
||||||
# return tuple x with valid id and corresponding class no.
|
# return tuple x with valid id, class and extra class IDs
|
||||||
return x
|
lis = list(tup)
|
||||||
|
lis[2] = lis[2].split()
|
||||||
|
return lis
|
||||||
else:
|
else:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print("Incorrect ID, try again.")
|
print("Invalid ID, try again.")
|
||||||
return get_data(conn)
|
return get_data(conn)
|
||||||
|
|
||||||
|
|
||||||
def select_final_time(conn, day, stud):
|
def select_final_time(conn, day, stuple):
|
||||||
"""
|
"""
|
||||||
Returns ending time of final lesson student must attend, or None.
|
Returns ending time of final lesson student must attend, or None.
|
||||||
:param conn: Connection object
|
:param conn: Connection object
|
||||||
:param day: current weekday, lowercase str
|
:param day: current weekday, lowercase str
|
||||||
:param stud: tuple with student ID no. and class no., int
|
:param stuple: tuple with student ID no. and class no., int
|
||||||
"""
|
"""
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
@ -70,18 +72,44 @@ def select_final_time(conn, day, stud):
|
|||||||
OR g4 = lesson_id
|
OR g4 = lesson_id
|
||||||
OR g5 = lesson_id
|
OR g5 = lesson_id
|
||||||
OR g6 = lesson_id
|
OR g6 = lesson_id
|
||||||
OR lesson_id = 'gu'
|
|
||||||
OR lesson_id = 'tok'
|
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
AND day = ?
|
AND day = ?
|
||||||
AND lesson_class = ?
|
AND lesson_class = ?
|
||||||
ORDER BY end_time DESC
|
ORDER BY end_time DESC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
""", (stud[0], day, stud[1]))
|
""", (stuple[0], day, stuple[1]))
|
||||||
finish = cur.fetchone()
|
ib_finish = cur.fetchone()
|
||||||
if str(type(finish)) == "<class 'tuple'>":
|
if ib_finish != None:
|
||||||
return finish[0]
|
ib_finish = parse_time_string(ib_finish[0])
|
||||||
|
|
||||||
|
others = []
|
||||||
|
for sub in stuple[2]:
|
||||||
|
cur.execute("""
|
||||||
|
SELECT end_time
|
||||||
|
FROM timetable
|
||||||
|
INNER JOIN students ON ? = lesson_id
|
||||||
|
WHERE id = ?
|
||||||
|
AND day = ?
|
||||||
|
AND lesson_class = ?
|
||||||
|
ORDER BY end_time DESC
|
||||||
|
LIMIT 1
|
||||||
|
""", (sub, stuple[0], day, stuple[1]))
|
||||||
|
other_final = cur.fetchone()
|
||||||
|
if other_final != None:
|
||||||
|
others.append(parse_time_string(other_final[0]))
|
||||||
|
if not others:
|
||||||
|
other_finish = None
|
||||||
else:
|
else:
|
||||||
|
other_finish = max(others)
|
||||||
|
|
||||||
|
if ib_finish != None and other_finish != None:
|
||||||
|
if ib_finish > other_finish:
|
||||||
|
finish = ib_finish
|
||||||
|
else:
|
||||||
|
finish = other_finish
|
||||||
|
else:
|
||||||
|
finish = None
|
||||||
|
|
||||||
return finish
|
return finish
|
||||||
|
|
||||||
|
|
||||||
@ -101,19 +129,19 @@ def main():
|
|||||||
conn = connect_database("database.db")
|
conn = connect_database("database.db")
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
id = get_data(conn)
|
student_data = get_data(conn)
|
||||||
day = time.strftime("%A").lower()
|
day = time.strftime("%A").lower()
|
||||||
finish_time = select_final_time(conn, day, id)
|
finish_time = select_final_time(conn, day, student_data)
|
||||||
current_time = time.strftime("%H:%M")
|
current_time = parse_time_string(time.strftime("%H:%M"))
|
||||||
|
|
||||||
if finish_time == None:
|
if finish_time == None:
|
||||||
print("Student has no lessons today, clear to leave.")
|
print("Student has no lessons today, clear to leave.")
|
||||||
elif parse_time_string(finish_time) < parse_time_string(current_time):
|
elif finish_time < current_time:
|
||||||
print("Student has finished for today, clear to leave.")
|
print("Student has finished for today, clear to leave.")
|
||||||
else:
|
else:
|
||||||
print("Student still has lessons, clearance not granted.")
|
print("Student still has lessons, clearance not granted.")
|
||||||
|
|
||||||
if input("Enter y to run again.") != "y":
|
if input("Enter y to run again.") not in ["y", "Y"]:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user