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