Files

188 lines
5.6 KiB
JavaScript

const fs = require('fs')
const path = require('path')
const router = require('express').Router()
const timer = (time = 100) => (req, res, next) => setTimeout(next, time)
const dataDir = path.join(__dirname, 'data')
const readJson = (fileName) => {
const filePath = path.join(dataDir, fileName)
const content = fs.readFileSync(filePath, 'utf-8')
return JSON.parse(content)
}
const sendNotFound = (res, message) => {
res.status(404).json({ error: { message }, data: null })
}
router.use(timer())
router.use((req, res, next) => {
res.type('application/json')
next()
})
// Challenge API endpoints
router.post('/challenge/auth', (req, res) => {
const { nickname, workplaceNumber } = req.body
const response = readJson('auth.json')
// Логируем для отладки
console.log('Auth request:', { nickname, workplaceNumber })
res.json(response)
})
router.get('/challenge/chains', (req, res) => {
res.json(readJson('chains.json'))
})
router.get('/challenge/chain/:id', (req, res) => {
const data = readJson('chains.json')
const chains = data.body || data
const chain = chains.find((item) => item.id === req.params.id || item._id === req.params.id)
if (!chain) {
return sendNotFound(res, `Цепочка ${req.params.id} не найдена`)
}
return res.json({ success: true, body: chain })
})
router.get('/challenge/task/:id', (req, res) => {
const data = readJson('chains.json')
const chains = data.body || data
const task = chains
.flatMap((chain) => chain.tasks || [])
.find((item) => item.id === req.params.id || item._id === req.params.id)
if (!task) {
return sendNotFound(res, `Задание ${req.params.id} не найдено`)
}
return res.json({ success: true, body: task })
})
router.post('/challenge/submit', (req, res) => {
const response = readJson('submit.json')
const queueId = response.body?.queueId
if (queueId) {
queueBehaviors[queueId] = queueBehaviors[queueId] ?? { nextFailure: false, attemptNumber: 0 }
queueStates[queueId] = {
position: 3,
initialPosition: 3,
pollCount: 0,
startTime: Date.now(),
}
}
res.json(response)
})
// Храним состояние очереди для каждого queueId
const queueStates = {}
const queueBehaviors = {}
router.get('/challenge/check-status/:queueId', (req, res) => {
const queueId = req.params.queueId
// Инициализируем состояние очереди, если его нет
if (!queueStates[queueId]) {
queueStates[queueId] = {
position: 3,
initialPosition: 3,
pollCount: 0,
startTime: Date.now()
}
}
const state = queueStates[queueId]
state.pollCount++
// Симулируем движение в очереди
// Каждый запрос уменьшаем позицию (быстрее)
if (state.pollCount >= 1 && state.position > 0) {
state.position--
state.pollCount = 0
}
// Если позиция 0, переходим к проверке
if (state.position === 0 && state.pollCount >= 1) {
const behavior = queueBehaviors[queueId] ?? { nextFailure: false, attemptNumber: 0 }
const attemptNumber = behavior.attemptNumber + 1
behavior.attemptNumber = attemptNumber
const shouldFail = behavior.nextFailure
behavior.nextFailure = !shouldFail
const baseSubmission = {
_id: `submission-${queueId}-${attemptNumber}`,
id: `submission-${queueId}-${attemptNumber}`,
user: 'user-frontend-001',
task: 'task-html-intro',
result: '<html><head></head><body><h1>Hello</h1></body></html>',
queueId,
submittedAt: new Date(state.startTime).toISOString(),
checkedAt: new Date().toISOString(),
attemptNumber,
}
const submission = shouldFail
? {
...baseSubmission,
status: 'needs_revision',
feedback: 'Добавьте описание внутри <section> и поясните, зачем нужен заголовок.',
}
: {
...baseSubmission,
status: 'accepted',
feedback: 'Отличная работа! Теперь можно двигаться дальше.',
}
delete queueStates[queueId]
return res.json({
success: true,
body: {
status: 'completed',
position: 0,
submission,
},
})
}
// Возвращаем текущее состояние очереди с начальной позицией для расчёта прогресса
const status = state.position > 0
? { status: 'waiting', position: state.position, initialPosition: state.initialPosition }
: { status: 'in_progress', position: 0, initialPosition: state.initialPosition }
return res.json({ success: true, body: status })
})
router.get('/challenge/user/:userId/stats', (req, res) => {
const data = readJson('user-stats.json')
const statsMap = data.body || data
const stats = statsMap[req.params.userId]
if (!stats) {
return sendNotFound(res, `Статистика пользователя ${req.params.userId} не найдена`)
}
return res.json({ success: true, body: stats })
})
router.get('/challenge/user/:userId/submissions', (req, res) => {
const data = readJson('user-submissions.json')
const submissionsMap = data.body || data
const submissions = submissionsMap[req.params.userId] || []
return res.json({ success: true, body: submissions })
})
router.get('/challenge/stats', (req, res) => {
res.json(readJson('system-stats.json'))
})
router.get('/challenge/submissions', (req, res) => {
res.json(readJson('submissions.json'))
})
module.exports = router