Untitled

 avatar
unknown
plain_text
a month ago
9.5 kB
1
Indexable
'use client'

import { useEffect, useState } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { 
  BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer,
  LineChart, Line, PieChart, Pie, Cell
} from 'recharts';
import { Trash2, Recycle, Clock, BarChart2, Calendar, Zap, TrendingUp, RatioIcon as Balance, Timer } from 'lucide-react';

interface StatsData {
  totalItemsSorted: number;
  itemsPerWasteType: Record<string, number>;
  sortingTimestamps: Array<{ timestamp: string; wasteType: string }>;
  bins: Array<{ id: number; type: string; fillLevel: number; emptyings: number }>;
  modelUsage: { api: number; local: number };
  dailyUsage: Array<{ date: string; count: number }>;
  weeklyUsage: Array<{ week: string; count: number }>;
  monthlyUsage: Array<{ month: string; count: number }>;
  timeBetweenSorts: { average: number; min: number; max: number };
  timeOfDayPatterns: Array<{ hour: number; count: number }>;
  streaks: { daily: number; weekly: number; monthly: number };
  binMetrics: {
    timeTo90PercentFull: { average: number; min: number; max: number };
    fillRate: { average: number; min: number; max: number };
    fillLevelBalance: number;
  };
  classificationResponseTimes: { average: number; min: number; max: number };
}

