From 6a2c0d0d359794d10a2680f20f74679b46e2d651 Mon Sep 17 00:00:00 2001 From: gkonoplya Date: Sat, 28 Feb 2026 12:59:56 +0300 Subject: [PATCH] Add new CLI command for file name extraction and hash generation - Implemented `get_filenames` command in `batch_extractor.py` to extract file names from a specified directory and generate a dated hash for each file. - Updated README.md with instructions for using the new command. - Enhanced PDF generation in `build_pdf.py` by modifying file naming conventions to include article and size. - Added example PowerShell script for batch processing tasks. - Introduced new example Excel file for user reference. --- README.md | 21 ++++++++++ batch_extractor.py | 27 +++++++++++++ build_pdf.py | 41 +++++++++++++------- resources/filenames_example.xlsx | Bin 0 -> 10045 bytes resources/run_task_example.ps1 | 30 ++++++++++++++ resources/ШАблон для загрузки этикеток.xlsx | Bin 13475 -> 22777 bytes 6 files changed, 104 insertions(+), 15 deletions(-) create mode 100644 resources/filenames_example.xlsx create mode 100644 resources/run_task_example.ps1 diff --git a/README.md b/README.md index 232b1e5..da7b3a6 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,27 @@ pip install -r requirements.txt Процесс разделен на три простых шага в терминале: +### ШАГ 0: Подготовить пакетнйы скрипт, если файлов больше чем 1. + +Нужно сохранить все файлы с КМ в одну папку. + +потом запустить команду, которая достанет имена файлов из этой директории: + +```bash +python batch_extractor.py get-filenames "C:\путь\к\архиву\" "C:\путь\к\временным файлам\filenames.xlsx" +``` + +эта команда создаст файл структуры Префикс/Имя файла + +затем надо открыть файл filenames_exaple.xlsx из папки resources и дополнить созданный файл формулами, которые создадут полную питон команду для экстракции КМ + +Затем открыть файл resources\run_task_example.ps1 - и вставить в него получившиеся команды + +### Важно!! Обратить внимание на тип файла, для pdf надо использовать команду from-pdf и аналогично для zip. Кроме того, обязательно надо заменить путь к файлам (он забит в формуле) + +потом можно запустить скрипт пакетной обработки. + + ### ШАГ 1: Извлечение кодов в Excel (Создание списка КМ) Возьмите файл, который вы скачали из системы «Честный ЗНАК», и натравите на него утилиту-экстрактор. diff --git a/batch_extractor.py b/batch_extractor.py index c876b8e..7ed7ab6 100644 --- a/batch_extractor.py +++ b/batch_extractor.py @@ -6,6 +6,23 @@ from read_image import read_datamatrix_zxing, extract_barcodes_from_pdf from pathlib import Path import click import render_eps +import hashlib +import random +from datetime import datetime + +def get_dated_hash(text: str) -> str: + """ + Генерирует хэш с префиксом даты в формате ГГ_ММ_ДД. + Пример вывода: 26_02_21_d6f7a6b2c1 + """ + # 1. Получаем текущую дату в формате ГГ_ММ_ДД (например, 26_02_21) + date_prefix = datetime.now().strftime("%y_%m_%d") + text = f"{text}_{random.randint(0,100000000)}" + # 2. Генерируем хэш-часть (SHA-256, 10 символов) + hash_part = hashlib.sha256(text.encode()).hexdigest()[:10] + + # 3. Соединяем через нижнее подчеркивание + return f"{date_prefix}_{hash_part}" def extract_eps_from_zip(zip_path: str) -> list: """ @@ -124,5 +141,15 @@ def from_pdf(input_pdf: Path, output_xlsx: Path): except Exception as e: click.secho(f"Ошибка при обработке PDF: {e}", fg="red") +@cli.command(help="Подготавливает excel с именами файлов в директории") +@click.argument('input_dir', type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path)) +@click.argument('output_xlsx', type=click.Path(dir_okay=False, writable=True, path_type=Path)) +def get_filenames(input_dir: Path, output_xlsx: Path): + # Используем .glob('*') или .iterdir() + filenames = [f.name for f in input_dir.iterdir() if f.is_file()] + filenames_with_hashes = [(get_dated_hash(f), f) for f in filenames] + save_to_excel(filenames_with_hashes, str(output_xlsx)) + + if __name__ == "__main__": cli() diff --git a/build_pdf.py b/build_pdf.py index 18b6e98..d4c42ca 100644 --- a/build_pdf.py +++ b/build_pdf.py @@ -17,6 +17,7 @@ from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT from read_image import read_datamatrix_zxing import render_eps import treepoem +import html import click from pathlib import Path @@ -184,7 +185,7 @@ def place_text(c: canvas.Canvas, text: str, font_name: str, while True: # Заменяем явные переносы на HTML-тег для ReportLab - text_for_pdf = current_text.replace('\n', '
') + text_for_pdf = html.escape(current_text) p = Paragraph(text_for_pdf, style) # Вычисляем реальные размеры @@ -262,13 +263,13 @@ def draw_label_page(c: canvas.Canvas, font_name: str, dm_image: ImageReader, lab eac_image_y = CHZ_image_y c.drawImage(load_png('resources/eac-conformity-mark-seeklogo.png'), eac_image_x, eac_image_y, width=eac_image_h, height=CHZ_image_h, mask='auto') - page_num_h = 2 * mm + page_num_h = 3 * mm page_num_y = CHZ_image_y - page_num_h - 0.3 * mm place_text(c, f'№ {label_data.page_num}', font_name, - x=img_x, y=page_num_y, width=10 * mm, height=page_num_h, - font_size=8, font_min = 3, font_type='bold', align='center') - #c.drawBoundary(c, img_x, page_num_y, width=10 * mm, height=page_num_h) + x=img_x, y=page_num_y, width=20 * mm, height=page_num_h, + font_size=8, font_min = 3, font_type='bold', align='left') + #c.drawBoundary(c, img_x, page_num_y, width=20 * mm, height=page_num_h) # Ниже на левой панели у вас останется место под логотипы ЧЗ, EAC и №1 # ... (резерв места от y=0 до y=10мм) @@ -295,28 +296,28 @@ def draw_label_page(c: canvas.Canvas, font_name: str, dm_image: ImageReader, lab ean_barcode_h += 0.5 # 5. Артикул (одна строка, жирно) - art_h = 2 * mm + art_h = 3 * mm art_y = ean_barcode_y + ean_barcode_h place_text(c, f"арт.: {label_data.article}", font_name, x=right_x, y=art_y, width=right_w, height=art_h, - font_size=5, font_type='bold', align='center') + font_size=7, font_type='bold', align='center') # 4. Размер (одна строка, жирно) - size_h = 2 * mm + size_h = 3 * mm size_y = art_y + art_h place_text(c, f"размер: {label_data.size}", font_name, x=right_x, y=size_y, width=right_w, height=size_h, - font_size=5, font_type='bold', align='center') + font_size=7, font_type='bold', align='center') # 3. Цвет (одна строка, жирно) - color_h = 2 * mm + color_h = 3 * mm color_y = size_y + size_h place_text(c, f"цвет: {label_data.color}", font_name, x=right_x, y=color_y, width=right_w, height=color_h, - font_size=5, font_type='bold', align='center') + font_size=7, font_type='bold', align='center') # 2. Описание (Крупно, жирно, центр, занимает всё среднее пространство) - desc_h = 16 * mm + desc_h = 13 * mm desc_y = color_y + color_h place_text(c, f"{label_data.description}", font_name, x=right_x, y=desc_y, width=right_w, height=desc_h, @@ -360,6 +361,7 @@ def process_batch(base64_codes: list[str], excel_path: str, output_dir: str): print(f"Ошибка парсинга кода {b64[:10]}... : {e}") font_name = init_pdf_font() + total_files = len(grouped_codes) # 3. Оркестрация: 1 GTIN = 1 Многостраничный PDF файл for search_key, raw_bytes_list in grouped_codes.items(): @@ -379,7 +381,7 @@ def process_batch(base64_codes: list[str], excel_path: str, output_dir: str): label_data = LabelData.from_excel_row(target_row) # 3.2. Создаем холст PDF для группы - pdf_path = os.path.join(output_dir, f"Labels_{search_key}.pdf") + pdf_path = os.path.join(output_dir, f"{label_data.article}_{label_data.size}_{search_key}.pdf") # Размер страницы 58х40 мм c = canvas.Canvas(pdf_path, pagesize=(58*mm, 40*mm)) @@ -398,9 +400,13 @@ def process_batch(base64_codes: list[str], excel_path: str, output_dir: str): # Рисуем страницу, передавая ПОЛНЫЙ КОД МАРКИРОВКИ вместо короткого search_key draw_label_page(c, font_name, dm_image, label_data, readable_km) + print(' ', end='\r') + print(f'Обработана страница {label_data.page_num} из {len(raw_bytes_list)}', end='\r') + # Сохраняем и закрываем сгенерированный PDF документ c.save() - print(f" -> Сохранен файл: {pdf_path}") + total_files -= 1 + click.echo(f" -> Сохранен файл: {pdf_path} \n Осталось {total_files}") @click.command(help="Генерирует PDF-этикетки на основе извлеченных Base64-кодов и Excel-шаблона.") @@ -455,4 +461,9 @@ def cli(codes_xlsx: Path, template_xlsx: Path, output_dir: Path): click.secho(f"Критическая ошибка при генерации PDF: {e}", fg="red") if __name__ == "__main__": - cli() \ No newline at end of file + cli() +# Left priamry for testing reasons! +# test_str = Path('c:/Python/CRPT/LabelExtractor/data/штучка_на_печать.xlsx') +# template_path = Path('c:/Python/CRPT/LabelExtractor/data/Шаблон для загрузки этикеток.xlsx') +# output_path = Path('c:/Python/CRPT/LabelExtractor/data/output/units') +# cli(test_str,template_path, output_path) \ No newline at end of file diff --git a/resources/filenames_example.xlsx b/resources/filenames_example.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..8b6844a77f94ac529bf910e8defa4e4dd902a9a5 GIT binary patch literal 10045 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 literal 0 HcmV?d00001 diff --git a/resources/run_task_example.ps1 b/resources/run_task_example.ps1 new file mode 100644 index 0000000..240853e --- /dev/null +++ b/resources/run_task_example.ps1 @@ -0,0 +1,30 @@ +# 1. Устанавливаем кодировку вывода (UTF8) +[Console]::OutputEncoding = [System.Text.Encoding]::UTF8 + +# 2. Переходим в корневую директорию проекта, где лежит batch_extractor.py +# Скрипт находится в \data\, поэтому поднимаемся на один уровень вверх +Set-Location "$PSScriptRoot\.." + +# 3. Активация виртуального окружения +& "c:/Python/CRPT/LabelExtractor/.venv/Scripts/Activate.ps1" + +Write-Host "--- Окружение активировано. Начинаю обработку файлов... ---" -ForegroundColor Green + +# 4. Список команд +# Используем '--' перед аргументами, если пути содержат сложные символы +python batch_extractor.py from-pdf "C:\Python\CRPT\LabelExtractor\data\тнск001, р. XL 110 шт_c090cb9d-02fa-412b-ac91-ed7446f48d6d_gtin_04639970975443_quantity_110.pdf" "C:\Python\CRPT\LabelExtractor\data\f\output\тнск001, р. XL _04639970975443_110.xlsx" +python batch_extractor.py from-pdf "C:\Python\CRPT\LabelExtractor\data\тнск001, р. XXL 20шт _c090cb9d-02fa-412b-ac91-ed7446f48d6d_gtin_04639970975450_quantity_20.pdf" "C:\Python\CRPT\LabelExtractor\data\f\output\тнск001, р. XXL _04639970975450_20.xlsx" +python batch_extractor.py from-pdf "C:\Python\CRPT\LabelExtractor\data\тнск002, р. M 20 шт_c090cb9d-02fa-412b-ac91-ed7446f48d6d_gtin_04639970975467_quantity_20.pdf" "C:\Python\CRPT\LabelExtractor\data\f\output\тнск002, р. M _04639970975467_20.xlsx" +python batch_extractor.py from-pdf "C:\Python\CRPT\LabelExtractor\data\тнск002, р. XL 90шт _c090cb9d-02fa-412b-ac91-ed7446f48d6d_gtin_04639970975481_quantity_90.pdf" "C:\Python\CRPT\LabelExtractor\data\f\output\тнск002, р. XL _04639970975481_90.xlsx" +python batch_extractor.py from-pdf "C:\Python\CRPT\LabelExtractor\data\тнск002, р. XXL 70шт_c090cb9d-02fa-412b-ac91-ed7446f48d6d_gtin_04639970975498_quantity_70.pdf" "C:\Python\CRPT\LabelExtractor\data\f\output\тнск002, р. XXL _04639970975498_70.xlsx" +python batch_extractor.py from-pdf "C:\Python\CRPT\LabelExtractor\data\тнск003, р. L 35шт_c090cb9d-02fa-412b-ac91-ed7446f48d6d_gtin_04639970975511_quantity_35.pdf" "C:\Python\CRPT\LabelExtractor\data\f\output\тнск003, р. L _04639970975511_35.xlsx" +python batch_extractor.py from-pdf "C:\Python\CRPT\LabelExtractor\data\тнск003, р. M 20 шт_c090cb9d-02fa-412b-ac91-ed7446f48d6d_gtin_04639970975504_quantity_20.pdf" "C:\Python\CRPT\LabelExtractor\data\f\output\тнск003, р. M _04639970975504_20.xlsx" +python batch_extractor.py from-pdf "C:\Python\CRPT\LabelExtractor\data\тнск003, р. XL 60 шт_c090cb9d-02fa-412b-ac91-ed7446f48d6d_gtin_04639970975528_quantity_60.pdf" "C:\Python\CRPT\LabelExtractor\data\f\output\тнск003, р. XL _04639970975528_60.xlsx" +python batch_extractor.py from-pdf "C:\Python\CRPT\LabelExtractor\data\тнск003, р. XXL 50 шт_c090cb9d-02fa-412b-ac91-ed7446f48d6d_gtin_04639970975535_quantity_50.pdf" "C:\Python\CRPT\LabelExtractor\data\f\output\тнск003, р. XXL _04639970975535_50.xlsx" +python batch_extractor.py from-pdf "C:\Python\CRPT\LabelExtractor\data\тнск004, р. L 10_a8f6b321-2601-4664-bcc0-fad7b529db76_gtin_04639970975559_quantity_10.pdf" "C:\Python\CRPT\LabelExtractor\data\f\output\тнск004, р. L _04639970975559_10.xlsx" +python batch_extractor.py from-pdf "C:\Python\CRPT\LabelExtractor\data\тнск004, р. M 5шт_c090cb9d-02fa-412b-ac91-ed7446f48d6d_gtin_04639970975542_quantity_5.pdf" "C:\Python\CRPT\LabelExtractor\data\f\output\тнск004, р. M _04639970975542_5.xlsx" +python batch_extractor.py from-pdf "C:\Python\CRPT\LabelExtractor\data\тнск004, р. XL 30шт _a8f6b321-2601-4664-bcc0-fad7b529db76_gtin_04639970975566_quantity_30.pdf" "C:\Python\CRPT\LabelExtractor\data\f\output\тнск004, р. XL _04639970975566_30.xlsx" +python batch_extractor.py from-pdf "C:\Python\CRPT\LabelExtractor\data\тнск004, р. XXL 20 шт_a8f6b321-2601-4664-bcc0-fad7b529db76_gtin_04639970975573_quantity_20.pdf" "C:\Python\CRPT\LabelExtractor\data\f\output\тнск004, р. XXL _04639970975573_20.xlsx" + + +Write-Host "--- Все задачи выполнены успешно! ---" -ForegroundColor Cyan \ No newline at end of file diff --git a/resources/ШАблон для загрузки этикеток.xlsx b/resources/ШАблон для загрузки этикеток.xlsx index 80c51d1a9eeea8ee6849be236bae32d892dd5bc2..53c240c93929a54a85689088ed3b3b3d65b360ae 100644 GIT binary patch delta 17313 zcmZ_01y~$S^Dl}!!QI{6CAb7z+}+(h5C#Yq+}+(Bf&_OD4#C}n6P!!l_kYiK&UfzJ zXZIPa{Z(~Ub@lXA^%Ph?)PdtF$w5M4g28~nfq{XMfqiI_k&Xrj1H*%$JZP*OJnN*M;i2DepK1nuIOmz!V5r)Jg7Qa^|lCPAM1 zV6$7{xK^R3@@zA3o$GgVdxUlqK+#A_L!EZL);jPkqK1tTT)rHEAKfipch3u~6KT}rbn@=ZA z7g5U(!j~D0vwWXOeP0Q2~cvo+jqo%uufDePh9LOWRyVA7+&2 z=|M8l6=N1m)h z0$JmYKipI#GFQMb#Y_c^vH55*CAEyFfU%X}?J07VGVTF&vt2B*AqRM=9iqjJ#urVS zp`2DX`_x+et@I^q3>7XtEZ{n8@j`VZ*7RbIdbNDFJ>H)}Mu#b|*j5`%76i1leHc%` zLKu6rcw)%v5SHB60K4zJoPRS6Vdy&7WNN*xMc z8(x*X9&Q2DmainQ$IY)BOp3!mhIM2(_acmcGsGq=Y%X|hsxPm5X@o+PqqrIiXNPEo zM2B$A9jNrOOb=d3>qE^qQrh z+E!hDgJs&*Y7v9J{*L+mP1qBf)f`mtoy-#b`5YEl+`MM<3xX5LOwbR!>lrBJVldgy zU3SGxr*&cyuTwIj4_S1^TKVZa@SU-bE4KQn`W8OYI2j|wYhYI23EEAQn>3zA4)TY! zM(lp2l}qkr<(W|Up|EXwlVY!t@}L8qwk9lISYBgmfuu@xd%ekbv!kO4D}9!=>7bHa z@`g14T-*M@kMu?ey0dh?P6CEa|KfObsyGii{dbyd=|h}}mQ=1+vpqwexipjRteaVG zddz2uQsxwq%HKu#$@gP9EI`NW<0C=f3}dXENYtLj z--F$gw{kJG%Z-){Q72ZS5Kn|K%A?UDqjDHvu|&fv!!U|IXdx$mGRcf0$R>?Wq=rX} ziCSIJy;=+QnRa3B>|#A-xP`;VyuZ`w4iA+_*SBwu;#|W{47hY3I3ack4eW}`Yqg)? z#$>V!Smkf7c8g4|zL&}kwGcoOo5FO#I8V6-)Gqmhv-XWK8Od}Xg0}9#vsEv;U_St8 z9ubs~okM0H8+NRja;+rb`UC6~E(JefafInu5J3A`Nx|0lJ`V`kT1i(aVvK7l`AV#n z4MkfOteyI~)MYJ6-Yd{KO9il+c|LA%NB2BNX14OReRM4VI8u=&SAB>;7M|0s8EXMJ zEeGeG(iDFVWbRd6gC8YB9Uz&1=@i4*P$aAigC!UzN@$Lr;Wa~OJXAVE~F zpA|LuJn)Tde63jD9c|eSCA@Z1W|0JS#+o3VnhL}H=^Pnrg_-eoX2(Z--Ivw7{iTfS z6!D|ACA66g0#cPraC4G>%+A;ZBrC!U_6%AdvGg)V= zK{bczmyRbNO#xu4wvhRMi8uw4LWudC#jzLBST)|!R;_t`N) z!8O0Oa=m%`KWi}?ckSyboWk}EeU0ZxQoxJBXDv&`mA>o7x3Q^+4CgLSdX3PMd1isa z*;n1q$8TP5L&B?HCa$JRQaG7DcRTSaJh4bR{~-FHc#`7Q#gANX`q_WOuHLtcelzFc z`oe8|c3$lg83`WE;1tzqtrGk%5o+Y_OWnCX;?o)r*-z~^ORMN6Rh zD;#D{bG!YeM*N-6)9u;Qfp~I_(Aj2N7vHPR+Ea2L!2Eok)lMgD z`SI-giJ*Xah6&iX_(u!BhlDM&79GRX`&-><-d9$|F1vXs4Yl9y;x2)RDY|jqn(@In z>{Ob5Pi`u+vB{%G>&s_(&!e_ac^D-ds&@}`V?qp@KKE8oi9_>b zXB{7jjgw2h;Ht(E2^VINgFFQeyHOrH=G&J1WB`cO#y2{KaJw3?B1FuKX=-4~PYz{| zbhLBs5VH(^fij)zLr($djgCdM$@sZ%40>+mAVNFw!?o(Vk1S8cqCT2sJ7AX+o?;EK zJ7o^zNwdm7uWdBc0HE(vEKXd}!WWx3MSSZ*9aKlw$gkijAK}z;PV8Wbx;HvrG#>a; z{~Tv5$RxCHk>0#?yXqP7VF8Y#``}G}9|K@`!C=!kVR1i=fD3n#hYI6L?~Kqk?)&r6 z@@>+%K)rU~`YP%d&eQsu`R5!cN5U$5VULDGKGI8r3r`V}l^#Le;h>X4KMSfxwjtn? z!9GiTaMV+1olg>}UAV^oydxWzzNM#?NMut$Tg9f0Rq@m=`1I>5EfjF=2T>7{`g^t4 z=;x1I^&fVNIhJYcJj-)|ahF4|Il2sku#)f_fg~4u7{1SYer`O^`7i;ocw(zF!*eMn zcQU;~X$^|lrwQgS31oUZdtyCq%fZpc`zJV;0-B#&*$3Fp`ZiJ!U5A6MgAjNQS%bbt;E7*M}J32D<^6fD1J-^=+fk> zQVB@#;0N}FU5E@uY;X-txv*rgFg)@0pDTDmmE=r|fHWqyB{bzC%t z^ATsUHovjRO|?H{eLRSk#IA5wrjd*Y-k3wW8?_|*9W6^lLJ)|Sa6j^mk7o)3Z@u~L zkIQgW&45Cf?f5iq42|Tfm4P67IBq&~i60EE(I~j!zJ=hSclBGgolKaah_LSquYofcTffnCML}RAR?jd|P z=wM4I!W|-HfIrGQ4)p0U%?*E+@C1t3Bje{kGLR5v$2>LG;;@2Oo&M8s#$1L^pVU&A zbLD_fz5ZHKk?&+`cfP^%mp=rJ>OkGKS|w~uGw>4f?|{kC*B6Oergnv{H5JsOHF0~C z_$QP|QSM>Z$sqFl8M0z!{(w-XSkl3FVawrDX!gOQ+|fe@`TH9`(YOs3&Zb%%1=$2L zmDolmxfQ0P{<)lt=%@w_sb^_2#mt@om{9W#d+;3G3TE_DnS5wrVkXP3{c~6mVdaPc zp~1ZUT69w3VHN{!+>Z2vch+8`!g+F()q{<+gWpa5`dO zwB-h+ViRE8QKxEN$p$b`t06E(FP}5C6so*Kmi!7aLDT=vh&QsZ5VmgvXA>vCltJ1t z5jX54mtG-5kzbJ#R_7v@gr-Z72Fg(wS(=DH*qRKJXkVJo#U9~R9j1I&!3ZzP*z~)- z;^Rhhmq*>g9b~0&KI>->2>=w$3N@lk@y^uDX@i_{gWg`Wv$zZ+pCo@Wrh!rvMy!zc zu70fG#d+aSluEKs_EYU7iS!eymO^PUHq<}~s=#x~Y6Nb<<519;PBGF-;g4Be2FXvv zla*$#1-mKYv4teXJ!r!TGSZ1hMkRR{LRcju<&3dW7HDX&tBf3)@B)E4lsk9=DUp`1 zXbJMe&(<0t?;c($w|@?w_7-IE3Rk`o!jWGl{Fm(HRgb+B=%&KBLs`OL$2Xvezi^BMo#q4sQFZY^rQF>){PJ7s|1Z(g>BdR?ONvqaDCkfOCQyFF>Mn*< zm3@2rTQ}y+8cjcLU8K-DxSu#Jy0&B$+LKl-xyh_uu&`0G|JI zGn{Z;dujFUacgI&>-lQ-&)aMB3L(tpP}cy8FpzWqyZyEH&0(uu_{USpb&d3`NzQf2 zIk7`mMi=5b6S0usB+x?OFy}+?d)V_u1~XV0cg7dRhqELQO64%3L=<4YoZ|~TcHR0p zBx2l{`E9x8i~g43A3c=^E|ZaqVr*|iaAl2ztt~Szed@2j1%{SP$ILGH`?eB#5V4Kf z89f-BK51l&(qrFZ$4^9{ik)rqx{(d?$OcrbS(_etlAWdEs8$Xvb{;bbe$Y2eCmS8*fXIx@9W#rxrVstt>=mL^TS@&@O}japY)&_N>^GiRTE7cs6x$v}tKqgQ`JE7iNhImiI_9=uWw|sl!)4o? zZl{tXA9KX%j~~u@9+q>t`^Vr<6_#N)*aFh>rrInQP7|ky%w2Lok9uI))a*nyUVfzB zQjr`PoXxa+Y0Dut7CK(~^aP}_gdWFJ_}ICMbCOXpp1!kqVjkX?Qz0p(2#Yo(_R~lQ zVv4x;Glk-~Xp7^Wy9jNGdQ_=4gTyvciDh{Dh|;lnY0`weXlaKGgm5;Mq)_AB`S9wFWe4ZaOaS~%YWe95Q!zz5lI2oC8$4Bh{VPfPKOrZKwzNQ z+@Tmi>)#p3vT|`f2Hhel7u$@_1x?^orz_$9{DZ&0q#t1eff4aeW(Zx#YPDKN-y_e} zHXcE%%H{Efc?|wehvGEPSt`jj+25BwsO4>y5>6URALt*s%qTRf#ekCM{OkvQt167P@flfq%TKPYVx zLxf(WT{^{2ACp(sl%V6IY|G-la#|xEjTSmz$Mel0LyyRzqoFpQqPhuVjoVvbHOnH; zkZ3~HmZs@0f5G6mdD#$aQQy5$Ni`@v_;Hv1BLJ%|Q1(TrrU|F%PUZVVXT_n_w5L}4 zLU~q@x{rY^i_KY)L&g_Pw!!@K(gn|XP;b5cl}3^`gCk)y%a6bOlB9K=l8B=WhC2kx z>03RR!74CD=LBim>?0YmG?riP0Jq0eB+$e{j7S_AB@qH?62GCHySp9 za$lBjqs=4pJvHd=%{uPvif8kB3H4vw`;{jo-Bxywjb5GAIK0=mTia57|J~tF^@RvU zSum^U;3=oOE%SRMY?`-?V`^?EpSU~~JNGDCkmb(~fLr*kczvLjMd@{1)u8E~n*-VI zm7-WtfY!98>BM__0sY~WvDuavkabERLU4y6*K)k{2ugVQpq)u{F{fz0J2db5xTya6 z<74J$0p1IxECM*!SS4@PFp&4eOYg zZ~&B$c*GMF7?>j-7#Q-uQ&CqpZ##3>zw^&k?JLckNl`VUk8n_* zzJhrKI7rVa;d>2}g-~S3#<^oZguaTWXz!Ao3Lj_X(W=xj&e~usBX6c&x4Hg)n!Mdq zh*LU)xz4QR{CUP9x9Egl$0vgm@CrPsTiv)Z;m~GLjH(bG+Gd_OhIGBM4-ceok5LVZ zL84m|AIg!{cUtdHqtnm|o8p0tsVoFVAwqnO_wk0Tvd6^XxroM&)8Wa>3{(zjlnKb; zw-+nM!?fbbL@k2Q>ogkOn7%za;?V6_NrBrKx6{rbw2u*0ZO&8K-1U5f{|4}mX){jx zSC4F`O5Bs_ZQLke&L{d`IVajpHD(g6Bl=NNE$-fje7ZgA6CGEHvqjS_BLCSArWT$H zWYw>5Cd%b*O;m4@zLl<#B5*W2e1JtOh_r=JgN;|^pp$iK-66+dTwJG^T&`LrCjUAkqK`qMxzm3K6}49O*#!(uvjzF4b;>KJ$Su&;nO(tr zPPUR4W@a)hm{)N7-ZvnAq{MqQX>w$Xkj14gD1Mg>>jeiw*h^H`S@W5QvUw=i0LOF6 zGu86S)9ES3H94oSBWHMx`nM=%6l+lm`}zx-qj(wQ2lalPHrZZ@AHn^w=SbR!8ac6- z+&Sh;jIgLG!~#&-QpF=Lq2ts+=t__gXT;D_4BIryGSznlzp{Y^rR3>bXsQU#o_e)d zEWSCdJtbXskWiqJnK^L}e@G~z;1txibdK+Y=9(=^CFYZK+vk*fVpJ+4i`Am;ZdJ)F zNc73FO6Qs*NY_dqmnf@UG=vE8DU51}qttpUhgbrbY9klNlT~dIdCQuhgV)~Tm>xc@ z-Ot-{_AY$r+V~E5JQwZ0L0Upc=i3bl3Ui8Z4mV?Rj^^7wj4NSX_R&t$!;ysRDT?~B zyL6CNR*|2Np*v#KGv4YHhTlOr7RQF9i4)osA9}2}Cvbx7Zej|h!rHkEW1m3iNjmhG zw2Ck=p5EmNe**Xs=hmw8mzglK)!|MnEY#p(C3OojSLp!i?^xN?KIQ>_e-_s^{uuri z-uTk~=JKbh=h#k?_QtHaXl3i`FAdolC@(;g^z*Ct)=jbL#&5i64j~>rV2W)?A)Y}bo2PcGtUa9l%Y>D zjEoU3k-G?NoSSL({+5MO!t5N&`v%t4ghd19$It(VX7(rBXY5T6fh7)KM@}|DPr-C~ zu??5X%MvNiXTzI8bq*4G<(0DoO#VaPzEhZI^N%=(QKImMBPd2Zbx)whwhOy4IDusQ z7X3Mn&uh_^LD^^WZNIIKgAE|tJ0F*tVS6Hh-DF%gMO; zw#V%(tD#2GjBENgrw$IjD`M5Y+u5u|``yg={gPVy8rr6PQ;98(K$cty4b92{3-EnKzB_eN#UMFAqm1G zQRfcKjrTkqojzf0)zjut(o@fO6+Mb-U^_f7;H$>*ws!~20#)feLp35VpRchml5NIk z{f!{^3WyxxWAzu2H~&5LFS?FL?s?}&1fL;+nj?Xw)&SwIqZP3?6OUE2M;Gk2s>SS5r9LfC^83m+8H&UBSWY1&7%)OCzRgo7+Y%?l^-Y4w!ghP zMdsPYe1+fo9&%N}fCO{#Mo7>b48?PR!E&_ycNc z4Xx(LOQOEhM={q=e1AAmr9a&ed!Z?onj;mzV7l_7-NhlIYWiY}Ogjm?q|a3-DtK5F zQOVUb ztE*ZW(R8yJkpo=GRkgP{!|pH!a*-Y=>B5yCHbRdL(fyaJnY5aSW z1N|9!snjH#$uc}nc1))*!r+}tf{|S4#M3APM)RMcb8hU&V=3qoflf@&V6C+nNO`T| zn6F&4i0mR@yl`_1_NV7#Ys&{tebI`dZe8(pA5nMOZAn@#dT`#SN(U`E(5F( zkX+Jq@P1m{`x`6K0^mya<3}*+sNkla;f^9;A_`^x=d{SgNzwWITZoZv&>{JHcby3F zr6t8)DhR3?zmxDlMGJE@Iszh#pPSdr=KN(D8y-old3s58V2fT5$ZQ}2@-zUe(O=A1 zHGm`y76&cKSOjfqSiZ3(ujl^8bk8>d2EOUa%g_rsnFeG|Any)*iYM-qr$WSus=J9c zLjmRZwc5TlVcDjc69gW0S~!HAY!QVE0cZKAGTd+FW4R7C?wZ2Ap>&g_3ze8%&VecW z!?R~{QP-&~Y_!c85hOge9I5QTXIldJrrcO&ZyXnHb@Vd@SL$g;FdUQ<%Sorq(1WHM zm`t)+Z|m#B0Hf~*4M(f3u9ku}k}}6mZs`)r*|bTPLJNs>QMl@r0cH|4_;?W+RB~+j z8`Ra!RE$R44<8d{VKLEKl%%u?gD)E(ak43q11v2vVr4H7`f{PuQlDxYDJIRT$+3Ae zlG?{jqO|SoG=7sta2e;-YPa$*F3iCe^SXFz4|*rU0NSJ94ky)nIdr9tq7q9Gu@zD| zMa~qUcAZi3cX&N_50&5@GVMQa%bt@lq}VnTBhe0L|J_R&`RROIDsLeaBoVhWhi3a* z{1axw<5MHA^o(+55j)oj+7yr z1(Ok1Oso=0snl*lNvGj5-~Mhk)SupTpRLk?cAJyf)Yfu9a-0$|YkDDULhoxn8`U^l zL<`?+SQuLcRuV>7Y8w_kpZ8pMT5w+PJ^n%THe7H#W8b%c3OS^2qi1>X9By3S$Sim1 zhrOAx_;r4xBTCBU%jKcP!Jdl`Gv;bM#<&zpdHHp7tl5 zxZ>GO(JAYby+mS+5iiVlRl#))&6_v`Ed*<`2iPHp7s>X-G_kaWj6Fmu2VRt;Z*{)> zwfd&nCh|bF-d7$7+%3H7nN`gI49jv0Ksgmkdz;oh(TQ{rK~cn@by8yTtAwQN;5U@s zmXQ`qpOH&=cb6pk-SmP&U5Nv#+HE&O&Jc<0fk%nhL*wl?X$jq7TxTOzwixDo!U|(j zhY>mVo@zTFV#QlV&Wv1DP(P1?x0^kmKVv0qG=m^~ENm3<=_jM6V$fH}aiZS_{A`qM z%4*L1D?PCZ(wW)rm(fuN3ToIthG!)XU7@FtRut=3Z{*E)K?a^41Qvt}Ori(Lb5T$}IgD zB6W|DbBaA-!rR*={r1kWdY>R?#UQcaU<~s_f;m$Xr-;|uwhZE_EVfazLS@R-AbAML z-ehue$vC7f+wN||(pPEk_iW^>B~aC|?*0LL2I(02>7=YfabDN9O6TcuiiD7OeDZ*% z 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 delta 7902 zcmZ8mWmsIxvK?S>cXtS`!6AX*HUtRn7TnzjcOM`~2n2U`cXtRHoG@4d!JS9WdEd=@ zcmHZxUv+m?*X~+Xw>2<%Rz%7Qa6mi&0ssjB08j&5`E&}sVE}*-_!=TwSnz}rEEiU1 z<_$)s0lMy~QH=3cfVUdXDU7vnHTqiP0UDCSiS0WRG;t)o#^uKIM@5T5Q9b@jt#{(2 zzVzN7HSspxI2Wc^eslT#6p4bB^UBjZRgOf@A;PeCxSIn3Sp`;1>8*2b=;#kgNJ2kG zY~Gp?sOCk0=k%lt2(2;BI>D=c2|}K*@5!yX`g5MqUN^X^wU>MOly*kD z6J>pi(kj;TIuFmsHGf^!1MILRYVA)GBQA$2cKWE8N<0UQSRz94N_ZXEcP{HuDIYi9 zTiu9#vUDek_H*R9(%tFgfoz0?agcc?(|V~*PxuypcKdaRlo#3V_j&LxUP^53lgu^t zlP~c{18+@&*}JiB23M>_qTz=QJ@GKXcM<5>)Q~ z(bNY1WMFK9Hlo{7!8VH?9u9s9x~SQvX`Q%JWR&qXqSz!Dw(q+`0osakIJMK8Wr32< zCkdtpHp_Y7w6$Jnwy>Pf-tC1WWSU3Qn{Y7J#FPGQT zmczrr*~Y}d!G_(_&bC~A%|4S8uQR*eL#(rC35b-F#4IWqJr7b@Y~W91M*M69&-q#j zQhYdYMdFkAM*3b__?7762xyUwhHtMMdh+>X$I-iy-FYW2R?oDwPPB^W>5 zH1_p?HV>>(uV}?CPw*AJY(^Wp6F!%c5M6?W3I`Y!5>HoEx72n^stHrtJoXibVKbQ?@#b{-pCszVu7sFy4RfA=zyenbf10cMtZW~fnBg}#}WU%9=S)+ zyj<)ev?JKIqO+Kzei=%jQ$j{8SfT#ed0-Z)!I(+ocmTeo+*{#`#Qb3AnzRPg2wD>Y zZwcO*z=zPQmvhL&Ypkj~YwGeYJt_u7#-d*NjnD^sAhH4vx@92=N=IDk={3n-A$MD5 z?JDVv3{cn6GtUY-P;vq!nOVqdPt4o)y6cn*!V=j^VACLRu1#Yj!og&^yLu< z*8vwaDSJ)xuXUu+GO}5%B}bx-Oz2Pj2Cw!Rci9X&ZKf$XY-X-CQ)c!%U>^@Pt~n!K zC&XOzN=_Gyy60N&BQ=Qiyx`=O4b|>fG z!LzW~t~kIfZVnK%Gbq;p?PnA*!(BJqZAcAXtuPEiiBIX-Hs&-wHSXbm6<+Lt1KVEf zy&io0df++PeGLE3XwZPu7M^IepBkO=i1=$E2)4$YZ**`4vx~xC^vUxZ(;r++g#)rK$ZaboZN80fa$}%H2DjOvt!y^`$cUp{Dm4C#TS#B!uS3v{-_V6H-OeElOEnNp(89e{^dXO*s#@s(vyg0fOzX~M{_ z@z1ZJXIZNl*-u{9s`@Mw8m|h+Xu0@*^{bVLy!CU+^|hkA>f2wGXh|zoi~a$Q9vC@r zei>3I!4cLcA|t9)D@CdQF)DlP+#uw_oLC%V$PU71`F)VCN-Qj@G^K=J=9$%zTs%IW z8b!$RNul6y-i+ozAiZDBDVOZS&Yb3$`u9wwq4{rT{qHpu4AWC=*)@nN74gE#;Qb62 zU3Hrt={u?(Ry~&&*!*%<plNJ_Ku)G_>?TBJSixNsNOMYWN&#GZVe+)3_HS!EL@m|ih>V^YK;gMMf(a!bJl>@ z40pUIfE~?tapdf9Ek3;KOBY-Ft$iDK7^XSOn|sxF<1(9y#!VM2QvN9A2AdZ`8rdHh zqx$Ej1CFplOYH+gqQIvHSd~fcpee|se9kHfy)WSP%pu!z+Nm$yO2`l84))HAVw zbo3d*dWVZZu>>M8N2c%-d0h)=^FI18x@7w}#c*tZ1hC~AJ)(Emm9(1eAr z3=G7fB0eKdMmS4LYsJ{Qay!Zo39)Au)e>N~VpGcInqKeGx{ybskYbJ0H@cwMnfVey zGe|{740p+_4z}yzY9cD*5zRv_47XW{X_1g2qnako2^FPIWgI`h5OfIf=Ye^MlA&Zg z{4AsRq5Z}&SBFT6Gcb+rY+}C&>b+>hH0X`{>6lqLo$&6gV>iYRc8n$$nFL0bk^6Ba zfDaZ1^2Rn7Uyf%Qchgdv^_gITp#0K;C#&0La>WOB1iS(Kbn@;Z6IktLjY?oQE80E4 z_vJcyhh%B7A2}ijGJ3gBcvz21NhTnTh3iz53>g>Fo`C5z-s#eE?10C-$sE6?RxECILuG8HDBxhPVSj@>y|Do%Ehfdmx_w>j zo1QX4w(>#mSnHBu?8Fh#Ov7OUY-yWNOS@r5?eDvc;Q%RWFsoc>>m(9f?=M_paDNba zFVA-Zl7@?tM2LH1M)h&G6dRJVn;YXxFO54&z-rM<3$u5ka*G30@`!!@fe|D@rdo%q zNek|2?Qf$L?N@@%5}QwxB)%+`pqW~T#-SxPqrx*p@jhX9p=FRvhkQpA*^r=mlZvxw z=3bk-@SD5D_wCVcoz)cRN{HbgpIdNIVOx3OVA-t8qm=stnG9t_Sfy%4hei~>@)c8n z95{VHJOPOqmepGESvBAk)-1;fr8hX5bw)u;o?4n<9+{4DVP#q{6FZMnvA}w!n*8;;AtU zJ^t(?nT!Tj#Ce2#xuKO~7U@aY_Yt3L?5-9^2!#7ttq$fl#I+e{1OmS#@BElGV15LP zy+7=GXJzLmuBNj#qz6%%Z% zx=K$yYbz>Q)WN7Je9-<0v{!qzS0vxEC24F?W{*+R*t$$WoYu$x;Z^3*+E==@b%w^d z17FF}W3Aps$EBzAV%t^fhTAZ?Is%4Mz$EsqZUnUjTC&Wi;r|l*bbT*KOHFYeTrwiN~6kG5o^ia2v~woj3+r>| zcnLlX1o{zn0@K(jgImDS@!U^m{@*Rl35fNYX0C=m(HuC<5d7A7Js}p~MsA`V184bD zkWq@~=BBwo98R;nD62`P0TWb_7-XEAG;=?#`jo`jM;%DnX_-Od&Cj1JHxS~rU+({2 z<0q0=sNtP`#-L%R8PP`{CNrXaPo2=#tG-}l-y+rrxId3A1ge1r+2%T{TP4Lq0&7_c z68HfD08&B#0R7+i)Wy}y_M^+6==8hRg#8X5Rwv=UFjlMZUCpjm*bgbPp>EjK0a&>} z1FOi|$O6g0+`2P@H`moC(;oXZ;hhp^(&Va1^ia*KMyFW`lO&q(4StD9G>eByS)$fg zG({rlX!rfxSaK2+Gp@u$U{S*f9|^c0I7QgzBJ_bZ)Gfd5&vr0(^z4aR^ss5LBV^CJ zwdB%c6<=d&()HXTPsySfny}-req~8D|AHKpr^hCrcA&M;t;h+ARqbU&ZbOo*zGfC0W58R)~lUWewItbOz~8NG<4gVkTNsYuCtyZK_6(w~);M zS(b6%5IqA$A<~lD09>rii`20vOJzwKak;%REkE*(CAp>|3t?1=lashFFjX?&Wk09X zuVJKHp6PpsYKiyy>$*>{4z@!_om9{mX_SGpc0WE}IJr`#B)8dXzvub$urEJ_*&hx} z>xv8Kcxd1wVNG*DHjS3WF4OR5v`FoFw2tv{V%f8PY8AW~;b7YyDPUZOJ7SU1rn4ot zIbEtFE>OR6zG|2F!O)SZ=N2@GJ)rQ#q|n}}Bew$w7WU?;TUJ(b5jld5<9y9Dhp*&n zzgc`|#!-kJu*v%?jzvCc%H{jF$(b#(O6Qg!zt zoIYnh&UauBZLqg&CB%znLt-&L#~-;g>-MMQW!RJ4je@4G>8~WE{049q_3O8T{Ndx6*T=W3*&PspqL!GU>8gOorez)Pnr)`+yDPa(bP zag#8hGQ^~eb+w_+!ek%9>Q_o~E+rBC-th8|aaJ#2# zru)iz1iWuUI7L|2fHe_$C^tY8YUwzk7rLDjmb?mjD2IAWX$gC+FBYuxnWZ$iA>ps# zuVYYGn1V6n2%CCKY;qd+-T7Tnd5 zzD8nvRrT`j=G&dUsa1!ju8jx3`=5JNsrv&N+>90?3DJSa#g?_gKOy<0)Q9a3ZKR(Y zBKkcicE4Sj8u9$hzHlL0QmcDAW5eF?!lzd#=fRn)6vf+UyKT?UHp zAD0KdAD~wpR70;K7tcEm%AqaLxn)px!qw|m>5cjt zO62&S4s=%HL?9d8Zv@uyL5Vr{K;*i{kY%+7hG)P(+(0J|a)b544a%q?cIcE~oz=K) zX)M3^WN`IEvIyEBAzE+%ewu=Yd@f_=Sltkh5xS9y4|^u#^Or-^rOHD)A(o$UJ#YP5 z@6_DxmnL@m?hp3cYimcN&*v|F{1%O&oGTu%!oDlh8K=4}Q`7i0Cd~X5eIO(Ok9ca&P77#lO;=Md)`Nqsv7jQc=&0;1<66P_nuBr5L zxn!>B{qb;Z#yf`2qtiQIFmsdz#sgB(otQQcOQn4;(x%_i^Dr~OcH7<;=e z<JXuFfj(q&)J&+uAFu8rV32wJ9PTLbjV!LzOCYJGZk8NH zx{wV+X5v)+$^orC!K_nCkZn#V3pBbt5txqQRl&|=$p6R%q_zg;7h`%|wKIASh;^8g z2||@`Fc1awdkz-C+TiUDXJ>eAMp>$;V1D`Gbb7%$8jFS9@j}1B;3WsRfTTV+q#fPy zhr{{MuBHS(yjn@IA8T0e2osehm!w#kXbx#K@VNGA7Vxk=ut}qc*0IRtj5xKD1P=YE z%g99BzIxj4P*R7|1@U(kK4LRTV!thoDL@F~u9+26W?moxBaIG7!&xQGBq9&Sd_<9^ znrm3Uy(~e+Z7U&9t`9{Bs!f$eQmhCokjqTdQb0!??U5HZYUO8TM79~l$)U5Q+pW<* z0^ta)oTiYnp_1F(TvqaN$@h!Hy{n^1OlaieQuUP6_AQSMA!_)_O3hpm8?s~xhi^O| zW+=0gldEM3rYdH{LFTfS(2n54F_{mm4PitkMXs4a*ygqFtD?0#b6Ial;shirH#+&P>5=%E&p7_eVou|yRoM%?+ zN2TGv$9l6z!7#fIOiuAVYUBkNDVlZ&4c3#E_)%3W=2E zTXr`Q%eZp9!U~m;L+^?$a_nktX2Ni5-*A^O0UDTHxvR@FPdqxWXUQ zlga3eke&yDKg6;g*GCP>)7o=@3TKK4+{Au8lAyI*E5vBij^bj!Y`UF7g~FulTXQ*2 zt3|n=wL0RG_7Ufj4vV609?aE(5XE+UaT|q^N5vL({5gtg0d`a7pipkATfjm_XjMxW&DGOAwMF}wGX@_BOXhAY*^R|n=UcdI~&U-2J z%-Tf<#2bCMV7n%NOnE0wyvs{ev!ru>lgqJzmV81D|Iz0#JN>j$sq{V$qJB)mLc(7K zj7QuPHv10a9wTG%y2M*QEePuVeJYVXmVf>XeaXKk)Nw1(zZ9IPIp|qYe^;0U(-=X}D9ajX~&V)u|IiHMta$%QS zWFMswK(upaT4A)t!V54;g61wt->)e(2f><_Y}O~hu2=#PDn3S|GJQaXkhnLf<=A1o zI;AtlDO}m_*8!&(*)Aa`&-1j4-|W@Q(>FX7`)H}S%libFil;gur#f3RRR(;`z?mT$ zS;i}wbX9>9=u;L$?j<4PrFqC}$Wb_lhPJ-WV|5W$eml4Hi#4-O#ig{9^Hy!?{p8>Ti z*AJAVoiKl*7jS5Vv0vE>uOfIc3)a8<%GB7_RKn8O%Ki_ zV`E$C)a!8MAR-+s0na`pQF;5&T4L7{r=9ee7TRY^LlEzBK7Xucm#4A}B~2zL{$BZL zjYubHk64){g}{L}%{L~+)=ZGKJDN0a1P4bfy;EPrgA^GS-V3t);Owz}nx-K-%jvZ% zkq|Lssgv>}HA4*mVvDeFEanqa6M~I+QoOs|ITk(O7X0WunLo9A#^L%@?DY?CL~;M2 zfn4`;3?6()ivl}1c}%`f3@_}N$Dov54NKCIn!NyCVdtZjl}-guAy0)XJsv4_j+`8A z?zXtzJ?wVh1-36hlU*+ob5r^`5?@6vsu_DS}@=0{>A+6+GN4`oK^7eZAHB!%qr%BC+xr`k8e{c4r#ku4WJa^Kz5~? z2=&f08n-YP3@g0q7*gtuNVId1@7$|?MsE}W3Dll~rF?9-x|CI1v zYE~pK_x10$^isiskfD-57&WoT{=2O87eou zO)mOB!XT@pSZIGC(|8am4SI(EPE7m-?2`RcM*BBS0l`+sBl}Ac005%Dz?W7GHN**> z1VXHVMfRVcBP;-b{r^C-j1Yb;TC)Fk)xVfH7Raq84cT7@000>N&c3uPSRow>Opu9} u!{}&{FdMQ10A>!R%FYgsE*!>=j(;3oSpohHQDhc9?_!