added an config option for a list of semester starts, now only sessions inside the current semester count

This commit is contained in:
2026-08-10 16:31:25 +02:00
parent 672faa5dc4
commit d278ccdc72
3 changed files with 70 additions and 8 deletions
+5
View File
@@ -7,3 +7,8 @@ CALDAV_PASS=
# timezone. for example the default: Europe/Berlin
TIMEZONE=
# an comma seperated list of semester starts.
# Studytime will only count sessions up to the last date in the past
# format: MM-DD,MM-DD,...
SEMESTER_STARTS=
+1 -1
View File
@@ -3,7 +3,7 @@ from src.fetch_sessions import *
app = Flask(__name__)
sessions = get_sessions()
sessions = get_this_semesters_sessions()
# web ui
@app.route("/")
+64 -7
View File
@@ -11,6 +11,8 @@ try:
CALDAV_USER = os.environ["CALDAV_USER"]
CALDAV_PASS = os.environ["CALDAV_PASS"]
TIME_ZONE = ZoneInfo(os.environ.get("TIMEZONE", "Europe/Berlin"))
SEMESTER_STARTS = os.environ["SEMESTER_STARTS"]
if SEMESTER_STARTS: SEMESTER_STARTS = SEMESTER_STARTS.split(",")
except Exception:
print("Failed to read settings from .env!\nTake a look at .env.example for the required structure!")
@@ -21,8 +23,8 @@ client = caldav.DAVClient(
)
calendar = client.calendar(url=CALDAV_URL)
def get_sessions():
# grab ALL sessions and return as array of dicts
def get_all_sessions() -> list:
events = calendar.events()
events.sort(key=lambda e: e.vobject_instance.vevent.dtstart.value)
@@ -38,8 +40,59 @@ def get_sessions():
})
return event_list
# grab only the sessions that fall into the current semester
# (or all if none was given)
def get_this_semesters_sessions() -> list:
sessions = get_all_sessions()
semester_start = get_current_semester_start()
print(f"grabbing sessions since {str(semester_start)}")
def calculate_totals(sessions):
if not semester_start:
# no semester starts given, just pass all sessions
return sessions
# only keep sessions with a date greater then semester start
# man i love list comprehension
return [session for session in sessions if datetime.strptime(session["date"], "%Y-%m-%d").date() >= semester_start]
# get the date of the start of the semester were currently in
# or return None if no semesters were specified
def get_current_semester_start() -> date:
if not SEMESTER_STARTS: # array of MM-DD strings
print("no starts")
return None
# first check if one the dates was previously this year
today = datetime.now().date()
found_start = None
try:
dates = [datetime.strptime(str(today.year)+"-"+date_str, "%Y-%m-%d").date() for date_str in SEMESTER_STARTS]
except Exception:
print("Failed to parse semester start date. Falling back to None!")
return None
for date in dates:
if date > today:
continue
if found_start and date < found_start:
continue
found_start = date
if found_start:
return found_start
# otherwise use the last date of last year
try:
last_year_dates = [date.replace(year=date.year - 1) for date in dates]
except Exception:
print("Failed to parse semester start date. Falling back to None!")
return None
return max(last_year_dates)
# return dict with all subjects and their respective total hours studied
def calculate_totals(sessions) -> dict:
totals = {}
for session in sessions:
subject = session["subject"]
@@ -52,7 +105,8 @@ def calculate_totals(sessions):
return totals
def get_last_n_days(n: int, sessions):
# get a list of the last n days and time strudying in minutes per day
def get_last_n_days(n: int, sessions) -> list[dict]:
days = []
today = datetime.now().date()
@@ -71,7 +125,8 @@ def get_last_n_days(n: int, sessions):
return days
def get_total_month(sessions):
# get total minutes studying this month
def get_total_month(sessions) -> int:
total_min = 0
for session in sessions:
year_month = str(session["date"])[:7]
@@ -80,7 +135,8 @@ def get_total_month(sessions):
total_min += session["minutes"]
return total_min
def get_worst_and_best(totals):
# return a dict containing the subjects with most and least hours studied
def get_worst_and_best(totals) -> dict:
worst = "None"
worst_h = 99999999
best = "None"
@@ -98,7 +154,8 @@ def get_worst_and_best(totals):
"best":best
}
def get_stats(sessions, totals):
# return all stats for api
def get_stats(sessions, totals) -> dict:
w_and_b = get_worst_and_best(totals)
return {
"semester":"hi",