#!/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 integer 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()