Untitled
unknown
plain_text
10 months ago
7.3 kB
4
Indexable
import json
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Set, Union
class MetricsManager:
def __init__(self, storage_path: str = "sorting_metrics.json"):
self.storage_path = Path(storage_path)
self.metrics = self._load_or_initialize_metrics()
def _load_or_initialize_metrics(self) -> dict:
"""Load existing metrics from file or initialize new metrics structure."""
if self.storage_path.exists():
with open(self.storage_path, 'r') as f:
return json.load(f)
return {
# Basic sorting metrics
'total_items_sorted': 0,
'items_sorted_per_bin': {},
'sort_timestamps': [],
'fill_levels_per_bin': {},
'bin_emptying_counts': {},
'api_vs_local_usage_counts': {'api': 0, 'local': 0},
# Time-based metrics
'daily_usage_counts': {},
'weekly_usage_counts': {},
'monthly_usage_counts': {},
'time_between_sorts': [],
'time_of_day_patterns': {},
'daily_weekly_monthly_streaks': {
'daily': 0,
'weekly': 0,
'monthly': 0
},
'time_to_empty_from_90': [],
'fill_rate_per_bin': {},
'fill_level_balance': {},
# Short-term tracking
'items_last_5_minutes': {
'count': 0,
'timestamps': []
},
'current_sorting_streak': {
'start_date': None,
'days': 0,
'last_sort_date': None
},
# Hour coverage tracking
'hours_sorted': [],
'weekend_streak': {
'count': 0,
'dates': []
},
# Seasonal tracking
'seasonal_counts': {
'summer': 0,
'winter': 0,
'current_season': '',
'season_start': None
},
# Environmental impact
'environmental_impact': {
'co2_saved': 0.0,
'trees_saved': 0.0,
'paper_weight_recycled': 0.0,
'plastic_weight_recycled': 0.0,
'organic_weight_processed': 0.0
},
# Fill level history
'fill_level_history': {},
'balance_tracking': {
'start_date': None,
'days_within_threshold': 0,
'last_check': None
},
# Achievement progress
'achievements': {},
# Bin specialization
'bin_specialization': {}
}
def save(self):
"""Save current metrics to file."""
# Convert datetime objects to string format
metrics_copy = self._prepare_for_serialization(self.metrics)
with open(self.storage_path, 'w') as f:
json.dump(metrics_copy, f, indent=4)
def _prepare_for_serialization(self, data):
"""Prepare data for JSON serialization by converting datetime objects to strings."""
if isinstance(data, dict):
return {k: self._prepare_for_serialization(v) for k, v in data.items()}
elif isinstance(data, list):
return [self._prepare_for_serialization(item) for item in data]
elif isinstance(data, datetime):
return data.isoformat()
elif isinstance(data, set):
return list(data)
return data
def update_sort_metrics(self, bin_id: str, fill_level: float, classification_method: str):
"""Update metrics after a new sort."""
current_time = datetime.now()
# Update basic metrics
self.metrics['total_items_sorted'] += 1
self.metrics['items_sorted_per_bin'][bin_id] = self.metrics['items_sorted_per_bin'].get(bin_id, 0) + 1
self.metrics['sort_timestamps'].append(current_time.isoformat())
self.metrics['fill_levels_per_bin'][bin_id] = fill_level
# Update classification method counts
self.metrics['api_vs_local_usage_counts'][classification_method] += 1
# Update time-based metrics
self._update_time_metrics(current_time)
# Update fill level history
if bin_id not in self.metrics['fill_level_history']:
self.metrics['fill_level_history'][bin_id] = {
'timestamps': [],
'levels': [],
'emptying_timestamps': []
}
self.metrics['fill_level_history'][bin_id]['timestamps'].append(current_time.isoformat())
self.metrics['fill_level_history'][bin_id]['levels'].append(fill_level)
# Save updates to file
self.save()
def _update_time_metrics(self, current_time: datetime):
"""Update time-based metrics."""
date_str = current_time.date().isoformat()
week_str = f"{current_time.year}-W{current_time.isocalendar()[1]}"
month_str = f"{current_time.year}-{current_time.month:02d}"
# Update usage counts
self.metrics['daily_usage_counts'][date_str] = self.metrics['daily_usage_counts'].get(date_str, 0) + 1
self.metrics['weekly_usage_counts'][week_str] = self.metrics['weekly_usage_counts'].get(week_str, 0) + 1
self.metrics['monthly_usage_counts'][month_str] = self.metrics['monthly_usage_counts'].get(month_str, 0) + 1
# Update hour coverage
hour = current_time.hour
if hour not in self.metrics['hours_sorted']:
self.metrics['hours_sorted'].append(hour)
def get_metrics(self) -> dict:
"""Return current metrics."""
return self.metrics
def update_environmental_impact(self, material_type: str, weight: float):
"""Update environmental impact metrics based on material type and weight."""
impact_factors = {
'paper': {
'co2_per_kg': 2.6,
'trees_per_kg': 0.017
},
'plastic': {
'co2_per_kg': 6.0
},
'organic': {
'co2_per_kg': 0.5
}
}
if material_type in impact_factors:
factors = impact_factors[material_type]
self.metrics['environmental_impact']['co2_saved'] += factors.get('co2_per_kg', 0) * weight
if material_type == 'paper':
self.metrics['environmental_impact']['trees_saved'] += factors['trees_per_kg'] * weight
self.metrics['environmental_impact']['paper_weight_recycled'] += weight
elif material_type == 'plastic':
self.metrics['environmental_impact']['plastic_weight_recycled'] += weight
elif material_type == 'organic':
self.metrics['environmental_impact']['organic_weight_processed'] += weight
self.save()Editor is loading...
Leave a Comment