Untitled

 avatar
unknown
plain_text
11 days ago
5.2 kB
3
Indexable
// /hooks/useMetrics.ts
'use client';

import { useState, useEffect, useMemo } from 'react';
import type { MetricsData } from '@/app/api/metrics/route';

interface ProcessedFillLevelData {
  timestamp: string;
  fill_level: number;
  bin_id: string;
}

export function useMetrics() {
  const [metrics, setMetrics] = useState<MetricsData | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    async function fetchMetrics() {
      try {
        const response = await fetch('/api/metrics');
        if (!response.ok) throw new Error('Failed to fetch metrics');
        
        const data = await response.json();
        setMetrics(data);
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Failed to load metrics');
      } finally {
        setLoading(false);
      }
    }

    fetchMetrics();
    const intervalId = setInterval(fetchMetrics, 5000);
    return () => clearInterval(intervalId);
  }, []);

  // Memoized helper functions for accessing fill level data
  const helpers = useMemo(() => {
    if (!metrics) return null;

    return {
      // Get all unique bin IDs that have any kind of data
      getActiveBinIds: () => {
        const binIds = new Set<string>();
        
        // Check fill predictions
        Object.keys(metrics.fill_predictions || {}).forEach(id => binIds.add(id));
        
        // Check fill level history
        Object.keys(metrics.fill_level_history || {}).forEach(id => binIds.add(id));
        
        // Check classification results
        metrics.basic_metrics.classification_results.forEach(result => binIds.add(result.bin_id));
        
        return Array.from(binIds);
      },

      // Get processed fill level history for a specific bin or all bins
      getFillLevelHistory: (binId?: string, timeRange?: {start: Date, end: Date}) => {
        const results = metrics.basic_metrics.classification_results
          .map(result => ({
            timestamp: result.timestamp,
            fill_level: result.fill_level,
            bin_id: result.bin_id
          }));

        let filtered = results;
        
        // Filter by bin if specified
        if (binId) {
          filtered = filtered.filter(result => result.bin_id === binId);
        }

        // Filter by time range if specified
        if (timeRange) {
          filtered = filtered.filter(result => {
            const timestamp = new Date(result.timestamp);
            return timestamp >= timeRange.start && timestamp <= timeRange.end;
          });
        }

        return filtered.sort((a, b) => 
          new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
        );
      },

      // Get emptying events for a specific bin or all bins
      getEmptyingEvents: (binId?: string, timeRange?: {start: Date, end: Date}) => {
        const history = metrics.fill_level_history;
        const events: Array<{
          timestamp: string;
          fill_level: number;
          bin_id: string;
        }> = [];

        Object.entries(history).forEach(([id, data]) => {
          if (!binId || id === binId) {
            data.emptying_timestamps.forEach((timestamp, index) => {
              events.push({
                timestamp,
                fill_level: data.fill_levels_at_empty[index],
                bin_id: id
              });
            });
          }
        });

        let filtered = events;

        // Filter by time range if specified
        if (timeRange) {
          filtered = filtered.filter(event => {
            const timestamp = new Date(event.timestamp);
            return timestamp >= timeRange.start && timestamp <= timeRange.end;
          });
        }

        return filtered.sort((a, b) => 
          new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
        );
      },

      // Get the latest fill level prediction for a specific bin or all bins
      getLatestPredictions: (binId?: string) => {
        const predictions = metrics.fill_predictions;
        if (binId) {
          return predictions[binId] ? { [binId]: predictions[binId] } : {};
        }
        return predictions;
      },

      // Get proactive emptying statistics
      getProactiveEmptyingStats: () => {
        const emptyingEvents = Object.values(metrics.fill_level_history).flatMap(
          history => history.fill_levels_at_empty
        );

        // Group emptying events by fill level ranges (0-20%, 21-40%, etc.)
        const ranges = Array.from({ length: 5 }, (_, i) => ({
          range: `${i * 20 + 1}-${(i + 1) * 20}%`,
          count: emptyingEvents.filter(
            level => level > i * 20 && level <= (i + 1) * 20
          ).length
        }));

        ranges.push({
          range: '81-100%',
          count: emptyingEvents.filter(level => level > 80).length
        });

        return ranges;
      }
    };
  }, [metrics]);

  return { 
    metrics, 
    loading, 
    error,
    helpers 
  };
}
Leave a Comment