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

180 lines
5.0 KiB
Python
Raw Normal View History

2018-10-09 10:01:01 +02:00
#!/usr/bin/env python3
2019-01-11 23:31:38 +01:00
# Copyright 2019 Abdulkadir Furkan Şanlı
2018-10-23 17:10:40 +02:00
# 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.
2018-10-09 10:01:01 +02:00
import sqlite3
import time
2019-01-11 12:53:06 +01:00
from os import name
2019-01-11 15:06:35 +01:00
# Windows has standard library getch, use that.
2019-01-11 12:53:06 +01:00
if name == "nt":
from msvcrt import getch
else:
from getch import getch
2018-10-09 10:01:01 +02:00
def connect_database(file):
2019-01-11 15:06:35 +01:00
"""Get database connection object.
Connect to SQLite database and return a connection object.
:param file: SQLite database
2018-10-09 10:01:01 +02:00
"""
conn = sqlite3.connect(file)
return conn
def get_data(conn):
2019-01-11 15:06:35 +01:00
"""Get student data.
Request student ID. Return integer tuple (id, class, other) with
valid student ID, corresponding class number and "other" subject
IDs.
2018-10-09 10:01:01 +02:00
:param conn: Connection object
"""
2018-12-30 09:28:16 +01:00
try:
2019-01-11 12:00:44 +01:00
id = int(input("\nPlease enter student ID: "))
2018-10-09 10:01:01 +02:00
2018-12-30 09:28:16 +01:00
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()
2018-12-30 09:28:16 +01:00
else:
raise ValueError
return data
2018-12-30 09:28:16 +01:00
except ValueError:
2019-01-11 12:00:44 +01:00
print("\nInvalid ID, try again.")
return get_data(conn)
2018-10-09 10:01:01 +02:00
def select_final_time(conn, day, stuple):
2019-01-11 15:06:35 +01:00
"""Select student finishing time.
Returns ending time (type struct_time) of final lesson student must
attend on given day, or None if no lessons.
2018-10-09 10:01:01 +02:00
:param conn: Connection object
:param day: current weekday, lowercase str
2019-01-11 15:06:35 +01:00
:param stuple: student data tuple returned by get_data
2018-10-09 10:01:01 +02:00
"""
cur = conn.cursor()
2019-01-11 15:06:35 +01:00
# Select finishing time of IB lessons.
2018-10-09 10:01:01 +02:00
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 = ?
2018-10-09 10:01:01 +02:00
ORDER BY end_time DESC
LIMIT 1
2019-01-11 15:06:35 +01:00
""", (stuple[0], day, stuple[1])) # Queries return None if no matches.
ib_finish = cur.fetchone()
2019-01-11 11:54:57 +01:00
if ib_finish is not None:
ib_finish = parse_time_string(ib_finish[0])
2019-01-11 15:06:35 +01:00
# Select finishing time of other lessons.
others = []
2019-01-11 15:06:35 +01:00
for subject 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
2019-01-11 15:06:35 +01:00
""", (subject, stuple[0], day, stuple[1]))
subject_finish = cur.fetchone()
if subject_finish is not None:
others.append(parse_time_string(subject_finish[0]))
if not others:
2019-01-11 11:54:57 +01:00
others_finish = None
2018-10-09 10:01:01 +02:00
else:
2019-01-11 11:54:57 +01:00
others_finish = max(others)
2019-01-11 11:54:57 +01:00
if ib_finish is not None and others_finish is not None:
if ib_finish > others_finish:
finish = ib_finish
else:
2019-01-11 11:54:57 +01:00
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
2018-10-09 10:01:01 +02:00
def parse_time_string(timestring):
2019-01-11 15:06:35 +01:00
"""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"
2018-10-09 10:01:01 +02:00
"""
structtime = time.strptime(timestring, "%H:%M")
return structtime
2018-10-09 10:01:01 +02:00
def main():
print("ib-clearance")
print("============")
2018-12-30 09:28:16 +01:00
conn = connect_database("database.db")
while True:
student_data = get_data(conn)
2019-01-11 23:28:08 +01:00
day = time.strftime("%A").lower()
finish_time = select_final_time(conn, day, student_data)
current_time = parse_time_string(time.strftime("%H:%M"))
2018-12-30 09:28:16 +01:00
if finish_time == None:
2019-01-11 12:00:44 +01:00
print("\nStudent has no lessons today, clear to leave.")
elif finish_time < current_time:
2019-01-11 12:00:44 +01:00
print("\nStudent has finished for today, clear to leave.")
2018-12-30 09:28:16 +01:00
else:
2019-01-11 11:54:57 +01:00
print("\nStudent still has lessons, clearance not granted.")
2018-12-30 09:28:16 +01:00
2019-01-11 12:53:06 +01:00
print("\nPress X key to exit, other key to run again.")
key = getch()
if isinstance(key, bytes):
2019-01-11 15:06:35 +01:00
# msvcrt.getch returns type bytes, decode into str.
2019-01-11 12:53:06 +01:00
key = key.decode()
if key.upper() == "X":
2018-12-30 09:28:16 +01:00
break
2018-10-09 10:01:01 +02:00
if __name__ == "__main__":
main()