полнота точки — множество ключей, победитель — функция множества точек
- отношение победы было нетранзитивным: полнота (частичный порядок) плюс тай-брейк (тотальный) в попарной свёртке давали цикл, из-за которого одна и та же доставка меняла содержимое объекта при каждой пересборке - надмножество побеждает только при совпадении значений общих содержательных ключей: иначе точка без единого измерения вытесняла измерение - Less стал тотальным, isEmpty не материализует значение, имя метрики в координате столкновения обрезается, отпечаток витрины включает units и sealed - на живом архиве строгий no-op: 1737 объектов, содержимое совпало побайтово
This commit is contained in:
+54
-2
@@ -29,6 +29,8 @@ healthlog принимает выгрузки Apple Health из приложен
|
||||
нестабилен. Хеш канонизированного содержимого остаётся детектором изменений,
|
||||
чтобы не писать зря. При столкновении выигрывает более полная точка, а не
|
||||
последняя пришедшая: бедная доставка не должна стирать поля у богатой.
|
||||
Полнота — **множество** ключей с непустым значением, а не их число (см.
|
||||
«Разрешение столкновений»).
|
||||
- **Дыры закрываются сами.** Данные приходят несколькими проходами разной
|
||||
глубины, поэтому пропущенная доставка не оставляет постоянного пробела —
|
||||
см. «Модель синхронизации».
|
||||
@@ -193,8 +195,10 @@ HRV); у накопительных — только `date`. Поэтому то
|
||||
доставку. Вместо этого редкий широкий проход **только по ручным секциям**: их
|
||||
единицы записей, и месячное окно там почти ничего не стоит.
|
||||
|
||||
Последние пришедшие данные всегда актуализируют картину — правило слияния
|
||||
одинаково для всех проходов, порядок прихода значения не имеет.
|
||||
Правило слияния одинаково для всех проходов, и порядок прихода значения не
|
||||
имеет. Но «последние данные всегда актуализируют картину» — неверно и никогда
|
||||
не было верным: при столкновении выигрывает более полная точка, а не последняя
|
||||
пришедшая (см. «Разрешение столкновений»).
|
||||
|
||||
Автоматизации различимы по заголовку `automation-id`; имена стоит задать,
|
||||
иначе `automation-name` приходит пустым (находка 12).
|
||||
@@ -535,6 +539,54 @@ hour метки выровнены на час heart_rate 00:00:00
|
||||
`WARN` и всё равно сохраняем. Так мы узнаём реальную глубину досчёта из
|
||||
эксплуатации, а не из предположений.
|
||||
|
||||
#### Разрешение столкновений
|
||||
|
||||
По одним координатам приезжают разные содержимые: 2 897 случаев из 444 256
|
||||
координат, 0.65% (находка 49). Выигрывает **более полная** точка, и полнота —
|
||||
это сравнение **множеств** ключей с непустым значением, а не их числа.
|
||||
|
||||
Число сравнимо всегда и потому отвечает там, где ответа нет: точка
|
||||
`{"qty":0,"a":0,"b":0,"c":{},"d":[]}` несла «пять значащих полей» против двух у
|
||||
настоящего измерения и стирала его безвозвратно. Множества дают три исхода
|
||||
вместо одного — надмножество, равенство, несравнимость, — и только первый
|
||||
означает «полнее».
|
||||
|
||||
Пусто — `null`, пустая строка, нулевое число, пустой объект и пустой массив;
|
||||
`false` содержателен (`isIndoor: false` — тренировка на улице). Считается по
|
||||
разобранному значению, а не по байтам: иначе `0.0` и `{ }` прошли бы как
|
||||
содержание. `source` не участвует — он нестабилен.
|
||||
|
||||
Надмножество побеждает только тогда, когда **несёт то же содержание**: значения
|
||||
общих содержательных ключей должны совпасть. Иначе точки несут разные
|
||||
измерения, и надмножество имён о полноте не говорит ничего — пара уходит в
|
||||
тай-брейк. Без этого условия `{date, qty:0.001, p1:null, p2:null}` вытесняло бы
|
||||
`{date, qty:72.5}`, то есть точка без единого измерения стирала бы измерение.
|
||||
|
||||
Разрядов сравнения два: сперва ключи с содержанием, при их равенстве (и
|
||||
совпадении значений) — все ключи. Второй разряд бережёт поля, которые не несут
|
||||
содержания, но и теряться не должны: `{date, qty:10, Min:0, Max:0}` не
|
||||
проигрывает `{date, qty:10}` по жребию. Несравнимость на втором разряде исходом
|
||||
не является: лишние ключи там заведомо пусты, объединять в них нечего.
|
||||
|
||||
**Победитель — функция множества точек, а не порядка их поступления.** Попарная
|
||||
свёртка этого не даёт: полнота — частичный порядок, тай-брейк — тотальный, и
|
||||
вместе они образуют нетранзитивное отношение победы, то есть цикл. При цикле
|
||||
повторная свёртка одной и той же доставки меняет содержимое объекта, и витрина
|
||||
перестаёт быть свёрткой журнала. Поэтому кандидаты координаты собираются
|
||||
вместе: отбрасываются превзойдённые по полноте, среди оставшихся берётся
|
||||
минимум по каноническому порядку. Обе операции зависят только от состава
|
||||
множества.
|
||||
|
||||
**Несравнимые множества не сливаются, а считаются.** Объединение полей — самая
|
||||
дорогая часть правила — на живом потоке не потребовалось ни разу (0 из 2 897),
|
||||
поэтому вместо реализации стоит счётчик и `WARN` с координатами объекта. Если
|
||||
событие наступит, оно будет видно, а не додумано заранее.
|
||||
|
||||
**Тай-брейк при равной полноте не выбран.** Сегодня это порядок канонических
|
||||
форм, и он измеримо смещён: в 96% случаев берёт меньшее значение. Правильный
|
||||
выбор зависит от рода метрики, а род измеряется сверкой слоёв между собой —
|
||||
значит он и станет известен точно, вместо того чтобы быть угаданным.
|
||||
|
||||
### Категориальные значения
|
||||
|
||||
HAE отдаёт перечислимые значения строками из локали телефона, а не кодами:
|
||||
|
||||
Reference in New Issue
Block a user