From bd9a34c2fec68898c840de7d656974addc131dbe Mon Sep 17 00:00:00 2001 From: SamNet-dev Date: Thu, 12 Feb 2026 00:40:22 -0600 Subject: [PATCH] =?UTF-8?q?feat:=20v1.3.3=20=E2=80=94=20Iran=20connectivit?= =?UTF-8?q?y=20monitoring,=20network=20testing,=20and=20Psiphon=20stats?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Iran Connectivity Status: real-time monitoring with IODA, OONI, irinter.net, and Cloudflare Radar data with 7-day charts - Iran Connectivity Test: diagnostics across 88 servers in 24 cities with quick test, full report, stability test, and MTU discovery - Psiphon Network Stats: global analytics with daily users, bytes transferred, running proxies, and country distribution charts - CLI Commands Reference page and reorganized Info & Help menu - Updated license and screenshots --- LICENSE | 2 +- conduit.sh | 4972 ++++++++++++++++++++++++----- screenshots/conduit-info.png | Bin 0 -> 60588 bytes screenshots/conduit-iranstats.png | Bin 0 -> 48962 bytes screenshots/conduit-irantest.png | Bin 0 -> 65235 bytes screenshots/conduit-menu.png | Bin 56848 -> 65875 bytes screenshots/network-stats.png | Bin 0 -> 56754 bytes 7 files changed, 4249 insertions(+), 725 deletions(-) create mode 100644 screenshots/conduit-info.png create mode 100644 screenshots/conduit-iranstats.png create mode 100644 screenshots/conduit-irantest.png create mode 100644 screenshots/network-stats.png diff --git a/LICENSE b/LICENSE index af49bbb..959aafb 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2026 Saman - SamNet +Copyright (c) 2026 SamNet Technologies Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/conduit.sh b/conduit.sh index be42597..242ceea 100644 --- a/conduit.sh +++ b/conduit.sh @@ -1,7 +1,7 @@ #!/bin/bash # # ╔═══════════════════════════════════════════════════════════════════╗ -# ║ 🚀 PSIPHON CONDUIT MANAGER v1.3.1 ║ +# ║ 🚀 PSIPHON CONDUIT MANAGER v1.3.3 ║ # ║ ║ # ║ One-click setup for Psiphon Conduit ║ # ║ ║ @@ -31,7 +31,7 @@ if [ -z "$BASH_VERSION" ]; then exit 1 fi -VERSION="1.3.1" +VERSION="1.3.3" CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:latest" INSTALL_DIR="${INSTALL_DIR:-/opt/conduit}" BACKUP_DIR="$INSTALL_DIR/backups" @@ -291,6 +291,10 @@ check_dependencies() { if ! command -v qrencode &>/dev/null; then install_package qrencode || log_warn "Could not install qrencode automatically" fi + + if ! command -v openssl &>/dev/null; then + install_package openssl || log_warn "Could not install openssl (needed for credential encryption)" + fi } get_ram_mb() { @@ -742,8 +746,9 @@ save_settings_install() { mkdir -p "$INSTALL_DIR" # Preserve existing Telegram settings on reinstall local _tg_token="" _tg_chat="" _tg_interval="6" _tg_enabled="false" - local _tg_alerts="true" _tg_daily="true" _tg_weekly="true" _tg_label="" _tg_start_hour="0" + local _tg_alerts="true" _tg_cpu_alert="true" _tg_daily="true" _tg_weekly="true" _tg_label="" _tg_start_hour="0" local _sf_enabled="false" _sf_count="1" _sf_cpus="" _sf_memory="" + local _mt_enabled="false" _mt_port="443" _mt_secret="" _mt_domain="google.com" _mt_cpus="" _mt_memory="" local _dc_gb="0" _dc_up="0" _dc_down="0" _dc_iface="" local _dc_base_rx="0" _dc_base_tx="0" _dc_prior="0" _dc_prior_rx="0" _dc_prior_tx="0" local _dk_cpus="" _dk_memory="" _tracker="true" @@ -784,41 +789,41 @@ save_settings_install() { fi local _tmp="$INSTALL_DIR/settings.conf.tmp.$$" cat > "$_tmp" << EOF -MAX_CLIENTS=$MAX_CLIENTS -BANDWIDTH=$BANDWIDTH -CONTAINER_COUNT=${CONTAINER_COUNT:-1} -DATA_CAP_GB=$_dc_gb -DATA_CAP_UP_GB=$_dc_up -DATA_CAP_DOWN_GB=$_dc_down -DATA_CAP_IFACE=$_dc_iface -DATA_CAP_BASELINE_RX=$_dc_base_rx -DATA_CAP_BASELINE_TX=$_dc_base_tx -DATA_CAP_PRIOR_USAGE=$_dc_prior -DATA_CAP_PRIOR_RX=$_dc_prior_rx -DATA_CAP_PRIOR_TX=$_dc_prior_tx -DOCKER_CPUS=$_dk_cpus -DOCKER_MEMORY=$_dk_memory -TRACKER_ENABLED=$_tracker -SNOWFLAKE_ENABLED=$_sf_enabled -SNOWFLAKE_COUNT=$_sf_count -SNOWFLAKE_CPUS=$_sf_cpus -SNOWFLAKE_MEMORY=$_sf_memory -MTPROTO_ENABLED=$_mt_enabled -MTPROTO_PORT=$_mt_port +MAX_CLIENTS="$MAX_CLIENTS" +BANDWIDTH="$BANDWIDTH" +CONTAINER_COUNT="${CONTAINER_COUNT:-1}" +DATA_CAP_GB="$_dc_gb" +DATA_CAP_UP_GB="$_dc_up" +DATA_CAP_DOWN_GB="$_dc_down" +DATA_CAP_IFACE="$_dc_iface" +DATA_CAP_BASELINE_RX="$_dc_base_rx" +DATA_CAP_BASELINE_TX="$_dc_base_tx" +DATA_CAP_PRIOR_USAGE="$_dc_prior" +DATA_CAP_PRIOR_RX="$_dc_prior_rx" +DATA_CAP_PRIOR_TX="$_dc_prior_tx" +DOCKER_CPUS="$_dk_cpus" +DOCKER_MEMORY="$_dk_memory" +TRACKER_ENABLED="$_tracker" +SNOWFLAKE_ENABLED="$_sf_enabled" +SNOWFLAKE_COUNT="$_sf_count" +SNOWFLAKE_CPUS="$_sf_cpus" +SNOWFLAKE_MEMORY="$_sf_memory" +MTPROTO_ENABLED="$_mt_enabled" +MTPROTO_PORT="$_mt_port" MTPROTO_SECRET="$_mt_secret" -MTPROTO_DOMAIN=$_mt_domain -MTPROTO_CPUS=$_mt_cpus -MTPROTO_MEMORY=$_mt_memory +MTPROTO_DOMAIN="$_mt_domain" +MTPROTO_CPUS="$_mt_cpus" +MTPROTO_MEMORY="$_mt_memory" TELEGRAM_BOT_TOKEN="$_tg_token" TELEGRAM_CHAT_ID="$_tg_chat" -TELEGRAM_INTERVAL=$_tg_interval -TELEGRAM_ENABLED=$_tg_enabled -TELEGRAM_ALERTS_ENABLED=$_tg_alerts -TELEGRAM_CPU_ALERT=$_tg_cpu_alert -TELEGRAM_DAILY_SUMMARY=$_tg_daily -TELEGRAM_WEEKLY_SUMMARY=$_tg_weekly +TELEGRAM_INTERVAL="$_tg_interval" +TELEGRAM_ENABLED="$_tg_enabled" +TELEGRAM_ALERTS_ENABLED="$_tg_alerts" +TELEGRAM_CPU_ALERT="$_tg_cpu_alert" +TELEGRAM_DAILY_SUMMARY="$_tg_daily" +TELEGRAM_WEEKLY_SUMMARY="$_tg_weekly" TELEGRAM_SERVER_LABEL="${_tg_label//\"/}" -TELEGRAM_START_HOUR=$_tg_start_hour +TELEGRAM_START_HOUR="$_tg_start_hour" EOF chmod 600 "$_tmp" 2>/dev/null || true mv "$_tmp" "$INSTALL_DIR/settings.conf" @@ -942,7 +947,7 @@ create_management_script() { # Reference: https://github.com/ssmirr/conduit/releases/latest # -VERSION="1.3.1" +VERSION="1.3.3" INSTALL_DIR="REPLACE_ME_INSTALL_DIR" BACKUP_DIR="$INSTALL_DIR/backups" CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:latest" @@ -953,15 +958,20 @@ GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' MAGENTA='\033[0;35m' +BLUE='\033[0;34m' BOLD='\033[1m' DIM='\033[2m' NC='\033[0m' -# Load settings -[ -f "$INSTALL_DIR/settings.conf" ] && source "$INSTALL_DIR/settings.conf" +# Load settings (enforce permissions on sensitive config files) +if [ -f "$INSTALL_DIR/settings.conf" ]; then + chmod 600 "$INSTALL_DIR/settings.conf" 2>/dev/null || true + source "$INSTALL_DIR/settings.conf" +fi MAX_CLIENTS=${MAX_CLIENTS:-200} BANDWIDTH=${BANDWIDTH:-5} CONTAINER_COUNT=${CONTAINER_COUNT:-1} +PERSIST_DIR="$INSTALL_DIR/traffic_stats" DATA_CAP_GB=${DATA_CAP_GB:-0} DATA_CAP_UP_GB=${DATA_CAP_UP_GB:-0} DATA_CAP_DOWN_GB=${DATA_CAP_DOWN_GB:-0} @@ -1603,14 +1613,17 @@ run_mtproto_container() { # Save traffic before removing existing container save_mtproto_traffic - # Remove existing container - docker rm -f "mtproto-proxy" >/dev/null 2>&1 || true - - # Pull image if not available locally + # Pull image if not available locally (before destroying old container) if ! docker image inspect "$MTPROTO_IMAGE" >/dev/null 2>&1; then - docker pull "$MTPROTO_IMAGE" 2>/dev/null || true + if ! docker pull "$MTPROTO_IMAGE" 2>/dev/null; then + echo -e " ${RED}✗ Failed to pull MTProto image. Existing proxy left running.${NC}" + return 1 + fi fi + # Remove existing container (only after confirming image is available) + docker rm -f "mtproto-proxy" >/dev/null 2>&1 || true + local actual_cpus=$(LC_ALL=C awk -v req="$mt_cpus" -v cores="$(nproc 2>/dev/null || echo 1)" \ 'BEGIN{c=req+0; if(c>cores+0) c=cores+0; printf "%.2f",c}') @@ -1944,7 +1957,7 @@ show_mtproto_menu() { if command -v qrencode &>/dev/null; then qrencode -t PNG -o /tmp/mtproto_share_qr.png "$_mt_link" 2>/dev/null if [ -f /tmp/mtproto_share_qr.png ]; then - local _tg_caption="📡 *MTProto Proxy*" + local _tg_caption="✉️ *MTProto Proxy*" _tg_caption+=$'\n'"Server: \`${_mt_ip}\`" _tg_caption+=$'\n'"Port: ${MTPROTO_PORT}" _tg_caption+=$'\n'"Domain: ${MTPROTO_DOMAIN}" @@ -1958,7 +1971,7 @@ show_mtproto_menu() { rm -f /tmp/mtproto_share_qr.png echo -e " ${GREEN}✓ Link and QR code sent to Telegram${NC}" else - telegram_send_message "📡 *MTProto Proxy* + telegram_send_message "✉️ *MTProto Proxy* Server: \`${_mt_ip}\` Port: ${MTPROTO_PORT} Domain: ${MTPROTO_DOMAIN} @@ -1967,7 +1980,7 @@ Domain: ${MTPROTO_DOMAIN} echo -e " ${GREEN}✓ Link sent to Telegram${NC}" fi else - telegram_send_message "📡 *MTProto Proxy* + telegram_send_message "✉️ *MTProto Proxy* Server: \`${_mt_ip}\` Port: ${MTPROTO_PORT} Domain: ${MTPROTO_DOMAIN} @@ -2264,7 +2277,7 @@ show_qr_code() { show_dashboard() { local stop_dashboard=0 - trap 'stop_dashboard=1' SIGINT SIGTERM + trap 'stop_dashboard=1' SIGINT SIGTERM SIGHUP SIGQUIT tput smcup 2>/dev/null || true echo -ne "\033[?25l" clear @@ -2408,7 +2421,7 @@ show_dashboard() { echo -ne "\033[?25h" # Show cursor # Restore main screen buffer tput rmcup 2>/dev/null || true - trap - SIGINT SIGTERM # Reset traps + trap - SIGINT SIGTERM SIGHUP SIGQUIT } get_container_stats() { @@ -3007,7 +3020,7 @@ check_stuck_containers() { if docker restart "$cname" >/dev/null 2>&1; then CONTAINER_LAST_RESTART[$cname]=$now CONTAINER_LAST_ACTIVE[$cname]=$now - if [ "$TELEGRAM_ENABLED" = "true" ] && [ -n "$TELEGRAM_BOT_TOKEN" ] && [ -n "$TELEGRAM_CHAT_ID" ]; then + if [ "${TELEGRAM_ENABLED:-false}" = "true" ] && [ -n "${TELEGRAM_BOT_TOKEN:-}" ] && [ -n "${TELEGRAM_CHAT_ID:-}" ]; then local _msg="⚠️ *Conduit Alert* Container \`${cname}\` was stuck (no peers for $((idle_time/3600))h) and has been auto\\-restarted\\." curl -s --max-time 10 -X POST \ @@ -3183,8 +3196,8 @@ show_advanced_stats() { fi local persist_dir="$INSTALL_DIR/traffic_stats" - local exit_stats=0 - trap 'exit_stats=1' SIGINT SIGTERM + local exit_stats=0 _adv_tmpdir="" + trap 'exit_stats=1; [ -n "$_adv_tmpdir" ] && rm -rf "$_adv_tmpdir"' SIGINT SIGTERM SIGHUP SIGQUIT local L="══════════════════════════════════════════════════════════════" local D="──────────────────────────────────────────────────────────────" @@ -3350,7 +3363,7 @@ show_advanced_stats() { echo -e "${CYAN}╠─── ${CYAN}TOP 5 BY UNIQUE IPs${NC} ${DIM}(tracked)${NC}\033[K" local total_traffic=$((total_in + total_out)) if [ "$total_conn" -gt 0 ] && [ "$total_active" -gt 0 ]; then - for c in "${!cips[@]}"; do echo "${cips[$c]}|$c"; done | sort -t'|' -k1 -nr | head -7 | while IFS='|' read -r active_cnt country; do + for c in "${!cips[@]}"; do echo "${cips[$c]}|$c"; done | sort -t'|' -k1 -nr | head -5 | while IFS='|' read -r active_cnt country; do local peers=$(( (active_cnt * total_conn) / total_active )) [ "$peers" -eq 0 ] && [ "$active_cnt" -gt 0 ] && peers=1 local pct=$((peers * 100 / total_conn)) @@ -3362,7 +3375,7 @@ show_advanced_stats() { for c in "${!cbw_in[@]}"; do local bytes=$(( ${cbw_in[$c]:-0} + ${cbw_out[$c]:-0} )) echo "${bytes}|$c" - done | sort -t'|' -k1 -nr | head -7 | while IFS='|' read -r bytes country; do + done | sort -t'|' -k1 -nr | head -5 | while IFS='|' read -r bytes country; do local pct=$((bytes * 100 / total_traffic)) local blen=$((pct / 8)); [ "$blen" -lt 1 ] && blen=1; [ "$blen" -gt 14 ] && blen=14 local bfill=$(printf '%*s' "$blen" '' | sed 's/ /█/g') @@ -3375,7 +3388,7 @@ show_advanced_stats() { # TOP 5 by Download echo -e "${CYAN}╠─── ${GREEN}TOP 5 BY DOWNLOAD${NC} ${DIM}(inbound traffic)${NC}\033[K" if [ "$total_in" -gt 0 ]; then - for c in "${!cbw_in[@]}"; do echo "${cbw_in[$c]}|$c"; done | sort -t'|' -k1 -nr | head -7 | while IFS='|' read -r bytes country; do + for c in "${!cbw_in[@]}"; do echo "${cbw_in[$c]}|$c"; done | sort -t'|' -k1 -nr | head -5 | while IFS='|' read -r bytes country; do local pct=$((bytes * 100 / total_in)) local blen=$((pct / 8)); [ "$blen" -lt 1 ] && blen=1; [ "$blen" -gt 14 ] && blen=14 local bfill=$(printf '%*s' "$blen" '' | sed 's/ /█/g') @@ -3388,7 +3401,7 @@ show_advanced_stats() { # TOP 5 by Upload echo -e "${CYAN}╠─── ${YELLOW}TOP 5 BY UPLOAD${NC} ${DIM}(outbound traffic)${NC}\033[K" if [ "$total_out" -gt 0 ]; then - for c in "${!cbw_out[@]}"; do echo "${cbw_out[$c]}|$c"; done | sort -t'|' -k1 -nr | head -7 | while IFS='|' read -r bytes country; do + for c in "${!cbw_out[@]}"; do echo "${cbw_out[$c]}|$c"; done | sort -t'|' -k1 -nr | head -5 | while IFS='|' read -r bytes country; do local pct=$((bytes * 100 / total_out)) local blen=$((pct / 8)); [ "$blen" -lt 1 ] && blen=1; [ "$blen" -gt 14 ] && blen=14 local bfill=$(printf '%*s' "$blen" '' | sed 's/ /█/g') @@ -3415,7 +3428,7 @@ show_advanced_stats() { echo -ne "\033[?25h" tput rmcup 2>/dev/null || true - trap - SIGINT SIGTERM + trap - SIGINT SIGTERM SIGHUP SIGQUIT } show_peers() { @@ -3431,7 +3444,7 @@ show_peers() { fi local stop_peers=0 - trap 'stop_peers=1' SIGINT SIGTERM + trap 'stop_peers=1' SIGINT SIGTERM SIGHUP SIGQUIT local persist_dir="$INSTALL_DIR/traffic_stats" @@ -3607,7 +3620,7 @@ show_peers() { echo -ne "\033[?25h" tput rmcup 2>/dev/null || true rm -f /tmp/conduit_peers_sorted - trap - SIGINT SIGTERM + trap - SIGINT SIGTERM SIGHUP SIGQUIT } get_net_speed() { @@ -3617,13 +3630,13 @@ get_net_speed() { [ -z "$iface" ] && iface=$(ip route list default 2>/dev/null | awk '/dev/{for(i=1;i<=NF;i++)if($i=="dev"){print $(i+1);exit}}') if [ -n "$iface" ] && [ -f "/sys/class/net/$iface/statistics/rx_bytes" ]; then - local rx1=$(cat /sys/class/net/$iface/statistics/rx_bytes) - local tx1=$(cat /sys/class/net/$iface/statistics/tx_bytes) - + local rx1=$(cat "/sys/class/net/$iface/statistics/rx_bytes") + local tx1=$(cat "/sys/class/net/$iface/statistics/tx_bytes") + sleep 0.5 - - local rx2=$(cat /sys/class/net/$iface/statistics/rx_bytes) - local tx2=$(cat /sys/class/net/$iface/statistics/tx_bytes) + + local rx2=$(cat "/sys/class/net/$iface/statistics/rx_bytes") + local tx2=$(cat "/sys/class/net/$iface/statistics/tx_bytes") # Calculate Delta (Bytes) local rx_delta=$((rx2 - rx1)) @@ -4133,7 +4146,7 @@ status_json() { local logs=$(cat "$_jt/logs_$i") if [ -n "$logs" ]; then local conn cing up_b down_b - IFS='|' read -r cing conn up_b down_b _ <<< $(echo "$logs" | awk '{ + IFS='|' read -r cing conn up_b down_b _ <<< "$(echo "$logs" | awk '{ ci=0; co=0; up=""; down="" for(j=1;j<=NF;j++){ if($j=="Connecting:") ci=$(j+1)+0 @@ -4142,7 +4155,7 @@ status_json() { else if($j=="Down:"){for(k=j+1;k<=NF;k++){if($k=="|"||$k~/Uptime:/)break; down=down (down?" ":"") $k}} } printf "%d|%d|%s|%s|", ci, co, up, down - }') + }')" total_conn=$((total_conn + ${conn:-0})) total_cing=$((total_cing + ${cing:-0})) # Convert upload to bytes @@ -4319,7 +4332,7 @@ show_status() { if [ "${_c_running[$i]}" = true ] && [ -f "$_st_tmpdir/logs_${i}" ]; then local logs=$(cat "$_st_tmpdir/logs_${i}") if [ -n "$logs" ]; then - IFS='|' read -r c_connecting c_connected c_up_val c_down_val c_uptime_val <<< $(echo "$logs" | awk '{ + IFS='|' read -r c_connecting c_connected c_up_val c_down_val c_uptime_val <<< "$(echo "$logs" | awk '{ cing=0; conn=0; up=""; down=""; ut="" for(j=1;j<=NF;j++){ if($j=="Connecting:") cing=$(j+1)+0 @@ -4329,7 +4342,7 @@ show_status() { else if($j=="Uptime:"){for(k=j+1;k<=NF;k++){ut=ut (ut?" ":"") $k}} } printf "%d|%d|%s|%s|%s", cing, conn, up, down, ut - }') + }')" _c_conn[$i]="${c_connected:-0}" _c_cing[$i]="${c_connecting:-0}" _c_up[$i]="${c_up_val}" @@ -4488,7 +4501,7 @@ show_status() { echo -e "${CYAN}═══ Traffic (current session) ═══${NC}${EL}" # Record connection history (every 5 min) — only if tracker is not running # to avoid double entries and race conditions on the history file - if ! systemctl is-active conduit-tracker.service &>/dev/null 2>&1; then + if ! systemctl is-active conduit-tracker.service &>/dev/null; then record_connection_history "$connected" "$connecting" fi # Get connection history snapshots (single-pass read) @@ -4692,10 +4705,12 @@ start_conduit() { # Batch: get all existing containers in one docker call local existing_containers=$(docker ps -a --format '{{.Names}}' 2>/dev/null) local running_containers=$(docker ps --format '{{.Names}}' 2>/dev/null) + local _start_failures=0 for i in $(seq 1 $CONTAINER_COUNT); do local name=$(get_container_name $i) local vol=$(get_volume_name $i) + local _rc=0 if echo "$running_containers" | grep -q "^${name}$"; then # Already running — skip @@ -4731,21 +4746,25 @@ start_conduit() { docker volume create "$vol" >/dev/null 2>&1 || true fix_volume_permissions $i run_conduit_container $i + _rc=$? else # Settings unchanged — just resume the stopped container docker start "$name" >/dev/null 2>&1 + _rc=$? fi else # Container doesn't exist — create fresh docker volume create "$vol" >/dev/null 2>&1 || true fix_volume_permissions $i run_conduit_container $i + _rc=$? fi - if [ $? -eq 0 ]; then + if [ $_rc -eq 0 ]; then echo -e "${GREEN}✓ ${name} started${NC}" else echo -e "${RED}✗ Failed to start ${name}${NC}" + _start_failures=$((_start_failures + 1)) fi done # Start background tracker @@ -4754,6 +4773,7 @@ start_conduit() { [ "$SNOWFLAKE_ENABLED" = "true" ] && start_snowflake 2>/dev/null # Start mtproto if enabled [ "$MTPROTO_ENABLED" = "true" ] && start_mtproto 2>/dev/null + [ "$_start_failures" -gt 0 ] && return 1 return 0 } @@ -4774,20 +4794,15 @@ stop_conduit() { fi done # Stop extra containers from previous scaling - local base_name="$(get_container_name 1)" - local idx - docker ps -a --format '{{.Names}}' 2>/dev/null | while read -r cname; do - case "$cname" in - "${base_name%1}"*) - idx="${cname##*[!0-9]}" - if [[ "$idx" =~ ^[0-9]+$ ]] && [ "$idx" -gt "$CONTAINER_COUNT" ]; then - docker stop "$cname" 2>/dev/null || true - docker rm "$cname" 2>/dev/null || true - echo -e "${YELLOW}✓ ${cname} stopped and removed (extra)${NC}" - fi - ;; - esac - done + while read -r cname; do + [[ "$cname" =~ ^conduit(-([0-9]+))?$ ]] || continue + local idx="${BASH_REMATCH[2]:-1}" + if [ "$idx" -gt "$CONTAINER_COUNT" ]; then + docker stop "$cname" 2>/dev/null || true + docker rm "$cname" 2>/dev/null || true + echo -e "${YELLOW}✓ ${cname} stopped and removed (extra)${NC}" + fi + done < <(docker ps -a --format '{{.Names}}' 2>/dev/null) [ "$stopped" -eq 0 ] && echo -e "${YELLOW}No Conduit containers are running${NC}" [ "$SNOWFLAKE_ENABLED" = "true" ] && stop_snowflake 2>/dev/null [ "$MTPROTO_ENABLED" = "true" ] && stop_mtproto 2>/dev/null @@ -4915,7 +4930,7 @@ restart_conduit() { fi done # Remove extra containers beyond current count (dynamic, no hard max) - docker ps -a --format '{{.Names}}' 2>/dev/null | while read -r cname; do + while read -r cname; do [[ "$cname" =~ ^conduit(-([0-9]+))?$ ]] || continue local idx="${BASH_REMATCH[2]:-1}" if [ "$idx" -gt "$CONTAINER_COUNT" ]; then @@ -4923,7 +4938,7 @@ restart_conduit() { docker rm "$cname" 2>/dev/null || true echo -e "${YELLOW}✓ ${cname} removed (scaled down)${NC}" fi - done + done < <(docker ps -a --format '{{.Names}}' 2>/dev/null) # Stop tracker before backup to avoid racing with writes stop_tracker_service 2>/dev/null || true local persist_dir="$INSTALL_DIR/traffic_stats" @@ -5041,10 +5056,10 @@ change_settings() { # Apply to specific container local idx=${targets[0]} if [ -n "$valid_mc" ]; then - eval "MAX_CLIENTS_${idx}=${valid_mc}" + printf -v "MAX_CLIENTS_${idx}" '%s' "$valid_mc" fi if [ -n "$valid_bw" ]; then - eval "BANDWIDTH_${idx}=${valid_bw}" + printf -v "BANDWIDTH_${idx}" '%s' "$valid_bw" fi fi @@ -5225,8 +5240,8 @@ change_resource_limits() { done else local idx=${targets[0]} - [ -n "$valid_cpus" ] && eval "CPUS_${idx}=${valid_cpus}" - [ -n "$valid_mem" ] && eval "MEMORY_${idx}=${valid_mem}" + [ -n "$valid_cpus" ] && printf -v "CPUS_${idx}" '%s' "$valid_cpus" + [ -n "$valid_mem" ] && printf -v "MEMORY_${idx}" '%s' "$valid_mem" fi save_settings @@ -5443,8 +5458,8 @@ uninstall_all() { } manage_containers() { - local stop_manage=0 - trap 'stop_manage=1' SIGINT SIGTERM + local stop_manage=0 _mc_tmpdir="" + trap 'stop_manage=1; [ -n "$_mc_tmpdir" ] && rm -rf "$_mc_tmpdir"' SIGINT SIGTERM SIGHUP SIGQUIT # Calculate recommendation (1 container per core, limited by RAM) local cpu_cores=$(nproc 2>/dev/null || grep -c ^processor /proc/cpuinfo 2>/dev/null || echo 1) @@ -5478,6 +5493,7 @@ manage_containers() { local docker_ps_cache=$(docker ps --format '{{.Names}}' 2>/dev/null) # Collect all docker data in parallel using a temp dir + [ -n "$_mc_tmpdir" ] && rm -rf "$_mc_tmpdir" local _mc_tmpdir=$(mktemp -d /tmp/.conduit_mc.XXXXXX) # mktemp already created the directory @@ -5514,7 +5530,7 @@ manage_containers() { local logs="" [ -f "$_mc_tmpdir/logs_${ci}" ] && logs=$(cat "$_mc_tmpdir/logs_${ci}") if [ -n "$logs" ]; then - IFS='|' read -r conn cing mc_up mc_down <<< $(echo "$logs" | awk '{ + IFS='|' read -r conn cing mc_up mc_down <<< "$(echo "$logs" | awk '{ cing=0; conn=0; up=""; down="" for(j=1;j<=NF;j++){ if($j=="Connecting:") cing=$(j+1)+0 @@ -5523,7 +5539,7 @@ manage_containers() { else if($j=="Down:"){for(k=j+1;k<=NF;k++){if($k=="|"||$k~/Uptime:/)break; down=down (down?" ":"") $k}} } printf "%d|%d|%s|%s", conn, cing, up, down - }') + }')" c_clients="${conn:-0}/${cing:-0}" c_up="${mc_up:-"-"}" c_down="${mc_down:-"-"}" @@ -5688,8 +5704,8 @@ manage_containers() { fi # Save per-container overrides for new containers for i in $(seq $((old_count + 1)) $CONTAINER_COUNT); do - [ -n "$new_cpus" ] && eval "CPUS_${i}=${new_cpus}" - [ -n "$new_mem" ] && eval "MEMORY_${i}=${new_mem}" + [ -n "$new_cpus" ] && printf -v "CPUS_${i}" '%s' "$new_cpus" + [ -n "$new_mem" ] && printf -v "MEMORY_${i}" '%s' "$new_mem" done fi @@ -5942,7 +5958,7 @@ manage_containers() { done echo -ne "\033[?25h" tput rmcup 2>/dev/null || true - trap - SIGINT SIGTERM + trap - SIGINT SIGTERM SIGHUP SIGQUIT } # Get default network interface @@ -5961,8 +5977,8 @@ get_data_usage() { fi local rx=$(cat /sys/class/net/$iface/statistics/rx_bytes 2>/dev/null || echo 0) local tx=$(cat /sys/class/net/$iface/statistics/tx_bytes 2>/dev/null || echo 0) - local used_rx=$((rx - DATA_CAP_BASELINE_RX)) - local used_tx=$((tx - DATA_CAP_BASELINE_TX)) + local used_rx=$((rx - ${DATA_CAP_BASELINE_RX:-0})) + local used_tx=$((tx - ${DATA_CAP_BASELINE_TX:-0})) # Handle counter reset (reboot) if [ "$used_rx" -lt 0 ] || [ "$used_tx" -lt 0 ]; then DATA_CAP_BASELINE_RX=$rx @@ -6169,41 +6185,41 @@ set_data_cap() { save_settings() { local _tmp="$INSTALL_DIR/settings.conf.tmp.$$" cat > "$_tmp" << EOF -MAX_CLIENTS=$MAX_CLIENTS -BANDWIDTH=$BANDWIDTH -CONTAINER_COUNT=$CONTAINER_COUNT -DATA_CAP_GB=$DATA_CAP_GB -DATA_CAP_UP_GB=$DATA_CAP_UP_GB -DATA_CAP_DOWN_GB=$DATA_CAP_DOWN_GB -DATA_CAP_IFACE=$DATA_CAP_IFACE -DATA_CAP_BASELINE_RX=$DATA_CAP_BASELINE_RX -DATA_CAP_BASELINE_TX=$DATA_CAP_BASELINE_TX -DATA_CAP_PRIOR_USAGE=${DATA_CAP_PRIOR_USAGE:-0} -DATA_CAP_PRIOR_RX=${DATA_CAP_PRIOR_RX:-0} -DATA_CAP_PRIOR_TX=${DATA_CAP_PRIOR_TX:-0} +MAX_CLIENTS="$MAX_CLIENTS" +BANDWIDTH="$BANDWIDTH" +CONTAINER_COUNT="$CONTAINER_COUNT" +DATA_CAP_GB="$DATA_CAP_GB" +DATA_CAP_UP_GB="$DATA_CAP_UP_GB" +DATA_CAP_DOWN_GB="$DATA_CAP_DOWN_GB" +DATA_CAP_IFACE="$DATA_CAP_IFACE" +DATA_CAP_BASELINE_RX="$DATA_CAP_BASELINE_RX" +DATA_CAP_BASELINE_TX="$DATA_CAP_BASELINE_TX" +DATA_CAP_PRIOR_USAGE="${DATA_CAP_PRIOR_USAGE:-0}" +DATA_CAP_PRIOR_RX="${DATA_CAP_PRIOR_RX:-0}" +DATA_CAP_PRIOR_TX="${DATA_CAP_PRIOR_TX:-0}" TELEGRAM_BOT_TOKEN="$TELEGRAM_BOT_TOKEN" TELEGRAM_CHAT_ID="$TELEGRAM_CHAT_ID" -TELEGRAM_INTERVAL=${TELEGRAM_INTERVAL:-6} -TELEGRAM_ENABLED=${TELEGRAM_ENABLED:-false} -TELEGRAM_ALERTS_ENABLED=${TELEGRAM_ALERTS_ENABLED:-true} -TELEGRAM_CPU_ALERT=${TELEGRAM_CPU_ALERT:-true} -TELEGRAM_DAILY_SUMMARY=${TELEGRAM_DAILY_SUMMARY:-true} -TELEGRAM_WEEKLY_SUMMARY=${TELEGRAM_WEEKLY_SUMMARY:-true} +TELEGRAM_INTERVAL="${TELEGRAM_INTERVAL:-6}" +TELEGRAM_ENABLED="${TELEGRAM_ENABLED:-false}" +TELEGRAM_ALERTS_ENABLED="${TELEGRAM_ALERTS_ENABLED:-true}" +TELEGRAM_CPU_ALERT="${TELEGRAM_CPU_ALERT:-true}" +TELEGRAM_DAILY_SUMMARY="${TELEGRAM_DAILY_SUMMARY:-true}" +TELEGRAM_WEEKLY_SUMMARY="${TELEGRAM_WEEKLY_SUMMARY:-true}" TELEGRAM_SERVER_LABEL="${TELEGRAM_SERVER_LABEL:-}" -TELEGRAM_START_HOUR=${TELEGRAM_START_HOUR:-0} -DOCKER_CPUS=${DOCKER_CPUS:-} -DOCKER_MEMORY=${DOCKER_MEMORY:-} -TRACKER_ENABLED=${TRACKER_ENABLED:-true} -SNOWFLAKE_ENABLED=${SNOWFLAKE_ENABLED:-false} -SNOWFLAKE_COUNT=${SNOWFLAKE_COUNT:-1} -SNOWFLAKE_CPUS=${SNOWFLAKE_CPUS:-} -SNOWFLAKE_MEMORY=${SNOWFLAKE_MEMORY:-} -MTPROTO_ENABLED=${MTPROTO_ENABLED:-false} -MTPROTO_PORT=${MTPROTO_PORT:-443} +TELEGRAM_START_HOUR="${TELEGRAM_START_HOUR:-0}" +DOCKER_CPUS="${DOCKER_CPUS:-}" +DOCKER_MEMORY="${DOCKER_MEMORY:-}" +TRACKER_ENABLED="${TRACKER_ENABLED:-true}" +SNOWFLAKE_ENABLED="${SNOWFLAKE_ENABLED:-false}" +SNOWFLAKE_COUNT="${SNOWFLAKE_COUNT:-1}" +SNOWFLAKE_CPUS="${SNOWFLAKE_CPUS:-}" +SNOWFLAKE_MEMORY="${SNOWFLAKE_MEMORY:-}" +MTPROTO_ENABLED="${MTPROTO_ENABLED:-false}" +MTPROTO_PORT="${MTPROTO_PORT:-443}" MTPROTO_SECRET="${MTPROTO_SECRET:-}" -MTPROTO_DOMAIN=${MTPROTO_DOMAIN:-google.com} -MTPROTO_CPUS=${MTPROTO_CPUS:-} -MTPROTO_MEMORY=${MTPROTO_MEMORY:-} +MTPROTO_DOMAIN="${MTPROTO_DOMAIN:-google.com}" +MTPROTO_CPUS="${MTPROTO_CPUS:-}" +MTPROTO_MEMORY="${MTPROTO_MEMORY:-}" EOF # Save per-container overrides for i in $(seq 1 "$CONTAINER_COUNT"); do @@ -6211,12 +6227,17 @@ EOF local bw_var="BANDWIDTH_${i}" local cpu_var="CPUS_${i}" local mem_var="MEMORY_${i}" - [ -n "${!mc_var}" ] && echo "${mc_var}=${!mc_var}" >> "$_tmp" - [ -n "${!bw_var}" ] && echo "${bw_var}=${!bw_var}" >> "$_tmp" - [ -n "${!cpu_var}" ] && echo "${cpu_var}=${!cpu_var}" >> "$_tmp" - [ -n "${!mem_var}" ] && echo "${mem_var}=${!mem_var}" >> "$_tmp" + [ -n "${!mc_var}" ] && echo "${mc_var}=\"${!mc_var}\"" >> "$_tmp" + [ -n "${!bw_var}" ] && echo "${bw_var}=\"${!bw_var}\"" >> "$_tmp" + [ -n "${!cpu_var}" ] && echo "${cpu_var}=\"${!cpu_var}\"" >> "$_tmp" + [ -n "${!mem_var}" ] && echo "${mem_var}=\"${!mem_var}\"" >> "$_tmp" done chmod 600 "$_tmp" 2>/dev/null || true + if [ ! -s "$_tmp" ]; then + echo -e " ${RED}✗ Settings file is empty (disk full?). Keeping existing config.${NC}" >&2 + rm -f "$_tmp" + return 1 + fi mv "$_tmp" "$INSTALL_DIR/settings.conf" } @@ -6230,7 +6251,7 @@ escape_telegram_markdown() { text="${text//\`/\\\`}" text="${text//\[/\\[}" text="${text//\]/\\]}" - echo "$text" + printf '%s\n' "$text" } telegram_send_message() { @@ -6336,7 +6357,7 @@ telegram_build_report() { report+=$'\n' report+=$'\n' - local running_count=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -c "^conduit" 2>/dev/null || true) + local running_count=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -cE "^conduit(-[0-9]+)?$" 2>/dev/null || true) running_count=${running_count:-0} local total=$CONTAINER_COUNT if [ "$running_count" -gt 0 ]; then @@ -6477,7 +6498,7 @@ telegram_build_report() { read -r _mt_dl _mt_ul <<< "$_mt_t" local mt_dl_fmt=$(format_bytes ${_mt_dl:-0}) local mt_ul_fmt=$(format_bytes ${_mt_ul:-0}) - report+="📡 MTProxy: Running | ↓${mt_dl_fmt} ↑${mt_ul_fmt}" + report+="✉️ MTProxy: Running | ↓${mt_dl_fmt} ↑${mt_ul_fmt}" report+=$'\n' fi @@ -6586,6 +6607,135 @@ for _ip_url in "https://api.ipify.org" "https://ifconfig.me" "https://icanhazip. _server_ip="" done +PERSIST_DIR="$INSTALL_DIR/traffic_stats" + +# --- Helper functions (not available from management.sh in standalone mode) --- + +get_public_ip() { + [ -n "$_server_ip" ] && { echo "$_server_ip"; return 0; } + local _ip _url + for _url in "https://api.ipify.org" "https://ifconfig.me" "https://icanhazip.com"; do + _ip=$(curl -4 -s --max-time 5 "$_url" 2>/dev/null | tr -d '[:space:]') + echo "$_ip" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' && { echo "$_ip"; return 0; } + done + return 1 +} + +get_snowflake_name() { + local idx=${1:-1} + [ "$idx" -le 1 ] 2>/dev/null && echo "snowflake-proxy" || echo "snowflake-proxy-${idx}" +} + +is_snowflake_running() { + local i + for i in $(seq 1 ${SNOWFLAKE_COUNT:-1}); do + docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^$(get_snowflake_name $i)$" && return 0 + done + return 1 +} + +start_snowflake() { + [ -f "$PERSIST_DIR/data_cap_exceeded" ] && return 1 + local i cname + for i in $(seq 1 ${SNOWFLAKE_COUNT:-1}); do + cname=$(get_snowflake_name $i) + docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${cname}$" && continue + docker start "$cname" >/dev/null 2>&1 || true + done +} + +stop_snowflake() { + local i + for i in $(seq 1 ${SNOWFLAKE_COUNT:-1}); do + docker stop --timeout 10 "$(get_snowflake_name $i)" 2>/dev/null || true + done +} + +restart_snowflake() { + [ -f "$PERSIST_DIR/data_cap_exceeded" ] && return 1 + local i + for i in $(seq 1 ${SNOWFLAKE_COUNT:-1}); do + docker restart "$(get_snowflake_name $i)" >/dev/null 2>&1 || true + done +} + +is_mtproto_running() { + docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^mtproto-proxy$" +} + +start_mtproto() { + [ -f "$PERSIST_DIR/data_cap_exceeded" ] && return 1 + [ -z "$MTPROTO_SECRET" ] && return 1 + docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^mtproto-proxy$" && return 0 + docker start "mtproto-proxy" >/dev/null 2>&1 +} + +get_mtproto_stats() { + is_mtproto_running || { echo "0 0"; return; } + local metrics + metrics=$(curl -s --max-time 2 "http://127.0.0.1:${MTPROTO_STATS_PORT:-3129}/" 2>/dev/null) + if [ -n "$metrics" ]; then + local traffic_in traffic_out + traffic_in=$(echo "$metrics" | awk '/^mtg_telegram_traffic\{.*direction="to_client"/ {sum+=$NF} END {printf "%.0f", sum}' 2>/dev/null) + traffic_out=$(echo "$metrics" | awk '/^mtg_telegram_traffic\{.*direction="from_client"/ {sum+=$NF} END {printf "%.0f", sum}' 2>/dev/null) + echo "${traffic_in:-0} ${traffic_out:-0}" + return + fi + echo "0 0" +} + +get_mtproto_traffic() { + local prior_dl=0 prior_ul=0 + local traffic_file="$PERSIST_DIR/mtproto_traffic" + [ -f "$traffic_file" ] && { read -r prior_dl prior_ul < "$traffic_file" 2>/dev/null || true; } + local cur_dl=0 cur_ul=0 + read -r cur_dl cur_ul <<< "$(get_mtproto_stats)" + echo "$(( ${prior_dl:-0} + ${cur_dl:-0} )) $(( ${prior_ul:-0} + ${cur_ul:-0} ))" +} + +save_mtproto_traffic() { + is_mtproto_running || return + local traffic_file="$PERSIST_DIR/mtproto_traffic" + local cur_dl=0 cur_ul=0 + read -r cur_dl cur_ul <<< "$(get_mtproto_stats)" + [ "${cur_dl:-0}" -eq 0 ] && [ "${cur_ul:-0}" -eq 0 ] && return + local prior_dl=0 prior_ul=0 + [ -f "$traffic_file" ] && { read -r prior_dl prior_ul < "$traffic_file" 2>/dev/null || true; } + echo "$(( ${prior_dl:-0} + ${cur_dl:-0} )) $(( ${prior_ul:-0} + ${cur_ul:-0} ))" > "$traffic_file" +} + +format_bytes() { + local bytes=$1 + [ -z "$bytes" ] || [ "$bytes" -eq 0 ] 2>/dev/null && { echo "0 B"; return; } + if [ "$bytes" -ge 1099511627776 ] 2>/dev/null; then + awk "BEGIN {printf \"%.2f TB\", $bytes/1099511627776}" + elif [ "$bytes" -ge 1073741824 ]; then + awk "BEGIN {printf \"%.2f GB\", $bytes/1073741824}" + elif [ "$bytes" -ge 1048576 ]; then + awk "BEGIN {printf \"%.2f MB\", $bytes/1048576}" + elif [ "$bytes" -ge 1024 ]; then + awk "BEGIN {printf \"%.2f KB\", $bytes/1024}" + else + echo "$bytes B" + fi +} + +# --- End helper functions --- + +# Cache server callback label for multi-server Telegram selection +_lbl_raw="${TELEGRAM_SERVER_LABEL:-$(hostname 2>/dev/null || echo 'server')}" +_cb_label=$(echo "$_lbl_raw" | tr -cd 'a-zA-Z0-9_-' | head -c 40) +[ -z "$_cb_label" ] && _cb_label=$(hostname 2>/dev/null | tr -cd 'a-zA-Z0-9_-' | head -c 40) +[ -z "$_cb_label" ] && _cb_label="server" +_lbl_display=$(printf '%s' "$_lbl_raw" | sed 's/\\/\\\\/g; s/"/\\"/g') + +# Build server selection inline keyboard +# Usage: _server_kb "prefix_" "emoji" +_server_kb() { + local prefix="$1" emoji="${2:-🖥}" + echo "{\"inline_keyboard\":[[{\"text\":\"${emoji} ${_lbl_display}\",\"callback_data\":\"${prefix}${_cb_label}\"}]]}" +} + telegram_send() { local message="$1" # Prepend server label + IP (escape for Markdown) @@ -6654,7 +6804,7 @@ escape_md() { text="${text//\`/\\\`}" text="${text//\[/\\[}" text="${text//\]/\\]}" - echo "$text" + printf '%s\n' "$text" } get_container_name() { @@ -6733,7 +6883,7 @@ get_container_stats() { done local all_stats=$(timeout 10 docker stats --no-stream --format "{{.CPUPerc}} {{.MemUsage}}" $names 2>/dev/null) if [ -z "$all_stats" ]; then - echo "0% 0MiB" + echo "0% 0MiB / 0MiB" elif [ "${CONTAINER_COUNT:-1}" -le 1 ]; then echo "$all_stats" else @@ -6753,7 +6903,7 @@ get_container_stats() { } track_uptime() { - local running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -c "^conduit" 2>/dev/null || true) + local running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -cE "^conduit(-[0-9]+)?$" 2>/dev/null || true) running=${running:-0} echo "$(date +%s)|${running}" >> "$INSTALL_DIR/traffic_stats/uptime_log" # Trim to 7 days @@ -6813,12 +6963,14 @@ check_alerts() { # System-wide CPU check (from /proc/stat, not Docker containers) if [ "${TELEGRAM_CPU_ALERT:-true}" = "true" ] && [ -f /proc/stat ]; then + local _c user nice system idle iowait irq softirq steal guest read -r _c user nice system idle iowait irq softirq steal guest < /proc/stat local total_curr=$((user + nice + system + idle + iowait + irq + softirq + steal)) local work_curr=$((user + nice + system + irq + softirq + steal)) local cpu_state="/tmp/conduit_cpu_alert_state" local cpu_val=0 if [ -f "$cpu_state" ]; then + local total_prev work_prev read -r total_prev work_prev < "$cpu_state" local total_delta=$((total_curr - total_prev)) local work_delta=$((work_curr - work_prev)) @@ -6841,7 +6993,7 @@ System CPU at ${cpu_val}% for 3\\+ minutes" fi # RAM check (from Docker container stats) - local conduit_containers=$(docker ps --format '{{.Names}}' 2>/dev/null | grep "^conduit" 2>/dev/null || true) + local conduit_containers=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -E "^conduit(-[0-9]+)?$" 2>/dev/null || true) local ram_pct="" if [ -n "$conduit_containers" ]; then ram_pct=$(timeout 10 docker stats --no-stream --format "{{.MemPerc}}" $conduit_containers 2>/dev/null | \ @@ -6862,7 +7014,7 @@ Memory usage at ${ram_pct} for 3\\+ minutes" fi # All containers down - local running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -c "^conduit" 2>/dev/null || true) + local running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -cE "^conduit(-[0-9]+)?$" 2>/dev/null || true) running=${running:-0} if [ "$running" -eq 0 ] 2>/dev/null && [ $((now - last_alert_down)) -ge $cooldown ] 2>/dev/null; then telegram_send "🔴 *Alert: All containers down* @@ -6893,7 +7045,7 @@ No connected peers for 2\\+ hours" } record_snapshot() { - local running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -c "^conduit" 2>/dev/null || true) + local running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -cE "^conduit(-[0-9]+)?$" 2>/dev/null || true) running=${running:-0} local total_peers=0 for i in $(seq 1 ${CONTAINER_COUNT:-1}); do @@ -7004,6 +7156,7 @@ process_commands() { import json, sys try: data = json.loads(sys.argv[1]) + allowed_chat = sys.argv[2] if not data.get('ok'): sys.exit(0) results = data.get('result', []) if not results: sys.exit(0) @@ -7014,7 +7167,7 @@ try: if msg: chat_id = msg.get('chat', {}).get('id', 0) text = msg.get('text', '') - if str(chat_id) == '$TELEGRAM_CHAT_ID' and text.startswith('/'): + if str(chat_id) == allowed_chat and text.startswith('/'): safe_text = text.split('|')[0].strip() print(f'{uid}|{safe_text}') else: @@ -7026,7 +7179,7 @@ try: cb_chat_id = cbq.get('message', {}).get('chat', {}).get('id', 0) cb_id = cbq.get('id', '').replace('|', '') cb_data = cbq.get('data', '').split('|')[0].strip() - if str(cb_chat_id) == '$TELEGRAM_CHAT_ID' and cb_data: + if str(cb_chat_id) == allowed_chat and cb_data: print(f'{uid}|callback|{cb_id}|{cb_data}') else: print(f'{uid}|') @@ -7042,7 +7195,7 @@ except Exception: print(f'{max_uid}|') except Exception: pass -" "$response" 2>/dev/null) +" "$response" "$TELEGRAM_CHAT_ID" 2>/dev/null) [ -z "$parsed" ] && return @@ -7056,127 +7209,15 @@ except Exception: local cb_id="$field3" local cb_data="$field4" case "$cb_data" in - mt_start) - telegram_answer_callback "$cb_id" "Starting MTProto..." - if [ "$MTPROTO_ENABLED" = "true" ] && [ -n "$MTPROTO_SECRET" ]; then - start_mtproto >/dev/null 2>&1 - if is_mtproto_running; then - telegram_send "🟢 MTProto proxy started." - else - telegram_send "❌ Failed to start MTProto proxy." - fi - else - telegram_send "❌ MTProto not configured." - fi - ;; - mt_stop) - telegram_answer_callback "$cb_id" "Stopping MTProto..." - if is_mtproto_running; then - save_mtproto_traffic - docker stop --timeout 10 "mtproto-proxy" >/dev/null 2>&1 - telegram_send "🛑 MTProto proxy stopped." - else - telegram_send "ℹ️ MTProto proxy is not running." - fi - ;; - mt_restart) - telegram_answer_callback "$cb_id" "Restarting MTProto..." - if [ -f "$PERSIST_DIR/data_cap_exceeded" ]; then - telegram_send "⚠️ Data cap exceeded. MTProto will not restart." - elif [ "$MTPROTO_ENABLED" = "true" ] && [ -n "$MTPROTO_SECRET" ]; then - save_mtproto_traffic - docker restart "mtproto-proxy" >/dev/null 2>&1 - if is_mtproto_running; then - telegram_send "🟢 MTProto proxy restarted." - else - telegram_send "❌ Failed to restart MTProto proxy." - fi - else - telegram_send "❌ MTProto not configured." - fi - ;; - sf_start) - telegram_answer_callback "$cb_id" "Starting Snowflake..." - if [ "$SNOWFLAKE_ENABLED" = "true" ]; then - start_snowflake >/dev/null 2>&1 - if is_snowflake_running; then - telegram_send "🟢 Snowflake proxy started." - else - telegram_send "❌ Failed to start Snowflake proxy." - fi - else - telegram_send "❌ Snowflake not enabled." - fi - ;; - sf_stop) - telegram_answer_callback "$cb_id" "Stopping Snowflake..." - if is_snowflake_running; then - stop_snowflake >/dev/null 2>&1 - telegram_send "🛑 Snowflake proxy stopped." - else - telegram_send "ℹ️ Snowflake proxy is not running." - fi - ;; - sf_restart) - telegram_answer_callback "$cb_id" "Restarting Snowflake..." - if [ "$SNOWFLAKE_ENABLED" = "true" ]; then - restart_snowflake >/dev/null 2>&1 - if is_snowflake_running; then - telegram_send "🟢 Snowflake proxy restarted." - else - telegram_send "❌ Failed to restart Snowflake proxy." - fi - else - telegram_send "❌ Snowflake not enabled." - fi - ;; - qr_*) - local qr_num="${cb_data#qr_}" - telegram_answer_callback "$cb_id" "Generating QR for container ${qr_num}..." - if [[ "$qr_num" =~ ^[0-9]+$ ]] && [ "$qr_num" -ge 1 ] && [ "$qr_num" -le "${CONTAINER_COUNT:-1}" ]; then - local vol=$(get_volume_name "$qr_num") - local raw_key=$(get_raw_key "$vol") - local node_id=$(get_node_id "$vol") - if [ -n "$raw_key" ] && command -v qrencode &>/dev/null; then - local hostname_str=$(hostname 2>/dev/null || echo "conduit") - local claim_json="{\"version\":1,\"data\":{\"key\":\"${raw_key}\",\"name\":\"${hostname_str}\"}}" - local claim_b64=$(echo -n "$claim_json" | base64 | tr -d '\n') - local claim_url="network.ryve.app://(app)/conduits?claim=${claim_b64}" - qrencode -t PNG -o "/tmp/conduit_qr_${qr_num}.png" "$claim_url" 2>/dev/null - if [ -f "/tmp/conduit_qr_${qr_num}.png" ]; then - telegram_send_photo "/tmp/conduit_qr_${qr_num}.png" "Container ${qr_num} — Conduit ID: ${node_id:-unknown}" - rm -f "/tmp/conduit_qr_${qr_num}.png" - else - telegram_send "❌ Failed to generate QR code for container ${qr_num}" - fi - elif ! command -v qrencode &>/dev/null; then - telegram_send "❌ qrencode not installed. Install with: apt install qrencode" - else - telegram_send "❌ Key not available for container ${qr_num}. Start it first." - fi - else - telegram_answer_callback "$cb_id" "Invalid container" - fi - ;; st_*) - # Only respond if callback matches this server's label - local _lbl="${TELEGRAM_SERVER_LABEL:-$(hostname 2>/dev/null || echo 'server')}" - local _cb_lbl=$(echo "$_lbl" | tr -cd 'a-zA-Z0-9_-' | head -c 50) - [ -z "$_cb_lbl" ] && _cb_lbl=$(hostname 2>/dev/null | tr -cd 'a-zA-Z0-9_-' | head -c 50) - [ -z "$_cb_lbl" ] && _cb_lbl="server" - if [ "$cb_data" = "st_${_cb_lbl}" ]; then + if [ "$cb_data" = "st_${_cb_label}" ]; then telegram_answer_callback "$cb_id" "Fetching status..." local report=$(build_report) telegram_send "$report" fi ;; pr_*) - # Only respond if callback matches this server's label - local _lbl="${TELEGRAM_SERVER_LABEL:-$(hostname 2>/dev/null || echo 'server')}" - local _cb_lbl=$(echo "$_lbl" | tr -cd 'a-zA-Z0-9_-' | head -c 50) - [ -z "$_cb_lbl" ] && _cb_lbl=$(hostname 2>/dev/null | tr -cd 'a-zA-Z0-9_-' | head -c 50) - [ -z "$_cb_lbl" ] && _cb_lbl="server" - if [ "$cb_data" = "pr_${_cb_lbl}" ]; then + if [ "$cb_data" = "pr_${_cb_label}" ]; then telegram_answer_callback "$cb_id" "Fetching peers..." local total_peers=0 local total_cing=0 @@ -7191,6 +7232,575 @@ except Exception: telegram_send "👥 Clients: ${total_peers} connected, ${total_cing} connecting" fi ;; + ut_*) + if [ "$cb_data" = "ut_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Fetching uptime..." + local ut_msg="⏱ *Uptime Report*" + ut_msg+=$'\n' + for i in $(seq 1 ${CONTAINER_COUNT:-1}); do + local cname=$(get_container_name $i) + local is_running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -c "^${cname}$" || true) + if [ "${is_running:-0}" -gt 0 ]; then + local started=$(docker inspect --format='{{.State.StartedAt}}' "$cname" 2>/dev/null) + if [ -n "$started" ]; then + local se=$(date -d "$started" +%s 2>/dev/null || echo 0) + local now_s=$(date +%s) + if [ "$se" -gt 0 ] 2>/dev/null && [ "$se" -le "$now_s" ] 2>/dev/null; then + local diff=$(( now_s - se )) + local d=$((diff / 86400)) h=$(( (diff % 86400) / 3600 )) m=$(( (diff % 3600) / 60 )) + ut_msg+="📦 Container ${i}: ${d}d ${h}h ${m}m" + else + ut_msg+="📦 Container ${i}: ⚠ unknown" + fi + else + ut_msg+="📦 Container ${i}: ⚠ unknown" + fi + else + ut_msg+="📦 Container ${i}: 🔴 stopped" + fi + ut_msg+=$'\n' + done + local avail=$(calc_uptime_pct 86400) + ut_msg+=$'\n' + ut_msg+="📈 Availability: ${avail}% (24h)" + telegram_send "$ut_msg" + fi + ;; + ct_*) + if [ "$cb_data" = "ct_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Fetching containers..." + local ct_msg="📦 *Container Status*" + ct_msg+=$'\n' + local docker_names=$(docker ps --format '{{.Names}}' 2>/dev/null) + for i in $(seq 1 ${CONTAINER_COUNT:-1}); do + local cname=$(get_container_name $i) + ct_msg+=$'\n' + if echo "$docker_names" | grep -q "^${cname}$"; then + ct_msg+="C${i} (${cname}): 🟢 Running" + ct_msg+=$'\n' + local logs=$(timeout 5 docker logs --tail 400 "$cname" 2>&1 | grep "\[STATS\]" | tail -1) + if [ -n "$logs" ]; then + local c_cing c_conn c_up c_down + IFS='|' read -r c_cing c_conn c_up c_down <<< "$(echo "$logs" | awk '{ + cing=0; conn=0; up=""; down="" + for(j=1;j<=NF;j++){ + if($j=="Connecting:") cing=$(j+1)+0 + else if($j=="Connected:") conn=$(j+1)+0 + else if($j=="Up:"){for(k=j+1;k<=NF;k++){if($k=="|"||$k~/Down:/)break; up=up (up?" ":"") $k}} + else if($j=="Down:"){for(k=j+1;k<=NF;k++){if($k=="|"||$k~/Uptime:/)break; down=down (down?" ":"") $k}} + } + printf "%d|%d|%s|%s", cing, conn, up, down + }')" + ct_msg+=" 👥 Connected: ${c_conn:-0} | Connecting: ${c_cing:-0}" + ct_msg+=$'\n' + ct_msg+=" ⬆ Up: ${c_up:-N/A} ⬇ Down: ${c_down:-N/A}" + else + ct_msg+=" ⚠ No stats available yet" + fi + else + ct_msg+="C${i} (${cname}): 🔴 Stopped" + fi + ct_msg+=$'\n' + done + ct_msg+=$'\n' + ct_msg+="/restart\_N /stop\_N /start\_N — manage containers" + telegram_send "$ct_msg" + fi + ;; + sg_*) + if [ "$cb_data" = "sg_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Fetching settings..." + local bw_display="${BANDWIDTH:-5}" + if [ "$bw_display" = "-1" ]; then + bw_display="Unlimited" + else + bw_display="${bw_display} Mbps" + fi + local dc_display="${DATA_CAP_GB:-0}" + if [ "$dc_display" = "0" ]; then + dc_display="Unlimited" + else + dc_display="${dc_display} GB" + fi + local st_msg="⚙️ *Current Settings*" + st_msg+=$'\n' + st_msg+="👥 Max Clients: ${MAX_CLIENTS:-200}" + st_msg+=$'\n' + st_msg+="📶 Bandwidth: ${bw_display}" + st_msg+=$'\n' + st_msg+="📦 Containers: ${CONTAINER_COUNT:-1}" + st_msg+=$'\n' + st_msg+="💾 Data Cap: ${dc_display}" + st_msg+=$'\n' + st_msg+="📊 Tracker: ${TRACKER_ENABLED:-true}" + st_msg+=$'\n' + st_msg+="🔔 Report Interval: every ${TELEGRAM_INTERVAL:-6}h" + st_msg+=$'\n' + st_msg+="🔕 Alerts: ${TELEGRAM_ALERTS_ENABLED:-true}" + st_msg+=$'\n' + st_msg+="🌡 CPU Alert: ${TELEGRAM_CPU_ALERT:-true}" + st_msg+=$'\n' + st_msg+="✉️ MTProto: ${MTPROTO_ENABLED:-false}" + telegram_send "$st_msg" + fi + ;; + he_*) + if [ "$cb_data" = "he_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Running health check..." + local h_msg="🏥 *Health Check*" + h_msg+=$'\n' + if docker info >/dev/null 2>&1; then + h_msg+="🐳 Docker: ✅ Running" + else + h_msg+="🐳 Docker: ❌ Not running" + fi + h_msg+=$'\n' + for i in $(seq 1 ${CONTAINER_COUNT:-1}); do + local cname=$(get_container_name "$i") + local is_running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -c "^${cname}$" || true) + local restarts=$(docker inspect --format='{{.RestartCount}}' "$cname" 2>/dev/null || echo "N/A") + if [ "${is_running:-0}" -gt 0 ]; then + h_msg+="📦 ${cname}: 🟢 Running (restarts: ${restarts})" + else + h_msg+="📦 ${cname}: 🔴 Stopped (restarts: ${restarts})" + fi + h_msg+=$'\n' + done + local net_ok=false + for i in $(seq 1 ${CONTAINER_COUNT:-1}); do + local cname=$(get_container_name "$i") + if timeout 5 docker logs --tail 100 "$cname" 2>&1 | grep -q "\[STATS\]\|Connected to Psiphon"; then + net_ok=true + break + fi + done + if [ "$net_ok" = true ]; then + h_msg+="🌐 Network: ✅ Connected" + else + h_msg+="🌐 Network: ⚠️ No connection detected" + fi + h_msg+=$'\n' + if command -v systemctl &>/dev/null && systemctl is-active conduit-tracker.service &>/dev/null; then + h_msg+="📊 Tracker: ✅ Active" + elif pgrep -f "conduit-tracker" &>/dev/null; then + h_msg+="📊 Tracker: ✅ Active" + else + h_msg+="📊 Tracker: ❌ Inactive" + fi + h_msg+=$'\n' + if command -v geoiplookup &>/dev/null; then + h_msg+="🌍 GeoIP: ✅ geoiplookup" + elif command -v mmdblookup &>/dev/null; then + h_msg+="🌍 GeoIP: ✅ mmdblookup" + else + h_msg+="🌍 GeoIP: ⚠️ Not installed" + fi + telegram_send "$h_msg" + fi + ;; + up_*) + if [ "$cb_data" = "up_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Updating..." + telegram_send "🔄 Checking for updates..." + local conduit_img="ghcr.io/ssmirr/conduit/conduit:latest" + local pull_out + pull_out=$(docker pull "$conduit_img" 2>&1) + if [ $? -ne 0 ]; then + telegram_send "❌ Failed to pull image. Check internet connection." + elif echo "$pull_out" | grep -q "Status: Image is up to date"; then + telegram_send "✅ Docker image is already up to date." + elif echo "$pull_out" | grep -q "Downloaded newer image\|Pull complete"; then + telegram_send "📦 New image found. Recreating containers..." + local upd_ok=0 upd_fail=0 + for i in $(seq 1 ${CONTAINER_COUNT:-1}); do + local cname=$(get_container_name "$i") + local vname + if [ "$i" -eq 1 ]; then vname="conduit-data"; else vname="conduit-data-${i}"; fi + local mc=${MAX_CLIENTS:-200} + local bw=${BANDWIDTH:-5} + local mc_var="MAX_CLIENTS_${i}" + [ -n "${!mc_var:-}" ] && mc="${!mc_var}" + local bw_var="BANDWIDTH_${i}" + [ -n "${!bw_var:-}" ] && bw="${!bw_var}" + local resource_args="" + local cpus_var="CPUS_${i}" + [ -n "${!cpus_var:-}" ] && resource_args+="--cpus ${!cpus_var} " + [ -z "${!cpus_var:-}" ] && [ -n "${DOCKER_CPUS:-}" ] && resource_args+="--cpus ${DOCKER_CPUS} " + local mem_var="MEMORY_${i}" + [ -n "${!mem_var:-}" ] && resource_args+="--memory ${!mem_var} " + [ -z "${!mem_var:-}" ] && [ -n "${DOCKER_MEMORY:-}" ] && resource_args+="--memory ${DOCKER_MEMORY} " + docker rm -f "$cname" >/dev/null 2>&1 + if docker run -d \ + --name "$cname" \ + --restart unless-stopped \ + --log-opt max-size=15m \ + --log-opt max-file=3 \ + -v "${vname}:/home/conduit/data" \ + --network host \ + $resource_args \ + "$conduit_img" \ + start --max-clients "$mc" --bandwidth "$bw" --stats-file >/dev/null 2>&1; then + upd_ok=$((upd_ok + 1)) + else + upd_fail=$((upd_fail + 1)) + fi + done + docker image prune -f >/dev/null 2>&1 + if [ "$upd_fail" -eq 0 ]; then + telegram_send "✅ Update complete. ${upd_ok} container(s) recreated with new image." + else + telegram_send "⚠️ Update: ${upd_ok} OK, ${upd_fail} failed." + fi + else + telegram_send "✅ Image check complete. No changes detected." + fi + fi + ;; + ra_*) + if [ "$cb_data" = "ra_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Restarting all..." + local ra_ok=0 ra_fail=0 + for i in $(seq 1 ${CONTAINER_COUNT:-1}); do + local cname=$(get_container_name "$i") + docker restart "$cname" >/dev/null 2>&1 && ra_ok=$((ra_ok + 1)) || ra_fail=$((ra_fail + 1)) + done + if [ "$SNOWFLAKE_ENABLED" = "true" ]; then + local si + for si in $(seq 1 ${SNOWFLAKE_COUNT:-1}); do + local sf_cname="snowflake-proxy" + [ "$si" -gt 1 ] && sf_cname="snowflake-proxy-${si}" + docker restart "$sf_cname" >/dev/null 2>&1 && ra_ok=$((ra_ok + 1)) || ra_fail=$((ra_fail + 1)) + done + fi + if [ "$MTPROTO_ENABLED" = "true" ]; then + if [ -f "$PERSIST_DIR/data_cap_exceeded" ]; then + ra_fail=$((ra_fail + 1)) + else + save_mtproto_traffic + docker restart "mtproto-proxy" >/dev/null 2>&1 && ra_ok=$((ra_ok + 1)) || ra_fail=$((ra_fail + 1)) + fi + fi + if [ "$ra_fail" -eq 0 ]; then + telegram_send "✅ All ${ra_ok} containers restarted successfully" + else + telegram_send "⚠️ Restarted ${ra_ok} containers (${ra_fail} failed)" + fi + fi + ;; + sa_*) + if [ "$cb_data" = "sa_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Starting all..." + local sa_ok=0 sa_fail=0 + for i in $(seq 1 ${CONTAINER_COUNT:-1}); do + local cname=$(get_container_name "$i") + docker start "$cname" >/dev/null 2>&1 && sa_ok=$((sa_ok + 1)) || sa_fail=$((sa_fail + 1)) + done + if [ "$SNOWFLAKE_ENABLED" = "true" ]; then + local si + for si in $(seq 1 ${SNOWFLAKE_COUNT:-1}); do + local sf_cname="snowflake-proxy" + [ "$si" -gt 1 ] && sf_cname="snowflake-proxy-${si}" + docker start "$sf_cname" >/dev/null 2>&1 && sa_ok=$((sa_ok + 1)) || sa_fail=$((sa_fail + 1)) + done + fi + if [ "$MTPROTO_ENABLED" = "true" ]; then + if [ -f "$PERSIST_DIR/data_cap_exceeded" ]; then + sa_fail=$((sa_fail + 1)) + else + start_mtproto >/dev/null 2>&1 && sa_ok=$((sa_ok + 1)) || sa_fail=$((sa_fail + 1)) + fi + fi + if [ "$sa_fail" -eq 0 ]; then + telegram_send "🟢 All ${sa_ok} containers started successfully" + else + telegram_send "⚠️ Started ${sa_ok} containers (${sa_fail} failed)" + fi + fi + ;; + xa_*) + if [ "$cb_data" = "xa_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Stopping all..." + local sto_ok=0 sto_fail=0 + for i in $(seq 1 ${CONTAINER_COUNT:-1}); do + local cname=$(get_container_name "$i") + docker stop "$cname" >/dev/null 2>&1 && sto_ok=$((sto_ok + 1)) || sto_fail=$((sto_fail + 1)) + done + if [ "$SNOWFLAKE_ENABLED" = "true" ]; then + local si + for si in $(seq 1 ${SNOWFLAKE_COUNT:-1}); do + local sf_cname="snowflake-proxy" + [ "$si" -gt 1 ] && sf_cname="snowflake-proxy-${si}" + docker stop "$sf_cname" >/dev/null 2>&1 && sto_ok=$((sto_ok + 1)) || sto_fail=$((sto_fail + 1)) + done + fi + if [ "$MTPROTO_ENABLED" = "true" ]; then + save_mtproto_traffic + docker stop --timeout 10 "mtproto-proxy" >/dev/null 2>&1 && sto_ok=$((sto_ok + 1)) || sto_fail=$((sto_fail + 1)) + fi + if [ "$sto_fail" -eq 0 ]; then + telegram_send "🛑 All ${sto_ok} containers stopped" + else + telegram_send "⚠️ Stopped ${sto_ok} containers (${sto_fail} failed)" + fi + fi + ;; + rn*|xn*|tn*) + local _pfx="${cb_data:0:2}" + local _tmp="${cb_data:2}" + local _num="${_tmp%%_*}" + if [ "$cb_data" = "${_pfx}${_num}_${_cb_label}" ] && [[ "$_num" =~ ^[0-9]+$ ]]; then + local action="restart" + [ "$_pfx" = "xn" ] && action="stop" + [ "$_pfx" = "tn" ] && action="start" + telegram_answer_callback "$cb_id" "${action^}ing container ${_num}..." + local cname=$(get_container_name "$_num") + if docker "$action" "$cname" >/dev/null 2>&1; then + local emoji="✅" + [ "$action" = "stop" ] && emoji="🛑" + [ "$action" = "start" ] && emoji="🟢" + telegram_send "${emoji} Container ${_num} (${cname}): ${action} successful" + else + telegram_send "❌ Failed to ${action} container ${_num} (${cname})" + fi + fi + ;; + lo*) + local _tmp="${cb_data#lo}" + local _num="${_tmp%%_*}" + if [ "$cb_data" = "lo${_num}_${_cb_label}" ] && [[ "$_num" =~ ^[0-9]+$ ]]; then + telegram_answer_callback "$cb_id" "Fetching logs..." + local cname=$(get_container_name "$_num") + local log_output + log_output=$(timeout 10 docker logs --tail 15 "$cname" 2>&1 || echo "Failed to get logs") + if [ ${#log_output} -gt 3800 ]; then + log_output="${log_output:0:3800}..." + fi + local escaped_cname=$(escape_md "$cname") + telegram_send "📋 *Logs: ${escaped_cname}* (last 15 lines): +\`\`\` +${log_output} +\`\`\`" + fi + ;; + sw_*) + if [ "$cb_data" = "sw_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Fetching Snowflake..." + local _sf_running=false + is_snowflake_running && _sf_running=true + local _sf_status="🔴 Stopped" + [ "$_sf_running" = "true" ] && _sf_status="🟢 Running" + local _sf_count="${SNOWFLAKE_COUNT:-1}" + local _sf_msg="❄️ *Snowflake Proxy* +Status: ${_sf_status} +Instances: ${_sf_count}" + local _sf_buttons="" + if [ "$_sf_running" = "true" ]; then + _sf_buttons="{\"text\":\"🛑 Stop\",\"callback_data\":\"fp_${_cb_label}\"},{\"text\":\"🔄 Restart\",\"callback_data\":\"fr_${_cb_label}\"}" + else + _sf_buttons="{\"text\":\"▶️ Start\",\"callback_data\":\"fs_${_cb_label}\"}" + fi + local _sf_kb="{\"inline_keyboard\":[[${_sf_buttons}]]}" + telegram_send_inline_keyboard "$_sf_msg" "$_sf_kb" + fi + ;; + fs_*) + if [ "$cb_data" = "fs_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Starting Snowflake..." + start_snowflake >/dev/null 2>&1 + if is_snowflake_running; then + telegram_send "🟢 Snowflake proxy started." + else + telegram_send "❌ Failed to start Snowflake proxy." + fi + fi + ;; + fp_*) + if [ "$cb_data" = "fp_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Stopping Snowflake..." + stop_snowflake >/dev/null 2>&1 + telegram_send "🛑 Snowflake proxy stopped." + fi + ;; + fr_*) + if [ "$cb_data" = "fr_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Restarting Snowflake..." + restart_snowflake >/dev/null 2>&1 + if is_snowflake_running; then + telegram_send "🟢 Snowflake proxy restarted." + else + telegram_send "❌ Failed to restart Snowflake proxy." + fi + fi + ;; + px_*) + if [ "$cb_data" = "px_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Fetching proxy..." + local _mt_ip + _mt_ip=$(get_public_ip) + if [ -z "$_mt_ip" ]; then + telegram_send "❌ Could not detect server IP." + else + local _mt_link="tg://proxy?server=${_mt_ip}&port=${MTPROTO_PORT}&secret=${MTPROTO_SECRET}" + local _mt_running=false + is_mtproto_running && _mt_running=true + local _mt_status="🔴 Stopped" + [ "$_mt_running" = "true" ] && _mt_status="🟢 Running" + local _mt_t + _mt_t=$(get_mtproto_traffic) + local _mt_dl _mt_ul + read -r _mt_dl _mt_ul <<< "$_mt_t" + local _mt_traffic="" + if [ "${_mt_dl:-0}" -gt 0 ] || [ "${_mt_ul:-0}" -gt 0 ] 2>/dev/null; then + _mt_traffic=" +Traffic: ↓ $(format_bytes ${_mt_dl:-0}) ↑ $(format_bytes ${_mt_ul:-0})" + fi + local _mt_msg="✉️ *MTProto Proxy* +Status: ${_mt_status} +Server: \`${_mt_ip}\` +Port: ${MTPROTO_PORT} +Domain: ${MTPROTO_DOMAIN}${_mt_traffic} + +🔗 [Connect to Proxy](${_mt_link})" + local _mt_buttons="" + if [ "$_mt_running" = "true" ]; then + _mt_buttons="{\"text\":\"🛑 Stop\",\"callback_data\":\"mp_${_cb_label}\"},{\"text\":\"🔄 Restart\",\"callback_data\":\"mr_${_cb_label}\"}" + else + _mt_buttons="{\"text\":\"▶️ Start\",\"callback_data\":\"ms_${_cb_label}\"}" + fi + local _mt_kb="{\"inline_keyboard\":[[${_mt_buttons}]]}" + if command -v qrencode &>/dev/null; then + qrencode -t PNG -o /tmp/mtproto_qr.png "$_mt_link" 2>/dev/null + if [ -f /tmp/mtproto_qr.png ]; then + telegram_send_photo "/tmp/mtproto_qr.png" "$_mt_msg" + rm -f /tmp/mtproto_qr.png + telegram_send_inline_keyboard "⚙️ MTProto Controls:" "$_mt_kb" + else + telegram_send_inline_keyboard "$_mt_msg" "$_mt_kb" + fi + else + telegram_send_inline_keyboard "$_mt_msg" "$_mt_kb" + fi + fi + fi + ;; + ms_*) + if [ "$cb_data" = "ms_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Starting MTProto..." + if [ "$MTPROTO_ENABLED" = "true" ] && [ -n "$MTPROTO_SECRET" ]; then + start_mtproto >/dev/null 2>&1 + if is_mtproto_running; then + telegram_send "🟢 MTProto proxy started." + else + telegram_send "❌ Failed to start MTProto proxy." + fi + else + telegram_send "❌ MTProto not configured." + fi + fi + ;; + mp_*) + if [ "$cb_data" = "mp_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Stopping MTProto..." + if is_mtproto_running; then + save_mtproto_traffic + docker stop --timeout 10 "mtproto-proxy" >/dev/null 2>&1 + telegram_send "🛑 MTProto proxy stopped." + else + telegram_send "ℹ️ MTProto proxy is not running." + fi + fi + ;; + mr_*) + if [ "$cb_data" = "mr_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "Restarting MTProto..." + if [ -f "$PERSIST_DIR/data_cap_exceeded" ]; then + telegram_send "⚠️ Data cap exceeded. MTProto will not restart." + elif [ "$MTPROTO_ENABLED" = "true" ] && [ -n "$MTPROTO_SECRET" ]; then + save_mtproto_traffic + docker restart "mtproto-proxy" >/dev/null 2>&1 + if is_mtproto_running; then + telegram_send "🟢 MTProto proxy restarted." + else + telegram_send "❌ Failed to restart MTProto proxy." + fi + else + telegram_send "❌ MTProto not configured." + fi + fi + ;; + qs_*) + if [ "$cb_data" = "qs_${_cb_label}" ]; then + telegram_answer_callback "$cb_id" "QR code..." + if [ "${CONTAINER_COUNT:-1}" -le 1 ]; then + local vol=$(get_volume_name 1) + local raw_key=$(get_raw_key "$vol") + local node_id=$(get_node_id "$vol") + if [ -n "$raw_key" ] && command -v qrencode &>/dev/null; then + local hostname_str=$(hostname 2>/dev/null || echo "conduit") + local claim_json="{\"version\":1,\"data\":{\"key\":\"${raw_key}\",\"name\":\"${hostname_str}\"}}" + local claim_b64=$(echo -n "$claim_json" | base64 | tr -d '\n') + local claim_url="network.ryve.app://(app)/conduits?claim=${claim_b64}" + qrencode -t PNG -o /tmp/conduit_qr_1.png "$claim_url" 2>/dev/null + if [ -f /tmp/conduit_qr_1.png ]; then + telegram_send_photo "/tmp/conduit_qr_1.png" "Conduit ID: ${node_id:-unknown}" + rm -f /tmp/conduit_qr_1.png + else + telegram_send "❌ Failed to generate QR code" + fi + elif ! command -v qrencode &>/dev/null; then + telegram_send "❌ qrencode not installed. Install with: apt install qrencode" + else + telegram_send "❌ Key not available. Start container first." + fi + else + local rows="" row="" row_count=0 + for i in $(seq 1 ${CONTAINER_COUNT:-1}); do + [ -n "$row" ] && row+="," + row+="{\"text\":\"Container ${i}\",\"callback_data\":\"qn${i}_${_cb_label}\"}" + row_count=$((row_count + 1)) + if [ "$row_count" -ge 4 ]; then + [ -n "$rows" ] && rows+="," + rows+="[${row}]" + row="" + row_count=0 + fi + done + if [ -n "$row" ]; then + [ -n "$rows" ] && rows+="," + rows+="[${row}]" + fi + local kb="{\"inline_keyboard\":[${rows}]}" + telegram_send_inline_keyboard "📱 Select a container for QR code:" "$kb" + fi + fi + ;; + qn*) + local _tmp="${cb_data#qn}" + local _num="${_tmp%%_*}" + if [ "$cb_data" = "qn${_num}_${_cb_label}" ] && [[ "$_num" =~ ^[0-9]+$ ]] && [ "$_num" -ge 1 ] && [ "$_num" -le "${CONTAINER_COUNT:-1}" ]; then + telegram_answer_callback "$cb_id" "Generating QR for container ${_num}..." + local vol=$(get_volume_name "$_num") + local raw_key=$(get_raw_key "$vol") + local node_id=$(get_node_id "$vol") + if [ -n "$raw_key" ] && command -v qrencode &>/dev/null; then + local hostname_str=$(hostname 2>/dev/null || echo "conduit") + local claim_json="{\"version\":1,\"data\":{\"key\":\"${raw_key}\",\"name\":\"${hostname_str}\"}}" + local claim_b64=$(echo -n "$claim_json" | base64 | tr -d '\n') + local claim_url="network.ryve.app://(app)/conduits?claim=${claim_b64}" + qrencode -t PNG -o "/tmp/conduit_qr_${_num}.png" "$claim_url" 2>/dev/null + if [ -f "/tmp/conduit_qr_${_num}.png" ]; then + telegram_send_photo "/tmp/conduit_qr_${_num}.png" "Container ${_num} — Conduit ID: ${node_id:-unknown}" + rm -f "/tmp/conduit_qr_${_num}.png" + else + telegram_send "❌ Failed to generate QR code for container ${_num}" + fi + elif ! command -v qrencode &>/dev/null; then + telegram_send "❌ qrencode not installed. Install with: apt install qrencode" + else + telegram_send "❌ Key not available for container ${_num}. Start it first." + fi + fi + ;; *) telegram_answer_callback "$cb_id" "" ;; @@ -7198,289 +7808,50 @@ except Exception: continue fi - # Handle regular commands + # Handle regular commands — show server selection for multi-server support local cmd="$field2" case "$cmd" in /status|/status@*) - local _lbl="${TELEGRAM_SERVER_LABEL:-$(hostname 2>/dev/null || echo 'server')}" - local _cb_lbl=$(echo "$_lbl" | tr -cd 'a-zA-Z0-9_-' | head -c 50) - [ -z "$_cb_lbl" ] && _cb_lbl=$(hostname 2>/dev/null | tr -cd 'a-zA-Z0-9_-' | head -c 50) - [ -z "$_cb_lbl" ] && _cb_lbl="server" - local _lbl_j=$(printf '%s' "$_lbl" | sed 's/\\/\\\\/g; s/"/\\"/g') - local kb="{\"inline_keyboard\":[[{\"text\":\"📊 ${_lbl_j}\",\"callback_data\":\"st_${_cb_lbl}\"}]]}" - telegram_send_inline_keyboard "Tap to view status:" "$kb" + telegram_send_inline_keyboard "Tap to view status:" "$(_server_kb "st_" "📊")" ;; /peers|/peers@*) - local _lbl="${TELEGRAM_SERVER_LABEL:-$(hostname 2>/dev/null || echo 'server')}" - local _cb_lbl=$(echo "$_lbl" | tr -cd 'a-zA-Z0-9_-' | head -c 50) - [ -z "$_cb_lbl" ] && _cb_lbl=$(hostname 2>/dev/null | tr -cd 'a-zA-Z0-9_-' | head -c 50) - [ -z "$_cb_lbl" ] && _cb_lbl="server" - local _lbl_j=$(printf '%s' "$_lbl" | sed 's/\\/\\\\/g; s/"/\\"/g') - local kb="{\"inline_keyboard\":[[{\"text\":\"👥 ${_lbl_j}\",\"callback_data\":\"pr_${_cb_lbl}\"}]]}" - telegram_send_inline_keyboard "Tap to view peers:" "$kb" + telegram_send_inline_keyboard "Tap to view peers:" "$(_server_kb "pr_" "👥")" ;; /uptime|/uptime@*) - local ut_msg="⏱ *Uptime Report*" - ut_msg+=$'\n' - for i in $(seq 1 ${CONTAINER_COUNT:-1}); do - local cname=$(get_container_name $i) - local is_running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -c "^${cname}$" || true) - if [ "${is_running:-0}" -gt 0 ]; then - local started=$(docker inspect --format='{{.State.StartedAt}}' "$cname" 2>/dev/null) - if [ -n "$started" ]; then - local se=$(date -d "$started" +%s 2>/dev/null || echo 0) - local diff=$(( $(date +%s) - se )) - local d=$((diff / 86400)) h=$(( (diff % 86400) / 3600 )) m=$(( (diff % 3600) / 60 )) - ut_msg+="📦 Container ${i}: ${d}d ${h}h ${m}m" - else - ut_msg+="📦 Container ${i}: ⚠ unknown" - fi - else - ut_msg+="📦 Container ${i}: 🔴 stopped" - fi - ut_msg+=$'\n' - done - local avail=$(calc_uptime_pct 86400) - ut_msg+=$'\n' - ut_msg+="📈 Availability: ${avail}% (24h)" - telegram_send "$ut_msg" + telegram_send_inline_keyboard "Tap to view uptime:" "$(_server_kb "ut_" "⏱")" ;; /containers|/containers@*) - local ct_msg="📦 *Container Status*" - ct_msg+=$'\n' - local docker_names=$(docker ps --format '{{.Names}}' 2>/dev/null) - for i in $(seq 1 ${CONTAINER_COUNT:-1}); do - local cname=$(get_container_name $i) - ct_msg+=$'\n' - if echo "$docker_names" | grep -q "^${cname}$"; then - ct_msg+="C${i} (${cname}): 🟢 Running" - ct_msg+=$'\n' - local logs=$(timeout 5 docker logs --tail 400 "$cname" 2>&1 | grep "\[STATS\]" | tail -1) - if [ -n "$logs" ]; then - local c_cing c_conn c_up c_down - IFS='|' read -r c_cing c_conn c_up c_down <<< $(echo "$logs" | awk '{ - cing=0; conn=0; up=""; down="" - for(j=1;j<=NF;j++){ - if($j=="Connecting:") cing=$(j+1)+0 - else if($j=="Connected:") conn=$(j+1)+0 - else if($j=="Up:"){for(k=j+1;k<=NF;k++){if($k=="|"||$k~/Down:/)break; up=up (up?" ":"") $k}} - else if($j=="Down:"){for(k=j+1;k<=NF;k++){if($k=="|"||$k~/Uptime:/)break; down=down (down?" ":"") $k}} - } - printf "%d|%d|%s|%s", cing, conn, up, down - }') - ct_msg+=" 👥 Connected: ${c_conn:-0} | Connecting: ${c_cing:-0}" - ct_msg+=$'\n' - ct_msg+=" ⬆ Up: ${c_up:-N/A} ⬇ Down: ${c_down:-N/A}" - else - ct_msg+=" ⚠ No stats available yet" - fi - else - ct_msg+="C${i} (${cname}): 🔴 Stopped" - fi - ct_msg+=$'\n' - done - ct_msg+=$'\n' - ct_msg+="/restart\_N /stop\_N /start\_N — manage containers" - telegram_send "$ct_msg" + telegram_send_inline_keyboard "Tap to view containers:" "$(_server_kb "ct_" "📦")" ;; /restart_all|/restart_all@*) - local ra_ok=0 ra_fail=0 - for i in $(seq 1 ${CONTAINER_COUNT:-1}); do - local cname=$(get_container_name "$i") - if docker restart "$cname" >/dev/null 2>&1; then - ra_ok=$((ra_ok + 1)) - else - ra_fail=$((ra_fail + 1)) - fi - done - # Restart snowflake containers if enabled - if [ "$SNOWFLAKE_ENABLED" = "true" ]; then - local si - for si in $(seq 1 ${SNOWFLAKE_COUNT:-1}); do - local sf_cname="snowflake-proxy" - [ "$si" -gt 1 ] && sf_cname="snowflake-proxy-${si}" - docker restart "$sf_cname" >/dev/null 2>&1 && ra_ok=$((ra_ok + 1)) || ra_fail=$((ra_fail + 1)) - done - fi - # Restart mtproto container if enabled - if [ "$MTPROTO_ENABLED" = "true" ]; then - if [ -f "$PERSIST_DIR/data_cap_exceeded" ]; then - ra_fail=$((ra_fail + 1)) - else - save_mtproto_traffic - docker restart "mtproto-proxy" >/dev/null 2>&1 && ra_ok=$((ra_ok + 1)) || ra_fail=$((ra_fail + 1)) - fi - fi - if [ "$ra_fail" -eq 0 ]; then - telegram_send "✅ All ${ra_ok} containers restarted successfully" - else - telegram_send "⚠️ Restarted ${ra_ok} containers (${ra_fail} failed)" - fi + telegram_send_inline_keyboard "Tap server to restart all:" "$(_server_kb "ra_" "🔄")" ;; /start_all|/start_all@*) - local sa_ok=0 sa_fail=0 - for i in $(seq 1 ${CONTAINER_COUNT:-1}); do - local cname=$(get_container_name "$i") - if docker start "$cname" >/dev/null 2>&1; then - sa_ok=$((sa_ok + 1)) - else - sa_fail=$((sa_fail + 1)) - fi - done - # Start snowflake containers if enabled - if [ "$SNOWFLAKE_ENABLED" = "true" ]; then - local si - for si in $(seq 1 ${SNOWFLAKE_COUNT:-1}); do - local sf_cname="snowflake-proxy" - [ "$si" -gt 1 ] && sf_cname="snowflake-proxy-${si}" - docker start "$sf_cname" >/dev/null 2>&1 && sa_ok=$((sa_ok + 1)) || sa_fail=$((sa_fail + 1)) - done - fi - # Start mtproto container if enabled - if [ "$MTPROTO_ENABLED" = "true" ]; then - if [ -f "$PERSIST_DIR/data_cap_exceeded" ]; then - sa_fail=$((sa_fail + 1)) - else - start_mtproto >/dev/null 2>&1 && sa_ok=$((sa_ok + 1)) || sa_fail=$((sa_fail + 1)) - fi - fi - if [ "$sa_fail" -eq 0 ]; then - telegram_send "🟢 All ${sa_ok} containers started successfully" - else - telegram_send "⚠️ Started ${sa_ok} containers (${sa_fail} failed)" - fi + telegram_send_inline_keyboard "Tap server to start all:" "$(_server_kb "sa_" "🟢")" ;; /stop_all|/stop_all@*) - local sto_ok=0 sto_fail=0 - for i in $(seq 1 ${CONTAINER_COUNT:-1}); do - local cname=$(get_container_name "$i") - if docker stop "$cname" >/dev/null 2>&1; then - sto_ok=$((sto_ok + 1)) - else - sto_fail=$((sto_fail + 1)) - fi - done - # Stop snowflake containers if enabled - if [ "$SNOWFLAKE_ENABLED" = "true" ]; then - local si - for si in $(seq 1 ${SNOWFLAKE_COUNT:-1}); do - local sf_cname="snowflake-proxy" - [ "$si" -gt 1 ] && sf_cname="snowflake-proxy-${si}" - docker stop "$sf_cname" >/dev/null 2>&1 && sto_ok=$((sto_ok + 1)) || sto_fail=$((sto_fail + 1)) - done - fi - # Stop mtproto container if enabled - if [ "$MTPROTO_ENABLED" = "true" ]; then - save_mtproto_traffic - docker stop --timeout 10 "mtproto-proxy" >/dev/null 2>&1 && sto_ok=$((sto_ok + 1)) || sto_fail=$((sto_fail + 1)) - fi - if [ "$sto_fail" -eq 0 ]; then - telegram_send "🛑 All ${sto_ok} containers stopped" - else - telegram_send "⚠️ Stopped ${sto_ok} containers (${sto_fail} failed)" - fi + telegram_send_inline_keyboard "Tap server to stop all:" "$(_server_kb "xa_" "🛑")" ;; /restart_*|/stop_*|/start_*) - local action="${cmd%%_*}" # /restart, /stop, or /start - action="${action#/}" # restart, stop, or start + local action="${cmd%%_*}" + action="${action#/}" local num="${cmd#*_}" - num="${num%%@*}" # strip @botname suffix + num="${num%%@*}" if ! [[ "$num" =~ ^[0-9]+$ ]] || [ "$num" -lt 1 ] || [ "$num" -gt "${CONTAINER_COUNT:-1}" ]; then telegram_send "❌ Invalid container number: ${num}. Use 1-${CONTAINER_COUNT:-1}." else - local cname=$(get_container_name "$num") - if docker "$action" "$cname" >/dev/null 2>&1; then - local emoji="✅" - [ "$action" = "stop" ] && emoji="🛑" - [ "$action" = "start" ] && emoji="🟢" - telegram_send "${emoji} Container ${num} (${cname}): ${action} successful" - else - telegram_send "❌ Failed to ${action} container ${num} (${cname})" - fi + local prefix="rn" + local emoji="🔄" + [ "$action" = "stop" ] && prefix="xn" && emoji="🛑" + [ "$action" = "start" ] && prefix="tn" && emoji="🟢" + telegram_send_inline_keyboard "Tap server to ${action} container ${num}:" "$(_server_kb "${prefix}${num}_" "$emoji")" fi ;; /settings|/settings@*) - local bw_display="${BANDWIDTH:-5}" - if [ "$bw_display" = "-1" ]; then - bw_display="Unlimited" - else - bw_display="${bw_display} Mbps" - fi - local dc_display="${DATA_CAP_GB:-0}" - if [ "$dc_display" = "0" ]; then - dc_display="Unlimited" - else - dc_display="${dc_display} GB" - fi - local st_msg="⚙️ *Current Settings*" - st_msg+=$'\n' - st_msg+="👥 Max Clients: ${MAX_CLIENTS:-200}" - st_msg+=$'\n' - st_msg+="📶 Bandwidth: ${bw_display}" - st_msg+=$'\n' - st_msg+="📦 Containers: ${CONTAINER_COUNT:-1}" - st_msg+=$'\n' - st_msg+="💾 Data Cap: ${dc_display}" - st_msg+=$'\n' - st_msg+="📊 Tracker: ${TRACKER_ENABLED:-true}" - st_msg+=$'\n' - st_msg+="🔔 Report Interval: every ${TELEGRAM_INTERVAL:-6}h" - st_msg+=$'\n' - st_msg+="🔕 Alerts: ${TELEGRAM_ALERTS_ENABLED:-true}" - st_msg+=$'\n' - st_msg+="🌡 CPU Alert: ${TELEGRAM_CPU_ALERT:-true}" - st_msg+=$'\n' - st_msg+="📡 MTProto: ${MTPROTO_ENABLED:-false}" - telegram_send "$st_msg" + telegram_send_inline_keyboard "Tap to view settings:" "$(_server_kb "sg_" "⚙")" ;; /health|/health@*) - local h_msg="🏥 *Health Check*" - h_msg+=$'\n' - if docker info >/dev/null 2>&1; then - h_msg+="🐳 Docker: ✅ Running" - else - h_msg+="🐳 Docker: ❌ Not running" - fi - h_msg+=$'\n' - for i in $(seq 1 ${CONTAINER_COUNT:-1}); do - local cname=$(get_container_name "$i") - local is_running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -c "^${cname}$" || true) - local restarts=$(docker inspect --format='{{.RestartCount}}' "$cname" 2>/dev/null || echo "N/A") - if [ "${is_running:-0}" -gt 0 ]; then - h_msg+="📦 ${cname}: 🟢 Running (restarts: ${restarts})" - else - h_msg+="📦 ${cname}: 🔴 Stopped (restarts: ${restarts})" - fi - h_msg+=$'\n' - done - local net_ok=false - for i in $(seq 1 ${CONTAINER_COUNT:-1}); do - local cname=$(get_container_name "$i") - if timeout 5 docker logs --tail 100 "$cname" 2>&1 | grep -q "\[STATS\]\|Connected to Psiphon"; then - net_ok=true - break - fi - done - if [ "$net_ok" = true ]; then - h_msg+="🌐 Network: ✅ Connected" - else - h_msg+="🌐 Network: ⚠️ No connection detected" - fi - h_msg+=$'\n' - if command -v systemctl &>/dev/null && systemctl is-active conduit-tracker.service &>/dev/null; then - h_msg+="📊 Tracker: ✅ Active" - else - h_msg+="📊 Tracker: ❌ Inactive" - fi - h_msg+=$'\n' - if command -v geoiplookup &>/dev/null; then - h_msg+="🌍 GeoIP: ✅ geoiplookup" - elif command -v mmdblookup &>/dev/null; then - h_msg+="🌍 GeoIP: ✅ mmdblookup" - else - h_msg+="🌍 GeoIP: ⚠️ Not installed" - fi - telegram_send "$h_msg" + telegram_send_inline_keyboard "Tap to run health check:" "$(_server_kb "he_" "🩺")" ;; /logs_*) local log_num="${cmd#/logs_}" @@ -7488,205 +7859,57 @@ except Exception: if ! [[ "$log_num" =~ ^[0-9]+$ ]] || [ "$log_num" -lt 1 ] || [ "$log_num" -gt "${CONTAINER_COUNT:-1}" ]; then telegram_send "❌ Invalid container number: ${log_num}. Use 1-${CONTAINER_COUNT:-1}." else - local cname=$(get_container_name "$log_num") - local log_output - log_output=$(timeout 10 docker logs --tail 15 "$cname" 2>&1 || echo "Failed to get logs") - # Truncate to fit Telegram 4096 char limit - if [ ${#log_output} -gt 3800 ]; then - log_output="${log_output:0:3800}..." - fi - # Send without escape_md — code blocks render content literally - local escaped_cname=$(escape_md "$cname") - telegram_send "📋 *Logs: ${escaped_cname}* (last 15 lines): -\`\`\` -${log_output} -\`\`\`" + telegram_send_inline_keyboard "Tap server for logs (container ${log_num}):" "$(_server_kb "lo${log_num}_" "📜")" fi ;; /update|/update@*) - telegram_send "🔄 Checking for updates..." - local conduit_img="ghcr.io/ssmirr/conduit/conduit:latest" - local pull_out - pull_out=$(docker pull "$conduit_img" 2>&1) - if [ $? -ne 0 ]; then - telegram_send "❌ Failed to pull image. Check internet connection." - elif echo "$pull_out" | grep -q "Status: Image is up to date"; then - telegram_send "✅ Docker image is already up to date." - elif echo "$pull_out" | grep -q "Downloaded newer image\|Pull complete"; then - telegram_send "📦 New image found. Recreating containers..." - local upd_ok=0 upd_fail=0 - for i in $(seq 1 ${CONTAINER_COUNT:-1}); do - local cname=$(get_container_name "$i") - local vname - if [ "$i" -eq 1 ]; then vname="conduit-data"; else vname="conduit-data-${i}"; fi - local mc=${MAX_CLIENTS:-200} - local bw=${BANDWIDTH:-5} - # Per-container overrides - local mc_var="MAX_CLIENTS_${i}" - [ -n "${!mc_var:-}" ] && mc="${!mc_var}" - local bw_var="BANDWIDTH_${i}" - [ -n "${!bw_var:-}" ] && bw="${!bw_var}" - local resource_args="" - local cpus_var="CPUS_${i}" - [ -n "${!cpus_var:-}" ] && resource_args+="--cpus ${!cpus_var} " - [ -z "${!cpus_var:-}" ] && [ -n "${DOCKER_CPUS:-}" ] && resource_args+="--cpus ${DOCKER_CPUS} " - local mem_var="MEMORY_${i}" - [ -n "${!mem_var:-}" ] && resource_args+="--memory ${!mem_var} " - [ -z "${!mem_var:-}" ] && [ -n "${DOCKER_MEMORY:-}" ] && resource_args+="--memory ${DOCKER_MEMORY} " - docker rm -f "$cname" >/dev/null 2>&1 - if docker run -d \ - --name "$cname" \ - --restart unless-stopped \ - --log-opt max-size=15m \ - --log-opt max-file=3 \ - -v "${vname}:/home/conduit/data" \ - --network host \ - $resource_args \ - "$conduit_img" \ - start --max-clients "$mc" --bandwidth "$bw" --stats-file >/dev/null 2>&1; then - upd_ok=$((upd_ok + 1)) - else - upd_fail=$((upd_fail + 1)) - fi - done - # Clean up old dangling images - docker image prune -f >/dev/null 2>&1 - if [ "$upd_fail" -eq 0 ]; then - telegram_send "✅ Update complete. ${upd_ok} container(s) recreated with new image." - else - telegram_send "⚠️ Update: ${upd_ok} OK, ${upd_fail} failed." - fi - else - telegram_send "✅ Image check complete. No changes detected." - fi + telegram_send_inline_keyboard "Tap server to update:" "$(_server_kb "up_" "🔄")" ;; /qr|/qr@*) - if [ "${CONTAINER_COUNT:-1}" -le 1 ]; then - # Single container: generate and send QR directly - local vol=$(get_volume_name 1) - local raw_key=$(get_raw_key "$vol") - local node_id=$(get_node_id "$vol") - if [ -n "$raw_key" ] && command -v qrencode &>/dev/null; then - local hostname_str=$(hostname 2>/dev/null || echo "conduit") - local claim_json="{\"version\":1,\"data\":{\"key\":\"${raw_key}\",\"name\":\"${hostname_str}\"}}" - local claim_b64=$(echo -n "$claim_json" | base64 | tr -d '\n') - local claim_url="network.ryve.app://(app)/conduits?claim=${claim_b64}" - qrencode -t PNG -o /tmp/conduit_qr_1.png "$claim_url" 2>/dev/null - if [ -f /tmp/conduit_qr_1.png ]; then - telegram_send_photo "/tmp/conduit_qr_1.png" "Conduit ID: ${node_id:-unknown}" - rm -f /tmp/conduit_qr_1.png - else - telegram_send "❌ Failed to generate QR code" - fi - elif ! command -v qrencode &>/dev/null; then - telegram_send "❌ qrencode not installed. Install with: apt install qrencode" - else - telegram_send "❌ Key not available. Start container first." - fi - else - # Multiple containers: send inline keyboard for selection - local buttons="" - for i in $(seq 1 ${CONTAINER_COUNT:-1}); do - [ -n "$buttons" ] && buttons+="," - buttons+="{\"text\":\"Container ${i}\",\"callback_data\":\"qr_${i}\"}" - done - local kb="{\"inline_keyboard\":[[${buttons}]]}" - telegram_send_inline_keyboard "📱 Select a container for QR code:" "$kb" - fi + telegram_send_inline_keyboard "Tap server for QR code:" "$(_server_kb "qs_" "📱")" ;; /snowflake|/snowflake@*) if [ "$SNOWFLAKE_ENABLED" != "true" ]; then telegram_send "❌ Snowflake proxy is not enabled." else - local _sf_running=false - is_snowflake_running && _sf_running=true - local _sf_status="🔴 Stopped" - [ "$_sf_running" = "true" ] && _sf_status="🟢 Running" - local _sf_count="${SNOWFLAKE_COUNT:-1}" - local _sf_msg="❄️ *Snowflake Proxy* -Status: ${_sf_status} -Instances: ${_sf_count}" - local _sf_buttons="" - if [ "$_sf_running" = "true" ]; then - _sf_buttons="{\"text\":\"🛑 Stop\",\"callback_data\":\"sf_stop\"},{\"text\":\"🔄 Restart\",\"callback_data\":\"sf_restart\"}" - else - _sf_buttons="{\"text\":\"▶️ Start\",\"callback_data\":\"sf_start\"}" - fi - local _sf_kb="{\"inline_keyboard\":[[${_sf_buttons}]]}" - telegram_send_inline_keyboard "$_sf_msg" "$_sf_kb" + telegram_send_inline_keyboard "Tap to view Snowflake:" "$(_server_kb "sw_" "❄")" fi ;; /proxy|/proxy@*) if [ "$MTPROTO_ENABLED" != "true" ] || [ -z "$MTPROTO_SECRET" ]; then telegram_send "❌ MTProto proxy is not configured." else - local _mt_ip - _mt_ip=$(get_public_ip) - if [ -z "$_mt_ip" ]; then - telegram_send "❌ Could not detect server IP." - else - local _mt_link="tg://proxy?server=${_mt_ip}&port=${MTPROTO_PORT}&secret=${MTPROTO_SECRET}" - local _mt_running=false - docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^mtproto-proxy$" && _mt_running=true - local _mt_status="🔴 Stopped" - [ "$_mt_running" = "true" ] && _mt_status="🟢 Running" - local _mt_t - _mt_t=$(get_mtproto_traffic) - local _mt_dl _mt_ul - read -r _mt_dl _mt_ul <<< "$_mt_t" - local _mt_traffic="" - if [ "${_mt_dl:-0}" -gt 0 ] || [ "${_mt_ul:-0}" -gt 0 ] 2>/dev/null; then - _mt_traffic=" -Traffic: ↓ $(format_bytes ${_mt_dl:-0}) ↑ $(format_bytes ${_mt_ul:-0})" - fi - local _mt_msg="📡 *MTProto Proxy* -Status: ${_mt_status} -Server: \`${_mt_ip}\` -Port: ${MTPROTO_PORT} -Domain: ${MTPROTO_DOMAIN}${_mt_traffic} - -🔗 [Connect to Proxy](${_mt_link})" - # Build inline keyboard for individual control - local _mt_buttons="" - if [ "$_mt_running" = "true" ]; then - _mt_buttons="{\"text\":\"🛑 Stop\",\"callback_data\":\"mt_stop\"},{\"text\":\"🔄 Restart\",\"callback_data\":\"mt_restart\"}" - else - _mt_buttons="{\"text\":\"▶️ Start\",\"callback_data\":\"mt_start\"}" - fi - local _mt_kb="{\"inline_keyboard\":[[${_mt_buttons}]]}" - if command -v qrencode &>/dev/null; then - qrencode -t PNG -o /tmp/mtproto_qr.png "$_mt_link" 2>/dev/null - if [ -f /tmp/mtproto_qr.png ]; then - telegram_send_photo "/tmp/mtproto_qr.png" "$_mt_msg" - rm -f /tmp/mtproto_qr.png - else - telegram_send_inline_keyboard "$_mt_msg" "$_mt_kb" - fi - else - telegram_send_inline_keyboard "$_mt_msg" "$_mt_kb" - fi - fi + telegram_send_inline_keyboard "Tap to view MTProto:" "$(_server_kb "px_" "✉")" fi ;; /help|/help@*) telegram_send "📖 *Available Commands* -/status — Full status report -/peers — Current peer count -/uptime — Per-container uptime -/containers — Per-container status -/settings — Current configuration -/health — Run health checks -/logs\\_N — Last 15 log lines for container N -/update — Update Docker image -/qr — QR code for rewards -/proxy — MTProto proxy (status + control) -/snowflake — Snowflake proxy (status + control) -/restart\\_N — Restart container N -/stop\\_N — Stop container N -/start\\_N — Start container N -/restart\\_all — Restart all containers -/start\\_all — Start all containers -/stop\\_all — Stop all containers + +📊 *Status & Monitoring* +/status — Full report: peers, uptime, traffic, services +/peers — Live peer count across all containers +/uptime — How long each container has been running +/containers — Per-container status with network stats +/health — Run health checks on all services +/logs\\_N — Last 15 log lines for container N (e.g. /logs\\_1) + +⚙️ *Configuration* +/settings — View current configuration and limits +/update — Pull latest Docker image and recreate containers + +🔌 *Add-on Services* +/proxy — MTProto proxy status, traffic stats, and connect link +/snowflake — Snowflake proxy status and instance count +/qr — Generate QR code for Psiphon rewards page + +🔧 *Container Control* +/start\\_N — Start a specific container (e.g. /start\\_1) +/stop\\_N — Stop a specific container (e.g. /stop\\_1) +/restart\\_N — Restart a specific container (e.g. /restart\\_1) +/start\\_all — Start all containers and services +/stop\\_all — Stop all containers and services +/restart\\_all — Restart all containers and services + /help — Show this help" ;; esac @@ -7707,7 +7930,7 @@ build_report() { report+=$'\n' # Container status + uptime - local running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -c "^conduit" 2>/dev/null || true) + local running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -cE "^conduit(-[0-9]+)?$" 2>/dev/null || true) running=${running:-0} local total=${CONTAINER_COUNT:-1} report+="📦 Containers: ${running}/${total} running" @@ -7799,11 +8022,13 @@ build_report() { # System CPU + Temp local sys_cpu="N/A" if [ -f /proc/stat ]; then + local _c user nice system idle iowait irq softirq steal guest read -r _c user nice system idle iowait irq softirq steal guest < /proc/stat local total_curr=$((user + nice + system + idle + iowait + irq + softirq + steal)) local work_curr=$((user + nice + system + irq + softirq + steal)) local cpu_tmp="/tmp/conduit_cpu_state" if [ -f "$cpu_tmp" ]; then + local total_prev work_prev read -r total_prev work_prev < "$cpu_tmp" local total_delta=$((total_curr - total_prev)) local work_delta=$((work_curr - work_prev)) @@ -7850,8 +8075,8 @@ build_report() { # Data usage if [ "${DATA_CAP_GB:-0}" -gt 0 ] || [ "${DATA_CAP_UP_GB:-0}" -gt 0 ] || [ "${DATA_CAP_DOWN_GB:-0}" -gt 0 ]; then local iface="${DATA_CAP_IFACE:-eth0}" - local rx=$(cat /sys/class/net/$iface/statistics/rx_bytes 2>/dev/null || echo 0) - local tx=$(cat /sys/class/net/$iface/statistics/tx_bytes 2>/dev/null || echo 0) + local rx=$(cat "/sys/class/net/$iface/statistics/rx_bytes" 2>/dev/null || echo 0) + local tx=$(cat "/sys/class/net/$iface/statistics/tx_bytes" 2>/dev/null || echo 0) local d_rx=$(( rx - ${DATA_CAP_BASELINE_RX:-0} )); [ "$d_rx" -lt 0 ] && d_rx=0 local d_tx=$(( tx - ${DATA_CAP_BASELINE_TX:-0} )); [ "$d_tx" -lt 0 ] && d_tx=0 local t_rx=$(( d_rx + ${DATA_CAP_PRIOR_RX:-0} )) @@ -7942,7 +8167,7 @@ build_report() { read -r _mt_dl _mt_ul <<< "$_mt_t" local mt_dl_fmt=$(format_bytes ${_mt_dl:-0}) local mt_ul_fmt=$(format_bytes ${_mt_ul:-0}) - report+="📡 MTProxy: Running | ↓${mt_dl_fmt} ↑${mt_ul_fmt}" + report+="✉️ MTProxy: Running | ↓${mt_dl_fmt} ↑${mt_ul_fmt}" report+=$'\n' fi @@ -8381,8 +8606,7 @@ show_settings_menu() { redraw=true ;; u) - uninstall_all - exit 0 + uninstall_all && exit 0 ;; 0) return @@ -8776,7 +9000,7 @@ SVCEOF fi # Auto-start/upgrade tracker if containers are up - local any_running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -c "^conduit" 2>/dev/null || true) + local any_running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -cE "^conduit(-[0-9]+)?$" 2>/dev/null || true) any_running=${any_running:-0} if [ "$any_running" -gt 0 ] 2>/dev/null; then local tracker_script="$INSTALL_DIR/conduit-tracker.sh" @@ -8829,7 +9053,7 @@ SVCEOF # If API unreachable — do nothing, badge stays as-is } & - local redraw=true + local redraw=true choice while true; do if [ "$redraw" = true ]; then clear @@ -8861,6 +9085,7 @@ SVCEOF echo -e " c. 📦 Manage containers" echo -e " a. 📊 Advanced stats" echo -e " m. 🌐 Multi-server dashboard" + echo "" # Snowflake menu item if [ "$SNOWFLAKE_ENABLED" = "true" ]; then local _sf_label="${RED}Stopped${NC}" @@ -8873,10 +9098,15 @@ SVCEOF if [ "$MTPROTO_ENABLED" = "true" ]; then local _mt_label="${RED}Stopped${NC}" is_mtproto_running && _mt_label="${GREEN}Running${NC}" - echo -e " p. 📡 Telegram MTProto Proxy [${_mt_label}]" + echo -e " p. ✉️ Telegram MTProto Proxy [${_mt_label}]" else - echo -e " p. 📡 Telegram MTProto Proxy" + echo -e " p. ✉️ Telegram MTProto Proxy" fi + echo "" + echo -e " ${CYAN}n${NC}. 📡 Psiphon Network Stats" + echo -e " ${CYAN}e${NC}. 📈 Iran Connectivity Status" + echo -e " ${CYAN}t${NC}. 🔗 Iran Connectivity Test" + echo "" echo -e " i. ℹ️ Info & Help" echo -e " 0. 🚪 Exit" echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}" @@ -8951,6 +9181,18 @@ SVCEOF show_info_menu redraw=true ;; + n|N) + show_psiphon_stats + redraw=true + ;; + e|E) + show_iran_connectivity + redraw=true + ;; + t|T) + show_iran_test + redraw=true + ;; 0) echo "Exiting." exit 0 @@ -8966,25 +9208,35 @@ SVCEOF # Info hub - sub-page menu show_info_menu() { - local redraw=true + local redraw=true info_choice while true; do if [ "$redraw" = true ]; then clear echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" echo -e "${BOLD} INFO & HELP${NC}" echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" - echo "" + echo -e " ${DIM}── Understanding Conduit ──${NC}" echo -e " 1. 📡 How the Tracker Works" echo -e " 2. 📊 Understanding the Stats Pages" echo -e " 3. 📦 Containers & Scaling" - echo -e " 4. 🔒 Privacy & Security" - echo -e " 5. ❄️ Snowflake Proxy" - echo -e " 6. 📡 MTProto Proxy" - echo -e " 7. ⚖️ Safety & Legal" - echo -e " 8. 🚀 About Psiphon Conduit" - echo -e " 9. 📈 Dashboard Metrics Explained" + echo -e " 4. 🖥️ Dashboard Metrics Explained" echo "" - echo -e " [b] Back to menu" + echo -e " ${DIM}── Proxies & Privacy ──${NC}" + echo -e " 5. 🔒 Privacy & Security" + echo -e " 6. ❄️ Snowflake Proxy" + echo -e " 7. ✉️ MTProto Proxy" + echo "" + echo -e " ${DIM}── Iran & Network ──${NC}" + echo -e " 8. 📈 Iran Connectivity — Data Sources" + echo -e " 9. 🔗 Iran Connectivity Test — Guide" + echo -e " a. 📶 Psiphon Network Stats — Guide" + echo "" + echo -e " ${DIM}── Reference ──${NC}" + echo -e " b. ⚖️ Safety & Legal" + echo -e " c. 💻 CLI Commands Reference" + echo -e " d. 🚀 About Psiphon Conduit" + echo "" + echo -e " [0] Back to menu" echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" echo "" redraw=false @@ -8994,13 +9246,17 @@ show_info_menu() { 1) _info_tracker; redraw=true ;; 2) _info_stats; redraw=true ;; 3) _info_containers; redraw=true ;; - 4) _info_privacy; redraw=true ;; - 5) show_info_snowflake; redraw=true ;; - 6) show_info_mtproto; redraw=true ;; - 7) show_info_safety; redraw=true ;; - 8) show_about; redraw=true ;; - 9) show_dashboard_info; redraw=true ;; - b|"") break ;; + 4) show_dashboard_info; redraw=true ;; + 5) _info_privacy; redraw=true ;; + 6) show_info_snowflake; redraw=true ;; + 7) show_info_mtproto; redraw=true ;; + 8) _info_iran_connectivity; redraw=true ;; + 9) _info_iran_test; redraw=true ;; + a) _info_psiphon_stats; redraw=true ;; + b) show_info_safety; redraw=true ;; + c) _info_cli_commands; redraw=true ;; + d) show_about; redraw=true ;; + 0|"") break ;; *) echo -e " ${RED}Invalid.${NC}"; sleep 1; redraw=true ;; esac done @@ -9149,6 +9405,3207 @@ _info_privacy() { read -n 1 -s -r -p " Press any key to return..." < /dev/tty || true } +_info_iran_connectivity() { + local _info_exit=0 + while [ "$_info_exit" -eq 0 ]; do + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} IRAN CONNECTIVITY — DATA SOURCES & METRICS${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " The Iran Connectivity Status page aggregates real-time" + echo -e " data from multiple independent sources. Select a topic" + echo -e " below to learn how each metric is measured and displayed." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo "" + echo -e " ${CYAN}a.${NC} ${BOLD}IODA — Internet Outage Detection${NC}" + echo -e " ${DIM}BGP Reachability, Active Probing, Outage Alerts${NC}" + echo "" + echo -e " ${CYAN}b.${NC} ${BOLD}IODA — Additional Signals${NC}" + echo -e " ${DIM}Darknet Traffic, Google Search Traffic, Latency & Loss${NC}" + echo "" + echo -e " ${CYAN}c.${NC} ${BOLD}OONI — Messaging Apps${NC}" + echo -e " ${DIM}Telegram, WhatsApp, Signal, Facebook Messenger${NC}" + echo "" + echo -e " ${CYAN}d.${NC} ${BOLD}OONI — Network Anomaly Trend${NC}" + echo -e " ${DIM}Web censorship detection across thousands of URLs${NC}" + echo "" + echo -e " ${CYAN}e.${NC} ${BOLD}RIPE Atlas — Probe Connectivity${NC}" + echo -e " ${DIM}Hardware probes reporting from inside Iran${NC}" + echo "" + echo -e " ${CYAN}f.${NC} ${BOLD}irinter.net — Internet Exchange Score${NC}" + echo -e " ${DIM}Domestic exchange point health monitoring${NC}" + echo "" + echo -e " ${CYAN}g.${NC} ${BOLD}Status Indicator & Data Freshness${NC}" + echo -e " ${DIM}How the status badge works, caching, auto-refresh${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${CYAN}[0]${NC} Back" + echo "" + printf " Select topic: " + local _ic="" + read -n 1 -s -r _ic < /dev/tty || true + echo "" + case "$_ic" in + a|A) _info_ic_ioda_core ;; + b|B) _info_ic_ioda_extra ;; + c|C) _info_ic_ooni_msg ;; + d|D) _info_ic_ooni_anomaly ;; + e|E) _info_ic_ripe ;; + f|F) _info_ic_irinter ;; + g|G) _info_ic_status ;; + *) _info_exit=1 ;; + esac + done +} + +# --- Info sub-pages (each returns to the menu) --- + +_info_ic_ioda_core() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} IODA — Internet Outage Detection & Analysis${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${DIM}Source: Georgia Tech · ioda.inetintel.cc.gatech.edu${NC}" + echo -e " ${DIM}Access: Public API, no authentication required${NC}" + echo "" + echo -e " IODA (Internet Outage Detection & Analysis) is a project by" + echo -e " Georgia Tech that monitors global internet connectivity using" + echo -e " multiple independent measurement methods. We query their API" + echo -e " for Iran (country code IR) over the last 7 days." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Internet Reachability (BGP)${NC}" + echo "" + echo -e " Tracks how many IP address blocks (prefixes) are visible in" + echo -e " the global routing table for Iran. When the government shuts" + echo -e " down the internet, BGP prefixes disappear from the global" + echo -e " routing table — this is the most reliable signal for" + echo -e " large-scale shutdowns." + echo "" + echo -e " The chart shows daily values normalized to the 7-day peak" + echo -e " (highest day = 100%). This normalization makes drops clearly" + echo -e " visible regardless of the absolute number of prefixes." + echo "" + echo -e " ${DIM}API: /v2/signals/raw/country/IR?datasource=bgp&maxPoints=7${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${CYAN}Active Probing (Ping)${NC}" + echo "" + echo -e " IODA sends ping probes to /24 subnets (256-address blocks)" + echo -e " inside Iran and measures how many respond. This complements" + echo -e " BGP: a network can be routed (BGP visible) but still" + echo -e " unreachable (probes fail) during throttling or partial" + echo -e " filtering. When both BGP and ping drop together, it's a" + echo -e " strong confirmation of a full shutdown." + echo "" + echo -e " ${DIM}API: /v2/signals/raw/country/IR?datasource=ping-slash24&maxPoints=7${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${YELLOW}Recent Outage Alerts${NC}" + echo "" + echo -e " IODA automatically detects significant drops in any of its" + echo -e " signals and generates alerts. Each alert includes:" + echo "" + echo -e " ${BOLD}Date${NC} When the outage was detected" + echo -e " ${BOLD}Source${NC} Which signal triggered it (bgp, ping, etc.)" + echo -e " ${BOLD}Level${NC} Severity: ${YELLOW}warning${NC}, ${YELLOW}major${NC}, or ${RED}critical${NC}" + echo -e " ${BOLD}Condition${NC} Whether the alert is ongoing or resolved" + echo "" + echo -e " If you see alerts here, Iran is likely experiencing or has" + echo -e " recently experienced an active internet disruption." + echo "" + echo -e " ${DIM}API: /v2/outages/alerts?entityType=country&entityCode=IR${NC}" + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_ic_ioda_extra() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} IODA — Additional Signals${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${DIM}Source: Georgia Tech · Same IODA API, different datasources${NC}" + echo "" + echo -e " Beyond BGP and ping, IODA collects several other independent" + echo -e " signals that confirm or reveal different types of disruption." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${MAGENTA}Darknet Traffic (Merit Network Telescope)${NC}" + echo "" + echo -e " The Merit Network Telescope observes unsolicited background" + echo -e " traffic (backscatter, scanning, spoofed packets) arriving" + echo -e " from Iran's IP address space. During normal operation this" + echo -e " traffic is steady. During a shutdown it drops sharply —" + echo -e " providing strong independent confirmation of outages even" + echo -e " when BGP routing tables look normal." + echo "" + echo -e " Chart shows raw daily traffic volume (not normalized)." + echo "" + echo -e " ${DIM}API: /v2/signals/raw/country/IR?datasource=merit-nt&maxPoints=7${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${YELLOW}Google Search Traffic (Google Transparency Report)${NC}" + echo "" + echo -e " Tracks the volume of Google product requests (Search," + echo -e " YouTube, Gmail, Maps, etc.) originating from Iran. Google" + echo -e " publishes this data through their Transparency Report." + echo -e " Sudden drops indicate internet disruption or targeted" + echo -e " filtering of Google services. This signal can detect" + echo -e " content-level blocking that BGP and ping measurements miss." + echo "" + echo -e " Chart shows raw daily request volume." + echo "" + echo -e " ${DIM}API: /v2/signals/raw/country/IR?datasource=gtr&maxPoints=7${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Network Quality (Latency & Packet Loss)${NC}" + echo "" + echo -e " IODA's active probing infrastructure also measures the" + echo -e " round-trip latency (in milliseconds) and packet loss (%)" + echo -e " to Iranian networks. These metrics reveal throttling or" + echo -e " congestion even when connectivity appears normal." + echo "" + echo -e " ${BOLD}Avg Latency${NC} Median round-trip time to Iranian /24 subnets" + echo -e " ${GREEN}< 200ms${NC} good | ${YELLOW}200-500ms${NC} slow | ${RED}>500ms${NC} degraded" + echo -e " ${BOLD}Packet Loss${NC} % of probes that received no response" + echo -e " ${GREEN}< 3%${NC} normal | ${YELLOW}3-10%${NC} elevated | ${RED}>10%${NC} severe" + echo "" + echo -e " ${DIM}API: /v2/signals/raw/country/IR?datasource=ping-slash24-latency${NC}" + echo -e " ${DIM}API: /v2/signals/raw/country/IR?datasource=ping-slash24-loss${NC}" + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_ic_ooni_msg() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} OONI — Messaging App Reachability${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${DIM}Source: ooni.org · Same OONI infrastructure${NC}" + echo "" + echo -e " OONI volunteers also test popular messaging apps from inside" + echo -e " Iran. Each app has a dedicated test that checks whether the" + echo -e " service's servers are reachable. The table format is identical" + echo -e " to the Circumvention Tools table:" + echo -e " Success% = ok_count / measurement_count * 100" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${BOLD}Telegram${NC}" + echo "" + echo -e " Tests connections to Telegram's web interface, API endpoints," + echo -e " and data centers. Checks if Telegram servers (149.154.*.*/32)" + echo -e " are reachable via TCP and if the web interface (web.telegram" + echo -e " .org) responds correctly." + echo "" + echo -e " ${DIM}API: api.ooni.io/api/v1/aggregation?probe_cc=IR&test_name=telegram${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${BOLD}WhatsApp${NC}" + echo "" + echo -e " Tests TCP connections to WhatsApp's registration service" + echo -e " endpoints and the web interface (web.whatsapp.com). An" + echo -e " anomaly means either the backend or web interface is blocked." + echo "" + echo -e " ${DIM}API: api.ooni.io/api/v1/aggregation?probe_cc=IR&test_name=whatsapp${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${BOLD}Signal${NC}" + echo "" + echo -e " Tests access to Signal's servers by attempting to establish" + echo -e " a TLS connection. An anomaly indicates the service is being" + echo -e " blocked or interfered with at the network level." + echo "" + echo -e " ${DIM}API: api.ooni.io/api/v1/aggregation?probe_cc=IR&test_name=signal${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${BOLD}Facebook Messenger${NC}" + echo "" + echo -e " Tests TCP connections to Facebook Messenger's backend servers" + echo -e " (edge-star, b-api, etc.) and checks DNS resolution. An" + echo -e " anomaly means Facebook's messaging infrastructure is blocked." + echo "" + echo -e " ${DIM}API: api.ooni.io/api/v1/aggregation?probe_cc=IR${NC}" + echo -e " ${DIM} &test_name=facebook_messenger${NC}" + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_ic_ooni_anomaly() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} OONI — Network Anomaly Trend${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${DIM}Source: ooni.org · web_connectivity test${NC}" + echo "" + echo -e " This chart shows the daily percentage of OONI web tests that" + echo -e " detected anomalies (possible censorship) in Iran." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${YELLOW}How it works${NC}" + echo "" + echo -e " Uses the ${BOLD}web_connectivity${NC} test — OONI's main censorship" + echo -e " detector. Volunteers test thousands of URLs from Iran and" + echo -e " OONI checks for four types of interference:" + echo "" + echo -e " 1. ${BOLD}DNS tampering${NC} — DNS responses differ from control" + echo -e " 2. ${BOLD}TCP/IP blocking${NC} — TCP connections to the site are reset" + echo -e " 3. ${BOLD}HTTP difference${NC} — Response content doesn't match" + echo -e " 4. ${BOLD}TLS interference${NC} — TLS handshake is disrupted" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${YELLOW}How the chart is calculated${NC}" + echo "" + echo -e " We request hourly buckets from the OONI API with each" + echo -e " bucket containing anomaly_count and measurement_count." + echo -e " We aggregate these into daily percentages:" + echo "" + echo -e " Anomaly % = daily_anomaly_count / daily_measurement_count" + echo "" + echo -e " ${DIM}API: api.ooni.io/api/v1/aggregation?probe_cc=IR${NC}" + echo -e " ${DIM}&test_name=web_connectivity&axis_x=measurement_start_day${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${YELLOW}How to read it${NC}" + echo "" + echo -e " Higher bars = more censorship/filtering activity detected." + echo -e " Spikes indicate new blocking campaigns or tighter" + echo -e " restrictions. A baseline of 10-20% is typical for Iran." + echo -e " Drops to near 0% during shutdowns (no tests can run)." + echo -e " Spikes above 50% indicate aggressive new filtering." + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_ic_ripe() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} RIPE Atlas — Probe Connectivity${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${DIM}Source: atlas.ripe.net · RIPE NCC${NC}" + echo -e " ${DIM}Access: Public API, no authentication required${NC}" + echo "" + echo -e " RIPE Atlas is a global network of small hardware probes" + echo -e " hosted by volunteers. These probes perform internet" + echo -e " measurements (ping, traceroute, DNS, TLS) and report back" + echo -e " to RIPE NCC. There are currently ~100+ probes in Iran." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}What we show${NC}" + echo "" + echo -e " We query the RIPE Atlas API for probe status in Iran:" + echo "" + echo -e " ${GREEN}Connected${NC} Probes that are online and reporting to RIPE" + echo -e " ${DIM}Disconnected${NC} Probes that have lost internet connectivity" + echo "" + echo -e " The percentage (connected / total) gives a ground-level" + echo -e " view of connectivity. A sudden increase in disconnected" + echo -e " probes indicates localized or national disruption." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Color thresholds${NC}" + echo "" + echo -e " ${GREEN}>= 70%${NC} connected — Normal connectivity" + echo -e " ${YELLOW}40-70%${NC} connected — Significant disruption" + echo -e " ${RED}< 40%${NC} connected — Major outage" + echo "" + echo -e " ${DIM}API: atlas.ripe.net/api/v2/probes/?country_code=IR&status=1${NC}" + echo -e " ${DIM}API: atlas.ripe.net/api/v2/probes/?country_code=IR&status=2${NC}" + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_ic_irinter() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} irinter.net — Internet Exchange Score${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${DIM}Source: irinter.net · Iran Internet Exchange Point${NC}" + echo -e " ${DIM}Access: Public API, no authentication required${NC}" + echo "" + echo -e " irinter.net monitors Iran's domestic internet exchange" + echo -e " infrastructure. Iranian ISPs exchange traffic domestically" + echo -e " through internet exchange points (IXPs) — when these are" + echo -e " healthy, domestic traffic flows efficiently." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Network Score${NC}" + echo "" + echo -e " The score is a 0-100% health metric for Iran's domestic" + echo -e " internet exchange. Higher = healthier." + echo "" + echo -e " ${GREEN}>= 70%${NC} — Healthy domestic exchange" + echo -e " ${YELLOW}40-70%${NC} — Degraded performance or congestion" + echo -e " ${RED}< 40%${NC} — Severe problems at exchange points" + echo "" + echo -e " Drops indicate domestic routing problems, exchange point" + echo -e " congestion, or deliberate throttling of domestic traffic." + echo -e " This metric specifically captures domestic infrastructure" + echo -e " issues that international measurements might miss." + echo "" + echo -e " We fetch 7 days of data and display the most recent score." + echo "" + echo -e " ${DIM}API: irinter.net/api/data/network-score?from=&until=${NC}" + echo -e " ${DIM}Response: {\"data\":[{\"from\":...,\"value\":65.02},...]}}${NC}" + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_ic_tor() { + # Reserved for future Tor relay integration + return 0 +} + +_info_ic_status() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} Status Indicator & Data Freshness${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${BOLD}Status Indicator${NC}" + echo "" + echo -e " The colored badge at the top of the status page is derived" + echo -e " from the latest IODA BGP visibility value, normalized as a" + echo -e " percentage of the 7-day peak:" + echo "" + echo -e " ${GREEN}● ONLINE${NC} >= 80% of peak — Normal connectivity" + echo -e " ${YELLOW}● DISRUPTED${NC} 40-80% of peak — Partial shutdown or throttle" + echo -e " ${RED}● OUTAGE${NC} < 40% of peak — Major shutdown detected" + echo "" + echo -e " BGP visibility is used because it's the most reliable and" + echo -e " tamper-resistant signal — it's measured from outside Iran" + echo -e " by observing the global routing table, so it can't be" + echo -e " spoofed or manipulated by Iranian authorities." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${BOLD}Data Freshness & Caching${NC}" + echo "" + echo -e " All data is cached locally for ${BOLD}5 minutes${NC} to avoid" + echo -e " excessive API calls. The \"Updated: Xm ago\" label at the" + echo -e " top shows the age of the oldest cached data." + echo "" + echo -e " ${BOLD}Auto-refresh${NC}: The page automatically refreshes when the" + echo -e " cache expires (every 5 minutes)." + echo "" + echo -e " ${BOLD}Manual refresh${NC}: Press ${CYAN}[r]${NC} to force an immediate refresh," + echo -e " bypassing the cache." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${BOLD}Data Sources Summary${NC}" + echo "" + echo -e " ${GREEN}IODA${NC} Georgia Tech — BGP, Ping, Alerts, Darknet," + echo -e " Google Traffic, Latency, Packet Loss" + echo -e " ${GREEN}OONI${NC} Volunteer network — Psiphon, Tor, Messaging" + echo -e " Apps (Telegram/WhatsApp/Signal/Facebook)," + echo -e " Web Anomaly Trend" + echo -e " ${GREEN}RIPE Atlas${NC} RIPE NCC — Hardware probe connectivity" + echo -e " ${GREEN}irinter.net${NC} Iran IXP — Domestic exchange health score" + echo "" + echo -e " All sources are public APIs with no authentication" + echo -e " required. Data is fetched in parallel for fast loading." + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +#═══════════════════════════════════════════════════════════════════════ +# Info pages: Iran Connectivity Test +#═══════════════════════════════════════════════════════════════════════ + +_info_iran_test() { + local _info_exit=0 + while [ "$_info_exit" -eq 0 ]; do + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} IRAN CONNECTIVITY TEST — GUIDE${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " This tool tests live network connectivity from your server" + echo -e " to ~100 endpoints across Iran. Select a topic below." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo "" + echo -e " ${CYAN}a.${NC} ${BOLD}Quick Ping & Full Ping${NC}" + echo -e " ${DIM}How ping tests work, what the results mean${NC}" + echo "" + echo -e " ${CYAN}b.${NC} ${BOLD}Test by City & Test by ASN${NC}" + echo -e " ${DIM}Filtered testing for targeted diagnostics${NC}" + echo "" + echo -e " ${CYAN}c.${NC} ${BOLD}Traceroute & MTR Analysis${NC}" + echo -e " ${DIM}Network path tracing and hop-by-hop analysis${NC}" + echo "" + echo -e " ${CYAN}d.${NC} ${BOLD}Full Report${NC}" + echo -e " ${DIM}Comprehensive report with city & ASN breakdown${NC}" + echo "" + echo -e " ${CYAN}e.${NC} ${BOLD}Server List & Coverage${NC}" + echo -e " ${DIM}What endpoints are tested and why${NC}" + echo "" + echo -e " ${CYAN}f.${NC} ${BOLD}Reading the Results${NC}" + echo -e " ${DIM}Color codes, latency thresholds, loss interpretation${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${CYAN}[0]${NC} Back" + echo "" + printf " Select topic: " + local _ic="" + read -n 1 -s -r _ic < /dev/tty || true + echo "" + case "$_ic" in + a|A) _info_it_ping ;; + b|B) _info_it_filter ;; + c|C) _info_it_trace ;; + d|D) _info_it_report ;; + e|E) _info_it_servers ;; + f|F) _info_it_results ;; + *) _info_exit=1 ;; + esac + done +} + +_info_it_ping() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} Quick Ping & Full Ping${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Quick Ping Test (option a)${NC}" + echo "" + echo -e " Sends ${BOLD}1 ICMP ping${NC} to every server in the list. All pings" + echo -e " run in parallel (background processes), so testing ~100" + echo -e " servers takes only a few seconds." + echo "" + echo -e " Best for: Fast overview of which Iranian networks are" + echo -e " reachable from your server right now." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Full Ping Test (option b)${NC}" + echo "" + echo -e " Sends ${BOLD}4 ICMP pings${NC} to every server. This gives more" + echo -e " reliable latency averages and packet loss statistics" + echo -e " by reducing the impact of single-packet anomalies." + echo "" + echo -e " The average latency shown is computed from all successful" + echo -e " replies: ${DIM}rtt min/avg/max/mdev${NC}" + echo "" + echo -e " Best for: Accurate latency comparison when you need" + echo -e " reliable numbers for troubleshooting." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}How it works internally${NC}" + echo "" + echo -e " 1. Creates a temp directory for results" + echo -e " 2. For each server: ${DIM}ping -c N -W 3 &${NC}" + echo -e " 3. ${DIM}wait${NC} — waits for all background pings to finish" + echo -e " 4. Parses each result file for avg latency and loss %" + echo -e " 5. Displays sorted by city with color-coded status" + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_it_filter() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} Test by City & Test by ASN${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Test by City (option c)${NC}" + echo "" + echo -e " Shows a numbered menu of all cities in the server list" + echo -e " with the count of servers in each. Select a city and" + echo -e " the tool runs a 4-ping test only on servers in that city." + echo "" + echo -e " Use case: You notice high latency to Mashhad — test just" + echo -e " Mashhad servers to see if it's a regional routing issue." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Test by ASN (option d)${NC}" + echo "" + echo -e " Shows a numbered menu of all ASNs (Autonomous Systems)" + echo -e " with their names and server counts. Select an ASN and" + echo -e " the tool tests only servers on that network." + echo "" + echo -e " ${BOLD}What is an ASN?${NC}" + echo -e " An Autonomous System Number identifies a network operator." + echo -e " Each ISP, data center, and large organization has one." + echo -e " For example:" + echo -e " AS12880 = DCI (Data Communication Iran)" + echo -e " AS44244 = Irancell (mobile operator)" + echo -e " AS197207 = MCI (mobile operator)" + echo -e " AS31549 = Shatel (major ISP)" + echo "" + echo -e " Use case: You suspect a specific Iranian ISP is blocking" + echo -e " traffic — test only that ASN to confirm." + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_it_trace() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} Traceroute & MTR Analysis${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Traceroute (option e)${NC}" + echo "" + echo -e " Pick a server from a numbered list, then runs:" + echo -e " ${DIM}traceroute -m 25 -w 3 ${NC}" + echo "" + echo -e " Shows every network hop between your server and the" + echo -e " target. Each line shows the hop number, router IP/name," + echo -e " and round-trip time for 3 probes." + echo "" + echo -e " ${BOLD}What to look for:${NC}" + echo -e " - ${BOLD}* * *${NC} = hop doesn't respond (firewalled, normal)" + echo -e " - ${BOLD}Sudden latency jump${NC} = bottleneck at that hop" + echo -e " - ${BOLD}!H / !N${NC} = host/network unreachable" + echo -e " - Last responding hop before ${BOLD}* * *${NC} = where blocking" + echo -e " likely occurs" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}MTR Analysis (option f)${NC}" + echo "" + echo -e " Pick a server, then runs:" + echo -e " ${DIM}mtr -r -c 10 -w ${NC}" + echo "" + echo -e " MTR combines traceroute + continuous ping into one tool." + echo -e " It sends 10 rounds of probes and shows per-hop stats:" + echo "" + echo -e " ${BOLD}Loss%${NC} Packet loss at each hop" + echo -e " ${BOLD}Snt${NC} Packets sent (10)" + echo -e " ${BOLD}Last${NC} Last probe round-trip time" + echo -e " ${BOLD}Avg${NC} Average RTT across all probes" + echo -e " ${BOLD}Best${NC} Minimum RTT (best case)" + echo -e " ${BOLD}Wrst${NC} Maximum RTT (worst case)" + echo -e " ${BOLD}StDev${NC} Standard deviation (jitter)" + echo "" + echo -e " ${BOLD}Tip:${NC} High loss at an intermediate hop but 0% loss at" + echo -e " the final destination is normal — many routers deprioritize" + echo -e " ICMP responses. Only worry if the ${BOLD}final hop${NC} shows loss." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Dependencies${NC}" + echo "" + echo -e " Both tools require ${BOLD}traceroute${NC} and ${BOLD}mtr${NC} packages. The" + echo -e " script auto-installs them via apt/yum/apk/dnf/pacman" + echo -e " when you first open the Iran Connectivity Test page." + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_it_report() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} Full Report${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " The Full Report (option g) runs a comprehensive 4-ping" + echo -e " test against all servers, then generates a detailed" + echo -e " breakdown in four sections:" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}1. Overview${NC}" + echo -e " Total reachable servers, average latency, best/worst" + echo -e " server with latency values, overall reachability bar." + echo "" + echo -e " ${GREEN}2. By City${NC}" + echo -e " Each city gets a summary line showing how many servers" + echo -e " responded, the average latency for that city, and a" + echo -e " colored bar. Helps identify regional routing issues." + echo "" + echo -e " ${GREEN}3. By ASN${NC}" + echo -e " Same breakdown but grouped by network provider. Shows" + echo -e " which Iranian ISPs/data centers are reachable and their" + echo -e " latency. Useful for identifying ISP-level blocks." + echo "" + echo -e " ${GREEN}4. All Servers${NC}" + echo -e " Full per-server results sorted by city, showing exact" + echo -e " latency, packet loss, and ASN for each endpoint." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Performance${NC}" + echo "" + echo -e " All pings run in parallel. Testing ~100 servers with" + echo -e " 4 pings each takes about 15-20 seconds total." + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_it_servers() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} Server List & Coverage${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " The test list includes ~100 curated Iranian endpoints" + echo -e " covering 7 categories across 29 cities and 45 ASNs:" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}DNS Resolvers${NC} (Shecan, Electro, TIC)" + echo -e " Public DNS servers hosted inside Iran. If these" + echo -e " respond, basic Iran connectivity is working." + echo "" + echo -e " ${GREEN}ISP Gateways${NC} (Shatel, ParsOnline, Irancell, MCI, ...)" + echo -e " Gateway IPs of major Iranian internet providers." + echo -e " Tests routing to Iran's backbone infrastructure." + echo "" + echo -e " ${GREEN}Websites${NC} (Digikala, Aparat, Snapp, Varzesh3, ...)" + echo -e " Popular Iranian services. Tests real-world endpoint" + echo -e " reachability, not just backbone routing." + echo "" + echo -e " ${GREEN}Banks${NC} (Mellat, Saderat, Pasargad, Saman, ...)" + echo -e " Iranian banking infrastructure. These are critical" + echo -e " services with dedicated network paths." + echo "" + echo -e " ${GREEN}Data Centers${NC} (ParsData, IranServer, HostIran, ...)" + echo -e " Iranian hosting providers. Tests connectivity to" + echo -e " server infrastructure inside Iran." + echo "" + echo -e " ${GREEN}Universities${NC} (Sharif, Amirkabir, IPM)" + echo -e " Academic networks with their own ASNs." + echo "" + echo -e " ${GREEN}Regional PoPs${NC} (TIC/MCI gateways in 29 cities)" + echo -e " TIC (backbone) and MCI (mobile) points of presence" + echo -e " across Iran — from Tehran to Kish Island." + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_it_results() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} Reading the Results${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Status Indicators${NC}" + echo "" + echo -e " Each server gets a colored dot:" + echo -e " ${GREEN}●${NC} ${GREEN}< 200ms${NC} — Good connectivity" + echo -e " ${YELLOW}●${NC} ${YELLOW}200-500ms${NC} — Slow / degraded" + echo -e " ${RED}●${NC} ${RED}> 500ms${NC} — Very slow / barely reachable" + echo -e " ${RED}●${NC} ${RED}---${NC} — Unreachable (100% packet loss)" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Result Columns${NC}" + echo "" + echo -e " ${BOLD}● Name Latency Loss ASN${NC}" + echo -e " ${DIM}● Digikala 142ms 0% AS43211 Digikala${NC}" + echo "" + echo -e " ${BOLD}Latency${NC} Average round-trip time in milliseconds" + echo -e " ${BOLD}Loss${NC} Percentage of packets that didn't return" + echo -e " ${BOLD}ASN${NC} The network operator hosting the endpoint" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}What the numbers mean${NC}" + echo "" + echo -e " ${BOLD}Low latency + 0% loss${NC} = great path to that network" + echo -e " ${BOLD}High latency + 0% loss${NC} = reachable but congested" + echo -e " ${BOLD}Low latency + high loss${NC} = unstable connection" + echo -e " ${BOLD}--- + 100% loss${NC} = blocked, down, or ICMP filtered" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Summary Bars${NC}" + echo "" + echo -e " The summary at the bottom shows reachability bars:" + echo -e " ${DIM} Reachable: 87/99 ${GREEN}█████████████████${NC}${DIM}░░░ 87%${NC}" + echo "" + echo -e " The bar length = percentage of servers that responded." + echo -e " Color follows the same green/yellow/red thresholds." + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +#═══════════════════════════════════════════════════════════════════════ +# Info pages: Psiphon Network Stats +#═══════════════════════════════════════════════════════════════════════ + +_info_psiphon_stats() { + local _info_exit=0 + while [ "$_info_exit" -eq 0 ]; do + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} PSIPHON NETWORK STATS — GUIDE${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " The Psiphon Network Stats page shows live data from" + echo -e " the Psiphon analytics API. Select a topic below." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo "" + echo -e " ${CYAN}a.${NC} ${BOLD}Iran Daily Connections${NC}" + echo -e " ${DIM}Connection count chart for Iran${NC}" + echo "" + echo -e " ${CYAN}b.${NC} ${BOLD}Daily Unique Users${NC}" + echo -e " ${DIM}Unique user estimates from Iran${NC}" + echo "" + echo -e " ${CYAN}c.${NC} ${BOLD}Global Daily Users${NC}" + echo -e " ${DIM}Total Psiphon users worldwide${NC}" + echo "" + echo -e " ${CYAN}d.${NC} ${BOLD}Connections by Region${NC}" + echo -e " ${DIM}Geographic breakdown of connections${NC}" + echo "" + echo -e " ${CYAN}e.${NC} ${BOLD}Top Station Regions${NC}" + echo -e " ${DIM}Where Psiphon servers are located${NC}" + echo "" + echo -e " ${CYAN}f.${NC} ${BOLD}Data Transferred${NC}" + echo -e " ${DIM}Daily bandwidth through the network${NC}" + echo "" + echo -e " ${CYAN}g.${NC} ${BOLD}Data Source & Caching${NC}" + echo -e " ${DIM}API details, refresh intervals${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${CYAN}[0]${NC} Back" + echo "" + printf " Select topic: " + local _ic="" + read -n 1 -s -r _ic < /dev/tty || true + echo "" + case "$_ic" in + a|A) _info_ps_connections ;; + b|B) _info_ps_users ;; + c|C) _info_ps_global ;; + d|D) _info_ps_regions ;; + e|E) _info_ps_stations ;; + f|F) _info_ps_data ;; + g|G) _info_ps_source ;; + *) _info_exit=1 ;; + esac + done +} + +_info_cli_commands() { + local _info_exit=0 + while [ "$_info_exit" -eq 0 ]; do + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} CLI COMMANDS REFERENCE${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " Run any command with: ${GREEN}conduit ${NC}" + echo "" + echo -e " ${CYAN}━━━ Core ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}status${NC} Show container status, connections, traffic" + echo -e " ${GREEN}status --json${NC} Machine-readable JSON output" + echo -e " ${GREEN}start${NC} Start all Conduit containers" + echo -e " ${GREEN}stop${NC} Stop all Conduit containers" + echo -e " ${GREEN}restart${NC} Restart all Conduit containers" + echo -e " ${GREEN}logs${NC} View raw Docker container logs" + echo -e " ${GREEN}health${NC} Run full health check (Docker, network, keys)" + echo "" + echo -e " ${CYAN}━━━ Configuration ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}settings${NC} Change max-clients, bandwidth, resources" + echo -e " ${GREEN}scale${NC} Add or remove containers (1-32)" + echo -e " ${GREEN}update${NC} Update to latest Conduit image & script" + echo -e " ${GREEN}update-geoip${NC} Refresh the GeoIP country database" + echo "" + echo -e " ${CYAN}━━━ Backup & Identity ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}backup${NC} Backup node identity key to file" + echo -e " ${GREEN}restore${NC} Restore node identity from backup" + echo "" + echo -e " ${CYAN}━━━ Monitoring ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}stats${NC} Live traffic & connection statistics" + echo -e " ${GREEN}peers${NC} Live peer connections by country" + echo -e " ${GREEN}network-stats${NC} Psiphon global network statistics" + echo -e " ${GREEN}iran-status${NC} Iran connectivity (IODA, OONI, RIPE)" + echo -e " ${GREEN}iran-test${NC} Iran connectivity test (ping, MTU, trace)" + echo "" + echo -e " Press ${BOLD}any key${NC} for page 2..." + read -n 1 -s -r < /dev/tty || true + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} CLI COMMANDS REFERENCE (continued)${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${CYAN}━━━ Multi-Server ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}dashboard${NC} Multi-server dashboard (live TUI)" + echo -e " ${GREEN}add-server${NC} Add remote server (auto-deploys Conduit)" + echo -e " ${GREEN}deploy${NC} Alias for add-server" + echo -e " ${GREEN}edit-server${NC} Edit server credentials or connection" + echo -e " ${GREEN}remove-server${NC} Remove a configured remote server" + echo -e " ${GREEN}servers${NC} List all configured remote servers" + echo "" + echo -e " ${CYAN}━━━ Proxies ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}snowflake${NC} Snowflake proxy status" + echo -e " ${GREEN}snowflake start${NC} Start Snowflake proxy" + echo -e " ${GREEN}snowflake stop${NC} Stop Snowflake proxy" + echo -e " ${GREEN}snowflake restart${NC} Restart Snowflake proxy" + echo -e " ${GREEN}snowflake remove${NC} Remove Snowflake completely" + echo "" + echo -e " ${GREEN}mtproto${NC} MTProto proxy status" + echo -e " ${GREEN}mtproto start${NC} Start MTProto proxy" + echo -e " ${GREEN}mtproto stop${NC} Stop MTProto proxy" + echo -e " ${GREEN}mtproto restart${NC} Restart MTProto proxy" + echo -e " ${GREEN}mtproto link${NC} Show MTProto share link & QR" + echo -e " ${GREEN}mtproto remove${NC} Remove MTProto completely" + echo "" + echo -e " ${CYAN}━━━ Info ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}version${NC} Show version, image digest, container info" + echo -e " ${GREEN}about${NC} About Psiphon Conduit" + echo -e " ${GREEN}info${NC} Dashboard metrics explained" + echo -e " ${GREEN}help${NC} Show quick help summary" + echo -e " ${GREEN}menu${NC} Open interactive menu (default)" + echo -e " ${GREEN}uninstall${NC} Remove everything (containers, data, service)" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${DIM}Tip: Running 'conduit' with no arguments opens the menu.${NC}" + echo -e " ${DIM}Tip: Most features are also accessible from the menu TUI.${NC}" + echo "" + read -n 1 -s -r -p " Press any key to return..." < /dev/tty || true + _info_exit=1 + done +} + +_info_ps_connections() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} Iran Daily Connections${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${DIM}Source: stats.psianalytics.live · Psiphon Analytics API${NC}" + echo "" + echo -e " This chart shows the total number of Psiphon connections" + echo -e " originating from Iran over the last 7 days." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}What is a \"connection\"?${NC}" + echo "" + echo -e " Each time a user's Psiphon client establishes a new" + echo -e " tunnel to a Psiphon server, it counts as one connection." + echo -e " A single user may generate multiple connections per day" + echo -e " (e.g., reconnecting after network changes)." + echo "" + echo -e " ${GREEN}Why it matters${NC}" + echo "" + echo -e " A sudden spike in connections often means increased" + echo -e " censorship pressure — more people are turning to Psiphon." + echo -e " A sudden drop could mean an internet shutdown or that" + echo -e " Iran is blocking Psiphon protocols more aggressively." + echo "" + echo -e " Your Conduit directly helps these users by providing" + echo -e " bandwidth for their connections." + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_ps_users() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} Daily Unique Users from Iran${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${DIM}Source: stats.psianalytics.live · Psiphon Analytics API${NC}" + echo "" + echo -e " This chart shows estimated unique Psiphon users in Iran" + echo -e " per day over the last 7 days." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}How users are counted${NC}" + echo "" + echo -e " Psiphon uses privacy-preserving techniques to estimate" + echo -e " unique users without tracking individuals. The count is" + echo -e " based on anonymized connection fingerprints — it's an" + echo -e " estimate, not an exact count." + echo "" + echo -e " ${GREEN}Connections vs. Users${NC}" + echo "" + echo -e " Users < Connections, because one user can create" + echo -e " multiple connections per day. The ratio gives insight:" + echo -e " - High connections/user = unstable network (reconnects)" + echo -e " - Low connections/user = stable connections" + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_ps_global() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} Global Daily Psiphon Users${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${DIM}Source: stats.psianalytics.live · Psiphon Analytics API${NC}" + echo "" + echo -e " This chart shows total daily Psiphon users worldwide" + echo -e " over the last 7 days — all countries combined." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Why it's useful${NC}" + echo "" + echo -e " Comparing Iran's user count against the global total" + echo -e " shows what fraction of Psiphon traffic comes from Iran." + echo -e " Iran is typically one of the top 3 countries by usage." + echo "" + echo -e " The global number also shows overall Psiphon network" + echo -e " health — if it drops globally, it may be an infrastructure" + echo -e " issue rather than country-specific censorship." + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_ps_regions() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} Daily Connections by Region${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${DIM}Source: stats.psianalytics.live · Psiphon Analytics API${NC}" + echo "" + echo -e " This chart shows daily connection counts broken down" + echo -e " by the top countries using Psiphon, over the last 7 days." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}How to read it${NC}" + echo "" + echo -e " Each country gets its own colored line in the chart." + echo -e " The top 5-6 countries are shown individually; the rest" + echo -e " are grouped as \"Other\"." + echo "" + echo -e " Common top countries:" + echo -e " - ${BOLD}Iran${NC} — usually #1 by connections" + echo -e " - ${BOLD}Russia${NC} — significant usage" + echo -e " - ${BOLD}Turkmenistan${NC} — heavy censorship" + echo -e " - ${BOLD}Myanmar${NC} — military censorship" + echo -e " - ${BOLD}China${NC} — Great Firewall bypass" + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_ps_stations() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} Top Station Regions${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${DIM}Source: stats.psianalytics.live · Psiphon Analytics API${NC}" + echo "" + echo -e " This section shows where Psiphon's proxy servers" + echo -e " (\"stations\") are physically located." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}What are stations?${NC}" + echo "" + echo -e " Psiphon operates servers in data centers around the" + echo -e " world. When a user in Iran connects, their traffic is" + echo -e " routed through one of these stations. Your Conduit" + echo -e " contributes bandwidth to this network." + echo "" + echo -e " ${GREEN}The horizontal bars${NC}" + echo "" + echo -e " Each region shows its percentage of total Psiphon" + echo -e " traffic, with a colored bar. Common station locations" + echo -e " include US, Germany, Netherlands, and other countries" + echo -e " with good connectivity and hosting infrastructure." + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_ps_data() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} Daily Data Transferred${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${DIM}Source: stats.psianalytics.live · Psiphon Analytics API${NC}" + echo "" + echo -e " This chart shows total data transferred through the" + echo -e " Psiphon network per day over the last 7 days." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}How to read it${NC}" + echo "" + echo -e " Values are shown in human-readable format:" + echo -e " ${BOLD}K${NC} = Kilobytes ${BOLD}M${NC} = Megabytes" + echo -e " ${BOLD}G${NC} = Gigabytes ${BOLD}T${NC} = Terabytes" + echo "" + echo -e " Typical daily transfer for the entire Psiphon network" + echo -e " is in the petabyte range. Each bar represents one day." + echo "" + echo -e " ${GREEN}Your Conduit's contribution${NC}" + echo "" + echo -e " Your Conduit container(s) contribute a portion of this" + echo -e " total bandwidth. The more containers you run and the" + echo -e " more bandwidth you allocate, the larger your share." + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +_info_ps_source() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} Data Source & Caching${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}API Source${NC}" + echo "" + echo -e " All data comes from the Psiphon Analytics API:" + echo -e " ${DIM}stats.psianalytics.live${NC}" + echo "" + echo -e " Three endpoints are fetched in parallel:" + echo -e " - ${BOLD}connected-clients${NC} — connections & unique users" + echo -e " - ${BOLD}psiphon-usage${NC} — global users by country" + echo -e " - ${BOLD}ir-usage${NC} — Iran-specific metrics" + echo "" + echo -e " The API is public and requires no authentication." + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Caching${NC}" + echo "" + echo -e " Data is cached locally for ${BOLD}6 hours${NC} to avoid excessive" + echo -e " API calls. The \"Updated\" label shows when data was last" + echo -e " fetched. Press ${CYAN}[r]${NC} to force a refresh." + echo "" + echo -e " Cache files are stored in the install directory as:" + echo -e " ${DIM}.psi_cache_connected_clients${NC}" + echo -e " ${DIM}.psi_cache_psiphon_usage${NC}" + echo -e " ${DIM}.psi_cache_ir_usage${NC}" + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e " ${GREEN}Chart Display${NC}" + echo "" + echo -e " All charts use vertical bar graphs with exact values" + echo -e " shown below. Numbers use K/M/G/T suffixes for" + echo -e " readability (e.g., 13.84M = 13,840,000)." + echo "" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + read -n 1 -s -r -p " Press any key to return to menu..." < /dev/tty || true +} + +#═══════════════════════════════════════════════════════════════════════ +# Psiphon Network Stats (live data from stats.psianalytics.live) +#═══════════════════════════════════════════════════════════════════════ + +# Helpers set variables (_CN, _FN, _MN) — no subshell forks +_psi_country_name() { + case "$1" in + IR) _CN="Iran";; RU) _CN="Russia";; + TM) _CN="Turkmenistan";; MM) _CN="Myanmar";; + DE) _CN="Germany";; US) _CN="United States";; + GB) _CN="United Kingdom";;FR) _CN="France";; + NL) _CN="Netherlands";; RO) _CN="Romania";; + CA) _CN="Canada";; SY) _CN="Syria";; + SE) _CN="Sweden";; FI) _CN="Finland";; + CH) _CN="Switzerland";; ID) _CN="Indonesia";; + UA) _CN="Ukraine";; SD) _CN="Sudan";; + AE) _CN="UAE";; SG) _CN="Singapore";; + EG) _CN="Egypt";; TR) _CN="Turkey";; + IN) _CN="India";; PK) _CN="Pakistan";; + *) _CN="$1";; + esac +} + +_psi_fmt_num() { + local n="${1:-0}" + n="${n%%.*}"; n="${n//[!0-9]/}"; [ -z "$n" ] && n=0 + if [ "$n" -ge 1000000000 ] 2>/dev/null; then + printf -v _FN '%d.%02dB' "$((n / 1000000000))" "$(( (n % 1000000000) / 10000000 ))" + elif [ "$n" -ge 1000000 ] 2>/dev/null; then + printf -v _FN '%d.%02dM' "$((n / 1000000))" "$(( (n % 1000000) / 10000 ))" + elif [ "$n" -ge 1000 ] 2>/dev/null; then + printf -v _FN '%d.%01dK' "$((n / 1000))" "$(( (n % 1000) / 100 ))" + else + printf -v _FN '%d' "$n" + fi +} + +_psi_month() { + case "$1" in + 01) _MN="Jan";; 02) _MN="Feb";; 03) _MN="Mar";; + 04) _MN="Apr";; 05) _MN="May";; 06) _MN="Jun";; + 07) _MN="Jul";; 08) _MN="Aug";; 09) _MN="Sep";; + 10) _MN="Oct";; 11) _MN="Nov";; 12) _MN="Dec";; + *) _MN="$1";; + esac +} + +# Vertical bar chart with min-max scaling and half-block tops +# Args: $1=color escape, $2=data lines "value label\n...", $3=month name (optional), $4=nolist (suppress values) +_psi_vchart() { + local _vc_clr="$1" _vc_month="${3:-}" _vc_nolist="${4:-}" + local -a _vc_v _vc_l + local _vc_n=0 _vc_min=2147483647 _vc_max=0 _vv _vl + + while read -r _vv _vl; do + [ -z "$_vv" ] && continue + _vc_v[_vc_n]="$_vv" + _vc_l[_vc_n]="$_vl" + [ "$_vv" -lt "$_vc_min" ] 2>/dev/null && _vc_min="$_vv" + [ "$_vv" -gt "$_vc_max" ] 2>/dev/null && _vc_max="$_vv" + _vc_n=$((_vc_n + 1)) + done <<< "$2" + + [ "$_vc_n" -eq 0 ] && return 1 + + local _vc_rng=$((_vc_max - _vc_min)) + [ "$_vc_rng" -le 0 ] && _vc_rng=1 + local _vc_pad=$((_vc_rng / 4)) + [ "$_vc_pad" -lt 1 ] && _vc_pad=1 + local _vc_lo=$((_vc_min - _vc_pad)) + [ "$_vc_lo" -lt 0 ] && _vc_lo=0 + local _vc_hi=$((_vc_max + _vc_pad)) + local _vc_span=$((_vc_hi - _vc_lo)) + [ "$_vc_span" -le 0 ] && _vc_span=1 + local _vc_h=8 _row _j _tf _th + + for (( _row=_vc_h; _row>=1; _row-- )); do + _tf=$(( _vc_lo + (_vc_span * _row / _vc_h) )) + _th=$(( _vc_lo + (_vc_span * (2*_row - 1) / (2*_vc_h)) )) + # Scale labels on top, middle, bottom rows + if [ "$_row" -eq "$_vc_h" ]; then + _psi_fmt_num "$_vc_hi"; printf " %8s ┤" "$_FN" + elif [ "$_row" -eq 1 ]; then + _psi_fmt_num "$_vc_lo"; printf " %8s ┤" "$_FN" + elif [ "$_row" -eq $(( (_vc_h + 1) / 2 )) ]; then + _psi_fmt_num "$(( (_vc_hi + _vc_lo) / 2 ))"; printf " %8s ┤" "$_FN" + else + printf " │" + fi + for (( _j=0; _j<_vc_n; _j++ )); do + if [ "${_vc_v[_j]}" -ge "$_tf" ] 2>/dev/null; then + printf " ${_vc_clr}███${NC} " + elif [ "${_vc_v[_j]}" -ge "$_th" ] 2>/dev/null; then + printf " ${_vc_clr}▄▄▄${NC} " + else + printf " " + fi + done + printf "\n" + done + # X-axis + printf " └" + for (( _j=0; _j<_vc_n; _j++ )); do printf "──────"; done + printf "\n" + # Date labels with month prefix + if [ -n "$_vc_month" ]; then + printf " ${DIM}%-5s${NC} " "$_vc_month" + else + printf " " + fi + for (( _j=0; _j<_vc_n; _j++ )); do printf " %-3s " "${_vc_l[_j]}"; done + printf "\n" + # Exact values — vertical list with month prefix (skip if $4=nolist) + if [ "$_vc_nolist" != "nolist" ]; then + local _vc_mn="${_vc_month:-""}" + for (( _j=0; _j<_vc_n; _j++ )); do + _psi_fmt_num "${_vc_v[_j]}" + printf " ${DIM} %s %s : %s${NC}\n" "$_vc_mn" "${_vc_l[_j]}" "$_FN" + done + fi +} + +#═══════════════════════════════════════════════════════════════════════ +# Iran Connectivity Status Page +#═══════════════════════════════════════════════════════════════════════ + +show_iran_connectivity() { + local _ic_exit=0 _force_refresh=true + local _BARS="████████████████████" + local _EMPTY="░░░░░░░░░░░░░░░░░░░░" + local _cache_max=300 # 5 minutes in seconds + + while [ "$_ic_exit" -eq 0 ]; do + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} IRAN CONNECTIVITY STATUS${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + + local _ic_need_fetch=true _ic_cache_age=0 + local _ic_today _ic_today_local + _ic_today=$(date -u +%Y-%m-%d) + _ic_today_local=$(date +%Y-%m-%d) + + # --- Cache check (5 minutes) --- + if ! $_force_refresh && [ -f "$INSTALL_DIR/.iran_cache_ioda_bgp" ]; then + local _ic_now _ic_ts + _ic_now=$(date +%s) + _ic_ts=$(stat -c %Y "$INSTALL_DIR/.iran_cache_ioda_bgp" 2>/dev/null || echo 0) + _ic_cache_age=$(( _ic_now - _ic_ts )) + if [ "$_ic_cache_age" -lt "$_cache_max" ] 2>/dev/null; then + _ic_need_fetch=false + fi + fi + + if $_ic_need_fetch; then + _force_refresh=false + echo -e " ${DIM}Fetching data from IODA, OONI...${NC}" + + local _tmpdir + _tmpdir=$(mktemp -d) + + local _ic_now _ic_7d_ago _ic_today _ic_today_local _ic_7d_date + _ic_now=$(date +%s) + _ic_7d_ago=$(( _ic_now - 7 * 86400 )) + _ic_today=$(date -u +%Y-%m-%d) + _ic_today_local=$(date +%Y-%m-%d) + _ic_7d_date=$(date -u -d "@$_ic_7d_ago" +%Y-%m-%d 2>/dev/null || date -u -d "7 days ago" +%Y-%m-%d 2>/dev/null) + + # Parallel fetches + curl -s --max-time 20 "https://api.ioda.inetintel.cc.gatech.edu/v2/signals/raw/country/IR?from=$_ic_7d_ago&until=$_ic_now&datasource=bgp&maxPoints=7" > "$_tmpdir/ioda_bgp" 2>/dev/null & + curl -s --max-time 20 "https://api.ioda.inetintel.cc.gatech.edu/v2/signals/raw/country/IR?from=$_ic_7d_ago&until=$_ic_now&datasource=ping-slash24&maxPoints=7" > "$_tmpdir/ioda_ping" 2>/dev/null & + curl -s --max-time 20 "https://api.ioda.inetintel.cc.gatech.edu/v2/outages/alerts?entityType=country&entityCode=IR&from=$_ic_7d_ago&until=$_ic_now&limit=10" > "$_tmpdir/ioda_alerts" 2>/dev/null & + curl -s --max-time 15 "https://api.ooni.io/api/v1/aggregation?probe_cc=IR&test_name=web_connectivity&since=$_ic_7d_date&until=$_ic_today&axis_x=measurement_start_day" > "$_tmpdir/ooni_anomaly" 2>/dev/null & + curl -s --max-time 20 "https://api.ioda.inetintel.cc.gatech.edu/v2/signals/raw/country/IR?from=$_ic_7d_ago&until=$_ic_now&datasource=merit-nt&maxPoints=7" > "$_tmpdir/ioda_merit" 2>/dev/null & + curl -s --max-time 20 "https://api.ioda.inetintel.cc.gatech.edu/v2/signals/raw/country/IR?from=$_ic_7d_ago&until=$_ic_now&datasource=gtr&maxPoints=7" > "$_tmpdir/ioda_gtr" 2>/dev/null & + # IODA latency & packet loss + curl -s --max-time 20 "https://api.ioda.inetintel.cc.gatech.edu/v2/signals/raw/country/IR?from=$_ic_7d_ago&until=$_ic_now&datasource=ping-slash24-latency&maxPoints=1" > "$_tmpdir/ioda_latency" 2>/dev/null & + curl -s --max-time 20 "https://api.ioda.inetintel.cc.gatech.edu/v2/signals/raw/country/IR?from=$_ic_7d_ago&until=$_ic_now&datasource=ping-slash24-loss&maxPoints=1" > "$_tmpdir/ioda_loss" 2>/dev/null & + # irinter.net network score (7 days) + curl -s --max-time 15 "https://irinter.net/api/data/network-score?from=$_ic_7d_ago&until=$_ic_now" > "$_tmpdir/irinter" 2>/dev/null & + # RIPE Atlas probe counts + curl -s --max-time 10 "https://atlas.ripe.net/api/v2/probes/?country_code=IR&status=1&page_size=1" > "$_tmpdir/ripe_up" 2>/dev/null & + curl -s --max-time 10 "https://atlas.ripe.net/api/v2/probes/?country_code=IR&status=2&page_size=1" > "$_tmpdir/ripe_down" 2>/dev/null & + # OONI messaging apps + curl -s --max-time 15 "https://api.ooni.io/api/v1/aggregation?probe_cc=IR&test_name=telegram&since=$_ic_7d_date&until=$_ic_today" > "$_tmpdir/ooni_telegram" 2>/dev/null & + curl -s --max-time 15 "https://api.ooni.io/api/v1/aggregation?probe_cc=IR&test_name=whatsapp&since=$_ic_7d_date&until=$_ic_today" > "$_tmpdir/ooni_whatsapp" 2>/dev/null & + curl -s --max-time 15 "https://api.ooni.io/api/v1/aggregation?probe_cc=IR&test_name=signal&since=$_ic_7d_date&until=$_ic_today" > "$_tmpdir/ooni_signal" 2>/dev/null & + curl -s --max-time 15 "https://api.ooni.io/api/v1/aggregation?probe_cc=IR&test_name=facebook_messenger&since=$_ic_7d_date&until=$_ic_today" > "$_tmpdir/ooni_facebook" 2>/dev/null & + wait + + # Validate & cache + local _f + for _f in ioda_bgp ioda_ping ioda_alerts ooni_anomaly ioda_merit ioda_gtr ioda_latency ioda_loss irinter ripe_up ripe_down ooni_telegram ooni_whatsapp ooni_signal ooni_facebook; do + if [ -s "$_tmpdir/$_f" ]; then + cp "$_tmpdir/$_f" "$INSTALL_DIR/.iran_cache_$_f" + fi + done + _ic_cache_age=0 + rm -rf "$_tmpdir" + fi + + # --- Format cache age with timestamp --- + local _ic_update_ts=$(( _ic_now - _ic_cache_age )) + local _ic_update_time + _ic_update_time=$(date -d "@$_ic_update_ts" '+%b %d, %H:%M' 2>/dev/null) || _ic_update_time=$(date -r "$_ic_update_ts" '+%b %d, %H:%M' 2>/dev/null) || _ic_update_time="" + local _ic_age_label="just now" + if [ "$_ic_cache_age" -gt 0 ] 2>/dev/null; then + if [ "$_ic_cache_age" -lt 60 ]; then + _ic_age_label="${_ic_cache_age}s ago" + elif [ "$_ic_cache_age" -lt 3600 ]; then + _ic_age_label="$((_ic_cache_age / 60))m ago" + else + _ic_age_label="$((_ic_cache_age / 3600))h ago" + fi + fi + if [ -n "$_ic_update_time" ]; then + echo -e " ${DIM}Updated: ${_ic_update_time} (${_ic_age_label})${NC}" + else + echo -e " ${DIM}Updated: ${_ic_age_label}${NC}" + fi + echo "" + + # --- Load cached data (no subprocesses) --- + local _ioda_bgp_raw="" _ioda_ping_raw="" _ioda_alerts_raw="" + local _ooni_anom_raw="" + [ -f "$INSTALL_DIR/.iran_cache_ioda_bgp" ] && _ioda_bgp_raw=$(<"$INSTALL_DIR/.iran_cache_ioda_bgp") + [ -f "$INSTALL_DIR/.iran_cache_ioda_ping" ] && _ioda_ping_raw=$(<"$INSTALL_DIR/.iran_cache_ioda_ping") + [ -f "$INSTALL_DIR/.iran_cache_ioda_alerts" ] && _ioda_alerts_raw=$(<"$INSTALL_DIR/.iran_cache_ioda_alerts") + [ -f "$INSTALL_DIR/.iran_cache_ooni_anomaly" ] && _ooni_anom_raw=$(<"$INSTALL_DIR/.iran_cache_ooni_anomaly") + local _ioda_merit_raw="" _ioda_gtr_raw="" + [ -f "$INSTALL_DIR/.iran_cache_ioda_merit" ] && _ioda_merit_raw=$(<"$INSTALL_DIR/.iran_cache_ioda_merit") + [ -f "$INSTALL_DIR/.iran_cache_ioda_gtr" ] && _ioda_gtr_raw=$(<"$INSTALL_DIR/.iran_cache_ioda_gtr") + local _ioda_latency_raw="" _ioda_loss_raw="" + [ -f "$INSTALL_DIR/.iran_cache_ioda_latency" ] && _ioda_latency_raw=$(<"$INSTALL_DIR/.iran_cache_ioda_latency") + [ -f "$INSTALL_DIR/.iran_cache_ioda_loss" ] && _ioda_loss_raw=$(<"$INSTALL_DIR/.iran_cache_ioda_loss") + local _irinter_raw="" + [ -f "$INSTALL_DIR/.iran_cache_irinter" ] && _irinter_raw=$(<"$INSTALL_DIR/.iran_cache_irinter") + local _ripe_up_raw="" _ripe_down_raw="" + [ -f "$INSTALL_DIR/.iran_cache_ripe_up" ] && _ripe_up_raw=$(<"$INSTALL_DIR/.iran_cache_ripe_up") + [ -f "$INSTALL_DIR/.iran_cache_ripe_down" ] && _ripe_down_raw=$(<"$INSTALL_DIR/.iran_cache_ripe_down") + local _ooni_tg_raw="" _ooni_wa_raw="" _ooni_sig_raw="" _ooni_fb_raw="" + [ -f "$INSTALL_DIR/.iran_cache_ooni_telegram" ] && _ooni_tg_raw=$(<"$INSTALL_DIR/.iran_cache_ooni_telegram") + [ -f "$INSTALL_DIR/.iran_cache_ooni_whatsapp" ] && _ooni_wa_raw=$(<"$INSTALL_DIR/.iran_cache_ooni_whatsapp") + [ -f "$INSTALL_DIR/.iran_cache_ooni_signal" ] && _ooni_sig_raw=$(<"$INSTALL_DIR/.iran_cache_ooni_signal") + [ -f "$INSTALL_DIR/.iran_cache_ooni_facebook" ] && _ooni_fb_raw=$(<"$INSTALL_DIR/.iran_cache_ooni_facebook") + # ============================================================= + # PARSE IODA BGP DATA + # ============================================================= + local _bgp_values="" _bgp_from=0 _bgp_step=86400 + if [ -n "$_ioda_bgp_raw" ]; then + # Pure bash extraction (avoids 6 subprocess forks) + local _tmp + _tmp="${_ioda_bgp_raw#*\"from\":}"; _bgp_from="${_tmp%%[,\}]*}"; _bgp_from="${_bgp_from//[!0-9]/}" + _tmp="${_ioda_bgp_raw#*\"step\":}"; _bgp_step="${_tmp%%[,\}]*}"; _bgp_step="${_bgp_step//[!0-9]/}" + [ -z "$_bgp_from" ] && _bgp_from=0 + [ -z "$_bgp_step" ] && _bgp_step=86400 + # Extract values array content between "values":[ and ] + _tmp="${_ioda_bgp_raw#*\"values\":\[}"; _bgp_values="${_tmp%%\]*}" + fi + + # Build BGP chart data: "normalized_value day_label\n" + # Skip the last (current/incomplete) time bucket + local _bgp_chart="" _bgp_max=0 _bgp_latest=0 _bgp_latest_pct=0 + local _ic_now_epoch + _ic_now_epoch=$(date +%s 2>/dev/null || echo 0) + if [ -n "$_bgp_values" ]; then + local _bgp_arr _bv _bi=0 _bts _bday _bmon="" _bgp_int + IFS=',' read -ra _bgp_arr <<< "$_bgp_values" + # Find max (skip incomplete current bucket) + for _bv in "${_bgp_arr[@]}"; do + _bts=$(( _bgp_from + (_bi * _bgp_step) )) + _bi=$((_bi + 1)) + [ "$_bts" -ge "$_ic_now_epoch" ] 2>/dev/null && continue + _bgp_int="${_bv%%.*}" + _bgp_int="${_bgp_int//[!0-9]/}" + [ -z "$_bgp_int" ] && _bgp_int=0 + [ "$_bgp_int" -gt "$_bgp_max" ] 2>/dev/null && _bgp_max="$_bgp_int" + done + [ "$_bgp_max" -eq 0 ] && _bgp_max=1 + # Build chart data normalized to 0-100 (skip incomplete current bucket) + _bi=0 + for _bv in "${_bgp_arr[@]}"; do + _bts=$(( _bgp_from + (_bi * _bgp_step) )) + _bi=$((_bi + 1)) + [ "$_bts" -ge "$_ic_now_epoch" ] 2>/dev/null && continue + _bgp_int="${_bv%%.*}" + _bgp_int="${_bgp_int//[!0-9]/}" + [ -z "$_bgp_int" ] && _bgp_int=0 + local _bpct=$(( (_bgp_int * 100) / _bgp_max )) + _bday=$(date -u -d "@$_bts" +"%m %d" 2>/dev/null) + if [ -n "$_bday" ]; then + [ -z "$_bmon" ] && { _psi_month "${_bday%% *}"; _bmon="$_MN"; } + _bgp_chart+="${_bpct} ${_bday##* }"$'\n' + fi + _bgp_latest="$_bgp_int" + _bgp_latest_pct="$_bpct" + done + fi + + # ============================================================= + # PARSE IODA PING DATA + # ============================================================= + local _ping_values="" _ping_from=0 _ping_step=86400 + if [ -n "$_ioda_ping_raw" ]; then + local _tmp + _tmp="${_ioda_ping_raw#*\"from\":}"; _ping_from="${_tmp%%[,\}]*}"; _ping_from="${_ping_from//[!0-9]/}" + _tmp="${_ioda_ping_raw#*\"step\":}"; _ping_step="${_tmp%%[,\}]*}"; _ping_step="${_ping_step//[!0-9]/}" + [ -z "$_ping_from" ] && _ping_from=0 + [ -z "$_ping_step" ] && _ping_step=86400 + _tmp="${_ioda_ping_raw#*\"values\":\[}"; _ping_values="${_tmp%%\]*}" + fi + + local _ping_chart="" _ping_max=0 + if [ -n "$_ping_values" ]; then + local _ping_arr _pv _pi=0 _pts _pday _pmon="" _ping_int + IFS=',' read -ra _ping_arr <<< "$_ping_values" + # Find max (skip incomplete current bucket) + for _pv in "${_ping_arr[@]}"; do + _pts=$(( _ping_from + (_pi * _ping_step) )) + _pi=$((_pi + 1)) + [ "$_pts" -ge "$_ic_now_epoch" ] 2>/dev/null && continue + _ping_int="${_pv%%.*}" + _ping_int="${_ping_int//[!0-9]/}" + [ -z "$_ping_int" ] && _ping_int=0 + [ "$_ping_int" -gt "$_ping_max" ] 2>/dev/null && _ping_max="$_ping_int" + done + [ "$_ping_max" -eq 0 ] && _ping_max=1 + _pi=0 + for _pv in "${_ping_arr[@]}"; do + _pts=$(( _ping_from + (_pi * _ping_step) )) + _pi=$((_pi + 1)) + [ "$_pts" -ge "$_ic_now_epoch" ] 2>/dev/null && continue + _ping_int="${_pv%%.*}" + _ping_int="${_ping_int//[!0-9]/}" + [ -z "$_ping_int" ] && _ping_int=0 + local _ppct=$(( (_ping_int * 100) / _ping_max )) + _pday=$(date -u -d "@$_pts" +"%m %d" 2>/dev/null) + if [ -n "$_pday" ]; then + [ -z "$_pmon" ] && { _psi_month "${_pday%% *}"; _pmon="$_MN"; } + _ping_chart+="${_ppct} ${_pday##* }"$'\n' + fi + done + fi + + # ============================================================= + # PARSE IRINTER.NET NETWORK SCORE DATA + # ============================================================= + local _ir_latest="" _ir_latest_int=0 _ir_trend="Stable" _ir_chart="" _ir_mon="" + if [ -n "$_irinter_raw" ] && [ "${#_irinter_raw}" -gt 5 ]; then + local _tmp + # Latest value (last "value": in data — most recent) + _tmp="${_irinter_raw##*\"value\":}"; _ir_latest="${_tmp%%[,\}\]]*}" + _ir_latest="${_ir_latest//[!0-9.]/}" + _ir_latest_int="${_ir_latest%%.*}"; _ir_latest_int="${_ir_latest_int:-0}" + + # First value (first "value": in data — oldest) + local _ir_first="" + _tmp="${_irinter_raw#*\"value\":}"; _ir_first="${_tmp%%[,\}\]]*}" + _ir_first="${_ir_first//[!0-9.]/}" + local _ir_first_int="${_ir_first%%.*}"; _ir_first_int="${_ir_first_int:-0}" + + # Trend: compare first vs latest + local _ir_diff=$(( _ir_latest_int - _ir_first_int )) + if [ "$_ir_diff" -gt 2 ] 2>/dev/null; then + _ir_trend="Increasing" + elif [ "$_ir_diff" -lt -2 ] 2>/dev/null; then + _ir_trend="Decreasing" + fi + + # Build daily chart: aggregate 5-min data points into daily averages + local _ir_data_block + _tmp="${_irinter_raw#*\"data\":\[}"; _ir_data_block="${_tmp%%\]*}" + + # Group by day bucket (epoch / 86400) — avoids date subprocess per entry + local -A _ir_day_sum _ir_day_cnt _ir_day_ts + local _ir_entries _ir_entry _ir_efrom _ir_eval _ir_eval_int _ir_day_key + _ir_entries="${_ir_data_block//\},\{/$'\n'}" + while IFS= read -r _ir_entry; do + [ -z "$_ir_entry" ] && continue + _tmp="${_ir_entry#*\"from\":}"; _ir_efrom="${_tmp%%[,\}]*}" + _ir_efrom="${_ir_efrom//[!0-9]/}" + [ -z "$_ir_efrom" ] && continue + _tmp="${_ir_entry#*\"value\":}"; _ir_eval="${_tmp%%[,\}\]]*}" + _ir_eval="${_ir_eval//[!0-9.]/}" + [ -z "$_ir_eval" ] && continue + _ir_eval_int="${_ir_eval%%.*}"; _ir_eval_int="${_ir_eval_int:-0}" + _ir_day_key=$(( _ir_efrom / 86400 )) + _ir_day_sum[$_ir_day_key]=$(( ${_ir_day_sum[$_ir_day_key]:-0} + _ir_eval_int )) + _ir_day_cnt[$_ir_day_key]=$(( ${_ir_day_cnt[$_ir_day_key]:-0} + 1 )) + [ -z "${_ir_day_ts[$_ir_day_key]+x}" ] && _ir_day_ts[$_ir_day_key]="$_ir_efrom" + done <<< "$_ir_entries" + + # Build chart sorted by day (skip today — incomplete data) + local _today_key=$(( _ic_now_epoch / 86400 )) + local _ir_dk _ir_davg _ir_dts _ir_dday + for _ir_dk in $(echo "${!_ir_day_sum[@]}" | tr ' ' '\n' | sort -n); do + [ "$_ir_dk" -eq "$_today_key" ] 2>/dev/null && continue + if [ "${_ir_day_cnt[$_ir_dk]:-0}" -gt 0 ] 2>/dev/null; then + _ir_davg=$(( ${_ir_day_sum[$_ir_dk]} / ${_ir_day_cnt[$_ir_dk]} )) + else + _ir_davg=0 + fi + _ir_dts="${_ir_day_ts[$_ir_dk]}" + _ir_dday=$(date -u -d "@$_ir_dts" +"%m %d" 2>/dev/null) + if [ -n "$_ir_dday" ]; then + [ -z "$_ir_mon" ] && { _psi_month "${_ir_dday%% *}"; _ir_mon="$_MN"; } + _ir_chart+="${_ir_davg} ${_ir_dday##* }"$'\n' + fi + done + fi + + # ============================================================= + # STATUS INDICATOR (two lines: irinter.net + BGP) + # ============================================================= + local _showed_status=false + if [ -n "$_ir_latest" ] && [ "$_ir_latest_int" -gt 0 ] 2>/dev/null; then + local _ir_sclr="${GREEN}" _ir_slabel="ONLINE" + local _ir_tclr="${DIM}" _ir_tarrow="" + if [ "$_ir_latest_int" -lt 50 ] 2>/dev/null; then + _ir_sclr="${RED}"; _ir_slabel="OFFLINE" + elif [ "$_ir_latest_int" -lt 80 ] 2>/dev/null; then + _ir_sclr="${YELLOW}"; _ir_slabel="WARNING" + fi + case "$_ir_trend" in + Increasing) _ir_tarrow="^"; _ir_tclr="${GREEN}" ;; + Decreasing) _ir_tarrow="v"; _ir_tclr="${RED}" ;; + *) _ir_tarrow="-"; _ir_tclr="${DIM}" ;; + esac + echo -e " ${_ir_sclr}●${NC} ${_ir_sclr}${BOLD}${_ir_slabel}${NC} ${DIM}—${NC} ${_ir_sclr}${_ir_latest_int}%${NC} ${DIM}connectivity${NC} ${_ir_tclr}${_ir_tarrow} ${_ir_trend}${NC} ${DIM}(irinter.net)${NC}" + _showed_status=true + fi + if [ -n "$_bgp_chart" ]; then + local _bgp_sclr="${GREEN}" + [ "$_bgp_latest_pct" -lt 80 ] 2>/dev/null && _bgp_sclr="${YELLOW}" + [ "$_bgp_latest_pct" -lt 40 ] 2>/dev/null && _bgp_sclr="${RED}" + echo -e " ${_bgp_sclr}●${NC} ${_bgp_sclr}${_bgp_latest_pct}%${NC} ${DIM}BGP reachability${NC} ${DIM}(IODA)${NC}" + _showed_status=true + fi + $_showed_status && echo "" + + # ============================================================= + # 1. IRAN INTERNET EXCHANGE SCORE (irinter.net - 7-day chart) + # ============================================================= + if [ -n "$_ir_chart" ]; then + echo -e " ${CYAN}── Iran Internet Exchange Score (irinter.net - last 7 days) ──${NC}" + echo "" + _psi_vchart "${GREEN}" "$_ir_chart" "$_ir_mon" "nolist" + echo "" + fi + + # ============================================================= + # 2. INTERNET REACHABILITY (IODA BGP - vertical bar chart) + # ============================================================= + if [ -n "$_bgp_chart" ]; then + echo -e " ${CYAN}── Internet Reachability (IODA BGP - last 7 days) ────────────${NC}" + echo "" + _psi_vchart "${GREEN}" "$_bgp_chart" "$_bmon" "nolist" + echo "" + fi + + # ============================================================= + # 2. ACTIVE PROBING (IODA ping - vertical bar chart) + # ============================================================= + if [ -n "$_ping_chart" ]; then + echo -e " ${CYAN}── Active Probing (IODA - last 7 days) ────────────────────────${NC}" + echo "" + _psi_vchart "${CYAN}" "$_ping_chart" "$_pmon" "nolist" + echo "" + fi + + # ============================================================= + # 3. RECENT OUTAGE ALERTS + # ============================================================= + echo -e " ${CYAN}── Recent Outage Alerts (IODA) ────────────────────────────────${NC}" + echo "" + local _has_alerts=false + if [ -n "$_ioda_alerts_raw" ]; then + # Extract data array content using bash string ops + local _alert_data _tmp + _tmp="${_ioda_alerts_raw#*\"data\":\[}"; _alert_data="${_tmp%%\],\"copyright\"*}" + if [ -n "$_alert_data" ] && [ "${#_alert_data}" -gt 2 ]; then + printf " ${DIM}%-14s %-10s %-10s %-8s${NC}\n" "Date" "Source" "Level" "Condition" + local _alert_entries + _alert_entries="${_alert_data//\},\{/$'\n'}" + while IFS= read -r _ae; do + [ -z "$_ae" ] && continue + local _a_from _a_ds _a_level _a_cond _a_date + # Pure bash field extraction + _tmp="${_ae#*\"from\":}"; _a_from="${_tmp%%[,\}]*}"; _a_from="${_a_from//[!0-9]/}" + _tmp="${_ae#*\"datasource\":\"}"; _a_ds="${_tmp%%\"*}" + _tmp="${_ae#*\"level\":\"}"; _a_level="${_tmp%%\"*}" + _tmp="${_ae#*\"condition\":\"}"; _a_cond="${_tmp%%\"*}" + [ -z "$_a_from" ] && continue + _a_date=$(date -u -d "@$_a_from" +"%b %d %H:%M" 2>/dev/null || echo "unknown") + local _a_clr="${YELLOW}" + [ "$_a_level" = "critical" ] && _a_clr="${RED}" + printf " %-14s %-10s ${_a_clr}%-10s${NC} %-8s\n" "$_a_date" "${_a_ds:-?}" "${_a_level:-?}" "${_a_cond:-?}" + _has_alerts=true + done <<< "$_alert_entries" + fi + fi + if ! $_has_alerts; then + echo -e " ${GREEN}No outages detected in last 7 days${NC}" + fi + echo "" + + # ============================================================= + # 4. NETWORK ANOMALY TREND (OONI - vertical bar chart) + # ============================================================= + if [ -n "$_ooni_anom_raw" ]; then + echo -e " ${CYAN}── Network Anomaly Trend (OONI - last 7 days) ────────────────${NC}" + echo -e " ${DIM}Higher = more censorship/disruption detected${NC}" + echo "" + + # Aggregate hourly data into daily: sum anomaly_count and measurement_count per date + # Uses pure bash string ops to avoid subprocess forks (~168 entries × 3 sed = 500+ forks saved) + local _anom_entries _anom_line _anom_date _anom_cnt _anom_tot _anom_tmp + local -A _anom_day_a _anom_day_t + _anom_entries="${_ooni_anom_raw//\},\{/$'\n'}" + while IFS= read -r _anom_line; do + [ -z "$_anom_line" ] && continue + # Extract date: find "measurement_start_day":" then grab YYYY-MM-DD before T + _anom_tmp="${_anom_line#*\"measurement_start_day\":\"}" + [ "$_anom_tmp" = "$_anom_line" ] && continue + _anom_date="${_anom_tmp%%T*}" + [[ "$_anom_date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] || continue + # Extract anomaly_count: grab digits after "anomaly_count": + _anom_tmp="${_anom_line#*\"anomaly_count\":}" + _anom_cnt="${_anom_tmp%%[,\}]*}" + _anom_cnt="${_anom_cnt//[!0-9]/}" + # Extract measurement_count: grab digits after "measurement_count": + _anom_tmp="${_anom_line#*\"measurement_count\":}" + _anom_tot="${_anom_tmp%%[,\}]*}" + _anom_tot="${_anom_tot//[!0-9]/}" + _anom_cnt="${_anom_cnt:-0}"; _anom_tot="${_anom_tot:-0}" + _anom_day_a[$_anom_date]=$(( ${_anom_day_a[$_anom_date]:-0} + _anom_cnt )) + _anom_day_t[$_anom_date]=$(( ${_anom_day_t[$_anom_date]:-0} + _anom_tot )) + done <<< "$_anom_entries" + + # Build chart data sorted by date (skip incomplete today) + local _anom_chart="" _anom_mon="" _ad _apct + for _ad in $(echo "${!_anom_day_a[@]}" | tr ' ' '\n' | sort); do + [ "$_ad" = "$_ic_today" ] && continue + [ "$_ad" = "$_ic_today_local" ] && continue + if [ "${_anom_day_t[$_ad]:-0}" -gt 0 ] 2>/dev/null; then + _apct=$(( (${_anom_day_a[$_ad]} * 100) / ${_anom_day_t[$_ad]} )) + else + _apct=0 + fi + [ -z "$_anom_mon" ] && { _psi_month "${_ad:5:2}"; _anom_mon="$_MN"; } + _anom_chart+="${_apct} ${_ad:8:2}"$'\n' + done + + if [ -n "$_anom_chart" ]; then + _psi_vchart "${YELLOW}" "$_anom_chart" "$_anom_mon" + fi + echo "" + fi + + # ============================================================= + # 6. DARKNET TRAFFIC (IODA Merit Network Telescope) + # ============================================================= + local _merit_values="" _merit_from=0 _merit_step=86400 + if [ -n "$_ioda_merit_raw" ]; then + local _tmp + _tmp="${_ioda_merit_raw#*\"from\":}"; _merit_from="${_tmp%%[,\}]*}"; _merit_from="${_merit_from//[!0-9]/}" + _tmp="${_ioda_merit_raw#*\"step\":}"; _merit_step="${_tmp%%[,\}]*}"; _merit_step="${_merit_step//[!0-9]/}" + [ -z "$_merit_from" ] && _merit_from=0 + [ -z "$_merit_step" ] && _merit_step=86400 + _tmp="${_ioda_merit_raw#*\"values\":\[}"; _merit_values="${_tmp%%\]*}" + fi + if [ -n "$_merit_values" ]; then + echo -e " ${CYAN}── Darknet Traffic (IODA Merit-NT - last 7 days) ────────────${NC}" + echo -e " ${DIM}Unsolicited traffic volume — drops indicate outages${NC}" + echo "" + local _merit_arr _mv _mi=0 _mts _mday _mmon="" _merit_int _merit_max=0 _merit_chart="" + IFS=',' read -ra _merit_arr <<< "$_merit_values" + for _mv in "${_merit_arr[@]}"; do + _mts=$(( _merit_from + (_mi * _merit_step) )) + _mi=$((_mi + 1)) + [ "$_mts" -ge "$_ic_now_epoch" ] 2>/dev/null && continue + _merit_int="${_mv%%.*}"; _merit_int="${_merit_int//[!0-9]/}" + [ -z "$_merit_int" ] && _merit_int=0 + [ "$_merit_int" -gt "$_merit_max" ] 2>/dev/null && _merit_max="$_merit_int" + done + [ "$_merit_max" -eq 0 ] && _merit_max=1 + _mi=0 + for _mv in "${_merit_arr[@]}"; do + _mts=$(( _merit_from + (_mi * _merit_step) )) + _mi=$((_mi + 1)) + [ "$_mts" -ge "$_ic_now_epoch" ] 2>/dev/null && continue + _merit_int="${_mv%%.*}"; _merit_int="${_merit_int//[!0-9]/}" + [ -z "$_merit_int" ] && _merit_int=0 + _mday=$(date -u -d "@$_mts" +"%m %d" 2>/dev/null) + if [ -n "$_mday" ]; then + [ -z "$_mmon" ] && { _psi_month "${_mday%% *}"; _mmon="$_MN"; } + _merit_chart+="${_merit_int} ${_mday##* }"$'\n' + fi + done + [ -n "$_merit_chart" ] && _psi_vchart "${MAGENTA}" "$_merit_chart" "$_mmon" "nolist" + echo "" + fi + + # ============================================================= + # 7. GOOGLE SEARCH TRAFFIC (IODA Google Transparency Report) + # ============================================================= + local _gtr_values="" _gtr_from=0 _gtr_step=86400 + if [ -n "$_ioda_gtr_raw" ]; then + local _tmp + _tmp="${_ioda_gtr_raw#*\"from\":}"; _gtr_from="${_tmp%%[,\}]*}"; _gtr_from="${_gtr_from//[!0-9]/}" + _tmp="${_ioda_gtr_raw#*\"step\":}"; _gtr_step="${_tmp%%[,\}]*}"; _gtr_step="${_gtr_step//[!0-9]/}" + [ -z "$_gtr_from" ] && _gtr_from=0 + [ -z "$_gtr_step" ] && _gtr_step=86400 + _tmp="${_ioda_gtr_raw#*\"values\":\[}"; _gtr_values="${_tmp%%\]*}" + fi + if [ -n "$_gtr_values" ]; then + echo -e " ${CYAN}── Google Search Traffic (IODA GTR - last 7 days) ───────────${NC}" + echo -e " ${DIM}Google product traffic from Iran — drops indicate disruption${NC}" + echo "" + local _gtr_arr _gv _gi=0 _gts _gday _gmon="" _gtr_int _gtr_max=0 _gtr_chart="" + IFS=',' read -ra _gtr_arr <<< "$_gtr_values" + for _gv in "${_gtr_arr[@]}"; do + _gts=$(( _gtr_from + (_gi * _gtr_step) )) + _gi=$((_gi + 1)) + [ "$_gts" -ge "$_ic_now_epoch" ] 2>/dev/null && continue + _gtr_int="${_gv%%.*}"; _gtr_int="${_gtr_int//[!0-9]/}" + [ -z "$_gtr_int" ] && _gtr_int=0 + [ "$_gtr_int" -gt "$_gtr_max" ] 2>/dev/null && _gtr_max="$_gtr_int" + done + [ "$_gtr_max" -eq 0 ] && _gtr_max=1 + _gi=0 + for _gv in "${_gtr_arr[@]}"; do + _gts=$(( _gtr_from + (_gi * _gtr_step) )) + _gi=$((_gi + 1)) + [ "$_gts" -ge "$_ic_now_epoch" ] 2>/dev/null && continue + _gtr_int="${_gv%%.*}"; _gtr_int="${_gtr_int//[!0-9]/}" + [ -z "$_gtr_int" ] && _gtr_int=0 + _gday=$(date -u -d "@$_gts" +"%m %d" 2>/dev/null) + if [ -n "$_gday" ]; then + [ -z "$_gmon" ] && { _psi_month "${_gday%% *}"; _gmon="$_MN"; } + _gtr_chart+="${_gtr_int} ${_gday##* }"$'\n' + fi + done + [ -n "$_gtr_chart" ] && _psi_vchart "${YELLOW}" "$_gtr_chart" "$_gmon" "nolist" + echo "" + fi + + # ============================================================= + # 8. IODA LATENCY & PACKET LOSS + # ============================================================= + local _show_net_quality=false + local _latency_val="" _loss_val="" + if [ -n "$_ioda_latency_raw" ]; then + # Response has nested: "agg_values":{"median_latency":193.38,...} + local _tmp + _tmp="${_ioda_latency_raw#*\"median_latency\":}"; _latency_val="${_tmp%%[,\}]*}" + _latency_val="${_latency_val%%.*}"; _latency_val="${_latency_val//[!0-9]/}" + [ -n "$_latency_val" ] && [ "$_latency_val" != "$_ioda_latency_raw" ] && _show_net_quality=true || _latency_val="" + fi + if [ -n "$_ioda_loss_raw" ]; then + # Response has nested: "agg_values":{"loss_pct":34.43,...} + local _tmp + _tmp="${_ioda_loss_raw#*\"loss_pct\":}"; _loss_val="${_tmp%%[,\}]*}" + _loss_val="${_loss_val%%.*}"; _loss_val="${_loss_val//[!0-9]/}" + [ -n "$_loss_val" ] && [ "$_loss_val" != "$_ioda_loss_raw" ] && _show_net_quality=true || _loss_val="" + fi + if $_show_net_quality; then + echo -e " ${CYAN}── Network Quality (IODA Active Probing) ─────────────────────${NC}" + echo "" + local _lat_clr="${GREEN}" _loss_clr="${GREEN}" + if [ -n "$_latency_val" ]; then + [ "$_latency_val" -gt 500 ] 2>/dev/null && _lat_clr="${RED}" + [ "$_latency_val" -gt 200 ] 2>/dev/null && [ "$_latency_val" -le 500 ] 2>/dev/null && _lat_clr="${YELLOW}" + echo -e " Avg Latency: ${_lat_clr}${_latency_val} ms${NC}" + fi + if [ -n "$_loss_val" ]; then + [ "$_loss_val" -gt 10 ] 2>/dev/null && _loss_clr="${RED}" + [ "$_loss_val" -gt 3 ] 2>/dev/null && [ "$_loss_val" -le 10 ] 2>/dev/null && _loss_clr="${YELLOW}" + echo -e " Packet Loss: ${_loss_clr}${_loss_val}%${NC}" + fi + echo "" + fi + + # ============================================================= + # 9. MESSAGING APP REACHABILITY (OONI) + # ============================================================= + local _has_msg_data=false + local _msg_name _msg_raw _msg_ok _msg_anom _msg_total _msg_pct + for _msg_name in Telegram WhatsApp Signal Facebook; do + _msg_raw="" + case "$_msg_name" in + Telegram) _msg_raw="$_ooni_tg_raw" ;; + WhatsApp) _msg_raw="$_ooni_wa_raw" ;; + Signal) _msg_raw="$_ooni_sig_raw" ;; + Facebook) _msg_raw="$_ooni_fb_raw" ;; + esac + [ -n "$_msg_raw" ] && _has_msg_data=true + done + + if $_has_msg_data; then + echo -e " ${CYAN}── Messaging App Reachability (OONI - last 7 days) ──────────${NC}" + echo "" + printf " ${DIM}%-12s %8s %8s %-20s${NC}\n" "App" "Success" "Tests" "" + + for _msg_name in Telegram WhatsApp Signal Facebook; do + _msg_raw="" + case "$_msg_name" in + Telegram) _msg_raw="$_ooni_tg_raw" ;; + WhatsApp) _msg_raw="$_ooni_wa_raw" ;; + Signal) _msg_raw="$_ooni_sig_raw" ;; + Facebook) _msg_raw="$_ooni_fb_raw" ;; + esac + if [ -n "$_msg_raw" ]; then + local _tmp + _tmp="${_msg_raw#*\"ok_count\":}"; _msg_ok="${_tmp%%[,\}]*}"; _msg_ok="${_msg_ok//[!0-9]/}" + _tmp="${_msg_raw#*\"anomaly_count\":}"; _msg_anom="${_tmp%%[,\}]*}"; _msg_anom="${_msg_anom//[!0-9]/}" + _tmp="${_msg_raw#*\"measurement_count\":}"; _msg_total="${_tmp%%[,\}]*}"; _msg_total="${_msg_total//[!0-9]/}" + _msg_ok="${_msg_ok:-0}"; _msg_anom="${_msg_anom:-0}"; _msg_total="${_msg_total:-0}" + if [ "$_msg_total" -gt 0 ] 2>/dev/null; then + _msg_pct=$(( (_msg_ok * 100) / _msg_total )) + else + _msg_pct=0 + fi + local _msg_clr="${GREEN}" + [ "$_msg_pct" -lt 70 ] && _msg_clr="${YELLOW}" + [ "$_msg_pct" -lt 30 ] && _msg_clr="${RED}" + local _msg_blen=$(( _msg_pct / 5 )) + [ "$_msg_blen" -lt 0 ] && _msg_blen=0 + [ "$_msg_blen" -gt 20 ] && _msg_blen=20 + local _msg_elen=$(( 20 - _msg_blen )) + local _msg_bar="${_msg_clr}${_BARS:0:$_msg_blen}${NC}${DIM}${_EMPTY:0:$_msg_elen}${NC}" + _psi_fmt_num "$_msg_total" + printf " %-12s %7s%% %8s ${_msg_bar}\n" "$_msg_name" "$_msg_pct" "$_FN" + else + printf " %-12s %8s %8s ${DIM}no data${NC}\n" "$_msg_name" "—" "—" + fi + done + echo "" + fi + + # ============================================================= + # 10. RIPE ATLAS PROBE CONNECTIVITY + # ============================================================= + local _ripe_up_cnt="" _ripe_down_cnt="" + if [ -n "$_ripe_up_raw" ]; then + local _tmp + _tmp="${_ripe_up_raw#*\"count\":}"; _ripe_up_cnt="${_tmp%%[,\}]*}"; _ripe_up_cnt="${_ripe_up_cnt//[!0-9]/}" + fi + if [ -n "$_ripe_down_raw" ]; then + local _tmp + _tmp="${_ripe_down_raw#*\"count\":}"; _ripe_down_cnt="${_tmp%%[,\}]*}"; _ripe_down_cnt="${_ripe_down_cnt//[!0-9]/}" + fi + if [ -n "$_ripe_up_cnt" ] || [ -n "$_ripe_down_cnt" ]; then + echo -e " ${CYAN}── RIPE Atlas Probes in Iran ──────────────────────────────────${NC}" + echo "" + _ripe_up_cnt="${_ripe_up_cnt:-0}"; _ripe_down_cnt="${_ripe_down_cnt:-0}" + local _ripe_total=$(( _ripe_up_cnt + _ripe_down_cnt )) + local _ripe_pct=0 + [ "$_ripe_total" -gt 0 ] && _ripe_pct=$(( (_ripe_up_cnt * 100) / _ripe_total )) + local _ripe_clr="${GREEN}" + [ "$_ripe_pct" -lt 70 ] && _ripe_clr="${YELLOW}" + [ "$_ripe_pct" -lt 40 ] && _ripe_clr="${RED}" + echo -e " Connected: ${_ripe_clr}${_ripe_up_cnt}${NC} ${DIM}of ${_ripe_total} probes${NC} (${_ripe_clr}${_ripe_pct}%${NC})" + echo -e " Disconnected: ${DIM}${_ripe_down_cnt}${NC}" + echo "" + fi + + # ============================================================= + # FOOTER + # ============================================================= + echo -e " ${DIM}Sources: IODA (Georgia Tech) · OONI · RIPE Atlas · irinter.net${NC}" + echo "" + echo -e " ${CYAN}[r]${NC} Refresh ${CYAN}[i]${NC} Info ${CYAN}[0]${NC} Back ${DIM}(auto-refresh every 5m)${NC}" + echo "" + local _icc="" + # Auto-refresh: timeout = remaining cache life (min 60s) so page refreshes when cache expires + local _ic_timeout=$(( _cache_max - _ic_cache_age )) + [ "$_ic_timeout" -lt 60 ] && _ic_timeout=60 + read -n 1 -s -r -t "$_ic_timeout" _icc < /dev/tty || { _force_refresh=true; continue; } + case "$_icc" in + r|R) _force_refresh=true; continue ;; + i|I) _info_iran_connectivity; continue ;; + *) _ic_exit=1 ;; + esac + done +} + +#═══════════════════════════════════════════════════════════════════════ +# Iran Connectivity Test — ping, traceroute, MTR to Iranian endpoints +#═══════════════════════════════════════════════════════════════════════ + +_ir_test_install_deps() { + local _need=false + command -v traceroute &>/dev/null || _need=true + command -v mtr &>/dev/null || _need=true + if $_need; then + echo -e " ${DIM}Installing network tools (traceroute, mtr)...${NC}" + if command -v apt-get &>/dev/null; then + apt-get update -qq 2>/dev/null && apt-get install -y -qq traceroute mtr-tiny iputils-ping 2>/dev/null + elif command -v yum &>/dev/null; then + yum install -y -q traceroute mtr 2>/dev/null + elif command -v apk &>/dev/null; then + apk add --no-cache traceroute mtr 2>/dev/null + elif command -v dnf &>/dev/null; then + dnf install -y -q traceroute mtr 2>/dev/null + elif command -v pacman &>/dev/null; then + pacman -Sy --noconfirm traceroute mtr 2>/dev/null + fi + fi +} + +# Server list: IP|Name|City|ASN|ASN_Name|Hostname (6th field optional — used for HTTPS test) +# ~79 curated Iranian endpoints (services, ISPs, banks, DCs, universities, regional PoPs) +_IR_TEST_SERVERS="178.22.122.100|Shecan DNS|Tehran|43754|Asiatech|shecan.ir +217.218.155.155|TIC DNS 1|Tehran|12880|DCI| +217.218.127.127|TIC DNS 2|Tehran|12880|DCI| +85.15.1.14|Shatel|Tehran|31549|Shatel|shatel.ir +212.33.192.1|Asiatech|Tehran|43754|Asiatech|asiatech.ir +2.144.0.1|Irancell|Tehran|44244|Irancell|irancell.ir +188.213.72.1|Mobinnet|Tehran|50810|Mobinnet|mobinnet.ir +212.16.74.1|ZapISP|Tehran|44889|ZapISP| +31.25.104.1|Zi-Tel|Tehran|206065|Zi-Tel| +185.143.233.1|ArvanCloud|Tehran|205585|ArvanCloud|arvancloud.ir +77.104.64.1|Respina|Tehran|42337|Respina|respina.net +185.188.104.10|Digikala|Tehran|43211|Digikala|digikala.com +185.147.178.23|Filimo|Tehran|44932|IDPS|filimo.com +185.147.179.11|Aparat|Tehran|44932|IDPS|aparat.com +81.12.31.29|Torob|Tehran|51026|Mobinhost|torob.com +212.33.194.190|Tap30|Tehran|43754|Asiatech|tapsi.ir +94.182.176.33|Namava|Tehran|31549|Shatel|namava.ir +2.189.68.126|Bale Messenger|Tehran|48159|TIC-IR|bale.ai +5.106.8.151|Rubika|Tehran|197207|MCI|rubika.ir +185.143.235.201|Varzesh3|Tehran|205585|ArvanCloud|varzesh3.com +185.143.234.1|Eitaa|Tehran|205585|ArvanCloud|eitaa.com +185.60.137.26|Soroush|Tehran|21341|Soroush-Rasanheh|splus.ir +185.143.233.120|Snapp|Tehran|205585|ArvanCloud|snapp.ir +185.165.205.129|Telewebion|Tehran|64422|Sima-Rayan|telewebion.com +86.104.40.185|CafeBazaar|Tehran|25184|Afranet|cafebazaar.ir +45.89.201.10|Alibaba.ir|Tehran|34947|Alibaba-Travel|alibaba.ir +92.114.18.116|Taaghche|Tehran|47330|MobinNet|taaghche.com +185.143.232.253|Anten.ir|Tehran|205585|ArvanCloud|anten.ir +185.143.234.235|Jobinja|Tehran|205585|ArvanCloud|jobinja.ir +185.143.233.235|Nobitex|Tehran|205585|ArvanCloud|nobitex.ir +45.89.137.20|ZarinPal|Tehran|208675|Hamrah-Pardaz|zarinpal.com +185.167.73.34|Shaparak|Tehran|49796|Shaparak|shaparak.ir +185.143.232.201|Pasargad Bank|Tehran|205585|ArvanCloud|bpi.ir +193.8.139.22|Saman Bank|Tehran|31182|Saman-Bank|sb24.ir +152.89.13.54|Sharif Univ|Tehran|12660|SUT|sharif.edu +185.211.88.131|Amirkabir Univ|Tehran|59794|AUT|aut.ac.ir +194.225.0.10|IPM Research|Tehran|6736|IPM|ipm.ir +185.147.176.1|Faraso|Tehran|44932|IDPS|faraso.org +185.86.180.1|NetPitch|Tehran|48551|Sindad| +185.213.164.1|Noavaran|Tehran|61173|GreenWeb| +185.215.228.1|DadehNegar|Tehran|42337|Respina| +185.228.236.11|ArvanCloud CDN|Tehran|202468|ArvanCDN|arvancloud.ir +78.38.112.1|TIC Karaj|Karaj|58224|TIC| +37.255.0.1|TIC Isfahan|Isfahan|58224|TIC| +37.254.0.1|TIC Isfahan 2|Isfahan|58224|TIC| +5.232.0.1|TIC Mashhad|Mashhad|58224|TIC| +5.235.0.1|TIC Tabriz|Tabriz|58224|TIC| +2.186.32.1|TIC Tabriz 2|Tabriz|58224|TIC| +94.74.176.1|Pishgaman Shiraz|Shiraz|44208|Pishgaman|pishgaman.net +78.39.240.1|TIC Shiraz|Shiraz|58224|TIC| +185.236.36.1|Shiraz DC|Shiraz|48551|Sindad| +2.182.96.1|TIC BandarAbbas|BandarAbbas|58224|TIC| +85.185.161.1|TIC Yazd|Yazd|58224|TIC| +78.39.246.1|TIC Kermanshah|Kermanshah|58224|TIC| +85.185.248.1|TIC Sanandaj|Sanandaj|58224|TIC| +94.182.0.1|Shatel Ahvaz|Ahvaz|31549|Shatel|shatel.ir +2.187.1.1|TIC Rasht|Rasht|58224|TIC| +2.185.128.2|TIC Hamadan|Hamadan|58224|TIC| +2.187.192.1|TIC Qazvin|Qazvin|58224|TIC| +80.191.161.1|TIC Kerman|Kerman|58224|TIC| +2.187.32.2|TIC Urmia|Urmia|58224|TIC| +78.38.168.1|TIC Arak|Arak|58224|TIC| +80.191.250.2|TIC Gorgan|Gorgan|58224|TIC| +217.219.166.1|TIC Sari|Sari|58224|TIC| +80.191.174.1|TIC Zahedan|Zahedan|58224|TIC| +5.234.192.2|TIC Zanjan|Zanjan|58224|TIC| +2.183.0.1|TIC Bushehr|Bushehr|58224|TIC| +2.185.192.1|TIC Khorramabad|Khorramabad|58224|TIC| +92.42.50.130|Irancell.ir|Tehran|44244|Irancell|irancell.ir +188.213.72.112|Mobinnet.ir|Tehran|50810|Mobinnet|mobinnet.ir +80.75.12.17|Afranet.com|Tehran|25184|Afranet|afranet.com +77.104.74.208|Respina.net|Tehran|42337|Respina|respina.net +77.36.149.173|IRIB|Tehran|42586|IRIB|irib.ir +45.157.244.26|Fars News|Tehran|62229|FarsNews|farsnews.ir +185.53.142.188|SibApp|Tehran|51026|Mobinhost|sibapp.com +185.126.18.154|Pishgaman DC|Tehran|49100|Pishgaman|pishgaman.net +85.15.17.13|Shatel.ir|Tehran|31549|Shatel|shatel.ir +185.98.112.170|Asiatech.ir|Tehran|43754|Asiatech|asiatech.ir +185.120.222.22|Myket|Tehran|43754|Asiatech|myket.ir +78.157.43.1|Electro Net|Tehran|62442|Samane-Fanava| +185.188.104.1|Digikala DC|Tehran|43211|Digikala|digikala.com +185.188.105.1|Digikala DC 2|Tehran|43211|Digikala| +92.114.18.1|MobinNet DC|Tehran|47330|MobinNet| +185.60.136.1|Soroush DC|Tehran|21341|Soroush-Rasanheh| +94.74.177.1|Pishgaman Shiraz 2|Shiraz|44208|Pishgaman| +185.53.143.1|Mobinhost DC|Tehran|51026|Mobinhost| +185.236.37.1|Sindad DC|Shiraz|48551|Sindad| +94.74.179.1|Pishgaman Shiraz 3|Shiraz|44208|Pishgaman|" + +# Parse ping output: extract avg latency and loss — sets _PING_AVG and _PING_LOSS +_ir_parse_ping() { + _PING_AVG="" _PING_LOSS="100" + [ ! -f "$1" ] && return 1 + local _line + # Extract rtt avg: "rtt min/avg/max/mdev = 1.0/2.0/3.0/0.5 ms" or "round-trip min/avg/max..." + while IFS= read -r _line; do + case "$_line" in + *min/avg/max*) + # Get the 4-number group: "1.0/2.0/3.0/0.5" + local _nums="${_line#*= }"; _nums="${_nums%% *}" + # Extract avg (second field) + local _a="${_nums#*/}"; _a="${_a%%/*}" + _PING_AVG="${_a%%.*}" + ;; + *packet\ loss*) + # "3 packets transmitted, 3 received, 0% packet loss" + local _p="${_line%%\%*}" + _p="${_p##* }" + _PING_LOSS="${_p//[!0-9]/}" + ;; + esac + done < "$1" + [ -n "$_PING_AVG" ] && return 0 || return 1 +} + +# Convert curl time_total (seconds) to milliseconds — sets _CURL_MS +_ir_curl_to_ms() { + _CURL_MS="" + local _ts="$1" + [ -z "$_ts" ] && return 1 + [ "$_ts" = "0.000000" ] && return 1 + local _w="${_ts%%.*}" _f="${_ts#*.}" + _f="${_f:0:3}" + while [ "${#_f}" -lt 3 ]; do _f="${_f}0"; done + _CURL_MS=$(( _w * 1000 + 10#${_f} )) + return 0 +} + +# Filter server list — $1=filter (all|city:X|asn:X), output to stdout +_ir_filter_servers() { + local _filter="${1:-all}" _s _ip _name _city _asn _aname _host + while IFS= read -r _s; do + [ -z "$_s" ] && continue + IFS='|' read -r _ip _name _city _asn _aname _host <<< "$_s" + case "$_filter" in + all) echo "$_s" ;; + city:*) [ "$_city" = "${_filter#city:}" ] && echo "$_s" ;; + asn:*) [ "$_asn" = "${_filter#asn:}" ] && echo "$_s" ;; + esac + done <<< "$_IR_TEST_SERVERS" +} + +# Quick Test — combined HTTPS + ICMP for all servers +_ir_quick_test() { + local _filter="${1:-all}" + local _tmpdir + _tmpdir=$(mktemp -d) || { echo " Failed to create temp directory"; read -n 1 -s -r -p " Press any key..." < /dev/tty || true; return 1; } + + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} QUICK TEST${NC} ${DIM}(HTTPS + ICMP combined)${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + + # Get filtered server list + local _test_list="" + _test_list=$(_ir_filter_servers "$_filter") + + local _total=0 _n_https=0 _n_icmp=0 _s + while IFS= read -r _s; do + [ -z "$_s" ] && continue + _total=$((_total+1)) + local _h="${_s##*|}" + [ -n "$_h" ] && _n_https=$((_n_https+1)) || _n_icmp=$((_n_icmp+1)) + done <<< "$_test_list" + + echo -e " ${DIM}Testing ${_total} servers (${_n_https} HTTPS + ${_n_icmp} ICMP)...${NC}" + echo "" + + # Launch parallel tests — HTTPS for services, ICMP for infra + local _ip _name _city _asn _aname _host + while IFS= read -r _s; do + [ -z "$_s" ] && continue + IFS='|' read -r _ip _name _city _asn _aname _host <<< "$_s" + if [ -n "$_host" ]; then + curl -o /dev/null -s -w '%{http_code} %{time_total}\n' --max-time 10 -k \ + "https://${_host}/favicon.ico" > "$_tmpdir/${_ip}.https" 2>/dev/null & + ping -c 1 -W 3 "$_ip" > "$_tmpdir/${_ip}.icmp" 2>&1 & + else + ping -c 1 -W 3 "$_ip" > "$_tmpdir/${_ip}.icmp" 2>&1 & + fi + done <<< "$_test_list" + wait + + # Display results sorted by city + local _sorted _current_city="" + _sorted=$(echo "$_test_list" | sort -t'|' -k3,3 -k2,2) + local _reachable=0 _total_lat=0 _min_lat=999999 _max_lat=0 + local _min_name="" _max_name="" + local _BARS="████████████████████" + local _EMPTY="░░░░░░░░░░░░░░░░░░░░" + + while IFS= read -r _s; do + [ -z "$_s" ] && continue + IFS='|' read -r _ip _name _city _asn _aname _host <<< "$_s" + + # City header + if [ "$_city" != "$_current_city" ]; then + [ -n "$_current_city" ] && echo "" + echo -e " ${CYAN}── ${_city} ─────────────────────────────────────────────────${NC}" + _current_city="$_city" + fi + + local _lat_str="---" _status="${RED}●${NC}" _lat_clr="" _method="" _lat_int=0 _got_result=false + local _https_lat=0 _icmp_lat=0 _has_https=false _has_icmp=false + + # Check HTTPS result (for services with hostnames) + if [ -n "$_host" ] && [ -f "$_tmpdir/${_ip}.https" ]; then + local _result + _result=$(cat "$_tmpdir/${_ip}.https" 2>/dev/null) + local _http_code="${_result%% *}" _time_sec="${_result##* }" + if [ -n "$_http_code" ] && [ "$_http_code" -gt 0 ] 2>/dev/null; then + if _ir_curl_to_ms "$_time_sec"; then + _https_lat="$_CURL_MS" + _has_https=true + fi + fi + fi + + # Check ICMP result + if [ -f "$_tmpdir/${_ip}.icmp" ]; then + if _ir_parse_ping "$_tmpdir/${_ip}.icmp"; then + _icmp_lat="${_PING_AVG:-0}" + _has_icmp=true + fi + fi + + # Pick the best (lowest) latency when both available + local _icmp_extra="" + if $_has_https && $_has_icmp; then + if [ "$_icmp_lat" -le "$_https_lat" ] 2>/dev/null; then + _lat_int="$_icmp_lat"; _method="ICMP" + _icmp_extra=" ${DIM}(https:${_https_lat}ms)${NC}" + else + _lat_int="$_https_lat"; _method="HTTPS" + _icmp_extra=" ${DIM}(icmp:${_icmp_lat}ms)${NC}" + fi + _got_result=true + elif $_has_https; then + _lat_int="$_https_lat"; _method="HTTPS" + _got_result=true + elif $_has_icmp; then + _lat_int="$_icmp_lat"; _method="ICMP" + _got_result=true + fi + $_got_result && _lat_str="${_lat_int}ms" + + if $_got_result; then + _reachable=$((_reachable + 1)) + _total_lat=$((_total_lat + _lat_int)) + [ "$_lat_int" -lt "$_min_lat" ] 2>/dev/null && { _min_lat="$_lat_int"; _min_name="$_name"; } + [ "$_lat_int" -gt "$_max_lat" ] 2>/dev/null && { _max_lat="$_lat_int"; _max_name="$_name"; } + if [ "$_lat_int" -lt 300 ] 2>/dev/null; then + _status="${GREEN}●${NC}"; _lat_clr="${GREEN}" + elif [ "$_lat_int" -lt 1000 ] 2>/dev/null; then + _status="${YELLOW}●${NC}"; _lat_clr="${YELLOW}" + else + _status="${RED}●${NC}"; _lat_clr="${RED}" + fi + printf " %b %-18s ${_lat_clr}%6s${NC} ${DIM}%-5s${NC} ${DIM}AS%-6s %s${NC}%b\n" \ + "$_status" "$_name" "$_lat_str" "$_method" "$_asn" "$_aname" "$_icmp_extra" + else + printf " %b %-18s ${RED}%6s${NC} ${DIM}%-5s${NC} ${DIM}AS%-6s %s${NC}\n" \ + "$_status" "$_name" "$_lat_str" "FAIL" "$_asn" "$_aname" + fi + done <<< "$_sorted" + + # Summary + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo "" + local _reach_pct=0 + [ "$_total" -gt 0 ] && _reach_pct=$(( (_reachable * 100) / _total )) + local _reach_clr="${GREEN}" + [ "$_reach_pct" -lt 70 ] && _reach_clr="${YELLOW}" + [ "$_reach_pct" -lt 40 ] && _reach_clr="${RED}" + local _rblen=$(( _reach_pct / 5 )) + [ "$_rblen" -gt 20 ] && _rblen=20 + local _relen=$(( 20 - _rblen )) + echo -e " Reachable: ${_reach_clr}${_reachable}/${_total}${NC} (${_reach_clr}${_reach_pct}%${NC}) ${_reach_clr}${_BARS:0:$_rblen}${NC}${DIM}${_EMPTY:0:$_relen}${NC}" + if [ "$_reachable" -gt 0 ]; then + local _avg_lat=$(( _total_lat / _reachable )) + echo -e " Avg Latency: ${BOLD}${_avg_lat}ms${NC}" + [ "$_min_lat" -lt 999999 ] && echo -e " Fastest: ${GREEN}${_min_lat}ms${NC} ${DIM}(${_min_name})${NC}" + [ "$_max_lat" -gt 0 ] && echo -e " Slowest: ${YELLOW}${_max_lat}ms${NC} ${DIM}(${_max_name})${NC}" + fi + echo "" + echo -e " ${DIM}HTTPS = service response via curl | ICMP = ping for infra IPs${NC}" + echo "" + rm -rf "$_tmpdir" + read -n 1 -s -r -p " Press any key to return..." < /dev/tty || true +} + +# Stability Test — 20 pings per server, packet loss, jitter, quality score +_ir_stability_test() { + local _filter="${1:-all}" + local _tmpdir + _tmpdir=$(mktemp -d) || { echo " Failed to create temp directory"; read -n 1 -s -r -p " Press any key..." < /dev/tty || true; return 1; } + + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} STABILITY TEST${NC} ${DIM}(20 pings — loss, jitter & quality)${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + + # Get filtered server list + local _test_list="" + _test_list=$(_ir_filter_servers "$_filter") + + local _total=0 _s + while IFS= read -r _s; do [ -n "$_s" ] && _total=$((_total+1)); done <<< "$_test_list" + + echo -e " ${DIM}Running stability test: 20 pings x ${_total} servers...${NC}" + echo -e " ${DIM}This takes 30-60 seconds. Please wait.${NC}" + echo "" + + # Launch parallel pings (20 count, 0.5s interval) + while IFS= read -r _s; do + [ -z "$_s" ] && continue + local _pip="${_s%%|*}" + ping -c 20 -W 3 -i 0.5 "$_pip" > "$_tmpdir/${_pip}" 2>&1 & + done <<< "$_test_list" + + # Progress dots + local _j=0 + while [ "$(jobs -r 2>/dev/null | wc -l)" -gt 0 ]; do + printf " ${DIM}.${NC}" + sleep 2 + _j=$((_j + 1)) + [ "$_j" -gt 30 ] && break + done + wait + echo "" + echo "" + + # Display results + local _sorted _current_city="" + _sorted=$(echo "$_test_list" | sort -t'|' -k3,3 -k2,2) + local _reachable=0 _total_loss=0 _total_jitter=0 + + printf " ${DIM}%-20s %7s %5s %7s %7s %7s %s${NC}\n" \ + "Server" "Avg" "Loss" "Min" "Max" "Jitter" "Gr" + echo -e " ${DIM}$(printf '%0.s-' {1..63})${NC}" + + while IFS= read -r _s; do + [ -z "$_s" ] && continue + IFS='|' read -r _ip _name _city _asn _aname _host <<< "$_s" + + # City header + if [ "$_city" != "$_current_city" ]; then + [ -n "$_current_city" ] && echo "" + echo -e " ${CYAN}-- ${_city} --${NC}" + _current_city="$_city" + fi + + local _avg="---" _loss="100" _min="---" _max="---" _jitter="---" _grade="F" _gclr="${RED}" + + if [ -f "$_tmpdir/${_ip}" ]; then + # Parse ping output for min/avg/max/mdev + local _stats_line _loss_line + # Parse rtt stats: "rtt min/avg/max/mdev = 1.0/2.0/3.0/0.5 ms" (3 slashes between 4 numbers) + _stats_line=$(sed -n 's|.*= \([0-9.]*\)/\([0-9.]*\)/\([0-9.]*\)/\([0-9.]*\) .*|\1/\2/\3/\4|p' "$_tmpdir/${_ip}" 2>/dev/null) + # BusyBox fallback: "round-trip min/avg/max = 1.0/2.0/3.0 ms" (3 values, no mdev) + [ -z "$_stats_line" ] && _stats_line=$(sed -n 's|.*= \([0-9.]*\)/\([0-9.]*\)/\([0-9.]*\) .*|\1/\2/\3/0|p' "$_tmpdir/${_ip}" 2>/dev/null) + _loss_line=$(sed -n 's|.* \([0-9]*\)% packet loss.*|\1|p' "$_tmpdir/${_ip}" 2>/dev/null) + + if [ -n "$_stats_line" ]; then + local _pmin="${_stats_line%%/*}" + local _rest="${_stats_line#*/}" + local _pavg="${_rest%%/*}" + _rest="${_rest#*/}" + local _pmax="${_rest%%/*}" + local _pmdev="${_rest#*/}" + + _min="${_pmin%%.*}" + _avg="${_pavg%%.*}" + _max="${_pmax%%.*}" + _jitter="${_pmdev%%.*}" + _loss="${_loss_line:-0}" + + _reachable=$((_reachable + 1)) + _total_loss=$((_total_loss + _loss)) + _total_jitter=$((_total_jitter + ${_jitter:-0})) + + # Quality grade based on loss + latency + jitter + # Latency: <300ms no penalty, 300-1000 mild, >1000 heavy + local _score=100 + _score=$((_score - (_loss * 5))) + if [ "${_avg}" -gt 1000 ] 2>/dev/null; then + _score=$((_score - 20 - ((_avg - 1000) / 50) )) + elif [ "${_avg}" -gt 300 ] 2>/dev/null; then + _score=$((_score - ((_avg - 300) / 70) )) + fi + _score=$((_score - (${_jitter:-0} * 2))) + [ "$_score" -lt 0 ] && _score=0 + + if [ "$_score" -ge 95 ]; then _grade="A+"; _gclr="${GREEN}" + elif [ "$_score" -ge 85 ]; then _grade="A"; _gclr="${GREEN}" + elif [ "$_score" -ge 75 ]; then _grade="B+"; _gclr="${GREEN}" + elif [ "$_score" -ge 65 ]; then _grade="B"; _gclr="${YELLOW}" + elif [ "$_score" -ge 50 ]; then _grade="C"; _gclr="${YELLOW}" + elif [ "$_score" -ge 35 ]; then _grade="D"; _gclr="${RED}" + else _grade="F"; _gclr="${RED}" + fi + + local _aclr="${GREEN}" + [ "${_avg}" -ge 200 ] 2>/dev/null && _aclr="${YELLOW}" + [ "${_avg}" -ge 500 ] 2>/dev/null && _aclr="${RED}" + + local _lclr="${GREEN}" + [ "${_loss}" -gt 0 ] 2>/dev/null && _lclr="${YELLOW}" + [ "${_loss}" -ge 20 ] 2>/dev/null && _lclr="${RED}" + + printf " %-20s ${_aclr}%7s${NC} ${_lclr}%5s${NC} %7s %7s %7s ${_gclr}%2s${NC}\n" \ + "$_name" "${_avg}ms" "${_loss}%" "${_min}ms" "${_max}ms" "${_jitter}ms" "$_grade" + else + _loss="${_loss_line:-100}" + printf " %-20s ${RED}%7s${NC} ${RED}%5s${NC} %7s %7s %7s ${RED}%2s${NC}\n" \ + "$_name" "---" "${_loss}%" "---" "---" "---" "F" + fi + else + printf " %-20s ${RED}%7s${NC} ${RED}%5s${NC} %7s %7s %7s ${RED}%2s${NC}\n" \ + "$_name" "---" "100%" "---" "---" "---" "F" + fi + done <<< "$_sorted" + + # Summary + echo "" + echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo "" + local _reach_pct=0 + [ "$_total" -gt 0 ] && _reach_pct=$(( (_reachable * 100) / _total )) + local _reach_clr="${GREEN}" + [ "$_reach_pct" -lt 70 ] && _reach_clr="${YELLOW}" + [ "$_reach_pct" -lt 40 ] && _reach_clr="${RED}" + echo -e " Reachable: ${_reach_clr}${_reachable}/${_total}${NC} (${_reach_clr}${_reach_pct}%${NC})" + if [ "$_reachable" -gt 0 ]; then + local _avg_loss=$(( _total_loss / _reachable )) + local _avg_jitter=$(( _total_jitter / _reachable )) + echo -e " Avg Loss: ${BOLD}${_avg_loss}%${NC}" + echo -e " Avg Jitter: ${BOLD}${_avg_jitter}ms${NC}" + fi + echo "" + echo -e " ${DIM}Grade: A+=excellent B=good C=fair D=poor F=fail${NC}" + echo -e " ${DIM}Score = 100 - (loss x 5) - (latency penalty) - (jitter x 2)${NC}" + echo "" + rm -rf "$_tmpdir" + read -n 1 -s -r -p " Press any key to return..." < /dev/tty || true +} + +# MTU Path Discovery — test path MTU to Iranian endpoints +_ir_mtu_test() { + local _tmpdir + _tmpdir=$(mktemp -d) || { echo " Failed to create temp directory"; read -n 1 -s -r -p " Press any key..." < /dev/tty || true; return 1; } + + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} MTU DISCOVERY TEST${NC} ${DIM}(Path MTU to Iranian destinations)${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + + # Targets: reliable Iranian servers across different networks + international baseline + local _MTU_TARGETS="178.22.122.100|Shecan DNS|Tehran|AS43754 +85.15.17.13|Shatel|Tehran|AS31549 +185.215.228.1|DadehNegar|Tehran|AS42337 +217.218.155.155|TIC DNS|Tehran|AS12880 +185.188.104.10|Digikala|Tehran|AS43211 +188.213.66.1|MobinNet|Tehran|AS47330 +185.143.233.2|ArvanCloud|Tehran|AS205585 +5.202.128.1|Pishgaman|Tehran|AS49100 +8.8.8.8|Google DNS|International|Global +1.1.1.1|Cloudflare|International|Global" + + echo -e " ${DIM}Discovering Path MTU to Iranian destinations...${NC}" + echo -e " ${DIM}(Binary search with Don't Fragment flag — takes ~15s)${NC}" + echo "" + + # Run MTU discovery for each target in parallel + local _target _tip + while IFS= read -r _target; do + [ -z "$_target" ] && continue + IFS='|' read -r _tip _ _ _ <<< "$_target" + ( + local _lo=576 _hi=1500 _best=0 _mid _psize + while [ "$_lo" -le "$_hi" ]; do + _mid=$(( (_lo + _hi) / 2 )) + _psize=$(( _mid - 28 )) + if ping -c 1 -W 2 -s "$_psize" -M do "$_tip" &>/dev/null; then + _best="$_mid" + _lo=$(( _mid + 1 )) + else + _hi=$(( _mid - 1 )) + fi + done + echo "$_best" > "$_tmpdir/${_tip}.mtu" + ) & + done <<< "$_MTU_TARGETS" + wait + + # Display results + printf " ${DIM}%-16s %-14s %-10s %6s %s${NC}\n" "Target" "Location" "Network" "MTU" "Status" + echo -e " ${DIM}$(printf '%.0s-' {1..62})${NC}" + + while IFS= read -r _target; do + [ -z "$_target" ] && continue + local _tip _tname _tloc _tasn _best + IFS='|' read -r _tip _tname _tloc _tasn <<< "$_target" + _best=0 + [ -f "$_tmpdir/${_tip}.mtu" ] && IFS= read -r _best < "$_tmpdir/${_tip}.mtu" + _best="${_best:-0}" + + if [ "$_best" -gt 0 ] 2>/dev/null; then + local _mtu_clr="${GREEN}" _mtu_status="OK" + [ "$_best" -lt 1400 ] 2>/dev/null && { _mtu_clr="${YELLOW}"; _mtu_status="Reduced"; } + [ "$_best" -lt 1200 ] 2>/dev/null && { _mtu_clr="${RED}"; _mtu_status="Low"; } + printf " %-16s %-14s ${DIM}%-10s${NC} ${_mtu_clr}%6s${NC} ${_mtu_clr}%s${NC}\n" "$_tname" "$_tloc" "$_tasn" "$_best" "$_mtu_status" + else + printf " %-16s %-14s ${DIM}%-10s${NC} ${RED}%6s${NC} ${RED}%s${NC}\n" "$_tname" "$_tloc" "$_tasn" "---" "Unreachable" + fi + done <<< "$_MTU_TARGETS" + + echo "" + echo -e " ${CYAN}── What This Means ──────────────────────────────────────────${NC}" + echo "" + echo -e " ${GREEN}1500${NC} ${DIM}Standard — no fragmentation, full speed${NC}" + echo -e " ${YELLOW}1400-1499${NC} ${DIM}Typical VPN/tunnel overhead${NC}" + echo -e " ${RED}< 1400${NC} ${DIM}May indicate DPI or restrictive network policies${NC}" + echo "" + echo -e " ${DIM}Path MTU = largest packet that can reach destination without${NC}" + echo -e " ${DIM}fragmentation. Lower values can reduce throughput.${NC}" + echo "" + rm -rf "$_tmpdir" + read -n 1 -s -r -p " Press any key to return..." < /dev/tty || true +} + +# City picker submenu +_ir_city_menu() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} TEST BY CITY${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + + # Collect unique cities with counts + local -A _city_cnt + local _s _city + while IFS= read -r _s; do + [ -z "$_s" ] && continue + IFS='|' read -r _ _ _city _ _ <<< "$_s" + _city_cnt[$_city]=$(( ${_city_cnt[$_city]:-0} + 1 )) + done <<< "$_IR_TEST_SERVERS" + + local _cities=() + while IFS= read -r _c; do + [ -n "$_c" ] && _cities+=("$_c") + done < <(printf '%s\n' "${!_city_cnt[@]}" | sort) + + local _i=1 _c + for _c in "${_cities[@]}"; do + printf " ${CYAN}%d.${NC} %-14s ${DIM}(%d servers)${NC}\n" "$_i" "$_c" "${_city_cnt[$_c]}" + _i=$((_i + 1)) + done + echo "" + echo -e " ${CYAN}[0]${NC} Back" + echo "" + + local _ch="" + read -p " Select city: " _ch < /dev/tty || true + _ch="${_ch//[!0-9]/}" + [ -z "$_ch" ] || [ "$_ch" = "0" ] && return + [ "$_ch" -gt "${#_cities[@]}" ] 2>/dev/null && return + local _sel="${_cities[$((_ch - 1))]}" + _ir_quick_test "city:$_sel" +} + +# ASN picker submenu +_ir_asn_menu() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} TEST BY ASN (Network Provider)${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + + # Collect unique ASNs with names and counts + local -A _asn_cnt _asn_names + local _s _asn _aname + while IFS= read -r _s; do + [ -z "$_s" ] && continue + IFS='|' read -r _ _ _ _asn _aname <<< "$_s" + _asn_cnt[$_asn]=$(( ${_asn_cnt[$_asn]:-0} + 1 )) + _asn_names[$_asn]="$_aname" + done <<< "$_IR_TEST_SERVERS" + + local _asns=() + while IFS= read -r _a; do + [ -n "$_a" ] && _asns+=("$_a") + done < <(printf '%s\n' "${!_asn_cnt[@]}" | sort -n) + + local _i=1 _a + for _a in "${_asns[@]}"; do + printf " ${CYAN}%2d.${NC} AS%-6s %-14s ${DIM}(%d servers)${NC}\n" "$_i" "$_a" "${_asn_names[$_a]}" "${_asn_cnt[$_a]}" + _i=$((_i + 1)) + done + echo "" + echo -e " ${CYAN}[0]${NC} Back" + echo "" + + local _ch="" + read -p " Select ASN: " _ch < /dev/tty || true + _ch="${_ch//[!0-9]/}" + [ -z "$_ch" ] || [ "$_ch" = "0" ] && return + [ "$_ch" -gt "${#_asns[@]}" ] 2>/dev/null && return + local _sel="${_asns[$((_ch - 1))]}" + _ir_quick_test "asn:$_sel" +} + +# Server picker for traceroute/mtr — sets _PICK_IP and _PICK_NAME +_ir_server_picker() { + local _label="$1" + echo -e " ${DIM}Select a server:${NC}" + echo "" + + local _items=() _s _ip _name _city _current_city="" + while IFS= read -r _s; do + [ -z "$_s" ] && continue + _items+=("$_s") + done < <(echo "$_IR_TEST_SERVERS" | sort -t'|' -k3,3 -k2,2) + + local _i=1 + for _s in "${_items[@]}"; do + IFS='|' read -r _ip _name _city _ _ <<< "$_s" + if [ "$_city" != "$_current_city" ]; then + [ -n "$_current_city" ] && echo "" + echo -e " ${CYAN}── ${_city} ──${NC}" + _current_city="$_city" + fi + printf " ${DIM}%2d.${NC} %-22s ${DIM}%s${NC}\n" "$_i" "$_name" "$_ip" + _i=$((_i + 1)) + done + echo "" + echo -e " ${CYAN}[0]${NC} Cancel" + echo "" + + local _ch="" + read -p " Enter number: " _ch < /dev/tty || true + _ch="${_ch//[!0-9]/}" + _PICK_IP="" _PICK_NAME="" + [ -z "$_ch" ] || [ "$_ch" = "0" ] && return 1 + [ "$_ch" -gt "${#_items[@]}" ] 2>/dev/null && return 1 + local _sel="${_items[$((_ch - 1))]}" + _PICK_IP="${_sel%%|*}" + local _tmp="${_sel#*|}"; _PICK_NAME="${_tmp%%|*}" + return 0 +} + +# Traceroute +_ir_traceroute_menu() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} TRACEROUTE${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + + if ! _ir_server_picker "traceroute"; then return; fi + + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} TRACEROUTE${NC} → ${_PICK_NAME} (${_PICK_IP})" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + + if command -v traceroute &>/dev/null; then + traceroute -m 25 -w 3 "$_PICK_IP" 2>&1 + else + echo -e " ${RED}traceroute not available.${NC}" + echo -e " ${DIM}Install: apt install traceroute${NC}" + fi + echo "" + read -n 1 -s -r -p " Press any key to return..." < /dev/tty || true +} + +# MTR analysis +_ir_mtr_menu() { + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} MTR ANALYSIS${NC} ${DIM}(combined traceroute + ping statistics)${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + + if ! _ir_server_picker "mtr"; then return; fi + + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} MTR ANALYSIS${NC} → ${_PICK_NAME} (${_PICK_IP})" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${DIM}Running 10 rounds of MTR... (this takes ~15 seconds)${NC}" + echo "" + + if command -v mtr &>/dev/null; then + mtr -r -c 10 -w "$_PICK_IP" 2>&1 + else + echo -e " ${RED}mtr not available.${NC}" + echo -e " ${DIM}Install: apt install mtr-tiny${NC}" + fi + echo "" + read -n 1 -s -r -p " Press any key to return..." < /dev/tty || true +} + +# Full report — pings all, summarizes by city & ASN +_ir_full_report() { + local _tmpdir + _tmpdir=$(mktemp -d) || { echo " Failed to create temp directory"; read -n 1 -s -r -p " Press any key..." < /dev/tty || true; return 1; } + + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} FULL CONNECTIVITY REPORT${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + # Count total + local _total=0 _s + while IFS= read -r _s; do [ -n "$_s" ] && _total=$((_total+1)); done <<< "$_IR_TEST_SERVERS" + + echo -e " ${DIM}Running comprehensive test (HTTPS + ICMP × ${_total} servers)...${NC}" + echo -e " ${DIM}This may take 15-30 seconds.${NC}" + echo "" + + # Launch all tests in parallel (HTTPS for services, ICMP for all) + local _pip _phost + while IFS= read -r _s; do + [ -z "$_s" ] && continue + IFS='|' read -r _pip _ _ _ _ _phost <<< "$_s" + ping -c 4 -W 3 "$_pip" > "$_tmpdir/${_pip}" 2>&1 & + if [ -n "$_phost" ]; then + curl -o /dev/null -s -w '%{http_code} %{time_total}\n' --max-time 10 -k \ + "https://${_phost}/favicon.ico" > "$_tmpdir/${_pip}.https" 2>/dev/null & + fi + done <<< "$_IR_TEST_SERVERS" + + # Progress dots + local _j=0 + while [ "$(jobs -r 2>/dev/null | wc -l)" -gt 0 ]; do + echo -ne " ${DIM}.${NC}" + sleep 1 + _j=$((_j + 1)) + [ "$_j" -gt 30 ] && break + done + wait + echo "" + + # Parse all results + local -A _city_reach _city_total _city_lat _asn_reach _asn_total _asn_lat _asn_names + local _reachable=0 _total_lat=0 _min_lat=999999 _max_lat=0 + local _min_name="" _max_name="" + local _ip _name _city _asn _aname _host _detail="" + local _BARS="████████████████████" + local _EMPTY="░░░░░░░░░░░░░░░░░░░░" + + while IFS= read -r _s; do + [ -z "$_s" ] && continue + IFS='|' read -r _ip _name _city _asn _aname _host <<< "$_s" + + _city_total[$_city]=$(( ${_city_total[$_city]:-0} + 1 )) + _asn_total[$_asn]=$(( ${_asn_total[$_asn]:-0} + 1 )) + _asn_names[$_asn]="$_aname" + + # Determine best latency: use lowest of HTTPS vs ICMP + local _lat_int=0 _got_result=false _method="" + local _fr_https_lat=0 _fr_icmp_lat=0 _fr_has_https=false _fr_has_icmp=false + # Check HTTPS + if [ -n "$_host" ] && [ -f "$_tmpdir/${_ip}.https" ]; then + local _hresult + _hresult=$(cat "$_tmpdir/${_ip}.https" 2>/dev/null) + local _hcode="${_hresult%% *}" _htime="${_hresult##* }" + if [ "$_hcode" -gt 0 ] 2>/dev/null && _ir_curl_to_ms "$_htime"; then + _fr_https_lat="$_CURL_MS" + _fr_has_https=true + fi + fi + # Check ICMP + if _ir_parse_ping "$_tmpdir/${_ip}" 2>/dev/null; then + _fr_icmp_lat="${_PING_AVG:-0}" + _fr_has_icmp=true + fi + # Pick lowest + if $_fr_has_https && $_fr_has_icmp; then + if [ "$_fr_icmp_lat" -le "$_fr_https_lat" ] 2>/dev/null; then + _lat_int="$_fr_icmp_lat"; _method="ICMP" + else + _lat_int="$_fr_https_lat"; _method="HTTPS" + fi + _got_result=true + elif $_fr_has_https; then + _lat_int="$_fr_https_lat"; _method="HTTPS"; _got_result=true + elif $_fr_has_icmp; then + _lat_int="$_fr_icmp_lat"; _method="ICMP"; _got_result=true + fi + # ICMP loss: from ping if available; if HTTPS reachable but ICMP blocked, don't penalize + local _ploss="100" + if _ir_parse_ping "$_tmpdir/${_ip}" 2>/dev/null; then + _ploss="${_PING_LOSS:-0}" + elif $_got_result; then + _ploss="0" # Reachable via HTTPS — don't penalize for ICMP block + fi + + if $_got_result; then + _reachable=$((_reachable + 1)) + _total_lat=$((_total_lat + _lat_int)) + _city_reach[$_city]=$(( ${_city_reach[$_city]:-0} + 1 )) + _city_lat[$_city]=$(( ${_city_lat[$_city]:-0} + _lat_int )) + _asn_reach[$_asn]=$(( ${_asn_reach[$_asn]:-0} + 1 )) + _asn_lat[$_asn]=$(( ${_asn_lat[$_asn]:-0} + _lat_int )) + [ "$_lat_int" -lt "$_min_lat" ] 2>/dev/null && { _min_lat="$_lat_int"; _min_name="$_name ($_city)"; } + [ "$_lat_int" -gt "$_max_lat" ] 2>/dev/null && { _max_lat="$_lat_int"; _max_name="$_name ($_city)"; } + local _sc="${GREEN}●${NC}" + [ "$_lat_int" -ge 500 ] 2>/dev/null && _sc="${RED}●${NC}" + [ "$_lat_int" -ge 200 ] 2>/dev/null && [ "$_lat_int" -lt 500 ] 2>/dev/null && _sc="${YELLOW}●${NC}" + # Quality grade — latency thresholds tuned for international testing + # <300ms = no penalty, 300-1000 = mild, 1000-3000 = moderate, >3000 = heavy + local _qs=100 + _qs=$((_qs - (_ploss * 5))) + if [ "$_lat_int" -gt 3000 ] 2>/dev/null; then + _qs=$((_qs - 60)) + elif [ "$_lat_int" -gt 1000 ] 2>/dev/null; then + _qs=$((_qs - 20 - ((_lat_int - 1000) / 50) )) + elif [ "$_lat_int" -gt 300 ] 2>/dev/null; then + _qs=$((_qs - ((_lat_int - 300) / 70) )) + fi + [ "$_qs" -lt 0 ] && _qs=0 + local _qg="F" _qc="${RED}" + if [ "$_qs" -ge 95 ]; then _qg="A+"; _qc="${GREEN}" + elif [ "$_qs" -ge 85 ]; then _qg="A"; _qc="${GREEN}" + elif [ "$_qs" -ge 75 ]; then _qg="B+"; _qc="${GREEN}" + elif [ "$_qs" -ge 65 ]; then _qg="B"; _qc="${YELLOW}" + elif [ "$_qs" -ge 50 ]; then _qg="C"; _qc="${YELLOW}" + elif [ "$_qs" -ge 35 ]; then _qg="D"; _qc="${RED}" + fi + _detail+="$(printf " %b %-18s %-12s %7s %5s ${_qc}%-2s${NC} ${DIM}%-5s${NC} AS%-6s" "$_sc" "$_name" "$_city" "${_lat_int}ms" "${_ploss}%" "$_qg" "$_method" "$_asn")"$'\n' + else + _detail+="$(printf " ${RED}●${NC} %-18s %-12s ${RED}%7s${NC} %5s ${RED}%-2s${NC} ${DIM}%-5s${NC} AS%-6s" "$_name" "$_city" "---" "100%" "F" "FAIL" "$_asn")"$'\n' + fi + done <<< "$_IR_TEST_SERVERS" + + # Display report + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} IRAN CONNECTIVITY REPORT${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${DIM}Date:$(date -u +" %Y-%m-%d %H:%M UTC" 2>/dev/null)${NC}" + echo -e " ${DIM}From: $(hostname 2>/dev/null || echo "unknown")${NC}" + echo "" + + # Overview + echo -e " ${CYAN}── Overview ──────────────────────────────────────────────────${NC}" + echo "" + local _reach_pct=0 + [ "$_total" -gt 0 ] && _reach_pct=$(( (_reachable * 100) / _total )) + local _reach_clr="${GREEN}" + [ "$_reach_pct" -lt 70 ] && _reach_clr="${YELLOW}" + [ "$_reach_pct" -lt 40 ] && _reach_clr="${RED}" + local _rblen=$(( _reach_pct / 5 )) + [ "$_rblen" -gt 20 ] && _rblen=20 + local _relen=$(( 20 - _rblen )) + echo -e " Reachable: ${_reach_clr}${_reachable}/${_total}${NC} ${_reach_clr}${_BARS:0:$_rblen}${NC}${DIM}${_EMPTY:0:$_relen}${NC} ${_reach_clr}${_reach_pct}%${NC}" + if [ "$_reachable" -gt 0 ]; then + local _avg_lat=$(( _total_lat / _reachable )) + echo -e " Avg Latency: ${BOLD}${_avg_lat}ms${NC}" + [ "$_min_lat" -lt 999999 ] && echo -e " Fastest: ${GREEN}${_min_lat}ms${NC} ${DIM}${_min_name}${NC}" + [ "$_max_lat" -gt 0 ] && echo -e " Slowest: ${YELLOW}${_max_lat}ms${NC} ${DIM}${_max_name}${NC}" + # Overall quality grade — weighted: reachability 50%, latency 50% + # Reachability: 98% = full marks, each % below costs 2 pts + # Latency: <300ms = full marks, scaled penalty above + local _oqs=100 + local _unreachable_pct=$(( ((_total - _reachable) * 100) / _total )) + _oqs=$((_oqs - (_unreachable_pct * 2))) + if [ "$_avg_lat" -gt 3000 ] 2>/dev/null; then + _oqs=$((_oqs - 50)) + elif [ "$_avg_lat" -gt 1000 ] 2>/dev/null; then + _oqs=$((_oqs - 15 - ((_avg_lat - 1000) / 60) )) + elif [ "$_avg_lat" -gt 300 ] 2>/dev/null; then + _oqs=$((_oqs - ((_avg_lat - 300) / 50) )) + fi + [ "$_oqs" -lt 0 ] && _oqs=0 + local _oqg="F" _oqc="${RED}" + if [ "$_oqs" -ge 95 ]; then _oqg="A+"; _oqc="${GREEN}" + elif [ "$_oqs" -ge 85 ]; then _oqg="A"; _oqc="${GREEN}" + elif [ "$_oqs" -ge 75 ]; then _oqg="B+"; _oqc="${GREEN}" + elif [ "$_oqs" -ge 65 ]; then _oqg="B"; _oqc="${YELLOW}" + elif [ "$_oqs" -ge 50 ]; then _oqg="C"; _oqc="${YELLOW}" + elif [ "$_oqs" -ge 35 ]; then _oqg="D"; _oqc="${RED}" + fi + echo -e " Quality: ${_oqc}${_oqg}${NC} ${DIM}(score: ${_oqs}/100)${NC}" + fi + echo "" + + # By City + echo -e " ${CYAN}── By City ───────────────────────────────────────────────────${NC}" + echo "" + local _c _cr _ct _cl _cp _cblen _celen _cclr _cavg + for _c in $(printf '%s\n' "${!_city_total[@]}" | sort); do + _cr="${_city_reach[$_c]:-0}" + _ct="${_city_total[$_c]}" + _cl="${_city_lat[$_c]:-0}" + _cp=0; [ "$_ct" -gt 0 ] && _cp=$(( (_cr * 100) / _ct )) + _cavg=0; [ "$_cr" -gt 0 ] && _cavg=$(( _cl / _cr )) + _cclr="${GREEN}" + [ "$_cp" -lt 70 ] && _cclr="${YELLOW}" + [ "$_cp" -lt 40 ] && _cclr="${RED}" + _cblen=$(( _cp / 5 )); [ "$_cblen" -gt 20 ] && _cblen=20 + _celen=$(( 20 - _cblen )) + printf " %-10s ${_cclr}%2d/%2d${NC} ${_cclr}%s${NC}${DIM}%s${NC} ${_cclr}%3d%%${NC}" "$_c" "$_cr" "$_ct" "${_BARS:0:$_cblen}" "${_EMPTY:0:$_celen}" "$_cp" + [ "$_cr" -gt 0 ] && printf " ${DIM}avg %dms${NC}" "$_cavg" + echo "" + done + echo "" + + # By ASN + echo -e " ${CYAN}── By ASN ────────────────────────────────────────────────────${NC}" + echo "" + local _a _ar _at _al _ap _aclr _aavg + for _a in $(printf '%s\n' "${!_asn_total[@]}" | sort -n); do + _ar="${_asn_reach[$_a]:-0}" + _at="${_asn_total[$_a]}" + _al="${_asn_lat[$_a]:-0}" + _ap=0; [ "$_at" -gt 0 ] && _ap=$(( (_ar * 100) / _at )) + _aavg=0; [ "$_ar" -gt 0 ] && _aavg=$(( _al / _ar )) + _aclr="${GREEN}" + [ "$_ap" -lt 70 ] && _aclr="${YELLOW}" + [ "$_ap" -lt 40 ] && _aclr="${RED}" + printf " AS%-6s %-12s ${_aclr}%d/%d${NC}" "$_a" "${_asn_names[$_a]:-?}" "$_ar" "$_at" + [ "$_ar" -gt 0 ] && printf " ${DIM}avg %dms${NC}" "$_aavg" + echo "" + done + echo "" + + # Individual results + echo -e " ${CYAN}── All Servers ───────────────────────────────────────────────${NC}" + echo "" + printf " ${DIM} %-18s %-12s %7s %5s %-2s %-5s %s${NC}\n" "Server" "City" "Ping" "Loss" "Gr" "Type" "ASN" + echo -n "$_detail" + echo "" + + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + rm -rf "$_tmpdir" + read -n 1 -s -r -p " Press any key to return..." < /dev/tty || true +} + +show_iran_test() { + _ir_test_install_deps + + local _exit=0 + while [ "$_exit" -eq 0 ]; do + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} 🔗 IRAN CONNECTIVITY TEST${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + + # Count unique cities and ASNs + local _n_cities _n_asns _n_total=0 + _n_cities=$(echo "$_IR_TEST_SERVERS" | grep -v '^$' | cut -d'|' -f3 | sort -u | wc -l) + _n_asns=$(echo "$_IR_TEST_SERVERS" | grep -v '^$' | cut -d'|' -f4 | sort -u | wc -l) + while IFS= read -r _s; do [ -n "$_s" ] && _n_total=$((_n_total+1)); done <<< "$_IR_TEST_SERVERS" + _n_cities="${_n_cities//[!0-9]/}"; _n_asns="${_n_asns//[!0-9]/}" + + echo -e " Test connectivity to ${BOLD}${_n_total}${NC} endpoints across Iran's major" + echo -e " networks, cities, and autonomous systems." + echo "" + echo -e " ${CYAN}┌──── CONNECTIVITY TESTS ────────────────────────────────────┐${NC}" + echo -e " ${CYAN}│${NC} ${CYAN}│${NC}" + echo -e " ${CYAN}│${NC} ${CYAN}a.${NC} ${BOLD}⚡ Quick Test${NC} ${DIM}HTTPS + ICMP combined${NC} ${CYAN}│${NC}" + echo -e " ${CYAN}│${NC} ${CYAN}b.${NC} ${BOLD}📊 Stability Test${NC} ${DIM}20 pings — loss & jitter${NC} ${CYAN}│${NC}" + echo -e " ${CYAN}│${NC} ${CYAN}c.${NC} ${BOLD}📍 Test by City${NC} ${DIM}Select a city to test${NC} ${CYAN}│${NC}" + echo -e " ${CYAN}│${NC} ${CYAN}d.${NC} ${BOLD}🌐 Test by ASN${NC} ${DIM}Select a network provider${NC} ${CYAN}│${NC}" + echo -e " ${CYAN}│${NC} ${CYAN}│${NC}" + echo -e " ${CYAN}├──── DIAGNOSTICS ───────────────────────────────────────────┤${NC}" + echo -e " ${CYAN}│${NC} ${CYAN}│${NC}" + echo -e " ${CYAN}│${NC} ${CYAN}e.${NC} ${BOLD}🔀 Traceroute${NC} ${DIM}Trace network path to server${NC} ${CYAN}│${NC}" + echo -e " ${CYAN}│${NC} ${CYAN}f.${NC} ${BOLD}📈 MTR Analysis${NC} ${DIM}Traceroute + ping statistics${NC} ${CYAN}│${NC}" + echo -e " ${CYAN}│${NC} ${CYAN}g.${NC} ${BOLD}📐 MTU Discovery${NC} ${DIM}Path MTU to Iranian servers${NC} ${CYAN}│${NC}" + echo -e " ${CYAN}│${NC} ${CYAN}│${NC}" + echo -e " ${CYAN}├──── REPORTS ───────────────────────────────────────────────┤${NC}" + echo -e " ${CYAN}│${NC} ${CYAN}│${NC}" + echo -e " ${CYAN}│${NC} ${CYAN}h.${NC} ${BOLD}📋 Full Report${NC} ${DIM}Complete test & quality scores${NC} ${CYAN}│${NC}" + echo -e " ${CYAN}│${NC} ${CYAN}│${NC}" + echo -e " ${CYAN}└────────────────────────────────────────────────────────────┘${NC}" + echo "" + echo -e " ${DIM}${_n_total} servers · ${_n_cities} cities · ${_n_asns} ASNs${NC}" + echo -e " ${CYAN}[i]${NC} Info ${CYAN}[0]${NC} Back" + echo "" + + printf " Enter choice: " + local _ch="" + read -n 1 -s -r _ch < /dev/tty || true + echo "" + case "$_ch" in + a|A) _ir_quick_test "all" ;; + b|B) _ir_stability_test "all" ;; + c|C) _ir_city_menu ;; + d|D) _ir_asn_menu ;; + e|E) _ir_traceroute_menu ;; + f|F) _ir_mtr_menu ;; + g|G) _ir_mtu_test ;; + h|H) _ir_full_report ;; + i|I) _info_iran_test ;; + *) _exit=1 ;; + esac + done +} + +show_psiphon_stats() { + local _ps_exit=0 _force_refresh=true + local _BARS="████████████████████" + local _cache_max=21600 # 6 hours in seconds + while [ "$_ps_exit" -eq 0 ]; do + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} PSIPHON NETWORK STATS${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + + local _cs_raw="" _ps_raw="" _ir_raw="" _cache_age=0 + + # Check if cache is fresh (< 6 hours) — skip network if so + # Use oldest cache file's timestamp so the age label reflects the stalest data + local _need_fetch=true + if ! $_force_refresh && [ -f "$INSTALL_DIR/.psi_cache_cs" ]; then + local _now _ts_cs _ts_ps _ts_oldest + _now=$(date +%s) + _ts_cs=$(stat -c %Y "$INSTALL_DIR/.psi_cache_cs" 2>/dev/null || echo 0) + _ts_ps=$(stat -c %Y "$INSTALL_DIR/.psi_cache_ps" 2>/dev/null || echo "$_ts_cs") + _ts_oldest=$(( _ts_cs < _ts_ps ? _ts_cs : _ts_ps )) + _cache_age=$(( _now - _ts_oldest )) + if [ "$_cache_age" -lt "$_cache_max" ] 2>/dev/null; then + _need_fetch=false + fi + fi + + if $_need_fetch; then + echo -e " ${DIM}Fetching live data from Psiphon...${NC}" + + # Fetch all APIs in parallel + local _tmpdir=$(mktemp -d /tmp/.psi_stats.XXXXXX 2>/dev/null || echo "/tmp/.psi_stats.$$") + mkdir -p "$_tmpdir" 2>/dev/null + curl -s --max-time 15 "https://stats.psianalytics.live/conduitStats" > "$_tmpdir/cs" 2>/dev/null & + curl -s --max-time 15 "https://stats.psianalytics.live/psiphonStats" > "$_tmpdir/ps" 2>/dev/null & + curl -s --max-time 15 "https://psix.ca/api/datasources/proxy/uid/000000001/query?db=psix&q=SELECT%20sum(%22rounded_count%22)%20FROM%20%22connections-extrapolate-daily%22%20WHERE%20%22client_region%22%20%3D%20%27IR%27%20AND%20time%20%3E%20now()%20-%2010d%20GROUP%20BY%20time(1d)%20fill(null)&epoch=s" > "$_tmpdir/ir" 2>/dev/null & + wait + _cs_raw=$(cat "$_tmpdir/cs" 2>/dev/null) + _ps_raw=$(cat "$_tmpdir/ps" 2>/dev/null) + _ir_raw=$(cat "$_tmpdir/ir" 2>/dev/null) + rm -rf "$_tmpdir" 2>/dev/null + + # Validate responses are complete JSON (reject HTML errors + truncated transfers) + [[ "$_cs_raw" != "{"*"}" ]] && _cs_raw="" + [[ "$_ps_raw" != "{"*"}" ]] && _ps_raw="" + [[ "$_ir_raw" != "{"*"}" ]] && _ir_raw="" + + # Save valid responses to cache; fall back to old cache for failed APIs + if [ -n "$_cs_raw" ] || [ -n "$_ps_raw" ]; then + [ -n "$_cs_raw" ] && printf '%s' "$_cs_raw" > "$INSTALL_DIR/.psi_cache_cs" 2>/dev/null + [ -n "$_ps_raw" ] && printf '%s' "$_ps_raw" > "$INSTALL_DIR/.psi_cache_ps" 2>/dev/null + [ -n "$_ir_raw" ] && printf '%s' "$_ir_raw" > "$INSTALL_DIR/.psi_cache_ir" 2>/dev/null + fi + # For any API that failed, try loading stale cache + [ -z "$_cs_raw" ] && _cs_raw=$(cat "$INSTALL_DIR/.psi_cache_cs" 2>/dev/null) + [ -z "$_ps_raw" ] && _ps_raw=$(cat "$INSTALL_DIR/.psi_cache_ps" 2>/dev/null) + [ -z "$_ir_raw" ] && _ir_raw=$(cat "$INSTALL_DIR/.psi_cache_ir" 2>/dev/null) + _cache_age=0 + else + echo -e " ${DIM}Loading cached data...${NC}" + _cs_raw=$(cat "$INSTALL_DIR/.psi_cache_cs" 2>/dev/null) + _ps_raw=$(cat "$INSTALL_DIR/.psi_cache_ps" 2>/dev/null) + _ir_raw=$(cat "$INSTALL_DIR/.psi_cache_ir" 2>/dev/null) + fi + _force_refresh=false + + # Check if we got data (from network or cache) + if [ -z "$_cs_raw" ] && [ -z "$_ps_raw" ]; then + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} PSIPHON NETWORK STATS${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e " ${RED}Could not fetch data from Psiphon servers.${NC}" + echo -e " ${DIM}Check your internet connection and try again.${NC}" + echo "" + echo -e " ${CYAN}[r]${NC} Retry ${CYAN}[0]${NC} Back" + echo "" + local _fc + read -n 1 -s -r _fc < /dev/tty || break + case "$_fc" in r|R) _force_refresh=true; continue ;; *) break ;; esac + fi + + # Cache age label + local _cache_label + if [ "$_cache_age" -lt 60 ] 2>/dev/null; then + _cache_label="just now" + elif [ "$_cache_age" -lt 3600 ] 2>/dev/null; then + _cache_label="$((_cache_age / 60))m ago" + else + _cache_label="$((_cache_age / 3600))h ago" + fi + + # Redraw header with update time + clear + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo -e "${BOLD} PSIPHON NETWORK STATS${NC} ${DIM}Updated: ${_cache_label}${NC}" + echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}" + echo "" + + # Exclude today's partial data — only show complete days + local _today _today_local + _today=$(date -u +%Y-%m-%d 2>/dev/null) + _today_local=$(date +%Y-%m-%d 2>/dev/null) + + # ============================================================ + # DATA EXTRACTION (all parsing before any display) + # ============================================================ + + # -- conduitStats data -- + local _split_cs="" _total_stations="" _today_stations="" + local _cdata="" _dates="" _regions="IR RU TM MM DE" + local _sr_data="" _chart_month="" + if [ -n "$_cs_raw" ]; then + _total_stations="${_cs_raw#*\"total_stations\":}" + _total_stations="${_total_stations%%[!0-9]*}" + + _split_cs=$(echo "$_cs_raw" | sed 's/},{/}\n{/g; s/\],"/]\n"/g') + _today_stations=$(echo "$_split_cs" | grep '"date"' | grep '"stations"' | grep -v "\"${_today}\"" | grep -v "\"${_today_local}\"" | tail -1 | sed -n 's/.*"stations":\([0-9]*\).*/\1/p') + + _cdata=$(echo "$_split_cs" | sed -n 's/.*"date":"\([0-9-]*\)".*"client_region":"\([A-Z]*\)".*"doc_count":\([0-9]*\).*/\1 \2 \3/p') + local _ld _lr _lc + while read -r _ld _lr _lc; do + [ -n "$_ld" ] && [ -n "$_lr" ] && printf -v "_cd${_ld//-/}${_lr}" '%s' "$_lc" + done <<< "$_cdata" + + _dates=$(printf '%s\n' "$_cdata" | cut -d' ' -f1 | sort -u | grep -v "^${_today}$" | grep -v "^${_today_local}$" | tail -7) + _sr_data=$(echo "$_split_cs" | grep '"region"' | grep '"stations"' | head -10 | sed -n 's/.*"region":"\([^"]*\)".*"stations":\([0-9]*\).*/\1 \2/p') + + # Get month name from first date in range + local _first_date + _first_date=$(echo "$_dates" | head -1) + [ -n "$_first_date" ] && { _psi_month "${_first_date:5:2}"; _chart_month="$_MN"; } + fi + + # -- psiphonStats data -- + local _split_ps="" _user_data="" _byte_data="" + if [ -n "$_ps_raw" ]; then + _split_ps=$(echo "$_ps_raw" | sed 's/},{/}\n{/g') + _user_data=$(echo "$_split_ps" | grep '"daily_unique_users"' | grep -v "\"${_today}\"" | grep -v "\"${_today_local}\"" | tail -7 | sed -n 's/.*"date":"\([^"]*\)".*"daily_unique_users":\([0-9.]*\).*/\1 \2/p') + _byte_data=$(echo "$_split_ps" | grep '"sum_of_bytes_value_TB"' | grep -v "\"${_today}\"" | grep -v "\"${_today_local}\"" | tail -7 | sed -n 's/.*"date":"\([^"]*\)".*"sum_of_bytes_value_TB":\([0-9.]*\).*/\1 \2/p') + fi + + # -- InfluxDB Iran data -- + local _irchart="" _ir_month="" + if [ -n "$_ir_raw" ]; then + local _today_epoch _local_epoch + _today_epoch=$(date -u -d "$_today" +%s 2>/dev/null || echo 0) + _local_epoch=$(date -d "$_today_local" +%s 2>/dev/null || echo "$_today_epoch") + [ "$_local_epoch" -lt "$_today_epoch" ] 2>/dev/null && _today_epoch="$_local_epoch" + local _ir_values + _ir_values=$(echo "$_ir_raw" | sed 's/\],\[/\n/g' | sed -n 's/[^0-9]*\([0-9]*\),\([0-9][0-9]*\).*/\1 \2/p' | while read -r _ets _ev; do + [ "$_ets" -lt "$_today_epoch" ] 2>/dev/null && echo "$_ets $_ev" + done) + if [ -n "$_ir_values" ]; then + local _ts _val _irday _ir_first_mm="" + while read -r _ts _val; do + [ -z "$_ts" ] || [ -z "$_val" ] && continue + _irday=$(date -u -d "@$_ts" +"%m %d" 2>/dev/null) + [ -z "$_irday" ] && continue + [ -z "$_ir_first_mm" ] && { _ir_first_mm="${_irday%% *}"; _psi_month "$_ir_first_mm"; _ir_month="$_MN"; } + _irchart+="${_val} ${_irday##* }"$'\n' + done <<< "$_ir_values" + fi + fi + + # ============================================================ + # DISPLAY (ordered: Iran focus first, then global) + # ============================================================ + + # === CONDUIT STATIONS (header) === + if [ -n "$_cs_raw" ]; then + _psi_fmt_num "${_today_stations:-0}"; local _factive="$_FN" + _psi_fmt_num "${_total_stations:-0}"; local _ftotal="$_FN" + echo -e " ${BOLD}Conduit Stations:${NC} ${_factive} active | ${_ftotal} total" + echo "" + fi + + # === 1. IRAN DAILY CONNECTIONS (vertical bar chart) === + if [ -n "$_dates" ]; then + echo -e " ${CYAN}── Iran Daily Connections ──────────────────────────────────${NC}" + echo "" + local _ircn_chart="" _d _cnt + for _d in $_dates; do + local _vn="_cd${_d//-/}IR"; _cnt="${!_vn:-0}" + _ircn_chart+="${_cnt} ${_d:8:2}"$'\n' + done + _psi_vchart "${CYAN}" "$_ircn_chart" "$_chart_month" + echo "" + fi + + # === 2. DAILY UNIQUE USERS FROM IRAN (vertical bar chart) === + if [ -n "$_irchart" ]; then + echo -e " ${CYAN}── Daily Unique Users from Iran ─────────────────────────────${NC}" + echo -e " ${DIM}Source: psix.ca (Psiphon regional metrics)${NC}" + echo "" + _psi_vchart "${GREEN}" "$_irchart" "$_ir_month" + echo "" + fi + + # === 3. DAILY PSIPHON USERS (vertical bar chart) === + if [ -n "$_user_data" ]; then + echo -e " ${CYAN}── Daily Psiphon Users (last 7 days) ───────────────────────${NC}" + echo "" + local _uchart="" _ud _uc + while read -r _ud _uc; do + [ -z "$_ud" ] && continue + _uc="${_uc%%.*}" + _uchart+="${_uc:-0} ${_ud:8:2}"$'\n' + done <<< "$_user_data" + _psi_vchart "${CYAN}" "$_uchart" "$_chart_month" + echo "" + fi + + # === 4. DAILY CONNECTIONS BY REGION (table) === + if [ -n "$_dates" ]; then + echo -e " ${CYAN}── Daily Connections by Region (last 7 days) ──────────────${NC}" + echo "" + printf " ${DIM}%-12s" "Date" + local _r + for _r in $_regions; do + _psi_country_name "$_r"; printf "%12s" "$_CN" + done + printf "${NC}\n" + for _d in $_dates; do + _psi_month "${_d:5:2}" + printf " %-12s" "$_MN ${_d:8:2}" + for _r in $_regions; do + local _vn="_cd${_d//-/}${_r}"; _cnt="${!_vn:-0}" + _psi_fmt_num "$_cnt"; printf "%12s" "$_FN" + done + printf "\n" + done + echo "" + + # TOP STATION REGIONS (horizontal bar chart) + echo -e " ${CYAN}── Top Station Regions ─────────────────────────────────────${NC}" + echo "" + local _sr_max=1 _sr_first=true _code _count + while read -r _code _count; do + [ -z "$_code" ] && continue + if $_sr_first; then _sr_max="${_count:-1}"; _sr_first=false; fi + [ "${_sr_max:-1}" -eq 0 ] 2>/dev/null && _sr_max=1 + local _pct=$(( (${_count:-0} * 100) / _sr_max )) + local _blen=$(( _pct / 5 )) + [ "$_blen" -lt 1 ] && _blen=1 + [ "$_blen" -gt 20 ] && _blen=20 + _psi_country_name "$_code" + _psi_fmt_num "${_count:-0}" + printf " %-16s %8s ${GREEN}%-20s${NC}\n" "$_CN" "$_FN" "${_BARS:0:$_blen}" + done <<< "$_sr_data" + echo "" + fi + + # === 5. DAILY DATA TRANSFERRED === + if [ -n "$_byte_data" ]; then + echo -e " ${CYAN}── Daily Data Transferred (last 7 days) ────────────────────${NC}" + echo "" + local _bd _btb + while read -r _bd _btb; do + [ -z "$_bd" ] && continue + _btb="${_btb%%.*}" + _psi_month "${_bd:5:2}" + printf " %-8s %8s TB\n" "$_MN ${_bd:8:2}" "${_btb:-0}" + done <<< "$_byte_data" + echo "" + fi + + echo -e " ${CYAN}[r]${NC} Refresh ${CYAN}[i]${NC} Info ${CYAN}[0]${NC} Back ${DIM}(auto-refresh every 6h)${NC}" + echo "" + local _psc + read -n 1 -s -r _psc < /dev/tty || break + case "$_psc" in + r|R) _force_refresh=true; continue ;; + i|I) _info_psiphon_stats; continue ;; + *) _ps_exit=1 ;; + esac + done +} + #═══════════════════════════════════════════════════════════════════════ # Multi-Server Dashboard #═══════════════════════════════════════════════════════════════════════ @@ -9160,6 +12617,7 @@ load_servers() { SERVER_COUNT=0 local conf="$INSTALL_DIR/servers.conf" [ -f "$conf" ] || return + chmod 600 "$conf" 2>/dev/null || true while IFS='|' read -r _l _c _a _rest || [ -n "$_l" ]; do [[ "$_l" =~ ^#.*$ ]] && continue [ -z "$_l" ] || [ -z "$_c" ] && continue @@ -9213,6 +12671,7 @@ _creds_key() { return 1 fi fi + chmod 600 "$keyfile" 2>/dev/null || true echo "$keyfile" } @@ -9255,6 +12714,7 @@ _load_cred() { local label="$1" local credsfile="$INSTALL_DIR/servers.creds" [ -f "$credsfile" ] || return 1 + chmod 600 "$credsfile" 2>/dev/null || true local encrypted encrypted=$(grep "^${label}|" "$credsfile" 2>/dev/null | head -1 | cut -d'|' -f2-) [ -z "$encrypted" ] && return 1 @@ -9644,6 +13104,10 @@ add_server_interactive() { fi fi + # Ensure trailing newline before appending + if [ -s "$INSTALL_DIR/servers.conf" ]; then + [ "$(tail -c 1 "$INSTALL_DIR/servers.conf" 2>/dev/null | wc -l)" -eq 0 ] && echo "" >> "$INSTALL_DIR/servers.conf" + fi echo "${label}|${conn}|${auth_type}" >> "$INSTALL_DIR/servers.conf" chmod 600 "$INSTALL_DIR/servers.conf" 2>/dev/null || true echo "" @@ -10528,7 +13992,60 @@ _server_actions() { 3) remote_cmd="conduit start" ;; 4) remote_cmd="conduit update" ;; 5) remote_cmd="conduit health" ;; - 6) remote_cmd="conduit logs" ;; + 6) + # Logs need special handling: fetch container list remotely, pick locally + echo "" + echo -e " ${DIM}Fetching container list from ${label}...${NC}" + local _clist + _clist=$(ssh_cmd "$label" "docker ps -a --filter name=conduit --format '{{.Names}} {{.Status}}'" 2>/dev/null) + if [ -z "$_clist" ]; then + echo -e " ${RED}Could not fetch container list.${NC}" + echo "" + echo -e "${CYAN}──────────────────────────────────────────────────────────────${NC}" + read -n 1 -s -r -p " Press any key to return to dashboard..." < /dev/tty || true + echo -ne "\033[?25l"; clear; return + fi + # Parse containers into arrays (sorted by name) + local -a _cnames=() _cstates=() + local _cl _cn _cs + while read -r _cl; do + [ -z "$_cl" ] && continue + _cn="${_cl%% *}" + _cs="${_cl#* }" + _cnames+=("$_cn") + if echo "$_cs" | grep -qi "up"; then + _cstates+=("${GREEN}Running${NC}") + else + _cstates+=("${RED}Stopped${NC}") + fi + done <<< "$(echo "$_clist" | sort)" + local _ccnt=${#_cnames[@]} + if [ "$_ccnt" -eq 0 ]; then + echo -e " ${RED}No conduit containers found.${NC}" + echo "" + echo -e "${CYAN}──────────────────────────────────────────────────────────────${NC}" + read -n 1 -s -r -p " Press any key to return to dashboard..." < /dev/tty || true + echo -ne "\033[?25l"; clear; return + fi + local _target="${_cnames[0]}" + if [ "$_ccnt" -gt 1 ]; then + echo "" + echo -e " ${CYAN}Select container to view logs:${NC}" + echo "" + local _ci + for (( _ci=0; _ci<_ccnt; _ci++ )); do + echo -e " $((_ci + 1)). ${_cnames[$_ci]} [${_cstates[$_ci]}]" + done + echo "" + local _sel + read -p " Select (1-${_ccnt}): " _sel < /dev/tty || { echo -ne "\033[?25l"; clear; return; } + if ! [[ "$_sel" =~ ^[0-9]+$ ]] || [ "$_sel" -lt 1 ] || [ "$_sel" -gt "$_ccnt" ]; then + echo -e " ${RED}Invalid selection.${NC}"; sleep 1; echo -ne "\033[?25l"; clear; return + fi + _target="${_cnames[$((_sel - 1))]}" + fi + remote_cmd="docker logs --tail 50 $_target" + ;; 7) remote_cmd="conduit status" ;; b|B|"") echo -ne "\033[?25l"; clear; return ;; *) echo -e "${RED} Invalid choice.${NC}"; sleep 1; echo -ne "\033[?25l"; clear; return ;; @@ -10669,6 +14186,9 @@ show_help() { echo " servers List configured remote servers" echo " snowflake Manage Snowflake proxy (status|start|stop|restart)" echo " mtproto Manage MTProto proxy (status|start|stop|restart|link)" + echo " network-stats Show Psiphon network statistics" + echo " iran-status Iran connectivity status (IODA, OONI)" + echo " iran-test Iran connectivity test (ping, traceroute, MTR)" echo " uninstall Remove everything (container, data, service)" echo " menu Open interactive menu (default)" echo " version Show version information" @@ -11287,6 +14807,9 @@ case "${1:-menu}" in regen-tracker) setup_tracker_service 2>/dev/null ;; regen-telegram) [ "${TELEGRAM_ENABLED:-false}" = "true" ] && setup_telegram_service 2>/dev/null ;; dashboard) show_multi_dashboard ;; + network-stats) show_psiphon_stats ;; + iran-status) show_iran_connectivity ;; + iran-test) show_iran_test ;; add-server|deploy) add_server_interactive ;; edit-server) edit_server_interactive ;; remove-server) remove_server_interactive ;; @@ -11331,7 +14854,8 @@ case "${1:-menu}" in *) echo "Usage: conduit mtproto [status|start|stop|restart|link|remove]" ;; esac ;; - menu|*) [ -t 0 ] || { show_help; exit 0; }; show_menu ;; + menu) [ -t 0 ] || { show_help; exit 0; }; show_menu ;; + *) echo "Unknown command: $1"; echo "Run 'conduit help' for usage."; exit 1 ;; esac MANAGEMENT @@ -11691,7 +15215,7 @@ SVCEOF fi } # -# REACHED END OF SCRIPT - VERSION 1.3.1 +# REACHED END OF SCRIPT - VERSION 1.3.3 # ############################################################################### main "$@" diff --git a/screenshots/conduit-info.png b/screenshots/conduit-info.png new file mode 100644 index 0000000000000000000000000000000000000000..ea69dbab9ddd032237916179cdee4ec15d39cda2 GIT binary patch literal 60588 zcmd3Oc{r8b`|mD7MU;66Q7BVn%sf-ZN||M*%$YKVO6Ei;nN?CUXP((IkC``_=Q*>@ zxgWjX_x#Se&iU_muIudU9oY7Mp0(CKKBY#S5+W7Lvsd&LJ=t`%HBbta75r= zJ_0;==fhLcJ^0^=CwCO2QQzC>=HM4x3n>*T6e=hD?19lK`2DoKqV^LM>VgyU?}-s} z1~(LHQA$Zx>YkgyBF4v!v@f3fP_P=0V@QbLC9cUSV;M3*Aufpvmk0g&O?Bf0tV$n$ zh!%AzT6WQ=t5E6tV-Tm8>s;ALv_4W3ZO~h8OFN3|Q;XM9?m?Ryz0Vvh-K9ms$p2F4 zWZdf@l-xtV&<5NOt5}@)?spN^mv>`0MzUr){l#WlET>zjZzKv!nCsoT)#OZa9(mQj z8wxr5>i9K&!v7)@@(Q|5=yLoH8y8RiCFGryqPm9xe?N5LzwJX^MNv^v3+NX$*rOg} zJ=x<|>g1|VBR^NliEOif?$`Bd5|7YYlKNkN^ zEL78a;Q!s&|K}>C(l359D5v?XmPo&vy7|=*dyC8Gw=cf*r%Z!#9j>z$`{)(Phq?-3 zbP;naWgF+3nwvuhQtlfVgt?A9wfI?hG#zJ$_tuvr!!v(sV05NcaFnp===dtMiatX= zGx4sg@Y@-R;QFF7$n)xaO||)O=3sYYc6L@$K>=TUZY(Fxpl0lw8t#OZke4l{_k>Orf%<4yOuhU2C z+(#!-LQkec^tRyl#-bq8yn&G5J+t9YYs?2b4HEMA?^E2J9~YVT>c3R*jWYi;;~uy3(Qxm=HI+|^PxaoK-m@3`XF-Dvlv5fYFOP@~gc<^T9`5>4O*0>s_HrK zg9(P_DdTCOrA3QQ_w`2BHL#+2ahywHs`aRm_SvC2F!7WiK)Cpx;tx@0 z7ni0SskOR($3Im##J}++c6@ng|L$k%jp}oJq~w#6lT?vRTLBUWCs3<}KKq3w+9Su$ zIY;W~p#6v=Mq#{sdj#jCeu?bE>5bjV=6gI{78+kkyz&rzXC8nZ%ga zH|{(sIpGV2gWvc&v#H^*H`W#mk95L#&YRc_+ZHaHrAG9ZJ}Sb zeO7k%$M;HdHU(*i;_NB{mxc;y^AtWLA|_;+7V4gT!)A~Vqjm0itTH1V4pBvT&*(wx zXi`qjc`*4B9u|q+Mz!omzpj~Vy@K}-h>)$!$j*ND?k8m_Sla~eJu4WF1UM_V)oOg1 ziXJB+xRtIC28X#-4VegE7y4sbnw}unWhCY>(JaW9{}Tl)g|7cU3`GCang1L2LT@W6 z72E2u4Iim-qK~(xEZ?njM=^R6Of;zf8itNNqb%S3oc|iH=<<%=CKC}dXXX7j4Dmf| zK8HN=^PO7t|Hi9-@A%&rX+smQ8%e))xD*JwpgxM}w5AghKZm!MH{QCOcJ1gay@%rF>mC|3PrlyQHZjfHR zdKI0yA_Ed}N_oiFp@Z(xv&UJsLjYLO%|IUS}G?9{*$BX7R3>(O^V7_|wG#C*(nLm#74z(#kbGec{3d`@KI_ zWqb2qEgwCSzI&I{d%JWrxwMql#>NKyYaFd5Vu%=63Dsf;=Sp25DO!$a0j8oLEq(H) zh{%{rsl)EN*}LiO{Tz?&eG9%CBC*OYlr=u&_;2cIuC* z-QAHV7ZpWDC+2?7cA^@eLH5z3Yi;o&0b(9ozrl^y!b*piE|=W?F=(kP%FD}p-EKtm z&*tV>X5mOpvP?k7$Vgb8MZ0nDH*FY`kjECsJkE&6aW1A zMJ89>^X0DdzQnzTA;aC^$3L}3 z#y#NWKd)Xi!#=pD1bcDq@jYFax~SsXO==}r`jXE}DRH{e(ta$Ilie^PA49lcIaGscw@I3cu}zq(^WSWSq3Sm-oME=Y3AYTg?0?RYJA`IijDR7GV1#MVe_P>rZP`9 z2t`PzK~#mzGZ?ZS;b|sFUj^cb&IQ!QiZR`e=8#fVRqb#~vbX!Bq!yxm9y4G$Np(~~ zxQUcfFGt|gIf}!|FCTH9S8ELLOJTz~K6$!t|KRl4huPZ4o zE-snc#<(UfyGrE`rhWcwa(J+do-}&0Ij=dvbg}c)wP6Qw2A_kR17T)n97qF8{#eTC zB-GjzZO_bhrp_)b$iN1p_ud(ME%n0X9aWtK7_)xIO`k*0%a<>MU$Rr@^zWq4+Nzei zbt{N4DBxDwaYPv>wJ^CMIPZLt zwA1QBEC&bDzZ;YXY3G?=5*DV04`pj{I0hN6IqAk3w&c1rTy&MxAS;F_@B}O-w53IP zx18G7>REk=BZ25ZTT4sbpSf=58(&W&Tc^Ff0df8B-d!zZ4=aQ~g@2Cj`uCUY557Ny zO^<|;`}d=VKY#c@r&sQ-`GXCHbvH)AdSA_Fj}$x{`~!Kpe{&2sILpWV%{L&-pQYfa zf_q=LXrqg5HNVWlg1B|?B4~Ki$&7z^pY*Dxro)g;q0xNL7jUj}aEIk#F(?P%b~O-u ze5+I{e~LWr<PXFuFO08Gf;K7sW79>#dfRoZIb36a#%NO`Y*RKG@_81b| zzhM9!9Z#~gIN%R<`DbgZ##(@xpPwA|wWW;>k$Z$u8sewI8<1^b^-4 zAENe#>?$wjs|5xI#$Gq_YuWDAwQJ;h46f?*>C;l&&y`_#nWTY=&E2NFjb8k5t-NgT z)|=)%_OJGY`4Tc83kt|Rwic^l(w!Jgrid$qts?s|Kd#E5C3z^MJuAb6D(S;5)O{&! z9m|rNMpw2cs(f)ENXvr8Ax%*jl?j*a7*Q+hh7rID}!&dQ6&ZsCWvoPYZQtx-_ zEaHmeMO^%P>E7XUndbXNbWKY z#n>VjCzIo0spmNF_F^MBSx_BAS;w!gp<$$aJT&aX2HV2a+hU zC?i0{-mnPcQEF;w!A0$0y-kpn>72zEv9hvK*CYp*r~3Jc^03hK;dPY!vFy%zJ&jGWJu5RepkRo`9e0+RAd9D-` z6tHn{^i1)n;ypaLSe1lMvur4P#TE4S?OUU8S4cD?8W3nEBjcJ0#TNi-Ha9mNU3Ick23eF)rQiQbZf0gyLYqS@aiCt9Kt+4Wma#tcNxuHs0uuwst4``y)m&V; zqpto8yl>UQW{oLt^_cy0Lbng9tU?wky$ zJ(1XsUpYz~T<^EO?ufYwiBi-)rn?&lQnK;!ac{flec$zio0@I`qy&!-9|q)I$pFzV z{o6Ofl7Z!L0?DDlL8oTstL>Iyf;!-5BZw7p^YTI)?-Xq^$dnyn-_AhU6p@%n{Ph>j zy`%OI!l})-Vb{w9SF4gO7the6s&>{U)_(gFBe?()SfGMyd3PgpAfRp{Tq106PzPfH z6(7J#Lrb}jF?*W}8ag^bDJe{gg9T>^a7p}%uHJ}im3(OZynQB8-~T!L1KTn|wmXA7 z+^}+})%9lX0REBsM+L?(5w>gBq^+#3!m^-#Lr&W>McVK+BSUngtLqMAICvQuHDmUK zZYH8V85tQ)4N-A%?Au>qo&=(Eean$rpY!v{V1eu2^FN*>D#_tz5)sjb2tM?~XsYS0 zW4V5*OZCjgDU5XhlkFbXyYjo{<*xORX}8)dB?Uoyu^&E!K-$mP(ZsBymw)2PWmuge zSRD)SARH8D0b^`>%WmdH!C)ek~o zS^>gOrWrXoTVwgh_w2}84~g$3=zu38e%cDot8>*ToAkv+5f>`Txsn1-{Sq=m?EHg> zs3_AG3jWXCP=qJ%KQGC-FhMJQiY>)i4wq-pi~#ongXiiAPjLo_VH|cX@+Nw3XSZB# zjJusZbH)!XGdVMZbLr&Eh|B1Bf{!0R+6&Q@Gz#4!T#0oo#c2JoerGEt^+BXlzbn1+ zi5YAGUESc9FY)f(zYkmH1z{|nZo(Ly-R1nvyXu;nf-*yaq^y(e5xqXC_S+J}>(-AR z`87=VHkwLnYg5zE(5M?45`XR%e%OJ)D>D9I&rmlV2YBOwOdH5}5C<#A;}2UK!>2c(L8+L!foGGE1a2 z5t(mV&Wj5?S_#I6OD-bc?z8LY=-2}bVrp*ABq-Py>s9w$H-SL8DaRY@UZlq*eAo!Z zd~WU?mv*GK9jkuGdJ^2=PH$nwiw1fRLM0`o{!&+NaqOSFCIS#cME4i-5O^&_sa92V z>fGiZ9Vh%QJnnG|9+u=UUrqxj5IymlB$nPYo$!y}PfN@2k0m8HCs{x6aHQ6c*`s{d zt_-fxA&H;)DZU2wHkG0>gDmUwWSGt~@H9#^>vf(6QE+Iuo=7Sze9#xa=1(mCT0%kR zC>7l2nby|U^zYxJIpvss<_uUHwQnI1XasF{br{4|6BFk7g@yg{Mygxwq8o$>?(y>(}Z&_WC6q*wS3gXW4QFsL^k4rr+smjk|r`>xa;HX z&hBo1aOxyMDU5=Glu*0WLikyoj8q#Rut=1H-RV$p{@3s@VR!=$s=vsA8L}7+Lql$S z^zk|U{W&K1_cUMB8&}`vF2CGvBO_CrgyzaG zC@>oOVI%pwvBXU+RA_n7`;#60xxo^SSMI~3-*i(v<=*x5^_fhdLvzhoB_tS#h=|r{ zI_T}Zy(^a89^*`S*R0i?GMoL<8-OP0m?9Uj?q{@X%e>Fd zqVgU$ruoJE{G)dY8e|y$j?pz8n4PVF3h&7oEnFQS1d6yaE0<`SZ@ixfjj~+3Lnfzs zozaiBQ`&OzKBetHbL{T!HoF}KIKBb59@m5Zl~rKsQf5Q`g070mM1ODvD0G}5;JnN-3zGb#bk;s(B?Oqc8nDZdV43-)rKQ5J zR7mP|K9mmcFHcAoBk$#R68Si6?5cm+%+eepMt*1BYkgQ|dYvt^v`-_k^tr#LxeayLpyuss=b0&qceAso zZ%_DOk+rf4=d2C-9~@hr&;{>$)QKj4nWD^yahFnn8$*My-WrRtFfzJ?*rb-0rE<_& zhzRzj7)YG>S&)kp6~_|5CJ=#e3lzu{(HPkFF{*WwWs;6QKs(@YUD)|oEVC!1aqzuM z%_;C2&DZ@ed3ESjFbuHl`uSg9LzQ@JIASVO*wWL}C1qs%5BBdG8iof21$l>C6otDM z6*6$G38Ht3wReF(tq+0?2pMX&!-RalwV;l8nE^LoD~?Z|XlQE-v)E0R?)|AGX6a8} zMYvDM7qyD)lXEI|Pn}Zhd1Tne7aG72*v9Y4}y+?p^=IMeB)cwccg5 zqQ4_BuvUrGhpg5Z`Rcs_EB?C9-%i79o(K|!)-p$tYHM9m|z z>11G#P}T`S7(IF3;ZK#4s7vO#gay{A+!ceTsH5xNyU*^baaX1jceo5cxft-{i0o)R zIB`BYAoa%&3YaGBiEhKg zdML@;x6dYcEDJ+%fWk)kC@Gx=Wd2-m{Yfa&x1qF$*rhL?bHtIf{0A{eYG(?%dLY2JU6CLr} zu~=PSKU4SRr9pr)3nS)TRx3)m>XQ@Jw@_c3VM%dHrI;{_gr|6rn?p4Sc{+eh{ncwz?x*=G1gc_!$aQY-CCH?-iA5O5Kn}(1d+xxJqz@G3H-;gh@z0@5|!FU(-HLI6m zw}yNrB~!_l*O;32sI9!HGS@FLrSy~Jaf*yvZGYD<^(!d~jmjC$#X<4&^Y<4&`D|O9 zk)f4i{9^c}+ZlEphPu`t-E&cq@|KC;2A5o{hl}7jBcb#yCoiB~{rOg;kPpCyA?0h6 za=LA8WmS#j5!2J=Y(Y%AB6T+hv7Y0BtTh$84Cxjl|`L5jvGc^tLN5)Y``!KjK*HfyU-$fBx&1Zh%0eCu4cWerxYi z`|RcNJiWK;DUMNjQ3P4N@_RiWYSPUn_N-Z3Tm$#HD=ObBwMv|>qJYEH=-d33nMq_< zwuXmdWMx(061?esP^8z+5Ic4n1qG_v&(j=+6`r!@?%=R%p(sG108K9Bp{7Ewhur_R zq?YC>p7_04!)ITje~%&z)&%fkBPg13-+oR?LP4Pn1sHnKpF-6u7_F$!O@Mpx)TvXb zXI}eT)RE43H%Al~W**MhDjwTxSnOHE^H&^US8z}Uo@@27UKa$dTt#e;mhC24Hx+!Y zn^S9|zhA+g7mOLC#mBX!mxfXW_oV*okd+aV8#B~)midE2L(Y{k(a}(o{fxr^=HMnu z55^9oN(Mj$#sj|WCvA$=&)c_dP3{NRSq$Wwp{;M$Y93?ef%l4zC&E=Z8lI_JXbdG< z{|_5lPv3Xw5Pgo+^D16v`xN!KQQ4NAOaT9+fX9JLA~_aVNST3MhtNC4Fu|^4EBtb7 zh2(du!)7aOc;971$@dx~VqCw|Eryn>9fzHOmP?%nCyx|II5ExS>l^c5vuGX!E1H>I z>CG}Ej%mKKKQUx2a1YOXnKlF*2^l3N{^sb)9QC^mr3mW4J@b1H9t3~^rDvRx)4+4S zD|%tmMktF?N`nlFJmen^3fQGk@v^7y585->@ogGiZURu;_(2P<2st_Vx>fQI?juW$ zPbv+G?eX;mkM{)q49eZfDY;!zJ}ZpcEDaWX-PtJ4D{|-GAxep-6p0YnMUxdqT&PCC z-Vmkrt264?D}*|CN)Z-v_ldK!^G`J&H8bYU;o%U-l?K+CZEsl%3_a5imVO%f_m#`Cv>Pfo4xN0(82U`b<|jp=J%_S7hhsF$d-t`pUe(k{PZ(o1$upMa z++kxEDi+$2JxWx#11`V{OP8^CeQ*k}PG*Z93lq{jEaNI)L0(>W?8i}8KFhxHfp2o1 zRF(oi=8g>U-#k8Ii!s!9V--J~dhpUyKme7Vl@)MhRs6Kw!}kVjrOnrGzlrr?>mgKH zt_rbCHW&1pj;8|97%9|N%CEQeUNJZ7`tC1z{2I<9#chW3J%yH*7T62Us=A}1^x+@GRN03oLh~!+ zO0bq$G4@1!w7P5&^kA|#-t1i;MiwH+u1D7;KOb9Dka(D2y^JY+aA+YI+Z(F&z`)?# zgWp%)42o|+t#Wn&&y*3uGVF8SSGhWw2yzMTn#qm{OmhCW)6J>7+BSyXOCIc9U0tT{ zALeL1EYRUGK@%1$vjdiNSheq(KeXvy4kb4B9F-k-y}WjD+I+Rf#>Vw{6%-=a0hjX5 z0t!MYK}RUTI5|sf10te7=d=ZveAgc_)P7--gr&YU7VX1VlWEt9u$54LJ2|WN6oLzQ zLFhzMy(X_aT7&V=L!nS$k-{wl!gQc%Ig6-3OSqUc1>*nF>M}6C{3>#T6o_JukmG@zw3+0wsHcBBO)fMpS=ID$;j zaY{UEh~&j(vA>#DiAM8VA|Up|RDYF;8hYcg|4}PKVQ{HE`o$>Ln%ujn>1AUhY3N@a z6<<()DCZgK?z=ft3>6_)gsB||zC6LW%_sT<7wW3bts~$y;K~oPNqylTp1lD+d)r=?N3$tBXXTQ!vq^}>{*V~>V4W9-i@Rf$9om*$Xej~c zq@vsmMi|1`UJBA`Ran3TxAD^mB`)}LADreu9zM7;^kS;9k}BShgW8w~9x=_rvcegf z5sVMsO#2tdfq3exZX31XtC35BBbUX=0KZ)8HwhoB*k6t`o7~>-?CkVai4zFj`6dVX zH^A*eZmYkuyPDFnkvwAL z?T1+2$${JurB!+{;+2Sv_3gAt*%lvryiY2X4jc-qJ8P+i%NL#c1pcOh@(<)Yh7Ur~ zp?WqpoB$g^4F;K4NTZCrXL#R&9KiiNyU~|NxWXk#PDICdZ$sag%RvlLnDF^mx4p<;m?cIrI>SHe*xH;W8O*=6&;Sb)^3Gt&lq4asbZS()zz?l{`e`)4yLD+P&(O+O~v8PnYP zWcK^#nCb^?y6z{nINO>7d<({_!WxAmpZkDAs&i0$AN8u|qr|U|aw!=ZXU+vMPbVmc z-)la1iqyB&KB~NE**LS}Qq!>(s-&P^Hk&kPHlw?%%kOi7dsD2av1~RDDnLySVzQcS zSK4XCTdJ~c2XjSFK6w+i@8Bk_xHH`0uWout8G)x9HJSABp1`39%i>Jq5YGWKwf{`%EoV8haPRKQ75%0Td9DiG}D( zHQ2suSFcvDPc=K67)Xbn?_LgWpON{$mOebwS8m+6F)Q?v=@nJr!@t!E$KskW6!i$# zJ6!z4%(WTn%p$$-NnRoO;sj%OBDMNHNS3#mY1e21cI&oQPnqMs`A93XH*T2$_IK!q zHK0QY4o5wsAbg5$_S^++1`TBX_VYcz(Pe~aK?;=y<&Ddzs@?FcTG!=k%1Vi2S%>Zv zpOp7+C*826v)8TpeEl8TWc>NsdrlPX(Stvv!kIZ@i9+LvZP0RoJ`~Tzappx<8$I+y3r`h2IwI9Z+UA z#Ji3J_Vn~5Ng8KEn!NTa%bOgOY@jj%R{Ynm81-HtZ7PrUD~~@2kQUWv)%cptg+63; zxV_hcrJT9C_85H1#Z3I`NRUbQ8E z(bU3XA~}G*28a@|B}K`KAYySqjBeh;kLb@ z_SZ4}h#&sbtyXKCGn`+a@fQaW^x_S_zHJy44kFC00SmKT7?Vl&Clv&p%`;a~FDDf& z_{8(>*J)|oyOAcS%{{mAM-5!3jesD8hwclERu?EYG zz;Wbz%bsNYOD+fl`27-8-fn+76+#E(-}0K#Rg_#l@q|+_XzA8WVyE-G5Q{2JpIy?8 zu4ur6ac!Fl1Y>mzZC_+$zzl%<>i*{7-#*igF%3e=J1NoJ0{I^z#zy@H21bBI;mR#d_!e?E>RFVe zgM&lIt|$oIm$w!91qBf(0<>m+kfEor!AlbIZNRI!vWn!z=+)E(^Py%+DJ%1=lEkmQ z$G}8xi+v~J%7yy<_JKj?sa)>zKW|tlVT0EP^%u$Dt3P;vA5iQ2mi<8r04Wc?>q&Wg zd;b*QNWIE)B39Vu!}RtTyR=QPQjuV53VSPXoS{mN@5lfAaWc7ZZ4>?y}!zM7UUB!G+Xao`gTm!dD(Qp9i@+A7nK0aH>e@n-1f+ z9cl}qu}?YfeO1eseJt%$xAOuVLTY-tVg>UoAcp8~%+elT0pBpXLj1^?>I{H#KL{TMu9I<^3*I2xyfl2j zZOqgYWpWUIyk>wr2BkbNd#YXPlBwst`di9`m&C0L1H}B^-rnmWsx$fz#QC{uK3i#{ z<*<9*16&g+ugd;(-G+z<{s^$Q(@*by)MrVU4<5*T4)qyec2b(ZUa^u9$c3EME^~9x zGRs;zG%Fm+fm&XFPw{-F061%KDf}$NaR6IUQ_3v@^MpE?7iz^y?6x}vX|vYCwBK2rfP_Px(STKGt9oE@rMw!vhWl^$eluOQzIB*PbuC z0tO#Mlqyae7ki~;W~0%2gCbaND^##;HSLPIPR;f5C%C9Ptf2}6F)Pw*F^64ux+3%N z`Wn>yzId@J7djicZ?E4s&tOLfWK;EUAD9*|HfTvdw7K=sD?eJO)|YpQfk-!Brwm z=ekm1eT5{}jcuVW zo-hEalw5j}AoFXvF}(R1Hlph1yW+ASANr>NHg35Ebpy{sNNmyX?Ks|tHDy^aJss39 zGOr-EVh~)=aXI`rrf+>(rga&gVTW5OB`Jnyw!eJ?-vzAt?2smw~JiJ zS1Nv-YEUJ_#w{H;H?i^IiQs5$MHbq79*Rzkzk1i6P+K?eNGE#mp6B=juU?)m&FRdB z64xJOaZq{jT!jof=+%1o6^^Rm>#6jHDru&q|<&c66&<&75#R{7h{Ctkn+#Qn(a*g0l z;uwLmfPe}$=iJF#G(%AFF#5D1YJH+!xFRrEfyWf`%P7bcup;+if9oeDV*$xS$9nZc zG1SzqNcD9F^hUP&pm75=DvmEL0SygzazOvnn z0$(7b5ykTq3m2%Fa|-Kk-BTB~|NV@sqr)4bTFAfzT1yO?5S$i*pgyp!;F-|Y)s5o` zeEDp2MFD_LNO0kr2;rn{86xcdhmB0m7h@Zf$qhP8esfwAG*q1!SkIa$iP zy*1%k4EzkB_q6NHcANo|yS6Vv zB$;!qOx*-+;|Ua!RzpKW4Uj*Dg?+IqP%24zd6h3~g*0%W8;dcvfV!e2&CEXPv54z* zMyaK{Kgn~DhhnHd*DQGWyNLRC_!<38qpy985q*cc@_`1~Q;tFRYi&|;a;LzYoco$3 zHzh7a^!UiSRpjq8G;Y$XV#(yk_h8HH@BqeHq)q+h#E-&UP)efS|Grb?ww6L?*YU6N zDv6fQ2%I@m`~70;0D?3*;~G3l zqJFcduXKpccC|@Up=Fl&n`e&Am~6ph)O!9cJ0 z+od!IX;iz3f*zhgNbNA2O!G$%JJsLoED zJWB3bonMiMCW>2v6&65`uH&`#-+U7jgAbbtU;@XfTL4(U;5UE(glNHdE4$}#QOCW6 z-z0ydi$8smpY{RrXR>tzqCU$86s(ZoqpJRQ!I_qP1YOoob|~VSR<5$MOb?C?8XTf>D4k32g6<`gZpKvra$LxhBD+C1v zo1J)2`XXDmJ@c738J2DW%_{_ZPLKYUi^~tu06;-&5nb53We~fGC#v;f`3Lu?zW}I| z3^8ri1i&d^q~UTJfF40L1KClNH|Vk>c>?8?U{70LEdotPXk!;(2mU(RdlMVGkm9rYP+|{N zSRz^a41pBHklF#WA~@oPgF=YpV!f8%eO+BC3wXuO3-^J>h-@Uw{Tg|{sNpQCA)Fy* zl-YdpfZEKddJ0je_|RViI3D-pey1U&x`sH&E=xqA;>i_#;^;WJUR|QS zD?8t*z;Fr$K&?Jj>Nj0XOw6{&Vg%5mSA$N1qVUh@kHy8>c%z_?genH<%sbqj3Dv$* zIhrLh0!zdvAaK(6nIjw6Pwmvku2Y|#PoGEH=99}=+>pW%16hyA1Lv4c%iE5tms~scQ`|}wTE|84oo}CNk zt`K^N^qTQ;ozXr@<%!*6_->!I4J4eR0XS(g26?gm^GCZr8*!sO&iGFc)*8&*)0ZzX zj~#vGtT`I_Be*jfcZfIlVEf_P#ijLaU-21Y>uSSxF;<_^wLH7zO)PCBP6$ho znO_eK`M(Q%3cZgld#5$~i2U*9(fwmQIai*)zq75&bnzUMA7f-=kKOj`2&cn?r=b1! z+#edPn45uG+*AFrG>6-4asaB9tbW|;4{S&030m7;!OFiC%6emYQD8na4d>Yrk$1+! z{*mJnfog{&WfSkcq|VSh>C&3~Es-|Ho)u=ff9e|?F>=Zi)0XG=xph!A{4|?S7@__I z1z2u@!{+=ioZizs7c1`g3S=-f(1MaetC}8OB)sNcj&&i< z8CtTmwwCqs!ah5yCVuf`rVTnPgxRuBZ$5=FPpY_afQlC|s=uNQgxlpPSyljN3y@LQ z$I+H!p6O+X%MsRF!ewQIv%9Y906Zl|1-QP)!1yBaZ?1d(Vk3vIBo{qK_Y-V)0m(?- z_ey*9d0Ze)MUb|?_0?$^NcKe+`+6no4s|noy+4bbYq0NakAuNEeo$3WA=2ZbM8ZAv zubSLf0@af&F0kRbUk89Y;}<@X&hLN3x;oo#|LaImPDjFI32_Ylf`8ivjW__5h~%!} zSemiH0MnRjSlB&B`1Gzw)SJl2sb_P(p3n-r>L!Y=X9f=SzKh0r?6h2SY(_?Z!Q&X) z-+4c?j%5>Ydngis`{U3Bx6v9Wm?cnF$rEBdQpHzj>;pM7#pW8*DlYwdFOmi?&{w{`VFg|qVfhK73ZW>4woU*S zrmEHt{kH92VTm`KEhMAOQb0guz&24Z)9+a_!mGw+Ac#v?7K%o*8SNh+9i%e4;Or}S<&R z*)vI39-oJ2EOWeW|He|m?wpOk7O}pMRmaIo4_xvnH$XJi;7X-@&z&^k1FP}$oqJM$ z2$h=DMLQjx_rv&7blZSWPV#1gJ^;W?YA5Z?`%W${;|MN&bGS81lRh-arCh5oacaWBQeqHm2nx#s z@AI>a>cqdQdYY0ydB{J!;I99U0zFfqJw5k;Bs4-mb0sAn^KflwF$L|P zA2d5tLI;W@v~ZP_mYVHyYh|NA$eqRGaZi5!Agq3!6+wR}7t!X>BMWDfgh*iL)Z9Sz zgY>+bG=z--qYx|Zb@R^MyAd!!Xk`9b^hg;xMHJN3h)15zTr|1U0_TrZJcpK75bYfw zK4HJu&y)7))A-hqT?3$U4(pRj6W5Gr=QczrnvvrR*bK7GSd{^_gj@;|jYM%wEL}H9 z?2Yuux}neKndG~(c9mEG=*m6^{-;sc>E*^jSiwIdrOPv6M8ln&9*$OcmGH@FtoFe% zA*g3?JOU1CeSICyR`9JV3J3X~3G~84Ppl+#z{1qm0CFCOPSp|{kV#VksJ)J^fEH(@ zpPD9e++GM8ERjxTK7RhjDe##f!#ahuu>;J3aUb-$Abm0XJ{3|LYk725&(*W!9qmg z$QE9SlP8p+h=PTlj6Dwz{M1{@U~qC7@d= zd%A(_XQX!w+W4iR1s!e{4CMk$x!FsB5!Kk#gd9tNaB+0PjzZnRSirTYW;_aJ!K;99{V}b{9@Hyw@EJTA{d?eO0cafr zSF@n=>&~4!NaHlB3P@O|eWa<8?5lhMZQSg4K0Vn7X^MaPTCYOWFVfx&8w+~a{7VP} zO{_qVQo2&X9uv%^l5#t`-#h)gr1AT4bxa}B{2v*~Y;g_@y%vr)@hcIh-gFg3J56{$ z?#{TW^EO4sYwqCJQg+bbC*jl@q_GiP1417l zhZ(^Gmb9?2=m^d3{a>2L<=vX1u1Y>U2#9bi;nLyDhsil0DDS7~)v;PZBBz>5Tdc6y zU+-sjdF7s5NmaUiJ91a;gOD#YVIvEQbo!-+iw7a%iE{xa9hf#m5}*o;zBpb0Xg(a> z@e_-LT;~NjlcF{|zB;!=@bpb)DQAbE<9~`*3fj{XzJj4p=biBV?nosR@UJUGYv4xwPJV@h5uil8Vfn`IP=}=Ek`8hH5Xn9(-gsQA`68xN(6T1L zo@jfQA4*kb^=M!l-jd?H3cMh#LY583N3yinDL#P)^Th!b0;V&=_gQrX0N*3AVr8VfzuZF*5IZ=fAd*SCZ(V9$9_l2bZ=SEh z0K=YZ@M`<;`TAM|Lv!K{US8ASM2HaPdD^P?NY1T|_rm!TXWwtxj(d( z@q?{`^h#%*|sAUtwd)MVxCW~2g^-l$()u0=DF`*B_2@F*MPaPX?h#U5` z(ifYupkrsp4VUli@Beu$A)&e3pL>G<6cf(|tb0SXl~hz-3|L3&cS$>xVvy6)Tz_MQ z$FTx%fQ#j~Hprh$OMb-tLV9lD{$Odk+p1*HB(vQJJ~Jko<;s;tGql%Z8yn!0B5=Cp zDiFcI_B6DerV6flQ`=NPyhD8%q6+(%WWrc z5S19sW2Djhl9etwb9}5XlFLvaN8|ZH2V0Zm3|RI*Mq~`R@(Ev_TM+E~TFLqc1_I$8 z!TJarV5y8`(9g`*17XO3fS$5wPas;*SN*$jfKxzT^;g3FJuWXgo{bZ-ws5g6D!|U4 zfwTD^#JzVo)_?y$d=_abDP>cU$jFLHNQ#C?Qf9J=$Sg9Fq(PE0LPko%NVYPfNVa5; zBuQ5G=J$B<8Q1sveUJON|GAI*IJ%DG`b5st`+SY(^YMI)4*1d$@?d__8uG6Wid=(S z58iSfgfdSdT#v~clcab<6>qfY7RNwUs1ht3^*Q6-)Fs>$WVB5#W;l!K;z^!EFCQ#% zfd#-T;L97h2$|2YiUIf~3MNi$I)ZxhY*@p$IR8=>sd}TPt-boy*Yi5GgyRL~)Gi^8 zT?9A$Q=_KR{+HfMs1HA%9iAXQ@Jb8K>hx4qRrP?hxWfQLYTSI(pt6AyRQTihE(wW+ zL8yA1MpAyTOUVuafe&1M`<4>9!)JG#AcP(-V(|e33^ENA)S^D5dR2d4ZW2%Plu3G% ze_-GZ&*gN54o*~7 z4;D8!8Gy|K*7v-xkpaXp$)(`{Y8N@mnsWq-6A%zL@vDan#vAV)%qDv`i}UBQ>U(j7xpRi zJ1}d*vF8sLMiYgnEZ{nWF$N{C(>4mkFX;3z2;6@z`u2N})G;YT^#L+iRd^fbj9B9f z!WgaQbFK?y4FBO33QuUs!+*mO6HJiWo0FWLYOd> zlbE*)5*=ot=7mMB7=;4d8H{S{HW|z`&1-8*N=oGMVg4)+Uk&OZ^|du1s$1V39vUJv z1aL{9xBD=MndLY9CZasv$5Xxo3fPh>QpX_=aYucJDp6R0XVStHjWNcE_Otc}+i9L# z8_4>0IqvQWohT2bcW{sSO+|WSc9E}d)G!B#n4jqyYJ;pBlnlc(dd3TpR1|(o$;Zuf z-oz3Eitc<6oiM#vvft4LR!e^-U9jN6&f?vpWq|J`-2P<+BLC?ePS_Ge>!e4WhAgS>#D0iy)yI|^eIBWfVd0$ zWq+iXg48eFI5p59sg|$()ERZtJoV5yE^wPbe!?KDAzQi9${mDD+jst7&#%eiD=RNo zkdp(k9TNhLOxveA));BXwPd$m?pQ;~W6b%pER)v5kRkp^;q0v%&bdF!H=hV>%-f8? zq*eOcwn#ypP)X}R$!<(;%*@R4fHnFyT+L(RgpmV?<4%B>KSJdW7ecnR-u=xAT95r% z%BO0Zn+1k%?d3SH6H$A(W;r?Ar3|*#JAw7r`K=c!0Z73xKzWRLpm(uRKH*O2Y~y)1 zGZn6pB*Qr09U5^Hjj;BHOuOw1>eZ^2 zyxW0~!GflnNa64pT6#G zIR~j9e{ZvNr$KSP)w*#B5#Er#X`g4f$ZH_Sc<2P6q;v-gKNaw7NaSGvVAl-9T{FR6#VN);e^MF=xPiei|nq3_{jYBGV2}X7&Ytft$x4ZO#=8orTioeaE^Q?XYOFz@>uobXB`H^l2Ds8*e|UOU zZf8Rrh)EEf;rp!K9a2&86KXp*1KU#?iY~=res-M7v-b_Rmiob0L>>b|J?3VAO2sNZ zZF-P>Wt^p!Ees$cq-gT$>b$q3EskW_cCK1izx{7n&G|IP9_ECp{kS#^iJ1nbx*izr z6Q%abi0S68t6P5Yi0d59b!MU53vgoI6H>t13r;Kso|Ax?^YKi;%R6XiCx+{8aYC(9 z>Bk{`zI2D_XRTZ}Y48KA_MYw->1H+Fp(UIj)e-@R1BOkTaM`ZOD!I?Z|Lnp>CwvIs zFkBT4!F;uSeA+vOH5jTk2g4+4RT&C2f$T$1E^PCCwojg3@ZgiVp$mXzMqN1P;=P+)8LSSJA#Ce(spML8=Q2jm!+D(YwnRA`++dVx-Wx;iVW za2?Y=idpg~$akwSf5_&~MJCCkQnx%#r*ytpa~D=;gd*I{b$s6+4ML`>o4UBTxvwb9 zN`tv|4rAyc*DVJ7lQXJ@FYlYpv5h3%#@KR64LWeDFuJy|L+hBVF6IgP55?VI+xuDd(9u}Ap6LU~9`B8)Ajc8sR z@k0tSHCac$g-gAB`FZ>WX0_cz`-hb`4!W@~sOFdAZmI~!ss`e2yc$LZx7hf(YByk! zSqh4tx3s(tN*ag=wzhA=ei#U2I@c*+*Ep+qu1$&O%TSmqwQufo z(E^JsGQoGYQ}O0dX?b}eEMATF0B6cKNcx8M)mHZ7uP<>0WB_0$&%Z(ssD%6~ea0uwzFxm_RqS9Si&h zY>=>|qt3TViakKF@g-vgf4t*AGp82&Sb>$oCk}MD3aqveKLR&M1QU zDzVMuyEiQc11nXkwz7HG)?7}0g3Obi9((n7_AH=y5`Vt!aznTA4q zW{jh1)zvqmv<{N&%$*xeB+%aPq0N;`?dx_dGDyeuhEh3wK{m0#U_)|VB(-VJ3ZdfHb2`&9D}GH4etV@ zi~f~$S4Bh-diY2vmYBdb_D)MnyQjKpZ*_r^1nP-;g9uR`GHL6qa~D#u|Jpo6uUQa2kELjvi!7w=pB6G zflektdWQWu>-<%Vv86gHk9;ahnI}qZIi2ULyk50U`HM)A28rHx>D`8vUrg1+{)BYe z9iHg0wvjd$b#|XvC6nCj-Q=RUM2#gOl*h2yiSxeOkf2XbU%qMJH07JZ-b2S#8RE3l z*P`abG?Rjpj$A9070wGwaD?f-$Lb;{ z<$_-NLaD^}1eqbajIoO=??-%ILeb6h+<$^=DLdsvg!zXHj57H#j|P6HiLL*qbK$0< zhLy};8k$n2f>*A5F_3Rhx=^m-B#DGFg92U_|FCxa>CNSy>`Af;hJ!OiV6-MZxVsRS z78I{ZFap4P1*->^6RNp3Z>ys1o-FHft~O$B#;m#jZs1jr(Y&$MPgMn)q7DA}m zPAr-u5j!JPaRfC0p#$DB_HC|`OG|+9`#D##TC8Q;z1ef0joYD0wUZ|eN=YYee+;xP zQ&1{VYLotypa0H_gxwn)=f!yXXWWhNeHow34HQdoHOZulXf-StHD?yhliR%iz~)~e zucu>!Cvt0xQ`$j}q@m8*W$yWiP%feOfK61*kGmJ5y{_%N@h%g8+1r}UN+D*UhNAd@ zsszp93<7!~s5ZD4*04%^P`c;2pD|5k?hB93mFEW;zm3d2SslSJ$5ms>GT5LSK}8u! zX!77U&b^*BNGB?s^;n#_jzj4E_IdMw-Z_br@b}he3Bg_kkBGF+XdA%|&+Bu1LKM=v zrO%_I5Bvn#0*%2Tef=mQzxp($Glnzl9xG`M92XT1OS5d)nw!4JK2uG-v1knEt&_fJ z9yW9Z_lo>a)}t^ahT!Sr)}ULi4AZ2oQU?p*K?!Jrr8}?Nxh=^9Uo>2eda3##yMeUL z94iZpy^|NAE~Dpx4akD8M)Y$Z=hwrP@^nimYdK|n;FNR@Um|P*uuH;}O*JHY3p&M0 zy8d)aOZdqCeE(rSb#1XqXI{$OYOI8XEzd16aKD6SF3~~q8r$gl`x4SO9^^)N9of}( zD4&z%PeV<}gt(zmVKF8&?+3;~1STzwt7kZfRbX!sAO#y1Pz7{NMtLBPc@|P*oC|?< zcg_I1)S7rnI5F|c>D7cQS_Z>H%|E4X)u)9)7$9KF@YY!=qx=ot})7f2$4`&LPS^UnU|?}t_dv0Auh9^ukgpPymj*+IEicn zZ?NC@5Kpoj?^e#+p{53DkoZ+4$wfYtqkaV& zHzHbDXZH1oipp|In2amS3Li!3k65AtW{u}^F@od%t&rFWot;cgqI;)@F8Zx)E zta+${L+f2tMRBHx>*R?yps_>%*EUrOyvr#oG=8k~7Y!xZq-<&Q?%WkMlJvB=OyMwr zRrYMAfRJQh&&eqYNWqlFbN)&dU3+eim@p~jQF9geF*G^`%1yf${cTJ8#3 zZC$xOj|Jm1PL3VZxiTRo$;17+@nYFrI^`<4K4~wL>uSRCJk3-fL*&4)ULo$#i)Cl8 z;uJbq5qO&XlN<4LJO78%Kxo*Dl6vDKm5#0~hXI;Lt~`-)@Xoar1}P=$R)i5xR^WMr zhfX8+{bw4OCqxoY-6smqvsc@z;7?fPYYfzvSeA)|f+;Hpk}|Oz11^JV*so}VxOOCO z1PGxmV=Y$cF0#tImwYWF`t&sWuZuQL*hkp1a?>$iTU!&Rvr|$|oq6W}SPz%X0)y-h zWM4TYmdL7)rafU z**%Wv4twYL5*k)lCO_R6%OCHoBn}}QpWx;Mw#20vUZR260Hp$C=Crha>{2GB zJbrZ@gTVQ`W{5d@;n%ItcyC*FuOHY7(4y{njx~%$>oRy_^ya7PD3Pm$2Xg1#{{9`{ z_-{A({m^FNz`S2}5pPAlGyqxhIl^V2W6g;7-|c&;o4WOhUFZNWj)A=EE%UTrrgm;_ z_sh*rvYcfU)*qMUGXG+DcxHCBEo+CL6aGTQCUoGrNeLGS(>+?6(GK4~tc;9^o&NqJ zN8&QQ>>Z(FfCh<|GCFr-{`~iz%Z=xvge#eLRvDy#F}Fts=_U-Qs)bFyf3o!1~z8m8SmhaBr}B zm@hLfbfrnFNe;uBOvs2od>Mp%s=F`%b=RKVGN)eAEp>wR5-h_w?Z50fMXE#{*B{Fd zPZaoe+isYfkP2}`y^~Qk&QbWHC8IB&FVkfviFG=({@rTVh{k}$v5oz!XK}pLSkG&9osmZ3KLIQay);@@+LGSns-Q{77`TVuXf?N)y0pF`OF

Z>zZRM#x7eS&sliY-xv|6RlsY+Z|K+Ob%ES|Lw8uBQ z_t%zD-o7UFf-u5kK!Q{*uS`Wjw`Z-Kj~vKna*}8A@z(H@VFK{_V*3HZp?lYGL4zJMY3JsdJ(5P8!ijEi&$u%wF*4^4@3H@NuXio1LG9%}qAaBmsJN&OYs605_l&^_nwD+d_G41J zTVY7tf3q>9^#fB-6rheZ=}l{Z87ArB8paS$wBp7Z)*of>fP2Oq30QPU5*+5eZTp3} z4f8~!ZzFIz?WtZga4?RHW!DzFuPd6G+_W-U2i;s$$*YaUle%DmDb+bXfkua_Cht^J zlord9bMtev`y=1camws75_BO`gZ#h9LJYmA;&mcS-e1UhBASsYQ+93eES*f~-eHBu z=9{=@e`sfvU1Eqho-N|pe3)kMLBm_oyoe4FLy>|iD_1as{H&_mw*teH_BXx!GVb;8 zQQptO;P99Tm(?BR(?3#bP(*y(@BN$;0HSCmPUXdkmBwph(|b4qFSqpb#*%o?~^M_bfZ!46It+ETihK*#1+9S1*&-5u*{5fq3&@mYb`$KnCh^l%7%}$%g(ye zw_cgQDPn#YMM*xK2q+L_|FAp*mMYd3<*$#-v}l!gK|6(VYN4}h3#R?I13UGMKCP(_ z4)p~%;1oNjy)*=g0e!T#YN@^9Fzy^q8?|4HIOQvMHxBqE|?0b8`P-EfeQ%j-0l#2kiKt%!aWmqb+ zRVQ(d!(B!yBlb^S!r4Q^oUI-M1;o!1R*!#cS|T@j5ztmtadQT3s!k7K?ZhwI1^7#j z0(LFzO=lyvMew7z6LPNTuqp#ehouzoaW5!w&?gT(_DZWYte@sA`;{5T5@7v%_DRuT zllvvZ1Nqc3Eiw(k`{F=*fpO2d^d@7AqN*oQ{@zeR1+z~D(3u!d+mMC~Sz}zp1#vFx zi1g4WBwnFairjR|U({{pa!f^-2a<)pmCgT&9Q7MuPQE_UmFzY%);69u-?ci}BHR<$ zi(#NXSZI=C4(<6~@PHLUl?j>;Ug;EkIw*MtNuP{yeBczoADG50#{*V}JEp2oa#NpZ zE?k;Dh@#wTQS9X4gp$iBiz)V$rY2v|EfwB&OZVr#_LIoaITmBVcYABDeBAcW$*6>b z&S+qa1Osh!Mg|L}*0+xU!yKtQel+DbMng;i3eDh9-P>a-;rx}K%JISm-P*a!e^v-w zGX8c~DwZ|bCm2B~5DXCJ0z57i@6rx@SV6fs-Iq?~AtFm=Jx0R(Sr^e3;7-FdW>JY- zGP9yNva1Vz1q^$BqEd!^ic;M&C8?i>U1BS`-gaMpaxq=DMj^|Eat;y_QCCv?PGa7; z9Mw^Jli>Cwq^K;4o3~KKf-$mG#P&Er1iTFK8Jqxiu9&@An->WuS8{cmQgmzkbFOSE z^y5s_z9bHs+UHGv1d0yuCUz|AR_wkGv6rrJ=zq;@9?Hd8q&IcO*=*H=s{#t;WdvNm z*HnFX&-%7W7!T9!Zson-N0;g^#7SLf1;O(FsMRs11cU*CaCN6U*n<>`-b6m5eTiX| zHXq)oYK(zsJ>igFRqfBO<*Z7*Q0QYXp6j&EyVd-?MeZDXmQ26LuBN>^bZe*VK-JoO zv7o8B*;0w)B(zSgX2?XS2o_+Mb<^p;6P!d#48WFAh*j9S-Q$g}tyvC$3!p7M0E0dq zju-8%Zte=nE{{S(jfFA9xq-S8-8f+v2hmaB0kZ_OFPI@y34A!5ev)kU!yk=a1IRSk ztnju3=$^snJ`;isuHIB$)T^nfVUTWE-n=K+cA6nrskl&G;W*%SwzbP)m#Ec?Vj+rK!)23yqA>8FQ+U-A24O}5K8IP20P*jllE@Qou~bx z9aeAG@VyA|50qHev0=SW@&3(z#SdtcopykR;ahBT=zsCsYO0Ulv8iNx^U57=vpsrL z6qs1@1QGVlejnWcvaKb_D+oC1A3G}g-sLTG0FSaLkC%PZg%0v6FJ72u^rcmCz7=Cb zVS{Pf41jI@p4#|AOM1f8gDCs@ifi(z=T~6tE+SOT+&fmV5x*V0xkJl%wB1qh#rHgW zMm%6~Ode8&f2KFwrh=881!pb%e);rxb#C2y+&qhwo~(fNQ%2p|`vGdg{b`@>oQIo( zNL{L6?X6o3kX|{c2_@>j-GrteJ-Lvs7P|5!OGiy3v)1*E86Fa!-dVW%#mn1|9`u=cddb4zLBT+5{@b2~Z`P6c?okOmQ9vxCDfOjiXq9m{RQ3Rn)W>*R)e$Td+{ zFIapY21k^ZN%=eKH^BuMOB|lyVt#8jBK)o)HiCswu@7ph!b3J#V8`!j)1w3cjImgD zsH3&Qh@p+nFi8We5!#+<_U1OU?SSr2r^(zLIIgT*2)c@c)02j|i%hqMH20d(PPJ$e-YF>_}|>Fe^R|Z{9`5i5A^*1L8jOL z?>zLs!#WR&i$X2q6Bj1{-9q$>7sbI!6zALe-tj97f{+$aT47A6sd^t+J$ zK;IJ0)XNlx*c`)M{*D-aGOdS%B1)?9}h+euRNlbU}j*cb_V;ED?e;P!@D7(>{{BxMCd%)#ll`LjWreqVtu zkR)1waDtSc-=BHI2GuKll0+Y?bPQBJ@UqdV1wM)BFCnS|P{qQaI5AUFiy76A6p=E} z257sbhX!{m{Td%gY(Rn8Ry2sQ-RIB|lqd*&Ap!zKcwV()M?*6a@n4K;JgrhI~K(Dcv-cqb*a5Ua{)|npsZ0 zlr~Apg<6E>7%FHg3NRq%O14}_cIq*t7m~T=FIt~Y`0@Rf<7MykMk2-6E}|m#*apcFERJAFYYs@U{~+e3y)sH3 zZ*n2A3lRfAO*I3tWZ$qMq5|vi4^bV!-^jltbvhp53@Si$WJtgU$-c>YrT8C0Nj;#|(vSzrvdvwpR* zj4r9XDB^hN_NnJq%Cq!E)i~$jhI&SbQP=-~!`JHdEg>YV2Slk%onFsh>z{tr3wm`J zB`kHS@=e!`glb*<{A~&I+n1!6C+R~-?eeTnne^>^eq74_*NNPgBCFHoUS3|<6@=64 zk9!+D_|L8w$tqwG^|Rd^*mtQvtk=!7`SkMv+H{%gzYD?7xP{_q%a$$rCv@u#W+4Z| zwzKLjl=vW|n-w#i4V)0!T6Hb7cZ4jkQ|?EA_}pD9Mx;zORgoy$slu_x2;92hYf9MD zR%avJre0WOzu)aN#0`bSwWR|33!Lp6yDv;4nf7Q-qGInEaVQ>sRA7l@*mti7NnZqX zPF(*O5Od$06>;?NG|`SeB=F$kZ^UCEmP_)@v*?_Wu=q%e>xU|$2?wb`?(vajF zXfg0X-7`EAy~h4Prpu%#31LI*u&LIU>a@sS5-?W8^vkRz?yI7uUP?W&>T2-_dVbs3 zpme=>0M+%zGa^ZHV7iF#8Q?&#&vBK46z48+_Fs`=g-B4QWYT=71~c{g+=m^P#$1@c zzsQcA%?!G6fC@X0kK(d$pz5Et&}F6-S*NFz8^29U4qp*L{+FR`?!h2Y5%YpFd?HSk zFJErmvPJHhZjOuQ+zf<(OFUf5K7G1Zf@!xOjLC4Rtf{x%;0sDPj13s^0coU|`HO_0 z6uz1Np`o4@S$zx4bhsfA?lgirZenMl^dSC7B)>(nr}5qQS$@I1EgXH+KT6K)c@dHZBA)W!&7(x@H1v(bQQ_zI6Uq*5-?duXMMOl5GO@Q34D7*K9$OXO;u?-;yn?_nZ78YPQ*c8@|Q1oHl z=@9<(;@1|+5yF=K7ja^3qMTIQ{=~LL_Is4Ep2GRxzArrIUHS!1-dDR9#y0iw;dU7_ z#h)#9KL!S_w8@w4biWPT(yyK1(xMh^M||dz8NY~`rEL>h9<=t+Hi@Hl6Aj1{SiY&z zXOW^H?t@^jbI+GPpmR=m!fz2`BT{vf|38dZ?Nq#QFt>9l|T#tE@H|jIq+e^uX zMkYx>j(r;xORK21``+2wUpOXL;b3`rK#e8 z=-;?ZWHh(K`JWu;koy8)=-83Y0D=a{Gi>`V3rD}f#FcP|7JbA;oGOW(>$Gew8U4a8 zArOouQbU36jU=2ePY>}2epXXufECF(FtOy^E3kqUT<3}VC}ET=(xsp!|0lc&(+=2| z!NV419xeSZrHB;*@7x-L*@#vI5nrEemrzh`h$hxq=opuxTOuaq=o8~MU^crj)@*+o zbXGLMwnQ`Ac^8r16L`D&>OuDP^J`NtrgQeq`KiMhqSg>C0$c^)8S@^FX~_!P0zVJK ztPA{Jw@N;MeYhGxqM4 zIN0#8BzU(?^dLX)_3aTZ>(OxH@nf!-wYLhT0UT&hEq2#NeZnZ6nQ;vOlR1qpcyFL* zgvT2gNQ9mqD8i4l(G~mdRnhE%iN)pLFJi44w*_JD`rLOam>nr`NOXHlgOMzdIN&QV z3Nbh}<)kQP(pA>M`Q6=Z--a*SmsYr1?YmDUxOZ3X1m9dIqwFpdzr*gvPoJ`LfpK^O ze0X3{#I=OX_W&Qgcp+zJm#kw7>HxT}hywcoU=Rfdqv-Q>)4+1^2^(KR|C{7K?*>GW z`OK}upcmkTMO*0D-)yebe+JY^E1#=~E9gng$t7$DTw#~Tch8zjs}K<(Vem2 z-9s3-aEydw0UnXZf*rw``g#4kY2*z0neP+1-;_IikDbEZjwDda`S?5v+OI<00O~S^ ztr%BYg_Ck^kQ%Bh0CgBo68k8jh|`$m64M>1!6&abwqG2%GR!GtlWh2|nE57r5m>ku z4R>k>)Q0gK@6P~K2ge$enm0OsC$Q-OPsKha2Aa5RfQ;fy0^W>f{v?N|<4oYomsj-# zZcZ@W+PfvKi4*i868=LRFno%^&lI67sCYZutz@fbt^WZzO)rH46JD3GlKsvCBQ!xR z{$gU$;Sx0xKT!EN8KW1sMA>+=gtm)^hR21QdsJ_ZIJf;1_25}vM@FMa3NgEf%yLB% z!bYNMS^}~oaL3E31Sy{67L+m&z1C#2ab8@OkGGQfMIbv|fZ;6l{>)jYW$@{ibhX_H z#(GD0Y{ZR^1}o3&SIHc&eRiu;GStgrbK?cp2!(NYOp%Bo%2jaROSY$cf01kBzO`lk z@bH~kgnGa#Ag-C1jafFPtmFwea%Suw1q5-k=|A!ZT}smB!SDA}9xp#H!gSbOrO<0m zi}izBYuwXOlP1Remiaj?>l6nkFy&|aEB1fLxzS-V-4GGV9-E=O{N(_Zu3vsxj_Kxh zOWF1C;K0;u$T}0iA*=N}4;WsuBrCYgj-AQ18cP>x&h_@kVmv$0n9E9~tB7OM9uHAkcCuRSIelZ;M+r zuj`)k4%O>bK`4}!J1FW4k!=)cMSl$a%ZGnQOepYc$$6AtZ2X5wf1Gx!mNO8kebJI; z{})ZZ{7T9+SAzFNl20X?AY+i9$+6t@7{MwZ|VKQj|b&LYW|`sFn|p)K0-)WizAJpWXp!UopKvnOm5tF zjL6SkiOQ53v=a7xsp&g~XKkP+6yf_mODCCIPdE{}PFXEh4Ywn+qZp&asd?V}R zdjic-2+t*; zHz|I5M|1`x`wwH$Z>yDLFZ7CT>KkQ^51p0v8F9uR?8N(GgM^6kPd0_f;5-|>>OK~7 zF`0t;XkP-+3W#?Uimh;;8NEk&rpnbd%$ywqg07ca=9$A7$9!;J6Gp_^ z-?FV=z8IG7-TI;I14!DwM-20EGhWRL(EpnakB|wzTm+y~C`44h?$>?8l}dE7^+L*3 z6QhalYbaT)LnKj?@)|fzrez#`$GsHE$^uvEwc}&*FBXUydw^X=^V&G5ah8pq#mdIc zEWpZUWok2Aup`~`tc_ohD4M0~Z>fJyA#U=?6W@9xRGlU^%w&#>%@l+)>i56BKHaY9 z;@%&MQm2ppV3c!@LFI0!BW{LM2A3XcD-1c(o+F&R zCfK1ezrnq4?nh@Qv54mhFek0E+;dy@-qFj+Lu|ccPdaf09`mg|p_?03>!%P?XBboW z7T&-MxfXA@ud#)eZL0YSk7F8BaD%FJ_m>uOfj=?Hou13ef_G&?MT|v!}6x=NbtSgO9JlSe|@p>;7mtz#R*XhHdM|(OkMIXw+wtAhMysr&Zr!II8FBD2L9g}Kt;di?|I@~7+_I%QKQHbkdUS|H z>Jb=@L@fIDI9`bJ-^QD8X4{3h_*VO$!C z<8wYggN0$5A^AHw$=ozvm1@9c|2J7yvsT}Aw;d&(nwf0L3fWng+R?mS@|k~*)MQ}{ z)ofWIPuN5xd&s5bvbw&G62yldQ(P*K_kWp=x$)@pbyZxX&fW>TQ@f4l74R79!sg&)xBo$od$68;Qx+)aC!;=#&=+Fxcsl%XK6~F=r{MYu? zw3eHS;5KOkbWC^dbKWsoSC4T!jim!`u_olicKBY$9)n#^!%(EOdsOR_Dm^!gZ+lmK z%_3|?j6EdG!vA(lRbx1mEYo;l38yQypxq-pEfMER(fpIiD>r!)ispvAvvB@>aWH-&-5NUUj!U?T88x0pTEW-bPDfu_H5^Xw zU01c{ubxXoprHCbiIyESg)^!_Lxi6~t1s7s{(hmErhZ-AFAUGnBr^X(eFzo^y3I{# zy|g4c?{=>4wdI>yf303i0l-gEl5h0X$unx_Pf(AzHg0zx_}zbibiGK=>mH)7%3CCP z7>ysNF0_X^lfIIJKGBsT!_WJs!F@;Do2VSW1LS-%^qBA>Sl<5QZu)O-2GFRj#EhPd zBH-T*XT)!qq7#&!WE^WQxR;ty3)eHp;1eKII2b>P@GPN__zTO1Hy<;C37~WHM#IF) z4LsM~e8pQ%fq6RDrOTM07&>@h^XbYX{MK z;BBBG+Q@&JDPXx^bD!edd3nAti(^dP76O|-n+oHJ=Rmd60m%uJg-dUATRUfr3NnCs z~z2N8#c)Fn5p5+X)L*f2HCYYduw*1(A&S~;(*;vq} z(SzT?83RZ14U*&Fuu|GHifh zb+HZNp@>g5=>#wD%Q_u~%9$*c`eai&@T+`YwVnhojRd*b@2#q-F;e0m`r z4tE=dmFRvP9FQ%t2Db>X>86RX^xQR+iT8AF zR}qS1W~(R^7Ravpc!hl*$r6Dcio@lP99A9{3yAT*tagLqvcQ(E^eRFS3CxnVc& z>qqwiZ?~1Y1GF4@Pq&E-mvMJ%l=l8)^)f#%?@@ETMt#EH{E+3d9nZMs?mf6Mz*&|3 zH9JslNX5oUnv+iYTE(96sb9?&oi6rn&82M*t*03tl}^V3u82)l@N_MV7)TbXn=XT8 zX)2f_Jz@!O-)bXXFGao1vM;1!bQy&q&4#l<1OQf9NDRhnQUQftVwKQrR%7Zu3W4aa z<+2kV#8v!h?$%c1NrAN8fALR)cnsfo| zoX&0sqOQe-{1y{!J+8;kUBjAvzlSGJf##JugHQP@=%479!ZGx2x z!cI|H3x#6|5)qL(~4)h zt!qomOE25f?9H9}nrM$DYXQ&z(v~kUfmM?pE)_f70AjuhW`wz;$A@A0YstFNCk@z2 zlVlWrFD(Qv=C{Ab853i_A8G7+zXf014bkroLG85CRZMRjM7I?S(_W~5EeAvqG{Rbi z^)P=5N;WIM_C8Xq`x-pcQ`a@RMBuB9Ij(QHU%Yu!ZS$dMDBeAxvurBnB;PBU_KO;* zj@5QNJh^$@>r_`Ls?>|{)4`VdoV6A+urpizUn^)}G8{j=t$OvFbgP#0PeXRbmiD|g zt>7?CD}xnNj89%6a)owa2zhD;FjVK_z@VN<@00Uq^jy{N+auq#zB>DC;^^`0WSJ*? zZ9S~CH1UpzgMZV{IsCA}iR0+>4sdQN z>)O~SPYO;)0Bm~I@pzKb=*{V-aUXc*u5-6baq+sHi)M002tUNsWl&q^)74me_+)opyHEOrF^@N%O{!ZIzU-)QpJffrrTeQ5uJMQVz zk7Fz)RrJHFlaY|t&>!&L(VnfG?CobZbdDI(jKJ&U1vdVRQ%7N@RgIUy%UdsFHk3a8 zk%5-xf=4->+aIb~sKwJ9HQvt8O^;&IsD?q>Ysk@K08pNdm@GAoS-R4myBj4|T0}wn zYZ&}qa6QG#aPru(JAI)oSh*FBVPDK#u7qmF>PUJ09Bae$uw0<0Y0&b^mf^)khF@sy zMA|#3!ECATnY5JBE5|1FehMX{!6VMV#^c28Vv5)%nfZ&2s;8>C?9R8ur?>9#EijeO zsjF)?``9rET6X!=f$i&W8Li1zRI{+?xvCod{%pa@*Wr2;rW^WK;6PmxDEp{1Yj>NU zo%ACtu+IolPlC^Im9}U|sfFOz!%mPea~E&A3YJ!1HIs_|mvxEOz?0yE6J;iT zK7Jk+8)pm+4drAMEuXthmgpVrPQ4cL%Pa|;nwM`UCrdYM?Z7QT9qIQ&9lXrM3RST65@}G`-9lt%JQfH#d z7K#%-!$;L#!F>@IMhb&kkMK1;uP`f~(M5x=sTb0=Beb*3`oZwS3njztzk7R6ZS}ub z*YmJ#AYI{9tIP0l(<=Rvr*k2rD``AmCM2ZQ>idj-I)e|UrlH{l1`!rUUwbFu6pfjh z)E#YG^N0heO$~jYJ^CW%y`!mZ_~P!mhTZNGYevc8ct&oS)Xz=v#1EsQOKq$FiQ&yn zw{~O)r#yKgkKMaR<;v%;Sl#jNbZNn(5Y^XW=Q`m1v&*<>B<9X#&B0x8EPAEAsIl@T z*dJ)UKIb9m9%q!$u9a@3TdRD;o$ILuQHCM*qoWpoyWS5 zuOdkSa#T;E;1#QtW&h&AV|Od%KCxUmb!Yaw$#Iixw-0WO!XcZJlM}bvv&{5#aF@8d zqBu)xqeO_3mWs4&+we{Uu91U7CwOCE#A1+@wxOdq1JX`^zHH@RUAOb$(KWj(&UHR?%Pk+~Xa5tgnOwLx)=A06CP~7o z*=$zu`hhJ?<>vvlqXxsh|9fB{sG8lPE4%%;tk|}Ptv|N-yO{)hIZ+W|F)QX^Z~v)d zkT*mLRoh{>^6eSuDmd}M_HudoxjO!)(Om-(rB`+j&#}endRNPM5sFxrX}H7qvvhCC zCf;G!N8>(lJ;KQqpW9tp5#cf*3A1suOvjiV_=JQ`TU#flhDHnz@JB3c_+=t*#2|sk z9DTjbDI`X24h(w?A6 zorkL*N>=wgf8%RqY}M=Uq=dM=z7X}ZiFJ-L!>heYM=Zw`L_ZQE?Z`fl^v7+%6$DXrGLcyKacV73-}_%OGD>q-Nr8&lKMsZh%_1+5AhS~z;n ztmBgMIuG)VR_ghOyPo!;XC^7f37J1xETk*UX!cU(pwd1MHaIH3C!+UPQz*^e=em|! zWwg_{b|2GwlNMQiFp|p0_nh!^pysFW+DRIgc_{#8uUf8fw6%xP*ZJ0WPLEJt60QmS z?F$;+Sn@t$XQK>EerCNRo5upvg$@a?H57`D&I(5gLriJe7V^!YT=;y995lzei5cr`0BY45#PRjH&}kTI2U$0ch0>a|C{RA zvtiqj+}y7N0;licU81;+2L5hZdym>v?xTT7YD&uP1)eJ~KgUz>_j zzO7e$Ew(BlXGnCJ$=MfqrTnAa%t2Dg!v>B#;fbK@;#ks9S;xsoYz_69$j%q*x&NSH z4k8TAVbpShuDqz_uD$YJK)L6Dk98!Fst zLmY~)zRdq{Zoz%CvHpI7H-F(Wh^6?YbxdZE0d8Hs^ zFWXwFWFaT;oiFm}KbV|#W4=L7H%RLm`se%mt;o@ju||1;@BusoT*lju5Ly;8rp$Cb z4|7KwiM~MfvxkmVRK}e`;qpCaO06Splg~Nl+F37d4w?|be~(nh%8c@vj=k=!Pbvtp zFTPXMfwN0q>)6$(P#M>(2XoJ4#h$}-w~F|^7Zw)!R5O_qH;`>ds?1IyH7~uhuRaML zIqJ9{Q=ZZ>M#xgG`io0Q53kk$F?ko=JKSGz0N~oI)qZ-Rxy>KAz)yWP{m|fWozO(w8uS% zc(gq|$=3p)0<1W1qvL%m2yaIZrnYm_(CgF-smo|B*#$8&k9FsRwQA>!B#i5ep?&p=?GpaR^ zoSOPIB>Z9K-LlC^|Gu-kj4c?u21Bso`W|6g*MDtXLCD^>&(rY)Fdxzmewp92HMWg@U(E{yJR8j5*n zeOA6}6hHs;q~6?6P;Kru^Zw?{lM1gbtRCER@)@#J89sYr>Rr@{!>GV+9Xx=p5(gGy z%F_&K3>_bMi=#sHJd7;~Aolvyi^6&!m~_%3-a-bf!Dk z{rsDpVP-!u3#E|o{?d={-k&>x_kj`~tMBED7fFp0Y->$tBd(ZC4>Tkf;S25Mjy>v-W7TlG!CV%c~Ml^1pvzJ({P_Udl$^h;cxLojz zIQ(X1NX+5rfJ@VtcZ^DCS8HwX`J9|$onO7o<)`#LB_40-GIN|ar}N;*_zE_}q!7~- z7#I`poSGDSFih7uAaW)|YT4OeyTaJ1!u6i{q`1hqlRP!Qq9@q?f|_qWWSPKE*KyOs zp_#uQo-$5^y@+n%?he$pvN7SBm9A(8qtHdc|Ho&98% zXYYf<+?JhXPLt(#r@%GmKZ2$*&EY;$K>uyw4s(ydfkac5&T+0CnrW26yR9k4wYj9H zn@3NV4OR607`U!#cTXODda`zxARk}SoH7n3e8hrBe)sjIex^&6K8~D~l)GY=s2{|H zT4fch4$i7 z!Xqi}uD!|ji_iPaMH64};cQ>Gf>z^T|L|lDu1LHxJTyO}lY8}wzblo4@xBsIDpcB7 z)aEEdkH%cuTIz7LWzy$oSB2S}G~9#MGO4rl?h32g)x}72L%;qk7>RE>{dkgv%E!g( zPZd|qVJ$G^pwR`}0w;mgIhko7PGN_N%3@7*5^%jb*i}vJ3d+=|7pBEwfXfe?LbqMu zi!E-sRD+MJ4n0w|aB~Lx1pgi1t;_U?C}ObBRx=9On;c+fZEk2pC^-c*_usq-}wWh^yKU@oo$ zd=w+6z*_1x(NPs532dtmbDkUeM)8IwE%;~2IW*IokaDw|X?Vt@%MJ$`mh4w>LgTHI zAY8C`$oXo_r>LVg+gzFMWn3IvmAQ7v{o2KqreETkmoI5_dET6W4itZ(MaTH?v;S^>~Req@L^CQglsp2Ei zSX-EjYN@#cbqQ7#l|@7Qpt{FRRLWzqZByOxkVV+*d|U|YMkDP|Be!EZkj^>K&z>vQ z%|w=1@R#gfJn-)GWQRKl+p#oVPB8^B3-1)TBC!ZEbv#QdNUM|IRb(wsc{VpqrkUnM z$WA_P$A8I#kYgDQQIPNU3$*asR^~ z8s!8Yw<Hji*I zs%?ooW-|LWE9;GnhIri=+wU%wgszJ5fuwc7B{kjU%g28ow>GspJ6-B1A}bHG`LTgE zYu%#KvC{Ej#A90^D(IwwF34bCo0=?KC%?^H;rxu%mM2~4YGjHQ0r2SkYW6r}m#q0! zk8G8mBfmok<8HQs-|lz$Q_ICZ$@_k0;r4~jaIHpVc;=>0I(F?!oR&+5;6^8IUd{a~ zx&G@{$tXoE>rJ_U)RMmJ3a5-r%*`AcJ~%m>UNUj-nJ0 zO)SJu-6c;cHaS@hAL^>cH3cW!-E+a6FMw$0+fC+WQh{s@Jz|=Tz!6 zo=S75Xpl(AJT%fSlm?QyGKDBpwyEJ?&N+qJC}dMfioMNaWlJja7BYuAW}6f?HsQS< zI{)*3-|t)Nd%v~5wZ8XV>pja_Ic$6X_WnK3{oMC;UH5h0=Xg}VRe#?sJnmS4TCm+y zL=1J&uJ!9{6$4~ke3&Vb6N}ibFSQlM<2Oz2zb>il{UOw)e0}Xtq%6B?)}g}Ij(F0n z`gPg(M0G$%*rK=psO&pOmUr2z6;WPUEN6ojmhy2!Y<5fZOZ#5*rlpWoY|k|8^=GvhCWWy?}w<6&?RH zTiwxe!EFvtreWXD6R&f3hkH0NSVD4%hkNl}A{ZAL+TBSmY!PC^XYP}2! zr4L7G26UsWNq>oijRMjl4gLOHj21fCg(DlCW>qKjjid1{=xC)Ozm9+LMM)d&PpD~J zg#r}?zw8kl@noxm8TG<6@-P+mP-hGVK#A0a5e1-)X(l_iFh0x4CxGY8u zZ{U^L9M`q{^WcD-03QtJI*WT<$Uu_&!39Sh_Ub;SbbGzJK+Vdl~JGHn+_?xnBWJJ zL6eIiYo-%7<~@u{1~G|e5pSHV$7`!B_ju{q#LT;!=1uRSRL}sd((}(lC_Iv%E~c({N%Q~x}#^X zd6Mkew;jCtb$=UPgBQ_QlC@s&M)&B%yBIv%1*{zJ+D}XH>B9t5IqqLAL z%y$jn9m(&mPWlwlk`tQdU)O3F=_&B%I6nZVa+&yCo%I*}Jv)D1vowUxYicsV>ZreK zMV3Bt5gA2W$4{~!20B*vw0caGFLdo^POZC@=@IN)vbj^N%3^VpVj-uiI3;C^qD&I! z*eVD*WlSv*6#W`6$c@f){I(EqT>#`YRSio6L6Wc zjk-Fps&^EB@~I+MR?gS1vNp)%z~rZEi@M224dtzQgCrGOyZVb2c1oJ-@)!L@;#`1( z=U+K*KbCG|TGvYTcG@gsVfWPRd@AVaD)e^zy{J>dVIIm44`kQyhw&@6|B23Is35Sc2ZZIOB`4c z4C9J6lS1DBq-X^37SmYq%j7G!kXz4}VnK-~7FP z!KiTYp>PBInD1R(rn*%O*hOqH)c@c}**#a~vO6!1548IZ<_YFhbm!D{l(0mhWl`m| z29khfuDVthm^Bzs0|7~an{UG@pt;$i?w5GlBmZ zdg$rvE8lEmPVt~xNGI8hn^)aSTfSw=09rNsxVUG29vOW^slZZ5SS4erkdj|od03r^ zA?l#8{~f}YcVod;2?-Y=X;E~*Wg?$K-iVn9SG>~Q>R^z1*lr_X-Lv@;^j5G!vW${@Xbf)|C)0Z3&nVA4vSBZ;6V!+jSN zVkvK;P@(t<(%M9?i#OLPyr~fdm_t`v+i#~AM<$YYD@qpkaPBNzfXS_rs?pIkX*`d( zL3*F3Chli_=7lKl$+2cmjQaR9)UuBqyf}uVY&TZajRY?pvKEF*BL7q=eM(?HQK0m- zSHn=ptHL}K$XUr2Rh4#ul#U1wc4*ty_OTuy0u`ty1?J4uNL59`A(cFLYwa)B_kdPD zvTgY>Oc&X3=Rhu_u9jP@NZss`a(A1@K~tEaaaZ_!TR{b$&G?=(IhIpXlQZGs1qX|o zO8d=0nLX>XKky#*u08WCGgF}>-4Kvr+VbdW$PfYw_USx8s{9Q13lsikQr2y2reVF* zijsRNogA;*nFdR=r=AipVq_fl(eODs zX~pi*&G@G%0-}QTF*@C_^=0gDN8dOOvsfnc1eo8H&f8#;en>NNAmDkHo?e~KA`?dR zytf9^DnyQl-uxu9;Y>;%{>X@--~`Y8s85cA9YX5z6z%>s24_DojbBvH{TX|cc=VwKRQaX>ZZ+N+Fo;vI z{=*KLpO-jmal7?pp0vf2&?x@Ud^n>+USRX~k7d<;26zlsGYIfB^F64-gP~awrQl|! zNnCZ4{D%+D=ZzHfX$D9%A|Bv<9ZV2g?O$W!p-m%<{yd@5JJCt=f9|(AOd+2=DphC* znA)NUGImikovbEuI9!i6yGp;La^7(4j@BloKZCbm{L)Cbeoibg#z1p6OVkD}9fXic z2?;V`sG;EKZ5aM0<2KRmFrk4lIR)<5qRL^K_6%xMf&$K^LI6fE+Ijo4~BX`{OP&~wJ z^L;b|P-svW0NGetW9pMlQk~w9S(OJpILr)w!K59Um!<7LX6l;qiuCPl&a4mBItSBC zd_)z9B8*-drgYKwFPnRv!ClkN0dwcHypohub7nH`iOER(I>#E2hMozfFu!aaZb2$t zefdp;%GWn4ub@t^M^}1K)6XBB@lpr#!e8s1Iu#3~m_nYK_!Ce@1J!v;!9bMKmGx=P zm{Qzu0a}%z!AmMfmH61sEJ5DIY_c@x8t`QlG5c9>?*?c*X z!t}9*GM&9y z!X>XRzLXarCx>>3v_(URRbYNB(Vi|aMHeXcHYi!(FF|+ayl)l*^$`D z!s5_cIJy}O+N$?Ycv5|z&q^y=fBFDHV8c{Pllohqo{_-byL^mw~`PB|)3vd!~J(>tQ=R8r_`4L1Bas&R0% zkKu{7(6;xFu6*^0B-9?y)|}7WJ=K-3Z}NJbJOBMD%P#gXz0BlS`_kG;R&X_Gl&s`Z{>`@|SK8?a^X) zukji8Z&FZkEi=s$K>Q|fr>%96w*oPs^3B%EmjG-2AXf`|BQGyi`&rNuKr^sHB1J?v zAfMREqNWVE{&gYSEdS%2&wlbv@1X-aL=X=nzrVBvtxi*rl3C`;x~$9nWqMsVUfl~X zRDAJg#`vhO{Q~ObhYMEAaW-7m-IwU}lh5F;>>=ielhs9bd$#v32QTHvEFZ7pP`oss znZORe1zV0l>d2X)-}q)KragtD3^fM@1p71|vG;WWdzL^^few_ILhh}L8(kahamS8Q zt(c@##Tu=SKZW`LlA0s3t4{#=ZrL_N(T!8I3HEt`{daB0zs6DS%AMw%99)r2Dd82{hD16e3djvA!?rMaC z4@o7;n{*v>hyWlxz?(m({N%P#4>vy_99$Z(Q!&9;{xb(uROaB$-MV}A7gr=QcbtSbIh@8ts#jdP{v6m6w&RUCu=6{q*_sdV`XpMbqU0Y6Ilt_-iW( zS2&&tUUaAEnM~IVXw&2uY{arAwINg+TLhAu_G)V8Kd4NR_Q`Q?j@hn@qewTqUe zvfo{pZXTk6;|@1Kfq;w$dK1*@D%(0hrH-DP z6X}pujp{j^aDyOIpfHRg;1B>NQXd9VK&U@UO8Q2di2VL`qIdX6H&|kXcXMVRMRW;H zV8X69k+J0U*&Z3lQ4v1L4gr0JrJ#zD!0bQWgVitm`HwW$Hkf_jFHmW8EZ8>9$H!qr z1V~3hJ%at~{1s;FOxWJw>8ejXgAjzMdD1V2Vn$dTiq=&(c9_{~BX3L@`7IQPnP?Xp zb<+p`Ch&!j|KsUrH1!>6b((-|;B6(Rq(sc^e_`nR6?4RDIC1MeSqq|pPON(YUJz{? zu$dF15OzH6NmOj?!D%V;5iEy+#6z#mnnz8x-8kw4K^gRclnQjjpcVGSv14bLoE?43 z2)*Mnb8Ku3#M|SktQl}i?-sf#kLW6TLB|KDRToIzVnk`vpmPV8{s0y3^*nQEa3~cB z#unlkklq6%1;TH5a}Z)@hOR&i3cOwuy%Q%a=*^yfdRCdKsUKoJKs*JXHvtW8VZ7Z* zRc~5|tx<&agr!3=TP8|8xqez1FZcrUZNPO#x#pY~(rj0VUPGE6 zxw*J3IQb$83@fDiaoAIL7Y;uMju`Fit2FRD!8FGN5kM$lbKkmiu#jdy9(aC)hq_o? z>WAE!8t7Y6&VaT10U8FuYlzw4WTHJLGUIBQw&cBy0HfK;jrIy;cC;a1e|Dc&*(nbT z)(Q)w1ZX1?@fN0!1fi`fF8Y-hJqrM5gJPr)a? zM!vZ$;~`nWX9?$m0LdVSBs zpEzfT{fO0$`^UGoX%!XqtW};dnyVq>)>8`?c1hd@oC-fg;t)`}&%V;pGQi`Xxryi^ zb(iA0p_McogIWtw?7*s@KL5M2qV~&ua={P`+o}8JnK$&U?B+RTvv}UD1!;e+x4Dgd zT-KLypX%-axk*3nsqbzLj2ivPZb0W$a!jpmVnWwJ~q$z?nVd5jd zX++T;6An5VauGMYkYhqW#ZdyC`|=)zxP|Sfz%D{5qvR z4j{s>l+Hwj8gm67S0XINLACR!Ilm%0u?*bStno*g0(}#S0)txyPGKs8mDd8fgTeDM z!qscaGRoso5Z?>KPA+i}1E~c>O=j#R_5|EzU^sDiK=zrZk61E% z<*o`z3hBkmhAe`B;P~yCXu_M&esK4uFh25aDamSh>7K%s%14W+Mej_jL*fFwY99zi zk5bLuEn~cZxu7aRdYo>fb7rHHQc!bW&DB}+?09=EB!_%@lJf1kAZSe*_gqgD8=L$> z2nD;s9jS}Gdwa73lm#&LIA6Txm-C7~@sSQu#;6@7cP@pG+(mY%LNyLB1or4bqf1Wq zH!A4=DB+EVLLA0$@40i}>>K4=?A8RBoCTS1wwU1(@;KA{rS4_OLO zgL6w$B(W@?4`ch1XbuCwS=V->=&Wa(OZ&LBkHdc<4I)9YmZt5~I$fMX{6X?%k##ph zdjk)M9!H!FF1yF`ru!U5&PWvDs3;s4@Q;n{ymrh=IV3qvQ!Xn)eZWMnW>si!kb9YO z8`aw)6(K^uLotV+=edUAnGW3e^1zzmJA%vs&GPi$M9QTsvzOW(SdZ?#2>^jTa7JGCsx=g!2bbq5(*H5is4UWb`~4EvqL&@?i>i}H7Pxw!xm}i#TNH2{fj=`y z;7x(fLuz}d)nI6u=etk_@e&!ueB3^*yP{ryE{!ZuivEJ(&Nb-P2`@yd#HT^oeXBJ$dtX_5Iw^#EynoLyd6;|iUV?glS0A@6HPN>!j&wi&2ryH{ z`}Yq}AR@iBTCTARpaKp`$SQkFR@2O+3b?C9qQ1FHR}idYrNJ!09;5l~=l-ZZoNd_b zelCqXmvOejI?8kEg;&eJIv1-|$Ou5inxbTfjLFS%g)CA6GpP{nmAE`}emAy0bcWcN zn2|;h^Bd;Yn9c_mapZ0Um8&$E$XJl{o_x|G1#y)SWSt@-ThRJ=$kM5V6ut$OpMvGFAZaZ17 zNJYmd5h9STZMuQThET1o*ogSLbD#i-D?kN;B$O|-#Bv>9A?(&#!!U^2wQe2Ut&C?Q z$3|9zIXiXkzuC4@)o%@rBb+9S)UJATu(Z7Ut@-%$duvJdo@n9>hI)qJh*sqy`DxQ;1t#Z#7K4bmrXC@^ZMt z@c1;0S_V3T3aK+NVM$OtY9_Of%~A9DqO{Yem-Bo=Y;5f~Qoqjp%~qYbu&|GlcPBcZ zIEC@b_o+JR2Zt@o2p0SUw;ri6iYBP~;xH{E>7*8*yY!1c3N#fVP>U~!^*aQO5H@3c z9;x8c7uvL6AQ;pWPbB7KHBd1ThCe9opEX^u(0qQ<=m<2}tJwaDae-repBYz|Dp)wo z8dfd*rVQQ}X9yDSvnw^;Ef&sk=*So(dgCICF|VRaWzes{RWu#gDS(FA_LC*94FEB~ zDKq-f0wCn*rJZGxP%hn#?ocxLJ z70++1z#j)7`W_kFEeKN}FRM{r)A#2$8flmR@nW*&@-EG;@@tb)oEhU|&3zRQ3A78(Gy`aJt#F+ol?MajR%&$In+nBuqr=c~blzViFR{^z>*jp=5lw zyK-6%tSb0~O0eq!0r_p;E-{9LkvT^*J=gtOP#-E>#N8?;rVE|4PDh!q`*y`^K?AEw zM+4q=P~rhOHc#^LJ>a`a#~MK`^AtcTPI_I1wMg89A?WGdrgWaH64mI2!5p@i#zqc* z^DHJBTqCg_WdWWHxj|8^}_o{{Z$;cpdFAn(!8^Y+Ee`^R&$#MIE2|xJTbO^}>3DmX&zP7o z>r0>W+m6Y&_>%{!_+8xGVIcR1ZfF}rzK*Fq4p4CNwj6n z;-VT5h2Ts(xdMAol!CrTy|BXXa#U!|*o>A;}XPth?b&z@Q-c!25`G9cWJ2{BZ;zQ{? z9Fks8TLkg1+PIQT-rh(-;&{Q*cn|?(e%@{Kl~_8}ck}C>{DS=L9H4xpEa0i}Q|N05 zfUr|_Zq^RX!x(En)i$%zZPwBrg_;NjAEE8OgDjRum9mn2Zm0|5u+*;P!%d~`ot*XK?I7ypdDKu-|BL#V`&fbJS)~UzgD(TR$C+UX|)Xk z)|Fkas0i2A;C$Gp?_#ZEDiDquNQqDG)_6pF6J&sNipUZ>{}0^NV(oIB@b$w#~ZkQHm>==O6C~S?WrQN?wj}D$$Ge7bDuu28i*V(MrZ^kbm<#EbhFZ_ zG&ORM4qs}cMs<9s_Pr{hYU~Yv+V>cXSjs+4S#(tT+mfTsrF{n2zo!lJf8%fAQkVU{ z4~0JxVD9%-7K|C-*-~8k?`=1gJWMU_wkun_BSu8bYhs>Pio=(SP`|v^eW90k0in#Q zBJomXgW-Ju6fVtP!xW;gA}ZLu*(OmIIQpyK&BNv{UVZ%R6F=8+-%)p3-*|Y!o*aZ> z$G8hVY!Zes;5T~k<#%)f05bCDOw8JCf(6;4)$sZ?qMhOqY)lDBBDWFCKR@hsoGtF1x zG0Cb9ma?44z77g&*oifK&E`iA)}oe-ctV=oT&O6Eekdbd=J2N=5XH45!VL;-LCnk! zJ?)(Cxs-~QNS$Y`?^38+RbM;xk1zVrJW)n_T(fDd+ge5G5_)yXvpqU69Yz~Sy2Mj7 zuN>_%W|nl3w4H!U#>S205Zt+KN;^8Bg8+|IWW$}`m@Ur+_w@C755FK(7b*}CA;8y6 zE`6RAcMILUfJA1m9Y(vhLG#P|F0h`efS%sYLbDRm>|ia2T>4+S)mRp*Nl(p50=u?4 zqd&BZsNx0B5H0|us%V}R(nnC4M8di?lCyL9ziUvet(OxDKt) zhet@ZD!CJ%)Ukr5F$Yt}P0t>UXT~c!Wp&f;brm&xy}aFFyL8BJWN@cZI9q-R*saS+ zI|&yM$eiupo$uh*b)8i+I8s-`WwE<);_V{PIiJ9~tMq}BjKve3<6Mbi+abK&>L$OR^~X-44u#b7&VNyD=YLL; zDoY%|JHmf&S-)~Vvib5*26!b$1<)2)&`z5uGzbc0e!&~Pd`RG9fey$v6`>3h82Pg| zxEHIKstCDRzBmZ%14R*PoGC@qtBuj0G+ZB*KZT;7UN-}s9h`^0LNtuu5Czs~3-TRk zi}P~9S8Kag{eFiI15{vI3W3W4^0^q4!-4gHlcnF*6g80@8(h^O&60sbSmPd(4O;k}^Jx=KU*rKKe|K zAEnlxY8OaC#k~dQ4pO%+tZ6JHGyN#E8jg!45dyEAfhQ*ex+xVv5$(HheT2`L>wT_@ z!1g!a;_E|s`9lnTny2G7kN+AeA^{vR&eQuwWS(A0YQ3_(0qDypPI*YR&p=inPZ+=U#!AVv5rSS!l;^U^K z33v_U)c`rVKl=)&2m9^Y0NFuWH7QHbH$$W&3(Q3Sx9%-%gy)`+d~UY6QY1j-5dc(R ztbSu3(q_$DPVycUBgk+n(W?0rwL0#m!c9oK3e#Cu=*!mQ`?R(f1DsDFDHkO@KqPf# z&O>}uoVDHZ2;?tL^+}TVkpsjvwQs2hvBH!c2rm4Wv>59Lxxz`?u##appe7&Ys(_gP zSG3+fScVgLFq$#?k34fCJ;R5BRzl7J1W#hlkMeAcylfcIxD z!?lE}#(v2jHWAByw>2e#{2HPtbWz!EZ8{PXb*1R(VWc2THA4JO$%ZgxJ)=S!JX*R2 z=`y5=!cjzbF0SW#>!XFPc#Sl4?b+8Qw_O#SC|~ZUv24yvXkG>(>^uid@cHK(Ym#+j z=3U=YJ-TXu

#9Atky%&UF-09uFSSmcu3{H^ae!q;mlDt1sK61_uQlpn;;N8&r25 zX)h?Ymf;-3EJNGLliMtN!#n0HY&57G!X-F<%j~>L2eEU2*3PEKK?DKUN<+a*DIy+V zl^S-mJVfUK`Xp&*V)dr&G9df2&n`Yt1DFi*0~E(`Q4^R&p?K5yB0P%X;tmnx3=T}s zoP~&v_U3zR`;Zrjp)Zmxa4^yc^{tfh?z&<(O|eSs*Et8exZ>@j0n_S|lNQpUA{#8% z-GfBnyq|1nWeQfarl)uh^oUAR{8NCe)7WRbV-KJqJUiZijuUA0(>((fi_BKOyWD%r2}7Y65TBuj zhh=pIB>9NYw8z)yt%#7nOmy=>ER)dt2ez5AjKDl1aXB?9y}V>-+xG1lt|e<0gyufO zDG$=bjz@x*7lIeWSZ5@X6Cio3jt&vo1ihN`+8uJzZf9gTXXAg`p{W-nbm7ip^!^zt zXE05&>sQx-&_~1fi)AaZ(XFvz^dfjhLIcazv}VcaSiXQ%Eui2AAF=hFCP=v^CBt<0 z2~seQ^`alpu&*w>-s(${oSt+;3W~|<2-GF#R-GN|Gs+(M^JaCPeM3V7X=lf4a>z`O ziru#DaFYQHnALezFj{jfnM!A0gVw96#zrQ<&L>ebL#HknktWrmcsY`F!!|N^%w=Lh z-g^kU(LQHyfyhIw6~;f-*T;g|Lr*71VE`>G$>)Q6QlT{ze^1zcdYwBFc^^Bhy7K|t zZTAzUFw+jJ6~~-Qc1cGAToiUROYQEkIUHGL<#%$y32a5ySYzL*vXO89noSMBXN1qp zS&PVT6s`We1lpCvOPs67{eqinYUF!n%PZwDERf(-k|kWE&^$H4kGsc$adTqZJ|4t2d0QD#j2Z0>AZ*Z#a8nrWrJ>2Hh}fBofDN6mkq zPMQB)HuZOdk7HpchvNj7M!r{X|3kaaUrjgizrQ`r76meAwM6nK>{lY(ky(Y0Rr18I zx&DA*wg^;!&;dNQk@PuWR`3yM@KDeV+zvBr4zHi7-0tDOZv$zsky#UU znJk`971Cd9U6Dqi9N8LNff={cv~v_1xQSbn?;>HLJG<~ezE{x}u(*QP$e}J9+tA(G zSn&~;{v=hpWe@@<-{p_D#$?mst^r;U)IJX1wwK-;QC6W>sMF5Q{g?)=afN{q@r?lWZNvk6uFf;DoT#GS0a zME3!LHPL5QTOUFe3H+tiy4kZqX6aNYTIqkmG)07hYM9`xpbbzz!2cGS3y|1ykYO3t zL3yoDL&j`AZym8CLwnOfT6NtOa`VeB^!A7<86Y2p6Jj433rG#rAf6|ouEU-aUoL}#xIAy zP($hu!?Wxru*~Vwn_%@IbGcYfI%<6?U`0NuqjNXa7D8YYi|N&%v1kF3w%U+H_VZDLoEYJhl9lr+0?~nY2@kVYVPJ&J{a(u=#pQo zl8K1YM}C?cFEW#^;kO9v}`k8QB}O=#zRz)RznW}t&371kyUZ{y7M?TEvlT+Ea+Fl!d$<8%DqJsF8k|` z>_0YBLr7f$JIX2)W$5nLwGknAsUfrP-QBF4Fc?HAM1q_YkzWC?yiawq@Zo^+=jb~p z^B|MMw1d%zk@jucsLQIA77w^#8{5~X7N)nHWOWELURLZrlHS-X?Iu$ES8wv#{)P7K z=j|X;t8Z6=T44g_!xeNfH6;tFLbPo{b~RP#5Hfkzc&~%{Kf7OdQJm~uijo(d?7 zX_QrwZu1&Ixigw7yPtF7D>1`m5QW`2=o$zQ9dQUlrXPdEo9fe}4n9Qy+yut3iie;% zIx(D+Fk9%-uA=^M`t+wjx*4BCN8tinYkcG|NGLK8-L7Kw;~*1JUTF|2qI}ISBFWC)-~QHGbIvu_j?&jvKXQoU5Ca3l z5tPPtLk5O@y72eY9|z!H3`gqH;m00dL-oHH%6iWd;l+MuRUK6ZhVppk?VF77n#oJU z!k2;Jq#yEk&$JUy5CcQY2fD7*`m;^$zRd0)-DwVgowVs|x99GZC&+JRuWV*Z&il5=3UsYd z1DP0T=T03WzGoI6`uoI%%wjm_M-Q1ZnHk;{CnvLJDTSIk_htK+?PXwKXZ<6SVZ%aQ z{qb}-)%u?!i{(Hw5|6tEQKku?2uj|fv!GReV*!IJ!GBA9-_l^nqX?0ux$m`fU8zW@70726RiqW_%I7iRQ-&fFgP zc}Ml$W!?L1|NibP{6BJDU+=O0pFdBvwtWS9;R{A?w{I_!?Wvu@*bQ^S=;#|R#ekpf zDm&%T(b3-rCg{t7xXOXuF5GsEZ#6Fw`9+cwWpRvY1U{M*ZJ8Z6R_W|M+nF?8Zm&M6 zyget2L)9Hq*;$RB8NiHJp{P@VIg)Af+f=^riaud%)5%({ygFRr5aaq~!_Bx=@!d6X zIDw&+2&$rc+Te6^=&*}0v-pG_UnyNNUnFupgJ3@4B{4gkqF`oh{QT{XTpt^DGtfs7 zH!#*BPheS!d_@yHw#CfA@FhorTaHU9#Ms~8zo@u)@a46~yeJP34}3*KgTlNSFY578 zu4pZm!w3A=dt^x?xSeXrLcX&{i%Uy&5{zwZmaV2fC{ZV8tcJvux4#`DsqDKyEAM1JR_rc#5U5}cfPlp z^6fPb{moG>1&67x!U5}6Xmn9cjZFB)Yo6iv51FMyDYxlA)m0LBr^42IP@emn=LlM~ z^z`()wc5yJ5sO=S>lHXkgPpRbK2NvLeBk6lU%pPpsi^D7R~(D{{Q>VY^N17kl-FaT zrUyOexMj0$Yio;LSa3rPnBiz9?uu=;+n;PT61c-R4CafThyVV-qiY_iOzV$#+oCLu zHwI!)^M>@`tcB*yY-@6a#Q(>(Ag8d|1gTM^`%aB=9z`wsDSEI>$RS zj%nqJ;m;3Pru$u?{e0co(_><7ouy1EkN;HNdmA=!rE?!1c8tIKSdT10Knpe9e`I`L2|A+PvpC_G0HY_n|?{ME~ z&euyCq4!AnF0%OZNm~ET4qcX?FM3j5t1!0DZg6~~$1`FOjb{rE4rU^uB3DBq9MSny zHprl^8jQO2_4Nt4){Oz5M01ovYow=DYdGzFD^oOhPxi-gDZ)NU40x!eeu@40E!k8| z_Y0~9?|}W}Q{JWNX3GRA*8$#np}tLOy0VE4CGcFT{mP=IQ)h!%D|@N-Rt9d9Q|#cVB;w`^#y~mV?`OCU-tEuUBuCsJWI=^de3~;t`*s; z>YL;5o7~`AgJSpd%gbw~S7nBRdT=QlaAkRUc}mLH?lQ$`zvV>@=IbQ#Hg61Q;VbTL zkg<{0aP_i;u*yS+4$<a5wmU65{PuD z{2C5l4(LJ{D`7@$BkAM^l0Ip!2}}1Eb&8E&m5T+q<4X)M7!1yDv;3f+O`GkH*;#ou zRQZ{YlR-U^MZ}R3i`U!R+uS^jepJ~(Z7+wm_YmKQ!h6!C6LMq3 z8a}6qV4TE5nTMT~*Ut#HnzI$~?EY>?wr|evW{#p+9^c6*jRZ{NlFWP&xAxbYZA|jk z5u3Ayx2<#~Y}Qw#n>od|6!mR_zA;u;S6l3qYopExLHi9d& z^lUbPTz}}m{qP0Dv61zzo^t#4%$O^rzJFHA305k=NppT+V1Qdz&B+NnIXRg-)fti@ zQ{U2JqZqKL@9OG`t4dGJSjW+daXw|5pPT%o4Vb_9k5~(QT1$O0vK^|k(ni`j`W&jG zM!CJ`!e@M`C0F4iER7bzr5rX|KU&$6ZHtNHRuV!r%%!_$7N6|RPScKD5@%qzDsk<+ zSA`yNyS^`643m{MMuIHr5|450Q{F0h{=TZiY2ZPNvXWT|v#I5xS~G5IYUSk7>{{`y zmE9drK^dj$btM%ik%7RLbuRbd^T@J!AN4R*i%erBLN2IKASs|RLWou|}|Jr030$>0MNL0D^ zU1A(*0lQu-8?UlcXR<4cnH;^a3;R7v5tBA)3m9tJ;ffcBN<`Ceb$ip|@Ys^TX^N@9 z`kKDvYqN@SVezJ4_oPY5mc@_Hs1NfXQBT6|EMSeTtv!yQWw+2~W+Sh=MoVj_i=^H0 z7f(i+&-(rR@@M$g1OcDGr}ce+e@1#2Lrm-`GE09ElQTjmpP!;Z!N*>EeAL3IUZCq5 za`JerEp}<5Rv7uXjlTX103k?i9B5ajT%I>G#OKVLc_s|+^1wgRASY(jRsHwWH|aZK z^M66&V|ceEG5s%IyvFr^0+IeNu&{$@P(@i+{c+?Q-%U`GTzl2nd0o8!#myEGxSW5% z=TFA}36#D&*UDbd8uK4u+RFYPfEx3E8+QLMF7p2mz`wRdx9)uyWQ#&Y%|Xr4;C)q8 zBsA}4W>lbS;_Y32^sL;A+Ubz4`Vb9^3Wq3OS3u3ZCLbOVRv;NyK2J$0$jm&8G7JrE zG%ZEXY6B&_v#!y$Pk<$;j!5bWx_R^EjkvRg`T6|SH8l!m1*O=#gG;ppv7EjF7pWrW zoNzoGnArDD(5Sswd^-ZiDvHj%dhP}ME>S>FGeI}|O5qVs8M(w`sKU(nsJNBMdf%j+ z98bnXQBhHVL3;6z_r$P?n_gmnVu>FZcxB%n=h~O8vKJon5F~FTRpPVvh49AP|r)@EP)A@T2$UJF)=ABD&mk)P2|mz_ia;{ zN2AfX`{(lqzkiA`0kjDVL<+ro^{S*(_ZK+-td2bMuXZ(Tf9yB5vMN!FVJ&?7_DkB3 z#Lf5n)m|H*2GrQBe^@EmH7#RDHg3RO@ijO`M9%B!nG3L#^+WYr;Y0cYx|#YW zCP|d#sf=HPW=8qi2D-X&92^{e+rPc%7pl^>Yinx@lKPrMsS87eMo8-O9e&Dk^f4c5 zqSiC8Y)u4Nbf=#5yv4=aOOy3RkQRG~KfLcq6e#r-i}-cYbMGHK=JxUL6YzPuVPDf)1I}iUjg=KG>LV{N?=5QRlts_{719J1 zXzs9i%;09XUt{Z6rv?l8MzgFwIF~&05&6*C3P@9yt+S3P)=r{&xz*Js!^6YT*UztQ zhBW}&$wHOboj)1%bF|#vP$ZSZ1@g6f$c2+p7X<|7GZ!xa4C%X5Ef?%j&h+?0x?*4% ztbwD_FqgF3a{&G&Qha=T4aEEmK#Zjs)9>H^_3*>DI=xo{Bk=F(^1k`Vin$Kv3!Xjd z4(pI`YGm)NzDQX4oyEQ#ZMez$!NK)nO~3vc9vPXa8TVNI{s~Z^t`#>hCx6Jv&W7$h z2#Gp;z-T-I;sdE6!RvEyxMBb@TwGk}w{~~o9}~SIo4qiR@D*-uZiW^XY0qDLA_CQT zJCK}`QvBwP2C`o5n&EObg%}+6y-^9{XhF(O9N5{{R2;n@Dz=Lqd*-t3<#(h7P3#pxA>FruHC7Z)1_P!baRxm z-tIUjK&eTet`dTC5IS{8P*HIr{(k{MIP~~K*@U==$k07T=91NOa~@Z+}?( z5_{FXH`n=fGv7RVbYL?~xhGr65}=%$t1E<{uBN>`?f$0X($W%>z^_YPZE;*At0etv z*Y2MZmTlC(=#UhvlokB+vi?6I9^l-YX<%fO$giFHLjU3qt0N2y2VSbO$(?3p6;e^L z?RPOIjbLjJ{KQ%}n!<}upFZJZZ@{str>}e?)cY1xcZV(h_3~+FS67~S*ZU%qVq+7N zJd+kW!`rsVI1~#q8n3hv=rDa`NTHE>>}y zvw?@TZJtE22%yP+OXJnR19J*r=PPSf43ye5qX7jQim>ZB5L&|Vxu;-N#^2t&Km2~~ z@D&MBi(j65&*t>a!}`4X`d5ttrneD~HznPDSO165Kg;vTRa$c>=@B zHSI?V*Yk}NfOYVqLMe;om@B-6_4O8>IC{-c`sX*z^dTF2R+r5HGFn1@xVAxuu*p88=6M5cE*9B(_p zBkz-Yuk{6Tk?;eO?-{C6Ba|2m@~6pPU96L-w8^2NQ)XD?n_Q%X;4kJNO*M)pMG%z4hLOsE7=bOX3y#hIXBQuYr`gL4wY_d;z;TIL(IFI5e(XC&L|-SjWd^k>pYj|hIu{>m2( zcz6t(yUM!YA9-q+H9<`4NXx!=AG0Mq(?{JNrC zAghS^3kVa?mSk-Nhp&Fo$*+z7(H)#Da_QF=-EeVI_aV{LHPYqgikquvRLk}n>_>g+ zfA@IQA^`_GdB`mdgv9$JcNldGD^$`5b>8;x^*l>?Fr@}gTlsu;Z+znDUOSE0%n9F} ziA#f*v9`ErjvSNOo3~RYRu@Q=KIy?(k^VYfN!NFUMg^J02afo*@VcF-|NT9N@0fU? zO#9mBXBY4igK826F;)F3-nVUnr);srEVQNN@X%1M-KEsGaez-+?Y}VU&Iw{7B3knG za+a;Kp4ZC@iilKYZ}8u$;W>OjI&j%)enGYG$x@n(2YPbt`bry0y)qJk?u~geL86pd}2XIAAi7K9tEwY`pO9$ z0UI5Ci1EHEyr*u%X|Ac-eT3o?E5qV4djE~~I#L7$Zt+L`T)|gE!I_HKS}H0j(I%el z@(Tgwxj~i6EwCPujzpN`S4h^bkfMde#m!JC)cYkrKfj*|T4G4?*VNJ~U3u`~CW1pk z);tLj0E{Mfo(mdnb`U>!ZVp0@0qa^;ukOeExf+A=7TU^g`i(AhJ7wMcAf%o z*QOM#M-Iwsr2Fv-c{aWuHC~#tR*SAqO?v+PBbQMlz`2E2F=B?0NcmE%UI8*lN=dP_ zt_)b7JVR9$N__liv@s0OhKcMU`;|?Uv6-PG;W6lj=C5zWLVXFCl(!>L6jz#FfB$|9 z&g%v!6Q(;c(b2i1>{+1sSP*r_Qhm}S9HYzX=QtSm?g1zTCC6=dhi+JMx)RnB$vcR2 za^%DOIuVwu|Bb=xlP%9jcWmA|w08?*w@A{>@{i_z3z@2Shb}lMQuv!wW*p6IY|2(= z+TDlV7$`(+2fZKrYe^!Do8it&%$I68!GIaGk&*qBemdumtLL6>%+=M`%VRp7*0UBD z7r9yVc_$(+$;9zn)K(d%vW=z3*SGd|bd)Fagpo@^cXqox6 zLH}YdG6Bll1G&iAv#l2AJ|1S0M`Sa&4(@nv>pP+^efO?(K5_5=M z7fKA|oi|XPRFztx$HdO<;?41Wd}0EWXk$xDtuGJO4I|?b@~80txZSk@K;C>Pz~#Lr zaAbPifBGk1OrVZH9|igub{fKhg8fk3r9(DcvaSS6%mxbFv`ZCB0u(WntrR*mIk~94 zm*L&hOSgV}ex{Yh{5XbBD;Z$QvEN!Zwz~BDBF}@iJPaB%7Pd0L-jR9^jWi%dfHpvw zF9UV}fra3tYMX~2ZUW}I1`Q(}+M4x74k+aSMAc{7VvRsn|L6|n^O|v+WoAf*#Awqy ziT;M2w*bme10XeI6<-ks2m@&i5}1^owrFWETG80*`^**_wMVrh{~H zTp|68SO;do7vzohgv0hkfDho`!ra_kJ>uYHNWREw-MxAavxU6z5HmBvn3OYl)?bZ7 z@m4;l1329DOV!N}2lQmWInmbQ;*QQ2?eT4~)`LV}?LBjYBnP<#x_F9-dl)XgIU)Dw zOUOP@6orV+Z#kf*!%pSkNndH2pqRvC+K#sp^FQ<)RYY7pJ>cuG;fH#2a-T*Sv zYx4Q+zf#I)$TzUuzGVj(?DQ{qy?;9ZwFsE6DZES2-)KEuc@P2>&gQkKWz9!X6-cVQ zWS7(H>C?i4uN)fY&UiMhBEfa9)o#F4KoLjqtS*CkN~j-~tSt45vv7BJM-#5?%K80# z`VTQf_WWVD`e=ZNEtSZBOL$GJ+Q%ELUa$Yam3HltHvT%@U zyVku3Du;xl)XB%?lyiZ*JrZ~}<+3i4Hh>I;DcfS(YsEu~Bcp13FZ?Cuw9#@$azF;-|M;|86ATTQ-YQPVD1dniSLMv67SI>PR9npl4kY0XOS!o24;Ww|*2BKtdro4S#%#GKEBIho3b+;G3di59lf`jGO z8Zby$oqKgv#2#0936P_z@>RCFKOGlIiwoo{=8A%qmP(^w2S}AzXJoe z7)Ndhjfeprd!@=L2V1_~e;t%2Jd_Jwbwbdf^c={q(IhwI5=pyLQnIp^vT<{QZVmsX zDp8zO)02}WkSr`Kj{G#^Stoq?@&d^OK+kkXdy2$?DHa0_rT&)lY=RPeBI^40hCP6- z(1{0lH6xXwWEosyHvLzcq* zv%Whr($b%@aF#W)Rc1SW*1cLI>o^7;nRzwnVE=% zp<{K%bB7>bY3ezps$JUzWzRfEORWB5nusXSYQsfTY50~_vPgNG#pwM?zcrQP5G#tDi&*o=!V+)HyXyVu1v47!@kRU#XUc&X(IM>sXd!B`--J0?sz$sQ&Rk=V} zhMs5AE$a(=7}(>Wjh@vNn8#ZI$><^U?#koEHOMzU#1iud0E9F&G(5;@l_Fl1fR>f8 zS=r*M_gu3Ib!5M}ADQUXhJ)|-AhalzG5&c1OEkI}_X!cNfQKTYp&OHo>=bbHsI55b zi>E614-?}tAp!ZbGgbh;@UVYPAjfLl4zmS1fe5Go^PSiJ>=}9t8ys*bAn_XjJ-v^q z>t-o9Zr#wcX+-a3xMU7uzl5lI6q>6$*6e%~COV|CJYa`ian~cYoCgShJZJpVg}TSr zw{AK|`ZRjav^~hVuGgKl>Aw^DRx>b?rQ_rNz1N08(ea=1AF)t<>KpKv0Gzu2;^<{T z6cr^Yc-6CAmSt)~`&@QnqNLq?RP!+3Gtep^aT)+FLf8A`N#|cwQNgKGO%-cNsQff0 zWo<8a=Qym=af$iH`hb;*T0MxtL;LsQC2CiF*lfefpTFll38h8m%&|;uYB3_Z?CgRL zfd8F+U8M>UqY|$^`0G#MpOKh*Wtz*q?FgSXEiK!`w71|&PM*XHoAhHnq;iBf|W`ZUEqXbw^_eG>pfWjf3K|Ulud$SazCYMqu6r08+a-giz2jv=mmc?WKAS(MWp-enW zz1F;xI;7Th^O#upKQaal7U-pjQ_}BT7j1*aG5%V4O-)VRay4d8#Tm0>_k>H)6mBX0`M2n5yHe{$Jk47SKpN6^8=LNUo|yO= zN~Al#_*Uaz-Hp!L=)@GLSnk@ofOTX%#!m%aV?Xq;%BBB2$?5&%?;k&YxRCIr-m+|S zS<)4=sPfBuva+(gC7pwNa9MP^6rDW%^7@LC_l#qtPWBRUu^n%*Yy;u70By~R9i@Op zbJ)BP59U*s0~bec(vM(?ON%SBsDLL;6+DBm91ra2iz{aVO^6NC?Dg2-IuaA@tN)-< zl(x1)cGgvP2g#4dV*nGPvBKuS39zL$x|F~uc~TwyitMaBd;wqsi(_Vs3fh_#!2xp1FlvBk6gnPNxdJ@WjE^xcB|9)N>ETAe8z$j#6`k4i zb16#jQfg{)3}jSDN{VI|KEUQLYo?$X?M0JeQK1BTujp!ita>ZQlX^~4TNvjJ>d%P% zeuj5;Qs+c<-+4*h`uK-n$I#~ICdht}CtSgzf~e2V&IQshRnG&{fUv1;$Rp#?k9Js| z^w^Cb5FYr!7P%sT(lSndo+5G9X_mYE7mVybOAqB6mcaR-5 zzo6W;LAm^P?%$3T2;gv6x6t&7~D$fjUsv9q+5(~rFLBLLz^(<;g~_jJ}*rmwwIrO(8TwC3yZl_e4O%NskM| zOPsReEjNlIHr2Q$>DHvJ4BIWI_daL3F*aeb*_+fpi*`PP9cJcxv>#c_{_Ee}OC0kv zZG$&?z7IsK^*$`3&(!*f1Zby3kj1~_?d?vnvKHm$UXK8lQ)C7qUk#a}tcB(_Ulj3d zfil>$yZH`)@$zJS!)&r;6|9A*Ma6Y+9zin)GqA=XG7I^-q)*@ZUOsdZ5!eb{%jN?* zYx=u`Nrg+tl4+9W!Gbv;nl7m9uB$+>2%w-}0DpQN-UZuh9Mn~huhB@zw^kaf?=-Zr zIfrt)6864cQ?kIe2>PO03GdBV<;~jVy?(vf*}(rvlKfN3G}624ES<8sm4y=BU0+t~ zRZ}{vgumsn{;u_PLN0u$onGo-IM%`|N?)-3Nz4f|9kEt4NhraYTnTR4`JOCKqca~< zz)Ac(#k!x|*|qzkAacz@v}M)J`f~NvgGae_f~#POikg66c>dYnkbX}=FA^G+2pIwx-itk)z6LzFLiw5n^dC=4d5pgObC&hKF)6Y^ zqMF`n7f^$9B9P_N=@B3|3q)dFeYpp^H*JRpJa;s zVBZ3%IPbK|*8QFN`N&&IyN@wH2?aTyGeI)|GU~9{CNns}vkV9u*aGmL>VPFQk{y8z zp&J8AAwMH6*Ea3LcM=kor*dCl2@z z7RzmEH&g@J2=;AHDv~o;GfZ&Xx2!_M(YpR0>7n>1C+QPZ6_$}DG1=NJPi`grl!9Y- znuQQ5B-}S^I;7a3g3+kZ+=#5+yhdo`MQtXw$(vc08rswl)rux|C(Mh7u%^vrTRcJh zm?@*ardMn3EhW+>kxwj@N5fWDai*(3R%wHlk2hL(SN~3qST}Q%d)`FqR%2t#9W7sq zWvYwEg$iMUG0PgHU7pa5-a4^J_AtmP^HxJxiDvq@+dn=p`w~G!^WI|!Im{-6$OoY` zVR*qvyX!9nfBCGHpl6VYBDoZXrkI_ek=bkVF8I%x#B19-4-Z;f`nFJitgzIat=oj0 zKt?t;5=^4o?_^6NwFcA}sTv8=H$HDqyn*B(1rf$}dh#`HYx@@c!?oHs3sg|S3L=lE zEGMPxs+wtweqqC{`6`jSg}q7tBsSYgiFVo+#gP!?khHu@kR_E)#Wt*d==zT58&5vD zsCV9`#@77!5PpQ`8Lv*px<0nG%}(0=MpQ&CZBLehKbo0URL7O)B-i?N$56;u8ykAc z#rqD%FGQ`F5tHM)2mD8LhpE}y%{D>aF)iz*dOxEJ8PU57mJPFUE9MiL>JT}anwp@< z0Z`#Z>FDT;BLW=f<9gqDq^}3)!SHs8+N(W7NLLx$s|yPYh))T$3j`_rTdkFxy4TXD zp(iRNCT4o>3)l0Ss;Zx$-J%+|b1QKC;+V|)t8D*hqY<}n{wo%<*LJT^Nf&rF|K@dt zR-6)A2Czce+S(fTz8^+YEhF0*8-QKW(9)AkOUeOX24d*z9ln+jo-~zotSMHv3!Se*YkEG26 z6o%X@I7|~)2dRz~Y5p;@is(a=8#p2Y^T2>tXDTK>LG@|YtljziVO7&PviVm9E}-xS zPJGs$?a;#wFahgp{waFttYg)u!nfysa!8>JXCFJuvE@0A4<`d5V6Q~Fwr694?AnZyuIPN$MW+G`}s2xVWf zA#Bd;{cLbAaHAJ{5`Q-qY>;fXo6AzsFLHLm!gKED69)?{=^cuSiXeOrO;48r$v}i` zr32%p#>N}$EGMC_1VPU28Vl(X6k+I36bq|?hyiW2ui8Sv+P0v~fF5-9oZXS<$M)}q zTEsM1(0~KxSzf~ydn0f3Sc`>|vMwU*;6Zy(G_yq7TBD;==~m|EKdn4OCH3@UjcZq= zcLB2@vcHdykCeY#AExFXd6Nhla<9p?t{^OL3a7uf&26+T9wk9aL9ny-3IU zoF5w-gKvh8cWq5tP7W5_DdgbAMYy;?wQYcazJ;kZAu4HPOqBa(*hzSlJmjI3|4e#g~Y`1s9^HIVNjLNY=etvmgdg|2|4;mrw%Xs;RWzq z4=oHAmwNBhJbCH!wUERd7b&;df}$c#K)og)#Cm&sPkxOM-KZ+Q zo$tE(i$?wD-b#a|!DWdGsvRE+GL(1luZr*sNhA{mayto$)xl?-JL!=H>AQZN2e0a# zIg)uGnyIO?i`m$6Ldkxzs#w51>~={^Vw&oTtoZGkb~s53|=@7vy*&qNvCiX0$Opi%NyZG$pDcSDApqZZKGW&SZMk55N6%jlK zM|M`_V{sS1yjJTHX1OFIBSZN~DR=B*Ew!u_E3;HrRi%nNh1~4jRr}u_e#)gkJX~F) zNNvsyAJQ;Bx`p|&n+Vaeib&7MAX6qhwQ7=2=9S~pD0oXxL5^4<@U2XBr*b}p4qUEv zrNm9}pGDtz4V{p`tRlpks~R06UaZet(PIgxDa=>^`vWUQF&NT>?;s6aM@Pqa&eokT zAPeT_FL&HQd_(hYf;9vRjW9m$##l|EEha(u)d3MtttOO~mPU`FooVNXNl9kmN;dN$ zkz47J4AYKMUNob7Vz;AGUF!y){cQB`D41~?_YKIC9DF(qjh6mhC4MHa^4vu8Z%GRF! zn^}Lvm~LQ#BM6P%<3pvNWqy@ad66=g7P*_*vfh{TC3Vt(_T4O^O#k9P;5B?cN9AQH zR%O6_tl_fCi;jj|InM-W9p{c7D@d%r%O&Xqq(ebbF)Jn{$qnKIsZpXQ^75uwN=7|( zo53r5$-i$p!45O36Ek$x)x)D2v#_N4p?)EM9$C$V*y3NW!1x8?W7#32-{Aw zTJf}9KlZK>vXp02Jyu<|{<@5(?(TW}hL=-Kzc~;TiEXK|gv?PgC2CYgBZ@zN7Yd?2ALhOl;Y|t&x&B7ntxl)aZu_4!lv(&Nbar2BY z_Aj<0ImdFLbtzEX!&hve*L+yE@gOe*2csLxg4v(v1xc%d!Z z3@Q+JqQ~I}Ujuf7zK+p5VM5A1vmmdRw(63iHV7C8Kq5-YAtsbu~TwlpDn}| zWYxDy`73kX-weCV((^U^{$^0#cdH*b?9}nQFU4NpP2^QtE8VTKk;wRb_r5w=MP-*| z{`>Q^l&>~2v$x#G3XQnDOGV}mSk}0HZhvxS`1R~3uZ-_oobe?Cpf~w{8rnOOk|%RE z+GRbN-f+w9E;-`m&d>yf5agRPd_HBN%jY1cZx{<>>zsM|sy4;-LsmO}zwulhr}*xO zZum+Efz)d4$c)8#0xYG9g+B<{ISC0T5kjt< z`u!kUAimbASutXp&Z#5mI}P=!8g0`(U!YA$4s z$rYWEA4ZgoJS}@VA~ck0UJ@hFhRf*MEGsZh%SeWv55QFgGpe0aPzI9F%*qg)GssV+ zvV5FQ#eo$!$LlICafB}2t>bs|=1r_@K2c(d%&(VyJBb8+k+X#Z^U}LcS9*XXlyaV^ z<)plHfrb&2fXl@v&Fp67V=b9Y$@5VxE4an+!>M{ngcUPrJ_8(qK2Kr|Ep54=S%>=@ zIqb~E{7@HLH1$z}F{$q=Hx};Fe>^ga(t0+z8N0?^0w*NP+~jPqcZ?mjm2`D;ntWfz zak~?1Q_7SnKeK2<0%b-<>nKvQ_FR^d(->0sIX#yvr)w9M~rA=mM@;xN?0#68b zggQ6nn~87s_4b-NJ3GfO@oHgtw~EcF@qpMYT3>F03o)(+GvzjQ4%|Sb#}g%e(EbHb z=x-mo_M?M)#;02`t9w7EXnEjUIq>WluX_e=E!B3-uNO8qTLTD0hRxo(dsmFi0*;49 zOxy50xauB=x9U`1=?V4M=BQjkMC~W)|BBkV&{`lV=~6t>8G5tDPOMvxQ5+XX%g1Xx zEUi-d9LOqTn-a(Kb+d|~yLyo$)(vz{l;xjIL%VPzt^J2h5=sy2)blE+|M1?@To2(p zMpoyJGgH`dcgCuKrpkn6A})FsZPu}urBSTH;ERFc4Gk;!?wTYLc zJGc1PXokZ?O0J>`eP8&huu3hO-W|~XBW_?$bc?(ex#Sn&sK5EMoyTZ+rM9qeGdGC} zG?3Dzn4FpYJ0c0;2ZyXreF3_u-qViW!0k|@tM2oEx|apAD5=mBoTAFmuuy8~Gycb} zqbpi2nAEc+52|WNx3TQ;gjtp2f0(P(73S*I;G&P%5#HXs7Qf=)?CcH=F4G2>`Keo) z{n+LKeFF0??UWmel7jco{PskLWe!Y5z>-MH{sf@*p(bM*F-IXj`}Ta=(eZ_K;OQ)g z;+2hUp%o2_inE7~`DD#F7Qwsmf#c)jC11yGOF|DAFe@NZ9S$i${At7&6y4_Jdbkb! zrlPWPW`M7Fx1%@Z?k|8k7UW$-*B)Q{k+&0nR(=5Oli~Br7**ZT=yKt;sIE!Ab z2>cMBD&*1<+%S(Jv@lZEE+b+!qYDU~XOc&R&z;_fjEDThFj`i*JllKs>VUwPtC6c) z^ajefdnxBG=ykA{Mv_lv610oU5Pf>#aIgD+obSgOp2{P18HVZr6C+BZE`WN|Z%yhj=yCWC>^bN>DPh_^!mtB~ zi%A%8*B{;kLhmJp#eFzM1%-`X#g)uNs>U9MI~)I*!HC(D^RIj85yyYWug#PgeyRb@ zhiq5U|609Z<5ky7CvbZkE`E9qSBs+g7&9>R2JY9rbFjI2tXU444)%LHl*t zP#2sWiT8^0n4>FsQT+uC8`Et+8fCuIL}KfdwJcZ~cf$kBQl_`CVp&t)w8un;H!jRM zxqeiycrLBGpzvpNZHv|lT`X9+NkSH{3nOzQ8Dq#|q)DiOP6+OVL|)R7IZjzj)d1f_ z3#t(uPU|5HKU%rvkYo#8e!#UMlriV5;!-^0r)gI4_`8V{lvp@K>{)q3fYH}#T8yD< z_pfakj2%q(nT&Ws65oU&0~gTn1KWW{`MNtGWTjr)`7VLeTA|Re9KpZj#MG%Gr@)JN z_PUZqdwE&GF$t5`0}528YzBs(uAk$*8@>v;4#|o=UAbUk`sGJkpn7sxZQwyw=VN|_ zqz8Vg7RePVp?AgVI@1)$8x|=61wEa_qp5!AwQydo3v>C&;^O}r#$a|AA?Q%skYsfB zsA8hf*`uTeQdwnoraBnRp;dGIk2la~l%4dtzb@=OQCnaQTNPRwLuj%{`vDEdrHyHTq)~_c(FjR}2jFQ8>g1&w+928+y^CM5r zNJ@dx$=OGcRU~Z*I5c9x?0=;uBqHL+U#*>bNfiX31iyYYHjtSC`VP0na+cCX#Kq^Y z9AtQR^COV?6a_X)V@&R%p3RFz#mXOB8p&b17ql+yh-g{-NnF%*zU3)aC#A)v-7_$z zQrPG?|CgY0TUlwzu{uxI*jj?z+2p?%To&e3(v(Gex64Lr5jG@R?(*#14&td)BO*aSU`aO zvA*f|Q~%z3rDNdeL8e;}!zN5e`}*gkt?31Bg;JM?A$E`{6J+f2X_m-E4c_4;J=nak zrfx1SU%;oCReZ2HP0|^d{N-_6Bo0g*S;eA=r4J@Bs{>bTKy^WSryrwOz{FCKJOM%s zth_Ks?80n{ExyKMqAHY%K@Gs~LFgqz7I*_w=M_ma|6AiNf?V^Ek58XEY9MB_q zLz{%5%QqH7`UpD{IdOYkE?!A2j(uZGm|Q zt@6k06ifgx12Y(47Ra8^&_tEn37wvM`T1j1 zc|-?H?Qs0fTCj-g8DMoYlU;>MfuI5Xb^!=?0y)df@tdDtxUN|J7F?UJ*jV9Xv1g9`<4i- zGzPBV!JR1;xf2Fs>^jh7gY7};KP>`tJkUu(I%wo6gV#3-3kwCsvToTcB5n>)Wq}_ zQOisa;*f_jz{n6{QhKSc0fRS7-e;E_-IT$3pcI#rSlPmxxIh6v4l+LtgFu#h!T?N9 zQbCj>Q?+TJ32(4ZTtGqZbtDHykdd(?I`_Mc{M_7+3T+v(o&jaLLP_|~7L`t@1TYMb z&d9+`FB&Fu20*zeU7_NA=GQlo5qC#tXUkI4He_-S>}UVqX`KiKV2>8oOj8Tsv7JwB zk*3zwzX=t2nxXw%B|V0NqYH`x8Lgy1F{swF{_!wN1RaB&xHoPfxC``*~qU zV5FA+7G+gAKW?;rE;YU!LPGee_7KOdw%N1tJ|FAdu5Q#|iC`Xkc56b%PdVKYcDz4K zT34Nd8KSz`m-?SMR2=nE+?WkLS>UNBUdmlAU!`toy6t(ER)~4A$qLo?V52~UM&6c{ z5b-sRIFRO zP!6cQ|6hb@|0%91(&1X=!Th=e( zMRf?-4L*igTBB!2IIXc6LRpYjT)TwHS5!f++gG7nrC>fl?1Kaly6{sfHX zqz(MOz~Ysr_saBS0RR%=cU}Sg3o*#Bj_i}U19~+DKjEnZ3Asw4l#j8W5Z4|&pFlM4 zlD#=Ju7*XI;n@dIES=GNz!x0qr!`*T7z3m7DPD)o!A@rtGMFTilrcTMW`F(sv$|z> zkO54eeyhP<>i~)i>WTEt_YdkaXj9J;P8Yz83#&ontny}Xj?eSjyQGgD~^rZG;Yv|ZYRt}wmhAiHFPUTykO zAe&!e$kh8N8rng^e^(KPa=I`fY0E`(neRUR#J*_LzP23p<;6`_zkLjszDRJ$`7f=7Nl#-DtDk~HF)~@XR4$?Y^-iVX4Z6t`vk7g7(*S`Pn@H6%@>}gTQyPx=0#P)Ii z1lwN6-b}x=ko4P)PK)W`XU#peW%WY8c&^Y~JxydP-SY>|>jWypBdK5?@}gFnN9pHB z9U9^^`fZO|eRbgXdwY*NgPH$RJ~v@2BBCi@rBNq($2mm-H^Il1SaIuvfkMtow%FAE zC^oBUs;Pj$pu#OQFNnsaUpxFzT1m}nhzkMT9O55O>^^v}19waE86R!b@{jHwDq@3O zRc(&#xjZ2&YDw>Lj|j0pK&1u>!>LE@{J4EYJNM;FRp60`iyL4jP-z%93+!zmj_u3b zIeK0@+_&bC*1#t=TajS)Yc31P&C2`j2cK?*wQ!4e-Kg;Pf7GE~wC5~j^_V9Ibs=Rt zw*=NW7Y`7ZT^stgU+g-kl6pcd?eA)hZB@<);+u6}=a#Wd1?wu(SEfCmCEOM@?Va|D z3sfQ_?Mux#R;KmkJg^bF)Aes*ZmomwByFFO_dg!Lp8YIQsY?g%w?0YME80YTT%i_& zAG&o^YL-5H$Q~_}nW(dIaEm#~h^f2#cPaQ1EM=GJT<1b=HXI8H|N6DfFDFC7QPWDF z6^3sWZuX8jERz4^hy~|KD;XKq<_;@?y&UoktMs?#$0x#9Qf7~VdFlBqb?abRy?_ik zXryqu{f}VpR+E9hGp3KZh^3xlc8Sxlh6xSIbj)gGAFzfSR&4H~3SS`9EIK(xn#E|w zX7Ox9n1z%5PFuG4-4N#&h>|kG=DJ1 z73poZuKH^OQa(OR0G^v*{i~ajHSzNp7$X}Nik69g^z>LluLyK*|Fs_|a8k6c#$x8^ zDn36{6csHItKZZ?XyM+T($5Ar5K^M{?}ejRwp~X&^#C;RI=3s9gp>Qgtb*PZ12a)m z@cQ@8ZgUvMKSes^8q^an7#XUpZ6Uv2YChc)TXwsB$VMe0sdUq_g6lCnP{a-K)O|b! zlS8KtxdO!i8mF`{330~Kl0t-bMhfH$D7irQ5ucv#!1rA9;%?w4kk_g)Qw_N@*^B<; zXDyw%eDH~#oto~qt$9zDw-lH&xQc5TMRu<~D^N{^+%rPnDs&2%b%AFn?Fn z+yt_)069sk!KTI+Ze#Y~+Cc`pOP#-&y|NmPqO6q&TWK}SVoMmNg`-XtxubQPB9YWC z*UC1>!eW^n$2#Z00Gyw!yA`!7xbjBeLFtv!sOA!Ut9wXeS#4g)vnf$iw&zZTq|{T^ z!KT(zEboI&*+W&`U>ez9RCk{?*Y~1w)J~s*KNVQ)eVAzg(9#46_F0QZG>VSai8PhorFQ}I(DV&Ql4i$Yt1#+TEG8)%9M>Cl&Ufs??sc0n=IQCc5JksaUnrON2zYI^Z-!5!@30_ z)JTv9@}BnUTWgU1L`t!NMC$nZ_FiUWE#az$xOm<3C*`n^aQCfG?X1L3Z^&k>TYal^ zmxYr%ZKv>L+DK= z!m#-RLIiZUAr+KIQkp-O%9Supwu2lFbgHjl`kouvK<6sWrXL$qk;uU5dVQ!r>I@06+p}m&ljouyC5vR*yj&2j=f+^7rg~W-*a_rseI+B zoC6xL0VZkd1U?}zj(u7ACHl2~{-;l$Ui$R;);$je`taOq0PmI{!|gcyk`c%Tum36N z?|+FH{Fl5Ld{2nT6Xm+jTIq7_8&X*j&BDeG15f9;EWT(A&pFNFMUIU&L3!^zPtUiw z6npY&hu=2H!OaqWf!Bvf5)+>6_3C1O&Lp)TX*j7{Y`m%{z=YG%2?)5K{8X*K*ZGCj z6=iJEoeXveNTkC@Cv2~kFyo4p`5e2=l9c#f3O~yg8Xu%)Y-!3~w7h4AlXBjEH)2M{ z^`OGditXd#X?$Q7<|`*P*tjz}q|CZ~G>Hv{6M9K=KGQMy%RTuuq#Cy#=fkWmH$ut` zw#c-<4@d{&Y)mN2s=WJL7fg9{a=NHewrHze^fBf`(*r>E*EzTo8 zH}@38&STv~WpYVrGr(#(R>F55y);)(@;XX5ssBe9b96p0`=CiI>BX){wg%%0u_%8- zSQVy_!ZXvY`~6UPjE`;ftE=K|ZV7rjPmQ(tmKzY-+B?rnQxy$|7aN`)KFtzLTgVqP z3B=eoW_e`^gdeORe(KQdIgpEkR*kNA+hpZVwiQsgniIfz;T3B?Jm>_sCCRpt+Pcr; z%VLACc>Z@8sY{m^=o*OuMsCWcxzUO1*G_2%2GiSs>z+LmxAu&+-3@|#4G9lsc%GN!i<;U(mJM^(qqy?P_a?&LMod6~$F{oazU7mMZSC;%t zHTtu8A}Qolm;(DEWAUh$mv@R6jmqvSecHhBtJjz8PYzAMPbW0UI`x>~vc}5;Buop% zy%){!2dB+B*3&K#T7k@5V(LNLXuT_$E!7S}u33}Sj|JU?T2VJ0#LcgVbNr6ri12y- z1tIfm5w%u%XX0gJUuBGcA|%W)cPdZSr4A6^0dY&x#o^hiF{Oe64rz?@btqg5G7dpnjLzaB3v$pYZ zuL`f*9A|4HB=Wy+=~#$|cKRjMCRtm9 zt>)0OELbaWyg#{ASp`smBm_O7vHtQ-+-Yy?$}lk%SsVEKNDgr{lxX;Y7<@Uf1uP7e z^T(pbRQpmsZP7Nl)@|s-5cN?@f{(qNYDMWED*axV_}rKwI=Iy;abB+|b#I4_8gxS4 zv_%4pWhI%412CM7B%5_QxaE;ylI8UC@JjncdQg39jY3~{|0$9teIY3x`s%i;K@g78 zW^tLC=HA}cjl_Xi;d%aJ@^D*XeXjcW{LyIH$UlV3MpFApC)Pz`_Yby2dCrj==YovK z97@S+WC!C&oTR;BY*f%HABM=sBr2d+X$C^yRw_MxRfh6$A}DC21JIQ6E>9Q+KoI{Tm1BGpk=x3 zvt(`b06pKzdIro~4tnmIN;gg@I%~h&e!cNEDmgSJg3>=qWTysWW6t)qLjjiJ(~r^JcqF|BJn*gicE0MJax7{|}vJo;5; z@NI?X51vFZrs^AnGMP5&83#n=wnbwf(T{hLIEOwc&FFue(n zRHAR!rC6=!zYDcai`5xbdg8PB;49@vaXk(Nt4~<$RX)pFBdq#H>gC>DNoG1G_+d4R7F&C56s+eJdKZ(;)vXf` zuD4XC?+-S%h>kWa5%Tu(zBIoD7wNv;?KQ;Y?qUrHWllo|> zIrK3xEt!J+0tdUkdD1mpnns2#FX0^U^nTY;M5PG7_t6WYv+QcscZ-W?9VOwpeV zl3Ei#bIsP0X*U?DiR<8g;?oZn+1dO3QL%8r(Ac&@W18Uoet&rG?QClA!zHt&n zX}wP-Zh29whXXC$JMVc|aY(FQ4rdn@h_Sozt+aOvSQ<<}S6L1D#mTBD{xs6KUY4R2 z-$D6DQ>ySu>Ma?GZZHl!S@*o|R-VhK+ny+&U5c`S-l?HPRp3t;^`ToV((}Qe*e`&f zRL-d*p$|@v2P{@$rs=XfMW1-n-GQu`I%i!o#e!8n?7}Q?Xh7DxiyZ(p9E` zzlg1CmPT()uMFpw^ie8@h{VV&`wF0uS{t^?lHU%Q#hN3o__wqDHaUOP5lw6oh zmK;Bt;82KEW7bvrlr}}qmbYzV9d*v^PJrA0EwClhSIX*^v<5bKtVvI7V<8hK^Mv-b zozhYn*OQ(_+Qe9_KFYqO@^r9YFl5-$vrq8-bo1?(v0NSPVZUM*1|@|P!ApJDA?fw5 zc5y-5!O3ti!q~kTA5*`^_{EhQbk|AC4@nVvzR#Hog^PYpozLpeOVq2+7A#IkTVTJI zQzmG0$+m@6^{FC9g{Ekhcx6{ZU4G!gVs%2DW3hXg`iA2S2Sb|~nyLD+qb|KAEfqpS zFq$A)s=9ns6+#+81UEV^)Qg)qXcf!u)NLmDTDfw%HIr5GF4mclOmrN}c%aai4)LvG z@>uDhEQZs_)p_V8So8h(m(bl;=`>~^`BDBs_!Lc|%07n({)`RD)Q!hSB7T0n%@ei@QnU}>Us+PQO|y=5z> zJlqnepSs~VgU#azvCGvf~=m7S$eUo@38 zo^r&r+z(cQ`P|HG+={1m^7CVrx%?rq6qISHv}Tdszr2l2Y#Kj&F>1&K@+*5f<4NI3 z&jqepR)3V4MP9L|$g|PmvA}1MHI1Bx!|C8h`q{xC*M*`Wrr$(0o#kKgyZOSp`Z=N1 zHPiEbk#p){IAw;uyoR^+9C>}wS^8F1@FA8uq_~od4{=zA#1xEpEiRMi_a)l_ z?xNJ)Sm)$>v6K^aw%o3<%ta>_Rte^`xe%$c$)l{dD}wLD@RW zh@v515tj8K0Osj2Q4O|%dhI(wT00u75D7P_(rXejH$w-#(tB;6w>k`<;+g7kZDkhK zo~0Gf5wygDq6uMQpWAnoC8nzLi| z9>&!v8KtdGQDu1?R)cZhTNKh`L#-Mk3%kX?)d&AK|{B6Zy9${x2u z7yBm>?1@L=R)THcskq$OU6EJu{9)rV#dv|OtYf{4DuNBY3vXIQYn2z8|B`xQDnU2l*Bt+ZcRtWRxeOt-JJepyFF zZ!ZIuaC$p?VqJw>q;WNV%bu-STgL^bXIS(q(qNlmgT~zNLC0zB)g=nhOG^i`>M{hm z5OoVCvAqR}D|wg=eJXp;K5|mlk$M)K60rtW!dW%zs=oia&*B9p%%2+Vr+H2#?ZBOS?+=VJAm1`=5L| z6fnR+aRX8eV`i9&e9Vy_Wp3`l3UCnfoBeburv4AGDzL9r0PVS=87j6gywN;*^#j=V z8f=W92A>i#04A@Yp}`n-5@9FI!B8S-7Hu81oO;x{Ycr@<7W(nXnz5;=$#1HL56;iV z5|B(CdvwWS_Q<2w7p`3PJbFo)_e4v@d|&!DDbrbjmA<;jn&^eg+GtV^93dm=9vpS} zEquLawPIKHD7uu{oi|#Q=5Fu?93kXi?LLgC9evfQ+hDU0KOF0?2hE}Z5+9Q--6=Q6{+JTS&z>OgV ziYIt=Uo9HVDw}LM#;XRRhQoLM+}-O|x6?6s{uNj$)U82ZkvA6O(HJ3X2F8@IUtQoi z+EVPrtNQ)AbLprUD1%18ja)~ng0Etg)`zrv9#`9VSCc(rTjNxymY#YB>J{+;ey12b z*UPHC5>@f=dPP1*@aiIDhSih6lpcP~E}(DO<*GakItv*Lva<9D%PRi%3#J9_tlC?* zB4zN1%JO87E3m^$NT6mDt!IXti^7}ZG;E;wLGX@D?Y~}BtGIEwz6LuVoFzms(DDRi zQ;*5n^TlI0186KaMPB7pxkM107RcT0GdThcxuWFVGt@Ql* z?=Q6SZ+$Y!M=yf=t9hwsYPhUT7LYq?->X)TL_ph%Ogo2~<6NXI;4f(01~8_J^U+9S zKB;nix)xqh8BikRJMb%nz?2`o9Zt)=#oBv)D4A=715P7PE{|>ShU*)4xeBa=fFguj zbVFkUOgQz`=%L6MA52NC%yTZ>kt+dFx~RnY({Q@a^Md;;48wT}jtIjr--#^K>rbnI zSDnZ{3br<(i2YMu3cBxkU{GfOD+9jEMsUm_6u9u!dWBd#L`}jhK&VRpc-8m{;f3oW z$T#9Sc>l#-`?d}_GB>NuM+342=M`Hc0)fcHyJvaJQyBX(Z;A$`r=G872?0A7;5qTRX?ZQbI&B|S@A4NitvUk zMfU74NtrLk=&yMBkHEX@XZG>$bdUch`N6-klG49*fdBNZ|MIUd0QLWN+5aT8fR>G% zYu`BAD93>iogQqYzu${b0Vn{pZ-B{}d3bnO zmIA6`fmfS*hLRJ=wyes$Q8nK_fj;JEAtR zv(zhHWE7lBa}!ZSMJam@sQ(1HU2i@k78ropfe?MM4Y8ocrZbvx)+iN3VH?q%D8yR(Pslq!VK&GGk3%j9 zloy7ORX(kSoiC#lh~2q1^70;%n?qZxOcuXo$TvaKgvy-AU+n_HHDGA!)4_Pf5Z?<) zhl_CNV>T;p6j1S*1b68$I*n}YuM4%0ghedULwljk5#QMDT&An9&Pafa6Jd;wqb-S~ z1oTd52gj!=si|%l6!%f7lt4yDT!)X>4XztUJw#SZ-H>z130f} z{g}IhPt7*7rC2;}*?tUYE&06^V3xl9Xe3_LNB|OR6S9aLKe!2sxjF!z=m6P0|Ky!N zU)~Nm5x|*=D++h%EAK23fX_Z6yczOcDbtM8SZoCtv7_#Ii7`F+*TgqCG?WJ1uJd^7 zPM@BaD78kJW0*I9pUj0iNJUYHGxX!z3ZHeoZK)qYxiFYZ+d;$$iwQIpR#sX!YjDej z0=`!l=OgVuoQ%WGW#kj`y{M+(^QZ&ge_wkk=coP0@M!z$zJUh6r5kg!ImSyyIe96U z{5v*6wzA^L&qbQbUowRM6a+$!y)XlBA`}_+8-MyyiQ`{VBJM;ug+_CiS@{@-*6<$q z^v7tG#JB9l&!p+E@A|6<$G;(MeDu?E_J$n5^I_rPlAvD!5`XEjR_!|SW#AQ<#z4~G zAv1X%)u}ikvD;Ov3F=K`0l5MxAcg>%s5G0!Z+w0e1>|T9WIyikxRm&`3EmT3iT;x% zbtTu{Bb5;>B*>^(mG1LH7>HA7F-ISX$18_y^i2)d2TZny7{Wk70+hVN-*!v2PX{N! zSYpwLHpqkV&Yy$?D6%sFXu_F}orwnOV8U4hc#W5Js6Hsl?d=nhY~9KyLfWE(N{ft` z-Z54ljwjFZtnRoUy!Vuhm&`jB=wXe|oJj#e%ocIIl!^+quMV`n3Q~4b0>JUr=U(e~ z^G^z0`?3sK-$13Xm*@@vhy%an5vUUIG0UoK$=9_KIMV()ycu+M#A`q)pbyL)>H&&_ zQT;F9I5GCk^)JTI0#5n#xZOjf=ro`d$zW*yO-DTeEOJn-J;Oh$3dvEBBBiFMYlDY@ z0elo^g2HK<^+W3)b&D0b&E^XzDM@B>Df@%)AP?VQpVG8J%;9(fy-pcun=;2 zB>)RGtfOw{D=plrg@o8BkfE=bETzh*F$O{i3CNxnY#Sz3jzyBEOCZ^U^(j1GX7Tjd z!Yh$mrQ#s-s>3?$D}#Dzki{l}^b3t~SZKP7J?Jm^$6cNJa{K56N?Es38>WEdG;b94 zA3p$-2P`bFoaw!PEliKmgX6LxB(}f<^rThHUxw)j)icqSvrI5je*g}9h+Zdv1KZ`{ zvE7YMjAvO65SJgP%OUq#It^Jhnya_@O2@e>{!w$&$)5os`)qYJWaJLg!eapQWPq3L zSzh&pb6UKcE5e6Q4;KWKC#~84eQoqX5hy|d{RQkDKS9+X@M3gir-(tt5HAo1I@J?I zOQD*FiGjgxB88^oZCx^++qmSx|G)zIT0)1%w0ww^>+k3U|6M1@yWfsU6vvRKB_KI~ z84Jxf_k;tleO|3|mpt8B;AHkDxf~vo;rLw_#V}~urMcFzB>~fMux5E03@6xnxY}2) zvxVLy}Tb zttj`YTERPVV~xYoa_2jivf(@f3Zz8T`m)M9FmNC_6lmrz^A~hZVr7OB)Vv$2aQQ6 zyHd*KuMw`^(hFW4x(A-@QCNg6?I!|KMFCr-w#q zgL$5#hH496ZjFtMd<3U?WK|A|0=2o%wxz7evY7gNLBPa-xWAuSztL2fwV8?2ziF5m=PAYYnAE2Pxq z*fBa*7}ka6c%N~wi=_rB^gX@89={i5+;}Rdnmt!t_m4%RY3kQnZN_IvVa){Y_RdBd zO2n-Zx^@I+wJu0emtqx^fkbQm$%=XF7-cW5xWxhSf@@P3hRJvD7&jz?(33mNT@=3B zTZ+og38?wy16-E`x7zHNa=3?TkY*^M&%=LZZL}c_pnRy_DJ0w~+YJ^#hF4r&f0lu$ zf5y{zWhS8Q)2H1SwBkmd7;GAjGPcRs&~OhZ?8l6IdeqN zY(aQai?ncjd3lc?X4rK+34+dtTyPcrWG+^BYh7!mo8otK^@nP=7s`k%6;z6|bfU0( z_RB5a%b+BK!EI<^(e0~dVXi#5j_2088%7#Vj*dAT959dTG*Z3iBNg3ViTv=m8Qv(z zGJIva$K#k&Tn+VscD_%7ox$lDppdI^TVjcbFh(9%3)Fy&mT_AB~Rz9husEvWc0i^_6I+S$#}f_ z7)0VxZQtcp=bi!vT^7B5suCfTu!9_|DKaSYJ9tt1IT(TQF~HV|pF{f*bKD*I!=b;w z1$z8a^)BR0s!;!qfr8WPzQaVA#ocN^UPV~)4bmu*tO{=(5Jz(=?9oq>V|)HPsF^g8_*%DM3@6uIigxix)<<6@l_T%3Z*7`6B`qzZxH)9mZp*{OOa7j@Df$*3li3_MwuVXep?0OoWfD*ST|yf zb)(0=89-xNSMXo^>%gb>|L_gZ|8hU%FEh^T&M)uyNVwL}rx~}#9`9)3;J7#C*71mV zGT6j$5wDY*Mn~>)Pd8?5B#H3c-Mn0U*R4O-(^`OKOYPT;@z(H82Pvv<<%|KKT8a}B z`sGvBR{WJmY0fyzsX%UmM?n^6IFoduYpE6?rsOJazo7hA!)-m&CJb!{P;^T>L<=+h zDtCD$WvuaMC{vHmNNJD()_7>K`rL>jZMnF|-tH()@#f*Cj8IvhXuU~4ljNv56*FFy z$Sw--F$F*eddZ+;ypB?`m)!($j!L1r+){J> z24!P1;cRkermyA1@0 z=K0E4*+>E?fVXcI$>WO0O%!A$*`}=2gBTyVP|dY(zj{;r+=w!*R`Eo)UJA4@;vfMn z5J^qXdu!g|mH@?c^KVP4XTniw%jaAW^4?95D5zdwd2`xMh{>0|gyd4dD@P>tnjU5qu38j1=Z_FRK)h6w>QCg7$y{aH9mn^6@veTL^?X@EniauPrlf`v{0x`#`;O5U?Q-sSmpRbg`Gzh8m zl?VtOB2MRf7!Vs~=j5ta3e-^+GCfS<9+!yiXtjQU*~Xev2D@Vww;g3r3yl&zYnfweWr zzLEMV*Xh=t98X&@n+eOHqZiw5Yg1@qrBlAcV>9NBlVlN0Nt^9CP1IpK6AyCUB`D<- zXvK)*C0&?JD4+oJM(rc_U;M0PUw(@)TOVu8un&SO4U378ttnNA{yb%)R=T#cPSsP$ z#TcH%Xp25hpCjQB8m49rV~$Ru#pOGnEFYlAge}h6GtOF7L{aI%-fd0#=y^>F+eSDx{S~J*cT?gQFxFN&89$&Em{+cv3 zqwX9eq3q>awkeZ&5r1IggW4v*b+##Vhy)wgZA~b}X4C5u@P#LrXksxV1Zx7l*+uoa z)I2}wnWY!mO~HtTQ6EUWwW4s&;QJ4P5L1Mz2BteLSC)NJE0_3Swvhc7H7wCqU0ronsQ#J~#a>WWj`^+8 zFWOb)?O zG7kX?1Ajl>Gq)|OrR~aFPowpKA-4t}dsuj~G=hz1eXES$I^&Y?JkE2zi1?U4QVKJ6 z%|X9s8aR{Bbw=errMeIkB!SR#TTwCb3s71RtqcKv^rLx3DPLeSJRWAD8ANnKS#gOl z#$_{t6Mo(6u@%rKY8hcbHYUbZ=YHxjF$!C{eZoIe19eD=#gPfI3#)Ii)9!*_R4)VSu4D6 z?s*&ljO`Z}>}P>&@~>s#`j!20(HQB}aNw6i5cxfWE$7=0JD-V{X5Sg^^mQz`EL?&q zv+X}Df?)ixTJ^r_4R?K>G`Vr!4>V=uuYO79PM?=*;(+O~Rm@HRz4;V|&U1;l-Ohp> zaDt{GPSr4@?6F7maY;r*-C{x>ku7?NE1pX#g;!}Q3V<0T~I*yDaLD%U7mJ*Y#ny#CU9`N3ALE9U!qMb@8`DQBLnpF8pu zI8Cp2V#aPAY)_D*j7+m|nP@&~5cV_hCHEu%XoT={Qi2~%r_95^{N%8HnBlWa2?}Q1 z8B;QTX0=Ldc{B|rA29Ji3v|&Z@D;eqC~9=(i32e+=^85=exL0wQG^gC3Ah&;dFYD6 z3|zb#w0-?5Vy{Wyc-|VFEE`KyHgPOvc72G^A`66w8TdTwE4?t=QBzCu)WsaKdVSVs zAaPJFi6M{cW~dEQ=m^v9Uo2zSTqy!zxCcKta)xi+aE`VDSFgTwL*!tlS5!U#S?{o? za)d2e8#Bq%`nA#;B=^&@R=VSas|vr$GUP$ookn+nXz0bDu>S;Vtv^X|vN`K$MVO;Y zPnNhdHSERX-iDe;>%uH8Ix*n$FSULuvgP}`bEpr!?!ho>n@-j^!_X-tlB(Wu48PjZ zYw}g??D3PW#v~FkMiW;tp!g{VW0DJXCs;F+Ov#C1+uEjHk}V5q@M z?Hv?9%Bat`GV}4DxUrDNlhmOlei-Kbpx85)v0JIX50o#{73cnqA$P6MPPwmb`}h~w z7kQOg7oDD9ZNAJ<8t3~#-$keQy+CBYrMz8?b62*}nj$cR+=gkWmks&NGaYlUVwK#M z0Nd&4M+s+KKMLy4aDS+AAO)**MK@c0RHl-*+=rx{8q@*mqvTh+m*zypdwj~TR2JVnnpqYVF+J<2w*8ku-d%aXupjy?>c8hQ+2VP+zwhPHu`TK| zp2Y>uMlDfL>t(U9j`t3u+qwI1sz2;fSw+FxYfaq5I8N;HK{6(X!xgKV3aSrj79O9v z-ExIeqPjhMkS4ED5q3gSKQKh?fv$)_U~fVx`*@vFBvMeoO?+GJ6(!!9s`uwdL5~lF zjRN{fMYdOGP4ABCZ93naeD3`qIP6|2(rgLS$9y`mR9Ii*r3_+Oxr;-C+k9L@&15YTchkh>~DSQ0KNWG zuB~F7?<}9uTvFHz(BC=XW-ek6$z%%pKk6vV)-i&_U}Nfw`mCZE(cT$0h`N*)KCI~4 zNj-lqDDsb(UZ+NTNhpEw%ruIl%(rpacVw|BSkE`fLk&~3C|Zy6oxhg$L|yO0vM)Wm zTpKof%xqcWl=Ws}`GL1~x|rr6vBW8}QADd?C11w0EI38H%Y=Y%wJ@rAa-Eo;Ue~Vf zxl{Uov=68Vdu2^3qz;J(gT~3EUQMF|bP6z_nW{&+_sb0^iARm_T2t}9sTYAI&b%J4 zvEula$JZ*p`n2Zy#3xMh)pWUVKwNVcM0$jTctOrv^Vs|B1yEqTOH^3VH4m~gw;OeE z&w18{PB+sz7fJVIx-)!+dbJ@zC5%Z<6mM_DKV ztAI}Ui%Ed_LwbdR+`#9ug3o20 zB4c_NM8+h~L9|U-2%#95j>jlpWK|yUy=+~yC#&rC_WP3EN1T>mWN#|1YsNWtSJdR% z`qhWPao2dpcGw%*Q2|IU|zCLcTx8sUS{TQJ_Ff7$4{^qL7%(u-M^@l;v3m&_k z$qx!o9=c$h<*hLlfr;DfZ%>={{*o#ycGaHlrxu(5QiA-X%``Dp1v4g{1YJB;!9XF`OgcniO?#EK};s>5vA- zH+p~qd5b^xH978h$j5z6GmYt-$s}=$n6S*rh1vnM4x>MPAxqXTGtLqp4JV!tRDtC4 zH)r9hFFt(*iVXL2R z!;B$$-f8U#KN#F+=rUabpH{`!o^f1i;AAfspLsz@R3UQDQ+3}5Q#4XRo!0=mrB^DI zo$=Z!!6dpJNNn04WST%%&!Bk;xwIi!-`af}jr!tky)qKLD-a}Jyk>RBp#e-O4=mWs zKYjLhVj7+rRE!-`^nvUi7WTAXzmIe0WkpnNPCjlhfxNX~JWyJO?Hat)_VYnyXFh#) zT0KtBf`u=V6jsKGOx}$oF$PV>Z8jA)>X^iG>y`H<@S z#ap$hbAcz?f7t5Lmg`^7!z^tAOHWvGP~uPIYCHzrmrM!uKu}@9_xwq$nxpHAb0ZCH z^mq9;x06imd5*2WvE}-1q(}`SdOv`CST1nyL0HvJ^V!71^msylC+!n`Q`N`tdTM<; zx7-AlDPCx;t>(aUR}7AykNx?RH#Ut>tSL>bV9&BW{g-`NN8Z9SstD_(W&FD6FKU}s@T$H5fDQ~(PawPicAOErp*H<~ z?{f`YpkEqj59BXQ^8EA*y(1E~`SqChjHhN) zjisHRnEYx<$m{aTH+_A-`z`IUYYibHT`^Ovh>fL|z zD{S6w=H09J?2lS{}(9PWm-dg!0$j{M-KSKM53XW-u)jsCal`j2t9dgapQ z@BUpswy>A|-?#pMX{MxN%dDdgd(VLZD!agSdqh z{eU)c^|39&^apt6xm-(pWaVSJ| z;5opWs&K_e#88-;hP&fXYwbPdDqstzNCZ^d7E^uhqqB>XQ|nTU1098ai3YspdhlMw zpe=QHVV}dPWo6x+cG`tY|K0X$bnOGMD^-j#K7IPjm0ZzobcsjC*6P`Q5D*1RANR6e zZ+~6gpxrrg=d_iSKFT(#TMYpxeg1yRB_t{Ni720?+3L zcm;z646^w}Wi{ZW3yx;ta=-j{Pw@t@J77JV0!4elx(y1S#|Q`r!0By_RpM6WQbTQ* z*>nTy3@&lo9tFK;SKdy^}rGhO6|dKgsnjd zrD&@}S1xiY|1kiz!vOFo>qUNka9}^+UDn>&nR;Z`E__`)SW5!^RXa|!t0&z4(F@RU zNl!~7)b*oM!2s!j1tR2nSJ%9NBDf%i_%KPEVGK-NgRT?Lbm=W^pR}>GyfTma>VEf? z$p=gk0^v8B7y&Psn1g%^daXVoA0WfB-U)AQ0`PY+DI6qDVAImGN*kR2dZ*jBg{gj$ z80<`{M8OyXwG-5_GcN0%2=AUS1>E<>iZ!naQLN#I8&W)ATf4y_1d0kr>%s+wK=dM0 zA?3(}+Xv-AGNh7_MxivqV6Oq{wkMx_IaHfrAR5=~p#L@`0l{gO#rt0k55p*EgZhnN z%!~pW5ZM5EbfF5DSG$MC(M){qHUyX};2;aJVEURW#L7<)B?}yyg)-0N{JC@IPST{I zq9SMn(zCPmVQ9f~0BcP$K-@59`^RJVQ(K0D70@+6>-c>Ca#U^cJ1Q<@1`H&`MaaNV z6?ZGQnr(*fO2sh1&_Z>M65zB@h7Am^{Gmga*i1U|&P7#Izyj^$;?k;N?+I6dHE_(I z4k&~^SdAf~5`+g(uX_)KXNW}*f;+M6*RL1Fz-9f4-vulKI{qdkfW2kP)dvurgx%4| zKjJD7(c@eMNDr9EGT>M*3N^E(-O6OQchJMY_!6vei-=pn`CTFn?{(k-P`oLRFri^# zqu_}i_9k8*-Q7vvYR4UyE?qhe-drfkf)OV;GeYX;^!DyXQr29Jh?cfCRATf7i9|XO zPhjPj~OW-jUMyA4V z6X>5%_x;0bq^mh+_tz|*BZE;F;CuLNu5~J`wHak+Ne52+&qOp=x3%x&pYz>AH`lUl z@4qSyyCoqL;qG&hTO%6fN3Oi9 z$pbD5(tAX-0+d2(Lf=}u>}JSOPzHfR=C>3i{Bf$KwNr1jd z{~*_V36Z#2fMtf0sa}V{QAX@^w`V-v`wut|xuBgXX z-*M`zhN%W;3J*z9VtRIER~8x7Cg3u&x$fTjPW5fWeg3qtH_KGqi41tByrNz8$xp+^PTl0c<2I!{LbFk$jn^ zQPku9NS(9L|7?E6$t_ONzs+_!!~rgN^|PSN<8R+CKxEWhqQ(LA2C(rm05^v3ZaDve zlx`4x0DNlz#lhOJEoXD-uvPG5I=Y{x4~E=Zv*13@!jC$E zv)u+|q`|KkX0f!qyw*-pt=#|E9sHZ*$(l=8yGgp~#!g%Yc75^FwR-&I%IUCd&95&P zU@w8>Oey!xgY2-}ns!@xGsaYsjw&2Ot_U5vAdu|`UhTTo=k}*H9}m{TUVt75WkbV6 zCi*J6OO%#wV5}1!?UsUORRE^vh}lqev`np6)B+XGk=T*7m)hFVaZ$Jj$=ICreUP6Y zSdoKxI_~4TcXrgsNkXQ6F1yt#x48%u6Cj848_%hG)s=ZxWIdnE z6wXB8C!(@}*J7XYQiMbrtW*n7KSlT}fM@O{mL%tphxDTh(7jF+thsd*x)i1b><3>J zo`3?19Svbp;%#TYYu0xpLjeZV%rLdy;#F5Xzam7mlj#XnPE@I*GmM1q%P7awpz$4D zTq2eJO);Ev~zNjh49%iz-0!_W}I|;|iu|L!bkpFl0W!rw%?C!;2S_;9qUs-H^@5UNC z(Q1YWHg8&ACQ622-BD3d0sABN3rbL4R?DZ?E21OYChj!P7#Md$l!THc4*Dy6L7H@- z1Gh&rK^+EahzRJdM_=9(LQSL2o;8B!fD{h^%f+W<` zYDo2vAPE{2M!Vaa%-~0%n%JcTh>xzGmYVw2qi1)p-|`2q_10F>J1j`LRVjNFMK3`m zG$;!;_%zCE*X0tBR3>~kzWqLZ1*8rji6;V645^)WSt3jsMD~Qs1a5wIc7#1oiMTte zv0cJV33HG!=Z8eD)+rZ z`*^4Ki4=9KrBb(O50pNBaOnBB&`Vgz&XCPOWum}$QXNZ*#~c0}DUIOVE!`sB&G z5bE#sz^ow9-mJV|T1KXjtZ=sI)vG-c0iuz|7di99h&LL7EvO&@fS@2_**iIp9S36d zz0df{AE{K!O6w!fFJZS@_XsPQ1;BiW(x=4x2B{CkBALh0G<9fM@~D!iVH^|+0zE)F zn8E@F5BRwu@_Ej-$^K_r!gEvv3sd$jmGvHjp{GTfxb?(Ei-HBfrRQ zQg!1j_x{y6Xo%$S zHWk7+bX8Cm1VjA%^X2KDnu#qiJ*~U|H`0oX6u^!awd9y&P}QB|t^)R`v?rHKC)?nC zwP!QlLzMy%3>e^hIzK;@kuF;!Aey`B(%$TENOuH}AH|1P!@i)r%M=*}TUU~v2|@wSRSBO?@Q0$J4qejY>qw| zDgPYy5njmR7>%T+b#5h=kcOGT!143V2b+uoZ4=Vzh}M^2+~6F!||1VD+Ei^ z@33)tzjWa!%+k&kbW@2M?G1SNxi|q9IMAV?D?8&PoPpTQ>rOaG@LLXFfL3&fvR=D# z7DN-9pSyn2g)6;9IvJ1!0w@%|&CJZ+82tg^bDVYsg&l`Dtk@k{r9KKpn63y~15*P7 z17jjAZ!m@~F4?GlrdRNT`jo6J66fT1NGYJwPWPItFzp!7J%20`v2!h@s;Q7-zj^th zva)Yd<5v+QVGLY}IQ@Z zP9#6xd*@gc2yghd{lN|-1~OaY^op@aRX^Y7pUrlGk&D`P`7(H`MERV^!40Ao&7R>` zu!M=YNdmSqn575hqll%VE#PgT_w3CoullxBBf;pP1xwJPqv+e$XT4KB;B$#m5-2Z^ zBMV}9fjpM!3ELg0{wH$HfI_W~!dLd~AjnkA8rs|0E&V@m?C@)r!=gEX?FPd3+idku z5}EDUvv*_zjsohASZY{~poABcrkfah1%UxaxHCj`C=S*F5kD0&Eve0GM+(T+t(3(k z%5i$!T0$ybq=Gq?UJBYE$lSJ=#DO;LC~n>dH#{CYN65qvPL|O+;2r5uJeEx*a?(9! zZU^gN5vdK81&m-khBpohOmiTX=ks0@duTVd7lXuUsHO?>X=csS$fz6(?DwoQv!{%3A%BN1YQAm(wkp9jx=EE(VbCP|B1_nN3_qf0|8yO|c zDRC7tv0fhA-~A`^$62lHr;fxph)sQa^r}L|-R=GFT z4vS*gR>GrgPTW^=G1*FGu<+Yj?HC>D!SZYRqePd8qn?Oa#AlM4_7}VBhFlEGGN#n; zRnBMV4PT7+%;M%Z4pASfaLlt_MU594Q?I}4`To}1Aw;>-Z0yRLeXlR8^--xk;x~zl z4l$qE@hOLSj`%%qt9JZqqn$hT%o;lOK>yJ)_-U@hl}fDQfo*}{ZFEUt)bTYtl^Jg|MCgmBE++ z<~y%q#qo-?S5Al3v*A5qUmNg#*x?@2bSd&7r7~^PGrwq9U$nmA{wRVvR-j?pw=Wxnp`sU)^Tuo?@OIjDhdx`?zmTc#FdQt4EYeVI$GlZ?okrzyL^*>JRC=V+5 zBI~0Z)k2CSk=wSZUvDm%UOhbICcTsDvMOj&fzw;!c>JOjSDcVw#PU87v?uyAdoO)Q zr!3}q#VoFSA}1Pp;FH7L5-iVlDNX$F{N4{qR)@JWj^WufcjwqP(vB`EOoLut^HH9v z(;?nLtp(h9QTyWQ_NfZPrV?z$5Ii5bH8$JlezBXhZ+}it3~MM2xRGQBb$a|(xKL+Z zy2e*b9PhyItKGpqL;X{)sA%+7^4O~`_!65w8Yk+|2Z5WuVH+EWqnqe8XDD)HA0oQi zh7VFt-?TdF5!rEX^+vTq3zGJA(4weTX$*>=<-=>F;N}7%t9X-h+Q&r~&he~O3Qo{W zXuR}uKP%g{y(_6rq74K;<8!@l+3z{@(Hfq7M8(C?@ii`^@p0UVr}DxNI&6N;o*JDy zOvia^`Px_~!ia%~*5!P_`J=@Z9K-9ZoZxuCj5~ zbF`P1?dmKP?nOMqdQ@X>*1~vCzT4L1M>*a{NgI67i{G&Bg(;5eg%2HPxv6S-Zqyqv z&q70%%G7k&G_iB8;!3Ap=YD<1+_91;AsM6eEtG0?Ih*`6p_S+u zwujWE(v*JXBO0B(9u*u{8N24;xXBW04=knKlENm~vhNp|?sd<+=jAa*W4`aZn7QTt zV2^m+c;2F%OL1?>*^>1nn-5jWZyhBv*pWSrm02Ikm$QcLhPJ)07^nWX>drMD>UHho zs;8$_ilua*(#lYa5{b%rt>iEcGm*++P*ECoRE`;p)lrccD#TdJF`7n(af*?UQ)a5k zs3>$A3^N8}V$96G{+{)Gp6A7SvG;zp_X{6y=ELp2uhV`1zOE}v-kp0;wAopW>R33@ zl++qcC8dL-*D@q`yy}ra@cI{Q?`)Nv-o!7P5D0L7X~xC&p}`O7L4vT3HzODHC3Oum z4kVn-zE)i5oikF@DR0Ih{wd$;-euquuED~|t)drRU)bOrfPGKrnCB&Bn|sGe=C&?7 zfigZ<)%VUw6RgcO3OY|3pM2^zU5(Fbb+++hPhX96qzT%>*4JuGD02_MscDI6 zWp>_YG+l?Ps{)UXIGpO%QJ=i{dQ15_{T^1Xe@hlq2Tgt0sD&QADBs6)M&A&{b-dW| z^3D;fa}jiHPZl^>;P1tbYSj6R{7g=rDL2%IkioN?qo;#6uMn8!UliULIp*^= zemCx?3frZRRNT|thaAz2EotG+%6+%?aTm>8U02)KAd#+}iGE5kv9VSf{?JuAE)M6S zd?hi&s*i0ds0(1_Np950kq6G~jeP0kbvZvA_V+N0rNr2Y&Ki>Dx{NnF8#@)r6yk3P zE@65cr(e@c9KzpUHm0K{#xBn^1)JH8c0J&J9fC7AF|TQEZB zk~Bwu^!OZg549y&7gI1qzTKL|UlUa4K`HU%2sYG~;nRx+Ed-`8qi8gVW>5|ucy%TgeU8Gt`(S9sjAy)IOu*i*AJRKAQ2Bhm{=8v>Qoc^A_(+~DPily> zD29mF+b@2R!eR{-sTX+?i&Muo-c^)}RTZx7A+e}8PP-=W_hA2`DK`+uP0Y-mP44;$ z+m*W=tv)rQ{3LcVn4em_Dk-GbzhIgEzd>MYG1$^Pikmw$9emVPD_&NPull3d=LLFvG3 z)l@*wp3~m^e$_NlMUhhuzdyY)D&Q%~BY!v3*el;8w(WhSemeMJK$@yjTmIHeu^%lv zU#~nkUnPsQ8^SjA-S?O`g!A9%Uzx$KQPG*Mq zCarpFOX__|CEQwUG7^%}$s8b_(O#-1L=H zW(nIQahq75dO8i|_pMxlg%@<@HOd!9*<#3sxY=fYs^NiH=U?zA#Aoi z{KftdMKM8ZhtDd%vyO#iCJSqm6t+sdiS&qA;BVIj$VYF%#`CmY1TaBI#N&eRwqF!- z?5`V7rc&_tZu6Has9J998;HfJQDfjQd>4QrEU~uJ(6kG*j4IvrO|R#r>PQ&jK9rk* z1CaMN>^0JE_7tDIHE%=P+R!}ULz=#aC}L)-fUlN&%S4h zp&>EKtO777zMiDT$^p1>b#2Vw)E6j$>2?5|LDJjEblAIa4lo^e;{PtYKd`3P+`l zt_ZIAK-LW%r4!Fj&&`V?p~k&<2c>MdzAtltp?lT0x_wDHlnPm^882!^lIEZue+Z>8 z#P@>V$W#^mo&j2M@b^9x}IW`2!^g1gRt zG)zL`Fcq=xjo2?!m2n)Xf-&=rdM>=}V1)G}XUmILdq~nX19MZ;ilO9u}Ry%P}9#A}HfR|DjX?Abua<1v5vaz)i+4T`I4_O<0=z;#cHx_)^=v`Tr zxIe4n=4%^|8{UUY+}gOHhp=(BB29J9&l#;Ix{3<+zHo5MHw1yLXYro+-n-h{-c{;_O#f?HkyHRk>%LMV4O|_h@h?AM^2cC^CNi@V(1tZx zrs6wgF*Yl(-JpbV$7Z0x13Z#<@IqZ9Oo3LWZI#q|y((7_rW%)p>) zAYRb$Fzw=IhO8?w5qJ<-s1_P#o&jOPiDXP|M)rafHa+ZucEw;YZx+a391bvug8x%$ ztiI$e@V3vD09R1srD``0SbbR_#{@8(8`M|W-s@6wVf#2JeTSe?94L!OixCh25Ws{^ zKLV}Lm`@y*o5vY`TB^-xTmFmblcDS5Kq(*>=72Q{$Fu!f@JaBDjwY?!>Ha$`y-kDQ z1Tt!x)U607~Lyjp6IF}jVCNqh?^9M+7 zo}Pie&R7zNDagcI_<=wf+x8=$dfNJ2z1Za_sOGRuy|QYceioRFcv!X82#7gJE37%5 z+tA1X!`nDeB3i3Fo}_nvzI}zxzkw$xyjBYWOaaxJ!2TIv*MAv)U9$-Iiulx%e1*wsG}AO1h$p#@E|`fHchJP7`N;z3a69)?U~)GDu=Lmy(VXdBEy>Ve~z{to+71^Dan+|7^09NQIWI|qQN{ztdPuerbP>>kfM^1nG7MbWL!ju%w)=( zIkRP6)_Z-spXc{Jd%wS9AICo4{m*-BNA4SI`hGvdb)DyVo!2K=Lrt0XFxz1i3PpSK zhN2bgYq{n{4<2mnRCfZ*^1gnvSQ*pCMnLV?C9!`^=a8@87J>=DYFcdgJ3$5eLZDC@xCq zd^)8{S^C~6Y2dDC(Dhvrt+O|Lxl1CIkG;{b$~SNN;RAQc{^&h!S(CN~bFNnxEcq>4RovUWTfc|KFbkjve9q`$HoG6_Xyc zo}G{4{`(vS78M5MDX&k}u3shdo@=AG3IF@lnZr`+MC*YMGT-9=^=^v#ZU4O8>+1jf z)AT=YK;VkK@Xvcwyvh03<2?T8|E){<_np1E#-#EKx4U3a_<;7a{opeZqtEwR-e1b= zw;Qngdpq3hj?04g9&z;$H3vTE28BM#v z&$PZfT?y^KejVAu3NPYGxEASP>P)_t= z)ECnJu9(a38!epj+8P>uX=!O{m|K&Rleoc{_wO}~j6&eTs?G8sR^ipFcB0O?z{U$-+#V--%>a^z`%?n=FaLz5FEnd-)PJNXei`*B|%t4H1-IeZ7({XJP+~*jSD~efbJ8x&{4q zPUS-=zqfCXEj*CD9eJ*Yj}Y|h*Ii^p@7%d_KBgtp{KoCuwZoO(y4%go&9B45dDkQ) zBzR7pB2&M*LiyRQKe;LEL&+X?RXR>hmnejx3si`Z?4Hmyp&5UQ>J7NjTa}(QKV95w zLV+^)q!*p`HYSE9{5xfOSMc1NjokD;;hpbLnHyXLe9Rin?>cu)j8Tb0kHg}d;Z=cI zDg4u?PswuIkP9BJG~zV!_NH z_{_}1FksiF{RCKPUtKZJH^{T@;)_z@)6vyEg+?25)>e3}wfFT2uvac$68NMi1TUXz zi3$AiL*+wS+IWP%2^s45@86VmL0{#z3BPkQGBkSdtHn-Z^3m#TD}uQPR^FOb98ynN6cTtCbe*%LYeeRcY!%38%LLlAui|E~6BV1sue?fsbs+u0ROi{`;hS{IQ zpipgB*Iu}5-&lXAe71WnCMJe`c_&uVk<-S;#_4w>BWsjf`c>E<3O#-_d9P5i5+?IJn2Fz}F!Py2oUE@&@u%G5%*-ip%cxhcUL_8_h;gi9MJ?~| zE=??t)%x*NAF5j{cOAaN$s6xA#R`Max8VLGK^Ef{SyEQU_VMFKgL3yzD$U=&llge` zTu(WI`k7-a6t=n2z!f?BczAWbg-fuqVQ^3}k(>NrYV-w5@+#X8xs>y943$T9b#(>K zoztsKmo42GuqDIDC058}Wo0?{8he=T?`=Q-1$XhG*N>WyhnIJyj!Atqr+o1%T$Ju0 zpIU5?GS{Q-CAzI4j}Z|P#>gmZ!2L|nDV6WvzYnNJU2zjcjh0Twhrhhec#pEcbz1Gq zki##xUgH7PA)cmu_3{q=fw zM=MDJo5j)-ae-r%N7ZGCMJn@cW@cvOCV_Bi-DnD)sGt`w>R?C(*>iZ6Lly7eKW*YU zcHr2F6JIA*P^iVyY0kR3I@EjJSeTsO_x}iezb{UPnwy{3orRHexhi?=<@Jts+Pc|? z$)7);kcep!4Vt4X>_4*g_m{ey`)apibvOC zy%)|)YWDh1QLcaf7Q$RR`;bROg!V+p^&X+5iop>s`=PSqYUxZ53R%lNmgp|my@DwC zVt%vciNveR&f}CYmRIT;8k&=6%(6Y&MpY}LUd$9Nw$npAdr;j_XS+Cvv#G#=s=T1Cm(+Ga^mFVikO<_YTTG{T{` zFNlk4n3ybXYKdbjDsRSmTQzyie<~qI?eA~mn~SQ}Wl3wY=c84S)x!Z(=Y2+A3jcMk zC(A-E|Ni%*5JIVpMP9-sug}6Ii@(aq$qw*ty zt7~hT#>OX|lBFTHKFz@#Wa{tl&y-8f%VTJ1Y1!&Z*r(ijCXObqcYWDiEQja#&*zlW zU3l;VmE*)sHgcETo;N)+Q*iXwd9#}alZtvB-i%g%Dzt9iq*me64m&cUK_!K)j|@q& zFig7Gz5Y(Nd+*GdGeKcto8D(x(Zj=h zZMko1$EsH+o5d`ej#aES3AuRn(XvZe6&?i~Ku5e1#o&<`#v%0>a#VDc{h&lYlWAdp zp680$eM`&co|v46++--*pV_ZzW8b_vimJZUdpD&e%`ompfB4E0X@5!1FMrJta-RR- zLcKnIM|XiwAy$naHCna1*yXUw%Qj&)?EjNi@)v5We*0hwq=Ge%>uoC=5#!@#u>Dw{ zJTHLMrWju67_9s0kNfWNg@~D)V%uJ`n#Ttq>_dtnx_n`0WbBaZ$PJ)&ZZOI|d^%Rv zms57DhJHB&vnPKke_+zZbh%w$SOYqYaFyHT$(x?L&kY{geS3aQUB_`eDm_V*OYFrs|h6diM)H_ zb|sE1@MTc`TAaw=tBU95D=i;#=(CeR_6cmMcMSvG-5;=QtFUG|`uYw5B9I*MVFKg> z57xgqa~p-Su&^KtQ@!c9t?-@8t~g@t2sGS zcDZKc(fE=fclLPCaq5egE`47!G&X)2iNUchx0si`S<`?GO;v_tSCJFz=Dl>OXK8U+ zziRb3UXI6rUdiLG_d>Bt-|MI&IVay7I}Bmhb2QT6Z&BLu@FY91{Traa zk*LHV(LM~f&MWo%V{!5EboGRK*dx5t+UpOv|AELgg!y=wqyT0U&uetn!NI{bb-_%m zH~u1V0tK1! z|1TW>Z_xa|O9%9F?t0CpMw)b{9lS`GK3IGca+#vy!>1fO`xouC63qTZ23V7`EdL=F zH}3uCpIrZ8B|G%3(SMmnGTF`ll|THyA}IeK-Pr#@Z$oRdy}jL6;dKGhNpTET(Qzr^ zSttO#w-FK6;k(CjEt8WblL9%v0;+r+7x!sM@mPVWkbX|ZdgpCX>#p3OKY#49O)3pz zI5hP1-bsAa2hK#3q8wH~LfZEzDk`#))E2#9NP^4(85Tlox)LpJ!CcAEc@Cpw(7 zY3Wa|i8t+`Vm^yh_!_Y8ObxyOgl2juMSr_Fr(|)RF zXn8u`n-1U=%4y=IBwMTc&I&dy>BoY*Z8%l&yLTt{TeM3ESyD{?Fr!Z|zFR^jGgiv= zUcLc<&DWLQo8u*T;wK3qGjsEmb_M!VXU|dta?P}F8adwNsj=R^)dW-gBTkwbLdE0n z_sLNlS3MaJ9Jdu%Wz!@0%V(`6=;g};K9l?N7}9e{JXx#3=6#jkl7@zc=RFqh*45X4 zU2sQGy*iqpQ?g2fo#Q&incJ~5QsGrN;xz=%MBu!xp`D%Zu;&CVsv54xzPqRA<7e58 zKJzb|!`{RkyvAm3$sUjI?b|eqbL=2deaKPCsx$q6Jg zIyzc>$Sgmxpx~%O3A^jmkJtVI!+T0kv1s;f@90amC#qInI^G*7vi4glBh9M&3g%w7 zAPQ~z{^=9@f@GlN?40i&USwKJ}HF>Fr8Wt=(FgAnM)dhkgH`H8$8bxAFu4mV`$etZE4|FX4F;zrTlz z`@)n6pP+$1(E=-6UUtIo8Apg53qxTOXP*o)~OFNG%{=&|G+G>#9_XoIp z5|%IW;q{>>Lsljlc6-8x_s(mOl8|MB2Ylc>_Vqxl%pLq@ZiK%0FI26!q&&HC^v@{DEd-2w-TRLuRb3o=v@RF^aUi>-yp3Ke+Z_oY- z5yK}47WUn4#^_8^M+~nX!sbX;%IqyGK$u_xh+Mt5z2@93QZfpwtsba=Gu$5nygb)h zBx$E5<=Y6^n@bkR)OCd6C_}!HmkhpysK;~e932c^1JJvJsJ=2c+iGH4oV0#1sjg1( z2LwiGkHxp!rlUTv4i%%H@<6yo{T&yuR+ z%Q+_8JmbT8rV7>Z zqsV{du}^NL5Z9VrN}y5JF@XGvfR>T^t7OWWKzR_2PczQ?xg%I8qNAW>cN zA!(H&F(-$Pw2LRvpg?OBH@0q#l`0rqyj2REjSO}C_;K9O8~jdBZl2kao0e9lrXC%QF8C>f?_2LckAQYabt`&RyW)k&pRs^cL|+rgSg=k$4PS6qV2U*KglaqLBQc zIpsYQ?iuXt-z1yS*{P+Yqf>of+!Pj&CuGFsxvX3>nEkkY&GmO%Tb_yG7X3xE%FY$4 zs;Zd}1>Siw?drJ9$LgH0!BrA+fsQ?98D7tYn-Uj6qferiYYuWX7FD%(c0L9zjO@7| z70Thu7*+LV(s1Mp6UU^10t=dgf&vX~?SSrX9briHG|cDfewDf+0qM-`cNt~-gsI-! zO9bI3JDWUg7Y3+q>wC=B{dP$Ol?L^`{<>p==&A0Bo-9$Bgl`IEZ>KkeFx$^1*xM-* z^v5}8|92$e2S9aX5`l(BVRC1JRmGCk0^$rBDd2OM$YqtYx{pk4y1_#MT z;!=jnJr4R1A+2duS`y}ZJVCU{_uh2q?(MAwzRt@_k)@wo|BRMh$Lpi3(i|S|1#$@L zo1om;vuE=RgsrTtXA45UNCt_Knna&`)J`WyJ%9fE{=hwMzIj**su7D$mo+ps$xvT_ zPFj==?_p`5&3h%zx3oz+KTnC#k*3uGAo#U03a-kwv@miIph%TS7oi=VgsDQxdEth&yTuf`|b~8yPDr3b<$hRop^vQ zzo(~b?~4ckT%NEa6Cf_2vza zcMctwjBuCtt`94qniDGe32oT3ffyt?0o^XNDZjVACa8mUt6KjFIauE?V|xBpX(yrI zh|s0o%TJ4=z+K|ssy`yLH5%Y&7H6?l&kroV$NQVj5fIr!vo1!f6qt^;XV38p=&Nh) zgMj#AWN%7xXeZ#X9&W3uPLcO!U!uWwYE_kqE^gsD@3<#Lk7=~yw*!-~OO*L1>2*kP zlgh6qo`&xD&LjoiKhOQSp}syjHT8O^w5-?ahY{?ASt@mjqt>0g`RbW{1rhu|dKD7_ zHeG%28TbAfXL|RFc1;rOnoMGFd1BK#$hu8?@&K{vIIkWG zcYK^Z!`d!hM$%}`J^4rGzQ+E9VOC54%NIly1A&9}1~4YESKK_woJ{QOAq||~Ds-mff^OX>f!^-~-zj`B z)}xQPe&-IWUapBqc{m2-c6&XLN{k=0ynosfBboBy1Epid3e{rerb)HrW)i>N$CRXy z8cI!BG3>e(s~qI1(QnL{y3W+w#QHiW5c|$dT|#6=V6>np)gn9yUn-@Db#DE4jrHF} z(f>}=5Ub8MEIte(8L;_6_pVp35)#7TDtKjOG36hX*EjY9Ay0{KKhcLvWaD^dcU}xa zEF!n^S9MlvK&=th*|B5CtRz3Opz%qI2~?6Pz4VNpM1~HA3-<$p5prcx$#%iAwc8;X z_hZZ{W1qHuW}DWHbny#oB`&CXJ}~H6)G2nA_UfXCvs!k2d1OfK&S8$RveFk3m1^Lk zX)mXyrVf1I>>1oeL?t%iogsyJs0`%;Lx*A-yNHNLl(fe=;G$#h<(j&>Pa&h++C71) zR-i{ek#e1a$|tJIRM2~KQ5W5>`KMe63W9z-zKm_+q~ctek)>$QSX!CQ>Y!? z361`go7;ehrgkG$#u1JHpl_(DQTbTlM*R;icWbMkf-(hPI5p%B(W)&TplRsRky6*` z%%;Sl-X&j>caJkH`*C2*@>*JN_Kf8diR(}Qdp5jb`$K5{210xPlG*peYeG-Td{Z@Y zB$MzxBvIT7jY^CJEo#)g97&9@X7c_h?Q>efLUHt&U|;n>NVP1a>=mf=pvdMhqUcFx zU(taz))~kC83M&g-zB9vrYjqwGGREH*Z=Z+_X=($h`D~VtM9gA0MgF$3WL*HRAck&2X3ea4 zG?w4MSqs!m3~DC-+BAS%Y5>!M+%uQxc6#+d%I4l-7>7dyEYpq=vE=jTrV(GLOP}WF zpMZP(^YCe&2I=n{a1m#eqa^Iv08+zUGjef-aqTY$X8H`7e%MPok0s7*do#;_QfK)^ zg16Vu)ja@o7~vYAy#9kbkP3^g*ULYcu;HqGg&|*S>$8xN7(f+wD*k*koR6$(RR3%@ z(PMh2W6g^^Zd$T?m5Gt{c$(^rDBRP^c!+3|wE1|Bx}o8F!IA7cg|A+}CId>D08_k5 zhr4y_aQvf#cfx)pvxU z2f{b9^Rqv#BBEyY;rPe&_^$wwASg3%afz<64*6zacXxWrNhIP3=^LQK5F>}u>uzx%Cp8V{ zBq#Gk=U9@4N^$bUtBj!ZW1G|!@9W?fqCs=Xr1xI&7k*ZE2$BC$i61^F_5|f*Wz|C6 zh(wOElZa92ZC-G1&LM#V1FC!ERrJ;?NkiS;r`JMOVIOMf#$$+c`bZrJ(2O$gtJ*;N z=FQ@wqDJXEzy&M$re!T4YEtbi4wV)w6b4Oc>l9evTUoZ|b@avRo*+SKJ2XsEzI7!idLK@N%feBo#BQB)Qc9fNEQqhj#cjum;RVrMQ3aEe0M zrK9T%4Z{NinM0ITa|N=U-j#%soxogXTL`(C1-_F)n2rb9)PyC?i_eP5k~UgxJXp^9 zI*RRVa@ss%L#EoBRQZTFKZFQ;bSJL>ts`y>TI?VdJW7`F4<01!Eb(ebR!OtE;*)(2 zl_$53h-GGERKpBVRPC>)%UX||5YHz;O0EGt8ORqvjZFG2IZRz;%YE@vQc|q>Ro`P! z%isAEtP06ckgs3zC-@u%74zMMGn9vsh{1UhCw`2jba+RbC`;(pMxq_DUOfSP2{FYO zwwXz;=l`rnq$-8dA)D#`s7=@q74(?P~&c6$N9OvIg54dyeL6b?~NA_ycN(M?|}pjQux_n zU(zG{pAMRIr>NHpHPO2Ja=r=v58a6C8zZ}N{l1BtLWB)Mt|bXkHDa@46zJNOtI7T4@wOV`l{AGv$){+O$=;ecmO+SFrfBy1i1m+^d zjZEi{O`?g9b~nhXg1ejOX8|f5fz{?vGU(W-<$(r@2a(zT`~9z*Rh#IADZkcube8HI z)40zWetz?wOx=MNw9?WxZA8bs>in%9d?JUMBtR2HS4dv0MKpG906Dra6kkd9Qk$&WbCsp#+06Lw}l z!X1?f%KG@~LovdW(4#Mnrs7G)?ZyW0pyn}=2fWg15s-0^%ZEWDTbh1EgS%vKp@d67 zubIKC&iluM3%IqIkw#GsP0rVrAIH6znl7e7OyjOCk-t^x*stsysb2cH141_-DU`rF zH@C|i5J4^@oF((p%x@{CWR+zi&VKtFZY+yglQVFs|AfE5=EqNKi-+8+Mzao1E@6T2 zyo!%M=L_Zw@jTZnaehl7Mn?Kc@fhA+dcA$QUL)Tu-~6T*0wn^?u<$2Y7C_xcG9!`= z9+J?lz~N+f``b|0hob(WH9an6uEN;n+zPrnsbT}+%MWK>?Xl}lG0Rut5+{~UQpt|2 z|H1rG@Sy^r`+em2pF)MUeZo&mj~tT5LrbJ)vwB%6l!Mi&m^Wp&*A=qh)edjm%XeJw zBNpC{oK;jbq^PnaN8xq{M-YK!wN=Z-MI6!@fP}|6DaN4rAo&Zo#46=-TInTQY71TX z_tTqaWOP*d!foytm=-T3>ClZ}7fy`qi~&i|cqA6ai8kCffj!I(Th_cGG{QPbKt$wv zrQ>A!^^gd>gwQOE(?yG; zHH@EPaWDVK8f;S-I}$(b`)<{8B_}77FGoo8@Q{~ZqUR2I`4W*=k1rh_@?NS8gb8g_ zvWB|=Gl7XOk-#ZMS2>xBq>f!*5H3dB10#`N zZUs~iR%uSRza-9=;?{lQXDo{LmI;Qzqe@b5BZF>ajSy5cNT(K6baiwZrGIyO7?2bz z`6VPyw4paSKyP2FU}AKuO`M5N9A;!?rG8lOLWpqgr>y2uV{7X>e?bcJJ1YD+SvP|6$|6CQw$jvBZC=lEW z(3#CC2PnqV&>Bj&%&Mv?<)2dg=5ST$6bShMv5}yH1Wl;!*cLJ{z9x(HQ~g`2eU|sH z!tDQ(>+}DhYA9&n|E-nvh*7D_BowN#H)GU@cOS0W-IdEq|8kz%_-| z$Ei=quZijIJBP$ydwWTBYQf6>@!Hb$%Y;Z~;;J!PgdOGdM{?v@77jo1Is7_%ht|GL z$=bm#c&U24apEnSNl)_&T-ALQ{5nfCQ|+7SWO6r_7`>R5ybn)xdyhJIk1vZdTSNM? zQ`a{$@O+X@gWjb-lj}6I+jZagbAOie!!^mh@$+0=J_CSMn!wEoZuvLjM1jj#cn`l zFMVT=E%M3$qlM~q7~E1WQ@i0?cQ9BAY8HX8xymc8O9c9>;4Q4c8cJk`?dfsGbgTls z0tVR`hGwGp5%h)n%UF4?xq&C;z@MH>lc1U3{WtC|^TvLBbdWz}p9#E?<`?k6a6Omz zcN;8t^*<dzuW^|n@F(r6Z{q)FygpH<4wa#wCEq;7h8 z$24ftpje_WYL`=|Ict-l7VEDpq?s^fd&sZff){!VznY;nO@lXJj(wRq-=&M^3iK__ z7^Ec*56gnbNu%MOnO|^`3K=T)lb2EX*~H~2Pn2KbD!w?zX}|9v%FoI5u{%@i&x)5Y zek>6_A@168*tNi0ODh`^i~@=#k~hn#8O^g%eiyhFe>%)vVtyYs_JXsC$8%Dbo|7R7R}j#6u(ZdT6h0vF1sHjG?VywY=k48_98 z9kmtM@N|vehQT`eXlIlQa;MWE%^y0Z_=-2E%t6+I-k`T~w$3(d)ZUfH#*9s=PE~_& zOJJ#fQ(0s(_v_%4qQP6%pUSw9d@rHmJ7uZ=d}cR%rkrAcuISRXp8Zi&EO5=()$i2CiH)(zRa5t)ld@K4r0}pQye9YdJ%^_;z$xn(i zt0esbeezTBm{gjUhW6!p?JYbhD&XC!Y~!R+1MbmNiL6t9)t}@fo9cCyhd&uuZ`BP= zYdbp9S#w^qBuGx#HlLpgP0f@p9~h?0zc_!ul6OE>nxiQFn&ZAkBwY{4`$@y4&syUt zR-DQdMiThu^RtFg=w0UZw_H@K^F2NLg!qwrZ*P-(Y*bg~G%=}UAi5IU;VZVH?oS~y zykN<7q)XB#t4iWn7CD}I$>l4AYww__&Zkr6mwl6|VBNBqs&zYTKy^ZYozoE`1%F&V za6j$IF_d5WN0ac77iH}}N0_gao-5D#*Sb9q>(;Od7XrHhCZyrRQpE|U$<#;S$3!dLK;^2KOx0zY7`+<~uP&fFOv+n$v4~_h02MuwNSCG3Wmx($3;6eOd zo8Ebulp&6Se{V@sHH!AWiij@~6DFmHwUup|s=myS`LtbWrz>F$4;U-&^6go^v0b=f z-7;W$+kb=6s_)J4-mrvayKdSQ*yZB0Xp_{OXEk*{ekj=e#FP1DN5bW1mjCo0mWD}u zlhF4R*~}+6{X>89brbD!Bx1&hG{zB_+m5)(vH|??T1?TykRvwVymUA8bYmd)a;z^z6plH74ll&3r=Tu5a}N##gD8t$oN5|gQOAP3n8i~p&%u7kABEuW^)6Hsn4!#{L>{u zYdU1@Sor@BT=KuR*c{<|7UZ1rwdfx!-O$&2W``Q%?tjg7H7ow7R|WagD|Ynw?Et}7 z&LJ1oBY z$K7KBPBR~$3UHcDPECy?_6S7Z1ta*v1GYp^l1(LIG&ME-!HkjlIW;}K)~2}09&9I2 z``4JHPRq;F@W2V+(%&^t%DcK=K@Gt){lJG=JIoaVY z2+@cQ_66$&CC)-9ird->A>`WY$M_z3HBd#rFxh<;6hhl&75=zOgB^%0fFS!Scmn*c zz+9kZL<@(L`TF(iC;^)f1^I<3p<9$k{d2gIqxS_7;=)4tN`cyJ}IIHJ5xQp?79>ZSzX6D{G z>6gGD1ZL5J`?YV~e!GVgpp1uYVBd%h|v zFKlAo#qV%6wZ=)O??eX4*TOP;&nC&CKI~E~QQGjysDuta9Hd2%gcSaw)uLWPp%*xWPJXkd=n1euV25up`!8@eJNcnuJZwnpaGF-@7ckln!Q+jvD6`zomShZ zowWeuI}dFfjNo?jH9ea`0=un4a837@W=vD12zUpVThQ$TC5~JusHikv6dSt}gHKH4 zo>80uS2ZYAA58`}ZI2&2HVSLxE7TN!dk#v;uo zP=74q0O1%M`P2sLO*_Zjeu13YpqY!o4=(Y6qS_dg2yDy>tB$e zIAn2m%Rg$HebIpeUry;1+n2lNe84a_U>7%+y-xrK*VmICzx+X*lG5A?m0pyCDvX5C zXw0A!Fy+RI8a{N$fMgeXPWfFP}rn`lEV zVs$e}AB!!MU>}uM%O84B_}v^{*#OI>xc^K{%d?7#tED9P57^S}C8~S7PKT;@n~oPc@G)c*@4y!b<0Yj}S#|v!c?+YI$6{=(dS}0eSZY)h3-SmTA8fFRhA?^- z4Wz>Jpb!F);eI?U2Y3{}2b(Mk?JY4rKK{EZB_*Xiwp;ySs#w&an*5PR2NSNAqmXaX zCYLM1o|OO!@zfiL0dy+r&y4~-q;h{Q&xC!W8^mW-avxVJ6l4)=$=L$vag!=ZOiq?B zzjFqz7#0c2Pv6ArfOeY7H3&axD$$QY&H%Ho*az6^9BS#>oXVKSmX_;a$%Q%)VsP~O z1+gk%a6t*i!iMhFwQFS1ng=Dk*N_;&?9+4i#nb1hlo76%>nJzCX79fyNtMLzSiy+& z;pk&>S$-ZDo5D!<7lS2@>e%?=66^w9uNR%e{#2;K{_I;9%Ca*|{Ml--u&-|wW8+O~ z<}hJ>eFosyLZKkO6_kwYH<3^!N+Z$@~K_K7YsH#5+M z4+`%T`>s@ei2ETL+B;8ZnmE2@T45quAI6nCcPAQbm5{ffef0%&;M|EEqTLF@8Z8x_ zJ1C`3#Kp=wA3~ky*}y_Vn~EOHrQZ2452&Mkd1!uYXP@#*m26VmvulLn)Z3BdsLaev zq*0>h^JH_RIT!?tsSX}EaKNC*iV-#HyFcw)6yx0keoHb;E#^)ubYM!ETr~(FK`W0o z?b(zhA;?;ArG%p%HM;>2;rpGsC7!Ueu_1vUDXb*&Kuyfc%M17NQe|D7DKs?pyesSa zvUuA}Eg06bfcQ7 z^CP?IcpE8U&&SzLiwAvQ#6X{^#XclgB;|nSjx@jm3W3J3m&WDpv+ud&18!fxe&8?- zjc%?Gn4X{lvGMBnyUuqUH&#K^2uW7Wp$GEx%-y67cL0bc|0|c(7#FP3=pmx>itj=K0tnP z>m>x0cD@6rLnY6g`If7%awO#>8e8;3v?-02&fDd{h2-Jtd&x9R`wNjsAcalc(J}Dh zy>!RO+XSn~Tqa8jj}T6qs-T{whv+5lV`jQ%oF%W%KVx@5`Os_5ErInhTTkf6gTh#K zr{&SfgJ0IqtdwVEW@>0@9bGQ=T6@srJ=K;F7RZHT0U_H3hivPgxtK5*m5-}Ojj17a z6$GA!Ky=PakZnBHv(kZ_8(~zo((()LY^T(1yuC{-e8gy9e zF@80SN~LDvvkE`Lh`;@7j6Pz>K^ed%IC>_Xl0n-hZ0DV_For&X%cDZ=v0;FI5Gx@7 zB51g40A~>j1$Lvj4ThnIU8)18lQ}I*26Zb>18lwQH0mc|q+xGwPw`;uHK&=3zdMJo z`n&`2ATO5XF+t5Xc!Ks~n<;pLP=0IEZMKqxL-{W6;?F!Rzuixv4O;T@@r>SUcV6@wrAWyym)i*kRTOJf;;%}L9!(lIbzlB;|Du7< zdWSOX(V)=KdVmCsc^xbQpYRMGJuMGh+b4A*>RQsje7UUa_ya;L57KD)Ho!t$NIys4Q3@*J#IvOZ zxu)=P)9v1brug8jbc=~*+2IfvlJ_3u9pR4O@|F)hX{a;TS^YH7@@VeqW?S->QyYDY zVU>>*)TMxctW3o?CRbE&AkFp#_o-2d+1V;?{Er}+KuHK%0y92+LbmnB;*b#jzGB&z zm?~)Z2HMpeX}}{2Zt%3Tk+(lVmnr(uE?CzyHv`KI8^9b+hDoUso#qs1PDn_|74&s; zE1oN5)VL}wZ^yK4g4?#J-kdyX1%}HuS$gmeJb6O-XQ*7i3TzLb)x#oh%$CjP)Iu`< zZMfGYw!civ+!4yZ6bd1p^W8+hu zK@8cK!fGEBeryubd#}|h)^TnmGq3;$HgO#SZ)@S3sP2=@%=~M^;H5*0w*_QKibc(Q zP0z*A+ix_#919ZDL&Ua!E3^E=S9 z{;6i1LXLT@5ii&E#VL!ajtq}_YOhD9$+x2kUFW?{c@ zSCPk0IOZValI_oos^4{42tc?Q3;q8Qu4v9j>zc4`k7w^eHxEvso=+tTmEQF+lYhnM zIb=y;gFHEKM?k+KG%*r!%AmNlOPyD&T!2mz1;{ja>$P93Ff%>f-DS!Pr02?cAA=hC zVEFpPjN|Pe)Ka*;FR@nVR;UopGMrU8Hlk^D8BJ5^HXMDk;W?pQlP_~N{78EJi1A?z* z{u--k+jmdXpSt-_>4-w#XM1)?BDCs{`4C6geppQ%w=OREOY(8H%&B zvpJ1Y|DKhx!$rl^odS(ENGyjw0;sPl$t?Ln?`9Ac@{kZb1YSbHgg1ZdQ33P;!DPZ$ zu*c$YHoSrxoL`lfxEhde=`+VOc18?AFw`+h zBgJGlO%#>cF$cX}RwGwP5>+p{qa(SfkeO6GCI~^FrDTRxg}8kUk%$LW_3x@vp{&tg za)qqnbPX#=5Z+o3GxV|z{DDRxCXjOKWwgKkZf8msk%{)fe@ZBdrwqP0C5?n&-+2nU z1Fvxp=Q3$ij0A!Dv0dP^u^syTZJRF{ElFYD%xd0=7{SROLhOAIQ2GiiLPokiK7}(H zfR0fP;ZhMV6)lS=8e$R-THp4_)9>Y0{p6ZU2NNeBkB|@z0O0~M zuZEKz4+r`Xkhi+Js#IBp6Z*KPZI$ zxCuzW?GCF1;A;dc>TJyM)aI1eD4Lp{LI{gQjA_XraF!ql zMsN(pz0JiTGOl|iFwIDxR>=si+`a3#8}vH&;0+qI$c^?3b7p` zd=#930q1%kN3eLUO(nrb26N3d2-h3-L_MG$(BETz*E%&$2GOM^-! zJ>CP*CJHqN`x(Tde_{Uu$s6n{NEe+=F*yp1*A)0Y;4qq#OSa&p%*e=K(Ryh*7Y{zI z>RzF{Iyz6l8wJFg1LZX2)@$wJF#@m#6tPoW)dQ^mT49Mw@0F4leAs1n0(a;(8)^;P z7grJ&e2l7lnTJs|PZ|Okd6lff6P1P(2`HAmn_a?_WPnoqc(8VSDef|MJwqZ`AOi#^ zl-%vxAu5A-Us(tT3O390JwJb@&9n7{M_T3mXPff~B4ofRBqIrFL*4xKB3LS@LLvpq zy9pJ6wigzWTzq%Vs$rYylGU&6i%_lUs`{kvv%c@VXWQVY={&n?%!V@PjDOyc`yTqx zD8h=bV*ebPDpJ!*C9XWXy_M+1Wa8-+E{HycFcLft4TXQ`ucHa9O={r@t}td)xPlyo zLjx+qGHt$;*XrqEuj!N7#^rhu^i|Y-|LBvR({Uboa3BSoNCFKv;3ylH9@!4Xu)^6i zlS6ltzy%D*M=#YnxV&;;)#hoLFEm4B@5*_^O4<)R0dWIp338rDr-Q_Yj~}Vs%PX6Q zgWTqSp5o^}2x;c;2{~_})#a)sC@i+UIoDlW3NYxizR-xo`s2-;H?Lkhdv!cP4pP9u zt_F394jh6wvKt`Q{&?V8ZJ%@$-|J8^0V2nZn>Vk)`5G`G?_*+C;9QlIPoGo?oGacD z|7e%G*6n{r{t;kZNVK%HeLyHTL_lt;Lw3+B1~?!Gx_DHg#SZ`>)0IUrfPRMXT`@5+ z+@#BuIEtxrg;74A&{cAsU0om%in32ZV_!oUm;Qm+$4J{0M$|bLa#v-ile)V4=I*a+ z{1)^Ctls`hccoa_%Iyf)dZrrV#ddhnv>e^h9+H-GBOSoTDB>H%7e(M zE~QSR)npehUd$L)R#5O582l4`s6)4wmoa8r)pIb`O4iNmh3DH#$8VDMd7w7f{(wsy z^2A{{-v$&7#5j*MGzq_PIZ`#aK;`rDM^61ng3KdB2U|zSKscHPbeAi}`Dei;a{HYy zsJ>ahEP+3`|LGf(wC){qY9wyf*VQ9EskpapTvl!ZVpsnv4IlLv28wBrm&nUM7Ip>v z@lN>8(d7^)Fy28wv44*ZLE6M(G`$2zRXA1~NKr))q}Q2PwrFF&F$D90QJK_H+@(z>Xu-PE3ldp2Gl!Bb(1OPd&U+&ao@Q0Cw>jn_?bu z@uM(PAnAZG55B2alGbnkHh^F+NlH?XJzFOnD;fMG=&IjqmC?HfN4!|bt%j{ppnqCO==Q#` zAcess_h~-#sC<|SG zd%IsohQO~!n?opuW%R`@xAe-E_+WYVU!?TBKJ@`Tdo}s9R~ojp%=-f&;w}_q2sLZ=|H+{e>zb447E0K*N!=j!aPzP z^Z0Wx0BI$K(Uyo&byL1cDR>DCl9KJ-kE3|C@7@)rpx$bYW*OlSW+(+Nv4?%xhyi8~ zHav)4(882GBur4GS3J)drhNQ7^a(Z=AT^rTT`ZB!scesV*>sYpuQN!Vm)YMk*Hzen z(^0g3AO0WIy>~d)|KC4+N~J+oMT&+pA|qvFRaQ!7Qg$LDl#xA3Rw{`!$V@_LDEmZ6 zkyS>>3fbFfkNfei&vjkj>wEpK`#A37xc|8Cj!(z&kvg5{`~7;qUeD)aJ^6)&-zYt5 zt842V8FCyq5qng#F@*KfkDotZvE|rdHvw?~cympD7ar@W-}JtfmqKscnmw=A7S*@J z`m$tB+I{x*z~X=4KAVHYSKG}`U7jO<_#mpCz9xi&mMf?8qxmEMGql@1U3OS{F=;rg z))90$MUHD+J{^&uB(Y-?zY%!{4(}qq^t?Tf{99r15lyifY)F+u4%Qhfo^dPiC;J4#0#~E>vL7djp(nP1O!Bav28&*==c;XFLmMn1^~sz z#2oz{UjcvgH8_{4Nzm5T^*`$fmYH9NLjt>N|G03?4L_$yX}7KGYC6R5jLJo9zCUZw z+_mw#4h7OU6t%~(MP2&(_y&@fwgYJUTwXq5^?X1ZoP=)9`*)8%UV4$u`KEDE zs~ElB9fxcl^?>9s-R=#yisZ%aWQ|Ph983sWHhQJgtbMxoy|Tw8Y_R8E8&d(H#o?C8 zhA1{)^w@#z&hzRGq{f{77wDTUn9|?0aGt6+ z7++3)^@G8kx`%Y`JGd?rMExl76>1>34NaZLAF|k(HL3 zsv0SqPQKVwdyO&isqDrd_pg39BJ6r*ESE)5e8)Y3onO}~P|LE8n@!>KAjn2rrm^rd z`wS6pmVY&qEav~)L0fi=j@Ru6?!5-*@|>>~>csTk+l*ML@n5Cj zSqTCZt(Wx3~0H>!N0O`RY}elS!%had-E{Ek;Ll(yRQo1}e|o@JkIC>|AtN*{=4-#;P8` zVQMCL4!ftm01FOuvhr8&Qa+wG10&CvE9OPptdisCtUBi<((i2rmrA7B7GlXK9$7Sc5G>dY`!-}AQR`2@JCXM?m!Jx7Sr zP%a!8_llg3JUf@~diZuwP>-c@xyS7o#V2a#GHuw&Ft?XSm+JO|foZF^7vEt=*|@K# zT;tad6iq=aM(!G_%c5{04l4Bn3?m$~N1mbmuX%q&^JR{1<$Cf(Lttz%&I0S)D<~f_ zGgI35&e}6kxF>j{)fg?3j&o8(77fvN2^29>kH*&Q22z}SkzlplJ>|{$rdI3bpUBn?X&fwt zQ;Y%nT$EGMl8hFIx$!@}X1DzPQyO{&_itEqX=~@HekUHK5wF-;6Dyaz`)c{aR3tkM zIKR)=|Fc8pqxVKbdZ0ShuH9sn3zD>gW%APA)kjVlR^PO9+;@%t*Afjq$J9bZU1&SV z%0j~@Vp38&*xA`9Sh1z|jOmQe?61;`IrzQi`yU)8r{>y-J<$)LEh4lxkmZ1`yn1%@ z)>0$=8amiQDC4S1|O zZ%F`s^76M9V|>!7fSK)^1bsVyAjMKNq9-&9?k2eO;1TPV8NM$0!M6P#;hkHxe)eoJ z!`v(K`){Q(3c9Z)+tK|f0=)WZllfB(rF61YGn~7rJNId*q1r@9nl#6WTb9JW{_fIU zqb6o1rp59@NQ$g~&pFXFd>yTiF;Kna#hW4X+xnnA079{3*t}*9L31GR^wFrxD%>Kw z{xjC`36ePA_WDQQBqvC0ycNG>o{If9*?Qgtbc!mXT|k+>O11qR&sTD+;Ems*g*X4eV@v*ke(teLA`4T+R zTJ05;m8D28)V}D9b+J`IzfUYO;3fA|X4HC(sH52L0erXgzZ18xV4hq@7z12oZeJHz zU#m_?Vtm%eQJqvV{LnHi?lFI8dblOgbwEr*ZE&>c*5h?<19iMRWZWO$SnYUHU-nlH zp2{642EX>4xqM;(!nD6x#I+0!c%gqXgF|-Ha;;6$2q^q{Ds+75l>OMBCYdmgNwEGf$PJ~^_SWI6%5qeW=Uy^20#bj9y=rv z!B@rrUQMbW$M{@{K^vw z(fOIH*G8^Cu_<;;c2`8D!zm)7MY)-NfsN;xYZRU^xFJyz!PMyseEEDYp-#GZk&{sK z47WT-jxHc)zuuS8CskB#HC^$;wjU+!h9IunfZ5Qs(;#Zo!rHp$>8#HQRImH@@1Hlg zsw7{xZ7s9U=e`Re&3g-3)SaU}=^x1qFWRusNg*+p7ThHO7eLzSt`jK34-;u%1VQeW z0gM734NsHVu}<$%)%OQ22umxXTkZmBQ?Oy9MMQM+={KWX~1*CNf`HddCFH(PB+Csb#k z-MRlKT68rDnTec4Z7k{zA1*R;gNVR^)U)-XJ)=x&w?z)+`Gz4L_ifIJ3AfeYPLT1S8=>j#`%51 zb2(7(<$einTjJigkBBP6YofX)dH?=>3EG!4qEYYF-fiLvn{fOMz0m#Q)7Zb=KF};=b2I`0T6(K zRWj}F*>3z7%qkq7) zWC%wwtRjq;pWJ-oqGk+-!?0djK%+l9Nb)JM9itDA?m2@FrZ27y&X1Mq6HU9Eo zAC>Gmr=cG=Ah*L!fh;ijw+YW^319D3Z1jaJ&v_glcYq|;SD7zZ%3=yTR zs@ay~$OlA|fC1|tfN&!bfkMrvcQYGZid~BUpR3}g1`eX*XKg*EOUE}IRto0u1+Wgx zXe4h^l@LK~mHmtCfOicKO@TTGDXl^PnUKvlHR3ft)o+*QtfWMPp8SGBN7^x7UGZ_)b<1(d=6Dp(~yZ%uj)!*f4HQf zf{~B9yMDzp+f%oE#XD4Cg*S6w+stNQD_!pj@&Zue^0qnl3@w#$KEC;;+4P}=(fnb{ z+PPbL@i_xep!_MV5G&F zw9Xv1YMAO1;;0p&I$FOS&gIt#*?|BNVFT=dkZ6u%ZwCq9{j6+iYU+OQDdi@6l4%m--!h~y~M5}Z)usF7c@BTd=(YP4)G4J$z5oa3F|V}?(}GTFjQBhqY%gu zQEIPW3t`jY?vM&ncjcNIkwy1F?2)9H7cUeY6P<8F2(%X6YPaX=Ynfz}7^AA5YH+zJ zC@K;J$vAxP4ud0EwOw1#*Ijt8dx5@2BzCjq(&|AE0)Rw>H64i%LTIb${)gX{c!StCj;Cd+SI9Z+`->VO`$&qORC6i)>>4H# z;Rq0)k1$)}x=-?UF>1bD(3vH=jdXR>u=CX)9}G9{Jud9E>|QA5qPLo9?CvN_SAox( zJxDAtDmeeN&L%U(l^VGvi*L6&bx?IQnMeD!3=<0o7fgkPZszIJr^o7Fb6A$Ouz=tE z4>^!zB|wGG6%}$OCUN`ISw)>8*3tHPk4%AR&w1XMEKciNe>M*)as+MjZcak_f}+ny z^wk2SQX7GbQ;`5tG}tsG6tIt?E`uV3k%c8umtqC~wzqAc_Di~7QM=NjvEgV-Bj%2T z%Yq%~?WTpBZG-1|g@r>-_WfHPGMrZgpTq|3tFj{{5wE!AYgsl{r z9_$R{jyh^)whtoJH&%@Tpa4I+FBL)M0y)+bm4lUtPryz~BIt-GGS`AJj0|{ zFYWt0P}#*^-rU?w0OvzLvzdXn*}0rED_lzge(x<9Q!jHz^=oLqs?Yh+F1nllP(4I;5HYNh_N^>#E0)NxdPk8E zo+d-Z1i22CQG}T7*?ex6=&I8?sXa^0)jaU2>xr>2* z8^8*qpZ-bNcCB^qFxSDO5+!B;Q>ctg$hS0sk8Tw-yn`|VUBN|w*50}_n)M05AD z&3atGBYo66ceJ#$)Z)q&loyJS7@};X3jI>YDd#CK*9nfM(Pm&vY@N9+hoC`2L&Mgw zqD$qHB6Wyt;e-r(LUY=3NY4{gakg+rjp^Kl0qPa;Gp?Hy=fqe~yzJS{_A=|K z*1Au>Q{}Jx7Na7;x_GU~WsaJWyo>W((_fl0H}7Z1m$d3|hH0Vfbv z6i-7A3UO5d^}%5an=e{HiVst6>eF*+4hY1=Ifa5AI)y&nXUQVKltZg?z0+0Y4bG<$ zd&if+QT$mk5tcq@_~vX5$bBa|_D%l!O-e$V(fN*fa>_)`Twjj90C139Qd0VDP1b~< z;p#Ks;HR#*dQ?L}2CXl?yV@h??K$Ojx7!Z`IN5Q;;l%roA#F=E74$~&k~ISw<@F9> zqk+h$MvyO^n0RUO5tHaRf#K`9QrDrw0zpvBoIu%;j+c!#8)G*@xq&8|c7&+Yh(1|L z=$tG>3WN+E#fY1W{k&?gC%5#uZcUL0ET9ijn{&S% zw`XO|`6;6M>i=U=+AV&5Dq8$}1|vsVPhbM%+7tD)&A0kYSKhy*`X4aJXWiWE2LOC> z794`A5dT5wyT}&7%%uWZH0Y(9`=cS)L$Kji{&O+qg3$S2oSW$JEZ{^iVO#CtI79}6 z$pB=J`1#C>cmk1DV^ec<71?DEyrmdB9nCUZ5XaL)zi#%d zAY%&wm~`@mp4eD7Y5ZKqZP3~OLAA^REvnHmXDQTQeoa@x2Ri{AV5-R2;m_zax=ZxX zt+gj!`C+Mj_UtcI%uvWpI0gD8J|OOf?R2G{dfLIgU`LFh`Sl!KPf!0yZH?G39P$t4 zo_;0Mls6r&c&(_Yczw{RPr@+t%kyS|@RhrF?u1=7nGJprGS66~VQOj`On>d0Rumc# zNK3NZs~<5m+Cz63yqc-ze3Wr7UkybH<7(>LC@)@4&(k`*B!yJ%ha_!_H| z7MIQPBeU7*!JWiw3BTO+2dTIyR7(eUmHIv5+;3#^eBD=06|=O&$6bbCRDEQ(=ve!%GBw*%R;lYUBLz2+Q62ijek%w-lf zw{TR$!ZFtpJzljjCB$_!KI`f-zhTabV&vSA7Cy9c=BnEOpzvdTrv|K`j^W|qSvPyA zw`c&Sk_VK046+%%^u^?jF%EEWTo30kaODl&XTdyE5ui}!|C(l`RSgf!aaY$P#1xaJ zqeOLwFA!gl(d2mT$g_$1XhPe>%bV0vCU)+Pr=K7ChmTi8FAkjPYX2_paige&VU||j2N2I*HSFWS^zePGOzPDX}{_^D{cM3OQQ$Wp*o+=|EfFff0SJ9;5RSKor z_QRKU5GzF7v74bPa&a?foZ`i=B}w8=1FP}nnFw}n8UC_>m$g~0LzJwV>(dj}oJyRO zHl_FH+!A2HK!kYUSHZ^V zzzkLuT4SwVPiE5V;qe_;+@xqmS7w4p-i>5QoflL`Pxo6*^fqT2`jj~;F1x>+qR*N$ z3Qw9oMO|Gf)=o=uURj#ChKl|uqcM*GW;A#Uc4)1oLvNOaJZB;F5(*<;Z(D}Z8B)zC z=bQh5QL3K*8;r7t?aE&qWx$DmQ9vOTzkgS7<3t5KzhxRh%wCJTVUS&;U-WiM-h^1j z538|Wx?mDHoB7Sz?H>fP6@H(8-{@Pg)L1<>(m?UHZTgX(zI@nl{?lFJ27FS9ynRz= z+0Qz-x1+?rHTn#kP^)uW+stfB{wL%@*dnaYB1#R4qOFL|LQ_iwuWKWWk1{B@)7%`T z=6mJcEy$Q9|1X0A7bt7SkZZt2fQW>4PW;*)VEpL1YN1L%IbhYk>ejhv&?Vg#wt^xoE85=^pmlBq5m$_`3-Q6kibAKL6i{{Js;5$*VNSPnz4GXt8G>@ zlJerkr?G7Hh85WVLXfI8NSFm7RwEDCp0J(sRUhEqzkdVKypW8mqoh5h1HhpvojiHl z$bhF}FU~=vv?hPM1(J{0EDgWokcJTNeu18w4dXA0pG_S-oys3jK5nD1$mIR34*!4* zm7;`u*I`=bgdw_XnUdK2%EJZ^t%b})wd^v^hS<`!Isex`JSjg0sY*|(nQUt!6D2bL z`M0Z~0<%*k)Xaa>L_W6vsU}jmcro5m!0)Z_tH|Qrzc*R@?@*A*Unt1DMsnW7P)TE;ngdC07P&aReY(3$QbG$g5nmC}4SoW&qJGKCU0q#}^6b!-;q0M*?}@g!`xhsc%WY|Wu5Uzj)*q*$+TN~gj+TK? zRe`zva`EoHdn1SXXyFklnvabQERttQd$vRec{;IesCkalxlatOT5R|FTExO4xxzWh zC)W0!VMf+y54T}(F0aN;o~jm;T=_jw))$*Zx9#} zx`YaeE&t^_8z@dfs6R120t4wVJ_7Iu?)gMjuHB|Gq$g651oOs@r+;n7^qWG^u4XQT z(hIu*G`H@fZtbCSguRqBHt2$E=ZPS5oVLlvS|oH`4YAJ-5_i!AiR)itfrdQhHW2! z5cGTPsq0%@XLfGi&gb(RA_xL&fKv5Gwmmn5tx)cncD;#>JvO4IBEAG8t|<`0#^t4j z9x_naKpZ2V*T#nI6Q>rAs6@Uby*d=Fn(bLmt1Zq9B&p?7I7e;;<@Ta1^RMW6AT4)u zok|RH4$nv7iH94EifZe121i~(3q-cXlj}V?^rAZwgSEXOD~P+xMTd7 zzSTBAH}tN$dx0={6Hqe_F?d9hKJcbjr=2|>`QQ9+Ve@I1dnB~K+2U8<=mgPSAuNietVI=a*0OLA!P23+w*LhQf5Od9_=sX=>=(ohXFo!^Jm%tvprRa8vO zU&=w4p*Dh8b}7@7wMsjA?UuBh(lgTr{QU$7{XJrXNESs-#Dq}-J0q{ zr&jO25h%xWD_PxJ=>JWnou;%FD>1Eiub*oUvq5U-!E?DsT!gBT(pvAj8 zig?m5hZt1?qBh2tys@CR8(yT1&27}vp~%Uxz)mrQOZ!?SS9{rgq%KgPSEfW)&}sa3 zHq)R_r4;doBY9oK0-ErxVRa%3zkhXaJlaGmeY&6SG` zvlm7LMbBV6fX~Y z{I`%h^-OTNt4W|OyOhQcsxnRAql-F|JFLn>2 zIDw8?^`75o+KjQouafmgYdQD$iG%VlSU;Sfnwc)fmcy!Yi|5FBX<_As$%kXLdcKbx ztOOMAZlfX1cDI_`VG~hZ-tn0(^Y<@YB)h1R${B&;Y%T72{>SQ@`p^F(uiEi{l2=JP zi5^lqG`8>&iryQfd^!{7`xYU*nm>Um(Sn!1YTrbAa0RDO;Gc3@~DF*y)DjGgmop!$i8Q5+@~ zj~={CF`it1{K9ijVC;l{0wn-p!sWXLDqfpBQd4!lW|`k%#+7pe%!4da_bTMhq%Az1 zFS2=ao<7NQ6T)pckXN<`=|!xJV#ji`TQ)shrebNXGN~23-i0o?dvZ@n^$jj#wVcB& zA+|yl z!&a_?S~YsI0DYp2ppIr6h~Ht!b#^QEeyz%~Co&#K2%S2`)oroL5r94TF?@X{TDx`k zRz3zCIcB?>o^de5Q#k#0-`y^zN>=;Y*|&*t-R%qS{wl!E3%TYqI{H>W={x@QtJFF7 zib6vOdk~QHQSnnu{Ci~?r#=4$HCpg`X-6cqXpVYpHu7+wR%MsC#p$&mqG%+xNoz#+ zR`KZ8_$EUiJu+pls{6T3WkpWcCJXqBeJ9N|wC36Tf_M1Vx$P`X;`BdLozR!29wqVy zu0*2z9P@Y+DESL22!s~sK=T3J0%h&UsH`^wm$5|n6;agCjzl$_e{r;h)S;QnuhK6 zn>)6PwAa?g>ONCYmZB#87fN|}2cUAF9)H2l>oRsY{AJWQw_E&@2AVJKJZ4KTO0+R$Jv)W7oO2>c|`OrA65HR;_V=q4>I2g(o@|a*GSIi~9$?;KBu%XE$dwTb1f;7!)!gr?kWqXs+t) z5t?B@HW#&Mx*|H4y`g>X&Y#qgkfNBkS5TBr{0!e6DBIHB1tTRTt6qbywBYtq^c@ZvqMiCnJ?q~{r_L7`9Uaz7 zzkuEY*uYk=wy|}@O1UOx7Kd+d}z^skUb8YwOhZHv{{)9BA~Y5HiLp_B9=*UmbMk&QQZ>4d1z?)hTMMFQY+iWee7- zv)l+ci@g_m2z_#oT`A?PhDNL<4{}}fmkp2Uinf3n`|Bx-n!ok+ZLN2zqoW5|EDn z$rW$ro#7QaSZJNq+c}C}E~R4(efns zrp~%3BO)7hS4j?|JiG5i)KSW|XHwe{Xt@*Gn71lzqTJZOYO^LUpXci1K`14ohT15nc!2S4lHz~}s+v!-vr=(dHlb#gvSv#7 z^coFkevY*^YR}0XAU*)>uu*|jic=~)qiw-ZuHSO=^hPeAfMZ5isF6EoN2}E}oqWUz zA>8I@?s>DXjo}x*vY+ZqZt+J%Dnj#QIwaKFk{YKCOK`(}NYHn7M@P$HuP2?ZzLi-S zxUvu|aS)!SK;&Bzo;O1Di#R?3w}bLW4oU9->ST=gg880cNMZ)b(>#a|EUK*x>KUzj z3P?XsKF)9>k<2%R&(rx>@_KC{ za(hg7#qJ&XO4FS9tzL_~fi#=Wj`#@(YbAMGnYRmmFILf^CJBgd*Pb(=EL@v? z6f~c=n`4Etg@`De*1EozpY}=)&B&oQsJ+AdR69+SpkF(2}2sYihKq4{N zsMgpVM;azf1~I2c?Bh5}v)5~T@%~wg=76mCn9Ka6<6-MiRN$@-@1n&1NVj0!82`X_ zjr*k7D!P<`ud-607BqZLRD{LYlm6zJ#;zJ(`E{9wWPEGSW7K9_u*$K>Udv4A-Ko?| za#m_*W`0S1dNcj=f`^D!40tI5rE17gIvY+!wIw!E%+kAJZ`%TsbDA-JD=aM1&Cl;= zkXN{3w!PRKFyoF9=cMj2-Z!pcS0}2gzpQlu4?W(qb5!A%N0Cn4z=1ui-%<*~{=6(7 z^`%wQ#-^qZPQ|SMaq`*enDu5Kg*Ko1cw~82t|0JxxpG6%v{UiS_0KERNB!S1mU+&w z?<(9o7{=|y$zOiw>CWd1)*C-~B^Z|x$&n@n69?{`oV#u5QeVA1VNxiu`Pcv2DVtJ`doc6 z%?|Xe&p}-6pCHmXp2zF<##%SmUfC&sOwM3rbTmVrC~IKY+W0D0t`fVn z=6yQ8X(P|&-UR=#H(WVm%^aFqn*EO=Y_7Rh#(UE-&*%>`$M~PQ7BvM-S8rN4K-bbV z$6_`-eZ#6*Nc$a zg_6^dZTXvJ2W5?LVCzq1!IL~`XE3@UAm9k3F$`#tsFY7-?t*R~l7jKMW$R}C-OPNV z>UNG30OUvhZ`SL*Rb zXQfKD2^;Bc9c$Wx-N5u{w_`LW?;bv2RzMVlM1aXRC&P{6Hw>OMv}1UNJT$AD?AeS< zgc4y6$iDr+!j$MYdbg~kx~|hj2U2orX*;6Vkp4U>c1xMIma#beCS53#nt6jw^q6gd zyhFLQcRH;}`vuO6-AwO_{3O=%s*Qx7YQFvpLCsV=h*}l?tQb_^ySfx zofn*Ixo&yPvOoxrUu>&#zPDYfE+I9LhqgF;&1t;4i;A@J`e(qjS$aoMH|^iQ6{m`b zj6&Cgq}gA7=bQK9pA|yM_y%cj7-eN8Mt2f~mE3@H;QYq5%%^VT5%22q@igLIGa{qitga2-cs*1FD2xv_k9g^pS~zv~0lfM$liF8UmsgoCb>!EKhwW$7~(H zdE0-lzwpD&EyJBXcfoQfUz$yaey3lGKYcM?sXQY;Q;C|i;eq1RIr=r&CK>5Y>$8c< zBLec*0I!h(Ry7IO!FnR>83Dd^mxe{G1-&+qvUq>*-^QxXzP#_}X8SE9W7q!kQnJOj zUS(Y+75b+db*Pld;;r8kVG+DgCD}W6VUUI7-Kh{El-K8yZ5xj(3~JJ6S`iUO$Xi`S z0)Ik;Um%iz7^-c0kiZKFlPiW2yI1Sk=C6sUTs!Nh{!Ge+X*6$g6C~$+lNLnUB-Al* z-}`=X$hJY#_ZpxAK|@Bc6aN_6a}eqzqb7h;i=G%HL|uqn6k<>kF*h9SAwe)ixs6B^ zxFeQ<7)1w6-OLsD9I;>N$$B9T4`*j98eeI?EIYMS@zHl9T=jU*!~is_um5|#z~`Ai zbY&Ky{09zCgw}%7c%sAy@i~?nm}U@F)FdMD0>IjzhzrU8j4`MX6M^03-cH%J{?T;` z@Gk>~#ifF{O&IgB2)Dx^B`!9WYGG!yk-TQz8!3}^173dq)tl!^=W3T}+vl{%N(AKt zi5o~!D$>6Q(908N7GM0yw_Tfesf3KnMH@|HwiFE`F9fh}mm~fq;UNm+3-c-Tl@e&c zY3E$m`G!oaBgTqAK|#z6-^0bFXt@1&%;Y_Wbg#a=HsX&VqNFAfgaRo1dNTBN_u#|w zHXFD*ao_U~v$T*o3Nl z08jsCGrj>I;Rk)rQQwuRL29==&hX5THoyd1Xa7NO^=zpa!EJ_nEPB?^Fd_w+w z1FHjf4GV^VBarpLtR~f|vsF6G{wz@Dj*S~2S-;#bVaRrlAQOAl35rv&A9zkt*Z3~j zeStqG&p>)FF+&6zfO!;+IM8=n9Guvru2RV(M>-si5L77(i$C&Yw$1(%jX((K3zWjF zaY>W&6iZ7=3gPFQ+Y2EktE{Jc;gY{DM^EII|Kvtj!%MhAPbiTw)r-y1rGErWN?~K6 z7MS~+@Z>==hmVZ41w%Zn*_}F%FvLwLPNRVs!Sq~DMTHiB8k@ZGACVD-#qr?ib4F9S}*#xLl_qe&1XA-9nfOiSZH7t}Id~i@D?0bF35|aN}#JcRh2X zc@(auRoVR~#dZ0jx6u|+lL$d@LG}Tb>0ODZ-1A|A6 zJ{*eWn0q(yFf8mANDt7nix>p_pp4J3If_-fQI=NUmYB585EFF~7_>w%yCm0lw_K?@ zCsq}Q-L4a9i!{oMo;jZASb!t!6`vK0XP0^g4-b@O~Hv z+8J3RWjL7ZPTZeJTOo|gU*^=H#sQjY=k)VY!J=9HhyREGUGy6wm@)zxq&xOh)=Q?t z>M`GUTsw`k*XI^3w|AdJ{QOV>j12Er;J_#zzK*fIM1H}GnGYizf^_^CYaf2MlyEs4 zM5t{;9rgBBfbu(N$;wO6J;jiUn8}SW=hIHX zkJg5RTTJ%+hd{J6^kFrLbGIp_G}0`qFdKaXd4@bQk61ozUnH{R>t^$d0oh8@wcbO2 zD9XB)9*s?W5Sf-iRD*OaA@|v<5>BURm2dqELwU>2vva%ULyR0Fgaq5RZNurgk(GfB zT3!aT@1h+PeOpCeSLvw_BT?;XM4B=Dl!Oulj6QKDaS963!;wVg6Ea&HyD&OjYbQxs6!0)DSkH4r>)g2j4DBwoe4qTAIwLd1P45nq(GW-o)D!Dx zn=x2*+M2on;?jYi@ZrD=wfISI=FCME+J453BCA~~7}{z3NNGqG!cz!OvYf~Ffb~v3 z=76b_rIPcC2+|-DOYhLO8?=%eS{hr_Atdrca!k=k#CBFhlVQJx;&!&xVQ_eGCrLF@ zoQlWwc?kn|a9NjFXP#iWoQDrsHUaUKCd&0+@3pCn(p|GYCPX8%o!9FH z8`RjWC8^}jPb8}?J(?6H%4#2Ei?XOQYe?$>RR8}NPU}w zIRW#3S9x2~UKWa-HvH+J)hjpRy5M}-c$=)JRLAz})E&01o4b=Jzc!_0#sApS!`_6m z$XjqYSuj5-x2JzdfOl10HK7yw6S8*Td&zwc9xhoLw(#9tHZ$^LsJ1k4aZwXWxI-M4 zP;o&xmPsx*Ox_@HEhjc5U4wcrqrqe;4@Xag`(i>W@95W{(K1|+`bA&jW?NWTcvtis z$H_-n-$!K~2f{?HqQm^>*ZKqs1Q_}QTw@w_JDHoUMSx#!IZS9jKLupfu=yyuJAX>i zt-Sn0lzTaKLaItXZ#Btzky^~p+P=I#vSXtt$4W+sUE$DCAP&5ch@1?CPw0tv@s zt<5y&L?Srs?=Ma_SGInDAgi$PeRMlj1ih`5*aG7mAwGggYWTN|d4`n9iIY5C->48< z{Uuh`CR6Wlosz_6l~-4oVLP&%I*p7UR0+^TNqd@qc>9(KnkIamHTOH>eFPm;_GeCK z+`}Ng8*(um_fh8^vt63`pk86WuS(FJPi>9K)O_P9T1Pf9n@A}eVSmM>^m4iU;OZyq ziZES-$lWCYE|nAz7xX%+e^`nMbBa1b%~>qkt~Fu2(`T10+(Dvo35(j+;WmubPim}O z>~6I`A0j(f$wRLMtM8gwwuLc|ABbH*vX61BE#38fE#7XT@`)3p&NXfY;-3~{3B)n}q*9xZ>eV(J6 zj$Gd(!VCh3R?OldMfPvVMD|ZU_eKmrbTcKHb-Vi9m|t0G$z7OzIUqT@V(YN#iSpX7 zCvNU#_Prx2&&p%5>zj#OinZynRO_Y#hS!r)-dYW(8`PD)bxXCgZZy%!oz6@ZNU_du zJ}@$1c+%JCtM(P;qEga+Ut`7#-lAeBRxwxJdU8T>ZmB5pyM#HHn7y4GlVNpPm((sq z2XVLCi-eB$y4&7ca;`64>X0|8h^I|UXZ|$KHgkh%=FOXx6Tb{-zs$R?NM^Uwev;(= z6?p7-fB6O0+Y>Ri^IGjM%;MIrW*=JLNbl& zpQNcezCWC@RG2c|ZU2em1nt8>X72qA>mGX@3VU3+n_->9!Xb~Qw`Q<%Cx*Q&%xxVB zW67CwmpL6NUb{F4vtk`4{8kEH?s8)55*X5ozW%7-<;&0C4t!Rgd-(WRQcg~DWL1N6 z0Wk+y>rx~#2Og1^hHX=ll9Xkl)!-CrKgje~>os;c+qJbk+tpf=*$yn)CXojyJ9zB1G6IoQ{yjwr>ZJx<7hciZ}1J&eXD zI6RQ?>*WghBh>W=sYv3oQ*}%vW7B>$j|k!$loq3A9f^Zn4FZkRy~CIaM)KxhRJmi^ zXo>;o`hfb81Pz#qs~iRa>2!mfP-QUhbhri_D zZ@fpYYr~6V)6(xb6Qh|Hznx}?-+ko;Y97L0)mdMXIzA_fSkk+fli7NY+S}WgAB=pZ zpRI`)x9{Z-`G%EARrc7)wY0S#!uEej?IQ!LO|MthLmD5vGBxqa-GWi-HZl4v_aQ&)~kh-^W8%ymiI+*-GbG4qDmO%-eVtLm!rx z^PSPrd)GF%9Nqt{%%)Z{xHXPbb}mPHFu-^<)0(d5DOFP|>t`_|+G=@aqCzn9x$-wW ze*6#3;y>=VtN1-lt)Z^YRC#93T{pub#1P}_-OiTXEQ*P%eYrR3)vK>jQhQ-{G8QPV zMPt4ft7n_ z|HqrY%2IuQuW$R0m-M>#euVmmm4(J@B_7cXPy3#@W$;eIE3t5T*?ILuRmVOjZqe6l)bsB?MM+;&Od&?n)Pr?57P6?mDgXK%hW%zVuA@e>vj#k{;R=DWU;7)n z7PUa&Zxg9nHelOCC=PUV%A{TH(PmD{{w((?k`oG{(n(W$;IQ~e?MJAe{ylCbcH*sn zH%P4C7WC(>ckQ(F5`SUq|JLEnpq$6#15uBV`KFU=911hbx>kC_TCGo}jq3fTJK8z78a-UuZvbl2&|^@9|cde$nXy zT&l2>Ll|?AN@Ub$c^JWZrG{k*nV4?2UBXE2s0@+ZI;CVpcF*R($P8^A9b)%2n*GSq zJvq1euHt(j3t@{V@01GZ9>K!Gmiht%n;Km)UU~TZfje(FeSQ1O-m#jk_bQ&*^-=3Z7V%s~||MXIh*Hr6UvkF)DmaBN2 z-O2ChrT2scAO`X!QfezkXDWK^c$oq%5IKzKvqPELBRPX#M>dW->qEJO`>W~Uk^iJD z4No7Wnm7gQvh^Q42iV0f<1TL9vzwLH5>W1hYrbaO6~rQ(o?}-n7gUC-ObgOVBpHQS z@Jb`j7SihBFn2u7vFaxzuMY_|Cc1^bdy^&xa4Iu>U~+s~$96{U#hr_|psuj4K#Rf! zshG1=8h%p#^86rD5nf*jb+4qIp0qmA=5>gz9s($vkpe8umQ34B+dT#C>6gF1crs%l zzN3Ncv2f_(C)zo8az?K#GYnNvWju1=uGYMFao31H*^?YOA{#oHzFWLa1t)od+Pto( zX_~B~zAjf4r;_TkT4rwU#MMmHyZ;;_{mCh5nnJ8~QPSqNO6aq*MP!5Oz^Do5ezq$Xo!FJPK(&i+FTMp zSi@5NG{ij0MX~ehIhkldYrfmUBk^fzRd1JlSqy71=wS1@)taB;5X5wD;v{A|`8=^1 z%?Ve1u~1fc+16Gp9kE)6`QGCW-7Yo3#osR|n0bZyuHqKeJNbPB0}rZuwS-tir_CZidR#uF>Ru<>`ybbN18E->IFK4A!Gr zm)Wo^Z*6-eC0T@4oJSm9()p(GBaU1VHd}#h~gilu12oWQ=b*@N!JfJo+IXUULL}@(r08jJ* zH64rwIZ)7Uds$*^VJQdE`&)v`2!*D-ho>hQK~Vrv9)95WI8gA$OSw76F(sSu=cHhI z0v=n8e2UC&SJCBquuV-5iT9dOVO;jEc^(hbdcLRSUhE6%POSaXD3-lAJs9;W_s`=r zk#F`Y(@3x@$rB|Kya!*;hLo3|oOBazrH&+@T+Rnl#hWV7+CR8-UsWwy(C7Qo3}unN zeti0DluChGWcW^x@6q$32biU=x(H}aKljdNeb8v8w&8P6_UE^)*>?Lq6$@Nt^$v3j zWV{kv6_~`)KN1w2fG4a6O0^Isudkxk&8BK2kJ3Gct(vj_W-tC?DYy^th-dSF&aT+! z+_RW^E!4Ozl^r(slx%_XfU)+i6Dl{(2%j>Ay7f{;C0^*VTGi)^!O|~qsNn!}F|j%` zH8?n!n_A=5f69ohCdqMlt=mdpE1V#evL)>7?7u_h;}=dJ!Q?YbXzll&ek@e<;H;+R zo_(tf+0$MQnPE zBQyzOJnNOEWh`RNT?|4j`z{#{q$zMR7nOv){z6rgl1|=F5mLBfZl36&oe6(;=mhx= zmVle666DMow(U(bk$Y)m-d%c@Z!~NWNgTPuKeM#}bo~jD82S;5hvzbg2wfa+`_h?x z^1V!dFU_=PF6txw6os!|lmMH7z=L+ZYfWa4&VLYLeK<-qEYrB>EY zy;+GHv~7FDrgsL)^UsAHVmCuMFMYXYYR1`3EA-MW%rSKaOZQwm(lK)^;X&Sq@iVHbK`vJ`O2<=F z4~J!pwBSfmLste)sAq!4kIi!@&T*@!oPhti{4f2^&CBn)aQ|w`?aR z(|NH(ckzM$kJEMRIKG-m#J_WM@x;Nx3l`o%zwAuC&dJYfe_JC3a$R-14x1pTJ5krb z|2-1C*w9x`_KdU|(PJ$LXb_Gvr)#5OU0?mbY%%RPo4?E9hJ`hw9p zNJ0>f7nai6f>}OyPpD}~c}M>_)W0>kG^mYai-?0$l5Dfv-NUCpU%8I*0NDXfnnvO^ zeY;o2K_Yx_j_6JJSlG2&dXoNsU|8`wc^baxp47s`o)#pTSQyOSFekg3|glOiw zx@|_hw=;FGbGGo+WQKG2Q`^B>r9QydF`?#~(B=nG!o+PV!u?+*#_z~WKf*jav1yxu zO5C;5)kv#5J&`p7TSOUSCpbzKr#<-%8gZ6f z%W!6W$p2g2TG53A4z_QR&W5`G=A=LEl|R?%G)m?4{`?H9qjmR_XVmw%(NIB;U4aF0 zemNK4?pt1REf9P6sm4Bb45u%69;e&u54a(nf(^?}g|SSG9;GUxl!#&>4R>fiD(Rj` z<6co75QK^-wV`=WM5VIDQra52z2{$TqZw%xef|BR{R6P3r;4o!;?H*scW(ATTErYOR#32d!JdwLs*#WL0tEwPDuu=kwO}ajA_3z%T~x z_{9Gh@!1^H>z>+}D_<>k{7rUF>vLvLpWTY(O--#HtM!Es(N7F?8ZjMox8YTntHWIv(5)K;(*%Fz)Ve^@)Du{!^nf0up18Mt48 z(?L5O$*8GbFTUPgv-bj9n)!2Sjw2Vt!or?`VhXqa=9MORVh@}(5Q>mW0kkkNRuZVN z7*X(5Kgi*#FnMAO=2HVOYD$|=<`sP%z`6bsWsbi}X z&h7sl6irNCp5#qkM}xpXdwm8Sa20mmgHwN`+VE_DXhIH~f*BkyDngG&ne&CF7TIMtOHMG8H}C^%8x^jNXW4eS`^$`wS>VJTU+3i? zen!IrHBk_VQ&{-BI`j&<1g`p*y{q+qCttd>g_=8DoRB!@?pLdNkZ$M5STk%d$nBGS zF}wC*gELK(TYBMOqqw<%#=+H>dq!1lUcXh+zFBQ5earU5_zBaofs|ia`u%!7d+|Dd z-7woD#lM=1UEKO(IE5p7=>C>*%Uc>NbTV#)%)cHxq0i&&bPI5hkma}H$oQJI#;EGW+xUYY3iquhmkP;n*^b-B;d6&a{sW9|f;UP3#GBZDrL*vQuWx;AX`R!t6F)O=h1!Iq zE77H;5!5w2qj6-Dd`03J_MuCMBQJbgV(BcV@4?S08vSW<^X4Z~JYJye zM|}aW3>3HZlY8`}bqsP)vPJJct)ikL)0w|_{8pyjxDGbgJWIe=cv#8qdwFKAu4i~$ z-rDDOPDfvMc!IVCay!&<(YL;7Z^a*)tj0BJ9V?IdEr$c`-Kdi`>koB?ropIzeo%2W zc_2XoEpD&--I9Dn8Yka));{E|p7SCRsa^n(PJiXhv!@oLMe#kP<7COM)jPAGV2R^GoH zZjEvhBawY4d46H4nU2oC$hX4#Qn`DfLbyZ>{MKLZ3Es%$!r$(`&S2j-?zqkOzfb?<&#$3p*x0lBr+~7&jpxPE))`1yH&re zpfU$cTaM8O$&z&yN=8kHvp}G7H^arJRi0;2^kum z-+jYH?0jh!+qys=?IS^zC6z;WPS*WQ&LfHkl?;0F2fXuVmlvbV7utgY!U7Cx1qKrG zW;Ldk2akL{B>()<;jJlLzQ_a`6WC=yDfW%?AY(+O816Ew{__m~^bKRd0^RNw{`RnB zD{91l%ETE*qz-8im-Y6&c58DvNK_Sn{k0y&W{Y1?d0hfoZo$R|L>gD^K8_gfY>jrd$9_FF2xT^^o^Ll&e3~O0zWL_a=;$1 zw$kU4Q5I^9muBanMc`q{%2>Ic^CfTa>C>Zkw^v5&DJ(uLG~*XNlfK-~>uJqg0;@cP z#xxvm$ee8YvY);|C$~tKbLy#=Psmj{e?RH8eM7W%98+A=A=QGELmOEQstU1iW9ef#3Zy0k7=cnd4f+i9w13ri^Emaxo?Raq_!&YMZ5gynyGQQpWIDOAxPa0)`S+0%L+vxNqdb zf}*xN%oNgo{Xny9Uz9^4+JmZ1Oy2P}*9nA`l@l zGc&W$-Y;dWAjQkN^y87`FXd=i{#iO_xQ>$<+iZGZ2h!nh4tNbeY_xYKSvv0qU4E}1 z=_rDAr4|lg)XA_o|B~;LW7sCgX0Wr0G087 zx19iLVjgk{s^;biq@1BP^i_v``trrJwHd5BK(fFLIrqzZ-TkKA3+sPw^1P2Zre2Gg zi(yzM);Qa-P;U434Eok~#*a{ARvz$tsMglXzqRW}sYu!nE8V0+o8R3Mjl(hdHX&Q4 zQ16n{?DIU%^C^&X>iAZzPkZ_DW#Mk!tK$^`H5+(yUmz3X{B5mTsnPvYe;gAMYDpa? z&$MW>betaFo0=N=skvX>Pf9L+FVcWRImfcc#$9RfR|HLk1PTZ;UORwkwW&QfuV1eN z*33aAfv;h2%|h`ZsXwR-Gl_0D)e8`1I~@AMP^k)3YNKc(MjBE2*Pid}&$G zGOt!L(vuleuoyYO;uQ=q{WxA?wCn^`3d)k}K&fVLJZ3cv6*BRKn{-n{gMO{Rh^QnD zRV3CtPX6_WN`-$oOOeG=s8<*6atTW<)NtA{&xj)>FHbvJO%6tQlX_>_+AYd~IpP=6 zt(RF1k@|3IcQmk#OkN{68QDMc&YW|nvy<7$Td#Hp6l5gTt) z<2YCmr^Kvr=TY1nz&| zmSc9E>}8jnvq$7z#WGgfW6_dS7%uTG^6kLUiRngG-FnTlc5rATxByNk z%8!yMIrqdE5=zG~qS6{BpAfmp@3k^b@I;d)}Y;LSy22zEG?e9 ziBM=8N2Ug=y9c||2tW4CD)*DJ4&FQl2%{aVZTba)NU8`qy}gc6sm~N<56K1VDcDk2 zywtKqS-Zq|f{t>kF0*#Rrh3{$84^|yrbL>S6{&)<~X`FSF)|H&966~wG^nU}g0%h_G*9t>ebXCE(AuSM& zcCWP)BL_{R<-<(XEv#)8h6@;GR$=vuSJSjuy_a~gO#nRw8rHu`jn~Hb^eDs7YXzX# zxutnA>=ZOm-#cPZOlYB$^jB5SY%*$%@Xh{*07;OH#>B?TK=Dxz4)Q2M(Jj&E4Hm5f z4awMsR#_t{m0S)BPykluo4!9LENqHn(s80>$0#+zqdpsidE2w9>m47<*%nOlHxhHE z-hSjJ@wx?_lkY3amxP1oYHuB>g-7qF_I573JM9{Y#Ebhk+OYf&5E+VC11Q$#mQW|uafg}SnzACvBOb|;tKzC5>=mGID->9)0*>1 zBpI>D%KUm-dT(4s!-Yl^{<;rbS*Ed_VL_gVo#q#OP;c_)Ucc|24pvIb=t!{hGM^==aW%%^e z9FOqxX%Ahtzm~)5I)ZaiiFa3lbVpO=>C1Z!Z@Kb0|1LMZ|MRVk4W%5krDujNuDzpy zw8nCz8uympoi^-pRPSCNr+v}mp5%*5-+FC>YK9v`@+Ths{`;lHF}nivKE?YTtpXn{ z9IC#?ai|T3JU3gCPJ#@>F|fQ?yL_Xz!J@;)Kp=c_%`bPQBm+b=gi*9|9ClcoDC?cD zC*_Dd2b~z7DC)mYt1sc~u-w@jf<%#I_fC^{ViFPpS>i=YLz@P_^|U*U!w^~8;faNv zH_x$%ysnh`QGLYa!0u`KQlH-V-C(iU#QsLsam7oQ^kRfSMrrZ{$xhhkb}6`eo_amk zrnk$yH~Bc=QI`OJA(aSZdr*639NNqp@wPE4NXN9(uGGoQcjFa@k?iBrtoin}XLu(Q zG+up^Udo^h%Be<6traN`@QY5!Fq+ES(h)G)pvhi;Hnm3nyxooN2-A*PL8n01;gsR`;~V zfTB8W2aEyuguSJcgOi?khAK9Q2|YeO|J=GCqk3@0Ag`%_D<(LwT6&;Yc&Fgg$NaTU z68r_O$WD>PqTX@1h!X)*Hw@V>gU;MPz4ZH+6P~+Zu(*jc3Y@(}1P9260+4yfa_!ikB-l+=U#hqNTuc zZ-Dh4|7jkNYsllCm-EbPAQOy1l+|sn)XTN{z}iDg*zHlsrMs{k8e6F zBdy-)7l4#{MTtWCVDap7lJUjg9q3oW28W2!r5BH2w8Sp64rR^Q_+OfQ~Sh`RH$Jf%3rKg2^OhEaV zKM(b9p!Aihe5-6!3u?b7fVsmDwv4OtH9TY)H+%CBkmj2}c0UM4;g7 z6uGwh@tQEpxVS9c`IV*OyEB?3j%;1e=^LEi6dGJxkdTm|d-p!&(VpX<7dy_as_wlV zGVDFh>!jn}JRDHlFPNj%Dwfx^fVihtVVc{->%e^ZcI)aKi4Xuk{9TDpocDb2niII$ zno^SQ1*R0YFzEI;wEMEZ4fHs&iHnPqjJ-z1<{y!lUSL`IeBt*qmG@8kNjYU6)XqF* zoGpH3Idf{H{Pc%Tfv?5oMLPzRhaW7=>Bhg*Tvro=(3JQ6!v>_oGHng3n3z_d|B16* z`=}|d>lf6Xcu!#|i!#{6zA)D_pp|ng&U!F6!GG}d-IrW23R7-7P{J0H_fh3ov8%@eIncRsJI+1#CySzdH z4ZQr^jzdgL9+&Xjf8COov}Vi17+CI+-RvMeqkN-E*ylM;*dgk6Y_1P zPAkaIR_p$J1#q$V4slSQmCE5mrd#**e!+it4*Uvf8WYp*KZ41Bf3Ge456q2xDtd|! zZ@~2a_kZit$XEY+yp+ufq7a$`T!=@9Js*X1bsV4)Ds+U}ALY|Qzn5}o)yUgz<7?j@ zNK+~kS$->ZT}(fr;2+ZBh^$UdP4^#pQ!U(zo9A=zAci(ODa~5E!?*o+1s_#SsI6jm z#kO9aTqm0^S3xWITlk{RZJMN+M)_RXyL&Oute13O`$tDl0&RSr_*2iRe}Bl-Or?L~ zN!GjDF4@;r0%RB;G#o^VkADbUESFV%S03KsTktksUESe9AERuWTzbz^OCImQEA=b4 zdl$Io4`Cf*DDj^hi7$D3ea?5ua=xV?a>(U$-fF$+6UAM7HZ^wZk4pARP4O;Yc07cd zIsyI3EwgS=U~^BWkRHP$vm0}9I;Pgk~a4|5ED^kGzJ(M;w?ja=<~#QiiBNB(t^ z*~&QNMorn28yCFZtWaic-?3-5np}wHQjA5T0KZIHUh?HVp0+Z+DWwW&hvqbU-rGX2 zc9>d`W&Jvf@rsQWNC|sG=S}^_LoE|#_=%s&p-{KQ} zVe?(roNO8<))T*OiTLOl9pM`}BAbwOXycy)<8DW(Q11yfvn_8P|G{e&_Or8SYoFte7#0Km>^xeobn?^xU$wG<4oooe)ZPb$gOz+(p$

+$r&NA*TzdX9^ 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 NdRG2S!YRFb{|jKlX@CF# literal 0 HcmV?d00001 diff --git a/screenshots/conduit-menu.png b/screenshots/conduit-menu.png index f8435b60f2b198c9504a307063452944cb904862..48e27eef9a1041f25af047bcc5e70cff430fe7a1 100644 GIT binary patch literal 65875 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 z z~rSbmD}=uo4U-ZNh9eIs0!Mh+LVRYQ55Oc?yHAQTaFPD|L*SYcl%Ou@4)=| z<*@*IJ_OyOl4n1Df4Kz7cCy)K7(;pMwr$IB186y&m6bgM$cV)b=DZfC$*Xyeuf|;f z&7|!>s*-N~H#F7a_Wut}kqA-{S}F6NAL)P`&$HO8xwhu=S6A3A z!UD_Dbq*DpF&iCdCAD7K)9&~xFKSB6kyDJSAB4Mj{k<1D`m_|}pW2I+Ol5r)RapGq zDL*$+cjqy=aIbvHd3xmmmXKK{uji4z^f?`>UKXw4g%jVFpqeEGfeG9G;=4`7^GSw_c3vw!QM_(M2nXC z=379KLQOocVJ|*qXqXtnuE6X(6OGkfQR^A6h%@{AH>=`64!n<|fvE?3jD`L(ZCHK? zOpPKIkVVV->ssxcfZY^|2Iyp z=nHRd*jqMzQf@niuRYFEt9(_Y3cW z&`%z{oK@>L-B;D5|2zYV@16S=1<)$MzBDmDfN2LpycMU1?LR3Yz;szIsn zm&2S3X$khdo{DP(ILm4NmhY5f+dxy;X7;Yf@}}=O0`rA|{c_)qJsQ3b5+;~?i0Cg5 z1@0e@Dt1!mNSd893Jl?Y!OF%)*k0Z>USeczohlK8*b}ouRW;P$<8?#BeK3H?D=KOW zcb$0+$jP?|BP>*|UZt^h*zNV(T7>Yg0~CUrs}2;rlz!A5Z^X>8hf(^0_lHTk zi65%5%z8Z2CTXR5CGB|aADk1`+T>JE`tHyrJ{Vn_jRkr<0I*8B_C;F~j<8QA{(2W5vH1?OE|L#;*EL2(z zy#boFkWvCG(1S^B><4aR!n<@$mfH#<31uA`!-TGhuQ3IJP;j^MbWKdB-^0_@ z)qiw2g?ug)`CP27tGB>ZosQo@(YExE;u;kIMWz^G}6`G1u(Xx4<_`1UQfhsSKblfd(P$og_r9w z*fXtjU?qdz>9@@qGZ@H;PqwjfJ&0ndjgX;GiSqn6-6@EmYjAGH-P{o^x}unOus%3d zf00RHRfG6zY$v8C7|LTLIPy$C@;r}@8E4m(^?X0z&K=!m$(d#y!R$FbHd;I!62U9W zBi!XlJ&ol52lK~gKHfki zYHC+}Gjk|NpP;%0=$S`>ZTMkWn23I@Tt@|O=Dp!;mNLVtrCvqXTJ#=Vwrut@s zifF%r(bLg?-jDTAh3Qy_xGHc@c*M&Q@o=CpJGXABr#b>eb>W4Z)qt1TuDJ z7zIh6MVpsK2`4m3?{Ze%-W2jqM0|kA6d*OBxn%zq6;55q7Y!pcn+QcJ$>P@+`qwgq z<-gS(q^-kK!t@_~{d#3XL3Z}{nt1?3Br|~VhJ4EH@M>ahdiYXQQOch>_SW=h*9sEk z$2Vr0-}os@|Ec)Q-?xEyxV>hx!a9=6K>nShBIWHB&C0`abwYd&55KQ{)*1sUjBx#u zo+Km~$fwBRBPVSY6jW|yyefjSg|uyJBOL0;2f^o$W)kes?tsQ9O`=Xn^J3;>nU=9q zO}qX;w&|NQj!XbXa+F96n^Tcqu93kdh zba2Ke7(GFeAg`h#q%WpzW0R%Azuh3u0%<8r8&wqz_fzyB*cD!^as#;YmXq@?!C;*h zRiD0cC*St#>(9rZ9BF`c5;<} z)Fi7KJrn!tLouKdqd_%fWMmX_OfY+i+h`Q?$X!{UYeB~*J4s{bxNwb5?Dc54ZRiC; zkvr{5Xc=VeE~i`ri+%3gIcdAwLN+GdGuVR|HVu%}qDKJFLGrcW&h}LflQ1ntSl-@h( zzG@PGrP8^KM~sNjIO@;SoUfnw=tdFK*%f>ZiH|;~d3_BNM5qXKH^u3CPckLBsAt!G z5YdoPQX(HaZCrbfFzq-5aD7S_*E(_Hwz|6Z6-v$2;Xf_tZmZhflt)#`{Wr76^tzUe z^NZm`q>u^Wi%LwWU|lnRrLG9B%MQ!d!ClT^UV%)8C%aQ{^@NWGVuI{#hsjg zZ-|y>%yyEFKS+^iT%T`Mlt)aFM|_mCePzX;CiD1Bv`^09&eeAvJZMsxxdxI2@Ro3- z#;vlsrgC4e#A~ztW1hk!IbMv-p&CWGXkam-AiV?!Ei9(IkLr(P*f>lI)-;fNEFUi~ zyoUM{(wW{9@pvTgonrBLL3RBM!M+S+cVQpcR(1&6Fl0OK#0awAoJ7fRfxtK8^0@kO z?YAj<^q-eV=u`$inBvd;KFa>!+TQ~}O3tBMdFJu3i{n-4b>}Wtl(H;Ly!+Mv2gG{( zHxL{4FCdn4U?Mha2)7QCHAij99r)P`)4ZPB){K2k=y#3_UT_9M;(guG#&r&zy zo;bnbLEeW3-wbm*)<8l}a@tfFYrVd{{&9k-xCby%VCPo?iUZo2wEdo{nto{bLJ3J0 zQARdWJb5#p74^M;amnxUo5&@20ez#p0>t$R>jq{iOp0hP=QN{SA@+K552M`Lu;c>7 z0oAM}-TGp{H}%PBBY_uF91kvAxb9sDR58prf@SR_*0@dkRkrGSAN{XBuS*xmq5Wkj zMc!dCDpoXMS#V>K4cH7_1wu`Tg*OmB{&TgBhvMsIYBUkMf(?D zerUCO!>bGlciQ)a4G0QOvUscWY`?ud*T?WpD@flge{ausc}3MK{>_zG>+oK4N3vHs z+TTdGU3dEazcqo!%HcnH3iL;)RV_^T(f(vylHT7kqjF!Y`(dpPsn$_NE&=!-Dq42l z&eI-($AT{mtJ49Ly$@HeXb=;s zsheraA^JD_P4TyRBs|s31Gj3KZ+$mW|0~pE)I1|f?dnzIbMBfgFNQZ% zl&*MEI02>@XOgLSzf377SKgOT^g`K&m+P51^B2NFiIq5B|<` zC;GGp51#p_PmAGzzL88PWFly2xT1bWOX~CmMA6(qkstP%ND}B79ebOzhzPM??&duT zRj9fwu%<}8%y}}cA6lbm9V0G8y##8dSFb8fZwXwvT$w>&>oOkTSJX}9a1}HnKt>iU zgX4<;lrsHMp`k~g&%aN1c|sVWtl4{Q_I&FiwAZHueLxYB2-PTl8{7uuuY{Tbl$UL9 zLj3j{_gnR>BPHsRN8>sGWX9)S2hWTjDj72arA_eJgj;>u^2H0ZfkT!*?ko$&_5wOq z8~so4*MwU~PR_T-{tTY-%&|N;*_@Iip@SZe697}$nZ8P%sJTRCM7;1&{!ygL5R~L; zU0vNu3wc-7TBSrfQl1!;1~a)u$X00cS_Y0B9e?{-!}a?PTu%RZ@nFaVUEr`?e`|rp zm%3G>i&MP2WF!4zhy-v70v0OK!NA)?=~!-BAuaU9$M?*yvEiwX?`8Tz&F*ewCm~=< zVu}@uGF&jPI7LjeP;#kfyw6cs7uLO0Q&U4a2OSB7b3M7MB8ram?X6W}g7Th+Od|N6 z`OuFOq<7&*EsB2MIyP2`z7@oz1RL8!tnZ65Sn!~}ksLQJJHeD8GyeUrqg~8Z7P|P} zh?-y1M59?icxhwfzl}Wjw_NfZp7u)-}bn)4(d!7#|*9J7QTR7w*WgSUy|D(Mp0F@0d*_H@vWTGTlt zB+%UX>sW6$D2y8~huGx7l8Heu4`Z`F03QyqCjGeT^{e^!skxtGYsEF#eZLP!8=N^H z6fS5Q84^oXmk&SQ1F0E-bkdiz;icTpb-=63Tc&Lq9N!v#)j2$3#d)TL<1LW{ReILG zmS|DiPS&&gXqWmdbGD~Cfbut9nNMEJ!80nQSebIBFe7ql=Bu1!sHG0rG^d|<;s!d+ zVi&7g*LnVaWw0Cx7QB%--JrW!+Y;a=9k^~?wPJ3TR9 zA$x{ld_?tM;+`apKo8G+IL3CwXlV1@&17U(tgv-RF+LI&sji@~9POJIz4s?*s52?v zE-Vjq>}niNy3hWd7E7VZK96t%m=3ZFPm{iOR4?ZQw+TH_+skF}(##y=k0&2}%F~m- z*uwKSv7QqW-M#XbM&z5j;?`H+V^8=!KX-kuuw{MRaXv6u_nU_q3YpweGBYm?##U#Z zt`vjQhbYqjI-N`xi0*}w()h%f?J+Eibt_D;VP+WCFK@BC3Hj_FUz7Xjjl6q91EG3A zJ!zM(!gVmeALTRjd!~;iy9SSPFZIoNMMeJj*X6lwySfr!UuQbpZ!H2D)A+PAtlm*O z^fN9)ws;psNnY-vn~JH?1-w<69ExKOB;0OzxT#bu@!haT>1Cb`1Aqhm*8#>?CL3> z7=M<~afnrxj-A_qs=cpe-|=xj&lx?LF)Eq+^G`kn9=T$gKfMd-MtAop#$CgHaaLOT zE?5^rxNOw)rs|?K9ILj7I0MUiTUp(16_h_A0*0F|Dis3+zp@{{p(ywJ0Ry+$$WJNo zY1oCg9zDAG-?>$zhIA>O0@y(a9+w<1SBf74F4;*W7!Vqpy?d7vNrc)Ew#2m*|2tz!5zAUTkJ)Vu*d=r5k&Lu-5$bEnT>4qKL_HyPq(V6ReIFk;kSd^p z!AQe24Ic{;1K8W?GTYdyH8a+O-iieFtBni{_^va0@6pN0<(9_Uvjr0khH=M|oV@xs z>(53VwOEZt{2R(dBOxaME$1{l(Nnt@!rrz97n}J=ge)V;Av> z<8Zt}1WnCw%bsc7v2cH%4fU7Kb!PyvG3NJ|WS8o)aQs2xyH%)ZO}GBBiV^>_$lcw) z|F?yI|NoJC|4&Q*|Hgli?w>n*wwsy3K>y|lzhlbp%^yFJpS);(?&3t1xo|U4#cT1& zcE5ceS-5q--O%X6fcRx3u00&tzC6sH8wgxQe^r@ELCQv7r?&H2L7#rB zTKt%MFDI`!zEQX0@eWF5Im!!FdtXDtZSM)`-+K$@1ajFYH@xFCb+<|uA{5&Tjst}6QUqTn2INasy6ZZLD zgM7a#N=4t&9g!P(u{c4?!7gNWO{IQ)dT!jmX$>Z5AXVjr6a_W=vfK(o#PJdGLlw(! zi1r1`v}@OFAS4RA?wvxi%e*Nx)Lv~B#9(@AxZcog_o5y-#bwW>MSo{h*yG1;lvRR^ z19LUaQ|jLjYaIelaJMDWvpeUTdv}Pw^nLH*QwGbQmV}CEwJwlP%)QHQ2;6joAibDP zQ$?|UVt!31h@F-yTvkuzPH?I}tZpPY=LpOL8iGRz@*Jm=J#B_Y zMt2cJzGZ0jllo-K5B-(fzvKMhEex-c4s188xH_rz$u+8UhwAsC@T1;zrCX05gGDKS zs+b1?B0L7o>KG}a(^#yv3k-qATs!kpixUvzHl$my;AsO9%>>*2&naH&4*eNVJ{w}) zxQ`tI;Sbf(wdpd$n- z38py!$Zg=SqNcy-JtTw!=+OqWaZ|5ML=?yIn>R?M+Ba(LZ?OTsXMhHwqMMa6Q1j=NquX#rajeXSe11VL%Bs}^LtXr~8RdIh1 zewj|_1y(<}oU$TURCTngLNJisq2a}|$7N1VA-vl*eWovFWVzuy`ODNSVR9qsM{jLn z+%aRhqEteWg5Dmm0AM%~G8+?fYX53m*VupZC7fs*AU1+91;ZOW%IY;1-_lpf5CvMn zXg%&F;ra8*(TTxU9^KjNXjz~O1iUDeJIc6>$PJFWiO&_r7k%h}J(%`EnS}Tf_ky`j zp17Nj2_?|OFA$@rq-@Ez-?bukRUYsPx=i-=*49T5bt1jb(e3es7^$+=9Tz3MBP60* z@O0!htLGByB?rc)=`T@ANPSS@6M2bHQ$R9wzqoK2M_22cANt(4DLMDY1Ufw zEW#g7BYfmZu~YhVIGj=XMn*McVse+TnUdV>qW!+WWaq|vL)6TlYxB7i3$BG|X39vI zECva8s$IGi)I-Pe?7c}=-@Zr7kE8m=5-+0zSS}MKA?3hH6mx@x$ScEhLkp#rr*dQm zy~pA$Z-0&Qg(&}Kdg9TogB6gF7Q*C%Afa_x&DLyN_t)?R71`bC(AF~R{LJ*_e1z`< za|RhZ(vYApC24-JyIWr|(l$vR+80Q#cVG#A1rB8kRhZCJs)uuE4i|G|JoV?+(UH4rhf%{QCE+-=6p7OjKOEPs@ zkAemT#R}5c81+CbEmObKAN@-!^e>_ZDo1Xw(^)j`Rb7Kxw~g|29xEe}C?^5^3}j+N za=ep}>hmtmX~l^=(+;Zg+Ns+X0uu$Vnb!tTE%zK4ZJuhIT%b{mZ+aR`X@90svLp06 z;yjP-lD=O&HC#0{Y+*ROqU(m^XjFmNuf!nM+M1ecu;wo+hQjhMPEJfLZ=rA@#;KyC zR#`*fO8+m#|MK_!6KnS9QBR?=YxH>g5dnc{$Zk+cVl=vONkKp5-J+cXj=1eh*!ky+ zsm}LTuXixp?XR<$AX}Fm=WJj(*l^>SjdQPwbjXJFdo;IS%%Hl!;_for=F%Q7Znrip zGNn*?-hQ)e#4+#Z<{b}1_&1Zx7MwhX=c8ypSo})2{mutce6_J7ZFFgTT3U5iTZ%GG z%PP&~^!n5CRlhFG%RJDli)p)up9dcf zToV5DlP{$S*}uI8={Ewy_F!PhB*u&KP|vM}kwc{57PnDf+KGv7BN;#PwB$`f88US+{4Pn7#l zyDS_h7Z>?RHWdk_vJk^f+}R{4g#8eq3KB(Qy3g~Dex498f$IbZVmM}+1W|!w<2<$-?NsB zxtG|Sy}+m#K^OoVW)Fpouyzcl)a9co7h@I((af9X8k@wguX|ToWR?J+#5Y%7LxFf1Si58E&PBhE zAA}MI#|JD$ZZf=H(r+M$#PtV{P)y%>bkD(cf~b&mTEk7$Kvl>c(cFN#s90k*C|~|7 zo9R5QY3{U0D$8jWW7;qtlr*q$u-=SZJjtTU+v{&iN%yb+F{R|@#2+K!(;-bWmYCmO z*;8LFTzp;TXQ`!qqPFTTW@(}N5_-vh{BXR?2RBo352}ICg!l*{Cl0y!pH{h)mbHqi zM3Dtc^l3|&T<(ROb(Qgnx@G#S**7XheO=kur?_L|zjuD|2)!FVt59X1wj!d-L1y}t z-&QOktuu95=wQ=s5$0Nau__rKQTM{3ccO<=+Zuhfex*yrjYSTK<>sVp(UVQIZ%8`K zFf>cIaEEh2IUvD^2v&tE0%<#ozAiQr6gEU6AqntWURBjV*f*I6TNaveLS{dXpH-Gd zHvrHB+l8;_L`cY@HAe7g`BC-{Ukn0npe9X7> z8P#3fb=rRSboU1)(s26#ywbW$ELk3Lh(uuifUo(y#Hx7TEp9XBbQ5{g%(;29JH{+0 zmyvL_k8>Z4R0hu-iLi++pu5m9%R75yw5jOY7GX;?CkgX;-udvuXWlOse~XR3m8U+3 z7Xo^L)4w)9H~lc?c1spwx87Vye&rn6JXX~F#>Hei=}D)GxNJn|tq10*AuOD(4q}IC zvRZUGZm^1SylHaT9MG;kmM%pnYPgqSjd8gqls$i-6(P6$9qGjRX3e%9fX5n$%}fndmYxY zyGso_5V#)kL`(+&GS4I0XYO?Q35^|W>FB>j&dw$*-K??2fsW^+?n0FBTl}EhygHmSM zLSrd&LRLB3Cg!xZx+rmKPNUf;;ZxK~w+k2Ey%|>CDpeJ-fz9~M@>dgG?|GzOTlOe` zHq@?9z6uQ{LA^mvcMpaU92o5~??@c!V461`bab{MA`{k~_;@OO z^UcEiEY%~L7*TZh!0bs%QX$?JOETC3!U}|Yrfg{Be+U84z4gq!owKvE^qidH-4RtQ z6Az-HlIn8(A?M7IU3@=@PxmF@T~w^fM1eak&v8Ra%a_gY$V5?I{|c4 z)h-_Nb%(hwk_gr#LXt_hkW~_5&kCu~ex-E7c#|d^1$YX|@2c4NWc^0R) z@44HuPdhS5EL`b;``i4wvRVl5U;#c8#cgoKxc1v&-KA_U)PfKYTy`1wM^E*Eux>Oo zyoh4Bf4o&NNo*)HI|%GN^1+)<^fMSautvR3i7bnzuAP617u?nwdc2SG_h|L#f z_f=q8FBu(~XCW71JLmN0kd}iigQ;**{%dA4Q}=9KZ9KG6f%$(AQh5klZ@l4|>d4!y zFDR}8O*6h@c3Z?8Rm9#C*1HsybMSwQVbRX%;8vbp&H zj?I3a(u$szt-}P7mPAx4OmaB}ci&Q02yCiA{vI`k76R( zkyi^PE2n6^TGBtQY@CnY*xMCruvl}%w!D76>K7$cID-$S!VIF~v6 zaj+Qh9x$uK5$2wbmVH_qleuV(&WN*fM$D;5voe&l*<vB>R$b1qrU|+Xd2t>W z*loCX5!-6j?lpZkVu#A3_aZHidN$KwuHTia@U!Povhz_^jq1|@?N2Yvb?;|%9tenh zHsEmSskkt0wV(0B5+^SMgQ!Ch&!#Ck+(ShT^^%NRX)`=xQyy_=j9eBu=f4v6r{J>K ztVg9C?}4CUQGTAXy2r5K&FVo9|B?y1v6+%uu?!37oZz;N8?5CP({LGd-Q@LPoI0?e zudrfP_lm001x89_n|3kzc%!2Bm1eR^JXX+LM03o%rc0;vThA`EwopnXm0Ii;Tt?Ys zAMT#0xwGW}eYnhl5~e`uj16^^x}r;yrCUxWg?-e`VSA8Wf3+!(VZZgLO4Fh2tjaV& z@37{^m;M>6K1{ZxRDX@htJjIKV%YHVgn{)>_eP(c4T{HW*q5)Fp7%Ri8X6$=k$Rf% zW8buGI90jT)vhlB^+(C&-1R&}H{2;I^swG%ei_xESoo^Wr@pKCUcehMLst{oGRw4P zWjd^_d+N$PzBZ;Ci$v27htCLgGUk}fIeVb*7m3_k(!*rF{-c30aOkXZJ&_gsX>c+} zlAm>p*_w7pD4IB*m7j}*pF7gxg~PlICCjwnMKImu_$BFMb}C)*8i|S)GnewmW{MjJ zd*)LHD@A>c3ZB2?-C|hx5~|qNd=KXW4aIm_nKc|tjT$^6Ii?Oi7h~-ynVCoMVuH^{ zW+}qXb8k={wFgbIcH0e2JDSin7PEBEtPnLVj~lAeuSt^R+IWGN<#$%Q!CN%$GLQ`H zYz2H#ja{$lW$il_G`Gl+7 z;zAK-92*}620l+qQuH_uZ_O>n1xa4Z>}koC zjWpk9$~p!6vZFZ2ucM>vUegQe?GM%Ghb8~gc%#||{NTH9TZM}553hDFKe;<4Z{jgj zW#`}zAd#+bxFbPa>D{-KOY4Y#usDpd)Bf<-r~CX@m1%eKPK_EST`STSYD=sehwpOig(wjC*Ga8$|>wQ@k7VswhOVpGh1z$Mc0v0%|z>tKY5?-M?2wrX4yN0*mXxI zeaYh~j+VJrC2HG6p|Q1G0hjS!(<28pZy!I7G`B-CE#XJ%&bD^s>x@hgK)Ayf8m z?i4~l@;&o_)MNDg1=)gMK?nI937&xGL%KAce)(ef1u>2_v;n+c`>kwTo|HO7lE?M( z+c9}DZe5IhRE%ufFp2rhTCdhg}osZd*qtB?+^ zd#|}s^-Pdh_xy3Ha+{qo3td9zMdM|ATnFgHj-7o4V^wXlxJI}t;p|#3pp-p6MPXZ{cAcMzyckh-*I4abxc%VvZYJCS@ z9N+pR#j$grNtm^zWj79Rl1F|RR|35F{?{MJg=NAQYGrL*a`iNNJqj=>Zuh$n0NgZo zaX=Z$c8C@k*WJ6W8iWQAe%z?B4h}E>I*rs(e1RWUpUrODip3;%Gb+G5lJy2!+6-XU zX-6?B1%B3Atl0r|2G9Eg4wCtmaK;4a$7#y^-Q1~6%Z6VkbH_K|n2mR!MAvcRL2!y| zw^-Psx<9?09)BQ|FB_c1ZYT|C+VV6w7Q1z5T*6td?NT_KE1s(-F3e;k@b`L04wpG| z8)q%9jaBGJXMk`wy?`YR;mT6g0Lz_U>kt#bC57lI*|Tz8&YeGh!V@kH4&CF__CwSX zkPAt<7Ghk1N<@yXTyt|XzLB>7JObxlBqUtGUni%p@nRMq!kfxc7mJbuT}VleIyW0* z2&ow!m4EA?GC!+TALD~lHMQdxh7Ff)9k_y&)T zeg68jR@+x}S5!qj)IUfo|EhNV;`MVC(PUTVb@vc(!!30~U;kn2;9z}6*Vx{pd742w zQmLf9;svH6-cym=9>QUoG+?itpqhk>pdRanjYCy2Wc@*VAD+bCNB# zK`g;z;R^GOEZcGl^=elshci@%Rc1xp>?xK@Z^WH=BfY*V0(S0lPQY$0eI>yciI6gx#${cjd*Cyb zu}RKxS(snHdW}T3MwLGQHhuHujCvoRcjV6w1aKkUV3KWDwgGup63A>C(oO?d4gF&v zdb&G?W99Nd2KmQ8XP?uPkXccTK#88`MqBs-C*(@?Yl(pss{O^a5Z(gB2)%Kbx>u-) z6Eup{_CJ$uHb1L8KTOx$;Zb1!N$vVKA&IRWu2HB*_IwK3B>Rd<<5DU~Ybz2U{J0Ki z1y?B7Vpte+O-hkRs7U=SZhslbN_+I z7k064iI^!)IonWK`Gcci(xHI6czLPkcp>M!yhm6e+_3wiD!9wiW@s*aNuRAHlXn!` zvr0tES9eTzMNLK?d5XE44uQwLliN;fjdG5Tjw<1_(QCZj2O|Be^cVbIisRuNY7D`i zFqe$VFcAO`OvVeeZ{XR=SK^3iKy8~mFi@l!qgN4GB~oCo zrdK}JIy^u1pyP9-U%w2;M!ogx3weJ|&N9$SrX4uY?tXul!e{zq zjjdeW@Q%!fAn+SX6uH^5BJtHj0CJ*x%`HK0nSz> zzpC)=&CC%HHGI3vE9&7xG0hJvWg?Eq1aQm9N^^=wr_2=eG_PrD@wvHIu%Ib4>6uMY=C=h4QcGkSbLX1A?LU06yvzH{ zvw>shY+p7d8`@Ml$_pr%XlTg^MXsCKN!Mp<&)QQFnkh^T~$MS;}K! zs~aDJXgpRO{QjNdu0t#Yl;|9o*-R&PR%~vun;OzI4Ps=Q(NhhQCR@6nM)b}e7V5nl z8_!n`PWDX=cQmBwoIm-nQ%5xjXF@ftQVY*x%scqYnMMgm8e#r4mNAP59%1#KU|TLM zZx>ZjZ>o`R*{Js%2R|JsOZz!Gy|I`6!6|H9={Ox|aF2q~iEv2BCT6K&Cwa`L?WT6H zd4jWdoV+-M#5hXQyLbb7;DQ3faC z-Aodsua;|2uZc-avrOx9>Ioj~=~WD{Qk<;)JRqD%x6oHFyxB?8Pf>C_agV6|BsrjF zI>97D)Z)y-aAeJB9h?97dYu9`r7p5dlE$eC2Oew;kaOSDj3xdixjkA={I!ObctsNR zKAGmO0q5g_Ez>$Op^-^_CewFX9J-k8v--L`tmjV6N-VsbY?;0{$w>V4N86R|5|(Pi zg>O6F*FHWZsunLUl(2`)FzIhmO*{XSY9>pjcI5-&ClBtS-nZorPwiZub6?vN=iy%8 zaTksP4gaz7=zONL5iXNi^RMRxrXD8ebgtjK(7F(9_^Tz{%v+j~)_r!%4je*#3cK>& zJ$r_Aw-tJqjJ7GMs600ldWqZ}(@P4N274YA1bUsGT|v54M)$sLm1DxML4iRZo<0p% zx*m-_j_NIR$#prV3s+hfMjg1M+|_54DYG_)#H|ZAJ1NMuxCFE~&33(AXgt8YWh=6l z--xg4Sn&dDR~!WU+~ENpXSv!r64tC-jv6q~;Bm{#6G@1Z#S}!5IiyQGIu`Af?yhev zinV8&n(4YNC#AmfIKHEqio0qa>+I4$xl?L%J!fT;NIsX;jKX+pPLE=oUf*QYlygB_ ze9v3({ml#cZEkEEN2;MnZR1E#N!7YXtf%N;n$|seTBZM?fOw9FsNT1cbgx)MY?{wH zmuI10(9%DX9VcB;CtzV}&HQ9|rZ`c&F0kkO+naUc!j$))^6OQPsJZ{IW1HSR!uIAN?q(MOckI`=|ib3$;?WcmfZNgtk`ALqp@d+21(`6n-Y z<>`))n5DXUZ>&q4lA0Xq@S1qTTs`mT3c5_}%=rino|He_4NpKb?qT)rtw~U9(HgkJ z-ePw@;oxsSFAHxoq5TD|JW>Eu=H%6vd3QLs{51O#Fm^~r5o1NFRqsiK8g2>3*{mzr zAORxtiZ>>Iuc_gZdXbc*1kZffrZp>LR7AtmK1F`V(z>jVf8)56^4ug3JFOw^-?jXJ zH%}vUnQm@wF;+G)76puk&p?k&I)SLjJH1h8A*?-+Znf(QXCGw8PBzGjuD;B_=TSvi zIptgiv3|Lcu?_m5Zs`C1TGCBZAJv|)dHda`RnMi#1lQknKx{AZ&Yi8g1t!P643h(_ zrk>S*5}H;nf2;1H_GwJZwQ#bng(+<<9x5R^?os@JvT}DTMxEGJQPzHmy*P8*x@Ul zyjTk*o#lE8uwsb7zm})T4BWDB#s>xlf&g4qRlnc5t^Q)N4A#<@k&zrg-kaT`@7%fL z+~2`VErG2;*!p)!qdK;jn(HfNikFU)0mn`(P)Vhn*-Lx(b*@KJm*4 z2nwF}caZ&4YI&bgx_r4eG74rkc&*bkL?z#fB{U!g4_b^G93W1Fg(d0nvRrg_&gZ|| zwF5>@q66h976m9yxH1HJurCJ&$AC#i^e^AG=1k*e3%S-IlVVW~|BWq;{4%xm^=14r z#sDSg0QF5u7t%L%F_sHrFS*C8bRtu;P}dAHAr%YpAf*3&EbWbnLr( z>Lfbn?o-}87(C6|&GOvF0Jb8E{k>c~y8TkXN>ciT{|=?qA&<1Ic)h=@pXu%VOnziL z$`n)z(~kLfqhn>|+7YF|u>7fCvfK-TN0eIJuSKKmeuchKaP9m3+tMMk>q}_IS8JM1 z=cAZKY%F_CT3%?fn8%83d~j;x9saVkrU^^2XYCCI&z|jwrU)80a5ZM?u($ykH;-L+ zo3RtPJ1fB6kG;{1?~s@f`*|woDN!5qP#fC*dLDI3>a6hhJNygt&H3s+E(<2!VMng0 zsUmNKC~KkK9@TX+Dl$#ttE3kXeDxn8__b=zafEX!7~Ow*IKJ#?I7j?@=O3KHmb=@m zaIOw0)s6OYlfS?3kh+}jm>u?udXH1*BjqN3Zv`iXwv}ov;$qZw>s8g&TTJJFARRil zIEH^9xNvicBVTx?$AWeMc^-O2D>8ez^*(4QPf+hv43}fT3xVZv9|Dwlp%NVK(1y>vW$Y!x9Ezl03B6|8@taLr!xvTX$7>`%va9e0|OJA ztYU8#xREh^V&5E*lN63(CXs$9oHP@lb;j!kEkp!3LzuWx<{Pg)%U@aVid z?Y7=?-*}5i0n6x*%Eno~kZ9U*#U{Fe)H?8>NJPrwE?IjBnm&e0u3m#gV&!@JD@Hsr z@P*`rC~Vze<{r4K(f&GrZvgG!jl`CETD|#3=*@^JGchpGoKvsH|6YEu-t4AZ7buE1 z24LF#R!=!kIf{L<@U5ogCX8feO$vabI-7mnwGea$_AWe&SjI~9MCx4Xuut{g_TJXK z(7(y1;AGc0rPaibi`ed+L%n~-=>J$Os=p`8dt4&BpG@5ifrmNQ_O(1)1QPa z!rR>?Xp2H8v-GQ;(i_ZrT8&)SFdOI``+%||@x_bJVWLLiOj0;+)Wqg&4>Vt*v1d}m zBsy2h;y5GulQXbzh72|AbAEIEZ~4J<{RxJyH2ESgOJM6@u#Rd20v^J$a16qp%*!_& zO%SgHSm*k0P`HxOP?NM152kWmT{uW+nq}Sl=+U#R08K1P;exO5nxpz_KC$nCL zf|D;4=5qZN@--4NQ3}2@%en4AYt!G*Ie+Wsr4e=$9@B+n^@XT4>rmTyZLiF25E$4lnV@aemw^AaWrfPbF_yH48 z1sQQy5TA@9>Kf)x35kh{sG_#4Uq^8+Kvy!ZhaB(V`Qr6!MVtn1u_gl(MnmD%xV(iBU+5C{JaVmw5}OdCoa621|bc1d%cGZhRgyBCtEZj(ujM>y%4f z)8IjAg5f2F`us4vPZSU{3SV2fSKj@Un@h>D?+LXUc#5-Au(0phDkNQHmF0NCVsOeo zN9LYZ)&^#C+kn$>qWH&5{1Z?U@;{2s+J- zshe(JZ9S2-a5nyYe)OJ&vFG;UZRBjWQ30JsjlLQUqpBihml)#fDDjwax`;ehzLx8N zX^3gH4dC+v-6SaGe^FlkhYa2>=Zeit?2qFT;BL7n*ktA^O%CJ&8w%>p4t(;cvdiTz zr>I)uk}U>@Eqi$~yK@J3dHZra^fDS}J;nFIHWIIfQ%Lo0+^MsBp9B!_x zd^prFIC;KsE)QIJ=nm~W5@h}ioY@Eb`aLsApMS5;N4j^1C+D-v=dH8TI6`@()-HRh zb>ayF%Q=6Ft!D}6Y;0WJg82ulYR$)S1hZ_`c2e+($C+pLl=1r7Z{K#8rRBz7kBM$- zo#K4DV|WKY`Hn=qn0jzKWs8)o8Kx7c)UL1AGBai7tP7#$E!W5M_eHd}qC`(p7XJ11 z>lMW#Ucqr^g%3oiTeXCV?g|(GLEQy0H0ipJSE$7lgc1ZliGl{i&qbgDaJ?n`yubVS ze)nzr9dV?PW_4+Vy&O4zoC!~`a!T8D=Snx(?6s!plM$R@Q6b4deJ7#cMwNrI01OzG z5d1H4|CNbCE6|HSaJDZ-=j4wgkN1};aBakyXM#rGe$1aBNz~8!Sk4#NH)}UNs=iy? z!9U&RH64|+?PzQ5q>V_I1_r)g5MM!%$=d{;A?z-aC1XL3Q`0(WoTgRTt+_da;|DY> zM@w*X3>uUI*2%uCrg!rG<;Y_C%_MOT^YxYy@iT%w_}bdBU?<=A{8$vE=GEhB0ex zCI?l&T-000ROU1pn5D)Df3^)DdA$2|SjSsl@*TD-%_0VM&WSentU2)kkC-ke!Ja1X z>0U}veDf{&)LROvTg^v&2CvjCCypFcFbdIh-0%&;P)QCuuAc2%LiaKZn#K{FGnQH| zsi@heuH5futETH?Em9^{sdOZd{nE{}$XQFhjP$PiQ^*fqa(KZES(xJ9XEl*La`)Cy zjo?Y)t0OeueY3jftfC%qMc7*=+V5SsfCtiaJk6$oI)c)FlbEFgW;K>yVbVQYh&;yi zL?Z=fj}Q#9px{1s+QiscoyxXs)EXw=mpBi!`M3hjll#A{AIraFB&LvdTIWnP(bAbT z1`Ua$Mla_XgD*jqEmd)VhX*Io2Fw!21xl6C#Mi4k$oPY?YT}Rgk=??T0B0l)nlZTy z*idlhV3IoEk$cRXR5g=IwNDmS3fjk5Sf-365svoHvCwnu0Zlo?TE+Mu<(&)mF#bA zNl`l@`g|9{`FrHV?R}+OjwbUQn8?QxJW`T!ds+CT)1@wxFZFi?8w5I|IF#ykjOx71 zm*{Y&1eMQEa2hByS_>L~78h+`W^CXVFs9s;SqSJ8$e8yP7>?DAD44k%F>7f*N_b_! z=m8lyIZ+<2@CRp(T__KU=Io?)N-Cv+B#EL-p|Xo*PD(PR zNh(7jnHxmANg0w@qzuVaDTGBORAR|It`(JK2pN}YE$4I7e)fLO`#e|nvwXEOz4fp;1ex~o^2M<=-ToB@$Ia+Lk%?lHtbY0n z3{HL220dt(2d%5i4jUhV%;z|4d}qQ_sH`K8?iBA+jih^uplim~8{MgBmYn@O<$6(? zt$b2KLXoYd^?MuO%IHcq6a~;(g;R zS$L1JqAB0MZefh?sXb$StNa~PB+_XWc25kR>i2(xIWCK;<|TAG~Ap= z>_DvSn98<5x(bD&$#!vOJ$Yr!w)$uz9kk?-~_yeSEtB-xW< z4x}`pq!Xi{`3o-i$vt=OT;{+8H^$0 zCAOmiyXh=Gw|v|A(xi~o=6F$aZ_a?>Qnv9kRx$4ij87zh2bjKMdoS6ja8cXF%zbIL zlG4)Bt2A?fJ;l_F-pX%Q7wB3MNAVv1ylGf^B+W-*+>(~J*)N4nedjr=@l=7EIL%Nh z@=25hvu*h{cK4sAZXQFAKGm#6!FGeTX%0W0P>>&AR@@qT0oX+T=@MHJM(-|XdkfD71alImy zw4NkBF0(>{BIAqmSZ!pWodMl=V_xyD+2tEJ?5h@#~>`@_KD27lG+%qV# ziNv+@>F~?5a`Ao}HT}Wj=cpRe#a|+9wWBI2&`JpOE~kBAH$uaCQzS99xlXQfv;%G* zBMl8d<)cGwagkl}4f~(D)1aoBq>y8oNMU%T%LhW`&H&SI=H*9xo|C|&M{XseBQR>CRy1*XMWDG%>BMmr#yXru{BvQT^_eN5cd&Tmn^o~)9ISmL^ikg4fiwLyGhZ- zJH_z%_M_35u!W`W)AB(fHMWBc$fIsH03!L@UPzJ1&TpXC!;E0CE~x)JcbG+si}@s{ zn=W2iJLfEdNRDJOzan@SgMn3$HW3gs|2EU3ub6y8j)P;0o|=b6oQP_QW7gq|tfq}`}=!OEo8u5Ie+NB)0ol4UYw zd@#uUCW@g`*wRmU^lxtnmX0`P!b>~frUXh@ZhQBg@>2^%ekhK2@~uMDS|$3xEfAxo zhnz%qv)yo$OwIZvJ^ycHr5X+fYFL-$l9GPn5`h0fGo?KB>({T3(u~KfQwZ81+ObD_ z-@1ibt-9DdDp`R&jO5m-Snm5BjiK79wGN>5yTvu`Hp<@4RZ4w zvZs}`qmY#7BO_jaU4oZM9#z#~wU7tt~N6AOvfBxc=hy z*VICS3fm9f2HdE9P3rUlHScHG&v6OUI-~Pcb<3T+hfMFr;0k5B<}I49P;CMXNVDsoEr3J*{j?V4~_b?eU_Ff2J1xg zWco24RV?UwI#MDf1QVH%DU&PR$*R$C{JFM)x=rB*ld;p7ozy>k#!0oTnqQz>cg#Z| z_xuMg6IWj7c*u{GOZnFq7s>FUaF;sp^mUlZhP9mfy_@$ln`U|lSazDm8$Fw0qniDF z{PS>!YS>f%C|Mt;h7@MN9!I~}ZB!wL=;kU@dlJT$4CTp%qM@B~-mC3YYe z#I<(~Q1cDKuTX?b=5g_Wx8gQ8Ok{mn!mk)!e?WoeUDB+KJ(2*Gv+q*b?k%C#3+f6K z(*Z=oYddXY!&juxGrFk&JqEp=gnU#kDZK8v1&r?*}VRa!2`@PP~P5RN3R zZr2>(qDw-|#}ePBjc@m&Pq1TdDjkK=`(v6dfS(TEWp=l1>yK=WmRl0Xc4*l0=alAG zDk1~x^|)ayM;a+-^f7D>NU#e%mD^u5VeEG5!b;`EBdYpVg zD!Vc0C$mHm8@-atksNogObgfVi(Jk}&{^8E-(vMl#2lk;35f*gQ`Rj!o9^w9EW$T) zmKk5Z3?F!NN<^>$RnaXExd?iw5z}n5B00#dyszq+X?h$CfZflp?9naA=9>h}Umepa z&;D`^0@ftE2g8UE7X1eK(Rv}i%!_Bn8n(yH-K{>>p28nzj`s!|Y_(X=W`EWYaqj!- z_cGZeb@#c`9k-6E)CRnOYfhqyG0N^1Nn7#F>UXAl#?YfLPuRL`c}cW(PmQH6F>+p2 z3RL%(#w?4G69Xk@jJ3W#FPrz?a8uXEcUPPW@_o|_;{3A;+^b5d-ZXpF*wn?%L-ZSa zyR&F^r9c5>>=6DiwmIVhI@gL(-bj=~8E+1Ci+kLkZ-f0OrBkwxH!{|4LH3;^vi^GET!Qe8B!0@?+XxR~;U z1?ew;4&GAs4!>%7Q3w>hhuL!#zef@|)j#u;@8-|A>la(#PYtz4#Fv|jzy^F%ax7K&<=ZtfeYtN<2cLXee9*^?F1&7Pyp)+52 zZO_g7;xC@}uChN{=hb7mhtm`p)NVaKoGE{*Mj=6ie^=%d^D*C=)4rZPc*GjcC8ngf z7>`0a^pQ>v5uLo#Vw}A(Isv%Fx8nT}he0`%Tu@N3srKAzl%>kbrr4R51+ra^o*c!8 z-dN-teCv{I9NjI@w-JgeFh~pdDbH<{ZQPWIK5bfF2No6Q@liafn(xbZF)TqTWCK({ z*$*;^B+$m%xLx&iO`3CuweAB0H)=jnaugq^?l3v&qBG`kk&c-a84(!tXy5+eO z_x0d$%Tn(Z3XerNrw#;)>+K&5md&oc(19pyzyjC{ zI(3yDzFbJJdD`~xeQk(J-7HkB$pvx>8#Zh(QV`ychzMw;D=>-=MGz418JFK|T3)sV zik9M>b9a+7+t+i3nDqm732J?Uly+*m6sOhF<)a(xUdu46{hDO*Pr(lg5SC*bGsJJh zA0m$#ycd0z14JDO`kBWdg)KX?6-~ZaF<{BZ0l)ea>Hdcub*W?LV{J0Ko5EQy ztkKo%G||AY0ia!5?HXE(aZ?MG63Q0EBl?RcfAx^-K$DQLBf;g)$Z*(S(m-zwYLsm? z*lRtzEn(Cmq&ri;>`xn#t1qhyiU)BA_M`lGg{ zQ?=zCTXgUdnNxOUL#5<$iz++)DOe`pId_lY-9#A7%L-RG^EOEXsikPV2-(6}=^qjj z5(l~Hdl^1L)*?~IKyGQU&HYR;3EBC32T{yPEco*T{8m7=$~#j08{Y1^g}ijbYsDr` z(d7|u4jD{fN9EL17JGCbVxQ+b71BeU7_v)mX4;fAZK>#(m;TvKghHk}gjw#}_dQk( z;ZUF~n;dG)Upxluh2xVej=tD}YavQO7!G3t?$Ig7{%~kzkCI78$hdp*uhwnJ78dKH zWQwrEW1F%0Wr~i;)jqre3rdQOP;!9$1xN%k>Kw~lvD4DPz+sQdk$8)7Nz37De0c^a zoL6}K+<^!C1dO^P-=zcTwTaMh-8+JFz{-JOGG<|i^Pk@HSi-EjlCjOX%*cL?w8N6V zN*8}%`~gv^&U64xHW;KwKb1mjnfaQeNgSW29H)yWJ?!pDcO|xQfN3)HY3R;EL>Dby zoK<}-QnoFdl}cCbh*i|cHcD1&*q!CMFwFg+rKL2AAF$cDtg zQKj{s_4E4KFkb22eXc07BUjY-c7bX3`Ddc>cpxy7(#{RN+-RO7E~cH^6GK`~c|E3P z-1V7ZLM+?t+*yu@ePeruFIp$oHqw#84jR)W&0lMAsBB@F=ML!H2iC?ML)mMX$mp@% zvH*L*vU@)mwED2lOapxRbi$FA5Z>3e9v2weXM7BV&(oF^4ceSK<#@Rel?=`bAP&#I zFs9Braf)fWU9fFEzNPliwD<6TO6D`Fv!4EruX||oYK3jk&dXCUf;Panr;zP%PtGPF zIrD66a?Z%f#>_AB1EC%ErL1XFimCF(#^$cUd~1r_wRRVM_;Ba2iV)+KWeL~5ZMx1a zqZE4~--V+Wg;P>fWt#@Jhg%oy0m+ZX5owQ^Hdt(U9SiZqVs=@81LFX)0`>xT!L**1 z;>;5$V~y0+FJrTSr!Jc4P-Xabt-j-<_VK*=V-@PCdw=U^pR?CG&Sc$-sJxStv!=W* z4)dIG8+UmW!a=3f=JNXa1`_2L;8bny@~TaqasJV}+lKHZ_}-Y!FWZ>W^K}d7+LDhY zIa&g1_4ErQqNae_bw|B|J~;1=4ES4{C8!) z*&n3K9$~oNVpO*QP`Q1$FE@NR>8}o`wNML;FwUbpvL#QVqh=hIAR1dVR3YUZ!HLzM znmh_;oqbj<@02oy9|Qq5aJDVo8p7NkhV$G#3ZA`sQv^1mC~C78!3r!r%;l6u#J- zhFuP)TYFtxjsFSO!CSLdoZpVkkh9;}Nnwufw!TlYynRLCbVDPf=$4iiACcaW>rQp4 zSO&q=2ap^5m2LZmmgWtK&EGdfH{*!hn;JTXW*jV|aW#c*4uVs}cC?u<&-@+KuzGiD z2BoLb^dWaVUB4fy5xb10nYC%f6ZiLB+~12#ova|VnuPE134j8G9Zpohc>}l|t7cZ& zSBGb|rYt(OZ*81yqF(`jES{b>he|tbu130l@Bb-^rYFup;Rp9U8(tb{d}8$@0T2dv zr2nPG>?oVmV%n7oNh>SY)9&WQ7h-ngf{#jwnfuB;fcHV?`DAC*ZTRFHHbW7ltgPIX zSfsAh8DF!T(728K?-tk7Hw*FcXWY}qidU6vUf&)1e$s=p;A5;K=Z?(M&c4=1{+Yu) zc?YW#P1Y!<4HRv!PXdajaZM$cbQ3?lH{@5 zM$CnKS6Tj`=rV<^kRfMsnY*%VKtk6E|s^*jBRkpU2Dlcb~8+_F>Ee5{3X}FI0)U8Kd#M! zK*i*GP7Ea#SRMJ7?Ym+3+5L5`c~p<_r_a$QGnD$Si=60nW}nR7RAjp02r)`w#4lhO zM&b*k&a4N`0&G0&ivLAu#=4|&_6ujfX_Co2{;~ex*-pCCcT;B7w~m~|a=+Y^57mtw zQd^If_}h0Q$}t*m2#sx1`Th_ong5c6n%{+uOI}{y#=^?VYNwkLwpg$UejG0^;d`<1 zcni3ldBejZZG*yX9Rv+sbSclO|7D7&E<(l9yK=|9sLI2>PJ_|ung=J?x;=20p`gS4 zv1iX6;O{btY6g#pEOh8S(F^J>-HIjGKv(xBgpps0Gk>U{I3s2eoBN!I@sW`cuN_&t zqf|5|+)GEUe397&-C%V$x2yYP-3uFR@+2t=OX6xN^GqY;$cBg#g5TP!XPS*+nj1Z* zoA$@Y!LG&x!27tLFfh{y2)vWGC@L=Z>v2ga>rg;q&tN1LF(8VkQG|$V3IbWE+%T7f zm+p1vn3pdr!<=fb!(OB7SkrR&@ChU##T?K-_b)Q<4^Y@= zV(_FmJS)(RRHapiDIEMH9dxpa<{jmte9(E2X4&zCnXMrZM>p!OUE%3)!k;k~H{PXk z?2~8bDa&%>oZdw=45DxE?5xZkE6Q#C9%5NVbz#I$o5kOXR)chwT`B+qD=Trv4Y6Hf zZ{2Bur#!-=mqH<%XPDgtqZ}LeT8MCnCwzE+f9@=p14|-FDesSRN z6*U8#_knE317FwbRxWyVeG6;ecu0Edz0tRea}b`rfz3p|Xo4H|`F@hk2^=CI8n;Ox zqujRS7|~0Q>)83beKV4YHNIT4ICdX1Me|0sAh^FMk{p5{vS1O&ZuR@gQVB3 z(_EU3HrLDX6WS`&WV3{KhGDuNSiM!|YRkK6>{q&|J~1Z0xU|KLM zST8b%OH}$9DS(adjt|qlySV8SHCaFdPlbt)I9E8PCZZ(uL5*`!Q4yGr2LKQz3MH**Q3~$9o07px7&u`*)hP0*cC>;0=AHwU zZbMCeTkILxK4W+0&z{~OGKgDw@VIsWrraqdN`@AsZjiL9F-OIL^w{VF+naC)3Vc+~ zlc8NK28$;~nql4@`B?2xEaBU@zi&p5=(8$dn)&!)s7S$q@-KBz8n6f6{MZ}6#=@g# zmqglwJ(-|8yKVIJZYg`bf)ocm>s`_1DsB~0k#_D%B-Aja$=+Pj&YMi?O)CH+lx3Byn<@FiXN<3ICk!nqg1ib3z-J{4N}!?D#P( z=oxIf?Yde*$1~6O9QJI}wk!kpn4MpihE)c3HnL?xMsP6Qj*2!M3X;W6C}B{@5J&{& zD*g?q=jEAG;)z*$vf&ferPirEVDoz}$HcW;-*_E__3Up7OwV7|J|JC%wFmycGRB_# z%G`{M3??H8%SqX;nZiA^cfMAw#qvxev_Hf^{d$ep35U$iHixcwGJ+m9N>0mx5f4>z zRQP19@YuspmvUMr5 z0`r=oKg|wua&b9@$%2fdF89bLl)xOi$#n1=pF68u?mK&w{OKFUviA~pXs^5)(fEIg zWtmcwV%aVS?PzOcu41*jE-2M|oN`88slL8`5p;Gd$aHr0i&c&U>p^?)H@9Z}e7i$5 zOs%=h?u|2}MOA*}#h`FTxp&rmkM!F2#E*cIFL(F?oT7|}HebmxZxn;?M$U7@$@9CU zhb-WPxtm33DnY4FA$tGiO$_#&k+UiFz((A{HV{SW!S?d)tz+>q%u z(C#yQL7nRE4m;iMk;${av35e30AK@m&ziwCatz`kfCT4{+~Kg?_+@q(JK!GxAX$Y* zz8{FuW4sh{$I85UYKe%$eC9=-$KbPyaUeGMXGM6FsHCz^-p)ydh7epDoBPjlAeYcFN z6vLoi76u+ z?frDJ-Yu&4-{^G{qGm)w*0L{G@eQi$*xvC*X}RdUWWG8kTOZhrK8 zxHc``Q!b5qVej}M8HLkx!p#zoI_fP)XbqO8_SV+Xue--Qg-%#zp%8@+IgP1^$BTIM z(lf9!r$7#U>iH^~x-A__ShnZ#5=XgGS()2aRr_6zm7@g*8F@4%yZ0K*84Dt8;<%*n zSt_*t%Agst93cv5+zfQBlkF!|E*DItcINE=?O$IPuD_p#n`^vmiC8!N?2y8;#5gc4 zJg;Lq13DFjrO@o}g#(@e!gPwi+E|`i1?FuQTbWJ;)X&4Sdzp&gVu#9o#uLd5@`_+< z^^SciExfaR!bbSBXP3j(Rcj{r7S)_zZoW^76ZA`|qrwBpvfFUu+fE*vs=D8~187!G2vp8KL z*BgmXGCk00{SlEx5Df) zDX}(M0a%Qh^88*RFBVodmG93N%$^>ER3EI!F%^O!%&`Ha*>*&@cl8{%d=X`#);Qun zeKH0BIZv7NgMU*%(F4oc5CAkl`uv^rrrBqv=IQI*5$s;n_G$FV?j5&X_TE3NUL3WD$H#;Q3!n z6K-%P*k%#c;HHoMbf{*vg3juq_hqvhMf#OX!c`tc?2Q|VQ7(Knj~?GQB%yNVd_Z!< zc|GsJcmXA5-^Ey+&}Pp$q9pwb2LkypDiBe=cr$SV{Qz^xcIIpRppFPcMi9^y{;#n z@$k`Fs-mBo>X0LclU3awxHno{Re6WWvlV$G-b1%?M&~hm1oi)v9hX_~CtriN z7z6XYe!|TUJ-~iMn`NPtkz2aY)00LdW{#kH9#4qDj&50c^CaeTQZCEH@kbeGBAO+y z2jC96QbOFQh>1Z80O$`FvkoEa^6uNw|M5B&03NhB-*m;RTJt40{;mroA*W#d03mGn z!{SH7D_NVc^@FM?b4XeUU*2s|s9)E?g#D($ks8NQpykAHN@q9A7aC zYVIG^M^MqmKx^bhXBwnLp5#z_0XpL9G7j5$;$ro`UlUJf1+!F0-$G@Eoa8K5=Xk|9 za)33Uk{>wL{f3+VHuOknU|@N7j+i8zP8+3>fN^hcPwp|Vrg?I0Piot-W4SRD6Uk{t zQ&t+THfG6aUeZzAWl<>-Rw*qbtc#YaYug|Hp+RtcQ#f(@^^E|;M#+GhFc$VmpR+xP z;X`{A`%kyul*=(uXD=z+8_3^-`M|#99<$pR*ctc(T7HaNd!*JsGBC_NC)l!pyD10^ zL7z-KZjFtw7_KgQjW{i=2htJK7! zMT`1*e5}}pGd1sXyP}g%o|VL4o-3+U2->p_(Qp6l(zDE6kv+t?IkZijvopbne=WC; z!3ense4N+@14za~x<*CYzTPVF%8|H(jCg;vZK(K6BavB>WSMK>YbE-^^Dp?J3^lNT zTOeGlfOj5xsnD)xdwU*@jkD-?>*h1EuAy;5Q&K2q}rFB? z)!bLhf2dBKkfaR?Tl6e*(F)MZUV3(#I>k+`S43$zHHW7#gDWWSxxv}HCSkFj-oB0$ zanWeyi%r7nPqH%;ED^d-TAP`Ic;Zy%{pxMdwhVyE(hdO2@wNEwVU?vlYA2~8PfKpU z|NI=yiiF_w!dV9Yq^!HZsF^jSaNpDBp<}CRi^{{0v-6kCqxB_3oGSF-jH6$CQOx-HS~l0e|2gKM56q zo%CS@*`t~*-}nzrh2&2iqkGiy zg%xfuk!lnfoN=Mviy9OANMInBpBmUaHE%4TpzY7FwI}N`Hg)*uw*RFaL?M5>blDzQ zm%%(BScHuM=ajdu79~&9n-*HeMR89QgEK>iSm&K^`^0JGE48VkEzb(Hf1QSm4239_ zykBu4+rLzF0!Ohsn0wAc_&*;d$bjQ)|&=8Zgc5to5dOR99$5r;+J>a_2 zTOT`Iii*(=aZBCEi$op6L~)sgzlo_tcynF5ZI*oZQyYt#$mt0q|%rk_i6vw4dZzO-7i6pBY!?zK{5ve$*@WOv_-B1??a<-L8mB z?(D7s!R3o4(wcndTA&xxh@Rp$iyFK$aA5tdpdt2z)$tvD!0Ds1%B}eO$}Y)hd%zzO z5w)BycJlPXE=WBX4;S068}LujM>z=%$5Ekzr+gC2uL2~Y_Z`}3G=81qWsc-B%An`f z>PbhXi|9pxg=mNT-y0kRPTEF%`)!NDz4B~F`k!+p75UdfJU-c@sju)=Fls!PUZ77+ z?#}iMzU8T~&;sZoM<%*3xPI~eLg2U&w?xizSe8b8m?_u&D z7F_JbF~_lYf*Iw<#pp3}Tvls4Lx)wn7KWb{CgmgSQHCX$;L&PgLM zj?F#apu6x*nDcHyEKL12j0GwSqn_pL#U|;-8B*JLFE;cn-TgV8^w;`FG7rWdb{D>H zIW&!82yBw7%GIWn`FtpM>iQ%>d&Xs}SofdV-@f@>V^^c+D<0+iBh)=;8iJjc&9L70 z2kU-`yU)&5>9$f6aV!wrZvC?U>NV3<&W|N;@<#);&Ck#8IxJmcZScbp&svt`)%EAP zk+Tz1qiTyE1}xf+jqSlGXmpsls99iw|>AGL-rkXWYP&drb zYv|tT>iTL~gW~W+A_Rf^ugzG^u+B4?TX9ROU0@*5qFs|cqMqcP4fPKY3hcJQ!CN*Y z*cPZMmpBTJkDZU)QfSZtG*_~+qcFs=uHl!>lchDtxjC+v@6EW_C5uPL;|2yOi#m4> znd0wVyymr`d)Y=-ET=>gHvp0cVG?=R5mUkG#SqDJ#f!2{+ zYAW<@*bHbe5<++H9KK((b^yb)d~<5J0K=a$e|zvK>K9X4do9=d!{D7|kF(Xb>Pwk) z+x$f#h692wzPBk)%KHBCw*%o8kB9n?(tVGapq+G><`l;&k!L3ZsN&tKfuk~lxsro^ixL(Jvnqca( zXQKyq`|+$$&YSCDe^<2a%3_OBa0j#xcmdDtGi!Asw!NwfyE>-`R4x;lysh$HU*$z9 z_+@)g#}U@V+_`cegiwaS7)9Fvrm(~3-pD}%%4v(_#sj}WN=bI@V%z8x)V&w(1S77% zSSrI<;HKn&#W!&!PJ%qGc1a;GAN32pUcI$Acbq#~iBPPTdBLfNza9cgolObJMsjXI6?ct!b>*yNjE&{jSz6-g@$ebN^l!sk{B@2AK_+V zGZ8X}Gz}wMG!rlAc(Ty?kKa3Pl6__GWIhM%|9M-z`(rf?Wh&uL~^U0<-7P) z^yQnA0gSs#?hRl)Uss9K{Wh$D&K8=fs6rde!3Vao8Pr zph84BwUM0ATf&M9jFp_#+Z3JLgcmNWGltU%%t#~V)8doCZJ}{Mt>Q?>{7i&!jMQQ7 z7L@&+O8&EftDq8N+9K z=ss%}{zgL1Ru%t>4%we<7GF|Q;zR6aV7u7vT&zV#9o<3c8?@1a^a(n4lp{CfNY8;n=g@y5&aLA<(^zyxcqHj*LFClvsUo<5zpZ+(%dTtL!VW8i?q;Lpt&bUB_F` zTITYl!h8-e+LN6H?`RHNg{tJN70~aFG`Y<7CkfFtIevPFhVby4I~`ImBF&_*#Q$3} z>6q|8+f263w7pZ)po97VZOw#OR@9Rz;dWV|4X~(*NkPOIgXR&%Mm$y~ zobkKIz!B)0K5gL~t#CQk&$AJ{tjuYEFhMXF{umx0nTDb^zy^5R0P;K; zu!m#omr}XUx2+XfsJ~ zYt^O3)$Cu06KI!`nin58nQAkOZ>qGDC#nH3xrfG5voXqjN=M+6IRnD6Zr)!b1K-pY zpL*O097(33AQ3R=d=a4>FzRlDwbqTdsk zdEU$Hy^$onam4A|x%T|UmO-K}o7PZ>Fm@u=gySn}hc|(8X)0k7ZWLjFFXujPU9D zEt+hB+!lN8Zp8RSqELCF@7cbWWPZi)@$!ka{inOTtLM@L6v4O17d7fxK?T4_4C+v; z=+*Ot98I8377`Xl+@G6>>i! zBIi{q9v+e)GmqszC$#+^y_)*k$zIK7W2=KJA&DiL<_XF(JyJz&K&IK%ozP@)t12o^ z4769`{as`4FfkBl;yNL|wL#E63Y|g(f!=V%Tt@V!uNyX|0$um%2bJQ<>9DLu5g{OW z-xZ7bfb@8;bcoKO#~H6YNz4sUNQgBE6bgMk!f&tT`Hc#$Jd3vLYB~1mpvH#~>`!*yr9)vh)l`27t_aGW1WsN48AwA{t1w z=YNr4D=KHGgj+nqX@novHFfmN$5D>gK4W9|)LGvW&%OdmWaT}$D1CJs#_M$QOTaFb z5N9-Em^2Q$79g!`cvSr(m1rZI2Ij?yE-Gkc8iE8WvH z;*Pv&ewUbVwDYu1=B4=5%?}S370q**{}ZOtz1VvlSWHH&lijt?sCah zKD0748E6xPE1J*p^`VvjQDfo5Z+$F(=y{L(^18I7jS#-TWwL6n_bpjCYKHrdck~Tp8&IffKlA(=PJbXOc_EhU zuaf)65h^BO$JEU4inOigB+DAO=BuW#M|u-)E%7eF@E%ZM`mdN*pl_AWaO~AB4?1Q- zIPQgW{>Y~LrY?P)`qD`c#Y;UfnlF)=Y{|G4mzIZ6AU?C3InKH9NO zt%vR~)~9HY69-oaun+ze4=o4z%e$BFX5_gm=@|<8(7kVs0ElXlF2*^iF$g`CKKCLN=_Mt%lusRn_o^NKs(mnMAdpAxGJsf!iI&-C-!aHpn??bZ zmK&8iZbpL5r?#FTzEv3^q-`~KTaM+NTfDy8zj&H%m3tj3M3Q)^EG{XjjS)x=MWL~w z4k~er*Q=`3rdmx#$?!C`z3S7NXeqZ@M+uk9X?RvvoS)X1a+K|Y+|Jz&kPqladHS@SQU<(kb9Wb^PKiZK(@ zd7bgxXPF*+w?=0AZVg}|WDpZPg;(;Lyz-22$I5J*&F}Xmt=_I2mIWumtr3S4_MnE& z4Lp3gxCc=~xG20l?5G8;sO)idExbv!3+&p_@S*$*SY@Ly;`o@(pb2=k38xhK@XbeF zP8`H*P$m=n+b>VlFH-JTi}YV1EoK!t-0cCsL~*m@NhHPaN6WT6)11d}y=B*`Z&r2N z9_Zqsfn1L}@^dD>-ET;s)Kkga#~K@Ee0!l|nrjB%Amb?cxA#I=iUG2;CTDe({nDek zrfO8q8vp5NZ+J;k+`l|>IIg`?fYm=vb1n#@9wJ`d-dpzWfzqzAHsn66M3KL;TuzMg zi`;mqxmuXtJ@Bu*8J^v{b{8v}AsiDuKS;Nx;*Sd6Es;-hM;hcfMT=uQWKBXp-#}x5 zD22-_^74^j2V)k9I?@}0L&mK=u~=)EAxRH_Z3Ddq${6&C_RoUARj$Jx`t)gOSPT@# zQ~G>A+N46qMa(}uyUmaPv1JpoqMMjHgI%FH{M9b>{`SVy(9gqez27MEH4b&9X`R3G z?p)zDWQBVS#XrH)Nv1F;I_ww7H#V9~?`zEbmp2ebE`Y7w)1C>cZ@atbrQ3uU4R~>+kRN<#@ro@a z^Q#QjMPmXHd^VXX(di7ggg6p>bm8JrBZqYqh&33|HwN1ObX+1JbZe{it)>I?xz6pF z)7=zHd{^)o5uKzMZgC#ID}0MausjmWv~of&$UEx%*#fcW9G%p z_=wxLHqGPD%FJvSb~vKAZPUIP)jAbY#=4~e`tVMeqv`m6a7I?V^Dn=704f!6qsogR z7Do`|*#lG8#uYw&{P=y?mbHLtahZwuo>d2;H8Jt@fx5lVCcI1zxv&n9EFk+m`0PXP z3$`i1G33n3>qHz}*v&m(z*j-hh?D2Sh!Z7kon0s%f57Z)hj(%0&X_-2G&~UD3C6@B zj*QkQyq4rz1sIu`{kW@Jtu0Lxr4awi?5$Lbw4uz{4#>G%*@}xdnzc%`cv&FcjBbjz zfn`M%xd_>s2qJes_!0Lp$tPe)vqmrl;=oip9G_VPj_+N~_1%wn9cNKpBgv8uZ~?1% zSJPE}GwumiKo8!k+UzY1jZ!C{q46z)Vg%bqSP@njd+wMa&^^rI$YHbko9;; zqnSg*K{E28BnF}bnNZhYDO68IjxFyom+8)7XHs60fI^1*QgVm=KAV5jVRY`R=awqB z_6-9{U*z|8NtG*+Qg)KT1SsLGgovd9^1bsc&FkYECL~UzPj<`>m}@+6U(qpE{zIpP z^Hd{pKK6y2b`XMN5y7vqv9YT-4+>fxVM^)kT_E@*{ufxS-03NWbOT*V8ENE4?M?2I zsx4jTc~i)m4{eJ+fmMJq5$H#W7HvWdIdBA^;#*l58i_7Vv<+I_iHGn))Uxs~PeDbu z{dODXB_{;ga=np654-`m;lywW%e&3S3q8MFoE3dwp1H>||5#8`E*rmOI(NWS`2g{@ zF2RP@m1RyO{2mwuR@hMMh%+gjr#z3 zW&@C+5)(k~Rri5+uY9~^cZ^+oSn^cY`f7~hjWl%Ju;;pXt6PufB7gX4^Kqs9Ne5#P z*_*##mp0O#Pzf9Y6A(~Nkai29h?$vnAW<}b`mpV>oCKKyykX1 z%9z$`@d8eRpZt_O-M&0xRRFyX3HpZs2j8FP%aM(1e1pmUOxjm45kz}%Vv>OF6I?Dk zi#vELXT{rc5x3L@pWa8rF7h7Fv{3aZ3k!ZeDI#zU6yRfh4E}emO%|*Ts6WXSC;JdN zJr2A}0bS!g*y130f$tRdckBZ;XeH1wF`7ffik<_`3|N8HiP3CB7P@i%qtKP%@&1gt zYS|{_du`kU))3yNOqC;m*T|fJ=f{fRpxc;#X}%`7vVBA>`Y0`}%5TQPeec*|-i59uOsl8s5yXRVg&?>E-2%x6n9YRUc_L|vJaxQnAe_~g z$=b9wW5B=`tJ_D)-n~hGC1eBW2)PFEUh%fY+Q6T@tH~jQc~}-dK$XF(fi+|25(?>n z`w+`Wq@l6QSLD}k)Wz}ZQI+-uIJK6p!Y~nFZ}R6AVV)C}K)g;<_%k`1=IO_d=`Q)1 zF_L*E^JDc_72AqL5cqglQL3Xmvl|i6-?j>hdwxFww-Xamc51FdP4i}q({n09C{TXO zS~u2qa;s#>-9)rM4hjnzP6Z(cfeVOH(Ck(L9f4~j8s!1fQ@i6Ib-iXXnsnQ(%U<*? zRf{)fkJC%6%#$jfZvYF_5Jq*fBNjR=u+aJwwE<*J+d(}cH)*|;)PSJ=mu%*hx^3K? zO?->+!9(YT$|Lg5hgPU7+?KUgt#B9DpL<@|d-R1~uKbv~HhLvY7I6{9q_bG`FxmkS zsQjHQRBpPEoGP;=0>WEC$%0Hrl!oK(PJ5vg_ShF{;$>E>G@#4}4<0Z#-NxuA+_4#> zyHz>;dn5Qq{FPc@9$Dk`3ReVErEImu9CGt&x~*rXtv|KkWdbEU=F}-*D>ns@Q+E?~s--e*C`4YfM2GzZ*P>&`%*ml)k1~ zA3&k;ub>py>#<2llnEf(j6J8^$=6wPO2=4oU&C*q0eD2@h}QFq(CICohWcho%A4_z zbuL$OY*8NwSL!G}do$2!*PvX|&}g;Bv6qJVQ(pp;mPm6b2I`11=miFi6FBUeskxjm zf7Y=@9ad&QE=TKZMu*tfb90E`gcwW+$6DVR1yn6I0?gp=xya~6L^;z3yn{HmSLB#9 ztv{f^UnB(syw;10Yk;f)^Ho}|ucmV1_8IP&t0%WFvbx?rHwix3x<+^V=xt;99sNzU zj!G_F+47Qag5m@F$2&Q}w;~iei?wQrb%sQ@qg9L?dM6&RB2GWDYM$56X_PYgoSwNP zR2WvakplUgCJSqztRuZ4xrulKDxBpC4%-9z0hsPVP2cr0e9@7wOlj`OEz9wdY7+B< z^mL53O9E5XCJ;H~1NbKngd3ZTY~tCtoDBSlSNNIk(&|Jvp{jDCaBMfMeoUw&FMQq{ z>&P!HrlB8R^({VdL~3W?pL5E{`?fy;kM)pgK1AVkz14RM9Cb}$h3DjapG#vpmV}Xo zl^D?`fJbqBW3^ovyI?4>X3C-h6r7Z%Ec9ArrVTn#(Hd>e?sPDF@zz+X}3>#j#OsT#9F)q1Xg@mqXGaQyU~z&^%cnz|l;O@0o_ID3L>ins zmqykx<}j7{8RD9X`uYSc6@>JGmXo*p&Nb}NoDY#>f2t0|>l661($t<7!(dooj8|)k za(4xCq6W$%xklGcMFNA8m_NIf!)A&+^%O>p081SqC87VsW)lOi*#t&ceNG{A7^em1 zLHujg1GaSVh-ChtKO4zMt(eW0h}y~d+xy=!F8Te$jJMY-H$P;R{@RKg?Khfw*dKy8 zwLbNG^t=}*W6SF?wIOiOND*Zh(!s^+(=ci9V0xkSzZP?n69WoVpu}uT>GCa2Y0+EpS`=wO%}DYI(I?PWLFeo$n-Nk$vEr?dSPw3tu3X zn&<>YZAeT-X7!uPvl{!t7ajN&Ng;e6S{;27h`_Md{0?grall2Z?}w*#=kUe4!r^RU znyRjaX9b0ul@RKy8_H|8#8-_UuFD0cPM$*e)JXa&&jmR|YLNV01B23Tp{t~2wYmeV zB?YqzfKTWtgmZ+*cmTzYHH@emc+yF3Dza3<#PX+>9`&tLEn%rlGAt2q zV zK#u}ed}ztKxiC&u&%e&$S6;${RKpX`E%KwZUUEaLxOm&^@86!!CLo9?1^$z>>8CUc z+JX^aG}$3mC=T=>mNYpTnLaOwm4%cWP#8A!f+?Q+fTe=jF zQ5~u5xznc}1iZFzj@QDlIP3azJE_uD+Xwdi@cgP~uhc2PH#0agQaXQ7UXCxXb4!1+ z%t5FTF$v^V3K)8cayfynNOo$Rq4!)vMm^V}BsIFmI`iHGK^#+tF!6hCPY532c;Oi@ zGTn9zl1!pog?c&qfI%~R6r^GdLKsDZY$tlXAI4Qk%Tc)<0GWShi=u}r^J!)6CIe4& zt`M`s=|jV?Qy8(ZFv2Ip3CAivq3C(U82#2?njhz`=KcgC*6ef+4Z}FU&kRI$*>{|j zj2Rcu+D%}yM}2Sn+COhd{c6u9Q@#JoM}1F%xBq+4e!eg41m hg#1sOgaEF$+Rl9=M_YG6M#{rO*`@bK^3Fq-{u@rV8l?aL literal 56848 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 z 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%0D_ z*`y6l;C zT6q$<#Itl53Nz9}XY}7{v!ZPfaE-Y4Y_~N@23iYutXjB*!-a?M(h~HhRaJ%N<>l?M zXsakIFMkT65M&(@4Ix}2`#L4XHtUoB786k~`BJPU+h!xajwT$zxUrl2o!cF9`@Bz$ zxCu4#`5v!b19>LMtUw&613E`-rZ@JkgS3HgrL$)-oI%#|EU71YiA{<)k$1#F0ah6SmTCkTVaDi^ zD}49PE4%4F1$(U;O`enb~oSROh zOVuM>c)|Z7RZqbs(+*I;!A=x>G6nDi(wtjvW$RX5{Eo7`(Al$>VTInDS?!B%?j_L6 zxE{y-gj2!T%rVAc735+WiZ>xx7mOIzZ77Y@$ zB;_6ID7#U8=pdAGfLtOkBgNTQ=((4?H1wSRWcqU?IZz_&1pfl*g_l`E<5(noGGYt@ zQ5e3&?|I}O1_PYJA&$J)zMmAeSH!|a99-IeM4W#O_EG?bJHZO?NJJ=JH?VM6nAj8 z>jN*&3SvZrtMSa_BRT(%A{>i_jUwh*9{mty*tCf)&Q%Mxg1~;!(Oe^RXQRhP%SwGb zmX-eE-waVP+1Pa#vvvP6$^j$3xwf<4MpQqK8GF}$qVrkRY1|&0{x8pINFbpwBGJx= z?Pq!99jtU@B{vlcY&77H6jmV%R|J}g@Ta;zbLO#(A))wUC7G!6dUgr)WN9C&t2gHU zyawXGHaciw()0>}hTYyeT@-*j~C~n#rJ##Ct5J=zQ@@rEp zp8=WvhtMrR^Nl7+`K{+opf~}ssbh$xi4s-r5@4i}m1lTS{R4!tf?v}|NryD#mX!q} z&bGAqj3;+m{yDcBx=)Z#RY~WRw`?nRcVe5{4l)s*x8AaJ7sL@21=$G2mKJ@@C;G1g zp+mOIUl%26$J*!J-`ysMgQm&(#~_G`U~q;+I$xp%+|j5OF(%mOC`+2r0jK}oy& zOMyrE+Tk8HzNH34hzq+gJTPz%q6$RA!gJD{ot>8~_y*a#AM&sv4?$jY} z(b3Vf2JcSL>6H}~8(eg*T;xWeYw4K{7;YiQOCpE@xMQL+#vz13ABE?E|7VfhFQSaM z|4_up_0r|b$N`>td95IMg^P;|2@D|geE+IOc#q0g%R1;3Au}?pM-R>wq0?`EBD&Hu z5SZG^#kXaGXu)`w#M1tbfz|4++JUSo%)zvvv29uq~x9c;SGVU5Up#oj3 zL#a%Wb()%*3NCu6&6|B@=E5x4+A=)rk*Uo{dLDtq;BjOj<5`V38Kvsn26^u@9z9xR zX)T@GHVh<_*~dcvCmo!G`MyhIs!iXm%;*;HG&lJZtleyX}|yac15S$ zL@ll>7_dj|<2ClMglWLaN@iTg?N;Mx`kALvX~nlDI9fXs*5DzllfJ7VHrXgCDn3E2 z1?LdlFx872A)Zr`I~U2bZ<#NWAsAzyv;O7fN<^OKk_-=2A_*d~@7+b&oBbSjf8K}O zn0W;xB9=M@A?4qymHMH$knOcc8A)$p&3uP%ZOG87y6|zi<2%r$4SkzovHkWGB8UTd z>?u-x2Joo&o;^v-Fo1N;ZR$++aX%2ai>_&oX$grx@R#xUtu6sN*>|%)x z@H`}hTbDdX-dy41ROrMYe5olmV_Ts5QZss1b}J&ar)9=(p033HflwDv{8bkOLq5LG z{!`S$^J;z{@)8{Q4>&fsza%1l85E?SbB$N)szJr-g$LivUZ3X$X^AQ!e|jt8A;w*U z5F)<9g4qmoI1Ok}5(}e+=?%LbIV=-t)DQ-4>}AqFD$f7Cs&4f(H`86JL#_ zBOvjFV2G&Y5oOQQ`gf67A}l?B{yYNub-4|F#Ac%;V`}}6uxY>4%4ZcsIFJ``K4JhG zLY5D8b(d>0(lw{^lkH)IC85*eq_4qw_1_JFv>*|KPa~qVNX`&hLkk>0 zf0S}QL0|6P{Z+*0wqqu|4?N@xEkOXKZQdN1=+*h-yWxk)UuQ6_2s@-DjbyS?q984)@A`4V!cB`m`h;MeQ0b9 zP_*C^Zcsszh_vkStX9AY6T>l%kIy>0x0;xnA9?tiV_{~a0B#Zq4{(zBMW8A~!1Bn_ zkQSl@TC88*=@`_5Fi7c3tKjioKu&&!Ko*IL}cD7ZBOV|q(xs`#rz-{7?M^&=^Wwr5eku$ppg^HmZM>gSXNZg8Nm-w95h$sQR8$$IK zS|c(J+Yn0==tfIx*Vj>Yi|2eELeEYMBAvp+Nr^iqnfdcwI zoa_LHiLe=tPM%NcDMQ2P_!X`jiG2U1S8eYjjzhUH9DyfXnRxrRPiM1PP{;E^xQS|b zNh<8$cW(${0wFaLXc*7{QK-a*P=;bSzvj#P-#EfjTfH=jb!W=#CmuzuTUOM7bI`qTUTp6 zBiPT)J>@;vC?rZC$)%N~m}Q&X;3GU9aJja2P(QE4-ee{)keCQF(q&=^NJ#YY<8z=# z+b!EDB@QqDx-j|YkZ7BZPk=6#h!%_?2*&V>Z9BPcWe1|{SdYW7!Al;hkpCPU@ry9? zvoVLmVnFz}?d)6b!(PmEMlW19NR>cp;eYUjT5l}|kpN6t+O_c6w8CRagM}uPE1Hx|ErYLv+|=CkDrn1C4|N<} zz0*b!02dMOB@mYVNPNI*_t7-W;;6q+cSh22Djl(z74}X&b|n@d6)HYUuN7F)rKbj2 zZthL(4E0-fXa5kCU;V0AkbaCSv8HcM{ft=3Ea6z2`p!TaM)+pL&KI3F>B6^Ylzzk{aQh={P?WoQ0J21Msi8W>v*UfqhYs z;6Epry5TNE!917vb4PYK>%%TYV}8pkRQ=inMK+AZ8=6tLOWv~0YCu{SnU+WL0PK@Z z(11n)JwIYqs2*judXQUGfURAYm)S2JHUwv4(rf@$rvz(XoSB@EfOxLv{_A4o0jb65 z0YyS5Mh|-#2%Yf1XHklG60*m9z@_P0wpwtLEbrE>$_EbIWS3KG-^|{d($4jLY|Dq# z?(p=+{_<&D`Vb31Q};V>F^dF2Mr7KtW=vNB#(eSX)hHr_l_*>29B5CfH9IawtC^oN z2Px>yH|Y&bX?St0E26Q!ZKVZq8!tHjMWFTM^@HXH3ye(IyLjoeg9~>-l#)s2lC`KP zQ9krvdPUwnMC~QBJ-^O8rTur#)tmm{@0Am>wFwXM2nL<_l|Dj-V<@8wunBRn-W%KR zB^TB%cHi6ZD!VR^XkN&uXl08DR6YCo?6xmww^67#cypYB5JdYe@)Nr@KS-WPa-Tje z``kjsE{&F$?K);DgR($VN`GovTFKg??@ltQ!Qw9itNHoC6{MH~?OdvMqp>zbC~*>4 zzoQ2}f)SG;gR8<(7a$tu*tR(GgpZVRzK&D?{P&@xDu$dBxrEQvBiK8zz=;rTvlPo} z5#5|2Q+9Y7XH{`0piSy)X>B3M1- z(}2((k@Vi8l~;J-?$0k|0`e?K6(T?rCIL@uIGvx_h$<6N@{dh_<9H~9fu=k7Xxt$b z$5EOA#&|jFT<4JEhS%$bumP84EB7g(xzn`@vn(Q>CBVmqc8H$hNsaBM6*ryh2LbVvVIP9MN>s{V5ls`9h#hy7 zT(yv@q^+&JcUn+1Bm;J4hs=A)@X) zYRqEZEMg<^>Fo6xyA1_>GLOOiig^8$s1rrK&UX7seoX?uM5@J;N&=3H>2ka!=RGrs zP<64**H0-G>4E0IQ?giv_s#|K52zsmRT&_gq*)ArT~RA0G5oOzc8sIV=$p;X>kAb) zU7?{qGt(&W=prWI92>aj>p*InKX*1DA}@>=Kqi1FeG}4jY=FKO*EdH5PE;7Xx$lz8 zCv1atF8{mgmy;RVvPguY^hq$?2J{VG*JCK~q^RzRo4Al;^t60QKyEC#6PPeka)k@u zaOq?OhLGVL;ntvh#i!c{e;TZsM|eoJNoV{}_e=oS96#N@%5}*CW0rlx&z2~%FE|mL zt;#FNdM8*+b1@c6rSxyqz+{E{@}ogKg{r7L%(6-SS3e*soS z!%+@`T3WE*un!cl2lBS}2)cq}kqQ`Q801u+!&f{Y>L{Kf&q2_>O4LV5Gs_l*9PXb)f&EWzR~wNPuaiFR$gyvPb_QNuNi%dA zR`(xG(V+YzVe?+R^PFFcv|0KGS1C1F$K{B$#h&V-yFJ; ztqW6(+}{+L3M{e*@L&;P&{8>vX2r?Smlq|mh>5;;MbVW|QIK$98dT$xoCaAz%+CJ{&_?+3gK(gQ zh=n&}st@$=W*xA!9K1i6;>6)E&MI@c#_CqKkWR-VWEA*s?<<^~4g~#3NemwYT0$5N ztIGYs1qw_D)1+a8&-VNn(J(V(lpmTESai(f_#X%Ys>09D)Rx>KCyAOig^I0$WkumO z_QV>?e_O2Dh(r2EJV*ayUk&0sQo$-Ikq?u8eB>EG9V>wAgM&iR`?{@_X0WrZR6-Q_ z17pVJ?f0<2=kJ9D^R01dur5zGOwPN$hg1(W`Qf?It3caCcXp~KnZpQ#egcR67Y8P2L|IDBH(^;?|DAmUh(Hfu3DNY}oiQ$egg$U`_W=hLwaVJmV;Tj>c(BbcSOc|%7^lM^S>IxFC62*5hfjDS&l z^3VOEQJ?1(5FiJgj9;w@01)JXx;UH=lpjI=G35e<_bE(icv@PWoqdaB!pV&g&PAw- zZHoUB0L?e>-v0H3donRG@d47JTwtkOiPcBe7_BTbw~(#b=wsT&7$mBn%rEZsLVR$T zW`%MTU~j+H->Xy~KmUM=3`ur2zjck>x2qK2?3U&kM5*BiqSW+iQ9e8@g^J>w+_rXr zelzjb9O0vRFS1ayzA+H^NYYvsi8mr8i~-~$gqe>ryTyJ1*aez8Nw~mIC-5_7k)EE9 z*G`ZiFnrKyjjd3K$+8h42B;s>g28Oq_<%4J)Rwf&)g-+G6oLyG`s%5z0`OogD)}|i zQulyhod_=eJ-m9pPbPtWeaF1;LSkc#O6R&pEzjgO0p-<{81f z7sviHv&VP%mw!u6Z!0;6t79umM(Sk$vi9Ah?Hdq9g4<<`0cuK`b15Ps6_JhrLrEbR z5j8e3pjc(FEqh;$lFA}VA}*@${}JMRuY+xB*`?l|mTUCQ{AJVJnSv6!(J@VQ+xl5i z>oVL}3WV+RRtcEy5NJnsbFJ4u{(?k8~vyhB-lc04BP~fP3=j zhV%W`e=d6=Dgz(m`0?YXqRbB?`c!lY`H z3*0rCum#gkV6^RDN`JY5a-m?&qlh95zbgkIGc)J|>U>PjM^T!>zQH_?qAMk-Ond(o zrAhx6l;*{*4P!H-RvS0PC&gxFHfnnE*WAyI1rYg9wXr{jS#cz~%bXgHNkroeFd~ow zU!T;Ryj&S%m}9 ztmKyjXE|P6Id9(V%?mcv-N%+B?8}SKayqTTQE=$}ILDEUnltr$z`l=;b5vZ(Smw9U z)7@Q2C&Oil&N6^9d`~|QU$RErMJ>O*>%&EmTSk#GMMry~PJkQ;Mg@hOWh>7%fMhd& zmJ2{u$0J^^Xf7j|v4?z!s5XEC1lx{>YID$kdonHx)VRAv4-h}-*p2;(U;)$yPDA73 zBAuT&Nfrbnh8T+UW`XI0_=>}cpmsJGoQnJ003WP;15Egwl65a9#^4h8Uh zxO-31bzZOl!KvFsoxoV=i}0A}DdjOk3aq*KDPS2=1kY}IFE3FaoSvS3W3;ZKLge$h z*ASr2L;?uUaVWX|f**+ZA>@hLw7cDt89KkfJR{PFx3<)jyZAo2#6zrb^Lk7tO z%+?_q9u|eW%JOo(D5*9wrX9_{pekdYqtaJ~|F&~`XV}tfhDW=tB&`QaBp}VMK+qoO zi9AZ!3XfFvluVn$8j@aef6G4?=Yo-mEwM%P&BSK=_X>0pfze?0frSJnIN(R{DS+7G zG2l;tEcq%rMxx^l#XG_4cg99FV9BptyLMwDh~e<+WDK#q1X1`#y*WG~+;B_p^~tr1 zUvND|WK}kK`ND+@Z;0ZOvwT27aj~Y+)>R553?9BTj9F{X!G_3pTceO#gKvEA+i ze{Hjqi|og{27+*Gq`pb&NI0GR-dmciNgxUA5J4#s)&DKXBTyp382lwv1TY=O>{EpE z>VL~y5)rNKy9kGv3VDiQ6oWcp>jLXe`VbDfaVdlM zP9X^p+!qRd_&;JYArUM5o@_&efdFH-#{5KLI-P$L)15}sK5d5f4hzjE4ft=SO%hXj z498W`A&Uy&KZkWJZ&_VN=;-dRtcub=%isg6+uGq^NWuzIs08J+Wl(`we!WFY@g^eBnq7+kcMJW*FEY=YvgYikeha7Y&dT5B`LJ z-A5uHP!{+AoiDDjY`C(`vdtL}xq?si2|x&0+V(Ge;F~r1ye@S9d8>@ z;*X4=y>kT{R2?#r<}iPC;^>8L(-l+Fwee4tDWwt{P4jivj<<+;>)Z>F-n@s$rYq z^Ko%Nslb3SO~V^87KT@2=5gY~GeNOtsi0|~PZ-=R_y;tl`koi`?4_@E8PN#&@j0RY zLgjfKT%@+K1(Aah0SpIi6<~(SF)e%PyJHx+1#w2jQq{1n-KDjS8@E+_I zzKA>7sdK0fvAHNtNxZAxq6~TQc_!PM>pUY@U&sj%VZB4K_c~6-D&032WrUW4fE|IR zq>@Qnzgm6!MJ%UmiE%+Ll~qE8*_$Fuod$;zW@S?VgfZk5q(V^#! zgX3i{?zBVI0gf7ZAy_p?K8&^3kkzxSbN{!584A*xpZLdJag9cCm)H=9br=c@u(is1E z?9_%jhLPnYmb*;~lzB7Xk)hxs^>t_dd4y<&`M-%@%%{*+*XEBb9 zZiv>jxr{2p`x2oyQeMi|&D9eEj6<|!5dBtl>C3KN{2qN6C8ySpj};XaK|th@QsWW3 zIQO2Z_+3+{keY~0OA81H7!X=^UMST=u|CD}AkgeN{Q8yXV_EK&Psoz!&RXXojXjJ2 zowuy{C~`@XwPF*|f+6Qw9GCl17$q($k!=Onzq)TMYCbiozu-g?y>w)ZC04aq?kP?u z{E}X*&ksHeKFdV~ePCox8`N5a3=z->yxl~Jg@gW&V$qGwE;@qGp~>mG2mSQO zRPe4y!zsG|c@eIH@ror$-_DPgN{p0~5v^gndoJ67K5_=T3k{@uk>G&2J&xSL9q9N6o?hU-(jpUE!QnhXoDT^KbEIg>@NYS zwg+eCp2u36+&?E0)B}bmus0=r{g#)n_Fxn&QRSs{f@>7?@TH5BnQJCw2M9z$@5{8% z!s>xjTTVHS6cgXzH#6r90au|29+pw%b|(^@QL^lPnPFfhUsWN476T;U0851CB$FomqG##Xe6@2=>Z!IRc^*Ii;^T`S%O@jnbyg+%kb&pi#4@o0E>Xr4rq8N>zA%9kVAl zH@kpIh;p~jv8$X*RbSSdin z!bfEy&JXB z7QWTF`>CN6UanUL4t+z`)`w`l!|*zrkr_mjmq?C!QTqh?W=5aQ!nl9kW@2u=(C%6 zeUi5yb&YA=pOFkZ-`G4S!1`oa>qEzo2F|F5G!d->(*i?1l$ja$~x~fWcc0Q@jyh*lvt8Tf+ z6TNof>B~zCn+7^gYR9AsFeJ}hj52HSNDh~^thOuKIS-4mJbYTCg#I|HuwaYa9q)6_ zRiMe#Tn-XDvn6XXT)N_Gz5{t>N>2}WL|IN7Wm!H7GiwRUQGI&NXeu$ZRHIzrNcOI& zFCRGr1`kes6KGYRyn$s@!HbKY?yK*@BAM&A+k9o~8Wix$kJ%ro#jW5&)#!7nN?01m zmcMwS(y{W>fCbdbr<ot+C6jvD2N`~rakshO}b%qQgqVRp@@si`W6;74LrvJ ztE&`kx41(IqjyQGsko$e4tkM)BA9<&uE3W+*)fW1JUcVtM9F5U-g2=4##GVy6}t?3 z>4%R!ewfy#!FcDPm8&r&(-1Rt6`Qc61q=0HG{W)z$k;)R{>)ENHAP#*UOk~0L~8fB zoEQ#aH}xv%=ZsZpwv@{3D*b{zYt&?V_u{S0P4txlA!Z&u{mwiZ`I)U2qL*z$R`Hjv z%>Psw*!eT}W}8d*+Ef^7vRc;;5GeL+HKGFk&}g~blppP?wC)e%gCoy`L#Ty6eNz#H?53pZefwKm}0e% zJN`bw^p#$^TjVr+Rv*%6yAUmWq`*Ey%Qoe^vy0Y?&^;o&@e2sT9V_)HZ zp&G8tC2P>88miU3Txu$V;v1!SB6%w8ot;I$Kfl&EG)PMGjku{5JEacylzH^f25zqKB%5Bjmbyv#b5Rrf+9VZghOc zyS>7?b)$ffmK#>vH(i@?UDtZFVsSsU`ansC@Tnf2Fy_Wm#eShsWeYmpn{M4An>>AW zL_%?NbCAQ>82z;4#b;{%>AiWSrW4jIMGxw28oIlc+XWiSu{Q;Ep2p~|%3QLe`$APq z$%svyd%?11T6rFSMT>;q{oYhTDUAZU#E9vGT~qBw#ih=%0^LS$qpwPNbe@`Um?!+f zT6c6}b+NJI^cmygerOYx#Kb)ux+C((F6+1K2L2RT_Pmex~tX^+bkj@wU`mKu)?$WqHi`}P){ z2-=7fQp~<_fq%o(a>v2xf@#K_JLdL&QI)ssCj+z;9*5FlS!3d-FQnL7`uFso+JL`r zHPXm0ffuGW5F0G=p`WvVobQvrQs2Eefz&OMhNbb*9Pv(pcMRi&Y3`t zdvoars(l`;w=KUlV<1LiJXx>5ap7E)@4R!nroThxm^#Z)(OF5~sr8Sr#SWA*o;_$0 zbvR=Iqs$WVbD&L8<6Gqc&xC&V$OGK8s0T&{*%4NjdDpEmjTj zt7OVRZsLf9jf<`(0r*9xs?WPPuqX$lR=N zc(|*=X;jI-TJM8|fBQg47<5&ZcUAdHS~|-j98s96?uOr>=O*N7M++uPq}Jx7W#1jO zqTUI+Us2*}XvM3fbn&r?|Ib~Mtr`rT<%&uY#BFFl^om$uVQ2br>v7tb>8V+kvI7k{ zqOEzEx9SX#f_{k#r@^<2TR6B_J_+vZ@fhvn*9tn&IKDuHALd1VkWUfksm;uyp#3m) z>7`AbDZ6MxxHU$bd1NEK(Ce`ckE4`F_cOnpYb#nxHI%t6zAXv~E=}*3oMX?^v&v1Y zQ%a!V>#9szs@7)tNslx-uY7f?d+&hvB$so`At@tS=X-HgB}2q;d-e=3V9GkRe?cV^ z9146#j$HJ5`CHb*J<>g+--_HCYC?OfT9leY4Q1aAIY_*Q;dlL1LkoW7YgxiLBCttl z4W;X>ZE@VA{VE$Gu$Q#lL$eW5nR01k^=^fhynq0Wwf4kQPPgnuTX89D!pf;d(^TwRvVAL-N_bUQP<&{J`<`}NI~rWL z^QcYjN$=rIagFn*wqqU=wa2k+W1_U6Ms{(_+byfy+xZNZD&&8)Z5zBva|=SaM#7cW zfT4g9$%>YXU*3sVvpZL_cZis@+sNE|+~OTvBsMLZ{O&`TfROdebCUrdrk*qoOV!dE zue*O>4>0Y%96v~oAds|uFoCoE$X=grHOD?#xLwtLee+5y66}ksKj+!hry}83a6Gv4 zTkzpfeDezZ>W$O03-E%bM;8&388oguo%c2MLx1MU!a@NqCVPB`kZ_B-B+DP6OU1S!ZLP zHxMXbuk8VjM5j|NqCsMVeFoZh5;0$NtLlr-S2JSnoDMFnHm*xB@tA#ecVYR*kH%3> zH)78^1Yr0IG9%KL&dsg8^LT1}d>$F0ZNmN}p(WX{gF}XO)x6vfiY)HQggh}>P$7tgnpi8I{g8Ihw%q<_ly(TnIQutPp zKTT#Fpu5VdwQxD8cWNqrK$(Cg67>%<%$@x0;%;u}f8kMpHlzDK-u!eC76`>Vd?Iq@ z)Jd0X?o!&L#~?Yx8nwEm1V9Tar9_$)m5lDLB_dVtETHgAszB(c>cBYfYA8WQDKqIP z*?iu594#}RteG#l7n!3OX982KqfxmFuJ!qaUpvEW>%$>u?WCSO9<&|cx=Q64GI#6s z-&}t^{_ta7?YNjjI+}uBM9;oLZMo_eD4cgZM^6a-K!Pn(?ch-I>PI6D2f7oEemsX^ zz^WfW{zf^)w{?z7D_ZSE=>rGXFF_&gGyoK!lmK#oo)HuUQnDpy9(>dW>Wbw6Z}P#| za4!K%rJlDKGvs!4P6cdPjV}(^)cn{05R1NA1<}FbhZ8@JpMj@lL+yOj{@y;?SZu`ur zCg0$kmU9FO#o}`gX&P)8=dhV(j7CKqV;-{gA`Lu7{xn%0GOFJ`sNX(m zILPqo8NFV)yKx7TpzqFa{EldwXj{{XO{a?1oqg}vP{kv{8Yu2SKzs|A8zHw6f$LMg z=iYX#N3G7YoaOYB=!57GoR}OeCAD_cZm3G&aA9Z^H}xT^n_y-fGv9e4QZ8G^Dl zfdvCoYDNGJ1*Kh2Jqx>Y1GH zQ;2dx;f#z5OE#}B_s$sNCgpkA(*{RZv=@yz=L5Wl99-ZnuC9yrxiX*o4kxus)b%Bs zWv+>QTGsLW(GDgy1umPtAvsLdP~jcSdwu9d`EdToxE&b*L7}1{h-m#0R_k{W4x$9n zYIyz$=liRyAS8;TFM+ppQ9pW+tig!k4r);V57f^G}Oi8I(6+^_1P;_RwJkc!RI9^1M zVX1qaPi*PGl-fVl984&k<)M%F3_|;B2 zScIc}Ayb~mJSiuD7j<>k&^(2I;9YUA02PkDQKE~Mkt1;02@J18cQ_Nim@mQAu=l)y zG-G;O`HF1I!8Z9pYcMHLDdH|jPZ2taUiP5IH6AFRbc2q|n{Tpe8g<8Gh5G{UOHFia zpq8UYrFh^JDpjNo1KJ+lI-4_EmCx(^WP$$qxm}zVpA=mZppt2+=L7@r7L)@nw+PUA z)Wu9|{9~+8aP?h_uEe6$iL2j0xbhCQl2GT!9pvT=2slKcDK)+f6ieO6{`F*^`yooJ z%GA{nY0Z81(x)!J;?#=9S{{o&XIidTef@U3YWhhUcjhg#((1D;!{Y^2XEPdQ1~Kc9 zCsoK@k+(np3(oT;*x*WZ^&ZmO+(8sud51y&!iKfk(xM^}#F>BSB{XshGrQ3U0(F}~ zr#EBSMppSR;&`O;z`}7r;fL2i$iK6Ht+{0R>dgKI4~uQ^c#%N&abU=-2~rjZM>7O+ zY$Gzo(SVB)d_3$&r+``JxrG-_UCw|{N+fJ-&8-+^q+TMvqYspSMbz+!#3H)As-m?Z zMih8<+b4meDQnudXzi@9cVGs!rs`<|R>8N|@uky*!`qQd5_$%&Iui%ksqGFqmI>HH z4|>Kqq64L*YYM?yaj=($QkjGyYxpU619-UmsNOs}(tcw?59d&+d1X#jRaL^hdg;(n z@OEC2hFGH8kgc1tRG+kzK~ycO@{EYy@Y*P~co`I&!2U*X)RYq+5SQ}0_(9n&{-xNC z_%6QSR`E0N7ft5fZ;TndImPp4*x!Y2`^wp=;6jGz?8ZeqH?lJ28N>1jm~?WTG?vS` zAAL9n`X}5}v>H|^GlJ>Ms}{C+pKS3i38YL5+kO2Qn^1I!!SUF|N@6fiAhwg$4|@o$ z2gQ>IDmz?NR8>F5_=T>RZ_NWX3ndK=Q>hyXK|$H-mEtXP zOFFF#C%H5pMi->X?20WlR$kFe&5c-S@ z`A#&?eRsPIWkiqDp%Sc1Pq8`o??xO#&M8Xws}|HNdRY`?b%_!*{A7sw$@@ zty$pV@M+NoTP$@zz}1hh8uIU&#awK$d|@{}@L&Micp;N@(e&jCJF4%M$)6zvAmvf{ zr1qlwJ3HU+Zrn9`y}nN(!YpHr^Eo4w<$i=_(zgn2dhfGlM#CmO;(w~XG8w$OMDT_zf#P3{F z{M;hvz?~NH<~7uv8o6X*rSwbLPd4C>4r*>XC!&{A1=eYFw7B-i@>j-Ro`*Lk|bzd%Ovty@CzoS^RfL_>E z%&wJTS5wuV|89JB$CzgueQRCcye%z>xFgh58!enyFv+c0lzy`dqP0ZFmv4m!QnQUh zJd{Ulnile*4>|_x5gQXTnHd-u*jOwBmMRF0is;Wn0*B*;fZkvDaTNZ5@Kg+`kS%MA z5_6sqd%bSC33~j%ejo3Si(RCkx9VzQ+PmGu_2w4~*GNZz%gM{-269;N&V#3dAMLt) z0xvjy9n>K^MqjidBM5#J@ntMIDTxe>;H4L%C+5zrGO=P`(Yc$pCn0zeANBrpvj?<% zMT9npdCHTFH{Tm$UN&vj-i_}HrfsohT~v_3Ba+u{v<+q)0~tx}53`<-zJ|-t?YN7+ z4C)^gucjMwboSk{s>a;5G)OXlVo{=+rx!bG>90H5O+{O_Kk9D9DACkQ!{Jyp_G;B; zc7@Sn;_XF?f4zw|5_gBXFQB0HRlfVN$h%B38siuahm!Pie-$~GX4BvNBF2)5t(41V z!E&z1*A7?n7|2tHkP|+X(8R%mUo&w`;o34b`DsnTRv+}X#7EEVr(1<~%ZSa~nFaP$0ZL1a`%orQ5^_|V6{(Sd>IZoG0 zOWz7N`yQdNmSG-g2hwv$rY=|xcJEAXsS0aK0rlVcXu^-`;BUYF|EWrNQ#TClqVO-@ zXYnpO^qc@0Sv;(N1Tr3iAJnV1VB-$tMPS0CM!X-4(wPoq65my-XeXX1RY%t@y7!}U zX~Ae$J5v+K9a4<876diO8rv=)8zDTmu#H6-5NVErKqmFh1bUukW~w;9r7P+&ds3jl z)J;BG=S|Sf!Z+ypMk}2P=BD6%p}l}~JVRy~W5iD4YE|-P(6c%QDs~}yq5^_Hgh4?k ztuG^@&#ryP93I^{YA_z-(}+cRi6Al)^P2gd2jIZLLWY7*0!FXk9*K^A6+%&NDsBZi zSyhSIIOdgxL&P+g4{@Db7?HgKfea;SGGzr6c;4=Ltk7(rfbRwgLlpwue4ojCUr~)s zYZBpc0PV_GKqQl+2%k#^$}WJaxQqTZ9<2=rYxy1KY=?RV9thOQgwvIqXH@jE-mVLb zBg{^U2_#c^TX9`{fk8+bl++|vA>l;?GAHR$%^Bqhj9K8O5{v=#G_oYBe1<F^4ZN1$^biEUs4%6?T>66pkksyAuYf#M@l zOENb$zOLykIzb*TRa+%x_i=_nk|pS_7(!-65#cdH0f+QB$Un$0hH6b?Ix*iV`9x{0 zpG8L4%9A#GNLwu#5kPt7~GiP z$oTG#vLMo2@0i-jK*nMuSu~n!g`lhMIBjCrr2Pa&5>pMfB-;MV!5}5tgUHhf$rA}Bob(UbczUQRCe5>1+xGsyN)g%rpC9Z8gJiZZQ2|{krOuI22Lm7qu+h`bV z{=^icX%ypnj}j5tlxZ@6181S?Gy}bh#;~|V!~)@VroM1tH)eGMZI6e@QY~My`OKI@ zE^x!(eyg<|wTP>_M4F_JLYoaIJORKzK2bxWpcdpz(yoRJhlPY3K)4AuH6YHkxpLuf zIS9TKF%FqH< zJWze|vOGK^>-Yziwhh`)mmAD}6S5?JBHJly1 z|K16N9l*>^I*hljTgsaa&~+2{2oVH9lMx^rH8N6wiES>{3Iz`MAOf`!D-3rF+aHZZ zfm!T=zOLNv2rZiZ3*e?fO08lwd}%7XClRI-jL3V{e(%iJq@oeX9b7H#va9*(t=^o zHB`u!W8+~B7X{ls3_kcd8XCy79&BiQ+R4j3Vq|1JygzsHeijOvuxO-q#Q1hgT6AO3 z*wkod43yq+`F8)y?^1m!zFJEGND;L&t;b^ewZmUXRn4b36iStstKJlt;dPVP0z}&& z>2VKfp&~R-)o?&sFA7a!4|;@2LkB_{a;zY2a0%imPpG1Wmi!1c4=rhNi9dY1l?alDvrY{h7x;Q5`i!( zCAptE65;<9Y+5CyEmg*-iZNE;>2!oQ1g4fc*D#!Grf4`zRI1i61@QP`jk>O#w+y5|x6p3rwMHrN_v-C6I@e^2|+ou3MP z>J{#s(?C}cBX0*ONYREq98(C9(>!|gXds40@8x(hOdM%e2M(1D1aQb=*^Qrng=m3T z83gLckVBwkgT2hMt)da312ncV!sO`#BPzEkQuMT?C=e)PKa(!9l3q*c@d5>oaaa;d!p(75sY18l9oD_AIVr%&uch9(5llNKgTR&>KHWuX|5&EB=g0R7N{bp(yI zJQGc%IW)!@Mvg-%i5*whOR+7KlD@t{>h~|7j=ZXktH@g9E%~3g<=bR0PtpmC3D(~lST{q_Bwmv|3omGg?sMvM9nUhq6U zNNTXX$rwHO%qV3<#=|I)`B`JvK`GB9iigT;jn)8TFANLxYwbKqEaL7F^d7t~FE6*4 ze{(PGhqQ{CL;;bJ{c)(!763zqbLAVOi{XdAC#2Zl@@f(fK;nKlt*xX)iz9s>S>N0h zS#;n#8D4;>spS9~A}ixDm2-HaJBBzE($$>FND@cuI50<3BwW1K7_%0FWDW!VU=AZ7 z0&Kw8O;Gy%5LZP%`^e!c@|Kww%~y7UC&ZL8ek$SJN53nCvqY>hlb!!?n1VIi(L78> zX_BN2wehOTIseXu3Z{;#0XnDBV5LQL20Z4YV-ns2xiJ~?y|35w`S6_a|CpOP_u8M3 z>HdH-9vKlgkQiexPa`GuttZn}EzZW>8I-qnT6&fU!WE3K#N9)sVk0EhJfK-bCKexG+fvvagUxC6|QZ%s) zB%fs$RQGhM1AiW+1z2~ltrd$L$M#tY-|cgprlTZ<(26*iNWYr%NZfhL&U`~oSXHSO ze`Ga8%`BpbL6O^x>ulPx#Y5&vnsyusS>%MzAsr><{RcGlSf{_rBgKBgiUGec`6-po zZ3+p*6`envhU!x0x%92%(N4+i#RTQAy&I{h^(vK9Ru*vC4;`hJ19;OT-3v@Q% zSM0V~8vRG(CCqml^X1NTWPU__44r%bF#W(B6v$AWupOk4?g)N>8{now574j%d7)Ag zF}i0R<$lY$oWm*(>Rr40Cu{b*8Tn%uF-(m~l@nEdN)z{r{YQB(K0D$f+Y! zRKGFb^*0L8pMU)~{^;+S!#jWduS0qHy}SJr7waGV*Z#K8v#?J>L5YFnuEsrj4Wx4t zHz5i0t$BGa2%sDc0fkCnk|~tqkD!4&@q{OOf-Yv#wa`ZbJAx8rZ7nHu_SD4ZtK08= z%Oi!8MPMh;e@cb{N6jeSLi7Xj+ub}ZC&l~25L@5{C#uqJyWs`jbQrzpsDi_xf^RPT z9;Q{QpZQcIN|b|nr@7ve0lSD9O#5GYn%F%Uo2p4VqmkLy4op%0ZKGRVpVHfQFgA9 z7imV@e!q=VqT3yFM49N$^dLeGz`78jE1)Un5=KRkc1o15;(NiPiIHYhNLOxf+xZkQ zy3a6rnPV`$oebh2Lxl^c^3%+kH&7iX^Bp5mH+KQk1?`+t&Q)qgJY z7Dg6AG7_J!l{G>B5P2oF9Ox*G35yCl*(D;;t)9^<1s~QXvjcpcj(TF*LQM` z*kQ5^Hx#_yrk;KiyL3&qg5$(70s|Y=q*&@PqzpDn<;iPfE5KPbIMC0K3*w>t&u-1S z(7Yk6vE2|)fC|Qa3QF;B)$KnOic85v>_w`W8GvQ`=j`)X5_@T!ODU#RJcB)jvkl34 z25?q3hy2mNuip$D16XnbNg_Rh3yD-#I>o7=LvdHs)kHR#!NdJMg z$AVjiFOg`Qssx?!|JB)*hecVh?W5T#%QTrn6qABs3|C+fFcFdv7z9xel~t2Xc2Ph? z1U)W=&VURP2&kkCn+OVnfT*B?gDj>Xiz5=rcuY2RlwFYTeg?n#>eT7#>pK6`QJ8t( z-|{^7b1%Vt#ozgba~JvIwOS9={vTLawy0%r(!>cGu|abyGjel(u$+a-vQK=>P6~_> z-8Rfd*X7n*9#lxLW^&_O3cr^;YL_i|2mkR81dqw=rdQ(`JB_Y- z_4nAGKM3l(JuizGDyeNlZchUI=Nb}$2Zma68_qqh%IC$vp7Yn{cXG1%Oe|x-?DscG zKv57@@P0BmY+oqTinvEyBl~od)3B(3LlY$VRf1qC{a;EsiB)9pu~O<%*!-{7(1~jM z4s=d{7Zr4pq?Y`q{7+?*;O%X+2)c#j*jC}{Gh|B1f%O3&``;y8wvzA@e$dbhcMdV^ zYzp(pHh-XWU^&W=(bl%n6L{e9e&P5sX%)OSx1)aHe5!2ZS;}Kg4GosXn~X#}FjZtA za}cTN3Vbfe6Yj@71J092lw}e zo~l}ZoJ?OD2d99{M+PQyV#qS-u~If7Lhvs>NEz}9_yX)H*i)n-6A<7!MY(|KhG+Bm zoOT@9W@R8^JsArAuA_Q|fd3bl4xW~y18^Rv0Cp@sR#3JjOJ)z)fY}jeZJ3vv^jtg2 zIv+>dC;HpI#9sB-$wySMdQac7>23-t|Fu*SMq7UoQ5I<&G9aqfG5j-Jf#E;JCEv2$ zwZND-6i#Nhjm8WHCMYIWFqAmVb!u*yF9TlhE>hA{8Yi)^Ivz0Phw) zkI1Qq1h=o#&TH>*+*;i-0~91rlG{eocd6N8_)gmACU1rXOQvObj{MMr8xJIK!kHBI z)j(GUhBHqvb0S}b-qvRk7{QpM7alL#EZJM1rtO|)05Zs&`DT1Nh$o-JFO)#GE4zzeeSIb-2_-;2|P!ab*}ScX;H#FcX$ zb{b_{wu?ZP0q#Mz@-*h6ZX4&jHyp*#p4aUxeff#V@r6koCmf>6UX?LvB$ejC3YNeK z?F44Z)PxVUF0V5(ORQ#|ylRe$;xoKKxo}o#G~@%!Uo9S-hk^gEy4lsHnC#e`&UOHL zvT3w&Q(~(zn8|V$iAD?aeI&Jjg@nLabq%djKUFJDY*6lGjZzse0CDJIr_#}$faER! z5D3t9E|krzMZY8zMvO4_wGJw=qt)5%t|OT`)9>+OuE9LK`GHCI(**nkZK;;xp+_nU zxGrxqRuszCwpT_Gj8sR*C{l&Dg4yeE!COB0MsJi4aUGuFIfWDM-p zG-vIe{`4Jo730&s4wc$e|P5ao9&$-&I#defZ(euxR<{y)>PH-Hf}>9Igzu zAMqG68NPmtWk@zW2w1wLG%eZ};IO8W&H(#I6bS00*IdB1uvq0m&=M%%oO&WIb5r%l$%cD?h2r)vHiWL!OVc20S*Al4mI_3(`T^e zl30(|tu~!Ar@4UkNug}jj}+tT(2?KDNQEi>O{wfyBo{_(w(UdhM;3R|A%W@#YZOc+ z%E#gpy4=#Os=3yUk+Kivp*P+&?yU8#+^aC1O6qS<9V zNm60Pr?|;>wt4sz9I$jnsB?f*A6pY;obTHX>ySRoB`H(3Zfiq$$Whsl7fdk$V&593 zcfMA2>Bd4|dyDJ#7`Lj7J~3lFWxE;FS8N{1S^fIeC_;YInH-6jp`@`1hVh*hpB#)- zd4#+~_+=>`AxdOZqZipoWMr5TTN@M*3gj4P=(ZLImXD~NHhDq5;$W_UvXB3P{N;Ql z%nq(l&G4;G%70e%L}g5-(s$>pX;o5LCU}=H{JeuL+>2k{|LTPks8&RXMH4_4?5L`N zrlc5-Jpby-(BotR_G~-pIe31G_@O4;AX!vnQW!T~qE_KRzbR`4++ETOOfwoe|E7>7 zZ_%;WZDX$l@+T21Btvj;j8U7KT7*xXV~{yEk}@W`FkFnyIi+p5si+s>6P@6@3_lwi zEpyyptt6@V8A-H_I4gCK*>lk;H==n1O0`{T%kd&r)Wt<)o(|s);!+YA(gh4Kd0SvC zxlve_4eT!Se4X#@ctisPWXyk&nzSlQ85JTl5aX(jB=Cod zKzsq)JJu%hEPC$IXd^g%!`2v-4w`jx)_05XAt}oUKcNxKAT&>4ykf`Y*jfG7PK0&n zja+4$Y84!n;erCD8QD-`&XMNajcyFz21QNz{o7w+AFe;=vQXW@fO1=quLyf4{8|_) zXI%CNmHaW@Wo@k3nZyQB1yE_DQmw0V=t<-zBqw^74X~1y5-{| zH^>74(h67=EOcLnN6fX3OF!s+S=-@z?xKi8SYe;fi9trDu)u~4E)hE-cd$dg#0w-~ zb3A4gp=!%ids@X327IF^?8dx_Pw^Bge?-?6aV39a%|(@_B5#m zub0U|Uu3EA?CH}c-0MP<`RldSmYVB=M#h;{_ml^l3UWcQvuixxmT^tLA16b);F8lK z93`+*h{!RPRLgsMFf@s+4eIwHOW_o81l|=^BBj{2jXc&Hk5T;DJhOhheD}yULD+re zJ%Bf22WLJ#H+WuwgYu*03`Iq6u>8s`bipiVcHk6;LzqL}mV+>vMeJ{9C!f#Xw~zcJ zUJpv~D>ZVQ$|+_MCmaqLIGi|cXxWb1o=!QiRsk`fjwkP)le-?zgzgAfu)jbVAep+Z;wDhRB`Kbog@L;@6AV_4PNLI zXcC$*Fu}Ek;KEY{qKWr|d+sm6$J_DG(padErh_U3%No)w5f5H2U%7Ks^xS>k-9d_X zv0$2$j;p0dx6%yTvNO^1@=f2@} zYh)?A^ZwqG; zT^MH*9zR)cKxzY3$OR00KD*@Xflo*&*%p=_f$;q$_kJM9jd*a-PT-HdV|k31doXX~ z*-fVbrtXdUy1w?s0Np+vLH&+~Lys7uuHy>Q@8JT3B}BrrEd{#p?hxJh`n>&XzUS*CRa6UZ%~9nLdUSjEZ!RA?yxvY?Or}%hQu} zyXxmI3RQ)0A#v-pkWxHxO+%|B#WSEa0X6P-1ZDiV&Eh#RtN1Y9gt{pyB+sAyVd|x0 zdDhFgeuTdxJ^>c~_q+Q&3|gK5AVF&JeXz2Q$Mu>=p!Ft{9S@0!jotfv( zEp|5=zfL(>o&`>%BQuH!zsFEOo{vfMO4pGDCN_&OD8><#e?04m zq@$S1xc)w#l;X^Pv6l%?(uuPXChKhZ6uL2Lfk3*&vZnkVoQYroTY+6|o>*`dNx&F# z;J104W?-A6Q^n_YLROnsb!m?#OOtYyu&@xL?7I5Q<||$)@To;MO*$@}1iAs$PgKv)Fp|5MxSlHEOJoxU4 z3`CB>+v;wC*IkT2LG=QfWuBF6pm8v`eF`fLZ~j;)D;$JW{KHig|G&5`6+1EyWg$5k z=M?Z55Dq||#gEh6XEk`>4C+ao6HV8g-51QCKmRUH z3NlEY`VC#@QMM8ZTPq6OFCn>c9~Cb}55lpJ)OIiSBFIC@rBEy(5lwYSuZf;^(PHQXV2R3dcB#ED&M1 z{@XDz()hP@1;#nd4lz#|L3X+|$uJWs^|h{-zWO#L`GVTN5Arz*gIpyDs0iYku95HBmc&RL;i2kq2C@$N2TCzM1iNrtr`E z^h3?c1tf)O^#@@U7uuf}B3$MEmZAWl_g*&+e@qp-pkX5M>_w$@Z}&uS-*<%m48;oW zN-W2mY`=?O<)B=rY)n+(xPNJT+%|a0MX?Q(#Ks}l^zig@OR4UgVHIVM`Udayk3hdshXaDGAEOx*VC+V<2n7T~{RJm%x#?>mSo=3L3XUnM(p{$YG&-p(h44C$`rIlAii#G)t)5Q4vAfURP3*V%eqK zI>R;ZUgpj+`2SwrujQpM4^D|Om3IU3SQ_G5--xod*+%XQ#J;;t>$L@VVXO9YMOBnV zh>0Y=n|MON9iGfqE=7_WqXK}_0&>eJr~njc zY2lrvoc+JI{ZhMKC5sY5un4Hog1Q?MXpM#34mU?~h-0+DMNj*?2X;^KvAt%b&Tn1= z^`r1Jv1H1PW37vwi&nU@45Xp_ON$*G+qot+TeFfWj9q>(EuH1)>EhScT%G1TzcEA=l~RmK?rTs?R2<+m~KSQIK+HPc^F^oSk~az9bC*2z}nk zsak$v(B}%2G6a{c;U7n_t@{nm>&HoDL*baTQGz%wCFsr!wr&^r?ZJn)TqH*_R{K0O z;U^@_#b4UEART3!{e}V82WMw|^bw|pBx8gS5`aQHrU(!%R!5AB-^rRjtgO$m3<<_L z_xov%ncir{VcR?F(=p{OUQa^%RB&&W52mPCNS+$52r zhhy8|P6$@Yn)M9lztCx>*>Bn(a Mt~SXv-u$os0qAI;xBvhE literal 0 HcmV?d00001