173 lines
7.5 KiB
Python
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.

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.utils.timezone import now
from .models import CareerTestResult
from .serializers import CareerTestSubmitSerializer, CareerTestResultSerializer
# ===== ЛОГИКА РАСЧЁТА ПРОФИЛЯ =====
EGE_SETS = {
'R': {
'title': 'Техника/производство/агро/транспорт',
'ege': [
'📐 Рус + Профмат + Физика (технические специальности)',
'🌾 Рус + Биология + Химия (агрономия/ветеринария)',
'🚗 Рус + Профмат + Информатика (автотранспорт)',
],
'desc': 'Инженерия, строительство, транспорт, агрономия, техника.'
},
'I': {
'title': 'IT/инженерия/наука/анализ',
'ege': [
'💻 Рус + Профмат + Информатика (IT/программирование)',
'🔬 Рус + Профмат + Физика (инженерия/физика)',
'📊 Рус + Профмат + Химия (технологии/материаловедение)',
],
'desc': 'Программирование, инженерия, физика, математика, исследования.'
},
'A': {
'title': 'Дизайн/медиа/креатив',
'ege': [
'🎨 Рус + Обществознание + Литература (журналистика/дизайн)',
'📱 Рус + Профмат + Информатика (веб-дизайн/UI/UX)',
'📸 Рус + История + Иностранный (медиа/реклама)',
],
'desc': 'Дизайн, журналистика, реклама, медиа, творческие индустрии.'
},
'S': {
'title': 'Помощь людям/педагогика/медицина',
'ege': [
'👩‍⚕️ Рус + Биология + Химия (медицина/биология)',
'👨‍🏫 Рус + Обществознание + История (педагогика/психология)',
'🧠 Рус + Обществознание + Биология (социология/социальная работа)',
],
'desc': 'Медицина, педагогика, психология, социальная работа.'
},
'E': {
'title': 'Управление/бизнес/право',
'ege': [
'⚖️ Рус + Обществознание + История (юриспруденция/госуправление)',
'💼 Рус + Обществознание + Профмат (экономика/менеджмент)',
'📈 Рус + Обществознание + Иностранный (международные отношения)',
],
'desc': 'Юриспруденция, экономика, менеджмент, государственное управление.'
},
'C': {
'title': 'Учёт/логистика/документы',
'ege': [
'📋 Рус + Обществознание + Профмат (бухучёт/логистика)',
'📊 Рус + Профмат + Информатика (экономика/финансы)',
'🏢 Рус + Обществознание + История (администрирование)',
],
'desc': 'Бухгалтерия, логистика, документооборот, администрирование.'
},
}
def calculate_profile(answers: dict) -> tuple:
"""
Считает профиль по RIASEC системе.
Возвращает: (profile, top3_profiles, recommended_ege_sets)
"""
scores = {'R': 0, 'I': 0, 'A': 0, 'S': 0, 'E': 0, 'C': 0}
# Маппинг вопросов на профили (если не знаешь — проверь исходный JS)
for q_num in range(1, 25):
key = f'q{q_num}'
if key in answers:
val = answers[key]
if val in scores:
scores[val] += 2
# Топ-3 профиля
sorted_profiles = sorted(scores.items(), key=lambda x: x[1], reverse=True)
main_profile = sorted_profiles[0][0]
top3 = [p[0] for p in sorted_profiles[:3]]
# Рекомендованные наборы ЕГЭ для основного профиля
recommended = EGE_SETS.get(main_profile, EGE_SETS['I'])
return main_profile, top3, recommended
# ===== API ENDPOINT =====
class CareerTestSubmitView(APIView):
"""
POST /api/career-test/submit/
Тело запроса:
{
"answers": {"q1": "I", "q2": "A", ...},
"ym_client_id": "123456789.1234567890"
}
Ответ:
{
"id": 42,
"profile": "I",
"profile_display": "Исследователь",
"top3_profiles": ["I", "E", "C"],
"recommended_ege_sets": {...},
"created_at": "2025-12-13T18:30:00Z"
}
"""
def post(self, request):
serializer = CareerTestSubmitSerializer(data=request.data)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
answers = serializer.validated_data['answers']
ym_client_id = serializer.validated_data.get('ym_client_id')
# Расчёт профиля
profile, top3, recommended_ege = calculate_profile(answers)
# Сохрани результат в БД
result = CareerTestResult.objects.create(
answers=answers,
profile=profile,
top3_profiles=top3,
recommended_ege_sets=recommended_ege,
ym_client_id=ym_client_id,
ip_address=self.get_client_ip(request),
user_agent=request.META.get('HTTP_USER_AGENT', ''),
)
# Отправь ответ
return Response(
{
'id': result.id,
'profile': result.profile,
'profile_display': result.get_profile_display(),
'top3_profiles': result.top3_profiles,
'recommended_ege_sets': result.recommended_ege_sets,
'created_at': result.created_at.isoformat(),
},
status=status.HTTP_201_CREATED
)
def get_client_ip(self, request):
"""Получи реальный IP клиента"""
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR')
return ip
class CareerTestResultsView(APIView):
"""GET /api/career-test/results/ — список всех результатов (для админа)"""
def get(self, request):
results = CareerTestResult.objects.all()
serializer = CareerTestResultSerializer(results, many=True)
return Response(serializer.data)
def index(request):
"""Возвращает главную страницу"""
return render(request, 'index.html')