"""Алгоритмы записи часов — порт addFromCalendar.""" from __future__ import annotations from datetime import date from typing import Any def normalize_time_value(time: float) -> float: x = (time - int(time)) * 100 if x <= 25: frac = 0 elif x >= 75: frac = 100 else: frac = 50 t = int(time) + frac / 100 if t < 0: t = 0 if t > 24: t = 24 return float(t) def apply_daily_limits( time: float, is_over: bool, total_work: float, total_over: float, project_hours: float, project_over: float, max_work_hours: float, max_over_hours: float, ) -> tuple[float, dict[str, float]]: tw = total_work - project_hours to = total_over - project_over new_work = tw + time new_over = to + time left_work = max_work_hours - tw left_over = max_over_hours - to clamped = False if is_over: if new_over > max_over_hours: time = left_over clamped = True else: if new_work > max_work_hours: time = left_work clamped = True if time < 0: time = 0 clamped = True limits = { "max_work_hours": max_work_hours, "max_over_hours": max_over_hours, "left_work_hours": left_work, "left_over_hours": left_over, "new_work_hours": tw + (time if not is_over else 0), "new_over_hours": to + (time if is_over else 0), "clamped": clamped, } return time, limits def sum_day_totals(rows: list[dict[str, Any]]) -> tuple[float, float]: total_work = 0.0 total_over = 0.0 for row in rows: dur = float(row.get("cc") or row.get("duration") or 0) if int(row.get("is_over") or 0): total_over += dur else: total_work += dur return total_work, total_over def project_day_info(rows: list[dict[str, Any]]) -> dict[str, float]: hours = 0.0 over = 0.0 for row in rows: dur = float(row.get("cc") or row.get("duration") or 0) if int(row.get("is_over") or 0): over += dur else: hours += dur return { "hours": hours, "over": over, "over1": 0.0, "over2": 0.0, "total": hours + over, }