From 7e16ef4f0d7e4c1636da0a54ec7d4625ef8cc8f5 Mon Sep 17 00:00:00 2001 From: daeungo1 Date: Fri, 3 Jul 2026 15:16:08 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat(ptu=5Flb):=20Adaptive=20TPM=20Quota=20?= =?UTF-8?q?Controller=20-=20Reserved-total=20=EA=B3=B5=EC=9C=A0=20?= =?UTF-8?q?=EC=BA=A1=20=EC=9E=AC=EB=B6=84=EB=B0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 다중 리전(KR/UK) Foundry 배포 용량을 고정 예약 총량 내에서 재분배하는 컨트롤러 추가 - Python 런북(adaptive_tpm_quota_controller.py) 실제 actuation + --dry-run 지원 - PowerShell 옵션 런북, requirements.txt - 아키텍처 다이어그램(excalidraw/png), 테스트 문서(ptu-lb-test.md), README --- ptu_lb/README.md | 3 + ptu_lb/ptu-lb-test.md | 311 +++ ptu_lb/ptu_architecture.excalidraw | 1801 +++++++++++++++++ ptu_lb/ptu_architecture.png | Bin 0 -> 189765 bytes ptu_lb/render_excalidraw.py | 106 + .../runbooks/adaptive_tpm_quota_controller.py | 447 ++++ ...optional_adaptive_tpm_quota_controller.ps1 | 418 ++++ ptu_lb/runbooks/requirements.txt | 3 + 8 files changed, 3089 insertions(+) create mode 100644 ptu_lb/README.md create mode 100644 ptu_lb/ptu-lb-test.md create mode 100644 ptu_lb/ptu_architecture.excalidraw create mode 100644 ptu_lb/ptu_architecture.png create mode 100644 ptu_lb/render_excalidraw.py create mode 100644 ptu_lb/runbooks/adaptive_tpm_quota_controller.py create mode 100644 ptu_lb/runbooks/optional_adaptive_tpm_quota_controller.ps1 create mode 100644 ptu_lb/runbooks/requirements.txt diff --git a/ptu_lb/README.md b/ptu_lb/README.md new file mode 100644 index 0000000..1303429 --- /dev/null +++ b/ptu_lb/README.md @@ -0,0 +1,3 @@ +# PTU LB Test Docs + +메인 문서는 [ptu-lb-test.md](ptu-lb-test.md) 입니다. diff --git a/ptu_lb/ptu-lb-test.md b/ptu_lb/ptu-lb-test.md new file mode 100644 index 0000000..97fcb9b --- /dev/null +++ b/ptu_lb/ptu-lb-test.md @@ -0,0 +1,311 @@ +# Adaptive PTU TPM Quota 조정 가이드 (with Sample Test) + +## 문제 상황 + +동일 워크로드를 처리하는 2개 모델 배포(Korea/UK)가 있으며, 각 리전의 사용률(utilization)에 따라 모델별 TPM quota(= deployment SKU capacity)를 안정적으로 자동 조정하는 adaptive 자동화가 필요하다. + +- 현재 테스트 환경: Global Standard deployment 2개 +- 목표 운영 환경: PTU deployment 기반 자동화 +- 핵심 목표: TPM quota 조정 자동화, 성능 안정화, 플래핑 방지 + +> **핵심 설계 결정 — Reserved quota 공유 상한 하 비례 재분배** +> +> 두 리전(Korea/UK)은 사용자가 **Reservation한 총 TPM quota**(예: 20,000 TPM)를 나눠 쓰며, 두 배포 capacity의 **합은 이 Reserved 총량을 어떤 시점에도 초과할 수 없다.** 초과하는 증설 요청은 거부된다. +> 따라서 각 리전을 독립으로 올리는 방식이 아니라, **고정된 Reserved 총량을 트래픽 비율에 맞춰 두 리전에 재분배**한다. +> - **감축 먼저, 증설 나중**: 총량이 꽉 찬 상태에서 증설을 먼저 하면 실패하므로, 여유를 내주는 리전을 **먼저 감축**해 headroom을 확보한 뒤 증설한다. +> - **loss 최소화**: 증설은 우선 미할당 버퍼로 충당(무손실)하고, 버퍼가 부족할 때만 잉여 리전에서 회수하되 감축·증설을 같은 사이클에서 연속 처리해 총 가용량이 줄어드는 구간을 최소화한다. +> - **리전 최소 보장**: 각 리전은 Reserved 총량의 25% 이상을 항상 유지한다. +> +> ※ 위 수치(총량 20,000 TPM, 리전 최소 보장 25% 등)는 **샘플 값**이며, 런북 상단 파라미터로 조정 가능한 **변수**다. Reserved 총량(`RESERVED_TOTAL_TPM`), capacity 환산(`TPM_PER_CAPACITY_UNIT`), 최소 보장 비율(`MIN_CAPACITY_RATIO`), 목표/상하한 사용률(`AIM_UTIL`/`TARGET_UTIL_HIGH`/`TARGET_UTIL_LOW`), 스텝(`MAX_STEP_UNITS`), 쿨다운(`COOLDOWN_MINUTES`) 등을 운영 환경에 맞게 바꿔 쓰면 된다. + +## 아키텍처 + +Azure Automation은 **스케줄러 + 실행/인증 호스트** 역할이며, 실제 제어 로직은 Python 런북(Azure SDK)이 담당한다. 제어 루프는 **① 메트릭 적재 → ② 윈도우 조회 → ③ 목표 재분배·capacity 갱신(감축→증설, 쿨다운 가드) → ④ 이력 기록** 순으로 동작한다. + +- 데이터 플레인(파랑): Client → App/Router → Foundry(KR/UK) → Azure Monitor +- 제어 플레인(초록): 스케줄이 Hybrid Runbook Worker를 트리거하고, Worker가 VNet 안에서 Python 런북을 실행(관리 ID 인증) +- 상태 저장소(보라): Table Storage(TrafficWindow/ControlDecision/ScaleAction)에 **Private Endpoint**로 접근 (Storage `publicNetworkAccess=Disabled`) +- capacity 조정(빨강): 런북이 Reserved 총량 제약 하에 **감축→증설 순서**로 Foundry 배포 SKU capacity를 ARM(공용 경로)으로 갱신 + + +![PTU TPM Quota Adaptive Controller 아키텍처](ptu_architecture.png) + +## Azure 리소스 구성 + +### 필수 + +1. Azure AI Foundry model deployment (Korea) +2. Azure AI Foundry model deployment (UK) +3. Azure Storage Account (Table Storage) +4. Azure Automation Account +5. Managed Identity (Runbook 실행 주체) +6. Azure Monitor 또는 Log Analytics + +### 권장 + +1. Application Insights +2. Azure Key Vault +3. Action Group + +## 데이터 모델 (Table Storage) + +### TrafficWindow + +- 목적: n분 단위 메트릭 집계 저장 +- PartitionKey: region (korea | uk) +- RowKey: windowStartUtc (ISO8601) +- 컬럼: requestCount, inputTokens, outputTokens, p95LatencyMs, errorRate, assignedTpm + +### ControlDecision + +- 목적: 리전별 제어 의사결정 저장 +- PartitionKey: date (yyyyMMdd) +- RowKey: `{timestamp}-{region}-{guid}` +- 컬럼: region, utilization, avgConsumedTpm, capacityBefore, capacityTarget, decision(up|down|hold), reason, cooldownBlocked, executed + +### ScaleAction + +- 목적: 리전별 실제 capacity 조정 실행 결과 저장 +- PartitionKey: date (yyyyMMdd) +- RowKey: `{timestamp}-{region}-{guid}` +- 컬럼: region, requestPayload, capacityBefore, capacityTarget, changed, responseStatus, success, errorMessage, durationMs + +## 안정적 자동화 운영 원칙 + +짧은 주기로 빈번하게 조정하면 오히려 불안정해질 수 있으므로, 제어 루프는 안정성을 우선한다. + +1. 관측 주기와 조정 주기를 분리 +2. 단일 포인트가 아닌 이동평균으로 판단 +3. 쿨다운 동안 재조정 금지 +4. 1회 최대 변경폭 제한 +5. 리전별 최소/최대 capacity 경계값 강제(최소 = Reserved 총량의 25%) +6. 두 리전 capacity 합은 Reserved 총량을 항상 준수(초과 증설 불가) +7. 재분배는 감축을 먼저 실행해 headroom 확보 후 증설 + +## 운영 파라미터 (변수화) + +제어 knob은 리전별 **capacity unit**(배포 SKU capacity)이며, `TPM_PER_CAPACITY_UNIT`로 TPM과 매핑한다. 두 리전 capacity의 합은 `RESERVED_TOTAL_TPM`(Reserved quota)을 넘을 수 없다. + +| 파라미터 | 의미 | 권장 시작값 | +|---|---|---| +| METRIC_WINDOW_MINUTES | 메트릭 집계 윈도우(분) | 5 | +| SMOOTHING_WINDOWS | 이동평균 윈도우 개수 | 3 | +| TPM_PER_CAPACITY_UNIT | capacity 1 unit ≈ TPM | 1000 | +| RESERVED_TOTAL_TPM | Reservation한 총 TPM 상한(합산 불변) | 20000 | +| TOTAL_CAPACITY_UNITS | Reserved 총량의 capacity 환산(= RESERVED_TOTAL_TPM / TPM_PER_CAPACITY_UNIT) | 20 | +| TARGET_UTIL_HIGH | 이 사용률 초과 → 증설 압력 | 0.75 | +| TARGET_UTIL_LOW | 이 사용률 미만 → 감축(잉여 회수) | 0.30 | +| AIM_UTIL | 조정 후 목표 사용률 | 0.60 | +| MAX_STEP_UNITS | 1회 최대 capacity 변경폭 | 5 | +| MIN_CAPACITY_RATIO | 리전별 최소 보장 비율(Reserved 총량 대비) | 0.25 | +| MIN_CAPACITY | 리전별 최소 보장 capacity(= ceil(TOTAL × 0.25)) | 5 | +| MAX_CAPACITY | 리전별 최대 capacity(= TOTAL − MIN_CAPACITY) | 15 | +| COOLDOWN_MINUTES | 조정 후 재조정 금지 시간(분) | 20 | + +> 불변식: 항상 `cap_KR + cap_UK ≤ TOTAL_CAPACITY_UNITS`. 2리전 가정에서 리전 최대는 `TOTAL − MIN_CAPACITY`이며, 최소는 총량의 25%를 보장한다. + +## 샘플 테스트 Sizing (권장) + +샘플 테스트 목적이므로 비용과 변동성을 낮추는 보수적 크기로 시작한다. + +### 권장 시작값 + +1. 모델 배포 수: 2개 (Korea, UK) +2. Reserved 총량: 20,000 TPM (= 20 capacity unit) +3. 초기 capacity: 10 / 10 (합 20 = Reserved 총량 만재, 버퍼 0) +4. 리전 최소 capacity: 5 (Reserved 총량의 25%) +5. 리전 최대 capacity: 15 (= 총량 − 상대 리전 최소) +6. 1회 조정폭: 최대 5 unit +7. 사용률 밴드: LOW 30% ~ HIGH 75% (AIM 60%) +8. 쿨다운: 20분 + +### 부하 프로파일 (샘플) + +Reserved 총량이 만재(10/10)인 상태에서 트래픽을 기울여 리전 간 재분배를 유도한다. + +1. Baseline 20분: 양 리전 util 40~60% (유지 구간, 재분배 없음) +2. 기울기 30분: Korea util 85%+ / UK util 20% → UK 먼저 감축 후 Korea 증설(감축→증설) +3. 역전 30분: UK util 85%+ / Korea util 20% → 반대 방향 재분배(쿨다운 경과 후) +4. 진동 30분: 10분 단위 고/저 교차 → 쿨다운/스텝 제한으로 왕복 억제 + +### 샘플 성공 기준 + +1. 두 리전 capacity 합이 Reserved 총량을 항상 준수(초과 0회) +2. 재분배 시 감축이 증설보다 먼저 실행됨(증설 선행 실패 0회) +3. 고사용률 리전 증설분이 잉여 리전 감축분으로 충당됨(loss 최소) +4. 쿨다운 중 불필요한 재조정이 발생하지 않음 +5. ControlDecision, ScaleAction 이력이 누락 없이 기록됨 + +### 파라미터 적용 규칙 + +1. 스케줄 주기는 METRIC_WINDOW_MINUTES의 배수 +2. COOLDOWN_MINUTES는 스케줄 주기보다 크게 설정 +3. 초기에는 MAX_STEP_UNITS를 낮게 시작해 플래핑 여부 검증 + +## Adaptive 제어 로직 (Reserved 총량 공유) + +두 리전을 **하나의 Reserved 총량 예산**으로 함께 평가하고, 목표를 먼저 산출한 뒤 총량 제약을 지키는 순서로 실행한다. + +1. 각 배포의 현재 capacity를 SDK로 조회(폐루프 기준값) +2. 최근 SMOOTHING_WINDOWS 구간의 분당 소비 TPM 이동평균 산출 + +$$ +consumedTpm_r = \frac{1}{N}\sum_{i=1}^{N} \frac{inputTokens_i + outputTokens_i}{METRIC\_WINDOW\_MINUTES} +$$ + +3. 리전별 사용률과 AIM_UTIL 기준 필요 capacity(need) 산출 + +$$ +utilization_r = \frac{consumedTpm_r}{capacity_r \times TPM\_PER\_CAPACITY\_UNIT} +\qquad +need_r = \left\lceil \frac{consumedTpm_r}{AIM\_UTIL \times TPM\_PER\_CAPACITY\_UNIT} \right\rceil +$$ + +4. 목표 capacity 산출 (Reserved 총량 제약) +- **여유 있음** ($\sum_r need_r \le TOTAL$): 각 리전에 need만 배정, 나머지는 미할당 버퍼로 둔다 +- **경합** ($\sum_r need_r > TOTAL$): 각 리전에 MIN을 먼저 보장하고, 남은 용량을 소비 TPM 비율로 배분 + +$$ +target_r = MIN\_CAPACITY + \left\lfloor (TOTAL - n \cdot MIN\_CAPACITY)\times\frac{consumedTpm_r}{\sum_j consumedTpm_j} \right\rfloor +$$ + +5. dead-band·스텝 완충 +- 경합이 아니고 사용률이 [LOW, HIGH] 안이면 유지(hold)로 churn 방지 +- 목표로의 이동을 ±MAX_STEP_UNITS로 제한 +- 리전 최소/최대(MIN_CAPACITY ~ MAX_CAPACITY = TOTAL − MIN) 경계 적용 + +6. 쿨다운 가드 +- 해당 리전의 마지막 '실제 변경(changed=true)' ScaleAction이 COOLDOWN_MINUTES 이내면 조정 차단 + +7. 총량 제약 실행 (감축 먼저 → 증설 나중) +- 현재 headroom = TOTAL − Σ(현재 capacity) +- planned < 현재인 리전(잉여 회수)을 **먼저 감축** → headroom 증가 +- planned > 현재인 리전을 **사용률 높은 순**으로, 남은 headroom 한도 안에서만 증설 +- headroom이 없으면 이번 사이클 증설은 보류(다음 사이클 수렴), 어떤 시점에도 합 ≤ TOTAL 보장 + +8. 실행 및 기록 +- capacity 갱신 API 호출(azure-mgmt-cognitiveservices) +- ControlDecision, ScaleAction 기록(경합 여부·headroom 제한 사유 포함) +- 다음 주기에서 개선 여부 재평가 + +## Runbook Workflow + +한 사이클은 두 리전을 함께 처리한다(공유 총량 재분배): + +1. (수집) 각 배포의 현재 capacity 조회 + Table 최근 윈도우로 이동평균 사용률 계산 +2. (산출) 리전별 need 계산 → Reserved 총량 제약으로 목표(target) 배분(여유/경합 분기) +3. (완충) dead-band·스텝·쿨다운 가드로 이번 사이클 planned 결정 +4. (실행 1) planned < 현재인 리전을 먼저 감축 → headroom 확보 +5. (실행 2) planned > 현재인 리전을 사용률 높은 순으로 headroom 한도 내 증설 +6. (기록) 리전별 ControlDecision / ScaleAction 기록 +7. (안전) 개별 API 실패 시 기록 후 계속, 합이 총량을 넘지 않도록 보장 + +## 테스트 시나리오 + +### Test-1 Baseline + +- 양 리전 util 40~60% 유지, 총량 만재(10/10) +- 불필요 조정 0회 확인 + +### Test-2 재분배 (감축→증설) + +- Korea util 85%+ / UK util 20% 유도 +- UK 감축이 Korea 증설보다 먼저 실행되고, 합이 총량을 유지하는지 확인 + +### Test-3 증설 선행 방지 + +- 총량 만재 상태에서 Korea 증설 요청 발생 +- 감축 없이 증설을 시도하지 않음(증설 선행 실패 0회) 확인 + +### Test-4 경합 비례 배분 + +- 양 리전 동시 고부하(합 need > 총량) +- 소비 TPM 비율대로 target이 배분되고 합 ≤ 총량 확인 + +### Test-5 플래핑 억제 + +- 10분 단위로 사용률 고/저 교차 +- 쿨다운/스텝 제한으로 왕복 조정 억제 확인 + +### Test-6 장애 복원력 + +- capacity 변경 API 실패 강제 +- 재시도/기록/안전 종료 및 총량 불변식 유지 확인 + +## 테스트 결과 + +실제 Azure 리소스(Foundry 배포 2개 + Storage Table)에 대해 라이브 검증한 결과다. Reserved 총량 = 20 unit(20000 TPM), baseline 10/10. + +| # | 시나리오 | 입력(소비 TPM/min) | 판단 | capacity 변화 | 합 | 결과 | +|---|----------|--------------------|------|----------------|-----|------| +| A | 경합 비례 배분(dry-run) | KR 9000 / UK 7000 | contention=True | 10/10 → 11/9 | 20 | 소비 비율대로 재분배, 합 ≤ 총량 | +| B | 재분배 실제 조정 | KR 9000 / UK 저부하 | contention=True | 10/10 → 13/7 | 20 | **UK 감축이 먼저 실행되어 headroom 확보 후 KR 증설**, SDK로 실 capacity 13/7 확인 | +| C | 수렴·안정 | B 직후 동일 부하 | hold/hold | 13/7 유지 | 20 | 조정 후 util이 dead-band(69%/52%)에 안착 → 불필요 조정 0회 | +| D | 쿨다운 가드 | 큰 부하 변화 재유도 | hold/hold | 13/7 유지 | 20 | target(14/6) 산출됐으나 쿨다운(20분)으로 차단 → 플래핑 억제 | + +- **총량 불변식**: 모든 사이클에서 KR+UK 합 = 20 ≤ Reserved 총량(초과 0회). +- **감축 선행**: Test-B에서 증설 선행 실패 없이 감축→증설 순서로 폐루프 조정 완료. +- 오프라인 시뮬레이션(Azure SDK 스텁)에서도 baseline·경합·유휴 등 케이스 전부 합 ≤ 20, 감축 선행 순서 준수 확인. + +## 완료 기준 + +1. 두 리전 capacity 합이 Reserved 총량을 항상 준수(초과 0회) +2. 재분배가 감축→증설 순서로 수행되고, 증설 선행 실패가 0회 +3. 조정 후 고부하 리전의 p95 latency 또는 error rate 개선 관찰 +4. 플래핑 없이 안정적 제어(쿨다운/스텝 준수) +5. 모든 판단/실행 이력 저장 + +## 파일 구성 + +- 메인 문서: [ptu-lb-test.md](ptu-lb-test.md) +- 아키텍처 다이어그램(원본): [ptu_architecture.excalidraw](ptu_architecture.excalidraw) +- 아키텍처 다이어그램(이미지): [ptu_architecture.png](ptu_architecture.png) +- 다이어그램 렌더러(유틸): [render_excalidraw.py](render_excalidraw.py) +- **Runbook(기본, Python): [runbooks/adaptive_tpm_quota_controller.py](runbooks/adaptive_tpm_quota_controller.py)** +- Runbook 의존성: [runbooks/requirements.txt](runbooks/requirements.txt) +- Runbook(선택, PowerShell 동등 이식본): [runbooks/optional_adaptive_tpm_quota_controller.ps1](runbooks/optional_adaptive_tpm_quota_controller.ps1) + +> 기본 구현은 Python 런북이다. PowerShell 버전은 동일한 Reserved 총량 공유 재분배 로직(감축→증설, 실제 actuation·쿨다운 포함)을 Az 모듈(Az.Accounts / Az.CognitiveServices / AzTable)로 이식한 **선택적 대체 구현**으로, PowerShell 선호 환경을 위한 참조본이다. Storage가 Private Endpoint 구성이면 이 런북도 프라이빗 경로가 닿는 워커(예: Windows Hybrid Worker)에서 실행해야 한다. + +## 배포 구성 (프로덕션 아키텍처) + +무인(unattended) 자동 운영을 위한 권장 구성이다. 핵심 제약은 Storage `publicNetworkAccess=Disabled` 환경에서 Automation 클라우드 샌드박스(공용 인프라)가 Table에 접근할 수 없다는 점이며, **VNet 내 Hybrid Runbook Worker + Table Private Endpoint**로 해결한다. Foundry capacity 갱신은 ARM(`management.azure.com`) 관리 평면이라 항상 공용 경로로 동작하므로 Foundry용 Private Endpoint는 필요 없다. + +### 제약과 해결 + +| 제약 | 원인 | 해결 | +|---|---|---| +| 샌드박스가 Storage에 접근 불가 | Storage public 접근 차단 + 샌드박스는 공용 인프라에서 실행 | VNet 내 Hybrid Runbook Worker + Table Private Endpoint | +| Foundry 접근용 PE 필요 여부 | capacity 갱신은 ARM 관리 평면(항상 공용) | Foundry PE 불필요, Table PE만 구성 | +| 10분 주기 스케줄 | Automation 네이티브 스케줄 최소 간격이 1시간 | 10분 오프셋 시간 스케줄 6개(`sched-min-00/10/20/30/40/50`) | + +### 네트워크 · 워커 + +1. VNet(예: `10.20.0.0/16`) — 워커 서브넷과 PE 서브넷(PE 네트워크 정책 비활성)을 분리 +2. Private DNS Zone `privatelink.table.core.windows.net` 생성 후 VNet에 링크 +3. Storage Table Private Endpoint(group-id=`table`) → 사설 IP로 해석 +4. Hybrid Worker VM(Ubuntu, 공용 IP 없음, System-assigned MI) + `HybridWorkerForLinux` 확장 → Hybrid Worker Group에 등록 +5. VM에 `python3` + `azure-identity` / `azure-data-tables` / `azure-mgmt-cognitiveservices` 설치 (인증은 IMDS로 VM MI 사용) + +### 권한 (RBAC) + +- Hybrid Worker VM MI: **Storage Table Data Contributor**(Storage) + **Cognitive Services Contributor**(양 Foundry) +- 인증 경로: `DefaultAzureCredential` → IMDS → VM System-assigned MI + +### 런북 · 스케줄 + +1. `runbooks/adaptive_tpm_quota_controller.py`를 Automation Python 3 런북으로 게시하고 Hybrid Worker Group에서 실행 +2. 6개 시간 스케줄을 `runOn=`으로 연결해 10분 주기를 구현 + - `az automation`에는 `job-schedule` 서브커맨드가 없으므로 REST로 연결: `az rest --method put --url ".../jobSchedules/{guid}?api-version=2023-11-01"` +3. 최초 배포는 `--dry-run`으로 판단 로직을 검증한 뒤 실제 실행으로 전환 + +### 배포 검증 체크리스트 + +- 런북 잡이 워커에서 **Completed**로 종료 +- 워커가 사설 경로로 Table을 읽고 Foundry capacity를 실제 변경 → 테스트 후 baseline(10/10) 복원 +- 고사용률 리전 단독 증설 · 저사용률 리전 단독 감축 · 쿨다운 중 재조정 차단 확인 +- ControlDecision · ScaleAction 이력이 누락 없이 기록 + +### 비용 참고 + +- Hybrid Worker VM은 상시 과금된다. 미사용 시 중지: `az vm deallocate -g -n ` diff --git a/ptu_lb/ptu_architecture.excalidraw b/ptu_lb/ptu_architecture.excalidraw new file mode 100644 index 0000000..7f4e033 --- /dev/null +++ b/ptu_lb/ptu_architecture.excalidraw @@ -0,0 +1,1801 @@ +{ + "type": "excalidraw", + "version": 2, + "source": "https://excalidraw.com", + "elements": [ + { + "id": "title", + "type": "text", + "x": 60, + "y": 24, + "width": 1140, + "height": 34, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 101, + "version": 1, + "versionNonce": 101, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "PTU TPM Quota Adaptive Controller — 리전 독립 오토스케일", + "fontSize": 26, + "fontFamily": 2, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "PTU TPM Quota Adaptive Controller — 리전 독립 오토스케일", + "lineHeight": 1.2 + }, + { + "id": "subtitle", + "type": "text", + "x": 60, + "y": 64, + "width": 1000, + "height": 20, + "angle": 0, + "strokeColor": "#868e96", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 102, + "version": 1, + "versionNonce": 102, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "Hybrid Runbook Worker + Storage Private Endpoint (unattended · 10분 주기)", + "fontSize": 15, + "fontFamily": 2, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Hybrid Runbook Worker + Storage Private Endpoint (unattended · 10분 주기)", + "lineHeight": 1.2 + }, + { + "id": "cFoundry", + "type": "rectangle", + "x": 520, + "y": 110, + "width": 250, + "height": 180, + "angle": 0, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1.5, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 110, + "version": 1, + "versionNonce": 110, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "cFoundryT", + "type": "text", + "x": 532, + "y": 116, + "width": 230, + "height": 18, + "angle": 0, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 111, + "version": 1, + "versionNonce": 111, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "모델 배포 (리전 독립 quota)", + "fontSize": 13, + "fontFamily": 2, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "모델 배포 (리전 독립 quota)", + "lineHeight": 1.2 + }, + { + "id": "cAuto", + "type": "rectangle", + "x": 60, + "y": 380, + "width": 700, + "height": 310, + "angle": 0, + "strokeColor": "#f08c00", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1.5, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 112, + "version": 1, + "versionNonce": 112, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "cAutoT", + "type": "text", + "x": 76, + "y": 388, + "width": 600, + "height": 20, + "angle": 0, + "strokeColor": "#f08c00", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 113, + "version": 1, + "versionNonce": 113, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "제어 플레인 — Azure Automation", + "fontSize": 15, + "fontFamily": 2, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "제어 플레인 — Azure Automation", + "lineHeight": 1.2 + }, + { + "id": "cStore", + "type": "rectangle", + "x": 820, + "y": 400, + "width": 400, + "height": 290, + "angle": 0, + "strokeColor": "#6741d9", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1.5, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 114, + "version": 1, + "versionNonce": 114, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "cStoreT", + "type": "text", + "x": 836, + "y": 408, + "width": 380, + "height": 34, + "angle": 0, + "strokeColor": "#6741d9", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 115, + "version": 1, + "versionNonce": 115, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "상태 저장소 — Table Storage\n(Private Endpoint · public 접근 차단)", + "fontSize": 13, + "fontFamily": 2, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "상태 저장소 — Table Storage\n(Private Endpoint · public 접근 차단)", + "lineHeight": 1.2 + }, + { + "id": "bClient", + "type": "rectangle", + "x": 60, + "y": 140, + "width": 150, + "height": 70, + "angle": 0, + "strokeColor": "#1971c2", + "backgroundColor": "#a5d8ff", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 120, + "version": 1, + "versionNonce": 120, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "bClientT", + "type": "text", + "x": 60, + "y": 153, + "width": 150, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 121, + "version": 1, + "versionNonce": 121, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "Client\n(부하·실사용)", + "fontSize": 16, + "fontFamily": 2, + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Client\n(부하·실사용)", + "lineHeight": 1.2 + }, + { + "id": "bRouter", + "type": "rectangle", + "x": 280, + "y": 140, + "width": 170, + "height": 70, + "angle": 0, + "strokeColor": "#1971c2", + "backgroundColor": "#a5d8ff", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 122, + "version": 1, + "versionNonce": 122, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "bRouterT", + "type": "text", + "x": 280, + "y": 153, + "width": 170, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 123, + "version": 1, + "versionNonce": 123, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "App / Router\n(요청 분배)", + "fontSize": 16, + "fontFamily": 2, + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "App / Router\n(요청 분배)", + "lineHeight": 1.2 + }, + { + "id": "bKR", + "type": "rectangle", + "x": 540, + "y": 150, + "width": 210, + "height": 54, + "angle": 0, + "strokeColor": "#f08c00", + "backgroundColor": "#ffe066", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 124, + "version": 1, + "versionNonce": 124, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "bKRT", + "type": "text", + "x": 540, + "y": 155, + "width": 210, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 125, + "version": 1, + "versionNonce": 125, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "Foundry (Korea)\ntpmtest-kr", + "fontSize": 15, + "fontFamily": 2, + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Foundry (Korea)\ntpmtest-kr", + "lineHeight": 1.2 + }, + { + "id": "bUK", + "type": "rectangle", + "x": 540, + "y": 222, + "width": 210, + "height": 54, + "angle": 0, + "strokeColor": "#f08c00", + "backgroundColor": "#ffe066", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 126, + "version": 1, + "versionNonce": 126, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "bUKT", + "type": "text", + "x": 540, + "y": 227, + "width": 210, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 127, + "version": 1, + "versionNonce": 127, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "Foundry (UK)\ntpmtest-uk", + "fontSize": 15, + "fontFamily": 2, + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Foundry (UK)\ntpmtest-uk", + "lineHeight": 1.2 + }, + { + "id": "bMon", + "type": "rectangle", + "x": 880, + "y": 170, + "width": 180, + "height": 70, + "angle": 0, + "strokeColor": "#495057", + "backgroundColor": "#e9ecef", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 128, + "version": 1, + "versionNonce": 128, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "bMonT", + "type": "text", + "x": 880, + "y": 183, + "width": 180, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 129, + "version": 1, + "versionNonce": 129, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "Azure Monitor\n(토큰·지연 메트릭)", + "fontSize": 15, + "fontFamily": 2, + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Azure Monitor\n(토큰·지연 메트릭)", + "lineHeight": 1.2 + }, + { + "id": "bSch", + "type": "rectangle", + "x": 90, + "y": 440, + "width": 170, + "height": 95, + "angle": 0, + "strokeColor": "#f08c00", + "backgroundColor": "#ffec99", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 130, + "version": 1, + "versionNonce": 130, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "bSchT", + "type": "text", + "x": 90, + "y": 454, + "width": 170, + "height": 66, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 131, + "version": 1, + "versionNonce": 131, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "스케줄 10분 주기\n(6× 시간 스케줄,\n10분 오프셋)", + "fontSize": 14, + "fontFamily": 2, + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "스케줄 10분 주기\n(6× 시간 스케줄,\n10분 오프셋)", + "lineHeight": 1.2 + }, + { + "id": "bMI", + "type": "rectangle", + "x": 90, + "y": 565, + "width": 170, + "height": 90, + "angle": 0, + "strokeColor": "#f08c00", + "backgroundColor": "#ffec99", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 132, + "version": 1, + "versionNonce": 132, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "bMIT", + "type": "text", + "x": 90, + "y": 588, + "width": 170, + "height": 44, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 133, + "version": 1, + "versionNonce": 133, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "Managed Identity\n(System-assigned)", + "fontSize": 14, + "fontFamily": 2, + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Managed Identity\n(System-assigned)", + "lineHeight": 1.2 + }, + { + "id": "bWk", + "type": "rectangle", + "x": 320, + "y": 455, + "width": 200, + "height": 110, + "angle": 0, + "strokeColor": "#2f9e44", + "backgroundColor": "#b2f2bb", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 134, + "version": 1, + "versionNonce": 134, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "bWkT", + "type": "text", + "x": 320, + "y": 477, + "width": 200, + "height": 66, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 135, + "version": 1, + "versionNonce": 135, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "Hybrid Runbook Worker\nhrw-vm (VNet)\nUbuntu · B2s", + "fontSize": 15, + "fontFamily": 2, + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Hybrid Runbook Worker\nhrw-vm (VNet)\nUbuntu · B2s", + "lineHeight": 1.2 + }, + { + "id": "bRb", + "type": "rectangle", + "x": 560, + "y": 455, + "width": 170, + "height": 110, + "angle": 0, + "strokeColor": "#2f9e44", + "backgroundColor": "#b2f2bb", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 136, + "version": 1, + "versionNonce": 136, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "bRbT", + "type": "text", + "x": 560, + "y": 477, + "width": 170, + "height": 66, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 137, + "version": 1, + "versionNonce": 137, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "Python 런북\nAdaptiveTpmQuota\nControllerPy", + "fontSize": 14, + "fontFamily": 2, + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Python 런북\nAdaptiveTpmQuota\nControllerPy", + "lineHeight": 1.2 + }, + { + "id": "bTW", + "type": "rectangle", + "x": 850, + "y": 460, + "width": 340, + "height": 54, + "angle": 0, + "strokeColor": "#6741d9", + "backgroundColor": "#d0bfff", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 138, + "version": 1, + "versionNonce": 138, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "bTWT", + "type": "text", + "x": 850, + "y": 477, + "width": 340, + "height": 22, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 139, + "version": 1, + "versionNonce": 139, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "TrafficWindow · 집계 메트릭", + "fontSize": 15, + "fontFamily": 2, + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "TrafficWindow · 집계 메트릭", + "lineHeight": 1.2 + }, + { + "id": "bCD", + "type": "rectangle", + "x": 850, + "y": 535, + "width": 340, + "height": 54, + "angle": 0, + "strokeColor": "#6741d9", + "backgroundColor": "#d0bfff", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 140, + "version": 1, + "versionNonce": 140, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "bCDT", + "type": "text", + "x": 850, + "y": 552, + "width": 340, + "height": 22, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 141, + "version": 1, + "versionNonce": 141, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "ControlDecision · 의사결정", + "fontSize": 15, + "fontFamily": 2, + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "ControlDecision · 의사결정", + "lineHeight": 1.2 + }, + { + "id": "bSA", + "type": "rectangle", + "x": 850, + "y": 610, + "width": 340, + "height": 54, + "angle": 0, + "strokeColor": "#6741d9", + "backgroundColor": "#d0bfff", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 142, + "version": 1, + "versionNonce": 142, + "isDeleted": false, + "boundElements": [], + "updated": 1762128000000, + "link": null, + "locked": false + }, + { + "id": "bSAT", + "type": "text", + "x": 850, + "y": 627, + "width": 340, + "height": 22, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 143, + "version": 1, + "versionNonce": 143, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "ScaleAction · 실행 이력 · 쿨다운 기준", + "fontSize": 14, + "fontFamily": 2, + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "ScaleAction · 실행 이력 · 쿨다운 기준", + "lineHeight": 1.2 + }, + { + "id": "a1", + "type": "arrow", + "x": 210, + "y": 175, + "width": 70, + "height": 0, + "angle": 0, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 150, + "version": 1, + "versionNonce": 150, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 70, + 0 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "a2", + "type": "arrow", + "x": 450, + "y": 170, + "width": 90, + "height": 7, + "angle": 0, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "seed": 151, + "version": 1, + "versionNonce": 151, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 47, + 0 + ], + [ + 47, + 7 + ], + [ + 90, + 7 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "a3", + "type": "arrow", + "x": 450, + "y": 185, + "width": 90, + "height": 64, + "angle": 0, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "seed": 152, + "version": 1, + "versionNonce": 152, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 47, + 0 + ], + [ + 47, + 64 + ], + [ + 90, + 64 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "a4", + "type": "arrow", + "x": 750, + "y": 177, + "width": 130, + "height": 13, + "angle": 0, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "seed": 153, + "version": 1, + "versionNonce": 153, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 65, + 0 + ], + [ + 65, + 13 + ], + [ + 130, + 13 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "a5", + "type": "arrow", + "x": 750, + "y": 249, + "width": 130, + "height": 29, + "angle": 0, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "seed": 154, + "version": 1, + "versionNonce": 154, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 95, + 0 + ], + [ + 95, + -29 + ], + [ + 130, + -29 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "a6", + "type": "arrow", + "x": 970, + "y": 240, + "width": 0, + "height": 220, + "angle": 0, + "strokeColor": "#6741d9", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 155, + "version": 1, + "versionNonce": 155, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 220 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "a7", + "type": "arrow", + "x": 730, + "y": 487, + "width": 120, + "height": 0, + "angle": 0, + "strokeColor": "#6741d9", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 156, + "version": 1, + "versionNonce": 156, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 120, + 0 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "a8", + "type": "arrow", + "x": 645, + "y": 565, + "width": 205, + "height": 72, + "angle": 0, + "strokeColor": "#6741d9", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "seed": 157, + "version": 1, + "versionNonce": 157, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 72 + ], + [ + 205, + 72 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "a9", + "type": "arrow", + "x": 645, + "y": 455, + "width": 0, + "height": 179, + "angle": 0, + "strokeColor": "#e03131", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 3, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 158, + "version": 1, + "versionNonce": 158, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 0, + -179 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "a10", + "type": "arrow", + "x": 260, + "y": 487, + "width": 60, + "height": 0, + "angle": 0, + "strokeColor": "#2f9e44", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 159, + "version": 1, + "versionNonce": 159, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 60, + 0 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "a11", + "type": "arrow", + "x": 260, + "y": 600, + "width": 160, + "height": 35, + "angle": 0, + "strokeColor": "#2f9e44", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "seed": 160, + "version": 1, + "versionNonce": 160, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 160, + 0 + ], + [ + 160, + -35 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "L1", + "type": "text", + "x": 985, + "y": 330, + "width": 150, + "height": 20, + "angle": 0, + "strokeColor": "#6741d9", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 161, + "version": 1, + "versionNonce": 161, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "① 메트릭 적재", + "fontSize": 14, + "fontFamily": 2, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "① 메트릭 적재", + "lineHeight": 1.2 + }, + { + "id": "L2", + "type": "text", + "x": 735, + "y": 462, + "width": 120, + "height": 20, + "angle": 0, + "strokeColor": "#6741d9", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 162, + "version": 1, + "versionNonce": 162, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "② 윈도우 조회", + "fontSize": 14, + "fontFamily": 2, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "② 윈도우 조회", + "lineHeight": 1.2 + }, + { + "id": "L3", + "type": "text", + "x": 658, + "y": 300, + "width": 160, + "height": 36, + "angle": 0, + "strokeColor": "#e03131", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 163, + "version": 1, + "versionNonce": 163, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "③ capacity 갱신\n(ARM · 공용 경로)", + "fontSize": 14, + "fontFamily": 2, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "③ capacity 갱신\n(ARM · 공용 경로)", + "lineHeight": 1.2 + }, + { + "id": "L4", + "type": "text", + "x": 470, + "y": 598, + "width": 160, + "height": 36, + "angle": 0, + "strokeColor": "#6741d9", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 164, + "version": 1, + "versionNonce": 164, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "④ 이력 기록\n(Decision·Action)", + "fontSize": 13, + "fontFamily": 2, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "④ 이력 기록\n(Decision·Action)", + "lineHeight": 1.2 + }, + { + "id": "L5", + "type": "text", + "x": 262, + "y": 463, + "width": 60, + "height": 20, + "angle": 0, + "strokeColor": "#2f9e44", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 165, + "version": 1, + "versionNonce": 165, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "트리거", + "fontSize": 13, + "fontFamily": 2, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "트리거", + "lineHeight": 1.2 + }, + { + "id": "L6", + "type": "text", + "x": 300, + "y": 576, + "width": 90, + "height": 20, + "angle": 0, + "strokeColor": "#2f9e44", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 166, + "version": 1, + "versionNonce": 166, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "인증(MI)", + "fontSize": 13, + "fontFamily": 2, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "인증(MI)", + "lineHeight": 1.2 + }, + { + "id": "legend", + "type": "text", + "x": 60, + "y": 712, + "width": 1140, + "height": 20, + "angle": 0, + "strokeColor": "#495057", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 167, + "version": 1, + "versionNonce": 167, + "isDeleted": false, + "boundElements": null, + "updated": 1762128000000, + "link": null, + "locked": false, + "text": "색상: 파랑=데이터 흐름 · 보라=제어 루프(①②④) · 빨강=capacity 조정(③) · 초록=Automation 실행·인증", + "fontSize": 13, + "fontFamily": 2, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "색상: 파랑=데이터 흐름 · 보라=제어 루프(①②④) · 빨강=capacity 조정(③) · 초록=Automation 실행·인증", + "lineHeight": 1.2 + } + ], + "appState": { + "gridSize": 20, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file diff --git a/ptu_lb/ptu_architecture.png b/ptu_lb/ptu_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..c79ced68f57e6cdd05ffe9d704051fde7f23895f GIT binary patch literal 189765 zcmeFZWmr|~+dZn=y$uX7Km`G@P(q}o6$Av7?zBh==>`J?6;MG+1f(0J8w>=bL2^+l z-AXrS%>8@c|9j5&b3UDSU0(YVwrkBfpXZKok1?M0OkP%UKN&UIwr$(?OI^RFxNX~> z58JlwJiq%d{N|hMWXQJd+qOwvyQ=K)ZnD?j;Yi!+$3NNM;_dyLL}e1AmQFpM*NxqM zJ#(*GNylT#4DF16inW!G&@i1pRcdeCvWLRt(DmIO$}P^llbf3%&LjEprg;`wD{gdj z5na8Uh7A#+;k|VNGkj#e5~p#!|9X9-%!mH{^!R|*1w|v`~Pg)Hc7Qz z;eURzd-3r6|NK-ee&xvj`RQTrsguN0{^#}4{2;|Y|NXx0(+UXECa z|6R;~0js>m2m>?E$0sHd4{dV#I#>({OiX9L@Y^SVNNdU`JE z6jhUtnYC)>&gHy%_pYbh-F@Zul<_gVL0;g$s#^E=14SVnEpaj<4dM4Ip2zb(JGpOThQclIHIX}^1(e(Z*$$k%U@k^)wyUbGM z*w6H3ly9!q1Ts@bG}aKW=f1u|PV=LZ^scQbY8i%+u6E16fAScg!5eQ?{im2F?x+j7 zB1Jm2E#+H%y-tb4pLCt#`3o*TKYKDpINVvCADbze^YilZit8pGww3-rMR#2!yMp%F z<+q7JHt#L#KlF5#2dOG5T5Ybcczb(SS67FGguHwAu7r3A`brE84GoQrjZIDU7THet z(F#0$`gC#ZdsT05@1)rWn;DIfrYuryn1oI6ix;)^VZ5x(Ax!%E`Zptmh0dLmaEmu= zj8KZdG4?${ZlKb)w4`Kqc2-eQ@$=`;dFH)Ne}0K4)y3ZoJ9X+5k7?(Rp&|X;c%n%x z`l82t+$Sn3T2osaH>7E`zvJAYLx*(TR)(0>(rsq?HonV=n2~al(zN~#@r_W+PqRCC zVq2YfO!El=JJYqrskNmUw)5u`vu+p=uXu`Iq}==6`4&e-3knPO(+j(_#7do(^s{;J z;DgDF+kaVDSfrSx6cj9HR?!8-L~U+v)&{ZCaNP5@J1#=J%A1;+Bu&$Lr0Gu zWn;@g2;^Awm+6(eiFq9uD!cnpn|LNH&Rz!D2*H&a=8ROG;`VmdWL9OSww1Y&#t0$j zh4Hq6f`Zo8*3X|sb2X=a{`@&M))g)OBG0UQak9(0`W1tln_Hea%R|lNN(zBL4#$2@ zc4f;1Uo3T5$%y~?Z#H5QR6c(s&*X-FSy`ECcRS*a zO{eG#E3awigYG=Dt5>h`*O22K2ySxWCa|?oDe_CZ2b?ZRug+ z^melcSXT}b)X z#ta@NTeSNY!@+|G?^gK*(ogpm=i@ItrgEim8&P}7$@6c^n7qWY)4MI-MkFW}iT%U( z@9WvKX9;qVy4eQ4F);(L7{sV9YIhdfTTJj$KCECV=X^xUc>n%~FK=IGo>|ypfUK{Aiy%c@p>9iuS|_D{JeyxjF10?ZJbVe|~)>ZXqa0I^~+UxX|io44!>+ z{<~a#n5(+vz-nP(A&DISoYj6SE<)!`WMqGm5~FdU)L2@46au{{&ct4 zRQ~NRJEy#8c+GQEWXAbcG{Y#O5imTaQf9A$gY)lw^Z)c@*VgjDOBD$*W@gkbo6)8m zAW<}dhudVkfbkl+*ZA=>+1Y*KC9RqZF%_*7X896a>x;g ziH5tqsjt)&(FoX0T9j`XOys@SjGv50hGSnsQ_jAA{aW%R9k-g<>UlOc_oZHYM0E-+ zxp`OC5Q4cQRl^z&k(ij++1ZIip}qXz#|yTy5ca!IU9$5u(>8~K^(uX7>?hh;@8@-? zM#sbiv*}&bGfJF5k!Cu>YucTcmYP~8QJ=}Xla@8oWmYOu*cB;(8nlJA&@3{`?JBe$ zd5R4&sHYB;J}WdZGqd&k3%UEBuSfBC$kW+0t$chg8)^oM%uM;#W}BK`>DK02czC#3 zx9N+lY)*3d?%0Hc`yxn+h&0W|q>P-L`EQJoKHlE1A~inT`jmOM3Ki<0kdh#Z>~KT4 z^JHh{KYOXFYse{`<$(>|CNbC032Ey(%Oz?aPZ%OhVWzDJf;>mOA0~uwOF4HhcH(#b#@(t1q`I z$&IB)aX5#!SHHFBneUB#A`!E)I+0Pn{A;h0=J{+ZCnICyvB&@HJwPwaB69e|3G}I7 zC=n_l*;Tc*DXvJ;?)*qW$JyeUvSNe!w~ZoOf+8Y%yDhOxyXajWpznkW*ykAxq?w`t zva_@2nS1hW{HdbX(9j??-ZLl+x1!mi&`L>fXh zG0Wp2hOdQV$D`X6nF9AybB#7deGwxUnqTP9qZe^=0cMy@nJHb;H7jVQH0ZxsY&Z4% za>8JyQp(i_52aySs(4#bxtlK zwJ}g0&+A3!WQ0u#vWU;MWZ52Mw>ob;!%m}pw|m3R*s9* zOko`QHOQp%B1BDSX=%BU^g&iD-&{vp`uQTKl$6v&M@GJi^BK~>HrvsrPy94(vRdT3 zcV9BnnVR+avJVRq^3Qe!S8g+sP5oQ$7ztm0Iuow9_WiDE4X#&NZ_k^P?b~PC68nrI zx};+jYJsIv*%X2zuhgP+At+~Za4^Ses76iC zwGHJgFYPaR`t_BOND}!=Iw8%KDj(Xv=WZ2Y%ip|tbG;U=(_uK&@J5C;z?fA?n$`1r z8?PfGhzOCY_4D(aokO8`7Lol-t2&g^FxK%-!PRMRvIi;Ke) zwR{^QMYd2yzL6)~3|kye$)MJJ=H*qDtdc^_ZE{Aa#BpwzG1BEu-nq~IJQjT{dhEx! zOs4eY~Fp5fUvMN z#0x1|D6u~0?g+Wa`iCb^j&Gi~d+;EH&pLknH!?21Lu15<>us=}8=ruHmeVr&3Q_Mh z8)|AabBtck@BOrjTruw}xxl&vTwv0@f8V}0!TU?)6pCHGJl$X4ehy3Vp6>1eg)a_{ zj`g9OBe-G^9i6ZXQ7rS!4l!}w;SCH7+<%xox;Eke-;E)kZL9sJHTt-Ah zNSN{q2(00b1A-{YzNTtq+f9-5uL(JkGVgjV{u3N06YS*Ra7?GWz;fW}0a_-VYWbA5 zt(8XiI*x~zSQrHbwIf0v%np7#aNxkBM~{~J-OIVW&2QYO!~0S%8F8NUPzO{&@r)Y+ zghm8(OMFWn?JrKYZqOD)&-E9Q_g^cG`{B;|DNLcA3(YoMsP;rf7c>>7nu`nPWV zK)xFXu>$>K|MmZ!0#x%~1qPn&Ph|3tKYs-9o4dAsf&ET}_ZKg6nOb1pFk#oC%?auJ zap}S1w~6!%d5m?$3^J%cJd%>TulJ@&E(uo}t_u~}m=B;h#l|*+M`AY@j*4_!m5TUa z(weA%MzgZABGDSdIQ4MoxDBT;=nl~3_Q=@_ExY$op)6{^z%Jmi5GBY#FM9D9& zt=W$@-LCLHh=Giqf15>f1k1&XeV7gC-PZx9Uk3%L>gx7=xcvns5^?WKFH(j$k?7E7 z92^;$>C7C!{L|8XR1_bCKz8`?@eykBI4L*fERUw9=4#~Dx}@83vn0KSS)aU2B)y`N zQod=I)%xyJgNpR-xEk->v#NcGLv{h$*`iSe)+4f_qMv_! zdJ>l@v17*$?7aSHt`A1x?K^f>A09F7Ey~5Tj9m+4YYEM7%+M{f)jH}S185lfO3FWum&pWzeY!wD-O%CXyzmqeRI7jqM0nvP~~&{@bTjpSZDgn%aMqy7H1LL zn>O}SBwN4>6)KDzc>7HG`m7A?((QdTJf`3L&ywtYL%yQN9c9%#!@2|>1-)T7tz6oG zPo$b@rT{Gj^_zeJc%US!z*nzcp>ST0c&sVuxtjQZMa5hWgE?q}G@+K5#0zCdJSK_yrifTnJ(7XKp^ipKAvw%J^3$wDy ziv9D7PoEf0o;-Q!lDxCsPwYWMxIli9ip_jUv%pX-TlqR>&NzMW6c{6R?%Fk>I|N9L zB!4{@63n783xKYo!NJE@=)SdC$xYy@M6VO3y$_2dBWQ2#{y8vk_e;=~U1IhDHilQS z4eBdj(z6K#1O*vX{Ih}LP}AHbjHwHmu{%oWMt~#0x}2^#>XU{+j>`EX-{Wrv&?B;% z=J|b(J1Zm+tFgbP+`oLDS#R*gABb&6=ad+r-7bZvDE5qSsJeeJRoEyRmx~SQ3M#BCL0D ziFU7NiI0yDQ0(Xva^a@%KsU@2dk&v_$7fynerK!E#_GasR^ijn-#?L!c!B)lvmSO? z84AXydQxO&W?GLlfR9VO%1y&~_N;!T&vDAXocUWLl#F~?>_@3d#)&V$MKF%U6&4g+ zj~Q59Sz*;H>uGLQa1!R`Uck7LKk7|8d?R+ws;5)+)>i^LrS8gKnpr z+|LGEm=NJ4?e~-^um&MeV1=h;#~LECwf!ENqe`Or%(8}5hH@Dz1^_eiTJ(X_kP0|g z545MZwb}t5Cm+Nb=GoEF(GMR!5F_A_j*brFjgVV4RK5gu8Iu!bxTdPwjx|6H-%dM( zwsgsH_8uQKKQKv3uL&{!bqYPL;|^I|PRYIJ&8KWIZ?1{Ag8hpf0&JQF$PdbhZ%a%~ zy-{}Jq{ni1|K>SX^^4?dxY0MkUI%DR(qGf$W{00TeVUVl!{i1HM=^>AI7w0G%?|9c z>{~A5j}N!+r{S@&vy;7f)7QtRC*PtUVIB9%8a?RrOTnx=U&*q`nR2n}k?xxsnszoe zlim3ymDtxYZB3ePO)0_ z6j%bL>}+$vCIfIw^Tmtq#zb=g!5AS(48o0#Y^P5TfDS>+XmCuT@s*}hU|^xWa$Vcl{!R}@Sue{(6RZ~a@FO9TKiX|4WiW?>7Q36P+R)$c4zPxO zNHGsY)&w))l9D;oo=T9N07Z(gb* z-JC|Fyoiy(qq?C1&zw+fJHZ1&7_r4;+*0xVJ11ycKE4%DmH;2^bbl9M?gV*R8n|m@ z7s7k;Sb5rhKoLI2E>X_RPc{-W@d&Si`(R9)2iYpdJ3}_zkr)RaGaw;J8&YVq{Iaz`fQvFIxjJ%%Jv237@;n` zpd!L_vCB};ZACxn0oV}hMxlK4da^%!*1nG1=r;L%PAQ)s`r>-w2r5LmVO_{UO3JfB zD_|Scovc2^#-8CzhyqtYDe>2d%MWg0Gvn@8Fv>;Tkd|(7PyG1!@#FuL4mA5Aj1Wz3 z9XH={g zP#-TFUW9r}?6HXnFe-q>Z!}}I#42q`8U5|sw?ElMF6^@Wf#MW^1CRzO=H1u__boTR z1sA{{b8~Y_vc$G=qV6!n(Fr-ZY%Fw;oCVJiuY0%xr~y*3eFjBzL4mraovkhR&`l{& z-xuh&fqJld@ZrbuVFM8n?>&0)1gF7`TesfZ{829Ym|V}VbB~Hj$Y%dISF5;5 z?rL1HZjsf{^Z5sWRFo2dE+F%fa6=EOlavw+8Y6HoCQltQ!Pco@bPEa!3JGyQ#407o zE{rx0cplaLU|U=PhM?bV&CFQ(1-L`ttBcwNO%?oV>Dm`YVu}k2e2#NgwyL(@!5*!T z#=OiCvj;1qn|VhZh1({h6BC7NGYuQGVJ zZbfM&gl2{1>{4xUXK9+9wVK-VjfzG6)@t~0k+`Jfee%ltl@Am1^Ya%k>9y0FK3JI@ zvdRlBFW&+Isrys0EDsq4IYQNK4GiwT>+NAE0d!pp{}*mc#TSmBFDkWxlrek zr!6NvFag5KsV!MWW!RJX$nz>X=Nr^F6=u6F%8e76G(OFbeIL@_kgRW`D=V(~V?`{o z`#q<{$wJJlOauMX)6>kVsiV*W<}dN^s0t+Y9s$4XADj{<|6M!P+HHBZmW`H{78OWx z$|x}pO}}LM*NfRNNNz&|1M1&A`_9Cv64Ma`7dfE?Wh|<;wzg)j3HRN~eU2aGHCP2b zRjZ=C(yxX;<(G_86xv#!v$A10f8Gd-7U=Fouzsz=W>3AmhndSq)x?rf2Mk-CVtK>D`+*XBws2@yGy!s^>9+Z($`RH5cdR*1%H> z2?{2s+)Pq-`~7K`Rmlnp-*=(Vl!%KX*+u2T=&;6)mn{RO ziCOJ!|HDjxqT!K|rGb|sJmx*>_TMxe$kP1c$aOXZ_7{zbh{v@Vq+-l=0~t72+z)Np z4e2ocbV;wsCdp1y9b8Gpv%`=e?iL>3|NhD1=()UHKxlAK#u^AS%z1>4rJ(RSYT?My zqeKTK<@=-JiAP-iB3w~fnXZvN403fE(1=jSP#wOp5kwfIG^mHXHV?ds`rQ;IM#>I| zjf(>$bph}KPxl)Q%5c?pFVWAj332+nc6p&uN!9YaGqeZB!7le;xiDP_I{f|-#HzKr zynH@TT2HV4$B!T2Cd$xA5DdM*D_{+8ja3rGXMtk7!j5Z_k|Mb8*)PP%4jGNdlsx%f zP%oGJri-IS;~9miJ95G+v6O!M9UXKTJfKcHR)zTAq_wCtBf=Z0& zGC;qX)j#m3yyB$waZUptzm-=xzQ@=_b<-_RvM9Y1a#k%f;WX{MG_`Sd@BaM|5KD7h zMjB|REMsk($|Tk?c#d+`w_tD5M;uBpD=hUn%SC?snG^8k0G*&wb43~1yYTQKpD*v; zoiJY3?#)qplyZZd&=!V1j*D#mc}YFTiIBxoElJgqnpKsq&k0Dg@DF`xYamD3fnH9X z=15OZCn;5E%%5iSa6mD9^7yd{i|SsvsJ6_{Q7MKAQRdJ5{35uF{ki($DMS%whZ+l>03l{s+Yvb?(bd69l} zE}$o!st|f^vfaCvAzq<7iI}vWUl~YJOp*=f&qYjvUMyW5Pm$mi;OAeRYZM8lZ-@}m za@Ols1(3yJy04=O6BP@+611N!N+%(huFo|#3eNdVXCEg*NU5_i(u68bH3ie&{EYjS zR)n$zW-U_iRRx+5OWvDM$wBQ&$;wiRV*3{X*wL$76gI(4p+vQ01qXM$V_0Hs^ z$8{;G%$}!6=JRYQ=D9_8(DehW$UuSK^^JNBvB0tVGLi-CxngAH`M?^CyY4`st4G=c z4hnUp>j((V#9QF;P<$Zho%cA;%q)Pp(NCDG7&eFuG*nG+aw*f+ZzN(~FXf`&B8Qlc zoIigaWNB&6$l8qVEF4!1yupSycf0y?{`@oeJ(ISGsFCQWMin~2EvN7?yjqR~i5rq2GA`ijSpx#j&YFiid~?uydVH6jG%i=GAag&Ft1 z6mjT`f1FiVT|T1|-UmCBwqwhK#iy+`JC6!3#tgK^?a{Xu4r-*a=$ zn91u~NThg#z1{jA!eUtG_s}SpjEv06$_hh)BZdb;dP^t=lG^-2E|PP*`($>LIg~Xy zASqaO;=J_SHx{6U*u3c|V|RfhhUQpl)^U;)e5$W8FoE z&o{o~JKZnW1VWF=@K#t~0Z)jKQoF_>b-@sjUcB(T} zpv+>CMU_u6jfF2P+^|)h10sYn`8tFcm{FM0w*cb^^}odPy=;okc7^@UUXiO|<}_efTu zxmeSn9ecp11Z|2 zPAXfJ^>@ZwlN8qrKw{&;fNB%dW8aA;$e&NHvlVb&Of5n0yd^}_1jZj)Pr+MJx)_z+ zw+oF|QXSoz8Wh?Y!073=TYHNS%+K`eMc%O;J!0Z1rq(Dcreg_q2vD`ScnyQWe%jr! zn9VTC!oE@utW8j(VunHl6zG@~+^o=zlI!T?)Bw>9 zNSsm>Ivz3T=#`b!_>;z>P#N1qk{Yg&ENjp~QDb$YgabI<$~ZU_l=S4@R})j4X-x_! zaT%!GKbMo_UD@&Yr)QqMA0()>CAA-;s}-yRFGA)Cf~1^xV)RmxFrsW z&UJK+?lR%*fqAFpWZS1tpHQ;WET!r&)4UXdkK(0}!SLeo>N0y(omgciM%j0lEq@Uf zFYr|8DCc;1c)*1-FkD@8Bm7>lGjLnlGRbOA<-Cc~OMx&#~Ov_qMrYfRg!z+ZL5UbhVYR46WlFjx{;BQ8LBDuA*1hIqq^SSyuHoSTfNUfuTHC$z}Y9I(^3)nw88{nfV^9?RXg{yyFY-_gB>a+Y3{zD2LqAISX}V@`m4{Ab##wX%ov2^}L)e>lL;eabYPWv^UfJ1Yh`5e15MndL!0#PhWR;cT-z#c5Yo5cUWZP z7Ou4pPzP^{L2CPM$`-L)N!fINDDNP!F@aq4Xfomg*dU1I6y{V~YOd(5h1-P@Tt=pb zQzeGR_e_}y9r6f;N=h3FWr&Eo+Ykq4z*kh%yyk)+$CxJAg-rB=q#lO>Qu_O!VoivT z*F423*ZOPj3FRoCf(`BXDdrPJ?V*h{?Snsl{Qi1Wud|49n@J3eo!HzOJzYdH!9!uz zGwWs|7A2Q#dvj4mS65+9jC>9s|(l_+lOnA{y!68o;k(+z#$jrQ2=-d2hgCy z%evZH=F7yZ064#8YclEqSHX;ZO9Yk|=eo zT?BoqSe5c8(zyIljepV6KE;0Xh#e3483YB_Ay>AQ1ww`CBWz{+!(yK}mP;S|N}OV7 zq9>LGw|n}um}Wy`Bd?Lmbtx#6c4osSA+-1V%Qi6D$6mF3@!|#WALGZGj0ss;9L9yQu@y~; z<#umswfFb|#-hmk-`xSK1+9sm+e8`lEjPgC?CeP$Dl5>~-~yFQu1ibvLqY(;(;G@5 z9al4;-(R4*5Nmg-Qnc_xk)wly53PVInT6!FYZ%D#G58igd`CAvI(ivn|MdObvy$nQ?IOz$66*)IyySea%@)+G9Gb74beQngwQk@8Q0(wQsyAs z4l783;pex$DJhdNXy%)zg&((TA*kjT*t(f`2p6fNBVY!JElD{U*zbBR zU`!MH*#x@*v&#{4@PRP0VSLg$U-%&}oZcjgzg0YUu<4&|tvXQaA)w9P&nP`7DFzD! zVv88@yLkwm?8?-&r$#z0@2~D~Joz19f#-gET@&@7DFhT$$oh7UVxC(cAHpq8z=7RR z0@u(brQGjsVbHNUB@1+v9QLy@da#helLEy9OknE8IXQP~UkSRi>bu#&`!cq@-kRZTq{kYTXaF??9+B(f)?Q1$lugn|(V4E4!`L;GTE;Sq#E&f`N<8ukD8eVb%&Z<@%=h)!UyQ|1&#_j+m&J z1S2$nXU^X0*Zb~MBS+E7)_-G=;4Ezr*;?lm7S?rB@4Zw)%KmOl{xwz1mz|U08WgBO zeaFAVH;mmc7TM33kB$dU^_T1EMxdPfvI`nZU*8L{u~_g`YD!AV)$d&B;tIOxW__7= zB?G_ad|^Zmu6F1RaI0da>{<+c38{fi%Ua&ZjLeh3d@WXY?)-wSZYa1tLywI$2R;W_ z^!S;KJJQ2TSbFnsGXo613MT48HhCe7N&iX|RWh>5`GC$b$uw11tWdi_*-uVR=H%pH zec`!>kPrc-75)J9hxO^=nLbz$kPdz{ywimL$2MR;MZ(v1v+eSPo!eMa%+=M^9V2^m z6tSK*C&h9uqD8(aIYC8bP@#SWp!#+29`A8N`a(3wT)$2sdgkm|S{MQ26ycyaSP; zGaoFtG8nMB@7R3?jPiQf1~+A8{V34!K*UTSpIh92G?5Y7KY&v0zx?mGG!(3BbW^|K zbpUEl%e0zGl1i}#1$E&F*_iYMJVQ!~iZ*o->Q|+tp1F7w7Z!#NnUo2dCQ+Qabm>Fo zEW8`>7CF)|3z9OQ<6qO{6p2P16LDL|yc_F<;{*6V#Mue?8v<%p*lsXS&72F4NWG%H z>QRg@=|$3oQqm9X*|Wz=;%!1g!v4E=0cbJK?ItHbDmqEZod8BsWeP;%BRfTRqlXcr zlKp;?;ViszN2sW%k6hr5dHC=lL6H<)yx`$5k(R%6-!TgKxGHb9=FN$*Dti?rE}kfA z^0K@tZ#ElC-t_6vo+JSwu$;5`+&*H{kf9HpW zn(JlSR)qpL6jA{PN{*MHxGzo!Ffd-l;HlgYJvTp}%JIFyq@=VI4Cl?2+fcF)Xuc^- z?CgIq00+?9jkg+usc54FNskc)ZIzl?Ev1dL$FI$}ucT1$zA^lLgbFsml!cO4E0sdb zcUFEko-I-yp6ayIpA}3J-F-nK4mGpegyrr#Ak*qv>9`hezWce7^_1@Qyn#Z$KkfiM z*kYxq=x;|IcL34aM(0;7tvdRR%${lVcdvc_w_2R9cn|37_j#3`wet1%^C0`6F32%d zfOL&D1mCYVz?Duc|A7NRK{!qTecxn}YJ3J((m=xm026{z8+sO0|CxVeS8e8e=9zKj zqixAzN81$69|73I3wMPeL>*(l!8z1KoP#1uf#y}5a_t)mfI6)>7p0rR7 zec&q0-P-VKgCtuAgF4+;x&~b`&y9E6WD|`=$sZ^h9Z^RAo&}{jC6?nCD&(9eI5`EI zlrTg`Og>}TcW&Q~vP-SaV=pPH#u*WO=IoE0EWl7FCnr*@R2C>*Oz}n_t6RRH3ul2l zz{v-$M1Lsz1Xxx35-2?c>LK~Gzz1*{KrXL?;*>>u72*gslG?gJVlNfTWw_dNKq89B zz2!ek&5?$PhkinWV6Jr>)+*4v}Loq3$N9$;6GI`*L!4>4s;L1(R zRw;7(2@&td6Y|(0P~-QYZgM|W@T8#j9VR>)1HQaIW)75sf`Xfnb|9R|Ja_c+^c0$_ z<0Pot<7`TrKi6;Z1qlb8A^LA))Qg%Bfy1kpYAx@0n(}d)f38SoT2dD>4tsX_Gy&Q! z?d7;O5d!Cfhlj`YTFm4G9lvgAZ7WWy15O5IUeiGjPX;EcuB`9d4-dcbI6h-#b$2! z=9EK;`Hr3YLN48YoRg}W0>k7O*yl0bI2>aj0$F4)G~7E-bZp)bMY|+b=zy6%$+8#= zDlYjA4HDYKn0Z1oM8agDgkc=c@JW%JR%f_|lSzUKae3&)wF)ipybu;rNlz>tPV!){ zo=!g~_@F9BknT7U)2?t*Laj%PaxrZdH`|`I@oY>KiPlfAAz4! z4(M##mde(UYPw;LMSn;FMM*m_K3-(n#lfcyX`dV59WKaGb;7I#G}&G5UOxW;zT~3Q zCldX@3gg60P9!o>8U&$f8=V>GN38W!Q`D1r`Iu%GP|hew1vun2O$n0?0T#XmFy2qF zz;w1|;l8HjtMv|~%K8JyaqwzqWDNpKAS+em<=@}k)<;HIQ}`D6SXrl{yy*Pr^q60~ zeCa;;S~50M!jl49G`rtrf5DQapG0j{!y9dz$pB%JzV){8CCFVh!35bE3oHnx`# zVsU~%HA9!RG`86&{zm8_I=YJ)0%*8678#2~fc}2`_;KP$7nnuVRW54ZfPn9-3lq5m z6$V|ssEi=L0_~O1yKu(hwvCzC(|xZ8_M@@@t>E|~WevP3LhHZ3kY@Pd69GQN(wX6G zhi01J%a>Bzgl!#EKlw-z%vJd7iW22E%DP@j?( zL;7%kFo;2y)5Zs42*Z2|mk0td8^{cCP2DOu0IC(^khqoCUIuL)9Z8>K?9eTsh=KRh zrZz1B#rOXGNm!AP<=9j~SSblpWo@l(e!b|(u7QTO)eQa7%zHKVUS`GB?}NgYnsR4n z_(MMX2)x)xf6^t8u&B2C*v+cu>I-`juOD{&eQo0273JNTAQXvXMTv>mw^aD;CUL4l zgs?unnWC;TC*%aAmdscl1dDaFLY5rL7-O!tgz5nonZMxsu_H1}Ee6w%3_{V<&2{&Wk~VeW%GXHs{GN_5|G zjzLg~IF*y~$5$(wk@-y*2t(qZGRBd>8l07(pwmAPP5MgD355(~` zo*Z^~f%~xaa41jA%w!bbgNdJD95?tF^%J&d;s3#$+N$IJ51$v5W_V!BSjzpJRndh&UZRS57j{U z8~hdkf9HF5F6CoZImd3|6lC<4Lm`PcK8i;poCNmlVRaqId zIt`c6kCBn1CrQXcTJ&6;8 zkd$#Y7tj%AJQ$X`p`#?9km42;bOFJHas@9Fn64J*$>x|U0%5@Is=dRc9OwX)$QIx- zzyLmg+P4xQ8)XlbEL_krDR+Asb%N}k|sw+IzVxNb)JEG z*sA;WB+ilYpwPllhShom!WEwkd+Ha+5gi@8Cr`d7TwrU9v^=IESD*ZOD-Jg=&bvafM>wG3uU?(eZUq620wjzSe(mZPwXSTjBVTtlaZ*swVCoo zfoEICj$C|k&gQL7__Rsq_6bApx3u)9u)kM!Ax*By$~FM_XWs9)IK_wq-&Ab6f`H_t z2T>;y58d_KeuY*=EqZUXpL;n4#Xs|s|9&yd2aA27d#?b$xh%A)ff(qJEyE<@2snmg zX~gNAFM0oI#JEVv<9!O-ws2f|45YQ7^{~%kfOOn!5^Rk?rStEY4t=2JxVHVh-><*T zY3Dg_QMtS!LQmkz)AJ9vhz4Lg(N6fVU?~oYR8CSRoGtKdg2=k}f4j)BN4Urpov*#C z#GCPYNd21O|Mf4ek%?+HGVT3W#`(`xKJ3P=|L3px@Bcr(=R-c5d^3CY$yREP?Z3wv zw>|vyCXWEa+a7981utkF_E#Jhg^#{E}0$wuGB-jXt**0;5HRs*xdf#@V?2eg}tyb-Pzb}`t#ujbf zxGue-zoE)daoC#PZ7)UJCVmY|O9W z;45_0%UD&}{in6$_@nKcZ7OGv&dn`sb`MyyG;3D3n%EB3YrW>Z~o%zZ|EcU$i7+J+L7 zpSrTwr8V*$CBJOj;v>JQ$}}-U&KYukwS6jljhsz$Id=LEtgW-Ti4zLEoE+IQwbG@6 zLZX_vqu*n+!q*t=|IBh5|E$SPd@VMUUvaLdS9^h_aHc8qH}k=mrw7K{O0&;u68ihL zZ8xfH^Z6$~58VeXee`n%X*}6HR66i=X!z?;*D=k(ismo;Irq&13|i@@NFMKm?P1+M zOw*AcY!RqGeeR6Z-j0}PuO2DBxQ9Rb~vL(SP?Di-3w8T7zd zJtgbT#$$|)+SjFSc4y9zZ|yAOS3GpPXwmHP77axyZAZRZK2vQ4<2jkV2YK&2?ddNs zN*=t!z`Dm{rgW|OhWQfvH-vh6Yn7AV^^{b^zPbOJmpLPA?c>3T z{A}3(IcX*pM_sqg@ZvoQUp{ANS+`sCF0__}UcA__s-__!2u$1cjT08P3Bj`;~yLtgwkmpZV*H#YDb>{15 zpOlQdYb8A%nb2_dOq^-|T-9B2InH_ELt);9wE1RBS78=-cK0bBdO^$HqO-_wab9Zw zj`~Grt|8sG6sMZXA4Lq|OEb>-9N!#Zqp_P7xHqasd|v}#?18_cZ96}FTG~(J5}B5l zE`Q#oq!fQhPjg5Gu8nEk_HtgHa?}E!Ri~23-*TCZP7Q^I1=B}{Xe%me4h`ikZ^gL{ z4-Vt5xbBk*YLa8`ka7xrt#znP}T;0!UT=yHvo3`RwTOGAz zKXJk&X#d%M8A{Q=|KVqD&+)`lA zwD+Lc`E~FXznWU`ryXl#4AB<7dA3>)O#CTbT+}yF?E2F-H(Co{ z2>0n))4lB}GxMHTG+N^!mkS&GHJ&x{qnW$h;+Y)Rm&WGAQE)icV#L6*S&GB0g*pW; zx$SoU`KG#s5q}_WN~Oof%#fpuQbzSZW#Cp z$VOh0RLoPraZZq>3)7He<#Fkuc9hnz9A(whGgya zepX-0_R6dOjb2*G9ZRWio-!TS;D(w8mB8RN2gkfU#$6fq}vs`raFRlC; ze5HV=Xw=4dZ^gZTvne{NAUH@@UD;;MTy#Q}l}XuZ$^Edmw3^6Gm-|I86;Jm$qqrCD z4UV}xGdMWNcbWfhuHO@#QD%+l;juYt*`}ouMetk0u|sv_$hk8Kt(VpAdp7@*ORsA5 zv}@_LbX*Z_@JSVQd01JM2V-r>_8B$B-F2qDOHM@@{Eoc*&|#Y3@VWkg8{O?`s|#Q< zhT~(F_K^zXU(H4;4-HX9@Q%h7jd$!%GCq!}`lZn1%!t;|(?bC>NLm^B0Ew4%Z<+Ru z-Pl+vXyZ?lt_*+WyL_N!+T}$=<;|_}X7~OvyD<|Fis)I>`1X}?u8vHTsMB30yCS0Y zb2>2xUD|5)T3|atbCk`)h*tX#<0F;=@oWM6!-xD8i|oe|VXuArPowaS~B`5Vp^KiKcA^O8K_Jb9nrx_bA^Yhz{H`%Qx zM(s3Pa#>bk@UV=Tv72f6GuX9P?X>y6!g6;{dgFhK$;Ui=eNL)me#5t2e!Ce?MMu*g z>&&R(K++r)ou5>-e0(KWv($BlUV+!*TVs!mOnGn+oh|3^Pvd}Onv$Fwahmy#30z^X zg?}9m$e--dQ=i{jd3#)=>-f>E3~@~RwvQtMj}6*smrz6(jWPKusjB8#uJsixUt0uYLdo`08C{Lay!SH$ns`6E4?U%BtO<$V>Z$Pkww z)s_s`9@Gw>_Ug%KWD?!&DcXE7wryxaLHz62XHpmHH~B-txHygEzgLzC_c1o=Qixu= zCa!kCTly=G@-W9f3z==-$1iPLvQ)5KkygBTlrngIDO38)xqg`&Wk(NE3R&0uZS5+N z8gH9IrIs#9D`<6R+GiKq@QsY7Lu;dxp0(}~{0SR3937=x?pV3pnMMB%sPawKZo^-? z?dX@cde4O4!;Mop&iyn#oO1u6r9j7J$CZCXy~hvD%nRNsvN3fZ?YzKnZ9Yu^HBU|B z+~hBPhHH^@I&oeSHu2`|lU%g>_!+`xX_b481!oQFzI;DdRHVG`a_EGIX^#N6_$*Aq z?|Qbmmyb`Ua`lM-s zO%JOM&^oBhF3y^wFwT~?dc+?xu=*Ap z92g#N$#nh7d;x1^f0~~tQ@zC=t1GKVD1)!{ft#8y9CS9u7b1l6TiOI_2|8~on!9ZR z?mgDZOSHV6^QJYYKYtSPV*Qi1^E2O1CraHlWYo8lozATeGi1{yWm%V7&S-i){u~{{ z*g(dBv^A(SAwR+Q`i(!oP18e^tAhWFz4wf2vg_JKv4SW~1eE%KN-ru+M2b`a={*n- zkq)7QbX1TI(xulx=)E@;q<08Cp!6Q;o$M8O-gCaazhC=|{p0-D84QI$lKWn3t~sxH z%~n?f?%~X3Ti0PdNp*>{(t>mboE+s$yo0?cB?!`)3I7m5${F2Rl2cUtO^=L~~7DhRDu7PPr z4pnSbC96(5ReE%G=E@7ZhhXIjt4sKBc(~Fs?^Z`d8~5VJofHxaN}g0jplai^$MZb3 zMeN$o(l#d5G*uMfgW=T1X&&>LYLx_L$V$gNpb9{%4_G10<>)B3NIL1(?XYT+p+foB zrgb9|dyn9mu(8T)P;}~|6nWm@cAeL1eSJPEDbk*Iwsrh=EdR!s&caB@bWLjw2@RW% z=|H|&bkVBIcLzc%=lR126%ZO4w`?!bh=9=T8ihsW;+ z6HnGKEzdH#^DXIpio%>7ZvYhNLkt`$BpJdsUZreje_Qu(UiYEK?%oz{e|DRA=@AeGPQV>uI{<<9o54S3kwThUCt8yOBbJJ}@`TR)lWn~k_jI-2_i zw9T6?DJm{*??F1YexAG2vxN^Ee^dLKg7hTTOk$2S(wF$kxu?qA=%{fehz7aGTCaZ4 zne$cUjaRzzUKXyj@E6l{pi-~o;H#|qG~Dn+Ta}6Dwt2c5D-^0bQAObLe(@fWa~0Kq z@nNu5TvhB+q95bQ@dt`~ir4S^v-G^{uF8|^Uq__NELuI*eI%PR&pT)o2Z7em*rWnl5!G&@bL>Nwr6?a zCJA_%4UUmKq(#i~(0Z&niKztcS9aTp@ogr>bFw^E$0HeTNqoqLCq7}_YN*by8u~tn z7OO2gfwn9xMrh%s8RlPg=I7sPk|AC#u&3ahskP_-KBIV0{iBxGYETJJ`L=Yyg|$pg z&I42@*<$0MYFJ^?Pfk4&U|)W{rdTY8*50L$&Z&O~j$AbEZ}X9I+p1ogpG6Y7Kq0Cj zm5i;#AiQ^WN3#tEN}LC|ODPYJLTNRA`9$@6iodfyxihBk*UqiBKx;uh{C;rk&mxwJ zb#+|R{nP6TOkB1}?1tN>nLg=gme+yQbUkpWH`eBaY`blw+gKSG#Bc5g)g^p$=h_4Q zePcsyT&aeU8zHT{jJ&;r!#6&&;85L=RUqV*FeJnFVgWF@>xsHGUk-iVr#ZSb7@k!6 zVO|ytm=@0Xk0`u}3Jhp6W{f)@*?oz%lZa&27j~!J@H~=$jsxIcPXmoaLUf16VN}P8uA|m*^S2CNp-MwF(gjPD5NA5<0 z%;62S&V}2n#l-2Vrh+?q1ynq#eP?HG2_<6M+5Jw@DN*SjH7@F5OJLup>m7CQfGB7( z86oMe0IA4xTY{bt&4dQU7G+XZY1}aB_0tavBo_l7xA%ZyPK5>OU6-90VunR0T{LFl zyG)LsUHSK+<_4pkQ~)yHp{GD^MO()+^pu-3DQM#Y2(F1M0z)(L!qPdL2c8d)D~Z!J z4}gwU*DWNt1)~p5dXvw}qyzl(uR&!y-~N1dbJ}oN?o)N%WRw60W(hXCZ19=&`j|sm zukhgF+T3Fw#McKdz!DOto9r>g^`>pG;!4Pm*YM_2PXgcd-~cUTDw?vYG0?;|;ZyEl zZ_mNX+UT<8fnlp4WT>Nr_dz4(0zsh3>fp@>UTw0?r$NOwHukAU= z;S|H;5?Ykt@n6~CpVdP4L_Hi&$3pC~DaHH@fB~x=Dgb{+G&MTvkK68p|5kiY=%3s^ zcpNL&&As)Bm0pz3r%ylYZpi@q-qELD3p%AOj~CcStMi)QS6bNlcz!PCKQ(pAs*l9f z2J>9k&s*%tW&3TlU7?xNhL0Zv%+X7y?e(o81CS9a{riV0(A3eOtA!1PSX7LLP;$aK zDj_j~)dvrjX0csqET4c!ufqLIURO@XQn#LG#vCIoRO_^wnn8=2xL)Pp;J^+-wE<_= zq9CPkT@O-A%z#+I5PcuZ5uXH`-Pwgy9;nLvF(WJ2wF%Fca0m&i@&`G^r%9J4 zGrb>b`b>Efvd^RU@L{8C@I!((5F_T^dtWMN*xPbpS=1fmLVxdAeOvH+mqgSA0VPVp zr-72!(q-YLpiK!}ML^wtSf(beSD|7-@tQ^JJJP$6SlFWinaDO7U4?b^rwscU?YaFm zxY%j)vu~@R zduOH{R~D)2u2L$MVQcS*r1dWGnEZO?hf&MvERvR#yE5RD`5v_UKY#HNp*;-=kv0oK zL(Q9sEJnaPRc8)Y7mU&ZV^nEAu->1-#HH8hIe)ma_)314dVARJ1OcR{C2j}!KICMh zFOlzFy-FkgnSH$FnfJ2eTdBRpdx@xt)N5H5*@P<9v%M$@Gg)PN2>`NzMfs}1aY}V) zPQi!Zb}Tc^ejwXNTDmgxDn>YDwB5gmcFvSX49_47J&(!uI_de4ziQkWZaHwRum6ko zCX+_dW)fgTM(W}P!g_v<%V=w8fUeXKsHj@J)#zSPw)B}bb$-uyN-ea8wgRx$+jfq? z=aqW-q<;?);bdk0op8Nd2FEhCMZb7qc4=20v(CKiFvl0 zt`#Ty*vBS!vC#c&>8VOir>_wwN+ZYKv<^@#FaZAr9oBPPxaH%lJJMO5iy%;-FAxU& zEI!2eTNtBY9XXx1-d^tSR8(Zm!PihL!JdUDa-!;1jpGT-rRLa4*ZqW#e(RPDa0#-! zZWYu#7p%HvM&`Jq0X#-M&yTU$emwbwVriyFqjyAxW*{MMO|1uo19KAwjz(`@?z8H* zRxB?-;e)oj#Xo>o0!V5s8=Ar+l~Tc89u_Dk>#5zuA@mSHNcw7{9RU4-Z3ZNaFt)@$ zxl8k0E6rWTEQeUk?6*v7RFcK5n>0^Cu3n?Od7PbPB+)h`vJ}S!l4fve=^ko5gZepqpO=6dPOJ7B}^TaZ}W)C8EYWBXr{%{XzN)kmE*r# z`>f3D;H-m0OGK%t0<4fY{bNxP92>`Pd3XDE&_102EuiO!)4kBN;<#}pT&K>pBalc7 zY!U+w&ZE-;Sp6pS1@I0_sxu$$_o6BbbZ*iAERq5k#Q{wXL9tSXWOZtpDZrA6e>V5@ zv@n82BqNIj*`?~v6>_y_Gr?c(ta}N2scrm9z8w?5X%Qw~9+ zkiTjG><7I@BUFB@PkVT{>4gP`D!v&ktM}a>=-{Rp#s6gWNwX_8OG50M}*rCm<)&BFEZ}U5Mxxok~z)0_$;50%-MRjN}fw$mL z^_3kLuQ(n_s(rm}oiYUC1Oi>$OU*%na*0u$wi#cXEN5DEqn9Y|;oG0)Vq4^ZmJsT4 zs>iF>xfH`H=?i>_N%+%!iJeI!o;@p@s4^>e2rr8 z>F+h-fpJ)Y@CA3a0#?3QSx!*@eb?$pcaGwdb4`y#o zG>^9F;DxIrHPgr%U-Y;E<>mWuy!t|UVVGiEWSSnlo69|GZ)ru5iTRZ0I_XV==;vVl zj_X8!;hA4p;&W9s-9f-WNSi2f8-l)G^ztovhL$cDEB%)Ax`g~-nGVwhDFlLUe>4kk zW5IuBhWmWTH`bIUcMe&+0mkapIO#nm`FWSE&b?K9z+JwZWn`^u^0KA}ah$D{;vh1; z?Y(_+u}6;{YwG3I7C!L>l&#Tja-B_0ef@;mHvkiF(E~m8)V2WsrO=d#eA4g5#rT9+ z%t;LN7vr1hkwSR@LsN^Hx24{=)J**NktPFr0EUJV(o9s6i)ChJNlLZ>;@X!OVBI{W zZg%SesoEL0yv0{y{&^()A%#t_@T($v$oG^v$W{D4EmJy~aI=|QyY)h8NlnjE5Kp3S z@$DMT%`5JVd;^`S*@VFcljsJjHo>Weh6Ms9b7iUo>ih1CQ&wfCTRo>!JTM;N{2XqS zRX&|33UncqKwu(NRoI%||10qN6+go*r#_mPHd}6!b_D|%1iIQ+!P;bwM#$bT&9_bm zINRIvo<#kv81flthVWRtIQ@7+>+!)nwI=c%yw7p&%az3f@{2wA=I@P=fmE1|fQarJ zcr7iN$3sTGC*Pa2l}Kq86qD<|#wb6f_|tv#H)@!Ni0FXOO1{B#vcevLZS2VZ$Ndo5 zS(FS|ml_%quqPlW6&_`KpWG8JW~W$|+A8J`TuRMqF;^~*vnk0Peg5GlHxT_rudIZJ zM>kkt!dZ(pK->kKgS)>$RyEWDxc2!UQ_#Vf^aW zC+p20o758;5WFUUI&Exi2|?&W?16nl1?9>IG*r;h#=)W5fp>N!sV>Vhz3{p7Rs?an zV_sm@tLmCsJo;y)rED*)0fV%-$m-)Cq?rHL9Z;EZJF%>>=;?|KhX?`ZKXwb6ikkKj zC7+WfD-3bzCDxPbfaeM@TAlNX*3q1?smZx>f%*Oi=sFL8W(vs_>t<8+xs%SvrX<5a zzC)b!KK^@DJdya)rM4G3 zPM)kh6@TIjgQ(A+#l=)QN1(XDa!;@v>lCvRXnPL(gfOqymDx$nn$}C6^)ghbw4_z5 zaWQrWdTq18&DHe|ZNDa{nVhOz`W`;lai9W{(A8Mg0m%in5QKj`s*asW`K>(iJW)2M z4r2v^&LB7p;yl1Mf>;pBC)3J}P_Nz{g+v;OrqGgUm<=M*h-ZI?lL9XvI3k|YVkZcX zgtzo9n`eF?-qa4lsa%?XOvSjYPSy4Z>QtF4*SKHPPdWE+#iJ)Yb1`3P6bH;HYjkdT zKD+Q!vz=ZKX~o2q$vmBfiuJckAlkG7v`j=iEsa|nP$|HnjPANW5f`!gAJK7Vcca}w8<;pp5HxHIO%0NK2)!gXq;nDG%`$Cq#4lKGS z?|iPU0%C`M<{mj&N`uYH zPq+mIr@A0>9vQpm)`PO)$oQD>_!#8{IRF_|nS%H8dEUcj^ic2SX6I%}o6cOIzO7pC z=m;8%taaU0q>M+VMM7`czVU1XnGvK?L^}I>xt)10ZS-emXJ!B&h+oO#w5n zR2hRIb+&bqigU)9hBL_afq|#x9tm=q4+|wE_RwdsR1fq2BF**<)erJC4uPwV#i0qO zEzcfWbM@trwpotXa6LVmM(a44Hw|Yh|K9B|jFy#tn9DoLpXE_~mjpgwDmGbV>%f!6 zeHmz7ASULG&dZYn4jhPQITBhetZZlB?fp&MG<$NV2H({F`3H%#iHy`fw zaDzhXCtxoCW#gyckR0V+gs5&op$cr9y*HD@Co2j0Mm4Zz7!9ymh?G4b@d1n4-bb`N z$^GOz<`mA>aWDvuC^*dkQi5=XIHgWs{hf_z4UTxBot8vkl_lGzJGwhLSvc$+9kC(T zMtPg6-ZUh%;~9_yaFLoyS|1MkhJf^exCQ~$%kTYFQ;qU}OCn9+3#-p00JBtaHT?(j zx`eMba3^xz(9JiAOh*|HXBRBC0y=K^`ikLcQc#HKr+^TJV5PNT>rJgT!?Nrd{{VT} z#@M)MkaffC^ApumVUX%oH}WG%Y*JmI#TEqFRGC7BUG~LXrLuUI^7zWo4?&Jno3Wyx z+xZ}Ht@0D8aeY6hq$n;CZn!$4XP341h_8YQNx*;si0A>dam)O@l}AIF%5TFslOVWN z%p7c_V%4?JHT6mg(NiF-_gdU&e`UO)^D2mZAe z4n4oPB*>BkJW>z|Ep&_RcYUT+C>b4_*XO4X*e4G+ji*|d`A)?gzG|4!mKJFi zaImww9*1iKGNuwnh%*L`!M=0e=n?2u&IxvoxHN|8YnC}Zxq%uH1O=O6RCEJDMhZFSIu+NaL``7LtC=lw?q#wr;+rf%9YWz3ReAp-JQUgdOnu&

