Changing logic
This commit is contained in:
@@ -38,6 +38,7 @@ class Application:
|
||||
self._tracking_thread: Optional[threading.Thread] = None
|
||||
self._running = True
|
||||
self.session_start_time: Optional[float] = None
|
||||
self.idle_start_time: Optional[float] = None
|
||||
|
||||
# Загружаем задачу
|
||||
if self.config.current_task_id:
|
||||
@@ -91,6 +92,7 @@ class Application:
|
||||
with self._lock:
|
||||
if not self.tracking_enabled or not self.current_task:
|
||||
self.session_start_time = None
|
||||
self.idle_start_time = None
|
||||
return
|
||||
|
||||
current_time = time.time()
|
||||
@@ -99,24 +101,106 @@ class Application:
|
||||
is_blocked = self._is_group_blocked(group_name)
|
||||
|
||||
was_idle = self.is_idle
|
||||
current_idle = (current_time - self.last_activity > self.config.idle_threshold_seconds) or is_blocked
|
||||
|
||||
if current_time - self.last_activity > 60 or is_blocked:
|
||||
# === СЛУЧАЙ 1: Переход в бездействие ===
|
||||
if not was_idle and current_idle:
|
||||
self.is_idle = True
|
||||
self.idle_start_time = current_time
|
||||
self.last_window_group = None
|
||||
self.session_start_time = None
|
||||
else:
|
||||
self.maybe_save_task()
|
||||
return
|
||||
|
||||
# === СЛУЧАЙ 2: Выход из бездействия ===
|
||||
if was_idle and not current_idle:
|
||||
self.is_idle = False
|
||||
idle_duration = current_time - self.idle_start_time if self.idle_start_time else 0
|
||||
self.idle_start_time = None
|
||||
|
||||
# Решаем, создавать ли НОВУЮ сессию
|
||||
create_new_session = False
|
||||
reasons = []
|
||||
|
||||
# Причина 1: Длительное бездействие (>10 минут)
|
||||
if idle_duration > self.config.new_session_after_idle_seconds:
|
||||
create_new_session = True
|
||||
reasons.append(f"бездействие {idle_duration / 60:.1f} мин")
|
||||
|
||||
# Причина 2: Смена календарного дня
|
||||
if self.current_task.sessions:
|
||||
last_session_date = self.current_task.sessions[-1].end_time.date()
|
||||
current_date = datetime.now().date()
|
||||
if last_session_date < current_date:
|
||||
create_new_session = True
|
||||
reasons.append(f"смена дня ({last_session_date} → {current_date})")
|
||||
|
||||
# Причина 3: Первая сессия для задачи
|
||||
if not self.current_task.sessions:
|
||||
create_new_session = True
|
||||
reasons.append("первая сессия задачи")
|
||||
|
||||
# Создаём новую сессию при необходимости
|
||||
if create_new_session:
|
||||
new_session = WorkSession(
|
||||
start_time=datetime.now(),
|
||||
end_time=datetime.now(),
|
||||
details=[],
|
||||
synchronized=False
|
||||
)
|
||||
self.current_task.sessions.append(new_session)
|
||||
logger.info(
|
||||
f"Новая сессия для {self.current_task.task_id}: "
|
||||
f"{', '.join(reasons)}"
|
||||
)
|
||||
|
||||
# Начинаем отслеживание
|
||||
self.session_start_time = current_time
|
||||
self.last_window_group = group_name
|
||||
self._add_work_detail_to_session(group_name, 5.0)
|
||||
return
|
||||
|
||||
# === СЛУЧАЙ 3: Продолжение активной работы ===
|
||||
if not current_idle:
|
||||
self.is_idle = False
|
||||
if self.last_window_group != group_name:
|
||||
self.last_window_group = group_name
|
||||
self._add_work_detail(group_name, 5.0)
|
||||
|
||||
# Начинаем/продолжаем сессию
|
||||
# Гарантируем наличие сессии (на случай редких состояний)
|
||||
if not self.current_task.sessions:
|
||||
self.current_task.sessions.append(WorkSession(
|
||||
start_time=datetime.now(),
|
||||
end_time=datetime.now(),
|
||||
details=[],
|
||||
synchronized=False
|
||||
))
|
||||
|
||||
self._add_work_detail_to_session(group_name, 5.0)
|
||||
if self.session_start_time is None:
|
||||
self.session_start_time = current_time
|
||||
return
|
||||
|
||||
# === СЛУЧАЙ 4: Продолжение бездействия ===
|
||||
self.is_idle = True
|
||||
|
||||
def _add_work_detail_to_session(self, group_name: str, seconds: float):
|
||||
"""Добавляет запись ТОЛЬКО в последнюю сессию (не создаёт новые)"""
|
||||
if not self.current_task or not self.current_task.sessions:
|
||||
logger.warning("Нет активной сессии для добавления времени")
|
||||
return
|
||||
|
||||
session = self.current_task.sessions[-1]
|
||||
|
||||
# Объединяем записи одной группы
|
||||
for detail in session.details:
|
||||
if detail.group_name == group_name:
|
||||
detail.duration_seconds += seconds
|
||||
break
|
||||
else:
|
||||
session.details.append(WorkDetail(group_name=group_name, duration_seconds=seconds))
|
||||
|
||||
session.end_time = datetime.now()
|
||||
|
||||
# Сохраняем при переходе в бездействие
|
||||
if not was_idle and self.is_idle:
|
||||
self.maybe_save_task()
|
||||
|
||||
def _match_window_to_policy(self, window_info) -> str:
|
||||
title = window_info.title.lower()
|
||||
@@ -183,9 +267,17 @@ class Application:
|
||||
self.config.tracking_enabled = self.tracking_enabled
|
||||
self._save_config(self.config)
|
||||
|
||||
# Сохраняем при переходе в паузу
|
||||
if was_enabled and not self.tracking_enabled:
|
||||
# Переход в паузу → сохраняем и сбрасываем состояние
|
||||
self.maybe_save_task()
|
||||
self.is_idle = True
|
||||
self.idle_start_time = time.time()
|
||||
self.session_start_time = None
|
||||
elif not was_enabled and self.tracking_enabled:
|
||||
# Возобновление → сбрасываем состояние бездействия
|
||||
self.is_idle = False
|
||||
self.idle_start_time = None
|
||||
self.session_start_time = time.time()
|
||||
|
||||
def create_task(self, task_id: str, project_id: Optional[str], estimated_minutes: Optional[float]):
|
||||
with self._lock:
|
||||
@@ -226,9 +318,30 @@ class Application:
|
||||
with self._lock:
|
||||
if not self.current_task:
|
||||
return
|
||||
seconds = abs(minutes) * 60
|
||||
sign = 1 if minutes >= 0 else -1
|
||||
self._add_work_detail("Manual", sign * seconds)
|
||||
|
||||
if minutes == 0:
|
||||
return
|
||||
|
||||
# Создаём ОТДЕЛЬНУЮ сессию для ручного времени
|
||||
new_session = WorkSession(
|
||||
start_time=datetime.now(),
|
||||
end_time=datetime.now(),
|
||||
details=[WorkDetail(
|
||||
group_name="Manual Adjustment",
|
||||
duration_seconds=abs(minutes) * 60
|
||||
)],
|
||||
synchronized=False,
|
||||
description=f"Manual: {minutes:+.1f} min"
|
||||
)
|
||||
self.current_task.sessions.append(new_session)
|
||||
logger.info(f"Добавлена ручная сессия: {minutes:+.1f} мин для {self.current_task.task_id}")
|
||||
|
||||
# Сохраняем и синхронизируем
|
||||
self.save_task(self.current_task)
|
||||
try:
|
||||
self.sync_with_youtrack()
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка синхронизации после ручного добавления: {e}")
|
||||
|
||||
def get_display_status(self) -> str:
|
||||
with self._lock:
|
||||
|
||||
@@ -58,6 +58,8 @@ class TrackerConfig(BaseModel):
|
||||
tracking_enabled: bool = False
|
||||
current_task_id: Optional[str] = None
|
||||
window_policies: List[WindowPolicy] = Field(default_factory=list)
|
||||
idle_threshold_seconds: int = 60 # Порог перехода в idle
|
||||
new_session_after_idle_seconds: int = 600 # 10 минут для новой сессии
|
||||
|
||||
@staticmethod
|
||||
def default_policies() -> List[WindowPolicy]:
|
||||
|
||||
Reference in New Issue
Block a user