Primakov Alexandr Alexandrovich 3a65307fd0
All checks were successful
platform/bro-js/challenge-pl/pipeline/head This commit looks good
init brojs
2025-11-02 17:44:37 +03:00

440 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Challenge Service - Руководство для преподавателей
Специальное руководство для пользователей с ролью `teacher` в Keycloak.
## Требования
Для создания и редактирования заданий и цепочек необходимо:
1. Быть авторизованным через Keycloak
2. Иметь роль `teacher` в клиенте `journal`
## Особенности для преподавателей
### 1. Скрытые инструкции для LLM
При создании заданий вы можете добавить **скрытые инструкции** (`hiddenInstructions`), которые:
- ✅ Видны только преподавателям
- ✅ Передаются в LLM при проверке
-Не видны студентам
-Не отображаются в интерфейсе студента
#### Примеры использования
**Пример 1: Контроль сложности**
```json
{
"title": "Реализовать сортировку",
"description": "Напишите функцию для сортировки массива чисел",
"hiddenInstructions": "Проверь, чтобы сложность алгоритма была не хуже O(n log n). Не принимай bubble sort или простые O(n²) решения."
}
```
**Пример 2: Специфичные требования**
```json
{
"title": "REST API endpoint",
"description": "Создайте endpoint для получения списка пользователей",
"hiddenInstructions": "Обязательно должна быть пагинация, обработка ошибок и валидация параметров. Если чего-то не хватает - укажи в feedback."
}
```
**Пример 3: Стиль кода**
```json
{
"title": "Компонент React",
"description": "Создайте компонент для отображения карточки товара",
"hiddenInstructions": "Проверь использование TypeScript, правильное применение хуков, и соблюдение best practices React. Код должен быть чистым и читаемым."
}
```
**Пример 4: Тонкая настройка проверки**
```json
{
"title": "SQL запрос",
"description": "Напишите запрос для выборки активных пользователей",
"hiddenInstructions": "Даже если запрос работает, но неоптимален (например, использует SELECT *), укажи на это в feedback и попроси оптимизировать."
}
```
### 2. Создание задания через API
#### С помощью Keycloak токена
```typescript
// Получение токена (пример для frontend)
const keycloakToken = keycloak.token // из keycloak-js
// Создание задания
async function createTask(title: string, description: string, hiddenInstructions: string) {
const response = await fetch('http://localhost:8082/api/challenge/task', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${keycloakToken}`
},
body: JSON.stringify({
title,
description,
hiddenInstructions
})
})
return response.json()
}
```
#### С помощью curl
```bash
# Получить токен от Keycloak
TOKEN="your_keycloak_token"
# Создать задание
curl -X POST http://localhost:8082/api/challenge/task \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"title": "Написать функцию",
"description": "# Задание\n\nНапишите функцию для...",
"hiddenInstructions": "Проверь производительность и обработку ошибок"
}'
```
### 3. UI компоненты для преподавателей
#### TaskForm с скрытыми инструкциями
```typescript
import { useState } from 'react'
import ReactMarkdown from 'react-markdown'
interface TaskFormProps {
onSubmit: (task: { title: string; description: string; hiddenInstructions: string }) => void
}
export function TeacherTaskForm({ onSubmit }: TaskFormProps) {
const [title, setTitle] = useState('')
const [description, setDescription] = useState('')
const [hiddenInstructions, setHiddenInstructions] = useState('')
const [showPreview, setShowPreview] = useState(false)
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
onSubmit({ title, description, hiddenInstructions })
}
return (
<form onSubmit={handleSubmit}>
<div className="form-group">
<label>Заголовок задания</label>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
required
maxLength={255}
/>
</div>
<div className="form-group">
<label>Описание (Markdown)</label>
<div className="tabs">
<button type="button" onClick={() => setShowPreview(false)}>Редактор</button>
<button type="button" onClick={() => setShowPreview(true)}>Превью</button>
</div>
{showPreview ? (
<div className="markdown-preview">
<ReactMarkdown>{description}</ReactMarkdown>
</div>
) : (
<textarea
value={description}
onChange={(e) => setDescription(e.target.value)}
required
rows={15}
placeholder="# Заголовок\n\nОписание задания..."
/>
)}
</div>
<div className="form-group highlight">
<label>
🔒 Скрытые инструкции для LLM
<span className="info-tooltip">
Эти инструкции увидит только LLM при проверке.
Студенты их не увидят.
</span>
</label>
<textarea
value={hiddenInstructions}
onChange={(e) => setHiddenInstructions(e.target.value)}
rows={5}
placeholder="Дополнительные требования к проверке..."
/>
</div>
<button type="submit">Создать задание</button>
</form>
)
}
```
#### TaskCard с индикацией скрытых инструкций
```typescript
interface TaskCardProps {
task: ChallengeTask
isTeacher: boolean
}
export function TaskCard({ task, isTeacher }: TaskCardProps) {
return (
<div className="task-card">
<h3>{task.title}</h3>
<div className="task-description">
<ReactMarkdown>{task.description}</ReactMarkdown>
</div>
{isTeacher && task.hiddenInstructions && (
<div className="hidden-instructions-indicator">
<span className="lock-icon">🔒</span>
<span>Содержит скрытые инструкции для LLM</span>
</div>
)}
{isTeacher && task.creator && (
<div className="task-meta">
<span>Создал: {task.creator.preferred_username}</span>
</div>
)}
</div>
)
}
```
### 4. Настройка Keycloak
#### Добавление роли teacher
1. Войдите в админ панель Keycloak
2. Выберите realm (например, `bro-js` или `itpark`)
3. Перейдите в **Clients**`journal`
4. Перейдите на вкладку **Roles**
5. Добавьте роль `teacher`, если её нет
6. Назначьте роль нужным пользователям через **Users** → [пользователь] → **Role Mappings**
### 5. Best Practices
#### ✅ Хорошие скрытые инструкции
```
"Проверь, что функция обрабатывает edge cases: пустой массив,
один элемент, отрицательные числа. Если что-то упущено - укажи."
```
```
"Код должен следовать принципу DRY. Если есть дублирование -
отправь на доработку с рекомендацией."
```
```
"Обязательна обработка ошибок. Если try-catch отсутствует или
неполный - укажи в feedback."
```
#### ❌ Плохие скрытые инструкции
```
"Проверь" // Слишком общее
```
```
"Это задание должно быть правильным" // Бессмысленное
```
```
"Не принимай, если не идеально" // Слишком строгое, непонятное
```
### 6. Просмотр скрытых инструкций
Скрытые инструкции доступны только при запросе с токеном `teacher`:
```typescript
// Получить задание (с токеном teacher)
async function getTaskAsTeacher(taskId: string) {
const response = await fetch(`http://localhost:8082/api/challenge/task/${taskId}`, {
headers: {
'Authorization': `Bearer ${keycloakToken}`
}
})
const { data } = await response.json()
// data.hiddenInstructions будет доступно
console.log('Hidden instructions:', data.hiddenInstructions)
}
// Получить задание (без токена или с обычным пользователем)
async function getTaskAsStudent(taskId: string) {
const response = await fetch(`http://localhost:8082/api/challenge/task/${taskId}`)
const { data } = await response.json()
// data.hiddenInstructions будет undefined
console.log('Hidden instructions:', data.hiddenInstructions) // undefined
}
```
### 7. Редактирование существующих заданий
```typescript
async function updateTask(
taskId: string,
updates: {
title?: string
description?: string
hiddenInstructions?: string
}
) {
const response = await fetch(`http://localhost:8082/api/challenge/task/${taskId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${keycloakToken}`
},
body: JSON.stringify(updates)
})
return response.json()
}
// Пример использования
updateTask('507f1f77bcf86cd799439011', {
hiddenInstructions: 'Обновленные требования к проверке'
})
```
### 8. Мониторинг эффективности инструкций
Отслеживайте, как скрытые инструкции влияют на результаты:
```typescript
interface InstructionEffectiveness {
taskId: string
taskTitle: string
hasHiddenInstructions: boolean
acceptanceRate: number // % принятых с первой попытки
averageFeedbackQuality: number // оценка качества feedback
}
// Анализ эффективности
async function analyzeInstructionsEffectiveness() {
const tasks = await fetchAllTasks()
const stats = await fetchSystemStats()
return tasks.map(task => ({
taskId: task.id,
taskTitle: task.title,
hasHiddenInstructions: !!task.hiddenInstructions,
acceptanceRate: calculateAcceptanceRate(task.id, stats),
averageFeedbackQuality: calculateFeedbackQuality(task.id, stats)
}))
}
```
### 9. Шаблоны скрытых инструкций
#### Для программирования
```
Проверь:
1. Корректность алгоритма
2. Обработку edge cases
3. Сложность алгоритма (должна быть оптимальной)
4. Читаемость кода
5. Наличие комментариев в сложных местах
```
#### Для веб-разработки
```
Проверь:
1. Соответствие HTML семантике
2. Доступность (accessibility)
3. Responsive design
4. Производительность
5. Best practices для используемого фреймворка
```
#### Для баз данных
```
Проверь:
1. Правильность SQL синтаксиса
2. Оптимальность запроса
3. Использование индексов
4. Защиту от SQL injection
5. Читаемость запроса
```
### 10. FAQ
**Q: Что если я не добавлю скрытые инструкции?**
A: Задание будет работать нормально. LLM проверит решение на основе только видимого описания.
**Q: Могут ли студенты как-то увидеть скрытые инструкции?**
A: Нет, сервер автоматически фильтрует это поле при запросах без роли teacher.
**Q: Можно ли изменить скрытые инструкции после создания?**
A: Да, используйте PUT /api/challenge/task/:taskId с новым значением hiddenInstructions.
**Q: Влияют ли скрытые инструкции на все проверки?**
A: Да, каждая проверка использует актуальные hiddenInstructions из задания.
**Q: Можно ли использовать Markdown в скрытых инструкциях?**
A: Можно, но это обычный текст. Markdown не рендерится, так как инструкции идут прямо в LLM.
---
## Примеры реальных сценариев
### Сценарий 1: Курс по алгоритмам
```json
{
"title": "Реализовать бинарный поиск",
"description": "Напишите функцию binarySearch(arr, target), которая ищет элемент в отсортированном массиве",
"hiddenInstructions": "Проверь сложность - должна быть O(log n). Если используется линейный поиск или неоптимальный алгоритм - отклони с объяснением. Также проверь обработку случаев, когда элемент не найден."
}
```
### Сценарий 2: Курс по React
```json
{
"title": "Форма регистрации",
"description": "Создайте компонент формы регистрации с полями email и пароль",
"hiddenInstructions": "Обязательна валидация на стороне клиента, использование controlled components, и правильное управление state. Если используются uncontrolled components или нет валидации - отправь на доработку."
}
```
### Сценарий 3: Курс по безопасности
```json
{
"title": "Безопасный API endpoint",
"description": "Создайте endpoint для аутентификации пользователя",
"hiddenInstructions": "Критически важно: пароли должны хешироваться, должна быть защита от SQL injection, rate limiting. Если что-то из этого отсутствует - обязательно отклони и подробно объясни риски безопасности."
}
```
---
Используйте скрытые инструкции разумно для повышения качества автоматической проверки! 🎓