MU|1t(Nh^ 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 int: + return max(low, min(value, high)) + + +@dataclass +class RegionResult: + region: str + avg_consumed_tpm: float + current_capacity: int + utilization: float + decision: str # "up" | "down" | "hold" + target_capacity: int + reason: str + cooldown_blocked: bool + executed: bool + contention: bool = False + error: str = "" + + +# --------------------------------------------------------------------------- +# 메트릭 조회 +# --------------------------------------------------------------------------- + +def get_recent_windows(table_svc: TableServiceClient, region: str, limit: int) -> list[dict]: + """리전 파티션의 최근(RowKey 내림차순) limit 개 윈도우를 반환.""" + tc = table_svc.get_table_client(TRAFFIC_TABLE) + entities = tc.query_entities( + query_filter="PartitionKey eq @pk", + parameters={"pk": region}, + ) + rows = list(entities) + # RowKey 는 ISO8601 타임스탬프 문자열이므로 문자열 정렬 = 시간 정렬 + rows.sort(key=lambda e: e["RowKey"], reverse=True) + return rows[:limit] + + +def avg_consumed_tpm(rows: list[dict]) -> float: + """윈도우별 (inputTokens+outputTokens)/window_minutes 의 평균(분당 소비 TPM).""" + if not rows: + return 0.0 + total = 0.0 + for r in rows: + tokens = float(r.get("inputTokens", 0)) + float(r.get("outputTokens", 0)) + total += tokens / METRIC_WINDOW_MINUTES + return round(total / len(rows), 2) + + +# --------------------------------------------------------------------------- +# 배포 capacity 조회/갱신 (실제 actuation) +# --------------------------------------------------------------------------- + +def get_deployment_capacity(mgmt: CognitiveServicesManagementClient, account: str, deployment: str) -> int: + dep = mgmt.deployments.get(RESOURCE_GROUP, account, deployment) + return int(dep.sku.capacity) + + +def set_deployment_capacity( + mgmt: CognitiveServicesManagementClient, account: str, deployment: str, capacity: int +) -> None: + """배포 SKU capacity 를 실제로 갱신한다(비동기 → 완료 대기).""" + dep = mgmt.deployments.get(RESOURCE_GROUP, account, deployment) + dep.sku.capacity = capacity + poller = mgmt.deployments.begin_create_or_update( + RESOURCE_GROUP, account, deployment, dep + ) + poller.result() + + +# --------------------------------------------------------------------------- +# 쿨다운 체크 +# --------------------------------------------------------------------------- + +def is_in_cooldown(table_svc: TableServiceClient, region: str, now: datetime) -> bool: + """해당 리전의 마지막 '실제 변경' ScaleAction 이 쿨다운 이내면 True.""" + tc = table_svc.get_table_client(ACTION_TABLE) + actions = list( + tc.query_entities( + query_filter="region eq @r", + parameters={"r": region}, + ) + ) + # 실제 capacity 가 바뀐(=changed=True) 액션만 대상으로 최신 것을 찾는다 + changed = [a for a in actions if str(a.get("changed", "")).lower() == "true"] + if not changed: + return False + changed.sort(key=lambda a: a.metadata["timestamp"], reverse=True) + last_ts: datetime = changed[0].metadata["timestamp"] + if last_ts.tzinfo is None: + last_ts = last_ts.replace(tzinfo=timezone.utc) + elapsed_min = (now - last_ts).total_seconds() / 60.0 + return elapsed_min < COOLDOWN_MINUTES + + +# --------------------------------------------------------------------------- +# 공유 상한(Reserved quota) 재분배 로직 +# --------------------------------------------------------------------------- + +@dataclass +class RegionState: + region: str + account: str + deployment: str + current: int + consumed: float + utilization: float + + +def need_capacity(consumed_tpm: float) -> int: + """AIM_UTIL 에서 돌릴 수 있는 capacity 를 역산(리전 최소/최대로 clamp).""" + if consumed_tpm <= 0: + return MIN_CAPACITY + raw = math.ceil(consumed_tpm / (AIM_UTIL * TPM_PER_CAPACITY_UNIT)) + return clamp(raw, MIN_CAPACITY, MAX_CAPACITY) + + +def compute_targets(states: list[RegionState]) -> tuple[dict[str, int], dict[str, int], bool]: + """ + Reserved 총량 제약(sum <= TOTAL_CAPACITY_UNITS) 하에서 리전별 목표 capacity 를 산출. + + 반환: (targets, needs, contention) + - needs: 각 리전이 AIM_UTIL 로 돌기 위해 필요한 capacity + - contention: 총 필요량이 Reserved 총량을 초과(True) → 소비 TPM 비율로 비례 배분 + """ + n = len(states) + needs = {s.region: need_capacity(s.consumed) for s in states} + total_need = sum(needs.values()) + + if total_need <= TOTAL_CAPACITY_UNITS: + # 여유 있음: 필요량만 배정하고 남는 건 미할당 버퍼로 둔다(증설은 무손실). + return dict(needs), needs, False + + # 경합: MIN 을 먼저 보장하고 남은 용량을 소비 TPM 비율로 배분한다. + rem = TOTAL_CAPACITY_UNITS - n * MIN_CAPACITY + total_consumed = sum(max(s.consumed, 0.0) for s in states) or 1.0 + targets: dict[str, int] = {} + for s in states: + extra = int(rem * max(s.consumed, 0.0) / total_consumed) + targets[s.region] = clamp(MIN_CAPACITY + extra, MIN_CAPACITY, MAX_CAPACITY) + # 내림으로 남은 잔여 unit 을 소비가 큰 리전부터 채운다(합이 TOTAL 을 넘지 않게). + leftover = TOTAL_CAPACITY_UNITS - sum(targets.values()) + for s in sorted(states, key=lambda x: x.consumed, reverse=True): + while leftover > 0 and targets[s.region] < MAX_CAPACITY: + targets[s.region] += 1 + leftover -= 1 + return targets, needs, True + + +def plan_region(state: RegionState, target: int, contention: bool) -> tuple[str, int, str]: + """ + 목표치를 dead-band/스텝 제한으로 완충해 이번 사이클의 planned capacity 를 만든다. + 반환: (decision, planned, reason) + """ + within_band = TARGET_UTIL_LOW <= state.utilization <= TARGET_UTIL_HIGH + if within_band and not contention: + # 편안한 구간이고 경합도 없음 → 불필요한 왕복(churn) 방지 위해 유지 + return "hold", state.current, f"util {state.utilization:.2%} in dead-band" + + delta = clamp(target - state.current, -MAX_STEP_UNITS, MAX_STEP_UNITS) + planned = state.current + delta + tag = f"util {state.utilization:.2%} -> target {target} (contention={contention})" + if planned > state.current: + return "up", planned, tag + if planned < state.current: + return "down", planned, tag + return "hold", state.current, f"util {state.utilization:.2%} bounded, no change" + + +# --------------------------------------------------------------------------- +# 이력 기록 +# --------------------------------------------------------------------------- + +def _date_pk(now: datetime) -> str: + return now.strftime("%Y%m%d") + + +def _row_key(now: datetime, region: str) -> str: + return f"{now.strftime('%Y%m%dT%H%M%S%f')}-{region}-{uuid.uuid4().hex[:8]}" + + +def write_decision(table_svc: TableServiceClient, now: datetime, res: RegionResult) -> None: + tc = table_svc.get_table_client(DECISION_TABLE) + tc.create_entity({ + "PartitionKey": _date_pk(now), + "RowKey": _row_key(now, res.region), + "region": res.region, + "utilization": res.utilization, + "avgConsumedTpm": res.avg_consumed_tpm, + "capacityBefore": res.current_capacity, + "capacityTarget": res.target_capacity, + "decision": res.decision, + "reason": res.reason, + "cooldownBlocked": res.cooldown_blocked, + "executed": res.executed, + }) + + +def write_action(table_svc: TableServiceClient, now: datetime, res: RegionResult, duration_ms: int) -> None: + tc = table_svc.get_table_client(ACTION_TABLE) + changed = res.executed and res.target_capacity != res.current_capacity + tc.create_entity({ + "PartitionKey": _date_pk(now), + "RowKey": _row_key(now, res.region), + "region": res.region, + "requestPayload": f"{res.region} capacity {res.current_capacity} to {res.target_capacity}", + "capacityBefore": res.current_capacity, + "capacityTarget": res.target_capacity, + "changed": changed, + "responseStatus": 200 if not res.error else 500, + "success": res.error == "", + "errorMessage": res.error, + "durationMs": duration_ms, + }) + + +# --------------------------------------------------------------------------- +# 메인 제어 사이클 +# --------------------------------------------------------------------------- + +def run_cycle(dry_run: bool) -> list[RegionResult]: + now = datetime.now(timezone.utc) + cred = DefaultAzureCredential() + + table_svc = TableServiceClient( + endpoint=f"https://{STORAGE_ACCOUNT}.table.core.windows.net", + credential=cred, + ) + mgmt = CognitiveServicesManagementClient(cred, SUBSCRIPTION_ID) + + # --- Phase 1: 상태 수집 (리전별 현재 capacity + 이동평균 사용률) -------------- + states: list[RegionState] = [] + for region, cfg in REGIONS.items(): + account, deployment = cfg["account"], cfg["deployment"] + current = get_deployment_capacity(mgmt, account, deployment) + rows = get_recent_windows(table_svc, region, SMOOTHING_WINDOWS) + consumed = avg_consumed_tpm(rows) + provisioned = current * TPM_PER_CAPACITY_UNIT + util = round(consumed / provisioned, 4) if provisioned > 0 else 0.0 + states.append(RegionState(region, account, deployment, current, consumed, util)) + + # --- Phase 2: 목표 산출(총량 제약) + dead-band/스텝/쿨다운 완충 --------------- + targets, _needs, contention = compute_targets(states) + + results: dict[str, RegionResult] = {} + planned_map: dict[str, int] = {} + for s in states: + decision, planned, reason = plan_region(s, targets[s.region], contention) + + cooldown_blocked = False + if decision != "hold" and is_in_cooldown(table_svc, s.region, now): + cooldown_blocked = True + planned = s.current + decision = "hold" + reason += " | blocked by cooldown" + + planned_map[s.region] = planned + results[s.region] = RegionResult( + region=s.region, + avg_consumed_tpm=s.consumed, + current_capacity=s.current, + utilization=s.utilization, + decision=decision, + target_capacity=planned, # 실제 적용 후 갱신될 수 있음 + reason=reason, + cooldown_blocked=cooldown_blocked, + executed=False, + contention=contention, + ) + + # --- Phase 3: 총량 제약 실행 (감축 먼저 → 증설은 남은 headroom 한도) ---------- + free = TOTAL_CAPACITY_UNITS - sum(s.current for s in states) + durations: dict[str, int] = {s.region: 0 for s in states} + + def _apply(st: RegionState, new_cap: int, res: RegionResult) -> int: + start = datetime.now(timezone.utc) + try: + if not dry_run: + set_deployment_capacity(mgmt, st.account, st.deployment, new_cap) + res.target_capacity = new_cap + res.executed = (not dry_run) and (new_cap != st.current) + except Exception as exc: # noqa: BLE001 - 기록 후 다음 리전 진행 + res.error = str(exc)[:500] + res.target_capacity = st.current + return int((datetime.now(timezone.utc) - start).total_seconds() * 1000) + + # 3-1) 감축(donor) 먼저 → headroom 확보 (loss 없이 여유 리전에서 회수) + for s in states: + res = results[s.region] + planned = planned_map[s.region] + if not res.cooldown_blocked and planned < s.current: + durations[s.region] = _apply(s, planned, res) + if not res.error: + free += s.current - res.target_capacity + + # 3-2) 증설(recipient): 사용률 높은 리전부터, 남은 headroom 한도로만 + for s in sorted(states, key=lambda x: x.utilization, reverse=True): + res = results[s.region] + planned = planned_map[s.region] + if res.cooldown_blocked or planned <= s.current: + continue + inc = min(planned - s.current, free) + if inc <= 0: + res.decision = "hold" + res.reason += " | no headroom (Reserved 총량 소진)" + continue + new_cap = s.current + inc + durations[s.region] = _apply(s, new_cap, res) + if not res.error: + free -= (res.target_capacity - s.current) + if res.target_capacity < planned: + res.reason += f" | headroom-limited to {res.target_capacity}" + + # --- Phase 4: 이력 기록 (판단/액션 모두 남겨 관측 가능하게) ------------------- + for s in states: + res = results[s.region] + write_decision(table_svc, now, res) + write_action(table_svc, now, res, durations[s.region]) + + return [results[s.region] for s in states] + + +def main(argv: list[str]) -> int: + parser = argparse.ArgumentParser(description="Adaptive TPM quota controller (Reserved 총량 공유 재분배)") + parser.add_argument("--dry-run", action="store_true", help="계산/기록만 하고 실제 capacity 는 바꾸지 않음") + args = parser.parse_args(argv) + + results = run_cycle(dry_run=args.dry_run) + + print(f"=== Adaptive TPM Quota Controller (dryRun={args.dry_run}) ===") + total_after = 0 + for r in results: + total_after += r.target_capacity + print( + f"[{r.region}] consumedTpm={r.avg_consumed_tpm} " + f"capacity={r.current_capacity}->{r.target_capacity} util={r.utilization:.2%} " + f"decision={r.decision} contention={r.contention} " + f"cooldown={r.cooldown_blocked} executed={r.executed} " + f"reason='{r.reason}'" + + (f" error='{r.error}'" if r.error else "") + ) + print(f"total capacity after={total_after}/{TOTAL_CAPACITY_UNITS} (Reserved cap)") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv[1:])) diff --git a/ptu_lb/runbooks/optional_adaptive_tpm_quota_controller.ps1 b/ptu_lb/runbooks/optional_adaptive_tpm_quota_controller.ps1 new file mode 100644 index 0000000..e11c3c2 --- /dev/null +++ b/ptu_lb/runbooks/optional_adaptive_tpm_quota_controller.ps1 @@ -0,0 +1,418 @@ +<# +.SYNOPSIS + Adaptive TPM Quota Controller (PowerShell / Azure Automation) — OPTIONAL 대체 구현 + +.DESCRIPTION + Python 런북(adaptive_tpm_quota_controller.py)과 **동일한 제어 로직**을 PowerShell(Az 모듈)로 + 이식한 "선택적(optional) 대체 구현"이다. 기본 구현은 Python 런북이며, 본 스크립트는 + PowerShell 선호 환경을 위한 동등 참조본이다. + + [Python 버전과의 동등성 — 핵심 설계 결정] + * 두 배포 capacity 의 합은 Reservation 한 총량(ReservedTotalTpm)을 어떤 시점에도 + 초과할 수 없다. 고정된 Reserved 총량을 트래픽 비율에 맞춰 재분배한다: + - 필요량 합 ≤ 총량 → 각자 need 만 배정(나머지는 미할당 버퍼) + - 필요량 합 > 총량 → 소비 TPM 비율로 비례 배분(경합) + * 감축 먼저, 증설 나중: 총량이 꽉 찬 상태에서 증설을 먼저 하면 실패하므로, + 잉여 리전을 먼저 감축해 headroom 을 확보한 뒤 증설한다(loss 최소화). + * 리전 최소 보장(MinCapacity)은 Reserved 총량의 25% 로 유지한다. + * capacity(배포 SKU capacity) 를 조정 knob 으로 직접 사용. 1 unit ≈ TpmPerCapacityUnit. + * 실제 actuation: Az.CognitiveServices 로 배포 SKU capacity 를 실제 갱신(폐루프). + * 쿨다운: ScaleAction 이력에서 리전별 마지막 실제 변경 시각을 확인해 재조정 차단. + +.NOTES + [인증 / 의존 모듈] + * 인증: 관리 ID -> Connect-AzAccount -Identity (로컬은 Connect-AzAccount 로 로그인) + * 필요 모듈: Az.Accounts, Az.CognitiveServices, AzTable + * 필요 RBAC: + - Storage: "Storage Table Data Contributor" (TrafficWindow 읽기 / 이력 쓰기) + - Foundry: "Cognitive Services Contributor" (배포 capacity 갱신) + + [네트워크 주의] + * Storage 가 publicNetworkAccess=Disabled + Private Endpoint 구성인 경우, 이 런북도 + 프라이빗 경로가 닿는 곳(예: Hybrid Runbook Worker)에서 실행되어야 테이블에 접근된다. + (Linux Hybrid Worker 에는 PowerShell 이 기본 설치되어 있지 않을 수 있으므로, + PowerShell 로 운영하려면 Windows Hybrid Worker 를 사용) + +.EXAMPLE + .\optional_adaptive_tpm_quota_controller.ps1 -DryRun # 계산/기록만 + +.EXAMPLE + .\optional_adaptive_tpm_quota_controller.ps1 # 실제 조정 +#> + +param( + # --- 대상 리소스 ------------------------------------------------------------- + [string]$SubscriptionId = "2cf925b6-80cb-4567-abda-5ccd3010aab5", + [string]$ResourceGroup = "ptu-lb", + [string]$StorageAccountName = "ptulb59018sa", + + [string]$TrafficTable = "TrafficWindow", + [string]$DecisionTable = "ControlDecision", + [string]$ActionTable = "ScaleAction", + + # --- 제어 파라미터 (Python 버전 상수와 동일) -------------------------------- + [int]$MetricWindowMinutes = 5, # TrafficWindow 1건이 대표하는 시간(분) + [int]$SmoothingWindows = 3, # 이동평균에 사용할 최근 윈도우 개수 + [int]$TpmPerCapacityUnit = 1000, # capacity 1 unit ≈ 1000 TPM (운영값으로 조정) + + [double]$TargetUtilHigh = 0.75, # 초과 시 증설 압력 + [double]$TargetUtilLow = 0.30, # 미만 시 감축(잉여 회수) + [double]$AimUtil = 0.60, # 조정 후 목표 사용률(중간값) + + [int]$MaxStepUnits = 5, # 1회 조정 최대 capacity 변경폭(단위) + [int]$ReservedTotalTpm = 20000, # Reservation 한 총 TPM 상한(합산 불변) + [double]$MinCapacityRatio = 0.25, # 리전별 최소 보장 = Reserved 총량의 25% + [int]$CooldownMinutes = 20, # 실제 조정 후 재조정 금지 시간(분) + + [switch]$DryRun +) + +$ErrorActionPreference = "Stop" + +# --- Reserved 총량 파생값 (합산 불변식의 기준) --------------------------------- +$TotalCapacityUnits = [int]($ReservedTotalTpm / $TpmPerCapacityUnit) # =20 +$MinCapacity = [int][math]::Max(1, [math]::Ceiling($TotalCapacityUnits * $MinCapacityRatio)) # =5 +$MaxCapacity = $TotalCapacityUnits - $MinCapacity # =15 (2리전 가정) + +# 리전 -> Foundry 계정/배포 매핑 (Reserved 총량을 두 리전이 공유) +$Regions = [ordered]@{ + korea = @{ Account = "ptufoundrykr001"; Deployment = "tpmtest-kr" } + uk = @{ Account = "ptufoundryuk001"; Deployment = "tpmtest-uk" } +} + +# --------------------------------------------------------------------------- +# 인증 + 테이블 컨텍스트 +# --------------------------------------------------------------------------- + +function Connect-Context { + # Azure Automation: 시스템 할당 관리 ID. 로컬: 이미 로그인된 컨텍스트가 있으면 재사용. + if (-not (Get-AzContext)) { + try { + Connect-AzAccount -Identity -Subscription $SubscriptionId | Out-Null + } + catch { + Connect-AzAccount -Subscription $SubscriptionId | Out-Null + } + } + Set-AzContext -Subscription $SubscriptionId | Out-Null +} + +function Get-CloudTable { + param([string]$TableName) + # 공유키 없이 Entra(RBAC) 자격으로 접근 + $ctx = New-AzStorageContext -StorageAccountName $StorageAccountName -UseConnectedAccount + return (Get-AzStorageTable -Name $TableName -Context $ctx).CloudTable +} + +function Clamp { + param([int]$Value, [int]$Min, [int]$Max) + return [math]::Min([math]::Max($Value, $Min), $Max) +} + +# --------------------------------------------------------------------------- +# 메트릭 조회 +# --------------------------------------------------------------------------- + +function Get-RecentWindows { + param([string]$Region, [int]$Limit) + + $table = Get-CloudTable -TableName $TrafficTable + $rows = Get-AzTableRow -Table $table -CustomFilter "PartitionKey eq '$Region'" + if (-not $rows) { return @() } + + # RowKey 는 ISO8601 타임스탬프 문자열이므로 문자열 정렬 = 시간 정렬 + return @($rows | Sort-Object -Property RowKey -Descending | Select-Object -First $Limit) +} + +function Get-AvgConsumedTpm { + param([array]$Rows) + # 윈도우별 (inputTokens+outputTokens)/window_minutes 의 평균(분당 소비 TPM) + if ($Rows.Count -eq 0) { return 0.0 } + + $total = 0.0 + foreach ($r in $Rows) { + $tokens = [double]($r.inputTokens) + [double]($r.outputTokens) + $total += $tokens / $MetricWindowMinutes + } + return [math]::Round($total / $Rows.Count, 2) +} + +# --------------------------------------------------------------------------- +# 배포 capacity 조회/갱신 (실제 actuation) +# --------------------------------------------------------------------------- + +function Get-DeploymentCapacity { + param([string]$Account, [string]$Deployment) + $dep = Get-AzCognitiveServicesAccountDeployment ` + -ResourceGroupName $ResourceGroup -AccountName $Account -Name $Deployment + return [int]$dep.Sku.Capacity +} + +function Set-DeploymentCapacity { + param([string]$Account, [string]$Deployment, [int]$Capacity) + # 기존 배포의 model/properties 는 유지하고 SKU capacity 만 갱신(create-or-update) + $existing = Get-AzCognitiveServicesAccountDeployment ` + -ResourceGroupName $ResourceGroup -AccountName $Account -Name $Deployment + $sku = New-Object 'Microsoft.Azure.Management.CognitiveServices.Models.Sku' ` + -ArgumentList $existing.Sku.Name, $null, $null, $Capacity, $null + New-AzCognitiveServicesAccountDeployment ` + -ResourceGroupName $ResourceGroup -AccountName $Account -Name $Deployment ` + -Properties $existing.Properties -Sku $sku | Out-Null +} + +# --------------------------------------------------------------------------- +# 쿨다운 체크 +# --------------------------------------------------------------------------- + +function Test-InCooldown { + param([string]$Region, [datetime]$Now) + + $table = Get-CloudTable -TableName $ActionTable + $actions = Get-AzTableRow -Table $table -CustomFilter "region eq '$Region'" + if (-not $actions) { return $false } + + # 실제 capacity 가 바뀐(changed=true) 액션만 대상으로 최신 것을 찾는다 + $changed = @($actions | Where-Object { "$($_.changed)".ToLower() -eq "true" }) + if ($changed.Count -eq 0) { return $false } + + $last = $changed | Sort-Object -Property TableTimestamp -Descending | Select-Object -First 1 + $elapsedMin = ($Now.ToUniversalTime() - $last.TableTimestamp.UtcDateTime).TotalMinutes + return ($elapsedMin -lt $CooldownMinutes) +} + +# --------------------------------------------------------------------------- +# 공유 상한(Reserved quota) 재분배 로직 +# --------------------------------------------------------------------------- + +function Get-NeedCapacity { + param([double]$ConsumedTpm) + if ($ConsumedTpm -le 0) { return $MinCapacity } + $raw = [int][math]::Ceiling($ConsumedTpm / ($AimUtil * $TpmPerCapacityUnit)) + return (Clamp -Value $raw -Min $MinCapacity -Max $MaxCapacity) +} + +function Get-Targets { + # $States: 각 원소 = @{ Region; Account; Deployment; Current; Consumed; Utilization } + param([array]$States) + + $needs = @{} + foreach ($s in $States) { $needs[$s.Region] = Get-NeedCapacity -ConsumedTpm $s.Consumed } + $totalNeed = ($needs.Values | Measure-Object -Sum).Sum + + if ($totalNeed -le $TotalCapacityUnits) { + # 여유 있음: 필요량만 배정, 나머지는 미할당 버퍼(증설은 무손실) + return @{ Targets = $needs; Contention = $false } + } + + # 경합: MIN 을 먼저 보장하고 남은 용량을 소비 TPM 비율로 배분 + $n = $States.Count + $rem = $TotalCapacityUnits - ($n * $MinCapacity) + $totalConsumed = ($States | ForEach-Object { [math]::Max($_.Consumed, 0.0) } | Measure-Object -Sum).Sum + if ($totalConsumed -le 0) { $totalConsumed = 1.0 } + + $targets = @{} + foreach ($s in $States) { + $extra = [int][math]::Floor($rem * [math]::Max($s.Consumed, 0.0) / $totalConsumed) + $targets[$s.Region] = Clamp -Value ($MinCapacity + $extra) -Min $MinCapacity -Max $MaxCapacity + } + # 내림으로 남은 잔여 unit 을 소비가 큰 리전부터 채운다(합이 TOTAL 을 넘지 않게) + $leftover = $TotalCapacityUnits - ($targets.Values | Measure-Object -Sum).Sum + foreach ($s in ($States | Sort-Object -Property Consumed -Descending)) { + while ($leftover -gt 0 -and $targets[$s.Region] -lt $MaxCapacity) { + $targets[$s.Region] += 1 + $leftover -= 1 + } + } + return @{ Targets = $targets; Contention = $true } +} + +function Get-RegionPlan { + param([hashtable]$State, [int]$Target, [bool]$Contention) + + $util = $State.Utilization + $withinBand = ($util -ge $TargetUtilLow -and $util -le $TargetUtilHigh) + if ($withinBand -and -not $Contention) { + # 편안한 구간이고 경합도 없음 → 불필요한 왕복(churn) 방지 위해 유지 + return @{ Decision = "hold"; Planned = $State.Current; Reason = "util $([math]::Round($util*100,2))% in dead-band" } + } + + $delta = Clamp -Value ([int]($Target - $State.Current)) -Min (-$MaxStepUnits) -Max $MaxStepUnits + $planned = $State.Current + $delta + $tag = "util $([math]::Round($util*100,2))% -> target $Target (contention=$Contention)" + if ($planned -gt $State.Current) { return @{ Decision = "up"; Planned = $planned; Reason = $tag } } + if ($planned -lt $State.Current) { return @{ Decision = "down"; Planned = $planned; Reason = $tag } } + return @{ Decision = "hold"; Planned = $State.Current; Reason = "util $([math]::Round($util*100,2))% bounded, no change" } +} + +# --------------------------------------------------------------------------- +# 이력 기록 +# --------------------------------------------------------------------------- + +function New-RowKey { + param([datetime]$Now, [string]$Region) + return "$($Now.ToString('yyyyMMddTHHmmssffffff'))-$Region-$([guid]::NewGuid().ToString('N').Substring(0,8))" +} + +function Write-Decision { + param([datetime]$Now, [hashtable]$Res) + $table = Get-CloudTable -TableName $DecisionTable + Add-AzTableRow -Table $table ` + -PartitionKey $Now.ToString('yyyyMMdd') -RowKey (New-RowKey -Now $Now -Region $Res.Region) ` + -Property @{ + region = $Res.Region + utilization = $Res.Utilization + avgConsumedTpm = $Res.AvgConsumedTpm + capacityBefore = $Res.CurrentCapacity + capacityTarget = $Res.Target + decision = $Res.Decision + reason = $Res.Reason + cooldownBlocked = $Res.CooldownBlocked + executed = $Res.Executed + } | Out-Null +} + +function Write-Action { + param([datetime]$Now, [hashtable]$Res, [int]$DurationMs) + $table = Get-CloudTable -TableName $ActionTable + $changed = ($Res.Executed -and ($Res.Target -ne $Res.CurrentCapacity)) + Add-AzTableRow -Table $table ` + -PartitionKey $Now.ToString('yyyyMMdd') -RowKey (New-RowKey -Now $Now -Region $Res.Region) ` + -Property @{ + region = $Res.Region + requestPayload = "$($Res.Region) capacity $($Res.CurrentCapacity) to $($Res.Target)" + capacityBefore = $Res.CurrentCapacity + capacityTarget = $Res.Target + changed = $changed + responseStatus = if ($Res.Error) { 500 } else { 200 } + success = [string]::IsNullOrEmpty($Res.Error) + errorMessage = $Res.Error + durationMs = $DurationMs + } | Out-Null +} + +# --------------------------------------------------------------------------- +# 메인 제어 사이클 +# --------------------------------------------------------------------------- + +Connect-Context +$now = (Get-Date).ToUniversalTime() + +# --- Phase 1: 상태 수집 (리전별 현재 capacity + 이동평균 사용률) --------------- +$states = @() +foreach ($region in $Regions.Keys) { + $cfg = $Regions[$region] + $current = Get-DeploymentCapacity -Account $cfg.Account -Deployment $cfg.Deployment + $rows = Get-RecentWindows -Region $region -Limit $SmoothingWindows + $consumed = Get-AvgConsumedTpm -Rows $rows + $provisioned = $current * $TpmPerCapacityUnit + $util = if ($provisioned -gt 0) { [math]::Round($consumed / $provisioned, 4) } else { 0.0 } + $states += @{ + Region = $region; Account = $cfg.Account; Deployment = $cfg.Deployment + Current = $current; Consumed = $consumed; Utilization = $util + } +} + +# --- Phase 2: 목표 산출(총량 제약) + dead-band/스텝/쿨다운 완충 ---------------- +$alloc = Get-Targets -States $states +$targets = $alloc.Targets +$contention = $alloc.Contention + +$results = @{} +$plannedMap = @{} +$durations = @{} +foreach ($s in $states) { + $p = Get-RegionPlan -State $s -Target ([int]$targets[$s.Region]) -Contention $contention + $decision = $p.Decision + $planned = $p.Planned + $reason = $p.Reason + + $cooldownBlocked = $false + if ($decision -ne "hold" -and (Test-InCooldown -Region $s.Region -Now $now)) { + $cooldownBlocked = $true + $planned = $s.Current + $decision = "hold" + $reason = "$reason | blocked by cooldown" + } + + $plannedMap[$s.Region] = $planned + $durations[$s.Region] = 0 + $results[$s.Region] = @{ + Region = $s.Region; Account = $s.Account; Deployment = $s.Deployment + AvgConsumedTpm = $s.Consumed; CurrentCapacity = $s.Current; Utilization = $s.Utilization + Decision = $decision; Target = $planned; Reason = $reason + CooldownBlocked = $cooldownBlocked; Executed = $false; Contention = $contention; Error = "" + } +} + +# --- Phase 3: 총량 제약 실행 (감축 먼저 → 증설은 남은 headroom 한도) ----------- +$free = $TotalCapacityUnits - (($states | ForEach-Object { $_.Current } | Measure-Object -Sum).Sum) + +function Invoke-Apply { + param([hashtable]$St, [hashtable]$Res, [int]$NewCap) + $sw = [System.Diagnostics.Stopwatch]::StartNew() + try { + if (-not $DryRun) { + Set-DeploymentCapacity -Account $St.Account -Deployment $St.Deployment -Capacity $NewCap + } + $Res.Target = $NewCap + $Res.Executed = ((-not $DryRun) -and ($NewCap -ne $St.Current)) + } + catch { + $msg = "$($_.Exception.Message)" + $Res.Error = $msg.Substring(0, [math]::Min(500, $msg.Length)) + $Res.Target = $St.Current + } + $sw.Stop() + return [int]$sw.ElapsedMilliseconds +} + +# 3-1) 감축(donor) 먼저 → headroom 확보 (여유 리전에서 회수, loss 없음) +foreach ($s in $states) { + $res = $results[$s.Region] + $planned = $plannedMap[$s.Region] + if (-not $res.CooldownBlocked -and $planned -lt $s.Current) { + $durations[$s.Region] = Invoke-Apply -St $s -Res $res -NewCap $planned + if (-not $res.Error) { $free += ($s.Current - $res.Target) } + } +} + +# 3-2) 증설(recipient): 사용률 높은 리전부터, 남은 headroom 한도로만 +foreach ($s in ($states | Sort-Object -Property Utilization -Descending)) { + $res = $results[$s.Region] + $planned = $plannedMap[$s.Region] + if ($res.CooldownBlocked -or $planned -le $s.Current) { continue } + $inc = [math]::Min($planned - $s.Current, $free) + if ($inc -le 0) { + $res.Decision = "hold" + $res.Reason = "$($res.Reason) | no headroom (Reserved 총량 소진)" + continue + } + $newCap = $s.Current + $inc + $durations[$s.Region] = Invoke-Apply -St $s -Res $res -NewCap $newCap + if (-not $res.Error) { + $free -= ($res.Target - $s.Current) + if ($res.Target -lt $planned) { $res.Reason = "$($res.Reason) | headroom-limited to $($res.Target)" } + } +} + +# --- Phase 4: 이력 기록 ------------------------------------------------------ +$results_ordered = @() +foreach ($s in $states) { + $res = $results[$s.Region] + Write-Decision -Now $now -Res $res + Write-Action -Now $now -Res $res -DurationMs $durations[$s.Region] + $results_ordered += $res +} +$results = $results_ordered + +Write-Output "=== Adaptive TPM Quota Controller (PowerShell, dryRun=$DryRun) ===" +$totalAfter = 0 +foreach ($r in $results) { + $totalAfter += $r.Target + $line = "[$($r.Region)] consumedTpm=$($r.AvgConsumedTpm) capacity=$($r.CurrentCapacity)->$($r.Target) " + + "util=$([math]::Round($r.Utilization*100,2))% decision=$($r.Decision) contention=$($r.Contention) " + + "cooldown=$($r.CooldownBlocked) executed=$($r.Executed) reason='$($r.Reason)'" + if ($r.Error) { $line += " error='$($r.Error)'" } + Write-Output $line +} +Write-Output "total capacity after=$totalAfter/$TotalCapacityUnits (Reserved cap)" diff --git a/ptu_lb/runbooks/requirements.txt b/ptu_lb/runbooks/requirements.txt new file mode 100644 index 0000000..db746c4 --- /dev/null +++ b/ptu_lb/runbooks/requirements.txt @@ -0,0 +1,3 @@ +azure-identity==1.19.0 +azure-data-tables==12.5.0 +azure-mgmt-cognitiveservices==13.5.0 From ae6fe9b8252b24455a219c7605ccc71ec8cfefcb Mon Sep 17 00:00:00 2001 From: daeungo1 Date: Fri, 3 Jul 2026 15:51:06 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat(ptu=5Flb):=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20-=20N=EB=A6=AC=EC=A0=84=20=EC=9D=BC?= =?UTF-8?q?=EB=B0=98=ED=99=94,=20RI=20=EA=B7=A0=EB=93=B1=EB=B6=84=EB=B0=B0?= =?UTF-8?q?=20fallback,=20PayGo=20100%=20util=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - region_max/Get-RegionMax 로 리전별 최대 capacity 를 N리전으로 일반화 - 메트릭 열화 시 RI 균등분배 fallback(even_split_targets/Get-EvenSplitTargets) 추가 - PayGo fallback 시 PTU util 100% 근접 허용 및 리전 확대 방안 문서화 --- ptu_lb/ptu-lb-test.md | 15 +++-- .../runbooks/adaptive_tpm_quota_controller.py | 63 +++++++++++++++--- ...optional_adaptive_tpm_quota_controller.ps1 | 65 +++++++++++++++---- 3 files changed, 117 insertions(+), 26 deletions(-) diff --git a/ptu_lb/ptu-lb-test.md b/ptu_lb/ptu-lb-test.md index 97fcb9b..2b97d7a 100644 --- a/ptu_lb/ptu-lb-test.md +++ b/ptu_lb/ptu-lb-test.md @@ -99,10 +99,14 @@ Azure Automation은 **스케줄러 + 실행/인증 호스트** 역할이며, 실 | MAX_STEP_UNITS | 1회 최대 capacity 변경폭 | 5 | | MIN_CAPACITY_RATIO | 리전별 최소 보장 비율(Reserved 총량 대비) | 0.25 | | MIN_CAPACITY | 리전별 최소 보장 capacity(= ceil(TOTAL × 0.25)) | 5 | -| MAX_CAPACITY | 리전별 최대 capacity(= TOTAL − MIN_CAPACITY) | 15 | +| MAX_CAPACITY | 리전별 최대 capacity. 2리전 기본값 = TOTAL − MIN_CAPACITY, N리전은 `TOTAL − (N−1)·MIN_CAPACITY` | 15 | | COOLDOWN_MINUTES | 조정 후 재조정 금지 시간(분) | 20 | -> 불변식: 항상 `cap_KR + cap_UK ≤ TOTAL_CAPACITY_UNITS`. 2리전 가정에서 리전 최대는 `TOTAL − MIN_CAPACITY`이며, 최소는 총량의 25%를 보장한다. +> 불변식: 항상 `Σ cap_r ≤ TOTAL_CAPACITY_UNITS`. 리전 최대는 `TOTAL − (N−1)·MIN_CAPACITY`로 일반화되며(2리전이면 `TOTAL − MIN_CAPACITY`), 최소는 총량의 25%를 보장한다. +> +> **리전 확대 시**: 코드 변경은 `REGIONS`(PS `$Regions`) 매핑에 항목을 추가하는 것으로 끝난다. 리전별 최대는 `region_max(n)`(PS `Get-RegionMax`)이 리전 수 n으로 자동 일반화하고, 총량 제약·감축→증설 순서·MIN 보장은 그대로 유지된다. +> +> **PayGo fallback 병행 시**: 상위 트래픽이 PTU 초과분을 PayGo(표준) 배포로 흘리는 구성에서는 PTU util을 100%에 근접(TARGET_UTIL_HIGH·AIM_UTIL ≈ 1.0)시켜도 무방하다. 초과분은 fallback LLM이 흡수하므로, 비용 최적화 관점에서 적정 PTU/PayGo 비중을 도출하는 것이 목표다. ## 샘플 테스트 Sizing (권장) @@ -124,7 +128,7 @@ Azure Automation은 **스케줄러 + 실행/인증 호스트** 역할이며, 실 Reserved 총량이 만재(10/10)인 상태에서 트래픽을 기울여 리전 간 재분배를 유도한다. 1. Baseline 20분: 양 리전 util 40~60% (유지 구간, 재분배 없음) -2. 기울기 30분: Korea util 85%+ / UK util 20% → UK 먼저 감축 후 Korea 증설(감축→증설) +2. 기울기 30분: Korea util 85%+(PayGo fallback 병행 시 ≈100%까지 허용) / UK util 20% → UK 먼저 감축 후 Korea 증설(감축→증설) 3. 역전 30분: UK util 85%+ / Korea util 20% → 반대 방향 재분배(쿨다운 경과 후) 4. 진동 30분: 10분 단위 고/저 교차 → 쿨다운/스텝 제한으로 왕복 억제 @@ -135,6 +139,7 @@ Reserved 총량이 만재(10/10)인 상태에서 트래픽을 기울여 리전 3. 고사용률 리전 증설분이 잉여 리전 감축분으로 충당됨(loss 최소) 4. 쿨다운 중 불필요한 재조정이 발생하지 않음 5. ControlDecision, ScaleAction 이력이 누락 없이 기록됨 +6. 메트릭 열화(조회 실패) 시 RI 균등분배 fallback으로 전환되어 미할당 버퍼 없이 총량을 소진함 ### 파라미터 적용 규칙 @@ -199,6 +204,7 @@ $$ 5. (실행 2) planned > 현재인 리전을 사용률 높은 순으로 headroom 한도 내 증설 6. (기록) 리전별 ControlDecision / ScaleAction 기록 7. (안전) 개별 API 실패 시 기록 후 계속, 합이 총량을 넘지 않도록 보장 +8. (fallback) 메트릭 조회 열화 시 소비 기반 재분배 대신 **RI 균등분배**(총량을 리전 수로 균등)로 전환 → 판단 근거가 없을 때도 미할당 버퍼 없이 RI에 맞는 PTU를 최대 소진(감축→증설 순서·총량 불변식 유지) ## 테스트 시나리오 @@ -209,7 +215,7 @@ $$ ### Test-2 재분배 (감축→증설) -- Korea util 85%+ / UK util 20% 유도 +- Korea util 85%+ / UK util 20% 유도 (PayGo fallback 병행 시 Korea ≈100%도 정상으로 판정) - UK 감축이 Korea 증설보다 먼저 실행되고, 합이 총량을 유지하는지 확인 ### Test-3 증설 선행 방지 @@ -231,6 +237,7 @@ $$ - capacity 변경 API 실패 강제 - 재시도/기록/안전 종료 및 총량 불변식 유지 확인 +- 메트릭(Table) 조회 실패 강제 → RI 균등분배 fallback 전환 및 총량 불변식 유지 확인 ## 테스트 결과 diff --git a/ptu_lb/runbooks/adaptive_tpm_quota_controller.py b/ptu_lb/runbooks/adaptive_tpm_quota_controller.py index 7c61d78..e3a1573 100644 --- a/ptu_lb/runbooks/adaptive_tpm_quota_controller.py +++ b/ptu_lb/runbooks/adaptive_tpm_quota_controller.py @@ -96,7 +96,9 @@ MAX_STEP_UNITS = 5 # 1회 조정 최대 capacity 변경폭(단위) MIN_CAPACITY_RATIO = 0.25 # 리전별 최소 보장 = Reserved 총량의 25% MIN_CAPACITY = max(1, math.ceil(TOTAL_CAPACITY_UNITS * MIN_CAPACITY_RATIO)) # =5 -MAX_CAPACITY = TOTAL_CAPACITY_UNITS - MIN_CAPACITY # 상대 리전 최소 보장(2리전 가정) =15 +# 리전 최대 = 총량 − 나머지 리전 최소 보장 합. 2리전 기본값(=TOTAL−MIN)이며, +# N리전 확장 시에는 region_max(n) 으로 (n-1)*MIN 을 차감해 일반화한다. +MAX_CAPACITY = TOTAL_CAPACITY_UNITS - MIN_CAPACITY # 2리전 기본값 =15 COOLDOWN_MINUTES = 20 # 실제 조정 후 재조정 금지 시간(분) @@ -104,6 +106,27 @@ def clamp(value: int, low: int, high: int) -> int: return max(low, min(value, high)) +def region_max(n: int) -> int: + """N리전 일반화된 리전별 최대 capacity(= 총량 − 나머지 (n-1) 리전 최소 보장). + + 한 리전이 최대를 가져가도 나머지 리전이 각각 MIN_CAPACITY 를 확보할 수 있어야 + 하므로 상한은 TOTAL − (n-1)*MIN 이다. n=2 이면 TOTAL − MIN 로 기존과 동일. + """ + return max(MIN_CAPACITY, TOTAL_CAPACITY_UNITS - (max(n, 1) - 1) * MIN_CAPACITY) + + +def even_split_targets(regions: list[str]) -> dict[str, int]: + """RI(Reserved) 총량을 리전 수로 균등 분배(내림 + 나머지 앞 리전부터). + + 메트릭 조회 실패 등 판단 근거가 열화됐을 때, 미할당 버퍼로 PTU 를 낭비하지 않고 + RI 에 맞는 PTU 를 최대 소진하기 위한 **fallback 목표**다. 합은 항상 TOTAL 이다. + """ + n = len(regions) or 1 + base = TOTAL_CAPACITY_UNITS // n + rem = TOTAL_CAPACITY_UNITS - base * n + return {r: base + (1 if i < rem else 0) for i, r in enumerate(regions)} + + @dataclass class RegionResult: region: str @@ -207,12 +230,15 @@ class RegionState: utilization: float -def need_capacity(consumed_tpm: float) -> int: - """AIM_UTIL 에서 돌릴 수 있는 capacity 를 역산(리전 최소/최대로 clamp).""" +def need_capacity(consumed_tpm: float, cap_max: int = MAX_CAPACITY) -> int: + """AIM_UTIL 에서 돌릴 수 있는 capacity 를 역산(리전 최소/최대로 clamp). + + cap_max 는 리전 수에 따른 상한(region_max(n))으로, 기본값은 2리전 기준이다. + """ if consumed_tpm <= 0: return MIN_CAPACITY raw = math.ceil(consumed_tpm / (AIM_UTIL * TPM_PER_CAPACITY_UNIT)) - return clamp(raw, MIN_CAPACITY, MAX_CAPACITY) + return clamp(raw, MIN_CAPACITY, cap_max) def compute_targets(states: list[RegionState]) -> tuple[dict[str, int], dict[str, int], bool]: @@ -224,7 +250,8 @@ def compute_targets(states: list[RegionState]) -> tuple[dict[str, int], dict[str - contention: 총 필요량이 Reserved 총량을 초과(True) → 소비 TPM 비율로 비례 배분 """ n = len(states) - needs = {s.region: need_capacity(s.consumed) for s in states} + cap_max = region_max(n) # 리전 수에 따른 상한(2리전이면 TOTAL−MIN 로 기존과 동일) + needs = {s.region: need_capacity(s.consumed, cap_max) for s in states} total_need = sum(needs.values()) if total_need <= TOTAL_CAPACITY_UNITS: @@ -237,11 +264,11 @@ def compute_targets(states: list[RegionState]) -> tuple[dict[str, int], dict[str targets: dict[str, int] = {} for s in states: extra = int(rem * max(s.consumed, 0.0) / total_consumed) - targets[s.region] = clamp(MIN_CAPACITY + extra, MIN_CAPACITY, MAX_CAPACITY) + targets[s.region] = clamp(MIN_CAPACITY + extra, MIN_CAPACITY, cap_max) # 내림으로 남은 잔여 unit 을 소비가 큰 리전부터 채운다(합이 TOTAL 을 넘지 않게). leftover = TOTAL_CAPACITY_UNITS - sum(targets.values()) for s in sorted(states, key=lambda x: x.consumed, reverse=True): - while leftover > 0 and targets[s.region] < MAX_CAPACITY: + while leftover > 0 and targets[s.region] < cap_max: targets[s.region] += 1 leftover -= 1 return targets, needs, True @@ -329,23 +356,39 @@ def run_cycle(dry_run: bool) -> list[RegionResult]: mgmt = CognitiveServicesManagementClient(cred, SUBSCRIPTION_ID) # --- Phase 1: 상태 수집 (리전별 현재 capacity + 이동평균 사용률) -------------- + # 메트릭 조회 실패는 리전을 degraded 로 표시한다(판단 근거 열화 → RI 균등분배 fallback). states: list[RegionState] = [] + degraded: list[str] = [] for region, cfg in REGIONS.items(): account, deployment = cfg["account"], cfg["deployment"] current = get_deployment_capacity(mgmt, account, deployment) - rows = get_recent_windows(table_svc, region, SMOOTHING_WINDOWS) - consumed = avg_consumed_tpm(rows) + try: + rows = get_recent_windows(table_svc, region, SMOOTHING_WINDOWS) + consumed = avg_consumed_tpm(rows) + except Exception: # noqa: BLE001 - 메트릭 열화 시 fallback 으로 진행 + consumed = 0.0 + degraded.append(region) provisioned = current * TPM_PER_CAPACITY_UNIT util = round(consumed / provisioned, 4) if provisioned > 0 else 0.0 states.append(RegionState(region, account, deployment, current, consumed, util)) # --- Phase 2: 목표 산출(총량 제약) + dead-band/스텝/쿨다운 완충 --------------- - targets, _needs, contention = compute_targets(states) + # 정상: 소비 비율 재분배. Fallback: 메트릭 열화 시 RI(Reserved) 총량을 균등분배해 + # 미할당 버퍼 없이 RI 에 맞는 PTU 를 최대 소진한다(감축→증설 순서는 그대로 유지). + fallback = bool(degraded) + if fallback: + targets = even_split_targets([s.region for s in states]) + _needs = dict(targets) + contention = True # 균등분배는 총량 만재 배분(버퍼 0) + else: + targets, _needs, contention = compute_targets(states) results: dict[str, RegionResult] = {} planned_map: dict[str, int] = {} for s in states: decision, planned, reason = plan_region(s, targets[s.region], contention) + if fallback: + reason += " | FALLBACK RI 균등분배(메트릭 열화)" cooldown_blocked = False if decision != "hold" and is_in_cooldown(table_svc, s.region, now): diff --git a/ptu_lb/runbooks/optional_adaptive_tpm_quota_controller.ps1 b/ptu_lb/runbooks/optional_adaptive_tpm_quota_controller.ps1 index e11c3c2..5758cdf 100644 --- a/ptu_lb/runbooks/optional_adaptive_tpm_quota_controller.ps1 +++ b/ptu_lb/runbooks/optional_adaptive_tpm_quota_controller.ps1 @@ -72,7 +72,9 @@ $ErrorActionPreference = "Stop" # --- Reserved 총량 파생값 (합산 불변식의 기준) --------------------------------- $TotalCapacityUnits = [int]($ReservedTotalTpm / $TpmPerCapacityUnit) # =20 $MinCapacity = [int][math]::Max(1, [math]::Ceiling($TotalCapacityUnits * $MinCapacityRatio)) # =5 -$MaxCapacity = $TotalCapacityUnits - $MinCapacity # =15 (2리전 가정) +# 리전 최대 = 총량 − 나머지 리전 최소 보장 합. 2리전 기본값(=TOTAL−MIN)이며 +# N리전 확장 시에는 Get-RegionMax 로 (n-1)*MIN 을 차감해 일반화한다. +$MaxCapacity = $TotalCapacityUnits - $MinCapacity # 2리전 기본값 =15 # 리전 -> Foundry 계정/배포 매핑 (Reserved 총량을 두 리전이 공유) $Regions = [ordered]@{ @@ -109,6 +111,27 @@ function Clamp { return [math]::Min([math]::Max($Value, $Min), $Max) } +function Get-RegionMax { + # N리전 일반화된 리전별 최대 capacity(= 총량 − (n-1)*MIN). n=2 이면 TOTAL−MIN 로 기존과 동일. + param([int]$N) + $nn = [math]::Max($N, 1) + return [math]::Max($MinCapacity, $TotalCapacityUnits - (($nn - 1) * $MinCapacity)) +} + +function Get-EvenSplitTargets { + # RI(Reserved) 총량을 리전 수로 균등 분배(내림 + 나머지 앞 리전부터). 합은 항상 TOTAL. + # 메트릭 열화 등 판단 근거 상실 시, 미할당 버퍼 없이 RI 에 맞는 PTU 를 최대 소진하는 fallback 목표. + param([array]$Regions) + $n = [math]::Max($Regions.Count, 1) + $base = [int][math]::Floor($TotalCapacityUnits / $n) + $rem = $TotalCapacityUnits - ($base * $n) + $targets = @{} + for ($i = 0; $i -lt $Regions.Count; $i++) { + $targets[$Regions[$i]] = $base + (&{ if ($i -lt $rem) { 1 } else { 0 } }) + } + return $targets +} + # --------------------------------------------------------------------------- # 메트릭 조회 # --------------------------------------------------------------------------- @@ -185,18 +208,20 @@ function Test-InCooldown { # --------------------------------------------------------------------------- function Get-NeedCapacity { - param([double]$ConsumedTpm) + param([double]$ConsumedTpm, [int]$CapMax = $MaxCapacity) if ($ConsumedTpm -le 0) { return $MinCapacity } $raw = [int][math]::Ceiling($ConsumedTpm / ($AimUtil * $TpmPerCapacityUnit)) - return (Clamp -Value $raw -Min $MinCapacity -Max $MaxCapacity) + return (Clamp -Value $raw -Min $MinCapacity -Max $CapMax) } function Get-Targets { # $States: 각 원소 = @{ Region; Account; Deployment; Current; Consumed; Utilization } param([array]$States) + $n = $States.Count + $capMax = Get-RegionMax -N $n # 리전 수에 따른 상한(2리전이면 TOTAL−MIN 로 기존과 동일) $needs = @{} - foreach ($s in $States) { $needs[$s.Region] = Get-NeedCapacity -ConsumedTpm $s.Consumed } + foreach ($s in $States) { $needs[$s.Region] = Get-NeedCapacity -ConsumedTpm $s.Consumed -CapMax $capMax } $totalNeed = ($needs.Values | Measure-Object -Sum).Sum if ($totalNeed -le $TotalCapacityUnits) { @@ -205,7 +230,6 @@ function Get-Targets { } # 경합: MIN 을 먼저 보장하고 남은 용량을 소비 TPM 비율로 배분 - $n = $States.Count $rem = $TotalCapacityUnits - ($n * $MinCapacity) $totalConsumed = ($States | ForEach-Object { [math]::Max($_.Consumed, 0.0) } | Measure-Object -Sum).Sum if ($totalConsumed -le 0) { $totalConsumed = 1.0 } @@ -213,12 +237,12 @@ function Get-Targets { $targets = @{} foreach ($s in $States) { $extra = [int][math]::Floor($rem * [math]::Max($s.Consumed, 0.0) / $totalConsumed) - $targets[$s.Region] = Clamp -Value ($MinCapacity + $extra) -Min $MinCapacity -Max $MaxCapacity + $targets[$s.Region] = Clamp -Value ($MinCapacity + $extra) -Min $MinCapacity -Max $capMax } # 내림으로 남은 잔여 unit 을 소비가 큰 리전부터 채운다(합이 TOTAL 을 넘지 않게) $leftover = $TotalCapacityUnits - ($targets.Values | Measure-Object -Sum).Sum foreach ($s in ($States | Sort-Object -Property Consumed -Descending)) { - while ($leftover -gt 0 -and $targets[$s.Region] -lt $MaxCapacity) { + while ($leftover -gt 0 -and $targets[$s.Region] -lt $capMax) { $targets[$s.Region] += 1 $leftover -= 1 } @@ -298,12 +322,20 @@ Connect-Context $now = (Get-Date).ToUniversalTime() # --- Phase 1: 상태 수집 (리전별 현재 capacity + 이동평균 사용률) --------------- +# 메트릭 조회 실패는 리전을 degraded 로 표시한다(판단 근거 열화 → RI 균등분배 fallback). $states = @() +$degraded = @() foreach ($region in $Regions.Keys) { $cfg = $Regions[$region] $current = Get-DeploymentCapacity -Account $cfg.Account -Deployment $cfg.Deployment - $rows = Get-RecentWindows -Region $region -Limit $SmoothingWindows - $consumed = Get-AvgConsumedTpm -Rows $rows + try { + $rows = Get-RecentWindows -Region $region -Limit $SmoothingWindows + $consumed = Get-AvgConsumedTpm -Rows $rows + } + catch { + $consumed = 0.0 + $degraded += $region + } $provisioned = $current * $TpmPerCapacityUnit $util = if ($provisioned -gt 0) { [math]::Round($consumed / $provisioned, 4) } else { 0.0 } $states += @{ @@ -313,9 +345,17 @@ foreach ($region in $Regions.Keys) { } # --- Phase 2: 목표 산출(총량 제약) + dead-band/스텝/쿨다운 완충 ---------------- -$alloc = Get-Targets -States $states -$targets = $alloc.Targets -$contention = $alloc.Contention +# 정상: 소비 비율 재분배. Fallback: 메트릭 열화 시 RI 총량을 균등분배해 RI 에 맞는 PTU 를 최대 소진. +$fallback = ($degraded.Count -gt 0) +if ($fallback) { + $targets = Get-EvenSplitTargets -Regions @($states | ForEach-Object { $_.Region }) + $contention = $true # 균등분배는 총량 만재 배분(버퍼 0) +} +else { + $alloc = Get-Targets -States $states + $targets = $alloc.Targets + $contention = $alloc.Contention +} $results = @{} $plannedMap = @{} @@ -325,6 +365,7 @@ foreach ($s in $states) { $decision = $p.Decision $planned = $p.Planned $reason = $p.Reason + if ($fallback) { $reason = "$reason | FALLBACK RI 균등분배(메트릭 열화)" } $cooldownBlocked = $false if ($decision -ne "hold" -and (Test-InCooldown -Region $s.Region -Now $now)) { From 7d7e723f4912825e12dcbcbd38198dcc4d9f5230 Mon Sep 17 00:00:00 2001 From: daeungo1 Date: Fri, 3 Jul 2026 16:13:16 +0900 Subject: [PATCH 3/3] =?UTF-8?q?docs(ptu=5Flb):=20=EB=A6=AC=EC=A0=84/?= =?UTF-8?q?=EB=AA=A8=EB=8D=B8=20N=EA=B0=9C=20=ED=99=95=EC=9E=A5=20?= =?UTF-8?q?=EC=8B=9C=20REGIONS=20=EB=A7=A4=ED=95=91=20=EC=95=88=EB=82=B4?= =?UTF-8?q?=20=EB=AA=85=ED=99=95=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ptu_lb/ptu-lb-test.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ptu_lb/ptu-lb-test.md b/ptu_lb/ptu-lb-test.md index 2b97d7a..7d235bd 100644 --- a/ptu_lb/ptu-lb-test.md +++ b/ptu_lb/ptu-lb-test.md @@ -104,7 +104,7 @@ Azure Automation은 **스케줄러 + 실행/인증 호스트** 역할이며, 실 > 불변식: 항상 `Σ cap_r ≤ TOTAL_CAPACITY_UNITS`. 리전 최대는 `TOTAL − (N−1)·MIN_CAPACITY`로 일반화되며(2리전이면 `TOTAL − MIN_CAPACITY`), 최소는 총량의 25%를 보장한다. > -> **리전 확대 시**: 코드 변경은 `REGIONS`(PS `$Regions`) 매핑에 항목을 추가하는 것으로 끝난다. 리전별 최대는 `region_max(n)`(PS `Get-RegionMax`)이 리전 수 n으로 자동 일반화하고, 총량 제약·감축→증설 순서·MIN 보장은 그대로 유지된다. +> **리전/모델 확대 시**: 코드 변경은 `REGIONS`(PS `$Regions`) 매핑에 배포 항목(리전 또는 모델별 `account`+`deployment` 쌍)을 추가하는 것으로 끝난다. 모델을 늘리는 경우도 동일하게 각 모델 배포를 하나의 항목으로 등록하면 같은 Reserved 총량을 공유한다. 항목별 최대는 `region_max(n)`(PS `Get-RegionMax`)이 항목 수 n으로 자동 일반화하고, 총량 제약·감축→증설 순서·MIN 보장은 그대로 유지된다. > > **PayGo fallback 병행 시**: 상위 트래픽이 PTU 초과분을 PayGo(표준) 배포로 흘리는 구성에서는 PTU util을 100%에 근접(TARGET_UTIL_HIGH·AIM_UTIL ≈ 1.0)시켜도 무방하다. 초과분은 fallback LLM이 흡수하므로, 비용 최적화 관점에서 적정 PTU/PayGo 비중을 도출하는 것이 목표다. @@ -169,6 +169,7 @@ $$ 4. 목표 capacity 산출 (Reserved 총량 제약) - **여유 있음** ($\sum_r need_r \le TOTAL$): 각 리전에 need만 배정, 나머지는 미할당 버퍼로 둔다 - **경합** ($\sum_r need_r > TOTAL$): 각 리전에 MIN을 먼저 보장하고, 남은 용량을 소비 TPM 비율로 배분 +- **fallback (메트릭 열화)**: 메트릭 조회가 실패해 판단 근거가 없을 때는 소비 기반 배분 대신 **RI 균등분배**(총량을 리전 수로 균등, $target_r \approx TOTAL / n$)로 전환해 미할당 버퍼 없이 RI에 맞는 PTU를 최대 소진한다 $$ target_r = MIN\_CAPACITY + \left\lfloor (TOTAL - n \cdot MIN\_CAPACITY)\times\frac{consumedTpm_r}{\sum_j consumedTpm_j} \right\rfloor @@ -177,7 +178,7 @@ $$ 5. dead-band·스텝 완충 - 경합이 아니고 사용률이 [LOW, HIGH] 안이면 유지(hold)로 churn 방지 - 목표로의 이동을 ±MAX_STEP_UNITS로 제한 -- 리전 최소/최대(MIN_CAPACITY ~ MAX_CAPACITY = TOTAL − MIN) 경계 적용 +- 리전 최소/최대(MIN_CAPACITY ~ `region_max(n)` = TOTAL − (n−1)·MIN) 경계 적용. 2리전이면 MAX_CAPACITY = TOTAL − MIN 과 동일 6. 쿨다운 가드 - 해당 리전의 마지막 '실제 변경(changed=true)' ScaleAction이 COOLDOWN_MINUTES 이내면 조정 차단

}d# zczC%||95)i#X9`|cs8c24nOu1MSJ2oUlb~qWEy?eignZmUsZ+qSi0u>i~o%7)JmY1 zd8~mwMp~5OiL{{z=5DARRwycSzvEb8&<|H$=T4%yR^8Io*Ez+Q3QFy)3{ z%%swSpJTksj2v`5?rwA~Cm$8|s^5zLdw1SK{WPhv5WaSEj-0C9V3K%S{bjmn>Vc9U z@!2mPK#AIj)+5~K?R~KNB}VEZwH~p-?pmOW`KDo2{hq6$(oQbdO|K81z^JgW-(;;K zZSq1vB8D#a?g>@8^9xB;mUrF$c}b25#ao&EWs-I4ElWC`h4;d-nwZVDJ4Ay?B0g~ThZm6QtAf{~nJ5*I8rJpxd zUi?5jJZ|*vjv%f}e4aY?z26pHE=q9}t4T$E668j;?@UkE`ONFG2|Ijsl`9!+nB&)C zH4tvh$A3)VN7;l0?80Rq&T8C32?IsBvIz_h$O)~;Ej!B9gq+!Sy5hsd=odwZcUN1N zqowaQ#ZOLO8f9$RDE16_zi7St5&2bAbE|30xBQrE4g4v~Iae8uu#d)58M^?v&O}DeMsuSJb%cHJ%=Jrx0 zgCvN*EitgeY<=!@(dVtc^FnL!Fjyk4bI+Zi@eP`Lizo;gZsu;N`O?SS0e`6GAb(Pm z^AXHb!yqm!q0~eUZSv*j-tDcNDN7pb%-UGamW2Yrgu70H`~r2E5^&h>Kg002rFq(q zk#5&nD{A%JvNg|5O~|7*Y9dN75Gh@$t%j+HyU|%WVLM+5J^R8e2ihmK-RwDK{e*u^ zx53^gH6#g^8eSuPaZ!P>PIo!K*jN?n!`0sR*iuH{-b%9Xjr8ZAAu3l*ozx$st3(Yi zE1UF9b&`ky2^+0O?rG{~c^ZlDF5b>j2o1ERyS3-2iBI474Fwx6{mVh2(xtY#Kvd;y zU)lPtp+ZT|_UIHD4nDY}FLNoDraE~`TB6m2dooVT#WwDEPyQ*@&rLHC7p|&ZJ&8p+ zk~oo+*T;XhLdkx{AzjQocF!#yO!Q54FrOd2-`-?<;HJMmJv=IT0za8Jq^=8hT+|@E zyn%k~SWNH;>SAXub0jqbFR#>pq-dru0DL!@5r z$jz5fX$!+Tm!$dVCLgEf6v>&x%nniYM!1`ewNEFi&5gYD-3s41*%cJV0m|b&?GHl~+fBHuYL%O9> zyPl43>t3+N=y=WA_3tP}lX4{IR2duuAWvb*0UH-Ablqhgk@tgESb=XwW~cn%)+TGc zTDpp+X7yY`Hrr@^SY6z&SugQzNbkfD%fJDCG-04o*@Vy-x6%pRDP(FCQ_$5sqZcB> zaeDN=Gyn_~BP2r^1q-UpJ_`)dlC%5m+WM!R9f)w@Qk~x^*APFDkoGq^!U{Ex(I})Li00j~cX4^srO7Xau8%5I6fKt>{LqzC11C$i{{83C zs@O3v_HxFkFC;5fFApZHkdYDng)w1*j~#*1AeEw+!Z=!~xRSc;UGmUf#bpog6Ag#; zpDMFZuPtq=847v{$DOt=-Zz0a`@pUUK|WOMI$JGoQ2$<7pG7S1_15H?Yuuuz{4k=+ zja~I&d#63zi>8aieCM>Cf-4L{P5Il`Vt`j%n;f2%+)Ka(G1_}$5J)rFoDZRf5x^A^o|+mt6gU-zNJuLlf9x3qte zn@;{YURkdm8!5zh`y0(s*lH^^SWi5_m zDx}{d5n(xB5LwH{(NG0?#Y3d*}i}NNUTQP*`j^)}; z*UEh4fPf+q;j_Xo$62kgr#wH8=YOZ_D`Zc}a!~H1$Q6Z}2~;-}RV6$VDq1&H8!5eJ zE38gn^s-X!J6OpSMaGkA7P{3TL_nCmn(QBGw@nE~3N>bd2Iq_rgB&KqQYLp>v-97n zGN@~xuc4@E?gflL_G5U~bofx1qsZZ1mA7)zDQ2789SXEglTiHMFp{1H8PU(zreM=- z?weH!MZs3%h2d`6HH+^Z_D|~2ht=vra?2gd)buSLR_=FJvGb6HSH zd-%4DeA4g{W}17IFa?i$zgKpLNNMPxj%Nz413&dM%Jt0`m$uIgY0x^98V1qXH~CSn zPxqu`|CC;H23CqqXk{L8xDudX-_(=^9ehQvAw+T_9{(!^v}Q~;^l>xFUx-bBRJVSl(lDWniP`$3D_rTy^TFoNs9=>vpMb{ z8k&1ORMnvyvrRzD;(uP2ol2sqI?I>@_3{T$dBtwdEeG{|*uvgyJGr{Tjn$1@-7~f9 z=5TFbW}*IF@?C894#Xk#&|}{ZeH$~?nt7~WWc7G*C6&#NHrZBK1mN3|8842|ZY6E8 zezRPt9=Q$bf(7EsGQ{0A#( z!%mJ{keXMY<41n+n|}2bPdFn9Kk6B{&W0qfoI=aAcR*^o7wB@Xxcm7gE_D10 zO^i1%7An8Ck$cEur6z+kPgjl2)%m}hQ6m$iQL-;?xVZ1U_Ul|=v))a}xFzQA+Z?}A zBYCmyeg9%j{tDK5CZFY*iEJ;66z(cJLcKof@tltZ37=n}-%2d*wR}1+@HqB;^6>&C z48Qq*35sHS+XufggzJ_!*FWr5=n1Qb4B%5m*r{0PP&d2~kj$m0gEF&oh#cDWkrU_w zyna87-X43qdA7xl7nH{LbD+{ZydVi~HSi+qz!FCtrK*O?r;B>972Kf-VuA}|O32pm zqC82fxm=H+;H4k)`XGOp1Hvv@8G9R|j_nsJ1^Ydg9{KmDVTyx}t z2VKZNmX}n@Tjnp_7jKUJlm8u3C1!Bs;?RI&;~Wt~Q0hnuUhjR3tug+89!^1*fa>yz z|IbtBfe)8jX;HgeU624ItodCMzcUcC{(q@b3ldyu(8ts6(Q~rqh@I`X)Hn?fqqQ z>pS}%dw%~%UC(JLz7F;K<*i|8V#*cJ(ec|w&22H|)pT{;g(Ywy<(;vpqseJPo8;^3 zI7=otIObFrrqmlbeBf>Bn|G=^i`$+4)5!U}zG&#V;?;eh9bn}ua4(R>cXKdl3`b{{ zRpc!_nXo*vM<`$d+|pZ<=OUv}c?z1?^YL2x%NuZ1JR|V8i>51PF07fn(i`awodxTH zeRv;do!^wGum!)nF08%p({O8yRCwU>RS3;hGtsE`c;Al?r;r@$T&d^3cL*<0D@uo5QS3vBZn*BhNSgQY=l}8(&i^8JDigIAuUePxHNn^6zk=gK{B!AX zNI`{VM@&25QP`= zB;?qqSGg}SQ1C0}d!jUAT3BF&_*c0+(Q+J6N?F+{n7WIDQ0dJ==YH7czVQ@$SW;;j zE|lK)Ctx1g<|Ia`Ik7+8EHOZSB4?#UnBzpu-wod!KK@BoJ&mb_#S?$ z0)m?SG2?~$WF!2y5S$W7sP3`Jq%lw-O4;hqE!6obE_BF=_{DJ$?E&LSim$a`i|4(M z11^`X8T-f1wl}dFVwL{#p3Ft>lHs`hI>MfL1kt~C5~o8QXZ1y|A$U&IBcuFMl?|I` zDqbnJ7D!=n*BjLGssnqj?UjN3lQW4+0>~p=26AeH8l+`=VxR zH@_FYpOLF~vO|a1OFxU4-7XtMF0g76S!1#|AWo|&$M#I)joJ~d<~SM)*`V8sRv4FE z(jrLO51fDG0&Dgcer^Htpl@k0o#t1NV90lizsP;>AfRW$(ZlJNf{d7SZbfbVKTJC#a8*GK_M`2%l9gK}#^y;6Y-;~)iI7V5ApObb{HQ~^ znGcVI=tstp4e09ev};m)mg6JMZB6CXPej;+1bLqx|J*`wdo8OXtB za<{R{yz(*FH*XZM{HhC?j||+lxvhi@0C|S zz!#M6Tk*CpOI(MuBJ9j|EODtDser>f3vodW+Wi$q-N0jjwEJ3&6E)dzmRF1(a~;># zJ`cof1g*Ys-;1fkKxpZGK3GD!s#1t5j8%JU8@N>1nkzLXrFX6yYGu zb9N207e*LkoeHnt5o@DOa-TV8*naaN3&f|eN1@^#5Q2^s8jD#5P9Ccvv(+HF7te>? z2d?0lr-3~Z9R2A-+#n_2*Hi7h^?UJCVz-=M)gCSP(1<*D$3~us>Rh^xUeYx@qN>`VI6twgfsjs2tmSz* z+dC*}rG=A&S{KmnrqD3u`O)kk8?MF-df`XP5%vO=NW55nd{|&bZiUR;qR*=To0c)y z!S2XOi&QyvoUO%|#or0DK0lw>Y5BJnWBT(~KM3N>zkcyS zf=2kl%~K(FL@GA2>qscJpQ)ni-61~v>mpm>d_rh`bl{g4bruE0=@^MJxSwny6y;02 zkXyP6rmro;5?a-H+Ud{sAWJcNGepN>S#YuzFSkZ=uH94iFDk1x4 z7TUsGU8+Zqnu0zj)Np-x{^3aRX_r@^_VxkB5ZySJkb5o?>Q#FHGc#l1a6^Y!ekCY< z^~E1A@Y)TDa5M!)VEP@~e@gvI{n#H|E#;4Dkj5=HazIC)p8Gd>S|ntdfh@^mSK$xt zO@F5C`_3MPNA5S;_j3FygJOj^^;^`j{^?uMsy^C4H(KQ!y&!z#T5R`&hnq860)}r+ zcU~j)xd$KZ8Y?aLq;`2>o*Iu(>fka}NV7zDqMCYNmN;tf#~dPRHIwNxcq-BQ!KI{l$$Fy1OHuhKV^hI)C; zib3(h9p3d7y;oc3wc_JH?2@L_k;uvT%yLD#IdaZ0m)C66tVN>9e6RG`Ao@nqSeb(c zSS^m7tk7>IuQxtQ^PSqgTPr=@IH`Z~*7B&6mrPrms3>{7Y9&hUB57_)`W$?=A3P9@LEi{)&g8 zCWt)PQWZ$qEGDzl4iv2PT|8%6Np)gtJ{*?Qywq#LHD5WM4$+Q#02Y5_^v<~@cqIcv zG_v8DZQn!kh8dBke4RaQO+$a3^LWkHmKUQV?$g z(-v$Bc1+rQJ*cdc1jd#M`luXNte2Kmc0XOg`DM~Wmv&1gF5_68eaRrB2Cl-QY78Z) zrL};;D&IgK?N})Vn`)LElS~lG2ib$x3O_q%4s)%RtVO`x9P~S@3qc{nlq&a&X&d zCTyPWomMH6Tnem6V81`ZE4oil9X1()78q^iV>}e^Y4(IF7OKk`G!^nrNCNtizURP>` zn=tcjxYT0~hY}8EGv=PHTe6?JTTb%sxI4b}o;V7+vav6Fe!$#gZN0zW&Au=}W00`_ z(vvtQQ%$y~Gc*JDdi}8E*)Zm?C0JcY{D97j@|0OXNc_*5)nrZdXhJhv-HW9Y--LBi z?1|8Jbw&>`h4-mQ@9w4Sy-E_EQ-s!#F)^HIR^%vmC~y4Hv~D|~buN7+A4?OYv)~-4 zJF?;ah#})xlf8Ih3iN8G4I~a+Vsx-X;Sp$|WmKeB``rf`qGo_%lsza62Bn^r)%A z5an%JkDq*)phEV@?Ld{W+Da7NO#sD_E%8~-W|&=F(7C#VUt{~{93BaqCew2@$pSs^ zPQWIuKH23Usd2E$n=oYKw~Xc{P%m+|v*NZ%^q*?5$^RgGQwhICm_U=@s(c+$M@@rS z6{yo!V+E%trv}$~#yfWUj8$;Bd&H@~T6PceJ`=8YYEkA%G~5dIIpd)iI4MhdjlboZ zC)!`j5i~h_jB=$Eouco<#RT3C@-MJz^dK4MTYXPnF|8-*`eB?6oG9aarl!)t$fs%- zO@EK=!{Y!U*PL8Y$)j}}wk2sw{ES(_qi?HWX}3R~LmSCP!QA&1`$9V5v-OUh^58p? z?(bTA+-@}$x{Vne4up6KkDyl~RLi6kg!v86L)fZj??yh0jNsX2CgI+SSB#2?=Y2O=6Rji0kODWhrrwKa zTKy4v?avWS^duZJOuox_vQbw2`Fa zlS|pF7jR^=UlE|MtKnv@Z#{XF7n?z2?V4L^l`aI~M7 zt?{di)Y25DLjw6IF!3R-4FV5Sog(Y&I57=SiTDG`WP6(J#C%Ijon6`*=W%|1#WVFL zkCgP`EO@%R6OXIy+mex+IIN@SR-&X2e2;naTpzbpNvXk*?Wmz1Mq!q@?Vf5Qs?T9b zVe!X3>Qojxr&-pkzax+MIcI_sgwv#EI2VMV1!!MJ?B0D3$QHrur&{QsZ}MWQULRHn zZe?U8D#~}6>&;mG^zRH=tDczD_W8nOJxO=IcKmw_qb}lUeBy{|{+pd6XUq$mnHp+6 zPT|7Y+fX_0@&z?v&zz`(6JIFwoC%XgK69oGwsEXnoz$MpcApiC@-Mf@Iv--1Jj#1Y z*W1X*V3pw7ov5ZG-o?;}-D!W_MzVudKZ?OYvW<8b1!^cx{&aZ&m17)5yG!8;e ztNfZ2J*T6AH!Atap?b`t74kI`>PbSV0u(g=VKN*m0I?NB&eXxnBfWLb(kb;O*2uB5 z?Sg9V*z|-^=b_V2*u58x`*}xsxwm^tOahow+26YKqkRFd_l!4?n~rQtObk!M4a^TT z@{w9+$_s3Pugz5wJ!QeBGe-yBKH&>|9SQqvzfoFTZa$Wi;-C4LDR*K%TQs4xKELP+`=Qz(*&X_2ah3C)gG1tY3rMY9e z*mBIY#og4$4h@483hH%}3i1oO^KL#@pwaX|of`M05AmifAJ7#b`XwEbI>*IL zwE#`w(;1k#SE2ZlTkhz*o6T$`@FVI>qt9$2zcHa8#J4O%J#2qkhobVYL)oUu9alqf<=&LxrpcL6n7e$r1m857jrA)-;~YUVIqVWplpwcXH@olzI-|A?t&_2B!} zBvhF~TD$r5oRPi#ZIr9hk*k-#|9j(1X+OV2RN3Y*9a~Y#Sk-Q`fuTu}dPqu5i_mR~ zaJwr=p52udO&N*1hRI~`CmUo7WzFN_J>^t5%=eHqk9Rs7>y|c~9@6G{Ix2Ri3rn>uB5z7Q}y=BQq_4xC^rT&?^RhU%87(O2Yh zPNAK`2pvu2{VmBuBjlmaYho!|0 zCWb!;MbY1D1|vvsTV^P|&q2Xr4(^7wZs2tK+q;bf_^ad`x_$@>tGhXWT=qKzmTL^q zcU3QSXA!A=&?#3gYcyqV;m*f+mV4Su`}tr1yy=MHx89`r_hv>=&Qu7RU*y5F4L5G? zGJw_uz0TFFx}sV>kd#!6I$-!L1l>qv6y*oxtZuM&n)pSB6f|~S@t)eJb7N&N#Kj#O z&&A*e)zpl$U1JSwFR}02a~wQ}dhEa~RYuh%Xhn`@gt!i@0ZS52 zHJSs0Jj!~yU6#v|>=fGj*eTV2>ZRj9=PvIzMo@`DdoO>Kyz*-_sNzf-t6e{B4B4AF zD4gawcu}q~!e_=3x01tBNoc-!EeDaVR6!6WYvehjs=OLcyfc2~dvU4Br^Thg9xW2H zysgF9p4FOw_5$41?6S2~NNT)wVbo4BN%(veh9fB*V!!8$=_A?MM&1_7l~@9$0tX?QUnum1hcZk1`zuQqF*Vt?o6zqWP! z2#fek#}xG1IO~{5+D-5_iOk6TfxHMxEXBAUd=JU!V+aneBOiC~O%_&oTJJo^KfepEGFvzWK~ z8Xglrqb7!w7Zq~9hTKFRiT3oaAInQX_8;Ulm)uz8GhPiLJ$aY>a^if>YexT6v+y|S zW&IGX(1-KoSH6@4+iR~Jn-wUEwgvbhkjeL1*+!X+O9#pk>1(S$+?{Zq*eO3e#9z&E`m^HYZ85$kXNSeS*K^I+B-S42*8}kd0;!C z1l9~=XjT9k&rxs8>&%0zF-x|*F%(){G`7z|1_j88xGx^*GbMZOH}`N&7Zp?*U8rka zq}Av^8?Qsc*TW(=mq(9HJe#)9TSe%|R#BP_T(Z8KdGc7X^p<(op}WkPsxXAlOPR^| znEG(zWL8-7h}BVI{!jGKFAoMBqn0C~HOZC+cS!;>gg@{)#2uU7AkQRr0`D|N&y-a4 zQQr*@te{*w5G6?eDZUAPx%h`lslv9To3FUEWKHOgDoH>np3paw`68{naQ~?n3Fz&g z40f1p8IoK1lk7`UZcLgaF8j-`Jf(f7>k&GaEA~KJmZYS(KWaY5xR2tS@G2PH5OeCK zluOlhni3259q;lum3-e9&h+2`J`&(vI#6C4vaB+{OKD5w>Qd#;^fDKpVH$$tVFR)n46>u2>_f~}0dL+EW@crfzvK&Juv_V;>)3kgLX|jvlrV7( zU`?*`3P}k{r`7DrkG;6&Hckg$*!)C6-H7FYj6|rF-rb|$#=X$JiM_kw z+=8PBk2Hx#Y~12|`BYA;DfVthofQ)Ei#bi(f-5CGay(I)2GyKLeT2Y3@td%b1boO{ z!R-a7mSOgfd6InwYhYLCU3*#ip*~1XC}GStW``0PsK`E;iHvpAEG~Z%q}cu3eLqFe zwh*<|-r0G&FinO(8J(S1;r}v-^{_B*zmlA-(MkoL{@LHX;_pa`-@~2Cfg|~W?(qQ? z3E29^UAywSFCya`6#4aDO9t=eUKD2YJ8N-Qt+ZK>+(#C@%hu2XPMjH`V2Ttxz&~4u z-W;nYy-U4C?@6ivx@TXU2@Lq1F==!(Z(E(Mo7HWCa=DpQ0qW+U=#UdV9b7)lu_HW; zen0~il9)GJhMqayj=D3`(dIA7`@G7eVfED+;f?F*41ofNp zY;+0%$q|>(2s%96*UZrN+g2YgYR}&Jc+}C^U0v)|<_lK`!0@)?TZ6sizj5%25C%5; zwF9~(>U|3yv|6L=M#~tYLcbv?IX-cX8Lm=umi?fQP9%T2yuqB)tP)b7cQ1TSCnh)P zQ7xcdaAOtC5Yo*y(Cri&W|`cN3JD@#3h%XRZkYEn*a0B@g>R{-)&F%fgj0Y&cQf{g z9U>1o`m4N2qQ(EwbDzO(%hl48fO960OBN%nR|$|Z69cgS{_QJr0|#Pv-6{|EncX8a z2S)Y&2U%|!7v&bU4`TpF5fEt*P!y38kp>ARB?Re4K)R%Rz=H^afJk>qcMRPv4a3kw z!;mxN5JUVop67W!yzl(xgTipneXqUuifdhKElD-EarU2y6>$55gy`dPb=K7j&Jw*E zio}91gZ9B@a5lm3J;@7_95ZOaGf7D^#k@%V>3bo=hYAw(%ppO(9$q`v|FZ;MK^eJq zVettuznrbG`E+6f0>{YdY($`j?O0c5K|>Z)QAN)gycIr8HimSglElthd!GoUc1{nb z59y}bpO`Hz9ucJ8p0@-+wBeB_XzkCXM2`@4T0f~W-5Yv>|Nc@Ve5k;9=h;NqMXl4K z`K@OIu8zk-RhAADT&hQtV#*4R24}~~pf=5*j6GQ=KkFHj9>Dd2+|_dn6B2W^qop|o zYGdVtAfBGc1dPO-+JH>I23SYM`S*8gAx%=~2!l)YSEDNbmZXTB%>3K!Rw7hWbL@rQ zIx;7Lm!Dg8qATB0{%T-l zJu-YTI#4rT6^J=G&a2>c=M_9~DI0fBVo+{#Wy%q`VuBFGp zhk3^;>oq>Q!@>B;lOJWU7dEZdoq1*?m#{THO)CVwQ;@AgEFwg3ODLUa>Y8^->5M#?G<=sA1 zG46+n$Tu~4oV5(V@EuX*mF1}8IrfW`;+?cT{`cDiwP1Yp*46CqKyk9H2v)p>a>#pt zpsR9}G9K4c>eFXF;gOzLkrQs^RqJQ9jI`6c z*r>_fT^Mk33Xd0!wrbk%e8qh1SX-q#GaY{Bycc}+BP`sr+-WgKm=coUWS{xsmS5eq4j(6{CLNk>yZax(fp_`P6Sm(?DV&z{L)VnyL$&8*!Ti}P?P<% zMsqfc2{>lrTVCBiSsDd zYk=)qj2!IjF#nO_37O&KsF-Mm1Ep*uJ9L)-0IBs)3Z2+Wh&Tv{><~#ssZu$~byQgi zGKo6?0WzEr8T-7jk!C?+IU*jbdF^50C{TTQewb-_oDRIpCQs+%0ag5z+w*ck9x3rL zR;DIfD+YrVZ<(%iLbobWI)@dN)B?qFnS9Ju9KN47KD|9uC1A65W4HqFX*KFNKg1km z-%a_UQzz6QzV^H&zczx{zScb&{c_v(0z*tj3hzAAo7np<<u@{^5@+$bhhl=^6DX`7x%3lgWec&McPZfduj7ZpC-(1yfgjCSCt5vhZ(^?km zo{9;7+?U(v$ExVKYJapg*=uJelvWU`z7X$7Ug)^f&Q@)+jsiwEF3ICmW44#$ao~Fq zr_zd((}QmmYgfUm2B_t$83rRwyUx&LSEJ3EO`xiuJvBuM?yt;rx+RP|i9ifsjwL$z zdLu^L3w}(r|B7K3*RJ86GtEK(y0SQ4ygx5jZ1oCzO)XY9x^$HAtM+Dm{GXuMbMs5* zt$HRm?pI`)XIrmC)FcfomKN7PdZ6SK)D-G4Y$(3s<+|O2Z_C++_dJqbW0pgNJNvD zFq+r*>-*EQ%}V}!H#_~ofhksYM$@g!U9hpXCr7R4%b2Z(9*{>uP;x&q{Y|%?b=K?M zK4iiMx=LF{8Hiwsxt;Ie9HNJ8w+Qub;;g5}tK{)G6Ed-y%f3VsLRN9)dhnYs(W&&! zJF!%VY<{lyRvXL3HyHPiF5fD3jGT%Sx}Kl^$=fM7Yr2ra+^q78aSR)he$UCkaF&3p zTPNBV?A|J3hq_W>h<&qsq#Bt=U{S3p`8LdTB6|;oB zt4h9?JFV3r=#^=zb@S%Mz%>p$dJQkv0rgcxVtiH-W(TV1MUS+dZ7x73g>R{E)F=g# zu9C(69Pw^h9IIrP!SAck70yS6=KF^u^}yNNUgo!M5NuFM51uMN-isZ6G8)C&QFmG^cl>{TX;?2*14ItyzyP!op&;Mk)CA5xzSOpUg&m;NhpRoqlUlxq<^ zGzE?WTlLqt#KcC?r^?m)IO4RD>EiJjXUt0McUySw1F5l?;3CQwM$^Ik$2$P_hq`=z z<;>xCM@9H&jDh#VQ*TC&xct-s6-obN(}YuFHZEU)@1KHw;g+iPbHWr*=I$Xh?m zwm9fW9CNV+$VKAZ!)^9wp?N}<3hEq6mEKOW9Tj8gjjZ4rX^K}k%39ZVE%m>*yzzvB z*Vf$i;u#~rsd=0q`~B(Vg~Sv`M26!~RjBK}%`k@P@;R4KtZQ`?XNQ(Rc2{7y1*l`x z`ZCfaCw5;hqC0{`tgs2aXm&9|3n$bkz=1^>($qO_WIQOoEq=%S=!pNoZhOj?D*m~j zN+@6m_1-Q1o|x|jnKK39cx1Gju>}j=%hP}SNaWrR=#)R!3Vto3*4aMbIoEyErBE-h zQBYtFbc>~t#x7SjBe%RD_`x3*Z86{JmUj5`@G8#BH&!s^4CR)ud6!?1p;CV&Z$w!M z&0%ljD9hzF?%KYRe{<81K3;()Arw3jIs8!hYTp$x?Xi{BPQ=l8iFFO-j?EOiTFf>O zV&@ROT3n0o8{wYIn|hqu8G0k_`F?gfTkH!)Lfqb)(5p#p5nAz$PQXWe?i9y-8wdAQ zBad1DxU4@&edznj4C+IaB(s%r)4QjV0KNn=ySXKEav|}NRzpc@GsEgQFBNNl5j!fU z-Rl(wjhZrWdNk8vF+~y#4D?pR?DFljNy!J+y2 z?PgDv;|Ala4>(zLU!ME@l3u}s?H*nJd?0#X{7=u3plREU$KWqJ+hz-YHMeg`+ywT) zeq9Ifts=mm1}Kn;TXu{5ooI5@`}RdosMLoxpvHVZ*UYr?+R94YNUMBAh?~}Cfs>|Y z@|RSloXw?9hVvuX(w8kjDMsb-#Gx{da>zSy*OWIutS*eUIOk%xSez$ypnU zc%*GOD^b>qdN|Le{*hFaGb+K2Ew=8?Dwx(&Azijl5p)+@?|=<^aVfQps{Z00RVlKu zDcadaG+gwl7wSMA5)(LtW`qQ&>qdXI*f(^E@9+eW1Y!mMH3$3AizSpU1m+FEKOyr3jfHChqCo zG_uF{aW6k8OpKFj#|J{L7EfZbELq;wx@P4(%gK4h-1V9m`29v#&uG26t8R6>JiH96 z#l3p@p@HXj`fv$|G--1%^Y!kp&*zR#a(l*p-~PaAOP7=+;^SQ~mN#9a2y#Y1sovAi zE*pML6zP|t_7YxMK5p_1Q1Rq+;&pObEx1I;#0?Z4;3~^S)TcQsvyx8{gAq-Hx<4>v z!G+ORbWX=@9|+|8>TJEnE#^k5 zwl#*?xMLF&b*buHNzF~r!BPwgCPLl#LYTYu8WiG>_ z^2#bMXF(=r7Cs^Dm(0W*qmYp~Kpa9D2!QD!!e-;FXur)`jLy^~cnj5eo@f-!RL=Zl ze(a{9z~FINW@b}KosKlO{5J6y*-jYumCZ5wN;lj$lHX- z0tkb~**nj8r^|pme^N*Q1nD_XyTp8*#SXhV^%kAw_L|=NYISR{AO1vf~ z?e6)W@rYue>rgq$6r{R?WqU?Y-(KAA3`-4_Hz=Oa+cAF;Z*ixu*5Cz9;>HRy^63YS z0bFIB`#~|!fTvh=dU)hWUJ!a|9RH0+t(~2bZv7?myI><7m6Jy6eEe{fUhz~$1w@!r zG?v(&GNQ@eH-(>Ypiel>GqqY2yK}G?ON>^g4Qe_>^_S|t5r!muNcX(hSGU?~){A?d zq1*_2O~VFo3{l@FD`y^F%oCSrU;S#^Aw9x}`Xb><7&2QE$$oscC%a?E~y%sE$D1!XvzdSES#FA=LcT1+>e z>G^qM*tK0l<@ueFAxTNB{BD!FRfsI0@j$)6h6XE@935Zgfx-_iRPZ6c1Cyr7cf$?q z0_>f=g?$!U;XwZ8`2--1EW4Q$`~G=j6Xfo~ejZz(8(IFZ!hYYbFMw9TJdbs$sSk-7YMAFL^<=HU^>;5fPK&`7`F% zr_APtDG(R{aAH|lbGCua0(Lo)%*MF1y_jt1?!A+ZA-z{yr zIt-ifGyx7kkTd;hQ>-t!?HRjfnN>~%dPn;e+j`459-ZN6Q`~xxZx<4d>nboTo_&4n-w}u0YJwc^Ft};W zOmFS6v)pmW$N%Fn;(1SUhKSzxxNU?^%y(&R8Le5Aveso(&AD@OO8S?!^35z+MzPM@ z9hpAwYcp+Y5nmV1UfB)bS;`!+cnG=r1~6RBmf7K?P3TUo`Jcide0~D;ez=LRnI`YY z(e0%Ad$i&-kEP#}Do4?JtO>>JDF+Y};JmC^G9YR^>^<%M%xw=e#X9a63znZL3ErOv zjwxbd5QbNirO_b8mNIoTlk60j8h}tz46b(hytiMXlIhVM(yddb%{i)+gzC3Xe8b~9HOC2r?D zCX4l)aErMzjRH!af^i29q_qk9laXa~bOeCnsE*lRpQE6(IhS=l82c=hYkC?*qm0!$ zterniqi=9RX}jL>ljbrd{$_z%+{+gw>mf0j4%e&!04Bkj%$bSN+qa-mWRyPM2M^%O z2VVR<+hZk;{u{5hzIRv@9d0PT6zK&W?Nd64H?Jp3VY4+^^8Xb&M(8A0SO|JA@*qPd*PC1QCrC zz9ko2>kCzhIm8xr=WTvv`i2*2EmQIXUPR3h<9R@6sx2gjIzmDd`tUt}uUgokw-fGP zu(M!lF}Ku=`<+M}Foz@Mjn~@_=^xc004PjA83~_u_wuHKLFDEpr&osW^>(a~XUTkZ zHq-xzU}99c6zxq{cv!pm;1cRe)YLEEf#;VF>vRNCP=5H2r2LobM4)Vl!L)(ri!k{= z0Lhu(9grm1E1AkgEbM)8Nt_X^eb(LmRZq;#8MXxUC1B<8pEoyOClw6Mf7~UW0{60D zZN8I?FgW#&Z;ULk@&fCnJvC{2X4jiJ6N?P@D(hp5)H$RvGBwfcfFXpi)tjyG%zCe| zR68>>gAO96{r!?xE1772B0JIuU{7BYG^XCa;Nf8UkVj^%D=ed_G;}xGE?Mv?W8?g} zWFk=kkCllDn#%FQTSYI*KO~S|K7eI$`pcZ9AdT0l=DQ$>>(0p>(syeL4Gnb^5kPnr~$QvA=M+xkS-xwZez!osoh zdr3ZO(%*~+Fr{LcK(T-1%S&GtsCQbPm&zsUc;qD@2;QAr4*0{~i~vp)x%c*&+mVlx zJJZ$`TDkA8)KgYIpN($|AhYa47Hv9>$I9fL!H%BV^ zhln6~ws8|2{v5?){bp~-et2}^n!=r2*w`OLK~RpoqMSgJ%f?7(2!L-9-sj!@Iy>s= zj)Qn0>A|X5wrOwJaC$!Cj|eftGZYcthjmH`nw%f>EEJeabyQm+Kz0D2(K?yh_yd6} ziplW7?q2JTA5uE5xnF?6fOpvzGt7H&u1oq8`9Q_)o8nW}9KFYm)EEHz_={B0nl-Er zM}19fiPpy<0OI0Lcylt^;x!t4Tn2Vbj6$Kg)HgEd&;xr-dJXA`(=LeheZ9GdC}0zX zWVu{%afYR2bbCEU@}bXe}9SYD6Q`x~C1GVTch)7RCd)E*dsB zf(%z^f+MO8ss%Sxg_VaThYPui=C2!>f4L@Ctzc;xM~mZ;Ii%LBwm<))dI8SDKI&%L zn?YiB7*+t(4)__71ku!cQHF=eLc44$EelPbX=-&>bM(o|7Xcp_eJ3>`e)ZC-3Xn0t zzeVoUdI5+3yKP@xc(O(Z%r=F46_9lqRe+}tl>TSugZ`N=;nFUz5KPKs)p^$+pIbTJ znjPHWKYDp;af!P3lB+&0*830_rx<>GWc8Wcny(Jxjm`vQ)k5N^dpk1A&-C$AXRFSq zGVz-mChQlY&{kFJh3R`c6~6W<*f(;4ZgYEiwqp&o^}O=zPwFWJAcz3ZthE z5=j%y`qd5?EWZ+i0AM8#8|s2&FFb8oe)VR)<>_|sKhlH7SrX@#_cR47tb5d(Ejcr+ z^M?x9`@(Q4a+s|wUb{^pL}XHa&^;6=bPH&?iz(Zq1}uVpeOEM~t+7-TzlhHgZS%HY zi(csdQz2G3Qp;BE9`wX1-Ov3V~+8MtK`fw1*xLelXYcYdT-ax^o_1R z@Of$Da#^XqiY3Q10ATiwXNv)q&QkSeDPR}mX|@A;ro+_-li4sI0OSbAF3WC%s!}Sn<1N z9VR>xBzr;B2tvN;ax~jD)p@mN@H#mvkRMlWzH_Qp%)}VcT76F!PubN%j7E2Ak|=er zZ$DgyNm5LocNq#!-UNEM8UzR_kS|q4gN(ltqV69F2po=gviYL#)%*Mz?X8=!W^kdx z#C#KFKs0$fVteKBuRz2_5u8~cQ|JARn?Jxy{z;D17X6F356$+-{ru*bgHmc? zfl@$rO(z{fiCrE7tpAyd{sFxU>vK@ft23Uz`TNWor1tunEnnL#O;uI+Ge+h zQgr}~^N10U-_VUZyyupiXZqo;4}+9(GjIVBqDkyPPN&ZJqg!(=!-VR^w2`&RNM@rO z%(EELoizC$%}UzkQgdcdB7(7eArg<5RWLXxH9R>rT)*0NuCAF!M^>?qhX2ACz`P(O z7(5l~q^L81!G@LcIwhDj>*3su+ER^ED#&;l&+ri}_F;(l*rbTpp}1tjc>!4LIOcH4 z4#Q>E2y!bvvIvkpd3yvnIoM98=mzpitVl2|^5Adsi%fYyV%LN&bWEgB>ad;318Vq&;sb{SRL2Py5q zgY>Y0m8A3g1H?CgFDr)SN0OA99MaE9N!@lXFC%M9+v4LZrQ1?t)lR3|JUqHEPdh+J zyEbj(KH+e@3;^t`1Rt~a4|EY0IAi1#fT`WymCFa8Y^L;?KzlkLRaIGcp)Q5@-)O1e zGSma~2YL1&JGOp6_X(Tt-f|J3&^h5{a5-!+sEC)AX zPImFJ@PZL3r=euP$j^hG7YWI(1s6L3Xz!UZQ3}ifIiIyXY@Xij*&&7a2q)@K| z`R7WPWsD-crz=&fg11I~IU{EmLws#XBC7nmJWlX}gOW4l!yRDN{mFG3^?x#(^^EN7 zjDEJ=T>(=W8NZhe5$gY=tU>0=16s1Gi>!mdKOAk~L*XhW_?YhrZ)flL;NZwqd&w`~ zP`tniPO^xbFlCaBqcvv0@fW#Zb)n%JndY1CD`5mp{HAxH;g#$vUIBGOWifJ)e32(P ze8G-VqdYI_R+Cw+p2k~{>fsJK9UH_P~){PG1XlOdw(-;o*g|8XTT^h(PjbAKgo{@WZ z+cj!cViqyCNC3o-?~(u*pTp&vGO52Yj$+k zIc=a4g`9p1)r@>b>?uxMkOL?iD&*zzL);H)H_5yfdb*Wook#0B0#7w9{4^*C))9VSj zfFKq`pI`}oEt|kpBc-CotB5dz#i-R=y_&`9jh0wBLLCZ+rurD8{7o#IbYjCRM+*J; zx`ddmro>MfFR8;$XECF#b1IU*RA0eSQ0RvPL1QDkn0W)Xf;Jyx>CWFFvezW2%6GEo znzki}B~<%h8r<4XkhZa(qMR$Ttvxm<((!(`BAlwP@jR-C*2|lx$@5F7esWQ8-o2Ku zdx8a&r-+;4?g2Ld|3~JL)pnunj!NW%QPs#XX;UVrfVu&{2_>|i6Y@L)(F~b#IzQC& z@Bg8civX$%E2984Z_y?R(hL-*2;Ci3@yGm>)5NtoJ2zO%;10~n&y+K*+VUns})T2#{Uni+$$LvcO~LHq=k8mVJTv84aEUH zl7ytd7g>W79KJR(`RK*=jQegiZvM<`|+|yfYIaE(d$)S5_(@u!`}H zkPe7Y#Wy`~({_E<+c=<1@jKh>dr)$bksVdKGTFIpbfIrG7e7DN*|XF9<{S%+2fULwK3PZd<_wiQ8F>=cPkXZH>IEhtmAgCSK3dvnmm!f z(-do%GT9A0xM{`DvR(U%do>o|@g6tIBYz zE#nfMR;EF{0VptXJlJz{@}Ss3Ul67(!kHoH~|O3f{R{D2IncR$tS`bbSE+z6nQTGP3} zbp98Y5R zYZXa6@^rr#0+4E*dkn+r)DrO3kki(tCg2Tf#kA9<{bPKjMVh=^26C3^4Md#W5ktu` zjU}~6Aa|*bBE3bs>AT|Q(ywR=l4h%3uP^ZF;^%ycY%Tz$TyuDQt}y@)r*HZKr>WlI zF-zZ~6sEzE&(+Fo|`;*0OOis#Mn*H65!q{(>FE zh!1Ttbg;h+_A03QN+$DYbLC^L=X=;C>3gwY1!}I<*{T2zp9Y&F z2t^d{ippD2&Hgx6P}cV|6gWwz8bw|J)|RQ}MDjQ0celV_l7~o+#l%juA4BC z@5FEb+4uPP(}g@IsJ&qUJVXe|;4s7}+0ktFgkwgt5H2gZlp;em`D%Ndi6l=s^NU@; zjpytGnPuP5wqz&KVdpd!viK$`q7)IVgu2!!!5m=H|6D0WuvbtC-iUim$y@*^Ojx6L zzyV&HSPO(73s>#;!WSl7h(YLc>{z`q)jIQtoM=Pas5KvJ?e^8hZWW%M6_#$JW>Xhb zQ@=vQ0`<_YRGXSN>a12YfS|XN!CY<8x>8pNw=Qk_tP45L-H_{tjB>c0(N*kt5rcVO z41CU|lz@8oQ<}Pm60E3riO$w37_$)L;U0nwfLzx93pjshaRKx|2lNsbN#68&KnCR< zaaw6!ntBgScM8|5)>TzrUFY%rpMW8lN5no@_k-pMvtM}{h$fzxr}|bctZAxR;h#+< z7SwB6;M&i$qLWS+j;uf-NxhJ^hb#N8>I?s+~-0{@ZEVGQku;w#|Ya4THOuv(=GAui(MH2_w2vcsUjV%MO0|i*xLhD!8?!?cwP5()qvmfDmJ6`tY+xN2(MBvTW-rvqPWp9p|kT0s_NLt&1?yRAwk%t z;@M_zy6TW%K%vV|fzqSE{3<0{pW{`Hv1o0Nb{3dj*!U1?(zTU@HAeCq42~q?-3QF=nLOq?4 zy|rQ!MVFukb8eFyyW#*yRd@BGPPS1{#?eZz)?;zpG#Q{Ms<*Lnk#-Uw0XyN%2Wd@2 z5EotSf$SbAV+B41$m&RGn0d;nI7_Z0Lb{2-?*i|LjC=FF;N@xpWsV%!AFpgy@j80$ zq_JB}^gE68OS|L?>T0iILk!?J-3WPIV)Pbz+0@$9)L^c!%2#tfSzafUTCIf!&7{2O zJC|SPV$=uWJUff2fR?|iE`N3GTw$j&;Q|26`j{1i=a8+o7$2c%;=_vSs#k7~r8Wlh zJBfKNaNv0Z(_W<0nRiK;pqbC|fAEiML?u(Y#&Yi&A z_RHj>=lEnrq%97zL-X-<`RrfWFyU1iPpRzC+G{meov@CKW`}M?Mn>`%8^&5=i|J-$ z!fEV&{=&iO@~6(o^7A?k9;hR}W(b=kQn=9{HKq4)#oa`=$HulIS+#X$eqim|FQey^ z=W5rw{#<|^IWauh+l2`bEphR2$p`%4Z)PAtTSAYp-CCdhz4gdvfJ|C%R z72}7p8%$51ZqHY19=XrYiJ%n|mR43iP5!#KwDNt~&2GNfAXEAahl#N<5&cQQZMjjK zg|t>6E*c(pi{hPBU(EM6n>PTr;^xR`I(E{M|NV|w!zB`r4(q9rYXi>pKQZHcBHdTj z7sJ({M&&c`XUvU`O;SbQ%fIVYP^zx1sw#8(%z;F%8fMA0kMrufI(&BEENut8+Ma${ z^lPhMp^YYY#)uy=XVQeyHVfn$AuowvB-eQ@T6A2{4z>HMJ}`!DG>tyiyP;$i z6^m4$RtjJ!pYtI~UpTN)uWF5QdV0Ff%l)euq`~-fw8Y$3^CQ+)mp>;bM^{(Z%M1H8 zfV|<*hs(o$H0t=7BG=f|bzVcf(z(>dnf`3#-&KZiovWh`knXgyG__q1mWyg-_M}Mm z5Ag!03v?_{>44A!&k=&gE4dpzbC0SZwhf0YxGb~_P@h49@R}p=E@e!%>(fr($Ca;^ z&l4wlZ{TDXwJ4Cij4IOQ3y}?>D9Xr4LC@5iZ>=esa@-&2>9LrpLVP>gBBFbJpXPxI zmpJUf8_?c=Yi)pW^tWY&*D)$aEffcbjOh422X8))XF8Jh%E$Y7lYth+B?4RrAD+w(pBsAc zt?h7_068S)eIhPdcf37SB%?&)akAUmNq{8O*Zi*Xoa`1pAs06{=;B|X@nT~3WOqI= z<@I;6h|61e&zPRY$bJDAqv4j6j|54Rn3$xKiTqlkVtNsStI6TjwBNQ@d(D9Nd6ak( z?K>d-tr+(?j4D)~MEX4$KH%=xSPB=y zL`#bt)CxY>+w17$6!QK1RD-3-@-szvmHl|lmv3|1bPvP8jKqr7+K^b@!$>z!@7~eT zAw}RT`V`ny>$PmeV4b;`q(a2Y;)eTSa$0G(cCwprw zp!z~(wKuuG!F{3R!WT8idpU4tZcg-+cditY9CUK3ZZV&3qNAe&85o7Z+;(OiR(9vz z(6eEop-?FFhy^`Uu3nJdZZKGKu#HTKj)uDQWhV=}e*JcvO)6ibh|j%e7$xGlHX({M zblOq>b0kEW#Yc!Hz-h?^q=Z+=(hA!=#u@1aen$6__7N>Cxbsyv#P59MdBFi(9ze>) zF_ap8LTLG1@~IH(CJ?{mZ?B;gMq?wRk=0JSM84uH>~QP)x`mtDahvPOVEx(Y02eRs z(axP^d%flqw~1OO^BkX(H{N=Bn3w|161_%G)Alf$&<&67=&;&f1xhF z?b)HI4|Y{kT28Ka<#=Ai7X`kCEtXTi)_bGXA8X%uQEaEAXb81*Hw5bU+uu%80DpYx zAelZrdD&gn->*QjF_IZ;B|kLR$ZxBc8XsS~9By0E#K(tz?16Ma!LvWwH?pU zl%~N%BXPmd@Bz6|(2QSag zzzEp+#IYhTVt%*dg@wT8^K)2PCSVI1j;BlHOuKBZxXtOQO2G#QIE-yi8##eu>-dk? z)p8i{aEBfg(4-gO;86LYS4=!$%65o^*thAERW21lJQkC~6GKYSGCPFlB{^Gg&v;QH z`P~4%3md&=6krd7@r_r>dwI3Bkm4pgMEOQ{DrFUVn9F=KCOVpTxtRf|y`xP8GB6cl zIawMJ8X6iIshTsWA5)~aiduA7U-$yH1=(uDa#ypFnORIiLLKUOejlZ%pfG!Yv?JNz z|CrX;*f>p3cDM5|Tuebxac8WyFJT@`+?nbt&=ZuGmj@!GoUXjET+A3L0kz?VzP#Lz zAHT6B_Hsq*?84eUWEyfHcWg~f)r)kF1P_`@bgNTT^3F|W#xq{mXG~;ce1H{V28_DD zua?^+0TjL8NxPpgGD`l&UMUf)e;A+${fAi0V@dK$vZS>1dHF6giN_JNESgnwT+`Ne z8d{>!C|w+ie>u$nbm!c}al0i97-L7&{_d`~OTRT^x%n|FBdJ>Fh-PQn?S6zJ?F2Iu z)9Q4+Q#S((3kwAWg+yRuk|A+Ef` z?uX?h-Tr}rKthJcjIo^fTFk6 zv#oJk$rYUuv!LLft>yXq5nsQ41=FlnW{bfHDqSHL)Y7u5Xmh*z@h2aT4q0H>poHMg z@QJCPF`BjEnOz>7T!JLU4z$)(&MlNlD2h zA&<9`I?cmfot?bM;=APMTkrx-!R()F=IGRVr4#{>Ysbt}r|M{HZ1)8Z;GUp}5(|OzvmtEY^|C{t zQ|i;?&o4AY3jN5n*nn54Q2uZ_VH!Ge=ta0~K6NBxxkEc>{W70slw9Y+`;eBDj)RdV z`)6=atfnBz_mB|Hdd;0fMflxnxh$0eW@Q^_p3k)w`~H7g?2Tl)4$z$aP48B^85A#0 zGV@NMvp}ou*(;P*syQjTpxoxWIy#~bFc2i-yJyL8TN@)<+IC4?y;oNfYBgbb@isA% zIjlq*>e$lK3icsjVyGzQ(s4OPt(kz{Hc}n4dN84Yd~9k$Vxpym>ce1z|L+p2Uc1GZ zryoX@cP@O^KRT;L@o{8kW)NNZuUfxrOvphJ%Jt3uzcFCnu+Xw-Mmw z#*3(|33(C3HGzjSEd1X|K6Q-G_>qVm;$K?k<8-Cw znJYcQ@oVa^HAuRcG?j~>&>tf-A`d3Mav>jIQ>2yZn4b1T8wMsNC5=_p`fQE&EJ{dy zI>;uhy*UyU6{T(H^O#ZJV0*esAA3G%Y;T_$7e_^Y^cqc5l%D=rC`v!eF?u~W7oV76 ztVmZWu$>?a=*l7;s3=go32?T07xW&oIGJ&Of0ra7M>AOVh=w;+Obi$ZYQps8RrxoJ zDmh`It10_=monAo7ymD^2&NE9VCVDx^PO^!6V#KElBJ$L z6`1@7lom!&{kIPis6H{h!+Fm2!%Wj7w9igfv5Fc^qvs%++X7DFd!d2D`5 z>=_ss*ekfRv9Vc?dZ8iw*hJcilAPbae`jR{h(R8bIXjHBr3T((cgHhN&wchiI0#&C zI9A5ODJV2_Ahx2Zth98p+HHvKNgx_=fUGbddd1DXyu9>2Sx9iB(Jkh@u4iuUa?8Gn z?emd-GCWUTMsf|pFU<2)GF_QU-4@61LHmDpob09>p!`l>lYgsxypEqfeHtViPA|g2 z&d$SMRb7pqZtP~ztp+~^5nDA{{z9Wf$Ke=7M24X zTO9jCn)5!T$8G^_xK}Y`j@d5md)NVNECnqs@MqO&`3q-ijFO2&$mH6;g(mP>yI#)L zzE7@?;!MT9&poxA{k=gf#*rktlUeU(H*_-8U5kl1KDw|QJZDue*sPztq88nchUF+F z3%j{~yz+f^!@QXVujG1%o!Ak81K@Y_rO#czJY(-$y*1lMj$TKoOhxRCTljhOHgmwL z#c;69QnDNP*lsuAid9)m^-fJqfxv6Nd5JBvyHM{UQM1-DV3RrLcrLZUrZXQU;^pCm z)zZFx)q1&)*$;nSVawFKD!vMGo;~50`gGFsAwVb}Y&+lW*$a#?=@#66VSCBg(sBcZ znro2i3(r=ZZ*cJnP2fE;Fn`aX3r)B{%+l~$1G7Y}d%X@O*=jLG3>QAk41JK-NJ6_; z#8E$qAs6#vjk_M_Fm9_Kk)VIfNnvAByUCwsjVW{fg&8vb33jAmJRprn_40~DiIer@ znO_-Ag=@ah|I{LfLshG3=*x}WOPv{~Eq#D9{DAwf=_F&Mmv!6Q+lCGLvGw;FYuB}+Z47t^b~Sznh=^tM&HH{{FUS#jU_( zR2lp>?H;Ss7mJgIs;P+z(G$>s?x*5dfd2+RI0pw5N=2kxJj7 zy7Tt>9&x66jUOctxb@r$CWeJ8+**G6(UU6mgSYG>@Vg%}-~>pn%y#x=<(e;x)f36- zx8i*C?6r8*yTY8dLcQ~YBDeFuM*yGpvr}WyG@>?VrC?xa_JDmekqP_y?c49{Y)^Oh zv0Uu}nIQu@VHZAb?(+wax=5c}9c0r=B;)w$fy*TjM5g*JwH!WCZ4eQn$~;Xb%E!-e7^D^0+y-0m2^#9C$dg z+C-88))(Ssi&pi2J|^8(xVH@2K6m*O8;ds=>ooyAxChVI#Jc=(q@|^mh|N^8A{FrA zc$^p)ck;(Khm9;aT=a4%tyQADn%`ow^iBIWm(4N#-HQg{YWr&YnYtk6w+6svciM^> zP!&ty`?TH%;&dDZ!+0V|DFhTkvgjz5R?*P+a$g=|33gE&-d~x;l?LtZzC$ZHySgUu zUj?3zD%)-4UR(0z<>eW-^*CQp9m*Tz)6Dgqq|259%Ofm3srCNKG(N1I8(a0Ze>DB9-_}<*^BSFO^x%D;LEz$n88-;dCAk8!#@gkvI89+ zyd?ZF1fKCF6M!n3U+7qvm>gj0(b2nkGgY?Dm}6chZ_>n z%=!Ajjo|3jPHWB8G(a>sv;)}Fke;ipJEtMN?*>k!)T1-8{4IYg&f{Cd^s&>5RLf75 z^SMMp*?-F+(BNELTn@tvkHIAS1YHVOW5X{6ZSNEI-x%c_Zdf}m4kYrc5u*_GTZU!E zAL>A)5*!+;C@cHf#YKJQ5eV-j_4cQ%&+i^3ST~cE(o+&vRaDRlSnQ56h49;HiS0GM zJKLlH4|{xnfWzBB_XXw6y2Vr_>Q-99D53L;Yhp~^naLIf2{n&iK$7l6G@7DTcS;ESqC_x*eo%{A16E??)i&T`4ZIOL6?pUrMMoZijqR_2RQr&V9%38#Bk`+*8P0oa)Op{a3~vm z@nX-xftcZSjW0Td&jWOszxS}x6CV5|@M^By1J?2e^d-~BViQQa!@u`Ta%G07@!TD) zv^==}(uU6|Am9Le+rP60fZ#@Dpb6F&cxSa-=6PvqtN?6bWMqIG?lE5_7b`y>FTq}j zaf`xhCA{zhIn8~z_mZod;*VCL1)6w-^g3Bq>RBot$AdeewBrDPl<|d9>J0u#KC8RP zZ?aHT0)7O@Yvh>*x@^HoBWNcM^y{f`lqGM21km4?Tx#jCGRd8P{u$0LBl?~&4c7=s z>0jMWFD0l$0p|%(?`AcT2P^Ul2bj`dki`uR@j0gjXqwOj4A^iq0G`BPV$)Ek?&4%& z$DJbOR$q*pQ^7=TgmrxxQBQidH zkzPfnLMCgBE=rBsnHw&`rt!+k$`01N*%$!`!_H{mcz_yt5(s=nh~Dl6@bOrB^K`4M zj=IAT05KEuT={GvD=Q}#91>zZpaT_h-JGq^v}a>0$Z)pP3Lvy2_>mj3k^OsawLxlS z3YOD3B6ywk{GV_%^1tFZth=0JdC=t4jI~{i;lEkIy>}Ds$yMo}G186~DZYEB-3%$3 z7FSDG_Qw42H8C*(&J*mnr7Fptdxbn_@QD~s-Ew<$3cv-Smb$->5r6({K+Bd5XoZWP zCqELyy)-wmHfLr8-~^Kj5l)oU|H|KwWf%0x!20&RWd}1mB|BzkXNLpUyMLy0+Rv8S zt(V5aQ5O!a=U^MD=Pq2e2Exku!@QOUoREVCjgF@kN|)G~x+781Rr&l$m9&$Lt)-7f zMvt$qQh9LF1VAC|e`}nb&8|QWkWEE7Ik|W59GsnboH;yq2Rn}E;!jeh^~Ekq7pi#+ z=;-K>94C*Fklq6&Bf=`Eb{( zZ&8j_g{i(onL5j74)in^*^R#TVU%aP$?XP?`2?fI={B_%3^ zT((|lS1r{~8Ty{WCzw>VMwoxa6nlA7RMYYof0qS;<~{v?aN^ki4<2*2h+}2VCJ*7W znstZwu2K%B#`6C^_TD-ws_<(Y9veXg1VKSSy1S&25b5rc7?75hMg?h*?(S}oR*+7m zTcl&?hJp7U27k}{yzd|1v(~rP_t!Uz#hRIO=A3iK-uJclz4x_kwtl-4t5|5@G1cyE zZ)?@t)o{?$Di_snkCL})hlCDp-K-}+Y1Dn`p(Dc9J_GSgW8(ZT=L%iZA66?l4QF<< zndToq<`f26fj3!r^yUf!H}|Q+fGDUhoz)wMUyB1_Qt!F0D?(+G#U_dVx_cqpUqe&V z5jFyxdA)TGmLAakn1njD;7W6v%&oJc#K|Y9qNA341%-u(4CDW5Maq~-Qk=T$PKHT) zT8mgP@R^J}TpxYt;&fZ@u|#@cU?BJu8y}BO#Pxfi65>fs`mdhJzVPxLlS%=(Y7|zm zs#InJaVStSPW$*V()nn$&fts)NFM?Fsq*I`xv?`9yc4?DST5XcR`7}0WPYbzg{BK| z<^#l|u>9-Lls6K)Z3*1{Z0y6iX;w{VGdl)i(G1#CnP%0yi{1FO&r>i+NJygSwKq05 zFTkSw4ABuFIshpvo(vK!_l6bR$)U@Mc>2G-w5qG^SUWmi?(fBhgSj*K?DAxBlpJ_= z$Q?|v;-8!J$hOCr4XUfCjAXN3golN(tjAkTPfb0z0zp@glmf|gYzFlMsQ5LqQn}Ax z$Uo=G=Wx@>+pqFvb3HDf>DQS8p1LJ?r{YrYiDjQ-Ilyew1B*{F!+S6@vH2M*@ARKo zIt;X;De@ne9H3c9G?M)@9w6+2@0)?hF%g=2C=HB8=TvO@B&(G*@VYK^w}|1@qNZT* z$8jW{6G9{&T(35Q;@y3vYCb7Lo$;^mwxx&Oo0chnCCL1${hp=s8e9;_>*k!_a=p8> zfhmZZ|2TjM1S4U|5x@?u0+e0R?+}3ZgyX8*miZ?L#;Ck zz!EtjqqL4jY~(E5reOu=&usuT+A1eM#ql))Me6MtMz;nt*hi}1O&mDXhK>`k% zT^+PR%5k9fA-nW^jc=?j-Wtn0*ZZnBA*QVsIt51aTC6PcF}xrd4B}ajyaRUd1X~2S ziM;$n2`2-2aG2@p@HtYOQhC*zP{~t4(la@5$g#W|k7f9c7Sz*2qroWrmmfzJPXZL} zQ0l-B2=i+u^9GD}Ufmm@JD%PGuo%&oDR#hElgnGgtK6-_Wl2#lN?~qNHhoA1L;zv_ zd1}QFBW$shw;8DrDbMbdoimg*fdo~k;i#RiXN?k!A09_$LfE0l{ zZ}r3>S^hf@Yl*P{E~C;$c9BP?6Dt#g<5KGa4ai)df4bj|Vnqt>;;Dsf`Mc(QYDiX) zJfaQymjH2x!e!C(#m+mYxWG)f83 zTIa+FM%)&;pCHH=m2<~m*eHqxB<6cMxPVw`#ABosytq;*7e0OjOmxZ$IdgztnN1zH zs8waF>@t&6CNm3~TlMbb)AFd)-dujwmpnYz+CN#oQpvV_;6fmr#GanWlQ{M_*)M_W z!hZMjwRI~z;2&tCTR#43I|YFlASWq=YLHMgtDXb)DIk2f%qnhdLJj+9^-;3>;R!mY zXoi7gvFuDCH3`VMs*@)e?f3ZR#7$NEt^ZNV%aS~x0z5;@ubtqY9{0H>rU%F)h-1~e z0Kek%=&z+lmaHIV@Gt)~%*W5l&4EiYwLrObb-5o;EhgR%m_6g?mqS}S6Mo{l+T%@m zLE*QW@@{3ugWaVp%+SWu(|Ev-z+(3V5{Nd~ej`Ewso4V)!SOr+kWbC@3XoCh)D!ZQ z#OqFG5w^M&Ei_KB|Y1@xT!VnEr^Cb%~Q{Wr&y2(9ptEcvX~`*Xq$S++YmZ~{jT#TY@ zV8JCIq!?uADbQpZLEC@bx~a3KpkraR{H1wxvI@{Iar&q_*jIIJ ztr{j%5mVdt{jLKPCw{I`+-b#^1?X%0&pg(;0Lc~@BIzKBU{mxaXP(BRZ{ZJ3Yd6%U zXqprk$}E>jF`o@LrA5K)IY1s#q7R7(f*^l-!g+agV{zs}prE!1x;1ZNrNqg}NxPW` z2u`NNu{}{i{(FQea$G$XRsk{RVM~ZivMqdj)mSzu8)``P7mL+$M)DX?LIXZ<%k#Zb zciHHKICh)e8W2yVRr4e|CL%T>!D&uo<0m77NA-ftOq+4>PrIk?=AadTzo?bcC?gBX zhawI5KfX=ow{P*j8E{RD7%IRF?*rA19-nM@(6$FVcj_LzZU4A^{zz+2EC-uny8eIT z4$p5i2lUkQYiA@Z^~IOpQa|EpoH|c(GD0fY=1xl0v^D zw+5(#5kf4H45GPwWO(Dl;*=Z0<~2!as!bO*SBqmg{@)X+;QiGf&K#&O7n>)o??2;t^jd}>d&xc7 zPdt_f{q;9)%>!5gOp)K3SVClieQ&6&!Lm;`2#}nEEwsrYgQbj#J5~RU?V5I^`R#kI zaMtfA@EQxZ{)?8f%PwB|6gtv}ci!Ga>Uv0~RFu$3pK&zcG7!*U zZZeDzXgb3=ipRY$BSj5Qr`EyLJmp@kg3skIvAF?x1#Gp21w9~jOygWR9VBf;N~kxj z%R8`o3!PjaD|2#*=*RDeD&`TQikB%{@JahD}0K z4}n0J`6}%=4qSX~#@ilQUHN8*d19%dO?j^{>K*EKIWD5*fAdiVOIb>5nw-MX_2p9n z<<3G9*{}syMX&G*B(vwjKvvXn;}3*K6YXlNR_B?Vyhw1OOHpz7;nrHbqX7u{BH2Ce zytF*5S?<8Xe8!iOHj%;6!nG6hLBA=yfP9w4-H;sn`m2%g}c4f?!F z9o^&07fg(^pKf+&C=W@YD?b}9{_BS(517bhbp2Jl(`lNvP_RPf;b_c&g)B^=OyuVe z8MmAQT-rtxUZ;^^kOj>+>+f>3*A3XW3@vp4J=~!K4oO&nwlgY(oOBc}QXcAe6M7Fk z-|ygOX$Wzb>k?_rkbKpdR-GN>`?GBwMwn)5oSv8Uk;YbP)b(*B1&KSq!^wf-TauME z^T^pE+{p+9*hrKdV|~1_2ly!|Nz5F1 z%gR_hY8<_r9Tryssa?bg9gVa_+Ulw$L2}H_wtN^(x6-=2h`;Z#(=rc%O6$ysK8UQo z+h~94{_eLbn$?NZvx0pRp*P_cix5}QKmtArOkpuUEJPajxi;JhzW{Fzitp_=$A?@8%w*A@;7g~ zTyYXN*Arc8rhP)f4iq#2?|kO*w}4Rtmx?2m$v?Y=$7%Z@XmxVY+Xk$=)IdJ3q?FI4s`(cKfCpTDfJ5%sBeF;lg6#)z}yrqTc@4x6TdzC(qZT7PP$ z5(*LY{olO?G5Zx}FL(W`vn|4F*XkZRCD4&vEbh4(-}wIFYg`1Tl|yYfJcg415LuP} z8LINi^S z@t*=d_{+lq!8w?S6xl{_K(FQ^sW+UvNk;-QZgQt5i)ylc3#Lz~=(XVi1#(oQn-8!; zi!8cKY`KwqpZ4}u0AvLwIuJMA)=&=NAf`o#k)Y(iN&8@Ja~)=~_kwNpb8)ee5zQXQ zvHM~J$SBUg!@Z;tSEL7Zlmrp{yqI{jkeR&#L$gKiPU=V~?3g``Epe?;cM;vVav>0;2Z5 zN1q*Q#>9i#HJl)$-pujuAS*VYQE0M2$3MKN$vV&iGiTBN5y%ns?JyRYN?=)E%Z#_C z&Qn`yP% z&n-Wsr|%IWqzr){>lbNOgIu=cy2tY?Z^vu>d@PYQroQ4HT^TJ>Q2?V)c?>C4ny)mj z)nx%L!&T6Wpk7K}Wi?>^|67bVoU;&P=2A!_qo`AS2>Z+9)6WZN!<`Nf1qIGPhOrs* zc8QK@{Gm}0NTvW#)@tVL15ip_jv)N{46woB7JI1uRD7^GcQhSV2f7ImM#Jk)*GBv* zBb{dZ7DqQxCM%YA;#-D)R@|yPYb7^wuiRDv6a<{cw-+bY{~8{&1fKSy32;>^(iU3@ zV8mQTgfyKtY8wc+P)?hUO`$sZG?uuas%I9p0^S z?UH*KixKEnfEpQqaIZ<@gA1VIW%Z~%SpBI%5*C`ORznVav>Sl$kXwNCO8j(;Br@YP zQxWf>;WYe8)G%WGzU8#E7FPfGv!+Tx?YlvYrqZ5CWZ6cQ&ujp#2mJdQ$M8*CSugsC z-11_JDfl~p{jKV?hALeHRzTj1G2F)GT`}scyV7V$WCVeAJg%{TL#)E@Xt6S})!!G^ zw<@JpDN+CQ$~cx0F>)(Sdqx8LmlbCYAye1pp7W|0Bl(Rlm8Oz!fXH=!*%Xxm!8a4f zYlM~~fJfHjc`Tr;wcC5ivIr7x_@)X3oIj)WB3h7Qe5Fi0O#thp3M>L!Up~SCNDLrf z59j~@45xt;oparZXjD?XH*SA;xQDKVE;RyhX@d6)5e4AD-up_9HxI$)2C!AYJYxnikBb)R20Jyili8Fs;Yy0%8Cs04Yftr%@)Ji&JqF-g^ z9k{rG;1w{85C#4xdqB9t2?$ZY7S|Kyy2cBHJAP*o?nt&@Wvt#!2TzFc6 z{Mj`11=vD{Fv%dt53h#8FV2)gBa5Q>reG<}sjq1m5gUbY{86+c258tjWG_G^^%%!T zoqO_XAaalQ56GYB*O2_43;M&3a4Fg#ujHJ?EMBn^JqoCTEN)j!(vlF1)#2A-e1BVh z8MLNY_EYC}y7LIQa|b$dsOg2FY2Mr>dW<)gyWDJH{_$oiIWv$Hw%XOvKB#}0nyfrd z6cy*m@|(l^00KH+4@Vb1PTqwnS+t0K<9oQ z*xz3~!Mp6fxgr=c&pMvB?SydFMIi_Gj+{0V`v16 z2n_jr8o!>n5j?&L)Wcl-H>^&?_5hVFq;Y(eu^KW zmXxvd7w-X%AwYC$R^ zY(cFz^-B*Q4HYVoNwO-*dHd4-?`nDnwj^44-p62gZ3NMHaayLg`pg6%umKeh&ByWG z1=u=gM$%;1vq1)W)4Ei2zQfPE!drU1HPgJ?&}2GTXW|HA594yY7zGn5QVSX$ZPc22KXYfbki zAa4ei-FHw|=e9~oNKpS6;P=@qa{<-yWMl2^JLwKEmt0tjZwtsI!S$vsVf8QzddnHv z7?58*H`ou_Fqsn7oxxcAl1l@=uii2eG!4ptjBcUEgA+bt$sQ4T085*Tp0?hVc5@h= zF(Z=}xDgUw)=D(s^{qbh$HGkms{qf6^Tv=>5kuTKmGRk0_m<8#9L;?HK~=@Ip`tZx zf_QhB%z0SQkJ<*hRvJJ+63_Yx46E|3=eX{_2AZ{c%~cT%73@TMM*Y1*$%45kV~nhr zm6(|#{=a8IVP(ZqRt3qAoQ2C1ZasbgLEY94u~1s}sD$xiQpRSA?P(#@ID}lPcUm9uCWhwsKv^!p9pfhNspVbO3Y_-?EM^~OQBA9x_Vt}GYu@vzz-IUpZH#k39gC`fwO2Dt4HY|!m)!p52QHIS(T$pBY)cy~cDMTdtg3?bYgeNjKl9B+28R1lmETdbq5;F_f!hn!p=X^*d0Dj~W zJA{?H5CN=Q3yUGCsR|~}ZmZ%*<+-RA{{G^)p+)H-X79p537ZL>RbA!<>)qX6Vo? zVxvMoT9jQ(w*eG3=vR4a$8ZVvcMj|dqfY|s_KhmSlYKp85Zbtii>RCrd)Hr z%54Xn(KI9=vwfwM2|!p(C!9o(_R}KP85d%2Q=-L}Z35VAR=(|HD)x!;D_(XXMg=1A z80k`r&^Iz7A&CXWKa!{IsaUpNXDWc&Wn?4(@;;F@x$G!z2Fgg(aJ_Lm&5j@8N%Qi` ze&?iMaSRGyb=2fDJ2}F*vE~2FE%KU=^jNHI>Jwa$*$>@Y2Kvh`=Succ#I9BVh@5}T zOLe~vcnR4<3wJfQ%fpr_EM^bwqis-y4Adw~BB&22Z9J!a{=58BWaJ5`TIwS!Fj%vf zGX@C19ZP@jW=ydr z2JjPLsC)9SiNKc*%sMnne&DjF8j|%b_+!CyoX84H3;qC^?hd&r_n4P%eFuQ~o*uCm z(>>DG{NjnT%Y>9up{Y^SZlwvXz{y41qNX*#w!m|vhe-|G;63Wj)q6SfHMNM;>NSg0 z&MitZGALkP)Bc9TbCRD=@;lqsiC#7@=>N&|tlY@ZqmR}#;wYMHmLsuTS}|k6RT^7?qEY=ndh}$UR{a7#3f!-uBe`my-{>+Ys zXvNsd0=l{IcD%lEl2dWLAaS;5hU17#)j|j7;S8a=(+Q{a1joU9>$0*c7LaG`0k{uf zO;x))W%Nn{z=D-YmJ=4?*mC1tkDlaKy6R6VZr02&dly6la&S41JXj~R?gnwbB_EI$ ztZPt+=?oQ&eO&EieP|F(P44DI=2EH^bp!HtVP?aQ@@ywfc=(|jz@^+s;%&r5zzc-k zAt4>&!*@d@Bt*OiC|MmT3&>AWQP+lw90VjoDxm|;Ty}GE$`9HgXKFoSI;lecUL4bz1!iQK#Xo>LsII6d|@4?;)Nl1MwIs8%V?vm?*DJ8!}lx1|9eyta<}dYv7Csc#|7J zx;8y;J~chXhG28HaUy<1hy0P;OR1uph&^q@LqRdF9>ep~Vw{L*8ZaWd*d0JHJ~%=} zdc9|jpi|F%jfWVY2=yprpn_oT9E<2P5C?u%oM-m~+`UB^P{eni-Fb9nXQfC1HgRyi z97+v~JTcClw?Bvapp?kiX(VR6zb8+cY?_7QYr{(_-xrsMk@HB;4_h{ z36U}|WR%t%Bzog1C-TDPEZ0#u667GHI_=Ji>c&>k1MQnqIKm*#7?>Q$sWU+E?AE?$ zR z!Z&YBd$Cz2%rac0f64{6`pCf5G=tueT)L8i!00apS9@v@3#5SpdEnQ9g}Az0!S%Gd zn=Xwfp?@{8sZf#E^(-Yt?8gJ@z(AyD?(Nf`35d_0kCCP=uteX;A|4e|Tl#M!yUf=U z3!3nsDNuzdJoC@YZVNVBWa6vMOeGG&zo%87bEJ>>EeJ9ox4pVb=G{Gst2f@)B1R?e z6^A&(GYr|q5T@5Bg~5_Z$j8J+KBizNwNgSS!BzY{L{tnZoK(aonW^3n`9b7A;sOJN z$Qk_oLn)yA0u1ukVJaY zz_*^ANE-%m#{aD^uBBDb5%}Ls20$H~qQE?(;Ki}OFA;MR!Pt$QD2Qu# zb|NE7-fqMQAQTK}5-V$_g2@Wr)d#5doB6hys@q!i@4iZa=_qsM8UOGrb?t5eI6d*& zJAQTU|3n)hPn5b=Hvj+6kUaqY|EEistif#YVY4*vAwY~j75}xC{yv0FUP88k7$d2` z>qQ4ldjF+_-#sH$e>=m;RS=-l^YPElNk-itI7oHY*6+KgUCZPRaHbd77*2^ z*AqYv2m0j;1rb-6&933ne7pLuUujAjA3ms^o=#MnLPv`dl`|#2FbupQ2h2xO;(oeK zGY5%|5*Hgca2fNalMc>L(u=g|-P{h|2N%!{U(&L&_R`guBOW^Drh6H1xBvxB9~(m0 z%Agg4hiy1pn!cAKuX5uC&gLdb*b{<8%*SCi=f~mIGiAA&qX)3+!kf1qY8U*n#$%(> z+cV1k@%f>4M^lD&0}aW@!8&e3enCu(2O+PAqZLc;paUY8{m%)e!ihm?Et=Qf=ybije4+HYW?1v{!%o$@=ZEUY3Jwt z>Z6(NNXqmgA~(pB`FizDDe%=SB{5l+ z*=h}7mxZ&HS2+-}cNJMo8i!Lr`JESb+wjSi-%{gLe<)3rN!f)kGIv%H? zdZFo3h40NoWp}DrNSY(UKKTCUT0=vHekbvX^EjRssOfF~O`AxQl9in*Bexzc3OqaN zO-v}bc{4%BeY{bTl9?3?Gyl6_awILOuG?_)=xC`d(dUuib875g?F8Nq@e3nh!jlfF$^O-|_oC)XVE-F`f0pp^ZqS}ZeG&*cu&SXR}o+}@UBFF{3l?|v{mM&z*{$5UNGsr<8* z+^gST zb0Pu@*;8gyrPG6T{(RNRp~Cz_a)~BuQvHQD@wN7DD#ata%DvQJ_8eE5^=fO?H(qG; z47)D#)X7+6`BT8g!z-+k0q4qy{n`iDL-mFHVxy@hB6i!Xz268REl6av+ia_#@Wv1>Zza3_E)L1WsUirBM$aW9A40n$OwP=d3oW|_W7Pl zB(0gp?+o}^x^bTp89CIdGtjpq(Dx0$9TiVz0Q}<2i(b=)FjGoOs?LEPHc`27>s~!B zBS(2!L$RZa29%%`Zp?R{{njG+<|`y1naJPt7+ZMHYoK)p2W(c)r+!>Ym%uCCe#mpbWK z5|WYOJSX>ylkyOLiPJq%>#uc&mkPimP8K=`#lu}WEqh|Eaq>Lq&H5xGBbO4nXh;sV>oj_jlg~$W z)x#;&KR7RO%V82FgW>hAtAhtHnw~W0Wh4m@!G~3!5fkGO5-#GwK(e=hKQk+Tw*e z&D0KmKk+6fR?Be~QLTjTvC<_OnVPtFc*f6{A4m6(LDd)==&q}ZGSB5nJeO9A$` z!8B95=5e*TdRM6diT-3+W_xzBhO^7MO1wV{AD?As*taLNBDwqLyOQyz2ezB`&zZjW zjBu<4Fe=C-eBd|ua>Uq#y?BL#A6$c+00|2U{9>AO-75Lx9=H$ z@i7(^F$AU8npL5urZa7ai9GqRpPSyeB4qP3eAB0l=Dic;+lN(KW6URieq^|vJwMy; zoJn#%G=KfZ*Daa>M?-eU&gBx`^XKhk6n&yt2nWbToKowKPpXwozHnVr8g-m0wV2^; z;usmuKcmwvf&vyHu*HTnxquP3tKO&;AtCDOI#O=jDHcptpi9K+;cjG@aW<68eH43g zT7?9WL)6qsFf|m~o;#{}iHrLv7-I5=6 z6R(WzkLzuoo;E&MtDhXSnnLI$*xGQoJ{j>r%YChV$_YevU#W){wcY>-|dv7Y;3cF`?K@_ z?F?GY_POqN)T$J2z<|DpYHZX<>YM7NUmq_Ay;IM5)W*NEEI6yC51TC(y9a*RNHiq>SFb?}}vw$RjI>3yaG%qJM4p zPNN?{q5&h_SFSiJ`W`gPD}zMP#0a!-jWD)`Dm>iQqSN266Xg*O=AK9YJ!vi{g%&;v zTY2eEQd2dGw&g=9FEFj0;0IbJnZ9I1yfL%#085!xQ^LkcNiN%G+ z+8aTk9=qboGOAMH({-KFU|M?CUPrQE{IP?d#j6yCZ5--P4ko*EFYookC}nH$QG4+@ zv-tME8djQe+bguS;cQZj!8hCDl*<>^($kOl*_*SoZa0JeAS8$)SxYBFI0}hgv6`kVue&pA&e)0 zp5i!4(@RQayPfEc$2sxB?w?YF?xsknEo1iDs#fcpO*aX3cLaVF{BH0NX>WfWA9~pdL;NqcTPl2r z`aaBg>ra0Ef*$f=w=*wrOS%_|QUgB>#MNahR5#ElZ)?aL3oPsU^3dMxG=|fHrC7Ik zeNuJ2L{C&!KCnuaaj+{g)~fN@!Dbzl&964Ft$=d|L+G8$VZq;L2(33Hf9+TJo^3hF zVR(LAL75yF&zjA|8@_swibdfi6C*bv&ydax>!cJW`tbeia6pojHWHJu@!eDAw6_W`*xrrt8d7t-R4G8f(lBi`P9pcQQf`9v%Y%0&!p7iRFQeFgB}R`fKi}S%$LMh zA1pOE?-y8hKZtbd#!;0C=4DeF%vBudMLtOGY3cL2a_|`WQ`6x&%m=sXYjy(%1Aqz&#ZiaoJLL zfceLANIxUe-RuiqSf~&Ww{trk3VYG(7LYezHS~1S5393!D$RWA+mAF+{@Cv$p%D=$ z6J}8aJY6%=lMOBac02E-MW1ugsV2IMLcZf;-FwdH%4=(HCII}Rf|!K11wFMsx+az^) zd5x);7u-XSQz@<@;C(0HF%ub0Id0BUsX_QS&2&m_x-{MWJ4CuYn4gOP(K>GbYd=qj z*OYtR;cmAr{~6s@-PZoCduylr@*JiazP=bjFU!lG`}r;P#sdwOAIBbWat@yN^sQ@~ z!(T6x1JjxxZ=do{Rg;==JM1ejh}ThqD`R}UUTqEnYAq&XRtGKGgJVaF`{Ac%ViNwW zw2~;PzP@s8?Pe~AffvUH_W3Fo46G&Jw8poZ7|EzVOuclH``VO`n1gan*N((BQu}z0 zH4Y0QN~vu};*WicWyv70-K`cn$^cD&ojTusR`&v&4>@>*^uR%KaF%QBX-*FC>SP~iukAvYB+{(Lzn{L)jPs-QoHg)w)`( zEc^AI^^x&lB1bYxNs92VWU)U|0s|DQP15VuXaHhIb5d@q)^>pJe*OB|Y*c0E3W~2i zN1_jiocfGtOqH9g*d(~WNIN=|+(#Hpuu z5$+E;v+IomPszBA8Q5Y{F1mpEc&&1W;o_!=fD6ask9*|d;?q?Y13B_>eTk7fJ2szR zq0F)15p;Hrz|YWd=*tNB;#l;A&ZlbfvZUQ~n&$tu25`=(MTXK&@T|iV5zZjF>3`$x z3q9Hdnn|VF4420&N~)0IumIK(x-e;lEA+EJG2aq65v={&4Qy&i=%l7og|~rNpB~Vj zef>6G&aPb>p_vEUo?GDAd@oQGv>MkUEQM?sdcqfy&+K^fClXa>{AFmu? zp&^Tj+aZLBJG2s&O=F6j|ualO0 zl8B)cY`FIN<}hv;_h-q*Wq>JivJeicvSW~V{P@&-FH|v0>FvAd?$}7^Ov#UWJ>hNo zY7yQu^JiyEeX&@q78*6eOa1YxA8(o_wGexK%~e|5e8=}*5CzkD)(zTQOdIVpA1KQr&8eiVU0RgNB1zsn>e=nogEnk;z_p8woaNZ z@>YjB0j$U*Ks+@N&RXSsme&r8i_cUGw*Qu$zb+g1!XUI={Hw(P9-3@+L&Z8Ok*Dw; zI-cdXAMje-01j;~F27rMkIyp*I~L`Oo09Ch>7N1L$o8a_e@92$OKQ-05Mqf-OA5pr z$PKci^ z?sEUpw|J?1WePIzVX24O<@+acNwR$9ES0*WqjcNpS|@WSyVzbKUmI2fVy`?WTVj#E zp4jG9I(y1&R^t&m@SS?OMD$vyVL7zn4A2xbQ%G&YIwDhigC4pZ>#54f07!LKhww3{ z5T+u1%oxYdb90?$Js8o^&|Lm}{C!BRRsseKSU#+zEyv5rCulggr|lF)WwCjk?Pkyg z#$*$=j|&XTSBo0CFSC;aJuV3jw_Ct6$`?W+zWGLZvOF8iQvVS-){IX#VBOc>o{;G_UbmYAtP5mf^{bg%)0MpV5B`hsy81`cGVYf zn3k5*Rh1tp-&TJpm_{^=ZfO_8`fP*-NdX z&E;B0*^OBNr>SoRz!c3+C3c)GY+Ax2!inW{w7g(!ddKbf$Yq6?=#eJ5jZ;UWBdU1U z+1x#kXar0j!nM2FZiL)SFs#PEJXh>ke3kw>vP$;i(;Xp{mWP}u#9ms2cJPB5+oc6Y zH4HAOgm)iQz)b@s)%15pgaR3~<;$1#BG!u&;~&2>Q?V$WwcfB?R?m820A**dsS@SG=HV* z^Plz1JLpQkS*K7hR3~zk1119r1%<;1ov2hG`n_WAnja~!@j(Ef07Qa&-nalnA|O@S z^%|~0jK^yfQBq;Q(klp1qv*q>D70rAz5R0YOccS|Kl1rrPtAA2dyydHBquiz#OZABq`V~k zbhVeCe>JIqd;J0)Tij?W;G!~}r@T*@Of^3r0Fx__0g|X6lpQuHK`omzz4~^T!vFGiKC;n z6;|L!_^Ji(p9P)lEqTv4&Nj)uOuQ3-b05*UIfBNfFhvbd4Tlnq-Ema!f~s^e+oqGY z3e!joA%S;tL$t+16D~QHvpOhxJnmD-Rr=uOzbD~(jOC5d^*V@`-;BrRr^9{@FV!1> z3Ph{%zdYzn;vRNb@P&0?+SfTOCW(S|vS)wQfBU_agaW%&5z)(m{eFQH0XVizI{`4* z8m23pD_Kc}I~JiwF;Vou4BPX7vmcLWwh%h~jE9?v8yi1?O2z7*uQL*R0So8vxbeZL zjwXR|?!ZtZbV?1(cOeuoclmQbGyp`<>3UVY(H9#}>qSMM2YN>kC6$QnO_mDoGz0p> zVQu?Jli|GcJ7~bf+WBA(FpD?Ycz<&L$p-7-+Hfv9FUAq9+UE0*_&k7{mNb;naaj*hBo&GZXM8rcGQ{_xCK#U~D3y@k-Z!{PkHK#ATDgZ3`F zT0DLiQEDM!Z;ZZrUJpbbHDn0w-+ZG~rxQYnRau{-4)6TtT7!}H_7};KRwa4t)pC`q zK&czqsU#gI(sb$G<#vS7h3=Q|j!~VxEE)j)PV4XCi{pO=zUFdT*v7DA{h1zC34n3g}WU*4#ei?@%&tf zfX-?QfW(NYAYh+2=0MFk8Wj&_U&h-VedX>bd8>v@%i*pwJ?+=&CatJ@RTjX^O~}m+ z8>jR7x@re>y>huxZ4%#s@RtwcTI&yu0S$!9R_w)z*c*i%w9-jn=z<>rpb3?YH~Mxs zv2C1uU{hqE8(N@3EK-_f2wDgk_CjKRj6VynUdiMSM@DB;J@aKyd!d+*U!+Bi{^;;S z0c_>h!lY$45Xl5VB@}?aH=(ZpE!>N_Xx(~~6s2m5{Pod(0FS_$`Si;J=8KbT43guj z$@;niQ#}D&ip9n=vT$)=Zf;9+niPE#8ZJqtqk4lv`~-W9QLAKQOdhB;_(JE<&iuUl z@vGsAT+S98I`uI4oKMlGPx_OY=dP;mjqn9=V5Wlg^6^E}<(-E_ItTghvobTM+^R|0 zl`WZ8d>;Hd*vK^*H$mJC%4-z83->9|+&4_Q0L2s)74hK-G=OCiNt7^hUaKna3qMoz1Vh?BK^pmCTC-zXRVO%DMGXM(oK*LkZUtT1^u zp$-L6>%P~HQY z@q&Ag#)64P?O+;qE{Jv7HwE8{?ra-4i&$q}Sph!opjPafQ3S}NZl2Y+?Lo^xDs-X1 zn~i{H&H0GKYCP<6uYc3_#1T(b92L_oRn!$?rwc3;E`7&QLj$02(im1$-;5`c3Y= zrC#!6dqzx+A{$5AnvNXUu{D5%P)Vz{D`Q7=QTESOT%urN7VNhuir#o-{>tl4Lly?z zBHzHFgH7$jxi6{0Q0E4dR(~5+{3k-diSfeg{o=wxU)&=wubJSUy=cj>nU8ut#fW!Dgn*416vo%*C{W$ zFh(k${o+7%cdQhkpLaa2V?aIp6ItF=sW&B?(=OIO5kF!p z)UaR8*hFK-18Yg##R=tJ5GO9$5^sT@OmAVLM`f8sZ)12FtXSk02vJ= zg+E+;rq>ENe-5Z?P}8mA_X=DNGo~Dq^Pt^cx*mmdo$~9?C+Aw8DQ1oJC(#=aDGz4J zTQ%ld&dzi*12*ISi-qvA<>yiO59Va~)h*GBqP4iV)VCUpwQ3Z;X+dF>(EwEVeOQW( z>!u*5UX9Y+pp4US!Sx!%BsMJ z!l+hTG1W@9&Siggczex#7KSkoB5n$U=aM=W4sv+(Nx*(~z#aJ#(NwC8TX2A%Zf z$7i5d)T*qillfs%vW~#OLaC9-_VtrzH_HM@lF85)xTIB8iP6yloRG;FF|VB-A!FD~9}uL0K7>Fn^EV%X zrID1H`eZ~CYHEL8+!WPNL?$PlpswC&&@RED3BIA3pN9jgq7UAWV5?eW4F(9+FJrn!2$H=D_a^6$df;h7S1OL z)}^Ud@=+TeyfDGND_8x`)fD;__}yyO89Y=!o>Ki?&GwtSk#b1Ic}Tjwmm2rL?#6f0 zYljSIu4`6Wd3{v;ov4P-R+N$SPDK*~q-YT3Yd<$QAxHZ+!`Pt(2jPrf&zq`cD33Rp z5D9jub>5-s3eV9af3vj1PIcZdu5=pe5zPIo?r)iEDx94b?@~J?i>uuj;{DI91T8|7 z40Ty}<`-_*MmN414Za^@k@4t}DlnwW6LbBlK2HV?Ce;j7Bswg($(IJXVg;yR5#4on z?|IixP+dzzmR!khR(zoP3?la*8aRljhTiDJxzpfaF#(qQD62J1Wx;(2ahY>>#ZAE$Y*1zQ`Tr= za~z<@{GsPh6TE68v3W0y%&@Eskjy6|gC-FZ>v;T7`9w2nnQzaDRCwEiq`E-q?4w1S z@MK_+rdfbda%s>|zm(Pf1*sqC+!^5&tb>Mx2kolGl--7ZL#y#z;je9871?fzKA+2aX~Yu&gF{?wEQp8Ejgu z@?nRL|MWdygLZ^!ji)CJ50&KZ1iuaybLcVpV2LcWUv z#_(N}xItoN=k0Pay3Kpy*@gVMIFR~RNKFoI_uWdNZ@lk$X`lylj%laR(^A?Ttxpxi$1B}NqUnltZ|_@ zGSSMF{V2}L{bj8*t{b^bsf*i3el@)=N5W}?T7AKicDFU-M-NjpuI*=V?{lNArB6lh zPfDihCw0zgN}aX)4=1W?UNnk(q36>iY*!t6*)FR5u5UPu?Z;PL#9ohH_%=9jLE3ET z#{2qkcGPeIE>Aq?f5Q43OICxEuD4L+MVw8a!|7KiFh^T;jh~O1+SPa^sMFmTLivyA zc+Nf_*Tb_j`=I=KWo&T!h;dxF{e%UhFhGHEEdOQmH%fih|Ha;0M@891@xs^$5=y;D z2@=vucZ?#^APgPS-3$#Q3W8FCq=0ny&2D;f{-EyYvip?AN7@UtTX4^`Z{=4D^xvStE(7wh$AE($GE+XRFV^acg!vKSm?TYA6LYr`Z z-AS0^Rgnk((SwRJ%AXU<#M_Y3fKz+;?=MUP}bH z6@kt-P)GXb@%lcOje~P`XC)4~T)Sk6TM=A2>+Ee49>2rT0R_2oN9q-{Wr5#VBe>w) zX=Ua~_PlZJ$>x!+lh{5PVU~QW!1}zy3zCc0vlZW*6|3NKR|8d;%6H9j&i6>HgwM^? z65CFf6h*Yx$LpG9R^LlGhO1GmAW!^t5-m25_F=hEebx?Lj(@GBoJ6q`k|E`LlmfY*Z^0*VKf_4z42Ez6*Otejm-*yGK%Se(fW5>(}x3qxiSZ(TL zJ_TD*FX_=RHsv#$ayB;Q;eES?25Z^^lSgO?zY73fzD$W!a>VE7%$yDD0lQ9=Xs<;c z95`K?w!aVgUv=t!f4ly-K<4ESSN_X;7Ww*L-ZO5&zY`mThyL$nAnNyjy97AX|96&L z3Xas$##J-*b){%-q>pR_PlP`2|MDrl8N9aK@wy}jBn7Bm${I|h8uNE)WcQ@U5;TmL zSr2CHX}|N2E>FQNFbMtT^v_S>^>q9hnZJx_MoOY>fXI1*P!!Lk^VCdqw#G>zNC#mE z1kT0ZOx3G~`5d(V(RkD6>CD#+Bc0{?8xKRe$p(e}23A-{gYVum79L_23o# z+0Tp+FjwO6`P8&sHIA!@zVU3Gt78j4!FFL&dhd&{=GiK68%}W ze`KaEK_q8MysC-tZX7!-vMrXS@A;#dN>DZ}*$k!#ZM>t@nbMIaY-KyA^JtVRx{vI= zIq7@z9RBg42_CtS?xx_mzgj$j57%!H8p=FT?2t3Fx(zS;M{zYhVnmJ^%7xU1&j>`f z%FCqZ>G^4VMm(Hl_|k7{o4i%#Rd1^J?VwlliP~^Myfg`=8iJIFTiwZhQF>hc@y7jz zC}`_Vk8HckP~xwnpX++kK&t9%l?r-osX0UpA(p-7j|Ymk%w219%sh%laW@!VASf<6 zD(A48qHCoweTf_M?y>n;%c@k4X0nO7=O>^_o!v`cS;-lL9}^LDyJo{+??%h{ob;I5roI#9vu-ke{6dvO zBq@Aa`S7FRSy5@VP6kpiZSADA*8ESOd}RlOg$xBShMM6h zzhBH!%J@JY;#j6FolAGGp$tZBntWh`WE6waPeM7<@5zNZMJp_19B>PY}a~5?>|b=>}-Du@k0#Vf(fs*^C& AH8vZcrm7 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 z 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