Add structural calculation worksheets

Collection of engineering calculation projects (Python + Typst), each with
input, calc script, tests, results, and generated PDF where available.
This commit is contained in:
smillmorel 2026-09-21 12:19:20 -04:00
commit d5ac3fca7e
81 changed files with 18668 additions and 0 deletions

14
.gitignore vendored Normal file
View file

@ -0,0 +1,14 @@
# Python
__pycache__/
*.py[cod]
.pytest_cache/
.venv/
venv/
# Typst
*.aux
# Editors / OS
.DS_Store
*.swp
*~

Binary file not shown.

View file

@ -0,0 +1,211 @@
# Project State: Concentric Footing Analysis
Last updated: 2026-08-21
Project root: `calcs/concentric-footing/`
Parent worksheets root: `/home/smill/Sync/worksheets`
Reference: `CONCENTRIC-FOOTING.pdf` — Blavatnik concentric footing for steel column (square footing, ACI-based checks). Parent project conventions as documented in `worksheets/codemap.md` and `calcs/wood-joist/PROJECT_STATE.md`.
## Overview
New hybrid (Typst + Python) calculation at `calcs/concentric-footing/` that checks a square, concentrically loaded, reinforced concrete spread footing under combined service and ultimate axial load per **ACI 318-19**. Five checks are covered:
1. Soil bearing (service, ASD) — `q = Ps/Af <= qa`
2. One-way (beam) shear — ACI 22.5 — `Vc = 2*lambda*sqrt(f'c)*Bf*d`
3. Two-way (punching) shear — ACI 22.6 — `vc = min(4, 2+4/beta, 2+alpha_s*d/bo)*lambda*sqrt(f'c)`
4. Flexure (bending) — ACI 22.5/7 — Whitney block `a = As*fy/(0.85*f'c*Bf)`, `Mn = As*fy*(d-a/2)`
5. Concrete bearing on footing — ACI 22.8 — `Bn = 0.85*f'c*A1*sqrt(A2/A1) <= 2*0.85*f'c*A1`
Minimum reinforcement `rho = As/(Bf*d) >= 0.0018` is checked as `minimum_steel`.
The default `input.yaml` reproduces the Blavatnik reference example subject to documented corrections (bearing plate clarification and ACI-correct punching perimeter). The pytest suite locks the corrected numbers.
## Architecture decisions
- **Hybrid pattern** (same as `wood-joist` / `steel-beam`): `input.yaml` (Pint unit-bearing quantities, quoted strings) -> `calc.py` (`compute()` -> writes `results.json`) -> `footing.typ` (presents only, no recomputation) -> compiled PDF with `--root .` from `worksheets/`.
- **`results.json` shape** (unchanged contract): `{tool, version, project, prepared_by, values, checks}` with `tool = "concentric_footing"`, `version = "0.1"`.
- **Pint units**: all dimensional inputs are quoted strings (e.g. `"3000 psi"`, `"3 ft"`, `"18.4 kip"`). `calc.py` converts with a `quantity(value, unit, name)` helper identical to `wood-joist/calc.py`; dimensionless factors are plain floats.
- **`calc.py` CLI** mirrors `wood-joist`/`steel-beam`: `--input`, `--output`, `--stdout`; runnable as `python calcs/concentric-footing/calc.py` with no args.
- **ACI 318-19** is the governing standard and edition. All clause references are to ACI 318-19 Chapter 22 / 13.
- **`footing.typ` imports** from `../../lib/sheet.typ` and reads `results.json`. It also **derives loads in Typst** (mirroring `wood-joist`/`steel-beam`): `DLr`, `LLr`, `Br`, `Lr`, `Ar`, column weight `Wc = bc*bc*Lc*gamma_c` -> `Ps_derived = (DLr+LLr)*Ar + Wc`, `Pu_derived = 1.2*(DLr*Ar+Wc)+1.6*LLr*Ar`. These are emitted as `<concentric-footing-loads>` metadata and reconciled to the Python-checked `Ps`/`Pu` by the test suite. Capacity numbers are never recomputed in Typst.
- **Sheet helpers**: flexure, shear, bearing, and soil bearing use `check` (Demand/Capacity D/C). No `check_service` variant is needed; soil bearing is presented as `q` vs `qa`.
- **Compilation**: `typst compile --root . calcs/concentric-footing/footing.typ calcs/concentric-footing/generated/footing.pdf` so the shared logo at `assets/logo.png` resolves.
## Engineering decisions (pinned for the builder)
All equations, units, and applicability limits are pinned here. The builder must not invent behavior. Tolerances and benchmark values are under "Reference example".
### Inputs and units
Pint-parsed quantities (all positive, `ValueError` if <=0 or wrong dimension):
- `Ps` -> kip (service axial load, column + roof)
- `Pu` -> kip (factored axial load, 1.2D+1.6L)
- `qa` -> psf (allowable soil bearing, gross)
- `Bf` -> ft or in (square footing side; `Af = Bf^2` -> ft2, also `Bf_in = Bf_ft*12`)
- `Df` -> in (total footing thickness)
- `cover` -> in (to centroid of steel, so `d = Df - cover`; `d` is effective depth)
- `fc` -> psi or ksi (concrete `f'c`)
- `fy` -> psi or ksi (reinforcement yield)
- `lambda` -> float (lightweight factor, 1.0 normal weight, (0,1])
- `column_width` (`c`) -> in (square column side)
- `base_plate_width` (`bp`) -> in (square base plate side, `A1 = bp^2`; if omitted defaults to `c`)
- `rebar_size` -> int (e.g. 4 means #4 -> db = rebar_size/8 in)
- `N` -> int (number of bars per direction)
Dimensionless / integers are validated: `N` integer >=1, `rebar_size` integer 3..18, `lambda` in (0,1], `rho_min` hardcoded 0.0018.
Derived:
- `db_in = rebar_size/8`
- `As1_in2 = pi*db^2/4`
- `As_in2 = N*As1`
- `d_in = Df_in - cover_in` (cover to centroid per reference; `ValueError` if `d <=0` or `d > Df`)
- `Af_ft2 = Bf_ft^2`, `Af_in2 = Af_ft2*144`
- `A1_in2 = bp_in^2`, `A2_in2 = Af_in2`, `A2_ft2 = Af_ft2`
- `Bf_in = Bf_ft*12`, `L_cant_ft = (Bf_in - c_in)/2/12`, `L_cant_in = (Bf_in - c_in)/2`
### Check 1 — Soil bearing (service)
- `q_psf = Ps_lbf / Af_ft2` where `Ps_lbf = Ps_kip*1000`
- `qu_psf = Pu_lbf / Af_ft2` (ultimate pressure for concrete checks)
- `ok_soil = q_psf <= qa_psf`
- Report `q_psf`, `qu_psf`, `qa_psf`, `Af_ft2`.
- Note: footing self weight and soil surcharge are excluded (gross pressure follows reference). Scope note states this limitation.
### Check 2 — One-way (beam) shear — ACI 22.5.5, phi=0.75
- Critical section at distance `d` from column face.
- `L1_in = (Bf_in - c_in)/2 - d_in` (cantilever beyond section). If `L1_in <=0` then `Vu_kip = 0` (no shear beyond section).
- Otherwise `Vu_lbf = qu_psf * (Bf_ft) * (L1_in/12)` because `qu` (psf) * width (ft) * length (ft). So `Vu_kip = Vu_lbf/1000`.
- `Vc_lbf = 2*lambda*sqrt(fc_psi)*Bf_in*d_in` (ACI 22.5.5.1, `lambda` factor). `Vc_kip = Vc_lbf/1000`.
- `phiVc_kip = 0.75*Vc_kip`
- `ok_one_way = Vu_kip <= phiVc_kip`
- Also report `Vu/phiVc`.
### Check 3 — Two-way (punching) shear — ACI 22.6.5, phi=0.75
- `bo_in = 4*(c_in + d_in)` (interior square column; critical perimeter at d/2). Documented correction: reference shows 68in which is inconsistent with ACI; correct value for c=14,d=9 is 92in.
- `beta = 1.0` (square). `alpha_s = 40` (interior per ACI 22.6.5.3).
- `vc1 = 4*lambda*sqrt(fc_psi)`
- `vc2 = (2 + 4/beta)*lambda*sqrt(fc_psi)`
- `vc3 = (2 + alpha_s*d_in/bo_in)*lambda*sqrt(fc_psi)`
- `vc_psi = min(vc1, vc2, vc3)`
- `Vc_lbf = vc_psi*bo_in*d_in`, `Vc_kip = Vc_lbf/1000`, `phiVn_kip = 0.75*Vc_kip`
- `Apunch_in2 = (c_in + d_in)^2`, `Apunch_ft2 = Apunch_in2/144`
- `Vu_lbf = qu_psf*(Af_ft2 - Apunch_ft2)`, `Vu_kip = Vu_lbf/1000`
- `ok_two_way = Vu_kip <= phiVn_kip`
- Also report `vc_psi`, `bo_in`.
### Check 4 — Flexure — ACI 22.5 / 7, phi=0.90
- Cantilever length `Lc_in = (Bf_in - c_in)/2`, `Lc_ft = Lc_in/12`
- `Mu_kipft = qu_psf * Bf_ft * Lc_ft^2 / 2` (qu as psf -> psf*ft*ft^2 = lbf*ft/1000 = kip*ft). Equivalent presentation: `Mu = qu*Bf*((Bf-c)/2)^2/2`.
- `a_in = As_in2*fy_psi / (0.85*fc_psi*Bf_in)`
- `c_block_in = a_in / beta1` where `beta1 = max(0.65, min(0.85, 0.85 - 0.05*max(0, (fc_psi-4000)/1000)))` (ACI 22.2.2.4.3). Computed for strain check but not required for phi (phi=0.9 tension-controlled assumed; still compute `et` for report).
- `beta1` per above.
- `Mn_kipft = As_in2*fy_ksi*(d_in - a_in/2)/12` (fy in ksi). Or `As*fy*(d-a/2)/12`.
- `phiMn_kipft = 0.90*Mn_kipft`
- `ok_flexure = Mu_kipft <= phiMn_kipft`
- `rho = As_in2 / (Bf_in*d_in)`, `rho_min = 0.0018`, `ok_min_steel = rho >= rho_min` (separate check `minimum_steel` with demand `rho_min`, capacity `rho`). For `checks` dict, `minimum_steel` uses `demand = rho_min`, `capacity = rho`.
- Also report `Mu/phiMn`, `a_in`, `rho`.
### Check 5 — Concrete bearing — ACI 22.8, phi=0.65
- `A1_in2 = bp_in^2`, `A2_in2 = Af_in2`
- `sqrt_ratio = sqrt(A2_in2/A1_in2)`, capped at 2.0: `sqrt_ratio_capped = min(sqrt_ratio, 2.0)`
- `Bn_lbf = 0.85*fc_psi*A1_in2*sqrt_ratio_capped`, but upper bound `2*0.85*fc_psi*A1_in2` already enforced by cap.
- `Bn_kip = Bn_lbf/1000`, `phiBn_kip = 0.65*Bn_kip`
- `ok_bearing = Pu_kip <= phiBn_kip`
- Report `A1_in2`, `A2_in2`, `sqrt_ratio`, `Bn_kip`, `phiBn_kip`, `Pu/phiBn`.
### Values dictionary (all rounded to 6 decimals via q() helper, except labels)
Keys in `results.json` `values` (units encoded in name):
`Ps_kip, Pu_kip, qa_psf, q_psf, qu_psf, Af_ft2,
Bf_in, Bf_ft, Df_in, cover_in, d_in,
fc_psi, fy_psi, fy_ksi, lambda,
c_in, bp_in,
N, rebar_size, db_in, As1_in2, As_in2,
rho, rho_min,
L1_in, Vu_one_way_kip, Vc_one_way_kip, phiVc_one_way_kip,
bo_in, vc_psi, Vu_two_way_kip, Vc_two_way_kip, phiVn_two_way_kip,
Lc_in, Mu_kipft, a_in, beta1, Mn_kipft, phiMn_kipft,
A1_in2, A2_in2, sqrt_ratio, Bn_kip, phiBn_kip`
### Checks dictionary
Each entry `{demand, capacity, ok}` with appropriate units (kip, kip-ft, psf, or dimensionless for rho):
- `soil_bearing`: demand `q_psf`, capacity `qa_psf`
- `one_way_shear`: demand `Vu_one_way_kip`, capacity `phiVc_one_way_kip`
- `two_way_shear`: demand `Vu_two_way_kip`, capacity `phiVn_two_way_kip`
- `flexure`: demand `Mu_kipft`, capacity `phiMn_kipft`
- `minimum_steel`: demand `rho_min`, capacity `rho`
- `bearing`: demand `Pu_kip`, capacity `phiBn_kip`
Overall ok requires all six true.
## Reference example (ground truth to lock, corrected)
Project "Blavatnik", prepared_by "Conemco Engineering". Derived loads shown in Typst: `DLr=10 psf`, `LLr=20 psf`, `Br=18.9 ft`, `Lr=27.5 ft`, `Ar=519.75 ft2`, column `14 in x14 in x14 ft`, `gamma_c=145 pcf`, `Ps~18.4 kip`, `Pu~26.2 kip`.
Footing assumed square `Bf=3 ft (36 in)`, `Af=9 ft2`, `Df=12 in`, `cover=3 in -> d=9 in`, `f'c=3000 psi`, `fy=60 ksi`, `lambda=1`, `N=4`, `rebar_size=4` -> `As=0.785 in2` (reference rounds to 0.8), `c=14 in`, `bp=6 in`, `qa=2500 psf`.
Corrected benchmark (ACI-correct, Pint conversion, tolerance in test is approx):
| Quantity | Value (rounded for display) |
|---|---|
| Ps, Pu | 18.4 kip, 26.2 kip (typst-derived 18.36/26.17) |
| q, qu | 2044 psf, 2911 psf (reference 2039/2909 within rounding of Ps/Pu) |
| soil D/C | 0.82 (q/qa) |
| One-way Vu | 1.46 kip |
| One-way Vc | 35.45 kip (2*sqrt(fc)*B*d) -> phiVc 26.59 kip, D/C 0.055 |
| Two-way bo | 92 in (corrected from 68) |
| vc | 219.1 psi (4*sqrt(fc)) |
| Two-way Vc | 181.4 kip -> phiVn 136.0 kip, Vu 15.51 kip, D/C 0.114 |
| Mu | 3.68 kip-ft |
| a | 0.524 in |
| Mn | 34.27 kip-ft -> phiMn 30.84 kip-ft, D/C 0.12 |
| rho | 0.00242 (>0.0018) |
| Bearing A1/A2 | 36 / 1296 in2, sqrt 6 capped 2 |
| Bn | 183.6 kip -> phiBn 119.3 kip, D/C 0.22 |
The reference PDF shows Vu one-way 1.5 kip, Vc 35.5 kip, phiVc 26.6 kip, Vu two-way 15.5 kip, Vc 134 kip (using 68in), phiVn 100.6 kip, Mu 3.7 kip-ft, Mn 34.3, phiMn 30.9. Differences are documented in `footing.typ` Scope: 68in perimeter corrected to ACI 92in and plate vs column clarification.
Pinned tolerances for pytest.approx: psf within 1%, kip within 0.02 kip, inches within 0.01, phi capacities within 0.3 kip or rel 1e-3.
## Conventions (inherited)
- `lib/sheet.typ` is shared. Do not modify; `footing.typ` uses `check` (not `check_service`) for all checks.
- No existing calculation (`shore-post`, `concrete-beam`, `steel-beam`, `wood-joist`) may be modified; shared `README.md` is allowed to add the new calc entry.
- Compile from `worksheets/` with `--root .`.
- Lock the reference example in pytest with `pytest.approx` before treating tool as stable.
## Milestones
- 001 DONE: `calc.py` + `input.yaml` + `results.json` — numerical core complete; corrected benchmark reproduced in results.json.
- 002 DONE: `test_concentric_footing.py` locks corrected benchmark (10 tests pass; reviewer PASS).
- 003 DONE: `footing.typ` + `generated/footing.pdf` + Typst metadata queries (12 tests pass; reviewer PASS skipped per user instruction).
- 004 DONE: `README.md` + `codemap.md` refreshed (depends on 003).
- 005 DONE: Reviewer PASS — engineering, deterministic evidence, docs, and simplify all verified (12 tests pass; PDF compiles; results.json idempotent).
## Final deliverables
- `calcs/concentric-footing/calc.py` — ACI 318-19 footing checks, CLI --input/--output/--stdout
- `calcs/concentric-footing/input.yaml` — Pint quantities, defaults reproduce Blavatnik
- `calcs/concentric-footing/test_concentric_footing.py` — locks benchmark + units + error guards + Typst queries
- `calcs/concentric-footing/footing.typ` — presents checked values, derives Ps/Pu in Typst, embeds sketch, compiled to `generated/footing.pdf`
- `README.md`, `codemap.md` — indexed
## Known limitations
- Square footing and square column/plate only; rectangular footings not checked.
- Interior column only (alpha_s=40); edge/corner punching not covered.
- Concentric axial load only; no moment or eccentricity, no overturning, no sliding.
- Gross soil pressure (excludes footing self weight and overburden) per reference; net pressure option not provided.
- One-way shear assumes uniform `qu` and prismatic width; beam shear Vc uses 2*sqrt(fc) only (no axial or size effect).
- Bearing uses `sqrt(A2/A1) <=2` per ACI 22.8.3.2; confinement reinforcement not checked.
- d = Df - cover (cover to centroid); bar diameter not subtracted separately. If cover is to clear, adjust input.
- Deflection, crack control, development length, and settlement not checked.
## Dependencies
- Python: `pyyaml`, `pytest`, `pint` (already in `requirements.txt`)
- `typst` CLI for compile and metadata-query tests
- No new third-party packages

View file

@ -0,0 +1,19 @@
# Tasks: Concentric Footing Analysis
Ordered, dependency-ordered plan. Each task has a spec in `tasks/`: `001_calc_and_input.md`, `002_numerical_tests.md`, `003_typst_sheet.md`, `004_docs_refresh.md`, `005_review.md`.
| # | Task | Files | Status | Depends on |
|---|---|---|---|---|
| 001 | Numerical core: `calc.py` + `input.yaml` + `results.json` | calcs/concentric-footing/calc.py, calcs/concentric-footing/input.yaml, calcs/concentric-footing/results.json | DONE | — |
| 002 | Numerical lock: `test_concentric_footing.py` (compute() only) | calcs/concentric-footing/test_concentric_footing.py | DONE | 001 |
| 003 | Presentation: `footing.typ` + compile + Typst metadata tests | calcs/concentric-footing/footing.typ, calcs/concentric-footing/generated/footing.pdf, calcs/concentric-footing/test_concentric_footing.py (append) | DONE | 001, 002 |
| 004 | Documentation refresh: `README.md` + `codemap.md` | README.md (at worksheets/calcs/wood-joist/README.md and/or worksheets root), codemap.md | DONE | 003 |
| 005 | Reviewer pass on the whole calculation | review notes only | DONE | 004 |
## Notes
- Task 001 is the numerical single source of truth; it pins every `results.json` value name and the exact ACI 318-19 equations. Tasks 002-005 depend on that contract.
- The Typst metadata tests (soil/structural reconciliation) live with Task 003 because they need `footing.typ` to exist; Task 002 is purely numerical to keep the dependency graph acyclic.
- `generated/` may not exist yet; Task 003 creates it before compiling.
- All tasks use hybrid Pint pattern: quoted quantity strings in YAML, `quantity()` conversion in Python, values+checks contract, presentation-only Typst.
- Load determination is derived in Typst (`DLr`, `LLr`, `Br`, `Lr`, `Ar`, column weight) and emitted as `<concentric-footing-loads>`; Python reads checked `Ps`/`Pu`. The suite reconciles them.

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View file

@ -0,0 +1,82 @@
#let navy = rgb("#1a3a5f")
#let muted = rgb("#626b73")
#let pass = rgb("#1f6b45")
#let fail = rgb("#9b2c2c")
#let calcsheet(
title: "Structural Calculation",
project: "",
prepared-by: "",
body,
) = {
set document(title: title, author: prepared-by)
set page(
paper: "us-letter",
margin: (x: 1in, top: 1.25in, bottom: 1in),
header: context {
grid(
columns: (1fr, 1fr),
align: (left, right),
image("../assets/logo.png", height: 30pt),
[#text(size: 9pt)[Project:] \
#text(size: 10pt, weight: "bold")[#project]],
)
},
footer: context {
set text(size: 8.5pt, fill: muted)
stack(
spacing: 4pt,
line(length: 100%, stroke: 0.5pt + muted),
[#prepared-by],
)
},
)
set text(font: "Libertinus Serif", size: 10pt, lang: "en")
set par(justify: true)
set heading(numbering: none)
show heading.where(level: 1): set text(size: 14pt, weight: "bold", fill: black)
show heading.where(level: 2): set text(size: 11pt, weight: "bold", fill: black)
show heading.where(level: 2): set block(above: 2em, below: 1em)
body
}
#let calcline(formula, note) = grid(
columns: (1.7fr, 1fr),
gutter: 4pt,
align: (left, left),
formula, text(size: 9pt, fill: muted, note),
)
#let check(label, demand, capacity, unit: "", ok: auto, demand-label: "Demand", capacity-label: "Capacity") = {
let utilization = demand / capacity
let passes = if ok == auto { utilization <= 1 } else { ok }
let color = if passes { pass } else { fail }
block(
breakable: false,
width: 100%,
stroke: 0.8pt + black,
inset: 8pt,
radius: 2pt,
)[
#grid(
columns: (1fr, auto),
[#text(weight: "bold")[#label]],
box(stroke: 0.8pt + color, inset: (x: 6pt, y: 2pt))[
#text(weight: "bold", fill: color)[#if passes { "OK" } else { "NOT OK" }]
],
)
#v(4pt)
#grid(
columns: (1fr, auto),
[
#demand-label: #calc.round(demand, digits: 2) #unit #h(14pt)
#capacity-label: #calc.round(capacity, digits: 2) #unit
],
[
D/C: #calc.round(utilization, digits: 2)
],
)
]
}

222
concentric-footing/calc.py Normal file
View file

@ -0,0 +1,222 @@
from __future__ import annotations
import json
import math
import sys
import argparse
from pathlib import Path
try:
import yaml
except ImportError:
raise SystemExit("Install dependencies: python -m pip install -r requirements.txt")
try:
from pint import DimensionalityError, UndefinedUnitError, UnitRegistry
except ImportError:
raise SystemExit("Install dependencies: python -m pip install -r requirements.txt")
HERE = Path(__file__).resolve().parent
ureg = UnitRegistry()
ureg.define("kip = 1000 * force_pound")
ureg.define("ksi = kip / inch ** 2")
ureg.define("psf = force_pound / foot ** 2")
ureg.define("pcf = force_pound / foot ** 3")
ureg.define("plf = force_pound / foot")
if "psi" not in ureg:
ureg.define("psi = force_pound / inch ** 2")
def quantity(value, unit: str, name: str) -> float:
try:
q = ureg.Quantity(value).to(unit)
except (DimensionalityError, UndefinedUnitError, TypeError, ValueError) as exc:
raise ValueError(f"{name}: expected {unit}, got {value!r}") from exc
magnitude = float(q.magnitude)
if magnitude <= 0:
raise ValueError(f"{name} must be positive")
return magnitude
def compute(inp: dict) -> dict:
Ps_kip = quantity(inp["Ps"], "kip", "Ps")
Pu_kip = quantity(inp["Pu"], "kip", "Pu")
qa_psf = quantity(inp["qa"], "psf", "qa")
Bf_ft = quantity(inp["Bf"], "ft", "Bf")
Df_in = quantity(inp["Df"], "in", "Df")
cover_in = quantity(inp["cover"], "in", "cover")
fc_psi = quantity(inp["fc"], "psi", "fc")
fy_psi = quantity(inp["fy"], "psi", "fy")
fy_ksi = fy_psi / 1000.0
lambda_f = float(inp.get("lambda", 1))
c_in = quantity(inp["column_width"], "in", "column_width")
bp_in = quantity(inp.get("base_plate_width", inp["column_width"]), "in", "base_plate_width")
N = int(inp["N"])
rebar_size = int(inp["rebar_size"])
if not (0 < lambda_f <= 1):
raise ValueError("lambda must be in (0, 1]")
if N < 1:
raise ValueError("N must be >= 1")
if not (3 <= rebar_size <= 18):
raise ValueError("rebar_size must be an integer in [3, 18]")
d_in = Df_in - cover_in
if d_in <= 0:
raise ValueError("d = Df - cover must be positive")
Bf_in = Bf_ft * 12.0
Af_ft2 = Bf_ft ** 2
Af_in2 = Af_ft2 * 144.0
# Derived rebar properties
db_in = rebar_size / 8.0
As1_in2 = math.pi * db_in ** 2 / 4.0
As_in2 = N * As1_in2
rho = As_in2 / (Bf_in * d_in)
rho_min = 0.0018
# Pressures
Ps_lbf = Ps_kip * 1000.0
Pu_lbf = Pu_kip * 1000.0
q_psf = Ps_lbf / Af_ft2
qu_psf = Pu_lbf / Af_ft2
# One-way shear — ACI 22.5.5, phi=0.75
L1_in = (Bf_in - c_in) / 2.0 - d_in
if L1_in <= 0:
Vu_one_kip = 0.0
else:
Vu_one_lbf = qu_psf * Bf_ft * (L1_in / 12.0)
Vu_one_kip = Vu_one_lbf / 1000.0
Vc_one_lbf = 2.0 * lambda_f * math.sqrt(fc_psi) * Bf_in * d_in
Vc_one_kip = Vc_one_lbf / 1000.0
phiVc_one_kip = 0.75 * Vc_one_kip
# Two-way (punching) shear — ACI 22.6.5, phi=0.75
bo_in = 4.0 * (c_in + d_in)
beta = 1.0
alpha_s = 40.0
vc1 = 4.0 * lambda_f * math.sqrt(fc_psi)
vc2 = (2.0 + 4.0 / beta) * lambda_f * math.sqrt(fc_psi)
vc3 = (2.0 + alpha_s * d_in / bo_in) * lambda_f * math.sqrt(fc_psi)
vc_psi = min(vc1, vc2, vc3)
Vc_two_lbf = vc_psi * bo_in * d_in
Vc_two_kip = Vc_two_lbf / 1000.0
phiVn_two_kip = 0.75 * Vc_two_kip
Apunch_in2 = (c_in + d_in) ** 2
Apunch_ft2 = Apunch_in2 / 144.0
Vu_two_lbf = qu_psf * (Af_ft2 - Apunch_ft2)
Vu_two_kip = Vu_two_lbf / 1000.0
# Flexure — ACI 22.5 / 7, phi=0.90
Lc_in = (Bf_in - c_in) / 2.0
Lc_ft = Lc_in / 12.0
Mu_kipft = qu_psf * Bf_ft * Lc_ft ** 2 / 2.0 / 1000.0
a_in = As_in2 * fy_psi / (0.85 * fc_psi * Bf_in)
beta1 = max(0.65, min(0.85, 0.85 - 0.05 * max(0.0, (fc_psi - 4000.0) / 1000.0)))
Mn_kipft = As_in2 * fy_ksi * (d_in - a_in / 2.0) / 12.0
phiMn_kipft = 0.90 * Mn_kipft
# Concrete bearing — ACI 22.8, phi=0.65
A1_in2 = bp_in ** 2
A2_in2 = Af_in2
sqrt_ratio = math.sqrt(A2_in2 / A1_in2)
sqrt_ratio_capped = min(sqrt_ratio, 2.0)
Bn_lbf = 0.85 * fc_psi * A1_in2 * sqrt_ratio_capped
Bn_kip = Bn_lbf / 1000.0
phiBn_kip = 0.65 * Bn_kip
def q(value: float) -> float:
return round(value, 6)
values = {
"Ps_kip": q(Ps_kip),
"Pu_kip": q(Pu_kip),
"qa_psf": q(qa_psf),
"q_psf": q(q_psf),
"qu_psf": q(qu_psf),
"Af_ft2": q(Af_ft2),
"Bf_in": q(Bf_in),
"Bf_ft": q(Bf_ft),
"Df_in": q(Df_in),
"cover_in": q(cover_in),
"d_in": q(d_in),
"fc_psi": q(fc_psi),
"fy_psi": q(fy_psi),
"fy_ksi": q(fy_ksi),
"lambda": q(lambda_f),
"c_in": q(c_in),
"bp_in": q(bp_in),
"N": N,
"rebar_size": rebar_size,
"db_in": q(db_in),
"As1_in2": q(As1_in2),
"As_in2": q(As_in2),
"rho": q(rho),
"rho_min": q(rho_min),
"L1_in": q(L1_in),
"Vu_one_way_kip": q(Vu_one_kip),
"Vc_one_way_kip": q(Vc_one_kip),
"phiVc_one_way_kip": q(phiVc_one_kip),
"bo_in": q(bo_in),
"vc_psi": q(vc_psi),
"Vu_two_way_kip": q(Vu_two_kip),
"Vc_two_way_kip": q(Vc_two_kip),
"phiVn_two_way_kip": q(phiVn_two_kip),
"Lc_in": q(Lc_in),
"Mu_kipft": q(Mu_kipft),
"a_in": q(a_in),
"beta1": q(beta1),
"Mn_kipft": q(Mn_kipft),
"phiMn_kipft": q(phiMn_kipft),
"A1_in2": q(A1_in2),
"A2_in2": q(A2_in2),
"sqrt_ratio": q(sqrt_ratio),
"Bn_kip": q(Bn_kip),
"phiBn_kip": q(phiBn_kip),
}
checks = {
"soil_bearing": {"demand": q(q_psf), "capacity": q(qa_psf), "ok": q_psf <= qa_psf},
"one_way_shear": {"demand": q(Vu_one_kip), "capacity": q(phiVc_one_kip), "ok": Vu_one_kip <= phiVc_one_kip},
"two_way_shear": {"demand": q(Vu_two_kip), "capacity": q(phiVn_two_kip), "ok": Vu_two_kip <= phiVn_two_kip},
"flexure": {"demand": q(Mu_kipft), "capacity": q(phiMn_kipft), "ok": Mu_kipft <= phiMn_kipft},
"minimum_steel": {"demand": q(rho_min), "capacity": q(rho), "ok": rho >= rho_min},
"bearing": {"demand": q(Pu_kip), "capacity": q(phiBn_kip), "ok": Pu_kip <= phiBn_kip},
}
return {
"tool": "concentric_footing",
"version": "0.1",
"project": inp.get("project", ""),
"prepared_by": inp.get("prepared_by", ""),
"values": values,
"checks": checks,
}
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Calculate the concentric footing design from a YAML input file.")
parser.add_argument("--input", "-i", type=Path, default=HERE / "input.yaml", help="YAML input path")
parser.add_argument("--output", "-o", type=Path, help="JSON output path; defaults beside the input")
parser.add_argument("--stdout", action="store_true", help="Write the complete JSON result to stdout instead of a file")
args = parser.parse_args(argv)
input_path = args.input
output_path = args.output or input_path.with_name("results.json")
with input_path.open(encoding="utf-8") as handle:
result = compute(yaml.safe_load(handle))
serialized = json.dumps(result, indent=2) + "\n"
if args.stdout:
sys.stdout.write(serialized)
else:
output_path.write_text(serialized, encoding="utf-8")
print(output_path)
return 0
if __name__ == "__main__":
raise SystemExit(main())

View file

@ -0,0 +1,41 @@
# Codemap: concentric-footing
Hybrid (Typst + Python) structural calculation that checks a square, concentrically loaded reinforced-concrete spread footing per ACI 318-19: soil bearing, one-way shear, two-way (punching) shear, flexure, minimum steel, and concrete bearing. `calc.py` is the single source of truth; `footing.typ` presents only.
Generated: 2026-08-21
Files indexed: 13 (all deliverables present)
## Layout
```
calcs/concentric-footing/
├── calc.py [logic] — ACI 318-19 footing checks; Pint YAML → compute() → results.json; CLI --input/--output/--stdout.
├── input.yaml [config] — Pint-quoted quantities; Blavatnik defaults (Ps, Pu, qa, Bf, Df, cover, fc, fy, lambda, column_width, base_plate_width, N, rebar_size).
├── results.json [state] — last calc output: {tool, version, project, prepared_by, values, checks}.
├── test_concentric_footing.py [test] — pytest lock of corrected ACI 318-19 benchmark (12 tests); imports calc.py:compute via importlib.
├── footing.typ [logic] — Typst presentation sheet; imports lib/sheet.typ + results.json, derives loads, emits <concentric-footing-loads>/<concentric-footing-results>.
├── generated/footing.pdf [doc] — compiled artefact (~204 KB).
├── CONCENTRIC-FOOTING.pdf [doc] — reference: Blavatnik square footing 36in×36in×12in, 3000 psi, 4-#4 (contains known 68in vs 92in perimeter typo).
├── PROJECT_STATE.md [doc] — architecture, pinned equations, units, tolerances, corrected benchmark, known limitations.
├── TASKS.md [doc] — 5-task plan (001 numerical core, 002 pytest lock, 003 Typst sheet, 004 docs, 005 review).
└── tasks/
├── 001_calc_and_input.md [doc] — numerical core spec (calc.py + input.yaml + results.json).
├── 002_numerical_tests.md [doc] — pytest lock spec (test_concentric_footing.py, compute() only).
├── 003_typst_sheet.md [doc] — Typst presentation spec (footing.typ + compile + metadata query tests).
├── 004_docs_refresh.md [doc] — README + codemap refresh spec.
└── 005_review.md [doc] — reviewer pass spec (engineering + deterministic evidence + simplify).
```
(footing.typ and generated/footing.pdf are now present on disk — see layout above.)
## Hot Spots
- `calcs/concentric-footing/calc.py` — single source of truth for all six ACI 318-19 checks; any equation change must be reconciled with `test_concentric_footing.py` and the benchmark in `PROJECT_STATE.md`.
- `calcs/concentric-footing/PROJECT_STATE.md` — pins every equation, unit, tolerance, and the corrected benchmark; the builder must not invent behavior beyond it.
- `lib/sheet.typ` (in worksheets root, external) — shared `calc-line` / `check` helpers used by `footing.typ`; changing them breaks every sheet's PDF.
## Conventions
- Hybrid Pint pattern: `input.yaml` (quoted quantity strings) → `calc.py:compute()` → `results.json` {tool, version, project, prepared_by, values, checks} → `footing.typ` (presents only, no recomputation) → PDF compiled with `--root .` from `worksheets/`.
- Load determination (DL/LL, tributary area, column self weight) is derived in Typst and emitted as `<concentric-footing-loads>`; Python reads checked `Ps`/`Pu`. The test suite reconciles them.
- Pin one hand-calculated example in `pytest.approx` before treating the tool as stable; correct reference typos in the Scope note rather than reproducing them.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,110 @@
#import "assets/sheet.typ": calcline, calcsheet, check
#let data = json("results.json")
#let n = data.values
#let checks = data.checks
#let round(value, digits: 2) = calc.round(value, digits: digits)
#show: calcsheet.with(
title: "Concentric Footing Analysis",
project: data.project,
prepared-by: data.prepared_by,
)
= Concentric Footing Analysis
Square spread footing under concentric axial load, ACI 318-19. Numbers come from
`calc.py`; this sheet only presents them. Typst derives gravity loads below;
checked Python demands are reconciled by the test suite.
#figure(
align(center)[
#box(width: 160pt, height: 130pt)[
#place(rect(width: 120pt, height: 120pt, stroke: 1pt))
#place(dx: 45pt, dy: 45pt, rect(width: 30pt, height: 30pt, fill: rgb("#cccccc"), stroke: 0.8pt))
#place(dx: 55pt, dy: 2pt, text(size: 8pt)[$B_f$])
#place(dx: 124pt, dy: 55pt, text(size: 8pt)[$B_f$])
#place(dx: 56pt, dy: 56pt, text(size: 7pt)[$c$])
]
],
caption: [Footing plan and section: #n.Bf_ft ft × #n.Bf_ft ft × #n.Df_in in, d=#n.d_in in.],
)
== Loads Determination
#let DLr = 10 // psf
#let LLr = 20 // psf
#let Br = 18.9 // ft
#let Lr = 27.5 // ft
#let Ar = Br * Lr // ft2
#let bc = 14 // in
#let Lc = 14 // ft
#let gamma_c = 145 // pcf
#let Wc_kip = bc * bc / 144 * Lc * gamma_c / 1000 // kip column weight
#let Ps_typst = (DLr + LLr) * Ar / 1000 + Wc_kip // kip
#let Pu_typst = 1.2*(DLr*Ar/1000 + Wc_kip) + 1.6*LLr*Ar/1000
#metadata((Ps_kip: Ps_typst, Pu_kip: Pu_typst, Ar_ft2: Ar, Wc_kip: Wc_kip)) <concentric-footing-loads>
#calcline([$A_r = B_r L_r = #round(Ar, digits: 2) " ft"^2$], [Tributary area])
#calcline([$W_c = b_c b_c L_c gamma_c = #round(Wc_kip, digits: 2) " kip"$], [Column self weight])
#calcline([$P_s = (D_L_r + L_L_r) A_r + W_c = #round(Ps_typst, digits: 2) " kip"$], [Typst-derived service load])
#calcline([$P_(s,"checked") = #round(n.Ps_kip, digits: 2) " kip"$], [Python-checked service load])
#calcline([$P_u = 1.2(D_L_r A_r + W_c) + 1.6 L_L_r A_r = #round(Pu_typst, digits: 2) " kip"$], [Typst-derived factored load])
#calcline([$P_(u,"checked") = #round(n.Pu_kip, digits: 2) " kip"$], [Factored axial load])
#calcline([$q_u = P_u / A_f = #round(n.qu_psf, digits: 1) " psf"$], [Factored gross pressure])
== Geometry and Materials
#calcline([$B_f = #n.Bf_ft " ft"$, $A_f = #n.Af_ft2 " ft"^2$], [Footing plan dimensions])
#calcline([$D_f = #n.Df_in " in"$, $"cover" = #n.cover_in " in"$, $d = D_f - "cover" = #n.d_in " in"$], [Effective depth])
#calcline([$c = #n.c_in " in"$, $b_p = #n.bp_in " in"$], [Column and base-plate widths])
#calcline([$f'_c = #n.fc_psi " psi"$, $f_y = #n.fy_ksi " ksi"$, $lambda = #n.lambda$], [Concrete and steel])
#calcline([$N = #n.N$, #("#" + str(n.rebar_size) + " bars"), $A_(s,1) = #round(n.As1_in2, digits: 4) " in"^2$, $A_s = #round(n.As_in2, digits: 4) " in"^2$], [Reinforcement per direction])
#calcline([$rho = A_s/(B_f d) = #round(n.rho, digits: 4)$, $rho_min = #n.rho_min$], [Reinforcement ratio])
== Soil Bearing
#calcline([$q = P_s/A_f = #round(n.q_psf, digits: 1) " psf"$], [Acting service pressure])
#calcline([$q_a = #n.qa_psf " psf"$], [Allowable gross pressure])
#check("Soil bearing", checks.soil_bearing.demand, checks.soil_bearing.capacity, unit: "psf", ok: checks.soil_bearing.ok, demand-label: [$q$], capacity-label: [$q_a$])
== One-Way Shear
#calcline([$L_1 = (B_f - c)/2 - d = #round(n.L1_in, digits: 2) " in"$], [Cantilever beyond d])
#calcline([$V_u = q_u B_f L_1 = #round(n.Vu_one_way_kip, digits: 2) " kip"$], [Demand at d])
#calcline([$V_c = 2 lambda sqrt(f'_c) B_f d = #round(n.Vc_one_way_kip, digits: 1) " kip"$], [ACI 22.5])
#calcline([$phi V_c = #round(n.phiVc_one_way_kip, digits: 1) " kip"$], [phi=0.75])
#check("One-way shear", checks.one_way_shear.demand, checks.one_way_shear.capacity, unit: "kip", ok: checks.one_way_shear.ok, demand-label: [$V_u$], capacity-label: [$phi V_c$])
== Two-Way Shear (Punching)
#calcline([$b_o = 4(c+d) = #n.bo_in " in"$], [Critical perimeter at d/2])
#calcline([$v_c = min(4, 2+4/beta, 2+alpha_s d/b_o) lambda sqrt(f'_c) = #round(n.vc_psi, digits: 1) " psi"$], [ACI 22.6])
#calcline([$V_c = v_c b_o d = #round(n.Vc_two_way_kip, digits: 1) " kip"$], [Concrete shear strength])
#calcline([$V_u = q_u (A_f - (c+d)^2) = #round(n.Vu_two_way_kip, digits: 1) " kip"$], [Punch demand])
#check("Two-way shear", checks.two_way_shear.demand, checks.two_way_shear.capacity, unit: "kip", ok: checks.two_way_shear.ok, demand-label: [$V_u$], capacity-label: [$phi V_c$])
== Flexure
#calcline([$L_c = (B_f - c)/2 = #round(n.Lc_in, digits: 1) " in"$], [Cantilever])
#calcline([$M_u = q_u B_f L_c^2/2 = #round(n.Mu_kipft, digits: 2) " kip·ft"$], [Demand])
#calcline([$a = A_s f_y/(0.85 f'_c B_f) = #round(n.a_in, digits: 3) " in"$], [Whitney stress block])
#calcline([$M_n = A_s f_y (d - a/2) = #round(n.Mn_kipft, digits: 1) " kip·ft"$], [Nominal moment strength])
#calcline([$phi M_n = #round(n.phiMn_kipft, digits: 1) " kip·ft"$], [phi=0.90])
#calcline([$rho = A_s/(B_f d) = #round(n.rho, digits: 4)$], [vs rho_min 0.0018])
#check("Flexure", checks.flexure.demand, checks.flexure.capacity, unit: "kip·ft", ok: checks.flexure.ok, demand-label: [$M_u$], capacity-label: [$phi M_n$])
#check("Minimum steel", checks.minimum_steel.demand, checks.minimum_steel.capacity, unit: "", ok: checks.minimum_steel.ok, demand-label: [$rho$], capacity-label: [$rho_min$])
== Concrete Bearing
#calcline([$A_1 = b_p^2 = #round(n.A1_in2, digits: 1) " in"^2$, $A_2 = B_f^2 = #round(n.A2_in2, digits: 1) " in"^2$], [Plate and footing])
#calcline([$sqrt(A_2/A_1) = #round(n.sqrt_ratio, digits: 2)$], [Uncapped ratio, capped at 2.0 for strength])
#calcline([$B_n = 0.85 f'_c A_1 sqrt(...) = #round(n.Bn_kip, digits: 1) " kip"$], [ACI 22.8])
#calcline([$phi B_n = #round(n.phiBn_kip, digits: 1) " kip"$], [phi=0.65])
#check("Concrete bearing", checks.bearing.demand, checks.bearing.capacity, unit: "kip", ok: checks.bearing.ok, demand-label: [$P_u$], capacity-label: [$phi B_n$])

View file

@ -0,0 +1,19 @@
project: "Blavatnik"
prepared_by: "Conemco Engineering"
Ps: "18.4 kip" # service axial (checked demand)
Pu: "26.2 kip" # factored axial (checked demand, 1.2D+1.6L)
qa: "2500 psf" # allowable soil bearing (gross)
Bf: "3 ft" # square footing side
Df: "12 in" # total thickness
cover: "3 in" # to centroid of steel -> d = Df - cover
fc: "3000 psi" # f'c
fy: "60 ksi" # fy
lambda: 1 # lightweight factor (float, (0,1])
column_width: "14 in" # c, square column
base_plate_width: "6 in" # bp, square base plate (A1 = bp^2); if omitted in code defaults to c
N: 4 # bars per direction
rebar_size: 4 # #4 -> db=0.5in
# Optional documentation keys (not used in compute, but keep for Typst derivation comments):
# DLr, LLr etc are NOT in input.yaml; Typst derives Ps/Pu there. This YAML holds checked demands only.

View file

@ -0,0 +1,84 @@
{
"tool": "concentric_footing",
"version": "0.1",
"project": "Blavatnik",
"prepared_by": "Conemco Engineering",
"values": {
"Ps_kip": 18.4,
"Pu_kip": 26.2,
"qa_psf": 2500.0,
"q_psf": 2044.444444,
"qu_psf": 2911.111111,
"Af_ft2": 9.0,
"Bf_in": 36.0,
"Bf_ft": 3.0,
"Df_in": 12.0,
"cover_in": 3.0,
"d_in": 9.0,
"fc_psi": 3000.0,
"fy_psi": 60000.0,
"fy_ksi": 60.0,
"lambda": 1.0,
"c_in": 14.0,
"bp_in": 6.0,
"N": 4,
"rebar_size": 4,
"db_in": 0.5,
"As1_in2": 0.19635,
"As_in2": 0.785398,
"rho": 0.002424,
"rho_min": 0.0018,
"L1_in": 2.0,
"Vu_one_way_kip": 1.455556,
"Vc_one_way_kip": 35.492422,
"phiVc_one_way_kip": 26.619316,
"bo_in": 92.0,
"vc_psi": 219.089023,
"Vu_two_way_kip": 15.50571,
"Vc_two_way_kip": 181.405711,
"phiVn_two_way_kip": 136.054283,
"Lc_in": 11.0,
"Mu_kipft": 3.669213,
"a_in": 0.513332,
"beta1": 0.85,
"Mn_kipft": 34.334992,
"phiMn_kipft": 30.901493,
"A1_in2": 36.0,
"A2_in2": 1296.0,
"sqrt_ratio": 6.0,
"Bn_kip": 183.6,
"phiBn_kip": 119.34
},
"checks": {
"soil_bearing": {
"demand": 2044.444444,
"capacity": 2500.0,
"ok": true
},
"one_way_shear": {
"demand": 1.455556,
"capacity": 26.619316,
"ok": true
},
"two_way_shear": {
"demand": 15.50571,
"capacity": 136.054283,
"ok": true
},
"flexure": {
"demand": 3.669213,
"capacity": 30.901493,
"ok": true
},
"minimum_steel": {
"demand": 0.0018,
"capacity": 0.002424,
"ok": true
},
"bearing": {
"demand": 26.2,
"capacity": 119.34,
"ok": true
}
}
}

View file

@ -0,0 +1,131 @@
# Task 001 — Numerical core: calc.py + input.yaml + results.json
## Goal
Implement the ACI 318-19 concentric footing calculator as the single source of truth for soil bearing, one-way shear, two-way shear, flexure, minimum steel, and concrete bearing.
## Background
Architecture is hybrid Pint pattern per PROJECT_STATE.md. This task establishes the contract every later task depends on: input.yaml Pint quantities, calc.py compute() with 6 checks, and results.json {tool,version,project,prepared_by,values,checks}. Parent conventions from wood-joist and steel-beam apply. No Typst work in this task.
The reference is CONCENTRIC-FOOTING.pdf (Blavatnik). Corrected benchmark is pinned in PROJECT_STATE.md (Bf=3ft, Af=9ft2, d=9in, fc=3000psi, fy=60ksi, Ps~18.4kip Pu~26.2kip, etc.). The 68in punching perimeter in the PDF is inconsistent; implement ACI-correct bo=4*(c+d)=92in.
## Files to Modify
- `calcs/concentric-footing/calc.py` — create. Single module, no external deps beyond pyyaml/pint.
- `calcs/concentric-footing/input.yaml` — create. Pint-quoted strings for all dimensional inputs.
- `calcs/concentric-footing/results.json` — create (generated by running calc.py on the default input.yaml). Do not hand-edit.
If `calcs/concentric-footing/generated/` does not exist, do not create it here (Task 003 does).
## Implementation
### 1. input.yaml — defaults reproduce corrected Blavatnik example
Write YAML with these keys (order as listed, comments allowed):
```yaml
project: "Blavatnik"
prepared_by: "Conemco Engineering"
Ps: "18.4 kip" # service axial (checked demand)
Pu: "26.2 kip" # factored axial (checked demand, 1.2D+1.6L)
qa: "2500 psf" # allowable soil bearing (gross)
Bf: "3 ft" # square footing side
Df: "12 in" # total thickness
cover: "3 in" # to centroid of steel -> d = Df - cover
fc: "3000 psi" # f'c
fy: "60 ksi" # fy
lambda: 1 # lightweight factor (float, (0,1])
column_width: "14 in" # c, square column
base_plate_width: "6 in" # bp, square base plate (A1 = bp^2); if omitted in code defaults to c but YAML provides it
N: 4 # bars per direction
rebar_size: 4 # #4 -> db=0.5in
# Optional documentation keys (not used in compute, but keep for Typst derivation comments):
# DLr, LLr etc are NOT in input.yaml; Typst derives Ps/Pu there. This YAML holds checked demands only.
```
All quantities must be quoted strings so Pint parses them. `lambda`, `N`, `rebar_size` are unquoted numbers.
Accept alternative units via Pint (e.g. Bf as "36 in", fc as "3 ksi", Ps as "18400 lbf") — conversion handled in calc.py.
### 2. calc.py — implement compute(inp) -> dict
Create file at `calcs/concentric-footing/calc.py` with structure identical to `calcs/wood-joist/calc.py`:
- Imports: json, math, sys, argparse, pathlib Path, yaml, pint UnitRegistry, DimensionalityError etc.
- Define `HERE = Path(__file__).resolve().parent`
- `ureg = UnitRegistry()` and define `kip = 1000*force_pound`, `ksi = kip/inch**2`, `psf = force_pound/foot**2`, `pcf = force_pound/foot**3`, `plf`, `psi` if missing.
- Helper `quantity(value, unit, name) -> float`: `ureg.Quantity(value).to(unit).magnitude` with ValueError on bad dimension or <=0. Message must include field name.
- Helper `factor(value,name)` or inline validation for lambda (0<lambda<=1), integer checks for N and rebar_size.
- `def compute(inp: dict) -> dict:` implements pinned equations from PROJECT_STATE.md **verbatim**:
1. Parse:
```
Ps_kip = quantity(inp["Ps"],"kip","Ps")
Pu_kip = quantity(inp["Pu"],"kip","Pu")
qa_psf = quantity(inp["qa"],"psf","qa")
Bf_ft = quantity(inp["Bf"],"ft","Bf")
Df_in = quantity(inp["Df"],"in","Df")
cover_in = quantity(inp["cover"],"in","cover")
fc_psi = quantity(inp["fc"],"psi","fc")
fy_psi = quantity(inp["fy"],"psi","fy") # accept ksi via Pint -> psi
fy_ksi = fy_psi/1000
lambda_f = float(inp.get("lambda",1))
c_in = quantity(inp["column_width"],"in","column_width")
bp_in = quantity(inp.get("base_plate_width", inp["column_width"]),"in","base_plate_width")
N = int(inp["N"]); rebar_size = int(inp["rebar_size"])
```
Validate lambda (0,1], N>=1, rebar_size 3..18, d_in = Df_in - cover_in >0 else ValueError, Bf_in = Bf_ft*12, Af_ft2 = Bf_ft**2, Af_in2 = Af_ft2*144.
2. Derived rebar: db_in = rebar_size/8.0, As1_in2 = pi*db^2/4, As_in2 = N*As1_in2, rho = As_in2/(Bf_in*d_in), rho_min=0.0018
3. Pressures: Ps_lbf=Ps_kip*1000, Pu_lbf=Pu_kip*1000, q_psf = Ps_lbf/Af_ft2, qu_psf = Pu_lbf/Af_ft2
4. One-way: L1_in = (Bf_in - c_in)/2 - d_in; Vu_one = 0 if L1_in<=0 else qu_psf*Bf_ft*(L1_in/12)/1000 (kip); Vc_one_lbf = 2*lambda_f* sqrt(fc_psi) * Bf_in * d_in; phiVc =0.75*Vc/1000
5. Two-way: bo=4*(c_in+d_in); beta=1; alpha=40; vc1=4*lambda*sqrt(fc), vc2=(2+4/beta)*lambda*sqrt(fc), vc3=(2+alpha*d/bo)*lambda*sqrt(fc); vc=min(...); Vc_two = vc*bo*d/1000; phiVn=0.75*Vc; Apunch = (c+d)^2 /144 ft2; Vu_two = qu*(Af - Apunch)/1000
6. Flexure: Lc_in=(Bf_in - c_in)/2; Lc_ft = Lc_in/12. Mu_kipft = qu_psf * Bf_ft * Lc_ft**2 / 2 / 1000 (qu psf * Bf ft * Lc_ft^2 / 2 = lbf-ft, /1000 = kip-ft). a_in = As_in2*fy_psi/(0.85*fc_psi*Bf_in); beta1 = max(0.65, min(0.85, 0.85 - 0.05*max(0, (fc_psi-4000)/1000))); Mn_kipft = As_in2*fy_ksi*(d_in - a_in/2)/12; phiMn_kipft = 0.9*Mn_kipft
7. Bearing: A1=bp^2, A2=Af_in2, sqrt_ratio = sqrt(A2/A1), capped 2.0, Bn=0.85*fc_psi*A1*capped/1000, phiBn=0.65*Bn
8. Build values dict with keys listed in PROJECT_STATE.md, each q(value,6) rounded. Include N, rebar_size, db, As1, As etc. Use helper q=lambda v: round(float(v),6).
9. Build checks dict with 6 entries: soil_bearing, one_way_shear, two_way_shear, flexure, minimum_steel, bearing each {demand, capacity, ok}. For minimum_steel demand=rho_min capacity=rho.
10. Return {tool:"concentric_footing", version:"0.1", project: inp.get("project",""), prepared_by: inp.get("prepared_by",""), values:..., checks:...}
- Implement `main(argv)` with argparse `--input/-i` default HERE/"input.yaml", `--output/-o` default beside input, `--stdout` flag. Mirrors wood-joist: read yaml, compute, write json indent2, print path or stdout.
- `if __name__=="__main__": raise SystemExit(main())`
### 3. results.json
After writing calc.py and input.yaml, run `python calcs/concentric-footing/calc.py` (from worksheets root) to generate `calcs/concentric-footing/results.json`. Verify file exists and contains tool concentric_footing.
## Acceptance Criteria
1. `python calcs/concentric-footing/calc.py` exits 0 and writes `results.json` with `tool=="concentric_footing"` and `version=="0.1"`.
2. Re-running with `--stdout` produces identical JSON to the file (idempotent).
3. Converting alternative units yields same magnitudes: Bf "36 in" vs "3 ft", fc "3 ksi" vs "3000 psi", Ps "18400 lbf" vs "18.4 kip" within 1e-6 rel.
4. Wrong dimension raises ValueError with field name (e.g. `Bf: "3 kip"`).
5. Negative or zero values raise ValueError.
6. `d = Df - cover` validation: if cover >= Df, ValueError.
7. Values for default input within approx of corrected benchmark: q ~2044 psf (±30), qu~2911 psf, one-way phiVc~26.6 kip, two-way phiVn~136 kip, Mu~3.68 kip-ft, phiMn~30.8 kip-ft, rho~0.0024, phiBn~119 kip. (Exact locks in Task 002.)
8. No existing calcs are modified.
## Tests
Do not create tests in this task. Manual verification commands (builder runs, reviewer will run pytest after Task 002):
```
python -m pip install -r requirements.txt
python calcs/concentric-footing/calc.py
python calcs/concentric-footing/calc.py --stdout | python -m json.tool
python -c "import yaml, importlib.util; spec=importlib.util.spec_from_file_location('c','calcs/concentric-footing/calc.py'); m=importlib.util.module_from_spec(spec); spec.loader.exec_module(m); print(m.compute(yaml.safe_load(open('calcs/concentric-footing/input.yaml'))))"
```
## Dependencies
None.

View file

@ -0,0 +1,110 @@
# Task 002 — Numerical lock: test_concentric_footing.py (compute() only)
## Goal
Lock the corrected Blavatnik benchmark in pytest so the calculator cannot drift, and guard Pint units and applicability limits.
## Background
Depends on Task 001 contract. This task is purely numerical: it imports `calc.py:compute` and asserts `pytest.approx` on every value name. It does not require Typst. The reference PDF contains known inconsistencies (68in vs 92in punching perimeter, plate vs column area, 66in textual dimension vs 36in computed Af); tests lock the ACI-correct values documented in PROJECT_STATE.md.
All assertions target values produced by `calc.py:compute()` sub-blocks: Pressures, One-way shear, Two-way shear, Flexure, Concrete bearing.
## Files to Modify
- `calcs/concentric-footing/test_concentric_footing.py` — create.
- `calcs/concentric-footing/calc.py` — read-only, do not edit.
- `calcs/concentric-footing/input.yaml` — read-only.
- `calcs/concentric-footing/results.json` — read-only.
## Implementation
Create `calcs/concentric-footing/test_concentric_footing.py` following `calcs/wood-joist/test_wood_joist.py` structure:
- Imports: pathlib Path, importlib.util, json, subprocess, sys, pytest, yaml
- Load calc module via `importlib.util.spec_from_file_location("concentric_footing_calc", HERE/"calc.py")`; `compute = calc_module.compute`
- Helper `load_input()` reads `HERE/"input.yaml"` with yaml.safe_load
- `@pytest.fixture def result(): return compute(load_input())`
### Tests to implement (each as `def test_*` function)
1. `test_example_pressures_and_geometry(result)` — asserts:
- `Af_ft2 == 9.0` approx
- `Bf_ft == 3.0`, `Bf_in == 36.0`
- `d_in == 9.0`
- `q_psf == pytest.approx(2044.44, rel=0.01)` (18.4k/9) — allow 1% because Ps 18.4 vs derived 18.36
- `qu_psf == pytest.approx(2911.11, rel=0.01)` (26.2/9)
- `qa_psf == 2500.0`
2. `test_example_one_way_shear(result)` — asserts:
- `L1_in == pytest.approx(2.0, abs=0.01)` ((36-14)/2 -9 =2)
- `Vu_one_way_kip == pytest.approx(1.455, abs=0.05)` (qu*Bf*L1)
- `Vc_one_way_kip == pytest.approx(35.45, rel=0.01)` (2*sqrt(3000)*36*9/1000)
- `phiVc_one_way_kip == pytest.approx(26.59, rel=0.01)`
- `checks["one_way_shear"]["ok"] is True`
- D/C approx 0.055
3. `test_example_two_way_shear(result)` — asserts corrected ACI values:
- `bo_in == pytest.approx(92.0)` (4*(14+9))
- `vc_psi == pytest.approx(219.089, rel=1e-3)` (4*sqrt(3000))
- `Vc_two_way_kip == pytest.approx(181.4, rel=0.02)` (vc*bo*d)
- `phiVn_two_way_kip == pytest.approx(136.0, rel=0.02)`
- `Vu_two_way_kip == pytest.approx(15.51, abs=0.1)` (qu*(9 - (23/12)^2))
- `checks["two_way_shear"]["ok"] is True`
- Document that reference PDF reports bo 68in and Vc 134kip; this test locks ACI-correct 92in.
4. `test_example_flexure(result)` — asserts:
- `Lc_in == pytest.approx(11.0)` ((36-14)/2)
- `Mu_kipft == pytest.approx(3.68, abs=0.1)` (qu*Bf*Lc^2/2)
- `a_in == pytest.approx(0.524, abs=0.02)` (As*fy/(0.85*fc*B))
- `As_in2 == pytest.approx(0.785, abs=0.02)` (4*#4 -> 4*0.196=0.785; reference rounds to 0.8, accept both with rel 0.03 but assert within 0.785±0.02)
- `Mn_kipft == pytest.approx(34.27, abs=0.5)`
- `phiMn_kipft == pytest.approx(30.84, abs=0.5)`
- `rho == pytest.approx(0.00242, rel=0.02)`
- `checks["flexure"]["ok"] is True`
- `checks["minimum_steel"]["ok"] is True` (rho >=0.0018)
5. `test_example_bearing(result)` — asserts:
- `A1_in2 == pytest.approx(36.0)` (6*6)
- `A2_in2 == pytest.approx(1296.0)` (36*36)
- `sqrt_ratio == pytest.approx(6.0, abs=0.01)` capped at 2 for Bn actually but store raw ratio and report capped separately? Store raw 6.0 and separately use capped 2 for Bn; test asserts stored sqrt_ratio is 6.0 and Bn uses capped 2.
- `Bn_kip == pytest.approx(183.6, abs=0.5)` (0.85*3000*36*2/1000)
- `phiBn_kip == pytest.approx(119.34, abs=0.5)`
- `checks["bearing"]["ok"] is True`
6. `test_all_checks_pass(result)` — asserts all six checks ok is True.
7. `test_alternate_units_match_default(result)` — copies input, replaces Bf with "36 in", fc with "3 ksi", fy with "60000 psi", Ps with "18400 lbf", Pu with "26200 lbf" etc, computes converted, asserts for keys ("Af_ft2","q_psf","Mu_kipft","Vu_one_way_kip","phiBn_kip") approx equal rel 1e-6.
8. `test_wrong_dimension_is_rejected()` — sets `Bf: "3 kip"` and expects ValueError match "Bf".
9. `test_effective_depth_validation()` — sets cover "13 in" with Df "12 in" (d negative) expects ValueError.
10. `test_zero_footing_size_rejected()` — sets Bf "0 ft" expects ValueError.
If any additional guard is implemented (lambda >1, N zero) add matching tests, but at minimum the 10 above.
Each test that reads values should use `v = result["values"]` and `pytest.approx`. The file must be runnable with `python -m pytest calcs/concentric-footing/test_concentric_footing.py -v`.
## Acceptance Criteria
1. `python -m pytest calcs/concentric-footing/test_concentric_footing.py -v` shows at least 10 tests, all passed.
2. Tests lock the corrected benchmark within stated tolerances; changing any equation in calc.py causes at least one failure.
3. Wrong-dimension and validation tests raise ValueError with correct field name.
4. Alternate units test demonstrates Pint equivalence.
5. No modification to `calc.py`, `input.yaml`, `results.json`.
## Tests
Builder runs:
```
python -m pip install -r requirements.txt
python -m pytest calcs/concentric-footing/test_concentric_footing.py -v
```
Expected: `10 passed` (or more if extra guards).
## Dependencies
Task 001 must be DONE.

View file

@ -0,0 +1,163 @@
# Task 003 — Presentation: footing.typ + compile + Typst metadata tests
## Goal
Present the checked numbers in a printable Typst sheet that also derives the Blavatnik gravity loads inline, emits queryable metadata, and compiles to PDF.
## Background
Architecture: `footing.typ` imports `../../lib/sheet.typ` and `json("results.json")`. It must not recompute capacities; it only presents `results.json` values via `calc-line` and `check` boxes. Load determination (roof DL/LL, tributary area, column self weight) is derived in Typst and reconciled to Python's checked `Ps`/`Pu` by the test suite — mirroring `wood-joist` and `steel-beam` where `<wood-joist-loads>` is queried.
The `check`, `calc-line`, and `calculation-sheet` helpers are defined in `lib/sheet.typ` (worksheets root). Signatures used here: `check(label, demand, capacity, unit:, ok:)`, `calc-line(content, note)`, and `calculation-sheet.with(title:, project:, prepared-by:)`.
## Files to Modify
- `calcs/concentric-footing/footing.typ` — create.
- `calcs/concentric-footing/generated/footing.pdf` — create via `typst compile --root .`.
- `calcs/concentric-footing/test_concentric_footing.py` — append two Typst query tests (do not rewrite existing tests); create `generated/` dir if needed.
## Implementation
### 1. footing.typ structure
Follow `calcs/wood-joist/beam.typ` as template:
- Header:
```
#import "../../lib/sheet.typ": calc-line, calculation-sheet, check
#let data = json("results.json")
#let n = data.values
#let checks = data.checks
#let round(value, digits: 2) = calc.round(value, digits: digits)
#show: calculation-sheet.with(title: "Concentric Footing Analysis", project: data.project, prepared-by: data.prepared_by)
= Concentric Footing Analysis
Square spread footing under concentric axial load, ACI 318-19. Numbers come from `calc.py`; this sheet only presents them. Typst derives gravity loads below; checked Python demands are reconciled by the test suite.
```
- Add a simple footing sketch using Typst `box`/`rect`/`line` drawing (no external image needed). Example: centered square footing with column on top, label `Bf` and `Df`. Wrap in `#figure(..., caption: [Footing plan and section: #n.Bf_ft ft × #n.Bf_ft ft × #n.Df_in in, d=#n.d_in in.])`. Keep geometry text as `calc-line` below.
- Section `== Loads Determination`:
Derive Blavatnik loads in Typst (visible arithmetic):
```
#let DLr = 10 // psf
#let LLr = 20 // psf
#let Br = 18.9 // ft
#let Lr = 27.5 // ft
#let Ar = Br * Lr // ft2
#let bc = 14 // in
#let Lc = 14 // ft
#let gamma_c = 145 // pcf
#let Wc_kip = bc * bc / 144 * Lc * gamma_c / 1000 // kip column weight
#let Ps_typst = (DLr + LLr) * Ar / 1000 + Wc_kip // kip
#let Pu_typst = 1.2*(DLr*Ar/1000 + Wc_kip) + 1.6*LLr*Ar/1000
#metadata((Ps_kip: Ps_typst, Pu_kip: Pu_typst, Ar_ft2: Ar, Wc_kip: Wc_kip)) <concentric-footing-loads>
```
Then emit `calc-line` rows:
- `Ar = Br·Lr = #round(Ar,2) ft2` (tributary area)
- `Wc = bc·bc·Lc·γc = #round(Wc_kip,2) kip` (column self weight)
- `Ps = (DLr+LLr)·Ar + Wc = #round(Ps_typst,2) kip (Typst-derived)`
- `Ps_checked = #round(n.Ps_kip,2) kip (Python-checked)`
- `Pu = 1.2(DLr·Ar+Wc)+1.6·LLr·Ar = #round(Pu_typst,2) kip (Typst-derived)`
- `Pu_checked = #round(n.Pu_kip,2) kip`
- Also show `qu = Pu/Af = #round(n.qu_psf,1) psf` for context but do not recompute Af.
- Section `== Geometry and Materials`:
`calc-line` for Bf, Df, cover, d, Af, c, bp, fc, fy, lambda, N, rebar_size, As, rho. Example:
`calc-line([$B_f = #n.Bf_ft " ft"$, $A_f = #n.Af_ft2 " ft"^2$], [Footing plan area])` etc. Show As1, As, rho, rho_min.
- Section `== Soil Bearing`:
`calc-line([$q = P_s/A_f = #round(n.q_psf,1) " psf"$], [Acting service pressure])`
`calc-line([$q_a = #n.qa_psf " psf"$], [Allowable])`
Then `#check("Soil bearing", checks.soil_bearing.demand, checks.soil_bearing.capacity, unit: "psf", ok: checks.soil_bearing.ok)`
Also show `qu` as info line.
- Section `== One-Way Shear`:
`calc-line([$L_1 = (B_f - c)/2 - d = #round(n.L1_in,2) " in"$], [Cantilever beyond d])`
`calc-line([$V_u = q_u B_f L_1 = #round(n.Vu_one_way_kip,2) " kip"$], [Demand at d])`
`calc-line([$V_c = 2 lambda sqrt(f'_c) B_f d = #round(n.Vc_one_way_kip,1) " kip"$], [ACI 22.5])`
`calc-line([$phi V_c = #round(n.phiVc_one_way_kip,1) " kip"$], [phi=0.75])`
`#check("One-way shear", checks.one_way_shear.demand, checks.one_way_shear.capacity, unit: "kip", ok: checks.one_way_shear.ok)`
- Section `== Two-Way Shear (Punching)`:
`calc-line([$b_o = 4(c+d)= #n.bo_in " in"$], [Critical perimeter, d/2])`
`calc-line([$v_c = min(4,2+4/beta,2+alpha d/b_o) lambda sqrt(f'_c)= #round(n.vc_psi,1) " psi"$], [ACI 22.6])`
`calc-line([$V_c = v_c b_o d = #round(n.Vc_two_way_kip,1) " kip"$], [])`
`calc-line([$V_u = q_u(A_f - (c+d)^2)= #round(n.Vu_two_way_kip,1) " kip"$], [Punch demand])`
`#check("Two-way shear", checks.two_way_shear.demand, checks.two_way_shear.capacity, unit: "kip", ok: checks.two_way_shear.ok)`
- Section `== Flexure`:
`calc-line([$L_c = (B_f - c)/2 = #round(n.Lc_in,1) " in"$], [Cantilever])`
`calc-line([$M_u = q_u B_f L_c^2/2 = #round(n.Mu_kipft,2) " kip·ft"$], [])`
`calc-line([$a = A_s f_y/(0.85 f'_c B_f)= #round(n.a_in,3) " in"$], [Whitney block])`
`calc-line([$M_n = A_s f_y(d -a/2)= #round(n.Mn_kipft,1) " kip·ft"$], [])`
`calc-line([$rho = A_s/(B_f d)= #round(n.rho,4)$], [vs rho_min 0.0018])`
`#check("Flexure", checks.flexure.demand, checks.flexure.capacity, unit: "kip·ft", ok: checks.flexure.ok)`
`#check("Minimum steel", checks.minimum_steel.demand, checks.minimum_steel.capacity, unit: "", ok: checks.minimum_steel.ok)` — for rho, show ratio but check helper expects demand/capacity; use demand=rho_min capacity=rho; label accordingly.
- Section `== Concrete Bearing`:
`calc-line([$A_1 = b_p^2 = #round(n.A1_in2,1) " in"^2$, $A_2 = B_f^2 = #round(n.A2_in2,1) " in"^2$], [Plate and footing])`
`calc-line([$sqrt(A_2/A_1)= #round(n.sqrt_ratio,2)$, capped at 2], [])`
`calc-line([$B_n = 0.85 f'_c A_1 sqrt(...)= #round(n.Bn_kip,1) " kip"$], [ACI 22.8])`
`calc-line([$phi B_n = #round(n.phiBn_kip,1) " kip"$], [phi=0.65])`
`#check("Concrete bearing", checks.bearing.demand, checks.bearing.capacity, unit: "kip", ok: checks.bearing.ok)`
- Section `== Scope And Limitations`:
Text stating square footing only, interior concentric axial only, gross pressure, no moment/overturning/sliding, no settlement, d from cover to centroid, bo correction noted (reference 68in corrected to ACI 92in), plate vs column clarification, no deflection/crack/development, final design by engineer.
- Footer metadata for reconciliation:
```
#metadata((soil_util: checks.soil_bearing.demand/checks.soil_bearing.capacity, one_way_util: checks.one_way_shear.demand/checks.one_way_shear.capacity, two_way_util: checks.two_way_shear.demand/checks.two_way_shear.capacity, flexure_util: checks.flexure.demand/checks.flexure.capacity, bearing_util: checks.bearing.demand/checks.bearing.capacity, q_psf: n.q_psf, qu_psf: n.qu_psf)) <concentric-footing-results>
```
Ensure all `n.*` keys match Task 001 values dict exactly.
### 2. Compile
From `worksheets/` run:
```
python calcs/concentric-footing/calc.py
typst compile --root . calcs/concentric-footing/footing.typ calcs/concentric-footing/generated/footing.pdf
```
Verify PDF exists and >50KB.
### 3. Append Typst query tests
Append to `calcs/concentric-footing/test_concentric_footing.py` two new tests (do not delete existing 10):
- `test_typst_compiles_and_presents_python_numbers(result)` — runs `calc.py` with `subprocess.run([sys.executable, str(HERE/"calc.py")], check=True, cwd=HERE.parents[1])`, then `typst compile ...` check pdf exists, then `typst query` for `<concentric-footing-results>` via `typst eval "query(<concentric-footing-results>)"`? Actually use `typst eval` or `typst query` command as in wood-joist: `subprocess.run(["typst","query", ...])`? Wood-joist uses `typst compile` and `typst eval query`. Use same pattern as wood-joist test:
```
subprocess.run(["typst","compile","--root",".",...], check=True, cwd=HERE.parents[1])
query = subprocess.run(["typst","query","..."]?)
```
Check wood-joist: it runs `["typst","eval","query(<wood-joist-results>)","--root",...,"--in","calcs/wood-joist/beam.typ","--format","json"]`. Mirror that: `["typst","query", str(HERE/"footing.typ"), "<concentric-footing-results>", "--root", "."]` may vary; adapt to whatever works but assert exactly one entry and that flexure_util approx equals Python f. Specifically query the published metadata and assert `meta["flexure_util"] approx values["Mu"]/values["phiMn"]` etc for soil, one-way, two-way, bearing.
- `test_typst_load_demands_match_checked_inputs(result)` — queries `<concentric-footing-loads>` and asserts `derived Ps_kip approx values["Ps_kip"]` within 0.1 kip (allow rounding of column weight 18.36 vs 18.4) and same for `Pu_kip`.
Implementation must be robust: if `typst query` syntax differs, use `typst compile` + `typst eval` as in wood-joist. Ensure tests pass on the CI image where typst is installed.
If `generated/` does not exist, create it with `Path(...).mkdir(parents=True, exist_ok=True)`.
## Acceptance Criteria
1. `footing.typ` imports only `lib/sheet.typ` and `results.json`; no arithmetic beyond load derivation and rounding.
2. Every `check` box reflects `checks.*.ok` from JSON; D/C printed as demand/capacity.
3. `typst compile --root . calcs/concentric-footing/footing.typ calcs/concentric-footing/generated/footing.pdf` succeeds and PDF exists.
4. Two appended pytest tests pass, reconciling Typst-derived Ps/Pu to Python-checked Ps/Pu and Typst-presented utils to Python values.
5. All prior 10 tests still pass (total 12).
6. No existing calc files modified; `generated/` is git-ignored regenerable.
## Tests
Builder runs:
```
python calcs/concentric-footing/calc.py
typst compile --root . calcs/concentric-footing/footing.typ calcs/concentric-footing/generated/footing.pdf
python -m pytest calcs/concentric-footing/test_concentric_footing.py -v
```
Expected: 12 passed, PDF exists.
## Dependencies
Tasks 001, 002 must be DONE.

View file

@ -0,0 +1,73 @@
# Task 004 — Documentation refresh: README.md + codemap.md
## Goal
Index the new concentric footing calculation in the shared documentation so the next engineer can discover and compile it without reading source.
## Background
Depends on footing.typ existing. This task is typst-builder-local (documentation only). Conventions per PROJECT_STATE.md: compile with --root ., hybrid pattern, no modification to existing calcs.
## Files to Modify
- `README.md` — the shared worksheets readme that lists calcs. At present this file lives at `calcs/wood-joist/README.md` which serves as the de-facto worksheets README (it documents all sheets). Also check for `README.md` at `worksheets/` root if it exists. Update whichever exists; if both exist update both with same concentric-footing entry. If only `calcs/wood-joist/README.md` exists, that is the file to edit.
- `codemap.md` — update at `worksheets/codemap.md` (and copy to `calcs/concentric-footing/codemap.md` if the per-calc map is expected). Regenerate the whole map rather than editing in place per codemap rules.
## Implementation
### 1. README.md
Add a new section `## Concentric footing` after the Wood joist section, following the same style. Include:
- One-sentence description: "Square concentric spread footing under axial load per ACI 318-19 — soil bearing, one-way/two-way shear, flexure, minimum steel, concrete bearing."
- Compile commands:
```
python calcs/concentric-footing/calc.py
typst compile --root . calcs/concentric-footing/footing.typ calcs/concentric-footing/generated/footing.pdf
python -m pytest calcs/concentric-footing/test_concentric_footing.py
```
- Stdout variant:
```
python calcs/concentric-footing/calc.py --input calcs/concentric-footing/input.yaml --stdout
```
and `--output` note.
- Note on load derivation: `input.yaml` supplies checked `Ps`/`Pu` (Pint quantities) and footing geometry/materials; `footing.typ` derives `Ps`/`Pu` inline from `DLr=10psf, LLr=20psf, Br=18.9ft, Lr=27.5ft, column 14in×14ft @145pcf` and reconciles via `<concentric-footing-loads>` query; bearing plate width `bp=6in` governs `A1`.
- Update the top index code block to add line:
```
calcs/concentric-footing/ YAML quantities → Pint → JSON → Typst (ACI 318-19)
```
- Ensure the 5-step New calculation list remains unchanged.
If editing `worksheets/README.md` vs `calcs/wood-joist/README.md`, keep both in sync; prefer editing the file that actually exists and then copying the change to the other if both are present.
### 2. codemap.md
Regenerate at `worksheets/codemap.md` (and also write copy to `calcs/concentric-footing/codemap.md` if needed for per-calc root check):
- Re-run classification for all 37+ files including the new `calcs/concentric-footing/calc.py [logic]`, `input.yaml [config]`, `footing.typ [logic]`, `test_concentric_footing.py [test]`, `results.json [state]`, `generated/footing.pdf [doc]`, `CONCENTRIC-FOOTING.pdf [doc]`.
- The layout section must now show `calcs/concentric-footing/` expanded with its 5 planned + 3 reference entries.
- Hot Spots must now include `calcs/concentric-footing/calc.py` as single source of truth.
- Conventions section must mention the new sheet's hybrid Pint pattern and Typst load derivation.
- Timestamp updated to now, Files indexed incremented.
Do not write summaries from imagination; if uncertain read first 20 lines.
## Acceptance Criteria
1. `README.md` contains a new `## Concentric footing` section with compile, stdout, and load-derivation notes; top index code block lists the new calc.
2. `codemap.md` at `worksheets/codemap.md` exists, is well-formed markdown with header, layout, hot spots, conventions; it lists `calcs/concentric-footing/` and its files.
3. `python -m pytest calcs/concentric-footing/test_concentric_footing.py -v` still passes (12 tests).
4. No existing calc logic files modified; only docs/maps changed.
## Tests
```
python -m pytest calcs/concentric-footing/test_concentric_footing.py -v
typst compile --root . calcs/concentric-footing/footing.typ calcs/concentric-footing/generated/footing.pdf
```
Both succeed; PDF still compiles.
## Dependencies
Task 003 must be DONE.

View file

@ -0,0 +1,69 @@
# Task 005 — Reviewer pass on the whole calculation
## Goal
Verify engineering correctness, deterministic evidence, and documentation for the concentric footing analysis before marking the project done.
## Background
This task is reviewer-local (reasoning) with simplify skill pass. It must not modify source except via review report; if issues are found the orchestrator will send them back to the builder. The reviewer must check ACI 318-19 clause references, units, applicability limits, benchmark tolerances, and that the Typst sheet presents only (no recomputation) per PROJECT_STATE.md.
## Files to Modify
No files to modify in this task. The reviewer writes a review note (verbal output) and runs the simplify skill as part of the standard review pass. If STATUS: FAIL, the orchestrator updates TASKS.md and re-delegates.
If the reviewer finds fixable issues, they must be reported as a structured list with file and line references.
## Implementation
Reviewer steps (read-only, then run commands via delegation tool if needed — but orchestrator handles command execution; reviewer describes what to run and checks output):
1. Read `PROJECT_STATE.md`, `TASKS.md`, `calcs/concentric-footing/calc.py`, `input.yaml`, `results.json`, `footing.typ`, `test_concentric_footing.py`, `README.md`, `codemap.md`, and `CONCENTRIC-FOOTING.pdf`.
2. Verify engineering spec. Formula → code-section map (all in `calc.py:compute()`):
- Soil bearing `q=Ps/Af`, `qu=Pu/Af`: Pressures block → `q_psf`, `qu_psf`.
- One-way shear `Vc=2·λ·√fc·B·d`, `Vu=qu·B·L1`: One-way shear block → `L1_in`, `Vu_one_way_kip`, `Vc_one_way_kip`, `phiVc_one_way_kip`.
- Two-way shear `bo=4(c+d)`, `vc=min(4,2+4/β,2+α·d/bo)·λ·√fc`, `Vu=qu·(Af-(c+d)²)`: Two-way shear block → `bo_in`, `vc_psi`, `Vu_two_way_kip`, `Vc_two_way_kip`, `phiVn_two_way_kip`.
- Flexure `Mu=qu·B·Lc²/2`, `a=As·fy/(0.85·fc·B)`, `Mn=As·fy·(d-a/2)`: Flexure block → `Lc_in`, `Mu_kipft`, `a_in`, `beta1`, `Mn_kipft`, `phiMn_kipft`.
- Bearing `Bn=0.85·fc·A1·min(√(A2/A1),2)`: Concrete bearing block → `A1_in2`, `A2_in2`, `sqrt_ratio`, `Bn_kip`, `phiBn_kip`.
- Soil bearing `q=Ps/Af` and `qu=Pu/Af` correctly use Af=Bf^2 in ft2, Ps/Pu in kip, qa in psf, D/C correct.
- One-way shear Vc=2*lambda*sqrt(fc)*B*d with phi 0.75, L1 = (B-c)/2 - d, Vu = qu*B*L1, correct unit conversion lbf->kip, handles L1<=0 edge.
- Two-way shear bo=4*(c+d), vc=min(4,2+4/beta,2+alpha*d/bo)*lambda*sqrt(fc) with alpha 40 interior, beta 1, phi 0.75, Vu=qu*(Af - (c+d)^2), bo correction documented.
- Flexure Mu=qu*B*Lc^2/2, a=As*fy/(0.85*fc*B), Mn=As*fy*(d-a/2), phi 0.9, beta1 formula per ACI, rho vs 0.0018.
- Bearing Bn=0.85*fc*A1*min(sqrt(A2/A1),2), phi 0.65, A1=bp^2, A2=Bf^2, sqrt cap.
- d = Df - cover to centroid, validation, lambda bounds, rebar area from #size.
3. Verify deterministic evidence:
- Run `python -m pytest calcs/concentric-footing/test_concentric_footing.py -v` and confirm 12 passed, no skipped.
- Run `python calcs/concentric-footing/calc.py --stdout | python -m json.tool` and confirm idempotent vs results.json (diff empty).
- Run `typst compile --root . calcs/concentric-footing/footing.typ calcs/concentric-footing/generated/footing.pdf` and confirm PDF exists and size >50KB.
- Run Typst queries for `<concentric-footing-loads>` and `<concentric-footing-results>` and confirm reconciliation within tolerances.
4. Check scope/limitations note in footing.typ mentions square only, interior only, gross pressure, no moment, bo correction, plate clarification, d definition, and that existing calc files were not touched.
5. Run simplify skill pass on the diff (calc.py + footing.typ + test file) for readability, no behavior change.
6. Return STATUS: PASS if all 8 checks below are satisfied, else STATUS: FAIL with enumerated issues.
## Acceptance Criteria (all must be true for PASS)
1. All six checks pass for default input; D/C values within expected ranges (soil ~0.82, one-way ~0.05, two-way ~0.11, flexure ~0.12, bearing ~0.22).
2. Corrected punching perimeter bo=92in is used; review notes the PDF's 68in deviation and that the sheet's Scope documents it.
3. Bearing plate vs column clarified (A1=36in2, A2=1296in2, Bn 183.6kip); alternative use of column size would be noted.
4. Pint unit conversions tested (alternate units test passes) and wrong-dimension guards raise ValueError with field name.
5. Effective depth d = Df - cover correctly validated; zero/negative d raises ValueError.
6. Typst sheet presents only (no capacity recomputation), derives loads inline, emits both `<concentric-footing-loads>` and `<concentric-footing-results>` metadata, and compiles.
7. README and codemap refreshed and list the new calculation; no existing calc files were modified (git diff or file timestamps check).
8. Pytest 12 passed, PDF compiles, results.json idempotent, simplify pass clean (no behavior change).
## Tests
Reviewer (via orchestrator delegation) runs:
```
python -m pip install -r requirements.txt
python -m pytest calcs/concentric-footing/test_concentric_footing.py -v
python calcs/concentric-footing/calc.py --stdout
typst compile --root . calcs/concentric-footing/footing.typ calcs/concentric-footing/generated/footing.pdf
```
All succeed; 12 passed.
## Dependencies
Task 004 must be DONE.

View file

@ -0,0 +1,170 @@
from pathlib import Path
import importlib.util
import json
import subprocess
import sys
import pytest
import yaml
HERE = Path(__file__).resolve().parent
spec = importlib.util.spec_from_file_location("concentric_footing_calc", HERE / "calc.py")
assert spec is not None and spec.loader is not None
calc_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(calc_module)
compute = calc_module.compute
def load_input():
with (HERE / "input.yaml").open(encoding="utf-8") as handle:
return yaml.safe_load(handle)
@pytest.fixture
def result():
return compute(load_input())
def test_example_pressures_and_geometry(result):
v = result["values"]
assert v["Af_ft2"] == pytest.approx(9.0)
assert v["Bf_ft"] == pytest.approx(3.0)
assert v["Bf_in"] == pytest.approx(36.0)
assert v["d_in"] == pytest.approx(9.0)
assert v["q_psf"] == pytest.approx(2044.44, rel=0.01)
assert v["qu_psf"] == pytest.approx(2911.11, rel=0.01)
assert v["qa_psf"] == 2500.0
def test_example_one_way_shear(result):
v = result["values"]
assert v["L1_in"] == pytest.approx(2.0, abs=0.01)
assert v["Vu_one_way_kip"] == pytest.approx(1.455, abs=0.05)
assert v["Vc_one_way_kip"] == pytest.approx(35.45, rel=0.01)
assert v["phiVc_one_way_kip"] == pytest.approx(26.59, rel=0.01)
assert result["checks"]["one_way_shear"]["ok"] is True
dc = v["Vu_one_way_kip"] / v["phiVc_one_way_kip"]
assert dc == pytest.approx(0.055, abs=0.001)
def test_example_two_way_shear(result):
v = result["values"]
# Reference PDF used 68 in; ACI-correct is 92 in (4*(c+d) for interior square column).
# PDF's 68 in perimeter yields ~134 kip Vc; ACI-correct 92 in yields ~181.4 kip Vc (phiVn ~136 kip).
assert v["bo_in"] == pytest.approx(92.0)
assert v["vc_psi"] == pytest.approx(219.089, rel=1e-3)
assert v["Vc_two_way_kip"] == pytest.approx(181.4, rel=0.02)
assert v["phiVn_two_way_kip"] == pytest.approx(136.0, rel=0.02)
assert v["Vu_two_way_kip"] == pytest.approx(15.51, abs=0.1)
assert result["checks"]["two_way_shear"]["ok"] is True
dc = v["Vu_two_way_kip"] / v["phiVn_two_way_kip"]
assert dc == pytest.approx(0.114, abs=0.002)
def test_example_flexure(result):
v = result["values"]
assert v["Lc_in"] == pytest.approx(11.0)
assert v["Mu_kipft"] == pytest.approx(3.68, abs=0.1)
assert v["a_in"] == pytest.approx(0.524, abs=0.02)
assert v["As_in2"] == pytest.approx(0.785, abs=0.02)
assert v["Mn_kipft"] == pytest.approx(34.27, abs=0.5)
assert v["phiMn_kipft"] == pytest.approx(30.84, abs=0.5)
assert v["rho"] == pytest.approx(0.00242, rel=0.02)
assert result["checks"]["flexure"]["ok"] is True
assert result["checks"]["minimum_steel"]["ok"] is True
dc = v["Mu_kipft"] / v["phiMn_kipft"]
assert dc == pytest.approx(0.12, abs=0.01)
def test_example_bearing(result):
v = result["values"]
assert v["A1_in2"] == pytest.approx(36.0)
assert v["A2_in2"] == pytest.approx(1296.0)
# Raw ratio stored; Bn uses capped 2.0.
assert v["sqrt_ratio"] == pytest.approx(6.0, abs=0.01)
assert v["Bn_kip"] == pytest.approx(183.6, abs=0.5)
assert v["phiBn_kip"] == pytest.approx(119.34, abs=0.5)
assert result["checks"]["bearing"]["ok"] is True
dc = v["Pu_kip"] / v["phiBn_kip"]
assert dc == pytest.approx(0.22, abs=0.01)
def test_all_checks_pass(result):
for k in ("soil_bearing", "one_way_shear", "two_way_shear", "flexure", "minimum_steel", "bearing"):
assert result["checks"][k]["ok"] is True
def test_alternate_units_match_default(result):
alt = load_input()
alt.update({
"Bf": "36 in",
"fc": "3 ksi",
"fy": "60000 psi",
"Ps": "18400 lbf",
"Pu": "26200 lbf",
})
converted = compute(alt)
for key in ("Af_ft2", "q_psf", "Mu_kipft", "Vu_one_way_kip", "phiBn_kip"):
assert converted["values"][key] == pytest.approx(result["values"][key], rel=1e-6)
def test_wrong_dimension_is_rejected():
bad = load_input()
bad["Bf"] = "3 kip"
with pytest.raises(ValueError, match="Bf"):
compute(bad)
def test_effective_depth_validation():
bad = load_input()
bad["cover"] = "13 in"
bad["Df"] = "12 in"
with pytest.raises(ValueError, match="d"):
compute(bad)
def test_zero_footing_size_rejected():
bad = load_input()
bad["Bf"] = "0 ft"
with pytest.raises(ValueError, match="Bf"):
compute(bad)
def test_typst_compiles_and_presents_python_numbers(result):
subprocess.run([sys.executable, str(HERE / "calc.py")], check=True, cwd=HERE.parents[1])
pdf = HERE / "generated" / "footing.pdf"
pdf.parent.mkdir(parents=True, exist_ok=True)
subprocess.run(
["typst", "compile", "--root", ".", "calcs/concentric-footing/footing.typ", str(pdf)],
check=True, cwd=HERE.parents[1],
)
assert pdf.exists()
query = subprocess.run(
["typst", "eval", "query(<concentric-footing-results>)", "--root", ".",
"--in", "calcs/concentric-footing/footing.typ", "--format", "json"],
check=True, capture_output=True, text=True, cwd=HERE.parents[1],
)
published = json.loads(query.stdout)
assert len(published) == 1
meta = published[0]["value"]
values = result["values"]
assert meta["soil_util"] == pytest.approx(values["q_psf"] / values["qa_psf"], abs=0.001)
assert meta["one_way_util"] == pytest.approx(values["Vu_one_way_kip"] / values["phiVc_one_way_kip"], abs=0.001)
assert meta["two_way_util"] == pytest.approx(values["Vu_two_way_kip"] / values["phiVn_two_way_kip"], abs=0.001)
assert meta["flexure_util"] == pytest.approx(values["Mu_kipft"] / values["phiMn_kipft"], abs=0.001)
assert meta["bearing_util"] == pytest.approx(values["Pu_kip"] / values["phiBn_kip"], abs=0.001)
def test_typst_load_demands_match_checked_inputs(result):
subprocess.run([sys.executable, str(HERE / "calc.py")], check=True, cwd=HERE.parents[1])
query = subprocess.run(
["typst", "eval", "query(<concentric-footing-loads>)", "--root", ".",
"--in", "calcs/concentric-footing/footing.typ", "--format", "json"],
check=True, capture_output=True, text=True, cwd=HERE.parents[1],
)
published = json.loads(query.stdout)
assert len(published) == 1
derived = published[0]["value"]
values = result["values"]
assert derived["Ps_kip"] == pytest.approx(values["Ps_kip"], abs=0.1)
assert derived["Pu_kip"] == pytest.approx(values["Pu_kip"], abs=0.1)

BIN
concrete-beam/assets/logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View file

@ -0,0 +1,82 @@
#let navy = rgb("#1a3a5f")
#let muted = rgb("#626b73")
#let pass = rgb("#1f6b45")
#let fail = rgb("#9b2c2c")
#let calcsheet(
title: "Structural Calculation",
project: "",
prepared-by: "",
body,
) = {
set document(title: title, author: prepared-by)
set page(
paper: "us-letter",
margin: (x: 1in, top: 1.25in, bottom: 1in),
header: context {
grid(
columns: (1fr, 1fr),
align: (left, right),
image("../assets/logo.png", height: 30pt),
[#text(size: 9pt)[Project:] \
#text(size: 10pt, weight: "bold")[#project]],
)
},
footer: context {
set text(size: 8.5pt, fill: muted)
stack(
spacing: 4pt,
line(length: 100%, stroke: 0.5pt + muted),
[#prepared-by],
)
},
)
set text(font: "Libertinus Serif", size: 10pt, lang: "en")
set par(justify: true)
set heading(numbering: none)
show heading.where(level: 1): set text(size: 14pt, weight: "bold", fill: black)
show heading.where(level: 2): set text(size: 11pt, weight: "bold", fill: black)
show heading.where(level: 2): set block(above: 2em, below: 1em)
body
}
#let calcline(formula, note) = grid(
columns: (1.7fr, 1fr),
gutter: 4pt,
align: (left, left),
formula, text(size: 9pt, fill: muted, note),
)
#let check(label, demand, capacity, unit: "", ok: auto, demand-label: "Demand", capacity-label: "Capacity") = {
let utilization = demand / capacity
let passes = if ok == auto { utilization <= 1 } else { ok }
let color = if passes { pass } else { fail }
block(
breakable: false,
width: 100%,
stroke: 0.8pt + black,
inset: 8pt,
radius: 2pt,
)[
#grid(
columns: (1fr, auto),
[#text(weight: "bold")[#label]],
box(stroke: 0.8pt + color, inset: (x: 6pt, y: 2pt))[
#text(weight: "bold", fill: color)[#if passes { "OK" } else { "NOT OK" }]
],
)
#v(4pt)
#grid(
columns: (1fr, auto),
[
#demand-label: #calc.round(demand, digits: 2) #unit #h(14pt)
#capacity-label: #calc.round(capacity, digits: 2) #unit
],
[
D/C: #calc.round(utilization, digits: 2)
],
)
]
}

132
concrete-beam/calc.py Normal file
View file

@ -0,0 +1,132 @@
from __future__ import annotations
import json
import math
import sys
from pathlib import Path
try:
import yaml
except ImportError:
raise SystemExit("Install PyYAML: python -m pip install pyyaml")
HERE = Path(__file__).resolve().parent
def _require_positive(name: str, value: float) -> float:
if value <= 0:
raise ValueError(f"{name} must be positive")
return value
def compute(inp: dict) -> dict:
span_ft = _require_positive("span_ft", float(inp["span_ft"]))
tributary_ft = _require_positive("tributary_ft", float(inp["tributary_ft"]))
D_psf = _require_positive("D_psf", float(inp["D_psf"]))
L_psf = _require_positive("L_psf", float(inp["L_psf"]))
bw_in = _require_positive("bw_in", float(inp["bw_in"]))
h_in = _require_positive("h_in", float(inp["h_in"]))
d_in = _require_positive("d_in", float(inp["d_in"]))
fc_ksi = _require_positive("fc_ksi", float(inp["fc_ksi"]))
fy_ksi = _require_positive("fy_ksi", float(inp["fy_ksi"]))
As_in2 = _require_positive("As_in2", float(inp["As_in2"]))
concrete_pcf = _require_positive("concrete_pcf", float(inp["concrete_pcf"]))
self_weight_klf = (bw_in * h_in / 144.0) * concrete_pcf / 1000.0
wD_klf = D_psf * tributary_ft / 1000.0 + self_weight_klf
wL_klf = L_psf * tributary_ft / 1000.0
wu_klf = 1.2 * wD_klf + 1.6 * wL_klf
Mu_kipft = wu_klf * span_ft**2 / 8.0
Vu_kip = wu_klf * span_ft / 2.0
fc_psi = fc_ksi * 1000.0
fy_psi = fy_ksi * 1000.0
a_in = As_in2 * fy_ksi / (0.85 * fc_ksi * bw_in)
beta1 = max(0.65, min(0.85, 0.85 - 0.05 * max(0.0, (fc_psi - 4000.0) / 1000.0)))
c_in = a_in / beta1
et = 0.003 * (d_in - c_in) / c_in if c_in > 0 else 0.0
if et >= 0.005:
phi = 0.90
else:
phi = max(0.65, min(0.90, 0.65 + (et - 0.002) * 250.0 / 3.0))
Mn_kipft = As_in2 * fy_ksi * (d_in - a_in / 2.0) / 12.0
phiMn_kipft = phi * Mn_kipft
rho_min = max(3.0 * math.sqrt(fc_psi) / fy_psi, 200.0 / fy_psi)
As_min_in2 = rho_min * bw_in * d_in
Vc_kip = 2.0 * math.sqrt(fc_psi) * bw_in * d_in / 1000.0
phiVc_kip = 0.75 * Vc_kip
def q(value: float) -> float:
return round(value, 6)
return {
"tool": "concrete_beam",
"version": "0.1",
"project": inp.get("project", ""),
"prepared_by": inp.get("prepared_by", ""),
"values": {
"span_ft": q(span_ft),
"tributary_ft": q(tributary_ft),
"D_psf": q(D_psf),
"L_psf": q(L_psf),
"self_weight_klf": q(self_weight_klf),
"wD_klf": q(wD_klf),
"wL_klf": q(wL_klf),
"wu_klf": q(wu_klf),
"Mu_kipft": q(Mu_kipft),
"Vu_kip": q(Vu_kip),
"bw_in": q(bw_in),
"h_in": q(h_in),
"d_in": q(d_in),
"fc_ksi": q(fc_ksi),
"fy_ksi": q(fy_ksi),
"As_in2": q(As_in2),
"a_in": q(a_in),
"et": q(et),
"phi": q(phi),
"Mn_kipft": q(Mn_kipft),
"phiMn_kipft": q(phiMn_kipft),
"As_min_in2": q(As_min_in2),
"Vc_kip": q(Vc_kip),
"phiVc_kip": q(phiVc_kip),
},
"checks": {
"flexure": {
"demand": q(Mu_kipft),
"capacity": q(phiMn_kipft),
"ok": Mu_kipft <= phiMn_kipft,
},
"minimum_steel": {
"demand": q(As_min_in2),
"capacity": q(As_in2),
"ok": As_in2 >= As_min_in2,
},
"shear": {
"demand": q(Vu_kip),
"capacity": q(phiVc_kip),
"ok": Vu_kip <= phiVc_kip,
},
},
}
def write_results(result: dict, path: Path) -> None:
path.write_text(json.dumps(result, indent=2) + "\n", encoding="utf-8")
def main() -> int:
input_path = Path(sys.argv[1]) if len(sys.argv) > 1 else HERE / "input.yaml"
output_path = Path(sys.argv[2]) if len(sys.argv) > 2 else input_path.with_name("results.json")
with input_path.open(encoding="utf-8") as handle:
inp = yaml.safe_load(handle)
result = compute(inp)
write_results(result, output_path)
print(output_path)
return 0
if __name__ == "__main__":
raise SystemExit(main())

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,119 @@
#import "assets/sheet.typ": calcline, calcsheet, check
#let data = json("results.json")
#let n = data.values
#let checks = data.checks
#let round(value, digits: 2) = calc.round(value, digits: digits)
#show: calcsheet.with(
title: "Concrete Beam Analysis",
project: data.project,
prepared-by: data.prepared_by,
)
= Reinforced Concrete Beam
Simple-span rectangular beam under uniform gravity load. Numbers come from `calc.py`. This sheet only presents them.
#let beam-sketch = {
set align(center)
box(width: 82%, inset: (y: 8pt))[
#line(length: 100%, stroke: 1.4pt)
#v(-7.5pt)
#grid(
columns: (auto, 1fr, auto),
align: (left, center, right),
polygon(fill: black, (0pt, 0pt), (8pt, 10pt), (-8pt, 10pt)),
text(size: 9pt)[$w_u$ uniform factored load],
polygon(fill: black, (0pt, 0pt), (8pt, 10pt), (-8pt, 10pt)),
)
#v(2pt)
#text(size: 9pt)[#n.span_ft ft simple span · #n.bw_in in × #n.h_in in section]
]
}
#figure(
beam-sketch,
caption: [#n.span_ft ft simply supported beam, #n.bw_in in × #n.h_in in rectangular section.],
)
== Loads and Beam Demand
#calcline([$L = #n.span_ft " ft"$], [Simple span])
#calcline([$B_t = #n.tributary_ft " ft"$], [Tributary width])
#calcline([$D = #n.D_psf " psf"$], [Dead load including superimposed dead])
#calcline([$L_L = #n.L_psf " psf"$], [Live load])
#calcline([$w_("sw") = #round(n.self_weight_klf, digits: 3) " kip/ft"$], [Beam self-weight])
#calcline(
[$w_u = 1.2 w_D + 1.6 w_L = #round(n.wu_klf, digits: 3) " kip/ft"$],
[Factored uniform line load],
)
#calcline(
[$M_u = w_u L^2 / 8 = #round(n.Mu_kipft) " kip·ft"$],
[Maximum positive moment],
)
#calcline(
[$V_u = w_u L / 2 = #round(n.Vu_kip) " kip"$],
[Support shear],
)
== Flexural Strength
#calcline([$b_w = #n.bw_in " in"$], [Beam width])
#calcline([$h = #n.h_in " in"$], [Overall depth])
#calcline([$d = #n.d_in " in"$], [Effective depth])
#calcline([$f'_c = #n.fc_ksi " ksi"$], [Concrete compressive strength])
#calcline([$f_y = #n.fy_ksi " ksi"$], [Steel yield strength])
#calcline([$A_s = #n.As_in2 " in"^2$], [Provided tension steel (2 No. 5)])
#calcline(
[$a = A_s f_y / (0.85 f'_c b_w) = #round(n.a_in, digits: 3) " in"$],
[Equivalent compression-block depth],
)
#calcline([$epsilon_t = #round(n.et, digits: 4)$], [Net tensile strain])
#calcline([$phi = #round(n.phi, digits: 2)$], [Strength reduction factor])
#calcline(
[$phi M_n = phi A_s f_y (d - a/2) = #round(n.phiMn_kipft) " kip·ft"$],
[Design flexural strength],
)
#v(7pt)
#check(
"Flexural strength",
checks.flexure.demand,
checks.flexure.capacity,
unit: "kip·ft",
ok: checks.flexure.ok,
demand-label: [$M_u$],
capacity-label: [$phi M_n$],
)
== Minimum Steel and Concrete Shear
#calcline([$A_("s,min") = #round(n.As_min_in2, digits: 3) " in"^2$], [Minimum longitudinal steel])
#calcline([$A_("s,prov") = #round(n.As_in2, digits: 3) " in"^2$], [Provided longitudinal steel])
#v(7pt)
#check(
"Minimum longitudinal reinforcement",
checks.minimum_steel.demand,
checks.minimum_steel.capacity,
unit: "in²",
ok: checks.minimum_steel.ok,
demand-label: [$A_("s,min")$],
capacity-label: [$A_("s,prov")$],
)
#v(10pt)
#calcline([$V_c = 2 sqrt(f'_c) b_w d = #round(n.Vc_kip) " kip"$], [Concrete shear strength])
#calcline([$phi V_c = #round(n.phiVc_kip) " kip"$], [Design concrete shear strength])
#v(7pt)
#check(
"Concrete shear",
checks.shear.demand,
checks.shear.capacity,
unit: "kip",
ok: checks.shear.ok,
demand-label: [$V_u$],
capacity-label: [$phi V_c$],
)

15
concrete-beam/input.yaml Normal file
View file

@ -0,0 +1,15 @@
project: "Deer Creek Shoring"
prepared_by: "Conemco Engineering"
span_ft: 16
tributary_ft: 6.25
D_psf: 55
L_psf: 20
bw_in: 8
h_in: 12
d_in: 9.5
fc_ksi: 3.0
fy_ksi: 60
As_in2: 0.62
concrete_pcf: 150
load_combination: "1.2D + 1.6L"

View file

@ -0,0 +1,49 @@
{
"tool": "concrete_beam",
"version": "0.1",
"project": "Deer Creek Shoring",
"prepared_by": "Conemco Engineering",
"values": {
"span_ft": 16.0,
"tributary_ft": 6.25,
"D_psf": 55.0,
"L_psf": 20.0,
"self_weight_klf": 0.1,
"wD_klf": 0.44375,
"wL_klf": 0.125,
"wu_klf": 0.7325,
"Mu_kipft": 23.44,
"Vu_kip": 5.86,
"bw_in": 8.0,
"h_in": 12.0,
"d_in": 9.5,
"fc_ksi": 3.0,
"fy_ksi": 60.0,
"As_in2": 0.62,
"a_in": 1.823529,
"et": 0.010285,
"phi": 0.9,
"Mn_kipft": 26.623529,
"phiMn_kipft": 23.961176,
"As_min_in2": 0.253333,
"Vc_kip": 8.325383,
"phiVc_kip": 6.244037
},
"checks": {
"flexure": {
"demand": 23.44,
"capacity": 23.961176,
"ok": true
},
"minimum_steel": {
"demand": 0.253333,
"capacity": 0.62,
"ok": true
},
"shear": {
"demand": 5.86,
"capacity": 6.244037,
"ok": true
}
}
}

View file

@ -0,0 +1,46 @@
from pathlib import Path
import importlib.util
import pytest
HERE = Path(__file__).resolve().parent
spec = importlib.util.spec_from_file_location("concrete_beam_calc", HERE / "calc.py")
assert spec is not None and spec.loader is not None
calc_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(calc_module)
compute = calc_module.compute
@pytest.fixture
def result():
import yaml
with (HERE / "input.yaml").open(encoding="utf-8") as handle:
return compute(yaml.safe_load(handle))
def test_example_demands(result):
v = result["values"]
assert v["self_weight_klf"] == pytest.approx(0.1)
assert v["wu_klf"] == pytest.approx(0.7325)
assert v["Mu_kipft"] == pytest.approx(23.44)
assert v["Vu_kip"] == pytest.approx(5.86)
def test_example_flexure(result):
v = result["values"]
assert v["a_in"] == pytest.approx(1.823529, rel=1e-5)
assert v["et"] == pytest.approx(0.010283, rel=1e-3)
assert v["phi"] == pytest.approx(0.9)
assert v["phiMn_kipft"] == pytest.approx(23.961176, rel=1e-5)
assert result["checks"]["flexure"]["ok"] is True
def test_example_min_steel_and_shear(result):
v = result["values"]
assert v["As_min_in2"] == pytest.approx(0.253333, rel=1e-4)
assert v["phiVc_kip"] == pytest.approx(6.244016, rel=1e-4)
assert result["checks"]["minimum_steel"]["ok"] is True
assert result["checks"]["shear"]["ok"] is True

BIN
concrete-beam2/assets/logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View file

@ -0,0 +1,82 @@
#let navy = rgb("#1a3a5f")
#let muted = rgb("#626b73")
#let pass = rgb("#1f6b45")
#let fail = rgb("#9b2c2c")
#let calcsheet(
title: "Structural Calculation",
project: "",
prepared-by: "",
body,
) = {
set document(title: title, author: prepared-by)
set page(
paper: "us-letter",
margin: (x: 1in, top: 1.25in, bottom: 1in),
header: context {
grid(
columns: (1fr, 1fr),
align: (left, right),
image("../assets/logo.png", height: 30pt),
[#text(size: 9pt)[Project:] \
#text(size: 10pt, weight: "bold")[#project]],
)
},
footer: context {
set text(size: 8.5pt, fill: muted)
stack(
spacing: 4pt,
line(length: 100%, stroke: 0.5pt + muted),
[#prepared-by],
)
},
)
set text(font: "Libertinus Serif", size: 10pt, lang: "en")
set par(justify: true)
set heading(numbering: none)
show heading.where(level: 1): set text(size: 14pt, weight: "bold", fill: black)
show heading.where(level: 2): set text(size: 11pt, weight: "bold", fill: black)
show heading.where(level: 2): set block(above: 2em, below: 1em)
body
}
#let calcline(formula, note) = grid(
columns: (1.7fr, 1fr),
gutter: 4pt,
align: (left, left),
formula, text(size: 9pt, fill: muted, note),
)
#let check(label, demand, capacity, unit: "", ok: auto, demand-label: "Demand", capacity-label: "Capacity") = {
let utilization = demand / capacity
let passes = if ok == auto { utilization <= 1 } else { ok }
let color = if passes { pass } else { fail }
block(
breakable: false,
width: 100%,
stroke: 0.8pt + black,
inset: 8pt,
radius: 2pt,
)[
#grid(
columns: (1fr, auto),
[#text(weight: "bold")[#label]],
box(stroke: 0.8pt + color, inset: (x: 6pt, y: 2pt))[
#text(weight: "bold", fill: color)[#if passes { "OK" } else { "NOT OK" }]
],
)
#v(4pt)
#grid(
columns: (1fr, auto),
[
#demand-label: #calc.round(demand, digits: 2) #unit #h(14pt)
#capacity-label: #calc.round(capacity, digits: 2) #unit
],
[
D/C: #calc.round(utilization, digits: 2)
],
)
]
}

154
concrete-beam2/calc.py Normal file
View file

@ -0,0 +1,154 @@
from __future__ import annotations
import json
import math
import sys
from pathlib import Path
try:
import yaml
except ImportError:
raise SystemExit("Install PyYAML: python -m pip install pyyaml")
try:
from pint import DimensionalityError, UndefinedUnitError, UnitRegistry
except ImportError:
raise SystemExit("Install Pint: python -m pip install pint")
HERE = Path(__file__).resolve().parent
ureg = UnitRegistry()
ureg.define("kip = 1000 * force_pound")
ureg.define("ksi = kip / inch ** 2")
ureg.define("klf = kip / foot")
if "psf" not in ureg:
ureg.define("psf = force_pound / foot ** 2")
if "pcf" not in ureg:
ureg.define("pcf = force_pound / foot ** 3")
def to_magnitude(value, unit: str, name: str) -> float:
try:
quantity = ureg.Quantity(value)
except (UndefinedUnitError, ValueError, TypeError) as exc:
raise ValueError(f"{name}: cannot parse {value!r}") from exc
try:
magnitude = float(quantity.to(unit).magnitude)
except DimensionalityError as exc:
raise ValueError(f"{name}: expected {unit}, got {value!r}") from exc
if magnitude <= 0:
raise ValueError(f"{name} must be positive")
return magnitude
def compute(inp: dict) -> dict:
span_ft = to_magnitude(inp["span"], "ft", "span")
tributary_ft = to_magnitude(inp["tributary"], "ft", "tributary")
D_psf = to_magnitude(inp["D"], "psf", "D")
L_psf = to_magnitude(inp["L"], "psf", "L")
bw_in = to_magnitude(inp["bw"], "in", "bw")
h_in = to_magnitude(inp["h"], "in", "h")
d_in = to_magnitude(inp["d"], "in", "d")
fc_ksi = to_magnitude(inp["fc"], "ksi", "fc")
fy_ksi = to_magnitude(inp["fy"], "ksi", "fy")
As_in2 = to_magnitude(inp["As"], "in**2", "As")
concrete_pcf = to_magnitude(inp["concrete_density"], "pcf", "concrete_density")
self_weight_klf = (bw_in * h_in / 144.0) * concrete_pcf / 1000.0
wD_klf = D_psf * tributary_ft / 1000.0 + self_weight_klf
wL_klf = L_psf * tributary_ft / 1000.0
wu_klf = 1.2 * wD_klf + 1.6 * wL_klf
Mu_kipft = wu_klf * span_ft**2 / 8.0
Vu_kip = wu_klf * span_ft / 2.0
fc_psi = fc_ksi * 1000.0
fy_psi = fy_ksi * 1000.0
a_in = As_in2 * fy_ksi / (0.85 * fc_ksi * bw_in)
beta1 = max(0.65, min(0.85, 0.85 - 0.05 * max(0.0, (fc_psi - 4000.0) / 1000.0)))
c_in = a_in / beta1
et = 0.003 * (d_in - c_in) / c_in if c_in > 0 else 0.0
if et >= 0.005:
phi = 0.90
else:
phi = max(0.65, min(0.90, 0.65 + (et - 0.002) * 250.0 / 3.0))
Mn_kipft = As_in2 * fy_ksi * (d_in - a_in / 2.0) / 12.0
phiMn_kipft = phi * Mn_kipft
rho_min = max(3.0 * math.sqrt(fc_psi) / fy_psi, 200.0 / fy_psi)
As_min_in2 = rho_min * bw_in * d_in
Vc_kip = 2.0 * math.sqrt(fc_psi) * bw_in * d_in / 1000.0
phiVc_kip = 0.75 * Vc_kip
def q(value: float) -> float:
return round(value, 6)
return {
"tool": "concrete_beam2",
"version": "0.1",
"project": inp.get("project", ""),
"prepared_by": inp.get("prepared_by", ""),
"values": {
"span_ft": q(span_ft),
"tributary_ft": q(tributary_ft),
"D_psf": q(D_psf),
"L_psf": q(L_psf),
"self_weight_klf": q(self_weight_klf),
"wD_klf": q(wD_klf),
"wL_klf": q(wL_klf),
"wu_klf": q(wu_klf),
"Mu_kipft": q(Mu_kipft),
"Vu_kip": q(Vu_kip),
"bw_in": q(bw_in),
"h_in": q(h_in),
"d_in": q(d_in),
"fc_ksi": q(fc_ksi),
"fy_ksi": q(fy_ksi),
"As_in2": q(As_in2),
"a_in": q(a_in),
"et": q(et),
"phi": q(phi),
"Mn_kipft": q(Mn_kipft),
"phiMn_kipft": q(phiMn_kipft),
"As_min_in2": q(As_min_in2),
"Vc_kip": q(Vc_kip),
"phiVc_kip": q(phiVc_kip),
},
"checks": {
"flexure": {
"demand": q(Mu_kipft),
"capacity": q(phiMn_kipft),
"ok": Mu_kipft <= phiMn_kipft,
},
"minimum_steel": {
"demand": q(As_min_in2),
"capacity": q(As_in2),
"ok": As_in2 >= As_min_in2,
},
"shear": {
"demand": q(Vu_kip),
"capacity": q(phiVc_kip),
"ok": Vu_kip <= phiVc_kip,
},
},
}
def write_results(result: dict, path: Path) -> None:
path.write_text(json.dumps(result, indent=2) + "\n", encoding="utf-8")
def main() -> int:
input_path = Path(sys.argv[1]) if len(sys.argv) > 1 else HERE / "input.yaml"
output_path = Path(sys.argv[2]) if len(sys.argv) > 2 else input_path.with_name("results.json")
with input_path.open(encoding="utf-8") as handle:
inp = yaml.safe_load(handle)
result = compute(inp)
write_results(result, output_path)
print(output_path)
return 0
if __name__ == "__main__":
raise SystemExit(main())

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,119 @@
#import "assets/sheet.typ": calcline, calcsheet, check
#let data = json("results.json")
#let n = data.values
#let checks = data.checks
#let round(value, digits: 2) = calc.round(value, digits: digits)
#show: calcsheet.with(
title: "Concrete Beam Analysis",
project: data.project,
prepared-by: data.prepared_by,
)
= Reinforced Concrete Beam
Simple-span rectangular beam under uniform gravity load. YAML quantities are converted by Pint in `calc.py`. This sheet only presents the results.
#let beam-sketch = {
set align(center)
box(width: 82%, inset: (y: 8pt))[
#line(length: 100%, stroke: 1.4pt)
#v(-7.5pt)
#grid(
columns: (auto, 1fr, auto),
align: (left, center, right),
polygon(fill: black, (0pt, 0pt), (8pt, 10pt), (-8pt, 10pt)),
text(size: 9pt)[$w_u$ uniform factored load],
polygon(fill: black, (0pt, 0pt), (8pt, 10pt), (-8pt, 10pt)),
)
#v(2pt)
#text(size: 9pt)[#n.span_ft ft simple span · #n.bw_in in × #n.h_in in section]
]
}
#figure(
beam-sketch,
caption: [#n.span_ft ft simply supported beam, #n.bw_in in × #n.h_in in rectangular section.],
)
== Loads and Beam Demand
#calcline([$L = #n.span_ft " ft"$], [Simple span])
#calcline([$B_t = #n.tributary_ft " ft"$], [Tributary width])
#calcline([$D = #n.D_psf " psf"$], [Dead load including superimposed dead])
#calcline([$L_L = #n.L_psf " psf"$], [Live load])
#calcline([$w_("sw") = #round(n.self_weight_klf, digits: 3) " kip/ft"$], [Beam self-weight])
#calcline(
[$w_u = 1.2 w_D + 1.6 w_L = #round(n.wu_klf, digits: 3) " kip/ft"$],
[Factored uniform line load],
)
#calcline(
[$M_u = w_u L^2 / 8 = #round(n.Mu_kipft) " kip·ft"$],
[Maximum positive moment],
)
#calcline(
[$V_u = w_u L / 2 = #round(n.Vu_kip) " kip"$],
[Support shear],
)
== Flexural Strength
#calcline([$b_w = #n.bw_in " in"$], [Beam width])
#calcline([$h = #n.h_in " in"$], [Overall depth])
#calcline([$d = #n.d_in " in"$], [Effective depth])
#calcline([$f'_c = #n.fc_ksi " ksi"$], [Concrete compressive strength])
#calcline([$f_y = #n.fy_ksi " ksi"$], [Steel yield strength])
#calcline([$A_s = #n.As_in2 " in"^2$], [Provided tension steel (2 No. 5)])
#calcline(
[$a = A_s f_y / (0.85 f'_c b_w) = #round(n.a_in, digits: 3) " in"$],
[Equivalent compression-block depth],
)
#calcline([$epsilon_t = #round(n.et, digits: 4)$], [Net tensile strain])
#calcline([$phi = #round(n.phi, digits: 2)$], [Strength reduction factor])
#calcline(
[$phi M_n = phi A_s f_y (d - a/2) = #round(n.phiMn_kipft) " kip·ft"$],
[Design flexural strength],
)
#v(7pt)
#check(
"Flexural strength",
checks.flexure.demand,
checks.flexure.capacity,
unit: "kip·ft",
ok: checks.flexure.ok,
demand-label: [$M_u$],
capacity-label: [$phi M_n$],
)
== Minimum Steel and Concrete Shear
#calcline([$A_("s,min") = #round(n.As_min_in2, digits: 3) " in"^2$], [Minimum longitudinal steel])
#calcline([$A_("s,prov") = #round(n.As_in2, digits: 3) " in"^2$], [Provided longitudinal steel])
#v(7pt)
#check(
"Minimum longitudinal reinforcement",
checks.minimum_steel.demand,
checks.minimum_steel.capacity,
unit: "in²",
ok: checks.minimum_steel.ok,
demand-label: [$A_("s,min")$],
capacity-label: [$A_("s,prov")$],
)
#v(10pt)
#calcline([$V_c = 2 sqrt(f'_c) b_w d = #round(n.Vc_kip) " kip"$], [Concrete shear strength])
#calcline([$phi V_c = #round(n.phiVc_kip) " kip"$], [Design concrete shear strength])
#v(7pt)
#check(
"Concrete shear",
checks.shear.demand,
checks.shear.capacity,
unit: "kip",
ok: checks.shear.ok,
demand-label: [$V_u$],
capacity-label: [$phi V_c$],
)

15
concrete-beam2/input.yaml Normal file
View file

@ -0,0 +1,15 @@
project: "Deer Creek Shoring"
prepared_by: "Conemco Engineering"
span: "16 ft"
tributary: "6.25 ft"
D: "55 psf"
L: "20 psf"
bw: "8 in"
h: "12 in"
d: "1 ft"
fc: "3000 psi"
fy: "50000 psi"
As: "0.62 in^2"
concrete_density: "150 pcf"
load_combination: "1.2D + 1.6L"

View file

@ -0,0 +1,49 @@
{
"tool": "concrete_beam2",
"version": "0.1",
"project": "Deer Creek Shoring",
"prepared_by": "Conemco Engineering",
"values": {
"span_ft": 16.0,
"tributary_ft": 6.25,
"D_psf": 55.0,
"L_psf": 20.0,
"self_weight_klf": 0.1,
"wD_klf": 0.44375,
"wL_klf": 0.125,
"wu_klf": 0.7325,
"Mu_kipft": 23.44,
"Vu_kip": 5.86,
"bw_in": 8.0,
"h_in": 12.0,
"d_in": 12.0,
"fc_ksi": 3.0,
"fy_ksi": 50.0,
"As_in2": 0.62,
"a_in": 1.519608,
"et": 0.017137,
"phi": 0.9,
"Mn_kipft": 29.037173,
"phiMn_kipft": 26.133456,
"As_min_in2": 0.384,
"Vc_kip": 10.516273,
"phiVc_kip": 7.887205
},
"checks": {
"flexure": {
"demand": 23.44,
"capacity": 26.133456,
"ok": true
},
"minimum_steel": {
"demand": 0.384,
"capacity": 0.62,
"ok": true
},
"shear": {
"demand": 5.86,
"capacity": 7.887205,
"ok": true
}
}
}

View file

@ -0,0 +1,70 @@
from pathlib import Path
import importlib.util
import pytest
import yaml
HERE = Path(__file__).resolve().parent
spec = importlib.util.spec_from_file_location("concrete_beam2_calc", HERE / "calc.py")
assert spec is not None and spec.loader is not None
calc_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(calc_module)
compute = calc_module.compute
def load_input():
with (HERE / "input.yaml").open(encoding="utf-8") as handle:
return yaml.safe_load(handle)
@pytest.fixture
def result():
return compute(load_input())
def test_example_demands(result):
v = result["values"]
assert v["self_weight_klf"] == pytest.approx(0.1)
assert v["wu_klf"] == pytest.approx(0.7325)
assert v["Mu_kipft"] == pytest.approx(23.44)
assert v["Vu_kip"] == pytest.approx(5.86)
def test_example_flexure(result):
v = result["values"]
assert v["a_in"] == pytest.approx(1.519608, rel=1e-5)
assert v["et"] == pytest.approx(0.017137, rel=1e-3)
assert v["phi"] == pytest.approx(0.9)
assert v["phiMn_kipft"] == pytest.approx(26.133456, rel=1e-5)
assert result["checks"]["flexure"]["ok"] is True
def test_example_min_steel_and_shear(result):
v = result["values"]
assert v["As_min_in2"] == pytest.approx(0.384, rel=1e-4)
assert v["phiVc_kip"] == pytest.approx(7.887205, rel=1e-4)
assert result["checks"]["minimum_steel"]["ok"] is True
assert result["checks"]["shear"]["ok"] is True
def test_alternate_units_match_default(result):
alt = load_input()
alt.update(
{
"span": "192 in",
"tributary": "75 in",
"fc": "3000 psi",
}
)
converted = compute(alt)
for key in ("span_ft", "tributary_ft", "fc_ksi", "Mu_kipft", "phiMn_kipft", "Vu_kip"):
assert converted["values"][key] == pytest.approx(result["values"][key], rel=1e-6)
def test_wrong_dimension_is_rejected():
bad = load_input()
bad["span"] = "16 kip"
with pytest.raises(ValueError, match="span"):
compute(bad)

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View file

@ -0,0 +1,82 @@
#let navy = rgb("#1a3a5f")
#let muted = rgb("#626b73")
#let pass = rgb("#1f6b45")
#let fail = rgb("#9b2c2c")
#let calcsheet(
title: "Structural Calculation",
project: "",
prepared-by: "",
body,
) = {
set document(title: title, author: prepared-by)
set page(
paper: "us-letter",
margin: (x: 1in, top: 1.25in, bottom: 1in),
header: context {
grid(
columns: (1fr, 1fr),
align: (left, right),
image("../assets/logo.png", height: 30pt),
[#text(size: 9pt)[Project:] \
#text(size: 10pt, weight: "bold")[#project]],
)
},
footer: context {
set text(size: 8.5pt, fill: muted)
stack(
spacing: 4pt,
line(length: 100%, stroke: 0.5pt + muted),
[#prepared-by],
)
},
)
set text(font: "Libertinus Serif", size: 10pt, lang: "en")
set par(justify: true)
set heading(numbering: none)
show heading.where(level: 1): set text(size: 14pt, weight: "bold", fill: black)
show heading.where(level: 2): set text(size: 11pt, weight: "bold", fill: black)
show heading.where(level: 2): set block(above: 2em, below: 1em)
body
}
#let calcline(formula, note) = grid(
columns: (1.7fr, 1fr),
gutter: 4pt,
align: (left, left),
formula, text(size: 9pt, fill: muted, note),
)
#let check(label, demand, capacity, unit: "", ok: auto, demand-label: "Demand", capacity-label: "Capacity") = {
let utilization = demand / capacity
let passes = if ok == auto { utilization <= 1 } else { ok }
let color = if passes { pass } else { fail }
block(
breakable: false,
width: 100%,
stroke: 0.8pt + black,
inset: 8pt,
radius: 2pt,
)[
#grid(
columns: (1fr, auto),
[#text(weight: "bold")[#label]],
box(stroke: 0.8pt + color, inset: (x: 6pt, y: 2pt))[
#text(weight: "bold", fill: color)[#if passes { "OK" } else { "NOT OK" }]
],
)
#v(4pt)
#grid(
columns: (1fr, auto),
[
#demand-label: #calc.round(demand, digits: 2) #unit #h(14pt)
#capacity-label: #calc.round(capacity, digits: 2) #unit
],
[
D/C: #calc.round(utilization, digits: 2)
],
)
]
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,141 @@
#import "assets/sheet.typ": calcline, calcsheet, check
#show: calcsheet.with(
title: "Mudsill Analysis and Design",
project: "BNC Typical Shoring",
prepared-by: "Conemco Engineering",
)
#let round(value, digits: 2) = calc.round(value, digits: digits)
= Mudsill Analysis and Design
Analysis to determine the adequacy of a plywood mudsill supporting a shore post
base over compacted soil. The mudsill consists of stacked plywood panels
distributing the post load to the ground.
== Geometry and Loads
#let P = 3000.0
#let Bp = 6.0
#let Hp = 6.0
#let B = 18.0
#let H = 18.0
#let t = 0.75
#let N = 3
#calcline([$P = #P " lbf"$], [Post axial load on mudsill])
#calcline([$B_p = #Bp " in"$], [Post base width])
#calcline([$H_p = #Hp " in"$], [Post base length])
#calcline([$B = #B " in"$], [Mudsill panel width])
#calcline([$H = #H " in"$], [Mudsill panel length])
#calcline([$t = #t " in"$], [Plywood thickness])
#calcline([$N = #N$], [Number of plywood panels])
== Plywood Bearing Under Post Base
#let Ap = Bp * Hp
#let fbrg_ply = P / Ap
#let Fabrg = 360.0
#calcline([$A_p = B_p H_p = #round(Ap) " in"^2$], [Post base contact area])
#calcline(
[$f_"brg" = P / A_p = #round(fbrg_ply, digits: 3) " psi"$],
[Bearing stress in plywood],
)
#calcline([$F_"abrg" = #Fabrg " psi"$], [Allowable plywood bearing (D510 ch 4.4.7)])
#v(8pt)
#check(
"Plywood bearing under post base",
fbrg_ply,
Fabrg,
unit: "psi",
demand-label: [$f_"brg"$],
capacity-label: [$F_"abrg"$],
)
== Soil Bearing
#let Abrg = (B * H) / 144.0
#let fbrg_soil = P / Abrg
#let Fbrg = 2000.0
#calcline([$A_"brg" = (B H) / 144 = #round(Abrg, digits: 3) " ft"^2$], [Mudsill bearing area on soil])
#calcline(
[$f_"brg" = P / A_"brg" = #round(fbrg_soil, digits: 3) " psf"$],
[Soil bearing pressure],
)
#calcline([$F_"brg" = #Fbrg " psf"$], [Allowable soil bearing pressure])
#v(8pt)
#check(
"Soil bearing pressure",
fbrg_soil,
Fbrg,
unit: "psf",
demand-label: [$f_"brg"$],
capacity-label: [$F_"brg"$],
)
== Plywood Bending
The soil pressure acting on the panel produces a lineal load on the plywood
spanning between the post base edge and the panel edge. A 0.6 reduction factor
is applied to the soil pressure to account for partial loading at the cantilever.
#let B_ft = B / 12.0
#let w = 0.6 * fbrg_soil * B_ft
#let a = (H - Hp) / 2.0
#let a_ft = a / 12.0
#let M = w * a_ft * a_ft / 2.0
#let Sp = N * B * t * t / 6.0
#let fb = (M * 12.0) / Sp
#let FbS = 405.0
#let S = 1.125
#let Fb = FbS / S
#calcline([$w = 0.6 f_"brg" B = #round(w) " plf"$], [Lineal load on plywood])
#calcline([$a = (H - H_p) / 2 = #round(a) " in"$], [Cantilever length])
#calcline([$M = w a^2 / 2 = #round(M) " lbf" dot "ft"$], [Maximum bending moment])
#calcline([$S_p = N B t^2 / 6 = #round(Sp, digits: 3) " in"^3$], [Section modulus of plywood])
#calcline(
[$f_b = M / S_p = #round(fb, digits: 3) " psi"$],
[Bending stress in plywood],
)
#calcline([$F_b = F_"bS" / S = #round(Fb) " psi"$], [Allowable bending stress])
#v(8pt)
#check(
"Plywood bending stress",
fb,
Fb,
unit: "psi",
demand-label: [$f_b$],
capacity-label: [$F_b$],
)
== Plywood Shear
#let V = w * a_ft
#let Av = N * B * t
#let fv = 1.5 * V / Av
#let Fv = 90.0
#calcline([$V = w a = #round(V) " lbf"$], [Maximum shear force])
#calcline([$A_v = N B t = #round(Av, digits: 3) " in"^2$], [Shear area of plywood])
#calcline(
[$f_v = 1.5 V / A_v = #round(fv, digits: 3) " psi"$],
[Shear stress in plywood],
)
#calcline([$F_v = #Fv " psi"$], [Allowable shear stress])
#v(8pt)
#check(
"Plywood shear stress",
fv,
Fv,
unit: "psi",
demand-label: [$f_v$],
capacity-label: [$F_v$],
)

BIN
shore-post-brace/assets/logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View file

@ -0,0 +1,82 @@
#let navy = rgb("#1a3a5f")
#let muted = rgb("#626b73")
#let pass = rgb("#1f6b45")
#let fail = rgb("#9b2c2c")
#let calcsheet(
title: "Structural Calculation",
project: "",
prepared-by: "",
body,
) = {
set document(title: title, author: prepared-by)
set page(
paper: "us-letter",
margin: (x: 1in, top: 1.25in, bottom: 1in),
header: context {
grid(
columns: (1fr, 1fr),
align: (left, right),
image("../assets/logo.png", height: 30pt),
[#text(size: 9pt)[Project:] \
#text(size: 10pt, weight: "bold")[#project]],
)
},
footer: context {
set text(size: 8.5pt, fill: muted)
stack(
spacing: 4pt,
line(length: 100%, stroke: 0.5pt + muted),
[#prepared-by],
)
},
)
set text(font: "Libertinus Serif", size: 10pt, lang: "en")
set par(justify: true)
set heading(numbering: none)
show heading.where(level: 1): set text(size: 14pt, weight: "bold", fill: black)
show heading.where(level: 2): set text(size: 11pt, weight: "bold", fill: black)
show heading.where(level: 2): set block(above: 2em, below: 1em)
body
}
#let calcline(formula, note) = grid(
columns: (1.7fr, 1fr),
gutter: 4pt,
align: (left, left),
formula, text(size: 9pt, fill: muted, note),
)
#let check(label, demand, capacity, unit: "", ok: auto, demand-label: "Demand", capacity-label: "Capacity") = {
let utilization = demand / capacity
let passes = if ok == auto { utilization <= 1 } else { ok }
let color = if passes { pass } else { fail }
block(
breakable: false,
width: 100%,
stroke: 0.8pt + black,
inset: 8pt,
radius: 2pt,
)[
#grid(
columns: (1fr, auto),
[#text(weight: "bold")[#label]],
box(stroke: 0.8pt + color, inset: (x: 6pt, y: 2pt))[
#text(weight: "bold", fill: color)[#if passes { "OK" } else { "NOT OK" }]
],
)
#v(4pt)
#grid(
columns: (1fr, auto),
[
#demand-label: #calc.round(demand, digits: 2) #unit #h(14pt)
#capacity-label: #calc.round(capacity, digits: 2) #unit
],
[
D/C: #calc.round(utilization, digits: 2)
],
)
]
}

BIN
shore-post/assets/logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View file

@ -0,0 +1,82 @@
#let navy = rgb("#1a3a5f")
#let muted = rgb("#626b73")
#let pass = rgb("#1f6b45")
#let fail = rgb("#9b2c2c")
#let calcsheet(
title: "Structural Calculation",
project: "",
prepared-by: "",
body,
) = {
set document(title: title, author: prepared-by)
set page(
paper: "us-letter",
margin: (x: 1in, top: 1.25in, bottom: 1in),
header: context {
grid(
columns: (1fr, 1fr),
align: (left, right),
image("../assets/logo.png", height: 30pt),
[#text(size: 9pt)[Project:] \
#text(size: 10pt, weight: "bold")[#project]],
)
},
footer: context {
set text(size: 8.5pt, fill: muted)
stack(
spacing: 4pt,
line(length: 100%, stroke: 0.5pt + muted),
[#prepared-by],
)
},
)
set text(font: "Libertinus Serif", size: 10pt, lang: "en")
set par(justify: true)
set heading(numbering: none)
show heading.where(level: 1): set text(size: 14pt, weight: "bold", fill: black)
show heading.where(level: 2): set text(size: 11pt, weight: "bold", fill: black)
show heading.where(level: 2): set block(above: 2em, below: 1em)
body
}
#let calcline(formula, note) = grid(
columns: (1.7fr, 1fr),
gutter: 4pt,
align: (left, left),
formula, text(size: 9pt, fill: muted, note),
)
#let check(label, demand, capacity, unit: "", ok: auto, demand-label: "Demand", capacity-label: "Capacity") = {
let utilization = demand / capacity
let passes = if ok == auto { utilization <= 1 } else { ok }
let color = if passes { pass } else { fail }
block(
breakable: false,
width: 100%,
stroke: 0.8pt + black,
inset: 8pt,
radius: 2pt,
)[
#grid(
columns: (1fr, auto),
[#text(weight: "bold")[#label]],
box(stroke: 0.8pt + color, inset: (x: 6pt, y: 2pt))[
#text(weight: "bold", fill: color)[#if passes { "OK" } else { "NOT OK" }]
],
)
#v(4pt)
#grid(
columns: (1fr, auto),
[
#demand-label: #calc.round(demand, digits: 2) #unit #h(14pt)
#capacity-label: #calc.round(capacity, digits: 2) #unit
],
[
D/C: #calc.round(utilization, digits: 2)
],
)
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

1038
shore-post/shore-post.pdf Normal file

File diff suppressed because it is too large Load diff

68
shore-post/shore-post.typ Normal file
View file

@ -0,0 +1,68 @@
#import "assets/sheet.typ": calcline, calcsheet, check
#show: calcsheet.with(
title: "Shore Post Analysis and Design",
project: "Deer Creek Shoring",
prepared-by: "Conemco Engineering",
)
#let round(value, digits: 2) = calc.round(value, digits: digits)
= Shore Post Analysis and Design
Analysis to determine the axial demand for heavy duty shore post supporting the building's roof adjacent to the masonry walls to be repaired.
#figure(
image("assets/tributary-areas.png", width: 69%),
caption: [Plan tributary area for highest loaded shore post pair.],
)
== Tributary Area
#let Bx = 6.25
#let By = 16
#let At = Bx * By
#calcline([$S_x = #Bx " ft"$], [Tributary width in x (Spacing in X)])
#calcline([$S_y = #By " ft"$], [Tributary width in y (Spacing in Y)])
#calcline(
[$A_t = S_x S_y = #round(At) " ft"^2$],
[Plan tributary area],
)
== Load Determination
#let DL = 40.0
#let SDL = 15.0
#let LL = 20.0
#let P = ((DL + SDL + LL) * At) / 2
#calcline([$D = #DL " psf"$], [Dead load])
#calcline([$D_("s") = #SDL " psf"$], [Superimposed dead load])
#calcline([$L_L = #LL " psf"$], [Live load])
#calcline(
[$P_max = display((( D + D_("s") + L_L) A_t ) / 2) = #round(P) " lbf"$],
[Maximum service load on one post],
)
== Shore Post Axial Capacity
Considering AS550 Heavy Duty Shore post
#let H = 14
#let Pcap = 6400
#calcline([$H = #H " ft"$], [Shore post height])
#calcline([$P_("cap") = #Pcap " lbf"$], [AS550 Shore post capacity as per tech report])
#v(8pt)
#check(
"Shore post axial capacity",
P,
Pcap,
unit: "lbf",
demand-label: [$P_max$],
capacity-label: [$P_"cap"$],
)

Binary file not shown.

BIN
slab-on-grade/assets/logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View file

@ -0,0 +1,82 @@
#let navy = rgb("#1a3a5f")
#let muted = rgb("#626b73")
#let pass = rgb("#1f6b45")
#let fail = rgb("#9b2c2c")
#let calcsheet(
title: "Structural Calculation",
project: "",
prepared-by: "",
body,
) = {
set document(title: title, author: prepared-by)
set page(
paper: "us-letter",
margin: (x: 1in, top: 1.25in, bottom: 1in),
header: context {
grid(
columns: (1fr, 1fr),
align: (left, right),
image("../assets/logo.png", height: 30pt),
[#text(size: 9pt)[Project:] \
#text(size: 10pt, weight: "bold")[#project]],
)
},
footer: context {
set text(size: 8.5pt, fill: muted)
stack(
spacing: 4pt,
line(length: 100%, stroke: 0.5pt + muted),
[#prepared-by],
)
},
)
set text(font: "Libertinus Serif", size: 10pt, lang: "en")
set par(justify: true)
set heading(numbering: none)
show heading.where(level: 1): set text(size: 14pt, weight: "bold", fill: black)
show heading.where(level: 2): set text(size: 11pt, weight: "bold", fill: black)
show heading.where(level: 2): set block(above: 2em, below: 1em)
body
}
#let calcline(formula, note) = grid(
columns: (1.7fr, 1fr),
gutter: 4pt,
align: (left, left),
formula, text(size: 9pt, fill: muted, note),
)
#let check(label, demand, capacity, unit: "", ok: auto, demand-label: "Demand", capacity-label: "Capacity") = {
let utilization = demand / capacity
let passes = if ok == auto { utilization <= 1 } else { ok }
let color = if passes { pass } else { fail }
block(
breakable: false,
width: 100%,
stroke: 0.8pt + black,
inset: 8pt,
radius: 2pt,
)[
#grid(
columns: (1fr, auto),
[#text(weight: "bold")[#label]],
box(stroke: 0.8pt + color, inset: (x: 6pt, y: 2pt))[
#text(weight: "bold", fill: color)[#if passes { "OK" } else { "NOT OK" }]
],
)
#v(4pt)
#grid(
columns: (1fr, auto),
[
#demand-label: #calc.round(demand, digits: 2) #unit #h(14pt)
#capacity-label: #calc.round(capacity, digits: 2) #unit
],
[
D/C: #calc.round(utilization, digits: 2)
],
)
]
}

View file

@ -0,0 +1,995 @@
%PDF-1.7
%€€€€
1 0 obj
<</Type/Pages/Count 1/Kids[112 0 R]>>
endobj
2 0 obj
<</Parent 6 0 R/Next 3 0 R/Title(Input Data)/Dest 97 0 R>>
endobj
3 0 obj
<</Parent 6 0 R/Next 4 0 R/Prev 2 0 R/Title(Acting Load)/Dest 98 0 R>>
endobj
4 0 obj
<</Parent 6 0 R/Next 5 0 R/Prev 3 0 R/Title(Required Steel Reinforcement)/Dest 99 0 R>>
endobj
5 0 obj
<</Parent 6 0 R/Prev 4 0 R/Title(Provided Steel Reinforcement)/Dest 100 0 R>>
endobj
6 0 obj
<</Parent 7 0 R/First 2 0 R/Last 5 0 R/Count -4/Title(Slab-On-Grade Design)/Dest 101 0 R>>
endobj
7 0 obj
<</Type/Outlines/First 6 0 R/Last 6 0 R/Count 1>>
endobj
8 0 obj
<</Type/StructTreeRoot/RoleMap<</Datetime/Span/Terms/Part/Title/P/Strong/Span/Em/Span>>/K[94 0 R]/ParentTree<</Nums[0 9 0 R]>>/ParentTreeNextKey 1>>
endobj
9 0 obj
[10 0 R 11 0 R 12 0 R 13 0 R 13 0 R 13 0 R 13 0 R 15 0 R 18 0 R 18 0 R 18 0 R 18 0 R 18 0 R 20 0 R 23 0 R 23 0 R 23 0 R 23 0 R 23 0 R 23 0 R 23 0 R 23 0 R 23 0 R 25 0 R 28 0 R 28 0 R 28 0 R 28 0 R 28 0 R 28 0 R 28 0 R 30 0 R 33 0 R 33 0 R 33 0 R 33 0 R 33 0 R 33 0 R 33 0 R 33 0 R 33 0 R 35 0 R 38 0 R 38 0 R 38 0 R 38 0 R 38 0 R 38 0 R 38 0 R 38 0 R 38 0 R 38 0 R 38 0 R 38 0 R 38 0 R 38 0 R 38 0 R 38 0 R 38 0 R 40 0 R 43 0 R 43 0 R 43 0 R 43 0 R 43 0 R 43 0 R 45 0 R 48 0 R 48 0 R 48 0 R 48 0 R 48 0 R 48 0 R 48 0 R 50 0 R 53 0 R 53 0 R 53 0 R 53 0 R 53 0 R 55 0 R 58 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 59 0 R 61 0 R 64 0 R 65 0 R 65 0 R 65 0 R 65 0 R 65 0 R 67 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 72 0 R 72 0 R 75 0 R 76 0 R 76 0 R 76 0 R 76 0 R 76 0 R 76 0 R 76 0 R 76 0 R 76 0 R 78 0 R 78 0 R 81 0 R 83 0 R 86 0 R 86 0 R 86 0 R 86 0 R 87 0 R 88 0 R 88 0 R 89 0 R 91 0 R]
endobj
10 0 obj
<</Type/StructElem/S/H1/P 94 0 R/T(Slab-On-Grade Design)/K[0]/Pg 112 0 R>>
endobj
11 0 obj
<</Type/StructElem/S/P/P 94 0 R/K[1]/Pg 112 0 R>>
endobj
12 0 obj
<</Type/StructElem/S/H2/P 94 0 R/T(Input Data)/K[2]/Pg 112 0 R>>
endobj
13 0 obj
<</Type/StructElem/S/Formula/P 14 0 R/A[<</O/Layout/Placement/Block>>]/K[3 4 5 6]/Pg 112 0 R>>
endobj
14 0 obj
<</Type/StructElem/S/Div/P 17 0 R/K[13 0 R]>>
endobj
15 0 obj
<</Type/StructElem/S/Span/P 16 0 R/A[<</O/Layout/Placement/Block>>]/K[7]/Pg 112 0 R>>
endobj
16 0 obj
<</Type/StructElem/S/Div/P 17 0 R/K[15 0 R]>>
endobj
17 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[14 0 R 16 0 R]>>
endobj
18 0 obj
<</Type/StructElem/S/Formula/P 19 0 R/A[<</O/Layout/Placement/Block>>]/K[8 9 10 11 12]/Pg 112 0 R>>
endobj
19 0 obj
<</Type/StructElem/S/Div/P 22 0 R/K[18 0 R]>>
endobj
20 0 obj
<</Type/StructElem/S/Span/P 21 0 R/A[<</O/Layout/Placement/Block>>]/K[13]/Pg 112 0 R>>
endobj
21 0 obj
<</Type/StructElem/S/Div/P 22 0 R/K[20 0 R]>>
endobj
22 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[19 0 R 21 0 R]>>
endobj
23 0 obj
<</Type/StructElem/S/Formula/P 24 0 R/A[<</O/Layout/Placement/Block>>]/K[14 15 16 17 18 19 20 21 22]/Pg 112 0 R>>
endobj
24 0 obj
<</Type/StructElem/S/Div/P 27 0 R/K[23 0 R]>>
endobj
25 0 obj
<</Type/StructElem/S/Span/P 26 0 R/A[<</O/Layout/Placement/Block>>]/K[23]/Pg 112 0 R>>
endobj
26 0 obj
<</Type/StructElem/S/Div/P 27 0 R/K[25 0 R]>>
endobj
27 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[24 0 R 26 0 R]>>
endobj
28 0 obj
<</Type/StructElem/S/Formula/P 29 0 R/A[<</O/Layout/Placement/Block>>]/K[24 25 26 27 28 29 30]/Pg 112 0 R>>
endobj
29 0 obj
<</Type/StructElem/S/Div/P 32 0 R/K[28 0 R]>>
endobj
30 0 obj
<</Type/StructElem/S/Span/P 31 0 R/A[<</O/Layout/Placement/Block>>]/K[31]/Pg 112 0 R>>
endobj
31 0 obj
<</Type/StructElem/S/Div/P 32 0 R/K[30 0 R]>>
endobj
32 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[29 0 R 31 0 R]>>
endobj
33 0 obj
<</Type/StructElem/S/Formula/P 34 0 R/A[<</O/Layout/Placement/Block>>]/K[32 33 34 35 36 37 38 39 40]/Pg 112 0 R>>
endobj
34 0 obj
<</Type/StructElem/S/Div/P 37 0 R/K[33 0 R]>>
endobj
35 0 obj
<</Type/StructElem/S/Span/P 36 0 R/A[<</O/Layout/Placement/Block>>]/K[41]/Pg 112 0 R>>
endobj
36 0 obj
<</Type/StructElem/S/Div/P 37 0 R/K[35 0 R]>>
endobj
37 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[34 0 R 36 0 R]>>
endobj
38 0 obj
<</Type/StructElem/S/Formula/P 39 0 R/A[<</O/Layout/Placement/Block>>]/K[42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58]/Pg 112 0 R>>
endobj
39 0 obj
<</Type/StructElem/S/Div/P 42 0 R/K[38 0 R]>>
endobj
40 0 obj
<</Type/StructElem/S/Span/P 41 0 R/A[<</O/Layout/Placement/Block>>]/K[59]/Pg 112 0 R>>
endobj
41 0 obj
<</Type/StructElem/S/Div/P 42 0 R/K[40 0 R]>>
endobj
42 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[39 0 R 41 0 R]>>
endobj
43 0 obj
<</Type/StructElem/S/Formula/P 44 0 R/A[<</O/Layout/Placement/Block>>]/K[60 61 62 63 64 65]/Pg 112 0 R>>
endobj
44 0 obj
<</Type/StructElem/S/Div/P 47 0 R/K[43 0 R]>>
endobj
45 0 obj
<</Type/StructElem/S/Span/P 46 0 R/A[<</O/Layout/Placement/Block>>]/K[66]/Pg 112 0 R>>
endobj
46 0 obj
<</Type/StructElem/S/Div/P 47 0 R/K[45 0 R]>>
endobj
47 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[44 0 R 46 0 R]>>
endobj
48 0 obj
<</Type/StructElem/S/Formula/P 49 0 R/A[<</O/Layout/Placement/Block>>]/K[67 68 69 70 71 72 73]/Pg 112 0 R>>
endobj
49 0 obj
<</Type/StructElem/S/Div/P 52 0 R/K[48 0 R]>>
endobj
50 0 obj
<</Type/StructElem/S/Span/P 51 0 R/A[<</O/Layout/Placement/Block>>]/K[74]/Pg 112 0 R>>
endobj
51 0 obj
<</Type/StructElem/S/Div/P 52 0 R/K[50 0 R]>>
endobj
52 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[49 0 R 51 0 R]>>
endobj
53 0 obj
<</Type/StructElem/S/Formula/P 54 0 R/A[<</O/Layout/Placement/Block>>]/K[75 76 77 78 79]/Pg 112 0 R>>
endobj
54 0 obj
<</Type/StructElem/S/Div/P 57 0 R/K[53 0 R]>>
endobj
55 0 obj
<</Type/StructElem/S/Span/P 56 0 R/A[<</O/Layout/Placement/Block>>]/K[80]/Pg 112 0 R>>
endobj
56 0 obj
<</Type/StructElem/S/Div/P 57 0 R/K[55 0 R]>>
endobj
57 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[54 0 R 56 0 R]>>
endobj
58 0 obj
<</Type/StructElem/S/H2/P 94 0 R/T(Acting Load)/K[81]/Pg 112 0 R>>
endobj
59 0 obj
<</Type/StructElem/S/Formula/P 60 0 R/A[<</O/Layout/Placement/Block>>]/K[82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100]/Pg 112 0 R>>
endobj
60 0 obj
<</Type/StructElem/S/Div/P 63 0 R/K[59 0 R]>>
endobj
61 0 obj
<</Type/StructElem/S/Span/P 62 0 R/A[<</O/Layout/Placement/Block>>]/K[101]/Pg 112 0 R>>
endobj
62 0 obj
<</Type/StructElem/S/Div/P 63 0 R/K[61 0 R]>>
endobj
63 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[60 0 R 62 0 R]>>
endobj
64 0 obj
<</Type/StructElem/S/H2/P 94 0 R/T(Required Steel Reinforcement)/K[102]/Pg 112 0 R>>
endobj
65 0 obj
<</Type/StructElem/S/Formula/P 66 0 R/A[<</O/Layout/Placement/Block>>]/K[103 104 105 106 107]/Pg 112 0 R>>
endobj
66 0 obj
<</Type/StructElem/S/Div/P 69 0 R/K[65 0 R]>>
endobj
67 0 obj
<</Type/StructElem/S/Span/P 68 0 R/A[<</O/Layout/Placement/Block>>]/K[108]/Pg 112 0 R>>
endobj
68 0 obj
<</Type/StructElem/S/Div/P 69 0 R/K[67 0 R]>>
endobj
69 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[66 0 R 68 0 R]>>
endobj
70 0 obj
<</Type/StructElem/S/Formula/P 71 0 R/A[<</O/Layout/Placement/Block>>]/K[109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127]/Pg 112 0 R>>
endobj
71 0 obj
<</Type/StructElem/S/Div/P 74 0 R/K[70 0 R]>>
endobj
72 0 obj
<</Type/StructElem/S/Span/P 73 0 R/A[<</O/Layout/Placement/Block>>]/K[128 129]/Pg 112 0 R>>
endobj
73 0 obj
<</Type/StructElem/S/Div/P 74 0 R/K[72 0 R]>>
endobj
74 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[71 0 R 73 0 R]>>
endobj
75 0 obj
<</Type/StructElem/S/H2/P 94 0 R/T(Provided Steel Reinforcement)/K[130]/Pg 112 0 R>>
endobj
76 0 obj
<</Type/StructElem/S/Formula/P 77 0 R/A[<</O/Layout/Placement/Block>>]/K[131 132 133 134 135 136 137 138 139]/Pg 112 0 R>>
endobj
77 0 obj
<</Type/StructElem/S/Div/P 80 0 R/K[76 0 R]>>
endobj
78 0 obj
<</Type/StructElem/S/Span/P 79 0 R/A[<</O/Layout/Placement/Block>>]/K[140 141]/Pg 112 0 R>>
endobj
79 0 obj
<</Type/StructElem/S/Div/P 80 0 R/K[78 0 R]>>
endobj
80 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[77 0 R 79 0 R]>>
endobj
81 0 obj
<</Type/StructElem/S/Span/P 82 0 R/A[<</O/Layout/Placement/Block>>]/K[142]/Pg 112 0 R>>
endobj
82 0 obj
<</Type/StructElem/S/Div/P 85 0 R/K[81 0 R]>>
endobj
83 0 obj
<</Type/StructElem/S/Span/P 84 0 R/A[<</O/Layout/Placement/Block>>]/K[143]/Pg 112 0 R>>
endobj
84 0 obj
<</Type/StructElem/S/Div/P 85 0 R/K[83 0 R]>>
endobj
85 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[82 0 R 84 0 R]>>
endobj
86 0 obj
<</Type/StructElem/S/Formula/P 90 0 R/A[<</O/Layout/Placement/Block>>]/K[144 145 146 147]/Pg 112 0 R>>
endobj
87 0 obj
<</Type/StructElem/S/Span/P 90 0 R/A[<</O/Layout/Placement/Block>>]/K[148]/Pg 112 0 R>>
endobj
88 0 obj
<</Type/StructElem/S/Formula/P 90 0 R/A[<</O/Layout/Placement/Block>>]/K[149 150]/Pg 112 0 R>>
endobj
89 0 obj
<</Type/StructElem/S/Span/P 90 0 R/A[<</O/Layout/Placement/Block>>]/K[151]/Pg 112 0 R>>
endobj
90 0 obj
<</Type/StructElem/S/Div/P 93 0 R/K[86 0 R 87 0 R 88 0 R 89 0 R]>>
endobj
91 0 obj
<</Type/StructElem/S/Span/P 92 0 R/A[<</O/Layout/Placement/Block>>]/K[152]/Pg 112 0 R>>
endobj
92 0 obj
<</Type/StructElem/S/Div/P 93 0 R/K[91 0 R]>>
endobj
93 0 obj
<</Type/StructElem/S/Div/P 94 0 R/K[90 0 R 92 0 R]>>
endobj
94 0 obj
<</Type/StructElem/S/Document/P 8 0 R/K[10 0 R 11 0 R 12 0 R 17 0 R 22 0 R 27 0 R 32 0 R 37 0 R 42 0 R 47 0 R 52 0 R 57 0 R 58 0 R 63 0 R 64 0 R 69 0 R 74 0 R 75 0 R 80 0 R 85 0 R 93 0 R]>>
endobj
95 0 obj
[/ICCBased 123 0 R]
endobj
96 0 obj
[/ICCBased 124 0 R]
endobj
97 0 obj
[112 0 R/XYZ 72 666.89 0]
endobj
98 0 obj
[112 0 R/XYZ 72 469.325 0]
endobj
99 0 obj
[112 0 R/XYZ 72 422.4 0]
endobj
100 0 obj
[112 0 R/XYZ 72 345.781 0]
endobj
101 0 obj
[112 0 R/XYZ 72 712 0]
endobj
102 0 obj
<</ProcSet[/PDF/Text/ImageC/ImageB]/ColorSpace<</c0 96 0 R/c1 95 0 R>>/XObject<</x0 126 0 R>>/Font<</f0 103 0 R/f1 106 0 R/f2 109 0 R>>>>
endobj
103 0 obj
<</Type/Font/Subtype/Type0/BaseFont/MHIXIW+LibertinusSerif-Regular-Identity-H/Encoding/Identity-H/DescendantFonts[104 0 R]/ToUnicode 114 0 R>>
endobj
104 0 obj
<</Type/Font/Subtype/CIDFontType0/BaseFont/MHIXIW+LibertinusSerif-Regular/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 105 0 R/DW 0/W[0 0 500 1 1 541 2 2 372 3 3 504 4 4 272 5 5 447 6 6 428 7 7 316 8 8 236 9 9 646 10 10 542 11 11 390 12 12 271 13 13 505.99997 14 14 500 15 15 250 16 16 465 17 17 381 18 18 538 19 19 512 20 20 220 21 22 465 23 23 519 24 24 264 25 25 457 26 26 493 27 27 747 28 28 465 29 29 490 30 30 220 31 32 465 33 33 485 34 34 531 35 35 485 36 36 839 37 37 515 38 38 951 39 39 701 40 40 528 41 41 497 42 42 310 43 43 587 44 44 503.00003 45 46 465 47 47 307 48 48 323 49 49 596 50 50 465 51 51 790 52 52 557]>>
endobj
105 0 obj
<</Type/FontDescriptor/FontName/MHIXIW+LibertinusSerif-Regular/Flags 131078/FontBBox[-48 -238 947 698]/ItalicAngle 0/Ascent 894/Descent -246/CapHeight 658/StemV 95.4/CIDSet 113 0 R/FontFile3 115 0 R>>
endobj
106 0 obj
<</Type/Font/Subtype/Type0/BaseFont/LXXYEH+LibertinusSerif-Bold-Identity-H/Encoding/Identity-H/DescendantFonts[107 0 R]/ToUnicode 117 0 R>>
endobj
107 0 obj
<</Type/Font/Subtype/CIDFontType0/BaseFont/LXXYEH+LibertinusSerif-Bold/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 108 0 R/DW 0/W[0 0 500 1 1 614 2 2 322 3 3 616 4 4 489 5 5 456 6 6 428 7 7 427 8 8 358 9 9 250 10 10 716 11 11 561 12 12 504 13 13 325 14 14 505.99997 15 15 542 16 16 358 17 17 730 18 18 732 19 19 734 20 20 521 21 21 367 22 22 581 23 23 598 24 24 740 25 25 577 26 26 551 27 27 573 28 28 391 29 29 905 30 30 529 31 31 736]>>
endobj
108 0 obj
<</Type/FontDescriptor/FontName/LXXYEH+LibertinusSerif-Bold/Flags 131078/FontBBox[0 -238 893 700]/ItalicAngle 0/Ascent 894/Descent -246/CapHeight 645/StemV 168.6/CIDSet 116 0 R/FontFile3 118 0 R>>
endobj
109 0 obj
<</Type/Font/Subtype/Type0/BaseFont/LSWPYR+NewCMMath-Book-Identity-H/Encoding/Identity-H/DescendantFonts[110 0 R]/ToUnicode 120 0 R>>
endobj
110 0 obj
<</Type/Font/Subtype/CIDFontType0/BaseFont/LSWPYR+NewCMMath-Book/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 111 0 R/DW 0/W[0 0 500 1 1 361 2 2 778 3 3 500 4 4 332 5 5 278 6 6 556 7 7 681 8 8 500 9 9 306 10 10 389 11 11 490 12 12 407 13 13 433 14 15 500 16 16 556 17 17 394 18 18 622 19 19 510.99997 20 20 444 21 21 579 22 22 500 23 23 539 24 24 389 25 26 500 27 27 389 28 28 500 29 29 828 30 30 784 31 31 429 32 32 716 33 33 278 34 34 778 35 35 500 36 36 278 37 37 643 38 38 750 39 39 339 40 40 392 41 41 444 42 42 528 43 43 359]>>
endobj
111 0 obj
<</Type/FontDescriptor/FontName/LSWPYR+NewCMMath-Book/Flags 131076/FontBBox[13 -250 804 750]/ItalicAngle 0/Ascent 806/Descent -194/CapHeight 683/StemV 95.4/CIDSet 119 0 R/FontFile3 121 0 R>>
endobj
112 0 obj
<</Type/Page/Resources 102 0 R/MediaBox[0 0 612 792]/StructParents 0/Parent 1 0 R/Contents 122 0 R>>
endobj
113 0 obj
<</Length 13/Filter/FlateDecode>>
stream
xœûÿ~äó
endstream
endobj
114 0 obj
<</Length 579/Type/CMap/Filter/FlateDecode/WMode 0>>
stream
xœm”IoÛ0FïúÓƒ€ä<E282AC>Š"µ$†a ¶#À‡,ˆƒöl‹cW@L Zþ÷ù<><C3B9> è!9ÙÇEñ<45>·íÝ£m÷|g~*zç¡<C3A7>úšïVÏ».Šãu[O'vã ³e{™fÔõm=ðH«Ízãš1Šã<C5A0>«?'Ë—˜ÿ…,ùظ¯_ƒVÓ0¶§(Ž?šñ“gtƒ
=ÑÆ²›ñLê6Šã_ÜMëf”Fqüäìª=ùæ†(‘”¼õm½å‘<0E>³½T¢½¯¥šlS<6C>Bá·>íº<C3AD>¼=#Ÿ6îÐ’A”<41>:‰$"JÞùØ c¦›ÐØ-Y>`æµ·Ü7îH7—f¿Mn§®ûdß$©0ÊΆÿ‰—Ù<7F>˜¾ŽŠ%¥_CçŽe<C5BD>ä÷sk/<2F>¢Åºµ<t»šû<C5A1>;r4WJ©Í«ªª¾â?ó¹FÚþPÿÙõ!<]Ð\©\-é@¥™@EÊ@<40> ”ƒ
<EFBFBD>•X%Ý2’÷(“ÈGä=<3D>–È“¹æ@k<>¬ù*AU ‡Ôo€R‘©÷ÓÊ`Í~Å=Hü– øé~—<ø© ~Bð+$~E
?ìg*~è:…Ÿ)@ð+¥3øiìK
?ƒU´ø¡‚ÆùeXEËùáT4ür8høeküJ쮆_ŽÎ4ü2ì †_? ¿Rꉟüré~¥ô ?#õàg¤Oø-‘gà§që üŠâzŸ  vÊÈÂʈc.¿Ürÿ ük¿¾»zê{vcxìá‘ùÕ8¾~5º¶óYá/|n._.O¯Õ_cxU¤
endstream
endobj
115 0 obj
<</Length 6193/Filter/FlateDecode/Subtype/CIDFontType0C>>
stream
xœ<EFBFBD>X xÕÚn-YDnÔŽ#í ÎPD‹\‹^ÙEÙײhé¾ïI÷$mÖÉ$“µéžîmÚ$]RJZ €€à•¬‚l"WÜ~•{÷¹ÿ“B[®^¯ÿó?OžÉd&ç›ïœùÞ÷¼ßëí5nœ—···ßª˜=©é1‰i#Rc"_Û•šê¹·ŒÅÙIš ûÂ/b¼©Ñ<<NàMú*š'ùá¿Üç¼àååÕÿô ^^ÞãŸ}ÁËë_ÿš0ÅséÇ S=__O˜æåãíͬ\ž´'byxDbzLzÖ’¤ä¬Ô˜¨èôÇÎf¿ðZÀì€7_ÜñâXZ/®KMŠ<4D>KqQFztRjÚ,/¯'¼¼½æˆ­ì¢â
+xÎâ*¶[¸° ˆGŒ÷)úׄ'5žj?ôÔ<C3B4>qŸØÔÇËÛËËËk®gFÏÑ 홀'·—=‡A_¯¹žp«½.x'y<±ø‰æ'þáëS9Î{Ü1N0ç
·‚WÌ+ãã|É“kÆÏ3þÎSË&p'„L€ªÄ
N=}òé;Ï$>óñ³bß™¾<E284A2>ˆð¹©è³¨ýùyáóÿœØæ·Ù¯Ï<C2B6>?Ö‚¿;ié ¼ M?û÷oM?;µßG3ŽUÝ_ó@Åý쟓P0Á|hä<à²ý¨ç z~<7E>l`¾Çy çÁ`p…ó<E280A6><C3B3>îpùj`œ`Щùþt dÜA¾ù‰µ¡¦ñ³ï©¹\#4ÈùÝô~ºÕõ!Õ?aªÁ ©’øï2iÌU ÌçɪkU.¬O]û0üp5±N†#ŸGn¡é0òQä›3ªrE v­m*u<>;}:"ÐkËîWRô: !€+*…àî·«OèD¾ß_Z0„ƒ¥àTí¦ê>bÖ«ÕºB<I’R°¬@-׿håüCŠ"Åz nን«•#™ºèÚíî¡\£™¾§ë®b€ä!uõÖkQVTã°âf³Zb"‘#R£5¿¯­©«#‘¦Ê¬¦Ðà=»ÃÓ ¤X.Q˜ô˜`›ÔÅ>íòî¼t×}:A(:íÈSNî¯q8‰î}¶<>Žc?m‚¯-J‰$¢B2ׯÂÀ6°½~ð]8ú®ˆþs ð½|£êÖ—¤º`Ú>ö£Fžý^#òýîû¹CH3à€3(”ó Ÿ>½M’Ïe„E*.ËÀ%BQVbk^eÕ]sÙÛÞx¬Ç@ù¨Ÿ9©!…®<E280A6>H’„<E28099>- Ò|HQ$߀!<21>yÀ…¦Ô¦Ô6Ö6TÕ
“ Ä‘–”–F
^”îaà)‡wÛ`Çuöù;hDdbÎz<*´j ž9Ä=G1P©æX<C3A6>†¢/¾„ä›<C3A4>_ÝXäˆ Ãœ½içðK‡\ܤÊ"׋i>,ëQÀ©<c®ÅÛ»…o(R}¥ûY‡wÛuvÊmTi.d
hþî˜<EFBFBD>Œ|ñš àIðDßÇhŠŽfÈd]IA^ÕXÜ<¸Á=óåÉp
DÏßc+¯ô“X ßv€©fï[C>]ì"4O).$óy
šbˆá!îÒæ¤žžþê}„Ú"7Hi¾(%¡0O–ÛO<C39B>ÀðÏR˜I<1B>QiœÐÁ=Ÿ5„A¥S( ”ŠB"—*òU|±Rª’‰uFèƒ àYã=°éž÷™{>gŽ¡‰µiMMµµMMiµ‰‰ii‰÷›k‚¯¤<C2AF>ì<EFBFBD>6ï¶Û>à¾ýæVÏ­OH³Bf<42>àï.}?~ñYàU0ýz͹ÖnòxÿÑÆ8 çÍ­'­J‹®È 8 ë“òõ[w¹áÓø_–Æ­#—¯ ›ñg .þNq„@\)dýèD¾w/-!CÈy°
ü‚"<22>r™\mƨu‡3Žÿ†™yRåZÅfì´›v»í”}3[õRæ
yÈ©*³Õd&ÚÚ»«;p[U~º•´ˆ´É |Õd‹‚PÈ5B½'H ív·z‚è š*…<>¿Q/ñ™ÁTö¥7ÕÙñÖh9¿}cþûëH ”:ÔBö‡Fä;X›}L¾„Äöe¶ë‚C1­ÅBëq¤ÙhШ<C390>¤¬¡AÙ†þ±á»O¶»ß¯#‘†µ5a¥ƒXgk<67>³úhá_Š ƒÜF |¤Hתm£|¤A¿£d ¾èƒ+;â/Ç‘Wc*…!ØöÂHiÏ(.’’5’}ò:>+7dRr9_[+…ìòQp~ùý8—
vü>äù†a&’¨ÖŒ®ªc˜‰Ú)Çèª"Ík sC:g³)ÿš;¤½²ð½ ì²—[4"ߎë yi7úQ=cÖÒ2¾.Í­ÁL*=mÐò‘¸ê
Wéq£Á )•ø+õ•û1vo¸<C2B8>J]<01>¸S¥ óÂTêBmŽAÎ×é4:|ŸªHóW >Ç“©Õ2B¹§<_¾;#"Œ IY·ƒOŸxxHcG›Í½Ÿ,º€fª óÄD\d\N*´ñCðì¹wiÙÛ¼WgÃ[ëòÓmdIŽN<16> ‚`AX<^Èf<C388>|1¨Y#òm9½çÊ¢ƒ`ûgƒÈå*v;­¬¨°Ue–%§ìÈŽI!‘óU&q¬m0oíëAµñ<C2B5>É$Ò’”–ƒEÙ’êó äÂì ¸¤<C2B8>!Ø›W’/L?¼Zrëk‰–ð÷èH9’•ªV¥‘T®”Rà‰Ñ%]6C•µœÌ«m”uà7?ü¶7¯!ÑNZŒ¶’bÜhTHärU!S,-‘ ³á©“QUQ™º¸¹QW‚÷ï¥ršÈŽ k^
¶drÄQo5}âÔÖ5¹ä|X ö¢³‚3#ß*8{òL]ëàGÎ<47><C38E>„¨`r/‹‹¼Aí%v1HBA7·_Ó¡5j-'Ž+SÈJrÕ|ȇó^‡æçê Év„¼ÎÝ¡ Ýo[h7ÝÓÑNµŒÖÎvF¨îž:Í+)­´Z” ç€NvÂ<76>¼<EFBFBD>+gÁ¸Óç à¢ûÓEÞç<C39E>Ù¼~:š/‘K”äøg¥¢”*Lf<4C>›=Ã舯€€Ãèµ&=fË(Àïùÿó9Ãô3R 7‡@äò7ðè@G¨bਢ‘vÒn·ÃƒŒßRÅþtû#ªØ¾6ÿý5$Ei(ŠP)r+Fƒ rñ±â¾ý{Åý`¹G¬•º<>v·;¨Æ1Šc
˜«˜ TíËê@ D>œÐõ!0ÌB¾ºh D¹ñ±NÚírP5£!ö £ù¯’*¡,ª¢Bs<42>5çü ¿¦pk&-æ«hµŽ°ÑÕ´­¹™²<E284A2> ŠaR™d'ôoû)õ*F<>1-Ã7oÛ[\&7ãÿ(t:•DEEDÒé¦>|üaeZt<5A>8=1>&%3#'Yœ©âƒÿá!w[ŒŸ~o1ðô™Þ`b‡ÏO_£ñ¤øzi…ЬT—ËÓ1aÔÎ-ù„T+3ʈcEGûÎ`ÇR:ÂA€ÔÅöº|{σeŸn½‰üâØsh—;eå¶õó_Î#õqmy…¦Gî¹<>9Ð? 9zkAM…˜,‘æ[E¸P˜™öEò1ðÔ½ËÀxÏëXg!)-ùáJGMçAÌ.«M«#ª3¢Ë·àð¥Ð™±yQ­‹qTž<m­'=޻㈸á2¥èeðä§@ü]ÚµÝGIWJ¨=ù58nÑñÒà&2©Ñ™×<E284A2>3ì´¼L.±’Í) †½®Z•·•˜—±½ Ÿ% nêxO7)ˆ†1B<31>îd9=:‘ïgž<67>Tr³Ùq(eW‹Î‹¿»<C2BF>>XÀ ”(ÖŒÂÕå©.wßcT¿t¸4€¯˜¡,JBZg—·à‡ûË;:ÉÞž†ŸcÈ×÷~;mçÖ„]a2$—+5”…<E2809D>Ü®ŒD[ê{ìMøÉÁ%<25>3/q—­/Ë"EJC+V𪳵„À®Jáýež‚ýziûz¸X“Ñã›Ï<1A>DcCyÈ鱚ù·Š9ª4¨b‚W¤<57>{úØqßÖ«+/ƒ¹Ÿ"<22> §<0F>7%÷ãí­å¶*‰W[•f‰<66>/—eKóñDª£‡/ñÀ”wÏ Ú<>f×4UT)£š!(e(š÷µ;{³!G¦Rª(b®<62>ƒtÎL[¶ù}lÞá”3.»É¹<C389>°•q´`5
ýxùrY¡œ¦Ä¤'áÛ2ÜÍÝU=*IÁ©S%dÉ}#äó鈹Ž4‚wX•Ë•Z3Vñ<56>–Ç0‘ö»‘Ë §²TyÒX¨×+­¸Á`1›Ì«ASTÀϬ±Ë]øÿ€§î€9@ðÆÅ7C"²“âIc<ZSo77áÇû½¹;ç¾/¬®‘@Ç«b,ÅE„™…ì,‡·ÌúL1`¼ØÍNA½„*šŠŠH¦SF`Ý«(’Vmá%¿<ƒInÁÍ&C™‘üP?Bš3z©Ô@‚‰àLYgyã€n„#DT•<>J'Œ»¨”&æE¿Ãý¤©JMaÕ\<5C>ä—Ù«µdFF%¤ÆŽ<C386>èUZ+vrüÞƒïåǪ©üÿwÀžÌ>º¬Oç/<08>¸À‡.ï}WAÔU0ÜEnŸüø÷ó­Js¡ž˜ž°:tã
þê%ñ³ÿŠÁÝ€vL<<04>ë×w^†“R óˆ‚(´Úá Ëño«gnƒO„nÛ¾jƒ,¨ÑÖšHÁJµ¼x<13>ßrà }Á<ø0£õl xÎoB <‹4,+À/hºÓHwëÍ#™ÚM%$$Œ-£S՘ݸçDüô2<C3B4>J©à#M ß‚^a[3TÑjÿG˜ðp±ÝÞHÕ<48> ²%QL!SÝòÑm?“•¡ GßñsíÈQÇ©F¥±ƒnmo jGÆìÒåêÂŽ¼?¥<>Òé ž'}ñ<>¶ÞZ}ëè‹Aì^"*<2A>JHHË<><C38B>ÜZئ,R¥Å¬˜í'“*éÂ"¾Þ<>Þó>rÏçH×o» A€æktù¸ºèâÂ`ñMäÔq6VfU•Û+ªMjƒÚH çÕF¹Ù„ÕÕ·žoH<>¹2}˺µÄ¢ÅäÖŒ—rv¬Ã4Ú,á¶ô¨5dñAËEÚ.×çk¥jþÒììÔ(.ãö<C3A3>þD¯'~ø†sd°kß% xÍÙ÷6<C3B7>œ‚>Ëæ­%=’†½ òQ—}@§GÏ;F×zµFIlŠÙœ:g<>VÂHÍr~eOµ¡/×¥Å<C2A5>pˆ˜ü˜°Ÿn¥õÕ>æ¼§ËÖ_ÅË*…àÓöODµ"°É͈|¾† <0C>Vp ½¦Kߥ# ò*<2A>GÕMÕQMNÌI×Óõº45r9“J•ÿ|ø€{ÈjÙGtsïÕ…-«&­EZ<45>‰D.*:sïªM|-E«dH•­ RqhâÆmxÌ—xèJüÚîpÑýtw÷þÇM„átÁNž Ý£ÐÙñÃÊgëÒ ¤hG¯G(<28>ôTS̘@ÏülâÙ™óB§Ò)•KåÆEÑ1£•²_U,^Ž!Ý0ˆ7"¼#rRñ„m%·H°â¿íS–HV`po™ýƒïÁ2ik>x<> vúœ_ Ý,yÿ)Ô´^[9ŸðÁä)7vÜŒ!<21>¥_Hš<48>½½+ô<>Yk»¾Ë <20>Ì|Fª–*˜ùLŠu;éþ¨1ýÞÝUTí"<22>¶¶?‰Ý{§w^3±¶ú¥ö/°Ã‡?ü¦yõrQ¤.¦ÍFeŸ²Qz<51>/íEÂ&![ž†Àш|ËÀxº<78>ƒ7<C692>Õ÷g>ª[I­ÁYí¦íöž±ýê}<7D>Š‘_M`çù)éK>yÄ`p¢ÚF?`8R¥J©ÆÕ*½IE"+a(«‡Ó´cùŸVÔ²…|du؃ÙòµâÔ Šðô¨µµî±Fw¹^Ѭ?ÌGjÛÙi-„=(ãÈt†Bn`Œ&†D‚@[ÏÑrá0÷2Ûïðµ‚×ÀB°ò¹Bà›hYcq£ÕþêþñgÛ[RÖk!‚<<<3C>”?Ƹ|äN‹ªEžõ2Ìò“å¨
m Ü/k¯¢òðMGRaTTL2-äVÔ¯Xæg•î”&‰cÅI¹ñ|‘$¯ 5O©“à‰¹ ùB[NC•Ût²•°“ÍÂû\‡¯¼ ƒE›Áà<>ü|€=<3D>ÂÙ–©hH°ogr霣¬µ‡ÚM…ÅFÓqc©~sPUoN©YîLjuÒLJf…=
Ng׈] z—v$@,µ›
<EFBFBD>N¤Gt«ŒTeX÷ Ý/Go<47>áÅK¹‘3ÀMŽÍ¬Óëq†‘dHÀƒ×8Ù½ÔŠ‹Jõ$ØÉ¶»*jG“K¤â¨””ÝtØXr?wªÜªÜ¾¼¤v²Ÿ:½ï]cyw}ÀË÷ýѨ͈ñú ÝÞ¶Wýã„©`2XsP` | ¼7‘K7©Ãñ®GQ6<51>çr•ìñgá8 î‚Ú'Ï<>ØZAЦƒýYä}ñ<ˆá6|¥Ö<C2A5>–~Ë)é^¢«ùKD‘ë&㫸áY•$À»Z®?£#ÍgLEDÓ;Gç󟳤;ŽÐN\°aDU¼bÀ“>àSv
zHi ·¾ ·úå„+49{—€ ¿¬>¥õ qô}DS±± cµwPṉmÏÁÓ~¹ƒ¼· ž÷á>®ÜWTwX?¦,Ò¨”Ø:u4;TU
ÙI@ìô¾;ä–x¶‚ª;<ó㦚×.˜ÕSë°—‰£Kˆ,SQ^^^[e+—TËÈŠ”]þÖ¬Åp6¶•—¥³ïNÃ*n`Ž2è1×5,¨Çø]Fîi×Òfµô8AÏ#Ç:þ+¤ ¬÷dó.ï‹ÊÜôòp1'¸©+ô^Z®Õ[HÆH™•&þ®TgW
}A$§«äË?cýÙ<C3BD>QN¢{ÇjݪàPYŽ$FÓtð¯šnº—noï¥ö<C2A5>iˆ®‡{ÃUV†?—ÇÃg—&½BîYÜ&«ë,!Ø:Üiì˪`yN<79>È×ud !ÁwÐÇÓ_þ<5F>d÷¸Ecëx%Ê"‰L^()$<24>‹ùYJ•ØÄ·Å…›Cq(xã%è7ë#ø ˜Úà0XÊI¤«¦˜Ñ
±4vjË`rÓ0ä"ÌæeQŠ|!NO¦rðõoî3Ú{á3é²7ˆS«IA€Y¨a¹×ÿPî}Ìhòì•Ó¡ÿ6¾˜)0)ˆì'ö>Å?q®ùövCž{>œ‘¹s{æƒIõ¦;anE3bc©l|FÆÝ~ðÄÞþý‰<> 2ÔÉòDrXPžéSþfù‚s·<73>;àX<>¾ºí½µùu¶\¢<?»Tˆgff‹ö\‹9ž¹ùðýæƒp\Hd<48>,‹´<E280B9>w8ʶEnwj™N¹\ö‰Œá wä‚›ñÈ(­.šŒ<C5A1><C592>ÛÁv¦?5½IÔ°^-qß<71>-vßރߟ@ºÏ³_ –]…ޤuÃ`<06>Q«'¬z«¹¯h‘¥¥ïŠ"wDF„îÀÀ.’in043­|FQHKp¤;I’<1E>rÍŽÒ†½vþa·Ãу<C391>\_¹í¯I[SòK$VBsîc"ïRÐìzîcè.”þ3ˆÓÉ앦 ãhªås§ïÝ!°yÉKX ›¹È<ÄûÙØÃÍÎúŠRSjÊ_¡Vª˜6CS°X©Q)1¸ù·\S^ŠQ{©C9¿ÖT]RŠ7–d'ZÉl£UbÃ+KJ«Ê
ÊE¥d©(Á<1C>'î̉K#Â
7ÏÁþV‘ü@ÉchuÒ­´ËÕE¹G+÷ýáöwÄAèù[èY°üLðyäû›…žÛxp<06>\ž¶|Íü<C38D> {ŽG<C5BD>õ9äVbnrVjOTö®plÚ¹ {`âÉ»—ަln!–vq<76>;½5—œÄ<C593>[ð<>!è®÷›¿´Ÿ¹~„ìM✈¨ Þ<>½´0{<17>\6±½è©Ú<C2A9><C39A>A›w%‹ÈøJΪN™£ëii?F€dÄ<ÿûØèù<7 Ùæƒ_<m«ÂÂÿ¯®y¾bÓè¬ít;ív7ÿ›k>ìbò<>ÏZaî6[3ÞÞ˜ö óæ*‚”#XÝ0ÚTݨ<>)Ð_ÁÀ^‰¦„²ûº‹;ðöêŒH¸”7OªØò«±.<2E>™õh즇cx·rÏÌÙº:sÓB¥’+Ôf~gAxË|ý–˜àPÙ¯PÈe”•/Ði:@Û¯e·ü<13> >àî³Ú¹ˆŴºHkÑ󥦿VeRi5<>°îwZºííÀA·ï3µ†,é/ýØ4 5ˆµù*þQôº8äsCóÊzI<7A>r›÷oºŸª§<1A>˜Ç.¬ýµêü/°@¿¨
endstream
endobj
116 0 obj
<</Length 12/Filter/FlateDecode>>
stream
xœûÿÿÿ úý
endstream
endobj
117 0 obj
<</Length 485/Type/CMap/Filter/FlateDecode/WMode 0>>
stream
xœm“Moâ0†ïù³KôÀƆ[„<>J ‡~¨TÛs°‰Ø‘ãø÷+{ºZí<5A> Ç3ãy_{,~¼ÆOÆq<ý)á{7x<37>ãò¹î2!¶N-Úð‚hÐÜ¢ý:ït<C3AF>Êývo›<6F> ±·ú2¼åü/eƒçÆ~'ÄP}pm&ÄG.¸„-@Ò{ƒ64á
ò!â7ú¾qv *bgMéÚ(®Ïrîù›wú€N<>5ž;Á1öÍÔL£Súê¶îRñáÚl÷öä`JYfè8 ÇsÓ…QöOyõ}cÏ0º‰ý+xºî‚Q$È´ŠÖ¤ÿ<š©[„œ ßWÙ%¨ï¥<C3AF>k‡¼AþùìÌ IÔÎ`ßÕ}mϘ­¤”r «ªªªuìøO|ÊeÇ“þª}JWkXI9“ëD“DóG¢)ÑŽ¨ š͈¦DóD‹ Ñ‚ˆc¿ˆ
¢ÇDî÷DݹnC{rfI1ÞeK±’hG¤ˆ*"ÚEÅ<03>r²%"EEDþŠù+¨Ÿb#<05>„b¤Z±?: Eþ
Ò¢È_A:ù›swò·àLò7Ÿ±?VMþ#Å&])ß]¼Ü8Ã÷iÒƒ÷hCá4:qN‹÷·Ð¹.V¥_zD·÷éµújyÿ
endstream
endobj
118 0 obj
<</Length 3670/Filter/FlateDecode/Subtype/CIDFontType0C>>
stream
xœ¥WitW––l¬ ˆŽ‹r *T¹ <09>…À$$Œ!!BâÁ³c08,Kض¼JÞmÙ–%•vKò‚yßÀ¶lI`ãÇ&ai „„sœõt§Ét¦o1<6F>™ÌK–ît&}æG½zïÕ¹ïÞ÷Õ}ß»Ÿ7m<1A>Ïç¯'ÆIÓ3S²2¶KÓeK^QŠ÷ç(îQƒˆææ‰xô c0ÜkEØ£*@×<1E>Cý4<>Çã<C387>˜5<CB9C>ÇãÏ|x<1E>÷ý÷¢ùþ©¿ˆø__‰òù|<7C>xãÚxEœ4"^š’™˜™³N‘š“žx0!3ôÇÞ²gž]¶dÙ3˞ݑ ý1¦Ð-éŠ$©$3tmVf‚"=c)<29>Àãóè¢jîÕšêvöÖuب¤ £gè‰ïEÓ ¢™ž2Bœ¢‡¸Q"<22>Ççñx¼Pÿ®f £þøžö7'ƒy¡þ%#y×ø›ù·dƒ<>/žœ¶eÚö ,h@ðº […<>Ån
#„·¦'ÎP͸>S-š/:ÿÐËÙÄ ÅݳÚ~·äáYQ†QîÆ(ß0Ê- 4Lãt··ÜÑ þý¿iVƒV#{Ðw’ð÷<C3B0>¹`¿û-èN†b`œ@þ|!ŸiPœðòA¡Sö?Ãâ@¸y{>!AEeJ­1d95 ]‡vyg!¶B¡Ý¡£ïÏzŒWŒÏ{¬G´Ài34©mÂf…eŠäaïT4Ž¿u1‰KÙ·2_i4ÐÙ¶‚šZ_£c[¨ÏÎ>êaF½uçÇIOþéH7Ý$ÛQù2%Fy Jn›ê?a6ÿ[ „|°µLèÊ[­(~¡4¼D¯1©LáD¹³t‰v`+Šõ›Êi<C38A>Æ<EFBFBD>eÓ}FŸq|ÜË-°Ù M›p“¥Ø<E"ŠK!’Z’<ƒm}m]™}b2åÉ´ø\ƒ’^á !°Êï2Ûïò ¬ÝãqÕSž®œm z Ë+‰ÓýèàˆqxâøO˜ó‘ð 1£Ë%¯î“î u½Ú.YÅ–Z (™zsÁßF½ù¢êøÉ¢,jó)Þ¨þžóî v…(pü·â@ÜÎb)…÷ÒÞÁ¯™
£ÅJB™ ÅZWóqÒèq¿1‰–¢%[7‹gûGò.S—Þé}”©.¯WÓ¨Æ^k<6B>KØRÛÚÝi/j …z=#~Jý|áã»<C3A3>
ä^ø”¨Ò7Ó2Ibv
õò–7A<04>­ãîÃñr3“jnW¡Ž4·vî|ñьǞFOlhÞ6 cdCù—©Ó—|ýŒ=Ü „Ë0ÛµæF¢¯òpõaÚiwT¦•%j;SZQWÚLuvtùÚ’»&H“#Þ`´}Wùˆ<C3B9>t°¥ö*¦(ª ¢L¯1e߃²ä@ù FÁênº<6E>‚>aà0,",{¬1v©PÓð‡¼Iꃯ|Ÿö”¶g¶2Š#Zßp %uG:Éæ††ÎÞù¦Vº^WitVû´ý%Gèyºs­’Ë™ÌÌbE*™\•Ñ ¤»'º
„žœÊƒ¤\ž›»wè}%<25>g.eó´B1Ú¥~>…ÇÁŸAÂG8ÌÁ¿9Ç…ùÚâB&+7²ú¼@¿ˆE³£ÉGbc<0E>ÝÜWÒBMœéèp1U[‘“V¦k³©¬¬ºQf”ýë-ò<1B>³Æâ`º1‹ÎTN㟣écO<63>é¢yÈ@Útærÿ¢LV\–Çä–¥hÊJ„e%ÚÔI1šC˜ÚW¨„~x½Á÷ˆ`1>ÿs—
,¿@xáo"XŽ]u”eÖ0øLG¯Åv{÷<>¦<'ÍV'c©`´valf‹OÁ GAôfÓ‡'¿ý%|<7C>6hÖÚì0z?ì¼Ó|ŸWh±]}núŠUÐZmP»!^<5E>ü"À0aÊ0åÈ"£½¼†r;O×\r˜lz—Þ&Üi-®=ErQ~ì¼Ùm e–ZVôbñ«:]‘±ÐZ"<WneÃI‚ámÙÖ
(¡¹[ÃG¤Œ¢¯µ`’j¿r¼¦‘±<E28098> r•QYETtü$L· 5t3íuíµ]T[«.©…A,Vj(1–Òâ=j_¬áÖ{ƒ½ð0¬<30>`|<7C>[y{&aß¡lXJÅn)H<ÀÈ’oì!¥Î½ÍÉôPäTâ±dá<64>|P²<50>ܳ?qÓúð‰?ªh<;Ï–§Í×
Y–e©—íQ•2<eVM<>©w{™¾î#CgÉ“Y½ÉGéøcÛ»ã]B‰ëÕ“§ÈÉžž±<C5BE>;VGÔÓ5ÚVC¥C8®õ–½E‹Qvƒòö:?€· wßœX‘W²é'T7hœø;ª›"¹ ¿ô ÿ¡8F}zó»ð¥/ø8ˆBÌ€Ù¸†Gˆ¸ŠöœãÔÄ@c¯›Áé«´ö"»P]¨ö粦~„1Á‚ X°¬så+hÚ<68>EUÖ@_[S‹•µ±6ZïÔ;MNa¥Ñ^u”òõæ œY¯ ½ó“Ö¦¬"Ãû~ÚùÖ‘¶£´Vh¦JOÏË¡öçwv»ÍÝ—›q±Ú—«äf]<06>ÏW V@(Þ{pOY¡/ÒJiü˜¶ªRWIUW:kõÂä<C382>3ê!
a:Àc§²&ånÆ{p¯3Š:• La`ö«8@J&šŽ6™›©wì“+ <0B>pUJfUs6#F»@~•ß½<>Ðr¢¹e°º²Ô©`PŒ@™—[\­naÄðšÚÇ]óñbXx{\'`/zBÐÆÇŸß¾•Þ™²â_H´žEÁêÿøÈ}ö=qºûú×$ú
<Ä_?ž<>ö¡¶¢€E(`9ða ì¿2õ9#†Sû Ô au™/ø(,†)ůqÌíEÄ“ËE†3ë7Ç?‹xä³}K/m¥wž»šõÓ€×óæµ£Ü^IÂt¬÷°³ÃLÛl†V<E280A0>M¨`cX©,Â+Z ÑÒmáIm›VB¢'1¹<C½›B/í„0˜óIõ‡î1f|`¢qœ‚<C593> «—·2ø<32>Z}­©ÊVâ+-{Oˆ_ÛÕ‹¦Ä¡÷qg|wëèñ—'‘!žëzõÙͦ³—™aßÑ©oIˆD"x±tÔVBI<42>Àd`~µv1€Àä¡/ÁL‚[ŠM´¹ú º ½„£ ˆ¹æµ´ª‹´XŽJ|°æÏ;•ðD?(ûµcÁ•À_só)Áï@\ô îçr4ÑQ[ånHë”îÛš”–ÂàƒãÎ¥)–Ú@<40>•ÄÄ¥¥Æï&÷tF §ÑøÐˇR÷F©Èls‘3ŸÆO„:
ªJ]áþ´}ÛrIYÕþöl:uà‚f˜ž{üÃÐFõ1I;Ý<16>žªXK多<µÎk£nld»)Ü;>v¢º«‡élsõ’“
wbí´­wRŽ
<EFBFBD>ÆÌZê•­~5 Þ #>€'tQóâ’r˜œC»õR*"vd¬ÇÐ\éb´Îj}#…ŽˆÅŠ¢´ÈÒ+cWêÛN¸âWÑb´©Ay{žŠßR1å¿AÀ¹ˆß\.Ħ:,fúþ¬„]ÇJ$k<>Ñ‚Ÿý&qJTB¦¾¾ÈÿB B¿„³Ä<C2B3>°ßvÅÃt¬¸©QÓBÁÓ7oÁã“ʳñLoBôá]TÊÎy£è;tM¿R—AÒàÀl«<>lëtW7SÞáh4=,yÉóÅé¶ötF<¨¾Â UüÏ!–CH Ws X‹}d*j!ë´•<1B>êØlÅcüÝcàx¬¼¶,ŒD‘˜Ú 6ªéô¸$}%I¶¾ËÀ‹?·T²9»¥Æý?XéÕa$zû½oç'}ïwy‹6¥›²å~Ãf}Oâ÷¼ùżïyçŠyÃÜLU°žCÏÝNÅaåUb˜ j«ÍÒBÁ6ž9‰Âª¦°Rý\M«¡ðÁû®ÝÆ/<2F>ÞIÖýåxK›3†â¸KsJò7'$P(ùŽ#-2¹|Ÿnî6õÆïÄ<C3AF>6RsŒ¹Ö+ì'²ÊÌN ódU®#u<>¸Åàã¾UÝ×<1E>ð­<C3B0>Ø,P4œf¸E?O˜•l2+¹{®ÿ&cþþ`c¦2<04>Ôç¨ó¼í¤Úª4é…ëT²íó)±^íã~B …h tƒ„@<40>üe9<65>—ßv¹½ôØ`Ý;“$<²ìzrEdJl<-Ý—»y °‹xgè4‰bäWÊaÖ•?Õ^»Èˆ]wsv8_n]p„Âk‚ßàT(€àÖaøµ»ê¿á×/…²\U]—•èÚK¡¹hæ4wKýš³±LzoOá$Õ~®Ë^ÇX-ømŠ&"ˆüìDuÙ<07>ß:þþù–¦’Ô&FŒþµAÉ…ŒBº<42>Ë_nçÂlŸ`õuÖ*¦³±–lzјžô65ÕYò3*h¹£-½<>:ÚÒx¬ýЉßÇlÏ<6C>“22IbôbR¥ÇãÊK™T¬Ì¢k¦GQ¥`åÿ]$|DŠá»»Ú*·.د®–ß{f?Š_»'²öbVƒÕJ¶ ô:ë~Ei wÿde‰9÷žÒje]:'ÝЬª–òtü³*M2º\&‘o¥<6F>åK:·P×IåÛ|D×¥k6<6B>øµÿ¿jËp(¹e=|H`=<_r‹ˆ7µyY»W¡<57>s´%Ú
]Åë>GoÕ[YKA¿¦fÒz+a÷$ì6ÊPÀ[e&•+A—æäÛê4Õ”Óejt00.¸«;Æ­sï[f±r6K&3¦þ@bبïá>ìá×ßcmXë<03>÷O07ìÆºÊ¸Ò`1ŠžãJ«Q˜ò„:£ÎB»ŒãÆ®;ð`ïÉ–,{ZR@Õœ\Wa<57><61>¬0VU:iàßxûääÈÛöa¦³ l‚$Ö(}æÛí¡èÝÂCò5¯È [ÙIÅBˆø<CB86>7ÆÿÙ¿¸±
endstream
endobj
119 0 obj
<</Length 14/Filter/FlateDecode>>
stream
xœûÿÿÿÿÿâì
endstream
endobj
120 0 obj
<</Length 568/Type/CMap/Filter/FlateDecode/WMode 0>>
stream
xœmTÉŽâ0½ç+j‘èCO¼@ ŠÔ$DâЋšÖÌ9ĉØQ–?²ËIFh€Þs-ï¹\„?>OϯʜñYþdð…<C3B0>ÚŸÓ·¢ Â03åP£îߪñ´ÛBÓš²ÃÒcvÔU„áQ—·Aáó¿<C3B3>=^+=Ø<1E>]oê ¿«þ†[XNê¾êïÀž‚0ü…mW½„áA«ÔÔV\D¾DŸ­)OØÃ¥Òªõ<C2AA>àlû\€ªÊÞ#÷]ÖEã’O÷®Çú¨/$E©¡ñ‘Ñ^«®oï°pž@á…N>Z…m¥¯°Åþsxšæ†V$0Ç¢Vî7²æß‹!ò†'Ö»>Sß÷}<7D>è÷›Q#à$±4
»¦(±-ôƒcŒ%°Ëó<OlLJ󥤴ó¥üS´.œ'°Ë6r•¥1O#Ø1&3B’ЊÐÒ!Á­Š_Å„„ÖS]™³¡J¾Ë EÇ„^Z/ í§Ü•$&M`'˜„²ùÜ+9Pm<1F>¢3n/„±µGÖ/ckŠäb¬”sêÍåcmNžcŸ±šï‹´sò-=š}Ç>Ÿ|‹ !òí<C3B2>pò-膸õ͘ ûäÖ3cÒëš=Ë51‡ÇæùÄ,‰lV³$Æú"¥y
šµØò³&¥ÂÏšæ)fß’ô ëÛ3¾¶õΘH ‘ï59~Þ¾¯Ÿ7½A¾÷Â=Yÿ6íãµ;:mK9´-êÞ­¨[ »•Æi×ÓØ,÷qãÿ<C3A3>Eù_g_JÞ
endstream
endobj
121 0 obj
<</Length 5559/Filter/FlateDecode/Subtype/CIDFontType0C>>
stream
xœmXy|[ʵP$ ÁÅB´"šWJi–¦„Hâ<48>ÅgwG–¼Ê²-Ë’l˶֫哵Y–åM–äM¶eÙ’wÇ&IÉž@’<02>(¿H ´”äÍu¯}?…¶´ïõŸ¹3÷Î<C3B7>;÷ÌÌùÎwh óæ%Ðh´û·Šë¶l9(Ë]¼¶¨¨ ~k=ùù($òÈ…4Þü>Àe"ëûУ·½Ÿ|tÁ—Œ… 4ÎýñRöÀ„„¿ý-ññx#=qQü’–ø_ t<1A>Éî}YX$¥EYž¬üWëžL^¾ì·+/_¶|EòËY‘$¯49­´H\T˜'Ë+]’œ–›Wš¬(’$ç•&KEbÑÁR‘0¹L"I“e¹¢ä ;¶§%¯/’È’7çe‰$¥¢äÅ‹““KE¢ä\™¬øù¥Kee9KФ9K³‹$²Ò¥â:•.<2E>¿·xý¶­i‹7§¬{uëöW—È”²äì"i²P$;˜'.]’<>pO-á׳¾É¿pËäº,O7“XY¼ùóÒŠïu&·Äû†æÜ»½ÁáLLºoÈÙhw8ív§3q=<3D>–<EFBFBD><E28093><EFBFBD>ð›8ˆZ¬qÐ&$$¬Šcò³¤„ßÄ?ñ‹„ž„´Úø=OÞsš®¡_™·}^„±—a`ÎcN³V²þŒZîÝqï‰ù›î[qßíDÿæ‚úgÙO³[ï_yÿW?±< y ðÀI I#œæ7?hç>Ìí~èŇŽ>SdÊmj
ÏLѧ"‘ýs‹˜Ss•\2ÏÌ¥°Ø”YÝC&Fi'ß¡ã<C2A1>Ég¹n<C2B9>CÎ{žÙù<C399>÷-°ƒ_]/TUJP6µd90ÊÔ¹ºžðó¯0÷R»JA5l<35>
<EFBFBD>BÂ-¡H{¨¥ÛÓe÷Ô:Án¡¤aTç='ì…
Ð6B4Õ6Û›Ñ<| <18>®ÚŸ<>žÀ<C5BE>OÐf·’tîÜ÷ÌJ<C38C>N¥ªÓ5óÉï™ÍuuM jO5ŸJ<C5B8>÷yÕõÕ|öceº<7F>×öàŸ÷)’¦n§E±ø&‡Âóñy®œv‡«g|80 èR´
<ÅN¤ÁfÝU‰T<E280B0>'Ï´v¾Y>m³ÔZí€8ÿÓÓìás¨^©¿<C2A9>ÇùŸ\•2û‰++þÄ?Ó<>‘±‘1ÿ œ€ßWLå<4C>fOînÄ¡ÒA Ê/Dx=«K×iì‚ òô{}~_C«³ÎÇ£>ŽGš<]-”™n<E284A2><6E>¨5Z<35>€´„VɧÆYrжòØT›º1LFø>ÌHúÓŸ¹Èñâ<C3B1>ä-n<>´³°°¤¤°°£¸‡×ÛÑÙËß=w“û<E2809C> bŒ|PÔìˆ3l°›=Њ€¤38—¨_Ô€ˆ¿ÉE¸[Èåc<C3A5>ÒT£7ê<37>e–@B{D1Ž–‡’0í}¼ç}Î8>Gþ–;Ì}…O)ìmÎ"̲a¦ ¢Œ<02>[56<35>Íè‚„·±`Ò6ù4'2zWÁfH/oCð9ƒóõ„DŒ˜ê u[u|Í,Pÿã¨Ù ¯ÕÛõvcøÞȺrøÒeû=ˆ‘߯häwt²ev)×£wTó¨_š¨ŸÚ*«N ·N‹ÛRgq@¯¥Åì°8,6`¶LDýl®›a(ÓT«ƒ¹Ü"$×è*5ñ­Lîgv@-¸|è2ÎgØ\VÇ«¥ Z¢J¹·<[%ËÞ¾9g) %L5èÁdÕƒ©lP[ë²y~˜ìe8ƒ^¯Ïá´ú­€º!Èg?12;¥ áÂ<C3A1>è80»„+8¸M¾*Žù4ŒÖ…›Ñœ<C391>åÆ-¡%¤¦,@¹BfGí[Ö<>ácxËÒaF±\–¤6<C2A4>Cç  ‘‡Yífg <09>MÍ@ ÏF±¡‡†ï¹xõK:n<>ÝÁ]ž²n9ŸºgµèêÝYå8ÂB̲1F¬£–QŠ•²òã0;ôS|T|Ï‹R,Lgï}÷¯\—Y¥ÓU<C393>‰›*{{››ûÆÓ»3xlªP&ï<>ŠBIß¾WЇïïã\Ÿâ$îñ‚×Y{Ê·(úÏóp;æGYœ3o*`ZòM} â W¤óRMHò1`Aj«(¢ìªêÐw:ÛöŸM!ê`<60>ç&)ŒâGozzh3·ðÑ[tòÐìîXfw:o dfÉVåêݕϢMÌ2ÑqX;÷S†ú ÍAmQMv…² TPcW»úÍ>èC<C3A8>ÕÞâ¼Ò¼ÃE“¼Öûü}áŽÉÖSžX}ÔE¿Ç§¯#Xo º55Ó9Ü<39>Ÿrûêý<C3AA>õ­Ð^£G/ÖW–ƒ•x«»úÛ{úyljßÜMǃäW
­Q«æž,%é ‡ÛVè)é,Ħ^V‡pàF_ˆ6üÎú†Ž¯àË\©·ºk Ø;p4µoo=l.Ü‘º#µx¼
OžYw f`Ò;ÜÑïïð7û]n› lÈC8Õ<£A—@P”^#ÖÉŒðEà8ú¼}´}ìðôÛ€¢Ð©n”‹MÅ
ÈGqj<‹çãGzqN˜ '<27>àùKq^öÍs˜Æ¡ðQ|‡{¶ãä)øFåAWNPа2@X“+–(ò åd}}<7D>`ÂÊVQmgd¸õ(‡ž\xêrU’â}ÙÚ-Pc6 E*´ñF™œ9õ{Ñ<>É+Ä/¿Äßû’±ˆ¥³úQ¿´#O¨Px°7 ÇŠ'ªÃ18äôOÀQ7^>ó‚?>õžYÔC‹]ÃÆkt\[ÆÅ<C386>½‹™Xɼ¸àÛÍS¹]ÂF ê±W)UIm>D-ÇÏðñ<r”ëʵ½K`©qƒþ@õ ÙY[A2·¼¥8X9©¿hê°LÇ>³<>p„ÝGZ#ÝM<C39D>Ÿ³ÎÀÀNO*bï¡vÆðã!rA´,œtû}lûœs®æž„™Àèøèx`NÁ Å´pL0¹'¸ vÃ…Hˆàmçkê×q¶„€9θöj<C3B6>£9Á<39>l÷÷³È´aVœµ³Aný‘í~Ç
ˆGK¦q®8Éç¹ÃÐ'ëØïÖ ÒÕ™eÂ’ô\Y&„ü6iLë5zÁ‹p+tx¸c&¾ÕrÕ!ò‰®¤ð‘´~¬‹<>p®á9üÞßõ梶tw¡§ÒSéÑ5ƒ&#Áwq¾<ƒ"Çj«Îa¬äqº[ùß°|„[ÃSƒª\£“¶ˆÝ9°^É‚<15>×( É"’°á”q.<2E>©K ÞÈ•¼ëáÀ„òºÉK¸´€Ô<06>’OqYJ‡¶žg‡­ÎÕÚ¬3µ¶†ŠªFÝ<{è >»Yý!yŸœæ<C593>â¼K¸pŠNÖ’<C396>pAm×Ôé;ä E<>Õ–“ZñÒÎ'ž‡] îÖõvÕw»z‘ÍcuƒÚtõ*<10>æ)óÁìÔLÉnHƒâ¸m6¿#€<c¡#“gìŽZ8À«w©@z“A¿wã>j>P4xj`ßE@ÇàPxôLã¦hþ C¯·»sr,ònûWM'êF¡ Bz•é]Z›J X
%ˆýM{¿n<C2BF>ÐN^ÃßÒI NâÀ`4èv§®/|R ?à|ø‹Þ¡èÔxG\utèZ*‘X¯R‚7Vw{O½Ö¹ž·6§nOÝ^ø¬…ǯ¼zNÂLÃX{Ð{fÚÁ]Ó <C393>¯ë
uÉïK꿆_»UæüÛɧ¹#Ч (JMe CùÍ•ápsKøÂêèjÞØ]&Ø/Ø/OƒÍ°Õ¿c8c8cªìLA¬±; 6ëÚçK›Ûê;¸ v5è€0štò<74>‚¼Í <20>"oQW~oå4üý)zës»˜Êèø¦/B& hI“#¦ïö]Q„S?âÜXCúÉu\ηk Òj+Ì&B©ÍAÛ(=C¯6hôº‚ìüò|8òN˜†Á–Ó‘kˆs{ÆÓãôƒ¦3vÁ>•í“ ÕEP j—¡<àrÚ¼(x9/¸4 •±\+“ï¬É'ªçÆšj¡!$°âÈ<C3A2>Oa ½ª7JÄ9‘Bb<>ÕUµ ÎÍ5Ý®`<
tU5Jr¤ù9©¿/8Å{fÚÅÅz5C7È{6<>ÕÔVÙ¤àÅ“äö]ºÕNù
ï¾õÊWœ9’CZ¹áæ–þ‹;b/óŸƒáÞU™ä«ái 8Áå“;‡öOÈâªp*›@œ¿Žùâ­åÓ9£¢‰½í©° ²$ÅÛ‘“˜ÑýÕñ±N_—»  SÓ"Gœ¹¼
e!¿È/ïæ ©ç¸œ¿zdÎ H<>MD¦ºL!Ë3Aeõ•mÕÍÚF£§¦×0 §tÛ»\<5C>ÞÉÁ±#ƒ…OˆØ5‘È7øáOz"Iþ"»€—¿»ñ3Î2ßæžÜÔµž·vË%ËÄê"<22>BzGÁT…ÛÔA éç¯3š.ˆAm¬Ñ©ä ÅHƒìe°ËÑ„^ÔUå-É
D¯~,ù<>w¦›z‡#mC0'÷-m©°WÛ´VĹ“ç¬h‚vðØë]_oÓ!<18><>¦I!ÕUW‚ÉjÚy=þÎ~>›*üóq:¾@Y¹n‡ÃÍ›Ùn²ï:xV|½øÃªËðú„4^îú°÷úÈÙé!›­Öß°„C 0YLæmû÷l,C§+az–«ÚVÆž^6µáø~›Ùf±b?Ÿà/ñ¼ë±¤)LÇÛ¿.sH¬™]ÂÝ ™åÙ9Ù9ʃ°åuH{{::{Â¥Áž Ì`¶ø<0E><>ž‚«0ñ
<óÖmx Q©T.£Zeµ‚‘,`pn‡ðÆ|`èvë%-AšÓQ/À×7çOÿñ<C3BF>Ð â<>m‘úDž¿ô2•Èc?vtOMÐÉÔY×—<>6hÖÕU‚ô„Q<E2809E>¨›ßofXÌ`TÖéšãgÁa÷ 6Uˆ•Çé—)3÷øÄÔùáë±Ïڮ‡q„>T\~&¸¾çü¶ S­Éj-hÁXk´™¦³FRz—¡®U<C2AE>/Âê8B««^,^%^v0eW–Éh6‚ ´ V°Ymµq´bø'1²HAÃo^¦ã;³+¹ZÐ-¢ŽÌ !7¬dÄ5«žÐJs> ©<>ª<>°ž„“0a ™QLÊÊå]uiŒ«Ë«·bO’¬z½«š÷:õ.õ¥d±±ôI?»÷<06><=û—ú”)S[ÊÔ"Ð6d«äÿ«p'î
wý½Lc–«=„Ÿ<E2809E>?bž‡3m§†ÿû<C3BF>oñ#€ŸCøWËîP¿äá_P…\ »©…»6¾±vMöb@ý®r7Z ÿ¦Ü!‡î°Å:èÏ;•BÍã³ñz%oŒÒfWÇè¸ï/$Ç6¯ÝmsÔyz‡¡š:MõfW%È,¥– ZeÙ`eÔ@–­*@§…
P»¯͘ €Q<>Ì<EFBFBD>2…¦FE–ŠøŸT0ÕƒT¨ÂköóH=³¬µî¶ZG<5A>¿1††1<E280A0>á ;[Á zghÁ`4éK¶X4y{rÒÖf/DÍc–kÌu|6õªº‡LîÁé‡h“çpée:î'_çæ@NEnzGf·ÉYù°V[mQ™uzP!<21>›ðù:­U<0
m6z<EFBFBD>z<EFBFBD>¡>Hä<48>ž™X{ÎÀ±ðÔ¹ñ“Á3p>ÛýÞs€Ì…ܘ¯0•ņœšŒ²’×sÅŠ
¥N PôÁi8Âõc(ð9ÃÖäð8ëb‡£<E280A1>ƒ€Øøuˆü­¢6”ŠŒ]´žûò^ÿç=SœOÈÏâq_ëÐx4ˆó±:XÖP Pa(®fS‰éÛÞ€t<E282AC>uÁðÙƒ®PëEß…–K¨Öeµƒ ÚÔõe €j<E282AC>^<5E>²¨e Õëjì¬&ÙNIq.ìiŽÁ`Ë©þkwCŽq¦å ìåe@žTºG!ÔCUüxÀ µN{cûG}CCÐ:J*C™º0û×ÊȆÇ2?ƒè÷w<C3B7>¶eËOÁI84¹Š‚Ó£˜ç ÉRoq}Êö2@%EÒ>›º‚÷Ü¡ýñ§a7TÚ.‘”–J$í¥¡P{{ˆÇÆò7i$íMúìVÜÅ¥¢8ÊŒSA¥NWÉ£¢T”¯ÅI€<49>£T”¯5×Õ5ópGYñš7nŒÜ X '<27>Oã†iñ1Î;Ø6»„»2+s
r
ʳ`/š²{ò]º@Å` â\[–¾+¼ ;™£ùCâIÕ8
‡Z‡†ü“p&*‡óQ<>WÜÛ‹8|0<1C>†èúÓÇó0—zŠ »Ä[²uße†¸­²zÑñ3ƒ§ß9±w=<3D>âΙ¹œk+׿ýÎ ¾õ‡a„ç¯a¼)nÏ…,´n;5¼¸½ñwPfþ&ƒÑî<>ÑÈ‚¾`?ï›]ÄÕxÿP›QË“YoªFÔCsmw³ùª#'áåã‡løW&FÜjQ[Jø@Zkp˜¬;8ÐiÜú%0&úÌ">T›+ ¥Åd1ZŒ Ž¯¿Ãêr¹šÐ[¸€Q[gu‚Íä68ôñí¤3ª4¢ªÒʚʚ"C p[uý§ üóë1Õr>(,åf•Em1€%>`=ÔƒÓ]ëCmø%†­[o+4§ŒsœŒÏÆ‹ †_<E280A0>Ñ"ø:^hã¶ÂI“šÀUMà68«­kU=øÀínóõt<C3B5>ûÂÞÂF&è­U¶2×Z{HY¦ÍPju•'ÑÀk‡÷míÐLm€š\uÍõZG9¿*j a3º-Mhù=Ãä³ÖÉ¡4}5¢¾žû£pOVñ^c¥E§hœ„šaÆÖ cò·‡:EƒMµ8‘†öÓñ‹˜Å-<2D>–äç¶—ôó½Ð`¯w™SJ·ïÏ “¨q<à‚úº¦æð@ß%8ƒŽ(ŽìᱩüØLß]üê Î8™@²¹±ì!o7 K¶"¸w‹Åó§øïºEöºEÿ׃ú‡—½ëeØ~ô2žbÁh]¬)Œ8ãm£¡@̪Ñ5P…ÄMª^^—ÏßÉ¿+¨± ?J꾆Ë.å‡9·Éßa;³6^¥æñ¶Á™ ]t@¹¶ÂfÿΑý#û§e'ጵõÄ: íÐŒê 5OaR—¥dæ¿<19>ë/Uöj'-§2ÎÚù-.‡ôä;
@‚(Óv¶e¼'ØÑ¨÷Ã8ôÈšÒûÅ¿g› ôþϱí}:®#·r·À.YfFf†|'l<>­þ<C2AD>wE¼ì‚dQÏÿ?çÇœ²ìÇœ’|«ˆ•û,C6z`x ãÜj®òÛKßTF5#0“ž‘@´s<tæðÆ<C3B0>|ŠÏÚš’º<E28099>Ǧ¿=ƒ÷½;Ý‘4pÿü‚´“Câ—fwp7nÈØTæSº‚Áª†"¾‰Ù µŒÂˆˆ „¥™{3õs*‰a L¨F¸-®”üøž`…D9A˜MrK
Á¹·‘î榆.Ks<4B>qÈf_]:ÐûëF^à±ÿGBEŸ
endstream
endobj
122 0 obj
<</Length 3009/Filter/FlateDecode>>
stream
xœÕ\ß<>ܶ~¿¿‚q~u“zŽCrÈ!`ˆímQ-|oIÎ_ã¾s.¤ùï ê$íJòÖ¢T¤/§½]I‡ä|œáÌðüë»ý›ëË«ý“'ç_ï÷—W?¾þáÛó‹Û÷ߟ¿üåÕþ·÷¯Ïÿüúò‡×wçéó?.ÿõæærÿæö櫯ž>vö“Š‚a½ÒJ+«U0*˜¨®Þ<C2AE>ÿG«ç·gÿ<ûIa÷ãcT„¼6F‡)Ýu¥ÕÕÏJ«Ÿ¯nΞ^(­.îίµŠêâúð\º\¼ûößi­¿Óû«Ùñð•í¯®¿Òîq~óý5t×W»ï/þzöÍÅ´eÎEà04]l*Ô'µjÞ¤£¦ÐФCËÝ´uÝß}÷÷F¼cÀ¹Ìvâ’~óâÙùË÷—7Ožœ¿xö—çJã7
ŒòÑ@ 5ù]Yþëîï]ß´¾Ë±o²Ñý§M¿úlx΋"Þw‹6¶Þ1fì<66>r Ø<01><>Ë@W'À~"ÚÍD€IçŒãcŽ~»9­ã†ï‘Íñ;Æî:hèˆñm=²ñòu¼/­Åöm³}Û¬™µqÚÃÓƒ6šÉÓ³¾î¶“̤>ÜÕËiiúÿá-;н¾Ù߆ãÿÕôÇû?šéÕu2nã”ƶð†G³9N;Ôc#Ë3׈3×EBE…Xá®abŒz9LŒœ”ÆÉÕäýo+-¶b‹-Bô®Â7FV·‘nwÿ–ñ\ŽÇ`9nG5ETÊP™!:"ߎj‹¨>C<>ŒoBW4—­ZÅ1Y;¬g@ǘb€ƒíš<C3AD>]3À²³hƒUF¯SúH:²v§ÛŸÈD§°åÍŒ<C38D>†i^YDXœØh--êPê˜O0â‚o-ÏjÌ-…hµ<>¾*Cæks k@ÖôsZEMà|êL<C3AA>z£®b“Øš¡íL¯ÍëªÑ'3õ™-Â3S\øæÆÁ`B ïì•mfìTúB q£(:°zéðceøsöXQ «#Šx×e´œµÁèØ&à]0§gf ï7öi<C3B6>:rzŒÐ8ò­éË 9K¢vë –©Ùä,‰:nŽš%âö²
Li 8×€:·82‘*öp<C3B6>5)ÜÂô<C382>ý½q¯áhk‚daΘ/vþèÌ7<X3•N‘é3¸°tN˜²ª<1B>>LB´ õ2þÔ¦Ì×F`Ð4Òœ­IÊ
¡™œE#A>Müв-drE­×À¬CF"ÑU$­‹H4=±µH,½IVqZ±F+Áƒåß3­L÷S¤Ý¨þÉO+] n5yðnÌ
û¢"r€a)‡P/çHv`Ɇ@<40>RVHÄæTDDj5e«È
ÛqК>ÑÛUbÌíe7—Õ Œi,Û€Úbй*gR¢ w<>L˜\†¢M<C2A2>.'ó¥ À¸_º_Zë–òee¶‰|©Q'›«IÈ
]:‘.És² š@­.ƒ
tÉàhÐÊ®µD—vÔJÿJt¹Ž¬/ÝIt¹’¬e…!ÉÀ `Ý
²VP/Ý0=j‹®–m’œôAk·SVÊ <09>ã5¶ò ueÔœ—ÐÑ*¨•µ—rbBÒ›£æÌ„´½¬5ùíe¨É3kÄ¥¨-Ö Åšuc‚ÙºùlÇCXxGî#WÕ ‚‡-<2D>“B]^Ì!dˆ¼X§Ëüå…üŒŽ¡Â…„iË+’Ï “9me&ã¦IÊ
_úœ/#{›Â·<C382>}[64¼À—Ú®[Qg/&@n<>}@Ÿ+û;Þ×´#pÜB›?Ÿù%“ì—1_EOõ}¸«"MÕSkH®àê¡h/D¾•‹<o žBð;€·<E282AC>z¶IYVÏ Ä¾0Ú4_[@Ëû½A0µ]³¦šA
~󿍂µØ±{êr>®ÆAû-øà(yr—/Ì‹ù £#X³xI© eN¦!‚Ñ)åª ´¦žBP;BèrŸš@+ê)„´Ý<1A>µõ:HÑ š©vIŽ늊86<38>œËÍ—ÌYRª—’L'i£w§ïౘì(‰¶4·Òêš©b¿’3Ň T!™m̉®´_Ü<5F>tÖ<74>[4/UqRrNÞœÒ ;<3B>_ŒWÕwÎ: ÓiAd%®ÍÂî#CèRÑ\J¯´«G¶Yðð52‡àäü¨Œ(x÷¨#¶<>d™ÑXðìу6Ö˜•5 ‘œkA¬:±QØo´H“k›>C9
¤C<08>|ؤg£`;R ±múTaÃ‘ÒÆPà¸Y¿
N³àÐ6õk•ð¢à1‡1`7c–í›(<28>›fÄ<66>Ë€÷ð
"Öì©(°OWùÔ†ùIP Ÿ”8D­BÖò™uN>F;ЗÞrß
u-0ìR DóïÄrÔBŽót³& &¸{†Z6ÔtꉥU<c¹à!ümgÙØ£Åy\x¸½ï ýQ¼ŠÝ‘Y-W*Î Û±>K€‹‡åtö*;/ÚÌûR¬/²§©}ZQ+!n€\HIC-˜Ta†¨ÔÉmB­”ah1
ÞŽY&JÔR \s²ñ{·Æ•\¡'›â¼YÞÊ#ÙË;¥<ò‹É­³ª¦ÞÝ<C39E>V Þ<08>Ï*4<0E>¢1ØTÓ½(êž÷à†?«Ô 1¨¤¬·©Ðnõ„*‘Ø‚ ¶òó
ž„"ðÎ/Ä;ÚbÜu#^I¡ø(2<>ÅÀMãYç5¡Ì'ùžš#‘S6X@^<5E>Ã…bŸ”ÂË4`V½ª~Ð8ð>R#ny›…ÊŸ”iÃÄ:Ñ8EHt¾º<C2BE><C2BA>Bñ"¯ƒ[«ã’ꌅ@¬½²Ò¶é*DqtpFw4Æß.»ýe_<65>Íž!ŽZôì¥Òê峿§…ƒÕ¯Ê©Ý3ï”IÞ³ÒêíÙKIB©ÖÈx¬ÝPS¥b#ç#!6ÂVbD(U®[±B„Š"$ 1l,ªÀ…Ä«ÀV _6L«M;lŶêwRnÏ*]\)*xÒŽŠ‰´µHI×/'ÖÝÃÀ¦j‰úÄš[X¢_Î3§ÿx0M¯…¼¡Ñv<>»Ü~‡~¸+K<ª¦eçÏç‰JGNùåçF{6Ot~Ê›žÅQH¨*ɸЄÏ^w'>wÜ€ÊÄ©%§¥u/0nQ®$ϙà ˆ^H­^Ì3³†Á³_‚<1B>f:ì;X³7Ifãu8tèÿ}gD¨aK<61>‰RîñÊÞ™T-Öyg:ùÏ~}ïL¨c¾«Gh‘±n UcétŠ® ¡ µfUc¨Í
°3H(»'¬”x°¥¬Ò&P\·fI•c©†«·ÿ@©p,•pùÐum¡ÊìhiA„àÝ6K‹tÎß@Û;é`µÜ.Yb‹œnLÏ {Àö¨uq->bR©f4›¤–?6îþÓÑygóSՆܸùéjó3é¦'ª=ž=4ýqÚ'úÒÁ(}1ñ¡!<21>DùN¹dÍ''Z9À°õé{çYièmö÷ÜÝÕ}r)sµ»?å¬y›êÎO»†û÷޾Ꞿÿüöø½Ý7úè-ºû•ÒÝ3o“HãýGŸúö_É®¿P`ÈZO@Î4Ÿ[¹Žq4=Èò!óH< skéÄéF)ç” x¤~iÊ$Ï~¦~&hb64›‘ý¦Ž‡n¾í?aR×nôŸÎ~,Œynåb×0oÇqïyá<79>†}È´µ¾æuH%¡Z™T ƒymS(夌õ`*°ØÄ”
A± 4@VB h´]`Þ‡ÄJдsêNÐúѨÑCæpçäøQ˜Üt´Öž§?Ýâ|pß+b•w€'‰±p^J…¥Áw˜MM©¬4Dÿ›áÊNY•G¬2RB<52>ª‹Lìˆ~±]Ú‡>Zeªu«Ê,Æ)žŠýôv¿¿}w8ûO··ûòÁØÇV ip Ä/"uî~ ¡ÉÒY/ê>,0OÖAëå‡2ЇžIÓ­µƒ90˜ C)a×Õ÷dº<64>6ˬÎÆ<16>EžŒÏ9Ž>G
endstream
endobj
123 0 obj
<</Length 314/N 3/Range[0 1 0 1 0 1]/Filter/FlateDecode>>
stream
xœ}<7D>¿KqÆ?×U–X 94%MQKS<4B>†Nø#Ô¦óüQ vÝ÷BšË¡©hˆFk ¢ÙÆú‚ !
¢­Õ †’‹¯ZPÏò~xx^Þ—”ç¼QÝжùµx"©¹^PñÒÏ cº!ÌåH0
ô’0l+ϽߣÈy7½®Ó;¯×«É¥º;QŽ?V.ø_îtFÀà3LËEÆK¶)y ðëz”80eÅIPö¤Ÿkñ‰äT‹/%[Ñp” å:8ÕÁ…ü¶¼+%¿÷dбÐŒ"ÂÿG¦·™ `d_¿{Ù¹ÙÖ–gzžçm\‡Ð8rœÏSÇiœ<69>úµ­öþfæë ´½Ô1\íÃÈCÛóU`¨ ÕS·ô¦¥]Ù ¨ŸÃ@†oÁ½ö ãâ_±
endstream
endobj
124 0 obj
<</Length 258/N 1/Range[0 1]/Filter/FlateDecode>>
stream
xœu<EFBFBD>±JÃPFOŒµUªv¬DœD@¤`]\Ú
F§ëMkŠIˆ¹‘RŸB|êê&Ø¥Žn‚ऋ¸º(¸H¹rëTųüË9ð`ù<> Õ¨a”&åʺ»ãî:Ùl
Œ3Ŭ<EFBFBD>*ÞªnÔ”h)™&C|>b™û°ä‹ÈëÞìçº<C3A7>«é»“æõAçívØýCÆ«+ ô€y')ð
̵Ò8+¤/<°ŠÀâa­RkpÂàØ´óA¾mWÓQ”Ihÿ㌠œ%–Álþ½E5VW~ªüdžµþX€ì)ôÏ´þ:׺öôŽb‘ˆ<E28098>k#<23>&¼_¤ 3÷0±÷ ØIì
endstream
endobj
125 0 obj
<</Length 47436/Type/XObject/Subtype/Image/Filter/FlateDecode/Width 3301/Height 993/ColorSpace/DeviceGray/BitsPerComponent 8>>
stream
xœìÝ=Ž+Ïšßy.!—À%prcД™F[cÑÐr ôF&-Y2èhŒ•Æ5d\ƒ@-à4Ƹ–”Òô@ƒT<>S§Èb2_"â‰xžˆïÇi ïÿ<C3AF>Y™ÁÈøÅën6ìÛ¾¿¨Xß¹‹!Esì|¸]º}î ÙŸ8xv;3¢«šŽ„ƒ)÷žñ´?<3F>¹ÛÒÐëÚæ. À6ûKîV4”ˆ90¤9çnAÀ<C383>Å9°âÄD5¬rnr—U`…Ã-wÓfŒÇÜÅXtÊÝn†)Ws [Ã®ÑØæÎÊhv¸çn2Þ.w±ÞêØqι .ðF—»± £.¹‹.0‰Œ_l?<00>È8ðwË]|€d„`Æ´!ã )ºØW <0A>N¹ 1ð !ã Ø1w1¾ ¹ÛÇ(À¸Ï]Ž€/}îæ1ŠÀkТÍÝ8F!úÜEøåž»mŒRr—eà“ÕË<>»0»ÝnŸ»aŒ‚t¹‹3°Û]s·‹+w†sß÷í£cß÷×Áâžwc“»<ì:<3A>ÉmèOm»ôtŽýÕÖFì=€ì,w»öí–#egC9‡¡äÆ@NR·ËiiðfRgg<†r<00>Ù%w›¸ãÐ{å›ß:+£9cÄÒ lÇÖjIŒ×Sð 2<>•"Ø` YqF޼[Ð΃Ιp‹ó×~ì,õ°i¼tâlLY ´ü±í€¤û9Òޱ”sŽüW°í€˜ûYb@ÃDʹ üáÀJÌV³”p><1C>ÌWˆ¡iOýuøåÜw±g •ê<E280A2>»5\$¹„ce«ˆ“àßP‡ýéú:‡çuÁw©NYšÀE/Gá‡vsê · pûóûWWrÎ+'¯˜qKPä, ¿‰ß€‚uÃBcëÂê€9V±Û1ž÷Ižš<C5BE> kÌðÕ­Y6?ÐÞzkŸ ¹[<5B>¡KöÜôoÁ¢ÁˆóaHÓ¿n§äXı²Ã'åøØ/MT{Ôç¾Z¥ Ì{2ážzñזŸ;x8m[MrciÎŽ<02>áš~B¤ú!¸I~KÌk&z²ÇáÜ÷m{ìûËT?wº†üÇíݲ<C39D>—,“!Õo‹—㦘vø¹g¼tÏMÍÃéå0‘K¶ËÕËÀ‰+º<>}¦MÊÕoÁ:8€mÚqͶVûþçÆ¡9?%mö–çžqxPûªö4ؤ{nMÍLú±ÿÚ<C3BF>”óCÚvoarFý«r9þç6Û˜jž·#åü<C3A5>¸á[’ìÇ/)Ÿj˜ûö˜Òn;sððÔ¼¥¹F3R·|‹#â´ŸšHšÚüëðP<>ÃãB›ûš<C3BB>¡Ï<C2A1>M/vx’¾í[„ ˆÓvýuxšGyúûf¬²mõÔ»ð¥¹oŸ}öÔåMÛëQú¶oͧ9öÏéæÑýrÜøqOé]~h^ǃ\ÖÎôyJ9œ
ú }Û·ÖˆÓt—·ùæËxÞ4žspšrÖ:=´¢®ëÿÙcʹ³ùÀ· <0C>ß*wTkמݹédÑÅÔ”!`¥ýè¹SÚcÊ9 ^ 59Z¿Fœ-idÃé¢Ï[*CÈØ~âøÜÜlTÕÿÒ¶íìú&¬ý‘£õkÖØ{Ýãvã±<C3A3>«vÓÐ?_<><5F>°}÷诖`ÓõÃD+ò~==OüyØIzÈrñ*%iî–aÜ0Äò`ÙþU] óÕ9›ÛtýŠƒß¯í›^oÎ)ü"ÚÌ-ʦÅ24ý(4ï¯FÈغ°æ¾[rœšÉ å|‘lå–dð›âxôjY91îèô"ä¬r›‹™ 9O»<48ÊùM°‘[<5B>ûÖl~Ùo\Œã1cÍéEÈX£<58>Š™9<>ÿåÃ@Ð%Ë <>\×Õ¾ß@¶÷Ùº¡£€%<25><>°Æer$f!ä¸ãäPgåü"ÖÄ-Çê#g<>ž°î8'Å›HrVh¦×Ô|‡œ{úØGút¾/åø<C3A5>wRž4í]ÿ™<C2BF>ÍÚÃ?ß[uœÓRÄψ<C38F>°Â›ˆòÝÌûžUÔ>¬Þqß»b5ß;]±õÀ/©Z¼F<C2BC>žaøèµ§Úí¶ä¯ !`…ï¾ñq·rvÍCÊé&'¼1_íS²&¯Iç&ù†Vñÿä´"ä¬0No0rv{7õÿ~Øq×o¿¬â$kòÖ³môîcgíPNø´8)„€e‡7e:ä<4þÿßW<”/Y“לѳ‘igíPŽÞ<C5BD>9ËNßͧfEÈé'ãÌw”E9ŸÒµyëØSm×ÅÆy^NfpçBÀ²ïõ4·Ý¦<C39D>ÓO÷{§ºnÝÒµyM¹{žaSµGçMœÊr– oNò|r.““ÛÚM½äH׿µÄïôÏH›ª=¸[~‚„€eã›&èÒÆO[±=ìGàÙW_˜tmÞò7hÎÑ/eÅ•DÎUñr–½‹'K[HŸÞ|
Ç<EFBFBD>~HÖä-~Ã<>Ýáé ÚdCJ<43>GB©BÈX´ßrš‡Õß×ç<C397>¹OI*Kº6¯Ã>|cŒˆW³ü½ÿè”"ä,z»šæû¸´ºþú0ƒçÚ¼[ÙCÈù<C388>¬ÉkÃè;¾×ÄÛ8úÉò7?p« !`KÈyû?¼zI2„œg¢Í\s~FâÕZ©•1Ë+Ç9u…œËëÔ#BÎ3ᆮ)ãÓ!³[Äßq`}RP{P!@ äL®® ä<oêV0Œ³\û¿|R! è59köÉ"ä<“né–¿'úá8w ä½»ÚšÎyBÎ3Ùvn›ª NUûð/‹ßOÈ0Ì'äüÜ@úñShƒ}<7D>låVp6Îã<C38E>L2ì>B~`ËÜ›1˜‡-¤ûç§fçÏñš-ûVÕ M{W¹›÷0ŽØ®j,/rJr– oc·/±eýni<6E>Í»aŸCÂk×+Y“W1ÿ‰‹"€>[ÎâN)BÀnÃy ·…<C2B7>³ÛuïZ°­Òd®Z²&¯Zwï´Û<„i1„€’õßͧÅ<C2A7>³ûn~ÞW%¥j¹Ú]|7ŽÞ¤—ã|"ä”ìa¦Ùq1ä¾ÿã§ŽúûŸÿ÷%Ý•kæêæþ§ìÎÑßþ— ÛêBÈXÁM”É<E2809D>ó<EFBFBD>fç«=dïcQÊâªæ¿qôãÀ¢¨Å0ÎÒeì<0.‡œËäqŠgšø7o‹âjæ¿ã@’å8Ÿ9E{Ø4à¸rºÉDô=¾Ã’œ_\½îþ›ˆ§YŽó‰<C3B3>P´ýôŸÓ!g?µ(ç¡=ø¼ u½\µ®<C2B5>öå8ëBοqJr¶ÍW{œl6rmº…¨š«U@<Áé8nr¶å¤ï‰™ÊrÖè&û·ß„œËëû0<C3BB>Ãlµß\<5C>üÇI<C387>*Gr9<>ósÐÚéDtŸÈaoµß\•¦ª5é–㬠9ÿè”"älݶwX
9û—©iG7½=[Õ\<5C>šß‡ïi<C3AF>JBÎ?;¥9«4ãDêMÈÙÝ~ü§Í=ÆÞÁ¥qõ ™ª–rË<72>•!çïN)BÀ桜ñ°rN?à<¬]ýg+•ÆU'`ªZÚ-~ù³O<C2B3><4F>°ÎãhÌ­™9Ã>íó®¬ÈùæjÒôαÆé0ŸÆiEÈXéa]Í×a9MûåGýþÏÿ°ßíóŒØZ훫Ëèè®yظ"<22>ÖêY „€Õ®[–+|{Ì8;³ÁUåkôÏÇ>ñ¶j+CÎã¥.„Ÿ½Ö§œ§ŒÃ®\MÎ7ê©%tX¿LMBÀj­Ç"ò§êâòUqõC–bu™2Ž[º°ÿà´"ä¬÷Ôu}û}Îú=ì¬öÄU#dç茓–®ìoK<1F>e%ÑB€ïWãbSªyþïY<C3AF>óÄÕbhŒm«öË~€¶½þýÅ7 >Ï}ÓÃ~Ëñ<C38B>ìýÌU"d9NÆŒ³¸àañ²m¿FÈØ¢ù±ÏÕå}ÌiLÖ!ãü઴çgqKê¯öTŸtÉöˆ 9›4<E280BA>I¸'ÿ³îgó”Œó“«AÐrœL[G¯Ü
pqsµn÷/.B@è¢ñr|^t±ï.cÄ“ Kå*´'×ÖÑ+“Ââ¶ûÝ_\„€­¦–S߇¾?¶m{ìûáþú?ߨsà•+߆3cÕeœÅ³@ÿï…ßíÎ.BÀf‡‰3kå™:•qÅ š¢˜oëèß‚ù~éß_¦ûR(5äÚÇþÑexçüç¿ùýwæ5Ó÷àÑuˆéûsOŸß»æø¨ÒþwMËתfSõ8¹j®paS³gz<>Ý<EFBFBD>ãs:™l¶ÿjEŸŸZ×[ûSV»ÿn»4ÚwfŽýEîžl3 ×<>áû$¯ñ®Ï Y’‹}á‹zßWgýÃÌt<C38C>úšÃMê[ÐjîOútzºÞ§7ÕšõÃ_ÿí廿ˆ9Njµë_´}¿^\Ù¦(.®ê÷Ÿ®p1è7»]ãò0ršöø‘j\v>G<>/Ù/MÛ_³îÃñÞíÚw·.K v‰¤Þ2%[çKFë h¦ Ô·3Sòwðb¹µÿìfûOÞ‹ô+÷œøQ¦[·bbÐÜpÈË-hË<68>œÇã|¹.\âmÍ1;.!gÿ1&á´¹_û£¾©X‡ÓEÉèÍŒÛå$W×EÿŒb_7!Ç`ȹï”iÆ:BNÓvýuȼø<>ûpé™ ¬EÓ-¿x‰83\É‚¶Ð<>q–jÜfÕ¨uYè9‡î¬/Þ<¯½ž.µÃéªåý»Âpþ±Óf$yÊ˘¨±ûº 9CŽº¡œô“)’‡œötV“nžŒƒÆÎ¶gû¶}3‹xÅ"ÏU<C38F>vs+l?çú¥¸EÇëìƒ:kLy¹‚UØ<55>Š&ð1°<31>p̘ÖÔ†œæØ«x¸Ënçüo™æh`çÅ­<C385>?Ï<S¡I4a-öer,†eC9‹ëØ9íé¢töïã r•ÒîÐêYêÆ<C3AA>™~'Ñ¥MM÷¦Ÿñ~a»<61>®Xa[M4:*ŸC`?׺ÿª¢<C2AA>ÓÏ:žìjw¡q‰u·«›íBRmŒ]ûçJÆi~H±¯š<C2AF>c1ä(ʹrš£î™On9ßA/Ú“Â9æ¿Ü‡^p¾ôáÇ>ç.{'¨®T÷CgisµÛª%=™ZúBÎᤵr\0œrìc9áHäœ\…'Í„µØWMÈ1rî•ä$ 9­µž6¡±ñÍö<C38D>…;w¿JŽ~}m²§àqá
uk’”g¦J³.gÒ\ìô—«Ñž•<T?÷sâJm~°ã%Ú}Ë–<C38B>“LXK~Ñ„œ„OCâå]
9ûwóŽô/9tšÎÔ¼i]£_Use
;ùõ ¥úÜ7à½ãÒ¿ÿÝì\í!§½hy¤îéMÙ÷–Þ' n]œ·M¾aÀ?¥Ø×Lȱr’íY¾,K  9û“<C3BB><E2809C>ˆY×H•éF‡Þâ<C39E>S1úW¤°mÕÔdœ¥ Òç•Sþæª9{Ûc8<63>†$SæÛ2qbo?“/䤘°ûš 96CŽ¢¡œ¡¬<C2A1>c?á|/©KˆÉ­o¤V†b3W¢®<C2A2>Œ³´ïÀ}å@еâ<C2B5>ÓtE¼YþÅO%_±+¿A—ðœ0ݽžü’ 9 Ÿ†Å¡œ<D*ä˜_àøà~J7œc9'3Wž1,ãõü¦þkà²Ì¯ßV_mÈÙŸõ<M1§Ìˆ%æäܵBþÇûŠ 9FCŽš¡œ¡œ<C2A1>SÜ{hŒÐiTÑ´iN²ÉÉg ›Ù9=Ú §…>æý›ò‡œâ¦]ý6ŠM©(7â||1ç 9òÖb_1!ÇjÈQ2”“éM,P·<1E>nê9O>æt%Ý·43Í1Á•æ^NÆYªo¯«6<C2AB>ÎÖœÈrÊ|µürém-;â|8‡ ‚ E·<“_0!'áÓØDG¯ó½<C3B3><C2BD>Sl­*××ö¡)d'åLsLr… Û:ZWÆYx'.n ýÝuàê 9žZ~‹ÿ‚i …Qæ²æ½?Ò?§Ø×KÈ1rÂö퉤+¢bmúÂæ©=¹‰m¶Ï±{¸¼4“üðÌ•e()ã¸&léïþwWYÈiËÚm þ.é/š2ß*¯†ƒÍ<C692>#=a-öõr̆C9÷BNÙçƒÌ¬B#ÎbNz®(<28>]PÊ2Îmþj/ë[qU…œ} cnŒ¹gKWúÛ8B3&s©ž°–ür 9 Ÿ†¹¡œ<›åÄ 9¥Ï&ž\]ĺc˜åJX7/;£ì(Ðq}È8×ršlïGed½:Raè,‹Ü7Iöûj 9vCNþ¡œf4r*˜M ±<´ðˆ#¾– /\A‡NÕý¸Ža³Õöë÷a+)ä´tŸEZ<45>Vã0N@ÙÌrd'¬Å¾ZBŽá<C5BD>“}('_GU¤h£­ËTütì„7\9JË8 Kr.&»µÕ„œŠÞ-öKÿuË
Ýh;úЦÜ!GvÂZò‹%ä$|<1B>M­9‘šìŠNÛ³´<´šÊkö±ÒЏR„®PЗqnÑf«-oÄVJÈ9ÔRIÆK9ÕÝ2ï­æ³‡ÑŸTìk%ä92GbšxÇøË«ÙÅ%šºÛÆÜ'lTÄ"´±w±¶âbËlµ<<3C>9ï8Ë´<Û˜õMUóÞL:È‘œ°ûZ 9–CNÞ¡œ½3rêë7
<<3C>°Âѯà<C2AF>€±š+C<>gaIΖÙj»Ý_]!§¦Ž X)§®Ù}aÍ™ü!GrÂZòK%ä$|¶†r.¦ÿð»ÚÂgÔ÷öŽº=*ÞsE¸íËË8nþ’ÇMuõ¥‚<C2A5>s¨c7›W‡Â
¾ÖåÕ
BŽà<EFBFBD>*ö•rL‡œœC99r‚CN}<7D>õ()§­k'òö¨˜ãJ:%TeSo›­vȾYMâ<4D>Se-ö~ij<69>…~+f5„¹ k±¯”<C2AF>c:ää<Ëy0rªíj»5ª9öAd1f¹™q^2KÝE÷ü Š´oIe¹Zèu­>ãl¬:4„¹ kÉ/”<>“ðil÷ã ’PÞ‚rÕvµ…4Ã*ýŠ´=*8û†"3Îü$¤fcÂ8¤¹æ¹K<C2B9>UsÆY܈ogã›YEÈûYžNBŽí<C5BD>º£‰¿ÁnÈ©ú5tõ½kûŠßDÛ÷¿ÁVμÐsË”fœ{XeúsV‹+;ä(}ˆšdœ­)GGÈ‘š°û: 9ÆCN®¡œÌå"$äT<C3A4>q¼—˜T<úõ<C3BA>”#ÍYWhÆYø»n[»öÿæJ9Z¢âš’Œ³yþ—Ž<E28094>#5a-ùer> C­¯»Ù<C2BB>SyÆYÚö<>zÓFjÂb<C382>3®ÔŒ3__ì7ŒkÉ!GíCTÜ¿¯¤Ån©
ÑrËd~X±¯’<C2AF>c=ääÊÉ<C38A>z³Wns”™»FÊæl+6㸰ÓMö
v/Ir*Ý™%¨_oÁ×;ËBKÈ‘™°û* 9ÖCNž¡œ»Õ<C2BB>CkÝg”™»FÊ‘æL ÝÓþbt߸y!zWnÈ¡šÜ~»k<¯.¸17˜_á;'öEṙÁ£gõÖL¾m
^C>/}îÚ'RŽ$gYWlÆ™ÿÓºíUM[lÈY<1¨[ú÷+l_Î:Ø
9~sßľFBŽù<C5BD>³ázciF£!‡ÖºÏ(sŽ]_UâXPAΰ‚3Îë|³M­­‰£\¡!§ò­Y¼ú÷ó·$L4¤'äHGû 9öCNú¡œüS<C3BC>ýB¯!Ÿ"Ã]ûƒ=Öä8»JÎ8· m¦š»wE†œ&÷n‹M(=­uS¯fE·M`ÂZìK$äØ9ɇrt¿ôF¯Ûà(3wMxtŸ\µGõøò)hÛ<68>©[óWdÈQÔð4³Röiï
õÆÊZüWbì+$är†êrüBûñ{ìÉÇ)<06>Æus¦±<C2A6>³ªèŒ3;[m±ÿcôJF&CŽ‚—¢¹ßÄžþ³ [!'þ„µØWHÈ) ä¬\­Ëâ¥!'ýËU±¾„©4Üæ ãƒ3ªìŒs ºô‹Žîû!§ÂvRx'š¦¶º‘ŸœÂ}ÂZì $ä”rÒnût±rØûƧÿEw¬’Í «àl*;ãÌïµqóz•¶†äxü,x#û6nT…œèÖb_!§„<C2A7>3¿N<>9!‡¡qŸ;È]‹~"
¦9“
Ï8³“Z¿þüÆ•r˜%°}(‡`è=3GWȉ=a-öõrŠ9)‡r®ÎdKSW½`¥fbAކ-Û«à,*=ã܃†ôßÔÒ®¸<C2AE>Sa+)ü—Á*&ïV¹²ÆLä k±/<2F><>SDÈI8”££@l9ìãâs yM`YŽWaÆÑQ™zÎVÛû¾•þêJ 9ŒIl_Y®<C382>þõв<C5A0>yÂZì«#ä”rÒ å &C5êº<C3AA><C2BA>ž1Ymg‚Jpõeý'PB¦h ZuJ‡ú‚<šQÜ4ÿi:aRÖb_!§Œ<C2A7>“l(GIyè n–`¯‰¦­.Õ‚ kœ9ågœ{P¿Q§¥y+rèAóèw妴oÔ½˜£NX‹~uFµ)™ 9©–C&ÿÜ
Kq„ ܵ7˜°&ÀYS~Æ™³ì½»wÛÂB=h½û äÜ<%­0¡ kÑ/né +lè˜ 9ñ<39>dR½PvcÈÑW)XØÄ…™æï°ÃZ|Θ
2Îìü€»wWþÁrTl7ªÐ|»——KÀ”h}환íÏè·ô…„œ”OC}»ënò¯ÕÍl­-á®éس½®®ŒcaÝ[Píð¾ÅrÈñ˜¯ÆËeAc+äÄœ°ýÚ–¾<E28093><C2BE>“òihÊQS5m 9Ú
Ï2à®%<å®®ŒcasöSHí0S»üÍrÈñy½¨8ˆB³ÞXȉ8a-ú¥-}!!'åÓP>”£§÷±7Í´™<1D>à®Íaï<61>Øœ%Udœ¹úá’,®%…—x’aP§µÆ<C2B5>¯—=ú¥-}!!'åÓÞ¸œú|SÈ1Ñ P×TShUZÜ–9CêÈ8CP3«Ñó 9–VéëÛçØº B;=»!ú•-}!!'åÓÈúæ]¤h×Ç-!§Â"aÖ4wmC9‘9;º:–qt!µÃEÑ ±dÈaÀÛgͧ‰<C2A7>¯w¶ŸÊ<C5B8>mÂZô [úÂ
Û:VC΋’r6…-
m ‹™4=<3D>¡œÈœÁ'/©‘š<E28098>VV«¨Q!rt¶7•W‘ÌV Ë : ]¬ kÑ/lé 9)Ÿ†ê¡E9[BN“ûZ{_+ñZÂPN\ΊZ2Î%¤U0ßãæŠ 9Ô“3ÞÞ5†¿Â¦é 9±&¬E¿®¥/$ä¤|ª‡r4½›7„¦ÿúuîÚ†rârµdœS =Éó¹âïIþ€•SÅÃÌâí&âLë‚Tr"MX‹~YK_HÈIù44å¨ê³Úr˜þës¹k‹8+'*WIƱҋ=5
æg®üÅ•r¨'}Ú#Šæ„(v2râLX‹~YK_HÈIù4×X5<>³!ä¨ÊffÆ—¹k š»xäL¨&ãÌ-BoÓÙr¨'}ŠÐ!Ù Ã0ôŸÚß¶uM5_ÿìøëS>>ïž¿9§5äÄ™°ýª–¾<E28093><C2BE>“òi(^'<27>®bŠr¿Om¹+š…1_úõ®_ÿæ^èñ»õpÜʪF½æ­i¼ÿÇ9ª¹<>Ãl5Ÿ½IîÚý|”ª ›¶O3öæBN” kÑ/jé 9)Ÿ†âuƒÑ<C692>Ãq/sš¬O{8÷ÇÍ<C387>k³~wº]oEìÙ^gÀ-´Ùt03Qg&Î ÁY°-%ä0[ÍgÆc‚I!—…˜¬9Ýó•[]<5D>±Ø=Ñ/jé 9)Ÿ†Þ¡eå /¯çTUyIðձ޶Íñb{vhuœ~eœ™`ІÇÿ¦<C3BF><C2A6>ÃlµyM¦hxI²^ò4æšü¥7äʰýšŒ5nS°rĆr£!GÑÙ><1A>2ýêÇ^~®WÓK¿„Øz "W~Æinulí´Ü<C2B4>ëÊ9ÌVójJ ë<7F>ª^n®EO´È5a-ú%-}!!'åÓP;”stFCŽ¡f…¢¥¡ÒÑ0AÄù°¿Ú=d°:N»ñPQƹ†´fö,øí¯.%±ßi¾­<C2BE>¿W0úºe»ñ²ã_cÊZù8f šCNø„µè—´ô…„œ”OCÍyLÚW¶¬ 9Ì'ðù“­DoÒó¥S½„˜¯‘+=ã˜êp9†ü{e[uŠ5{\ûí|j¥êË}{ºÜÓ¿¦ÛB^.Ÿ·PôG}6r› Ñ¯hé 9)ŸF"Cµêö=íu]ømÓ–`ö»åÙ^MËGáÑ÷óÕâq¥gU{ð{Ÿ+ÝEiåôE„éÆÑ(»nQ~¸{H>ÉoH½åesÉЋ¦:äOX‹~AŠCÎmHâú³i¹¾åâj9½CÛ@Îꆲü|‚Ûù(ÚÔ=tWÉшäã_£à6çÉ÷g¾Z<N·cMg¦~]ñ*Xñ OÛ¬<C39B>ú™ÊFµ{¢I½‚‹‡Ô·-ÇÙe’/“!'tÂZô J\ îqœ<71>Óh_Ãúʵ!Gxéùý”¢/–û3‰W`ÝÓÎ&ÍšZ%§ZWÜ`ø¬}ÀŸñ~(צ—R!g0¾5‹ü
úÄq?ÏùÌ‚?íÖbÈ }-F¿ž¥/$äÌpÅÿ¡7£Õ<C2A3>#»$çãä«Ì»U¶i»Ú‚7¨òÑ楧 M©œf•eœ!äU°ê^¹BŽà{ñšx&¬P•Ÿ¶‰ž'ãHþ¸O&CNà°wôËYúBBÎ §RôêQá6Ì}þ¦ÅØ•°Àñ”´«-KÆ‘<ž$õÜ»‚9Å‚[OÆŽëê^ë&«üÍÙ9û’æÁžÒµE†Â2Ž`;ãb3ä܃ÞóÑ/gé 93œJËxšÈYr§Ë^S·×/énäPVÆL9I7Q(›+9ã(¬B=Nª_õ*èõm¾,Ú‚æô
½_Ú„¯—œs‡»’v?ÍÝ<06>~5K_HÈ™áT
ߨ<ÝÂ:áÆ¥\e<>tGð<47>™¬<E284A2>nûwT¶2˪ϲrj]Kì&òj¢\¢M$è 9§¢ú‚š»í<C2BB>“­M´‘d4äMqˆ~1K_HÈ™átŠÛ½¼7ü'ÞKêjy Mþ µn«/å¼íóÆVN«àÖ“¥C@gsÊ>Þ¨WW@È
j—L­õ6Õ<EFBFBD>i¢<69>™·óšâÝ 9!šÑ/fé 93\ C9Ã!GèÛ3uµ¶CNÞõ+B­*NʉÅ)þc×ß$Yù’âýÊ“î!m*ää[Y2Xž <0A>n ¤=­Õ%`ÂZôkYúBBÎ WÁPÎÞð_ظ²Æ/‰Ž+rùŠL“$÷»µN§º<01><>ŠÛÆ|Á;û!g(lÖÕÑpȉ½YËÞ"fCN@ŸfôKYúBBÎ WÁPNÒ¢‘[Ì2Ý…ù^C<12>sê{¾FÁ/(1º•ÚqîMéyÎÍ=fèÿ»KÇPȉ½ v“»Ù<C2BB>“q¹§ìýd6äø?’è—²ô…„œN«xËâÓMm!ää¬O*·©¯)pÊôGD”X–Ãq ±8•Žu<1D>3W·®Yg¿æ Ð_þâÒ1rŽe­ž¿&ºoözuOöc´rü×¢_ÉÒrf8­Ö¿k–(ý9e 99—Ï ´˜¦¾¦ˆƒÒì†TV…–“Ó¨+´“hÎ>`‹¸Nåž<C3A5>vBNÞêä˜æï·w´õgȇœ»º kÑ/dé 93œZ±z6´¾£ó…œ¬ó“M}<7D>+ô-$PŸ³½Z,N¡seäÌ<C3A4>Mžãþ¤ö_¶rònÎÒZ 9*rDÞ/ò!g›Oë;ç%ú…,}!!g†S+V£Rëæ§ÙBNÖ9Ó»]ü6S“$JuÅvµåþ›Šáô¹Ôv@ÎL;û¹(e÷™™<E284A2>3–¶v>QÈQ°"G(¸'9r<39><Ï>¢è×±ô…„œN¯8­Jµʳ…œÌ»¸ )Ú4·­)¶«-÷ŸT §Îä΃E<1F>3Ó=6DîÚùÒvÈɽÂ/ú4ÙÞ»©û¡êÝ(EÈ‘ÙÎ`2úe,}!!g†+}(Gn¾¦Õ<C2A6>“yË`£!'÷ËûK_Ú“‚8mÂwQÔ¹3¥W è¢÷¹tÌ„œÜ{5=†-ÿþÑ¿ÝL†œ<E280A0>² kÑ/cé 93œbÇ’rV¾ ®?ó&ag›!'÷Ë[°«<C2B0><C2AB>‰S&|?@s伌iVuwmºcuɘ 9¹gõ 9vµùÔÛ 9Ê&¬%ß+Š<>3Ã)áN+žQÞgªsr/ ïm†5Ià^îŸf<C5B8>+퀽]DÛ—!õñ—0%Œ€B<E282AC>àò*£!'÷mKÞ=;äèš°–ü"93œfá¿|ÅÇØå
9¹Ë¯Ñ<EFBFBD>“ÿ<EFBFBD>±–•š¬uN—Náùñ LÿR¿òÞ|ÈqÅU&Ñÿ ÊBNc4äèš°ý"9œfCÁ9„[!g§EWî Ö:§Ê©ÂÍ£ß×oƒÀ^t ·W#ä”r”lk#±ûi¢<69>£jÂZôk äpªµåäd 9Á›Ê"ä„)x&žuN“*7<>~»’³“ø%ÈM‘±rr·Ö<C2B7>†œ<E280A0>ƒÕ<C692>£iÂZòK äÌpªÞë½æ×t®<74>“{½Í<C2BD>£e‹O‰ù„œHœ"UnývÉáºÀ¶ùuã’1rv™E/µ„#!GÓ„µè—@È àtÛ—»7!'–C‚<43>£èWûO#ä¨}297<39>V]ynMg™Âß\*„œ\môɳ
;BUt÷Ód!GÑ„µèW@È àt»(Ûm7"BN,»ºBNô‘9‘¸‚6VÓ<ÓwóþÑ­Ðo<Ý)B„U¿^z»!GnáÖWdò äÌpåèî‹$äÄRYȉþ'äDâÔh«Ü<úm¯ØM覥K‚„œ•9õ†œÝÉ)™°ý9\¹C9±ºcްQÞ‘Ô6CNî»ö€<C3B6>£•+fóè„KêtŠõR/öÎxȘë°ËŒ<C38B>¨MÓ„ 9Í%¿ kÖCÎ8håójsååD.ðcäɪµ†œø ƒÊBNôIÓ„œH\)«©Þ±eóŠ•<E280A2>ÇÏ 5r®—Ù9I«*ö]+9ä CŽ\ŵ­vHþõ w³Ï˧!÷
®Š^ر{y¢Ö<C2A2>“dwç’CNô¡0BN$®”ãÅln¬ö®(rwÍ¥BÈQ%I8ÏÃtÈÑ2a-ú×rÔ„œö®gãýØ9 !'Š}ß÷]ÑÔkB΄œH\!«¥[OŸbÿèNðWðw—!G•‚_/¶CŽ’ kÑ¿<C391><C2BF>£'äLRöüý#_F»qYkÈI¢ä<C2A2>½³Š<C2B3>‰+ccµèó!“éüÏ4õþú«K„<4B>£JÁ¯—<C2AF>í<EFBFBD>£cÂZò/'ä${müýmßl
º(ò…Ü£÷ rµ<07>’ÿ6ÛœÇZ7V{3<>s•üüŸ.BŽ*%¿”m‡Ö¢9!GQȉ=€â[Ä~Sw„KJ%ÿm¶9‚[Ãr‡Mˆ›ªÚV¾<56>ürØxàÅ®
%¿”<C2BF>‡Ö¢7!GQÈ(b^C9ñrò„œøK€5Õ§bJ%ÿm¶¹6V[9»K£©ÅÚ?Çï7 ÖžzAÈQ¥ä—²õ<C2B2>£aÂZò¯&ä${­ÈÝîó/Îîr…œ¸ß¹þ{<7B>+9”ü·Ùæìo:`wcµé€w–ÈI8±O&äLíÙU¡ä—²õ<C2B2>£aÂZô¯&äh
9½[“S­“vG~^!ÇŽ’ƒ@É›m.·ÑÿT±ß.ή½ÿoÅë'Ðì%š6äÄ?˜™<CB9C>“çô^Å[ò<>£`ÂZôo&ä¨
9·»Ó0<C393>CÈ1äXp ähår ÞXM¬4<>« ´D„·9ª”\Û 9.Ù”ÛµÏ)ùr’=<3D>V¦3ð®a ‡<>cHÉgÉìm4 *ä2 îØ6&<26>Ö3l¯_·ÜÜÿ „Mš‚_/Ñ—§9rõØÚ kÑ¿˜<C2BF>£+ä쳿½Ï"_Oȱ#úÛ{§Hì¿­ŠañÁ¤ÞtÀðÆj“m©µoþAÿ‘©„MŠLì‡¹ßæÊ kÑ¿—<C2BF>£+ädÊÙË|;!ÇBÎU”‹f›Û®âM¦:ÂV¯™ñZÉ”¶YAÈÑ„<C391>£<äÈMX[7#8ú×r”…œÜC9™/'äØAÈÙ ŠañÁ$Þt éÐD‚~°³èXÚDHÈÑ„<C391>£<äÈMX[וýk 9ÊBNôébÛ&ì…¾;Gȉ>ù·’&-!gƒ*J„Å“¶<E2809C>”r}Šn°Õ휽òí£?r4!äh9r=6«Þ–Ñ¿•<C2BF>£-ä ¶ù~¤mÆ<6D>£ãÔ!{9TQ",>˜¤­àÄ­öÈÆ—¿gõKèbáÌT™<54>#°aø®„õ!'è_JÈÑrzˆÖå´RßLȱƒ<C2B1>³A%ÂâƒÙ îM¦ÊðUtš_üÉ
9BŽÀ<EFBFBD>"»rÔ‡œ¼Ö¢)!G]ÈÉ9”#5<>CÈ1„<31>³A%ÂâƒYï¶ú,n[
ï6ŽWéXv:<3A><>£ !GÈÉ:a-úwrÔ…œŒC9b9„C9TQ",>˜ÕÆàS@Å Oãeg×ÕÝl¯ñHåí"ähýµüû<C3BC>¨”<C2A8>“sÂZô¯$äè 9»øƒ+;;îb_Kȱƒ<C2B1>³A%ÂâƒYíX÷¦{ ¢…?ý¡©„M¢¿–wŠ”rrNX‹þ•„…!§Ë4뼓û…rì älPE‰°ø`"ŸP§©Ñ.ün8ÉœÀ–on!GBŽ…<C5BD>#±¯ÆÊ7fôo$ä( 9C9û¼9„C9TQ",>˜T§€ßtàõÕ°þÚt[Æq/BŽ&„œ <C593>£KòΈ¥ kÑ¿<C391><C2BF>£1ääÊÈ!äÒg<§I\ä¿­ŽañÁH®*yФ=×ÒÉ¿n¢¿ë}†LHÈÑ„<C391>üÇ¥9rMÿ¥~¥è_HÈÑrN„^ʉ¾Ö¬Ír¯¨¢IKÈÙ ŠañÁ$Ú™Il¢\wà,{ïrÜ/BŽ&„!Gn§÷…wfôï#ä¨ 9m†¡ѶmŽ<6D>#01¢Š&-!gƒ*J„Å“æéYßtàåÇÙÊþ¬³´'dBŽÀt¯S‡¬!ä 9¹&¬Eÿ:BŽÊ<C5BD>#ÐM´O=<3D>óô…„;9TQ",>˜$%Óþë±õ~ xµÈïå„<1C> Õtâ‹BŽ‘<C5BD>“kÂZô¯#äè 9mò?°:"äØAÈÙ ŠañÁ¤X<C2A4>“c<E2809C>‰ìoó*»+]ž<>/BŽ&„+!'Ó„µä¿BN²§ÑÊþZÞèÑ<C3A8>¡~îè#äØAÈÙ ŠañÁ¤hSZßtàå<C3A0> “l@Ì
9šrÌ„œ<Ö\êw4!'ÙÓheCÇÂ_x‘]Dȱƒ<C2B1>³A%ÂâƒIðèÄŽ’Hæî½voh—BŽ&„3!'Ï„µè_FÈQrâ¿AgûÞ„r9†r6¨¢DX|0òÅR`÷ÆÔ:ß‘)¯s@s5&9šr서,ÖR~×'BÎ Ñ.íPŽð@!ÇBÎU”‹F|AŽùS@_¢ÊÙ{šÛ*r“_r4!ä
99&¬Eÿ*BŽÖ<C5BD>#0”“ð1ÿÜz‡<7A>cGìÞBÒ?ée¶&»Ø@ÎQø'<27>m»mBŽ&„C!'Ç„µè_EÈQrâ¯Òü19Að·ùr*!ÇŽØ…¡è<C2A1>sÍý•Â¥üK6
èÏ<EFBFBD>œ-ï›ùƒ.¦ÅŸš°!G“ Yz<59><7A>"Å…œ ÖÒ}Óo„œÂ5\ôFú=Û@!ÇBŽÕ?βØFø±­ß‡L¯Î÷gïµ}tü£ßÖ"ähýµ¼S¤¼<C2A4>#·…仞’è_DÈÑršdC9â9YBŽ@_+!Çzp%ÿq–9S rJx/>ß„^øîEïÀ_<C380><5F>£ !ÇVÈ9¸ÄÖ¢!GoÈI6”}› ½Š<C2BD>#ÐuHȱž\Éœe.%Ÿuó²ýOô¾/ú“±;FÈÑ„<C391>c+äÈ­¥{ÓšJõ=rfH×p©†rîò÷’<C3B7>c!Çêg™KÈkº•Ž©Wñ<<3C>ÇlyÕÌ<C395>q‘~jÿ
„M9ÆBNê kÑ¿†<C2BF>£8äÄb™ʉý-S³9vr¬þq–¹t¼Zé*ö «Ëᦸ؜—l!G¢eDÈñ±S¤È<C2A4>“xÂZô¯!äh9ÑÇX¦¾$ú^¨S·’<C2B7>c!Çêg™KfôÙ¬¸—âSWT/½Ÿ Xgð„M9ÖBNâ ki¾¥´úÜnÈé´Éb—àÉe©„;9Vÿ8Ë\2ïwÒ_'þÞþ9ôžoùñuÁ¥ö½è9šrÌ…œ´Ö¢ !GuÈI0”}áÏä<C38F>,$äTѤ%äXýã,s©Ÿl”uTB¢+jÓ+ · 9%‡U5p¡!'鄵è_BÈÑr¢ßÿ!Ë@!ÇBŽÕ?Î2—È=t÷èœKèejÐ[Œ³ÖœJÈÑ„<C391>³…ü·¬ú»RNXKñO93RÔpÑ5mŽ<6D>BŽ!„«œe.‘ІdÆó^„º¢ÎÒ·/÷-#ähBÈÙBþ[Öýa '¬Eÿ
BŽò<EFBFBD>Ó
ÏÖ¸Dþø7ÅEþ39‚9Vÿ8Ëœ<C38B>Ý£ËX<C38B>óX<C3B3>¥çúEßÙf+BŽ&„œ-JBN kÑ¿‚<C2BF>£<äÄÿÙ<-Ý'º<>„;9Vÿ8Ëœ<C38B>Ý£‹X<E280B9>óØuû°”Ïï#ähBÈ .BŽÜÞ!/m9ùoø<6F><C3B8>3#I ý \2 är !äXýã,s&v<>.ℜÇú³¹IÇ…¬Gäx_õ"BŽ'BŽÉ<C5BD>#wòÏ:9úr´‡œè9äq(ç<>ê6rì äXýã,sš»…¼º¢.âã`ùǾ9šrl†±‰º?k•è_@ÈQrö‚C9±“o÷Þ!äØQtÈKþã,‹ü\DVô]Z2é='¡lŽ}r4!äØ 9rÖ~ü>£>!G}ÈÊi“<69>³Gȱ£è<C2A3>Sôg™“çµ¢$ÉŒ<C389>´¾ïÃA|Ó 5r4):ä\ 9bÕß<C395>ó…£>!GÈ‘ÊI6<49>CÈ1¤èPôg™“w ¼DƒqkÏm#S^' iÈ…„œ šSÿÎà¡«+äô%‡±‹çGýã 9úCŽØy<C398>ér9† ÚŽ˜<C5BD>‰<EFBFBD>£”ZKy~ä â±s
rò5d_ßÔ„«!'Ñ„µèŸNÈ1r¤ìŒ}~ÁÌiØ„œhšË(û'
~Zb9J9í“Õ²÷ý÷¸mog¯#r檪ÿ+Õ %ä¬{n<!§ <C2A7>“fÂZôO'ä9BC9]º<>BN<‘w+"ä˜/EpÒZmÓí3ùöº<C3B6>‰óîÙõŸ]„œõä+BŽÝ<C5BD>“dÂZô'äX92C9 r9Ñ´âO-v¹ ä`™æ³j>ÉT<C389>ÔzŸS@ý’ÂqþBþø—H^ú"BÎ*„œ’BN’ kÖCŽª,] '1”sJ8<4A>CÈÑûr}ù†Ø_PtÈÙöŽÀ[N–תù#<23>þ<EFBFBD>œ<EFBFBD>³ï|j¾…¾¹cômCß äh
9Û&Išx'×rRLX‹þÙ„œ k¸Ø½ë§ø£Cs9„œh9A9J9Y<39>íÇ&ÿ‘–‘<E28098>>Gä,4g÷„œCNÑcé]é!'Á„µèMÈ <09>°†‹ýã¹Çïs˜È!äTrB'
E½a•û*…Zcw?gÈ9ËwT,ÔT÷Ý¿qirÖ#äè*ÚBÎÂÔ¿ÒèŸLÈ <09>²†‹>”“t ‡<>SqÈQpÓ¾EÏö¹ÿ R8Í“ÕÄÞìÉõ^<5E>f7<66>{¶4îšlÁ¯Hȉ~z!§€×Kù!Gl–?Ö¢2!'@ÊNÅ<4E>þ—Oȉ…<E280B0>„<>£”Ó<Ym,l gë
#<23>Éjîd;äHXBŽõ×K!G¬2üz<C3BC>Ñ?˜<> i §áèhÿ'Kȉ…<E280B0>„<>£”S<YMyÝ»¹âÜzäÏY¢žj 9?r¬¿^*9âÖ¢.!'@ÒNùfÞi¯ž<C2AF>ÏË7xÓ¾r”rz'«³{ô×@ÎMþþ-ç(™_S9ëÅ~i^ë
9Ç
BŽô„µèŸKÈ <09>¶†SÝ<53>¸ô` 9j«Ñ—o(ð¦}#ä(å䮽׿>÷FVpirÖ“<C396> E‡œâ·<C3A2>N0a-úÇr¤­áTå´
CNô
GEù•o¥xÓ¾±»šRNëdµrv<72>þ=<3D>³uy§ÈdµÏ*Ü¥AÈ)9䨪<C2A8>Ï5„á kÑ?õu4ñ!gFâNj”0Ås%äÄBÈ Rô+Ö2§u²Z1»Gÿ®6·VÅ2“Õ>_w. BÎz„œ C!GvšõiFªÚ;Á×p©¦0K\;!'BN<42>{ɯXËœ”À–c9»GÿÈÙº±šÌd57Š>ó!G`Î!LJÏÖRÆ:BŽè„5‘<0F>CÈ™‘º†KuB´Àc%äÔræOPJ«‰ýÇr"qB.a—UÎîÑ¿jÍÍ“ïd&«ýšBâ,‡<1C>%Ÿ„œè§<C3A8>§ù^¯2äˆNX‹þ™„œ©k8µC9Ë—Nȉ%ú_õu×%ç€ø•sNt?1oŠç{ÝŠ«ŽÉj¿‚ÇÿtI˜ 9
šëCN`7FLçZBŽä„µèŸIÈ <09>¼GéPΊ§š#äìü:Ô°K‰”ro¡ÜQ)œŒcØU•³{ô¯Jssù—8ôO×ÊqI˜ 9«^k² †œ{Á“¡Õ†Á k9<><39>3#ySPé܉VgÈØŽNA}j0䄞Ũú-”û/*…±´±Î‚½Î
×{ §KÑìnWW¤¦CŽ@<40>£‚æ‘Á<E28098>£§móÏËnÈ‘Ûì7~¿!'@úŸªÀ ¬4 ‰BBŽ‚&­Á<C2AD>£ ÊM%Îý'•Bòx9oåìýYgn^2pÛÉLVûÝïa:äH¼‹wÙY 9jæ« …±]'ã÷+r¤9*‡rö…œü<C593>FCŽžýoÞB¹ÿ¤RhlÞªìSò46Û7Vóúá^ÖW:¦×äôú&WVrVµ@<12>X<EFBFBD>¯7ä¬êÌP<C38C><50> CûYákwU?JŽ<4A>#ÑnÊ?óÊbÈÑÒÕVæØ^Mèë&þ^Iõ§šž¤ZzŸHß]í¨ove­!GÇûE¤Õ¯7äè><3E>þ!'@†<>£0>ïk
9ùg^Y 9ZºÚ$fåþ›J!ðhG·‡ÅÆf{ÓÈçm½n®ÁïV©³rDÚxÙ+Jg1äè˜* 2KqÈ1sL2!'@Ž™PkÛRô¢d 9÷ç«™ 9:ºÚD¶ÊÊýG•©۬ÊÊ;|•~ûBy¯M×-Ó²œå<C593>ÿÈ- ¥Í<C2A5>ã³v,6™<36> Í!Ga<47>û$BN€,Ígmk¯7äHT§ÙK°É<C2B0>“?Šm••û¯*Eü'ãsÄ‹ÅÙkŒÍ)É‘u}p¿g«Ù9ñO·×PQÚ 9
6ßZ.}Tr¬T‘„œYª7eC9+»ž²„œs‰o!ñ<>#räl`ƒ3
™ÙG¹ÿªRhû¥Zé¦\§ï’¬YÙ<59>ðõÒp¦CÎPbEi4äd- ýYÓ—–<E28094>cd°›<C2B0> ÏÏT×Ëw¯8äˆìÒp/=äÈtÏdŸ‡!U!g»BÛ"nïï•Æ5&im›º§EºSÒ…™’yk›ØÎ<7F>¨ý2f^–#uNûNuȱÑDÈ <09>§µ¤jŒpmÛ5KÈiK|  9®Ûå%5JȉCâì˪jÙ`ç1I¹^Y7<59>‰ïñÉпÌeôGòÚâs2ï:Ë›.U5!ÇF5IÈ ÷Þ´™F½ì5‡œ}‰ÍÚ«ôŸ#UoåM9bÛ«ØØ§ºZ¶*$óö_ÿ)É"‡ÃÆž1ã!Gèò³ŽI\̆wËxßÄÖ\•‡Þ„œ™ÚΊÒóêIHYBŽÌÒÐàcÔÃŒVCNÖ—÷ös×ÊøGE×~KÑ»²º'¹}«·Ü>–r¤šë—åÄï
Jr2¾`¤ÆqÞ5t… ûìrä P3”³~ˆ8OȺQ·¦¤>£T!'çXŽ\ÆÉ½D«‘ŸËAÝA<C39D>ùü¿iúqÖvꎩ{<7B>¥BŽTû.ÛûE`‰Åk‹O®U<ve­ÇyÛ(Tr,œ˜LÈ <09>+ä¨)Wëç4ä 9";d]E/0<>ægs°µ×ÚXÒÊM>*«FËHÓ¹²&«yði-¶›Ÿ<E280BA>`ã0Iµ#vý™RŽD5™jwµ_®nÜ^r,£QrÄYñrd[ê‘êío­_ž<5F>#Ö!›+åH ÿü޶°—<C2B0>äl 4BÓ*ä²&«¥©ÞÖÃ?½*ÿÞÙ9r§9äX_Òi•ˆ6ŠÓæœ$;DÞÌUr‡æ"!äÈrRí½¯<>—'äÈݧ<)§“¨P~‰èLù»Ï ƒaö¢³;Óÿ=…ŠúTš:eMVK4<4B>pÝÞp»9’¯áKÚ…ŸM'ô0úÔ¿®!é¾@­ìÊg !GÍÄ¢w9âÞ›-?NC9[ºKó„Á3…†ä»4<>Ì_óó{„—§¾q¢=më·Ä=¯™ê'«DGK¿#GªC6ÄfÉŠþ·ó1Qå²ï.bE¾OßC›.ætÒ«£<C2AB>BŽú k„œqïÍ–Ÿ¦Š¡œ-3u2…É0xMÚ‰ð8êb<C3AA>—orÂRvR
Ã×EÔó©„Mö©}²ÚIvg<76>ï®±ÿጇù¾Æá­K?ãÔ¾ú¼ïû§ÿ×±ïûë šé'ÞÔòÙöÖ%˜½?Ëÿ!;!Gû„µÄ!çÖê·þ÷÷Þ´ÆÂó¦yï™BŽÜ¬éOCßm(.ÞÚN²>}ù:ç
‰9ÍIü54}޶S³ë@í“Õ®²Íœ‡‰¾ÎzÈ~½” Ï3 e¼%_ÌÍ1AÂyÿSÔr”OXKr,X6r}¯Ž)›–\g
9*F¼><3E>o:äÞõÅ]¿þéÊtÌÒ/3ˆ÷µ5]ŠyöˆEË®
jÖ¬¼Ni9û¼ææCN“ê/°«Í ‡s×FïM;´]M5ϲ3r4ô¹Ï äØ 9ù‹Õ¶¦D¦<44>£} Ue <0A>hÁ×õ$¶…С;'zð98-‹–6mí“Õ²ƒ_÷ m ¹<>ëk/,^­šFiãŒL͈ÆJÈÑÝÎ"ä 9Ù;·õaç
9©Î›³kHºãò·§‘¬Ày¦_C`©úÙX’“ô¶«+UøÂ [ÞE§ ýtr!'aUiÔÔP
Ñ0p⨾<EFBFBD>£zÂ!ÇhÈÉ]¿nœ’+ä¨þñ©ðº6÷ÌÀ©°Å‰öLZeg¾—¿ gK›«ÉÐ%rrJè7u×Xʸ¾¾<C2BE>“fÑ BŽÕ<C5BD>“lÎ(/Ž\!'ó]2`âVæ$´#ùÑsåÒ±Då#¿^ rzÏ^<5E>¿:ó!‡A‰õ³¿ § ( 9š'¬r̆œN]å¥1äTÞjñj¨8…É„[ëÕ"Òƒ–Wøº{4ú,ÈÙ4ðûøwöCƒ>íK^0a›Dj 9{½]£„³!'ë Eg%äèÙ_M©‰bWû&º«±<C2AB>t<¶»«}²Z'}Ïžš®€<C2AE>è·ÏÏ‘Ì{S!'÷ú‰„»!çhg '_ÈÑ<Œªu0‚é+1[-žŒó­LL,׺Âìêûƒi‹9Ìð©!+ïLmš« 9q¯*&BŽÝ<C5BD>“±TuvB
¶Oüe¦y‚YðDAì¬|Ç<>[#Ý{ÏÓó+r˜)à3¡·×_<C397>ÖZÈQ;a<><61>c8ä´fr2†œì{më6Y0<>`öV‹HÁöÑuúz­f:øWÛç"BB> ^ÊA-s<>!Gmt%ä9Ù†r:C!‡ w’wМQþí£µ¾£9Š/bzùÊ9<>"tU>14°*Sr´NX#äX9­•<C2AD>œœ!‡ ÛêCña<˾„ÚÙiôòÃÏÛE¹2BŽÖ–<C396>îàÌPNHÃ\kÈQZ….µW 93r}oî±òÎTÈaÃÊí{ñ W`Û<>˜b<‘ í£ën¬^Œ}í3µ,dCN…M¤ð“^Ê i j 9ZîºÂ_°¥<C2B0>³72<37>“5äÐbß>Ÿ îŸØÏo‰,±BÝëмv¥;„Ô5§RBu¥Ï¢E†rúÔ†¥¿……‹&äÌÈõ½™G):c!Gé/Oõ|‚
÷[1<>UæÍîênty<74>ºõT¡}®7—pÈ¡®ôYUÚéob½!G焵…‹®ðl*äìõ-ãÒrÊÙ>A0\À@N\™Ï­{šW`¿uëß‹ 9Ô•^»OrVŽwU¦7äèÌ® ×LÈ™‘ë{ó¾œ[s!‡U9Û7þð·a '®¼©³îâÞ§hβu<I‡œÊÏWzk~8¢îŸ\PU¦8ä¨ÜR}á’+,‰¶BNòi^9™CC9Û+Sº'g1<67>YÞÔYõ9×5ú<35>ïŒfé<66>C'š×1bÜ5ߦ æ<C2A0>£qÞïÂ%rfäúÞ¬Û”´CNå“Q¼Ú…þò¥OÁŒ¬©³ê½žnMжL›¯…+r46ìô.Ë]ómÝh9wpY¸â
›:ÆBNâªÂo 'wÈ¡>ÝÞ.Ô8çÏoå<TçrYÍ›lú2®È9:W"dÖ[lÛ8MuÈQØpX¸`BÎŒ\ß›³²5r’ÎŽ0cþY2ÇOêDLÈ™:«žšéU£Ÿ¿%iå"rêžîè}T2,ü:t‡}=Ê LÈ™‘ë{”©”<C2A9>b¾m‰Ü!§îvŒßTüªçðnä…)rªîQöJ]èúŒSa!‡½|~<7E> ÙÐkm¡î<C2A1>£¯>]¸^BÎŒ\ß›q”¢µrx mž3Í&Ÿ!½”Ø&ÃÚù½DÖV‡O:lî«ÝçœÒ’ äÐ#äu0ïö‚T¼57NyÈQ7amár 93r}ïOé^ÒÞ“B²‡ÞBÛ_ýþø×ñZÅ€Yù¦Ö\3xÅõíð/QÊ•r˜°æU®Ôuú綪…¥=äh›°¶p¹¶sì…œtC9­Ý<C2AD>Su­gmÊœé|<7C>¦Ú¤<1F>ø­æ1Þ{“¦£vŸµm›ä÷Zs1
誹‡Á{§Cí!G[v]¸ZBÎŒ\ß›­Éuoþ<6F>ScQš¬ö<C2AC>îÉÈS£ðN¶<4E>œŠWëùm¬Ö‡OÁ¹Ø)AsÝëŽsZ΃q]§ƒú<C692>£lÂÚÂÅVØ24rZõÓt„ÞBÛÏyaÎt¬Þo,È5<C388>Só¾‹Ç4UùkÓm,qä•!¯n Š;|;ô‡]Ö.–<>3#×÷æª(ÚBo¡í<C2A1>²æ&`ÌÞo,É4<C389>£ëm¬n§(g
õ™g³$
9UŸ¶äß Äk›_-Q›{2}vª&¬-\+!gF®ïÍõ˜öÆCãÛ9gYNŒ–!‰ïä4­âòíÕgåÑ$}mó^Ê\C§ªag§ˆ”³õ¾ ZÚ<5A>F*Ö…K%äÌÈõ½™†rB&…¨9ŒKx¼†˜Mð„r„ˆOdŸTñrq¿¥e—Ýc¡…0!Ú«ˆ”³ñ¥l!ähÚèiáR 93r}ï„'Hï͇V9nŸ‹Ï(VÐÇœ<¹³Þ¿~07°Ë>â‘n7DÞ/^w›wŒs÷\<1D>B!GSt°s¥©˜ 9 ª× ö<C2A0>’<EFBFBD>òœí¯¡šW-üDÆ“e §Þ F~wíå½v)wËwÞ/~“ uíÆ¥½ÏÁDÈQ4amáB 93r}ož¡œ} !‡>£í¯!–2}!ãÈÉ1<C389>£iJ……í3|j‚×ßLãÊ 9Õ¿_|«ÈÊÇÀ®›úl„=µëÂ…rfäúÞ,µDXOKÈ¡Åîñ ¹g¿<67>qåÈ©w E›ª?qWWòὕ§ÿ*²êõ²·N±rô„+×™ŽÑ<C5BD>#½<>後<C2BE>S}‹ýâÑ(¬ýžýBÆ‘”¡*H±<48>±¤-‡8<E280A1>çVrÈÙ5õ.ó
Ûz²­ö%3n=¯ÊHÈQ3amá2 93r}oŽnÉÀžž<C5BE>Sy‹Ýï9Ö}Ï~!ãˆÊ0<C38A>SíB€>Ù\<5C>»† í’†œŠg^mY;?a_é Ømóm³r´LX[¸LBÎŒ\ßû¦D<C2A6>zr4…œj+Ó<>®¶šïÙ/ì-+ýc©ðÝ×»H/µKé!gwrUÚ¶®dJ•ÓG=Nù²r´T±6®2%«!G´Šmâi
9õÎ(èj«|®9g€Jó|. +%ÝŒFÈi#}U†ÍS‡œ*g^mžs5yãªûMÞ}š}fBŽ’ k IÈ™‘ë{ß|}„L
Ñr´üöR;=ÅjgaxoF… ’Ï!¬´¿Ýó€¯ «»äX`ž<äTØ<54>>ŒóëÆUöfö{%Û 9:&¬-\$!gF®ï}§Ó;WGYÈÙëëkóê3zTïþ7Cœ78f¤žE[ëñO~Ço w*]Ük9»Ý©ªâünùÖV4eÀ÷¶Ù 9:„…kLËnÈ{<7B>ä¨ 9»}m}maÃ8Ÿ*ºeÒc9N©r*ë2ž\YÁ«¶¼)9~5GÈ©é3Æ­ kɇþ·ÍPÈQ±Îjá 93r}oò¾öðJL]È©§.ý4D™oUåÁÔ£ð[ŸäTº}´ç¼K¿©ªSß5Ôrv»c%}B—ÀM‰^4Æšo›¥<E280BA>“~ÇøW WHÈ™‘ë{ß»+ÈÑr*êk£-›¯oš_¤ÉæX<C3A6>x §šß~ŒŒÓEÛ6*K{"SÈÙíú
jËA¢‘¼/~hÐm3rÒoÿbá
93r}ï{2“"D
<EFBFBD>!§š¾¶>b;½²Áœ({aŸ§ã?<Yá{íC—ð­rŸªu.U…œ]Sz̹Kí:YvÌ L†¦BŽ‚ k XáËÀrÈé Œ0<C592>£4äT1gíy6A%É0ÖB&¬ãñtÓs(2èRžܪ™$˜/äsFÉ;»?—zç‚¿l…œü•íÂõrfäúÞÄÏ+F¢ÐrÊ~ ÉÌ&(ý–ÉÎÄÀ4<C380>çãÿxêÜ(°K¹ Ý䇗êBÎGuYh¯Ðs†Àä<C380>ëJ¼s—𷊱<C5A0>“}ÂÚÂõrfäúÞ´C91rô†œ‚_B³ df[•=—@z&¦¤ÈÑqzƒ<7A>£ÕýOžœ¬–i·‡¼!ç#SgïËŽï.q>µ—²:ÔÆsŒyÆBNö k —GÈ™‘ë{Ó>°(<28>BqÈùx •Ùèl¦¿iƒx7%žmD<7F>Ù—nž»4 ßf—JCÎGcÝå–¬¨éÊY:DºkÖBNî k Á’<C381>3#×÷Ί]›NvÉrv»¶œšôË »f¾´×ö"Nr›ŸÑÝû«ª<Ô3ã\"Žåš¶¢ äìvÍ©˜áœñrH{ëŠÈ9÷(ƒ86CNæ k "!gF®ï<C2AE>{J@œÎí!g·Û—5k-Á{¨ØIkDœ VL¥–[<5B>ŒÓÇìj9M½"æ^]» µcs¼˜~=ÇÍ…æBNæ±sBNa!'ò+Ü¿¿ÔXÈùØ7¬„£·Sš÷P‘Ë™î‰nž¤[*Xã9 CÚ ªÚZBN¯˜áûäÏõö<C3B5>Ñ s?GöBNÞ k„œÒBNÜwxWQÈÙíöÌ)¸ŸSN&8Ö-.<É狼Œ·3}Üš¤µöô³ÉVµ*
9s¯¬ŽçŒYÆpží<C5BE>ý`ëö §ø¯cƒ!Çsú$"!gF®ï]pÖ7<C396>c%ä|üÏ6»‹r$œOMWÌ&qö¾<C3B6><C2BE>­ÏÊûIUøJóÌ8¾ “›²m»U…œmo®Êúä/–·öm1unç£H,4rv§˜×÷O¬ð<C2AC>`>äÄ\WÛUr>^îFÇs®¹æì‹Xze'£4kL2® 1—qöžï‘q¯l·u!çCÛ_<C39B>ô¦Ý¯'•†µmß_¥igz™€c5ää¬w 9Å…œˆ«¼b äØ
9Ÿ ϶‚ÎÐç}Y_ª`*FÝ6>/ï~åúÞhžÇó€œwc—« 9íC·Kßš¨÷í]ÿÇeø#á]‡¾“ö2r|ûLäÿÄú^ „œx<C593>fÑvÃoœ­<C593>ó©í¯’Îí"0í·ª•¡$œüRj³„Ê8u»=¨ 9CÊF$nCß·…ÎÝ=|¢Ów úÎCþâ6ô§¡ÐdÈÉ8a<38><61>S^ȉÖkm 'ö½Jr>µ]Õ:Ãå>ô<>²™<04>µ•¡÷3³Ô4HÔû’oeˆ­Œã½=ÛïËY…j9_š¶=>7·ÃÚÜ݇a8÷}×*{¥äô<C3A4>‡>žÌoçïgss·a®}Jy×l†œ|u!§À<C2A7>«»2â±ÆÎjÈùí£×碥»í>\ûS«cøfJӞ΃<C38E>.óû¥+´·ÒžmÎûk ”JÇ{Óă¾li%äø<C3A4>F¼zŸxçøôô¾I0å!e…K÷ð÷1/;âŸxª³þ¡çúÞeÇ(Wt<57>xECTÓ—ïûåõMr<4D>¼Ô[”çþ³›ÍÎéð1?:aWä&·3G“4<E2809C>µ ä$Ï8Ó<38>"ã®e† ´ûñ!>ÂD<C382>žá¬s» ªmz‚¾óÞ›Êr|3Ž÷ôù7›ÞåÝ|‘<>´h–&C{µV‡D C±]’ý£3nñe)ãt‘¿ðè²"䋦·}œ<ÈrZý¶´Z}glæ<6C>5U~Æ*o;!ylh´Þ|¿£®<C2A3>ߌã?îòf©dî“‚ 9ÈcC£ÕwÛ‘Ü#
62ÎÁû.<2E>w'«r<00>Ëú6ëèûU ä¤Ï8ƒº“Î#ä <20>àƒEU ä¤Ï8÷7ߘyBòXßfõ=Þ¨¦<C2A8>œôçͦî:!y„ΊZTÓ@ŽoÆ ¸GoJµ.?Bòßv@Á<>‚úŒsóþʳâdIÈ@ÒÛ¨hn›q®o>Òÿ#"ä <20>µ-Ö‹çç×3<C397>ã{‡2λXuvüƒç ¬m±¾Yß¾¤ž<C2A4>œ g|“q:§BëyG€0+¬7Ï<37>¯f 'GÆy<NBò<>]_QÍ@N†ŒãŽÊï9!y¬l°z®©¯e §Ë<C2A7>qºø—ç G PØ.^Kî®
92ΛͣwW§Ãà{x,(hfÔ%+àKÌ8ïæÇ]œ
sÕ<00><>è!9U ä¼[ÿ/šq†7Ÿyrq<00>SÐÔ¨U ädÉ8ïÈQqÇïžã~@«š­žíx5KàÝÈ8Ï÷€HVµ[ý>ºuå{7D3λC@Ü𑈀ìÖ´\{¿<>\ñ†,çÝ! ÙÈ{ßûij¦íê·ðÁÏ÷Р<¢6ãq ÃŠÆëÍï“•lf,Ès„«ÐŒCÄ€+Z¯'¯Þ»Òy/?)1ã\8ûZ¬h¿ú5_Ï®l£÷FÉAyä¨2ãq ˆÔlµ&÷ì)­ÇãìŽcüÑ£6ëݾq ‰Ôlµ“+š÷ÖÑagÙt
ÏÇZß[ˆXnÄúuÓß]ɼ·Ž..ãq ŽÐlµ£+™÷ÖÑ»^ ãd4#â@!¡ÙjEêwK‚·Õî´mÕ}'â@#™Ùj%ïí¿­ZP§E“-ãܽ·ÐDÉÌV+ø л÷¶jÍ-þnnAŸ‚ˆµ–³½Ï‡¼´ÿ¶jç<>i"[jÎz<C38E>[”»´ÿ–AÇu¾É8AGî\ š-´gï^ZìþÑþ[´'h«6ÿ‹é½³€Z´gŸÏl]™èâO‘k®."Ô[hÓz5ë Ývàæ½å@ؘËtÆ9äØr€ˆZµ>Yèþуûþÿ{» Ëqˆ80a¾Y{õùÈ<KE¤yMÜ‹°ÍóôVg—FÌ7l½¶Ñ*qÛ<71>€ ÅÂæ•Mf«}†©j"Œ˜oÙî=>±ÄmüO ÛVm:ef˜ªvñ) @ñ7<C3B1>.pÛ<70>€å8]ôíÜ2ìªFÄ€%Ñס4®8þËqÂßäñ8mòÙ€DØ}é“+LÀé8ÍòÅ·½†ˆ8°f¶<66>ëó<C3AB>9ŽoQz:NØ–×FÁá8DØ3×Â<>ïàʰ©ØqŒ=G.õæÜDX4ׯí=>/Ã.’Nþw6,‘tùWãq`Ó\+·õø¼ô»ëÜ9:l´‰-šÄñ‘ˆ«æÚ¹wt™Z³RØâ™‰-Âæ¾mFÄ€]3 Ý¡òCr¦ª…×ùºh´MÛö âÀ°¸Kr
:$'`ªZगpÕ¤Ýp€ˆÛâ.Éé\)¦ª5ASÕÆ—ÛÞ%Ýp€ˆëfš»Ÿ´Ú¾<C39A>©jmÐTµÛÏpÕ&<26>©FÄ€}Q—ä”2[-dªZØÔ²Ÿ§ãì“.r"â Q—ä2[-dªZиËx̹‡ˆ€2¼oóþhpW3[mœ8‡3ÑTµç”Ñô)·<>&âTißöça+h·a8÷]ëß5 vTE°^þîõï|Η„ ÷Ï«©s¶ÚMËTµ¤û (Ž8’k’Ú¸Ï: ¿Õ†îêþÞát<C3A1>£Ç¡o%ÿz<C3BF>±eû<65>LiñWzYCß·aèû6à­0…rm®** ÅO¶üÝΔ>EÞ>§{<7B>³Õ~.ŠÙ`¶«ÚóÈÇbsê²3Sµï{‘6^<F€3¾<33>Õ?2¥Å_ée ÎïÎK6åÚ\UTŠŸxù/‘ûEàííCºÔ8[íuÿæT€>OU#âmN½lާ´j?nh1ö<31>¡·±öG¦´ø+½,ÙEŒã%V-åÚ\UTŠ_Šò70œ£CÄM”›ªwKxO Çns*$&'«Úá=ûâµ-¼<>•?2¥Å_ée‰ïÔr<C394>3‡rm®** Å/Mù´7®êðöù´ÕÍVCÇ Ê%÷‡›ÝÈŒÝ[<5B>8öšS¥(QÕ~”ßÐâ±Dkë~dJ‹¿ÒËJ°åc
åÚ\UTŠ_¢ò²‹byûxª›­öco³„ïÖ‡¤¤;ª<>"ŽÁæÔ¥Ñ]µ§Ù—üdèm¬ù‘)-þJ/+EÙŽÑp¡\›«ŠJBñKVþH9ù½{6ÿ´ý£Rnx_ÀOýkÇ<6B>¤GZȷל
‰ËòU{ª2v1ô6VüÈ”¥—•¦ÕÞp¡\›«ŠJBñKWþH9ÙÅ«ŽÎ°|GOÛ<J6¬F“Í©Ÿ‡ºjªÚ§®{ü<\¢mÛÅwÒ¡}Öõ}ßÃ]ªi‘êm¬÷‘)-þJ/+ÑéÉÁ3 (׿ª¢’PüÂËßkQìú~ªø1]2·xC¼ggW¾<57>£¿îssJ¹ÇNÄùÑœÒSaÌ7§B_bUûkWÄíc‘Á¡;ߦ‰${«}dJ‹¿ÒËê£\VóÝn¾N¦¹{hõI¹6W•„â'VþöÝ~ ¢zW6·¿ R6Òõ,M<<3C>1†q—”sý,EÍ©1æF}’U{óóJc.ËÚŸ|úAñÛØÊ#SZü‹9ÏöÝkíZ)׿ª¢’Pü$Ë_û#æ0a-3÷Ææ’¹wV<77>ý…‡!Â0NÓ mu7qŒ4§.Q'@ÊU홋|³‘ú ømlå‘)-þ…œ©]ýÇÀÏ£\›«ŠJBñ“-§ç<C2A7>ŽøÉðà¦ý=ð¹Ö1Œc5N›t'Ö9 ÙhN½i:rÔª}/>U½³²vÁÊ#SZü+ 9/u}`5J¹6W•„â'\þžËž…MlKö³@z—¡k}Ã8á«qöIűqÌ4§÷˜+½„ªö‹ürܧûrÕü6¶ñÈ”ÿêBÎ<42>vKào‡rm®** ÅOºü=­P7Øê*ÊKyô-ø®²aœ&l£…a¿kNI§©ÙŒ8všSÍëÔÅ¡ÑUµ7.Ákÿé§úmlá‘i-þõ…œçn¼ÀÕÄÕ—k{UQIª/~âå¯y,{lî——›Ö•À
†qŽAC0ã±éR} &#Ž¥æÔkì½TUíO<C3AD>Ñ£ÐÒ¬SÌç%û66ðÈ´ÿ
CÎó—°Ïª¾\Û«ŠJR}ñ“/<>_À‚°¼^J£g<C2A3><67>è€%Ã8û°„òïþ×ä“û³u¼¡æÔÄtäNSÕ~M±«êÞÆ.TF™Öâ_aÈÙÝâ}xõåÚ^UT’ꋟ|ù{*ø|¬÷³,ú>•Ä3¯"Ød¬Ú+à?ÿÍ¥f7âØjNM,Ó:+ªÚcîõÞ]ê¯ï+|dZ‹<E280B9>!ç©:l1uõåÚ^UT’ê‹_‚ò÷xD¾k¹IÿOØGv lƒÝÿç’»èi„”Þœú±qé‡[£¥j?¸$ïü!â»Hþm¬û‘©-þ5†œS¼ÂX{¹6X•¤öâ—¢ü=v‰ˆ|Öz)‰¿Šcøé±ª<C2B1>þ?ìýëFðºÅ<c-cÍ©×y›ãAIÕþÔH‹³­ç”ÞVÈQýÈÔÿCNÄÂX{¹6X•¤öâ—¢ü=þù"_€µÜ¤Wö’œ_'Ôd˜©–žõˆc¯9u|-!<21>Žªýiº<69>܉°æBŽâG¦¶ø+½,BŽ<42>rm°**IíÅ/Eù#ä¨ñR ýÊýë¦<C3AB>z,<2C> ÛS-¹1`Ý‘æšSû×錗FCÕ>$™o0äè}dj‹ÿP{È {®µ—kƒUQIj/~)ÊßãåÊ|Vr“Žq>F%ÿŸÙÁR”+$âXlN5¯3o{Uû-Í+¿µrÔ>2µÅ_éerl”kƒUQIj/~)Ê!G<>—B8QTK:%Çßhc‹qî§""ŽÍæÔÓ”ßOc›¿j<C2BF>÷I³öý·ÎÈÛXë#S[ü•^!ÇF¹6X•¤öâ—¢ürÔp“¶¶<C2B6>_‹ri4¶ãÜË©ÒM6§Ú×Òrª¥eaóm¬ó‘©-þJ/‹<>c£\¬ŠJR{ñ#äTå¥z=”äg[ú¹z•žLEœ¡œˆcµ9m:rÝ-‹„oc•<63>LmñWzY„åÚ`UT’Ú‹_Šò×´ßd¾+¹)›—b™X<E284A2>÷Þ*°3ñ÷•pògAÍ©‰éȇ¬U{Ô¶w<C2B6>oc…<63>LoñWzY„åÚbUT’Ê‹å¯.nÊ?—x¨÷2|[ÇöÉŸ%5§º—g3zÄìº[i߯ê™Þâ¯ô²9&ʵŪ¨$•?Ê_]Ü”¿”·ï€÷Ñ8­­ˆcþXœ‚šS‡×9ŽÛ_(u·,¿<>µ=2½Å_éerL”k‹UQI*/~”¿º¸)—ÒŽõž©ÖZÚ5zìË‹8¦›SÍëtäëÖñĺ[©ßÆÊ™Þâ_cÈ9Ù 9ÊʵŪ¨$•?Ê_]Ü”[Ö¾Þ{ª™š¨Vȱ8e5§žNVöšŽ\wË"ùÛX×#Ó[ük 9Ok ®AUy¹¶X•¤òâGù«‹›²us®r%Ná2q
Ú3º¨æT÷2P?n{Ru·,2¼<32>5=2½Å¿Æ<C2BF>s<EFBFBD>W+/׫¢’T^ü(uùYð¼ÞN±›ß«®1qnÅFóÍ©Ãk9:oùžº[9ÞÆŠ™Þâ_aÈ9:Û!GQ¹¶X•¤òâGù«ËK¹óx;(Þw`cg<63>Í£? Û3º°æTóº¬kØ0±°î–E–·±žG¦·ø×ršç6Z؇W^®-VE%©¼øQþêâ¦lœ,ùºC ~ËTö¯»+vñÙsÞ±­’5§^÷帯fu·,ò¼<C3B2>Õ<2½Å_ée †œ/…°«¼\[¬ŠJRyñ£üÕå¥ÔyTà}Q‹qަ6T+pÏèòšSÇ×qÁÕ#Œu·,r½<72>•<2½Å¿¶<C2BF>ÓüØ\'lß<6C>Ú˵Ū¨$•?Ê_]Ü”"6WóšÄÕœ,-Å)uCµâšS‡›÷6íu·,²½<C2B2>u<2½Å¿®<C2BF>ó:}9ð³+/׫¢’T^ü(uqS6~Æk¹5ºÛØábi)N¹ª•לúÙü±Yĺ€ZwË"ßÛXÅ#Ó[ü+
9ûîõµ8<>S{¹¶X•¤òâGù«‹›ã3Ì<33>ŒÓtÃÚ[C§˜æÔëœÎqÕtäº[߯™Þâ_zÈiÚÇþ<L í<>¡#è•—k‹UQI*/~”¿ºLÔàî¿DøŒ¬<fqµ¦qÜUφFÒJiNµ¯ì´æŸUݲÈú6ÎÿÈô¥—õôˆOí“Sÿä2<Ù2My]£lNååÚbUT’Ê‹å¯.B޶¤·¯Åß÷–Vâøoj’…æÔªÈ¹Ÿ˜ŽÜXhY=Ëoãì<C3A3>LoñWzYIöÀ¹…W¿•—k‹UQI*/~„œºr†}ÙÓÔêØmÀXsjݸZsñh/ÕݲÈü6ÎýÈôÿzCθ¦×yIååÚbUT’Ê‹!§.BNoxKµ¦Ó¹5\í» zìàéåyŽKÿ´î–Eî·qæG¦·ø+½,ñwÑ5Ný[y¹¶X•¤òâGÈ©KQ!çÞ–<C39E>pÜpÜUÇBsjõe6OG®»e‘ÿmœõ‘é-þJ/Kð]4—S´?´òrm±**IåÅ<C3A5><C385>S—!çß;‹ƒû“­YjóVƒ×»Zd¡9µþ²š×Rw<52><77>~XwËBÁÛ8ç#Ó[ük 9ãpî"®„¬¼\[¬ŠJRyñ#äÔ%Bȹً8íÙÖNŸKqjÚmÀXsjËeMLGž ¯u·,4¼<34>3>2½Å_éeÉÎ*¸Ÿcu3U^®-VE%©¼ørê!äÜmEœÃÉÚ$µ<>¿ïT×nÆšS›.«{yºãÌ,ĺ[:ÞÆÙ™Þâ¯ô²z#k"+/׫¢’T^ü9u)"ä¬Þpì0qxµÕüiµ9µí²¯¿˜÷/šº[JÞÆ¹™Þâ¯ô²¬<0F>ím^«òrm±**IåÅ<C3A5><C385>S—!ÇÙˆ8íéj1à8wÑÓ†ÈÁBsjëž~¯ïê¡ÑÛ²Øêé¯+ãmœé‘é-þJ/+ä?k>=öýë1¡ºœ*/׫¢’T^ü9u1rÖDœ¶;ëX8´]µKqÊnN<6E>_ôýMqÝ- 5oã<<3C>Loñ/>ä<ØŸî±SNååÚbUT’Ê‹!§.ÆCÎRÄ9´ýÕj¾ùœ^íRœÂ›SÝ˨â8Ýtª»e¡èmœã‘é-þ5…œ<E280A6>c=žŸ}ð'W^®-VE%©¼ørêâ&üÏð<C38F>Ⱦ¿mû~0oj=§šæÔÄtäóÔWwËBÓÛ8Ã#Ó[ü+ 9?Žõ¸‡~\ååÚbUT’Ê‹!§./åk{mà2ùïÿ{ß?gN·‡ý¯ÿÛžú¾¬‡›_.µÏS+¼9Õ\WMG®»e¡êmœþ‘é-þµ…œ)'tÂZååÚbUT’Ê‹_šò÷Õ&ýl 
}Öx)^ÛkƒÉ<C692>@<40>ûÚýâÊWnsêu+¨ñ YÇû¤JCNúG¦¶øWrv§˜Oµöró^Î!äLª½ø%)<>£E9½”®íµÁäG @Õ[FWÔœ:¾n÷÷òäënYh{§~dj‹}!çù¨„ÀϪ½\Çü…Ì!äLª½ørªâ¦Â?Þ*ß2º¦æÔáub奬–Å­°·qâG¦¶øWrN?»öró’¨**IíÅ<C3AD><C385>S•—¢µ½¤N~ü°etUÍ©æòRn{©ªý–¡e1”ö6NûÈÔÿ
CÎáñ³ÇÚk/׫¢’Ô^ü’”?BŽ/%k{I<>üø¸1O­¶æÔSÿ𧱪Úï专3r’>2µÅ¿Â<C2BF>³‹Xk/׫¢’Ô^ü’”?BŽ/k{±ŸülÇ<µ›SíëtäÓãÿì¢Õ•Oç® nlQzc0á#S[ük 9<>3庶ª¨$µ¿$å<><C3A5>£…›òoÃ?1O­ÖæÔ~b:r#Qµ?u•É<E280A2>Á´/{ZOÒG¦¶ø+½,BŽ<42>rm°**IíÅ/Iùë—þA"nÊ?†6a?µŠ›S³Ó‘#VíO‹
äªÝcĦômœì‘©-þJ/‹<>c£\¬ŠJR{ñKRþG‹EÌé¥P}¬ð<C2AC>ÀΊª»9Õ½‰ñ(¼§ŒÜLø§U¡oãd<C3A3>LkñWzY„#åúé vª¢’T_üR”¿ˆÕ‚¼”©íO}ò#°ç~Ϋ¢9õ|žúc½³j¿¾›î¬v±¯Þ·q¢G¦µø+½,BŽ‘rm¯**IõÅ/EùKR±‚›á#°Ê 7!¹u4§š×éÈ×&vÕþÔM6
eëS̨â·qšG¦µø+½,BŽ‘rm¯**IõÅ/Aùcª¤nÒ>ü#°l<³ÙÀ¢ZšSÓ‘‘«öæéã¯.zâ;žzâ¿<>“<2­Å_éerŒ”k{UQIª/~ ÊßS I;/§—ò´½¨N–Ü:æ©­PMsª§¦#G­Ú/³GJGñÔw/ûmœâ‘)-þJ/‹<>c¥\›«Š<Ý‹cD?ñò×J¬ú1_ðòøYš<îÞß§?³8g¥zšS‡ûK)9Ç­ÚŸ¶T•¨Ú›§§>YùÛ8Á#SZü•^!ÇJ¹6W•ÔÖ¤øI—¿ç¥E±FŠÌ¼<^
ÓïµÁÿ1ýxï~bg­ŠšS?Þˆ£`ÿÕ¯iµÏ/§ð¹ÎÚ߯ò<C386>LiñWzY„+åÚ\UôøÙÖÛš?áò÷ã\ÓX„˜/xy¸IÿqËG¼.ì+› lPUsêé$æOcÔªýyšúGVÄÙÂíÏ7Ó©ü·±ø#SZü•^!ÇJ¹6W=~ºõ¶&ÅO´üí¨h Û|ÁËÃMÛòÿÛ›ÏÀ”±¯cZsŠÔ5RWsêøºƒfÔªý©;ìÓ-΃jÏ÷°ã¶¦?UÿÛXø‘)-þJ/‹<>c¥\›«Š¿Àz[“â'Wþ§—^ÿh§<68>š/xy¼)C{ßBŽYC¬<43>KåŽ×hõÝ ù8ô5§7Ùª}ê×:ç¾kÛ¶Ý\Ç7ÿêØ_¦Ò¸¯ãm,ûÈ”¥—EȱR®ÍUE%µ5)~ïËße{ùû,z…¯¿N–¾hS%ͼ<Þ”¡cÐ!µ¨zÇèýù³†<>㥹Š\ïÌ<06>BÚZÞÆ¢<C386>LiñWzY„+åÚ\UTR[“â—²üÅ[<5B>`¾àåñæ¹ôþwUâ4ÝW !'ÆGǺÞ5ÓØÕó6–|dJ‹¿ÒË"äX)× ¯¯**©­Iñ{·ðG@ÄÒg¾àå¡ =Ÿ«„šqŽ<0F>#ÿç#+lN½<4E>Ž<$˜íÇýPÕÛXî‘)-þJ/‹<>c¥\/|¼¾ª¨¤¶&Åoéóu&ló/<2F>wÏfËgü7é‚b]%ƒ8û矑6´©±9µ¿‰Ví<56>ø8ý¥©ìm,öÈ”¥—EȱR®ÍUE%µ5)~©Êßwgjë/<2F>wç ä…g_%ƒ8ßÓÔ¾r¢×½±ªöÝA´nÚúÞÆR<C386>LiñWzY„+åÚ\UTR[“â÷­<C3B7>Yùê¹wÛ|ÁËãÝãÙÒBe{5Wû Îã4µ/„œ§È×ûÓ¾=U:Šñr¨òm,ôÈ”¥—EȱR®ÍUE%µ5)~33P╾è7Ã|ÁËãݺm8ŽO÷:ÎÄySIrbšz½§kì)É·ó±Þ·±È#SZü•^!ÇJ¹6W•ÔÖ¤ø —¿qèBTãíSÚðû˜Å£W±JV÷45‘C¦!cßöça¯àoõïô
ÀcUÑw×.mÍ"D)ÃpíOm}Ûv¼}Z[z…F›-»ŸöµNSûBÈè{£Žé€QQš¨Éõ2B`6¦F‡_‡~¾CÈrªxÙV½m¢n™ôØÅÍÆÝºø›Vê³?½›¦ö…<C3B6>(Ð÷ô•*ælV½o£nh©³(ç<>{Fw+ö]$äÊsòZ¾ µ÷mÔ-Ëæ—:õkQÇ^íeÕê<B (‡¶}Ümç’ûzÌxßF½„ne^›Û©Šij«7•'äŠòcûô*¦nf½o£²‰ôãYæÜ1]šÅ…89€‚CÎ9÷å˜3ÓHe¾Új—*¦©­Yˆó€<C3B3>(7äÜj˜¾6×rßð15ÏW«c7µ• qrņœK ï~À²™Fê¸á÷Û¸JÝû¦äV/Äy@ÈrŽÈ´›k¥n9É·Êó@ÇK q–OÄ™FÈ”rîù«¡°n®•ºå<Ѓ«NûE7Ý<37>½dÖ#ä <20>Ùfê–ž
ï¶°MC qŽÛ¶xFÈ@³ÍÔ~õ®·S ÕÇÍ[ <#ä <20>Ùfê–£rªʹŸkH8^[ <#ä <20>ùvê–­ªʹWqæç¾N8„d3ßNݲõÀ.dý† 㥆#}7S{AÈ@ Õ-­ú}ØåÆ ›©mCÈ@ ÕË–Ïê]©jI8Qã9Èc©¥ºi‘}¤yNÊÔ‘p¶‹žBÈ@.æPN<50>'‚Ö’p·‹žBÈ@.êPÎÉ…„‚<>€<\Ô¡œ’vX»×‘p2 ‡<>€l\Ü¡œ¦<C593>e9uœ‡ãÈÏ÷9Èc¹­ºé¬œÝ¡€}¤o= 'BòXÑXÝv¦õ͆Ӧ¡+«¤!Ù¬h¬Þ¶}bç̯]³«@‚„CÈ@6kZ«])ç~®b£<62>D ‡<>€lÖ´VǦø”s;U± ']Â!ä ›UÍÕmÛHïvGS»Œ—:&©%M8„d³®½ºmïK{¬U²“Zò„CÈ@6ëÚ«÷­C{ çåT3„³;&O8„d³²ÁzÞú¹ÍÅé6Ô2„³;^òŒ«r<00>ÇÚëÖ k»]§wÊÚí|¬d'[Â!ä ›µ-ÖÍÖv»ýàº_º*NûüMë®9ƒ&!y¬n²^=>ü¤l0g¼Vp>Næ»MÈ@ëÛ¬<1B>ý´×³2g¼Vr·ýIÁƄ䱾Í:ze„Vܵû¥«'àì!Ùlh´Þüëÿÿöî¹y àxŽÐÜ “d&\PT\fjXXZ\T^°° ÈLÑÂNn<4E><6E>¼<EFBFBD>mÙ–d=²äù~ÐîïMmËúûزÔÃêÅêU¿Þϵ^¶Ã1"È@?$£VŸÏr®{z›s>¦›{YE­ï¥Ô4rÐѰU¼[NfÓù·9ßw5Cm Tä ²q«ÏâigÓ¨~Ïò]}Æm Tä Â<>k›·#›ø“©¾Ï÷5Am`Ÿá”ä Â<>«ßk¹Çhãñóñuoïo®“Ô†õN Aú!¹žÛ¾(Y=þvä||½Ã×7W‹Ð·2,‚ôC<tõ\Hºdõüâ<>Î÷1Ýßgxóo’Ú?Ã)!È@?.½D9׉V›ôÃs˜þs<Üqt3ðIj‚ôãÒ[”óÏbóœ~<1C>^ëü<1C>¯éóæžƒ›Ï=m;$E<>€~\zŽr2«ÍfŸ¦iúzT¼^ÿKú¸!²‰¿rCx9èÇe(Qš,·Ý§Aúá7~ý^ô}Ý÷f3øujrÐÏlËýr ±ØŒ`<60><>‚ôÃw{¾Ã<C2BE>7{1ÂW879è‡ÿvß÷¥OßÀwûl@<40>€~´ľö}í“öðxÏBjZ9èG›Q심E²JG²Ž A޳4È ?»ä*`?Ç×ç ßç=”Cú>gî]÷îª:Ó0wh<>‚<2›A´À¤\Úø¦ o¤Ë Ôätäd~ûæÕCFÑ?¯í‚ÊÄÌŸž <´¯}ç<>=OÐ3
òäÁµlù0'¨‡1möÙ„ §§ çê»i|øUá±e¯ü\=àǬ›C Ûq`<60>}ôˆ‚<J9@p­Ažõ„²IÇºŽšAN<41>AÎårN­U3ø|ÈV“WWçŸUÈ{BȾP<C2BE>GŠ ®uÈ”µVÏø§‚ §× çrù±õ”áË[›‚¿°WàL8?v|ýÀ?ä±"È‚ Ц}§aäVÏù§‚ §ç Ǻb„ úìýÌ÷Uw¸ïY—BMð)0—Ý£ <20>A\ˆ6<CB86>—9Þû±/mF<6D>Ó{<7B>s9OãÍáwë¾½¿5êcLepˆÎQ<C38E>Ç‹ .L#ÈËSp®r|‚¿Þías•¾Ï®QŽäø]ój³Ù¿~‡ÈòÓ‹Ì{úÚãïã!}¼ÞS—?^ý»û<C2BB>éë±çw¸{ä#È‚»„ÁË™©8W9Ý9…ÕëÙ)Z9©zºŸÖ«G‚Ì“z,݃÷g<08>¥áá1ìU (È“röÇÌlÊî$™èÆ%”WaqtÎANAÎlöPžü¶ˆäÌf õmÎcÛÕ£Wß=¬#]~—Ô®)Û¨•›g?èyÚANѴϦìN’‰n\‚aÏ÷à\äôäTd>FrfjXâñͪRfªÿ¿ jXxÞô{?oäQ#ȹ«d¢—€¾™Hj³zþ¸›çê?}ßð» rÊQÎ&r<>£® Ÿ^Pzss¬¿Ù™uáôóåqz·+ÄáÞQ<C39E>G<EFBFBD> ç®’‰n\‚ú`d½M:Íe¢my{ rJ¯C>b93%voµzôíõk€ï.fÁîGUʇLâEw(ÈãF<C3A3>sWÉD7.<2E>s*Óémôé‚ §¿ §4oe;Èiq¬Ò‡Ò͇]Ì“ù½NdõQ Ð
ò¸äÜU2Ñ<32>Kp„9…ÅþcÛ‚q [ì1ÈQ…çá9úx¦´oNû­ŸC¯çV¼ž¢ ;äq#ȹ«d¢1Æà„9÷:C­„ =9ê!?†ä”f¦Yç°E´rÙ<ÕóýcCt†‚<r9w•Ltã¿—î<ÌYÔvI¼G}çÂ}9 91ˆ G]c ô¡tm5‚˜ƒ¿6bS?ô€‚<r9w•LtC}fÒÇ<C392>6Š›´¶ëü}ú_ßYqßAŽ:?5РǼZtiy¸çîî~¨·Fá³hBA9‚œ»J&ºQÞ80¤ï»Û7gó|Ç_àÔ°Yq¿AŽò–d?Ì çA]Q½2§®Ëu¤oÅ<6F>kv®Óôx´µ?ÇãkúèU*6éÁ|ìóñ#}t ¯ÓÃÑúøæçxLŸ7ÂÁõÃcúa>êñð¬Íúkºô«ñ<1F>é^RZ›¦û¹ÞA²¢æèp rÔt‡,È9Þð ò|<ÒÇÅDƒœ¿ºl½—ã¿ÌZõ”UA’9èœF‡Jßøv~½›Â³Ú¿Þçjfl×o<C397>³²¯´4€ ç`ûòFyuù‰ûYNqù?¡é’<C3A9>+Ѫ‹ß¯<C39F>N%(;áã«Ó¦\ßÏÍmôÃ^ðuáÏÁ2Š)_åÃÞá™ÐO¥Y<7ÞµóÇÞ©À<
6fþ~uðÍÑñä éŽY<C5BD>7ÂuN-É^Œ¸lÿ¶ ñzÓ²._ƒËm ›UA“0§1zêÔýŽÓ<C393>C|£7ýœv<>3³¿Të?ÈÑ­mXw-ÐgÔ<67>—ìíccv.ÜÆ%çÃÊ5|H#™£½È-^¥ÓoÏÆO2KWùìz\åp‹CÛKÈ<¤?a§&„ÎÑ‘äÐéŽV<C5BD>ååøŸÃfBAŽkõq+÷a³*\2Ãæ4ÆOÞBõÚŽ
ñ<EFBFBD>Åt³}$Aηu»ò<C2BB>AŽò@Þý<C39E>jO¤y×ÔÝ:Òßádž›Œþù ×`ãßn\<1C>ç`{8?ø<>= 1†r• ÁÌÞsöU–äbÖG³Î–êhnÓÂçè(
røtG*Èþ¿>L%È)ÍøÙt<C399>U¡’:§1~¾<>”@uÆÁlž‰o¬Î}çÐìÞƒ{0ÈQÞ[¯­ïõÎ1[¯ËïëCHCG¬8äMúÙTêV¾æq‰á*K+K4û÷*ïAv1gsdüàÙvŸj÷:´êþƒÈðéŽS<C5BD>Wmžå~?L#È9ž{6«%3xNcüö-Ê„ ô8̘‰Å&ý`}<7D>FÚÍYÐa<C390>£4n<34>“ú,„æÂtµŽt7gi=¾ù^5 8¼Æ2úÑ»0)9Ø®Rü"å Žq ߢµLÖ¾³õÐu<C390>#ÝQ
ré­q<EFBFBD>¾l„ANizpÐÚ$«Â$3|Ncü—Ž8}º9l›ý+ëC;нîï¤ÄrV1ƒœ•ÏÆ<C38F>¥Õ£÷~ÚBévlX«ÿÓÔ0èáßOÓ<4F>òÃÉÒ†BõGiNÊñ˜Þ¿Ùl³ÅßÿxNµáéª98ÒgÍÜ¥¿ƒ¦iuÁ3͸H3<48>ùùH÷¥C®²Ã•OþXzõ—ßµ…z§j/×õ<C397>Pe dÌ€ìB*×ÑQŽzPÒ4ë@”tG)È¥1ø÷G~¤êoo‡Ý<¦å5)Srκj§«Ê×ô§G÷Ú$«Â$3|Nc:|+a]ygÐV<C390>¼¾‘¡µP<>³‰äl΋MØV<C398>6¼eŽ÷ˆ¤Û±¡ÚŒü¤nÕdñ¬þ•.”Ì3;¿g߯ö•Q7i©AÓ¬`WʤƒÃgQ‹ý‡}ŽK*zÁ_Jõ9uú«ÇCi,·i|Cèòµ×ãÁzóãäèà rœtÇ(Èʃܳó”’Ňí K‡AN˜Óª<C393>éÙ-³6¥%%;ɪ–ÉŒ<C389>Ó˜€XÛ<58>õ[ á<>íW˜\<5C>³:x-‚æ¸@t7ëHw:6|uøÂCgóc½Ì<³«÷¯Ôû›Ú.õè:`(­±´±9ßQª³KÙ®@·”ò«è
jß&½v”£C/ȑң ?û}t±w¹ÌÑ9ECýíþR™VZHcdUËdFÈiL@iâH'Σt6ûÔ¾M̘­Ö{<7B>³‰ä\g <—W<E28094>uÏóÒ+šMÛ>m]:ìâ6Þ_¹>lw:õû–ýÑ2ˆYø-áýða1JWyíï*eÓ¨ê£o%Yî9P³zŸbåèÀ r¬tG(ÈÊø^ֺ̫èŒ/È9zM²Pf¬î»Èªê‘g2rSÐË@þüñ<ØeÉW×ÙÝ|{Ó
³ÕÆä„aY‡Øÿc›M;/u96<¶XɧèÁmƒ.·@@óˆko<<3C>𶌇T¯2õùðÃñëÛêé¿(ömÚw“£/ȱÒ¡ —*Ü#µ8悜³ßMx4?dŠ‘UÕ#‹®5JNc
|WOoïøº_ .º‰½qÐ]`•’A9ϱƒœoÑ*ñ‚eÓºXGÚùbÚ[µIŒ2Þ·>Um*”߬œ½Ëä‡i¨‘z´¥™ŽISv’­ÝfË?Y¥úû-G‡]<5D>£¥;BA.Ú:émÉi9ÛX‚yÍûSdÕ¬ƒ¬ªþ@v­1rSPÚ[¼{Ç×}ßït›}zàÝM@Q7oœžØAN5È9¾š¶
lLmó©q;<3B>ö””Ì"K[}áºqzªzðÜäèÛt2ñm/f„­ŒWé>2þðÈŸWcK´ñ¼OE¢¾»ÉÑaähé_<>[ }ó?œR<C593>“ú>_u<5F>UÕ#Ë®5FNc:Ø´É÷GúØýK<C3BD>Õ¿à†W7Á _ß½q9WççÅl6¢h¸ƒu¤;Û­§U|Rý¯ð¡|IÓŸý{”Tø·a¦<61>ó³“<C2B3>±È— íoô÷)ZŽ» GKwø‚Übè»Oo&ä3Âw†ækŠ‘UÕ#ËŽ#§1 <09>m•Óäçøšn¢¿Öy¸.Úþz þQ¢=1Uãr®>œ®½¼0qóïK{ØEi:÷ÊëÏÍ#ôÔ; ÅKÓ ùÓ§½ábŠ«ô›Âï>ž6ýï¨Bÿ°7ZŽ» GKwø‚Übèk6¾ §ýèÐä„˪ꑅŽ<>Ó˜†¼ÊQ<C38A>¯ÛI=Þöy äáßW‡#“Ò:À‹œ» rÜVØ/ }ˆ½Žtqøcg¿'†.OU¥G6 (šž¶:]ç<>é\’ƽÈ}÷¿9›n‡ÿ0HäÄËÑAäxé_<>Õ·N^×*;ÙÔ‚œY‡mŽë¿EÈiLÃ`^åT}ÿÛ=÷qãózço›Ý4=™<>Ö1^ä ,ÈÑdHœ™Í -•–9qzz}éîÆ†m‡´ ã²ÔûÈÅrÞåÿþÓ⦘r~ƒŸì9šÆ_?žŸäf´ÄËÑAäxé_<>ÕÁ¦ÄäÄɪꑅŽ<>Ó˜ˆŽ7õôóoJé!5ûø÷ 6·é/rî`ŸœÅõ!Âæ9­¼=ºï»àüpy&÷«o«õs{ã­ó{GR¾&éZ9/ß®1È‘¾ÞrtÚAŽ1Ýá ²ú`%Ø›`‚œ8YU=²ðÀrÑók˜”¾ËŸ9…ÇÒK¡4ØêцåØÂ?¢ó¸¢9þ×äxªéô»JcÀâó7m’¥A<C2A5>-Èñ¿$ËS’ï@í+AN¬{ÐêÈrSQÚ‚h<>=r†ä<wä”ö°nXlI}e,X–)î:Òű r4§j… §AÈë)n;AŽñÑÊÏ!ý÷Úï²Gä¬ö×ù.g‡Ï¢oïgÆäDÈiLk<>! ¿%Eï[” 'í,È)­
½¶z´áMóë,°âÐ9šSµB<C2B5>Ó äõ·<> ǼB££ãñ#Ý/&ä<ìÕU_š}?_ûòQ9ás“QÚŽðÆ> Ã r"9ê
h1b•¨ëHG&ÈÑœª‚œ!¯§¸í9e²Á½âçu1• ç!•<>ñÎ<C3B1># rÂç4¦ƒ k<08>Éj rf±ƒœ•Ó²¢uØBÌssR™ GsªVr„¼žâ¶ä”=´˜©ò±˜D<CB9C>³ò[c6Y<><§1!Û,£$»"^<5E>S´öçèAN±/‰åpòÕ£ ßñéâÀ9šSµB<C2B5>Ó äõ·<> Ƕx‰Ðy?<3F> §´¬¥Ä󸂜à9<C3A0> ) #Ö¾ºQ‚œoë<6F>'p<>ãp¸v+AG\G:ÂØða“)U‚Ÿ«$È\A_<>3[¤þÛåíGä”6ó4’ 'pNcJXGmñAÎp‚œâ˜‡!9¥‡(ƒ°6ï<36>ÚDƒ^6úCŽ2È  ´¸J‚œÁä9×ÑïþÕs½Õ؃œRëyù>¤û¿Ðµ<ñb•E´<45>iúñ=Ö 'lNcR¼ßhÿðd8A޲’Y:„ çu°³"‹k'Èq8U 95!¯§»‚<Î ÇÍ¿‘þ>ýPGC?# r²’<C2B2>ÿeÄN]?=Ù¼ž‡äÔ’!§1-¥)!€PðÅ}ïEŒ ǾMNçAÎãp‹Ú1|G<>£E<C2A3>Sòzº+ÈSr´»ï#,rÜa<C39C>óàù|èáuÊAŽSNcbXb þt³¢ÐW<C390>£<»›õäŸ ûeÉ•P‡$ÈÑ"È© y=Ýä»rÔ¶ÕµNü/3í#ÈÙx/M¹¿‡ Ç–Ó˜uïr@‚gHA΢8ä÷‚œà› \GÚ¾¡<C2BE>‚-‚œš<C593>×Ó]A¾<41> GÙ=ð<• Gü
üã‚KNcrø.~xÍ;¨ Gyª›ö䔿{ "Ü*¹<>áß=Ç rÆõåÂ8¾#,G<€ çÇÿ‰m~ÌNrtÐ9^º#ŒœÙçô-’¿u™EÐÐK<C390>³ñ/TÃrbä4¦ÇsÏ(Ü7V˜V<>³hZ0¦Ó 'ÊÇ~ÁÖ‘^…™êdž‹–Ïí78ŽÖ<17>£ rZ$+ï;ÉÑAäxéŽ0rNýoq„Ë,ÆW‚Ó… rÄCøÅˆ‚œ9<> j³e,îûã ,È)žFs<46>ƒåÑHœM4‚•¹sðIpÅí/¿00ügy9YEpIxh±»ÊÃЂœÉÒ^|´vAŽ–îÑ9ï§O‚ÓÕOk?Kö¶~à™Ø€ƒœj2 rËXÜ¥cÈ}ïPð G<>¶ï ÈQ_ÕX§Î]~Bom¥=h PΆÛ B‹ÏcgÑÅå/iMS\äø'ëAûÔ ZŽ» GK÷H‚œ½o1RšzÁéêmOËe*AŽ,™9pµaÊÂn@‡B9ê*‰†ÕdÃ9Js¶¯Ýò<C39D>ué¥P¨99ûЯ‡”î í3ݘŸ‡plZ¬Gœ7ÈñOÖ^;q+ZŽ» GKwÌ ç9ÜÐ×7ãÔU&§«ß<C2AB>g—xü`ºZ¿AŽ,™1rUZ°92Um`ANéUìcAŽ:¸ú0/\âséóžPŸWŸÃN¼T#±•áêÏ‹6‡­=>Ž0à(nʳÿsúÁMWóOÖ·v<C2B7>ªh9:ì‚-Ý1ƒùCóW÷Å<C3B7>Yø¾‰¶%a#[ìÎpÙÇCø.¿l›Ì(9<>©Ú(ÛlF¬80´ §\uMC9¥íµjåAýÆïv&žÇøª1*l?8T6]¨½×:úmÊWy]V[aÀ¡¼<C2A1>ÖqeWŽÙà‚ßd™æ¹ÅÊÑ<C38A>äXéŽP<C5BD>7þ3늇½ c´"I¾:q×'ÈY¸u‡jã¿ò_BúÐC<C390>ã›Ì(9<>éÚ3g MÎ)_ã *ÈY<—ŸN{àpAŽº]´¦{)<29>»B”õah å<C2A0>Ë[•¾>„ 2Æî]:6|PHõw1VÞU’ñìùœþcxAŽš¬½WlýÐI޼ ÇJwÔ‚üê};,v¾]‡Å«rÛlK‚©øv¹é«zá÷þ<C3B7>±—Í@}“%§1e„9°"ÄH<>³º.dõ˜¾«5Öü4·}<7D>s=ç>ý¨l¬õh›^¶ ><3E> ô}u鳡Ëåà=n±//NYKñ«çKPõ;IMhcÀ¡ÎY>ºg<C2BA>:”3~ÈÑ_<C391>SN–ãøtña~7)G‡^<5E>#¥;FAþñŒ%•7YõùO?Ò~ðQ}:ãä<;ÄVÅ^‡<>mß»=¨<>¨: r|“%§1i•†(üâ }=ÃóŒ•H5û`[( PD²‰°ŽtiÉÕñ<C395>>^Ã8—?¾íA—¦µ óÃ:èòó¼ðx?§{cÀQ^ùûçÕé^<ªw²ºzù ‚å1ñ5Ÿ÷ Yšjc½H9:ô‚)Ý1
²Ò¼Ý£¾‡gåiÊ¢!œü°£Õþ<C395>ìG·§l- ‡'<çTwÎEzÖÌ|nú3ݹó‹î:ÈñMf”œÆÄ­^y<> ÿg„è*ȱ­ì'È9t0·¬|»B­#åDÝàµ46¼ŽyÒôßÈraØmæ9ýøi~;eÀQ<+½ù>¦é^³Îߺ¾J´_é0‚œÒJ×,øHŸuYðoÈ_M“f"Lœ|AŽ“î(Ѻšáçã_~°mïôœJ‰{u'ÏÇ×[åXÝÞ­ÿ«éë±t¨M« §üýãåûõß-È_æ—.;ÕOÒüWâoÕX›úk˜[ŸÐe<C390>ã›Ì89<38>É[½²T?‡G^â >È9[ߨG ržm}U¨U*díÝò‡¡è¯-w[þÖ4΀£åÈZ.t<>Ó*YºÙ>Qrtø9Jº£äò<C3A4>YNÿxÆëF?EÓ–ó‹7÷³~îbº r|“'§q_<>íú;LÄñ°gÉè9çƒ==v±–xé™yÀW¥vû¡f‚qðÚæL†<4C>É# 8V?AçJ$È©~Þþåh„CAŽ<41>î8¹ÝØ×Ô”zl´ñªM[,³ ]‡ÿ•‡J¾E¾<45>ÕÕZ$3NNãN<\ß½¦¯GÜ£Cz<43>©Â„Õ(ÂKž›ZëàAŽîÓôïXó61Þ­ÂÞË'k ß§íÆïÿc 8üwLÓ%(AŽo²Îiw9:Š‚>Ý‘
òþã<>ø£ðÀùú §m<C2A7>㘖ê+GÏ×n‡>6m‘ÌH9 F<>óspø–:p<>sÔ~wœZ¾AxÇÂzlªOÓ×½ <0B>oÏó;Ôˆ{VÂ-J2˜ Ç+YçâÃIA<0E>îXÙ7³gºhÚÛËõÖAÎì¡øèÞäGó~»ù¯ê޽9¾ÉŒ”Ó€^ƒœïãõ jÇî¡‚œŸã!mÜž;è9 _ž¶õ°¯®‰íáûÕejÞ*=†;fÌÇó¨°œ<C2B0>ÏÍóôzr®ë3IFçç<C3A7>ýC§9:ž‚4Ý£õÊb.2ýñàVŒŽÙËõöAοܵœêü¡¿Ã¢ͪk Ñ[<5B>ã›ÌX9 Àè­Ó<>úÚB.~ŽG÷0óvªôX^}©~È×ô1œ&™Íszlº'Çãu}­1=]\súìðìàq5Æí° *ÝF×Åòœ¾.þþw»Ú§¶”<1F>¯Î‡ؤ‡zæ~7œkõ|pJÿùxL]&Äç•ÌX9 à*I^.7oI2ïûr¦é)I~o7ù%If÷ƒÒ…Q¹Ûš
ŽèØ1˼C/$[Ã<>k¿TþF2ØfÕ¦f$ÉWVÃv³a›g—Zø2µ
Éß¿Ÿ|ΣùÛÏÛ=š ¿tÁ$n&ª™ÓxŠwåÇš¢ç¢ÔP¼Ù~ùž$O³ÁÖTï4çí_¬Z9°›:A*
îÆ(²?k‹–¢¿¢cÇXlo窓>bièÉ]Ãù¼ð~NúT¹ðYíÔVíïÔ~r9ñ GXºnæïƒÉË¡\JwAÎoÃoçê<C3A7>£9 AFÏ5u¤AN×7u:‚T KÄ6~²AŽ_ÇtoièÓÿ•W]XÞØw^Þ\ú΢ðÊÏfÛÚãÖÞÞUx7W/SrÄ¥ëO"}¨Ï`.¥» çÒðRt§þ¶› ǵU鼦Ž9Èéì¦NI<4E>Š‚A‰ÙÆO4ÈñìØ<C3AC>îmëoúu‡®óס”+ƒ¯‰f/úúµž ÏüÝþ@u=Ù G^ºþýÕIüæ<–]J‡ANÃ9Jʳ dz<C387>ˆ\SGätqS§%HEÁ€Ämã§äøuì@žšúÀÏÚŸ8u<38>;•÷0ï!»ðí0Q«íDƒ<1C>Ò•?#Bd1 Ké4ȱOÙ—:¸ƒÿ‰­ñjê胜è7ub‚T Fì6~’AŽWÇô¡ô>ݱ¸†y@¸V¼ ôg<>QΓGL8<4C> ǧtÍ–Þe"¸]J·A޽•³µË 'ò€Ü§¦Ž?È!Ê RQ0ÑÛø)9^;Ї¥ò¨é”$Ëê’eÚW<C39A>Ž]çRЋ»YÛÈâwcRý¥&Ùê#Oɧ¥³œD<C593>ãUº<z‰b{·AŽuºAyJW§ANÔÉU^5uA3Ö$‚T Eô6~Ù/» ~;ЇOãÂdsó'3ÆZ»NÔáÀ—Ë›üO·Uj,µìýo… µRÁõA½­<C2BD>÷ø7ê·Dý9^¥kH‘Å9_ÍòVu³™]ê?eÙúä9×>/õ<>¿ó¡ÕTß4wäôzS§'HEÁPäÈï‚_Çô`kû v™å“ Ö΋ç‡O3C²®V8BÈOò©T²Ýi€ÕKy±«Y¥RùÎÙs‰¹9~¥kH‘Å9o_<6F>ÓpþŠôoV£9å…_†VSÇättS'(HEÁPäˆï‚gÇô +<2B>_s{(ñ$©µ[§B~;õ:ñyù’Í£­Œæ_ƒ{•£¼rÒG^I'<03>^‚¿Ò5¤È⃜—ÆÒø7Üé2ÈQÎVSGätpS§(HEÁPäˆï‚gÇtoÝôË—6\iªµùh`Û¦üæñŠh¶Vb˜—T³ŽtñXcÝø±órZAŽgéRdq<64>Aκñ Å_%Ûvä‹1&«©#r¢ßÔ)
RQ09Ò»àÛ±Ýkìžó7&[Q­ÍÆ –‡\·Ç`ïy<C3AF>õôÙÔ‘¥i2”>;<17>–ÍëĽM+Èñ,]CŠ,î1È™<C388>žÜ&áäc莂œü†ý[¿îkꘃœÈ7u’‚T AŽô.øvì@÷Þ?;}Ñ…+<2B>µv×ÜsÞ:×$¯2¢o_<5F>£ƒ_ÿ<5F>w"˜ç_ Ù^-å<>S—“
r<K×<4B>"‹» rš¦áü<C3A1>ÙÞºrŠÄËaÕÔ19qoê4©(
‚é]ðíØ<C3AD>î<EFBFBD>#‚¥.\i¬µóKÓÊ3Y´,N!xù27Ï<37>Ô‹Ò|ñä´cÐˤ‚ÏÒ5¤Èâ.ƒœ¦i8Ïv<>9ó˜ËŠ´¨©£r¢ÞÔi
RQ09Ò»àÛ±Ýsèd³g—²Z«û+ÝÀ/eì&ˆK–æÞ;{/4„_·…²^ðwRAŽgéRdq—ANVj×öI8<49>9yiyVMu<>õ¦NS<4E>Š‚¡ È‘ÞߎèžCi}ÑþæZ›}”cú÷ÒÛ›'ñNË&ÅÙÁô¸K’|ZJ’D_ü#Ÿçß<C3A7>´uôÇ© rt¥Ë¡½]&×áÅ)Û¬±…§än¿kKCèÐráE³« çÅúj5›„Ó}<7D>“•–·aÕÔq9ö›j)°ùžhúªSûõ_Dðž¬ãW”ЧÛ¼üí¨V˜'·è$ê
‚T”6éÙÝîüoÒ8ûAvpa&ín·ïòÙ|!¡rB~Φ»5Ü 'bɘ'­ÖWVÃ9ÚŽÝ[<5B>þ^^rÜÈÚASRæYÝ»^Þ0ž©NÄ¥ù–¬ß r²£®•-ÓßÑXÞä<™ß‰dãYÅ{ÜIŸ®+Zg[¢n«wèTþ÷¹ý~ìtÛw<C39B>#)]º=ÚŸJÿTþÕ)iJ<69>¥¨Ì¶•QÚÒr)²ÓÙ.\V4»
r¶Ö¹Ù$œîƒœ$Þñ-jêȃœúMu)°OŸ<4F>¥U±+ýúô¤Ô”·E9Ry‹×Ë›2~X—Ž•t[Q|Ò³¬î¶xÍ6Ë<36>—uxn™”[¿Tެ-easBtN‡»eiãÊŽ,û«˜%c§ì|ùÚy9Âa£°“6´²‘<C2B2>{ÉÉ.ØtÓÞõWïÔ67lE0{KqN0'¿YR͵¶iÚ©Ô;d9ï¾ô€¹9|1õ;å ¨âqŸïþT{†UTžìªÌÑH<>ãQºœ‚œR»òæä([!æÞç1ƒœú…ËŠfWAŽuÎ6ÏÔ΃œ§hAN›š:ò §~S› l±ë²¥´æÖµŠvÝCÐä´­(ʨb[½Ô<C2BD>©‚Ÿ\{‚ Å'=ËÒ2æ™OÃ[Y‡çšI7Ëú\{!!sBxN‡»5Ü 'fɨeõµ×óø&G8lôr*q„d$ä^r–öÈ-ë Ê÷ß±ljØ´™ýÆÎea¼ûUì,Ì¿hx7³-)•ÿëàËx|ÿÔZØB¼ÉèYámn æµ:[T²:f¸¡§rJäx”.— §Ü`í|ƒM»WzB>ÈÑ\¸¬hv䨦á¼äqBAN›š:Ý ÇP`çÚQ‡1Ú.<±9­+J1ªÐœ<)ï­pŒr‚TŸô, ­–nÀ'ìðœ3éO}@m¸sBzN‡»5Ô 'jÉÐdÄi鳺šðVù9•Ö@4”û+¢'ÍS{çvÐÞ°™óËR0aûvÙ˱,Œ?hŠZª¯nNÒ¥ŒS>·úúg(æ‘£œ¬Lû¬g] T²CÍm
¬‡äx”.‡ §ÜFÿ<46>JåAÎÒØ<C392>lc9º —Í΂œ<E2809A>eN> §¿éj©#rê7µ¡À®³5j´ ëêѵk09í+J>ªÐŽÝw¥ÃUn[H©(>éYêjë2XØá¹g’íçšú.'Äçt¸[ r¢– í}<-}öÉ‘ =ƒœjk  ™S\+9OÖüÿ¬hÝÛAkæ‹ñ­—™uã&ßZÙ_ðfŸ8Yû§iBd<42>éåbÖbVÎlm5âmY•ÕŸïÜ*<2A>ÊÎVî«Sôäx”®æ 'ßgLmòÅAŽ9ÆÉÈÐAŽöÂeE³³ '+¹Kã$œyAÎ[´§mjêȃœúMµØì¢u4û¨VæÂ+Ç«¥=\EÑ<45>*2׫Y¸­x¤¢ø¤G7ë¦8‹ïÁe™tePë^²Ë ù9îÖ0ƒœ¨%Ã0âÿ’9~ÃF¿ §ÖˆFBÊy›JŽõËpÍJW‚vÐÚ°™cׇ.°ûÔ~Ø$ûÓ¿ï:ïÚWiKñ<”¬®šßD_)MerŲMY­*ÙÒö<>Uäx”®æ §Òd­½‚ýÓÃr¿:ÈÑ^¸¬hvä¼5|óö¯'è<ÈÉúƒ ‹ã´®©#rê7Õ^`­ÅuîömAá-FE¹Éô7‰a®ªc©(>é1>’®– a‡'É$Û“qÍ•„Ê <09>s:Ü­A9QK†1«³f`mØèäÔ[ÉHHRrl_†'µsJÚA[Ãf­{ÙíqäÔpôݹzgÑãwÄýªea–ÿÎUf™ïk¡.Òò¥ïk‹ÒuÊWÌWì‹÷*'¿>\ T²‡msëÆªÃ
r䥫9ȹeãm1ÆÛ#i<>£ô¬_«¥n•âð%ÈÑ^¸¬hv䘧á“p:rÖÑpµª©ãr47ÕV`ÕÇŸKmÕ¥<C395>*ÏA•‡—§¿ŠöôÒä¨(·#Ý®ëóßzÅk·þeó®tIIñ0õ³³Šâ“žìò“¿õ°Ô_/[tx¢L* Ë>ÿ~ž­ÿ¬‰÷å„Ï9îÖ ƒœ˜%£žÕêm¬ý<è°Ñ/È©·’‘<E28099>¤äؾ±¸•Ë"©¢vÐÒ°eï<65>®G¹¥þ¶¸wå„ðW.âïÕåëõ²Ÿkÿq™r×Я&õÒé>e[½èe¶ºàåò[í _<<3C>â~•ÓjÅÛj ¢¹iÕ³¡9~¥Ëð ¤r¬bšcâÕ~æ¢T"жeÛp)ÞANíÂeE³» Ç8 G™„Óy<C393>oËÜvkS<6B>:ÈÑÜT[<5B>}Ó®N¤,T¨ýš·üí[s<>Ó²¢¨gP®³üÖ@¹¤¢A˜wTQüÓóû¤k²’ž(“”qò»RæEXTºarÂÿœwk`ûäD-º¬ž—2c­c÷rÊ­<C38A>d$$*9¿ÆÙ)uk¯:´ƒ–†-Q–2Ôä^„ÍîPý³§—æ%º³ŸZ6F²M*Ñ­ðÛðò§Î<'²ã˜÷ÀÈ×µˆóZ°Õ'µ@¥¼ê¶"{ð4¼ Ç«t59omÛOCp›¿<E280BA>~<7E>ä/ܱhv䘦á(“pºròwáÓßîcŸ19º›j)°E£[)ù¨¡Ô‚ç_|–Úõ­ò ù-FEQF¥,-m²Ô<C2B2>,wUïô”ïd~ƒµ_!¸\–IÅ8¹r«Ö'ÝYÃä„÷9]îÖÀ‚œ˜%c«ÿ4¾ˆ,]ï‚OÇîäTÿB0•ó¦/¦q<C2A6>[;hiؾôKäÇgé´Ÿ`¿ÙKìÅ…1ÆÉŠâ§®p
KÃeê¿3ÍW^Îbxð5ó©6”Zš¶?<3F>/Èñ*]MAΩmû™·ÿ‰iÄ·ŒäÔ/\X4; rv†žö¤ÔR[<5B>Óh+<1D>Ei;¬šê<C5A1>æ9Ú›j)°y“»5Þ51ÙP¨ZŒ” ío1*ŠiT¡<«Iæ¨(<28>Ò£Üö¹÷Áe™´5<ITÊÒ6tN:§þn ,ȉZ2²êkS;ß<05>ŽÝ7È©µ‚‘<E2809A>¨ä˜_ýV%Y;hNJ¶5HíòÄKqÁƸڷ¹Ç¿4³,ò­]«o-ZßF·qovÓŽ3ÚøÉX_Bøl3±²¨d Ab¡)³@‡äø”®¦ ç©mûùiÐdÅ!‰äÔ/\X4; r²µÒÞªiyiÝUrŠ­#>VSGäèoª¹ÀæO4­{ö˜J3ĨØŠ<C398>«ßbT㨢è0Öú rYC<@E •žbà»ö=¸0“>Í% ûNV½‡Ar"Ô9µwk`ANÌ’±4.ý\4aËh»o<C2BB>S»‚‘<E2809A>¬äd¯Uª?ÝVgô
ÛÁÆõä¸á¼™WÜ0̵4ý^)ê–×lú]—¾|Ó*“ãn>ëÅîÝ2%m³<>Ó=erVT>õU0{°d<>ãQº‚œß¶í§Ã³²÷AŽæÂ…E³Ã '»4íÛøÛíé0ÈY¿E]%¤UMm<>cº©æûb»`ã2mºóÛx¶¯(ÆQ…ö}Ó?¶5›*T”Pé)²dç{pY&eí›vð•ý~6'‚<>S{·äÄ,–*H-£uìžAަ5p KNbx¯òV=Šg;XOÊÖ˜Û/—·$_wíWY¿\Þuä¥Ñ§9{–öµ Ý;|åë1ÕIóðú©<C3BA>þŠ4µk¨AΓ¾
&õ
4¨ G\º‚œ÷¶í§íYÙKåf† r´‰EE³Ë G? G<>„ÓU<C393>³,--åÙÖý9¶›j.°Ö/'³Ô|¹ùsæ·Å8ªÈ¿>¨Ý’O÷¯3ÃT” é1l &9¸,“[ È~Ÿ„͉`çÔß­a91KF}UÛú„µe´ŽÝ3ÈÑ´Î#!aə뻘ì‡kßvМ”èe…¥q;°Ë{=.~×MrÊÌùS+ó–YÕ<59>rl~ÇäªàWý¿+È‘–®† GW®Díç»e<C2BB>®õuÙNefqÈ GúXæ·× G; §4 'J<>Ó¨:<3A><ˆ‰9›j,°kûõfOƒç•Ÿkg.kj…«(o¦ Í'ìÔòæäxV¯ôhüµp¦eõàÂLú²–€ú|¡9á{NÇ»5´ 'ZɘÛê—hŸ¯ŽÝ3ÈÑ\­óHHZrôCƒ§jÐ"l-I‘o‰6vÆ[Ë›‹“òªx<C2AA> õ ?þµuà¿[éðf AŽþMvVMÖrd¥«!ÈÑÝMQûù+¸!ƒi18õäd¥íÉ8 §— §><3E><„;r*7ÕX`MÓ9*<2A><>væwÌÖúá*Ê[Ótþú3Õß Ç³¢x¥G‰XG®—e’fn´ª~°9á}NÇ»5¢ §]ÉØÙª¯ï×Éî»g<C2BB>£k GBâ’³Óž³6!UØÚ’òk,#¸­²—ªg^éÊçÎÔ(ïDË9ý÷oò×€.åí©s?)ý}ŸA޶‘J41ãƒAéjrtOò%í§õÑeÌ Gú
âÒo<EFBFBD>󤄜JU·‡ ç§/¸ï §zS<7A>ÖöTó€µþ¤TUÊ®¢dGª—–Ê%ZŲ̂%Pzò_'ž—eÒΞEkãÆ²-r"à9µwkDAN»’Q<E28099>‹êëdÇŽÝ3ÈÑe»ãHH\r´@çµ;#lmIy¯îJŽìt%¶2GÄ\k×IéÏ·æ\<5C>ƒÚ­d\Qú§øJÇí<C387>o±Gm” Dz´G3]§ûkÞp ~<7E>ãZºìA޶e‘´Ÿš]‘; rd[Xj‹f§ANÖTÏM“p¢ì“c÷iÛ€V5uøûäoª±À~5¬@Vù÷“uøýf
rTó¨âbº&ÿ ǯ¢x¥gÖ2ÈÑ\–IÖ÷>ÅÅìBæ„÷9gÓ
rZ— {<kÚÕ6XÇîäè³Ým$$.9Ú80©…lÂvЖ”'Ñæg—W'}PÞPk‹'›õX#ë4äÅ}ϵ~,e<>§¦¥¨—<C2A8>ÑX{ïA—<41>ÖWAí˜á9.¥Ëäh3VÒ~6µ|±‚çÅÑÍE³Ó G3 ')çV×AN}uøAÔÔq9š›j,°õo¼mè6Yä-FE1<45>*ŒYåäøU”@éqr f’ùŒ’$dN<çXƒœ0%þ*ñgë»Ðбû9úÖÀm$$.9Úi_µ‚*kíI©í7ôÂ’j<E28099>IÊ=déÎgÿ±y›ÎOŸ©Kÿ]<5D>‹=žLEeýoñ’ª(AŽï‡´ÆNw]¿ÚÝ<>v<>ÓTºìAŽö=Iû)˜|4Èiþ¶°±hväÔ§á|•3«Ó ç7æÛüV5uÄAŽþ¦š
ì¼)<29>å纯;S<> ¢˜WˆäxU”@éirìf’y=­’—<E28099>9𜣠r‚– ûØü-È]°tì~A޾5p ‰KNs¼×®MYIMØÚ“¢ìÚû4m®<6D>àžÔê¥þì¿™ÿ4ÿËjAÐm”[Õ8Ô0ï_Vͳ<C38D>'M{áä–r³ÿ‘|UìúŸtwO9à¯î6{9^É ]º"9ÎC©.ƒ·¢éäxæbµ´Î«­{eNgAΗdÀîkjAŽgŽzÞTS<54>Õ E´—YN<59>aØ´õ
rÜ*J·AŽWE ”k<>ãppa&<19>Wö2'ž³e<C2B3>Ó®av£áK†ñŽ«·}­cä¸<C3A4>„Ä%DzyΛw;Ø<>ýcÿ/Þçteû¥- Ù3ÿáüdŸ‰dÕ8“Ⱥ O¢¯î|×Q<C397>³k³> ¶Ó­MµÊöâ<C3B6><C3A2>/È1–®ÈAÎûà‚ç¢Ùm<C399>“<EFBFBD>ng˜„%ÈiýJµûš:ü GxS›‚œµ,È1üx-rœ+ŠùH1‚¯Šâ“Q<>ãvpa&<26><Ž69qºÃ 'FÉh› rL{Ð Çi$$.9Å•<YV´¶ƒŽI©_ t¤˜Ö¨”žì?¹´k<>Oa›F ÖÝ©k»Ö7ì[U-Âöä”ÙÿÈòR©™¶Ó]'Ôo¬:ô ÇPº"9¢9_9‚¢Ùq<C399>“T*Re΄‚œV5õn‚œÆÑ`¹sÏ"GÃ<47>—Ò GPQ:r|*ŠOzAŽëÁ…™ä8lüì!ÈùœN<C593>§d49O!'íé:ö AŽÓHH\rŠ«ü¬”Ž“;ØØ°)1aÙP>.˜¼<ÎTÚ…ì?ÙþNûmL¾…² Ô‰÷?Ó|”–o¯Üi<C39C>“¯ç’ë;ÝÏrwšÝÏíHƒm麯 GR4;r*ÓpÖÕ[1<> §UM%È©^fùçö\ßbT”ŽƒŸŠâ“÷ ÇùàÂL"ÈÑhú3×ßE.]9ºŽ=h<>ã4ò rž*â¥þÝNè g6{úêpçkÔe•7#YØþL»V𡕍±<C2A8>5®ÿ³é´_I¶[œ G°¿é®º| ¾Ó}*w§;ýèñ9ºÒÕM<C395>3<EFBFBD>éj¢¢Ùq<C399>S™†“T—ˆ™P<E284A2>Ó¦¦ÞM<C39E>ã9]-Ì79¢ŠÒq<C392>ãSQ|Òãä¸\˜ILWÓhú3×ßE.<19>9šŽ=l<>ã2ò˜®–GKÙ]û­·y<C2B7>§«ý3Ñ>ÿw^iz[·.0{o¢Ô£, l¶Óe“齜µØÕ4,<7팢úM’ÿîv<›·Ä}Q쿘P>é;ÝÊÂïúE!‡äø—®{Zx@V4»rÊß\V'áL)ÈiSSï.ÈÙº5Ìš½öüWW“U”®ƒyEñJ<C3B1>ë°]ppa&ÙwÕÑäˆÏ9Ò '^É0ÞqÑ79Þ{Ø Çe$$.9Êy¿J¹ñÕ¢tr,u[ Öû†£¬6•<36>ìÖËjm¾šæŒÆø4.T>¤öG•ʼ,ÇÈI’(k¸ÕXÏæ-ŸêßüÖñ·š†D–6ôšz¨!9þ¥+l<>S[lÒÖ-´r4k[Z.\X4»r²i8×Z»
rÚÔÔ» r—N-¯Î^›6ï¸ON€ŠÒu<C392>#®(~éq¶K.Ì$ñ"örÂ÷œã r"– ûÒ®AŽwÇ.ë5#‡‘<E280A1>×– ÛÒ¡Þu]‹®a—
÷çªOµUØ´•¹c°Xo¢}ƒœ—¦ú‘]’½ ƒœb±ƒ¯ú¶šÚÐÉuø“¯:·nHdöœg®ü¦3aŸÿÒåä|º<x
·¨Óé¬.,šÝî“StT;í$œa9Ý×Ôáï“(Èiܯ²p¡ýç/’ GXQºrÄÅ/=ŽÃvÑÁe™$Zš2PNøžsœûäD,_ÖùÍñ.xwì²^³12p ‰KNíýO6ymÞ¦”M™%¥@‡W9íüºµëÙ=oäd)–<>sã¿Â9Ù³ªËïÎaj[XYT×X¼³áÔ˜Hµ‚}*Û‚ÿÒ6Èyªæð“¤O9µÓÙ.\Z4;r¥¡­M™T<E284A2>Ó¢¦ÞO<C39E>óÕ0§¯²y…ýç_‚ GZQ:r„Å3=nÃvÙÁe™¤YÔÇ.@Nøžs”ANÌ’aó¹Þߎ]Ök6GÍ#!qÉQÿêK¿Ï¯G;( rþí›¾Ê ômØÚ­ÿ—ÕÚ,Ð>Õ‹ò§Ã„ÔmûorJŸ<4A>^.¿KÇ÷¤e‡o:~Þ´ÕæÀÔšecßì¯æƒ r¼KWØ '©æÀÚ:Aãåò®î’(rj§³]¸´hväd»=ÿs=Ñ §EM½Ÿ çÝ­áM\ÆÙ<>ßbT”΃aEñL<C3B1>Û°]vpY&=IW! <0C>¾çe<>³d$.Y½ŒÖ±ËzÍæÈ y$$.9µÏÔÞµca;(r”Çý¦uá&q{#öîµð€fuµO‡ÁÀÉ¡ßßÙËnå[ÊwÛYuµ+¤,ÉŸŽï¨k_3ŸL©›ç?©{AŽwéòrtO=Þk9l½®ÒL߆ Çít– —Í΃œì™ÕV7 gRAN‹šz?ANCkY݆ygûù“$È‘V”΃aEñL<C3B1>Û°]vpY&¹~<7E>2'|Ï9Ê 'fÉØÙï5,Y c—õšÍ‘AóHH\rJu9©­ ïÙz9®±$¿¶µlÍæš.µöT«
K—<EFBFBD>{ó÷t–5”ݤ|„“-ìÖÕ®<C395>òOŸœ#:tº·ô<å•ñi˜AŽwéòrÞÌyü[Ëá/K<>¨. i½·ÓY.\Z4»rŠi8Ÿõ*7© Ç¿¦ÞO<C39E>³¶_ïW¥éΞh¾Ûúð·¥û GVQ<Óã6l—\˜IŽs•‚æ„ç9GäÄ,š—§µ9Üߎ]Ök:DÍ#!iÉùS|àS_Ò§´%e—$‰>·­Oàìä²pê“×f ù÷¹»ÚXàM:df(»ŸÖTeO .–çg3,.îÿZòy¾žûÖ¡ÓÍ·×ΦḢäx—.ÿ Goë·¶ö Es9k—Kq;]s?ï\4»rnÍù)ë ד rükêý9ö<39>*³Ô|Õek˼ä·¥û GVQ<Óã6l\–IÖ7 ³íu±cu9° 9áyÎQ9QKÆ»9¥ù6íËh»¬×tršGBÒ’S<E28099>¹÷fh?…í`ã«q]—Ó¸P5ü÷›7õëKQ­Í‡ õÿdϵìá‘­·±¾yª¼B²5ùÂäâñ‰øñ©yµÝãáúmÈkt} Öa9¾¥Ë#È1Ç-YqRÊŠm!óÏJ©Õ_Šètžc7]Ñì>ÈÉ.cý¤¹eÓ
r¼kê9/¶ ÎJlý‹¶/K´ø£¢täÈ*ŠgzÚ9šƒË2)ÿÔvn;ü.hNxžsrANë’¡™"Z­Ù.wÁ³c—õšANóHHZrnòu£ 7WØ6¾×ÍükØÁ
ŽòðÝÒ?gýú§¨Ö¾™›Ç_DZÆN¸Ñhu<68>ù¬pXN›×ìxANQ<4E><51>c§bÑȵS§›m¯ýnÁ #Èñ-]-‚œOóÎj[[+d
<EFBFBD>‚·Ó5öóÎE³‡ ç–Ôä]sǦäx×Ô;
ròÙzOnäl¤S=Ô¼Øöî-FEé!ÈUÏôˆ‚çƒË2é×ò?ÿj>pNø<4E>sÌANœ’‘÷È;cÅv¹ ž»¬×tù<74>¥y$$,9å z_›Æ Âv°ñÕ¸næŸfÙYø(v·zkzv¹•ÔÚü¯”œ~w\ø;+—Ÿ~Ë|UÿܼF1f‰ää‹BÎfó|lU¾3æN÷–i–æmAŽoé2¼¨µ5z¦µ±ÖÅÎj[Íum›dÃ¥ÈN×ø©<C3B8>sÑì!ȹ%õëWóTibAŽoM½£ Gÿ̵üxWML^Ó>K<>R—ÊÖÞo1*JAލ¢x¦GôMŽóÁe™¤ÍçÊ`õ%pNø<4E>Ó5ȉ>/(»D—ßF-Å<>Üw ]FëØe½¦K<C2A6>ã<r-9™¿+úMŒ·DÖš“òf~<7E>jÿ&ì¤ë¢·ù¿¿ jíSþš[Éé|ŸÏ¦×o./N í²Ú2o«õ­:×~YŒYÄëoH([;½×“´+jø—c§›ßISJ<>ãYºò^§ü7ÖF/»‹åG"[e÷hµ5ÊËgy0»®?ÓÔ_ŠìtÍ‹F¹Í‚%k…qbAŽoM½§ 'Ÿ=oØ’¢ÚloÇ”ªö¤nêþ£¢ôäˆ*Šgzd_^8wx¢L*æ°UûÞDW‚ä„ß9¥AN´<07>Ù%ºü6jÉPÞÁì´Ÿëû,¿Ž]ÖI;9Í#!aÉ©´f§@í 9)ùqŒ¯Qã=~¿J9UGú»¢b•Ë¥¥ÖÎKûµ*Ÿ‚%®›åÿ‹S-KÔÂ[œû]óßÔò²,J£¦¨U¼Öº\ÞÊã<C38A>'¥g¬¼²´tºêµ1ãP‚¿Ò•·]åŠomôÞ5á—ʳ¯rû¹ÓfÍ=Õ_Šìtæ —Í>‚õb^¦äxÖÔ{
r”çÉŸkݨ¦Ò’oÇ.§¿ Üw‰:zî“ãZQúr$Å3=²}rœ;<Q&)<29>ñÕã¯ßµ©“^çt r m|8Ù5ºü6jÉPÿVš¹9~»¬“vYw¹q$$,9ù?î¶g;èòj\}À0›móoÚÙ&§½b¼wõ•d1Ã.)Õ«ò#ï‹«<E280B9>ˇU_ù«Ö²÷ä¯*©á•ò¥YñôârJþjÑ6QŸ‹Dü—Nö›Ü.w]¾ÃÕ‘ˆ¥ÓUóL3%Èñ+]Eùz_»6zÅ“•Ë×ßIn“ã/Ý„]¥e}ÿûù“Rx^š.Ev:ó…K‹fAÎÚÜ<C39A>Ø‚§¡9~5Õ;Íc rŠG£—ËçßýÙ&_æö¨ñ޼Ũ(}9’Šâ™á—Ξ$“Ê#Ë۾ɥ"PúÊ;PNøœÓuàohãù¸ØvP2Ê-ÜË¿[¿Ë?M‘|™äÕ±Ë:i— §q$$,9ÚײóÖí Ó«ñË)¹Õ…]rêäéûý(B]‹Ê­vù“ÊŸå™Ù™æMî“s-«Ñ|ÂoÕø~©•j#¥c9i[/%ÂKäx•®r“ÿ³½Ñ+ÿ‰âåIs•ojÊ‚öRd§³\¸°höäsûjeqzAŽWM½« G<>A¯K^mŒTzR«‘Ĩ(}9¢Šâ—é—n—eRCãiX=»mNøœÓyàohヹ¸ØvQ2f³åÉtÌ7Ñò ^»¨“v rGBÂ’£<E28099>¹<kݺ½ï~\z?Â]ùiþ‹ÚŸ½¹¬­^y˜ñå]ËÊ#ZS½¾žâÅiÉ·¶J¯Uu~M#'më¥<-™;Èñ)]ÕÛõæÒè•^0+>³‚R¾Áƶ¾Ú>i/Ev:Ë… ‹f/A΋ñÅþƒŸšz_AŽú챞º¥s/þù) r„¥— GRQüÒãúå…¼ÃsϤ†ã»/#Ë <09>s:ü m|0¶+¯%!jɰ Îײ Ç«cuÒNANÓHHXrt38M«ü
ÚAë«q[fÙÍ"ë/i·nÿ}–Aꟙ/ÔÈ[ܵ_-«^°9è~É‹jäÕÈ||.E<>nÑXècÆ9¥«Ú~|:5zú‘æ×\ä”Ö²µ+ÚK‘<4B>κ,œ¨höä…m}AŽGM½³ §ô¥pÙ—¶O.Ïõ»y™‰‚aEé%ÈU¯ô¸e=:<çLj˜UÊZ°œ<C2B0>ŸÓyàojãC1_¸. QK†ñøOÙ‘–1;vI'íä4<C3A4>„„%GóJßüøÛ½´&Åö¼•=r±öÒÊjÛϳ²‘h‡NßQå<51>޽óW×±1c»q ÃæÍ},­ŽR¥›—gítOö}C
r䥫öm„[£§;ÍuI}<7D>czf_]„E{)²ÓùÌþÑÍ^‚ݾ¾rä5õÞ‚ã2%#ÿж¸ »™0È‘U”^‚YEñI<C3B1>óPÖ£ÃsͤrŠª¾ ñ]ˆœ<CB86>žÓ}àoj㹸ØvS2 Ï÷’üH˨» “v
ršFB¥C5—ͳ.ËòWÎí =)ÊÖ•Ã{œ<>²=cë´ã]š¼T_Ø|Šºs×¥%tW]ZDÃVoaا{çÖÎÖ4æÅuÊYíM7hXAŽ´tÕ¾Ìݽú£¥9l
rf»“KáÑ]Šìtö —Í~‚œSs?Í G\Sï.È©¬/¬Ye¨Jù’6/Þ'Y<>#ª(ý9¢Šâ“÷¡¬O‡ç–I7[íȬþ»<C3BE>9!<§ûÝ2¶ña\\l;*Úë:\“9» “v rFBÂ’£$­¶e^‹v°))ÚÙÚ<>,ZÙi^XŸJë3LEû_ÉÉÖ$R™ö<E284A2>2ÈëNãû•rÃ|]µÃ”¼JåúL*¬ƒÑÕ\]~£z¢Nwi ,È–®Ú×­k£§®ó{¹¼ý•Cc<43>3›=}ÚÞ>š/Evº¦ w/šý9ÙP|{/Aް¦Þa<C39E>3›UoÐKÃÌŠe¶öåûmͨlüì´…§´¢ôäˆ*ŠOz$CYŸÏ%“ŠÔVŸ<56>kûÞ°9!:§änÛø..¶<>•ŒZtò÷ÒÅ#ÈñéØ<C3A9>;i· §a$$,9õÓ7}ùïÔ6'¥Öß4]<Í“¤Xÿå¶ÞÞÐÍ“,Ðù²_ñ<OÜ{<7B>IÛ%EyN²5ï‚°tÍ“[Óðò·uƒëIþÝ_×,γÃró¥ˆO7䢉’û­©næùýyK\¾´¬ºµÚ»{®(QÓâàöL* þì,;"<22>Ó¯»‰'zIßÝjïKÒù°1P¯·äÜ®$z;˜I²Øae êÕôÈ$ܧ۔e>‹2Ù7ÔŒ"ŒLÂ]—üðK퀉Ûu²AZ!“pŸn³Õ˜¥ 4N×eh S<>nóãÙÒ»odPõé¾ã ¸;·Õw–%Z-ÛP d _´­¯ÅhÀ(>ÞÕ ²…ŽÚ¬G„È$ â¶Äö Úƒóbün=ÛR†ù ½#“í+L¦iÛwë—¯¹aøÌ|<7C>þ‘I€öí&˭웎˩4ái^ì>ÎÚĽ#“]ŒÃ¢‚À (ç»›o“ÛâŠ<C3A2>½€L®ï4“ëËÌyr¢à»eö–@<40>9ïC@&Ê×iٛ;¯ ÿƒ­´™äKªeXS4î®}EÀ·A&•`ŸÍ¡€ÍÎ4Š5»†ƒLÖ¥è¾ï«§,Ó¥Ž!¶}_dîÞ\)úŸÌÒM–•Éî—Ë£ç¡!“pïŠ÷™,¬œ¬“baÖ„/z‡‰LÂ]Û&Ÿ×ÂÿNˆ³Áø?ãX”
endstream
endobj
126 0 obj
<</Length 66941/Type/XObject/Subtype/Image/Filter/FlateDecode/Width 3301/Height 993/ColorSpace 95 0 R/BitsPerComponent 8/SMask 125 0 R>>
stream
xœìÝOŠ[´/à©Ü–-ÄÆ¡:¡@lˆ6ª£ä€<C3A4>c§:ŠrÏ8PpgÀ8€×<E282AC>Ç¥.u뙑YùgG¬µ×þ>~]ËÈý/3b¯ˆ˜&FôŸÿùDDD®ý¥”^ !""½$ú+ èRx̓ˆˆô›è/1 á""R)Ñ_k@Fá% ""R5Ñ_q@áe ""2B¢¿î€Hᥠ""2Z¢¿ú€á ""2l¢¿€•„W)ˆˆˆD‹ ¯O¹Iô·"°ˆðš‘ÍD=<00>…W#ˆˆˆlKô—$ÐLx‚ˆˆÈîDU „W ˆˆˆì“è/Là$áµ"""%ú›8FxÉ<78>ˆˆÈ¡‰þò^o ""r\¢¿B€„Wˆˆˆœ’è/R`/á5"""§'úë¸Cxu<78>ˆˆH«D©»„—ˆˆˆ4Lô÷*0/¼¨@DD¤m¢¿Z€á"""K$ú ø]x9<78>ˆˆÈB‰þŽþWx!<21>ˆˆÈr‰þšþGx<15>ˆˆÈÒ‰þ²þ[x <09>ˆˆÈ
‰þ¾€Ñ…ˆÈ˜±²I±QÜ)¼x@DÊ'z<>³ÐÉÿ&z0À¸ÂËD¤^¦ÄÂGÂ=`\áe"R SoÂ[L=ú`Pá5"Òo¦Î…7 &zôÀˆÂ D¤¯Lå„7©„$zÜÀˆÂ D¤‹L¥…7¯„$zÜÀXÂKD$s¦‘„·¶¬ŸèAc /‘„™FÞò²r¢GŒ%¼T@Dò$zAJ!¼dåD<C3A5>8 Û…<C39B>\x‘€ˆdHôR”Nx<4E>Èš‰nÀIìBG‹D$0Ñ+Pjá½#«%z¬ǰ<C387>=
/‘<>D¯=ï#Y-Ñc 8ŒÍDèWx‘€ˆ¬™è%§3áý%«%z¬{±Ÿ] /‘u½Øt,¼ïd<C3AF>D4àv¡€ð‰,"K'z™é^xÊ:‰hÀVáû‰6¡•ðY,"Ë%z<>©#¼+e…D<E280A6>2`^øf¢íEh(|þŠHóD¯+…÷©¬<C2A9>èQü.|Ñ#4>yE¤a¢W”ÊÂ;W–Nôþ?ëìÚd„•…—ˆH“D¯%õ…w±¬<C2B1>èQü<>õ·üì3Â:ÂkDä”D/!c ïnY:ÑC øo±›}¶aQáµ"r\¢<17>…wº,<2C>è!¼3›áì6ÂþÂkDäÐD/C ï}Y4Ñã F—jƒ/ÕÁ@áµ"²¦ºþhác@Môø€¡åÜÝKxHеðÚÙ'So
êðÁ Ë%zpÀ¸2oí¥=0èQxm€ˆìÎÔƒ¡!|HÈr‰\0®äûzÉ:^ "Û2å6l›„ Y.у ÕÅŽž<C5BD>Gh"¼6@D63å¦}Â[@JôÈ€u´£×ËqBfáµ"r;Sná퓤­Â?»ÔT0¬¶ÛyKoÚ|„…׈Èu¦ÜÂÛ'U£…p)6¢`X§ìåEíÚ|„S„׈Hòï©ðÆÉÙtá\* 'Ö)yQû†öááµ"ƒgJ,¼q2·aø§–2c †uâ.^àî¡ýG8Zxm€È°™r oŸä<C5B8>þ‘¥Æ@€‘<E282AC>¸‹»<>h Ž^ 2`¦ÜÂÛ§—V ÿÈR`À°Nß‹Ý@´ Ç ¯ *SnáíÓWó†^é}ÀÈNß ßC´ G¯ 'SnáíÓ]#‡XézüÀÈšìß…ï!Ú…„#„׈Œ<CB86>)·ðöé´©Ã?¬t=~`dMöïNù M¶íBÂÂkDjgJ/¼‰úmóðO*ý\“Í»ÿH“mD‘p¨ðڑ™r oŸÍþa¥ßÁ#k²ywú9}ÑF$*¼6@¤d¦ô›¨Fû‡RétäÀÈZmÞ%ù#6"á áµ"Å2¥ÞD•z!ü“J§#FÖjó.ɱ  ¯ ©”)½ð&*ÖáSz60¸V;wMþÎéÄF$$¼6@¤F¦ô›¨d<C2A8>„LéqØÀàZíÜ5ù;§ÿ{‘p<E28098>ðÚ‘Þ3õ ¼•
÷Kø'•‡ Œ¬ÕÎÝé§É‘Ø‹„ƒ„׈t<CB86>)½ð&*ß;áSº30¸V;w'þ<>†{ˆö"aáµ"<22>fêAx+<2B>ÐGáSº30²†;wGÿ<47>æˆö"aáµ"=fêAx+…G;KÎ1#k¸s—gÑ^$ì/¼6@¤¯DOÙ½„·R’hmÉ9f`d ·íòlÚ‹„ý…׈t”©á­”*\² \Ãm»<û†ö"aáµ"]dêDxCe‹6—l×pÛ.ÏŽ¡½HØ_xm€HþL=o¥œÑò’mÀÀàîÜåÙ4´ û ¯ Éœ©á •6_² \Ã<>»<[‡ö"aáµ"i3u"¼¡2GûK¶´Ú¹Ë³uh/ö^ ’0S'Â*t„$00¸V;wyvíEÂþÂkD²eêDxCõ}!©F ÐjçÓ|Ñ^$$¼6@$O¦~„·UGÑ’j´­vîNù; 7mDÂAÂkD’dêDxCu<17>"©F ÐjçîÄ¿“ä0`4áµ"2u"¼¡zŒ~‘T£hµywâIr0šðÚ‘ØLýo«N£_$Ïh®5Ù¼;ý<>¬ðlDÂoÂkD3õ#¼­ú<C2AD>®‘<£¸Ödóîô?²Â_° ¿ ¯  ÉÔ<C389>ð¶ê=:HòŒàZ“ý»F^ ²~¦~„·U<C2B7>è#É3Z€kMöïVø »ÿˆ]H8Bxm€ÈÊ™úÞV5¢›$Ïhnœ¾…×dð”?bŽ^ ²Z¦®„7W™è)É3Z€§oá5Ù<ú<>Ø‚„ã„׈¬“©+áÍU):KòŒà¶wñšìýGlAÂqÂkDVÈÔ<C388>ð¶ª]&yF pÛ‰»xMv<00>;û<>p´ðÚ‘E3u%¼¹JF¯IžÑÜvâF^«ÀCÿŽýG8Exm€Èr™ºÞ\U£ã$Ïh~sÊ^^«ÀCÿŽýG8Exm€ÈB™ºÞ\…£ï$Ïh~sÊv^«Àƒþw›<77>p¢ðÚ‘æ™zÞbµ£ï$Éhf½<>×ppÏ?eçN^ Ò6SW›k„èAI2Z€mºØÑ³óM„׈4ÌÔ•ðæ$:Q’Œ`›ü›zù<7A>z^ Ò$SoÂ[lœèGI2Z€2oí¥=0èQxm€Èé™zÞbãDWJªì<>sw/çQA¿ÂkDNÌÔ›ð*zSR `·T|6a áµ"§dêMx‹<78>*© p§$Û|Iê ¯ 9.S‡ÂmÀèPÉ3`€}„oöÙj„E…׈‘©7á-6l
t«ñSfÀ{
Ùò³Ïë¯ 94SoÂ[läèYC¨Ì€²ÎöŸMFXYxm€ÈA™zÞbƒ§@çEe p¨ð=D;ŒÐ\øÌÙ3S‡ÂMzï_iå,:`€#„o#Ú^„¶Â'¯È>™:Þh²èÈYóøÃ›qœ,7``Oÿ÷¿þ£X¢[”
‡±˜ËЄSo€S„ï$ÚX„†Â§°È<C2B0>™:ÞhRàÑjÊÕŠ<C395>z^2f¢»<C2A2>HáÃOŽNôØéIxg•Ot÷*¼ãê •ð(ÒéÜ1­FîbŽ>fJ&ºW9RøÈÉŸè.h#|?Ñ®"4>‹EvgêPx£Éu
ô²UiÌ<69>Vøe"Ù?у…ÆÂG”,šèñ•Wx×”Ot÷*¼ãê •ð(ÒéÜ1­FîbŽ>fJ&ºWÞïr;ÑÃànö¡wáµ";2u(¼Ñä&½w´qUlÌ<6C>Dø¥i›èÅÁÂÇŒD%zè%Þ#$º“»ÞkõÆIøétî˜V#w1G0UݱŅ÷¯<1C>è±ð;;‰ÐµðÚ‘ÙL}
o7¹<EFBFBD>Þ;ÚЪ4f~GÖLôpc^øÀ<C3B8>„™Þøƒ$ºŸûÞeõIøétî˜Vƒ÷2‡
-UݱՄw¨,”è‘Å‚ÂG—Ü$z,tÃ"ô(¼6@d3S‡ÂM6Ó{w`•Æ k
?”$‰‰£ ÒK¦ñ„·ù ‰îçþ„wY½AþE:<3A>;¦Õà½ÌA‡JáD÷m÷Â{PÖOô ãxáƒGNIôðIÇÖ!ô%¼6@ä·L
o4™M×=nŒ3,-ü¬pýüûî<C3BB>}òýíÙ׋筲ã?úqù ¼Mv$z„dýÎýqù`Ïépg®Þ<i8_ÒæêÍ“ÝíðëÓ=ótQáKâ8‰îê΄÷W½þE:<3A>;¦U’v4û '…Ý·ý ï2É–è!É.áÃCMôøJÄŽ!ä^ r;S‡ÂMfÓ{§fõ† KXó,ïçûû›E{‡|yqñןÿì“óGÂ'BÃ<~øù·øåÅÅlÍÌÏ÷÷<C3B7>­wm‰éöíÕÓ¯ÏKN<4B>~'òÇg¯¯çï÷·gËÍÜ©º=¿bdÿì(™Žîíž,ZžÙBÜõ›tÿ;D’$ÛÒZ{¥ÒÑj¶ã~}º>¢ºKÈï„2–8%\'ûO–ë«ûdÏ«/Ï.gϾ÷üçïÎÿÞÿ>ÓÕ.¸íHô å¿… LôèËeÇ%ÐèCƒA…oˆÜdêPx£É¶ôÞéFZ±aC[ <0B>¸]ït\_ƒúøìõõ% Ç?‡<>Ì¡rþèÃí¶o¯ž.ôè¶èQ\G«KÄß^=½žwáƒPŽ›×s¶íÅð©¨ÍOúõâyx?öžmßѽݓÍÖ«´&{õtýá1;&ÛBä d[Zk¯T<C2AF>Q±Ö©Ù^óòÕˆîÞÔš_¢Ùv¡`ó­ûTs…<73>¨..»Ý¾ív<C3AD>ÛÒ==xDzÂT•=0þ?῎D®3u(¼ÑdGzïwã­Ø°¡‰†'e7å1×Ï=óà¦.òòìòúÒ¶/+Œ×½:±Ù\>¸®O3ûªæº€íêÍ“&å¦S-›Юâéyyv9ÈøYÎfÓUÚìûzñ|ý±1; ÛBä d[Wk¯T<C2AF>ùëϲõ5wÚv­Ã=wGD¹ÚžZ]‡ùíâÀÍË Ü7šð)ë7w’6¼gŠõ8U¥d¢‡*À ÿÙ#2õ)¼ÝdwºîzC®Þ°áMN¾~\>¸zóäº8Í…¯9ô¡aõZô0ïÉ)ÓðÛ«§ïÎÿ6ÌõUîïoÏN™­S›M¹ÚrõHÅÏ¢j<17>(W9.ÙÕÚ+Ul<`­;³ýåWeÃñÝÉœx½åvþ}÷ÇÕ›'וin^ë´†íúÔ¾ÕcÕ£Gw) §êìä=1û¿T÷Ä\_ÿ_'·QxD¶µÕúïð<C3AF>¼ÀÐÂáÈà™úÞnrgºî}£®Þ°á'ždýútïú}ö/É˳ËëG9<47>xF=ðS;n&^½yâ)jr;/Ï.¿^<?ú©kSÿ6?”<>ÅVñJÐSl¶[¥QÊÕDŽK¶EµöJXëËlgý|?| uåj ]š».q¹~²ú˳ËðŽ–¶yüðóÍm¤§•èÁÞ±Óÿö÷ÈM]™§æÉMuÜu‘ÛõzuoôpF¾ÌÊÈ™úÞnrgzï}¯ÞÈá '–¨}yqá"Øà9ôáã³×§<Ç)z¤sÄ®«7OÞ<4F>ÿ>$s?ü|=UG›¤›G¹Z«x%è)j<17>(W9.ÙVÔÚ+UxT}wd¶§>>{>Š:<3A>rµV×åÜ=:r®o#õLõ.æéM®‹Ó®G>„äèg^Ž~{vô<76>¡&#(|-•a3õ)¼ÝdŸt=Œ½’#‡=<3D>ò†A§Õ2›—g—ß^==âl=z6dqèué«7OLF9"ÇÕ­M}Úü ÊÕÆ+A<>¶Ùb•Ösåj"Ç%ÛrZ{¥
ÏÇg¯³õ8³f»É£ÕN‰rµ¯Ë]½¸{T~{¦úÑOŠžeçéÍí¥fkí¼<»üøìõõCØN-&#°ŽðeSÆÌÔ§ðv“=Óõ0üJŽîtÄéÒõƒÔ¼aPöÌù£_^\Z·6 ìÐùèYjÒêykåçéæGP®Ö6sœÚE ÊÕDŽK¶å´öJ•!?ßßÏÖélší#§c§D¹Úq×å<V]ö<Ç¿zóäÐG®EOˆ"“ôö½¥Ÿ½v}Ìüõç?ž|d¾NÊ€™úÞn²ºá0r9ìvèÉÑ¿ïþøøìõ㇟ÃŒtšóG¾^<ß¶ã|ü Yùóýý¯Ï]ï’æyyvyÐí©+›Ç¯\­ùø©1TVV»D¹šÈqɶ–Ö^©2ÄÖòÛv<C39B>$|ðt<C3B0>‘ËÕŽ(Zøùþþ·WO=šIÍ»ó¿­[‹žÝ¿ŽÄSÔdöɇG¿34z*5…¯<E280A6>2Z¦>…·›”®‡AøŒœ…FÛz5̳ԤmþúóŸ«7Oœ<4F>ßvháhx'Jí<~ø¹dqéæ‘+Wk¯=Bí"åj"Ç%ÛBZ{¥JXKn¶wL„3f¹Ú¡U
ªÔ¤áóÖöGá4¶CçéõëÜè-{ÎÄïoÏŽcÑÓ¨&|I”q2u+¼éä t=Â`ð,7xøÍAg@Wož¸ô*Ëåüчo¯žîswçTÝžSòßw˜’²r>>{½gÑÚÔƒÍÃV®Ö<<3C>~¶Û~¨Ú{ßÊÕDŽK¶…´öJ•$°–Ù¶´ðaÓ{,W;ôºœ7~Jàå¸òóñôIêu$²~ÝZôê_ e<>LÝ
o:94]†ð<Ë nú85gÙ²æCœ†=ßsV~{æNj L™¢µÍV®¶DþúóŸNGH”ÚE ÊÕDŽK¶U´öJ•'J¾sÚöÃÆ,8=C•«¹.' /ǹ‡ô¸Iz=O¿^<÷:9=<3D>~þòâbÿ 5+<2B>E…/€2B¦n…7<E280A6>‘®C†c9 nìy¦ã%ƒ•óGöyÁTËž³Ò&ˆ$I<>KÙ›G«\m¡|{õ´Ç¥öö·r5‘ã’m ­½Råɶy»žm_+Wož„˜¤\mÿ
„ßýáqj²f¿‡ôˆIz}K©y*Kä¯?ÿ¹zódÿ¡=o€î…¯{R>S·Â›NŽK¿ã!Ã1 ž…^2(}åË‹‹AÎÄ÷™•?.˜•’-<2D>~ÞQ†”ªn§rµå†ŠçÃì¯vˆr5‘ã’m ­½RåÉ㇟·ÝØûƒÛös×ušd„rµ=¯Ë]½yâ™ê•1ï!=t’þútïÛ«§Y:ç<>>ìy»hí‰ ¬ |œڙºÞtr\ºŽað,7~·Ï<19>B5I•wçßy>>unŸ+`_^\„÷…ȶ¼<»üqù Ç+f›©\m¹x%èþj<17>(W9.ÙÖÏÚ+UªxÀZ6Û*‹Â‡J<E280A1>Ô.WÛ³ÒàêÍ0’!û<ÖiªeÏIúëÓ½¯ϽŸWr¾®·ÞÄV¾ÖIáLÝ
o:9:]‰<G2l?ƒ»óDæçûû¶$a?üüýíYÕÓð}®T»&]äË‹‹îŠK7<4B>P¹Ú¢ñJÐ=Õ.Q®&r\²-žµWªTñ€µT¶Õ-(.j•Âåjû(T“lùøìuw§ù‹NÒëûI]¦“¨(Z¾ÊIÕLÝ
o:9%ýŽŠ<G2r?ÃÚç\Û½ô~‰lêÐ‚TJ¾1dÊdóð|.¯ÝSí"åj"Ç%ÛâY{¥ÊXËc¶#ü€l˜ªåjw^—ó¦I›Ú÷<C39A>^Û§òÇÕ$[ÑÚ>ã6zn<01> _ߤd¦n…7<E280A6>œ’®Fž#9Ë ¡ísMÌÍ›Rã…ƒSWvOÌo¯žº&<26>æÎ‹fSv×<>W‚î£vˆr5‘ã’m嬽ReË㇟}{f°­€Á‰[ÃÔ+WÛ§æã³×á-/²;_^\ôrš¨}j~\£“„9ôáÎRÒ®ç&°¾ð•MêeêVxÓɉéz`¤:˜a³ÐÐ<>׾¼¸ïn‘ýóøáçkwNÌwç‡7µÈ)ùëϺxcÈæQ)W[!^ :xˆr5‘ã’mÙ¬½R%ÌÕ›'ÙÆÀ€f»À¯Ç¶)V®vgÁ÷·gj`¤—¼<»í­îò–üùë϶=ľ÷é ¬/|M“b™ºÞtrzú©fä,4„Fãt[JæñÃÏÛ6kº8ß=1\>01¥F?üœÿÅ 6£Æ†W‚Ž\¢\Mä¸d[6k¯T sþèC¶10šÙöÿùþ¾Z£¶©T®¶ûTÈ}jÒc*½õàÎò“TzÉ㇟wÜØãô¢„/hR)S·Â›Nš¤ß±‘íx†ÍCh4»OOlÇKïÙQ±6u;1¯Þ< oX‘¶Ù]\>a}?FÅ+AG.Q®&r\²­™µWªœñ€µX³<58>ïŽÍS¦\m÷IпïþPè(%ßz0uâÎÂoÿ”’<E2809D>Y‹žy@váK™ÔÈÔ³ðÖ“&ézx$<¤1³Ð(ÇŽ³’_ŸîÙG<C399>é®bm÷;R5Ÿ½N{¹L¹Z`¼tØ"åj"Ç%Û‚Y{¥ÊX 4Ûò?ßßõR£\m÷é<C3B7>3é=½W¬íž¡®œKá7’t1C<31>@áë˜ÈÔ³ðÖ“Véw„$<¤a³Ì ÅŽóï”Jéëú˜Ka2rvW¬¥š˜6<CB9C>V‹W‚[¢\Mä¸d[0k¯TiãkQf›Ý GK¤@¹šsül.ùœÝ]Éóý홇ªIïùøìõ¯O÷r^…’ _Á¤÷L= o=i˜~GHΣ3KŒ¢A8ã–¡ÒQÅÚŽëÕ/Ï.Ã[Rdé¼<»Üq¹,ÏÄT®¶f¼tÌ"åj"Ç%ÛjY{¥JX 1Ûæ?.„<>‡’é½\mÇE97<39>J±ä<Ç?¥VíË‹‹ðVi’—g—»_ =<17>¤Â—/é:SÏÂ[O¦ëA’ó¨ÆÌ2㨾ç Wož„w«ÈÊ×Ǧ4Ôª‰ä¼š­\-<^ :`ˆr5‘ã’m©¬½RuWÌ3ø÷æÒfÜ€_s„Oý_”û÷Ýn •zyyvÙÑÙÜŽêɇR/<2F>~Þö£1í$Â…¯]Òo¦ž…·ž´M¿ã$çQ ›Q};Î>l¾Kí¼;ÿ;ó©·Z5‘´k¾1Ãã• ³jï‰+W9.Ù–ÊÚ+U<>Ï&  µm+=
 UÓo¹ÚŽ‹rn •Âùøìužüãf¨'Ê€ï‘O8I<38> ÂW-é4SÏÂ[Oš§ßq’öÀÆÌ㨸矽ïP‘aŸÏ£VMdÿû¯×Ÿ°ÊÕ2Ä+AG+Q®&r\²­“µWªäñ€µÕlû‰b´¯<¼§ôÔªÉÈÙQ3õP«æÉ‡2ì5ó<“H"|É’3õ,¼õd‰ô;T2Û€i=ˆŠS«&òøáç—²<>w«U9ôþë•ç¬rµ$I[r¥ö¶¸r5‘ã’m‘¬½R%<25>¬­f¶<66>¿¿= …Óc¹šZ5<ÉŸ˜m†Šä¹
$¾^Iw™zÞz²Dú*ÉoÀ4DÅ©U¹ó‘MÙ¦§¹)’ä<E28099>!ÊÕ’$ùÇúj<17>(W9.ÙÉÚ+UþxÀÚ
¶ýXõθõÇö”˜J‘œWäÌP‘ÛQ±ì#|±’¾2õ,¼õd¡ô;Z’Þ€i:ˆŠsÒ-²{<ê¤{ÛÜT #’ç<E28099>!fhžx%è8E ÊÕDŽK¶²öJ•?ïÎÿÎ6$êq¥%$eÊÕ -©®Èížžf¨ŒkÀ<6B>ÂW*é(SÏÂ[O–K§£%ÿ˜vƒ¨8'Ý"9ŸÏ³mnzqŒÈ>YmÎ*WK¯¤D¹šÈqɶ<Ö^©ºH’Ÿª¶ý&ñhµ¥ÓW¹š‹r" ¯È™¡"Û¢b Ø-|™’^2õ,¼õd¹ô;`òá€i7ˆ*ÛvfñãòAxŠ þœ<C3BE>Ùcøùþþ㇟ÛH$OÂ/h+WK•ðñ<C3B0>Gí"åj"Ç%ÛòX{¥êzÃ1pTT2Û¶ß^= ï÷òé¨\ÍE9‘ÌOÌ6CEÒ¾éH+|<7C>’.2õ,¼õdÑô;fòá€i7ˆÊÚvZ¡FdÛóšÂ§ç˳ËðÆÉ–—g—<67>Ê”«eKª Ž@µ‹@”«‰—lkc핪—(ó^Èl«þútÏÅ–ÒK¹ÚŽJãDFÎ÷·g¾˜ÌP‘Q±l¾@IþL= o=Y:<3A>Ž™.rÀ4D•©‡9´Ú!vnª<6E>9¨v%ª‚ÅT <0A>W‚–/Q®&r\²-ŒµWª^âk qB˜®ËÕ~}ºç¢œ žóG2œÍ™¡";òøáç—2LU ›ðJ’gêYxëÉÒéwØôrœ£¥ÅªlÛÙÄ—á}'’ù6±¨éùóýýð6Éœ¨‡"ÚˆL¯-_¢\Mä¸d[k¯TÅ—æjEȳNº(WÛvQîã³×á (2ò¹Ý3ôÝùßá<C39F>#’$<24>~þõ鞊5à7á«“dÎÔ³ðÖ“Òï°éèP‡J‹ATÙìyÄ÷·gá'’üvÎ<76>¹ióNäΜ?ú°íBÙÊsV¹Z†x%híïåj"Ç%ÛªX{¥ê(_^\d½›mO÷®–üåjÛ~¦~{õ4¼õDF¾"g†Š”—g—ƒ_x6…/M’6SÏÂ[OÖI§#§£C-Mº¦ªÙ“·úŠü–ïoÏ2”¾üßÿú<C3BF>«7OÂ[C¤ßÍÖE§­rµ´ü• µ‹@”«‰—lKb핪ÆÃ1‡G¿f[Ò³²×L§åj?ßßwQN$í+~\>o‘„ ¹d¾.IÎL= o=Y'ýŽœ¾Žv¨4éš’<E28099>Axž¹ÈžçYzž?úÞ"]äÇåƒði«\-I%hí"<22><>Ï^+W9"Ù–ÄÚ+U<>2àA¾1››mIox\3ÉËÕ¶<C395>õ¿<» o:‘<ÉöÊ3Tä ¯Ýl_¾ÀjÂ%I˜©gá­'«¥ßÁÓ×Ñ•&]SÒì¹Ã¿ïþï2‘„Y¹ôeöÿRú"’ù<15>ælæŒüJÐÚE ³=»~“*W“î’m=¬½RõXke¶ =ZmåôX®æ%ƒ"I°æºœÈ¡ñ3¸-|Q’l™zÞz²f:?}íhiÕ;ÅlÛ´õì&‘ýŸß²fÝ‹·ôŠ$¿¦íRvò ûJÐÚE ÊÕDŽK¶Å°öJÕ]<`­‰Ù6ô(û•“¹\m[A£³~‘ͼ<»\ù‹IɱÈqywþ÷˜^€Má+’¤ÊÔ³ðÖ“5Óïøéñ˜ÇIÃÞ©Ä=b"Mn[mz^½yÞ"}åüч5ïëô­š<þ´vˆr5‘ã’m1¬½RuOÆ8Ýlëy”ýúé®\Í»bEzåÁÊ3Ô<33>‘}òý홟‘€j¹<>©gá­'+§Ó!Ôã1•¶TÃì)ƒg7‰ñ¤¦Õf¨'Š$<ˆrµüó• µ÷Y”«‰—l+a핪Ò#IIG¶ýØ0ª×OÚr5<05>"‡æË‹‹ÀS{3T$í­£@ZáË‘$ÉÔ³ðÖ“õÓéêô°ÇIÛªaö|Á®ºH†÷<E280A0>Îþßßž…ü’yyvùןÿ$Ixk”Ìš<C38C>ñÅÚE|%hííråj"Ç%Û2X{¥ê1ç<31>>d$Qç<51>'}•«Y÷D’|1™¡"'Æ›åÕr<>©gá­'ë§ßQÔéa<C3A9>“¶TÃæÉ‚G«‰$¹86û_¼;ÿ;üãçÌ㇟ÿúóŸ<C3B3>Ï^½x~<7E>o¯žþûî<C3BB>ÛÙöú¿ŽòÛ'ú÷Ýß^=½ùÈ_/ž_¼y_ìU²ÍÿB¹Z øJÐÚ[-ÊÕDŽK¶e°öJUéÉÒ…¿.[Ùö{þåÙexŸ˜œåjÛÎøÂ›K$yfÏãÖ™¡î!=å¶Ð//.n_¿º<C2BF>«7O6¯w­œß.¯ý–Í[Mm ì™Ñ.¼›Â" ÏÔ¹ð”õÓéj{Ø}Ô»Ù3[ê"I.ŽmþýŸïï‡ðT9ôáË‹‹ïo϶=5kðüûî<C3BB>ëKjá=•ükmg®rµŽ2Ú+A7?f¥õA¹šÈqɶÖ^©:<3A>¬g¶Ñ®Þ< ïÐ1ÓQ¹šEOä¸:j34$/Ï.¿¼¸¸¾]ôÇåƒðë`<60>ùqùàºìíëÅó<C385>Ï^«N_ù%@fá ‘Äfê\xJH:EmÛøï¢<C3AF>z7{¦àÎ ‘}òýíÙ¢'Ú³ÓóÛ«§á<C?üüñÙëÁ¯ƒ”_Ÿî}{õÔ#×V{<ÈæßW®Ö×b¾Ä¨È ön‹r5‘ã’m¬½RõX;Ô¶_~<7E>G%a¹Úìñh5‘$Õ/fèî¼;ÿûêÍ·ŽîίO÷®Þ<ñšŒmßÂá_ÄÀjÂW! ÌÔ¹ð”<>t:ŠÚöúÇ?Hê¦NÍž#¸ÕWdÏ|yq±þ•1·æ=~øùëÅsÄŽÎÕ›'ƒï‘E½ÉW¹ZwÏÜ+yá´vˆr5‘ã’m¬½RõX;Ô¶Ÿâá]9lz)Wûøìux[‰äÏ˳˥¿•ÌÐÙœ?úðíÕSåͯO÷¾^<ùÛžlßpΙ…¯B•©sá (Qét µ=ìõ<C3AC><EFBFBD>,ÔM<C394>š=G° ’äD{ó/{¨BµVùöêéÈWÉV¸©só<73>+WËœwço›,S-µø)W9.ÙV¿Ú+UÉ瑎–´fê×§{#ÿOåj¿>Ý o(‘^2{uÈ ].<2E>~Þö¨UÙ3ƒ­yÀŒ,| ’<>L<EFBFBD> o@‰J¿©í‘‡|„²P7ujóì@1ÌŽ¼<»üëÏŽÈÇg¯¿^</<2F>wç_¢ð¾È“Eϲ7ÿòÈ7ãÿõç??ßß¿²T)¿>Ýö}Ûj“ZMÞ’åjŸ½®}Mu<4D>W‚n~ºJ_ëÊÕDŽK¶¥¯öJÕu<c³ Õû¯ÁÞ“­\mv<6D>|{õ4¼¡DzÉ¢“Ú ý-îm˜Ÿïï<C3AF>y9n…wøi…/A²~¦Î…7 ¦Ó±Ôö°C> Y®§ºã¼{w^ž]~yqqõæÉ¶äßw\½yòåÅÅȯ§üqù`¡³ìÙ6ójÆþçÿùöêé:£zÊa͉|õæIí¤<7b÷¾Aùõâù÷·gᇱ\y%hí"åj"Ç%ÛÒW{¥ê=‹±<E280B9>Ù&òhµðtQ®6òÕ•mùëÏÞ<7F>ÿ}}å·WOÿ}÷ǰùþöìöͤá]ž¯Ï—›ÔfèM^ž]Î^ü”óýíÙ€? ¶Ý‰Üjæi…¯?²r¦Î…7 Ä¦Ó±Ôð°?ÅY®§ºã¼{3<>~þøìõ÷·gî;4?ßßÿøìux®ŸÙÇà/7C¼ŽñøáçC/‹5iÿÞÔb?. ¸øo«<6F>\®
”«•/šá• ›­ÒV—rµ¶9ôḠ/šð§ ÷˜ëpv$ÛºW{¥ê=°¶<C2B0>Ù&êý§`<60>ä/Wûqù ¼•òÜ=úýí™ç«ß™Ÿïï_½y2æå¸¥Ÿš>ÛÚáyý|yqqâ(<28>J;}
<EFBFBD>v9ÎÖ`Xáë<C3A1>¬œ©gá­'±ét8µ=ì¨O1Hí¬¾8ï¾<C3AF>óG®Þ<Q¥vb~}ºwõæÉù£áZà^ÎÍ?;àµë—g—{ÎÊ&m^Õž“·vÒìèZt,ÕÛ£¼^îÊ?¤ü+Ak<17>(W[áGŽŒ“¥çΰ+U<>$,qLe¶q~¾¿_ûTIU®6;N¾¼¸o¥Àœ?úðíÕS%jÇå×§{_/žu9îzÌ,÷}´ùgG{#É㇟goÑÝ–&Í^ÉþM7TÅé¶ÇÚGw°¸ðõGÖÌÔ³ðÖ“ðt:œvì!‹vVGfOŽF;ï¾]¨~e©X¾½z:ÈÕøå/°ù7¯Þ< ÿ¼n¸kÞÔ㸳1‡ºD¶í˵v<C2B5>rµë7V„Ìr)ÿJÐÚE ÊÕÚF¹ÚàYzî »Rˆ¬í6Û8£ýÌΙüåj£ÕÝä¯?ÿÙV+‡f´{Hga¡:Ô¯‘ýßtÐbE,nÏ™Þé«eÛFLtGË
_|dµL= o=É<>NGTÃÃÿ,å³tgõbö¤`´§O?~øÙ6ÜrùùþþWr–»—sð[­÷©Uk±çÎVªnyÑ÷<C391>.WóJЮm~¨J_ÖÊÕÚÆïäÁ³ôÜv¥ª‘m<E28098>?
6IÌ6ËÈϱO•äåj>M]¡ÚrçÒ…æõl«†ØÕòòìrŸç¶X rg{^½y2È´]úe@Ná‹<C3A1>¬“©gá­'ÒéˆjxØ>Nù¬Ð_]Ø<#í
ê_þã+d„»È—8Åžý›ãìÓÝY«Öh!×îæç¦ÎEŸ R»\Í+AûUûËE¹ZÛ(W<KÏ<4B>aWªÚ?ׇMÞw‘<åj³ã¤÷“…¥ß3(‡æÇåƒîJžEKLÒßýþa×É˳ËmÏoØÂúsÚÖ¾Ò²ÎË€œÂWY!Ñ£ìTá (ÒéˆjxØ>Nù¬Ð_]Ø<#ðD<C3B0>}Ýo)Úhå‡Ö½g[r<>KjÕÖ±»‘Ç©X›½ »P ÷¾õ[áŠW‚vªvˆrµ¶Q®6x–ž;îTeâk›fdœ
‡üI^®6BeÑMÞ<4D>ÿ}g=Œœž_ŸîÕ~,ö¶ß«KLÒÞOç[ÕªµXG·{ÚR±¶èË€œÂWY:SçÂP2¤ÓÕð°“|¢òY§Ë’›=(ã:<3A>~>èEÑ}Õ<>}š±öíä³áiÞª¿>Ý ÿ¤+D­Úšv7õ kKÌߪ׷77jÿr¨úJÐÚE ÊÕÚF¹ÚàYzî »R•‰¬mšm<C5A1>£·ÌyAærµ¡ÞwpÄ ¤!Ý”Üþ­WûŠÜ¿ÿ«.æwF­Úš¯Xó>PPøÊ#‹fê\xJ’t:¨v’OT>ëtYr³§á]³B^ž]îùÐè.êÏ<C3AA>MZ¸ªa‰{9Ǽ+ÛÅ
³rQ;Ú¼ÌÎÔŽ|yq±Ð`¡\Í+A{T{çE¹ZO«€ÁWªJñ€µÛf›¢ÀIÜÇg¯ |Šüåj#œyziH×ôèΖüõé^ág÷Íþþ?qüÌþÁÚg¾×Ós÷5óvc–ÿ1xÅš÷<C5A1>Âh—Y.SçÂPò¤ÇAÕê˜S}¨òY­×2+yõÎüõç?û¼k ºsú¶ûúØù£áà—r—'éî»8<1B>Pž¹µoÄ^ôŽÎÊÕ¼´Gµ‹@”«µ<C2AB>r5¢T]©¾¼¸?†¶ñ€µÛ~Kº?ßß/s*š¤\m´ûû½<>týäŠ\áÒ—æi¶Ã?æ¢yüðó<C3B0>Ë&æúv´y™/߃ž´Ý!À‚—Y(SçÂPò¤ÓAÕê°~´ÂY³×Òª·‡~ú<06>54Ú‰ö:¯¨=Iw_k40ÙeÇÚX~ëd¡QWoo{-`½Í÷Ú¯-¹“~åjm£\<5C>(UWª’÷ïÔ«ë>Îl#¨ê¿¾<C2BF>RæD>s¹ZáR¢=_28ັ„Í[f"o¦ùpªõî|®¸¹¹´-_ûÁ›K<È,|Ù‘%2u.¼%U:W­;áG+œ5{-§Ù<13>×ÿ=ýq´œmM]r¤­óê<C3B3>Þ ]|ã^w¶uAÉ­Õö­Æ)W+?BŠ-Pµ¿š•«µ<C2AB>r5¢T]©Jn;nûy0<79>dÛï„?<3F>®Ÿ…U¦N#m¹ÚÏ÷÷ÃgѨU[Ùhw¢5ŸÚ›íÛ«§ásý¯rss5;Ú¿öí<C3B6>† %|Í‘æ™:Þ€’*<2A>Ž«V‡<56>óÓÎÊ—PÕë¨G_‹î<E280B9>²f[»êeØæC«^¡Ë¡oS5=Cl눗ÂÇIw/ ¨7‹w\Ä.³‰9Â+A«<16>\G¹ZÛ(W#JÕ•ªä©w±oÉãÌ~ü¥‰7Ϩ/óK/m¹Z<C2B9>ñ툋r!†º"·B¹ZïçòGßâÝnHr‡½ðòì2|œÔþ^Ö¾æHÛL<C39B> o@É–N‡V«ÃÎùé
gåŽK¨ðžÚf?ü|};°óîõ u;góÑ5Îű;\fhˆm}1ZÁä-Ù{î¾çºö=¿•^ Zµä:ÊÕÚF¹Qª®Teª˜~ËàXÛö ¡@]â͵åjK<6A>™ÞOŽ>ßg¡Xß¶ÿøìuø¨ÈÚ W2ï¼lÞn<²—mñóýýª/Œv¾ C _s¤m¦ž…·ž$L<>C«É1gþ€…³~ße³yPæÚãA/ðrú³‚Ùf/yãðìضMWõ
öÕ›'fh6…7ÝV{Ÿï€åj^ Ú‹ªE ×Q®Ö6¶ˆRu¥ªú›jð¬Í~ðÞõývCG™KFiËÕªVÂlkó¡–ˆ@ã<`­ùOÖª¿Cö¬ô3=m뎪¯£]èr<1C>Søš# 3u.¼%[:Z­;í,œõû.›ÍS€2×÷žyt' d¶ý‹mÐxõÀÑ1IsÚÖ)%kM¯÷X—„£•«þ9Ql/¾öæ‹rµ¶Q®F”ª+UáoÌa°6û©}º×ûSP~ûÙSfÄf(W›35–¸=Ÿb=Îú<C38E>ÁlË×+<2B>T®v\Î}0=ê•  ]Žr
_s¤U¦Î…7 $L<>C«É1çÿ˜UÕ}ylžÔ{Éu<Ï<ƒAÞ§\­a»™¡l[<K^¤]â}¾c–«•\Þë½´ö¼V®Ö6ÊÕˆRu¥ª÷‰n2ì–÷ìGîý'ßæú¯\mé1Ó{}ãlÎ}ØñЕ›}X³<58>_ï"ðìiZÛv+ö­½ûeí Gší—2ßÅûlßD÷°ˆðGšdê\xJÂt:ºZvò<76>Y5QÝ—GÉ«©›ùøìµËbIŒðŒ&åjGdØ]­^ÌvM½É»Üõ±1ËÕ¼4¿Ú›/ÊÕÚF¹Qª®Tµ÷ÜõÞö[¨÷Ò£Í'Ê–®iËÕÂ[fÍ5¡ö²<C3B6>Ðì2><’ŸTýr;®Èe¶­kê<6B>Ã$_ÍÀ:Â9=SçÂPr¦ÇÑÕ䘻ø¤U؃IÔÛ@Ÿ<>§6å±Ù ?.„<><E2809E>
Ú6Z½yúíÕS“4¹Ù*YŒ´Äõ±1ËÕ*mhV}%hí‹ÞÊÕÚF¹Qª®T%?Ô<>ßS]³Ÿ÷ã³×á}Ñ|ñ/óë.Þx០·£&<26>Ù^(ö¤\íˆ XdÞ—qn uÊ ã_päÄL<C384> o@I›GW‹9Ñ͇-™ÀL¢Þúf¼TžÙ×c›Ÿ\<5C>0O=ï½ÓÉûíÕÓðÁÓ<ÊÕ–«y%hrµ7_”«µ<C2AB>½¢T]©ÊßÂ3ÔÞ÷ì'ýùþ~x/,Q™¯\mé‘Þ2ÍóåÅÅ8«Ar³Qã[õ&ÊÕŽÈìMXíÆKMÞz7<7A>Î~_D·=°ˆðGNÉÔ¹ð”´éq€59æ^>lÕÄvbõ6Ð7ãÊX*#\<5C>U®vh^ž]š¤](¹ ·åjmËÕ¼4³Ú›/ÊÕÚF¹Qª®T%ŸÄ5ì]c³Ÿ´@‡Î®üÊÕ–9á-Ó<?.Œ³äWþö¢ÙS€£ÇÛ쟪ñ;äÎ;°Z=N2ÛGÅ&oÔ)<"|Á‘£3u.¼%sz`-¦EOŸ·db;1ƒzè{¾d0ºáÇ5{~ýòì2|œ4ŒrµC£¦´#Ì_åj'.t³ƒ¤Þcʼ´öæ‹rµ¶Q®F”ª+Õw ò€µÙÏX 7·ýÂQ®¶ôà o™¶yüðóë@Gê<47>™n¦á<C2A6>a’Î^67IáJ‹r5Gø‚#Çeê\xJæt:ÆšvGŸ·db;1ƒ.Sd¸É[N7Q®ÖäÙDíFÍÌ^Ã,6•«-Q®VàóV}%híodåjm£\<5C>(UWªªÏãðʳŸ±À(Ýö(]åjKžð–Éü¨+N·Ùß^= 'mÓpÈ<70>0I3,†=‹=Ê~¨góÂàÂ9.SçÂP2§Ç6%Þq݇ñFØPvÞ<76>MÉ‹ù+—«½;ÿ;üc6ŒIÚ‘Â;V‹Èzß¶;ºÙ«‹%ÄWà• µ¿‘•«µ<C2AB>r5¢T]©f—‹Ÿïï?~ø9üØ–þYUiõ˜ýt~ïxxl<78>O·cpf?á-Ó6ÊÕ²)<©oÒpÈ<70>0IÍÐ^Œp§ƒ ã_mäˆL<CB86> o@IžØ”@xÇHtÆ«·<C2AB>¾§9ÙTÝrZ³\­X‹™¤áj­rµÓºÙqRïE^ Zûû%äÖ실r5¢T]©f—‹¿†ªTÙÖ‰…­V©²%g¹Z™æ½‰ßÙŒ0ê~ïþm¯ëíËfO]½y>ŠÚÆ€„A„¯6rh¦Î…7 $O<>clÊ!¼ï
$ºãmþþÿòâ"¼_ÚÆiN6%¯çߎrµCc’vd„·(W[¨\­À§®÷JPß/+4i™--ÛÍD©ºRmûÊøõ鞬õbös(üØQ„_ãî™áC¨LóÞÄï‡lFu ¿t
ÿ¶¡ª¼žî
4 aá«<C3A1>”©sá (ùÓã›rﻉîÃxU/þߎӜlÊ<6C>:åjŽœ}™í¬JR¹Z«…nÛ§W‚¦R~:¯ß…·´l7¥êJµíû¢À<C2A2>„A¶Â·u_<75>û8®Þ<Ù1>ËT¶(W['~?d3¨kø¥Sø·ýŽïèÖƒŽfÊHû80ŽðÕFöÏÔ¹ð”üéq˜Mi„w_<77>D÷a¼ªÿo¢&¡ò£N¹ÚA©º<C2A9>UXùMUåj­ºÙ©]ïæß®_ ZûûE¹ZÛØn&JÕ•jv¹¸Ž¬uaöx'×¶Wi׫lQ®x7ÇÊíÌh£®á7Náßö;žÞzÐÑÌ·ÖûÅÌ
_mdÏL<EFBFBD> o@é"=³)<29>ðî+<2B>è>ŒWõâÿMTÂ$4{UÿëÅó2i~Ý»ö<u/gwêU^ýåj‹–«øì•^ ZûûE¹ZÛ(W#JÕ•jÛ—Åu¾½z~„ óñÙë^¾÷4ì£Õ*U¶(W§<>mÔ5üÆ)üÛþ:~á÷ev@Öøa|“b¿<18>mÂWÙ'SçÂPºH<C2BA>ÃlJ&¼{OtÆ+Ž£&¡ÝW¿«¦m‹Uš§&iwJ>Gâv”«5¼¬½mI,vÿo¿¯­ýý¢\­mlf¥êJuçéC<C3A9>§Ûùùþ~ߌ{šý,#<Z­ReK†2ªÂÍ›ª<E280BA>¹íÎ9^5 ›+|Z5Œ_øÝÙì¯w燤†i8<38>ÌÂWÙ'SçÂPºH<C2BA>ÃlJ&¼{OtÆ«zñÿ&*a
¿HÕÑ•±æéìÃÚ 7Ú+¿«¢\­íeíÙ%Ñ+A“¨ýý¢\­mlf¥êJuçéC<C3A9>Ú§ªX+ü
×;­Vé—†2ªÂÍ›ª<E280BA>¹mÏKXÅÒ¶¹Â§UÃø…ß<E280A6>z—~KÛ) ¤¾ÚÈ<C39A>™:Þ€ÒKºfS>á<>Ø{¢;0^Õ‹ÿ7Q®–Pøuª¾.Ž•Ÿ§.Žu§ü®ŠrµÊÕ
´Àî|yq±Ä×Asµ¿_”«µ<C2AB>ïk¢T]©ö9ƒð€µœªþ°ÙçÑj•~ùg(£*ܼ©Ú™Ûö™æõÒ¶¹Â§ÕÒUÊMG<1C>•ür;m§0<C2A7>Vøj#»3u.¼¥—ô8Ò¦|Âû±÷Dw`¼ªÿo¢\-¡ðëT}]+?Omwg³¿~¾¿><3E>F¹Zó™;æ+AgR¶%®ö÷‹rµ¶ñ}M”ª+Õ>gßßž…gÃÔxÀÚà<C39A>V«TO•¡Œjó¾½zÞ2õÚ™Ûö™æõÒ¶¹Â§•:²ò_m§0<C2A7>Vøj#;2u.¼¥£t7Ò¦”Âû±÷Lc›ýý_ãâÿM”«%~<7E>ª¯‹c…7é®cû»;å/Ø~{Ö|L^®¶ã• öv·åüчü¯­ýý¢\m…Y/•2eUu¥Ú³_j|ØJX›=þq­¦\méáT`,%lgn ÿ½’¶Í>­ÌБþ^¾NÛ) ¤¾ÚȶL<C2B6> o@é(=Ž´)¥ð®ì=ÓØÊŸt+WË)ü:U_Ç
oÒ]G¹ZwÊw,1&ëmE5)W«w#pw¯­ýý¢\­m”«•Ï”UÕ•jÏ~)¶¹m%™:1{ð5ž3¼ç£Õ*<2A>ÉÿÇÞãX‘tÛš¡´……ÑÂh„TN ©$„Ñ£P !a4N9 „„Ú¸  'Àè0ÀÚ<>§§óT¯n<C2AF><§òdFäÚ{íïÓrî›S±WìˆÌˆÜ¡HÃo<C383>Óg¸Žü~C¢¾vɇ#´2Æ×å<C397>úa‹|¶A“jÉ‘ˆr)]²µÀÈ{3µZmìÝ”«<E2809D>®éÆ<C3A9>dC±¿vP®6È¥CÏœ&´tŸµïŽí<C5BD>7ž!)W³W‹ŠëL5¿k<âÝéуOñ<4F>=ÂdË?<})7v³£Õœ‹G(Òð[#Äô®#¿ß<C2BF>¨¯]òaÅ­Œñuy§¾CÂ"ŸmФZrä¢Dʘi-0òM­VûE7åjà<6A>÷C+6Ç<®çßËs©—(WçÒdòüxw<78>O‚ªð¾¾P®ÖW”«Ù«EÅu¦šß5fO!ó°f|´Úä D»N1NÈëP¿5BLŸ397ʇÕè<C395>t«]‡c¸ÞŠ\)é]"œŠ|¶AûjÉ‘ˆr)]¦µØÈ;4µZmìÝ”«<E2809D>®évbû:#Þ9I¹Ú8—=ˆç“ *¼Ç2åj}E¹š½ZT\gªC½0ù¿¿=-op/å=`ÍõhµÉ=“«îØÿß)WšTÙ×1}XÌäô(V•ñr\r<<3C>Ï6è†Zrä¢\ʘl-6ò>M­Vûåjà<6A>ëCº<43>ؾΈwNR®6Ô¥CeN)”è“ ö±½çÆw×”«Ù«EÅu¦:Ô “ÿ»Ù¹X›l°GáÖ¡»”C<E2809D>{Ddê·Fˆé3Àb&§Gù°ê¨t—c 'Àùlƒ®«%Gn J§tÉÖuÄôGÞ¡ÙÕjc¿À¡\ <p}H·Û×ñÎIÊÕF»tèA<ŸÝï±L¹Z_ýùû_ÿ\ü<><”ëÃO®3Õ‘ Êõ¯Ô¬M¶Ö <15>­F¹Úöy•}<7D>Óg€ÅßÛï”ëZ ä$Ø ŸmЕZr䢌J—l-6òÍ®Vûåjà<6A>å“‘+±}<7D>\m´K“·|T‚÷X¦\ !<21>»/×™êÈUဵ¯¯G»&a²©ŽV£\mûÔò˜ß¢ù °û{ûD×bØAN€òÙ]©eFîʨtùÖb#ïPµÚìßüÿüxWÞ)}E¹ཉÍöuF¼s’rµ \šÜ<C5A1>4K¤Ÿµï‚íݶ|€<”ëîËu¦:>AMþ??»<>7»—ξuA¬yÓrëÑj”«mŸ]yÐg€ÅØßÛg¹Ãä$x ŸmÐN-9rQF¥K¶yoz¨ÕÆxãñJ”«<E2809D>Þ›ØlDdÄ;')WÛÆ¥É±Ï'A7Æ{,S®†<C2AE>Gñ€ëLu|‚šüÿþüx×é*™å€µÉF~}õXnàG«yïE˜ ]ç·h>,ÆþÞ>Å…®CN€òÙHÈ D•.ÙZläê¡Vã<>Ç+Q®xob³‘\mŽ><}¹Ò¥É±Ï'A7Æ{,S®†<C2AE>Gñ€ëLuë5ùd¿HwÀÚ¡«öùÃ÷r78ZÍ{×(ÂLè:¿Eó`1Æs௿þÏ£Ÿâ_ˆá“]ætíøñî9 PùlƒZr䢤J—o-0òÞ´Q«<51>÷¢{'ÊÕ ;ölŽeÄûëT”«mvy=ôØiŠ þIP{ó·÷yò/Ê}@(uñ€ëLuë5ùpÀÚÆ?ZÍ{×(ÂLè:¿Eó`1Æs {æyñ¾vpÕ(‚|¶)®–¹<>(©Òå[‹<>¼CmÔjã½èÞ‰¥7dÇþÁwðGT0‰_ñÕuQ®¶ååµÂ³øÈŸõÞè¦\ !<21>Ç@®3Õ²J!ƒ[ˆD¬ºK©s´š÷®Q„™Ðu~‹æ3ÀbŒç@öÌóâ}íàªPùlSY-9rQ^¥Ë·yo:©ÕÆ{ѽKoÈŽýƒïÈ<C3AF>¨àÞON)W“—«ý÷÷/ßÞœÉc¬ðIPï<50>nÊÕòx ä:SÍ™ ], Ê¥N=ãKÂdòßÂ<C39F>j»ñ®Q„™Ðu~‹æ3ÀbŒç@öÌóâ}íàªPùlSY-9rQR¥Ë·y‡:©ÕÆ{ѽKoÈŽýƒï°Ï§à®Oîv¢\mãËë¡gñoÏ_Ëô:ï½ÑM¹B<1E><>\gªÅÅB6£<õ˜¯<CB9C>1>ö$Ï<>w<EFBFBD>ä3ád/xÌo¡|XƒñÈžy^¼¯\5Š Ÿmʪ%Gn Ê«tùÖ#ïM3µÚx/ºwbé Ù±ðóùǯøêº(WÛþòjüD8ø'A½7º)WCÈã1<C3A3>ëL5s‚šüÏ8`m&›”ýþm§ïîÍ7Üx×H>¹g<C2B9>û °ã9<C3A3>=ó¼¸ÞïÄU òÙ¦¦Zr䢼J—o-0òÞôS«M…oo±ô†ìØob|8·âúðn'ÊÕ‚”«YÞ–Dû$¨÷F7åjy<r<>©æOP“ÿ%¬ Ÿ<C385>þÃÓ—'¹m\ª!Ÿ ‹Ü3È}XƒñÈžy^\ï<>wâªPùlSP-9rQj¥K¹yoú©ÕÆïéù¾XzCvì7±£=œ‚9x_>(W“\^'§> :ï<>nÊÕòx ä:SÍŸ ]"ŸŸ]Ê£°¹ ÎñüÃÓ—r£6>ZÍ»TC>¹g<C2B9>û °ã9<C3A3>=ó¼¸ÞïÄU òÙ¦ Zfäî¡ìÊ•r-0ò®´T«<54>ßÓó}±ô†ìØob‡z23ñ¾|P®¦º¼Ÿdö“ ÞÝ”«!äñÈu¦ZY2döÄüíùë8‹‚É–üxwOîÒöG«y—jÈgÂ"÷ rŸÖ`<²gž×{ã<>¸jA>ÛTSKŽÜ@”Zéò­FnŽ¥Zmüžžï‹¥7dÇ{ûùÙeœ'S0ïËåj¡ÊÕø$èP¼7º)WCÈã1<C3A3>ëLuê5ùß{X±ìÔ¯qL6£æÑjÞ¥ò™°È=ƒÜg€5Ï<>ì™çÅû†<C3BB>«@ä³M)µäÈ DÙ•+åZ`ä]éªV¿§çûbé ÙñÞÄf„&ÅûòA¹špðNÎx|tÞÝ”«!äñÈu¦Z_5döÐ|ÁÁ_#˜lÃ÷Ëûe6Î:ùLXäžAî3ÀŒç@väòâzo¼W €"Èg›:jÉ‘ˆ²+WʵÀÈ»ÒX­6~OÏ÷ÅҲ㽉ÍMŠ÷åƒr5íà<C3AD>œôø$è ¼7º)WCÈã1<C3A3>ëLÕ¥pÈÆ<C388>8¬›¼Ì^ãR ùLXäžAî3ÀŒçÀCeÌjËáv\oTvâªPùlSD-9r‘<>r¥\ ŒÜcµÚø==ßÅ0<C385>ïMlFhR¼/#ölýÛ¸\<5C>O‚Â{£›r5„<¹ÎT &¨ÉòãÝ=y,6¬Mþu<C3BE>Ê„ÅÞºa&,rÏ ÷` Æsà 7õ`\ï<>wâªPùlSD-3r÷<72><C3B7>re] Œ¼+½Õjã÷ô|_Ã@v¼7±¡Iñ¾|ŒHK?džÞÉyï¿¿ùðô¥<p³O‚zotS®†<C2AE>Çc ×™ªWí<57>ÙõQxÀÚ¡Û<0F>|[l¬q©†|&Üÿë??Þ•Ûâç3ÀŒç@ÊÕòâz¯²W €"Èg›
jÉ‘ˆ ”+åZ`äæx«ÕÆïéù¾(†<>ìx?øf„&ÅûòA¹Z„Á;9õýüx÷üá{yìNŸõÞè¦\ !<21>Ç@®3U¯Ú!X—i6e k\uõ$ÂLhìm(ŸÖà=N)WKŠë½ñN\5Š ŸmìÕ’#7(WʵÀÈͱW«<57>ßÓó}=?»TmwtÁûÁ7åjIñ¾|P®aðNN}fO"|Ô{£›r5„<¹ÎT‹'(ïÖ=ø´}ñö‘ƒ:ùG>­9³ÎøfL>{Êg€5x<35>SÊÕ’âzo¼W €"ÈgoµäÈ DÊ•r-0rsìÕj㽺¹Òö{Ýñ~ðM¹ZRüНF§¥Ÿc ÞCŽ??»<>‡oóIPû[Á rJýÈu¦êX>´;`íуOò Æ==—ÌÞ__=–»!÷Ó¸TC>{Êg€5x<35>SÊÕ’âzo¼W €"ÈgoµÌÈÝCÊ•u-0rs*¨ÕÆ{us¥í÷º:âýà›rµ¤ø_<>NK?Ƕ¼“ Ÿê°Ù­àäy2#œ,rÕF6ÊõÈu¦ê[Adpk!<`Íûhµ•f—jÈgBcoCù °ïqJ¹ZR\ï<>wâªPùlc¬–¹<>ÈC¹R®EEîLµÚx¯n®´åF7@w¼|S®–ã'¤”«…¼‡;=#Ð~ÔþVpû½nï«6²Q®Ç@®3Uß
¢]97¬õʱÿþþåË‹'r"8i|&Ÿ <09>½ å3À¼Ç)åjIq½7Þ‰«@ä³<C3A4>«Zrä"åJ¹¹9EÔj㽺¹Ò–ÝÝñ~ðM¹ZRüНF§¥Ÿc› ÞÉ9<C389>O‚޳×ìV<C3AC>r5„ ¹ÎTÝ‹ˆ î.$¬×þu±Ñ¸TC>{Êg€5x<35>SÊÕ’âzo¼W €"ÈgKµäÈ D6J”u-0rsê¨ÕÆ{us¥mv¹áýà›rµ¤?¥\-àà=ôÙà]òO‚Úß
R®†<EFBFBD>Ác ×™ª{‘M‘ÕN_^<Ùf!?ùW²ß§u<¤Î¸TC>{Êg€5x<35>SÊÕ’âzo¼W €"ÈgKµÌÈÝC6Ê•u-*rgJ©ÕÆ{us¥mv¹áýà›rµ¤¸>Ô—–~ŽÉËÕÌž¨> j+H¹B<06><>\gªuDÿýýË×W<C397>å¡uÑùÃ÷,ä<>«þz<C3BE>Pg|&Ÿ <09>½ å3À¼Ç)åjIq½7Þ‰«@ä³<C3A4>ŸZfäî!'%ʺ¹9¥Ôj㽺¹Ò»Üãð~ðM¹ZRüНF§¥ŸcÞÉ™<C389>O‚Ž0ÖìV<C3AC>r5„ ¹ÎT#êˆv²9}ôë«ÇÛ_mî.º­æ]ª!Ÿ <09>½ å3Àüò×E¹ZR\ï<><C3AF>Üþ©-€þÈg3µäÈ D6Ê•r-*rgª©ÕÆ{us¥Ñ[ÜCñ~ðM¹ZR¼÷l)W‹9x ~ôùÙå¡R„q®šÝ
R®†<EFBFBD>Añ€ëL5¨”ˆÖVº÷ãÝ=yàqŽVó.©’Ï„ÆÞ†ò` ~ ùë¢\-)®÷Ƥ%@)ä³<C3A4>“Zrä"'%ʺ¹9ÕÔj㽺¹ÒÐ-n€ÑxobS®–ï=[ÊÕÂÞÉ ºÓ”8ÿh”^nÛß
R®†<EFBFBD>Añ€ëL5¨”h'›ZMþò‡§/åQÇ9ZÍ{5*Ÿ <09>kMCù °¿…üuQ”×{cÒ òÙÆI-3r÷<72>™e]‹ŠÜ™‚jµñ^Ý\iÜþ6À?  \-/Þ{¶”«…¼‡Ê{|´ë<C2B4>¾_ÞßòI½Ù­ åj¸ÎT㪉œÖ ãX›üYŽV›c”MvÉgB¿BLŸÖà=N© JŠë½1i P
ùlc£–¹{ÈL‰²®EEîLMµÚx¯n®4î!/À?  \-/Þ{¶”«E¼“×ôÿþþåù٥ܓŒŸµ¿¤\ !ƒâ×™j\5‘“KãX›üÍ·ç¯åñ†:ZÍ{5*Ÿ ý1}Xƒ÷8¥.()Æw}¤%@ä³<C3A4>‡Zrä"3eI¹¹95Õj㽺¹Ò '¼Û`ü€€rµ¼xïÙR®|ðN^Ö¿_Þ—{’ñ“ ö·‚”«!dP<à:S -(rZ2LÞr¬ÌXcÇ<0E>GG¹ZÀ™Ðo<C390>Óg€5x<35>Sê‚’âzoLZ”B>Û¨%Gn 2S¢¬kQ‘;SV­0už¦<C5BE>x¼ °Æ(WË‹÷ž-åjÁ°Ù-•|Ô{£›r5„<Š\gª¾³úä¯yu(cûV÷ÙØÕý0:ãÕ¨|&,r7+÷` Þ㔺 ¤¸ÞÃ<C39E>–¥<>Ï6j™‘»‡ü”%ëZ`äæ”U+L<>§i#ïl†ñÊÕòâ½gK¹ZüÁ{èA3Ÿ]ï¤ÓF7åjy¸ÎT£kŠœV }X3öªûÑjÞ«QùLè·@ˆé3À¼Ç)uAIq½7&-J!Ÿm²«eFîòS¢¬kQ‘;SY­0už¦u °%Æä/°ï=[ÊÕR ÞÉ‹;Ÿ]o£ÓF7åjy¸ÎTÝW©“?øáéKy¤¡Xó®xï~´š÷jT>ú-&õåÅ“DW€R㔺 ¤¸Þ“–¥<>Ï6©Õ’#7ù)Kʵ¨È<C2A8>)®V˜:OÓºoØl‰ñv!òâ½gK¹šÊ¥•–z»ñ'A½7º)WC(l‘ÆI¸ÎT”ý÷÷/?ÞÝ“GꀵÉùúê±<À˜G«y¯Få3a‘ûX–ü<E28093>ïqÊðLŠë½1i P
ùl“Z-3r÷<72>Ÿ²d] ŒÜœâj…©ó4­û†-À–? `"/Þ{¶”«©\ZïªÓ)Û|Ô{£›r5„Âiœ„ëL5b•ê}ÀÚúšíC×Ðó‡ïåÑÅ<ZÍ{5*Ÿ ý“bÉ©ñ§ Ϥ¸Þ“–¥<>Ï6yÕ2#wY*KÖµ¨È<C2A8>A­0už¦<C5BE>سØ ãìBäÅ{Ï–r5•K]Œå“ + tÚè¦\ ¡°E'á:SmSYätÀÚ‡§/Wš6ùÏ9Zm<5A>iòx=fB¿¤XòCj¼Ç)Ã3)®÷Ƥ%@)ä³MRµÌÈÝC–Ê’u-*rgPäôØã]DZg °ûÙK¹ÈñÞ³=ô¼Dz”«Ø»Ù'A½7º)WC(l‘ÆI¸ÎTƒV©Þ—Åïî-ömòþüx—£Õø&<26>×c&4ª×Å’Rã=NžIq½7&-J!Ÿm2ª%Gn ²T–”kQ‘;ƒ"§Çï:ÞРm[€mØÏ^ÊÕ@Ž÷žíˆ ‡ŸcAÊÕø$èÊ.ðÞè¦\ ¡°E'á:S Z¥NþìÏ<C3AC>w=ø$Y{ÀÚä?Ì~?6úh5ïëš|&tMÈbÉ©ñ§ Ϥ¸Þ“–¥<>Ï6Õ2#wY*Kʵ¨È<C2A8>A;µÂï:ÞРm[€mØÏ^ÊÕ@Ž÷ž-åj¹ÊÕø$èš^ðÞè¦\ ¡°E'á:S<>[¥Nþrö<1B>•¬yWñ<57>;ZÍûº&Ÿ <09>Çéu±ä‡Ôx<C394>S†gR\ï<>IK€RÈg›tj™‘»‡\•"ëZ`äæ <C3A6>ZaŒwohÜÎ-Àìg/åj Ç{Ï–r5<72>rµÿþþåË‹'r£‚Ô{£›rµ¾:øþÏßÿBšœ@ZT\gªq«TïÒ¬e¬Mþ“ì7cÇÏ\í’KÞ×5ÊÕ¶K~H<>÷8ex&e¿×><})O'ÒNB>ÛäRËŒÜ=äª,Y×¢"w]©Æx×ñ††nÞŒf?{)W9Þ{¶”«¥+W;R±æQÒ0î“ öŽQ®¶Í™~ÈC-*®3ÕÐ^˜üñì÷WúùñîIîMþÇ?ÞÝó¨ß›¼ÒQ®¶Øº^¾-óÖf<C396>^K~H<>÷8ex&…´ä³M.µÌÈÝC®J‘r-*rgÐuµÂï:ÞP®Ç17ØÏ^ÊÕ@Î~¯}}õXžN‘/~Û‰ÑÊÕìFú$¨kÈ•(Wë(ÊÕìÕ¢â:S í…C½|þð½ñtt’ç<>LÞ<4C>õΓ¿/¼‹(WÛF,ù!5Þã”á™Ò <0C>Ï6‰Ô2#w¹*Kʵ¨È<C2A8>A×Õ
c¼ëxC¹ÇTCõ<N¥.Q®r¼Ó’r5§r5> Z³äJ”«uåjöjQq<51>©F÷Âäï{¼_ðèÁ§ù¬Mþg?ÞÝ“G‘âh5ïëåjÛˆ%?¤Æ{œ2<“BZ€òÙ&‹Zfäî!c¥Èº¹3è†ZaŒwo(×ã˜RŸÇ©ÔÅ%§º v!’â<E28099>–”«%-Wã“  ºÃÞ+ÊÕ:Šr5{µ¨¸ÎT£{áPGW;`mò?ãhµ•‰$<24>½‹(WÛF,ù##¿÷ØX],r§__=fxfÄ;-¹jA>ÛdQK‹Ü:d¬Y×¢"wí«Æx×ñ†zíQ@wä[UI7Çœê‚Ø…HŠwZR®–·\<5C>O‚žÚ#®E W¢\­£(W³W‹ŠëLµA/Lþ‰R¬Mþß/ïËÛŸåh5ïëåjÛˆ%dä÷«‹ENãT> Â2¼Ó’«@ä³M
µÌÈÝCÆJ‘r-*rgоZaŒwo¨×tG¾U•tsÌ©.ˆ]ˆ¤x§%åj~åj|´ZÈ•(Wë(ÊÕìÕ¢â:SmÐ ‡úÚÃÀ9¬‡¿ÍÑjÞ×5y<35>†ßaR,ùÃ"¿ñØ^]\r§òi–á<E28093>–\5Š Ÿmâ«eFî2VŠ”kQ‘;ƒ&Õ
c¼ëxC½ö( ;ò­ª¤›cNuAìB$Å;-)WK]®fÿt¾ï'Aí]¢\­£¸dƒ
×™ªûÍÆL÷lnÛ=øtüÚgûfG«y_×äu~ „Iqÿ–CS¨±º¸äqd„ex_>Þž¿&-* Ÿmâ«¥EnòVü”kQ‘;ƒ©Æx×ñ†zíQ@wä[UI7Çl²°w<C2B0>ï´¤\-{¹Ÿ<04>ß/ÞÏ_(Wë+.Ù Âu¦ê~³1ß@¿¾z|ÈÆC×D<C397>À7;ZÍûº&¯Óð[ LŠû‡°š'<27>ÕÅ%<25>ëH<C3AB>i–á}ù¾×½<>Ï6ÁÕÒ"·y+EÖµ¨È<C2A8>A‡Ô
c¼ëxC½ö( ;ûýòãݽßþ¶F_^<ùçâ<C3A7>úñîÞ Í1§]ö®“²ßk??Þ•§Sä ‡ß@¾…xè Ÿ-õü…rµ¾â’ *\gªÍV©“ÈãEƒó‡ïÙ8ù¿{s&os®£Õ¼¯kò: ¿¤¸Ë¡“±º¸äqd„e¸Þ×¥Øk€^Èg›Èj™‘»‡¼?åZT6\n~^µÂï:ÞP¯=
èŽ÷öl¯mo—Ø»NŠý¤û…Ão ÇßB<ô<>ÂéùÂúO‚ÚûC¹ZGqÉ®3Õ–«ÔÉ¿õöüµÜ„q¬Mêüá{yƒs­æ}]“×iø-&ÅýCX­•<ôùÙE—Äs½ 2 Â2ö{<7B>r5H‡|¶‰¬–¹uÈ[ñS®Ee›ØåþçU+Ìä¾Äó³Ky§t×–{¹pÞÛ³”«Í{×I1~n5èÂá7<C3A1>Sl!Nö#Ÿ­óü…rµ¾â’ *\gª-W©‡.ˆrư¶¯¯¯Ë[›îh5ïëš¼NÃo<C383>0)îÂb<º;.W]oBvbx&e¿×(W€tÈg›°ji‘[‡ì?åZT¶‰]î^µÚx/º¯´å^.œ„÷ö,åjsÄæXR¼w¶)W³ÙB<ôÀÚæ[`ë? j+H¹ZGqÉ®3ÕÆ«ÔÉ?÷áéK¹›°æq´Ú‡§/#dŽÜ‡.¢\mqÿãÑM¹ÚL1<“²ßk”«@:ä³MLµÌÈÝCÞŠŸo-*›…/jµñ^t_iãí\˜<>÷ö,åjsÄæXR¼w¶)WsÚB<ôÌÚã hë? j+H¹ZGqÉ®3ÕÆ«TãÖŽ\ølî»®ôãݽ™#÷¡‹(WÛFÜ?„ÅxtS®6S Ϥì÷åj<00>ùlS--rë<72>½â§\ É–±Ë» ¯Zm¼ÝWÚx;æã½=;ùš?.Ý›cIñÞÙ¦\Íl q²7~¼Ë'A+Ü
R®ÖQ\²A…ëLµý*Õø€µCßÇ4»èo´š÷u-`¹Ú—Oä¶t÷a1Ý”«ÍÃ3)û½F¹¤C>ÛTK‹Ü:d¯ø)×¢²qøòŽHªVïE÷•¶ßÑ…™øÕoŒØöÁ%ˆëéWê~áðȉ¶=¼æ“ n)Wë(.Ù Âu¦Ú~•j\Ê5y[bsÓ%<ZÍûº°\Í©ÞàJÜ?„Å;)W›#†gR¼`€|¶‰¦–¹u¨‚‚§\‹ÊöÈû"©Zm¼ÝWÚ~Gfbü(<28>rµ5G È5èŒ÷æåj~[ˆ‡ž_óIPû[ÁooÎx¬ßK<Ï®3•d•:ùG³ß“?`Í£Ou´š÷u<C3B7>rµmÄýCX¼3<C2BC>rµ9bx&ÅûpÎ\{M°ùlM--rë<72>½âç[ ‰Äy_$U«<55>÷¢ûJ’M]˜ƒë³’<C2B3>(W›#v!’²ßk__=–§Sä ‡ß@N7x½a/þ$¨ý­àö<C3A0>`Œëó< T¸ÎT’UjÁÖ>?»<>·-ïÑjÞ×5ÊÕ¶÷añÎ@ÊÕæˆá™¿ý¥Ô{M° ùlJ--rëPÏ·‰òîHªVã½Üë’lê¼××”«­y®4 Ý 'ÞiI¹šåâdŸòIPïç/”«e7À{¦RÝOþÝì·%‡ª<E280A1>l¾V¯:ZÍûºF¹Ú6âþ!,ÞH¹Ú1<3bn|º½&X†|¶‰£–¹u¨‚‚ç[‹ŠÊy<>$U«<55>ë6õ ©öu¡xR®6SŒÐtLv™Óží¡"Ÿ¾¦eÈ·'S×lk÷ÔO‚Ú<E2809A>eÊÕR› à=S©î<C2A9>'ÿîÏ<C3AE>wϾ—{Ò½¦ëÃÓ—òV¥>ZÍûºF¹Ú6âþ!,Þxh´Þ%<25>›<EFBFBD><E280BA>Þž¿fx¦c2±ŸŸ]ÊÓ©ò^,@>ÛÄQK‹Ü:TAÁó­…Dh‚¼G’ªÕÆïéù¤TûºP<)W[óðe@ºA7&'UƒoH }zå7<C3A5>“n!zFo–Àó? êýü…rµìfìp<C3AC>©„«ÔÉ?íña÷ë+ ŽV—-rO\ËÕ~~¼+·¥»¸‹w¹Z¯ë¬ëMHߢ>ØûkGÒ½&8ùlD--rëPÏ·¡òNIªV¿§ç17!¡fR®6S__=f„æÂ~[›r5ã-ÄšŸ=r$‹÷óÊÕ²› °Ãu¦> >t54;`Í#O´G«y_×ä;EÆÞ^÷a±_×w™9]oBúº[b¿›‘t¯ NE>ÛDPK‹Ü:TD‘ó­EE냼_’ªÕÆ~<7E>³Ó·7g,sbâW¿q]”«¥8.Ne²³>?»<>'R_Q®f¼…Xð“ “<C2A0>uHfÏ_(WKm&À×™J{lÀšMÑ…|­d|]£\mñµÁ°ì÷‹Í̹S—ÉÓõ&$ÎL'1™Õ6Ÿ>Ͼ×'!Ÿm"¨¥Enª ÈÉÖ¢"·BÞ5IÕjc¿5±×ÂâW¿1"ñ¼]úõ×ÿyôà“ö œ„ëY7D¹š÷bÁO‚~yñd2jûç/”«¥6`‡ëL¥½>t0¸©ÛÕwy$É£Ÿ~~¼0UäÎxi¸ŽÁâkƒa±ßî’x®7!Wúü삚ˆÉÎ2ÛÇH½×ó‘Ï6rµ´È­CE9ÙZTäVÈ»&©Zmöoþ¿_Þ—wÊf‡Š¨íÃú<C383>ë¢\måˆ Ò€Lv“屜”«yo!zFoö€æº=øtèSbÞÏ_(WKm&À×™J~÷k|)üò≼ ã&Þy"wÆ£\Íx~»!yÃ$®—€¾‰g?HϾg„f¡ÈŽ\ê½&˜<>|¶Ñª¥En*¢ÈÉÖ¢Á
yï$U«<55>ñÆã M¾’¬¶ ë7®‹rµD߸<C39F>9Lö‘ßníN”«Ùo!Êg¿/Ûï2ûM¹Zj3v¸ÎTò»ß"‚¼Šp´š÷u<C3B7>rµRVÃ>û<>B¹ZÍAúýò¾üZs(rÛ–}¯ f"Ÿm´j9‘û†ê(l¾µ¨qCÞAIÕjSäÓ¿þú?__=fé<1D>ýy{þZž-½D¹ÚIŠð,Ž3ÙAfÚW¢\­ÂâdJÿüx×òFhþ'AͶ»)WKm&À×™*­o©»»tŠp´š÷u-B •ßaR|m0&öó—¬s½ ¹.^ MÁdýxwOž?Ýe°×s<>Ï6Bµ´È­CE9ÙZT‚¸!ï ¤jµ©ð˜r§·ç¯YzÄ;ý(W[oƒ4“½c6f¯kò³‰} Ì><3E>eµÙcšS? j6¨)WKm&À×™*È­o…kAF9ZÍûº³\íë«Çrgº‹¯ ÆÄ~Ô%ëŠ\"ƒ\qà‡ïN/};í5Àä³<C3A4>P-'rß’«E%Žò>JªÍS&~ÐéÐóYu”Æ{Û‡rµ¤Od`þÎØ·7gò̤î©è7<C3A8>=¶åvåO‚:]ˆ)WËn&À×™*È}ïd3¾_Þ—ûS\qÞå1¾®Å,W3«:î67ZìÓo}ÊMþÂó³Kyh›]t¤A˜ì³k¶×·"ŸmTj9‘û†<C3BB>\-*¡ ‘wSRmž5á(ò.'K>{:’r]\Ê^årê'B¤rª}3ñùÙe÷<ôÈ6[ˆÕÒûÖO‚:]ˆ)WËn&À×™*ÎMïdK><})·¨¬B½Èc|]‹Y®öóã]¹3#Ä×b_ý²>åŒ'Àù§pK@˜Ë¡•»eåä.IE€
Èg‰ZZäÖ!$W‹JCä}”WŠÄ‰…ýîDÌ-_ð~ö4º\ÍøØŸï—÷íà H@˜Å¡1ÎÃÉïGw·‘rµà^ö“ NbÊÕ²› °Ãu¦ŠsÇ;Ù’ïîÉ-*«8G«y_×b–«ý÷÷/®/MP  ûÐú|3žç×”2Hµê”//žÈsfœÈC€
ȧ‰ZNä¾!$W‹J(CäÝ”W›'N8Xz³äQaÿ”|\¹š“K3Oµbœª8ÔfûØ”dìÿ åjñó¼æ'AÍ.1”«¥6`‡ëLêvw²1°&Q´÷쌯kaËÕ<¦¸™ïq;!Ä~™¿>ÙŒ'À“>ÚË Uq¨;~¼»÷èÁ'yÂl¼Y¡î èŒ|¶Ù^-'rß’«E%š'òžÊ«Ís'¥N“fé
ûmÊÕº”qº1‡záçÇ»Æ;cƒ]íÿ åj¡8”ê? jv‰¡\-µ™;\gªP÷º‡†Ê]*¨PG«y_×"”«Y.Nõœ;
ö¹·>ÓŒ'ÀI<C380>?|¨^šAº=G¶F<C2B6>Ü úÞD>Ûl¬–¹uiÕ¢ÐygåÕæé‘R¯Q³ô¤ÿf/rŽ+W3¡;}{svd[f@>ÂewÆ=>ö{P¡\ÍïÂ4ç“ E W¢\-µ™;\gªh7º“íÉ~»’NÑŽVó¾®…-WûöæLnÎ ±#‡É.0ÛkZŸfÆà‚S¤[r¤ÌÆé¾XuA>Ûl¬–¹oÉÕ¢ÐygåÕ¶¹”ý%À×W<C397>å]3N,½åYq<59>+W³lôèÁ§ï—÷§B*ïŒú"mwK³d³r5> jVr%ÊÕR› °Ãu¦Šv—[óLÝhúúêqŠÄ<C5A0>å]®æ}°á‡§/YæË9ÔNþùÃ÷ëÓÌx\pÈ'ãt3ŽøïýÈæÈ+Ìê>€þÈg›-Õr"÷ !¹ZTbÚ"ﯼÚ6}‚RmsìÈ&0+  8d»ß£<C39F>qåjÆo[ϯXc¨â¸çÙ+¬Ö|޶»±ÙÍô+W;ò¤ÞøDÁýO‚z<14>\‰rµÔfìØO<<3C>™*àýmÙÛ¿àÅ”«U+Wûïï_Œ¿Gü4õíý/È!óÍ6šº,W<>'À5Ûæ Õ¡±Ýøì÷ëš<^Ý-Ðùl³¥ZNä¾!¤U‹JXgä Ë«m3((7Ç~ýõ8»i{Žïuø_3¹½ÓÅ7û‚Ò<E2809A>¨XÛžãnWx‹sÜ‹œ~-ËÕ<0E>‚ï—÷å†oöIP<49>"<22>+Q®–ÚL€û‰ç1S¼¹-òVQX<ZÍûº¹\ÍûDëã+ýí» GÖû×Ö+Q®¶RT¬mÏqÿ_Þ¯p?öèÁ'ò  ò g3µœÈ}CH®•°¶È»,¯6LŸ¸ÜÛ-~~¼ËÒ{Ž›lü‚X¯Ýó+Öª]¸Õä"µjãžïÿ&åj194²÷×ü®4{PE¹Zj3vì'žÇLó¶v²U_^<‘Ûe¯˜G«y_ׂ”«Mšl¿øz~vy|GNÒ•×ûfG«Q®¶^<5E>|ºµb<C2B5>¡Ú‘ã>©Uûõ×ÿy{þšL(‚|ÂÙF-'rß’«E%²3ò¶åÕ†š‚›csöÇX­a¦±»³Â,ÝCËÕì J¯ôèÁ§I'¤½˜ã­q¡Îf;c~®º–«E> êQr%ÊÕR› °c?ñ<fª˜7´‡.‚E^–*æÑjÞ×µÈåjTŸ\MD莂ë}ËM¹qåj7!35§b<C2A7>¡º’[í­S«vck‚ðF>ál£–¹oiÕ¢"w†rµí]-ÅþBàçÇ»òÞ‰V±VAdzb„¾_Þw-è¸û]³ ôÖýŠ9i ‡˜iæÏ<C3A6>wëÔFvü†ïÃ)W‹Ì¡ –Üö > jöü…rµÑf¢::pNV3U4Ÿ¯˜lXµÕÇÆ
{´š÷u-r¹š÷‹Wúðôe¢‹Q"N²ôçÇ»–ÉÖk¹ºÿ#¥vHNZ ÈegfºúõÕã:µj¿þú?“ŸØP÷ A>ál –¹oiÕÜyóòj« ŠNÙÍ1*Ö´úöæÌxÑ}õèÿºz<C2BA>Ð"¥×õöüõ©Cµ÷L™žSG¨q5é!MæØ ó)W‹Ì¡A‘½×æt¨GÈ•(Wm&ª£¡çÔaå1SEóùŠC9Àk<05>Vó¾®/WûüìBnQÌŠ5ÔQ?ÞÝs]ò~v±o—áYðÙþþ×IÛq¦IN¡Æû“zôàPùœ³<C593>ZBä¦!$W‹ŠÜŽV“[ŠÉµ@<40>øùÃ÷“/ï qúñîÞÛó×ò®ªÉÀ;ŽP{÷õèÁ§™_"èh~^VÒjÛbC¿J¹ZF ×:WçXz<14>\‰rµÑf¢::pNV3U4Ÿ¯3Ù¶ooÎä¦Y*òÑjÞ×µ8åj“>Ÿë{CT¬©ä}jS¯U@å±y]<5D>|úöæìÔ0Y¦dÁðüñîžÇín—Ë<E28094>º`ò9g´ZNä¾!¤U‹ŠÜŽVz[ŠÉ•‘¼ƒ¶Ôçg³¶<C2B3>þ}û[‘“ó;.±'ªìyþüý/êKGRã‚Õ¹û?K¹Z|&óÁþ“ f»â”«<E2809D>6ÕÑÐ<C391>sê°ò˜©¢ù|<7C>Ciàá|4E>ZÍûº¼\­Ô‘†ÏÏ.Yão©ßþf?Ÿ<>+Wûïï_ŒËüŽëÏßÿšü<C5A1>ê«//žÔ̱É;¢—\<08>|Ϊ–¹oiÕ¢’ÂyóRk«TJÀäú¨ÚñM<C3B1>|úüì‚¥÷ýüx÷ë«Çuj`& 9Ö¬²'-•‡)Ô‡§/ªÝUa×ZõÑ<C3B5>ý_¦\->‡FJö¾;Þ­f“åj£ÍDu4tàœ:¬<fªh>ß`²yÿ¾ýMî›™‚­æ}]‹_®Vä{ Wb<57>¿<EFBFBD>¾¾z\¤ ²×Ÿ´±ÈK¸‡ôÏżî=Hÿ¾ý­È<08>Ôd^ ¸ä@äsÎPµ„ÈMCH«˜É›—Z[¥R&WIe<49>oz~vùùÙÅ¿oc¾R?ÞÝûúêñÛó×ÕÞ ›üª`÷Z|‹l·¡Í[Ø]ôí͙ǓßÅúüìbÒ™qÙì%OÊÕj~ÔL”«<E2809D>6ÕÑÐ<C391>sê°ò¸i‰æó>“-ô0?Ž‚­æ}] U®Æ7¯ôáéËßDÇõýòþçg¥öå:ðýß)»[~¥G>Q´ÖWlÊMn¤‡º#€¾È§<C388>qj9‘û†<C3BB>V-*Yü‘·0µ6I¥4L.
JífLêуOþþ×Ûó×ÿ\üÑQ__=þ÷íoÝ¥zõªßÞœíüó÷¿*¿Öýùø!Ûå‘FП¿ÿuèAš³k]y¨^iròìw<C3AC>¥\-1‡ÆŽ¼ ÐQ®6ÚLTGCΩÃÊãq^4Ÿ÷™l! <0B>È'r<>`²…r는«EâÏßÿúçâ<C3A7>ooÎxCm™~¼»÷íÍYÙõ~ÇÙuÿwŠìàJ|£d½~~¼ûåÅ“šƒ4]?ôE>íŒSKˆÜ4„´jQId‘¼…©µI6¥arQPí땵ûØ•*ï‹®×äëÀ#F({WzôàÓîEl^ð¼u7¬ò®õ¤><}9z[lÿÇ)WË¡¡”½‹ˆr5„hô5qý°¢\m3&ùöüµÜ=ãr©hi`|]KQ®Æ!NGö¬6Óçg+ßWýòâI¯wT¿¾z|ä±›wü;ËÇ&—ÂýwHÙ‹[ð-yßÑ£Ÿ:ŽYH<>|椖¹iiÕ¢’Ë"y#Sk|6%cr%ï&„ÒiÄIM“+w¶¯<C2B6>|Ïww†¡|J®ï—÷ÿ}ûÛ?|xú’<C3BA>ëIza¿Ó¥uzüf/vªS®Æ'AS‹r5„hô5qý°¢\m3&ÉA<>£Õ¼¯kÑÊÕâÄ'Ò~Upò§¾½9“‡Pþþ×—O8ñÐíÓîÕQ¶$ï<>@4ä3Ï µ„ÈMCH¨˜D.É[˜]›$T&&—ž¾”÷Be_ä¼u„rFÖ­y™ºû·€{éó³‹#Ífl~nl°-¶ÿû”«åâІ3ƒ‹r5„(ÚÓ¢ýÆP®¶%lT>ZÍûº–¢\Í`Õ€<C395>Á`rl²<®?ÿëÃÓ—ÿ\ü±{“ô¸²Qt÷–è í6îÞž¿ö¸qÍþ)DC>óŒPKˆÜ4„´jQÉe‘¼‘Ù5>¡’qhÍ%ï)„iÜKal_#”ôY¡ßÈ¥\m§//žÈûåj-P´§Eû<45>ñxêÍçCL¶“ÖŠ­æ}]ËR®ÆpCH>º'ÇæçgòH2P¢›"èˆ|òé®–¹o Õ¢’Î%y#³k|Nåcr<63>àñD¡môõÕãA«ìÉáùóã]XC(ø(W3®Xã)²(WCh<43>¢=0r<30>x£ù|Ó—=ZÍûº°\<5C>ó Z¯G><3E>˜`)%Eh<45>¾½9ËrS‘O>ÝÕ"7 !¡ZT2%odv<64>O«|L.þ}û›¼³J¡G>ýüxwÜ*{r„~}õX8Bu蓽쑑K¹ZF&³…O‚Fåj-P´F”«É™lêÏ<C3AA>w¹üU8EÄøº–¨\<5C>ª„æëíùëmÊÕ(%Eh½Î¾OtS‘Ï?}Õ"7 !¡Z`2%ogv Ω¬L.Þž¿–÷Bñ5ú°¦Éÿïï_žŸ]ÊcGÈ Žeжåjš<>ù$hX}~vA¹B§*Ú3#ÊÕ"0ÙÚì73*%:ZÍûº³\<5C>ª„FœÔ4h`òr7B#>Pär C‘Ï?}Õ"7 !•Z`2z%o¤<6F>ÆgVJ&— ¼Î‰ÐâÚ6¡ì’!t’ξŸ<‘rµ™ªY®Æ'AÓiûD5~¬<>ê(Ú3#×)7šÏÇ™l-¬Ù­æ}]ËU®Æq¾ÉOjbˆP_q´@eäSPGµ„ÈMCH¨•¤FÉÛi Á™•˜ÉÅÂçgò.C¨òÑjG†'G "ù\ ÊÕœàb"Q®†ÐE{läúh8šÏ·2Ùàì÷3Û+×ÑjÞ×µ°åj 7„bžÔ4ù˼:ŠP<C5A0>›"èˆ|
ꨖ ¹c Õ¢’×+y; 48¹3¹Xàíi„ŽèуO›ÖÄE¨û÷)W;I”«í‹O‚åj-P´ÇF”«áÐäüá{¹™Y”îh5ïëZºr5Öû×ó³ËÑsìäïó­^„ŠÜ@Gä³P/µ„ÈMCH¥˜¼^É›j ‘™•Å"t’¾¼x¢­~ùïï_¾½9“û€PpmüÐC–r5ËŠ5<C5A0>
'Q®†ÐE{rä:ÙFóy“mþúê±ÜÌ,úñî^º~7¾®E.Wc¸!ó¤¦Éßÿñîž<v„Ò)ãMtD> uQKˆÜ4„Tj<54>Ék—¼<E28094>œ_ž<5F>bŸŸ]Ê;¡,oqn\®Æ'AºUß/ïo¿'F¹š‡UpêE(Q®†ÐE{rD¹Z-@8`mŽ><}iÓér3Ë–«ÙL€u×Ûó×Û̱“%ûê¡<>õÏÅoŠ #ò‰¨‹ZBä¦!$Q Lj»äMõÐÈür`ráðýò¾¼ã*øçÌÊyZp
"åj§ŠrµC‰Ä9´¡D¹B íá‘kµF4Ÿg2ÙlN|2>EÄøº¼\<5C>9„æëуO›Í±lÄ!”ñ“ ù\´^-!rÓR©E%»]ò¦zhdŠ9?ŠýüìBÞwÅÑçgA
`®v°9Þ¡ù‡Zl°'F¹š%‡Ò‰S.ãˆr5„(ÚÃ#ÊÕR\û8ƒÝòh5ïëZÒr5väšÿVÚ–cóß·¿É}@(…$o|@4äsÑzµlÈCH¥˜ìvÉ[ë¡aùåÃäò<C3A4>·Æ
òRØ¡lŽ8@膞Ÿ]†ª”«yß&Q3D”«!´@ÑžQ® Ó×9ZÍûº¿\<5C>9„ßðo_®F))Bk>ð C‘OG+Õ"7 !‰Z`²;&oª<6F>Ff™lG#tDß/ïkWÙl”!´¦¬”rµe¢\mÇ¡¤úöæLÞGˆr5„–)Úó#ÊÕ²\û<úe„ò­æ}]KQ®ÆŽBq>zëÀ¤”¡ãz~vI­ì<>ÏH+Õ²!w !‰Z` “·ÖFòÌ
ŠaŠüRØ¡ü÷÷/ž¾”[„<>\<5C>|:TVºÙP¥\͘C©Å'A#ˆr5„(Ú#$ײ¨h>Ÿõ3EŽV󾮥.WcG¡<>¾¾z¬ZéOþÑï—÷åž SªâRˆ‰|RZ£– ¹cIÔãaš¼µ6–hnZû??»”w"Bu¾8pêýùñ.ƒW„Z5ÊÕì94óIP¹(WCh<43>"ÜÜV”«E`²ý]ÓW©<57>Vó¾®e)Wã'„éíùkáJÿПþúê±Ü„²\v#_|`(òIi<49>Z6äŽ!´½Z`lL“7ØFcÍ“ÉÕÄ÷Ëû<ŠE5õèÁ§Cߌ3B©XCŤV<C2A4>r5{埕‹r5„H~ѼuXyÔDEóùT&ÛÿãÝ=¹±Ñ”ý ãëZör5ÎqBÅuþð½|SîÐØäKÅ9b"Ÿ—KíÜÉÈCH¢Óä­uÒ°\3äК‚·ÆPM|)ŒŠ5„æ×ªQ®¶R”«ÝàPšñIÐj‰jüXÕ‘ü¢yë°¢\-<£·?ZÍûº–¨\íÈ­æ—OäN"$QØÓvb¡[o‡"_v`4ò©i±Z6äŽ!´½Z`lL“7ØIcrÍ–C+ v¤Q5…})ŒŠ5„ÖªQ®V„CÓ/çЖJTãÇú¨Ž"\7<>+ÊÕ‚0¬9­æ}]ËU®ÆËÅÜ”c¡ÅµjÁ/»0ùì´L-rÇÚ^-0N¾Éì¤1éæÌ¡Å…Ç#„ ^
;²WÆ8EEôüì2T­åjE8”o|´T¢?ÖGuäÒydXyÜÓFóy“Qð:ÛNÿ\üaÐËÆ×µtåjG^Ž *•ÒçgqVúG–<47>?ÞÝãÅ%T\oÏ_‡Úš€8È'¨ej©<6A>Û…Ðöj<C3B6>qòMÞ`3<>É8gŽT°?†*(þKaGšÇÃ#TAÏÏ.~¼mœ)W 2
9”uœz*Q·Ï¹<08>¤hÓû~c(W‹èéуO‡îH[*Œ¯k6åjç‹J)æ¦Ü¡ö|¿¼ÏØDeu|wN5Z ò9j<39>Z6äŽ!´±Z`̬“7ØLc’Μ#ûcT¬!oÅÜÛçH# ŠdZ<HCm_g‰<>|
åpx†J”«!´@Ѧ÷ýÆP®
VÆG«y_×2–«QƒŠëùÙeÀÅ>c¡}½=M­A>M-PK…Ü.„6V‹<56>™uò6›i@Æ•àÐZƒŠ5Tð‰CÌ…öñŠ<C3B1>ooÎØ.C~úúêññÌ5$ ãF39G&^y—åjLïû<C3AF>¡\-‡v*/7lŽVó¾®%-W£*•Õ‡§/#W¿Ùˆ`l¢jÊòº7‘ÏT§ªeCîB«ÆÌ7y›ý4 éªphÅñóã]¾6ˆÌôèÁ§É­ìà íãu;ß/ïS\Šltþðý÷ËûÇs>Úx¤\͘CIøùÙ…¼×ª‰r5„ ¦÷ýÆP®<16>ÉX nuËæh5ïëZÞrµãkçß˽E¨æ ¤lÁ!D­ÌD>Y<>ª–
¹]m¬?ëämöÓ€¼+Ä‘¥Gå­iTêôòà íãÕ;??Þ¥vÙ¿ddœZ^(cZ„C³.7åjLïû<C3AF>¡\-ËU¯æa2NG«y_×,ËÕøêòÓùÃ÷‰^ el¢â:þÕõ€@Èç«“ÔR!· ¡<>Õãg<C3A3>¼Í–<1A>z…8^À×Qv=zðéÛ›³à50s8¿o£|Ò ãt¿U”«ysdÊ•w\)Q®†<C2AE>Áô¾ßÊÕ2Î×W<C397>å>o/§£Õ¼¯k©ËÕn]æóÕ䡌/<2F>i-_$AÆJúiP!ŸµNRK…Ü.„¶T Œ¥{ò6[j@öÕâøþØ<C3BE>w÷<% ‚ºuO,×Bûx ³†2*Å¡jWì·<C3AC>r5{¥%óí–¢\ !ƒé}¿1kÌh>ºêU{/Æìh5ïëZörµ[—ù__=æR”Wçßgy7mŸãm6Ø
@膞Ÿ]þxw/ÝP!ò‰k¾Z*äv!´¥Zl,Ý“7ÛR½S¯"·n|yñ„-2äô¡<C3B4>¤ í[#ú÷ío|˜¥PÆAj¹Gßv9“ñIÐ-E¹BÓû~c(W‹É¡‚¹Õ[Êìh5ïëšA¹Ú­Ëüï—÷Y㣌úüì"Ñ»i“ܺÿÆV9²Ñçg©G+H<>Ï]óÕR!· ¡ÍÔbcéž¼Ù®ê<C2AE>}u9¾*á˜5”B<E2809D>|:ô|Ác¡='4êKQdå¤û-¤\­GOÈ»¯ˆ(WCÈ`zßoŒÇÒ2šÏã®zuŠ´ýŽVó¾®y”«ÍYæ¬;Pýùû_ß/ï§[ïOr<„ŸïzÜÏ ÊzôàÓ­§ ª"E>ƒÍTK…Ü.„6S‹<53>«<EFBFBD>òf»ªw–æÖÍ„ooÎêìT£túðôåñsËmÚ·øóãÝ.þ h e|Ã:ìµ|l”È!‡•O‚n#ÊÕ2˜Þ÷ãñx7šÏ]8´ w{ù­æ}]³)W›³ÆçR_<>|úúê±Ù¦Ü­±ðÆ(Ê«·ç¯³Ÿ‚B䓨LµTÈíBhµØ¸(o¶±zç`uæì*|}õ˜•8
¥?ÿk·<05>VÙs‚¥h Å‘A5é~S)W«Ã¡9–þ D¹BÓû~c<Š.¢ùÜ…Cwh]v\çßû­æ}]s*WÛqëZéß·¿qÿ‰bꟋ?æ¼›–t<E28093><1E>ˆjRdy¨ZÒÑ
›!ŸÊ樥BnB›©ÆØ@y³<79>Õ; <0A>2”IçßÏY_[®²gFÍhEY
Õ‚ÒýÖR®V‡#O å<>h/ÊÕ2˜Þ÷ãñT7šÏ½({É;t(PKŽñuͯ\mþ;¤­¡82x7m·FÇIP¥þðÄA>›ÍQ˃Ü+„6S Œ·<C592>ò–«kÂÿgÎ>ÃÏ<C383>wÙ%C*<2A>?|?ó+ÞKì™0ZÑö²)TÛ±ßfÊÕJq(uù$èhQ®†<C2AE>Áô¾ßÊÕ‚3šG¯ÒùÃ÷yoSË^×,ËÕæ¯ñYà£D_:(26y]ן¿ÿõýò~…Ñ
 ŸÓnUK…Ü.„¶Q‹<51>±<EFBFBD>ò–{«kÂÿbæ†Ãn—Ì{ï……jkFë¿oûðô%»ghœÎ¾Ÿÿ<1D>Dƒt¿å”«UãÐ# åj-P´é}¿1‹Çh>wäÐ:Bîù8¹­æ}]s-WÛ1;îùÙ¥¼/P5U+T»bN¼?ÞÝûðô¥¼<C2A5>Zöuõ €4Èg¶[Õò ÷
¡mÔbãí¡¼åÞꚉ0ÁÌ͇ÿþþåûå}Ê`ÐPýùû_ó Õª-±çÛruØÚÛó×ò>E•Gh®AºßxÊÕ
Rðñ½\”«!d0½ï7†rµøLFçúüÝøh5ïëšw¹Ú‚·Òä=‚*¨l¡ÚuæÄNÑ
"^ú€AÈç·ãj©<6A>Û…Ðj±ñöPÞr{uMFè°K¶+ƒáíNÔQ<C394>|úðôåœãÊY_Ï·èú€¥n ­ÑùÃ÷ŸŸ]ÌÿîgÒAºåj9”ÏÉV”«!d0½ï7†rµøzø.·}„Œ<E2809E>Vó¾®Ù—«í˜¿ÂúñîÞ?pð/·/wÒª¿Y3Tòf7R‰B5Š|–;®–¹Wm {å-·W×|„cÌß‘ØéûåýÏÏ.X’£õ‡5Íÿª ëëe£uW·öíÍÙ‡§/ÙÜF'íWϱ:û µ¬Prê Í8”ØêåjLïû<C3AF>¡\-“ú<>ã}´š÷u­H¹ÚŽ“\ßÞœñJê¥çg—_^<a_n’ùn_^<a· m¦çg—|<7C>F#Ÿëލ¥BnB£Õbco£¼åÔ5%¡óehÍn˜ýaMGëN?ÞÝûúê1¥kèÈYjßÞœ-H­–™ýp(W+ˤoß/ïË;ÔR”«!d0½ï7†rµZ)È<>ï+ï£Õ¼¯k¥ÊÕ–¥þåÅ^©@kþ'}æÀ{â$vo‰Ê;ëíùë“Þ*U HŒ|Æ;¢–¹W<08>V‹Må<>¯ ~) wÉ®s<7F>óÖФ=øôöüõ©g©±¾¾•fÞ¹ßÞœýsñÇŸ¿ÿEõZeýùû_ÿ\üqêfµÓÝŠrµ²Êsƒ”(ÊÕ2˜Þ÷C¹Zì¯wöG«y_ת•«íX°Û}û€å<W¥VaègÁ9¥¤¨£Î¾ÿçâ>× ["Ÿú©åAîB£ÕbSÁIyË‹¨kbÂeÿýýË¿oûçâæèªfÁ÷Y_ŸÊb‡oìªýûö·//žì
ØÅÞz~v¹;HmY©Ùµ|VëÝeC9”ðÌŠÝE¹BÓû~c(WË¡<15>Í;höG«y_×j–«]±`iöýò>{qhRþþ×—O–½ž¦
<EFBFBD>8Õºïî}yñ„/’ 5z{þzÁçÔc<1C>O€‡Ôò ÷
¡¡já©à¤¼ñEÔ/+a9 v3n”®½=Í›žEtþðýÛó×_^<YS¢ÆÊz1k<?^öËÿ\üñùÙÅŸ¿ÿu]ò¬C3õèÁ§«
Ò5%j–#t?FÊÕŠ3éŸí®çg—'ê䟓û€Pêé}¿1÷‡Ñ|Äd˜wAEŽVó¾®/WÛ±x ÿíÍÙçg”®Uo<>bñ<62>üðô%{ãh¦ D=>ÀùL8©–¹W U O'å<>¯£~‰ kY¼¿q}yÎÁM–Õ/ž¾ÜÕ§­,€aeÝ‘õѽÚí<C39A>v_#=¢ý¹bÇï<C387>ξßíQ{svÒW
ŽP˵¥z°;‡†€AbOÔÉ?'7¡ÔÓû~c(WK„ñk‡Š4šÆ×5ÊÕ®X¹‚Û½zöáéKvá¼µÛ<C2B5>ûúêñ²SÔh'±ØÛïî}}õ˜Ò5Ô·J<C2B7>a Ý‘O‰“jy<6A>{…Ð8µð1SÞø:ê—›Ð<E280BA>•›ûëôëõ*Ÿ„Õó³ËÝÞ×?|}õ¸Wq+ëÑôí£¤ÚÍ3GôõÕãã%soÏ_/™“?ÑÛU¦íFè·7g+<2B>7,8<-«’jveG žô¥NÔÉ?'7¡ÔÓû~c(WËÅd¤Ùo„&?6mÙƒÆ×5ÊÕöé²²û~yWÀ¶{/Œ;Û¤úó÷¿Þž¿Þ-ÿ××§1Ä–ÑåíN>JR\çß~v±à‹Ÿ [Š|zœTK‚Ü(„Æ©…§ˆ™òÆ—R¿ô„þôÚ ¹umN1É©µ%œÔtUßr]ŸŸ]\yxUÉ3º—Õ‰\ˆ Æ,ºu6;¤9ÓÚõÿsW“6¢pôºZüžÒ–zÎ>ŽCÃYÞ¹NÚ8Q'ÿœÜ„ROïû<C3AF>¡\-‡îS¯‹‹­æ}]£\탖~»ÕåîƒW/“RÌá½ÑÝ‘éW›#vÔI<C394>žŽÃp·¾ÛÖ–g ¤ó‡ïwg!®ù‚:ëÀùT¹¯–¹W<08>S‹M'åí/¥Né ù6Ê
žïÔKòHgJ<EFBFBD>¹Õ‘'ЬV<C2AC>}æÔ<17>»žCcäÖ¯£°‰:ùçä& ”zzßoÌ©¯ÅT4Ÿ‡2lÞ{¡//žÔé>ãëÚäC|µß±P­wGB<47>ª.—†Åï¥ÆÑõ·D¯ÏZ’m=u
»1ôåÇ«ôáéËâ/_'Õnø¯,QcäÀfȧÍ}µ$È<>BhœZlê8)o5uÊP0ß+CY¤ÎP8ˆ<7PµÂÈͧ—Ã"ﲚ¢CŠ3jVA|ŠÜXºo1rWéÄÈûå’:aý‘wñ²×¨¯W\ü)“G>ÉŸ%Ñ£Ÿvç"~}õ¸×çzÕy µ<>O¤7Ôò ÷
¡Aj±©c¦¼ñÕ/OakäËpDêL„åÈ“m u–EAÞôxdä½VPô&BqF Ã*ˆÏ£‘{Kß-Cn,ý
y¡°RçfQäýM·øòˆEÉ÷‹wíýðôåÕ{¿`€¼6 i©€Ü(„©Å¦”™òöT§<1òå0ÚXꌃí<C692>':Uê” Š¼_H€ÈÈ{­ èM„⌆UŸG#÷–¾[†ÜXú12òþBZ©þò|@s¾eüíÍÙ­ß컽꜀ÒÈk’Ö È½Bh„ZlJ™)oMuJUˆˆ|‰ŠzI<7A>JPù.uÿä@ÞMäCpäWMt%BqF Ã*ˆÏ ·—Ž[†Ü^º2 òîC£¥N1˜‹<UPX©sàÿ!¯ ÈX' 7
¡já)å§¼ý5Õ)U!ò…!:$ujÄE><¡+‘wyyß•ýˆPœQð
âó6Ȧ㠷—®L<C2AE>¼OÑb©sº!Ï%$—:n"¯ ÈX$ ÷
¡îR<EFBFBD>ªÛ)å§¼ýeÕ)[N@¾De9 °1òÙ˜i?>ò¾+%ú¡8£†aÄçm<C3A7>;L¯-@î0½iŒ¼Ç‘:@†<÷Ðh©S àòÚ€tEr£ê®žR~ÊÛ_Y<5F>À
yñºUê8ym@®"¹KuW O5?å!TV<54>„€ÎÈ‹ÁJÝ'Ë‘×äª<10>…P_µðT³TÞþâê”¶àei½<>×$ª<10>»„P_µðT³TÞ~Ô)s`ym@¢ò¹QuT OAKå! ™ ‘×d)<0F>»„PGµð´TJ14RCm@£ê¥ž‚–ÊC@;õÈ_8µ)\B¨—Zxjº*íÔ#…à Ô¤p ¡.já©éª<t¥Y ¡0àVäåuQ OMWå! ëê‘Èp
nE^><3E>ÐzµðÔtUº¡¹ ¡*à8òÚ „Ö«…§¬«ò(Јn€CPpyíBkÔ2PÖ[yh_=2BUÀä…­QË@Yoå! IõHj8%G<>N ´X-e½•‡€©G^ÀA( 8„¼j¡Åj(ë­<tD=RBIÀ!äU-SË@Yoå! ãê‘Ýpê!¯š@h<>Z*{+<2B><02>îb8%“È«&Z –<C2A0>ÊÞÊ£@Cûn…ª€Iäµ<08>ª–<C2AA>ÊÞÊ£@ã:fBmÀ>òò „NUË@e{å! }õHj8 *ö‘Q t’Z*Û+ÝP<C39D>Œ€%P$pyB'©e ²½òÐuõHgX¥7<>WS 4_-•핇€®«G:À*¨¸Ž¼š¡™jI¨ì°<t¥¹  `à:òš
„æ¨%¡²ÃòÐN=ºAÙÀò²
„æ¨%¡²ÃòP¢‘P
Š®<>W t«Z*;,õHaõ;äõݪ–„ÊËC(®ù ¡Š`‡¼Ê¡ãjI¨ì°<„Êꑼ0j vÈk-:¢–„ÊËC(«™ A9u&(²Z*›,¡¦z¤-l
E”š °jy¨l²<„‚ꑳ €ÒyÝB“jy(k²¼ýÕ)g@Õòê „öÕ’PÙdyû«©S΀’â5ò „öÕ’PÙdyûK©S€žâ•ò2 „®«å¡²Ïòö×Q§l€(/6<>c t¥–‡Ê>ËÛ_G<5F>²Q¹Þ@^Œ<>ЕZÊú,o|õËVˆEåªyIB;µ<”õYÞø"ê—ª‘²…òª „vjy(ë³¼ñÔ/O .eËäµµ<TöYÞ~{uJRH@Ù"y…*®–‡²>Ëo¯~I
9¨YŠ /Ò@ÅÕòPÖgyã½Õ/C 5«ä¥¨²Zjú,o¹·ºf($£`M‚¼Z•UKEM«å-7V×ô€”¬L<C2AC>×l šjy(kµ¼å®êšž<00>˜‚Å òÊ TP-5­–7ÛU½ÓrS­DA^¼<>
ªå¡¦Ïò–[ªkb€ Õ
ä%¨”Z*
Z-o¶¥z'&øP­\A^È<>ê¨å¡ Õò6[j@n€¥*䵨ŽZ
Z-o³Ÿ$&RªnA^Ñ<>*¨¥¢šÛòûiLb€'uªäE¨‚Z*JY-o°ŸÆd%8S§†A^Ú<>ìÕòPÍjyƒÍ4&+ÀŸ:e òd¬–ŠRnË[k¦aY %(RÌ ¯ñ@Æj©¨cµ¼µf–’Pˆ"% òJ䪖‡:VË›j¦‘Y µ(RØ ¯÷@~j©(â¶¼<C2B6>fœ• áNÔÌB½xÚµÇ7¹c<C2B9>Ú]€¹T(o<>—| ?µT±ZÞT'<27>ÌGØõª((-¥‚íõM¤Ô´J±…”XF‹V¦‡+-j·‚ÒR¡v+­ E<!–<>E})5jï¬(2ô˜v–<76>EÝs))j׎Q¡ÂA^ø<>œÔRQÄmy;<3B>48%akÔ+¡ ´TT‹·øÓ+œh(âɰŒ"þ¬OKZ*Ôn¥¥BíV\š5E| –<>?½òÇ uo8PdÄ1á,:¦<>ê~˜ B<C2A0>ƒ¼üÙ¨¥¢‚ÛòF:i|J‚õ((-5£^ÎôÊKš/EL –QÄ™^éaFK…Ú­ ´T¨ÝJ@s¤HøäÀ2p¦WæX¢î€ÄhÌ6ËÀ®¿“¨ûàa_í ¯A6jy¨`µ¼‘NŸ’ C½ô JKEÙÀWRÙ–Ž9ãMs¤Hø¤Á2ŠØÒ1=œh©P»”–
µ[ih^ œXFe[:æŒ7êŽHI‘!ÆT³Œâ¶tLKÔýðÿ°¯y<C2AF>×<EFBFBD> µTx»-ož™¶ÊJ<C38A>¡^ô¥¥¢rìk(ëIß„±§ÙQ$vÒ`E<é›6´T¨Ý
JK…Ú­d4Š„Lï/£¬'}Æuwä£ÈøbªYFeOúæŒ+ê^ø¿Ø—=È«APvµT»-o›™6ÌJP¢^ñ¥¥–QÓ<51>ÙbOó¢HàdÂ2Џ1"= h©P»”–
µ[ùh‰—XFM7Fd‹=êNHF‘ÁÅl³Œ²nŒHWÔ}@¹BÕRaì¶¼mfÚ0+A<>z¹”–
LXFA+¥JšE¢&–QÄŠAé‘<C3A9>–
µ[Ai©P»•’–Ÿ"Á’Ë(hÅ T©€ºë2Qdd1Û,£¦ƒ²Åu<>@u¼K äe!(¯Z*\Ý–7ÌLÛf%„@½Ö JK>,£šyóäN š EB&–Qćq鑚–
µ[Ai©P»••–œ"‘’˨æCÞ<¹ƒÑaØPdX1Û,£ Æ©2.´Ñ@e¼ !äÅ!(£Z*,Ý–·ÊO›'&D<>%‰#W¢Îý^ÊÒ`>ÔÉü•}mìÌqŠ˜P$LoèDü:ñÎV´Ìæzš/¥L vàÀS+çcgŽSÍ2¡rì<00>ïry‰J§–
?·åMò“"1!,I*/3‹÷~<7E>ðé÷IÊzR$Ø;ãiŽ ¿H˜ÞЉTîÄù±ûB˜½hŽÔ Ÿ~ŸOQd@ÝOs¤Tøtýuða\!¯AéÔò`fµ¼=–å&Ä‚õHÍÕåšub§»<C2A7>PЙ"ÁÞÙ„fG‘Ø‹„é <0A>h<00>xª†fGšub§»<C2A7>€3Ý)2 îlB³£Tìôø>¸)0®‹<C2AE>׊ Dj©pr[Þ?é"Âz¤Z'ž´õÎ<C3B5>"<22>ïå™”²¨H¤'…yR8¹´O‘À‹„é <0A>h<00>¸Ì<C2B8>ìžTˆ‘û<E28098>Å ¼x/Ï‹:Rd4<64>æI“Œ“KûÔ ¼xG[ >Æò¢”E-6VË[b)inBPXŒìÄ“¡ÆiP$ê²ý{*u\*é©aÎÿïÍŒºA‘¨‹„é <0A>h<00>¸Ø<C2B8>ÔžTˆ‘û<E28098>ʼnºlÿž
.ô¢Èh:5Ìùÿ½™Q7¨uÙ.žÎ@pŒË$ä¥#(¾Z<Ü–·ÁUêô„¸°©Ù‰óÿ‰q2Tˆ·`·®¡ˆQERbA˜óÿ‰Ÿ]W‰·H˜ÞЉЉ5=©#÷!‹©oÁn]Ft¡È´³ ÌùÿÄÏ®+ŠÄ[°gOs 8®Åòê_-r¯PX©s¢Ãb¤r'Îÿ‡–ùP!Øj}º’"^æñ0çÿC3Çv ¶H˜ÞЉЉ5=©#÷!‹©lµ>] ^t¡ÈPZæühæØŽ"ÁVëÖ`DƵdB^C‚"«åAî
+unBX©ïÄùÿÖ/%*DZ!ÆŽ±‹0o sþ¿53<35>ô0 Ó:Ñ:±¦-ö®sþ¿53­HzTˆ±#ØÐ…"CiM˜óÿ­™i¤‡Y˜kÀˆŒkÕ„¼’…U˃Ü+SêÄ„L°X3`e'ÎÿçfYQ!Lû»SÁ±
™ÏĸÂt
Ó:Ñ:±¦-öv sþ?Ç·tØØXO…Ù•‹ïbÓ&Æõ`„ŲvB^L‚bªåAîŠ)ubB>ЬI½Y߉óÁ)70{€#¨àX‘ÄXæü_prÏ>ÀRazC'@'Ö´Å>À^aÎÿ'÷0{€#À1€õ™|Ö‡9ÿœÜ³°HŒ]À"‹e…¼¤ES˃Ü+SêÄ„¬°^3 W'Îÿ<1D>ôðŽ®B€#¨àX‘Äèæüßñ0Ð;ºjazC'@'Ö´Å>À¾aÎÿ½£«àp `=E&Ÿ^aÎÿ½£«c°ÂbYG!/,A¡Ôò ÷
”:+!7¬× èØ‰óÊ CŒC+à*8V$1:†9ÿ§ <4­`˜ÞЉЉ5m±°{˜óÊÀCãЊ8XO‘ɧc˜óÊÀCãÐJÅØ,€°XVSÈËKPµ<ȽB¥ÎJp€õš};qþ¯eÏË ®ãÝ *˜fŸù#œÿkÙ<6B>´ ªl˜ÞЉЉ5m±pD˜ó-»“–A]Ç;ºA`Àzìg×aÎÿµìNZuû{<7B>KËš
y‘ Š –¹Q( ÔY >TX“ÚÓ½çÿ`êTñ‹èÞÑ ¢‚iö™?(Ìù?˜ÚL¿ˆ*‡é <0A>h<00>XÓû…9ÿS›éÑ ¼£¦¬Ç~væüLm¦_DûØØ \€°øUVÈëL<C3AB>\- r£P@©³ܨ°&µgP'ÎÿÙ¤ÙbÎ>ÞÑ ¢‚iö™?4Ìù?›ÔO³pЇé <0A>h<00>XÓû‡†9ÿg“úiÎ>ÞÑ ÓÖc?» sþÏ&õÓ,œIìì.@Xüê+äÕ&H¨–¹Q(šÔ) ¶TX“Ú3®çÿrÆ„qŠeïè`1ö™?:Ìù¿œÑR§XŽP$LoèDèÄš¶Ø8:Ìù¿œÑR§X&ñŽÂb?»Žsþ/g´Ô)–CØØ \€°øUYÈËN<C38B>J- r£P(©óÌ©°&µgh'Îÿñtiãż£ƒÅØgþaÎÿñtÆzDq+EÂô†N4€N¬i‹}€„9ÿÇÓëż£€°ØÏ®„9ÿÇÓëÅqìì.@Xüj-äÅ'h{µ$È<>B¡¤ÎG(A…5©=tâü?‘(s B(¬¡Hnlæü?‘È[ƒæP$LoèDèÄš¶Ø¸Y˜óÿD"o B(D¦Èü³A˜óÿD"o B( @Ì*.äõ'h{µ È]B¡¤ÎG(K6¶éÄù%Kòdoåè` Erc›0çÿ•,öfoÿLŠ„é <0A>h<00>XÓû· sþ_ÉboööWŽ"SdþÙ&Ìù%‹½ÙÛ+öTÀ¬îB^…‚¶TË€Ü%Jê|„r°d3`³Nœÿ‡RäOêÆ<17>ÖP$76 sþJápêÆÏ§H˜ÞЉЉ5m±pã0çÿ¡§n|ñè 2EæŸÍœÿ‡R8œºñs° fÕòZ´<>Zä.¡PRç#…%›[vâü¿?‹’6{&ÞÑÁŠäÆ–aÎÿ[ñ}NÚìS)¦7t¢tbM[ìÜ>Ìù+¾ÏI›=ïè 2EæŸ-Üÿ·âûœ´Ùó± f5òŠ4Z-r—P(©óJÃ’Í€í;qþ_ŒœHÛ<ïè` Ercû0çÿÅÈVglóŠ„é <0A>h<00>XÓûUaÎÿ‹‘­ÎØæùxG‘)2ÿlæü¿ÙêŒm> û*`V‰!¯KACÕÂ#·Å‘:þ/,Ù <0C>tâü?6—Ò5ø$¼£ƒ5É I˜óÿhX·Ó5xEÂô†N4€N¬i‹}€Â0çÿѰn§kðIxG‘)2ÿHœÿGú<C383>®Á§b @ÌJ2ä*h<>Zläþ PRç#Àÿ‡%›ªNœÿwc¦S®ÖžŠwt°†"¹¡
sþß<EFBFBD>ix®Ö.¦H˜ÞЉЉk<Ék‹}€Ú0OJ¡€†çjí©xG‘)2ÿ¨Âœÿwcž«µ ° N…ò4B-6rP(©óà&,Ù vâü?0©²´sÞÑÁŠä†0Ìù: íYÚ¹’"azC'@'.6$µ-öÊÃ<5‘BÙž¥<C5BE>ËðŽ"Sdþ†9ÿO´=K;c @œÊ3ä•*¨»Z`äæ PRç#À4‹–Ñž´´ÈcLj{ŠF.Æ;:XC‘Ü<E28098>‡9¿¡œOÑHmï˜ÑÒ¢v.--b< úÝ&Æaž”NqœOÑÈÅxG‘)2ÿÈÜ߀PΧhä쨀S…†¼^uT ŒÜJê|8Æ¢5´'--bÌè|ü®Á;:XC‘܈æü6Ä1?~ å]cFK‹Ú¹@´´Tˆq&ô»YŒAÂ\<5C>Wróã·p ÞÑ@dŠÌ?œ߆8æÇoáJ쨀S<E282AC>†¼juQ‹ŠÜMꔸ<>E hOZZ‚ĘÎüàÍ[‰wt°†"¹$ÌùÍâðæEè3ZZÔ΢¥¥BŒ·B¿[Æ'ÌEÉ¥ô?xóVâD¦Èü$ÌùÍâðæ­Ç>@€
8UkÈkWÐJ©3è rgP(©óà­ž=ii‰c®.Û°.xGk(’qœߒ½¶a¡:ʼn–µs<C2B5>hi©ã!Êvz<76>~<7E>梓õB؆uÁ;:ˆL‘ù'N˜ó[¡Â6¬öTÀ©lC^Ä‚«…Dn Š&uJœÌ¢u³'--ÑbÌÒ 1[Õ ïè` Er#Z˜óۣ툘­
Õf´´¨<C2B4> DK‹qŒ#;<¥!×!LI˜‹MÐ1[Õ ïè 2EæŸhaÎo<C38E>¶#b¶ª#öTÀ©xC^Ê‚–©ÅCî Š&uJ,dÑ¢Ù“––€1¦èˆ€Mêˆwt°†"¹0ÌùMJÑÈ–™5}aFK‹Ú¹@´´¨<C2B4>ËJKN‘H†¹(Ýâ6²%Ä;:ˆL‘ù'`˜ó›”¢‘-'öTÀ¦„C^Í‚¨Cn
(uV¬bÑŠÙ“––˜1ÆïŽP<C5BD>©Ý<>œ´´Tˆ1l˜‹rmÓ¦†jLØŽp¢¥Eí\ ZZÔÎ¥¤å§H°1Ã\”t›65Tc*Gw''jÛâRdÅ sÑ|¶iSC5föTÀ¦<C380>C^Ó‚NR‹„Ü SêÄèÀ¢µ²'--ac Þ#qZR<º;9ii©cä0¥Ûv­<76>ӒȽàDK‹Ú¹@´´¨<C2B4>KFs¡HÈaÃ\”}Ûµ6NKŠGw''jÛâRd… sÑ”¶]kã´döTÀ¦œC^Ù‚fª…AnŠ)ubô„%›Á;q~ó6np<6E>f "QtwrÒÒR!Æøa.Jº-¤£)¦7tb©N,Nó¢HàÁÃ\”‰[48H3‘(º;9QÛ—"ã(x˜‹&¶-¤ã° 6uòt«Z ä> °Rç&@X²¿ç·pË6GhÃ8Ew''--bL梼ÞæmØ€"azC'–êÄš4SŠ8?ÌEY9¼ÍÚ0ŽDÑÝɉÚ6€¸GñÃ\4· os„6 Å>@€
ØTwÈ ]еÈM@‘¥NO€Q°d3 E'Îoäf-Oá[…èî䤥¥BŒYÂ\”zc[žÂ·õ Ó:±T'V£YSća.Jϱ-Oá[…èîäDm@\ŠŒ£a.šÞƶ<…ok° 65òr4)u^<5E>è©3`,,Ù HÔ‰ó›ºAãùæÝ<>œ´´Tˆ1W˜‹pTãù¶†"azC'–êIJ4GŠ„Ÿ(ÌE¹9ªñ‰|óŽîNNÔ¶Ä¥È8Jæ¢InTãù¶ û*`Sé!/zA7D2 à¦(Àf°d3 W'ÎoíèöçòÍ8º;9ii©cº0åà<C3A5>öçòm1EÂô†N,Õ‰Åi^ <W˜‹sHûsùfÝ<>œ¨mˆK‘q”+ÌEóÜ<C3B3>öçòmöTÀ¦ÞC^ú‚®‹@aµ}raÉf@ºNœßà¡!¤óÍ5º;9ii©cÆ0¥aÿÒù¶Œ"azC'–êDpÊä"!§ sQVö!<21>o®ÑÝɉÚ6€¸GéÂ\4Õõ!<21>o§b @l
?ä50h':…Õ–É –ldìÄùmHFßæãÝPì}+’Ãœßæq<C3A6>dômEÂô†N4À»çGçíÃ>EâÍ梬ìHFßæãÝPð `%E柌aÎoó¸@2úvöTÀ¦üC^ ƒèeT99bÂ’Í€¼<E282AC>8¿å#bÉëÛ¼£нoEr#o˜ó[>"–¼¾<C2BC>D‘0½¡ (Þ‰óÃ7³¢H°yÃ\”˜ÝbÉëÛ¼£
¾¬¤Èü“7Ìù-K^ßfb @lŠ@äõ0•EŸ¢jÉ <09>–l¤îÄù<C384>ïNjߊG7{ߊäFê0ç7¾{8©}›O‘0½¡  OõÁÃ<C381>"‘¦óÔœìNjߊG7|XI‘ù'u˜óß=œÔ¾ÍÁ>@€
Ø”‚È«bjŠîCÞ™ <09>–ldïÄùíïQvß*G7{ߊäFö0ç·¿oDÙ}›I‘0½¡  XaàF‘H³‡yRNvŒ(»o•£
¾¬¤Èü“=ÌùíïQvßnÅ>@€
ØÔ„ÈËcB¤žŠbÁ’̓NœBǸ |+ÝPì}+’aΡc\¾Í¡H˜ÞЉЉËÜÈnaf ó¤œì—<>oe£
¾¬¤Èücæü:Æeà[ñû‚W›Êy‘ BH+õ$–lØtâü@º„fãÛ!¼£‡½oö™oæü@º„fãÛqŠ„é <0A>h<00>XÓÂÌæü@º„fãÛ!¼£¾¬Ä~v5 s~ ]B³ñíöv¯ &6õ!òR„<>Dê¹ 4Ö¤ö8uâüXÖGçäÛ$ÞÑ<C39E>ÃÞ7ûÌ÷ s~,ë£sòíEÂô†N4€Nܧ‚!EúÝ)Ìù±¬<C2B1>ÎÉ·I¼£¾¬Ä~võ s~,ë£sòíöv¯ &6µ"òš„ÐÆRÏ: ¨°&µÇ¬燳2@3ßöñŽnö¾Ùg¾e˜óÃY ™oÅÃô†N4€N¬éI…ýœÎÊÍ|ÛÇ;ºqàÀJìgWË0燳2@3ß&±°#x1±©‘WÎ „6“z¾HC…5©=~<7E>8?¢5aúùvïèÆaï›}滆9?¢5aúùV9LoèDèÄšžTˆÑ2Ìù­ ÓÏ·xG7|X‰ýìêæüˆÖ„éçÛ>öv¯ &6u#òú„Ðh©§€|TX“ÚãÚ‰óãZ©«oWxG7{ßì3ß;Ìùq-‹ÔÕ·šazC'@'NbïI‘~w s~\Ë"uõí
ïèÆ<EFBFBD>o+±Ÿ]½ÃœײH]}»Ž}€Á+ˆ‰M‰¼<E280B0>!4Nê  +Ö¤öwâüÐkì[‘aoZ‘Ä0s~h ‚5ö­`˜ÞЉЉ“Ø{R¤ß<C2A4>ÜÚ‚`<60>}+à 0 `%E&ã0燶 XcßJÅØ Œ€˜Ø”‘ÈËiB#¤žZrÃzÍïNœÝ©!{ûV!ÀT0­BŒöaÎ<61>îÔ<C3AE>½}«¦7t¢tâ$öžéwï0çGwjÈÞ¾Up˜°ž"ãÈ;ÌùÑ<C3B9>²·oubìF@LlŠIäE5¡ŽRÏ(&°^3À¾çxRÔø–=ÀT0­BŒœàIQÛûV*LoèDèÄIì=)ÒïöaÎð¤¨ñ-{€#À4€õGöaÎð¤¨í}+c/0
bbSU"¯®Au‘z.°‚õšE:q~˜3¯à›}€Ý©àX…Ì'ÌÅ<C38C>ã›S˜ÞЉЉ“Ø{R¤ß sYà|³°;8°ž
³+a.ßlbìF@LljKä56¡•RÏ"†Y“zS§çG:'ö
¾Uˆ±/ì*’EÂdb\F‘0½¡  '±÷¤H¿ “û<E2809C>Tˆ±/ذž"3O‘0¹ø.£H˜ëÁ%ˆ‰M…‰¼Ò!´LêÉÀk”êÄùÁÞê@ß›S“"^¦S˜§{«E|+¦7t¢ÿ‡½;ZzlÅëÇœ‰~ÿçð\TGEÍ9™ö6HHÀZÁ]³%!ØNÔß/‹ø'Ç×ä’u¿$Í_“ýZ<C3BD>ê6\œ;©„¸d+]’æ¯É~­À%u®ÏU”hë˜Û&åWn ÃøuTp>ÿ 9À…‹ø<åE¸¡nc•¹Ó=µ’æIi÷ðߊpIÝ.Iólññ<>ޝÉ%ë~Išc)( u«Ì<C2AB>Ô
¢\²•.Isøœü[.©ÛXqn£D@[ÇÜ9)¿xcÆóQ}`À-ü3äw.âó¬ÿV‡Kê6P™;ÝS¥K2½$Íá¬ÿV‡KêvIšg³ˆ°ˆt|M.Y÷KÒÎúou¸¤n•¹“*<2A>õÌ áW—4Ï%iNžÿ®Ã=u(ÎU./ÎOíqj ³cnž”_¿1 ãë¨>'à:¾„àÚEüõ’ÿ(Å%u¨Ìmn+Ñ%™^’æ|?ÿ£—Ôí’4Ïf`ÿèøš\²î—¤9“øKqIÝ*s%úaÒ%ÍsIšóGÄ?JqOÝŠs•ÑÐÜ1WPÊïá†ñaTŸp)_Âpó"¾–xo»°8—dzIšQ]=ཱིKÒ<›E<€Eü£ãkrɺ_’ædî3Þ›»0åççß„I—4Ï%i†œcÞû»3ë¯ÔD ¿c.¢”߯1 ãߣú`€Ûù~‹øJöÞܵ‰vmM.Iö’4?x%{ïì’4Ïf`ÿèøš\²î—¤R<>1ïÍ]›øgjò7j¤Kšç’4ÏŠ_½÷wsî¤ÿ¥ÐÜ17Rʯå†ñ¿£úH€Ü·¾„À"fÿ&óÞŸ
ü—:\’ï%i~6ÔæWÔí’4Ïf`ÿèøš\²î—¤U„ïý©À©ÃWʤKšç’4c<34>‹Ÿ¼<C5B8> Þ¼¤ÐÜ1WSÊ/ç†Ñá(€ŸßÀ3ÿ<9Ø{+§æõ+ýðÙ=õ¹'Ó1—ä{Iš_ uúùuË+ËÖÞ[©®VSï­œš×¤ãkrɺ_’f`~õ>Â=õ¹'Ó$ʤKšç’4ÃOŒ ëvp‰òRë“cu€æŽ¹£R~KÇ0.Õgüàž6Îù‡ËöÞ[95¯ú¡¤>—xŸâ’”/Ió‰¡~?¼nI5ÙÝ{+ÕÕj꽕Sóšt|M.Y÷KÒŒ-ÅOÞ§HªÏ%Þ×P&]Ò<—¤™qh\X·¤ï}.¥€æŽ¹©R~WÇ0îÕ[~pa?çüÛe{ï­œš×°Ëûaqq.ñ>È%Y_’æsC<73>lÝ«q†÷Vª«ÕÔ{+§æ5éøš\²î—¤™Q<E284A2> ë^œK¼o¢8Lº¤y.I3ï踭náõ9ÞûhªÍse¥üÒŽaÜ6ª7=üàÚ®ÎùçËöÞ[95¯7÷ÃââÜà}–K¿$ÍŸ µÿ™u‹-Å1ª—å7ÕÕj꽕Sóšt|M.Y÷KÒLªÉ…u‹-Î Þ—Q&]Ò<—¤™zzÜV·Øúœí}:<05>æNº¸R~{Ç0nÕ~ ½sþ³½÷VNÍkÒµý°¸8Ç{ç’Ü/IóWC›àÀºÖá$ï­TW«©÷VNÍkÒñ5¹dÝ/I3¯,Ö-°8Ç{ßG‰˜tIó\’för[Ýës°÷Ôš;éKù5Ã8{ToqxJ“ÿWÎ?b¶÷ÞÊ©yÍ»³Ö×çTïC]R<>KÒ0´N«[TóÞJuµšzoåÔ¼&_“KÖý’4S+sgÝ¢êsª÷­ŠI—4Ï%i.8C.¬[T‰Îó¾†Ê@s']e)¿ÌcGŽê<C5BD> ?Ðíÿ<C3AD>óO™í½·rj^Qnë‡õõ9Ïûh—Ôá’4‡ íŒsê6Ÿþ‘Þ[©®VSï­œš×¤ãkrɺ_’æ‚úÜY·ùúœç}7åbÒ%ÍsIšËN’ ë6_¢“¼/£>ÐÜIwZÊoõÆa£zOÃSzþorþA³½÷VNÍ+ÐUýPU¥¼ïpIA.IsÆÐ.9¤n“¹Ÿê½•êj5õÞÊ©yM:¾&—¬û%i®)ÑÍu›¬ÒªW  ucÒ%ÍsIš+“këöºØûV
Í<>t³¥ün<C3BC>aœ1ª·2<¥ù¼®Q]i€/^ר®ôÔ`™×ªk ðÝaè/¿çc[<5B>ê OÙÀ1\<à*‡ý¡¿ü¶<C3BC>aì8ª7.<e/çq] €«ö‡þòk?†±×¨Þ²ðˆÌu5®rØßúË/ÿÆ£vŸÂs¶p6wÕ¸Íyë/¿dmGõî„§ìàÚûi®«p¶óþÖ_~#È0Žê} <09>Ø)Àñ\Wàrçý­¿ü¶ƒaôÕÛ)ß)¶ °Œ»j\îÈ?÷—_x0ŒÚQ½á©òÍb®ÀåŽüsù…èÕ›)ß)vPÅ]5.wä_üË/<ÆâQ»ãà¡ò<C2A1>b+å\Tàr§þÅ¿ü΃a,Õû )ß)öЇ‹j\îÔ¿ø—ßy0Œ¼Q½½à‘ò<E28098>bs@7ÿÑ¿üÚƒa„<61>ê]<05>”ï[ z:ø<>þå× #jTo&x¤|§ØkÐÜÙô/¿ù`3£zÁ#å;Ŧ€]œýwÿò›†10ª÷ <R¾Sì>ØÎñ÷/¿ü`Gõ^<5E>GÊwŠmû:þOÿå— ãó¨Þ"ðHùN±à7üé¿üþƒaü{To x¤|§Ø˜p’Kþú_~Â0þ3ª·<U¾YìP8Ï%ý/¿a\>ªw<U¾YlU8Ø=ÊoAŽê®‡§Ê7K“Q½p¸«.”_„0.Õ<>O•o–n£zAàpWÝ(¿aœ=ªž*ß,mGõÊÀán»P~Â8oT75<U¾Yú<59>ê%€Ã]x  ü:„qƨndxª|³l4ª×
wç5€òƾ£ºyá©òͲã¨^48ܵ7Ê/E<1B>ên…”ï—­GõêÀán¾ P~/Âh>ª;~P¾_ÎÕˇ»ü2@ùÕ£á¨îJøAù~9lT¯'Î}€òÛF‡Q݆ð›ò-sê¨^X8œ+.~Ü<ª[~S¾eŽÕ+ ‡s%à?ÊïHËFu¯ÁÏÊwÍ=£z©àpnü¯ò›FÞ¨n.øYù®¹pT¯9ÎÅ€(¿,aŽên‚Ÿ•ïšËGõúÀá\ ø£ò+Æð¨îQ¾qŒÿŒêF€Ã¹ж2ÆóQÝ,0¨|ïÿÕ‡+¿Ðüz@yqŒ¿<C592>êÖ€qåÛÇøÛ¨n 8\ùÝ€-n”×ÇøÏ¨n˜R¾ƒŒ¯£ºGàpåw6º!P^¥;Gõ²Ã¬òMd<Õ͇+¿°Ý%<25>òB?ªW”ï#clT7®ünÀ¦÷ÊkuÒ¨^LS¾›ŒÉQÝAp¸ò»»_(¯Ø¦£zÝ Rù†2¢Fu+ÀáÊïs[ ¼n<C2BC>Gõâ@¼òmedŒê¶€Ã•ß 8ïÂ@yõ:ŒêE€,å›ËHÕý‡+¿pö<70><C3B6>ò2Z,Q¾ËŒ5£ºÑàpåwî¹6P^O‹?)ßnÆúQÝtp¸ò»7ß(/ﵕ‡ÊwŸQ8ª»W~7Àå<C380>?RUX¬ü¬3:Œê6€Ã•ß p¨R~¸ÝFuKÀáÊï¸B,V~ mGuoÀáÊï¸E,P~‚[Œê>€Ã•ß p‘ÈS~j{<7B>ê†€Ã•ß p—ˆU~LûŽêæ€Ã•ß p<>˜W~.gŒêF€Ã•ß p©V~‡<>ꎆ{½®¡°»—4Õ͹oáµ³êâÿôÚYuñ€Ó8v.T~7À½à'å'<27>qð¨în¸×ëJ
»]=³Ý™us¯Uîõ:QuQ<75>8j.T~7ÀÕà«ò£Æ¸dTw:Üëu7…Ý¢˜ÙnË·¿×éª wy<77>®ºÀÀÞ2*¿à‚ð7åg‹qÛ¨ny¸×’¿Ÿt§°Í‹™êªdû{ݤºØp¾×Mª‹ ìÊñp¡ò»îÿ«ü01nÕí÷Zò—“ (lçb¦º*Ùæ^÷©.9œìuŸê’[r¶\¨ün€k@ùéaÿÕ[îµäÏ&{PضÅÌsO¦Í½.V]{8ÐëbÕµöã`¸PùÝ— àNåg…aü{To ¸×’¿™lCaV2ÏUÉ^²›ª.?œæu·êò›qª\¨ün€ûp<>òÃÁ0><3E>ê-÷:àïÒ‰Ov÷ªÿÿKædv{%Ûܦ €@›¾ ÃöÕø‰#àBåwÜ:€³•†ñ|To¸×ñì¨úãΑU]_ÆV<C386>±u¾m\ê#“€æ|µØ+) ƒGŠ#‹íhZŽW~7ÀÝ8OùÆ7Œ±Q½uà^—ü±ãIš±)\Õ•elÒ['ÛÙ E>;;hÅW‹Ý³J,8OœWlGÓp¼ò»®ÀÊwºaÌ<61>êm÷ºê/O’]ócìîU]VÆmðëÏs—Ôö† _-ŽÉXiÁyâ¼b;š€ã•ß p öU¾¯ #vTo)¸×méx’oHÖÇWuÓÎk€±OñÕ=U½$M¨å«Åaik,8OœWlGÓp¼ò»®"À^Êw±aä<61>êí÷ºð/ORv]íÔ®þ¿ƒþ s[=¯JÖóÕâàd<C3A0>T ‡ÛÑ´¯ün€ Ð\ù†5Œe£z·Á½îü3Ç“¬'¿¡ªÛåøpÝÿùÌgù£ ‹y[¾°’¯Çç ì{˜8¬ØŽ¦àxåw\K€†Ê·§a”Œê<C592>÷úú³ä‘?Â<ÉÚuµÃr|¸èžŸ<C5BE>ÿua%oËVòÕâø|<7C>}‡ÛÑ´¯ün@ù¨^è¢|3Fù¨Þ…p¯¯?Kžú#Lvâ7Tu¯Ÿ¬ø×˜NÒ-÷†î¬á…)À¾Z\’2°éaâ°b;š€ã•ß h2ª×
”ï;Ãh5ªw$\íëÏ’§þ“<>ø UÝ(Ç'Ëý0æ¨y.wg /LÖðÕâ’”<E28099>M‡ÛÑ´¯üz@«Q½<1A>«|‹FçQ½Aáj_–<øG˜ÔÜo¨ê.9>YèçÇÎv­k xaʰ€¯÷¤ „[p~:¬ØŽ¦àxå׎ê5<C3AA>HåÊ0vÕ›®öõgɃ„IÍý†ªn‘ã“Uþ5ÚŒ9osm骲~Õy7vCVæØ$åëŸoÛÀB¤f×6÷;³®ume
³~ÕywuC^ Tå~°5?lM_ÕÞýœ—~‡½¨®ÿT~= ó¨^Q¾q cÓQ½wáj7ÿž<C3BF>šû UÝ"Ç'«<mÒ´÷¸¶n+³~õ›à“4V&£­ü£eÙu¨Cçe
\ˆž þÍ…)¯L¼‰k«±8ëW?‹slX–ð
tKð³ ¾›Éˆv²Î¯Ý$Ui¯trlX–¤L:/Íáµ Pùõ€þ£z‰à‹ò=bgŒê­ W»ü7„¼Üo¨jÿŸ´÷X¨y3_âÚº-Èúµƒ<C2B5>LŸäÛ¶2<C2B6>h›ã¿-ȱO):/SÈB´Íîƒ SÎν•k‹°&ë×Ö$Û¶,Qé·Mð³ÔLßÍdD;Yá×nÂëÓÁØÒÿ”iÛš„gÚЩ٠¬±Êoì2ª
þ¯ò½`GŽê<C5BD> W»ü׃¼Üo¨jóŸôöLœÙóŸíÚ¢¥fýÚÍÊ’¾Î­@çÿ(5ÓV¥h¾R“ Ñ<»nË7)÷†®M?;ë×n–•ôuhú<68>³û*)ßw3ÑNÖöµ›Øâ´2Ö“m^“ƒ—µùÿçy?ö)‘Êol7ªWŒë”÷¼a?ªw9Üîòß òr?¾ªý;çI„“A>|Dy)R±p¯m¥&Þ¿8‹ß:Á?º'Ùæ‘O·^ëì>¸0åðôº6ñT¯måeÝ¿27¯{Òe­w3ë+póuµ×†ÆzàI¾ýkrðÊ™ÔÿíYf•_ØwT/g*oløpTï{¸Ýå?äå~|U›wΓðB‚\ó”ó¨XI··•—þõ¹³îÉ·yØ“í×<»nË7cÝ»¹3ë<¯ý%å¾Eqn^ú¤Eoe}®½®öÚÖX\u¾vs^FQM À¤òKŒê5doå lFõ1·»üGƒ¼ôϮꓺæØóÿø@DfçP®(Ï;0£æµO<0F>áaœIÓvHñ;¤ü9’ÀùC&iµUZüÜÚ|÷=uÛº0å<µ<>Vût_-ªb¨zî“§¿›Éˆv²ª¯ÝD•%êY!xnùRæþÚÍÊŒªzæ§ç¨üžÀI£z1鮼E Ãø÷¨>àv—ÿb<C3BF>—þÁU}R´KîªU=ñjµ¾ýÖWu—?©Dç=UöS²œ iñ5†òdWF¸òÑ% †´¬°Ù±<C399>÷ª½-ßT—÷ù¯<C3B9>XS“5aÔæ^øÌïf2¢]°â{¹ívx•0û¹ïNj(*¼’ØpÆåò”÷¡a_Gõ9¸®–•þ‘U}R®òìJ‚Ü¢2­(Tˆ]º.5·“WÕ$5¤nÉĶàÿ¦VN~S!-‹pA å9NÆ–1çñ§n[·å›g—þÉ‹óáÌUI ©U¦ÃA†Ïùn&#Úë¾W‘ûo‡Vÿ×ksRœ
oÁãÞ<EFBFBD>´Z¦á «¸WùU<C3B9>ãGõ
³Hy§†10ªO`<60>ß4vL÷ª>©LÃÔª‚Ü¢8­(Ô¼½Z./Ú‡3×$#¶¶ÉfyÀÿ¥‹ÅæÓ*Íácgë°ïvŒ6ÄUÉæÙ«s’¢}8mm5ªr÷äY§F»`é÷*òÛák„ÀÔ½;é¹Rÿ¶E<C2B6>w*¿-pϨ^jb”7’aQ£ú8öø{÷Žé¿n½D)5?ïéÛQ¥y;6[FÀ϶]}5Â#lžïÿZœxUú«Š0#ž†iyX¾ÿ°]À3®J6<4A>>¿ù«ÅF ÂãÜ%ñ¼h?ÏyÛÍŸ<C38D>_¸¯6©Àš;W`ÓPw‰àBå·®Õ+ÏwåMbFÞ¨>`€u?ò\˜þë>Ñ‹“Uóò:ÔªœMÚ´Í2Â~2g“jĹEÊÿµ2ñÂÜŸÄVaFT Óü£<C3BC> {.ë©a<C2A9>¹'Ó<›6LxØO&lRŠð û§ü_±qn”¸ëjËìplœ_;¡Oú ‚ì_„ÃB­ àjåŒÿŒêF¸Zùꆱ~T<À£_xÎþÅ /ý×MÞ 4‰¶C [P¢k ùF;.0Î]R.ɽÿÿ<C3BF>϶±Ζ*$Î<>ò=&ò_Ý“iž}kù×Ùú”"<Î-²þ<C2B2>Ø87JÜuµev 8ví¾ÎÖ'÷qnQ‡“B­ àvåwŒ?Žê¾8Pùš†ÑdTŸFÀÓ_xÎþÅ /ý×­¢—(¸Ú÷DÒœúÜ\ÀØÈ÷ÚnQqn”òm¹ Ïuµóqî•ï?ìùO¶^£&¶®a`ä_ëЪ±qî’µëjáÑ~žó¶›?{»v_gÛ(÷þó:#ÔêÐnW~mÀx>ª›¥»ò2 c‹Q}V<01>~Ó8þƒ¼ô_w‹^¨˜RßOOŠ3iëêÅ®þ^½ê^Y_•ûÖÿÇߪ¦Z`>Ô½òý)øþñ?tIš©¶.``ìÕK±¡n”x¬½ψöóœ·ÝüÙKìÚ-è„@švÇPè¬üæ€1?Þ(/²aŒê“ øáǨ³ÙÈKÿÉÌÇ‹^®ÙR¯‰§gHݨÌÍÕ‹<C395>¯jD…ºQÊ‹sï<73>~çðcëœæ¿M†ú9Ù†ùÿC—¤™g÷Æ¿W)bCÝ(ñX{%žíç9o»ù³<C3B9>ÀÚ.è„@švÇPè¬üò€±f¼[*/‹aW<>ê3øáǨ³ÙÈKÿÉÌ7ˆ^±ñ:gGÒ?ªVTææêÅÆ¿W5¢BÝ(å sïa`l<>Óü·ÉP?'Û0ßÃâè’4óì^ÀÀø÷*El¨{åh¯¬3¢]°ô{y/<2F>µ]Ð <09>4í¦ @gå÷ Ã0 #{T¿l<C2BF>ß~Ó8ûg<C3BB>¼ôw¯ê“ÊäU/<ÈÔ0¶‹­e¹¼z<C2BC>ñïU<C3AF>¨P7J9|¥úçÞ9ÂÀØ:§îs²[ä»{ü—,S­
ÿ^¥ˆ õkîÝÒ<C39D>²WÊÑ.X÷½Š¼—ÀÚ.è„@šöùÂu €¶Ê¯†aFö¨~Ùÿ?—ÿ¦‘—þÙU}R·™–ÞîÍ0FM.¯^`ü{•"*Ú½²~³ëjÛÅÖ9ÍpŸ“Ý"ßÝã¿d™jPÀ¨ø÷ªCl´_Û gæí•oF´ }¯"ï%°¶{-“¦}jϘh«ü<16>a†aä<61>ê×,ðO—ÿ ‘—þ U}R½¼dkŸäû>jryõãß«QѾN´¸†y:G[ç4Ã}Nv‹|w<>ÿ’eªu@£âß«áÑ~í„<C3AD>ŠóÜ^yeD»`q÷*òp¡ø5ªÀßÍdG{R5öÊ€råw Ã0 #iT¿c<C2BF>ºü‡‹¼ô/©ê“f$ûð¹åuÞ%ÎõäòêÆ¿W)¢¢}<7D>hq ótŽ00¶Îi†ûœìùîÿ%ËTë€FÅ¿W£}m¥mSeD» Ô{ù§âTya`²ïf²£=©ÝTW €/Êï†aFƨ~ÁpùÏyéßSÕõ-ôä‰}мW´Ë¨ÆåÕ Œ¯RDEû:Ñâæéa`l<>Ó ÷9Ù-òÝ=þK–©ÖŒŠ¯:dDûÚPÃ2æÉˆ6»ÂÛùaYÊ=‰30åw3ÙÑîU<C3AE>-:öߪkÀ_•ß(0 Ã0ŒØQýjþìò_òr¿§ªë[èÉ[y»€PŠË«ÿ^¥ˆŠöu¢Å5ÌÓ9ÂÀØ:§îs²[ä»{ü—,S­
ÿ^uȈöµ­VeÌ“m^mSÃNõÚÄÍ_ð²£Ý«5í¿UW€?+¿W`†a<18>£ú½
üÙå¿äå~UUW&û¤c»Uxǘ³)ÅåÕ Œ¯RDEû:Ñâæéa`l<>Ó ÷9Ù-òÝ=þK–©ÖŒŠ¯:äEûÚS·2fX_<58> oþ¼˜ø»™ìh÷ªÆ½öT]6þ ü^<5E>a†aD<61>ê—*ðW—ÿh<C3BF>—ûUU]–ì“víYÞ}#OrmB? z<C2A0>ñïUЍh_'Z\Ã<<3C># Œ­sšá>'»E¾»ÇÉ2Õ&~@£âß«©Ñ¾öÔ­Œá2¢Í¨ê‚°“¼Î˜û»™ìh÷ªÆÿzí©ºlüAùíÃ0 ØÕ¯Sà“Ë1ÈËýªª®IöI¯v®íîñǺ¶!‰P½Àø÷*ET´{e«î<7F># Œ­sšá>'»E¾»ÇÉ2Õ&~@£âß«k¢}í¦g£dD^Ò5a'yÅYÿÄážDòn&;Ú½ªñG¯ÝT €?(¿c`†a3£úE
|qóÏ©¹_UÕ5ɾnò>ݵIü€êÆ¿W)¢¢Ý+ëXýsïa`l<>Ó ÷9Ù-òÝ=þK–©6ñ
ÿ^uØ+Úç¾6dlâ{•1#Úð’® {æ¹Ã¡® ;$¼<> æ[mU5v©ÿ@Ѿª€?+¿i`†ac£ú
|wóÏ©¹_UÕɾ.ó>ݵIü€êÆ¿W)¢¢Ý+ëXýsïa`l<>Ó ÷9Ù-òÝ=þK–©6ñ
ÿ^uØ+Ú_{u ÷½Ê˜ml=—…=óܱ8üÐÃ8í…ÎóÿúÜ÷æ>×ó˜4NU~ßÀ0 Ã0~Õ/Oà‘›+HMüªªf'ûºÒûhצ’øÕ Œ¯RDE»WÖ±úçÞ9ÂÀØ:§îs²[ä»{ü—,Smâ0*þ½ê°W´Q¾¶ëÙ/µŒhcë¹,ì™çŽÅ™í¯Â£Ý%ñ5ÑVUc—ú‡—ô˜4NU~ëÀ0 Ã0ž<30>ê×&ðÔµ¿d'~UU³“}Ýê}®kÓÉú€ÒÆ¿W)¢¢Ý+ëXýsïa`l<>Ó ÷9Ù-òÝ=þ<>e:&ÓˆÊú€êEÅ¿WöŠ6PlÇîUÆŒhcë¹,ì™çŽÅ¹]?Ø <0B>çÿõ¹ï#|®ê1iœªüî<C3BC>a†a<Õ/L ò‡‚S+ÈNüªªÖVò`ïs]›~HÖ»—.6þ½Jí^YÇêŸ{çcëœæÍDû9ÙžùžTšÇdúQYï^½Àø÷ªC`´{%nÑc£ ,æÊ°gž;çvýpö9<C3B6>mU5~}â^«¶ã.à•ß@0 Ã0ŒÏ£úU ÿJpäO²v]­C²Wê`ïC]›{HÖ»—.6þ½Jí^YÇêŸ{çcëœæÍDû9ÙžùžTšÇdúQYï^½Àø÷ªC`´{%nÑc£ ,æÊ°gž;çvýpö9<C3B6>mU5~}â^«¶ã.àÊï!†aÆßFõKˆÿ•àÈ
d}UU“’}²L7xêÎÜ£RÞºn±ë¾W)¢¢<C2A2>­áQ1÷O¼s„<73>±E-è2“¡î•ìî‹•—éIÉþW`Ê[—îÚ:F»Wâ+½UúI¡.¨@U…}bUœ3cÞ+ýìh«ªñë÷Zµ½Ž\>(¿<>`†aÿÕïF åW‚ó~(x’²ëjÏåóáJí[ÌãüìÎÄ£RÞºt±‘ïU‡¨hwl€¨˜û'Þ9ÂÀØ¢t<>ùP÷Ê÷ö<>üW_—é°|ÿ#0å­«ù^E¸6ñk›?)Ô¨*ò¯<C3B2>+ rR`Ì{¥Ÿíçù5ív… \ùµÃ0 ÃøÏ¨~%‰¿öCÁ“|·þ]k½¤z>\©­+yCŽ\˜{`¾ûÖ-<ò½êíŽ sÿÄ;G[Ô‚®1ê^ùžyF²w¦8Û»«ØÈ÷*µ‰ßy]íkœ®«=h«8'¼WîÙÑ–4ÃÀãöZµMwS~?Á0 Ã0ª_†@î¯'ýPð$Ù¨”/©jR=W®T­{2ý£«r<C2AB>MvÓºe„½W£Ý®¢îŸuçcc‹ZÓæãüšl«|w;;åc²OvÓÒ…‡½W®M|ñ5Å&ø¤ëjÏÚ*αŸ”{öü»4í»Ÿ’Â<02>ªü¢‚a†qç¨~+~%8㇂'iÆæ«ª3É®\©ƒËØß=¹g¤¹cÝ2>©<02>SuK?0Ôþ)wŽ06¶¯ËZžïD¹K¾ÿk»€ç=Y¦3rOJsÇÒ-.»™Àh/_ú¯³•WàI„[_W˨ðÀ³Ö9)6à“rÏž?©&ÏZä¤íà¡òK †aÆU£ú½Ä(ùù¥UvIù\Õ<>Â&Mþ>Åmù®i¤>’Ü«hyÑn‘þÝÙ±qîžïI±=YÙæ)ÿáùníúÄw¯@^‚{Õ­¤ïf£ÝeÝÿcñº×áal3®I|q…‡´2Èn%Ý%ñeцWxæqÃA¾;Ù+Z”ß^0 Ã0ŽÕï: Òâß^JâÿɲÀÞ;X_Ò¤i›»3ëÿÈSÛ¥b©q6ÏýJ ¶á¶Ít‹Ãc{¸¾%‰gÖ6ÙMã¬MÇR¬Im—¢UUàÝLl´ý×ý?J–¾¤ÏCšŒmMÊ+Ë;ó”eA.(¦ëj©<6A>Xü¬¤Ï®´¬˜”+¿É`†a9ªßo@¼g?½ÜBaÃ%í}¹‡Ø4ìáà;×gYx­R^í1{$pÚw<03>#̈íùB/«@^< “Ý(¼Î¥hR¥À°g‚ï\¢5áµÊwq´yU<79>Òê«uR)˜iM¦  ¹³ È55²[¾åÑæ•ú×§„Äù®³ Œ4T~«Á0 Ã8cT¿Ð€¿OaÃ%í}¨¼Âö7ÚbG)/ÝvOû™ÎKðk$‹—WÃp<C383>#̈í÷<05>‰añã2òÝîé{ ¬Õ¾:To»§7?Ƴ£íYóeaäE>í×'†'>\Òð
‡Ì“ä“§,kŒÀz7³&Ú¨%™$;ÈõÅ €þÊï9†a›Žê7<18>.ü·…)l†¼Š½ÏumF»ì—W//ýw3Ѿ6ס†±:G˜Ûk[·å;¿Ö©®q=LÊýÝLx´¯ý¥–´ƒÏA&e=YÕVÞ"È@<40>«ónfY´¯j[9/pÉh«üÚƒa†ÑT¿¬€¥ª<C2AA>¨§°òÊõ>ÚåuxÝêòê¥&þn&)Ú×¶úÔ0Pçób{m(µ˜'¾—×­0/ëw3Ѿ6—]ÕZ_#LJy¾ª?=.ÕA
\šw3+£}•Ú"Èy±KÀÊoD†aFõë¨ôº˜ÂfH-×ûÙ¥nîuŸ›«· ëw3yѾ6Ô­†Q:G˜ÛkAåÜ)åØÄ÷òºÏåÌNùÝLR´¯=-+l•'á%åWÚ§OLÒ?Â_Åž<03>S-°8ÚW‘-‚œ¾XÀ^÷QØ$Ùµz_CA^w¸¹zËò}7“ík<13>k8¯s„ b{µ’æ^)—7^¯;\^À5ɾ›É‹öµ›¸¢6-ÂÃÀ’2 ªèo<0F>µE<C2B5>\W[ík­-‚œ½JÀ6^wPØ$+ õ¾‰š¼‰n.àú4ßͬ‰öÕÕ‚ìÞ tŽpYl¯–Ü%ëì”·ó:Ôå5\œã»™ìh_;ˆ(dë"üRRŽÓUô¼þŽya`²ïfª¢}åÛ"Èy«<00>赿k X›8…K¯¸¹/Ly;¯ýU—PŸßåÕÌñEx_©y _m„§Æ°þ+ûj&#G~òÿü¿ÿçù¨¨ä¬àÞŒ€o¿<00>ÊOñp›ŸÞþy_ æÃèù<C3A8>¥slúœTöãŽ<C3A3>7óŽÉž¡C«<03>lÕ¿ir¦EÅ0z¯9ÿ›„ÁMÖ¢¼±Ÿ'¢-?ë³R@‰&¹C rø_¥ÿëÞ?‚àN­~]ð³mÉ—–nñŒÙ¥Úäé³wì·á˜wLvw}Zýk„“3Ïõä8ý›_êcˆ=ÃóNþ†!ño­V¡¼±]W‹ÒsÕ€e:lÞ1,æpû‡ÿU:¿îýóîÔðçÐ5¿Ö.þÒÒ'’a»”š<ݶáŽÍ6óŽÉîk‹—Ž6hεå8ý›_êÈ;Éc Õ60þ£á”7¶ëjQ:¯°@‡<>[Àb·sø_¥çëÞ?àZ= ÍŽªäKŸHÆìUmÂõ܉;¶ÙpÌ;&»©†­þ5ˆ¼ c<>šsœþM‡¯s<C2AF>,øê²uœÓku¾¶«PÞØ®«Ei¾|@¶Û¶<€enãð¿JÃ×½þÀµÚþº&°ÅßXš„1f»j«íNܱdžcÞ1Ùõlõ¯á…Ö€qh –éoÊ¿ËŰæ<ß:Îé;YçU(ol×Õ¢ô_A Uùž-` ‡Ûgês•n¯{ÿü€kuþ-telk¾±4 cÌvÕ&Vç<56>¸cƒ Ǽc²ÛiÛê_ÃK(?³@»°L“}ˆžNáQß? 5_…òÆv]-Ê‹ä)ß³N à·¯Ôç*­v„þÀµB^åy_V~KYó<59>¥C cv¬6<C2AC>BV6¯7vì®á˜wLv/!<21>šz :Q›³@»°LSþE.ö鿞êc‹8§×í4!5L]…òžq]-Ê.ë$)ß°Ž à·¯Ôç*}vDÈ?^Ê¿McbßÝá_¿NtøºÒ!†1caï˜)Þ·›n„&Ôêò7c«ßø# ´ ËÔó+køÓwÙ’IqÖ®æ¾Â‹–±
-åF¡–°ýár‡}õèÉáö•ú\¥ÏŽXöÏd] Ý$½²|µ ìy„åÿsÅn_™&CÝ(Sþ-¯]÷Ú}¨ÕåoÆV¿'ðGh–©çWÖðGï²%³ãô½ë¹¼Î<C2BC><C38E>v£¥Ü(Ô¶?\î°¯^=9ܾRŸ«4ÙIß=|¥€-¤¾¯C&/üÍ6ä?=±íW¦Ô¥l•)ÿ¶ QwÙ}(ÔåoÆ>¿'ð7h–©çWÖðGï²%×Äé{×Iß~7ZÇ<5A>B-aûÃåûêГÃí+õ¹J“QøOï  €¾oê¼_àCÂ[üuåÃSšeŠ
ϗíù­Ò/¢?Q¥ËߌýßX ]X¦á÷rÉwæáGï²%›T8öY;ÚèÛïFë¸Q¨%l¸Üa_½zr¸}¥>Wé°#jÿé2?Ðù5<C3B9>÷ üI¿ ?ù­X"_÷²ò‡J¿ˆ>§J—¿<19>¥ýY ]X¦<58>Ê”’“ÏÝeK.‹Ó—®c¾ýn´Ž…ZÂö‡ËöÕ  'ß‚¾RŸ«tØ bð/ h«üGø™<C3B8>÷‰pþA‹ÃXÛ4ùé›|Æ’ù·ÃCJtù›±ù+ ´Ë4P™ì¢e<w—-éKW¹í¾ýn´ˆ…Zb£®2öÕ  '_<>¾RŸ«tØkbè<62>)ðok^Гߎù®òõ)m¿2…Ö3M~Zú¤õZÿÄM)ÑåoÆÎ¯ þÃíÂ2 T&»hÏÝeK®ŒÓ—®3¾ýn´ˆ…ZÂö‡ËöÕ  '_<>¾RŸ«tØkè<>)ðoå?‡ö rÁSž<¢çW¦ðïr=Ó¤É×xÿvxB‰.3Ú)ýY ]X¦±ÊäÕ-é¡»lÉÅqîR–•¶ûö»Ñ"nj Û.wØW/€ž|úJ}®ÒaG,  <S á7<C3A1>™_à×D˜=ÿÃëjµßšÂ£Zü;[Ã’n¡ªzVí õ¹üÍØçÿ.èÖRßg—®ð«BxI¯Z¦ÀÊäÕ-é¡»lÉÅqîR–eòŽš¼çn´ˆ…Zâ˜í>sö7<C3B6>ÀHÖ„ñ5˜ð 3 Œ¤OR¿Føäÿ5ü¹%-_šòHú”¥¼?S²Ï8<C38F>ޝí¯óe°½<C2B0>êÓçØü)ªV<C2AA>î\±eêÙÞ3Ë´Õ/Ô§Q4<À<>[|XdöSV ç<C2A0>UxŽÏßkÝjÛYaÅÆýü#©©ý4yóƒñNËjûk†t_ÿ³<C3BF>ië—±[£
2mÆù0áÀÍ}>ÈÀ§<yâÀT‡ù\™¼º%=4¶mò,Žs—²,SX<53>Ø#ºç"nj‰-¶ÿ×ÿ>ðeýdªòZ dà‰¿†””Ý|ÁÎFy =ô9¤¼€W>´I¿ l¨Ô>Y_–¨Hž|vY0óÕx8a`<»,tRm—íı|3*¿‹þ¥X¿¦µ=<áLØ<4C>á<EFBFBD>¿ìAÃÇõúH¢þ¥<C3BE>ºîQ“/ˆ?»ÿw©Ã×ÇýORR­ÞD@ -¶üš ³Ÿò|þžGqlH<6C>³ ¿×Z•·¡ÚZ<C39A>=±É.ûiæá0´qž¶µ ?â>ÿgc3‡W/v·NÖpìÆìñ×ÕBªWøB¯ó1¾V&£tyOŒj˜l‹ãÜ¥,k,!O?o7
µÄÛì”þ5£çódWl>†À
D•—ÝLÁ¿ÎCm ýäk0Ñ.{b«~ÛP}RU–ØH>ÏPR–À"Ì›æXj=k»l'–¤¼µÎ¥˜ïá±tj{8©&_?>Ø|
ï6Â# ?Ӟ̼¦!Cʵ,‹’:,»n<C2BB>ñ¿-šô|R­ Äû}M„©Où©Î=%6¤<36>ÙBÞk}*ÜMm•ÆÔd—ý4ópz8OÛ#"ü|ûðŸ Ï^ºÀå˜,à×çÞy]­Cé&«^çc|­LFéòžÒ- ,Žs—²¬Q[<5B>ám´ˆ…Zb‹íÿá¿yMÿ4ÉØ#BJô<†±ð6ªó@Á?<0†òúÕ×H2B]ðĆý6¶¡b‹_[–ð`û³°Ÿç fß…Ž­í²<C3AD>XUð}õ,ET<03>eTÛÃyeiòo´1|¶ráÆ>ûuÚÝø5»É<C2BB>'%’WŠ™i£ŠõMl ªÔ¤ú@ˆ-öû‚ð²‹ðëü W$û}÷ëT±¯¶&EneÇ…첌{36ûv«³‘¶GDøáö·ÿlfÚ𺅬ÅdéæO•S¯«Í­Ã =¼ÎÇøZ™ŒÒå=q¾UÖXç.eYcÓjlöF¡–Øbûÿí¿yAÿ4Éä³fê³ °íêüSµ?|60†•EN*ü¡<C3BC>OìÙo*¶OÊ˲&˜<><CB9C>j«ña’À`ÎX訧¯Ù‰ë«½»†¥ˆmà<6D>¤j{x}Y¯x“0><08>m&ß<>Vìó×±çOêá¼Þ‹]âeÛ9ªÁZ%4·Å~_[j&o¸"Q!…ô[Æ«­C‘[Ù±>?œ”`Ôfϵ="ÂO¶Œ3¼hó ’æ‚z>Ÿp}1“*Öä…^çc<©Llõ¾Î–±ÐÝÖzqœ»”e<E2809D>M«±QØ…Zb‹íŸ÷v™9ªzyÁ<ŒjÇ:?¯öß>òt= #6Ô¯³M>®m¿•DÒª,+ëSÌ|5Î8<C38E>zÖvYH‹«}€n¥¨êœ•1ôÜVïUúDòk„á.»ËÔç¯cá©Ö3£kþ%8“NÒ³j“úë¿å³£ÊN|`þžkU“×eç†ï`ÓúDm´-bØnuöÒó ?Ù2ÌðrM.AHŽ“¹‡/Ðúbf”«Ï =¼ÎÇxR™Øê¥>n²O–Yç.eY`þ0©²QØ…Zb‹íŸôv™6ª€ÙÁ< iÓ:wø~{·dñéô$†Ø8SwI¿ýZÿÛ‚éðcoŸ‚T<E2809A>N7Ôös<ËÒ<F«RvÎâ06ÚSºÅó0¼­¯«5ùëXl^á<>^\‡¼"<O'ãAµ[è¿ñSãY<C3A3>rø‹é]d²C¢l¦]ûw{›Væ×˜ÃÓ˜p8€h#=ÏŠçQ= uà³Ãsfd[´<>OU-Ðúbf´JŸzx<7A><78>1³YŸõ¸™&Yieœ“{ç0û–b£È7
µÄÛàýûuòçsŽ}aKúÛßp
OBºó«×@š“•<E2809C>mžy31>1êqô[Æ9Ó¤,}Ž»5Á<‰áÔÓé€ÚÎǸ4—hUŠ5KÆš=•CÉŠ÷ŒêkxáÆvãß>Fl^µ;+£ß&Þž±Û'°Á~šp8’'I[øé\$Ű&ÇV¯ÈyyïʨÏsªM+ókÌáiÌ6ÀŽ ´—‡gWañœ„_·Ïó9KÒœ_µ™<C2B5>ç-ÐÃ<C390>†´²UÂÛxx†‡ìae¢
ødž™gÍ7Û+ãÜ¥&kì[<5B><>"ß(Ô[lÿ’¯©Qý:Õ|$m뼦DQUz>ÉüTïUç“yòVy¯~‹Ê¨OYúw­Þ!I=Ÿd~ª<>Œ²gøµ,“óLóäã7èSŸ<53>÷6K¤ÕÝå†<07>Ý<EFBFBD>Ÿ?ÆO±åe”=Ãï5øOIU öd¯ñ„ÌláÉùSx,{Sd$•ô^xoÛ-“éÖÄ;îƒM+3s`šcE ?"ç<>–kÎϾ¦úäÌg£ª”ùç~<0¤•­²þ…î8<C3AE>¬Lê:>+¶<>ó,‹3|SïnßjlùF¡–Øbû‡%œp~ª<>`¾NRRç-¾z%•zÙ¿æ= u£žµW¿-ûKÙFe™<65>aý\“QÔ<kгWmw܉§êSŸÀÅJÝM+{xå1õ^ëaT%ц?´¼2R)*<2A>™yb[k`ªÀe<C380>œ*|¯•/.°‘¯GÐÃÑ9¶õYL>¢íñ[UíðUk[ár›Vf æÀLǦ~úŽ ´<>nï”çá…$ÕØlþ©;<UÞý|HHá­²rÂáÏ„q˜‡•‰*`ö³>w]ö˜¬CxO|Œ}«±Koo]ä5¶ØþáGGì„“³-hõ3êÜäOl±ÇT‡êa©û%äYGöÛ|j»”%*†’²LÎÕ-MN§#k›ÌOa¬I}b{ØÛä׌º]Püi, ,|Âõÿ;‹ò©–¥³ì¯„×Õ¢x2Ûa lçá»þáhX“È|<ÛúRg¤y‘«lZ–<5A>˜ôgƧúütp¼¶ï×Õšü¯¢\Wës]<<»áHŽñ°2!«9ù¬™G¬ó¥Xó?¨¹¹ù÷-È.½½u‘רbûÇžgÑðœ+SóÕkÁ©òël¨‡¤æ;öŸeD5çÊ­<C38A>”Bøœ+k²¾,3Vf²,!<19>Z[×ÕhRŸ>ÇfŸ^FÕŽøÕO#;ªŒ4g>Ûó6Ѳ&',¬CFϹ¦Áb“› èløÕ~œ¦†´æX›вPÇ,.uF)šW¸Ê¦e‹9$Óአ?}ÇÚWÏ×MÏW̲ ÿ+o`¶¼ˆ2¤ðVÉØáÙÍs†ç•™¯á‚}>²Çd)¢z2<Ú“ì[<5B>]z{ë"¯±Åö<C385> 2)å±iÙ)õ²`Æf› rÍ©RþǔϘ5õA§ö[R$1L³ì„YIŸn‰m<µ ŒÄ7Ò'šÔGÆ¿,¯(Ÿñd$˜úÙŸ&\<5C>ÑâõZŒ:<™-*£±y€-D}XðîîäOa/ž$\mÁÃKѰÂåz6ÞWc1§nÕ†dL×Îü´<19>-›pý¿ò~<7E>0o<30>ÂSXÿ7Ó¿M;3[«?¨<>áyeæk¸àAÚxÁ˜,ÅLOæ…z˜}k²Koo]ä5¶Øþ±A&µÄØ´á‘ÌT{Yeöýø×©\WxVìƒÎë·<C3AB> ;”¥Ïq·ì¬»ðt:¸¶ó&ç$­êÓáØìÓÃáK{XÅúÛðˆ &#»ÔÏæMØdgÍL›Z‡<5A>ÞÚ±Á$¥Ü#ü›@Æ<>Ö'ÈŸÂŽÊý]¡mÁÃ3z_¬íb}6sêVmøAf´zéÌO˜±Ó—M¸øœçÓ™Œ<5‹á<E280B9>2Z%Clv«¢îëye&;dþA3OY3žDØ!Λ;ßšlÔ0ûy<>-¶à"¦öï“'3<í.›¥<»ØB•×üyIy濼¡ß’&œôk0­Ž»¼J–wKùétpmç'ì¶‹:»>ûöp«|™áÍŒ¨02òJýlÞ„±;k,‘ñ Ì<>ºË<>šæ' °‘¶_²GRÝÓ/×¶ÚI½/Ös¥¾Žy2Ù™rUÅ̤gàül;}Ù„U¿ÍvX õ!e´J†ØìVEÝ×O•™)cáS–<53>'îçyö-ËF=³o‘רb)1µ~<7E><)’áwÙ,åÙŪ¼æËš¶|klÚoINú5˜>Ç]j%/?<3F>ήíü„ÝvqCg×gßNjÝ]vć8ÇFÈÓ3ÒIýì¯s¦¦“Ú{U;}—:¬<jw"@ìW‚ªç¦Æù0æÂ©&<26>mAµ'u‹§ƒ†ËôÄpÌ“ù–|vÇ:Rág~ªŒ<C2AA>¾lªßfS#8Ãú<C383>š”ô«ØìVEÝ×O•™)cáS–<53>'–Çù¾Û¾•Ù¥··.ò[¬cà"¦6ïqæ36ó.›¥Cv=§³¬i;l<>Mûm&’$¿Óç¸K=èÆ&?æt:¾¶ŸçLJá*g×gß·IÒºl·#>üë˜hF©ŸMš³Ï¶šŸ<£c¯È3 )|]Â÷#À­ü>Pr6æ=¥|¶1ó…êöJjL7›–e&æí>»ãoà=8³‚ó“dtQøœi69Á.ÐpHêùÁä¶jž]¡Ÿ*³¦þ3‹Õäd˜ïç¤Q<C2A4>w½}‹³Qä…Zb‹í¸‚ÙÍðÓüyÁŒÍÜ|§L6UìQÐsªÂ¦íóÕ«y¿e„43gT _ƒésÜe—q`þcN§<4E>j»8ŒÏìóž-wd}x›ô9À7ZÖ'cæA‘¯f~Ú>Ûª6ª3ê°²Û÷=|€†R¿ Þ.~Pø1[~n–¨ð5ä<35>øÜ¦e™‰yø³“µ
²ÀÀ;1ð8<C3B0>œa4é”9Òl²;.ÐpHMJú5ž3²ëcÍÖ[¶»CÞ†í=?ª3îbßmùF¡–Øbû÷œjrþÔΛ¹ÛN‰m­Øì6êÉðëûˆƒû-oÎá‡þÌpg"ŒÊ(j¦[<5B>À©Ž¯í䜩á gÔ'°<>›ôp޺ܹâ?¥^¢™x’Öký¡:¼d“#)<29>¶ÿôûuþŒx’ ào2N›ªãzøA­^¯!bŸ¾ <20>]
ÛÖ¦eÉ8g²¿O|ǺVÒá“7ÃD®-þýÞdw4\ ªƒnåöÙ+»æÖl½e»{~K®Òó![ã6ûj£È7
µÄÛ?jÂÍð|þÔ`Æf.Ü) ,6»ÀÙʨ_¬ì#î·¼9×”e¸Œ3a§¦Û0±Å œMmcçLÝgØ®>٠ܤ‡óÖe»ÿ*võ/¿®–·;BvnøfÿÜØûÑuµ¼‚W);Ä8Õú×뤌§¯œ°ga›GXØo3&cûxÉCKþ!Ù¼i·[¨ù:g,Søœi6i¿† 4ÒÊ’†5m³‹M35ÂØ?‹d?b&<26>n歷-Ð$Ùæñ÷,Úa‘7<К´_`<60>ÙñGM¾ ÎÏçO flæ•M¸¾Ùb³ œ­jï0°Ùÿýñý¶{Y†Ë8“Åʬ'&¶8<C2B6>³©m윩aæé!¥N òÝÆânÒÃyëÒҵm€™ Þ­ÂÉ3<>-«Þa×Õ—{2 àN©o‡•¡FÍSòz<C3B2>”ôèþÕžÉnMä%á½›Œyàãó…þx«®èд‰*Taû­œs Í&í×p<C397>†CZPÒ<50>¦mvIù¦FûZüé¿<C3A9> éëg»½›v‰ó¼¶ß·òEÞð@kÒ~_ƒ|·á‚dŸÏŸÉØä :!dStÈ.p¶ò 8À¯Éžÿø~Û½,©MÒ<> F`
± œêøÚNÎ9–B”ìR§™ýÜáÀTµ¼‡Sû¡íŠGiØ3 Úª2É3<>ÅV¯Û¿‹g™‰$iþaò`Yv…œ~=ß°eIšvþoŽ[WµI„Ue™”·y“žèºÚÍæk5_çŒe
Ÿ³dc†h¸@Ã!¥–4äl™ÙM% ³ ¯¼ ?’=ÿ“Ïv{7íçym¿oå7мá<C2BC>Ö¤ý¾ùn#*ÂÉ>Ÿ?5’±ÉKB
+³ œ­|ðëG²ç?¾ßv/Kj“‡tcmÃÄÖ'p6µ<36><C2B5>s,…(Ù¥N 2û¹!­ià=œÚ W<C«ClfA×wBÒ<42>ð öuxláuHÝÚ‹s™ &o)þ×Ì©²ò,Jz‹uxÖdlò™¨¶¨êÿ8­zîŒù€š!¤Dá»à}qÓng²VóuÎX¦ð9ÒlÒ~ h8¤¼’†,“'OIÃ,È+/ȱ¼RçŸI§Û»i—8<E28094>lûM‹¿QØ ´>í·ËRFE¸ Ùù÷Qá<51>ëã‰+³ œ­|ðÓ*Îm¿í^–á2f”eM~Ê4¶8<C2B6>³©m윩aæé!¥N 2û¹¿Æ³¬<C2B3>;ôpj?t[ñ<}±™M]¯•m¹fk‡Ç6_·ÀÎäõ߆”· ÿ5|ž¬<…6}Ãæ<C383>É©O›|÷’fQaêsÿÀÀGþ)ë<>ú O²~uú7íŽfj5_çŒe
Ÿs Í&í×p<C397>†CJ*iÈ©2ò”4Ì‚¼ò‚ŒúÔâÅ*¬äOv‰óȶ//þØCËÃ~®á<C2AE>Ö§ývYʨ$û|þÔ`ÆfNŠ'd#Ìo–Øìg+߀Ùõ\¼XGöÛîe.cFY–•ây¦±Å œMmcçLÝ3O)uj<75>ÙÏý)˜• Ü¡‡Sû¡ÕŠgkrˆÍ,hêzýØd$Ëv÷@x¿~<|5Ͼ®öùA
ôT²µ‡º2Ô¼·XöȨF«/?_?2\®’×\çEÿaêsg˜ø§‡†Ôgx’õ«Ó¿i'•„=óÐù€3ò Ÿ³ä(Ñp<C391>†CZÙ*3§JŸìÖ¤ŸáU3}w²KœG¶}yñÇ(û¹†ZŸöÛe)£"\<5C>ìóùSƒ›9#žS¿zÎV¾³ë¹r±Ní·ÝËòpÎ5e)ßqÙ!Φ¶±s¦n„™§<E284A2>+ƒÌ~îóHf*6–]‡Î[—n<E28094>Öð§øð8grO-ÚO<C39A>MFÒç¨ù£5uX° ú5¿>ñùÈ‹ HUµ¯Çº2ÔŒï Þ,ë R2ÒÛªÕ^èó.ÿ0ðô<C3B0>hNUœðç§§Ö´“ºíµgä>gÕQ0¯á ‡´2’™3¤Iv©XÙÒ©õ\¿X…•üÉ.qÙöµ;ÎuµËÛo—¥ŒŠpA²ÏçO flæðx’Ú¾Cv<43>³•oÀÔzvXâúm÷² ?å‰_g.ßqÙ!Φ¶±s¦n„™§G yAf?·á±9ù©Ø9óÖ¥[§5ü)><Ιܳ‹öpþùåkrÔüÍógY° ú53Ñ~k®ý&àºÚÃG¸®6›Üß¾ýÇ–8$Ú‡Ï-o?}{Lþt2ò Ÿ³ê(˜×p<C397>†CZÉúµIÃ4”ú†Ê›ù×Ïv[ë]â<Uaý‡ÏÃ<C38F>zf£PKlQŸÀ³“ýiþ¼`š|9ù| Ïß!»<>z2/€'Ì›ùª~; ,y}Þ'’aÇœNÇ×vrÎÀ xª&õirlÎ|êÔ<JÕfxhxœ3¹gíalóa49j>˜©CŸk{}Žš_}¨m‡ð€»|p]­ä)_·~þ¤÷‘\ÏâŒ=:*Ú'ó¬|Vì9ãÍØö_Cás¤Ùä`o¸@Ã!ÅFò!Œ¤iÇ>8ÆIRßPy3ÿúÙnk½Kœ§*¬ø!Ö°g6
µÄõ Œ0;ÙŸæÏ ¦Ã—“­•4íØcè<C383>jÌpO>˜7óUýv@Yòú¼O$ÃŽ9<C5BD>ޝíäœá;ñ<êÓçØüüÁ±0Ææìs€*yôÀCÃãœéíE{òˆù0:57Ô¡ÏQ“±_:„Ì(Ù×cO\çpY–Õsñ™œú ŸIJÜ îƒª/ÃÏ<C383>
õë<<3C>ežGßfhÕð ¢ÍH¶Ã)<29>·Ž!'’ëjÂ8 »“佡òføl·µÞ%ÎS%P©Ïݨg6
µÄõ Œ05Ù_‹™Lø¾〯^»ôdj_?˜7ómýv@Y’ú<0’·Þ1§Óñµ<C3B1>œ³a}ºéPŸ>Çæçp‡¤vG”<}à‰}Z±Éuµ<75>…ë?‰0¯ËRXO^:M"Ný&àºÚÁÏúiò¤H¼Ý6:(¾>7*Ô¯O¬ÉðTúöø†_íÊC5|ÂÅ?# LÛp<C39B>†CŠ<43>$i£5Éî$3•ùüÙ¤iÇ>Ûm­w‰ó`%Kðá¡­þ:i£PKlQŸÀSóýuò¤`Â÷õâ0¶Î®vª13|þlÒ´öÛe9>’ÇœNÇ×vrΆõé¦C}úVŸ?˜Lxðca¸®6ù‘±šüUèkx!1lq<1A>աϵ½<C2B5>É›/Êm„lê]n‚õ rq1W>®Ï»2) o·<6F>Š•gÅç©–=(ãƒìÒð©Ÿý<CFF\Wû5’† ÔátmøBwœfTæóg“¦ûl·µÞ%΃íõíw¯žÙ(Ô[Ô'0ÂÔ|<><)˜áicƒIªóyÙ•oÀ™>6iÚð,N½`Ъ,Õ <0C>¤Ã¦;øt:»¶“s&í‚“t¨OŸc3/ž­ð(»üáLÖkÊõù)Q1t8mÊë<C38A>º&_ÐíûY@†-¾ ¬|g}ˆpøºZx<5A>}nÇ-ž9#ŒÅ•ÜÔÊ*}~V“ëj±ÕžJß&ésž/uñ¹ºû{ù×9óhq1;ÿnß0»“ÌTæÃg“¦þl·µÞ%γÍ)±Ï:ì/n…Zb‹ú¬ùJÐêÖDFv¾zõÌ®|Îðá³IÓfdÑ¿ßÎ(Ëp1ûGòyæáDNº®vFm'çÌ+Î1:Ô§Õ±Ù§‡ûà<>0ö¸Ø '˾¦\žX<>¼Õ_°X ®íµúwñ²ÖÏ Ôš|-.{Ö²Ã'<¼r囼+Çàíö°J±…š|К¯R±uè<75>,UÇBRû®¶ø_Cy14)fçßífw’¼.9µ2Ž… »Äy¶¨Ž<C2A8>Öä ïf6
µÄõYó• ÕÏòIÿœûø@$ÇõZ°jc<6A>­àk×Ι—Å@já) ÇÓ$Œ<>Ž»<C5BD>.ýuæ<75>OÅÆ°fª³k;9gReNÒ¡>­ŽÍ>=Þ½ygEφŸádÊjÕ¤c3GMµìRܰØn_Àú9<C3BA>Zï—<C3AF>g öÈï*ÙÑÆ>+cÎe×ÕVöÿîÖÔjþ)±á}<7D>'õ)y¤ÏÉ0ù”ù 3r ,ÝäZÄ.âÀly Ô§˜¿†‘1[·ìN’×À%§Vì™<C3AC>g—8<E28094>Õ´ ž²QÏlj‰-ê³æ+AÕœQÁÌ¿øÖÔ䌯^<5E>³•oÀÉž4^ÔœyY äžÂpH”¥ÏqWòwÌØHgSÛØ93*s˜õÙåØާÃMÔÉšDYFx””}Ùz} 5$€Œ¥<C592><C2A5>sA¶Ãíý߯€>’^1?=eøã!±=‰°áuµÅÏ]ù®\CÒ÷ŠSe—+jþe]˜~çƒñZk‡¼†o{]í§™ç÷]à"ŽM•·@}Šù<†‡ñÄÎV’ÝIRxý©Ûxyv‰óx<C3B3>}›=ÿF=³Q¨%¶¨Ox„±»lr¶<72>]òâ‹­slkí’]íTcò^ásŽ…ñð¡¿&žÂpTc‰´*ËOQ…4[H£FMÛ- ’º¶¶“sÆ–åHê³Ë±9š_ýÖž¯I 5‘d4@IÙ—­×“hçŸ>mFœ J;gF·‡çU>ÐJỦä
ʯ®ü_4F¾òY±_ÉÆ>€Üå-pÚØ¥|Þ*®«<C2AE>§dÑ£¾öºZöM¼<4D>mUç’hRÌØV‰ÚYSs]mز5ZRH ìç Âø§™Cf{7³Q¨%¶¨Ox„köBÈËâÉ$Ï _½dW;Õ˜ek”ÒÙývLYúwIõûøó’fSÛØ9C
r¶õYÖºÛõpȾ©I¬Ôx-*ÇVz¾}RWgý? Ç‚ìÐ¥!S­,]ÕT@CI'màœ%oÀ‡*<Î!«™Tꨧ{Á}^ºeöI90f}›*ié—í É~Jê§À¾Î{JÏO’”Ë×ȳˆªÃóD¢’HÍuµa 8jÂÉ`Þ<>ìç%¢Î™¼ ÷ê™<C3AA>B-±E}2"Ì{•/Û¤Ï?5™ÑÃ,~M*°,}²«<C2B2>jÌ|! 4ÒÙývLYúwË~p^ÿ;[àl=ËRXÛÉ9g¹D‡ú¬iÝçîÒÃO&‰ªI¬¤¨ç\SónZÓ-©e r—:ôl°ò ìâ§×å‡í??C`xQc8¶w¾•çóLÑBª½àéëWp;óeL]ˆð¥\Ð*ÃsêÛlQçFêÉ39UR<17>%›t8¤3ùôòøŸÛ*ÃQ äµ>»“ÌW&p/χ4Ü?±c&Îç…"Ðü*gôÉŽ½­½Ï¨OF„Ã<E2809E>¶õž‹a¨À‡õ
œ­|ξ#f8»ßŽ)Ëä䅑̤0Æ“RgSÛð9ç›öl©gÂÚ¯iÝçë¾Wÿqªðš„[ß<?¥96aFÙW®×²V®Ï²–îóˆ™6› cA^ߎ èæ§“0dtŽía<C3AD>å'äâÊ[¢Õê_«ó*d,ev«„o‡™`¨íö<C3AD>囜<¯‹ú”k£§w.fx«¬Iª*»c„T&d+…„´¸ë†C<E280A0>ª<15>º5Imx3akïê“a‡þ\<19>¯^<5E>ÙΖÔÞ‹ˆÝ±K|@¿S–•QÆÃbæÍ¦¶µeyßgAÛ<)r‡¾“Qç™Ï®¬ÉÁ½WÞp…ŸÍzÍSjûùŒ:ÌÄÐ6¯™À€†¼Æ<0E>•<EFBFBD>ýdù ¹þ”®m‰n p­¶K<C2B6>±”Ù­2<§¾]£ù™39^Å–e2ÎÂõ
™°C1Ã[%iQšdwŒ<77>Ê„l¥<6C><C2A5>wÝp¨Qµ"VŸ)Œm>rí}@}ò"lµ­ÊÿR^çVš•ª<E280A2>jLH±;"v‰è·cʲ2°aLÆð¼˜I³©møœ9ž$µgž¹C _ƒÉ¨óäÇ—Õ$IŸEO<45>m£¿
-k•Vk=^Dêÿ]œ‘]óźI=4†O<E280A0>5Qýd“r}µ-‘ñèë¸<C3AB>{ðyT©™ÎL¾Ñ?Ln¶ Û×üíùǧköslŸÃž<C383>³j½¢æ,/fF«d,Jlyg²;CHe¢vÓ|Há-7ܨÃqþT+Âuh<75>ªÀ¢‚×ÞÔ'5Â>Û**_½d8[ù vS Orj¿S–ðÀzþ³=*€ç3$ͦ¶ás&¥yŒ¤†(rƃÆÖº[Ö§ÃW Œ¼†»nMlýU(©’cÏZ¹Ö¿†õ”ò'%Ø|q<>†’Î<E28099>áÓ#5žá›’%aÔ¶Dø£;¬ãŽÊ÷àó<C3A0>R3Mš<ïƒtkøexzþÙ™xÆbûITœ%ë5mm1“Z¥É =)»,Øz+C
ì·ù^]S.Â6FITá)hïê“a“mÏçÆž[˜ÎOÙ¹®6&*€À}13Ï‘ývLYb›/KR‰VþOcRgSÛŒ9“2=Cl«L9ü)±adÔ9d’<64>š¼KUµÜ‚À>Ï3ÀLR3)/~Üʵþ)°ÀÕþ»8/ÁØ•-?£€¸‚RaŸC²êÄÞº%N8]¤óõ9(\WÓ´Ûuûúïù?;ÕXx‹!0Îõë8a1›4pRW/Ø›ŠªLàžš™g¾ÙBÆÊr‘d}W,Ž'/ í}@}ÖDX¾­&ãyòÙ±'®Ïåk ¡Æf8[ùŒ
pkLÎs^¿S–¨Øš„‘ýÜ“N§3j2gvÊ[ é“À
‡Ï?FÃ~2Õò´íüõÍ–Ø“I†Ÿ’Ú@¾ëŸ¸r­ŸGþ¸ªg'Øsq<73>æ:!1¬9±KŽÊÚ`
ß&<26><>›*?%>‡‘—]aÌ:v놯ú#ÚÃOÅÆ6ù£wFœë×+ð)%ÅÌn•ÀM4PÞea;Q• ÜY+÷NÒXY.R-h†e‘¬émí}F}VFX»³Æâyþ©±g­ÌåáÓÖ"6»ÀÙÊ7`T<00>$dž“ú혲ÌÇ–T–_ÃXóÄòÙÔ6oÎìÄ75Ü!©­8ó@$m{øëlOžÒ¿ó—µYjT?>üÜð¿>1»Iú¬õ×<C3B5>òž¸þßÅkrl¸¸À|Pز÷hõf,`>†!-þ³`àlï uØGú|€óì¾³:¼{mÙ‹~;¾,yÁŸT¥nÔv‹Óø_šö«³+ó°VæÛ!†ãõ_îÂGïÞo§æ…üÞ\ÂqœÍ· 9ÿópàŽ;àl¾êýù‹p Çp6ßv€Xwð  !ÇÀ¯|ÛšÿõÁÿ×x@OŽ;€Ÿøª„s¸„ãà'¾êáb¯[|˜Í5€ZŽ;€ç|Ï2Þ¸pyèÌqðœ¯:@†Ï—.þ1âë$þ¨”sÜ<ä{<00>çÉí‹?þaâáýQhÂqð_ÿþã«°Àókc£:?€ÿËqð_¾êUÜß.á¸ø_u€B.o—pÜüú¥¨:Xà@nn—pÜø¶”sy¸„㸜/<@nn—pÜ7ó…hŵ àŽ;àB¾óüíÁ  þ©o7  ?ój+T
endstream
endobj
127 0 obj
<</Title(Slab-On-Grade Design)/Author(Conemco Engineering)/Creator(Typst 0.15.1)/ModDate(D:20260903203734-04'00)/CreationDate(D:20260903203734-04'00)>>
endobj
128 0 obj
<</Length 1174/Type/Metadata/Subtype/XML>>
stream
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?><x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="xmp-writer"><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:xmpTPg="http://ns.adobe.com/xap/1.0/t/pg/" xmlns:pdf="http://ns.adobe.com/pdf/1.3/" ><dc:title><rdf:Alt><rdf:li xml:lang="x-default">Slab-On-Grade Design</rdf:li></rdf:Alt></dc:title><dc:creator><rdf:Seq><rdf:li>Conemco Engineering</rdf:li></rdf:Seq></dc:creator><xmp:CreatorTool>Typst 0.15.1</xmp:CreatorTool><dc:language><rdf:Bag><rdf:li>en</rdf:li></rdf:Bag></dc:language><xmp:ModifyDate>2026-09-03T20:37:34-04:00</xmp:ModifyDate><xmp:CreateDate>2026-09-03T20:37:34-04:00</xmp:CreateDate><xmpTPg:NPages>1</xmpTPg:NPages><dc:format>application/pdf</dc:format><xmpMM:InstanceID>oBAM8AmI8aSAsY4e75FCMQ==</xmpMM:InstanceID><xmpMM:DocumentID>N4kjbvDt0cm9AtUu+xPiqg==</xmpMM:DocumentID><xmpMM:RenditionClass>proof</xmpMM:RenditionClass><pdf:PDFVersion>1.7</pdf:PDFVersion></rdf:Description></rdf:RDF></x:xmpmeta><?xpacket end="r"?>
endstream
endobj
129 0 obj
<</Type/Catalog/Pages 1 0 R/Metadata 128 0 R/Lang(en)/StructTreeRoot 8 0 R/MarkInfo<</Marked true/Suspects false>>/ViewerPreferences<</Direction/L2R>>/Outlines 7 0 R>>
endobj
xref
0 130
0000000000 65535 f
0000000016 00000 n
0000000069 00000 n
0000000143 00000 n
0000000229 00000 n
0000000332 00000 n
0000000425 00000 n
0000000531 00000 n
0000000596 00000 n
0000000760 00000 n
0000001848 00000 n
0000001939 00000 n
0000002005 00000 n
0000002086 00000 n
0000002197 00000 n
0000002259 00000 n
0000002361 00000 n
0000002423 00000 n
0000002492 00000 n
0000002608 00000 n
0000002670 00000 n
0000002773 00000 n
0000002835 00000 n
0000002904 00000 n
0000003034 00000 n
0000003096 00000 n
0000003199 00000 n
0000003261 00000 n
0000003330 00000 n
0000003454 00000 n
0000003516 00000 n
0000003619 00000 n
0000003681 00000 n
0000003750 00000 n
0000003880 00000 n
0000003942 00000 n
0000004045 00000 n
0000004107 00000 n
0000004176 00000 n
0000004330 00000 n
0000004392 00000 n
0000004495 00000 n
0000004557 00000 n
0000004626 00000 n
0000004747 00000 n
0000004809 00000 n
0000004912 00000 n
0000004974 00000 n
0000005043 00000 n
0000005167 00000 n
0000005229 00000 n
0000005332 00000 n
0000005394 00000 n
0000005463 00000 n
0000005581 00000 n
0000005643 00000 n
0000005746 00000 n
0000005808 00000 n
0000005877 00000 n
0000005960 00000 n
0000006121 00000 n
0000006183 00000 n
0000006287 00000 n
0000006349 00000 n
0000006418 00000 n
0000006519 00000 n
0000006642 00000 n
0000006704 00000 n
0000006808 00000 n
0000006870 00000 n
0000006939 00000 n
0000007118 00000 n
0000007180 00000 n
0000007288 00000 n
0000007350 00000 n
0000007419 00000 n
0000007520 00000 n
0000007659 00000 n
0000007721 00000 n
0000007829 00000 n
0000007891 00000 n
0000007960 00000 n
0000008064 00000 n
0000008126 00000 n
0000008230 00000 n
0000008292 00000 n
0000008361 00000 n
0000008480 00000 n
0000008584 00000 n
0000008695 00000 n
0000008799 00000 n
0000008882 00000 n
0000008986 00000 n
0000009048 00000 n
0000009117 00000 n
0000009323 00000 n
0000009359 00000 n
0000009395 00000 n
0000009437 00000 n
0000009480 00000 n
0000009521 00000 n
0000009565 00000 n
0000009605 00000 n
0000009760 00000 n
0000009920 00000 n
0000010602 00000 n
0000010820 00000 n
0000010977 00000 n
0000011470 00000 n
0000011684 00000 n
0000011835 00000 n
0000012422 00000 n
0000012630 00000 n
0000012748 00000 n
0000012830 00000 n
0000013497 00000 n
0000019783 00000 n
0000019864 00000 n
0000020437 00000 n
0000024200 00000 n
0000024283 00000 n
0000024939 00000 n
0000030591 00000 n
0000033671 00000 n
0000034078 00000 n
0000034421 00000 n
0000082019 00000 n
0000149132 00000 n
0000149301 00000 n
0000150553 00000 n
trailer
<</Size 130/Root 129 0 R/Info 127 0 R/ID[(N4kjbvDt0cm9AtUu+xPiqg==)(oBAM8AmI8aSAsY4e75FCMQ==)]>>
startxref
150738
%%EOF

View file

@ -0,0 +1,74 @@
#import "assets/sheet.typ": calcline, calcsheet, check
#show: calcsheet.with(
title: "Slab-On-Grade Design",
project: "Pinecrest Residence",
prepared-by: "Conemco Engineering",
)
#let round(value, digits: 2) = calc.round(value, digits: digits)
= Slab-On-Grade Design
Considering 4" thick, 3000 psi slab on grade with 6x6 w.2.1. For interior use.
== Input Data
#let t = 5
#let L = 15
#let fc = 3000
#let wc = 150
#let fy = 60000
#let fs = (2 / 3) * fy
#let DL = 20
#let LL = 100
#let b = 12
#calcline([$t = #t " in"$], [Slab thickness])
#calcline([$L = #L " ft"$], [Max joint spacing])
#calcline([$f'c = #fc " psi"$], [Concrete strength])
#calcline([$omega_c = #wc " pcf"$], [Concrete density])
#calcline([$f_y = #fy " psi"$], [Steel strength])
#calcline([$f_s = (2\/3) f_y = #fs " psi"$], [Working stress])
#calcline([$D_L = #DL " psf"$], [Dead load])
#calcline([$L_L = #LL " psf"$], [Live load])
#calcline([$b = #b " in"$], [Design width])
== Acting Load
#let w = wc * (t / 12) + DL + LL
#calcline(
[$w = omega_c dot t + D_L + L_L = #round(w) " psf"$],
[Design lineal load],
)
== Required Steel Reinforcement
#let F = 1.5
#let As_req = (F * L * w) / (2 * fs)
#calcline([$F = #F$], [Subgrade friction factor])
#calcline(
[$A_(s,"req") = display((F L w) / (2 f_s)) = #round(As_req, digits: 4) " in²/ft"$],
[Required steel reinf area using subgrade drag equation],
)
== Provided Steel Reinforcement
#let As = 0.058
#calcline(
[$A_s = #As " in²/ft"$],
[Provided steel reinf. area #linebreak() WWF 6"x6" 2.9x2.9],
)
#v(8pt)
#check(
"Provided steel reinforcement",
As_req,
As,
unit: "in²/ft",
demand-label: [$A_(s,"req")$],
capacity-label: [$A_s$],
)

Binary file not shown.

BIN
steel-beam/assets/logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View file

@ -0,0 +1,82 @@
#let navy = rgb("#1a3a5f")
#let muted = rgb("#626b73")
#let pass = rgb("#1f6b45")
#let fail = rgb("#9b2c2c")
#let calcsheet(
title: "Structural Calculation",
project: "",
prepared-by: "",
body,
) = {
set document(title: title, author: prepared-by)
set page(
paper: "us-letter",
margin: (x: 1in, top: 1.25in, bottom: 1in),
header: context {
grid(
columns: (1fr, 1fr),
align: (left, right),
image("../assets/logo.png", height: 30pt),
[#text(size: 9pt)[Project:] \
#text(size: 10pt, weight: "bold")[#project]],
)
},
footer: context {
set text(size: 8.5pt, fill: muted)
stack(
spacing: 4pt,
line(length: 100%, stroke: 0.5pt + muted),
[#prepared-by],
)
},
)
set text(font: "Libertinus Serif", size: 10pt, lang: "en")
set par(justify: true)
set heading(numbering: none)
show heading.where(level: 1): set text(size: 14pt, weight: "bold", fill: black)
show heading.where(level: 2): set text(size: 11pt, weight: "bold", fill: black)
show heading.where(level: 2): set block(above: 2em, below: 1em)
body
}
#let calcline(formula, note) = grid(
columns: (1.7fr, 1fr),
gutter: 4pt,
align: (left, left),
formula, text(size: 9pt, fill: muted, note),
)
#let check(label, demand, capacity, unit: "", ok: auto, demand-label: "Demand", capacity-label: "Capacity") = {
let utilization = demand / capacity
let passes = if ok == auto { utilization <= 1 } else { ok }
let color = if passes { pass } else { fail }
block(
breakable: false,
width: 100%,
stroke: 0.8pt + black,
inset: 8pt,
radius: 2pt,
)[
#grid(
columns: (1fr, auto),
[#text(weight: "bold")[#label]],
box(stroke: 0.8pt + color, inset: (x: 6pt, y: 2pt))[
#text(weight: "bold", fill: color)[#if passes { "OK" } else { "NOT OK" }]
],
)
#v(4pt)
#grid(
columns: (1fr, auto),
[
#demand-label: #calc.round(demand, digits: 2) #unit #h(14pt)
#capacity-label: #calc.round(capacity, digits: 2) #unit
],
[
D/C: #calc.round(utilization, digits: 2)
],
)
]
}

255
steel-beam/calc.py Normal file
View file

@ -0,0 +1,255 @@
from __future__ import annotations
import json
import math
import sys
import argparse
from pathlib import Path
from zipfile import ZipFile
from xml.etree import ElementTree as ET
try:
import yaml
except ImportError:
raise SystemExit("Install dependencies: python -m pip install -r requirements.txt")
try:
from pint import DimensionalityError, UndefinedUnitError, UnitRegistry
except ImportError:
raise SystemExit("Install dependencies: python -m pip install -r requirements.txt")
HERE = Path(__file__).resolve().parent
DATABASE = HERE / "aisc-shapes-database-v15.0.xlsx"
NS = {"m": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"}
ureg = UnitRegistry()
ureg.define("kip = 1000 * force_pound")
ureg.define("ksi = kip / inch ** 2")
ureg.define("psf = force_pound / foot ** 2")
def quantity(value, unit: str, name: str) -> float:
try:
q = ureg.Quantity(value).to(unit)
except (DimensionalityError, UndefinedUnitError, TypeError, ValueError) as exc:
raise ValueError(f"{name}: expected {unit}, got {value!r}") from exc
magnitude = float(q.magnitude)
if magnitude <= 0:
raise ValueError(f"{name} must be positive")
return magnitude
def _shared_strings(book: ZipFile) -> list[str]:
root = ET.fromstring(book.read("xl/sharedStrings.xml"))
return ["".join(t.text or "" for t in item.findall(".//m:t", NS)) for item in root.findall("m:si", NS)]
def _cell_value(cell: ET.Element, shared: list[str]):
value = cell.find("m:v", NS)
if value is None:
return None
text = value.text or ""
if cell.get("t") == "s":
return shared[int(text)]
try:
return float(text)
except ValueError:
return text
def load_section(label: str, path: Path = DATABASE) -> dict[str, float | str]:
with ZipFile(path) as book:
shared = _shared_strings(book)
root = ET.fromstring(book.read("xl/worksheets/sheet2.xml"))
rows = root.findall(".//m:sheetData/m:row", NS)
headers: dict[str, int] = {}
for cell in rows[0].findall("m:c", NS):
# The workbook repeats the metric section after the first 84 columns;
# the first occurrence is the US customary section used here.
headers.setdefault(str(_cell_value(cell, shared)), _column_number(cell.get("r", "A1")))
label_column = headers["AISC_Manual_Label"]
wanted = {
# Use detailing dimensions for d and thicknesses, as shown in the
# reference sheet; nominal dimensions are also retained in the source.
"A": "A", "d": "ddet", "b": "bfdet", "tf": "tfdet", "tw": "twdet",
"Ix": "Ix", "Zx": "Zx", "Sx": "Sx", "Iy": "Iy", "Zy": "Zy",
"Sy": "Sy", "ry": "ry", "J": "J", "rts": "rts", "ho": "ho",
"lambda": "h/tw",
}
for row in rows[1:]:
values = {_column_number(cell.get("r", "A1")): _cell_value(cell, shared) for cell in row.findall("m:c", NS)}
if values.get(label_column) == label:
result: dict[str, float | str] = {"label": label}
for name, header in wanted.items():
raw = values.get(headers[header])
if raw is None or raw == "–":
raise ValueError(f"Section {label} has no usable {header} property")
result[name] = float(raw)
return result
raise ValueError(f"Section {label!r} was not found in {path.name}")
def _column_number(reference: str) -> int:
letters = "".join(ch for ch in reference if ch.isalpha())
number = 0
for letter in letters:
number = number * 26 + ord(letter.upper()) - ord("A") + 1
return number
def compute(inp: dict, database: Path = DATABASE) -> dict:
beam_length = quantity(inp["beam_length"], "ft", "beam_length")
unbraced_length = quantity(inp["unbraced_length"], "in", "unbraced_length")
moment_kipft = quantity(inp["Mu"], "kip * ft", "Mu")
shear_kip = quantity(inp["Vu"], "kip", "Vu")
E = quantity(inp["steel_modulus"], "ksi", "steel_modulus")
Fy = quantity(inp["steel_yield"], "ksi", "steel_yield")
service_load = quantity(inp["service_load"], "lbf/ft", "service_load")
Cb = float(inp.get("cb", 1))
c = float(inp.get("c", 1))
if Cb <= 0 or c <= 0:
raise ValueError("cb and c must be positive")
section = load_section(str(inp["section"]), database)
# The entered demands are the factored moment and the factored reaction on
# the connector (used here as the factored shear). They arrive from the load
# determination, which is based on a uniform gravity load, so the equivalent
# factored uniform load is recovered from the shear: w_u = 2 V_u / L.
factored_uniform_load_kipft = 2.0 * shear_kip / beam_length
Lb = unbraced_length
Lp = 1.76 * float(section["ry"]) * math.sqrt(E / Fy)
rts = float(section["rts"])
Sx = float(section["Sx"])
ho = float(section["ho"])
J = float(section["J"])
Lr = 1.95 * rts * E / (0.7 * Fy) * math.sqrt(J * c / (Sx * ho) + math.sqrt((J * c / (Sx * ho)) ** 2 + 6.76 * (0.7 * Fy / E) ** 2))
Fcr = Cb * math.pi**2 * E / (Lb / rts) ** 2 * math.sqrt(1 + 0.078 * J * c / (Sx * ho) * (Lb / rts) ** 2)
Mp = Fy * float(section["Zx"]) / 12.0
if Lb <= Lp:
Mn_ltb = Mp
ltb_mode = "yielding"
elif Lb <= Lr:
Mn_ltb = Cb * (Mp - (Mp - 0.7 * Fy * Sx / 12.0) * (Lb - Lp) / (Lr - Lp))
ltb_mode = "inelastic LTB"
else:
Mn_ltb = Fcr * Sx / 12.0
ltb_mode = "elastic LTB"
Mn = min(Mp, Mn_ltb)
phi_mn = 0.9 * Mn
Aw = float(section["d"]) * float(section["tw"])
lambda_lim = 2.24 * math.sqrt(E / Fy)
kv = 5.34
lambda_web = float(section["lambda"])
cv1 = 1.0 if lambda_web <= 1.10 * math.sqrt(kv * E / Fy) else 1.10 * math.sqrt(kv * E / Fy) / lambda_web
phi_v = 1.0 if lambda_web <= lambda_lim else 0.9
phi_vn = phi_v * 0.6 * Fy * Aw * cv1
# Serviceability deflection under the service uniform load (L/240 limit).
L_in = beam_length * 12.0
w_serv_lbf_in = service_load / 12.0
delta_limit = L_in / 240.0
delta = 5.0 * w_serv_lbf_in * L_in ** 4 / (384.0 * (E * 1000.0) * float(section["Ix"]))
def q(value: float) -> float:
return round(value, 6)
values = {
"beam_length_ft": q(beam_length),
"unbraced_length_in": q(Lb),
"factored_uniform_load_kipft": q(factored_uniform_load_kipft),
"service_load_lbf_ft": q(service_load),
"moment_kipft": q(moment_kipft),
"shear_kip": q(shear_kip),
"E_ksi": q(E),
"Fy_ksi": q(Fy),
"Lp_in": q(Lp),
"Lr_ft": q(Lr / 12),
"Lb_ft": q(Lb / 12),
"rts_in": q(rts),
"Fcr_ksi": q(Fcr),
"Mp_kipft": q(Mp),
"MnLTB_kipft": q(Mn_ltb),
"Mn_kipft": q(Mn),
"phiMn_kipft": q(phi_mn),
"Aw_in2": q(Aw),
"lambda": q(lambda_web),
"lambda_lim": q(lambda_lim),
"kv": q(kv),
"Cv1": q(cv1),
"phi_v": q(phi_v),
"phiVn_kip": q(phi_vn),
"delta_limit_in": q(delta_limit),
"delta_in": q(delta),
"ltb_mode": ltb_mode,
}
values.update({f"section_{key}": q(float(value)) for key, value in section.items() if key != "label"})
return {
"tool": "steel_beam",
"version": "0.1",
"project": inp.get("project", ""),
"prepared_by": inp.get("prepared_by", ""),
"section": section["label"],
"values": values,
"checks": {
"flexure": {"demand": q(moment_kipft), "capacity": q(phi_mn), "ok": moment_kipft <= phi_mn},
"shear": {"demand": q(shear_kip), "capacity": q(phi_vn), "ok": shear_kip <= phi_vn},
"deflection": {"demand": q(delta), "capacity": q(delta_limit), "ok": delta <= delta_limit},
},
}
def summary(result: dict) -> str:
values = result["values"]
checks = result["checks"]
def status(name: str) -> str:
return "OK" if checks[name]["ok"] else "NOT OK"
return "\n".join(
[
"Steel Beam Design Summary",
f"Project: {result['project']}",
f"Section: {result['section']}",
f"Span: {values['beam_length_ft']:.2f} ft",
"",
"Demands",
f" Factored moment, Mu: {values['moment_kipft']:.3f} kip-ft",
f" Factored shear, Vu: {values['shear_kip']:.3f} kip",
f" Service load: {values.get('service_load_lbf_ft', 'see input')} lbf/ft",
"",
"Strength",
f" Flexure: {status('flexure')} ({values['phiMn_kipft']:.3f} kip-ft capacity, D/C {values['moment_kipft'] / values['phiMn_kipft']:.3f})",
f" Shear: {status('shear')} ({values['phiVn_kip']:.3f} kip capacity, D/C {values['shear_kip'] / values['phiVn_kip']:.3f})",
f" LTB mode: {values['ltb_mode']}",
"",
"Serviceability",
f" Deflection: {status('deflection')} ({values['delta_in']:.3f} in / {values['delta_limit_in']:.3f} in limit, D/C {values['delta_in'] / values['delta_limit_in']:.3f})",
]
)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Calculate the steel beam design from a YAML input file.")
parser.add_argument("--input", "-i", type=Path, default=HERE / "input.yaml", help="YAML input path")
parser.add_argument("--output", "-o", type=Path, help="JSON output path; defaults beside the input")
parser.add_argument("--stdout", action="store_true", help="Write a human-readable design summary to stdout")
args = parser.parse_args(argv)
input_path = args.input
output_path = args.output or input_path.with_name("results.json")
with input_path.open(encoding="utf-8") as handle:
result = compute(yaml.safe_load(handle))
serialized = json.dumps(result, indent=2) + "\n"
if args.stdout:
sys.stdout.write(summary(result) + "\n")
else:
output_path.write_text(serialized, encoding="utf-8")
print(output_path)
return 0
if __name__ == "__main__":
raise SystemExit(main())

25
steel-beam/input.yaml Normal file
View file

@ -0,0 +1,25 @@
# Project name shown in the Typst report header.
project: "Casablanca Hotel - 16 Steel Joists Replacement"
# Person or organization shown in the Typst report footer.
prepared_by: "Conemco Engineering"
# Beam span used for the service deflection limit.
beam_length: "9 ft"
# Unbraced length of the compression flange used for lateral-torsional buckling.
unbraced_length: "9 ft"
# Factored major-axis bending demand taken from load-determination.typ.
Mu: "8.124 kip * ft"
# Factored reaction on the connector, used here as the factored shear demand.
Vu: "3.611 kip"
# AISC Shapes Database v15.0 label. Section properties are read from the XLSX.
section: "W10X15"
# Steel yield stress used for flexure and shear (AISC A992).
steel_yield: "50 ksi"
# Steel elastic modulus used for LTB and deflection.
steel_modulus: "29000 ksi"
# LTB moment-gradient factor. Use the applicable AISC Cb value.
cb: 1
# AISC coefficient c for the selected I-shape LTB equation.
c: 1
# Service uniform load for the deflection check (lbf/ft).
service_load: "548.98 lbf/ft"

69
steel-beam/results.json Normal file
View file

@ -0,0 +1,69 @@
{
"tool": "steel_beam",
"version": "0.1",
"project": "Casablanca Hotel - 16 Steel Joists Replacement",
"prepared_by": "Conemco Engineering",
"section": "W10X15",
"values": {
"beam_length_ft": 9.0,
"unbraced_length_in": 108.0,
"factored_uniform_load_kipft": 0.802444,
"service_load_lbf_ft": 548.98,
"moment_kipft": 8.124,
"shear_kip": 3.611,
"E_ksi": 29000.0,
"Fy_ksi": 50.0,
"Lp_in": 34.332994,
"Lr_ft": 8.608917,
"Lb_ft": 9.0,
"rts_in": 1.01,
"Fcr_ksi": 32.555772,
"Mp_kipft": 66.666667,
"MnLTB_kipft": 37.439137,
"Mn_kipft": 37.439137,
"phiMn_kipft": 33.695224,
"Aw_in2": 2.5,
"lambda": 38.5,
"lambda_lim": 53.946344,
"kv": 5.34,
"Cv1": 1.0,
"phi_v": 1.0,
"phiVn_kip": 75.0,
"delta_limit_in": 0.45,
"delta_in": 0.040559,
"ltb_mode": "elastic LTB",
"section_A": 4.41,
"section_d": 10.0,
"section_b": 4.0,
"section_tf": 0.25,
"section_tw": 0.25,
"section_Ix": 68.9,
"section_Zx": 16.0,
"section_Sx": 13.8,
"section_Iy": 2.89,
"section_Zy": 2.3,
"section_Sy": 1.45,
"section_ry": 0.81,
"section_J": 0.104,
"section_rts": 1.01,
"section_ho": 9.72,
"section_lambda": 38.5
},
"checks": {
"flexure": {
"demand": 8.124,
"capacity": 33.695224,
"ok": true
},
"shear": {
"demand": 3.611,
"capacity": 75.0,
"ok": true
},
"deflection": {
"demand": 0.040559,
"capacity": 0.45,
"ok": true
}
}
}

BIN
steel-beam/steel-beam-ref.pdf Executable file

Binary file not shown.

1751
steel-beam/steel-beam.pdf Normal file

File diff suppressed because it is too large Load diff

84
steel-beam/steel-beam.typ Normal file
View file

@ -0,0 +1,84 @@
#import "assets/sheet.typ": calcline, calcsheet, check
#let data = json("results.json")
#let n = data.values
#let checks = data.checks
#let round(value, digits: 2) = calc.round(value, digits: digits)
#show: calcsheet.with(
title: "Steel Beam Design",
project: data.project,
prepared-by: data.prepared_by,
)
= Steel Beam Design
Steel beam design for the Casablanca Hotel steel-joist replacement. Demands determined assuming
the new beam takes all load, non-composite action with concrete slab.
== Factored Demands
As determined in "Load Determination section"
#let Mu_lbf = n.moment_kipft * 1000
#let Vu_lbf = n.shear_kip * 1000
#let L = n.beam_length_ft
#let wu_kipft = n.factored_uniform_load_kipft
#let wu_lbf = wu_kipft * 1000
#calcline([$M_u = #round(n.moment_kipft, digits: 2) "kip·ft"$], [Factored moment from load determination])
#calcline([$V_u = #round(n.shear_kip, digits: 2) "kip"$], [Factored reaction on connector (factored shear)])
#calcline([$L = #L "ft"$], [Beam span])
#metadata((Mu_kipft: n.moment_kipft, Vu_kip: n.shear_kip)) <load-demands>
== Material And Section Properties
#calcline([$E = #n.E_ksi "ksi"$], [Steel Young's modulus])
#calcline([$F_y = #n.Fy_ksi "ksi"$], [Steel yield strength])
#calcline([$"Section" = #data.section$], [AISC W-shape])
#calcline([$d = #n.section_d "in"$, $b = #n.section_b "in"$], [Depth and flange width])
#calcline([$t_f = #n.section_tf "in"$, $t_w = #n.section_tw "in"$], [Flange and web thickness])
#calcline([$A = #n.section_A "in"^2$], [Section area])
#calcline([$r_y = #n.section_ry "in"$], [Weak-axis radius of gyration])
#calcline([$S_x = #n.section_Sx "in"^3$, $Z_x = #n.section_Zx "in"^3$], [Elastic and plastic major-axis modulus])
#calcline([$S_y = #n.section_Sy "in"^3$, $Z_y = #n.section_Zy "in"^3$], [Elastic and plastic minor-axis modulus])
#calcline([$h_o = #n.section_ho "in"$, $J = #n.section_J "in"^4$], [Flange centroid distance and torsional constant])
#calcline([$I_x = #n.section_Ix "in"^4$, $I_y = #n.section_Iy "in"^4$], [Major and minor-axis inertia])
#calcline([$lambda = #n.lambda$], [Web slenderness ratio])
== Bending About Major Axis
#calcline([$L_b = #round(n.Lb_ft, digits: 2) "ft"$], [Unbraced length of compression flange])
#calcline([$L_p = 1.76 r_y sqrt(E / F_y) = #round(n.Lp_in / 12, digits: 2) "ft"$], [Limit for yielding])
#calcline([$C_b = 1$, $c = 1$], [Moment gradient and I-shape coefficient])
#calcline([$r_"ts" = sqrt(I_y h_o / (2 S_x)) = #round(n.section_rts, digits: 2) "in"$], [Effective radius of gyration])
#calcline([$L_r = 1.95 r_"ts" E / (0.7 F_y) sqrt((J c)/(S_x h_o) + sqrt(((J c)/(S_x h_o))^2 + 6.76 (0.7 F_y / E)^2)) = #round(n.Lr_ft, digits: 2) "ft"$], [Limit for inelastic torsional buckling])
#calcline([$F_"cr" = (C_b pi^2 E)/(L_b/r_"ts")^2 sqrt(1 + 0.078 (J c)/(S_x h_o) (L_b/r_"ts")^2) = #round(n.Fcr_ksi, digits: 2) "ksi"$], [Elastic lateral-torsional-buckling stress])
#calcline([$M_p = F_y Z_x = #round(n.Mp_kipft, digits: 2) "kip·ft"$], [Plastic moment])
#calcline([$M_n("LTB") = M_p, "for" L_b <= L_p$], [LTB moment for yielding range])
#calcline([$M_n("LTB") = C_b [M_p - (M_p - 0.7 F_y S_x)(L_b - L_p)/(L_r - L_p)], "for" L_p < L_b <= L_r$], [LTB moment for inelastic range])
#calcline([$M_n("LTB") = F_"cr" S_x, "for" L_b > L_r$], [LTB moment for elastic range])
#calcline([$M_n("LTB") = #round(n.MnLTB_kipft, digits: 2) "kip·ft"$], [Lateral-torsional-buckling strength])
#calcline([$M_n = min(M_p, M_n("LTB")) = #round(n.Mn_kipft, digits: 2) "kip·ft"$], [Nominal bending capacity])
#calcline([$phi M_n = 0.9 M_n = #round(n.phiMn_kipft, digits: 2) "kip·ft"$], [Design bending capacity])
#check("Flexure", checks.flexure.demand, checks.flexure.capacity, unit: "kip·ft", ok: checks.flexure.ok, demand-label: [$M_u$], capacity-label: [$phi M_n$])
== Shear Of Web
#calcline([$A_w = d t_w = #round(n.Aw_in2, digits: 3) "in"^2$], [Web area])
#calcline([$lambda_lim = 2.24 sqrt(E / F_y) = #round(n.lambda_lim, digits: 3)$], [Limiting web slenderness])
#calcline([$k_v = #n.kv$], [Web shear buckling coefficient])
#calcline([$C_"v1" = #n.Cv1$], [Web shear strength coefficient])
#calcline([$phi_v = #n.phi_v$], [Shear reduction factor])
#calcline([$phi V_n = phi_v 0.6 F_y A_w C_"v1" = #round(n.phiVn_kip, digits: 3) "kip"$], [Design shear capacity])
#check("Shear", checks.shear.demand, checks.shear.capacity, unit: "kip", ok: checks.shear.ok, demand-label: [$V_u$], capacity-label: [$phi V_n$])
== Deflection
#calcline([$delta_max = L / 240 = #round(n.delta_limit_in, digits: 3) "in"$], [Maximum allowed deflection])
#calcline([$delta = 5/384 (w L^4) / (E I_x) = #round(n.delta_in, digits: 3) "in"$], [Expected center deflection under service uniform load])
#check("Deflection", checks.deflection.demand, checks.deflection.capacity, unit: "in", ok: checks.deflection.ok, demand-label: [$delta$], capacity-label: [$delta_"max"$])

View file

@ -0,0 +1,92 @@
from pathlib import Path
import importlib.util
import json
import subprocess
import sys
import pytest
import yaml
HERE = Path(__file__).resolve().parent
spec = importlib.util.spec_from_file_location("steel_beam_calc", HERE / "calc.py")
assert spec is not None and spec.loader is not None
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
def result():
with (HERE / "input.yaml").open(encoding="utf-8") as handle:
return module.compute(yaml.safe_load(handle))
def test_typst_load_demands_match_checked_inputs():
subprocess.run([sys.executable, str(HERE / "calc.py")], check=True, cwd=HERE.parents[1])
query = subprocess.run(
[
"typst", "eval", "query(<load-demands>)", "--root", ".",
"--in", "calcs/steel-beam/steel-beam.typ", "--format", "json",
],
check=True,
capture_output=True,
text=True,
cwd=HERE.parents[1],
)
published = json.loads(query.stdout)
assert len(published) == 1
derived = published[0]["value"]
values = result()["values"]
assert derived["Mu_kipft"] == pytest.approx(values["moment_kipft"], abs=0.001)
assert derived["Vu_kip"] == pytest.approx(values["shear_kip"], abs=0.001)
def test_ground_truth_section_properties():
values = result()["values"]
assert values["section_d"] == pytest.approx(5.875)
assert values["section_A"] == pytest.approx(2.52)
assert values["section_Sx"] == pytest.approx(5.1)
assert values["section_Zx"] == pytest.approx(5.73)
assert values["section_rts"] == pytest.approx(1.05)
def test_ground_truth_demands_and_flexure():
output = result()
values = output["values"]
assert values["point_load_lbf"] == pytest.approx(7500)
assert values["moment_kipft"] == pytest.approx(9.375)
assert values["shear_kip"] == pytest.approx(3.75)
assert values["Lp_in"] == pytest.approx(37.7, abs=0.1)
assert values["Lr_ft"] == pytest.approx(9.48, abs=0.01)
assert values["Fcr_ksi"] == pytest.approx(99.57, abs=0.25)
assert values["Mp_kipft"] == pytest.approx(23.875)
assert values["MnLTB_kipft"] == pytest.approx(21.235, abs=0.01)
assert values["phiMn_kipft"] == pytest.approx(19.1, abs=0.1)
assert output["checks"]["flexure"]["ok"] is True
def test_ground_truth_shear_and_deflection():
output = result()
values = output["values"]
assert values["Aw_in2"] == pytest.approx(1.102, abs=0.001)
assert values["Cv1"] == pytest.approx(1)
assert values["phiVn_kip"] == pytest.approx(33.047, abs=0.1)
assert values["delta_limit_in"] == pytest.approx(0.25)
assert values["delta_in"] == pytest.approx(0.078, abs=0.001)
assert all(output["checks"][name]["ok"] for name in ("shear", "deflection"))
def test_invalid_section_is_rejected():
with pytest.raises(ValueError, match="not found"):
module.compute({**yaml.safe_load((HERE / "input.yaml").read_text()), "section": "W0X0"})
def test_cli_can_write_json_to_stdout():
completed = subprocess.run(
[sys.executable, str(HERE / "calc.py"), "--input", str(HERE / "input.yaml"), "--stdout"],
check=True,
capture_output=True,
text=True,
)
output = json.loads(completed.stdout)
assert output["section"] == "W6X8.5"
assert output["values"]["moment_kipft"] == pytest.approx(9.375)
assert completed.stderr == ""

207
wood-joist/PROJECT_STATE.md Normal file
View file

@ -0,0 +1,207 @@
# Project State: Wood Joist Analysis
Last updated: 2026-08-20
## Overview
New hybrid (Typst + Python) calculation at `calcs/wood-joist/` that analyzes an
existing wood joist under uniform gravity loads per **NDS 2018 Allowable Stress
Design (ASD)**. Four checks are covered:
1. Flexure (bending) — NDS 3.3 (beam stability factor `C_L`)
2. Shear — NDS 3.4
3. Bearing (compression perpendicular to grain) — NDS 3.10
4. Serviceability (deflection) — NDS 3.5, limits L/240 (total) and L/360 (live)
The default `input.yaml` reproduces a reference worked example ("Analysis for
existing wood joists under shoring loads", Conemco Engineering, project
"Pompano Beach") exactly. The pytest suite locks those numbers.
## Architecture decisions
- **Hybrid pattern** (same as `steel-beam`): `input.yaml` (Pint unit-bearing
quantities) → `calc.py` (computes, writes `results.json`) → `beam.typ`
(presents only, no recomputation) → compiled PDF.
- **`results.json` shape** (unchanged contract): `{tool, version, project,
prepared_by, values, checks}`. `tool = "wood_joist"`, `version = "0.1"`.
- **Pint units**: quantities are quoted strings in YAML (e.g. `"25 psf"`,
`"9 ft"`). `calc.py` converts with a `quantity()` helper identical in spirit
to `steel-beam/calc.py`. Dimensionless adjustment factors are plain floats.
- **`calc.py` CLI** mirrors `steel-beam`: `--input`, `--output`, `--stdout`
flags; runnable as `python calcs/wood-joist/calc.py` with no args.
- **NDS 2018** is the governing standard and edition. All clause references are
to NDS 2018.
- **`beam.typ` imports** from `../../lib/sheet.typ` and reads `results.json`
(no recomputation). Compiled with `--root .` from the worksheets root so the
shared logo resolves.
## 2026-08-20 change: load determination moved to Typst (user-approved)
This change moves wood-joist gravity-load determination from Python to Typst,
mirroring the `steel-beam` pattern. No engineering equations changed — only
where load determination lives. The Pompano Beach benchmark values are
unchanged.
- **`beam.typ` determines loads inline.** It binds `DL = 25 psf`, `LL = 50 psf`,
span `L = 9 ft`, spacing `B = 13 ft` as Typst `#let` values, then derives
`w = (DL + LL)·B`, `wL = LL·B`, `M = w·L²/8`, `V = w·L/2`, `R = V`. These are
emitted as a Typst metadata label `<wood-joist-loads>` with fields
`w_plf`, `wL_plf`, `M_ftlbf`, `V_lbf`, `R_lbf`. `beam.typ` presents both the
Typst load-derived values and the Python-checked values (like steel-beam's
`M_u,load` vs `M_u,design`), and the test suite reconciles them via the
metadata query.
- **New `input.yaml` contract.** `DL`, `LL`, and `spacing` are removed. The
checked demands are supplied as Pint-quantity strings: `w: "975 plf"`,
`wL: "650 plf"`, `M: "9871.875 ft * lbf"`, `V: "4387.5 lbf"`,
`R: "4387.5 lbf"`. `span` is kept (Python needs it for the L/240 and L/360
deflection limits). All other keys are unchanged (`width`, `depth`,
`bearing_length`, `bearing_end_distance`, `unbraced_length`, `species_grade`,
NDS reference values, adjustment factors, `project`, `prepared_by`).
- **`calc.py` reads demands.** It no longer performs load-path arithmetic.
`w_plf`, `wL_plf`, `M_ftlbf`, `V_lbf`, `R_lbf` come from `quantity()` on the
YAML demand keys. Section properties, all NDS 2018 ASD checks, and the
`{tool, version, project, prepared_by, values, checks}` contract are
unchanged (`tool = "wood_joist"`). `values` no longer includes `DL_psf`,
`LL_psf`, or `spacing_ft`.
- **`check_service` added to `lib/sheet.typ`** as a sibling of `check`.
Signature `check_service(label, acting, allowed, unit: "", ok: auto)`.
Identical layout (label, OK/NOT OK badge, colored box, ratio) but the left
column reads **Acting** / **Allowed** (instead of Demand / Capacity) and the
ratio is labeled **Utilization** (instead of D/C). Used only by the two
deflection checks in `calcs/wood-joist/beam.typ`; flexure, shear, and bearing
keep `check`.
- **Convention change.** The inherited "`lib/sheet.typ` must not be modified"
convention is superseded by this explicit user request. The change is
**additive only**: `check` is unchanged and no other sheet
(`steel-beam`, `concrete-beam`, `concrete-beam2`, `shore-post`) is modified.
Pinned benchmark (unchanged): `w` 975 plf, `wL` 650 plf, `M` 9871.88 ft·lbf
(exact 9871.875), `V` 4387.5 lbf, `R` 4387.5 lbf; flexure util 0.938, shear
util 0.66, bearing util 0.772, Δ_total 0.339 in, Δ_live 0.226 in.
## Engineering decisions (pinned for the builder)
The equations are fully pinned by the reference worked example (every
intermediate value and formula is supplied). **No separate engineering
specifier pass was required**; the equations reproduce NDS 2018 directly and
the clause references are recorded here and in `tasks/001`. The reviewer task
(`tasks/005`) still verifies the engineering specification.
### Section properties (rectangular joist)
- `A = b·d`
- `I_x = b·d³ / 12`
- `S_x = b·d² / 6` (= `2·I_x / d`)
### Check 1 — Flexure (NDS 3.3)
- Slenderness: `R_B = sqrt(l_e · d / b²)` (NDS 3.3.3.7). Require `R_B < 50`.
If `R_B >= 50`, `calc.py` raises `ValueError` (member needs lateral bracing;
the `C_L` equation is out of scope).
- `F*_b = F_b · C_D · C_M · C_t · C_F · C_i · C_r` (all factors except `C_L`, `C_fu`).
- `F_bE = 1.20 · E'_min / R_B²`
- `C_L = (1 + F_bE/F*_b)/1.9 − sqrt(((1 + F_bE/F*_b)/1.9)² − (F_bE/F*_b)/0.95)`
(NDS 3.3.3, `c_b = 0.95` for sawn lumber). Formula yields `C_L ≤ 1.0`.
- `F'_b = F*_b · C_L · C_fu`
- `f_b = M / S_x` (M in lbf·in)
- Allowable moment `M_a = S_x · F'_b` (reported in ft·lbf).
### Check 2 — Shear (NDS 3.4)
- `F'_v = F_v · C_D · C_M · C_t · C_vr`
- `f_v = 3·V / (2·A)` (rectangular section, NDS 3.4.1 Eq. 3.4-1)
### Check 3 — Bearing (NDS 3.10, compression perpendicular to grain)
- Bearing area factor `C_b = (l_b + 0.375) / l_b` (NDS 3.10.4; bearing < 6 in
and ≥ 3 in from member end).
- `F'_c⊥ = F_c⊥ · C_M · C_t · C_i · C_b`
- Bearing area `A_b = l_b · b`
- `f_c⊥ = R / A_b` (`R = w·L/2`)
### Check 4 — Serviceability (NDS 3.5)
- `Δ_total = 5·w·L⁴ / (384·E·I_x)`
- `Δ_live = 5·w_L·L⁴ / (384·E·I_x)`
- Limits `L/240` (total) and `L/360` (live). **Hardcoded constants** in
`calc.py` (`240`, `360`) — not YAML inputs — matching the reference.
## Reference example (ground truth to lock)
Project "Pompano Beach", prepared_by "Conemco Engineering".
| Quantity | Value |
|---|---|
| DL, LL | 25 psf, 50 psf |
| span L, spacing B | 9 ft, 13 ft |
| w, w_L | 975 plf, 650 plf |
| b × d | 3.5 in × 9.5 in |
| A, I_x, S_x | 33.25 in², 250.1 in⁴, 52.6 in³ |
| F_b, F_v, F_c⊥, E, E'_min | 2400, 300, 565, 1,700,000, 510,000 psi |
| All adjustment factors | 1.0 |
| M, V, R | 9871.88 ft·lbf, 4387.5 lbf, 4387.5 lbf |
| Flexure util / shear util / bearing util | 0.938 / 0.66 / 0.772 |
| Δ_total, Δ_live | 0.339 in, 0.226 in |
Corrected vs. the source PDF: the shear section label "acting bending stress"
becomes "acting shear stress", and the blank page 3 is omitted. Corrections are
noted in the sheet's Scope section.
## Conventions (inherited)
- `lib/sheet.typ` is shared. It must not be modified except where an explicit
user request authorizes an **additive-only** change (see the 2026-08-20
change: `check_service` added; `check` unchanged).
- No existing calculation (`steel-beam`, `concrete-beam`, `concrete-beam2`,
`shore-post`) may be modified.
- Compile from `worksheets/` with `--root .`.
- Lock the reference example in pytest with `pytest.approx` before treating the
tool as stable.
## Milestones
- 2026-08-19 — Task 001 DONE: `calc.py` + `input.yaml` + `results.json` created.
All five checks pass for the default "Pompano Beach" input; values match the
reference example (flexure 0.938, shear 0.66, bearing 0.772, Δ_total 0.339 in,
Δ_live 0.226 in). See `TASKS.md`.
- 2026-08-19 — Task 002 DONE: `test_wood_joist.py` created with 10 numerical
lock tests; all pass (`10 passed`).
- 2026-08-19 — Task 003 DONE: `beam.typ` created, compiled to
`generated/wood-joist.pdf` (206 KB), and the Typst metadata test appended;
all 11 tests pass (`11 passed`).
- 2026-08-19 — Task 004 DONE: `README.md` and `codemap.md` refreshed with the
wood-joist entry; all 11 tests still pass.
- 2026-08-19 — Task 005 DONE: Reviewer PASS after one fix cycle. Issues found
and fixed: (1) C_L ≤ 1.0 now explicitly enforced with regression test;
(2) bearing applicability limits enforced (l_b < 6 in, end distance ≥ 3 in)
with new `bearing_end_distance` input and tests. Final state: 14 tests pass,
PDF compiles, results.json idempotent. Calculation approved.
- 2026-08-20 — Tasks 006–008 DONE: load determination moved to Typst (mirroring
steel-beam), `check_service` added to `lib/sheet.typ` (Acting/Allowed/
Utilization) and used for the two deflection checks, `input.yaml` switched to
checked demands (`w`, `wL`, `M`, `V`, `R`), tests updated with the
`<wood-joist-loads>` reconciliation test, and README/codemap refreshed.
Reviewer PASS (all 8 checklist items, deterministic evidence verified);
simplify pass clean. Final state: 15 tests pass, PDF compiles, results.json
idempotent, benchmark values unchanged (flexure 0.938, shear 0.66, bearing
0.772, Δ_total 0.339 in, Δ_live 0.226 in).
## Final deliverables
- `calcs/wood-joist/calc.py` — NDS 2018 ASD wood joist analysis (flexure with
C_L, shear, bearing, deflection). CLI: `--input`, `--output`, `--stdout`.
- `calcs/wood-joist/input.yaml` — Pint-quantity inputs; defaults reproduce the
"Pompano Beach" reference example.
- `calcs/wood-joist/test_wood_joist.py` — 14 tests locking the reference values
plus validation guards and the Typst metadata query test.
- `calcs/wood-joist/beam.typ` — presentation sheet (no recomputation), compiled
to `calcs/wood-joist/generated/wood-joist.pdf`.
- `README.md`, `codemap.md` — documented and indexed.
## Known limitations
- Single-span, uniformly loaded, rectangular-section joist only.
- No repetitive-member live-load reduction beyond the explicit `C_r` factor.
- No lateral-torsional restraint beyond the single unbraced length `l_e`.
- Deflection limits hardcoded to L/240 (total) and L/360 (live).
## Dependencies
- Python: `pyyaml`, `pytest`, `pint` (already in `requirements.txt`).
- `typst` CLI for compile and the metadata-query test.
- No new third-party Python packages beyond `requirements.txt`.

160
wood-joist/README.md Normal file
View file

@ -0,0 +1,160 @@
# Worksheets
Typst-first calculation sheets. Use Python only when the arithmetic is no longer comfortable in Typst.
```text
lib/sheet.typ Shared letterhead, calc-line, check, check_service
calcs/shore-post/ Typst-only completed calculation
calcs/concrete-beam/ YAML numbers → Python → JSON → Typst
calcs/concrete-beam2/ YAML quantities → Pint → JSON → Typst
calcs/steel-beam/ YAML quantities → Pint + AISC XLSX → JSON → Typst
calcs/wood-joist/ YAML quantities → Pint → JSON → Typst (NDS 2018 ASD)
calcs/concentric-footing/ YAML quantities → Pint → JSON → Typst (ACI 318-19)
```
Compile every sheet from this folder so the shared logo resolves.
## Typst-only
Edit numbers in `calcs/shore-post/shore-post.typ`.
```bash
typst compile --root . calcs/shore-post/shore-post.typ calcs/shore-post/generated/shore-post.pdf
typst watch --root . calcs/shore-post/shore-post.typ calcs/shore-post/generated/shore-post.pdf
```
## Hybrid
Edit `calcs/concrete-beam/input.yaml`, then:
```bash
python -m pip install -r requirements.txt
python calcs/concrete-beam/calc.py
typst compile --root . calcs/concrete-beam/beam.typ calcs/concrete-beam/generated/beam.pdf
```
Optional output path: `python calcs/concrete-beam/calc.py path/to/input.yaml path/to/results.json`
```bash
python -m pytest calcs/concrete-beam/test_concrete_beam.py
```
`calc.py` writes named numbers. `beam.typ` does not recompute the design.
## Hybrid with units (Pint)
Same calculation pattern with unit-bearing YAML values. Write `span: "16 ft"`
or `span: "192 in"`. Quote every quantity.
```bash
python calcs/concrete-beam2/calc.py
typst compile --root . calcs/concrete-beam2/beam.typ calcs/concrete-beam2/generated/beam.pdf
python -m pytest calcs/concrete-beam2/test_concrete_beam2.py
```
## Templates
Copy one of these folders into `calcs/` and rename it. Compile from the
`worksheets/` directory so the shared logo resolves.
Typst-only:
```bash
typst compile --root . template/typst-only/main.typ template/typst-only/generated/calculation.pdf
```
Typst + Python:
```bash
python template/typst-python/calc.py
typst compile --root . template/typst-python/main.typ template/typst-python/generated/calculation.pdf
python -m pytest template/typst-python/test_template.py
```
## Steel beam
The steel beam sheet reads section properties directly from
`aisc-shapes-database-v15.0.xlsx`. Edit `calcs/steel-beam/input.yaml`, then:
```bash
python calcs/steel-beam/calc.py
typst compile --root . calcs/steel-beam/beam.typ calcs/steel-beam/generated/beam.pdf
python -m pytest calcs/steel-beam/test_steel_beam.py
```
For a standalone JSON result on stdout, use:
```bash
python calcs/steel-beam/calc.py --input calcs/steel-beam/input.yaml --stdout
```
Use `--output path/to/results.json` to select a JSON output path. The reusable
Python function is `compute(input_dict)` in `calcs/steel-beam/calc.py`.
`input.yaml` supplies the checked `Mu` and `Vu` demands. `beam.typ` determines
and displays the gravity loads that produce those demands, and the test suite
queries Typst metadata to verify the values match. The calculation covers
major-axis AISC lateral torsional buckling, web shear, and point-load
deflection. The test fixture locks the supplied `steel-beam.pdf` example for
W6X8.5.
## Wood joist
The wood joist sheet reads reference design values and adjustment factors from
`calcs/wood-joist/input.yaml`, then computes capacity checks per NDS 2018 ASD.
```bash
python calcs/wood-joist/calc.py
typst compile --root . calcs/wood-joist/beam.typ calcs/wood-joist/generated/wood-joist.pdf
python -m pytest calcs/wood-joist/test_wood_joist.py
```
For a standalone JSON result on stdout, use:
```bash
python calcs/wood-joist/calc.py --input calcs/wood-joist/input.yaml --stdout
```
Use `--output path/to/results.json` to select a JSON output path. The reusable
Python function is `compute(input_dict)` in `calcs/wood-joist/calc.py`.
`input.yaml` supplies the checked demands (`w`, `wL`, `M`, `V`, `R` as
Pint-quantity strings), `span`, section dimensions, bearing geometry, NDS
reference design values, and adjustment factors — and no longer supplies `DL`,
`LL`, or `spacing`. `beam.typ` determines the gravity loads inline (`DL = 25
psf`, `LL = 50 psf`, span 9 ft, spacing 13 ft), derives `w`, `wL`, `M`, `V`,
`R`, and presents them beside the Python-checked demands; the test suite
reconciles the two via the `<wood-joist-loads>` metadata query. `calc.py` reads
the demands and computes section properties, flexure (with `C_L`), shear,
bearing, and L/240 + L/360 deflection. The two deflection checks use the shared
`check_service` helper (Acting/Allowed/Utilization); flexure, shear, and
bearing use `check`.
## Concentric footing
Square concentric spread footing under axial load per ACI 318-19 — soil bearing, one-way/two-way shear, flexure, minimum steel, concrete bearing.
```bash
python calcs/concentric-footing/calc.py
typst compile --root . calcs/concentric-footing/footing.typ calcs/concentric-footing/generated/footing.pdf
python -m pytest calcs/concentric-footing/test_concentric_footing.py
```
For a standalone JSON result on stdout, use:
```bash
python calcs/concentric-footing/calc.py --input calcs/concentric-footing/input.yaml --stdout
```
Use `--output path/to/results.json` to select a JSON output path. The reusable
Python function is `compute(input_dict)` in `calcs/concentric-footing/calc.py`.
`input.yaml` supplies checked `Ps`/`Pu` (Pint quantities) and footing geometry/materials; `footing.typ` derives `Ps`/`Pu` inline from `DLr=10psf, LLr=20psf, Br=18.9ft, Lr=27.5ft, column 14in×14ft @145pcf` and reconciles via `<concentric-footing-loads>` query; bearing plate width `bp=6in` governs `A1`.
## New calculation
1. Copy the nearer example.
2. Stay in Typst if it is arithmetic you want to see.
3. If you need branching or iteration, write a small `calc.py` that reads YAML and writes `results.json` (`values` and `checks`).
4. Lock one hand example in a pytest before treating the tool as stable.
5. Extract a shared Python module only the second time you need the same procedure.

29
wood-joist/TASKS.md Normal file
View file

@ -0,0 +1,29 @@
# Tasks: Wood Joist Analysis
Ordered, dependency-ordered plan. Each task has a spec in `tasks/NNN_name.md`.
| # | Task | Files | Status | Depends on |
|---|---|---|---|---|
| 001 | Numerical core: `calc.py` + `input.yaml` + `results.json` | calcs/wood-joist/calc.py, calcs/wood-joist/input.yaml, calcs/wood-joist/results.json | DONE | — |
| 002 | Numerical lock: `test_wood_joist.py` (compute() only) | calcs/wood-joist/test_wood_joist.py | DONE | 001 |
| 003 | Presentation: `beam.typ` + compile + Typst metadata test | calcs/wood-joist/beam.typ, calcs/wood-joist/generated/wood-joist.pdf, calcs/wood-joist/test_wood_joist.py (append) | DONE | 001, 002 |
| 004 | Documentation refresh: `README.md` + `codemap.md` | README.md, codemap.md | DONE | 003 |
| 005 | Reviewer pass on the whole calculation | review notes only | DONE | 004 |
| 006 | `check_service` + move load determination to Typst | lib/sheet.typ, calcs/wood-joist/input.yaml, calcs/wood-joist/calc.py, calcs/wood-joist/beam.typ, calcs/wood-joist/results.json | DONE | 001–005 |
| 007 | Test updates + Typst load-demand reconciliation | calcs/wood-joist/test_wood_joist.py | DONE | 006 |
| 008 | Docs refresh (`README.md` + `codemap.md`) + reviewer pass | README.md, codemap.md | DONE | 006, 007 |
## Notes
- Task 001 is the numerical single source of truth; it pins every `results.json`
value name and the exact equations. Tasks 002–005 depend on that contract.
- The Typst metadata test (steel-beam query pattern) lives with Task 003 because
it needs `beam.typ` to exist; Task 002 is purely numerical to keep the
dependency graph acyclic.
- `generated/` may not exist yet; Task 003 creates it before compiling.
- Tasks 006–008 implement the user-approved "move load determination to Typst"
change. Task 006 changes the shared `lib/sheet.typ` (additive `check_service`
only) and the wood-joist contract; Task 007 adapts the tests and adds the
`<wood-joist-loads>` reconciliation test; Task 008 refreshes docs and runs the
reviewer pass verifying deterministic benchmark evidence. The Pompano Beach
benchmark values must stay identical.

Binary file not shown.

BIN
wood-joist/assets/logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View file

@ -0,0 +1,82 @@
#let navy = rgb("#1a3a5f")
#let muted = rgb("#626b73")
#let pass = rgb("#1f6b45")
#let fail = rgb("#9b2c2c")
#let calcsheet(
title: "Structural Calculation",
project: "",
prepared-by: "",
body,
) = {
set document(title: title, author: prepared-by)
set page(
paper: "us-letter",
margin: (x: 1in, top: 1.25in, bottom: 1in),
header: context {
grid(
columns: (1fr, 1fr),
align: (left, right),
image("../assets/logo.png", height: 30pt),
[#text(size: 9pt)[Project:] \
#text(size: 10pt, weight: "bold")[#project]],
)
},
footer: context {
set text(size: 8.5pt, fill: muted)
stack(
spacing: 4pt,
line(length: 100%, stroke: 0.5pt + muted),
[#prepared-by],
)
},
)
set text(font: "Libertinus Serif", size: 10pt, lang: "en")
set par(justify: true)
set heading(numbering: none)
show heading.where(level: 1): set text(size: 14pt, weight: "bold", fill: black)
show heading.where(level: 2): set text(size: 11pt, weight: "bold", fill: black)
show heading.where(level: 2): set block(above: 2em, below: 1em)
body
}
#let calcline(formula, note) = grid(
columns: (1.7fr, 1fr),
gutter: 4pt,
align: (left, left),
formula, text(size: 9pt, fill: muted, note),
)
#let check(label, demand, capacity, unit: "", ok: auto, demand-label: "Demand", capacity-label: "Capacity") = {
let utilization = demand / capacity
let passes = if ok == auto { utilization <= 1 } else { ok }
let color = if passes { pass } else { fail }
block(
breakable: false,
width: 100%,
stroke: 0.8pt + black,
inset: 8pt,
radius: 2pt,
)[
#grid(
columns: (1fr, auto),
[#text(weight: "bold")[#label]],
box(stroke: 0.8pt + color, inset: (x: 6pt, y: 2pt))[
#text(weight: "bold", fill: color)[#if passes { "OK" } else { "NOT OK" }]
],
)
#v(4pt)
#grid(
columns: (1fr, auto),
[
#demand-label: #calc.round(demand, digits: 2) #unit #h(14pt)
#capacity-label: #calc.round(capacity, digits: 2) #unit
],
[
D/C: #calc.round(utilization, digits: 2)
],
)
]
}

187
wood-joist/calc.py Normal file
View file

@ -0,0 +1,187 @@
from __future__ import annotations
import json
import math
import sys
import argparse
from pathlib import Path
try:
import yaml
except ImportError:
raise SystemExit("Install dependencies: python -m pip install -r requirements.txt")
try:
from pint import DimensionalityError, UndefinedUnitError, UnitRegistry
except ImportError:
raise SystemExit("Install dependencies: python -m pip install -r requirements.txt")
HERE = Path(__file__).resolve().parent
ureg = UnitRegistry()
ureg.define("kip = 1000 * force_pound")
ureg.define("ksi = kip / inch ** 2")
ureg.define("psf = force_pound / foot ** 2")
ureg.define("plf = force_pound / foot") # pounds per linear foot
if "psi" not in ureg:
ureg.define("psi = force_pound / inch ** 2")
def quantity(value, unit: str, name: str) -> float:
try:
q = ureg.Quantity(value).to(unit)
except (DimensionalityError, UndefinedUnitError, TypeError, ValueError) as exc:
raise ValueError(f"{name}: expected {unit}, got {value!r}") from exc
magnitude = float(q.magnitude)
if magnitude <= 0:
raise ValueError(f"{name} must be positive")
return magnitude
def factor(value, name: str) -> float:
magnitude = float(value)
if magnitude <= 0:
raise ValueError(f"{name} must be positive")
return magnitude
def compute(inp: dict) -> dict:
span_ft = quantity(inp["span"], "ft", "span")
b_in = quantity(inp["width"], "in", "width")
d_in = quantity(inp["depth"], "in", "depth")
lb_in = quantity(inp["bearing_length"], "in", "bearing_length")
bed_in = quantity(inp["bearing_end_distance"], "in", "bearing_end_distance")
le_in = quantity(inp["unbraced_length"], "in", "unbraced_length")
Fb_psi = quantity(inp["Fb"], "psi", "Fb")
Fv_psi = quantity(inp["Fv"], "psi", "Fv")
Fcp_psi = quantity(inp["Fcp"], "psi", "Fcp")
E_psi = quantity(inp["E"], "psi", "E")
Emin_psi = quantity(inp["E_min"], "psi", "E_min")
species_grade = str(inp["species_grade"])
CD = factor(inp["CD"], "CD")
CM = factor(inp["CM"], "CM")
Ct = factor(inp["Ct"], "Ct")
CF = factor(inp["CF"], "CF")
Cr = factor(inp["Cr"], "Cr")
Cfu = factor(inp["Cfu"], "Cfu")
Ci = factor(inp["Ci"], "Ci")
Cvr = factor(inp["Cvr"], "Cvr")
# Checked demands supplied by YAML. beam.typ derives the same values and the
# test suite reconciles them via the <wood-joist-loads> metadata label.
w_plf = quantity(inp["w"], "plf", "w")
wL_plf = quantity(inp["wL"], "plf", "wL")
M_ftlbf = quantity(inp["M"], "ft * lbf", "M")
V_lbf = quantity(inp["V"], "lbf", "V")
R_lbf = quantity(inp["R"], "lbf", "R")
A_in2 = b_in * d_in
Ix_in4 = b_in * d_in ** 3 / 12.0
Sx_in3 = b_in * d_in ** 2 / 6.0
# Flexure (NDS 3.3.3)
RB = math.sqrt(le_in * d_in / b_in ** 2)
if RB >= 50.0:
raise ValueError(f"RB = {RB:.3f} >= 50; member requires additional "
"lateral bracing (NDS 3.3.3)")
Fb_star_psi = Fb_psi * CD * CM * Ct * CF * Ci * Cr
FbE_psi = 1.20 * Emin_psi / RB ** 2
ratio = FbE_psi / Fb_star_psi
CL = (1.0 + ratio) / 1.9 - math.sqrt(((1.0 + ratio) / 1.9) ** 2 - ratio / 0.95)
if not math.isfinite(CL) or CL > 1.0 or CL <= 0:
raise ValueError(f"CL = {CL:.4f} out of range (0, 1]; beam stability "
"factor invalid (NDS 3.3.3)")
Fb_prime_psi = Fb_star_psi * CL * Cfu
fb_psi = M_ftlbf * 12.0 / Sx_in3
Ma_ftlbf = Sx_in3 * Fb_prime_psi / 12.0
# Shear (NDS 3.4)
Fv_prime_psi = Fv_psi * CD * CM * Ct * Cvr
fv_psi = 1.5 * V_lbf / A_in2
# Bearing (NDS 3.10)
if lb_in >= 6.0:
raise ValueError("bearing_length must be < 6 in for the bearing area "
"factor (NDS 3.10.4)")
if bed_in < 3.0:
raise ValueError("bearing_end_distance must be >= 3 in for the bearing "
"area factor (NDS 3.10.4)")
Cb = (lb_in + 0.375) / lb_in
Fcp_prime_psi = Fcp_psi * CM * Ct * Ci * Cb
Ab_in2 = lb_in * b_in
fcp_psi = R_lbf / Ab_in2
# Serviceability (NDS 3.5). Limits hardcoded per reference: L/240, L/360.
L_in = span_ft * 12.0
delta_total_in = 5.0 * (w_plf / 12.0) * L_in ** 4 / (384.0 * E_psi * Ix_in4)
delta_live_in = 5.0 * (wL_plf / 12.0) * L_in ** 4 / (384.0 * E_psi * Ix_in4)
delta_allow_total_in = L_in / 240.0
delta_allow_live_in = L_in / 360.0
def q(value: float) -> float:
return round(value, 6)
values = {
"span_ft": q(span_ft),
"w_plf": q(w_plf), "wL_plf": q(wL_plf),
"b_in": q(b_in), "d_in": q(d_in),
"A_in2": q(A_in2), "Ix_in4": q(Ix_in4), "Sx_in3": q(Sx_in3),
"M_ftlbf": q(M_ftlbf), "V_lbf": q(V_lbf), "R_lbf": q(R_lbf),
"species_grade": species_grade,
"Fb_psi": q(Fb_psi), "Fv_psi": q(Fv_psi), "Fcp_psi": q(Fcp_psi),
"E_psi": q(E_psi), "Emin_psi": q(Emin_psi),
"CD": q(CD), "CM": q(CM), "Ct": q(Ct), "CF": q(CF),
"Cr": q(Cr), "Cfu": q(Cfu), "Ci": q(Ci), "Cvr": q(Cvr),
"le_in": q(le_in), "RB": q(RB),
"Fb_star_psi": q(Fb_star_psi), "FbE_psi": q(FbE_psi),
"CL": q(CL), "Fb_prime_psi": q(Fb_prime_psi),
"fb_psi": q(fb_psi), "Ma_ftlbf": q(Ma_ftlbf),
"Fv_prime_psi": q(Fv_prime_psi), "fv_psi": q(fv_psi),
"lb_in": q(lb_in), "bed_in": q(bed_in), "Cb": q(Cb), "Ab_in2": q(Ab_in2),
"Fcp_prime_psi": q(Fcp_prime_psi), "fcp_psi": q(fcp_psi),
"delta_total_in": q(delta_total_in), "delta_live_in": q(delta_live_in),
"delta_allow_total_in": q(delta_allow_total_in),
"delta_allow_live_in": q(delta_allow_live_in),
}
checks = {
"flexure": {"demand": q(fb_psi), "capacity": q(Fb_prime_psi), "ok": fb_psi <= Fb_prime_psi},
"shear": {"demand": q(fv_psi), "capacity": q(Fv_prime_psi), "ok": fv_psi <= Fv_prime_psi},
"bearing": {"demand": q(fcp_psi), "capacity": q(Fcp_prime_psi), "ok": fcp_psi <= Fcp_prime_psi},
"deflection_total": {"demand": q(delta_total_in), "capacity": q(delta_allow_total_in), "ok": delta_total_in <= delta_allow_total_in},
"deflection_live": {"demand": q(delta_live_in), "capacity": q(delta_allow_live_in), "ok": delta_live_in <= delta_allow_live_in},
}
return {
"tool": "wood_joist",
"version": "0.1",
"project": inp.get("project", ""),
"prepared_by": inp.get("prepared_by", ""),
"values": values,
"checks": checks,
}
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Calculate the wood joist design from a YAML input file.")
parser.add_argument("--input", "-i", type=Path, default=HERE / "input.yaml", help="YAML input path")
parser.add_argument("--output", "-o", type=Path, help="JSON output path; defaults beside the input")
parser.add_argument("--stdout", action="store_true", help="Write the complete JSON result to stdout instead of a file")
args = parser.parse_args(argv)
input_path = args.input
output_path = args.output or input_path.with_name("results.json")
with input_path.open(encoding="utf-8") as handle:
result = compute(yaml.safe_load(handle))
serialized = json.dumps(result, indent=2) + "\n"
if args.stdout:
sys.stdout.write(serialized)
else:
output_path.write_text(serialized, encoding="utf-8")
print(output_path)
return 0
if __name__ == "__main__":
raise SystemExit(main())

76
wood-joist/codemap.md Normal file
View file

@ -0,0 +1,76 @@
# Codemap: worksheets
Typst-first structural calculation sheets. Hybrid calculations parse YAML inputs
through Pint, compute design values in Python, and present them in Typst.
Generated: 2026-08-19
Files indexed: 24
## Layout
```
worksheets/
├── README.md [doc] — project conventions, template usage, hybrid pattern docs.
├── aisc-shapes-database-v15.0.xlsx [asset] — AISC section-property workbook consumed by steel-beam.
├── requirements.txt [config] — Python deps: pyyaml, pytest, pint.
├── steel-beam.pdf [doc] — reference worked example for the W6X8.5 lock case.
├── WOOD-JOISTS-BENDING-SHEAR-BEARING-DEFLECTION.pdf [doc] — reference sheet for the new wood-joist calculation.
├── assets/
│ └── logo.png [asset] — shared letterhead image resolved from the worksheets root.
├── lib/
│ └── sheet.typ [doc] — shared letterhead, calc-line, check, check_service helpers; no calculation logic.
├── template/
│ ├── typst-only/
│ │ ├── README.md [doc] — pure-Typst template instructions.
│ │ └── main.typ [logic] — pure-Typst sample: arithmetic shown inline, no results.json.
│ └── typst-python/
│ ├── README.md [doc] — hybrid template instructions.
│ ├── calc.py [logic] — minimal YAML-driven compute(); writes results.json with values+checks.
│ ├── test_template.py [test] — locks one hand example with pytest.approx.
│ └── input.yaml [config] — template fixture inputs.
├── calcs/
│ ├── shore-post/ — pure-Typst reference calculation.
│ │ ├── shore-post.typ [logic] — tributary area, axial demand, AS550 shore-post capacity check.
│ │ ├── assets/tributary-areas.png [asset] — figure used by shore-post.typ.
│ │ └── generated/shore-post.pdf [doc] — last compiled artefact (regenerable).
│ ├── concrete-beam/ — hybrid YAML numbers → Python → JSON → Typst.
│ │ ├── calc.py [logic] — span, demand, Whitney block, phiMn, phiVc, min steel.
│ │ ├── test_concrete_beam.py [test] — locks example demands and capacities.
│ │ ├── input.yaml [config] — plain-number inputs.
│ │ ├── beam.typ [logic] — presents calc.py values; embeds beam sketch.
│ │ └── results.json [state] — last calc.py output (regenerable).
│ ├── concrete-beam2/ — hybrid YAML quantities + Pint unit conversion.
│ │ ├── calc.py [logic] — Pint-parses quantities; same procedure as concrete-beam.
│ │ ├── test_concrete_beam2.py [test] — locks Pint-parsed demands and capacities.
│ │ ├── input.yaml [config] — unit-bearing inputs ("16 ft", "3000 psi").
│ │ ├── beam.typ [logic] — presents calc.py values; embeds beam sketch.
│ │ └── results.json [state] — last calc.py output (regenerable).
│ ├── wood-joist/ — hybrid YAML quantities + Pint → JSON → Typst (NDS 2018 ASD).
│ │ ├── calc.py [logic] — section props, flexure (C_L), shear, bearing, deflection; reads YAML demands.
│ │ ├── test_wood_joist.py [test] — locks Pompano Beach example; queries <wood-joist-loads> and <wood-joist-results>.
│ │ ├── input.yaml [config] — Pint-quantity checked demands (w, wL, M, V, R), span, geometry, NDS design values.
│ │ ├── beam.typ [logic] — derives gravity loads (w, wL, M, V, R) and presents Python-checked values.
│ │ ├── results.json [state] — last calc.py output (regenerable).
│ │ └── generated/wood-joist.pdf [doc] — last compiled artefact (regenerable).
│ └── steel-beam/ — hybrid YAML quantities + Pint + AISC XLSX loader.
│ ├── calc.py [logic] — loads section from XLSX; AISC LTB, web shear, point-load deflection.
│ ├── test_steel_beam.py [test] — runs typst query(<load-demands>); locks W6X8.5 ground truth.
│ ├── input.yaml [config] — Pint-quantity inputs (span, Mu, Vu, section label).
│ ├── beam.typ [logic] — load determination shown in Typst; LTB/shear/deflection from Python.
│ └── results.json [state] — last calc.py output (regenerable).
└── tasks/ [doc] — Architect-written task specifications; one per builder task.
```
## Hot Spots
- `lib/sheet.typ` — shared by every sheet. Changing `calculation-sheet`, `calc-line`, or `check` breaks every compiled PDF.
- `aisc-shapes-database-v15.0.xlsx` — steel-beam fixture; column mapping in `calc.py:load_section` is brittle to schema changes.
- `calcs/steel-beam/calc.py` — single-source of truth for the steel-beam capacity numbers; test suite asserts exact values.
- `calcs/wood-joist/calc.py` — single source of truth for the NDS wood-joist capacity numbers; the test suite asserts the locked Pompano Beach values.
- `README.md` — documents the hybrid contract (Python computes, Typst presents). Keep the contract consistent across new sheets.
## Conventions
- Hybrid calculations: `input.yaml` (units via Pint) → `calc.py` (computes) → `results.json` (values + checks) → `beam.typ` (presents only). Wood-joist now derives loads in Typst (like steel-beam) while `calc.py` reads the checked demands. `check_service` is a presentation helper.
- Pure-Typst sheets are reserved for arithmetic the engineer wants to see inline; calculations with branching or iteration move to Python.
- The shared logo resolves only when sheets are compiled with `--root .` from the worksheets directory.

46
wood-joist/input.yaml Normal file
View file

@ -0,0 +1,46 @@
# Project name shown in the Typst report header.
project: "Pompano Beach"
# Person or organization shown in the Typst report footer.
prepared_by: "Conemco Engineering"
# Checked demands (ASD) supplied for verification. beam.typ derives the same
# gravity loads and the test suite reconciles them to these values.
w: "975 plf" # total uniform line load (w = (D + LL) B)
wL: "650 plf" # live uniform line load (wL = LL B)
M: "9871.875 ft * lbf" # maximum moment (M = w L^2 / 8)
V: "4_387.5 lbf" # support shear (V = w L / 2)
R: "4387.5 lbf" # support reaction (R = V)
# Joist geometry: span (needed for the L/240 and L/360 deflection limits).
span: "9 ft"
# Joist cross-section (actual dimensions).
width: "3.5 in" # b
depth: "9.5 in" # d
# Bearing length at each support (wood beam).
bearing_length: "2.5 in" # l_b
# Distance from member end to near edge of bearing; must be >= 3 in for C_b to apply (NDS 3.10.4).
bearing_end_distance: "3 in" # l_end
# Unbraced length of the compression edge used for beam stability.
unbraced_length: "1 in" # l_e
# Species and grade label shown in the report.
species_grade: "SP No. 2"
# NDS 2018 reference design values (Spruce-Pine No. 2).
Fb: "2400 psi" # bending (F_b)
Fv: "300 psi" # shear (F_v)
Fcp: "565 psi" # compression perpendicular to grain (F_c-perp)
E: "1700000 psi" # modulus of elasticity (E)
E_min: "510000 psi" # adjusted modulus for stability (E'_min)
# Adjustment factors (NDS Table 4.3.1). All 1.0 for this example.
CD: 1 # load duration factor
CM: 1 # wet service factor
Ct: 1 # temperature factor
CF: 1 # size factor (bending)
Cr: 1 # repetitive member factor
Cfu: 1 # flat use factor (bending)
Ci: 1 # incising factor
Cvr: 1 # shear reduction factor (NDS 3.4.3)

80
wood-joist/results.json Normal file
View file

@ -0,0 +1,80 @@
{
"tool": "wood_joist",
"version": "0.1",
"project": "Pompano Beach",
"prepared_by": "Conemco Engineering",
"values": {
"span_ft": 9.0,
"w_plf": 975.0,
"wL_plf": 650.0,
"b_in": 3.5,
"d_in": 9.5,
"A_in2": 33.25,
"Ix_in4": 250.067708,
"Sx_in3": 52.645833,
"M_ftlbf": 9871.875,
"V_lbf": 4387.5,
"R_lbf": 4387.5,
"species_grade": "SP No. 2",
"Fb_psi": 2400.0,
"Fv_psi": 300.0,
"Fcp_psi": 565.0,
"E_psi": 1700000.0,
"Emin_psi": 510000.0,
"CD": 1.0,
"CM": 1.0,
"Ct": 1.0,
"CF": 1.0,
"Cr": 1.0,
"Cfu": 1.0,
"Ci": 1.0,
"Cvr": 1.0,
"le_in": 1.0,
"RB": 0.880631,
"Fb_star_psi": 2400.0,
"FbE_psi": 789157.894737,
"CL": 0.999848,
"Fb_prime_psi": 2399.634053,
"fb_psi": 2250.178077,
"Ma_ftlbf": 10527.561199,
"Fv_prime_psi": 300.0,
"fv_psi": 197.932331,
"lb_in": 2.5,
"bed_in": 3.0,
"Cb": 1.15,
"Ab_in2": 8.75,
"Fcp_prime_psi": 649.75,
"fcp_psi": 501.428571,
"delta_total_in": 0.338572,
"delta_live_in": 0.225714,
"delta_allow_total_in": 0.45,
"delta_allow_live_in": 0.3
},
"checks": {
"flexure": {
"demand": 2250.178077,
"capacity": 2399.634053,
"ok": true
},
"shear": {
"demand": 197.932331,
"capacity": 300.0,
"ok": true
},
"bearing": {
"demand": 501.428571,
"capacity": 649.75,
"ok": true
},
"deflection_total": {
"demand": 0.338572,
"capacity": 0.45,
"ok": true
},
"deflection_live": {
"demand": 0.225714,
"capacity": 0.3,
"ok": true
}
}
}

View file

@ -0,0 +1,181 @@
from pathlib import Path
import importlib.util
import json
import subprocess
import sys
import pytest
import yaml
HERE = Path(__file__).resolve().parent
spec = importlib.util.spec_from_file_location("wood_joist_calc", HERE / "calc.py")
assert spec is not None and spec.loader is not None
calc_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(calc_module)
compute = calc_module.compute
def load_input():
with (HERE / "input.yaml").open(encoding="utf-8") as handle:
return yaml.safe_load(handle)
@pytest.fixture
def result():
return compute(load_input())
def test_example_loads_and_section(result):
v = result["values"]
assert v["w_plf"] == pytest.approx(975)
assert v["wL_plf"] == pytest.approx(650)
assert v["A_in2"] == pytest.approx(33.25)
assert v["Ix_in4"] == pytest.approx(250.1, abs=0.1)
assert v["Sx_in3"] == pytest.approx(52.6, abs=0.1)
def test_example_demands(result):
v = result["values"]
assert v["M_ftlbf"] == pytest.approx(9871.88, abs=0.01)
assert v["V_lbf"] == pytest.approx(4387.5)
assert v["R_lbf"] == pytest.approx(4387.5)
def test_example_flexure(result):
v = result["values"]
assert v["RB"] == pytest.approx(0.881, abs=0.001)
assert v["Fb_star_psi"] == pytest.approx(2400)
assert v["FbE_psi"] == pytest.approx(789157.9, rel=1e-3)
assert v["CL"] == pytest.approx(0.9998, abs=0.001)
assert v["Fb_prime_psi"] == pytest.approx(2399.6, abs=0.2)
assert v["fb_psi"] == pytest.approx(2250.2, abs=0.1)
assert v["Ma_ftlbf"] == pytest.approx(10527.6, abs=0.3)
assert v["fb_psi"] / v["Fb_prime_psi"] == pytest.approx(0.938, abs=0.001)
assert result["checks"]["flexure"]["ok"] is True
def test_example_shear(result):
v = result["values"]
assert v["Fv_prime_psi"] == pytest.approx(300)
assert v["fv_psi"] == pytest.approx(197.932, abs=0.001)
assert v["fv_psi"] / v["Fv_prime_psi"] == pytest.approx(0.66, abs=0.005)
assert result["checks"]["shear"]["ok"] is True
def test_example_bearing(result):
v = result["values"]
assert v["bed_in"] == pytest.approx(3)
assert v["Cb"] == pytest.approx(1.15)
assert v["Fcp_prime_psi"] == pytest.approx(649.75, abs=0.01)
assert v["Ab_in2"] == pytest.approx(8.75)
assert v["fcp_psi"] == pytest.approx(501.429, abs=0.001)
assert v["fcp_psi"] / v["Fcp_prime_psi"] == pytest.approx(0.772, abs=0.001)
assert result["checks"]["bearing"]["ok"] is True
def test_example_deflection(result):
v = result["values"]
assert v["delta_total_in"] == pytest.approx(0.339, abs=0.001)
assert v["delta_live_in"] == pytest.approx(0.226, abs=0.001)
assert v["delta_allow_total_in"] == pytest.approx(0.45)
assert v["delta_allow_live_in"] == pytest.approx(0.30)
assert result["checks"]["deflection_total"]["ok"] is True
assert result["checks"]["deflection_live"]["ok"] is True
def test_all_checks_pass(result):
assert all(result["checks"][name]["ok"] for name in ("flexure", "shear", "bearing", "deflection_total", "deflection_live")) is True
def test_alternate_units_match_default(result):
alt = load_input()
alt.update({
"span": "108 in",
"width": "3.5 in",
"depth": "9.5 in",
"M": "118462.5 lbf * in",
"V": "4387.5 lbf",
"R": "4387.5 lbf",
})
converted = compute(alt)
for key in ("span_ft", "M_ftlbf", "V_lbf", "R_lbf", "fb_psi", "delta_total_in"):
assert converted["values"][key] == pytest.approx(result["values"][key], rel=1e-6)
def test_wrong_dimension_is_rejected():
bad = load_input()
bad["span"] = "9 kip"
with pytest.raises(ValueError, match="span"):
compute(bad)
def test_rb_limit_enforced():
bad = load_input()
bad["unbraced_length"] = "4000 in"
with pytest.raises(ValueError, match="50"):
compute(bad)
def test_cl_bounds_enforced():
bad = load_input()
# A very large E_min drives the beam stability factor to 0 (catastrophic
# cancellation in the C_L equation), which is out of the valid (0, 1] range.
bad["E_min"] = "1e100 psi"
with pytest.raises(ValueError, match="CL"):
compute(bad)
def test_bearing_length_limit_enforced():
bad = load_input()
bad["bearing_length"] = "6 in"
with pytest.raises(ValueError, match="6"):
compute(bad)
def test_bearing_end_distance_enforced():
bad = load_input()
bad["bearing_end_distance"] = "2.5 in"
with pytest.raises(ValueError, match="3"):
compute(bad)
def test_typst_compiles_and_presents_python_numbers(result):
subprocess.run([sys.executable, str(HERE / "calc.py")], check=True, cwd=HERE.parents[1])
pdf = HERE / "generated" / "wood-joist.pdf"
subprocess.run(
["typst", "compile", "--root", ".", "calcs/wood-joist/wood-joist.typ", str(pdf)],
check=True, cwd=HERE.parents[1],
)
assert pdf.exists()
query = subprocess.run(
["typst", "eval", "query(<wood-joist-results>)", "--root", ".",
"--in", "calcs/wood-joist/wood-joist.typ", "--format", "json"],
check=True, capture_output=True, text=True, cwd=HERE.parents[1],
)
published = json.loads(query.stdout)
assert len(published) == 1
meta = published[0]["value"]
values = result["values"]
assert meta["flexure_util"] == pytest.approx(values["fb_psi"] / values["Fb_prime_psi"], abs=0.001)
assert meta["shear_util"] == pytest.approx(values["fv_psi"] / values["Fv_prime_psi"], abs=0.001)
assert meta["bearing_util"] == pytest.approx(values["fcp_psi"] / values["Fcp_prime_psi"], abs=0.001)
assert meta["delta_total_in"] == pytest.approx(values["delta_total_in"], abs=1e-6)
assert meta["delta_live_in"] == pytest.approx(values["delta_live_in"], abs=1e-6)
def test_typst_load_demands_match_checked_inputs(result):
subprocess.run([sys.executable, str(HERE / "calc.py")], check=True, cwd=HERE.parents[1])
query = subprocess.run(
["typst", "eval", "query(<wood-joist-loads>)", "--root", ".",
"--in", "calcs/wood-joist/wood-joist.typ", "--format", "json"],
check=True, capture_output=True, text=True, cwd=HERE.parents[1],
)
published = json.loads(query.stdout)
assert len(published) == 1
derived = published[0]["value"]
values = result["values"]
assert derived["w_plf"] == pytest.approx(values["w_plf"], abs=0.001)
assert derived["wL_plf"] == pytest.approx(values["wL_plf"], abs=0.001)
assert derived["M_ftlbf"] == pytest.approx(values["M_ftlbf"], abs=0.01)
assert derived["V_lbf"] == pytest.approx(values["V_lbf"], abs=0.001)
assert derived["R_lbf"] == pytest.approx(values["R_lbf"], abs=0.001)

2090
wood-joist/wood-joist.pdf Normal file

File diff suppressed because it is too large Load diff

108
wood-joist/wood-joist.typ Normal file
View file

@ -0,0 +1,108 @@
#import "assets/sheet.typ": calcline, calcsheet, check
#let data = json("results.json")
#let n = data.values
#let checks = data.checks
#let round(value, digits: 2) = calc.round(value, digits: digits)
#show: calcsheet.with(
title: "Wood Joist Analysis",
project: data.project,
prepared-by: data.prepared_by,
)
= Wood Joist Analysis
Simple-span wood joist under uniform gravity load, analyzed per NDS 2018 ASD.
Pint parses `input.yaml`, `calc.py` computes the member capacities and checks.
Typst determines the gravity-load demands below; the checked Python inputs
are reconciled to those values by the test suite.
== Loads Determination
#let DL = 25
#let LL = 50
#let L = 9
#let B = 13
#let w = (DL + LL) * B
#let wL = LL * B
#let M = w * L * L / 8
#let V = w * L / 2
#let R = V
#metadata((w_plf: w, wL_plf: wL, M_ftlbf: M, V_lbf: V, R_lbf: R)) <wood-joist-loads>
#calcline([$L = #L " ft"$], [Simple span])
#calcline([$B = #B " ft"$], [Tributary spacing, on-center])
#calcline([$D = #DL " psf"$], [Dead load])
#calcline([$L_L = #LL " psf"$], [Live load])
#calcline([$w = (D + L_L) B = #w " plf"$], [Total uniform line load, Typst-derived])
#calcline([$w_("checked") = #round(n.w_plf, digits: 1) " plf"$], [Total uniform line load, checked input])
#calcline([$w_L = L_L B = #wL " plf"$], [Live uniform line load, Typst-derived])
#calcline([$w_("L,checked") = #round(n.wL_plf, digits: 1) " plf"$], [Live uniform line load, checked input])
#calcline([$M = w L^2 / 8 = #round(M, digits: 2) " ft·lbf"$], [Maximum moment, Typst-derived])
#calcline([$M_("checked") = #round(n.M_ftlbf, digits: 2) " ft·lbf"$], [Maximum moment, checked input])
#calcline([$V = w L / 2 = #V " lbf"$], [Support shear, Typst-derived])
#calcline([$V_("checked") = #round(n.V_lbf, digits: 1) " lbf"$], [Support shear, checked input])
#calcline([$R = V = #R " lbf"$], [Support reaction, Typst-derived])
#calcline([$R_("checked") = #round(n.R_lbf, digits: 1) " lbf"$], [Support reaction, checked input])
== Section Properties
#calcline([$b = #n.b_in " in"$, $d = #n.d_in " in"$], [Joist width and depth])
#calcline([$A = b d = #round(n.A_in2, digits: 2) " in"^2$], [Section area])
#calcline([$I_x = b d^3 / 12 = #round(n.Ix_in4, digits: 1) " in"^4$], [Moment of inertia])
#calcline([$S_x = b d^2 / 6 = #round(n.Sx_in3, digits: 1) " in"^3$], [Elastic section modulus])
== Material And Adjustment Factors
#calcline([$"Species/grade" = #n.species_grade$], [NDS Supplement reference values])
#calcline([$F_b = #n.Fb_psi " psi"$, $F_v = #n.Fv_psi " psi"$], [Reference bending and shear])
#calcline([$F_(c"⊥") = #n.Fcp_psi " psi"$], [Reference compression perpendicular to grain])
#calcline([$E = #n.E_psi " psi"$, $E'_"min" = #n.Emin_psi " psi"$], [Moduli of elasticity])
#calcline([$C_D = #n.CD$, $C_M = #n.CM$, $C_t = #n.Ct$, $C_F = #n.CF$], [Load duration, wet service, temperature, size])
#calcline([$C_r = #n.Cr$, $C_"fu" = #n.Cfu$, $C_i = #n.Ci$], [Repetitive member, flat use, incising])
== Flexure
#calcline([$l_e = #n.le_in " in"$], [Unbraced length of compression edge])
#calcline([$R_B = sqrt(l_e d / b^2) = #round(n.RB, digits: 3)$], [Slenderness ratio, NDS 3.3.3])
#calcline([$F^*_b = F_b C_D C_M C_t C_F C_i C_r = #round(n.Fb_star_psi, digits: 1) " psi"$], [Adjusted reference bending])
#calcline([$F_("bE") = 1.20 E'_"min" / R_B^2 = #round(n.FbE_psi, digits: 1) " psi"$], [Critical buckling stress])
#calcline([$C_L = (1 + F_("bE")/F^*_b)/1.9 - sqrt(...) = #round(n.CL, digits: 4)$], [Beam stability factor, NDS 3.3.3])
#calcline([$F'_b = F^*_b C_L C_"fu" = #round(n.Fb_prime_psi, digits: 1) " psi"$], [Adjusted bending])
#calcline([$f_b = M / S_x = #round(n.fb_psi, digits: 1) " psi"$], [Acting bending stress])
#calcline([$M_a = S_x F'_b = #round(n.Ma_ftlbf, digits: 1) " ft·lbf"$], [Allowable moment])
#v(7pt)
#check("Flexure", checks.flexure.demand, checks.flexure.capacity, unit: "psi", ok: checks.flexure.ok, demand-label: [$f_b$], capacity-label: [$F'_b$])
== Shear
#calcline([$F'_v = F_v C_D C_M C_t C_"vr" = #round(n.Fv_prime_psi, digits: 1) " psi"$], [Adjusted shear])
#calcline([$f_v = 3 V / (2 A) = #round(n.fv_psi, digits: 3) " psi"$], [Acting shear stress])
#v(7pt)
#check("Shear", checks.shear.demand, checks.shear.capacity, unit: "psi", ok: checks.shear.ok, demand-label: [$f_v$], capacity-label: [$F'_v$])
== Bearing
#calcline([$l_b = #n.lb_in " in"$], [Bearing length])
#calcline([$l_("end") = #n.bed_in " in"$], [Distance from member end to near edge of bearing, >= 3 in])
#calcline([$C_b = (l_b + 0.375) / l_b = #round(n.Cb, digits: 3)$], [Bearing area factor, NDS 3.10.4])
#calcline([$F'_("c⊥") = F_("c⊥") C_M C_t C_i C_b = #round(n.Fcp_prime_psi, digits: 2) " psi"$], [Adjusted bearing])
#calcline([$A_b = l_b b = #round(n.Ab_in2, digits: 2) " in"^2$], [Bearing area])
#calcline([$f_("c⊥") = R / A_b = #round(n.fcp_psi, digits: 2) " psi"$], [Acting bearing stress])
#v(7pt)
#check("Bearing", checks.bearing.demand, checks.bearing.capacity, unit: "psi", ok: checks.bearing.ok, demand-label: [$f_("c⊥")$], capacity-label: [$F'_("c⊥")$])
== Deflection
#calcline([$Delta_"total" = 5 w L^4 / (384 E I_x) = #round(n.delta_total_in, digits: 3) " in"$], [Total-load deflection])
#calcline([$Delta_"live" = 5 w_L L^4 / (384 E I_x) = #round(n.delta_live_in, digits: 3) " in"$], [Live-load deflection])
#calcline([$L/240 = #n.delta_allow_total_in " in"$], [Total-load limit])
#calcline([$L/360 = #n.delta_allow_live_in " in"$], [Live-load limit])
#v(7pt)
#check("Deflection (total)", checks.deflection_total.demand, checks.deflection_total.capacity, unit: "in", ok: checks.deflection_total.ok, demand-label: [$Delta_"total"$], capacity-label: [$L/240$])
#check("Deflection (live)", checks.deflection_live.demand, checks.deflection_live.capacity, unit: "in", ok: checks.deflection_live.ok, demand-label: [$Delta_"live"$], capacity-label: [$L/360$])

BIN
wood-stud-column/assets/logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View file

@ -0,0 +1,82 @@
#let navy = rgb("#1a3a5f")
#let muted = rgb("#626b73")
#let pass = rgb("#1f6b45")
#let fail = rgb("#9b2c2c")
#let calcsheet(
title: "Structural Calculation",
project: "",
prepared-by: "",
body,
) = {
set document(title: title, author: prepared-by)
set page(
paper: "us-letter",
margin: (x: 1in, top: 1.25in, bottom: 1in),
header: context {
grid(
columns: (1fr, 1fr),
align: (left, right),
image("../assets/logo.png", height: 30pt),
[#text(size: 9pt)[Project:] \
#text(size: 10pt, weight: "bold")[#project]],
)
},
footer: context {
set text(size: 8.5pt, fill: muted)
stack(
spacing: 4pt,
line(length: 100%, stroke: 0.5pt + muted),
[#prepared-by],
)
},
)
set text(font: "Libertinus Serif", size: 10pt, lang: "en")
set par(justify: true)
set heading(numbering: none)
show heading.where(level: 1): set text(size: 14pt, weight: "bold", fill: black)
show heading.where(level: 2): set text(size: 11pt, weight: "bold", fill: black)
show heading.where(level: 2): set block(above: 2em, below: 1em)
body
}
#let calcline(formula, note) = grid(
columns: (1.7fr, 1fr),
gutter: 4pt,
align: (left, left),
formula, text(size: 9pt, fill: muted, note),
)
#let check(label, demand, capacity, unit: "", ok: auto, demand-label: "Demand", capacity-label: "Capacity") = {
let utilization = demand / capacity
let passes = if ok == auto { utilization <= 1 } else { ok }
let color = if passes { pass } else { fail }
block(
breakable: false,
width: 100%,
stroke: 0.8pt + black,
inset: 8pt,
radius: 2pt,
)[
#grid(
columns: (1fr, auto),
[#text(weight: "bold")[#label]],
box(stroke: 0.8pt + color, inset: (x: 6pt, y: 2pt))[
#text(weight: "bold", fill: color)[#if passes { "OK" } else { "NOT OK" }]
],
)
#v(4pt)
#grid(
columns: (1fr, auto),
[
#demand-label: #calc.round(demand, digits: 2) #unit #h(14pt)
#capacity-label: #calc.round(capacity, digits: 2) #unit
],
[
D/C: #calc.round(utilization, digits: 2)
],
)
]
}

163
wood-stud-column/calc.py Normal file
View file

@ -0,0 +1,163 @@
from __future__ import annotations
import json
import math
import sys
import argparse
from pathlib import Path
try:
import yaml
except ImportError:
raise SystemExit("Install dependencies: python -m pip install -r requirements.txt")
try:
from pint import DimensionalityError, UndefinedUnitError, UnitRegistry
except ImportError:
raise SystemExit("Install dependencies: python -m pip install -r requirements.txt")
HERE = Path(__file__).resolve().parent
ureg = UnitRegistry()
ureg.define("kip = 1000 * force_pound")
ureg.define("ksi = kip / inch ** 2")
ureg.define("psi = force_pound / inch ** 2")
def quantity(value, unit: str, name: str) -> float:
try:
q = ureg.Quantity(value).to(unit)
except (DimensionalityError, UndefinedUnitError, TypeError, ValueError) as exc:
raise ValueError(f"{name}: expected {unit}, got {value!r}") from exc
magnitude = float(q.magnitude)
if magnitude <= 0:
raise ValueError(f"{name} must be positive")
return magnitude
def factor(value, name: str) -> float:
magnitude = float(value)
if magnitude <= 0:
raise ValueError(f"{name} must be positive")
return magnitude
# NDS 2018 constants for sawn-lumber columns (NDS 3.7.1.5, Eqs. 3.7-1 and 3.7-2).
KC_EULER = 0.822 # Euler buckling coefficient for a rectangular section about its
# weak axis (pi^2 / 12); appears directly in Eq. 3.7-2.
C_SAWN = 0.8 # Column-stability denominator coefficient c for sawn lumber
# (Eq. 3.7-1). c = 0.85 for round timber, 0.9 for glulam/SCL/CLT.
def _column_stability_factor(Fc_star: float, Emin_prime: float, Le: float, d: float):
"""NDS 3.7.1.5, Eq. 3.7-1 — column stability factor Cp for one buckling axis."""
FcE = KC_EULER * Emin_prime / (Le / d) ** 2
ratio = FcE / Fc_star
Cp = (1.0 + ratio) / (2.0 * C_SAWN) - math.sqrt(((1.0 + ratio) / (2.0 * C_SAWN)) ** 2 - ratio / C_SAWN)
if not math.isfinite(Cp) or Cp <= 0:
raise ValueError(f"Cp = {Cp:.4f} is not finite/positive; column stability invalid (NDS 3.7.1.4)")
return min(Cp, 1.0), FcE, ratio
def compute(inp: dict) -> dict:
# Geometry
b_in = quantity(inp["width"], "in", "width")
d_in = quantity(inp["depth"], "in", "depth")
L_in = quantity(inp["length"], "in", "length")
Ke = factor(inp["Ke"], "Ke")
# Material (NDS Supplement reference values)
Fc_psi = quantity(inp["Fc"], "psi", "Fc")
E_psi = quantity(inp["E"], "psi", "E")
Emin_psi = quantity(inp["E_min"], "psi", "E_min")
species_grade = str(inp["species_grade"])
# Adjustment factors (NDS Table 4.3.1)
CD = factor(inp["CD"], "CD")
CM = factor(inp["CM"], "CM")
Ct = factor(inp["Ct"], "Ct")
CF = factor(inp["CF"], "CF")
Ci = factor(inp["Ci"], "Ci")
# Checked axial demand (ASD)
P_lbf = quantity(inp["P"], "lbf", "P")
A_in2 = b_in * d_in
Le_in = Ke * L_in
d_least = min(b_in, d_in)
d_great = max(b_in, d_in)
# Adjusted reference compression (without Cp), NDS 3.7.1.5
Fc_star = Fc_psi * CD * CM * Ct * CF * Ci
Emin_prime = Emin_psi * CM * Ct * Ci
# Column stability factor about each axis; the weak axis governs.
Cp_weak, FcE_weak, ratio_weak = _column_stability_factor(Fc_star, Emin_prime, Le_in, d_least)
Cp_strong, FcE_strong, ratio_strong = _column_stability_factor(Fc_star, Emin_prime, Le_in, d_great)
governing_axis = "weak" if Cp_weak <= Cp_strong else "strong"
Cp = min(Cp_weak, Cp_strong)
FcE = FcE_weak if governing_axis == "weak" else FcE_strong
# Adjusted compression design value, NDS Table 4.3.1
Fc_prime = Fc_star * Cp
fc_psi = P_lbf / A_in2
Pa_lbf = Fc_prime * A_in2
def q(value: float) -> float:
return round(value, 6)
values = {
"P_lbf": q(P_lbf),
"L_in": q(L_in), "b_in": q(b_in), "d_in": q(d_in),
"A_in2": q(A_in2), "Ke": q(Ke), "Le_in": q(Le_in),
"d_least_in": q(d_least), "d_great_in": q(d_great),
"Le_d_weak": q(Le_in / d_least), "Le_d_strong": q(Le_in / d_great),
"species_grade": species_grade,
"Fc_psi": q(Fc_psi), "E_psi": q(E_psi), "Emin_psi": q(Emin_psi),
"CD": q(CD), "CM": q(CM), "Ct": q(Ct), "CF": q(CF), "Ci": q(Ci),
"kc_euler": q(KC_EULER), "c_sawn": q(C_SAWN),
"Fc_star_psi": q(Fc_star), "Emin_prime_psi": q(Emin_prime),
"FcE_weak_psi": q(FcE_weak), "FcE_strong_psi": q(FcE_strong),
"ratio_weak": q(ratio_weak), "ratio_strong": q(ratio_strong),
"Cp_weak": q(Cp_weak), "Cp_strong": q(Cp_strong),
"Cp": q(Cp), "governing_axis": governing_axis,
"Fc_prime_psi": q(Fc_prime), "fc_psi": q(fc_psi), "Pa_lbf": q(Pa_lbf),
}
checks = {
"axial": {"demand": q(P_lbf), "capacity": q(Pa_lbf), "ok": P_lbf <= Pa_lbf},
}
return {
"tool": "wood_stud_column",
"version": "0.1",
"project": inp.get("project", ""),
"prepared_by": inp.get("prepared_by", ""),
"values": values,
"checks": checks,
}
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Calculate the wood stud column axial capacity from a YAML input file.")
parser.add_argument("--input", "-i", type=Path, default=HERE / "input.yaml", help="YAML input path")
parser.add_argument("--output", "-o", type=Path, help="JSON output path; defaults beside the input")
parser.add_argument("--stdout", action="store_true", help="Write the complete JSON result to stdout instead of a file")
args = parser.parse_args(argv)
input_path = args.input
output_path = args.output or input_path.with_name("results.json")
with input_path.open(encoding="utf-8") as handle:
result = compute(yaml.safe_load(handle))
serialized = json.dumps(result, indent=2) + "\n"
if args.stdout:
sys.stdout.write(serialized)
else:
output_path.write_text(serialized, encoding="utf-8")
print(output_path)
return 0
if __name__ == "__main__":
raise SystemExit(main())

View file

@ -0,0 +1,29 @@
# Project name shown in the Typst report header.
project: "Interior Bearing Wall"
# Person or organization shown in the Typst report footer.
prepared_by: "Conemco Engineering"
# Axial load (ASD) checked against the allowable column capacity.
P: "400 lbf"
# Stud geometry (actual dimensions of a nominal 2x4).
length: "6 ft" # L, total stud length
width: "1.5 in" # b, actual 2x4 width
depth: "3.5 in" # d, actual 2x4 depth
Ke: 1.0 # effective-length factor, pinned-pinned (NDS 3.7.1.2 / Appendix G)
# Species and grade label shown in the report. "SP" is read as Southern Pine
# (SYP) per NDS Supplement Table 4B; confirm if SPF or SPF-S was intended.
species_grade: "SP (Southern Pine) No. 2"
# NDS Supplement reference design values for Southern Pine (SYP) No. 2, dimension lumber.
Fc: "1450 psi" # compression parallel to grain (F_c)
E: "1400000 psi" # modulus of elasticity (E)
E_min: "510000 psi" # 5th-percentile modulus (E_min)
# Adjustment factors (NDS Table 4.3.1). All 1.0 except size factor for this example.
CD: 1 # load duration factor (1.0 = normal/occupancy duration, NDS 2.3.2)
CM: 1 # wet service factor (dry, moisture < 19%, NDS 4.3.3)
Ct: 1 # temperature factor (< 100 deg F, NDS 4.3.4)
CF: 1.15 # size factor for compression, 2x4 (NDS 4.3.6)
Ci: 1 # incising factor (NDS 4.3.8)

View file

@ -0,0 +1,50 @@
{
"tool": "wood_stud_column",
"version": "0.1",
"project": "Interior Bearing Wall",
"prepared_by": "Conemco Engineering",
"values": {
"P_lbf": 400.0,
"L_in": 72.0,
"b_in": 1.5,
"d_in": 3.5,
"A_in2": 5.25,
"Ke": 1.0,
"Le_in": 72.0,
"d_least_in": 1.5,
"d_great_in": 3.5,
"Le_d_weak": 48.0,
"Le_d_strong": 20.571429,
"species_grade": "SP (Southern Pine) No. 2",
"Fc_psi": 1450.0,
"E_psi": 1400000.0,
"Emin_psi": 510000.0,
"CD": 1.0,
"CM": 1.0,
"Ct": 1.0,
"CF": 1.15,
"Ci": 1.0,
"kc_euler": 0.822,
"c_sawn": 0.8,
"Fc_star_psi": 1667.5,
"Emin_prime_psi": 510000.0,
"FcE_weak_psi": 181.953125,
"FcE_strong_psi": 990.633681,
"ratio_weak": 0.109117,
"ratio_strong": 0.594083,
"Cp_weak": 0.106575,
"Cp_strong": 0.496288,
"Cp": 0.106575,
"governing_axis": "weak",
"Fc_prime_psi": 177.71332,
"fc_psi": 76.190476,
"Pa_lbf": 932.994931
},
"checks": {
"axial": {
"demand": 400.0,
"capacity": 932.994931,
"ok": true
}
}
}

View file

@ -0,0 +1,65 @@
from pathlib import Path
import importlib.util
import json
import subprocess
import sys
import pytest
import yaml
HERE = Path(__file__).resolve().parent
spec = importlib.util.spec_from_file_location("wood_stud_column_calc", HERE / "calc.py")
assert spec is not None and spec.loader is not None
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
def result():
with (HERE / "input.yaml").open(encoding="utf-8") as handle:
return module.compute(yaml.safe_load(handle))
def test_typst_loads_match_checked_inputs():
subprocess.run([sys.executable, str(HERE / "calc.py")], check=True, cwd=HERE.parents[1])
query = subprocess.run(
[
"typst", "eval", "query(<wood-stud-column-loads>)", "--root", ".",
"--in", "calcs/wood-stud-column/beam.typ", "--format", "json",
],
check=True,
capture_output=True,
text=True,
cwd=HERE.parents[1],
)
published = json.loads(query.stdout)
assert len(published) == 1
derived = published[0]["value"]
values = result()["values"]
assert derived["P_lbf"] == pytest.approx(values["P_lbf"], abs=0.001)
assert derived["A_in2"] == pytest.approx(values["A_in2"], abs=0.001)
def test_ground_truth_column_stability():
output = result()
values = output["values"]
assert values["A_in2"] == pytest.approx(5.25)
assert values["Le_in"] == pytest.approx(72.0)
assert values["Le_d_weak"] == pytest.approx(48.0, abs=0.01)
assert values["FcE_weak_psi"] == pytest.approx(181.9, abs=0.5)
assert values["Cp_weak"] == pytest.approx(0.107, abs=0.003)
assert values["Cp_strong"] == pytest.approx(0.497, abs=0.005)
assert values["Fc_prime_psi"] == pytest.approx(177.6, abs=0.5)
assert values["Pa_lbf"] == pytest.approx(932.0, abs=3.0)
assert output["checks"]["axial"]["ok"] is True
def test_cli_can_write_json_to_stdout():
completed = subprocess.run(
[sys.executable, str(HERE / "calc.py"), "--input", str(HERE / "input.yaml"), "--stdout"],
check=True,
capture_output=True,
text=True,
)
output = json.loads(completed.stdout)
assert output["values"]["P_lbf"] == pytest.approx(400)
assert completed.stderr == ""

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,62 @@
#import "assets/sheet.typ": calcline, calcsheet, check
#let data = json("results.json")
#let n = data.values
#let checks = data.checks
#let round(value, digits: 2) = calc.round(value, digits: digits)
#show: calcsheet.with(
title: "Wood Stud Column — Axial Capacity",
project: data.project,
prepared-by: data.prepared_by,
)
= Wood Stud Column — Axial Capacity
Concentrically loaded 2x4 wood stud (SP / Southern Pine No. 2) analyzed for
axial compression parallel to grain per NDS 2018 ASD. Pint parses `input.yaml`;
`calc.py` computes the column stability factor $C_p$ (NDS 3.7.1.5, Eq. 3.7-1)
and the adjusted compression capacity. The governing limit state is compression
with buckling about the weak axis.
== Geometry And Axial Load
#let P = 400
#let L_ft = 6
#let b = 1.5
#let d = 3.5
#let A = b * d
#metadata((P_lbf: P, A_in2: A)) <wood-stud-column-loads>
#calcline([$P = #P " lbf"$], [Axial load, compression (ASD)])
#calcline([$L = #L_ft " ft" = #n.L_in " in"$], [Total stud length])
#calcline([$b = #b " in"$, $d = #d " in"$], [Actual dimensions of a nominal 2x4])
#calcline([$A = b d = #round(n.A_in2, digits: 2) " in"^2$], [Cross-sectional area])
#calcline([$K_e = #n.Ke$], [Effective-length factor, pinned-pinned (NDS 3.7.1.2)])
#calcline([$L_e = K_e L = #round(n.Le_in, digits: 1) " in"$], [Effective length])
#calcline([$d_"min" = min(b, d) = #n.d_least_in " in"$], [Least dimension; weak-axis buckling governs])
#calcline([$L_e / d_"min" = #round(n.Le_in / n.d_least_in, digits: 1) <= 50$], [Slenderness ratio, weak axis; cap $L_e/d <= 50$ (NDS 3.7.1.4)])
== Material And Adjustment Factors
#calcline([$"Species/grade" = #n.species_grade$], [NDS Supplement reference values])
#calcline([$F_c = #n.Fc_psi " psi"$], [Reference compression parallel to grain])
#calcline([$E = #n.E_psi " psi"$, $E'_"min" = #n.Emin_psi " psi"$], [Moduli of elasticity])
#calcline([$C_D = #n.CD$, $C_M = #n.CM$, $C_t = #n.Ct$, $C_F = #n.CF$, $C_i = #n.Ci$], [Load duration ($C_D=1.0$ normal/occupancy, NDS 2.3.2), wet service, temperature, size ($C_F=1.15$ for 2x4 compression, NDS 4.3.6), incising (NDS Table 4.3.1)])
== Column Stability Factor (NDS 3.7.1.4)
#calcline([$F^*_c = F_c C_D C_M C_t C_F C_i = #round(n.Fc_star_psi, digits: 1) " psi"$], [Adjusted reference compression, NDS 3.7.1.5])
#calcline([$E'_"min" = E_"min" C_M C_t C_i = #round(n.Emin_prime_psi, digits: 0) " psi"$], [Adjusted 5th-percentile modulus])
#calcline([$F_("cE") = 0.822 E'_"min" / (L_e / d_"min")^2 = #round(n.FcE_weak_psi, digits: 2) " psi"$], [Critical buckling stress, NDS Eq. 3.7-2 (coefficient 0.822)])
#calcline([$0.822$ (Euler coeff., NDS Eq. 3.7-2), $c = #n.c_sawn$], [Sawn-lumber column coefficient, NDS Eq. 3.7-1])
#calcline([$C_p = (1 + F_("cE")/F^*_c)/(2c) - sqrt(...) = #round(n.Cp, digits: 4)$], [Column stability factor, NDS Eq. 3.7-1 (3.7.1.5); weak axis governs])
== Adjusted Compression Capacity
#calcline([$F'_c = F^*_c C_p = #round(n.Fc_prime_psi, digits: 2) " psi"$], [Adjusted compression design value, NDS 3.7.1.5])
#calcline([$f_c = P / A = #round(n.fc_psi, digits: 2) " psi"$], [Acting compression stress])
#calcline([$P_a = F'_c A = #round(n.Pa_lbf, digits: 1) " lbf"$], [Allowable axial load])
#v(7pt)
#check("Axial Compression", checks.axial.demand, checks.axial.capacity, unit: "lbf", ok: checks.axial.ok, demand-label: [$P$], capacity-label: [$P_a$])