export default function StatsDisplay() {
  const [stats, setStats] = useState<StatsData | null>(null);

  useEffect(() => {
    fetch('/home/SortiMate/web/stats.json')
      .then(response => response.json())
      .then(data => setStats(data));
  }, []);

  if (!stats) return null;

  const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042', '#8884D8'];

  return (
    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
      <Card>
        <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
          <CardTitle className="text-sm font-medium">Total Items Sorted</CardTitle>
          <Trash2 className="h-4 w-4 text-muted-foreground" />
        </CardHeader>
        <CardContent>
          <div className="text-2xl font-bold">{stats.totalItemsSorted}</div>
        </CardContent>
      </Card>

      <Card>
        <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
          <CardTitle className="text-sm font-medium">Items per Waste Type</CardTitle>
          <Recycle className="h-4 w-4 text-muted-foreground" />
        </CardHeader>
        <CardContent className="h-[200px]">
          <ResponsiveContainer width="100%" height="100%">
            <PieChart>
              <Pie
                data={Object.entries(stats.itemsPerWasteType).map(([name, value]) => ({ name, value }))}
                cx="50%"
                cy="50%"
                outerRadius={80}
                fill="#8884d8"
                dataKey="value"
                label
              >
                {Object.entries(stats.itemsPerWasteType).map((entry, index) => (
                  <Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
                ))}
              </Pie>
              <Tooltip />
              <Legend />
            </PieChart>
          </ResponsiveContainer>
        </CardContent>
      </Card>

      <Card>
        <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
          <CardTitle className="text-sm font-medium">Sorting Timestamps</CardTitle>
          <Clock className="h-4 w-4 text-muted-foreground" />
        </CardHeader>
        <CardContent className="h-[200px]">
          <ResponsiveContainer width="100%" height="100%">
            <LineChart data={stats.sortingTimestamps.slice(-50)}>
              <XAxis dataKey="timestamp" />
              <YAxis />
              <Tooltip />
              <Line type="monotone" dataKey="wasteType" stroke="#8884d8" />
            </LineChart>
          </ResponsiveContainer>
        </CardContent>
      </Card>

      <Card>
        <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
          <CardTitle className="text-sm font-medium">Fill Levels per Bin</CardTitle>
          <BarChart2 className="h-4 w-4 text-muted-foreground" />
        </CardHeader>
        <CardContent className="h-[200px]">
          <ResponsiveContainer width="100%" height="100%">
            <BarChart data={stats.bins}>
              <CartesianGrid strokeDasharray="3 3" />
              <XAxis dataKey="type" />
              <YAxis />
              <Tooltip />
              <Legend />
              <Bar dataKey="fillLevel" fill="#8884d8" />
            </BarChart>
          </ResponsiveContainer>
        </CardContent>
      </Card>

      <Card>
        <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
          <CardTitle className="text-sm font-medium">API vs Local Model Usage</CardTitle>
          <Zap className="h-4 w-4 text-muted-foreground" />
        </CardHeader>
        <CardContent className="h-[200px]">
          <ResponsiveContainer width="100%" height="100%">
            <PieChart>
              <Pie
                data={[
                  { name: 'API', value: stats.modelUsage.api },
                  { name: 'Local', value: stats.modelUsage.local }
                ]}
                cx="50%"
                cy="50%"
                outerRadius={80}
                fill="#8884d8"
                dataKey="value"
                label
              >
                <Cell fill="#0088FE" />
                <Cell fill="#00C49F" />
              </Pie>
              <Tooltip />
              <Legend />
            </PieChart>
          </ResponsiveContainer>
        </CardContent>
      </Card>

      <Card>
        <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
          <CardTitle className="text-sm font-medium">Usage Counts</CardTitle>
          <Calendar className="h-4 w-4 text-muted-foreground" />
        </CardHeader>
        <CardContent className="h-[200px]">
          <ResponsiveContainer width="100%" height="100%">
            <LineChart>
              <XAxis dataKey="date" />
              <YAxis />
              <Tooltip />
              <Legend />
              <Line type="monotone" data={stats.dailyUsage.slice(-30)} name="Daily" dataKey="count" stroke="#8884d8" />
              <Line type="monotone" data={stats.weeklyUsage.slice(-4)} name="Weekly" dataKey="count" stroke="#82ca9d" />
              <Line type="monotone" data={stats.monthlyUsage.slice(-12)} name="Monthly" dataKey="count" stroke="#ffc658" />
            </LineChart>
          </ResponsiveContainer>
        </CardContent>
      </Card>

      <Card>
        <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
          <CardTitle className="text-sm font-medium">Time of Day Patterns</CardTitle>
          <Clock className="h-4 w-4 text-muted-foreground" />
        </CardHeader>
        <CardContent className="h-[200px]">
          <ResponsiveContainer width="100%" height="100%">
            <BarChart data={stats.timeOfDayPatterns}>
              <CartesianGrid strokeDasharray="3 3" />
              <XAxis dataKey="hour" />
              <YAxis />
              <Tooltip />
              <Bar dataKey="count" fill="#8884d8" />
            </BarChart>
          </ResponsiveContainer>
        </CardContent>
      </Card>

      <Card>
        <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
          <CardTitle className="text-sm font-medium">Bin Metrics</CardTitle>
          <TrendingUp className="h-4 w-4 text-muted-foreground" />
        </CardHeader>
        <CardContent>
          <div className="space-y-2">
            <div>
              <span className="font-medium">Time to 90% Full (avg): </span>
              {Math.round(stats.binMetrics.timeTo90PercentFull.average / 3600)} hours
            </div>
            <div>
              <span className="font-medium">Fill Rate (avg): </span>
              {stats.binMetrics.fillRate.average.toFixed(2)} %/hour
            </div>
            <div>
              <span className="font-medium">Fill Level Balance: </span>
              {(stats.binMetrics.fillLevelBalance * 100).toFixed(2)}%
            </div>
          </div>
        </CardContent>
      </Card>

      <Card>
        <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
          <CardTitle className="text-sm font-medium">Classification Response Times</CardTitle>
          <Timer className="h-4 w-4 text-muted-foreground" />
        </CardHeader>
        <CardContent>
          <div className="space-y-2">
            <div>
              <span className="font-medium">Average: </span>
              {stats.classificationResponseTimes.average} ms
            </div>
            <div>
              <span className="font-medium">Min: </span>
              {stats.classificationResponseTimes.min} ms
            </div>
            <div>
              <span className="font-medium">Max: </span>
              {stats.classificationResponseTimes.max} ms
            </div>
          </div>
        </CardContent>
      </Card>
    </div>
  );
}

Leave a Comment