93 lines
2.3 KiB
Python
93 lines
2.3 KiB
Python
|
|
"""Алгоритмы записи часов — порт 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,
|
||
|
|
}
|