From b482d2278955305a1809b7bd86f8cb7742ed4188 Mon Sep 17 00:00:00 2001 From: iakov Date: Sat, 28 Feb 2026 19:18:07 +0300 Subject: [PATCH 1/5] Convert repo checklist to Markdown --- repo-checklist/repo-checklist.md | 159 ++++++++++++++++++++++++++++++ repo-checklist/repo-checklist.pdf | Bin 58072 -> 0 bytes repo-checklist/repo-checklist.tex | 152 ---------------------------- 3 files changed, 159 insertions(+), 152 deletions(-) create mode 100644 repo-checklist/repo-checklist.md delete mode 100644 repo-checklist/repo-checklist.pdf delete mode 100644 repo-checklist/repo-checklist.tex diff --git a/repo-checklist/repo-checklist.md b/repo-checklist/repo-checklist.md new file mode 100644 index 0000000..407dfd8 --- /dev/null +++ b/repo-checklist/repo-checklist.md @@ -0,0 +1,159 @@ +# Чеклист по оформлению репозитория + +## Основной чеклист + +| № | Пункт | Выполнено | +|---|-------|-----------| +| 1 | Лицензия | ☐ | +| 2 | Лицензия правильно применяется к репозиторию | ☐ | +| 3 | Используемые третьесторонние компоненты и материалы совместимы с лицензией | ☐ | +| 4 | Настроенный CI | ☐ | +| 5 | Модульные тесты в CI | ☐ | +| 6 | Линтер в CI | ☐ | +| 7 | В репозитории нет результатов сборки, настроен `.gitignore` | ☐ | +| 8 | В репозитории нет секретной информации (паролей, ключей и т.п.) | ☐ | +| 9 | Различные сторонние анализаторы (если уместно) | ☐ | +| 10 | Для кода на С/С++: использование санитайзеров | ☐ | +| 11 | `README.md`, плашки CI и анализаторов | ☐ | +| 12 | `README.md`, общее описание проекта | ☐ | +| 13 | `README.md`, пример использования | ☐ | +| 14 | `README.md`, инструкция по сборке и запуску | ☐ | +| 15 | `README.md`, как помочь проекту (если уместно) | ☐ | +| 16 | `README.md`, корректные названия компаний и организаций | ☐ | +| 17 | Настроена секция About, указаны темы (topics) | ☐ | +| 18 | Код соответствует принятому в сообществе стилю кодирования | ☐ | +| 19 | Имеется техническая документация (в `README.md` или на вики) | ☐ | +| 20 | В коде достаточно комментариев | ☐ | +| 21 | Комментарии к коммитам адекватны, коммиты показывают историю проекта | ☐ | +| 22 | В главной ветке адекватная история коммитов | ☐ | +| 23 | Добавление релизов | ☐ | +| 24 | Настройки репозитория | ☐ | + +## Пояснения + +1. **Лицензия** + Отдавайте предпочтение разрешающим лицензиям. Код мы рекомендуем лицензировать под *Apache License 2.0*, *MIT License*, *BSD 3-Clause License*. + +2. **Правильное применение лицензии** + Каждая лицензия имеет требования к тому, как её правильно применить к файлам в репозитории. Например, *Apache License 2.0* позволяет себя применять пофайлово, для чего требует включения в лицензируемые файлы стандартного заголовка. Также распространено использование файла `LICENSE` в корне репозитория и ссылка на него в заголовке каждого файла. Поищите для своей лицензии, как её правильно применять. + +3. **Совместимость сторонних компонентов** + Если используете чужую интеллектуальную собственность, найдите на неё лицензию и проверьте, что вы действительно выполняете её требования (например, проект, лицензированный под *Apache License 2.0* **не может** использовать код, лицензированный под *GPL v2*). Если чужой материал не имеет лицензии (например, просто картинка из интернета или кусок кода со Stack Overflow), использовать его **нельзя**. + +4. **Настройка CI** + Если вы используете GitHub, Continuous Integration-систему удобнее всего настраивать на *GitHub Actions*, однако вполне допустимы и сторонние системы, такие как *AppVeyor*, *CircleCI*. Если вы используете компилируемые языки, CI-система должна проверять собирабельность кода в каждой ветке репозитория и при пуллреквесте. Если интерпретируемые — проверять качество кода и работоспособность. + +5. **Модульные тесты в CI** + В проекте должны быть модульные тесты (за редкими исключениями, где они неприменимы или бессмысленны), и модульные тесты должны запускаться в CI. + +6. **Линтер в CI** + Должен быть настроен форматтер/линтер, следящий за качеством кода, и также запускаться в CI. Если линтер выдаёт ошибки, сборка должна не проходить. + - Например, для F# линтер — это *FSharpLint*, для Python — *flake8*, форматтер для F# — это *Fantomas*, для Python — *black*. Нет ничего плохого в том, чтобы использовать форматтер и линтер в CI, настроенные так, чтобы некачественный код даже не доходил до фазы сборки. + - Запуск линтера может быть отдельной задачей в CI, чтобы не гонять его по нескольку раз в разных конфигурациях сборки. + - Имеет смысл сделать запуск линтера локальным *pre-commit hook* в git, чтобы некорректный код даже не позволяли закоммитить. Если есть возможность интегрировать среду разработки и линтер/форматтер, сделайте это. Например, *Visual Studio Code* легко подружить с *Fantomas*, чтобы он запускался при каждом сохранении файла и делал как надо. + +7. **`.gitignore`** + На GitHub файл `.gitignore` можно выбрать при создании репозитория, но также часто требуется ручная модификация. Должно быть так, чтобы все файлы, которые `.gitignore` позволяет закоммитить, реально нужно было коммитить. **В репозитории не должно быть результатов сборки** (то есть папок `bin`, `obj`, `__pycache__` и т.п.), в идеале не должно быть бинарных файлов вовсе (только если очень надо и вы реально знаете, что делаете). + +8. **Секретная информация** + Разумеется, в репозитории (включая историю коммитов) не должно быть ничего, что вы не хотели бы публиковать (например, ключей авторизации от сообществ ВКонтакте). Если пользуетесь GitHub, кое-что он умеет ловить сам, для этого надо убедиться, что в *Settings → Code security and analysis* включено *Push protection*. Но, разумеется, большую часть секретов он не найдёт. + +9. **Сторонние анализаторы** + Используйте сторонние анализаторы для слежения за качеством кода: например, *CodeCov* для анализа тестового покрытия, *CodeFactor* или *Codacy* как продвинутый статический анализатор. Чем больше инструментов следят за тем, что всё хорошо, тем лучше. + +10. **Санитайзеры для C/C++** + Языки типа С и С++ дают возможности для работы на низком уровне, но благодаря этому повышается вероятность появления таких ошибок, как небезопасная работа с памятью или *undefined behavior*. Поэтому для проектов на этих языках стоит включать санитайзеры при сборке, тестировать санитайзерами на CI, а также запускать инструменты для отслеживания утечек памяти (например, *Valgrind*). + +11. **Плашки в `README.md`** + Добавьте в `README.md` плашки CI и анализаторов (штучки, на которых написано «*CI passing*» или что-то такое). В документации конкретной CI-системы или анализатора обычно легко найти, как добавить плашку в Markdown. Это поможет посетителям сразу посмотреть статус кода. + +12. **Общее описание проекта** + Напишите в `README.md` пару абзацев текста, про что вообще проект. Помните, что код вы пишете не только для себя, в ваш репозиторий придут люди, которые вообще не имеют идей, о чём это. + +13. **Пример использования** + Опишите типичный пример использования, если уместно, с картинками или gif-ками. Включая информацию, откуда брать датасеты, куда подкладывать конфигурацию и т.п., чтобы любой пользователь мог с чистого листа запустить проект и понять, что у него получилось. + +14. **Инструкция по сборке и запуску** + Опишите также действия по сборке и внешние зависимости (версию используемых SDK и т.п.). Это всё есть в CI, но в `README` это всё должно быть в удобной человекочитаемой форме и заодно приводить к развёртыванию окружения, пригодного для работы над проектом (тогда как сборка в CI может быть весьма хитрой, использовать несколько Docker-образов и т.п.). + +15. **Как помочь проекту** + Если проект предполагает возможность стороннего участия (то есть имеет хоть один шанс стать знаменитым), опишите, как сторонний человек может вам помочь: + - куда и как писать баги; + - как связаться с разработчиками; + - как контрибьютить; + - где посмотреть техническую документацию и найти первый вводный баг, который можно поправить. + +16. **Корректные названия** + Названия каких-либо организаций, используемых инструментов или технологий должны быть написаны так же, как в официальных источниках (пример: *TRIK Studio*, а не *Trik Studio*, *RISC-V*, а не *RISC-5*). + +17. **Секция About** + Оформите секцию *About*: стоит добавить подходящие темы (*topics*), чтобы ваш репозиторий было легче найти, и описание (*description*), чтобы стороннему человеку было понятно, зачем репозиторий нужен (кратко, одним предложением — подробное описание в `README.md`). + +18. **Стиль кодирования** + Проверьте, что код в репозитории адекватно оформлен. Если на Python, то *PEP-8*, если на C++, то в соответствии с *Core Guidelines* и т.п. — у каждого языка и даже у некоторых фреймворков есть свой стиль кодирования, проверьте, что код его уважает. Если в проекте используется свой стиль кодирования, он должен быть явно задокументирован и весь код должен ему соответствовать. + +19. **Техническая документация** + Где-то должно быть некое техническое описание проекта — из каких компонентов он состоит, кто за что отвечает. В идеале — полноценная архитектурная документация в виде страниц на вики, с UML-диаграммами, но если сил нет, можно ограничиться разделом в `README`, где кратко словами всё описать. Также вместе с/вместо вики может быть уместна документация на *Read The Docs*. + +20. **Комментарии в коде** + В коде должны быть комментарии (в принятом для языка формате — *DocString*, *Doxygen*, *Javadoc*, *XML Documentation* и т.п.), хотя бы у ключевых классов/интерфейсов/модулей, кратко описывающие, что вообще делает класс. В идеале — для всего, что *public*, с документированием предположений о входных данных, инвариантов, бросаемых исключений и свойств потокобезопасности (*reentrant*, *thread-safe* и т.п.), но насколько сил хватит. + - В идеале — по комментариям в коде должна автоматически генерироваться документация и выкладываться на *GitHub Pages* или тот же *Read The Docs* (в т.ч. как действие при сборке в CI, то есть полностью автоматически). Например, для Python есть инструмент *Sphinx*, который в этом помогает. + +21. **Комментарии к коммитам** + Комментарии к коммитам пост-фактум исправить тяжело, поэтому за ними надо следить изначально. Рекомендуется следовать соглашению *Conventional Commits*. Коммиты не должны быть сделаны в последний день, а должны показывать, как шла работа, от создания пустого проекта до последнего релиза. Фразы вида «*я тут локально разрабатывал, потом выложил, как получилось что-то разумное*» очень сильно огорчают комиссию. Могут помочь инструменты типа *Mergeable*, *Mergify*. + +22. **История коммитов в main** + Почистите главную ветку репозитория от лишнего. Если у вас в репозитории больше пяти маловменяемых комментариев (типа «*fix*») подряд, либо несколько коммитов отвечают за небольшие изменения одной и той же функциональности, лучше либо сделайте *squash* и склейте коммиты в один, либо измените всю историю через `git rebase -i`. + +23. **Релизы** + Если ваш проект позиционируется как библиотека, игра или какой-либо независимый инструмент, рекомендуется публиковать новые версии в качестве релизов, т.к. они предоставляют пользователям удобный способ доступа к конкретным версиям вашего проекта и информации о том, что именно изменено или добавлено в каждой версии. Рекомендуется ознакомиться со стандартами оформления релизов и *Semantic Versioning*. + +24. **Настройки репозитория** + Рекомендуется настроить правила защиты веток (например, запретить *force push* в `main`), а также инструменты безопасности и анализа кода (обновление зависимостей через *Dependabot*, инструмент *CodeQL* для автоматического обнаружения распространенных уязвимостей и ошибок в коде). + +--- + +## Чеклист по оформлению пуллреквеста + +| № | Пункт | Выполнено | +|---|-------|-----------| +| 1 | Адекватное название | ☐ | +| 2 | Описание пуллреквеста, список предлагаемых изменений (если применимо, со ссылками на закрытые issues) | ☐ | +| 3 | Описание пуллреквеста, описание работы предлагаемой функциональности (если возможно, с gif-кой демо) | ☐ | +| 4 | Описание пуллреквеста, техническое описание, изменения в архитектуре | ☐ | +| 5 | Модульные тесты на новый код | ☐ | +| 6 | CI проходит, при необходимости подредактирован, чтобы запускать новый код | ☐ | +| 7 | Содержимое пуллреквеста лицензионно совместимо с основным репозиторием | ☐ | +| 8 | Коммиты в истории следуют принятым в проекте соглашениям (отдельные или склеены в один) | ☐ | +| 9 | Стиль кодирования соответствует стилю проекта | ☐ | + +### Пояснения к чеклисту пуллреквестов + +3. **Демонстрация изменений** + Анимированные gif-файлы легко делаются инструментами для захвата экрана (например, *ScreenToGIF*), и очень нужны, когда делается что-то в UI (например, чтобы наглядно показать, как было → как стало). + - Если пуллреквест что-то ускоряет, приложите графики замера времени (или *flame graphs* из вашего любимого профилятора — вы ведь не пытаетесь что-то ускорить без профилятора, да?), показывающие ускорение. + - Если пуллреквест улучшает какой-то классификатор, приложите *ROC-кривую* или что-нибудь такое. + - Если занимаетесь машинным зрением, выложите кучу наглядных скриншотов. + - Вообще, активно используйте наглядные иллюстрации того, почему именно пуллреквест должны принять. + +4. **Техническое описание** + Для описания архитектуры используйте UML-диаграммы (см. [uml-diagrams.org](https://www.uml-diagrams.org/) как краткий справочник по стандарту, избегайте *UML-like* картинок). Выделите цветом, что поменялось. Текстом опишите, что на диаграмме нарисовано (одна диаграмма архитектуры не описывает). + +--- + +## Полезные ссылки для любопытных + +- Правильное именование коммитов: [https://www.conventionalcommits.org/en/v1.0.0/](https://www.conventionalcommits.org/en/v1.0.0/) +- Исправление комментариев к коммитам, редактирование истории (не делайте так без крайней нужды): [https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History) +- Хорошее описание `.gitignore`: [https://www.atlassian.com/ru/git/tutorials/saving-changes/gitignore](https://www.atlassian.com/ru/git/tutorials/saving-changes/gitignore) +- Модели работы с ветками: + - [https://www.atlassian.com/ru/git/tutorials/comparing-workflows](https://www.atlassian.com/ru/git/tutorials/comparing-workflows) + - [https://www.gitkraken.com/learn/git/best-practices/git-branch-strategy](https://www.gitkraken.com/learn/git/best-practices/git-branch-strategy) + - [https://www.endoflineblog.com/oneflow-a-git-branching-model-and-workflow](https://www.endoflineblog.com/oneflow-a-git-branching-model-and-workflow) +- Зачем нужен `README.md` и как его писать: [https://bulldogjob.com/readme/how-to-write-a-good-readme-for-your-github-project](https://bulldogjob.com/readme/how-to-write-a-good-readme-for-your-github-project) +- Шаблон `README` с плашками и другими хорошими вещами: [https://github.com/othneildrew/Best-README-Template](https://github.com/othneildrew/Best-README-Template) +- Подборка примеров хороших `README`: [https://github.com/matiassingers/awesome-readme](https://github.com/matiassingers/awesome-readme) +- Генератор `README`: [https://readme.so/ru](https://readme.so/ru) +- Гайд по лицензиям от GitHub: [https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository) +- Слайды лекции про авторские права в IT от Я.А. Кириленко: [https://docs.google.com/presentation/d/1-xMvM_EyouDM9slBpQHR3h7MRgYrMQCKZ2dxYeFKh20](https://docs.google.com/presentation/d/1-xMvM_EyouDM9slBpQHR3h7MRgYrMQCKZ2dxYeFKh20) +- Может быть полезен *Dependabot* ([https://docs.github.com/en/code-security/dependabot](https://docs.github.com/en/code-security/dependabot)), для автоматического обновления внешних зависимостей в проекте. \ No newline at end of file diff --git a/repo-checklist/repo-checklist.pdf b/repo-checklist/repo-checklist.pdf deleted file mode 100644 index d215ad1ccd33a4ed77520183aad7587d5a1743ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58072 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≤*?8cO;LL7HHbF820Lg!<%bvJgHVH%G z%1#{jTW~~9VWb4WDc0xT!N&Y83pyTRWLUkNbn%1th` zw{A}p^0AXh=9jtsmM|T<(d7hwZpp?s%|o30k4aAr`gtgzBS+4D4X3=#m@U{G_Gprn zLqD>-7EfD!BqiU3IHmJZP)%XWkD07?P+Ec&yUN`>oU6w8S-2%P&}&v2A6^(4+)XFI ziN%u^WH{nX@}0E>Fq6-0DlcyRPXyA+yz|U~O|L}0UUpk{jmU@n*HmY_f~KQUmbp3V zn!>wv{Z_aas9&LW13|n|UFcOwtM>a`lq3ZFsil@Acj35L zz9bHojvFFl8zp@a9=SR;YfVZ6Ym~;IG;>^{z0zcW{tDKVHgrEwv+$v``C-+lfyvox zS1lJc)XbA*%?L4*Pv$ItwBSx=x-5{v)DmIK{n9IQ=jJO_48`?whMWz*W|EGuynK~6 zumkirC$78{w)AMaCeLu)VQ2@^Ur-eU9X_@#G#NkQ>S-Uns3r|$86i*4Br*Vx-OJ|L z8ImGGi+8?d7b)PaN7A*(;caD5U1@Zko!OkX!ybx-W2Y*CZ$2=?R?8+)x05I~JuPl` zNrNGp8?Zw3La8iyhszXRslr1vO==T@IVVvHYuCAr?e)cBri-yYNe43|^U8rj9B~kX zWex|1K~QzpX}(wkgpdy{Ssc0XT8y7Dd^ToYsJcypE!S{pzk8 zw4Ej-6$GBl_u)H@^>|3Wp0RqT-c|;7%Yy)WEh|E4l3^`R@oYik!BJ6V2!B{y6y^vS zN+Gc5WrBEr!k}z;8HhQhVLTS@U@!7oU}75ZWP|t4X$@71_o5qTSQ3mZPGmqhB+BXWIazrrYtC zP_g~EY(kpt&;z?f3%Acm$aqw@>gT_Mna8Rg=e5%xcvY9W!i6R>!KtK5u0;4;x58K1 zCTq)X#7BgoX9dBEElWuMx;BNxuC^FBn+0UzKWV-8G_~NiFr%Z~$`>F|t3+2;#D3(9 zm!h6zwQd-#U^O)np{$c#{CrG2#*$Wz-Qz0rAv|V6d2LUUwqVr6M)AlhCEdde;iRgVIg2~GuaC5n@vn0nn9s15przR#&@H(O0%H|vu;h;nB5#{2xVn3 zbLJ~gg(|^FS@t%i(cH4Ut#~Kg!`}FbVarsKbo1}0wbEB+^UOlXrMp1OZYEb}gGPeW zlg-0qcih|ZpBn+>!2cKj_0*EhdFs7(6-(Wf-pi^s2kZw- zTG-7Q2-1feBVFH28E1ve{8vp<7&9vFUrBE;SvAX!EP~Wrbonx2zA04fV<8RJ@UP$? z>#YGzDx(?4%I!xJMlOEJh7i|0_)fw{rK&8KAYn!u7)0qbw6)3XBQR> zmv4_PT<>a|of$F2B~1fUYL=Zj1OQVVK34hP(4l+(3iLy+YdDhojnd+;R^%Cz5Ky~u zG+SUDD{f{k|a=c;F8|0oS3c{|nAkktMix0(k-pP6^| zRVJ761h`v~1w(IaoZd{3B3(HDft2x`T4NlYSW6fDll0eSer5jqDE|Yr)Zv-_-yp~Q zUo~);I641E1E)u8BJQajvG=tX#$5Vz5CapGPaSV z>kj}}IDxdGUB$O0X~;epPv!T5Fk=9lJBtB!>fguA+{fqJ(ht4`}g`xctY6GSjp^zwSiOr4``l0^Y^j)sk)9hVXWjC+XKor*iE6WNj+UH8MCTw zR!5a8rtR?g_3CEc3@Hp(sbzO>uZ1?eR7Tx3H^|V~{>V}XIF7VE`;XoZA5Y4P$1)#Z z9uaBv4{#@+tZGTaoS@N(Lt}PrJ6#VhPpjB?@>)d_OBl5#k0X~;$cEV&9FDqZF zq9%FBv>e;ie6@+(GBOFF(g#m_VIr_3WZb>*3Vpx>meB2{lDLEbgcISe_PdR3XdK zZC%Q{gGn5>!XNcFXH$cmdarljX`v5BR)U^ryGls&qoK#aHe`$|eJM5S+_iwDSoA>Z_<+V< zJV22x*o2XSX%K%Ik^WytcCUPG|;No^<-wH=!P%FipF`29wjUBK$1iTpLj`*v}qDLmjRM) z&QNPMn^l(slQN1Y@5r@paw;I3P5_#CLINLFFd{WL!!?T9#PLw!Xm67BU-&l35U@@i zP7J4j5?zuthDCA~i>-BdF+kHTVWFpD63985=}pK8^Z-Rts})BPL)B9bTD83x#)8zj!S?5+`p4tY6CIP6fnXrI6bX)yd{aC0C zaY1k(E$}gbEq0TvivL8qhirDr36r1KwKi-j=nzwfD?4#f@dwyg78HPCzOjk0NhVG@ zxScww{zCX^>)H*Zoh=B~478w{Iqyp(GufTaeb9no0FqpS@P?=jh$Dj1#Pml4*_0G& z9F|p?l*+l7d1gtK7F`;8E-r6tIUw(1njZPGorDMp1U)(16h57bl}_iHq~ zeidy?rEFSdo$4?I?|av7`kcogay3sXa$1DERH}Z87)xp#erXw*mS2EKm5hY*Gt1SS zb4n8n$aTEcX^F>bL=@l8Nli5dt@fQzIhW2E$rIs*f~NuuzGonOW@kbKZ$WS!=|T9k zLriXWZ|S4kj{W1Xd^!V&!QelGcx%Q^6!#Ff4OIEsr9EkArqKU<(pW8w4?IqSt_Cz| zabTl03q)Ydf&KSYh3@v35lUBFyxh(}JQIYvp;+)QK_-HVZOno}f|}D_U7KgcuT#92 zDQR0R1@CHQWKc~xq3^w>#*WUL24{O!R}X50LdQg#S_Ss0-b&@ltX}59EJf53^G!9T z>;4kiL{(@dfi_hsAPY)qoid1!T8mk_=$tSJblvgrC&*O2IR@iycuj+g1>ng!HLW1I z;3>sn&BxMbR;b-%8d15QEn$n&KE~`Q);BLR^VA8sV+cv}?dAH^Af8q9FtKV%>mVer zITQUok1hXkwf~235gpA0ZuBsD##pez+`B;d{dy@;U@KckkN_8LLOK6MHBZ?5E<0MP zpplQdTDwKwmI!5COAz{4;b@mFM5fAMLR{lN^Yhg&Gc~x3vh_fYNUF}-Ffx7ZvtN?E z)*|tAV3sb_PYZpkOxvaw3q6th5z~}ytDs)@cI0e**oRHu*A^?{DjM<8&e-^IF^!pa zyo;HgCiZezuPM)%+sAiaW5|g{CQ^r#)B>grRr*E}xtywE_4eaV9dpo8!YjjRhmSn1 zsHjj1e#28eOdjDF+KlChJwwnoF^?kUga((~`$^TL)>XP*qBA0ND%uUZcZsjgv z*suMopL!si*<5jUrdeOjfrh(K^L({!DRZgW7Qdw>Qub8oZ>yL~RB9Y|aE3>anNaU*_)*`g(d8WjH=t znrmjh7%uQ4?$b463cxxfGE~Ew52l+(W_>Pgdwgv%RUldn{;_tiXUV&v#w34JS~oc0 zf3JNCYl<$=lb2tMU7nDD)}xgw(Kb0^_@RL2{;I+LZyi%C$YN#f`iCQuWL)8i8V}>` z&i=^~eC)7EzIAWNKekWxili&`#0=1|tM(cY^^0QW73f!tNV# zJI`yDXTaz@dCTbB`96^ksspRRpK0dkptW53vi6~YO+*uUUgE1cWbTi%pcQQfP{&USM4g%M) z^y4q)+Em0=vqW7kpGC`OIoK@=8)qu^1Zn6bC0-a_Q3#Ey~`@kkC#9MksIDQ|g;o zsy0jAvMK|{hng%6Ckx#^UiWZd6^w8%4T3dOHnc>rampW%{8#2XlnCkDa6@mv37Fs;^qoX>i<4-hqL@d|8LjN%JSdDH;inY|D)@& zqS+O9#fI>o_~sLk`S>1|Mg>HIE`e^qO%O^uUb|G{w{P5m!$-ne)7lu3fB{4jB^<|T zHWQrpo3}#nP#zW!3|cF|edrmz)o1AH>)@yS?O;rQ89~%#KkUu5-GbI-J~&Ruc<6g9 zTgMjX&*#te{o^MP1H&-oYUG(GcJt7;#ly4rUvbiUtIP!!{qE%Akl_^9=rh(mBP52E z5#TLNYRaNWx1Ew!`rXBjQP)WP>VDV%$Jjf?h!Sn>+HKpmZQHhO+wNX%+qP}nwr!iM z^{?c=INz7EbF%O1u97*bYL3i$#`BK(DKBx^PT%dlAKNW37TELo7jeJQ9+h}X zknejg;v}4?;z>(x21hLlg5W*~Mp)Qt8gB3{k;qsSy>8A|tM48bN^*dP4)D4Gdl;Hz zq_}!Pkc$yUhMWnm7e7~vQ$T3j!Fp38G%ExGoH6gG_G?5hO7z!Z<`nSICX_t%QVmia zsFV$~hF_^H_e4SkJ5uez65pIY>)j*A_v}M3+KB(vH*CdczL0v_fPe4tco~&S8$f#n zpl&O%zeT|_2%49=bCa3LW5?PDIFOEBjeG81@Y15|CJ%ih#len=#@Q58?&AhyY3%^C zsuG*uF{yomzFoIhIbg9uY^~(PzXY(i?cAJb>a@IA>hL5Ezc;kcW2|Eo8cIuV!@ux+ zYJ`M+Dii2=B&v_V_&N3JS3LiFcfMF{^f#?%XaCR6?UG8P+=!bsf1)MyCrN{RO)V(| z{-NDe9t0!0If%xKPx1!DrR9M}y+io?ktp?3YE$}4WX%&qLooi3e#s~=;5NK~0l+Oy z^+!%)wuwucS1AisNY&SJ7@lfrLG&fpDWz@Bmz-KkV3r>nzmuRwhxRjNBdj>2*7znN z*MZHcxi^ksWD^l*#-8Q&7A{GegR(N-GdQ9_+9SfY%^Cj?F_VUcgPq@{L=zPzc5&A7 za7@8xJvlCI^u-Rz##JH_^PFt&BTChzSOQO$JJ2!pakv}>EPZ?t`tnm|Q+=kf;OsEP znv_cYWjxeZN+W~qAI2DB6{u;o34`owwo&82X=EAHdX}HKNXyD z4Q*ROGh&_D_YEvL1ov6Nx8+c^GDuI)4=Ms^DLYdPXgk% zzA1Yve^wapC53am{kcq=`wbe%KNLrwF;ykjUxZ4;US4d4ka~;POM7PC-NM zNnUU`tc26>kd~f4a?PCBm8ymxrd=oBUGQfss)-P#OpM)-u>EtUs##?G9eQxdpq+c; z!=k=O05L0cSE6|#--wb6_lyiqS2Y`~sXoALbWq61Gm+EGnN=tQzmrLD@&UmUD)H7R&ygsb5yUz5+^C) z<)jp7dQYC!Q-rJkeUUa7kzSHhO4x=Ny$8;kRa4t8Qa?*ViYXF$mozMOeEoJqz#1t# zz->d49#C^NsjK}W%zKVslYM6crp}IuHPK0UPa~ zYH-NsGB;hEH&#>rlyvvT6WOc1H6$SQ3`MUh_{+S zF~{3CInDrFw6|llTi|A8CzhPA<{#=Cz;0Ijy7ZbEj}g4}zo(yxjjysVid-t-MVZbO zM#aGvqRB|25=sP=LB$f7@l4b4i71wm$))Q9I?}%CKejC58To0&+YN}-je}`u7|SRy z<#`Izy~oX+nu(LCNixuQ#Jotf5ip3YHBKzcO30=nfQToOlT(y&U`2SWia&Qis%WxI zDG7D)$HB%bo+1OmFv2jI9g!bR0-j9*G5+b+F~6eDI4N+$uFQw6m@}l49ugfFeWcO3 zWW*i)6X^s(iI1Jb%^jsn_s$rVP0mMXBg8>j{+nerA$iIx?%&BFZ|JwNFGByR(En9G z!_4%*4l#8TWupce{uTNgm9vvZnqNsbM5$hXKBy~7m1oW563qr_(d&NCKCz+^!{Q*L z_i5Io)K3q+<(&NR*J1)IU1ANo)-aiUCLsG@5t=?4;%tzK_;LE0s z-*oFu3YaDTlP*d9$B{?nAkyJn!Lyy3U}4&IVS5ZRRLdoiBtksAkA3v0_|Bx^MEVaOpJ{=v<#HKU207=4V2K|zQmkx-6Q9y>(Z8ts;!o-bX+_7 z{SR)63Y%2#AAqv1lFt8B2iE_luVmun_@B7GuHux{5CcN@C-rN(Ql!46#Q+A<6reDE zfg7Jd!fFLUYDhKC<6BF!9Gq^vfml<~3Pml}s>KNb-@0P+dA_=qR`zHWDg-$XHEs!} z1nG9*ARU-pVf)|X(dpRUbz?e?e7ATJQ_O26EV*bT@*z;I z+Bpo=2^~_D&yGommM`}oDcv%?FDL9}8#QuCwG`$__g;3*GEIROZ-Fb^0$M_))o6sB z#`hEVw@(I7Rd3DNadvqj`l;}3gbuPt+IUx~W48xV@?V6!Ut&MU7PnYpA0>!Q^FkKB zpM~gA_mCIxA-80i|Fqu!m1c~Ync;t}cjBIP5Cg*4-Z%B*I%6oA)s#T6n!3aMcO&gJ zBboVGx@7p@`Cq@xslW9Bp>v)ccWYh2qN-|@*plyNE#-zJwq?a3g7Rtrmivnp0Zc^P zj9yOm3(m;FBY(2ccYz_@^X}$eK6-=g{c^2pLxa@*9=L2Tu_nwLT|QU^FwCiH>W3lz zm1@Z}(G-w)XH>@%^CqpTS%%%FZBVBkaJv*zD=TzM@M1az_fjB^2;^};q3}Z18Z>AJ zm|6i1q{&p5Yy9qh1W5jR%lT_8OWoV9yLjOy7gy+!#7z~CmmpPKL;QM7vB4QhT#Q8N zn5du#UPe-lI-mVSae-B_Mhs(@qeCwWmh8? zPX|+aVM!4&dpj4Ef7cAc{|^})BLgEF^Z%^Vj5oN3iu&en^ihtt5lYHK=J0v6t}#;J zdcE;ADH;lhA|fbaNrVeHhL`6>P64rMW*`I=7Iv$Kkv#>Lu~9T*=FDl&HDTAU^Fs2s zkz3Q8|J&AF*cqStY4+3Wo;DnDn(GZ!($vY$sRsuKjr+aBCdK!h%r!k+z^#=cEi$W< zqXD{Oz7R_1kLrSBe&6F%pUeT+xJjeDcVpR?*WC}Vx-0&)9yzBgKGpZB(3>GsiB2s+ z&+g{=X|rQ!&z4u%$17ZIu3WC)sIhn!Mn-xxKJ(Jd&fL(1W73%bvaxZ}Tk%=?>{XINA8$$=&!KN^j{^`PbI!KAQlWc$;vWa+`FUcAH?E;%nRuijA(uHB{R~d)SASN@oZDA5y=tD5zGRvS-MV}&%%6GK~nFpPRoJ0A@J5+zQuY7@! zatrk@Q9)GPNPJX()vubWYU{Mx$XeYlC*2fX$+-~T8dRo^V&EK^wUC~Xsm+tSiJN1@ zN8v~5$Gc9KE29O{iYfL;)<~6+xPO14V$Qsr?Q}Tb)KAb(IQ?+_W1|UU>SDZVI=A-i ztUFPAer~UN>--md4c`Xw{vjtpc3=%)?%uPv8C%vib;dp5Z?AW>SaeJ@Dx6h#uNgaK zVi@!uFSsjh&3EkfHoiv#S!TYmO?SNv`MBLS4ahs$^6Rjf%Y zE5K#9MbH&_KlUt>!~9Zss=z4yinW7)3+y8&7#9z{=z*X}55 zf5%5?+l4UzKi2QO1B#0Bf!64N(K}OnLAguR&0jZR4M5!hXR}_5f_r`evMQXRRSKA2 zjiJ}CPRXoX=8;mh~poaq3R z!$k!oy9^_I#@5n5T7Zs#K~(tr3)-=6q8$-@gW&Q6V$O{^UjcC=tYmFIy@j-qPs)K^ z>v1{kvTxum;<7Ro9QB7{fqHOq(*4jQ;X?vdZqQ`ISmB{tFU&-dX;ZI0C>yqx_5lDN zBrR}q%wYg^blvO{^^hijYNJHePq?A$Z+nf(+EppS_b>Y@YQ9i5_uDyT0xGPd$vx!`atzPVJDGyz*ZsF0;* zvkXtQ;m}p#wd|tsv;gjAy?W^m!`F|Uai{=O=x=k>WtZprcJ_Io?4VIr|53qlHHqCwJOEk~W&+yf`gw!>B)ONh?r}*c_g0j17 z-KKIADO-*n{16M__@Lf@tA+pQSlD8$ofXe5m#&rw_H7=j-9{ojN}jBXA71jbd3OMD zSB4Z$;DjYTDk2mkoD30Ck+N*T7FxGD6(S`<_svkFwfiq38IOtqSCd!WXPjb;FP}|G z_b6KT5E^IlVb?mUDMx3ph`BRL&Wt72{2D~gOMGwW_wv@rpTX}SW=s3c5x<9PMl}5c zaCGO)z62b?C2b!U)mSrg)I!luiUMIs>5K4e1-rYD?dc+cdC>F9SaEYe_7?ct#te17&|B25)Cua|;d=5&WIdptdUO0!04fN%F97`_Am1Gm z4&N*+o!nri7e$M4zHW2g9063|3vX@6Oyd}aol~q{zn1&0&pg(cB4w7>uS7;I_Lr#r zVGXqW8l`|&bX$Myf@C*e(PgIKehd|iMqfeKN|Eg6I)D(XoG6PoD4Kl70;E@LJ&%ab zO7ipHJHYQd|DX>r)A+De?_o#2N4F^+Lt7t(%Tw#%(Fk+jfK7K0NBjjuK&>o`!>Fo9 z5A3{YCRmeUb5gTJ-*>D_!?`Y;?$ytRe9gCE@Mp`0a zaAt`yB|I|_uuL&TeZ7@{Jj#VffJr**b5Jf34b*t8iUAG0&jJKN@Fly^t#X|vh&zb$ zF?5o$%as_Z6^~>2jdYooW?y~deav|ZzvGywD_HCJ@KaDg(aJmP`%;0Mdj6X*HLK(O zi(ciLVfwTzM(f@vO6c|4=3jD*kSBb`jxbAw0JNjVHwi=sDn^i=oV$;fX6P2?#kZ_3*mY*w5odo#GQ z6F+}(o}#FtR*~&@ZUF&dJ-7?tr&~%zDqK}8&%nF08qr`Cgf-GoR;a|-Q)di^Y-TSM zr$Zj2g$Q#^0{C=P9b^D9bR|`70B*u#svpwzLY8$lsK%_SwAx|g0uAea$Y~tfowfsg z;X+f2!j4py6|xU$h^4}3UYF%ekHaO6lS!F;{^D+Q^$~Jsfh+5lG1XJW<)tFzhp7!R zZ8G$tIyGY^g$sHL@a9g8U`-@SIqoBW3fU%Haw{(FO856Vj2C+ul|}Tzi;B~m5$X2< z*sp_FSBWw3sVxz@far?5=YQ&4*C|H40eY`3uOT#_9EgaSNfS+!Q2KqPK=@+F5WDd7 znKpdNa2bM7IW}N+Lt=JrPj=_g|vAS)c@Iyl3>a&19FS5<0$$dyjbtAgMHksbPN913D88C^%4AjJBO6p`3sMS zO9p|IhtEQQ;@>~IXc~&1+oT>Y#D0F%>-K)l+(!$fza;6FNer$YKPV#yF=2ECNJ~Ne z@T7OyxtXBZ0N=Up(+$W;OB&go# z>MZanc2h{OCR)xzn`I#TrDMduEHb4rG1o~2Zrra zY7Jt29tr3K!MOmy6`#6r-pGe7vbqpAenl{|o`=SPZu;U@QO}&KaO*_#*0156-k8DH zzY$@LStYNfFQKm<2|}*q@{QfVtmKAwiKeE6DHdr_DOYJ(#@0PrS!mtM`{85p@Lq?& zl?_{y{tkosNV>?$KvHvjy%BU26vWj><$Eb*X6r=S=jrjfEGt=0R{0VTtTM-9sLXSE z-n{gMFY;k;f#?W-9x0FwKx5jhR67Y81$Tcpgsf49ZNvjp#^Xvmc~(Z}ZF5|F5?fmA z0cnVoGs)$LUY(1(WHPdHOg;L?^|V8n=Nn?*$fcFTwlZO2Th)stK5U&~P)vl!RO=Zv zrhHP>g_K_SIi2nkFi+s2PUA(;IMFlz({7=K5k8~D0*@cz9QrQmR6**-Np9z&;AjAp zlW|01rF9pv6{LYiAE?StE-GI(xKDMyWgyhWJmnJ?Y1C()jz!#f!^m&r>xa+Gsj!Ox z`)H?|_nZp1K+%8sbli`p;8C8tLL5O9S@mD#D)4x=Qm*6i=+kOH9jR(6)hd`yk4#0=8;Rkhm(V>!Jla$ zGsef8AGSWIx;rbujUZ3boyJh;o8V#>UiT>B;)dZ7sCIUCDWP#y(#kzR+uLSKk0R8| zS3;GVJR*e0OBHgzQU29mcR>*7#FZLbinhJ}$52r%K_&#y^Q#f055=JSJj(rs_?;`( zM+V$UwaO_+0GjXiU=@+Re}`#;-}M_(NZo)EZVYsrybWrRU(z5q5pSEQw_~XOeIUDw zqfzyx{5_(+eBm{@6Y&)#`!9#1Y3&4e{n=#u{foSwyv7fG@G%ePa z_zLMQiNx-9ls26{AOg}5Pth^6J9Al}6ih{8wLuLqf0|e7q;!QvuZfELun9+hf|T{8if0l zC1~Cnxp|Pupn7IjF=69E0INoC~YNK-K{={t9GoRDhl zl2a=-;q!Qi0^G&s@$d^TIe4r~KF!u8XzVxnM(sG>2bo#3^>!GDa}@|9jH76ec$5gS zAFHgSloySyh?Wl6boc@Fg*`#<&p{sI-gi}Kr zzh}MtG?g5{w(RE_LlOOS{g=VPdD*)^e0;JlKbH;x48B}=9{X!%j>(Ro5Ee)p0O{rX!R!f z79|13+?DzfqeT=i-9}aAf4=Wq+^oRob9Cn7`{(worF+g0ubmFL;LPB9LnE4&mk1py z@R7lx4&BS=e((xBW#S_=If%9W>SPmEYY~`?mW-AHR7yZMEx5WpH84?GnZqNH%FoV< z!^kC>$+Bmq;z)I*5UNrFB@GOkyR@Qey>{7lIp=N>3hs(bJt@byI(JnYrdz!_=>qDa zB;!nS%q%1X1P}^<%K^hn6CAgp_`!F?wMyqZqT}wGPV)K;h?v=U*^nhnwfe1O$JFp> zfPm0N8OU6`{1k;0uy9O8m(*=OrToM8Ie&)t`L=2%AwSpe-LUBr{r*0yx0po+g-pLE zue*ezR&3d_ut;)A{2N%pJuWz-J!-yC5U&qaXT95AOVorbZg4<$##HmATf3Mh{q(%_ zeA2Lm%O*=7SHG^A+yOuKsO_o<<$5&0!|J4orgd6+(mvuyYwy>&Xn)~xYvSjW?SZLo z)uMUgzE!aTY~4pQ=nU^~sppVeu{yab)*dh^z2fSC{OI%XVKv>4zZ(K)5d@+n~)>3ZljyH{f}z=POpjWJVQ(+ zs`t!~PqG*1y4SiELObFtho8|w52Zs0KXv=G#*La|wcFmx=|!@_2vt)?)r>VY27Kx= zDKxEIM5rm!t-U$LeG!MMhVo^i)m(hrTUYfrz7*_ShEIv*pCZy2a0pY_ekcB$YKYNz zx+whw#7rPq5ufU#3&%?ugSH{{yPVw)&)m$~Ged0?1BddoyHf&lf}l2{j>*7NOy=wZ zOiyZJSCC(->-n=}RnIeS%j^CX=M@?t{YDVuixZ6Y<+KrfH6JS*u=vB}8yM_E&w4m$ zZ3I+9&qWE4Ta_k6`^zOfsjL>yknuE%%!L%$0Jef9xHgX@F)=a z`#Ehe<^F9bv%$wn*f$%ADYM#9a&zn|K-;!LU*b4Hk3dd3=PFg}b;K+iF zI!L>Ia#{yOIJ+t>CF$~OWI5Hd)Ee4QrSd(^R`^)q5ak5Og{IU`C6d>*hE#5*e<2nR zONPTp)^Adw4N%hvv>^u)$(D={2bcBn_wn@x$eUwD@h`E84GRwo#|*rM*$NG}!JU|H zcjbT6K}wx>@qPyM1lX*k=Pc@PG3^CxgR}!1hkG?c)3zMsvL@A^c_>6E*8Vx>N9!sg z`2D%4h%u@mVU2qEe5+^2{G?rju1JW)?I6o7 zNKQ%J!_C23lBQbMK zuw1Z=AEjzez65bw=AqR`$w5o(OWfajW=uOsM2ZKAh)>K=6iTlP`*&!evpNa_RyGlz zo~bLZQO|qggoT9kl(g}htJTXzLksgIh}|oDCMTvG2YEj6aR(eALm?x-OJCEt^5{*x z=+dGxd+cgLXF2HsHFhKTs=2U-d2BxUhO6e5eFUSa1R}|O{2?Dz3?=VP?ntWEk)`2#(-`@xv**b^AE3SCSTzZAmtR)@JDmewkBmf&M67XZYqNIs z>)uKYOE_{yPadxxsVaNO$EX}Wct9@}g-+}Qq%TJ@E!0yg(wi>9*8w0&-b4pZdvZ9lJ=P$L zObN|QN#YL6EU=i9l{QOxHYJk#_Do$%_*KWF+!`+RFOZb_Hh(TWnnIYT5nRd$s~ zR^-?ulZCWfa-lsT2lAFxUSOCC7}&IeB_1s$J`eXdEB|``(kkz5^0U0WeB3Onm)Z^o zb=4R1^^ZCDBl3L=V02aC84GqWpo-n-IVQYYc1)hYlNVq)P;PsItcP>}`5O1B(nOr8 z%4aSru7dc3T}yf6=7XH}tC;Jj25adO5YZB4ybDm|kjpyesT3Zlo4N;N_cR+a-LQ_k z2AUDiQNVI_t!psb{Vck#fPK(sKBXnC`+5!*dc@hR%ipJ4fZ+nS`}3LD!pg1=atXz` zrvKqc{4`hA+3ime-FV69@!v?}3Sou^q5Fr>eRK231}$hUuXa)bp`;+>E4F z!Ke@Iy5hp|Sh@16A&;xcPYHbfC%z-MNpl3@`nqE>)lf8_kB6FuTcHm&ye+OT%*?lE zO7P|P(S-H4k1_FgPDU$(;&3e{$6Z_oNmcptuotEl>8puE!mwLsMy@Yg;?Xbrc1j;^ z4i2zME}}HdQ$EsX;BBg<659v~?<)NLgZZbAX*k7hR|eYQ@ON@%tIyxX6Yp7ma)jO8 zuQYA#3o^|wiu$M8!hNs|D7H{6Z=QWw=`|)=k}E^g5m93>PBPq(b&Sv!Y)|R1RRkFm z8#Ez$i2b~L!v*Eak=3kxfkcYhSkeZhZF`JCsdvHL$1Ukj=VRug?Wcf9XpfSIvug zZi)3UX%=8b8jvazn!lT>5$qwkk0a(Kg8ab3(wDVB?N>-e>)skS&9fSSY2fV3HU>~_ z$S!Oa8(qw`>v>4)>-3f7A%Fg0perQIMs-P2>g|4+Ddv1sSX*mwW*8k@4|?u8*s7I^ zXjoV41dFo9DOt_*Yfe?#GX>4;(q&1b{L2&#xI7KD|609(XQ!4#-sGL2jw!7&CCMG&#O`F+z<<83y@e$@k#=d%nFE9-h;;1x?u8esa zz0(G6g$~3l$&v?d6r=X9h?)&@Jd#ySaK@iMOGJ9xvFVacbzM1`?a8Trv?0e0U-DBa zcS{S{7ZR}Zc<-fKAqauM?hw)`%;MKx@7L#u*SdLlC#4_!><4-)oIecJ9vq!Gb-X4K zee9bMW?NuA@}BJ3ulrIfJKk0*DvO9mEYI?Jkjp;{>3w;T<>Ui2=Hjbf6?P({4h`l^ z_<6PV++I}AG7|}d+d-Hy!Kk)?2=zP`r>}^1(xrAg-Bw8R1xm(HsB~Vl?pR zP8+Z|r06u*6@*(VK~kPO0iLS2&BYU5CT-)@%LfR3+?3Ev06kmBc7=q|jqL%&?<*hv z7L)XJ>Ug#-nx0^l!6s#RYH57F&q{}?9am;HVzO)fv}H>;m#0VyR?v_*&{MZRB`G~$ z&Lxuz-lhB{oG`^(M~Ud+Ts;sDS(oQxAV%*}J(_O??x^fqziU)zuDh4w@e_D`_?WP{ zV=m#NToxC0e~b$3u32vGV&dQ-400`MsF1uMfu;t{7t2lJz2;^2x>_BJr?46>FV?Gg ze=kmM#W;yf$w@An4{wr#h)xre-srwWz?mAikR$mU+pG0sU{cCYV>BuM`8Ic+^GCA@ z>ND?Y0ozD8>k^SIze}L2N6B>O-Df;NLdH#OnM5ot;}%da6- zXNo&;%klSn`o=fT#>!--p{OnIs#WJsNEVKSyrhJTl#HZAnDbbnb|XgQp>*>e5sg^~ zhq%bLBq1R47mBuhIFsVL#qJ?3$}n#-f(9}O?Lp!|$%1-< z7|HR;^@p^6xq#Yedd}U|YPy9{TxwruANn8Eb=@=BkN)S^WkGw#&;=+=J`k^^RlmE0 zZ9Zc-OtJi`S`gc3ec&D$(ZEH)AK56p~pS-pDm_|aeFoe*yv*3xqy}*^tW%u zl5RU+=+?r~iy7T`JoIjFgjL^Fer8128-yz;Or>nL>n>LKTwqqWH-X9t5Cx(=)MewU z&9(eRK$W<>)!k9QIxn;<%7Y?}b@h7@=ArT7(S0=)ii}|WE{C9 zv~|;O7^|aB|Dyz&^i&w=sk+^CZ}kcZzfxI|poE>9SZ4_MR_R)zg#1Kw4Rg*EDtJUS zFHhe`s@qE80JI9x=E;$n@G#ZuqI>Pclz{(MqQ6vDU9F-FM$a5L_(O?fX-Hbo<5}<2 z+Uizkr+}UPkrHpV2yeaAeADaui&^|lq_yWyvFZ2|S3P-seW-^v*LM{Om%zDec%uRx4c0x<53+_=9hZcPP&`1 z>^o;Q0P`LnrzIZjCsR0rH-^_*`4JjJ$_#YvC|mcS#X`p}y>9HW4l_D$0Ev)>W85D3 zYBv*ipmh+EEg)>o4L`B;XmN=tDXN&!nfBVXHUz7DR(=NfiGnM&7u>DBaJnY--KyiV z1>C03V4~nmIh3Wxu|K)YC3zH6EzB$Ak|?lf$e&8gpHlP*KfCG+W4uklG}Ax~Mki?M zi;MYvn+aYL(41eqk6tzAP{c9yUKjD|);oHS$$3>l{yL7A<&BD7UumiCTvzbqee&>^ zrp~IkGD{efIy@CHX6lDfo4`-?Mj?fVv+Cdj*ih3<{}+c(pFt zEZ_ROb(&I3Z}F5|b}cH@5z#e^OFC^zA9YJjMMKL9^MtI>&FAl#JC!&bZk69qGiZ4!{kg&B+NhsG-l1)0e7Z5B z4^0}S{1^-JbXr{|eEJaM zNVH21wxNlgWRI72khA+H0<-J$DCT01t2X@IVB30D<`c2n6`=#8Rasmtl!C6RDJwWT<6` zB7sDCctw~N;?mIUg zJxTR=Yc<$+#Vx|OoNv7G`*F$FZfYd?FCAf}Vy}2bbBtq;IAa{E`sr-CSKfFJ8x%(1c&| zkd__pof_#nzXyB0(h^sm`*&HPP)F9IeF2Y03U*n!RXh&2IKMQ>ePI0bGpS@y_Bg)Z zqC#NQ!5;n$>K+CIkIYBR!O?ht|1=8>>O3EpTlxWyrWn84&`~2Hdp@Uc{1Orq@J!u# z_c|e;Yzsj&?Cp%_54;|~e9b&kos{A)IBUb$FJ7^0-|)9r*n6Z?*um{w0e9mQ+;ov3 zw=uAK|D4ifAL16LOeNUZ{et?Zy#YL=I--{hUy4myV;VZ?Qa)Zsi3p z^pnmcQnHE9CioVmk&b~ra4?BUoicPt;u1MNARgl36AhV!{bG_Qj*clGxlJOc6Qz#< zow6m488G7|#mH)zoi4x9eLh z#YW|Z$BJ^8@-iNx9uuC76+gy3%BrUf)+~7b7Br{_(Z_-RvA;eWU>^&5D6f`}n;2Rf z)f{@~h%TGcxa(P_#AcF;=7VdBire$HS0H1EW-MxMs3gu(mBlP0fIH?gRTleF%|8B@ z6;e1&E;lBsx#rg;GaI)lu_yX1skRunwg3h{87(J645mmK$?C5ws9b%wTdSuKlP_XoX?f5Wyf&BpF zrqH!trR=uP#35)0h$=AHA^ZpXJre!4OQ#Of&DB&O0y~b-rcHj-9>etEYu$DLy>0{L z#~V-K#l_^*E@vsZHnEf3>}*}#1Q4Uu64Qx-bPKPLdZm=~>5DT$y!1sTM+!fSdya8K zgC~w;1X*ggx6LO=?{dnTVjpWKsxp#&Q+Eo_{c96pik|*cc}O`@By5a$-asSCLGI(~ zPOU>=VBknzLJre207V$b0Zmsgt$d|e2-PHB5Eb>dshgK}*ar=7dwG35p-qdTTn-fY zh27j&kLms7ZY*Hb!azPMk-og}u)&E>F}j&IytxnU4iWECVvH+pI@htS&Wpu4^$Yn` z`UQGNQRzxj9C>m0y_a5Q-ZG^F75^$?x5wOG;jx}8NXz!FF4|Gw*B<2pnxwDDEeVnSNMxi$5>?^wmW}q&@Du{;ByCcvwlkBxN~5PbRa-uR zm+%=&DRo~q5??w14vGo3utM;5qkiNiW8r84VU5a5V~s^+Wi81?mW#_>ac@E2f-+uN zW3agW*S|c9HDnvuF91RsV_j=`7ZD<_J6Uj|kI~l$yF+DhV&3Qe8|b&^I{b^sC4Bg( z-WTv*MA>_DqF$??UZUIL97yXPSwF!);U<#!AL_+eVlm&IC2O6d79$(oYAp@|CISc1 zpfRMz3?&uYc}XLxqCig!l19i)Wx!iEkTA63OHN_M9NE^BehOLX{YZoVqHK_|=d?GI zGT8P4t`SiD9RQ|>FhkYu0=B8g2LL&bbQ-vMjL_?^*$@YE(%_WwS4mbbg?;?>`>bed z^@7H3W~BQTHg~ZiWc7XazVV7?ZSHu}C0KI0s;(SZoNMWqY|h7(`hsn(JL8p24hr}gUA~`St z7|;(qMfD8F2+rXC`7*Lpaus!$BUnWKoO&r++@RT|F!6_RNb| zL47Bx;ZPV)^Gd+H{}~RvwZ3=I!S{X#9_zkxkA{-18~+B21baW{7|BBjRXN23vgfa=S!)fE042<|d;^?1Vq0~oOd z*Jne}L5f0_K%VPX+0+8khe1sJ3vlNS4bQ96{x~mAZ*Kh1pb`CZ9+7cDp4;w!88Ln$ zetPGr|1p#XIW*myaF!{Mi(na+(_$s&d3f4VnG^sISqa}!QVBN#E$kb<^-N1et~v%p zO+>`8zq<=sn*wkVlP?P1jm(CiYc57Rh~XZsRw;%(N0?c6k@#%$M(sO|P-?){!|Q*| zo!;T#>c+CULuR(NXXWhOA2H15e<%9)F~a3@XsIL){188FlQV8_KVsgUh_9!wY47JP zXzvRyia7k&Ip3ZdlUxd~9pjuaX@+ zDd#MdD93sBdnZmW$M@2K4u?C1sbh3bmKI#VY)LHlC%hM?V+N_B6he!&I+!q|5UUfw z7H~Li=X7EnO&dda_Q0mAfN?$lx;=6E@nu4vnY%bZ~n>5tT!Evxg}uq`ULQ)vuL|n@hCdHboR)hTAH&V7{_( zrt33SL1}3Z=I=w@+1a-W6*CBbNt~GsRT8bQRt5s5Y1RjZV1SUon%#>J6ciJDd6SYt z@hCPI5-)(T1Q%OTMV6>=Cu@i``NYi z&cEz?p1B`d#7#Rw>ZvNzoy@(qzAGsD5UIBRw*GeXqF8rZ`-6^T=u40f-KM_vc+qDA zf0aL&tZQty8 z&oBR5Djt-xCb~73{nx2$s*2e|32`c;K!eA0@x;ymq_^&IZy8`(a({tV&tHAI7`Z#p z*`zOvFOu=2qRxl68#B>!5eV!aZQTReVpZ@5w8Be)8P_D9PZCx+pY&RtTJex^C{f&T zYCSDUTMZQ|K`ObD7G&y@nQG=1f%pS=^L3W~047ih%jVtLT!C5}vrGkfq_a`n1G~K{k(GL%a zuv4G##c=zLPL-DCcvEKn>SWPUa|t zBA2=Q+>|=m+^%Hrs$bo$`|D5akhE3b<`MnvH9|AoJ-8TX3Q)sg%Ho+Jh#ZQZwgQo7)f~j*c&B z$;v}0$R?K}h9C-j-aMfSPjz?@xxQh4+j3Cx3L3>Q33qxsK^>9=Lr{OZ&YEe9K&Ea* z2YoI3L4#04Y7+B}NIe0-$l{oqr?rQZle59w25ZU|6aF;+h-SD&x?<*u#aysX-|zypiocAR?A zBNec;73p%R37jMbqZwXzoKiP@6T~5{-~g|Z=P=1NdY`AXIZx~HQBb8M9)e{;#d}bh zMGrpnvcz(b2Q}^%JgIELBOGaX1ocp!fIIjjg5`BRJC|)6sEByMvpBH6mP8W`DcGqp z$CdIG(IkSGCB;#((3UENtSQHdbB^lH>9p5@ysT1Oq^{oWwT|5|XdD}2OFHMQ$g2o2 zV!$f)6Iw08qiJ052JX%t)8RB)?Kb()?nS}mCm>TdSI?D9t9wZTA_Lk&dxlZAN9N2@ zHoj}~Tdva@b==UlXRlssE7(ipUv1uOT|{B#n@Frt|96&r(Q?qS~9End66!J9^R^S{I^a$ z`v>s2hNr2@AXIw3`|ONjn{~n%_buDh+2VIeWM-*VTYjSuB%0SU*3~UIdh3;UVhB2ci`cp znKV6}=BJ(^KQkY0t)1H+m(0rW;_=o|VirUBkc8qVYSNl38$Goty_5UZRlF$u%Cn;^ z`G@cJ=u=0=lNAF&haSb0b_Sn0h$ya-D$sGH&}rBt-;A^NfGElA{K#f=Ly2Tx+=`?Q zU^3v701mw*{z7(JjcRY>uQ##E&K0x>Jmn#!Y{WC2zTc~E;CXRZFv^@mLYuv;Yd^(N ztA~jM_+%>GAJ0OQz!hD!p!fCp*u#A>@#^&zp$GE4uW4)Ty5AQL!DoGv(nT#n`{2#= zp@jPOVd-Z59`KKqb=Xq-eJ7(iKi33T4@l3%b5t2WIHm2O(|#oS-BztH&$5VU#MODN z=rg;nC9ON^gZpyo>wWh2{f8`l{Xy;eOra=JG?<3%w3?$vmd>tq+hhA+Iuv<()8jYG zsHqu5?KqLR%B=nqU|!c0^39FFf!&y%7&uVifMFF9f8mux#otV3{RKJP69M^yJ`U`^ zDi`@o{iVZxLh6UtxrXT3Q`}lG&L`z?<*N8P%YV!_BTCn>tWMSErXiwcf@(Z?XTR~T z#yuFtdju;KDoV(=PgvUZDn2B9+^a6`8*^k?0!ThWIclAOP6gy&I}~SmF82{;W_Q9>#tlXfYa~>Jof0j207MZoj)k>e3Aj#a_%*Jx7KOcdkva8 zG&do*kjv8bbk`oeh6$>H>aDq%PZ7OfkZ=*_L2igbD|K}f1h zNJo6kC9RbY#*VB`$>NIgD-R(@2t@#=gHBF1h$kldo8cE}X`qEX$V*DTVJdP(glCq* zajU--WQxH?b7`vsck8X;M(8?(I&C*Dd|+Q))t@{+fRoqEdXMA&Fg#ACUDom*qQ8{- z9@l<(Q{nM@^FoE$yC=uO;$h$w+HfV7g@44ryjJxFXmg5kj-N^_2b*65H{CHcfhALm zQ)?(5jM(gs5%kpzRgvNCMHy5iRr@du(s*5ZVftF^JPT|TkR@L0FI~e;VWI-7Tf*&} zyIw!y10I5oZGa!8$3L?dG zm1JF5&`8Y_Hs5VaVv=kTuvhfU?!zqjg>zMXO9I2*X0{tGzRJ&*pn`VeJ)SY``xCBU zeiU%!TwTchM7We)_Bk{aJ~z{Fby&LaU884)+B&`Q;Xa&nczLer%8jv|$(7@FF-RNp zwhC4afmc-0QC>Q}b%KZ23N9fR^Xat8f08!ie_sJ|W$b}pwRR8s#Qs7q_`P)lpIY9& z>i)dvVk&*v0ooy#>&(UZf%u_YaRXd4ji4mv-5mVu;~g9_4axaQ0zGZsJ;FiSD;So} z0)JyM%)j1gX&qW>$5cA7)Ql{*VX6JE;Q4oV*zCS{vQ31m-G%Ej>4*SnRn9i3(G{BN z6$yQtptauUQ>!SsQ>OBkm_|F{tgUtc`=Tvq4t&=QiSBM2?9>H4XYn0r?slK8m*>P& z4mWC?OmLUmq0giD|CsB)PyBJ}UOfln6Y=Pj+Rk@M`m=js7}M#%b~CcwhV6FvE*U1gZ!L)jO3lS9szCw=iadS2P5gZ&mqUp;&In8n>csb zTvFOtr;wwdP&Vd7!arx;9JhWx&ax?o{k)ZVgTLx&6l+`9{lh87mdwIdyRf?BRtpHr zhS)}sJX+cXXX^NAXU-hg;`N8N(4(x?<95XyH^QS7qdLs9k*#>1bK&CJs0r}*qjWXz zUvSXOumSNblhetfDJGaR8O<7i(mUNGg!N0dq-Vu^w@4Oq5+Uq^1?yv>Q21OFFUp1p>?2l~IlhgvY+iYuxHZbWAu7x9!&Nw4R_G*LC?Ixpi}4~?5v4_+wTy}w``6f_9i7NHV?ctYta;2 zv_;3jIWqEIAUen%ICaK4H2q#C3T!*GYwFB}ODv@!bE>* z+ej1EiymE^?Qpw$WAWCCI`_?@Qv5k3ZV1r#d0-w<_HzO?PS>@Ou|gj82&MRw{b`ZI z`9~$8C!?6uN~sE#mPt+S(#>XdU$$m*fZwie4CN$-_HeKft z>vpAJFp$y(M5YL07YUWzrD z?ypOp5PavSRio9Wnwmu~X;eE+Z73eDY!4Y;@EMMf2gU-j zBwR_4oTvv-q-k)B*l$~G3T64B{=qbN?5Hu5kwlbSYZa_%tdF$DP0hEBkdW7}Gx{dE z)UeAEVa1A#&`!*=h>+j_zm*7me;^x0I+SlN^A8ny8F|1-6ie=1QCvJENjkw)16+|M zIW@?l;-B_6CgPaf8B;LrhQcCa$zjB{LAt1+m#{2^x4ZB)2)iK?l1^?0c&=E_|3pj2 zTg(7kbxkwzO$FODnXGfYTJImJChQu!KxZ}EC^d*!m|>jhKAA*f+R}1uSfqT>ESFf} z)Fa<#&TKDRMrrza>w>%02z^Ce=^1iP3w)(s6vkB|dG!~GNl-eHRj*W_fbXw}Y5X8$ z1Y%1O%Rk9uH4T|Af1zQ_zBo=dXo}(7(U9$V!6~Z z{2Z=2>7{%HvZ|Em;yJl~IrM0Gx2rytJ!fJ&kMOR*yXaUl+=bc9jwD!2LR(F3VyT_3 z8~dPPC^uuqUW-YmOvXZ=d#PErXycjq$yF!VSXR~E?4I#D58H9ni6W1}a$Q~1X3|8V zTM=1S)Im|BDe7v+Gl!pS?Ze@5r(*c(jp#qOY3cIe+ur1Db%&0IuCJ_PXw|yVO{=i# zXePei+HMg``OvW960mvMpw-mMOei^4vB4!{Gs`rV8}e=KvDC7OzTA-Q=`<6KDr%(8 zK=aGbF+p>pnhLX`;v9ZxZPz-3Uw=4zlE!2_YY!=wbWkvUXI7?0L8CIXuwE~MdesD9q>W|6HP>?IqQ)A4vv#_l}Y<~}<& zHa3S_cnBWQ$fy&za?o7BIWx62a0LScok5LuLN!To*N#j)Dhv2KH@|2m7Z+PNHCQTk z%kHor$nJd_&Q6kpkA=zOb9Jzuk9hwz{P)pKmmLt=DPR3dL|wMN8DNYoDtTba8uJM! zESV}uyfN{>d0!Jz)xLn;2^NIXUxb?aml2v-E2DP;1y~lAxhe6FLyz)!xCz1}^*~4| z2s?>(udmOeH+?0X!c6+KkV#s7mwZ-Q0A?h-Gz$6>Xhq#c94mg(v z$axK_sTmn2fPMw3=>dQ^=5rfwcbAN#Lo9CL?<)y=bwSm;1#V7NOC8LDO5`I}nN~tz z$<$xVn-a{Z4b*Ia&cdhyR?@TwOF$in4w)1JPwN?I(xWyw*`D<@K;mo~)kv;WYBhbB zlCvd43){^vjRz@HJHv*-)+Qg0&eh^lkI*7FgEQC*o*7${rsBklX{oU zgq9{6{lu4(o#BAZnVrLxjT`@071b!M*_|#fkC{ez)K{jNe_M&|f*oCtLW6L1-t>md z$5Qj9rptB*Q%9oza(ZS#d*UhOCha5}rcY(FZs`JDzMI4%_GB7Xxz_Ci4fF1_Mx?afrHhiOzrW>CWo$bo6X&1Rh`xH{|1WnyWlwC$K zmDI+YNFR{PX6Ns;$7&kvw_KkwEW54gG*_Fn#3F-I?|Igr2Ddoe>x!w?ha^c{v{q67 zI%f?YwA8d~>g}RYU2nJD0ai;JC2EE3%+eLrcTiu|UEbPtk9#x*eek%Ox|{f$yc-O6 zT{_`L-R(V@FDJU5#*7#=+sH}N&(^b%QR5E>M^Rf&z7qM5r8dUs-#C*7qp#>IJivqe z`#Nj!T`p1MYo|@2&1+&49yq- z7}-(Nc|ei=E{!JQ-k_1zHy(APO8ovP7ChP}mBS!`uJ!2x{K%eIO$Tk)(qD9LG#23h z3at1K`mX<9T@({N`+u^iHK%%Mqo}2fT0{j>wPXiNnrz`-i}H;qjN}zaEDZ^ZWK+~Y zJ)nSkKmo;AWPo*Gn|FBNBV?q`b>#+9>_G!2hhbojDilB%;uSC`uqAFgm`cl@PfuA3 zxIU(5&rV%^HU4J(V{j^N-m_Oi{s1cltfDu@PJDu4@#0!wpj&`zKp z`6d%*f47TU9%Ua3qyQa3IvU z*y;3cx|}C!vRdq9H#ibkHFu|w!ne~|d1l1=< z`!J1K&cNJHShEm7rg(E0tw!rHS*2@UqO3&H)M*$l+FV+A1>GG@P0=t>T`M>KxU3kJ z$34Bb%h*iM2Iq7*nO!S9PhDbh#yafo6YnGLZfGwruOc1)0k?CBubkYp!&urFE@JGg z3*iZwq^|&1$Rz`|Zo69`S(n zXMA`r@tv4#KWtJqb7C1Z48)i-t5`6E^f~{;t+GvJFmj`uUw5>$ZtX`kf9BZuvv>c} zay=c~G4$9Q+L+E#!n830a7VIaIjBkr9o@)0ncvxE4-hoYuKKV1CO%Q(XFrwWB4(xN z<6+hJvli~s+khfqY+d3NP$e(V63*R>zPrHONwTF?=AYK^?nPh4ryZZ3q$0Bjb1O12 z!TkDH;xxGO{qys1DyUs_y&KQ549lEx{vhbZ>ZK;b)aP+0IHJf389lENCnyex3JZr^ z29WH@M=1Gk$#Jz9}fIAPl+3y(55|Y1r+iPQ9OWg_5 z+_nXXE^6Ra)I{}u;}kl$`X#&hYl|L-f*Cjjb)Q)u7Jab3fhZv*!FAa4Hqt32f@_x*WPaDokptGGDg z>U^IGOTGP4l)g_~6sgAo4aSFwjD}XWgsE&Qu5LF)K<@V8l#Q;;f_ugb(w)tI8=cqt zE(q<2zrs=7EUAJ)RpN@HEwEe2?d3Rn7pH#J){gT+@hAIud466tPEftm5gXh>t-IeN z@>>Pg&9C^bLoeVoKp4@)&*^osJhQe+J&WPQ>IhN0B#qJ2A8-N7%@1~4M=jojzafYn zAy9vy7O^=p=Z%VO-rWfRKeBdCti^bT>Imhm!QJvv^Mxjx(QX$ohhp?T=6D%OHA420 zhd$<%7gFDnyl9CVy9>!bma7wt_D_dj)vqgfHs`XGO(wC{L2C>2&45WR_#g#b9fb32F9gx}+As%TA9MA4rk z=O>D2CShS-U15HHYrRccRO=gNNZN>h?sNS5_I=s~&|T8&qAKImrki0q_44Dk-;(&T zL$JQ{2~#d=u;Hm*KK0kGd0Z2z?mpwREM7s!Rp2i##;Onx>fwHgC;J)n+1?*?^adUI zc_i70kkB^2LU=iSlJzWJW|g<}iIjQLWFoB2`&^x3%v1SNT;pWMb{j>`#kIJ@V% zr8r?@Cls&_W+EG#WI{y*2AOY1Q#ifep##qV_t&n3i-b_P(Jl~Is^1!VkB)+@gWei^ z>4w(b^VD7zNszIQxLD}ijZ|@FfZ2jhMI z>!6ltwL6?C_VOko1dS%u5AYtFTl z6!4Yxb*W@}#Y{l*|cx#&G68fM`l zp%0{lh$2A9|BlceO2*ns(8@18A8|IbZCK4_I@~P=RECV*O)$fvJd|6{q?qLNTUXMC z{;TY(Y(!^`d5Uz$19MV{Wt5iFI4MDfc9vNQU3ng9Eo&EYNV{Nm4VfoD8qNftGc6U&QbDY>hQNahHhT&xqi zeLj0h8?3TjgXb>JH(xs3{N~fvyv>~y4C=QB7PDWWWtMM;ZI$&ie34xiSvNvx&=*hZ zq@99TM;dJ*RY|~W%b2&?(Q#8u&f%-5i}t{(Z;ee}JuQs@e{6l#oh_->3Z0K`JN8n^7pOgDm)Zc$6 z8re~oGcgD?4sQ;-!?F&Hk+27C#YOncA`vWlgN`&3yz743Tn#GBbwI7k&~RuzrQP(O zR5#=31BN|SoPRU`M}VCL*s~i$&{Vw75@eh)%PL<$raTGSAhPdt zw9EI%Zor;w6YPL{#ao+;U`efgS&hfr$uaBHZ?i=oo~U;;MwG_2mNFk0?o&89vd;Q) zo1$5C@Hzbe$M*ip^Myo9!r}%Ns4hGKD2ZWqkyV}i;%N>WvWI`pJ`@Mx$sHNlpRe6z z|6%pIf{NHAZr~`mMAM9mv_3&$)MnEGzx*lZ^k!r5AiqVf(Q)@oU^7XRLXnTxGq5Ef zPMbYBIaP_6JC|n>>%*=~t5LbJ>N0AFS)Qx0jrPZ_^SEUE;Cwgl2x0%-{*y7a>{(#d zWJ4*n7)7)^2`?|(O-9AC9u~csHJY3MfyohJ+69uT+_jE zb$-uti(W*>!F91_RN8*_2hhcCpwIu!t0Cw}fZj#l1@G^H9ys}e9>f#{HCiHo$NS0G zz!wn(p~{G*iFN@iYX#9Ao1-=q+k7*y9x})0xSms*{j6d%DcUd}5yK4Y(~S+k3A!Xz z?C|DmOyTd)vIDIN2HXAlMHTy8{PZ>N?q09A$L)P9_T%?aK;0kig;e9?XrrH9T$L<2 zv-{TR&qD1jofQvK*rq>uEqV2ARSoxFpboD?cprf9%f;28$w!2-QIph?;j>WVNU4}( zfBuaOCg%%>5%}9v7h4O3B`@zkb&+qX9`MdBx;Z4{#n#rw8Gn}ZmM@fI_+YH^+h%7N zzc3<=IZ;l2S>QC%@|n8O)w26wr(f6~0VPW?)M>2`e6kEz+T1({m_($;#=rP$CmA|5ZYU|El&hxLGl8Ydb7_cug5b8NixHD&Hzz7y{_vyzSF_aRX4PD$CAyH; zS;WXcRSsM_z^hVmL@0dFJ#y6nkmZ?&``ws3cID-EJ$y%P??UdofVVs@Ih5pV^miD7 zkkIE|-H$(_e@{mN%`v(rVP`yF7oza(LSD}yhC$g_+p*1l4%*-dz5WPxhzGwry&;ki zkVvDs0;MusBz8qrv;*v|QCvg}IpO@8B|R-`o#C^w2af=oDr?%f5n?Cwen`S72Hw%? z@cfwn8Nm0x1N@Hcn8$qa0^oz1wPbBf*9vRPuf)y{zQqZ;95K67{ep^qEd*?{6ZRVf zdw}MK73HaOCBz4B#5HHrS{L{U)EuikvvJ1ihA-^h!vtA5XjQ=Z0jRUVEfMtGyC&IM zjmK+17(MWOLh*&8uK~=!Yl;mbR|8A)8_x||*DIK|w-J*ggpdAXh8^&`n~$!5-4W<& zpE{>Q?+cm@u@XM0)!c!Q$98REJhQwHzh5ey6PoW`vq_jzCGj-(d76Z&i=5858KCAKq~`3B;P+8)fw zE}T+ud{#9_4wet619X8<=|I(+q+?a)y+!H!hu5DLa7OZhv}+X5tTTNGqI)bEa#)aI zOdHmzbG=)rI|}Vd$`SYJhoW?E-J5qjkk0B&unG7&DEW||3Bp61O#U^GWq|cr5PUC# z!kReSKi2|S?!;ECv)ytFY)co|#EzJXz4+Lm_s&hdfGF&0b zx?{MMa~s_HjW$JZ4~4DaM4H-qK_Yzqf{<^uNCW~>#Zy-y3M_{U85s z5X5(KZb*F^u{mBiF(vi9q<RK7gE}tYUYCXEly5<~dpc16Ja&mOFMZ2ZmrX zZNLwz?m95?_?4W1$`dYC6*yh)Qj=X)sbSv}d-?!?dqd#qH^g*RqG8R^Ah35ySAp$rCSlYMI1 zDC2t#!IZS($%KX{jZkVMNXmXv?TGxLHV~SAsW#G3(h(kW_?^LPLa#TT0X&B|+qfpN z-qE^IcLdxa@b;i10zY|n3cMxUB)AKBEI6#Ve51F2vwh$dkNv9C$cgU_*V7pNb6?VwiLbq(RrY0xzc#W>F;V!OR^;9C4WEvU{@?OU!sZ&*W&dr19V3g=Q9Oc7G3 z0t7TX0YPG95rwgOb-$}s)TQx4S~v|D9M+-W5v?(r`4qrBm#;P!{ZP@niOh2ZR?euq zau#PWpI}q!NI8&=bfx(wF8hK0wV#(~x89w$ zEA*MydWXMOp1T3S;IjKmT&ix#RX*(GuhSBkslF{w?oKbce|ok0@k;@F4;29Ku-8zn z%@=Q9FOiHkkG>UjAhQo<_RJE5fDj>};v^b|;@{Q?e5@JopkZ=v!B6_QKKpsfgLFHs z+qsExNB8y!@T%BpnZVXEp}J)I(l7K;7KJx@wBC;{8r)J;e!Coh_XoLLuPryf&w`>n zEj9g4+WbSRNnE$+@P3!cC0es)vKHE}Ke=9OYhG(G`F>C}e1A)=aulDp!9GeDC<>&t z+TzC$V@V!>a*3VuX@m*VM(-(9!Sk1_vIUa8ig!!ZKRPLR>1i>@_u5z=uJ%UloEG#; z=GcBezzl$j0Gr^P6K4&d(VR1Bc;$t42>I&Yn$z)GoQI=y6teHRkby-4jSim~N{a5* zgeUukeIYdU`T}`tbXx*Ny&J&6Ll8=m04gzqq|9U?)2M^I3ftaDY77TouCej98r}!1 z!lGhxCAsGAGUa}MyrzC--m@Pf4jF15lS^|vkKcd2Z|3$^)R0E^*>P?(17OvDpf8id zP~sXi?ni)TEq?-Uf={N!Gx1yDc_wd>L2;&u#~poD{lHx6s4N*9Eg^06{qak)luYZI zz#Pc~WphEZ9T9N3tk)?JkxKfUB7kax^cWNn+5o+=kV!;mV1YuYL$MYF(mX82RQ@p4Yh&+--S%B___N< zW68;MYmtk=?^R_rqtT3zMiZ=XB=#&n?f{S9E8m{lL;EXTPJ@F5a=6`mfOd-b|B%hy z6a4VTiwUZd6mHr;?w3vG-9oJecEZe#YR2r>2OyCXI7x@cBeF=u83HXF_8BoU!<+do z&T`{eTP$;@zkx+KP}`iRZIT;#@0x{i=6ZiL%K6qg3>r<~d`;x`Y_&Oj#wA-#@FjWQ zJnh}CSbz4b)@ZgDI$ZnIeDnRDuaE}`&fM@grF<~HZIaxz+9z2?LHGgU!krWO(xt&^ zbv$Jon+fZOLdqa55>r@Z#Fgu&#r|XHwj!_{fOpcfykA_gi>CD`dlh|cIotvM3dDESpJ&N!5Wd*~Zr*^@R1h9X_akyrFfl8?{pBn?AcB`cmqC%_h6WVUzrCt zO`;N!o{>;EbcmAJB=#T#=&*z#HDwUtk?V2Pkoo;Y%dmch@@emxm!Mq)!x1P+Ate@+ zX>&72Y2wi?bha$>RWu9PoZ?4ZfRH$FL9xh-!jYXN7NiddKn(+KY#aF1DQK5y;#K39 zk9>6~NWc+5btEI>V^%@b)v z0+9-cgPHW#b5CPOW5a`IF&$^xSJNWf(L7B9}XazfdhS7n8 z^sH^Xx+fbvR%fO&-EKB;#`mA!1iCP5!^~|}XeqeNUfagd*8+%>_^9aqY)|Amuy3mb z=FA4<0OxaQ+Wx!B6^Jn;Jb+C2_f#TwtWbXdcvV2hS1Y zo^T`yuR4@+nM)jDB3L|A#H$HFB|QJbwq$y-z};M25ExmUGUuOvzH!HhBF0G%jV&qL zWX4RmTaM*uGbIUyvle-iM{D^VLSqI;Fl7d0W+^ujqNY=$6^^7|)~=opR9MP=>W zEoI*&zZ=mEMLo@m7h>nxBmghlGU&2?*GhpfB4eerUN~IH z#b)rK=JC;jO}lf*HO!N+!8iLx0p{cJE)4I{>J+M`u-P$r4KOkMyc*kfX`bA3+HJIK zyiD5C(c;lt5wCk)+ggKK2feYKxo!im!B^2VbfadgLP(Cp661{)QWM#9PwbhZam`Cp zAweVhRi{t*Un7_8*wed7y4{z7kK8Vg!&|*Q@YY?gubYcP=uO$}91^F*TPtU_o^MIV z{k_od8q(TpE>EJ5{*`j2j?ow@s>!vQi4Ux?4g}X5(eS^{TEb}(avR^z*Zo}IUPQSN zVt|0424o7+V{u^XjEqaLP|*7E47i^i(tGH;0pwO%r9}??bC-W-XfpA<&+@_9Y%sql zjw3GEemu{kt;{Ul*iv6+LS8>-eqVsx{MH322y*}AQk0@4*%gk0|8uYUA_=_iQ%s{7 zSUz&u3fSzA3T;Fb>+A|;CIBEKJre8JUS3L2PoQqR?i4k>Gmn$cyuUJ<@O$8s8~)7b z498wa{XQla&eCrG5;XZc=9T5T}<*$--kNM-301E@1rcqYor3wL#r z?`&G!3d$wO=T;5_vhsIeU4~|PH}9S+7_lxjZ9tg9P{?$2RC9B?kX=oe!tdSRDSoqC zZz`|0SuCMB!b$y%`>{EOzO!M+z)H7(Mmgj{_x0+z{f6fCMGMpo48ZTCfxO@g&0b_> zID$ai{Jyi=zYgH>!rx73DC~JX zjPttWTAh575mWjWVf-#$ z8+bAegjieMF!BWY07jg?UyK_0BEX8GMllo6EaD1v&TvpMU1yCVh2(uWK7O?^zr4wL zYI-G~wHE_BwHNEa^F1dI${fz?FHKSP5r1~YI6DU9;duzs;cs&WN%w@6%R?q|3nmW{ zrG^SIuMsc<3+mT(O7Y}(_`5-c+ZfA&eBr7Bx7<6Rc z?i>}at8ju0J$D~eW6(jP$-g#7yH7l{VC5T_6)y{hK`J}@{#bwsTIXYAS9{VDora|b z32wd(AK@ESn(MMo%a`aa01KRP0@oVYROc6>muT2ggx74S`nlY@q1gIE!A_4ZA%i zmuzZICh-Iz%=T}acx&L&L$hIZP4X69Q)G2V8AGZI7V!m>|bJ_fDtifw2SGcvfgr4wUxYLp^T0gQGG=+ z73S8P8%#${ujei}5wXY)eWgxm zPa?TsE$6WdI@E~a6{6pRf3N63cm*C$YzdV_wue=ry3u)Kig>$te-s3009z^vBy(OK zpwe^FBsGmnwxSk2o(p!Q)kvi-JfDX;8>xz`nyad-x~mGS8mlU+I;&23Hst8hRiUq5 zu1H-zU&3C-;1c5I;~L=Z<09hz#Z|za$7O(YXP}ZM+;cU)8V9|@}tldK>t@Z z4NV_DAIKcCym1{Q>wPdot98hQa?)oWx63C1a814dEZG)xhx7LF#esnAB90{V+=^4+ zemI{Isq+SB%OUu?BH29CaS?)CfK<3@X>x}*35!TZdb6K<5B zE>rC6mGtfnI#>K`-#}wohWC=@c93`^%)B%Jq>3u$4294sM9SbGE?X^zvCLKF`EH_# z^!u>NR^fIq%U0<#cw!S&Dk3EI4s?7vF*-+0Se5xfO4AlISn zU#FVM!PLmyI=bl8Idm>|(Ho)*DMr=`z6$~EmeB56CDIWV0$HJp~JK&V9w|s*%*L`m0-3BCn zw`uB|7JcN>%rhtaef8=}aTv6w=JjY0pbD@7`7PAv#;=hhw|q|zlZiR)x9g?%i_B~0 zWe(MBFFe=IK4lw=po}YzQh&p@T8zh5>lC0=UZv!@gh>wMgM~ZvH~~dMZk9a28!r6= zw0}C_Yyz%SSz0$M!n^3Ar%| zKu2!bxDusM1M3dR!NP#;OTlwT%1=25(N|1xPU1uM4<%BH1%%2F7Iq$>NRI~VF8Zm? zQV3hvQJ%z18|J)7GCr$I%BB+ExD9s-aV^YY8!1r7nHGts;MERa5W^yht}h`;3QlY% zA=HpwAr=2qg1Mz^5XvsZrjcRNAO+{s;}C1n(8qM4mu1z07%V&BZ$ZNGNxPmd5?CvCM0iCCQpjkbA%PU zqE|L}WA^e4n6(>+EFZ_50)+rJ-xIh5z7Vjf5*~E>1jCv8gtU&MG=@ElWC1SVMy1*5 zG3ffLBN@#>$1tp;C6qU~d?~I&EBzVQYAnO`M=GN6NpVwzN67SM7f9 zhPPPDqaEIjDu>O15pR?Z_v=!h%~xjpz|_fL0_v-c(hBzI8kWEcV8g2MGbH1?>=J{c zJHnM~We(u1Mev&@oVN;%uQAuJZ2ch^LO0AId)MI>0%x z@`nc|st&U-mS1#o;)gb(S$Gk64U)@F!(yML5(U8)>Q#!7{9UePw zDmVC#95y_xA;CCic-`eV%3pD{TH!_Z-upQ<0l_$|XJTJ^Ke**QyYGHlZ%CCwnKP^n zfmxY#Iqa{R!BkN|vVw2=Ues(s6y1=b*Y}NAG*3@ax$MwAw>ZsS$ZoLiS*$kMhTXw4 z)U)PSK|6P(yC(qhNd6Z&-oTLathYu~tSfI%2V`CwKP%iw4+y9UE1CwI2)oChlnE8tf2y+jB-% zN;XVbrXSuaj5&yTd>XXZDNmPJy)rYmWWx5YAPI9shzw`%o4R~Y~r!CC@(E5jZ;f^G&TW1M4dEe-io-<0P$g;^p4HVC$eF6 z+s76Gm^kRK0Z)ZE@Ma_ZAP0NvjCmL9(4P(rG$#RgGqbVHNJ}{ZE+o^G>&i(fC3kKtHce%3?1j$06SLpFhtI0@-ef*uKXb7? z>an@UgI5EoUzGoPeZ_e;?3W~|Sg{*0C!E%fW&p~3;cF*-{KmW`_X?e8%0w}K-Wc=B z&o*@cop9^F-yVcWs!rT3Gg%M%Rv*+D>~3XfPhup4og~wSmS*_4z$+-xRC#Ja9Zn9i zTkBt9H?JxDaR;z!G~L%cL9L)x$tdw*&%{J8JRE?OSD6yRV!7glLD4+cc_v|l=2;Fp z6mys0Zp6{KG?b$|tb|%&XL(n~uL7#AGE>i3N6+=GFiMSX2@+~ijKAH1#ttpiil$Xh2gt$ zdgAXk*~tW6XcdMH+7XB9k#lLZY}5@(a{Z^eDSGRmzwPGgzl^T_g<#%4*Gb&(N61jSZbMRDyjHh3oug-t;>R3Z8OukebsremBV;7cM ztBW};a1VNOMD%E)O!PzxyV$HWfXg`AD8JQMV8f|^&J{qcq6oGKe&K z;cBUU(r9!`O!C`~=zUXk^^zQFPT_ zjKtlsvbaKxE~QJNz2+cxwV2=UH4aI>X?h{Yw9kJ_&%$a7vkerhGLTPJ-Q=SZU)Mf- zT_Y+DGImep=*Eb#J(k(MpsRFb9^0c=LcmVl5I>{-R)0%=QDFa6GF+OhFRC?$70#e5 z$g1vo^N1(57&4EDp3GDIx5CacDhlvh_k`5YFqGsV-QC?iNOw65AuS*!J=6#c-5t^~ z2m*o#2n-;tq#)oR(k&?*&i!)lS^u@p{r;}?e%bF{d%x@VJkR5T5V=D_3>ij^h(98QzV#mKcYJNi@3DTa8!6uC4WpSo9zBAcIT4uFTOpG~uNUjg2*X#q37h zlWqBNM1X8WGWxKfJh`4o%s$fQsn-D7xN?wU{s?*;8p7oW^jnmyQ?HvE0HKiNW~0tG z<$=16vOOLg+Wm-tVV%uEiDendGZJPP7Dq{uTOC3vayF2U>y#!J@gR2h}gQ%qRs0N(Wsl7^Tw8! z(1LH7&P1Xu;2J@FYI#TPRyak!;iw=xId|6vNobq7xfn_#JuDezrQj0+i?zg$-8(}l%zY0m7zZY(% zq4RX4uMTJVnu;r*=i|nnE;%yDPgS~*yd{PFpdw3O% zYc-xwa1RAD)>?Z`IxbP%`aUlXrI~O5!?nO$ZViwGscc9QU-d znbJxtT2!kIwJGFQroU<*Zm`_rcC)K-S^hu?ZJCz#w9|U|v&L6VC;T_tV6qtE+v+_TY(1Est?U-@L3f_kBoeeMfh;OnzGvoee2&R);`oXo0!Q!O%${Gw}qb#;wSQNU7Ro$oH(G-?|{o3FD?Jad7r&Yi~oAnSY^ivEP?)RvJucSHitePJ5g<= z1-soUpiad6f8{NImVsG)HR%TBbInt?U{g6&y$ehbzWg^qCXQ@tC0F@sX}Mj^Y;uix zMmzXTs^HQ2n?|UcUSkgjMI73x>*eO-Ml_N-$$L^4`x9!}{4Pa9LX=TF)3~XE?#bp5 z-r}DIs|_36Xk|W$pt#c!#UqOfE#+A(>eYbnnYBxS(tVYkDguI|%@zn-Xb$6+pPS`q zm}ap&IAuy8{_+YK997{IINAfCV;Mujd8tR)ul)i~Sc97?qy*JF1o`;ea&pGmoskta z@24H(r8RxMHhSbVeWMDo_mXsZ&?=f~6<7$f%tr$lp7`EER$gSz)@0nmK7(dih12t- z!lN3l>PObjt-~hY)@%b+WS(owku%B5%g_A*J4H^(dY@}j5S!;Ot1Lcdf}gGqO_nqO zYF_!d9FVJ*#yf^Q+gD$5er3!R&(7kP_f^R#O7}BpWqWRDtF4WYaEn1xJy<;mkuOjmwh+gbc$P!riRKU8KHaj%lENDuZ73~)rq1FB;BQ- z?K}j>1@zL!bq~5oWH97q#`e3Yh$#F?^SL1Vzq5fkD@TQRlo;F3FmdxdUD%W&J+3mw zrCw~(#B>6|>e`RF3A}_1TYrJlAHO~~utW*+Vg}aAJK|*dGX2ST+HCPFXE|Z=&8jR$ zQq%mCuWc?gSOb1z!wU}mANMcKyXXsQyR%>SKe80;Z=rPmBS|7k6ChOc~ppRBm zg|v=UKsz_q%h{#Xb^FBLM7~xPf3)^}Sw)X5&8enHASKo3sCVz>n=K=n4}IUg9Wak6 zY$5&x=X%x>Z@fp< zXVnE(eQXk^awu?>e^K~N!Xz|*S9~V#rY_&*#?Q5_=Pl@U)OvBXb1iZs;`BqgTLYmT zW}jQbEC1HBPLn{1W&BqaQ`evV9U0DLiYl2c z_RX~-F3q<+>`zL7h*ZI@*i_k3cAD#YmHX3etqnoI^((gP3>ASU7G`dAs^(~X1U`*I zkHI~efx;iQK6BI&@O0%e2KJK&{m;R#ETiYLz+pokb_XqZex)xI{F*=5g<~fs=TjcK zM`bO1oTaA`@qq|ks1n|YXd|_RwLM3hgU~sE;I@oHH(lT)7n&GWXs2sujuHf(zJe7l zZ*iXUpet1jxX|J-2E4G57?d#O&h^ssGEI@7g?-1JEqM(Y$( z_59H8mPNvHfPPPyG@CL?u$pM7PNU%rfoa5D5k;nxNL?HwNrzmd+~G7by*j-y2Xy4<;k<|2&g|k%obS}A$Tsi2k z54>nRKrnEPSzd=pn~kybZHmXKkk+ja*%FlPKxpQW)wA?{huSG3%fl2!4f8NV#S}CQ z!~m8c><`t5WWe<&am}l6>7`P{#brjoPix)=W7Oq*db=jWB^(mgZbuB5Px9i!beK^ejLo}+qS)4@U~Ag%BpXEI&%c84UaujvSa z&IeeKN}w|;5kV1~+#F>dpivV-1oopVJCmo9Edj_|i4O)Q0gZw(zcPYUTly>H*r5VgZ~Ux&y21az)f%5Bmy0UU@O#yu;)OAK@Y_Q|z9i#75N)AtAQ`{T zzXGL3{?iVWR3P#0;LC6jrL>l`BlWiA=tVfQTCOfaU!A<>LI*l*{N00Ot9a3ap*#>= zuAn%$UI`GSSEBnkIqZI6aja7j*-q!)As@)>f{4g*@UmfJhyq0j6u?O=JLGJ{8g7nk zrp&CBOzf1#Sg=H8h?At|XthOyiVll**?!eU z$rl6zXvV)Nkzd425!z%1hXa<={iOFy;UivqQL1+Hqv6VU>7M=<6^S` zIRXf9h{~?n*n-N*(p95l_*9P7C?KFH3>sQBEQdFdDh(`M;_()d(L*|Xb%%Eo9Q{8_ zuIjr*Z|R=2CFYv0UPm3?5q%-`zhw2ErKG%QbnAHz!bN;3C3}OP#;5jO`?{49K4iVaHc09Kpw1_L%-BAP^WqBwQzmzX%=LPw!+zr&f1^%thB{a{}I zGlCCaA~}D&D(1qaBLe5)Z>X2EsJmrxB?$juOJcLm61=A*rYwv2)fC&uv2aEp^)MS#8CeT}M2uqX0;qaG`Q)<}nfNew z)Z&1uM*r)=sF>*I3<_fTGo&fZ_;{Ln$#HIm^R%&XJyiNi<}d!>bw5RI68SY?Se0h9 z=D&?rBfJ&w0^W-ssBZ(A{L=V`yLC$nC&(5>^8P+HK zK2Mi3YYO#`#YvU+txNd+5yT+DqsCIJac~wQT+1L+Yd}3aW>+ExTLUQZOv)s0q8!#4 zl|dhXggq^>PUjuej#O;Gr#`!zj?!3Lv>Q)T0t$^;v`J&Nm57ssrd33QJlC<_M?ITz z5a#@hufof!UQFf6tEAq)^o88u^)Xqh9UfGAh~zU^3ZzAlZ<^l{Yv^;c5h)%rE~lLd zD*lWVisex|AA;}K*od8DoC;5X?LU28GkqkTU2&H_4p!{r@NTuVCchSt(yPBf=H#|6X)CBj4Xyq!{-~U}+Heax_`6kfN>{t0yMCzhY zXc41J^R!ZK+>%0Ek@L@Drn#SMrgJt6_Ryt+1J4lAl8ceKFr%$A8UA|h`52jZLp5|< z1+2P;oyOI!(TSOqVwqoz?>f4*HjKTrrP%#4bRgz>!@#yb(m=W_IO$M%UN$^Tf@k~8 zjq-wnb|1*YppsnI)G=LZAaNG^VaD4`i)qg#J>=+_>i;xa=xE9>UR9mpJ>!q&ztMRzUgVswElzh*uQPM2{7K$7w%dyu?kMS z)>W_6VKg;-J0}-RQUxFC>?zcz85(LRd@?kyu3Wso{ja?my%{Vm0R0yx{OR@I?B(n* z-S#G(#tJMWN(Y4x%QTX0OPz&xHg;+z!0RA8h`C`G_id&xV78ZUwDB1|E5@{L!=%RIF$ck0f zWd)pD>g4fi!ydTWF~5!Hw7-~wUtbV)uAK^U#yjl`r}?8%LgxKGlKX#HCvi z_~nxtsLdK0VG;bL6EEDJ$P{5P@-lU~_I#d$AN=;N`oT3zEUp7mTjlxgEZ2GS(#!xq z3t&ZrG7TqItmNZW{J2+s{9d4y_I({eNgTgqqW@xdX`PZUC@s5CqQn~JD_u92onv@m zG8AA5b~9B8FWH8NsSt?jEr-t9t~SHt>dIu;X2w~)y?D-HRFt5!lDchH;oy z6_2v;*Grw98aO%jnbzOmPNR)l3mFCyOmY>YL&h&uX#Ey@A7ZOMbnihR?HkrdxQYRL zmr$LR-~DTj(z_+%!QapSrW808pRNhrhAId$A^gcYb}=r?+WR?Y7n5}16G`Q7-~>l> z^P}nwohW^Qau+o?eBZI{$B=qsXRf|Lor^ylewf$srrITtu5*ja>Gs0khO}k2RJMpA zK0b+bp*Gj{QNx+ERP4;JZ!>jjAP_!^^U5~{eq`D8n>EC&-KxPQfCk)eE;ob=Hf-?p z#hf#^jkWQeDX@V|weM5bZ3orYh8o?vyf==8HYw&WVcADJqW!%jb(+kCGC_aXNk8_hUj7*z zkSCq1m?FH?U#UnXTH#9zbBnrt?B4gQr{-{j66FN@dipnH!Ljc=PQJ+o4eaNZEHpdF zY?Ipe3kfit{J|y%@tiLuU@0@lY>IA{e4=Z-j%|WUi)N=;Ul`Yi#~gFqj*u!ky+b^` zsV+5o;u4j7?Ni|1x??rNnn6vzvSc!DfJEY2zxNWUsOU35zV`<%YFAg-Ey(9jQZhf+ z7nR|&FxuiEx7M56B0Hcp1u~i#X#NUUr@EQxw}vEcD%BZ?@Ik}lXA2YJ+Dr~+L-5)U zQf$#9nuI4(mWn#r;GEv!+&^sI4jyp6KP?>@dbDS&U#m)EMhuYCi|4OXHLmkSzH9$Y zNm&ZK@~4kkF^TJ6g;deL!QEli)!=+n1OfTGe;obMl5J@X*)y6+_StAPe_aGgk$J3F zO$}MT-D;Ab{i+kX%?9wNE5py9bAp0L-0vAhIPYs)dI?JG6ORF=V#}z6Mqn2cqv&?i z#^J^>UTwGdntVW5=tb|5UBw`AH(bA6mBJqC*=~$nw@v@2IvRbz)LblM7vB9lO_TMo zNP?`@jyjFSGVF`{dYKcFmu&{o?j+)uTF@yIR*-r{tHro9;%qeRq@h6!`KF{!Y|`Lk zVq=l@Hnr2e4yCRxz~lEk4W4AjBW-hzUb*$cF?nnCJc6ZOZh9soAqHF4S z1VWdt-{(;Y3c$y8huKIAzMo9g)cjRQQPgW5$vI0M1&2lxeAD=G|7}m*iz|fWta?%Q zj)E=G2(awRJ3*s&pVz8*S-$>Z(c~x|;MRrDq+j6Ja{T1u(f&$zQ0UyWWRc9g%f>0* z1))LbYm4LY`kqmjt=Q5Ey!=*>3$}KNQx$`s^mLp71+Dm?@ieDSx7m4Y-?V*OStfSX zH$!(1#~>9+SE5y~sJ_-yc9}v~!uLBYa~%H0UuK7Bfyn|tpfmmzutNa5|Io0*hdSXL zq6&%ClnvDbTv`ROz|zQwbmA!OPAwJt{=s%`xWuerwhjTyOM|~s-7_keg-XAC85r;5 z1-&K6Ynp%(qDk|vHwS+xY2xE;&NB@+c0db$DestR9i!DXaQEWY%1JH1u!pZ;7X76E z@SaEp;e5`vhvIE<|HF7icZzr#GKGu#lKg7@Lx0fmxtD{G{iqqtlXQo(wfc!IyR8{u zV|IbH|Q&N6zIaA1=^7&64=eY_TfTn;i@*T z2S9P3)@6+5dyOfZ$|S0CW3Y0TaL;BDGhj}m%2?X{O>iwZ_(G}@v=elX;jjlO|27iO zD`3rO;V096&J=%5#qK=~nvXyNPJ40zd}D>H0NvbS zr?-mox3;SMN_lOP@&PY&}$Jbbt>Vy>IE&cjU+1l`@y3q@$5IuUe5Ag zk))cC+lz#t{#ujd*q?8rhUwnlq#SOr#M|@I29MONClW>`$*zg@T9%YG>OXhs7<{nrON>WOD6vx?Zo% zvId>kinp3{{v?3lHhT+S&eEYB;St|;>39tbIyd(^?3?^#^>$3yrlfsM9WVJ6zTjXI zbx!)(>B>;1fks(!m|hqmRe9sk&L!UMOMa5Er6As>*3v7YNK6sKP)ZS}EM>l_@jfQz zV)Vjg$Gv+e?J5Dy35I~&XZ4D&Uz`qcR)}dFpDZ*`ijruxUiH$8%Jzh$rf&^&$EJOz zztHYn>c8cVOyp!IC9fz>$j!bR{BJTv`&5{9`gY*Z@3u|yAl}CjM^y<9GVb~u zat69keT328fLjPz;t-pWbOTcwDoZ=VRC2(TuUttHIvPu(cib$Ag!iflK5y{-&QG9J z)%AZatioa<|5tSTe^yotBWI|fwwkrv3n5`)NhyeksD!id3t`9$QHYb6u(ObugtU{8 zq^Pr)!vFt-t)P*&w?E*&b-hM{+Fnp^mjAxZNYL0V#F<4{OjOX^`Y}_AMa1@h+lc?C zHkp6+gHg0HFm6LWAqi9TH-nJo=R!)>1oBst(yUe%q1Y1H)D~7NyZjbb!8mr2$@fPM z6QVz*ZzuM@PV!WRN9d20lQ=MEuM-)lvGb@Kot~6rZ%|CC+k|koU@iEt&%b`-5G_7R z@JASHe(1hYQ`DoMKb8f+3VO=78TNgPb}>pS0T$Gvg2krHTB#&bsm!y;@|f<7jRX<; zfiy$x&pm^u2}n?Qq;FL)gZlAcLb&0NibJkAg4|e&Tr5sKRqn4!7-J69za5zN4M_+e zzYtvGs9j+?t}%f%(IkK3F>B(U(#C>nV2(b6_}`Ri{8i=8l?2a~vBgv<`39I825|QW zI6UCD{a32Rve?Z_pJ~1wh4F;98N^c{cl3JUJxkm_&?iVt~lKn nzX~zlB`s$XOZm?Vc;)Zt=O5(f3> включено <>. Но, разумеется, большую часть секретов он не найдёт. - \item Используйте сторонние анализаторы для слежения за качеством кода: например, CodeCov для анализа тестового покрытия, CodeFactor или Codacy как продвинутый статический анализатор. Чем больше инструментов следят за тем, что всё хорошо, тем лучше. - \item Языки типа С и С++ дают возможности для работы на низком уровне, но благодаря этому повышается вероятность появления таких ошибок, как небезопасная работа с памятью или undefined behavior. Поэтому для проектов на этих языках стоит включать санитайзеры при сборке, тестировать санитайзерами на CI, а также запускать инструменты для отслеживания утечек памяти (например, Valgrind). - \item Добавьте в README.md плашки CI и анализаторов (штучки, на которых написано <> или что-то такое). В документации конкретной CI-системы или анализатора обычно легко найти, как добавить плашку в Markdown. Это поможет посетителям сразу посмотреть статус кода. - \item Напишите в README.md пару абзацев текста, про что вообще проект. Помните, что код вы пишете не только для себя, в ваш репозиторий придут люди, которые вообще не имеют идей, о чём это. - \item Опишите типичный пример использования, если уместно, с картинками или gif-ками. Включая информацию, откуда брать датасеты, куда подкладывать конфигурацию и т.п., чтобы любой пользователь мог с чистого листа запустить проект и понять, что у него получилось. - \item Опишите также действия по сборке и внешние зависимости (версию используемых SDK и т.п.). Это всё есть в CI, но в README это всё должно быть в удобной человекочитаемой форме и заодно приводить к развёртыванию окружения, пригодного для работы над проектом (тогда как сборка в CI может быть весьма хитрой, использовать несколько Docker-образов и т.п.). - \item Если проект предполагает возможность стороннего участия (то есть имеет хоть один шанс стать знаменитым), опишите, как сторонний человек может вам помочь: - \begin{itemize} - \item куда и как писать баги; - \item как связаться с разработчиками; - \item как контрибьютить; - \item где посмотреть техническую документацию и найти первый вводный баг, который можно поправить. - \end{itemize} - \item Названия каких-либо организаций, используемых инструментов или технологий должны быть написаны так же, как в официальных источниках (пример: TRIK Studio, а не Trik Studio, RISC-V, а не RISC-5). - \item Оформите секцию About: стоит добавить подходящие темы (topics), чтобы ваш репозиторий было легче найти, и описание (description), чтобы стороннему человеку было понятно, зачем репозиторий нужен (кратко, одним предложением --- подробное описание в README.md). - \item Проверьте, что код в репозитории адекватно оформлен. Если на Python, то PEP-8, если на C++, то в соответствии с Core Guidelines и т.п. --- у каждого языка и даже у некоторых фреймворков есть свой стиль кодирования, проверьте, что код его уважает. Если в проекте используется свой стиль кодирования, он должен быть явно задокументирован и весь код должен ему соответствовать. - \item Где-то должно быть некое техническое описание проекта --- из каких компонентов он состоит, кто за что отвечает. В идеале --- полноценная архитектурная документация в виде страниц на вики, с UML-диаграммами, но если сил нет, можно ограничиться разделом в README, где кратко словами всё описать. Также вместе с/вместо вики может быть уместна документация на Read The Docs. - \item В коде должны быть комментарии (в принятом для языка формате --- DocString, Doxygen, Javadoc, XML Documentation и т.п.), хотя бы у ключевых классов/интерфейсов/модулей, кратко описывающие, что вообще делает класс. В идеале --- для всего, что public, с документированием предположений о входных данных, инвариантов, бросаемых исключений и свойств потокобезопасности (reentrant, thread-safe и т.п.), но насколько сил хватит. - \begin{itemize} - \item В идеале --- по комментариям в коде должна автоматически генерироваться документация и выкладываться на GitHub Pages или тот же Read The Docs (в т.ч. как действие при сборке в CI, то есть полностью автоматически). Например, Для Python есть инструмент Sphinx, который в этом помогает. - \end{itemize} - \item Комментарии к коммитам пост-фактум исправить тяжело, поэтому за ними надо следить изначально. Рекомендуется следовать соглашению Conventional Commits. Коммиты не должны быть сделаны в последний день, а должны показывать, как шла работа, от создания пустого проекта до последнего релиза. Фразы вида <<я тут локально разрабатывал, потом выложил, как получилось что-то разумное>> очень сильно огорчают комиссию. Могут помочь инструменты типа Mergeable, Mergify. - \item Почистите главную ветку репозитория от лишнего. Если у вас в репозитории больше пяти маловменяемых комментариев (типа «fix») подряд, либо несколько коммитов отвечают за небольшие изменения одной и той же функциональности, лучше либо сделайте squash и склейте коммиты в один, либо измените всю историю через git rebase -i. - \item Если ваш проект позиционируется как библиотека, игра или какой-либо независимый инструмент, рекомендуется публиковать новые версии в качестве релизов, т.к. они предоставляют пользователям удобный способ доступа к конкретным версиям вашего проекта и информации о том, что именно изменено или добавлено в каждой версии. Рекомендуется ознакомиться со стандартами оформления релизов и Semantic versioning. - \item Рекомендуется настроить правила защиты веток (например, запретить force push в main), а также инструменты безопасности и анализа кода (обновление зависимостей через Dependabot, инструмент CodeQL для автоматического обнаружения распространенных уязвимостей и ошибок в коде). -\end{enumerate} - -\section*{Чеклист по оформлению пуллреквеста} - -\begin{tabu} {| X[0.1 l p] | X[2 l p] | X[0.1 l p] |} - \tabucline- - \everyrow{\tabucline-} - 1 & Адекватное название & \\ - 2 & Описание пуллреквеста, список предлагаемых изменений (если применимо, со ссылками на закрытые issues) & \\ - 3 & Описание пуллреквеста, описание работы предлагаемой функциональности (если возможно, с gif-кой демо) & \\ - 4 & Описание пуллреквеста, техническое описание, изменения в архитектуре & \\ - 5 & Модульные тесты на новый код & \\ - 6 & CI проходит, при необходимости подредактирован, чтобы запускать новый код & \\ - 7 & Содержимое пуллреквеста лицензионно совместимо с основным репозиторием & \\ - 8 & Коммиты в истории следуют принятым в проекте соглашениям (отдельные или склеены в один) & \\ - 9 & Стиль кодирования соответствует стилю проекта & \\ -\end{tabu} - -\section*{Пояснения} - -\begin{enumerate} - \setcounter{enumi}{2} - \item Анимированные gif-файлы легко делаются инструментами для захвата экрана (например, ScreenToGIF), и очень нужны, когда делается что-то в UI (например, чтобы наглядно показать, как было --- как стало). - \begin{itemize} - \item Если пуллреквест что-то ускоряет, приложите графики замера времени (или flame graphs из вашего любимого профилятора --- вы ведь не пытаетесь что-то ускорить без профилятора, да?), показывающие ускорение. Если пуллреквест улучшает какой-то классификатор, приложите ROC-кривую или что-нибудь такое. Если занимаетесь машинным зрением, выложите кучу наглядных скриншотов. Вообще, активно используйте наглядные иллюстрации того, почему именно пуллреквест должны принять. - \end{itemize} - \item Для описания архитектуры используйте UML-диаграммы (см. \url{https://www.uml-diagrams.org/} как краткий справочник по стандарту, избегайте UML-like картинок). Выделите цветом, что поменялось. Текстом опишите, что на диаграмме нарисовано (одна диаграмма архитектуру не описывает). -\end{enumerate} - -\section*{Полезные ссылки для любопытных} - -\begin{itemize} - \item Правильное именование коммитов: \url{https://www.conventionalcommits.org/en/v1.0.0/}. - \item Исправление комментариев к коммитам, редактирование истории (не делайте так без крайней нужды): \url{https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History}. - \item Хорошее описание .gitignore: \url{https://www.atlassian.com/ru/git/tutorials/saving-changes/gitignore}. - \item Модели работы с ветками: - \begin{itemize} - \item \url{https://www.atlassian.com/ru/git/tutorials/comparing-workflows}; - \item \url{https://www.gitkraken.com/learn/git/best-practices/git-branch-strategy}; - \item \url{https://www.endoflineblog.com/oneflow-a-git-branching-model-and-workflow}. - \end{itemize} - \item Зачем нужен README.md и как его писать: \url{https://bulldogjob.com/readme/how-to-write-a-good-readme-for-your-github-project}. - \item Шаблон README с плашками и другими хорошими вещами: \url{https://github.com/othneildrew/Best-README-Template}. - \item Подборка примеров хороших README: \url{https://github.com/matiassingers/awesome-readme}. - \item Генератор README: \url{https://readme.so/ru}. - \item Гайд по лицензиям от GitHub: \url{https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository}. - \item Слайды лекции про авторские права в IT от Я.А. Кириленко: \url{https://docs.google.com/presentation/d/1-xMvM_EyouDM9slBpQHR3h7MRgYrMQCKZ2dxYeFKh20}. - \item Может быть полезен dependabot (\url{https://docs.github.com/en/code-security/dependabot}), для автоматического обновления внешних зависимостей в проекте. -\end{itemize} - -\end{document} \ No newline at end of file From c21abe19be554b53adb3881baf3488aec671a563 Mon Sep 17 00:00:00 2001 From: iakov Date: Sat, 28 Feb 2026 20:40:57 +0300 Subject: [PATCH 2/5] Rename to -full, fix formatting --- ...po-checklist.md => repo-checklist-full.md} | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) rename repo-checklist/{repo-checklist.md => repo-checklist-full.md} (95%) diff --git a/repo-checklist/repo-checklist.md b/repo-checklist/repo-checklist-full.md similarity index 95% rename from repo-checklist/repo-checklist.md rename to repo-checklist/repo-checklist-full.md index 407dfd8..d3ee197 100644 --- a/repo-checklist/repo-checklist.md +++ b/repo-checklist/repo-checklist-full.md @@ -3,7 +3,7 @@ ## Основной чеклист | № | Пункт | Выполнено | -|---|-------|-----------| +| --- | ------- | ----------- | | 1 | Лицензия | ☐ | | 2 | Лицензия правильно применяется к репозиторию | ☐ | | 3 | Используемые третьесторонние компоненты и материалы совместимы с лицензией | ☐ | @@ -116,7 +116,7 @@ ## Чеклист по оформлению пуллреквеста | № | Пункт | Выполнено | -|---|-------|-----------| +| --- | ------- | ----------- | | 1 | Адекватное название | ☐ | | 2 | Описание пуллреквеста, список предлагаемых изменений (если применимо, со ссылками на закрытые issues) | ☐ | | 3 | Описание пуллреквеста, описание работы предлагаемой функциональности (если возможно, с gif-кой демо) | ☐ | @@ -129,14 +129,15 @@ ### Пояснения к чеклисту пуллреквестов -3. **Демонстрация изменений** +П.3. **Демонстрация изменений** Анимированные gif-файлы легко делаются инструментами для захвата экрана (например, *ScreenToGIF*), и очень нужны, когда делается что-то в UI (например, чтобы наглядно показать, как было → как стало). - - Если пуллреквест что-то ускоряет, приложите графики замера времени (или *flame graphs* из вашего любимого профилятора — вы ведь не пытаетесь что-то ускорить без профилятора, да?), показывающие ускорение. - - Если пуллреквест улучшает какой-то классификатор, приложите *ROC-кривую* или что-нибудь такое. - - Если занимаетесь машинным зрением, выложите кучу наглядных скриншотов. - - Вообще, активно используйте наглядные иллюстрации того, почему именно пуллреквест должны принять. -4. **Техническое описание** +- Если пуллреквест что-то ускоряет, приложите графики замера времени (или *flame graphs* из вашего любимого профилятора — вы ведь не пытаетесь что-то ускорить без профилятора, да?), показывающие ускорение. +- Если пуллреквест улучшает какой-то классификатор, приложите *ROC-кривую* или что-нибудь такое. +- Если занимаетесь машинным зрением, выложите кучу наглядных скриншотов. +- Вообще, активно используйте наглядные иллюстрации того, почему именно пуллреквест должны принять. + +П.4. **Техническое описание** Для описания архитектуры используйте UML-диаграммы (см. [uml-diagrams.org](https://www.uml-diagrams.org/) как краткий справочник по стандарту, избегайте *UML-like* картинок). Выделите цветом, что поменялось. Текстом опишите, что на диаграмме нарисовано (одна диаграмма архитектуры не описывает). --- @@ -156,4 +157,4 @@ - Генератор `README`: [https://readme.so/ru](https://readme.so/ru) - Гайд по лицензиям от GitHub: [https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository) - Слайды лекции про авторские права в IT от Я.А. Кириленко: [https://docs.google.com/presentation/d/1-xMvM_EyouDM9slBpQHR3h7MRgYrMQCKZ2dxYeFKh20](https://docs.google.com/presentation/d/1-xMvM_EyouDM9slBpQHR3h7MRgYrMQCKZ2dxYeFKh20) -- Может быть полезен *Dependabot* ([https://docs.github.com/en/code-security/dependabot](https://docs.github.com/en/code-security/dependabot)), для автоматического обновления внешних зависимостей в проекте. \ No newline at end of file +- Может быть полезен *Dependabot* ([https://docs.github.com/en/code-security/dependabot](https://docs.github.com/en/code-security/dependabot)), для автоматического обновления внешних зависимостей в проекте. From 57b1b88cd1dd0c0f4ab3dde0f60656006b0909a7 Mon Sep 17 00:00:00 2001 From: iakov Date: Sat, 28 Feb 2026 20:58:16 +0300 Subject: [PATCH 3/5] Add SPDX CC BY to repo-checklist --- repo-checklist/repo-checklist-full.md | 5 ++ repo-checklist/repo-checklist-short.md | 76 ++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 repo-checklist/repo-checklist-short.md diff --git a/repo-checklist/repo-checklist-full.md b/repo-checklist/repo-checklist-full.md index d3ee197..4b9e85b 100644 --- a/repo-checklist/repo-checklist-full.md +++ b/repo-checklist/repo-checklist-full.md @@ -1,3 +1,8 @@ + + # Чеклист по оформлению репозитория ## Основной чеклист diff --git a/repo-checklist/repo-checklist-short.md b/repo-checklist/repo-checklist-short.md new file mode 100644 index 0000000..d6d4196 --- /dev/null +++ b/repo-checklist/repo-checklist-short.md @@ -0,0 +1,76 @@ + + +# Чеклист репозитория + +Короткая версия чеклиста для проверки репозиториев и PR , более полная (с дополнительными детальными пояснениями) лежит [в основном репозитории](https://github.com/spbu-se/practice-templates/tree/main/repo-checklist) + +## Основной чеклист (10 пунктов, не более) + +| № | Пункт | Выполнено | +| --- | ------- | ----------- | +| 1 | Выбрана нужная лицензия и правильно применена | ☐ | +| 2 | `README.md` с описанием, примером и инструкцией по запуску | ☐ | +| 3 | История коммитов чистая, названия коммитов понятны | ☐ | +| 4 | Настроен `.gitignore`, нет артефактов сборки и зависимостей | ☐ | +| 5 | В репозитории нет секретной информации (ключи, пароли, токены) | ☐ | +| 6 | Код следует стилю языка (PEP-8 для Python, и т.п.) | ☐ | +| 7 | Код имеет необходимые комментарии и документацию | ☐ | +| 8 | В CI настроены автоматическая проверка качества кода и регрессионное тестирование | ☐ | +| 9 | Общие замечания: названия и технологий написаны корректно | ☐ | +| 10 | Дополнительно: плашки, заметки о решениях и т.д. | ☐ | + +--- + +## Пояснения + +**1. Лицензия** +Выберите лицензию для своего кода, правильно примените её. Рекомендуется использовать популярные в сообществе лицензии, используемые в аналогичных ситуациях. Добавьте файл `LICENSE`/`LICENSE.md` в корень репозитория. Если репозиторий использует чужой код или библиотеки, убедитесь, что выбранная лицензия совместима. Правильно используйте лицензию (заголовок в стиле SPDX или специальная шапка, если лицензией не предполагается иное). + +**2. README.md (описание PR) и сопутствующая документация** +Напишите описание проекта или раскройте суть PR (2-3 абзаца), покажите пример использования (где уместно). Если в репозитории несколько компонентов, кратко объясните их назначение. Для проекта сделайте инструкцию по установке (установке зависимостей, сборке, запуску), для эксперимента по производительности или иной решаемой проблемы (актуально для PR) опишите способ воспроизведения. Документируйте требования по сборке (развёртыванию) и запуску. Важны конкретные команды и необходимые версии инструментов (но допустимо ссылаться на скрипты CI). + +**3. История коммитов** +Правило применяется к главной ветке представляемого проекта или к конкретному рассматриваемому PR (ветке для PR). Коммиты должны показывать логику разработки. Названия должны быть понятны (например, `"Add user authentication"`, а не `"fix"`). Рекомендуется следовать соглашению [Conventional Commits](https://www.conventionalcommits.org/). Если в ветке несколько коммитов, отвечающих за одну фичу, их можно объединить через `git rebase -i` перед merge'ем. + +**4. `.gitignore` и артефакты** +Настройте `.gitignore`, чтобы в репозитории не было результатов сборки (`bin/`, `obj/`, `__pycache__/`, `node_modules/`, `.venv/` и т.п.), временных файлов и зависимостей. В репозитории должен быть только исходный код — всё остальное должно генерироваться при сборке. + +**5. Отсутствие секретов** +Убедитесь, что в коде и истории коммитов нет никаких ключей API, паролей, токенов авторизации или прочей конфиденциальной информации. Если используете переменные окружения для секретов, добавьте пример конфига (например, `.env.example`). + +**6. Стиль кода** +Код должен соответствовать принятому в сообществе стилю для вашего языка. Например, PEP-8 для Python, LLVM Coding Standards для C++ и т.п. Используйте форматтер и линтер (например, `black`/`flake8`/`ruff` для Python, `clang-format` для C++) локально перед коммитом. + +**7. Комментарии** +Добавьте комментарии к функциям и классам (в стиле DocString, JSDoc, Doxygen и т.п.), объясняющие, что они делают для нетривиальной логики. Ставьте себя на место другого разработчика — ему должно быть понятно, зачем нужна каждая часть кода. + +**8. Автоматизация проверок: тесты и CI** +Автоматизируйте проверку качества кода (линтеры и форматтеры, статические анализаторы, опции компилятора). Напишите тесты для регрессионного тестирования (предпочитайте модульные тесты). Используйте предоставляемые языком (компилятором, библотеками) дополнительные возможности проверки корректности при исполнении (санитайзеры, опции интерпретатора). Настройте CI так, чтобы проверки и регрессионные тесты запускались при каждом push'е и pull request'е. Сборка должна не проходить, если тесты падают или есть ошибки стиля кода. + +**9. Общие рекомендации** +_Это пункт с перечнем типовых недочётов, обязательно выполнить._ + +* Везде (обязательно в коде и в документации) названия организаций, инструментов, технологий должны быть написаны так же, как в официальных источниках. Примеры: RISC-V (не RISC-5), OpenGL (не OpenGl), GitHub (не Github). + +**10. Дополнительно** +_Можно использовать дополнительные возможности проявить себя._ + +* **Плашки CI и анализаторов** — полезно для проекта, уместно в README. +* **Architectural Decision Records (ADR)** — краткие документы, объясняющие, почему вы выбрали ту или иную технологию, алгоритм или структуру данных. Это помогает понять, что проект не «слепая» копипаста, а обдуманный дизайн. +* **`CHANGELOG.md`** — стандартный файл с перечнем изменений по версиям, полезно даже для учебных проектов; формат можно взять с [Keep a Changelog](https://keepachangelog.com/). +* **benchmark**/**performace notes** — если вы писали простые замеры (например, сравнение скорости нескольких реализаций), положите их в репозиторий вместе с инструкциями воспроизведения. +* **issues** / **project board** в проекте — демонстрация, что вы умеете разбивать работу на задачи, использовать метки (good‑first‑issue, bug, enhancement) и закрывать их по мере выполнения. +Выберите один или несколько вариантов. Главное — показать, что проект ведётся формально, с документированием мыслей и изменений, а не только набором файлов. + +--- + +## Бонус: полезные идеи при оформлении, дают доплнительные баллы при проверке + +* **Архитектура**: если в README добавить краткое описание структуры проекта (какие файлы/папки за что отвечают), разбирающему будет проще. Можно сделать отдельный `ARCHITECTURE.md`, добавить в него схему и описания компонентов. +* **Примеры**: отдельная папка `examples/` с работающим кодом очень помогает. +* **Документирование ошибок**: если есть известные ограничения или баги, про них лучше написать в README, чем скрывать, а на GitHub и подобных ресурсах можно занести в issues и дать ссылку. +* **Версионирование**: используйте [Semantic Versioning](https://semver.org/) (major.minor.patch) и добавляйте теги в Git при релизе. +* **Релиз для проверки**: опубликуйте релиз, соответствующий состоянию представляемой на контроль работы (для PR -- сделайте PR в основной проект, а не просто ветку для проверки) From 0d57ab1f7ff7e1cacfc483106b4a3039040bed0a Mon Sep 17 00:00:00 2001 From: iakov Date: Sat, 28 Feb 2026 21:08:10 +0300 Subject: [PATCH 4/5] Rephrase license and tests statement --- repo-checklist/repo-checklist-full.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/repo-checklist/repo-checklist-full.md b/repo-checklist/repo-checklist-full.md index 4b9e85b..7b845f0 100644 --- a/repo-checklist/repo-checklist-full.md +++ b/repo-checklist/repo-checklist-full.md @@ -13,7 +13,7 @@ SPDX-License-Identifier: CC-BY-4.0 | 2 | Лицензия правильно применяется к репозиторию | ☐ | | 3 | Используемые третьесторонние компоненты и материалы совместимы с лицензией | ☐ | | 4 | Настроенный CI | ☐ | -| 5 | Модульные тесты в CI | ☐ | +| 5 | Тесты в CI | ☐ | | 6 | Линтер в CI | ☐ | | 7 | В репозитории нет результатов сборки, настроен `.gitignore` | ☐ | | 8 | В репозитории нет секретной информации (паролей, ключей и т.п.) | ☐ | @@ -37,7 +37,7 @@ SPDX-License-Identifier: CC-BY-4.0 ## Пояснения 1. **Лицензия** - Отдавайте предпочтение разрешающим лицензиям. Код мы рекомендуем лицензировать под *Apache License 2.0*, *MIT License*, *BSD 3-Clause License*. + Выбрана лицензия из числа конвенциональных, принятых в сообществе для данного типа проекта. В случае соменений, отдавайте предпочтение разрешающим лицензиям. Подсказка (но выбор должен быть осознанным): *MIT License* для примеров кода к статьям и небольших инструментов, *BSD 3-Clause License* -- для небольших библиотек и полезных утилит, *Apache License 2.0* -- для перспективных фреймворков и масштабных идей, L(GPL) v2 или даже семейство v3 -- по желанию или по ситуации. 2. **Правильное применение лицензии** Каждая лицензия имеет требования к тому, как её правильно применить к файлам в репозитории. Например, *Apache License 2.0* позволяет себя применять пофайлово, для чего требует включения в лицензируемые файлы стандартного заголовка. Также распространено использование файла `LICENSE` в корне репозитория и ссылка на него в заголовке каждого файла. Поищите для своей лицензии, как её правильно применять. @@ -48,8 +48,8 @@ SPDX-License-Identifier: CC-BY-4.0 4. **Настройка CI** Если вы используете GitHub, Continuous Integration-систему удобнее всего настраивать на *GitHub Actions*, однако вполне допустимы и сторонние системы, такие как *AppVeyor*, *CircleCI*. Если вы используете компилируемые языки, CI-система должна проверять собирабельность кода в каждой ветке репозитория и при пуллреквесте. Если интерпретируемые — проверять качество кода и работоспособность. -5. **Модульные тесты в CI** - В проекте должны быть модульные тесты (за редкими исключениями, где они неприменимы или бессмысленны), и модульные тесты должны запускаться в CI. +5. **Тесты в CI** + В проекте должны быть регрессионные (рекомендуются даже модульные) тесты, за редкими исключениями, где они неприменимы или бессмысленны, и тесты должны запускаться в CI. 6. **Линтер в CI** Должен быть настроен форматтер/линтер, следящий за качеством кода, и также запускаться в CI. Если линтер выдаёт ошибки, сборка должна не проходить. From 5ea1d33b8af440925f9027db60ad9573a3f6b213 Mon Sep 17 00:00:00 2001 From: iakov Date: Sat, 28 Feb 2026 21:08:45 +0300 Subject: [PATCH 5/5] repo-checklist-short: rephrase 10th point --- repo-checklist/repo-checklist-short.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repo-checklist/repo-checklist-short.md b/repo-checklist/repo-checklist-short.md index d6d4196..fc32a03 100644 --- a/repo-checklist/repo-checklist-short.md +++ b/repo-checklist/repo-checklist-short.md @@ -20,7 +20,7 @@ SPDX-License-Identifier: CC-BY-4.0 | 7 | Код имеет необходимые комментарии и документацию | ☐ | | 8 | В CI настроены автоматическая проверка качества кода и регрессионное тестирование | ☐ | | 9 | Общие замечания: названия и технологий написаны корректно | ☐ | -| 10 | Дополнительно: плашки, заметки о решениях и т.д. | ☐ | +| 10 | Опционально: плашки, заметки о решениях и т.д. | ☐ | ---