This repository has been archived on 2023-12-11. You can view files and clone it, but cannot push or open issues or pull requests.
ib-clearance/ib-clearance.py
2019-01-18 19:52:06 +01:00

200 lines
5.3 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# Copyright 2019 Abdulkadir Furkan Şanlı
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sqlite3
import time
from os import name
from sys import exit
# Windows has standard library getch, use that.
if name == "nt":
from msvcrt import getch
else:
from getch import getch
def connect_database(file):
"""Get database connection object.
Connect to SQLite database and return a connection object.
:param file: SQLite database
"""
conn = sqlite3.connect(file)
return conn
def get_data(conn):
"""Get student data.
Request student ID. Return tuple (id, class, other) with valid
student ID, corresponding class number and "other" subject IDs.
:param conn: Connection object
"""
try:
id = int(input("\nPlease enter student ID: "))
cur = conn.cursor()
cur.execute("""
SELECT id, student_class, other
FROM students
WHERE id = ?
""", (id,))
data = cur.fetchone()
if data is not None:
data = list(data) # SQLite returns tuples.
data[2] = data[2].split()
else:
raise ValueError
return data
except ValueError:
print("\nInvalid ID, try again.")
return get_data(conn)
def select_final_time(conn, day, data):
"""Select student finishing time.
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 day: current weekday, lowercase str
:param data: student data tuple returned by get_data
"""
cur = conn.cursor()
# Select finishing time of IB lessons.
cur.execute("""
SELECT end_time
FROM timetable
INNER JOIN students ON g1 = lesson_id
OR g2 = lesson_id
OR g3 = lesson_id
OR g4 = lesson_id
OR g5 = lesson_id
OR g6 = lesson_id
WHERE id = ?
AND day = ?
AND lesson_class = ?
ORDER BY end_time DESC
LIMIT 1
""", (data[0], day, data[1])) # Queries return None if no matches.
ib_finish = cur.fetchone()
if ib_finish is not None:
ib_finish = parse_time_string(ib_finish[0])
# Select finishing time of other lessons.
others = []
for subject in data[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
""", (subject, data[0], day, data[1]))
subject_finish = cur.fetchone()
if subject_finish is not None:
others.append(parse_time_string(subject_finish[0]))
if not others:
others_finish = None
else:
others_finish = max(others)
if ib_finish is not None and others_finish is not None:
if ib_finish > others_finish:
finish = ib_finish
else:
finish = others_finish
elif ib_finish is not None:
finish = ib_finish
elif others_finish is not None:
finish = others_finish
else:
finish = None
return finish
def parse_time_string(timestring):
"""Convert time string to tuple.
Parses given 24h time string of format "HH:MM" into the struct_time
object provided by library time.
:param timestring: time string "HH:MM"
"""
structtime = time.strptime(timestring, "%H:%M")
return structtime
def clear(finish_time):
"""Return clearance message.
Compare the current time with finishing time and return relevant
clearance message.
:param finish_time: finishing time, struct_time object
"""
current_time = parse_time_string(time.strftime("%H:%M"))
if finish_time == None:
message = "Student has no lessons today, clear to leave."
elif finish_time < current_time:
message = "Student has finished for today, clear to leave."
else:
message = "Student still has lessons, clearance not granted."
return message
def exit_sequence():
"""Initiate exit sequence.
Asks user to enter character, and exits program if X is pressed.
"""
print("Press X to exit.")
key = getch()
if isinstance(key, bytes):
# msvcrt.getch returns type bytes, decode into str.
key = key.decode()
if key.upper() == "X":
exit()
def main():
print("ib-clearance")
print("============")
conn = connect_database("database.db")
while True:
student_data = get_data(conn)
day = time.strftime("%A").lower()
finish_time = select_final_time(conn, day, student_data)
print("\n" + clear(finish_time) + "\n")
exit_sequence()
if __name__ == "__main__":
main()