1
0
Fork 0
mirror of https://github.com/EDeev/tablo.git synced 2026-10-07 20:49:31 +03:00
tablo/app/services/schedule_helpers.py
2026-05-19 13:49:09 +03:00

119 lines
4.8 KiB
Python
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.

from datetime import date, timedelta
from collections import defaultdict
DAYS_RU = ['понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота', 'воскресенье']
DAYS_DISPLAY = ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье']
def _parse_date_range(dr: str):
"""Парсим 'ДД.ММ-ДД.ММ' в даты"""
if not dr or dr == 'Весь период':
return None, None
try:
start_str, end_str = dr[:5], dr[6:]
year = date.today().year
start = date(year, int(start_str[3:5]), int(start_str[0:2]))
end = date(year, int(end_str[3:5]), int(end_str[0:2]))
return start, end
except Exception:
return None, None
def get_week_dates():
"""Даты текущей недели Пн-Вс"""
today = date.today()
monday = today - timedelta(days=today.weekday())
return [monday + timedelta(days=i) for i in range(7)]
def _merge_same_subject(slots: list) -> dict:
"""Несколько слотов одного предмета в одно время — объединяем различающиеся поля через /"""
merged = dict(slots[0])
for field in ('classroom', 'teacher', 'type'):
vals = list(dict.fromkeys(str(s.get(field) or '') for s in slots))
vals = [v for v in vals if v]
merged[field] = ' / '.join(vals) if vals else None
return merged
def _group_by_time(slots: list) -> list:
"""Группирует слоты по времени; один предмет — мёрджит поля; разные предметы — группа"""
by_time = defaultdict(list)
for slot in slots:
by_time[slot.get('time') or ''].append(slot)
result = []
for time_key in sorted(by_time.keys()):
group = by_time[time_key]
subjects = {s['subject'] for s in group}
if len(subjects) == 1:
result.append(_merge_same_subject(group))
else:
result.append({'_group': True, 'time': time_key, 'slots': group})
return result
def build_day_view(schedule_data: list, target_date: date) -> list:
"""Занятия на конкретную дату с группировкой по времени"""
day_name = DAYS_RU[target_date.weekday()]
raw = []
for item in schedule_data:
subject = item.get('subject', '')
for type_name, type_data in item.get('types', {}).items():
# Support both old format (dates directly) and new format ({color, dates})
if isinstance(type_data, dict) and 'dates' in type_data:
type_color = type_data.get('color', 'gray')
date_ranges = type_data['dates']
else:
type_color = 'gray'
date_ranges = type_data
for dr, slots in date_ranges.items():
start, end = _parse_date_range(dr)
if start and end and not (start <= target_date <= end):
continue
for slot in slots:
if not slot or slot[0].lower() != day_name:
continue
raw.append({
'subject': subject,
'type': type_name,
'type_name': type_name,
'color': type_color,
'time': slot[1] if len(slot) > 1 else None,
'classroom': slot[2] if len(slot) > 2 else None,
'teacher': slot[3] if len(slot) > 3 else None,
'date_range': dr,
'day': day_name,
})
raw.sort(key=lambda x: x.get('time') or '')
return _group_by_time(raw)
def build_week_view(schedule_data: list) -> dict:
"""Расписание на всю неделю"""
week_dates = get_week_dates()
return {i: build_day_view(schedule_data, d) for i, d in enumerate(week_dates)}
def is_now(time_str: str) -> bool:
"""Идёт ли занятие прямо сейчас"""
if not time_str or '-' not in time_str:
return False
from datetime import datetime
try:
parts = time_str.split('-')
now = datetime.now()
start = datetime.strptime(parts[0].strip(), '%H:%M').replace(
year=now.year, month=now.month, day=now.day)
end = datetime.strptime(parts[1].strip(), '%H:%M').replace(
year=now.year, month=now.month, day=now.day)
return start <= now <= end
except Exception:
return False
def get_all_subjects(schedule_data: list) -> list:
"""Список уникальных названий предметов"""
return [item.get('subject', '') for item in schedule_data if item.get('subject')]