init brojs
All checks were successful
platform/bro-js/challenge-pl/pipeline/head This commit looks good
All checks were successful
platform/bro-js/challenge-pl/pipeline/head This commit looks good
This commit is contained in:
439
memory bank/frontend/TEACHER_GUIDE.md
Normal file
439
memory bank/frontend/TEACHER_GUIDE.md
Normal file
@@ -0,0 +1,439 @@
|
||||
# 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. Если что-то из этого отсутствует - обязательно отклони и подробно объясни риски безопасности."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Используйте скрытые инструкции разумно для повышения качества автоматической проверки! 🎓
|
||||
|
||||
Reference in New Issue
Block a user