diff --git a/src/charts/chart2.js b/src/charts/chart2.js
index 9ec232c..a267731 100644
--- a/src/charts/chart2.js
+++ b/src/charts/chart2.js
@@ -1,101 +1,65 @@
/**
- * Chart 2 — Горизонтальные бары лидеров (переработчики / производители / регионы).
- *
- * Универсальный ranked-barchart: сортировка по убыванию, подпись значения справа,
- * опциональная подсветка субъекта отчёта и опциональные категории (легенда).
- *
- * Параметры:
- * items: [{ name, value, category?, isHighlight? }]
- * regionLabel: string
- * unit: string — единица измерения (по умолчанию 'руб./кг')
- * categories: { ключ: { color, label } } — опционально, для легенды/окраски
- * highlightName: string — имя строки для подсветки (альтернатива isHighlight)
- * sort: bool — сортировать по убыванию (по умолчанию true)
- * width: number
+ * Chart 2 — Горизонтальные бары лидеров.
+ * Все бары красные. Значение справа от бара жирным тем же цветом.
+ * Под заголовком — подзаголовок (unit).
*/
const sharp = require('sharp')
const { PALETTE } = require('../data/palette')
-const { red: RED, dark: DARK, mdGray: MDGRAY, ltGray: LTGRAY, grid: GRID,
- green: GREEN, orange: ORANGE, o: O } = PALETTE
+const { red: RED, dark: DARK, mdGray: MDGRAY, ltGray: LTGRAY, grid: GRID } = PALETTE
function esc (s) { return String(s).replace(/&/g,'&').replace(//g,'>') }
-async function chart2_leaders ({
- items, regionLabel, unit = 'руб./кг',
- categories = null, highlightName = null, sort = true,
- width = 920
-}) {
- const rows = (sort ? [...items].sort((a,b) => b.value - a.value) : [...items])
-
+/**
+ * items: [{ name: string, value: number }]
+ * title: string — заголовок панели
+ * unit: string — единица измерения (в подзаголовке)
+ * regionLabel: string
+ */
+async function chart2_leaders ({ items, title, unit = 'млн руб.', regionLabel, width = 920 }) {
+ const sorted = [...items].sort((a, b) => b.value - a.value)
const W = width
- const rowH = 26, gap = 8
- const PT = 24, PB = 36
- const H = PT + PB + rows.length * (rowH + gap)
-
- // место под подписи имён слева
- const PL = 200, PR = 70
+ const ROW_H = 36 // высота одной строки
+ const PL = 200, PR = 100 // отступ слева (для лейблов), справа (для цифр)
+ const PT = 64, PB = 28
+ const H = PT + sorted.length * ROW_H + PB
const cW = W - PL - PR
- const maxV = Math.max(...rows.map(r => r.value), 0)
- const minV = Math.min(...rows.map(r => r.value), 0)
- // ось от 0 (или от minV если есть отрицательные)
- const axMin = Math.min(0, minV)
- const axMax = Math.ceil(maxV / 5) * 5 || maxV
- const xV = v => PL + (v - axMin) / (axMax - axMin) * cW
- const zeroX = xV(0)
+ const maxV = Math.max(...sorted.map(i => i.value)) * 1.1
+ const xV = v => (v / maxV) * cW
let svg = ''
- // вертикальные грид-линии + подписи оси X
- const step = (axMax - axMin) > 40 ? 10 : 5
- for (let v = Math.ceil(axMin / step) * step; v <= axMax; v += step) {
- const x = xV(v)
- svg += ``
- svg += `${v}`
- }
- svg += `${esc(unit)}`
+ // Заголовок панели
+ svg += `${esc(title)}`
+ svg += `${esc(unit)}`
- // бары
- rows.forEach((r, i) => {
- const y = PT + i * (rowH + gap)
- const hl = r.isHighlight || (highlightName && r.name === highlightName)
- let color = RED
- if (categories && r.category && categories[r.category]) color = categories[r.category].color
- if (hl) color = O
+ // Ось Y (вертикальная линия)
+ svg += ``
- const bx = r.value >= 0 ? zeroX : xV(r.value)
- const bw = Math.abs(xV(r.value) - zeroX)
+ sorted.forEach((item, i) => {
+ const y = PT + i * ROW_H
+ const bH = 18
+ const bY = y + (ROW_H - bH) / 2
+ const bW = xV(item.value)
- // подпись имени слева
- svg += `${esc(r.name)}`
- // бар
- svg += ``
- // значение справа от бара
- const vx = r.value >= 0 ? bx + bw + 6 : bx - 6
- const anchor = r.value >= 0 ? 'start' : 'end'
- svg += `${r.value.toFixed(1)}`
+ // Бар
+ svg += ``
+
+ // Лейбл слева
+ svg += `${esc(item.name)}`
+
+ // Значение справа от бара
+ const valX = PL + bW + 8
+ svg += `${item.value.toFixed(1)}`
})
- // нулевая/левая ось
- svg += ``
+ // Нижняя ось
+ svg += ``
+ // Подпись единиц снизу
+ svg += `${esc(unit)}`
- // легенда категорий (если заданы)
- let legendH = 0
- if (categories) {
- const keys = Object.keys(categories)
- legendH = 22
- const lx = PL
- keys.forEach((k, i) => {
- const cx = lx + i * 170
- const ly = PT + rows.length*(rowH+gap) + 30
- svg += ``
- svg += `${esc(categories[k].label)}`
- })
- }
-
- const totalH = H + legendH
- const fullSvg = `