diff --git a/generate_pdf.py b/generate_pdf.py index b198fe2..d70a3e3 100644 --- a/generate_pdf.py +++ b/generate_pdf.py @@ -139,6 +139,84 @@ class HotWeatherBriefingPDF(FPDF): def _measure_lines(self, w, line_h, text): return len(self.multi_cell(w, line_h, text, dry_run=True, output="LINES")) + def draw_card(self, emoji, title, text, x, y, w): + """Draw a single card with emoji, title and body text.""" + pad = 8 + # Calculate card height + self.set_font("DejaVu", "B", 10) + title_h = 6 + self.set_font("DejaVu", "", 9) + n_lines = self._measure_lines(w - 2 * pad, 4.5, text) + body_h = n_lines * 4.5 + 4 + card_h = pad + 12 + title_h + body_h + pad # emoji + title + body + padding + + # Card background + self.set_fill_color(*self.c["white"]) + self.set_draw_color(*self.c["gray_bg"]) + self.set_line_width(0.3) + self.rect(x, y, w, card_h, "DF") + + # Emoji + self.set_xy(x + pad, y + pad) + self.set_font("DejaVu", "", 20) + self.cell(20, 12, emoji) + + # Title + self.set_xy(x + pad, y + pad + 12) + self.set_font("DejaVu", "B", 10) + self.set_text_color(*self.c["ink"]) + self.cell(w - 2 * pad, title_h, title) + + # Body + self.set_xy(x + pad, y + pad + 12 + title_h + 2) + self.set_font("DejaVu", "", 9) + self.set_text_color(*self.c["gray"]) + self.multi_cell(w - 2 * pad, 4.5, text, align="L") + + return card_h + + def draw_cards_row(self, cards, y, card_w=None): + """Draw 3 cards in a row. cards = list of (emoji, title, text).""" + n = len(cards) + gap = 12 + avail_w = self.w - self.l_margin - self.r_margin + if card_w is None: + card_w = (avail_w - gap * (n - 1)) / n + for i, (emoji, title, text) in enumerate(cards): + x = self.l_margin + i * (card_w + gap) + self.draw_card(emoji, title, text, x, y, card_w) + # Return max height + max_h = 0 + for emoji, title, text in cards: + pad = 8 + self.set_font("DejaVu", "", 9) + n_lines = self._measure_lines(card_w - 2 * pad, 4.5, text) + body_h = n_lines * 4.5 + 4 + card_h = pad + 12 + 6 + body_h + pad + if card_h > max_h: + max_h = card_h + return max_h + + def draw_cards_2x2(self, cards, y): + """Draw 4 cards in a 2x2 grid. cards = list of (emoji, title, text).""" + gap = 12 + avail_w = self.w - self.l_margin - self.r_margin + card_w = (avail_w - gap) / 2 + max_h = 0 + for row in range(2): + for col in range(2): + idx = row * 2 + col + if idx < len(cards): + emoji, title, text = cards[idx] + x = self.l_margin + col * (card_w + gap) + cy = y + row * (max_h + gap if max_h > 0 else 0) + h = self.draw_card(emoji, title, text, x, cy, card_w) + if row == 0 and col == 0: + max_h = h + elif h > max_h: + max_h = h + return max_h * 2 + gap + def build(): pdf = HotWeatherBriefingPDF() @@ -213,7 +291,17 @@ def build(): pdf.cell(col1_w, 7, " " + outdoor, border=1, fill=True) pdf.cell(col2_w, 7, " " + cabin, border=1, fill=True) pdf.cell(col3_w, 7, " " + risk, border=1, fill=True, new_x="LMARGIN", new_y="NEXT") - pdf.ln(4) + pdf.ln(6) + + # Карточки рисков + cards_risk = [ + ("T", "Тепловой удар", "Потеря сознания, спутанность сознания, судороги. Риск ДТП \u2014 100%."), + ("\u2022", "Обезвоживание", "Снижение концентрации внимания, замедление реакции, головокружение."), + ("Z", "Гиперсомния", "Повышенная сонливость, \u00abмикрозасыпания\u00bb за рулём \u2014 основная причина лобовых столкновений."), + ] + y_cards = pdf.get_y() + cards_h = pdf.draw_cards_row(cards_risk, y_cards) + pdf.set_y(y_cards + cards_h + 4) # ══ 4. ДО ВЫЕЗДА НА ЛИНИЮ ══ pdf.section_title("4. Действия до выезда на линию") @@ -269,21 +357,20 @@ def build(): # ══ 6. ОСОБЫЕ ТРЕБОВАНИЯ ══ pdf.section_title("6. Особые требования") - pdf.sub_title("Режим работы в жару") - pdf.body_text( - "Выезд на линию — не ранее 6:00. Возвращение — не позднее 18:00. " - "В период с 12:00 до 15:00 — обязательный перерыв в тенистом месте (не менее 30 минут)." - ) - pdf.sub_title("Запреты") - pdf.body_text( - "Запрещается: оставлять детей в ТС, оставлять ТС с работающим двигателем " - "без присмотра, перевозить легковоспламеняющиеся жидкости без охлаждения." - ) - pdf.sub_title("Взаимный контроль") - pdf.body_text( - "Водители обязаны проверять состояние здоровья коллег при встрече. " - "При признаках недомогания у коллеги — оказать помощь и сообщить диспетчеру." - ) + + cards_special = [ + ("\u25b6", "Режим работы в жару", + "Выезд на линию \u2014 не ранее 6:00. Возвращение \u2014 не позднее 18:00. В период с 12:00 до 15:00 \u2014 обязательный перерыв в тенистом месте (не менее 30 минут)."), + ("\u2716", "Запреты", + "Запрещается: оставлять детей в ТС, оставлять ТС с работающим двигателем без присмотра, перевозить легковоспламеняющиеся жидкости без охлаждения."), + ("\u25cb", "Охлаждение", + "Допускается использование portative вентиляторов от прикуривателя, охлаждающих бандажей, бутылок с замороженной водой."), + ("\u25a1", "Взаимный контроль", + "Водители обязаны проверять состояние здоровья коллег при встрече. При признаках недомогания у коллеги \u2014 оказать помощь и сообщить диспетчеру."), + ] + y_cards6 = pdf.get_y() + cards_h6 = pdf.draw_cards_2x2(cards_special, y_cards6) + pdf.set_y(y_cards6 + cards_h6 + 4) # ══ 7. ЧЕК-ЛИСТ ══ pdf.section_title("7. Чек-лист перед выездом") diff --git a/Инструктаж_Действия_жаркий_период_ТС_без_кондиционера.pdf b/Инструктаж_Действия_жаркий_период_ТС_без_кондиционера.pdf index e67b60a..ca28d93 100644 Binary files a/Инструктаж_Действия_жаркий_период_ТС_без_кондиционера.pdf and b/Инструктаж_Действия_жаркий_период_ТС_без_кондиционера.pdf differ