feat: исход вызова — не каждый звонок заканчивается карточкой (lct-36)
Весь продукт стоял на допущении «звонок → карточка → выезд». В билетах заказчика оно нарушается намеренно: «поругался с продавцом Мегафон» — справка, а вызов из Волгоградской области передаётся в систему-112 другого субъекта. Курсант, заведший карточку на такой вызов, занял расчёт зря, и прежняя оценка этого не видела — наоборот, награждала за полноту заполнения. - Outcome в домене, поле outcome в сценарии, событие call.resolve у курсанта и две кнопки на АРМ. Отдельное действие, а не «положил трубку»: система должна отличить осознанное решение от брошенного вызова. - Метрика outcome (E2, вес 3 — лишний выезд дороже неточного признака). - Там, где карточка не заводится, метрики карточки не считаются вовсе. Полнота опроса считается: передать вызов не значит не опрашивать. - call.resolve останавливает норматив опроса, как и передача карточки. Попутно (lct-34): библиотека стала вложенной — scenarios/tickets/, поля ticket и position, чек-листы для медицины, полиции и ЖКХ. Перенесён билет 1 целиком: три вызова, три классификатора, третий — из другого региона. Найдено по ходу: модификаторы списка оповещения не были подключены ни к чему. В классификаторе скорая добавляется к массовой драке признаком «пострадавшие», но взять его было неоткуда. Теперь модификаторы берутся из карточки — victims_count, life_threat, evacuation_needed, fire.gasified, — и список оповещения пересобирается при правке любого из этих полей. 161 тест зелёный (13 новых), make typecheck чистый.
This commit is contained in:
parent
d4f0d0a0f8
commit
b8dc39fd7d
22 changed files with 628 additions and 9 deletions
26
scenarios/checklists/medical.yaml
Normal file
26
scenarios/checklists/medical.yaml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Чек-лист по классификатору 03 — скорая помощь.
|
||||
# Методика: docs/product/METHODOLOGY.md#чек-листы-опроса
|
||||
#
|
||||
# `examples` — как спрашивают живые операторы, а не как написано в инструкции.
|
||||
# Чем их больше и чем они разнообразнее, тем точнее звонящий «понимает» вопрос.
|
||||
id: medical
|
||||
dds: "03"
|
||||
checklist:
|
||||
- id: q_address
|
||||
question: "Назовите адрес: улица, дом, квартира, этаж, код домофона?"
|
||||
examples: ["Какой у вас адрес?", "Где вы находитесь?", "Куда ехать скорой?", "Код домофона какой?", "Номер квартиры?"]
|
||||
- id: q_what_happened
|
||||
question: "Что случилось с пострадавшим?"
|
||||
examples: ["Что с человеком?", "Что произошло?", "На что жалуется?", "Как это случилось?"]
|
||||
- id: q_who
|
||||
question: "Кто пострадавший: имя, возраст, пол?"
|
||||
examples: ["Сколько лет?", "Как зовут больного?", "Это мужчина или женщина?", "Возраст какой?"]
|
||||
- id: q_conscious
|
||||
question: "Человек в сознании, дышит?"
|
||||
examples: ["В сознании?", "Дышит?", "Он отвечает вам?", "Реагирует на голос?"]
|
||||
- id: q_can_move
|
||||
question: "Может ли пострадавший передвигаться самостоятельно?"
|
||||
examples: ["Он может идти?", "Ходит сам?", "Встать может?"]
|
||||
- id: q_caller
|
||||
question: "Представьтесь и оставьте контактный телефон"
|
||||
examples: ["Как вас зовут?", "Ваш номер телефона?", "Кем вы приходитесь пострадавшему?"]
|
||||
26
scenarios/checklists/police.yaml
Normal file
26
scenarios/checklists/police.yaml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Чек-лист по классификатору 02 — полиция.
|
||||
# Методика: docs/product/METHODOLOGY.md#чек-листы-опроса
|
||||
id: police
|
||||
dds: "02"
|
||||
checklist:
|
||||
- id: q_address
|
||||
question: "Назовите адрес или ориентир, где это происходит?"
|
||||
examples: ["Где это происходит?", "Какой адрес?", "Улица, дом?", "Куда наряду подъехать?"]
|
||||
- id: q_what_happened
|
||||
question: "Что именно происходит?"
|
||||
examples: ["Что случилось?", "Что произошло?", "Опишите, что вы видите"]
|
||||
- id: q_victims
|
||||
question: "Есть ли пострадавшие, нужна ли скорая?"
|
||||
examples: ["Пострадавшие есть?", "Скорая нужна?", "Кто-то ранен?", "Кровь есть?"]
|
||||
- id: q_suspects
|
||||
question: "Сколько нарушителей, как выглядят, есть ли оружие?"
|
||||
examples: ["Сколько их?", "Как они выглядят?", "Оружие есть?", "Во что одеты?", "Чем дерутся?"]
|
||||
- id: q_fled
|
||||
question: "Нарушители на месте или скрылись, в какую сторону?"
|
||||
examples: ["Они ещё там?", "Куда скрылись?", "В какую сторону уехали?", "Они на месте?"]
|
||||
- id: q_vehicle
|
||||
question: "Если есть транспорт: марка, цвет, номер?"
|
||||
examples: ["Какая машина?", "Номер запомнили?", "Цвет машины?", "Марка автомобиля?"]
|
||||
- id: q_caller
|
||||
question: "Представьтесь и оставьте контактный телефон"
|
||||
examples: ["Как вас зовут?", "Ваш номер телефона?", "Вы это сами видели?"]
|
||||
20
scenarios/checklists/utility.yaml
Normal file
20
scenarios/checklists/utility.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Чек-лист по коммунальным авариям и городскому хозяйству.
|
||||
# Методика: docs/product/METHODOLOGY.md#чек-листы-опроса
|
||||
id: utility
|
||||
dds: gkh
|
||||
checklist:
|
||||
- id: q_address
|
||||
question: "Назовите адрес: улица, дом, подъезд?"
|
||||
examples: ["Какой адрес?", "Где это?", "Улица, дом?", "Какой подъезд?"]
|
||||
- id: q_what_happened
|
||||
question: "Что именно произошло?"
|
||||
examples: ["Что случилось?", "Что там с трубой?", "Опишите повреждение"]
|
||||
- id: q_scale
|
||||
question: "Каков масштаб: что затоплено, обесточено, перекрыто?"
|
||||
examples: ["Сколько залило?", "Насколько всё серьёзно?", "Что перекрыто?", "Подъезд затоплен?"]
|
||||
- id: q_threat
|
||||
question: "Есть ли угроза людям, пострадавшие?"
|
||||
examples: ["Люди пострадали?", "Есть угроза для жильцов?", "Кто-то пострадал?"]
|
||||
- id: q_caller
|
||||
question: "Представьтесь и оставьте контактный телефон"
|
||||
examples: ["Как вас зовут?", "Ваш номер телефона?"]
|
||||
53
scenarios/tickets/t01-1-fire-container.yaml
Normal file
53
scenarios/tickets/t01-1-fire-container.yaml
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Билет 1, вызов 1 (docs/spec/TICKETS.md). Ситуация и адрес — дословно из билета,
|
||||
# факты и чек-лист выведены из ситуации: чего в строке нет, того звонящий не знает.
|
||||
id: t01-1-fire-container
|
||||
title: "Возгорание мусорного контейнера"
|
||||
ticket: 1
|
||||
position: 1
|
||||
type: fire
|
||||
level: L2
|
||||
topics: [fires]
|
||||
modes: [training, exam, self]
|
||||
|
||||
extends: checklists/fire.yaml
|
||||
signs: [на улице, мусор, открытое пламя]
|
||||
|
||||
persona:
|
||||
base: calm
|
||||
arc:
|
||||
- { stage: registration, mood: calm }
|
||||
- { stage: interview, mood: calm }
|
||||
|
||||
first_line: "Здравствуйте. Тут мусорный контейнер горит, у депо."
|
||||
|
||||
facts:
|
||||
- id: f_address
|
||||
value: "Депо, около станции Москва-Пассажирская Киевская, длинное помещение недалеко от участкового пункта полиции"
|
||||
refined: "Московская железная дорога, Киевская, 1 км, дом 2, строение 2"
|
||||
reveal_on: { question: q_address }
|
||||
refine_on: q_address_check
|
||||
- id: f_what_burns
|
||||
value: "горит мусорный контейнер, пламя открытое"
|
||||
reveal_on: { question: q_what_burns }
|
||||
- id: f_people
|
||||
value: "пострадавших нет, рядом никого"
|
||||
reveal_on: { question: q_people }
|
||||
- id: f_caller
|
||||
value: "Сидоров Иван Сергеевич, телефон 916-126-34-71"
|
||||
reveal_on: { question: q_caller }
|
||||
|
||||
checklist:
|
||||
- { id: q_address, fact: f_address }
|
||||
- { id: q_address_check }
|
||||
- { id: q_what_burns, fact: f_what_burns }
|
||||
- { id: q_people, fact: f_people }
|
||||
- { id: q_caller, fact: f_caller }
|
||||
|
||||
required_fields: [address, incident_type, description]
|
||||
|
||||
ground_truth:
|
||||
address: "Московская железная дорога, Киевская, 1 км, дом 2, строение 2"
|
||||
victims: 0
|
||||
|
||||
tree:
|
||||
pregenerated: false
|
||||
58
scenarios/tickets/t01-2-mass-fight.yaml
Normal file
58
scenarios/tickets/t01-2-mass-fight.yaml
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# Билет 1, вызов 2 (docs/spec/TICKETS.md). Массовая драка с пострадавшими:
|
||||
# в списке оповещения и полиция, и скорая — это тот случай, где выбор одной
|
||||
# службы был бы неверен по построению.
|
||||
id: t01-2-mass-fight
|
||||
title: "Массовая драка у посольства, пятеро пострадавших"
|
||||
ticket: 1
|
||||
position: 2
|
||||
type: police
|
||||
level: L2
|
||||
topics: [police]
|
||||
modes: [training, exam, self]
|
||||
|
||||
extends: checklists/police.yaml
|
||||
signs: [Драка, Улица общественное место, Массовая (от 10 человек)]
|
||||
|
||||
persona:
|
||||
base: worried
|
||||
arc:
|
||||
- { stage: registration, mood: worried }
|
||||
- { stage: interview, mood: worried }
|
||||
|
||||
first_line: "Алло! Тут человек пятнадцать дерутся, прутами машут! Скорее!"
|
||||
|
||||
facts:
|
||||
- id: f_address
|
||||
value: "рядом с посольством Азербайджана, на тротуаре"
|
||||
refined: "Леонтьевский переулок, дом 16, строение 1"
|
||||
reveal_on: { question: q_address }
|
||||
refine_on: q_address_check
|
||||
- id: f_what_happened
|
||||
value: "дерутся десять-пятнадцать человек"
|
||||
reveal_on: { question: q_what_happened }
|
||||
- id: f_victims
|
||||
value: "пятеро пострадавших с разными травмами"
|
||||
reveal_on: { question: q_victims }
|
||||
- id: f_suspects
|
||||
value: "дерутся палками и железными прутами, огнестрельного не видно"
|
||||
reveal_on: { question: q_suspects }
|
||||
- id: f_caller
|
||||
value: "Иванов Пётр Иванович, телефон 916-123-98-78"
|
||||
reveal_on: { question: q_caller }
|
||||
|
||||
checklist:
|
||||
- { id: q_address, fact: f_address }
|
||||
- { id: q_address_check }
|
||||
- { id: q_what_happened, fact: f_what_happened }
|
||||
- { id: q_victims, fact: f_victims }
|
||||
- { id: q_suspects, fact: f_suspects }
|
||||
- { id: q_caller, fact: f_caller }
|
||||
|
||||
required_fields: [address, incident_type, description, victims_count]
|
||||
|
||||
ground_truth:
|
||||
address: "Леонтьевский переулок, дом 16, строение 1"
|
||||
victims: 5
|
||||
|
||||
tree:
|
||||
pregenerated: false
|
||||
64
scenarios/tickets/t01-3-child-other-region.yaml
Normal file
64
scenarios/tickets/t01-3-child-other-region.yaml
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# Билет 1, вызов 3 (docs/spec/TICKETS.md). Вызов не из Москвы: Волжский —
|
||||
# это Волгоградская область. Правильное действие — не заводить карточку,
|
||||
# а передать вызов в систему-112 другого субъекта. Проверяется тем, что
|
||||
# курсант вообще спросил про город.
|
||||
id: t01-3-child-other-region
|
||||
title: "Ребёнок упал с велосипеда, вызов из другого региона"
|
||||
ticket: 1
|
||||
position: 3
|
||||
type: medical
|
||||
level: L3
|
||||
topics: [medical, address]
|
||||
modes: [training, exam, self]
|
||||
|
||||
extends: checklists/medical.yaml
|
||||
signs: [Травма]
|
||||
outcome: transfer_region
|
||||
|
||||
persona:
|
||||
base: worried
|
||||
arc:
|
||||
- { stage: registration, mood: worried }
|
||||
- { stage: interview, mood: worried }
|
||||
|
||||
first_line: "Здравствуйте, сын с велосипеда упал, рука и нога опухли!"
|
||||
|
||||
facts:
|
||||
# Мама называет улицу так, будто это Москва. Про область она скажет только
|
||||
# если спросить: ей не приходит в голову, что попала не туда.
|
||||
- id: f_address
|
||||
value: "улица Карла Маркса, около Молсыркомбината"
|
||||
refined: "Волгоградская область, город Волжский, улица Карла Маркса, около Волжского Молсыркомбината"
|
||||
reveal_on: { question: q_address }
|
||||
refine_on: q_address_check
|
||||
- id: f_what_happened
|
||||
value: "упал с велосипеда сам, отёк руки и ноги"
|
||||
reveal_on: { question: q_what_happened }
|
||||
- id: f_who
|
||||
value: "Смирнов Илья, 11 лет, сын"
|
||||
reveal_on: { question: q_who }
|
||||
- id: f_conscious
|
||||
value: "в сознании, плачет, дышит нормально"
|
||||
reveal_on: { question: q_conscious }
|
||||
- id: f_caller
|
||||
value: "звонит мама, телефон 9163201283"
|
||||
reveal_on: { question: q_caller }
|
||||
|
||||
checklist:
|
||||
- { id: q_address, fact: f_address }
|
||||
- { id: q_address_check }
|
||||
- { id: q_what_happened, fact: f_what_happened }
|
||||
- { id: q_who, fact: f_who }
|
||||
- { id: q_conscious, fact: f_conscious }
|
||||
- { id: q_caller, fact: f_caller }
|
||||
|
||||
# Карточка здесь не заводится, поэтому обязательных полей нет: штрафовать
|
||||
# за пустую карточку значит учить заполнять лишнее.
|
||||
required_fields: []
|
||||
|
||||
ground_truth:
|
||||
address: "Волгоградская область, город Волжский, улица Карла Маркса, около Волжского Молсыркомбината"
|
||||
victims: 1
|
||||
|
||||
tree:
|
||||
pregenerated: false
|
||||
Loading…
Reference in a new issue