2018-10-09 10:01:01 +02:00
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
2019-01-23 20:39:47 +01:00
|
|
|
|
# Copyright 2018-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-17 18:31:22 +01:00
|
|
|
|
from sys import exit
|
2019-01-11 12:53:06 +01:00
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
2019-01-05 10:49:18 +01:00
|
|
|
|
def get_data(conn):
|
2019-01-11 15:06:35 +01:00
|
|
|
|
"""Get student data.
|
|
|
|
|
|
2019-01-18 19:52:06 +01:00
|
|
|
|
Request student ID. Return tuple (id, class, other) with valid
|
|
|
|
|
student ID, corresponding class number and "other" subject IDs.
|
2019-01-11 15:06:35 +01:00
|
|
|
|
|
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()
|
2019-01-15 12:43:51 +01:00
|
|
|
|
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
|
2019-01-15 12:43:51 +01:00
|
|
|
|
|
|
|
|
|
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.")
|
2019-01-05 10:49:18 +01:00
|
|
|
|
return get_data(conn)
|
2018-10-09 10:01:01 +02:00
|
|
|
|
|
|
|
|
|
|
2019-01-15 16:57:53 +01:00
|
|
|
|
def select_final_time(conn, day, data):
|
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-15 16:57:53 +01:00
|
|
|
|
:param data: 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
|
2019-01-05 10:49:18 +01:00
|
|
|
|
WHERE id = ?
|
|
|
|
|
AND day = ?
|
|
|
|
|
AND lesson_class = ?
|
2018-10-09 10:01:01 +02:00
|
|
|
|
ORDER BY end_time DESC
|
|
|
|
|
LIMIT 1
|
2019-01-15 16:57:53 +01:00
|
|
|
|
""", (data[0], day, data[1])) # Queries return None if no matches.
|
2019-01-06 10:04:44 +01:00
|
|
|
|
ib_finish = cur.fetchone()
|
2019-01-11 11:54:57 +01:00
|
|
|
|
if ib_finish is not None:
|
2019-01-06 10:04:44 +01:00
|
|
|
|
ib_finish = parse_time_string(ib_finish[0])
|
|
|
|
|
|
2019-01-11 15:06:35 +01:00
|
|
|
|
# Select finishing time of other lessons.
|
2019-01-06 10:04:44 +01:00
|
|
|
|
others = []
|
2019-01-15 16:57:53 +01:00
|
|
|
|
for subject in data[2]:
|
2019-01-06 10:04:44 +01:00
|
|
|
|
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-15 16:57:53 +01:00
|
|
|
|
""", (subject, data[0], day, data[1]))
|
2019-01-11 15:06:35 +01:00
|
|
|
|
subject_finish = cur.fetchone()
|
|
|
|
|
if subject_finish is not None:
|
|
|
|
|
others.append(parse_time_string(subject_finish[0]))
|
2019-01-06 10:04:44 +01:00
|
|
|
|
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-06 10:04:44 +01:00
|
|
|
|
|
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:
|
2019-01-06 10:04:44 +01:00
|
|
|
|
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
|
2019-01-06 10:04:44 +01:00
|
|
|
|
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.
|
|
|
|
|
|
2018-10-09 10:06:48 +02:00
|
|
|
|
:param timestring: time string "HH:MM"
|
2018-10-09 10:01:01 +02:00
|
|
|
|
"""
|
2019-01-05 10:49:18 +01:00
|
|
|
|
structtime = time.strptime(timestring, "%H:%M")
|
|
|
|
|
return structtime
|
2018-10-09 10:01:01 +02:00
|
|
|
|
|
|
|
|
|
|
2019-01-17 18:02:12 +01:00
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
2019-01-17 17:19:22 +01:00
|
|
|
|
def exit_sequence():
|
|
|
|
|
"""Initiate exit sequence.
|
|
|
|
|
|
|
|
|
|
Asks user to enter character, and exits program if X is pressed.
|
|
|
|
|
"""
|
2019-01-17 18:02:12 +01:00
|
|
|
|
print("Press X to exit.")
|
2019-01-17 17:19:22 +01:00
|
|
|
|
key = getch()
|
|
|
|
|
if isinstance(key, bytes):
|
|
|
|
|
# msvcrt.getch returns type bytes, decode into str.
|
|
|
|
|
key = key.decode()
|
|
|
|
|
if key.upper() == "X":
|
|
|
|
|
exit()
|
|
|
|
|
|
|
|
|
|
|
2018-10-09 10:01:01 +02:00
|
|
|
|
def main():
|
2018-12-10 16:08:14 +01:00
|
|
|
|
print("ib-clearance")
|
2019-01-23 20:39:47 +01:00
|
|
|
|
print("Copyright 2018-2019 Abdulkadir Furkan Şanlı")
|
2018-12-30 09:28:16 +01:00
|
|
|
|
|
|
|
|
|
conn = connect_database("database.db")
|
|
|
|
|
|
|
|
|
|
while True:
|
2019-01-06 10:04:44 +01:00
|
|
|
|
student_data = get_data(conn)
|
2019-01-11 23:28:08 +01:00
|
|
|
|
day = time.strftime("%A").lower()
|
2019-01-06 10:04:44 +01:00
|
|
|
|
finish_time = select_final_time(conn, day, student_data)
|
2018-12-30 09:28:16 +01:00
|
|
|
|
|
2019-01-17 18:02:12 +01:00
|
|
|
|
print("\n" + clear(finish_time) + "\n")
|
2018-12-30 09:28:16 +01:00
|
|
|
|
|
2019-01-17 17:19:22 +01:00
|
|
|
|
exit_sequence()
|
2018-10-09 10:01:01 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|