/
m2517724
/
test
Обзор
Документация
Войти
/
m2517724
/
test
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
database.py
215 строк
12 KB
eddanilina-coder
Add database.py and utils.py from danilina branch
13 дек 2025, 20:15
13 дек 2025, 20:15
a386143
Код
Авторство
О чём код?
import aiosqlite from config import DATABASE_PATH async def init_database(): async with aiosqlite.connect(DATABASE_PATH) as db: await db.execute(''' CREATE TABLE IF NOT EXISTS subjects ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL, display_name TEXT NOT NULL ) ''') await db.execute(''' CREATE TABLE IF NOT EXISTS tickets ( id INTEGER PRIMARY KEY AUTOINCREMENT, subject_id INTEGER NOT NULL, number INTEGER NOT NULL, title TEXT NOT NULL, question TEXT NOT NULL, answer TEXT NOT NULL, FOREIGN KEY (subject_id) REFERENCES subjects(id), UNIQUE(subject_id, number) ) ''') await db.execute(''' CREATE TABLE IF NOT EXISTS user_progress ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, ticket_id INTEGER NOT NULL, is_learned INTEGER DEFAULT 0, skip_count INTEGER DEFAULT 0, FOREIGN KEY (ticket_id) REFERENCES tickets(id), UNIQUE(user_id, ticket_id) ) ''') await db.commit() async def seed_data(): async with aiosqlite.connect(DATABASE_PATH) as db: cursor = await db.execute("SELECT COUNT(*) FROM subjects") row = await cursor.fetchone() count = row[0] if count > 0: return subjects = [ ("vychmash", "Вычмаш"), ("matvpiska", "Матвписка"), ("polevoy", "Полевой") ] await db.executemany("INSERT INTO subjects (name, display_name) VALUES (?, ?)", subjects) vychmash_tickets = [ (1, "Основы вычислительной математики", "Расскажите об основах вычислительной математики", "Вычислительная математика — раздел математики, включающий круг вопросов, связанных с производством вычислений. В более узком понимании вычислительная математика — теория численных методов решения типовых математических задач."), (2, "Численные методы", "Что такое численные методы?", "Численные методы — методы решения математических задач в численном виде. Представление как исходных данных в задаче, так и её решения — в виде числа или набора чисел."), (3, "Аппроксимация функций", "Объясните аппроксимацию функций", "Аппроксимация — замена одних математических объектов другими, в том или ином смысле близкими к исходным. Аппроксимация позволяет исследовать числовые характеристики и качественные свойства объекта."), (4, "Численное интегрирование", "Расскажите о численном интегрировании", "Численное интегрирование — вычисление значения определённого интеграла. Основные методы: метод прямоугольников, метод трапеций, метод Симпсона."), (5, "Решение СЛАУ", "Методы решения СЛАУ", "Методы решения СЛАУ делятся на прямые (метод Гаусса, LU-разложение) и итерационные (метод Якоби, метод Гаусса-Зейделя). Прямые методы дают точное решение за конечное число операций.") ] matvpiska_tickets = [ (1, "Основы математической логики", "Расскажите об основах математической логики", "Математическая логика — раздел математики, изучающий математические обозначения, формальные системы, доказуемость математических суждений, природу математического доказательства."), (2, "Теория множеств", "Что такое теория множеств?", "Теория множеств — раздел математики, в котором изучаются общие свойства множеств. Основные операции: объединение, пересечение, разность, симметрическая разность."), (3, "Комбинаторика", "Объясните основы комбинаторики", "Комбинаторика — раздел математики, изучающий дискретные объекты, множества и отношения на них. Основные формулы: перестановки P(n)=n!, размещения A(n,k)=n!/(n-k)!, сочетания C(n,k)=n!/k!(n-k)!") ] polevoy_tickets = [ (1, "l-value и r-value", "Что такое l-value и r-value?", "l-value — объект с определённым адресом памяти (например, переменная x), сохраняется за пределами одного выражения.\nr-value — временное значение без определённого адреса памяти, существует только в пределах одного выражения."), (2, "Векторные поля", "Расскажите о векторных полях", "Векторное поле — отображение, которое каждой точке пространства ставит в соответствие вектор. Примеры: поле скоростей жидкости, электрическое поле, магнитное поле."), (3, "Скалярные поля", "Что такое скалярные поля?", "Скалярное поле — функция, которая каждой точке пространства ставит в соответствие скалярную величину. Примеры: температурное поле, поле давления, потенциал.") ] cursor = await db.execute("SELECT id FROM subjects WHERE name = 'vychmash'") row = await cursor.fetchone() vychmash_id = row[0] for num, title, question, answer in vychmash_tickets: await db.execute( "INSERT INTO tickets (subject_id, number, title, question, answer) VALUES (?, ?, ?, ?, ?)", (vychmash_id, num, title, question, answer) ) cursor = await db.execute("SELECT id FROM subjects WHERE name = 'matvpiska'") row = await cursor.fetchone() matvpiska_id = row[0] for num, title, question, answer in matvpiska_tickets: await db.execute( "INSERT INTO tickets (subject_id, number, title, question, answer) VALUES (?, ?, ?, ?, ?)", (matvpiska_id, num, title, question, answer) ) cursor = await db.execute("SELECT id FROM subjects WHERE name = 'polevoy'") row = await cursor.fetchone() polevoy_id = row[0] for num, title, question, answer in polevoy_tickets: await db.execute( "INSERT INTO tickets (subject_id, number, title, question, answer) VALUES (?, ?, ?, ?, ?)", (polevoy_id, num, title, question, answer) ) await db.commit() async def get_subject_by_name(display_name): async with aiosqlite.connect(DATABASE_PATH) as db: cursor = await db.execute("SELECT id, name, display_name FROM subjects WHERE display_name = ?", (display_name,)) row = await cursor.fetchone() return row async def get_tickets_by_subject(subject_id): async with aiosqlite.connect(DATABASE_PATH) as db: cursor = await db.execute( "SELECT id, number, title, question, answer FROM tickets WHERE subject_id = ? ORDER BY number", (subject_id,) ) rows = await cursor.fetchall() return rows async def get_ticket(ticket_id): async with aiosqlite.connect(DATABASE_PATH) as db: cursor = await db.execute( "SELECT t.id, t.number, t.title, t.question, t.answer, s.display_name " "FROM tickets t JOIN subjects s ON t.subject_id = s.id WHERE t.id = ?", (ticket_id,) ) row = await cursor.fetchone() return row async def get_ticket_count(subject_id): async with aiosqlite.connect(DATABASE_PATH) as db: cursor = await db.execute("SELECT COUNT(*) FROM tickets WHERE subject_id = ?", (subject_id,)) row = await cursor.fetchone() return row[0] async def get_user_progress(user_id, subject_id): async with aiosqlite.connect(DATABASE_PATH) as db: cursor = await db.execute(''' SELECT COUNT(*) FROM user_progress up JOIN tickets t ON up.ticket_id = t.id WHERE up.user_id = ? AND t.subject_id = ? AND up.is_learned = 1 ''', (user_id, subject_id)) row = await cursor.fetchone() learned = row[0] cursor = await db.execute(''' SELECT t.number, up.skip_count FROM user_progress up JOIN tickets t ON up.ticket_id = t.id WHERE up.user_id = ? AND t.subject_id = ? AND up.skip_count >= 3 ''', (user_id, subject_id)) problematic = await cursor.fetchall() return {"learned": learned, "problematic": problematic} async def mark_ticket_learned(user_id, ticket_id): async with aiosqlite.connect(DATABASE_PATH) as db: await db.execute(''' INSERT INTO user_progress (user_id, ticket_id, is_learned, skip_count) VALUES (?, ?, 1, 0) ON CONFLICT(user_id, ticket_id) DO UPDATE SET is_learned = 1, skip_count = 0 ''', (user_id, ticket_id)) await db.commit() async def skip_ticket(user_id, ticket_id): async with aiosqlite.connect(DATABASE_PATH) as db: await db.execute(''' INSERT INTO user_progress (user_id, ticket_id, is_learned, skip_count) VALUES (?, ?, 0, 1) ON CONFLICT(user_id, ticket_id) DO UPDATE SET skip_count = skip_count + 1, is_learned = 0 ''', (user_id, ticket_id)) cursor = await db.execute("SELECT skip_count FROM user_progress WHERE user_id = ? AND ticket_id = ?", (user_id, ticket_id)) row = await cursor.fetchone() skip_count = row[0] await db.commit() return skip_count async def get_ticket_weights(user_id, subject_id): async with aiosqlite.connect(DATABASE_PATH) as db: cursor = await db.execute(''' SELECT t.id, COALESCE(up.is_learned, 0) as is_learned, COALESCE(up.skip_count, 0) as skip_count FROM tickets t LEFT JOIN user_progress up ON t.id = up.ticket_id AND up.user_id = ? WHERE t.subject_id = ? ''', (user_id, subject_id)) rows = await cursor.fetchall() weights = {} for ticket_id, is_learned, skip_count in rows: if skip_count >= 3: weights[ticket_id] = 3.0 elif is_learned: weights[ticket_id] = 0.5 else: weights[ticket_id] = 1.0 return weights