Merge branch 'phase/45-presence-talk'

# Conflicts:
#	docs/phases/README.md
#	src/HSchool.Server/Api/PeopleModels.cs
#	src/HSchool.Server/Game/PersonCardReader.cs
This commit is contained in:
Leonid Pershin
2026-08-20 11:27:58 +03:00
28 changed files with 679 additions and 41 deletions
+8 -8
View File
@@ -11,18 +11,18 @@
## Задачи
- [ ] Кадр присутствия: у человека, который в кружке, список id участников и id темы.
- [x] Кадр присутствия: у человека, который в кружке, список id участников и id темы.
Имена не строкой. Клиент собирает «говорит с Машей о футболе» из справочника и локали
- [ ] Версия протокола +1. `ProtocolCodec.cs`, `protocol.ts`, `docs/protocol.md` в одном коммите
- [ ] Не в кружке — пустой список, как сейчас только id/узел/состояние
- [ ] Вкладка «Сейчас» на карточке согласована с тем же составом
- [ ] Старый клиент отваливается Hello, как обычно
- [x] Версия протокола +1. `ProtocolCodec.cs`, `protocol.ts`, `docs/protocol.md` в одном коммите
- [x] Не в кружке — пустой список, как сейчас только id/узел/состояние
- [x] Вкладка «Сейчас» на карточке согласована с тем же составом
- [x] Старый клиент отваливается Hello, как обычно
## Тесты, без которых фаза не закрыта
- [ ] Круглый трип и байтовая раскладка человека с кружком и без — на обеих сторонах
- [ ] Имя человека не встречается в кадре присутствия
- [ ] Клиентский тест: локация показывает тему и имя напарника из directory, не из кадра
- [x] Круглый трип и байтовая раскладка человека с кружком и без — на обеих сторонах
- [x] Имя человека не встречается в кадре присутствия
- [x] Клиентский тест: локация показывает тему и имя напарника из directory, не из кадра
## Критерий готовности
+1 -1
View File
@@ -212,7 +212,7 @@
| Фаза | Статус | Зачем |
| --- | --- | --- |
| [44. Ссора и драка](44-quarrel-fight.md) | 🔄 | Жертва задиры, заступник, извинение, двор/физкультура |
| [45. Кружок в присутствии](45-presence-talk.md) | 🔄 | Id участников и темы в кадре, протокол +1 |
| [45. Кружок в присутствии](45-presence-talk.md) | | Id участников и темы в кадре, протокол +1 |
44 и 45 стоят на 42, можно параллельно.
+13 -2
View File
@@ -1,4 +1,4 @@
# Wire protocol v8
# Wire protocol v9
The client talks to the server two ways:
@@ -316,6 +316,9 @@ grid fetches `GET .../timetable?classId=` with it.
`activity` is the ActionDef name currently in progress, or `null` when idle. `activityLabel`
is that def in the request locale. HTTP JSON is additive — no protocol version bump.
`talkCircleMemberIds` is the live circle (including self, sorted) or `[]`; `talkTopicId` is the
topic def id or `null` when not talking. Same ids as the presence frame; names are not repeated
here either — the Now tab uses the directory and locale, like the location panel.
`skills` lists only keys the person has, not every `SkillDef` in the catalog. A first-year has
no Chemistry; a related tongue from the name set may sit beside the native at a low value.
@@ -358,6 +361,8 @@ compute thresholds. There is no school-wide opinions endpoint.
"needs": [{ "id": "Sleep", "label": "Сон", "value": 1 }],
"activity": null,
"activityLabel": null,
"talkCircleMemberIds": [],
"talkTopicId": null,
"family": {
"parents": [{ "id": "f0.p1", "fullName": "Иванова Ольга Михайловна", "female": true }],
"children": [],
@@ -983,6 +988,12 @@ Each person:
| string | person id |
| string | node id they occupy |
| `u8` | `1` here, `2` walking |
| `u8` | talk-circle member count, then that many person-id strings |
| string | topic id (empty when not in a circle) |
Member ids are the live circle, including self, sorted by id. Count `0` and an empty topic mean
the person is not talking — the same id/node/state as before the circle fields. Names are not
on this frame; the client builds «говорит с Машей о футболе» from the HTTP directory and locale.
## Guarantees and limits
@@ -997,7 +1008,7 @@ Each person:
the oldest, because a stale clock is worthless once a newer one exists.
- The map snapshot and presence use a separate reliable queue so ticks cannot crowd them out.
## Not in v8 yet
## Not in v9 yet
Authentication, Sit orders, an event log, walk animation, and `OpenLocation` on the server —
the tree and the location panel are filtered on the client from the snapshot plus presence.