From 5db283c05aeafa2f1a99de3fd1f3cd284bc63927 Mon Sep 17 00:00:00 2001 From: TIAN <1846195334@qq.com> Date: Sat, 10 Oct 2026 10:51:59 +0800 Subject: [PATCH] Restore default template binding across browser sessions --- 各种归档/20261010_默认画面保存绑定/README.md | 22 ++++++ .../Windows文件访问失败.md | 19 +++++ .../20261010_默认画面保存绑定/浏览器验证.json | 16 ++++ .../演示案例保存_手机.png | Bin 0 -> 38939 bytes .../用户模板保存_桌面.png | Bin 0 -> 57404 bytes .../20261010_默认画面保存绑定/验收结果.json | 38 +++++++++ 整体开发需求/01_网页配置端需求.md | 1 + 核桃派软件源代码/FEATURE_UPDATED_AT | 2 +- 核桃派软件源代码/app/main.py | 7 +- 核桃派软件源代码/app/static/app.js | 3 +- .../app/static/board-startup-model.js | 58 ++++++++++++++ 核桃派软件源代码/app/static/scene-board.js | 72 +++++++++++++++++- 核桃派软件源代码/app/static/style.css | 3 +- .../app/static/template-edit-model.js | 4 +- .../app/static/views/templates.js | 4 + 核桃派软件源代码/tests/test_api.py | 10 +++ .../tests/test_template_management_ui.mjs | 68 +++++++++++++++++ 测试相关资料/如何测试/本机测试环境/README.md | 4 + .../如何测试/核桃派点阵屏控制服务测试流程.md | 9 +++ 移动端相关内容/开发要求/跨端兼容与变更记录.md | 2 + 20 files changed, 334 insertions(+), 8 deletions(-) create mode 100644 各种归档/20261010_默认画面保存绑定/README.md create mode 100644 各种归档/20261010_默认画面保存绑定/Windows文件访问失败.md create mode 100644 各种归档/20261010_默认画面保存绑定/浏览器验证.json create mode 100644 各种归档/20261010_默认画面保存绑定/演示案例保存_手机.png create mode 100644 各种归档/20261010_默认画面保存绑定/用户模板保存_桌面.png create mode 100644 各种归档/20261010_默认画面保存绑定/验收结果.json create mode 100644 核桃派软件源代码/app/static/board-startup-model.js diff --git a/各种归档/20261010_默认画面保存绑定/README.md b/各种归档/20261010_默认画面保存绑定/README.md new file mode 100644 index 0000000..aa783a2 --- /dev/null +++ b/各种归档/20261010_默认画面保存绑定/README.md @@ -0,0 +1,22 @@ +# 默认画面保存绑定修复 + +本轮只补齐设备网页的保存绑定与保存选项,正式版本保持 1.1.3,功能更新时间为 `2026-10-10T10:18+08:00`。用户静态模板可以覆盖;演示静态图和演示动图第一帧的“保存到当前模板”为黑色受限态,只能另存。新设备开机会话载入默认画面,同次开机刷新保留草稿、原修订与保存基线;用户动图仍使用原逐帧流程。 + +## 验证证据 + +- 原工作区完整本机 `all` 套件通过,包括 Python、Node、静态 JavaScript 语法和文案目录校验;新增模板保存模型行为测试 6 项通过。 +- 实际浏览器验证了另存、覆盖、取消、刷新绑定、默认引用不变、新开机会话、两个演示案例的黑色受限按钮、`409` 冲突、删除后的 `404`、读取失败、未来版本草稿、初始化期间编辑和多标签外部草稿绑定。用户动图实际保存帧返回 `200`,退出后恢复普通画布绑定。桌面和手机保存弹窗截图为隔离 mock 数据,见本目录 PNG。 +- 初次隔离副本缺少内核依赖及内核源码材料,依赖完整性测试失败;补齐这些离线材料后重新验证。不复制、检查或重建历史 IMG。 +- 初次隔离测试还出现一次 `app/persistence.py` 原子替换的 `PermissionError / WinError 5`,导致动图 API 错误响应;独立定向重测及下一轮完整测试均未复现该项。没有足够证据确定其系统根因,没有为此修改动画或生产写入保护。 +- 补齐材料后的隔离全量 Python 结果为 505 通过、10 跳过、1 失败;失败项为 OTA 故障注入测试的目录 rename,同样返回 `WinError 5`,定向重测 1 项通过。隔离前端 84 项全部通过,全部静态 JavaScript 语法及文案目录校验通过。隔离环境从文档入口重新创建 venv 和安装依赖,没有复用原工作区环境;本轮 Windows 间歇性文件访问失败的根因仍未确认,不把这一轮全量运行写成零失败。 +- 板端通过现有 `update_walnutpi.sh` 原子更新:全部依赖离线安装,原生 bitplane 与 fake safeoff 测试通过,Python 509 项通过、7 项按平台/应用载荷边界跳过;生产切换和服务 restart 健康检查通过,真实驱动为 `walnutpi-h618-hub75`。9 个安装后的实现/版本文件与本机源码摘要一致。 +- 生产网页临时模板覆盖返回 `200`,保留 ID、名称和创建时间,刷新后恢复保存绑定;用户默认引用不变,临时模板删除返回 `200`。当前设备默认为用户动图,沿用现有逐帧流程;两个演示案例的黑色受限状态在隔离 mock 中验证,没有为此切换设备默认或实际画面。 +- 部署前后全部 430 个持久文件数量和 SHA-256 一致,用户配置、模板、动图、字体等内容未被修改。汇总证据见 `验收结果.json`,未保存实际凭据或设备标识。 +- 远端 `/var/tmp/qms-default-save-20261010` 已清理,更新脚本的 staging、候选数据、回滚数据和测试运行目录均不存在;当前正式运行程序及其 venv 保留。本轮本机 mock 服务、SSH 验收隧道和专用浏览器已停止。本机临时目录的递归删除被工具安全策略拒绝(`blocked by policy`),未换手段绕过。 +- 可手动删除 `测试相关资料/如何测试/本机测试环境/.local/work/default-save-20261010/`:仅含本轮测试副本及其重建 venv、mock 数据、专用浏览器状态、上传包、中间日志和摘要;交付证据已保存到本归档。该目录不包含生产数据或长期复用的 SSH/本机测试环境,不要连带删除上级 `.local/`。 + +## 可重复经验 + +稳定验收条目和保存交互经验已加入 `测试相关资料/如何测试/核桃派点阵屏控制服务测试流程.md` 的默认画面保存绑定小节;隔离依赖边界及 Windows 文件替换诊断记录在本机测试环境 README。跨端兼容登记说明 REST、BLE、scene v2、配置和驱动契约不变,无需 App 更新。 + +本次实屏视觉验收不适用,没有摄像头、接线、调压或测试图案操作。真实断电开机的行为通过 mock 开机会话验证;板端采用服务重启验收,不将其写成物理断电验证。 diff --git a/各种归档/20261010_默认画面保存绑定/Windows文件访问失败.md b/各种归档/20261010_默认画面保存绑定/Windows文件访问失败.md new file mode 100644 index 0000000..acf864d --- /dev/null +++ b/各种归档/20261010_默认画面保存绑定/Windows文件访问失败.md @@ -0,0 +1,19 @@ +# Windows 隔离测试失败证据摘要 + +以下调用和错误类型来自本轮实际测试日志;省略本机绝对路径及无关依赖安装日志,完整结果计数见验收结果 JSON。 + +## 首轮 + +测试:`tests/test_animations.py::test_default_animation_delete_and_last_frame_delete_fall_back`。 + +第二个用户动图添加帧时,`app/animations/store.py::_write_at` 调用 `app/persistence.py::atomic_write_many_bytes`,`os.replace(temporaries[target], target)` 返回 `PermissionError: [WinError 5]`。API 返回错误响应后,测试访问 `second["id"]` 产生 `KeyError: 'id'`。独立定向运行和下一轮全量运行未复现该项;没有确认其系统根因。 + +同轮另有内核依赖完整性测试失败,原因是隔离副本没有复制该测试要求的内核载荷和源码归档;补齐项目内登记的原材料后该项通过。 + +## 补齐材料后的全量运行 + +测试:`tests/test_ota_checkpoints.py::test_power_loss_between_data_renames_recovers_original`。 + +测试中的 `c.DATA.rename(backup)` 经 `pathlib.Path.rename` 调用 `os.rename`,返回 `PermissionError: [WinError 5]`,尚未进入恢复断言。该轮为 505 通过、10 跳过、1 失败;使用独立测试目录定向重测该项,结果 `1 passed in 0.06s`。没有修改 OTA、动画、文件写入保护或测试断言来掩盖失败。 + +上述现象仍保留为本机间歇性文件访问边界,不能仅凭重测通过推断具体原因。板端 Linux 原子部署验证为 509 通过、7 跳过,生产保存接口和数据保留验证通过。 diff --git a/各种归档/20261010_默认画面保存绑定/浏览器验证.json b/各种归档/20261010_默认画面保存绑定/浏览器验证.json new file mode 100644 index 0000000..b230335 --- /dev/null +++ b/各种归档/20261010_默认画面保存绑定/浏览器验证.json @@ -0,0 +1,16 @@ +{ + "staticOverwrite": true, + "refreshBinding": true, + "defaultReferencePreserved": true, + "demoStaticBlack": true, + "demoAnimationBlack": true, + "conflict409": true, + "deleted404": true, + "readFailurePreservesDraft": true, + "futureDraftUntouched": true, + "initializationEditRace": true, + "newBootReload": true, + "mobileNoOverflow": true, + "externalDraftBinding": true, + "animationFrameSaveAndRestore": true +} \ No newline at end of file diff --git a/各种归档/20261010_默认画面保存绑定/演示案例保存_手机.png b/各种归档/20261010_默认画面保存绑定/演示案例保存_手机.png new file mode 100644 index 0000000000000000000000000000000000000000..b1aa379405e32332dd2e2c4a451560e789754332 GIT binary patch literal 38939 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 literal 0 HcmV?d00001 diff --git a/各种归档/20261010_默认画面保存绑定/用户模板保存_桌面.png b/各种归档/20261010_默认画面保存绑定/用户模板保存_桌面.png new file mode 100644 index 0000000000000000000000000000000000000000..7953500aea798247bc6a8fe03a63876dcd187d9f GIT binary patch literal 57404 zcmeFYWmr^E`!_nYq>8kFO2^RMs7MVB14DN>bhm^e(o%ykl+w-64T22a3>^XzLrN;B z_->!)`k(j1`FyT(UFW>}%j`X??zPrk>$mPZMn_A9oP>b{1Okz(sVeD#Km@=m-kUqP zz>lXtsR0Od52U8_)F2@HaFxi4^=0Vazbc)uV_*Ny&gSKVsP+QJH*3!x6X1UQGbBK8 zM?rP(jfWxwt;sVfX?)6OC)+B-e{NRSuDUFO{Z}h0Ep9EbD8~Uf!fp{!^@Frtf?+IP zxlT4KscYgqe$~OhlzQk>cs4j{oslMveO|-etoLa=U+x#$dN_j^_!SyeF27>|cpk|G}mF2C=rF z+i=6EkU(uL-hU~1D|?g@W7`cDQ`?aQ(ziD)4^p5CKhoZo#T_ta`o^$9&=Q+tTK$JeA zbd=IZc5B;@{F=u&6t381@AXp->But2_CG)UpunKNZBqSbLZ_@m|83~6t18QGdE4UA z3WkLDzd{6U6xRv^WvG|?l-cLRE-d>nt#?4#Uiy)5gDFxRuN%=fe+48-HXo4Kt7 z$T5t8fTi5vkh3ghj3!Zv+KrI)rTR`+&L~Pzcs+FSuiB2O#DGIwr!9N3?fX7A?**oW z%kdi}Cl}%SaTyIbC731XZlke*Ak7bz0@jZ@vM8UL_%XO=k-l^L%*>|Nl{OJe%(Q$w z!vC)b_%{~J6E}9OQ&cZwW{C6{%pi?B6>}9%jvuf+4KUDBx0yQY?pI?4&C>z9ro&i) zaq|yk{rK|wi*6~t6t73yfz3vENRG}o9>1F9jf%MFXDG!Fc-(MYoPgxTPUh(O2f5j? zTG6p)MN`{{9_<5t$uX({t=ia>1b(B`87Vpv%{Ou6PcaRD>4yWQ?H4+oRZdAWEO44& zvcBYJ87$U{UHJ+9GzXc3v_pRFA}_rq&2sa@yl}#@sUmPdnctqH;r@groK!q2UFz>M zX1A*$=x^ieYlTgjyrpE*@-_Iy0nwvlGzG#Lk8kMG5B zmOmDQv2hXFq9~G7{Omj4O~UMd<$e5CQjf3x5Faw!-}RPeb=48I9Ah5%uJBB(Db1)% zT)Y?rYGJ{gNik*_!tl>}heu>i0zY6Jyl3af3N1mUjAc_%oW*Q-rbkV^5b3HpzvlKZ z4mm^8Mf$}eza&$?n(rx?*1zQWaaq<_i2ovxXK!To?E+S-K3pw!^oKU{Y2QbOs0DT&-!1obNL*0 zeHYNxoEX}6B&7OY(hIpRWhjTqQ#_DfrQt(cGJ%NMJB-(+?Z!D2(*oiBG^9~3;~nc? z0uP&FRG}pUWlpoH3POf|ZymXQ`ye!QaTbm}*k}H{!qln%Aktc5(jovUwz8$O@A`SiPWOfD_M%&4{dGCx-Fe6z_Ryzehowh6^x+7idjjsQ9Z}56}JP&bY0>e z9iy(j920UxYE|LzpLw>yXFd5Dh~SNXyr*<#<$6^gO=sIb6o;lybgVmaBBzYbm>9i z8uMnMjWgRFKh}QPwH37nPUNl%dtU6JrcgrXHWI5o1$}N3J0m81d}A5>=JI~OTTr9N z=Ith?rWe9>9W~YCEzUkZhZ`!)LT+x09f4bD@+l|LUlGGI7)+!0z?F_3o`Kx%-eWxUZPhizKmdxZrWsdad%Sc%+xn?&YshF;nyA(SXO^YT~x9 z(aP~i`)?ac;9RDs2|nd@XRRxkSC?*~jmTmqHE;{+OVa4pAQlhseWB0RxV%i zEmKijj@#SmKlvm|_{|WZ?~yz?zxfcEvS3e>XN@jqUH0!)glHo!E1vu{IrLNOz9Eg{ zo%q!HF>qN~Sg>~CP7eq)`Xr*Zdi=nvm91TU+8GY_l4Ojq613#-vWOF?GgPYQnT{NPE4|n`_^n~>Z}x@rC%mTF zSdlFLhu_#;+u`%G*Ye0^Xme8^#^B`0CH;h`6{>h+a|;1!>F;Oq=clXzIopU8O?;h_B${BHfWg5tS#+%F)=XH zt98d+v_07P-uK))%OHTsZ!uCsR#KAc9eQ?iGRbCbLcaU&mj$IO+=7qqQPJqp0O6Oi z_y5eAthk-0ns1iqa}(eR9_8VH8dbdV?Pkr}{lrDZWsgzKkTPWl_3f(|f7z!3U-NPi zqP$T39O7ozRj-X_Cp%+EpDL(c(YNQUjJG!u-RaVBF1m~B5OJg?BKZiiBdYL;AG1#+ zyjjgp3$Z%Ja(`qg92qp6!6r_)NnDu?oD9o9HHgXfgt#>wFT1VGzR+FOS?u_rJB7Kl zDAQBVho+0WeFgUZz50ebGj;TDWqgrs0WfUqt&~q*4o5@i2 zDz;27hm>d?Y;)sB$HDVI+SUd-vSmW{m=w~tWbSb5@ER25j3unfuXn^9!L^t$A~qWx zET;jY$vP0#+&BdWk*oT}?dj8nT_5##V}sQx*UPeQOyS!W#>L;!8MoLp&M=VH&IcYe z^w*X6n5(jI&FSfo%H2o0Admr3%)9PCt8(R5yf!&5zNFUa@&Z4CWK$H_p&XRN$Rl<9 zbYEW)+nB7>*Uxz_KTGh_*A*2RpE<7g$2qsP>D@gYvBZj_mG6yJ|JgS%dmNH0=dT5* zors*8!v{)YgYQh~g-xy*5+W``3O*r4GE6EB3o;vQU#o08jxV3S<1roQm~_}UDPqK=TC=6!C5Ys#jvk_MNm379db-wBW7*Yu^f|& zKh(c627UX$vvYs@0O5nTgL`;vAjCtHHMDq^Pw8y`0xHd|8N8Hr=>xte>^IF-4tac+ zB9TG+2^4m<^M^$dj*U?@=vLpc3I6hEu(bnF@tHlc;!>DkwY_x(g*;7HRaE4G|U{XT3uU_tq!B8hb5!;4nJnlh!D`_VRZXd)QjMPZ(@?MW;sQ~fdGeYBjL;WNewTI` zs!2ckONxPn-r7RF%WK|Bkgd$Z#-m`QsJ^<(sLn0yacvb!w~OEodW$msPx6JOZ?*re zo_tQ!$b;|^*S}<-p7Q%iobl4G$`P~gvQpRv1_lzWD@a7GazA`{&v)_Tu4>O*#j;Bi z>eSPme9jd)R`D?Q#MPM}jQmB7#5>xQdkU73Bk>t;7mjpOqyD;yRHUs2(LSg3+QOb6 z#=o81(alc?at{a@Ueq~pb9>)!r|`i001X(3Z!sfE9!{cyk~X)IkGJ-}NaqaeyDp)O zpEU-u>h+2#qnn1eOsb|7oesZU&pIuiW+E^_;5`;BsXoCpyZv?1;7qpU^25vzdZp@m zIDRD*g&Vjdc4Rd67B4vBr|Rp9q{q-1)iaf89@_B}qFx9acm12?Y4b77HoSUuqYf1f z%O?p@taY(qn%Dtf1BA54$0LEG8SaM#ig=*+NCTC;?>`4JiPDy``QM{$P!Bk@>CNrf z^VL(*gln{tu9qlB#;y{t5)=K1I{}@;W~v^3c+yR2bm3s%yO-wN0Oe2je8HZ6+y`JUt60_ufeOT3aMFcfLrv%66yzqXC?CxcAiq5;e5c$}<#Yc6ndh_0r)=JGxsF zx1CMD;QSL5z(?FC%(>3~&XwQjyqd4g4E)(tudVB{@%2KtcHW8u$Bu*o-=y*6_mq9vIZK zFDS_42*KsDoM-X^D|vtN>mc1VW7|WStU|?-P@bx)_Zgjh;bQly?*t1 zdFs=^q&mj~!{yi$NbA1ZyYxX$`k(t(yg8(aNeQ&D?cOv?%7V(XFP8@w+1XVE8Mkdu zInf*)e(i?~h_^wR;%yQK5jAW-ESA@bgMSlhCS>ZbzMko`BqzirC~vRW6IO*_ZZn_O zfXaXaJKRE0&dy%fQ1-{&zo3zU zGED|U^OTp-Y!?g}q)oxAZPOL6-MB) z9ZE6qHYjgO!$d>5K#vGvWu|v`m&XycSbrnr=nJZLcS}+(-<;=Q)S93DS!;5S@Usa9 z92NE%Va6mheGV?xG|QA(&qBjHs=}#zw_Wf2oc}+m!^O`r%PWACW+`nSmulYR<7CB*7 zL>*md4=dpx=H{+?a{7wo|KJ;E{9L=PUv+;|N1NRe$7q5F_8(h*(J&ufmG(FC-dZd_ z3GFOG-Ts6fPgGK)fP<)PPSk$^k(yDEtawLlt*8BVF(8t|>5iOvr(WpC>v5cvF>$m4 zni^?W4^!Odwy8=EF|>nx>x1HAM6V-aV$`7ZfQwI(B>^hXyVIjcf&aDW1*n<_b1&RE z^j;<4go@2dDA`QaJC2*ROgc9&i@UF_EKT!RJNVf71T9(a6LwnEd~ZX zV|~=;G&v||X38R#*zS&Km=8O@bZy;Alo=g?u)X^FndtIjO)hxOw}!XYbExOnkCW8A z!*>2Fb4I3z%bmd)ohua%zy9229RN631^p)D@X~EmKgvc?31_vhxXHDCF`S>`6TK8$dr;?K03v6awt?NSV ztAn|!l+=Q$($*KA>-}BX1(rc_xd}+|eU3@F-C*3$R#(CiJq=371u98=g~S)=gog(Q z2j_fWwRmfzhD?sx0Q;)P^DFo^gqJcNC*Q1bnW&|DyaLZomf8I~rlhcKRw$X5uREP+wMJZ zp0CE>x$LCM6(aDhfZZsc`6TWp;+`!?1}ggSFx(l7YsbgOhwi5nxO=gD=$9wp`zI!( zQQ!6z7ggON&-eb%Vn&v$*%X}_0_II7RVfjq;L7OPrMkfS$`n<$;Gpq5IsfC$A_yAS z+&stC)m2Xqv2@nzz3XC#?0RL+#+cZ@x%e=RrvW!SD@}ugkH%RzQwOGjrIq?yTTgt= z2LmKbkMGX|Vdi8uGP`<{)YA@?Uoe)J^(LD!`*Qb&j{DC}EG|#N-u7xc4$Zm|z&1Y# z5kf^NbLbvrfWUcQYzu5Zdh9=&uy8lm*Dpx37(k=hpu^d72t%Wr8?07zK}ChLj|;e+ z+DAw;-+uM2vnaE(}ID=4G{OlK`iV7%g$Gk@6cdBQ(*@E z3UpoGESBjpAs&ZeyIk&H$p?u8IfkZ!x}8KUB^Vx=%#*c!05OZo8&4^l05q}|IOGsX?5C@c4Fywi{n7i%-%0nJOy)>w9TeWx40&Qh%Kk@~TK z+LAh9pl5DfS?_jVw-{=><^GFzSKdi!F@&wzzvg7FAW&0V`^VKK4@mKq+BL%zyecy3 zD^#niLX+xF59$NP4N{p1GJ|4hZ3L}se5s_z-)wqjj4@PhZoMCIAl?4kQho~nhCi|3 z%yjy2+7Ot#ySu++&f@uYnp0?&kV?A&sN1lHr6YNJ#;3FWE6;kZq~30a&~2Jvi%?C#w>>2wATlk%D)*CVE!9KFKE#lqZsd0AO) zK3F|V0Or&xIcT4+Ik4D04JZ^3{{8cGYKm90cz%2Tf;SMlKiZakQ1L^}k5BeP{dI4D z-2`(Dr)|U`|5*BdA6cadwJe#ijwUpApnxL7DDlndPab%fslAJMbU!>!<$PyZN%9k= zMf>~%Qhbbh1Iu{EyU(Sr6nUJPs$b5-rgoB)O;@WqGMvE%36^NFcC#2eJwM@f+<#c( zPAGs8DieK9eX1rL_Mz^egUz!;#6QA!t=fL@er?p7(@Bpf$UJgt&MXo`=>>?Y;(Y?RNme zl9n+Vjf#taH!lz=5|)>7OsP&{tM6)QbAc%`mLF1RQNtAFBm1`WkLS<~ z*Lo>^6!7F1T6=QGJ(Erm`%Wxn{F+4KbMx9N1<5=Q>3Uz*i%aIn>FdX&|AVswfytDr zTh(QuX(|TC@o{lt3iL>;Dj>cW=FM(L<4ns;TDuw_G|H_6_W-mh(QUm;jxxq&siCa1 z^Etf3YkoXO=26J^C&q9)J4q@s2Al<~&)yVxEJlopneubPOT?0_!fGyOk|IT6p zK{E`(bldmw`_G>(FN}Ra2sW4aPqJcSVuFH?G3H4!nCzA{qp+<6iScjf!mR8p+4Y$M z397jM;2?h0WAbR$Gxy-&;OEZ^`jUgxwoc!ypLF|RKe_0zG~j{dqcK%^8|D zJs0tIt?rmjW%dM3qV178js*hDcZzQCjIQ(g)ZMvMxak@{A74s#9DjeKz`#}Bj&c+JYYfdaqwdWIk) zh;sT#947Me?#11tc$f7i&Gqc;Y~W^2?~;j`*|@tacmz>pSYdDDrT62oaXc}dl8m6} z3!H5Mfj|_a(ZxF)HS^B(Mf`1m+u50H9awdEWq@={8h8+gJ_NkwR;4-T>eic;R&Poq zCQ>tAdv<;vu>EVKoycYv4iH{ZS?&X4EwzlKHw~&D!y9J{n`IobF-m5yTI4;-zO}!s zfXahiX`JCat7olm6l!6QsqU&28E$#WY$e0=y37;N2Gogrb<%Ayo;{!8_Vr7L6cv3A z-qNY30ahNOy6PxTS;ovn<@tbv5P20r8q$HSj{zavH8sxlCM)8|5r^}IqqCOXl4A8X zi{m=LoDs<9^gEFBTqniE1b|-(%+mV~vCW9-HCoNgL`WeuiHwLFR##WC@k|F;Z0b)q zq(nXNSA0UkaHm^y@KKhSG-w_Z_~USqZ)(0HXI9XFIVtcSmW;B#=<&+rq{ra`Dx0+O zz=BgDsI91Rdr14XGX%-N^zdA4HcuvaZlg5TlDyW&V8a+(^&mrEZ#aE!_MN6-^y*90 z5*_TL!O(055%z?F^3sl)<=+v3NV#1qO*Vm_f3%QLVdT7p6VQ*X_y~R_5oMt@{Wq za|Fs#5Iz}eijNm`9sy`H6BE<(zUO*eh&y}`1{}%c;%Qp?l%u`R73cv@+=$FI`;R)3 zVs<{k?JnaR9#ma#J%k9S4T5~C18M!*&Bqcn4f%iJ7@QA*(lfVNKWp|=(-K-(#K6p6 zeZ$kQdJN4KkSwgcqqfy8wWdAPdVk)B*S67aF1EbqVFP;FlbEeaEk5^-k-Qr?A-(G_ zq>rl4i;=zNw>|#vtuAyE%ttDEp=punHpaT~&hJ~S;^W63FKpIdaGxJ9pq>{$|M;G5 zp}Jbj_%TDAmWGykh;OSoQrwN<(W9jPO~;8`CPv2Cfi1vub9Hk|LDKTy^^pGlKUhHF z+t#+*wu8a|-UlBc79hDmBi(bQJ8fKANo6Ro5)U9=U z_(f1E&pooi!yFlZSX#fCTjR3ph7JsomH>eopLsyMM|L!kNzCnfC%z?RFIfAJ+N3Sn zC=*}U{=xf0O&>`Lvu<(X3@6!qj|<{8d?}~9HT5pc1}5wQ|L{JuvIV9liP@UBnfmif zpD&O0{5zl6v;l3LPhzLXM&zu^Lk5Nmf`m7tj7&_)G4+lUL7f)e>tR2?Cp%YnwRLuy zJKU7~>Ffl2Y|F0GV&s14C0hJJj1n6IJtJevqr4ie;gPzI@zDpV4_H|X9?rSHOP9>g zz+`QCsQ{1&0C&vHdjPyMVgb1_EMp}pHBOg>=J=aZOKW-dk{Iw&aD!@7wn=&r@pyIe zcH=KeUA@~5#iI=zj>?2Yc*8W(KRL@Xr|NlwY0_sy?FDGyUk@f7CzuM}4oci=WDIaLW0LMF=80m3o=OkQcIH={*j~F5ETN zK(+|`cZnrn0=%ImXLrqq;{PH>Q*6su_&}u;jCwkr@wnvRg=2G>SWC&U2YbD~UtcuS zVQCc;j0em1dz1XoG~jJRi_!%UH0mGAg%JD#nbsv;BKjwK5V*}CtK{w99HF0)*)InM z?~|8`0X_1%&}@54hESBuI5e8h^bvf#`jX0nP*vLW3=`#1I4yT^5?p@_YZa+A$)?k| zAkdLwe^f-XA?thGG$Q3#WP@iwOu?{n5Q*{=3pc#T@{0ZZRkQ_`Q;&@FvR6Xylf zUk?vBx-v{!eiW1N_Bl$)xAS2v9l?^M4##euDa}ZS2+y16^5G#g=LVSHk7@epxpeR( z3-b+sGG6i5ILb0&&$W4HWv@3`DKkhsSneg1>9l;_UNJa1xQqX1YPveKzEr)HOz(JS zV#n4^NF@le=#Q(2QkOX~OVNjJeN>mT-u^}d^JCNtH(Odc=E$g5xc9!NARL^!p~^*b za27PsyD_EHqE7O8Zkncf^mf$SKO!%Z7pF(hv{xTGgU5gL92X}1Z38ThkXlaU<*)D=3pXS|n*Q|25GdHfl*+Az-Tsk5=0XG?D3v(&yYxE#U(sPpc{kt9- zDg|bHci599Mt#8lsa*bv>563}=M@rZYGSfHo-O}!<#5l;`)YK^Ni+*p*tfCJU~g*a zt}S>^(815oPfS!SPude~i@X-Ev!2;OAeyp+DdYNqcGfPkwj-v^M|4c|%nu)qEoA); z-uT@b(oSS0e~y9kT((-YnA_-C4y6iU!_yO=lfYG9&q&=*{=>33RPC0|=)*EWr7{GE( zEdbWTQXNhiwRH+avhX!SABB5|fex4I*N?P1Zz#b$ zSjwToA`%LV3K`IDXlT+SIXfx{yWf6`^Gd}-I*6+wNtFtP9Lvm(IQqsyBy;QXMk`m6 zXJd|09V%^wL`u*irt(ev6ziH--D=#OX1&?oTXrq%R-F%xtH!`c`W>~H=G!GiB_|sl zR-;IFN$_1jybnt{dMLNZ9u2aK#orHO;>rne)g!RAn!=Z6l3|A*ulj$T?q9n>qu;*e zU@~U6R+sZTxvjXgX~P9W=d7%xE2~8#5dA(=Fo8@}wxHl~dUHQ^2ls_qV z$YOD>AZ1M#JxP?EcH6wW#+R)rm_c(sf?S;$aWsghsi{TxuyXlOzux!jCaXm464hm( zSuM&2mA6MfLhUIjaL@8(-JMD+-mCY$xQIzOMD-%~s zN9|KIE9WiaQd`-gvh7|g(;-mk*i~Zyh26;%vSkYd)z>!*><;? z*$`YV>S(I`wuMSWfXzn&x9G9`T9bkpB~jn9Z-xCfAIAbNVO2N*xf5ioL;*od0^63{ z8`Z|m7PJ9kY9CYeQ+do+)7vjbfl~u}W%YW?B7DqKvn(EsS!6q4RtOqw;oi2i)h@&Z zvpZGvGeAa%Mk)OhE}Z!pMyefV^KjBQT6@@cDoS+Rao{A;R92n=OjifeOF4!Ir>N7o z+m}!&E#&3R1wuPf+bl~fy{m1%BiJPC!O*vl06?gN%8*~1)>%I~AL>#gT+=ye7nKXO zad}pRzFXfIyn<*AYYnQea?1!T#^3p9#g+B0IaoHO$X=Q;spcGW1a}(_n5&!c^^2}t z+w`=&__fUsuuLPBua7E6>c@aF-#v?TV4c^Sr-)#g>Miv4P)*8{?YPi3+!dYmuV(>X zZXQbt>2g8dq1JXGp6=pTiEBz@HJ?)LM!^&RS4_vh&jR z_AVHC30AnD2msLarr=;x6Ei=gkV2-`&Xo@mp3Z;W)V3;=sWmR^oOz{EPV=6`|zqVybFanhHMWN;~4_9N)DY zpM`3FNpnNzzZVS#;oc6n!M}*0ZI8|xk6cqG5^kDIM(4J82lwyvus_+!P-(yO2e)|GmmqC?NVQY$z1H5r|Yg@byl_t&%88ty)9raLq2v9(o2}exKT~ z(qTpw6>0jxR4g;g28O5S;h%8Hs9Zl=#?cH;K)l- zD;rc(mBu`MM*Q`A7#l^)%B}7ZsTHt}sU~ZYfgHD$4bwBPoKH zO7$b$p7S9Y-!^8&-1*dpJAzHK`c8jNO$o6Ix4SgOZ#POu_c`6knG*76S^a4Y?;0DX z*8K7x-=~mIdtHO7X&TQXQ^oI`+JBcx*7(y)^cj7{hv=a3A6$zPyQ`>;kDs%XoJ1oG zv1YDa#8#f^f>xT?lH7(!LclYjJ?s4cppGb0>iyi_4V-mmMWK#3?g-Ht2VA4 zQudF&Z4~bFzBJ}prtH8IN-A7DPt^|+s_C2B%f|9$!|&wmQ_6}wMzqp;vL)A=mfY!y zs%im^PCWu{f=Z?IoD+&35}G;`R8EP_?^Pl-Ny>vwO-JzrAZ%+h(=ID%lK~!1cKXjd zJ+b*is^wbC`+g9MbR_2hC%QNDD33j-7~N7gMh0cyHjb&$Pkv`-l(d?w%GQT!sW!M9 z^^CGg?kb3QG^HY^^-BLNF!ewkeN`yIA~Po=Hlx|>KO82Xxw1M9t~lTysM`*$;ycSS z%gROUu5DkcqmMJQmoT%lvJ%z)ze3JZPv4<`THiWdeEhiK#Am;gP93h+4MOA=^8Xcg!QJoJn4!R5AWo>>w7IN#?wC|56t2XZ z-cX3w#81UJo$)j!wnAwWxG4%ve{8Hc2lsEccczqij&lSOHAMs<`-2dM3acv%Z$;eEv zsURc9NY;Af*J>mj7$&%|QU^6Lbn`mdm>uR#FuYw4E&9` z|L*rXr;d~@Gf7D1WRfly{e~xNaQV*HKM*00@zt7pZ6f8;blld)T44M6g5VYVzzypZ z%|tq4V%+Cv8bi%>kZP8J<|Af?xzM-vzM;M>-lRuW3FK|LVB%{<(+Z6d8%oa_I0W}(Z!4y7Nq5-}C$A6H-YVrN zWSpB!ajh4IphU5XS@?WinH}Y|8WmNpp0n;MPL#yA0*TpwzTebCC}~QdlhQAj>!I2U zw`FECPOWn^y21UlDBEN(s#aW+j0~+&QYtH$lVMCzWgk|bx=c~Hr~buMV|yk>m2K

