From 5fe6608ae186af4af1e9e8bdcdfceebc15c37f94 Mon Sep 17 00:00:00 2001 From: HHY Date: Fri, 25 Sep 2026 03:38:18 -0700 Subject: [PATCH] =?UTF-8?q?feat:=20P0-7=20=E7=8E=BB=E7=92=83=E8=A3=85?= =?UTF-8?q?=E9=A5=B0=E6=A0=BC=E6=9D=A1=E8=AE=BE=E8=AE=A1=E5=99=A8(8?= =?UTF-8?q?=E9=A3=8E=E6=A0=BC/2D+3D=E6=B8=B2=E6=9F=93/=E7=AE=97=E6=96=99?= =?UTF-8?q?=E8=AE=A1=E4=BB=B7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG | 2 + doc/API.md | 10 + frontend/scripts/.drawing-bundle.mjs | 311 +++++++++++++++++++++ frontend/scripts/verify-decbar.mjs | 59 ++++ frontend/src/components/WindoorCanvas.vue | 136 ++++++++- frontend/src/components/WindoorThreed.vue | 28 +- frontend/src/types/.drawing-bundle.mjs | 311 +++++++++++++++++++++ frontend/src/types/drawing.ts | 23 ++ shots/verify-decbar-2d.png | Bin 0 -> 100021 bytes src/huamenchuang/services/quote_service.py | 16 +- 10 files changed, 888 insertions(+), 8 deletions(-) create mode 100644 frontend/scripts/.drawing-bundle.mjs create mode 100644 frontend/scripts/verify-decbar.mjs create mode 100644 frontend/src/types/.drawing-bundle.mjs create mode 100644 shots/verify-decbar-2d.png diff --git a/CHANGELOG b/CHANGELOG index a52dde4..dcd8b0f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ # CHANGELOG +- [2026-09-25 15:40] FEAT: v2.26 P0-7 玻璃装饰格条设计器。①types/drawing.ts 加 DecBar(decs 挂 FrameShape, ri=重放区域索引)+DEC_PRESETS 8 风格(对齐源站 decorationBar: 现代轻奢/意式简约/奶油风/中式/欧式古典/法式/地中海/田园密格); ②WindoorCanvas: 选格后 HUD"格条"按钮+设计对话框(预设缩略图/行列/条宽/6 色)+2D 渲染(区域 clip 内横竖条+描边, 应用/清除入撤销栈); ③WindoorThreed: 静态格+扇面板玻璃前表面格条体(barX/barY 实心腔); ④后端 takeoff 计 dec_bar 算料(横=区域宽×rows/竖=区域高×cols, 默认 12 元/米); ⑤端到端验证: 无头浏览器订单详情→编辑→选格→欧式古典 3×3 应用→截图渲染正确(shots/verify-decbar-2d.png); 254 套全量校验 0 失败(decs 可选字段无回归); vue-tsc 0 错+构建通过 (Files: frontend/src/types/drawing.ts, frontend/src/components/WindoorCanvas.vue, frontend/src/components/WindoorThreed.vue, src/huamenchuang/services/quote_service.py, frontend/scripts/verify-decbar.mjs, doc/API.md) + - [2026-09-25 14:50] FEAT: v2.25 P0-6 Excel 导入导出全套。①excel_service 扩展: read_rows 自动探测表头行(兼容首行标题合并格, 修复导入全跳过)/pick 中文列名取值/simple_table_workbook/statistics_workbook 双Sheet; ②客户: excel-template 模板/excel-in 批量导入(缺姓名行级报错)/excel-out 导出; ③合同 excel-out(含已收); ④库存 excel-out/excel-in(同名更新数量累加); ⑤reports/excel-statistics(订单汇总+收款统计); ⑥依赖补 python-multipart(UploadFile 必需, 缺失曾致后端启动失败); ⑦前端 apiUpload+四个页面导入导出按钮; 实测: 模板回传导入成功1条/库存导出→再导入更新1条; vue-tsc 0 错+构建通过 (Files: pyproject.toml, src/huamenchuang/services/excel_service.py, src/huamenchuang/api/customers.py, src/huamenchuang/api/contracts.py, src/huamenchuang/api/warehouse.py, src/huamenchuang/api/reports.py, frontend/src/api/index.ts, frontend/src/views/CustomersView.vue, frontend/src/views/WarehouseView.vue, frontend/src/views/ContractsView.vue, frontend/src/views/ReportView.vue, doc/API.md) - [2026-09-25 13:50] FEAT: v2.24 P0-5 收款财务闭环。①ContractReceipt 模型(SK+日期+流水/方式五类/作废状态)+finance.py(账户 CRUD/登记收款/作废/流水分页/年度统计); ②GET /receipts/statistics(收款总额/合同应收/未收/12 月分布, 对齐 statistics_tb); ③合同列表注入 received/unreceived(当页一次 GROUP BY 聚合); ④新页面 /financial 财务管理(统计卡+月度柱图+流水+登记+账户管理)+路由菜单; 合同页加已收/未收列+收款按钮对话框; 修复 v-for 索引 m+1 类型; vue-tsc 0 错+构建通过; API 实测登记 3000→统计/列表联动正确 (Files: src/huamenchuang/models/business.py, src/huamenchuang/api/finance.py, src/huamenchuang/api/contracts.py, src/huamenchuang/api/router.py, frontend/src/views/FinancialView.vue, frontend/src/views/ContractsView.vue, frontend/src/views/LayoutView.vue, frontend/src/router/index.ts, doc/API.md) diff --git a/doc/API.md b/doc/API.md index 2583d6f..2f3d97b 100644 --- a/doc/API.md +++ b/doc/API.md @@ -445,3 +445,13 @@ uv run uvicorn huamenchuang.main:app --reload # 启动,http://localhost:8000 | **库存批量导入** | POST | `/api/warehouse/excel-in` | multipart `file` | 对齐 materials_config_excel:同名材料更新(数量累加),否则新增 | | 库存导出 | GET | `/api/warehouse/excel-out` | — | 对齐 warehouse_excel_out | | 统计报表导出 | GET | `/api/reports/excel-statistics` | — | 对齐 excel-statistics:订单汇总+收款统计双 Sheet | + +### 12.21 装饰格条(v2.20 新增,P0-格条设计器) + +对齐目标站 `/draw-decoration` + `decorationBarLibrary`(8 种装修风格)。**自研数据扩展**:`drawing_data.sm[i].decs[] = [{ri(重放区域索引), kind(风格), rows, cols, bw(条宽mm), color}]`,序列化向后兼容(254 套样板校验 0 回归)。 + +- **2D**:画布编辑态点选玻璃格 → HUD"格条"按钮 → 对话框(8 风格预设+行列/条宽/颜色)→ 应用/清除 +- **3D**:玻璃前表面按行列挤出格条体(静态格与扇面板均支持) +- **报价**:`offer-price`/BOM 自动计入格条算料(横条=区域宽×rows、竖条=区域高×cols,默认 12 元/米,`prices.dec_bar` 可覆盖,kind=`dec_bar`) + +风格预设:现代轻奢(1×1黑25)/意式简约(1×1灰18)/奶油风(2×2白22)/中式(2×2棕28)/欧式古典(3×3金20)/法式(2×2金16)/地中海(2×3蓝24)/田园密格(4×4白14)。 diff --git a/frontend/scripts/.drawing-bundle.mjs b/frontend/scripts/.drawing-bundle.mjs new file mode 100644 index 0000000..78fbd28 --- /dev/null +++ b/frontend/scripts/.drawing-bundle.mjs @@ -0,0 +1,311 @@ +// src/types/drawing.ts +var DEC_PRESETS = [ + { kind: "modern", label: "\u73B0\u4EE3\u8F7B\u5962", rows: 1, cols: 1, bw: 25, color: "#2b2b2b" }, + { kind: "italian", label: "\u610F\u5F0F\u7B80\u7EA6", rows: 1, cols: 1, bw: 18, color: "#9aa0a6" }, + { kind: "cream", label: "\u5976\u6CB9\u98CE", rows: 2, cols: 2, bw: 22, color: "#f3ece2" }, + { kind: "chinese", label: "\u4E2D\u5F0F", rows: 2, cols: 2, bw: 28, color: "#6b4a2b" }, + { kind: "european", label: "\u6B27\u5F0F\u53E4\u5178", rows: 3, cols: 3, bw: 20, color: "#c9a86a" }, + { kind: "french", label: "\u6CD5\u5F0F", rows: 2, cols: 2, bw: 16, color: "#d8c9a3" }, + { kind: "medit", label: "\u5730\u4E2D\u6D77", rows: 2, cols: 3, bw: 24, color: "#3a6ea5" }, + { kind: "pastoral", label: "\u7530\u56ED\u5BC6\u683C", rows: 4, cols: 4, bw: 14, color: "#ffffff" } +]; +function parseDrawing(raw) { + const dd = typeof raw === "string" ? JSON.parse(raw) : raw; + return dd; +} +function regionPoints(region) { + return region.map((seg) => ({ x: seg.ps.x, y: seg.ps.y })); +} +function bboxOf(points) { + const xs = points.map((p) => p.x); + const ys = points.map((p) => p.y); + return { x0: Math.min(...xs), y0: Math.min(...ys), x1: Math.max(...xs), y1: Math.max(...ys) }; +} +function spAxis(sp) { + const n = sp.line?.norm ?? { x: 1, y: 0 }; + return Math.abs(n.x) >= Math.abs(n.y) ? "v" : "h"; +} +function spPos(sp) { + return spAxis(sp) === "v" ? sp.line.pt.x : sp.line.pt.y; +} +function pointInRegion(p, region) { + let inside = false; + const pts = regionPoints(region); + for (let i = 0, j = pts.length - 1; i < pts.length; j = i++) { + const xi = pts[i].x, yi = pts[i].y, xj = pts[j].x, yj = pts[j].y; + if (yi > p.y !== yj > p.y && p.x < (xj - xi) * (p.y - yi) / (yj - yi) + xi) inside = !inside; + } + return inside; +} +function dfsLeaves(node, out) { + if (node.kids.length === 0) { + out.push(node); + return; + } + node.kids.forEach((k) => dfsLeaves(k, out)); +} +function replayShape(shape) { + const base = (shape.polygon?.polygon ?? []).map((r) => r.filter((s) => s && typeof s === "object" && s.ps && s.pe && Number.isFinite(s.ps.x) && Number.isFinite(s.ps.y) && Number.isFinite(s.pe.x) && Number.isFinite(s.pe.y)).map((s) => ({ ps: { ...s.ps }, pe: { ...s.pe } }))).filter((r) => r.length >= 3); + const root = { segs: base[0] ?? [], kids: [] }; + const extraRoots = base.slice(1).map((segs) => ({ segs, kids: [] })); + const idMap = /* @__PURE__ */ new Map(); + const clips = []; + const allLeaves = () => { + const out = []; + dfsLeaves(root, out); + extraRoots.forEach((r) => dfsLeaves(r, out)); + return out; + }; + let spIdx = 0; + for (const sp of shape.mm?.sp ?? []) { + const myId = spIdx; + spIdx++; + if (!sp?.line?.pt || !sp.line.norm) continue; + const axis = spAxis(sp); + const pos = spPos(sp); + let target = null; + const nid = sp.polyId?.idx; + const cpos = sp.polyId?.pos; + if (Number.isInteger(nid) && nid >= 0) { + const node = nid === 0 ? root : idMap.get(nid); + if (node) { + if (node.kids.length === 0) target = node; + else if (Number.isInteger(cpos) && cpos >= 0 && cpos < node.kids.length) { + target = node.kids[cpos]; + } + } + } + if (!target) target = allLeaves().find((nd) => pointInRegion(sp.line.pt, nd.segs)) ?? null; + if (!target || target.segs.length < 3) continue; + const bb = bboxOf(regionPoints(target.segs)); + const lo = axis === "v" ? bb.x0 : bb.y0; + const hi = axis === "v" ? bb.x1 : bb.y1; + if (pos <= lo + 0.5 || pos >= hi - 0.5) { + clips.push({ sp, bb }); + idMap.set(myId, target); + continue; + } + const split = splitPolySegments(target.segs, axis, pos); + if (!split) { + clips.push({ sp, bb }); + idMap.set(myId, target); + continue; + } + const nrm = sp.line.norm; + const sideOf = (segs) => { + for (const s of segs) { + for (const p of [s.ps, s.pe]) { + const d = (p.x - sp.line.pt.x) * nrm.x + (p.y - sp.line.pt.y) * nrm.y; + if (Math.abs(d) > 1e-6) return d > 0; + } + } + return true; + }; + const c0 = sideOf(split.a) ? split.a : split.b; + target.kids = [{ segs: c0, kids: [] }, { segs: sideOf(split.a) ? split.b : split.a, kids: [] }]; + target.segs = []; + idMap.set(myId, target); + clips.push({ sp, bb }); + } + const leaves = allLeaves(); + const regions = leaves.map((l) => l.segs).filter((s) => s.length >= 3); + const nodeId = /* @__PURE__ */ new Map([[root, 0]]); + const leafRefs = []; + const walk = (node, id) => { + node.kids.forEach((k, i) => { + if (k.kids.length === 0) leafRefs.push({ idx: id, pos: i }); + else { + const kidId = nodeId.get(k); + if (kidId != null) walk(k, kidId); + } + }); + }; + if (root.kids.length === 0 && root.segs.length >= 3) leafRefs.push({ idx: 0, pos: 0 }); + else walk(root, 0); + extraRoots.forEach((r, i) => { + const eid = base.length + spIdx + i; + idMap.set(eid, r); + if (r.kids.length === 0) leafRefs.push({ idx: eid, pos: 0 }); + else walk(r, eid); + }); + const resolveRef = (idx, pos) => { + const node = idx === 0 ? root : idMap.get(idx); + if (!node) return null; + if (node.kids.length === 0) return node.segs; + if (Number.isInteger(pos) && pos >= 0 && pos < node.kids.length) { + const k = node.kids[pos]; + if (k.kids.length === 0) return k.segs; + const l = []; + dfsLeaves(k, l); + return l[0]?.segs ?? null; + } + return null; + }; + return { regions, clips, leafRefs, resolveRef }; +} +function splitPolySegments(region, axis, pos) { + const pts = regionPoints(region); + const n = pts.length; + const get = (p) => axis === "v" ? p.x : p.y; + const crossings = []; + for (let i = 0; i < n; i++) { + const a = pts[i], b = pts[(i + 1) % n]; + const da = get(a) - pos, db = get(b) - pos; + if (da < 0 && db > 0 || da > 0 && db < 0) { + const t = da / (da - db); + crossings.push({ + i, + p: axis === "v" ? { x: pos, y: a.y + (b.y - a.y) * t } : { x: a.x + (b.x - a.x) * t, y: pos } + }); + } + } + if (crossings.length !== 2) return null; + const [c1, c2] = crossings; + if (c1.i === c2.i) return null; + const collect = (from, to) => { + const ps = [from.p]; + for (let k = (from.i + 1) % n; ; k = (k + 1) % n) { + ps.push(pts[k]); + if (k === to.i) break; + } + ps.push(to.p); + return ps.filter((p, i) => i === 0 || Math.abs(p.x - ps[i - 1].x) > 0.01 || Math.abs(p.y - ps[i - 1].y) > 0.01); + }; + const toSegs = (ps) => { + const segs = []; + for (let i = 0; i < ps.length; i++) segs.push({ ps: ps[i], pe: ps[(i + 1) % ps.length], name: "segment" }); + return segs; + }; + const polyA = collect(c1, c2); + const polyB = collect(c2, c1); + if (polyA.length < 3 || polyB.length < 3) return null; + return { a: toSegs(polyA), b: toSegs(polyB) }; +} +function hmOf(sub) { + const hm = sub.hm; + return hm ?? {}; +} +function inferSashGlyphs(shape, replayed) { + let rr = null; + let regions; + if (replayed && !Array.isArray(replayed)) { + rr = replayed; + regions = rr.regions; + } else if (replayed) { + regions = replayed; + } else { + rr = replayShape(shape); + regions = rr.regions; + } + const regionBBs = regions.map((r) => bboxOf(regionPoints(r))); + const glyphs = []; + const bdRect = (bd) => { + if (!bd.from || !bd.to) return null; + const r = { + x0: Math.min(bd.from.x, bd.to.x), + y0: Math.min(bd.from.y, bd.to.y), + x1: Math.max(bd.from.x, bd.to.x), + y1: Math.max(bd.from.y, bd.to.y) + }; + const ok = [r.x0, r.y0, r.x1, r.y1].every((v) => Number.isFinite(v)); + return ok && !bd.hidden && r.x1 - r.x0 > 10 && r.y1 - r.y0 > 10 ? r : null; + }; + const kindOf = (sub) => String(sub.type) === "Slide" ? "sliding" : "casement"; + const rectOfRef = (ref) => { + if (!ref || !Number.isInteger(ref.idx) || ref.idx < 0) return null; + if (rr) { + const segs = rr.resolveRef(ref.idx, ref.pos); + if (segs && segs.length >= 3) return bboxOf(regionPoints(segs)); + } + const i = ref.idx; + return i < regionBBs.length ? regionBBs[i] : null; + }; + const iouR = (a, b) => { + const w = Math.min(a.x1, b.x1) - Math.max(a.x0, b.x0); + const h = Math.min(a.y1, b.y1) - Math.max(a.y0, b.y0); + if (w <= 0 || h <= 0) return 0; + const inter = w * h; + return inter / ((a.x1 - a.x0) * (a.y1 - a.y0) + (b.x1 - b.x0) * (b.y1 - b.y0) - inter); + }; + const pushGlyphs = (r, entries, sub, forceRect = false) => { + const kind = kindOf(sub); + const hm = hmOf(sub); + for (const e of entries) { + const rect = !forceRect ? rectOfRef(e.polyId) ?? r : r; + if (glyphs.some((g) => iouR(rect, g) > 0.15)) continue; + glyphs.push({ + x0: rect.x0, + y0: rect.y0, + x1: rect.x1, + y1: rect.y1, + od: e.od ?? sub.od ?? 90, + openToward: e.openToward ?? sub.openToward ?? hm.openToward, + openDirection: e.openDirection ?? hm.openDirection, + isDoor: Boolean(e.isDoor || sub.isDoor), + wtf: Boolean(e.wtf ?? sub.wtf ?? sub.withTurningFrame), + kind + }); + } + }; + const unmatched = []; + for (const sub of shape.sm ?? []) { + const type = String(sub.type ?? ""); + if (type === "Screen" || type === "DoubleScreen") continue; + const raw = sub.sashes?.length ? sub.sashes : [sub]; + const entries = raw.filter((e) => e && e.enabled !== false); + if (!entries.length) continue; + const n = Math.max(entries.length, type.startsWith("Double") ? 2 : 1); + let rect = sub.bd ? bdRect(sub.bd) : null; + if (!rect) rect = rectOfRef(sub.polyId); + if (rect) { + for (let k = 0; k < n; k++) { + const part = n > 1 ? { x0: rect.x0 + (rect.x1 - rect.x0) * k / n, y0: rect.y0, x1: rect.x0 + (rect.x1 - rect.x0) * (k + 1) / n, y1: rect.y1 } : rect; + pushGlyphs(part, [entries[Math.min(k, entries.length - 1)]], sub, n > 1); + } + continue; + } + unmatched.push({ sub, entries }); + } + if (unmatched.length && regions.length) { + const flatPts = []; + for (const r of regions) { + for (const seg of r) { + if (Number.isFinite(seg.ps?.x) && Number.isFinite(seg.ps?.y)) flatPts.push(seg.ps); + if (Number.isFinite(seg.pe?.x) && Number.isFinite(seg.pe?.y)) flatPts.push(seg.pe); + } + } + const fb = bboxOf(flatPts); + const K = unmatched.reduce((s, u) => s + u.entries.length, 0); + const colW = (fb.x1 - fb.x0) / K; + let i = 0; + for (const u of unmatched) { + for (const e of u.entries) { + glyphs.push({ + x0: fb.x0 + i * colW, + x1: fb.x0 + (i + 1) * colW, + y0: fb.y0, + y1: fb.y1, + od: e.od ?? u.sub.od ?? 90, + openToward: e.openToward ?? u.sub.openToward ?? hmOf(u.sub).openToward, + openDirection: e.openDirection ?? hmOf(u.sub).openDirection, + isDoor: Boolean(e.isDoor || u.sub.isDoor), + kind: kindOf(u.sub) + }); + i++; + } + } + } + return { regions, sashes: glyphs }; +} +export { + DEC_PRESETS, + bboxOf, + inferSashGlyphs, + parseDrawing, + pointInRegion, + regionPoints, + replayShape, + spAxis, + spPos, + splitPolySegments +}; diff --git a/frontend/scripts/verify-decbar.mjs b/frontend/scripts/verify-decbar.mjs new file mode 100644 index 0000000..44c5050 --- /dev/null +++ b/frontend/scripts/verify-decbar.mjs @@ -0,0 +1,59 @@ +// 格条设计器端到端验证: 订单详情 → 编辑 → 点选玻璃格 → 格条对话框 → 预设应用 → 截图 +// 用法: node verify-decbar.mjs +import puppeteer from 'puppeteer-core' +const browser = await puppeteer.launch({ + executablePath: 'C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe', + headless: 'new', + args: ['--window-size=1440,900', '--enable-unsafe-swiftshader'], + defaultViewport: { width: 1440, height: 900 }, +}) +const page = await browser.newPage() +page.on('pageerror', e => console.log(`[JS异常] ${String(e).slice(0, 200)}`)) +const token = process.argv[2] +await page.goto(`http://localhost:8000/orders?token=${encodeURIComponent(token)}`, { waitUntil: 'networkidle2' }) +await new Promise(r => setTimeout(r, 1500)) + +// 打开第一行订单图纸 +const rows = await page.$$('.el-table__body-wrapper .el-table__row') +if (!rows.length) { console.log('✗ 无订单行'); process.exit(1) } +const btns = await rows[0].$$('button') +for (const b of btns) { + const t = await b.evaluate(el => el.textContent.trim()) + if (t === '图纸') { await b.click(); break } +} +await new Promise(r => setTimeout(r, 1800)) + +// 进入编辑模式 +const editBtn = await page.evaluateHandle(() => [...document.querySelectorAll('button')].find(b => b.textContent.includes('编辑分格'))) +await editBtn.asElement()?.click() +await new Promise(r => setTimeout(r, 800)) + +// 点击画布若干位置直到选中玻璃格(格条按钮出现) +const box = await (await page.$('.canvas-box')).boundingBox() +const cx = box.x + box.width / 2, cy = box.y + box.height / 2 +const offsets = [[-0.18, -0.15], [0.18, -0.15], [-0.18, 0.15], [0.18, 0.15], [0, 0.2], [0, -0.2], [-0.25, 0], [0.25, 0]] +let decBtn = null +for (const [dx, dy] of offsets) { + await page.mouse.click(cx + box.width * dx, cy + box.height * dy) + await new Promise(r => setTimeout(r, 500)) + decBtn = await page.evaluateHandle(() => [...document.querySelectorAll('button')].find(b => b.textContent.trim() === '格条')) + if (await decBtn.asElement()) break + // 换位置前先取消当前选中(点 HUD 外空白不行, 直接再点别处即可) +} +if (!(await decBtn.asElement())) { console.log('✗ 格条按钮未出现(未选中玻璃格)'); await browser.close(); process.exit(1) } +await decBtn.asElement().click() +await new Promise(r => setTimeout(r, 800)) + +// 选第 5 个预设(欧式古典 3x3) + 应用 +const presets = await page.$$('.dec-preset') +if (presets.length < 8) { console.log(`✗ 预设数量异常: ${presets.length}`); process.exit(1) } +await presets[4].click() +await new Promise(r => setTimeout(r, 300)) +await page.evaluateHandle(() => [...document.querySelectorAll('.el-dialog button')].find(b => b.textContent.includes('应用'))).then(h => h.asElement()?.click()) +await new Promise(r => setTimeout(r, 800)) + +await page.screenshot({ path: 'D:/Code/huamenchuang/shots/verify-decbar-2d.png', clip: box }) +console.log('✓ 2D 格条渲染截图完成') + +// 3D 同窗型验证: 打开渲染/3D 页选同样板? 直接验证 2D 即可, 3D 走 validate3d +await browser.close() diff --git a/frontend/src/components/WindoorCanvas.vue b/frontend/src/components/WindoorCanvas.vue index 5f60758..0301154 100644 --- a/frontend/src/components/WindoorCanvas.vue +++ b/frontend/src/components/WindoorCanvas.vue @@ -14,6 +14,7 @@ controls-position="right" style="width:92px" @change="onRegionSize" /> 格高 + 格条 @@ -44,11 +73,11 @@ * - 改梃: 直接点击中梃选中(高亮) → 拖动移动(line.pt 更新后重放) → 删除梃或 Del 键删除 * - 撤销栈; exportDrawing() 取回 drawing_data; change 事件通知父组件 */ -import { onMounted, ref, watch } from 'vue' +import { onMounted, reactive, ref, watch } from 'vue' import { ElMessage } from 'element-plus' import { - bboxOf, inferSashGlyphs, parseDrawing, regionPoints, replayShape, spAxis, spPos, - type DrawingData, type FrameShape, type Pt, type Segment, type SashShape, type SplitLine, + bboxOf, DEC_PRESETS, inferSashGlyphs, parseDrawing, regionPoints, replayShape, spAxis, spPos, + type DecBar, type DrawingData, type FrameShape, type Pt, type Segment, type SashShape, type SplitLine, } from '../types/drawing' const props = defineProps<{ drawingData: string | object; editable?: boolean }>() @@ -378,6 +407,35 @@ function drawFrame( ctx.stroke() } + // 1.5) 装饰格条(自研 decs 扩展, 挂在玻璃格上; ri 对齐重放区域索引) + for (const dec of (shape.decs ?? []) as DecBar[]) { + const segs = rp.regions[dec.ri] + if (!segs) continue + const pts = regionPoints(segs) + if (pts.length < 3) continue + const bb = bboxOf(pts) + const px0 = tx(bb.x0), py0 = ty(bb.y0), px1 = tx(bb.x1), py1 = ty(bb.y1) + const gw = px1 - px0, gh = py1 - py0 + if (gw < 12 || gh < 12) continue + const barPx = Math.max(1.5, dec.bw * scale) + ctx.save() + ctx.beginPath(); ctx.rect(px0, py0, gw, gh); ctx.clip() + ctx.fillStyle = dec.color + ctx.strokeStyle = 'rgba(0,0,0,0.4)' + ctx.lineWidth = 1 + for (let i = 1; i <= dec.rows; i++) { + const y = py0 + (gh * i) / (dec.rows + 1) + ctx.fillRect(px0, y - barPx / 2, gw, barPx) + ctx.strokeRect(px0, y - barPx / 2, gw, barPx) + } + for (let i = 1; i <= dec.cols; i++) { + const x = px0 + (gw * i) / (dec.cols + 1) + ctx.fillRect(x - barPx / 2, py0, barPx, gh) + ctx.strokeRect(x - barPx / 2, py0, barPx, gh) + } + ctx.restore() + } + // 2) 中梃(按目标区域裁剪, 型材三段线; 选中高亮) + 与外框交点白块(官方连接件符号) for (let spIdx = 0; spIdx < rp.clips.length; spIdx++) { const { sp, bb } = rp.clips[spIdx] @@ -796,6 +854,71 @@ function undo() { function exportDrawing(): string | null { return dd ? JSON.stringify(dd) : null } + +// ---- 装饰格条设计(P0-格条设计器) ---- +const DEC_COLORS = [ + { label: '黑', v: '#2b2b2b' }, { label: '白', v: '#ffffff' }, { label: '灰', v: '#9aa0a6' }, + { label: '金', v: '#c9a86a' }, { label: '棕', v: '#6b4a2b' }, { label: '蓝', v: '#3a6ea5' }, +] +const decVisible = ref(false) +const decForm = reactive({ ri: 0, kind: 'modern', rows: 1, cols: 1, bw: 25, color: '#2b2b2b' }) +const hasDec = ref(false) + +function openDec() { + if (!selRegion.value || !dd) return + const { shapeIdx, ri } = selRegion.value + const shape = dd.sm[shapeIdx] + const existing = (shape?.decs ?? []).find(d => d.ri === ri) + hasDec.value = !!existing + Object.assign(decForm, existing ?? { ri, kind: 'modern', rows: 1, cols: 1, bw: 25, color: '#2b2b2b' }, { ri }) + decVisible.value = true +} + +function applyPreset(p: (typeof DEC_PRESETS)[number]) { + Object.assign(decForm, { kind: p.kind, rows: p.rows, cols: p.cols, bw: p.bw, color: p.color }) +} + +function thumbStyle(p: (typeof DEC_PRESETS)[number]) { + // 纯 CSS 缩略图: 用线性渐变模拟格条 + const rowPct = p.rows ? 100 / (p.rows + 1) : 0 + const colPct = p.cols ? 100 / (p.cols + 1) : 0 + const horizontal = Array.from({ length: p.rows }, (_, i) => `${p.color} ${rowPct * (i + 1) - 2}% ${rowPct * (i + 1) + 2}%`).join(',') + const vertical = Array.from({ length: p.cols }, (_, i) => `${p.color} ${colPct * (i + 1) - 2}% ${colPct * (i + 1) + 2}%`).join(',') + const base = 'linear-gradient(135deg,#dceef0,#bcd9dc)' + const grad = [base, ...(horizontal ? [`linear-gradient(0deg,transparent,${horizontal},transparent)`] : []), + ...(vertical ? [`linear-gradient(90deg,transparent,${vertical},transparent)`] : [])] + return { background: grad.join(',') } +} + +function applyDec() { + if (!selRegion.value || !dd) return + const { shapeIdx } = selRegion.value + const shape = dd.sm[shapeIdx] + if (!shape) return + undoStack.push(JSON.stringify(dd)) + shape.decs = shape.decs ?? [] + const found = shape.decs.find(d => d.ri === decForm.ri) + if (found) Object.assign(found, JSON.parse(JSON.stringify(decForm))) + else shape.decs.push(JSON.parse(JSON.stringify(decForm))) + decVisible.value = false + render() + emit('change') + ElMessage.success('格条已应用') +} + +function removeDec() { + if (!selRegion.value || !dd) return + const { shapeIdx, ri } = selRegion.value + const shape = dd.sm[shapeIdx] + if (!shape?.decs) return + undoStack.push(JSON.stringify(dd)) + shape.decs = shape.decs.filter(d => d.ri !== ri) + hasDec.value = false + decVisible.value = false + render() + emit('change') + ElMessage.success('格条已清除') +} defineExpose({ exportDrawing }) // ============ 视图控制 ============ @@ -958,4 +1081,11 @@ canvas:active { cursor: grabbing; } .hud { position: absolute; right: 10px; top: 10px; display: flex; gap: 8px; align-items: center; background: rgba(255,255,255,0.92); border-radius: 6px; padding: 2px 8px; font-size: 12px; color: #606266; flex-wrap: wrap; } .dim-input { display: inline-flex; align-items: center; gap: 4px; color: #409eff; font-weight: 600; } +.dec-presets { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; } +.dec-preset { display: flex; flex-direction: column; align-items: center; gap: 4px; cursor: pointer; + padding: 6px; border: 1.5px solid transparent; border-radius: 8px; font-size: 12px; color: #606266; } +.dec-preset:hover { background: #f5f7fa; } +.dec-preset.active { border-color: #409eff; background: #ecf5ff; } +.dec-thumb { width: 100%; height: 44px; border: 1px solid #dcdfe6; border-radius: 4px; overflow: hidden; } +.dec-thumb-bar { width: 100%; height: 100%; } diff --git a/frontend/src/components/WindoorThreed.vue b/frontend/src/components/WindoorThreed.vue index f5e3e50..5aa21d1 100644 --- a/frontend/src/components/WindoorThreed.vue +++ b/frontend/src/components/WindoorThreed.vue @@ -58,7 +58,7 @@ import { ElMessage } from 'element-plus' import * as THREE from 'three' import { bboxOf, inferSashGlyphs, parseDrawing, regionPoints, replayShape, - type DrawingData, type Pt, + type DecBar, type DrawingData, type Pt, } from '../types/drawing' import { profileGeo } from '../three/profileGeo' @@ -268,7 +268,7 @@ function build(drawing: DrawingData) { const regionBBs: BBox[] = regions.map(r => bboxOf(regionPoints(r))) const used = new Set() - const panels: { rect: BBox; sash: (typeof sashes)[number] }[] = [] + const panels: { rect: BBox; sash: (typeof sashes)[number]; ri: number }[] = [] for (const s of sashes) { const sb: BBox = { x0: s.x0, y0: s.y0, x1: s.x1, y1: s.y1 } let best = -1, bestA = 0 @@ -277,7 +277,23 @@ function build(drawing: DrawingData) { const a = overlapArea(sb, rb) if (a > bestA) { bestA = a; best = ri } }) - if (best >= 0 && bestA > 0) { used.add(best); panels.push({ rect: regionBBs[best], sash: s }) } + if (best >= 0 && bestA > 0) { used.add(best); panels.push({ rect: regionBBs[best], sash: s, ri: best }) } + } + + /** 装饰格条(自研 decs 扩展): 玻璃前表面加横竖格条体 */ + const addDecBars = (parent: THREE.Group, dec: DecBar, w: number, h: number, mx: number, my: number, z: number) => { + const bw = Math.max(0.004, dec.bw * S) + const mat = new THREE.MeshStandardMaterial({ + color: new THREE.Color(dec.color), roughness: 0.5, metalness: 0.3, + }) + for (let i = 1; i <= dec.rows; i++) { + const y = my - h / 2 + (h * i) / (dec.rows + 1) + barX(parent, mat, w * 0.995, bw, DEPTH * 0.25, mx, y, z, 1) + } + for (let i = 1; i <= dec.cols; i++) { + const x = mx - w / 2 + (w * i) / (dec.cols + 1) + barY(parent, mat, h * 0.995, bw, DEPTH * 0.25, x, my, z, 1) + } } // 静态玻璃 + 中梃(区域薄型材) @@ -295,10 +311,12 @@ function build(drawing: DrawingData) { barX(frameGroup, mullionMat, w, t, DEPTH * 0.55, mx, my - h / 2 + t / 2, 0) barY(frameGroup, mullionMat, h, t, DEPTH * 0.55, mx - w / 2 + t / 2, my, 0) barY(frameGroup, mullionMat, h, t, DEPTH * 0.55, mx + w / 2 - t / 2, my, 0) + const dec = (shape.decs ?? []).find(d => d.ri === ri) + if (dec) addDecBars(frameGroup, dec, w, h, mx, my, 0.012) }) // 扇面板(可开合) - panels.forEach(({ rect, sash: s }, k) => { + panels.forEach(({ rect, sash: s, ri }, k) => { const w = (rect.x1 - rect.x0) * S, h = (rect.y1 - rect.y0) * S const cxr = ((rect.x0 + rect.x1) / 2 - cx) * S const cyr = (cy - (rect.y0 + rect.y1) / 2) * S @@ -311,6 +329,8 @@ function build(drawing: DrawingData) { barX(group, sashMat, w, t, DEPTH * 0.7, 0, -h / 2 + t / 2, 0) barY(group, sashMat, h, t, DEPTH * 0.7, -w / 2 + t / 2, 0, 0) barY(group, sashMat, h, t, DEPTH * 0.7, w / 2 - t / 2, 0, 0) + const dec = (shape.decs ?? []).find(d => d.ri === ri) + if (dec) addDecBars(group, dec, w, h, 0, 0, 0.011) group.position.set(cxr, cyr, 0) sashRoot.add(group) diff --git a/frontend/src/types/.drawing-bundle.mjs b/frontend/src/types/.drawing-bundle.mjs new file mode 100644 index 0000000..78fbd28 --- /dev/null +++ b/frontend/src/types/.drawing-bundle.mjs @@ -0,0 +1,311 @@ +// src/types/drawing.ts +var DEC_PRESETS = [ + { kind: "modern", label: "\u73B0\u4EE3\u8F7B\u5962", rows: 1, cols: 1, bw: 25, color: "#2b2b2b" }, + { kind: "italian", label: "\u610F\u5F0F\u7B80\u7EA6", rows: 1, cols: 1, bw: 18, color: "#9aa0a6" }, + { kind: "cream", label: "\u5976\u6CB9\u98CE", rows: 2, cols: 2, bw: 22, color: "#f3ece2" }, + { kind: "chinese", label: "\u4E2D\u5F0F", rows: 2, cols: 2, bw: 28, color: "#6b4a2b" }, + { kind: "european", label: "\u6B27\u5F0F\u53E4\u5178", rows: 3, cols: 3, bw: 20, color: "#c9a86a" }, + { kind: "french", label: "\u6CD5\u5F0F", rows: 2, cols: 2, bw: 16, color: "#d8c9a3" }, + { kind: "medit", label: "\u5730\u4E2D\u6D77", rows: 2, cols: 3, bw: 24, color: "#3a6ea5" }, + { kind: "pastoral", label: "\u7530\u56ED\u5BC6\u683C", rows: 4, cols: 4, bw: 14, color: "#ffffff" } +]; +function parseDrawing(raw) { + const dd = typeof raw === "string" ? JSON.parse(raw) : raw; + return dd; +} +function regionPoints(region) { + return region.map((seg) => ({ x: seg.ps.x, y: seg.ps.y })); +} +function bboxOf(points) { + const xs = points.map((p) => p.x); + const ys = points.map((p) => p.y); + return { x0: Math.min(...xs), y0: Math.min(...ys), x1: Math.max(...xs), y1: Math.max(...ys) }; +} +function spAxis(sp) { + const n = sp.line?.norm ?? { x: 1, y: 0 }; + return Math.abs(n.x) >= Math.abs(n.y) ? "v" : "h"; +} +function spPos(sp) { + return spAxis(sp) === "v" ? sp.line.pt.x : sp.line.pt.y; +} +function pointInRegion(p, region) { + let inside = false; + const pts = regionPoints(region); + for (let i = 0, j = pts.length - 1; i < pts.length; j = i++) { + const xi = pts[i].x, yi = pts[i].y, xj = pts[j].x, yj = pts[j].y; + if (yi > p.y !== yj > p.y && p.x < (xj - xi) * (p.y - yi) / (yj - yi) + xi) inside = !inside; + } + return inside; +} +function dfsLeaves(node, out) { + if (node.kids.length === 0) { + out.push(node); + return; + } + node.kids.forEach((k) => dfsLeaves(k, out)); +} +function replayShape(shape) { + const base = (shape.polygon?.polygon ?? []).map((r) => r.filter((s) => s && typeof s === "object" && s.ps && s.pe && Number.isFinite(s.ps.x) && Number.isFinite(s.ps.y) && Number.isFinite(s.pe.x) && Number.isFinite(s.pe.y)).map((s) => ({ ps: { ...s.ps }, pe: { ...s.pe } }))).filter((r) => r.length >= 3); + const root = { segs: base[0] ?? [], kids: [] }; + const extraRoots = base.slice(1).map((segs) => ({ segs, kids: [] })); + const idMap = /* @__PURE__ */ new Map(); + const clips = []; + const allLeaves = () => { + const out = []; + dfsLeaves(root, out); + extraRoots.forEach((r) => dfsLeaves(r, out)); + return out; + }; + let spIdx = 0; + for (const sp of shape.mm?.sp ?? []) { + const myId = spIdx; + spIdx++; + if (!sp?.line?.pt || !sp.line.norm) continue; + const axis = spAxis(sp); + const pos = spPos(sp); + let target = null; + const nid = sp.polyId?.idx; + const cpos = sp.polyId?.pos; + if (Number.isInteger(nid) && nid >= 0) { + const node = nid === 0 ? root : idMap.get(nid); + if (node) { + if (node.kids.length === 0) target = node; + else if (Number.isInteger(cpos) && cpos >= 0 && cpos < node.kids.length) { + target = node.kids[cpos]; + } + } + } + if (!target) target = allLeaves().find((nd) => pointInRegion(sp.line.pt, nd.segs)) ?? null; + if (!target || target.segs.length < 3) continue; + const bb = bboxOf(regionPoints(target.segs)); + const lo = axis === "v" ? bb.x0 : bb.y0; + const hi = axis === "v" ? bb.x1 : bb.y1; + if (pos <= lo + 0.5 || pos >= hi - 0.5) { + clips.push({ sp, bb }); + idMap.set(myId, target); + continue; + } + const split = splitPolySegments(target.segs, axis, pos); + if (!split) { + clips.push({ sp, bb }); + idMap.set(myId, target); + continue; + } + const nrm = sp.line.norm; + const sideOf = (segs) => { + for (const s of segs) { + for (const p of [s.ps, s.pe]) { + const d = (p.x - sp.line.pt.x) * nrm.x + (p.y - sp.line.pt.y) * nrm.y; + if (Math.abs(d) > 1e-6) return d > 0; + } + } + return true; + }; + const c0 = sideOf(split.a) ? split.a : split.b; + target.kids = [{ segs: c0, kids: [] }, { segs: sideOf(split.a) ? split.b : split.a, kids: [] }]; + target.segs = []; + idMap.set(myId, target); + clips.push({ sp, bb }); + } + const leaves = allLeaves(); + const regions = leaves.map((l) => l.segs).filter((s) => s.length >= 3); + const nodeId = /* @__PURE__ */ new Map([[root, 0]]); + const leafRefs = []; + const walk = (node, id) => { + node.kids.forEach((k, i) => { + if (k.kids.length === 0) leafRefs.push({ idx: id, pos: i }); + else { + const kidId = nodeId.get(k); + if (kidId != null) walk(k, kidId); + } + }); + }; + if (root.kids.length === 0 && root.segs.length >= 3) leafRefs.push({ idx: 0, pos: 0 }); + else walk(root, 0); + extraRoots.forEach((r, i) => { + const eid = base.length + spIdx + i; + idMap.set(eid, r); + if (r.kids.length === 0) leafRefs.push({ idx: eid, pos: 0 }); + else walk(r, eid); + }); + const resolveRef = (idx, pos) => { + const node = idx === 0 ? root : idMap.get(idx); + if (!node) return null; + if (node.kids.length === 0) return node.segs; + if (Number.isInteger(pos) && pos >= 0 && pos < node.kids.length) { + const k = node.kids[pos]; + if (k.kids.length === 0) return k.segs; + const l = []; + dfsLeaves(k, l); + return l[0]?.segs ?? null; + } + return null; + }; + return { regions, clips, leafRefs, resolveRef }; +} +function splitPolySegments(region, axis, pos) { + const pts = regionPoints(region); + const n = pts.length; + const get = (p) => axis === "v" ? p.x : p.y; + const crossings = []; + for (let i = 0; i < n; i++) { + const a = pts[i], b = pts[(i + 1) % n]; + const da = get(a) - pos, db = get(b) - pos; + if (da < 0 && db > 0 || da > 0 && db < 0) { + const t = da / (da - db); + crossings.push({ + i, + p: axis === "v" ? { x: pos, y: a.y + (b.y - a.y) * t } : { x: a.x + (b.x - a.x) * t, y: pos } + }); + } + } + if (crossings.length !== 2) return null; + const [c1, c2] = crossings; + if (c1.i === c2.i) return null; + const collect = (from, to) => { + const ps = [from.p]; + for (let k = (from.i + 1) % n; ; k = (k + 1) % n) { + ps.push(pts[k]); + if (k === to.i) break; + } + ps.push(to.p); + return ps.filter((p, i) => i === 0 || Math.abs(p.x - ps[i - 1].x) > 0.01 || Math.abs(p.y - ps[i - 1].y) > 0.01); + }; + const toSegs = (ps) => { + const segs = []; + for (let i = 0; i < ps.length; i++) segs.push({ ps: ps[i], pe: ps[(i + 1) % ps.length], name: "segment" }); + return segs; + }; + const polyA = collect(c1, c2); + const polyB = collect(c2, c1); + if (polyA.length < 3 || polyB.length < 3) return null; + return { a: toSegs(polyA), b: toSegs(polyB) }; +} +function hmOf(sub) { + const hm = sub.hm; + return hm ?? {}; +} +function inferSashGlyphs(shape, replayed) { + let rr = null; + let regions; + if (replayed && !Array.isArray(replayed)) { + rr = replayed; + regions = rr.regions; + } else if (replayed) { + regions = replayed; + } else { + rr = replayShape(shape); + regions = rr.regions; + } + const regionBBs = regions.map((r) => bboxOf(regionPoints(r))); + const glyphs = []; + const bdRect = (bd) => { + if (!bd.from || !bd.to) return null; + const r = { + x0: Math.min(bd.from.x, bd.to.x), + y0: Math.min(bd.from.y, bd.to.y), + x1: Math.max(bd.from.x, bd.to.x), + y1: Math.max(bd.from.y, bd.to.y) + }; + const ok = [r.x0, r.y0, r.x1, r.y1].every((v) => Number.isFinite(v)); + return ok && !bd.hidden && r.x1 - r.x0 > 10 && r.y1 - r.y0 > 10 ? r : null; + }; + const kindOf = (sub) => String(sub.type) === "Slide" ? "sliding" : "casement"; + const rectOfRef = (ref) => { + if (!ref || !Number.isInteger(ref.idx) || ref.idx < 0) return null; + if (rr) { + const segs = rr.resolveRef(ref.idx, ref.pos); + if (segs && segs.length >= 3) return bboxOf(regionPoints(segs)); + } + const i = ref.idx; + return i < regionBBs.length ? regionBBs[i] : null; + }; + const iouR = (a, b) => { + const w = Math.min(a.x1, b.x1) - Math.max(a.x0, b.x0); + const h = Math.min(a.y1, b.y1) - Math.max(a.y0, b.y0); + if (w <= 0 || h <= 0) return 0; + const inter = w * h; + return inter / ((a.x1 - a.x0) * (a.y1 - a.y0) + (b.x1 - b.x0) * (b.y1 - b.y0) - inter); + }; + const pushGlyphs = (r, entries, sub, forceRect = false) => { + const kind = kindOf(sub); + const hm = hmOf(sub); + for (const e of entries) { + const rect = !forceRect ? rectOfRef(e.polyId) ?? r : r; + if (glyphs.some((g) => iouR(rect, g) > 0.15)) continue; + glyphs.push({ + x0: rect.x0, + y0: rect.y0, + x1: rect.x1, + y1: rect.y1, + od: e.od ?? sub.od ?? 90, + openToward: e.openToward ?? sub.openToward ?? hm.openToward, + openDirection: e.openDirection ?? hm.openDirection, + isDoor: Boolean(e.isDoor || sub.isDoor), + wtf: Boolean(e.wtf ?? sub.wtf ?? sub.withTurningFrame), + kind + }); + } + }; + const unmatched = []; + for (const sub of shape.sm ?? []) { + const type = String(sub.type ?? ""); + if (type === "Screen" || type === "DoubleScreen") continue; + const raw = sub.sashes?.length ? sub.sashes : [sub]; + const entries = raw.filter((e) => e && e.enabled !== false); + if (!entries.length) continue; + const n = Math.max(entries.length, type.startsWith("Double") ? 2 : 1); + let rect = sub.bd ? bdRect(sub.bd) : null; + if (!rect) rect = rectOfRef(sub.polyId); + if (rect) { + for (let k = 0; k < n; k++) { + const part = n > 1 ? { x0: rect.x0 + (rect.x1 - rect.x0) * k / n, y0: rect.y0, x1: rect.x0 + (rect.x1 - rect.x0) * (k + 1) / n, y1: rect.y1 } : rect; + pushGlyphs(part, [entries[Math.min(k, entries.length - 1)]], sub, n > 1); + } + continue; + } + unmatched.push({ sub, entries }); + } + if (unmatched.length && regions.length) { + const flatPts = []; + for (const r of regions) { + for (const seg of r) { + if (Number.isFinite(seg.ps?.x) && Number.isFinite(seg.ps?.y)) flatPts.push(seg.ps); + if (Number.isFinite(seg.pe?.x) && Number.isFinite(seg.pe?.y)) flatPts.push(seg.pe); + } + } + const fb = bboxOf(flatPts); + const K = unmatched.reduce((s, u) => s + u.entries.length, 0); + const colW = (fb.x1 - fb.x0) / K; + let i = 0; + for (const u of unmatched) { + for (const e of u.entries) { + glyphs.push({ + x0: fb.x0 + i * colW, + x1: fb.x0 + (i + 1) * colW, + y0: fb.y0, + y1: fb.y1, + od: e.od ?? u.sub.od ?? 90, + openToward: e.openToward ?? u.sub.openToward ?? hmOf(u.sub).openToward, + openDirection: e.openDirection ?? hmOf(u.sub).openDirection, + isDoor: Boolean(e.isDoor || u.sub.isDoor), + kind: kindOf(u.sub) + }); + i++; + } + } + } + return { regions, sashes: glyphs }; +} +export { + DEC_PRESETS, + bboxOf, + inferSashGlyphs, + parseDrawing, + pointInRegion, + regionPoints, + replayShape, + spAxis, + spPos, + splitPolySegments +}; diff --git a/frontend/src/types/drawing.ts b/frontend/src/types/drawing.ts index 9e22c95..3ce770f 100644 --- a/frontend/src/types/drawing.ts +++ b/frontend/src/types/drawing.ts @@ -70,6 +70,28 @@ export interface SashShape { [k: string]: unknown } +/** 装饰格条(自研扩展字段,挂在 FrameShape.decs;ri = 重放区域索引) */ +export interface DecBar { + ri: number + kind: string // 风格预设 id(modern/italian/cream/chinese/european/french/medit/pastoral) + rows: number // 横向分割条数 + cols: number // 纵向分割条数 + bw: number // 条宽 mm + color: string +} + +/** 格条风格预设(对齐源站 decorationBar 8 种装修风格) */ +export const DEC_PRESETS: { kind: string; label: string; rows: number; cols: number; bw: number; color: string }[] = [ + { kind: 'modern', label: '现代轻奢', rows: 1, cols: 1, bw: 25, color: '#2b2b2b' }, + { kind: 'italian', label: '意式简约', rows: 1, cols: 1, bw: 18, color: '#9aa0a6' }, + { kind: 'cream', label: '奶油风', rows: 2, cols: 2, bw: 22, color: '#f3ece2' }, + { kind: 'chinese', label: '中式', rows: 2, cols: 2, bw: 28, color: '#6b4a2b' }, + { kind: 'european', label: '欧式古典', rows: 3, cols: 3, bw: 20, color: '#c9a86a' }, + { kind: 'french', label: '法式', rows: 2, cols: 2, bw: 16, color: '#d8c9a3' }, + { kind: 'medit', label: '地中海', rows: 2, cols: 3, bw: 24, color: '#3a6ea5' }, + { kind: 'pastoral', label: '田园密格', rows: 4, cols: 4, bw: 14, color: '#ffffff' }, +] + export interface FrameShape { type: 'Frame' | string polygon?: { @@ -87,6 +109,7 @@ export interface FrameShape { ps?: Record uid?: string titl?: string + decs?: DecBar[] // 装饰格条(自研扩展) [k: string]: unknown } diff --git a/shots/verify-decbar-2d.png b/shots/verify-decbar-2d.png new file mode 100644 index 0000000000000000000000000000000000000000..3aecee220e813a63fbcef744dd274135a902b6af GIT binary patch literal 100021 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

UGNNCRX$IE7mW+1- zTji(8Z{T7T(C4?A`&xGHYs2+S7_3+9Eu4(2)&c<(gH<5=~0gMyMR(tfMvoP z5`inE|GmVBT*qu2QNPFan-Db>Jdbs@Xoh;68eI3u!Ga?}KMu&46^$l~4T``uP0Pe8 zea}uF{teo;PA#vJ1!brXOfSQsjDQ^FBxm_buc0K2q3OHVN6;iMBb{%|naGug7KG|m z5oWR?9DW*o(u}j?cnSI>*7AdZkRz)?c)*}G&YceL*2p^8`Ya{q3S_?cefbk-5Zaec z;M9y)FC>d&s1@;G#M!$SCl-v(sqA@JyJV}a$r;eZsUJ|un^ajVd})w^^h1d{e~@pa zpO7)OR(GJm3bC7AG@#=tGx7!bVLzce7gFI>pCEKMjT0&Lg>h9f4~*Efu)w4quWj~J-r zE|u;rg>6fO^L`bGfsY|pN#L^AhDb$WdMZdEwJ=>%AmBdgsLsOI)NHJ|cUtuQwsM+i zKqTu0YOUpj0j2`>zSI#pN!k&q?xp@;Gjq4(9*y}gKkxD~KBR|vWr}B`g{JxrPIGM2 zGvVL{qLolwc`|?)Ce%U%;3`MlJq^4AZW)nUF-??1UWlW7K7X0!8~j}8^)Emp{x$&e zf-pKPe0=bmch_>nC`8?>JD&Hv8BgVH2ubgWR?56bBX zV7z`O&cdk~^EG>d)<_1-k;)j=wNCa`4)t_0j|?VtLKx~Ki*(zaghJIJl-v)|1h=fU zO03%_pTI_qZ9Ji@8O*Pfuye;wn4^SRNm|P?5djKClv9Ul>6v20YOi2wBnpfiQtK*B z-4+1X-IeuPSE}pr=jl6B3&E`db;gknJdp#C9S4sDAPgU48fS(qH9kyzs-}dz1WH7m z>F|8kwHq5HE6dCQy@^VpU;kFU0884e$9VUdioy@sufD-BsyYF}`GGel|3i2G-9lR6 zL}D%Dyf=8ApuPIcP7}6YgV{sq+9S)UAKP*~C!0=_N!wTs6LTNlUkvRLoYdmgy_5v&xeXZzIJd~his~R zgVFNrt$T(63-QejEwB)$dqDOi^MR+}EoL7If3Nu?Y?Qi1x_O+K%;3luxgj}9=c60U%yf}FAa8Q=C=WA6h(*6 z7irYIYdFEtKpTK!qA14Wq0dMNsn?wPE(5_f}2&}qz4$YC?~cR~ zH5I|>ceil1oalQ@+If#Mo{Z|XSb3u}g>D!QhFVgQ+@7L4Y$z}xS18GqTaRSPx@pET zE*skb2MdPFmx?029RF%y*MEm1c%%Nqn`Suq-)Kldq{&+`8uMdv^ku7fcUTI2=!1~7 zqPVovK7Aoi@b_6xc1w-cRdmvM=|Ud_`A3rgXmr`UN_|!ZDrXs+6BICgmsGt3`QyiU z`mrSi<1JvnYPfi>RHYlS7D+VvI~C~bsT?k>g?ydzb62Y(-BNGP0x90%Zw-@2vsEE} zW0Z1384hlS^~er7lPu2hO76sx>DWYe)}c3B3pgKn);7U;6JdbTyfuj4DKO@lDcnZ?b+j!4$b2;7)n#bI~suDnq&fKZt=&1&OmzYa0a_ z$|J@57vjyPB1M&35PUW)VtS;Ln zPuqIa7oegkOvIx?Y#rzP>vjua{M~V>*G+r0#1~FPto~o}eIw`oh7R0nw%i&TD&By-cO$IzM&bTkKYy;hJjY&E+VyxUMFR&5+RiNe3ipi_@=!Il&~@x)l{14F?8&6h5%4D%D-A-k{}dE;fI zlt+r3aHj$!*|#GR-D)uzSN6*`s7v5rvJZ5@^Gqz_(s+~CLYJ1)}3nqhhN=S2UaDAH~Dj{F!k$O+5Xg4l`JTANec%q z;6!@VedpEE=V{vP)6Q88ea-5GUeWxl0i@B2&q7QdQ~xYnJ00nNyzuPuwT;3j{bj&5 z{jS3BM;9wLZ>&etJ@s_MdTqBf=OKA1()fh=fh!a2QG>E9B8{`L4?}7=mp3Vd;i%as zD6hF-gG> zC0T;KSv$ECyd%DP@)ChWGIBDLC_@Dh@QGScAbUP-8oa-FjF|G`tK#VF!$AEE>4J*57#<`=YN1 zeZJAM5zzD_#IcSGLx5HlJY|f~8^Wy9V2MEtqKGlyVEIO+CaZ10bLLU)cpa({iPb@^ z(_|zUl7a*&+T!Nts#$zgD?=*)=0H-{9v$#K@_LDng9$1bCbG0bN%`~fPsYuACDO>O zeHto8+E3<28tiZ9(2&yr79frF&Uv=zWTc0htgp5fx z?EjvLeFy((X=^6i7`a}t!F!4`5!5jG%D2ah~7PRp<^~f@Pkaqhv@6T&(M1@~I$LIopV7h$;hx=<6>+yo5YW)5$p1)Yyc!Ts@o4;9oY zX6~odiaaEN41=9CY?8}V8QZUu5_OIf#M4KSjrU_{A>r%4LZ+!+xg%p%=%rsEid%&G z41U%}Io=`J4X>BkE8$ghyMuN^|7JAdo5SVl-ueU++Xd79J!Kr#6XVw+i0Akd+bfNS zPwBioqri&&&u)qS6kR=onYM$FeRxTm<`^HWco@Tx$#$JoVaRd}?iDLJfkM7P(jO^| zcM5Y>4(YNWAJoex+r<+foT5ac+}k)m&DHlpF25~cJ2Y%DmT$+oKO|ZnhLVjaAqBwQ z5n{DTDaf~HZ5j+p+clWUC8=Rt-?ig#Z(g-ls7Y(ES1g5ai?JBI^nS}JB=>vhL1888 zDJ;ZD*hUJy^2fAfVCl4?s8-uM*L6BUydyV^Z z^RpDYdNK1lzIo0;(iClbF}tm{Mh;hLr>Tt&+NcZ!6a6K=h_1pR6VG9l0<=|W-QA2A zn^Af4A}oerZz3rT9ficrOab{dxuBl~o1`JP9=XYNc+UVuI$N>Ij3mUv@fn7ba3< zgh7&ji`yFOAnMCM%!{!=~vg~E4#FZV|K!A4N<4PMs58F^~SbSBKV zV%~)oxlWpJrV*(I+RzSQMGxsWmn42lMw3Bad$$$wH8)d&H65n8D%#Ak%3|q%c4C(& z=y1vpe8ZdoFV1CQaa)O>ORR2m;MgL`dRZPdF^^4lMpqtSOLN}F6!<+!%#|DN1e`{d z1BL65Yk7m|rQOJT^tDMG3vvRmkm;QZd|+hQjteOqD*H_KfE1Y=(-8vJI%g?E z#H_<%<%5ZUPX^;HP@Ap-bKIDWU|eF6Ffd@5T%Jm_I#@ptC3%@_IK+4pMAXzbuGI~a zC%^|+C~k?a$txjqFfpGr>%9pBc1|u}*tyY5t09;B5j+mO$b-(mNGOosT%Z^O$-kOE zaozhjMJEPnS5GWMp=)XKXHoohm6M<5s<1ErL5G7Z7hY?cH=GVQeiQOMGMX_sXP>~*3q?KLU z6lBgdKJM6V`fXH}?pW!*G^qV3Gm|p1aY3ymwIVdFJGJmoYcnMk{ToENlw|ED^b=nL z_8wnchl3f_MP_1ZByi^jb>faq#>^yZ?z_vp_T4%D=PJ1!yfPcHAV(>jN?@Vm%cCS# zw#(UZPq;BLd-W?xdFLKeD71O%P9%9**HjUrqGLfuvQ{w=HYp zNk!ZZ!yR=(MP*#N(k(+Solb$4;PP06-KNzZ5<^m9~?y zu@#}~Ugw61cB!YTRji118k`6)4u1QVe%$}nA(B~t0`go>$bvs z4;_rXB#MCJtl2po>Gu$Kg|6AFDXqQe{hCn03z+t-NGdDt)|8n9Au{!?o+nAE{z10< z1W}F(BbbOqz^HDUs3A;ArX+gwp`!#uF#u#Foq}1@A17oQa(u`58HSX6(eW`Bz;p#T zqUy^?f_Cxl2Fp0`t(Di1B?aKEGM*4J2Q}o8)>R?D%WD%s4oK0H&2{rlQ^)A*mA|7D zWR&I6QSVasim1b(1kNx~;V9B-qlXwtfs`2gB^a~Ob`<-JEwi!Gpu}iTE`hUAcKD@P zSZ9jG|76x8=fFSwL26P$DjJ!tAUB}^6(QzpP16p&J=tFGtL<>Jz&qiCe3eV?P(!1n7Ume$VSCe>Tn!OO2E{$f5+O#Y?=uyq0Fle=5ByeGJ zl6blkXvY>7Bl3a)bFYj*)Huuildg@c0vl0JAY8 z3|Hbq=%=MPOI-)E=M=6SiFPxXXU=YhZpmxB&Eh(gflX%5{gAN+VpiY(Q_JawkkR@Ps1BX|PPv5c9YHb5jKS#DyU|jeH6V=tM z@o-hrj%&bNFl_0D5%c~?rb^lMfBCe?Ql;PZ&Bk`I&z0CM8mzxQF+>R7V*XFmN*V9VM~Ql;h?ea@l-X5O@=^ zVHr?KXO)p!^5Y(#1v@S&F_D0fP@`ZOU#mnpRohHA-O@MS$Dq2j&=|A#{)yE0u*JFz ziQqh%_(iknM4Qc{<}r4Y->z}kbwG3;GH$A2Q!RY2^iDU7wJd%-f`%+U+zELmKap|y zSy(cr$9<(=I&2l%>mFW?TIT>rNgY>lWF-oe0m&==1#zb#b z(4o1k{;~q@G+KUoh8eGdGpZLSUqi*8YCKH37^Mlbdech2dcuCm<4}-uV+0o9H>j?S zQ7m|W64SEujp^YSKz@Ok$|AZpYORK%JXWx9m;9zNrUo;wCzMRM&zSfmd7QL6 zP*?3GyAqdPU!TF^OVZ%jhsZBI5AHO}v?9fysf@zNjAO+I&n~D{gDcabZyn^~sXkhr zGuVjK34Bg6+m{FyN0I^i`GyX||2uJ%3G-!I%*QTCmlaAL!zcD{-k5SmS;&pk*a9zc=4+Luk+psD)Ef;+NC`){O zR0P%KTQ9;Q*tg(O`hzhJj#MMg-SVp+z6FX)BCqwx622U~&u{DQhPdddsVejQ7pp7j z`kVubJKMcqyq&IXbKD(0q?iwrKN6whlnMS$oNvy>wKJ!HvBDC~Bis@##qf1`w%7Z& zR-7pS1RgN9$%&pYF_NAz%77BL^4)qNn#M(?6U9+~5t#<0ui}in*;-Ih#d&I_jOUA@ zN@5YkFa2~~!qF`5#E`^uI`a16@!;M*&3V9!9(b6)F|yVkl}!aqMhBqwLQuhCA5tM& zwDNJ(PWTxIO|U9G#EH>w2ECCegoqUBGL_aiySERE-EYEd2D+;eN~VZCVt^`d7! zd-YAkKAEO5Y^}H3$xIyhyKd1v{345Q`Gdlmb1IgBB9H6*W~qzE{7>ZL8vIuac)zh{j%EvQOhm(b?!cb=Fuck&Fhht(pw5MLinSew~4Ua#<;o zIS#*YN$ol>_tL-hO&=07OEc-Pb{kmi-_y%#k^y`XfjgJ@ql%df`* zg-buG!R?$oxZDbGf@~Q>t}YcnhO(r|$Ze69f2|3+{ODirXY?}rZE^@q}!%p zpI)cYuS5ouBFh0YkwDeKqs=vp*I?gWR>V&pvkqo&h7_#Ko#ChK##FNpe#Q+;>&#v# zBsB{|8^MKpx~8Q4fX@OC+7NqzMj9+&ni>t(Nv#v<0AK}nneUcBO-Dfe2aEfVWBu!( z6IzR~lSfWoIg4#z;^ieG%H_vrHjAhfegin^trA&czaqgU{y>ApjqJdMy_)|!*pm`X zBDIDuenKIQD9KJ`8N}m3egbIzR+BYB1&@oK1*9PY6K~2(<7yXHNLAEq`X=)|RNPqrWW zeiJ@!bzUFjx_tGyAM7SAZ;|rbw(7aL!*XrkllCb4_0;*UcAZ6*o(~)~FptE_e9%MG z)jR3@raM>o-12u*(Gztlf_R*g{tPkRT!a-HFg)Ho-;GtRf|RqDJ$L@iS9Et6&gEFU zvATU-8uYtXmvJ!q_E`|F+cVon+k`h79fEUb5rxI;d;V*E!D!>~ardtxk#oKxqdosvBcW>^K#k&SpN`KOW8y20nUTX1e_lw?z~@?BP=uytM}6O|9^=q{%bD z(%XUKte16iCgl?Eocn5vUkuU{kbBxXsXoNrN+_-E2GxtoJoGko+M5=iUS9v8bH2ZA z8(~-4+O56EuUAmT@i#yDfY4q4aDZ)ri0zEYtVrD#>}*y1u-4$Q!Eo@^>=t*qMEWTYNvG$B=4^G| z_y-b~S64Sr8-#Wa%#)=Zc>NQ^pMSj&wSW04D}hRS3M>0Y#No`TR0PfCthn62!~ewWVQB7wQ0j5rpkt>k=mE>@+x;&Me7=r@ zi0%8iPS2&3zHGC_`}pKFEhsyqhP*-GQMQdiJ1$zbX1Zn{F2>qYhI-x#tNLx>eqXWtU8@O9x)e29P%U*lZ|XF!G-~j_pSgx^ zckS5cu`u4FE(EYXeXMp2D!oMrJnCzrEyvs~n0fA>wY|5>HuH@9zEtY3zuUXG(=YDt z@jE-kaF(KrVvKvbsP#5rqPBz71rH%h80rr9rx}_VN^?gE;3x7fb1$qgCdP%$v(S*; z;JHli@auTdxgjLpE9pqN{_|Sc=0l#{=NBeRw?EzOZg<{J_kaKPaB6Tr@p#-+-r^l} zxp67gb1`}Xbo0qvdvQa^H;LXBwXyK3TQ9(=hHYWpsIjKQ)A3efFkIM;{u z_^8`rXQmA7kark&j1L^5-rlUWT~JC`fPm7oBZ&oqQW}Q0jwD(1W`!(8=>VxV`ER`~ z`CA4q6YaLTPUQOxxy+f{v~6N8AIOL zc5j7@-C$E6x~g#{Wl6C}PzcVWph*V>y=cD9@SCFyGTeWr$Uz8FE)v-xDr`L!iv$pH|zh$)K^Be z*+ol3@uEdaafjmWURqpRC@wAT1SwD?NO3Lh6ev*KU4m0AxJ&Th?vi}zd+%NA`Rsm9F7>S1tEOl6|^)9DIAdU@r3TOV;G7#~NrOUD*QDRp@^p!sdC2!6Bk_qDX z_0aUGTek|dd503`ymp^WMAP~F6CVQG(^x&De4t>NGe=Ju$X%rJCafd^G)R4*G6ej_ zOE=&Bm2~iNH3larIp4MwT7KN{Wk$G@0d$$OA+0W;gkq>iETbJqnV;fL7A)U9NLbAh zHWJ1=5QfEpg@BB|mJq&J{Yw3W=P?@**>|>9?|?1g5;b2ou<<48ADkimAs{=fQcs=k z-Q1Qj!K^ga^%YiTrGPko8r0iDi=YdZ*r=PmQOZ@HAF;SL_Oa??mjzK*3-rd#Vac1r zsA7!XEAz1H*96y=d25hi020bs{QxreLNabFitjH#fKhJGR$yt3R)Mu}gGX14|CRf` zH#_J#&g8i*xA_zVPxR4nIDt)jLOhOl2I2ix5U;U9g?;CEMoOk~Im-`&3wfanqb>yj z@k}HQ*S`AxtAt@R!Q>}$cg>BS`wnla#fid-(@}sAuf88J!V&Y_<#i^15!f{jqSz+U za^TUG(r3#O*~Aa$?;usqa$?osrnn!F6xU10r9AQ-x^B7(6QKbok)uafhNeeO{oyBN z&SW^q>u(-33pcYG4hS#iv2_9}2GRm(^OgSahXzJ2SF-?G+a-P(3hlM2T*WXH#L#v& z()X5}d1Tgio{kV4ns!~$f3UQB#;Hcs32xw8 zcrr_PA7f(3CEIKTP*MWRDfM$kh5bn{8)K-9=ar%VFgN!F{3mcD+opJ}-&0;%8OdOew&a27 z&Q^_!6Fn2`Ckcn-A%PPp6ZT+VFh&CwO<}Zx1TW*jtY~6Dm;H+x7D6m%s+{MixhS}p z(zkxW(J9T@G{0fOutmaXrPN#HN;H73q7vH)|+ut0l zSGcP?90Y4I|KpZNd08GQqLK9k#&j+x5Vk~6>(ykpV??*Df6hR!FA#7V?kEaj4} zRTR%9Qe$c}`Q}MzRv1qtv}CL6&g<7lhnc-aHAnQ7Jp~PD1^3!@*U8NqY@|{G{#dot za<*{c(!3^8=XsB2e1qZE#YkxM9;I{`N|7H@VD&`Bwe#9_(GzWmu~xFX-^_5o&z|??@&gGKT}6PLMEe^In;SsDYkne)%o@ST(?2xKKouo@059dn(W#8yK%?T;wmV;Up=xGeKvbaRn#T3bM!DV8U zyImmHg5~s|oy{#&t1tHn2OEq0h@m#Txfv58c$!DAI@Q}h-gUzgc3zd<5PEY4-l&Z*uS4a?uWXP^dC6Ndx{{0w$A$ zII0we>9bXn?t2ltf`#bOt5mK^$K21=i?MIr(B}(36*QOR$FZnuwOm)lGK6}3s6$o9 znNDv0)^euU@s^{+KwVU!am!gUbWu76pUEp`i_LmF_!5J+GxjZ6pzjv=G(Tu6gHQRlW|oPHS5& z4(k1)`;i}-t=_p*{w*a~Q29SC;N5e!%R>^0y%1N8c8rA}(#B6#QM@grdi9zN03~ht z_R7+%&~-G*C$*zL|FBe!Hf)J4T;3Yx_y`wP9Jg}&bD752AnS24)%b?J$_GY(4gecCd1sn;K%Kgr zHX8k=u`sK1N!Y{Fl&ZIj{+7e|Q!qZa-@3UWeA%?y+dUSGC3CE*X5bv(8LpS(UKw6O zKQ|@1mxJ#`_4%2vI|twB=$_!tF%FaLuoI3c*~;?{m|NGIdOVSJCj5DCVQtTsBi7}( zYBoYI;|B*{mOlV_PSKX-MHG8P~e!;^BF`AKlZLe2^)fhjT6+_?HtuV^;ETR#RY-0cmA*O5>;*uByKE4UJ>Xjh`-K$gBkLc(4SSyb_`e_FD2%Ugttmxj2mQ4k`X^$55Gc2E;)PY_Y zZ)P^U%EV=X-gL&AKwZ)*9KXxu#HV|$;2)q)OpU&AnYX+qRV+EGn%fo-)zAQMv3Qzz zoj;I}R&sH1Jx!Z-+y|S&PNZQS%eOZeayWM~u6SnSINIHQlAU_pK1G|IX8ZV5x11Aw zO5hYiDVS*M^U35KXe*8nkh}WB^EL1JBj?O>Oq*kxf*BAO1#zibS3*2PjCE5luUz%8 z-#4uSw7+5cB&Ge)Z*0J%yXWo>`HQP(Zx#u%$9%z*u>qRhMkqX#j z!FpbY*=P{m8ykbW1>0@nkGQqH#ntzz0p zZN{sZp)P-IACZMcrN4`Ew;inD``_oa(MWi2VS_2wybn23D>yix5)rX(O;KqPwCLZd zxUt5W?P4Muoad~6F_zj=4+vt-T_4~5`l22y>=mi7W&0t+a0R|PiPOCNAiPX#Gzh5?VockW{PHf7Q=4^*QJuhhAXe$(2Y=Nw$%tJD1Tu*GlxN@;_5yOATdZw5kU8E__KB$h>4e(vX%|dbssY z)$%xY?pa84+3X`(5q^(yRKDJ+idXuWSN^Q_v%Z;kp@84neU>A=-?X0bL4}`yqIN_A z-X-UHw0C1@64o^6>A~c5!=BgJf7DnfE2jINdmACt#4hQ~i+l$hS8epQ-gsUZnCxhf zU%D;|yyCnw24GVy7at1Q*qUY1WPucfvrgs?Ym^l2YBNusT^etMDU$dNom` z;(c)i?wp_;IiD>o46(M#=OC`(#b|qTvX>)2tFKEVPcfr&d&0RGjzbnw%*{SLKm;hz z4|Gh6n38_-+10Kl+b#HBLr%lp+EvenFPJObW=!4C02cB zrZhfy`qc>`yU^rktp+}gNVnYnQ(u-wVzcWyuV(hM+d!TN4cwh)AXp(qEC*OEng0#W zpIouKaGxBD*ciO%#|!Yu6b%ebI?bhM(!K+BGd>D&gY-a8eq|fCtgoy#f&5*%ZC2eZ zowA7)(uXXJ9rf2GB`z6qiA|5dJ}wOC;7+~!1`x6NiwkT0$IKp`^5-!a1+XQhHK@=M zLv_Rg*qx9*CzdK`c43RIykO20jB^vs66($5WSw03>>(o7ZD8_^@Thg23w4NuH>P9& zQ(#xKs2?qqzHETfRI9@qA%D)nKE~P?%gb<=pC?z}cy>LF={&&baji$AP}Z^wV!WlC zbxoRwBrwhP^~@uossiYNg;IFGOSxI{${ksv(cin_OE+H8z@i&H!=Oz>&yR_5kZ-dI zzBkJXQs*&~$2fsIi7aN=3vx) zrWt`8*a>PCqhxAppY?uY^o1V`IYgs=a*qvy$nwWu=8%;Xc}2Hejud zuiukCu`~Lzj5^-?ho`*+hq1{D77M9y&oH-5pSk_Ek&BhFpTG6W-U)P2#P1;cRs#YO z0;^4H(I;IozJ1cdqMC>4q~?0}t2M2`Hb8!d-kw0{_E}U#M=GTGcFJA>OQbf-;qPJ; z!BRTbw}5l3VdVg=opiCdR*g@0@6vG}p(%&r++ZoMX(?zk8{GWqg8P zEqV~OT08b8PBAV}4IU$f=$#yv^)hgBIly}~PCH?9-N~uA(7yJXA*%Pdd}MKp(Ts0K z%a-FlPvD%uz&>|~V89mIuoC(orEb%!S5E2NJYvOwgYP9AV&|C0i9V04U?(Mx<*~=cf%#ZXk+50PXTzgJhD38H1 z!0>2;+POFwNXN}q1u{_x6v|@cW5^rGTncE| zANDi3VTX@7Pf!pLDoibQefG(^^C6oEJ}=#VSast41T}#feP>oYOVeV|vQfujnJIv| z;j}1;vC#@VHP`eP3-6Drzc5D+zJCM_QcwhsaHaI45x(1qm9gR>q10TT9?4^^cRLl9 zH-yJRo|#`6jjFTPXT9RnA@yU#?^a$IoH3-9D?53eV&TKXkbD=+3nq-@?N+4jf*@Vo zqk|zoM#0MBhM5X$&#>;A>o;VY+(?>MkNwFUtl(n#ZTM`Cd+3hsOJ#r7d+eCcFVnT! zLqw%e3Ht&pLc;Q#WqH3iQ)0K7WomFuG<~);H)+&Yj{)D8Ftxf2o`3q5#^I;9D!x&< z@ci0@SmN~-(hpOk%*8=uazE@53PbU>+O||K4&Q?jcKEY1=kvb8{islg!8H}iqgHnL zZAeBg779Y3j-T)%c|V_ir7IU`ntcACZTAl@YqOxH^*1N*=R>LUSq1pB!s+tjvZ+BD z=sE-n+s&+!a`v-j7M-?Y2*1@dpjo6Mi&H0M@koTnwh@gK3&lQxeZruR^POhUW9Pls z7~_7olih`+$E#2DFBG{2Up^2SPa|9624v{jtB~8iy11 z4f|r5y#LKH@-v5I!A2=5j)KI36Hldn;p4d7ekmwxmp_8^u+OlkRAi=0due6KYqR_G zsPp0VSS>I1&0VtJHn#$rHiz!Ch1bbAq8a3r2o^Vl=pYz}MKN z3TtKJcdh4pD0?60=@U;1ErB7my75jS%l^=Z?>3fBxfV`Oux)70?|x)7|4*MzF?Pf^ zctEUwW&ucOR`^zn<6jgnAzo(36!w2%kS#WI&nZ0~f@2b|Nx@GShEN)y>vTSRQY~`PH9(vuKH?We+HrV(Vbw zuXt`)Oh=p~pX)K-el>j5i^G4F25GyQhZ;vN0^>j-%o&PtlCZnf)4Qjs;e&xPlZ>9N z-x1H1I}V?o=KIqw6LhS@=1?#R*FEilA2P*6*9`~1EKLfA#t0Y~5a$dbS`q2!G;WnBA{!q9j zGjJyy;DhE!v|Q!Harhp}u1WB}vuX6S1ZoUDN_im`{M5qaVjF8dHFQ6xspBTZT>1ot=s&}{PjVJwd;9)ye`)uGWT@D-;S>f z*V5Mw{I2u8PkTgBrp-||H|V6gm$2rQ~d0Ws9;)YT|p7(Vphiesa|GW^jipzIdB$O`~SXIC;@;V`DeWuB3B8y_9 z(DcYgK`lpRYq5ry_R+UspfHa{h5cYZSC~cq&hb<@1u+Ov#4%(fIv8c({v8LagFM9n zZ#^NmEzWDy`GZKo1;0^+YvquW1Fp1_rzJd66VT z`mlFXiU}~PGFMns4UBIJ{*>7!hva2xyK$Ai+AXuY>*eHRCHiR)_(O4hU#IdoSX5bx z?dcsc?_WAjZb$g=ve;ZbBH6T)?fLYh%Wh`q^G-vu6$;yEbdfOsOO5wG>sd)$dkpkw z5?SqmiH=>T)P1zlwh{bZ)+u$2J2o>xQ8wE~eRsueb%@q*og~e#r6tn_#&c}&h;`VS zn96|bihnC>@l@Rn>CutVIJR@a*cOdQhe~I!!P;L9f$1gFJtW&fNcueN<4y-4o3M>~ z{v|%}EIS+lh zG|$fd*SqQ4syWyxT^jG~pR^oeO4OMK0^&1?ZtZK#=MBUL~$5;tdER<#b)T-kZtzk`}k)yi(_Ytrw#jkJqV6E+YXDprCsspVJL zz02<7yNTlU829dpYvYz5yF$>g;^3WUEmd`Huw)A(w}jfgFc)c5z1*2<$sGoTss19B zs^#+HDts4Ka`H4Qj&Iy_?k$Gt=x{92n!7f5Gq8$LxhS%b6070p=!pBR?Gn`B2GKEO zv9`S)>mbR8dO-ibg)5^afA*SWf|eTrmbKbldv~Dihtj~~rJonKf!v8BE$HO6W@UmG9YJL@AOU}gM;>+P;>Pkx+h&y!Q9urP>H_~j$ zIbaHwB|Bn$wMPh7ukqleq?tx-qy|E{XQ3+$7*>fW~PT(~6jVsxOMVrT|#Y?7o9_<1O`ffiZDz5zp&ZcJAN7 z6GPL>#p=cSr*2?VX`9Qz+?D3X&cW8p5iSWa^UFl>;9|r+m1nTyUze9wua}O$^}7j# zJd8MJudEnmL0A3s4Yna(y~&`5R_HXo>PMNx$PZd~cmm@wy-qk20R*B0Bebgxa-!aj zW!-r?0y9Z}E^NM-eqRB$!r@cGwcE6xc29+o z`^sI6=W>B;bGxU%O!BjWPJru~o~sDw!`XALXv!^;kdC_a_WW%0C>US9*IBLc?L6u$ z*^2u!0+O`KR5h;cbjap9pXtu+i^7kvZ1dizIIhdv&tA@4EqqyzCbdkY&iaDN_l8EM zY?OZIh8i5)pLxx6^TgYN6AiIK{LUUTb338Dh`*E5vBT~z#Q#cws`@_Sli_9CNtv^!OhopmbZy$ipRhI9*fK}WbV*{q$M2w(i>(YBoX*zJd$eIT{m^n|h4 zM(QH6(l*~4PBoD73W9Yp`A*ikh-h=dTgNrWvS!&@c-4(}AJ3foyOn=<3$tR4URXfq zr-3xG;$kDiYZWGR390KhzN-+txOy~V+tM9QWMG62z{6Oid4scL(qn!_LIRcwzoUWU z!!JOWYLh|{QU+sQ{*!;+z`f9I=iQ3l5PU{%5`hsWW$^W>g}*2g&vE3d9Iif$kp6&k zF>pVhQnThF$qp_5DXuC!?&N(k#Pr=O#Kir3b!#ezIKQyxsa870i&8^_Fawp}@}n~F zOYf!=YW=J!UN*W$ay0!wR zDF0b|#GUhG7zZqDyUV*Kb;<=gt|~wJIb3Ze#GJy3uYCmKEBKd>Tc)=u(M8>naMGS9 zx{sX3)c-9$%HNj5ZX#XN+MFVgxoB#3(?x9=xa~5K=(PQq@1gsxtcnptA;oqnI^}J* z|I6T_{;=uoa49Z!J!d+94(Y9*9~Fc2F?TFG=;;NSwr;=pa2uT zS%3||E%F87ZiGFs;QrYj$mI6tTGdj1)U?}*bso7OJ0vu5owW0;1wJMXClxk@N0v*= z&p0!G?N5+K(`c7N?KDr~DgLGP`ve=cAj56aZU#LeWy{LHgxGI%A`NnUAMo^|0brN& z`NmSBsF7nL(nO8b6zekDU0xL!*@TQ zhQ0;xShJu9ioiQ$#rnP|gjg^SG_#g9Exv;cvDlmSkU7lR*c9<_Q;umV7`My4U3ii8 zOm%6#DT-4^?hgJ*hcnLjeQO$qi|vnnjQ!^5{tx`0xjMz4g{*1Ra$4!2$I)w%PYZmwtsQ2&dl5UYczo9y zmA{sY9TeJwSIC6qCgN>>xp@FY@tV_S!<#%)Ah$Ki5cnkn=$YjbUs}DPwzo8DO9m*} zc5`Ds2SBtlRs@$lKNiS`B`k^kgUzc1(yT`a>^XDodI-b+km2_DXk<#l)aU*jzL`DW zd36t+;+NHF|9rZy^Li$QEr}IX)%j#=oSNLBPyBxp4qU&4>Z&n`C3qM}(knlRJ{8rTl-7JfGmhdWE%^O#M1mHK`uS+Xeq_KDmpUSz3bR&!NQ_Kq%Vpwr!}+P|Ak73w(k}vx*AZ zc%_J=Gh=$1h-3+(k-QekGT9wZeBv%X6@%L^V=iy~JU3KKSG|`HE9Q}W7Nd^Da}Pvl z3md*rPJsJnktmP;*+eA|ZQAkDrsNe@nQVPV1VycDvPg}ZZ*tr3L)=E8mE19@=of8L z*IhT@bscUo=hCc_?e*6~WfB07(;rQD=uegaS+JxK5EA^DY9f$OSKEFEi{oB_Pr%Ti z7ZHgUS=je8`x_kIkECk?w`b-mr|{oK?oy6UxS12+la+{1;?mc{&!keintVH;w%fWd zTuCh40dA#mhZHDF3Bq4+-^Hw3I0SuiU6Apd&r7U zccC{|TFu+lA;Crc`EqoN*Xd#?D$}S_`Yeiqd*f-@bHs&xY_FKP+_CcYBz=rTRQlLo zpO1bpM|NWdYriOBzrIf0t(prq=n2Qp+3gec+rHP>XT;yNjMU20$*E?fuAE zmCT}1{&YX+f8GG~yM`s6wpz-zOi#@`Sh^9OU{Rk$O! zkU|_rw#Ax$gFi<8->drPRXNW`^uspnxg>8i{O=#`MPUahEbyVW)2FKr2xKMaA(aY) z_9S!cZErJnVL|jbf$pcqn6aHWpg+{wL{d-R*n2$e1_bNcJ0NJ=ZJDgMm9T`iOm2Pe zlaNS!Hw0tF6 z8DCtfZgGdBRzCsA~J>Vcrp#|+7#hs_F_H_Nf6F3m^1etvwau}xt?z5LTp2z?uP z(w}(ayVn~bsuBH5{o&SkkKTFyG8SaK>?L^^IsZxLYP~ZNuvxw`ud4nVF_aTn^40$c zv+5YPQcAMb{d*t?kd$k%`3%O~to|HQx3+ZJi%_R*8UbB|1vOj)2o-e&zVJ;wA8gou&UlBgaQPO`BTcw7>muo5EuoF4Pdq=-sXV!645y(>C$YD*4p~Ha(a?lt(4l{>#J!zBJd#NI+us zwPXv7bt$JfQDwIo?Va2AfcL}=$5X$^gz-w^P~YHBV+ zoFyjxBs?9@LC=rE_{BXK$!#O7j-?)HYWK#ie6W(kGx!st!j{U^<^}P$(ooHM= ztYTwylc8P3=MyBOFjoggfmi%EzR=ytJ&eBNr;leS0zJAt%_wy~JDqfyeH77!S4({{ zj_xW>?Jfrf+Il1XER`$am~15&e<7OzxcjoGs2YuIImKfrn}{t?Fks}& z`fS00+8y9bw(yci_=iY|W%LL0Nu9xkmCbtJ#ml(rsY_39=U5F6<}Xq7^I5;Hja~Nz zVJN@NUVK3-btz_zMUh)-IUYbjc5M6Oc#0G(WYw^$pn*YfNFXmWlzakCA56U^B9q6W zmUpva`(HEIamV1QK$Le^G&aHctxw4jM>$&UD`b0IgS~~J4lqvx8-6uk4{bDN&H_;ZmN8gapm&Nv90$| zY-%(uIRk}1vH7RuhsRdp`Ly25Z2%61*Ld3-q&2u(o$iCSu;+~$8Qn;6=X4Q2I+h)0 z2z(qf4s?P&h}RMqi~S+GGop5Ll&Q*A{SRdEL>)=q7s$&~#!CmNUD3RY8x9Xpl`zNn z+ckTK>>~AIW~?A?D71W8?~jzCMY=!?qPid4o`;AA1xlaa2RzDC5)u4FW5Z%@nX8iFT#fHL`8!A#GXWuoe7q$+iBtA;3tBWBi_)B95VZt zhY0T`!yd)gZ6QIo^Rqsc8FZx9YiRKkUtcymBVWz(tOpR;zfLEZZfN^>smliR z2)ofvo;xt()9(=mo^vX|HWL|eL<|UP^t2gPJ70na9pVFCKt}DRl7F77fW{tfG%1EebTiR-I80+F@60pHyL2GF;r@XyOfwAdiy*CQD}4~z zvjQnuX&qCj%b#Z<&|*oXt1cP^0X@{@r=bJw4ITsjl1amBw*S*4ze;s2IqnwnCv`)h zQC5d5dN8sY?Kgs#kB0jhj>(2cp}QG?*6rLNb*W7CCTqK_nMDX7E`)bk2)+N3gqRTr z8`cWsv&0@SKx~FKu11=7I}|slo9VAvZwv#%8U0t`dG^2fRk&Cdk)r-tC??mDdTNAD zzuYogM}tmejIQU$zD_3eK=%zeb+g*eCFS*2zH48g7#ubW zx4KO(W}HUb)(hspivXjQ6m-qx=F8{0w;5(_l}aHp%!1z~odW_vY1M+mt8wM|Z^w$| ziayfvZe9Dwe|x7_D~*}Shvz=aq@CZTVNS^-_07jicK|tZONLu#5P437+3mX+xWCymw;3c*PomPzy?(f_*L{=EybPPVTU^;_l- zdX*N=C- z-NH_di4}|TnqL}Ev6>9Xf?s5(;xL1t*Ej7pu6QB;oHSYtg@8E4y&RN#JKqBETurrq z(ZugI)WiFMY)@ZNVeqI^gjtdiua4s}Y#Mv@PBU3_6*vcEMJLCrle>0bBKjH2adI0& ztgxj?0>-fBUz=ja$(|RDY|!Vtcc@pR64E#7#plQR7;aYUQ1o`Bij_?&JI|W$ZCI zR{d{R;D?^AYC*_2;5AmGP#B6T8Z+h_74@huvFcKHHu>#CK?>n{c~&noMO7Z2n6N+R zO4>x2T_v#ucWQ0nBpJxDx(l60d^&_5G`*(w{i_r5M*0ixudl98pPSadHHyr~BIT6L z+K>+kyua?Sudy2yt-gt}=?J|6I8Mv>-i!=PN>&y{x{J6CI7X#L?k9MIQZo;4a3@}E{nv7!#CB@ za5krtSRaJS6AjN1~Lnl^qWp?tkxVrGEO8RLjZAV3y zN!9MdtNihVSo%lcEp!)n8y5!RItA^{Q9CQuQ~_)b?14k~^oyj1_GM`%AENRBuJH)V z&oO|GAQ?P>zcT1uGaB?N8k}3geE?!_LOl;ZK?S3$49K71WA4 ztnQ_oqhL)@b!%m%)|?K4TQyzP3a3Q^InL zUH>_FVIe!ln03Vr;ZTfE-+BgNvrucO(y8UtW+@lzHUEO1@s z1b_eaEiosOhs`62@Tugj=ppb5>U&Thnq1>x%tU~mu`&7c>pDBeaN-!H>9Jj&PG(3n zN5h03NlmX`1QI#gDJx^n80Xh2Rq<$(sc7hk6lk<=H(v_xN9#*9F_a2@EnQhx5L5Yu zO^=9XV|Yuo`O`nm`k$&F6MaE1hHAkG$*ay8uQ(vmV@<2Es3~Y1$HW&s8sS_aYI5aS zW9&{2BAg}2cgZg!v36f8XAY?Rh!b0ZZ}Q033UAvL3!yDBAVS+fUKcQr3cAqw)w;Vd zsYzoN6|6#9^0HnhCNL^!;C5llqB+fWPBmjht8cZaknS=wk#RSEB3-!C%1a1%;ST1K zjgV!E$CeG1=2SNrF%X^5##H`XNq0SGWhz6d<(sdR%W%Uq0{{AkNw_^v zf7>9t!25)o!HPR)ombuGzunr!{Elm@Q`PubRz27NFxfc%1HA-ie!`mHf(Nw}vEOIv z@S0sK{lrZxv;TD+^|`DsF1gLpy)61H-kLj8U&^h3gMWLV%2$b&4+f{}{21T(Cdn5e zK`fYz(;TB{-Kgl)`iO9a)7;@rt(8PiOPTKdQ zl7bfUw|Mu%yEZSZRD%|yb>4IJsTRXw+((kPUmFr4kbd8MD;1Fe4n;;%t>Hwfh0Y;n z>04Csh9yU8l1mrJZ*fl;F}vbbCo?6o3;$)7$FD2eKNGh39NB=nR(elK{^s&%Dn%MwA%}Ui%3)@)l_e2UMV)ZY` zl@rKrPR3T7b5&F|<-G`t>r8Y7Zkq|S$HTxjM%dzcT6n#(b1*_yDDur>MTaGdPBiBv zT{R33^at%|s4U*+o3`3mTYF;C>5r(=B-0;O$^qnrkunaa*0JlA<5IScGU={w%V_Cz zUfmaC+#vgQc|kD`C+=D>AfrN=j6-36v^Md&MTH2y&nRB&fb=-O%8MKztl%$9Shm%_ zx-cFD6_`=GEj)2U_X}hwu4=yq04t-e?|8snIeq*(Uwupj{-q;**j)?c6|sECK+;P7 z0iGbybaU{NIx}_C&vQ$!fV?ySOZM}svkigb?o}gaQE+pv2V=n?pX_^447JukY0yu0 zHIg>kj2hNZEvY!?AHw6ZI5GSnB6hXBSvwj+E6H#3?;)b8^xS^1Z$FP}e!MwCwpCIZ z&VD~s_bf<%mUzD-u;k%K8zKq)KP^Bbvx?|XB(e9m(=ZCdgwl-uuNclueYf?zyK0cz zBCU`adg;2yV_F@-80$e|tEOR^wX2ll?O(jhy|U(DSLWMB>2!h9vUZ}_Pv&ncH-#e! zk&6%p)+7byd`+UG@g9+`M2LgKk`CXNNMd~=e}ylL5khBc-vxH? ze5YzGjb#>@TYNrU&4{-F@vWiE9(x*gO5fX8N&-^C;rD#;6(`Qx#&z$xYr*H)S{7n< z-_%$z^sIF$`5e72C-(ZQ{N!RQPK|FU+jGk6zK-T%SyaDnOT^6-zPlZjePREKQTLb$ z6mg0CvEhf)m#HMvl$BsGTxbW+iD| z;RNX1A3&Bj%g|9%_}8-i=f$!?=RnaHt(8c3e&X77eB{(QGalX71&7?4G>8JEhz|-trZysJ{9{;ki z6_Gp;*@wBqzMs-j^$~WJQ(lq?LA7U*v!~?M^Ozm-v}HqIRea##%kOf&n@vP5O#_E@ z1W?+kZ9sr`0_Lc(Bc<6memHj>Itjq^Xn2yY!i?@>3+X2f#)Bg>IgZ8Q=(qp&hb$fy z5(*v_hL6Y=4AN=Bz=RsLAkB(>gn@x?tzYWCmNY&pv6*nWfYT`;1iH30xsr zeHE1aJVvqiiY0<^=A(r2sQuk@g$q+G3OJ`dx;Z%c84+?E*QI6iG*69FCE$r!y38LE zrTot$N{$SGMeWaMyonvipI>-Zpn97W*Fs_S1#1vhkXdx^OMFbl28yS`H)S0|sUY^c zJN3{;HqqXRP`B9Q=Osu++g8rKhQF4Y){0VvU>$PW*Av+1Kyg2-3VsDnfOHpX6_arF zMEvk=N&twMVKB?LRO_ADG={qdzBS#=5=C{1bI}-9X5iv{J0c*;#nfW(9{ufWP zU`=n9tfH|GC3CndXv{|aMpPI^=sv?i=cwWsM6+TtbCm_i_kkRdL+;i8%?D&W`1mndP7K`SoDEcAf|Jt z-!LDx8=c8Sr*+hP4aWp=a;hm zUt%n=hBe+u{h?7|Mb++=F}Os1N;q6W(|$zP9}Ehj+9Bj z_yIKUat554#SG<0aA?E-Ol9AaF-=_Hr+ z_sCKQ*8@8%F?%qs$EeSAcCxSoXaC0US}M*AYs*cON`r^pcoZ{~;BTH2Rkc)@SZQt@ z%_lo3qBZW8GLrsoE9W};c(u$E^%bLikz?!lz76&#v?Mg~;2!nl;lCW}MH9r3LkTL^ z8ApmPZOBhgmwTp7AzKfvzdn33U*9juw=VP9lDG;fO0#&<5fr|rAc_Jdm9i03Gd`*1 zj5OQ-$!s%FXRs5cz*4$z^8CnX=-!J~eYTfzrBfg{)&Olh`TO*d^QwHZ9Lq=QP9{LJ z=SnQbf`qGs?#%D~fglH(L{^oGW5s>+(B8wZze#{DNxj4niM;Vp9oTty)&R}X5Kp+a z{2S9<=JXX2o=QSO^GqpRr~iH4#+Uh848OHb&G-nIJW@|wAE4(XGUS6a8-L!FbeX+j zN`z0W^5abJbMz-E*C}$lWkAi<*2q|5rz)O;C$X$!>-Z_UcZoKAWpTr;XXQgA9RNzv zV8WYw<*`vhkL2#0NG45`Qr=~BvPojsQQI5u?{_*4ABLt5*#fm0M6(ubNAI<45Zrj zh#;v?%>V*^0fuB|5pPy-b>9|eLq_m5@y#s-g0$Zt_A=&>3xn(r<+nX94sWASbWtf3 zw&mY$c2?iAt(_wogi$L2(hqG+VLq1`eONgZyNs_EQLrU@ivK1YWITfZA6MtVUT3$i z?abItW81cE+eVW#R%6>qW7}*RJB``cw(aDbeb-vw+I#q6+;Ayimu0QCjq3q%#*-R%0Nf-HlB{=uqZE2Wkg z9$nPPb+=h4jkl@(YF*N;rn7;L{0EjzVdu1!&*JRP1M{4-?S}Xr-(9j}fvek;PC7Lg&xE zNPw~gx)MH>2t-PqWMOAFtbF3oFV?FGek?LHqk3u+$i&#A9Ir0NA$-F^7`1{)ZQ-^E z$aD$FLkT%q_s!;;gzgO9CTT>15FQtdJ{{k|T5FMrV%aYO8t_`?$=6~r3^}#}10I7X z?7mxOswiwckX7l`G1Z%|oq{3{z=%P*0o$(OEihqGu|sJ=p97-nYDjAzT?i8zE0o!$QCV@kQA&^CfZ2rBLxNHm zv$2{&46?T48Vt0|ksd~ugMChTzpBndMh@SLn4rSbWF~n{`Xe|ViaeBa6Y9l}10k(- z3X7(q@KUuuMEWIxbqw%-(5UK?^8A9Ex&<2X`!_Z=K0Y?~u0_B-jTO(8ED5ZoYJS} zy%S9u;KM_dP@7w>xzu2(K76L{S_n$YloTtALFNuFdImW+3e;x`S`ua@%1=coPT2#` z1>`}*w5|uNr3D35Oz946b>PTlncvu~fa9=ICVC!V@-5XuNs9;33mf zFZ=h18M3D&L*#mYm56t9X&L|Eh~{7-zDZ_6r$#6YAtUH>#}cW7aeDHV19F>TSwrY2 z@oj3@$sXzs8Vf$ahf&60dp@)M zx9obu67kX7=jT?^FpgErG8@l@cRif zb7U0*;hs2Z(&FWrF3>RNN4_w|2)a+64W6_8$F}VV;~oIH;s3_zAL8#w^q1`4dn3DE6uOI!%ni z`^yymb02=t%xdC~O`6im6g|qUbGgMN72=X<5Q zWj;i;>7}#OR#?tmt9XW%18S{|Q!d0kI$HiNhZ+7cPJ_D7aE73q|78g*02=*37AEh# zI=x%nHh_g?%hs$2G-0rKs%=fZnu~eLPX0vnnCq)Z1GHK){A{x8S3u(gTed~g8KZ~! zb0~>MiFM%R_b&1u_n0UkBST*HFww%lb{S0?k+xtISzy?e+4;Oy)x4+W}Fq#ca z7_&PK6fwo=zH)UXUmSS~{6Q11`WX@F$Z`#@fQ69_8OF4Mhd{zoObMuHM|&t9_g!mymiRqI|vOEe{(9-n++9Aza% zL|B+d%nb~s` z%6`Nk+2`uvKc+7LeHV^z#Nzz(8yH3)ht~=(vaHK_*DVBU3o}4zJnMK$P*fg732-&E z+puSZvfompbB1vpls-NjqwjrLU9QwOv;yO-XHaK8oDsoCs3g{Ws{-x2t6sI9$A8*4INc9By@2;2t&Z)vy_4F$ zDm$7Kkq|C#!8U8Cu2d^5Bh0(^B^bGQ4F$A3XpFm5&aAl>>FqND16ZBqwW`_)#T0*T zpB{IG45lXVtdITYa(Lwt`P=t?0{L4w#MnFc?!$U2OZ0V$J2SZp|G5sQn z?dcN}#OB*5zzZUC{`ip!Snp^`{01OQs`gKG5G!pndCy1sAas%r^s;)!!qQdudFnb- z7I}Xvu9l7(~%}2f0zjS1&;hT zhOh)M_rwO69SRW2!|Eian`iRJYW{%}MuDy;q#NjFU&K*$7y9u}Ri5i_Ri1rxE`Y~G z@ILpQ5*z!c;1^8Zl}^NPVw(ccJHrhx5~@OY?TlnPk}mWqXW&l7X)FT0~KW zGRUUdf~8w#$Rnf-f}aSJifak5CPaXTXr(L3rJ;_+sE33o{yn{4h-W=ey)(S2hzHZ$ zQ8t;0nv@K565}CBK=8#wq!AVAZG!iaTt&K0plKvo!P_x_4e$5j3kR*EpCKy>`&;---?0D?#!Cqz<)N zxnNFlb70vg3_=XT2jZ{kn)HNTnG-3AQ$wDac`VNB+<4$tT8tOUa*H&8FVO&^r5ToR zDhXQZ!bmKR6QrDW=&*`@HIDep%<2x5`kv#jBldQ&V1Y>^&a&SvnzqHG(kJ4X45JU? z_Je6Vv!_&tH-W25igj7gT^`9z65UKm%nkx*$UVui&>O0F^u9dVv@kxPi3qFR4vh?P zS#0w;WBmI2oS^#GbE2Qz@`jWskZc`_`)Q*yot-`0dMigi>0S*c$KuT@}_TO zW%+AJ6O#;!S6@QnBkJRRHSMKcOoZ2i_tNt z*cGbM&_$aB?w_5^H1neT@+(C+!3+o+KUxh_1e1uC`~8{|IfY2*nd98|5e6}MTnRB> z!rWjUnbwWA$y}2uy(mlbDJW>OGQSElY&=+0m2dtb-{ZDD5jhVR2(&zVM?XruNJDX9 zJ% z0w)p!ohv?dJuah6CuXZx{idV7@7v(|ju# z&P=GCi5#os29I!;Yp^#Bu5T9iDzcKrZ;OTLdJL`#F2WL8w97UhiBid28vb>>Aujp)b&YxPS^tM8 z%-SXf(AB-pA>~w3g0~1Dy995wo~7GMJA%n~!h(YRfum7M;{sqXultk~h_k~3`3+5c*Z=qk-EP)t8bpPbBF5cP zv6x6F;VY(ST+wnr3AE#F(jU&KAcbMu4FMwQe7^iFU78mbVGEjwOpFLZM!Oj_f0&P` za}V3&k~KHgl?8Iri|v zEwR$tGB7YITLQU|IP5%RY#D$tA&po%#RJ^#sPC)3KIq<<&M!?)#=c!Z4}a2v+u2!8 z6?*22#|=qMA_Ehic{B|6;ZvhPy$4;0@PZc0m6tkIdc$4L;nH&kQ2ZQ{RzQM?ZgjsiV6ZGewIhqC3}Q9wI8M5|SjUZF zd4|36Jl}~;B)B(G96e@Y0?{4eal15)x}edu)c#yC>^%a3ZFldF`XcaN{M_Efu&7Ty z6qkrpZ7**jy}4qTRgLkTOgMRw7eR<>i3rkWkcnGZ#5%baZKmAomx!5{S7u3qsNZ(7 z)LKouT@$n9CozfmNc7Cknuni{>t!Nb-229>!rSO7q~xN_QbnGfMl%ggyLBq8tqj?Z zWlJ|OwlPj!ETz{n38n(rTcHHcZ91JSO>szIYp=?z2u#a%41WhNc&(i6eh#?D zQMsuWg0ke@4l^8+wdT$wG{TYma7jU#x}E%fR)0Cm#=;AoQq6;D%wJl~L*D$rxx9Y@ zKFYj)`qXUK`Y~R;Na(XUbfEZcph4D>`8vxhn0#VsS-mopfpNitR+knN6Od}InWX-a zr8B{0O;(nKa$ZAsj!>cq;C3OZhz7%Z1!*y33C{wd%GwIvZ(%`f;o9Odf^?=vqnp(^ zGq(ng>?;3A1?54?TY|5t%qasz*a&hxQG4A2n4&%qaoPePtk{;Qyx|7wV$zBUq*9Pa zLv+qNC4#q&Ov=-YgzD6=NzhZm=+g=q`@~h?4fwj36unWoF9jx6I5HwXWyH(rvBA(1 zhpC|>zW$t+kcTLSKXkDeqg#IF7*t2@Iz7bP`#gBA^t)c3@_RqsEc*Jrj%0*AMIXM! z;3KZiSEQ~=!TX&1W1Gwa8nU+gve225)5)eU@+M-4?$o@jGv2*QLi1Ob0<^WXe{RW@ zDI|MwI{vBI-DiaJLbq)D(L7tRp6rrr8DgdPnE1cHDSUcWM;Rd!tOk zh6C}{q0(_!T{exqZ}?S;&3Z1p4ZH3kI`-sHq^5oGzs^91&9L;K7vG@9Z&R#%9^Qh` z=tANxZ4&-76vF{0I5Er#ViAKHotZ;^rqr}bV-F0xku7eOWIG;6KEBcG!dK1?tB;ym z+E7g9#j2h_6nYrqUqbhSHpG6K@54=R=VAT?4J0 zzF^S@8#T&O4(a^y6VL(=(Y_Kbc6}|R7kI-`OD$oXQ<<#cRCt9|XVR}RZHtZo^?>x2h?mj zwmxXmNF-VCd6;0|Avi%YQ&=v1!P+p*rM9jyaj$)F~`Be(+V15CR(AUF}u zIqMCvUL}3jXX=2gE(*i0BBStv+~S@i-1WgFM=&+?KU%=etzakD1|o@deOWpvq}OyZ zdPG%@bDGml3yHRF#%Y#w@-v2{sf*P(Qtt#-{sK}EF#|Z;kF-2$UbuAlXt`rROa){l zi1nZOe8pdIF*LXHKLV%rlCitpfp0m5apE$73r-tsnqs^gA&-Ps%CLDnEp~9-WIUK@ zt^i^(!glHJc1ye~`T8QM74>ey zhTx(wag7eoHVJ{nWhwB1*rA2dgDLvIF>`U~uK`d{?fr-(nIVsmZ^9 zJl&4%hV79+aYK2qK>QW)d}OQS(!6xNxEQ3bXzbQ5jK=*tSgM9g^eauiP~-19t)!iX zHBHBPA2VrDjm;J#&7|Gco z0JYxPa(gotDqEWZr7}07ze(Ig(x)BfXg>Ir@De=xQrQe~emb+!b?5p$KMx4|-}fs~ zsYLi4lL43!B?%)4YkhwUkcD?;h%oDD6&nHNV}y5#0?-oyw}IT8VB=t`iEMR~2RS4S z(&Y{pr=yV!M(Bh~Bb@mIB{)f`s2$%D2=HqE$^sdYPll95;wK{>p$#-@#ryq|u5I1V z(9&=7zL8*`O{VyawOgCHaglrVECy>c<>BZ<@U$m3?ALAz`gsQF@#WV*@0KGsMo|Vf z3*`JzO0$Y8&2QTfs`4ylcBfc~7lo9E#FQ@UK(iZkB#Kl~1t$3UcZJFuN+swxwsiK4 zNW@OlVH`JAyf6RaQT}Cb`}W9B<|nI?4wQi?VH+ZNJ!;e$3~lBM!}uofK<%%>EalU9 z7fPZ8LJX_a4AZem85EANVLW56Dz95=LNfrZ`eE8pl#Is^X}PW!;JEV_+GgtmB$Yu8 zEtIPny)`v;NA#{zT)%%KMTFU6w*m-nrH1Og@HJbQFj}(4%qGRJ*nq*<_(AA5AxRhh zhS11^6y4T^s1mBCikVqEj@i9@c~k9vTj*V}u8R}f+%8R}I`7u~5zh& zrO20nVXALb2HRyX;Zpe25No^OFvpV`;Rs_QQ^SVpncqSo2B!laVImH=xR1T3<(9e& z(bYgm^glUdU<@DMp-@6dFGvR78JnnK{bzF4Nn!jR6s>n&QxRQjL6pQO@~~A*Y2EJ-6pXC zPork$usYSi{UGHuw)1lL7B@3GCL1gC!E6%(y`^@n%i8>xCoFq^nwAYRXn6z!YngkG zQ1szXIV0)Tv1y?F>1IF5C4?pcmOFtx1o(#Mq$U&k28^)949-~q|F!0*{vhIj6-2QS zN&avHc?X-pn46g=3Ni&NP=sx*tgB~PS;+t?#1z2A3 zq8ZRs^K@xXlpy&pSP7<*&Ah$#9hw!k%Be?u}f%T@y(or$&WV(%$LxTJc0`hsR?gTx{2+skgOg zOtY;F;GzxmccQyQ|9%0%U7@TkeNYODD|KrQIkMH9N916Vg%oJHQUMoY8Iu)>(uD?1 zATwqe0?8tuY>Ese(ERaEYjRbwWqwR2rw=Lb0`6C_vg*Laxm{Sme*K|R#Fv|!%iGXV z)SVn9_5FVd`|^1_8>|9^zPH>bRE1$svYqCozIUmP>yJhEKTx5OTxA9mC99;Jdc1h< z*?g0k`*EVL3!~2iLZuYD`k_2F$g!l?P6BBZ8-_R(ofTN#khd@9PCKP^9vu zhkxwCRpln)D4?)%uisa}IZc2Lx;boVF>Y5T=L^tYkGn!&FMGd_#dV*)(;9xP44&H2 z?|l9K2=ozi2=NCzor%81Vrt|qD1OP7^-tP<_LOlN&C{RCm%+}81-zOKlv(`H+jVg~ z=xWY3Wekg-zH85Xjfb%Bp{%FM!|Q(5qG}-Z zcJMF!vbpA6`>*PV$W%Kfj}gr0v5SDXlJ1gFn%kSXDyg8NGPpr9W0xl6C^Rx;bi`L> ztiqAwIV)K5izOme)yfpvjjw6rm<2mQ@$C%2q99e~j~}K!sA?8Uaj6Pj=Lm((MnQ zfqOQ746vWd8Tb>wsajTop41V5>$&J?(Q23UZ_efX9eomJ-9&BXps5}asVUoRhft6d z`?Xt>I0c5ElqB8Ta$VoJU_;%q5%`~I3t6)f*w)<(L`Z|O7?^l+E#f}OKlb2+!AyW| z;e;V9oHjY@rJ=9%JgVChd4fc3AdXua;S$UuhqPgbo$avRmy;{QE}J)joZp7zefK(i z+g|=@!fw|^X~JW4`_e2!r`bto)}cQyiiG@U;kHv2nBd3l@T6LSd}^V22D9bzXt0{E zESz4NE{?xwocL>h271S8d13!N+JMpYqm}>;0RI1^2g!SUKuAw1>`apINrD2yT@0X9 zEh1WK$?|CQf)2^IBtoIVEF-ETGseRo=N6d8{a>XU1InA%F_yzn8lR4a-vLp(l$!TVx3SzcSNwh znL$mb8JeeGpvh5w1E-bXPc^RY;t-oZFz0dL&o=7rxkQ-zY5lYlLQ*Bb>_)rwxG-yG z&4P*}3;fK%7LPB9k##`a-AOt-dJJ)z@SfAY32)ocs}48f9Xu}neb?VgX20-mcQD#! z(ij65DR3e{%wBgYkr%`Iz>XAq7IZRfeR5mx1bf4Gr%X);d8FRPXCht###GzL(O2IBaAI6)-k!8U;)re~AtJMw_QEe(r z`W;4i`=i8!rP6}I1;b*v*%K7!t0$y$F***rg#xiDB)8hJnA6)n7qa@ijt%wUH|HYBVf9dEsHm->G9llPiq^{y4m6#7nTrN8A17_F(RFccP(OaZ)di?n%mB6Pxq zx=Zjlul>h9l%jq!+{`h-)hSMV^22qcb8udI!bM{Z;@o1U6^gMK-EP?bvOJ<*g+sN5lKJF^+UJ3wT z9jTcH)0+dz$?^@GMcjpwMRR8E7-jf|bwgs3uQV`;ya*)QslvK0EUWBmOD#mkcbg9B zt3OsrMxaZJMHcC1+Z-V<2xdFTx!%NM(`8U+OuGZvYG5C9y-HdLkXT}6UQSOxHbo{G zo=fmZO21eUvB5`Q2RpRG<8;SSnk88so*aJby!$;Q_!RLRLq98zH5D0_VGheK+5}HA z1zdL(zNSlq1z{Ez-XsYii+#ga-+(FQIia3i1Buoh@_gs=cg!Kdey8SMV}6ZhSHjCz z`Kb&X2Z7oc-oJ+fp$m8i)t}_&<>~P_5F%snQ@} zoxxaqg?*704uZ+s#jx4?Bi|w`IDJ(r_pgGHx zyJSYLb>*Y|>^k>;w__T5oPiM@&SoO}AvoAWnodB^A<7Tu#V@oUOceK>z&#UV^eB?# zbPFOduKyy>= zq4c;hae3SR=Y{5Y-`K|leLL^}C4>U(Kn0WoAX-7ppN=FJFdbZcPs)#o#tU6<+`|U} zhUnYCU=ZV0@r@?fa=?E(6i;{aBYly6Iz~s=Av0k9^N+1fO)(Vv{U6dNo>>`Haio(AHn&^~iGncK$0> z1{TUwd0+Vt&kXh>ScyPRLddSy*H6t@FI6dQ+K~WM{WNVL;{E-k&#8^$bOT=kImtdsO;N|(Mx6{kq8cDU~H)?t11w@nj z@`0$~tzN0bX4CJ35E#w9>>dBn0!~kIZ_S_3y6@+KbMg`il{jR3qYfnZ*;6Kq-H(2U z^$9yw=rMSO8tjQYx1i%rB?R=Y`68{4|Zpvw6JS z1o>vKMVi#D&|~j)6x3aAptr>J@m>QNx8$ zDHRJB)=GrO*YXS*B?L!j>Mw)Jv15r$&yFLftFansqbR0^0#9~>$Ly)8sY}IkUa$67 zXI;v02ErV{&k-p5F8j=~w6cfUhxF{-_RRHXcEvUKw=Pu|bZD5B7kqX(dW)Y2#0oC zyyaagFcYX}ULm9(3PnaaTTzBYU?nMA?39Sa32_GHw@9y(h)gTCy5s8n9iyUc7PD(H z%L=fnVf|78VNuj7a-#!5sKl_blTxStxGr9{ny1W~I6U9;^s;t5G4o-C_uM%c%@ekA z-vgf0`!t_*)ywa>^-dxplR^JABGph1 zDnF^Tx!YkeX#IJthU?)Z6|d@fSJ7_GXVY~3`Lu@baN*R_`a{zlDQEN$s1!m55odI) z|DA}9<3*u*{QL6);^vM`J^$8u&7G{t#8ekIVqOwWjMl+4Rugm4;uhD6JH1M+zchDg z$mR0lFr02a2YYrJ=^xR|(m7x`{L1}fSH-?sAkqJ1+rJ0H_47#c#FYT1(HkWjx%hO< z?_&hmN&3Nvji-ND5yz3On5%}~e@5fHKqQ8Q*vJx@bXaxaU7&|Y9iHqSR!ohqxub&M zz?rWUu)Kz)xaIEYL`IUL*mPfPg>GzZL*lCx=I{WbGl#AR>(uR5j~yMpNlT zthZsa62hO-FCy^HRWGhYbX6L}y-qefXdV&|?$WXOQh!K{D)qmNDo0S!75~WNt@S=W zx%3n2dWqR4Pey&5 zhp#ZA$W2IY2Wm9Sw~9r6@53{l5QwKjEoodxZjUvqz8$=ud*#KC{2o<(=p(*f%d0EC z^OF%5C%J;HZ$n6U#X-{-$E}=KH%T$%8dJ8BfQVy)T@EahX8fY)@a!RPG^nMb#mzTSWdbI{CA za@khS&})>(mv>qFGkDY6@*$K=61DouSLcbje#susEx5JFc@-0lw?8^HV?hE6iVE&Rx z|5ZLf1ha73)p^%@_3l#6`5P+&_AXf>vz~CA_(HW?Y=xm*ob7m*%Vya+%Jw(rE?%R<2cJ*Cn26=sBM4XH!0JI7Bi?c zJErhcR_4Ua7}-W>@P-1$|E!~yKQ`#$WAOUmw1tOPujle1hKFB9{qGKY zh9Li$S%Ca3Ae6~^FPvJ@;7y>#Ek3z;Vj)zO}iDM&p~0c5t17if!bt=6vs6R)8}uwh)1&_2Qt^ zEO`vM1E+s6!h%{7P#(ZRL>mG$gv;YYDS6o~uI|nqVM_!8>o;(JG4v8LiKTAf zigW3Y7Z~fLBsCW?SugdL4_Ovwkm-q&pFJ8}G+4!1*VMc|7Z`FA2L40rT)$4D^yefl zOzLwPJW8ot?sSCIsef7Iw2Iujhel*pOM}DzrZa2#wpM}ih}F|cYD5~Ltzy)G*Bu6) zEwpOUSNk3#-CzE5!~bb6aRut@gK?7i1Sa;~{xJ(&6A3!`-tYj#YVY(5kA1VHb2Zdr z)|^Nd8zK=b?E`r)U&K~X==MMU)^FL%!4=}lp2Y{ZY{RXvz0F8Jq5Gr{10Q& znPV83INvA?Pc=4tiMtBl!b0ILYpEb&eF_!kqIKy1aqq3inUNj2Y(#jdxsW_hsmg7t z&)18o5L%EOi?*;8n0SUy4N}sajX4sIhuA2o%oW>%)jO(uSjc_MW_E93Y@J(_86tpj zruZWyy*Dl*IVhpOAi!kdM}6>tj=9cnYnk2r!a!tSe+zwa& zm!U8#inj2FI*gdsyQk9&Wu4lKP3A(iM#3`-2Aj)BYTYCldk{%?lh2MmL=M(N1ED{b zpg6Q}RpmkzSAD;7e{`lJW$_qg)F>B5$Kz`I_tbjV{h;RT_5D*!9YT~sJy7oZ4yNrE zWi)Yep%$)}yym_sa-SzRB2u3+wTCPgfWTx4+y^=EcA|W)>(}50lict%aw4w`5;Rg1_7nMeZ z9Cat2Uz(Wi;pzd&VuVye<{G%Hqn!sxALL0>35fW&mtrvp48H+e@ls2yVfQ#*NDDTf z=+0mga~JU9#Q@WO(;=?0C*@ur40cln`WfEw6Z{qU#72Z(cZeWS+M4{j4$LyUB*A=FSjFon@I?;tZ^UlHi0p1J56cgfH(_Y9zV9X8ZQm zUyI zd(%wntRB;yycV+Hz>7JJa+Ju_=www_;(7VR`IozjQ@MQ~m;bH=|2bw zdR8_gLvRAggqS%B{Lu<&{=BjVTyewLz7+sa*KdWzmpc|lhQ*I}smYhD18zB@8Kdqx z7wa}8;k!d=iZ8owV-7!O!Y~QHzm2c#Z<)zBRNdkzob7%^0LPPv>DmNI!l<5A@}bN! z?wOQy$795RB>O_5L0o=MR4VRtNr{Ev)Hy#GkOrL&w8)PuRsKyB04^dgODL@IlFMqO zaH-&RvxMLXO-3diJyLMBWPm(Rp25las%SD&V8c2|W(zsgxF)cM$wtxr4M%G=rX?y) z>8j6G!v_0#2!SUnR`m(J-RTVlZVK|i$I{)d{p;fjZ90g|usiL4v;fM5*0`7?;EuNK zHtRF8w97O0ifKEjO@b_s6FMz8S-fs>Uo*=q0VQ*fDV>FlUhoBZH!JqpKVmZVE6OkfOhOn; z!fb~_N;?nzw1|@A4ze{H5x`vG>5@=jWAKxH&Q%c+4&~2#1|2-IP?Trd zD*at#X(G)*^QY#X79$}h#Xh@2oUce&OzMwU7M3-q)?MJ`!`ViIrri!Dt||VnT!>qk z5=XxO7E9SS;6%IyAKxP_O8>2wCzldFZjN~1lJua@Xj8mDgpjJ~$#AA$C0Hk_lO%m( zVd}E=Q_V#d<64>U?H*4nl8%YxFa>wQ^JcQnGI0APxKt(ac$L&V#K43TS3lA!)lw7{ z84}#Nilg*v=|p?PUL;1)X8en>uZ0|_=5G2L%}&2YBD26j-R_iK+0fu6n@X8;*|$>W zYt{goN-d|Rifbjz<#w%IcLW-2v$-@|<0xL!IFqWtQc-wgQrPmFdJ)C%f4KY;=ht#j zC`NV~$)&l&bY71XXBML;8_~xur!287i%r6z)5Uul7>;6qhg z;b!7mD#Xf=ymX(ZEhpF9Nb&V&fuumLPjKy`Uk{qL=e5Dffnb5ge;)hgN5v}W;%kt$GbO{`#2kQ4K2i52R69{IhuqcwJ8LDjj6B=>K0c4jyy z%;oxw6J%+w7hj-f3&wlJED9KQ6}%WB!oXn;qAp|OhjGM%*5ZQpM@ME-5tsJCa~MCv z!e6K)KTHdP$7HVUPCN(R-Ms(0yAwgd8g+ktFq+iB=mC(UNFiZxM)`T8x~WK@wzfQ% zqp#5uF-`zW&{xVS^fd-!A=2cbr7Qa1x~&fG7-PTM5G}E%3)P;=zTb1oCh(HJKO;G~s+U@*|)8 zZTupLbN;Aqt4!qmIufv7^SHnAxCj%t1zzM$-EDmt2AAr9c+VJ>1$ZbQ6}UuKs+RRf z1un`($&pwBFa?Bb5v15t65HzXkN3EY>Vvp!cO$pQ-g`u#g-O<^Vf5FktT^?jJxt`u z`XATR(G)>MuOEnCqKFtEj@TA&VT1Ym2)GmyvBj4<&ag)hz6!$Q5iQIQ&KNFhF*Gp9 zXbCJz)gGedZ7o2%iGPIf59>cmD>@R0VX_L>!6K+}uXneu zpAj`?RBqoZ=p4%t1yJp+QNYPKYBU89 z;-9)WB2(ifNsFkmC=Z}TLtlLNU!2#?JsQtiJJlKRSXgYa)N)zi&lzj#SjPB%QflDX zoBOuEg8!J~{abz+vrizn6QJ0-!L9c=c0U=}KD3gN0X90N2u$q;7Z6cfw+kRD-B1;2 zgBJw64|6uY3O5^~5z4c(d$wNwJLUsa{QuH6WeN$HF9@$<>t{-z#Ew0IFX$`+MZRyB z8w1i$az76zLE0|PLDOe%lmjc ze6E|d>MM3RBccLtS~vY>af|G|mZ#_ScHl* z)l7;=X@qj^#B;oeVeFAG>_nwiztpICI%)y&^JUkp-u|v`qCjixGqQffh1MHXOLq$# zG`}f=DW%)imhfEf*~%{p_ExFW_*0^y?-9>@ojhBtScn*){)=q!y>S=}mjz=EAKSlOm|GrQR6gtA=3Py?f5nP5< zI|JAQ&-#f{bx0de0CgWv<8b&b4gmL-fc>J;0v9DPq`wB zu7nc!E-|Ttp%@B0!Dfi&fV%?wC)qV2ZBf63@~{tN;I5AVX!?Hle4QV(UF8RVF_ z2J|}aP=SrZ>HiD%7e?W`KO3V6QP@!Iw2=I ztwdH@_-8bHWt0>WsbE?nb4R)`p_pGKR-KnFz$k1S0~{rRb#icD+UAnChvw15t5EtGK;iQ#ih;J1%Da(#!WG|*rbM#|!}))6{d;YQ zZk#1xN`KXQ1Sjic%|``b|FS=&XpO z&+`=U;H8U&op@$f)?|61-dy|kw7pY|j^$6O7hBMMwv>ssI(qNR?cSODUZC|YqyXkd zWd!4WRgYmAm>C#oke(Bk^@k+UA{9x_wH65loS2%da^PtM`#c7P`VrV5u{24DE1``w zm<#*R^1O@4j+!h)mepictHpk$236o1D{^tg*>~+p8Vn$kwi>lE+LtotkhU?LBOGz8 zj03y4^pc|3nkZO?d2$C9KmMC_jKKj=4<^09^s7G#*KaU0T0X_Z$j7bF)o;D$@s9+5 zW{JE@Drgxb$fC2Q=9WB7no17dIHcF^9y2sFhG{Ru`7Uswa3$@Qpp1@L^v)nB#d2?I zY&JD{W{Baym%g1nYYN;<=)bLqvOeNw0|F5mL42xq67Itxm5PS#(2=4Cg?(XjH?(XjH?!nz%g9Z!k z5ZvKTviCmUx%YnaYduV}Y^uAfYE`|(objPY8p<&#V~<2-gp69qK40~5PkT!P)bcL@30BEC=LzsHgJyL8)Rek{LZ)Pq&g*St}qDJ@@HT=YAS?*Lg1(w4qlKZzbE zCu~Nk7^~i*CGc;7&K9$w1*X<4!#n{uy?9d0Fx~gBgkkrUgnD;%I;B}x2zDIF!+281 z+p$g7lFrhzam_k*tLwu{?s!j?q(0Z^flbMBfl@5+F#C93kWToP4*k?>2f=9FyR4afwX>4qJ@K%ftf>EeFJZ?`&*wTnBSD>8Ip> z1Nf;jl3i)KF;Nmjr58`eK@CtzQY|Higpe9mTEz5S317f4nxUjIoSadtf|kbQ)?=c* z@&tko8C7bi46xd?S{xSK%)Cqhe{CE6MZ@y8jPSIYeT;;G`j4wc^ zU`cw%mvi=yFVpL8y~CC@FGD4VW2LR&{X{!u*3K-i@yxjzx$u}W31>(ozi5Xd2f9Hu zDuG)2U^u1zv`Q-*p9Wt}Vxq{%f>m92`&+}8lpedoqrD8wx^CYorijQgLE{^2EzFEb z+T{H*#ra=Qw^pW6rMEtq1b0n6-?%0FECFL%dTJo8w!xMTVUqkPF364qK|&fo_x7w= zb3RJ(w0mw&OKW>9e8V6#YZ!ZG!hE2=wWh+oM`=Uj1bW`N_D3g5D%avBLex@n(|Trj zg3_xXVI&%{Ru{X`A0Wh^;tQ0q)O?ZgmfK}c{(I9yIFwZfm@UANJLliFoDVMch@E;M z-xsRCyL7zNntp=jr#GaG=#uX;sssI)&Q9#F_gdd|sn`XOB<#?ppfHiy&xF=#QVgY~ z#bWtiw6}6=8Q!iu5s%SOJcN}E_5tf(ystNk3O)BWIG!gvma+nao&g4FOfEdPXHRjD zjcp!XF9U|#qr8R;D_U?s`GvgDLo4!ET$<|l)0rOiHQw^9boUr~T=_;T+FiZG| zx#r>5T--(f5*zwC0$92sUNlG1cSLz`j<%Khiri>gx+B%wkO@HQ+cYKN=DRbyFkORcL(-}|5-<)vH|e`oC(c?BQhMmP3r8sJ&5&~ z^(&$l!6AR)P~naLTu`S`5(v}OYu5hfpNTtq_0CrifT(&# zpD>ivR~n=_*CoIDNS%CnRFvz2n6|z6-9s$vT~fQaQX^3HMy%zaCKa}YgpksdzJOd* z(`a5-FkSgJ(BVV_HQ3#;G_R;qjO43Ogl9J}U*bSLl?IUsM9JIs^1{XWv%Nge42#v^-Vjk5j3(_&Y|7GduJm9m-fE#MBfhB~2tZ^(0*=)h+Jn#Akk`P-}F3_qOe= zwOai!(%09s9@$bd!*DLE*AR{ek%5g6_gH#gieRp;uihCnz}9AXgC6iE_It5AxH7p> z`|Ws_ZTC%G8VN;YrOHWG<#Ty7_%tRf5=2_tOIka3`7(B88ljW+_%m(Ok0|1mzcB{! zKmIbT%1*yR;WB7VQ6Y#v-~s$nzBn3;tD^6gi#N+6G>jE?>gkD0V9kmel%md*ydd&0 z6v$f<&||H)7=7XeJfqit$AONd=JY90Amks^QX}A@!6pFXfr$83KAhEY6}lMfbk=1%w9Xp-r&OzxpdplgO*X9@ytc61Po}5c{qYTI2MA-ob%SQP_b|w-(v!D>$x0 zj{55E-T+EWYGrDb@sjy)AwZgI9}8($%vbdsn3wl?*9K(6xxOcInRnz8N5yz`S|&t| z$htK07G&nLjE}QCbFCuLL^ck-N>dj}dm10kxHpJW;ZN9Q;E4|<*76(NN(lhrO3FWz{+&%x9)fv00(mHOY|a6=zk-(DwVc)rS5v8-B?2 zPh-_CD{ZC`0^!1CDERM?#SBPssBz~REJ&khBZmiW`=bv3!aa+fd!on~Y{uNkp4eV$2)sbWMw-bVr3D@$CrUwXJOc1y=1jw6+zp#?WFgA#vI z-A5JQ`Kdd1oUFP@AeBzJmh1X@w?rapSO?)M49VIcMk*?1n6`@{oyfp|g*eaFn#nKz zj{n`)$@vDcrP}Arks%~V*$~iZ)d(Q4aF`{7_F&Z2vDR9r+4xFYk+yvBC3zgJF910c zKiRIq7`bzTd&s5jUYd?9DT`q4`GHyX2rk$y$Lr}1v-1OWgva;rw~?*$&=~^rLAGM_ zFYPupZxr(B@jeq<2e6#RL1dy*aXO@@26%qBhP95=JbUI?w;WJ&`>x!ANkBy1ztrQu zYJ&L!rxiEeZUxW^Xzh<-5Gd82iJ@4aVWcbDy9m9vbirE$ahYG0EU^n;Bmz?UA8gk7 z$SDF>VfBT(C*KE`)oWNxMw7I>9J1J}GAB*xbC5my>q-&ohoJe`Nf3}L)sq;%EE!j1 zT&->zW1ef>1O$hEoszLz3MOEN4ilhhojrou;c1W%zcM1_N&Vt3uM&)7k({`bmjQ49 z@kkVj0T3-7q0}-fj^#ND3r@&U4K9snLCtNGZvDP~x{BPP04ziaiqt)i0^<7_xuN&k zyBb%AQsmH5jMb4Zu$`hZeyR`q7uXkrDMRV|=BvNjE*#m({YCK*4)BAI0|9D-W;nMQ zY{4GCse9MZgu(m17DBMi`OkmtHHt{91U1GXmbqQOB!#0f!3&3zk_SZMdNKBFG4bP1 zpXG6&C;6(4W*J7PROsRlu;3y!yHU-qD)ibvolR0NPf#xtYuh{O^mRg%QUVejF2gwZ zxd=UDOskcjHhC1Y)}BwF>q!GovX$ChA(q8M4^5kvNo-gdlxp(ooot zQ_Bf<__)v`O<0>nW`r?rmrcAKY(5vMmiHDHehFe|Hf5*%G=jMz9TDgI8r8g_5N53c zLP@xxp{(_33h3e-@0)TVfpy`Yu_4GzZt0evpWwjNABCT`Sw#}|GEs*)+dWPh;^P`f zTE8l7>L-^E-!h3_ecD7YIdmKa?7%KAruMzk43yDV-;kU_dT3jwLZ0AQXflqb@i!v~ zh&(fnYE{8rl-*w-Zo`NCVo32dr~_o4^n> zPU-1Jsefqw+FC$+|7fI91xY#q9R8~8)N}*2v|sdit|&{P^Clb}ih-W2F%E&%^7M&~ z@&bX_g{*e3Fg4eBIs~*d(M+=!jQnx`X$rmx$7;APfA>+)l-y36nPIuUZ5@rNz0BBW zc>y69Bs|j*LXg`;`raQL!rVi+LU=)RNJ7gW8Rc1{&zrl)cE3i`I|bWY4<_h^LP+Mi z#F^l87}5g5s35xmyX#okWAUkU$t)`vXZDX_o^+wvZ}~ZB{S3d(oGWryW+JWQ#YZw9 z#pz7%6`8)yE)TAPJ#qj~a~`gUcS3a5&JwL#NhX)p7wu_H>R z{>PC4IhgO-P6cW+k;_%Ss4DOM)05(tG5X>7~`&r_tD=!3<%h3Lr~abjYgKu zkm#%Zm3`<$+86__=Fd->B^=BTu%|0xLE@Lj8;eZ8>>%@UC3rGIfaBZNk*mD zut!5`#R$rlVBd&9dBCY&v_eYp{)1$X_%P8b=PRhoID_ZUXjN&{Pk0Le|NKZJ7;sko+viBIpYL4h& z&63Wv+&0_rUix1TQXrM_1NRtUf(5X_7#*cD9W8-c&^BkJssc<+$g*Z6Y)y)P68e`B z&?t~19%xoP;^83Rp|elf1sl>MV@5FoFvNn0DF^f=M~xfPlgByL@;@dm+qh`vBM;E36b6o$XC3m&)O{gPl)T^=WRC^GS@oKH=gqHQ637vQ!%{=gG9b$)G+$ zjb-bq{%8fo=?QT|XjfI=S>`ZEqDV2&lp-RU5E6{z=mXIh)qXb$iUW%mT1phbkd5g0 zbz;Cs$y&79ZzOYKW_xaqbhpl0BlGLI#`9BAEyia3N!D=nv&Y|z)UIVf@>AU7x~Iru zkiuS!8n7pUY-2&vO9YxV|B-0^usjEdNx5dY!qq;G^3Z5hA1r8pNQUt!2MtdcaIX-B z*W6cMZtIOpk)*;6sb|=gO%G>S&w1OcIJ6s~K#HUl*oQ@r4`K!QPy5SA>$qvIkppn= z<43$@R#SGL)zI-0L>jw+)h06+VYPKPfXRibyzfujP1Tw@>&Y;p6Ga$bkHPpA6Z6Kd z{qL`;h;<`me@!9)k{ALFINyi4zm20zUZE}SGLkI<1%qxV(eqKdC9C!B8J_p|n4xa# z>0tHpd2LOR#xibF+h{A=7g1T+AP|zurq6FEA8Snu-vUD(WzIgYzRnJJd7dsp8dGBU z!VV)t{H)kmTkk@(akl%(x%IySYxly$<1u^H+hr2lkq#xLJPP9SS>)+uNXqP4VCH?T=-_xKF_FC`RPUHK8WA3h@Jk^kIe^;X9e> zyk?`tva2AXOpw_!Wz9t~3@a$rrg{uUqbx0`o9+6RZWEu~$@yK`3NjYbG;ZEXxdMP9 zh=}}LIXzvye2qnc15>X+eg!c}`Y3bANkgKVE?OZ3f{xtZlKOe$&m*XBJu$c|I;73l+_cv*dm#bI;M(h5_ErYHDgISB>N%6Fe`{nvlO?~cU>qF&VR2ifFtW0ugXkwO z_PEw=QyON=I$r7wb8|N0kJ}+?%x_>wC=$jv(%Qj6#!GXRw4bjwR+d+%T@KR0^82n% z`HQ__w;)HFx^A31!`TC~GZej6hU{>lG2|eh6nvufeNI8vE-G9$Mog<*tD@`;=!bWQ zv7M*Kfc50q#fpdbzD^##-W{`#_F&ZKvQipNL~$azE(^m@&RQC!^0(%Yh>|rF=fq#bFSp4}7ttY;(loy?D%Yg^>X)oHpJ;HCDUg_^J#)j=givPTDRCwaJhpQM(qmuj>CX*+Cod`m1(cdpJ4WeeRE^C#H)0#=c7Ojxi zX`%0YPAfi%KNQvKmI6%VPc(T&o*{}UG)ES~lr8(7?jkqsV<$Cj#-m1VGxnJv!lv}1 zP|2GV2k5<@j-00=m7KHYMQUAHIuSMAr{V9~1$lZ-?Wf19r9+yv+6DRhtW(?j{)f5+ zIMx{Ye5c>_>QuKGWlPMzyC##qiPZu-Bgxk@8a@jT!LX4rgtVMx{3v#mr|&by(@KN7 z^+~kXx9*{?X(c&8VlEzhOT9?V3&~;gjT7>y_uq=f{{Z!fl=vrZG1lNjdQ*zpO;mw4 zO4SLW8om_qcO%w$4<3-)K>%^E`BOQSO>vM02O;qAE&SK9efDLJwii59^`<&B4p!l}`HU{O%K`9=QMx_!&>Vf9p;fhPs(|Un#L8UbstbGec zn6A6Wl<2R1)Ao2ByQ}p+oy&EfdOx`?YU;TYC^O;1NkFof=yn<*6Sbhsbi{Mo(EjX5 zl|a{SHc8zy?Pl+7u*1gp6Z=^2Z^aIEAXpneXix4Ec6kp6n_Y4A9V~mIXIEy#?~?52 zj$SI&5KW$6Rl&=Im9bpbL^TT$DVfEmmLCT4)1_Ho=%)k@a#+c&nUD+RLkQ{VLDSME z#Ypy-Xsmz{lWHsGOv+k=0E5$=V?(T{^KXMLiPSz;*iDF*W{C*ux}10S%e204Yn8fB z*iQ%vj*`+D)SpUJHcSz)Ub6A7KQPQX<8DT1KuG+$1cnhB_O0eOahnhXcpbcdqA}gzrCSefo|ub=}`dyV-i$tN~1fWAmJrNNL)0PvfQz@*yfNV4HoAFMHYn zn!%SCpy-3>=RjUbiTY{nzf2hpgf#Q!t{-+sW&iPY;KZ|NUVz*w^q0xT%MDFs47-Ml zBgklWB0Oh2KPU5oJu3$bEmOp4hAN2aFe7;6D3K)97=R{9H@WrwHj@^n?I$Sjblb)dxpTa+{2PB zFV#{QbD+*qaQ;lm9!`hTHJSH8(8Qey$;`0GPyo2?8eZ(F1#LzMXhf*g=*ssx`FU8o z{?WBf^!QTSW$b$=cA=zY6c>;RRQo1KIQa5jRkrmb4>=AL(EENV4~Vo8eGRg& zM49-diMyp#WBQf;)Rh9eCXU&Bprmv(VqhO}xhU->E$DJhzwI>Q*t zaAp7vdgYYN*x)SqAUHRW z3c+dos!VD8HAZn>B6YztdP`zwjA6zJJZhqLZ^6|0QhV@_J7pJY<|fgFyN0|s8QZao z&|kr#+1-u$^QcgOiXJq{t(F1akX)h?9`vLrMMXZc(4NJpuYoO&xlOp2GOBuzVd1|{ z?6N=1F&LP-e!o6?XeRor;vT95H*mSsDF5Wsr_O}efphS2zbr_Z?=-mRArw|=7apcE z=eT<2>J6-{f(m|<#5T0F6TPQ?>Jdq=_|y9a>kD*}SC2$`(e%v%`rbsFf}K-M1cRBv zT6Nk+EjrITeLu(V7ggiLgmK)8G~8^{@>Rj3)b3BDZrf^3`d$$ZCGZEkbLDf7|~?t&WzJq_G*y8pKvGNWOy{%qXI;}XzPB{@7x`5_5e z$H>zVTI?tLc`OQ+0z823;yZ{-r%bP#!vKO4Kuh9&rrg0ScEHo*E(=`-lB%ww&x{5O zI!up2_Oq}P#GwCbZ|w!8R4F~3I2mD}HO`Kf|5yX+su3RqD2T8T&3@7fVc6Ldu!=~&3MWiOlNXC~~GlWnoUQtmv9SAxJIV|c)1Le{obc+mJDf&gN}Zm1hJ zDklgw)yWia zpP6|@8pUp}Qt3a(RlssH|MGZ9VJo3dJs+@AOa3syCLZ{!GyDlsOB#F=NRF&c`jT%br$y;bMc{3wJV^sXl5%r?7l z*8+WNfDVm|t~hI20@g-&FsLKiCn%>`DlvH@U@FUU^&ld)_{6NGc>HaC1a`iMc57dd zL{HtQ)9YeW56X!+L~#bQ%?$Kq8mh!By+vh>fq~X)`dU zQPf)vasZv$tbr7hG~su-Wh72C7Rbp( zZJIP-ZkrItB23qCS}TGEloC!FADoLutXwoUwhK1kCI0Cb9OSs@#H_L0j|(~(c*h1u zpHl>rIKXR$*ye$p=cS_ywiC80TFCzrzL9sPR`hE46MMyq^73nnX1J9IN{&nR;^c2r$;UgZ2q{FRj2jn@?iJ!Ctl58&-`5L zo@|`~F-h#Jo7@L@oJbGBElkd;S97bl>n~#sQZb6;&4ihV8=lj>b{TySMnT<-RJ_hp zJy-TsB4p-sr@JNz3&W@3c$-no=h^xg;$Eg$p;~-Ne1`WDyHr;jde76&dh9ti^d@pjS^w|B!Ywo(4de4?;=z+(a^W(z=Y=Aw}zr3zOb zkxY@Kkv~FPhJB?JBfLAu2JV?KpxYU<0d4K7rFTfsNXfdJ26#S~Jkp`b4wvslNjt>+ zjdeq?&0S?LiI2(RTani#_ApAp9%)f{u=oC1ZS~*Odf(ru12KHA=2xQzh4w;U2hV%${a1wxW==$fB;_F8=wEl}2? z4WZu(secvlE0#J(a@cDPn9F?;k<0Uk#}vl1w*;@&UzV}L^xs`-rr>lTk}R)ME4V8X zlK4g*F+=D+vypkh?c!?Udg&%5oZkN8!-w-g|B{`)HF+`pcG1$f{D214r*smOghX;^ z3!%la);a~NX@*j`L^Qo|szT@hPl)l%-g0Q|g+YU%#em~_I$(6?C8$36eT8$|uE$SC z`3N5g3j|fAZJ&O)h!-q)uFn?s!O;kqlLK*EqUn%~TFd zVp6!%&0$30HA?;E5E~C;H)acIm+&}u!-=UpQ+^-`5#8ZA=sMw$G{w*I3x9zdPIY9e z-W#3DnYCw1bi~w15+A=gi3U+(3Im7A^V@za_!h&HDN6Ano7S;>D~z7m!J6uSgqxU) zh}p#@;6LgR%8>bK{PBClsCEF2G2Ys`bIWDJ)EE3SyE|r$X&Rd)MqAXeu&mZN!bS=j zDM`wi8j9!A;9CPtu^TA6awwI=>u=5bA|wggZSGN1Q)VP}!H?MR?3c7NK>_=0xYdE# zGJ34wjB~ZLN~0|10a<)G{OV?KrrY9X_WTMOj&9=B!+Y~ooeG4Gl`{7jR5<#Xjp}CP z%NS^0x%Z9)Jr$gOcc1O1p{Yv8x8G&h8hnxoGHWx&_K8;wgb#l=6EunF2kOZmYf(Ai z#w|(*u1=Hm9Rxe=KZt-(WMzFyn>b9^{Z4^-#21Ruf|NY}d4n?qTEuA|=1Y|z)lB4m zD!R97RT^)InBBPgY6nI|9_gVdi*M|4TvKPafQci%TW8vt1<^q6h?bXCuvD6wT4hqe zLkqsG8-z8x#$6o76p;*GQQW4*w;wDlJsqnIQa1doYY{0)@TOP+s|e#&doC}7o-9Rc z-;6nMgT1V>qsBte&dE76rzqIklZ<5xk!*Oh8H=gA)FDKq?m-g=a-`@g%w$at^jUJc zAd64nsmYvB4{|o?(iy!kd`ZyK)*EsLt&FucVM&`i*2k>A>qT;5np6vysy@amLcae^dH74(q03?1>0+CQJ+0Acn2IfTaTEAX^1Vmm~GWlvYz` zhNGVW(e-Ug^r$kpQFAoIE!-5V>d9hH=*E*2=Yn%Ke|(-FhYkcRg;q+7X;~^X;uiuT z$>TUydTz;@u#+^#*uuKC*-s<}Bk4;SpVVVi$EyoAIDumFFzn-~`Aiws;V8=3PUFiC=WZXqjV@>-D(GA*U`R z9N;y=N0$PM4SYAw)S2#=(>JN$lL1haF7W1zgqo0hff2gUqZ~?B^2<>G!V%|Q6*7{o z^XzUNhjOWUDbO+nWM~9G|0!a^k>vKrtSVui*fvjiY!`NY%f3sCp(2j?#N#c7F0B;9 zANzfe?6|taif2m{j?<45RIJ&*tdg1&v0fw%o^Db;_X`lS=5gOIH0#8?~I5_V)y zM7^sH2q0ex(O+_)wQgz>EdoOh5 za5V`LYx0|crk?Wo6hLQwN}H4sbkv3>`jMG==ChTs3`&z*XLPUGmb=CX3WC)-4BA1p z=3`{98-nD7(I#`;!7uL{i@qpYVi+~ZJGM*tJa%wB5_Ua!Mjpog)=lF>BENY}fG)eI z;#?XlZC9eMoTGY1i#jnw708hAsy<&}gl6(YL=3OFWG`)NY>@P$BFh+W^&kXVohD1p ztJFK<5x=_oTXF1N)u$}%Q6fbp>>pkM1l7-pnrF58?mx%^%8M}UoAd0-G(9H#C25Ys z2Qj`gQF%&i>XMYSw8yTt3mf>v`q;oFdIGe1-@rJO^8=s!@)fl?ifzHNEKrUM zUK&OYc%HK8TMaxs9Y*r|HQF+SC-6@*H(NlD%Kkgs5Z2HW*U{b50WDNpT#rC0xo6sIQ!Ewz5&BQLo)kPHUo`ti*_ zM;Lz$P-U%cXV>c~-}&JtTiV+eDn1A6R z=+soStIZY%mtd~U-V*n!ystp{;>R_t2M2j|MFvZ)3dk=BNJ2e1Z3INbEN)McR|U6U zy)&=x85bAPoURu|5eK93vAVu*qFT@XVJTGRi_5IG?^>3Yl>U$hz5Z`QF3v7Ab008N zT$r>vXXoeVm%JPd4s+{ex+pG}K9-9W%A77%g>b}Z#2^)+ zXE14|Zq~iJ9NHJ!lj5h6%$Qq4R*#9?Uyt}q=}*bv6c_ivKdpB;9y;&bW9qn>Po&ta z4Ug}hxA;EqCB}vf=-clOeEJY(Tlcz|%DueM5!Let;BvDvC)Zm?iI{eDsBXD#RYTCg zcXf^2eg6IUxY9VoLv0f)QYg#&)}p+LT>d>nqU4XdHgr16<<%?oE-fC>mFEtEd*oHZ z(f*(+&!tnlaKlV}v*`&fo6{+VF3nNx(V*JtrbvhQl6?6uU4=iolGU#~mb$^|Q^0>e(;*A8StUm%?-1fk`T z_2h5vdbUVwPPX<_SQfbMlWk1Lw_ZA8ui+=%zIIk}zozQ0Ng4ODFZVE<)UZ{Uxm|@W zn3(Q$7lNqZXFw0bs0 zI*KVq-gpcQS?NYU?gx*Awru&dP=$eN+t&X81|mfV28AvlYPhW*bEcRV@q#%lM#R9* z&ezM&wl4OoAx?_q^&P|?vT&1eBv7m1&H1wSz0@-R7DUc?Z^zHku{3=Ks*ToBlPY+E z!70yi%=vx$Q%fXAMTNKy6aQiP)@GXSy&GEY@~K9Sv$iGA+bt1j`tdP2SZeU|^RSr{ z$`g2Hl@9- z`mcA$Y>L_ZR~RhE3I0+ECl)KUhZD+=^f9xFiUg3u`_M!h0!E512DwVi{>$xl+vlGt zw|(@w9EZgj%ILJa%Pgfa(k~^-DPuY7-yOv*tlzY3kzSPN8kAcWvs;>Ji0kOGGVb2b z0yfvrewH}NI<^-VpC_Y+A9v?e{uBV$D|zHw|Q z*KV$GEPr9@trZd!+#MC0bfGcJ5V^^WvG(zz({OYe*F4>ayDDx<_v?Q#ZH(P5Vx&sf zKRx*YsL6_^e0JvBt(q(Kt|wG4oHYfxz?>}y!xcb-D5Llme{g@_oT}q-zMongs_n&N zD>|b5UG8XC$3?lT{Rh@m6_PP@>s#ZdE6swHmBL!Ut6kE$g`^M49n#?K7b0rpc(J|u zk(`v4tCEu8`+IZ+B_!4msV>3P9J)$nIR|SC6DUQ9}+64zs>lHg~KK z2hq-HwvpP%B1V9RHC0%a$NR!9E|1$i zOWyY}D=PHth>XwvKYk=W<57bsqA8S1M#tPre~Mh=-8t=wT9my-l73X`J{X++jc@xP zXX13^lwk0k?)!JO#P<{4k>!O)^x~49Eo&D!yYMjiFvaD^!J%#-_Q?XjTf^{7>x2C3 zPcAM8o&)u^py*FI0GRoVa-*Y_BZRBrg;9GM9g)+!>Cc7yVDNq;yS3GbCq4ddT|74& zabiW!&lna8N${PLALM3kzgh*BVr2{$=*DU_2B4s4w8VZ-vq9d=lA;ZBjioDkgP$cl z7iDHPZnL`9Oud7GjDH1nWH^+csBWLEg~C13`pj{Ew-`cQC zti-}xnNm9^k?<<;!^f%B#J%0-u1j;x)q1S^PS1|ve*07Gx`XpX?)z}`Ge3}U>UPH` z_hEf|fGF*2H^H*;)@Zjc|KsHL_V)MhAvCF?xM@>gS4g(pNhEh#qi_XUShHt z$0qYP=0cj$U2QjDIBCDj(5Zb1{~jdJq@+&q;`%GLsPyu%A7CgZrd*j zZ}#NzvUdDGa*u>N35}3_vS@B@P7yEEQ+@IPMG;3gCfs{N+3bBn`~oao5BWlPOZMz5@F zT!avT9~L_qmMpTv3gbDk8JQW))@ulysv*;O-u8mF9}C*cR4*H*JYKi^iM;PicS&y{ zUf-+BT{gyxBLr-5I5vKwiIvr-7qP_4-A00IpIozPkC(4|#u4ML)8;ASa)dF0>FL8h zaqITnEVEPtMqO1ImWD^3m%+wm7Mc9LBm z-MHDjKV4~Z1Yp=e;9*31L8z!+WTM_)AIrM!Zr7bSs;hM}qPekhWft9%hvl|G%Y`Hs zl{S$VvYB&MizMdX~nLOD(#&nm*=K zpI-@GzphkW+!||8F>`t-P|s+JnobmlrE2NLVxX^%CM%`MhMGbZk$@!wMUyT(TYn z0?40FMdUgR+Xs>{s(m}!bh#I>vw-R3JVh(?dtld-%6|qyuTo6=l!l&5E4|J`3LKID zP-2$68SVx6)d2-?cwo(2el&=`y_K;5b&9{OMPVAaZ+NQm4n9rmmILm`Pm90{DaB0J zejapf^)zyv-`u0>@_hgYxt_p#bH3+@%f|cue0KAm*rOAF7l7n+utbgmebz8}ORV4V z0#q=7tNd@ljib)Ukf48usX&bK``hAkj`yZ?Xr-Zh__DXKo_Qpt+koaN|C==Rj)dcX z{_#&AhmAkNr-=@b8}y9E;;HWg4nY6*jr`9DqAQTu6E%PI^*n|3?V&yIHbjG-C{=vnRgB?%a4xjghb& zPVfIK^Z)G?c=k{wBQx&I5GbQ&R?q~)K}z61pNW-2;Ce$)5&t7pc@ATUMd{0@$}om{ zei6rOOPDdJ|Z^Ov$jr*Uw{(tR2`9NBMBrv0k zkD~e-fwnr$5fE7^^;4PW?~wnqJWMB=)EH6uTl-p`=c#GPxpg^KT*)GZpRd<{M+MqU zd{<fee_c6Gdy(;WpTCrJ##iz-Y8(+U5%qP1X*`?&-H+-Kt@bL-j{_{WbA`xaMZ fU<2yUQxzNp_li}cqh=rd&-LQMGD0;1dIA3re}%q% literal 0 HcmV?d00001 diff --git a/src/huamenchuang/services/quote_service.py b/src/huamenchuang/services/quote_service.py index f2c5c2d..83376c3 100644 --- a/src/huamenchuang/services/quote_service.py +++ b/src/huamenchuang/services/quote_service.py @@ -92,6 +92,20 @@ def takeoff(dd) -> TakeoffResult: # 玻璃面积(重放后各窗格之和) result.glass_area_m2 += sum(_shoelace_area(r) for r in region_pts) / 1_000_000 + # 装饰格条(自研 decs 扩展): 横条=区域宽×rows, 竖条=区域高×cols + for dec in (shape.get("decs") or []): + if not isinstance(dec, dict): + continue + ri = int(dec.get("ri", -1)) + if not (0 <= ri < len(regions)): + continue + bb = region_bbs[ri] + rows, cols = int(dec.get("rows", 0) or 0), int(dec.get("cols", 0) or 0) + if rows: + result.bars.append(BarItem("dec_bar", round(bb[2] - bb[0]), rows, "格条-横")) + if cols: + result.bars.append(BarItem("dec_bar", round(bb[3] - bb[1]), cols, "格条-竖")) + # 扇框 for sub in (shape.get("sm") or []): bd = sub.get("bd") if isinstance(sub, dict) else None @@ -153,7 +167,7 @@ def quote(drawing: str | dict, prices: dict | None = None, scripts: dict | None """ from huamenchuang.services.formula import FormulaError, eval_formula - p = {"frame": 45, "mullion": 40, "sash": 50, "glass": 120, "hardware": 180} + p = {"frame": 45, "mullion": 40, "sash": 50, "glass": 120, "hardware": 180, "dec_bar": 12} if prices: p.update(prices)