- bd/__init__.py: добавлены get_engine() и get_session() — один SQLAlchemy engine на весь процесс - make_engine(): pool_size=5, max_overflow=5, pool_timeout=30, pool_recycle=1800 - Все 17 route-файлов: убраны локальные get_session()/make_engine(), импорт из bd - transfer_crud.py: _get_session() → get_session() из bd - init_data_base.py: get_engine() вместо make_engine() - Результат: 78 idle соединений → 1
502 lines
42 KiB
Python
502 lines
42 KiB
Python
"""Эндпоинты для работы с тестом «Карта интересов»
|
||
(А.Е. Гломшток, модификация А.А. Азабель, А.Г. Грецова).
|
||
|
||
POST /polls/glomshtok — создать опрос в БД (144 утверждения, 5 вариантов ответа)
|
||
POST /polls/glomshtok/{id}/seed-scores — загрузить ключ расшифровки (24 сферы интересов)
|
||
GET /polls/glomshtok — список тестов «Карта интересов»
|
||
|
||
Ключ: вопрос с position=N относится к измерению dimension = ((N - 1) % 24) + 1.
|
||
Пример: вопросы 1, 25, 49, 73, 97, 121 → Биология; вопросы 13, 37, 61, 85, 109, 133 → Военные специальности.
|
||
|
||
Варианты ответа и баллы: ++ = +2 | + = +1 | 0 = 0 | - = −1 | -- = −2
|
||
|
||
Интерпретация суммы по сфере (6 вопросов × ±2, диапазон −12..+12):
|
||
−12..−6 → область деятельности активно отрицается («Что угодно, только не это!»)
|
||
−5..−1 → область деятельности интереса не вызывает
|
||
+1..+4 → интерес выражен слабо
|
||
+5..+7 → выраженный интерес
|
||
+8..+12 → ярко выраженный интерес
|
||
|
||
После прохождения теста (POST /polls/{id}/responses) диаграмма строится автоматически
|
||
и сохраняется в data/radar/<poll_title>/<user_id>/<result_id>.svg.
|
||
"""
|
||
|
||
from fastapi import APIRouter, HTTPException
|
||
import uuid
|
||
|
||
from bd import get_session
|
||
from bd.tables.poll import Poll
|
||
from bd.tables.question import Question
|
||
from bd.tables.choice import Choice
|
||
from bd.tables.scale import ScaleDimension, ChoiceScore
|
||
|
||
router = APIRouter(tags=["polls"], prefix="/polls")
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 144 утверждения «Карты интересов»
|
||
# Порядок строго соответствует PDF; индекс + 1 = номер вопроса.
|
||
# ---------------------------------------------------------------------------
|
||
STATEMENTS: list[str] = [
|
||
"Изучать разнообразие животного и растительного мира.", # 1
|
||
"Проводить физические эксперименты.", # 2
|
||
"Разрабатывать новые технологии химического синтеза.", # 3
|
||
"Изучать месторождения полезных ископаемых.", # 4
|
||
"Разрабатывать новые методы диагностики и лечения различных болезней.", # 5
|
||
"Устанавливать и налаживать работу компьютерных программ.", # 6
|
||
"Следить за последовательностью и технологиями строительных работ.", # 7
|
||
"Решать задачки из книг типа «Математические игры», «Занимательная математика».", # 8
|
||
"Планировать финансовую и производственную деятельность предприятия, фирмы.", # 9
|
||
"Помогать делать переводы документации.", # 10
|
||
"Управлять машиной, автобусом, трейлером и т. д.", # 11
|
||
"Заниматься в секции парашютистов, в авиаклубе или заниматься в секции яхтсменов, аквалангистов.", # 12
|
||
"Заниматься в стрелковой секции.", # 13
|
||
"Заниматься в историческом клубе, разыгрывать ролевые игры по сюжетам исторических событий.", # 14
|
||
"Изучать устройство и режимы работы станков.", # 15
|
||
"Писать статьи, фельетоны, очерки в периодические издания и в Интернет.", # 16
|
||
"Оказывать юридическую помощь людям, консультируя их по вопросам законодательства.", # 17
|
||
"Организовывать для ребят игры и праздники.", # 18
|
||
"Консультировать людей при крупных покупках (автомобиль, заграничный тур и т. д.).", # 19
|
||
"Тренировать команду спортсменов.", # 20
|
||
"Работать на музыкальных радиоканалах, составлять списки произведений для звучания в эфире.", # 21
|
||
"Сниматься в кино или играть на сцене.", # 22
|
||
"Делать интернет-сайты, веб-страницы.", # 23
|
||
"Разрабатывать мероприятия по охране численности редких растений и животных.", # 24
|
||
"Участвовать в биологических экспедициях, посещать биологические секции.", # 25
|
||
"Изучать законы природы, находить физические закономерности.", # 26
|
||
"Проводить опыты с различными веществами, следить за ходом химических реакций.", # 27
|
||
"Вести наблюдения за изменениями состояния атмосферы.", # 28
|
||
"Читать о том, как люди учились бороться с болезнями и изобретали новые лекарства.", # 29
|
||
"Находить и устранять причины сбоя в компьютерах, аппаратуре, приборах.", # 30
|
||
"Набрасывать эскизы или выполнять чертежи различных построек.", # 31
|
||
"Соревноваться в решении математических задач.", # 32
|
||
"Выступать посредником при заключении торговых сделок (искать покупателям продавцов и наоборот).", # 33
|
||
"Проводить экскурсии на иностранном языке для гостей нашего города.", # 34
|
||
"Управлять пожарной машиной.", # 35
|
||
"Управлять самолётом МЧС или скоростным катером.", # 36
|
||
"Участвовать в военизированных учениях («Зарница», «Разведчик» и др.).", # 37
|
||
"Посещать исторические музеи, изучать исторические памятники разных народов.", # 38
|
||
"Регулировать механизмы и заменять их в случае неисправности.", # 39
|
||
"Наблюдать и анализировать события, поступки людей, делать об этом репортажи.", # 40
|
||
"Искать и фиксировать следы на месте преступления.", # 41
|
||
"Заниматься репетиторством и преподавательской деятельностью.", # 42
|
||
"Изучать спрос покупателей на определённый товар.", # 43
|
||
"Читать специальные спортивные новости в газетах и на сайтах.", # 44
|
||
"Исполнять произведения на музыкальных инструментах с использованием различных техник игры.", # 45
|
||
"Изучать основы сценического искусства, творчество знаменитых мастеров сцены.", # 46
|
||
"Искать наиболее рациональное и эстетическое цветовое решение для интерьеров.", # 47
|
||
"Проводить наблюдения и контроль загрязнения окружающей среды.", # 48
|
||
"Изучать анатомию и физиологию животных.", # 49
|
||
"Собирать установки для проведения физических экспериментов.", # 50
|
||
"В лабораторных условиях определять степень загрязнённости почвы химическими веществами.", # 51
|
||
"Создавать ландшафтные карты с помощью компьютерных геоинформационных систем.", # 52
|
||
"Интересоваться причинами и способами лечения болезни.", # 53
|
||
"Прокладывать сетевые кабели и кабели силового питания.", # 54
|
||
"Изучать новые технологии строительства.", # 55
|
||
"Изучать языки программирования на компьютере.", # 56
|
||
"Осуществлять финансовые расчёты между предприятиями.", # 57
|
||
"Читать литературу на иностранном языке или смотреть фильмы без перевода.", # 58
|
||
"Управлять современным поездом дальнего следования.", # 59
|
||
"Оказывать экстренную помощь людям на терпящих бедствие судах.", # 60
|
||
"Быть военным инженером или командиром.", # 61
|
||
"Обсуждать исторические и текущие политические события России и других стран.", # 62
|
||
"Подбирать цветовые оттенки, красить дома, расписывать стены.", # 63
|
||
"Добывать эксклюзивную информацию, передавать её читателям и зрителям.", # 64
|
||
"Контролировать своевременную уплату налогов фирмами и физическими лицами.", # 65
|
||
"Обучать маленьких детей, играя с ними.", # 66
|
||
"Встречать и размещать пассажиров в салоне самолёта.", # 67
|
||
"Тренироваться в профессиональном спортивном клубе.", # 68
|
||
"Играть в музыкальной группе или в оркестре, следуя указаниям дирижёра.", # 69
|
||
"Вести концертные программы, объявлять зрителям новые номера программы.", # 70
|
||
"Создавать необычные модели одежды.", # 71
|
||
"Разрабатывать меры по снижению количества вредных производственных выбросов в окружающую среду.", # 72
|
||
"Разрабатывать средства борьбы с возбудителями заболеваний животных и растений.", # 73
|
||
"Изучать процессы взаимодействия элементарных частиц в ядерных реакторах.", # 74
|
||
"Брать на анализ химические пробы воды, продуктов питания, почвы и пр.", # 75
|
||
"Вести разведку месторождений полезных ископаемых: нефти, газа, драгоценных металлов и др.", # 76
|
||
"Тренироваться в навыках первой медицинской помощи.", # 77
|
||
"Проверять, испытывать, регулировать работу узлов автомобиля, самолёта, корабля и т. д.", # 78
|
||
"Готовить растворы, смеси для строительных работ.", # 79
|
||
"Разрабатывать программные алгоритмы для выполнения сложных расчётов.", # 80
|
||
"Вести финансовую документацию фирмы, предприятия.", # 81
|
||
"Изучать иностранные языки.", # 82
|
||
"Регулировать движение транспортных потоков на улицах города.", # 83
|
||
"Оказывать экстренную помощь людям «с воздуха» (например, управляя вертолётом МЧС).", # 84
|
||
"Изучать устройство оружия, военной техники.", # 85
|
||
"Анализировать по книгам исторические факты.", # 86
|
||
"Обеспечивать в домах систему отопления, исправную работу водопровода.", # 87
|
||
"Редактировать тексты книг, статей, выступлений высокопоставленных лиц.", # 88
|
||
"Выдвигать обвинения преступникам, назначать им наказания в соответствии с законом.", # 89
|
||
"Готовить школьников к олимпиадным заданиям, конкурсам.", # 90
|
||
"Помогать подбирать людям наряды и украшения для торжественных церемоний.", # 91
|
||
"Сдавать спортивные нормативы.", # 92
|
||
"Выступать в качестве солиста перед публикой на концертах, в клубах.", # 93
|
||
"Подбирать актёров для съёмки художественного фильма или рекламного клипа.", # 94
|
||
"Делать фотоснимки, монтировать фотографии с помощью компьютера.", # 95
|
||
"Заниматься мониторингом состояния воздуха на оживлённых городских магистралях.", # 96
|
||
"Отбирать и заготавливать семена для посадки, высаживать растения в зимних садах.", # 97
|
||
"Моделировать на компьютере физические законы природы.", # 98
|
||
"Создавать новые синтетические вещества из нефтепродуктов и других полезных ископаемых.", # 99
|
||
"Изучать особенности флоры и фауны различных регионов.", # 100
|
||
"Осуществлять уход за человеком во время его выздоровления после болезни.", # 101
|
||
"Заниматься в технической или электротехнической секции (например, в авиа- или судомоделировании).", # 102
|
||
"Изучать качества и условия применения строительных материалов.", # 103
|
||
"Писать компьютерные программы на основе анализа математических алгоритмов.", # 104
|
||
"Рассчитывать предполагаемый размер прибыли предприятия.", # 105
|
||
"Осуществлять перевод телепередач на русский язык.", # 106
|
||
"Консультировать людей по соблюдению правил дорожного движения.", # 107
|
||
"Изучать особенности управления яхтой в штормовую погоду.", # 108
|
||
"Предупреждать незаконное пересечение государственной границы иностранными гражданами.", # 109
|
||
"Разыскивать и собирать материалы, свидетельствующие о событиях прошлого.", # 110
|
||
"Обрабатывать и изготовлять металлические детали на фрезерном станке.", # 111
|
||
"Работать в средствах массовой информации, вести телепередачи.", # 112
|
||
"Выяснять у людей причины незаконных поступков, которые они скрывают.", # 113
|
||
"Организовывать походы для школьников.", # 114
|
||
"Разрабатывать рекламные акции для продвижения товара в магазинах города.", # 115
|
||
"Ездить в качестве участника на спортивные соревнования в другой город.", # 116
|
||
"Сочинять музыку для кинофильмов, телепередач, для известных исполнителей.", # 117
|
||
"Подготавливать и ставить трюки в кино.", # 118
|
||
"Придумывать оригинальные ювелирные изделия, украшения.", # 119
|
||
"Изучать взаимоотношения живых организмов с их средой обитания.", # 120
|
||
"Заниматься дрессировкой служебных собак или других животных.", # 121
|
||
"Читать книги типа «Занимательная физика», «Физики шутят» и т. п.", # 122
|
||
"Управлять технологическими процессами производства лекарств.", # 123
|
||
"Участвовать в географических экспедициях.", # 124
|
||
"Работать врачом на станции «Скорой помощи».", # 125
|
||
"Ремонтировать радиоприборы и различную аппаратуру.", # 126
|
||
"Продумывать планировку домов, этажей, квартир. Намечать план строительства.", # 127
|
||
"Отражать в виде чисел и формул какие-либо события, процессы или явления.", # 128
|
||
"Заключать сделки, договоры на выполнение определённых работ.", # 129
|
||
"Изучать происхождение слов и различных словосочетаний в разных языках.", # 130
|
||
"Тренироваться водить машину или мотоцикл для подготовки к гонке.", # 131
|
||
"Изучать особенности управления лёгким самолётом в ветреную погоду.", # 132
|
||
"Жить согласно уставу, носить военную форму.", # 133
|
||
"Участвовать в археологических экспедициях, работать на раскопках.", # 134
|
||
"Делать из дерева различные предметы, мебель и пр.", # 135
|
||
"Осуществлять литературную обработку статей в соответствии с жанровым своеобразием.", # 136
|
||
"Продумывать новые законы и поправки в кодексы, которые были бы удобны для применения.", # 137
|
||
"Руководить одной из секций в доме детского творчества.", # 138
|
||
"Помогать человеку улучшить внешность с помощью причёски, макияжа, подбора красивой одежды и т. п.", # 139
|
||
"Осуществлять честное и грамотное судейство на спортивных соревнованиях.", # 140
|
||
"Изучать творчество выдающихся композиторов, поэтов песен и исполнителей.", # 141
|
||
"Создавать творческие проекты, «раскручивать» исполнителей.", # 142
|
||
"Заниматься дизайном интерьеров.", # 143
|
||
"Следить за качеством воды, поступающей в городскую водопроводную сеть.", # 144
|
||
]
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 24 сферы интересов
|
||
# Порядок соответствует столбцам бланка ответов из PDF.
|
||
# ---------------------------------------------------------------------------
|
||
DIMENSIONS = [
|
||
{
|
||
"code": "1", "name": "Биология", "position": 1, "color": "#6B8E5E",
|
||
"description": (
|
||
"Интерес к живой природе, биологии, зоологии, ботанике, экспедициям. "
|
||
"Рекомендуемые профессии: биолог, зоолог, ботаник, агроном, ветеринар, эколог."
|
||
),
|
||
},
|
||
{
|
||
"code": "2", "name": "Физика", "position": 2, "color": "#4A7FA5",
|
||
"description": (
|
||
"Интерес к физическим законам, экспериментам, моделированию. "
|
||
"Рекомендуемые профессии: физик, инженер-физик, научный сотрудник, метролог."
|
||
),
|
||
},
|
||
{
|
||
"code": "3", "name": "Химия", "position": 3, "color": "#9B59B6",
|
||
"description": (
|
||
"Интерес к химическим процессам, лабораторным опытам, синтезу веществ. "
|
||
"Рекомендуемые профессии: химик, технолог, лаборант, провизор."
|
||
),
|
||
},
|
||
{
|
||
"code": "4", "name": "География", "position": 4, "color": "#27AE60",
|
||
"description": (
|
||
"Интерес к изучению Земли, природных ресурсов, экспедициям, геоинформатике. "
|
||
"Рекомендуемые профессии: географ, геолог, картограф, метеоролог."
|
||
),
|
||
},
|
||
{
|
||
"code": "5", "name": "Медицина", "position": 5, "color": "#E74C3C",
|
||
"description": (
|
||
"Интерес к здоровью, лечению людей и животных, медицинским технологиям. "
|
||
"Рекомендуемые профессии: врач, медсестра, фельдшер, фармацевт."
|
||
),
|
||
},
|
||
{
|
||
"code": "6", "name": "Техника и электроника", "position": 6, "color": "#2980B9",
|
||
"description": (
|
||
"Интерес к приборам, компьютерам, электронике, ремонту техники. "
|
||
"Рекомендуемые профессии: инженер, электроник, системный администратор, радиотехник."
|
||
),
|
||
},
|
||
{
|
||
"code": "7", "name": "Строительство", "position": 7, "color": "#795548",
|
||
"description": (
|
||
"Интерес к строительным технологиям, архитектуре, планировке зданий. "
|
||
"Рекомендуемые профессии: архитектор, прораб, строитель, проектировщик."
|
||
),
|
||
},
|
||
{
|
||
"code": "8", "name": "Математика", "position": 8, "color": "#1ABC9C",
|
||
"description": (
|
||
"Интерес к числам, формулам, задачам, алгоритмам, программированию. "
|
||
"Рекомендуемые профессии: математик, программист, статистик, аналитик данных."
|
||
),
|
||
},
|
||
{
|
||
"code": "9", "name": "Экономика", "position": 9, "color": "#F39C12",
|
||
"description": (
|
||
"Интерес к финансам, торговле, производственному планированию. "
|
||
"Рекомендуемые профессии: экономист, бухгалтер, финансист, менеджер."
|
||
),
|
||
},
|
||
{
|
||
"code": "10", "name": "Иностранные языки", "position": 10, "color": "#3498DB",
|
||
"description": (
|
||
"Интерес к языкам, переводу, межкультурным коммуникациям. "
|
||
"Рекомендуемые профессии: переводчик, лингвист, преподаватель иностранного языка."
|
||
),
|
||
},
|
||
{
|
||
"code": "11", "name": "Транспорт", "position": 11, "color": "#E67E22",
|
||
"description": (
|
||
"Интерес к управлению транспортом, логистике, ПДД. "
|
||
"Рекомендуемые профессии: водитель, машинист, диспетчер, логист."
|
||
),
|
||
},
|
||
{
|
||
"code": "12", "name": "Авиация, морское дело", "position": 12, "color": "#16A085",
|
||
"description": (
|
||
"Интерес к полётам, мореплаванию, экстремальным видам деятельности. "
|
||
"Рекомендуемые профессии: лётчик, штурман, капитан, водолаз, парашютист."
|
||
),
|
||
},
|
||
{
|
||
"code": "13", "name": "Военные специальности", "position": 13, "color": "#2C3E50",
|
||
"description": (
|
||
"Интерес к армии, военной технике, патриотическим видам деятельности. "
|
||
"Рекомендуемые профессии: офицер, пограничник, военный инженер, командир."
|
||
),
|
||
},
|
||
{
|
||
"code": "14", "name": "История", "position": 14, "color": "#8E6B3E",
|
||
"description": (
|
||
"Интерес к истории, политике, археологии, изучению прошлого. "
|
||
"Рекомендуемые профессии: историк, археолог, политолог, архивист."
|
||
),
|
||
},
|
||
{
|
||
"code": "15", "name": "Рабочие специальности", "position": 15, "color": "#7F8C8D",
|
||
"description": (
|
||
"Интерес к ручному труду, ремёслам, работе на станках. "
|
||
"Рекомендуемые профессии: слесарь, токарь, столяр, сантехник, маляр."
|
||
),
|
||
},
|
||
{
|
||
"code": "16", "name": "Журналистика", "position": 16, "color": "#C0392B",
|
||
"description": (
|
||
"Интерес к написанию текстов, СМИ, репортажам, медиапроизводству. "
|
||
"Рекомендуемые профессии: журналист, редактор, корреспондент, телеведущий."
|
||
),
|
||
},
|
||
{
|
||
"code": "17", "name": "Юриспруденция", "position": 17, "color": "#1F3A5F",
|
||
"description": (
|
||
"Интерес к законам, правопорядку, криминалистике, судопроизводству. "
|
||
"Рекомендуемые профессии: юрист, адвокат, судья, следователь, нотариус."
|
||
),
|
||
},
|
||
{
|
||
"code": "18", "name": "Педагогика", "position": 18, "color": "#D4A84B",
|
||
"description": (
|
||
"Интерес к обучению, воспитанию, работе с детьми. "
|
||
"Рекомендуемые профессии: учитель, воспитатель, педагог-психолог, тренер."
|
||
),
|
||
},
|
||
{
|
||
"code": "19", "name": "Сфера обслуживания, торговля", "position": 19, "color": "#F1948A",
|
||
"description": (
|
||
"Интерес к торговле, обслуживанию клиентов, маркетингу, сервису. "
|
||
"Рекомендуемые профессии: продавец, менеджер по продажам, администратор, стилист."
|
||
),
|
||
},
|
||
{
|
||
"code": "20", "name": "Физкультура и спорт", "position": 20, "color": "#28B463",
|
||
"description": (
|
||
"Интерес к спорту, тренировкам, соревнованиям, физическому развитию. "
|
||
"Рекомендуемые профессии: спортсмен, тренер, инструктор, спортивный судья."
|
||
),
|
||
},
|
||
{
|
||
"code": "21", "name": "Музыка", "position": 21, "color": "#A569BD",
|
||
"description": (
|
||
"Интерес к музыке, игре на инструментах, сочинению, звукорежиссуре. "
|
||
"Рекомендуемые профессии: музыкант, композитор, дирижёр, звукорежиссёр."
|
||
),
|
||
},
|
||
{
|
||
"code": "22", "name": "Сценическое искусство", "position": 22, "color": "#EC407A",
|
||
"description": (
|
||
"Интерес к театру, кино, сцене, перевоплощению, продюсированию. "
|
||
"Рекомендуемые профессии: актёр, режиссёр, сценарист, продюсер."
|
||
),
|
||
},
|
||
{
|
||
"code": "23", "name": "Изобразительное искусство", "position": 23, "color": "#FF8C42",
|
||
"description": (
|
||
"Интерес к рисованию, дизайну, фотографии, созданию визуальных образов. "
|
||
"Рекомендуемые профессии: художник, дизайнер, фотограф, ювелир."
|
||
),
|
||
},
|
||
{
|
||
"code": "24", "name": "Экология", "position": 24, "color": "#2ECC71",
|
||
"description": (
|
||
"Интерес к охране природы, экологическому мониторингу, контролю загрязнений. "
|
||
"Рекомендуемые профессии: эколог, природоохранный инспектор, санитарный врач."
|
||
),
|
||
},
|
||
]
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Шкала оценок: позиция варианта ответа → числовой балл
|
||
# ---------------------------------------------------------------------------
|
||
CHOICE_SCORES: dict[int, float] = {
|
||
1: 2.0, # ++
|
||
2: 1.0, # +
|
||
3: 0.0, # 0
|
||
4: -1.0, # -
|
||
5: -2.0, # --
|
||
}
|
||
|
||
CHOICE_LABELS: list[str] = ["++", "+", "0", "-", "--"]
|
||
|
||
|
||
|
||
|
||
@router.post("/glomshtok", status_code=201)
|
||
def create_glomshtok_poll():
|
||
"""
|
||
Создаёт тест «Карта интересов» в базе данных (144 утверждения, 5 вариантов ответа).
|
||
После создания вызовите POST /polls/glomshtok/{id}/seed-scores для загрузки ключа расшифровки.
|
||
"""
|
||
Session = get_session()
|
||
with Session() as session:
|
||
poll = Poll(
|
||
title="Карта интересов — А.Е. Гломшток (модификация А.А. Азабель, А.Г. Грецова)",
|
||
description=(
|
||
"Методика «Карта интересов» для профориентации. Оцените 144 утверждения по шкале: "
|
||
"«++» (очень хотелось бы), «+» (нравится), «0» (сомневаюсь), "
|
||
"«-» (не нравится), «--» (совершенно не нравится). "
|
||
"Определяет выраженность интересов в 24 сферах деятельности."
|
||
),
|
||
)
|
||
session.add(poll)
|
||
for idx, text in enumerate(STATEMENTS, start=1):
|
||
q = Question(text=text, position=idx, type="single", poll=poll)
|
||
session.add(q)
|
||
for pos, label in enumerate(CHOICE_LABELS, start=1):
|
||
ch = Choice(question=q, text=label, position=pos)
|
||
session.add(ch)
|
||
session.commit()
|
||
session.refresh(poll)
|
||
return {"id": str(poll.id), "questions": len(poll.questions)}
|
||
|
||
|
||
@router.get("/glomshtok")
|
||
def list_glomshtok_polls():
|
||
"""Возвращает список тестов «Карта интересов» Гломштока."""
|
||
Session = get_session()
|
||
with Session() as session:
|
||
rows = session.query(Poll).filter(Poll.title.like("%Гломшток%")).all()
|
||
return [{"id": str(p.id), "title": p.title, "description": p.description} for p in rows]
|
||
|
||
|
||
@router.post("/glomshtok/{poll_id}/seed-scores", status_code=201)
|
||
def seed_glomshtok_scores(poll_id: str):
|
||
"""
|
||
Загружает ключ расшифровки «Карты интересов» в базу данных:
|
||
- создаёт 24 оси диаграммы (ScaleDimension) для указанного теста
|
||
- для каждого из 144 вопросов привязывает 5 вариантов ответа к соответствующей оси (ChoiceScore)
|
||
с баллами: ++ = +2 | + = +1 | 0 = 0 | - = −1 | -- = −2
|
||
|
||
Формула: вопрос с position=N → измерение ((N − 1) % 24) + 1
|
||
При повторном вызове оси и расшифровки пересоздаются.
|
||
"""
|
||
Session = get_session()
|
||
try:
|
||
pid = uuid.UUID(poll_id)
|
||
except Exception:
|
||
raise HTTPException(status_code=400, detail="Invalid poll UUID")
|
||
|
||
with Session() as session:
|
||
poll = session.get(Poll, pid)
|
||
if not poll:
|
||
raise HTTPException(status_code=404, detail="Poll not found")
|
||
|
||
questions = (
|
||
session.query(Question)
|
||
.filter(Question.poll_id == pid)
|
||
.order_by(Question.position.asc())
|
||
.all()
|
||
)
|
||
if len(questions) != 144:
|
||
raise HTTPException(
|
||
status_code=422,
|
||
detail=(
|
||
f"Ожидается 144 вопроса, найдено {len(questions)}. "
|
||
"Убедитесь, что тест создан через POST /polls/glomshtok."
|
||
),
|
||
)
|
||
|
||
# Удаляем старые оси (ChoiceScore удаляются каскадно)
|
||
old_dims = session.query(ScaleDimension).filter(ScaleDimension.poll_id == pid).all()
|
||
for d in old_dims:
|
||
session.delete(d)
|
||
session.flush()
|
||
|
||
# Создаём 24 оси: position → объект
|
||
dim_map: dict[int, ScaleDimension] = {}
|
||
for d_data in DIMENSIONS:
|
||
dim = ScaleDimension(
|
||
poll_id=pid,
|
||
name=d_data["name"],
|
||
description=d_data["description"],
|
||
color=d_data["color"],
|
||
position=d_data["position"],
|
||
)
|
||
session.add(dim)
|
||
session.flush()
|
||
dim_map[d_data["position"]] = dim
|
||
|
||
# Для каждого вопроса привязываем все 5 вариантов к соответствующей оси
|
||
scores_created = 0
|
||
for q in questions:
|
||
dim_idx = ((q.position - 1) % 24) + 1
|
||
dim = dim_map.get(dim_idx)
|
||
if dim is None:
|
||
continue
|
||
choices = (
|
||
session.query(Choice)
|
||
.filter(Choice.question_id == q.id)
|
||
.order_by(Choice.position.asc())
|
||
.all()
|
||
)
|
||
for ch in choices:
|
||
score_val = CHOICE_SCORES.get(ch.position, 0.0)
|
||
session.add(ChoiceScore(choice_id=ch.id, dimension_id=dim.id, score=score_val))
|
||
scores_created += 1
|
||
|
||
session.commit()
|
||
|
||
return {
|
||
"status": "ok",
|
||
"dimensions": len(DIMENSIONS),
|
||
"choice_scores": scores_created,
|
||
"message": (
|
||
"Расшифровка «Карты интересов» успешно загружена. "
|
||
"После прохождения теста диаграмма строится автоматически и "
|
||
"сохраняется в data/radar/."
|
||
),
|
||
}
|