bjEJ_V;*}8;KV_y+QCR1bvbDWRJQt6Afz_ve9)mczB;Yr4jIrbn|Zr=s+=(* zWg5v$9xb3rRQzemgD0$9iXSH7eVc}xf%8JITGO)p)+UJmm-|2PT2F~$|E zTe*oZir!|c`dj%e*Vsu1^0&P`{BV>8hGfMp+^DHJNsLui^%3CEDJBg0qm8*3COQRn zQxJh}v_-R@_+MD%N2>qvsvH%V;R%vOrAa=54HfcBr*|>DhZ-~JH(JIO4ya1Y!6_Mj zG>HBnirnSoM9!GQ?bDsAL162%y}dn*YuU)RVV-DZtkOk2F{H z4~&>ZQ4?^0QB8+F+hOfvHEM2lb%(qB2w*VNDl53UDJlB0ui5CA_`5pnai)Ro#`iVE zjw09(Zu4yVXBp~rm2a$W_v%8@^ro&)562Lz)w-jSVHfNW!jkP~#-uGalsL4dUTx@G zb{O=xN2j?)Yr0N1Y<%v}Yq((04|l31k{E{$6r21v8&9m0*bV|dkud80JSTMc$(pP(8XC@r0Nlw{B3NqaB6RoYdk~x7zUV=c5}=85tBRJG z-OFnfgv9SppftPy6OmSFt#~mN>B6o^Z_{; zsm3bQ$NnSr@=;vh=ZEHS{R!3%Vh%1JCyq&oz22zQ+ch!xT0|rq#0bEoK#+8(A z?Cr%VM=rsKxkKFCe;Kyj%8rI-46rn_J2fCO`4aQHA?yz`W0k2ifE$0ELbKhI7@9WKzFvlseIY6xE zQf}kY?PM4zApD)>jYXfaX`yr^gzPPDFJ0*JnAA1=G`eB$zO^a-qPQu%(0xjNzC!OIJvJuWT5(;lgF|r zlp{e+CZ$~DJ%v1k?Izz(-*o%TmS6OY2$jq%?)j`uPPujQX1cYx)SE2H9)}yKJUAsk z9_0nuo5>h$-`J{i=uhdsVpDd5e^;ApENcI0u{_1GtROADkCL%tO>qw{`F-Xto0&Ek zdcHD3#i>8fMWWh<_ydS4o5Dc{F9!QiTBeR!U+voD)kOodlF3Mm+YAtcaw@$SQ7J55 zSJA4LRJ)y|JfW$@J^BJf7@lI+U^v?4yg{?ln88N&%>cDxT1IY6b8UrNsipT+PFA?7 zvkWzb)hQ4HX|@W2CNweA#zJ<&1tk)T8!;!n0lQY}>A$y!6~ zYyx|O>9mZy*?YBp^hTxf_>|JK-YWL_+`EL4WBes-S16sm$w8+sny-zcHuW;Iv7dKw zVy!Yu{uZ$tC27V9cXxw}ThFUrR-%{d)v0{5wP{RTPzv1Oey|Sq$Ac5?*}CDsx}3Y~ zJHpIrv9fPHV5OA*fzw5YS~tf2FF3uu_G`}hGG^t&lvRN5`v-FVZHpeTUgzosFloTy zm7=K0)q0W`CS{QaNl{eYY3I3Ad86LT6PnB!(>P`DYrk;Wt@+z}0t=hH!c2yLd0Y26 zU&7_U0Ea=*(OP4{&nUoQ?x8fP*8XHieTY|^hUna}E{hBW>5vd3quNJ?aj_7h^uJPB zstLQ5k60S-Z>79odEert`)Tr7@R7-MQtxi48=&z&RPbn-(w^h0h`vYjG*N|hK;JuG zZxMuh8B>F1vjZ811?GnAlac0i^#^R!Je4d%MSqsL(RGY!GzE7F1dUkAz#Stx(t*og zQb)peo&s!OhWJ|$S|n7EQ~C673W+{g;B z;tGZ{IFwBa$DxvoCV(utcxwBy_3EM$OV^>qCw3;_bSv<_ui*Q8>N}|A5?kHI6<|0x zqW`DkEx|}Np+I4LhZ+3`x_F)pGbyZ*=~tY>Hy4mQXuaCF$-ts70gxr#8c zgYXpl)4wO1ZI<|}aTZX&d>YD*$C=UgLR2RQ(KhDo^$|N?yGQi?lhNa5D{GchB`z9g zuU0CZ296SudkHVFfS)ijrZ?W2Z{L+il9d{gAxNAWp&NzRbCvpWw`w!Yn_3}U@Js}; zqA0lV)u-+70$*8o#ShtGP52rIN&paDOR2?_dY$s!h7ea+uzYy4>q%;>xBKN^>h~ci z#=<+Y_wM)w$%>mivz0&NNN$b|d8tRfZ3&2Ct#ta8rweyIMF%)#k#m2DeYmfuJmoUF zp7L*s1H8M4v0Ih5^nHw~oh+lVkxb;7A?rc|l+_ zU!WtO)30p)0tSN}cM++R`1Cj3n&9RQ9WJUQ-$1zs8+&$zCY$8tDg`rBdtO&WxVKIk zP;y|4pyl60D~O_U`S7ch=-XX&(}!y8tibIg#p{?U)lY{)dDo`OMQXLg+Sf9jYaB+a zKB6>0A|8OLB&$w8F5@uf8+L0PP8x8i@Rodb8ZeR8t!^U!5Lgr|#P}F5iYi-EfgtWw zL-PEEtGdH)|9)PXKe%zvH#PIZmYkadkNoobHfl|_qpLqRs(q>s!J|}TdxrX1gvBa? ztIO{KhEaIb!KyLK=6g1GzIf%_Ud7Mn%G4>Psai7D1O^f}m3XkuVTBhBc0kWa5gS9} z3cQh`(dN9DW)&Fg4Q$3N8OR_U=W)^^Wv%CMi*)(t^nE%qgGS8!s>A>}NRhr2ga^aW z1hqM3>XTa#aOT<1M{wiX8mFD3P5H3%DY}>D3pno%$v`iGUaTyNDLz-^Kh|KPt5_V? z?grcwJP=JJh|H?7V&VO`_dvgiSb-f*DP_gPAG3tN~JoYibu=I72C$W%T`!|+n!U!0Bm?kgRpOj!6D=EP{G$8OB`!#w@g7^wd%y1T& zc|i&qc>^NLCj_6yux|wDRE!WS#{wEGmYYWxp(@4_| z*38HG7sDnN0T2&7rNn^h0Ukw7faZTMKo%w4zh9jPz!n2fc$OmQKe@EC`2UkBb}#(@ zV_kf%27yKn-ujlSuY~DBWA+0z-zWSa23hq3u)x1H_&fUN%8mjA=UpnQ)1r-iXJw=n&GumE7q|F?QL1oDO9-hI+Qyr<5~|0>wtyB)4Pi*BH?8gkRbs) zh8<`$I{O^B5{rNNUkzo|U%%`I8sS^h8pDy7p;^6IE^ZRYgGO|7$+a}KVJ<0zS!8TL5(qhy|rh(!R>jr zSHL9%00w|zf|b4N0_kvn0dSFj=6L%FP;3Llzrrp7BV|bWNdU-WwgEhy_ zr&*uUDhi!3@fs>M6;hE|`2xe2DnpsM)jB{tTwCw;#-60=2?E!m!2H_`9Gloqfs1Hp zZZwc<37h&ipel4*+)ADXs(tvcizpVL3mPb;{guqp;o z_DMNp66CX$=^r-B*#Nf`r}7{CGvZEvZt5y83aTf$72*$NFuP*Y0GiYR(hjb-ABuon z-C0xl5!*DKY(UL9f{ z*!Dk4{6cCKL30wT0(ta$2$(rw*u%F`X;@Tb(u+NU+5nzc{RQlapY5zbm?U69=_@Pw zTi#fJAT^QJ0o=BN^mK~p|F#znN#&%yi0}rp%0T>4YC)V4>eH6({ ziT7b%*uvW>LZ((!2%s?^{*M!Q>`MmH^)d)`$YZZfEoSjsde}4+33UFY4Isupp}XO6 zU3TXAXudJuq~Yp4en0LH@#Oi^Kud5kk4ASq1-Vs>{Uct4f5YyJgff6i=sSQ)Zm@;C z8G6rjk@LkHLc>o{L>=~zjskTd|Cz>HpaKCet0@20J!2&^t4r?R{^k}meD16932CR3 zY*0{RI8b8>s>ZooG+J$E4uV^+hSSQALdy>L^$0mk@Je}rY4Pf*5qlG(2TX>)K-vgt zmZ!vA>b-r7Q8YyO1-~TEzxLt&4uNgKG+=txqnZ$HIk# z1zQ;uFaL40(g^YuZCUhpVTyKweE9aShXRfF&pMpbjqdSt%l_Li8(_pZd;6mGzzoYQ z<#~`{=2>;HK?tQqp+y%k=?ZEbx}I2FyYfnx3-dxEVENSd@nqd8`3o{?c%n_?=r!p!@XVaq0eo5G}ZUb2_0VbxLv51+VrMR%`a`vfKAT2v5X@~z$&CGzA+@&*n8LZ&L9O(+ zP)lKAS9y!`eIp*c2PHUQ0f3nO#xGcj+y;#|ImGtlL?wM671^lb-{8drXyEjC0a1}! z&GXo^mKBSP5-nVh*CICcg%p<8EcW)0&-g~53P5x9kTmtoP3>H#K5dbxXS4m^fK#ek+Il*Snoo3{QKGe4D{2#j zDju~rwW?}wiV{M#_O3l5)Lsc8A|c6p_xm2d_jv!6L%6T|y3Wr!&+}?lFsc2aloB@e zUi-(I6{xYZ9Q65%&=jS`P|4FvEL|r%*VOJ6;ncVmJM;>$lVHBfeg&T^_gI;k`&vt~ z^ZoCi5?meA*fn4EU&n%K{edc@^sBRi(kH@8gZt|5M+zuME6ac$f!V>k)-P}%V{6A9 zuNJrCHe%^s#Lza?#07f5445;Rlo(pW8#4OE5@I8)RmrRx9U#+Ek1_BhT870l%V|S| zPJF3=8D#p;-&LtE-IlQ%vG3c-|HMb8F(2onJtG_4`Y}WVHbWl(;I&=1C$y_FCy@TX zZ|b$G(VyK0ReBWCw!ermyY6!5DCX_ul(-;9TV~+smS#reONyRl!pAggTbp05pg{m^KTDLa7#H^)DQ4Z$HorO0lQ{}9jeEn#7uD$h z+tPk;vs~#7ZReN&Asn-~?Cm#^X~h#Dn6WRvVlZDGUJe-@nPgSLN07Lum8Be4rgL?6EES zi}az-l`fPAkxT|&H}d~^L6^VnViTM{q9sx@mQC>cgVW__cvYo2H z(ekRl1!?~cLRq3;aSySfVkWRdCXhK_H{>7prA8r7agZ@H@Js8@NOYked1+}?{vNZ6 zTL9Thbd~KgNbWDfX+$ux<`6Ha+{vKXkiB9%^%pLs9b`&{S7YNEclhav7X5gH);7X?kwxOZI;-G>{q*2`?B6XHxpg^5Yga^?Of`n$o_< zOJe35clQvCSDu>=$5F0W#v{l;TlZuUK&L(V0w%7KB8?xO1h(zY)HGOD)#o-%OJ@%Y zG1~<^YM7aCaVcq|nM@4pVlg}&Zq5Z(@^Y7CC_hk)*WOFZ^%u@t@Waj*F&5loyUMNP zt3y+38Ol-Jfl_zbFg+G|^ngDPlnFPTZv+%~J@ z3?XAr?;j8kCw&1Yto@(P82cDuN_wIBBE zUg_*?!#OM$3DVH2Nb!Q~Op=+PkrU=_T0&GY3lggB?L^bQRa|zss%i&i3JL)>-4~Wl z_vV>^_M=GEvLr2C^RzxJVK*KjoYcFI#8_(1=Np1HjC?PN;lwKK&-GqR{7nPqyL!J1 ziT8@BW$*Vc25Q5svfmvYtnhA*ZV z2fR&${)Gp60f&u!jsFdUOdkMeHLdCthkgBhrPT${7UrcVo^*z1>Bi90UqT-=LkF5k ztjdJ#BBoA2K)pnnmXVPz3MBgadYe~C&ir(#tbwCDC@DJUYb9XV{6v0{6J_}f{pivU z(kUwcyptYWxk(*%fsi+A0*fA9o{pjJt@oVNv^t|V!DnUD(=1s{3Y=mY+M^lK9j7s7 zWOz+bmJZnS;DucPk*i-@=AkUxl_-FR3&nP;JoF%XQUNyv`b(EK+;p#fX8U{c|Ch0v zUli8ncOuZM6LXjLF+@}1=pzLmq z+m(CYwUFZs*)hsroSI5|XXa$Ki3JnnoG~6Rf2fRM34;LrH!ajzL}Y@p{nm-^%WtLp z;f1oJX*X0WKkV#!)K85wR&g7N4fVotefWl#+P6yvPu8#fXHxd+8|X6wfJnwM5)#fy z8Oj6ietgx+8A17;*-a1iD9&vFif+kyaE4Q0ASnt=stXvgS~~Bk9ub}~k@wmdq6Z&i z9UvD@)3c$U{IX`+NHux5HG%DIBvM)FFxE*?Hzd~K68)v)Ux47XgOCgDd#10Cg;4M= zw?iFFbnL4%Ze+S%wdDtbg}EWKW(%W5#rvY=-lY)4IK^Tha}y?JFFr9oSFpgm$ww$B zz6@UOOo3yg4V9;40Fs}02(dyyk@C(V)@I(1YL%5QxWOpG zY_KMk4!RAdF)g#QYBK@Zz6CPxO1_9ymq+Vpt$@W<_YP+?GJtiV$!C`aMns;k!>5%N zPAxdWA-Hp59--}wN2@(DQLEW49khrBAN=H@m=i993=PZp`3_H})05~!V53SxQ|YkJ zjYZGXTmaJh#?aj1;k&GpuhoYORfs!-eis4W^RF*2vbfo~rPIYd!iugwx3RmT5}EVv zn}-_z4;u3-;G~p4brAlkZ9obB!{ztwTYCP@nBy<3l*9dIlw(fhC7Lj3$gb6)|4Y%% zmZME<&?tD|*F+v^vKLHw*K;0SCTQ1IO+aqy*--#t-!X)WUk|cEti}r{u5Rl~jRqW# z{}d0{7Ct_v2Ybu_lF~F8wj2M~3pnV<{WWNYM#HZ19F;9x#pl6m+GjzECD5 z<^Qc?Osd-M)_9Io+LGEyofpbL9IFE2$!-fx?RyUJ=`n*E=l}(Lx~!Uib`EEmu>8&j z$oY)yRKwpjR5To!P|?B|%CijP>6!L;Ql31Kmk^rWnA-A~)cbFgt=YNmU z(6-FY=<|apaNvRhgQo>2^fE} z;7%S-fS)giGjSa8&%yz)AOff+g5S(Qu66UYpJBv>KtG~&|cfanS3`5bR=?*N< zmW+6oWUf})Z2E@B>`Zk_eG-lY0t1iY;_BKLkZ~>#@O@k0ROKSayw!Bk?EHfdy)Y&2 zEF@`%){IB?0LYjmg7>9n*k<6LGIQDp$VGAXP#PA)i}!(MO7P!Ms6l7+W-hyYQu*pJ z0XvJ-{Zr&Rrtzk06@S~y=U&F3AXpBYEE*dZAEElnq!q|JjtUd5CIsza^n*x}`Ge*< z3>~AeC9j5wx1$k^KUCgemrxz2>otI!f_gwVI&(C*MSJcfPBiMTyCa$M*0jRM)^<4q zNDNKP_GK{aTz44t=)FOhy{*%B0q_f&gN8i(5Z6L8$6$`U4~ZUpUO;1zQ{Ui1rz%do zqr&_bk(C%S-V0}To{8D$@ZDrmI`50bqc%ReJYNJ7&I~b#O-l8TOEeeMKOrmH+xPuC zC=tyg*P^N`qMEPGo7V;&4IBsyu;R ztK8HYKk|YV8h77B?8@wD@QBxtQexxw_Vy@zB}PAB082iRA$xfVSg#d5EW2rS0pyMS~KAC0IU<0Rt~w%n%C!nMeQ4`RZcV7h~5q-KcGBkx}Ym zHf^W)8u$^^MnS;l677=?G&IkyVL_?5XVlS9<$A=^JCY8JI4tpKvj%a(F1SJ=P=lVA zm#LY4Gp|ezi4l~jIR4LcPLf|U^8Jbj-@O}vu2h+{RnQB_mfvB;Lk@+BnxZW6_KG*s zcDVPXTUqE;3;d@;hXOaT-&e2n99XWd-om726^{VU0l_$ zMLd;^hU6*0Z7!6SzW(h+`srehmBUD>~&Vp*OGnp^GoBw|MbEVu9&rLnJJc` zd~Z~Vuy}@sPzI*xt0mGkf4$BpFT#=Aaqxx7$0Q!|AWL?E)zrHi!V*s9@244lJVk*4AF1xda=7k_VOcXR)pL{T>0*89lfE@{=;M zvgg6)N9^gZ7Mk2-7CqWuEM(!%fG2p7#;ri&L7!nt6p5NWvR3n=&5P&J2rx;U>Y0I* zco_Qefuf4{BjMLAeS#lzN*{pM0r1TFQ#YFmZ>_2_xlr`x&70F{8Dy&;miuUKCHj`Y z5*`D09Su|nUax>G)V?AQLQV|rKG^pU0r1xVZ9VLfK@zJvh{I5mZO-fJNdm=m5>0D5 zUXyL)6JTLBWSacG?Pia^`3ARDVS2^i=%QId0Ga?%)YZZ}GY{nbC_zXZjt9BSWbd=O z(T$7&pRO>izo1~Q)c}SlekYW{oNV{D70GrjDS=s9m7yf~>eTH8(4f-|9<|o(@8?*4CKXsKGpEeI3}j zh7y%P=$lgbVGQJyNY4%4oiJXG%6uFrA-o zc6|NlH7sR@4%kG?$Vin9Bt0Xm!%xo@F#cVDF#=#aEpfA~+EF_%!x+l_XV9@hQzJd! ztR2U!8m>w`7WWI@T|ketkW0Y(Zvo4bo?!rV1r%4_0mbgHxef$GB#xeu^(MN6P>^}| z=3Fqk5M-=3H(XG6ytZZ^$3dB|JT;MH9;!w6Ye0X=b)-rTW@UZVc+JO7CgvuU+Qx_H|kgFB8Pa=pEm zY#%@;E4mmBJG}hzak}%K=C@1+XsTt+={AtJ}y-t?eSurE8N5OAtI>!cS$)AO^GWBlzbtS zx-#w%h495JwJ&5!%E{s5fPx9wpP|G%ng;NGZO9>sdM49BUEJKlHL`K=P^X)bMz*U2 z6rr=PuM|TRu^<8PF_?S~MG|`!+z}>SfW$SW=Bjs+MG+)@r68%fV}F?b`b&PoKn01+ zbG`*sUeSP0&5h`1_e+Y`WECGOV)8i?y6-V`cKs7tx05!f%MNrRcWGE;OzG z-&=S_#7lT4Xi{U~s=H=b)$W+^Q|^U=eH zKt=A4kVky|T3K_|`1I~T15iey5PoyNAs8JUo%3@zykL_`q!I=Wqoc*Cqh=q`lh$Ns-UO(k2drakt|WJzNt2Z;yvZG4h=Njm*-csWcf`X#*o^OxsCV zK3umd$b>UA!?{=JTsEiKPHLguB`VLKybH;PW&z`BZT){jUoZ-B&6eK-i7n^>`PJXa zmN0JFdCnw+RTkRoY-$K9zVg^Ptf=eVxZ$-snfekS6}^g8+Aopd4ULY@*I)E`{|=`A z&hNwO53Gd%l8LO|!_enyAhkI252Lq~zW|&ZI?;hLx=rCu&WpCT7fy8m(gX7kO}bh> zwu_97cJCsqfAg4Cyn1O57$bACJR&8Rhv@*vLu>g67|ExG8C|x0dn5FP5zCQkBopBA z{Fg@_usnIOFYNx9%K8{5Fc`lb?!h2(OQ^F{Dux)VS@ z*9X9(WC)gZ(TpW$_kR!Wxs3X6z)l)VfbQGC;B8L103?LDq7YW$b*uwXDe@#1r}q(; ze#G*#BmBOV)_Dc1O6+eh0_$e}+TQRp1Mr5zKeAt+Z(b>ni%SYq?Tum-n{F*aJ$l6K zwqqls9P)^l{!(N@F5;{4L~AYwCvQR?j|Aq8WwT4}+m^AhBqLtArgq0wy$qrF8?tf! zS?a6vKKSuyLG{g(^cADR09M4}#Oi$0JJ?`Stb^e@RBq1EPJlE9`q2GiWI{edgvzDl z_kh~t6q~2uYFYelIR50If8wZGN_{ZhZJ)%iH9(!l%%)9Fl)LZ7ZybxuDf_(ZLRQb^ z8W$v`Z1&90xG!J~9~;qwL<$`G+Ml`o3yj8`jecBRM7p5a^+o=PEerVOCO1|PnQ&rb zY-i=`IzJwGx~9<+uJLrKt?mhBM80MoRkqn902BMfTK_=5cd26DOIgL$kh!25rXS^1 zPWW%~BmZajS+)T)l-o;$mn!Nw!YDaWb-{0c@ix-XX2kkG%q*hg=l3Lr=It-Xhh8l) zzmd8NUf{T(Y1hSx9qCaGlTf3M4ErJYq5bH25q7+xAv!>h&fiOWEvJPh$hmK#u~AM+ z%KPoFhH<%h$z>?276R<3(sY5Sh>{0mhd&Lgs?e=24TYT~H>+xlx84b- zeu)KjE`_XcvbRuBZEvgDgz-^edOU9=chVK@WypQvgS9FY(<<=Kl?Ya}cpo0+Wg0r; zK5wE!_r0!cgqw5f#R=}fevlL?<$UUS@_N_Ty)xlC*9?AT#i%{6eb>+ZliTaymQ4-k zv}sWoDqMZ2Xs;CyTX?D-=r}l|Bw$=0d{!M_S<9K7s+%h`YcD^zo>$ltB3-R(7OHMs zCXeuI`fBK1PSXZ!qN!}cym|2>NwQsa0O7uBnXl_e^mTXtw8LXIO=`>zP6e1sF?Lz2 z0^6*a^cUD3{A?XQTgYAAOvvHV*FP)1p3BCq9Ps#?Lobr{8kv4{__nPotA38|x*d9B zAI9{x%iCk?jdNOY)@Vr1)pKsVFIvfzNMtHzLSmn>oO!s8L6q~=j~oR9$S-#1(k6L?A>d{ zJ_zZ@v&I*25uIf=*y31R&1^%5HK25i*2i-rjGujJDjn;K_OiRh-;Y z;~br$N^d&z_fYShuB7m??gihyIhacK`wLl4m4Nw1(QG#RKSEwkuW#MFy%}G{pVVkH zT*fwo;EVtVI++G|J2D@2sg}fF>sN&|zO`+N!Hs!)Ltrl0)1j{Y{cB0vF?7;-+`Gc^ zwwM*gki*mOHqXm@_X~K-5cYK^2W1TzIxg|~;7_e{LTLWdq}5GFj5DgOMsD6u-tJl5 zw{%_Df^l_Hod~AM8nF=j2fGLEpB$_t6pp(YHBGza3T?SpHSja%0cW!@k?TVV zpjdXZe`z;~w-58>-f667e1w-#NtUS$CBmJ$z?NIA#j22&mOEF%dCTNbUNf!Ul)j=r zCtb;M6Fl)kQE&C8X?_BavQnwkFIaMO4;TZhDMUxp3O(!lhcRs`!7Nr3&8>zhiKl=Al90C9&bt z?pu<~FVNcr7Kx!){#<67Byk9Zy@!3VqVZjizn z{}NX-_q}9z!XV!muh5JT%ahN4@tS8}F4-yejo-qEQUmj{@JzPWCH&yn_#fal5-uO- zgFpPeJ&ve9oFIT^kRbip{GzQ2b6+PTMbV-;06nxd@WU9r{EoV~Px{n8-v5&|%A~d8 zAf0P>vgno**?GSe)7gzY{KNg{_rbHl$oNK9vSFX~!gT3zt=K__~A;wUkzzrEDZ4Lf#y@nRZ1BU9&Pw{!EU;Uf&# z|6N|6b3aus%ee}*Wl(pRSE$}IA;Yxy?rT$kGI}cU$aQe09ja<%zkE=%N1w*-qxc1O z6(SEec3WK7(1ko~@j0@|z}$2t5OU>bjC2m%=jsc2l@im-u-N%r#8jHIM^HI-vNIFs zYdweR?A&gkEq5R*(}6las*~unfU)~kFUf<+?bU>Gx+_`1|c8?&R-jmh5tIuyg+S!JBZBY053< z_vTk~z*!!-zaK~wHYz{~c}j2HnXQ{&X_v6e!tOdTdg%RA`w``Nq>DY90ZP-8#lJH- z29;|oKd(K=GP&^mODt0|(km){vowJ;nj@Pco)S;s0#9!0$FT?NG2s-0{%oy;%Y}T@ z>fp!aD+SzxHDrtwaUXh&>>T#Z9gk!Vj{g*JI(eubXZhOeB&eONzP>qoLrH7;v^zy2 zmwlww=g0&>u$fx9s1>COf^Plo|n{=Ks8Ld&}}DEVCr@P zpAQg2fgy1)y1gR_Huc`b!)P9c_S%Go;E(o#^Je~zCwYRX3P7V5m6DrkZBq2WQ8d7S z_~JP>TM-d7xNBy}B71s3?sk>rnRA$iZN6-h7A(AaW6=D6ZL)1bdBsV_G2&rf zQkyI>q#INYxYIlUB2r&xZ@(djoPg%(xSha=iSoYqr@#HX0*^I29x@@L{dkm*nj`0< zLtVrp;qGp41Mm=P(Ia)5Nc)@pY-m!CS=?0I@?F5*{8s`^0{_au`9F8Sf!4f>EPZ-t z;)vfmy5l?sJQ`55bn7S`pI7m|8gcRoFiQ;!3k!l}N^%ZZj%z%d7OGvZ2_|RX++5r4 zGa6hfZri(qzJ8JRf(25=os*OE94NH~2iaJ z^I8Hvm_Gcsugwp41b?Xn$OX7%RVF8JL@Wf-W9c&EjXz0S{JP4^L;emJ+a30B7;mq2 zzbz%C5y+QA9lEv|4DJJT(zyW)Q!G2~TM1bE_c)in|6)}$_(!JT_PQuEU^N4IjNZun z`df3GZWNyPOA__epXbAD+DyPLvxEQv!G$L8oZ&7r0Tq1#$jMVWDb`a7~H5b@bLv#`P;p-V<^8lt~mo zsKETLv4O*>9F!AXiH@S8^#sZR5tmYTBq3^H?1?;2&&O9f?W_;WS;$yUPt0`)9!X2) zDEe3~U772c3lgTBG?K4nFlaNhHUkPAPGv?WT#ZgA=*-juaM6{7j6F)ka)Nu zaL2sJ&PHu5@c}xE&|{rG(E&0^6#9P&KWu@!j ztNq%oaLK=H$)6?e`aF$}sCSqv*3rh0!#9=81jOw0`9!wYy(FA!g9uu-(=u_huJ&^M zKF&?GFEix=1_trKm}~0tH#!ZW6dsF^&G`M{;bFu4$6db2bpZi^1TFydzseOIwxdR(V*#jfYlUFj|9)gft?}^E ztXF_4ycJX0__m*Bz^S8<^Tubq*6idZ0zC7@x73IR8K4QEMrR0pGJNT|$=g<3;t?asA4uYm_A>fNxmw?1sYLZfg}A|6t9y|h*1 zf!CU5KWA1A>%;o#gRz|P24HyfNI&p57pvIIhoh-J4rwzTD{+8-2M>jiuvL}Cnn-S= zkapKBf;JlRCzzbh`z+<7l@2ZKP(Xe{N9W zApljZ9n%07!~=uaTN^JLuLgd7~vF4;Ws(t&Itn=m`<^8D;0iy z0#uDkc6GD7OyEC<{@z|&L2<6bqZ&-K#R}3+W2!33X=eW)FTf$8z`?uDv?$TiT`fS4 zx76vO)^0s5-Mq$3iE8nS%&9qiHk#DLU8ap(P4p@1+tUI+DH+6rA;fv0pY0U5lG8C4 z%c`4KoVqJ{udWV;Q%mm5X;?;2FWLBi5Or|o%SW-F0}bDJ*C!WB4cBZw;{cCw&HsM% ziNY$amE>O_*ZD;pAPjvP-4azsb4%?oz6FivQFbg7A*2?cvVO< z&pT7AP+sH?ufSl3e&8Rjp3D7_duq!!s~i*zIY)?NhPSJXWsCzfeQHxtDeY1{R|hRN zC+8GyMzj5VvYF!bkBHO)z=v%Q*sBARR$1?uB_>Cuqs@AzhxUK-Bei^kdnWSli@y(= zNhFW0XsiiC$bm><(JJc+{vuo~%qIr(y1IxD;s$hp%AXz6u`mMlVfbO)vzt9v`(Mnp zyB+z|P6j_KN)>A1KO3khtE;a@Y)s@67h`OW1>}jDtGXxnL|l?BuQt0VT<=@q5d4Qo?i|0OSnKRq1K#PSW|krI)+yYy|voc)6*Gq3A{4r8be&$PIzz@%{m zg!nO|sj-PO=#&zxeXpz~%fKw$=Y8<$in_g?s%pC{;9#}hI5T|b$eSdpXyE%unR2MF zVSz8sb~oNe`}bt9_w=l@0?5^-ec#g3at$9ef`x30i*`%^^AQ7Fd0Su&4CO*Sns<@l z?mCZn-?Aj!!4<%d*EZ%37^|qB7k|<^dDsIIx$Y@myR}7oRpcVd^PwtXP>O1Q94e(T zdpfI5wf5BZh3i?fP=Lm|$Et4g$?;1A#?RSeyX>EVOAD!yGLD1`=~+e%H>@RgMywS& zPVmqj$``|LsV|S~Gbk31!lhl31^A_@yJt({6KKk`U*6H46MJq7|CK>W`H=JPI)Gd3 z-$`5S_3AspX+Bcs>ZV!g>qTG7yuS0n1rOrm;?@_gS>P}UWc41M0Is#Ehwz!t3VegA z;t$E?-l}f`d?Oh9aN5*mdg?yFWpoG3p9N>Ro0Swt7#Nl0tRsB~|A zsdMr7*FC^o-*e`SLIkpwr9sGHIXL)GyC{CZ+i;2lLMNIc!Q)UBiZm^E2mDzG*Pyi@e(m$KoTngdfW%{*7@=SP>G#wW{(KXRh5t@l0^GrPd9=Qhvu7xH0KrCL z%L|RE5+C!47^wsrYg^_tcTVAMd#~QfF8hojIyGXFedF8JNNg}QN{whn5E(W<^r?YW zeMO80odA>!Ehe0??@-Dod)b?RA;3gFO_MF%a%(M>8cZeW&&Bmz!*RTQ`!-4F+sKF3 zhHrbJ&y)kC)}$W6#S@kMJ;SW4WJGg<8wJwzzFIZ8P7lw=Wwo|9pYQl#l@f2vtT*3> zJWeHWg>kQH<&}*GDTN2+-mQ~fZ5C(Z(|>~8@Lyr1nuoOD5b4lY%13jf{R@U4S4h#j zjz@vN>Y+hL3x)w9zf&*|Ns_ds|BSEz1Y;gs+oVkJ)Rs^igQl(_lS*1r?@+Kif2CGn zs+?NBzNWX~g%Q6rGl!j2;VWZlC99Y=Zyq~A5p6cab}@&f+QSk5??G0HmybJXnRdM0 zV%H|oXlhbI$YR^t8JhZohFQZx3B6_7%2=H@;w~m8)t{8~A^^Wuz)#+}(Q>TYAEG8; z4p@6fHs=|-S=UkI)gQZ9x>~#a`Zn2*g!A2t(!qITPI7zrYz{O zs}!Mr6!*#LnFVS~1=nym;PmpoWk*ab3}2&fvzD{p-f@(R9hgXx*$3DiYr+W;#}6(g z@>sBzvan>M3I={bBx?T=mSPr2skl1|p`LEybNn?-_<4uyAxmn^GMCdIefk!U?(sgM zb$EHZB(QHHmG3@U;_>9!kofzN9QAn4G+S};q{HB_A!>FIe;~#pEE&^pRIFe z9WV9C-69swFg%d+s$WTg`kJ{p`3z(h8I;QZ=bjL?=gSSc&p_i;N7+)YiHtdpF-D36*4m2)>eW$Mi9iP z%47SljJi_;%%!>B(y{AiMkPHUn!TH)@vQJwMz51!YCy0*=n~Dt#PDuMpDL`5A7OY( z`y+7g1SmcA`9Ozzg8l__w!a@c&8Ybl5nkl=x!k=<3krQMwQ0=Dk`TDVemj&7$V0RC zhVcWRj`VrqOZcGPP^C z{-6S^{~DRNbxHL8 zbj_(IU1ucNy86Sy8&~smCi)TS;gNT;Gcu8Sx}|j#4gYMf3ubQr<$}4{#C>1&7VlRN zedmhFQ|6HdXZKoHfj+0Z&3hSnecN0yBJ)=@`k<>s>%0g&9mf83jR@%69vgYMP{7e? zukB=GdW(qWPFCM--PzC`NrG|9I@r7##5XrS8&N)Zv$S74?fmg71y|6(0Ac}jR%;pW zeCC+Nd`~oNMP|4PLa5%^ksiDWjS2w#kwbUVMhldC?|P0N`SZQ8EOml zXE3nRW9uL(v5xEpt9I>>J<&z%Y@RbDn}zUdN^Q=hAhR}S_@|cfF~-+UPT6xY@)--e z9szs4LL(Ir5tg{f@D+o9Z)RS1WbsUBLHra(vVfynmm?iSqGei7(E6$o%YzZ;D?g|43PD`m-I9YrN1I~*AZGJ5+&YYMm2Tqp-^~6oNV-A2 zn>8mp@gQ)+$7*&^#^>$Mo_)2#j?&r85cl}&aidMg-S(t|vWb;QX|w9!>Z>u0g)oXm1uJkyA8Evk3a31btDB4mjua z<{8ZK?$61Mm)(%#7YXlu5)u`dWF7h*!-kBavWQ2E#qF^Ji6C} zY#>it%}=>nN`Hk$Tnahb(mYyhgt^ba{)!^~T#qF_zm=~H|XRVwI z%?im4!J&Sx9xyhC1n*|FcLvW?A;*qWbPyAp?1F!=R_+>6b2SMK2 zJc@#U`M_{cRM?>{-hR}YZN)38`HJ~hjnF@0fyIXu$L3mi}cz(SX>r9#eIda z(HPz0vd#`9C$LPUPu;`jSL^=$A?5HyDmzf0=jHpRu`(Ps=gxFw+{{wjBPpp8rh`Rs zg=Pq9BThG0p`AEyHGjNgq5FAaKVM&oRAJI9$sdl#1_(pX8EE(IDTgV56w|6CtS^{|$dDNGZo|*G|YxVC58VY~87IFI53yww9!oS{^sD zSF%z1-v!uRJCPIo?D)`ZgzD}{Tb*nwnbi;+G((w zOf!{DKb_2i#gE)+b4KM^)hKp;YMR8Aza11!u#!BDp%|ZXvwib!RMVr5n7iy=Yo3Y% zw23T$yn2!)d%+3nSGMHgJ&S#NEceO8TZB_{>eraY6XDawo?`ZrJ8hJ}395+!PG$ z-ha>aiFod!o!?2BmTZ33c8c6F07>RyQuBu?A-H{9!TVKGV32NEvwkXpY2&}%dw_Ck z)#c^lyMp%kt-co>*!j6t=TTmQb)U@+ZahjHLag>WYTU2)kLTTtcX8i2{?#*zhV^mk z&PbiD)jTQx-n_K<&|80p+v;c2g8N*0i?0U;Hvq5JcboNgF$<*hmvy>{y6sLr&kgmP zgstAdiHAl2k$3LciBjIqP&+k=o7?d!tMe#7Y*5J5io`e~Trj`wlv0>7p_>@mN=FX4 zl7S8(lUHxHV%4taUyXQ)AusH$mi7Dw;zV0{FBY1<8t*fhC(QbE;5+g~eE(M=H;q)4 zHP2^KlM44s9PK>#Ox8{HT*4RTvHG#1-e2!zEFgkRf{dkNrv7*aFwoluP#-X2|6Q}K zGtUvj{<*a5)yr+-JV-e{PH&fKZgpZ;+~qPzkI$~gwn+#m2dpITxD!6Sf8vJ`zWnRH z822X*9Y1erwewpeYMY(VODGvghxDiUq3v_#9pkwe|GX5ka4d}lhP@%?w&KV&N3uk?A4 zf(9oq_!nz?9Q8z20VvLsxlil*lK#7&??24el(Z;0AHMb>=@Q{yJ#&R7DQ}SzA`l zyEo^5W+z>qmG|@TFzIc+*B2)hH=S$tKE!3EjG6t8kO~Djoj)p1THoXJ$<$a<03o`} z*39Kd-iP>SNFu|e>fRv@^E1$;k4fbIhClb-$>xb)M|W>IWeDlc5kvq zJyehRgVWGO$BCTxPs?cP?aplU?Rt1ytGeAjf7vt5Flw1ht0+^uS9WR1J<8;I;IQ6Q z$5?R*kf-o42>q+A$Z|9(b=yWwD`;ixKbrbJ8J8vE5;*47uE|W}GZ>b~x%E}J!`cNn zdHAde<#qZEi5)6HfBk*1A%z<~j)v)tTD64DtI)9jM%=ujY~Sf3d$LtFZc~ zfL@2}Z*^}I1AbGzHZ8{+o{*D>(DB+k)F>|)=~pM!ARHzrRc=T%sdq?UF-Dz5Iu<~J z{y-n8U*deN=M}2k?|%IJ0{fJCA8JGEdk}KhDsHE`q5sWF@oGi=`rD)QvO2^H2_xrq zzsHE#u-R!Ob2KG5rJWnSM8|Z|jr-#6I48l%YQ9R(;n(7?N&6ik-8^G21s9i!c6foq zMFc8I=l<=)=Syt3lLu|F!|t2p@SL@{yHKXa)K=fc+5#KhlO=f2SiKt4KmL>?n6$Om z(KQ)8o9|fjZQ8Va`OF=e2KNoq^7DnnK((I4@ulHrMfZj}?^^0i!Xns@R$*63NTNs* z7fnyk;lBIkqkfL^H-^EEi`KRlK!0vPXk)_l&Qs6VK_b9&O2-%D%D3IQOm(N`f2qI& z^$K~Z-E2M_+b#UBQCPDCsa$8HD#XQ6xd|pb{Uz3i|9JnLCsoW8+o-OZ=#-laU&C$k6g;^19Fij&NcUGnK(_#wE5i#KJGPUCB?%zbGg4=ltVGD$3UnIo?O=3H2ZRW zU0=KW;H)ob@FmgD_q8VAK@IBpt>VSJ$eZ?;?l}v`NDg{bE)$o%XPU+v%iQCt-F5vOTCLBgT>KD z9m5ZHidj)}Q*W5AD+g-&Kzx2qtDOxAIS-r2pmE==?vE~deRx+368Q(H-Rbaoy9D`> zlk$;3*rtusyIphnW*K|8Un$N78Q#T~x`6w5eeCAG}#MG+Vf{Cl!3WRaBW&_GRUTgUNMub?Y{Qx9rQ!xdjI!kio4{{rclm%wbsV&gTX%P}!?nVYm;!!$C4@Lp@qm~17>D4sOwwq7|- z8*oQ0N!JWr(O7hA(#a(@-tZF#e`43!jjU?6wsx}N25A9)Db5kWgMp34o>7}wpIiM! zJA*M~h2I&ErnA0}G(r)BoM|&qybs{?@&)02>_?i{AZ%a|u){I3mrIKi_o+|o-IKE8 zDwvp6{lI`l1xQ7XMgHcszcnaG_+b5tYL z(C4#JXeVSAbg+Z6?Y9mwxj1)W?%Gio?jH#GcM1NRPM_`(4mVa$TW?0!BlkdZA2)<%4}2AaRr8jZ&BMw*OGoBmmWpZ@`Q(v%-S9n++w4gg4m8E)M0~fC(mwvi-s26xWfmT& zIU`d&H^G!$`VPX+zY`W{vVbzhmpG11&rt{}ApALkoO(7sq+416ZoY~?k){Kgw*yKa z;Ge73XbT{qJGNyAizP=1d|4|=Ce*hdG=V}=~p*`%1dZw8-H^w2|0z5uP1#Ka+q~e zS{20o<5ndq#6(ux*?J?hp%^qeYD_{f69H*K^^_z%eH3K}y2Q6_oSuQTkno+FRcf!E zZFNY|$tLuQ+>8zZ1~h$H-!6bEH~?23gWH6(CY!ReQ3_sgGki6vf? z6Nilj%1XZdAeuU^?{jbJ+W*7ZTZhHbeBpu(ge3R}!8L*47Tg&^fFQvkxNC4HI0Oj6 zL$KfwTn8t}%pk!%Sa1mLHn`p9C%gAPyL+GAoqy(;p6c%E>Z()kvG-t#pH6ea|K@WF zgV7Dk-=I}K1oiZmJE5mq{8yv-ZoZ39|2*4y#Qm;S&v4aB6fHJT_dtZ#qgaS8#_lZn zDZ>1Fo$chN5Cwl;*Em0Ig}l}cGGyEzI@53tzO^nGua6;m9+IUIc{sXqQef1Zr4~4t z>6l=J(}V$QsS`g7AC`Ne6#)CeQ$LUZq{HxCSN61EH=W!WHC?tNi$j}|N3j7{u3oI$ zNtc*_N<3%{OZuok{Zoz2DIcqdtN!aR<6QRA)mboUtXER_t0=PPg=?cSNCzJ#-_Ct} z*>d2&k+xRYvqm2?IWcj&EpUFbIcvntmV;wJLFgO3-wmFMEiSe2F={W9@-3__XL*of>V7@*dfe{$CAhc>Pd*bK zMUm#F#DA{1VAcqty#{QL`MT@04(|8y{BJt%?@DgWIoXcX;E#HB!uPBl<5$ZT*~xe~ z4d84+V?F8X1^q1ZC70lQ8Z4sNiSnL+!`4&4*&g+In#{rw*3!b0|K;|Q(~q7YT>Nmv z(W2l8Q}%iC^YSz#+QfiqRo4m^m{tQ?#ngRStjkY&7^6^a^kkk{U!Dg&q4C=1$zti` z?ZvMBEUYU&^>ffKa=nLT61eL<7UAXm#mz} zX1Tq%#YCe7@A6AR35=f&P|mL@U_!+L%(ZzpZ6Rw1+T1jxXXWr4PlGYClOR@_DA47>H0K=9 zO6^$t=W<7)yx#$pJ>^Va89F{fJ6hy$Z^y>=TGpohn~z0PZm!rOQ(JXYyG#G{TY=`_ ziqX8wXlOv4?;;mJf1IoBH&v`Wqj}e#0mg@BSr@w#T6;c&MsOD=>pwSZvRzCg-bhP6 z5llCwVec+=8JTYL{utWf+~I-E6wYL6g#;DkP8)5JgPEJ36Q&=PX363G2&GlC|r zAdLhCGB*sxEGKSy;bLE4FCpv5KCZ2jHRTgWKN zp8@ONoMY8dEl)9v96*!OU9>bErbMG)=M$Hw)IwUG^BlUb(VBuvQ_K71>f?UVdNB}$ zr&2`9hiq=|UK}Y0R5+@k7{1OECXbe({&*PYi?!MH`}j8WokBFSo>6?v7kc^k&9vL) zx#WQ~ox%Ny0Zmei_pLj~z+ESp!DC-?DyV(D|7{DTGd8#L;=BdBRC+!k=6xaC#ZNCp zBjQ}raQ=gD^}o&&p|-Vqo&V%jvNx2_-{|ZcWK=o2A2s)C zdKdS8^$VCO0?y_zb6PS{ueKU{ShWt3idj_ufGk7f`CV8=<0Wn`2jlBCP0oNShqRI> za=#U2+!>W~6=+3s6akj)217k=g1Ol>@9a_GDj z2)O2_TH?cieY-qWA7dw94O)Foq%v>E@8jgH#)ZmT`3mfJ!^JPRL$@reZtp}EG<8fF z94@?A^8%3=avc49}R`QJUx z3lYZVLgWPRur{;aI^*-@9j{|Agvho1| zrP;LLyo^uBsiEJLKfG&;^)FE9-cl`47yG()onds3Y$l`ofYPtv0;Qj)P>6towY|pu zgXAlF&gDwpjsH>sQRQiUm#|(&_cjAYsd@FB^3rPhz4_p9Q(QVv;(#`rmql1L4eba2 zpXM=jXSGzDLUEo^(_Z#-UVDEIEznng&(#+kHru)*0;1~orw5lO_wjiDIb)p*!KQk zD_jeZ9=Qj-O9k}SbUXpM|JcB^id_$M^Qvj8QKzCq?zpcl0hE|Mw2o1-OxXYs3DT_r z^jKl2{2*Wv>Y<<`K#~|T5Tvd@sBCF`UOr49Oa;B%61^{%UlM(NqekCxf=+sgDy>8K zRe_r_4S#xl<@*VF9UxUm2dn2Q9=)!vg@|!L=fh(*FAXkBX7HLfE{L-ejs} zjR=LFNcUs!jy8hNobs@M$3AJg!uBlzHfi(Ab~bz81m4IU&;Sx%q@e^r9|`V-k1}Lt z6gFttpvRV^%|;&E`K>pk-3H`gwD$;`cS!z}A+6)BOwE?-!ASP=9QoSo{v{>uwCvUG zv$b1wEXzemOrCrn^sc@4Z4pQY^&9k$wSLN*sXog*z92W)7cOibQlB#3Ab|2owA=7f zMuZf+Y1m0@o>zB{_mcYsb!wGw@^c@0|6LW1K|o>P8L^&IB~6N`?Ru>hifkjg!= zsD16%Pk_Mu*EGieKc>sWDgRd*)(6JPPhJi)dvh&ab+)jY=8kQ5<}#0P3BlhYgyPOG zeAm@B?^ZAYpzIO&;$jLJ~m5!j44#U9R530TBp>o?Pzimf@>v|^8wKfkf0~Llv zbw}%fJsRy@kH|!`4~jLIY2|yT!%&~TQ}FH@TuL)QHk*Uh309W1y9m)&OIIPiJ7h00 zqhBPLk7f8Usorjg7}C}mp?`nLo)psn(*}EC^DmD5M#mX@XVq(IhSCYs;`5)5e~Q7i zrU`mKBzpDJrvB*pV)mHYB83E?s$iBE%cwsdAiq8{YM+l9rC;VyXuIJJCTW!rfFy8C zDXxBuQ`gc;NqH{zn`#fORZ&0^f1MqD%%0x%SY|a<5qkY;tScmayK%pzt{B_wzhY}>zMEH*YjL7y$SklXC;j*>PiEQc zYPU0mysSteA8+iJMCxby>2TCjn^&lL8W!}1@)ZvL?Ko+MW#NbqFEbO_-1OBO@OI391V@V2g| z;}No9El5bkm3*D=rVl~|T;^U6S&rUYXT$44O_$DHrUcA`0`BKC1>FWlg0~UgM~y}Bv9s`~(P%A)%rk1C!Qss9jyh0Np0%eNVgS541SAP4|{4vp6ZPZ znZrIk>n^yd8tv8I4mUb?WPa_7pF?N9F29Skp)Na!C~+Ko{%6E z`viWqQne^rmZfy^%;90Kf}>odTWpeYZXXZW4W#_MucW?a85el|EP84$L)>3UzFC-9 z9(&=YKJK}tEi^WwgRV3@UVRuV z-N-s!zYl)}U$Vy=*zGY?!_UBWmY#hFrFE5=B3U05C`0uK8(VgpweyGsi~R(FcrLd4 zN8HyNBNSIqRv24+wevcPH=0_}I`#W&%iX>0T<*8!n#U`A6Kq66omQf8Wr`?~jM#m+ zWs-=4{D9@buIbZ`440+wk5I zb7Vv}?Kj8xUa27q5WYJJ8hA9*5vIQnd?-NlK2YkF@A4x2`7?^UgUCT0r4l%W(K!JX zA!}j~y_Y<5U3Iu{u+;f(U^(l847#4p=o9#vKVMpiLE2;qvQm5YZmVuRqN2+8;_p|k zg~YpR2`DYs&%Z|hfB`F>ALCX?VC>~ zrpvwPnLJ>dWT13#z75J~;;Br5V^(BNPMEE5nCV-a#o+!XL$j3*Q`<|K-)ZKqfB$*B zazNeR2R8gYw*lH;FQhdZTV&hgasqBXUb~40172~<%LjLonURG49m!zyW`}p;9jCwY z8N%l6Jt{!hvG2rEN>7eUjEIo32?Su=4ef1hX;Ik9rA*a1N3WVsHO182A69jxL0j|*g6YxDTkcQR*H8e~m;~3A zs&B4#v`Hms&jL*<|Lo#wGDM=P_z&|9x) z-v9mVJ-DHR;s6K4jo^2Y2k0=fVHaxAF6Y-#MS0*`20tYRyad(L^7}0xYGya6_{jM} zLHbdTkz8yE#pUcUO?u+!m)|hLYC?9J`rE^$KH*mygJiSdd6lRk!DB2bZcUbf=32_Y-eh7${X&usP6oIiXUf@b`S7M zhxVU(Z~c3S&-vv1uet+2|D>TO{ZD+wC0e^4OFj?!O4NhO_@eiZV{Z2!P7@=D-)wGk z_x>n!X{!{zIXb+yK;lzYRz?&SVje1iYJ&1OYUKo<#+@ZmW0*}Y$wJR6(L(O@78_kY zU#(ZJq+qA;KD}ns;0vW&+|#${z|x-{ZG~#-&P`Mtz(RdPOAgT^N75wRObd>f!2^(+ z9`DsLP=30^WFTcU0OCcJR#)CWHK)7 zZ#DtdTTPkTi!q|#30r&3(jNn>Aa7@&Jlj3=-az>m`d3Ag{`)-y7I;bM!zD2cCMNHO z?>X_KF`hG1hgaM<-a|(&bRPkMR}V-BQ<_@2{C4pkL9P696WiV%BX`HubnpI(X0&h& z6#<4qHHj<9K#_4sl0QRgBI~n8^I6r_J0XawHlbaU9TeV+4h#X5AXyoo^mEK6Ka- z7X_I7@ts1=T~qJQ@jmuE7i+(NL!S<<;!Y`Tn0;iIVA*@lHOPGZ@L z8u(DZ$N1CXFz4zU@a1O5jH3UGUElaWHADjGL5KkU0VK7O8Uw_?kgtGLQbkH&^#Q)F z{PLOnuPxwVX8h0RXsf=9p4p8;K^f67uVJ7NKmmF{;_=pq_BQ+EZbl$GyvLHAa*hB9 zya78<*7LO00SW{%{B^mOY_tDw+fTEOYl%M|4j+FE)^kJ$o2pBs<{p8ES-@*Bkz;%gZdM`zxy<98nqWCg_2f7hfP_EzB8mBK|Gqw7`T_(NjPM9@ z-`)g)L=CNu$L56Q$rWAj@nI?vSX2w+XEt1wM zaL!foip71r+i768&!7@}g9?yG*!}bkirI*TPq-TZfIK*jRKhKbU z;R7ur0Qsk}Jt|6nM_a$kPUs?^`c?i7*3wUBP^WvvHmFp=Ih+am*s+0EWTPD&GGQ$n z9YWx&2(-%8OjB{h4zHaxiW(;O|6Caz%Ra$?@dHB4buoEi6(4## zB>aSzFXTXO=8}H`*#|9aW_LZBJ4|YXR*fQ}jY^q=!EphMuGQzUWU1>kEDx7pX3N_Vu(>s z5n!-ad73dQ@j`L^fsD$P#M$3#_YXe??9+gS?Ls@3go9C%9 z_6|=;RsQms^lHUmYNY`31>e*CKlmGag-eN2&Q#4(9lInCJ?aSq?C2v7uV!ntH8kl^ zD~aVHKI))q%$nk_{VSS5?kYq zA#&SW(h$H}dX8F2Pa40{D2DX?yv9s~&>sC9wjf3DxU8W4*YqrxPBB zSjz^U4W5|bM4rl5%iC%%@X(@%Yo9f?2*mpb5xgXD_9C;Z!S||+y#@pjbll#^RH-GH$lAr|m_Ox|y*uirX1NBu*Y&YWaoO-ZP=0vv9%;o=AXgu{>=A(FE)=tT1Y2B8vnden(Rw@1oFo{kCR3f zd}Pfib~KSpf;qi#GA#P2D9#k^8m7zzZ+zrq4<%r}2ap>Q{4Qeg#H zs+OhsH)6aB)CE(|S|1%BOHZX0cRL6X8LoRjR;jAaHL9_Y2D$XfACwbu3lBF23^XQH z`kdJ8rvL-E;3Z7fV$TQR@4&Ec*<#UF0zZ`2f7$h<^T!PFKcldg@;5ykdk{=a2JSTw z8dw570ovfNfuHh7^guI^N8LE4Ani#haN_VuV~HTy4tu=NOu2wK0zMFko_z*B#yhio zY_=G`Ayy776x*sfA>}J{CtC2h3cY2(V-+sR=fF52h?EB;2_CD^f<*7>*x+z|-yg|m z_aX(tNq}w8RUVka#*h6|YTyoA8^^if>0oa~$+#6Q zZYTR20-S3;k-n!xr!Q2SJR#zX%TLS2Q;C3)?5oA=)w9#8)xWKYu?PAzLO62M$ zD4p~QCdDq_Y0q{{gS8xDYNzYU1t6kwU8AErE3k!jA54yb`~Lo2BF^M`hZtmRL}xPk zS>=7j=#HOE?#^EG?FJkzEhHI?Z+ro`jzEeC``S|veUSA@KlC0C=?l#oUYLs4A}>0( zbKK`iDr)z@l$`)`Pdbv}I$?#G*`=NdYNH$+E!8z!2#xAAabHKy?S8O`k}INWbT z7fJKyJt223dVZ&SIoyui)cy9jWi(A^TiVTkv_ZjFWJMz0GVilg%~gxoJfK31rRg_t zJ3G1rz@o6_KVCNbzII#ME;mW8Mx?uor7z^v3-LKSzBt{=*wzpRGcJ2S?#9njYD1jX z;^X+M8o@dPHgYgt@{v0q0i#p3_?w4f z+=e&)Jg*nK-91%e(Y=0Cye7t7aAt0w%BoukF)Yw`7JM1zF@^=tWYrqG?!|1FSx;lE zc`GB_Ph+M6PGX?L?#)!w?M&CIXX(7>=T0}_+&;G%lW|MWig~gq-*YpMg3Rw?etSdT zZTFxMGFywkdn5`zz3<;g*JWIyZB708*->SLsnqN?CX0CcgBuu6AwkT|#wN)03~bLa zxgKz)%!zoc3^AXc#>Pg!V}S<3V4e==>x+AaQHCFV1KOCLH!l=;SghJtRVUkZql(*m z9!XsB@jG~iBprx-A21a2=#WJ?;=Z*2y5%sW6DFbusz>Ac%2FG#^TVztPmP+ZjS>XE zTApL}ms>#%`)7>TmZ<&ww4kTqqESCZ?yrt+?g|?$40U@|eTievT&HGS_n7OM0Z=(t zjZ)QdFZVwggJ8KUz}-$9l7%nlI~vEP!lIvFIVpWa&tf8Tp=SmRr;LO{kjHsem`-Q6%kP`JK)<%Yy_xR98y z-H9rjg!gM0c0)?L>_^9Z+BpZE9a$sNzA_e5k?SM%_kjVu>QPj__wlaN8BaE*g00>P zFVg&j2xm2bUrg@w?kXdr=csAqIC@)Pn@Xoy$kPRC2sw0iIC@biSvLwKqPy#D0ZJt9 zH)u^$xf@d9DH-!gg7b8CmP(WH2+k_DiG9xo2S`Bqyfqs)y-w~|R$>d$eL=wk>rqT6 zm!q3HxW-s~3GlX7``#a2(3VjnP*voSal)I~^z^S)+^qW`i_R;a4izm4JEi>ijT#yf z$X)Gq?RVP`r(y2{gloB3Gls-;scu@DuaO@{|30m-sCM>95zwLMufOr&Xr%n3c=xgx zZ$5IZghDl}Y;}WU)OkHhT5*9pUl@M(*iwx4no_ z@!qH_>$)<7GWf^p)C!?6Vj3~8#M9qHI~%dC@G#6*HeiO4Iz8Gp+zR5Cc5~hBh&yQO zem7=IYmhTocAlk7>>X{=I@4vzTbFZG^6E+ni*L&JBOcB1Pat zUq_#0RQsxK-(&easWLt|*v@a-AhjlQ-(AR~J`48SpMSVQa&`;-?Qp)WRrDOILUn9r z9&2lF#Zb=PU^@iFF+u`l!4~Kj@|jzk7W@koAuU|jc4p95rtiM2>Gnec$%@EPNY|Wd zW9M&0CuoGmc!WM$r>&Z62;r73{Wd~eGM_t)g<8C^5j|{({WS;{=Sv;`^L7Om%Ai7& zvlecY$(YQs@H5_Z?Ciu-Tr9vTu|BcluO+csqT$rld2Hv~l@$DsTV93IZL*SvC^50s zwK*ZQ;hx^1^Bii=jO-6^R`D*7L-oHsY9KxJ338S4X-YbJUS~aDVAcNMv-Ap8or$k4 zz0~Gnr(M^gA)z6QBXT<@gP3@8X+`WqNYh;LC?2y&0Wv}n9zn!!BU*cLd%J!b1bBbm zNT93H-lMlliI1MHPGCWTx83D01Lt)W=#wm8%aC##r*ze>O2xQ`hB2PGO~~nUOi3l zW}ZmVm+#NEdIMGr@ySohs&brVsy@vp)Rc{@z5Z~BYa(`6EX~@Vs_qx#iPKupa~Uj> z?OOdZ)bu0)#xQha@HzTa6o+K}*A}2veDbV|Ql}6) ze@W{VnH%Ps?7-mZKeIwGYQI9S+B6;ZY~WtslL-~=3DeP_7UU+iMtO1Rx?z~6xP(dG z>BHZRxiJZ&i_Nj2VEXz$f6wvE6-1GDj9FwtqF*yc>fSe+*;m#nQhbhB8X2(bcqkCvAmnlF6(E|h3C4Xr=L?_kl-=LNsHeipin zaK`LO>6Y?=tAjE`A>eAe^aChkv}SOzr`dB*?Z&^(X1Mfk$rd#9ZbyEA;v=px!R{A5 zMIoj4IU6&=^E4CJwe>q&5eVa#|Ge5`7n4{jgV+r0&na%^{>xC<^X>A|HNfeEi=$S(?QO}EROU%rVq zrXte!l~T3_qTlj=4V%=z*sKxH<$bBX)4s1ViM2BZ{ndEV+gDkCx_!O4{wwr-mP*4$ zCW7>8X?SH1m#l{I&O~2;A>PTG;>h>#R%E05;9~*&n*EY*IWm8+V)-O1CX4gJH8jb8 zMM1iiw^+Dxp!GO%IjEw~(r_55$twl27AAg2oEdN;AuU9Z$j=n=YzH0x6#vW;(E=^ ztd9@XDIe6owTKp&*kvdjoe4<2BU^o&j_~@xFO))@>q|i@ZM?KZs3FH47h|bNL#jWd zpN9*(-x$TMI&x`eB4HGupdykX=PQA`x*nV8E93e(`IsYfBVDl^JbiZt_pd$0ZDTq7 zuFp5FMHT~CqEumvgGM)FR&)VPg6DW6b*an*DGpLAocN9!z+8Ux8jci<7LoETjl2E zsia^(R$e?tYjp-Ic3OMC`-GmY$}9)giR07N02Gb={KPh{LPJ9bxWRU2D?f06lGm)5 z*&kXy9?@=G2{U~#qIIAnPW6TE zK-bdQg{h4OFxg5^1rSQmVPLs5iQ2qm8)<237FNeVm!wfGsCMPE$_m{)> zH^cW}0gIGqqUH`}7OAmmQq;YSoOyN>Z6a3-6wn&*e%);9vvyM(+E-n>1sVNCw{{OkLpRqrgur&Bpmq_joQ{g?SFWAz%DtnK~VOouCz!T2=HuX+Q>_KMjVA z)J@Zk5rcr z?X#@O@Yz6aFWAC?{KiYYxm)(KjQ%Yunb?K>kg@rPe`;~I$|)#1?45E5Cd|5YTJOB?j` z$UQRFD1|oY-I0Y$neUyC7pu3wtiECOWb$N9e)0s2gVKJZ*Lu;X?2ksu>w^p%Xx-V_ zamj&|OaJ%W{LY_Wzga|_oq3qBGdlGFT&b+l345DHwlvLG;B&h_dS!GPOWc zbYFm`c|J2$erC-D6R7;Gp+_Fu4PKV7q}m;f+R%Oo(*i&Lr+-U=1l(rLkika_ziwdN z&^5^h{*#V_F-dI0OY6Kn6?J06rt_V=s-v9I6>u9Hj=g0lHzI9xZr&KVv74Dh;wclO z1H2*n(Ix-v@5f=~-uma7C`t*C6jCGPlzZ1{n%pkmHFp}J(%-DurLK-oSd`aqE;&wf~W@W6a>r$qlO ztycULMI@55#!&XxyJlNfV7z@)#(k;f9m3S=a?Q7PWmjct>9Df_FUt{Ql;35`u9@}t zY!F%Cb2uPzKCRHUX0$P&$En-RkuJ0rQK5KWwY(3RTI6%#s=b(P0RZ)fempXIn|z)y z%q%r9Jt4GO6)7c|ZsU%aSAwUGOipUK!r1W*j0{A&PLD$;>fBKP90teSnZ^0PvbzH} z{B=yfOv~1kwUp}c+#||Q>x1~SZt9QLB6Y|OQ{(KKDRhdxc60Lmc4*31HcFqH;PrA6F~isqTD@W@U#A-r3+vb&3JS0e z+Oe}=wD>z6oc=l0^9%0`H!56{RQA1FaO62gU#XV+LursPUySptYOi57Mb(Vo)5=qr zzWa@B+UuIBev*f+B~tgJ9~~2rjlXKEajnj-dmf4>Ba)HR+5O^lH|QM4;BNI@WIY!j zO?>YK>11SEsX&-+-C#1-F}lO2r>!7oA`mSVSy*FF8^`xZ`)4ypO#Vr6{q0qEp-*rZ zWqGh!`PSO%fHnh^Bu3&sKk~MCZR8lt;0Nc{SJCK_8{N_6N+Ep?&&?5vbdNMe_$EPj zt)U>5mm&DpK!m^>GLX=3)$N!?R2-UCXg;aPLGv_UM{SIcX3@LA@9{|XF<;5nG;UIs zxHkXYKEhl5Dc_EtBlV(>*^QXT?Lg3NN}b_5$c@R&g%2{=6%`oh2ED#GCP$|yo%V`S zlZ;sw#0*wb|9J;%*<4IhKKyl>dXb>ASmaER7j6AcaL(SonB=h^^$XfIuan7s5{>1< z+I*kc^s~m$FONwc0bnQr_y$7wCwFnfMre0RyCfxXpis-`Q*k_214)>pj(jW+^(B zRH$!o;Nm@!vUb0kb{ii!HT5~}9MGGXcK5KWHG)^3U0q@?x}d(w070T?M<(sa(|@A| zRc0dvy?5+Ltj&`n<<%^8b@h&pj&{40`8)f+PrwDyzU8uE`!SNg#EkBs2SOv}{W7Mz z&UR`wD;|3P54dSy@|NU(#W@&SZ<07^a&s<2MnAA_gCDm4lzXoPi+Df$ZY2Qy84n+Y z=RmG*33+^gaK_L_QI2=?puA1Hd68!ZbG?DA%zyo%asq+YaeOWlQqp2Bx zpg{M3w6q?#R!}d`+VT}Q0;MQW`5Y9lb)k<>RoL$JQ; zFRsn~{UKj4#DEwy!_*NcB|U4}cWI==?Y?UIaIPKS>_XoOMhM}9fl?;6K5t2Wz+f*^ zzajr?3xMV4OMfpZFIV(0Wzw^IXa*?If{(H6WbW-P!{O%PAwwHCJw3g*XRkOWC2d;u zXJ{y9E_`mHSiNvHRbY(gnC=m{o3Is>Ln)|ihB8D*o<0hZTdf#M7osDXoD^7l`xG3p zE$#I`5nwk(1BD5<1nCP z^)q8>WulGyGHZACV@iR$0PcU%y*)E~2X{aWFS)&UaqBeIWg^7<+#adGIx7;ThBoqX zH8j;u=me$+3z~MvK6CqW<$gh^^SR zjzAzOE^!%!du*uWW*_wmDTDJ-2V3g}71Z;%(Q>I-4j+kMX0HIZFQUpQlM#iHc z86rSl>jCz4avBpBeh$`*B6YHbiN3#G4MF}7f1$huVwj-^8rl1 z96XD4M=~Q<$x-WMsMlKH%31JcpJtCh1B|&mppVVFv&Fm!Ms%PruZnN79*k5 zins*X z1t=o>O#QFOm;c>z{C`-lKk;7mSvopaU5eHdLkD*VJemQOijSiB@1Hdrw3i)J`VH-6}pQK{mK@qplYp`#zF? zO=6wUx3GQQ0x>;lltTpStWKMsc&(;b;9bZEB+u_3Ug%j^D)}i^?5u@a0n=_P`Vl)_ zZ<4K&L=o}ntOK(k-27bj%jNp}RaNNESrSbmaS}PcrYdb4Aq)OoRjuDfkCYi~l-0N=%w) zf0PLf-I*J;PPOmyX+kInqIdV$t5MkiN&#tAN`9}dHJ|x?r|rj&$xyo$GA)`oFx^^K z%^%qmY=X@rje}|J#AE-OK1R(ZCJcL%>3nHeH~n*mRE18yjVC4^zlc6G9=8CLRZsOI zwNy|Z+jKba4E+?1GP)nALmLlaJ0QkrO^=c&Clsdv)doA25b#9R4=o1&)nc@csPoSU=RoqlfG%eK^&e<9g{@@Wy-&wU8L8e${W}@pe~F-akoZYp zaL~iIHfp>viXwXx{MwxPg?=V$F30&oU-|T2@~mX-l|y>L1NB&-yVEHa?-#cO_UJ;+ zL&HMa5cuWf$H9Re|wh0rwnmk!rGfR7XUePa;& z4r!Ckq6yk89W!>6`y|&a53*bN=*2|N{tJVgXOUZ#a<;e~O!b!8KZg49{w5ZwC6G7) zH4&Wl`DvHjnljIx0m^jE=+K_uL&5pu!W+et+ESFda(p1+-u*c?`~VHLN7hU7$MjlZAyl6kYH=O)9bbEDX*-$$rh z>4u@9O021Ec_LEH$K!5tAh-pK=FVH22l|c-uL?iRj)$N;!|}MHoH?UOIff2&faZeR z@zfJLk7OL3XATDN`>-(DS0iAMnnbSbnql%rpGa?ESEb>`dVhvaRf931r3n{4}@ zh|No)@K9>1(-1=$%PFy3lzSrlbWeKMfrMtDqwcpuW_%IQ0`mR*=d`KHqLN+s4Z%=j# zqX??>KZLAi-GbZz1~e&ohgiH|6`7H|D2}m;!{FrEniNe15#`^0nGK8kj-)Az&Z>_d z%QqY%!$Qq{_uL&Anssmu$@)TO&A<4i)#-P|+$x0;V_^Ujq=!FOPs<^VqU49+hrj(j zqdL2HU@Nc(EIF^|>e0e}>8W?tmw7ZR=GG0Qf-E7{rYHx|{R;y%X^(Io_b!)7)*ATzDC9Tz;d^eYtp8ezXk3sljT}ncWo~9JMi$;nS8EH?-jm)+SN3i~kuLNm z){7)0mPY@9+ZQLM)xDsu&wxP^EAZ6eQv?n;S`q5})kNE?N1hfQ!sJ=B4ve7|{Pz1l-4Vm9UDTYb|H zMzyP3S9MZx{hk$JAYMyWG(%Z=Cwfz^9z#vGB~Xeg!2?2C;>1)=;oA@m>;#j%i8|PY z8uFZ6xvOH4+o8ba0IXC}epG+>d)#Bn$%UVa%=+LqwRqE#;b&@q={uh5-b57!QVO5L z(B%EmOR`r%QO%O`DFK)DH78|UStm-*z5J;zJ;Hr%P~U^`si_)6cf+O#tlB-K^$t#Q zRNLz#T(iI+ZtRaCqgvBbS-$+2hwz{NwyS6CE8bU`Kb@PqO`=}-?vRU52t8jXIa@50 z`JKE}+z@4St|*F4fAE5>VFR8k(aA0F0*hi%`BKVyTDCscO39CVj%WXwP#@xl1o|Hp zYc{mN$6)#fxki;-CGKeeu~)MMqot95Uj6$6p2|;Fp+KwwVuBvv1sPRFob)TsIW|iFZ1-O-ZX8Yj@}MP%h#Z3P7)6(p z!?H6n9@xnvV*}pdp7SxdCTT5q`9*bAP;d@FQg&LrJXY5&j&cXOP_l@12Q-4?JA&i= z@)rB-uVSz<9;=j$`!$ZqI3V|N&Z&Ohgug>@ukAnT@^OrQvU!O8{9y_a*ZoeT##r7* zX8AYsG*fvWB3rN2ty=8CD9I?^ow@X;dqF=U2V|>8a&*Ml3QcGk-gzu$Kx-*_a{ z)|Yo^4icCelC$Y@xH55_o?&qw=XEL6jps8~yhOr{xwp4yA}e ztY{W3g7ccRG0X)C>sDV*UjOAo~}Hyg&p_AMW^MLLjoY)OF^0tNyX1u2v!OUy&TO zdQdO@PVON%?}m6ZKtIgvW!X9YMYLajIx`+$P<$;jR$|M#T9qXwhznTw4 zYvni{^Zu&j7qa=Bft_IPyK`RUDPx(|^;&Ib!hx(mGcv(Q`05r+drf*=H(AHsS5zK)BuGM0(cQ9%bnx0OQ z0swY_fa~UTCQL@vk(tZEE+YYoPXWm?YvDkEXSZkH6^zbsVv4{`-BZ42Oen@QdhF-R zwu_!;IRcce7-ZQG@aXUasFe?!l6Qf0&#H2h%eqz`Ve=SdSq^c=l?^Y`WmXolN^Ajo z{z;*Z#nk6rFIF5#_=(T0r&lz7_eFLJaGab z^Ko=EJ1h4q3w`_4V~eYTAa>KMmoMGy$7k!cbr>JWh?4$5Zd{L9Xf?OizYbbNPl zFh5dKCX_NaZX}JRY)o5bZ+Y$%_mn>2$d|9$r_7|N^MQsmD^Og{8S@C_L+#OwV1K*0 zIkU#Y(rTwnReY8!Zpl%9=+Z*!{Q@-a+^JT*$R^m*e4h|LLVK;R&7U|q9ksSjX|<)& zd{$Je)+nou^tcdc_Cs&jSF2*Lcll@|_ynF?QyVzaDPRw&;>#2G>SzPz!3K9wUP^Xv zyCY;AZMxdJ3u#mSFgIkmcSv*PHkKA*5qujR5a|1*JYzIO|BdZvh7~7?|Il>t*g%G) zo9Ou7T-CBe3UvoUW zEIYl@9W$ey94nYO7?FB^c#_;f`ievr;wWeM{CqeeGT6;s@-!J06$TQ4W(r^0I7j z*Ld%cyWd8ZTqN`+49m={De3yGb#`9ZlD$@GJAt;`xdNNV>8)$&x+QU77{~d02MCT$ z>eid{#@q?;r(56fV>>d*g9HXTvHT!q@aHU+Y-?a?%!7-nU;OJ`CU5wuq?j-jSC>t-Bh+<_k1-=ZbnmYP6RSq4l3^M~3CL2e5e- z9;~qaJ6fwjt4kL(9*^I2vqXYj$z3UoTfaBXs;} z>AYMwFJzpOKDZ%4xE-K4#FROd{}7e$fnef+$+bA?CVH6MEAOPGip6#ok1x(fxPNqM zr+9cPtUAZ&^*E;8m0;adix_W@-Q64bNzb!H%cGCQ!Yqka8qn@q)*(z_N7fclj zi9T$yMw7oz&E4pep?mWn0aZZJ1Pp&GDdCs7HO1 z)@;*-)oAz)w0Zpuzw}V^DHL~|JSnm-GJ@%P2$)<%kWAJ2Av?t~Ndl-ttBm-R&NpXL zIoTNm!~MQ~?A+B(Mddr;vN`9as}rL5s{P(9mwTD~!SLe%n6Na@tBeGP+LOMFstsn< zMwW3|C7lju_bY(iV|!T=D}altujdX;UB5?W0i2)2s&C1+@|nC!Pzo1!3@dV=np^L{ zRJMNE~(pl zKIm*&(Jo%T@wt^kJ!*9f=*<1VAm7?Hr*i(XKeM}+ih`f+l2LL#nz*^0#W$>&7AOpjE*unHBUle-ZfzZM!6cdXhXUiMQEb3d~JrsGawJ^LwJ}~@VT?=9VDE+ zheqwO>lY5%@udzQDrU5$3K|y3ckIaudn0b7nQX7<*4WhScbOQo)fB7Iz%eo)D+F+w zLZxanm@R!7>!n|~em0B#0W~oc{#*kJ$zzKFo%8Wz&Ho660C#>+{tZ_0|6F16xMt|} zCI74*^!M6X@3SQ^En~O<_fLU9e&$6?Zgq4mzMkJ(-0h`+<;eB+vh>Un+YtFQO7a27<69Ms0qZ3i(@MT z5eb)l;l}IM*`Qu;V3!ttq(3ue~p;A6Ryx7wjkmVJPp`1DJ*s(R%{M@8OBQ*1&ECLA(~OC#0|)mBexwhEofQX7Pn{9E-`#Rht?xunl?m z@v}^Az6P(y@&bK0JDV4c{wBwyV8{hJMSMMYB4mNzvf1*0XiIOJQ+SC;HOmQ53-dyj znMYJ2N4J1WM{VD3GO*=O%sRa@pSj+|c(pi0C~ba~9J0e!5N0L=?ci0!obH#W8R^V` z8sOa31J=lSGt@&5wECMax3N_v03YWR3MBm;4zeKpo2o?~-!#-yr|X3fA0zo+>r(Uz z|5n-hUsq@rlK2DIWkBIQ^fyEMFG%x0y{204z_c9)BHk6VtW&}z6y5m}SQl8}$q)1? zM(3Z$Eqa=_Nb%tcwfWKujXn$DG}C~>@HAIUfMAO~Qr_O@XONe#ZF=%u^}*DA5$9jWuB{U8t%YwTL>Z{*a|w9H(Xzd*)B~fx7j|WeDMw;QuHKu zt@+ZG-GA|w#*f2*ji78ou9$n04A9{{@w0NUB!wViTDe@zIoIgFcqu9Yyl{i%U~O~9 z>pToIBbua;G-Ufe9SC09A*KKjOohg#Dqx|@&~;hzN7Q}!(`dzWv{=4Nb`1Jcs`R6sdC4^&aUNX|DzHU z9$o88fEfH2u^WkqCf}QwTWob*hK=I=DQXk5#>l`kfDZv(*y8b+bBiY8x-h%i_YzI( zkD71ACFC(wnynYkl)a6eY`e@qU3NKix=DK(*uxt;INl z{cjG&kSJk)v8!Sk_vvU(T5Jq~>ALO}_py~Vmr+9a-HS4qRK@M)K!Q>|B9cV`q^tI{ z{|Qas#z&5%LyOImX*vFWj?=CE|G+0JkUfI+cnbyTkQ+lGd;5AZI=`XCP%&eO=`>Ga z_$l9r&;A3NREH?Vp)8KH1AY0HT*5iI_u}F=n`- zkbN@K0lacvc!MyJ?8{PkCRKklGmi=&-gYNprTCQ(9jOeO^?AVmrOk1j5fvZ&<@}J3 zauB&!OtBy=O;^|&VJyRyy;mmdJ+m>qHtIB20T6mY8&-%4f~+BBDY$l4)ovz>wI}69 zW#vMv?-fn>)v8oV2#&@cFWi?gf+D7FwMTGnOoXiNb~NsE^iuc1A)r*+YGXnA0*IY& zgB{_0lT!I9jiq$flj2bNW$nIMHIi?!Q!hMAdo**DW^;ROElDzGSD+VKMAn?LdyZko zz|x8BFFpVUpN~Y>%8s~=WsLM*2&)ryLw|j+lNmi)I(_h1pp{l(^3tlK)(hBOL-&3r zyokl;&>!OgMo-nB)O-8;E1K+qZeWHSL_ErQfya&HOqj8Z&E7>XPpdh)!-n+5%v|Ye zwepFq_9k_#w(})-_rv(I{mrEP&7tsJBvvw%1eu!7WiB0~rvT79?UMG+_O=`oCYLL_ z^nO$x`itwf;X-@E_PyBm5vkm)_vxoxI%dCjtbv6v0w+jJXkyiR{BznDXI4lTp-vPe zQhM9y@bjz>nns0Rgh75&KR$&E^77W+-J2Ki-(WLBgNX}7&L>Cnz!m7Kj^X7}ExUXF E1mrg(4FCWD literal 0 HcmV?d00001 diff --git a/各种归档/20261010_默认画面保存绑定/验收结果.json b/各种归档/20261010_默认画面保存绑定/验收结果.json new file mode 100644 index 0000000..e11d751 --- /dev/null +++ b/各种归档/20261010_默认画面保存绑定/验收结果.json @@ -0,0 +1,38 @@ +{ + "deployment": { + "result": "success", + "native_unit": "passed", + "python_passed": 509, + "python_skipped": 7, + "restart_health": "passed" + }, + "production_browser": { + "featureUpdated": "2026-10-10T10:18+08:00", + "version": "1.1.3", + "bootMarkerPresent": true, + "defaultType": "animation", + "defaultIsDemo": false, + "overwriteStatus": 200, + "refreshRestoresBinding": true, + "keepsTemplateIdentity": true, + "defaultUnchanged": true, + "temporaryDeleted": true + }, + "persistent_files": 430, + "persistent_contents_unchanged": true, + "installed_source_matches": true, + "local_original_all": "passed", + "isolated_python_full": { + "passed": 505, + "skipped": 10, + "failed": 1, + "failed_case": "test_power_loss_between_data_renames_recovers_original", + "failure": "Windows WinError 5 directory rename", + "targeted_retest": "1 passed" + }, + "isolated_frontend": { + "passed": 84, + "failed": 0 + }, + "payload_sha256": "84527ee7b383c6bacdc22e3b4ab74ef05ad3fa7b95582c07d0a24efb277e9385" +} diff --git a/整体开发需求/01_网页配置端需求.md b/整体开发需求/01_网页配置端需求.md index d64d83a..6355fc5 100644 --- a/整体开发需求/01_网页配置端需求.md +++ b/整体开发需求/01_网页配置端需求.md @@ -400,6 +400,7 @@ WantedBy=multi-user.target - 静态模板缩略图必须由核桃派后端按场景顺序生成原生 `64x64 PNG`;动图卡片复用各帧同规格 PNG,按完整帧顺序和原始 `duration_ms` 在普通 `` 中切换,不得抽帧、截断或在浏览器重新合成场景。动态缩略图只在当前可见工作区和视口内运行,页面隐藏、离开视口、启用减少动态效果或加载失败时必须安全暂停或回退,不得影响真实屏幕输出。 - 静态模板“播放”直接显示该模板并结束活动动图,但不得替换当前浏览器草稿或修改默认显示引用;动图“播放”保持相同的编辑解耦语义。静态模板“编辑”才读取完整 scene 并进入像素画布,且不得自动更新真实屏幕。 - 普通画布记录当前绑定模板、修订值和最近保存的 scene 基线。未绑定的新草稿,或绑定模板后相对基线发生修改,均视为未保存;静态编辑将替换该画布时必须提示“当前内容将会丢失”,取消不得读取或切换目标。干净的已保存模板可以直接切换。动图帧编辑继续使用独立的未保存修改守卫,并完整保存、恢复普通画布及其模板编辑状态。 +- `WEB-DEFAULT-DISPLAY`、`WEB-TEMPLATES`:浏览器识别新的设备开机会话后载入默认静态模板及其编辑绑定;同次开机刷新恢复本地草稿和对应绑定,保存可以覆盖当前模板或另存。两个演示案例均提供保存选择,“保存到当前模板”为黑色受限态,只能另存;演示动图以第一帧作为可另存的静态编辑画面,来源仍为只读动图,不能误写静态模板 API。用户动图沿用现有逐帧编辑保存流程。绑定信息独立于 scene v2 和设备配置,保留原修订与基线以识别未保存修改和并发冲突;读取失败、草稿损坏或初始化期间发生编辑不得覆盖现有草稿。 - 编辑普通静态模板时,页面顶部提供单个“保存模板”入口,点击后选择“保存到当前模板”“另存为新模板”或取消。保存当前模板保留 ID、名称和创建时间并更新修改时间、内容摘要、缩略图及修订值;另存生成独立 ID 和唯一名称并把编辑上下文绑定到新模板。普通未绑定草稿沿用“保存为模板”;演示静态图的当前模板保存受限,只能另存。保存成功更新基线,失败或冲突保留当前画布和未保存状态。 - 删除需要确认,并删除模板及其所有有效、过期缩略图。页面同时显示单模板占用、模板总占用和模板目录所在文件系统的总/已用/可用空间。 - 模板管理固定把两个随程序发布的只读演示案例放在所有用户内容之前:第一个为“演示静态图”,内容与开机笑脸睁眼帧完全相同;第二个为“演示动图”,按开机笑脸的睁眼 `1300ms`、闭眼 `200ms` 两帧无限循环。二者来自可替换程序资源,不写入、不迁移也不计入用户模板持久空间。 diff --git a/核桃派软件源代码/FEATURE_UPDATED_AT b/核桃派软件源代码/FEATURE_UPDATED_AT index 8c6ae66..b03972e 100644 --- a/核桃派软件源代码/FEATURE_UPDATED_AT +++ b/核桃派软件源代码/FEATURE_UPDATED_AT @@ -1 +1 @@ -2026-10-09T16:12+08:00 +2026-10-10T10:18+08:00 diff --git a/核桃派软件源代码/app/main.py b/核桃派软件源代码/app/main.py index e3a4009..0c16a1b 100644 --- a/核桃派软件源代码/app/main.py +++ b/核桃派软件源代码/app/main.py @@ -5,6 +5,7 @@ import hashlib import json import logging import os +from html import escape from io import BytesIO from pathlib import Path from typing import Any, Callable, Literal @@ -801,7 +802,11 @@ def create_app( @app.get("/") def index() -> HTMLResponse: network.dismiss_for_boot() - return HTMLResponse(index_html) + return HTMLResponse(index_html.replace( + "", + f'', + 1, + )) if ui_copy_store is not None: @app.get("/api/dev/ui-copy") diff --git a/核桃派软件源代码/app/static/app.js b/核桃派软件源代码/app/static/app.js index b26f767..59f90e7 100644 --- a/核桃派软件源代码/app/static/app.js +++ b/核桃派软件源代码/app/static/app.js @@ -1,7 +1,7 @@ import { DEFAULT_WORKSPACE_ID, announce, apiJson, getWorkspaces, markAppStale } from "./core.js"; import "./interaction-feedback.js"; import { setControlBusy, setControlReady, setControlUnavailable } from "./interaction-feedback.js"; -import { setBoardWorkspace } from "./scene-board.js"; +import { setBoardWorkspace, initializeStartupBoard } from "./scene-board.js"; import { renderUiCopy } from "./ui-copy-runtime.js"; import { moveWorkspaceOrder, resolveWorkspaceOrder } from "./workspace-order.js"; import { @@ -343,6 +343,7 @@ window.addEventListener("keydown", (event) => { }); buildNavigation(); +initializeStartupBoard(); setWorkspaceOrderToggleLabel(); navigate(resolveWorkspaceId(), false); loadWorkspaceOrder().catch((error) => { diff --git a/核桃派软件源代码/app/static/board-startup-model.js b/核桃派软件源代码/app/static/board-startup-model.js new file mode 100644 index 0000000..923ce59 --- /dev/null +++ b/核桃派软件源代码/app/static/board-startup-model.js @@ -0,0 +1,58 @@ +export const BOARD_SESSION_KEY = "matrix-board-session-v1"; + +function validContext(context) { + return context === null || ( + context && ["template", "animation"].includes(context.type) + && ["id", "name", "revision", "baseline"].every((key) => typeof context[key] === "string" && context[key]) + && typeof context.readOnly === "boolean" + && (context.type !== "animation" || context.readOnly) + ); +} + +export function readBoardSession(storage, draft, bootId) { + const raw = storage?.getItem(BOARD_SESSION_KEY); + if (!raw) return { bootId: null, context: null }; + try { + const value = JSON.parse(raw); + if (value.version !== 1 || typeof value.bootId !== "string" || !validContext(value.context)) { + throw new Error("invalid session"); + } + return { + bootId: value.bootId, + context: value.bootId === bootId && value.draft === draft ? value.context : null, + }; + } catch { + throw new Error("画板保存绑定损坏或来自未来版本;原值已保留,请另存当前内容后处理浏览器存储。"); + } +} + +export function writeBoardSession(storage, bootId, draft, context) { + storage.setItem(BOARD_SESSION_KEY, JSON.stringify({ version: 1, bootId, draft, context })); +} + +// Resolve only editable static defaults and the read-only demo animation. +// Ordinary animations retain their existing explicit frame editing workflow. +export async function loadDefaultBoard(apiJson) { + const reference = await apiJson("/api/display/default-content"); + if (reference.type === "template") { + return { ...await apiJson(`/api/templates/${reference.id}`), type: "template" }; + } + if (reference.type !== "animation" || !reference.is_demo) return null; + const animation = await apiJson(`/api/animations/${reference.id}/frames`); + const first = animation.frames[0]; + if (!first) throw new Error("默认演示动图没有帧"); + const frame = await apiJson(`/api/animations/${reference.id}/frames/${first.id}`); + return { ...animation, type: "animation", read_only: true, scene: frame.scene }; +} + +export async function initializeDefaultBoard({ canLoad, load, apply, retain }) { + if (!canLoad()) return false; + const content = await load(); + if (!canLoad()) { + retain(); + return false; + } + if (content) apply(content); + else retain(); + return Boolean(content); +} diff --git a/核桃派软件源代码/app/static/scene-board.js b/核桃派软件源代码/app/static/scene-board.js index 89bc57e..afabfbb 100644 --- a/核桃派软件源代码/app/static/scene-board.js +++ b/核桃派软件源代码/app/static/scene-board.js @@ -1,5 +1,6 @@ import { attachScene, createLayer, cloneLayer, cloneScene, composeScene, clipTextPixels, translatedOverflow, clipBrushPixels, textClipAt, normalizeTextElement, layerToStorage } from "./scene-model.js"; -import { announce, apiBlob, isAppStale } from "./core.js"; +import { announce, apiBlob, apiJson, isAppStale } from "./core.js"; +import { readBoardSession, writeBoardSession, loadDefaultBoard, initializeDefaultBoard } from "./board-startup-model.js"; import { renderUiCopy, renderUiValue } from "./ui-copy-runtime.js"; import { RGB_BYTE_LENGTH, @@ -102,10 +103,61 @@ let lastExactRgb = null; let sceneSource = null; let draftConflict = false; let externalDraftValue = null; +let externalDraftContext = null; let draftPersistenceBlocked = !draftLoad.canPersist; let draftProtectionNotice = ( draftPersistenceBlocked || draftLoad.status === "cleanup-warning" ) ? draftLoad.notice : ""; +const deviceBootId = document.querySelector('meta[name="device-boot-id"]')?.content || ""; +let boardBootId = ""; +let boardMutation = 0; +let startupBoardPromise = null; +if (draftLoad.canPersist && deviceBootId) { + try { + const session = readBoardSession(draftStorage, serializeScene(scene), deviceBootId); + boardBootId = session.bootId || ""; + templateEdit = session.context; + if (templateEdit && !deserializeScene(templateEdit.baseline)) throw new Error("画板保存基线无效;原草稿已保留。"); + if (templateEdit && !sceneNeedsTemplateSave(templateEdit, serializeScene(scene)) && templateEdit.type === "template") { + sceneSource = { type: "template", id: templateEdit.id, revision: templateEdit.revision }; + } + } catch (error) { + templateEdit = null; + draftPersistenceBlocked = true; + draftProtectionNotice = error.message; + } +} + +export function initializeStartupBoard() { + if (startupBoardPromise) return startupBoardPromise; + const mutation = boardMutation; + const canLoad = () => Boolean(deviceBootId) && boardBootId !== deviceBootId + && !draftPersistenceBlocked && !draftConflict && !animationEdit && boardMutation === mutation; + const retain = () => { + if (draftPersistenceBlocked || draftConflict || animationEdit) return; + boardBootId = deviceBootId; + persistScene(); + }; + startupBoardPromise = initializeDefaultBoard({ + canLoad, + load: () => loadDefaultBoard(apiJson), + apply: (content) => { + // Validate before changing either the session marker or the current draft. + if (!deserializeScene(content.scene)) throw new Error("默认画面场景无效"); + boardBootId = deviceBootId; + replaceSceneFromStorage(content.scene, { + reason: "startup-default-load", + source: content.type === "template" ? { type: "template", id: content.id, revision: content.revision } : null, + templateEditContext: content, + }); + }, + retain, + }).catch((error) => { + announce(`默认画面读取失败,已保留当前草稿:${error.message}`, true); + return false; + }); + return startupBoardPromise; +} const draftConflictNotice = document.getElementById("draft-conflict-notice"); const loadExternalDraftButton = document.getElementById("load-external-draft"); @@ -122,6 +174,7 @@ function blockDraftPersistence(message) { } export function persistScene() { + boardMutation += 1; if (animationEdit) { animationEdit.dirty = serializeScene(scene) !== animationEdit.baseline; updateBoardUi(); @@ -131,7 +184,10 @@ export function persistScene() { if (draftConflict || draftPersistenceBlocked) return false; try { if (!draftStorage) throw new Error("browser storage unavailable"); - draftStorage.setItem(SCENE_STORAGE_KEY, serializeScene(scene)); + const draft = serializeScene(scene); + // Commit metadata first: a torn pair never restores the wrong binding. + writeBoardSession(draftStorage, boardBootId, draft, templateEdit); + draftStorage.setItem(SCENE_STORAGE_KEY, draft); return true; } catch (_error) { blockDraftPersistence("浏览器无法保存统一画板草稿;原草稿已保留,本页不会继续覆盖或应用它。"); @@ -157,6 +213,12 @@ window.addEventListener("storage", (event) => { return; } if (external.status !== "valid") return; + try { + externalDraftContext = readBoardSession(draftStorage, event.newValue, deviceBootId).context; + } catch (error) { + blockDraftPersistence(error.message); + return; + } externalDraftValue = event.newValue; setDraftConflict(true); announce("另一标签页修改了画板草稿,请选择要保留的版本", true); @@ -164,11 +226,12 @@ window.addEventListener("storage", (event) => { loadExternalDraftButton.addEventListener("click", async () => { const value = externalDraftValue; + const context = externalDraftContext; if (!value) return; if (animationEdit && !await sceneReplacementGuard()) return; externalDraftValue = null; setDraftConflict(false); - replaceSceneFromStorage(value, { persist: false, reason: "tab-sync" }); + replaceSceneFromStorage(value, { persist: false, reason: "tab-sync", templateEditContext: context }); announce("已载入另一标签页的最新画板草稿"); }); @@ -670,6 +733,7 @@ export function replaceSceneFromStorage( templateEditContext = null, } = {}, ) { + boardMutation += 1; const restored = deserializeScene(value); if (!restored) throw new Error("模板场景无效,无法载入"); textLayers.forEach((entry) => { @@ -719,6 +783,8 @@ export function markTemplateSaved(template) { clearEditHistory(); templateEdit = createTemplateEditContext(template, serializeScene(scene)); sceneSource = { type: "template", id: template.id, revision: template.revision }; + boardBootId = deviceBootId; + persistScene(); updateBoardUi(); document.dispatchEvent(new CustomEvent("matrix:template-edit-change", { detail: templateEditState() })); return true; diff --git a/核桃派软件源代码/app/static/style.css b/核桃派软件源代码/app/static/style.css index 9b3c16c..79005b8 100644 --- a/核桃派软件源代码/app/static/style.css +++ b/核桃派软件源代码/app/static/style.css @@ -1663,7 +1663,8 @@ dd { font-size: 0.8rem; } -.template-card-actions .demo-restricted-action[aria-disabled="true"] { +.template-card-actions .demo-restricted-action[aria-disabled="true"], +.template-save-choice-actions .demo-restricted-action[aria-disabled="true"] { border-color: #000; background: #050505; color: #9aa1ab; diff --git a/核桃派软件源代码/app/static/template-edit-model.js b/核桃派软件源代码/app/static/template-edit-model.js index e005f8d..1a90c2f 100644 --- a/核桃派软件源代码/app/static/template-edit-model.js +++ b/核桃派软件源代码/app/static/template-edit-model.js @@ -1,9 +1,10 @@ export function createTemplateEditContext(template, baseline) { return { + type: template.type || "template", id: template.id, name: template.name, revision: template.revision, - readOnly: Boolean(template.read_only ?? template.readOnly), + readOnly: template.type === "animation" || Boolean(template.read_only ?? template.readOnly), baseline, }; } @@ -11,6 +12,7 @@ export function createTemplateEditContext(template, baseline) { export function templateEditSnapshot(context, serializedScene) { if (!context) return null; return { + type: context.type || "template", id: context.id, name: context.name, revision: context.revision, diff --git a/核桃派软件源代码/app/static/views/templates.js b/核桃派软件源代码/app/static/views/templates.js index 9fa8b7c..93c9e34 100644 --- a/核桃派软件源代码/app/static/views/templates.js +++ b/核桃派软件源代码/app/static/views/templates.js @@ -558,6 +558,10 @@ async function saveSceneAsNew({ initial = "", note = "", bind = true } = {}) { } async function saveSceneToCurrentTemplate(context) { + if (context.readOnly || context.type !== "template") { + announce("演示案例不得覆盖,请另存为新模板", true); + return; + } await mutate(async () => { const result = await apiJson(`/api/templates/${context.id}`, { method: "PUT", diff --git a/核桃派软件源代码/tests/test_api.py b/核桃派软件源代码/tests/test_api.py index b4e464e..76e816c 100644 --- a/核桃派软件源代码/tests/test_api.py +++ b/核桃派软件源代码/tests/test_api.py @@ -23,6 +23,16 @@ def solid_scene(color=(12, 34, 56)): } +def test_homepage_exposes_escaped_boot_session_without_changing_rest_contract(tmp_path): + boot_id = 'boot-"&' + with TestClient(create_app(project_root=tmp_path, driver_kind="mock", startup_boot_id=boot_id)) as client: + response = client.get("/") + assert response.status_code == 200 + assert '' in response.text + assert response.headers["cache-control"] == "no-store" + assert 'name="device-boot-id"' not in client.get("/api/status").text + + def test_status_config_and_display_api(tmp_path): client = TestClient(create_app(project_root=tmp_path, driver_kind="mock")) diff --git a/核桃派软件源代码/tests/test_template_management_ui.mjs b/核桃派软件源代码/tests/test_template_management_ui.mjs index 80ae4b5..b9098ba 100644 --- a/核桃派软件源代码/tests/test_template_management_ui.mjs +++ b/核桃派软件源代码/tests/test_template_management_ui.mjs @@ -1,6 +1,7 @@ import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import test from "node:test"; +import { BOARD_SESSION_KEY, readBoardSession, writeBoardSession, loadDefaultBoard, initializeDefaultBoard } from "../app/static/board-startup-model.js"; import { createTemplateEditContext, @@ -22,6 +23,7 @@ test("template edit baseline distinguishes clean, dirty, and unbound scenes", () assert.equal(sceneNeedsTemplateSave(context, "scene-a"), false); assert.equal(sceneNeedsTemplateSave(context, "scene-b"), true); assert.deepEqual(templateEditSnapshot(context, "scene-a"), { + type: "template", id: "template-1", name: "测试模板", revision: "revision-1", @@ -31,6 +33,71 @@ test("template edit baseline distinguishes clean, dirty, and unbound scenes", () assert.equal(templateEditSnapshot(context, "scene-b").dirty, true); }); +test("same boot restores binding and original dirty baseline; new boot or mismatched draft does not", () => { + const values = new Map(); + const storage = { getItem: (key) => values.get(key), setItem: (key, value) => values.set(key, value) }; + const context = createTemplateEditContext({ id: "saved", name: "默认画面", revision: "original" }, "clean-scene"); + writeBoardSession(storage, "boot-a", "dirty-scene", context); + const restored = readBoardSession(storage, "dirty-scene", "boot-a"); + assert.deepEqual(restored.context, context); + assert.equal(templateEditSnapshot(restored.context, "dirty-scene").dirty, true); + assert.equal(restored.context.revision, "original"); + assert.equal(readBoardSession(storage, "dirty-scene", "boot-b").context, null); + assert.equal(readBoardSession(storage, "another-scene", "boot-a").context, null); + assert.equal(readBoardSession(storage, "another-scene", "boot-a").bootId, "boot-a"); + values.set(BOARD_SESSION_KEY, '{"version":99}'); + assert.throws(() => readBoardSession(storage, "dirty-scene", "boot-a"), /原值已保留/); + assert.equal(values.get(BOARD_SESSION_KEY), '{"version":99}'); +}); + +test("default static loads its complete latest scene and both demos keep read-only ownership", async () => { + const staticDetail = { id: "static", name: "默认静态", revision: "r2", scene: "complete-scene" }; + const calls = []; + const normal = await loadDefaultBoard(async (url) => { + calls.push(url); + return url.endsWith("default-content") ? { type: "template", id: "static" } : staticDetail; + }); + assert.deepEqual(normal, { ...staticDetail, type: "template" }); + assert.deepEqual(calls, ["/api/display/default-content", "/api/templates/static"]); + const staticDemo = createTemplateEditContext({ ...normal, read_only: true }, "baseline"); + assert.equal(staticDemo.readOnly, true); + const demo = await loadDefaultBoard(async (url) => { + if (url.endsWith("default-content")) return { type: "animation", id: "demo", is_demo: true }; + if (url.endsWith("/frames")) return { id: "demo", name: "演示动图", revision: "r1", frames: [{ id: "first" }, { id: "second" }] }; + assert.equal(url, "/api/animations/demo/frames/first"); + return { scene: "first-scene" }; + }); + assert.equal(demo.scene, "first-scene"); + const context = createTemplateEditContext(demo, demo.scene); + assert.equal(context.type, "animation"); + assert.equal(context.readOnly, true); + assert.equal(context.id, "demo"); + assert.equal(await loadDefaultBoard(async () => ({ type: "animation", is_demo: false })), null); +}); + +test("startup skips protected drafts and never replaces intervening edits or failed reads", async () => { + let allowed = false, applied = 0, retained = 0, loaded = 0; + const options = { + canLoad: () => allowed, + load: async () => { loaded++; return { scene: "default" }; }, + apply: () => applied++, retain: () => retained++, + }; + assert.equal(await initializeDefaultBoard(options), false); + assert.equal(loaded, 0); + allowed = true; + assert.equal(await initializeDefaultBoard(options), true); + assert.equal(applied, 1); + options.load = async () => { allowed = false; return { scene: "late-default" }; }; + assert.equal(await initializeDefaultBoard(options), false); + assert.equal(applied, 1); + assert.equal(retained, 1); + allowed = true; + options.load = async () => { throw Error("deleted or unavailable"); }; + await assert.rejects(initializeDefaultBoard(options), /deleted or unavailable/); + assert.equal(applied, 1); + assert.equal(retained, 1); +}); + test("template manager uses a monitor and unified four-row card actions", async () => { const [html, board, templates, style] = await Promise.all([ readFile(new URL("index.html", staticRoot), "utf8"), @@ -54,6 +121,7 @@ test("template manager uses a monitor and unified four-row card actions", async assert.match(html, /id="template-save-choice-dialog"/); assert.match(html, /value="current">保存到当前模板/); assert.match(html, /value="new">另存为新模板/); + assert.match(style, /\.template-save-choice-actions \.demo-restricted-action\[aria-disabled="true"\][\s\S]*background: #050505/); }); test("animation editing backs up and restores template edit ownership", async () => { diff --git a/测试相关资料/如何测试/本机测试环境/README.md b/测试相关资料/如何测试/本机测试环境/README.md index 1e6ee70..26f40c7 100644 --- a/测试相关资料/如何测试/本机测试环境/README.md +++ b/测试相关资料/如何测试/本机测试环境/README.md @@ -99,6 +99,10 @@ python -X utf8 "测试相关资料/如何测试/本机测试环境/local_env.py" ### 复制项目与持续维护 +隔离副本执行 `test --suite all` 时,除源码和测试入口外,还须复制该套件校验的内核离线依赖、内核源码归档及依赖登记表;不能只带 Python wheel 和 FRP 后把缺少材料算成软件回归。普通开发不需要复制或重建历史 IMG。只含应用的板端更新载荷沿用 `MATRIX_SOURCE_ONLY_UPDATE_TESTS=1` 的既有选测边界,其跳过项不能写成完整工作区依赖验收通过。 + +Windows 原子替换遇到 `PermissionError / WinError 5` 时保留失败调用和软件错误响应,核对文件是否被占用,再在独立测试目录定向重测。单次重测通过只能说明未复现,不足以认定杀毒软件、路径长度或其他根因;不要据此放宽生产写入保护。 + Git 克隆后按上述命令重新搭建。复制整个工作区时,旧 venv 含绝对位置和旧 Python 绑定,不能当作可移植程序:先保留并改名旧 `.local/ssh/venv`、`.local/image-editor/venv`,再 setup;wheel 和数据可继续复用。Android 在新机器重新配置工具路径并 setup,刷新本工具管理的 AVD 路径。源码入口、锁文件、搭建文档与包登记必须随测试修订一起维护。 每轮相关测试先查已有排障记录;已验证解法更新本 README 或移动端排障,依赖更新同时维护原始 requirements、完整锁文件和 wheel 哈希。临时修补不能长期只存在 `.local/work/`:通用化且脱敏后加入可复用源码,或把复建步骤写进文档。单次日志保留在 `.local/work/`;需要归档的结果先脱敏再写入 `各种归档/`。 diff --git a/测试相关资料/如何测试/核桃派点阵屏控制服务测试流程.md b/测试相关资料/如何测试/核桃派点阵屏控制服务测试流程.md index 250d369..a295fbc 100644 --- a/测试相关资料/如何测试/核桃派点阵屏控制服务测试流程.md +++ b/测试相关资料/如何测试/核桃派点阵屏控制服务测试流程.md @@ -73,6 +73,15 @@ NetworkManager DNS 往返:`tests/test_wifi.py::test_nmcli_multiple_dns_can_rou ## 1. 本机 mock 与自动化 +### 默认画面保存绑定(TEST-TEMPLATE-MANAGEMENT / TEST-DEFAULT-CONTENT) + +- 覆盖 `WEB-DEFAULT-DISPLAY`、`WEB-TEMPLATES`:新设备开机会话载入默认静态模板并绑定 ID、修订及基线;覆盖保留 ID、名称、创建时间和默认引用,另存绑定新模板,取消不发写请求。同次开机刷新保留未保存草稿及原修订;新开机会话载入最新默认模板。服务 restart 不作为设备重新开机。 +- 演示静态图和演示动图第一帧均显示保存弹窗;“保存到当前模板”须为黑色受限态,点击只解释原因且不关闭弹窗、不发覆盖请求;另存生成可写静态模板。演示动图绑定类型仍是只读 animation。用户动图保持原逐帧编辑、保存和普通草稿恢复流程。 +- 定向反例:过期修订返回 `409`、删除目标返回 `404`、默认读取失败、损坏/未来版本草稿、初始化响应期间新增图层;都保留当前草稿,不误绑定或自动重写。多标签选择载入外部草稿时仅恢复与该草稿精确匹配的绑定。 +- Node 行为用例在 `tests/test_template_management_ui.mjs`,首页开机会话标记及 HTML 属性转义在 `tests/test_api.py`。浏览器验证覆盖桌面与手机弹窗、真实保存请求及刷新,不以代码文本匹配替代交互验收。 +- 已验证经验:场景持久化不等于模板来源持久化;绑定须单独保存原修订与基线,并核对草稿对应关系。仅设置 `aria-disabled` 不会把主按钮变黑,保存弹窗也须应用演示受限样式。另存弹窗关闭后请求仍可能在途,自动化必须等待写请求成功及绑定更新后再刷新。DELETE 同样要求 `If-Match`,不能把缺少请求头的 `428` 当成删除成功。 +- 本项不改驱动、扫描或输出实现,实屏视觉验收不适用;板端验收检查服务、静态资源和临时模板保存,不改写用户原件,不启动摄像头或切换测试图案。 + 从独立项目根执行: ```powershell diff --git a/移动端相关内容/开发要求/跨端兼容与变更记录.md b/移动端相关内容/开发要求/跨端兼容与变更记录.md index 65f2871..16163a2 100644 --- a/移动端相关内容/开发要求/跨端兼容与变更记录.md +++ b/移动端相关内容/开发要求/跨端兼容与变更记录.md @@ -26,6 +26,8 @@ ## 后续登记模板 +2026-10-10,WEB-DEFAULT-DISPLAY / WEB-TEMPLATES:设备网页补齐开机默认静态模板及只读演示案例的保存绑定,浏览器单独保留来源、修订与基线;首页增加不含身份凭据的设备开机会话 meta 标记。REST、BLE、scene v2、设备配置、驱动和固定部署路径不变,用户动图仍按原流程逐帧保存。无需修改或发布 App;本轮按网页、模板 API、隔离构建和原子部署影响选测,Android 回归及实屏视觉验收不适用。 + 2026-09-27,DEPLOY-OTA-OFFLINE-CLOSURE/DEPLOY-OTA-CANDIDATE:设备端移除误加入的电脑测试专用 Paramiko 依赖,改为检查 OTA 离线依赖闭包并按实机验证的原字节候选发布 1.1.3。REST、BLE、驱动及移动端协议均不变;无需 App 更新或重新签名。实机试装和恢复结果以本轮验收记录为准。 2026-09-26,WEB-PERFORMANCE-MODE/DEPLOY-OTA-KERNEL-RECOVERY:设备 REST 的 `/api/ota/status` 增加可选 `kernel_recovery` 状态,`/api/status.system.performance_mode.last_error` 对缺失 cpufreq 给出具体原因;已有字段和 BLE 协议不变。旧 App 忽略新增 REST 字段,无需 App 更新。本轮仅改设备端;本机和实机验证结果以本次交付记录为准。