Go to file
2023-08-06 00:56:49 +03:00
app optional feature for source 2023-08-05 23:26:45 +03:00
lib add async reader stream 2023-08-06 00:56:49 +03:00
.drone.yml fix publish 2 2023-03-29 13:46:21 +03:00
.gitignore new db file rename 2023-01-03 23:52:50 +03:00
bench.txt db::read -- io::Cursor instead of take 2022-11-09 21:31:38 +03:00
Cargo.lock add sync/async features 2023-08-05 23:06:55 +03:00
Cargo.toml add sync/async features 2023-08-05 23:06:55 +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.

Ссылки