import { PrismaClient } from '@prisma/client'; import * as fs from 'fs'; import * as path from 'path'; import { randomUUID } from 'crypto'; const prisma = new PrismaClient(); // Helper function: Add UUIDs to questions and answers if they don't have them // This is a copy from src/utils/question-utils.ts to avoid dependency on src in production interface Answer { id?: string; text: string; points: number; } interface Question { id?: string; text?: string; question?: string; answers: Answer[]; } function ensureQuestionIds(questions: Question[]): Question[] { return questions.map((question) => { const questionId = question.id || randomUUID(); const questionText = question.text || question.question || ''; const answersWithIds = question.answers.map((answer) => ({ ...answer, id: answer.id || randomUUID(), })); return { ...question, id: questionId, text: questionText, question: questionText, // Keep both fields for compatibility answers: answersWithIds, }; }); } async function main() { console.log('Starting seed...'); // Create demo user const demoUser = await prisma.user.upsert({ where: { email: 'demo@100k1.ru' }, update: {}, create: { email: 'demo@100k1.ru', name: 'Демо пользователь', }, }); console.log('Demo user created:', demoUser); // Demo questions data const demoQuestions = [ { text: 'Что дед мороз делает летом?', answers: [ { text: 'Отдыхает', points: 100 }, { text: 'Готовит подарки', points: 80 }, { text: 'Спит', points: 60 }, { text: 'Путешествует', points: 40 }, { text: 'Загорает', points: 20 }, { text: 'Работает', points: 10 }, ], }, { text: 'Что намазывают на хлеб?', answers: [ { text: 'Масло', points: 100 }, { text: 'Икру', points: 80 }, { text: 'Варенье', points: 60 }, { text: 'Паштет', points: 40 }, { text: 'Майонез', points: 20 }, { text: 'Горчицу', points: 10 }, ], }, { text: 'Кто работает в новый год?', answers: [ { text: 'Дед Мороз', points: 100 }, { text: 'Снегурочка', points: 80 }, { text: 'Врач', points: 60 }, { text: 'Полицейский', points: 40 }, { text: 'Таксист', points: 20 }, { text: 'Продавец', points: 10 }, ], }, { text: 'Почему лошадь не курит?', answers: [ { text: 'Боится умереть', points: 100 }, { text: 'Неудобно (копыта мешают)', points: 80 }, { text: 'Не хочет', points: 60 }, { text: 'Не продают', points: 40 }, ], }, { text: 'Какая самая "лошадиная" фамилия?', answers: [ { text: 'Конев', points: 100 }, { text: 'Жеребцов', points: 80 }, { text: 'Кобылин', points: 60 }, { text: 'Табунов', points: 40 }, { text: 'Лошадкин', points: 20 }, ], }, { text: 'Что носят на голове?', answers: [ { text: 'Шапка', points: 100 }, { text: 'Шляпа', points: 80 }, { text: 'Кепка', points: 60 }, { text: 'Корона', points: 40 }, { text: 'Платок', points: 20 }, { text: 'Панама', points: 10 }, ], }, { text: 'Что можно найти в холодильнике?', answers: [ { text: 'Еда', points: 100 }, { text: 'Молоко', points: 80 }, { text: 'Колбаса', points: 60 }, { text: 'Масло', points: 40 }, { text: 'Лёд', points: 20 }, { text: 'Свет', points: 10 }, ], }, { text: 'Где можно встретить новый год?', answers: [ { text: 'Дома', points: 100 }, { text: 'На улице', points: 80 }, { text: 'В кафе', points: 60 }, { text: 'У друзей', points: 40 }, { text: 'На работе', points: 20 }, { text: 'В самолёте', points: 10 }, ], }, ]; // Create question pack const demoQuestionsWithIds = ensureQuestionIds(demoQuestions); const questionPack = await prisma.questionPack.upsert({ where: { id: 'demo-pack-1' }, update: {}, create: { id: 'demo-pack-1', name: 'Демо пак вопросов', description: 'Базовый набор вопросов для игры "100 к 1"', category: 'Общие', isPublic: true, createdBy: demoUser.id, questions: demoQuestionsWithIds as any, questionCount: demoQuestionsWithIds.length, rating: 5.0, }, }); console.log('Question pack created:', questionPack); // Create family questions pack const familyQuestions = [ { text: 'Что мама говорит чаще всего?', answers: [ { text: 'Убери', points: 100 }, { text: 'Поешь', points: 80 }, { text: 'Спать', points: 60 }, { text: 'Я люблю тебя', points: 40 }, { text: 'Делай уроки', points: 20 }, ], }, { text: 'Что папа делает на выходных?', answers: [ { text: 'Отдыхает', points: 100 }, { text: 'Чинит что-то', points: 80 }, { text: 'Смотрит телевизор', points: 60 }, { text: 'Спит', points: 40 }, { text: 'Работает', points: 20 }, ], }, { text: 'Что бабушка любит дарить внукам?', answers: [ { text: 'Деньги', points: 100 }, { text: 'Еду', points: 80 }, { text: 'Одежду', points: 60 }, { text: 'Игрушки', points: 40 }, { text: 'Конфеты', points: 20 }, ], }, ]; const familyQuestionsWithIds = ensureQuestionIds(familyQuestions); const familyPack = await prisma.questionPack.upsert({ where: { id: 'family-pack-1' }, update: {}, create: { id: 'family-pack-1', name: 'Семейные вопросы', description: 'Вопросы для семейной игры', category: 'Семья', isPublic: true, createdBy: demoUser.id, questions: familyQuestionsWithIds as any, questionCount: familyQuestionsWithIds.length, rating: 4.8, }, }); console.log('Family pack created:', familyPack); // Read default questions from JSON file // questions.json is in the project root, one level up from backend/ const questionsJsonPath = path.resolve( process.cwd(), '../questions.json', ); const questionsJson = JSON.parse( fs.readFileSync(questionsJsonPath, 'utf-8'), ); // Transform questions: remove id field const defaultQuestions = questionsJson.map((q: any) => ({ text: q.text, answers: q.answers, })); // Add UUID to questions const defaultQuestionsWithIds = ensureQuestionIds(defaultQuestions); // Create default question pack const defaultPack = await prisma.questionPack.upsert({ where: { id: 'default-pack-1' }, update: {}, create: { id: 'default-pack-1', name: 'Новогодние вопросы', description: 'Новогодние вопросы', category: 'Новый год', isPublic: true, createdBy: demoUser.id, questions: defaultQuestionsWithIds as any, questionCount: defaultQuestionsWithIds.length, rating: 5.0, }, }); console.log('Default pack created:', defaultPack); // Create default themes const defaultThemes = [ { id: 'new-year', name: 'Новый год', icon: '🎄', description: 'Праздничная новогодняя тема с золотым свечением', isPublic: true, colors: { bgPrimary: 'linear-gradient(135deg, #1a4d7a 0%, #2b0d4f 50%, #4a1942 100%)', bgOverlay: 'rgba(10, 10, 30, 0.4)', bgCard: 'rgba(255, 255, 255, 0.12)', bgCardHover: 'rgba(255, 255, 255, 0.18)', textPrimary: '#ffffff', textSecondary: 'rgba(255, 255, 255, 0.95)', textGlow: 'rgba(255, 215, 0, 1)', accentPrimary: '#ffd700', accentSecondary: '#ff6b6b', accentSuccess: '#4ecdc4', borderColor: 'rgba(255, 215, 0, 0.4)', borderGlow: 'rgba(255, 215, 0, 0.6)', }, settings: { shadowSm: '0 2px 15px rgba(255, 215, 0, 0.2)', shadowMd: '0 4px 20px rgba(255, 215, 0, 0.3)', shadowLg: '0 8px 35px rgba(255, 215, 0, 0.4)', blurAmount: '10px', borderRadiusSm: '12px', borderRadiusMd: '15px', borderRadiusLg: '20px', animationSpeed: '0.3s', }, }, { id: 'family', name: 'Семейная', icon: '🏠', description: 'Светлая и уютная тема для семейной игры', isPublic: true, colors: { bgPrimary: 'linear-gradient(135deg, #56ccf2 0%, #2f80ed 50%, #b2fefa 100%)', bgOverlay: 'rgba(255, 255, 255, 0.1)', bgCard: 'rgba(255, 255, 255, 0.25)', bgCardHover: 'rgba(255, 255, 255, 0.35)', textPrimary: '#2d3748', textSecondary: '#4a5568', textGlow: 'rgba(47, 128, 237, 0.8)', accentPrimary: '#2f80ed', accentSecondary: '#eb5757', accentSuccess: '#27ae60', borderColor: 'rgba(47, 128, 237, 0.3)', borderGlow: 'rgba(47, 128, 237, 0.5)', }, settings: { shadowSm: '0 2px 10px rgba(47, 128, 237, 0.15)', shadowMd: '0 4px 15px rgba(47, 128, 237, 0.2)', shadowLg: '0 8px 30px rgba(47, 128, 237, 0.25)', blurAmount: '10px', borderRadiusSm: '12px', borderRadiusMd: '15px', borderRadiusLg: '20px', animationSpeed: '0.3s', }, }, { id: 'party', name: 'Вечеринка', icon: '🎉', description: 'Яркая энергичная тема для шумных компаний', isPublic: true, colors: { bgPrimary: 'linear-gradient(135deg, #f093fb 0%, #f5576c 50%, #4facfe 100%)', bgOverlay: 'rgba(0, 0, 0, 0.2)', bgCard: 'rgba(255, 255, 255, 0.15)', bgCardHover: 'rgba(255, 255, 255, 0.25)', textPrimary: '#ffffff', textSecondary: 'rgba(255, 255, 255, 0.95)', textGlow: 'rgba(255, 87, 108, 1)', accentPrimary: '#f5576c', accentSecondary: '#f093fb', accentSuccess: '#4facfe', borderColor: 'rgba(255, 87, 108, 0.5)', borderGlow: 'rgba(255, 87, 108, 0.7)', }, settings: { shadowSm: '0 2px 15px rgba(245, 87, 108, 0.3)', shadowMd: '0 4px 20px rgba(245, 87, 108, 0.4)', shadowLg: '0 8px 35px rgba(245, 87, 108, 0.5)', blurAmount: '10px', borderRadiusSm: '12px', borderRadiusMd: '15px', borderRadiusLg: '20px', animationSpeed: '0.2s', }, }, { id: 'dark', name: 'Темная', icon: '🌙', description: 'Контрастная тема для ТВ и проектора', isPublic: true, colors: { bgPrimary: 'linear-gradient(135deg, #0f0f0f 0%, #1a1a1a 100%)', bgOverlay: 'rgba(0, 0, 0, 0.7)', bgCard: 'rgba(40, 40, 40, 0.8)', bgCardHover: 'rgba(60, 60, 60, 0.9)', textPrimary: '#e0e0e0', textSecondary: '#b0b0b0', textGlow: 'rgba(100, 255, 218, 0.8)', accentPrimary: '#64ffda', accentSecondary: '#ff5370', accentSuccess: '#c3e88d', borderColor: 'rgba(100, 255, 218, 0.3)', borderGlow: 'rgba(100, 255, 218, 0.5)', }, settings: { shadowSm: '0 2px 10px rgba(0, 0, 0, 0.5)', shadowMd: '0 4px 15px rgba(0, 0, 0, 0.6)', shadowLg: '0 8px 30px rgba(0, 0, 0, 0.7)', blurAmount: '5px', borderRadiusSm: '12px', borderRadiusMd: '15px', borderRadiusLg: '20px', animationSpeed: '0.3s', }, }, ]; for (const theme of defaultThemes) { await prisma.theme.upsert({ where: { id: theme.id }, update: { name: theme.name, icon: theme.icon, description: theme.description, isPublic: theme.isPublic, colors: theme.colors as any, settings: theme.settings as any, }, create: { id: theme.id, name: theme.name, icon: theme.icon, description: theme.description, isPublic: theme.isPublic, createdBy: demoUser.id, colors: theme.colors as any, settings: theme.settings as any, }, }); console.log(`Theme "${theme.name}" created/updated`); } console.log('Seed completed successfully!'); } main() .then(async () => { await prisma.$disconnect(); }) .catch(async (e) => { console.error('Seed error:', e); await prisma.$disconnect(); process.exit(1); });