sticky qrcode
This commit is contained in:
parent
b2121cc133
commit
f4883ee6ea
@ -278,6 +278,9 @@ const LessonDetail = () => {
|
||||
borderRadius="xl"
|
||||
bg={colorMode === "light" ? "gray.50" : "gray.700"}
|
||||
boxShadow="md"
|
||||
position="sticky"
|
||||
top="20px"
|
||||
zIndex="2"
|
||||
><Box pb={3}>
|
||||
{formatDate(accessCode?.body?.lesson?.date, t('journal.pl.lesson.dateFormat'))}{' '}
|
||||
{t('journal.pl.common.marked')} -
|
||||
|
@ -1,21 +1,88 @@
|
||||
const router = require('express').Router()
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
const mockGenerator = require('./mock-generator')
|
||||
|
||||
// Функция для чтения JSON файла и случайной модификации содержимого
|
||||
function readAndModifyJson(filePath) {
|
||||
try {
|
||||
// Используем fs.readFileSync вместо require для избежания кэширования
|
||||
const fullPath = path.resolve(__dirname, filePath);
|
||||
const fileContent = fs.readFileSync(fullPath, 'utf8');
|
||||
const jsonContent = JSON.parse(fileContent);
|
||||
|
||||
// Если это список учеников, немного перемешаем их
|
||||
if (jsonContent.body && Array.isArray(jsonContent.body.students)) {
|
||||
jsonContent.body.students.sort(() => 0.5 - Math.random());
|
||||
}
|
||||
|
||||
// Если это список реакций, обновим время создания и слегка перемешаем
|
||||
if (jsonContent.body && Array.isArray(jsonContent.body.reactions)) {
|
||||
const now = Date.now();
|
||||
jsonContent.body.reactions.forEach((reaction, index) => {
|
||||
// Интервал от 10 секунд до 2 минут назад
|
||||
const randomTime = now - Math.floor(Math.random() * (120000 - 10000) + 10000);
|
||||
reaction.created = new Date(randomTime).toISOString();
|
||||
});
|
||||
|
||||
// Сортируем реакции по времени создания (новые сверху)
|
||||
jsonContent.body.reactions.sort((a, b) =>
|
||||
new Date(b.created) - new Date(a.created)
|
||||
);
|
||||
}
|
||||
|
||||
// Если это список уроков, обновим даты
|
||||
if (jsonContent.body && Array.isArray(jsonContent.body) && jsonContent.body[0] && jsonContent.body[0].name) {
|
||||
jsonContent.body.forEach((lesson) => {
|
||||
// Случайная дата в пределах последних 3 месяцев
|
||||
const randomDate = new Date();
|
||||
randomDate.setMonth(randomDate.getMonth() - Math.random() * 3);
|
||||
lesson.date = randomDate.toISOString();
|
||||
lesson.created = new Date(randomDate.getTime() - 86400000).toISOString(); // Создан за день до даты
|
||||
});
|
||||
}
|
||||
|
||||
// Если это список курсов, добавим случайные данные
|
||||
if (jsonContent.body && Array.isArray(jsonContent.body) && jsonContent.body[0] && jsonContent.body[0].id) {
|
||||
jsonContent.body.forEach((course) => {
|
||||
course.startDt = new Date(new Date().getTime() - Math.random() * 31536000000).toISOString(); // В пределах года
|
||||
course.created = new Date(new Date(course.startDt).getTime() - 604800000).toISOString(); // Создан за неделю до начала
|
||||
});
|
||||
}
|
||||
|
||||
return jsonContent;
|
||||
} catch (error) {
|
||||
console.error(`Error reading/modifying file ${filePath}:`, error);
|
||||
return { success: false, error: "Failed to read file" };
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для чтения JSON без модификации
|
||||
function readJsonFile(filePath) {
|
||||
try {
|
||||
const fullPath = path.resolve(__dirname, filePath);
|
||||
const fileContent = fs.readFileSync(fullPath, 'utf8');
|
||||
return JSON.parse(fileContent);
|
||||
} catch (error) {
|
||||
console.error(`Error reading file ${filePath}:`, error);
|
||||
return { success: false, error: "Failed to read file" };
|
||||
}
|
||||
}
|
||||
|
||||
const timer =
|
||||
(time = 1000) =>
|
||||
(_req, _res, next) =>
|
||||
setTimeout(next, time)
|
||||
|
||||
router.use(timer())
|
||||
// Небольшая задержка для имитации реальной сети
|
||||
router.use(timer(100));
|
||||
|
||||
const config = {
|
||||
examCreated: false
|
||||
}
|
||||
|
||||
router.get('/course/list', (req, res) => {
|
||||
res.send(require('../mocks/courses/list/success.json'))
|
||||
const modifiedData = readAndModifyJson('../mocks/courses/list/success.json');
|
||||
res.send(modifiedData);
|
||||
})
|
||||
|
||||
router.get('/course/:id', (req, res) => {
|
||||
@ -23,18 +90,30 @@ router.get('/course/:id', (req, res) => {
|
||||
return res.status(400).send({ success: false, error: 'Invalid course id' })
|
||||
|
||||
if (config.examCreated) {
|
||||
config.examCreated = false
|
||||
return res.send(require('../mocks/courses/by-id/with-exam.json'))
|
||||
config.examCreated = false;
|
||||
const modifiedData = readAndModifyJson('../mocks/courses/by-id/with-exam.json');
|
||||
return res.send(modifiedData);
|
||||
}
|
||||
res.send(require('../mocks/courses/by-id/success.json'))
|
||||
|
||||
const modifiedData = readAndModifyJson('../mocks/courses/by-id/success.json');
|
||||
res.send(modifiedData);
|
||||
})
|
||||
|
||||
router.get('/course/students/:courseId', (req, res) => {
|
||||
res.send(require('../mocks/courses/all-students/success.json'))
|
||||
const modifiedData = readAndModifyJson('../mocks/courses/all-students/success.json');
|
||||
res.send(modifiedData);
|
||||
})
|
||||
|
||||
router.post('/course', (req, res) => {
|
||||
res.send(require('../mocks/courses/create/success.json'))
|
||||
const baseData = readJsonFile('../mocks/courses/create/success.json');
|
||||
|
||||
// Добавляем данные из запроса
|
||||
if (baseData.body) {
|
||||
baseData.body.name = req.body.name || baseData.body.name;
|
||||
baseData.body.created = new Date().toISOString();
|
||||
}
|
||||
|
||||
res.send(baseData);
|
||||
})
|
||||
|
||||
router.post('/course/toggle-exam-with-jury/:id', (req, res) => {
|
||||
@ -43,35 +122,62 @@ router.post('/course/toggle-exam-with-jury/:id', (req, res) => {
|
||||
})
|
||||
|
||||
router.get('/lesson/list/:courseId', (req, res) => {
|
||||
res.send(require('../mocks/lessons/list/success.json'))
|
||||
const modifiedData = readAndModifyJson('../mocks/lessons/list/success.json');
|
||||
res.send(modifiedData);
|
||||
})
|
||||
|
||||
|
||||
// https://platform.bro-js.ru/jrnl-bh/api/lesson/67cf0c9f2f4241c6fc29f464/ai/generate-lessons
|
||||
router.get('/lesson/:courseId/ai/generate-lessons', timer(3000), (req, res) => {
|
||||
res.send(require('../mocks/lessons/generate/success.json'))
|
||||
const modifiedData = readAndModifyJson('../mocks/lessons/generate/success.json');
|
||||
res.send(modifiedData);
|
||||
})
|
||||
|
||||
router.post('/lesson', (req, res) => {
|
||||
res.send(require('../mocks/lessons/create/success.json'))
|
||||
const baseData = readJsonFile('../mocks/lessons/create/success.json');
|
||||
|
||||
// Добавляем данные из запроса
|
||||
if (baseData.body) {
|
||||
baseData.body.name = req.body.name || baseData.body.name;
|
||||
baseData.body.date = req.body.date || new Date().toISOString();
|
||||
baseData.body.created = new Date().toISOString();
|
||||
}
|
||||
|
||||
res.send(baseData);
|
||||
})
|
||||
|
||||
router.post('/lesson/access-code', (req, res) => {
|
||||
// Generate random students and reactions dynamically
|
||||
const dynamicData = mockGenerator.generateDynamicAccessCodeResponse();
|
||||
res.send(dynamicData);
|
||||
const modifiedData = readAndModifyJson('../mocks/lessons/access-code/create/success.json');
|
||||
|
||||
// Обновляем дату истечения через час от текущего времени
|
||||
if (modifiedData.body) {
|
||||
modifiedData.body.expires = new Date(Date.now() + 60 * 60 * 1000).toISOString();
|
||||
modifiedData.body.created = new Date().toISOString();
|
||||
}
|
||||
|
||||
res.send(modifiedData);
|
||||
})
|
||||
|
||||
router.get('/lesson/access-code/:accessCode', (req, res) => {
|
||||
// Generate dynamic data for the access code lookup
|
||||
const dynamicData = mockGenerator.generateDynamicAccessLookupResponse(req.params.accessCode);
|
||||
res.send(dynamicData);
|
||||
const modifiedData = readAndModifyJson('../mocks/lessons/access-code/get/success.json');
|
||||
|
||||
// Обновляем дату истечения через час от текущего времени
|
||||
if (modifiedData.body && modifiedData.body.accessCode) {
|
||||
modifiedData.body.accessCode.expires = new Date(Date.now() + 60 * 60 * 1000).toISOString();
|
||||
modifiedData.body.accessCode.created = new Date().toISOString();
|
||||
}
|
||||
|
||||
res.send(modifiedData);
|
||||
})
|
||||
|
||||
router.get('/lesson/:lessonId', (req, res) => {
|
||||
// Generate dynamic lesson data using the same helpers
|
||||
const dynamicData = mockGenerator.generateDynamicLessonResponse(req.params.lessonId);
|
||||
res.send(dynamicData);
|
||||
const modifiedData = readAndModifyJson('../mocks/lessons/byid/success.json');
|
||||
|
||||
// Обновляем даты
|
||||
if (modifiedData.body) {
|
||||
modifiedData.body.date = new Date().toISOString();
|
||||
modifiedData.body.created = new Date(Date.now() - 86400000).toISOString(); // Создан день назад
|
||||
}
|
||||
|
||||
res.send(modifiedData);
|
||||
})
|
||||
|
||||
router.delete('/lesson/:lessonId', (req, res) => {
|
||||
@ -103,270 +209,3 @@ router.post('/lesson/reaction/:lessonId', (req, res) => {
|
||||
});
|
||||
|
||||
module.exports = router
|
||||
|
||||
// Database of potential students
|
||||
const potentialStudents = [
|
||||
{
|
||||
"sub": "fcde3f22-d9ba-412a-a572-c59e515a290f",
|
||||
"email_verified": true,
|
||||
"name": "Мария Капитанова",
|
||||
"preferred_username": "maryaKapitan@gmail.com",
|
||||
"given_name": "Мария",
|
||||
"family_name": "Капитанова",
|
||||
"email": "maryaKapitan@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocJgIjjOFD2YUSyRF5kH4jaysE6X5p-kq0Cg0CFncfMi=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "8555885b-715c-4dee-a7c5-9563a6a05211",
|
||||
"email_verified": true,
|
||||
"name": "Евгения Жужова",
|
||||
"preferred_username": "zhuzhova@gmail.com",
|
||||
"given_name": "Евгения",
|
||||
"family_name": "Жужова",
|
||||
"email": "zhuzhova@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocJUtJBAVBm642AxoGpMDDMV8CPu3MEoLjU3hmO7oisG=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "a723b8c2-f1d7-4620-9c35-1d48c821afb7",
|
||||
"email_verified": true,
|
||||
"name": "Иван Петров",
|
||||
"preferred_username": "ivan.petrov@gmail.com",
|
||||
"given_name": "Иван",
|
||||
"family_name": "Петров",
|
||||
"email": "ivan.petrov@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocJKHmMLFXY1s0Lkj_KKf9ZEsHl-rW6FnDs4vPHUl2aF=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "e4f9d328-7b2e-49c1-b5e8-12f78c54a63d",
|
||||
"email_verified": true,
|
||||
"name": "Алексей Смирнов",
|
||||
"preferred_username": "alexey.smirnov@gmail.com",
|
||||
"given_name": "Алексей",
|
||||
"family_name": "Смирнов",
|
||||
"email": "alexey.smirnov@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocK9Nfj_jT4DLjG5hVQWS2bz8_QTZ3cHVJ6K8mD8aqWr=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "b9d7e1f5-6a3c-47d0-9bce-3c54e28a0ef2",
|
||||
"email_verified": true,
|
||||
"name": "Ольга Иванова",
|
||||
"preferred_username": "olga.ivanova@gmail.com",
|
||||
"given_name": "Ольга",
|
||||
"family_name": "Иванова",
|
||||
"email": "olga.ivanova@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocI48DY7C2ZXbMvHrEjKmY6w9JdF5PLKwEDgTR9x1jY2=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "c5e8d4f3-2b1a-4c9d-8e7f-6a5b4c3d2e1f",
|
||||
"email_verified": true,
|
||||
"name": "Дмитрий Кузнецов",
|
||||
"preferred_username": "dmitry.kuznetsov@gmail.com",
|
||||
"given_name": "Дмитрий",
|
||||
"family_name": "Кузнецов",
|
||||
"email": "dmitry.kuznetsov@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocLqZD7KjXy3B1P2VsRn6Z9tY8XMhCJ6F5gK7sD1qB3t=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "d6f9e8d7-3c2b-4a1d-9e8f-7a6b5c4d3e2f",
|
||||
"email_verified": true,
|
||||
"name": "Анна Соколова",
|
||||
"preferred_username": "anna.sokolova@gmail.com",
|
||||
"given_name": "Анна",
|
||||
"family_name": "Соколова",
|
||||
"email": "anna.sokolova@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocK3dN5mYwLjE1qFvX9pZ8rY1hJ5L2mN3oP6gR7tUb4s=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "e7f8g9h0-4d3c-2b1a-0f9e-8d7c6b5a4e3d",
|
||||
"email_verified": true,
|
||||
"name": "Сергей Новиков",
|
||||
"preferred_username": "sergey.novikov@gmail.com",
|
||||
"given_name": "Сергей",
|
||||
"family_name": "Новиков",
|
||||
"email": "sergey.novikov@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocI7P2dF3vQ5wR9jH6tN8bZ1cM4kD6yL2jN5oR8tYb5r=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "f8g9h0i1-5e4d-3c2b-1a0f-9e8d7c6b5a4e",
|
||||
"email_verified": true,
|
||||
"name": "Екатерина Морозова",
|
||||
"preferred_username": "ekaterina.morozova@gmail.com",
|
||||
"given_name": "Екатерина",
|
||||
"family_name": "Морозова",
|
||||
"email": "ekaterina.morozova@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocJ6N5oR7sD8tUb4rY1hJ5L2mN3oP6gR7tUb4s9pZ8=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "g9h0i1j2-6f5e-4d3c-2b1a-0f9e8d7c6b5a",
|
||||
"email_verified": true,
|
||||
"name": "Андрей Волков",
|
||||
"preferred_username": "andrey.volkov@gmail.com",
|
||||
"given_name": "Андрей",
|
||||
"family_name": "Волков",
|
||||
"email": "andrey.volkov@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocK4e3d2c1b0a9f8e7d6c5b4a3e2d1c0b9a8f7e6d5=s96-c"
|
||||
}
|
||||
];
|
||||
|
||||
// Available reaction types
|
||||
const reactionTypes = ['thumbs_up', 'heart', 'laugh', 'wow', 'clap'];
|
||||
|
||||
// Function to generate a random integer between min and max (inclusive)
|
||||
function getRandomInt(min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
// Function to generate a random subset of students
|
||||
function getRandomStudents() {
|
||||
const totalStudents = potentialStudents.length;
|
||||
const count = getRandomInt(1, Math.min(8, totalStudents));
|
||||
|
||||
// Shuffle array and take a subset
|
||||
const shuffled = [...potentialStudents].sort(() => 0.5 - Math.random());
|
||||
return shuffled.slice(0, count);
|
||||
}
|
||||
|
||||
// Function to generate a random reaction
|
||||
function generateReaction(studentSub, index) {
|
||||
const reactionType = reactionTypes[getRandomInt(0, reactionTypes.length - 1)];
|
||||
|
||||
return {
|
||||
"_id": `r-${Date.now()}-${index}`,
|
||||
"sub": studentSub,
|
||||
"reaction": reactionType,
|
||||
"created": new Date().toISOString()
|
||||
};
|
||||
}
|
||||
|
||||
// Function to generate random reactions for each student
|
||||
function generateReactions(students) {
|
||||
const reactions = [];
|
||||
let reactionIndex = 0;
|
||||
|
||||
students.forEach(student => {
|
||||
// Small chance (20%) of a "reaction burst" - multiple reactions in rapid succession
|
||||
const hasBurst = Math.random() < 0.2;
|
||||
|
||||
if (hasBurst) {
|
||||
// Generate a burst of 2-5 rapid reactions
|
||||
const burstCount = getRandomInt(2, 5);
|
||||
const now = Date.now();
|
||||
|
||||
for (let i = 0; i < burstCount; i++) {
|
||||
// Reactions spaced 0.5-2 seconds apart
|
||||
const timeOffset = i * getRandomInt(500, 2000);
|
||||
const reactionTime = new Date(now - timeOffset);
|
||||
|
||||
reactions.push({
|
||||
"_id": `r-burst-${now}-${i}-${reactionIndex++}`,
|
||||
"sub": student.sub,
|
||||
"reaction": reactionTypes[getRandomInt(0, reactionTypes.length - 1)],
|
||||
"created": reactionTime.toISOString()
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Each student may have 0-3 random reactions
|
||||
const reactionCount = getRandomInt(0, 3);
|
||||
|
||||
for (let i = 0; i < reactionCount; i++) {
|
||||
// Space out regular reactions by 5-30 seconds
|
||||
const timeOffset = getRandomInt(5000, 30000);
|
||||
const reactionTime = new Date(Date.now() - timeOffset);
|
||||
|
||||
reactions.push({
|
||||
"_id": `r-${Date.now()}-${reactionIndex++}`,
|
||||
"sub": student.sub,
|
||||
"reaction": reactionTypes[getRandomInt(0, reactionTypes.length - 1)],
|
||||
"created": reactionTime.toISOString()
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Sort reactions by creation time (newest first)
|
||||
return reactions.sort((a, b) => new Date(b.created) - new Date(a.created));
|
||||
}
|
||||
|
||||
// Function to generate the entire dynamic response
|
||||
function generateDynamicAccessCodeResponse() {
|
||||
// Base template from the static file
|
||||
const baseTemplate = {
|
||||
"success": true,
|
||||
"body": {
|
||||
"expires": new Date(Date.now() + 60 * 60 * 1000).toISOString(), // 1 hour from now
|
||||
"lesson": {
|
||||
"_id": "65df996c584b172772d69706",
|
||||
"name": "ВВОДНАЯ ПО JS.ПРИМЕНЕНИЕ И СПОСОБЫ ПОДКЛЮЧЕНИЯ НА СТРАНИЦЕ. LET, CONST. БАЗОВЫЕ ТИПЫ ДАННЫХ, ПРИВЕДЕНИЕ ТИПОВ. ПЕРЕМЕННЫЕ, ОБЛАСТЬ ВИДИМОСТИ ПЕРЕМЕННЫХ",
|
||||
"date": new Date().toISOString(),
|
||||
"created": new Date().toISOString(),
|
||||
"__v": 0
|
||||
},
|
||||
"_id": `access-${Date.now()}`,
|
||||
"created": new Date().toISOString(),
|
||||
"__v": 0
|
||||
}
|
||||
};
|
||||
|
||||
// Generate random students
|
||||
const students = getRandomStudents();
|
||||
baseTemplate.body.lesson.students = students;
|
||||
|
||||
// Generate random reactions for those students
|
||||
baseTemplate.body.lesson.reactions = generateReactions(students);
|
||||
|
||||
return baseTemplate;
|
||||
}
|
||||
|
||||
// Function to generate a dynamic lesson response
|
||||
function generateDynamicLessonResponse(lessonId) {
|
||||
// Base template for lesson response
|
||||
const baseTemplate = {
|
||||
"success": true,
|
||||
"body": {
|
||||
"_id": lessonId || "65df996c584b172772d69706",
|
||||
"name": "ВВОДНАЯ ПО JS.ПРИМЕНЕНИЕ И СПОСОБЫ ПОДКЛЮЧЕНИЯ НА СТРАНИЦЕ. LET, CONST. БАЗОВЫЕ ТИПЫ ДАННЫХ, ПРИВЕДЕНИЕ ТИПОВ. ПЕРЕМЕННЫЕ, ОБЛАСТЬ ВИДИМОСТИ ПЕРЕМЕННЫХ",
|
||||
"date": new Date().toISOString(),
|
||||
"created": new Date().toISOString(),
|
||||
"__v": 0
|
||||
}
|
||||
};
|
||||
|
||||
// Generate random students
|
||||
const students = getRandomStudents();
|
||||
baseTemplate.body.students = students;
|
||||
|
||||
// Generate random reactions for those students
|
||||
baseTemplate.body.reactions = generateReactions(students);
|
||||
|
||||
return baseTemplate;
|
||||
}
|
||||
|
||||
// Function to generate a dynamic access code lookup response
|
||||
function generateDynamicAccessLookupResponse(accessCode) {
|
||||
// Generate a lesson with students and reactions
|
||||
const lessonData = generateDynamicLessonResponse();
|
||||
|
||||
// Create a mock user
|
||||
const mockUser = {
|
||||
sub: `user-${Date.now()}`,
|
||||
email_verified: true,
|
||||
name: "Текущий Пользователь",
|
||||
preferred_username: "current.user@example.com",
|
||||
email: "current.user@example.com"
|
||||
};
|
||||
|
||||
// Combine into the expected format
|
||||
return {
|
||||
"success": true,
|
||||
"body": {
|
||||
"user": mockUser,
|
||||
"accessCode": {
|
||||
"expires": new Date(Date.now() + 60 * 60 * 1000).toISOString(),
|
||||
"lesson": lessonData.body,
|
||||
"_id": accessCode || `access-${Date.now()}`,
|
||||
"created": new Date().toISOString(),
|
||||
"__v": 0
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,264 +0,0 @@
|
||||
// Database of potential students
|
||||
const potentialStudents = [
|
||||
{
|
||||
"sub": "fcde3f22-d9ba-412a-a572-c59e515a290f",
|
||||
"email_verified": true,
|
||||
"name": "Мария Капитанова",
|
||||
"preferred_username": "maryaKapitan@gmail.com",
|
||||
"given_name": "Мария",
|
||||
"family_name": "Капитанова",
|
||||
"email": "maryaKapitan@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocJgIjjOFD2YUSyRF5kH4jaysE6X5p-kq0Cg0CFncfMi=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "8555885b-715c-4dee-a7c5-9563a6a05211",
|
||||
"email_verified": true,
|
||||
"name": "Евгения Жужова",
|
||||
"preferred_username": "zhuzhova@gmail.com",
|
||||
"given_name": "Евгения",
|
||||
"family_name": "Жужова",
|
||||
"email": "zhuzhova@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocJUtJBAVBm642AxoGpMDDMV8CPu3MEoLjU3hmO7oisG=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "a723b8c2-f1d7-4620-9c35-1d48c821afb7",
|
||||
"email_verified": true,
|
||||
"name": "Иван Петров",
|
||||
"preferred_username": "ivan.petrov@gmail.com",
|
||||
"given_name": "Иван",
|
||||
"family_name": "Петров",
|
||||
"email": "ivan.petrov@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocJKHmMLFXY1s0Lkj_KKf9ZEsHl-rW6FnDs4vPHUl2aF=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "e4f9d328-7b2e-49c1-b5e8-12f78c54a63d",
|
||||
"email_verified": true,
|
||||
"name": "Алексей Смирнов",
|
||||
"preferred_username": "alexey.smirnov@gmail.com",
|
||||
"given_name": "Алексей",
|
||||
"family_name": "Смирнов",
|
||||
"email": "alexey.smirnov@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocK9Nfj_jT4DLjG5hVQWS2bz8_QTZ3cHVJ6K8mD8aqWr=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "b9d7e1f5-6a3c-47d0-9bce-3c54e28a0ef2",
|
||||
"email_verified": true,
|
||||
"name": "Ольга Иванова",
|
||||
"preferred_username": "olga.ivanova@gmail.com",
|
||||
"given_name": "Ольга",
|
||||
"family_name": "Иванова",
|
||||
"email": "olga.ivanova@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocI48DY7C2ZXbMvHrEjKmY6w9JdF5PLKwEDgTR9x1jY2=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "c5e8d4f3-2b1a-4c9d-8e7f-6a5b4c3d2e1f",
|
||||
"email_verified": true,
|
||||
"name": "Дмитрий Кузнецов",
|
||||
"preferred_username": "dmitry.kuznetsov@gmail.com",
|
||||
"given_name": "Дмитрий",
|
||||
"family_name": "Кузнецов",
|
||||
"email": "dmitry.kuznetsov@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocLqZD7KjXy3B1P2VsRn6Z9tY8XMhCJ6F5gK7sD1qB3t=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "d6f9e8d7-3c2b-4a1d-9e8f-7a6b5c4d3e2f",
|
||||
"email_verified": true,
|
||||
"name": "Анна Соколова",
|
||||
"preferred_username": "anna.sokolova@gmail.com",
|
||||
"given_name": "Анна",
|
||||
"family_name": "Соколова",
|
||||
"email": "anna.sokolova@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocK3dN5mYwLjE1qFvX9pZ8rY1hJ5L2mN3oP6gR7tUb4s=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "e7f8g9h0-4d3c-2b1a-0f9e-8d7c6b5a4e3d",
|
||||
"email_verified": true,
|
||||
"name": "Сергей Новиков",
|
||||
"preferred_username": "sergey.novikov@gmail.com",
|
||||
"given_name": "Сергей",
|
||||
"family_name": "Новиков",
|
||||
"email": "sergey.novikov@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocI7P2dF3vQ5wR9jH6tN8bZ1cM4kD6yL2jN5oR8tYb5r=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "f8g9h0i1-5e4d-3c2b-1a0f-9e8d7c6b5a4e",
|
||||
"email_verified": true,
|
||||
"name": "Екатерина Морозова",
|
||||
"preferred_username": "ekaterina.morozova@gmail.com",
|
||||
"given_name": "Екатерина",
|
||||
"family_name": "Морозова",
|
||||
"email": "ekaterina.morozova@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocJ6N5oR7sD8tUb4rY1hJ5L2mN3oP6gR7tUb4s9pZ8=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "g9h0i1j2-6f5e-4d3c-2b1a-0f9e8d7c6b5a",
|
||||
"email_verified": true,
|
||||
"name": "Андрей Волков",
|
||||
"preferred_username": "andrey.volkov@gmail.com",
|
||||
"given_name": "Андрей",
|
||||
"family_name": "Волков",
|
||||
"email": "andrey.volkov@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocK4e3d2c1b0a9f8e7d6c5b4a3e2d1c0b9a8f7e6d5=s96-c"
|
||||
}
|
||||
];
|
||||
|
||||
// Available reaction types
|
||||
const reactionTypes = ['thumbs_up', 'heart', 'laugh', 'wow', 'clap'];
|
||||
|
||||
// Function to generate a random integer between min and max (inclusive)
|
||||
function getRandomInt(min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
// Function to generate a random subset of students
|
||||
function getRandomStudents() {
|
||||
const totalStudents = potentialStudents.length;
|
||||
const count = getRandomInt(1, Math.min(8, totalStudents));
|
||||
|
||||
// Shuffle array and take a subset
|
||||
const shuffled = [...potentialStudents].sort(() => 0.5 - Math.random());
|
||||
return shuffled.slice(0, count);
|
||||
}
|
||||
|
||||
// Function to generate random reactions for each student
|
||||
function generateReactions(students) {
|
||||
const reactions = [];
|
||||
let reactionIndex = 0;
|
||||
|
||||
students.forEach(student => {
|
||||
// Small chance (20%) of a "reaction burst" - multiple reactions in rapid succession
|
||||
const hasBurst = Math.random() < 0.2;
|
||||
|
||||
if (hasBurst) {
|
||||
// Generate a burst of 2-5 rapid reactions
|
||||
const burstCount = getRandomInt(2, 5);
|
||||
const now = Date.now();
|
||||
|
||||
for (let i = 0; i < burstCount; i++) {
|
||||
// Reactions spaced 0.5-2 seconds apart
|
||||
const timeOffset = i * getRandomInt(500, 2000);
|
||||
const reactionTime = new Date(now - timeOffset);
|
||||
|
||||
reactions.push({
|
||||
"_id": `r-burst-${now}-${i}-${reactionIndex++}`,
|
||||
"sub": student.sub,
|
||||
"reaction": reactionTypes[getRandomInt(0, reactionTypes.length - 1)],
|
||||
"created": reactionTime.toISOString()
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Each student may have 0-3 random reactions
|
||||
const reactionCount = getRandomInt(0, 3);
|
||||
|
||||
for (let i = 0; i < reactionCount; i++) {
|
||||
// Space out regular reactions by 5-30 seconds
|
||||
const timeOffset = getRandomInt(5000, 30000);
|
||||
const reactionTime = new Date(Date.now() - timeOffset);
|
||||
|
||||
reactions.push({
|
||||
"_id": `r-${Date.now()}-${reactionIndex++}`,
|
||||
"sub": student.sub,
|
||||
"reaction": reactionTypes[getRandomInt(0, reactionTypes.length - 1)],
|
||||
"created": reactionTime.toISOString()
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Sort reactions by creation time (newest first)
|
||||
return reactions.sort((a, b) => new Date(b.created) - new Date(a.created));
|
||||
}
|
||||
|
||||
// Function to generate the entire dynamic response
|
||||
function generateDynamicAccessCodeResponse() {
|
||||
// Base template from the static file
|
||||
const baseTemplate = {
|
||||
"success": true,
|
||||
"body": {
|
||||
"expires": new Date(Date.now() + 60 * 60 * 1000).toISOString(), // 1 hour from now
|
||||
"lesson": {
|
||||
"_id": "65df996c584b172772d69706",
|
||||
"name": "ВВОДНАЯ ПО JS.ПРИМЕНЕНИЕ И СПОСОБЫ ПОДКЛЮЧЕНИЯ НА СТРАНИЦЕ. LET, CONST. БАЗОВЫЕ ТИПЫ ДАННЫХ, ПРИВЕДЕНИЕ ТИПОВ. ПЕРЕМЕННЫЕ, ОБЛАСТЬ ВИДИМОСТИ ПЕРЕМЕННЫХ",
|
||||
"date": new Date().toISOString(),
|
||||
"created": new Date().toISOString(),
|
||||
"__v": 0
|
||||
},
|
||||
"_id": `access-${Date.now()}`,
|
||||
"created": new Date().toISOString(),
|
||||
"__v": 0
|
||||
}
|
||||
};
|
||||
|
||||
// Generate random students
|
||||
const students = getRandomStudents();
|
||||
baseTemplate.body.lesson.students = students;
|
||||
|
||||
// Generate random reactions for those students
|
||||
baseTemplate.body.lesson.reactions = generateReactions(students);
|
||||
|
||||
return baseTemplate;
|
||||
}
|
||||
|
||||
// Function to generate a dynamic lesson response
|
||||
function generateDynamicLessonResponse(lessonId) {
|
||||
// Base template for lesson response
|
||||
const baseTemplate = {
|
||||
"success": true,
|
||||
"body": {
|
||||
"_id": lessonId || "65df996c584b172772d69706",
|
||||
"name": "ВВОДНАЯ ПО JS.ПРИМЕНЕНИЕ И СПОСОБЫ ПОДКЛЮЧЕНИЯ НА СТРАНИЦЕ. LET, CONST. БАЗОВЫЕ ТИПЫ ДАННЫХ, ПРИВЕДЕНИЕ ТИПОВ. ПЕРЕМЕННЫЕ, ОБЛАСТЬ ВИДИМОСТИ ПЕРЕМЕННЫХ",
|
||||
"date": new Date().toISOString(),
|
||||
"created": new Date().toISOString(),
|
||||
"__v": 0
|
||||
}
|
||||
};
|
||||
|
||||
// Generate random students
|
||||
const students = getRandomStudents();
|
||||
baseTemplate.body.students = students;
|
||||
|
||||
// Generate random reactions for those students
|
||||
baseTemplate.body.reactions = generateReactions(students);
|
||||
|
||||
return baseTemplate;
|
||||
}
|
||||
|
||||
// Function to generate a dynamic access code lookup response
|
||||
function generateDynamicAccessLookupResponse(accessCode) {
|
||||
// Generate a lesson with students and reactions
|
||||
const lessonData = generateDynamicLessonResponse();
|
||||
|
||||
// Create a mock user
|
||||
const mockUser = {
|
||||
sub: `user-${Date.now()}`,
|
||||
email_verified: true,
|
||||
name: "Текущий Пользователь",
|
||||
preferred_username: "current.user@example.com",
|
||||
email: "current.user@example.com"
|
||||
};
|
||||
|
||||
// Combine into the expected format
|
||||
return {
|
||||
"success": true,
|
||||
"body": {
|
||||
"user": mockUser,
|
||||
"accessCode": {
|
||||
"expires": new Date(Date.now() + 60 * 60 * 1000).toISOString(),
|
||||
"lesson": lessonData.body,
|
||||
"_id": accessCode || `access-${Date.now()}`,
|
||||
"created": new Date().toISOString(),
|
||||
"__v": 0
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Export all the necessary functions
|
||||
module.exports = {
|
||||
getRandomStudents,
|
||||
generateReactions,
|
||||
generateDynamicAccessCodeResponse,
|
||||
generateDynamicLessonResponse,
|
||||
generateDynamicAccessLookupResponse,
|
||||
reactionTypes
|
||||
};
|
@ -1,100 +0,0 @@
|
||||
{
|
||||
"success": true,
|
||||
"body": {
|
||||
"expires": "2024-03-01T07:52:16.374Z",
|
||||
"lesson": {
|
||||
"_id": "65df996c584b172772d69706",
|
||||
"name": "ВВОДНАЯ ПО JS.ПРИМЕНЕНИЕ И СПОСОБЫ ПОДКЛЮЧЕНИЯ НА СТРАНИЦЕ. LET, CONST. БАЗОВЫЕ ТИПЫ ДАННЫХ, ПРИВЕДЕНИЕ ТИПОВ. ПЕРЕМЕННЫЕ, ОБЛАСТЬ ВИДИМОСТИ ПЕРЕМЕННЫХ",
|
||||
"students": [
|
||||
{
|
||||
"sub": "fcde3f22-d9ba-412a-a572-c59e515a290f",
|
||||
"email_verified": true,
|
||||
"name": "Мария Капитанова",
|
||||
"preferred_username": "maryaKapitan@gmail.com",
|
||||
"given_name": "Мария",
|
||||
"family_name": "Капитанова",
|
||||
"email": "maryaKapitan@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocJgIjjOFD2YUSyRF5kH4jaysE6X5p-kq0Cg0CFncfMi=s96-c"
|
||||
},
|
||||
{
|
||||
"sub": "8555885b-715c-4dee-a7c5-9563a6a05211",
|
||||
"email_verified": true,
|
||||
"name": "Евгения Жужова",
|
||||
"preferred_username": "zhuzhova@gmail.com",
|
||||
"given_name": "Евгения",
|
||||
"family_name": "Жужова",
|
||||
"email": "zhuzhova@gmail.com",
|
||||
"picture": "https://lh3.googleusercontent.com/a/ACg8ocJUtJBAVBm642AxoGpMDDMV8CPu3MEoLjU3hmO7oisG=s96-c"
|
||||
}
|
||||
],
|
||||
"reactions": [
|
||||
{
|
||||
"_id": "r1-rapid-001",
|
||||
"sub": "fcde3f22-d9ba-412a-a572-c59e515a290f",
|
||||
"reaction": "thumbs_up",
|
||||
"created": "2024-03-08T10:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"_id": "r1-rapid-002",
|
||||
"sub": "fcde3f22-d9ba-412a-a572-c59e515a290f",
|
||||
"reaction": "heart",
|
||||
"created": "2024-03-08T10:00:01.500Z"
|
||||
},
|
||||
{
|
||||
"_id": "r1-rapid-003",
|
||||
"sub": "fcde3f22-d9ba-412a-a572-c59e515a290f",
|
||||
"reaction": "laugh",
|
||||
"created": "2024-03-08T10:00:02.800Z"
|
||||
},
|
||||
{
|
||||
"_id": "r1-rapid-004",
|
||||
"sub": "fcde3f22-d9ba-412a-a572-c59e515a290f",
|
||||
"reaction": "wow",
|
||||
"created": "2024-03-08T10:00:04.200Z"
|
||||
},
|
||||
{
|
||||
"_id": "r1-rapid-005",
|
||||
"sub": "fcde3f22-d9ba-412a-a572-c59e515a290f",
|
||||
"reaction": "clap",
|
||||
"created": "2024-03-08T10:00:05.500Z"
|
||||
},
|
||||
{
|
||||
"_id": "r2-rapid-001",
|
||||
"sub": "8555885b-715c-4dee-a7c5-9563a6a05211",
|
||||
"reaction": "thumbs_up",
|
||||
"created": "2024-03-08T10:01:00.000Z"
|
||||
},
|
||||
{
|
||||
"_id": "r2-rapid-002",
|
||||
"sub": "8555885b-715c-4dee-a7c5-9563a6a05211",
|
||||
"reaction": "heart",
|
||||
"created": "2024-03-08T10:01:01.200Z"
|
||||
},
|
||||
{
|
||||
"_id": "r2-rapid-003",
|
||||
"sub": "8555885b-715c-4dee-a7c5-9563a6a05211",
|
||||
"reaction": "wow",
|
||||
"created": "2024-03-08T10:01:02.300Z"
|
||||
},
|
||||
{
|
||||
"_id": "r2-rapid-004",
|
||||
"sub": "8555885b-715c-4dee-a7c5-9563a6a05211",
|
||||
"reaction": "laugh",
|
||||
"created": "2024-03-08T10:01:04.100Z"
|
||||
},
|
||||
{
|
||||
"_id": "r2-rapid-005",
|
||||
"sub": "8555885b-715c-4dee-a7c5-9563a6a05211",
|
||||
"reaction": "clap",
|
||||
"created": "2024-03-08T10:01:05.300Z"
|
||||
}
|
||||
],
|
||||
"date": "2024-02-28T20:37:00.057Z",
|
||||
"created": "2024-02-28T20:37:00.057Z",
|
||||
"__v": 0
|
||||
},
|
||||
"_id": "65e18926584b172772d69722",
|
||||
"created": "2024-03-01T07:52:06.375Z",
|
||||
"__v": 0
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user