diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0f6b387 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# Build results +bin/ +obj/ +*.exe +*.dll +*.pdb + +# VS temporary files +.vs/ +*.suo +*.user +*.userosscache +*.sln.docstates + +# VS Code workspace +.vscode/ + +# Backup and cache +*.cache +*.dbmdl +*.bak +*.log +*.tlog + +# Project-specific +*.ncb +*.sdf +*.opensdf +*.VC.db + +# Others you mentioned +*.dtbcache.v2 +*.futdcache.v2 +*.suo +*.DocumentLayout* +*.metadata.* +*.projects.* +*.strings.* +M18Batte.C072E897.Up2Date +TempPE/ + +# System +__pycache__/ +runtimes/ +System.IO.Ports.dll +System.Management.dll diff --git a/AppSettings.cs b/AppSettings.cs new file mode 100644 index 0000000..5be7ca4 --- /dev/null +++ b/AppSettings.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; +using System.Text.Json; + +namespace M18BatteryInfo +{ + /// + /// Persists user configurable paths for the Python executable and m18.py script. Paths are stored + /// in a JSON file under the user's application data folder so they survive app restarts without + /// requiring registry edits or manual config tweaks. + /// + public class AppSettings + { + public string PythonExecutablePath { get; set; } = "python"; + public string ScriptPath { get; set; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "m18.py"); + + private static string SettingsFilePath => + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "M18BatteryInfo", "settings.json"); + + /// + /// Load persisted settings from disk. If the file is missing or unreadable, defaults are + /// returned and a new settings file will be written the next time is called. + /// + public static AppSettings Load() + { + try + { + if (File.Exists(SettingsFilePath)) + { + var json = File.ReadAllText(SettingsFilePath); + var settings = JsonSerializer.Deserialize(json); + if (settings != null) + { + return settings; + } + } + } + catch + { + // If the file is malformed, fall back to defaults without throwing to keep the UI usable. + } + + return new AppSettings(); + } + + /// + /// Persist the current settings to disk, creating the directory if needed. + /// + public void Save() + { + var directory = Path.GetDirectoryName(SettingsFilePath); + if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + var json = JsonSerializer.Serialize(this, new JsonSerializerOptions { WriteIndented = true }); + File.WriteAllText(SettingsFilePath, json); + } + } +} diff --git a/Help Contents.txt b/Help Contents.txt new file mode 100644 index 0000000..505d927 --- /dev/null +++ b/Help Contents.txt @@ -0,0 +1,121 @@ +Functions: + DIAGNOSTICS: + m.health() - print simple health report on battery + m.read_id() - print labelled and formatted diagnostics + m.read_id(output="raw") - print in spreadsheet format + m.submit_form() - prompts for manual inputs and submits battery diagnostics data + + m.help() - this message + m.adv_help() - advanced help + + exit() - end program + +Advanced functions: + m.read_all() - print all known bytes in 0x01 command + m.read_all_spreadsheet() - print bytes in spreadsheet format + + CHARGING SIMULATION: + m.simulate() - simulate charging comms + m.simulate_for(t) - simulate for t seconds + m.high_for(t) - bring J2 high for t sec, then idle + + m.write_message(message) - write ascii string to 0x0023 register (20 chars) + + Debug: + m.PRINT_TX = True - boolean to enable TX messages + m.PRINT_RX = True - boolean to enable RX messages + m.txrx_print(bool) - set PRINT_TX & RX to bool + m.txrx_save_and_set(bool) - save PRINT_TX & RX state, then set both to bool + m.txrx_restore() - restore PRINT_TX & RX to saved values + m.brute(addr_msb, addr_lsb) + m.full_brute(start, stop, len) - check registers from 'start' to 'stop'. look for 'len' bytes + m.debug(addr_msb, addr_lsb, len, rsp_len) - send reset() then cmd() to battery + m.try_cmd(cmd, addr_h, addr_l, len) - try 'cmd' at [addr_h addr_l] with 'len' bytes + + Internal: + m.high() - bring J2 pin high (20V) + m.idle() - pull J2 pin low (0V) + m.reset() - send 0xAA to battery. Return true if battery replies wih 0xAA + m.get_snapchat() - request 'snapchat' from battery (0x61) + m.configure() - send 'configure' message (0x60, charger parameters) + m.calibrate() - calibration/interrupt command (0x55) + m.keepalive() - send charge current request (0x62) + + + + +@echo off + +echo *************************************************** +echo ** Runs m18.py with spreadsheet output and ** +echo ** copies to clipboard. You will not see output, ** +echo ** just a completion message. Then you can ** +echo ** 'ctrl+v' into a spreadsheet ** +echo ** ** +echo ** THIS WILL TAKE ~10 SECONDS ** +echo ** ** +echo ** RIGHT-CLICK AND EDIT .BAT FILE. ** +echo ** CHANGE "--port COM5" to where your adapter is ** +echo ** (you can delete this message) ** +echo *************************************************** + +python.exe .\m18.py --ss --port COM5 | clip.exe + +echo: +echo *************************************************** +echo ** Finished. Now use 'ctrl+v' to paste ** +echo ** diagnostics output into spreadsheet ** +echo ** ** +echo ** If you get errors, you must edit this batch ** +echo ** file to have the correct port. You may also ** +echo ** have hardware issues. See github ** +echo *************************************************** + +cmd /k + + + + +:: RECOMMEND RUNNING m18_idle.bat BEFORE CONNECTING TO BATTERY +:: Gives simple health report of M18 batteries +:: Add "--port COM5" (or whatever your port is) to avoid +:: having to enter it everytime + +@echo off +echo *************************************************** +echo ** RIGHT-CLICK AND EDIT .BAT FILE. ** +echo ** ADD "--port COM5" to command ** +echo ** (or whatever port your serial adapter is on) ** +echo ** (you can delete this message ** +echo *************************************************** + +python.exe .\m18.py --health +cmd /k + + + + + +:: Puts serial adapter TX in idle (low = <1V) +:: This prevents false charge count increases + +@echo off + +echo *************************************************** +echo ** RIGHT-CLICK AND EDIT .BAT FILE. ** +echo ** ADD "--port COM5" to command ** +echo ** (or whatever port your serial adapter is on) ** +echo ** (you can delete this message ** +echo *************************************************** + +python.exe .\m18.py --idle +cmd /k + + + + +:: RECOMMEND RUNNING m18_idle.bat BEFORE CONNECTING TO BATTERY +:: Runs script in interactive mode +:: All functions available + +python.exe .\m18.py \ No newline at end of file diff --git a/M18 copy.png b/M18 copy.png new file mode 100644 index 0000000..9b6143f Binary files /dev/null and b/M18 copy.png differ diff --git a/M18.ico b/M18.ico new file mode 100644 index 0000000..ab6e21b Binary files /dev/null and b/M18.ico differ diff --git a/M18.png b/M18.png new file mode 100644 index 0000000..87e3cab Binary files /dev/null and b/M18.png differ diff --git a/M18AnalyzerMain.Designer.cs b/M18AnalyzerMain.Designer.cs new file mode 100644 index 0000000..59281a5 --- /dev/null +++ b/M18AnalyzerMain.Designer.cs @@ -0,0 +1,1251 @@ +// ************************************************************************************************* +// M18AnalyzerMain.Designer.cs +// --------------------------- +// Auto-generated WinForms designer file that declares and initializes every UI control used by +// frmMain. The code positions buttons, text boxes, labels, tabs, and rich text boxes that the logic +// in M18AnalyzerMain.cs interacts with. Although the designer typically omits comments, we include +// them here to help beginners understand how InitializeComponent wires up control properties (size, +// docking, events) and how the UI layout maps to protocol actions such as toggling TX lines and +// reading health reports. +// ************************************************************************************************* +namespace M18BatteryInfo +{ + partial class frmMain + { + /// + /// 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() + { + components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmMain)); + tabControlM18Main = new TabControl(); + tabSimple = new TabPage(); + btnTestFT232 = new Button(); + grpOutput = new GroupBox(); + btnCopyOutput = new Button(); + btnReset = new Button(); + btnHealthReport = new Button(); + btnActive = new Button(); + rtbOutput = new RichTextBox(); + btnIdle = new Button(); + btnDisconnect = new Button(); + btnConnect = new Button(); + btnRefresh = new Button(); + lblSerialPort = new Label(); + cmbBxSerialPort = new ComboBox(); + tabAdvanced = new TabPage(); + btnRestoreTxRxState = new Button(); + grpTryCmd = new GroupBox(); + txtTryCmdLength = new TextBox(); + txtAddressLow = new TextBox(); + txtAddressHigh = new TextBox(); + lblTryCmdLength = new Label(); + lblAddressLow = new Label(); + lblAddrHigh = new Label(); + lblCommand = new Label(); + txtCommand = new TextBox(); + grpbxDebugCmd = new GroupBox(); + txtResponseLength = new TextBox(); + txtDebugCmdLength = new TextBox(); + txtAddrLSB = new TextBox(); + lblResponseLength = new Label(); + lblDebugCmdLength = new Label(); + lblLSB = new Label(); + lblMSB = new Label(); + txtAddrMSB = new TextBox(); + btnFullBrute = new Button(); + btnBruteAddr = new Button(); + btnSaveTxRxState = new Button(); + chkboxRxLog = new CheckBox(); + chkbxTXLog = new CheckBox(); + txtWriteMessage = new TextBox(); + btnWriteMessage = new Button(); + btnReadIDLabelled = new Button(); + btnReadIDRaw = new Button(); + btnReadAllSpreadsheet = new Button(); + btnReadAllRegisters = new Button(); + rtbAdvOutput = new RichTextBox(); + tabD2xx = new TabPage(); + rtbD2xxLog = new RichTextBox(); + tabSimulation = new TabPage(); + grpBxSimCustomProfile = new GroupBox(); + lblCutoffRaw = new Label(); + lblMaxCurrAmps = new Label(); + txtMaxCurrAmps = new TextBox(); + lblMaxCurrRaw = new Label(); + txtCutoffAmps = new TextBox(); + lblCutoffAmps = new Label(); + txtMaxCurrRaw = new TextBox(); + txtCutoffRaw = new TextBox(); + txtSimDuration = new TextBox(); + btnStopSim = new Button(); + btnStartSim = new Button(); + lblSimProfile = new Label(); + lblBaudRate = new Label(); + lblDuration = new Label(); + cmbBxChgProfile = new ComboBox(); + cmbBxBaudRate = new ComboBox(); + tabDiagnostics = new TabPage(); + btnClearDiagForm = new Button(); + grpboxDiagOutput = new GroupBox(); + rtbSubmitDiagReadOnly = new RichTextBox(); + lblType = new Label(); + lblStickerInfo = new Label(); + lblToolSerialNum = new Label(); + lblSubmitDiagDate = new Label(); + lblOneKeyID = new Label(); + txtSubmitDiagDate = new TextBox(); + txtSubmitDiagSerial = new TextBox(); + txtSubmitDiagSticker = new TextBox(); + txtSubmitDiagType = new TextBox(); + txtOneKeyID = new TextBox(); + btnSubmitDiagForm = new Button(); + tabAbout = new TabPage(); + linkLabelKillaVolt = new LinkLabel(); + lblKillaVoltAbout = new Label(); + linkLabelMartin = new LinkLabel(); + lblMartin = new Label(); + lblAboutTitle = new Label(); + toolTipSimpleTab = new ToolTip(components); + rtbDebugOutput = new RichTextBox(); + tabControlM18Main.SuspendLayout(); + tabSimple.SuspendLayout(); + grpOutput.SuspendLayout(); + tabAdvanced.SuspendLayout(); + grpTryCmd.SuspendLayout(); + grpbxDebugCmd.SuspendLayout(); + tabSimulation.SuspendLayout(); + grpBxSimCustomProfile.SuspendLayout(); + tabDiagnostics.SuspendLayout(); + grpboxDiagOutput.SuspendLayout(); + tabAbout.SuspendLayout(); + SuspendLayout(); + // + // tabControlM18Main + // + tabControlM18Main.Controls.Add(tabSimple); + tabControlM18Main.Controls.Add(tabAdvanced); + tabControlM18Main.Controls.Add(tabD2xx); + tabControlM18Main.Controls.Add(tabSimulation); + tabControlM18Main.Controls.Add(tabDiagnostics); + tabControlM18Main.Controls.Add(tabAbout); + tabControlM18Main.Location = new Point(6, 6); + tabControlM18Main.Margin = new Padding(2); + tabControlM18Main.Name = "tabControlM18Main"; + tabControlM18Main.SelectedIndex = 0; + tabControlM18Main.Size = new Size(1098, 394); + tabControlM18Main.TabIndex = 0; + // + // tabSimple + // + tabSimple.Controls.Add(btnTestFT232); + tabSimple.Controls.Add(grpOutput); + tabSimple.Controls.Add(btnDisconnect); + tabSimple.Controls.Add(btnConnect); + tabSimple.Controls.Add(btnRefresh); + tabSimple.Controls.Add(lblSerialPort); + tabSimple.Controls.Add(cmbBxSerialPort); + tabSimple.Location = new Point(4, 29); + tabSimple.Margin = new Padding(2); + tabSimple.Name = "tabSimple"; + tabSimple.Padding = new Padding(2); + tabSimple.Size = new Size(1090, 361); + tabSimple.TabIndex = 0; + tabSimple.Text = "Simple"; + tabSimple.UseVisualStyleBackColor = true; + // + // btnTestFT232 + // + btnTestFT232.Location = new Point(274, 38); + btnTestFT232.Margin = new Padding(2); + btnTestFT232.Name = "btnTestFT232"; + btnTestFT232.Size = new Size(90, 27); + btnTestFT232.TabIndex = 7; + btnTestFT232.Text = "Test Device"; + btnTestFT232.UseVisualStyleBackColor = true; + // + // grpOutput + // + grpOutput.Controls.Add(btnCopyOutput); + grpOutput.Controls.Add(btnReset); + grpOutput.Controls.Add(btnHealthReport); + grpOutput.Controls.Add(btnActive); + grpOutput.Controls.Add(rtbOutput); + grpOutput.Controls.Add(btnIdle); + grpOutput.Location = new Point(5, 70); + grpOutput.Margin = new Padding(2); + grpOutput.Name = "grpOutput"; + grpOutput.Padding = new Padding(2); + grpOutput.Size = new Size(971, 282); + grpOutput.TabIndex = 6; + grpOutput.TabStop = false; + grpOutput.Text = "Output"; + // + // btnCopyOutput + // + btnCopyOutput.Location = new Point(832, 120); + btnCopyOutput.Margin = new Padding(2); + btnCopyOutput.Name = "btnCopyOutput"; + btnCopyOutput.Size = new Size(118, 27); + btnCopyOutput.TabIndex = 11; + btnCopyOutput.Text = "Copy Output"; + toolTipSimpleTab.SetToolTip(btnCopyOutput, "Send 0xAA to battery. \r\nReturn true if battery replies wih 0xAA"); + btnCopyOutput.UseVisualStyleBackColor = true; + // + // btnReset + // + btnReset.Location = new Point(832, 248); + btnReset.Margin = new Padding(2); + btnReset.Name = "btnReset"; + btnReset.Size = new Size(118, 27); + btnReset.TabIndex = 10; + btnReset.Text = "Reset"; + toolTipSimpleTab.SetToolTip(btnReset, "Send 0xAA to battery. \r\nReturn true if battery replies wih 0xAA"); + btnReset.UseVisualStyleBackColor = true; + // + // btnHealthReport + // + btnHealthReport.Location = new Point(832, 88); + btnHealthReport.Margin = new Padding(2); + btnHealthReport.Name = "btnHealthReport"; + btnHealthReport.Size = new Size(118, 27); + btnHealthReport.TabIndex = 9; + btnHealthReport.Text = "Health Report"; + toolTipSimpleTab.SetToolTip(btnHealthReport, "Print simple health report on the connected battery."); + btnHealthReport.UseVisualStyleBackColor = true; + // + // btnActive + // + btnActive.Location = new Point(832, 56); + btnActive.Margin = new Padding(2); + btnActive.Name = "btnActive"; + btnActive.Size = new Size(118, 27); + btnActive.TabIndex = 8; + btnActive.Text = "Active (Tx High)"; + toolTipSimpleTab.SetToolTip(btnActive, "Charger simulation active.\r\nMay increase battery charge counter.\r\nNot safe to connect or disconnect battery during this state."); + btnActive.UseVisualStyleBackColor = true; + // + // rtbOutput + // + rtbOutput.BackColor = Color.Black; + rtbOutput.ForeColor = Color.Lime; + rtbOutput.Location = new Point(5, 24); + rtbOutput.Margin = new Padding(2); + rtbOutput.Name = "rtbOutput"; + rtbOutput.Size = new Size(811, 252); + rtbOutput.TabIndex = 0; + rtbOutput.Text = resources.GetString("rtbOutput.Text"); + rtbOutput.TextChanged += rtbOutput_TextChanged; + // + // btnIdle + // + btnIdle.Location = new Point(832, 24); + btnIdle.Margin = new Padding(2); + btnIdle.Name = "btnIdle"; + btnIdle.Size = new Size(118, 27); + btnIdle.TabIndex = 7; + btnIdle.Text = "Idle (Tx Low)"; + toolTipSimpleTab.SetToolTip(btnIdle, "Does not increase charge count.\r\nSafe to connect or disconnect battery."); + btnIdle.UseVisualStyleBackColor = true; + // + // btnDisconnect + // + btnDisconnect.Location = new Point(371, 38); + btnDisconnect.Margin = new Padding(2); + btnDisconnect.Name = "btnDisconnect"; + btnDisconnect.Size = new Size(90, 27); + btnDisconnect.TabIndex = 5; + btnDisconnect.Text = "Disconnect"; + btnDisconnect.UseVisualStyleBackColor = true; + // + // btnConnect + // + btnConnect.Location = new Point(179, 38); + btnConnect.Margin = new Padding(2); + btnConnect.Name = "btnConnect"; + btnConnect.Size = new Size(90, 27); + btnConnect.TabIndex = 4; + btnConnect.Text = "Connect"; + toolTipSimpleTab.SetToolTip(btnConnect, "Connect to the selected serial port."); + btnConnect.UseVisualStyleBackColor = true; + // + // btnRefresh + // + btnRefresh.Location = new Point(83, 38); + btnRefresh.Margin = new Padding(2); + btnRefresh.Name = "btnRefresh"; + btnRefresh.Size = new Size(90, 27); + btnRefresh.TabIndex = 3; + btnRefresh.Text = "Refresh"; + toolTipSimpleTab.SetToolTip(btnRefresh, "Refresh the serial port list."); + btnRefresh.UseVisualStyleBackColor = true; + // + // lblSerialPort + // + lblSerialPort.AutoSize = true; + lblSerialPort.Location = new Point(5, 11); + lblSerialPort.Margin = new Padding(2, 0, 2, 0); + lblSerialPort.Name = "lblSerialPort"; + lblSerialPort.Size = new Size(79, 20); + lblSerialPort.TabIndex = 2; + lblSerialPort.Text = "FTDI Device:"; + // + // cmbBxSerialPort + // + cmbBxSerialPort.FormattingEnabled = true; + cmbBxSerialPort.Location = new Point(86, 9); + cmbBxSerialPort.Margin = new Padding(2); + cmbBxSerialPort.Name = "cmbBxSerialPort"; + cmbBxSerialPort.Size = new Size(626, 28); + cmbBxSerialPort.TabIndex = 1; + cmbBxSerialPort.SelectedIndexChanged += cmbBxSerialPort_SelectedIndexChanged_1; + // + // tabAdvanced + // + tabAdvanced.Controls.Add(btnRestoreTxRxState); + tabAdvanced.Controls.Add(grpTryCmd); + tabAdvanced.Controls.Add(grpbxDebugCmd); + tabAdvanced.Controls.Add(btnFullBrute); + tabAdvanced.Controls.Add(btnBruteAddr); + tabAdvanced.Controls.Add(btnSaveTxRxState); + tabAdvanced.Controls.Add(chkboxRxLog); + tabAdvanced.Controls.Add(chkbxTXLog); + tabAdvanced.Controls.Add(txtWriteMessage); + tabAdvanced.Controls.Add(btnWriteMessage); + tabAdvanced.Controls.Add(btnReadIDLabelled); + tabAdvanced.Controls.Add(btnReadIDRaw); + tabAdvanced.Controls.Add(btnReadAllSpreadsheet); + tabAdvanced.Controls.Add(btnReadAllRegisters); + tabAdvanced.Controls.Add(rtbAdvOutput); + tabAdvanced.Location = new Point(4, 29); + tabAdvanced.Margin = new Padding(2); + tabAdvanced.Name = "tabAdvanced"; + tabAdvanced.Padding = new Padding(2); + tabAdvanced.Size = new Size(1090, 361); + tabAdvanced.TabIndex = 1; + tabAdvanced.Text = "Advanced"; + tabAdvanced.UseVisualStyleBackColor = true; + + // + // tabD2xx + // + tabD2xx.Controls.Add(rtbD2xxLog); + tabD2xx.Location = new Point(4, 29); + tabD2xx.Margin = new Padding(2); + tabD2xx.Name = "tabD2xx"; + tabD2xx.Padding = new Padding(2); + tabD2xx.Size = new Size(1090, 361); + tabD2xx.TabIndex = 2; + tabD2xx.Text = "Raw D2XX Log"; + tabD2xx.UseVisualStyleBackColor = true; + // + // btnRestoreTxRxState + // + btnRestoreTxRxState.Location = new Point(6, 198); + btnRestoreTxRxState.Margin = new Padding(2); + btnRestoreTxRxState.Name = "btnRestoreTxRxState"; + btnRestoreTxRxState.Size = new Size(166, 27); + btnRestoreTxRxState.TabIndex = 15; + btnRestoreTxRxState.Text = "Restore TxRx State"; + btnRestoreTxRxState.UseVisualStyleBackColor = true; + // + // grpTryCmd + // + grpTryCmd.Controls.Add(txtTryCmdLength); + grpTryCmd.Controls.Add(txtAddressLow); + grpTryCmd.Controls.Add(txtAddressHigh); + grpTryCmd.Controls.Add(lblTryCmdLength); + grpTryCmd.Controls.Add(lblAddressLow); + grpTryCmd.Controls.Add(lblAddrHigh); + grpTryCmd.Controls.Add(lblCommand); + grpTryCmd.Controls.Add(txtCommand); + grpTryCmd.Location = new Point(448, 6); + grpTryCmd.Margin = new Padding(2); + grpTryCmd.Name = "grpTryCmd"; + grpTryCmd.Padding = new Padding(2); + grpTryCmd.Size = new Size(262, 147); + grpTryCmd.TabIndex = 14; + grpTryCmd.TabStop = false; + grpTryCmd.Text = "Try Command"; + // + // txtTryCmdLength + // + txtTryCmdLength.Location = new Point(128, 115); + txtTryCmdLength.Margin = new Padding(2); + txtTryCmdLength.Name = "txtTryCmdLength"; + txtTryCmdLength.Size = new Size(129, 27); + txtTryCmdLength.TabIndex = 14; + // + // txtAddressLow + // + txtAddressLow.Location = new Point(128, 83); + txtAddressLow.Margin = new Padding(2); + txtAddressLow.Name = "txtAddressLow"; + txtAddressLow.Size = new Size(129, 27); + txtAddressLow.TabIndex = 13; + // + // txtAddressHigh + // + txtAddressHigh.Location = new Point(128, 51); + txtAddressHigh.Margin = new Padding(2); + txtAddressHigh.Name = "txtAddressHigh"; + txtAddressHigh.Size = new Size(129, 27); + txtAddressHigh.TabIndex = 12; + // + // lblTryCmdLength + // + lblTryCmdLength.AutoSize = true; + lblTryCmdLength.Location = new Point(6, 122); + lblTryCmdLength.Margin = new Padding(2, 0, 2, 0); + lblTryCmdLength.Name = "lblTryCmdLength"; + lblTryCmdLength.Size = new Size(54, 20); + lblTryCmdLength.TabIndex = 11; + lblTryCmdLength.Text = "Length"; + // + // lblAddressLow + // + lblAddressLow.AutoSize = true; + lblAddressLow.Location = new Point(6, 90); + lblAddressLow.Margin = new Padding(2, 0, 2, 0); + lblAddressLow.Name = "lblAddressLow"; + lblAddressLow.Size = new Size(93, 20); + lblAddressLow.TabIndex = 10; + lblAddressLow.Text = "Address Low"; + // + // lblAddrHigh + // + lblAddrHigh.AutoSize = true; + lblAddrHigh.Location = new Point(6, 58); + lblAddrHigh.Margin = new Padding(2, 0, 2, 0); + lblAddrHigh.Name = "lblAddrHigh"; + lblAddrHigh.Size = new Size(98, 20); + lblAddrHigh.TabIndex = 9; + lblAddrHigh.Text = "Address High"; + // + // lblCommand + // + lblCommand.AutoSize = true; + lblCommand.Location = new Point(6, 26); + lblCommand.Margin = new Padding(2, 0, 2, 0); + lblCommand.Name = "lblCommand"; + lblCommand.Size = new Size(78, 20); + lblCommand.TabIndex = 8; + lblCommand.Text = "Command"; + // + // txtCommand + // + txtCommand.Location = new Point(128, 19); + txtCommand.Margin = new Padding(2); + txtCommand.Name = "txtCommand"; + txtCommand.Size = new Size(129, 27); + txtCommand.TabIndex = 7; + // + // grpbxDebugCmd + // + grpbxDebugCmd.Controls.Add(txtResponseLength); + grpbxDebugCmd.Controls.Add(txtDebugCmdLength); + grpbxDebugCmd.Controls.Add(txtAddrLSB); + grpbxDebugCmd.Controls.Add(lblResponseLength); + grpbxDebugCmd.Controls.Add(lblDebugCmdLength); + grpbxDebugCmd.Controls.Add(lblLSB); + grpbxDebugCmd.Controls.Add(lblMSB); + grpbxDebugCmd.Controls.Add(txtAddrMSB); + grpbxDebugCmd.Location = new Point(179, 6); + grpbxDebugCmd.Margin = new Padding(2); + grpbxDebugCmd.Name = "grpbxDebugCmd"; + grpbxDebugCmd.Padding = new Padding(2); + grpbxDebugCmd.Size = new Size(262, 147); + grpbxDebugCmd.TabIndex = 13; + grpbxDebugCmd.TabStop = false; + grpbxDebugCmd.Text = "Debug Command"; + // + // txtResponseLength + // + txtResponseLength.Location = new Point(128, 115); + txtResponseLength.Margin = new Padding(2); + txtResponseLength.Name = "txtResponseLength"; + txtResponseLength.Size = new Size(129, 27); + txtResponseLength.TabIndex = 14; + // + // txtDebugCmdLength + // + txtDebugCmdLength.Location = new Point(128, 83); + txtDebugCmdLength.Margin = new Padding(2); + txtDebugCmdLength.Name = "txtDebugCmdLength"; + txtDebugCmdLength.Size = new Size(129, 27); + txtDebugCmdLength.TabIndex = 13; + // + // txtAddrLSB + // + txtAddrLSB.Location = new Point(128, 51); + txtAddrLSB.Margin = new Padding(2); + txtAddrLSB.Name = "txtAddrLSB"; + txtAddrLSB.Size = new Size(129, 27); + txtAddrLSB.TabIndex = 12; + // + // lblResponseLength + // + lblResponseLength.AutoSize = true; + lblResponseLength.Location = new Point(6, 115); + lblResponseLength.Margin = new Padding(2, 0, 2, 0); + lblResponseLength.Name = "lblResponseLength"; + lblResponseLength.Size = new Size(121, 20); + lblResponseLength.TabIndex = 11; + lblResponseLength.Text = "Response Length"; + lblResponseLength.Click += lblResponseLength_Click; + // + // lblDebugCmdLength + // + lblDebugCmdLength.AutoSize = true; + lblDebugCmdLength.Location = new Point(6, 90); + lblDebugCmdLength.Margin = new Padding(2, 0, 2, 0); + lblDebugCmdLength.Name = "lblDebugCmdLength"; + lblDebugCmdLength.Size = new Size(54, 20); + lblDebugCmdLength.TabIndex = 10; + lblDebugCmdLength.Text = "Length"; + // + // lblLSB + // + lblLSB.AutoSize = true; + lblLSB.Location = new Point(6, 58); + lblLSB.Margin = new Padding(2, 0, 2, 0); + lblLSB.Name = "lblLSB"; + lblLSB.Size = new Size(90, 20); + lblLSB.TabIndex = 9; + lblLSB.Text = "LSB Address"; + // + // lblMSB + // + lblMSB.AutoSize = true; + lblMSB.Location = new Point(6, 26); + lblMSB.Margin = new Padding(2, 0, 2, 0); + lblMSB.Name = "lblMSB"; + lblMSB.Size = new Size(96, 20); + lblMSB.TabIndex = 8; + lblMSB.Text = "MSB Address"; + // + // txtAddrMSB + // + txtAddrMSB.Location = new Point(128, 19); + txtAddrMSB.Margin = new Padding(2); + txtAddrMSB.Name = "txtAddrMSB"; + txtAddrMSB.Size = new Size(129, 27); + txtAddrMSB.TabIndex = 7; + // + // btnFullBrute + // + btnFullBrute.Location = new Point(6, 282); + btnFullBrute.Margin = new Padding(2); + btnFullBrute.Name = "btnFullBrute"; + btnFullBrute.Size = new Size(166, 27); + btnFullBrute.TabIndex = 12; + btnFullBrute.Text = "Brute Force All"; + btnFullBrute.UseVisualStyleBackColor = true; + // + // btnBruteAddr + // + btnBruteAddr.Location = new Point(6, 250); + btnBruteAddr.Margin = new Padding(2); + btnBruteAddr.Name = "btnBruteAddr"; + btnBruteAddr.Size = new Size(166, 27); + btnBruteAddr.TabIndex = 11; + btnBruteAddr.Text = "Brute Force Addresses"; + btnBruteAddr.UseVisualStyleBackColor = true; + // + // btnSaveTxRxState + // + btnSaveTxRxState.Location = new Point(6, 166); + btnSaveTxRxState.Margin = new Padding(2); + btnSaveTxRxState.Name = "btnSaveTxRxState"; + btnSaveTxRxState.Size = new Size(166, 27); + btnSaveTxRxState.TabIndex = 10; + btnSaveTxRxState.Text = "Save && Set TxRx State"; + btnSaveTxRxState.UseVisualStyleBackColor = true; + // + // chkboxRxLog + // + chkboxRxLog.AutoSize = true; + chkboxRxLog.Checked = true; + chkboxRxLog.CheckState = CheckState.Checked; + chkboxRxLog.Location = new Point(589, 301); + chkboxRxLog.Margin = new Padding(2); + chkboxRxLog.Name = "chkboxRxLog"; + chkboxRxLog.Size = new Size(125, 24); + chkboxRxLog.TabIndex = 8; + chkboxRxLog.Text = "Enable Rx Log"; + chkboxRxLog.UseVisualStyleBackColor = true; + // + // chkbxTXLog + // + chkbxTXLog.AutoSize = true; + chkbxTXLog.Checked = true; + chkbxTXLog.CheckState = CheckState.Checked; + chkbxTXLog.Location = new Point(461, 301); + chkbxTXLog.Margin = new Padding(2); + chkbxTXLog.Name = "chkbxTXLog"; + chkbxTXLog.Size = new Size(126, 24); + chkbxTXLog.TabIndex = 7; + chkbxTXLog.Text = "Enable TX Log"; + chkbxTXLog.UseVisualStyleBackColor = true; + // + // txtWriteMessage + // + txtWriteMessage.Location = new Point(179, 326); + txtWriteMessage.Margin = new Padding(2); + txtWriteMessage.Name = "txtWriteMessage"; + txtWriteMessage.Size = new Size(532, 27); + txtWriteMessage.TabIndex = 6; + txtWriteMessage.Text = "Write ASCII To Register. 20 Characters Max."; + // + // btnWriteMessage + // + btnWriteMessage.Location = new Point(6, 326); + btnWriteMessage.Margin = new Padding(2); + btnWriteMessage.Name = "btnWriteMessage"; + btnWriteMessage.Size = new Size(166, 27); + btnWriteMessage.TabIndex = 5; + btnWriteMessage.Text = "Write Message"; + btnWriteMessage.UseVisualStyleBackColor = true; + // + // btnReadIDLabelled + // + btnReadIDLabelled.Location = new Point(6, 115); + btnReadIDLabelled.Margin = new Padding(2); + btnReadIDLabelled.Name = "btnReadIDLabelled"; + btnReadIDLabelled.Size = new Size(166, 27); + btnReadIDLabelled.TabIndex = 4; + btnReadIDLabelled.Text = "Read ID (Labelled)"; + btnReadIDLabelled.UseVisualStyleBackColor = true; + // + // btnReadIDRaw + // + btnReadIDRaw.Location = new Point(6, 83); + btnReadIDRaw.Margin = new Padding(2); + btnReadIDRaw.Name = "btnReadIDRaw"; + btnReadIDRaw.Size = new Size(166, 27); + btnReadIDRaw.TabIndex = 3; + btnReadIDRaw.Text = "Read ID (Raw)"; + btnReadIDRaw.UseVisualStyleBackColor = true; + // + // btnReadAllSpreadsheet + // + btnReadAllSpreadsheet.Location = new Point(6, 51); + btnReadAllSpreadsheet.Margin = new Padding(2); + btnReadAllSpreadsheet.Name = "btnReadAllSpreadsheet"; + btnReadAllSpreadsheet.Size = new Size(166, 27); + btnReadAllSpreadsheet.TabIndex = 2; + btnReadAllSpreadsheet.Text = "Read All Spreadsheet"; + btnReadAllSpreadsheet.UseVisualStyleBackColor = true; + // + // btnReadAllRegisters + // + btnReadAllRegisters.Location = new Point(6, 19); + btnReadAllRegisters.Margin = new Padding(2); + btnReadAllRegisters.Name = "btnReadAllRegisters"; + btnReadAllRegisters.Size = new Size(166, 27); + btnReadAllRegisters.TabIndex = 1; + btnReadAllRegisters.Text = "Read All Registers"; + btnReadAllRegisters.UseVisualStyleBackColor = true; + // + // rtbAdvOutput + // + rtbAdvOutput.Location = new Point(179, 160); + rtbAdvOutput.Margin = new Padding(2); + rtbAdvOutput.Name = "rtbAdvOutput"; + rtbAdvOutput.Size = new Size(532, 142); + rtbAdvOutput.TabIndex = 0; + rtbAdvOutput.Text = ""; + + // + // rtbD2xxLog + // + rtbD2xxLog.Dock = DockStyle.Fill; + rtbD2xxLog.Location = new Point(2, 2); + rtbD2xxLog.Margin = new Padding(2); + rtbD2xxLog.Name = "rtbD2xxLog"; + rtbD2xxLog.Size = new Size(1086, 357); + rtbD2xxLog.TabIndex = 0; + rtbD2xxLog.Text = ""; + // + // tabSimulation + // + tabSimulation.Controls.Add(grpBxSimCustomProfile); + tabSimulation.Controls.Add(txtSimDuration); + tabSimulation.Controls.Add(btnStopSim); + tabSimulation.Controls.Add(btnStartSim); + tabSimulation.Controls.Add(lblSimProfile); + tabSimulation.Controls.Add(lblBaudRate); + tabSimulation.Controls.Add(lblDuration); + tabSimulation.Controls.Add(cmbBxChgProfile); + tabSimulation.Controls.Add(cmbBxBaudRate); + tabSimulation.Location = new Point(4, 29); + tabSimulation.Margin = new Padding(2); + tabSimulation.Name = "tabSimulation"; + tabSimulation.Padding = new Padding(2); + tabSimulation.Size = new Size(1090, 361); + tabSimulation.TabIndex = 3; + tabSimulation.Text = "Simulation"; + tabSimulation.UseVisualStyleBackColor = true; + // + // grpBxSimCustomProfile + // + grpBxSimCustomProfile.Controls.Add(lblCutoffRaw); + grpBxSimCustomProfile.Controls.Add(lblMaxCurrAmps); + grpBxSimCustomProfile.Controls.Add(txtMaxCurrAmps); + grpBxSimCustomProfile.Controls.Add(lblMaxCurrRaw); + grpBxSimCustomProfile.Controls.Add(txtCutoffAmps); + grpBxSimCustomProfile.Controls.Add(lblCutoffAmps); + grpBxSimCustomProfile.Controls.Add(txtMaxCurrRaw); + grpBxSimCustomProfile.Controls.Add(txtCutoffRaw); + grpBxSimCustomProfile.Location = new Point(237, 6); + grpBxSimCustomProfile.Margin = new Padding(2); + grpBxSimCustomProfile.Name = "grpBxSimCustomProfile"; + grpBxSimCustomProfile.Padding = new Padding(2); + grpBxSimCustomProfile.Size = new Size(269, 160); + grpBxSimCustomProfile.TabIndex = 16; + grpBxSimCustomProfile.TabStop = false; + grpBxSimCustomProfile.Text = "Custom Charger Profile"; + grpBxSimCustomProfile.Enter += grpBxSimCustomProfile_Enter; + // + // lblCutoffRaw + // + lblCutoffRaw.AutoSize = true; + lblCutoffRaw.Location = new Point(6, 26); + lblCutoffRaw.Margin = new Padding(2, 0, 2, 0); + lblCutoffRaw.Name = "lblCutoffRaw"; + lblCutoffRaw.Size = new Size(92, 20); + lblCutoffRaw.TabIndex = 12; + lblCutoffRaw.Text = "Cutoff (Raw)"; + // + // lblMaxCurrAmps + // + lblMaxCurrAmps.AutoSize = true; + lblMaxCurrAmps.Location = new Point(6, 122); + lblMaxCurrAmps.Margin = new Padding(2, 0, 2, 0); + lblMaxCurrAmps.Name = "lblMaxCurrAmps"; + lblMaxCurrAmps.Size = new Size(144, 20); + lblMaxCurrAmps.TabIndex = 15; + lblMaxCurrAmps.Text = "Max. Current (Amps)"; + // + // txtMaxCurrAmps + // + txtMaxCurrAmps.Location = new Point(147, 122); + txtMaxCurrAmps.Margin = new Padding(2); + txtMaxCurrAmps.Name = "txtMaxCurrAmps"; + txtMaxCurrAmps.Size = new Size(108, 27); + txtMaxCurrAmps.TabIndex = 8; + // + // lblMaxCurrRaw + // + lblMaxCurrRaw.AutoSize = true; + lblMaxCurrRaw.Location = new Point(6, 90); + lblMaxCurrRaw.Margin = new Padding(2, 0, 2, 0); + lblMaxCurrRaw.Name = "lblMaxCurrRaw"; + lblMaxCurrRaw.Size = new Size(134, 20); + lblMaxCurrRaw.TabIndex = 14; + lblMaxCurrRaw.Text = "Max. Current (Raw)"; + // + // txtCutoffAmps + // + txtCutoffAmps.Location = new Point(147, 58); + txtCutoffAmps.Margin = new Padding(2); + txtCutoffAmps.Name = "txtCutoffAmps"; + txtCutoffAmps.Size = new Size(108, 27); + txtCutoffAmps.TabIndex = 9; + // + // lblCutoffAmps + // + lblCutoffAmps.AutoSize = true; + lblCutoffAmps.Location = new Point(6, 58); + lblCutoffAmps.Margin = new Padding(2, 0, 2, 0); + lblCutoffAmps.Name = "lblCutoffAmps"; + lblCutoffAmps.Size = new Size(102, 20); + lblCutoffAmps.TabIndex = 13; + lblCutoffAmps.Text = "Cutoff (Amps)"; + // + // txtMaxCurrRaw + // + txtMaxCurrRaw.Location = new Point(147, 90); + txtMaxCurrRaw.Margin = new Padding(2); + txtMaxCurrRaw.Name = "txtMaxCurrRaw"; + txtMaxCurrRaw.Size = new Size(108, 27); + txtMaxCurrRaw.TabIndex = 10; + // + // txtCutoffRaw + // + txtCutoffRaw.Location = new Point(147, 26); + txtCutoffRaw.Margin = new Padding(2); + txtCutoffRaw.Name = "txtCutoffRaw"; + txtCutoffRaw.Size = new Size(108, 27); + txtCutoffRaw.TabIndex = 11; + // + // txtSimDuration + // + txtSimDuration.Location = new Point(134, 6); + txtSimDuration.Margin = new Padding(2); + txtSimDuration.Name = "txtSimDuration"; + txtSimDuration.Size = new Size(97, 27); + txtSimDuration.TabIndex = 7; + // + // btnStopSim + // + btnStopSim.Location = new Point(6, 102); + btnStopSim.Margin = new Padding(2); + btnStopSim.Name = "btnStopSim"; + btnStopSim.Size = new Size(90, 27); + btnStopSim.TabIndex = 6; + btnStopSim.Text = "Stop"; + btnStopSim.UseVisualStyleBackColor = true; + // + // btnStartSim + // + btnStartSim.Location = new Point(141, 102); + btnStartSim.Margin = new Padding(2); + btnStartSim.Name = "btnStartSim"; + btnStartSim.Size = new Size(90, 27); + btnStartSim.TabIndex = 1; + btnStartSim.Text = "Start"; + btnStartSim.UseVisualStyleBackColor = true; + // + // lblSimProfile + // + lblSimProfile.AutoSize = true; + lblSimProfile.Location = new Point(6, 70); + lblSimProfile.Margin = new Padding(2, 0, 2, 0); + lblSimProfile.Name = "lblSimProfile"; + lblSimProfile.Size = new Size(108, 20); + lblSimProfile.TabIndex = 5; + lblSimProfile.Text = "Charger Profile"; + // + // lblBaudRate + // + lblBaudRate.AutoSize = true; + lblBaudRate.Location = new Point(6, 38); + lblBaudRate.Margin = new Padding(2, 0, 2, 0); + lblBaudRate.Name = "lblBaudRate"; + lblBaudRate.Size = new Size(77, 20); + lblBaudRate.TabIndex = 4; + lblBaudRate.Text = "Baud Rate"; + // + // lblDuration + // + lblDuration.AutoSize = true; + lblDuration.Location = new Point(6, 6); + lblDuration.Margin = new Padding(2, 0, 2, 0); + lblDuration.Name = "lblDuration"; + lblDuration.Size = new Size(136, 20); + lblDuration.TabIndex = 3; + lblDuration.Text = "Duration (Seconds)"; + // + // cmbBxChgProfile + // + cmbBxChgProfile.FormattingEnabled = true; + cmbBxChgProfile.Location = new Point(134, 70); + cmbBxChgProfile.Margin = new Padding(2); + cmbBxChgProfile.Name = "cmbBxChgProfile"; + cmbBxChgProfile.Size = new Size(97, 28); + cmbBxChgProfile.TabIndex = 2; + // + // cmbBxBaudRate + // + cmbBxBaudRate.FormattingEnabled = true; + cmbBxBaudRate.Location = new Point(134, 38); + cmbBxBaudRate.Margin = new Padding(2); + cmbBxBaudRate.Name = "cmbBxBaudRate"; + cmbBxBaudRate.Size = new Size(97, 28); + cmbBxBaudRate.TabIndex = 1; + // + // tabDiagnostics + // + tabDiagnostics.Controls.Add(btnClearDiagForm); + tabDiagnostics.Controls.Add(grpboxDiagOutput); + tabDiagnostics.Controls.Add(lblType); + tabDiagnostics.Controls.Add(lblStickerInfo); + tabDiagnostics.Controls.Add(lblToolSerialNum); + tabDiagnostics.Controls.Add(lblSubmitDiagDate); + tabDiagnostics.Controls.Add(lblOneKeyID); + tabDiagnostics.Controls.Add(txtSubmitDiagDate); + tabDiagnostics.Controls.Add(txtSubmitDiagSerial); + tabDiagnostics.Controls.Add(txtSubmitDiagSticker); + tabDiagnostics.Controls.Add(txtSubmitDiagType); + tabDiagnostics.Controls.Add(txtOneKeyID); + tabDiagnostics.Controls.Add(btnSubmitDiagForm); + tabDiagnostics.Location = new Point(4, 29); + tabDiagnostics.Margin = new Padding(2); + tabDiagnostics.Name = "tabDiagnostics"; + tabDiagnostics.Padding = new Padding(2); + tabDiagnostics.Size = new Size(1090, 361); + tabDiagnostics.TabIndex = 4; + tabDiagnostics.Text = "Submit Diagnostics"; + tabDiagnostics.UseVisualStyleBackColor = true; + // + // btnClearDiagForm + // + btnClearDiagForm.Location = new Point(461, 173); + btnClearDiagForm.Margin = new Padding(2); + btnClearDiagForm.Name = "btnClearDiagForm"; + btnClearDiagForm.Size = new Size(122, 27); + btnClearDiagForm.TabIndex = 23; + btnClearDiagForm.Text = "Clear Form"; + btnClearDiagForm.UseVisualStyleBackColor = true; + // + // grpboxDiagOutput + // + grpboxDiagOutput.Controls.Add(rtbSubmitDiagReadOnly); + grpboxDiagOutput.Location = new Point(237, 6); + grpboxDiagOutput.Margin = new Padding(2); + grpboxDiagOutput.Name = "grpboxDiagOutput"; + grpboxDiagOutput.Padding = new Padding(2); + grpboxDiagOutput.Size = new Size(474, 160); + grpboxDiagOutput.TabIndex = 22; + grpboxDiagOutput.TabStop = false; + grpboxDiagOutput.Text = "Diagnostic Output"; + // + // rtbSubmitDiagReadOnly + // + rtbSubmitDiagReadOnly.Location = new Point(6, 26); + rtbSubmitDiagReadOnly.Margin = new Padding(2); + rtbSubmitDiagReadOnly.Name = "rtbSubmitDiagReadOnly"; + rtbSubmitDiagReadOnly.Size = new Size(462, 129); + rtbSubmitDiagReadOnly.TabIndex = 16; + rtbSubmitDiagReadOnly.Text = ""; + // + // lblType + // + lblType.AutoSize = true; + lblType.Location = new Point(13, 141); + lblType.Margin = new Padding(2, 0, 2, 0); + lblType.Name = "lblType"; + lblType.Size = new Size(40, 20); + lblType.TabIndex = 21; + lblType.Text = "Type"; + // + // lblStickerInfo + // + lblStickerInfo.AutoSize = true; + lblStickerInfo.Location = new Point(13, 109); + lblStickerInfo.Margin = new Padding(2, 0, 2, 0); + lblStickerInfo.Name = "lblStickerInfo"; + lblStickerInfo.Size = new Size(53, 20); + lblStickerInfo.TabIndex = 20; + lblStickerInfo.Text = "Sticker"; + // + // lblToolSerialNum + // + lblToolSerialNum.AutoSize = true; + lblToolSerialNum.Location = new Point(13, 77); + lblToolSerialNum.Margin = new Padding(2, 0, 2, 0); + lblToolSerialNum.Name = "lblToolSerialNum"; + lblToolSerialNum.Size = new Size(59, 20); + lblToolSerialNum.TabIndex = 19; + lblToolSerialNum.Text = "Serial #"; + // + // lblSubmitDiagDate + // + lblSubmitDiagDate.AutoSize = true; + lblSubmitDiagDate.Location = new Point(13, 45); + lblSubmitDiagDate.Margin = new Padding(2, 0, 2, 0); + lblSubmitDiagDate.Name = "lblSubmitDiagDate"; + lblSubmitDiagDate.Size = new Size(41, 20); + lblSubmitDiagDate.TabIndex = 18; + lblSubmitDiagDate.Text = "Date"; + // + // lblOneKeyID + // + lblOneKeyID.AutoSize = true; + lblOneKeyID.Location = new Point(13, 13); + lblOneKeyID.Margin = new Padding(2, 0, 2, 0); + lblOneKeyID.Name = "lblOneKeyID"; + lblOneKeyID.Size = new Size(85, 20); + lblOneKeyID.TabIndex = 17; + lblOneKeyID.Text = "One-Key ID"; + // + // txtSubmitDiagDate + // + txtSubmitDiagDate.Location = new Point(96, 45); + txtSubmitDiagDate.Margin = new Padding(2); + txtSubmitDiagDate.Name = "txtSubmitDiagDate"; + txtSubmitDiagDate.Size = new Size(121, 27); + txtSubmitDiagDate.TabIndex = 15; + // + // txtSubmitDiagSerial + // + txtSubmitDiagSerial.Location = new Point(96, 77); + txtSubmitDiagSerial.Margin = new Padding(2); + txtSubmitDiagSerial.Name = "txtSubmitDiagSerial"; + txtSubmitDiagSerial.Size = new Size(121, 27); + txtSubmitDiagSerial.TabIndex = 14; + // + // txtSubmitDiagSticker + // + txtSubmitDiagSticker.Location = new Point(96, 109); + txtSubmitDiagSticker.Margin = new Padding(2); + txtSubmitDiagSticker.Name = "txtSubmitDiagSticker"; + txtSubmitDiagSticker.Size = new Size(121, 27); + txtSubmitDiagSticker.TabIndex = 13; + // + // txtSubmitDiagType + // + txtSubmitDiagType.Location = new Point(96, 141); + txtSubmitDiagType.Margin = new Padding(2); + txtSubmitDiagType.Name = "txtSubmitDiagType"; + txtSubmitDiagType.Size = new Size(121, 27); + txtSubmitDiagType.TabIndex = 11; + // + // txtOneKeyID + // + txtOneKeyID.Location = new Point(96, 13); + txtOneKeyID.Margin = new Padding(2); + txtOneKeyID.Name = "txtOneKeyID"; + txtOneKeyID.Size = new Size(121, 27); + txtOneKeyID.TabIndex = 10; + // + // btnSubmitDiagForm + // + btnSubmitDiagForm.Location = new Point(589, 173); + btnSubmitDiagForm.Margin = new Padding(2); + btnSubmitDiagForm.Name = "btnSubmitDiagForm"; + btnSubmitDiagForm.Size = new Size(122, 27); + btnSubmitDiagForm.TabIndex = 9; + btnSubmitDiagForm.Text = "Submit Form"; + btnSubmitDiagForm.UseVisualStyleBackColor = true; + // + // tabAbout + // + tabAbout.Controls.Add(linkLabelKillaVolt); + tabAbout.Controls.Add(lblKillaVoltAbout); + tabAbout.Controls.Add(linkLabelMartin); + tabAbout.Controls.Add(lblMartin); + tabAbout.Controls.Add(lblAboutTitle); + tabAbout.Location = new Point(4, 29); + tabAbout.Margin = new Padding(2); + tabAbout.Name = "tabAbout"; + tabAbout.Padding = new Padding(2); + tabAbout.Size = new Size(1090, 361); + tabAbout.TabIndex = 5; + tabAbout.Text = "About"; + tabAbout.UseVisualStyleBackColor = true; + // + // linkLabelKillaVolt + // + linkLabelKillaVolt.AutoSize = true; + linkLabelKillaVolt.LinkArea = new LinkArea(13, 60); + linkLabelKillaVolt.Location = new Point(218, 141); + linkLabelKillaVolt.Margin = new Padding(2, 0, 2, 0); + linkLabelKillaVolt.Name = "linkLabelKillaVolt"; + linkLabelKillaVolt.Size = new Size(289, 25); + linkLabelKillaVolt.TabIndex = 4; + linkLabelKillaVolt.TabStop = true; + linkLabelKillaVolt.Text = "GitHub Repo: https://github.com/KillaVolt"; + linkLabelKillaVolt.UseCompatibleTextRendering = true; + // + // lblKillaVoltAbout + // + lblKillaVoltAbout.AutoSize = true; + lblKillaVoltAbout.Font = new Font("Segoe UI", 10F, FontStyle.Bold, GraphicsUnit.Point, 0); + lblKillaVoltAbout.Location = new Point(256, 115); + lblKillaVoltAbout.Margin = new Padding(2, 0, 2, 0); + lblKillaVoltAbout.Name = "lblKillaVoltAbout"; + lblKillaVoltAbout.Size = new Size(219, 23); + lblKillaVoltAbout.TabIndex = 3; + lblKillaVoltAbout.Text = "GUI designed By: KillaVolt"; + // + // linkLabelMartin + // + linkLabelMartin.AutoSize = true; + linkLabelMartin.LinkArea = new LinkArea(13, 60); + linkLabelMartin.Location = new Point(160, 90); + linkLabelMartin.Margin = new Padding(2, 0, 2, 0); + linkLabelMartin.Name = "linkLabelMartin"; + linkLabelMartin.Size = new Size(429, 25); + linkLabelMartin.TabIndex = 2; + linkLabelMartin.TabStop = true; + linkLabelMartin.Text = "GitHub Repo: https://github.com/mnh-jansson/m18-protocol/"; + linkLabelMartin.UseCompatibleTextRendering = true; + linkLabelMartin.LinkClicked += linkLabel1_LinkClicked; + // + // lblMartin + // + lblMartin.AutoSize = true; + lblMartin.Font = new Font("Segoe UI", 10F, FontStyle.Bold, GraphicsUnit.Point, 0); + lblMartin.Location = new Point(179, 64); + lblMartin.Margin = new Padding(2, 0, 2, 0); + lblMartin.Name = "lblMartin"; + lblMartin.Size = new Size(386, 23); + lblMartin.TabIndex = 1; + lblMartin.Text = "Original M18 Protocol code by: Martin Jansson"; + // + // lblAboutTitle + // + lblAboutTitle.Font = new Font("Segoe UI Black", 26F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point, 0); + lblAboutTitle.Image = (Image)resources.GetObject("lblAboutTitle.Image"); + lblAboutTitle.ImageAlign = ContentAlignment.MiddleLeft; + lblAboutTitle.Location = new Point(115, 6); + lblAboutTitle.Margin = new Padding(2, 0, 2, 0); + lblAboutTitle.Name = "lblAboutTitle"; + lblAboutTitle.Size = new Size(506, 64); + lblAboutTitle.TabIndex = 0; + lblAboutTitle.Text = " Pack Analyzer GUI"; + lblAboutTitle.TextAlign = ContentAlignment.TopCenter; + // + // rtbDebugOutput + // + rtbDebugOutput.Location = new Point(8, 400); + rtbDebugOutput.Margin = new Padding(2); + rtbDebugOutput.Name = "rtbDebugOutput"; + rtbDebugOutput.Size = new Size(1136, 224); + rtbDebugOutput.TabIndex = 1; + rtbDebugOutput.Text = ""; + // + // frmMain + // + AutoScaleDimensions = new SizeF(8F, 20F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(1155, 637); + Controls.Add(rtbDebugOutput); + Controls.Add(tabControlM18Main); + Icon = (Icon)resources.GetObject("$this.Icon"); + Margin = new Padding(2); + Name = "frmMain"; + ShowIcon = false; + Text = "M18 Pack Analyzer"; + Load += frmMain_Load; + tabControlM18Main.ResumeLayout(false); + tabSimple.ResumeLayout(false); + tabSimple.PerformLayout(); + grpOutput.ResumeLayout(false); + tabAdvanced.ResumeLayout(false); + tabAdvanced.PerformLayout(); + grpTryCmd.ResumeLayout(false); + grpTryCmd.PerformLayout(); + grpbxDebugCmd.ResumeLayout(false); + grpbxDebugCmd.PerformLayout(); + tabD2xx.ResumeLayout(false); + tabSimulation.ResumeLayout(false); + tabSimulation.PerformLayout(); + grpBxSimCustomProfile.ResumeLayout(false); + grpBxSimCustomProfile.PerformLayout(); + tabDiagnostics.ResumeLayout(false); + tabDiagnostics.PerformLayout(); + grpboxDiagOutput.ResumeLayout(false); + tabAbout.ResumeLayout(false); + tabAbout.PerformLayout(); + ResumeLayout(false); + } + + #endregion + + private TabControl tabControlM18Main; + private TabPage tabSimple; + private TabPage tabAdvanced; + private TabPage tabD2xx; + private ComboBox cmbBxSerialPort; + private RichTextBox rtbOutput; + private TabPage tabSimulation; + private TabPage tabDiagnostics; + private Button btnConnect; + private Button btnRefresh; + private Label lblSerialPort; + private GroupBox grpOutput; + private Button btnDisconnect; + private Button btnIdle; + private Button btnActive; + private ToolTip toolTipSimpleTab; + private Button btnHealthReport; + private Button btnReset; + private Button btnCopyOutput; + private Button btnReadAllSpreadsheet; + private Button btnReadAllRegisters; + private RichTextBox rtbAdvOutput; + private RichTextBox rtbD2xxLog; + private TextBox txtWriteMessage; + private Button btnWriteMessage; + private Button btnReadIDLabelled; + private Button btnReadIDRaw; + private TabPage tabAbout; + private CheckBox chkboxRxLog; + private CheckBox chkbxTXLog; + private Button btnSaveTxRxState; + private Button btnBruteAddr; + private Button btnFullBrute; + private GroupBox grpbxDebugCmd; + private TextBox txtAddrMSB; + private Label lblResponseLength; + private Label lblDebugCmdLength; + private Label lblLSB; + private Label lblMSB; + private TextBox txtResponseLength; + private TextBox txtDebugCmdLength; + private TextBox txtAddrLSB; + private GroupBox grpTryCmd; + private TextBox txtTryCmdLength; + private TextBox txtAddressLow; + private TextBox txtAddressHigh; + private Label lblTryCmdLength; + private Label lblAddressLow; + private Label lblAddrHigh; + private Label lblCommand; + private TextBox txtCommand; + private ComboBox cmbBxChgProfile; + private ComboBox cmbBxBaudRate; + private Button btnRestoreTxRxState; + private Button btnSubmitDiagForm; + private Label lblType; + private Label lblStickerInfo; + private Label lblToolSerialNum; + private Label lblSubmitDiagDate; + private Label lblOneKeyID; + private RichTextBox rtbSubmitDiagReadOnly; + private TextBox txtSubmitDiagDate; + private TextBox txtSubmitDiagSerial; + private TextBox txtSubmitDiagSticker; + private TextBox txtSubmitDiagType; + private TextBox txtOneKeyID; + private Button btnStartSim; + private Label lblSimProfile; + private Label lblBaudRate; + private Label lblDuration; + private Button btnStopSim; + private TextBox txtSimDuration; + private TextBox txtCutoffRaw; + private TextBox txtMaxCurrRaw; + private TextBox txtCutoffAmps; + private TextBox txtMaxCurrAmps; + private Label lblMaxCurrAmps; + private Label lblMaxCurrRaw; + private Label lblCutoffAmps; + private Label lblCutoffRaw; + private GroupBox grpboxDiagOutput; + private Button btnClearDiagForm; + private GroupBox grpBxSimCustomProfile; + private Label lblAboutTitle; + private LinkLabel linkLabelMartin; + private Label lblMartin; + private LinkLabel linkLabelKillaVolt; + private Label lblKillaVoltAbout; + private RichTextBox rtbDebugOutput; + private Button btnTestFT232; + } +} diff --git a/M18AnalyzerMain.cs b/M18AnalyzerMain.cs new file mode 100644 index 0000000..538cf2e --- /dev/null +++ b/M18AnalyzerMain.cs @@ -0,0 +1,814 @@ +// ************************************************************************************************* +// M18AnalyzerMain.cs +// ------------------ +// Hosts the user-facing WinForms logic for the Milwaukee M18 battery analyzer GUI. This partial +// class pairs with M18AnalyzerMain.Designer.cs (UI layout) to render the form and wire up buttons, +// combo boxes, and rich text boxes. It now acts as a bridge between UI events and the authoritative +// Python implementation (m18.py), launching the script as a child process and streaming stdout/stderr +// into the existing logs. Serial port discovery still flows through SerialPortUtil.cs so the user can +// select the COM port that will be passed to Python. Every method and key line is commented to teach +// WinForms fundamentals (event registration, marshaling to the UI thread) and logging approaches. +// ************************************************************************************************* + +using System; // Provides core types like EventArgs, Action, and DateTime used throughout the form. +using System.Collections.Generic; // Supplies List for storing serial port objects. +using System.IO; // Validates python and script paths. +using System.Linq; // Enables LINQ helpers such as Select and ToList used during logging. +using System.Threading; // Supports cancellation and timeouts. +using System.Threading.Tasks; // Enables Task.Run for background work that keeps the UI responsive. +using System.Windows.Forms; // Provides Form, control types, and dialog helpers used by WinForms. + +namespace M18BatteryInfo +{ + /// + /// The primary WinForms window that presents user controls for serial port selection, + /// connection management, and protocol commands (idle/high/reset/health-report). This class + /// captures events fired by buttons and other controls, marshals work to background threads so + /// the UI does not freeze, and forwards user actions to the Python reference implementation + /// (m18.py). It also uses to enumerate serial ports with extended + /// metadata for the Python process to consume. + /// + public partial class frmMain : Form + { + // Hosts the interactive Python session. + private PythonProcessController? _pythonController; + // Persisted settings for python and script locations. + private readonly AppSettings _settings = AppSettings.Load(); + // Tracks whether a Python command is currently in-flight (waiting for prompt). + private bool _isPythonBusy; + // Timeout used when waiting for Python to return to the REPL prompt. + private readonly TimeSpan _commandTimeout = TimeSpan.FromSeconds(15); + // Track whether the simple output RichTextBox already has content to manage newlines. + private bool _hasAppendedLog; // Ensures we only prepend Environment.NewLine after the first log line. + // Track whether the advanced output RichTextBox already has content. + private bool _hasAppendedAdvancedLog; // Similar flag for the advanced log tab to avoid leading blank lines. + // Track whether the debug output RichTextBox already has content. + private bool _hasAppendedDebugLog; // Prevents inserting extra blank lines before first debug message. + // Track whether the raw serial log RichTextBox already has content. + private bool _hasAppendedSerialLog; // Prevents inserting extra blank lines before first raw serial entry. + // Store the currently selected serial device for connection attempts. + private SerialPortDisplay? _selectedDevice; // Persisted when user picks an item from cmbBxSerialPort. + // Store a human-friendly device description for user messages. + private string? _selectedDeviceDescription; // Derived from SerialPortDisplay to show manufacturer/USB metadata. + + /// + /// Constructs the form, initializes UI components generated by the designer, and hooks up + /// event handlers for all buttons and checkbox controls. The constructor also sets helpful + /// tooltips and initializes the UI to a disconnected state. + /// + public frmMain() + { + InitializeComponent(); // Calls into the designer-generated control creation code. + + // Wire up button click and change handlers to their corresponding methods. Delegates are + // created here to keep designer file clean and to demonstrate event subscription syntax. + btnRefresh.Click += btnRefresh_Click; // Refresh list of serial ports when "Refresh" pressed. + btnConnect.Click += btnConnect_Click; // Launch Python on the selected port when "Connect" pressed. + btnDisconnect.Click += btnDisconnect_Click; // Stop the Python process when "Disconnect" pressed. + btnIdle.Click += btnIdle_Click; // Ask Python to drive TX low (idle charger pin). + btnActive.Click += btnActive_Click; // Ask Python to drive TX high (charging simulation). + btnHealthReport.Click += btnHealthReport_Click; // Trigger multi-register read via Python health(). + btnReset.Click += btnReset_Click; // Send reset handshake through Python. + btnCopyOutput.Click += btnCopyOutput_Click; // Copy logs to clipboard for sharing/debugging. + chkbxTXLog.CheckedChanged += chkbxTXLog_CheckedChanged; // Toggle TX byte logging. + chkboxRxLog.CheckedChanged += chkboxRxLog_CheckedChanged; // Toggle RX byte logging. + btnTestFT232.Click += btnTestFT232_Click; // Run quick FT232 loopback/response test. + cmbBxSerialPort.SelectedIndexChanged += cmbBxSerialPort_SelectedIndexChanged; // Capture selected serial port. + FormClosing += frmMain_FormClosing; // Ensure we cleanly close serial port when form closes. + + // Default logging preferences to on to maintain parity with previous UI. + chkbxTXLog.Checked = true; // TX log checkbox retained for compatibility. + chkboxRxLog.Checked = true; // RX log checkbox retained for compatibility. + + // Provide friendly tooltips describing each control's purpose. + toolTipSimpleTab.SetToolTip(btnRefresh, "Refresh the list of available serial ports."); // Helps beginners understand UI flow. + toolTipSimpleTab.SetToolTip(btnConnect, "Connect to the selected serial port."); // Explains connection button. + toolTipSimpleTab.SetToolTip(btnDisconnect, "Disconnect from the currently connected device."); // Clarifies safe disconnect. + toolTipSimpleTab.SetToolTip(btnIdle, "Drive TX low (idle). Safe for connect/disconnect."); // Notes electrical effect on TX line. + toolTipSimpleTab.SetToolTip(btnActive, "Drive TX high (active). Charger simulation."); // Indicates charger-simulation state. + toolTipSimpleTab.SetToolTip(btnHealthReport, "Read and display a basic battery health report."); + toolTipSimpleTab.SetToolTip(btnReset, "Send a reset signal to the connected battery."); + toolTipSimpleTab.SetToolTip(btnCopyOutput, "Copy all output log text to the clipboard."); // Guides how to export logs. + + InitializePythonController(); // Prepare the Python process host and logging bridges. + + UpdateConnectionUi(false); // Disable connection-dependent buttons until a port opens. + } + + /// + /// Placeholder handler generated by WinForms designer for a tool strip button; retained to + /// illustrate event signatures even when unused. + /// + private void toolStripButton1_Click(object sender, EventArgs e) + { + // No logic implemented. Keeping the method demonstrates the event handler pattern that + // other buttons follow. Deleting could break designer hookups, so it stays as a template. + } + + /// + /// Create a fresh PythonProcessController instance and wire its events into the existing log + /// surfaces so stdout/stderr are mirrored into the UI. + /// + private void InitializePythonController() + { + _pythonController?.Dispose(); + _pythonController = new PythonProcessController(_settings.PythonExecutablePath, _settings.ScriptPath); + _pythonController.OutputReceived += line => AppendPythonLog(line, false); + _pythonController.ErrorReceived += line => AppendPythonLog(line, true); + _pythonController.PromptDetected += () => SetPythonBusy(false); + _pythonController.Exited += exitCode => + { + AppendLogBoth($"Python process exited (code: {exitCode?.ToString() ?? "unknown"})."); + SetPythonBusy(false); + UpdateConnectionUi(false); + }; + } + + /// + /// Stub for tooltip popup events. Included for completeness to show how ToolTip can be + /// customized if desired. + /// + private void toolTipReset_Popup(object sender, PopupEventArgs e) + { + // Intentionally blank. If we wanted dynamic tooltips, this would adjust size or text. + } + + /// + /// Executes when the form finishes loading. We immediately refresh serial ports so the + /// combo box is populated before the user interacts with it. + /// + private void frmMain_Load(object sender, EventArgs e) + { + RefreshSerialPorts(); // Kick off device enumeration via SerialPortUtil. + } + + /// + /// Auto-generated click handler for label controls; retained as teaching stub. + /// + private void lblResponseLength_Click(object sender, EventArgs e) + { + // Labels typically do not need click handlers, but this stub shows the event signature. + } + + /// + /// Stub demonstrating how to handle PictureBox click events if interactive imagery is added. + /// + private void pictureBox1_Click(object sender, EventArgs e) + { + // No operation required; included so readers see how to subscribe to image clicks. + } + + /// + /// Stub illustrating how to respond to link clicks in LinkLabel controls. + /// + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + // Could open documentation URLs; left empty to avoid unintended navigation. + } + + /// + /// Stub demonstrating Enter events on group boxes (focus gained). + /// + private void grpBxSimCustomProfile_Enter(object sender, EventArgs e) + { + // Could be used to populate custom simulation values; no logic required today. + } + + /// + /// Handles the Refresh button click by logging intent and enumerating ports. + /// + private void btnRefresh_Click(object? sender, EventArgs e) + { + LogDebugAction("Requesting RefreshSerialPorts()."); // Show action in debug log for traceability. + RefreshSerialPorts(); // Pull latest serial ports using SerialPortUtil. + } + + /// + /// Enumerates available serial ports, populates the combo box, and logs rich metadata for + /// troubleshooting USB cables/adapters. Uses . + /// + private void RefreshSerialPorts() + { + AppendLogBoth("Refreshing serial port list..."); // Inform user in both simple and debug logs. + + try + { + var devices = GetSerialPorts(); // Gather serial info via SetupAPI for COM mapping. + + cmbBxSerialPort.Items.Clear(); // Reset combo box so old entries do not linger. + foreach (var device in devices) + { + cmbBxSerialPort.Items.Add(device); // Add serial record; ToString() shows DisplayName. + AppendLogBoth($"Found serial port {device.DisplayName}"); // Echo discovery to the log. + } + + AppendDebugLog($"RefreshSerialPorts(): {devices.Count} serial port(s) detected."); // Debug summary count. + foreach (var device in devices) + { + var sourceLabel = string.IsNullOrWhiteSpace(device.Source) ? "Unknown source" : device.Source; // Prefer readable source text. + AppendDebugLog($" - {device.DisplayName} (source: {sourceLabel})."); // Include display name and source origin. + AppendDebugLog($" Details: description='{device.Description}', serial='{device.UsbSerialNumber}', COM='{device.PortName}', manufacturer='{device.Manufacturer ?? "(none)"}'"); // Show manufacturer/hardware IDs for driver troubleshooting. + } + + if (devices.Count == 0) + { + AppendLogBoth("No serial ports detected."); // Warn user if no cables are found (e.g., driver missing). + } + else + { + cmbBxSerialPort.SelectedIndex = 0; // Auto-select first device to streamline connection flow. + } + + if (cmbBxSerialPort.SelectedItem is null) + { + _selectedDevice = null; // Reset selection tracking if nothing is selected. + _selectedDeviceDescription = null; // Clear human-friendly description too. + } + } + catch (Exception ex) + { + LogError("Error while refreshing serial ports", ex); // Surface exceptions with MessageBox to aid debugging. + } + } + + /// + /// Captures combo-box selection changes so we know which serial port to open. + /// + private void cmbBxSerialPort_SelectedIndexChanged(object? sender, EventArgs e) + { + if (cmbBxSerialPort.SelectedItem is SerialPortDisplay selected) + { + _selectedDevice = selected; // Save serial port entry for connection. + _selectedDeviceDescription = selected.DisplayName; // Save descriptive text for user prompts. + AppendDebugLog($"Selected serial port set to {selected.DisplayName} (source: {selected.Source})."); // Log the selection for trace. + } + else + { + _selectedDevice = null; // Clear cached name if selection is removed. + _selectedDeviceDescription = null; // Clear description as well. + } + } + + /// + /// Launches the Python process against the selected port. Validates configured paths before + /// starting so the backend can run without blocking the UI thread. + /// + private async void btnConnect_Click(object? sender, EventArgs e) + { + LogDebugAction("Requesting Python connect."); // Debug log entry noting button press. + if (_pythonController?.IsRunning == true) + { + AppendLogBoth("Python process is already running."); + return; + } + + if (!ValidatePythonPaths()) + { + return; + } + + var selectedPort = _selectedDevice?.PortName ?? string.Empty; + if (string.IsNullOrWhiteSpace(selectedPort)) + { + AppendLog("No serial port selected. Please choose a port before connecting."); + MessageBox.Show("Please select a serial port before connecting.", "Python Process", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + + try + { + UpdatePythonPathsFromSettings(); + AppendLogBoth($"Starting m18.py using {_settings.PythonExecutablePath} on port {selectedPort}..."); + await _pythonController!.StartAsync(selectedPort); + AppendLogBoth("m18.py launched. Waiting for prompt..."); + UpdateConnectionUi(true); + } + catch (Exception ex) + { + AppendLogBoth($"Failed to start m18.py: {ex.Message}"); + MessageBox.Show($"Failed to start m18.py: {ex.Message}", "Python Process Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + UpdateConnectionUi(false); + } + } + + /// + /// Handles Disconnect button clicks by invoking and logging the + /// action for debugging. Uses async void because it is an event handler. + /// + private async void btnDisconnect_Click(object? sender, EventArgs e) + { + LogDebugAction(FormatLogMessage("btnDisconnect pressed - requesting DisconnectAsync().")); // Timestamped debug entry. + await DisconnectAsync(); // Attempt to close the python process safely. + } + + /// + /// Closes the active python process if present, optionally informing the user via MessageBox. + /// + private async Task DisconnectAsync(bool showUserMessages = true) + { + if (_pythonController == null || !_pythonController.IsRunning) + { + var message = "Disconnect requested, but the Python process is not running."; // Friendly explanation. + AppendDebugLog(FormatLogMessage(message)); // Debug log for trace. + if (showUserMessages) + { + AppendLog(message); // Display in primary log when requested by user (e.g., clicking Disconnect). + MessageBox.Show(message, "Python Process", MessageBoxButtons.OK, MessageBoxIcon.Information); // Notify via modal dialog. + } + UpdateConnectionUi(false); // Reset UI state regardless. + return; // Exit early when nothing to close. + } + + AppendLogBoth("Stopping Python process..."); // Inform user which process is closing. + + try + { + await _pythonController.StopAsync(TimeSpan.FromSeconds(5)); + AppendLogBoth("Python process stopped successfully."); // Confirm closure. + } + catch (Exception ex) + { + LogError("Error while stopping Python.", ex); // Report exceptions thrown during close. + } + finally + { + UpdateConnectionUi(false); // Re-enable Connect and refresh buttons. + } + } + + /// + /// Requests Python to set TX line to idle (low) via m.idle(). + /// + private async void btnIdle_Click(object? sender, EventArgs e) + { + AppendDebugLog(FormatLogMessage("btnIdle pressed - sending m.idle().")); // Trace button press. + await SendPythonCommandAsync("m.idle()", "idle (TX low)"); + } + + /// + /// Requests Python to set TX line high (active) via m.high(). + /// + private async void btnActive_Click(object? sender, EventArgs e) + { + AppendDebugLog(FormatLogMessage("btnActive pressed - sending m.high().")); // Trace user action. + await SendPythonCommandAsync("m.high()", "active (TX high)"); + } + + /// + /// Initiates a comprehensive battery health report by invoking m.health() inside Python. + /// + private async void btnHealthReport_Click(object? sender, EventArgs e) + { + AppendDebugLog(FormatLogMessage("btnHealthReport pressed - sending m.health().")); // Trace user action. + await SendPythonCommandAsync("m.health()", "health report"); + } + + /// + /// Issues a reset command to the battery by invoking m.reset() within Python. + /// + private async void btnReset_Click(object? sender, EventArgs e) + { + LogDebugAction("Requesting Python reset command."); // Note action for trace. + await SendPythonCommandAsync("m.reset()", "reset"); + } + + /// + /// Copies all simple log output to the clipboard, allowing users to paste logs into emails + /// or issue reports. + /// + private void btnCopyOutput_Click(object? sender, EventArgs e) + { + LogDebugAction("Copying output via btnCopyOutput_Click()."); // Record action. + if (string.IsNullOrEmpty(rtbOutput.Text)) + { + AppendLogBoth("No output to copy."); // Warn when nothing to copy. + return; // Exit early to avoid placing empty text on clipboard. + } + + Clipboard.SetText(rtbOutput.Text); // Use System.Windows.Forms.Clipboard to place text into OS clipboard. + AppendLogBoth("Output copied to clipboard."); // Confirm to user. + } + + /// + /// Sends a command into the Python REPL and handles prompt/timeout state transitions. + /// + private async Task SendPythonCommandAsync(string command, string description) + { + if (!EnsurePythonRunning()) + { + return; + } + + AppendLogBoth($"Sending {description} command to Python: {command}"); + SetPythonBusy(true); + + try + { + var success = await _pythonController!.SendCommandAsync(command, _commandTimeout); + if (!success) + { + AppendLogBoth($"Timed out waiting for Python prompt after '{command}'. The process is still running."); + SetPythonBusy(false); + } + } + catch (Exception ex) + { + SetPythonBusy(false); + LogError($"Failed to send command '{command}' to Python.", ex); + } + } + + /// + /// Ensures the Python backend is running before dispatching commands. + /// + private bool EnsurePythonRunning() + { + if (_pythonController?.IsRunning == true) + { + return true; + } + + AppendLog("Python process is not running. Please connect first."); + MessageBox.Show("Start the Python process with the Connect button before sending commands.", "Python Process", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return false; + } + + /// + /// Validate configured paths and prompt the user to locate python.exe or m18.py when missing. + /// + private bool ValidatePythonPaths() + { + if (!File.Exists(_settings.ScriptPath)) + { + var message = $"Could not find m18.py at '{_settings.ScriptPath}'. Please locate the script."; + AppendLogBoth(message); + MessageBox.Show(message, "m18.py Missing", MessageBoxButtons.OK, MessageBoxIcon.Error); + + using var dialog = new OpenFileDialog + { + Filter = "Python Script|m18.py;*.py|All Files|*.*", + Title = "Select m18.py", + FileName = "m18.py" + }; + + if (dialog.ShowDialog() != DialogResult.OK) + { + return false; + } + + _settings.ScriptPath = dialog.FileName; + _settings.Save(); + InitializePythonController(); + } + + if (PathLooksLikeFile(_settings.PythonExecutablePath) && !File.Exists(_settings.PythonExecutablePath)) + { + var message = $"Could not find python executable at '{_settings.PythonExecutablePath}'. Please locate python.exe."; + AppendLogBoth(message); + MessageBox.Show(message, "Python Missing", MessageBoxButtons.OK, MessageBoxIcon.Error); + + using var dialog = new OpenFileDialog + { + Filter = "Python|python.exe;python|All Files|*.*", + Title = "Select python executable", + FileName = "python.exe" + }; + + if (dialog.ShowDialog() != DialogResult.OK) + { + return false; + } + + _settings.PythonExecutablePath = dialog.FileName; + _settings.Save(); + InitializePythonController(); + } + + return true; + } + + private static bool PathLooksLikeFile(string path) + { + return path.Contains(Path.DirectorySeparatorChar) || path.Contains(Path.AltDirectorySeparatorChar); + } + + /// + /// Sync controller paths with the persisted settings in case the user updated them on disk. + /// + private void UpdatePythonPathsFromSettings() + { + if (_pythonController == null) + { + InitializePythonController(); + } + else + { + _pythonController.PythonExecutablePath = _settings.PythonExecutablePath; + _pythonController.ScriptPath = _settings.ScriptPath; + } + } + + /// + /// Route Python stdout/stderr into the existing logs with a timestamp and error marker. + /// + private void AppendPythonLog(string line, bool isError) + { + var tagged = isError ? $"[stderr] {line}" : line; + var formatted = FormatLogMessage(tagged); + AppendSimpleLog(formatted); + AppendDebugLog(formatted); + } + + /// + /// Update UI state to reflect Python busy/idle states and disable command buttons while a + /// command is outstanding. + /// + private void SetPythonBusy(bool busy) + { + _isPythonBusy = busy; + UpdateConnectionUi(_pythonController?.IsRunning == true); + } + + /// + /// Wrapper around SerialPortUtil to retrieve detailed device metadata, keeping the logic + /// isolated for easier unit testing and mocking. + /// + private List GetSerialPorts() + { + return SerialPortUtil.EnumerateDetailedPorts(AppendRawSerialLog); // Pass raw logger to capture detailed enumeration. + } + + /// + /// Executes a quick FT232 communication test against the selected device by toggling control + /// lines and sending a byte. Helps verify USB-UART hardware is responsive. + /// + private async void btnTestFT232_Click(object? sender, EventArgs e) + { + LogDebugAction("Requesting Test FT232 operation."); // Trace user action. + + if (cmbBxSerialPort.SelectedItem is not SerialPortDisplay selectedPort) + { + AppendLog("No serial port selected. Please choose a port before testing."); // Provide guidance. + MessageBox.Show("Please select a serial port before testing.", "Serial Port", MessageBoxButtons.OK, MessageBoxIcon.Warning); // Block until user acknowledges. + return; // Abort test. + } + + var selectedDescription = _selectedDeviceDescription ?? selectedPort.DisplayName; // Friendly name for messages. + + AppendLog($"Testing serial connectivity on {selectedDescription}..."); // Inform user test is starting. + LogDebugAction($"Testing serial connectivity on {selectedDescription}."); // Duplicate in debug log. + + var testResult = await Task.Run(() => TestSerialDevice(selectedPort)); // Run test on background thread to keep UI fluid. + + if (testResult.Success) + { + AppendLog($"Device responded successfully on {selectedPort.DisplayName}."); // Success message for user. + LogDebugAction($"Device responded successfully on {selectedPort.DisplayName}."); // Debug confirmation. + } + else + { + AppendLog($"No response / failed to communicate with device on {selectedPort.DisplayName}{(string.IsNullOrWhiteSpace(testResult.ErrorMessage) ? string.Empty : $": {testResult.ErrorMessage}")}."); // Provide failure details. + LogDebugAction($"No response / failed to communicate with device on {selectedPort.DisplayName}{(string.IsNullOrWhiteSpace(testResult.ErrorMessage) ? string.Empty : $": {testResult.ErrorMessage}")}."); // Debug echo. + } + } + + /// + /// Opens the specified device with the serial settings and performs a minimal + /// control-line toggle plus a single-byte write to check for driver/hardware responsiveness. + /// + private static (bool Success, string? ErrorMessage) TestSerialDevice(SerialPortDisplay device) + { + try + { + using var serialPort = new SerialPortConnection(device, null); // Open serial handle with default logger. + serialPort.SetDtr(true); // Assert DTR to mimic idle charger line initially. + serialPort.SetBreak(true); // Assert BREAK to drive TX low. + serialPort.SetDtr(false); // Toggle DTR to confirm control-line responsiveness. + serialPort.SetBreak(false); // Release BREAK to drive TX high. + + serialPort.WriteBytes(new byte[] { 0x00 }); // Send a single zero byte out TX to verify TX data path. + + return (true, null); // Success indicates driver and hardware are reachable. + } + catch (Exception ex) + { + return (false, ex.Message); // Return error message so caller can log it. + } + } + + /// + /// Appends a message to the primary output log after prefixing with a timestamp. + /// + private void AppendLog(string message) + { + AppendSimpleLog(FormatLogMessage(message)); // Reuse helper to add timestamp and write to RichTextBox. + } + + /// + /// Appends a message to both the simple log and debug log so the text appears in two tabs. + /// + private void AppendLogBoth(string message) + { + var formatted = FormatLogMessage(message); // Create timestamped text once. + AppendSimpleLog(formatted); // Show in user-friendly log window. + AppendDebugLog(formatted); // Also show in verbose debug tab. + } + + /// + /// Writes text into the primary rich text box, marshaling to the UI thread if necessary so + /// background tasks can safely log without cross-thread exceptions. + /// + private void AppendSimpleLog(string formattedMessage) + { + if (rtbOutput.InvokeRequired) + { + rtbOutput.Invoke(new Action(() => AppendSimpleLog(formattedMessage))); // Marshal to UI thread. + return; // Exit current thread path. + } + + var prefix = _hasAppendedLog ? Environment.NewLine : string.Empty; // Insert newline if previous messages exist. + rtbOutput.AppendText($"{prefix}{formattedMessage}"); // Append timestamped message. + rtbOutput.SelectionStart = rtbOutput.TextLength; // Move caret to end to keep view updated. + rtbOutput.ScrollToCaret(); // Auto-scroll so latest text is visible. + _hasAppendedLog = true; // Record that log has content. + } + + /// + /// Writes text into the advanced output rich text box (used for protocol-level logs), + /// marshaling to the UI thread when invoked from background tasks. + /// + private void AppendAdvancedLog(string formattedMessage) + { + if (rtbAdvOutput.InvokeRequired) + { + rtbAdvOutput.Invoke(new Action(() => AppendAdvancedLog(formattedMessage))); // Ensure UI-thread access. + return; // Prevent cross-thread access. + } + + var prefix = _hasAppendedAdvancedLog ? Environment.NewLine : string.Empty; // Add newline after first entry. + rtbAdvOutput.AppendText($"{prefix}{formattedMessage}"); // Append formatted message. + rtbAdvOutput.SelectionStart = rtbAdvOutput.TextLength; // Move caret to end. + rtbAdvOutput.ScrollToCaret(); // Auto-scroll to maintain visibility. + _hasAppendedAdvancedLog = true; // Track that text exists. + } + + /// + /// Creates a timestamped log message string using millisecond resolution to help correlate + /// serial I/O timing. + /// + private string FormatLogMessage(string message) + { + return $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} - {message}"; // Compose human-readable timestamp + message. + } + + /// + /// Writes a formatted message to all log panes (simple, advanced, debug) to keep them in sync. + /// + private void AppendProtocolLog(string message) + { + var formattedMessage = FormatLogMessage(message); // Timestamp once for consistency. + AppendSimpleLog(formattedMessage); // User-friendly log. + AppendAdvancedLog(formattedMessage); // Protocol log. + AppendDebugLog(formattedMessage); // Debug log. + } + + /// + /// Logs an error context with exception details and shows a MessageBox to alert the user. + /// + private void LogError(string context, Exception exception) + { + var fullMessage = $"{context} Error details: {exception}"; // Combine context and exception message/stack trace. + AppendLogBoth(fullMessage); // Write to logs for persistence. + MessageBox.Show(fullMessage, "Serial Port Error", MessageBoxButtons.OK, MessageBoxIcon.Error); // Display blocking error dialog. + } + + /// + /// The legacy TX/RX log toggles remain for UI continuity; Python output is always captured to + /// comply with the requirement that no lines are dropped. + /// + private void chkbxTXLog_CheckedChanged(object? sender, EventArgs e) => AppendDebugLog(FormatLogMessage("TX log checkbox toggled (Python output remains enabled).")); + + /// + /// The legacy RX log toggle is informational only for the Python bridge. + /// + private void chkboxRxLog_CheckedChanged(object? sender, EventArgs e) => AppendDebugLog(FormatLogMessage("RX log checkbox toggled (Python output remains enabled).")); + + /// + /// Convenience wrapper to send a debug message to the dedicated debug log pane. + /// + private void LogDebugAction(string message) + { + AppendDebugLog(message); // Delegates to AppendDebugLog for thread-safe logging. + } + + /// + /// Appends text to the debug rich text box with optional timestamping. Invocations from + /// background threads are marshaled to the UI thread to avoid InvalidOperationException. + /// + private void AppendDebugLog(string message) + { + if (rtbDebugOutput.InvokeRequired) + { + rtbDebugOutput.Invoke(new Action(() => AppendDebugLog(message))); // Marshal to UI thread if needed. + return; // Stop processing on worker thread. + } + + var prefix = _hasAppendedDebugLog ? Environment.NewLine : string.Empty; // Add newline after first message. + var formatted = message.Contains("- ") ? message : FormatLogMessage(message); // Preserve existing timestamps if provided. + rtbDebugOutput.AppendText($"{prefix}{formatted}"); // Write to debug output box. + rtbDebugOutput.SelectionStart = rtbDebugOutput.TextLength; // Move caret to end. + rtbDebugOutput.ScrollToCaret(); // Auto-scroll to newest entry. + _hasAppendedDebugLog = true; // Note content exists. + } + + /// + /// Writes text into the raw serial log rich text box, mirroring SerialPort actions for visibility. + /// Background threads are marshaled to the UI thread to avoid cross-thread exceptions. + /// + private void AppendRawSerialLog(string message) + { + if (rtbD2xxLog.InvokeRequired) + { + rtbD2xxLog.Invoke(new Action(() => AppendRawSerialLog(message))); // Marshal to UI thread if needed. + return; // Stop processing on worker thread. + } + + var prefix = _hasAppendedSerialLog ? Environment.NewLine : string.Empty; // Add newline after first message. + var formatted = message.Contains("- ") ? message : FormatLogMessage(message); // Preserve existing timestamps if provided. + rtbD2xxLog.AppendText($"{prefix}{formatted}"); // Write to raw serial output box. + rtbD2xxLog.SelectionStart = rtbD2xxLog.TextLength; // Move caret to end. + rtbD2xxLog.ScrollToCaret(); // Auto-scroll to newest entry. + _hasAppendedSerialLog = true; // Note content exists. + } + + /// + /// Enables or disables UI controls based on connection state so users cannot issue protocol + /// commands before opening a port. + /// + private void UpdateConnectionUi(bool connected) + { + btnConnect.Enabled = !connected; // Disable Connect when connected to prevent double opens. + btnDisconnect.Enabled = connected; // Enable Disconnect to allow clean closure. + var commandsEnabled = connected && !_isPythonBusy; + btnIdle.Enabled = commandsEnabled; // Only allow TX toggling when process is ready. + btnActive.Enabled = commandsEnabled; // Only allow TX toggling when process is ready. + btnHealthReport.Enabled = commandsEnabled; // Health report requires running process. + btnReset.Enabled = commandsEnabled; // Reset requires running process. + btnCopyOutput.Enabled = true; // Copy is always allowed because it is read-only. + btnTestFT232.Enabled = !connected; // Prevent running FT232 test while another session holds the port. + cmbBxSerialPort.Enabled = !connected; // Lock selection to avoid confusion while connected. + btnRefresh.Enabled = !connected; // Avoid refresh while port is open to prevent handle conflicts. + } + + /// + /// Attempts to disconnect gracefully when the form is closing. This prevents dangling COM + /// handles and leaves TX in idle (safe) state. + /// + private async void frmMain_FormClosing(object? sender, FormClosingEventArgs e) + { + AppendDebugLog(FormatLogMessage("Form closing requested - attempting clean disconnect.")); // Trace closure intent. + + try + { + await DisconnectAsync(false); // Do not show user messages to avoid blocking closure. + } + catch (Exception ex) + { + AppendDebugLog(FormatLogMessage($"Form closing disconnect encountered an error: {ex.GetType().Name} - {ex.Message}")); // Log but do not rethrow to avoid crash. + } + } + + /// + /// Stub for RichTextBox text change event; kept for demonstration of event wiring. + /// + private void rtbOutput_TextChanged(object sender, EventArgs e) + { + // Could auto-save logs or update counters; not needed currently. + } + + /// + /// Duplicate combo box change handler generated by designer; kept for completeness. + /// + private void cmbBxSerialPort_SelectedIndexChanged_1(object sender, EventArgs e) + { + // All selection logic handled in cmbBxSerialPort_SelectedIndexChanged; this remains empty. + } + + /// + /// Stub button handler reserved for future UI actions. + /// + private void button1_Click(object sender, EventArgs e) + { + // Intentionally left blank to illustrate event handler shape. + } + + /// + /// Sends a raw byte (0xAA) and waits for a response to validate echo/loopback behavior on + /// the open serial port. This is similar to a ping test for UART communications. + /// + private void btnTestEcho_Click(object sender, EventArgs e) + { + rtbDebugOutput.AppendText($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} - Raw echo test is not available when controlling the Python reference implementation.\n"); + } + } +} diff --git a/M18AnalyzerMain.resx b/M18AnalyzerMain.resx new file mode 100644 index 0000000..460cf1d --- /dev/null +++ b/M18AnalyzerMain.resx @@ -0,0 +1,3594 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + 9, 21 + + + Step 1: Choose the serial port for your UART device, and press connect UART. +Step 2: Once UART is connected, set Idle (Tx Low). +Step 3: Plug in battery. +Step 3: Once battery has been plugged in set Active (Tx High). +Step 4: Set Idle (Tx Low) before unplugging battery and/or disconnecting the serial port. +=========================================================== + + + + + + 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 + + + + 68 + + + + AAABAAkAEBAAAAEAIABoBAAAlgAAABgYAAABACAAiAkAAP4EAAAgIAAAAQAgAKgQAACGDgAAMDAAAAEA + IACoJQAALh8AAEBAAAABACAAKEIAANZEAABISAAAAQAgAIhUAAD+hgAAYGAAAAEAIAColAAAhtsAAICA + AAABACAAKAgBAC5wAQAAAAAAAQAgAGmUAABWeAIAKAAAABAAAAAgAAAAAQAgAAAAAAAABAAAEwsAABML + AAAAAAAAAAAAADgx4LE8NuFqPTfhWDkz4JJCPOE6ODLgqT8550o8OzUyNDM3oDo5PUFJSUwoMTA0xCko + LPgvLjLWQkFESQAAAwAnIN3/LSbenS4n3pApIt3hMy3fXigh3fgwKeVtLCskSSIhJf8rKi52Li0xkCEg + JP8gHyP/IB8j/ykoLMpHR0odJyDd/y0m3p4sJt6hKCHd6jMs32ooId31MCnlbC0sIzwhICT4KiktlCUk + KMogHyP/IB8j/yAfI/8iISX6MTA0Yicg3f8tJt6iKyXesycg3fMyK994KCHd9C8p5G0uLiEwIiEl8yko + K60jIibbIB8j/iIhJcghICTeIB8j/ykoLJknIN3/LSfeqSsk3sMnIN35MSrfiSgh3fQvKeNuMTEfJiIh + JewoJyq8IyIm4CIhJeMxMDQkJiUpWiAfI/0mJSm6JyDd/y4n3rEqI97SJh/d/TAp35soId3zLynibjMz + Gx0iISXlJyYqwyQjJ9ohICTgLi0xFiQjJzUgHyP1JSQoyScg3f8uJ967KiPe3igh3f8vKd6tKCHd9C8p + 4W84OBUVIyIm3SYmKcQnJirEIB8j+iYlKYIlJCiNIB8j/iYlKcQnIN3/LifeyCsl3uMsJt7vLifewSgh + 3fQvKeBvPD4ADCMiJtMlJCjFLy4yjyEgJP8gHyP/IB8j/yAfI/8qKi2fJyDd/i0n3tcrJd7fLife0C0n + 3tYoId32MSvadVVWPR0lJCjOIyImz0A/QkkmJSntIB8j/yAfI/8kIyb5PDs+Yycg3f4tJ97oKyTe2S4o + 3rItJt7pKCHf9zIss5krKirGIiEl+CMiJtUxMDRpIiEl+SEgJOUiISXTISAk/iwsL6QnIN39LCbe+isk + 3tAvKN6ULCXe+igi3/wvKrGYIiEh5iAfI/8jIibdKyoujiAfI/8lJCd2LCwvKiEgJOQlJCjjJyDd/Scg + 3f8qJN7DMSrfeSch3f8nIN7/MCq6jiIhIt0gHyP/IiEl5SsqLpYgHyP/JSQofjQ0NxshICTZIyIm+icg + 3f0mH93/KiTeszIr32AnIN39Jh/e/zErxoMqKSm/ISAk/yIhJewsKy+PISAk/CIhJeUlJCfDIB8j+CIh + Jf4nIN39Jh/d/ywl3qM0Ld9KJyDd+SYf3f8wKt1xWFhCICopLbghICT1MC8zeSIhJe4gHyP/IB8j/yAf + I/8kIyb1JyDd/yYf3f8sJd6SNi/fOCgh3fQnIN3/LyjfcCckdwAwLzNZIiEl+DEwNFwpKCy7IB8j/yAf + I/8gHyP/KSgsxjQt364zLN+yODLgWkE74R40Lt+iNC3fsj034U01MZUAPj1BKDQzNrk8Oz9CQEBDQS4t + MNcoJyv9LSww2kA/Qk0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAKAAAABgAAAAwAAAAAQAgAAAAAAAACQAAEwsAABMLAAAAAAAAAAAAAElD + 431IQuKAUk3kN1VQ5B9JQ+J8S0bjZWdi5wxMRuNeSELigk9K408AACoATk1QMkdGSmxJSUxiWFdaEwAA + AABTUlVIOjk9yC4tMfMxMDTuPz5BrV5eYS4dHCAAAAAAACoj3vwpIt3/NS7fbzkz4EoqI979LSbe1ExG + 4x8tJ96+KCHd/zIs358AAAQAMC8ycCQjJ/8nJinsODc7MFRTViktLC/ZIB8j/x8eIv8fHiL/ISAk/zEw + NMRcW14fT05RACgh3fwmH93/MyzfbzUv310nIN3/KiPe4UQ+4iorJN69Jh/d/zAp36AAAAkALSwwZSEg + JP8iISX1NzY6PDQ0N38hICT/IB8j/yAfI/8gHyP/IB8j/yIhJf83NjqCAAAAACgh3fwnIN3/My3fcDMt + 33AmH93/KSLd60A64TcrJN69Jh/d/zAp36AAAA8ALy4xVyEgJP0iISX5NzY6UykoLLYgHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8pKCzOVlVZGCgh3fwnIN3/NC3fcTEr34MmH93/KCHd8z024UYrJN68Jh/d/zAp + 36AAABMAMTAzSyIhJfohICT8NDM3bCUkKM8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8kIyfwPDs/QSgh + 3fwmIN3/NC7fcy8p3pYmH93/KCHd+joz4FYrJN67Jh/d/zAp36AAABQAMjE0PiIhJfUhICT+MTA0gCQj + J9ggHyP/IB8j/SMiJr8kIyekISAk7SAfI/8hICT8MjE0aSgh3fwmH93/NS7fdy4n3qkmH93/JyDd/jcx + 4GgrJN67Jh/d/zAp36AAABQANDQ3MyMiJu8gHyP/Ly4yjiQjJ9kgHyP/IyIm5DY1OSr///8BJyYqiCAf + I/8hICT/Li0wiSgh3fwmH93/NS/ffS0m3romH93/JyDd/zUv33srJd67Jh/d/zAp36AAAA8ANzY5KSMi + JukgHyP/Ly4xmCUkKNUgHyP/IyIm1Dk4PBQpKCwAJSQoTiAfI/sgHyP/Kyounigh3fwmH93/NS/fhCwl + 3skmH93/Jh/d/zMt344sJd68Jh/d/zAp36AAAAUAOTg8ICQjJ+EgHyP/Li0xnicmKskgHyP/IiEl3i8u + Mh0qKS0AJSQoRyAfI/kgHyP/KiktqCgh3fwmH93/NS/fjisk3tcmH93/Jh/d/zEr36IsJd6/Jh/d/zAp + 36AAAAAAPj1AGCQjJ9ggHyP/LCsvoSsqLrEgHyP/ISAk+CopLWk/PkIcJyYqgiAfI/8gHyP/KiotpCgh + 3fwmH93/NS/fmikj3uMsJd77KSLd/zAp3rQtJt7CJh/d/zAp36AAAAAAQ0NFESUkKM4gHyP/KSkspzMy + NochICT/IB8j/yEgJPIkIybeISAk9CAfI/8hICT/Li0xjigh3fwmH93+NS7fqCgi3e0wKt/hKiPe9C4n + 3sYtJt7IJh/d/zAp36AAAAAATExOCyYlKcMgHyP/JyYqs0RDR0olJCjzIB8j/yAfI/8gHyP/IB8j/yAf + I/8jIib5OTg7Xygh3fwmH93+NC7ftygh3fUyK9/DKyTe5S0m3tcuJ97PJh/d/zAp36AAAAAA29vZAicm + KrYgHyP/JiUpwmhnahQ3NjqqISAk/yAfI/8gHyP/IB8j/yAfI/8wLzPQYmFkHSgh3fwmH939NC3fySgh + 3fszLN+mKyTe1Swl3uUuJ97ZJh/d/zEq3qFNTE1JRERHcCopLdEfHiL/JSQozVZVWBcyMTSqISAk/yAf + I/8gHyP/IB8j/yAfI/8rKi7fT05RNCgh3fwnIN39Myzf2ycg3f40Lt+KLCXexSsk3vIuKN7kJh/d/zIr + 36EtLC+lIyIm/yEgJP8gHyP/JSQo1UJBRDglJCjfIB8j/yEgJPEkIye2IiEl0CAfI/8hICT/NDM3jCgh + 3fwnIN3+Mivf7ycg3f82L99xLSbetCoj3vwvKN7yJh/d/zEr4Z8rKi2XIB8j/yAfI/8gHyP/JCMn3Tk4 + O1EjIibsIB8j/yUkKKtWVVgIMTA0NyIhJeogHyP/Kyotxigh3fwnIN3/LSbe/Sch3f04MeBbLifeoygh + 3f8rJd79Jh/d/zEq450sKy6JIB8j/yAfI/8gHyP/IyIm5TY1OV4iISXuIB8j/yMiJpYYFxsALi0wECIh + Jc4gHyP/JyYq5igh3fwmH93/Jh/d/ygh3fk7NeBHLynekSYf3f8mH93/Jh/d/zAp45wtLC97IB8j/yAf + I/8gHyP/IyIm7DU1OGIjIibqIB8j/yUkKLlfXmELOzo+GCIhJdQgHyP/JSQo9ygh3fwmH93/Jh/d/ygh + 3fI8NuA1MSrffyYf3f8mH93/Jh/d/zAp5JsxMDJuIiEl/yAfI/8gHyP/IiEl8jY1OWEkIyfgIB8j/yEg + JPQpKCuqKCcrsSEgJPggHyP/JCMn/Sgh3fwmH93/Jh/d/yki3epAOuEmMivfbScg3f8mH93/Jh/d/y8o + 4Z1UU1MxPTw/licmKu0gHyP/IiEl+Dc2Ol0mJSnNIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JCMn+ygh + 3fwmH93/Jh/d/yoj3uBHQeIaNC3fXCcg3f4mH93/Jh/d/y8p3p8AAAAA////ADo5PXwiISX/ISAk/TU0 + N1otLDCmIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JiUp6ygh3fwmH93/Jh/d/ysk3tNMRuMQNjDgTCgh + 3fomH93/Jh/d/y8p3p////8ATEtRAEhHSigmJSnlISAk/y8uMmA7Oz5fIyIm/iAfI/8gHyP/IB8j/yAf + I/8gHyP/LSwwvyoj3vwoId3/KCHd/y0n3sRdWOYIOTPgPCoj3vMoId3/KCHd/zEr35////8AaGd2AGdm + aQkqKS29IiEk/y0tMHFycXQRMTA0uiEgJP8fHiL/Hx4i/x8eIv8nJirxQkFFXUE74X0/OeF/PznhgEQ+ + 4l2AfOsCT0njGUI84XdAOuF/QTvhgkxG41H///8AnJrCAP///wBHRkpnQUBDq0tKTVAvLjIAW1teLDw7 + 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 + rAQpKCyIIB8j/yAfI/8hICT/MTA0giki3fsmH93/KCHd+EA64W4rJN7fJh/d/ysk3v4mH93/Lifeyjkz + 4HsnIN3/Jh/d/y8o3sphW+YPWleaAFBPUxAnJirNIB8j/yAfI/8wLzOJOTg7eSEgJP8gHyP/IB8j/yMi + JuIqKS2lKCcrpyIhJeogHyP/IB8j/yIhJf01NDhxKSLd+yYf3f8oId33PjjhfCoj3ukoId3+Ni/f6iYf + 3f8sJd7XOTPghCcg3f4mH93/LyjeymFb5g9gXa4AXFteCygnK8IgHyP/IB8j/ywrL5ZKSUxHJSQo9iAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IyIm9z49QVQpIt37Jh/d/ygh3fY9N+GLKSLd8Sgh + 3fk5MuDGJiDd/isk3uM5M+CRJyDd/iYf3f8vKN7KYVvmD2VhwwB1dHYGKSgstiAfI/8gHyP/KyotpnZ2 + eBcvLjLMHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8pKCzgVFNWKSki3fsmH93/KCHd9js1 + 4JwoId33KSLd8zs14KQnIN38KiPe7Dky4J8nIN39Jh/d/y8o3spfWukOdXOmAP///wEqKS2pIB8j/yAf + I/8qKS2009PTBExLTmMpKCz2IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IyIm/z8+QpbQ0NEEKSLd+yYf + 3f8oId32OjTgricg3fwqI97sPjjhgygh3fgpIt3zODLgrycg3fwmH93/Lyjeym9rzRWNjYgTmZmbFDAv + M6QgHyP/IB8j/ykoLMBlZGcHZWRnMi8vMugfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8mJSj/TU1QfwAA + AAApIt37Jh/d/yki3fY4MuDBJh/d/yok3uNCPOFmKSLd8ygh3fk3MeDAJyDd/CYf3f8uKOHHTUtpSzc2 + OcY1NDjLKikt6iAfI/8gHyP/KCcrzGtqbQ03Nzp6IiEl/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8sKy/bXFteKSki3fsmH93/KSLd9zcx4NUmH93/LCXe2UZA4kwqI97sJyDd/TYw4NMnIN38Jh/d/y8o + 4sY/PlpSIiEl+B8eIv8gHyP/IB8j/yAfI/8nJinWWllcGi0sMKwgHyP/IB8j/yEgJPskIye6JiUpmyMi + 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 + 39BoY+cSlJHuBjMt37kmH93/Jh/d/yYf3f8tJt7nVE/kKAAA1QA1L9+WJh/d/yYf3f8mH93/KiPe+0lD + 4lI4MeAAhoWHAKampwUvLjGxIB8j/yAfI/8gHyP/IiEl/zs6PW0sKy8AWVhbRCgnK/QfHiP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8pKCz2W1pdUDU0OAAfHiMAKiPe+SYf + 3f8mH93/Jh/d/zEq39BoY+cSc27pDjIr38kmH93/Jh/d/yYf3f8sJd7wTknjNgAA1wA1L9+WJh/d/yYf + 3f8mH93/KiPe+0lD4lI4MeAAlZSWAP///wIwLzOkIB8j/yAfI/8gHyP/ISAk/zg3O3sAAAAAQkFFdyIh + Jf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8hICT/Pz5Bn/// + /wOzs7QAKiPe+SYf3f8mH93/Jh/d/zEq39BpZOgRYVzmFzAp39cmH93/Jh/d/yYf3f8qI974SkTjRwAA + 1wA1L9+WJh/d/yYf3f8mH93/KiPe+0lD4lI4MeAAtbS2AAAAAAAyMTWXIB8j/yAfI/8gHyP/ISAk/zY1 + OIkAAAAANzY5oSAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/MC8z2XZ1dxxycnQAKiPe+SYf3f8mH93/Jh/d/zEq39BrZugQVU/kIi0n3uMmH93/Jh/d/yYf + 3f8pIt39RT/iWAAA1gA1L9+WJh/d/yYf3f8mH93/KiPe+0lD4lI4MeAA/f39AAAAAAA1NDeJISAk/yAf + I/8gHyP/IB8j/zQzNpbFxMUILy4yvCAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/JyYq9VNSVkRCQUUAKiPe+SYf3f8mH93/Jh/d/zEq39BuaegQUEvkMCwl + 3u0mH93/Jh/d/yYf3f8oId3/QTvhagAA0wA1L9+WJh/d/yYf3f8mH93/KiPe+0lD4lI4MeAAAAAAAAAA + AAA3Njp7ISAk/yAfI/8gHyP/IB8j/zEwNKN9fX8SKyouzCAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IiEl/0NCRXAIBwsAKiPe+SYf3f8mH93/Jh/d/zEq + 39BybukPSUTjPysk3vUmH93/Jh/d/yYf3f8nIN3/PTfhfQAAzQA1L9+WJh/d/yYf3f8mH93/KiPe+0lD + 4lI4MeAAnZ2fABYVGQA4NzttIiEl/yAfI/8gHyP/IB8j/zAvMrBoZ2ocKSgs1SAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yEgJPQiISXuISAk9iAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/zc2OpYAAAAAKiPe+SYf + 3f8mH93/Jh/d/zEq39B3c+oOQz3iTyki3fomH93/Jh/d/yYf3f8mH93/OjTgkAAAuAA1L9+WJh/d/yYf + 3f8mH93/KiPe+0lD4lI4MeAA5ubnACQjJgA6OT1fIiEl/iAfI/8gHyP/IB8j/y0sMLxfXmEjKCcr2iAf + I/8gHyP/IB8j/yAfI/8gHyP/JSQoxi8uMV4xMDRJLi0wbSUkKNkgHyP/IB8j/yAfI/8gHyP/IB8j/zAv + M7WdnZ8IKiPe+SYf3f8mH93/Jh/d/zEq39B8eOsOQTvhYigh3f8mH93/Jh/d/yYf3f8mH93/NzHgo/// + /wE1L9+WJh/d/yYf3f8mH93/KiPe+0lD4lI4MeAA////AC4tMAA/PkFTIyIm+yAfI/8gHyP/IB8j/ysq + LsdaWl0pJyYq2iAfI/8gHyP/IB8j/yAfI/8kIyfxPTxASQAAAAAWFRkAAAAAADg3O1ciISXwIB8j/yAf + I/8gHyP/IB8j/ywrL8xtbG8UKiPe+SYf3f8mH93/Jh/d/zEq39B/e+sPPTfhdCcg3f8mH93/Jh/d/yYf + 3f8mH93/NS7fterq/AU1L9+VJh/d/yYf3f8mH93/KiPe+0lD4lI4MeAA/v7/ADY1OQBCQUVGJCMn+CAf + I/8gHyP/IB8j/yopLdFbWl0uKCcr1yAfI/8gHyP/IB8j/yAfI/8pKCvTY2JlF2FgYwAAAAAAUFBTAFhY + Ww4mJSnAIB8j/yAfI/8gHyP/IB8j/yopLdxcW14iKiPe+SYf3f8mH93/Jh/d/zEq39CAfOsQOjTgiCcg + 3f8mH93/Jh/d/yYf3f8mH93/MizfxZaT7ww1Lt+VJh/d/yYf3f8mH93/KiPe+0lD4lI4MeAA/f3/AD09 + QABFREg6JSQo8yAfI/8gHyP/IB8j/ykoLNtaWVwxKSgs0SAfI/8gHyP/IB8j/yAfI/8qKS3GaWhrDWtq + bQDd3N0AgH+CAAAAAAAnJiqXIB8j/yAfI/8gHyP/IB8j/ycmKudRUFMwKiPe+SYf3f8mH93/Jh/d/zEq + 39B+eusTODLgmyYf3f8mH93/Jh/d/yYf3f8mH93/MCrf1Hdz6hU1Lt+UJh/d/yYf3f8mH93/KiPe+0lD + 41I4MeAA/f3/AEVERwBJSEswJiUp7CAfI/8gHyP/IB8j/ycmKuRZWVw1KyouyCAfI/8gHyP/IB8j/yAf + I/8nJirGUlJVDVRTVgD///8A////AA0MEAAlJCh9IB8j/yAfI/8gHyP/IB8j/yYlKe5KSU08KiPe+SYf + 3f8mH93/Jh/d/zAq3893c+oXNC7frCYf3f8mH93/Jh/d/yYf3f8mH93/Life4GRf5x81Lt+UJh/d/yYf + 3f8mH93/KiPe+0pE41I4MeAA/f3/AEtKTgBMTE8mJyYq5SAfI/8gHyP/IB8j/yYlKetWVVg4Li0xuiAf + I/8gHyP/IB8j/yAfI/8kIyfQQD9DFEFAQwB3d3kAAAAAABgXGwAkIyd3IB8j/yAfI/8gHyP/IB8j/yUk + KPJIR0pFKiPe+SYf3f8mH93/Jh/d/zAq389xbOkcMizfvSYf3f8mH93/Jh/d/yYf3f8mH93/LSbe61pV + 5Sw1Lt+TJh/d/yYf3f8mH93/KiPe+0pE41I4MeAA/f3/AFVUVwBVVFcdKCcr3SAfI/8gHyP/IB8j/yUk + KPJRUFM8MzI2pCAfI/8gHyP/IB8j/yAfI/8jIiblOjk9KDc2OQDBwcIAAAADAAQDCAAnJiqAIB8j/yAf + I/8gHyP/IB8j/yUkKPNFREhHKiPe+SYf3f8mH93/Jh/d/zAq389qZegkMSrfzSYf3f8mH93/Jh/d/yYf + 3f8mH93/KyTe81JM5Ds1Lt+SJh/d/yYf3f8mH93/KiPe+0pE41I4MeAA/f3/AF5dYABcW14WKSgs1CAf + I/8gHyP/IB8j/yQjJ/dKSUxDOjk8hSEgJP8gHyP/IB8j/yAfI/8hICT6MzI2YAAAAAA4NzsAOjk9AM7N + zgQpKCylIB8j/yAfI/8gHyP/IB8j/yUkKPFHRkpDKiPe+SYf3f8mH93/Jh/d/zAq385hW+YuLife2iYf + 3f8mH93/Jh/d/yYf3f8mH93/KiPe+UtF40s1L9+SJh/d/yYf3f8mH93/KiPe+0pE41I4MeAA/f3/AGlo + awBnZmkPKyouySAfI/8gHyP/IB8j/yMiJvtCQUVNR0ZJYSMiJv8gHyP/IB8j/yAfI/8gHyP/JiUpyzk4 + PEZOTVAlSklNJDMzNlkkIybnIB8j/yAfI/8gHyP/IB8j/yYlKe1LS046KiPe+SYf3f8mH93/Jh/d/zAp + 381bVuU7LSbe5iYf3f8mH93/Lyne/Sgh3f8mH93/KCLd/kdB4l42L9+SJh/d/yYf3f8mH93/KiPe+0pE + 41I4MeAA/f3/AHl4ewB8fH4KLSwwvyAfI/8gHyP/IB8j/yMiJv4+PUBcWlpdNygnK/EgHyP/IB8j/yAf + I/8gHyP/IB8j/yMiJucpKCzWKCcr1iEhJOogHyP/IB8j/yAfI/8gHyP/IB8j/ykoK+NWVVgrKiPe+SYf + 3f8mH93/Jh/d/zAq38xUT+RIKyTe7yYf3f8mH93/PTbh6Soj3vsmH93/KCHd/0I84XA2MOCSJh/d/yYf + 3f8mH93/KiPe+0pE41I4MeAA/f3/AIiIigCgn6EFLi0xsiAfI/8gHyP/IB8j/yIhJf86OT1rj4+REzEw + NNMfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/y4t + MNFwb3IZKiPe+SYf3f8mH93/Jh/d/zAq38xOSONYKiPe9iYf3f8nIN3/QTrhxysk3vQmH93/JyDd/z44 + 4YM3MOCTJh/d/yYf3f8mH93/KiPe+0pE41I4MeAA/f3/AKWkpgD///8CMC8zpiAfI/8gHyP/IB8j/yEg + JP83Njp5AAAAAEFARJkhICT/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/zY1ObDBwcIHKiPe+SYf3f8mH93/Jh/d/zEq38tLReNqKSLd+yYf3f8nIN3+RD7ipiwl + 3uwmH93/Jh/d/zs14Jc4MeCVJh/d/yYf3f8mH93/KiPe+0pE41I4MeAA/f3/ANLS0wAAAAAAMjE1mCAf + I/8gHyP/IB8j/yEgJP82NTiIDQwQAF9fYUoqKS30Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IyIm/0dGSnkAAAAAKiPe+SYf3f8mH93/Jh/d/zEq38xGQOJ8KCHd/yYf + 3f8oId38SELihi0m3uMmH93/Jh/d/zgy4Kk5MuCZJh/d/yYf3f8mH93/KiPe+0pE41I4MeAA/f3/AP// + /wAAAAAANTQ3iyEgJP8gHyP/IB8j/yAfI/8zMjaWAAAAAK2srgxFREepIyIm/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/MjE14m1sbzFcXF8AKiPe+SYf3f8mH93/Jh/d/zEr + 38xCPOGPJyDd/yYf3f8pIt74TUfjai4o3tgmH93/Jh/d/zUv37o6NOCeJh/d/yYf3f8mH93/KiPe+0pE + 41JDPdIAd3Z4AHZ1eAAlJCcANjU5eyEgJP8gHyP/IB8j/yAfI/8yMTSj////AmhnagCLio0zQD9D3yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8pKCv/ZGNmjf///wLd3d4AKiPe+SYf + 3f8mH93/Jh/d/zIr385AOeGjJh/d/yYf3f8rJN7zU03kUDAq38wmH93/Jh/d/zMt38o7NeCmJh/d/yYf + 3f8mH93/KiPe+0lD41L//28EpaSmE6WkphPKyssQQ0JFeyIhJf8gHyP/IB8j/yAfI/8wLzKwsrKzBUdG + SQBlZWhIMjE17SAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8jIib/RkVIvI6O + kBl7e30AKiPe+SYf3f8mH93/Jh7d/zMs39E8NeC1Jh/d/yYf3f8sJd7rWVTlOjMs374mH93/Jh/d/zEq + 39c7NeCvJh/d/yYf3f8mH93/KiPe+0pE6U9YWFFKRURHvkNDRr5EQ0e8ODc62CEgJP8gHyP/IB8j/yAf + I/8uLTG8hIOGCf///wI8Oz6hIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/JiUp/lJSVW4AAAAAKiPe+SYf3f8mH93/JR7d/zQt39Y5M+DHJR7d/yYf3f8uJ97iY17nJzUu + 368mH93/Jh/d/y8o3uM8NuC7Jh/d/yYf3f8mH93/KiPe+0xG7U49PTheIyIm/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8sKy/IcG9yDW5ucBcuLTDUHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP9ISAk/CAf + I/0gHyP/IB8j/yAfI/8gHyP/IB8j/zc2Or6ZmZsQKiPe+SYf3f8mH93/JR7d/zUu3903MeDYJR7d/yYf + 3f8wKd/Wc2/pGTcx4J8mH93/Jh/d/y0m3u08NuDIJh/d/yYf3f8mH93/KiPe+0tF7E4/PzlPIyIm/CAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8qKi3SZWRnElRTVi8oJyvsIB8j/yAfI/8gHyP/IB8j/yMi + JuIpKCyHLSwwdCgnK4QjIibfIB8j/yAfI/8gHyP/Hx4i/yoqLepgX2I5KiPe+SYf3f8mH93/JR7d/zUv + 3+U0Lt/lJR7d/yYf3f8yK9/JkY7uDToz4I0nIN3/Jh/d/ywl3vU8NeDYJh/d/yYf3f8mH93/KiPe+0tE + 605CQTpDJCMn+CAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8pKCzcX19hGUVER0AlJCj2IB8j/yAf + I/8gHyP/ISAk/zQzNoLk5OUDAAAAAP///wI1NDhqIiEl+iAfI/8gHyP/IB8j/yQjJ/tIR0tqKiPe+SYf + 3f8mH93/JR7d/zYw4PAzLN/yJR7d/yYf3f8zLN+5+vn+BDw24XsnIN3/Jh/d/yok3vo7NeDpJh/d/yYf + 3f8mH93/KiPe+0pE6k5GRjw3JSQo8yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8oJyvkVlVYIEBA + Q0wkIyf6IB8j/yAfI/8gHyP/IiEl9zc2OkgmJSkAXl1gAEVERwBSUlUjJiUp3yAfI/8gHyP/IB8j/yEg + JP89PD+XKiPe+SYf3f8mH93/JR7d/zUv3/swKd/8JR7d/yYf3f81L9+oAACjAD854WkoId3/Jh/d/yki + 3f45M+D5Jh/d/yYf3f8mH93/KiPe+0lD6E9MSz4sJiUp7SAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8mJSnrTk5RKkA/QlAjIib8IB8j/yAfI/8gHyP/ISAk8ygnKzslJCgASEdLAE5NUABMS04MJCMnwCAf + I/8gHyP/IB8j/yAfI/80Mze7KiPe+SYf3f8mH93/Jh/d/y0m3v8qI97/Jh/d/yYf3f85M+CYAADSAEM9 + 4lcpIt38Jh/d/ycg3f8uJ97/Jh/d/yYf3f8mH93/KiPe+0hB509RUT8iJyYq5iAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8lJCjySklNNT8+QU0jIib7IB8j/yAfI/8gHyP/ISAk9ywrL0YlJCgA6OjoAD49 + QQBCQUQFIyImryAfI/8gHyP/IB8j/yAfI/8vLjLVKiPe+SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ycg + 3f89N+GGEgvaAEdB4kYqI973Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KiPe+0dB5k9ZWUAZKCcr3iAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8kIyf3RURHQD8+QkUkIyb5IB8j/yAfI/8gHyP/ISAk/jU0 + OGUNDBAA////AISEhgBZWFsFJCMnsSAfI/8gHyP/IB8j/yAfI/8tLC/oKiPe+SYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ych3f8/OeFzKSLdAE1H4zcrJN7xJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KiPe+0dB + 5VBlZkASKiks1SAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8jIib7QUBETUZFSDolJCj0IB8j/yAf + I/8gHyP/IB8j/y8uMqWenZ8JCQgMAAoIDQBYWFsbJyYp0SAfI/8gHyP/IB8j/yAfI/8qKS30KiPe+SYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f5BO+FgODHgAFNO5CotJt7oJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/KiPe+0dB5FB7fUALKyouyiAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8jIib+PTxAW05N + USwmJSntIB8j/yAfI/8gHyP/IB8j/yMiJu40MzaDR0ZKS0VESFMvLjKSISAk+CAfI/8gHyP/IB8j/yAf + I/8oJyv6KiPe+SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yki3fpDPeJPQTvhAFxW5R4vKN7eJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/KiPe+0dB41CqrjMGLCsuwB8eIv8fHiL/IB8j/yAfI/8gHyP/IB8j/yAf + I/8iISX/Ojk9aWFgYx0pKCzhIB8j/yAfI/8gHyP/IB8j/yAfI/8hICT6JSQo7SQjJ/IhICT8IB8j/yAf + I/8gHyP/IB8j/yAfI/8oJyv9KiPe+SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yoj3vRIQuI/SkTjAGVg + 5xQwKd/RJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KiPe+0dB41H//wABS0pNmTs6PuAsKy/0ISAk/yAf + I/8gHyP/IB8j/yAfI/8hICT/ODc7eIyLjQ4tLDDNIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8oJyv7KiPe+SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ywl + 3u1QS+QxVE7kAHdz6gwyK9/DJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KiPe+0dC4lElHuEAoKChGY+O + kChpaWtfOTg71iEgI/8gHyP/IB8j/yAfI/8hICT/NjU4h////wM0MzavIB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8qKS30KiPe+SYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/y4n3uRZVOUlX1nmAKCd8AY0Ld+zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KiPe+0hC + 4lE4Md8AhYSGAHt6fQAAAAAAa2ptTy0sMO0fHiL/IB8j/yAfI/8gHyP/NDM3lQAAAAA/PkKDIiEl/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8uLTHjKiPe+SYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/zAp39ljXucZaWToAP///wE3MOCiJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/KiPe+0hC4lE3MOAA6+vsANLS0wC9vL4A////BUJBRJ8hICT/IB8j/yAfI/8gHyP/MTE0ogAA + AABUU1ZPJyYq+SAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8zMjbFKiPe+SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/zEq38psZ+gQcW3pAAAAvwA6M+CRJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/KiPe+0hC4lE3MOAA/f3/AMTExQB2dngAPDs+AFdWWU0nJir2IB8j/yAf + I/8gHyP/Ly4yr+Df4AN7enwcMjE11R8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yIhJP8/PkGVKiPe+SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/zIs37uDf+wJf3vrAAAA + 1gA9N+F+JyDd/yYf3f8mH93/Jh/d/yYf3f8mH93/KiPe+0hC4lE3MOAA/f3/AAAAAAD///8Ac3N1AHZ1 + eBkvLjLVHx4i/yAfI/8gHyP/Li0xvIWEhgkAAAAASUhLiSMiJv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/ygnKvRVVFdTKiPe+SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/zQu + 36vOzfcDkI3uAB0V3AA/OeFrKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/KiPe+0hC4lE3MOAA/f3/AAAA + AADk4+QAqaiqAP///wQ4NzqnIB8j/yAfI/8gHyP/LCsvx29ucQ5kY2YAdXR3LDU0ONkgHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/zo5PcGOjZAWKiPe/SYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/zgy4JwAAAAAqqjyAC4n3gBCPOFaKSLd/yYf3f8mH93/Jh/d/yYf3f8mH93/KiPe/0hC + 4lI3MeAA/f3/AAAAAAAAAAAA////AAAAAAA/PkJ4ISAk/x8eIv8fHiL/Kikt1GJhZBRycXQAAAAAAGFg + Y2EwLzPwIB8j/x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8fHiL/MC8z8GVkZ1YAAAAAQTvhvj03 + 4cM9N+HCPTfhwj034cI9N+HCPjfhxU1H42kAANMAwb/1AEtF4wBWUOU5QDrhvj034cM+N+HDPjfhwz43 + 4cM+OOHERD7iw11X5j5PSeQA/f3/AAAAAAAAAAAA3t7fAEJBRABUU1ZJODc75TU0OOo1NDfsPj1AyGpp + bBhqamwApqWnAOPj5AZkY2ZlOjk91ycnKvwhICT/Hx4i/x8eIv8fHiL/IB8j/yUkKP43NjnhYWBjbuLi + 4garq6wAko7uGI+M7hiQjO4YkIzuGJCM7hiQjO4YkIzuGZiU7wx9eOsA////AJuY8ACgnPAGk4/uGJGN + 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 + 3f8mH93/Jh/d/z034a/m5fsFp6TxAAAAAABwb3IAcG9xEy0sMNAgHyP/IB8j/yAfI/8gHyP/Hx4i/y0s + MNpra20bUVFUAF1dYEspKCv3Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Pz5CvbKysw6dnZ8AaGdqACwl3vcmH93/Jh/d/yYf + 3f8mH93/JyDd/0I84YUAAM8AAADDAEI84YonIN3/Jh/d/yYf3f8mH93/Jh/d/ysk3vlSTeROR0HiAIaC + 7Ao0Ld+/Jh/d/yYf3f8mH93/Jh/d/yYf3f89N+Gv5uX7Baek8QAAAAAAf36BAIGBgw4wLzLFIB8j/yAf + I/8gHyP/IB8j/x8eIv8rKi7iYWBjIxwbHwBKSk11IyIm/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/y4uMe10c3Y5YmFkAM/P + 0AAsJd73Jh/d/yYf3f8mH93/Jh/d/ycg3f9CPOGFAADQAP///wE9N+GcJh/d/yYf3f8mH93/Jh/d/yYf + 3f8qI97+TUfjYDcw4ACGguwKNC3fvyYf3f8mH93/Jh/d/yYf3f8mH93/PTfhr+bl+wWnpPEAAAAAAI+O + kACdnZ8JMjE1uiAfI/8gHyP/IB8j/yAfI/8fHiL/KSgs6ltbXi0AAAAAPz5CmCEgJP8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8lJCj/VFNWbgAAAAD///8ALCXe9yYf3f8mH93/Jh/d/yYf3f8nIN3/QjzhhQAA0gDV1PgFOjPgrSYf + 3f8mH93/Jh/d/yYf3f8mH93/KCHd/0dB4nIdFtwAhoLsCjQt378mH93/Jh/d/yYf3f8mH93/Jh/d/z03 + 4a/m5fsFp6TxAAAAAACamZsA1dTVBTQzN64gHyP/IB8j/yAfI/8gHyP/IB8j/ygnK/BVVVg3////AjY1 + ObEgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/ISAk/0JBRKP///8DvLy9ACwl3vcmH93/Jh/d/yYf3f8mH93/JyDd/0I8 + 4YUAANUAmJXvCzgx4L8mH93/Jh/d/yYf3f8mH93/Jh/d/ycg3f9DPeKFAADSAIaC7Ao0Ld+/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f89N+Gv5uX7Baek8QAAAAAApaSmAP///wI3NjqhIB8j/yAfI/8gHyP/IB8j/yAf + I/8mJSn1T05RQqyrrQkxMDTDIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv81NTjMkpKUE42NjwAsJd73Jh/d/yYf + 3f8mH93/Jh/d/ycg3f9CPOGFAgDXAH156xM1Lt/OJR7d/yYf3f8mH93/Jh/d/yYf3f8nIN3/QDnhmAAA + eQCFgewKNC3fvyYf3f8mH93/Jh/d/yYf3f8mH93/PTfhr+bl+wWnpPEAAAAAAK+vsAAAAAAAODg7kyEg + JP8gHyP/IB8j/yAfI/8gHyP/JSQo+kxLTk6DgoUOLi0xziAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/LSwv5mpp + bCllZGcALCXe9yYf3f8mH93/Jh/d/yYf3f8nIN3/QjzhhQsD2QBqZegcMSvf2yUe3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/zs14Kr///8DhYHsCjQt378mH93/Jh/d/yYf3f8mH93/Jh/d/z034a/m5fsFp6TxAAAA + AADHxscAAAAAADo5PYQhICT/IB8j/yAfI/8gHyP/IB8j/yQjJ/1IR0tbdXR2EywrL9UfHiP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMiJeglJCjKJiUpyCMiJtghICT7IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/ycmKvZVVFdFRENHACwl3vcmH93/Jh/d/yYf3f8mH93/JyDd/0I84YURCdoAX1rmKC8o + 3uYlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f84MuC7pKHxCYWB7Ao0Ld+/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f89N+Gv5uX7Baek8QAAAAAA////AAAAAAA9PUB3IiEl/yAfI/8gHyP/IB8j/yAfI/8jIib/Q0NGZ3Bv + cRUrKi7YHx4j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yUkKM01NDdcODc7Ljs6PSw2NjlALi0xnSIh + JfggHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8kIyf+SklMYh8eIgAsJd73Jh/d/yYf3f8mH93/Jh/d/ycg + 3f9CPOGFFQ3aAFpV5TcuJ97wJh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/Ni/fy4N/7BCGguwJNC3fvyYf + 3f8mH93/Jh/d/yYf3f8mH93/PTfhr+bl+wWnpPEAAAAAAAAAAAAXFhoAQkFEaiMiJv8gHyP/IB8j/yAf + I/8gHyP/IiEl/z8+QnVvbnEWKikt2SAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMiJvc8Oz9j////ABIR + FQAXFhoAAAAAAGBgYx4sKy+xIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IiEl/0JBRH0AAAAALCXe9yYf + 3f8mH93/Jh/d/yYf3f8nIN3/QjzhhRIK2gBTTuRHLCXe9yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zMs + 39lwbOkaiobtCTQt378mH93/Jh/d/yYf3f8mH93/Jh/d/z034a/m5fsFp6TxAAAAAABkY2YAKCcrAEZF + SV0kIyf9IB8j/yAfI/8gHyP/IB8j/yEgJP89PD+DeHh6FiwrLtgfHiL/IB8j/yAfI/8gHyP/IB8j/x8e + I/8qKS3ba2ttI1hXWgD///8AAAAAAIWFhwAAAAAAOzo9TyIhJfIgHyP/IB8j/yAfI/8gHyP/IB8j/yEg + JP88Oz+WAAAAACwl3vcmH93/Jh/d/yYf3f8mH93/JyDd/0I84YUKAtkAS0bjVyoj3vwmH93/Jh/d/yYf + 3f8mH93/Jh/d/yUe3f8wKd/kY17nJZGN7gg0Ld+/Jh/d/yYf3f8mH93/Jh/d/yYf3f89N+Gv5uX7Baek + 8QAAAAAAvr6/ADU0OABJSExQJSQo+iAfI/8gHyP/IB8j/yAfI/8hICT/Ojo9kYB/ghUsKy/TIB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/LSwwwoOChQ2Af4EAysnKAPj5+QBmZmgARURHAElITB0lJCjXIB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/ODc7qf///wQsJd73Jh/d/yYf3f8mH93/Jh/d/ycg3f9CPOGFAADWAEhD + 4mopIt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life7lxX5TObmO8HNC3fvyYf3f8mH93/Jh/d/yYf + 3f8mH93/PTfhr+bl+wWnpPEAAAAAAOrp6gA/PkIATUxPQyYlKfYgHyP/IB8j/yAfI/8gHyP/IB8j/zc2 + Op6Pj5ETLi0xzSAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/zAvM7qWlZcJi4qMAP///wAAAAAA5+bnAFhY + WwBbW14KJiUpuiAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/zQzNrimpqgKLCXe9yYf3f8mH93/Jh/d/yYf + 3f8nIN3/QjzhhQAA0QBFP+J+KCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ywl3vZVUORDqqfyBjQt + 378mH93/Jh/d/yYf3f8mH93/Jh/d/z034a/n5vsFqKXxAAAAAAD///8ASUhLAFFRVDgnJirxIB8j/yAf + I/8gHyP/IB8j/yAfI/81NDisoJ+hEjEwNMQgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8rKi66d3Z5CXBw + cgD///8AAAAAAObm5wBeXWAAiIiKAiUkKKMgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8xMDTFh4aIECwl + 3vcmH93/Jh/d/yYf3f8mH93/JyDd/0I84YUAAMMAQDrhkCcg3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8qJN77T0njU7q49AY0Ld+/Jh/d/yYf3f8mH93/Jh/d/yYf3f89N+Gv5+b7Bamm8QAAAAAA////AFBP + UwBVVFctKCcr6iAfI/8gHyP/IB8j/yAfI/8gHyP/MzI2uampqhA0Mza2IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/JiUpwVNSVgxTUlUA1tbWAAAAAAD///8AR0dKAP///wAkIyeaIB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/Ly4yzXt6fBUsJd73Jh/d/yYf3f8mH93/Jh/d/ycg3f9CPOGFAABEADs14KImH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/KSLd/0lE42XIxvYGNC3fvyYf3f8mH93/Jh/d/yYf3f8mH93/PTfhr+fm + +wWppvEAAAAAAP///wBaWVwAXFteJCopLeMfHiL/IB8j/yAfI/8gHyP/IB8j/zEwM8Wop6kQOTg8pCAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yUkKNNKSUwYSEhLAP///wD///8A/v7+AFRTVgD///8AJSQomiAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/y4tMdJzcnQZLCXe9yYf3f8mH93/Jh/d/yYf3f8nIN3/Qjzhhf// + /wQ5M+C0Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9GQOJ4y8r3BzQt378mH93/Jh/d/yYf + 3f8mH93/Jh/d/z034a/n5vsFqabxAAAAAAD///8AZmVoAGZlaBwsKy/bHx4i/yAfI/8gHyP/IB8j/x8e + Iv8vLjLPlZWXEj8/QoshICT/IB8j/yAfI/8gHyP/IB8j/yAfI/8jIibpQD9CMTY1OABnZmkA1dXWANTU + 1QB4eHoAmZmbAycmKqYgHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8uLTHScG9yGSwl3vcmH93/Jh/d/yYf + 3f8mH93/JyDd/0I84YS7ufQLNzDgxSYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8nIN3/Qjzhi8LA + 9Qk0Ld+/Jh/d/yYf3f8mH93/Jh/d/yYf3f89N+Gv5+b7Bamm8QAAAAAAMzMzAG9vcQBvbnEULSww0R8e + Iv8gHyP/IB8j/yAfI/8fHiL/LSww2nx8fhdIR0psIyIm/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk+jY1 + OGcAAAAAiYiKAOrq6gDn5+gAUlFUAGZlaBEnJirEIB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Ly4y0HZ1 + eBcsJd73Jh/d/yYf3f8mH93/Jh/d/ycg3f9CPOGEi4ftEzMt39MlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/z034Z6wrvMLNC3fvyYf3f8mH93/Jh/d/yYf3f8mH93/PTfhr+fm+wWppvEAAAAAAAAA + AAB8e30AfX1/Di8uMsYgHyP/IB8j/yAfI/8gHyP/Hx4i/ysqLuJmZWgfWFdaSycmKvggHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8pKCzBUlFUKgAAAAAAAAAAAAAAAAAAAAA/PkJUIyIm7CAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/zAvM8l/foESLCXe9yYf3f8mH93/Jh/d/yYf3f8nIN3/Qjvhg3Rw6R4xKt/fJR7d/yYf + 3f8mH93/JyDd/ycg3f8mH93/Jh/d/yYf3f86NOCwnpvwEDQt374mH93/Jh/d/yYf3f8mH93/Jh/d/z03 + 4a/n5vsFqabxAAAAAAAAAAAAi4qNAJiXmQkxMTS7IB8j/yAfI/8gHyP/IB8j/x8eIv8pKCzpW1pdKnJx + dCouLTHoHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk+iopLbMyMTVoQkFEYj8/QmEtLDBsJyYqzCAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8zMja9mpqcDCwl3vcmH93/Jh/d/yYf3f8mH93/JyDd/0I8 + 4YJpZOgsLyje6iUe3f8mH93/JR7d/zMs3/0tJt7+Jh/d/yYf3f8mH93/NzHgwY6K7RY0Ld++Jh/d/yYf + 3f8mH93/Jh/d/yYf3f89N+Gv5+b7Bamm8QAAAAAAAAAAAJmZmwDNzc4FNDM3ryAfI/8gHyP/IB8j/yAf + I/8gHyP/KCcr8FVVWDavrrAONzY6xx8eI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP+IiEl8CYl + Ke4lJCjuISAk8SAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ODc7q/T09AUsJd73Jh/d/yYf + 3f8mH93/Jh/d/ycg3f9CPOGCXlnmOi0m3vMmH93/Jh/d/yUe3f8+OOHsMyzf9SUe3f8mH93/JR7d/zQu + 389/e+seMy3fvSYf3f8mH93/Jh/d/yYf3f8mH93/PTfhr+fm+wWppvEAAAAAAAAAAACgoKIA////AjY1 + OKEgHyP/IB8j/yAfI/8gHyP/IB8j/yYmKfVQUFNCAAAAAEhHSpciISX/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk/0JB + RZEAAAAALCXe9yYf3f8mH93/Jh/d/yYf3f8nIN3/QjzhgVNO5EkrJN75Jh/d/yYf3f8lHt3/QTvh0TUu + 3+UlHt3/Jh/d/yUe3f8xK9/ccm3pKDMt370mH93/Jh/d/yYf3f8mH93/Jh/d/z034a/n5vsFqabxAAAA + AAAAAAAAq6utAAAAAAA4NzuUISAk/yAfI/8gHyP/IB8j/yAfI/8lJCj5S0pOTjIxNQBhYWRbKCcr+h8e + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yQjJ/9OTlFsCAcLACwl3vcmH93/Jh/d/yYf3f8mH93/JyDd/0M94oFOSONbKSLe/SYf + 3f8mH93/Jh/d/0Q+4rY2MODVJR7d/yYf3f8lHt3/Lyne52lk5zUzLd+8Jh/d/yYf3f8mH93/Jh/d/yYf + 3f89N+Gv5+b7Bamm8QAAAAAAAAAAAMbGxwAAAAAAPDs+hyEgJP8gHyP/IB8j/yAfI/8gHyP/JCMn/UdG + SVpHRkkAioqMIjg3OtkfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8rKi7zZWRnQlJRVAAsJd73Jh/d/yYf3f8mH93/Jh/d/ycg + 3f9EPuKBSkXjbygh3f8mH93/Jh/d/ycg3f9IQuKcODHgxCYf3f8mH93/Jh/d/y0m3vBhXOZDMy3fuyYf + 3f8mH93/Jh/d/yYf3f8mH93/PTfhr+fm+wWppvEAAAAAAAAAAAD///8AAAAAAD8+QXkiISX/IB8j/yAf + I/8gHyP/IB8j/yMiJv9EQ0doJyYqAP///wNUU1eQJCMn/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/OTg80JKSlBmJiIoALCXe9yYf + 3f8mH93/Jh/d/yYf3f8nIN3/RT/ig0U/4oEnIN3/Jh/d/yYf3f8oId3/S0Xjgzo04LMmH93/Jh/d/yYf + 3f8rJN73WVTlUzQt37smH93/Jh/d/yYf3f8mH93/Jh/d/z034a/n5vsFqabxAAAAAAAAAAAA////ABQT + FwBCQURsIyIl/yAfI/8gHyP/IB8j/yAfI/8iISX/QD9DdgAAAgBiYmQAhISGMzs6Pd4fHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/JiUp/1dX + WoX///8B2NjZACwl3vcmH93/Jh/d/yYf3f8mH93/JyDd/0ZA4oVAOuGUJyDd/yYf3f8mH93/KSLd/09J + 42w8NuGhJh/d/yYf3f8mH93/KiPe/FNN5GU0Ld+7Jh/d/yYf3f8mH93/Jh/d/yYf3f89N+Gv5+b7Baqo + 9AAAAAAAAAAAAAAABAAnJioARUVIXiMiJv4gHyP/IB8j/yAfI/8gHyP/ISAk/z09QIQAAAAA1tbXAP// + /wJvbnFsOTg77yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/JCMn/0tLTsyTkpQpdHR2AJeXmQAsJd73Jh/d/yYf3f8mH93/Jh/d/ycg3f9HQeKJPTfhpyYf + 3f8mH93/Jh/d/yoj3vxUTuRXPznhkCcg3f8mH93/Jh/d/ygh3f9OSON3NS7fuyYf3f8mH93/Jh/d/yYf + 3f8mH93/PTfhr+bl+gV8epAAYF9iAF9eYQBfXmEAQUFEAEhHSk8kIyf6IB8j/yAfI/8gHyP/IB8j/yEg + JP87Oj6SAAAAAOHh4gCVlZcAvr6/H1hXWs0iISX/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/ywrLv90c3ae////CcHBwgDDw8QALCXe9yYf3f8mH93/Jh/d/yYf + 3f8nIN3/SEPijjo04LgmH93/Jh/d/yYf3f8sJd73WFPlREQ+4n8nIN3/Jh/d/yYf3f8nIN3/SUTjijUv + 37wmH93/Jh/d/yYf3f8mH93/Jh/d/z034a/q6f8FsK+uCqyrrRSsq60UrKutFMbGxxBdXF9UJiUp9yAf + I/8gHyP/IB8j/yAfI/8gHyP/ODc7n////wHCwcMAAAAAAGVkZ2ktLDD3IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/NzY663d2eVMAAAAA////ACwl + 3vcmH93/Jh/d/yYf3f8mH93/JyDd/0lD4pU2MODHJh/d/yYf3f8mH93/LSfe8F5Z5jRHQeJtKCHd/yYf + 3f8mH93/JyDd/0U/4p02MOC+Jh/d/yYf3f8mH93/Jh/d/yYf3f89N+Gv////A2VkZ1tVVFeuVFNXrFRT + V6xVVFerS0tOwSUkKPwgHyP/IB8j/yAfI/8gHyP/IB8j/zU0OKzq6usEk5KUAKCfoQ89PEC/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEg + JP9GRUm9r66wEpqanAAsJd73Jh/d/yYf3f8mH93/Jh/d/ycg3f9JQ+OfMy3f1SUe3f8mH93/JR7d/y8p + 3udmYecmTEbjXCoj3v4mH93/Jh/d/yYf3f9BO+GvNzHgwSYf3f8mH93/Jh/d/yYf3f8mH93/PTfhr/// + /wI+PUGEJCMn/yIhJf8iISX/IiIl/yIhJf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/80Mza5qaiqCGNj + ZQBnZmk0LCsv6x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/LCsv9GppbEtCQUQALCXe9yYf3f8mH93/Jh/d/yYf3f8nIN3/SkXjqzIr + 3+IlHt3/Jh/d/yUe3f8xK9/dcGzpGlFL5EsrJN75Jh/d/yYf3f8mH93/PTfhwTky4MYlHt3/Jh/d/yYf + 3f8mH93/Jh/d/z034a////8BQUBDdSIhJf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/MTA0xImIig04NzsAUlFUXiUkKP0gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP+ISAk8CMi + Ju4iISXuIB8j+CAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yIhJf9MTE+S////ASwl3vcmH93/Jh/d/yYf + 3f8mH93/JyDd/0pE47gvKd7rJR7d/yYf3f8lHt3/NC7f0YSA7BFWUOU8LSbe8yYf3f8mH93/JR7d/zo0 + 4NE6NODNJR7d/yYf3f8mH93/Jh/d/yYf3f89N+Gv////AUNCRWYjIib/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/y8uMs93d3kTAAADAERDR38iISX/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP8KCcrsDAvM1o4NztSMTAzUiopLYMjIibrIB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/OTg8x5yb + nRQsJd73Jh/d/yYf3f8mH93/Jh/d/ycg3f9IQuLGLSbe8iYf3f8mH93/Jh/d/zcw4MOin/AKXFfmLi4o + 3usmHt3/Jh/d/yUe3f83MeDfOzXg1iUe3f8mH93/Jh/d/yYf3f8mH93/PTfhr////wFFRUhZJCMn/CAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8tLDDZbm1wGgAAAAA7Oj2WISAk/yAf + I/8gHyP/IB8j/yAfI/8gHyP/KCcr305OUTQAAAAAAAAAAAAAAABsbG4NMzI2jyEgJP4gHyP/IB8j/yAf + I/8gHyP/Hx4i/y0sMOdtbW81LCXe9yYf3f8mH93/Jh/d/yYf3f8nIN3+R0Hi2Csl3vgmH93/Jh/d/yYf + 3f85MuCy8O/9BGVg5yIxKt/hJR7d/yYf3f8lHt3/NS7f6zw24OElHt3/Jh/d/yYf3f8mH93/Jh/d/z03 + 4a////8BSklMTSUkKPkgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Kyou4WNi + ZSIAAAAANjU5pCAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/zAvM7G4t7kJcG9yAFxbXgBMS08ALSwwAFNT + Vj0mJSnsIB8j/yAfI/8gHyP/IB8j/yAfI/8nJir4V1ZZXCwl3vcmH93/Jh/d/yYf3f8mH93/JyDd/kZA + 4usqI978Jh/d/yYf3f8mH93/OzTgoAAAAABxbOkYMyzf1SUe3f8mH93/JR7d/zIs3/Y9NuHuJR7d/yYf + 3f8mH93/Jh/d/yYf3f89N+Gv////AU5NUEAmJSn1IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/ykoLOlaWVwr////AjY1OK4gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8oJyuSAAAAAI2M + jgBXV1oAcXBzAGNiZQBpaGsWKCcrzCAfI/8gHyP/IB8j/yAfI/8gHyP/IyIm/0pJTIQsJd73Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9BO+H5KSLd/iYf3f8mH93/JyDd/z854Y8AAMsAg3/sDzUv38gmH93/Jh/d/yUe + 3f8wKd/9OzTg+yUe3f8mH93/Jh/d/yYf3f8mH93/PTfhr////wJTU1U1KCcq7yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8oJyvvVFNWNf///wI0NDexIB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/JSQojQAAAABaWVwA////AP///wBfXmEAaWhrBiYlKa8gHyP/IB8j/yAfI/8gHyP/IB8j/yEg + JP8/PkKlLCXe9yYf3f8mH93/Jh/d/yYf3f8nIN3/NC3f/ycg3f8mH93/Jh/d/ygh3f9EPuJ+AADXAKSh + 8Qg4MeC4Jh/d/yYf3f8mH93/KiPe/zEq3/8mH93/Jh/d/yYf3f8mH93/Jh/d/zw24K7///8CWFdaKyko + LOgfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JiYp9VBQU0H///8BNDQ3ryAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/ycmKpr///8BaWhrAP7+/gD///8AV1ZZANLS0wElJCidIB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/ODc7wCwl3vcmH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f8mH93/Jh/d/yYf + 3f8pIt3/SkTjbCEZ3AD///8DOzTgpyYf3f8mH93/Jh/d/yYf3f8nIN3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f88NuCu////Al5dYCEqKS3hHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yUk + KPlMS05NAAAAADQzNqcgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8pKCyyhISGCHl5ewD///8A////AEZF + SQAAAAAAIyImlyAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/zQzN9YsJd73Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/KiPe/U9J41s1Lt8AAAAfAD444ZYnIN3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/PDbgrv///wNnZ2kZLCsv2B8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8kIyf9R0dKWgAAAAA2NjmeIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Kikt1W1s + bx5iYmUA////AP///wClpacAtLS2BCkoLKggHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8xMDPmLCXe9yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ysl3vhTTuRKQz3iAAAAzQBCPOGFJyDd/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/zw24K7///8Dc3JzEi4tMc4gHiP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IyIm/0VER2gAAAAAOjk8kSEgJP8gHyP/IB8j/yAf + I/8gHyP/IB8j/yQjJ/REREdaAAAAAAgHDAAODREAAAADAGRjZiApKCzSIB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/Li0x8Swl3vcmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8tJt7xVlHlOU5I + 4wALA9kARkHicygh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f88NuCu+/r/BIWF + hQ0wLzPEIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yIhJf9BQEN1AAAAAD49 + QX8iIST/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Kiktx0RDRlNYV1ouXFteLlBPUz0yMTWGIiEl9yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/ysrLvgsJd73Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mHt3/Lyje6F1Y5itZU+UAKiPeAEtG42EpIt7+Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/PDbgrvDv/wSjoqEIMjE1uCAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8hICT/PT1AgwAAAABFREdqIyIm/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/4mJSnlLSwwxy8u + McgrKi7bIiEl8iAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eI/8rKi78LCXe9yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/JR7d/zAq391kX+cfYl3mADs14ABQSuRPKyTe+iYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/zw24K7q6f8E6+vlBDMzNqwfHiL/Hx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/ISAk/zs7PpEAAAAAT05RUyUkKPogHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/yAfI/8gHyP/Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Kyou/Cwl + 3vcmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f8zLN/Sc27pFXNv6QBJQ+IAVE/kPywl + 3vQmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f88NuCu5+b9BP///wBcW16FS0pN2D8+ + QeErKi75IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/85ODueAAAAAFtbXjgpKCzwHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/ysqLvgsJd73Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/NjDgxYyI + 7Q2JhewAVU/kAFtV5TAuJ97sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/PDbgruXk + +wSPjcAAsK+xGKSkpSiSkZM2a2ptgTg4O+YgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/NjU4q/// + /wJzcnUfLy4y3R8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8uLTHxLCXe9yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/zo04La2tPQHm5jvAGFc5gBjXuckMCnf4iUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/zw24K7l5PsFp6TzAHV0dwBnZmkAbGtuAP///wZ1dHZmMTE07x8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/zQzN7iurq8HqamqCzg3O70gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/MjE14ywl3vcmH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8+OOGm////A66r8gBuaegAbmnoGTIs39clHt3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f88NuCu5eT7BaSh8QDq6usA6OjpAMnJygDCwsMA/v7+CVRT + VpsjIib/IB8j/yAfI/8gHyP/IB8j/yAfI/8xMTTEi4uNDQAAAABIR0qRIiEl/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/zc2 + OsosJd73Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8nIN3/QDrhkwAAgwC9u/UAf3vrAIB8 + 6xA1Lt/KJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/PDbgruXk+wWkofEAAAAAAP// + /wDU1NQAlZWXAGBfYgB7e304MTA06B8eIv8gHyP/IB8j/yAfI/8fHiL/Ly4yznd3eRJCQkUAYF9iWSgn + K/ogHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yEgJP9AP0KnLCXe9yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JyDd/0I8 + 4X8AANIA4+L7AJKP7gCgnfAJODLguyYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/zw2 + 4K7l5PsFpKHxAAAAAAAAAAAA/v7+AP///wC2tbcA5eXmCERDRq4hICT/IB8j/yAfI/8gHyP/Hx4i/y0s + L9hqamwZdnV4AImIiiM2NTnbHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8kIyf8UE9Sdywl3vcmH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9GQOJtFg/bAP///wCin/AA8fH9BDs14KsmH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f88NuCu5eT7BaSh8QAAAAAAAAAAAAAAAAD5+fkA////AAAAAABVVFhoJSQo/SAf + I/8gHyP/IB8j/x8eIv8rKi7hY2NlInBvcgD///8DT05RmCMiJv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/LSwv62loaz8sJd73Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8pIt79SUPiWy4o3gBeWeYAsa/zAP///wA+OOGZJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/PDbgruXk+wWkofEAAAAAAAAAAAAAAAAA////AMrK + ywBkY2YAb25xNC0sMOsfHiL/IB8j/yAfI/8fHiL/KSgs6FtbXStYV1oAUVFUAHh4ekAzMjXqHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/0A/ + Qr2rq6wSLCXe9yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KyTe+E5I40o+OOEAysj3AMnH + 9wAAAMoAQTvhhycg3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/zw24K7l5PsFpKHxAAAA + AAAAAAAAAAAAAAAAAAD///8Ajo6QAJWUlhI1NTjKHx4i/yAfI/8gHyP/IB8j/ygnK+9VVFc1TU1QALa2 + twDt7e0HVlZZlCYmKf8fHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/yopLftjYmVpAAAAACsk3vclHt3/JR7d/yUe3f8lHt3/JR7d/yUe3f8lHt3/JR3d/ywl + 3vNWUeU8TEbjAPr6/gD///8ABgDYAEQ+4nQnIN3/JR7d/yUe3f8lHt3/JR7d/yUe3f8lHt3/JR7d/yUe + 3f87NeCu5eT7BaSh8QAAAAAAAAAAAAAAAAAAAAAA9fX1ALu6vAD///8CPz5BoCAfI/8gHyP/IB8j/x8e + Iv8mJSn0UVBTQERDRwCNjY8AcG9yAJaWmCZJSEvCJCMn/x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/yQjJ/9NTE+5qKepGZOSlAA1Lt/2Lyje/y8p3v4vKd7+Lyne/i8p + 3v4vKd7+Lyne/i8o3v83MeDpYl3mLV5Z5gD///8AAADRADAp3wBOSONhMivf/S8p3v4vKd7+Lyne/i8p + 3v4vKd7+Lyne/jAp3/4wKd//RD7irubl+wSmo/EAAAAAAAAAAAAAAAAAAAAAAH9/fwD///8AAAAAAEpJ + THYkIyf/ISAk/yEgJP8gHyP/JiUp/U1MT046Oj0A6+vrAP///wAAAAAAiYiKPExLTsIqKS3/Hx4i/x8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hh0i/yYlKf9ISEvLiomLPAAAAAD///8AXljmc1lU + 5XdZVOV3WVTld1lU5XdZVOV3WVTld1lU5XdZVOV3X1nmaX966xF9eOsA////AJ6b8ABhXOYAcWzpKFxX + 5nZaVeV3WlXld1pV5XdaVeV3WlXld1pV5XdcV+Z5Y13ngHFs6VXp6PwCtrP0AAAAAAAAAAAAAAAAAAAA + AAAAAAAAjo2PAFxbXgBxcHNAV1ZZv1VUV8NVVFfDVVRXw1hXWsBzcnRAYmJkAMTExQDk4+QA7e3uAAAA + AACTkpQvX15hlD8+QuErKi77IyIm/yEgJP8gHyP/IB8j/yAfI/8iISX/KCcr/jk4POxZWFunioqMOf// + /wDw8PAA9PT1AP///wT///8E////BP///wT///8E////BP///wT///8E////BP///wT///8A////AP// + /wD///8A////AP///wH///8E////Bf///wX///8F////Bf///wX///8E////Bf///wb///8E////AP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wCzs7QAvLu9CKyrrR+qqashqqqrIaqpqyGrqqwgtLS1C62t + rgDR0dIAzs7PALu6vADX19cAAwIHAMTDxQ+LioxHb25xkVxbXsxLSk3lSUlM90pJTPlJSUztVVVY12tq + bamDg4VbsrGzGAAAAADIyMkAtrW3ANzc3QAAAAAAAAAABwAAAAAAAAAHAAAAAAAAAAMAAAAAAAAAAwAA + AAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAA + AAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAA + 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 + AAAtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979UErkXTIs3wBPSeMAWlXlOy0n3vImH93/Jh/d/yYf + 3f8mH93/JR7d/y8p3uxjXucxXFblAB8Y3ABFP+JpKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzDg1oN/ + 7BiDf+wAAAAAAPDv8ABYWFsAXl5gLCopLegfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/87Oz6f////AZiY + mgChoaIWPDs/zB8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Ojo925CQkieAf4EA5+foAP///wAtJt71Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8qI979UErkXTIr3wBAOuEAVlDkTSwl3vkmH93/Jh/d/yYf3f8mH93/Jh/d/y0n + 3vRcVuVBTUfjAB8Y3ABFP+JpKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzDg1oN/7BiDf+wAAAAAAP// + /wBhYGMAY2NmIisqLuAfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/85ODys+fn5BGhnagBvb3E4Li0x7h8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/KCcr/GJhZGcAAAAA////AP///wAtJt71Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8qI979UErkXTIr3wAtJt4AUUzkXyoj3v0mH93/Jh/d/yYf3f8mH93/Jh/d/ywl3vpWUORSPTbhAB8X + 3ABFP+JpKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzDg1oN/7BiDf+wAAAAAAP///wBtbW8Abm1wGi4t + MNgfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/82NTi4s7K0CDU0NwBXV1pfJiUp/CAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/ISAk/0hHSq3t7e4Jv77AAMPDxAAtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979UErkXTIs + 3wANBdkAS0XjcSki3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yoj3v5QS+RkJh/dAB8Y3ABFP+JpKCLd/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/NzDg1oN/7BiDf+wAAAAAAP///wB5eXsAfHt9EzAvM88fHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8zMjbElJSWDQAAAABJSEyEIiEl/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zY1 + Od+JiIolgYCCAPT09AAtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979UErkXTQt3wAAAM0ART/igycg + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9KReN2AADWACAZ3ABFP+JpKCLd/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/NzDg1oN/7BiDf+wAAAAAAP///wCDg4UAjY2PDTIxNcQgHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv8xMDTPgoKEE////wA+PkGgISAk/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/ykoLPdkY2ZPQkFEABgX + GwAtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979UErkXTcx4AAAAAAAQjzhlicg3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ycg3f9GQOKJAAC+ACIb3ABFP+JpKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzDg1oN/ + 7BiDf+wAAAAAAAAAAACNjY8AqamrCTU0N7kgHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8vLjLYc3J1GtfX + 2AY3Njq1IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMiJv9QT1N/AAAAAPHx8QAtJt71Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8qI979UErkXTs14AD///8EPznhqSYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ycg + 3f9CPOGc////ASYf3QBFP+JpKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzDg1oN/7BiDf+wAAAAAAAAA + AACbm50A5+bnBTc2OqwgHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8tLC/haGhqIZeXmQszMjXEIB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/9BQEOq////Bbu6vAAtJt71Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8qI979UErkXT854QCsqvIJOzTguiYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8+N+Gu4+L7BSsk + 3gBFP+JpKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzDg1oN/7BiDf+wAAAAAAAAAAACtrK4A////ATg4 + O54gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8rKi7pY2JlK3x7fRAvLjLNHx4j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv82NTjLlJOVEo+PkQAtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979UErkXUI8 + 4QCGguwQNjDgyCYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f86M+C+oJ3wCzAp3wBFP+JpKCLd/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/NzDg1oN/7BiDf+wAAAAAAAAAAADNzc4AAAAAADs6PZAhICT/IB8j/yAf + I/8gHyP/IB8j/x8eIv8pKCzvXFxfNXRzdhQuLTHUHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IyIm5yYlKbcqKS2xJyYqsyQjJ9wgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv8uLTHib29xJWxrbgAtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979UErkXUU/4gB1cOkZNC3f1iUe + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f83MODNhoLsEzYw4ABFP+JpKCLd/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/NzDg1oN/7BiDf+wAAAAAAAAAAAD///8AAAAAAD49QYMhICT/IB8j/yAfI/8gHyP/IB8j/yAf + I/8nJir1VVRXP25ucBUtLC/XHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8lJCjSNzY6Xjs6 + PiZBQEMiOTg8Izs6Pk0sKy66IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8pKCzxXl5hPFFQ + UwAtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979UErkXUZA4gBsZ+gmMivf4yUe3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yUe3f80Ld/bdnHqHTo04ABFP+JpKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzDg1oN/ + 7BiDf+wAAAAAAAAAAAD///8AAAAAAENCRXYiISX/IB8j/yAfI/8gHyP/IB8j/yAfI/8mJSn5T09SS25t + cBUsKy/XHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMiJvk7Oj5vo6OkBQAAAAAKCQ0ABwYKAP7+ + /gJOTVE9KCcr0yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8mJSn7U1JVVDY1OQAtJt71Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8qI979UErkXUM94gBiXeYzLyne7SUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe + 3f8xK9/mamXoKTo04ABFP+JpKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzDg1oN/7BiDf+wAAAAAAAAA + AABHRkkAGBcbAEdGSmkjIib/IB8j/yAfI/8gHyP/IB8j/yAfI/8lJCj8S0tOWHl4ehUtLDDXHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/yoqLeBqaWwsS0pOAOHg4QD///8A////AFlYWwD///8DMzI2eyEg + JPwgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8jIib/S0pOaxAPEwAtJt71Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8qI979UErkXT034QBYUuVBLSbe9CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f8vKN7vX1rmNzcx + 4ABFP+JpKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzDg1oN/6xiDf+wAAAAAAAAAAACurrAAKyouAEtK + TVskIyf9IB8j/yAfI/8gHyP/IB8j/yAfI/8kIyb/SUhLZoOChBIuLTHTHx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/y4uMcONjI4PiYmLAKioqQDh4eEAwcHCAAAAAAAnJioAQD9COyMiJuwgHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8iISX/RUVIgQAAAAAtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979UErkXTYv + 4ABTTeRSKyTe+iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8tJt72WVPlRzMs3wBFP+JpKCLd/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/NzDg1oN/6xiDf+wAAAAAAAAAAADd3d4AOTg7AE5NUE4lJCj5IB8j/yAf + I/8gHyP/IB8j/yAfI/8iISX/RERHc5aWmA8vLjLNHx4j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/zIx + Nbatra4IoKCiAMvKywD///8A+vr6APHx8QBFREgASUlMGyUkKNUgHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8hICT/Pz5CkgAAAAAtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979UErkXSoj3gBPSeNmKiPe/iYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8rJN78U07kWCoj3gBFP+JpKCLd/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/NzDg1oN/7BiDf+wAAAAAAAAAAAD29vYARERHAFNSVUInJir1IB8j/yAfI/8gHyP/IB8j/yAf + I/8iISX/QUBDgb6+vwwzMjbHIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/zIxNbWtra4Hn56gAPj4 + +AAAAAAA////ALq5uwBRUVQAVVRXDCYlKL0gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Ozo+ov// + /wMtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979UErkXRcQ2wBKRON4KCHd/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8pIt7/Tkjjah0V3ABFP+JpKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA + 7BiEgOwAAAAAAAAAAAD///8ATk5RAFdWWTcoJyvvIB8j/yAfI/8gHyP/IB8j/yAfI/8hICT/Pz5BkPLy + 8gg1NDe7IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yopLLZxcXMIbWxvAP///wAAAAAAAAAAAOjo + 6ABCQUUATUxPBSMiJq0gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ODc6rd7e3gYtJt72Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8qI979UErkXQAA1gBEPuKKJyDd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8oId3/SELifQcA2ABFP+JpKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA7BiEgOwAAAAAAAAA + AAD///8AV1ZZAFtaXSwpKCzpHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/Ozo+nv///wU5OTysIB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/ycmKsFbWl0NWllcALOytAAAAAAAAAAAAGhnagBAP0IAUlFVBCQj + J6ogHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/NzY6t7e3uAktJt72Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8qI979UErkXAAAxQA/OeGcJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8nIN3/RD7ikAAA + 0ABFP+JpKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA7BiEgOwAAAAAAAAAAAD///8AYmFkAGRj + ZiMrKi7hHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/ODc7qv///wRAP0KYISAk/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yYlKdVOTVAbS0pNAP///wD///8AAAAAAO/v7wBKSUwAXVxfBCUkKKsgHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/NTQ4uqWkpgstJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979T0rkXP// + /wE9NuGvJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QDrhogAAogBFP+JpKCLd/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA7BiEgOwAAAAAAAAAAAD///8Abm5wAG9ucRsuLTDZHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/NjU5t////wVHRkp+IiEl/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMi + JupBQEQ2Ly4yACYlKQDOzs8A1NTUAMnIyQBeXmAAYmFkCScmKrcgHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/NTQ3uqOipAstJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979T0nkXN7d+gc6M+DAJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/PTbhtP///wNFP+JpKCLd/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/NzHg1oSA7BiEgOwAAAAAAAAAAAAAAAAAeXl7AHl4exQvLjLPHx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/NDM3w8bGxwlQT1NfJSQo/SAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJPs3NjlrAAAAAG1s + bwDb29wA5ubmANDQ0QA+PUAAVlVYHCYlKdIgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/NjU5uLCv + sQotJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979T0nkW5iV7w82L9/OJR7d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/OTLgxMrJ9wlFP+JpKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA + 7BiEgOwAAAAAAAAAAAAAAAAAiIiKAImJiw0xMDTEIB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/MTA0zoyM + jg9jYmVAKikt8x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8qKS2+WVhbJf///wAAAAAAAAAAAAAA + AAD///8CPz9CWSIiJfAgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/NzY6sM7OzwctJt72Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8qI979T0nkW3p26hkzLN/bJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/Ni/f0pSR7hJFP+JoKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA7BiEgOwAAAAAAAAA + AAAAAAAAnJudAKenqAk0Mze5IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Ly4y13NzdRd/f4EjMjE14R8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8hICT5MC8znj8+QT1NTE8tWFdaLkdGSS04NztIKiotyCAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Ozo+pP///wMtJt72Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8qI979T0nkWm9q6CYxKt/nJR7d/yYf3f8mH93/JyDd/y8o3v8nIN3/Jh/d/yYf3f8lHt3/Myzf3314 + 6x1FP+JnKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA7BiEgOwAAAAAAAAAAAAAAAAAsbGyAOTk + 5QU3NjqtIB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/LSww4WtqbSHDw8QMPTw/wCAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/ISAk+yUkKNUtLDDIMjE1ySsqLsgiISXZIB8j/iAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8hICT/QD9CkgAAAAAtJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979T0rkWWRf + 5zQvKN7wJR7d/yYf3f8mH93/KSLd/kM94fQoId3+Jh/d/yYf3f8lHt3/MCrf6m5p6CpFP+JnKCLd/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA7BiEgOwAAAAAAAAAAAAAAAAAxcXGAP///wE5ODygIB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/Kyou6GNiZSsAAAAATEtOkCIhJf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/Hx4i/x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8jIib/SklNewAAAAAtJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979UEvkWVlU5UMsJt73Jh/d/yYf + 3f8mH93/KiPe+01H49YpIt38Jh/d/yYf3f8mHt3/Life8mJd5jhFP+JmKCLd/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/NzHg1oSA7BiEgOwAAAAAAAAAAAAAAAAA0tLTAAAAAAA7Oj6SISAk/yAfI/8gHyP/IB8j/yAf + I/8fHiL/KSgs71xbXjVDQkUAZmVoWikoLPofHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8mJSn9WVhbXSwr + LgAtJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979UUvkWVFL5FQqI978Jh/d/yYf3f8mH93/KyTe9lFM + 5LMqI976Jh/d/yYf3f8mH93/LCXe+FlU5UhGQOJlKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA + 7BiEgOwAAAAAAAAAAAAAAAAA29rbAAAAAAA/PkGFISAk/yAfI/8gHyP/IB8j/yAfI/8gHyP/JyYq9FVU + V0BeXWAAjo6QJjg3Ot0fHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8tLC/vbGtuOV5dYAAtJt72Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8qI979Uk3kWUxH42cpIt3/Jh/d/yYf3f8mH93/LSbe8VdS5ZIrJN72Jh/d/yYf + 3f8mH93/KiPe/VNO5FpGQOJlKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA7BiEgOwAAAAAAAAA + AAAAAAAA39/gAAAAAABDQkV4IiEl/yAfI/8gHyP/IB8j/yAfI/8gHyP/JiUp+FFQU0xLS04A////BlBP + UqAiISX/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv85ODvTlZWXGY6OkAAtJt72Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8qI979VE7kWklD4nsoId3/Jh/d/yYf3f8lHt3/Lyje6l5Z5nMtJt7wJh/d/yYf3f8mH93/KSLd/05I + 421IQuJmKCLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA7BiEgOwAAAAAAAAAAAAAAAAA////ABUU + GABGRUlqIyIm/yAfI/8gHyP/IB8j/yAfI/8gHyP/JSQo/E1MT1kvLjIANDM3AHd3eU8xMDTyHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yIhJf9OTVCc////BMrKywAtJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979VVDkXEQ9 + 4o0nIN3/Jh/d/yYf3f8lHt3/MSrf4mZh51gvKN7pJR7d/yYf3f8mH93/KCHd/0hC4oBJQ+JnKCHd/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA7BiEgOwAAAAAAAAAAAAAAAAAAAAAACkoLABKSUxdJCMn/SAf + I/8gHyP/IB8j/yAfI/8gHyP/JCMm/0hHS2YcGyAAqqqrAMXFxhBSUVSrJCMn/x8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hh0h/zEx + NPN0c3VONTQ4AAAAAAAtJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979VlHlXz444Z4mH93/Jh/d/yYf + 3f8lHt3/NC3f13Br6UAxK9/gJR7d/yYf3f8mH93/JyDd/0M94pJLReNpKCHd/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/NzHg1oSA7BiEgOwAAAAAAAAAAAAAAAAANDM2ADg3OwBPTlFQJSQo+iAfI/8gHyP/IB8j/yAf + I/8gHyP/IyIm/0VER3QAAAMAAAAAACMiJgCHh4k+SEdK0SYlKf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/LSwv/FpZXKK+vb8RpqanAPDw + 8AAtJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI979WFLlZDw14LEmH93/Jh/d/yYf3f8lHt3/NzDgy356 + 6yw0Ld/VJR7d/yYf3f8mH93/Jh/d/z854aVMRuNtKCHd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA + 7BiGgu8AAAAAAAAAAAAAAAAAAAAAAEZFSQBSUVREJyYp9SAfI/8gHyP/IB8j/yAfI/8gHyP/IiEl/0JB + RYIAAAAAlZWXAOfn6AD///8BiomLdTo5PPkfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/S0pN7aenqExRUFMAAAAAANvb2wAtJt72Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8qI978WVTlazkz4MImH93/Jh/d/yYf3f8mH93/OjPgvZWR7hs3MeDJJR7d/yYf + 3f8mH93/Jh/d/zw24LZOSONzKCHd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA6xh2c7IAQ0JFAD08 + PwA9PEAAPTxAAENCRgBbWl0zKCcr8B8eIv8gHyP/IB8j/yAfI/8gHyP/ISAk/z8+QZAAAAAA2dnZALKy + swDOzs8NXV1goCwrLv4fHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/MzI2+WZlaJHh4OEMvr6/APz8/AAtJt72Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8qI978WVPldDUv388lHt3/Jh/d/yYf3f8mH93/PTfhrb279Q46NOC6Jh/d/yYf3f8mH93/JR7d/zgy + 4MVPSeN6KCHd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oN/7xecm5MPh4aJU4SDhVqEg4ZZhIOGWYaF + h1dxcXN5Kyou8x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/zs6PZz///8B0tHSAExLTgBycnRIMjE17x8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/zU0OO56eXxUDAsPAP///wAtJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI977V1HlfjIr + 39slHt3/Jh/d/yYf3f8nIN3/QDrhnP///wU+OOGqJh/d/yYf3f8mH93/JR7d/zUu39NPSuODKCHd/iYf + 3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oiD/BVmZWQpPTxA0jU0OOY1NDjkNTQ45DU0OOQ0MzbpJCMn/SAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/zk4PKr///8EycjJAP///wBLSk6OIyIm/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yIh + Jf9MS06xz8/QDLOztAAtJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI976V1HljDAp3+YlHt3/Jh/d/yYf + 3f8nIN3/RD7iigAAaABCPOGZJyDd/yYf3f8mH93/JR7d/zIs399QSuSPKCHd/SYf3f8mH93/Jh/d/yYf + 3f8lHt3/NzHg1oiE/RViYWAoLCsv6iAfI/8hICT/ISAk/yEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/zY2Obe7u7wInZyeAKKioxA5ODzEHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8yMTXrfHt+OWNj + ZQAtJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI976VlDlmy4n3u8mH93/Jh/d/yYf3f8oId3/SELieAAA + zgBGQOKHJyDd/yYf3f8mH93/JR7d/zAp3+lPSeOcKCHd/SYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oaC + +BZsa2kfLSww3x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/zMy + NsKWlpgMeHh6AHZ1eCgwLzLkHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8hICTvJCMm5SQj + J+UiISXmIB8j9yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8lJCj/W1pdeQAAAAAtJt72Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8qI975U03kqywl3vUmH93/Jh/d/yYf3f8pI97/TknjZxEK2gBKRON0KCHd/yYf + 3f8mH93/Jh/d/y4n3vFOSOOsKCHd/CYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oWB9BZycm0WLi4x1R8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zEwNM2DgoQSXFteAF9e + YUApKCzzHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yYlKc0yMTVhOjk9QkA/QkMxMDNELCsvjCIh + JfEgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Q0JFr+Pj5AktJt72Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8qI975T0njuyoj3vkmH93/Jh/d/yYf3f8rJN77VE7kVTAp3wBOSeNiKiPe/iYf3f8mH93/Jh/d/ysl + 3vZMRuO8KCHd/CYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oSA8ReAgHgPMDAzyx8eI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zAvMth4d3kaSUlMAFBQU1QmJSj7IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/JCMn9kJBRWKIh4kFmpmbAaqpqwJycXQBYGBjFjEwNJ8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/NTQ31omJiyEtJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8rJN76TEfjzigh + 3fwmH93/Jh/d/yYf3f8sJt72WFLlREI84QBTTuRRKyTe+iYf3f8mH93/Jh/d/yoj3vpKROPOKSLd/CYf + 3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oN/7xeamowKMzI2wCAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/y0sMOBsa24hOzo+AEhHS2IkIyf+IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/Kiot229ucSVPTlEAUE9SAFlYWwBCQUUAAAAEAFFQU0wlJCjyIB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/LCsu7mhoa0ItJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8rJd77SkXj4icg3f4mH93/Jh/d/yYf + 3f8uJ97uW1blNE9J4wBZVOVBLSbe9CYf3f8mH93/Jh/d/ygi3f1IQuLhKSLd/CYf3f8mH93/Jh/d/yYf + 3f8lHt3/NzHg1oN/7RfJyqwFNTQ4tCAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/ysqLudiYWQqLi0xAEdGSm4jIib/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JyYqv2pp + bA1paGsAU1NWAFVUVwA+PUEAY2JlAG9ucR4qKS3TIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JiUp+lhX + WmgtJt72Jh/d/yYf3f8mH93/Jh/d/yYf3f8sJd79R0Hi9CYf3f8mH93/Jh/d/yUe3f8wKd/lZF/nJ11Y + 5gBgW+YyLyje7SUe3f8mH93/Jh/d/ycg3f5FP+L0KiPe/iYf3f8mH93/Jh/d/yYf3f8lHt3/NzHg1oN/ + 7Bj///8CODg7qCAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/yko + LO5bWl00KCcrAEVESHMjIib/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IyImtUNCRgdCQkUAysnKAP// + /wD///8AcXBzAHd2eAgoJyuzIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IyIm/0tKTYstJt71Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8rJd7/PTfh/SYf3f8mH93/Jh/d/yUe3f8zLd/bcm7pHWxn6ABpZOclMSrf4yUe + 3f8mH93/Jh/d/ycg3f88NuD+KSPe/yYf3f8mH93/Jh/d/yYf3f8lHt3/NzDg1YF97BcAAAAAOzo9miEg + JP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/ygnKvRWVVg/JSQoAERE + R3MjIib/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JCMnukxMTwpMS08A////AAAAAAD///8AeHd6APDw + 8QEnJiqcIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk/0FAQ6ctJt71Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8oId3/Life/yYf3f8mH93/Jh/d/yUe3f83MODPhIHsFHt26gB0cOkaNC3f2CUe3f8mH93/Jh/d/yYf + 3f8tJ97/JyDd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NjDg1YB76xcAAAkAPTxAjCEgJP8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yYlKflSUlVMJiUpAEVER24jIib/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/JSQoyUxLThFMS04A////AP///wD19fUAeHd6AAAAAAAlJCiOIB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/zs6PsEtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f86NODBoZ7wDI6K7QCFgewRNjDgyyYe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/NjDg1YB86xcODDUAQD9DfyIhJf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yUkKPxNTE9YJyYqAENDRmUjIib/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/JiUp3VdWWSRKSU0AvLy9AP///wD///8AjYyOAAAAAAAlJCiPIB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/zc2OdUtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8+OOGx2tn5Bqmm8QClovEKOTPgvCYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/NjDg1YB86xcoJkkARENGcSMiJf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yQjJ/9JSEtlJSQoAElJTFwkIyf9IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JCQn81FR + VE4TEhYA9PT0AP///wD///8AqaiqAM3NzgUsKy+lIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zMy + NuUtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f9BO+Gg////As7M + 9wDx8f0EPTfhrCYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/NjDg1YB8 + 6xc6OFgAR0ZKYyMiJv4gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMi + Jv9GRUlzHx4iAE9OUU4mJSj5IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk/zc3OpSdnJ4MAAAAAAAA + AAAAAAAAAAAAAGVkZyQqKS3SIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zAvM/AtJt71Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ycg3f9DPeKNAAC5AP///wD///8BQTvhmycg + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/NjDg1YB86xdGRGQATEtOVyUk + KPwgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yIhJf9CQUWBEA8TAFZV + WD8nJyrzIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yYlKeU/PkFqV1ZZLWRjZiFeXWAlVVRXNDQz + N4IiISX4IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/y0sMPYtJt71Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9HQeJ6AADVAAAAAAAAAMIART/iiScg3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/NjDg1YB86xdQTm8AUE9TSiYlKfggHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJP8+PUGOAAAAAGBfYi8qKS3rHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8kIyfqMC8zvzc2Oqw0Mze2MC8yzyIhJe4gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/ywsL/stJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yki3f9JRONnHhfcAKuo8gAAANYASUPjdygh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/NjDg1YB86xdXVnkAU1JVPiUkKPUeHSH/Hh0h/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJP88Oz+cAAAAAHNydR8vLjLdHx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/yAfI/8gHyP/Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/y0sL/wtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yok + 3vtPSeNWNS/fAOTj+wAjHN0ATUfjZSkj3v4mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/NjDg1YB86xdoZo0AY2JlMTw7P+UyMTX3LCsv/SIhJf8fHiL/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/85OTyq////A5KRkxE0NDfJHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/ywr + L/otJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ywm3vdXUuVHRkDiAJaS + 7gA5M+AAUkzkUysk3vomH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/NjDg1YB8 + 6xeEgb0Ai4qMFnRzdnhmZWiBWFdamkJCRdIpKCz+Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/82NTm2uLe5B////wU9PD+sIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/y4tMfQtJt71Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/y8o3vBfWuY4VVDkAG5p6ABJQ+IAWFLlQy0m + 3vUmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/NjDg1YB86xeJhfIA////AP// + /wX///8E9vb2EYuLjUZQUFO3JyYq/h8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/80MzfCl5aYDAAA + AABISEuHIiEl/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zIxNeotJt71Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/JR7d/zEr3+hpZegrZF/nANPR+ABWUOQAXlnmNC8o3u4lHt3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/NjDg1YB86xd/e+sA9PT0APHx8QDr6+wAuLi5AAAA + AACbm502RURHziEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8yMTXNhYWHEkJBRQBaWVxcJyYq/CAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/zc2OtgtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JR7d/zQu3952cuogdHDpAP///wBjXuYAZ2LnJzEq3+QlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/NjDg1YB86xeAfOsA6+vrAOrp6gDm5eYAuLe5AP///wAAAAAAcXBzZi0s + L/YfHiL/IB8j/yAfI/8gHyP/IB8j/x8eIv8vLjLXdnV4GXBvcgB4eHoyMC8z6h8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/z08QLwtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zYw + 4NGCfusVgX3rAP///wBybekAc2/pHDMt39olHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/NjDg1YB86xeAfOsAAAAAAAAAAAD///8A2trbAMnJygCenZ8As7K0F0JBRMMgHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv8tLDDfamlsIXx7fgC0tLURQUBDwyAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IiEl/0dG + SpctJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/zgy4MGUke4MiobtAP// + /wCAfOsAhIDsEzYw4M0lHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/NjDg1YB8 + 6xeAfOsAAAAAAAAAAAAAAAAA/v7+AKSjpQD///8AAAAAAFxbXnkmJSn/IB8j/yAfI/8gHyP/IB8j/x8e + Iv8rKi7nYWBjKWRjZgAAAAAAWFdagyQjJ/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JyYq+lpZXGktJt71Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/zs14LHCwPUGlZLuAP///wCOiu0AnpvwCzoz + 4L8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/NjDg1YB86xeAfOsAAAAAAAAA + AAAAAAAAAAAAAP///wC5uboAZGNmAHh3ejYvLjLqHx4i/yAfI/8gHyP/IB8j/x8eIv8pKCzuXFxfNFRT + VgBgX2IAfn2AOzMyNusfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/MC8z5XZ1eDYtJt71Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/z034aD///8CpKHxAP///wCem/AA2dj5BT034a8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/NjDg1YB86xeAfOsAAAAAAAAAAAAAAAAAAAAAAAAA + AAD///8An5+hAK6urxA9PEDEIB8j/yAfI/8gHyP/IB8j/yAfI/8oJyvzV1ZZP0pJTACysrMA2tnaC1BP + UqgiISX/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/RENHt729vg4tJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JyDd/0E74Y4AAK4Awb/1AAAAAAC2tPQA////AUA54Z0mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/NjDg1YB86xeAfOsAAAAAAAAAAAAAAAAAAAAAAAAAAAD09PQA7OzsAP// + /wBKSU2RIiEl/yAfI/8gHyP/IB8j/yAfI/8mJSn4UVBTSj49QQD///8AKSgrAH59f0Y3NjnqHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv8qKS37Z2ZpaQAAAAAtJt71Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KCHd/0ZA + 4n0AANIA////AAAAAADo5/sAAAC5AEM94osnIN3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 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 + Kf5CQUTghYSHbv///wbd3d4A2dnaAP///wD///8AAAAAAAAAAAAAAAAALyne8SYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9Qq9u/UAQTvhAF1Y5gBsaOg5MSvf7iUe3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f9EPuKx4N/6CLOw8wCrqfIAUErkAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP///wAAAAAAAAAAAAAAAACXl5kAz8/QCD08QLIgHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yIhJf9JSEyLAAAAAP///wDOzs8A////AM3NzgD///8LcG9xijMy + NvYfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x4dIf8oJyv/S0tOzpSTlUkAAAAA////AP///wDBwMEAAAAAAAAA + AAAAAAAALyne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9Qq9u/UAdXHpAExG + 4wBmYedJLyje9iUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f9AOuHBrqzyDpuX7wCsqfIAUErkAF1Y + 5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP///wAAAAAAAAAAAAAA + AAChoKIA////BEA/Q6UhICT/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJP9GRUiZ////Ae3t + 7gDf398AAAAAAD8+QQCWlZc6SEhL2yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8eHSH/Kysu/2Fg + Y6i3trgddHN2ACIhJQDo6OkA////AAAAAAAAAAAALyne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/QTvhvMC+9Qq9u/UAvrv1ADIs3wBfWuZbLSbe+yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe + 3f88NuDQlZHuF4mF7ACtq/IAUErkAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9RTOSRAAA1AP///wAAAAAAAAAAAAAAAACvr7AA////AURDRpghICT/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yEgJP9CQUSm////BMjIyQDz8/MAz8/QAP///wVram2IKikt/h8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zg3O/KCgYRl////A9HR0gD7+/sAk5OUAAAAAAAAAAAALyne8SYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9Qq9u/UAs7DzAAkC2QBYU+VsKyTe/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f84MuDdhIDsIXt36gCvrPIAUErkAF1Y5kEuJ97zJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP///wAAAAAAAAAAAAAAAADFxcYAAAAAAEdG + SosiISX/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8+PUCy2trbCK6trwDV1dUAoqGjALCw + sSFIR0rPIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMiJv9TU1bCvLu9HqGh + owDU09QAubi6AAAAAAAAAAAALyne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+ + 9Qq9u/UAAACoAAAAzABQSuR9KSLd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f80Lt/ndnLqLW1o + 6ACqqPIAUErkAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP// + /wAAAAAAAAAAAAAAAADq6uoAAAAAAExLTn4jIib/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/87Oj2+srGzDJqanAD///8AKiktAH18f1QxMTT0Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv80MzbzfHt+YQAAAAD///8Azs7PAAAAAAAAAAAALyne8SYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9Qq9u/UA////AAAABQBLReOQKCHd/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yUe3f8xK9/wbWjoO11Y5gCgnfAAUErkAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP///wAAAAAAAAAAAAAAAAD///8AAAAAAE9OUXAkIyf/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv84NzvJnJudEo2MjgDV1NUA////Al5dYI0lJCj/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8jIyb/VlVYrdTT1BC5uboA7OzsAP// + /wAAAAAALyne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9Qq9u/UA5uX7AP// + /wNHQeKjJyDd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f8vKN73ZWDnTElD4wCkofEAUErkAF1Y + 5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP///wAAAAAAAAAAAAAA + AAD///8AHx4iAFJRVGIlJCj9IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv82NTjUjIyOGYGB + gwCkpKYAv7/AEEdGSr4gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/Ozo+5Y2NjzliYWQA////AP///wAAAAAALyne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/QTvhvMC+9Qq9u/UAx8b2ANbV+QlDPeK1Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8tJt78XlnmXS4n3gC1s/MAUErkAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9RTOSRAAA1AP///wAAAAAAAAAAAAAAAAAKCQ0ANzc6AFhXWlUnJir6IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv8zMjXcf3+BIHZ2eACBgIIAjYyOKDc2OuAfHiL/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiP/KSgs/Whoanj///8A3t7fAKKhowAAAAAALyne8SYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9Qq9u/UArKnyAKuo8hA/OeHFJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8rJN7/WFPlcAAA1wCopfEAUErkAF1Y5kEuJ97zJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP///wAAAAAAAAAAAAAAAACDg4UASEdLAF5d + YEkoKCv2IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8wLzLkdXV3KWxsbgBUU1YAcnJ0Ry0t + MPQfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk/1BP + UrnW1tYQurq7AHRzdgACAgIALyne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+ + 9Qq9uvUAkI3uAJCM7hg6NODSJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8pIt3/Uk3kggAA + wgAAALYAUErkAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP// + /wAAAAAAAAAAAAAAAAC4uLkAVlVYAGVkZz4rKi3xHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv8uLTDrb29xM2VkZwAREBQAYGBiZycmKv0gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zs6PeORkZMuf36BAPDw8AD///8ALyne8SYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9Qq8uvUAenXqAH156yI2MODeJR7d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8nId3/TUfjlP///wD///8AUErkAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP///wAAAAAAAAAAAAAAAADc3NwAYWBjAGtrbTMtLDDrHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8sKy7xaWhrPl1cXwAAAAAAUlFUgyMiJv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/ywrL/hwb3JaISAkAP// + /wD///8ALyne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9Qq8uvUAaWTnAHJt + 6S8zLN/oJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8nIN3/R0Hipv///wTk4/sAUErkAF1Y + 5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP///wAAAAAAAAAAAAAA + AADx8fIAbGtuAHJydCkvLjLlHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8pKSz2YmJkSlNS + VQD///8BR0ZKmiEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yQjJ/9aWVyL////Aerp6gD///8ALyne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/QTvhvMC+9Qq9u/UAW1blAGxn6D8xKt/xJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Qz3it87N9wnEwvYAUErkAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9RTOSRAAA1AP///wAAAAAAAAAAAAAAAAD9/f0Aenp8AH18fyExMTTdHx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8oJyr6W1teVUZGSQD19fUGQD9CrSAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/9IR0u32traDLe3uAD///8ALyne8SYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9Qq/vfUAR0HiAGVg51AuKN74Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/Pzjhx6il8RGpp/IAUErkAF1Y5kEuJ97zJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP///wAAAAAAAAAAAAAAAAD///8AiomMAImI + ihk0MzfUHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8mJSn9VlVYYjY1OAC2tbcLOzo9uyAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv86OT3WmJeZHouLjQDBwcMALyne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+ + 9QrBv/YAJyDdAF1X5mEsJd78Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/OjTg1ZCM + 7hqQjO4AUErkAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP// + /wAAAAAAAAAAAAAAAAD///8AmZmbAJaWmBI2NTjJHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8lJCf/U1JVcBwbIACXl5kPNjU5xSAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8wLzPseHh6OGVlZwC4t7kALyne8SYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9QrCwPYAAADUAFRP5HIqI97/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/NzDg4H966yV6duoAUErkAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP///wAAAAAAAAAAAAAAAAD///8AqqqrAKuqrAw4Nzq9IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8jIib/T05SfgAAAACIh4oTNDM3zB8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/4iISXvIiEl4iMiJuIjIibhIiEl5CEg + JPcgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8pKCz5ZGNmVTg4 + OwCxsLIALyne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9QrAvvUAAAC3AE1H + 44MoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/My3f6nNu6TJoZOcAT0rjAF1Y + 5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP///wAAAAAAAAAAAAAA + AAD///8AwMDBANPS0wc7Oj6xIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8iISX/SklNiwAA + AACDgoQXMzI20h8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/CMi + JuAqKS2oLCsufjIxNX0wLzN9KSgshignK8MiISXuIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8lJCj/VVRXcwAAAAD///8ALyne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/QTvhvMC+9Qq6uPQA////AUlD4pYnIN3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/MCrf8mtm6EFZVOUAT0rjAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9RTOSRAAA1AP///wAAAAAAAAAAAAAAAAD///8A29vcAP///wQ/PkGmIB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8hICT/RkVImAAAAAB7en0YMTA00x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/JCMn3jY1OG1NTE8sPz5CE01MTxNGRUkSRENGGEZGST80MzaaIyIm9CAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8iISX/TEtOkv///wD///8ALyne8SYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9QqzsPMA/f3/BUZA4qkmH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life+WRe51JDPeIAUErkAF1Y5kEuJ97zJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP///wAAAAAAAAAAAAAAAAAAAAAA////AP// + /wFDQkaZISAk/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8hICT/QUFEpP///wJ4d3oYMTAz1B8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8iISX8NzY5k1hXWhv///8CBgUJAAAA + AwAHBgoAAAAAAJmYmgdTUlU2MTAzriAfI/0gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Q0JGrP///wbV1dYALyne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+ + 9QqqqPIAu7n0C0I84bsmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/LCXe/VxX + 5mQgGdwAUUvkAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP// + /wAAAAAAAAAAAAAAAAAAAAAA////AAAAAABIR0qMIiEl/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Pj1Asf///wV7e30YMjE11B8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8oJyvrXFteTAAAAAB5eHsA////AP///wD///8AtLS1AFVUVwD///8CR0ZKVSQjJ+IgHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/PDs/wrOztA6xsLIALyne8SYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9QqfnPAAm5jvEz034colHt3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/KiPe/1VQ5HYAANEAUk3kAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMS05/IyIm/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Ozo+vcLCwwqCgYMWMzI20h8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8xMTTPlZSWIHd3eQB7en0AtLO1ANvb3ADJycoAnJudABEQ + FQBfXmEAfn1/FCsrLrIgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/NzY605WU + lhmVlZYALyne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9QqRje4AhYHsGzgy + 4NYlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KCHd/09J44gAAJsAVE/kAF1Y + 5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAA1AP///wAAAAAAAAAAAAAA + AAAAAAAAoqGjAAAAAABPTlJxJCMn/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/ODc7yaSj + pRCGhYgTNDM3zB8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/82NTmzvb2+C5yc + ngCbm5wAxMTFANvb3ADJycoAzc3OAAAAAACSkZMA////ATQ0N30hICT+IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/MzI24YKBhCV9fX8ALyne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/QTvhvMC+9QqCfusAeXXqJzUv3+IlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JyDd/0pE45r///8CV1HlAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9RTOSRAAA1AP///wAAAAAAAAAAAAAAAAAAAAAAysrLABsaHgBTUlVjJSQo/SAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/NTQ40o+OkBeSkpQPNjU4xiAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/88Oz6m////BMDAwQBzcnUA////AAAAAAD///8A////AAAAAAD///8AAAABADs6 + PlUiISX2IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Ly4x6nNydDFpaGsALyne8SYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+9QpzbukAcWzpNjMs3+0lHt3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/0ZA4qzv7/0GWlXlAF1Y5kEuJ97zJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAAzAP///wAAAAAAAAAAAAAAAAAAAAAAr6+wADIx + NQBXV1pXJyYq+iAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/MjE1239/gR6xsbILOjk8wCAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8+PUCj////A8rKywD///8AAAAAAAAA + AAAAAAAA////AP///wA9PEAALSwwAEA/QzgjIibqIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/LCsu8WppbD5aWVwAMCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhvMC+ + 9QpiXeYAaWToRTAp3/UlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/0I7 + 4b22tPQMXlnmAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RTOSRAAAqAP// + /wAAAAAAAAAAAAAAAAAAAAAAHBsfAENCRgBdXF9LKCcr9iAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/MC8z5HZ1eCfq6uoHPT1AtyAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/84Nzqj////A6+vsAD///8AAAAAAAAAAAAAAAAAAAAAAP///wCUlJYANjU4AD8+QiUjIibeIB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/KSgs92JiZEpLS04AMCne8iYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/QTvhu8C+9QpPSeMAYVzmVi0n3vomH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/JR7d/z034cybl+8UYl3mAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9STOSSAAAaAP///wAAAAAAAAAAAAAAAAAAAAAAJiUpAFFQUwBiYWQ/Kikt8R8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Li0x629vcTL///8CQD9DqSAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8tLDCmrKutBHt7fQD///8AAAAAAAAAAAAAAAAAAAAAAAAA + AADV1NUAMjE0ADQ0NxsiISXVIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JyYq+lxb + XlQ8Oz4AMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhu7+99Qo2L98AWFPlZisk + 3v4mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zky4NmHg+weYl3mAF1Y + 5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAYAP///wAAAAAAAAAAAAAA + AAAAAAAAfHt+AFtbXgBmZWgzLCsu6x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/LCsu8Whn + aj0AAAAARkZJmiEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8qKS2xfn6ACWpp + bAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAADh4eIANDM3ADY1ORgjIibTIB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/JiYp/FtaXV8rKi4AMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/QTvhu7+99QoGANgAUUvkeCki3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JR7d/zUv3+R6duoqX1nmAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9STOSSAAAYAP///wAAAAAAAAAAAAAAAAAAAAAAsrKzAGZlaABubXAqLi0x5R8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/KSgs9mFhZEgAAAAAT05RhyMiJv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8pKCzFZWVoE1xcXwD///8A////AAAAAAAAAAAAAAAAAAAAAAD///8ANzY6ADk4 + PBgjIibTIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JiUp/ldWWWQhICQAMCnf8iYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhu7+99QoAALYATEbjiygh3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zIs3+5wa+k3WFPlAF1Y5kEuJ97zJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAYAP///wAAAAAAAAAAAAAAAAAAAAAA2NjZAHFw + cwB5eHshMTA03R8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JyYq+lxbXlQbGh4AWFdbcCUk + KP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8mJSnbU1NWJkVERwC6ursA1NTVAP// + /wAAAAAAAAAAAP///wD///8APj1BAEFBRB0kIyfXIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/JSQo/lRTVmUdHCAAMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhu7+9 + 9Qr///8CSELinicg3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zAp + 3/VoY+dHUErkAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAYAP// + /wAAAAAAAAAAAAAAAAAAAAAA8vLyAHp6fACFhIYaNDM21B8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/JiUp/VdXWmIsKy8AY2JlVykoLPofHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8jIibuRURHRgMCBwD///8Ag4KEAMbGxwDT0tMA0tLSALm5ugAzMzYAPj5BAEhHSiokIyfhIB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JSQo/lVUV2UeHSEAMCnf8iYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/QTvhu8C+9Qro5/sHRD/isCYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y0m3vthXOZYRD7iAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9STOSSAAAYAP///wAAAAAAAAAAAAAAAAAAAAAA/Pz8AIODhQCRkZMTNjU4yh8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JSQo/1RTVnArKi4AcHByPC4tMe8fHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8hICT7ODc7ef///wNpaGsAcnF0AMbGxwDT09QA09LTALi4 + uQBzcnUAAAAAAEVER0YjIibvIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JiUp/VhY + WmMjIiYAMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhu8TC9gmuq/INQDnhwCYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ysk3v9ZVOVqMyzfAF1Y + 5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAYAP///wAAAAAAAAAAAAAA + AAAAAAAA////AJCQkgClpacNODc7vyAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IyIm/05O + UX0QDxMAiomLJTY1Od4fHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Kyouvmtq + bScAAAAAfXx+AMvKywDa2tsA2dnaALu7vABSUVQA////BDk4O30hICT7IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/JiUp/FlYW1swLzMAMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/QTvhu8nI9wmPi+0UOzTgziUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yki3f9TTeR8EgvaAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9STOSSAAAYAP///wAAAAAAAAAAAAAAAAAAAAAA+fr5AKOjpADJycoIOzo+syAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IiEl/0lITIkAAAAAtLS1EkFBRMUgHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IyIm7jc2OYNiYmUj////AQAAAAAAAAAAAAAAAAAAAADw8PEDT05SRSop + LcYgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/KCcr+V5eYFFCQUQAMCnf8iYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhu9LQ+Ah/e+sfNzHg2iUe3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ycg3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9NSOOPAADMAF1Y5kEuJ97zJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAYAP///wAAAAAAAAAAAAAAAAAAAAAA////ALy8 + vQD///8EPz5BpyAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk/0ZFSJf///8B////BVBP + UqIiISX/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/ycmKtk2NTiCNTQ4R0JC + RUBOTVFATUxPQDw7P0AwLzJLMTA0pSIhJfcgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/Kikt9GZmaEVSUlUAMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhu97d + +gd3cuosNS7f5iUe3f8mH93/Jh/d/yYf3f8mH93/KCHd/y4n3v8mH93/Jh/d/yYf3f8mH93/Jh/d/ycg + 3f9JQ+KhAAAAAF1Y5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAYAP// + /wAAAAAAAAAAAAAAAAAAAAAA////AN/f4AD///8BQ0JFmyEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/ISAk/0NCRqX///8EAAAAAGJhZHcnJir+IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8jIibsJiUpwS8uMrs2NTm7NTQ4uywrL7skIyfFISAk8yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Li0x7XBwcjZkY2YAMCnf8iYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/QTvhu+/v/Qduaeg7Mivf8CUe3f8mH93/Jh/d/yYf3f8mH93/Life/kI8 + 4fomH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f9EPuKz////BV1X5kEuJ97zJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9STOSSAAAYAP///wAAAAAAAAAAAAAAAAAAAAAA////AP///wAAAAAAR0ZKjiIh + Jf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/0A/QrLa2tsHW1pdAHh3ekgvLjLyHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP+IB8j+yEgJPoiISX6IiEl+iEg + JPogHyP7IB8j/iAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/MzI24YOC + hCZ+fYAAMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhu////wZlYOdKLyje9iUe + 3f8mH93/Jh/d/yYf3f8lHt3/Mivf+E9J4+UmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f9AOeHDycf3C1xX + 5kAuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAYAP///wAAAAAAAAAAAAAA + AAAAAAAAAAAAAP///wAAAAAASUlMfyIhJf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/zw7 + P720tLUMlJSWAJ6eoCI/PkHXHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/PDs/0KSjpReioqQAMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/QTvhu////wZbVuVaLCbe+yYf3f8mH93/Jh/d/yYf3f8lHt3/NC7f7ldR5cgnIN3/Jh/d/yYf + 3f8mH93/Jh/d/yUe3f87NeDRnZrwFFxX5kAuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9STOSSAAAYAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATUxPcSQjJ/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zk4O8idnJ4RqKipAPj4+AlUU1aqIiEl/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/R0ZJteLi4wrKycoAMCnf8iYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhu////wdUTuRrKiPe/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/NjDg5FxX5akoIt3+Jh/d/yYf3f8mH93/Jh/d/yUe3f83MeDdh4PsHlxX5j8uJ97zJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAYAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAHd3 + eQAeHSEAUlFUZSUkKP4gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zU0ONKMi40XjYyOAAAA + AABwcHJuLCsv+h8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8jIib/VVRYj////wH///8AMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhu/// + /whPSeN+KSLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/ODLg2GJd5osqI979Jh/d/yYf3f8mH93/Jh/d/yUe + 3f80Lt/oenbqK11X5j4uJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAYAP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAALOztAAzMjYAWFdaWCcmKvsgHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/zIxNdt/foEffHt+AHp5fACYmJoxPj1B3x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8qKi37bGtuYxEQFAAAAAAAMCnf8iYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/QTvhu/z8/wpLRuOSJyHd/yYf3f8mH93/Jh/d/yYf3f8lHt3/PDXgzGlk + 6HAsJd75Jh/d/yYf3f8mH93/Jh/d/yUe3f8xK9/wb2roOV1Y5j4uJ97zJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9STOSSAAAYAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAANnZ2gBDQkUAXV1gTCgo + K/cfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zAvM+R4d3oocnJ0ALa2twDk5OULXl1goyUk + KP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv84NzvmjIyONXNy + dQDKyssAMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTrhu+Hh+w5HQeKlJyDd/yYf + 3f8mH93/Jh/d/yYf3f8mH93/PznhvnFs6VcuKN71JR7d/yYf3f8mH93/Jh/d/yUe3f8vKN73ZmHnSl9a + 5j0uJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAYAP///wAAAAAAAAAAAAAA + AAAAAAAAAAAAAPDw8QBQT1IAYmJkQCopLfMfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/y4t + MetvbnEyZWRnAP///wAAAAAAhIOFVDo5Pe0fHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yEgJP9QT1K2xMTFEaioqQD///8AMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/QDrhu8fF9hNCPOG1Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Qz3ir3p26kIxKt/vJR7d/yYf + 3f8mH93/Jh/d/yYf3f8sJt78XlnmW2Bb5j0uJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9STOSSAAAYAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP39/QBdXF8AaWhrNSwrL+0fHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/ysrLvFnZmk8V1ZZANzc3QCpqaoAyMfIF1pZXKkqKS3/Hh0h/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hh0h/zEwNPhxcHNv////AP///wB7e30AMCnf8iYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QDrhuq+s8xo9NuHEJh/d/yYf3f8mH93/Jh/d/yYf + 3f8nIN3/SELin4WB7C80Ld/mJR7d/yYf3f8mH93/Jh/d/yYf3f8qI97/VlHlbGJd5j4uJ97zJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAYAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP// + /wBram0AcnF0LC8uMeYfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/ykpLPZgYGNHSklMAOnp + 6QD///8AAAAAAJKRk0tFREjYJiUp/SEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8hICT/JyYq/VBP + U8arq6wojo2PAL69vwD///8AMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QDrhupyY + 7yM5MuDSJR7d/yYf3f8mH93/Jh/d/yYf3f8oId3/TUfjjpWS7iA3MeDcJR7d/yYf3f8mH93/Jh/d/yYf + 3f8pIt3/UUvkf2Vg5z8uJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAYAP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wB3dnkAenp8IjEwNN4fHiL/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/ygnK/pcW15UOzo9AMjIyQD///8AqamrANjY2QqEg4VuTEtO5CYlKf8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8mJSn/Tk5R442Nj17///8EysnKAMHBwgD///8AMCnf8iYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/QDrhuY6K7S82MODfJR7d/yYf3f8mH93/Jh/d/yYf3f8pIt3/Uk3kfa6s + 8hQ7NODQJR7d/yYf3f8mH93/Jh/d/yYf3f8nIN3/TEbjkmdi50IuJ97zJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9STOSSAAAYAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJiIoAg4KEGjMy + NtUfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yYlKf1YV1phJyYqAJiXmQD///8A////AFpZ + XADNzM0jd3d5vC4tMf8fHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8tLDD/d3Z5xtXV1imJiIoAFhUZAL++ + vwD+/v4AMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QDrhuYJ+6zwzLd/qJR7d/yYf + 3f8mH93/Jh/d/yYf3f8rJN7/V1LlbODf+gs/OeHDJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/R0HipGpl + 6EYuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAASAMbGvwBaWlwATEtPAExM + TwBMTE8ATExPAExMTwBWVVgAtbS2DTY1OcofHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yUk + J/9TUlVuCAcLACsqLgBtbXAA////AAAAAACOjY9IU1JV1ignK/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8nJir/T05R4H18f2n///8IycnKANra2wD///8AMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/QDrhuHdz6kswKt/yJR7d/yYf3f8mH93/Jh/d/yYf3f8tJt77XVjmWv///wREPuK0Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/QjzhtWxn6EsuJ97zJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9STOSSAAA3ALq6vQKbmpwalJSWI5WUliKVlJYilZSWIpWUliKVlJYhl5eZLzw7P8sfHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMiJv9NTVB7AAAAAP///wC4uLkAo6KkAL+/wBFeXWClKCcr/x8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/JSQn/1BPUs+WlZc7AAAAAP///wDLy8wAMCnf8iYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhuGxo6FotJ973Jh/d/yYf3f8mH93/Jh/d/yUe + 3f8vKN72ZF/nSgAALgBIQuKjJyDd/yYf3f8mH93/Jh/d/yYf3f8lHt3/PTfhxGxn6FItJ97yJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAABlALe2uAd5eHptbGxulGxsbpJsbG6SbGxukmxs + bpJsbG6Rbm5wlzw8P+MfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yIhJf9JSEuIAAAAAP// + /wD///8AYWBjAIWEhz45ODzoHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/yop + Lf5paWuV6+vsCru7vADg4OAAMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QTvhuGJd + 52orJN78Jh/d/yYf3f8mH93/Jh/d/yUe3f8xKt/wbGfoOwAAygBNSOOSKCHd/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/OTPg0mtm6FwtJt7yJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAABwALCv + sQtEQ0azLSww9S0sMPItLDDyLSww8i0sMPItLDDyLi0w8iYlKfsgHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yEgJP9HRkmX////Afb29gDZ2doAAAAAAF1cX3onJir+Hx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/9BQEPdmJeZNHl4ewDU09QAMCnf8iYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/QjzhuV1Y5n4pIt7/Jh/d/yYf3f8mH93/Jh/d/yUe3f80Ld/ndXDpLQwE + 2QBSTeSAKSLd/yYf3f8mH93/Jh/d/yYf3f8lHt3/NjDg3mll6GctJt7xJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9STOSSAABwAM3Mzgg+PUC5ISAk/yEgJP8hICT/ISAk/yEgJP8hICT/ISAk/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJP9DQkak////A8/P0ACurq8A0tLTC0hH + SrEhICT/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8rKi78ampseP// + /wD///8AMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/RD7iullT5ZIoId3/Jh/d/yYf + 3f8mH93/Jh/d/yUe3f83MeDdgHzrITEr3wBYUuVuKyTe/yYf3f8mH93/Jh/d/yYf3f8lHt3/Myzf6Gdi + 53UtJt7xJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAABjAP///wVBQESqIB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8/PkGw5eXlB7KyswCKiowAlpaYIDo5PdgfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/0hICT4IiEl+CIhJfghICT4IB8j/CAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8hICT/Tk5RucvLzBK1tbYAMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/RT/ivVNO5KUnIN3/Jh/d/yYf3f8mH93/Jh/d/yUe3f87NeDRj4zuF0dB4gBeWOZdLCbe/CYf + 3f8mH93/Jh/d/yYf3f8lHt3/MCnf8GRf54QtJ97wJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9STOSSAABJAP///wFEREecISAk/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/87Oj68t7e4C52cngBpaGsAenl8OTAvM+4fHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk8yMiJs8lJCi5KCcruignK7olJCe5IiElySEh + JPEgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Ojk855GQkjR9fX8AMCnf8iYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/RkDiwU1H47YmH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8/OeHEqabyD1pU5QBkX+dMLyje9yUe3f8mH93/Jh/d/yYf3f8mH93/LSbe9WBb5pQuJ97wJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAsAAAAAABGRUmNIiEl/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv84ODvHn56gEY2M + jgBDQkYAZmVoUSopLfkfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8hICT7KikstTo5 + PFQ8Oz8uTk1QL01MUC86OTwuMjE1SisrLrAhICT3IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/Kyou+m1sb2APDhMAMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/R0HixkZB + 4sUlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f9DPeK10tD4CWlk6ABrZ+g8MSrf8CUe3f8mH93/Jh/d/yYf + 3f8mH93/KyTe+lxW5aUuJ97wJh7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAbAAAA + AABKSUyAIyIm/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv82NjnSkJCSGIWEhgAdHCAAWFdaZiYlKf4gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8pKCzjSUlMT1hYWw1lZGcEjYyOBIyLjQReXWAET05RC0pKTUAsKy/FIB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IyIm/1ZWWZD///8CMCnf8iYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/SUPizkI84dQlHt3/Jh/d/yYf3f8mH93/Jh/d/ycg3f9HQeKk////BHZx + 6QB0cOkuNC3f6CUe3f8mH93/Jh/d/yYf3f8mH93/KSLd/FhS5bgvKN7xJR7d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9STOSSAAAVAAAAAABPTlFzJCMn/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv80Mzbbg4OFH3x8fgAAAAAAT05RdiQj + J/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/83Njq5n56gFi0sMABDQkYAWllcAFlY + WwBCQUUAGBcbAN/f4AdDQkWAIyIm+iAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/0ZF + SLjLy8wOMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/SkXj2T854eIlHt3/Jh/d/yYf + 3f8mH93/Jh/d/ycg3f9KROORAAAAAH976wB/e+siNzDg3iUe3f8mH93/Jh/d/yYf3f8mH93/KCHd/lRO + 5MswKd/zJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAUAB8eIQBTUlZmJSQo/iAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv8wLzPjeHd5J3RzdgAAAAAASklNhCIhJf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/9AP0KK////Av///wBAQEMAVFNWAFNTVgBFREcAAAAAACEgJABoZ2pCKCgr5yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zo5PNaWlpgjMCnf8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/TEbj5Tw14O4lHt3/Jh/d/yYf3f8mH93/Jh/d/ygi3f9NSON+AADKAIiE7ACNiu0YOjTg0iUe + 3f8mH93/Jh/d/yYf3f8mH93/JyDd/1BK5N0xK9/2JR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9STOSSAAAWADY2OABXVllYJyYq+yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8uLTDqbm1wMGtqbQAAAAAASUhMjiIhJf8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJP01NDhoAAAAAP///wB+foEA////AP///wDJycoAxcXGAHFw + cwCKiowbLi0wxx8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zEwNOt9fH8/MCnf8iYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/S0Xj8jgy4PglHt3/Jh/d/yYf3f8mH93/Jh/d/yoj + 3v9TTuRsDQXZAJSR7gCjoPEQPjfhxCYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/0xG4+8zLN/6JR7d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSSAAAZAElISwBdXWBNKCcr9x8eI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8rKi7wZ2ZpO2Bf + YgAAAAAAR0ZKlCIhJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJPwqKS1cGRgcAA8O + EgC0tLYA////AP///wDNzc4A////AISEhgCqqqsHLCsvpSAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/ysqLfdpaGtcMCne8iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/RkDi+jQt + 3/0lHt3/Jh/d/yYf3f8mH93/Jh/d/ywl3vxbVuVcMSvfAKil8QDKyfcJQTvhtCYf3f8mH93/Jh/d/yYf + 3f8mH93/JR7d/0U/4vsyLN/9JR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9RS+SRAAA/AFhX + WQBjYmVBKikt8h8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv8pKCz1YWBjRlJRVAD///8ARkVJlSEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yEgJPwsKy5fExIWAAAAAAD8/PwAAAAAAAAAAAD///8A1tbXAKSjpQAAAAAALCsviyAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yYlKf1aWVx4MCne8SYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/OzXg/i4n3v8mH93/Jh/d/yYf3f8mH93/JR7d/y4o3vdjXudNSELiAMXE + 9gD///8ERkDipCcg3f8mH93/Jh/d/yYf3f8mH93/JR7d/zky4P8vKN7/JR7d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9QSuSQAABaAGRjZQBpaGs1LCsv7R8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8oJyv5XVxfU0BAQwAAAAAARkZJkyEg + JP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJP4uLTFsAAACAAAAAAD///8AAAAAAAAA + AAAAAAAA////AP///wAAAAAAKikteCAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMi + Jv9QT1OTMCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Lyje/yki3f8mH93/Jh/d/yYf + 3f8mH93/JR7d/zEr3/FsaOg+W1blAPj3/gD///8ASkTjkycg3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ywm + 3v8pIt7/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9PSuOQAABkAG5tbwBvb3ErLi0x5h8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8mJSn9WFdaYCopLQAAAAAAR0ZJjCIhJf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8wLzKAAAAAAObm5gDCwsMA////AAAAAAAAAAAA////AAAAAAAMCg8AJycqbiAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJP9JSEysMCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JyDd/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zQu3+p3c+oxbmnoAP///wAAAMUAT0njgSgi + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9QSuOQAABjAHd3eAB3d3kiMDAz3h8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8lJCj/U1JVbQoJDQAAAAAARkVIgiIhJf8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8xMTSd4+PkBqSjpQDPz9AA8/P0AP///wD///8A8fHyAAAA + AAALCQ4AJyYqbiAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/9DQkbBMCne8SYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zgx + 4OCEgOwlf3vrAAAAzwAFANgAVU/kbyoj3v8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9QSuOQAABjAIKCggCDgoQaMzI21R8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8jIib/Tk1QegAA + AAAAAAAAS0pNeSMiJv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8xMDTEmZiaGYSE + hgC5uboA9PT0AP///wD///8A7e3tAP///wAAAAAAMC8zfiAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8+PUDTMCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/JR7d/zs14NSSj+4ajYntAJaS7gAuKN4AW1blXiwl3vwmH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9QSuOQAABjAI+O + jgCQkJITNjU4yx8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8iISX/S0pNiAAAAAALCQ4AUE9TbSQjJ/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8pKCzmZWRnQQAAAQC6ursA////AP///wD///8A////AIqKjADl5eUJMzI2pCAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/86OT3hMCne8SYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/z444cakofERlpPvANHP + +ABGQOIAYl3mTi4n3vglHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9QSuOQAABjAJ+enQCkpKYOODg7wSAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8hICT/R0ZKlv///wAuLTAAVlVYXyYl + Kf0gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8iISX6Pj1BiIGBgxUAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAABhYGMzLCsv0SAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv83NjnrMCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/0E74bXCwPUJmpfvAPb2/gBZU+UAamXoPzEq3/IlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9QSuOQAABjALW1sgDHxscJPDs/tiAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8hICT/Q0JFo////wNIR0oAXVxfTygnK/gfHiP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/KSks2EhIS2BhYGMka2ptFXh4ehNtbW8UcG9yHFhXWig5OTyCIyIm9iAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8zMzbyMCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JyDd/0U/4qX///8EpaLxAP39/wBpZegAc2/pMTQt + 3+olHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9QSuOQAABjANDQywD///8FPz9CqSAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Pz5Br+/v8AZgX2IAZmVoPisqLvEfHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk+yYlKdM3NjqlPz5BfU1MT3hDQkZ/QD9ClTIy + Na4jIibdIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8yMTX3MCne8SYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JyDd/0lD + 4pP///8BtrT0AP///wB7d+oAf3vrJDcw4OAlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9QSuOQAABjAPHx6AD///8CQkFFnCEgJP8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Ozs+u76+ + vwt7e30AdXR3LjAvMugfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEg + JPslJCjvJiUp3ikoLNwoJyviJyYp6iQjJ/IgHyP8IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv8yMTX6MCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/KCHd/0xH44EAAMAA19X5AP///wCIhOwAjYntGjo04NQlHt3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9QSuOQAABjAP// + /wAAAAAARENGkB8eIv8eHSH/Hh0h/x4dIf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/OTg8x6WkphCQkJIAioqMHjY1ONkfHiL/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/IB8j/yAfI/8gHyP/Hx4i/x8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8yMTX7MCne8SYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KiPe/1JM5G8AANcA////AP// + /wCRju4AnpvwET034cYlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9QSuOQAABjAP///wAAAAAAUVBTfi8uMvwrKi74KSgs+yUkKP8hICT/Hx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/NjU50ZOSlBeYl5kArKytED08 + P8QgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv8yMTT4MCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/LCXe/FpV5V8rJN4A////AP///wCZle8Avrz1CkE74bcmH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9QSuOQAABjAP///wA5ODwAdHN2Wl9e + YctVVVjDTUxP0Tw7PucqKS35ISAk/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/MzI22oODhR6Li40A////BkZFSaghICT/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8zMjXyMCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life+GNe509HQeIAT0rjAP///wCjoPEA////BEU/ + 4qYnIN3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9QSuOQAABjAP///wCOjY8Ao6KkGJqZmzuNjI41h4aJQHp5fGVgYGKtOTg88yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/MC8z4nh3eiZ5eHsAAAAAAFRTVoYjIyb/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv83NjnrMCne8SYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/MSrf8mtn + 6EBaVeUAsa7zAAAAAAC1svMA////AUpE45UnIN3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9QSuOQAABjAP///wD///8A////Af///wT///8C////Bc7O + zxSNjI47ZWVokzg3O/EfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Li0x6nFx + czBqaWwAFhUZAGRkZmApKCz7Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/88Oz7fMCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/NC3f63Zx6TJsZ+gA4uH6AAAAAADV0/gAAAC1AE5J44QoIt3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9QSuOQAABjAP// + /wDv7+8A8vLyAPDw8ADr6+sA1tbXAJ2cngAAAAAAt7e4LlxcX6krKi78Hx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/LCsv8GtrbTtdXF8AaGhqAHx8fjoyMTTsHx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/9CQUTMMCne8SYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/ODHg4oN/7CZ+eusA/f3/AAAA + AAD///8AAADVAFNO5HEqI97/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9QSuOQAABjAP///wDp6ekA6urrAOrq6gDk5OQA1tbWALCvsQD///8ACgkOAKGh + o0NEQ0fZISAk/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Kikt9WRkZkdQT1IAoJ+hAKem + qBtAP0LQHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEg + JP9JSEuyMCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/OzXg1pKP7huSj+4A////AAAAAAD///8AKCHdAFpV5WAsJd78Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9QSuOQAABjAP///wDp6ekA6urrAOrq + 6gDk5OQA1tbWALGxsgD///8AoqKkAP///whsa26GKikt/B8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/KCcr+V1dYFJAP0IA2NjZAP///wdVVFekIiEl/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMjJv9TUlWQMCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/PTfhyKSh8RGmo/EA////AAAAAAA8NuAARD7iAGFc + 5lAuJ974Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9QSuOQAABjAP///wAAAAAAAAAAAAAAAAAAAAAA////AN3d3gD19fYA////ADo5PQCUlJY2Pj1A3B8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JiUp/FdWWV8pKCwA////AAAAAABwb3JrLCsu/B8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4j/ygoK/pjYmVrMCne8SYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/QDrhuMTC + 9gq8uvQA////AAAAAACtqvIAWFPlAGlk6EAwKt/yJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9QSuOQAABjAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP// + /wDw8PEA9fX1AMjIyQD///8KV1daoyQjJ/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JSQn/1JR + VGsHBgoA////AHV0dgCUlJY0PDw/4R8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/zEwNOt7en1DMCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/RD7ip////wTa2fkA////AAAAAADi4foAaGPnAHJu6TIzLd/rJR7d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9QSuOQAABjAP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A5OTlAAAAAAAAAAAAdnV4YC0sMPYfHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IyIm/05NUHkAAAAA////AMHAwgDk5OQNVlVYqiQjJ/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/z8+Qs2ioqMfMCne8SYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8nIN3/SUPilv///wH///8A////AAAA + AAD8/P8AeHTqAH156yY2MODhJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9QSuOQAABjAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxMPFANzc + 3ACCgoQAl5eZJzo5PdofHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IiEl/0tKTYcAAAAA09PUAP// + /wAAAAAAfXx/XzIxNfMfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IyIm/1RT + Vpv///8GMCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8oId3/TEbjgwAAwAD///8A////AAAAAAD///8AjIntAIyJ7Rs6M+DWJR7d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9QSuOQAABjAP///wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAoaGjAP///wCwsLEA4ODgC05NULEhICT/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IiEl/0ZFSZX///8BuLi5ADY1OACMjI4AsbCyHlJRVL8iISX/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/MC8z9nd2eVsAAAAAMCne8SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI97/UUvkcQAA1gB3cuoAAAAAAAAAAAD7+/4AoZ7wAJ+c + 8BE9NuHIJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh + 3f9QSuOQAABjAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////APDw8QD09PQAAAAAAF9f + Yn0mJSn/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk/0JBRaH///8Dp6aoAP///wDi4uIA////Anl4 + e2Q5ODvvHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8hICT/S0pOyaWlpiKHhogAMCne8SYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8rJd79V1LlYCYf + 3QDFw/YAAAAAAAAAAAD///8Aurf0AMC+9QpAOuG5Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9QSuSQAABjAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPPz8wAAAAAARENGAHNydUwtLDD0Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/z8+ + Qa7k5OUGnZyeAP///wCWlpgAlJSWAL29vhxbWl2nLSwv/B8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv8zMjX3b29xev///wT19fUALyje8iUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yUe3f8tJt75YFvmUUA54QChnvAAAAAAAAAAAAD///8A2dj5AP///wVEPuKpJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh7d/ycg3f9PSeOQAABiAP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADn5+cAhoaIAI6Njyc2NTneHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/zw7P7q5uLoLl5aYAP///wD///8A////AAAAAACZmZtES0pNzSgn + K/0gHyP/Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/ygnK/1UU1bBsbGyKYaFhwCop6kALyne8iUe3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f8wKd/zaWTnQlZQ5ABAOuEAAAAAAAAA + AAD///8A////AP///wFIQuKXJyDd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9PSuOQAABjAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAD09PQAtbW2AL6+vw9BQUTAIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/zo5PMehoaMQkpKUAP// + /wD///8A////AK6urwDv7+8GjIuOXktKTdomJSn+IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JCMn/0pJTd2SkZNW////A9DQ + 0QClpKYAPDbh8DMs3/4zLd/9My3f/TMt3/0zLd/9My3f/TMt3/0zLd/9My3f/TMt3/0zLd/9My3f/TMs + 3/8+OOHpdnLqMmtm6AB+eusAAAAAAAAAAAD///8A////AAAAwQBVUOSENS/f/zMt3/4zLd/+My3f/jMt + 3/4zLd/+My3f/jMt3/4zLd/+My3f/jMt3/40Ld/+NC7f/zYw4P9aVOWOAACHAP///wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADJycoA4+PkAP///wNOTVGdIyIm/yEgJP8hICT/ISAk/yEg + JP8hICT/IB8j/zc2OtWPj5EXiomLAAAAAAD///8A////AP///wA2NTkAvr2/En9+gF9VVVjIMjE1/SEg + JP8eHSH/Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Hh0h/x8e + Iv8sKy//T05R1n9+gGfGxscQamlsAAAAAABjY2YAV1Hljk9J45dPSeSWT0nklk9J5JZPSeSWT0nklk9J + 5JZPSeSWT0nklk9J5JZPSeSWT0nklk5J45dYUuWGh4PsGYB86wCxrvMAAAAAAAAAAAAAAAAAFg7bAA0F + 2QBsZ+hIUUzkmFBK5JdQSuSXUErkl1BK5JdQSuSXUErkl1BK5JdQSuSXUErkl1BK5JdRTOSYVlHlnVhS + 5Z9zb+lWAACzAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////AAAA + AABsa25oS0pN2klIS9pJSEvaSUhL2klIS9pJSEvaSEdL3FlYW7ebmpwWmZiaAAAAAAD///8A+Pj4APT0 + 9AD///8AWVhbAOHh4hKAf4JWWVlcoUNCRto0Mzb5KCcr/yIhJf8fHiL/Hh0h/x4dIf8dHCD/HRwg/x0c + IP8eHSH/Hh0h/yAfI/8lJCj/Li0x/j49QehUU1a0eHd6ZNDQ0RdQT1IA////AP///wD///8AoZ7xI52Z + 8CWdmvAlnZrwJZ2a8CWdmvAlnZrwJZ2a8CWdmvAlnZrwJZ2a8CWdmvAlnZrwJZ2Z8CWinvEgvbr1BLq3 + 9AD7+/8AAAAAAAAAAAAAAAAA5eT7AJGO7gCvrfMQoJzwJp6b8Caem/AmnpvwJp6b8Caem/AmnpvwJp6b + 8Caem/AmnpvwJp6b8Cain/EnrKnyLK2q8i24tfQXZmHoAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD///8A5ubmAHJydACamZssgYCDcH9+gXJ/f4Fyf3+Bcn9/gXJ/f4Fyf36Ac4iH + iWCvr7AMr66wAAAAAAAAAAAA/Pz8AOjo6QD5+fkA////AJ+foQD///8Erq6vMnRzdnRWVlmqRENGyzs6 + PuE2NTjvMC8z8y8vMvowLzP9MC8y/TAvM/wvLjL3MjE18To5POpAP0PXTk1Rumloa4mcm51F////CouL + jQD///8A////APn5+QD///8AiobtAIWA7ACFgewAhYHsAIWB7ACFgewAhYHsAIWB7ACFgewAhYHsAIWB + 7ACFgewAhYHsAISA7ACKhu0ApqPxAKKf8QDV1PkAAAAAAAAAAAAAAAAAraryAG1o6ACXk+8AhoLsAISA + 7ACFgOwAhYDsAIWA7ACFgOwAhYDsAIWA7ACFgOwAhYDsAIWA7ACEgOwAgn7sAIN/7ACWku8AAADSAP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wD///8B////Bf// + /wb///8G////Bv///wb///8G////Bv///wX///8B////AAAAAAAAAAAAAAAAAP///wDw8PEA////AAAA + AADd3d4AVVRXAP///wq9vL01kZGTbHp6fKNoaGrKVVVY2FNSVe5TUlX3U1JV91NTVvZTUlXjXV1f0nRz + dr2Ih4mJqamqTOrq6hcAAAAAysrLAP///wD///8A8fHxAP///wAAAAAAAAAAAABwABwAAAB/AAAAAABw + ABgAAAA/AAAAAABwABAAAAAfAAAAAABwABAAAAAPAAAAAABwAAAAAAAHAAAAAABwAAAAAAAHAAAAAABw + AAAAAAAHAAAAAABwAAAAAAADAAAAAABwAAAAAAADAAAAAABwAAAAAAADAAAAAABwAAAAAAADAAAAAABw + AAAAAAABAAAAAABwAAAAAAABAAAAAABwAAAAAAAAAAAAAABwAAAAAAAAAAAAAABwAAAAAAAAAAAAAABw + AAAAAAAAAAAAAABwAAAAAAAAAAAAAABwAAAAAAAAAAAAAABwAAAAAAAAAAAAAABwAAAAAAAAAAAAAABw + AAAAAAAAAAAAAABwAAAAAAAAAAAAAABwAAAAAAAAAAAAAAB4AAAAAAAAAAAAAAB4AAAAAAAAAAAAAAB4 + AAAAAAAAAAAAAAB4AAAAAAAAAAAAAAB4AAAACAAAAAAAAAB4AAAAHAAAAAAAAAB4AAAAHgAAAAAAAAB4 + AAAAHwAAAAAAAAB4AAAAHwAAAAAAAAB4AAAADwAAAAAAAAB4AAAABgAAAAAAAAB4AAAAAAAAAAAAAAB4 + AAAAAAAAAAAAAAB4AAAAAAAAAAAAAAB4AAAAAAAAAAAAAAB4AAAAAAAAAAAAAAB4AAAAAAAAAAAAAAB4 + AAAAAAAAAAAAAAB8AAAAAAAAAAAAAAB8AAAAAAAAAAAAAAB8AAAAAAAAAAAAAAB8AAAAAAAAAAAAAAB8 + AAAAAAAAAAAAAAB8AAAAAAAAAAAAAAB8AAAAAAAAAAAAAAB8AAAAAAAAAAAAAAB8AAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAA + AAAAA4AAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAA + AAAAAAAAAAAQAAAAAAAAAAAAAAAQAAB4AAAAAAAAAAAQAAB8AAAAAAAAAAAQAAB+AAAAAAAAAAAQAAB/ + AAAAAAAAAAAQAAB/AAAAAAAAAAAwAAB/AAAAAAAAAAAwAAB/gAAAAAAAAAAwAAB/wAAAAAAAAAAwAAB/ + wAAAAAAAAAAwAAB/wACAAAAAAAA4AAB/wACAAAAAAAA4AAB/wADAAAAAAAA4AAB/4ADgAAABKAAAAIAA + AAAAAQAAAQAgAAAAAAAAAAEAEwsAABMLAAAAAAAAAAAAAKuo8gCnpPEAp6TxAKek8QCnpPEAp6TxAKek + 8QCnpPEAp6TxAKek8QCnpPEAp6TxALCt8wDQzvgAy8n3AO3s/AAAAAAA////AMnH9wDh4PoAr63zAKek + 8QCnpPEAp6TxAKek8QCnpPEAp6TxAKek8QCnpPEAp6TxAKuo8gDAvvUAt7X0ALOx8wAAAAAAAAAAAN/e + +gD///8At7T0AKil8QCnpPEAp6TxAKek8QCnpPEAp6TxAKek8QCnpPEAp6TxAKek8QCnpPEAqqfyAL27 + 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 + AAAAAAAAAAAAAAAAAAD///8AAAAAAF5eYGknJir9Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv8pKCz6ZmZoXSUkKAD///8AAAAAAAAAAAD19fUA9PT0AP///wB3d3kA1NTUIXR0 + dpk5ODzuJCMn/iAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8hICT/JyYq/EJB + ROZ7e32Qz8/PIEJBRAD///8A5OTlAP///wD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAA0Ld/rJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f88NeDjioftKn566wDS0fgAAAAAAEI7 + 4QBeWeYAeHTqQTQu3+8lHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8pIt3/VE/km/// + /wS2tPQA////AAAAAACwrfMA////Ak1H45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/y4n3v9pZOdzAADOAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAkIycAZWRnXCko + LPkgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/ygnK/xiYWRqAAAAAP// + /wAAAAAA////AO/u7wC7ursAycjJAP///wmKiYtoS0pO2SgnK/8eHSH/Hx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8eHSH/LSww/01MT9R+fYBv6urqE5KSlAD///8A////AP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAADQt3+smH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JR7d/zw14OOKh+0qfnrrANLR+AD///8A////AEE74QBybelSMSvf9iUe3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ycg3f9PSeOs6ur8CaSh8QD///8AAAAAALCt8wD///8CTUfjlCgh + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2lk53MAAM4A////AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEVERwBsa25QKyou9h8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/JiUp/11dYHcAAAAA////AP///wCBgIIA8vLyAPj3+AAqKS0At7e4J2hn + argsKy/+Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/Kyou/l5dYMWko6VC////A6+vsQAAAAAA////AOzs7AAAAAAAAAAAAAAAAAAAAAAANC3f6yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/PDXg44qH7Sp+eusA0tH4AP// + /wD///8ABgDYAGpm6GQvKN77Jh7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/0pE + 47zBvvUPlpPvAP///wAAAAAAsK3zAP///wJNR+OUKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8uJ97/aWTncwAAzgD///8AAAAAAAAAAAAAAAAAAAAAAAAAAABIR0oAWVhbAHJx + dEUuLTHxHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8lJCj/WFdahAAA + AADe3t4A////ALy8vQD8/PwA7u7vAP///wSFhIdsQD9C6SIhJf8fHiL/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8iISX/ODc68WxrbpnW1tYehYSGAAAA + AAAAAAAA7OzsAAAAAAAAAAAAAAAAAAAAAAA0Ld/rJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yUe3f88NeDjioftKn566wDS0fgA////AP7+/wAAAL4AY17ndiwm3v4mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/RT/iy6im8ReNiu0A9fX9AAAAAACwrfMA////Ak1H + 45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9pZOdzAADOAP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAIyMjgBnZ2kAeXh7OjAvM+wfHiL/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMiJv9SUlWR////AcTExQD///8A3d3dAAAAAACFhIcAv7/AHWRj + Zq8pKCv/Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv8jIib/TUxP3JKRk1f///8FxMTFALGxswDk5OUA////AAAAAAAAAAAAAAAAADQt + 3+smH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zw14OOKh+0qfnrrANLR + +AD///8A1tX5AP///wBbVuWHKiTe/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe + 3f9AOuHYmJXvIYaC7ADk4/sAAAAAALCt8wD///8CTUfjlCgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Life/2lk53MAAM4A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAtbW2AHJy + dACAgIIvMzI25R8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IiEl/05N + UJ3///8EsbCyAP///wDR0dEA////AAAAAACZmJpNQkFE5CEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8tLDD6aWhrq9PT + 1BympqcAfHt+AOjo6QD///8AAAAAAAAAAAAAAAAANC3f6yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/PDXg44qH7Sp+eusA0tH4APj4/gC3tfQA////A1RO5JcpIt3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zs14OOLh+0te3fqAL689QAAAAAAsK3zAP// + /wJNR+OUKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/aWTncwAA + zgD///8AAAAAAAAAAAAAAAAAAAAAAAAAAADS0dIAenp8AImJiyY3NjneHx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8hICT/SklMqfX19QihoaMA////AP7+/gDPz9AA////B3Nz + dYcvLjH8Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/yEgJP9IR0vhj46QU////wH19fYA+Pj4AP///wAAAAAAAAAAAAAA + AAA0Ld/rJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f88NeDjioftKn56 + 6wDS0fgA////AKGd8ADy8v0HTUfjpycg3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/NzDg7H976zprZ+gAh4PsAAAAAACwrfMA////Ak1H45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9pZOdzAADOAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAOXl + 5gB/f4EAk5KUHjo5PdUfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/9GRUm2zMzNDJaVlwD///8AuLi5AKWlpgDGxscaV1ZZvyMiJv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/ywr + L/xtbW+b4ODhELS0tQBtbG8A////AAAAAAAAAAAAAAAAADQt3+smH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/JR7d/zw14OOKh+0qfnrrANLR+AD///8Ak5DuAMG/9Q1IQuK4Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f8zLN/zdnLqSlJN5AAAAMoA////ALCt + 8wD///8CTUfjlCgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2lk + 53MAAM4A////AAAAAAAAAAAAAAAAAAAAAAAAAAAA9PT1AIKBhACdnJ4XPDw/yx8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/0NCRsK1tbYRjo6QAP///wD///8AWlpcAJeW + mD5AP0LkHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/IiEl/0tKTdShoaI7SEhLAP///wAAAAAA////AAAA + AAAAAAAANC3f6yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/PDXg44qH + 7Sp+eusA0tH4APTz/QCLiO0AqabxFUQ+4scmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JR7d/zAp3/luaehbKSPeAP///wD///8AsK3zAP///wJNR+OUKCHd/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/aWTncwAAzgD///8AAAAAAAAAAAAAAAAAAAAAAAAA + AAD///8AhYWHAKurrBA/PkLAIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/QD9CzKWkpheIiIoA+vr6AOnp6gAAAAAAenl7aTAvMvkfHiL/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/MzI293x8fnP///8EysrLAM/P0AD///8AAAAAAAAAAAA0Ld/rJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f88NeDjioftKn566wDS0fgA5+f7AIeD7ACal+8gQDrh1iUe + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/LSfe/WZh520AANAA////AP// + /wCwrfMA////Ak1H45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n + 3v9pZOdzAADOAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wCPjpAAxMPFC0NCRrQgHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv88Oz7VmJeZHoOChQDw8PAAxMTFAP// + /wVgX2KVJiUp/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8mJSj/WllcsdLS0xasrK0Avb2/AP// + /wAAAAAAAAAAADQt3+smH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zw1 + 4OOKh+0qfnrrANLR+ADCwPYAfXnrAI6K7Sw8NuDiJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8rJd7/X1rmfwAAegDo5/sA////ALCt8wD///8CTUfjlCgh3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2lk53MAAM4A////AAAAAAAAAAAAAAAAAAAA + AAAAAAAA////AJubnQDt7e0HR0ZKqSEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/zg3O96NjI4mfXx/ANzc3QClpacAysrKEk9OUbohICT/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv9DQkXenJudPxgXGwD///8AxMTFAFdXVwAAAAAANC3f6yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/PDXg44qH7Sp+eusA0tH4AJCN7gBva+kAg3/sOTgx + 4OslHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yoj3v9ZVOWR////AsnH + 9wD9/f8AsK3zAP///wJNR+OUKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8uJ97/aWTncwAAzgD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAD///8Aq6utAP///wRLS06dIiEl/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/NDM35YSDhi92dXcAwsLDAI2N + jwCko6UmQUBE2B8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zAvM/l/f4F2////Aerq + 6gD///8AVlZWAAAAAAA0Ld/rJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe + 3f88NeDjioftKn566wDS0fgADwfZAFhT5QB3c+pHNC3f8iUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/KCHd/1NO5KL///8GsK7zAP///wCwrfMA////Ak1H45QoId3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9pZOdzAADOAP///wAAAAAAAAAAAAAA + AAAAAAAAAAAAAP///wC/vsAA////AlBPU5EjIib/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv8xMTTsfn1/OmtqbQBoaGoAaWhrAIqKjD02NTnrHx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/JiUp/2FgY6jr6+sNvLu9APPz8wD///8AAAAAADQt3+smH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zw14OOKh+0qfnrrANLR+AD///8ANi/fAGxo + 6FcwKd/3JR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8nIN3/TUjjstjW + +Quem/AA////ALCt8wD///8CTUfjlCgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Life/2lk53MAAM4A////AAAAAAAAAAAAAAAAAAAAAAAAAAAA////ANjX2AAAAAAAVVRXhCQj + J/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/y8uMvJ4d3lGXVxfAAAA + AAA3NjoAd3d5Vi4tMfYfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/SUhL0K2t + riSKiowAFRQZAP///wAAAAAANC3f6yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/PDXg44qH7Sp+eusA0tH4AP///wAAANUAY17nZy0n3vwmH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f9IQuLCtbPzEpGO7gD///8AsK3zAP///wJNR+OUKCHd/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/aWTncwAAzgD///8AAAAAAAAA + AAAAAAAAAAAAAAAAAAD///8A+fn5AAAAAABaWVx3JiUp/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/LCsv9nFwc1FHRkoA////AAAAAABmZmltKSgs/R8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv84NzrsjIuNSjs7PgD///8A////AAAAAAA0Ld/rJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f88NeDjioftKn566wDS0fgA7Oz8AAAA + qABdWOZ5KyTe/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/0M9 + 4c+hnvAbiYbtAO/u/ACwrfMA////Ak1H45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/y4n3v9pZOdzAADOAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAF9e + YWonJir9IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8qKS36amlsXSgn + KwD09PUAAAAAAFpaXYIlJCj/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/ywr + L/xzc3V0////AOPj5AD///8AAAAAADQt3+smH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JR7d/zw14OOKh+0qfnrrANLR+ADLyvcA////AVlT5Y0qI97/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/Pjjh3JOQ7iWDf+wA2tn5ALCt8wD///8CTUfjlCgh + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2lk53MAAM4A////AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAfHiIAZWVoXikoLPogHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/ygnK/xiYmRpAAAAAM7NzgD///8DUVFUlSMiJv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JSQn/15dYKD///8IwMDBAP///wAAAAAANC3f6yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/PDXg44qH7Sp+eusA0tH4ALOx + 8wD///8FVE7knygh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe + 3f86M+DniITsMndz6gCtqvIAsK3zAP///wJNR+OUKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8uJ97/aWTncwAAzgD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA/ + QgBsa25SKyou9h8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JiUp/1xc + X3YAAAAAtbW2AP///wZLSk2lIiEl/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8hICT/TExPw7++wBegoKIA5OTkAP///wA0Ld/rJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yUe3f88NeDjioftKn566wDU0vgAoZ7wAN/e+gpOSOOwJyDd/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zYv3+9+eutBZWDnAF5Y5gCwrfMA////Ak1H + 45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9pZOdzAADOAP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4NzsAVlZZAHFxc0YtLDDxHx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8lJCj/WFdagwAAAACkpKYA0dDRCkVFSLEhICT/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8+PUDdmpqbLIGBgwCjo6QA////ADQt + 3+smH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zw14OOKh+0qfnrrANfW + +QCTj+4Aubf0EUhC4r8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/Mivf9XRv6VFIQuIAAACAALCt8wD///8CTUfjlCgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Life/2lk53MAAM4A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAISE + hgBkY2YAdnV4OS8uMusfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yQj + Jv9UU1aR////ApiXmQCysrMNQD9DuiAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/zMyNu+BgIJHUE9SAP///wD7+/sANC3f6yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/PDXg44qH7Sp+eusA2Nf5AIeE7AChnvAYQz3hzSUe3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYe3f8vKN76a2boYRcP2wD///8AsK3zAP// + /wJNR+OUKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/aWTncwAA + zgD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArq2vAG1sbwB7en0vMjE15B8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IiEl/1BPUp7///8EkI+RAKKipBE9PEDCIB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8hICT9ISAk8iEgJOsiISXrIiEl6yIhJeshICTsISAk9SAfI/0gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Kyou+m1tb2UAAAAA////AP// + /wA0Ld/rJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f88NeDjioftKn56 + 6wDV0/gAfnrrAI+L7SI9N+HYJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/y0m3v5iXeZyAADHAP///wCwrfMA////Ak1H45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9pZOdzAADOAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AADLy8wAdHR2AIOChCU1NDjdHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8hICT/S0pOqvj4+QiLio0AnJudFTw8P8kfHiP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/SQjJ+wnJirBJyYqpCsqLqQtLDCkKiktpCYl + KKYnJirLIyIm8CAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8mJSn/XVxfhP///wHU1NUA////ADQt3+smH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/JR7d/zw14OOKh+0qfnrrAMG/9QB0b+kAg3/sLjky4OMlHt3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KyTe/1xW5YQAAAAA2dj5ALCt + 8wD///8CTUfjlCgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2lk + 53MAAM4A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOPj4wB6eXwAjYyOHjg3O9UfHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJP9HRkm1zs7PDIWFhwCVlZcXOzo9zR8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/slJCjTKyouojEwNHEtLDBTNTQ4Uzg3O1MzMjZSKyouVDEwM3wqKS2rJiUp3SEgJP0gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yIhJf9RUFSh////B7Cw + sQD///8ANC3f6yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/PDXg44qH + 7Sp+eusAnpvwAGVg5wB7d+o8NS/f7CUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8pIt3/VlHllv///wO+vPUAsK3zAP///wJNR+OUKCHd/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/aWTncwAAzgD///8AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA7+/vAH9+gQCamZsXPDs/zB8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/0NCRcC0tLUQgH+BAI+PkRc5ODvOHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IyIm6DEwNItHRkk9YWFkG0dGSgpdXF8KZWVoCldX + WgpHRkoLXVxfIkVFSEc2NTieJCMn7CAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/0hHS7vFxcYQmpqcAP39/QA0Ld/rJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f88NeDjioftKn566wAwKd8AS0XjAHRv6U0yLN/0JR7d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ych3f9RS+So/f3/B6mm + 8QCwrfMA////Ak1H45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n + 3v9pZOdzAADOAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD9/f0AhoaIAKurrBFAP0PCIB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Pz5ByqKioxZ9fH4AjY2PFzg3 + O84fHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEg + JP0yMTW1RkVIP3Bwcg////8BCgkOAAEABAAAAAAABQMIAAAAAwD///8EaWhrFEtKTkwyMTWrIiEl9SAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/QD9C0KOj + pRyMjI4A6enpADQt3+smH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zw1 + 4OOKh+0qfnrrAP///wAdFdwAbWjoXy8p3volHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/0tG47jKyPcNmpbvAK+t8wD///8CTUfjlCgh3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2lk53MAAM4A////AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAP///wCRkJIAxMPEDERDR7cgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv87Oj7UlZWXHXx7fQCPjpAXOTg7zh8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JSQo801MT3nKyssJMTA0AISEhgCJiYsAtLS1AMjI + yQCnp6gAh4eJAHl4egAAAAAAvr2/DkxMT18mJSnXIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv85ODvgj4+RK318fgC/v8AANC3f6yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/PDXg44qH7Sp+eusA////AAAAygBkX+dwLSbe/SYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/RkDix66r + 8hWPjO4Ar6zyAP///wJNR+OUKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8uJ97/aWTncwAAzgD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AJ2dnwDp6OkISEdLrCEg + JP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zg3Ot2MjI4lfHt9AJWU + lhc7Oj3OHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv8wLzPddXR3RAAAAABJSEwAjo6QAP///wD///8A////AP///wD+/v0Af36AADAvMwD///8BbWxvIjIx + NZohICT6IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zMy + NeyCgYM9aWhrAHFwcwA0Ld/rJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe + 3f88NeDjioftKn566wDf3voAAABZAFxX5YErJN7/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f9BO+HUm5jvHoeD7ACurPIA////Ak1H45QoId3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9pZOdzAADOAP///wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD///8ArKytAP///wVMS0+fIiEl/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/NTQ35YWEhi95eHoAmpqbFjw7P8sfHiL/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/zk4PMGxsbIfamlsAAAAAACJiIoAmJiaAMvL + zADi4uIAvb2+AJGQkgB/foAAAAAAAJKSlAD///8CQ0JFYCMiJuwgHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Li0x9XZ2eFBIR0oAAAAAADQt3+smH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zw14OOKh+0qfnrrALu59AD///8CVE7kkSki + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zw2 + 4OCNie0pfnrrAK6s8gD///8CTUfjlCgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Life/2lk53MAAM4A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wC+vr8A////AlBP + UpIjIib/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8yMTXsfn2AOXJx + dACfnqATPTw/xSAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8hICT/QD9DpN3d3gySkZMAAAAAAIqJjACYmJkAy8vMAOLi4gC9vb4AkZCSAIGAgwAAAAAAnp6fAAAA + AABaWVwxJyYq1CAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv8qKS36bGxuYg4NEgD///8ANC3f6yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/PDXg44qH7Sp+eusApaLxAP///wZPSeOiKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/ODHg6YJ+6zdwa+kAsa/zAP///wJNR+OUKCHd/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/aWTncwAAzgD///8AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA////ANTU1QAAAAAAVFNWhSQjJ/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/y8uMvF2dnhEZ2ZpAKioqRA+PkG/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yIhJf9IR0qT////A8bFxgD///8A////AP// + /wAAAAAAAAAAAAAAAAD///8A9vb2AP///wBPTlEAX15hAHp6fBYsKy+4IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/ycmKv5iYmRzAAAAAP///wA0Ld/rJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f88NeDjioftKn566wCYlO8Azcz3DEpF + 47QnIN3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe + 3f80Lt/xenXqRltW5QC3tfQA////Ak1H45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/y4n3v9pZOdzAADOAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A9fX2AAAA + AABYV1p4JiUo/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/LCsv9W9u + cU9XVlkAubm6DEJBRLggHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IyIm/01MT4z///8BxcXGAP///wD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////ALy8 + vQBxcXMAqamqCDEwNJogHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/JSQo/1pZXIIAAAAA4eHhADQt3+smH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JR7d/zw14OOKh+0qfnrrAI+M7QCxrvMURkHixCYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zEq3/dxbOlXODHgAL+99QD///8CTUfjlCgh + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2lk6HMAAM4A////AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wD///8AAAAAAF5dYGsnJir9IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8qKS35aGdqW0A/QwDW1tcKR0ZKsiEgJP8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8jIib/Tk1Qi////wHJycoA////AP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wD///8A////AJKSlAD///8BNDM3fSEgJP0gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8kIyb/VFNWkv///wLGxscANC3f6yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/PDXg44qG7Sp+eusAiITsAJ+b + 8B1CPOHTJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Life/Glk52gAANUAxcP2AP///wJNR+OUKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8uJ97/aWTocwAAzgD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP// + /wAcGx8AY2NmXykoLPogHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/ygn + K/xiYWRoFxYaAP///wdMS06oISAk/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yIhJf9HRkqL////AbW1tgD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP// + /wDf3+AAuLi5AAAAAAA0MzZlISAk+SAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yIhJf9PTlGf////BbOytAA0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yUe3f88NeDjiobtKn156wCAfOsAkY3uKD034d8lHt3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8sJd7/YlzmegAArADFw/YA////Ak1H + 45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9qZehzAADNAP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD08PwBpaGtSKyot9h8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JiUp/15dYHYAAAAA////A05OUZoiISX/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk/zo5PIz///8BjIuNAP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AOnp6QD///8AAAACAC8uMlUhICT2IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk/0pJTKr19fUIoaGjADQt + 3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zw14OOKhu0qfnnrAHJu + 6QCEgOw0OTLg6CUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yoj3v9aVeWL////Ab679QD///8CTUfjlCgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Life/2pl6HQAAM0A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAoJysAUlJVAG5tcEYtLC/xHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8lJCj/WVhbgwAAAAD///8BVFNWjCQjJ/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/MjE1k/v7+wN2dXcA////AP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA////AAAAAAAaGR0ALSwwTCEgJPQgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8hICT/R0dKtNTU1QuZmJoANC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/OzXg44qG7Sp+eusAXlnmAHh06kI0Lt/wJR7d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KCHd/1NO5Jz///8EsrDzAP// + /wJNR+OUKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/amXodAAA + zQD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIOChQBiYWQAc3J1Oi8uMuwfHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yQjJ/9TU1aP////AQAAAABdXF98JiUp/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8vLzKhoqKjCGxr + bgDv7/AA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAB0cIAAvLjJKISAk8yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/9GRkm9w8PEDpST + lQA0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f87NeDjiobtKoB8 + 6wBAOuEAbWnoUTEq3/YlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8nIN3/TkjjreXk+wmmo/EA////Ak1H45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9qZeh0AADNAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAra2vAG5tcAB7en0wMjE15h8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IiEl/09OUZz///8ECAYLAGdnaWkpKCz8Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/y0sMLZ/foERaWlrANLR0gD///8AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAALu6vAAAAAAAHh0hADEwM0oiISXzIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/0RDR8G3t7gQjYyOADQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/JR7d/zs14OOKhu0qgn7sAAkB2ABlYOdiLife+iYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f9JQ+K9vLr1EJuY + 7wD///8CTUfjlCgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2pl + 6HQAAM0A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADNzc4Ad3Z5AIWEhyc1NTjfHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8hICT/SkpNqPz8/AdLSk0AdHN2Vi0s + MPcfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/KiktzGZm + aCBJSUwAAAAAAP///wD+/v4A////AAAAAAAAAAAAAAAAAAAAAAD///8AmZiaAAAAAAATEhYANDM2TiIh + JfQgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/QkFFw6+v + sBGIh4kANC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/OzXg44qG + 7SqFgewAAAC+AF9a5nUsJd7+Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/JR7d/0Q+4symo/EYk5DuAP///wJNR+OUKCHd/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/amXodAAAzQD///8AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAOLi4gB9fX8AkI+RHzk4PNcfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yEgJP9HRkm00NDRC29vcQCCgoRBMzI17h8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8mJSnhVVRXOBQTFwAAAAAA////AP7+/gD///8AAAAAAAAA + AAAAAAAAAAAAAP///wCampwA////AAAAAAA4NztZIiEl9yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/9BQETDrayuEYaFhwA0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f87NeDjiobtKoeD7AD///8AWlXliCoj3v8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/QDnh2ZeU + 7yKMiO0A////Ak1H45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n + 3v9qZeh0AADNAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9PT1AIKBhACcm50YPTw/zR8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/0NCRsC3t7gRhIOFAJOS + lC05OTzgHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMi + JvBEREdcAAAAAKCfoQAEAwgAcnF0ALGxsgDQz9AA0tLTANLS0wDJycoAl5eZAFJRVADb29sAAAAAADk4 + O24hICT6IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/0JB + RcOwr7ERiIeJADQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zs1 + 4OOKhu0qiITsAP///wRVT+SaKSLd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f87NeDkjIjtL4N/7AD///8CTUfjlCgh3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2pl6HQAAM0A////AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD6+voAhYWHAKmpqhI/P0LDIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/QD9Dy6emqBeMjI4AqamqGkJBRcwgHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk+zg3OouxsLIMX19iAHh3egBiYWQAsbGyANDP + 0ADS0tMA0tLTAMnJygCTk5UAHx4iAIqJiwDj4+MGNjU4jSAfI/4gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/RENHwbe3uBCNjY8ANC3f7CYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/OzXg44qG7SqHg+wA7u78CE9J46snIN3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zcw + 4O2AfOs8c27pAP///wJNR+OUKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8uJ97/amXodAAAzQD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wCMjI4Avr6/DEJB + RbcgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv88PD/VmpmbHpCP + kQDW1tcNTk1QsyEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Kyouv1xbXjcAAAAARkVIAHh3eQC3trgA39/fAOXl5QDl5OUA1dTVAJmYmgBUVFcAAAAAAHl4 + ex8uLTC0IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/9FREi7wsHCDpGRkwA0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe + 3f87NeDjiobtKoSA7ADAvvUOSUPiuiYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/Myzf9HZx6ktcVuUA////Ak1H45QoId3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9qZeh0AADNAP///wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA////AJeXmQDi4uIIRkVIqyEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zk4O92OjpAli4uNAP///wRdXF+VJSQo/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8jIibpQkFEdXd2eRiOjY8E////AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAALu7vAGYmJoLUE9TUCcmKdkgHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk/0dGSbLV1NUKl5eZADQt3+wmH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zs14OOKhu0qgX3rAKSh8RVDPeLIJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe + 3f8wKd/5bGjoXDYw4AD///8CTUfjlCgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Life/2pl6HQAAM0A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6+voApqanAP// + /wVKSUyfIiEl/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/NTQ45ISE + hi5/foAAAAAAAHBvcnMrKi79Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yEgJPorKi7CQUBEYGtqbSP6+voEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAk5OVB1dW + WT8zMjajIiEl8yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8hICT/S0tOqfz8/AelpaYANC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/OzXg44qG7Sp/e+sAlJHuHz444dUlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ycg + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y0m3v1lYOdtAADTAP///wJNR+OUKCHd/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/amXodAAAzQD///8AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wC5uLoA////Ak5NUZIjIib/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8yMTTrfX1/OG9ucQA1NDgAhoWHUDQzN/IfHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMiJvEwLzOsPj1BZzo5 + PDg/PkIwUVBUMVZVWDFVVFgxTEtOMTg3OjAzMjU9OTk8iCgnK+AgHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMiJv9RUFOc////BLe2uAA0Ld/sJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f87NeDjiobtKn146wCLh+0sOzXg4SUe + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KiTe/ych3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/KyTe/15Z5n8AAJwA////Ak1H45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/y4n3v9qZeh0AADNAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////ANDQ + 0QAAAAAAU1JWhiQjJ/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/y8u + MvF5eHpEX15hAIKBgwChoaIvQkFE3h8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/SMiJuwoJyvKKCcrnC4uMZQ6Oj2VPj1AlT49QJU2NTmVKyotlCUk + KKIlJCjZISAk+iAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/JCMn/1dWWYv///8B0M/QADQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JR7d/zs14OOKhu0qdXDpAIJ+6zo3MeDrJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f85M+D+LCbe/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8pIt7/WFLlkf///wL///8BTUfjlCgh + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2pl6HQAAM0A////AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A8PDxAAAAAABZWFt6JSUo/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/LSww9nJxdFBJSEsArq2vAMnJyhZQUFO8ISAk/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yIh + JfYjIibdJiUp2SwrL9ktLDDZLSww2SopLNkkIyfZIiEl4CAfI/sfHiL/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8nJir/YWBjeAAAAAD09PUANC3f7CYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/OzXg44qG7SpnYucAeXTqSjQt + 3/MlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JiDd/0xG4/YzLN/8JR7d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ygh3f9STeSj////Bv///wFNR+OUKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8uJ97/amXodAAAzQD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAD///8AAAAAAF5eYG0nJir9IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv8qKS35a2ptXCsqLgDU1NQA////BWRjZpEnJir/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP+IB8j/iEgJP4hICT+IB8j/iAf + I/4gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/ysqLvpubXBjCggNAP///wA0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yUe3f87NeDjiobtKlBL5ABvauhaMCrf+CUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8nIN3/WVTl4jcx4PUlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JyDd/01H47TW1PkL////AU1H + 45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9qZeh0AADNAP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAVFBgAYmFkXygnK/ogHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/ygnK/xkY2ZoAAAAAP///wAAAAAAfn2AYjMy + NfcfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/Hx4i/x8eIv8fHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/MjE184GAgkxTU1YAAAAAADQt + 3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zs14OOKhu0qLyjeAGZh + 52suJ978Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yki3f5jXufIOzXg7CUe3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/SELiw7Ox8xL///8ATUfjlCgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Life/2pl6HQAAM0A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAADs6PgBnZmlSKikt9h8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/JyYp/15dYHUAAAAA////AHt6fQChoaM4Q0JG4CAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv87Oj7ll5aYNX19fwCXl5kANC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/OzXg44mG7SoAANUAXFfleysk3v8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/KiPe/Wlk6Ko+OOHhJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f9CPOHQnpvwGwAA + AABNR+OUKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/amXodAAA + zQD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsKy8AU1JVAG5tcEctLC/yHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8lJCj/WFdagQAAAADm5uYAp6eoAMzM + zRddXF+2JCMn/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/0dGSc2ysbMdlpaYANDQ + 0QA0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f87NeDjiYbtKgAA + qQBVUOSMKSLe/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8sJd77cGvpjkE74dUlHt3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/JR7d/z034dyQje4lAAA9AE1H45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9qZeh0AADNAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAIGAgwBjY2UAdnV3PC8uMu0fHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yQjJ/9SUlWN////AcbGxwDj4+MA////BHd2eH8wLzP5Hx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8jIib/V1ZZrebm5gyysbMA////ADQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/JR7d/zs14OOJhu0q////AlBK5J0oId3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JR7d/y8o3vd3c+pzRT/ixyUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/OTPg54aC + 7DMAAI8ATUfjlCgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2pl + 6HQAAM0A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAra2uAHBvcgB+foAyMzI15x8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IiEl/05NUJr///8Ds7K0AP// + /wAAAAAAm5qcQkRDRuIgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/ykoLP5tbG+E////AtXV + 1QD///8ANC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/OzXg44mG + 7Sn6+v4HTEbjrycg3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/Mivf84F961xJQ+K5Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f81L9/vfHjqQQAAogBNR+OUKCHd/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/amXodAAAzQD///8AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAADMzM0AeXh6AIeGiSk2NTngHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8hICT/SkpNp////wekpKUAenp8AJuanADIx8gZYWBjrikoLP8fHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/NzY68YaFh1UAAAAA////APr6+gA0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f87NeDjiobtKcG/9Q9IQuLAJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yUe3f82L9/ti4jtR01H46knIN3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zIr + 3/Zzb+lRAACdAE1H45QoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n + 3v9qZeh0AADNAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObm5gB+foAAkJCSITk4 + PNgfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJP9HRkq009LTC5iY + mgD///8A6+vrAP///wOHh4luOTg87yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJP9KSUzSrKutK4eG + iAADAgcA+fn5ADQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zs1 + 4OOKhu0op6TxF0M94s8lHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zkz4OWXlO81UkzkmSgh + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mHt3/Lyje+2tm6GMAAHQATUfjlCgh3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2pl6HQAAM0A////AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA8fHxAIGAgwCamZsZPDs/zh8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/0NCRr+3trgQjYyPAP///wD///8ADQwRAKuqrC5bW16+KCcq/x4d + If8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHSL/Kikt/2hnapvd3N0OsLCxALa2twDp6ekANC3f7CYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/OzXg44qH7SiUke4iPjjh2yUe3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/Pjjh26aj8SVXUuWJKiPe/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8tJt7+Y17ndAAAAABMR+OUKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8uJ97/amXodAAAzQD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD7+/sAhoWHAKio + qRNAP0LEIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiP/Pz5CyaSk + pRaGhYgA/f39ANjY2ADX19gA////CX19f3k8Oz/oJCMn/x8eIv8fHiL/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/yIhJf8+PkHniYiKXf// + /wD///8A////AP///wA0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe + 3f87NeDji4jtJ4WB7C05M+DlJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f9DPeLPu7j0GV1Y + 5ngrJd7/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yok3v9bVeWF////AkxH45QoId3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9qZeh0AADNAP///wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/wCPj5EAv77ADkRDRrogHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv88Oz7Tl5eZHIKBgwD09PQA1tbXAOLi4wD///8AqqqsK2Zl + aK4yMTT8Hx4i/x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8eHSH/LSww/2VkZ7O0tLUiZmVoAP///wD///8A////ADQt3+wmH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zs14OONiu0neXXqOzUu3+0lHt3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/0hC4sLb2vkPZF/naC4n3vwmH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/KSLd/1VP5Jb///8FTEfjlCgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Life/2pl6HQAAM0A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AJua + nADg4OEJR0dKriEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zg3 + O9yOjY8kfX1/AN3d3QDBwcIAqqqrAMLBwgD///8Ih4aJXlBPU8M1NDjzJiUp/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IiEl/zAvM/lLSk3QhYSGZv// + /wfW1tcA1NTVAP///wAAAAAANC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/OzXg45CM7idxbOlLMivf9CUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8nIN3/TEbjs/// + /whsaOhXMCnf+CUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8nIN3/T0rjqP///wlMRuOUKCHd/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/amXodAAAzQD///8AOTg7AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqamrAP///wVLSk2hIiEl/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/NTQ45IaFiC53d3kAw8LDAKKipACwsLEA////AISD + hgDW1tYWioqMdlhXWtkxMTT+IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8nJir/TUxP7oCAgpLNzM0edXR3AP///wDHxscA////AAAAAAA0Ld/sJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f87NeDilJDuJ2pl6F0vKN76Jh7d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9STOSj////A3Vw6UgzLN/zJR7d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f9KROO46en8D0xG45MoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/y4n3v9qZeh0AADNAP///wA5ODsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAD///8A////Ak5NUJQjIib/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv8yMTXrf3+BOG9ucQCfnqAAoqKkAAAAAACIh4kAxcXGAP///wDCwsMxhIOFskFARPwgHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/y4tMf9ubXDgsbGyYP// + /wPV1dYAt7e4AMHBwgD+/v4AAAAAADQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JR7d/zs14OKXlO8oZF/nby0m3v4mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KSLe/1hS + 5ZMAAGUAfnrrOjcw4OwlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/0ZA4sjFxPYXTEbjkygh + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2pl6HQAAM0A////AIOC + hQBRUFMARUVIAEZFSQBGRUkARkVJAEZFSQBGRUkARkVJAFVUVwAAAAAAU1JVhiQjJ/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/y8uMvF4d3pDYWBjAGRjZgAAAAAA////ANHR + 0gDg4OAA////AKuqrDF8fH6zPz9C/SAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/LSww/2dmaeKPjpBwtbS2GAAAAAD39/cA3d3eAPv7+wD///8ANC3f7CYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/OzXg4pqX7ypdV+aBKyTe/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8rJN7/XVjmgQAAzACKhu0uOzXg4yUe3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/QTvh1a+s8iFMRuOSKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8uJ97/amXodAAAzQD///8AYmFkAB8eIgAPDhMAEA8TABAPEwAQDxMAEA8TABAP + EwAQDxMAGRgcAAAAAABbWl14JiUp/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/LCwv9XBvck5MS04AAAAAAAAAAAD///8Ara2uALy8vQDt7e4PeXl7hj8/QuonJir/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8jIib/MjE1+VJS + Vc2WlZdd////BuDg4QDS0tMA/Pz8AP///wA0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yUe3f87NeDim5jwLVZQ5JIpIt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y0m + 3v1jXudwFxDbAJaT7yI/OeHZJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f88NuDhnZnwLUxG + 45IoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9qZeh0AADNAL+/ + uwCvr7AJlZWXKpGQki+RkJIvkZCSL5GQki+RkJIvkZCSL5GQki+RkJIvnZyeLWRkZ4wmJSn+IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8qKS35aGdqWi8vMgD///8A////AP// + /wD///8AAAAAAJaWmDxTUlXKKCcr/x4dIf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8fHiL/NjY5+WNjZqqrqqwvAAAAAP///wD///8AwsLDADQt + 3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zs14OKal+8xT0njoigh + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mHt3/Lyje+mtm6F9BOuEApKHxGEQ+4swlHt3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/JR7d/zcx4OqOiu06TEbjkSgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Life/2pl6HQAAM0ApaSkAKKioxh8fH53dHN2hnR0doV0dHaFdHR2hXR0 + doV0dHaFdHR2hXR0doV3d3mDX19iuCYlKf4gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/ygnK/xiYWRmAQAFAP///wD///8A6+rrAMfGyAD///8EdXR3fDIxNfcgHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8hICT/Pj1A7YiIinL///8Gzc3OAMDAwQDLy8wANC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/OzXg4peU7zZJQ+KyJyDd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe + 3f8yK9/1c27pT1xX5gC6uPQQSUPivyYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/NC3f8YF9 + 60lMR+ORKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/amXodAAA + zQCIiIkAi4uNJk5NUbw/PkLUQD9C00A/QtNAP0LTQD9C00A/QtNAP0LTQD9C00A/Q9I7Oj7lIyIm/iAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JyYp/l5dYHMAAAAA////APr6 + +gCvr7EAmJeZALW0thhTUlW2JSQo/x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x4dIf8qKS3/W1pdubS0tSeDg4UAIyImANvb + 2wA0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f87NeDhlJHuPUM9 + 4sEmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zUv3+57d+o/cWzpAN/e+gpOSOOwJyDd/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f8wKt/3d3PqWU1H45EoId3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9qZeh0AADNAH18fgCDg4UrODg75SQjJ/8lJCj/JSQo/yUk + KP8lJCj/JSQo/yUkKP8lJCj/JSQo/yMiJv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8lJCj/WllcgQAAAADl5eUA////AP///wBQT1IAjo2POTw7P+EfHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv8+PUHtiomLW////wHa2toA8fHxADQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/JR7d/zs14OGRju5HQDrh0CUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/OTLg5oSA7DJ/e+sA////BVNN5J8oId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n + 3vxuaehqT0njkSgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2pl + 6HQAAM0AhYWGAI6NkCQ5ODzeIB8j/yEgJP8hICT/ISAk/yEgJP8hICT/ISAk/yEgJP8hICT/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yQjJ/9VVFeO////AcvL + zAD///8A/f39AAAAAABzcnVnLi0x9x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/yopLf1kZGef7u7uD8TE + xQDt7O0ANC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/OzTg4I6K + 7VQ8NuDdJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f89N+Hcj4vtJYqG7QD///8BWFPljyoj + 3v8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KyXe/2Zh53xQS+STKCHd/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/amXodAAAzQCOjY4Am5udHD08P9MfHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IyIm/1BPUpv///8EtrW3AP///wDDwsQA////BWBfYpIlJCj/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j+yEg + JPohICT6ISAk+iEgJPohICT6IB8j/CAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/0tLTtOpqKoxZWVnAP///wA0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f87NODfiYXtYjgy4OclHt3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JR7d/0E74dCcmfAbkY3uAAAAigBfWuZ+KyTe/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8qI97/X1rmjlJN5JUoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n + 3v9qZeh0AADNAJSTkwCpqKoVQD9DyR8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8iISX/S0pNpv// + /welpKYA////AKinqQDV1dUPUE9StyEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJPghICTjIyIm3yUkKN8lJCjfJCMn3yIhJd8hICTlIB8j+iAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/NjU484iI + imIAAAAA////ADQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zs1 + 4N+BfetwNC7f7yUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/R0HixLCu8xOZle8AAADQAGVg + 52wtJ979Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ygh3f9ZU+WgVE/kmSgh3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2pl6HQAAM0Am5qaALm5ug9DQkW9IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJP9HRkmy1NTVC5eXmQDm5uYAkpKUAKqqqx1DQ0bQHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eI/8iISXoKSgsuicm + KosqKS2CLi0xgzAvMoMtLDCDJyYqgiUkKI8nJirFIiEl9CAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8pKCz/aWhrk////wbKyssANC3f7CYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/OzXg33l16n8wKt/0JR7d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/ycg3f9MRuO2z874DKKf8QAqI94AbGjoWzAp3/klHt3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JyDd/1JN5LFWUOSeKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8uJ97/amXodAAAzQCkpKIA09LTCkVESLAhICT/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/0ND + Rr66ubsQj46QAMbGxwB/f4EAkZGTLTk5POIfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/ISAk+SkoLLc6OTxoPT1AL0VESCRXVlklXFteJVFQUyU7Oj4kNDM3MzQz + NnkoJyvNISAk+iAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEg + JP9RUFS/w8PEFqGhogA0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe + 3f88NuHfcGzpji0m3vgmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KCHd/1FL5Kb///8HsK7zAFFL + 5AB0cOlLMyzf8yUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/TEfjwFdS5aQoId3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9qZeh0AADNALSzsQD///8GSUhLpCIh + JP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/QUBDyqmpqxaLiowAkI+RAGloawB/foA9MjE17R8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8qKS3kRENGZ0tK + TiBYWFsKa2ttBo6OkAaZmJoGg4KEBlhXWgZGRUkLSUhLKz08P3cnJirhIB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/z8+Qt+cnJ0zenl7ADQt3+wmH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/z034eFpZeifKyTe/CYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8pIt3/VlDklP///wPDwfYAaWTnAH156zw2L9/tJR7d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yUe3f9HQeLOWVTlrSch3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Life/2pl6HQAAM0Ax8fDAP///wNNTFCYIyIl/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv89PUDUnJyeHYaGiABCQUUAUVBTAHFxc0stLDD0Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/zg3OsGAgIIqAAAAACAfIwBHRkkAVlZZAFtbXgBRUFMAPTw/ABoZ + HQD///8AaGdqMTQzN7YhICT+IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/MjE19IGAg1UeHSEANC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/Pznh42Rf57IpIt3+Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yok3v9bVeWDAAAAAN7d + +gB3c+oAh4PsLzoz4OQlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/0I84dtaVeW3JyDd/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ97/amXodAAAzQDe3tgA////AVNS + VYwkIyf/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zk4PNyRkJIlgYCCAAAAAAAyMjUAZ2dpWCop + LfgfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8iISX8TEtPkdTU + 1Q09PEAAJSQoAEdGSQBXVlkAXFteAFFQVAA9PD8AHx4iAAAAAACurq8LUlFUeyUkKPYgHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8pKCz+amlsegAAAAA0Ld/sJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f9AOuHnX1rmxSch3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/LCXe/V9a5nAAAMgA////AIF96wCSju4jPjjh2iUe3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/Pjjh5ltW5cQnIN3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/y4n3v9qZeh0AADNAPj57wAAAAAAV1ZZfyUkKP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/NTU45IaGiC14eHoA////AAoJDgBjYmVkKCcr+yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yMiJvZUU1Zn////AP///wAAAAAARkVJAFNSVQBXV1oATU1QAD08 + QAAAAAAA0tLTAAAAAABycXRJKyou4CAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yQjJ/9aWVyd////CDQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JR7d/0I84exbVeXXJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8uJ975ZF/nXhcQ + 2wD///8Ah4PsAKCd8BlCPOHNJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f86M+DvXFbl0icg + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Life/2pl6HQAAM0A////AAAA + AABbWl1yJiUp/iAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8yMTXqfX1/Nm5tcAD///8AAAAAAGFg + Y24nJir+IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IyIm7klI + TEcAAAAA////AP///wD///8A////AAAAAAD///8A9PT0AAAAAADk5OQATEtPAJeWmCIyMTXBHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk/01MT73LyssVNC3f7CYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHd3/RD7i8lZQ5OclHt3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/JR7d/zEq3/VsaOhORT7iAAAAtgCPi+0AtLLzEUdB4r8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/JR7d/zYw4PZbVuXiKCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8uJ97/amXodAAAzQD///8ABAMHAGFhZGUoJyv8IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/y8uMvB2dXdBYF9iAP///wAAAAAAXl1gdCcmKv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8iISXpOzo9OC0sMAAmJSkA////AP///wD///8AAAAAAP// + /wD09PQAAAAAAJmYmgCNjY8AxsbHDDQzNp8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/QkFE1KalpyY0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yQd3f9EPuL4T0nj8yUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/NC3f7nZy + 6kBfWuYAYFvmAJqW7wDV1PgKS0XjsCcg3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/Myzf+1hT + 5fAoId3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y4n3v9qZehzAADNAP// + /wAwLzIAaGdqWSopLfgfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/LCsv9G9ucUxNTE8A////AAAA + AABcW153JiUp/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yIh + JegyMTU0KiktACQjJwD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAACAgIMA////AJaVlwD///8BMzI2gSAf + I/4gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv84Nzvljo2POjQt + 3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/0I74fxGQOL6JR7d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f84MuDngn7rM3Jt6QClo/EAq6jyAP///wVQSuSgKCHd/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f8vKd7+UUvk+igh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Life/mhk53IAAM4A////AEtKTQBubXBNLCsv9B8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv8qKS34aWhrWS8uMgD///8AAAAAAFtaXXgmJSn/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IiEl6jg3OjoiISUAAAAAAPz8/AAAAAAAAAAAAAAA + AAAAAAAAAAAAAKGhowD///8Ar66wAAAAAAA0MzdqISAk+iAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zAvM/B7e31RNC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/OzXg/jw24P4lHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/z02 + 4d6Oi+0nf3vrAM/N9wDCwPUA////AlVQ5I8pIt7/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ywl + 3v9FP+L/KCHd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8tJ97+Z2LncgAA + zwD///8AXl1gAHR0dkEuLTHvHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/ygnK/xkY2ZmAAACAP// + /wAAAAAAXFtedSYlKf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8iISXvOjk9RBwbHwAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wD///8AAAADADMy + NlghICT2IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Kyou925u + cGk0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f8yLN//MSvf/yUe + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/QTvh05yZ8B2Hg+wA6+r8AOHg+gAAAIgAW1blfysk + 3v8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KSLd/zYv3/8nIN3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y0n3v5nYudxAADPAP///wBram0Ae3p8NjEwNOkfHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/JyYq/l9eYXQAAAAA////AAAAAABdXF9xJyYq/iAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yIhJfQ6OT1VAAAAAP///wD///8AAAAAAAAA + AAAAAAAAAAAAAAAAAAA7OzsA////AP///wARDxQAMC8yTCEgJPMgHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8nJir8ZGNmgTQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ysk3v8qI97/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f9HQeLHsK3zFJCN7gD///8A////AAAAzwBiXeZtLSbe/SYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8nIN3/LCXe/ycg3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/LSfe/mdi + 53EAANAA////AHRzdgCCgYMsNDM34h8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8lJCj/WVlcgAAA + AAD9/f0AAAAAAFxbXmgnJir8IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/ISAk+jw7P2wAAAAA4uLiAP///wD///8AAAAAAAAAAAAAAAAAAAAAAP///wD///8AAAAAACEg + JAAsKy9GISAk8SAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yUk + KP5bW16XNC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/0xH47nLyfcOm5fvAP///wD///8AJBzdAGlk + 6FwvKN75Jh7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8tJ97+Z2LncQAAzwD///8Aenp8AIqJiyM3NjrbHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yQjJ/9UU1aN////Ad/f3wAeHSEAXVxfXygnK/ogHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8hICT+PDs+iv///waenqAAIiElAMfH + yADx8fEA////AP///wD///8A9PT0AM7OzwAAAAAAEhEWAC8uMkohICTyIB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IyIm/1RTVqw0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8nId3/Ukzkqfv7/giqqPIA////AAAAvwBNR+MAcW3pTTIr3/QlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y0n + 3v5nYudxAADPAP///wB/foEAlZSWHDs6PdIfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IyIm/09O + UZn///8Dw8LDADU0NwBkZGdXKiks+B8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/85ODuxurq7GIeHiQAAAAAAx8bHAPHx8QD///8A////AP///wD09PQAzc3OAP// + /wAAAAAAPDs+WSEgJPYgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8iISX/TU1QvTQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yki3f9XUuWZ////BL+99QD///8Ac2/pAGZh + 5wB7d+o+NS/f7iUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/LSfe/mdi53EAAM8A////AISDhgCioqQVPj1ByCAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8iISX/S0pNpf///watrK4ASUhLAGxrbk0sKy/1Hx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zEwNNR8fH45AAAAAGhn + agDR0dEA////AP///wD///8A////AP///wDW1dYAamlsAP///wQ/PkF4ISAk+iAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJP9ISEvNNC3f7CYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/KiTe/11Y5oj///8A2dj5AP///wCwrvMAdXHpAIWB7DA5M+DlJR7d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8tJ97+Z2LncQAAzwD///8AiYmLALOztA9BQES9IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEg + JP9IR0uy2NjZC52cngBdXF8Ac3N1QS4tMfAfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/JyYq71ZVWGr///8GR0ZKAMPCwwDn5+gA6urrAPDw8ADw7/AA7OzsAMjH + yABHRkoAt7e4FTs6PaQgHyP+IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/0RER9o0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8sJd7+Yl3mdQAAvQD///8A////ANXU + +ACAfOsAkY3uJT034dslHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y0n3v5nYudxAADPAP///wCTk5UAz8/QCkVE + SLIhICT/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/0RDR767u7wQkI+RAGxrbgB8fH42MjE16R8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8iISX8ODc6qGBf + YjjMzM0IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOno6QVcW15HLi0xzyAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/QD9D4zQt3+wmH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/y4n3vtnYudjBwDYAP///wD///8A8fD9AIeE7ACfnPAbQjzh0CUe3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/LSfe/mdi53EAAM8A////AKKhowD///8HSUhMpiEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/QD9DyaenqRWHhogAeHh6AIeHiSo2NTngHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8nJirhRURHgl5dYCx9fH8XiYiKDYaGiAqfnqAMhYSHC42M + jhCBgIIYU1NWJj49QIokIyfxIB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv89PD/rNC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/MSrf9m9q6FI/OOEAAAAAAP// + /wD///8Aj4ztALKv8xJHQeLCJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8tJ97+Z2LncQAAzwD///8As7O0AP// + /wROTVCaIiEl/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv88Oz/SmZmbHIKChACAgIIAlZSWHjs6 + PdQfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEg + JPkrKi7NMDAzjURDRnNGRUhUUE9ST1pZXFBJSEtWR0ZJYkZFSHctLDCGKSgszSEgJP0gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zs6PfE0Ld/sJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yUe3f80Ld/wd3PqQ1xX5QA+OOEAAAAAAP///wCal+8A0c/4C0xG47QnIN3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/y0n3v5nYudxAADPAP///wDHx8gA////AVJRVI0kIyb/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/zk4O9uPjpAjfn1/AIqJiwCqqqsUQUBExSAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJPomJSnaNDM2xTQzNqM7Oj6eQD9Dnzc2 + Oag1NDi1NTQ4yyUkKNYgHyP3IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/Ojk89jQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zcw4Od+eus0bWjoAJaT + 7wAAAAAA////AKup8gD///8GUUzkpCgh3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/LSfe/mdi53EAAM8A////AODg + 4AAAAAAAVVRXfyUkKP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/NTQ444aGiCx4d3oAm5qcANLS + 0wxJSEyzISAk/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yEgJPkkIyb0JCMm6CYlKeYnJirnJSQo7SQjJ/EkIyf2ISAk+CAfI/4gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv86OTz5NC3f7CYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8lHt3/OjTg3YeD7Cd3c+oAw8D2AAAAAAD///8Awb/1AP///wJWUeWTKSLd/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8tJ97+Z2LncQAAzwD///8A////AAAAAABZWFtzJCMn/x4dIf8eHSH/Hh0h/x4d + If8fHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv8yMjXqgH+CN29vcQC1tLYA////BVNSVZ0jIib/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8fHiL/IB8j/yAf + I/8gHyP/Hx4i/x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zo5PPk0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f8+OOHSko7uHH56 + 6wDh4PoAAAAAAP///wDd3PoAAABDAFtW5YErJN7/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y0n3v5nYudxAADPAP// + /wD///8AAQAFAF9fYmUoJyv8IB8j/yEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zAvM/B6eXxCY2JlAOTk + 5QD///8AXV1ghCYlKf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Ojk89zQt + 3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/0M94salovEUh4PsAPv7/gAAAAAA////AP///wAAAMsAYVzmcCwm + 3v0mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/LSfe/mdi53EAAM8A////AP///wA+PkEAcXBzUkZFSeo/PkHxOzo97Dg4 + O/QxMDT8KSgs/yAfI/8eHSH/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/LSww9XJxdE1PTlEA////AAAAAABram1nKikt+x8eIv8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv86OTzyNC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/SUPiuMG/ + 9Q2Tj+4A////AAAAAAD///8A////ABoS2wBpZOdfLyje+iYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8tJ97+Z2LncQAA + zwD///8AAAAAAGtqbQCHhok3Z2ZptGBfYrxYV1qzU1NWwUZFSdE5ODzmLCsv9SQjJ/4gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8rKi34ampsWTIx + NQD///8AS0pNAHx7fksxMDTxHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zw7 + Puw0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ycg3f9PSeOq8fD9CKSh8QD///8AAAAAAP///wAAAJsASELiAHBs + 6U4xK9/1JR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y0n3v5nYudxAADPAP///wBDQkUAkJCSAKCgohSOjY9IiIiKS3t7 + fUR7en1PcXFzY2hnaotWVVjDOjo99SIhJf8fHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/ygnK/xjY2ZlBQQJAP///wB4d3kAkpKUMDs6PeEfHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/QD9D5TQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/KSLd/1VP + 5Jr///8Eubb0AP///wAAAAAAAAAAAGVg5wBiXeYAeXXqPzUu3+4lHt3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/LSfe/mdi + 53EAAM8A////AP///wD///8A////Av///wv///8L////CP///w3Z2docpaSmPHp5fHNVVFe4NzY57SMi + Jv8fHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JyYq/l5e + YXIAAAAA////AJiYmgCysrMaRkZJyCAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/9GRUjZNC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8qI97/W1Xlif///wDT0fgA////AAAAAAAAAAAAqqfyAHNu + 6QCDfuwyODLg5iUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8tJ97+Z2LncQAAzwD///8A////AP///wD///8A////Af// + /wH///8B////Adzc3QO5uboHrKutGJSUllNhYWO7Ly4y+x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8lJCj/WlpdgAAAAADq6uoAsLCxAPDw8ApWVVimIyIm/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/ISAk/0xLTsk0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/ywl + 3v9jXud5AAC0APn5/gD///8AAAAAAAAAAADQzvgAfXnrAI2J7SY8NuDcJR7d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y0n + 3v5nYudxAADPAP///wDx8fEA8/PzAPX19QDx8fEA8O/wAOrp6gDe3t8At7e4AIODhQAAAAAA4uLjGYKC + hGVOTVHPJyYq/x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yQj + J/9WVViN////Ac/OzwDW1tYA////AWlpa34qKSz+Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8jIiX/VFNWtDQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mHt3/Lyje/Gtn6GoAANQA////AP///wAAAAAAAAAAAO/v + /QCEgOwAmpbvG0A64dAlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/LSfe/mdi53EAAM8A////AOXl5gDq6eoA6+vrAOrq + 6gDp6ekA4uHiAN7d3gC0tLUAWVhbAMrKywBvbnEA4eDhF318f4w2NTnyIB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IyIm/1FQU5r///8Durm7AP///wAcGx8Ag4OFVDQz + N/IfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yUkKP5dXF+ZNC3f7CYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe + 3f8xK9/4dG/pWTUu3wD///8A////AAAAAAAAAAAA////AIuH7QCsqfITRT/iwyYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8tJ97+Z2LncQAAzwD///8A5eXmAOrp6gDr6+sA6urqAOnp6QDi4eIA3t3eALW1tgBqaWwA////AKmo + qgD///8CoaGjPFdWWcAlJSj/Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8iISX/TEtOpv///waoqKkAAAAAAHx7fgCko6UuRkVI2h8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHiL/KSgs+mloa3o0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JR7d/zQu3/J8d+pIWVTlAAAA0wAAAAAAAAAAAAAA + AAD///8AlpLuAMrI9wxKROO1JiDd/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y0n3v5nYudxAADPAP///wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD///8A////AMPDxAD9/f0AeXl7AMvLzAD///8Kenp8fjMyNvIgHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yEgJP9HR0qx2NjZCpmZmwD19fUAuLi5ANzc + 3BNbWl2yJCMn/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8vLjLxeHd6WjQt3+wmH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8lHt3/NzHg6oJ+6zhtaegAi4jtAAAAAAAAAAAAAAAAAP///wCnpPEA////B09J46UoId3/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/LSfe/mdi53EAAM8A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wD///8Aw8PEAP39 + /QCCgYQA1NTVAAAAAACioaM1TUxPzyEgJP8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/0NCRry6ubsPjY2PAP7+/gDU1NUA////A3h4enwvLjL8Hx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/zo5POOPj5E6NC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f87NODgiYbtKnp16gDAvvUAAAAAAAAA + AAAAAAAA////ALy69QD///8DVU/klSki3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8tJ97+Z2LncQAAzwD///8AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////AAAAAACtrK4AwcHCAP///w5nZ2mYKikt/R8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Pz9Cx6ampxSGhYgA////AP// + /wAlJCgAmJeZR0FBROMgHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/SEdLyK+vsCA0Ld/sJh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/JR7d/z444dWUkO4fgXzrAN/e+gAAAAAAAAAAAAAAAAD7+/4A2Nf5AAAAAABbVuWEKiTe/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/y0n3v5nYudxAADPAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA////AJ6dnwDh4eEAAAAAAI2Nj1k5ODvuHx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv88Oz/RmZiaG4GBgwDu7u8Aa2ptAKWkpgDKyssaXFtetiUkKP8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yQjJ/9bWl2i9PT0DDQt3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Qz3iyKOg8RWHhOwA9vb+AAAA + AAAAAAAAAAAAAP///wD///8AAADFAGJd5nMsJt7+Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/LSfe/mdi53EAAM8A////AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAB8eIgB/foEAsrKzKEpK + TcghICT/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/Hx4i/zk4PNqQkJIjf3+BAOHg + 4QDt7e0A19fYAP///wV6enx0NzY59R8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Li0x+XFwc3D///8BNC3f7CYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f9HQeK5u7n0Do+M7gD///8AAAAAAAAAAAAAAAAA////AP///wAOB9kAaWToYy8o + 3vsmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8tJ97+Z2LncQAAzwD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD///8A9vb3AMrKywD///8JYGBjmCYlKf8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8fHiL/NjU544iIiix6eXwAycjJAMnIyQD///8AXVxfAKqpqzdOTVDQJCMn/x8e + Iv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8+PUHikI+RP0lJTAA0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/JyDd/0tF46nl5PsInJjvAP// + /wAAAAAAAAAAAAAAAAD///8AAAAAAEI84QBybelTMSvf9iUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y0n3v5nYudxAADPAP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wD///8A8vLzAAAA + AAB8fH5mMTA09x8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8zMjXqf3+BNnBv + cgCmpqcA0tLTAF5dYACgoKEA1tbXEHRzdok0Mzf4Hh0h/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/JSQo/1paXba5uboZkZGTADQt + 3+wmH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8oId3/T0njmP///wOtqvIA////AAAAAAAAAAAAAAAAAAAAAABCPOIAX1nmAHp1 + 6kM0Lt/wJR7d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/LSfe/mdi53EAAM8A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA////APHx8QArKi4AdHR2AJybnTo+PUDiHx4i/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/Hx4i/y8vMu93dnlAYmFkAHJxdAC+vr8A////AP///wAAAAAAnJyeRU1M + T8woJyv/Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/x8eIv82NTjzeHd6eP///wXg4OEANC3f7CYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yoj3v9VT+SH////AMfF + 9gD///8AAAAAAAAAAAAAAAAAAAAAAKGd8ABwbOkAgX3rNDgx4OglHt3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8tJ97+Z2LncQAA + zwD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A8vLyAKmp + qwCdnZ4AwcHCGU1MUMAhICT/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/LSww9HBv + cktPT1IAAAAAAL6+vwD///8A////AIeGiADQ0NAQfHt9gjs6PvEgHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/JCMn/1NSVc+mpac2CQcMAPT0 + 9AA0Ld/sJh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/KyXe/1xX5XgAALsA7+/8AP///wAAAAAAAAAAAAAAAAAAAAAAy8r3AHx4 + 6wCLiO0nPDXg3iUe3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/y0n3v5nYudxAADPAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADz8/MA////AMnJygD///8HXl1glyUkKP8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8qKS34amlsVzQzNgD///8AAAAAAP///wDp6ekA////AAAA + AACgoKE6XFterzQzN/ggHyP/Hh0h/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/Hx4i/yEgJP88Oz/xc3J1heTj5BCrq6wAmZmbADQt3+wlHt3/Jh/d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yUe3f8tJ978ZWDnaAAA + 1QD///8A////AAAAAAAAAAAAAAAAAAAAAADt7PwAhIDsAJiV7x1AOuHSJR7d/yYf3f8mH93/Jh/d/yYf + 3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8mH93/Jh/d/yYf3f8lHt3/LSbe/mdi + 53EAAM8A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AADg4OEA/f39AAAAAABxcHNsKyou+h8eIv8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yko + K/tkZGdkBwYKAP///wAAAAAA////ALe3uACqqasAzMzNAP///weSkpRfTk1Q0iopLfohICT/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8hICT/LCsu+ltaXcOura87AAAAAP// + /wD///8AMyzf7CQd3f8lHt3/JR7d/yUe3f8lHt3/JR7d/yUe3f8lHt3/JR7d/yUe3f8lHt3/JR7d/yUe + 3f8lHt3/JR7d/yUe3f8lHt3/JB3d/y8o3vhtaehYNC3fAP///wD///8AAAAAAAAAAAAAAAAAAAAAAP39 + /wCJhe0AqKbxFEM94sUkHd3/JR3d/yUe3f8lHt3/JR7d/yUe3f8lHt3/JR7d/yUe3f8lHt3/JR7d/yUe + 3f8lHt3/JR7d/yUe3f8lHd3/JB3d/yQd3f8sJd7/ZmHncQAAzwD///8AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPHx8QD///8ASklNAIWFh0Y1NDftHx4i/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/JyYq/mBfYnIAAAAA////AAAAAAD///8A2dnaANHR + 0gDx8fEAAAAAALOztB14eHp1UE9S1i4tMf8fHiL/Hh0h/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8fHSL/Hh0h/ywrL/9SUVTWg4OFZ9nY2RCFhIYAAAAAAP///wA3MeDtKSLe/yoj3v8qI97/KiPe/yoj + 3v8qI97/KiPe/yoj3v8qI97/KiPe/yoj3v8qI97/KiPe/yoj3v8qI97/KiPe/yoj3v8pIt3/NjDg83dz + 6khYU+UABADYAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AJGO7gDCwPUMSkTjtioj3v8qI97/KiPe/yoj + 3v8qI97/KiPe/yoj3v8qI97/KiPe/yoj3v8qI97/KiPe/yoj3v8qI97/KiPe/yoj3v8qI97/KiPe/zEq + 3/9pZOdyAADRAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA6enpALi3uQCLiowAoaGjJ0A/QtkfHiL/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8e + Iv8lJCj/WllcgQAAAADn5+cAAAAAAAAAAAD19fYAw8PEANLR0gD6+voAAAAAAMPDxCxycnSMRURH1DAv + M/QmJSn/ISAk/x8eIv8fHiL/Hx4i/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/x8eIv8fHiL/IB8j/yQjJ/8tLDD5QkJF2nV1d47R0dIkSklNAP// + /wD///8A////AEI84eY1L9/6NS/f+TUv3/k1L9/5NS/f+TUv3/k1L9/5NS/f+TUv3/k1L9/5NS/f+TUv + 3/k1L9/5NS/f+TUv3/k1L9/5NS/f+TUu3/pDPeLkhIDsOHFs6QCGguwAAAAAAAAAAAAAAAAAAAAAAAAA + AAD///8AoZ7wAO3t/AdXUeWiNzDg/DUv3/k2L9/5Ni/f+TYv3/k2L9/5Ni/f+TYv3/k2L9/5Ni/f+TYv + 3/k2L9/5Ni/f+TYv3/k2L9/5Ni/g+Tcw4Po2MOD7PTfh+XBs6W0AANUA////AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADp6ekA19fYAKGgogDGxscSTk1QvSMi + Jv8jIiX/IyIm/yMiJv8jIib/IyIm/yMiJv8jIib/IiEl/ycmKf9WVlmN////Ac7OzwAAAAAAAAAAAPX1 + 9gDDw8QA0dHSAPv7+wAyMTUA3d3dB6Khoyp8fH55WFdazDk4O/cmJSn/IB8j/x4dIf8fHiL/IB8j/yAf + I/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8gHyP/IB8j/yAfI/8fHiL/Hx4i/x8e + Iv8jIib/MTA0/E9PUtp5eHuIpqanLu/v8AV6enwA////AP///wD///8AVU/knElD46pJQ+OpSUPjqUlD + 46lJQ+OpSUPjqUlD46lJQ+OpSUPjqUlD46lJQ+OpSUPjqUlD46lJQ+OpSUPjqUlD46lJQ+OpSELiqlVP + 5JiQjO4gg3/sALGv8wAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wCwrvMA////A2di52hLReOsSUPjqklE + 46pJROOqSUTjqklE46pJROOqSUTjqklE46pJROOqSUTjqklE46pJROOqSUTjqklD46pLReOrT0njr09J + 469VT+Suf3vrSxoT2wD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAP///wD///8Avb2+AP///wZlZWeNQkFE5EBAQ+JBQEPiQUBD4kFAQ+JBQEPiQUBD4kFA + Q+JAQEPiQ0JG5WppbIH///8BysnKAAAAAAAAAAAAAAAAAPLy8wDPz9AA5+foAP///wCZmZsA////BK+v + sDF1dHdyVVRXq0NCRdQ3NjnuLi0x/ScmKv8jIib/IB8j/x8eIv8fHiL/Hh0h/x4dIf8eHSH/Hh0h/x4d + If8eHSH/Hh0h/x8eIv8fHiL/ISAk/yQjJ/8qKS3/MjE19z49QeJPTlG7bGtugqWlpjv///8GpKSmAP// + /wD///8A+fn5AP///wCIhO0/f3vrRH9760R/e+tEf3vrRH9760R/e+tEf3vrRH9760R/e+tEf3vrRH97 + 60R/e+tEf3vrRH9760R/e+tEf3vrRH9760R/e+tFhoLsO6up8gqkofEA09L4AAAAAAAAAAAAAAAAAAAA + AAAAAAAA/v7/AMrJ9wD///8AlJDuJ4J+7EaBfetFgX3rRYF960WBfetFgX3rRYF960WBfetFgX3rRYF9 + 60WBfetFgX3rRYF960WBfetFgXzrRYWB7EeOiu1NjoruTZGO7kyppvIfeHPqAP///wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADd3d0A////AYyM + jlRycXOjcHBypHBwcqNwcHKjcHByo3BwcqNwcHKjcHByo3BwcqNycXSli4uNYP///wHMy8wAAAAAAAAA + AAAAAAAAAAAAAPv7+wDp6ekA////AHt7fQCrqqwA////As7Ozhecm51KdnV3iVlYW71FRUjfNjU57y0s + MPcoKCv7JSQo/SMiJv4jIib+IiEl/yIhJf8iISX/IiEl/yMiJv8jIib+JCMn/SYlKf0qKS37MTAz9Tw8 + P+pPTlHQa2pto4+PkWG+vr8i////BKinqQCamZsA////APn5+QD///8AAAAAALKv8w+tqvIQraryEK2q + 8hCtqvIQraryEK2q8hCtqvIQraryEK2q8hCtqvIQraryEK2q8hCtqvIQraryEK2q8hCtqvIQraryEKyq + 8hC0sfQN19b5AtLQ+AD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAD9/f8A////AAAAvgDAvvYJr63zEa6r + 8xGurPMRrqzzEa6s8xGurPMRrqzzEa6s8xGurPMRrqzzEa6s8xGurPMRrqzzEa6s8xGuq/MQs7DzEby5 + 9RS8uvUUvrz1FMrI9wi0sfQA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA////AP///wAAAAAAp6aoHY+OkD2NjY8+jo2PPo6Njz6OjY8+jo2PPo6N + jz6OjY8+jY2PPo6OkD+goKEk////AdDQ0QAAAAAAAAAAAAAAAAAAAAAA+/v7AOnp6gD///8AaGhqAOvr + 6wB5eHsA////AdHR0hOTkpQweXl7U21sb3leXmCZV1ZZt1JRVdFKSU3fQUBE5T8+Qu5AP0P5QD9D+kA/ + Q/pAP0P6QUBD9z8+QutDQkbjTk1R3VVVWMpcW16uZWVnjHNydWaIiIo/tra3Hf///wRZWFsA4+PkAGtq + bQD///8A+fn5AP///wAAAAAAj4vuAIeD7ACHg+wAh4PsAIeD7ACHg+wAh4PsAIeD7ACHg+wAh4PsAIeD + 7ACHg+wAh4PsAIeD7ACHg+wAh4PsAIeD7ACHg+wAh4PsAI6K7QCwrvMAqqfyANnY+QAAAAAAAAAAAAAA + AAAAAAAAAAAAAP///wDQzvgA////AJqW7wCIhO0Ah4PtAIeD7QCHg+0Ah4PtAIeD7QCHg+0Ah4PtAIeD + 7QCHg+0Ah4PtAIeD7QCHg+0Ah4PtAIeD7QCJhe0Ai4jtAIuI7QCPi+4AqKXxAHRv6gD///8AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4+PkA0tLTAP// + /wAAAAAAAAAAAP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAD///8AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA////AP///wAaGR0A4eHiAAAAAADr6+sAl5aYAAAAAAD///8QyMjJN52d + n2CHhoiLeXh6tGloa8tYWFvVVFNW41VUV/VVVFf3VVRX91VUV/dWVVjyVVRX31xcX9Fwb3HIf3+BqZGR + k36wr7FO6OjoIv///wNkZGYA1NPUAP///wDf3t8AAAAAAP///wD///8AAAAAAAAAAAAAAIAAMAAD4AAD + 4AAAAAP/AACAADAAA+AAA8AAAAAA/wAAgAAwAAPgAAPAAAAAAP8AAIAAMAAD4AADgAAAAAB/AACAABAA + A+AAAwAAAAAAPwAAgAAQAAPgAAMAAAAAAD8AAIAAEAAD4AADAAAAAAAfAACAABAAA+AAAwAAAAAAHwAA + gAAQAAPgAAIAAAAAAB8AAAAAEAAD4AAAAAAAAAAPAAAAABAAA+AAAAAAAAAADwAAAAAQAAPgAAAAAAAA + AAcAAAAAEAAD4AAAAAAAAAAHAAAAABAAA+AAAAAAAAAABwAAAAAQAAPgAAAAAAAAAAcAAAAAAAAD4AAA + AAAAAAADAAAAAAAAA+AAAAAAAAAAAwAAAAAAAAPgAAAAAAAAAAMAAAAAAAAD4AAAAAAAAAABAAAAAAAA + A+AAAAAAAAAAAQAAAAAAAAPgAAAAAAAAAAEAAAAAAAAD4AAAAAAAAAABAAAAAAAAA+AAAAAAAAAAAQAA + AAAAAAPwAAAAAAAAAAEAAAAAAAAD8AAAAAAAAAABAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAPwAAAAAAAA + AAAAAAAAAAAD8AAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAPwAAAAAAAAAAAAAAAAAAAD8AAA + AAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAPwAAAAAAAAAAAAAAAAAAAD8AAAAAAAAAAAAAAAAAAA + A/AAAAAAAAAAAAAAAAAAAAPwAAAAAAAAAAAAAAAAAAAD8AAAAAAAAAAAAAAAAAAAA/AAAAAABwAAAAAA + AAAAAAPwAAAAAA+AAAAAAAAAAAAD8AAAAAAPgAAAAAAAAAAAA/gAAAAAH8AAAAAAAAAAAAP4AAAAAB/A + AAAAAAAAAAAD+AAAAAAP4AAAAAAAAAAAA/gAAAAAD+AAAAAAAAAAAAP4AAAAAA/gAAAAAAAAAAAD+AAA + AAADwAAAAAAAAAAAA/gAAAAAA8AAAAAAAAAAAAP4AAAAAAAAAAAAAAAAAAAD+AAAAAAAAAAAAAAAAAAA + A/gAAAAAAAAAAAAAAAAAAAP4AAAAAAAAAAAAAAAAAAAD+AAAAAAAAAAAAAAAAAAAA/gAAAAAAAAAAAAA + AAAAAAP4AAAAAAAAAAAAAAAAAAAD+AAAAAAAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAAAAAAP8AAAAAAAA + AAAAAAAAAAAD/AAAAAAAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAAAAAAP8AAAAAAAAAAAAAAAAAAAD/AAA + AAAAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAAAAAAP8AAAAAAAAAAAAAAAAAAAD/AAAAAAAAAAAAAAAAAAA + A/wAAAAAAAAAAAAAAAAAAAP8AAAAAAAAAAAAAAAAAAAD/AAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAA + AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + AAAASUVORK5CYII= + + + \ No newline at end of file diff --git a/M18BatteryInfo.csproj b/M18BatteryInfo.csproj new file mode 100644 index 0000000..5fc9b35 --- /dev/null +++ b/M18BatteryInfo.csproj @@ -0,0 +1,31 @@ + + + + WinExe + net10.0-windows + enable + true + enable + + + + + + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + diff --git a/M18BatteryInfo.csproj.user b/M18BatteryInfo.csproj.user new file mode 100644 index 0000000..03f6b68 --- /dev/null +++ b/M18BatteryInfo.csproj.user @@ -0,0 +1,8 @@ + + + + + Form + + + \ No newline at end of file diff --git a/M18BatteryInfo.slnx b/M18BatteryInfo.slnx new file mode 100644 index 0000000..a4665e5 --- /dev/null +++ b/M18BatteryInfo.slnx @@ -0,0 +1,3 @@ + + + diff --git a/M18Protocol.cs b/M18Protocol.cs new file mode 100644 index 0000000..cae7274 --- /dev/null +++ b/M18Protocol.cs @@ -0,0 +1,1282 @@ +// ************************************************************************************************* +// M18Protocol.cs +// -------------- +// Literal, instruction-for-instruction port of m18.py. Every sleep, buffer reset, control-line +// toggle, byte ordering rule, and logging string mirrors the Python implementation. The structure +// intentionally ignores .NET conventions so the execution order, timing, and side effects remain +// identical to the Python reference, including redundant operations and blocking behaviour. Serial +// I/O now routes through RJCP.IO.Ports.SerialPortStream (via SerialPortConnection) to guarantee +// .NET 10 compatibility and access to manual BREAK/DTR toggles plus buffer flushes. +// ************************************************************************************************* + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; + +namespace M18BatteryInfo +{ + public class M18Protocol + { + // --------------------------- + // Constants matching m18.py + // --------------------------- + public const byte SYNC_BYTE = 0xAA; + public const byte CAL_CMD = 0x55; + public const byte CONF_CMD = 0x60; + public const byte SNAP_CMD = 0x61; + public const byte KEEPALIVE_CMD = 0x62; + + public const int CUTOFF_CURRENT = 300; + public const int MAX_CURRENT = 6000; + + // --------------------------- + // State fields (mirror Python names and defaults) + // --------------------------- + public int ACC = 4; + public bool PRINT_TX = false; + public bool PRINT_RX = false; + public bool PRINT_TX_SAVE = false; + public bool PRINT_RX_SAVE = false; + public Action? TxLogger { get; set; } + public Action? RxLogger { get; set; } + private Action? rawLogger; + public Action? RawLogger + { + get => rawLogger; + set + { + rawLogger = value; + port?.UpdateLogger(value); + } + } + + public SerialPortConnection port; + + // --------------------------- + // Data tables copied verbatim from m18.py + // --------------------------- + private readonly List<(int, int, int)> data_matrix = new() + { + (0x00, 0x00, 0x02), + (0x00, 0x02, 0x02), + (0x00, 0x04, 0x05), + (0x00, 0x0D, 0x04), + (0x00, 0x11, 0x04), + (0x00, 0x15, 0x04), + (0x00, 0x19, 0x04), + (0x00, 0x23, 0x14), + (0x00, 0x37, 0x04), + (0x00, 0x69, 0x02), + (0x00, 0x7B, 0x01), + (0x40, 0x00, 0x04), + (0x40, 0x0A, 0x0A), + (0x40, 0x14, 0x02), + (0x40, 0x16, 0x02), + (0x40, 0x19, 0x02), + (0x40, 0x1B, 0x02), + (0x40, 0x1D, 0x02), + (0x40, 0x1F, 0x02), + (0x60, 0x00, 0x02), + (0x60, 0x02, 0x02), + (0x60, 0x04, 0x04), + (0x60, 0x08, 0x04), + (0x60, 0x0C, 0x02), + (0x90, 0x00, 0x3A), + (0x90, 0x3A, 0x3A), + (0x90, 0x74, 0x3A), + (0x90, 0xAE, 0x3A), + (0x90, 0xE8, 0x3A), + (0x91, 0x22, 0x30), + (0x91, 0x52, 0x00), + (0xA0, 0x00, 0x06) + }; + + private readonly List<(int, int, string, string)> data_id = new() + { + (0x0000, 2, "uint", "Cell type"), + (0x0002, 2, "uint", "Unknown (always 0)"), + (0x0004, 5, "sn", "Capacity & Serial number (?)"), + (0x000D, 4, "uint", "Unknown (4th code?)"), + (0x0011, 4, "date", "Manufacture date"), + (0x0015, 4, "date", "Date of first charge (Forge)"), + (0x0019, 4, "date", "Date of last charge (Forge)"), + (0x0023, 20, "ascii", "Note (ascii string)"), + (0x0037, 4, "date", "Current date"), + (0x0069, 2, "uint", "Unknown (always 2)"), + (0x007B, 1, "uint", "Unknown (always 0)"), + (0x4000, 4, "uint", "Unknown (Forge)"), + (0x400A, 10, "cell_v","Cell voltages (mV)"), + (0x4014, 2, "adc_t", "Temperature (C) (non-Forge)"), + (0x4016, 2, "uint", "Unknown (Forge)"), + (0x4019, 2, "uint", "Unknown (Forge)"), + (0x401B, 2, "uint", "Unknown (Forge)"), + (0x401D, 2, "uint", "Unknown (Forge)"), + (0x401F, 2, "dec_t", "Temperature (C) (Forge)"), + (0x6000, 2, "uint", "Unknown (Forge)"), + (0x6002, 2, "uint", "Unknown (Forge)"), + (0x6004, 4, "uint", "Unknown (Forge)"), + (0x6008, 4, "uint", "Unknown (Forge)"), + (0x600C, 2, "uint", "Unknown (Forge)"), + (0x9000, 4, "date", "Date of first charge (rounded)"), + (0x9004, 4, "date", "Date of last tool use (rounded)"), + (0x9008, 4, "date", "Date of last charge (rounded)"), + (0x900C, 4, "date", "Unknown date (often zero)"), + (0x9010, 2, "uint", "Days since first charge"), + (0x9012, 4, "uint", "Total discharge (amp-sec)"), + (0x9016, 4, "uint", "Total discharge (watt-sec or joules)"), + (0x901A, 4, "uint", "Total charge count"), + (0x901E, 2, "uint", "Dumb charge count (J2>7.1V for >=0.48s)"), + (0x9020, 2, "uint", "Redlink (UART) charge count"), + (0x9022, 2, "uint", "Completed charge count (?)"), + (0x9024, 4, "hhmmss","Total charging time (HH:MM:SS)"), + (0x9028, 4, "hhmmss","Time on charger whilst full (HH:MM:SS)"), + (0x902C, 2, "uint", "Unknown (another low-voltage charge counter?)"), + (0x902E, 2, "uint", "Charge started with a cell < 2.5V"), + (0x9030, 2, "uint", "Discharge to empty"), + (0x9032, 2, "uint", "Num. overheat on tool (must be > 10A)"), + (0x9034, 2, "uint", "Overcurrent?"), + (0x9036, 2, "uint", "Low voltage events)"), + (0x9038, 2, "uint", "Low-voltage bounce? (4 flashing LEDs)"), + (0x903A, 2, "uint", "Discharge @ 10-20A (seconds)"), + (0x903C, 2, "uint", " @ 20-30A (could be watts)"), + (0x903E, 2, "uint", " @ 30-40A "), + (0x9040, 2, "uint", " @ 40-50A "), + (0x9042, 2, "uint", " @ 50-60A "), + (0x9044, 2, "uint", " @ 60-70A "), + (0x9046, 2, "uint", " @ 70-80A "), + (0x9048, 2, "uint", " @ 80-90A "), + (0x904A, 2, "uint", " @ 90-100A "), + (0x904C, 2, "uint", " @ 100-110A "), + (0x904E, 2, "uint", " @ 110-120A "), + (0x9050, 2, "uint", " @ 120-130A "), + (0x9052, 2, "uint", " @ 130-140A "), + (0x9054, 2, "uint", " @ 140-150A "), + (0x9056, 2, "uint", " @ 150-160A "), + (0x9058, 2, "uint", " @ 160-170A "), + (0x905A, 2, "uint", " @ 170-180A "), + (0x905C, 2, "uint", " @ 180-190A "), + (0x905E, 2, "uint", " @ 190-200A "), + (0x9060, 2, "uint", " @ 200-210A "), + (0x9062, 2, "uint", "Discharge @ 5-10A (seconds)"), + (0x9064, 2, "uint", " @ 10-15A (could be watts)"), + (0x9066, 2, "uint", " @ 15-20A (histo not well understood yet)"), + (0x9068, 2, "uint", " @ 20-25A "), + (0x906A, 2, "uint", " @ 25-30A "), + (0x906C, 2, "uint", " @ 30-35A "), + (0x906E, 2, "uint", " @ 35-40A "), + (0x9070, 2, "uint", " @ 40-45A "), + (0x9072, 2, "uint", " @ 45-50A "), + (0x9074, 2, "uint", " @ 50-55A "), + (0x9076, 2, "uint", " @ 55-60A "), + (0x9078, 2, "uint", " @ 60-65A "), + (0x907A, 2, "uint", " @ 65-70A "), + (0x907C, 2, "uint", " @ 70-65A "), + (0x907E, 2, "uint", " @ 75-80A "), + (0x9080, 2, "uint", " @ 80-85A "), + (0x9082, 2, "uint", " @ 85-90A "), + (0x9084, 2, "uint", " @ 90-95A "), + (0x9086, 2, "uint", " @ 95-100A "), + (0x9088, 2, "uint", " @ 100-105A "), + (0x908A, 2, "uint", " @ 105-110A "), + (0x908C, 2, "uint", " @ 110-115A "), + (0x908E, 2, "uint", " @ 115-120A "), + (0x9090, 2, "uint", " @ 120-125A "), + (0x9092, 2, "uint", " @ 125-130A "), + (0x9094, 2, "uint", " @ 130-135A "), + (0x9096, 2, "uint", " @ 135-140A "), + (0x9098, 2, "uint", " @ 140-145A "), + (0x909A, 2, "uint", " @ 145-150A "), + (0x909C, 2, "uint", " @ 150-155A "), + (0x909E, 2, "uint", " @ 155-160A "), + (0x90A0, 2, "uint", " @ 160-165A "), + (0x90A2, 2, "uint", " @ 165-170A "), + (0x90A4, 2, "uint", " @ 170-175A "), + (0x90A6, 2, "uint", " @ 175-180A "), + (0x90A8, 2, "uint", " @ 180-185A "), + (0x90AA, 2, "uint", " @ 185-190A "), + (0x90AC, 2, "uint", " @ 190-195A "), + (0x90AE, 2, "uint", " @ 195-200A "), + (0x90B0, 2, "uint", " @ 200A+ "), + (0x90B2, 2, "uint", "Charge started < 17V"), + (0x90B4, 2, "uint", "Charge started 17-18V"), + (0x90B6, 2, "uint", "Charge started 18-19V"), + (0x90B8, 2, "uint", "Charge started 19-20V"), + (0x90BA, 2, "uint", "Charge started 20V+"), + (0x90BC, 2, "uint", "Charge ended < 17V"), + (0x90BE, 2, "uint", "Charge ended 17-18V"), + (0x90C0, 2, "uint", "Charge ended 18-19V"), + (0x90C2, 2, "uint", "Charge ended 19-20V"), + (0x90C4, 2, "uint", "Charge ended 20V+"), + (0x90C6, 2, "uint", "Charge start temp -30C to -20C"), + (0x90C8, 2, "uint", "Charge start temp -20C to -10C"), + (0x90CA, 2, "uint", "Charge start temp -10C to 0C"), + (0x90CC, 2, "uint", "Charge start temp 0C to +10C"), + (0x90CE, 2, "uint", "Charge start temp +10C to +20C"), + (0x90D0, 2, "uint", "Charge start temp +20C to +30C"), + (0x90D2, 2, "uint", "Charge start temp +30C to +40C"), + (0x90D4, 2, "uint", "Charge start temp +40C to +50C"), + (0x90D6, 2, "uint", "Charge start temp +50C to +60C"), + (0x90D8, 2, "uint", "Charge start temp +60C to +70C"), + (0x90DA, 2, "uint", "Charge start temp +70C to +80C"), + (0x90DC, 2, "uint", "Charge start temp +80C and over"), + (0x90DE, 2, "uint", "Charge end temp -30C to -20C"), + (0x90E0, 2, "uint", "Charge end temp -20C to -10C"), + (0x90E2, 2, "uint", "Charge end temp -10C to 0C"), + (0x90E4, 2, "uint", "Charge end temp 0C to +10C"), + (0x90E6, 2, "uint", "Charge end temp +10C to +20C"), + (0x90E8, 2, "uint", "Charge end temp +20C to +30C"), + (0x90EA, 2, "uint", "Charge end temp +30C to +40C"), + (0x90EC, 2, "uint", "Charge end temp +40C to +50C"), + (0x90EE, 2, "uint", "Charge end temp +50C to +60C"), + (0x90F0, 2, "uint", "Charge end temp +60C to +70C"), + (0x90F2, 2, "uint", "Charge end temp +70C to +80C"), + (0x90F4, 2, "uint", "Charge end temp +80C and over"), + (0xA000, 6, "uint", "Unknown (Forge)") + }; + + // ------------------------------------- + // Helper exception to mirror Python usage + // ------------------------------------- + private class ValueError : Exception + { + public ValueError(string message) : base(message) { } + } + + // ------------------------------------- + // Debug byte printer (identical format) + // ------------------------------------- + public static void print_debug_bytes(IEnumerable data) + { + var dataPrint = string.Join(" ", GetHex(data)); + Console.WriteLine("DEBUG: " + dataPrint); + } + + private static IEnumerable GetHex(IEnumerable bytes) + { + foreach (var b in bytes) + { + yield return $"{b:02X}"; + } + } + + // ------------------------------------- + // Constructor mirroring __init__ in m18.py + // ------------------------------------- + public M18Protocol(SerialPortDisplay device, Action? rawLogger = null) + { + RawLogger = rawLogger; + port = new SerialPortConnection(device, RawLogger); + idle(); + } + + // ------------------------------------- + // Logging flag helpers (match Python naming and behaviour) + // ------------------------------------- + public void txrx_print(bool enable = true) + { + PRINT_TX = enable; + PRINT_RX = enable; + } + + public void txrx_save_and_set(bool enable = true) + { + PRINT_TX_SAVE = PRINT_TX; + PRINT_RX_SAVE = PRINT_RX; + txrx_print(enable); + } + + public void txrx_restore() + { + PRINT_TX = PRINT_TX_SAVE; + PRINT_RX = PRINT_RX_SAVE; + } + + // ------------------------------------- + // Reset: identical control-line toggles, sleeps, send, and idle logic + // ------------------------------------- + public bool reset() + { + ACC = 4; + port.SetBreak(true); + port.SetDtr(true); + Thread.Sleep(300); + port.SetBreak(false); + port.SetDtr(false); + Thread.Sleep(300); + send(new[] { SYNC_BYTE }); + try + { + var response = read_response(1); + Thread.Sleep(10); + if (response.Length > 0 && response[0] == SYNC_BYTE) + { + return true; + } + Console.WriteLine($"Unexpected response: {string.Join(" ", GetHex(response))}"); + return false; + } + catch (ValueError) + { + return false; + } + } + + // ------------------------------------- + // Utility helpers mapped directly + // ------------------------------------- + public void update_acc() + { + var accValues = new List { 0x04, 0x0C, 0x1C }; + var currentIndex = accValues.IndexOf(ACC); + var nextIndex = (currentIndex + 1) % accValues.Count; + ACC = accValues[nextIndex]; + } + + public bool PrintTx + { + get => PRINT_TX; + set => PRINT_TX = value; + } + + public bool PrintRx + { + get => PRINT_RX; + set => PRINT_RX = value; + } + + public int reverse_bits(int value) + { + return Convert.ToInt32(string.Concat(Convert.ToString(value & 0xFF, 2).PadLeft(8, '0').Reverse()), 2); + } + + public int checksum(IEnumerable payload) + { + var cksum = 0; + foreach (var b in payload) + { + cksum += b & 0xFFFF; + } + return cksum; + } + + public byte[] add_checksum(List lsbCommand) + { + var cksum = checksum(lsbCommand); + lsbCommand.AddRange(BitConverter.GetBytes((ushort)cksum).Reverse()); + return lsbCommand.ToArray(); + } + + // ------------------------------------- + // Send path (input buffer reset + bit reversal + optional log) + // ------------------------------------- + public void send(byte[] command) + { + port.PurgeRx(); + var logBytes = command.ToArray(); + var msb = command.Select(b => (byte)reverse_bits(b)).ToArray(); + + if (PRINT_TX) + { + LogTx("Sending: " + BitConverter.ToString(logBytes).Replace("-", " ")); + } + + port.WriteBytes(msb); + } + + public void send_command(byte[] command) + { + send(add_checksum(new List(command))); + } + + // ------------------------------------- + // Read path (exact ordering and timing) + // ------------------------------------- + public byte[] read_response(int size) + { + var msbResponse = new List(); + var first = ReadOneByte(); + msbResponse.Add(first); + if (reverse_bits(first) == 0x82) + { + msbResponse.Add(ReadOneByte()); + } + else + { + for (var i = 0; i < size - 1; i++) + { + msbResponse.Add(ReadOneByte()); + } + } + + var lsbResponse = new List(); + foreach (var b in msbResponse) + { + lsbResponse.Add((byte)reverse_bits(b)); + } + + var debugPrint = string.Join(" ", GetHex(lsbResponse)); + if (PRINT_RX) + { + LogRx($"Received: {debugPrint}"); + } + Thread.Sleep(50); + return lsbResponse.ToArray(); + } + + private void LogTx(string message) + { + if (TxLogger != null) + { + TxLogger(message); + return; + } + + Console.WriteLine(message); + } + + private void LogRx(string message) + { + if (RxLogger != null) + { + RxLogger(message); + return; + } + + Console.WriteLine(message); + } + + private byte ReadOneByte() + { + try + { + var buffer = port.ReadBytes(1); + if (buffer.Length < 1) + { + throw new ValueError("Empty response"); + } + + return buffer[0]; + } + catch (Exception ex) when (ex is InvalidOperationException) + { + throw new ValueError(ex.Message); + } + } + + // ------------------------------------- + // Protocol commands + // ------------------------------------- + public byte[] configure(byte state) + { + ACC = 4; + var cmd = new List(); + cmd.Add(CONF_CMD); + cmd.Add((byte)ACC); + cmd.Add(8); + cmd.AddRange(BitConverter.GetBytes((ushort)CUTOFF_CURRENT).Reverse()); + cmd.AddRange(BitConverter.GetBytes((ushort)MAX_CURRENT).Reverse()); + cmd.AddRange(BitConverter.GetBytes((ushort)MAX_CURRENT).Reverse()); + cmd.Add(state); + cmd.Add(13); + var cmdBytes = cmd.ToArray(); + send_command(cmdBytes); + return read_response(5); + } + + public byte[] get_snapchat() + { + var cmd = new List { SNAP_CMD, (byte)ACC, 0 }; + var cmdBytes = cmd.ToArray(); + send_command(cmdBytes); + update_acc(); + return read_response(8); + } + + public byte[] keepalive() + { + var cmd = new List { KEEPALIVE_CMD, (byte)ACC, 0 }; + var cmdBytes = cmd.ToArray(); + send_command(cmdBytes); + return read_response(9); + } + + public byte[] calibrate() + { + var cmd = new List { CAL_CMD, (byte)ACC, 0 }; + var cmdBytes = cmd.ToArray(); + send_command(cmdBytes); + update_acc(); + return read_response(8); + } + + // ------------------------------------- + // Charger simulation routines + // ------------------------------------- + public void simulate() + { + Console.WriteLine("Simulating charger communication"); + txrx_save_and_set(true); + + reset(); + + configure(2); + get_snapchat(); + Thread.Sleep(600); + keepalive(); + configure(1); + get_snapchat(); + try + { + while (true) + { + Thread.Sleep(500); + keepalive(); + } + } + catch (ThreadInterruptedException) + { + Console.WriteLine("\nSimulation aborted by user. Exiting gracefully..."); + } + finally + { + idle(); + } + + txrx_restore(); + } + + public void simulate_for(double duration) + { + Console.WriteLine($"Simulating charger communication for {duration} seconds..."); + var beginTime = DateTime.UtcNow; + reset(); + configure(2); + get_snapchat(); + Thread.Sleep(600); + keepalive(); + configure(1); + get_snapchat(); + try + { + while ((DateTime.UtcNow - beginTime).TotalSeconds < duration) + { + Thread.Sleep(500); + keepalive(); + } + } + catch (ThreadInterruptedException) + { + Console.WriteLine("\nSimulation aborted by user. Exiting gracefully..."); + } + finally + { + idle(); + Console.WriteLine("Duration: " + (DateTime.UtcNow - beginTime).TotalSeconds); + } + } + + // ------------------------------------- + // Debug helpers + // ------------------------------------- + public void debug(byte a, byte b, byte c, int length) + { + var rxDebug = PRINT_RX; + var txDebug = PRINT_TX; + PRINT_TX = false; + PRINT_RX = false; + + reset(); + PRINT_TX = txDebug; + var data = cmd(a, b, c, length); + var dataPrint = string.Join(" ", GetHex(data)); + Console.WriteLine($"Response from: 0x{(a * 0x100 + b):04X}: {dataPrint}"); + idle(); + PRINT_RX = rxDebug; + } + + public void try_cmd(byte cmdByte, byte msb, byte lsb, byte length, int retLen = 0) + { + txrx_save_and_set(false); + if (retLen == 0) + { + retLen = length + 5; + } + + reset(); + var cmdBuf = new List { cmdByte, 0x04, 0x03, msb, lsb, length }; + var cmdBytes = cmdBuf.ToArray(); + send_command(cmdBytes); + var data = read_response(retLen); + var dataPrint = string.Join(" ", GetHex(data)); + Console.WriteLine($"Response from: 0x{(msb * 0x100 + lsb):04X}: {dataPrint}"); + idle(); + txrx_restore(); + } + + public byte[] cmd(int a, int b, int c, int length, byte command = 0x01) + { + var cmdBuf = new List { command, 0x04, 0x03, (byte)a, (byte)b, (byte)c }; + var cmdBytes = cmdBuf.ToArray(); + send_command(cmdBytes); + return read_response(length); + } + + public void brute(int a, int b, int length = 0xFF, byte command = 0x01) + { + reset(); + try + { + for (var i = 0; i < length; i++) + { + var ret = cmd(a, b, i, i + 5, command); + if (ret[0] == 0x81) + { + var dataPrint = string.Join(" ", GetHex(ret)); + Console.WriteLine($"Valid response from: 0x{(a * 0x100 + b):04X} with length: 0x{i:02X}: {dataPrint}"); + } + } + } + catch (ThreadInterruptedException) + { + Console.WriteLine("\nSimulation aborted by user. Exiting gracefully..."); + } + finally + { + idle(); + } + } + + public void full_brute(int start = 0, int stop = 0xFFFF, int length = 0xFF) + { + var addr = 0; + try + { + for (addr = start; addr < stop; addr++) + { + var msb = (addr >> 8) & 0xFF; + var lsb = addr & 0xFF; + brute(msb, lsb, length, 0x01); + if ((addr % 256) == 0) + { + Console.WriteLine($"addr = 0x{addr:04X} " + DateTime.Now); + } + } + } + catch (ThreadInterruptedException) + { + Console.WriteLine("\nSimulation aborted by user. Exiting gracefully..."); + Console.WriteLine($"\nStopped at address: 0x{addr:04X}"); + } + finally + { + idle(); + } + } + + public byte[] wcmd(byte a, byte b, byte c, int length) + { + var cmdBuf = new List { 0x01, 0x05, 0x03, a, b, c }; + var cmdBytes = cmdBuf.ToArray(); + send_command(cmdBytes); + return read_response(length); + } + + public void write_message(string message) + { + try + { + if (message.Length > 0x14) + { + Console.WriteLine("ERROR: Message too long!"); + return; + } + Console.WriteLine($"Writing \"{message}\" to memory"); + reset(); + message = message.PadRight(0x14, '-'); + for (var i = 0; i < message.Length; i++) + { + wcmd(0, (byte)(0x23 + i), (byte)message[i], 2); + } + } + catch (Exception e) + { + Console.WriteLine($"write_message: Failed with error: {e}"); + } + } + + // ------------------------------------- + // Control-line helpers + // ------------------------------------- + public void idle() + { + port.SetBreak(true); + port.SetDtr(true); + } + + public void high() + { + port.SetBreak(false); + port.SetDtr(false); + } + + public void high_for(double duration) + { + high(); + Thread.Sleep((int)(duration * 1000)); + idle(); + } + + // ------------------------------------- + // Calculations and conversions + // ------------------------------------- + public double calculate_temperature(int adcValue) + { + var r1 = 10e3; + var r2 = 20e3; + var t1 = 50; + var t2 = 35; + + var adc1 = 0x0180; + var adc2 = 0x022E; + + var m = (t2 - t1) / (r2 - r1); + var b = t1 - m * r1; + + var resistance = r1 + (adcValue - adc1) * (r2 - r1) / (adc2 - adc1); + var temperature = m * resistance + b; + + return Math.Round(temperature, 2); + } + + private ulong BigEndianToUInt(byte[] data) + { + ulong value = 0; + foreach (var b in data) + { + value = (value << 8) + b; + } + return value; + } + + public DateTime bytes2dt(byte[] timeBytes) + { + var epoch = (long)BigEndianToUInt(timeBytes); + var dt = DateTimeOffset.FromUnixTimeSeconds(epoch).UtcDateTime; + return dt; + } + + // ------------------------------------- + // Bulk read helpers + // ------------------------------------- + public void read_all() + { + try + { + reset(); + foreach (var entry in data_matrix) + { + var response = cmd(entry.Item1, entry.Item2, entry.Item3, entry.Item3 + 5); + if (response.Length >= 4 && response[0] == 0x81) + { + var data = new byte[entry.Item3]; + Array.Copy(response, 3, data, 0, entry.Item3); + var dataPrint = string.Join(" ", GetHex(data)); + Console.WriteLine($"Response from: 0x{(entry.Item1 * 0x100 + entry.Item2):04X}: {dataPrint}"); + } + else + { + var dataPrint = string.Join(" ", GetHex(response)); + Console.WriteLine($"Invalid response from: 0x{(entry.Item1 * 0x100 + entry.Item2):04X} Response: {dataPrint}"); + } + } + idle(); + } + catch (Exception e) + { + Console.WriteLine($"read_all: Failed with error: {e}"); + } + } + + public object? read_id(IEnumerable? id_array = null, bool force_refresh = true, string output = "label") + { + if (id_array == null || !id_array.Any()) + { + id_array = Enumerable.Range(0, data_id.Count); + } + + if (!((output == "label") || (output == "raw") || (output == "array") || (output == "form"))) + { + Console.WriteLine($"Unrecognised 'output' = {output}. Please choose \"label\", \"raw\", or \"array\""); + output = "label"; + } + + var array = new List(); + + try + { + reset(); + + if (force_refresh) + { + foreach (var entry in data_matrix) + { + cmd(entry.Item1, entry.Item2, entry.Item3, entry.Item3 + 5); + } + idle(); + Thread.Sleep(100); + } + + var now = DateTime.Now; + var formattedTime = now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); + if (output == "label") + { + Console.WriteLine(formattedTime); + Console.WriteLine("ID ADDR LEN TYPE LABEL VALUE"); + } + else if (output == "raw") + { + Console.WriteLine(formattedTime); + } + else if (output == "form") + { + array.Add(formattedTime); + } + + reset(); + foreach (var i in id_array) + { + var entry = data_id[i]; + var addr = entry.Item1; + var addr_h = (addr >> 8) & 0xFF; + var addr_l = addr & 0xFF; + var length = entry.Item2; + var data_type = entry.Item3; + var label = entry.Item4; + + var response = cmd(addr_h, addr_l, length, length + 5); + object? array_value; + object? value; + + if (response.Length >= 4 && response[0] == 0x81) + { + var data = new byte[length]; + Array.Copy(response, 3, data, 0, length); + switch (data_type) + { + case "uint": + array_value = value = BigEndianToUInt(data); + break; + case "date": + var dt = bytes2dt(data); + array_value = dt; + value = dt.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); + break; + case "hhmmss": + var dur = (int)BigEndianToUInt(data); + var mm = dur / 60; + var ss = dur % 60; + var hh = mm / 60; + mm = mm % 60; + array_value = value = $"{hh}:{mm:00}:{ss:00}"; + break; + case "ascii": + var str = Encoding.UTF8.GetString(data); + array_value = value = $"\"{str}\""; + break; + case "sn": + var btype = (data[0] << 8) + data[1]; + var serial = (data[2] << 16) + (data[3] << 8) + data[4]; + if (output == "label" || output == "array") + { + array_value = value = $"Type: {btype:3d}, Serial: {serial:d}"; + } + else + { + value = $"{btype}\n{serial}"; + array_value = value; + } + break; + case "adc_t": + var adcTemp = calculate_temperature((data[0] << 8) + data[1]); + array_value = value = adcTemp; + break; + case "dec_t": + var temp = data[0] + data[1] / 256.0; + array_value = value = temp.ToString("0.00", CultureInfo.InvariantCulture); + break; + case "cell_v": + var cv = new List(); + for (var idx = 0; idx < 10; idx += 2) + { + cv.Add((data[idx] << 8) + data[idx + 1]); + } + array_value = cv; + if (output == "label") + { + value = $"1: {cv[0]:4d}, 2: {cv[1]:4d}, 3: {cv[2]:4d}, 4: {cv[3]:4d}, 5: {cv[4]:4d}"; + } + else + { + value = $"{cv[0]:4d}\n{cv[1]:4d}\n{cv[2]:4d}\n{cv[3]:4d}\n{cv[4]:4d}"; + } + break; + default: + array_value = null; + value = null; + break; + } + } + else + { + array_value = null; + value = "------"; + } + + if (output == "label") + { + Console.WriteLine($"{i:3d} 0x{addr:04X} {length:2d} {data_type,6} {label,-39} {value}"); + } + else if (output == "raw") + { + Console.WriteLine(value); + } + else if (output == "array") + { + array.Add(new List { i, array_value }); + } + else if (output == "form") + { + array.Add(value); + } + } + + if ((output == "array" || output == "form") && array.Count > 0) + { + return array; + } + + idle(); + } + catch (Exception e) + { + Console.WriteLine($"read_id: Failed with error: {e}"); + } + + return null; + } + + public void read_all_spreadsheet() + { + try + { + reset(); + foreach (var entry in data_matrix) + { + cmd(entry.Item1, entry.Item2, entry.Item3, entry.Item3 + 5); + } + idle(); + Thread.Sleep(500); + + reset(); + var now = DateTime.Now; + var formattedTime = now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); + Console.WriteLine(formattedTime); + + foreach (var entry in data_matrix) + { + var response = cmd(entry.Item1, entry.Item2, entry.Item3, entry.Item3 + 5); + if (response.Length >= 4 && response[0] == 0x81) + { + var data = new byte[entry.Item3]; + Array.Copy(response, 3, data, 0, entry.Item3); + Console.WriteLine($"0x{(entry.Item1 * 0x100 + entry.Item2):04X}"); + if (data.Length == 0) + { + Console.WriteLine("EMPTY"); + } + else + { + var dataPrint = string.Join("\n", data); + Console.WriteLine(dataPrint); + } + } + else + { + Console.WriteLine($"0x{(entry.Item1 * 0x100 + entry.Item2):04X}"); + var dataPrint = string.Join(" ", GetHex(response)); + Console.WriteLine($"INV: {dataPrint}"); + for (var i = 1; i < entry.Item3; i++) + { + Console.WriteLine("blank"); + } + } + } + + idle(); + } + catch (Exception e) + { + Console.WriteLine($"read_all_spreadsheet: Failed with error: {e}"); + } + } + + public void health(bool force_refresh = true) + { + var reg_list = new List + { + 4, + 28, + 25, + 26, + 12, + 13, + 18, + 29, + 39, + 40, + 41, + 42, + 43, + 33, 32, 31, + 35, + 36, + 38 + }; + reg_list.AddRange(Enumerable.Range(44, 20)); + reg_list.AddRange(new List { 8, 2 }); + + txrx_save_and_set(true); + + try + { + Console.WriteLine("Reading battery. This will take 5-10sec\n"); + var array = read_id(reg_list, force_refresh, "array") as List; + if (array == null) + { + txrx_restore(); + return; + } + + var sn = array[40] as List; + var snValue = sn?[1]?.ToString() ?? string.Empty; + var numbers = Regex.Matches(snValue, @"\d+\.?\d*"); + var bat_type = numbers.Count > 0 ? numbers[0].Value : ""; + var e_serial = numbers.Count > 1 ? numbers[1].Value : ""; + var bat_lookup = new Dictionary + { + { "36", (1.5, "1.5Ah CP (5s1p 18650)") }, + { "37", (2, "2Ah CP (5s1p 18650)") }, + { "38", (3, "3Ah XC (5s2p 18650)") }, + { "39", (4, "4Ah XC (5s2p 18650)") }, + { "40", (5, "5Ah XC (5s2p 18650) (<= Dec 2018)") }, + { "165", (5, "5Ah XC (5s2p 18650) (Aug 2019 - Jun 2021)") }, + { "306", (5, "5Ah XC (5s2p 18650) (Feb 2021 - Jul 2023)") }, + { "424", (5, "5Ah XC (5s2p 18650) (>= Sep 2023)") }, + { "46", (6, "6Ah XC (5s2p 18650)") }, + { "47", (9, "9Ah HD (5s3p 18650)") }, + { "104", (3, "3Ah HO (5s1p 21700)") }, + { "150", (6, "5.5Ah HO (5s2p 21700) (EU only)") }, + { "106", (6, "6Ah HO (5s2p 21700)") }, + { "107", (8, "8Ah HO (5s2p 21700)") }, + { "108", (12, "12Ah HO (5s3p 21700)") }, + { "383", (8, "8Ah Forge (5s2p 21700 tabless)") }, + { "384", (12, "12Ah Forge (5s3p 21700 tabless)") } + }; + var bat_text = bat_lookup.ContainsKey(bat_type) ? bat_lookup[bat_type] : (0, "Unknown"); + Console.WriteLine($"Type: {bat_type} [{bat_text.Item2}]"); + Console.WriteLine($"E-serial: {e_serial} (does NOT match case serial)"); + + var bat_now = (array[39] as List)?[1] as DateTime? ?? DateTime.Now; + + Console.WriteLine("Manufacture date: " + ((array[0] as List)?[1] as DateTime?)?.ToString("yyyy-MM-dd")); + Console.WriteLine("Days since 1st charge: " + ((array[1] as List)?[1] ?? "")); + Console.WriteLine("Days since last tool use: " + (bat_now - (((array[2] as List)?[1] as DateTime?) ?? bat_now)).Days); + Console.WriteLine("Days since last charge: " + (bat_now - (((array[3] as List)?[1] as DateTime?) ?? bat_now)).Days); + + var cvList = (array[4] as List)?[1] as List ?? new List(); + Console.WriteLine($"Pack voltage: {cvList.Sum() / 1000.0}"); + Console.WriteLine("Cell Voltages (mV): " + string.Join(", ", cvList)); + Console.WriteLine($"Cell Imbalance (mV): {(cvList.Count > 0 ? cvList.Max() - cvList.Min() : 0)}"); + if ((array[5] as List)?[1] != null) + { + Console.WriteLine($"Temperature (deg C): {(array[5] as List)?[1]}"); + } + if ((array[6] as List)?[1] != null) + { + Console.WriteLine($"Temperature (deg C): {(array[6] as List)?[1]}"); + } + + Console.WriteLine("\nCHARGING STATS:"); + Console.WriteLine($"Charge count [Redlink, dumb, (total)]: {(array[13] as List)?[1]}, {(array[14] as List)?[1]}, ({(array[15] as List)?[1]})"); + Console.WriteLine($"Total charge time: {(array[16] as List)?[1]}"); + Console.WriteLine($"Time idling on charger: {(array[17] as List)?[1]}"); + Console.WriteLine($"Low-voltage charges (any cell <2.5V): {(array[18] as List)?[1]}"); + + Console.WriteLine("\nTOOL USE STATS:"); + var totalDischarge = Convert.ToDouble((array[7] as List)?[1] ?? 0); + Console.WriteLine("Total discharge (Ah): " + (totalDischarge / 3600).ToString("0.00", CultureInfo.InvariantCulture)); + string total_discharge_cycles; + if (bat_text.Item1 != 0) + { + total_discharge_cycles = (totalDischarge / 3600 / bat_text.Item1).ToString("0.00", CultureInfo.InvariantCulture); + } + else + { + total_discharge_cycles = "Unknown battery type, unable to calculate"; + } + Console.WriteLine($"Total discharge cycles: {total_discharge_cycles}"); + Console.WriteLine($"Times discharged to empty: {(array[8] as List)?[1]}"); + Console.WriteLine($"Times overheated: {(array[9] as List)?[1]}"); + Console.WriteLine($"Overcurrent events: {(array[10] as List)?[1]}"); + Console.WriteLine($"Low-voltage events: {(array[11] as List)?[1]}"); + Console.WriteLine($"Low-voltage bounce/stutter: {(array[12] as List)?[1]}"); + + var tool_time = 0; + for (var i = 19; i < 39; i++) + { + tool_time += Convert.ToInt32((array[i] as List)?[1] ?? 0); + } + + Console.WriteLine($"Total time on tool (>10A): {TimeSpan.FromSeconds(tool_time)}"); + + var j = 0; + for (var idx = 19; idx < 38; idx++) + { + j = idx; + var amp_range = $"{(idx - 18) * 10}-{(idx - 17) * 10}A"; + var label = $"Time @ {amp_range,8}:"; + var t = Convert.ToInt32((array[idx] as List)?[1] ?? 0); + var hhmmss = TimeSpan.FromSeconds(t); + var pct = tool_time != 0 ? Math.Round((t / (double)tool_time) * 100) : 0; + var bar = new string('X', (int)Math.Round(pct)); + Console.WriteLine($"{label} {hhmmss} {pct:00}% {bar}"); + } + j += 1; + var lastAmp = "> 200A"; + var lastLabel = $"Time @ {lastAmp,8}:"; + var lastT = Convert.ToInt32((array[j] as List)?[1] ?? 0); + var lastHhmmss = TimeSpan.FromSeconds(lastT); + var lastPct = tool_time != 0 ? Math.Round((lastT / (double)tool_time) * 100) : 0; + var lastBar = new string('X', (int)Math.Round(lastPct)); + Console.WriteLine($"{lastLabel} {lastHhmmss} {lastPct:00}% {lastBar}"); + } + catch (Exception e) + { + Console.WriteLine($"health: Failed with error: {e}"); + Console.WriteLine("Check battery is connected and you have correct serial port"); + } + + txrx_restore(); + } + + // ------------------------------------- + // Form submission (synchronous to match Python flow) + // ------------------------------------- + public void submit_form() + { + var formUrl = "https://docs.google.com/forms/d/e/1FAIpQLScvTbSDYBzSQ8S4XoF-rfgwNj97C-Pn4Px3GIixJxf0C1YJJA/formResponse"; + Console.WriteLine("Getting data from battery..."); + var output = read_id(output: "form") as List; + + if (output == null) + { + Console.WriteLine("submit_form: No output returned, aborting"); + } + var s_output = output != null ? string.Join("\n", output) : string.Empty; + + Console.WriteLine("Please provide this information. All the values can be found on the label under the battery."); + Console.Write("Enter One-Key ID (example: H18FDCAD): "); + var one_key_id = Console.ReadLine() ?? string.Empty; + Console.Write("Enter Date (example: 190316): "); + var date = Console.ReadLine() ?? string.Empty; + Console.Write("Enter Serial number (example: 0807426): "); + var serial_number = Console.ReadLine() ?? string.Empty; + Console.Write("Enter Sticker (example: 4932 4512 45): "); + var sticker = Console.ReadLine() ?? string.Empty; + Console.Write("Enter Type (example: M18B9): "); + var model_type = Console.ReadLine() ?? string.Empty; + Console.Write("Enter Capacity (example: 9.0Ah): "); + var capacity = Console.ReadLine() ?? string.Empty; + + var formData = new Dictionary + { + { "entry.905246449", one_key_id }, + { "entry.453401884", date }, + { "entry.2131879277", serial_number }, + { "entry.337435885", sticker }, + { "entry.1496274605", model_type }, + { "entry.324224550", capacity }, + { "entry.716337020", s_output } + }; + + using var client = new HttpClient(); + var response = client.PostAsync(formUrl, new FormUrlEncodedContent(formData)).Result; + + if (response.IsSuccessStatusCode) + { + Console.WriteLine("Form submitted successfully!"); + } + else + { + Console.WriteLine($"submit_form: Failed to submit form. Status code: {(int)response.StatusCode}"); + } + } + + // ------------------------------------- + // Help text (unchanged) + // ------------------------------------- + public void help() + { + Console.WriteLine("Functions: \n" + + "DIAGNOSTICS: \n" + + "m.health() - print simple health report on battery \n" + + "m.read_id() - print labelled and formatted diagnostics \n" + + "m.read_id(output=\"raw\") - print in spreadsheet format \n" + + "m.submit_form() - prompts for manual inputs and submits battery diagnostics data \n" + + "\n" + + "m.help() - this message\n" + + "m.adv_help() - advanced help\n" + + "\n" + + "exit() - end program\n"); + } + + public void adv_help() + { + Console.WriteLine("Advanced functions: \n" + + "m.read_all() - print all known bytes in 0x01 command \n" + + "m.read_all_spreadsheet() - print bytes in spreadsheet format \n" + + "\n" + + "CHARGING SIMULATION: \n" + + "m.simulate() - simulate charging comms \n" + + "m.simulate_for(t) - simulate for t seconds \n" + + "m.high_for(t) - bring J2 high for t sec, then idle \n" + + "\n" + + "m.write_message(message) - write ascii string to 0x0023 register (20 chars)\n" + + "\n" + + "Debug: \n" + + "m.PRINT_TX = True - boolean to enable TX messages \n" + + "m.PRINT_RX = True - boolean to enable RX messages \n" + + "m.txrx_print(bool) - set PRINT_TX & RX to bool \n" + + "m.txrx_save_and_set(bool) - save PRINT_TX & RX state, then set both to bool \n" + + "m.txrx_restore() - restore PRINT_TX & RX to saved values \n" + + "m.brute(addr_msb, addr_lsb) \n" + + "m.full_brute(start, stop, len) - check registers from 'start' to 'stop'. look for 'len' bytes \n" + + "m.debug(addr_msb, addr_lsb, len, rsp_len) - send reset() then cmd() to battery \n" + + "m.try_cmd(cmd, addr_h, addr_l, len) - try 'cmd' at [addr_h addr_l] with 'len' bytes \n" + + "\n" + + "Internal:\n" + + "m.high() - bring J2 pin high (20V)\n" + + "m.idle() - pull J2 pin low (0V) \n" + + "m.reset() - send 0xAA to battery. Return true if battery replies wih 0xAA \n" + + "m.get_snapchat() - request 'snapchat' from battery (0x61)\n" + + "m.configure() - send 'configure' message (0x60, charger parameters)\n" + + "m.calibrate() - calibration/interrupt command (0x55) \n" + + "m.keepalive() - send charge current request (0x62) \n"); + } + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..79c1bee --- /dev/null +++ b/Program.cs @@ -0,0 +1,51 @@ +// ************************************************************************************************* +// Program.cs +// ---------- +// Entry point for the WinForms application. This file ties the executable to the UI defined in +// frmMain (the main form constructed in M18AnalyzerMain.cs / M18AnalyzerMain.Designer.cs) and uses +// ApplicationConfiguration to bootstrap high-DPI awareness and default fonts. The goal is to show +// how a C# WinForms app starts, how STAThread is required for COM-based UI components, and where the +// program transitions from the process boundary into user-interface code that eventually invokes +// serial-protocol logic in M18Protocol.cs and USB enumeration utilities in SerialPortUtil.cs. Even +// though the logic is minimal, commenting every line reveals the basic structure of a .NET desktop +// program for newcomers. +// ************************************************************************************************* + +namespace M18BatteryInfo +{ + /// + /// Hosts the Main method required by .NET to start execution. The class is marked internal to + /// keep the symbol inside the assembly while still being discoverable by the runtime. It + /// delegates all user interaction to , which wires up event handlers to + /// the serial protocol layer () and utility helpers + /// () that talk to hardware. + /// + internal static class Program + { + /// + /// The main entry point for the application. The STAThread attribute is mandatory for + /// WinForms because UI components rely on COM apartment threading. The method enables + /// framework-level configuration (high DPI, default fonts) and then instantiates and shows + /// the primary form, which in turn registers all button click handlers that trigger + /// hardware traffic over UART. + /// + [STAThread] + static void Main() + { + // Initialize WinForms settings such as DPI awareness and default font. This call lives + // in System.Windows.Forms.ApplicationConfiguration and is automatically generated when + // you create a modern WinForms project. Without it, UI rendering may be blurry on high + // DPI displays. This line does not touch our custom code but configures the Win32/WinForms + // plumbing that all later GUI code depends on. + ApplicationConfiguration.Initialize(); + + // Create and run the main window. Application.Run enters the WinForms message loop + // (GetMessage/DispatchMessage under the hood) and will not exit until the form closes. + // We construct frmMain, which is defined across M18AnalyzerMain.cs (logic) and + // M18AnalyzerMain.Designer.cs (control layout). That form then interacts with + // M18Protocol.cs to toggle UART lines and read battery data, plus SerialPortUtil.cs to + // discover serial devices. + Application.Run(new frmMain()); + } + } +} diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs new file mode 100644 index 0000000..848d075 --- /dev/null +++ b/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace M18BatteryInfo.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("M18BatteryInfo.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Properties/Resources.resx b/Properties/Resources.resx new file mode 100644 index 0000000..29dcb1b --- /dev/null +++ b/Properties/Resources.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/PythonProcessController.cs b/PythonProcessController.cs new file mode 100644 index 0000000..10b2c30 --- /dev/null +++ b/PythonProcessController.cs @@ -0,0 +1,240 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace M18BatteryInfo +{ + /// + /// Hosts the m18.py process and provides asynchronous helpers for sending commands, capturing + /// stdout/stderr, and detecting the Python REPL prompt. The class is intentionally thin and + /// delegates all protocol behavior to the Python script. + /// + public sealed class PythonProcessController : IDisposable + { + private readonly object _syncRoot = new(); + private Process? _process; + private TaskCompletionSource? _promptTcs; + private CancellationTokenSource? _shutdownCts; + + public string PythonExecutablePath { get; set; } + public string ScriptPath { get; set; } + public bool IsRunning => _process != null && !_process.HasExited; + + public event Action? OutputReceived; + public event Action? ErrorReceived; + public event Action? PromptDetected; + public event Action? Exited; + + public PythonProcessController(string pythonExecutablePath, string scriptPath) + { + PythonExecutablePath = pythonExecutablePath; + ScriptPath = scriptPath; + } + + /// + /// Launch m18.py as a child process. Throws if the process is already running or if the + /// underlying executable/script cannot be started. + /// + public Task StartAsync(string? portArgument, CancellationToken cancellationToken = default) + { + if (IsRunning) + { + throw new InvalidOperationException("Python process is already running."); + } + + _shutdownCts?.Dispose(); + _shutdownCts = new CancellationTokenSource(); + _process?.Dispose(); + _process = null; + + var startInfo = BuildStartInfo(portArgument); + var process = new Process + { + StartInfo = startInfo, + EnableRaisingEvents = true + }; + + process.OutputDataReceived += (_, args) => + { + if (args.Data != null) + { + HandleOutputLine(args.Data); + } + }; + + process.ErrorDataReceived += (_, args) => + { + if (args.Data != null) + { + ErrorReceived?.Invoke(args.Data); + } + }; + + process.Exited += (_, _) => + { + Exited?.Invoke(process.ExitCode); + _shutdownCts?.Cancel(); + }; + + if (!process.Start()) + { + throw new InvalidOperationException("Failed to start python process."); + } + + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + _process = process; + + return Task.CompletedTask; + } + + /// + /// Send a command string to the Python REPL and wait for the next prompt. Returns false if a + /// timeout occurs; the process is left running so callers can decide how to recover. + /// + public async Task SendCommandAsync(string command, TimeSpan timeout) + { + if (!IsRunning || _process?.StandardInput == null) + { + throw new InvalidOperationException("Python process is not running."); + } + + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + lock (_syncRoot) + { + _promptTcs = tcs; + } + + await _process.StandardInput.WriteLineAsync(command); + await _process.StandardInput.FlushAsync(); + + var delayTask = Task.Delay(timeout, _shutdownCts?.Token ?? CancellationToken.None); + var completed = await Task.WhenAny(tcs.Task, delayTask); + + if (completed == tcs.Task && tcs.Task.IsCompleted) + { + return true; + } + + lock (_syncRoot) + { + if (ReferenceEquals(_promptTcs, tcs)) + { + _promptTcs = null; + } + } + + return false; + } + + /// + /// Attempt a graceful shutdown by sending exit() to stdin and waiting for the process to + /// exit. If the process does not exit within the timeout, it will be killed. + /// + public async Task StopAsync(TimeSpan timeout) + { + if (!IsRunning || _process?.StandardInput == null) + { + return; + } + + try + { + await _process.StandardInput.WriteLineAsync("exit()"); + await _process.StandardInput.FlushAsync(); + } + catch + { + // Ignore input failures; we'll fall back to kill below. + } + + var exitedTask = WaitForExitAsync(); + var completed = await Task.WhenAny(exitedTask, Task.Delay(timeout)); + + if (completed != exitedTask && IsRunning) + { + try + { + _process.Kill(true); + } + catch + { + // Swallow kill failures to avoid throwing on shutdown. + } + } + } + + public void Dispose() + { + _shutdownCts?.Cancel(); + _shutdownCts?.Dispose(); + _process?.Dispose(); + } + + private Task WaitForExitAsync() + { + if (_process == null) + { + return Task.CompletedTask; + } + + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + _process.EnableRaisingEvents = true; + _process.Exited += (_, _) => tcs.TrySetResult(true); + + if (_process.HasExited) + { + tcs.TrySetResult(true); + } + + return tcs.Task; + } + + private ProcessStartInfo BuildStartInfo(string? portArgument) + { + var workingDirectory = Path.GetDirectoryName(ScriptPath); + var arguments = $"\"{ScriptPath}\""; + if (!string.IsNullOrWhiteSpace(portArgument)) + { + arguments += $" --port {portArgument}"; + } + + return new ProcessStartInfo + { + FileName = PythonExecutablePath, + Arguments = arguments, + WorkingDirectory = string.IsNullOrWhiteSpace(workingDirectory) ? Environment.CurrentDirectory : workingDirectory, + RedirectStandardInput = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }; + } + + private void HandleOutputLine(string line) + { + OutputReceived?.Invoke(line); + + if (IsPrompt(line)) + { + lock (_syncRoot) + { + _promptTcs?.TrySetResult(true); + _promptTcs = null; + } + + PromptDetected?.Invoke(); + } + } + + private static bool IsPrompt(string line) + { + var trimmed = line.Trim(); + return trimmed == ">>>" || trimmed.EndsWith(">>>", StringComparison.Ordinal); + } + } +} diff --git a/PythonScriptRunner.cs b/PythonScriptRunner.cs new file mode 100644 index 0000000..359a024 --- /dev/null +++ b/PythonScriptRunner.cs @@ -0,0 +1,59 @@ +// ************************************************************************************************* +// PythonScriptRunner.cs +// --------------------- +// Provides a tiny helper to execute the companion Python script (m18.py) from within the C# GUI. +// This allows reuse of the original Python implementation when experimenting or comparing results. +// Comments explain how ProcessStartInfo is configured to capture stdout/stderr without opening a +// console window, which is useful when embedding scripting in desktop applications. +// ************************************************************************************************* + +using System; // Access to AppDomain for locating the application base directory. +using System.Diagnostics; // Process and ProcessStartInfo for launching external interpreters. +using System.IO; // Path.Combine to build script path safely across OSes. +using System.Text; // StringBuilder for efficient concatenation of stdout/stderr text. + +namespace M18BatteryInfo +{ + /// + /// Utility class for launching the Python reference implementation (m18.py) with arbitrary + /// arguments. Captures standard output and error streams for display in the WinForms UI. + /// + public static class PythonScriptRunner + { + /// + /// Executes m18.py with the provided argument string. The method starts a child process + /// configured to hide its console window, captures both stdout and stderr, waits for the + /// process to exit, and returns the combined output. This is helpful for comparing Python + /// protocol behavior to the C# port without leaving the GUI. + /// + /// Arguments passed directly to m18.py (for example, "health"). + /// Combined standard output and error text from the Python process. + public static string RunPythonScript(string arguments) + { + var scriptPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "m18.py"); // Build absolute path to bundled Python script located next to executable. + + var startInfo = new ProcessStartInfo + { + FileName = "python", // Use system Python interpreter (must be on PATH). + Arguments = $"\"{scriptPath}\" {arguments}".Trim(), // Quote script path to handle spaces; append user arguments. + WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory, // Run from app directory so relative imports/resources resolve. + RedirectStandardOutput = true, // Capture stdout so UI can display results. + RedirectStandardError = true, // Capture stderr for troubleshooting Python exceptions. + UseShellExecute = false, // Required when redirecting streams; avoids shell involvement. + CreateNoWindow = true // Prevent console window from flashing when launched from GUI. + }; + + using var process = new Process { StartInfo = startInfo }; // Create Process with configured start info inside using to ensure disposal. + var outputBuilder = new StringBuilder(); // Collects both stdout and stderr text. + + process.Start(); // Launch python process; OS loads interpreter and script. + + outputBuilder.Append(process.StandardOutput.ReadToEnd()); // Read stdout to completion (blocking until stream closes). + outputBuilder.Append(process.StandardError.ReadToEnd()); // Read stderr to completion; concatenated for holistic log. + + process.WaitForExit(); // Ensure process has exited before returning to caller. + + return outputBuilder.ToString(); // Return combined output for display/logging. + } + } +} diff --git a/README.md b/README.md deleted file mode 100644 index 82e99c3..0000000 --- a/README.md +++ /dev/null @@ -1,83 +0,0 @@ -# M18 Protocol - -This repository contains research about the Milwaukee M18 protocol. - -First step was to fake the charger commands in order to verify that the communication works as expected. :white_check_mark: Next step was figuring out what other commands are supported. :white_check_mark: - -While most of the registers and data are known, there are still some unknown. Contributions are welcome! - -## Hardware - -In order to simulate the charger, the following circuit is proposed: - -**NOTE When using fake FT232 chips, break condition is not supported. The behaviour can be emulated by using the DTR line to pull the TX line low.** - -List of [working and non-working devices](https://github.com/mnh-jansson/m18-protocol/discussions/16). Please add yours if not already listed. - -The voltage of the USB to Serial adapter should be 3.3V - -![hardware](docs/wiring.png) - -## Requirements and Usage - -To use this software, Python is required. Please read the [python](https://docs.python.org/3/) and [pip](https://pip.pypa.io/en/stable/installation/) documentation. - -Install the required packages by running - -```bash -pip install -r requirements.txt -``` - -Once the required packages are installed, run the following command. If the serial port is known, specify it using `--port` to speed things up. - -```bash -python3 m18.py -``` -or on Windows -```bash -python.exe m18.py -``` - -Alternatively, use the [uv](https://docs.astral.sh/uv/) package manager to create an isolated virtual environment, install the correct version of Python, install dependencies, and execute the project: - -```bash -uv run m18.py -``` - - -This opens an interactive shell that can be used to send different commands. Refer to the instructions provided in the shell. - -## Output - -* Most users will just want to use `m.health()` for a simple health report. -* To see all registers, use `m.read_id()` -* To output all registers in a format that can be copy/pasted into a spreadsheet, use `m.read_id(output="raw")` -* To help us identify unknown registers, you can submit your diagnostics to us with `m.submit_form()`. This will prompt you for the 3 parts of the serial number, the type of battery (e.g. 3Ah high output), and other stuff that you can leave blank if you like - -A spreadsheet template can be found below. Do NOT request access, go to `File -> Make a copy` or `File -> Download` - -https://docs.google.com/spreadsheets/d/1rZZ3mtU2uwuo_uMv7O7hi5kyPA9AXUDU5CBsHKWMi-U/ - -## Windows Users -There are 4 .bat files for Windows users that are not familiar with the command line. Double-click on them to run them. -* `m18_idle.bat` will prompt you to select a serial device, then bring the TX (J2) pin low. This is recommended before connecting to the battery to avoid increasing the counter for dumb-charges -* `m18_health.bat` will print out a simple health report. The adapter must be connected to the battery or you will get errors -* `m18_interactive.bat` will put you into the interactive shell where you can call `m.health()`, `m.read_id()`, and submit your diagnostics to us with `m.submit_form()` -* `m18_clipboard.bat` will fetch all diagnostic registers and copy them to the clipboard. You must right-click on this .bat file and select `Edit`, then change `--port COM5` to whatever your port is. Once finished, you can select a cell in a spreadsheet (for example, the template provided above), and ctrl+v to copy all the registers - -## Troubleshooting -Some USB serial adapters don't give/receive the correct voltages when paired with M18 batteries. To test if this is your problem, connect adapter to battery then measure voltages between B- and J2 (next to B-) and J1 (next to B+). Then use the m.idle() and m.high() commands. - -You should see: -* m.idle(): J2<1V, J1<1V -* m.high(): J2>8V, J2>2V - -I get: -* m.idle(): J2=0.13V, J1=0.81V -* m.high(): J2=8.8V, J1=3.3V - -If m.idle() has J1 > 1V, then [this circuit](https://github.com/mnh-jansson/m18-protocol/issues/7#issuecomment-3312151944) by Spud2233 has fixed this issue for some people. -![isolator](docs/spud_isolator.png) - - - diff --git a/SerialPortConnection.cs b/SerialPortConnection.cs new file mode 100644 index 0000000..03aa78a --- /dev/null +++ b/SerialPortConnection.cs @@ -0,0 +1,139 @@ +// ************************************************************************************************* +// SerialPortConnection.cs +// ----------------------- +// Wraps RJCP.IO.Ports.SerialPortStream with helper methods that mirror the subset of operations +// needed by M18Protocol: opening the port with specific framing, toggling BREAK/DTR, purging +// buffers, and reading/writing exact byte counts. The wrapper also supports an optional raw logger +// to surface low-level serial actions to the UI without exposing SerialPortStream directly. RJCP +// provides .NET 10 support and granular control-line handling that matches the Python reference +// script, including manual Break/DTR and millisecond timeouts. +// ************************************************************************************************* + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Diagnostics; +using RJCP.IO.Ports; + +namespace M18BatteryInfo; + +public sealed class SerialPortConnection : IDisposable +{ + private readonly SerialPortStream _serialPort; + private Action? _rawLogger; + + public SerialPortConnection(SerialPortDisplay device, Action? rawLogger) + { + Device = device; + _rawLogger = rawLogger; + + _serialPort = new SerialPortStream(device.PortName, 4800, 8, Parity.None, StopBits.Two) + { + ReadTimeout = 800, + WriteTimeout = 800, + DtrEnable = false, + RtsEnable = false + }; + + Log($"Opening {device.PortName} at 4800 8N2 using RJCP.SerialPortStream"); + _serialPort.Open(); + PurgeAll(); + } + + public SerialPortDisplay Device { get; } + + public bool IsOpen => _serialPort.IsOpen; + + public void SetBreak(bool enable) + { + _serialPort.BreakState = enable; + Log($"SerialPort.BreakState={(enable ? "On" : "Off")}"); + } + + public void SetDtr(bool enable) + { + _serialPort.DtrEnable = enable; + Log($"SerialPort.DtrEnable={(enable ? "On" : "Off")}"); + } + + public void PurgeAll() + { + _serialPort.DiscardInBuffer(); + _serialPort.DiscardOutBuffer(); + Log("SerialPort.DiscardInBuffer/DiscardOutBuffer"); + } + + public void PurgeRx() + { + _serialPort.DiscardInBuffer(); + Log("SerialPort.DiscardInBuffer"); + } + + public void WriteBytes(byte[] data) + { + _serialPort.Write(data, 0, data.Length); + _serialPort.Flush(); // Ensure immediate transmission; mirrors Python's synchronous writes. + Log($"SerialPort.Write {FormatHex(data)}"); + } + + public byte[] ReadBytes(int count) + { + var buffer = new byte[count]; + var totalRead = 0; + var stopwatch = Stopwatch.StartNew(); + try + { + while (totalRead < count) + { + var bytesRead = _serialPort.Read(buffer, totalRead, count - totalRead); + totalRead += bytesRead; + } + } + catch (TimeoutException ex) + { + throw new InvalidOperationException($"SerialPort.Read timed out after reading {totalRead} of {count} byte(s) over {stopwatch.ElapsedMilliseconds} ms", ex); + } + + stopwatch.Stop(); + Log($"SerialPort.Read count={count}, bytesRead={totalRead}, elapsed={stopwatch.ElapsedMilliseconds}ms, data={FormatHex(buffer.Take(totalRead))}"); + + if (totalRead < count) + { + throw new InvalidOperationException($"SerialPort.Read returned {totalRead} of {count} byte(s)"); + } + + return buffer; + } + + public void Close() + { + if (!_serialPort.IsOpen) + { + return; + } + + Log("SerialPort.Close"); + _serialPort.Close(); + } + + public void Dispose() + { + Close(); + _serialPort.Dispose(); + } + + public void UpdateLogger(Action? logger) + { + _rawLogger = logger; + } + + private void Log(string message) + { + _rawLogger?.Invoke(message); + } + + private static string FormatHex(IEnumerable data) + { + return string.Join(" ", data.Select(b => $"{b:X2}")); + } +} diff --git a/SerialPortUtil.cs b/SerialPortUtil.cs new file mode 100644 index 0000000..6ca1b24 --- /dev/null +++ b/SerialPortUtil.cs @@ -0,0 +1,521 @@ +// ************************************************************************************************* +// SerialPortUtil.cs +// ------------------ +// Provides detailed COM-port enumeration for Windows using the SetupAPI P/Invoke layer. This mirrors +// Python's pyserial list_ports.comports() by retrieving friendly names, hardware IDs (VID/PID), +// manufacturer strings, and registry data. The WinForms UI (frmMain) uses these helpers to populate +// the serial-port combo box with human-readable entries and to supply debug metadata for hardware +// troubleshooting. Every method is heavily commented to explain Windows API interop, registry access, +// and why multiple discovery strategies are combined. +// ************************************************************************************************* + +using System; // Core types like IntPtr and StringComparer. +using System.Collections.Generic; // Collections used to gather port metadata. +using System.Linq; // LINQ helpers for ordering and filtering port lists. +using System.Runtime.InteropServices; // P/Invoke attributes to call SetupAPI functions. +using System.Text; // StringBuilder for marshaling strings from unmanaged memory. +using System.Text.RegularExpressions; // Regex for extracting COM port names and USB VID/PID. +using Microsoft.Win32; // Registry access to augment port data. +using Microsoft.Win32.SafeHandles; // Safe handle wrapper for registry keys opened via SetupAPI. + +namespace M18BatteryInfo; + +/// + /// Provides serial port enumeration using Windows SetupAPI to capture detailed descriptions similar + /// to Python's pyserial list_ports.comports(). The class combines multiple discovery sources (friendly + /// names, registry keys, and GetPortNames) to produce robust metadata for UI display and debugging. +/// +internal static class SerialPortUtil +{ + // SetupAPI flags and registry property identifiers. These magic numbers come from Windows header + // files (setupapi.h/devpkey.h) and let us request specific properties from the device tree. + private const uint DIGCF_PRESENT = 0x00000002; // Return only devices currently present in the system (ignores removed/phantom devices). + + private const uint SPDRP_DEVICEDESC = 0x00000000; // Device description (REG_SZ) property key. + private const uint SPDRP_HARDWAREID = 0x00000001; // Hardware IDs (REG_MULTI_SZ) property key (contains VID/PID). + private const uint SPDRP_MFG = 0x0000000B; // Manufacturer string (REG_SZ) property key. + private const uint SPDRP_FRIENDLYNAME = 0x0000000C; // Friendly name shown in Device Manager (REG_SZ). + private const uint SPDRP_LOCATION_INFORMATION = 0x0000000D; // Location information string (REG_SZ) e.g., USB port path. + + private const uint DEVPROP_TYPE_STRING = 0x12; // DEVPROP_TYPE_STRING constant used with SetupDiGetDeviceProperty. + private const uint DEVPROP_TYPE_STRING_LIST = 0x1012; // DEVPROP_TYPE_STRING | DEVPROP_TYPEMOD_LIST for multi-string values. + + private const uint DIREG_DEV = 0x00000001; // Flag to open hardware key for device. + private const int KEY_QUERY_VALUE = 0x0001; // Registry access mask for querying values. + + private static readonly Guid PortsClassGuid = new("4d36e978-e325-11ce-bfc1-08002be10318"); // GUID for Ports (COM & LPT) device class. + private static readonly DEVPROPKEY DEVPKEY_Device_LocationPaths = new() + { + fmtid = new Guid("9d7debbc-c85d-4e75-a5f2-0e0e3bfb4ffd"), // GUID for location paths property set. + pid = 37 // Property identifier within the set representing location paths. + }; + + /// + /// Enumerates serial ports using SetupAPI and returns metadata suitable for UI display. This helper + /// remains to correlate FTDI serial numbers with COM port assignments for reference only; all I/O + /// now flows through RJCP.IO.Ports.SerialPortStream. + /// + /// Optional logger for verbose debug output. + /// Ordered list of serial port metadata. + public static List EnumerateDetailedPorts(Action? debugLogger = null) + { + var ports = new Dictionary(StringComparer.OrdinalIgnoreCase); // Use dictionary to merge data from multiple sources case-insensitively. + + EnumerateViaSetupApi(ports, debugLogger); // Primary enumeration using SetupAPI P/Invoke for rich data. + + return ports.Values + .OrderBy(port => port.PortName, StringComparer.OrdinalIgnoreCase) // Sort alphabetically for predictable UI ordering. + .ToList(); // Materialize list for caller. + } + + private static void EnumerateViaSetupApi(IDictionary ports, Action? log) + { + // Acquire a handle to the Ports device class (COM & LPT) containing the serial devices. The GUID restricts + // the search to devices implementing the ports interface so we do not enumerate unrelated hardware. + var portsClassGuid = PortsClassGuid; + var deviceInfoSet = SetupDiGetClassDevs(ref portsClassGuid, null, IntPtr.Zero, DIGCF_PRESENT); // Calls into setupapi.dll. + if (deviceInfoSet == IntPtr.Zero || deviceInfoSet == new IntPtr(-1)) + { + log?.Invoke("SetupAPI enumeration failed to acquire device info set; no COM metadata available."); // Warn UI that we cannot fetch metadata. + return; // Without a valid handle we cannot enumerate. + } + + try + { + var devInfoData = new SP_DEVINFO_DATA + { + cbSize = (uint)Marshal.SizeOf() // Populate structure size before calling into SetupAPI. + }; + + for (uint index = 0; SetupDiEnumDeviceInfo(deviceInfoSet, index, ref devInfoData); index++) // Loop through devices until function returns false. + { + try + { + var friendlyName = GetDeviceRegistryProperty(deviceInfoSet, ref devInfoData, SPDRP_FRIENDLYNAME); // Pull human-friendly text e.g., "USB Serial Port (COM3)". + var description = GetDeviceRegistryProperty(deviceInfoSet, ref devInfoData, SPDRP_DEVICEDESC); // Generic device description. + var manufacturer = GetDeviceRegistryProperty(deviceInfoSet, ref devInfoData, SPDRP_MFG); // Manufacturer string (e.g., FTDI). + var hardwareIds = GetMultiStringProperty(deviceInfoSet, ref devInfoData, SPDRP_HARDWAREID); // Multi-string containing USB VID/PID. + var locationInformation = GetDeviceRegistryProperty(deviceInfoSet, ref devInfoData, SPDRP_LOCATION_INFORMATION); // Port location info (hub/port). + var locationPaths = GetDevicePropertyMultiString(deviceInfoSet, ref devInfoData, DEVPKEY_Device_LocationPaths); // More detailed location path list. + var deviceInstanceId = GetDeviceInstanceId(deviceInfoSet, ref devInfoData); // Unique device instance string used for registry lookup. + + var (portName, portSource) = ExtractBestPortName(friendlyName, description, deviceInfoSet, ref devInfoData, deviceInstanceId); // Try multiple strategies to extract "COMx". + + if (string.IsNullOrWhiteSpace(portName)) + { + log?.Invoke($"SetupAPI device entry missing COM port name. Desc: '{description ?? friendlyName ?? "(none)"}'"); // Skip devices without COM port string. + continue; + } + + ports.TryGetValue(portName!, out var existing); // Try to merge with existing record if fallback already added. + existing ??= SerialPortDisplay.Create(portName!); // Create base record when first seen. + var combinedSource = CombineSources(existing.Source, "SetupAPI (Ports class)"); // Track provenance for debugging. + + var parsedUsb = ParseUsbIdentifiers(hardwareIds, deviceInstanceId); // Parse VID/PID/serial from hardware IDs and instance ID. + var locationPath = locationPaths?.FirstOrDefault() ?? locationInformation; // Prefer detailed location path but fall back to location info. + + // Merge new data into record, preserving existing values when already populated by other sources. + ports[portName!] = existing with + { + Description = string.IsNullOrWhiteSpace(existing.Description) ? description : existing.Description, + Manufacturer = string.IsNullOrWhiteSpace(existing.Manufacturer) ? manufacturer : existing.Manufacturer, + FriendlyName = string.IsNullOrWhiteSpace(existing.FriendlyName) ? friendlyName : existing.FriendlyName, + HardwareIds = string.IsNullOrWhiteSpace(existing.HardwareIds) ? hardwareIds : existing.HardwareIds, + DeviceInstanceId = string.IsNullOrWhiteSpace(existing.DeviceInstanceId) ? deviceInstanceId : existing.DeviceInstanceId, + UsbVendorId = string.IsNullOrWhiteSpace(existing.UsbVendorId) ? parsedUsb.Vid : existing.UsbVendorId, + UsbProductId = string.IsNullOrWhiteSpace(existing.UsbProductId) ? parsedUsb.Pid : existing.UsbProductId, + UsbSerialNumber = string.IsNullOrWhiteSpace(existing.UsbSerialNumber) ? parsedUsb.SerialNumber : existing.UsbSerialNumber, + LocationPath = string.IsNullOrWhiteSpace(existing.LocationPath) ? locationPath : existing.LocationPath, + Source = combinedSource + }; + + // Emit verbose log of all discovered values so users can diagnose driver issues. + LogDevice(log, portName!, new() + { + ($"FriendlyName", friendlyName, "SetupAPI SPDRP_FRIENDLYNAME"), + ($"Description", description, "SetupAPI SPDRP_DEVICEDESC"), + ($"Manufacturer", manufacturer, "SetupAPI SPDRP_MFG"), + ($"HardwareIds", hardwareIds, "SetupAPI SPDRP_HARDWAREID"), + ($"DeviceInstanceId", deviceInstanceId, "SetupDiGetDeviceInstanceId"), + ($"LocationPath", locationPath, "DEVPKEY_Device_LocationPaths/SPDRP_LOCATION_INFORMATION"), + ($"USB VID", parsedUsb.Vid, "Parsed from hardware IDs"), + ($"USB PID", parsedUsb.Pid, "Parsed from hardware IDs"), + ($"USB Serial", parsedUsb.SerialNumber, "Parsed from device instance"), + ($"Port source", portSource, "FriendlyName/Description/Registry") + }); + } + catch (Exception ex) + { + log?.Invoke($"SetupAPI enumeration error: {ex.Message}"); // Log individual device failures without aborting enumeration. + } + } + } + finally + { + SetupDiDestroyDeviceInfoList(deviceInfoSet); // Always release the device info set handle to avoid leaks. + } + } + + private static (string? Port, string Source) ExtractBestPortName(string? friendlyName, string? description, IntPtr deviceInfoSet, ref SP_DEVINFO_DATA devInfoData, string? deviceInstanceId) + { + var portFromFriendly = ExtractPortName(friendlyName); // Friendly name often contains "(COM3)" suffix. + if (!string.IsNullOrWhiteSpace(portFromFriendly)) + { + return (portFromFriendly, "Friendly name"); // Return immediately when found in friendly name. + } + + var portFromDescription = ExtractPortName(description); // Device description sometimes includes COM port. + if (!string.IsNullOrWhiteSpace(portFromDescription)) + { + return (portFromDescription, "Device description"); // Use description source if found. + } + + var registryPort = TryGetPortNameFromRegistry(deviceInfoSet, ref devInfoData); // Query device-specific registry key for PortName value. + if (!string.IsNullOrWhiteSpace(registryPort)) + { + return (registryPort, "Device registry PortName"); // Use value from HKLM\SYSTEM\CurrentControlSet\Enum\\Device Parameters. + } + + var enumRegistryPort = TryGetPortNameFromEnumRegistry(deviceInstanceId); // Try alternate registry path using device instance ID. + if (!string.IsNullOrWhiteSpace(enumRegistryPort)) + { + return (enumRegistryPort, "HKLM\\SYSTEM\\CurrentControlSet\\Enum device parameters"); // Note source for debugging. + } + + return (null, "Unavailable"); // Signal failure to extract COM port name. + } + + private static void LogDevice(Action? log, string portName, List<(string Name, string? Value, string Source)> values) + { + if (log == null) + { + return; // No logger supplied; do nothing. + } + + var builder = new StringBuilder(); + builder.Append($"Detected {portName} with: "); // Prefix with port name for clarity. + foreach (var (name, value, source) in values) + { + if (string.IsNullOrWhiteSpace(value)) + { + continue; // Skip empty values to avoid noise. + } + + builder.Append($"{name}='{value}' (from {source}); "); // Append each property and where it came from for auditability. + } + + log(builder.ToString().Trim()); // Emit constructed line to UI logger. + } + + private static string CombineSources(string? existingSource, string newSource) + { + if (string.IsNullOrWhiteSpace(existingSource)) + { + return newSource; // If no existing source, return the new one. + } + + return existingSource.Contains(newSource, StringComparison.OrdinalIgnoreCase) + ? existingSource // Avoid duplicating same source string. + : $"{existingSource}; {newSource}"; // Concatenate sources with semicolon to show multiple discovery paths. + } + + private static string? GetDeviceInstanceId(IntPtr deviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData) + { + var buffer = new StringBuilder(512); // Start with moderate buffer size for instance ID. + if (SetupDiGetDeviceInstanceId(deviceInfoSet, ref deviceInfoData, buffer, (uint)buffer.Capacity, out var requiredSize)) + { + return buffer.ToString(); // Return instance ID string when call succeeds. + } + + if (Marshal.GetLastWin32Error() != 122) // ERROR_INSUFFICIENT_BUFFER + { + return null; // If failure not due to buffer size, give up. + } + + buffer = new StringBuilder((int)requiredSize); // Resize buffer to required size. + return SetupDiGetDeviceInstanceId(deviceInfoSet, ref deviceInfoData, buffer, (uint)buffer.Capacity, out _) + ? buffer.ToString() // Return string on success. + : null; // Otherwise return null. + } + + private static string? GetDeviceRegistryProperty(IntPtr deviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData, uint property) + { + var buffer = new byte[1024]; // Allocate buffer for UTF-16 data. + + if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref deviceInfoData, property, out _, buffer, (uint)buffer.Length, out var requiredSize) || requiredSize == 0) + { + return null; // Return null when property missing or call fails. + } + + return Encoding.Unicode.GetString(buffer, 0, (int)requiredSize).TrimEnd('\0'); // Decode UTF-16 and trim null terminator. + } + + private static string? GetMultiStringProperty(IntPtr deviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData, uint property) + { + var buffer = new byte[2048]; // Allocate larger buffer for REG_MULTI_SZ values. + + if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref deviceInfoData, property, out var regType, buffer, (uint)buffer.Length, out var requiredSize) || requiredSize == 0) + { + return null; // Fail fast on missing data. + } + + // REG_MULTI_SZ is a sequence of null-terminated UTF-16 strings ending with an additional null terminator. + if (regType != 7) // 7 = REG_MULTI_SZ + { + return Encoding.Unicode.GetString(buffer, 0, (int)requiredSize).TrimEnd('\0'); // For non-multi strings, decode directly. + } + + var multiSz = Encoding.Unicode.GetString(buffer, 0, (int)requiredSize).TrimEnd('\0'); // Decode concatenated strings. + var entries = multiSz.Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries); // Split into individual entries. + return entries.Length == 0 ? null : string.Join(", ", entries); // Join with comma for display. + } + + private static List? GetDevicePropertyMultiString(IntPtr deviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData, DEVPROPKEY propertyKey) + { + var buffer = new byte[4096]; // Large buffer for location paths list. + + if (!SetupDiGetDeviceProperty(deviceInfoSet, ref deviceInfoData, ref propertyKey, out var propertyType, buffer, (uint)buffer.Length, out var requiredSize, 0) || requiredSize == 0) + { + return null; // Return null when property missing or call fails. + } + + if (propertyType != DEVPROP_TYPE_STRING_LIST && propertyType != DEVPROP_TYPE_STRING) + { + return null; // Ignore unsupported property types to avoid mis-parsing binary data. + } + + var value = Encoding.Unicode.GetString(buffer, 0, (int)requiredSize).TrimEnd('\0'); // Decode UTF-16. + var parts = value.Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries); // Split on null separators. + return parts.Length == 0 ? null : new List(parts); // Return list for caller convenience. + } + + private static string? TryGetPortNameFromRegistry(IntPtr deviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData) + { + var regKey = SetupDiOpenDevRegKey(deviceInfoSet, ref deviceInfoData, 0, 0, DIREG_DEV, KEY_QUERY_VALUE); // Open device-specific registry key. + if (regKey == IntPtr.Zero || regKey == new IntPtr(-1)) + { + return null; // Key could not be opened (permissions or missing). + } + + using var safeHandle = new SafeRegistryHandle(regKey, true); // Wrap raw handle for safe disposal. + using var key = RegistryKey.FromHandle(safeHandle); // Create RegistryKey from handle. + return key.GetValue("PortName") as string; // Return PortName value (e.g., COM3) if present. + } + + private static string? TryGetPortNameFromEnumRegistry(string? deviceInstanceId) + { + if (string.IsNullOrWhiteSpace(deviceInstanceId)) + { + return null; // No instance ID means we cannot build registry path. + } + + try + { + var path = $"SYSTEM\\CurrentControlSet\\Enum\\{deviceInstanceId}\\Device Parameters"; // Build registry path to device parameters. + using var enumKey = Registry.LocalMachine.OpenSubKey(path); // Open read-only. + return enumKey?.GetValue("PortName") as string; // Extract PortName if it exists. + } + catch + { + // Registry access can fail due to permissions; ignore and continue. + return null; // Silence exception; other methods may still succeed. + } + } + + private static string? ExtractPortName(string? source) + { + if (string.IsNullOrWhiteSpace(source)) + { + return null; // Nothing to parse. + } + + var match = Regex.Match(source, @"(COM\d+)", RegexOptions.IgnoreCase); // Regex finds patterns like COM3. + return match.Success ? match.Groups[1].Value.ToUpperInvariant() : null; // Normalize to uppercase for consistency. + } + + private static (string? Vid, string? Pid, string? SerialNumber) ParseUsbIdentifiers(string? hardwareIds, string? deviceInstanceId) + { + string? firstHardwareId = hardwareIds + ?.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries) + .Select(id => id.Trim()) + .FirstOrDefault(); // Hardware IDs can be comma/semicolon separated; take the first entry. + + var vidMatch = Regex.Match(firstHardwareId ?? string.Empty, "VID_([0-9A-Fa-f]{4})"); // Capture USB vendor ID. + var pidMatch = Regex.Match(firstHardwareId ?? string.Empty, "PID_([0-9A-Fa-f]{4})"); // Capture USB product ID. + + string? serialNumber = null; + if (!string.IsNullOrWhiteSpace(deviceInstanceId)) + { + var segments = deviceInstanceId.Split('\\'); // Device instance ID typically "USB\\VID_xxxx&PID_xxxx\\SERIAL". + if (segments.Length >= 3) + { + serialNumber = segments[2]; // Third segment often contains USB serial number or location. + } + } + + return ( + vidMatch.Success ? vidMatch.Groups[1].Value.ToUpperInvariant() : null, // Normalize VID to uppercase. + pidMatch.Success ? pidMatch.Groups[1].Value.ToUpperInvariant() : null, // Normalize PID to uppercase. + serialNumber); // Return parsed serial (may be null). + } + + /// + /// Mirrors the native SP_DEVINFO_DATA structure used by SetupAPI to describe a device instance. + /// + [StructLayout(LayoutKind.Sequential)] + private struct SP_DEVINFO_DATA + { + public uint cbSize; + public Guid ClassGuid; + public uint DevInst; + public IntPtr Reserved; + } + + /// Represents a DEVPROPKEY structure used with SetupDiGetDeviceProperty. + [StructLayout(LayoutKind.Sequential)] + private struct DEVPROPKEY + { + public Guid fmtid; + public uint pid; + } + + /// Retrieves a handle to a device information set for a specified class. + [DllImport("setupapi.dll", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern IntPtr SetupDiGetClassDevs(ref Guid classGuid, string? enumerator, IntPtr hwndParent, uint flags); + + /// Enumerates device information elements in a device information set. + [DllImport("setupapi.dll", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern bool SetupDiEnumDeviceInfo(IntPtr deviceInfoSet, uint memberIndex, ref SP_DEVINFO_DATA deviceInfoData); + + /// Destroys a device information set and frees associated memory. + [DllImport("setupapi.dll", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern bool SetupDiDestroyDeviceInfoList(IntPtr deviceInfoSet); + + /// Retrieves a device property from the registry. + [DllImport("setupapi.dll", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern bool SetupDiGetDeviceRegistryProperty( + IntPtr deviceInfoSet, + ref SP_DEVINFO_DATA deviceInfoData, + uint property, + out uint propertyRegDataType, + byte[] propertyBuffer, + uint propertyBufferSize, + out uint requiredSize); + + /// Retrieves a device instance identifier (e.g., USB\\VID_XXXX&PID_XXXX\\SERIAL). + [DllImport("setupapi.dll", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern bool SetupDiGetDeviceInstanceId( + IntPtr deviceInfoSet, + ref SP_DEVINFO_DATA deviceInfoData, + StringBuilder deviceInstanceId, + uint deviceInstanceIdSize, + out uint requiredSize); + + /// Retrieves device properties such as DEVPKEY_Device_LocationPaths. + [DllImport("setupapi.dll", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern bool SetupDiGetDeviceProperty( + IntPtr deviceInfoSet, + ref SP_DEVINFO_DATA deviceInfoData, + ref DEVPROPKEY propertyKey, + out uint propertyType, + byte[] propertyBuffer, + uint propertyBufferSize, + out uint requiredSize, + uint flags); + + /// Opens a registry key for a device instance. + [DllImport("setupapi.dll", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern IntPtr SetupDiOpenDevRegKey( + IntPtr deviceInfoSet, + ref SP_DEVINFO_DATA deviceInfoData, + uint scope, + uint hwProfile, + uint keyType, + int samDesired); +} + +public sealed record SerialPortDisplay( + string PortName, + string? Description, + string? Manufacturer, + string? FriendlyName, + string? HardwareIds, + string? DeviceInstanceId, + string? UsbVendorId, + string? UsbProductId, + string? UsbSerialNumber, + string? LocationPath, + string Source) +{ + public static SerialPortDisplay Create(string portName) => new(portName, null, null, null, null, null, null, null, null, null, string.Empty); // Factory helper to start with empty metadata. + + public string? DeviceDescription => SanitizeDescription(FriendlyName ?? Description); // Choose friendly name or description, cleaning redundant COM text. + + public string DisplayName + { + get + { + var parts = new List { PortName }; // Always start with COM port name (e.g., COM3). + + var ftdiOrUsbSegment = BuildFtdiOrUsbSegment(); // Add FTDI/USB VID/PID segment when available for quick visual identification. + if (!string.IsNullOrWhiteSpace(ftdiOrUsbSegment)) + { + parts.Add(ftdiOrUsbSegment!); + } + + if (!string.IsNullOrWhiteSpace(DeviceDescription)) + { + parts.Add(DeviceDescription!); // Append cleaned description for context (e.g., "USB Serial Device"). + } + + if (!string.IsNullOrWhiteSpace(Manufacturer)) + { + parts.Add(Manufacturer!); // Append manufacturer such as "FTDI" or "Microsoft". + } + + return string.Join(" - ", parts); // Join with hyphen separators to produce combo-box display text. + } + } + + public bool IsLikelyFtdi => new[] { Description, Manufacturer, FriendlyName } + .Any(value => value != null && value.IndexOf("FTDI", StringComparison.OrdinalIgnoreCase) >= 0); // Heuristic: check for "FTDI" substring to highlight FT232 cables. + + private string? BuildFtdiOrUsbSegment() + { + if (IsLikelyFtdi) + { + return "FTDI"; // Explicitly flag FTDI devices because they are commonly used with this project. + } + + var usbParts = new List(); // Collect VID/PID pair for non-FTDI devices. + + if (!string.IsNullOrWhiteSpace(UsbVendorId)) + { + usbParts.Add($"VID:{UsbVendorId}"); + } + + if (!string.IsNullOrWhiteSpace(UsbProductId)) + { + usbParts.Add($"PID:{UsbProductId}"); + } + + return usbParts.Count > 0 ? string.Join(" ", usbParts) : null; // Return combined VID/PID or null if unknown. + } + + private string? SanitizeDescription(string? rawDescription) + { + if (string.IsNullOrWhiteSpace(rawDescription)) + { + return null; // No description to clean. + } + + var cleaned = rawDescription + .Replace($"({PortName})", string.Empty, StringComparison.OrdinalIgnoreCase) // Remove redundant "(COMx)" segments. + .Replace(PortName, string.Empty, StringComparison.OrdinalIgnoreCase) // Remove raw COM string. + .Trim().Trim('-', '—').Trim(); // Trim leftover punctuation and whitespace. + + return string.IsNullOrWhiteSpace(cleaned) ? rawDescription : cleaned; // If cleaning removed everything, fall back to raw description. + } + + public override string ToString() => DisplayName; // ComboBox calls ToString(), so return DisplayName for a friendly label. +} diff --git a/docs/Protocol.ods b/docs/Protocol.ods deleted file mode 100644 index 15fff3a..0000000 Binary files a/docs/Protocol.ods and /dev/null differ diff --git a/docs/thumbnail.png b/docs/thumbnail.png new file mode 100644 index 0000000..d8699a4 Binary files /dev/null and b/docs/thumbnail.png differ diff --git a/m18.py b/m18.py index 39def59..09ea439 100644 --- a/m18.py +++ b/m18.py @@ -1,3 +1,13 @@ +""" +Core protocol implementation for communicating with Milwaukee M18 battery packs. + +This module exposes the :class:`M18` class, which handles all low-level serial +communication and provides helper routines for querying registers, simulating +charger behaviour, and collecting diagnostic data. The large data tables at the +top of the file describe the known register layout for the pack so higher-level +functions can translate raw bytes into meaningful information. +""" + import code import datetime import struct @@ -9,6 +19,10 @@ from serial import Serial from serial.tools import list_ports +# Address map describing contiguous register blocks to read from the pack. +# Each entry is [MSB, LSB, LENGTH] describing the starting address and +# number of bytes available in that window. These windows are used to prime +# caches and pull coherent chunks of data before decoding individual fields. data_matrix = [ [0x00, 0x00, 0x02], [0x00, 0x02, 0x02], @@ -45,13 +59,14 @@ ] -# label, addr, len, type -# uint - unsigned integer -# date - UNIX time (seconds from 1 Jan 1970) -# ascii - ascii string -# sn - serial number (2 bytes battery type, 3 bytes serial) -# adc_t - analog-to-digital converter temperature (mV of thermistor) -# dec_t - decimal temperature (byte_1 + byte_2/255) +# Lookup table describing each known register and how to decode it. Entries are +# formatted as [address, length, data_type, label] with the following types: +# uint - unsigned integer +# date - UNIX time (seconds from 1 Jan 1970) +# ascii - ASCII string +# sn - serial number (2 bytes battery type, 3 bytes serial) +# adc_t - analog-to-digital converter temperature (mV of thermistor) +# dec_t - decimal temperature (byte_1 + byte_2/255) # cell_v - cell voltages (1: 3568, 2: 3567, 3:3570, etc) data_id = [ [0x0000, 2, "uint", "Cell type"], # 0 @@ -250,6 +265,7 @@ def print_debug_bytes(data): print(f"DEBUG: ", data_print) class M18: + """Encapsulates serial communications and helper utilities for M18 packs.""" SYNC_BYTE = 0xAA CAL_CMD = 0x55 CONF_CMD = 0x60 @@ -265,24 +281,33 @@ class M18: PRINT_RX = False # Used to temporarily disable then restore print_tx/rx state - PRINT_TX_SAVE = False + PRINT_TX_SAVE = False PRINT_RX_SAVE = False - + def txrx_print(self, enable = True): + """Toggle verbose logging of transmitted and received frames.""" self.PRINT_TX = enable self.PRINT_RX = enable - + def txrx_save_and_set(self, enable = True): + """Save current TX/RX logging state and apply a temporary setting.""" self.PRINT_TX_SAVE = self.PRINT_TX self.PRINT_RX_SAVE = self.PRINT_RX self.txrx_print(enable) - + def txrx_restore(self): + """Restore TX/RX logging flags saved via :meth:`txrx_save_and_set`.""" self.PRINT_TX = self.PRINT_TX_SAVE self.PRINT_RX = self.PRINT_RX_SAVE def __init__(self, port): + """Create a protocol instance and open the serial port. + + Args: + port (str | None): Serial device path. When ``None`` the user is + prompted to choose from detected ports in an interactive menu. + """ if port is None: print("*** NO PORT SPECIFIED ***") print("Available serial ports (choose one that says USB somewhere):") @@ -345,36 +370,43 @@ def reset(self): return False def update_acc(self): + """Cycle the access control code used when issuing commands.""" acc_values = [0x04, 0x0C, 0x1C] current_index = acc_values.index(self.ACC) next_index = (current_index + 1) % len(acc_values) self.ACC = acc_values[next_index] def reverse_bits(self, byte): + """Reverse the bit-order of a single byte.""" return int(f"{byte:08b}"[::-1], 2) - + def checksum(self, payload): + """Calculate a simple additive checksum for the payload.""" checksum = 0 for byte in payload: checksum += byte & 0xFFFF return checksum def add_checksum(self, lsb_command): - lsb_command += struct.pack(">H", self.checksum(lsb_command)) + """Append a big-endian checksum to a command payload.""" + lsb_command += struct.pack(">H", self.checksum(lsb_command)) return lsb_command - + def send(self, command): + """Transmit a raw command buffer after reversing bit order for the wire.""" self.port.reset_input_buffer() debug_print = " ".join(f"{byte:02X}" for byte in command) msb = bytearray(self.reverse_bits(byte) for byte in command) if self.PRINT_TX: print(f"Sending: {debug_print}") self.port.write(msb) - + def send_command(self, command): + """Send a command with checksum pre-appended.""" self.send(self.add_checksum(command)) def read_response(self, size): + """Read and decode a response of ``size`` bytes from the serial port.""" msb_response = self.port.read(1) if not msb_response or len(msb_response) < 1: raise ValueError("Empty response") @@ -390,28 +422,33 @@ def read_response(self, size): return lsb_response def configure(self, state): + """Send configuration command declaring charger capabilities.""" self.ACC = 4 - self.send_command(struct.pack('>BBBHHHBB', self.CONF_CMD, self.ACC, 8, + self.send_command(struct.pack('>BBBHHHBB', self.CONF_CMD, self.ACC, 8, self.CUTOFF_CURRENT, self.MAX_CURRENT, self.MAX_CURRENT, state, 13)) return self.read_response(5) def get_snapchat(self): + """Request a short snapshot from the pack and advance ACC.""" self.send_command(struct.pack('>BBB', self.SNAP_CMD, self.ACC, 0)) self.update_acc() return self.read_response(8) - + def keepalive(self): + """Send a keepalive/charge-current request.""" self.send_command(struct.pack('>BBB', self.KEEPALIVE_CMD, self.ACC, 0)) return self.read_response(9) - + def calibrate(self): + """Trigger calibration/interrupt command on the pack.""" self.send_command(struct.pack('>BBB', self.CAL_CMD, self.ACC, 0)) self.update_acc() return self.read_response(8) def simulate(self): + """Continuously mimic charger behaviour until interrupted.""" print("Simulating charger communication") - + self.txrx_save_and_set(True) # Turn on TX/RX messages self.reset() @@ -435,6 +472,7 @@ def simulate(self): def simulate_for(self, duration): + """Simulate charging communication for ``duration`` seconds.""" # Simulate charging for 'time' seconds print(f"Simulating charger communication for {duration} seconds...") begin_time = time.time() @@ -457,6 +495,7 @@ def simulate_for(self, duration): print(f"Duration: ", time.time() - begin_time) def debug(self, a,b,c,length): + """Send a single command after reset and print the raw response.""" # Turn off debug, restore after printing rx_debug = self.PRINT_RX @@ -473,6 +512,7 @@ def debug(self, a,b,c,length): self.PRINT_RX = rx_debug def try_cmd(self, cmd, msb, lsb, length, ret_len=0): + """Fire an arbitrary command and display the response for debugging.""" # Turn off TX/RX printing, restore after printing self.txrx_save_and_set(False) @@ -490,11 +530,13 @@ def try_cmd(self, cmd, msb, lsb, length, ret_len=0): def cmd(self, a,b,c,length, command = 0x01): + """Send a read command to address ``a:b`` with length ``c``.""" self.send_command(struct.pack('>BBBBBB', command, 0x04, 0x03, a, b, c)) return self.read_response(length) def brute(self, a, b, length = 0xFF, command = 0x01): + """Probe a single address with many lengths looking for valid replies.""" self.reset() try: for i in range(length): @@ -532,10 +574,12 @@ def full_brute(self, start=0, stop=0xFFFF, length = 0xFF): self.idle() def wcmd(self, a,b,c,length): + """Send a write command to address ``a:b`` requesting ``c`` bytes.""" self.send_command(struct.pack('>BBBBBB', 0x01, 0x05, 0x03, a, b, c)) return self.read_response(length) def write_message(self, message): + """Write a short ASCII message into the pack's note register.""" try: if len(message) > 0x14: print("ERROR: Message too long!") @@ -549,14 +593,17 @@ def write_message(self, message): print(f"write_message: Failed with error: {e}") def idle(self): + """Drive control pins low to indicate idle/stop state.""" self.port.break_condition = True self.port.dtr = True def high(self): + """Drive control pins high to request charging.""" self.port.break_condition = False self.port.dtr = False - + def high_for(self, duration): + """Bring control pins high for ``duration`` seconds then idle.""" self.high() time.sleep(duration) self.idle() @@ -584,12 +631,14 @@ def calculate_temperature(self, adc_value): return round(temperature, 2) def bytes2dt(self, time_bytes): + """Convert a big-endian timestamp to an aware ``datetime`` object.""" epoch_time = int.from_bytes(time_bytes, 'big') dt = datetime.datetime.fromtimestamp(epoch_time, tz=datetime.UTC) return dt def read_all(self): + """Read and print every address block defined in :data:`data_matrix`.""" try: self.reset() for addr_h, addr_l, length in data_matrix: @@ -797,7 +846,7 @@ def health(self, force_refresh = True): # turn off debugging messages - self.txrx_save_and_set(False) + self.txrx_save_and_set(True) try: print("Reading battery. This will take 5-10sec\n") @@ -899,6 +948,7 @@ def health(self, force_refresh = True): def submit_form(self): + """Collect diagnostics and submit them to the community Google Form.""" form_url = 'https://docs.google.com/forms/d/e/1FAIpQLScvTbSDYBzSQ8S4XoF-rfgwNj97C-Pn4Px3GIixJxf0C1YJJA/formResponse' # Get data from battery @@ -956,6 +1006,7 @@ def submit_form(self): def help(self): + """Print a concise overview of commonly used interactive commands.""" print("Functions: \n \ DIAGNOSTICS: \n \ m.health() - print simple health report on battery \n \ @@ -967,8 +1018,9 @@ def help(self): m.adv_help() - advanced help\n \ \n \ exit() - end program\n") - + def adv_help(self): + """Print extended help covering simulations and debugging helpers.""" print("Advanced functions: \n \ m.read_all() - print all known bytes in 0x01 command \n \ m.read_all_spreadsheet() - print bytes in spreadsheet format \n \ diff --git a/m18_clipboard.bat b/m18_clipboard.bat deleted file mode 100644 index 7fa5375..0000000 --- a/m18_clipboard.bat +++ /dev/null @@ -1,28 +0,0 @@ -@echo off - -echo *************************************************** -echo ** Runs m18.py with spreadsheet output and ** -echo ** copies to clipboard. You will not see output, ** -echo ** just a completion message. Then you can ** -echo ** 'ctrl+v' into a spreadsheet ** -echo ** ** -echo ** THIS WILL TAKE ~10 SECONDS ** -echo ** ** -echo ** RIGHT-CLICK AND EDIT .BAT FILE. ** -echo ** CHANGE "--port COM5" to where your adapter is ** -echo ** (you can delete this message) ** -echo *************************************************** - -python.exe .\m18.py --ss --port COM5 | clip.exe - -echo: -echo *************************************************** -echo ** Finished. Now use 'ctrl+v' to paste ** -echo ** diagnostics output into spreadsheet ** -echo ** ** -echo ** If you get errors, you must edit this batch ** -echo ** file to have the correct port. You may also ** -echo ** have hardware issues. See github ** -echo *************************************************** - -cmd /k \ No newline at end of file diff --git a/m18_health.bat b/m18_health.bat deleted file mode 100644 index 65b4117..0000000 --- a/m18_health.bat +++ /dev/null @@ -1,15 +0,0 @@ -:: RECOMMEND RUNNING m18_idle.bat BEFORE CONNECTING TO BATTERY -:: Gives simple health report of M18 batteries -:: Add "--port COM5" (or whatever your port is) to avoid -:: having to enter it everytime - -@echo off -echo *************************************************** -echo ** RIGHT-CLICK AND EDIT .BAT FILE. ** -echo ** ADD "--port COM5" to command ** -echo ** (or whatever port your serial adapter is on) ** -echo ** (you can delete this message ** -echo *************************************************** - -python.exe .\m18.py --health -cmd /k \ No newline at end of file diff --git a/m18_idle.bat b/m18_idle.bat deleted file mode 100644 index e553f3f..0000000 --- a/m18_idle.bat +++ /dev/null @@ -1,14 +0,0 @@ -:: Puts serial adapter TX in idle (low = <1V) -:: This prevents false charge count increases - -@echo off - -echo *************************************************** -echo ** RIGHT-CLICK AND EDIT .BAT FILE. ** -echo ** ADD "--port COM5" to command ** -echo ** (or whatever port your serial adapter is on) ** -echo ** (you can delete this message ** -echo *************************************************** - -python.exe .\m18.py --idle -cmd /k \ No newline at end of file diff --git a/m18_interactive.bat b/m18_interactive.bat deleted file mode 100644 index 92c0864..0000000 --- a/m18_interactive.bat +++ /dev/null @@ -1,5 +0,0 @@ -:: RECOMMEND RUNNING m18_idle.bat BEFORE CONNECTING TO BATTERY -:: Runs script in interactive mode -:: All functions available - -python.exe .\m18.py \ No newline at end of file diff --git a/m18gui.py b/m18gui.py new file mode 100644 index 0000000..5eac978 --- /dev/null +++ b/m18gui.py @@ -0,0 +1,410 @@ +"""Tkinter-based GUI wrapper around the :mod:`m18` protocol module.""" + +import sys, subprocess, threading, io, time, traceback, tkinter as tk +from tkinter import ttk, messagebox + +def ensure_module(mod_name, pip_name): + """Import ``mod_name``, installing ``pip_name`` via pip if missing.""" + try: __import__(mod_name) + except ImportError: + root = tk.Tk(); root.title("Installing dependencies") + ttk.Label(root, text=f"Installing {pip_name}…").pack(padx=6, pady=6) + pb = ttk.Progressbar(root, mode="indeterminate"); pb.pack(fill="x", padx=6, pady=(0, 6)); pb.start(12) + root.update_idletasks() + subprocess.check_call([sys.executable, "-m", "pip", "install", pip_name], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + pb.stop(); root.destroy() + try: __import__(mod_name) + except ImportError: messagebox.showerror("Error", f"Installed {pip_name} but cannot import."); sys.exit(1) +ensure_module("serial", "pyserial") +from serial.tools import list_ports +import m18 + +class M18GUI(tk.Tk): + """Simple desktop interface for performing common M18 operations.""" + def __init__(self): + super().__init__() + self.title("M18 Protocol GUI") + self.geometry("610x370") + self.resizable(False, False) + self.m18_obj = None + self.sim_thread = None + self.sim_stop_event = None + self.sim_profiles = {"Gentle": (150, 2500), "Normal": (300, 6000), "Aggressive": (450, 9000)} + self.custom_cutoff_raw_var = tk.StringVar(value="300") + self.custom_cutoff_amps_var = tk.StringVar(value="0.30") + self.custom_max_raw_var = tk.StringVar(value="6000") + self.custom_max_amps_var = tk.StringVar(value="6.00") + self._sync_in_progress = False + self.port_map = {} + self.create_widgets() + self.refresh_ports() + self.update_profile_display() + + def create_widgets(self): + """Build all tabs, controls, and shared output areas.""" + self.notebook = ttk.Notebook(self); self.notebook.pack(fill="both", expand=True, padx=0, pady=0) + self.main_tab, self.console_tab, self.sim_tab, self.about_tab = (ttk.Frame(self.notebook) for _ in range(4)) + self.notebook.add(self.main_tab, text="Main Controls"); self.notebook.add(self.console_tab, text="Interactive Console") + self.notebook.add(self.sim_tab, text="Simulation"); self.notebook.add(self.about_tab, text="About") + + # Main Controls + top = ttk.Frame(self.main_tab); top.pack(fill="x", padx=5, pady=(4,1)) + ttk.Label(top, text="Serial port:").grid(row=0, column=0, sticky="w") + self.port_var = tk.StringVar() + self.port_combo = ttk.Combobox(top, textvariable=self.port_var, state="readonly", width=40); self.port_combo.grid(row=0, column=1, padx=2, sticky="w") + ttk.Button(top, text="Refresh", width=7, command=self.refresh_ports).grid(row=0, column=2, padx=2) + self.connect_btn = ttk.Button(top, text="Connect", width=7, command=self.connect_device); self.connect_btn.grid(row=0, column=3, padx=2) + self.disconnect_btn = ttk.Button(top, text="Disconnect", width=9, command=self.disconnect_device, state="disabled"); self.disconnect_btn.grid(row=0, column=4, padx=2) + self.status_var = tk.StringVar(value="Not connected") + ttk.Label(top, textvariable=self.status_var).grid(row=1, column=0, columnspan=5, sticky="w", pady=(2,0)) + cmds = ttk.LabelFrame(self.main_tab, text="Commands"); cmds.pack(fill="x", padx=5, pady=(3,1)) + self.idle_btn = ttk.Button(cmds, text="Idle (TX low, safe to connect)", width=25, command=self.cmd_idle, state="disabled"); self.idle_btn.grid(row=0, column=0, padx=2, pady=2) + self.health_btn = ttk.Button(cmds, text="Health report", width=15, command=self.cmd_health, state="disabled"); self.health_btn.grid(row=0, column=1, padx=2, pady=2) + self.clipboard_btn = ttk.Button(cmds, text="Copy all registers to clipboard", width=28, command=self.cmd_clipboard, state="disabled"); self.clipboard_btn.grid(row=0, column=2, padx=2, pady=2) + # Output (only on non-About tabs) + self.bottom_frame = ttk.LabelFrame(self, text="Output"); self.bottom_frame.pack(fill="x", padx=5, pady=(0,4), side="bottom") + self.output_text = tk.Text(self.bottom_frame, wrap="word", height=6, font=("Consolas", 9)); self.output_text.pack(fill="both", expand=True, padx=2, pady=2) + scrollbar = ttk.Scrollbar(self.bottom_frame, orient="vertical", command=self.output_text.yview); scrollbar.pack(side="right", fill="y") + self.output_text.configure(yscrollcommand=scrollbar.set) + def on_tab_changed(event): + tab = event.widget.tab(event.widget.select(), "text") + if tab == "About": self.bottom_frame.pack_forget() + else: self.bottom_frame.pack(fill="x", padx=5, pady=(0,4), side="bottom") + self.notebook.bind("<>", on_tab_changed) + + # Console Tab + c_frame = ttk.Frame(self.console_tab); c_frame.pack(fill="both", expand=True, padx=4, pady=2) + ttk.Label(c_frame, text="Python console. Use 'm' for M18 object.").pack(anchor="w", pady=(0,1)) + self.console_text = tk.Text(c_frame, height=4, wrap="none", font=("Consolas",9)); self.console_text.pack(fill="x", padx=1, pady=(0,1)) + c_btns = ttk.Frame(c_frame); c_btns.pack(fill="x") + ttk.Button(c_btns, text="Execute", width=10, command=self.run_console_code).pack(side="left", padx=3) + ttk.Button(c_btns, text="Clear", width=7, command=lambda: self.console_text.delete("1.0", tk.END)).pack(side="left", padx=3) + + # Simulation Tab + s_frame = ttk.Frame(self.sim_tab); s_frame.pack(fill="both", padx=4, pady=1) + ttk.Label(s_frame, text="Simulation duration (sec):").grid(row=0, column=0, sticky="w", padx=2) + self.sim_duration_var = tk.StringVar(value="60") + ttk.Entry(s_frame, textvariable=self.sim_duration_var, width=5).grid(row=0, column=1, sticky="w", padx=2) + ttk.Label(s_frame, text="Sim baudrate (concept):").grid(row=1, column=0, sticky="w", padx=2) + self.sim_baud_var = tk.StringVar(value="4800") + ttk.Combobox(s_frame, textvariable=self.sim_baud_var, state="readonly", width=8, values=["1200","2400","4800","9600"]).grid(row=1, column=1, sticky="w", padx=2) + ttk.Label(s_frame, text="UART to pack always runs at 4800 baud.\nNo real charging current flows from USB.").grid(row=2, column=0, columnspan=2, sticky="w", padx=2, pady=(0,6)) + ttk.Label(s_frame, text="Charger profile:").grid(row=3, column=0, sticky="w", padx=2) + self.sim_profile_var = tk.StringVar(value="Normal") + profs = list(self.sim_profiles.keys())+["Custom"] + prof_box = ttk.Combobox(s_frame, textvariable=self.sim_profile_var, state="readonly", width=10, values=profs) + prof_box.grid(row=3, column=1, sticky="w", padx=2) + prof_box.bind("<>", self.on_profile_changed) + self.profile_info_var = tk.StringVar() + ttk.Label(s_frame, textvariable=self.profile_info_var, foreground="blue").grid(row=4, column=0, columnspan=2, sticky="w", padx=2, pady=(0,2)) + self.sim_status_var = tk.StringVar(value="Simulation idle. Connect to a battery to enable.") + ttk.Label(s_frame, textvariable=self.sim_status_var).grid(row=5, column=0, columnspan=2, sticky="w", padx=2) + self.sim_start_btn = ttk.Button(s_frame, text="Start simulation", width=15, command=self.start_simulation, state="disabled") + self.sim_start_btn.grid(row=6, column=0, padx=2, pady=2) + self.sim_stop_btn = ttk.Button(s_frame, text="Stop simulation", width=15, command=self.stop_simulation, state="disabled") + self.sim_stop_btn.grid(row=6, column=1, padx=2, pady=2) + + # About Tab + import webbrowser + a_frame = ttk.Frame(self.about_tab) + a_frame.place(relx=0.5, rely=0.09, anchor="n") + ttk.Label(a_frame, text="M18 Protocol GUI", font=("Segoe UI", 15, "bold")).pack(pady=(0,1)) + ttk.Label(a_frame, text="Core protocol by Martin Jansson", font=("Segoe UI", 9, "italic")).pack(pady=(5,0)) + link2 = ttk.Label(a_frame, text="Original: https://github.com/mnh-jansson/m18-protocol", foreground="blue", cursor="hand2"); link2.pack() + link2.bind("", lambda e: webbrowser.open("https://github.com/mnh-jansson/m18-protocol")) + ttk.Label(a_frame, text="Developed by KillaVolt", font=("Segoe UI", 9)).pack() + link = ttk.Label(a_frame, text="GitHub Profile: https://github.com/KillaVolt", foreground="blue", cursor="hand2"); link.pack() + link.bind("", lambda e: webbrowser.open("https://github.com/KillaVolt")) + + table = ttk.Treeview(a_frame, columns=("addr", "desc"), show="headings", height=8) + table.heading("addr", text="Hex Addr"); table.heading("desc", text="Meaning") + table.column("addr", width=65, anchor="center"); table.column("desc", width=150, anchor="w"); table.pack() + for addr, desc in [("F85D","1: Command"),("F85E","4: Access"),("F85F","3: Length"),("F860","Address?"),("F861","Address?"),("F862","Length?"),("F863","N/A"),("F864","Checksum")]: + table.insert("", "end", values=(addr,desc)) + + # -------- Utility / Port / Logging ---------- + def log(self, text, clear=False): + """Append ``text`` to the shared output area, optionally clearing it.""" + self.output_text.delete("1.0", tk.END) if clear else None; self.output_text.insert(tk.END, text + "\n"); self.output_text.see(tk.END) + + def sim_log(self, text): + """Prefix simulation messages to distinguish them in the log area.""" + self.log(f"[SIM] {text}") + + def set_status(self, text): + """Update the status label at the top of the UI.""" + self.status_var.set(text) + + def refresh_ports(self): + """Enumerate available serial ports and repopulate the dropdown.""" + ports = list_ports.comports(); names = []; self.port_map.clear() + for p in ports: + label = f"{p.device} — {p.description} ({getattr(p,'manufacturer','') or ''})".strip() + names.append(label); self.port_map[label] = p.device + self.port_combo["values"] = names; self.port_combo.current(0) if names else self.port_combo.set("") + self.set_status("Ports refreshed") + + def require_connection(self): + """Warn the user if no device is connected before running an action.""" + if self.m18_obj is None: messagebox.showwarning("Not connected", "Please connect to a port first."); return False + return True + + def capture_output(self, func, *a, **k): + """Run ``func`` while capturing stdout into a string.""" + buf, old = io.StringIO(), sys.stdout + try: sys.stdout = buf; func(*a, **k) + finally: sys.stdout = old + return buf.getvalue() + + # --------- Connect/Disconnect ----------- + def connect_device(self): + """Instantiate :class:`m18.M18` using the selected serial port.""" + sel = self.port_var.get() + port = self.port_map.get(sel, sel) + try: self.m18_obj = m18.M18(port) + except Exception as e: + self.m18_obj = None; messagebox.showerror("Connection error", f"Failed to connect to {port}.\n\n{e}") + self.set_status("Connection failed"); return + self.set_status(f"Connected to {port}"); self.log(f"Connected to {port}", clear=True) + for b in [self.connect_btn]: b.configure(state="disabled") + for b in [self.disconnect_btn, self.idle_btn, self.health_btn, self.clipboard_btn, self.sim_start_btn]: b.configure(state="normal") + + def disconnect_device(self): + """Return the pack to idle, close the port, and reset UI state.""" + self.stop_simulation() + if self.m18_obj: + try: self.m18_obj.idle() + except: pass + try: self.m18_obj.port.close() + except: pass + self.m18_obj = None + self.set_status("Disconnected"); self.log("Disconnected") + for b in [self.connect_btn]: b.configure(state="normal") + for b in [self.disconnect_btn, self.idle_btn, self.health_btn, self.clipboard_btn, self.sim_start_btn, self.sim_stop_btn]: b.configure(state="disabled") + + # ----------- Command Handlers ----------- + def cmd_idle(self): + """Invoke ``idle`` on the connected device in a worker thread.""" + if not self.require_connection(): return + def work(): + try: + self.m18_obj.idle() + self.after(0, lambda: self.log("TX now low (<1V). Safe to connect battery.")) + self.after(0, lambda: self.set_status("Idle (TX low)")) + except Exception as e: + self.after(0, lambda: messagebox.showerror("Idle error", str(e))) + threading.Thread(target=work, daemon=True).start() + + def cmd_health(self): + """Run ``health`` and display captured output.""" + if not self.require_connection(): return + def work(): + try: + output = self.capture_output(self.m18_obj.health) + def finish(): + self.log("=== Health report ===", clear=True) + self.log(output) + self.set_status("Health report complete") + self.after(0, finish) + except Exception as e: + self.after(0, lambda: messagebox.showerror("Health error", str(e))) + threading.Thread(target=work, daemon=True).start() + + def cmd_clipboard(self): + """Copy all register values to the clipboard.""" + if not self.require_connection(): return + def work(): + try: + output = self.capture_output(self.m18_obj.read_id, None, True, "raw") + def finish(): + self.clipboard_clear() + self.clipboard_append(output) + self.log("Register data copied to clipboard") + self.after(0, finish) + except Exception as e: + self.after(0, lambda: messagebox.showerror("Clipboard error", str(e))) + threading.Thread(target=work, daemon=True).start() + + # ---------- Interactive Console ---------- + def run_console_code(self): + """Execute arbitrary Python with the M18 object available as ``m``.""" + code = self.console_text.get("1.0", tk.END).strip() + if not code: messagebox.showinfo("No code", "Please enter some code."); return + if not self.require_connection(): return + def work(): + buf = io.StringIO(); old_stdout, old_stderr = sys.stdout, sys.stderr + sys.stdout = sys.stderr = buf + try: + env = {"m": self.m18_obj} + try: exec(code, env, {}) + except Exception: traceback.print_exc() + finally: sys.stdout, sys.stderr = old_stdout, old_stderr + output = buf.getvalue() + def finish(): + self.log("=== Console execution ===") + self.log(output if output.strip() else "(no output)") + self.after(0, finish) + threading.Thread(target=work, daemon=True).start() + + # ---------- Profile Display ---------- + def on_profile_changed(self, event=None): self.update_profile_display() + def update_profile_display(self): + """Show human readable info about the selected simulation profile.""" + p = self.sim_profile_var.get() + if p in self.sim_profiles: + c, m = self.sim_profiles[p] + info = f"Profile '{p}': Cutoff {c} ({c/1000:.2f}A), Max {m} ({m/1000:.2f}A). Simulation only." + self.profile_info_var.set(info) + else: self.profile_info_var.set("Custom profile: adjust fields below.") + def get_profile_currents(self): + """Return cutoff and max currents based on profile or custom fields.""" + p = self.sim_profile_var.get() + if p in self.sim_profiles: return self.sim_profiles[p] + try: + c = int(self.custom_cutoff_raw_var.get()) + m = int(self.custom_max_raw_var.get()) + if c < 0 or m <= 0 or c > 20000 or m > 20000: raise ValueError + except: raise ValueError("Invalid custom values.") + return c, m + + # ---------- Simulation ---------- + def start_simulation(self): + """Spawn a background thread to perform the charging dialogue.""" + if not self.require_connection(): return + if self.sim_thread and self.sim_thread.is_alive(): + messagebox.showinfo("Running", "Simulation already running."); return + try: + duration = float(self.sim_duration_var.get()) + if duration <= 0: raise ValueError + except: messagebox.showwarning("Invalid duration", "Enter a positive number."); return + sim_baud = self.sim_baud_var.get() + interval_map = {"1200": 1.0, "2400": 0.75, "4800": 0.5, "9600": 0.25} + keepalive_interval = interval_map.get(sim_baud, 0.5) + try: + cutoff, maxc = self.get_profile_currents() + except Exception as e: + messagebox.showwarning("Profile error", str(e)) + return + + pname = self.sim_profile_var.get() + + self.sim_stop_event = threading.Event() + self.sim_thread = threading.Thread( + target=self._simulation_worker, + args=( + duration, + keepalive_interval, + pname, + cutoff, + cutoff / 1000.0, + maxc, + maxc / 1000.0, + ), + daemon=True, + ) + self.sim_thread.start() + + self.sim_start_btn.configure(state="disabled") + self.sim_stop_btn.configure(state="normal") + self.sim_status_var.set(f"Simulation running ({pname}, baud {sim_baud})") + + self.sim_log( + f"Start {duration}s | {pname} | " + f"cutoff={cutoff} ({cutoff/1000:.2f}A) | " + f"max={maxc} ({maxc/1000:.2f}A) | " + f"interval={keepalive_interval:.2f}s" + ) + + def stop_simulation(self): + """Signal the simulation worker to exit.""" + if self.sim_stop_event: + self.sim_stop_event.set() + + def _simulation_worker( + self, + duration, + interval, + pname, + cutoff_raw, + cutoff_amps, + max_raw, + max_amps, + ): + """Perform the scripted keepalive dialogue for the configured duration.""" + m = self.m18_obj + if m is None: + self.after( + 0, + lambda: messagebox.showerror( + "Simulation error", "No active M18 connection." + ), + ) + return + + old_cutoff = getattr(m, "CUTOFF_CURRENT", None) + old_max = getattr(m, "MAX_CURRENT", None) + + m.CUTOFF_CURRENT = cutoff_raw + m.MAX_CURRENT = max_raw + + start_time = time.time() + + try: + self.after(0, lambda: self.sim_log("Resetting and negotiating charger state...")) + + try: + m.reset() + except Exception as e: + self.after(0, lambda: self.sim_log(f"reset() failed: {e}")) + return + + try: + m.configure(2) + m.get_snapchat() + time.sleep(0.6) + m.keepalive() + m.configure(1) + m.get_snapchat() + except Exception as e: + self.after(0, lambda: self.sim_log(f"Initial negotiation failed: {e}")) + return + + while not self.sim_stop_event.is_set(): + elapsed = time.time() - start_time + if elapsed >= duration: + break + + try: + time.sleep(interval) + m.keepalive() + self.after( + 0, + lambda e=elapsed: self.sim_log(f"Keepalive t={e:.1f}s"), + ) + except Exception as e: + self.after(0, lambda: self.sim_log(f"keepalive() failed: {e}")) + break + + finally: + try: + m.idle() + except Exception: + pass + + if old_cutoff is not None: + m.CUTOFF_CURRENT = old_cutoff + if old_max is not None: + m.MAX_CURRENT = old_max + + def finish(): + self.sim_log("Simulation finished. Returned to idle.") + self.sim_status_var.set("Simulation idle.") + self.sim_start_btn.configure(state="normal") + self.sim_stop_btn.configure(state="disabled") + + self.after(0, finish) + + +if __name__ == "__main__": + app = M18GUI() + app.mainloop() diff --git a/m18gui.pyw b/m18gui.pyw new file mode 100644 index 0000000..5eac978 --- /dev/null +++ b/m18gui.pyw @@ -0,0 +1,410 @@ +"""Tkinter-based GUI wrapper around the :mod:`m18` protocol module.""" + +import sys, subprocess, threading, io, time, traceback, tkinter as tk +from tkinter import ttk, messagebox + +def ensure_module(mod_name, pip_name): + """Import ``mod_name``, installing ``pip_name`` via pip if missing.""" + try: __import__(mod_name) + except ImportError: + root = tk.Tk(); root.title("Installing dependencies") + ttk.Label(root, text=f"Installing {pip_name}…").pack(padx=6, pady=6) + pb = ttk.Progressbar(root, mode="indeterminate"); pb.pack(fill="x", padx=6, pady=(0, 6)); pb.start(12) + root.update_idletasks() + subprocess.check_call([sys.executable, "-m", "pip", "install", pip_name], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + pb.stop(); root.destroy() + try: __import__(mod_name) + except ImportError: messagebox.showerror("Error", f"Installed {pip_name} but cannot import."); sys.exit(1) +ensure_module("serial", "pyserial") +from serial.tools import list_ports +import m18 + +class M18GUI(tk.Tk): + """Simple desktop interface for performing common M18 operations.""" + def __init__(self): + super().__init__() + self.title("M18 Protocol GUI") + self.geometry("610x370") + self.resizable(False, False) + self.m18_obj = None + self.sim_thread = None + self.sim_stop_event = None + self.sim_profiles = {"Gentle": (150, 2500), "Normal": (300, 6000), "Aggressive": (450, 9000)} + self.custom_cutoff_raw_var = tk.StringVar(value="300") + self.custom_cutoff_amps_var = tk.StringVar(value="0.30") + self.custom_max_raw_var = tk.StringVar(value="6000") + self.custom_max_amps_var = tk.StringVar(value="6.00") + self._sync_in_progress = False + self.port_map = {} + self.create_widgets() + self.refresh_ports() + self.update_profile_display() + + def create_widgets(self): + """Build all tabs, controls, and shared output areas.""" + self.notebook = ttk.Notebook(self); self.notebook.pack(fill="both", expand=True, padx=0, pady=0) + self.main_tab, self.console_tab, self.sim_tab, self.about_tab = (ttk.Frame(self.notebook) for _ in range(4)) + self.notebook.add(self.main_tab, text="Main Controls"); self.notebook.add(self.console_tab, text="Interactive Console") + self.notebook.add(self.sim_tab, text="Simulation"); self.notebook.add(self.about_tab, text="About") + + # Main Controls + top = ttk.Frame(self.main_tab); top.pack(fill="x", padx=5, pady=(4,1)) + ttk.Label(top, text="Serial port:").grid(row=0, column=0, sticky="w") + self.port_var = tk.StringVar() + self.port_combo = ttk.Combobox(top, textvariable=self.port_var, state="readonly", width=40); self.port_combo.grid(row=0, column=1, padx=2, sticky="w") + ttk.Button(top, text="Refresh", width=7, command=self.refresh_ports).grid(row=0, column=2, padx=2) + self.connect_btn = ttk.Button(top, text="Connect", width=7, command=self.connect_device); self.connect_btn.grid(row=0, column=3, padx=2) + self.disconnect_btn = ttk.Button(top, text="Disconnect", width=9, command=self.disconnect_device, state="disabled"); self.disconnect_btn.grid(row=0, column=4, padx=2) + self.status_var = tk.StringVar(value="Not connected") + ttk.Label(top, textvariable=self.status_var).grid(row=1, column=0, columnspan=5, sticky="w", pady=(2,0)) + cmds = ttk.LabelFrame(self.main_tab, text="Commands"); cmds.pack(fill="x", padx=5, pady=(3,1)) + self.idle_btn = ttk.Button(cmds, text="Idle (TX low, safe to connect)", width=25, command=self.cmd_idle, state="disabled"); self.idle_btn.grid(row=0, column=0, padx=2, pady=2) + self.health_btn = ttk.Button(cmds, text="Health report", width=15, command=self.cmd_health, state="disabled"); self.health_btn.grid(row=0, column=1, padx=2, pady=2) + self.clipboard_btn = ttk.Button(cmds, text="Copy all registers to clipboard", width=28, command=self.cmd_clipboard, state="disabled"); self.clipboard_btn.grid(row=0, column=2, padx=2, pady=2) + # Output (only on non-About tabs) + self.bottom_frame = ttk.LabelFrame(self, text="Output"); self.bottom_frame.pack(fill="x", padx=5, pady=(0,4), side="bottom") + self.output_text = tk.Text(self.bottom_frame, wrap="word", height=6, font=("Consolas", 9)); self.output_text.pack(fill="both", expand=True, padx=2, pady=2) + scrollbar = ttk.Scrollbar(self.bottom_frame, orient="vertical", command=self.output_text.yview); scrollbar.pack(side="right", fill="y") + self.output_text.configure(yscrollcommand=scrollbar.set) + def on_tab_changed(event): + tab = event.widget.tab(event.widget.select(), "text") + if tab == "About": self.bottom_frame.pack_forget() + else: self.bottom_frame.pack(fill="x", padx=5, pady=(0,4), side="bottom") + self.notebook.bind("<>", on_tab_changed) + + # Console Tab + c_frame = ttk.Frame(self.console_tab); c_frame.pack(fill="both", expand=True, padx=4, pady=2) + ttk.Label(c_frame, text="Python console. Use 'm' for M18 object.").pack(anchor="w", pady=(0,1)) + self.console_text = tk.Text(c_frame, height=4, wrap="none", font=("Consolas",9)); self.console_text.pack(fill="x", padx=1, pady=(0,1)) + c_btns = ttk.Frame(c_frame); c_btns.pack(fill="x") + ttk.Button(c_btns, text="Execute", width=10, command=self.run_console_code).pack(side="left", padx=3) + ttk.Button(c_btns, text="Clear", width=7, command=lambda: self.console_text.delete("1.0", tk.END)).pack(side="left", padx=3) + + # Simulation Tab + s_frame = ttk.Frame(self.sim_tab); s_frame.pack(fill="both", padx=4, pady=1) + ttk.Label(s_frame, text="Simulation duration (sec):").grid(row=0, column=0, sticky="w", padx=2) + self.sim_duration_var = tk.StringVar(value="60") + ttk.Entry(s_frame, textvariable=self.sim_duration_var, width=5).grid(row=0, column=1, sticky="w", padx=2) + ttk.Label(s_frame, text="Sim baudrate (concept):").grid(row=1, column=0, sticky="w", padx=2) + self.sim_baud_var = tk.StringVar(value="4800") + ttk.Combobox(s_frame, textvariable=self.sim_baud_var, state="readonly", width=8, values=["1200","2400","4800","9600"]).grid(row=1, column=1, sticky="w", padx=2) + ttk.Label(s_frame, text="UART to pack always runs at 4800 baud.\nNo real charging current flows from USB.").grid(row=2, column=0, columnspan=2, sticky="w", padx=2, pady=(0,6)) + ttk.Label(s_frame, text="Charger profile:").grid(row=3, column=0, sticky="w", padx=2) + self.sim_profile_var = tk.StringVar(value="Normal") + profs = list(self.sim_profiles.keys())+["Custom"] + prof_box = ttk.Combobox(s_frame, textvariable=self.sim_profile_var, state="readonly", width=10, values=profs) + prof_box.grid(row=3, column=1, sticky="w", padx=2) + prof_box.bind("<>", self.on_profile_changed) + self.profile_info_var = tk.StringVar() + ttk.Label(s_frame, textvariable=self.profile_info_var, foreground="blue").grid(row=4, column=0, columnspan=2, sticky="w", padx=2, pady=(0,2)) + self.sim_status_var = tk.StringVar(value="Simulation idle. Connect to a battery to enable.") + ttk.Label(s_frame, textvariable=self.sim_status_var).grid(row=5, column=0, columnspan=2, sticky="w", padx=2) + self.sim_start_btn = ttk.Button(s_frame, text="Start simulation", width=15, command=self.start_simulation, state="disabled") + self.sim_start_btn.grid(row=6, column=0, padx=2, pady=2) + self.sim_stop_btn = ttk.Button(s_frame, text="Stop simulation", width=15, command=self.stop_simulation, state="disabled") + self.sim_stop_btn.grid(row=6, column=1, padx=2, pady=2) + + # About Tab + import webbrowser + a_frame = ttk.Frame(self.about_tab) + a_frame.place(relx=0.5, rely=0.09, anchor="n") + ttk.Label(a_frame, text="M18 Protocol GUI", font=("Segoe UI", 15, "bold")).pack(pady=(0,1)) + ttk.Label(a_frame, text="Core protocol by Martin Jansson", font=("Segoe UI", 9, "italic")).pack(pady=(5,0)) + link2 = ttk.Label(a_frame, text="Original: https://github.com/mnh-jansson/m18-protocol", foreground="blue", cursor="hand2"); link2.pack() + link2.bind("", lambda e: webbrowser.open("https://github.com/mnh-jansson/m18-protocol")) + ttk.Label(a_frame, text="Developed by KillaVolt", font=("Segoe UI", 9)).pack() + link = ttk.Label(a_frame, text="GitHub Profile: https://github.com/KillaVolt", foreground="blue", cursor="hand2"); link.pack() + link.bind("", lambda e: webbrowser.open("https://github.com/KillaVolt")) + + table = ttk.Treeview(a_frame, columns=("addr", "desc"), show="headings", height=8) + table.heading("addr", text="Hex Addr"); table.heading("desc", text="Meaning") + table.column("addr", width=65, anchor="center"); table.column("desc", width=150, anchor="w"); table.pack() + for addr, desc in [("F85D","1: Command"),("F85E","4: Access"),("F85F","3: Length"),("F860","Address?"),("F861","Address?"),("F862","Length?"),("F863","N/A"),("F864","Checksum")]: + table.insert("", "end", values=(addr,desc)) + + # -------- Utility / Port / Logging ---------- + def log(self, text, clear=False): + """Append ``text`` to the shared output area, optionally clearing it.""" + self.output_text.delete("1.0", tk.END) if clear else None; self.output_text.insert(tk.END, text + "\n"); self.output_text.see(tk.END) + + def sim_log(self, text): + """Prefix simulation messages to distinguish them in the log area.""" + self.log(f"[SIM] {text}") + + def set_status(self, text): + """Update the status label at the top of the UI.""" + self.status_var.set(text) + + def refresh_ports(self): + """Enumerate available serial ports and repopulate the dropdown.""" + ports = list_ports.comports(); names = []; self.port_map.clear() + for p in ports: + label = f"{p.device} — {p.description} ({getattr(p,'manufacturer','') or ''})".strip() + names.append(label); self.port_map[label] = p.device + self.port_combo["values"] = names; self.port_combo.current(0) if names else self.port_combo.set("") + self.set_status("Ports refreshed") + + def require_connection(self): + """Warn the user if no device is connected before running an action.""" + if self.m18_obj is None: messagebox.showwarning("Not connected", "Please connect to a port first."); return False + return True + + def capture_output(self, func, *a, **k): + """Run ``func`` while capturing stdout into a string.""" + buf, old = io.StringIO(), sys.stdout + try: sys.stdout = buf; func(*a, **k) + finally: sys.stdout = old + return buf.getvalue() + + # --------- Connect/Disconnect ----------- + def connect_device(self): + """Instantiate :class:`m18.M18` using the selected serial port.""" + sel = self.port_var.get() + port = self.port_map.get(sel, sel) + try: self.m18_obj = m18.M18(port) + except Exception as e: + self.m18_obj = None; messagebox.showerror("Connection error", f"Failed to connect to {port}.\n\n{e}") + self.set_status("Connection failed"); return + self.set_status(f"Connected to {port}"); self.log(f"Connected to {port}", clear=True) + for b in [self.connect_btn]: b.configure(state="disabled") + for b in [self.disconnect_btn, self.idle_btn, self.health_btn, self.clipboard_btn, self.sim_start_btn]: b.configure(state="normal") + + def disconnect_device(self): + """Return the pack to idle, close the port, and reset UI state.""" + self.stop_simulation() + if self.m18_obj: + try: self.m18_obj.idle() + except: pass + try: self.m18_obj.port.close() + except: pass + self.m18_obj = None + self.set_status("Disconnected"); self.log("Disconnected") + for b in [self.connect_btn]: b.configure(state="normal") + for b in [self.disconnect_btn, self.idle_btn, self.health_btn, self.clipboard_btn, self.sim_start_btn, self.sim_stop_btn]: b.configure(state="disabled") + + # ----------- Command Handlers ----------- + def cmd_idle(self): + """Invoke ``idle`` on the connected device in a worker thread.""" + if not self.require_connection(): return + def work(): + try: + self.m18_obj.idle() + self.after(0, lambda: self.log("TX now low (<1V). Safe to connect battery.")) + self.after(0, lambda: self.set_status("Idle (TX low)")) + except Exception as e: + self.after(0, lambda: messagebox.showerror("Idle error", str(e))) + threading.Thread(target=work, daemon=True).start() + + def cmd_health(self): + """Run ``health`` and display captured output.""" + if not self.require_connection(): return + def work(): + try: + output = self.capture_output(self.m18_obj.health) + def finish(): + self.log("=== Health report ===", clear=True) + self.log(output) + self.set_status("Health report complete") + self.after(0, finish) + except Exception as e: + self.after(0, lambda: messagebox.showerror("Health error", str(e))) + threading.Thread(target=work, daemon=True).start() + + def cmd_clipboard(self): + """Copy all register values to the clipboard.""" + if not self.require_connection(): return + def work(): + try: + output = self.capture_output(self.m18_obj.read_id, None, True, "raw") + def finish(): + self.clipboard_clear() + self.clipboard_append(output) + self.log("Register data copied to clipboard") + self.after(0, finish) + except Exception as e: + self.after(0, lambda: messagebox.showerror("Clipboard error", str(e))) + threading.Thread(target=work, daemon=True).start() + + # ---------- Interactive Console ---------- + def run_console_code(self): + """Execute arbitrary Python with the M18 object available as ``m``.""" + code = self.console_text.get("1.0", tk.END).strip() + if not code: messagebox.showinfo("No code", "Please enter some code."); return + if not self.require_connection(): return + def work(): + buf = io.StringIO(); old_stdout, old_stderr = sys.stdout, sys.stderr + sys.stdout = sys.stderr = buf + try: + env = {"m": self.m18_obj} + try: exec(code, env, {}) + except Exception: traceback.print_exc() + finally: sys.stdout, sys.stderr = old_stdout, old_stderr + output = buf.getvalue() + def finish(): + self.log("=== Console execution ===") + self.log(output if output.strip() else "(no output)") + self.after(0, finish) + threading.Thread(target=work, daemon=True).start() + + # ---------- Profile Display ---------- + def on_profile_changed(self, event=None): self.update_profile_display() + def update_profile_display(self): + """Show human readable info about the selected simulation profile.""" + p = self.sim_profile_var.get() + if p in self.sim_profiles: + c, m = self.sim_profiles[p] + info = f"Profile '{p}': Cutoff {c} ({c/1000:.2f}A), Max {m} ({m/1000:.2f}A). Simulation only." + self.profile_info_var.set(info) + else: self.profile_info_var.set("Custom profile: adjust fields below.") + def get_profile_currents(self): + """Return cutoff and max currents based on profile or custom fields.""" + p = self.sim_profile_var.get() + if p in self.sim_profiles: return self.sim_profiles[p] + try: + c = int(self.custom_cutoff_raw_var.get()) + m = int(self.custom_max_raw_var.get()) + if c < 0 or m <= 0 or c > 20000 or m > 20000: raise ValueError + except: raise ValueError("Invalid custom values.") + return c, m + + # ---------- Simulation ---------- + def start_simulation(self): + """Spawn a background thread to perform the charging dialogue.""" + if not self.require_connection(): return + if self.sim_thread and self.sim_thread.is_alive(): + messagebox.showinfo("Running", "Simulation already running."); return + try: + duration = float(self.sim_duration_var.get()) + if duration <= 0: raise ValueError + except: messagebox.showwarning("Invalid duration", "Enter a positive number."); return + sim_baud = self.sim_baud_var.get() + interval_map = {"1200": 1.0, "2400": 0.75, "4800": 0.5, "9600": 0.25} + keepalive_interval = interval_map.get(sim_baud, 0.5) + try: + cutoff, maxc = self.get_profile_currents() + except Exception as e: + messagebox.showwarning("Profile error", str(e)) + return + + pname = self.sim_profile_var.get() + + self.sim_stop_event = threading.Event() + self.sim_thread = threading.Thread( + target=self._simulation_worker, + args=( + duration, + keepalive_interval, + pname, + cutoff, + cutoff / 1000.0, + maxc, + maxc / 1000.0, + ), + daemon=True, + ) + self.sim_thread.start() + + self.sim_start_btn.configure(state="disabled") + self.sim_stop_btn.configure(state="normal") + self.sim_status_var.set(f"Simulation running ({pname}, baud {sim_baud})") + + self.sim_log( + f"Start {duration}s | {pname} | " + f"cutoff={cutoff} ({cutoff/1000:.2f}A) | " + f"max={maxc} ({maxc/1000:.2f}A) | " + f"interval={keepalive_interval:.2f}s" + ) + + def stop_simulation(self): + """Signal the simulation worker to exit.""" + if self.sim_stop_event: + self.sim_stop_event.set() + + def _simulation_worker( + self, + duration, + interval, + pname, + cutoff_raw, + cutoff_amps, + max_raw, + max_amps, + ): + """Perform the scripted keepalive dialogue for the configured duration.""" + m = self.m18_obj + if m is None: + self.after( + 0, + lambda: messagebox.showerror( + "Simulation error", "No active M18 connection." + ), + ) + return + + old_cutoff = getattr(m, "CUTOFF_CURRENT", None) + old_max = getattr(m, "MAX_CURRENT", None) + + m.CUTOFF_CURRENT = cutoff_raw + m.MAX_CURRENT = max_raw + + start_time = time.time() + + try: + self.after(0, lambda: self.sim_log("Resetting and negotiating charger state...")) + + try: + m.reset() + except Exception as e: + self.after(0, lambda: self.sim_log(f"reset() failed: {e}")) + return + + try: + m.configure(2) + m.get_snapchat() + time.sleep(0.6) + m.keepalive() + m.configure(1) + m.get_snapchat() + except Exception as e: + self.after(0, lambda: self.sim_log(f"Initial negotiation failed: {e}")) + return + + while not self.sim_stop_event.is_set(): + elapsed = time.time() - start_time + if elapsed >= duration: + break + + try: + time.sleep(interval) + m.keepalive() + self.after( + 0, + lambda e=elapsed: self.sim_log(f"Keepalive t={e:.1f}s"), + ) + except Exception as e: + self.after(0, lambda: self.sim_log(f"keepalive() failed: {e}")) + break + + finally: + try: + m.idle() + except Exception: + pass + + if old_cutoff is not None: + m.CUTOFF_CURRENT = old_cutoff + if old_max is not None: + m.MAX_CURRENT = old_max + + def finish(): + self.sim_log("Simulation finished. Returned to idle.") + self.sim_status_var.set("Simulation idle.") + self.sim_start_btn.configure(state="normal") + self.sim_stop_btn.configure(state="disabled") + + self.after(0, finish) + + +if __name__ == "__main__": + app = M18GUI() + app.mainloop() diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index a032c50..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,10 +0,0 @@ -[project] -name = "m18-protocol" -version = "0.1.0" -description = "Read Milwaukee M18 Protocol Data" -readme = "README.md" -requires-python = ">=3.13" -dependencies = [ - "pyserial==3.5", - "requests", -] diff --git a/uv.lock b/uv.lock deleted file mode 100644 index 8949790..0000000 --- a/uv.lock +++ /dev/null @@ -1,100 +0,0 @@ -version = 1 -revision = 3 -requires-python = ">=3.13" - -[[package]] -name = "certifi" -version = "2025.8.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" }, -] - -[[package]] -name = "charset-normalizer" -version = "3.4.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/83/2d/5fd176ceb9b2fc619e63405525573493ca23441330fcdaee6bef9460e924/charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", size = 122371, upload-time = "2025-08-09T07:57:28.46Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/65/ca/2135ac97709b400c7654b4b764daf5c5567c2da45a30cdd20f9eefe2d658/charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe", size = 205326, upload-time = "2025-08-09T07:56:24.721Z" }, - { url = "https://files.pythonhosted.org/packages/71/11/98a04c3c97dd34e49c7d247083af03645ca3730809a5509443f3c37f7c99/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8", size = 146008, upload-time = "2025-08-09T07:56:26.004Z" }, - { url = "https://files.pythonhosted.org/packages/60/f5/4659a4cb3c4ec146bec80c32d8bb16033752574c20b1252ee842a95d1a1e/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9", size = 159196, upload-time = "2025-08-09T07:56:27.25Z" }, - { url = "https://files.pythonhosted.org/packages/86/9e/f552f7a00611f168b9a5865a1414179b2c6de8235a4fa40189f6f79a1753/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31", size = 156819, upload-time = "2025-08-09T07:56:28.515Z" }, - { url = "https://files.pythonhosted.org/packages/7e/95/42aa2156235cbc8fa61208aded06ef46111c4d3f0de233107b3f38631803/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f", size = 151350, upload-time = "2025-08-09T07:56:29.716Z" }, - { url = "https://files.pythonhosted.org/packages/c2/a9/3865b02c56f300a6f94fc631ef54f0a8a29da74fb45a773dfd3dcd380af7/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927", size = 148644, upload-time = "2025-08-09T07:56:30.984Z" }, - { url = "https://files.pythonhosted.org/packages/77/d9/cbcf1a2a5c7d7856f11e7ac2d782aec12bdfea60d104e60e0aa1c97849dc/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9", size = 160468, upload-time = "2025-08-09T07:56:32.252Z" }, - { url = "https://files.pythonhosted.org/packages/f6/42/6f45efee8697b89fda4d50580f292b8f7f9306cb2971d4b53f8914e4d890/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5", size = 158187, upload-time = "2025-08-09T07:56:33.481Z" }, - { url = "https://files.pythonhosted.org/packages/70/99/f1c3bdcfaa9c45b3ce96f70b14f070411366fa19549c1d4832c935d8e2c3/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc", size = 152699, upload-time = "2025-08-09T07:56:34.739Z" }, - { url = "https://files.pythonhosted.org/packages/a3/ad/b0081f2f99a4b194bcbb1934ef3b12aa4d9702ced80a37026b7607c72e58/charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce", size = 99580, upload-time = "2025-08-09T07:56:35.981Z" }, - { url = "https://files.pythonhosted.org/packages/9a/8f/ae790790c7b64f925e5c953b924aaa42a243fb778fed9e41f147b2a5715a/charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef", size = 107366, upload-time = "2025-08-09T07:56:37.339Z" }, - { url = "https://files.pythonhosted.org/packages/8e/91/b5a06ad970ddc7a0e513112d40113e834638f4ca1120eb727a249fb2715e/charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15", size = 204342, upload-time = "2025-08-09T07:56:38.687Z" }, - { url = "https://files.pythonhosted.org/packages/ce/ec/1edc30a377f0a02689342f214455c3f6c2fbedd896a1d2f856c002fc3062/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db", size = 145995, upload-time = "2025-08-09T07:56:40.048Z" }, - { url = "https://files.pythonhosted.org/packages/17/e5/5e67ab85e6d22b04641acb5399c8684f4d37caf7558a53859f0283a650e9/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d", size = 158640, upload-time = "2025-08-09T07:56:41.311Z" }, - { url = "https://files.pythonhosted.org/packages/f1/e5/38421987f6c697ee3722981289d554957c4be652f963d71c5e46a262e135/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096", size = 156636, upload-time = "2025-08-09T07:56:43.195Z" }, - { url = "https://files.pythonhosted.org/packages/a0/e4/5a075de8daa3ec0745a9a3b54467e0c2967daaaf2cec04c845f73493e9a1/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa", size = 150939, upload-time = "2025-08-09T07:56:44.819Z" }, - { url = "https://files.pythonhosted.org/packages/02/f7/3611b32318b30974131db62b4043f335861d4d9b49adc6d57c1149cc49d4/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049", size = 148580, upload-time = "2025-08-09T07:56:46.684Z" }, - { url = "https://files.pythonhosted.org/packages/7e/61/19b36f4bd67f2793ab6a99b979b4e4f3d8fc754cbdffb805335df4337126/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0", size = 159870, upload-time = "2025-08-09T07:56:47.941Z" }, - { url = "https://files.pythonhosted.org/packages/06/57/84722eefdd338c04cf3030ada66889298eaedf3e7a30a624201e0cbe424a/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92", size = 157797, upload-time = "2025-08-09T07:56:49.756Z" }, - { url = "https://files.pythonhosted.org/packages/72/2a/aff5dd112b2f14bcc3462c312dce5445806bfc8ab3a7328555da95330e4b/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16", size = 152224, upload-time = "2025-08-09T07:56:51.369Z" }, - { url = "https://files.pythonhosted.org/packages/b7/8c/9839225320046ed279c6e839d51f028342eb77c91c89b8ef2549f951f3ec/charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce", size = 100086, upload-time = "2025-08-09T07:56:52.722Z" }, - { url = "https://files.pythonhosted.org/packages/ee/7a/36fbcf646e41f710ce0a563c1c9a343c6edf9be80786edeb15b6f62e17db/charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c", size = 107400, upload-time = "2025-08-09T07:56:55.172Z" }, - { url = "https://files.pythonhosted.org/packages/8a/1f/f041989e93b001bc4e44bb1669ccdcf54d3f00e628229a85b08d330615c5/charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", size = 53175, upload-time = "2025-08-09T07:57:26.864Z" }, -] - -[[package]] -name = "idna" -version = "3.10" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, -] - -[[package]] -name = "m18-protocol" -version = "0.1.0" -source = { virtual = "." } -dependencies = [ - { name = "pyserial" }, - { name = "requests" }, -] - -[package.metadata] -requires-dist = [ - { name = "pyserial", specifier = "==3.5" }, - { name = "requests" }, -] - -[[package]] -name = "pyserial" -version = "3.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1e/7d/ae3f0a63f41e4d2f6cb66a5b57197850f919f59e558159a4dd3a818f5082/pyserial-3.5.tar.gz", hash = "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb", size = 159125, upload-time = "2020-11-23T03:59:15.045Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/07/bc/587a445451b253b285629263eb51c2d8e9bcea4fc97826266d186f96f558/pyserial-3.5-py2.py3-none-any.whl", hash = "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0", size = 90585, upload-time = "2020-11-23T03:59:13.41Z" }, -] - -[[package]] -name = "requests" -version = "2.32.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "charset-normalizer" }, - { name = "idna" }, - { name = "urllib3" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, -] - -[[package]] -name = "urllib3" -version = "2.5.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, -]