Go to file
Dmitry 6a21543890
All checks were successful
continuous-integration/drone/push Build is passing
Merge branch 'master' into postcard_custom
2023-08-25 15:33:01 +03:00
app Merge branch 'master' into postcard_custom 2023-08-25 15:33:01 +03:00
app_async Merge branch 'master' into postcard_custom 2023-08-25 15:33:01 +03:00
lib add impl Deserializer for Question 2023-08-25 12:26:36 +03:00
.drone.yml ci: publish lib with all features 2023-08-18 09:33:42 +03:00
.gitignore deps: add insta for tests 2023-08-12 21:42:14 +03:00
bench.txt db::read -- io::Cursor instead of take 2022-11-09 21:31:38 +03:00
Cargo.lock add manual impl Serialize for BatchInfo 2023-08-24 13:34:29 +03:00
Cargo.toml add app_async 2023-08-07 22:06:21 +03:00
LICENSE add LICENSE 2022-10-02 17:40:27 +03:00
README.md data format in README 2022-10-08 15:39:54 +03:00

chgk_ledb

Утилита загружающая базу данных ЧГК вопросов из ZIP файла в JSON формате в базу данных.

Исходный файл вопросов: json.zip, кодировка UTF-8.

При загрузке базы информация о пакете(файле/турнире) дублируется в каждом вопросе.

Выходной формат данных

Для хранения данных используется bincode и zstd. Данные вопросов в виде структуры сериализуются через bincode в бинарные данные и сжимаются zstd. Каждый вопрос сериализуется и сжимается отдельно. В файле сжатые данные храняться последовательно, после заголовка файла.

Заголовок файла

В заголовке хранятся только смещения каждого сжатого блока данных, и дополнительно, смещение указывающее на конец файла. Смещение указывается в виде 32-битного беззнакового целового числа u32, сохраненного в виде 4-х байтов от младшего к старшему (Little Endian).

Пример заголовка:

00:  10 00 00 00
04:  1A 00 00 00
08:  2E 00 00 00
0А:  3A 00 00 00

данные:

10:  00 00 00 00 00 00 00 00 00 00
1A:  00 00 00 00 00 00 00 00 00 00
     00 00 00 00 00 00 00 00 00 00
2E:  00 00 00 00 00 00 00 00 00 00
     00 00
3A:  (EOF)

В этом примере сохранены 3 записи:

  1. смещение 0x10, длина 10 байт
  2. смещение 0x1A, длина 20 байт
  3. смещение 0x2E, длина 12 байт

Размер файла - 58 байт (0x3A), размер заголовка 16 байт (0x10).

Чтение данных

Пусть размер записи заголовка в байтах = M, количество записей в файле = N.

Тогда для того чтобы:

  • Найти N, нужно прочитать первую запись (M байт) в начале файла и разделить её значение на M;
  • Найти элемент данных с индексом i, нужно последовательно прочитать 2 записи (M * 2 байт), начиная c индекса i (по смещению в файле: i * M). Смещением будет значение по индексу i, длинной - разница между значениями по индексам i + 1 и i.

Далее для каждого вопроса отдельно предполагается распаковка данных через zstd и десериализация через bincode.

Ссылки