File size: 5,376 Bytes
bf5b4d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"""
AI 垃圾分类助手 - 数据库模块
使用 SQLite 记录用户分类历史和环保积分
"""

import sqlite3
from datetime import date


class Database:
    def __init__(self, db_path="garbage_assistant.db"):
        self.db_path = db_path
        self.init_database()

    def _get_conn(self):
        conn = sqlite3.connect(self.db_path)
        conn.row_factory = sqlite3.Row
        conn.execute("PRAGMA journal_mode=WAL")
        return conn

    def init_database(self):
        conn = self._get_conn()
        conn.executescript("""
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                username TEXT UNIQUE NOT NULL,
                total_points INTEGER DEFAULT 0,
                total_classifications INTEGER DEFAULT 0,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            );

            CREATE TABLE IF NOT EXISTS records (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id INTEGER NOT NULL,
                image_path TEXT,
                predicted_class TEXT NOT NULL,
                confidence REAL,
                points INTEGER DEFAULT 10,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                FOREIGN KEY (user_id) REFERENCES users(id)
            );

            CREATE TABLE IF NOT EXISTS daily_stats (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id INTEGER NOT NULL,
                date TEXT NOT NULL,
                count INTEGER DEFAULT 0,
                points INTEGER DEFAULT 0,
                FOREIGN KEY (user_id) REFERENCES users(id),
                UNIQUE(user_id, date)
            );
        """)
        conn.commit()
        conn.close()

    def register_user(self, username):
        conn = self._get_conn()
        try:
            cursor = conn.cursor()
            cursor.execute("INSERT INTO users (username) VALUES (?)", (username,))
            conn.commit()
            user_id = cursor.lastrowid
            print(f"✓ 用户 '{username}' 注册成功 (ID: {user_id})")
            return user_id
        except sqlite3.IntegrityError:
            user_id = conn.execute(
                "SELECT id FROM users WHERE username = ?", (username,)
            ).fetchone()["id"]
            print(f"ℹ 用户 '{username}' 已存在 (ID: {user_id})")
            return user_id
        finally:
            conn.close()

    def get_user(self, username):
        conn = self._get_conn()
        user = conn.execute(
            "SELECT * FROM users WHERE username = ?", (username,)
        ).fetchone()
        conn.close()
        return dict(user) if user else None

    def add_record(self, user_id, predicted_class, confidence, image_path=None):
        today = date.today().isoformat()
        points = max(5, min(20, int(confidence * 20)))

        conn = self._get_conn()
        conn.execute(
            "INSERT INTO records (user_id, image_path, predicted_class, confidence, points) VALUES (?, ?, ?, ?, ?)",
            (user_id, image_path, predicted_class, confidence, points),
        )
        conn.execute(
            "UPDATE users SET total_points = total_points + ?, total_classifications = total_classifications + 1 WHERE id = ?",
            (points, user_id),
        )
        conn.execute(
            "INSERT INTO daily_stats (user_id, date, count, points) VALUES (?, ?, 1, ?) "
            "ON CONFLICT(user_id, date) DO UPDATE SET count = count + 1, points = points + ?",
            (user_id, today, points, points),
        )
        conn.commit()
        conn.close()
        return points

    def get_user_stats(self, user_id):
        conn = self._get_conn()
        user = conn.execute("SELECT * FROM users WHERE id = ?", (user_id,)).fetchone()
        if not user:
            conn.close()
            return None

        stats = dict(user)
        stats["recent_records"] = [
            dict(r) for r in conn.execute(
                "SELECT predicted_class, confidence, points, created_at FROM records WHERE user_id = ? ORDER BY created_at DESC LIMIT 10",
                (user_id,),
            ).fetchall()
        ]
        stats["class_distribution"] = [
            dict(r) for r in conn.execute(
                "SELECT predicted_class, COUNT(*) as count FROM records WHERE user_id = ? GROUP BY predicted_class ORDER BY count DESC",
                (user_id,),
            ).fetchall()
        ]

        today = date.today().isoformat()
        today_row = conn.execute(
            "SELECT * FROM daily_stats WHERE user_id = ? AND date = ?", (user_id, today)
        ).fetchone()
        stats["today"] = dict(today_row) if today_row else {"count": 0, "points": 0}

        stats["weekly"] = [
            dict(r) for r in conn.execute(
                "SELECT date, count, points FROM daily_stats WHERE user_id = ? AND date >= date('now', '-7 days') ORDER BY date DESC",
                (user_id,),
            ).fetchall()
        ]

        conn.close()
        return stats

    def get_leaderboard(self, limit=10):
        conn = self._get_conn()
        leaders = conn.execute(
            "SELECT username, total_points, total_classifications FROM users ORDER BY total_points DESC LIMIT ?",
            (limit,),
        ).fetchall()
        conn.close()
        return [dict(r) for r in leaders]