commit 2e46747ba9698b65f1bd28e7b25a78cf4d43a468
Author: 17860779768 <3219079380@qq.com>
Date: Mon Aug 25 16:33:58 2025 +0800
视觉修改
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1ff0c42
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9491a2f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,363 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Oo]ut/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
\ No newline at end of file
diff --git a/Check.Main/Camera/CameraManager.cs b/Check.Main/Camera/CameraManager.cs
new file mode 100644
index 0000000..3762048
--- /dev/null
+++ b/Check.Main/Camera/CameraManager.cs
@@ -0,0 +1,838 @@
+using Check.Main.Common;
+using Check.Main.Infer;
+using Check.Main.Result;
+using Check.Main.UI;
+using OpenCvSharp;
+using SkiaSharp;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Text.Json.Serialization;
+using System.Threading.Tasks;
+using System.Timers;
+using System.Windows.Forms;
+
+namespace Check.Main.Camera
+{
+ ///
+ /// 静态全局相机管理器,负责所有相机的生命周期、配置应用和多相机同步
+ ///
+ public static class CameraManager
+ {
+ // 活动的相机实例字典,键为相机名称
+ public static Dictionary ActiveCameras { get; } = new Dictionary();
+
+ // 相机对应的图像显示窗口字典
+ //public static Dictionary CameraDisplays { get; } = new Dictionary();
+
+ public static Dictionary OriginalImageDisplays { get; } = new Dictionary();
+ public static Dictionary ResultImageDisplays { get; } = new Dictionary();
+
+ // --- 多相机同步逻辑 ---
+ // 产品检测队列
+ private static readonly Queue ProductQueue = new Queue();
+ // 队列锁,保证线程安全
+ private static readonly object QueueLock = new object();
+ // 当前启用的相机数量,用于判断产品是否检测完毕
+ private static int EnabledCameraCount = 0;
+
+ //public static event EventHandler OnDetectionCompleted;
+ // public static bool IsDetectionRunning { get; private set; } = false;
+
+ // 产品ID计数器
+ private static long _productCounter = 0;
+ // 用于同步计数器访问的锁,虽然long的自增是原子操作,但为清晰和未来扩展,使用锁是好习惯
+ private static readonly object _counterLock = new object();
+
+ // --- 新增:硬触发模拟器 ---
+ private static readonly System.Timers.Timer _hardwareTriggerSimulator;
+
+ ///
+ /// 获取或设置模拟硬触发的间隔时间(毫秒)。
+ ///
+ public static double TriggerInterval { get; set; } = 1000; // 默认1秒触发一次
+
+ ///
+ /// 获取一个值,该值指示硬件触发模拟器当前是否正在运行。
+ ///
+ public static bool IsHardwareTriggerSimulating { get; private set; } = false;
+
+ ///
+ /// 静态构造函数,用于一次性初始化静态资源。
+ ///
+ static CameraManager()
+ {
+ //初始化硬触发模拟器
+ _hardwareTriggerSimulator = new System.Timers.Timer();
+ _hardwareTriggerSimulator.Elapsed += OnHardwareTriggerTimerElapsed;
+ _hardwareTriggerSimulator.AutoReset = true; // 确保定时器持续触发
+ _hardwareTriggerSimulator.Enabled = false; // 默认不启动
+ }
+
+
+ //// 事件:用于向UI发送日志消息
+ //public static event Action OnLogMessage;
+ //// 用于写入日志文件的 StreamWriter
+ //private static StreamWriter _logFileWriter;
+
+ ////私有的、静态的、只读的对象,专门用作线程同步的“锁”。
+ //private static readonly object _logLock = new object();
+
+ ///
+ /// 初始化文件日志记录器。应在程序启动时调用一次。
+ ///
+ //public static void InitializeLogger()
+ //{
+ // try
+ // {
+ // string logDirectory = Path.Combine(Application.StartupPath, "Logs");
+ // Directory.CreateDirectory(logDirectory); // 确保Logs文件夹存在
+
+ // string logFileName = $"Log_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.txt";
+ // string logFilePath = Path.Combine(logDirectory, logFileName);
+
+ // // 创建StreamWriter,设置为追加模式和自动刷新
+ // _logFileWriter = new StreamWriter(logFilePath, append: true, encoding: System.Text.Encoding.UTF8)
+ // {
+ // AutoFlush = true
+ // };
+
+ // Log("文件日志记录器已初始化。");
+ // }
+ // catch (Exception ex)
+ // {
+ // // 如果文件日志初始化失败,在UI上报告错误
+ // OnLogMessage?.Invoke($"[CRITICAL] 文件日志初始化失败: {ex.Message}");
+ // }
+ //}
+
+ ///
+ /// 【新增】一个完整的业务流程方法:
+ /// 1. 根据配置初始化所有相机并显示它们的窗口。
+ /// 2. 在所有窗口都显示后,命令所有相机开始采集。
+ /// 这个方法是响应“开启设备”或“应用配置并启动”按钮的理想入口点。
+ ///
+ /// 要应用的相机配置列表。
+ /// 主窗体,用于停靠显示窗口。
+ //public static void ApplyConfigurationAndStartGrabbing(List settingsList, FrmMain mainForm)
+ //{
+ // ThreadSafeLogger.Log("开始执行“开启设备”流程...");
+
+ // // 步骤 1: 初始化所有相机和UI窗口
+ // // Initialize 方法会负责 Shutdown 旧实例、创建新实例、打开硬件、显示窗口等。
+ // // 因为 Initialize 方法中的 displayForm.Show() 是非阻塞的,它会立即返回,
+ // // 窗体的创建和显示过程会被调度到UI线程的消息队列中。
+ // Initialize(settingsList, mainForm);
+
+ // // 检查是否有任何相机成功初始化
+ // if (ActiveCameras.Count == 0)
+ // {
+ // ThreadSafeLogger.Log("“开启设备”流程中止,因为没有相机被成功初始化。");
+ // return;
+ // }
+
+ // // 步骤 2: 在 Initialize 完成后(意味着所有窗口都已创建并 Show),开始采集
+ // // 这个调用会紧接着 Initialize 执行,此时窗体可能还在绘制过程中,但这没关系。
+ // // StartAll() 会启动后台线程开始拉取图像,一旦图像到达,就会通过事件推送到已经存在的窗体上。
+ // ThreadSafeLogger.Log("所有相机窗口已创建,现在开始采集图像...");
+ // StartAll();
+
+ // ThreadSafeLogger.Log("“开启设备”流程已完成。相机正在采集中。");
+ //}
+
+ /////
+ ///// 根据配置列表初始化或更新所有相机
+ /////
+ //public static void Initialize(List settingsList, FrmMain mainForm)
+ //{
+
+ // // 先停止并释放所有旧的相机
+ // Shutdown();
+ // ThreadSafeLogger.Log("开始应用新的相机配置...");
+
+ // EnabledCameraCount = settingsList.Count(s => s.IsEnabled);
+ // if (EnabledCameraCount == 0)
+ // {
+ // ThreadSafeLogger.Log("没有启用的相机。");
+ // return;
+ // }
+
+ // var deviceList = new HikvisionCamera().FindDevices();
+ // if (deviceList.Count == 0)
+ // {
+ // ThreadSafeLogger.Log("错误:未找到任何相机设备!");
+ // return;
+ // }
+
+ // int deviceIndex = 0;
+ // foreach (var setting in settingsList)
+ // {
+ // if (!setting.IsEnabled) continue;
+
+ // if (deviceIndex >= deviceList.Count)
+ // {
+ // ThreadSafeLogger.Log($"警告:相机配置'{setting.Name}'无法分配物理设备,因为设备数量不足。");
+ // continue;
+ // }
+
+ // // --- 创建相机实例 ---
+ // var cam = new HikvisionCamera { Name = setting.Name };
+ // cam.TriggerMode = setting.TriggerMode;
+ // if (!cam.Open(setting))
+ // {
+ // ThreadSafeLogger.Log($"错误:打开相机'{setting.Name}'失败。");
+ // cam.Dispose();
+ // continue;
+ // }
+ // // --- 设置触发模式 ---
+ // switch (setting.TriggerMode)
+ // {
+ // case TriggerModeType.Continuous:
+ // cam.SetContinuousMode();
+ // break;
+ // case TriggerModeType.Software:
+ // cam.SetTriggerMode(true);
+ // break;
+ // case TriggerModeType.Hardware:
+ // cam.SetTriggerMode(false);
+ // break;
+ // }
+
+ // // --- 订阅事件 ---
+ // cam.ImageAcquired += OnCameraImageAcquired;
+ // cam.CameraMessage += (sender, msg, err) => ThreadSafeLogger.Log($"{(sender as HikvisionCamera).Name}: {msg}");
+
+ // // --- 创建显示窗口 ---
+ // var displayForm = new FormImageDisplay { Text = setting.Name, CameraName = setting.Name };
+ // displayForm.OnDisplayEvent += ThreadSafeLogger.Log;
+ // displayForm.Show(mainForm.MainDockPanel, WeifenLuo.WinFormsUI.Docking.DockState.Document);
+
+
+ // ActiveCameras.Add(setting.Name, cam);
+ // CameraDisplays.Add(setting.Name, displayForm);
+ // mainForm.AddCameraToStatusStrip(setting.Name);
+ // ThreadSafeLogger.Log($"相机'{setting.Name}'初始化成功,分配到物理设备 {deviceIndex}。");
+ // deviceIndex++;
+ // }
+ //}
+
+
+ ///
+ /// 准备所有相机硬件、UI窗口和后台处理器,但不开始采集。
+ /// 这是“启动设备”的第一阶段。
+ ///
+ public static void PrepareAll(ProcessConfig config, FrmMain mainForm)
+ {
+ // 1. 清理旧资源和UI
+ mainForm.ClearStatusStrip();
+ Shutdown();
+ ThreadSafeLogger.Log("开始准备设备和模型...");
+
+ // 2. 初始化检测协调器和AI模型
+ // 注意:YoloModelManager 的 Initialize 现在也应在这里被调用,以确保逻辑集中
+ YoloModelManager.Initialize(config.ModelSettings);
+ DetectionCoordinator.Initialize(config.CameraSettings, config.ModelSettings);
+
+ // 3. 创建相机硬件实例和UI窗口
+ var deviceList = new HikvisionCamera().FindDevices();
+ if (deviceList.Count == 0)
+ {
+ ThreadSafeLogger.Log("错误:未找到任何相机设备!");
+ return;
+ }
+
+ foreach (var setting in config.CameraSettings.Where(s => s.IsEnabled))
+ {
+ var cam = new HikvisionCamera { Name = setting.Name, CameraIndex = setting.CameraIndex };
+ cam.TriggerMode = setting.TriggerMode;
+ if (!cam.Open(setting))
+ {
+ ThreadSafeLogger.Log($"错误:打开相机'{setting.Name}'失败。");
+ cam.Dispose();
+ continue;
+ }
+ // --- 设置触发模式 ---
+ switch (setting.TriggerMode)
+ {
+ case TriggerModeType.Continuous:
+ cam.SetContinuousMode();
+ break;
+ case TriggerModeType.Software:
+ cam.SetTriggerMode(true);
+ break;
+ case TriggerModeType.Hardware:
+ cam.SetTriggerMode(false);
+ break;
+ }
+
+ // --- 订阅事件 ---
+ cam.ImageAcquired += OnCameraImageAcquired;
+ var processor = DetectionCoordinator.GetProcessor(cam.CameraIndex);
+ if (processor != null) { processor.OnProcessingCompleted += Processor_OnProcessingCompleted; }
+
+ // --- 创建【但不显示】图像的UI窗口 ---
+ var originalDisplay = new FormImageDisplay { Text = $"{setting.Name} - 原图", CameraName = setting.Name };
+ var resultDisplay = new FormImageDisplay { Text = $"{setting.Name} - 结果", CameraName = setting.Name };
+ originalDisplay.Show(mainForm.MainDockPanel, WeifenLuo.WinFormsUI.Docking.DockState.Document);
+ resultDisplay.Show(mainForm.MainDockPanel, WeifenLuo.WinFormsUI.Docking.DockState.Document);
+
+ // --- 保存引用 ---
+ ActiveCameras.Add(setting.Name, cam);
+ OriginalImageDisplays.Add(setting.Name, originalDisplay);
+ ResultImageDisplays.Add(setting.Name, resultDisplay);
+ mainForm.AddCameraToStatusStrip(setting.Name);
+ }
+ ThreadSafeLogger.Log("所有设备和模型已准备就绪。");
+ }
+
+
+ ///
+ /// 根据配置列表初始化或更新所有相机
+ ///
+ public static void Initialize(ProcessConfig config, FrmMain mainForm)
+ {
+ mainForm?.ClearStatusStrip();
+
+ // 先停止并释放所有旧的相机
+ Shutdown();
+ ThreadSafeLogger.Log("开始应用新的相机配置...");
+ // 2. 初始化新的检测协调器
+ DetectionCoordinator.Initialize(config.CameraSettings, config.ModelSettings);
+
+ var deviceList = new HikvisionCamera().FindDevices();
+ if (deviceList.Count == 0)
+ {
+ ThreadSafeLogger.Log("错误:未找到任何相机设备!");
+ return;
+ }
+ int deviceIndex = 0;
+ foreach (var device in config.ModelSettings.Where(s => s.IsEnabled))
+ {
+ if (!device.IsEnabled) continue;
+ mainForm.AddCameraToStatusStrip(device.Name);
+ }
+ foreach (var setting in config.CameraSettings.Where(s => s.IsEnabled))
+ {
+ if (!setting.IsEnabled) continue;
+
+ if (deviceIndex >= deviceList.Count)
+ {
+ ThreadSafeLogger.Log($"警告:相机配置'{setting.Name}'无法分配物理设备,因为设备数量不足。");
+ continue;
+ }
+ // --- 创建相机实例 ---
+ var cam = new HikvisionCamera { Name = setting.Name, CameraIndex = setting.CameraIndex };
+ cam.TriggerMode = setting.TriggerMode;
+ if (!cam.Open(setting))
+ {
+ ThreadSafeLogger.Log($"错误:打开相机'{setting.Name}'失败。");
+ cam.Dispose();
+ continue;
+ }
+ // --- 设置触发模式 ---
+ switch (setting.TriggerMode)
+ {
+ case TriggerModeType.Continuous:
+ cam.SetContinuousMode();
+ break;
+ case TriggerModeType.Software:
+ cam.SetTriggerMode(true);
+ break;
+ case TriggerModeType.Hardware:
+ cam.SetTriggerMode(false);
+ break;
+ }
+
+ // --- 订阅事件 ---
+ cam.ImageAcquired += OnCameraImageAcquired;
+ cam.CameraMessage += (sender, msg, err) => ThreadSafeLogger.Log($"{(sender as HikvisionCamera).Name}: {msg}");
+ ActiveCameras.Add(setting.Name, cam);
+ // --- 创建显示窗口 ---
+ var displayForm = new FormImageDisplay { Text = $"{setting.Name} - 原图", CameraName = setting.Name };
+ var checkFrm = new FormImageDisplay { Text = $"{setting.Name} - 结果", CameraName = setting.Name };
+ displayForm.OnDisplayEvent += ThreadSafeLogger.Log;
+ displayForm.Show(mainForm.MainDockPanel, WeifenLuo.WinFormsUI.Docking.DockState.Document);
+ checkFrm.Show(mainForm.MainDockPanel, WeifenLuo.WinFormsUI.Docking.DockState.Document);
+
+ OriginalImageDisplays.Add(setting.Name, displayForm);
+ ResultImageDisplays.Add(setting.Name, checkFrm);
+ mainForm.AddCameraToStatusStrip(setting.Name);
+ var processor = DetectionCoordinator.GetProcessor(cam.CameraIndex);
+ if (processor != null)
+ {
+ processor.OnProcessingCompleted += Processor_OnProcessingCompleted;
+ }
+ ThreadSafeLogger.Log($"相机'{setting.Name}'初始化成功,分配到物理设备 {deviceIndex}。");
+ deviceIndex++;
+ }
+ }
+
+ ///
+ /// 启动硬件触发模拟器。
+ ///
+ public static void StartHardwareTriggerSimulator()
+ {
+ if (IsHardwareTriggerSimulating) return;
+
+ _hardwareTriggerSimulator.Interval = TriggerInterval;
+ _hardwareTriggerSimulator.Start();
+ IsHardwareTriggerSimulating = true;
+ ThreadSafeLogger.Log($"硬件触发模拟器已启动,触发间隔: {TriggerInterval} ms。");
+ }
+
+ ///
+ /// 停止硬件触发模拟器。
+ ///
+ public static void StopHardwareTriggerSimulator()
+ {
+ if (!IsHardwareTriggerSimulating) return;
+
+ _hardwareTriggerSimulator.Stop();
+ IsHardwareTriggerSimulating = false;
+ ThreadSafeLogger.Log("硬件触发模拟器已停止。");
+ }
+
+ ///
+ /// 定时器触发事件。
+ ///
+ private static void OnHardwareTriggerTimerElapsed(object sender, ElapsedEventArgs e)
+ {
+ // 遍历所有活动的相机
+ foreach (var cam in ActiveCameras.Values)
+ {
+ // 仅对配置为“硬件触发”模式的相机执行操作
+ // 重要:我们使用软触发命令(SoftwareTrigger)来“模拟”一个外部硬件信号的到达。
+ if (cam.TriggerMode == TriggerModeType.Software && cam.IsGrabbing)
+ {
+ // ThreadSafeLogger.Log($"模拟硬触发信号,触发相机: {cam.Name}"); // 如果需要详细日志可以取消注释
+ cam.SoftwareTrigger();
+ }
+ }
+ }
+
+
+ ///
+ /// 所有启用的相机开始采集
+ ///
+ public static void StartAll()
+ {
+ foreach (var cam in ActiveCameras.Values)
+ {
+ cam.StartGrabbing();
+ }
+ ThreadSafeLogger.Log("所有相机已开始采集。");
+ }
+
+ //public static void StartDetection()
+ //{
+ // if (!IsDetectionRunning)
+ // {
+ // IsDetectionRunning = true;
+ // ThreadSafeLogger.Log("检测已启动,开始统计数据。");
+ // }
+ //}
+ //public static void StopDetection()
+ //{
+ // if (IsDetectionRunning)
+ // {
+ // IsDetectionRunning = false;
+ // ThreadSafeLogger.Log("检测已停止。");
+ // }
+ //}
+
+ ///
+ /// 所有启用的相机停止采集
+ ///
+ public static void StopAll()
+ {
+ foreach (var cam in ActiveCameras.Values)
+ {
+ cam.StopGrabbing();
+ }
+ ThreadSafeLogger.Log("所有相机已停止采集。");
+ }
+
+ /////
+ ///// 停止并释放所有相机资源
+ /////
+ //public static void Shutdown()
+ //{
+ // // --- 新增:确保在关闭时停止模拟器并释放资源 ---
+ // StopHardwareTriggerSimulator();
+ // //_hardwareTriggerSimulator?.Dispose();
+
+ // StopAll();
+ // foreach (var cam in ActiveCameras.Values)
+ // {
+ // cam.Dispose();
+ // }
+ // foreach (var display in CameraDisplays.Values)
+ // {
+ // display.Close();
+ // }
+ // lock (QueueLock)
+ // {
+ // while (ProductQueue.Count > 0)
+ // {
+ // ProductQueue.Dequeue()?.Dispose();
+ // }
+ // }
+ // ResetProductCounter();
+ // ActiveCameras.Clear();
+ // CameraDisplays.Clear();
+ // ThreadSafeLogger.Log("正在关闭文件日志记录器...");
+ // ThreadSafeLogger.Log("所有相机资源已释放。");
+
+ //}
+
+ // Shutdown 方法也简化
+ public static void Shutdown()
+ {
+ // 1. 停止硬件和模拟器
+ StopAll();
+ StopHardwareTriggerSimulator();
+ // 2. 关闭相机实例和窗口
+ foreach (var cam in ActiveCameras.Values) { cam.Dispose(); }
+ foreach (var display in OriginalImageDisplays.Values) { display.Close(); }
+ foreach (var display in ResultImageDisplays.Values) { display.Close(); }
+ ActiveCameras.Clear();
+ OriginalImageDisplays.Clear();
+ ResultImageDisplays.Clear();
+ // 3. 关闭检测协调器,它会负责清理所有后台线程和队列
+ DetectionCoordinator.Shutdown();
+
+ YoloModelManager.Shutdown();
+
+ ThreadSafeLogger.Log("所有相机及协调器资源已释放。");
+ }
+
+ ///
+ /// 重置产品计数器的公共方法
+ ///
+ public static void ResetProductCounter()
+ {
+ lock (_counterLock)
+ {
+ _productCounter = 0;
+ }
+ ThreadSafeLogger.Log("产品计数器已重置。");
+ }
+
+ ///
+ /// 接收到相机图像时的核心处理逻辑
+ ///
+ //private static void OnCameraImageAcquired(HikvisionCamera sender, Bitmap bmp)
+ //{
+
+ // Bitmap bmpForDisplay =null;
+ // Bitmap bmpForQueue = null;
+ // try
+ // {
+ // bmpForDisplay?.Dispose();
+ // bmpForQueue?.Dispose();
+ // // 1. 为“显示”和“处理队列”创建独立的深克隆副本
+ // bmpForDisplay = DeepCloneBitmap(bmp, "Display");
+ // bmpForQueue = DeepCloneBitmap(bmp, "Queue");
+ // }
+ // finally
+ // {
+ // // 【关键】无论克隆成功与否,都必须立即释放事件传递过来的原始bmp。
+ // // 这是保证没有泄漏的第一道防线。
+ // bmp?.Dispose();
+ // }
+ // // --- 现在我们使用完全独立的副本进行后续操作 ---
+
+ // // 4. 将显示副本传递给UI
+ // if (bmpForDisplay != null && CameraDisplays.TryGetValue(sender.Name, out var display))
+ // {
+ // display.UpdateImage(bmpForDisplay);
+ // }
+ // else
+ // {
+ // // 如果不需要显示,或者显示失败,必须释放掉为它创建的副本
+ // bmpForDisplay?.Dispose();
+ // }
+ // // 5. 将队列副本添加到产品中
+ // if (bmpForQueue != null)
+ // {
+ // lock (QueueLock)
+ // {
+ // ProductResult currentProduct;
+ // bool isNewProductCycle = ProductQueue.Count == 0 || ProductQueue.Last().CapturedImages.ContainsKey(sender.Name);
+ // if (isNewProductCycle)
+ // {
+ // if (ProductQueue.Count > 0 && !ProductQueue.Peek().IsComplete(EnabledCameraCount))
+ // {
+ // var orphanedProduct = ProductQueue.Dequeue(); // 从队列头部移除这个不完整的产品
+ // ThreadSafeLogger.Log($"[警告] 产品 #{orphanedProduct.ProductID} 未能集齐所有相机图像而被丢弃,以防止内存泄漏。");
+ // orphanedProduct.Dispose(); // 确保释放其占用的所有资源
+ // }
+ // long newProductId;
+ // lock (_counterLock)
+ // {
+ // _productCounter++;
+ // newProductId = _productCounter;
+ // }
+ // currentProduct = new ProductResult(newProductId);
+ // ProductQueue.Enqueue(currentProduct);
+ // }
+ // else
+ // {
+ // currentProduct = ProductQueue.Last();
+ // }
+
+ // currentProduct.AddImage(sender.Name, bmpForQueue); // bmpForQueue的所有权转移给了产品队列
+
+ // while (ProductQueue.Count > 0 && ProductQueue.Peek().IsComplete(EnabledCameraCount))
+ // {
+ // // Peek() 查看队头元素但不移除它
+ // var finishedProduct = ProductQueue.Dequeue(); // Dequeue() 移除队头元素
+ // ThreadSafeLogger.Log($"产品 #{finishedProduct.ProductID} 已完整,出队处理。");
+
+ // // --- 这是您已有的处理逻辑 ---
+ // bool isOk = new Random().NextDouble() > 0.1;
+ // string finalResult = isOk ? "OK" : "NG";
+ // ThreadSafeLogger.Log($"产品 #{finishedProduct.ProductID} 检测结果: {finalResult}");
+
+ // if (IsDetectionRunning)
+ // {
+ // OnDetectionCompleted?.Invoke(null, new DetectionResultEventArgs(isOk));
+ // }
+
+ // try
+ // {
+ // // 确保完成的产品被完全释放
+ // finishedProduct.Dispose();
+ // }
+ // catch (Exception ex)
+ // {
+ // ThreadSafeLogger.Log($"[ERROR] 释放产品 #{finishedProduct.ProductID} 资源时出错: {ex.Message}");
+ // }
+ // }
+ // }
+ // }
+ //}
+
+ // 图像回调方法现在极其简单
+ private static void OnCameraImageAcquired(HikvisionCamera sender, Bitmap bmp)
+ {
+ Bitmap bmpForDisplay = null;
+ Bitmap bmpForProcessing = null;
+
+ try
+ {
+ // 1. 为“显示”和“处理”创建两个完全独立的深克隆副本
+ bmpForDisplay = DeepCloneBitmap(bmp, "Display");
+ bmpForProcessing = DeepCloneBitmap(bmp, "Processing");
+ }
+ finally
+ {
+ // 2.无论克隆成功与否,都必须立即释放事件传递过来的原始bmp,防止泄漏。
+ bmp?.Dispose();
+ }
+ // 分支 A: 将用于显示的副本发送到对应的UI窗口
+ if (bmpForDisplay != null && OriginalImageDisplays.TryGetValue(sender.Name, out var displayWindow))
+ {
+ // displayWindow.UpdateImage 会处理线程安全问题
+ displayWindow.UpdateImage(bmpForDisplay);
+ }
+ else
+ {
+ // 如果没有对应的显示窗口,或克隆失败,必须释放为显示创建的副本
+ bmpForDisplay?.Dispose();
+ }
+ // 分支 B: 将用于处理的副本发送到检测协调器的后台队列
+ if (bmpForProcessing != null)
+ {
+ // bmpForProcessing 的所有权在这里被转移给了协调器
+ DetectionCoordinator.EnqueueImage(sender.CameraIndex, bmpForProcessing);
+ }
+ //// 深度克隆图像以确保线程安全
+ //Bitmap bmpForProcessing = DeepCloneBitmap(bmp, "Processing");
+ //bmp?.Dispose(); // 立即释放原始图
+
+ //// 直接将图像和相机编号交给协调器,无需任何本地处理
+ //DetectionCoordinator.EnqueueImage(sender.CameraIndex, bmpForProcessing);
+ }
+ // 事件处理器
+ private static void Processor_OnProcessingCompleted(object sender, ProcessingCompletedEventArgs e)
+ {
+
+ // 1. 找到与此相机匹配的相机名称
+ var cameraEntry = ActiveCameras.FirstOrDefault(kvp => kvp.Value.CameraIndex == e.CameraIndex);
+ if (cameraEntry.Key == null)
+ {
+ e.Dispose(); // 如果找不到接收者,必须释放事件参数中的图像
+ return;
+ }
+ // 2. 找到此相机的结果显示窗口
+ if (ResultImageDisplays.TryGetValue(cameraEntry.Key, out var resultDisplay))
+ {
+ var bmp = ConvertSKImageToBitmap(e.ResultImage);
+ if (bmp != null)
+ {
+ // UpdateImage 会负责克隆并显示,所以这里传递 bmp 即可
+ resultDisplay.UpdateImage(bmp);
+ }
+ }
+ else
+ {
+ // 如果找到了相机但没有对应的结果窗口,也要释放图像
+ e.Dispose();
+ }
+
+ }
+
+ ///
+ /// 【将 SkiaSharp.SKImage 安全地转换为 System.Drawing.Bitmap。
+ ///
+ private static Bitmap ConvertSKImageToBitmap(SKImage skImage)
+ {
+ if (skImage == null) return null;
+
+ try
+ {
+ // SKImage -> SKBitmap -> System.Drawing.Bitmap
+ using (var skBitmap = SKBitmap.FromImage(skImage))
+ {
+ // SKBitmap.ToBitmap() 会创建一个新的 Bitmap 对象
+ return SKBitmapToGdiBitmapFast(skBitmap);
+ }
+ }
+ catch (Exception ex)
+ {
+ ThreadSafeLogger.Log($"[错误] SKImage to Bitmap 转换失败: {ex.Message}");
+ return null;
+ }
+ }
+ public static Bitmap SKBitmapToGdiBitmapFast(SKBitmap skBitmap)
+ {
+ if (skBitmap == null) throw new ArgumentNullException(nameof(skBitmap));
+ if (skBitmap.ColorType != SKColorType.Bgra8888 || skBitmap.AlphaType != SKAlphaType.Premul)
+ throw new ArgumentException("skBitmap must be Bgra8888 + Premul for the fast path.");
+
+ int w = skBitmap.Width;
+ int h = skBitmap.Height;
+
+ Bitmap bmp = new Bitmap(w, h, PixelFormat.Format32bppArgb);
+ var rect = new Rectangle(0, 0, w, h);
+ var bmpData = bmp.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
+ try
+ {
+ IntPtr srcPtr = skBitmap.GetPixels();
+ int srcRowBytes = skBitmap.RowBytes;
+ int dstRowBytes = bmpData.Stride;
+ int copyBytesPerRow = Math.Min(srcRowBytes, dstRowBytes);
+
+ byte[] row = new byte[copyBytesPerRow]; // 复用同一行缓冲区,避免每行分配
+ for (int y = 0; y < h; y++)
+ {
+ IntPtr s = IntPtr.Add(srcPtr, y * srcRowBytes);
+ IntPtr d = IntPtr.Add(bmpData.Scan0, y * dstRowBytes);
+
+ Marshal.Copy(s, row, 0, copyBytesPerRow);
+ Marshal.Copy(row, 0, d, copyBytesPerRow);
+ }
+ }
+ finally
+ {
+ bmp.UnlockBits(bmpData);
+ }
+
+ return bmp;
+ }
+ ///
+ /// 对Bitmap进行真正的深度克隆,确保内存完全独立。
+ /// 这是解决跨线程GDI+问题的最可靠方法。
+ ///
+ /// 源Bitmap对象。
+ /// 一个与源图像在内存上完全独立的全新Bitmap对象。
+ private static Bitmap DeepCloneBitmap(Bitmap source, string cloneFor)
+ {
+ if (source == null) return null;
+
+ // 创建一个新的Bitmap对象,具有与源相同的尺寸和像素格式
+ Bitmap clone = new Bitmap(source.Width, source.Height, source.PixelFormat);
+
+ // 如果有调色板,复制调色板
+ if (source.Palette.Entries.Length > 0)
+ {
+ clone.Palette = source.Palette;
+ }
+
+ // 锁定源和目标Bitmap的内存区域
+ var rect = new Rectangle(0, 0, source.Width, source.Height);
+ BitmapData sourceData = null; //source.LockBits(rect, ImageLockMode.ReadOnly, source.PixelFormat);
+ BitmapData cloneData = null;//clone.LockBits(rect, ImageLockMode.WriteOnly, clone.PixelFormat);
+
+ try
+ {
+ sourceData = source.LockBits(rect, ImageLockMode.ReadOnly, source.PixelFormat);
+ cloneData = clone.LockBits(rect, ImageLockMode.WriteOnly, clone.PixelFormat);
+ // 计算需要拷贝的字节数
+ int byteCount = Math.Abs(sourceData.Stride) * source.Height;
+ byte[] buffer = new byte[byteCount];
+
+ // 从源图像拷贝数据到字节数组
+ Marshal.Copy(sourceData.Scan0, buffer, 0, byteCount);
+
+ // 从字节数组拷贝数据到目标图像
+ Marshal.Copy(buffer, 0, cloneData.Scan0, byteCount);
+ }
+ catch (Exception ex)
+ {
+ ThreadSafeLogger.Log($"[克隆错误] 在 DeepCloneBitmap ({cloneFor}) 中发生异常: {ex.Message}");
+ // 如果发生错误,确保返回null,并且释放可能已经创建的clone对象
+ clone?.Dispose();
+ return null;
+ }
+ finally
+ {
+ // 确保即使在发生错误时也能尝试解锁
+ if (sourceData != null)
+ {
+ source.UnlockBits(sourceData);
+ }
+ if (cloneData != null)
+ {
+ clone.UnlockBits(cloneData);
+ }
+ //ThreadSafeLogger.Log($"[克隆完成] 解锁并完成克隆 ({cloneFor}).");
+ }
+
+ return clone;
+ }
+
+ // 触发日志事件的辅助方法
+ //public static void Log(string message)
+ //{
+ // string formattedMessage = $"[{DateTime.Now:HH:mm:ss.fff}] {message}";
+
+ // // 1. 触发事件,更新UI
+ // OnLogMessage?.Invoke(formattedMessage);
+
+ // // 2. 【关键修改】在写入文件前,先获取锁。
+ // // lock 语句块确保了花括号内的代码在同一时间只能被一个线程执行。
+ // // 如果另一个线程也想执行这段代码,它必须等待前一个线程执行完毕并释放锁。
+ // lock (_logLock)
+ // {
+ // try
+ // {
+ // _logFileWriter?.WriteLine(formattedMessage);
+ // }
+ // catch (Exception)
+ // {
+ // // 即使有锁,也保留try-catch以防万一(如磁盘满了等IO问题)。
+ // // 可以在这里决定是否要在UI上显示警告。
+ // }
+ // }
+ //}
+
+ }
+
+}
diff --git a/Check.Main/Camera/CameraProcessor.cs b/Check.Main/Camera/CameraProcessor.cs
new file mode 100644
index 0000000..2386223
--- /dev/null
+++ b/Check.Main/Camera/CameraProcessor.cs
@@ -0,0 +1,211 @@
+using Check.Main.Common;
+using Check.Main.Infer;
+using SkiaSharp;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Drawing.Imaging;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using YoloDotNet.Extensions;
+
+namespace Check.Main.Camera
+{
+ public class CameraProcessor : IDisposable
+ {
+ private readonly int _cameraIndex;
+ private readonly int _modeId;
+ // private readonly ModelSettings _model;
+ private readonly BlockingCollection _imageQueue = new BlockingCollection();
+ private readonly Thread _workerThread;
+ private volatile bool _isRunning = false;
+ private long _imageCounter = 0;
+ private readonly object _counterLock = new object(); // 用于线程安全地重置计数器
+
+ public event EventHandler OnProcessingCompleted;
+
+
+ public CameraProcessor(int cameraIndex, int modelId)//, ModelSettings model
+ {
+ _cameraIndex = cameraIndex;
+ _modeId = modelId;
+ //_model = model;
+ _workerThread = new Thread(ProcessQueue) { IsBackground = true, Name = $"Cam_{_cameraIndex}_Processor" };
+ }
+
+ public void Start()
+ {
+ _isRunning = true;
+ _workerThread.Start();
+ }
+
+ public void EnqueueImage(Bitmap bmp)
+ {
+ if (!_isRunning)
+ {
+ bmp?.Dispose();
+ return;
+ }
+ _imageCounter++;
+ _imageQueue.Add(new ImageData(_imageCounter, _cameraIndex, bmp));
+ }
+
+ private void ProcessQueue()
+ {
+ // 从模型管理器获取此线程专属的YOLO模型
+ var yoloModel = YoloModelManager.GetModel(_modeId);
+ if (yoloModel == null)
+ {
+ ThreadSafeLogger.Log($"[错误] 相机 #{_modeId} 无法获取对应的YOLO模型,处理线程已中止。");
+ return; // 如果没有模型,此线程无法工作
+ }
+ while (_isRunning)
+ {
+ try
+ {
+ // 阻塞式地从队列中取出图像,如果队列为空则等待
+ ImageData data = _imageQueue.Take();
+ using (data)
+ {
+ //SKImage resultSkImage = null; // 用于存储最终绘制好结果的图像
+
+ using (var skImage = ConvertBitmapToSKImage(data.Image)) // 转换图像格式并管理其生命周期
+ {
+ if (skImage == null) continue;
+ var predictions = yoloModel.RunObjectDetection(skImage);
+ // 模拟模型处理
+ //Thread.Sleep(50); // 模拟耗时
+ //bool isOk = new Random().NextDouble() > 0.1;
+ //string result = isOk ? "OK" : "NG";
+
+ string result = predictions.Any() ? "NG" : "OK";
+ ThreadSafeLogger.Log($"相机 #{_cameraIndex} 处理产品 #{data.ProductId},检测到 {predictions.Count} 个目标,结果: {result}");
+ // 将处理结果交给协调器进行组装
+ DetectionCoordinator.AssembleProduct(data, result);
+
+ if (OnProcessingCompleted != null)
+ {
+ using (var resultSkImage = skImage.Draw(predictions))
+ {
+ // 4. 触发事件,将绘制好的 resultSkImage 传递出去
+ // 所有权在这里被转移
+ OnProcessingCompleted?.Invoke(this, new ProcessingCompletedEventArgs(
+ _cameraIndex,
+ data.ProductId,
+ resultSkImage
+ ));
+ }
+ }
+ }
+
+ }
+ }
+ catch (InvalidOperationException)
+ {
+ // 当调用 Stop 时,会 CompleteAdding 队列,Take 会抛出此异常,是正常退出流程
+ break;
+ }
+ catch (Exception ex)
+ {
+ ThreadSafeLogger.Log($"[ERROR] 相机 #{_cameraIndex} 处理线程异常: {ex.Message}");
+ }
+ }
+ }
+ ///
+ /// 将 System.Drawing.Bitmap 安全地转换为 SkiaSharp.SKImage。
+ ///
+ private SKImage ConvertBitmapToSKImage(Bitmap bitmap)
+ {
+ if (bitmap == null) return null;
+ try
+ {
+ // 使用 using 确保 SKBitmap 被正确释放
+ using (var skBitmap = ToSKBitmapFast(bitmap))
+ {
+ return SKImage.FromBitmap(skBitmap);
+ }
+ }
+ catch (Exception ex)
+ {
+ ThreadSafeLogger.Log($"[错误] Bitmap to SKImage 转换失败: {ex.Message}");
+ return null;
+ }
+ }
+ public static SKBitmap ToSKBitmapFast(Bitmap bitmap)
+ {
+ // 确保是 32bppArgb(BGRA 内存布局)
+ Bitmap src = bitmap;
+ if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
+ {
+ src = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb);
+ using (Graphics g = Graphics.FromImage(src))
+ {
+ g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
+ }
+ }
+
+ var rect = new Rectangle(0, 0, src.Width, src.Height);
+ var bmpData = src.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
+ try
+ {
+ var info = new SKImageInfo(src.Width, src.Height, SKColorType.Bgra8888, SKAlphaType.Premul);
+ var skBitmap = new SKBitmap(info);
+
+ IntPtr destPtr = skBitmap.GetPixels(); // 目标内存
+ IntPtr srcRowPtr = bmpData.Scan0; // 源行首
+ int srcStride = bmpData.Stride;
+ int destRowBytes = skBitmap.RowBytes;
+ int copyBytesPerRow = Math.Min(srcStride, destRowBytes);
+
+ // 使用一次分配的缓冲区并用 Marshal.Copy 行拷贝(不分配每行)
+ byte[] row = new byte[copyBytesPerRow];
+ for (int y = 0; y < src.Height; y++)
+ {
+ IntPtr s = IntPtr.Add(bmpData.Scan0, y * srcStride);
+ IntPtr d = IntPtr.Add(destPtr, y * destRowBytes);
+
+ Marshal.Copy(s, row, 0, copyBytesPerRow);
+ Marshal.Copy(row, 0, d, copyBytesPerRow);
+ }
+
+ return skBitmap;
+ }
+ finally
+ {
+ src.UnlockBits(bmpData);
+ if (!ReferenceEquals(src, bitmap))
+ {
+ src.Dispose();
+ }
+ }
+ }
+ public void Stop()
+ {
+ _isRunning = false;
+ // 解除阻塞,让线程可以检查 _isRunning 标志并退出
+ _imageQueue.CompleteAdding();
+ _workerThread.Join(500); // 等待线程结束
+ }
+ ///
+ /// 线程安全地重置该相机的图像计数器。
+ ///
+ public void ResetCounter()
+ {
+ lock (_counterLock)
+ {
+ _imageCounter = 0;
+ }
+ }
+ // 别忘了在 DetectionCoordinator 中添加一个辅助方法来获取处理器
+
+
+ public void Dispose()
+ {
+ Stop();
+ _imageQueue.Dispose();
+ }
+ }
+
+}
diff --git a/Check.Main/Camera/CameraSettings.cs b/Check.Main/Camera/CameraSettings.cs
new file mode 100644
index 0000000..054a4f0
--- /dev/null
+++ b/Check.Main/Camera/CameraSettings.cs
@@ -0,0 +1,182 @@
+using Check.Main.Common;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing.Design;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms.Design;
+
+namespace Check.Main.Camera
+{
+ // 相机触发方式枚举
+ public enum TriggerModeType
+ {
+ [Description("连续采集")]
+ Continuous,
+ [Description("软件触发")]
+ Software,
+ [Description("硬件触发")]
+ Hardware
+ }
+ public enum CheckType
+ {
+ [Description("传统算法")]
+ Traditional,
+ [Description("深度学习")]
+ DeepLearning
+ }
+
+ ///
+ /// 相机配置信息类,用于PropertyGrid显示和编辑
+ ///
+ public class CameraSettings : INotifyPropertyChanged, ICloneable
+ {
+ // 1. 实现 INotifyPropertyChanged 接口所要求的事件
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ private int _cameraIndex = 0;
+ private string _name = "Camera-1";
+ private string _ipAddress = "192.168.1.100";
+ private string _ipDeviceAddress = "192.168.1.101";
+ private TriggerModeType _triggerMode = TriggerModeType.Continuous;
+ private bool _isEnabled = true;
+ private CheckType _checkType = CheckType.DeepLearning;
+ private int _modelID = 0;
+
+ [Category("基本信息"), DisplayName("相机编号"), Description("相机的唯一标识符,用于与模型编号对应。")]
+ public int CameraIndex
+ {
+ get => _cameraIndex;
+ set
+ {
+ if (_cameraIndex != value)
+ {
+ _cameraIndex = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+ [Category("基本信息"), DisplayName("相机名称"), Description("给相机起一个唯一的别名")]
+ public string Name
+ {
+ get => _name;
+ set
+ {
+ // 2. 在setter中检查值是否真的改变了
+ if (_name != value)
+ {
+ _name = value;
+ // 3. 如果改变了,就调用通知方法,广播“Name”属性已变更的消息
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ [Category("网络信息"), DisplayName("相机IP地址"), Description("相机的IP地址(GigE相机需要)")]
+ public string IPAddress
+ {
+ get => _ipAddress;
+ set
+ {
+ if (_ipAddress != value)
+ {
+ _ipAddress = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ [Category("网络信息"), DisplayName("上位机IP地址"), Description("相机对应的上位机的IP地址(GigE相机需要)")]
+ public string IPDeviceAddress
+ {
+ get => _ipDeviceAddress;
+ set
+ {
+ if (_ipDeviceAddress != value)
+ {
+ _ipDeviceAddress = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ [Category("采集控制"), DisplayName("触发模式"), Description("设置相机的图像采集触发方式")]
+ [TypeConverter(typeof(EnumDescriptionTypeConverter))]
+ public TriggerModeType TriggerMode
+ {
+ get => _triggerMode;
+ set
+ {
+ if (_triggerMode != value)
+ {
+ _triggerMode = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ [Category("采集控制"), DisplayName("是否启用"), Description("是否在程序启动时初始化并使用此相机")]
+ public bool IsEnabled
+ {
+ get => _isEnabled;
+ set
+ {
+ if (_isEnabled != value)
+ {
+ _isEnabled = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ [Category("检测配置"), DisplayName("检测类型"), Description("使用传统算法或深度学习")]
+ [TypeConverter(typeof(EnumDescriptionTypeConverter))]
+ public CheckType CheckType
+ {
+ get => _checkType;
+ set
+ {
+ if (_checkType != value)
+ {
+ _checkType = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ [Category("基本信息"), DisplayName("模型编号"), Description("相机调用的模型编号")]
+ [TypeConverter(typeof(ModelSelectionConverter))]
+ public int ModelID
+ {
+ get => _modelID;
+ set
+ {
+ if (_modelID != value)
+ {
+ _modelID = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ ///
+ /// 4. 触发 PropertyChanged 事件的辅助方法
+ /// [CallerMemberName] 特性是一个“语法糖”,它会自动获取调用此方法的属性的名称。
+ /// 例如,在Name属性的setter中调用OnPropertyChanged(),C#编译器会自动传入"Name"作为参数。
+ ///
+ protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+ public object Clone()
+ {
+ // MemberwiseClone() 会创建一个新对象,并将当前对象的所有非静态字段的值
+ // 复制到新对象中。对于值类型,这是值的拷贝;对于引用类型,这是引用的拷贝。
+ // 在本类中,这已经足够了。
+ return this.MemberwiseClone();
+ }
+ }
+}
diff --git a/Check.Main/Camera/HikvisionCamera.cs b/Check.Main/Camera/HikvisionCamera.cs
new file mode 100644
index 0000000..79e7779
--- /dev/null
+++ b/Check.Main/Camera/HikvisionCamera.cs
@@ -0,0 +1,502 @@
+using MvCamCtrl.NET;
+using Sunny.UI;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Check.Main.Camera
+{
+ public class HikvisionCamera : IDisposable
+ {
+ [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
+ private static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
+ // 事件委托
+ public delegate void ImageAcquiredEventHandler(HikvisionCamera sender, Bitmap bmp);
+ // public delegate void ImageAcquiredEventHandler(object sender, Bitmap bmp);
+ public delegate void CameraMessageEventHandler(object sender, string message, int errorCode = 0);
+
+ // 事件
+ public event ImageAcquiredEventHandler ImageAcquired;
+ public event CameraMessageEventHandler CameraMessage;
+
+ // 私有成员变量
+ private MyCamera m_MyCamera;
+ private MyCamera.MV_CC_DEVICE_INFO_LIST m_stDeviceList;
+ private bool m_bGrabbing = false;
+ private Thread m_hReceiveThread = null;
+
+ private Bitmap m_bitmap = null;
+ private IntPtr m_ConvertDstBuf = IntPtr.Zero;
+ private uint m_nConvertDstBufLen = 0;
+ public string Name { get; set; }
+
+ ///
+ /// 由外部逻辑分配的、唯一的相机软件编号。
+ /// 主要用作图像路由和与逻辑处理器匹配的键。
+ ///
+ public int CameraIndex { get; set; }
+
+ ///
+ /// 相机是否已经打开
+ ///
+ public bool IsOpen { get; private set; } = false;
+
+ public TriggerModeType TriggerMode { get; internal set; } // internal set 保证只有 CameraManager 能设置它
+
+
+ ///
+ /// 相机是否正在采集
+ ///
+ public bool IsGrabbing => m_bGrabbing;
+
+ public HikvisionCamera()
+ {
+ // 初始化SDK
+ MyCamera.MV_CC_Initialize_NET();
+ }
+
+ ///
+ /// 查找所有可用的相机设备
+ ///
+ /// 设备名称列表
+ public List FindDevices()
+ {
+ var deviceList = new List();
+ m_stDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
+ int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_stDeviceList);
+ if (nRet != MyCamera.MV_OK)
+ {
+ OnCameraMessage("设备枚举失败!", nRet);
+ return deviceList;
+ }
+
+ for (int i = 0; i < m_stDeviceList.nDeviceNum; i++)
+ {
+ var device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));
+ if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
+ {
+ var gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO_EX)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO_EX));
+ if (!string.IsNullOrEmpty(Encoding.Default.GetString(gigeInfo.chUserDefinedName).TrimEnd('\0')))
+ deviceList.Add("GEV: " + gigeInfo.chUserDefinedName + " (" + gigeInfo.chSerialNumber + ")");
+ else
+ deviceList.Add("GEV: " + gigeInfo.chManufacturerName + " " + gigeInfo.chModelName + " (" + gigeInfo.chSerialNumber + ")");
+ }
+ else if (device.nTLayerType == MyCamera.MV_USB_DEVICE)
+ {
+ var usbInfo = (MyCamera.MV_USB3_DEVICE_INFO_EX)MyCamera.ByteToStruct(device.SpecialInfo.stUsb3VInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO_EX));
+ if (!string.IsNullOrEmpty(Encoding.Default.GetString(usbInfo.chUserDefinedName).TrimEnd('\0')))
+ deviceList.Add("U3V: " + usbInfo.chUserDefinedName + " (" + usbInfo.chSerialNumber + ")");
+ else
+ deviceList.Add("U3V: " + usbInfo.chManufacturerName + " " + usbInfo.chModelName + " (" + usbInfo.chSerialNumber + ")");
+ }
+ }
+ return deviceList;
+ }
+
+ ///
+ /// 根据索引打开相机
+ ///
+ /// 设备索引
+ /// 成功返回true,否则返回false
+ public bool Open(CameraSettings camConfig)
+ {
+ string ipCam = "";
+ string ipDevice = "";
+ FindDevices();
+ if (camConfig.IsEnabled == true)
+ {
+ ipCam = camConfig.IPAddress;
+ ipDevice = camConfig.IPDeviceAddress;
+ }
+ try
+ {
+ if (m_stDeviceList.nDeviceNum == 0 || string.IsNullOrEmpty(camConfig.IPAddress))
+ {
+ OnCameraMessage("没有找到设备或索引无效。", -1);
+ return false;
+ }
+
+ if (IsOpen)
+ {
+ OnCameraMessage("相机已经打开。", 0);
+ return true;
+ }
+ MyCamera.MV_CC_DEVICE_INFO device = new MyCamera.MV_CC_DEVICE_INFO();
+ device.nTLayerType = MyCamera.MV_GIGE_DEVICE;
+ MyCamera.MV_GIGE_DEVICE_INFO stGigEDev = new MyCamera.MV_GIGE_DEVICE_INFO();
+ var parts = ipCam.Split('.');
+ int nIp1 = Convert.ToInt32(parts[0]);
+ int nIp2 = Convert.ToInt32(parts[1]);
+ int nIp3 = Convert.ToInt32(parts[2]);
+ int nIp4 = Convert.ToInt32(parts[3]);
+ stGigEDev.nCurrentIp = (uint)((nIp1 << 24) | (nIp2 << 16) | (nIp3 << 8) | nIp4);
+
+ parts = ipDevice.Split('.');
+ nIp1 = Convert.ToInt32(parts[0]);
+ nIp2 = Convert.ToInt32(parts[1]);
+ nIp3 = Convert.ToInt32(parts[2]);
+ nIp4 = Convert.ToInt32(parts[3]);
+ stGigEDev.nNetExport = (uint)((nIp1 << 24) | (nIp2 << 16) | (nIp3 << 8) | nIp4);
+ IntPtr stGigeInfoPtr = Marshal.AllocHGlobal(216);
+ Marshal.StructureToPtr(stGigEDev, stGigeInfoPtr, false);
+ device.SpecialInfo.stGigEInfo = new Byte[540];
+ Marshal.Copy(stGigeInfoPtr, device.SpecialInfo.stGigEInfo, 0, 540);
+ //释放内存空间
+ Marshal.FreeHGlobal(stGigeInfoPtr);
+
+ //var device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[index], typeof(MyCamera.MV_CC_DEVICE_INFO));
+ m_MyCamera = new MyCamera();
+ int nRet = m_MyCamera.MV_CC_CreateDevice_NET(ref device);
+ if (nRet != MyCamera.MV_OK)
+ {
+ OnCameraMessage("创建设备句柄失败!", nRet);
+ return false;
+ }
+
+ nRet = m_MyCamera.MV_CC_OpenDevice_NET();
+ if (nRet != MyCamera.MV_OK)
+ {
+ OnCameraMessage("打开设备失败!", nRet);
+ m_MyCamera.MV_CC_DestroyDevice_NET();
+ return false;
+ }
+
+ // 探测网络最佳包大小(只对GigE相机有效)
+ if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
+ {
+ int nPacketSize = m_MyCamera.MV_CC_GetOptimalPacketSize_NET();
+ if (nPacketSize > 0)
+ {
+ m_MyCamera.MV_CC_SetIntValueEx_NET("GevSCPSPacketSize", nPacketSize);
+ }
+ }
+
+ // 默认设置为连续模式
+ SetContinuousMode();
+
+ IsOpen = true;
+ OnCameraMessage("相机打开成功。", 0);
+ return true;
+ }
+ catch (Exception ex)
+ {
+ OnCameraMessage("相机打开失败。"+ ex.ToString(), 0);
+ return false;
+ }
+
+ }
+
+ ///
+ /// 关闭相机
+ ///
+ public void Close()
+ {
+ if (!IsOpen) return;
+
+ if (m_bGrabbing)
+ {
+ StopGrabbing();
+ }
+
+ m_MyCamera.MV_CC_CloseDevice_NET();
+ m_MyCamera.MV_CC_DestroyDevice_NET();
+
+ IsOpen = false;
+ m_MyCamera = null;
+ OnCameraMessage("相机已关闭。", 0);
+ }
+
+ ///
+ /// 开始采集图像
+ ///
+ /// 成功返回true
+ public bool StartGrabbing()
+ {
+ if (!IsOpen || m_bGrabbing)
+ {
+ OnCameraMessage(m_bGrabbing ? "已经在采集中。" : "相机未打开。", -1);
+ return false;
+ }
+
+ // 取图前的必要操作
+ if (NecessaryOperBeforeGrab() != MyCamera.MV_OK)
+ {
+ return false;
+ }
+
+ int nRet = m_MyCamera.MV_CC_StartGrabbing_NET();
+ if (nRet != MyCamera.MV_OK)
+ {
+ OnCameraMessage("开始采集失败!", nRet);
+ return false;
+ }
+
+ m_bGrabbing = true;
+ m_hReceiveThread = new Thread(ReceiveThreadProcess);
+ m_hReceiveThread.IsBackground = true;
+ m_hReceiveThread.Start();
+
+ OnCameraMessage("开始采集。", 0);
+ return true;
+ }
+
+ ///
+ /// 停止采集图像
+ ///
+ public void StopGrabbing()
+ {
+ if (!m_bGrabbing) return;
+
+ m_bGrabbing = false;
+ if (m_hReceiveThread != null && m_hReceiveThread.IsAlive)
+ {
+ m_hReceiveThread.Join(1000); // 等待线程退出
+ }
+
+ int nRet = m_MyCamera.MV_CC_StopGrabbing_NET();
+ if (nRet != MyCamera.MV_OK)
+ {
+ OnCameraMessage("停止采集失败!", nRet);
+ }
+
+ OnCameraMessage("停止采集。", 0);
+ }
+
+ ///
+ /// 设置为连续采集模式
+ ///
+ public void SetContinuousMode()
+ {
+ if (!IsOpen) return;
+ m_MyCamera.MV_CC_SetEnumValue_NET("AcquisitionMode", (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS);
+ m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);
+ OnCameraMessage("已设置为连续模式。", 0);
+ }
+
+ ///
+ /// 设置为触发模式
+ ///
+ /// true为软触发, false为硬触发(Line0)
+ public void SetTriggerMode(bool isSoftwareTrigger)
+ {
+ if (!IsOpen) return;
+
+ m_MyCamera.MV_CC_SetEnumValue_NET("AcquisitionMode", (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS); // 触发模式也需要在Continuous模式下
+ m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
+
+ if (isSoftwareTrigger)
+ {
+ m_MyCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
+ OnCameraMessage("已设置为软触发模式。", 0);
+ }
+ else
+ {
+ m_MyCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0);
+ OnCameraMessage("已设置为硬触发(Line0)模式。", 0);
+ }
+ }
+
+ ///
+ /// 执行一次软触发
+ ///
+ /// 成功返回true
+ public bool SoftwareTrigger()
+ {
+ if (!IsOpen || !m_bGrabbing)
+ {
+ OnCameraMessage("请先打开相机并开始采集。", -1);
+ return false;
+ }
+
+ int nRet = m_MyCamera.MV_CC_SetCommandValue_NET("TriggerSoftware");
+ if (nRet != MyCamera.MV_OK)
+ {
+ OnCameraMessage("软触发失败!", nRet);
+ return false;
+ }
+ return true;
+ }
+
+ ///
+ /// 图像接收线程
+ ///
+ private void ReceiveThreadProcess()
+ {
+ MyCamera.MV_FRAME_OUT stFrameInfo = new MyCamera.MV_FRAME_OUT();
+ var stConvertParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();
+
+ while (m_bGrabbing)
+ {
+ int nRet = m_MyCamera.MV_CC_GetImageBuffer_NET(ref stFrameInfo, 1000);
+ if (nRet == MyCamera.MV_OK)
+ {
+ Bitmap bmpForEvent = null; // 在 try 外部声明
+ try
+ {
+ // 初始化转换参数
+ stConvertParam.nWidth = stFrameInfo.stFrameInfo.nWidth;
+ stConvertParam.nHeight = stFrameInfo.stFrameInfo.nHeight;
+ stConvertParam.pSrcData = stFrameInfo.pBufAddr;
+ stConvertParam.nSrcDataLen = stFrameInfo.stFrameInfo.nFrameLen;
+ stConvertParam.enSrcPixelType = stFrameInfo.stFrameInfo.enPixelType;
+ stConvertParam.pDstBuffer = m_ConvertDstBuf;
+ stConvertParam.nDstBufferSize = m_nConvertDstBufLen;
+
+ // 创建用于事件的Bitmap,它的格式与类成员m_bitmap一致
+ bmpForEvent = new Bitmap((int)stConvertParam.nWidth, (int)stConvertParam.nHeight, m_bitmap.PixelFormat);
+
+ // 判断并设置目标像素格式
+ if (bmpForEvent.PixelFormat == PixelFormat.Format8bppIndexed)
+ {
+ stConvertParam.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8;
+ }
+ else
+ {
+ stConvertParam.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_BGR8_Packed;
+ }
+
+ // 执行像素格式转换
+ nRet = m_MyCamera.MV_CC_ConvertPixelType_NET(ref stConvertParam);
+ if (nRet == MyCamera.MV_OK)
+ {
+ // 转换成功,锁定位图内存并拷贝数据
+ BitmapData bmpData = bmpForEvent.LockBits(new Rectangle(0, 0, stConvertParam.nWidth, stConvertParam.nHeight), ImageLockMode.WriteOnly, bmpForEvent.PixelFormat);
+
+ // 使用更健壮的逐行拷贝
+ int pixelSize = (bmpForEvent.PixelFormat == PixelFormat.Format8bppIndexed) ? 1 : 3;
+ for (int i = 0; i < bmpData.Height; ++i)
+ {
+ IntPtr pDst = new IntPtr(bmpData.Scan0.ToInt64() + i * bmpData.Stride);
+ IntPtr pSrc = new IntPtr(m_ConvertDstBuf.ToInt64() + i * stConvertParam.nWidth * pixelSize);
+ CopyMemory(pDst, pSrc, (uint)(stConvertParam.nWidth * pixelSize));
+ }
+ bmpForEvent.UnlockBits(bmpData);
+
+ // 触发图像采集事件,转移 bmpForEvent 的所有权
+ ImageAcquired?.Invoke(this, bmpForEvent);
+
+ // 【关键】所有权已转移,将本地引用设为null,防止它在finally块中被错误地释放
+ bmpForEvent = null;
+ }
+ // 如果转换失败,不执行任何操作,让 finally 块来处理 bmpForEvent 的释放
+ }
+ finally
+ {
+ // 【关键】如果 bmpForEvent 不为 null,意味着它被成功创建,
+ // 但没有被成功传递给事件处理器(可能因为转换失败或发生其他异常),
+ // 在这里必须将其释放。
+ bmpForEvent?.Dispose();
+
+ // 无论成功与否,都必须释放相机SDK的内部图像缓存
+ m_MyCamera.MV_CC_FreeImageBuffer_NET(ref stFrameInfo);
+ }
+ }
+ else
+ {
+ // 超时,继续等待
+ Thread.Sleep(5);
+ }
+ }
+ }
+
+ ///
+ /// 取图前的内存和参数准备
+ ///
+ private int NecessaryOperBeforeGrab()
+ {
+ var stWidth = new MyCamera.MVCC_INTVALUE_EX();
+ int nRet = m_MyCamera.MV_CC_GetIntValueEx_NET("Width", ref stWidth);
+ if (nRet != MyCamera.MV_OK) { OnCameraMessage("获取宽度失败!", nRet); return nRet; }
+
+ var stHeight = new MyCamera.MVCC_INTVALUE_EX();
+ nRet = m_MyCamera.MV_CC_GetIntValueEx_NET("Height", ref stHeight);
+ if (nRet != MyCamera.MV_OK) { OnCameraMessage("获取高度失败!", nRet); return nRet; }
+
+ var stPixelFormat = new MyCamera.MVCC_ENUMVALUE();
+ nRet = m_MyCamera.MV_CC_GetEnumValue_NET("PixelFormat", ref stPixelFormat);
+ if (nRet != MyCamera.MV_OK) { OnCameraMessage("获取像素格式失败!", nRet); return nRet; }
+
+ PixelFormat bitmapPixelFormat;
+ // 判断当前像素格式是否为Mono
+ bool isMono = IsMono(stPixelFormat.nCurValue);
+
+ if (isMono)
+ {
+ bitmapPixelFormat = PixelFormat.Format8bppIndexed;
+ m_nConvertDstBufLen = (uint)(stWidth.nCurValue * stHeight.nCurValue);
+ }
+ else
+ {
+ bitmapPixelFormat = PixelFormat.Format24bppRgb;
+ m_nConvertDstBufLen = (uint)(stWidth.nCurValue * stHeight.nCurValue * 3);
+ }
+
+ // 分配转换后的图像数据缓存
+ if (m_ConvertDstBuf != IntPtr.Zero) Marshal.FreeHGlobal(m_ConvertDstBuf);
+ m_ConvertDstBuf = Marshal.AllocHGlobal((int)m_nConvertDstBufLen);
+
+ // 创建Bitmap对象
+ if (m_bitmap != null) m_bitmap.Dispose();
+ m_bitmap = new Bitmap((int)stWidth.nCurValue, (int)stHeight.nCurValue, bitmapPixelFormat);
+
+ // 如果是Mono8格式,设置调色板
+ if (isMono)
+ {
+ ColorPalette palette = m_bitmap.Palette;
+ for (int i = 0; i < 256; i++) palette.Entries[i] = Color.FromArgb(i, i, i);
+ m_bitmap.Palette = palette;
+ }
+
+ return MyCamera.MV_OK;
+ }
+
+ private bool IsMono(uint enPixelType)
+ {
+ switch (enPixelType)
+ {
+ case (uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8:
+ case (uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10:
+ case (uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10_Packed:
+ case (uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12:
+ case (uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12_Packed:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ ///
+ /// 触发相机消息事件
+ ///
+ private void OnCameraMessage(string message, int errorCode = 0)
+ {
+ CameraMessage?.Invoke(this, message, errorCode);
+ }
+
+ ///
+ /// 释放资源
+ ///
+ public void Dispose()
+ {
+ Close();
+ if (m_ConvertDstBuf != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(m_ConvertDstBuf);
+ m_ConvertDstBuf = IntPtr.Zero;
+ }
+ if (m_bitmap != null)
+ {
+ m_bitmap.Dispose();
+ m_bitmap = null;
+ }
+ MyCamera.MV_CC_Finalize_NET();
+ }
+ }
+}
diff --git a/Check.Main/Check.Main.csproj b/Check.Main/Check.Main.csproj
new file mode 100644
index 0000000..d210470
--- /dev/null
+++ b/Check.Main/Check.Main.csproj
@@ -0,0 +1,37 @@
+
+
+
+ WinExe
+ net8.0-windows
+ enable
+ true
+ enable
+
+
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\..\HslCommunication-master\HslCommunication.dll
+
+
+ C:\Program Files (x86)\MVS\Development\DotNet\win64\MvCameraControl.Net.dll
+
+
+
+
\ No newline at end of file
diff --git a/Check.Main/Common/ConfigurationManager.cs b/Check.Main/Common/ConfigurationManager.cs
new file mode 100644
index 0000000..173346a
--- /dev/null
+++ b/Check.Main/Common/ConfigurationManager.cs
@@ -0,0 +1,124 @@
+using Check.Main.Camera;
+using Check.Main.Dispatch;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.Serialization;
+
+namespace Check.Main.Common
+{
+ ///
+ /// 静态全局配置管理器,作为配置数据的“单一数据源”。
+ /// 负责加载、保存和通知配置变更。
+ ///
+ public static class ConfigurationManager
+ {
+ // private static readonly string _configFilePath = Path.Combine(Application.StartupPath, "main_config.xml");
+ // private static ProcessConfig _currentConfig;
+ // private static readonly object _lock = new object();
+
+ // ///
+ // /// 当配置通过 SaveChanges() 方法保存后触发。
+ // /// 其他模块(如 FormControlPanel)可以订阅此事件以响应配置变更。
+ // ///
+ // public static event Action OnConfigurationChanged;
+
+ // ///
+ // /// 静态构造函数在类首次被访问时自动执行,确保配置只被加载一次。
+ // ///
+ // static ConfigurationManager()
+ // {
+ // Load();
+ // }
+
+ // ///
+ // /// 获取对当前配置对象的直接引用。
+ // /// PropertyGrid 可以直接绑定到这个对象进行编辑。
+ // ///
+ // /// 当前的 ProcessConfig 实例。
+ // public static ProcessConfig GetCurrentConfig()
+ // {
+ // return _currentConfig;
+ // }
+
+ // ///
+ // /// 从 XML 文件加载配置。如果文件不存在或加载失败,则创建一个新的默认配置。
+ // ///
+ // private static void Load()
+ // {
+ // lock (_lock)
+ // {
+ // if (File.Exists(_configFilePath))
+ // {
+ // try
+ // {
+ // XmlSerializer serializer = new XmlSerializer(typeof(ProcessConfig));
+ // using (var fs = new FileStream(_configFilePath, FileMode.Open, FileAccess.Read))
+ // {
+ // _currentConfig = (ProcessConfig)serializer.Deserialize(fs);
+ // ThreadSafeLogger.Log("主配置文件加载成功。");
+ // }
+ // }
+ // catch (Exception ex)
+ // {
+ // ThreadSafeLogger.Log("加载主配置失败: " + ex.Message + " 将使用默认配置。");
+ // _currentConfig = new ProcessConfig();
+ // }
+ // }
+ // else
+ // {
+ // ThreadSafeLogger.Log("未找到主配置文件,将创建新的默认配置。");
+ // _currentConfig = new ProcessConfig();
+ // }
+ // }
+ // }
+
+ // ///
+ // /// 将当前配置保存到文件,并通知所有监听者配置已更改。
+ // /// 这是响应UI变化的推荐方法。
+ // ///
+ // public static void SaveChanges()
+ // {
+ // lock (_lock)
+ // {
+ // try
+ // {
+ // XmlSerializer serializer = new XmlSerializer(typeof(ProcessConfig));
+ // using (var fs = new FileStream(_configFilePath, FileMode.Create, FileAccess.Write))
+ // {
+ // serializer.Serialize(fs, _currentConfig);
+ // }
+ // }
+ // catch (Exception ex)
+ // {
+ // ThreadSafeLogger.Log("保存主配置失败: " + ex.Message);
+ // }
+ // }
+
+ // // 在锁之外触发事件,以避免监听者中的代码导致死锁
+ // ThreadSafeLogger.Log("配置已保存,正在触发 OnConfigurationChanged 事件...");
+ // OnConfigurationChanged?.Invoke();
+ // }
+ // 不再自己管理配置,而是直接从 ProductManager 获取
+ public static ProcessConfig GetCurrentConfig()
+ {
+ return ProductManager.CurrentConfig;
+ }
+
+ public static void SaveChanges()
+ {
+ ProductManager.SaveCurrentProductConfig();
+ }
+
+ // OnConfigurationChanged 事件现在由 ProductManager.OnProductChanged 替代
+ // 如果其他地方还依赖这个事件,可以做一个桥接:
+ public static event Action OnConfigurationChanged
+ {
+ add { ProductManager.OnProductChanged += value; }
+ remove { ProductManager.OnProductChanged -= value; }
+ }
+ }
+
+}
diff --git a/Check.Main/Common/EasyE5Options.cs b/Check.Main/Common/EasyE5Options.cs
new file mode 100644
index 0000000..59fb256
--- /dev/null
+++ b/Check.Main/Common/EasyE5Options.cs
@@ -0,0 +1,236 @@
+using NPOI.SS.Formula.Functions;
+using Sunny.UI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Sockets;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace Check.Main.Common
+{
+ ///
+ /// 汇川 Easy 系列 PLC 客户端 (Modbus TCP)
+ /// 支持 D/M/X/Y 地址读写,整数、浮点数、字符串
+ ///
+ public class EasyPlcClient : IDisposable
+ {
+ private readonly TcpClient _tcpClient = new();
+ private NetworkStream _stream;
+ private ushort _transactionId = 0;
+ private readonly SemaphoreSlim _lock = new(1, 1);
+
+ private readonly string _ip;
+ private readonly int _port;
+ private readonly byte _slaveId;
+
+ public EasyPlcClient(string ip, int port = 502, byte slaveId = 1)
+ {
+ _ip = ip;
+ _port = port;
+ _slaveId = slaveId;
+ }
+
+ public async Task ConnectAsync()
+ {
+ await _tcpClient.ConnectAsync(_ip, _port);
+ _stream = _tcpClient.GetStream();
+ }
+
+ #region ---- 基础 Modbus ----
+ private ushort GetTransactionId() =>
+ unchecked((ushort)Interlocked.Increment(ref Unsafe.As(ref _transactionId)));
+
+ private async Task SendAndReceiveAsync(byte[] pdu, ushort startAddr, ushort length = 1)
+ {
+ ushort tid = GetTransactionId();
+ ushort lengthField = (ushort)(pdu.Length + 1);
+ byte[] mbap = {
+ (byte)(tid >> 8), (byte)tid,
+ 0x00, 0x00, // Protocol = 0
+ (byte)(lengthField >> 8), (byte)lengthField,
+ _slaveId
+ };
+
+ byte[] adu = new byte[mbap.Length + pdu.Length];
+ Buffer.BlockCopy(mbap, 0, adu, 0, mbap.Length);
+ Buffer.BlockCopy(pdu, 0, adu, mbap.Length, pdu.Length);
+
+ await _lock.WaitAsync();
+ try
+ {
+ await _stream.WriteAsync(adu, 0, adu.Length);
+
+ byte[] header = new byte[7];
+ await _stream.ReadAsync(header, 0, 7);
+ int respLength = (header[4] << 8) + header[5];
+ byte[] resp = new byte[respLength - 1];
+ await _stream.ReadAsync(resp, 0, resp.Length);
+
+ return resp;
+ }
+ finally { _lock.Release(); }
+ }
+ #endregion
+
+ #region ---- 地址解析 ----
+ private void ParseAddress(string address, out string area, out ushort offset)
+ {
+ var letters = Regex.Match(address, @"^[A-Za-z]+").Value.ToUpper();
+ var digits = Regex.Match(address, @"\d+").Value;
+
+ if (string.IsNullOrEmpty(letters) || string.IsNullOrEmpty(digits))
+ throw new ArgumentException($"地址 {address} 无效");
+
+ area = letters;
+ offset = (ushort)(ushort.Parse(digits) - 1);
+
+ // 👉 注意:这里的偏移需根据你的 PLC Modbus 地址表调整
+ // 例如 D 区可能是 40001 起,M 区可能是 00001 起
+ // 目前假设 D -> Holding Register, M/Y -> Coil, X -> Discrete Input
+ }
+ #endregion
+
+ #region ---- 整数读写 ----
+ public async Task WriteAsync(string address, int value)
+ {
+ ParseAddress(address, out string area, out ushort offset);
+
+ switch (area)
+ {
+ case "D": // 写寄存器
+ byte[] pdu = {
+ 0x06,
+ (byte)(offset >> 8), (byte)offset,
+ (byte)(value >> 8), (byte)value
+ };
+ await SendAndReceiveAsync(pdu, offset);
+ break;
+
+ case "M":
+ case "Y": // 写单线圈
+ byte[] coil = {
+ 0x05,
+ (byte)(offset >> 8), (byte)offset,
+ (byte)(value != 0 ? 0xFF : 0x00), 0x00
+ };
+ await SendAndReceiveAsync(coil, offset);
+ break;
+
+ default:
+ throw new NotSupportedException($"写 {area} 区未支持");
+ }
+ }
+
+ public async Task ReadAsync(string address)
+ {
+ ParseAddress(address, out string area, out ushort offset);
+
+ switch (area)
+ {
+ case "D": // Holding Register
+ byte[] pdu = { 0x03, (byte)(offset >> 8), (byte)offset, 0x00, 0x01 };
+ var resp = await SendAndReceiveAsync(pdu, offset);
+ return (resp[1] << 8) + resp[2];
+
+ case "M":
+ case "Y": // Coils
+ byte[] pdu1 = { 0x01, (byte)(offset >> 8), (byte)offset, 0x00, 0x01 };
+ var resp1 = await SendAndReceiveAsync(pdu1, offset);
+ return (resp1[2] & 0x01) != 0 ? 1 : 0;
+
+ case "X": // Inputs
+ byte[] pdu2 = { 0x02, (byte)(offset >> 8), (byte)offset, 0x00, 0x01 };
+ var resp2 = await SendAndReceiveAsync(pdu2, offset);
+ return (resp2[2] & 0x01) != 0 ? 1 : 0;
+
+ default:
+ throw new NotSupportedException($"读 {area} 区未支持");
+ }
+ }
+ #endregion
+
+ #region ---- 浮点读写 (2寄存器) ----
+ public async Task WriteFloatAsync(string address, float value)
+ {
+ ParseAddress(address, out string area, out ushort offset);
+ if (area != "D") throw new NotSupportedException("浮点仅支持 D 区");
+
+ byte[] bytes = BitConverter.GetBytes(value);
+ if (BitConverter.IsLittleEndian) Array.Reverse(bytes);
+
+ byte[] pdu = {
+ 0x10,
+ (byte)(offset >> 8), (byte)offset,
+ 0x00, 0x02,
+ 0x04,
+ bytes[0], bytes[1], bytes[2], bytes[3]
+ };
+ await SendAndReceiveAsync(pdu, offset, 2);
+ }
+
+ public async Task ReadFloatAsync(string address)
+ {
+ ParseAddress(address, out string area, out ushort offset);
+ if (area != "D") throw new NotSupportedException("浮点仅支持 D 区");
+
+ byte[] pdu = { 0x03, (byte)(offset >> 8), (byte)offset, 0x00, 0x02 };
+ var resp = await SendAndReceiveAsync(pdu, offset, 2);
+
+ byte[] data = { resp[1], resp[2], resp[3], resp[4] };
+ if (BitConverter.IsLittleEndian) Array.Reverse(data);
+
+ return BitConverter.ToSingle(data, 0);
+ }
+ #endregion
+
+ #region ---- 字符串读写 ----
+ public async Task WriteStringAsync(string address, string value, int maxLength)
+ {
+ ParseAddress(address, out string area, out ushort offset);
+ if (area != "D") throw new NotSupportedException("字符串仅支持 D 区");
+
+ byte[] strBytes = Encoding.ASCII.GetBytes(value);
+ if (strBytes.Length > maxLength) Array.Resize(ref strBytes, maxLength);
+
+ // 每寄存器2字节
+ int regCount = (strBytes.Length + 1) / 2;
+ byte[] data = new byte[regCount * 2];
+ Array.Copy(strBytes, data, strBytes.Length);
+
+ byte[] pdu = new byte[7 + data.Length];
+ pdu[0] = 0x10;
+ pdu[1] = (byte)(offset >> 8); pdu[2] = (byte)offset;
+ pdu[3] = (byte)(regCount >> 8); pdu[4] = (byte)regCount;
+ pdu[5] = (byte)(data.Length);
+ Buffer.BlockCopy(data, 0, pdu, 6, data.Length);
+
+ await SendAndReceiveAsync(pdu, offset, (ushort)regCount);
+ }
+
+ public async Task ReadStringAsync(string address, int length)
+ {
+ ParseAddress(address, out string area, out ushort offset);
+ if (area != "D") throw new NotSupportedException("字符串仅支持 D 区");
+
+ int regCount = (length + 1) / 2;
+ byte[] pdu = { 0x03, (byte)(offset >> 8), (byte)offset, (byte)(regCount >> 8), (byte)regCount };
+ var resp = await SendAndReceiveAsync(pdu, offset, (ushort)regCount);
+
+ byte[] data = new byte[resp[0]];
+ Array.Copy(resp, 1, data, 0, data.Length);
+
+ return Encoding.ASCII.GetString(data).TrimEnd('\0');
+ }
+ #endregion
+
+ public void Dispose()
+ {
+ _stream?.Dispose();
+ _tcpClient?.Close();
+ _lock?.Dispose();
+ }
+ }
+}
diff --git a/Check.Main/Common/ImageData.cs b/Check.Main/Common/ImageData.cs
new file mode 100644
index 0000000..ea5f904
--- /dev/null
+++ b/Check.Main/Common/ImageData.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Check.Main.Common
+{
+ public class ImageData : IDisposable
+ {
+ public long ProductId { get; }
+ public int CameraIndex { get; }
+ public Bitmap Image { get; }
+
+ public ImageData(long productId, int cameraIndex, Bitmap image)
+ {
+ ProductId = productId;
+ CameraIndex = cameraIndex;
+ Image = image;
+ }
+ public void Dispose() => Image?.Dispose();
+ }
+
+ // ProductAssembly.cs - 用于组装一个完整的产品
+ public class ProductAssembly : IDisposable
+ {
+ public long ProductId { get; }
+ private readonly int _expectedCameraCount;
+ // 使用 ConcurrentDictionary 保证线程安全
+ private readonly ConcurrentDictionary _results = new ConcurrentDictionary();
+
+ public ProductAssembly(long productId, int expectedCameraCount)
+ {
+ ProductId = productId;
+ _expectedCameraCount = expectedCameraCount;
+ }
+
+ // 添加一个相机的检测结果
+ public bool AddResult(int cameraIndex, string result)
+ {
+ _results.TryAdd(cameraIndex, result);
+ return _results.Count == _expectedCameraCount;
+ }
+
+ // 获取最终的聚合结果
+ public string GetFinalResult()
+ {
+ // 如果任何一个结果包含 "NG",则最终结果为 "NG"
+ return _results.Values.Any(r => r.Contains("NG")) ? "NG" : "OK";
+ }
+
+ public void Dispose()
+ {
+ // 目前只持有结果字符串,无需释放资源
+ }
+ }
+}
diff --git a/Check.Main/Common/ModelSelectionConverter.cs b/Check.Main/Common/ModelSelectionConverter.cs
new file mode 100644
index 0000000..ed5845b
--- /dev/null
+++ b/Check.Main/Common/ModelSelectionConverter.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using static System.ComponentModel.TypeConverter;
+
+namespace Check.Main.Common
+{
+ ///
+ /// 一个自定义的 TypeConverter,用于在 PropertyGrid 中为模型选择提供一个下拉列表。
+ ///
+ public class ModelSelectionConverter : Int32Converter // 我们转换的是整数 (ModelId)
+ {
+ // 告诉 PropertyGrid,我们支持从一个标准值集合中进行选择
+ public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
+ {
+ return true;
+ }
+
+ // 告诉 PropertyGrid,我们只允许用户从列表中选择,不允许手动输入
+ public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
+ {
+ return true;
+ }
+
+ // 这是最核心的方法:提供标准值的列表
+ public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
+ {
+ try
+ {
+ // 从中央配置管理器获取所有已配置的模型
+ var modelSettings = ConfigurationManager.GetCurrentConfig().ModelSettings;
+
+ if (modelSettings == null || modelSettings.Count == 0)
+ {
+ // 如果没有模型,返回一个包含默认值 "0"(代表“无”)的列表
+ return new StandardValuesCollection(new[] { 0 });
+ }
+
+ // 使用LINQ从模型列表中提取所有模型的ID
+ // .Prepend(0) 在列表开头添加一个 "0",代表“未选择”的选项
+ var modelIds = modelSettings.Select(m => m.Id).Prepend(0).ToArray();
+
+ return new StandardValuesCollection(modelIds);
+ }
+ catch
+ {
+ // 如果在获取过程中发生任何异常,返回一个安全的默认值
+ return new StandardValuesCollection(new[] { 0 });
+ }
+ }
+
+ // --- 为了让下拉列表显示模型名称而不是ID,我们还需要重写以下方法 ---
+
+ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
+ {
+ return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
+ {
+ return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
+ }
+
+ // 将模型ID转换为其对应的名称字符串,以便在UI上显示
+ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
+ {
+ if (destinationType == typeof(string) && value is int modelId)
+ {
+ if (modelId == 0)
+ {
+ return "未选择"; // 对ID为0的特殊处理
+ }
+
+ // 查找ID对应的模型名称
+ var model = ConfigurationManager.GetCurrentConfig()
+ .ModelSettings?
+ .FirstOrDefault(m => m.Id == modelId);
+
+ // 返回 "名称 (ID)" 的格式,更清晰
+ return model != null ? $"{model.Name} (ID: {model.Id})" : "未知模型";
+ }
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+
+ // 将用户在UI上选择的名称字符串,转换回其对应的模型ID,以便保存
+ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
+ {
+ if (value is string displayString)
+ {
+ if (displayString == "未选择")
+ {
+ return 0;
+ }
+
+ // 从 "名称 (ID: X)" 格式中解析出ID
+ if (displayString.Contains("(ID: ") && displayString.EndsWith(")"))
+ {
+ var startIndex = displayString.IndexOf("(ID: ") + 5;
+ var endIndex = displayString.Length - 1;
+ var idString = displayString.Substring(startIndex, endIndex - startIndex);
+ if (int.TryParse(idString, out int modelId))
+ {
+ return modelId;
+ }
+ }
+ }
+ return base.ConvertFrom(context, culture, value);
+ }
+ }
+}
diff --git a/Check.Main/Common/ProcessConfig.cs b/Check.Main/Common/ProcessConfig.cs
new file mode 100644
index 0000000..e6c9a1a
--- /dev/null
+++ b/Check.Main/Common/ProcessConfig.cs
@@ -0,0 +1,161 @@
+using Check.Main.Camera;
+using Check.Main.Infer;
+using Check.Main.UI;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing.Design;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms.Design;
+
+namespace Check.Main.Common
+{
+ public class ProcessConfig
+ {
+ private string _logPath = Path.Combine(Application.StartupPath, "Logs");
+ private List _cameraSettings = new List();
+ private List _modelaSettings = new List();
+
+
+ [Category("常规设置"), DisplayName("日志路径"), Description("设置日志文件的保存目录。")]
+ [Editor(typeof(FolderNameEditor), typeof(UITypeEditor))] // 使用内置的文件夹选择器
+ public string LogPath
+ {
+ get => _logPath;
+ set => _logPath = value;
+ }
+
+ [Category("核心配置"), DisplayName("相机配置"), Description("点击 '...' 按钮来配置所有相机。")]
+ [Editor(typeof(CameraConfigEditor), typeof(UITypeEditor))] // 【关键】指定使用我们自定义的编辑器
+ [TypeConverter(typeof(CameraConfigConverter))] // 【关键】指定使用我们自定义的类型转换器来显示文本
+ public List CameraSettings
+ {
+ get => _cameraSettings;
+ set => _cameraSettings = value;
+ }
+
+ [Category("核心配置"), DisplayName("模型配置"), Description("点击 '...' 按钮来配置所有模型。")]
+ [Editor(typeof(ModelConfigEditor), typeof(UITypeEditor))] // 【关键】指定使用我们自定义的编辑器
+ [TypeConverter(typeof(ModelConfigConverter))] // 【关键】指定使用我们自定义的类型转换器来显示文本
+ public List ModelSettings
+ {
+ get => _modelaSettings;
+ set => _modelaSettings = value;
+ }
+ }
+ ///
+ /// 自定义TypeConverter,用于在PropertyGrid中自定义显示相机列表的文本。
+ ///
+ public class CameraConfigConverter : TypeConverter
+ {
+ public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
+ {
+ // 声明可以将值转换为字符串
+ return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
+ }
+
+ public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
+ {
+ // 如果目标类型是字符串,并且值是相机设置列表
+ if (destinationType == typeof(string) && value is List list)
+ {
+ // 返回自定义的描述性文本
+ return $"已配置 {list.Count} 个相机";
+ }
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+ ///
+ /// 自定义TypeConverter,用于在PropertyGrid中自定义显示相机列表的文本。
+ ///
+ public class ModelConfigConverter : TypeConverter
+ {
+ public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
+ {
+ // 声明可以将值转换为字符串
+ return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
+ }
+
+ public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
+ {
+ // 如果目标类型是字符串,并且值是相机设置列表
+ if (destinationType == typeof(string) && value is List list)
+ {
+ // 返回自定义的描述性文本
+ return $"已配置 {list.Count} 个模型";
+ }
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+
+
+ ///
+ /// 自定义UITypeEditor,用于在点击 "..." 时打开相机配置窗体。
+ ///
+ public class CameraConfigEditor : UITypeEditor
+ {
+ // 1. 设置编辑样式为模态对话框
+ public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
+ {
+ return UITypeEditorEditStyle.Modal;
+ }
+
+ // 2. 重写编辑方法
+ public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
+ {
+ // 'value' 就是当前属性的值,即 List
+ var settingsList = value as List;
+
+ // 使用 FrmCamConfig 作为对话框进行编辑
+ // 我们需要给 FrmCamConfig 添加一个新的构造函数
+ using (var camConfigForm = new FrmCamConfig(settingsList))
+ {
+ // 以对话框形式显示窗体
+ if (camConfigForm.ShowDialog() == DialogResult.OK)
+ {
+ // 如果用户点击了“确定”,返回修改后的新列表
+ return camConfigForm._settingsList;
+ }
+ }
+
+ // 如果用户点击了“取消”或直接关闭了窗口,返回原始值,不做任何更改
+ return value;
+ }
+ }
+ ///
+ /// 【新增】自定义UITypeEditor,用于在点击 "..." 时打开模型配置窗体。
+ ///
+ public class ModelConfigEditor : UITypeEditor
+ {
+ // 1. 设置编辑样式为模态对话框
+ public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
+ {
+ return UITypeEditorEditStyle.Modal;
+ }
+
+ // 2. 重写编辑方法
+ public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
+ {
+ // 'value' 就是当前属性的值,即 List
+ var settingsList = value as List;
+
+ // 使用ModelEditor 作为对话框进行编辑
+ // 我们需要给 FrmCamConfig 添加一个新的构造函数
+ using (var modelConfigForm = new ModelListEditor(settingsList))
+ {
+ // 以对话框形式显示窗体
+ if (modelConfigForm.ShowDialog() == DialogResult.OK)
+ {
+ // 如果用户点击了“确定”,返回修改后的新列表
+ return modelConfigForm._settingsList;
+ }
+ }
+
+ // 如果用户点击了“取消”或直接关闭了窗口,返回原始值,不做任何更改
+ return value;
+ }
+ }
+}
diff --git a/Check.Main/Common/ProcessingCompletedEventArgs.cs b/Check.Main/Common/ProcessingCompletedEventArgs.cs
new file mode 100644
index 0000000..ddae0d8
--- /dev/null
+++ b/Check.Main/Common/ProcessingCompletedEventArgs.cs
@@ -0,0 +1,29 @@
+using SkiaSharp;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Check.Main.Common
+{
+ public class ProcessingCompletedEventArgs : EventArgs, IDisposable
+ {
+ public int CameraIndex { get; }
+ public long ProductId { get; }
+ public SKImage ResultImage { get; } // 【修改】携带已绘制好结果的SKImage
+
+ public ProcessingCompletedEventArgs(int cameraIndex, long productId, SKImage resultImage)
+ {
+ CameraIndex = cameraIndex;
+ ProductId = productId;
+ ResultImage = resultImage;
+ }
+
+ // 实现 IDisposable 以确保SKImage资源被释放
+ public void Dispose()
+ {
+ ResultImage?.Dispose();
+ }
+ }
+}
diff --git a/Check.Main/Common/StaticMethod.cs b/Check.Main/Common/StaticMethod.cs
new file mode 100644
index 0000000..bcf6167
--- /dev/null
+++ b/Check.Main/Common/StaticMethod.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Check.Main.Common
+{
+ ///
+ /// 一个自定义的类型转换器,用于让PropertyGrid等控件显示枚举成员的Description特性,而不是成员名。
+ ///
+ public class EnumDescriptionTypeConverter : EnumConverter
+ {
+ ///
+ /// 构造函数,传入枚举类型。
+ ///
+ /// 要进行转换的枚举类型。
+ public EnumDescriptionTypeConverter(Type type) : base(type)
+ {
+ }
+
+ ///
+ /// 重写此方法,将枚举值转换为其描述文本。
+ /// 这是从 "数据" -> "UI显示" 的过程。
+ ///
+ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
+ {
+ // 如果目标类型是字符串,并且我们有一个有效的枚举值
+ if (destinationType == typeof(string) && value != null)
+ {
+ // 获取枚举值的字段信息
+ FieldInfo fi = value.GetType().GetField(value.ToString());
+ if (fi != null)
+ {
+ // 查找该字段上的DescriptionAttribute
+ var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
+
+ // 如果找到了Description特性,就返回它的描述文本;否则,返回基类的默认行为(即成员名)
+ return ((attributes.Length > 0) && (!String.IsNullOrEmpty(attributes[0].Description)))
+ ? attributes[0].Description
+ : value.ToString();
+ }
+ }
+
+ // 对于其他所有情况,使用基类的默认转换逻辑
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+
+ ///
+ /// 重写此方法,将描述文本转换回其对应的枚举值。
+ /// 这是从 "UI显示" -> "数据" 的过程。
+ ///
+ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
+ {
+ // 如果传入的值是字符串
+ if (value is string)
+ {
+ // 遍历枚举类型的所有成员
+ foreach (FieldInfo fi in EnumType.GetFields())
+ {
+ // 查找该成员上的DescriptionAttribute
+ var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
+
+ // 如果找到了Description,并且它的描述文本与传入的字符串匹配
+ if ((attributes.Length > 0) && (attributes[0].Description == (string)value))
+ {
+ // 返回这个字段(成员)对应的枚举值
+ return Enum.Parse(EnumType, fi.Name);
+ }
+ }
+ }
+
+ // 如果没有找到匹配的描述,或者传入的不是字符串,使用基类的默认转换逻辑
+ return base.ConvertFrom(context, culture, value);
+ }
+ }
+}
diff --git a/Check.Main/Common/StatisticsData.cs b/Check.Main/Common/StatisticsData.cs
new file mode 100644
index 0000000..fa75e09
--- /dev/null
+++ b/Check.Main/Common/StatisticsData.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Check.Main.Common
+{
+ ///
+ /// 封装了所有生产统计数据的模型。
+ /// 实现了INotifyPropertyChanged,未来可用于数据绑定。
+ ///
+ public class StatisticsData : INotifyPropertyChanged
+ {
+ private int _goodCount;
+ private int _ngCount;
+
+ public int GoodCount
+ {
+ get => _goodCount;
+ private set { _goodCount = value; OnPropertyChanged(nameof(GoodCount)); OnPropertyChanged(nameof(TotalCount)); OnPropertyChanged(nameof(YieldRate)); }
+ }
+
+ public int NgCount
+ {
+ get => _ngCount;
+ private set { _ngCount = value; OnPropertyChanged(nameof(NgCount)); OnPropertyChanged(nameof(TotalCount)); OnPropertyChanged(nameof(YieldRate)); }
+ }
+
+ public int TotalCount => GoodCount + NgCount;
+
+ public double YieldRate => TotalCount == 0 ? 0 : (double)GoodCount / TotalCount;
+
+ ///
+ /// 根据检测结果更新统计数据。
+ ///
+ public void UpdateWithResult(bool isOk)
+ {
+ if (isOk) GoodCount++;
+ else NgCount++;
+ }
+
+ ///
+ /// 重置所有统计数据。
+ ///
+ public void Reset()
+ {
+ GoodCount = 0;
+ NgCount = 0;
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+ protected void OnPropertyChanged(string propertyName)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+
+ ///
+ /// 用于在检测完成事件中传递结果的事件参数。
+ ///
+ public class DetectionResultEventArgs : EventArgs
+ {
+ public bool IsOK { get; }
+ public DetectionResultEventArgs(bool isOk)
+ {
+ IsOK = isOk;
+ }
+ }
+}
diff --git a/Check.Main/Common/StatisticsExporter.cs b/Check.Main/Common/StatisticsExporter.cs
new file mode 100644
index 0000000..1bc3954
--- /dev/null
+++ b/Check.Main/Common/StatisticsExporter.cs
@@ -0,0 +1,82 @@
+using Check.Main.Camera;
+using NPOI.SS.UserModel;
+using NPOI.XSSF.UserModel;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace Check.Main.Common
+{
+ public static class StatisticsExporter
+ {
+ ///
+ /// 将给定的统计数据导出到指定的Excel文件路径。
+ ///
+ /// 要导出的统计数据对象。
+ /// 自定义的文件名部分(如 "Reset" 或 "Shutdown")。
+ public static void ExportToExcel(StatisticsData data, string customFileName)
+ {
+ if (data.TotalCount == 0) return; // 如果没有数据,则不导出
+
+ try
+ {
+ string directory = Path.Combine(Application.StartupPath, "Statistics");
+ Directory.CreateDirectory(directory); // 确保文件夹存在
+
+ string fileName = $"Statistics_{customFileName}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.xlsx";
+ string filePath = Path.Combine(directory, fileName);
+
+ // 创建工作簿和工作表
+ IWorkbook workbook = new XSSFWorkbook();
+ ISheet sheet = workbook.CreateSheet("生产统计");
+
+ // --- 创建样式 (可选,但能让表格更好看) ---
+ IFont boldFont = workbook.CreateFont();
+ boldFont.IsBold = true;
+ ICellStyle headerStyle = workbook.CreateCellStyle();
+ headerStyle.SetFont(boldFont);
+
+ // --- 创建表头 ---
+ IRow headerRow = sheet.CreateRow(0);
+ headerRow.CreateCell(0).SetCellValue("项目");
+ headerRow.CreateCell(1).SetCellValue("数值");
+ headerRow.GetCell(0).CellStyle = headerStyle;
+ headerRow.GetCell(1).CellStyle = headerStyle;
+
+ // --- 填充数据 ---
+ sheet.CreateRow(1).CreateCell(0).SetCellValue("良品数 (OK)");
+ sheet.GetRow(1).CreateCell(1).SetCellValue(data.GoodCount);
+
+ sheet.CreateRow(2).CreateCell(0).SetCellValue("不良品数 (NG)");
+ sheet.GetRow(2).CreateCell(1).SetCellValue(data.NgCount);
+
+ sheet.CreateRow(3).CreateCell(0).SetCellValue("产品总数");
+ sheet.GetRow(3).CreateCell(1).SetCellValue(data.TotalCount);
+
+ sheet.CreateRow(4).CreateCell(0).SetCellValue("良率 (Yield)");
+ sheet.GetRow(4).CreateCell(1).SetCellValue(data.YieldRate.ToString("P2"));
+
+ // 自动调整列宽
+ sheet.AutoSizeColumn(0);
+ sheet.AutoSizeColumn(1);
+
+ // --- 写入文件 ---
+ using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
+ {
+ workbook.Write(fs);
+ }
+
+ ThreadSafeLogger.Log($"统计数据已成功导出到: {filePath}");
+ }
+ catch (Exception ex)
+ {
+ ThreadSafeLogger.Log($"[ERROR] 导出统计数据失败: {ex.Message}");
+ MessageBox.Show($"导出统计数据失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+}
diff --git a/Check.Main/Common/ThreadSafeLogger.cs b/Check.Main/Common/ThreadSafeLogger.cs
new file mode 100644
index 0000000..2d22f5b
--- /dev/null
+++ b/Check.Main/Common/ThreadSafeLogger.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Check.Main.Common
+{
+ ///
+ /// 一个线程安全的、基于队列的日志记录器。
+ /// 使用一个独立的后台线程来处理文件写入,避免业务线程阻塞。
+ ///
+ public static class ThreadSafeLogger
+ {
+ // 使用线程安全的队列作为日志消息的缓冲区
+ private static readonly BlockingCollection _logQueue = new BlockingCollection();
+
+ // 日志写入线程
+ private static Thread _logWriterThread;
+
+ private static StreamWriter _logFileWriter;
+
+ // 事件,用于将格式化后的日志消息广播给UI等监听者
+ public static event Action OnLogMessage;
+
+ ///
+ /// 初始化日志记录器,启动后台写入线程。
+ ///
+ public static void Initialize()
+ {
+ try
+ {
+ string logDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
+ Directory.CreateDirectory(logDirectory);
+
+ string logFileName = $"Log_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.txt";
+ string logFilePath = Path.Combine(logDirectory, logFileName);
+
+ _logFileWriter = new StreamWriter(logFilePath, append: true, encoding: Encoding.UTF8) { AutoFlush = true };
+
+ // 创建并启动后台线程
+ _logWriterThread = new Thread(ProcessLogQueue)
+ {
+ IsBackground = true, // 设置为后台线程,这样主程序退出时它会自动终止
+ Name = "LogWriterThread"
+ };
+ _logWriterThread.Start();
+
+ Log("日志系统已初始化。");
+ }
+ catch (Exception ex)
+ {
+ // 如果初始化失败,尝试通过事件通知UI
+ OnLogMessage?.Invoke($"[CRITICAL] 日志系统初始化失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 将一条日志消息添加到队列中。这个方法是线程安全的,且执行速度非常快。
+ ///
+ /// 原始日志消息。
+ public static void Log(string message)
+ {
+ string formattedMessage = $"[{DateTime.Now:HH:mm:ss.fff}] {message}";
+ _logQueue.Add(formattedMessage);
+ }
+
+ ///
+ /// 后台线程的工作方法。它会持续不断地从队列中取出消息并处理。
+ ///
+ private static void ProcessLogQueue()
+ {
+ // GetConsumingEnumerable会阻塞等待,直到有新的项加入队列或队列被标记为已完成
+ foreach (string message in _logQueue.GetConsumingEnumerable())
+ {
+ try
+ {
+ // 1. 写入文件
+ _logFileWriter?.WriteLine(message);
+
+ // 2. 触发事件,通知UI
+ OnLogMessage?.Invoke(message);
+ }
+ catch
+ {
+ // 忽略在日志线程本身发生的写入错误
+ }
+ }
+ }
+
+ ///
+ /// 关闭日志记录器,释放资源。
+ ///
+ public static void Shutdown()
+ {
+ Log("日志系统正在关闭...");
+
+ // 标记队列不再接受新的项目。这会让ProcessLogQueue中的循环在处理完所有剩余项后自然结束。
+ _logQueue.CompleteAdding();
+
+ // 等待日志线程处理完所有剩余的日志,最多等待2秒
+ _logWriterThread?.Join(2000);
+
+ // 关闭文件流
+ _logFileWriter?.Close();
+ _logFileWriter?.Dispose();
+ }
+ }
+}
diff --git a/Check.Main/Dispatch/ProductManager.cs b/Check.Main/Dispatch/ProductManager.cs
new file mode 100644
index 0000000..262094b
--- /dev/null
+++ b/Check.Main/Dispatch/ProductManager.cs
@@ -0,0 +1,243 @@
+using Check.Main.Common;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Xml;
+using System.Xml.Serialization;
+
+namespace Check.Main.Dispatch
+{
+ public static class ProductManager
+ {
+ private static readonly string _productRootPath = Path.Combine(Application.StartupPath, "Product");
+ private static readonly string _productListFilePath = Path.Combine(Application.StartupPath, "products.json");
+
+ // --- 公共属性和事件 ---
+ public static List ProductList { get; private set; } = new List();
+ public static string CurrentProductName { get; private set; }
+ public static ProcessConfig CurrentConfig { get; private set; }
+
+ ///
+ /// 当产品切换或配置加载后触发。
+ ///
+ public static event Action OnProductChanged;
+
+ ///
+ /// 静态构造函数,在程序启动时自动执行。
+ ///
+ static ProductManager()
+ {
+ Directory.CreateDirectory(_productRootPath); // 确保Product文件夹存在
+ LoadProductList();
+ // 默认加载列表中的第一个产品,或者创建一个默认的
+ SwitchToProduct(ProductList.FirstOrDefault() ?? "DefaultProduct");
+ }
+
+ ///
+ /// 切换到指定的产品,并加载其配置。
+ ///
+ public static bool SwitchToProduct(string productName)
+ {
+ if (string.IsNullOrWhiteSpace(productName)) return false;
+
+ ThreadSafeLogger.Log($"正在切换到产品: {productName}");
+ var config = LoadConfigForProduct(productName);
+ if (config == null)
+ {
+ // 如果加载失败(例如新创建的产品还没有配置文件),则创建一个新的
+ config = new ProcessConfig();
+ }
+
+ CurrentProductName = productName;
+ CurrentConfig = config;
+
+ // 广播产品已变更的通知
+ OnProductChanged?.Invoke();
+ return true;
+ }
+
+ ///
+ /// 添加一个新产品。
+ ///
+ public static bool AddNewProduct(string newProductName)
+ {
+ if (string.IsNullOrWhiteSpace(newProductName) || ProductList.Contains(newProductName))
+ {
+ return false; // 名称无效或已存在
+ }
+
+ // 创建一个全新的、空的配置
+ var newConfig = new ProcessConfig();
+
+ // 保存这个新产品的空配置,这也会创建文件夹
+ if (SaveConfigForProduct(newProductName, newConfig))
+ {
+ ProductList.Add(newProductName);
+ SaveProductList(); // 更新产品列表文件
+ SwitchToProduct(newProductName); // 创建后立即切换到新产品
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// 删除指定的产品及其所有相关配置。
+ ///
+ /// 要删除的产品名称。
+ /// 成功删除返回 true,否则返回 false。
+ public static bool DeleteProduct(string productNameToDelete)
+ {
+ if (string.IsNullOrWhiteSpace(productNameToDelete) || !ProductList.Contains(productNameToDelete))
+ {
+ ThreadSafeLogger.Log($"[警告] 尝试删除一个不存在的产品: {productNameToDelete}");
+ return false; // 产品不存在
+ }
+
+ ThreadSafeLogger.Log($"正在删除产品: {productNameToDelete}...");
+ try
+ {
+ // 1. 从产品列表中移除
+ ProductList.Remove(productNameToDelete);
+ SaveProductList(); // 更新列表文件
+
+ // 2. 删除对应的配置文件夹
+ var safeFolderName = GetSafeFolderName(productNameToDelete);
+ var productDir = Path.Combine(_productRootPath, safeFolderName);
+ if (Directory.Exists(productDir))
+ {
+ Directory.Delete(productDir, true); // true 表示递归删除所有子文件和子文件夹
+ }
+
+ ThreadSafeLogger.Log($"产品 '{productNameToDelete}' 已成功删除。");
+
+ // 3. 如果被删除的是当前活动产品,则需要切换到一个新的有效产品
+ if (CurrentProductName == productNameToDelete)
+ {
+ // 切换到列表中的第一个产品,或者如果列表为空,则创建一个默认产品
+ string nextProduct = ProductList.FirstOrDefault() ?? "DefaultProduct";
+ SwitchToProduct(nextProduct);
+ }
+ else
+ {
+ // 如果删除的不是当前产品,我们仍然需要触发一次事件,
+ // 以便UI(主要是下拉列表)能够刷新它的数据源。
+ OnProductChanged?.Invoke();
+ }
+ return true;
+ }
+ catch (Exception ex)
+ {
+ ThreadSafeLogger.Log($"[错误] 删除产品 '{productNameToDelete}' 失败: {ex.Message}");
+ // 如果出错,最好把刚删除的项加回来,保持状态一致性
+ if (!ProductList.Contains(productNameToDelete))
+ {
+ ProductList.Add(productNameToDelete);
+ }
+ return false;
+ }
+ }
+
+ ///
+ /// 为当前产品保存更改。
+ ///
+ public static void SaveCurrentProductConfig()
+ {
+ if (CurrentConfig != null && !string.IsNullOrWhiteSpace(CurrentProductName))
+ {
+ SaveConfigForProduct(CurrentProductName, CurrentConfig);
+ }
+ }
+
+ #region 文件操作辅助方法
+
+ private static void LoadProductList()
+ {
+ try
+ {
+ if (File.Exists(_productListFilePath))
+ {
+ var json = File.ReadAllText(_productListFilePath);
+ ProductList = JsonConvert.DeserializeObject>(json) ?? new List();
+ }
+ }
+ catch (Exception ex)
+ {
+ ThreadSafeLogger.Log($"[错误] 加载产品列表失败: {ex.Message}");
+ ProductList = new List();
+ }
+ }
+
+ private static void SaveProductList()
+ {
+ try
+ {
+ var json = JsonConvert.SerializeObject(ProductList, Newtonsoft.Json.Formatting.Indented);
+ File.WriteAllText(_productListFilePath, json);
+ }
+ catch (Exception ex)
+ {
+ ThreadSafeLogger.Log($"[错误] 保存产品列表失败: {ex.Message}");
+ }
+ }
+
+ private static ProcessConfig LoadConfigForProduct(string productName)
+ {
+ var safeFolderName = GetSafeFolderName(productName);
+ var configPath = Path.Combine(_productRootPath, safeFolderName, "config.xml");
+
+ if (!File.Exists(configPath)) return null;
+
+ try
+ {
+ XmlSerializer serializer = new XmlSerializer(typeof(ProcessConfig));
+ using (var fs = new FileStream(configPath, FileMode.Open, FileAccess.Read))
+ {
+ return (ProcessConfig)serializer.Deserialize(fs);
+ }
+ }
+ catch (Exception ex)
+ {
+ ThreadSafeLogger.Log($"[错误] 加载产品 '{productName}' 的配置失败: {ex.Message}");
+ return null;
+ }
+ }
+
+ private static bool SaveConfigForProduct(string productName, ProcessConfig config)
+ {
+ try
+ {
+ var safeFolderName = GetSafeFolderName(productName);
+ var productDir = Path.Combine(_productRootPath, safeFolderName);
+ Directory.CreateDirectory(productDir); // 确保文件夹存在
+
+ var configPath = Path.Combine(productDir, "config.xml");
+
+ XmlSerializer serializer = new XmlSerializer(typeof(ProcessConfig));
+ using (var fs = new FileStream(configPath, FileMode.Create, FileAccess.Write))
+ {
+ serializer.Serialize(fs, config);
+ }
+ return true;
+ }
+ catch (Exception ex)
+ {
+ ThreadSafeLogger.Log($"[错误] 保存产品 '{productName}' 的配置失败: {ex.Message}");
+ return false;
+ }
+ }
+
+ private static string GetSafeFolderName(string productName)
+ {
+ // 移除所有不适合做文件夹名称的字符
+ string invalidChars = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
+ Regex r = new Regex(string.Format("[{0}]", Regex.Escape(invalidChars)));
+ return r.Replace(productName, "");
+ }
+
+ #endregion
+ }
+}
diff --git a/Check.Main/FrmMain.Designer.cs b/Check.Main/FrmMain.Designer.cs
new file mode 100644
index 0000000..a3333d6
--- /dev/null
+++ b/Check.Main/FrmMain.Designer.cs
@@ -0,0 +1,180 @@
+namespace Check.Main
+{
+ partial class FrmMain
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows 窗体设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmMain));
+ menuStrip1 = new MenuStrip();
+ 文件ToolStripMenuItem = new ToolStripMenuItem();
+ 退出ToolStripMenuItem = new ToolStripMenuItem();
+ ToolStripMenuSaveLayou = new ToolStripMenuItem();
+ 视图ToolStripMenuItem = new ToolStripMenuItem();
+ 配置ToolStripMenuItem = new ToolStripMenuItem();
+ 日志ToolStripMenuItem = new ToolStripMenuItem();
+ 控制面板ToolStripMenuItem = new ToolStripMenuItem();
+ statusStrip1 = new StatusStrip();
+ uiTableLayoutPanel1 = new Sunny.UI.UITableLayoutPanel();
+ dockPanel1 = new WeifenLuo.WinFormsUI.Docking.DockPanel();
+ menuStrip1.SuspendLayout();
+ uiTableLayoutPanel1.SuspendLayout();
+ SuspendLayout();
+ //
+ // menuStrip1
+ //
+ menuStrip1.Items.AddRange(new ToolStripItem[] { 文件ToolStripMenuItem, 视图ToolStripMenuItem, 控制面板ToolStripMenuItem });
+ menuStrip1.Location = new Point(0, 0);
+ menuStrip1.Name = "menuStrip1";
+ menuStrip1.Padding = new Padding(7, 3, 0, 3);
+ menuStrip1.Size = new Size(933, 27);
+ menuStrip1.TabIndex = 0;
+ menuStrip1.Text = "MainMenu";
+ //
+ // 文件ToolStripMenuItem
+ //
+ 文件ToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { 退出ToolStripMenuItem, ToolStripMenuSaveLayou });
+ 文件ToolStripMenuItem.Name = "文件ToolStripMenuItem";
+ 文件ToolStripMenuItem.Size = new Size(44, 21);
+ 文件ToolStripMenuItem.Text = "文件";
+ //
+ // 退出ToolStripMenuItem
+ //
+ 退出ToolStripMenuItem.Name = "退出ToolStripMenuItem";
+ 退出ToolStripMenuItem.Size = new Size(124, 22);
+ 退出ToolStripMenuItem.Text = "退出";
+ //
+ // ToolStripMenuSaveLayou
+ //
+ ToolStripMenuSaveLayou.Name = "ToolStripMenuSaveLayou";
+ ToolStripMenuSaveLayou.Size = new Size(124, 22);
+ ToolStripMenuSaveLayou.Text = "保存布局";
+ ToolStripMenuSaveLayou.Click += ToolStripMenuSaveLayou_Click;
+ //
+ // 视图ToolStripMenuItem
+ //
+ 视图ToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { 配置ToolStripMenuItem, 日志ToolStripMenuItem });
+ 视图ToolStripMenuItem.Name = "视图ToolStripMenuItem";
+ 视图ToolStripMenuItem.Size = new Size(44, 21);
+ 视图ToolStripMenuItem.Text = "视图";
+ //
+ // 配置ToolStripMenuItem
+ //
+ 配置ToolStripMenuItem.Name = "配置ToolStripMenuItem";
+ 配置ToolStripMenuItem.Size = new Size(180, 22);
+ 配置ToolStripMenuItem.Text = "配置";
+ 配置ToolStripMenuItem.Click += 配置ToolStripMenuItem_Click;
+ //
+ // 日志ToolStripMenuItem
+ //
+ 日志ToolStripMenuItem.Name = "日志ToolStripMenuItem";
+ 日志ToolStripMenuItem.Size = new Size(180, 22);
+ 日志ToolStripMenuItem.Text = "日志";
+ 日志ToolStripMenuItem.Click += 日志ToolStripMenuItem_Click;
+ //
+ // 控制面板ToolStripMenuItem
+ //
+ 控制面板ToolStripMenuItem.Name = "控制面板ToolStripMenuItem";
+ 控制面板ToolStripMenuItem.Size = new Size(68, 21);
+ 控制面板ToolStripMenuItem.Text = "控制面板";
+ 控制面板ToolStripMenuItem.Click += 控制面板ToolStripMenuItem_Click;
+ //
+ // statusStrip1
+ //
+ statusStrip1.Location = new Point(0, 616);
+ statusStrip1.Name = "statusStrip1";
+ statusStrip1.Padding = new Padding(1, 0, 16, 0);
+ statusStrip1.Size = new Size(933, 22);
+ statusStrip1.TabIndex = 2;
+ statusStrip1.Text = "statusStrip1";
+ //
+ // uiTableLayoutPanel1
+ //
+ uiTableLayoutPanel1.ColumnCount = 2;
+ uiTableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 76F));
+ uiTableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 24F));
+ uiTableLayoutPanel1.Controls.Add(dockPanel1, 0, 0);
+ uiTableLayoutPanel1.Dock = DockStyle.Fill;
+ uiTableLayoutPanel1.Location = new Point(0, 27);
+ uiTableLayoutPanel1.Margin = new Padding(4);
+ uiTableLayoutPanel1.Name = "uiTableLayoutPanel1";
+ uiTableLayoutPanel1.RowCount = 1;
+ uiTableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
+ uiTableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
+ uiTableLayoutPanel1.Size = new Size(933, 589);
+ uiTableLayoutPanel1.TabIndex = 3;
+ uiTableLayoutPanel1.TagString = null;
+ //
+ // dockPanel1
+ //
+ uiTableLayoutPanel1.SetColumnSpan(dockPanel1, 2);
+ dockPanel1.Dock = DockStyle.Fill;
+ dockPanel1.Location = new Point(4, 4);
+ dockPanel1.Margin = new Padding(4);
+ dockPanel1.Name = "dockPanel1";
+ dockPanel1.Size = new Size(925, 581);
+ dockPanel1.TabIndex = 0;
+ //
+ // FrmMain
+ //
+ AutoScaleDimensions = new SizeF(7F, 17F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(933, 638);
+ Controls.Add(uiTableLayoutPanel1);
+ Controls.Add(statusStrip1);
+ Controls.Add(menuStrip1);
+ Icon = (Icon)resources.GetObject("$this.Icon");
+ MainMenuStrip = menuStrip1;
+ Margin = new Padding(4);
+ Name = "FrmMain";
+ Text = "星科瑞升视觉检测设备";
+ WindowState = FormWindowState.Maximized;
+ FormClosing += FrmMain_FormClosing;
+ Load += FrmMain_Load;
+ menuStrip1.ResumeLayout(false);
+ menuStrip1.PerformLayout();
+ uiTableLayoutPanel1.ResumeLayout(false);
+ ResumeLayout(false);
+ PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.MenuStrip menuStrip1;
+ private System.Windows.Forms.StatusStrip statusStrip1;
+ private System.Windows.Forms.ToolStripMenuItem 文件ToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem 退出ToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem 视图ToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem 配置ToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem 日志ToolStripMenuItem;
+ private Sunny.UI.UITableLayoutPanel uiTableLayoutPanel1;
+ private WeifenLuo.WinFormsUI.Docking.DockPanel dockPanel1;
+ private System.Windows.Forms.ToolStripMenuItem 控制面板ToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem ToolStripMenuSaveLayou;
+ }
+}
+
diff --git a/Check.Main/FrmMain.cs b/Check.Main/FrmMain.cs
new file mode 100644
index 0000000..8a5f002
--- /dev/null
+++ b/Check.Main/FrmMain.cs
@@ -0,0 +1,297 @@
+using Check.Main.Camera;
+using Check.Main.Common;
+using Check.Main.UI;
+using HslCommunication;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using WeifenLuo.WinFormsUI.Docking;
+
+namespace Check.Main
+{
+ public partial class FrmMain : Form
+ {
+ // private FrmCamConfig _formCameraConfig;
+ private FrmConfig _frmConfig;
+ private FrmLog _formLog;
+ private ThemeBase _theme = new VS2015BlueTheme(); // 外观主题
+ public DockPanel MainDockPanel => this.dockPanel1;
+
+ private FormControlPanel _formControlPanel;
+
+ private FormStatistics _formStatistics;
+
+ private readonly string _layoutConfigFile = Path.Combine(Application.StartupPath, "layout.xml");
+ //用于反序列化时创建窗体的委托
+ private DeserializeDockContent _deserializeDockContent;
+
+ public FrmMain()
+ {
+ InitializeComponent();
+ dockPanel1.Theme = _theme;
+ IsMdiContainer = true;
+ _deserializeDockContent = new DeserializeDockContent(GetContentFromPersistString);
+ }
+
+ private void FrmMain_Load(object sender, EventArgs e)
+ {
+ EasyPlcClient easyPlcClient = new EasyPlcClient("127.0.0.1", 502, 1);
+ easyPlcClient.ConnectAsync();
+
+ _frmConfig = new FrmConfig { Text = "主程序配置" };
+ _formLog = new FrmLog { Text = "运行日志" };
+ _formStatistics = new FormStatistics { Text = "生产统计" };
+ _formControlPanel = new FormControlPanel { Text = "控制面板" };
+ // 为每个子窗体订阅 FormClosing 事件
+ _frmConfig.FormClosing += DockContent_FormClosing;
+ _formLog.FormClosing += DockContent_FormClosing;
+ _formStatistics.FormClosing += DockContent_FormClosing;
+ _formControlPanel.FormClosing += DockContent_FormClosing;
+
+ ThreadSafeLogger.Initialize();
+ ThreadSafeLogger.OnLogMessage += (msg) => { _formLog.AddLog(msg); };
+
+ // 2. 尝试加载布局文件
+ if (File.Exists(_layoutConfigFile))
+ {
+ try
+ {
+ // 使用委托加载布局
+ dockPanel1.LoadFromXml(_layoutConfigFile, _deserializeDockContent);
+ ThreadSafeLogger.Log("成功加载用户布局。");
+ }
+ catch (Exception ex)
+ {
+ ThreadSafeLogger.Log($"加载布局失败: {ex.Message}。将使用默认布局。");
+ // 如果加载失败,则使用默认布局
+ ShowDefaultLayout();
+ }
+ }
+ else
+ {
+ // 3. 如果布局文件不存在,则显示默认布局
+ ThreadSafeLogger.Log("未找到布局文件,使用默认布局。");
+ ShowDefaultLayout();
+ }
+ }
+ ///
+ /// 将相机名称添加到状态栏
+ ///
+ public void AddCameraToStatusStrip(string name)
+ {
+ if (statusStrip1.InvokeRequired)
+ {
+ statusStrip1.Invoke(new Action(() => AddCameraToStatusStrip(name)));
+ return;
+ }
+ var label = new ToolStripStatusLabel(name)
+ {
+ Name = "status_" + name,
+ BorderSides = ToolStripStatusLabelBorderSides.All,
+ Spring = false,
+ };
+ label.Click += StatusLabel_Click;
+ statusStrip1.Items.Add(label);
+ }
+ private void 控制面板ToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (_formControlPanel == null || _formControlPanel.IsDisposed)
+ {
+ _formControlPanel = new FormControlPanel { Text = "控制面板" };
+ _formControlPanel.FormClosing += DockContent_FormClosing;
+ }
+ _formControlPanel.Show(this.dockPanel1);
+ }
+ ///
+ /// 清空状态栏中的相机名称
+ ///
+ public void ClearStatusStrip()
+ {
+ if (statusStrip1.InvokeRequired)
+ {
+ statusStrip1.Invoke(new Action(ClearStatusStrip));
+ return;
+ }
+ // 从后往前删,避免索引问题
+ for (int i = statusStrip1.Items.Count - 1; i >= 0; i--)
+ {
+ if (statusStrip1.Items[i] is ToolStripStatusLabel && statusStrip1.Items[i].Name.StartsWith("status_"))
+ {
+ statusStrip1.Items.RemoveAt(i);
+ }
+ }
+ }
+
+ private void StatusLabel_Click(object sender, EventArgs e)
+ {
+ if (sender is ToolStripStatusLabel label)
+ {
+ string cameraName = label.Text;
+ ThreadSafeLogger.Log($"用户点击状态栏标签: {cameraName}");
+
+ bool foundOriginal = false;
+ bool foundResult = false;
+
+ // 1. 尝试重新显示“原图”窗口
+ if (CameraManager.OriginalImageDisplays.TryGetValue(cameraName, out var originalDisplayForm))
+ {
+ // 使用 Show() 方法来重新激活或显示隐藏的窗口
+ // 传入 DockPanel 确保它知道在哪里显示
+ originalDisplayForm.Show(this.dockPanel1);
+ originalDisplayForm.Activate(); // 调用 Activate() 确保它成为当前焦点窗口
+ foundOriginal = true;
+ }
+
+ // 2. 尝试重新显示“结果”窗口
+ if (CameraManager.ResultImageDisplays.TryGetValue(cameraName, out var resultDisplayForm))
+ {
+ resultDisplayForm.Show(this.dockPanel1);
+ resultDisplayForm.Activate();
+ foundResult = true;
+ }
+
+ // 3. 提供反馈
+ if (foundOriginal || foundResult)
+ {
+ ThreadSafeLogger.Log($"已重新激活相机 '{cameraName}' 的显示窗口。");
+ }
+ else
+ {
+ ThreadSafeLogger.Log($"[警告] 未能找到相机 '{cameraName}' 对应的活动显示窗口。可能设备已关闭。");
+ }
+ }
+ }
+
+ ///
+ /// 根据持久化字符串创建或返回对应的窗体实例。
+ /// 这是DockPanel Suite反序列化布局时需要的回调方法。
+ ///
+ /// 在XML中代表一个窗体的唯一字符串(通常是其类型名)。
+ /// 对应的窗体实例。
+ private IDockContent GetContentFromPersistString(string persistString)
+ {
+ if (persistString == typeof(FormControlPanel).ToString())
+ return _formControlPanel;
+ if (persistString == typeof(FrmConfig).ToString())
+ return _frmConfig;
+ if (persistString == typeof(FrmLog).ToString())
+ return _formLog;
+ if (persistString == typeof(FormStatistics).ToString())
+ return _formStatistics;
+
+ // 对于图像显示窗口,由于它们是动态创建的,情况会更复杂。
+ // 在当前设计中,我们不保存图像窗口的布局,它们会在应用相机配置时重新创建。
+ // 如果需要保存它们,需要在CameraManager中管理它们的持久化字符串。
+ // 目前的设计下,返回null是安全的。
+ return null;
+ }
+
+ ///
+ /// 显示程序的默认窗口布局。
+ ///
+ private void ShowDefaultLayout()
+ {
+ // 确保所有窗体都未被意外关闭
+ if (_formControlPanel.IsDisposed) _formControlPanel = new FormControlPanel();
+ if (_frmConfig.IsDisposed) _frmConfig = new FrmConfig();
+ if (_formLog.IsDisposed) _formLog = new FrmLog();
+ if (_formStatistics.IsDisposed) _formStatistics = new FormStatistics();
+
+ // 显示默认窗口
+ _frmConfig.Show(dockPanel1, DockState.DockLeft);
+ _formLog.Show(dockPanel1, DockState.DockBottom);
+ _formControlPanel.Show(dockPanel1, DockState.DockRight);
+ _formStatistics.Show(dockPanel1, DockState.DockTop);
+ }
+
+ ///
+ /// 【新增】保存当前窗口布局到XML文件。
+ ///
+ private void SaveLayout()
+ {
+ try
+ {
+ // 将当前DockPanel的布局保存到指定文件
+ dockPanel1.SaveAsXml(_layoutConfigFile);
+ ThreadSafeLogger.Log("布局已成功保存!");
+ //MessageBox.Show("布局已成功保存!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ }
+ catch (Exception ex)
+ {
+ ThreadSafeLogger.Log("保存布局失败: " + ex.Message);
+ //MessageBox.Show("保存布局失败: " + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ if (_formStatistics != null && !_formStatistics.IsDisposed)
+ {
+ StatisticsExporter.ExportToExcel(_formStatistics.CurrentStatistics, "Shutdown");
+ }
+
+ CameraManager.Shutdown();
+ ThreadSafeLogger.Shutdown();
+ }
+
+ private void ToolStripMenuSaveLayou_Click(object sender, EventArgs e)
+ {
+ SaveLayout();
+ }
+
+ private void 配置ToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ //_frmConfig.Show();
+ // 如果窗体因意外被销毁,则重新创建它
+ if (_frmConfig == null || _frmConfig.IsDisposed)
+ {
+ _frmConfig = new FrmConfig() { Text = "主程序配置" };
+ _frmConfig.FormClosing += DockContent_FormClosing;
+ }
+ // 调用 Show() 会自动处理隐藏和显示逻辑
+ _frmConfig.Show(this.dockPanel1);
+ }
+ private void 日志ToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (_formLog == null || _formLog.IsDisposed)
+ {
+ _formLog = new FrmLog { Text = "运行日志" };
+ _formLog.FormClosing += DockContent_FormClosing;
+ }
+ _formLog.Show(this.dockPanel1);
+ }
+
+ ///
+ /// 处理所有可停靠子窗体关闭事件的通用方法。
+ /// 通过取消关闭并隐藏窗口,来实现“假关闭”,以便后续能重新显示。
+ ///
+ private void DockContent_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ // 检查关闭原因是否为用户点击了关闭按钮
+ if (e.CloseReason == CloseReason.UserClosing)
+ {
+ // 1. 取消真正的关闭(Dispose)操作,防止窗体被销毁
+ e.Cancel = true;
+
+ // 2. 将窗口隐藏起来
+ // 我们需要将 sender 转换为 DockContent 类型来访问 Hide() 方法
+ if (sender is DockContent dockContent)
+ {
+ if (dockContent is FormImageDisplay imageDisplay)
+ {
+ ThreadSafeLogger.Log($"用户关闭了窗口 '{imageDisplay.Text}',已将其隐藏。");
+ }
+ dockContent.Hide();
+ }
+ }
+ }
+
+
+ }
+}
diff --git a/Check.Main/FrmMain.resx b/Check.Main/FrmMain.resx
new file mode 100644
index 0000000..3e6d304
--- /dev/null
+++ b/Check.Main/FrmMain.resx
@@ -0,0 +1,3244 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ 250, 17
+
+
+
+
+ AAABAAkAEBAAAAEAIABoBAAAlgAAABgYAAABACAAiAkAAP4EAAAgIAAAAQAgAKgQAACGDgAAMDAAAAEA
+ IACoJQAALh8AAEBAAAABACAAKEIAANZEAABISAAAAQAgAIhUAAD+hgAAYGAAAAEAIAColAAAhtsAAICA
+ AAABACAAKAgBAC5wAQAAAAAAAQAgACphAABWeAIAKAAAABAAAAAgAAAAAQAgAAAAAAAABAAAIy4AACMu
+ AAAAAAAAAAAAAI1CAACNQgBJjUIA6I1CAPONQgDujUIAUo1CAACOQQAAAAAAAI1CAACNQgAHjUIArI1C
+ APSNQgDqjUIASY1CAACNQgAAjUIAC41CALKNQgD/jUIA/41CAJGMQwAAjkIAAAAAAACNQgAAjUIAHY1C
+ ANyNQgD/jUIA241CAB2NQgAAjUIAAI1CAACNQgBNjUIA9o1CAP+NQgDMjUIAEo1CAACNQgAAjUIAAI1C
+ AESNQgD2jUIA/41CAKaNQgADjUIAAI9EAACNQgAAjUIAEI1CAMeNQgD/jUIA741CADWNQgAAjUIAAI1C
+ AACNQgBvjUIA/41CAP+NQgBwjUIAAI1CAACNQgAAjUIAAI1CAACNQgCEjUIA/41CAP6NQgB1jUIAKI1C
+ ABGMQwAAjUIAlY1CAP+NQgD1jUIAQI1CAACLQgAAjUIAAIxCAACNQgBNjUIApo1CAPWNQgD/jUIAwY1C
+ ANaNQgDLjUIAio1CAMyNQgD/jUIA4o1CACKNQgAAAAAAAI1CAACNQgAcjUIAmY1CAH6NQgDbjUIA/41C
+ ANKNQgDVjUIA/41CAP+NQgD/jUIA/41CAMyNQgAOjUIAAI1CAACMQgAAjUIAG41CAA+NQgAFjUIAtY1C
+ AP+NQgDcjUIAUY1CAJGNQgDmjUIA/41CAP+NQgDjjUIAQY1CAACNQgAAjUAAAY1CAFGNQgAKjUIAAI1C
+ AI6NQgD/jUIA7Y1CAC6NQgAAjUIANI1CAK6NQgD8jUIA/41CAN2NQgA9jUIAAI1CADiNQgCrjUIARoM+
+ AACNQgBpjUIA/41CAPiNQgBIjUIAAI1CAACNQgANjUIAjo1CAPyNQgD/jUIAyY1CACCNQgA6jUIAx41C
+ AKWNQgAKjUIATI1CAPyNQgD+jUIAWo1CAACNQgAAjUIAAI1CAA2NQgCxjUIA/41CAP+NQgCKkEEAAI1C
+ AF2NQgCcjUIAl41CAFWNQgDbjUIA/41CAGWNQgAAiD0AAI1CAACNQgAAjUIAYI1CAP+NQgD/jUIA4I1C
+ AAGNQgAPjUIAGY1CAKqNQgDfjUIAso1CAKuNQgBOjUIAAI1CAACNQgAAjUIACY1CAI+NQgD/jUIA/41C
+ APeNQgAAjUIAAI1CAACNQgASjUIAio1CAO+NQgDtjUIAwY1CAJqNQgCBjUIAhY1CALmNQgD3jUIA/41C
+ AP+NQgDPAAAAAI5CAACNQgAAjUIAAI5CAAONQgBFjUIAsY1CAPKNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDgjUIATwAAAAAAAAAAi0IAAI1CAACNQgAAjUIAAI1CAAuNQgBEjUIAkI1CAMyNQgDsjUIA9Y1C
+ AOONQgCnjUIAPolDAAAAgAAAAIAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIAAAADAAAAAKAAAABgAAAAwAAAAAQAgAAAAAAAACQAAIy4AACMuAAAAAAAAAAAAAI1C
+ AACNRAABjUIAgY1CAOyNQgDqjUIA6Y1CAOyNQgC7jUIAEY1CAACAgAAAAAAAAAAAAAAAAAAAjkAAAI1C
+ AACNQgAmjUIA0Y1CAOiNQgDmjUIA6Y1CAHaNQgAAjUMAAI9AAACNQgAAjUIALI1CAN6NQgD/jUIA/41C
+ AP+NQgDvjUIAN41CAACPQAAAAAAAAAAAAAAAAAAAiUEAAI1CAACNQgBRjUIA+41CAP+NQgD/jUIA9I1C
+ AEONQgAAjkEAAItGAACNQQAAjEIAAI1CAHqNQgD/jUIA/41CAP+NQgD/jUIAdI1CAACHSgAAAAAAAAAA
+ AAAAAAAAjEEAAI1DAACNQgCGjUIA/41CAP+NQgD/jUIAyo1CABGNQgAAAAAAAAAAAACNQQAAjUIAAI1C
+ ACKNQgDajUIA/41CAP+NQgD/jUIAs45CAAeOQgAAAAAAAAAAAAAAAAAAjUIAAI1CAAmNQgC5jUIA/41C
+ AP+NQgD/jUIAkZBBAACLQwAAAAAAAAAAAACPRAAAjkIAAIpDAACNQgCNjUIA/41CAP+NQgD/jUIA4Y1C
+ ACONQgAAAAAAAAAAAAAAAAAAjUIAAI1CACCNQgDfjUIA/41CAP+NQgD8jUIAWo1CAACMQgAAAAAAAAAA
+ AAAAAAAAjkIAAI1CAACNQgA/jUIA8o1CAP+NQgD/jUIA+Y1CAE+NQgAAjUIAAI5DAACLQAAAjUIAAI1C
+ AD6NQgD0jUIA/41CAP+NQgDpjUIALY1CAACNQgAAAAAAAAAAAAAAAAAAjUIAAI1CAACNQgAOjUIAxY1C
+ AP+NQgD/jUIA/41CAISMQgADhDMAAI1CAACNQgAAjUIAAI1CAGCNQgD+jUIA/41CAP+NQgDHjUIAD41C
+ AAAAAAAAAAAAAAAAAACOQwAAjUIAAI1CAACNQgAbjUIAl41CAP+NQgD/jUIA/41CALqNQgCHjUIAmo1C
+ AGSNQgAsj0IABI1CAISNQgD/jUIA/41CAP+NQgChjkIAAY1CAAAAAAAAAAAAAAAAAACMQQAAjUIAAI1C
+ ADiNQgDIjUIAoo1CAPWNQgD/jUIA/41CANmNQgCvjUIA/41CAP6NQgDnjUIAq41CAMqNQgD/jUIA/41C
+ AP+NQgB9jEIAAI9BAAAAAAAAAAAAAAAAAACNQgAAjUIAGo1CAL2NQgDejUIAho1CAN6NQgD/jUIA/41C
+ AO6NQgCgjUIA/o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP2NQgBdjUIAAItDAAAAAAAAAAAAAI5C
+ AACNQgAAjUIAMI1CAFGNQgAcjUIAEY1CALuNQgD/jUIA/41CAPuNQgCJjUIAv41CAPeNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPmNQgBLjUIAAI9CAACLQQAAAAAAAI1CAACNQgAFjUIAH41CAACNQgAAjUIAAI1C
+ AI6NQgD/jUIA/41CAP+NQgB9jUIAD41CAE+NQgCwjUIA9o1CAP+NQgD/jUIA/41CAP+NQgC8jUIAKY1C
+ AACPRQAAjkEAAI1CAACNQgAVjUIAbI5CAASOQwAAjUIAAI1CAGeNQgD/jUIA/41CAP+NQgCdkUIAAI1C
+ AACNQgAKjUIAVo1CAM2NQgD/jUIA/41CAP+NQgD/jUIAx41CACiNQgAAjUIAAI1CAACNQgAkjUIAoY1D
+ AAiNQgAAjUIAAI1CAEWNQgD2jUIA/41CAP+NQgC6jUIACI1CAACNQgAAjUIAAI1CAB+NQgCejUIA/I1C
+ AP+NQgD/jUIA/41CALmNQgAXjUIAAI1CADaNQgCIjUIA4I1CAGqNQgAijUIAAI1CACmNQgDnjUIA/41C
+ AP+NQgDOjUIAE41CAACNQwAAizgAAI1CAACNQgAMjUIAk41CAP6NQgD/jUIA/41CAP+NQgCHjEIAAo1C
+ ADyNQgCOjUIA/I1CAMONQgArjUIAAI1CABiNQgDWjUIA/41CAP+NQgDdjUIAHY1CAAAAAAAAlEMAAIxC
+ AACNQgAAjUIAEY1CALSNQgD/jUIA/41CAP+NQgDmjUIAOY1CAACNQgAjjUIAwY1CANCNQgCBjUIADo1D
+ AAmNQgDGjUIA/41CAP+NQgDmjUIAJY1CAAAAAAAAAAAAAI1CAACNQQAAjUIAAI1CAEeNQgD0jUIA/41C
+ AP+NQgD/jUIAl41CAACNQgAWjUIAbI1CAFiNQgDsjUIAs41CAD2NQgCPjUIA8o1CAP+NQgDsjUIAKo1C
+ AAAAAAAAAAAAAAAAAACNQwAAjUIAAI1CAB2NQgDejUIA/41CAP+NQgD/jUIA3Y1CAACNQgAGjUIAII1B
+ AAKNQgBrjUIA9Y1CAOyNQgCljUIAg41CAKGNQgDAjUIAJI1CAACNQgAAjUIAAI1CAACNQgAAjUIAAI1C
+ AD6NQgDujUIA/41CAP+NQgD/jUIA9IxBAACMQQAAjEEAAI1CAACOQgADjUIAY41CAOeNQgD/jUIA7I1C
+ ALiNQgCEjUIAPo1CABqNQgAMjUIABo1CAAeNQgAVjUIAS41CAMiNQgD/jUIA/41CAP+NQgD/jUIA5ZlN
+ AACaTQAAnU8AAI1CAACNQgAAjUQAAI1CAD6NQgC/jUIA/41CAP+NQgD+jUIA741CANqNQgDFjUIAs41C
+ ALWNQgDSjUIA9Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIAogAAAAAAAAAAAAAAAAAAAACNQQAAjUEAAI1C
+ AACOQgAVjUIAd41CANuNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDSjUIALgAAAAAAAAAAAAAAAAAAAAAAAAAAjkIAAI1CAACNQgAAjkEAAI1CACSNQgB3jUIAxI1C
+ APCNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+I1CAMGNQgA6jUIAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACNQwAAjEMAAI1CAACNQgAAjUIAEo1CAEWNQgCFjUIAuo1CANuNQgDtjUIA7o1C
+ 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
+ AAyNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQgAAjUIAAI1CAE+NQgCwjUIAbo1CAD2NQgAhjUIAwo1C
+ AP+NQgD/jUIA/41CAP+NQgCvjUIAp41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgCkjT8AAo1BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAItEAACLRAABjUIAIY1CAA6NQgAAjUIAAIpD
+ AACNQgCVjUIA/41CAP+NQgD/jUIA/41CAMiNQgA8jUIAio1CANSNQgD9jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CALKNQgAPjUIAAI5CAACCQAAAAAAAAAAAAAAAAAAAjUIAAI1CABSNQgAojUIAAJo8
+ AACRQAAAjUIAAI1CAGeNQgD/jUIA/41CAP+NQgD/jUIA4I1CAB+NQAAAjUIAHI1CAGuNQgDNjUIA/o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA+41CAKKMQwAYjUIAAI1CAACMQgAAAAAAAP8AAACNQgAAjUIAOI1C
+ AHGNQgAAj0MAAIxDAACNQgAAjUIARI1CAPWNQgD/jUIA/41CAP+NQgDwjUIAOI1CAACNQgAAjUIAAI1C
+ ABuNQgB9jUIA5o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAKyNQgAYjUIAAI1CAACIRAAAjEIAAI1C
+ AACNQgBXjUIAm45DAAOOQwAAkkkAAI1CAACNQgAmjUIA5Y1CAP+NQgD/jUIA/41CAPqNQgBVjUIAAItD
+ AAD/SwAAjUIAAJg4AACNQgA7jUIAu41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAKCNQgAOjUIAAI1B
+ AACNQgAAjEIAAI1CAHeNQgDBjkIACY1CAACNQgAAjUIAAI1CABONQgDMjUIA/41CAP+NQgD/jUIA/41C
+ AHCNQgAAjUIAAAAAAACNQgAAjUIAAI1CAACOQgAWjUIAmY1CAPyNQgD/jUIA/41CAP+NQgD/jUIA/I1C
+ AH2OQAACjUEAAI1CADyNQgBzjUIA0Y1CAPCNQgCOjUIAT41CABCNQgAAjUIABY1CALCNQgD/jUIA/41C
+ AP+NQgD/jUIAh41DAACNQQAAAAAAAAAAAACPQgAAjEIAAI1CAACNQgAOjUIAmo1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA641CAECNQgAAjUIARY1CAICNQgDXjUIA/41CANiNQgBcjEIAEIxCAACiOgAAjUIAlo1C
+ AP+NQgD/jUIA/41CAP+NQgCcjUEAAY1CAAAAAAAAAAAAAAAAAAAAAAAAjUIAAI1CAACNQgAWjUIAuY1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIArI5CAAqNQgAAjEIAAI1CAHaNQgD3jUIA6I1CAHCMQwAGjUIAAI1B
+ AACNQgB9jUIA/41CAP+NQgD/jUIA/41CAKyOQgACjkEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUEAAI1C
+ AACNQgBBjUIA7o1CAP+NQgD/jUIA/41CAP+NQgDujUIAR4tBAACNQgAAjUIAWI1CAKaNQgCfjUIA+Y1C
+ AJSNQgAbjUIAAI1CAGeNQgD/jUIA/41CAP+NQgD/jUIAtY5CAAWOQgAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACMQgAAjUIAAI1CAAqNQgC6jUIA/41CAP+NQgD/jUIA/41CAP+NQgCc/wAAAI1CAACNQgA7jUIAcI1C
+ AByNQgDCjUIA/41CAMiNQgBQjUIAQI1CAMiNQgD8jUIA/41CAP+NQgC5j0IACI9BAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJI9AACPPgAAdHMAAI1CAJyNQgD/jUIA/41CAP+NQgD/jUIA/41CANgAAAAAjUIAAI1C
+ ABeNQgAujUIAAI1CADCNQgDQjUIA/41CAPWNQgCwjUIAaY1CAHONQgCvjUIA7I1CALiPQQAIj0EAAJI9
+ AAAAAAAAAAAAAAAAAACMQwAAi0EAAI1CAACNQgAMjUIAvI1CAP+NQgD/jUIA/41CAP+NQgD/jUIA8AAA
+ AACCNQAAgjYAAIQ5AACSRQAAjUIAAI1CADSNQgDJjUIA/41CAP+NQgD0jUIAvY1CAHaNQgBdjUIAUpE+
+ AAKNQgAAjUIAAI1CAACNQgAAjUIAAI1CAACNQgAAjUIACI1CAHSNQgD2jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDqAAAAAJpNAACaTgAAnk8AAJBEAACPQgAAjUIAAI1CACWNQgCrjUIA/I1CAP+NQgD/jUIA/o1C
+ AN+NQgCtjUIAe41CAFaNQgA5jUIAKI1CAB6NQgAfjUIAMI1CAF6NQgCsjUIA9o1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAMQAAAAAAAAAAAAAAAAAAAAAAAAAAI5CAAC7VAAAjUIAAI1CAA+NQgB2jUIA5Y1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA+41CAPKNQgDmjUIA2o1CANyNQgDsjUIA/I1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD6jUIAcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKRRAACMQgAAjUIAAORW
+ AACOQgA4jUIAqo1CAPSNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CALSNQgAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACOQgAAjkIAAI1CAACNQgAJjUIATY1CALCNQgDujUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDFjUIAK41CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACQQQAAi0MAAI1CAACNQgAAjUIACY1CADqNQgCDjUIAxY1CAOyNQgD9jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPuNQgDcjUIAjY1CACGNQgAAizoAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkIAAI1CAACNQwAAjUIAAIxEAACNQQASjUIAPo1C
+ AHaNQgCljUIAyI1CAN+NQgDpjUIA541CANSNQgCsjUIAbo1CACmNRQACjUIAAIlBAACNQgAAgAfwAYAH
+ 8AGAA/ABwAPwA8AD4APgA+AD4AHgB/AA4AfwAAAH4AAAB8AAAA/AAAAPgAAAD4AAAA+AAAADgAAAAQAA
+ AAAAAAAAAABAAAAAYAAAAHgAAAB8AAAAfAAAAHwAgAA4AIAAAACAAAAA+AAAAPwAAAD/AAAA/4AAAP/g
+ AAAoAAAAMAAAAGAAAAABACAAAAAAAAAkAAAjLgAAIy4AAAAAAAAAAAAAAAAAAAAAAACPQAAAcVYAAI1C
+ AGeNQgDOjUIAzY1CAM2NQgDNjUIAzY1CAM2NQgDNjUIAzY1CAM2NQgDPjUIAc449AAGNQQAAAAAAAAAA
+ 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
+ AFmNQgAyjUIAFo5EAAKNQgAAjUIAAJBCAACOQQAAjkIAH41CANeNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIAZo1CAACOQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACSSQAAjUEAAI1CAACNQQAHjEIATo1CAESNQgDRjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AJeNQgB1jUIA/41CAPmNQgDsjUIAyo1CAJqNQgBYjkEAIpFCAAONQgAAjUIAOI1CAO2NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDyjUIARo1CAACHSgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAI5DAACNQgAAjEIAAI1CABGNQgCLjUIA8Y1CAH2NQgCdjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAL2NQgBbjUIA9I1CAP+NQgD/jUIA/41CAP+NQgD5jUIA2Y1CAJuNQgBFjUIAWY1C
+ APiNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDijkIAKo5CAACZMwAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIlEAACOQgAAj0EADI1CAJKNQgD8jUIA/41CAKeNQgByjUIA/I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOCNQQBSjUIA3o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDyjUIA3Y1CAP2NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDRjkEAE45BAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIlEAAB9TwAAjUIAcI1CAPmNQgD/jUIA/41C
+ ANuNQgBXjUIA6o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPeNQgBYjUIAxI1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgC1jUIACY1C
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkEAAI1DAACMQgAyjUIA441C
+ AP6NQgDijUIAv41CAJqNQgA2jUIAzo1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP2NQgB1jUIAoY1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgCXjUEAA41CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkEAAI5B
+ AASNQgCIjUIAtY1CAGONQgAqjkIADoFFAAGOQAAGjUIApI1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgCUjUIAdY1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgB5jUUAAI1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjEMAAIxDAA+NQgA+jUIADY1CAACNQgAAjkIAAI5BAACKQwAAjUIAdo1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgCyjkMAKI1CAIaNQgDQjUIA+I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgB0jUIAAI1DAACNQQAAgIAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAkEYAAI1DAAaJRwAAjUIAAI5BAAAAAAAAAAAAAJBBAACNQgAAjUIASI1C
+ APONQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDNjkIAF4tFAACNQwAbjUIAWY1CALGNQgDxjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDbjUIAVYpHAAKMQgAAjkMAAIBA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOQQAAiEIAAI1CAFeNQgAljkMAAJBDAAAAAAAAAAAAAAAA
+ AACNQgAAjUIAJI1CAOSNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDmjUIAKI1CAACNQgAAjEIAAI5C
+ AAyNQgBJjUIArI1CAPSNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA641C
+ AGqLRQAFjUMAAI5CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQQQAAkUAAAo1CAJyNQgBJjUIAAJFE
+ AAAAAAAAAAAAAAAAAACNQgAAjUIAFI1CAMeNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD0jUIAP41C
+ AACRRAAAoU0AAI1DAACNQgAAjEEADI1CAFeNQgDEjUIA/Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPGNQgBxjUAABI1BAACMQgAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQQAAjUEAD41C
+ AL+NQgBljEIAAI5DAAAAAAAAAAAAAAAAAACNQQAAjEAABo1CAKeNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD6jUIAXo1CAAAAAAAAAAAAAIhEAACgOgAAjEIAAI9BAACMQwAajUIAhI1CAOqNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDxjUIAaIlCAAGMQwAAjUQAAAAAAAAAAAAAAAAAAAAA
+ AACMQgAAjEIAIY1CANqNQgCEij8AAIpFAAAAAAAAAAAAAAAAAACQQAAAjEIAAI1CAIaNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIAfo1CAACPRQAAAAAAAAAAAAAAAAAAi0QAAIlFAACMQgAAjEMAA41C
+ AEeNQgDHjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA6Y1CAFONPwAAkEMAAP8A
+ AAAAAAAAAAAAAI1BAACNQgAAjkIAM41CAPKNQgCjk0EAAZxHAACSSQAAAAAAAAAAAACQQQAAjUIAAI1C
+ AGSNQgD7jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAmo1AAACNQgAAAAAAAAAAAAAAAAAAAAAAAI5E
+ AACLQQAAjUIAAIxBAACOQgAijUIAp41CAP6NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ ANiNQgAzi0QAAIJJAAAAAAAAjUIAAI5AAACRQAACjUIAYY1CAP2NQgDJjkIAHKlqAACNQgAAjUIAAI5C
+ AAAAAAAAjUIAAI1CAECNQgDzjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAro1BAAiNQgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAj0MAAJVDAACMQwAAjEIAFY1CAJ2NQgD+jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgCzjUIAEo1CAACOQwAAjUIARI1CAH2NQgCvjUIA4o1CAP+NQgD5jUIAyo1C
+ AJ2NQgBljUIAIIxCAAAAAAAAjUIAAI1CACaNQgDnjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAwI1B
+ ABKNQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI/AACKQwAAjUIAAI1CABWNQgCojUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD6jUIAbog/AACOQwAAjUIAUo1CAJONQgDBjUIA7Y1C
+ AP+NQgD/jUIA9I1CALCNQgB0jEIAJIxCAAAAAAAAjEIAAIxCABuNQgDTjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA0o1CABqNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMQwAAjkEAAI1B
+ AACNQQAijUIAxY1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA1I1CACKNQgAAjEMAAHsr
+ AACOQwAKjUIAa41CAPuNQgD/jUIA8I1CAGSKOwABjUIAAI1CAACLRgAAjUMAAIxDABGNQgC/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA341CACGNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjEMAAIxCAACNQgAAjEIARY1CAOqNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/Y1C
+ AHSJRwAAmU0AAP++AACNQgAAjUIAMo1CAO+NQgDrjUIA941CAO6NQgBxjEMACI1CAACeQQAAjUMAAI1E
+ AAeNQgCrjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA6o1CACeNQgAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxCAACNQwAAjEQABY1CAJyNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAMaNQwAYAAAAAAAAAACOQgAAjkIAIo1CANqNQgCSjUIAmo1CAP+NQgD2jUIAko1C
+ ABqLQgAAjUIAAI4/AACNQgCYjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA741CAC+NQgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQgAAjUIAAI1CAEqNQgD0jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPKNQgBVAAAAAAAAAACNQgAAjUIAEY1CAMKNQgBjjUIAHo1C
+ AMeNQgD/jUIA/o1CAL6NQgBDi0IAA41CAACNQgCBjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA8I1C
+ ADaNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUIAAI1C
+ ACCNQgDdjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCcAAAAAAAAAACLQgAAi0IAA41C
+ AKCNQgBHjUIAAI1CAD+NQgDdjUIA/41CAP+NQgDpjUIAiY1BACWNQgAzjUIArY1CAPKNQgD/jUIA/41C
+ AP+NQgD/jUIA8Y5CADiNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjUEAAI1BABqNQgDTjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDLAAAAAAAA
+ AACLQwAAikAAAI1CAGCNQgAojUIAAIxFAACNQgBUjUIA6I1CAP+NQgD/jUIA/41CANiNQgB6jUIANI1C
+ AE6NQgCbjUIA3Y1CAPyNQgD/jUIA8o5CADiNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACNQQAAjUIAAI1CAC+NQgDojUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDkAAAAAAAAAAAAAAAAi0IAAI9FAAmQRQADkEYAAI5CAACQQgACjUIAXI1CAOeNQgD/jUIA/41C
+ AP+NQgD+jUIA2o1CAIeNQgA9jUIAL41CAGWNQgCxjUIA2I5CADaNQgAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA/wAAAIhEAACNQQAAjj0AA41CAIaNQgD+jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDoAAAAAAAAAAAAAAAAi0IAAI5EAACPRAAAj0QAAI5CAACOQgAAkT8AAY1C
+ AFaNQgDfjUIA/41CAP+NQgD/jUIA/41CAP+NQgDpjUIAqo1CAFyNQgAsjEEAMY1BAA6NQgAAjUIAAI1C
+ AACRRAAAZRMAAJlNAAAAAAAAgFUAAJE5AACLQwAAjUEAAIxCAACNQgAJjUIAa41CAO6NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACOQgAAjkIAAH0sAACNQgA+jUIAxo1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPqNQgDXjUIAn41C
+ AGiNQgA6jUIAJI1CABKRRAAEjEEAAI5CAACNQgAAjUMAAI1BAACKQwAEjUEAHI1CAE6NQgCljUIA9I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCwAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjkMAAI5DAACNQwAAjUIAIo1CAJyNQgD1jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP2NQgDyjUIA3I1CAMONQgCujUIAmY1CAIONQgB2jUIAdo1CAImNQgCrjUIA0o1C
+ APaNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPmNQgBvAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJFDAACWSgAAjkIAAIxCAAmNQgBkjUIA141C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD+jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ ANCMQwAjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACLQgAAjUIAAI1C
+ AACJQQAAjkIAKo1CAJyNQgDvjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA941CAGWQPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJBDAACRQwAAjUIAAI9BAAeNQgBHjUIAsI1CAPONQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD+jUIAl41BAAuMQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEIAAI5CAACOQgAAjUMADY1CAE+NQgCsjUIA641C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPuNQgCdjUIAFo1BAACOQQAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIpFAACRQAAAjUMAAI1C
+ AACMQwAJjUIAOY1CAISNQgDHjUIA8Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD9jUIA2o1CAHONQwAPjUMAAI1CAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAiUUAAJI/AACMQwAAjUIAAI4+AACOQQAVjUEAQY1CAICNQgC2jUIA4Y1CAPONQgD8jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD5jUIA6Y1CALqNQgBujUIAJa5EAACNQwAAjUIAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUMAAIxEAACNQQAAjUIAAItDAACOQgAOjEIAK41C
+ AFeNQgB8jUIAnY1CALuNQgDQjUIA241CANyNQgDWjUIAwI1CAKGNQgBwjUIAOo1CABGOQQAAjUIAAI9C
+ AACMRAAAAAAAAAAAAAAAAAAAwAA//gAHAADAAB/+AAcAAOAAH/4ABwAA4AAf/gAHAADwAA/8AA8AAPAA
+ D/wADwAA+AAP/AAPAAD4AA/8AA8AAPwAD/wAHwAA/AAP+AAfAAD+AAf4AB8AAP4AB/gAHwAA/gAB+AA/
+ AAD/AAAYAD8AAP4AAAAAPwAA+AAAAAA/AADwAAAAAD8AAPAAAAAAfwAA8AAAAAB/AADgAAAAAH8AAOAA
+ AAAAfwAA4AAAAAAfAADgwAAAAA8AAMDgAAAADwAAwOAAAAAHAADA4AGAAAMAAMDgAOAAAQAAgGAA8AAB
+ AAAAEAD8AAAAAAAQAP4AAAAAABAA/wAAAAAAAAD/gAAAAAAAAP/AAAAAwAAA/+AAAADAAAD/8AAAAMAA
+ AP/wAAAAwAAA/+AAAADgAAD/gAAAAOAAAAQAAAAA/wAAAAAAAAD/gAAAAAAAAP/AAAAAAAAA/+AAAAAA
+ AAD/+AAAAAAAAP/+AAAAAAAA//8AAAABAAD//8AAAAMAAP//+AAABwAAKAAAAEAAAACAAAAAAQAgAAAA
+ AAAAQAAAIy4AACMuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9AAACNQwAAjUIAKo1CAKeNQgC6jUIAuY1C
+ ALmNQgC5jUIAuY1CALmNQgC5jUIAuY1CALmNQgC5jUIAuY1CALmNQgC6jUIAdo5AAAmOQQAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACORAAAkEkAAo1CAGONQgCwjUIAr41CAK+NQgCvjUIAr41CAK+NQgCvjUIAr41C
+ AK+NQgCvjUIAso1CAHWNQgAHjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPQAAAjEMAAIxE
+ AAuNQgCVjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ ANmNQgAjjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAjUIAAI1CABWNQgC5jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPyNQgB3kDwAAItGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIxCAACMQgAAjEMAJY1CANCNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD4jUMAUI1BAACJOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAIxCAACOQgAujUIA441C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDjjUIALY1CAACLRgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACLRgAAjEEAAJFHAACNQgBljUIA9o1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAJKGOAABhDMAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5B
+ AACMQwAAjUIAVI1CAPuNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAp41C
+ AAmNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9DAACOQgAAjUEAEo1C
+ ALGNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDHjEAAFoxB
+ AACAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACTOQAAikMAAY1CAImNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA+Y1CAFyOQQAAjEMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACKQAAAhUwAAItEAACNQgBIjUIA7Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA6oxCAESNQQAAmgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkAAAI1BAAmNQgC9jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CANWOQQApjkIAAIxDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJkzAACOQwAAjkQACo1CAKONQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgB4lkcAAI1CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5CAACOQgApjUIA3I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCpkkUABpFEAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkUUAAIxBAACNQgBCjUIA541C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAtY5CAA+NQgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxD
+ AACNQQAAjUEAVo1CAPKNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD6jEIAbYtB
+ AACCOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9E
+ AACPQQAAj0EACI1CAKSNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AOeOQQAsjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACKQQAAukkAAI1CAIKNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA6oxDADGNQgAAqlUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAj0EAAI1CAACNQgBKjUIA8o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD5jkIAZ41CAACPQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUMAAI1DABCNQgCxjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAL6NQgASjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQQAAjkIAEo1CALWNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAKSNRAAEjUMAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1CAACMQwAljUIA3o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCKjkMABI1CAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAk0AAAIlE
+ AACNQgBjjUIA941CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDMjUMAII1D
+ AACJOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACNQgAAjUIAR41CAPeNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD5jUIAXY5C
+ AACEQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJNAAACNQgAAjUIAII1CANONQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA7oxCAEONQwAAhzcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACSSQAAjUMAAI1CAHONQgD8jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA341CADSNQgAAg0EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZXMAAJBCAAKNQgCRjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgBukkkAAIxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdQ8AAJBLAACNQgCdjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMOORAAQjkQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxFAACOQQAAjUMARY1C
+ APKNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIApY5CAAiOQgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJBFAACQRQALjUIAv41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCWhkwAAHhPAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACNQgAAjkIAAI5CABmNQgDCjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ ANaOQwAYjkMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACOQwAAjkMAJI1CANSNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD7jUIAYI1D
+ AACLRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1EAACSYAAAjUIAh41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDtjEIAQYxCAACAVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACIRAAAjUEAAI1BAD+NQgDmjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA7I1CADGNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQgAAjUIAAI1CAEeNQgDtjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+o1CAHGOQAAAhUUAAG7/AACAgAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEcAAI1CAACNQgBZjUIA+I1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMeNQgAajUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1B
+ AACNQQATjUIAy41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCfh0IABolC
+ AAaMSAAChz4AAI1DAACNQgAAjUIAAI1CAACdUgAAj0QAAAAAAAAAAAAAAAAAAI1CAACLQwAAjUIAeY1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgChjEMACoxDAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjUEAAIc7AACMQgAAkEYAAY1CAIqNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIAxI1CACyNQgCJjUIAqY1CAIGNQgBajUIAM41CABuNQgAGjUEAAI1BAACUPQAAjkMAAACa
+ AACOQgAAjkEACY1CAJ2NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAfIpD
+ AACQQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjUIAAIxCAACNQwAAjEIAJoxCADiNQgBUjUIA+I1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOmNQgA8jUIAlo1CAP+NQgD+jUIA/I1CAO2NQgDHjUIAmY1C
+ AGONQQAnkj8ABopBAACMQwAAjkIAAI1CABONQgDBjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA9Y1CAFyNQgAAiUoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAi0UAAI5CAACLQgAEjUIAT41CAM2NQgCzjUIAPo1C
+ ANeNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD9jkIAVY1CAG6NQgD+jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD3jUIA3I1CAKqOQgBijkIAJqJKAAGNQwAYjUIA3I1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOaOQgA+jkIAAJkzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAikQAAIxEAACSRAADjUIAaI1C
+ AOiNQgD/jUIA541CADaNQgCvjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AISNQQBPjUIA7o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+41CANSNQgCOjUIAXY1C
+ AOWNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDZjkEAIo9BAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiEQAAI9B
+ AACWPgABjkIAXo1CAOmNQgD/jUIA/41CAPmMQgBajUIAfo1CAP2NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgC2jUEAMI1CANyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPGNQgD8jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAyJBB
+ AAuSQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJNBAACOQgAAjUIAPY1CAN6NQgD/jUIA/41CAP+NQgD/jUIAlI1CAEiNQgDxjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA2I5CACaNQgDEjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAKuNQQAEi0MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5DAACMQwAAi0MAFY1CALSNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ ALSMQgAqjUIA3o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOeNQgA/jUIAn41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCMjEIAAo1CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMQQAAkEkAAI1CAGeNQgD7jUIA9o1C
+ ANiNQgCkjUIAcI1CAFCNQQAvjUIAEo1CALSNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD1jUIAXo1CAHWNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD+jUIAbotHAACNQQAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUIAAI5B
+ ABmNQgC7jUIAr41CAF+MQgAgjkEABYQ8AACNQQAAjUEAAJA9AAKNQgCEjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAHyNQwBIjUIA+I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/I1B
+ AE+NRAAAjT8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIxDAACMQwAxjUIAUY1CABCNQgAAjEMAAI1BAACOQgAAjEMAAJk8AACLQwAAjkIAWI1C
+ APmNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCajkQAGI1CAHyNQgDNjUIA9I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPiNQgA/jUIAAItCAACNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1DAACNQwAAiUgAApA6AACNQgAAh0gAAIxDAAAAAAAAAAAAAAAA
+ AACKRAAAjUIAAI1CADWNQgDgjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAt45D
+ ABOMRAAAjkEAG41CAFmNQgCijUIA5o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD+jUIAnI5CABqMQwAAi0sAAICAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQwAAjUMACo1DAByNQgADjUIAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1CAACNQgAVjUIAxI1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CANKNQgAhjUIAAI5CAACNPgAAjkMACo5DADSNQgCOjUIA2o1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPyNQgC1jEMAL487
+ AACKSQAAjkMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVQAAAjUIAAI1C
+ AC6NQgCIjkMAD45DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQPwAAkT4AAY1CAKmNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDsjUIALo1CAACPRgAAjVEAAI5DAACNQQAAlDsAAo1C
+ AC+NQgCHjUIA4o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAMaMQwA4kj4AAI9BAACZMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAlkAAAI1CAACOQgBCjUIAzY1CABmNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj0AAAI1C
+ AACNQgCFjUIA/o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+o1CAEWNQgAAAAAAAAAA
+ AAAAAAAAkj0AAJE+AACOQQAAikAAA41CADiNQgChjUIA741CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA0I1CAD2KRwAAkD4AAI1CAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1BAACMQwAAjUIAXo1CAOyOQgAqjUIAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACNQwAAjUEAX41CAPmNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APyNQgBljkIAAAAAAAAAAAAAAAAAAAAAAACIRAAAb1MAAIxBAACNQgAAikQAC4xCAFSNQgDHjUIA/o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDNjUIAOI5C
+ AACMQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQQAAjD0AAY1CAICNQgD0jkIASI1C
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUIAAI1CADqNQgDzjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jEIAhoRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEQAAIxE
+ AACNRAAAjUMAIo1CAJCNQgDtjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAMWMQgApjEMAAI9EAACNRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEIAAItC
+ AAWNQgCijUIA+o1CAGeNQgAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1BAACNQQAhjUIA4o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAKaMQgACjEAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIBAAACPQgAAikIAAI5DAACMQgAIjUIAV41CANKNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAsI5CAByNQQAAfkQAAP8AAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJQ/AACQQQAJjUIAw41CAP+NQgCGjEMAAINJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACNQQAAjEEAFY1CAMGNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDCjUEACIxB
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAAACQQwAAjUIAAIg7AACOQgAvjUIAtY1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCRjEMACIpD
+ AACIQwAAAAAAAAAAAACKQgAAjEMAAIxDAACOQgAAj0IAGo1CANmNQgD/jUIApQDJAACPQgAAjUIAAI1C
+ AACHPwAAiUAAAAAAAAAAAAAAjUIAAI1CAAqNQgCgjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIAz41CABiNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJJJ
+ AAAeLwAAiUUAAI1CACGNQgCmjUIA/I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA8Y5CAGaROgACjkAAAAAAAAAAAAAAjkIAAItFAAKMRAALjkIAG41CAG6NQgDwjUIA/41C
+ ANeNQgBMjkQAFo1CAAmFUgAAjkIAAIpBAAAAAAAAAAAAAI5CAACCQAAAjUIAf41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CANqNQQAqjUEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA2RYAAJk7AACNQgAAjEMAGY1CAKiNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDZjEIAL41CAACOQwAAAAAAAI1CAEmNQgCEjUMAtY1C
+ AN2NQgD0jUIA/41CAP+NQgD+jUIA741CANiNQgCrjUIAeI1CADSTRQAAAAAAAAAAAACbWQAAjEEAAI1C
+ AGaNQgD9jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDkjUIAO41CAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi0QAAIxDAACMQwAgjUIAtY1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAJuOQwAJjkMAAIxE
+ AACOQgBZjUIAoo1CANGNQgDqjUIA+o1CAP+NQgD/jUIA/41CAP6NQgDmjUIAwY1CAI6MQgA7nUkAAAAA
+ AAAAAAAAkkkAAI1CAACNQgBTjUIA8o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA7o1C
+ AEyNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1C
+ AACNQgAAjUIAAIxBADCNQgDRjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDrjUIASY5BAACKRgAAAKkAAI1CAAiPRAASjkIAMY1CAIaNQgDzjUIA/41CAP+NQgD3jUIAd41B
+ AA+KQgADkkMAAI5CAAAAAAAAAAAAAAAAAACNQgAAjUIAQI1CAOeNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPaNQgBajUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1CAACLRAAAjEIAUo1CAOuNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAKWOQwAMjUMAAI9BAACNQgAAjkMAAI1CAACNQgAbjUIA2Y1C
+ AP+NQgD/jUIA/41CAOGNQgBcjEMABIxCAACMQgAAi0YAAAAAAAAAAAAAjUMAAI1DAC2NQgDbjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD9jUIAZY1CAACZMwAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQgAAjEMAAIxDAAeNQgCUjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDsjkIAPo1DAAAAAAAAAAAAAAAA
+ AACTPgAAkEAACY1CAMONQgD/jUIA341CAPKNQgD/jUIA641CAHCMQgAKjUIAAIpFAACMQwAAAAAAAI1D
+ AACNQwAajUIA0Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAHCMQwAAmjYAAAAA
+ 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
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAG9SAACOQAAAmzYAAY1C
+ AGmNQgD2jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA2gAA
+ AAAAAAAAAAAAAAAAAACZTQAAmU0AAJ5PAAC+XgAAqlUAAAAAAACOQgAAjkIAAI5CAACOQQAMjUIAeo1C
+ AO2NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/I1CANqNQgCcjUIATo1CABqLQAATjEAAEItD
+ AACPQAAAjUIAAI1BAACNQgAAlEYAAIAsAACZTQAAAAAAAAAAAAAAAAAAgFUAAAD/AACLQwAAjkAAAI1D
+ AACKRAAAjUEAC41CAGaNQgDljUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAMIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACOQQAAjkIAAI5EAAaNQgBbjUIA241CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APeNQgDLjUIAj41CAF2OQQAsj0EADI1CAAWNPwACjEEAAIxBAACNQgAAjUEAAI1CAACNQwAAjkEAAI1C
+ AACNQgAAjkEAAI89AAKNQwAPjUIARY1CAJ6NQgDyjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjkIAAI5EAACOQwAAAAAAAI5BADyNQgC7jUIA/Y1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD1jUIA4Y1CAMuNQgCpjUIAhY1CAGSOQgBLjUIAO41B
+ AC+NQgAmjUMAIY5BACGNQgApjUMANo1CAFKNQQCFjUIAxI1CAOuNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD3jUIAYwAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEAAAIs/AACNQgAAjEIAHI1C
+ AImNQgDtjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/Y1CAPGNQgDgjUIA041CAMuNQgDLjUIA141CAOmNQgD9jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA0IxC
+ ACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAmEAAAI5CAACMQgAGjUIAVY1CAMaNQgD9jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/oxDAIOETQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIhEAACYPgAAjUIAAIlAAACOQgAgjkIAiY1CAOeNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMuNQgAkjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJBDAACTRAAAjkIAAJJB
+ AAWNQgA/jUIApY1CAPCNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOqNQQBRiUIAAI5BAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjkIAAJZAAACPQgAAjkMAAI1DAAyNQwBOjUIAso1CAO+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPKNQgBxikEABYtB
+ AACNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEAAAI9IAACNQgAAjkEAAI1DAA2NQgBRjUIApY1C
+ AOiNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AOuNQgBxjUEACYxBAACLQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkIAAIpF
+ AACNQwAAkEEAAIxDAAuNQgA3jUIAgo1CAMaNQgDtjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA+41CAMaNQgBSjkUABY1CAACNQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAiUUAAIRIAACMQwAAjUMAAKcAAACMQgAUjUEASo1CAIaNQgDEjUIA8I1C
+ APuNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDyjUIAvo1CAG+OQgAehkYAAI9BAACOQwAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5HAACINgAAjUIAAI1C
+ AACROwACjUEAFo5CADeNQgBvjUIApo1CAMmNQgDgjUIA8o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD7jUIA4o1CAMSNQgCTjUIARY1DABSQOAAAjkEAAHhNAAD/AAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJI9AAC9GwAAjkAAAI1CAACNQgAAjEEAAIc9AAOMQgAejUIAPY1DAFWNQgBvjUIAkY1C
+ AKyNQgDAjUIAzI1CAM2NQgDNjUIAw41CAKmNQgCNjUIAaI1DAD+MQgAYi0IAAY1CAACNQgAAjEQAAI85
+ AACAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAH//+AAD+AAAf//wAAP8AAA///AAA/wAAD//8AAH/gA
+ AH//wAAf+AAAf//AAB/8AAB//8AAP/4AAH//gAA//gAAf/+AAD//AAA//4AAf/+AAD//gAB//4AAH/+A
+ AH//gAAf/wAAf//AAB//AAD//8AAH/8AAP//wAAf/wAA///gAA/+AAH//+AAA/4AAf//8AAADgAB///A
+ AAAAAAH//4AAAAAAAf/+AAAAAAAB//4AAAAAAAP//AAAAAAAA//8AAAAAAAD//gAAAAAAAP/+AAAAAAA
+ A//4AAAAAAAD//gAAAAAAAH/8BwAAAAAAP/wfgAAAAAAf+B+AAAAAAA/4H4AA4AAAB/gfwADwAAAH+B/
+ AAP4AAAH4D8AAfgAAAPgPwAB/gAAAwADAAH/gAADAAMAAf/AAAEAAwAB//AAAAADAAH/8AAAAAOAAf/8
+ AAAAAYAA//wAAOAAgAD//gAA4AAAAP//AADgAAAA//8AAOAAAAD//wAA4AAAAP//AADgAAAA//8AAPAA
+ AAD//gAA8EAAAP/4AADwQAAAA4AAAP/wAAAAAAAA//AAAAAAAAD//AAAAAAAAP//AAAAAAAA//8AAAAA
+ AAD//8AAAAAAAP//4AAAAAAA///4AAAAAAH///4AAAAAA////4AAAAAH////8AAAAA/////8AAAAHygA
+ AABIAAAAkAAAAAEAIAAAAAAAAFEAACMuAAAjLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj0AAAH5X
+ AACNQgBQjUIAq41CAK+NQgCvjUIAr41CAK+NQgCvjUIAr41CAK+NQgCvjUIAr41CAK+NQgCvjUIAr41C
+ AK+NQgCvjUIApI5BADWNRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkQAAI5D
+ AAyNQgCCjUIApY1CAKONQgCjjUIAo41CAKONQgCjjUIAo41CAKONQgCjjUIAo41CAKONQgCmjUIAh41C
+ ABWNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj0AAAIxDAACMQwAnjUIAyY1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/Y1C
+ AIyCUQAApyEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAjkIAAI1CADeNQgDljUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAqoxFAAeLRgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI4+AACPPgAAjEMAVY1CAPGNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMOMRAATjEQAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2TwAAi0MAAI1CAGmNQgD2jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD4jUIAWo1FAACLRgAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAItGAACNQgAAjEIADI1CAJ2NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOSNQwBCjUMAAIw/AAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACSPwAAnTcAAo1CAJaNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDUjUIAHo1BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACIPwAAjkMAAI1CADmNQgDajUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP2NQgB0kEgAAIs9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACNQgAAjUIAGo1CALyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgCMjEEAB41CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACKQAAAjz8AAJQ6AAKNQgB8jUIA+o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgCqjEEAEYxBAACAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5AAACMQgAAjEIAOY1C
+ AOGNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAO2NQgBMjUEAAItF
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEMAAI1C
+ AACNQgAgjUIAz41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDfjEMALI1BAACAfQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5AAACMQwAAjUIAXI1CAPyNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMSOQgAgjkIAAIxDAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9FAACdXQAAjUMAcI1C
+ APuNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD7jUIAW45F
+ AACNQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1CAACOQwAGjUIAjY1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAJefTgACk0YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ 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
+ AP+NQgDpjkMAKY1BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACOQwAAjkMAEI1CAKmNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CANWNQQAqjUEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUQAAI1D
+ ABGNQgDKjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD5jEIAWJBB
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACNQQAAjUEAII1CAMeNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ ALeOQAAIjkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEIAAIxBAAONQgCKjUIA/o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD9jUIAjI1CAAGGPgAAhFsAAIVP
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKM4AACNQgAAjUIALo1C
+ AOSNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/Y1CAImPOAAAjUEAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEAAAI5DAACNQgBDjUIA9Y1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAvYlGAAiXSQAAjkAAAI1CAACNQgAAjUEAAIlA
+ AACKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAItCAACOQgAAjUIARI1CAPqNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA941CAFyOQgAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACKQgAAiUIAAI1CAACNQgAcjUIAxo1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA2YxCACqMQQAzjUIAXo1CAEiMQgAwjUEAFXAyAACNQgAAjUIAAI1C
+ AACNQQAAjz8AAH5JAAD/AAAAAAAAAI5CAACXPwABjkIAao1CAP6NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA8I1CADCNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1B
+ AACMQQAAj0EAAIpCAASNQgAKjUIAj41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA7Y1CAFONQgBZjUIA9I1CAOmNQgDUjUIAvY1CAJuNQgBrjUIAN45DABGMQAAEjEMAAI1C
+ AACQQgAAeFAAAI1CAACNQQAFjUIAkY1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA2o5BABiNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAAAIpBAACMRAAAjEIAJ4xC
+ AIuNQgBLjUIAX41CAPaNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AHuOQwArjUIA741CAP+NQgD/jUIA/41CAP+NQgD3jUIA641CAMqNQgCGjUEAR45CAB+WQgADi0QAAJJC
+ AACNQgAJjUIAuI1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAto1B
+ ABCNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAACKQwAAjUAAAHxAAAGNQgBHjUIAxY1CAP6NQgCXjUEAOI1C
+ ANqNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAJ+OQQAhjUIA041C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA841CAMSNQgCIjUIAQZFDAAqNQwALjUIAzY1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAlI9CAAiOQgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIhFAACNRAAAzkUAAI1CAFSNQgDcjUIA/41CAP+NQgDKjEMAH41CALqNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMSMQQAujUEAp41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA5Y1CALONQgBtjUIA2o1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAdJw0AAGPQAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiEQAAI9B
+ AACERwAAjkIASI1CANuNQgD/jUIA/41CAP+NQgDljEIAPY1CAIaNQgD9jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOmNQQA7jUIAe41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD6jUIA/Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD9jUIAV4tCAACUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj0IAAI5DAACOQwAnjUIAyY1C
+ AP+NQgD/jUIA/41CAP+NQgD5jUIAboxCAE2NQgDzjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP2NQgBSjUIAV41CAPyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDrjUIAQo1CAACUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMQAAAi0MAAIpEAAyNQgCajUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIAmIxCACaNQgDkjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgB5jUEAQo1CAOeNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDWjUIAMY1C
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACMQAAAjkYAAI1CAFSNQgDujUIA/41CAP+NQgDqjUIAvY1CAJ6NQgCJjUIATI1C
+ ABSNQgC+jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgChjUIAMY1C
+ AMyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDCjUIAII1CAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACNQgAAjUEAE41CALSNQgDyjUIAv41CAHONQgA7jkEAG45EAAmSQQAAjUIAAI1AAAaNQgCNjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDJjkIAH41CALKNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCvjkAAD45AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQwAAjUIAQ41C
+ AKmNQgBNjEMADolFAAGNQgAAjkIAAI5DAACIQgAAkEAAAIhFAACOQgBcjUIA/Y1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDkjkMAHo1CAG6NQgDsjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgCZ46gAAIg8AACOQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACLQwABjEMAKY1DABiNQgAAjUIAAIxD
+ AACMQgAAjEIAAAAAAAAAAAAAAP8AAIxDAACNQgA7jUIA541CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDtjkMAPI9DAA2NQgBMjUIAkY1CANiNQgD6jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgChj0UAB41DAACOQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1DAACNQwAAjUEAAI1DAACNQwAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAA/wAAAI1CAACMQwAhjUIAw41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD0jkIAXY5CAACMQwAAjkEAB41EACOOQwBjjUIAto1CAO2NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDujUIAgI1C
+ ABOMRAAAjjoAAICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAI1DAACNQwAejUIAJo1BAAGNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5B
+ AACPQAAIjUIAoY1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD7jUIAfY1C
+ AACRPgAAjUIAAI1BAACIOAAAj0MADo1DAFCNQgCmjUIA6o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+o1CAJ2MRAAgjjwAAIdQ
+ AACIQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlUAAAI1C
+ AACNQgBcjUMAhI5DAAaOQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9AAACMQwAAjUIAhI1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAm45DAACIPAAAAAAAAAAA
+ AACRRAAAkUMAAItFAACOQQAPjUIARo1CAKuNQgDzjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPyNQgCtjEMAJZBBAACgHwAAmTMAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmUAAAIxCAACOQgB8jUIAwY1C
+ AAqNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9AAACNQgAAjUIAY41CAPSNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAs45CAAqOQgAAAAAAAAAAAAAAAAAAkj0AAK4h
+ AACOQQAAjkIAAIxBAA+NQgBYjUIAv41CAPmNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD+jUIAuoxCACiIRwAAhlIAAIBAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkEAAI8/AASNQgCWjUIA4I5CABSOQwAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQQAAjUEARI1CAOeNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIAxY1CAB6NQgAAAAAAAAAAAAAAAAAAAAAAAAAAAACMQgAAikIAAI1B
+ AACNQgAAi0QAHIxCAHmNQgDfjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/o1CALSNQgAmj0IAAIlBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjUEAAI1BABONQgCwjUIA6o5DAC+OQwAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACMQQAAjEEAI41CANqNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA14xCADSMQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACnQQAAjUMAAIxB
+ AASNQwA8jUIAtI1CAPeNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP2NQgCujEIAG45BAACOQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD/AAAAjEEAAIxBACONQgDKjUIA8Y1CAE2NQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACTQAAAkEEACY1CAMeNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA6oxC
+ AEmMQgAAjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQAAAkUMAAIxCAACNQQAAjEIAFI1C
+ AHeNQgDjjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD9jUIAmI5BABOOQQAAjkMAAIhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+UAAAjUIAAI1C
+ ADKNQgDkjUIA+I1CAGqOQgAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVQAAAjUAAA41B
+ AKeNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+41CAF6NQgAAijwAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIhCAACPQgAAjUIAAJFCAAWOQgBKjUIAyo1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA941C
+ AHuMRQAGj0IAAJU/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACbPwAAi0IAAI5CAEWNQgD5jUIA/41C
+ AIiJRQAAWWIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEIAAo1CAICNQgD9jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAHWNQgAAjUIAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj0IAAI9BAACHQQAAjkEALY1CALCNQgD+jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOuNQgBXc0wAAJBB
+ AAAAAAAAAAAAAAAAAACJQgAAjEMAAIxDAACMQwAAiUMAAI1CAGWNQgD/jUIA/41CAKWSQQAEjUEAAI1C
+ AACNQgAAikEAAItBAAAAAAAAAAAAAAAAAAAAAAAAiUMAAI1CAFuNQgD6jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAImMQgAFjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAItCAACORAAAjEIAAIxCACKNQgCnjUIA/o1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDRjUEALo1AAACMPwAAAAAAAAAA
+ AACPQgAAi0QABYxDABGNQgAhjUIAR41CAL6NQgD/jUIA/41CAN6NQgBrjkMAK41CABeOQwAJkUQAAI1C
+ AACNQgAAAAAAAAAAAAAAAAAAjEIAAI1CADeNQgD2jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAJ2NQQAMjUEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjEIAAI1CAACNQgAfjUIAro1CAP6NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAnItDAAuMQwAAjkMAAAAAAACNQgBMjUIAiI1C
+ ALWNQgDhjUIA9o1CAP6NQgD/jUIA/41CAP+NQgD6jUIA7Y1CAMeNQgCZjUIAZI1CABqNQgAAAAAAAAAA
+ AAAAAAAAjEIAAIxCACWNQgDnjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ ALGNQQATjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjEMAAIxDAACMQwAAjEMAJo1CALmNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA7Y1CAFiFOwAAjkMAAAAAAACOQgBbjUIAqI1CANWNQgDzjUIA+o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA9Y1CAN6NQgCzjEIAdYxCABuMQgAAAAAAAAAAAAAAAAAAjEIAAIxC
+ AB2NQgDRjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMWNQgAZjUIAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1C
+ AACMQwAAjUIAAIxBADiNQgDYjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CALuNQgAWjUIAAAAAAACZPAABjUIADY1DABqOQwA1jUIAaY1CANGNQgD/jUIA/41C
+ AP+NQgD8jUIAi41BACCNQgAQhEIAApJDAACTQwAAAAAAAAAAAAAAAAAAjUIAAIxCABaNQgC6jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CANWNQgAfjUIAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUIAAIhI
+ AACMQgBZjUIA7I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APeNQwBbjj4AAI9AAACQQQAAjUIAAI1CAACMQQAAi0UAAI1CAGmNQgD/jUIA/41CAP+NQgD/jUIA3I1B
+ AFKNPQADjEEAAHc/AACAQAAAAAAAAAAAAAAAAAAAjEMAAIxDAA6NQgCkjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOONQgAjjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkIAAIxCAACLQwAKjUIAk41C
+ AP6NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgC5j0AAEI9A
+ AAAAAAAAAAAAAAAAAACTOQAAjEMAAI1BAESNQgD5jUIA/o1CAPmNQgD+jUIA/41CAOONQgBli0MAB41D
+ AACPQAAAi0YAAAAAAAAAAAAAjUMAAI1EAAeNQgCPjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPCNQgAojUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxDAACMQwAAjUMAM41CAN6NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDrjUIAS45AAAAAAAAAAAAAAAAA
+ AABzTAAAjUIAAI5CADONQgDkjUIA941CAKKNQgDMjUIA/41CAP+NQgDvjUIAfI1EABSOQQAAikkAAHpP
+ AAD/AAAAjUMAAI84AACNQgB5jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APeOQgAvjEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJSQAAjEUABI1DAJqNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAkYdKAAQAAAAAAAAAAAAAAAD/AAAAjkIAAI5D
+ ACWNQgDNjUIA8Y1CAFCOQgBXjUIA7o1CAP+NQgD/jUIA9Y1CAKSNQgAoiUAAAItDAACgYAAAi0YAAI1B
+ AACNQgBnjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPeNQgA3jUIAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACMRAAAjEQAAI1BAE6NQgD4jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIAy41CACoAAAAAAAAAAAAAAAAAAAAAjUIAAI1BABaNQgC0jUIA6o1C
+ AC+MQQAGjUIAio1CAPuNQgD/jUIA/41CAP+NQgDLjkIAUY5AAAqOQgAAf0AAAI1CAACNQgBXjUIA9Y1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPiOQgBAjEIAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjUIAAI1CACWNQgDijUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA9o1DAFYAAAAAAAAAAAAAAAAAAAAAjEMAAIpEAAeNQgCbjUIA3oxDABOOQgAAjEIAG41C
+ ALKNQgD/jUIA/41CAP+NQgD/jUIA7I1CAJONQgApnkUAAIxBAACMQQA9jUIA3o1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPiOQgBDi0MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkIAAI5C
+ ABuNQgDJjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AIsAAAAAAAAAAAAAAAAAAAAAij8AAI9DAACNQgCCjUIAv41BAAmLQAAAkUQAAI1CAC6NQgDHjUIA/41C
+ AP+NQgD/jUIA/41CAP6NQgDMjEIAbY9AABeNQgAKjUIASo1CAK+NQgDwjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPiOQgBDi0MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUEAAI1BABuNQgDMjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CALUAAAAAAAAAAAAA
+ AAAAAAAAikAAAI1CAACNQgBkjUIAjY1CAAaNQgAAiz8AAIpEAACNQgA8jUIA2I1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA+I1CAMSNQgBejUEAHI1GAA2NQgBMjUIAqY1CANuNQgD8jUIA/41CAP+NQgD/jUIA/41C
+ APiOQgBDi0MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUIAAI1CACqNQgDmjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CANEAAAAAAAAAAAAAAAAAAAAAAAAAAI1D
+ AACNQwAmjkMAMY9EAAKORAAAjkEAAI5CAACRQgABjkIAUI1CANuNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD2jUIAv41CAG2MQwAeikQACYxBADWNQgBwjUIAt41CAPCNQgD+jUIA/41CAPqOQgBDi0MAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJI9AACTOgAAkj0AAI1DAGaNQgD7jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CANwAAAAAAAAAAAAAAAAAAAAAAAAAAHs0AAB8NAAAgjsAAIZA
+ AACEPQAAAAAAAI5CAACOQgAAj0IAAo5CAEyNQgDZjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APeNQgDPjUMAgI1DAC2ORAAMj0EAEY5CAD6NQgCHjUIAzo1CAOaOQQBBikMAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi0YAAJFB
+ AACJRQAAjEEAJY1CAMuNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CANkAAAAAAAAAAAAAAAAAAAAAAAAAAJlNAACZTQAAoFAAAP+EAACqVQAAAAAAAAAA
+ AACOQgAAjkIAAJ83AACOQgBIjUIA1I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/o1C
+ AOaNQgChjUIAVoxCAB6IQgADjEEAFIxBAEuNQQAdiUIAAJM7AACSPQAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi0YAAJI4AACMRAAAjkIAAJA9AACNQgAhjUIAqY1C
+ AP2NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AMYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkIAAI5C
+ AACQQgABjUIAPI1CAL+NQgD+jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA8o1C
+ AMeNQgCNjUEAQ4tBABONQQAGYVsAAIxDAACNQgAAjUEAAI1CAACRQwAAm1AAAJlNAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAI88AACGSgAAjEEAAI5BAACPPwAAkUAACI1BAD+MQgC4jUIA+41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAKUAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5CAACOQwAAjD4AAIxB
+ ACCNQQCfjUIA9Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD+jUIA741C
+ ANWNQgCfjkIAZY1CAEGNQgAujUEAH41CAA6fRwACi0AAAI1CAACNQQAAjUIAAI1DAACOQQAAjUIAAI1C
+ AACSPAAAjEEADY5BACiNQgBUjUIAoY1CAOaNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/o1CAHMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACORAAAj0UAAIxAAACQQgASjUIAdY1C
+ AOONQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APaNQgDcjUIAwY1CAKaNQgCSjUIAf41CAGyNQQBZjUIATY1DAESOQQBEjUIAUY1CAGKNQgCAjUIApI1C
+ ANGNQgD5jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA5o1BAEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqlUAAIo+AACOQgAAiEMABI1CAEKNQgC+jUIA/I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPmNQgDwjUIA6o1CAOWNQgDljUIA7I1CAPWNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIArYxDABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACLQgAAjEIAAJBCAACOQgAfjUIAho1CAOONQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDxjEMAW41C
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAj0EAAJs/AACOQgAAkUMABY5CAEiNQgC5jUIA+Y1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCpjEMAEIxDAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACPQgAAj0IAAI5CAACPQgAXjUIAbY1CAM6NQgD6jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CANaNQQAxjEIAAIxDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjkIAAI5CAACNQgAARQAAAI1CACONQgB8jUIA1Y1CAP6NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA5I1CAFV/NwABi0EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACMQAAAll0AAI1DAACHSQACjUIALY1CAICNQgDXjUIA+I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDnjUIAYY1E
+ AAaMQwAAi0EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAItE
+ AACLRAAAjkIAAI9DAAOMQwAgjUIAbo1CALeNQgDpjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAM+NQwBSjkEAA41DAACNQwAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQwAAjEQAAI5C
+ AACNQQAAh0oAAI1BABSMQgBJjUIAhY1CAMiNQgD1jUIA/Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP6NQgDqjUIAlY1BAC9/XAABjEQAAI1CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZMwAA7gAAAI1C
+ AACMQQAAi0IABI5BABqOQQBDjUIAh41CAMWNQgDijUIA9o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDyjUIAzo1C
+ AIaNQgA4jUQACYlEAACNSAAAi0YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5HAACSUwAAjEIAAI1B
+ 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
+ APqNQgD6jUIA+o1CAPqNQgD6jUIA+o1CAPqNQgD6jUIA+o1CAPqNQgD8jUIA3Y5BAFuOQQAAi0YAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjkQAAI5EACiNQgDXjUIA+41CAPmNQgD5jUIA+Y1CAPmNQgD5jUIA+Y1CAPmNQgD5jUIA+Y1C
+ APmNQgD5jUIA+Y1CAPmNQgD5jUIA+Y1CAPmNQgBqgF0AAYtGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAItFAACZLAAAjUIAVo1CAOeNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA+Y1CAJWPPgAAikcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAjkIAAI1CAF6NQgDpjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CANONQgA/jUIAAItG
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAItG
+ AACLRAAAikUAEI1CAIqNQgD+jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAL6MRQAXjEQAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOZgAAhUcAAI1C
+ AJKNQgD1jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAJmMQQAWjEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACLRAAAjUIAAI1CADiNQgDGjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ ANmOQgBLjkIAAIk7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACZOwAAnzcABI1CAL+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA9I1CAGKKPgAAkkkAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAikAAAHAv
+ AAGNQgBujUIA8o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPONQwCAj0UAAIU2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOQQAAjkEAKo1CANiNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAwI1B
+ ADKNQQAAkkkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAikAAAI1CAACNQgAijUIAq41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCuiz0ADIw/
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACNQgAAjUIAXI1CAOaNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIAiotEAAmMQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMQAAACJRwAAjUIAV41C
+ AOGNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDOjEEAPIxCAACAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5AAACNQgAAjEIAjo1CAPSNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDnjUIAWI1CAACMQwAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJkzAACOQAAAjUAAEY1CAJyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDsjEIAbo0+AACZBgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI4/AACPPAAEjUIAuo1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgC7jkEALY5BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQQAAjUMAAI1DAE6NQgDbjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIAnItGAASMQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAI5CAACOQgAojUIA041CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCTk0YACZBEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAj0QAAJFGAAyNQgCajUIA/I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAwY1BACyNQQAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1CAACNQgBZjUIA441CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAO+NQgBoiT8AAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj0QAAI5CAACOQgBIjUIA141CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA445C
+ AFyOQgAAj0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiUAAAIxB
+ AACNQQCJjUIA841CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAMqMQgA8jEIAAKpVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJBB
+ AACSQAAIjUIAnI1CAPyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/o5CAItmcwAAj0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAiD8AAH87AAONQQCzjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAKWKRAARi0MAAAAAAAAAAAAAAAAAAAAA
+ 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
+ AAAAAAAAAAAAAAAAAACNQgAAjUEAI41CAMWNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD0jUIAfZBDAABtPAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlUAAAI5BAACNQQAyjUIA1o1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDjjEIAVYxC
+ AACJOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQQAAjUEARo1CANaNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDcjEEAU4xB
+ AACAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI4/
+ AACPPAADjkIAqI1CAPuNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIAeZNNAACJOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACNQwAAjUMAZ41CAOaNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDDjkMAKo5DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ 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
+ AACNQQBSjUIA241CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CALGRPgAFjkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkcAAI5GAAGNQgCWjUIA9o1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMCMQgAxjEIAAIBV
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAiEQAAI1BAACNQQBujUIA7I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA9Y1CAImNQgAAj0AAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxB
+ AACMQQBQjUIA6Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAOWOQQBMj0AAAIVAAACFSwAAdPAAAICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhkUAAI5CAACNQgCKjUIA/I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA5I1C
+ AGGNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxAAACMQAASjUIA041CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgBqnTIAAH8vAAGUOQAAjUAAAI1C
+ AACMQgAAjkEAAItAAACKQAAAikAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAi0MAAIdEAASNQgCjjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA1YxCADyMQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxAAACNQgACjUIAmY1C
+ APeNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgCPi0EAEYs/ABuMQwAyjUMAK41CACGMQgAYjkEADog+AAKOQgAAjkIAAIxBAACPRAAAj0QAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj0EAAI9BACCNQgC3jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAxY1EABeNRAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACKQgAAikIAAIxCAACLQgAAjUMAUo1CAO6NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgC3jUIAJo1BAFGNQgDbjUIA5Y1CAMCNQgCejUIAfI1C
+ AFKNQgA1jkIAJIxBABSRRgADjUIAAI1BAACMQQAAAP8AAP8AAAAAAAAAAAAAAAAAAAAAAAAAjkIAAI5C
+ ADuNQgDLjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIAr4NPAACbMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1BAACNQQAAhUIAA4xCACeNQwAWjkEAHo1CAOCNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDejUIAP41E
+ ACiNQgDPjUIA/41CAP+NQgD/jUIA/41CAP+NQgDqjkIAvY1CAI6NQgBcjUIAOI1BAB6LQAAHiEQAAI5C
+ AACPQgAAV2MAAP8AAAAAAAAAjUEAAI1BAFeNQgDfjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD2jUIAkI1CAACZMwAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQAAAoEUAAI1CAACNQQAQjEIAU4xC
+ ALqNQgBsjUIAEI1CALaNQgD7jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD9jUIAWZlGAAaNQgC8jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA441BAKaNQQBsjkEAP45CACGRQwAGiEUAAI9DAACYQwAAjUIAAI1CAHKNQgDyjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDqjUEAb41C
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJJJ
+ AACNgwAAkEMAAI1CACGNQgB+jUIA6I1CAP+NQgCxjUIAGY1BAHqNQgD1jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAe6A+AASNQgCejUIA+41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA5I1CAKqNQgBvjkIAPI5E
+ ABOFQQAAjUMAAI1DAIGNQgD9jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDfjkMAT45DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA/wAAAF5MAACLPgAAjUIAKY1CAKGNQgD3jUIA/41CAP+NQgDljUIAJoxD
+ AD6NQgDwjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIAooxCABqMQQB1jUIA7Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA1o1CAJGOQgBXjkMAIY1CAIuNQgD9jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDVjkAAMI5BAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgUoAAIhGAACPQgAljUIAp41C
+ APqNQgD/jUIA/41CAP+NQgD9jEIASoxEABeNQgDajUIA/o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAyYxBAC6OQQBNjUIA4I1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDvjUIAsI1C
+ AMmNQgD9jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDLkT8AE5BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACOQwAAj0IAAJBBAByOQgCZjUIA9o1CAP+NQgD/jUIA/41CAP+NQgD9jEIAhIxCABONQgCmjUIA+o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA741B
+ AESNQQAkjUIA041CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgC6RUwAAJdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIhEAACNQwAAj0QAC41CAH6NQgDxjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD+jUIAv41CABiMQgBpjUIA9o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAGCQQAAJjUIAwY1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPmNQQCejkEAAJVA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAINFAACTQQAAjUIAVI1C
+ AN6NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA7o1DACmMQQAzjUIA8o1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAIGQQQALjUEAoo1C
+ APqNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPCNQgCBjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjEAAAIxDAACLQwAnjUIAso1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA841D
+ AECLQQAWjUIA241CAP6NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAKKMQwAajUEAfY1CAPCNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOmMQgBljEIAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEAAAIo5AAONQgB0jUIA9Y1CAP+NQgD/jUIA/41C
+ APKNQgDCjUIAlo1CAHqNQgBijUEAT41DABiNQgAMjUEArY1CAPyNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMSNQgApjUIAWI1CAOaNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AOGNQQBJjUEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPQAAAjUIAAI1C
+ ADKNQgDBjUIA/41CAPWNQgC/jUIAe41CAEuOQQAtjUIAF49FAAmYQgAAjkEAAI1DAACNQQAHjUEAeY1C
+ APmNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AOWNQgA3jkMAMY1CANyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CANmOQAAujkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACPQAAAmDcAAo1CAHSNQgDrjUIAoI1CAE2MQwAni0MADI5CAACOQQAAjUIAAI5E
+ AACIQgAAej4AAJFBAACPQQADjkEARI1CAPaNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+OQgBJjUkACo1CAMiNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CANGKPQASiz4AAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMQwAAjEMAJo1DAHiNQgBdjUIAF3tU
+ AACMQwAAjEMAAIxCAACMQgAAAAAAAAAAAAAAAAAAAAAAAJo7AAClNgAAkUAAHI1CAOiNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQwBki0oABY5D
+ AE+NQgC/jUIA+o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAMT//wAAhDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACMRAAAjEQADoxEAByNQwAGjUIAAIxDAACMQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE9n
+ AACHRgAAjkEAEI1CAL2NQgD9jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQwCCjkMAEJBDAAaNQgAhjkEASY1CAJWNQgDhjUIA/Y1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAM+ORAAZjkQAAI5CAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJTQAAiUwAAJknAACNQwAAjUMAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAACNQgAAjEMAC4xDAIqNQgD8jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+OQwCgjkMAGo5DAACNQgAAkT4AA41C
+ ABONRAApjkMAZY1CALeNQgD3jUIA/o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APeNQgCsjkIAKpFCAACNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1DAACNQwABjUMAA41C
+ AAGNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOQQAAjkEABY1C
+ AFeNQgD6jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgC9jUEAJI1BAACPQAAAj0AAAI1BAACPMAAAj0QACI1CABmOQwBHjUMAqY1CAPKNQgD8jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD6jUIAxI1CAEiYNAAAkC0AAICAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAI1DAACNQwArjUMAbY1CACuNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACPQAAAkD8AAY5BAC2NQgD4jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDajUIALo1CAACMQAAAAAAAAH6GAACLVgAAj0QAAIpB
+ AACQRAAEjkIAE45BAD6NQgCijUIA7o1CAPyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/o1C
+ ANOMQwBZgm8AAZRGAAB/VQAAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlUAAAI1CAACNQgBDjUIAt45DAFSOQwAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPQAAAjUIAAI1CABqNQgDhjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD2jUIAOY1C
+ AACMQAAAAAAAAAAAAAAAAAAAkUQAAJJEAACQQwAAh0oAAJA/AAOMQwAOjEIAPI1CAKuNQgDzjUIA/Y1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDbjEIAZIZPAAWSTAAAfzwAAJkzAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkAAAI1C
+ AACOQgBSjkIA541CAHGNQgAAkEMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACPQAAAjUIAAI1CABSNQgC9jUIA/o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIATYs7AAGNQQAAAAAAAAAAAAAAAAAAAAAAAAAAAACSPQAAlToAAI1B
+ AACbOwAAjEEAAotCABGNQgBWjUIAxY1CAPeNQgD+jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA4o1C
+ AGyEQAAGhkYAAKwAAACAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAkkAAAHlJAACOQgBkjUIA/41CAImMQgAAkEMAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUEAAI1BAA+NQQCXjUIA/Y1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jkIAao9DAAmOQwAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIhEAAB+SgAAikIAAIdCAACOQAACjEQAG4xDAHeNQgDYjUIA+o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOKNQgBnkTwABZJAAACeRQAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUEAAIxAAAyNQgB/jUIA/41C
+ AJyTRAAGj0MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUEAAI1B
+ AAmNQQBxjUIA/Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jEIAh4xCABGMQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACLRAAAjUUAAH5DAAKMQgA0jUIAqI1CAPGNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDgjUIAYYlB
+ AAWLQgAAjEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjkEAAI5BABqNQgCbjUIA/41CAK+OQwAcjkMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAi0EAAItBAASMQQBMjUIA/I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jEIApoxCABqMQgAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAAAJlEAACQRwAAjkQAEY1CAHKNQgDVjUIA+o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA141CAFOIQgACjUIAAI5BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEEAAIxBACiMQgC2jUIA/41CAMGOQgAxjkIAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlUAAAGJMAACPQQAqjUIA941C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jEIAw4xC
+ ACKMQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACORAAAfj8AAKFFAACNQgA3jUIAqo1CAPGNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMeNQgBBlTwAAY5C
+ AACNRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAjEIAAIxC
+ ADaNQgDSjUIA/41CANONQwBGjUMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAlUAAAI1BAACNQQAdjUEA3I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA4Y1CACqNQgAAjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAAAKBFAACOQgAAkEIAE41CAICNQgDejUIA/o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgC2jkIAL44yAACLRQAAiEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAA5egAAi0MAAI1CAEONQgDujUIA/41CAOWNQgBcjkIAAP8AAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1BAACNQQAXjUEAt41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+o1CADWOQwAAjD8AAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACPQgAAkEUAAKZmAAGNQgBZjUIAyY1CAP2NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAmoxDABqSQQAAlzUAAP8A
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACbPwAAgUUAAI5CAFSNQgD/jUIA/41C
+ APeMQwBxikQAAFBnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxC
+ AACMQgAQjUIAk41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAEqNQgACjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkkkAAKFFAAB+SwAAjUIAP41CALyNQgD8jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA941CAHaQQQAMh0UAAHtLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlUAAAJo/
+ AACPQQAAkUMABo5CAG6NQgD/jUIA/41CAP+NQgCHhEUAAJFEAACUTAAAkkkAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5CAACOQgAKjkIAcI1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAF+NQwAHjUMAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8A
+ AABUYwAAjUIAAIxCADSNQgCyjUIA+41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOKOQQBQjzwABI1BAACLRgAAAAAAAAAA
+ AAAAAAAAikIAAItCAACNQwAAjEMAAItDAACyLwABjUIAL41CAKiNQgD/jUIA/41CAP+NQgC2jUIANJVL
+ AAaLPwAAjUIAAI5DAACMQgAAiD8AAIlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5BAACOQQAEjUIASo1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41B
+ AHWMQQAMjEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEIAAIxCAACMQwArjUIAtI1CAP2NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgC8jEIAJ447AACKTAAAAAAAAAAAAAAAAAAAjkIAAIlCAAqNQwAljEMAQYxDAF6NQgB8jUIArY1C
+ APCNQgD/jUIA/41CAP+NQgDxjUIAuY5DAISNQgBljUIAR45DACmLQQAMkUQAAIxCAACNQgAAAAAAAAAA
+ AAAAAAAAAAAAAJNMAACHOgAAjUMAL41CAPiNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAIqNQQARjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxD
+ AACMQwAAjUIAMo1CALyNQgD+jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD+jEIAeYtBAAyMQgAAjkMAAAAAAAAAAAAAjUIAUY1C
+ AJONQgC0jUIA041CAPKNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD4jUIA2o1C
+ ALmNQgCZjUIAY41CABCNQgAAAAAAAAAAAAAAAAAAAAAAAJJJAACNQgAAjEIAJY1CAOWNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAJ+NQQAVjUEAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQgAAjkEAAIxDADuNQgDMjUIA/o1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA3o1C
+ AD2QRQACjkMAAAAAAAAAAAAAjkIAW41CALKNQgDUjUIA8o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA8o1CANONQgCxjEIAbIxCABGMQgAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACNQgAAjEIAII1CAM2NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CALWNQQAajUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEMAAIyB
+ AACMQQBRjUIA441CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAJuNQgATjUMAAIxEAAAAAAAAmT4ABI5BACONQgA/jUMAW45D
+ AHmNQgCbjUIAyo1CAPyNQgD/jUIA/41CAP+NQgD/jUIA/41CAMyNQgB+jkEAWY1CAD6LQgAffkAAA5pE
+ AACpRgAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQgAAjEIAGo1CALWNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMiNQgAfjUIAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIZZAACOPQAGjUIAb41CAPSNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOyMQwA/ikYAAoxE
+ AAAAAAAAkkAAAI5BAACNQgAAjEIAAP+2AACOQgAWjUIARo1CALiNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ ANaNQQBKkUQAAI1BAACLQgAAiEEAAHE9AACAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMQwAAjEMAFY1C
+ AJ6NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ ANaNQgAijUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI46AABviAAAjEIAEoxC
+ AJyNQgD+jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgCYjkMAEI5CAACPQAAAAAAAAAAAAACZTQAAoFMAAJNHAACNQgAAikIABY1C
+ AHGNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDMjUEATY08AAWNQQAAjEMAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACNQwAAjEMAEI1DAIWNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOWNQgAljUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIxCAACMQgAAi0UAAY1DAC+NQgDajUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDqjkEAN5E+AAKPQAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACSOQAAiUgAAI1BAFONQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA141C
+ AF2LRAAJjEMAAIxCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQwAAjUMACo1DAG6NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPSNQgAojUIAAJkz
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMQwAAjEMAAI1DAAiNQwB4jUIA/o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIAg41BAAyNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeegAAjEMAAI5CAESNQgDujUIA/41C
+ AOqNQgDJjUIA5o1CAP+NQgD/jUIA/41CAOGMQgBwjEIADoxDAABtcwAAi0YAAAAAAAAAAAAAAAAAAAAA
+ AACNQwAAjUQABY1CAFiNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP2OQQAtiUcAAJkxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjEUAAIhKAACNQwApjUMA3o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD+jUIA1YtFABqcLAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD/AAAAjUMAAI1DADeNQgDUjUIA/41CANWMQgBfjkIAkY1CAPyNQgD/jUIA/41CAP+NQgDqjUMAko1E
+ ABySOgAAi0UAAIxDAAAAAAAAAAAAAAAAAACMRAAAc4IAAI1DAEGNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+OQwA1cSsAAJNHAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEQAAI1DAACNQgAQjUIAlI1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA94xD
+ AFCLRAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkIAAI5CACqNQgC6jUIA/41CAMKNQgAxjkIAKY1C
+ ALuNQgD/jUIA/41CAP+NQgD/jUIA9I1CALmMQwA4jEMABItDAABbYQAA/wAAAAAAAACKRwAAjUEAAI1C
+ ADKNQgD4jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+MQgA9h0AAAYtBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI4/
+ AACPPgAEjUEAS41CAP6NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/Y5CAJ+OQgAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUEAAI1B
+ AByNQgCgjUIA/41CALCOQQAdi0QAAIxCAFWNQgDZjUIA/41CAP+NQgD/jUIA/41CAPuNQgDYjkMAY5U/
+ AAudNwAAhkQAAIpCAACLRgAAjUIAAI1CACuNQgDkjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+OQwBGj0UAA45DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA7AACMRAAAjUIAKI1CAOiNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/o1CAOGLRQAaAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjEMAAIxEAA+NQgCFjUIA/41CAJyKSAAGjEMAAIZBAAWNQgCAjUIA8I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA641CAKaLQgAsjEIABYhBAACAQAAAjEEAAIxBACWMQQDOjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+OQgBKkkEABJBB
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI89AACOQgAAjkIAHo5C
+ AMiNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPWNQwBJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAikEAAIQ+AAONQgBsjUIA/4xC
+ AIaMQQAAiEcAAI5BAACLQQATjUIAnI1CAPiNQgD/jUIA/41CAP+NQgD/jUIA/41CAPiNQgDajUIAbIpC
+ ABCNQQADiUQAAI1CABSNQgCOjUIA9o1CAPyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+OQgBLkkAABJBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACNQQAAjUEAG41BALiNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPmNQgB6AAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAikAAAI1CAACNQgBXjUIA7I1BAG2NQQAAiUUAAIg/AACTRAAAjkEAH41CALCNQgD8jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD+jUIA8YxCAL6NQQBQkz4ADY1BAASOQQAQjkIASo1DAK+NQgDxjUIA+41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+OQgBLkkAABJBBAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1DAACNQQAAjUEAHo1BAMaNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APuNQgCiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAikAAAI1CAACNQgBIjUIAwY1CAFWNQgAAAAAAAIpA
+ AACNQQAAiEIAAI1BAC6NQgDBjUIA/o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPyNQgDvjUIAsI1B
+ AEKNQgAOjUEAB41FABCNQwBKjUIAsY1CAOyNQgD2jUIA/Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+OQgBLkkAABJBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1D
+ AACNQgAAjUIAJo1CAOCNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPyOQgC9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxC
+ AACMQgAyjEIAgo1DADaNQwAAAAAAAAAAAACOQQAAjUEAAJpQAACOQgBCjUIAzY1CAP6NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/I1CAO6NQgCsjUIASYxGABONQwAIikQACoxCADKMQQCBjUIAy41C
+ AO2NQgD4jUIA/41CAP+NQgD/jUIA/41CAP+OQgBLkkAABJBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAi0AAAI1DAACNRAAEjUIAUI1CAP2NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP2NQgDNAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJVJAACVSQAFlkoACptMAAOaSwAAAAAAAAAAAAAAAAAAAAAAAI5C
+ AACOQgAAjkIAR41CAM6NQgD+jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD9jUIA8o1C
+ ALiNQgBVjEUAGo1DAAuIQQADjUUAD41DAEeNQgCejUIA2Y1CAO6NQgD7jUIA/41CAP+OQgBLkkAABJBB
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSPQAAjj4AAJNFAACNQgAXjUMAo41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP2NQgDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJlNAACZTQAAnE4AAK5X
+ AACqVQAAAAAAAAAAAAAAAAAAAAAAAAAAAACOQgAAjkIAAI5CAEKNQgDLjUIA/Y1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD3jUIAx41DAGyMQwAsjkIAEo5CAAM+cAAAjkEAH41C
+ AGSNQgCwjUIA241CAO6OQQBIkUAABJBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAItG
+ AACMRQAAh0kAAI4/AAiMQQBejUIA941CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPyOQgDKAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkIAAI5C
+ AACOQQA+jUIAyI1CAPyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDhjUIAko1CAEWOQQAfi0IACpJCAADARgAAjEEAK4xBAHKNQQArkEAAA49AAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA/wAAAKA2AACOPwAAjUQAB45BAEqNQgDejUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APyNQgC3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5BAACOSQAAjkIAOI1CALmNQgD3jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPSNQgC8jUIAcI1CADmOQQAciz8ABo1C
+ AACNQQAAjkIAAJE/AACTPAAAkj0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAItGAACLRgAAjEIAAINIAACNQQAVjEMAWY1C
+ ANyNQgD+jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPqOQwCaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOQgAAjj0AAI5E
+ ACCNQgCdjUIA7I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAOeNQgCnjUEAaIxCAECNQQApjkIAFJs2AAKMQwAAjUIAAI1BAACNQQAAjEMAAJFC
+ AACZTgAAmU0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgFUAAHtdAACLQgAAjUEAAI5B
+ AABqhQAAjUIAF45BADqNQgCMjEIA741CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPiNQQBuAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjkQAAJRKAACJPQANjUEAfo1CANyNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/4xCAO+NQgDAjUIAjo5B
+ AGKNQgBKjUIAOo1BACyNQQAdjEMAD5ZBAAWFOwAAjUIAAI1CAACNQQAAjEIAAI1CAACNQwAAjkEAAI1B
+ AACNQgAAjUMAAJE8AACKQgAGjUEAGo5BADWNQgBZjUIAlY1CAN+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPONQgA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIc8AACEOgAAnEoABI5B
+ AFqNQgDCjUIA+41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD4jUIA241BAL+NQgCijUIAho5CAHGOQwBejUIAUY1C
+ AEaNQQA7jEIAM41DAC6NQwApjkEAKI5BADCNQgA3jUIAQo1DAFWNQgBzjUIAm41BANGNQgD9jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/o1CANKPPwAVAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAKpVAAD9kAAAkkQAAKs7AACMQgAvjkIAm41CAOiNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA+I1CAOaNQgDTjUIAxo1CAL6NQgC1jUIAtI1BAMCNQgDNjUIA4I1C
+ APyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/Y1C
+ AIWMQgALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi0IAAIpCAACPQQAAikMAD41C
+ AG2NQgDOjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA64xDADaKRQACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIhEAACARwAAjEIAAJFCAAOOQgBBjUIAno1CAOiNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jEMAmoxDAA2MQwAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkIAAI9CAACLQQAAj0IAFY5C
+ AGaNQgDEjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDZjUIANItEAAKMQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJBDAACSRAAAjkIAAI5CAAOPQgA2jkIAio1CANyNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPeNQgBpjkIAB41CAACMQwAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkIAAI9CAACKQwAAjkIAD41C
+ AEiNQgCVjUIA541CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41BAJaNQAAVikMAAJU6
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJVAAAC0OAAAjkEAAI5FAACNQwAVjEMAUY1CAKKNQgDujUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIAroxCACd+PQABjEEAAI9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEAAAIs9AACMQwAA/wAAAI5D
+ AByNQgBSjUIAo41CAPCNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCyjUIAMo5HAAKMQgAAi0EAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACKRQAAiEYAAI1DAACJTAABjkIAHIxDAEmNQgCQjUMA4I1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAKSNQgAvjD0AAo1C
+ AACNQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1DAACNQwAAjkIAANQP
+ AACNQgAUjkIAM41CAHGMQgC7jUIA9o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDpjUIAgI1EACCURwABjUIAAI1BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAiUUAAIhGAACNQgAAiUgAAI1CAAuMQgAgjUMAPo1BAIGOQQDJjUIA+o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA9I1CAKyOQgBHj0EADpsvAACNRAAAjkMAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZMwAAnC8AAI1C
+ AACMQgAAk2AAAIxBAA6OQQAgjkEAP41BAH+NQgDDjUIA9o1CAP2NQgD+jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD+jUIA/Y1CAOCNQgCVjUIARY1FABeRQQADh0YAAJFG
+ AACLRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACORwAAjkYAAIxBAACNQgAAlDoAAo1BAA2NQgAajkEAMY5D
+ AGaNQgCijUIA2o1CAPmNQgD6jUIA/I1CAP2NQgD+jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP6NQgD8jUIA+41CAPCNQgC7jUIAZYxD
+ ACaNQgAQjEMAA448AACPRAAAek4AAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI9
+ AACSPQAAkD4AAI1BAACNRAAAkjwAAY9EAAiNQgAQjEEAG4xBADeNQgBmjUEAkY1CALONQgDTjUIA7Y1C
+ APaNQgD3jUIA+Y1CAPqNQgD7jUIA+41CAPuNQgD7jUIA+41CAPuNQgD6jUIA+Y1CAPiNQgD2jUIA741C
+ AMeOQwCSjEIAXI1CACuNQgATjUMACKcSAACNQwAAjUMAAJQdAACAgAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI45AACNMQAAj0AAAI5DAACNQgAAlUsAAIlA
+ AAKMQgAHjUEADI1DABCNQgATjUQAHoxCADqMQgBejUIAeY1CAI+NQgCjjUIAsI1CALKNQgCyjUIAso1C
+ ALGNQgCdjEMAgoxCAGaOQQBJkEIAJY1CABKOQwAMjEIABotCAAGNQgAAjUIAAIpIAACLRgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAH/////AAAB//AAAAD//
+ ///AAAB//gAAAD////+AAAB//gAAAD////+AAAD//wAAAB////+AAAD//4AAAB////+AAAD//4AAAB//
+ //+AAAH//8AAAA////8AAAH//8AAAA////8AAAP//+AAAA////8AAAP///AAAA////8AAAP///AAAAf/
+ //4AAAP///gAAAf///4AAAf///gAAAf///4AAAf///wAAAP///4AAAf///wAAAP///wAAA////wAAAP/
+ //wAAA////4AAAP///wAAA////4AAAH///wAAA////8AAAH///wAAB////8AAAH///gAAB////+AAAH/
+ //gAAB////+AAAD///gAAB////+AAAD///gAAD/////AAAD///gAAD/////AAAB///AAAD/////gAAAP
+ //AAAH/////gAAAAf/AAAH/////gAAAAD/AAAH////+AAAAAAPAAAH////8AAAAAABAAAH////wAAAAA
+ AAAAAP////gAAAAAAAAAAP////AAAAAAAAAAAP////AAAAAAAAAAAP///+AAAAAAAAAAAP///8AAAAAA
+ AAAAAP///8AAAAAAAAAAAf///4AAAAAAAAAAAf///4AAAAAAAAAAAf///wAAAAAAAAAAAf///wAAAAAA
+ AAAAAf///wA8AAAAAAAAAf///wH8AAAAAAAAAP///wf8AAAAAAAAAH///g/+AAAAAAAAAB///g/+AAAE
+ AAAAAAf//A/+AAAHAAAAAAP//Af+AAAHwAAAAAH//Af/AAAH8AAAAAH//Af/AAAH/wAAAAD//Af/AAAH
+ /4AAAAB//Af/AAAH/+AAAAA/+Af/AAAD//AAAAAf+AP/gAAD//wAAAAP+AP/gAAD//4AAAAP4AD/gAAD
+ //8AAAAHAAAPgAAD///AAAAHAAAHgAAD///gAAADAAAHgAAD///wAAADAAAHwAAD///4AAABAAAHwAAD
+ ///8AAABAAAHwAAD///8AAAAwAAfwAAD///8AAAA+AAPwAAB///+AAAA+AADwAAB////AAAA+AABwAAB
+ ////AAAA/AAAQAAB////gAAA/AAAAAAB////gAAA/AAAAAAB////gAAA/AAAAAAB////wAAA/AAAAAAB
+ ////gAAA/AgAAAAB////gAAA/gwAAAAB////AAAA/g8AAAAB///+AAAA/g+AAAAB///8AAAA///AAAAB
+ ///4AAAA///gAAAAf//gAAAA///wAAAAAf4AAAAA///4AAAAAAAAAAAA///8AAAAAAAAAAAA///8AAAA
+ AAAAAAAA////AAAAAAAAAAAA////gAAAAAAAAAAA////4AAAAAAAAAAA////8AAAAAAAAAAA/////AAA
+ AAAAAAAB/////gAAAAAAAAAB/////4AAAAAAAAAD/////+AAAAAAAAAH//////gAAAAAAAAP//////4A
+ AAAAAAAf//////+AAAAAAAA////////wAAAAAAB////////8AAAAAAH/////////gAAAAA//KAAAAIAA
+ AAAAAQAAAQAgAAAAAAAAAAEAIy4AACMuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAj0AAAI9AAACQPwAIjkIASo5CAIuNQgCJjUIAiY1CAImNQgCJjUIAiY1CAImNQgCJjUIAiY1C
+ AImNQgCJjUIAiY1CAImNQgCJjUIAiY1CAImNQgCJjUIAiY1CAImNQgCJjUIAiY1CAImNQgCJjUIAiY1C
+ AImNQgCJjUIAio1CAImOQwBwjUEAIIs+AASMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACORAAAjUEAAI1BABSNQQBfjUIAdY1CAHmNQgB5jUIAeY1C
+ AHmNQgB5jUIAeY1CAHmNQgB5jUIAeY1CAHmNQgB5jUIAeY1CAHmNQgB5jUIAeY1CAHmNQgB5jUIAeY1C
+ AHmNQgB5jUIAeY1CAHaOQQBAjkEAEo5BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPQAAAj0AAAHhaAACNQwBIjUIAqo1C
+ ANaNQgDYjUIA141CANeNQgDXjUIA141CANeNQgDXjUIA141CANeNQgDXjUIA141CANeNQgDXjUIA141C
+ ANeNQgDXjUIA141CANeNQgDXjUIA141CANeNQgDXjUIA141CANeNQgDYjUIA2Y1CAMOOQQBnjkEAGI5B
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5E
+ AACPRwAGjUMAP41CAMCNQgDTjUIA0o1CANKNQgDSjUIA0o1CANKNQgDSjUIA0o1CANKNQgDSjUIA0o1C
+ ANKNQgDSjUIA0o1CANKNQgDSjUIA0o1CANKNQgDSjUIA0o1CANKNQgDTjUIAy41CAEyMRQAIjEQAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAI9AAACPQAAAjEMAAIxEACWMQwCDjUIA9I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA+I1CALCOQQAvjUIAAItGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUMAAI1DABmNQgBxjUIA+Y1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDdjUMAQpUzAACLRwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKSAAAjz0AAI1D
+ ADKNQgC4jUIA9Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD8jUIA3o1C
+ AESPPgAAikcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8A
+ AACNQgAAjUIAMY1CAJqNQgD3jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA741CAJ6NQgAmjUIAAItG
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAItGAACLQwAAi0QAD4xDAFCNQgDajUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD5jUMAY4pIAAuMRQAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/wAAAIxCAACNQgBGjUIAwY1CAPqNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDhjEEAXYxBABKMQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi0YAAItF
+ AADjAAAAjEMAGY1CAJuNQgDpjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APyNQgCOjkIAKo5CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8A
+ AAD/AAAAhUcAAI5CAFuNQgDojUIA/Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMyNQwAmj0UAAo5D
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi0QAAIxCAACNQQAFjEIAQo1CALyNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/Y1CALqNQwBLjUIAAIk7AACJOwAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkEAAAJBAAACUPQAHjUIAdY1CAPyNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDrjUIAm45DABCLPwAAqWcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAiD8AAIg+AAGHPgAHjUIAfY1CAOSNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD+jUIA5I1CAGySSwAAhjcAAIY3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACNQgAAjUIAAI5BACONQgCSjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMyNQQBcjUEACY1C
+ AACSSQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKQAAAjUIAAI1CAACNQgA4jUIAoY1C
+ APyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAjIo8AAuLPgABiz4AAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1CAACNQgAAjUIARY1CALGNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIArIxDACSMQwAEjEMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIpAAACPPgAAjz4AAJoyAAONQgBbjUIA341CAPyNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgCsjUEANY1BAAONQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjEIAAIxCAACMQgBmjUIAz41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAO+NQgCHi0QAA4tE
+ AACMQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHNjAABzYwAAikUAAI1B
+ ACmNQgCPjUIA9Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMqMQgBijEEABYxC
+ AACAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5AAACNQgAAjkAAAI1CAIiNQgDtjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIAyY5BAF6NQgAAjUIAAIxDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAmTMAAJkzAACOQAAAjUAACI1CAEaNQgDZjUIA/I1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA6Y1CAJCKTAAGjjsAAJwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjj8AAI4+AAGOPwANjUIApI1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+OQgCgj0EANY5C
+ AACOQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1B
+ AACNQwAAjUMAGo1DAJuNQgDsjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAt4xF
+ ABWIUgABjEYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOQgAAjkEABY5CAC2NQgC6jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/Y5CAHuRRAASkEQAAJBEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9EAACPRAAKj0QARI1CAMyNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDOjUEAPo1AAAmNQAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAI5DAACOQwAKjkMAV41CAMyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP2NQgDrjkIAWoM7
+ AACfTQAAn00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAj0QAAJpPAACOQwAQjUIAmI1CAOyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AN6NQgByjUIAE41CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEEAAIxBAA+MQQCAjUIA3o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA+IxBAL2MQQBAi0AAAP+uAAD/rgAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPRAAAjkIAAI1AAAKOQgBNjUIAvo1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA745CAKiOQgAdjkIAAI9AAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIlAAACMQQAAjUEAE41BAKmNQgDwjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD0jEIAi4xC
+ ACeMQgAAqlUAAKpVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACPQQAAj0EAAZBAABKNQgCJjUIA941CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD8jkIA1I5CADCKRgAAj0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiD8AAJRFAACMQQAgjUEAy41C
+ AP6NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAO+MQwBai0QAEIxDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9BAACPQQAAjUIAAI1C
+ AFiNQgDMjUIA/o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDujkEAUZA/AAuPQAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACKQQAAiEEAB4tCADyNQgDgjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA3oxC
+ ADObPAAAiEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAj0EAAI9BAACNQQAAjUEAKI1CAIuNQgD6jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPOOQQCCjkEAI45BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxDAACMQwAWjEMAZ41C
+ AOeNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPKNQgCyjUIAIY5CAACIRAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJBD
+ AACXRQAEjkIAUo1CAOaNQgD9jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+I5CALOOQgA7jkIAAItG
+ AACLRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjkMAAI5DACWOQwCSjUIA7o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA5I1C
+ AIWNQgAXjUIAAIhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaikAAIk/AACOQgAtjUIAq41CAPONQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD8jUIA4o1CAFWPPwAAiUkAAIlJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAItGAACNQwAAjUIAM41C
+ AL2NQgD2jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDXjUIAWY1CAA6NQgAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACqVQAAjkEAAI1BABONQQBfjUIA441CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD+jUIAco1E
+ AAmNQwAAjUMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAikcAAI0/AACMQgBFjEIA441CAPyNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AMmNQwAwjUMABo1DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUQAAAWFEAAI9BACONQgDHjUIA/I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCTjkIAKI5CAACOQgAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMRQAAiUgABo1D
+ AF2NQgD5jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAtohBABC0SAAAgkAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJlAAACKQwAAjUMAEYxDAIuNQgDjjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ ALONQwBJjUMAAI1DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1BAACNQQAejUIAfY1CAPuNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AOuNQgCUi0IACI9CAAB7PwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlUAAAI1CAACMQgAIjUIASY1C
+ AMeNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA1IxCAGmMQQAAi0EAAIk7AAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUEAAI1B
+ ADONQQCajUIA/I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA0oxBAG6NQQAFjEEAAIBAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjj8AAI8/AAKOPwAXjUIApY1CAP2NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDzjEIAioEqAAGCLAAAhzcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQgAAjUIAR41CALWNQgD9jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgC5jUIASY1CAAONQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOQAAAjkIAAI5A
+ AACOQgB5jUIA4I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCmij4AEoo+AAKLPgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSSQAAkkkAAI1D
+ AACNQwBbjUMA0I1CAP2NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAKCPRQAkj0QAAo9EAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5AAACNQwAAjUMAAI1DAEaNQgCyjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CALqMQQA5jEEABoxBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJJJAACSSQAAjEEAAI1CAHCNQgDrjUIA/o1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIAh4tKAASMRQAAjEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxE
+ AACMRAAAjEUAFI1CAIONQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAz45CAGKOQgAKjkIAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkkoAAJJK
+ AACtcAABjUIAhI1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/o1DAOaNQwBtjkEAAIlHAACJRwAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAikgAAIpIAACUOQAAjUMAXI1CAOGNQgD8jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDkjkIAjY5CAA2OQgAAkkkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQRAAAkEQAAZBFABaNQgCXjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD9jUIAxI1DAFKNQwAAi0YAAItGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACLRgAAi0YAAI5DAACOQwA8jkIAsI1CAPmNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPeOQgC1j0MAFYs/
+ AACVTQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9D
+ AACPQwACj0MAMI1CAKiNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPyNQgCfjUIAN41CAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUEAAI1BACCNQgB7jUIA9I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CANSORAAnllAAAo9GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkMAAI5DAASOQwBJjUIAuY1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA+41CAHuNQQAcjUEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACORAAAjkgABY1DAEiNQgDsjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA34xC
+ AE+MQgAOjEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACNQQAAjUEABY1BAGKNQgDKjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD3jUIAWZE8AASOQAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9KAACMPwAAjUMALI1C
+ AMWNQgD3jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDnjEIAeIxCABqMQgAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1BAACNQQAGjUEAfI1CANuNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA+41CANyNQgBCjEMAAJBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjkcAAI1CAACNQgAcjUIAkI1CAOmNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APCNQQChjUEAJ41CAACAVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACIRAAAjUIAAI1BAAaNQQCVjUIA7Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD1jUIAuI1CADKNQgAAj0AAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEEAAIxB
+ AA6MQQBVjUIA2Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+I5BAMqOQgA0jz8AAINGAACHPQAAhFcAAHfZ
+ AACAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIZFAACQQQAAi0MACo1CAK2NQgD8jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAO+NQgCTjUIAJY1CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMQAAAiz4AAoxBACCNQgDFjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA7YxDAEWXNAAAkgAAAIc9AAGEWQAAAP8AAIpRAACNQgAAjEIAAI1BAACNQQAAiUAAAIpA
+ AACKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAikMAAINGAAGLQwAYjUIAwY1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA6YxCAHGMQgAZjEIAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxA
+ AACNQwAAjUEADY1CAJ2NQgDujUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD3jEIAY4lBAA6ENwAChjwACgD/
+ AACPNQAAjUMAAI1CAACMQgAAjUEAAI1BAACJQAAAikAAAIpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPQQAAj0EAB45BADWNQgDLjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDjjUMAToxEAA2NQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEAAAI1CAACNQwAGjUMAa41CANGNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPqNQgCHjEIAI4xAABaNQQBdjUIAiI1CAIGNQgBrjUIAVoxCAEKNQQAujUAAFQAA
+ AACNQgAAjkIAAI1BAACNQgAAj0QAAI9EAACPRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAI5CAACPQgANjkIAVI1CANWNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CANuOQgAtlEIAAo9C
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKQgAAikIAAIlC
+ AACMQgAAjEIAAI1CAAKNQwA6jUIAtI1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+41CAKuNQgA6jUEAHY1C
+ AIiNQgDujUIA841CANqNQgDDjUIArI1CAJaNQgB7jUIAYI1CAEqOQgA5jUEAJ4xBABSUSQADjUIAAI1B
+ AACMQQAAjEAAAPoDAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkIAAI5CABSOQgBzjUIA3o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD+jUIAyo5AABmKRgAApSIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjUEAAI1BAACNQQAAh0IAAotCAA6MQgAXjUMAC45AABWNQgCYjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD9jUIAzo1CAFONRAAOjUMAYI1CAOaNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD3jUIA3I5CALWNQgCNjUIAYo5DADqNQgAhjUEAFoxBAAyMQAAEf0kAAIxDAACPQgAAkEIAACGD
+ AAD/AAAA/wAAAAAAAACNQQAAjUEAGo1BAJGNQgDojUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPONQgCvjUIAFY1C
+ AACZMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQQAAjkEAAI1B
+ AAKKQgAUjEIAXIxCAJCNQwBAjUMACo1CAHqNQgDyjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP6NQgDvjUIAa6th
+ AAGOQwA8jUIA341CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP6NQgD7jUIA941CAPKNQgDtjUIA4o1C
+ AMONQQCNjEEAU4xAACKdOAAFkUAAA41DAAKQQgABIYMAAP8AAAD/AAAAAAAAAI1CAACNQgAgjUIAr41C
+ APGNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA5o1BAJKNQQARjUEAAJkzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACAQAAAlUMAAI1BAACNPgACjUEANY1CAI6NQgDXjUIA141CAHeNQgAVjUEAWo1C
+ AM+NQgD+jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCDn0YABpBBACGNQgDRjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+I1CAOWNQgDSjUIAuo1BAJiOQgBojkMAOJFC
+ AA+DSAAAjEMAAJFDAACZQwAAjUMAAI1DACaNQwDLjUIA+o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDajkIAdo5C
+ AA6OQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSSQAAkkkAAJBRAACQQwAAjEIAEI1C
+ AFKNQgChjUIA541CAP+NQgDzjUIAqo1CACONQQA5jUIAqY1CAP6NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AJqPQgAej0AAFo1CALaNQgD2jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA8o1CAM6NQgCrjUIAhI5CAFqNQwAwk0QACYdBAACNQwAAjUIAJo1D
+ ANeNQgD9jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAM6OQgBbjkIAC45CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAA/wAAAAFiAACxHgAAijwAAIxCABONQgBYjUIAwI1CAPmNQgD/jUIA/41CAPqNQgDUjUIAM4tC
+ ABuNQgCDjUIA/o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAso1CAD+MQQAUjEEAlI1CAOeNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD5jUIA1Y1DAJaOQgBbjkIAN41DABiOQwA0jUIA2Y1CAP2NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAwo5B
+ AEGOQQAHjkEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAhEsAAJw9AAGRRQAKjUIAZI1C
+ AM2NQgD7jUIA/41CAP+NQgD/jUIA/41CAPGNQgBMiEYACI1DAF+NQgD5jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDKjEIAYI1BABCNQQByjUIA2I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP6NQgD9jUIA+o1CAPONQgDJjUIAgo5D
+ AGuNQgDgjUIA/Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgC3j0AAKI9AAASPQAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAD/AAB/SwAAoTcABI5CAGGNQgDDjUIA+o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA9o1C
+ AHOLRAAVjUIARI1CANuNQgD7jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOKNQQCBjkEADY5BAFCNQgDJjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPiNQgDpjUIA5I1CAPmNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AKySQAAPlD8AAZJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOQwAAjkIAAI9BAAqPQgBOjUIAu41C
+ APaNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD5jEIAnYxCAC2MQgAvjUIAsI1CAPWNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA+Y1CAKGQPgALjEEALY1CALuNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD+jUEAm5dAAANWSQAAl0AAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACIRAAAiEQAAI1DAACQRQAEjkIAM41CAK6NQgDyjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APuNQgDHjUIASYxCABuMQgCCjUIA7o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAuY9BABiMQQATjUIAqo1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AO6NQQCImj8AAI5BAACVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIVFAACFRQAAkUIAAI1DACONQgB/jUIA8o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/o5CAOyOQgBljEEADI1BAFeNQgDojUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDGjkMAM5k9AAeNQgCVjUIA+o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA3I1CAHWNQgAAjUIAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAiUQAAIlEAACCRwAEjUIAX41CAOONQgD8jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAICLRQANi0AAMo1CAN+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CANGMQgBRjUIADI1B
+ AHyNQgDkjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDLjUIAYo1CAACNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxAAACMQQAAjEIAAIxDAECMQgCpjUIA/Y1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQQD5jUIAho1FABWMQQAfjUIAxo1C
+ APuNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA241DAHCNQwARjUIAY41CAM+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CALqMQgBQjEIAAIxCAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjD8AAIw/AAGMPwAMjUIAhY1CAOiNQgD/jUIA/41CAP+NQgD/jUIA/41CAOqNQgDLjUIAsI1C
+ AJ2NQgCOjUIAf41BAHKNQgA+jUYACo1CABaNQgCjjUIA7Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDmjUIAj41C
+ ABeNQgBKjUIAuY1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIAqo1CAD2NQgAAjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9AAACNQQAAjEEABY1BAD2NQgC+jUIA/41C
+ AP+NQgD2jUIA4o1CAM2NQgCzjUIAjo5BAGOOQgA/jkQAJY9FABL/WgAAkEIAAIxCAACNQgAAjUEAEY1B
+ AHuNQgDdjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPGNQgCujUIAHI1CADGNQgCjjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCZjkEAK45BAACOQQAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAj0AAAIxDAACNQgARjUIAj41CAOGNQgD3jUIA5I1CAL+MQwCDjEMARIxCABaNQgAFjkEAA41C
+ AAKOQwABjkQAAYRBAAB6PgAAgEAAAI1BAACNQQALjUEAVI1CAM6NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+41C
+ AMuNQgAikEQAFo1CAIqNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAImOPwAZjkAAAI5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPQAAAkT4ABI5BACyNQgDNjUIA4o1C
+ AJyMQwBJjUIAIoxDABSMQwAJi0IAAo1CAACOQQAAjUIAAI5DAACORAAAhEEAAHo+AACAQAAAj0EAAI9B
+ AAWPQQAsjUIAvo1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA4o9CAC2PGgAAjUMAa41CAPaNQgD+jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUEAeIQ3AAaJPQAAiT0AAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIxDAACMQwAXjEMAXo1CAJGNQgBnjUIAK4tEAAqNQgAAjEMAAIxDAACMQgAAjEIAAIxC
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACWPgAAoTkAAZU+AA6NQgCqjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDpjUMAQ4lRAAONQwAvjUIAjo1CANeNQgD9jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/o1CAPyNQgBokkYAAIE3AACBNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEMAAIxDABSMQwBIjUMANo1E
+ AA2NQgAAjEMAAIxDAACMQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADl0
+ AACDSAAAsysAAo1CAI+NQgDvjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOyNQwBdjkQAEZJEAAaOQwArjUIAao1C
+ AJaNQgC6jUIA3Y1CAPqNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD+jUIA+41CAG57IAAAjkIAAI5C
+ AACOQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACLRwAAi0cAAotHAAZ6YgAAjEQAAI1DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAI1CAACMQwACjUIAb41CANWNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA745DAHeOQwAejkMAAI5CAACLRAAAkD8AD41CAD+NQgB/jUIAt41CANaNQgDpjUIA+I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIAnY5DADWOQgAKEk4AAI1CAACNQgAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAItGAACLRgAAi0YAAYtG
+ AACLRgAAjUMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD/AAAAjEMAAIxDAAGMQwBPjUIAu41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDyjkMAkI5DACmOQwAAj0EAAI9A
+ AACPQAABjkEABYxGAAqNRwAXjkQARo1CAIeNQgDJjUIA9I1CAPqNQgD+jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD0jUIAro5C
+ AECOQgAMiUIAAI1CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACNQwAAjUMAAI1DAACNQgAAjUIAAI1CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQgAAjUIAAY1CAC6NQgCgjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPWNQQCqjUEANI1BAACPQAAAj0AAAI9AAACNQwAAjj4AAI8VAACPRQALjUIAHI5C
+ ADaOQwBljUMAro1CAO2NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDyjUIAwo1CAGSNQgAVjUMAAJQaAACAgAAAgIAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1DAACNQwAijUMAQo1C
+ ACqNQgAHjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAI5BAACOQQAAj0AAEY1CAIiNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+I1CAMONQgA/jUIAAAAA
+ AAAAAAAAAAAAAICAAACbEwAAjE8AAI9EAACOQgAAfzwAAI9EABKNQwA/jUIAbo1CAKONQgDYjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD7jUIAyYxDAHKLRQAijjkAAIdFAAAA/wAAgFUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjUMAAI1DAEuNQwCSjUIAZY5CABKNQgAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj0AAAI9AAACCTQAAjUIAdI1C
+ AP6NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD7jUIA3I1CAEqNQgAAjEAAAIxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJFE
+ AACTRAAAj0MAAIxEAACfMAADjkEAM41CAHSNQgCvjUIA2I1CAPiNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA1IxDAHqLRAAjAP8AAJA7
+ AAAndwAAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlUAAAJVAAACNQgAAjUIAXo1C
+ AL+OQwCSjkMAG45DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACPQAAAj0AAAI1CAACNQgBjjUIA641CAP2NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP6NQgDzjUIAVY1C
+ AACMQAAAjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSPQAAkj0AAJM8AACUPgAAhkUABItC
+ AB6NQQBxjUIAwo1CAO2NQgD5jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA3YxCAIiLRQAeiEYABJRIAACAOAAAmTMAAJkzAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACVQAAAlUAAAI5CAACOQgBtjkIA4Y1CALWNQgAijUIAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9AAACPQAAAjUIAAI1C
+ AFONQgDRjUIA/I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP2NQgBliDcAAoxAAACMQAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJI9AACSPQAAkzwAAIxCAACYPAAAi0IAA41BABCLQgAtjUIAdo5CAMuNQgD7jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD9jUIA4o5C
+ AJiMQgAivkoAAIBCAACZMwAAmTMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJdAAACXQAAAdkcAAI5C
+ AHuNQgD8jUIA1I1CACeNQgAAkEMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQQAAjUEAQ41CALWNQgD6jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AHiQQwASj0MAAI9DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiEQAAIBJ
+ AACLQgAAjUEAAIBCAAKOQgAbjUIASIxDAIWMQwDUjUIA+41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD9jUIA441CAI+NQQAqiEgAAIE7AACBPAAAgEAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjkEAAI5BAAGPQAAOjUIAi41CAP+NQgDmjkIAMolBAACQQwAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1B
+ AACNQQAyjUEAmo1CAPmNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAi41DACSNQgAAjUIAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIpCAACKQgAAiUIAAI1DAAB4UwABi0QAIoxD
+ AGONQgCmjUIA4I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA441CAIaNQQAqlEMAAJRDAACVQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQQAAjUEAAY1B
+ ACWNQgCcjUIA/41CAO2OQgBGkkQABo9DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUEAAI1BACKNQQCAjUIA941CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgCfjEIANoxCAACMQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAi0QAAIlEAACORAAAnUcAAI1CADONQgCHjUIA041CAPONQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA4Y1CAIaMQgAdjEIAAYxC
+ AACMQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5BAACOQQACjkEAPI1CAK2NQgD/jUIA745CAF+OQwASjkMAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACLQQAAi0EAEoxCAGWNQgD1jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/4xCALOMQgBIjEIAAIxCAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAAAHw/
+ AAB7PwAAjEAAAo5EABSNQwBMjUIAuY1CAOuNQgD8jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA2o1CAICNQgATkkIAAIxCAACOQQAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEEAAIxB
+ AAOMQQBSjUIAvo1CAP+NQgDyjkIAd45CAB6OQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJBBAACeOQACjkIASo1CAPONQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jEIAx4xCAFqMQgAAjEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQAAAfD8AAHs/AACNQwAAk0wAAY1DAAyMQgAsjUIAd41C
+ AM2NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD9jUIA1YxC
+ AGeMQgAVjEIAAI5BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMQgAAjEIAA4xCAGqNQgDPjUIA/41CAPSNQgCPjUMAKY1D
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAmUAAAIlCAACOQQA5jUEA5Y1CAP6NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDajUIAbI1CAACNQgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAI5EAACNRAAAj0MAAJVDAACNQgAejUIAWY1CAKeNQgDxjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD6jUIAyY1CAFePQAAQjkIAAI1EAACNRAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAI1C
+ AACMQgAEjEIAgY1CAOCNQgD/jUIA9o1CAKeOQwA1jUMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVQAAAjUEAAI1BAC+NQQDMjUIA+I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAO6NQgB+jUIAAIxBAACMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAAAC4SQAAh0EAAI1C
+ AACSQgAHjkIAPI1CAJmNQgDajUIA+o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIAtI1CAEuNSAAFbkAAAItEAACIRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAi0MAAJBAAAWNQgCXjUIA8Y1CAP+NQgD5jkIAv45C
+ AEGOQgAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACNQQAAjUEAJ41BAK2NQgDxjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAI+PRgAAjD8AAIxA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj0IAAJJJAACgXgABj0UAGY1CAH6NQgDQjUIA+I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD+jUIAoI1DADCJRAADmT8AAItB
+ AAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANEd
+ AAB/SgAAmzoABo1CAKyNQgD/jUIA/41CAPuMQwDXjEMATYxDAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxCAACMQgAfjEIAkI1C
+ AOqNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIAnIxAAAuMQAABjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACPQgAAkUYAAIsWAACUQwADkz8AEI1CAF2NQgC+jUIA/o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDqjUIAlIpDABOIRAABh0UAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAk0MAAJhEAAKSQwAXjUIAu41CAP+NQgD/jUIA/Y1C
+ AO+NQgBZhkYAAADFAAAAxQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjUMAAI1DABeNQwBzjUIA5I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCmjkQAG45E
+ AAKORAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSSQAAuEkAAIlIAACBSQAAjkIAEY1C
+ AFKNQgCxjUIA/I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDXjkIAc5NA
+ ABCFRgAAZlYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVQAAAlUAAAJlA
+ AACPQQAAj0IABI5CAC+NQgDFjUIA/41CAP+NQgD/jUIA/Y1CAGlbTAAAj0QAAJFHAACTSwAAkkkAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOQgAAjkIAD45C
+ AFaNQgDdjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAK+NQgArjUIABI1CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAD/AAAANXUAAPUGAACNQgAAi0IAD4xCAEyNQgCujUIA8o1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPmNQgDKjUEARo0/AAuNQQAAi0YAAItGAAAAAAAAAAAAAAAA
+ AAAAAAAAikIAAIpCAACMQwAAjUMAAIxDAACMQwAAhkQAAJU9AAKNQQAbjUIAZY1CANaNQgD/jUIA/41C
+ AP+NQgD/jUIAk41CAC6QRQALp2UAAYtAAACNQgAAjUIAAI5DAACLQQAAiD8AAIlAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1BAACOQAAHjUEAOI1CANaNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAuIxB
+ ADyMQQAFjEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxC
+ AACMQwAAjEQACYxDAEONQgC2jUIA9I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APWNQgCcjEIAMI47AACKSgAAikoAAAAAAAAAAAAAAAAAAAAAAACOQgAAiUIAAoxDAAWNQwAIjEMADIxD
+ ABCPQgAYjkEALo1CAGKNQwDAjUIA8o1CAP+NQgD/jUIA/41CAP+MQQDZjUIAko9EAEiPRAAkjkMAFI1C
+ AA6NQgAKjkMAB4tBAAOGPgABi0EAAI1CAACNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkUgAAP//
+ AACPRQAdjUIAzY1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDBjUEATY1BAAaNQQAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxDAACPQAAAjUIACI1CAEyNQgC3jUIA/I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/Y1CAO2NQgBoikUADIxEAACNQwAAjkMAAAAA
+ AAAAAAAAAAAAAI5CAACJQgAQjEMAMI1DAFaMQwB7jEMAoY1CAMONQgDXjUIA441CAPWNQgD9jUIA/41C
+ AP+NQgD/jUIA/41CAPmNQgDsjUIA3Y1CANONQgC3jUIAko1CAGqOQwBEi0EAHYY+AAWLQQAAjUIAAI1C
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACTSwAAi0AAAI1DABGMQgDAjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AMqNQgBdjUIACI1CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjEMAAI1CAACRPgAAjUIACoxDAFSNQgC5jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/YxCALWMQQBLjEEAAI1DAACOQwAAAAAAAAAAAAAAAAAAjUIAYY1CAJaNQgC+jUIAzI1C
+ AN2NQgDujUIA/Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APiNQgDnjUIA1Y1CAMSNQgCzjUIAh41CAD2NQgAAjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJJJ
+ AACNQgAAjEIADo1CAK+NQgD3jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA041BAG2NQQAJjUEAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUIAAI1CAACNQgAAi0QAEYxC
+ AF6NQgDPjUIA+41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA8I1CAI+OQwAYjkMAAo5D
+ AAAAAAAAAAAAAAAAAACNQgBmjUIAqI1CANeNQgDkjUIA9Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPqNQgDpjUIA141CAMSNQgCPjUIAPo1C
+ AACNQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1CAACNQgAMjUIAnI1CAO2NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDcjUEAfo1BAAqNQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxDAACMQgAAjEAAGYxBAHONQgDfjUIA/o1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIAyI1CAFeOQgAGjUMAAIxEAAAAAAAAAAAAAJVAAAqPQQAyjUEAX41C
+ AIONQwCojUIAyY1CANmNQgDijUIA7I1CAPuNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+o1C
+ AOSNQgDRjUIAtI5BAI+MQgBni0IAPYhCABVqPAABfUAAAH1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjEIAAIxCAAuMQgCKjUIA4o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOWNQgCOjUIAC41CAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI43
+ AACLTwAAjUAAG41CAJqNQgDnjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDwjUIApYxD
+ ABWTNwAAjEQAAAAAAAAAAAAAlUAAAY9BAAWNQQAJjUIADY1DABGQRQAajkMANo1CAFyNQQCPjUIA3o1C
+ APqNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDojUEAfIxBAC6MQQARjkEADoxCAAqLQgAGiEIAAms8
+ AAB9QAAAfUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQgAAjUIACo1CAHiNQgDYjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA641CAJqNQgAMjUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjjgAAIxFAACNQQAFjEIAKYxCAK2NQgD5jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDVjEMARYxEAAuMRAAAAAAAAAAAAACUQAAAj0EAAI1B
+ AACNQgAAjEIAAH82AACRRgAGjkIAEI1CACqOQgB4jUIA3I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APaNQgDBjEEAQoI1AAKNQQAAjEIAAItCAACJQgAAdj4AAIBAAACAQAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIxDAACMQwAIjEMAZo1CAM+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDxjUIApY1CAA2NQgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACOOQAAjD8AAINPAACLQgAGjEMAVo1CAMCNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AO2OQgCVjkIAII5CAACPQAAAAAAAAAAAAAAAAAAAAAAAAJlNAACZTQAAmk4AAI9EAACNQgAAjEQAA41C
+ ADONQgDGjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPWNQgCsjUEATY0+AAuMRAAAjEIAAIxD
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEMAAIxDAAeMQwBTjUIAxI1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPeNQgCwjUIADo1CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMQgAAjEMAAIxBAACMRAAUjUIAfI1C
+ AO2NQgD+jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA+41CANiOQQBDlDoAA49AAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIo/AACIOwABiz8AFo1CALqNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAPyNQgC0jUEAUoxDABOKSQABjEIAAIxCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACNQwAAjUMABY1DAEGNQgC6jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/Y1CALuNQgAPjUIAAJkz
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACMQwAAjEMAAI1CAACNQgBAjUIAtI1CAPuNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA+I1CAHeOQQAcjUIAAIBVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzxoAAIBK
+ AACaOgAGjUIArI1CAP+NQgD/jUIA/o1CAPmNQgD3jUIA+o1CAP+NQgD/jUIA/41CAP6NQgDKjEMAWoxC
+ ABaLQQABjEIAAIpHAACLRgAAi0YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1DAACNQwAEjUMAMI1C
+ ALGNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIAxo1CABCNQwAAmTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEQAAIxF
+ ABONQwBmjUIA8Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD6jUIAtI1CAEKOQAAAfFsAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAjEMAAJFAAAWOQgCYjUIA8Y1CAP+NQgD6jUIA0IxC
+ AL2NQgDWjUIA/41CAP+NQgD/jUIA/41CAPmNQgDWjEIAcYxCAB2MQgAAikcAAItGAACLRgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjUMAAI1DAAONQwAejUIAqI1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDMjz8AFIhJ
+ AACZMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMRAAAj0EAAI1DADaNQwDMjUIA+I1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP2NQgDrjUMAZpouAACAVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8A
+ AACOQgAAjUMABI1DAIKNQgDijUIA/41CAPeNQgCujEIAYI1CAIaOQgD2jUIA/o1CAP+NQgD/jUIA/41C
+ AP2NQgDWjUMAjI1DADiUNAAAjUIAAItEAACMQwAAAAAAAAAAAAAAAAAAAAAAAAAAAACMRAAAjEQAAYxF
+ AA2NQgCejUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAM+QQwAaeDYAAJRGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxE
+ AACNQwAAjUMAHY1DAI2NQgDqjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgCOi0QAHItE
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1DAACNQwADjUMAbY1CANKNQgD/jUIA9IxC
+ AJOMQwApjkIAOY5CALKNQgD5jUIA/41CAP+NQgD/jUIA/41CAP+NQgDljUIAoI1CAEyMQwAQlEAAAI9C
+ AABuVgAA/wAAAP8AAAAAAAAAAAAAAIpHAACKRwAAfl8AAY1CAJSNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA0I1D
+ ACCPTAABjUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1BAACNQQANjUEATY1CANuNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CALmNQgBLj0AAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjkIAAI5CAAOOQgBXjUIAwo1CAP+NQgDyjUIAeo1CAB2PQAAKjUEAT41CANeNQgD8jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD3jUIAxI1CAFmNQwAfkkIABYVHAACJQgAAjEEAAIpCAAAAAAAAi0YAAIxD
+ AACNQgAAjUIAiI1CAPqNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDSjEEAJ4lAAAOLQQAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAjz0AAJUuAAGOPwAgjUIAyo1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA4Y5C
+ AHyISgADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQQAAjUEAAo1BAEKNQgCyjUIA/41C
+ AO+NQgBhjkEAE4xCAACMQgAZjEIAfo1CAOCNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD6jUIA445D
+ AISPQgAvnDgABItCAAKHQwAAikIAAAAAAACLRgAAjUIAAI1CAACNQgB7jUIA641CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ ANOOQwAukEUABY9EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPPQAAjUMAAI1CAA+NQgCxjUIA+I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAoodLAAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIxDAACMQwABjEMALI1CAKGNQgD/jUIA7Y1DAEaMRgAGjEMAAIlCAAOLQgAjjUIApo1C
+ APKNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD+jUIA5o1CALaNQgBoikIAFWZCAACLQgAAnkUAAIBA
+ AACMQQAAjEEAAIxBAG+NQgDejUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA1I9CADKSQQAGkEIAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAI89AACOQgAAjkIADI5CAJiNQgDqjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgC5jkMAMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi0MAAItDAAGLQwAWjUIAko1C
+ AP+MQgDjjEMAMY89AACHSAAAkEIAAH8/AAGMQgBHjUIAso1CAPuNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA941CAM+NQgCNjUIARYxCAA2PQgAAjUEAAKA2AACNQQAAjEEAUI1CAL6NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgDVj0EAM5JAAAaQQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5BAACOQQALjkEAh41C
+ AOGNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAMiNQgBbAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACKPwAAij8AAIM7AASNQgCDjUIA/oxCAM6MQgAmjEIAAIpFAACGPwAAjD4AAIM7
+ AASNQgBYjUIAw41CAPyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPSNQgCujEIAZIxC
+ AC+OQAAPgEoAAItDAACNQgAkjUIAbo1CALyNQgDcjUIA+I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CANSPQQAzkkAABpBBAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjUEAAI1BAAuNQQCGjUIA4I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA1I1CAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIpAAACKQAAAjUIAAI1C
+ AHSNQgDqjUEAsY1BACCNQQAAAAAAAIpAAACKQAAAj0EAAI5BAA6NQgBbjUIA2o1CAPuNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP2MQgDpjEIAqI1BAFSQQAAcj0AACopCAAKQPwAIjkEALI1D
+ AHiNQgDDjUIA6o1CAPaNQgD+jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA1I9BADOSQAAGkEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1DAACNQQAAjUEADI1B
+ AJSNQgDojUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDfjUIAnwAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAikAAAIpAAACNQgAAjUIAZY1CAMqNQgCUjUIAG41CAAAAAAAAikAAAIpA
+ AACNQQAAh0QAAI1BABmNQQBmjUIA4o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP2NQgD1jUIA341CAK2NQQBUjUEAF6swAACOQQAGjUMAEY1EACqNQwBnjUIAt41CAPKNQgD9jUIA/o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDUj0EAM5JAAAaQQQAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjUMAAI1CAACNQgAOjUIAqY1CAPONQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAOaOQgC0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxC
+ AACMQgBUjEIApo1DAHSNQwAVjUMAAAAAAAAAAAAAAAAAAI5BAACNQQAAjD4AAo1BAB6NQgCCjUIA4I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA8I1CAM+NQgChjUIAZo1B
+ ACeSKwAAjjQAAI1DABWNQgA3jEIAXI1CAIqNQQC9jUIA641CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CANSPQQAzkkAABpBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQwAAjUQAAo1D
+ ACSNQgDHjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA641CAMQAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUMAAI1DACuNQwBSjkMAN45EAAqORAAAAAAAAAAA
+ AAAAAAAAAAAAAI1BAACOQgAAj0MAAo5CACmNQgCLjUIA4I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPaNQgDOjUIAl41DAGWNQgA2jEQADJE9AAD/KAAAjUEAJIxB
+ AE+MQgB6jUIAoY1CAMSNQgDqjUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA1I9BADOSQAAGkEEAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAi0AAAI1CAACNRAAOjUMAVo1CAN6NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDujUIAzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACiVAAAoVQAAqZXAAT/zQAAAAAAAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5CAACOQgAAjkIAAI5C
+ AC2NQgCKjUIA5I1CAP6NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA5I1CAKKNQgBejEQAL45DABmKRgAFj0EAAJS1AACNRQAdjUIAVo1CAJWNQgDBjUIA2o1C
+ AOqNQgD6jUIA/41CAP+NQgDVj0EAM5JAAAaQQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkj0AAJI9AACOPgAAlEoAAI1C
+ ACqNQwChjUIA7o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAO6NQgDMAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJlNAACZTQAAm04AAKhUAACtVgAAqlUAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5CAACOQgAApkIAAI5CACiOQgCAjUIA6Y1CAP6NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD9jUIA+o1CAO2NQgDFjkMAfIxD
+ ADaLQwATjkIACIxDAAaPQQAGlj0ACY5BACSNQgBWjUIAlY1CANGNQgDtjUIA/Y1CANCPQQAykkAABpBB
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAItGAACSPgAAkzsAAINFAACLQAASjEEAYY1CAOuNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA7I5CAMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAmU0AAJlNAACbTgAAqFQAAK1WAACqVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkIAAI5C
+ AACOQgAAj0MAA45CACaOQQB7jUIA4o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPeNQgDljUIA045CAKaOQgBojEMAKvALAAGERwAAkj8AAo1C
+ AA6NQgAejEIALoxCAFaMQQCRjEEAmY5BACqQQAAGj0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi0YAAI9CAACHSwAAnTMABI1B
+ AFaNQgDIjUIA+41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDojUIAugAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5CAACOQQAAjz8AA45BACSNQgB9jUIA1o1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA8Y1CANGNQgCrjUIAgY1CAFWMQgAmekIAA41CAACPQgAAikAACoxBACuMQQA2jkAAEJBA
+ AAKPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAA/wAAAHVPAACPQQAAjzsAAItIAAuNQgBajUIAuY1CAPiNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAOGOQwCnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAI5BAACOQQAAjT0AAI5CACGNQgB0jUIAyo1CAPiNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDvjUIAwo1C
+ AI+MQgBjjUIAQY5BACaMQAAMkUQAAIxBAACNQQAAjkIAAI9BAACTPAAAkj0AAJI9AAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACLRgAAikcAAItFAACNQgAAiEUAAJU6AASNQQAljEMAYY1C
+ AMGNQgD4jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA2I5C
+ AIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5CAACOQgAAjkQAAI5F
+ ABCNQwBXjUIAxI1CAO+NQgD+jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAPKNQgDHjkEAi41BAFSLQQAvjEIAHY1B
+ ABWOQgANkEAABqMsAAGNQgAAjUIAAI1BAACNQQAAjUEAAIxDAACPQgAAk0QAAJtQAACZTQAAmU0AAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAVQAAcmwAAIZLAACMQQAAjUEAAI1C
+ AACRPAAAikcAAo1CAAuQQQAVjkEAOY1BAISMQgDgjUIA/I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDMjUEAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAjkIAAI5CAACOQwAAk0oAAYtAAAuMQAA3jUEAqY1CAOuNQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/o1CAPmNQgDxjUIA7I1CANqMQgC3jUEAiI5CAFqPQQAukT4AEI1CAAWNQgAEjUEABI1B
+ AAONQQACjEMAAY9CAAGTRAAAm1AAAJlNAACZTQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIBVAABybAAAhksAAIxBAAGNQQACjkAAAoxEAAeMRQAbjUIAT41CAJWNQgDQjUIA8I1C
+ APyNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AL+NQgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5E
+ AACMQgAAlkoAAIo+AAeOQgAwjkEAhY1CANeNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APSNQgDkjUIA041CAMWNQgC2jUIAo41CAIuNQQBzjUEAW41BAEOMQwAsj0EAGphGAAh7MQAAjUIAAI1C
+ AACNQQAAjUEAAIxCAACNQgAAjUMAAI1CAACNQgAAjkEAAI1BAACNQwAAjUMAAJA9AAAA/wAAi0EAGo1B
+ ADqOQQBjjkEAkY1CALiNQgDQjUIA6I1CAPuNQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAqo9AABYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIc8AACLPgAAhjwAAIE5AACPQQAnjUIAbY1C
+ ALqNQgD1jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD6jUIA6I1C
+ ANaNQgDFjUIAs41CAKGNQgCUjkIAh41CAHuNQgBxjUIAZo1BAFqMQQBPjEIAR41CAEONQwA+jUMAN45B
+ ADeOQQA+jUEARY1DAE2NQwBZjUIAaY1CAH6NQgCTjUIArI1CAMuNQgDsjUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AOuNQQCIlzUAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAKpVAAANAAAAoE4AAI1CAACJQgAOjEIASY5CAKqNQgDfjUIA+o1CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APaNQgDmjUIA1Y1CAMSMQgC4jUIAsY1DAKqNQgChjUIAoI5BAKqNQQC2jUIAwY1CANONQgDqjUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIAxI1BAFiMQwABAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi0IAAIxA
+ AACJQwAFi0MAHY1CAICNQgDSjUIA+Y1CAP6NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/o1CAP6NQgD9jUIA/I1CAPyNQgD7jUIA+41C
+ APuNQgD7jUIA+41CAPuNQgD8jUIA/Y1CAP6NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+MQgCVi0QAI4tEAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACLQgAAiUMAAJJAAACIRAADjUIAFY5CAFGNQgCpjUIA9I1C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD9jEMA5YxDAGZlbgAAi0QAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACIRAAAgEcAAIpDAACNQgAAj0IADo5CADmNQgB4jUIAw41CAPeNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APyMQwCcjEMAMoxDAACLRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkIAAI5CAACPQgAAiEAAAJBD
+ ABOOQgBajUIAo41CAN6NQgD+jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD7jUIA2Y1CAFCLRAALjEMAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJBDAACSRAAAjkIAAI5CAACOQgAojkIAfY5CAMyNQgDqjUIA+41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AOaNQgCKjUIAHY1CAACMQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkEMAAJJE
+ AACOQgAAjkIAAI1CAASRQQAOjkIAN41CAIqNQgDbjUIA+I1CAP2NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD3jUEAuI5BACaPQQAEjkEAAIxDAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5CAACOQgAAj0IAAIdEAACQQQAHjUIAIY1C
+ AEWNQgCJjUIA041CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AMCMQQBOjUAACIlDAACSPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACVQAAApzsAAI9BAACNQgAAehoAAI1DACeNQwBfjUIAmo1CANGNQgD6jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDMjUIAaIpBAA6HQgABjEEAAI9AAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjEAAAIxA
+ AACMQAAAjEMAAH1PAAKMRAAkjkIAbI1CAKyNQgDWjUIA8I1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD9jUIA2I1C
+ AG+NRAAbjEIAAItBAACLQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKRQAAiEYAAIxEAAGOQgAEjUMAG45C
+ AF2OQgCtjUIA441CAPGNQgD5jUIA/o1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA+41CANuNQQBtjUEAHI1AAACNQwAAjUMAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIpFAACIRgAAjEQAAI5CAACNRAADjkIADY1DACCMQwBDjUIAho1DAM2NQgD2jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP6NQgDLjkMAXY1C
+ ABmMPgACjUIAAI1DAACNQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNQwAAjUMAAI1D
+ AACNQwAAkz8AAIhGAAeNQgAkjUIAQ41CAG6NQgChjEIA0Y1CAPmNQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgDrjUIApI1DAE+OQwAUlUwAAY1CAACNQQAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIlFAACHRgAAi0QAAI1CAACJSAAAjz8ADY1C
+ ADeMQgBkjUIAjY1CALCNQgDQjUIA7Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgDujUIAwI1BAIaNQQA6hlAABY9C
+ AACNRAAAjkMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACZMwAAmTMAAOEAAACOQQAAjUIAAItAAACPSwAGjEIAL41BAGiOQQCejUIAyI1C
+ ANyNQgDpjUIA9Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APSNQgDmjUIAzo1CAJ+NQwBNkkEAD4BKAACUQgAAi0YAAItGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJkzAACZMwAA4QAAAI5B
+ AACNRQAAj0kAAI5IAAGMQgAEjUEACI9AAA+QPwAhjUEAUI1CAIiNQgC+jUIA6o1CAPWNQgD4jUIA+o1C
+ AP2NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD+jUIA+41CAPeNQgDqjUMAuY1CAHeNQgA4jEkADo1EAAaRQAABeFAAAMsg
+ AACLRgAAi0YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI5HAACORwAAjkgAAIxCAACNQQAAjUIAAJ0y
+ AAGOQAAOjUIAHY1CAC2NQQBBjkMAZo1CAI+NQgC6jUIA4Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAO+NQgDAjUIAg41D
+ AEqNQwAsjUIAGI1CAAiPOAAAjUEAAJFCAAB2UAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI9AACTPAAAkj0AAI5BAACNQQAAjUQAAIlSAACQRAASjkMAK41C
+ AEWNQgBfjUIAeY1CAJKNQgCqjUIAwI1CANONQgDkjUIA9Y1CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ AP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41CAP+NQgD/jUIA/41C
+ APWNQgDcjUIAwI1CAKSNQgCIjUIAao1CAEmNQgAkiE0AA45BAACNQgAAjUIAAHmkAAB6nwAAgIAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAI45AACNMQAAjj0AAI9EAACOQwAAjUIAAI9EAAB7MQAEi0MAHY1CADqNQQBVjUIAa41D
+ AH+NQgCTjUIApI1CALKNQgC8jUIAxo1CAM2NQgDTjUIA2Y1CAN6NQgDijUIA441CAOONQgDjjUIA441C
+ AOONQgDhjUIA2o1CANONQgDLjUIAw41CALuNQgCujUIAlY5DAHWOQwBUjEIAM4xCABGQQgAAjUIAAI1C
+ AACLRQAAikcAAItGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACHPAAAhjsAAIc9AACLQgABjUIAAY1BAAKNQgACjUMAAo1BAAKORgAJjUQAG4tBADiMQgBVjUIAa41C
+ AHyNQgCOjUIAnY1CAKiNQgCrjUIAq41CAKuNQgCrjUIArI1CAKSNQgCRjEMAe4xCAGSNQgBOj0EANJJD
+ ABaRQwAGi0IAAo5DAAKMQgABjEIAAIxCAACMQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAA//////
+ /wAAAAP//wAAAAAP//////8AAAAD//8AAAAAB///////AAAAA///wAAAAAf//////AAAAAP//8AAAAAH
+ //////wAAAAH///AAAAAB//////8AAAAB///4AAAAAH//////AAAAAf///AAAAAB//////wAAAAH///w
+ AAAAAf/////8AAAAD///8AAAAAH//////AAAAA////gAAAAA//////gAAAAP///4AAAAAP/////4AAAA
+ H////gAAAAD/////+AAAAB////8AAAAA//////gAAAAf////AAAAAP/////4AAAAH////wAAAAB/////
+ 8AAAAB////+AAAAAf/////AAAAB/////gAAAAH/////wAAAAf////4AAAAB/////8AAAAH/////gAAAA
+ H/////AAAAB/////4AAAAB/////gAAAA/////+AAAAAf////4AAAAP/////wAAAAH////+AAAAD/////
+ 8AAAAB/////gAAAA//////AAAAAP////4AAAAP/////4AAAAD////+AAAAH/////+AAAAA////+AAAAB
+ //////gAAAAP////gAAAAf/////8AAAAD////4AAAAH//////AAAAAf///+AAAAB//////wAAAAH////
+ gAAAB///////AAAAB////4AAAAf//////wAAAAf///+AAAAH//////8AAAAH////gAAAB///////AAAA
+ A////wAAAAf//////4AAAAA///8AAAAP//////+AAAAAAH//AAAAD///////gAAAAAB//wAAAA//////
+ /4AAAAAAA/8AAAAP//////wAAAAAAAAfAAAAD//////4AAAAAAAAAQAAAA//////+AAAAAAAAAEAAAAP
+ /////+AAAAAAAAAAAAAAH/////+AAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAf/////wAAAAAAAAAA
+ AAAAH/////8AAAAAAAAAAAAAAB/////+AAAAAAAAAAAAAAAf////+AAAAAAAAAAAAAAAH/////gAAAAA
+ AAAAAAAAAD/////4AAAAAAAAAAAAAAA/////8AAAAAAAAAAAAAAAP/////AAAAAAAAAAAAAAAD/////g
+ AAAAAAAAAAAAAAA/////4AAAAAAAAAAAAAAAP////+AAAAAAAAAAAAAAAD/////gAPwAAAAAAAAAAAA/
+ ////4A/8AAAAAAAAAAAAH////+B//AAAAAAAAAAAAA/////gf/wAAAAAAAAAAAAP////wP/+AAAAAAAA
+ AAAAAf///8D//gAAADgAAAAAAAD////A//4AAAAPgAAAAAAAf///AP/+AAAAD+AAAAAAAB///wD//gAA
+ AA/gAAAAAAAf//8Af/+AAAAP/AAAAAAAD///AH//gAAAD/8AAAAAAA///wB//4AAAA//4AAAAAAH//8A
+ f/+AAAAP//AAAAAAA///AH//gAAAD//wAAAAAAP//wB//4AAAA///gAAAAAA//4Af/+AAAAH//8AAAAA
+ AH/+AB//wAAAB///4AAAAAA//gAf/8AAAAf//+AAAAAAP/4AH//AAAAH///wAAAAAD/wAAf/wAAAB///
+ +AAAAAAPAAAAP8AAAAf///8AAAAADwAAAA/AAAAH////gAAAAAcAAAAPwAAAB////4AAAAAHAAAAD8AA
+ AAf////AAAAABwAAAA/gAAAH////8AAAAAMAAAAP4AAAB/////gAAAADAAAAD+AAAAf////4AAAAAwAA
+ AA/gAAAH////+AAAAAHgAAB/4AAAB/////wAAAAB/gAAP+AAAAP////+AAAAAP4AAAfgAAAD/////4AA
+ AAD+AAAH4AAAA/////+AAAAA/gAAA+AAAAP/////gAAAAP8AAABgAAAD/////8AAAAD/AAAAIAAAA///
+ ///AAAAA/wAAACAAAAP/////wAAAAP8AAAAAAAAD/////8AAAAD/AAAAAAAAA//////gAAAA/wAAAAAA
+ AAP/////4AAAAP8AgAAAAAAD/////8AAAAD/AIAAAAAAA//////AAAAA/8DgAAAAAAP/////wAAAAP/A
+ 8AAAAAAD/////4AAAAD/wPgAAAAAA/////4AAAAA/8D8AAAAAAP////8AAAAAP/A/AAAAAAD/////AAA
+ AAD///8AAAAAA/////AAAAAA////gAAAAAB///+AAAAAAP///8AAAAAAAD/wAAAAAAD////AAAAAAAA/
+ 8AAAAAAA////8AAAAAAAAAAAAAAAAP////gAAAAAAAAAAAAAAAD////8AAAAAAAAAAAAAAAA/////4AA
+ AAAAAAAAAAAAAP////+AAAAAAAAAAAAAAAD/////wAAAAAAAAAAAAAAA//////AAAAAAAAAAAAAAAf//
+ ///8AAAAAAAAAAAAAAH//////AAAAAAAAAAAAAAB//////8AAAAAAAAAAAAAA///////wAAAAAAAAAAA
+ AAP///////AAAAAAAAAAAAAH///////+AAAAAAAAAAAAD////////gAAAAAAAAAAAA////////+AAAAA
+ AAAAAAA/////////8AAAAAAAAAAAf/////////wAAAAAAAAAAP/////////8AAAAAAAAAAD/////////
+ /8AAAAAAAAAD///////////8AAAAAAAAD////////////8AAAAAAAP/////////////+AAAAAA///4lQ
+ TkcNChoKAAAADUlIRFIAAAEAAAABAAgGAAAAXHKoZgAAAAFvck5UAc+id5oAAGDkSURBVHja7b15lCX5
+ Vd/5uRFvy5d7Vmbte3dVL+pFau0CoVZ3Ix0E2DPjwXjGnsU2Nvaxh2MWA2MPnsYeGyEhyWgQBm/MscE+
+ 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
+
+
+
\ No newline at end of file
diff --git a/Check.Main/Infer/DetectionCoordinator.cs b/Check.Main/Infer/DetectionCoordinator.cs
new file mode 100644
index 0000000..e472ece
--- /dev/null
+++ b/Check.Main/Infer/DetectionCoordinator.cs
@@ -0,0 +1,149 @@
+using Check.Main.Camera;
+using Check.Main.Common;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Check.Main.Infer
+{
+ public static class DetectionCoordinator
+ {
+ ///
+ /// 定义存储所有相机处理器的字典
+ /// 键是相机的唯一编号 (CameraIndex),值是对应的处理器实例。
+ ///
+ private static ConcurrentDictionary _processors = new ConcurrentDictionary();
+ ///
+ /// 用于在产品组装时进行同步,确保线程安全
+ ///
+ private static ConcurrentDictionary _productAssemblies = new ConcurrentDictionary();
+ ///
+ /// 可用的相机数量
+ ///
+ private static int _enabledCameraCount = 0;
+
+ public static event EventHandler OnDetectionCompleted;
+ public static bool IsDetectionRunning { get; private set; } = false;
+
+ // OnDetectionCompleted 事件现在也属于这里
+ //public static event EventHandler OnDetectionCompleted;
+
+ public static void StartDetection()
+ {
+ if (!IsDetectionRunning)
+ {
+ IsDetectionRunning = true;
+ ThreadSafeLogger.Log("检测统计已启动。");
+ }
+ }
+
+ public static void StopDetection()
+ {
+ if (IsDetectionRunning)
+ {
+ IsDetectionRunning = false;
+ ThreadSafeLogger.Log("检测统计已停止。");
+ }
+ }
+ public static void Initialize(List cameraSettings, List modelSettings)
+ {
+ Shutdown(); // 先关闭旧的
+ var enabledCameras = cameraSettings.Where(c => c.IsEnabled).ToList();
+ _enabledCameraCount = enabledCameras.Count;
+ if (_enabledCameraCount == 0) return;
+
+ foreach (var camSetting in enabledCameras)
+ {
+ // 找到与相机编号匹配的模型
+ var model = modelSettings.FirstOrDefault(m => m.Id == camSetting.ModelID);
+ if (model == null)
+ {
+ ThreadSafeLogger.Log($"[警告] 找不到与相机 #{camSetting.CameraIndex} 匹配的模型,该相机将无法处理图像。");
+ continue;
+ }
+
+ var processor = new CameraProcessor(camSetting.CameraIndex,camSetting.ModelID);
+ _processors.TryAdd(camSetting.CameraIndex, processor);
+ processor.Start();
+ }
+ ThreadSafeLogger.Log($"检测协调器已初始化,启动了 {_processors.Count} 个相机处理线程。");
+ }
+
+ public static void EnqueueImage(int cameraIndex, Bitmap bmp)
+ {
+ if (_processors.TryGetValue(cameraIndex, out var processor))
+ {
+ processor.EnqueueImage(bmp);
+ }
+ else
+ {
+ // 如果找不到处理器,必须释放Bitmap防止泄漏
+ bmp?.Dispose();
+ }
+ }
+
+ // 供 CameraProcessor 回调,用以组装产品
+ public static void AssembleProduct(ImageData data, string result)
+ {
+ var assembly = _productAssemblies.GetOrAdd(data.ProductId, (id) => new ProductAssembly(id, _enabledCameraCount));
+
+ if (assembly.AddResult(data.CameraIndex, result))
+ {
+ string finalResult = assembly.GetFinalResult();
+ ThreadSafeLogger.Log($"产品 #{assembly.ProductId} 已检测完毕,最终结果: {finalResult}");
+
+ // 只有在检测运行时,才触发事件
+ if (IsDetectionRunning)
+ {
+ OnDetectionCompleted?.Invoke(null, new DetectionResultEventArgs(finalResult == "OK"));
+ }
+
+ if (_productAssemblies.TryRemove(assembly.ProductId, out var finishedAssembly))
+ {
+ finishedAssembly.Dispose();
+ }
+ }
+ }
+ ///
+ /// 命令所有活动的相机处理器重置它们的内部计数器。
+ ///
+ public static void ResetAllCounters()
+ {
+ foreach (var processor in _processors.Values)
+ {
+ processor.ResetCounter();
+ }
+ ThreadSafeLogger.Log("所有相机处理器的产品计数器已重置。");
+ }
+
+ public static CameraProcessor GetProcessor(int cameraIndex)
+ {
+ _processors.TryGetValue(cameraIndex, out var p);
+ return p;
+ }
+ public static IEnumerable GetAllProcessors()
+ {
+ return _processors.Values;
+ }
+
+
+ public static void Shutdown()
+ {
+ foreach (var processor in _processors.Values)
+ {
+ processor.Dispose();
+ }
+ _processors.Clear();
+
+ foreach (var assembly in _productAssemblies.Values)
+ {
+ assembly.Dispose();
+ }
+ _productAssemblies.Clear();
+ ThreadSafeLogger.Log("检测协调器已关闭。");
+ }
+ }
+}
diff --git a/Check.Main/Infer/ModelSettings.cs b/Check.Main/Infer/ModelSettings.cs
new file mode 100644
index 0000000..cf05f07
--- /dev/null
+++ b/Check.Main/Infer/ModelSettings.cs
@@ -0,0 +1,131 @@
+using Check.Main.Common;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Check.Main.Infer
+{
+ public enum DetectDevice
+ {
+ [Description("CPU")]
+ CPU = 0,
+
+ [Description("GPU")]
+ GPU,
+
+ [Description("VPU")]
+ VPU,
+ }
+ public enum ModelVersion
+ {
+ [Description("v8")]
+ V8 = 0,
+
+ [Description("v11")]
+ V11,
+ }
+ public enum CheckModelType
+ {
+ [Description("分类")]
+ Classification,
+
+ [Description("检测")]
+ ObjectDetection,
+
+ [Description("OBB")]
+ ObbDetection,
+
+ [Description("分割")]
+ Segmentation,
+
+ [Description("位姿")]
+ PoseEstimation
+ }
+
+ [Serializable] // 确保可被XML序列化
+ public class ModelSettings : INotifyPropertyChanged, ICloneable
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ private int _id;
+ private string _name = "New Model";
+ private string _path = "";
+ private DetectDevice _checkDevice=DetectDevice.CPU;
+ private ModelVersion _mVersion=ModelVersion.V8;
+ private CheckModelType _mType = CheckModelType.Classification;
+ private bool _isEnabled = true;
+
+ [Category("基本信息"), DisplayName("模型编号"), Description("模型的唯一标识符,用于与相机编号对应。")]
+ public int Id
+ {
+ get => _id;
+ set { if (_id != value) { _id = value; OnPropertyChanged(); } }
+ }
+
+ [Category("基本信息"), DisplayName("模型名称"), Description("给模型起一个易于识别的别名。")]
+ public string Name
+ {
+ get => _name;
+ set { if (_name != value) { _name = value; OnPropertyChanged(); } }
+ }
+ [Category("基本信息"), DisplayName("推理设备"), Description("推理模型的设备。")]
+ [TypeConverter(typeof(EnumDescriptionTypeConverter))]
+ public DetectDevice CheckDevice
+ {
+ get => _checkDevice;
+ set { if (_checkDevice != value) { _checkDevice = value; OnPropertyChanged(); } }
+ }
+
+ [Category("基本信息"), DisplayName("模型版本"), Description("推理模型的版本。")]
+ [TypeConverter(typeof(EnumDescriptionTypeConverter))]
+ public ModelVersion MVersion
+ {
+ get => _mVersion;
+ set { if (_mVersion != value) { _mVersion = value; OnPropertyChanged(); } }
+ }
+ [Category("基本信息"), DisplayName("模型类型"), Description("推理模型的类型。")]
+ [TypeConverter(typeof(EnumDescriptionTypeConverter))]
+ public CheckModelType MType
+ {
+ get => _mType;
+ set { if (_mType != value) { _mType = value; OnPropertyChanged(); } }
+ }
+
+ [Category("基本信息"), DisplayName("是否启用"), Description("是否在程序启动时是否启用模型")]
+ public bool IsEnabled
+ {
+ get => _isEnabled;
+ set
+ {
+ if (_isEnabled != value)
+ {
+ _isEnabled = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ [Category("文件"), DisplayName("模型路径"), Description("选择模型文件(.onnx, .bin, etc., .pt)。")]
+ [Editor(typeof(System.Windows.Forms.Design.FileNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
+ public string Path
+ {
+ get => _path;
+ set { if (_path != value) { _path = value; OnPropertyChanged(); } }
+ }
+
+ protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+
+ public object Clone()
+ {
+ return this.MemberwiseClone(); // 浅克隆对于这个类足够了
+ }
+ }
+}
diff --git a/Check.Main/Infer/YoloModelManager.cs b/Check.Main/Infer/YoloModelManager.cs
new file mode 100644
index 0000000..927da00
--- /dev/null
+++ b/Check.Main/Infer/YoloModelManager.cs
@@ -0,0 +1,102 @@
+using Check.Main.Common;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using YoloDotNet;
+using YoloDotNet.Models;
+
+namespace Check.Main.Infer
+{
+ ///
+ /// 静态全局YOLO模型管理器。
+ /// 负责在程序启动时加载所有模型,并在关闭时释放资源。
+ ///
+ public static class YoloModelManager
+ {
+ // 使用 ConcurrentDictionary 保证线程安全
+ private static readonly ConcurrentDictionary _loadedModels = new ConcurrentDictionary();
+
+ ///
+ /// 根据模型配置列表初始化所有YOLO模型实例。
+ /// 应在程序启动时调用一次。
+ ///
+ /// 模型配置列表。
+ public static void Initialize(List modelSettings)
+ {
+ Shutdown(); // 先确保清理掉旧实例
+
+ if (modelSettings == null) return;
+
+ ThreadSafeLogger.Log("开始加载YOLO模型...");
+ foreach (var setting in modelSettings)
+ {
+ bool gpuUse = false;
+ if (setting.CheckDevice == DetectDevice.GPU)
+ {
+ gpuUse = true;
+ }
+
+ if (string.IsNullOrEmpty(setting.Path) || !File.Exists(setting.Path))
+ {
+ ThreadSafeLogger.Log($"[警告] 模型 '{setting.Name}' (ID: {setting.Id}) 路径无效或文件不存在,已跳过加载。");
+ continue;
+ }
+
+ try
+ {
+ // 创建YOLO实例
+ var yolo = new Yolo(new YoloOptions
+ {
+ OnnxModel = setting.Path,
+ // 您可以根据需要从配置中读取这些值
+ ModelType = (YoloDotNet.Enums.ModelType)setting.MType,
+ Cuda = gpuUse, // 推荐使用GPU
+ PrimeGpu = false
+ });
+
+ if (_loadedModels.TryAdd(setting.Id, yolo))
+ {
+ ThreadSafeLogger.Log($"成功加载模型 '{setting.Name}' (ID: {setting.Id})。");
+ }
+ }
+ catch (Exception ex)
+ {
+ ThreadSafeLogger.Log($"[错误] 加载模型 '{setting.Name}' (ID: {setting.Id}) 失败: {ex.Message}");
+ }
+ }
+ ThreadSafeLogger.Log($"YOLO模型加载完成,共成功加载 {_loadedModels.Count} 个模型。");
+ }
+
+ ///
+ /// 获取指定ID的已加载YOLO模型。
+ ///
+ /// 模型编号。
+ /// Yolo实例,如果未找到则返回null。
+ public static Yolo GetModel(int modelId)
+ {
+ _loadedModels.TryGetValue(modelId, out var yolo);
+ return yolo;
+ }
+
+ ///
+ /// 释放所有已加载的YOLO模型资源。
+ /// 应在程序关闭时调用。
+ ///
+ public static void Shutdown()
+ {
+ if (_loadedModels.Count > 0)
+ {
+ ThreadSafeLogger.Log("正在释放所有YOLO模型...");
+ foreach (var yolo in _loadedModels.Values)
+ {
+ yolo?.Dispose();
+ }
+ _loadedModels.Clear();
+ ThreadSafeLogger.Log("所有YOLO模型已释放。");
+ }
+ }
+ }
+}
diff --git a/Check.Main/Program.cs b/Check.Main/Program.cs
new file mode 100644
index 0000000..0354e6b
--- /dev/null
+++ b/Check.Main/Program.cs
@@ -0,0 +1,28 @@
+using System.Diagnostics;
+
+namespace Check.Main
+{
+ internal static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ var current = Process.GetCurrentProcess();
+ var others = Process.GetProcessesByName(current.ProcessName)
+ .Where(p => p.Id != current.Id);
+ if (others.Any())
+ {
+ MessageBox.Show("ѾУظ", "ʾ",
+ MessageBoxButtons.OK, MessageBoxIcon.Information);
+ return;
+ }
+ // To customize application configuration such as set high DPI settings or default font,
+ // see https://aka.ms/applicationconfiguration.
+ ApplicationConfiguration.Initialize();
+ Application.Run(new FrmMain());
+ }
+ }
+}
\ No newline at end of file
diff --git a/Check.Main/Result/ProductResult.cs b/Check.Main/Result/ProductResult.cs
new file mode 100644
index 0000000..d5be058
--- /dev/null
+++ b/Check.Main/Result/ProductResult.cs
@@ -0,0 +1,74 @@
+using Check.Main.Common;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Check.Main.Result
+{
+ ///
+ /// 代表一个待检测产品的类,存储来自多个相机的图像
+ ///
+ public class ProductResult
+ {
+ ///
+ /// 产品唯一ID,可以是时间戳或触发计数
+ ///
+ public long ProductID { get; }
+
+ ///
+ /// 存储每个相机名称和其拍摄到的图像
+ ///
+ public Dictionary CapturedImages { get; }
+
+ public ProductResult(long productID)
+ {
+ ProductID = productID;
+ CapturedImages = new Dictionary();
+ }
+
+ ///
+ /// 添加一张某个相机拍摄的图像
+ ///
+ /// 相机名称
+ /// 拍摄的图像
+ public void AddImage(string cameraName, Bitmap image)
+ {
+ if (!CapturedImages.ContainsKey(cameraName))
+ {
+ CapturedImages.Add(cameraName, image);
+ }
+ else
+ {
+ // 如果这个键已经存在,说明发生了逻辑错误。
+ // 我们不应该持有这个新的 image 对象,必须释放它以防泄漏。
+ ThreadSafeLogger.Log($"[警告] 相机 {cameraName} 为产品 #{this.ProductID} 发送了重复的图像。多余的图像将被丢弃。");
+ image?.Dispose();
+ }
+ }
+
+ ///
+ /// 检查是否所有预期的相机都已完成拍摄
+ ///
+ /// 预期的相机数量
+ ///
+ public bool IsComplete(int expectedCameraCount)
+ {
+ return CapturedImages.Count == expectedCameraCount;
+ }
+
+ ///
+ /// 释放所有图像资源,防止内存泄漏
+ ///
+ public void Dispose()
+ {
+ foreach (var image in CapturedImages.Values)
+ {
+ image?.Dispose();
+ }
+ CapturedImages.Clear();
+ }
+ }
+}
diff --git a/Check.Main/UI/FormControlPanel.Designer.cs b/Check.Main/UI/FormControlPanel.Designer.cs
new file mode 100644
index 0000000..3e0283e
--- /dev/null
+++ b/Check.Main/UI/FormControlPanel.Designer.cs
@@ -0,0 +1,113 @@
+namespace Check.Main.UI
+{
+ partial class FormControlPanel
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.uiTableLayoutPanel1 = new Sunny.UI.UITableLayoutPanel();
+ this.btnStartDevice = new Sunny.UI.UIButton();
+ this.btnStartCheck = new Sunny.UI.UIButton();
+ this.uiTableLayoutPanel1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // uiTableLayoutPanel1
+ //
+ this.uiTableLayoutPanel1.ColumnCount = 2;
+ this.uiTableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
+ this.uiTableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
+ this.uiTableLayoutPanel1.Controls.Add(this.btnStartDevice, 0, 1);
+ this.uiTableLayoutPanel1.Controls.Add(this.btnStartCheck, 0, 3);
+ this.uiTableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.uiTableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
+ this.uiTableLayoutPanel1.Name = "uiTableLayoutPanel1";
+ this.uiTableLayoutPanel1.RowCount = 5;
+ this.uiTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 11.38585F));
+ this.uiTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 35.35353F));
+ this.uiTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 7.575758F));
+ this.uiTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.83838F));
+ this.uiTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 11.38585F));
+ this.uiTableLayoutPanel1.Size = new System.Drawing.Size(230, 198);
+ this.uiTableLayoutPanel1.TabIndex = 0;
+ this.uiTableLayoutPanel1.TagString = null;
+ //
+ // btnStartDevice
+ //
+ this.uiTableLayoutPanel1.SetColumnSpan(this.btnStartDevice, 2);
+ this.btnStartDevice.Cursor = System.Windows.Forms.Cursors.Hand;
+ this.btnStartDevice.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.btnStartDevice.FillPressColor = System.Drawing.Color.LimeGreen;
+ this.btnStartDevice.FillSelectedColor = System.Drawing.Color.LimeGreen;
+ this.btnStartDevice.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnStartDevice.Location = new System.Drawing.Point(3, 25);
+ this.btnStartDevice.MinimumSize = new System.Drawing.Size(1, 1);
+ this.btnStartDevice.Name = "btnStartDevice";
+ this.btnStartDevice.Size = new System.Drawing.Size(224, 64);
+ this.btnStartDevice.TabIndex = 0;
+ this.btnStartDevice.Text = "启动设备";
+ this.btnStartDevice.TipsFont = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnStartDevice.Click += new System.EventHandler(this.btnStartDevice_Click);
+ //
+ // btnStartCheck
+ //
+ this.uiTableLayoutPanel1.SetColumnSpan(this.btnStartCheck, 2);
+ this.btnStartCheck.Cursor = System.Windows.Forms.Cursors.Hand;
+ this.btnStartCheck.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.btnStartCheck.FillPressColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(192)))), ((int)(((byte)(0)))));
+ this.btnStartCheck.FillSelectedColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(192)))), ((int)(((byte)(0)))));
+ this.btnStartCheck.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnStartCheck.Location = new System.Drawing.Point(3, 110);
+ this.btnStartCheck.MinimumSize = new System.Drawing.Size(1, 1);
+ this.btnStartCheck.Name = "btnStartCheck";
+ this.btnStartCheck.Size = new System.Drawing.Size(224, 61);
+ this.btnStartCheck.TabIndex = 1;
+ this.btnStartCheck.Text = "开始检测";
+ this.btnStartCheck.TipsFont = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnStartCheck.Click += new System.EventHandler(this.btnStartCheck_Click);
+ //
+ // FormControlPanel
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(230, 198);
+ this.ControlBox = false;
+ this.Controls.Add(this.uiTableLayoutPanel1);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "FormControlPanel";
+ this.Text = "启动管理";
+ this.uiTableLayoutPanel1.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private Sunny.UI.UITableLayoutPanel uiTableLayoutPanel1;
+ private Sunny.UI.UIButton btnStartDevice;
+ private Sunny.UI.UIButton btnStartCheck;
+ }
+}
\ No newline at end of file
diff --git a/Check.Main/UI/FormControlPanel.cs b/Check.Main/UI/FormControlPanel.cs
new file mode 100644
index 0000000..578b166
--- /dev/null
+++ b/Check.Main/UI/FormControlPanel.cs
@@ -0,0 +1,264 @@
+using Check.Main.Camera;
+using Check.Main.Common;
+using Check.Main.Infer;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using WeifenLuo.WinFormsUI.Docking;
+
+namespace Check.Main.UI
+{
+ public partial class FormControlPanel : DockContent
+ {
+
+ private bool _isDeviceReady = false; // 新的状态:设备是否已准备好
+ private bool _isDetecting = false; // 新的状态:是否正在检测中
+
+ // 用于跟踪设备运行状态的私有标志
+ private bool _isDeviceRunning = false;
+ public FormControlPanel()
+ {
+ InitializeComponent();
+
+ ConfigurationManager.OnConfigurationChanged += HandleConfigurationChanged;
+ UpdateUI();
+
+ }
+ ///
+ /// 处理全局配置在其他地方(如 FrmConfig)被更改的事件
+ ///
+ private void HandleConfigurationChanged()
+ {
+ // 这是一个安全措施。如果设备正在运行时配置发生了变化,
+ // 最安全的做法是停止设备,以防止出现不可预知的行为。
+ if (_isDeviceRunning)
+ {
+ // 使用 Invoke 确保UI更新在正确的线程上执行
+ this.Invoke((Action)(() =>
+ {
+ ThreadSafeLogger.Log("相机配置已在运行时发生更改,设备将自动停止。请重新启动设备以应用新配置。");
+ //MessageBox.Show("相机配置已在运行时发生更改,设备将自动停止。请重新启动设备以应用新配置。",
+ // "配置变更", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ // 触发与点击“关闭设备”按钮相同的逻辑
+ btnStartDevice_Click(this, EventArgs.Empty);
+ }));
+ }
+ }
+ private void btnStartDevice_Click(object sender, EventArgs e)
+ {
+ if (_isDeviceReady)//_isDeviceRunning
+ {
+ // --- 关闭流程 ---
+ ThreadSafeLogger.Log("用户点击“关闭设备”,开始完整关闭流程...");
+ // 如果正在检测,先停止它
+ if (_isDetecting)
+ {
+ btnStartCheck_Click(this, EventArgs.Empty); // 调用停止检测的逻辑
+ }
+ var mainForm = this.DockPanel.FindForm() as FrmMain;
+ CameraManager.Shutdown();
+ _isDeviceReady = false;
+
+ //// 1. 停止硬触发模拟器
+ //CameraManager.StopHardwareTriggerSimulator();
+
+ //// 2. 如果检测正在运行,则停止
+ //if (DetectionCoordinator.IsDetectionRunning)
+ //{
+ // DetectionCoordinator.StopDetection();
+ // UpdateDetectionButtonUI();
+ //}
+
+ // 3. 执行完整的系统关闭(包括相机硬件和检测协调器)
+ //CameraManager.Shutdown();
+ //YoloModelManager.Shutdown();
+ //_isDeviceRunning = false;
+ }
+ else
+ {
+ // --- 启动流程 ---
+ ThreadSafeLogger.Log("用户点击“启动设备”,开始新的启动流程...");
+
+ // 1. 从单一数据源获取完整的配置对象
+ var config = ConfigurationManager.GetCurrentConfig();
+ // 2. 验证相机配置的有效性
+ if (config.CameraSettings == null || !config.CameraSettings.Any(c => c.IsEnabled))
+ {
+ ThreadSafeLogger.Log("没有已启用的相机配置,启动中止。");
+ return;
+ }
+ // 3. 获取主窗体引用
+ var mainForm = this.DockPanel.FindForm() as FrmMain;
+ if (mainForm == null)
+ {
+ ThreadSafeLogger.Log("无法找到主窗体,启动中止。");
+ return;
+ }
+ // 4. 执行新的启动流程:
+ // 第一步:初始化系统。这会准备好相机硬件、UI窗口和所有后台处理线程。
+ CameraManager.PrepareAll(config, mainForm);
+ _isDeviceReady = true;
+
+
+ //YoloModelManager.Initialize(config.ModelSettings);
+ //CameraManager.Initialize(config, mainForm);
+ //// 第二步:命令所有相机开始采集图像。
+ //CameraManager.StartAll();
+
+ //// 5. 如果有任何相机配置为软触发模式,我们启动模拟器来模拟触发信号
+ //if (config.CameraSettings.Any(c => c.IsEnabled && c.TriggerMode == TriggerModeType.Software))
+ //{
+ // ThreadSafeLogger.Log("检测到软触发相机,启动触发模拟器。");
+ // CameraManager.TriggerInterval = 100; // 根据需要设置间隔
+ // CameraManager.StartHardwareTriggerSimulator();
+ //}
+
+ //_isDeviceRunning = true;
+ }
+ UpdateUI();//UpdateDeviceButtonUI();
+ }
+
+ private void btnStartCheck_Click(object sender, EventArgs e)
+ {
+ if (_isDetecting)
+ {
+ // --- 停止检测 ---
+ ThreadSafeLogger.Log("用户点击“停止检测”,暂停数据流...");
+ // 停止硬触发模拟器
+ CameraManager.StopHardwareTriggerSimulator();
+ // 停止相机采集
+ CameraManager.StopAll();
+
+ // 停止统计
+ DetectionCoordinator.StopDetection();
+
+ _isDetecting = false;
+ }
+ else
+ {
+ // --- 开始检测 ---
+ ThreadSafeLogger.Log("用户点击“开始检测”,启动数据流...");
+
+ // 命令相机开始采集
+ CameraManager.StartAll();
+
+ // 启动硬触发模拟器(如果需要)
+ var config = ConfigurationManager.GetCurrentConfig();
+ if (config.CameraSettings.Any(c => c.IsEnabled && c.TriggerMode == TriggerModeType.Software))
+ {
+ CameraManager.TriggerInterval = 100;
+ CameraManager.StartHardwareTriggerSimulator();
+ }
+
+ // 开始统计
+ DetectionCoordinator.StartDetection();
+
+ _isDetecting = true;
+ }
+ UpdateUI();
+
+ //if (!_isDeviceRunning && !DetectionCoordinator.IsDetectionRunning)
+ //{
+ // ThreadSafeLogger.Log("设备未启动,无法开始检测。");
+ // return;
+ //}
+
+ //// 现在调用 DetectionCoordinator 中的方法
+ //if (DetectionCoordinator.IsDetectionRunning)
+ //{
+ // DetectionCoordinator.StopDetection();
+ //}
+ //else
+ //{
+ // DetectionCoordinator.StartDetection();
+ //}
+ //UpdateDetectionButtonUI();
+ }
+
+ #region UI 更新辅助方法
+
+ ///
+ /// 根据设备运行状态更新“设备”按钮的UI(文本和颜色)。
+ ///
+ private void UpdateDeviceButtonUI()
+ {
+ if (_isDeviceRunning)
+ {
+ btnStartDevice.Text = "关闭设备";
+ btnStartDevice.BackColor = Color.Salmon;
+ }
+ else
+ {
+ btnStartDevice.Text = "启动设备";
+ btnStartDevice.BackColor = SystemColors.Control;
+ }
+ }
+ // 统一的UI更新方法
+ private void UpdateUI()
+ {
+ // --- 更新“设备”按钮 ---
+ if (_isDeviceReady)
+ {
+ btnStartDevice.Text = "关闭设备";
+ btnStartDevice.BackColor = Color.Salmon;
+ btnStartCheck.Enabled = true; // 设备就绪后,检测按钮才可用
+ }
+ else
+ {
+ btnStartDevice.Text = "启动设备";
+ btnStartDevice.BackColor = SystemColors.Control;
+ btnStartCheck.Enabled = false; // 设备未就绪,检测按钮不可用
+ }
+
+ // --- 更新“检测”按钮 ---
+ if (_isDetecting)
+ {
+ btnStartCheck.Text = "停止检测";
+ btnStartCheck.BackColor = Color.LightGreen;
+ btnStartDevice.Enabled = false; // 正在检测时,不允许关闭设备
+ }
+ else
+ {
+ btnStartCheck.Text = "开始检测";
+ btnStartCheck.BackColor = SystemColors.Control;
+ if (_isDeviceReady) btnStartDevice.Enabled = true; // 停止检测后,允许关闭设备
+ }
+ }
+
+ ///
+ /// 根据检测运行状态更新“检测”按钮的UI(文本和颜色)。
+ ///
+ private void UpdateDetectionButtonUI()
+ {
+ //if (CameraManager.IsDetectionRunning)
+ //{
+ // btnStartCheck.Text = "停止检测";
+ // btnStartCheck.BackColor = Color.LightGreen;
+ //}
+ //else
+ //{
+ // btnStartCheck.Text = "启动检测";
+ // btnStartCheck.BackColor = SystemColors.Control;
+ //}
+ if (DetectionCoordinator.IsDetectionRunning)
+ {
+ btnStartCheck.Text = "停止检测";
+ btnStartCheck.BackColor = Color.LightGreen;
+ }
+ else
+ {
+ btnStartCheck.Text = "启动检测";
+ btnStartCheck.BackColor = SystemColors.Control;
+ }
+
+ }
+
+ #endregion
+ }
+}
diff --git a/Check.Main/UI/FormControlPanel.resx b/Check.Main/UI/FormControlPanel.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/Check.Main/UI/FormControlPanel.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Check.Main/UI/FormImageDisplay.Designer.cs b/Check.Main/UI/FormImageDisplay.Designer.cs
new file mode 100644
index 0000000..3e9a70e
--- /dev/null
+++ b/Check.Main/UI/FormImageDisplay.Designer.cs
@@ -0,0 +1,46 @@
+namespace Check.Main.UI
+{
+ partial class FormImageDisplay
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.SuspendLayout();
+ //
+ // FormImageDisplay
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(508, 290);
+ this.Name = "FormImageDisplay";
+ this.Text = "FormImageDisplay";
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Check.Main/UI/FormImageDisplay.cs b/Check.Main/UI/FormImageDisplay.cs
new file mode 100644
index 0000000..a1bdc8a
--- /dev/null
+++ b/Check.Main/UI/FormImageDisplay.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using WeifenLuo.WinFormsUI.Docking;
+
+namespace Check.Main.UI
+{
+ public partial class FormImageDisplay : DockContent
+ {
+ ///
+ /// 相机名称
+ ///
+ public string CameraName { get; set; }
+
+ ///
+ /// 当此显示窗口发生特定事件时(如ROI裁剪),触发此事件以通知外部(如日志系统)
+ ///
+ public event Action OnDisplayEvent;
+
+ // 使用我们全新的自定义控件
+ private ZoomPictureBox zoomPictureBox;
+ public FormImageDisplay()
+ {
+ InitializeComponent();
+
+ // 实例化新的控件
+ zoomPictureBox = new ZoomPictureBox
+ {
+ Dock = DockStyle.Fill,
+ // 其他属性可以在这里设置,例如
+ // RectangleColor = Color.LawnGreen,
+ // BackgroundFillColor = Color.FromArgb(45, 45, 48)
+ };
+ this.Controls.Add(zoomPictureBox);
+
+ // 订阅自定义控件的ROI裁剪完成事件
+ zoomPictureBox.CroppingEnabled = false;
+ //zoomPictureBox.Cropped += ZoomPictureBox_Cropped;
+ }
+ ///
+ /// 更新显示的图像(线程安全)。
+ /// 此方法现在将图像设置到 ZoomPictureBox1 控件中。
+ ///
+ /// 从相机事件传来的原始Bitmap
+ public void UpdateImage(Bitmap image)
+ {
+ if (zoomPictureBox != null && !zoomPictureBox.IsDisposed)
+ {
+ zoomPictureBox.SetImageThreadSafe(image);
+ }
+ else
+ {
+ // 如果PictureBox已经被释放,那么我们也应该释放这个多余的图像
+ image?.Dispose();
+ }
+ }
+ // 重写 Close 方法,确保在窗口关闭时,内部的控件和资源也能被妥善处理
+ public new void Close()
+ {
+ // 取消事件订阅,防止内存泄漏
+ if (zoomPictureBox != null)
+ {
+ //zoomPictureBox.Cropped -= ZoomPictureBox_Cropped;
+ }
+ base.Close();
+ }
+ }
+}
diff --git a/Check.Main/UI/FormImageDisplay.resx b/Check.Main/UI/FormImageDisplay.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/Check.Main/UI/FormImageDisplay.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Check.Main/UI/FormStatistics.Designer.cs b/Check.Main/UI/FormStatistics.Designer.cs
new file mode 100644
index 0000000..3d2679a
--- /dev/null
+++ b/Check.Main/UI/FormStatistics.Designer.cs
@@ -0,0 +1,245 @@
+namespace Check.Main.UI
+{
+ partial class FormStatistics
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormStatistics));
+ this.uiTableLayoutPanel1 = new Sunny.UI.UITableLayoutPanel();
+ this.toolStrip1 = new System.Windows.Forms.ToolStrip();
+ this.uiLabel1 = new Sunny.UI.UILabel();
+ this.uiLabel2 = new Sunny.UI.UILabel();
+ this.uiLabel3 = new Sunny.UI.UILabel();
+ this.uiLabel4 = new Sunny.UI.UILabel();
+ this.txtOKNum = new Sunny.UI.UITextBox();
+ this.txtNGNum = new Sunny.UI.UITextBox();
+ this.txtTotal = new Sunny.UI.UITextBox();
+ this.txtYieldRate = new Sunny.UI.UITextBox();
+ this.toolStripButtonRest = new System.Windows.Forms.ToolStripButton();
+ this.uiTableLayoutPanel1.SuspendLayout();
+ this.toolStrip1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // uiTableLayoutPanel1
+ //
+ this.uiTableLayoutPanel1.ColumnCount = 2;
+ this.uiTableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 45.88745F));
+ this.uiTableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 54.11255F));
+ this.uiTableLayoutPanel1.Controls.Add(this.txtYieldRate, 1, 3);
+ this.uiTableLayoutPanel1.Controls.Add(this.txtTotal, 1, 2);
+ this.uiTableLayoutPanel1.Controls.Add(this.txtNGNum, 1, 1);
+ this.uiTableLayoutPanel1.Controls.Add(this.toolStrip1, 0, 4);
+ this.uiTableLayoutPanel1.Controls.Add(this.uiLabel1, 0, 0);
+ this.uiTableLayoutPanel1.Controls.Add(this.uiLabel2, 0, 1);
+ this.uiTableLayoutPanel1.Controls.Add(this.uiLabel3, 0, 2);
+ this.uiTableLayoutPanel1.Controls.Add(this.uiLabel4, 0, 3);
+ this.uiTableLayoutPanel1.Controls.Add(this.txtOKNum, 1, 0);
+ this.uiTableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.uiTableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
+ this.uiTableLayoutPanel1.Name = "uiTableLayoutPanel1";
+ this.uiTableLayoutPanel1.RowCount = 5;
+ this.uiTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20F));
+ this.uiTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20F));
+ this.uiTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20F));
+ this.uiTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20F));
+ this.uiTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20F));
+ this.uiTableLayoutPanel1.Size = new System.Drawing.Size(231, 228);
+ this.uiTableLayoutPanel1.TabIndex = 0;
+ this.uiTableLayoutPanel1.TagString = null;
+ //
+ // toolStrip1
+ //
+ this.uiTableLayoutPanel1.SetColumnSpan(this.toolStrip1, 2);
+ this.toolStrip1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.toolStripButtonRest});
+ this.toolStrip1.Location = new System.Drawing.Point(0, 180);
+ this.toolStrip1.Name = "toolStrip1";
+ this.toolStrip1.Size = new System.Drawing.Size(231, 48);
+ this.toolStrip1.TabIndex = 0;
+ this.toolStrip1.Text = "toolStrip1";
+ //
+ // uiLabel1
+ //
+ this.uiLabel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.uiLabel1.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.uiLabel1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
+ this.uiLabel1.Location = new System.Drawing.Point(3, 0);
+ this.uiLabel1.Name = "uiLabel1";
+ this.uiLabel1.Size = new System.Drawing.Size(100, 45);
+ this.uiLabel1.TabIndex = 1;
+ this.uiLabel1.Text = "良品数";
+ this.uiLabel1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // uiLabel2
+ //
+ this.uiLabel2.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.uiLabel2.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.uiLabel2.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
+ this.uiLabel2.Location = new System.Drawing.Point(3, 45);
+ this.uiLabel2.Name = "uiLabel2";
+ this.uiLabel2.Size = new System.Drawing.Size(100, 45);
+ this.uiLabel2.TabIndex = 2;
+ this.uiLabel2.Text = "不良品数量";
+ this.uiLabel2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // uiLabel3
+ //
+ this.uiLabel3.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.uiLabel3.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.uiLabel3.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
+ this.uiLabel3.Location = new System.Drawing.Point(3, 90);
+ this.uiLabel3.Name = "uiLabel3";
+ this.uiLabel3.Size = new System.Drawing.Size(100, 45);
+ this.uiLabel3.TabIndex = 3;
+ this.uiLabel3.Text = "总数";
+ this.uiLabel3.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // uiLabel4
+ //
+ this.uiLabel4.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.uiLabel4.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.uiLabel4.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
+ this.uiLabel4.Location = new System.Drawing.Point(3, 135);
+ this.uiLabel4.Name = "uiLabel4";
+ this.uiLabel4.Size = new System.Drawing.Size(100, 45);
+ this.uiLabel4.TabIndex = 4;
+ this.uiLabel4.Text = "良品率";
+ this.uiLabel4.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // txtOKNum
+ //
+ this.txtOKNum.Cursor = System.Windows.Forms.Cursors.IBeam;
+ this.txtOKNum.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtOKNum.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.txtOKNum.Location = new System.Drawing.Point(110, 5);
+ this.txtOKNum.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.txtOKNum.MinimumSize = new System.Drawing.Size(1, 16);
+ this.txtOKNum.Name = "txtOKNum";
+ this.txtOKNum.Padding = new System.Windows.Forms.Padding(5);
+ this.txtOKNum.ShowText = false;
+ this.txtOKNum.Size = new System.Drawing.Size(117, 35);
+ this.txtOKNum.TabIndex = 5;
+ this.txtOKNum.Text = "0";
+ this.txtOKNum.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter;
+ this.txtOKNum.Watermark = "";
+ //
+ // txtNGNum
+ //
+ this.txtNGNum.Cursor = System.Windows.Forms.Cursors.IBeam;
+ this.txtNGNum.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtNGNum.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.txtNGNum.Location = new System.Drawing.Point(110, 50);
+ this.txtNGNum.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.txtNGNum.MinimumSize = new System.Drawing.Size(1, 16);
+ this.txtNGNum.Name = "txtNGNum";
+ this.txtNGNum.Padding = new System.Windows.Forms.Padding(5);
+ this.txtNGNum.ShowText = false;
+ this.txtNGNum.Size = new System.Drawing.Size(117, 35);
+ this.txtNGNum.TabIndex = 6;
+ this.txtNGNum.Text = "0";
+ this.txtNGNum.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter;
+ this.txtNGNum.Watermark = "";
+ //
+ // txtTotal
+ //
+ this.txtTotal.Cursor = System.Windows.Forms.Cursors.IBeam;
+ this.txtTotal.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtTotal.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.txtTotal.Location = new System.Drawing.Point(110, 95);
+ this.txtTotal.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.txtTotal.MinimumSize = new System.Drawing.Size(1, 16);
+ this.txtTotal.Name = "txtTotal";
+ this.txtTotal.Padding = new System.Windows.Forms.Padding(5);
+ this.txtTotal.ShowText = false;
+ this.txtTotal.Size = new System.Drawing.Size(117, 35);
+ this.txtTotal.TabIndex = 7;
+ this.txtTotal.Text = "0";
+ this.txtTotal.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter;
+ this.txtTotal.Watermark = "";
+ //
+ // txtYieldRate
+ //
+ this.txtYieldRate.Cursor = System.Windows.Forms.Cursors.IBeam;
+ this.txtYieldRate.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtYieldRate.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.txtYieldRate.Location = new System.Drawing.Point(110, 140);
+ this.txtYieldRate.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.txtYieldRate.MinimumSize = new System.Drawing.Size(1, 16);
+ this.txtYieldRate.Name = "txtYieldRate";
+ this.txtYieldRate.Padding = new System.Windows.Forms.Padding(5);
+ this.txtYieldRate.ShowText = false;
+ this.txtYieldRate.Size = new System.Drawing.Size(117, 35);
+ this.txtYieldRate.TabIndex = 8;
+ this.txtYieldRate.Text = "0";
+ this.txtYieldRate.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter;
+ this.txtYieldRate.Watermark = "";
+ //
+ // toolStripButtonRest
+ //
+ this.toolStripButtonRest.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
+ this.toolStripButtonRest.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButtonRest.Image")));
+ this.toolStripButtonRest.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.toolStripButtonRest.Name = "toolStripButtonRest";
+ this.toolStripButtonRest.Size = new System.Drawing.Size(60, 45);
+ this.toolStripButtonRest.Text = "重置计数";
+ this.toolStripButtonRest.Click += new System.EventHandler(this.toolStripButtonRest_Click);
+ //
+ // FormStatistics
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(231, 228);
+ this.ControlBox = false;
+ this.Controls.Add(this.uiTableLayoutPanel1);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "FormStatistics";
+ this.Text = "统计";
+ this.uiTableLayoutPanel1.ResumeLayout(false);
+ this.uiTableLayoutPanel1.PerformLayout();
+ this.toolStrip1.ResumeLayout(false);
+ this.toolStrip1.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private Sunny.UI.UITableLayoutPanel uiTableLayoutPanel1;
+ private System.Windows.Forms.ToolStrip toolStrip1;
+ private Sunny.UI.UITextBox txtYieldRate;
+ private Sunny.UI.UITextBox txtTotal;
+ private Sunny.UI.UITextBox txtNGNum;
+ private System.Windows.Forms.ToolStripButton toolStripButtonRest;
+ private Sunny.UI.UILabel uiLabel1;
+ private Sunny.UI.UILabel uiLabel2;
+ private Sunny.UI.UILabel uiLabel3;
+ private Sunny.UI.UILabel uiLabel4;
+ private Sunny.UI.UITextBox txtOKNum;
+ }
+}
\ No newline at end of file
diff --git a/Check.Main/UI/FormStatistics.cs b/Check.Main/UI/FormStatistics.cs
new file mode 100644
index 0000000..bb927a2
--- /dev/null
+++ b/Check.Main/UI/FormStatistics.cs
@@ -0,0 +1,89 @@
+using Check.Main.Camera;
+using Check.Main.Common;
+using Check.Main.Infer;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using WeifenLuo.WinFormsUI.Docking;
+
+namespace Check.Main.UI
+{
+ public partial class FormStatistics : DockContent
+ {
+ private readonly StatisticsData _statisticsData;
+
+ ///
+ /// 将私有字段通过公共属性暴露,以便外部(如FormMain)访问。
+ ///
+ public StatisticsData CurrentStatistics => _statisticsData;
+ public FormStatistics()
+ {
+ InitializeComponent();
+ _statisticsData = new StatisticsData();
+
+ // 订阅CameraManager的检测完成事件
+ DetectionCoordinator.OnDetectionCompleted += CameraManager_OnDetectionCompleted;
+ // 初始化UI显示
+ UpdateUI();
+ }
+ // 当CameraManager发布检测结果时,此方法被调用
+ private void CameraManager_OnDetectionCompleted(object sender, DetectionResultEventArgs e)
+ {
+ // 更新统计数据
+ _statisticsData.UpdateWithResult(e.IsOK);
+
+ // 在UI线程上更新界面显示
+ UpdateUI();
+ }
+ // 更新所有标签的文本
+ private void UpdateUI()
+ {
+ // 使用Invoke确保线程安全
+ if (this.InvokeRequired)
+ {
+ this.Invoke(new Action(UpdateUI));
+ return;
+ }
+
+ txtOKNum.Text = _statisticsData.GoodCount.ToString();
+ txtNGNum.Text = _statisticsData.NgCount.ToString();
+ txtTotal.Text = _statisticsData.TotalCount.ToString();
+ // 将良率格式化为百分比
+ txtYieldRate.Text = _statisticsData.YieldRate.ToString("P2", CultureInfo.InvariantCulture);
+
+ // 根据良率改变颜色以示提醒
+ if (_statisticsData.YieldRate < 0.9 && _statisticsData.TotalCount > 10)
+ {
+ txtYieldRate.ForeColor = Color.Red;
+ }
+ else
+ {
+ txtYieldRate.ForeColor = Color.ForestGreen;
+ }
+ }
+
+ private void toolStripButtonRest_Click(object sender, EventArgs e)
+ {
+ StatisticsExporter.ExportToExcel(CurrentStatistics, "Reset");
+
+ _statisticsData.Reset();
+ // 同时重置产品ID计数器
+ DetectionCoordinator.ResetAllCounters();
+ UpdateUI();
+ ThreadSafeLogger.Log("统计数据已重置。");
+ }
+ // 窗体关闭时,取消事件订阅,防止内存泄漏
+ protected override void OnFormClosing(FormClosingEventArgs e)
+ {
+ DetectionCoordinator.OnDetectionCompleted -= CameraManager_OnDetectionCompleted;
+ base.OnFormClosing(e);
+ }
+ }
+}
diff --git a/Check.Main/UI/FormStatistics.resx b/Check.Main/UI/FormStatistics.resx
new file mode 100644
index 0000000..013a61e
--- /dev/null
+++ b/Check.Main/UI/FormStatistics.resx
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
+ YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
+ 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
+ bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
+ VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
+ c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
+ Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
+ mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
+ kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
+ TgDQASA1MVpwzwAAAABJRU5ErkJggg==
+
+
+
\ No newline at end of file
diff --git a/Check.Main/UI/FrmCamConfig.Designer.cs b/Check.Main/UI/FrmCamConfig.Designer.cs
new file mode 100644
index 0000000..4a75ee7
--- /dev/null
+++ b/Check.Main/UI/FrmCamConfig.Designer.cs
@@ -0,0 +1,175 @@
+namespace Check.Main.UI
+{
+ partial class FrmCamConfig
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmCamConfig));
+ tableLayoutPanel1 = new TableLayoutPanel();
+ toolStrip1 = new ToolStrip();
+ toolBtnAdd = new ToolStripButton();
+ toolBtnRemove = new ToolStripButton();
+ toolBtnSet = new ToolStripButton();
+ splitContainer1 = new SplitContainer();
+ listBoxCameras = new ListBox();
+ propertyGrid1 = new PropertyGrid();
+ tableLayoutPanel1.SuspendLayout();
+ toolStrip1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit();
+ splitContainer1.Panel1.SuspendLayout();
+ splitContainer1.Panel2.SuspendLayout();
+ splitContainer1.SuspendLayout();
+ SuspendLayout();
+ //
+ // tableLayoutPanel1
+ //
+ tableLayoutPanel1.ColumnCount = 1;
+ tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+ tableLayoutPanel1.Controls.Add(toolStrip1, 0, 0);
+ tableLayoutPanel1.Controls.Add(splitContainer1, 0, 1);
+ tableLayoutPanel1.Dock = DockStyle.Fill;
+ tableLayoutPanel1.Location = new Point(0, 0);
+ tableLayoutPanel1.Margin = new Padding(4, 4, 4, 4);
+ tableLayoutPanel1.Name = "tableLayoutPanel1";
+ tableLayoutPanel1.RowCount = 2;
+ tableLayoutPanel1.RowStyles.Add(new RowStyle());
+ tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+ tableLayoutPanel1.Size = new Size(632, 560);
+ tableLayoutPanel1.TabIndex = 0;
+ //
+ // toolStrip1
+ //
+ toolStrip1.Items.AddRange(new ToolStripItem[] { toolBtnAdd, toolBtnRemove, toolBtnSet });
+ toolStrip1.Location = new Point(0, 0);
+ toolStrip1.Name = "toolStrip1";
+ toolStrip1.Size = new Size(632, 25);
+ toolStrip1.TabIndex = 0;
+ toolStrip1.Text = "toolStrip1";
+ //
+ // toolBtnAdd
+ //
+ toolBtnAdd.DisplayStyle = ToolStripItemDisplayStyle.Text;
+ toolBtnAdd.Image = (Image)resources.GetObject("toolBtnAdd.Image");
+ toolBtnAdd.ImageTransparentColor = Color.Magenta;
+ toolBtnAdd.Name = "toolBtnAdd";
+ toolBtnAdd.Size = new Size(36, 22);
+ toolBtnAdd.Text = "添加";
+ toolBtnAdd.Click += toolBtnAdd_Click;
+ //
+ // toolBtnRemove
+ //
+ toolBtnRemove.DisplayStyle = ToolStripItemDisplayStyle.Text;
+ toolBtnRemove.Image = (Image)resources.GetObject("toolBtnRemove.Image");
+ toolBtnRemove.ImageTransparentColor = Color.Magenta;
+ toolBtnRemove.Name = "toolBtnRemove";
+ toolBtnRemove.Size = new Size(36, 22);
+ toolBtnRemove.Text = "移除";
+ toolBtnRemove.Click += toolBtnRemove_Click;
+ //
+ // toolBtnSet
+ //
+ toolBtnSet.DisplayStyle = ToolStripItemDisplayStyle.Text;
+ toolBtnSet.Image = (Image)resources.GetObject("toolBtnSet.Image");
+ toolBtnSet.ImageTransparentColor = Color.Magenta;
+ toolBtnSet.Name = "toolBtnSet";
+ toolBtnSet.Size = new Size(60, 22);
+ toolBtnSet.Text = "应用配置";
+ toolBtnSet.Click += toolBtnSet_Click;
+ //
+ // splitContainer1
+ //
+ splitContainer1.Dock = DockStyle.Fill;
+ splitContainer1.Location = new Point(4, 29);
+ splitContainer1.Margin = new Padding(4, 4, 4, 4);
+ splitContainer1.Name = "splitContainer1";
+ //
+ // splitContainer1.Panel1
+ //
+ splitContainer1.Panel1.Controls.Add(listBoxCameras);
+ //
+ // splitContainer1.Panel2
+ //
+ splitContainer1.Panel2.Controls.Add(propertyGrid1);
+ splitContainer1.Size = new Size(624, 527);
+ splitContainer1.SplitterDistance = 210;
+ splitContainer1.SplitterWidth = 5;
+ splitContainer1.TabIndex = 1;
+ //
+ // listBoxCameras
+ //
+ listBoxCameras.Dock = DockStyle.Fill;
+ listBoxCameras.FormattingEnabled = true;
+ listBoxCameras.ItemHeight = 17;
+ listBoxCameras.Location = new Point(0, 0);
+ listBoxCameras.Margin = new Padding(4, 4, 4, 4);
+ listBoxCameras.Name = "listBoxCameras";
+ listBoxCameras.Size = new Size(210, 527);
+ listBoxCameras.TabIndex = 0;
+ listBoxCameras.SelectedIndexChanged += listBoxCameras_SelectedIndexChanged;
+ //
+ // propertyGrid1
+ //
+ propertyGrid1.Dock = DockStyle.Fill;
+ propertyGrid1.Location = new Point(0, 0);
+ propertyGrid1.Margin = new Padding(4, 4, 4, 4);
+ propertyGrid1.Name = "propertyGrid1";
+ propertyGrid1.Size = new Size(409, 527);
+ propertyGrid1.TabIndex = 0;
+ //
+ // FrmCamConfig
+ //
+ AutoScaleDimensions = new SizeF(7F, 17F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(632, 560);
+ Controls.Add(tableLayoutPanel1);
+ Margin = new Padding(4, 4, 4, 4);
+ Name = "FrmCamConfig";
+ Text = "属性配置";
+ tableLayoutPanel1.ResumeLayout(false);
+ tableLayoutPanel1.PerformLayout();
+ toolStrip1.ResumeLayout(false);
+ toolStrip1.PerformLayout();
+ splitContainer1.Panel1.ResumeLayout(false);
+ splitContainer1.Panel2.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)splitContainer1).EndInit();
+ splitContainer1.ResumeLayout(false);
+ ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
+ private System.Windows.Forms.ToolStrip toolStrip1;
+ private System.Windows.Forms.SplitContainer splitContainer1;
+ private System.Windows.Forms.ListBox listBoxCameras;
+ private System.Windows.Forms.PropertyGrid propertyGrid1;
+ private System.Windows.Forms.ToolStripButton toolBtnAdd;
+ private System.Windows.Forms.ToolStripButton toolBtnRemove;
+ private System.Windows.Forms.ToolStripButton toolBtnSet;
+ }
+}
\ No newline at end of file
diff --git a/Check.Main/UI/FrmCamConfig.cs b/Check.Main/UI/FrmCamConfig.cs
new file mode 100644
index 0000000..becaf95
--- /dev/null
+++ b/Check.Main/UI/FrmCamConfig.cs
@@ -0,0 +1,193 @@
+using Check.Main.Camera;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Xml.Serialization;
+using WeifenLuo.WinFormsUI.Docking;
+
+namespace Check.Main.UI
+{
+ public partial class FrmCamConfig : DockContent
+ {
+ // public List _settingsList = new List();
+ public List _settingsList { get; private set; }
+ private readonly string _configFilePath = Path.Combine(Application.StartupPath, "cameras.xml");
+ public FrmCamConfig()
+ {
+ InitializeComponent();
+ _settingsList = new List();
+ LoadSettings();
+ RefreshListBox();
+ AdaptForDialogMode(); // 调整UI为对话框模式
+ }
+
+ ///
+ /// 用于从外部接收一个设置列表进行编辑。
+ ///
+ /// 要编辑的相机设置列表
+ public FrmCamConfig(List settingsToEdit)
+ {
+ InitializeComponent();
+
+ // 创建一个现有列表的副本进行编辑,这样如果用户点“取消”,原始列表不会被影响
+ _settingsList = settingsToEdit != null
+ ? settingsToEdit.Select(s => s.Clone() as CameraSettings).ToList() // 深度克隆更好,这里为简化用浅克隆
+ : new List();
+
+ // 别忘了为列表中的每个对象重新订阅事件
+ foreach (var setting in _settingsList)
+ {
+ setting.PropertyChanged += Setting_PropertyChanged;
+ }
+
+ RefreshListBox();
+ AdaptForDialogMode(); // 调整UI为对话框模式
+ }
+
+ ///
+ /// 【新增的方法】
+ /// 调整UI,使其更像一个对话框。
+ ///
+ private void AdaptForDialogMode()
+ {
+ // 将“应用配置”按钮改为“确定”
+ toolBtnSet.Text = "确定";
+ toolBtnSet.ToolTipText = "保存更改并关闭窗口";
+
+ // 新增一个“取消”按钮
+ var toolBtnCancel = new ToolStripButton("取消")
+ {
+ DisplayStyle = ToolStripItemDisplayStyle.Text,
+ Alignment = ToolStripItemAlignment.Right // 靠右对齐
+ };
+ toolBtnCancel.Click += (sender, e) => {
+ this.DialogResult = DialogResult.Cancel;
+ this.Close();
+ };
+ toolStrip1.Items.Add(toolBtnCancel);
+ }
+
+ ///
+ /// 【新增的事件处理方法】
+ /// 当PropertyGrid中的属性值被用户修改后触发此事件。
+ ///
+
+ // 刷新左侧的相机列表
+ private void RefreshListBox()
+ {
+ listBoxCameras.Items.Clear();
+ foreach (var setting in _settingsList)
+ {
+ listBoxCameras.Items.Add(setting.Name);
+ }
+ }
+ ///
+ /// 【全新的事件处理方法】
+ /// 监听单个CameraSettings对象的属性变更通知。
+ ///
+ private void Setting_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ // 检查是不是“Name”属性发生了变化
+ if (e.PropertyName == nameof(CameraSettings.Name))
+ {
+ // 'sender' 就是那个属性发生了变化的 CameraSettings 对象
+ var changedSetting = sender as CameraSettings;
+ if (changedSetting == null) return;
+
+ // 在 _settingsList 中找到这个对象的索引
+ int index = _settingsList.IndexOf(changedSetting);
+
+ // 如果找到了,就更新ListBox中对应项的显示文本
+ if (index >= 0)
+ {
+ // 使用Invoke确保线程安全,虽然在此场景下通常不是问题,但这是个好习惯
+ this.Invoke(new Action(() => {
+ listBoxCameras.Items[index] = changedSetting.Name;
+ }));
+ }
+ }
+ }
+
+ private void listBoxCameras_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (listBoxCameras.SelectedIndex >= 0)
+ {
+ propertyGrid1.SelectedObject = _settingsList[listBoxCameras.SelectedIndex];
+ }
+ else
+ {
+ propertyGrid1.SelectedObject = null;
+ }
+ }
+
+ private void toolBtnAdd_Click(object sender, EventArgs e)
+ {
+ var newSetting = new CameraSettings { Name = $"Camera-{_settingsList.Count + 1}" };
+ _settingsList.Add(newSetting);
+ newSetting.PropertyChanged += Setting_PropertyChanged;
+ RefreshListBox();
+ listBoxCameras.SelectedIndex = listBoxCameras.Items.Count - 1;
+ }
+
+ private void toolBtnRemove_Click(object sender, EventArgs e)
+ {
+ if (listBoxCameras.SelectedIndex >= 0)
+ {
+ _settingsList.RemoveAt(listBoxCameras.SelectedIndex);
+ propertyGrid1.SelectedObject = null;
+ RefreshListBox();
+ }
+ }
+
+ private void toolBtnSet_Click(object sender, EventArgs e)
+ {
+ this.DialogResult = DialogResult.OK;
+ this.Close();
+ }
+ // 加载XML配置文件
+ private void LoadSettings()
+ {
+ if (!File.Exists(_configFilePath)) return;
+ try
+ {
+ XmlSerializer serializer = new XmlSerializer(typeof(List));
+ using (FileStream fs = new FileStream(_configFilePath, FileMode.Open))
+ {
+ _settingsList = (List)serializer.Deserialize(fs);
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("加载相机配置失败: " + ex.Message);
+ }
+ foreach (var setting in _settingsList)
+ {
+ setting.PropertyChanged += Setting_PropertyChanged;
+ }
+ }
+
+ // 保存配置到XML文件
+ private void SaveSettings()
+ {
+ try
+ {
+ XmlSerializer serializer = new XmlSerializer(typeof(List));
+ using (FileStream fs = new FileStream(_configFilePath, FileMode.Create))
+ {
+ serializer.Serialize(fs, _settingsList);
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("保存相机配置失败: " + ex.Message);
+ }
+ }
+ }
+}
diff --git a/Check.Main/UI/FrmCamConfig.resx b/Check.Main/UI/FrmCamConfig.resx
new file mode 100644
index 0000000..8782d2a
--- /dev/null
+++ b/Check.Main/UI/FrmCamConfig.resx
@@ -0,0 +1,169 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
+ YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
+ 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
+ bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
+ VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
+ c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
+ Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
+ mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
+ kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
+ TgDQASA1MVpwzwAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
+ YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
+ 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
+ bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
+ VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
+ c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
+ Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
+ mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
+ kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
+ TgDQASA1MVpwzwAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
+ YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
+ 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
+ bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
+ VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
+ c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
+ Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
+ mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
+ kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
+ TgDQASA1MVpwzwAAAABJRU5ErkJggg==
+
+
+
\ No newline at end of file
diff --git a/Check.Main/UI/FrmConfig.Designer.cs b/Check.Main/UI/FrmConfig.Designer.cs
new file mode 100644
index 0000000..9b13c1f
--- /dev/null
+++ b/Check.Main/UI/FrmConfig.Designer.cs
@@ -0,0 +1,171 @@
+namespace Check.Main.UI
+{
+ partial class FrmConfig
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmConfig));
+ propertyGrid1 = new PropertyGrid();
+ toolStrip1 = new ToolStrip();
+ toolBtnApply = new ToolStripButton();
+ toolBtnAddProduct = new ToolStripButton();
+ tableLayoutPanel1 = new TableLayoutPanel();
+ uiLabel1 = new Sunny.UI.UILabel();
+ cmbProducts = new Sunny.UI.UIComboBox();
+ toolBtnDeleteProduct = new ToolStripButton();
+ toolStrip1.SuspendLayout();
+ tableLayoutPanel1.SuspendLayout();
+ SuspendLayout();
+ //
+ // propertyGrid1
+ //
+ tableLayoutPanel1.SetColumnSpan(propertyGrid1, 2);
+ propertyGrid1.Dock = DockStyle.Fill;
+ propertyGrid1.Location = new Point(3, 70);
+ propertyGrid1.Name = "propertyGrid1";
+ propertyGrid1.Size = new Size(417, 345);
+ propertyGrid1.TabIndex = 0;
+ //
+ // toolStrip1
+ //
+ tableLayoutPanel1.SetColumnSpan(toolStrip1, 2);
+ toolStrip1.Dock = DockStyle.Fill;
+ toolStrip1.Items.AddRange(new ToolStripItem[] { toolBtnApply, toolBtnAddProduct, toolBtnDeleteProduct });
+ toolStrip1.Location = new Point(0, 0);
+ toolStrip1.Name = "toolStrip1";
+ toolStrip1.Size = new Size(423, 28);
+ toolStrip1.TabIndex = 1;
+ toolStrip1.Text = "toolStrip1";
+ //
+ // toolBtnApply
+ //
+ toolBtnApply.DisplayStyle = ToolStripItemDisplayStyle.Text;
+ toolBtnApply.Image = (Image)resources.GetObject("toolBtnApply.Image");
+ toolBtnApply.ImageTransparentColor = Color.Magenta;
+ toolBtnApply.Name = "toolBtnApply";
+ toolBtnApply.Size = new Size(60, 25);
+ toolBtnApply.Text = "应用配置";
+ toolBtnApply.Click += toolBtnApply_Click;
+ //
+ // toolBtnAddProduct
+ //
+ toolBtnAddProduct.DisplayStyle = ToolStripItemDisplayStyle.Text;
+ toolBtnAddProduct.Image = (Image)resources.GetObject("toolBtnAddProduct.Image");
+ toolBtnAddProduct.ImageTransparentColor = Color.Magenta;
+ toolBtnAddProduct.Name = "toolBtnAddProduct";
+ toolBtnAddProduct.Size = new Size(60, 25);
+ toolBtnAddProduct.Text = "添加产品";
+ toolBtnAddProduct.Click += toolBtnAddProduct_Click;
+ //
+ // tableLayoutPanel1
+ //
+ tableLayoutPanel1.ColumnCount = 2;
+ tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 23.4042549F));
+ tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 76.59574F));
+ tableLayoutPanel1.Controls.Add(propertyGrid1, 0, 2);
+ tableLayoutPanel1.Controls.Add(toolStrip1, 0, 0);
+ tableLayoutPanel1.Controls.Add(uiLabel1, 0, 1);
+ tableLayoutPanel1.Controls.Add(cmbProducts, 1, 1);
+ tableLayoutPanel1.Dock = DockStyle.Fill;
+ tableLayoutPanel1.Location = new Point(0, 0);
+ tableLayoutPanel1.Name = "tableLayoutPanel1";
+ tableLayoutPanel1.RowCount = 3;
+ tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 6.69856453F));
+ tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 9.330144F));
+ tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 83.97129F));
+ tableLayoutPanel1.Size = new Size(423, 418);
+ tableLayoutPanel1.TabIndex = 2;
+ //
+ // uiLabel1
+ //
+ uiLabel1.Dock = DockStyle.Fill;
+ uiLabel1.Font = new Font("宋体", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+ uiLabel1.ForeColor = Color.FromArgb(48, 48, 48);
+ uiLabel1.Location = new Point(3, 28);
+ uiLabel1.Name = "uiLabel1";
+ uiLabel1.Size = new Size(93, 39);
+ uiLabel1.TabIndex = 2;
+ uiLabel1.Text = "当前产品";
+ uiLabel1.TextAlign = ContentAlignment.MiddleCenter;
+ //
+ // cmbProducts
+ //
+ cmbProducts.DataSource = null;
+ cmbProducts.Dock = DockStyle.Left;
+ cmbProducts.FillColor = Color.White;
+ cmbProducts.Font = new Font("宋体", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+ cmbProducts.ItemHoverColor = Color.FromArgb(155, 200, 255);
+ cmbProducts.ItemSelectForeColor = Color.FromArgb(235, 243, 255);
+ cmbProducts.Location = new Point(103, 33);
+ cmbProducts.Margin = new Padding(4, 5, 4, 5);
+ cmbProducts.MinimumSize = new Size(63, 0);
+ cmbProducts.Name = "cmbProducts";
+ cmbProducts.Padding = new Padding(0, 0, 30, 2);
+ cmbProducts.Size = new Size(225, 29);
+ cmbProducts.SymbolSize = 24;
+ cmbProducts.TabIndex = 3;
+ cmbProducts.TextAlignment = ContentAlignment.MiddleLeft;
+ cmbProducts.Watermark = "";
+ cmbProducts.SelectedIndexChanged += cmbProducts_SelectedIndexChanged;
+ //
+ // toolBtnDeleteProduct
+ //
+ toolBtnDeleteProduct.DisplayStyle = ToolStripItemDisplayStyle.Text;
+ toolBtnDeleteProduct.Image = (Image)resources.GetObject("toolBtnDeleteProduct.Image");
+ toolBtnDeleteProduct.ImageTransparentColor = Color.Magenta;
+ toolBtnDeleteProduct.Name = "toolBtnDeleteProduct";
+ toolBtnDeleteProduct.Size = new Size(60, 25);
+ toolBtnDeleteProduct.Text = "删除产品";
+ toolBtnDeleteProduct.Click += toolBtnDeleteProduct_Click;
+ //
+ // FrmConfig
+ //
+ AutoScaleDimensions = new SizeF(7F, 17F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(423, 418);
+ Controls.Add(tableLayoutPanel1);
+ Name = "FrmConfig";
+ Text = "属性配置";
+ toolStrip1.ResumeLayout(false);
+ toolStrip1.PerformLayout();
+ tableLayoutPanel1.ResumeLayout(false);
+ tableLayoutPanel1.PerformLayout();
+ ResumeLayout(false);
+ }
+
+ #endregion
+
+ private PropertyGrid propertyGrid1;
+ private ToolStrip toolStrip1;
+ private ToolStripButton toolBtnApply;
+ private TableLayoutPanel tableLayoutPanel1;
+ private ToolStripButton toolBtnAddProduct;
+ private Sunny.UI.UILabel uiLabel1;
+ private Sunny.UI.UIComboBox cmbProducts;
+ private ToolStripButton toolBtnDeleteProduct;
+ }
+}
\ No newline at end of file
diff --git a/Check.Main/UI/FrmConfig.cs b/Check.Main/UI/FrmConfig.cs
new file mode 100644
index 0000000..f68d61a
--- /dev/null
+++ b/Check.Main/UI/FrmConfig.cs
@@ -0,0 +1,163 @@
+using Check.Main.Camera;
+using Check.Main.Common;
+using Check.Main.Dispatch;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Xml.Serialization;
+using WeifenLuo.WinFormsUI.Docking;
+
+namespace Check.Main.UI
+{
+ public partial class FrmConfig : DockContent
+ {
+ //private ProcessConfig _mainSettings=new ProcessConfig();
+ //private readonly string _configFilePath = Path.Combine(Application.StartupPath, "main_config.xml");
+ public FrmConfig()
+ {
+ InitializeComponent();
+ ProductManager.OnProductChanged += UpdateUIForNewProduct;
+ // 初始化UI
+ InitializeProductComboBox();
+ //LoadSettings(); // 窗体加载时,读取主配置文件
+ propertyGrid1.SelectedObject = ProductManager.CurrentConfig; //_mainSettings; // 将配置对象绑定到属性网格
+ propertyGrid1.PropertyValueChanged += (s, e) => { ProductManager.SaveCurrentProductConfig(); }; // 任何属性改变后自动保存
+ }
+ // 【新增】初始化产品下拉列表
+ private void InitializeProductComboBox()
+ {
+ cmbProducts.DataSource = null; // 先清空数据源
+ cmbProducts.DataSource = ProductManager.ProductList;
+ cmbProducts.SelectedItem = ProductManager.CurrentProductName;
+ }
+ // 【新增】当产品管理器中的产品切换后,此方法被调用以更新整个UI
+ private void UpdateUIForNewProduct()
+ {
+ // 使用Invoke确保线程安全
+ if (this.InvokeRequired)
+ {
+ this.Invoke(new Action(UpdateUIForNewProduct));
+ return;
+ }
+
+ ThreadSafeLogger.Log($"UI正在更新以显示产品 '{ProductManager.CurrentProductName}' 的配置。");
+ // 更新下拉列表的显示(如果产品列表也变了)
+ InitializeProductComboBox();
+
+ // 【关键】将PropertyGrid重新绑定到新产品的配置对象上
+ propertyGrid1.SelectedObject = ProductManager.CurrentConfig;
+ propertyGrid1.Refresh(); // 强制刷新UI
+ }
+ private void toolBtnApply_Click(object sender, EventArgs e)
+ {
+ ThreadSafeLogger.Log("用户点击“应用”按钮...");
+
+ // 1. 确保在应用前,任何可能未触发 PropertyValueChanged 的更改都被保存。
+ ConfigurationManager.SaveChanges();
+
+ // 2. 获取主窗体引用
+ var mainForm = this.DockPanel.FindForm() as FrmMain;
+ mainForm?.ClearStatusStrip(); // 清理UI状态
+
+ // 3. 从 ConfigurationManager 获取最新的相机配置列表
+ var cameraSettings = ConfigurationManager.GetCurrentConfig();//.CameraSettings;
+
+ if (cameraSettings != null)
+ {
+ // 使用全局配置来初始化或重新初始化相机。
+ // CameraManager.Initialize 内部会首先调用 Shutdown,所以这是个完整的重启流程。
+ CameraManager.Initialize(cameraSettings, mainForm);
+ }
+
+ ThreadSafeLogger.Log("中央配置已成功应用到相机系统。");
+ //MessageBox.Show("主配置已应用!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ }
+
+ private void cmbProducts_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (cmbProducts.SelectedItem is string selectedProduct && selectedProduct != ProductManager.CurrentProductName)
+ {
+ ProductManager.SwitchToProduct(selectedProduct);
+ }
+ }
+
+ private void toolBtnAddProduct_Click(object sender, EventArgs e)
+ {
+ // 使用一个简单的输入框来获取新产品名称
+ string newName = ShowInputDialog("请输入新产品名称:");
+ if (!string.IsNullOrWhiteSpace(newName))
+ {
+ if (ProductManager.AddNewProduct(newName))
+ {
+ ThreadSafeLogger.Log($"成功添加新产品: {newName}");
+ }
+ else
+ {
+ MessageBox.Show("产品名称无效或已存在!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ }
+ // 一个简单的输入对话框辅助方法
+ public static string ShowInputDialog(string text)
+ {
+ Form prompt = new Form()
+ {
+ Width = 300,
+ Height = 150,
+ FormBorderStyle = FormBorderStyle.FixedDialog,
+ Text = text,
+ StartPosition = FormStartPosition.CenterScreen
+ };
+ Label textLabel = new Label() { Left = 50, Top = 20, Text = "产品名称:" };
+ TextBox textBox = new TextBox() { Left = 50, Top = 50, Width = 200 };
+ Button confirmation = new Button() { Text = "确定", Left = 150, Width = 100, Top = 80, DialogResult = DialogResult.OK };
+ confirmation.Click += (sender, e) => { prompt.Close(); };
+ prompt.Controls.Add(textBox);
+ prompt.Controls.Add(confirmation);
+ prompt.Controls.Add(textLabel);
+ prompt.AcceptButton = confirmation;
+
+ return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : "";
+ }
+
+ private void toolBtnDeleteProduct_Click(object sender, EventArgs e)
+ {
+ // 1. 获取当前选中的产品
+ string productToDelete = ProductManager.CurrentProductName;
+
+ if (string.IsNullOrWhiteSpace(productToDelete) || productToDelete == "DefaultProduct")
+ {
+ MessageBox.Show("不能删除默认产品或无效产品!", "操作无效", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ return;
+ }
+
+ // 2. 弹出安全确认对话框
+ var confirmResult = MessageBox.Show($"您确定要永久删除产品 '{productToDelete}' 吗?\n\n此操作不可恢复,将删除其所有相关配置!",
+ "确认删除",
+ MessageBoxButtons.YesNo,
+ MessageBoxIcon.Warning);
+
+ if (confirmResult == DialogResult.Yes)
+ {
+ // 3. 调用核心删除逻辑
+ if (ProductManager.DeleteProduct(productToDelete))
+ {
+ ThreadSafeLogger.Log($"用户成功删除了产品 '{productToDelete}'。");
+ // 无需在这里手动更新UI,因为DeleteProduct方法内部会触发 OnProductChanged 事件,
+ // 而我们的 UpdateUIForNewProduct 方法会自动响应这个事件并刷新整个界面。
+ }
+ else
+ {
+ MessageBox.Show($"删除产品 '{productToDelete}' 失败,请查看日志获取详细信息。", "删除失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+ }
+}
diff --git a/Check.Main/UI/FrmConfig.resx b/Check.Main/UI/FrmConfig.resx
new file mode 100644
index 0000000..b813d1d
--- /dev/null
+++ b/Check.Main/UI/FrmConfig.resx
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACRSURBVDhPY/j27dt/SjDYACcnJ7IwigEf3n8kCZNswPNb
+ J/+f6DYF0yA+yQac6Db5f6hWCmwIiE+mC0wIu2DS2Vf/F1x6DefjwlgNyNr34r/0wkdgTMgQDAOQNRNj
+ CIoBOg0rMTTDMLIhIHbriZeYBmDTiIxBGkEYxge5liQDsGGQqykyAISpZwAlmIEywMAAAAc1/Jwvt6sN
+ AAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACRSURBVDhPY/j27dt/SjDYACcnJ7IwigEf3n8kCZNswPNb
+ J/+f6DYF0yA+yQac6Db5f6hWCmwIiE+mC0wIu2DS2Vf/F1x6DefjwlgNyNr34r/0wkdgTMgQDAOQNRNj
+ CIoBOg0rMTTDMLIhIHbriZeYBmDTiIxBGkEYxge5liQDsGGQqykyAISpZwAlmIEywMAAAAc1/Jwvt6sN
+ AAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACRSURBVDhPY/j27dt/SjDYACcnJ7IwigEf3n8kCZNswPNb
+ J/+f6DYF0yA+yQac6Db5f6hWCmwIiE+mC0wIu2DS2Vf/F1x6DefjwlgNyNr34r/0wkdgTMgQDAOQNRNj
+ CIoBOg0rMTTDMLIhIHbriZeYBmDTiIxBGkEYxge5liQDsGGQqykyAISpZwAlmIEywMAAAAc1/Jwvt6sN
+ AAAAAElFTkSuQmCC
+
+
+
\ No newline at end of file
diff --git a/Check.Main/UI/FrmLog.Designer.cs b/Check.Main/UI/FrmLog.Designer.cs
new file mode 100644
index 0000000..734d162
--- /dev/null
+++ b/Check.Main/UI/FrmLog.Designer.cs
@@ -0,0 +1,66 @@
+namespace Check.Main.UI
+{
+ partial class FrmLog
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.txtLog = new Sunny.UI.UIRichTextBox();
+ this.SuspendLayout();
+ //
+ // txtLog
+ //
+ this.txtLog.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtLog.FillColor = System.Drawing.Color.White;
+ this.txtLog.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.txtLog.Location = new System.Drawing.Point(0, 0);
+ this.txtLog.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.txtLog.MinimumSize = new System.Drawing.Size(1, 1);
+ this.txtLog.Name = "txtLog";
+ this.txtLog.Padding = new System.Windows.Forms.Padding(2);
+ this.txtLog.ReadOnly = true;
+ this.txtLog.ShowText = false;
+ this.txtLog.Size = new System.Drawing.Size(399, 299);
+ this.txtLog.TabIndex = 0;
+ this.txtLog.TextAlignment = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // FrmLog
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(399, 299);
+ this.Controls.Add(this.txtLog);
+ this.Name = "FrmLog";
+ this.Text = "FrmLog";
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private Sunny.UI.UIRichTextBox txtLog;
+ }
+}
\ No newline at end of file
diff --git a/Check.Main/UI/FrmLog.cs b/Check.Main/UI/FrmLog.cs
new file mode 100644
index 0000000..a4c0bd3
--- /dev/null
+++ b/Check.Main/UI/FrmLog.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using WeifenLuo.WinFormsUI.Docking;
+
+namespace Check.Main.UI
+{
+ public partial class FrmLog : DockContent
+ {
+ public FrmLog()
+ {
+ InitializeComponent();
+ }
+ public void AddLog(string message)
+ {
+ if (txtLog.InvokeRequired)
+ {
+ txtLog.BeginInvoke(new Action(() => AddLog(message)));
+ return;
+ }
+ if (txtLog.Lines.Length > 500)
+ {
+ txtLog.Clear();
+ }
+ txtLog.AppendText(message + Environment.NewLine);
+ txtLog.ScrollToCaret();
+ }
+ }
+}
diff --git a/Check.Main/UI/FrmLog.resx b/Check.Main/UI/FrmLog.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/Check.Main/UI/FrmLog.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Check.Main/UI/ModelListEditor.Designer.cs b/Check.Main/UI/ModelListEditor.Designer.cs
new file mode 100644
index 0000000..c89c245
--- /dev/null
+++ b/Check.Main/UI/ModelListEditor.Designer.cs
@@ -0,0 +1,145 @@
+namespace Check.Main.UI
+{
+ partial class ModelListEditor
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ModelListEditor));
+ propertyGrid1 = new PropertyGrid();
+ listBoxModels = new ListBox();
+ toolStrip1 = new ToolStrip();
+ toolBtnAdd = new ToolStripButton();
+ toolBtnRemove = new ToolStripButton();
+ toolBtnSet = new ToolStripButton();
+ tableLayoutPanel1 = new TableLayoutPanel();
+ toolStrip1.SuspendLayout();
+ tableLayoutPanel1.SuspendLayout();
+ SuspendLayout();
+ //
+ // propertyGrid1
+ //
+ propertyGrid1.Dock = DockStyle.Fill;
+ propertyGrid1.Location = new Point(245, 4);
+ propertyGrid1.Margin = new Padding(4);
+ propertyGrid1.Name = "propertyGrid1";
+ propertyGrid1.Size = new Size(316, 400);
+ propertyGrid1.TabIndex = 1;
+ //
+ // listBoxModels
+ //
+ listBoxModels.Dock = DockStyle.Fill;
+ listBoxModels.FormattingEnabled = true;
+ listBoxModels.ItemHeight = 17;
+ listBoxModels.Location = new Point(4, 4);
+ listBoxModels.Margin = new Padding(4);
+ listBoxModels.Name = "listBoxModels";
+ listBoxModels.Size = new Size(233, 400);
+ listBoxModels.TabIndex = 2;
+ listBoxModels.SelectedIndexChanged += listBoxModels_SelectedIndexChanged;
+ //
+ // toolStrip1
+ //
+ toolStrip1.Items.AddRange(new ToolStripItem[] { toolBtnAdd, toolBtnRemove, toolBtnSet });
+ toolStrip1.Location = new Point(0, 0);
+ toolStrip1.Name = "toolStrip1";
+ toolStrip1.Size = new Size(565, 25);
+ toolStrip1.TabIndex = 3;
+ toolStrip1.Text = "toolStrip1";
+ //
+ // toolBtnAdd
+ //
+ toolBtnAdd.DisplayStyle = ToolStripItemDisplayStyle.Text;
+ toolBtnAdd.Image = (Image)resources.GetObject("toolBtnAdd.Image");
+ toolBtnAdd.ImageTransparentColor = Color.Magenta;
+ toolBtnAdd.Name = "toolBtnAdd";
+ toolBtnAdd.Size = new Size(36, 22);
+ toolBtnAdd.Text = "添加";
+ toolBtnAdd.Click += toolBtnAdd_Click;
+ //
+ // toolBtnRemove
+ //
+ toolBtnRemove.DisplayStyle = ToolStripItemDisplayStyle.Text;
+ toolBtnRemove.Image = (Image)resources.GetObject("toolBtnRemove.Image");
+ toolBtnRemove.ImageTransparentColor = Color.Magenta;
+ toolBtnRemove.Name = "toolBtnRemove";
+ toolBtnRemove.Size = new Size(36, 22);
+ toolBtnRemove.Text = "移除";
+ toolBtnRemove.Click += toolBtnRemove_Click;
+ //
+ // toolBtnSet
+ //
+ toolBtnSet.DisplayStyle = ToolStripItemDisplayStyle.Text;
+ toolBtnSet.Image = (Image)resources.GetObject("toolBtnSet.Image");
+ toolBtnSet.ImageTransparentColor = Color.Magenta;
+ toolBtnSet.Name = "toolBtnSet";
+ toolBtnSet.Size = new Size(60, 22);
+ toolBtnSet.Text = "应用配置";
+ toolBtnSet.Click += toolBtnSet_Click;
+ //
+ // tableLayoutPanel1
+ //
+ tableLayoutPanel1.ColumnCount = 2;
+ tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 42.65487F));
+ tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 57.34513F));
+ tableLayoutPanel1.Controls.Add(listBoxModels, 0, 0);
+ tableLayoutPanel1.Controls.Add(propertyGrid1, 1, 0);
+ tableLayoutPanel1.Dock = DockStyle.Fill;
+ tableLayoutPanel1.Location = new Point(0, 25);
+ tableLayoutPanel1.Name = "tableLayoutPanel1";
+ tableLayoutPanel1.RowCount = 1;
+ tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
+ tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
+ tableLayoutPanel1.Size = new Size(565, 408);
+ tableLayoutPanel1.TabIndex = 4;
+ //
+ // ModelListEditor
+ //
+ AutoScaleDimensions = new SizeF(7F, 17F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(565, 433);
+ Controls.Add(tableLayoutPanel1);
+ Controls.Add(toolStrip1);
+ Name = "ModelListEditor";
+ Text = "模型配置";
+ toolStrip1.ResumeLayout(false);
+ toolStrip1.PerformLayout();
+ tableLayoutPanel1.ResumeLayout(false);
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private PropertyGrid propertyGrid1;
+ private ListBox listBoxModels;
+ private ToolStrip toolStrip1;
+ private ToolStripButton toolBtnAdd;
+ private ToolStripButton toolBtnRemove;
+ private ToolStripButton toolBtnSet;
+ private TableLayoutPanel tableLayoutPanel1;
+ }
+}
\ No newline at end of file
diff --git a/Check.Main/UI/ModelListEditor.cs b/Check.Main/UI/ModelListEditor.cs
new file mode 100644
index 0000000..453fc04
--- /dev/null
+++ b/Check.Main/UI/ModelListEditor.cs
@@ -0,0 +1,175 @@
+using Check.Main.Camera;
+using Check.Main.Infer;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Xml.Serialization;
+using WeifenLuo.WinFormsUI.Docking;
+
+namespace Check.Main.UI
+{
+ public partial class ModelListEditor : DockContent
+ {
+ public List _settingsList { get; private set; }
+ private readonly string _configFilePath = Path.Combine(Application.StartupPath, "model.xml");
+ public ModelListEditor()
+ {
+ InitializeComponent();
+ _settingsList = new List();
+ LoadSettings();
+ RefreshListBox();
+ AdaptForDialogMode(); // 调整UI为对话框模式
+ }
+ ///
+ /// 用于从外部接收一个设置列表进行编辑。
+ ///
+ /// 要编辑的相机设置列表
+ public ModelListEditor(List settingsToEdit)
+ {
+ InitializeComponent();
+
+ // 创建一个现有列表的副本进行编辑,这样如果用户点“取消”,原始列表不会被影响
+ _settingsList = settingsToEdit != null
+ ? settingsToEdit.Select(s => s.Clone() as ModelSettings).ToList() // 深度克隆更好,这里为简化用浅克隆
+ : new List();
+
+ // 别忘了为列表中的每个对象重新订阅事件
+ foreach (var setting in _settingsList)
+ {
+ setting.PropertyChanged += Setting_PropertyChanged;
+ }
+
+ RefreshListBox();
+ AdaptForDialogMode(); // 调整UI为对话框模式
+ }
+ ///
+ /// 【新增的方法】
+ /// 调整UI,使其更像一个对话框。
+ ///
+ private void AdaptForDialogMode()
+ {
+ // 将“应用配置”按钮改为“确定”
+ toolBtnSet.Text = "确定";
+ toolBtnSet.ToolTipText = "保存更改并关闭窗口";
+
+ // 新增一个“取消”按钮
+ var toolBtnCancel = new ToolStripButton("取消")
+ {
+ DisplayStyle = ToolStripItemDisplayStyle.Text,
+ Alignment = ToolStripItemAlignment.Right // 靠右对齐
+ };
+ toolBtnCancel.Click += (sender, e) =>
+ {
+ this.DialogResult = DialogResult.Cancel;
+ this.Close();
+ };
+ toolStrip1.Items.Add(toolBtnCancel);
+ }
+
+ ///
+ /// 【新增的事件处理方法】
+ /// 当PropertyGrid中的属性值被用户修改后触发此事件。
+ ///
+
+ // 刷新左侧的相机列表
+ private void RefreshListBox()
+ {
+ listBoxModels.Items.Clear();
+ foreach (var setting in _settingsList)
+ {
+ listBoxModels.Items.Add(setting.Name);
+ }
+ }
+ ///
+ /// 【全新的事件处理方法】
+ /// 监听单个CameraSettings对象的属性变更通知。
+ ///
+ private void Setting_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ // 检查是不是“Name”属性发生了变化
+ if (e.PropertyName == nameof(CameraSettings.Name))
+ {
+ // 'sender' 就是那个属性发生了变化的 CameraSettings 对象
+ var changedSetting = sender as ModelSettings;
+ if (changedSetting == null) return;
+
+ // 在 _settingsList 中找到这个对象的索引
+ int index = _settingsList.IndexOf(changedSetting);
+
+ // 如果找到了,就更新ListBox中对应项的显示文本
+ if (index >= 0)
+ {
+ // 使用Invoke确保线程安全,虽然在此场景下通常不是问题,但这是个好习惯
+ this.Invoke(new Action(() =>
+ {
+ listBoxModels.Items[index] = changedSetting.Name;
+ }));
+ }
+ }
+ }
+
+ private void listBoxModels_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (listBoxModels.SelectedIndex >= 0)
+ {
+ propertyGrid1.SelectedObject = _settingsList[listBoxModels.SelectedIndex];
+ }
+ else
+ {
+ propertyGrid1.SelectedObject = null;
+ }
+ }
+
+ private void toolBtnAdd_Click(object sender, EventArgs e)
+ {
+ var newSetting = new ModelSettings { Name = $"model-{_settingsList.Count + 1}" };
+ _settingsList.Add(newSetting);
+ newSetting.PropertyChanged += Setting_PropertyChanged;
+ RefreshListBox();
+ listBoxModels.SelectedIndex = listBoxModels.Items.Count - 1;
+ }
+
+ private void toolBtnRemove_Click(object sender, EventArgs e)
+ {
+ if (listBoxModels.SelectedIndex >= 0)
+ {
+ _settingsList.RemoveAt(listBoxModels.SelectedIndex);
+ propertyGrid1.SelectedObject = null;
+ RefreshListBox();
+ }
+ }
+
+ private void toolBtnSet_Click(object sender, EventArgs e)
+ {
+ this.DialogResult = DialogResult.OK;
+ this.Close();
+ }
+ // 加载XML配置文件
+ private void LoadSettings()
+ {
+ if (!File.Exists(_configFilePath)) return;
+ try
+ {
+ XmlSerializer serializer = new XmlSerializer(typeof(List));
+ using (FileStream fs = new FileStream(_configFilePath, FileMode.Open))
+ {
+ _settingsList = (List)serializer.Deserialize(fs);
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("加载相机配置失败: " + ex.Message);
+ }
+ foreach (var setting in _settingsList)
+ {
+ setting.PropertyChanged += Setting_PropertyChanged;
+ }
+ }
+ }
+}
diff --git a/Check.Main/UI/ModelListEditor.resx b/Check.Main/UI/ModelListEditor.resx
new file mode 100644
index 0000000..7046689
--- /dev/null
+++ b/Check.Main/UI/ModelListEditor.resx
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
+ YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
+ 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
+ bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
+ VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
+ c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
+ Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
+ mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
+ kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
+ TgDQASA1MVpwzwAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
+ YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
+ 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
+ bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
+ VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
+ c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
+ Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
+ mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
+ kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
+ TgDQASA1MVpwzwAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
+ YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
+ 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
+ bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
+ VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
+ c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
+ Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
+ mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
+ kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
+ TgDQASA1MVpwzwAAAABJRU5ErkJggg==
+
+
+
+ 37
+
+
\ No newline at end of file
diff --git a/Check.Main/UI/ZoomPictureBox.cs b/Check.Main/UI/ZoomPictureBox.cs
new file mode 100644
index 0000000..262a663
--- /dev/null
+++ b/Check.Main/UI/ZoomPictureBox.cs
@@ -0,0 +1,381 @@
+using OpenCvSharp;
+using OpenCvSharp.Extensions;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace Check.Main.UI
+{
+ public class ZoomPictureBox : PictureBox, IDisposable
+ {
+ private float zoom = 1.0f;
+ private System.Drawing.Point imageLocation;
+ private Image image;
+ private bool dragging = false;
+ private System.Drawing.Point mouseDownPos;
+ private System.Drawing.Point imageLocationOnMouseDown;
+
+ // 矩形绘制相关
+ private bool isDrawingRect = false; // 绘制状态
+ private Rectangle currentRect; // 当前绘制矩形
+ private Rectangle storedRect; // 上次绘制并固定的矩形
+ private bool hasStoredRect = false; // 是否存在固定矩形
+ private System.Drawing.Point rectStartPoint;
+
+ // 一个私有的锁对象,专门用于保护对 'image' 字段的访问。
+ private readonly object imageLock = new object();
+
+ private bool croppingEnabled = true;
+ //private bool croppingEnabled = true;
+ [Category("Behavior")]
+ [Description("是否允许通过右键绘制矩形裁剪区域。设置为 false 则不再响应右键并清除已有矩形。")]
+ public bool CroppingEnabled
+ {
+ get => croppingEnabled;
+ set
+ {
+ croppingEnabled = value;
+ // 禁用裁剪时清除所有矩形和裁剪结果
+ if (!croppingEnabled)
+ {
+ isDrawingRect = false;
+ hasStoredRect = false;
+ LastCroppedMat?.Dispose();
+ LastCroppedMat = null;
+ }
+ Invalidate();
+ }
+ }
+
+ // 裁剪完成事件,外部可订阅以接收 Mat
+ public event Action Cropped;
+
+ public Mat LastCroppedMat { get; private set; }
+
+ private Color backgroundFillColor = Color.LightSteelBlue;
+ private Color rectangleColor = Color.Red;
+ private int rectangleThickness = 2;
+
+ [Category("Appearance")]
+ [Description("指定控件背景的填充颜色。使用 BackColor 属性同步更新。")]
+ public Color BackgroundFillColor
+ {
+ get => backgroundFillColor;
+ set
+ {
+ backgroundFillColor = value;
+ base.BackColor = value; // 同步 WinForms BackColor
+ Invalidate();
+ }
+ }
+
+
+ [Category("Appearance")]
+ [Description("绘制矩形框的颜色。")]
+ public Color RectangleColor { get => rectangleColor; set { rectangleColor = value; Invalidate(); } }
+
+ [Category("Appearance")]
+ [Description("绘制矩形框的线宽。")]
+ public int RectangleThickness { get => rectangleThickness; set { rectangleThickness = Math.Max(1, value); Invalidate(); } }
+
+ public ZoomPictureBox()
+ {
+ DoubleBuffered = true;
+ ResizeRedraw = true;
+ base.BackColor = backgroundFillColor;
+ SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
+ MouseWheel += ZoomPictureBox_MouseWheel;
+ MouseDown += ZoomPictureBox_MouseDown;
+ MouseMove += ZoomPictureBox_MouseMove;
+ MouseUp += ZoomPictureBox_MouseUp;
+ DoubleClick += ZoomPictureBox_DoubleClick;
+ }
+ // 重写背景绘制,使用自定义背景色
+ protected override void OnPaintBackground(PaintEventArgs e)
+ {
+ e.Graphics.Clear(backgroundFillColor);
+ }
+ //[Browsable(false)]
+ //public new Image Image
+ //{
+ // get => image;
+ // set
+ // {
+ // image = value;
+ // zoom = 1.0f;
+ // LastCroppedMat?.Dispose();
+ // LastCroppedMat = null;
+ // isDrawingRect = false;
+ // hasStoredRect = false;
+ // FitImage();
+ // Invalidate();
+ // }
+ //}
+ // 【关键优化】
+ // 2. 重写 Control.Dispose 方法来释放我们自己的资源
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ // 在这里释放托管和非托管资源
+ // 清理事件订阅 (虽然在这个类里没有,但这是个好习惯)
+
+ // 释放我们持有的最后一个图像资源
+ lock (imageLock)
+ {
+ this.image?.Dispose();
+ this.image = null;
+ }
+
+ // 释放我们持有的最后一个裁剪结果资源
+ this.LastCroppedMat?.Dispose();
+ this.LastCroppedMat = null;
+ }
+
+ // 调用基类的 Dispose 方法来完成标准清理
+ base.Dispose(disposing);
+ }
+
+ // 重写 Image 属性,但不做任何额外操作,因为我们将通过一个新方法来更新它。
+ [Browsable(false)]
+ public new Image Image
+ {
+ get
+ {
+ // 在访问时也加锁,确保读取的是一个完整的对象
+ lock (imageLock)
+ {
+ return image;
+ }
+ }
+ // set 访问器可以保持原样,但我们不再直接使用它来更新图像
+ private set
+ {
+ lock (imageLock)
+ {
+ image = value;
+ }
+ }
+ }
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ base.OnPaint(e);
+ var g = e.Graphics;
+ //在绘制前获取锁,确保在绘制期间,image对象不会被其他线程替换或释放
+ lock (imageLock)
+ {
+ if (image != null)
+ {
+ try
+ {
+ int w = (int)(image.Width * zoom);
+ int h = (int)(image.Height * zoom);
+ g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
+ g.DrawImage(image, new Rectangle(imageLocation, new System.Drawing.Size(w, h)));
+ }
+ catch (Exception)
+ {
+
+ // 如果在绘制时仍然发生罕见的GDI+错误,静默忽略,避免程序崩溃。
+ // 这通常意味着图像状态仍然存在问题,但UI不会因此卡死。
+ }
+ }
+ }
+ //if (image != null)
+ //{
+ // int w = (int)(image.Width * zoom);
+ // int h = (int)(image.Height * zoom);
+ // g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
+ // g.DrawImage(image, new Rectangle(imageLocation, new System.Drawing.Size(w, h)));
+ //}
+ // 仅当允许裁剪时才绘制矩形
+ if (croppingEnabled)
+ {
+ using (var pen = new Pen(rectangleColor, rectangleThickness))
+ {
+ if (hasStoredRect) g.DrawRectangle(pen, storedRect);
+ else if (isDrawingRect) g.DrawRectangle(pen, currentRect);
+ }
+ }
+ }
+
+ ///
+ /// 一个线程安全的、用于更新显示图像的公共方法。
+ /// 这个方法将替换掉直接的 pictureBox.Image = ... 赋值。
+ ///
+ /// 要显示的新图像。此方法会接管该对象的所有权。
+ public void SetImageThreadSafe(Image newImage)
+ {
+ Image oldImage = null;
+
+ lock (imageLock)
+ {
+ // 1. 保存旧图像的引用,以便在锁外部释放它
+ oldImage = this.image;
+ // 2. 将新图像赋值给成员字段
+ this.image = newImage;
+ }
+ // 3. 【关键】在锁的外部释放旧图像,避免长时间持有锁
+ oldImage?.Dispose();
+
+ // 4. 计算自适应并触发重绘
+ FitImage();
+ Invalidate();
+ }
+
+ private void FitImage()
+ {
+ //if (image == null) return;
+ //float sx = (float)ClientSize.Width / image.Width;
+ //float sy = (float)ClientSize.Height / image.Height;
+ //zoom = Math.Min(sx, sy);
+ //CenterImage();
+ //在访问image属性前获取锁
+ lock (imageLock)
+ {
+ if (image == null) return;
+
+ try
+ {
+ float sx = (float)ClientSize.Width / image.Width;
+ float sy = (float)ClientSize.Height / image.Height;
+ zoom = Math.Min(sx, sy);
+ CenterImage();
+ }
+ catch (Exception)
+ {
+
+ // 忽略错误,同 OnPaint
+ }
+ }
+ }
+
+ private void CenterImage()
+ {
+ if (image == null) return;
+ int w = (int)(image.Width * zoom);
+ int h = (int)(image.Height * zoom);
+ imageLocation = new System.Drawing.Point((ClientSize.Width - w) / 2, (ClientSize.Height - h) / 2);
+ }
+
+ private void ZoomPictureBox_MouseWheel(object sender, MouseEventArgs e)
+ {
+ if (image == null) return;
+ float oldZoom = zoom;
+ zoom *= e.Delta > 0 ? 1.1f : 1 / 1.1f;
+ zoom = Math.Max(0.1f, Math.Min(zoom, 100f));
+ var m = e.Location;
+ float ix = (m.X - imageLocation.X) / oldZoom;
+ float iy = (m.Y - imageLocation.Y) / oldZoom;
+ imageLocation = new System.Drawing.Point((int)(m.X - ix * zoom), (int)(m.Y - iy * zoom));
+ Invalidate();
+ }
+
+ private void ZoomPictureBox_MouseDown(object sender, MouseEventArgs e)
+ {
+ if (image == null) return;
+ if (e.Button == MouseButtons.Left)
+ {
+ hasStoredRect = false;
+ LastCroppedMat?.Dispose();
+ LastCroppedMat = null;
+
+ dragging = true;
+ mouseDownPos = e.Location;
+ imageLocationOnMouseDown = imageLocation;
+ Cursor = Cursors.Hand;
+ }
+ else if (e.Button == MouseButtons.Right && croppingEnabled)
+ {
+ // 清除上次固定矩形和裁剪
+ hasStoredRect = false;
+ LastCroppedMat?.Dispose();
+ LastCroppedMat = null;
+
+ // 开始新绘制
+ isDrawingRect = true;
+ rectStartPoint = e.Location;
+ currentRect = new Rectangle(e.Location, System.Drawing.Size.Empty);
+ Invalidate();
+ }
+ }
+
+ private void ZoomPictureBox_MouseMove(object sender, MouseEventArgs e)
+ {
+ if (dragging)
+ {
+ var delta = new System.Drawing.Point(e.X - mouseDownPos.X, e.Y - mouseDownPos.Y);
+ imageLocation = new System.Drawing.Point(imageLocationOnMouseDown.X + delta.X, imageLocationOnMouseDown.Y + delta.Y);
+ Invalidate();
+ }
+ else if (isDrawingRect)
+ {
+ int x = Math.Min(rectStartPoint.X, e.X);
+ int y = Math.Min(rectStartPoint.Y, e.Y);
+ int w = Math.Abs(e.X - rectStartPoint.X);
+ int h = Math.Abs(e.Y - rectStartPoint.Y);
+ currentRect = new Rectangle(x, y, w, h);
+ Invalidate();
+ }
+ }
+
+ private void ZoomPictureBox_MouseUp(object sender, MouseEventArgs e)
+ {
+ if (e.Button == MouseButtons.Left && dragging)
+ {
+ dragging = false;
+ Cursor = Cursors.Default;
+ }
+ else if (e.Button == MouseButtons.Right && isDrawingRect)
+ {
+ isDrawingRect = false;
+ // 固定当前矩形框
+ storedRect = currentRect;
+ hasStoredRect = true;
+ if (croppingEnabled && image is Bitmap bmp)
+ {
+ this.LastCroppedMat?.Dispose();
+ this.LastCroppedMat = null;
+ Mat srcMat = null;
+ try
+ {
+ int ix = (int)((storedRect.X - imageLocation.X) / zoom);
+ int iy = (int)((storedRect.Y - imageLocation.Y) / zoom);
+ int iw = (int)(storedRect.Width / zoom);
+ int ih = (int)(storedRect.Height / zoom);
+ ix = Math.Max(0, ix);
+ iy = Math.Max(0, iy);
+ if (ix + iw > bmp.Width) iw = bmp.Width - ix;
+ if (iy + ih > bmp.Height) ih = bmp.Height - iy;
+ if (iw > 0 && ih > 0)
+ {
+ srcMat = BitmapConverter.ToMat(bmp);
+ var roi = new Rect(ix, iy, iw, ih);
+ LastCroppedMat = new Mat(srcMat, roi);
+ Cropped?.Invoke(LastCroppedMat);
+ bmp.Dispose();
+ }
+ }
+ finally
+ {
+ // 5.确保从Bitmap转换来的 srcMat 被释放
+ srcMat?.Dispose();
+ }
+ }
+ Invalidate();
+ }
+ }
+ private void ZoomPictureBox_DoubleClick(object sender, EventArgs e)
+ {
+ if (image == null) return;
+ FitImage();
+ Invalidate();
+ }
+ }
+}
diff --git a/CheckDevice.sln b/CheckDevice.sln
new file mode 100644
index 0000000..ab65da3
--- /dev/null
+++ b/CheckDevice.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36310.24 d17.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Check.Main", "Check.Main\Check.Main.csproj", "{3AEFC44E-BD2D-48A9-8C0D-BF4D429E1166}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3AEFC44E-BD2D-48A9-8C0D-BF4D429E1166}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3AEFC44E-BD2D-48A9-8C0D-BF4D429E1166}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3AEFC44E-BD2D-48A9-8C0D-BF4D429E1166}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3AEFC44E-BD2D-48A9-8C0D-BF4D429E1166}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {53CBAFF8-60D2-4B61-B76A-2C11D7DA949E}
+ EndGlobalSection
+EndGlobal