87 lines
5.2 KiB
Python
87 lines
5.2 KiB
Python
"""План генерации данных стенда: сколько чего создать на заданном масштабе.
|
||
|
||
Обоснование чисел масштаба 1
|
||
----------------------------
|
||
* Размер листа складывается из шаблонных строк (дерево статей из сида, создаётся самой БД)
|
||
и добавленных строк (`extra_lines_per_sheet`, POST .../line). Шаблон у FORM_2/AHR — 566 строк,
|
||
у FORM_1/AHR — 522, у FORM_4/STRUCTURE — 775 (+ программы, проекты и все строки AHR/CAP/OPER).
|
||
`extra_lines_per_sheet = 500` даёт у `rf` лист FORM_2/AHR ~1090 строк (требование: самый
|
||
большой лист rf >= 1000). Строки раскладываются по листьям дерева статей по кругу, так что
|
||
покрыто всё дерево. На листах FORM_4 строк в 5 раз меньше (FORM4_LINES_DIVISOR, причина ниже);
|
||
лист FORM_4/STRUCTURE содержит 775 строк шаблона и от числа добавленных строк не зависит.
|
||
* Формы: FORM_1 — по ССП, FORM_2 — по ССП и РФ (свод 2 «РФ» читает именно FORM_2 РФ),
|
||
FORM_4 — по РФ. 3 ССП и 6 РФ: в сводах 1 и 2 несколько организаций с правдоподобным
|
||
разбросом, а объём остаётся таким, чтобы полная генерация шла десятки минут, а не часы
|
||
(каждый add_line/PATCH — отдельный запрос, добавление строки ~0.05-0.15 с и растёт с размером листа).
|
||
* `vsp_per_rf = 30`: ВСП на РФ; на каждый ВСП по одной строке на сателлитных листах FORM_2
|
||
(AHR_RENT/UTILITY/SECURITY) и источник `vsp_id` для строк FORM_4.
|
||
* `projects_per_rf = 4`: проекты FORM_3 (по 2 отчёта LIMIT/CURRENT_EXPENSES за 2026, у половины
|
||
ещё 2027), по 616 строк в отчёте каждого — отчёт проекта тоже >1000 строк с шаблоном.
|
||
* `fill_ratio = 0.6`: доля строк, в которые записаны значения; остальные пустые, как в жизни.
|
||
* Масштаб 2 удваивает org_units_rf, vsp_per_rf, extra_lines_per_sheet, projects_per_rf (и
|
||
org_units_ssp, чтобы своды росли по обеим осям); объём строк растёт ~4x, а время генерации
|
||
~4-5x, а не 2x: число организаций и число строк на лист удваиваются одновременно, плюс add_line
|
||
на вдвое больших листах медленнее. Замер масштаба 1 и оценка масштаба 2 — в отчёте задачи.
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
from dataclasses import dataclass
|
||
|
||
YEAR = 2026
|
||
PROGRAMS_PER_SHEET = 2 # FORM_4: программ на каждый лист AHR/CAP/OPER формы
|
||
PROJECTS_PER_PROGRAM = 3 # FORM_4: проектов на программу
|
||
PASSWORD = "perf"
|
||
# FORM_4: добавление строки и правка ячеек стоят O(число строк листа) на стороне БД (замер: add_line
|
||
# 0.2 с на пустом листе -> 1.6 с на 300 строках; батч из 200 ячеек 9-11 с), тогда как у FORM_1/2
|
||
# 0.05-0.15 с при 500. Поэтому на листах FORM_4 строк в DIVISOR раз меньше; размер самого большого
|
||
# листа rf (>= 1000) даёт FORM_2/AHR, а не FORM_4. Находка по приложению, см. отчёт.
|
||
FORM4_LINES_DIVISOR = 5
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class GenPlan:
|
||
org_units_ssp: int
|
||
org_units_rf: int
|
||
vsp_per_rf: int
|
||
extra_lines_per_sheet: int
|
||
projects_per_rf: int
|
||
fill_ratio: float
|
||
|
||
def lines_per_sheet(self, form_type: str) -> int:
|
||
"""Сколько строк добавляется на каждый лист (AHR/CAP/OPER) формы данного типа."""
|
||
n = self.extra_lines_per_sheet
|
||
return n // FORM4_LINES_DIVISOR if form_type == "FORM_4" else n
|
||
|
||
@property
|
||
def forms_form1(self) -> int:
|
||
return self.org_units_ssp
|
||
|
||
@property
|
||
def forms_form2(self) -> int:
|
||
return self.org_units_ssp + self.org_units_rf
|
||
|
||
@property
|
||
def forms_form4(self) -> int:
|
||
return self.org_units_rf
|
||
|
||
@property
|
||
def programs(self) -> int:
|
||
return self.org_units_rf * 3 * PROGRAMS_PER_SHEET
|
||
|
||
@property
|
||
def form4_projects(self) -> int:
|
||
return self.programs * PROJECTS_PER_PROGRAM
|
||
|
||
|
||
def plan_for_scale(scale: int) -> GenPlan:
|
||
if not isinstance(scale, int) or scale < 1:
|
||
raise ValueError(f"scale должен быть целым >= 1, получено {scale!r}")
|
||
return GenPlan(
|
||
org_units_ssp=3 * scale,
|
||
org_units_rf=6 * scale,
|
||
vsp_per_rf=30 * scale,
|
||
extra_lines_per_sheet=500 * scale,
|
||
projects_per_rf=4 * scale,
|
||
fill_ratio=0.6,
|
||
)
|