разбор метрик HAE: фикстуры, канонизация, парсер

- tmp/research/fixtures.py собирает фикстуры из архива, вычищая измерения и
  сохраняя порядок ключей, форму литералов, выравнивание меток и невидимые
  символы; шесть фикстур в internal/hae/testdata
- internal/canon — общий дом канонической формы, полноты и хеша: числа читаются
  литералом через json.Number, округление до 12 значащих цифр
- internal/hae — разбор секции metrics, вывод слоя по метрике, разделение схем
  сна, координаты интервалом; recover внутри Parse, фаззинг
- миграция bucket и docs/database.md
This commit is contained in:
av
2026-08-01 17:31:41 +03:00
parent 3e93dd95b4
commit 01d0de59df
18 changed files with 3693 additions and 21 deletions
+78
View File
@@ -0,0 +1,78 @@
{
"_comment": "Рукотворная фикстура: случаи, которых живой поток не даёт. Скриптом tmp/research/fixtures.py не порождается. Значения выдуманы целиком.",
"data": {
"metrics": [
{
"name": "mixed_alignment",
"units": "count",
"data": [
{ "date": "2025-06-05 10:00:00 +0300", "qty": 1, "source": "Device A" },
{ "date": "2025-06-05 11:00:00 +0300", "qty": 2, "source": "Device A" },
{ "date": "2025-06-05 12:00:00 +0300", "qty": 3, "source": "Device A" },
{ "date": "2025-06-05 13:00:00 +0300", "qty": 4, "source": "Device A" },
{ "date": "2025-06-05 14:00:00 +0300", "qty": 5, "source": "Device A" },
{ "date": "2025-06-05 15:00:00 +0300", "qty": 6, "source": "Device A" },
{ "date": "2025-06-05 16:00:00 +0300", "qty": 7, "source": "Device A" },
{ "date": "2025-06-05 17:00:00 +0300", "qty": 8, "source": "Device A" },
{ "date": "2025-06-05 18:00:00 +0300", "qty": 9, "source": "Device A" },
{ "date": "2025-06-05 19:00:00 +0300", "qty": 10, "source": "Device A" },
{ "date": "2025-06-05 19:30:00 +0300", "qty": 11, "source": "Device A" }
]
},
{
"name": "unknown_shape",
"units": "widget",
"data": [
{
"date": "2025-06-05 10:00:00 +0300",
"qty": 1.0,
"hugeInteger": 9007199254740993,
"longFraction": 0.095231829624713534,
"inventedField": { "nested": ["значение", 42], "flag": true },
"source": "Device A"
}
]
},
{
"name": "broken_timestamps",
"units": "count",
"data": [
{ "date": "2025-06-05T10:00:00Z", "qty": 1, "source": "Device A" },
{ "date": "", "qty": 2, "source": "Device A" },
{ "qty": 3, "source": "Device A" },
{ "date": 1749110400, "qty": 4, "source": "Device A" }
]
},
{
"name": "interval_points",
"units": "hr",
"data": [
{
"date": "2025-06-05 22:04:00 +0300",
"start": "2025-06-05 22:04:00 +0300",
"end": "2025-06-05 22:16:00 +0300",
"qty": 0.2,
"value": "Во сне",
"source": "Device A"
},
{
"date": "2025-06-05 22:04:00 +0300",
"start": "2025-06-05 22:04:00 +0300",
"end": "2025-06-06 02:21:00 +0300",
"qty": 4.28,
"value": "В кровати",
"source": "Device A"
},
{
"date": "2025-06-05 22:04:00 +0300",
"start": "2025-06-05 22:04:00 +0300",
"end": "2025-06-06 07:51:00 +0300",
"qty": 9.78,
"value": "В кровати",
"source": "Device A"
}
]
}
]
}
}