mirror of
https://github.com/Omni-guides/Jackify.git
synced 2026-06-08 01:47:45 +02:00
168 lines
6.6 KiB
Python
168 lines
6.6 KiB
Python
"""Metrics and synthetic entry methods for ProgressStateManager (Mixin)."""
|
|
|
|
import logging
|
|
import re
|
|
import time
|
|
from typing import TYPE_CHECKING
|
|
|
|
from jackify.shared.progress_models import FileProgress, OperationType, InstallationPhase
|
|
|
|
if TYPE_CHECKING:
|
|
from jackify.backend.handlers.progress_parser import ParsedLine
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ProgressStateMetricsMixin:
|
|
"""Mixin providing metrics augmentation methods."""
|
|
|
|
def _augment_file_metrics(self, file_progress: FileProgress) -> None:
|
|
"""Populate size/speed info to improve UI accuracy."""
|
|
now = time.time()
|
|
history = self._file_history.get(file_progress.filename)
|
|
|
|
total_size = file_progress.total_size or (history.get('total') if history else None)
|
|
if total_size and file_progress.percent and not file_progress.current_size:
|
|
file_progress.current_size = int((file_progress.percent / 100.0) * total_size)
|
|
elif file_progress.current_size and not total_size and file_progress.total_size:
|
|
total_size = file_progress.total_size
|
|
|
|
if total_size and not file_progress.total_size:
|
|
file_progress.total_size = total_size
|
|
|
|
current_size = file_progress.current_size or 0
|
|
|
|
computed_speed = 0.0
|
|
if file_progress.speed < 0:
|
|
computed_speed = 0.0
|
|
if history and current_size:
|
|
prev_bytes = history.get('bytes', 0)
|
|
prev_time = history.get('time', now)
|
|
delta_bytes = current_size - prev_bytes
|
|
delta_time = now - prev_time
|
|
|
|
if delta_bytes >= 0 and delta_time >= 1.0:
|
|
computed_speed = delta_bytes / delta_time
|
|
elif history.get('computed_speed'):
|
|
computed_speed = history.get('computed_speed', 0.0)
|
|
|
|
file_progress.speed = computed_speed
|
|
else:
|
|
computed_speed = file_progress.speed
|
|
|
|
if current_size or total_size:
|
|
self._file_history[file_progress.filename] = {
|
|
'bytes': current_size,
|
|
'time': now,
|
|
'total': total_size or (history.get('total') if history else None),
|
|
'computed_speed': computed_speed,
|
|
}
|
|
elif history:
|
|
self._file_history[file_progress.filename] = history
|
|
|
|
def _maybe_add_wabbajack_progress(self, parsed: "ParsedLine") -> bool:
|
|
"""Create a synthetic file entry for .wabbajack archive download."""
|
|
if not parsed.data_info:
|
|
return False
|
|
if not parsed.data_info:
|
|
return False
|
|
|
|
current_bytes, total_bytes = parsed.data_info
|
|
if total_bytes <= 0:
|
|
return False
|
|
|
|
for fp in self.state.active_files:
|
|
if fp.filename.lower().endswith('.wabbajack'):
|
|
synthetic_entry = fp
|
|
if getattr(fp, self._synthetic_flag, False):
|
|
percent = (current_bytes / total_bytes) * 100.0
|
|
synthetic_entry.percent = percent
|
|
synthetic_entry.current_size = current_bytes
|
|
synthetic_entry.total_size = total_bytes
|
|
synthetic_entry.last_update = time.time()
|
|
self._augment_file_metrics(synthetic_entry)
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
synthetic_entry = None
|
|
for fp in self.state.active_files:
|
|
if getattr(fp, self._synthetic_flag, False):
|
|
synthetic_entry = fp
|
|
break
|
|
|
|
message = (parsed.message or "")
|
|
phase_name = (parsed.phase_name or "").lower()
|
|
should_force = 'wabbajack' in message.lower() or 'wabbajack' in phase_name
|
|
|
|
if not synthetic_entry:
|
|
if self._has_real_download_activity() and not should_force:
|
|
return False
|
|
if self.state.phase not in (InstallationPhase.INITIALIZATION, InstallationPhase.DOWNLOAD) and not should_force:
|
|
return False
|
|
|
|
percent = (current_bytes / total_bytes) * 100.0
|
|
if not self._wabbajack_entry_name:
|
|
filename_match = re.search(r'([A-Za-z0-9_\-\.]+\.wabbajack)', message, re.IGNORECASE)
|
|
if filename_match:
|
|
self._wabbajack_entry_name = filename_match.group(1)
|
|
if not self._wabbajack_entry_name:
|
|
self._wabbajack_entry_name = "Downloading .wabbajack file"
|
|
entry_name = self._wabbajack_entry_name
|
|
|
|
if synthetic_entry:
|
|
synthetic_entry.percent = percent
|
|
synthetic_entry.current_size = current_bytes
|
|
synthetic_entry.total_size = total_bytes
|
|
synthetic_entry.last_update = time.time()
|
|
self._augment_file_metrics(synthetic_entry)
|
|
else:
|
|
special_file = FileProgress(
|
|
filename=entry_name,
|
|
operation=OperationType.DOWNLOAD,
|
|
percent=percent,
|
|
current_size=current_bytes,
|
|
total_size=total_bytes
|
|
)
|
|
special_file.last_update = time.time()
|
|
setattr(special_file, self._synthetic_flag, True)
|
|
self._augment_file_metrics(special_file)
|
|
self.state.add_file(special_file)
|
|
return True
|
|
|
|
def _has_real_download_activity(self) -> bool:
|
|
"""Check if there are real download entries already visible."""
|
|
for fp in self.state.active_files:
|
|
if getattr(fp, self._synthetic_flag, False):
|
|
continue
|
|
if fp.operation == OperationType.DOWNLOAD:
|
|
return True
|
|
return False
|
|
|
|
def _remove_synthetic_wabbajack(self) -> None:
|
|
"""Remove any synthetic .wabbajack entries once real files appear."""
|
|
remaining = []
|
|
removed = False
|
|
for fp in self.state.active_files:
|
|
if getattr(fp, self._synthetic_flag, False):
|
|
removed = True
|
|
self._file_history.pop(fp.filename, None)
|
|
continue
|
|
remaining.append(fp)
|
|
if removed:
|
|
self.state.active_files = remaining
|
|
|
|
def _remove_all_wabbajack_entries(self) -> None:
|
|
"""Remove ALL .wabbajack entries when archive download phase starts."""
|
|
remaining = []
|
|
removed = False
|
|
for fp in self.state.active_files:
|
|
if fp.filename.lower().endswith('.wabbajack') or 'wabbajack' in fp.filename.lower():
|
|
removed = True
|
|
self._file_history.pop(fp.filename, None)
|
|
continue
|
|
remaining.append(fp)
|
|
if removed:
|
|
self.state.active_files = remaining
|
|
self._wabbajack_entry_name = None
|