Properly document the damn thing.
This commit is contained in:
parent
42e6042405
commit
4e05e3380a
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
ib-clearance is a program which helps schools manage the entrance and exiting of their IB Diploma Program students. Due to the unique nature of IB students' timetables, the program helps to automatically 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 IB Diploma Program students. Due to the unique nature of IB students' timetables, the program helps to automatically check individual timetables and give clearance to students who have finished for the day.
|
||||||
|
|
||||||
## Building
|
## Building & running
|
||||||
|
|
||||||
The code is currently designed to run on Python 3.6.*.
|
The code is currently designed to run on Python 3.6.* and requires the [`getch`](https://pypi.org/project/getch/) module on platforms other than Windows.
|
||||||
|
|
||||||
Binaries can be built using the `pyinstaller` package (`pyinstaller --onefile ib-clearance.py`).
|
Binaries can be built using [`pyinstaller`](https://pypi.org/project/PyInstaller/): `pyinstaller --onefile ib-clearance.py`
|
||||||
|
|
||||||
## Database specification
|
## Database specification
|
||||||
|
|
||||||
The program requires a SQLite database `database.db` in the working directory, containing data for all classes.
|
The program requires a SQLite database `database.db` in the working directory, containing data for all school classes.
|
||||||
|
|
||||||
`database.db` must contain:
|
`database.db` must contain:
|
||||||
|
|
||||||
|
1
TODO.md
1
TODO.md
@ -6,6 +6,7 @@ To-Do List
|
|||||||
- [x] Make database contain data for all classes
|
- [x] Make database contain data for all classes
|
||||||
- [x] Flexible mandatory subjects
|
- [x] Flexible mandatory subjects
|
||||||
- [x] Make script functional (sorta)
|
- [x] Make script functional (sorta)
|
||||||
|
- [x] Document the damn thing
|
||||||
|
|
||||||
## v0.3
|
## v0.3
|
||||||
- [ ] Usability and GUI
|
- [ ] Usability and GUI
|
||||||
|
@ -14,12 +14,11 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import time
|
import time
|
||||||
from os import name
|
from os import name
|
||||||
|
|
||||||
# Import getch from msvcrt if running on Windows.
|
# Windows has standard library getch, use that.
|
||||||
if name == "nt":
|
if name == "nt":
|
||||||
from msvcrt import getch
|
from msvcrt import getch
|
||||||
else:
|
else:
|
||||||
@ -27,18 +26,23 @@ else:
|
|||||||
|
|
||||||
|
|
||||||
def connect_database(file):
|
def connect_database(file):
|
||||||
"""
|
"""Get database connection object.
|
||||||
Creates and returns Connection object.
|
|
||||||
:param file: database file
|
Connect to SQLite database and return a connection object.
|
||||||
|
|
||||||
|
:param file: SQLite database
|
||||||
"""
|
"""
|
||||||
conn = sqlite3.connect(file)
|
conn = sqlite3.connect(file)
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
|
|
||||||
def get_data(conn):
|
def get_data(conn):
|
||||||
"""
|
"""Get student data.
|
||||||
Requests student ID and returns integer tuple (id, class) with valid
|
|
||||||
student id, corresponding class no. (1 or 2) and extra subject IDs.
|
Request student ID. Return integer tuple (id, class, other) with
|
||||||
|
valid student ID, corresponding class number and "other" subject
|
||||||
|
IDs.
|
||||||
|
|
||||||
:param conn: Connection object
|
:param conn: Connection object
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
@ -46,12 +50,10 @@ def get_data(conn):
|
|||||||
|
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute("SELECT id, student_class, other FROM students")
|
cur.execute("SELECT id, student_class, other FROM students")
|
||||||
ids = cur.fetchall()
|
ids = cur.fetchall() # ids is list of tuples.
|
||||||
|
|
||||||
for tup in ids:
|
for tup in ids:
|
||||||
# ids is list of tuples
|
|
||||||
if id == tup[0]:
|
if id == tup[0]:
|
||||||
# return tuple x with valid id, class and extra class IDs
|
|
||||||
lis = list(tup)
|
lis = list(tup)
|
||||||
lis[2] = lis[2].split()
|
lis[2] = lis[2].split()
|
||||||
return lis
|
return lis
|
||||||
@ -63,13 +65,17 @@ def get_data(conn):
|
|||||||
|
|
||||||
|
|
||||||
def select_final_time(conn, day, stuple):
|
def select_final_time(conn, day, stuple):
|
||||||
"""
|
"""Select student finishing time.
|
||||||
Returns ending time of final lesson student must attend, or None.
|
|
||||||
|
Returns ending time (type struct_time) of final lesson student must
|
||||||
|
attend on given day, or None if no lessons.
|
||||||
|
|
||||||
:param conn: Connection object
|
:param conn: Connection object
|
||||||
:param day: current weekday, lowercase str
|
:param day: current weekday, lowercase str
|
||||||
:param stuple: tuple with student ID no. and class no., int
|
:param stuple: student data tuple returned by get_data
|
||||||
"""
|
"""
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
|
# Select finishing time of IB lessons.
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT end_time
|
SELECT end_time
|
||||||
FROM timetable
|
FROM timetable
|
||||||
@ -84,13 +90,14 @@ def select_final_time(conn, day, stuple):
|
|||||||
AND lesson_class = ?
|
AND lesson_class = ?
|
||||||
ORDER BY end_time DESC
|
ORDER BY end_time DESC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
""", (stuple[0], day, stuple[1]))
|
""", (stuple[0], day, stuple[1])) # Queries return None if no matches.
|
||||||
ib_finish = cur.fetchone()
|
ib_finish = cur.fetchone()
|
||||||
if ib_finish is not None:
|
if ib_finish is not None:
|
||||||
ib_finish = parse_time_string(ib_finish[0])
|
ib_finish = parse_time_string(ib_finish[0])
|
||||||
|
|
||||||
|
# Select finishing time of other lessons.
|
||||||
others = []
|
others = []
|
||||||
for sub in stuple[2]:
|
for subject in stuple[2]:
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT end_time
|
SELECT end_time
|
||||||
FROM timetable
|
FROM timetable
|
||||||
@ -100,10 +107,10 @@ def select_final_time(conn, day, stuple):
|
|||||||
AND lesson_class = ?
|
AND lesson_class = ?
|
||||||
ORDER BY end_time DESC
|
ORDER BY end_time DESC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
""", (sub, stuple[0], day, stuple[1]))
|
""", (subject, stuple[0], day, stuple[1]))
|
||||||
other_finish = cur.fetchone()
|
subject_finish = cur.fetchone()
|
||||||
if other_finish is not None:
|
if subject_finish is not None:
|
||||||
others.append(parse_time_string(other_finish[0]))
|
others.append(parse_time_string(subject_finish[0]))
|
||||||
if not others:
|
if not others:
|
||||||
others_finish = None
|
others_finish = None
|
||||||
else:
|
else:
|
||||||
@ -125,8 +132,11 @@ def select_final_time(conn, day, stuple):
|
|||||||
|
|
||||||
|
|
||||||
def parse_time_string(timestring):
|
def parse_time_string(timestring):
|
||||||
"""
|
"""Convert time string to tuple.
|
||||||
Parses given 24h time string of format "HH:MM" into struct_time.
|
|
||||||
|
Parses given 24h time string of format "HH:MM" into the struct_time
|
||||||
|
object provided by library time.
|
||||||
|
|
||||||
:param timestring: time string "HH:MM"
|
:param timestring: time string "HH:MM"
|
||||||
"""
|
"""
|
||||||
structtime = time.strptime(timestring, "%H:%M")
|
structtime = time.strptime(timestring, "%H:%M")
|
||||||
@ -141,7 +151,7 @@ def main():
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
student_data = get_data(conn)
|
student_data = get_data(conn)
|
||||||
day = time.strftime("%A").lower()
|
day = time.strftime("%A").lower() # db days are also lowercase.
|
||||||
finish_time = select_final_time(conn, day, student_data)
|
finish_time = select_final_time(conn, day, student_data)
|
||||||
current_time = parse_time_string(time.strftime("%H:%M"))
|
current_time = parse_time_string(time.strftime("%H:%M"))
|
||||||
|
|
||||||
@ -154,13 +164,12 @@ def main():
|
|||||||
|
|
||||||
print("\nPress X key to exit, other key to run again.")
|
print("\nPress X key to exit, other key to run again.")
|
||||||
key = getch()
|
key = getch()
|
||||||
# msvcrt.getch returns type bytes, decode into str.
|
|
||||||
if isinstance(key, bytes):
|
if isinstance(key, bytes):
|
||||||
|
# msvcrt.getch returns type bytes, decode into str.
|
||||||
key = key.decode()
|
key = key.decode()
|
||||||
if key.upper() == "X":
|
if key.upper() == "X":
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
# Run main() if script is run standalone.
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
Reference in New Issue
Block a user