commit 6b1fd776ab7c7b01165ee4107162b3eacfc537d4 Author: Ray Date: Sat Jul 11 02:31:25 2026 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8f87d36 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +bin +obj +packages +*~ +/.github +/.vs \ No newline at end of file diff --git a/Cursor GuardRail.slnx b/Cursor GuardRail.slnx new file mode 100644 index 0000000..d0ce028 --- /dev/null +++ b/Cursor GuardRail.slnx @@ -0,0 +1,3 @@ + + + diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..4b59c29 --- /dev/null +++ b/build.bat @@ -0,0 +1,11 @@ +rmdir /s /q "bin\" +rmdir /s /q "source\bin\" +rmdir /s /q "source\obj\" + +dotnet restore RandomFileRunner.slnx +dotnet publish RandomFileRunner.slnx -r win-x64 -c Release /p:PublishSingleFile=true /p:SelfContained=false /p:PublishReadyToRunfalse=true /p:PublishDir="..\bin\" + +rmdir /s /q "source\bin\" +rmdir /s /q "source\obj\" + +REM PAUSE \ No newline at end of file diff --git a/icon/favicon.ico b/icon/favicon.ico new file mode 100644 index 0000000..4e29cac Binary files /dev/null and b/icon/favicon.ico differ diff --git a/icon/icon.svg b/icon/icon.svg new file mode 100644 index 0000000..fef9209 --- /dev/null +++ b/icon/icon.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + diff --git a/icon/icon_128.png b/icon/icon_128.png new file mode 100644 index 0000000..6bee063 Binary files /dev/null and b/icon/icon_128.png differ diff --git a/icon/icon_16.png b/icon/icon_16.png new file mode 100644 index 0000000..70aebdc Binary files /dev/null and b/icon/icon_16.png differ diff --git a/icon/icon_24.png b/icon/icon_24.png new file mode 100644 index 0000000..266617d Binary files /dev/null and b/icon/icon_24.png differ diff --git a/icon/icon_32.png b/icon/icon_32.png new file mode 100644 index 0000000..4d97e82 Binary files /dev/null and b/icon/icon_32.png differ diff --git a/icon/icon_48.png b/icon/icon_48.png new file mode 100644 index 0000000..c4527d2 Binary files /dev/null and b/icon/icon_48.png differ diff --git a/icon/icon_64.png b/icon/icon_64.png new file mode 100644 index 0000000..6c68993 Binary files /dev/null and b/icon/icon_64.png differ diff --git a/icon/raw/circle.svg b/icon/raw/circle.svg new file mode 100644 index 0000000..80a34e6 --- /dev/null +++ b/icon/raw/circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon/raw/red-gear.svg b/icon/raw/red-gear.svg new file mode 100644 index 0000000..0fc8cb5 --- /dev/null +++ b/icon/raw/red-gear.svg @@ -0,0 +1,2590 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icon/raw/skip-forward.svg b/icon/raw/skip-forward.svg new file mode 100644 index 0000000..64ff623 --- /dev/null +++ b/icon/raw/skip-forward.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/research/D3u8VJkrvKwGB7rX6bUebZ.jpg b/research/D3u8VJkrvKwGB7rX6bUebZ.jpg new file mode 100644 index 0000000..a03bea0 Binary files /dev/null and b/research/D3u8VJkrvKwGB7rX6bUebZ.jpg differ diff --git a/research/DisplaySettings.webp b/research/DisplaySettings.webp new file mode 100644 index 0000000..11db403 Binary files /dev/null and b/research/DisplaySettings.webp differ diff --git a/source/.gitignore b/source/.gitignore new file mode 100644 index 0000000..81d4c76 --- /dev/null +++ b/source/.gitignore @@ -0,0 +1,8 @@ +/.vs +/bin +/obj +/*.user +/*/.vs +/*/bin +/*/obj +/*/*.user \ No newline at end of file diff --git a/source/AppResource.Designer.cs b/source/AppResource.Designer.cs new file mode 100644 index 0000000..5a249df --- /dev/null +++ b/source/AppResource.Designer.cs @@ -0,0 +1,159 @@ +//------------------------------------------------------------------------------ +// +// 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 CursorGuardRail { + 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 AppResource { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal AppResource() { + } + + /// + /// 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("CursorGuardRail.AppResource", typeof(AppResource).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; + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string AppAuthorURL { + get { + return ResourceManager.GetString("AppAuthorURL", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to https://www.hiimray.co.uk. + /// + internal static string AppCompanyURL { + get { + return ResourceManager.GetString("AppCompanyURL", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to https://www.hiimray.co.uk. + /// + internal static string AppHelpURL { + get { + return ResourceManager.GetString("AppHelpURL", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to https://www.hiimray.co.uk. + /// + internal static string AppProductURL { + get { + return ResourceManager.GetString("AppProductURL", resourceCulture); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap folder_minus { + get { + object obj = ResourceManager.GetObject("folder_minus", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap help_circle { + get { + object obj = ResourceManager.GetObject("help_circle", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap icon_64 { + get { + object obj = ResourceManager.GetObject("icon_64", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap refresh_cw { + get { + object obj = ResourceManager.GetObject("refresh_cw", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap save { + get { + object obj = ResourceManager.GetObject("save", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap settings { + get { + object obj = ResourceManager.GetObject("settings", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/source/AppResource.resx b/source/AppResource.resx new file mode 100644 index 0000000..5a6ada5 --- /dev/null +++ b/source/AppResource.resx @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + https://www.hiimray.co.uk + + + https://www.hiimray.co.uk + + + https://www.hiimray.co.uk + + + + Resources\folder-minus.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + Resources\help-circle.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + Resources\icon_64.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + Resources\refresh-cw.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + Resources\save.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + Resources\settings.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/source/CursorGuardRail.csproj b/source/CursorGuardRail.csproj new file mode 100644 index 0000000..5853e7a --- /dev/null +++ b/source/CursorGuardRail.csproj @@ -0,0 +1,67 @@ + + + + WinExe + net10.0-windows8.0 + true + randomfilerunner + Ray Lam + Hi, I'm Ray + Cursor GuardRail + Ray Lam + favicon.ico + true + 0.1.0.119 + + + + none + false + + + + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + AppResource.resx + + + + + + ResXFileCodeGenerator + AppResource.Designer.cs + + + + + + + + \ No newline at end of file diff --git a/source/Dtos/AppSession.cs b/source/Dtos/AppSession.cs new file mode 100644 index 0000000..d2dcf0c --- /dev/null +++ b/source/Dtos/AppSession.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace CursorGuardRail +{ + public class AppSession + { + public class HotKeyOptions + { + public bool IsCtrl { get; set; } = false; + public bool IsAlt { get; set; } = false; + public bool IsShift { get; set; } = false; + public int Key { get; set; } = (int)System.Windows.Forms.Keys.None; + + public int ModifierCode => ((this.IsAlt ? 1 : 0) + (this.IsCtrl ? 2 : 0) + (this.IsShift ? 4 : 0)); + + public System.Windows.Forms.Keys KeyCode => (System.Windows.Forms.Keys)this.Key; + } + + + public string SearchFilePattern { get; set; } = "*"; + + public List SearchItems + { + get => field ?? new List(); + set => field = value; + } + + public bool SearchTopDirectoryOnly { get; set; } = false; + + public bool ClosePrevOnNext { get; set; } = false; + + public int RetryOnError { get; set; } = 8; + + public HotKeyOptions NextHotKey + { + get => field ?? new HotKeyOptions(); + set => field = value; + } + + + } +} diff --git a/source/Dtos/ScreenItem.cs b/source/Dtos/ScreenItem.cs new file mode 100644 index 0000000..d84485c --- /dev/null +++ b/source/Dtos/ScreenItem.cs @@ -0,0 +1,14 @@ +using System.Drawing; + +namespace CursorGuardRail.Dtos +{ + public class ScreenItem + { + public RectangleF Bound { get; set; } + + public bool IsPrimary { get; set; } + + public bool IsSelected { get; set; } + + } +} \ No newline at end of file diff --git a/source/MainForm.Designer.cs b/source/MainForm.Designer.cs new file mode 100644 index 0000000..0295e1c --- /dev/null +++ b/source/MainForm.Designer.cs @@ -0,0 +1,342 @@ + +namespace CursorGuardRail +{ + partial class MainForm + { + /// + /// 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(MainForm)); + toolTip1 = new System.Windows.Forms.ToolTip(components); + button2 = new RyzStudio.Windows.ThemedForms.T3Button(); + button1 = new RyzStudio.Windows.ThemedForms.T3Button(); + menuStrip1 = new System.Windows.Forms.MenuStrip(); + fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + toolStripMenuItem13 = new System.Windows.Forms.ToolStripSeparator(); + exitToolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); + toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + refreshToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + helpToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + viewHelpToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + toolStripMenuItem16 = new System.Windows.Forms.ToolStripSeparator(); + aboutToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + dialogFooter1 = new RyzStudio.Windows.ThemedForms.Composite.DialogFooter(); + screensLayout1 = new CursorGuardRail.Windows.Forms.ScreensLayout(); + contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(components); + toolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); + toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + notifyIcon1 = new System.Windows.Forms.NotifyIcon(components); + menuStrip1.SuspendLayout(); + contextMenuStrip1.SuspendLayout(); + SuspendLayout(); + // + // button2 + // + button2.ActiveImage = null; + button2.Align = RyzStudio.Enums.ContentAlignment.Right; + button2.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; + button2.BackColor = System.Drawing.Color.Transparent; + button2.Checked = false; + button2.EnableMenuOnClick = false; + button2.EnableMovable = false; + button2.EnableStepWidth = true; + button2.HoverImage = null; + button2.IdleImage = null; + // + // + // + button2.Label.BackColor = System.Drawing.Color.White; + button2.Label.Dock = System.Windows.Forms.DockStyle.Fill; + button2.Label.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold); + button2.Label.ForeColor = System.Drawing.Color.FromArgb(126, 54, 244); + button2.Label.Location = new System.Drawing.Point(4, 4); + button2.Label.Margin = new System.Windows.Forms.Padding(0); + button2.Label.Name = "label1"; + button2.Label.Size = new System.Drawing.Size(173, 30); + button2.Label.TabIndex = 0; + button2.Label.Text = "Open Display &Settings"; + button2.Label.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + button2.LabelText = "Open Display &Settings"; + button2.Location = new System.Drawing.Point(274, 242); + button2.Name = "button2"; + button2.Size = new System.Drawing.Size(180, 37); + button2.TabIndex = 68; + toolTip1.SetToolTip(button2, "Open Display Settings"); + button2.MouseClick += button2_MouseClick; + // + // button1 + // + button1.ActiveImage = null; + button1.Align = RyzStudio.Enums.ContentAlignment.None; + button1.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; + button1.BackColor = System.Drawing.Color.Transparent; + button1.Checked = false; + button1.EnableMenuOnClick = false; + button1.EnableMovable = false; + button1.EnableStepWidth = true; + button1.HoverImage = null; + button1.IdleImage = null; + // + // + // + button1.Label.BackColor = System.Drawing.Color.White; + button1.Label.Dock = System.Windows.Forms.DockStyle.Fill; + button1.Label.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold); + button1.Label.ForeColor = System.Drawing.Color.FromArgb(126, 54, 244); + button1.Label.Location = new System.Drawing.Point(4, 4); + button1.Label.Margin = new System.Windows.Forms.Padding(0); + button1.Label.Name = "label1"; + button1.Label.Size = new System.Drawing.Size(113, 30); + button1.Label.TabIndex = 0; + button1.Label.Text = "&Refresh"; + button1.Label.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + button1.LabelText = "&Refresh"; + button1.Location = new System.Drawing.Point(143, 242); + button1.Name = "button1"; + button1.Size = new System.Drawing.Size(120, 37); + button1.TabIndex = 69; + toolTip1.SetToolTip(button1, "Refresh"); + button1.MouseClick += button1_MouseClick; + // + // menuStrip1 + // + menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { fileToolStripMenuItem, toolStripMenuItem1, toolsToolStripMenuItem, helpToolStripMenuItem1 }); + menuStrip1.Location = new System.Drawing.Point(0, 0); + menuStrip1.Name = "menuStrip1"; + menuStrip1.Size = new System.Drawing.Size(464, 24); + menuStrip1.TabIndex = 32; + menuStrip1.MenuActivate += menuStrip1_MenuActivate; + // + // fileToolStripMenuItem + // + fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { newToolStripMenuItem, toolStripMenuItem13, exitToolStripMenuItem2 }); + fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); + fileToolStripMenuItem.Text = "&File"; + // + // newToolStripMenuItem + // + newToolStripMenuItem.Enabled = false; + newToolStripMenuItem.Name = "newToolStripMenuItem"; + newToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N; + newToolStripMenuItem.Size = new System.Drawing.Size(141, 22); + newToolStripMenuItem.Text = "&New"; + newToolStripMenuItem.Click += newToolStripMenuItem_Click; + // + // toolStripMenuItem13 + // + toolStripMenuItem13.Name = "toolStripMenuItem13"; + toolStripMenuItem13.Size = new System.Drawing.Size(138, 6); + // + // exitToolStripMenuItem2 + // + exitToolStripMenuItem2.Name = "exitToolStripMenuItem2"; + exitToolStripMenuItem2.Size = new System.Drawing.Size(141, 22); + exitToolStripMenuItem2.Text = "E&xit"; + exitToolStripMenuItem2.Click += exitToolStripMenuItem2_Click; + // + // toolStripMenuItem1 + // + toolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { refreshToolStripMenuItem }); + toolStripMenuItem1.Name = "toolStripMenuItem1"; + toolStripMenuItem1.Size = new System.Drawing.Size(39, 20); + toolStripMenuItem1.Text = "&Edit"; + // + // refreshToolStripMenuItem + // + refreshToolStripMenuItem.Image = AppResource.refresh_cw; + refreshToolStripMenuItem.Name = "refreshToolStripMenuItem"; + refreshToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F5; + refreshToolStripMenuItem.Size = new System.Drawing.Size(132, 22); + refreshToolStripMenuItem.Text = "&Refresh"; + refreshToolStripMenuItem.Click += refreshToolStripMenuItem_Click; + // + // toolsToolStripMenuItem + // + toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { optionsToolStripMenuItem }); + toolsToolStripMenuItem.Name = "toolsToolStripMenuItem"; + toolsToolStripMenuItem.Size = new System.Drawing.Size(46, 20); + toolsToolStripMenuItem.Text = "&Tools"; + // + // optionsToolStripMenuItem + // + optionsToolStripMenuItem.Enabled = false; + optionsToolStripMenuItem.Image = AppResource.settings; + optionsToolStripMenuItem.Name = "optionsToolStripMenuItem"; + optionsToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.F12; + optionsToolStripMenuItem.Size = new System.Drawing.Size(177, 22); + optionsToolStripMenuItem.Text = "&Options..."; + optionsToolStripMenuItem.Click += optionsToolStripMenuItem_Click; + // + // helpToolStripMenuItem1 + // + helpToolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { viewHelpToolStripMenuItem1, toolStripMenuItem16, aboutToolStripMenuItem1 }); + helpToolStripMenuItem1.Name = "helpToolStripMenuItem1"; + helpToolStripMenuItem1.Size = new System.Drawing.Size(44, 20); + helpToolStripMenuItem1.Text = "&Help"; + // + // viewHelpToolStripMenuItem1 + // + viewHelpToolStripMenuItem1.Image = AppResource.help_circle; + viewHelpToolStripMenuItem1.Name = "viewHelpToolStripMenuItem1"; + viewHelpToolStripMenuItem1.ShortcutKeys = System.Windows.Forms.Keys.F1; + viewHelpToolStripMenuItem1.Size = new System.Drawing.Size(146, 22); + viewHelpToolStripMenuItem1.Text = "&View Help"; + viewHelpToolStripMenuItem1.Click += viewHelpToolStripMenuItem1_Click; + // + // toolStripMenuItem16 + // + toolStripMenuItem16.Name = "toolStripMenuItem16"; + toolStripMenuItem16.Size = new System.Drawing.Size(143, 6); + // + // aboutToolStripMenuItem1 + // + aboutToolStripMenuItem1.Name = "aboutToolStripMenuItem1"; + aboutToolStripMenuItem1.Size = new System.Drawing.Size(146, 22); + aboutToolStripMenuItem1.Text = "&About"; + aboutToolStripMenuItem1.Click += aboutToolStripMenuItem1_Click; + // + // dialogFooter1 + // + dialogFooter1.Align = RyzStudio.Enums.ContentAlignment.None; + dialogFooter1.BackColor = System.Drawing.Color.FromArgb(240, 240, 240); + dialogFooter1.Button1Result = System.Windows.Forms.DialogResult.OK; + dialogFooter1.Button1Text = "&Lock Cursor"; + dialogFooter1.Button1Visible = true; + dialogFooter1.Button2Result = System.Windows.Forms.DialogResult.Cancel; + dialogFooter1.Button2Text = "&Close"; + dialogFooter1.Button2Visible = true; + dialogFooter1.Dock = System.Windows.Forms.DockStyle.Bottom; + dialogFooter1.EnableMovable = false; + dialogFooter1.EnableStepWidth = false; + dialogFooter1.Location = new System.Drawing.Point(0, 531); + dialogFooter1.Name = "dialogFooter1"; + dialogFooter1.Size = new System.Drawing.Size(464, 70); + dialogFooter1.TabIndex = 0; + dialogFooter1.TabStop = false; + dialogFooter1.OnButton1Click += dialogFooter1_OnButton1Click; + dialogFooter1.OnButton2Click += dialogFooter1_OnButton2Click; + // + // screensLayout1 + // + screensLayout1.Align = RyzStudio.Enums.ContentAlignment.None; + screensLayout1.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; + screensLayout1.BackColor = System.Drawing.Color.Transparent; + screensLayout1.EnableMovable = false; + screensLayout1.EnableStepWidth = false; + screensLayout1.Location = new System.Drawing.Point(10, 34); + screensLayout1.Name = "screensLayout1"; + screensLayout1.Size = new System.Drawing.Size(444, 198); + screensLayout1.TabIndex = 67; + // + // contextMenuStrip1 + // + contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { toolStripMenuItem2, toolStripSeparator1, exitToolStripMenuItem }); + contextMenuStrip1.Name = "contextMenuStrip1"; + contextMenuStrip1.Size = new System.Drawing.Size(138, 54); + // + // toolStripMenuItem2 + // + toolStripMenuItem2.Name = "toolStripMenuItem2"; + toolStripMenuItem2.Size = new System.Drawing.Size(137, 22); + toolStripMenuItem2.Text = "&Lock Cursor"; + toolStripMenuItem2.Click += toolStripMenuItem2_Click; + // + // toolStripSeparator1 + // + toolStripSeparator1.Name = "toolStripSeparator1"; + toolStripSeparator1.Size = new System.Drawing.Size(134, 6); + // + // exitToolStripMenuItem + // + exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + exitToolStripMenuItem.Size = new System.Drawing.Size(137, 22); + exitToolStripMenuItem.Text = "Exit"; + exitToolStripMenuItem.Click += exitToolStripMenuItem2_Click; + // + // notifyIcon1 + // + notifyIcon1.ContextMenuStrip = contextMenuStrip1; + notifyIcon1.Icon = (System.Drawing.Icon)resources.GetObject("notifyIcon1.Icon"); + notifyIcon1.Text = "notifyIcon1"; + notifyIcon1.Visible = true; + notifyIcon1.MouseDoubleClick += notifyIcon1_MouseDoubleClick; + // + // MainForm + // + AllowDrop = true; + AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + BackColor = System.Drawing.Color.FromArgb(250, 250, 250); + ClientSize = new System.Drawing.Size(464, 601); + Controls.Add(button1); + Controls.Add(button2); + Controls.Add(screensLayout1); + Controls.Add(dialogFooter1); + Controls.Add(menuStrip1); + Icon = (System.Drawing.Icon)resources.GetObject("$this.Icon"); + MinimumSize = new System.Drawing.Size(480, 480); + Name = "MainForm"; + Text = "Cursor GuardRail"; + menuStrip1.ResumeLayout(false); + menuStrip1.PerformLayout(); + contextMenuStrip1.ResumeLayout(false); + ResumeLayout(false); + PerformLayout(); + } + + #endregion + private System.Windows.Forms.ToolTip toolTip1; + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem newToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem13; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem2; + private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem viewHelpToolStripMenuItem1; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem16; + private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem1; + private RyzStudio.Windows.ThemedForms.Composite.DialogFooter dialogFooter1; + private Windows.Forms.ScreensLayout screensLayout1; + private RyzStudio.Windows.ThemedForms.T3Button button2; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem refreshToolStripMenuItem; + private RyzStudio.Windows.ThemedForms.T3Button button1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.NotifyIcon notifyIcon1; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem2; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + } +} + diff --git a/source/MainForm.cs b/source/MainForm.cs new file mode 100644 index 0000000..ca45049 --- /dev/null +++ b/source/MainForm.cs @@ -0,0 +1,351 @@ +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using System.Windows.Forms; +using RyzStudio.Windows.Forms; +using static CursorGuardRail.MainForm; + +namespace CursorGuardRail +{ + public partial class MainForm : Form + { + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int Left; + public int Top; + public int Right; + public int Bottom; + } + + [DllImport("user32.dll", SetLastError = true)] + private static extern bool ClipCursor(ref RECT lpRect); + + [DllImport("user32.dll", SetLastError = true)] + private static extern bool ClipCursor(IntPtr lpRect); + + + private bool _requestExit = false; + private Rectangle? _lockCursorArea; + private readonly Timer _timer; + + + + public MainForm() + { + InitializeComponent(); + + screensLayout1.Padding = new Padding(10); + + _timer = new() { Interval = 50 }; + _timer.Tick += (_, _) => + { + if (Cursor.Clip != _lockCursorArea.Value) + { + ClipCursor(_lockCursorArea.Value); + } + }; + } + + protected async override void OnShown(EventArgs e) + { + base.OnShown(e); + + await Task.Run(() => + { + UIControl.Invoke(screensLayout1, (_) => screensLayout1.InvalidateScreens()); + }); + + //memoBox1.Focus(); + } + + protected override void OnFormClosing(FormClosingEventArgs e) + { + if (!_requestExit) + { + e.Cancel = true; + + this.Hide(); + return; + } + + ClipCursor(Rectangle.Empty); + + base.OnFormClosing(e); + } + + + public AppSession CurrentSession + { + get + { + if (field == null) field = new AppSession(); + + return field; + } + private set => field = value; + } + + [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] + public bool IsCursorLocked + { + get => field; + set + { + field = value; + + dialogFooter1.Button1.Checked = value; + dialogFooter1.Button1Text = value ? "&Unlock Cursor" : "&Lock Cursor"; + toolStripMenuItem2.Text = value ? "&Unlock Cursor" : "&Lock Cursor"; + + if (value) + { + _lockCursorArea = GetMaxScreenBound(); + if (!_lockCursorArea.HasValue || _lockCursorArea == Rectangle.Empty) + { + this.IsCursorLocked = false; + return; + } + + //ClipCursor(_lockCursorArea.Value); + + _timer.Start(); + } + else + { + ClipCursor(Rectangle.Empty); + + if (_timer.Enabled) + { + _timer.Stop(); + } + } + } + } = false; + + private void menuStrip1_MenuActivate(object sender, EventArgs e) + { + //saveAsToolStripMenuItem.Enabled = (!this.IsBusy && (this.SearchPathList.Count > 0)); + //toolStripMenuItem2.Enabled = (!this.IsBusy && (_foundFiles.Count > 0)); + } + + #region Main Menu + + /// + /// New + /// + /// + /// + private async void newToolStripMenuItem_Click(object sender, EventArgs e) + { + refreshToolStripMenuItem_Click(sender, e); + } + + /// + /// Close + /// + /// + /// + private void exitToolStripMenuItem2_Click(object sender, EventArgs e) + { + _requestExit = true; + + this.Close(); + } + + + /// + /// Refresh + /// + /// + /// + private async void refreshToolStripMenuItem_Click(object sender, EventArgs e) + { + await Task.Run(() => + { + this.IsCursorLocked = false; + + ClipCursor(Rectangle.Empty); + + UIControl.Invoke(screensLayout1, (_) => screensLayout1.InvalidateScreens()); + }); + } + + + /// + /// Options + /// + /// + /// + private void optionsToolStripMenuItem_Click(object sender, EventArgs e) + { + // Do nothing + } + + + /// + /// Help + /// + /// + /// + private void viewHelpToolStripMenuItem1_Click(object sender, EventArgs e) + { + RyzStudio.Diagnostics.Process.Execute(AppResource.AppHelpURL); + } + + /// + /// About + /// + /// + /// + private void aboutToolStripMenuItem1_Click(object sender, EventArgs e) + { + var form = new RyzStudio.Forms.T3AboutForm(); + form.ProductURL = AppResource.AppProductURL; + form.AuthorURL = AppResource.AppAuthorURL; + form.CompanyURL = AppResource.AppCompanyURL; + form.ProductCopyrightStartYear = 2026; + form.ProductLogo = AppResource.icon_64; + + form.ShowDialog(); + } + + #endregion + + + /// + /// Hide/show + /// + /// + /// + private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e) + { + if (this.Visible) + { + this.Hide(); + } + else + { + this.Show(); + } + } + + /// + /// Lock/unlock cursor + /// + /// + /// + private void toolStripMenuItem2_Click(object sender, EventArgs e) + { + this.IsCursorLocked = !this.IsCursorLocked; + } + + + /// + /// Refresh + /// + /// + /// + private async void button1_MouseClick(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + refreshToolStripMenuItem_Click(sender, e); + } + } + + /// + /// Open display settings + /// + /// + /// + private async void button2_MouseClick(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + try + { + Process.Start(new ProcessStartInfo + { + FileName = "ms-settings:display", + UseShellExecute = true + }); + } + catch (Exception) + { + // Do nothing + } + } + } + + + /// + /// Enable + /// + /// + /// + private async void dialogFooter1_OnButton1Click(object sender, MouseEventArgs e) + { + this.IsCursorLocked = !this.IsCursorLocked; + } + + /// + /// Close + /// + /// + /// + private void dialogFooter1_OnButton2Click(object sender, MouseEventArgs e) + { + this.Close(); + } + + + private Rectangle GetMaxScreenBound() + { + Rectangle? rect = null; + + for (var i = 0; i < screensLayout1.Screens.Count; i++) + { + if (!screensLayout1.Screens[i].IsSelected) + { + continue; + } + + if (rect == null) + { + rect = Screen.AllScreens[i].Bounds; + } + else + { + rect = Rectangle.Union(Screen.AllScreens[i].Bounds, rect.Value); + } + } + + return rect ?? Rectangle.Empty; + } + + private void ClipCursor(Rectangle rect) + { + if (rect == Rectangle.Empty) + { + ClipCursor(IntPtr.Zero); + } + else + { + var rect2 = new RECT + { + Left = rect.X, + Top = rect.Y, + Right = rect.Width, + Bottom = rect.Height + }; + + ClipCursor(ref rect2); + } + } + + } +} \ No newline at end of file diff --git a/source/MainForm.resx b/source/MainForm.resx new file mode 100644 index 0000000..7713526 --- /dev/null +++ b/source/MainForm.resx @@ -0,0 +1,730 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 127, 15 + + + 14, 15 + + + 224, 15 + + + 379, 15 + + + + + AAABAAQAMDAAAAEAIACoJQAARgAAACAgAAABACAAqBAAAO4lAAAYGAAAAQAgAIgJAACWNgAAEBAAAAEA + IABoBAAAHkAAACgAAAAwAAAAYAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAlJSUpKCgojCkpKbYoKCjYKCgo7CgoKPkoKCj5KCgo7CgoKNgpKSm2KCgojCUlJSkAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAoKCjVKCgo/ygoKP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygo + KNUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoKCjtKCgo/ygoKP8sKyj/OzQn/0M6J/9DOif/OzQn/ywr + KP8oKCj/KCgo/ygoKO0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAMzMzBSgoKDogICAIAAAAAAAAAAAAAAAAAAAAAAAAAAAoKCjtKCgo/zs0J//bnR//3p8f/96f + H//enx//3p8f/9udH/87NCf/KCgo/ygoKO0AAAAAAAAAAAAAAAAAAAAAAAAAACAgIAgoKCg6MzMzBQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAkJCQjKCgozCgoKP8oKCjNKCgoEwAAAAAAAAAAKSkpJSgoKHgoKCj5KCgo/zw1 + J//enx//3p8f/96fH//enx//3p8f/96fH/88NSf/KCgo/ygoKPkoKCh4KSkpJQAAAAAAAAAAKCgoEygo + KM0oKCj/KCgozCQkJCMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAACkpKUsoKCjxKCgo/ygoKP8oKCj/JycnzykpKUQnJye1KCgo/ygo + KP8oKCj/KCgo/0M6J//enx//3p8f/96fH//enx//3p8f/96fH/9DOif/KCgo/ygoKP8oKCj/KCgo/ygo + KLQpKSlEJycnzygoKP8oKCj/KCgo/ygoKPApKSlLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCgoXygoKPsoKCj/KCgo/ygoKP8oKCj/KCgo/ygo + KP8oKCj/KCgo/ygoKP8oKCj/Rjsm/6h8Iv/enx//3p8f/96fH//enx//3p8f/96fH/+ofCL/Rjsm/ygo + KP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKP8oKCj7KSkpXgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoKChfKCgo/igoKP8oKCj/XEol/7CB + If82MSf/KCgo/ygoKP8oKCj/OjQn/4VlJP/AiyD/3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/8CMIf+EZCT/OjQn/ygoKP8oKCj/KCgo/zYxJ/+vgCH/XEol/ygoKP8oKCj/KCgo/ikp + KV4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkpKUsoKCj7KCgo/ygo + KP9sVCX/3J4g/96fH/+8iSD/PDUn/zo0J/+NaiP/15of/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//15of/41qI/86NCf/PDUn/7yJIP/enx//3J4g/2xU + Jf8oKCj/KCgo/ygoKPspKSlLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJCQkIygo + KPAoKCj/KCgo/2xUJf/dnh//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/92eH/9sVCX/KCgo/ygoKP8oKCjwJCQkIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABAQEAEKCgozCgoKP8oKCj/XEol/9yeIP/enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//cniD/XEol/ygoKP8oKCj/KCgozEBAQAQAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAqKio3KCgo/ygoKP8oKCj/sIEh/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/8ONIP+QbCP/eFwk/2hSJf9oUiX/eV0k/5BsI//DjSD/3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//sIEh/ygoKP8oKCj/KCgo/yoq + KjcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAIKCgozigoKP8oKCj/NjEn/7yJIP/enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/9yeIP+UbyL/RTsn/ygoKP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygo + KP8oKCj/Rjwn/5VvI//cniD/3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH/+8iSD/NjEn/ygo + KP8oKCj/KCgoziAgIAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCgoEycnJ88oKCj/KCgo/z42 + J//dnh//3p8f/96fH//enx//3p8f/96fH//enx//tIMh/0U7J/8oKCj/KCgo/ygoKP8oKCj/KCgo/ygo + KP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKP9GPCf/tYQh/96fH//enx//3p8f/96fH//enx//3p8f/92e + H/8+Nif/KCgo/ygoKP8nJyfPKCgoEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkp + KUQoKCj/KCgo/zkzJ//dnh//3p8f/96fH//enx//3p8f/96fH/+YcSL/LCso/ygoKP8oKCj/KCgo/1VV + Vf+YmJj/xMTE/9vb2//b29v/xMTE/5eXl/9UVFT/KCgo/ygoKP8oKCj/LSso/5lyIv/enx//3p8f/96f + H//enx//3p8f/92eH/85Myf/KCgo/ygoKP8pKSlEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAACcnJ7UoKCj/KCgo/41qI//enx//3p8f/96fH//enx//3p8f/5hxIv8oKCj/KCgo/ygo + KP9TU1P/ycnJ////////////////////////////////////////////x8fH/1FRUf8oKCj/KCgo/ygo + KP+ZciL/3p8f/96fH//enx//3p8f/96fH/+NaiP/KCgo/ygoKP8nJye1AAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAKCgoJigoKP8oKCj/OjQn/9eaH//enx//3p8f/96fH//enx//tIMh/ywr + KP8oKCj/KCgo/3t7e//6+vr///////////////////////////////////////////////////////n5 + +f95eXn/KCgo/ygoKP8tKyj/tYQh/96fH//enx//3p8f/96fH//XmyD/OTMn/ygoKP8oKCj/KSkpJQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCgoeCgoKP8oKCj/hWUk/96fH//enx//3p8f/96f + H//cniD/RDon/ygoKP8oKCj/e3t7//////////////////////////////////////////////////// + ////////////////////////eXl5/ygoKP8oKCj/Rjwn/9yeIP/enx//3p8f/96fH//enx//hGQk/ygo + KP8oKCj/KCgoeAAAAAAAAAAAAAAAAAAAAAAlJSUpKSkp1igoKO4oKCjuKCgo+SgoKP8oKCj/wIsg/96f + H//enx//3p8f/96fH/+TbiL/KCgo/ygoKP9TU1P/+vr6///////39/f/sLCw/87Ozv////////////// + ////////////////////////+vr6/7W1tf//////+fn5/1BQUP8oKCj/KCgo/5VvI//enx//3p8f/96f + H//enx//wIwh/ygoKP8oKCj/KCgo+SgoKO4oKCjuKSkp1iUlJSkoKCiOKCgo/ygoKP8oKCj/KCgo/ygo + KP9GPCb/3p8f/96fH//enx//3p8f/96fH/9EOif/KCgo/ygoKP/Kysr///////////9VU07/FhEH/wYF + A/9RT0z/4ODg////////////////////////////zc3N/wEBAf///////////8fHx/8oKCj/KCgo/0Y8 + J//enx//3p8f/96fH//enx//3p8f/0Y7Jv8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKI4nJye1KCgo/ygo + KP8/Nyf/QTgn/0Y8J/+pfCL/3p8f/96fH//enx//3p8f/8GMIP8oKCj/KCgo/1ZWVv////////////// + //8GBQT/xYQA/9mSAP9HMgb/CgkG/4SEg//4+Pj/////////////////y8vL/wAAAP////////////// + //9UVFT/KCgo/ygoKP/DjSD/3p8f/96fH//enx//3p8f/6l8Iv9GPCf/QTgn/z42J/8oKCj/KCgo/ycn + J7UoKCjaKCgo/y0rKP/bnR//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/45rI/8oKCj/KCgo/5mZ + mf////////////////8AAAD/y4gA//+rAP//qwD/sncA/yAYB/8kIRz/tbW1////////////y8vL/wAA + AP////////////////+Xl5f/KCgo/ygoKP+QbCP/3p8f/96fH//enx//3p8f/96fH//enx//3p8f/9ud + H/8sKyj/KCgo/ygoKNkoKCjsKCgo/zs0J//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/3ld + JP8oKCj/KCgo/8bGxv////////////////8AAAD/y4gA//+rAP//qwD//6sA//WkAP96UgH/BwYD/1ZU + T//39/f/y8vL/wAAAP/////////////////Dw8P/KCgo/ygoKP97XiT/3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH/86NCf/KCgo/ygoKOooKCj5KCgo/0Q6J//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/2dRJf8oKCj/KCgo/9vb2/////////////////8AAAD/y4gA//+rAP//qwD//6sA//+r + AP//qwD/2ZIA/ygdCP+IiIj/y8vL/wAAAP/////////////////a2tr/KCgo/ygoKP9oUiX/3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH/9EOif/KCgo/ygoKPgoKCj5KCgo/0Q6J//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/2ZQJf8oKCj/KCgo/9zc3P////////////////8AAAD/y4gA//+r + AP//qwD//6sA//+rAP//qwD/2ZIA/ygdCP+IiIj/y8vL/wAAAP/////////////////b29v/KCgo/ygo + KP9nUSX/3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH/9EOif/KCgo/ygoKPgoKCjsKCgo/zs0 + J//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/3hcJP8oKCj/KCgo/8fHx/////////////// + //8AAAD/y4gA//+rAP//qwD//6sA//WkAP96UgH/BwYD/1ZUT//39/f/y8vL/wAAAP////////////// + ///ExMT/KCgo/ygoKP96XiT/3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH/86NCf/KCgo/ygo + KOooKCjaKCgo/y0rKP/bnR//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/45rI/8oKCj/KCgo/5qa + mv////////////////8AAAD/y4gA//+rAP//qwD/sncA/yAYB/8kIRz/tbW1////////////y8vL/wAA + AP////////////////+Xl5f/KCgo/ygoKP+QbCP/3p8f/96fH//enx//3p8f/96fH//enx//3p8f/9ud + H/8sKyj/KCgo/ygoKNknJye1KCgo/ygoKP8/Nyf/QTgn/0Y8J/+pfCL/3p8f/96fH//enx//3p8f/8CL + IP8oKCj/KCgo/1ZWVv////////////////8GBQT/xYQA/9mSAP9HMgb/CgkG/4WFhP/4+Pj///////// + ////////y8vL/wAAAP////////////////9VVVX/KCgo/ygoKP/CjSD/3p8f/96fH//enx//3p8f/6l8 + Iv9GPCf/QTgn/z42J/8oKCj/KCgo/ycnJ7UoKCiOKCgo/ygoKP8oKCj/KCgo/ygoKP9GPCb/3p8f/96f + H//enx//3p8f/96fH/9DOif/KCgo/ygoKP/Ly8v///////////9UUk3/GBIH/wYFA/9SUE3/4ODg//// + ////////////////////////zc3N/wEBAf///////////8nJyf8oKCj/KCgo/0U7J//enx//3p8f/96f + H//enx//3p8f/0Y8Jv8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKI4lJSUpKSkp1igoKO4oKCjuKCgo+Sgo + KP8oKCj/wIsg/96fH//enx//3p8f/96fH/+TbiL/KCgo/ygoKP9VVVX/+/v7///////39/f/rq6u/83N + zf//////////////////////////////////////+vr6/7W1tf//////+vr6/1JSUv8oKCj/KCgo/5Rv + Iv/enx//3p8f/96fH//enx//wIsg/ygoKP8oKCj/KCgo+SgoKO4oKCjuKSkp1iUlJSkAAAAAAAAAAAAA + AAAAAAAAKCgoeSgoKP8oKCj/hWUj/96fH//enx//3p8f/96fH//bnR//Qzon/ygoKP8oKCj/fX19//// + ////////////////////////////////////////////////////////////////////////e3t7/ygo + KP8oKCj/RDon/9yeIP/enx//3p8f/96fH//enx//hWUk/ygoKP8oKCj/KCgoeAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAKCgoJigoKP8oKCj/OzQn/9eaH//enx//3p8f/96fH//enx//s4Mi/ywr + KP8oKCj/KCgo/319ff/6+vr///////////////////////////////////////////////////////r6 + +v97e3v/KCgo/ygoKP8sKyj/tIMh/96fH//enx//3p8f/96fH//Xmh//OjQn/ygoKP8oKCj/KSkpJQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkpKbYoKCj/KCgo/45rI//enx//3p8f/96f + H//enx//3p8f/5dxI/8oKCj/KCgo/ygoKP9UVFT/y8vL//////////////////////////////////// + ////////ycnJ/1NTU/8oKCj/KCgo/ygoKP+YcSL/3p8f/96fH//enx//3p8f/96fH/+NaiP/KCgo/ygo + KP8nJye1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkpKUQoKCj/KCgo/zkz + J//dnh//3p8f/96fH//enx//3p8f/96fH/+XcSP/LCso/ygoKP8oKCj/KCgo/1ZWVv+ampr/xsbG/9vb + 2//b29v/xsbG/5mZmf9WVlb/KCgo/ygoKP8oKCj/LCso/5hxIv/enx//3p8f/96fH//enx//3p8f/92e + H/85Myf/KCgo/ygoKP8pKSlEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCgoEycn + J88oKCj/KCgo/z42J//dnh//3p8f/96fH//enx//3p8f/96fH//enx//s4Mi/0I5Jv8oKCj/KCgo/ygo + KP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKP9EOif/tIMh/96fH//enx//3p8f/96f + H//enx//3p8f/92eH/8+Nif/KCgo/ygoKP8nJyfPKCgoEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAgICAIKCgozigoKP8oKCj/NjEn/7yJIP/enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/9ud + H/+TbiL/Qzon/ygoKP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKP8oKCj/RDon/5NuIv/cniD/3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH/+8iSD/NjEn/ygoKP8oKCj/KCgoziAgIAgAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAqKio3KCgo/ygoKP8oKCj/sIEh/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/8GMIP+PayP/eFwk/2hSJf9oUiX/eFwk/49rI//BjCD/3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//sIEh/ygoKP8oKCj/KCgo/yoq + KjcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEAEKCgozCgoKP8oKCj/XUsl/9yeIP/enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//cniD/XEol/ygo + KP8oKCj/KCgozEBAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJCQkIygoKPEoKCj/KCgo/2xU + Jf/dnh//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/92e + H/9sVCX/KCgo/ygoKP8oKCjwJCQkIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgo + KEwoKCj7KCgo/ygoKP9sVCX/3J4g/96fH/+8iSD/PDUn/zo0J/+OayP/15of/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//15of/41qI/86NCf/PDUn/7yJ + IP/enx//3J4g/2xUJf8oKCj/KCgo/ygoKPspKSlLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAoKChfKCgo/igoKP8oKCj/XUsl/7CBIf82MSf/KCgo/ygoKP8oKCj/OzQn/4Vl + I//AiyD/3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/8CLIP+FZST/OjQn/ygo + KP8oKCj/KCgo/zYxJ/+wgSH/XEol/ygoKP8oKCj/KCgo/igoKF8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCgoXygoKPsoKCj/KCgo/ygoKP8oKCj/KCgo/ygo + KP8oKCj/KCgo/ygoKP8oKCj/Rjsm/6h8Iv/enx//3p8f/96fH//enx//3p8f/96fH/+ofCL/Rjsm/ygo + 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 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoKCjxKCgo/y4sKP84Myj/ODMo/y4sKP8oKCj/KCgo8QAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAACAgIAgpKSlqJycnJwAAAAAAAAAAAAAAAygoKPQ0MCf/3Z4f/96fH//enx//3Z4f/zQw + J/8oKCj0AAAAAwAAAAAAAAAAJycnJykpKWogICAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAmJiYiJycnzygoKP8pKCjrJycnQigoKIwoKCjpKCgo/zgyJ//enx//3p8f/96f + H//enx//ODIn/ygoKP8oKCjpKCgojCcnJ0IpKCjrKCgo/ycnJ88nJychAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAKCgoLSkoKOcoKCj/Pzcn/ygoKP8oKCj/KCgo/ysqKP9bSSb/qXwi/96f + H//enx//3p8f/96fH/+pfCL/Wkkm/ysqKP8oKCj/KCgo/ygoKP8+Nif/KCgo/ykoKOcoKCgtAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAACcnJyEpKCjnKCgo/3JYJf/bnR//el4k/zAtJ/96XiT/zpQf/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//zpQf/3peJP8wLSf/el4k/9yeIP9xWCT/KCgo/ygo + KOcnJychAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAIKCgozigoKP9xWCT/3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H/91WiT/KCgo/ygoKNIcHBwJAAAAAAAAAAAAAAAAAAAAACgoKGwoKCj/PjYn/9udH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//0pcg/6Z6Iv+QbCP/kGwj/6Z6Iv/SlyD/3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/9yeIP8+Nif/KCgo/ygoKGwAAAAAAAAAAAAAAAAAAAAAKCgoJikoKOsoKCj/eFwk/96f + H//enx//3p8f/96fH//enx//wIwh/2FNJf8qKij/KCgo/ygoKP8oKCj/KCgo/yoqKP9iTiX/wIsg/96f + H//enx//3p8f/96fH//enx//eFwk/ygoKP8pKCjrKCgoJgAAAAAAAAAAAAAAAAAAAAAAAAAAKioqQygo + KP8yLyj/3Z4f/96fH//enx//3p8f/5dxI/8sKyj/KCgo/zw8PP97e3v/nJyc/5ycnP97e3v/Ozs7/ygo + KP8sKyj/mHEj/96fH//enx//3p8f/92eH/8yLyj/KCgo/ycnJ0IAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAoKCiOKCgo/3teJP/enx//3p8f/96fH/+XcSP/KCgo/y0tLP+dnZ3/+vr6//////////////////// + ///5+fn/nJyc/y0tLP8oKCj/mHEj/96fH//enx//3p8f/3peJP8oKCj/KCgojAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAygoKOksKij/z5Uf/96fH//enx//wIsh/ywrKP8tLSz/yMjI//////////////////// + ////////////////////////x8fH/y0tLP8sKyj/wIsg/96fH//enx//zpQf/ysqKP8oKCjoAAAAAwAA + AAAAAAAAKCgodCgoKO4oKCjwKCgo/1tJJv/enx//3p8f/96fH/9hTSX/KCgo/56env//////s7Ku/397 + cv/p6en//////////////////////5mZmf//////nJyc/ygoKP9iTiX/3p8f/96fH//enx//W0km/ygo + KP8oKCjwKCgo7igoKHQoKCjIKCgo/zMvJ/83Mij/qXwh/96fH//enx//0Zcg/ysqKP88PDz/+vr6//// + //8tJRX/pnED/zAnFf+TkIv//Pz8////////////NDQ0///////5+fn/PDw8/ysqKP/SlyD/3p8f/96f + H/+pfCH/NzIo/zMvJ/8oKCj/KCgoxygoKOouLCj/3J4f/96fH//enx//3p8f/96fH/+leiL/KCgo/319 + ff///////////zQqFf//qwD/9qUA/39ZDP84MSP/xMTD//////80NDT///////////97e3v/KCgo/6Z6 + Iv/enx//3p8f/96fH//enx//3J4f/y0rKP8oKCjpKCgo+TgyJ//enx//3p8f/96fH//enx//3p8f/5Ft + I/8oKCj/nJyc////////////NCoV//+rAP//qwD//6sA/9qSAP8+MBL/yMjI/zQ0NP///////////5ub + m/8oKCj/k24j/96fH//enx//3p8f/96fH//enx//ODMo/ygoKPgoKCj5ODIn/96fH//enx//3p8f/96f + H//enx//kGwj/ygoKP+dnZ3///////////80KhX//6sA//+rAP//qwD/25MA/z4wEv/Hx8f/NDQ0//// + ////////nJyc/ygoKP+RbSP/3p8f/96fH//enx//3p8f/96fH/84Mif/KCgo+CgoKOouLCj/3J4f/96f + H//enx//3p8f/96fH/+keSL/KCgo/319ff///////////zQqFf//qwD/9qUA/39ZDP83MCP/xMTD//// + //80NDT///////////97e3v/KCgo/6V6If/enx//3p8f/96fH//enx//3J4f/y0rKP8oKCjpKCgoyCgo + KP8zLyf/NzIo/6l8If/enx//3p8f/9CWIP8rKij/PT09//r6+v//////LSUV/6ZxA/8wJxX/k5CL//z8 + /P///////////zQ0NP//////+vr6/zw8PP8qKij/0Zcg/96fH//enx//qXwh/zcyKP8zLyf/KCgo/ygo + KMcoKCh0KCgo7igoKPAoKCj/W0km/96fH//enx//3p8f/2FNJv8oKCj/oKCg//////+ysKz/f3ty/+np + 6f//////////////////////mZmZ//////+enp7/KCgo/2FNJf/enx//3p8f/96fH/9bSSb/KCgo/ygo + KPAoKCjuKCgodAAAAAAAAAAAAAAAAygoKOosKij/z5Uf/96fH//enx//v4sh/ysqKP8uLi3/yMjI//// + ////////////////////////////////////////yMjI/y0tLP8sKyj/wIsg/96fH//enx//zpQf/ysq + KP8oKCjpAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAKCgojigoKP97XiT/3p8f/96fH//enx//lnAj/ygo + KP8uLi3/oKCg//r6+v//////////////////////+vr6/5+fn/8uLi3/KCgo/5dxI//enx//3p8f/96f + H/97XiT/KCgo/ygoKI0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqKipDKCgo/zIvKP/dnh//3p8f/96f + H//enx//lnAj/ysqKP8oKCj/PT09/3x8fP+dnZ3/nZ2d/3x8fP88PDz/KCgo/ywrKP+XcSP/3p8f/96f + H//enx//3Z4f/zIvKP8oKCj/JycnQgAAAAAAAAAAAAAAAAAAAAAAAAAAKCgoJikoKOsoKCj/eFwk/96f + H//enx//3p8f/96fH//enx//wIsh/2FNJv8rKij/KCgo/ygoKP8oKCj/KCgo/ysqKP9hTSX/wIwh/96f + H//enx//3p8f/96fH//enx//eFwk/ygoKP8pKCjrKCgoJgAAAAAAAAAAAAAAAAAAAAAoKChtKCgo/z83 + J//bnR//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/9CWIP+leiL/kGwj/5BsI/+leiL/0Zcg/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//cniD/PjYn/ygoKP8oKChtAAAAAAAAAAAAAAAAAAAAACAg + IAgoKCjOKCgo/3JYJf/enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/3dcJP8oKCj/KCgo0hwcHAkAAAAAAAAAAAAA + AAAAAAAAAAAAACYmJiIpKCjnKCgo/3JYJf/bnR//el4k/zAtJ/97XiT/z5Uf/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//z5Uf/3teJP8wLSf/el4k/9yeIP9xWCT/KCgo/ykoKOcmJiYiAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAACgoKC0pKCjoKCgo/z83J/8oKCj/KCgo/ygoKP8sKij/W0km/6l8 + Iv/enx//3p8f/96fH//enx//qXwi/1tJJv8sKij/KCgo/ygoKP8oKCj/PjYn/ygoKP8pKCjnKCgoLQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYmJiIoKCjQKCgo/ykoKOsqKipDKCgojigo + KOooKCj/ODIn/96fH//enx//3p8f/96fH/84Mif/KCgo/ygoKOooKCiOKioqQykoKOsoKCj/KCgo0CYm + JiIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAgIAgpKSlqJycnJwAA + AAAAAAAAAAAAAygoKPQ0MCf/3Z4f/96fH//enx//3Z4f/zQwJ/8oKCj0AAAAAwAAAAAAAAAAJycnJykp + KWogICAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAKCgo8SgoKP8uLCj/ODIn/zgyJ/8uLCj/KCgo/ygoKPEAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJyd1KCgoyCgoKOooKCj5KCgo+SgoKOkoKCjIJycndQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/wD///8A///GAGP/gA + AB/wAAAP4AAAB8AAAAPAAAADwAAAA+AAAAfgAAAHwAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAwAAAA+AAAAfgAAAHwAAAA8AAAAPAAAAD4AAAB/AAAA/4AAAf/GAGP//wD///8A//KAAAABgA + AAAwAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAACkpKKEtLCjdKSkn9ykpJ/ctLCjdKSkooQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJycnDQAAAAIAAAAAAAAAACopKPhXRyb/imgk/4po + JP9XRyb/Kiko+AAAAAAAAAAAAAAAAicnJw0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAApKSlLKioo8ykpKK4pKSk+KSgopykoKP6OayP/3p8f/96fH/+OayP/KSgo/ikoKKcqKio9KSkorioq + KPMpKSlLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkpKWopKSj9UEMm/SopJ/0oKCj/QTgn+4Nj + I//RlyD/3p8f/96fH//RlyD/g2Mj/0E4J/soKCj/Kikn/VBDJv0pKSj9KSkpagAAAAAAAAAAAAAAAAAA + AAAAAAAAKSkpSykpKP1zWST/250f/7CBIf+gdiL/3J4f/96fH//enx//3p8f/96fH//enx//3p8f/9ye + H/+gdiL/sIEh/9udH/9zWST/KSko/SkpKUsAAAAAAAAAAAAAAAAnJycNKioo9FBDJv3bnR//3p8f/96f + H//enx//3p8f/96fH//EjiD/p3si/6d7Iv/EjiD/3p8f/96fH//enx//3p8f/96fH//bnR//UEMm/Soq + KPQnJycNAAAAAAAAAAAAAAACKSkoriopJ/2vgCH/3p8f/96fH//enx//rH4h/0o+J/8oKCj/KCgo/ygo + KP8oKCj/Sj4n/61/Iv/enx//3p8f/96fH/+vgCH/Kikn/SkpKK4AAAACAAAAAAAAAAAAAAAAKCgoPygo + KP+hdyL/3p8f/96fH/+OayP/KSko/1taWP+7u7v/6Ojo/+fn5/+6urr/W1pY/yopKf+OayP/3p8f/96f + H/+gdiL/KCgo/yoqKj0AAAAAAAAAAAAAAAAAAAAAKScnqUE5J/vcnh//3p8f/6x+If8pKSj/h4eH//7+ + /v///////////////////////f39/4aGhv8qKSn/rX8i/96fH//bnR//QDgn+ykoKKcAAAAAAAAAACsp + KKArKijzKSko/YNjI//enx//3p8f/0o/KP9bWlj//v7+/4R8av+JgnT/9/f3////////////oqKi//39 + /f9bWlj/Sj4n/96fH//enx//gmMj/ykpKP0rKijzKykooC0rKN5VRSb/jWoj/9GXIP/enx//w40g/ygo + KP+8vLz//////2VOH//IiAT/Vkcn/7WyrP//////ZmZm//////+7u7v/KCgo/8WPIf/enx//0Zcg/41q + I/9VRSb/LSso3isqKPWJaCT/3p8f/96fH//enx//pnoi/ygoKP/o6Oj//////2ZOH///qwD//KkA/5Zq + EP9/dmT/ZmZm///////n5+f/KCgo/6h8Iv/enx//3p8f/96fH/+JZyP/Kyoo9CspJ/aKaCT/3p8f/96f + H//enx//pXoh/ygoKP/p6en//////2ZOH///qwD//KkA/5ZqEP9/dmP/ZmZm///////n5+f/KCgo/6d7 + Iv/enx//3p8f/96fH/+JaCT/Kykn9i0rKN5VRSb/jWoj/9GXIP/enx//w40g/ygoKP+8vLz//////2ZP + H//IiAT/Vkcn/7WyrP//////ZmZm//////+6urr/KCgo/8SOIP/enx//0Zcg/41qI/9VRSb/LSso3isp + KKArKijzKSko/YNjI//enx//3p8f/0o/KP9cW1n//v7+/4N6af+IgXP/9/f3////////////oqKi//7+ + /v9bWlj/Sj8o/96fH//enx//g2Mj/ykpKP0rKijzKykooAAAAAAAAAAAKScnqUE5J/vcnh//3p8f/6t+ + If8pKSj/iYmJ//7+/v///////////////////////v7+/4eHh/8qKSn/rH4h/96fH//cnh//QTgn+yko + KKcAAAAAAAAAAAAAAAAAAAAAKCgoPygoKP+hdyL/3p8f/96fH/+MaSP/KSko/1xbWf+8vLz/6Ojo/+jo + 6P+8vLz/W1pY/ykpKP+OayP/3p8f/96fH/+gdiL/KCgo/ykpKT4AAAAAAAAAAAAAAAAAAAACKSkoriop + J/2vgCH/3p8f/96fH//enx//q34h/0o/KP8oKCj/KCgo/ygoKP8oKCj/Sj8o/6x+If/enx//3p8f/96f + H/+vgCH/Kikn/SkpKK4AAAACAAAAAAAAAAAnJycNKioo9FBDJv3bnR//3p8f/96fH//enx//3p8f/96f + H//CjSD/p3si/6d7Iv/DjSD/3p8f/96fH//enx//3p8f/96fH//bnR//UEMm/SoqKPQnJycNAAAAAAAA + AAAAAAAAKSkpSykpKP1zWST/250f/7CBIf+hdyL/3J4f/96fH//enx//3p8f/96fH//enx//3p8f/9ye + H/+gdiL/sIEh/9udH/9zWST/KSko/SkpKUsAAAAAAAAAAAAAAAAAAAAAAAAAACkpKWopKSj9UEMm/Sop + J/0oKCj/Qjkn+4NjI//RlyD/3p8f/96fH//RlyD/g2Mj/0E5J/soKCj/Kikn/VBDJv0pKSj9KSkpagAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApKSlLKioo8ykpKK4oKCg/KScnqCkoKP6OayP/3p8f/96f + H/+OayP/KSgo/iknJ6gpKSk+KSkorioqKPMpKSlLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAJycnDQAAAAIAAAAAAAAAACopKPhXRyb/imgk/4poJP9XRyb/Kiko+AAAAAAAAAAAAAAAAicn + Jw0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkp + KKEtLCjdKSkn9ykpJ/ctLCjdKSkooQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+B + /0H5gZ9B8AAPQeAAB0HAAANBgAABQYAAAUHAAANBwAADQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQcAA + A0HAAANBgAABQYAAAUHAAANB4AAHQfAAD0H5gZ9B/4H/QSgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyLifSLSsn9y0rJ/cyLifSAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMzMFMy4nlioqJ1UrKyhfLiwo+dyeH//cnh//Liwo+Ssr + KV4qKidVMy4nljMzMwUAAAAAAAAAAAAAAAAzMzMFMy8ox2RPJfU5Myj1YU0l87GCIf/enx//3p8f/7CB + If9hTSXyOTMo9WRPJfUzLyjHMzMzBQAAAAAAAAAAMy4nlWRPJfXenx//3p8f/96fH//cniD/vYkg/72J + IP/cniD/3p8f/96fH//enx//ZE8l9TMuJ5UAAAAAAAAAACoqJ1U5Myj13p8f/96fH/+ieCL/PTgt/1dS + Rv9XUUX/Pjgs/6N4Iv/enx//3p8f/zkzKPUqKidVAAAAAAAAAAArKyhfYk4l8t6fH/+jeCL/TUlB/9/f + 3////////////9/f3/9NSUD/o3gi/96fH/9hTSXyKyspXgAAAAAyLyjVLiwn+LCBIf/bnR//PTgt/9/f + 3/+Lelb/q6KS//7+/v+zs7P/3t7e/z03LP/cniD/sIEh/y4sJ/gyLijTLiwn9tyeH//enx//vIkg/1hT + Sf//////mXEf/9yVBf+GcEP/lJSU//////9XUUX/vYkg/96fH//cnh//Liwn9i4sJ/bcnh//3p8f/7yJ + IP9YU0r//////5lxH//clQX/hnBD/5SUlP//////V1FG/72JIP/enx//3J4f/y4sJ/YyLyjVLiwn+LCB + If/bnR//PTgu/+Dg4P+Lelb/q6KS//7+/v+zs7P/39/f/z04Lf/cniD/sIEh/y4sJ/gyLijTAAAAACsr + KGBiTiXy3p8f/6F3Iv9OSkP/4ODg////////////39/f/01JQf+jeCL/3p8f/2FNJfMrKyhfAAAAAAAA + AAAqKidVOTMo9d6fH//enx//ongi/z04Lv9YU0r/V1NI/z04Lf+ieCL/3p8f/96fH/85Myj1KionVQAA + AAAAAAAAMy4nlWRPJfXenx//3p8f/96fH//cniD/vYkg/72JIP/cniD/3p8f/96fH//enx//ZE8l9TMu + J5UAAAAAAAAAADMzMwUzLyjHZE8l9TkzKPViTiXysYIh/96fH//enx//sYIh/2FNJfM5Myj1ZE8l9TMv + KMczMzMFAAAAAAAAAAAAAAAAMzMzBTMuJ5YqKidVKysoYC4sKPncnh//3J4f/y4sKPkrKyhfKionVTMu + J5YzMzMFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyLifSLSsn9y0rJ/cyLifSAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/D+sQcADrEGAAaxBgAGsQYABrEGAAaxBAACsQQAArEEAAKxBAACsQYAB + rEGAAaxBgAGsQYABrEHAA6xB/D+sQQ== + + + + 92 + + + + AAABAAQAMDAAAAEAIACoJQAARgAAACAgAAABACAAqBAAAO4lAAAYGAAAAQAgAIgJAACWNgAAEBAAAAEA + IABoBAAAHkAAACgAAAAwAAAAYAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAlJSUpKCgojCkpKbYoKCjYKCgo7CgoKPkoKCj5KCgo7CgoKNgpKSm2KCgojCUlJSkAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAoKCjVKCgo/ygoKP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygo + KNUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoKCjtKCgo/ygoKP8sKyj/OzQn/0M6J/9DOif/OzQn/ywr + KP8oKCj/KCgo/ygoKO0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAMzMzBSgoKDogICAIAAAAAAAAAAAAAAAAAAAAAAAAAAAoKCjtKCgo/zs0J//bnR//3p8f/96f + H//enx//3p8f/9udH/87NCf/KCgo/ygoKO0AAAAAAAAAAAAAAAAAAAAAAAAAACAgIAgoKCg6MzMzBQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAkJCQjKCgozCgoKP8oKCjNKCgoEwAAAAAAAAAAKSkpJSgoKHgoKCj5KCgo/zw1 + J//enx//3p8f/96fH//enx//3p8f/96fH/88NSf/KCgo/ygoKPkoKCh4KSkpJQAAAAAAAAAAKCgoEygo + KM0oKCj/KCgozCQkJCMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAACkpKUsoKCjxKCgo/ygoKP8oKCj/JycnzykpKUQnJye1KCgo/ygo + KP8oKCj/KCgo/0M6J//enx//3p8f/96fH//enx//3p8f/96fH/9DOif/KCgo/ygoKP8oKCj/KCgo/ygo + KLQpKSlEJycnzygoKP8oKCj/KCgo/ygoKPApKSlLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCgoXygoKPsoKCj/KCgo/ygoKP8oKCj/KCgo/ygo + KP8oKCj/KCgo/ygoKP8oKCj/Rjsm/6h8Iv/enx//3p8f/96fH//enx//3p8f/96fH/+ofCL/Rjsm/ygo + KP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKP8oKCj7KSkpXgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoKChfKCgo/igoKP8oKCj/XEol/7CB + If82MSf/KCgo/ygoKP8oKCj/OjQn/4VlJP/AiyD/3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/8CMIf+EZCT/OjQn/ygoKP8oKCj/KCgo/zYxJ/+vgCH/XEol/ygoKP8oKCj/KCgo/ikp + KV4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkpKUsoKCj7KCgo/ygo + KP9sVCX/3J4g/96fH/+8iSD/PDUn/zo0J/+NaiP/15of/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//15of/41qI/86NCf/PDUn/7yJIP/enx//3J4g/2xU + Jf8oKCj/KCgo/ygoKPspKSlLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJCQkIygo + KPAoKCj/KCgo/2xUJf/dnh//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/92eH/9sVCX/KCgo/ygoKP8oKCjwJCQkIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABAQEAEKCgozCgoKP8oKCj/XEol/9yeIP/enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//cniD/XEol/ygoKP8oKCj/KCgozEBAQAQAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAqKio3KCgo/ygoKP8oKCj/sIEh/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/8ONIP+QbCP/eFwk/2hSJf9oUiX/eV0k/5BsI//DjSD/3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//sIEh/ygoKP8oKCj/KCgo/yoq + KjcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAIKCgozigoKP8oKCj/NjEn/7yJIP/enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/9yeIP+UbyL/RTsn/ygoKP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygo + KP8oKCj/Rjwn/5VvI//cniD/3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH/+8iSD/NjEn/ygo + KP8oKCj/KCgoziAgIAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCgoEycnJ88oKCj/KCgo/z42 + J//dnh//3p8f/96fH//enx//3p8f/96fH//enx//tIMh/0U7J/8oKCj/KCgo/ygoKP8oKCj/KCgo/ygo + KP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKP9GPCf/tYQh/96fH//enx//3p8f/96fH//enx//3p8f/92e + H/8+Nif/KCgo/ygoKP8nJyfPKCgoEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkp + KUQoKCj/KCgo/zkzJ//dnh//3p8f/96fH//enx//3p8f/96fH/+YcSL/LCso/ygoKP8oKCj/KCgo/1VV + Vf+YmJj/xMTE/9vb2//b29v/xMTE/5eXl/9UVFT/KCgo/ygoKP8oKCj/LSso/5lyIv/enx//3p8f/96f + H//enx//3p8f/92eH/85Myf/KCgo/ygoKP8pKSlEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAACcnJ7UoKCj/KCgo/41qI//enx//3p8f/96fH//enx//3p8f/5hxIv8oKCj/KCgo/ygo + KP9TU1P/ycnJ////////////////////////////////////////////x8fH/1FRUf8oKCj/KCgo/ygo + KP+ZciL/3p8f/96fH//enx//3p8f/96fH/+NaiP/KCgo/ygoKP8nJye1AAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAKCgoJigoKP8oKCj/OjQn/9eaH//enx//3p8f/96fH//enx//tIMh/ywr + KP8oKCj/KCgo/3t7e//6+vr///////////////////////////////////////////////////////n5 + +f95eXn/KCgo/ygoKP8tKyj/tYQh/96fH//enx//3p8f/96fH//XmyD/OTMn/ygoKP8oKCj/KSkpJQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCgoeCgoKP8oKCj/hWUk/96fH//enx//3p8f/96f + H//cniD/RDon/ygoKP8oKCj/e3t7//////////////////////////////////////////////////// + ////////////////////////eXl5/ygoKP8oKCj/Rjwn/9yeIP/enx//3p8f/96fH//enx//hGQk/ygo + KP8oKCj/KCgoeAAAAAAAAAAAAAAAAAAAAAAlJSUpKSkp1igoKO4oKCjuKCgo+SgoKP8oKCj/wIsg/96f + H//enx//3p8f/96fH/+TbiL/KCgo/ygoKP9TU1P/+vr6///////39/f/sLCw/87Ozv////////////// + ////////////////////////+vr6/7W1tf//////+fn5/1BQUP8oKCj/KCgo/5VvI//enx//3p8f/96f + H//enx//wIwh/ygoKP8oKCj/KCgo+SgoKO4oKCjuKSkp1iUlJSkoKCiOKCgo/ygoKP8oKCj/KCgo/ygo + KP9GPCb/3p8f/96fH//enx//3p8f/96fH/9EOif/KCgo/ygoKP/Kysr///////////9VU07/FhEH/wYF + A/9RT0z/4ODg////////////////////////////zc3N/wEBAf///////////8fHx/8oKCj/KCgo/0Y8 + J//enx//3p8f/96fH//enx//3p8f/0Y7Jv8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKI4nJye1KCgo/ygo + KP8/Nyf/QTgn/0Y8J/+pfCL/3p8f/96fH//enx//3p8f/8GMIP8oKCj/KCgo/1ZWVv////////////// + //8GBQT/xYQA/9mSAP9HMgb/CgkG/4SEg//4+Pj/////////////////y8vL/wAAAP////////////// + //9UVFT/KCgo/ygoKP/DjSD/3p8f/96fH//enx//3p8f/6l8Iv9GPCf/QTgn/z42J/8oKCj/KCgo/ycn + J7UoKCjaKCgo/y0rKP/bnR//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/45rI/8oKCj/KCgo/5mZ + mf////////////////8AAAD/y4gA//+rAP//qwD/sncA/yAYB/8kIRz/tbW1////////////y8vL/wAA + AP////////////////+Xl5f/KCgo/ygoKP+QbCP/3p8f/96fH//enx//3p8f/96fH//enx//3p8f/9ud + H/8sKyj/KCgo/ygoKNkoKCjsKCgo/zs0J//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/3ld + JP8oKCj/KCgo/8bGxv////////////////8AAAD/y4gA//+rAP//qwD//6sA//WkAP96UgH/BwYD/1ZU + T//39/f/y8vL/wAAAP/////////////////Dw8P/KCgo/ygoKP97XiT/3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH/86NCf/KCgo/ygoKOooKCj5KCgo/0Q6J//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/2dRJf8oKCj/KCgo/9vb2/////////////////8AAAD/y4gA//+rAP//qwD//6sA//+r + AP//qwD/2ZIA/ygdCP+IiIj/y8vL/wAAAP/////////////////a2tr/KCgo/ygoKP9oUiX/3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH/9EOif/KCgo/ygoKPgoKCj5KCgo/0Q6J//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/2ZQJf8oKCj/KCgo/9zc3P////////////////8AAAD/y4gA//+r + AP//qwD//6sA//+rAP//qwD/2ZIA/ygdCP+IiIj/y8vL/wAAAP/////////////////b29v/KCgo/ygo + KP9nUSX/3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH/9EOif/KCgo/ygoKPgoKCjsKCgo/zs0 + J//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/3hcJP8oKCj/KCgo/8fHx/////////////// + //8AAAD/y4gA//+rAP//qwD//6sA//WkAP96UgH/BwYD/1ZUT//39/f/y8vL/wAAAP////////////// + ///ExMT/KCgo/ygoKP96XiT/3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH/86NCf/KCgo/ygo + KOooKCjaKCgo/y0rKP/bnR//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/45rI/8oKCj/KCgo/5qa + mv////////////////8AAAD/y4gA//+rAP//qwD/sncA/yAYB/8kIRz/tbW1////////////y8vL/wAA + AP////////////////+Xl5f/KCgo/ygoKP+QbCP/3p8f/96fH//enx//3p8f/96fH//enx//3p8f/9ud + H/8sKyj/KCgo/ygoKNknJye1KCgo/ygoKP8/Nyf/QTgn/0Y8J/+pfCL/3p8f/96fH//enx//3p8f/8CL + IP8oKCj/KCgo/1ZWVv////////////////8GBQT/xYQA/9mSAP9HMgb/CgkG/4WFhP/4+Pj///////// + ////////y8vL/wAAAP////////////////9VVVX/KCgo/ygoKP/CjSD/3p8f/96fH//enx//3p8f/6l8 + Iv9GPCf/QTgn/z42J/8oKCj/KCgo/ycnJ7UoKCiOKCgo/ygoKP8oKCj/KCgo/ygoKP9GPCb/3p8f/96f + H//enx//3p8f/96fH/9DOif/KCgo/ygoKP/Ly8v///////////9UUk3/GBIH/wYFA/9SUE3/4ODg//// + ////////////////////////zc3N/wEBAf///////////8nJyf8oKCj/KCgo/0U7J//enx//3p8f/96f + H//enx//3p8f/0Y8Jv8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKI4lJSUpKSkp1igoKO4oKCjuKCgo+Sgo + KP8oKCj/wIsg/96fH//enx//3p8f/96fH/+TbiL/KCgo/ygoKP9VVVX/+/v7///////39/f/rq6u/83N + zf//////////////////////////////////////+vr6/7W1tf//////+vr6/1JSUv8oKCj/KCgo/5Rv + Iv/enx//3p8f/96fH//enx//wIsg/ygoKP8oKCj/KCgo+SgoKO4oKCjuKSkp1iUlJSkAAAAAAAAAAAAA + AAAAAAAAKCgoeSgoKP8oKCj/hWUj/96fH//enx//3p8f/96fH//bnR//Qzon/ygoKP8oKCj/fX19//// + ////////////////////////////////////////////////////////////////////////e3t7/ygo + KP8oKCj/RDon/9yeIP/enx//3p8f/96fH//enx//hWUk/ygoKP8oKCj/KCgoeAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAKCgoJigoKP8oKCj/OzQn/9eaH//enx//3p8f/96fH//enx//s4Mi/ywr + KP8oKCj/KCgo/319ff/6+vr///////////////////////////////////////////////////////r6 + +v97e3v/KCgo/ygoKP8sKyj/tIMh/96fH//enx//3p8f/96fH//Xmh//OjQn/ygoKP8oKCj/KSkpJQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkpKbYoKCj/KCgo/45rI//enx//3p8f/96f + H//enx//3p8f/5dxI/8oKCj/KCgo/ygoKP9UVFT/y8vL//////////////////////////////////// + ////////ycnJ/1NTU/8oKCj/KCgo/ygoKP+YcSL/3p8f/96fH//enx//3p8f/96fH/+NaiP/KCgo/ygo + KP8nJye1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkpKUQoKCj/KCgo/zkz + J//dnh//3p8f/96fH//enx//3p8f/96fH/+XcSP/LCso/ygoKP8oKCj/KCgo/1ZWVv+ampr/xsbG/9vb + 2//b29v/xsbG/5mZmf9WVlb/KCgo/ygoKP8oKCj/LCso/5hxIv/enx//3p8f/96fH//enx//3p8f/92e + H/85Myf/KCgo/ygoKP8pKSlEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCgoEycn + J88oKCj/KCgo/z42J//dnh//3p8f/96fH//enx//3p8f/96fH//enx//s4Mi/0I5Jv8oKCj/KCgo/ygo + KP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKP9EOif/tIMh/96fH//enx//3p8f/96f + H//enx//3p8f/92eH/8+Nif/KCgo/ygoKP8nJyfPKCgoEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAgICAIKCgozigoKP8oKCj/NjEn/7yJIP/enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/9ud + H/+TbiL/Qzon/ygoKP8oKCj/KCgo/ygoKP8oKCj/KCgo/ygoKP8oKCj/RDon/5NuIv/cniD/3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH/+8iSD/NjEn/ygoKP8oKCj/KCgoziAgIAgAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAqKio3KCgo/ygoKP8oKCj/sIEh/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/8GMIP+PayP/eFwk/2hSJf9oUiX/eFwk/49rI//BjCD/3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//sIEh/ygoKP8oKCj/KCgo/yoq + KjcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEAEKCgozCgoKP8oKCj/XUsl/9yeIP/enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//cniD/XEol/ygo + KP8oKCj/KCgozEBAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJCQkIygoKPEoKCj/KCgo/2xU + Jf/dnh//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/92e + H/9sVCX/KCgo/ygoKP8oKCjwJCQkIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgo + KEwoKCj7KCgo/ygoKP9sVCX/3J4g/96fH/+8iSD/PDUn/zo0J/+OayP/15of/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//15of/41qI/86NCf/PDUn/7yJ + IP/enx//3J4g/2xUJf8oKCj/KCgo/ygoKPspKSlLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAoKChfKCgo/igoKP8oKCj/XUsl/7CBIf82MSf/KCgo/ygoKP8oKCj/OzQn/4Vl + I//AiyD/3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/8CLIP+FZST/OjQn/ygo + KP8oKCj/KCgo/zYxJ/+wgSH/XEol/ygoKP8oKCj/KCgo/igoKF8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCgoXygoKPsoKCj/KCgo/ygoKP8oKCj/KCgo/ygo + KP8oKCj/KCgo/ygoKP8oKCj/Rjsm/6h8Iv/enx//3p8f/96fH//enx//3p8f/96fH/+ofCL/Rjsm/ygo + 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 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoKCjxKCgo/y4sKP84Myj/ODMo/y4sKP8oKCj/KCgo8QAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAACAgIAgpKSlqJycnJwAAAAAAAAAAAAAAAygoKPQ0MCf/3Z4f/96fH//enx//3Z4f/zQw + J/8oKCj0AAAAAwAAAAAAAAAAJycnJykpKWogICAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAmJiYiJycnzygoKP8pKCjrJycnQigoKIwoKCjpKCgo/zgyJ//enx//3p8f/96f + H//enx//ODIn/ygoKP8oKCjpKCgojCcnJ0IpKCjrKCgo/ycnJ88nJychAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAKCgoLSkoKOcoKCj/Pzcn/ygoKP8oKCj/KCgo/ysqKP9bSSb/qXwi/96f + H//enx//3p8f/96fH/+pfCL/Wkkm/ysqKP8oKCj/KCgo/ygoKP8+Nif/KCgo/ykoKOcoKCgtAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAACcnJyEpKCjnKCgo/3JYJf/bnR//el4k/zAtJ/96XiT/zpQf/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//zpQf/3peJP8wLSf/el4k/9yeIP9xWCT/KCgo/ygo + KOcnJychAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAIKCgozigoKP9xWCT/3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H/91WiT/KCgo/ygoKNIcHBwJAAAAAAAAAAAAAAAAAAAAACgoKGwoKCj/PjYn/9udH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//0pcg/6Z6Iv+QbCP/kGwj/6Z6Iv/SlyD/3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/9yeIP8+Nif/KCgo/ygoKGwAAAAAAAAAAAAAAAAAAAAAKCgoJikoKOsoKCj/eFwk/96f + H//enx//3p8f/96fH//enx//wIwh/2FNJf8qKij/KCgo/ygoKP8oKCj/KCgo/yoqKP9iTiX/wIsg/96f + H//enx//3p8f/96fH//enx//eFwk/ygoKP8pKCjrKCgoJgAAAAAAAAAAAAAAAAAAAAAAAAAAKioqQygo + KP8yLyj/3Z4f/96fH//enx//3p8f/5dxI/8sKyj/KCgo/zw8PP97e3v/nJyc/5ycnP97e3v/Ozs7/ygo + KP8sKyj/mHEj/96fH//enx//3p8f/92eH/8yLyj/KCgo/ycnJ0IAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAoKCiOKCgo/3teJP/enx//3p8f/96fH/+XcSP/KCgo/y0tLP+dnZ3/+vr6//////////////////// + ///5+fn/nJyc/y0tLP8oKCj/mHEj/96fH//enx//3p8f/3peJP8oKCj/KCgojAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAygoKOksKij/z5Uf/96fH//enx//wIsh/ywrKP8tLSz/yMjI//////////////////// + ////////////////////////x8fH/y0tLP8sKyj/wIsg/96fH//enx//zpQf/ysqKP8oKCjoAAAAAwAA + AAAAAAAAKCgodCgoKO4oKCjwKCgo/1tJJv/enx//3p8f/96fH/9hTSX/KCgo/56env//////s7Ku/397 + cv/p6en//////////////////////5mZmf//////nJyc/ygoKP9iTiX/3p8f/96fH//enx//W0km/ygo + KP8oKCjwKCgo7igoKHQoKCjIKCgo/zMvJ/83Mij/qXwh/96fH//enx//0Zcg/ysqKP88PDz/+vr6//// + //8tJRX/pnED/zAnFf+TkIv//Pz8////////////NDQ0///////5+fn/PDw8/ysqKP/SlyD/3p8f/96f + H/+pfCH/NzIo/zMvJ/8oKCj/KCgoxygoKOouLCj/3J4f/96fH//enx//3p8f/96fH/+leiL/KCgo/319 + ff///////////zQqFf//qwD/9qUA/39ZDP84MSP/xMTD//////80NDT///////////97e3v/KCgo/6Z6 + Iv/enx//3p8f/96fH//enx//3J4f/y0rKP8oKCjpKCgo+TgyJ//enx//3p8f/96fH//enx//3p8f/5Ft + I/8oKCj/nJyc////////////NCoV//+rAP//qwD//6sA/9qSAP8+MBL/yMjI/zQ0NP///////////5ub + m/8oKCj/k24j/96fH//enx//3p8f/96fH//enx//ODMo/ygoKPgoKCj5ODIn/96fH//enx//3p8f/96f + H//enx//kGwj/ygoKP+dnZ3///////////80KhX//6sA//+rAP//qwD/25MA/z4wEv/Hx8f/NDQ0//// + ////////nJyc/ygoKP+RbSP/3p8f/96fH//enx//3p8f/96fH/84Mif/KCgo+CgoKOouLCj/3J4f/96f + H//enx//3p8f/96fH/+keSL/KCgo/319ff///////////zQqFf//qwD/9qUA/39ZDP83MCP/xMTD//// + //80NDT///////////97e3v/KCgo/6V6If/enx//3p8f/96fH//enx//3J4f/y0rKP8oKCjpKCgoyCgo + KP8zLyf/NzIo/6l8If/enx//3p8f/9CWIP8rKij/PT09//r6+v//////LSUV/6ZxA/8wJxX/k5CL//z8 + /P///////////zQ0NP//////+vr6/zw8PP8qKij/0Zcg/96fH//enx//qXwh/zcyKP8zLyf/KCgo/ygo + KMcoKCh0KCgo7igoKPAoKCj/W0km/96fH//enx//3p8f/2FNJv8oKCj/oKCg//////+ysKz/f3ty/+np + 6f//////////////////////mZmZ//////+enp7/KCgo/2FNJf/enx//3p8f/96fH/9bSSb/KCgo/ygo + KPAoKCjuKCgodAAAAAAAAAAAAAAAAygoKOosKij/z5Uf/96fH//enx//v4sh/ysqKP8uLi3/yMjI//// + ////////////////////////////////////////yMjI/y0tLP8sKyj/wIsg/96fH//enx//zpQf/ysq + KP8oKCjpAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAKCgojigoKP97XiT/3p8f/96fH//enx//lnAj/ygo + KP8uLi3/oKCg//r6+v//////////////////////+vr6/5+fn/8uLi3/KCgo/5dxI//enx//3p8f/96f + H/97XiT/KCgo/ygoKI0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqKipDKCgo/zIvKP/dnh//3p8f/96f + H//enx//lnAj/ysqKP8oKCj/PT09/3x8fP+dnZ3/nZ2d/3x8fP88PDz/KCgo/ywrKP+XcSP/3p8f/96f + H//enx//3Z4f/zIvKP8oKCj/JycnQgAAAAAAAAAAAAAAAAAAAAAAAAAAKCgoJikoKOsoKCj/eFwk/96f + H//enx//3p8f/96fH//enx//wIsh/2FNJv8rKij/KCgo/ygoKP8oKCj/KCgo/ysqKP9hTSX/wIwh/96f + H//enx//3p8f/96fH//enx//eFwk/ygoKP8pKCjrKCgoJgAAAAAAAAAAAAAAAAAAAAAoKChtKCgo/z83 + J//bnR//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/9CWIP+leiL/kGwj/5BsI/+leiL/0Zcg/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//cniD/PjYn/ygoKP8oKChtAAAAAAAAAAAAAAAAAAAAACAg + IAgoKCjOKCgo/3JYJf/enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//3p8f/96fH//enx//3p8f/3dcJP8oKCj/KCgo0hwcHAkAAAAAAAAAAAAA + AAAAAAAAAAAAACYmJiIpKCjnKCgo/3JYJf/bnR//el4k/zAtJ/97XiT/z5Uf/96fH//enx//3p8f/96f + H//enx//3p8f/96fH//enx//z5Uf/3teJP8wLSf/el4k/9yeIP9xWCT/KCgo/ykoKOcmJiYiAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAACgoKC0pKCjoKCgo/z83J/8oKCj/KCgo/ygoKP8sKij/W0km/6l8 + Iv/enx//3p8f/96fH//enx//qXwi/1tJJv8sKij/KCgo/ygoKP8oKCj/PjYn/ygoKP8pKCjnKCgoLQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYmJiIoKCjQKCgo/ykoKOsqKipDKCgojigo + KOooKCj/ODIn/96fH//enx//3p8f/96fH/84Mif/KCgo/ygoKOooKCiOKioqQykoKOsoKCj/KCgo0CYm + JiIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAgIAgpKSlqJycnJwAA + AAAAAAAAAAAAAygoKPQ0MCf/3Z4f/96fH//enx//3Z4f/zQwJ/8oKCj0AAAAAwAAAAAAAAAAJycnJykp + KWogICAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAKCgo8SgoKP8uLCj/ODIn/zgyJ/8uLCj/KCgo/ygoKPEAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJyd1KCgoyCgoKOooKCj5KCgo+SgoKOkoKCjIJycndQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/wD///8A///GAGP/gA + AB/wAAAP4AAAB8AAAAPAAAADwAAAA+AAAAfgAAAHwAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAwAAAA+AAAAfgAAAHwAAAA8AAAAPAAAAD4AAAB/AAAA/4AAAf/GAGP//wD///8A//KAAAABgA + AAAwAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAACkpKKEtLCjdKSkn9ykpJ/ctLCjdKSkooQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJycnDQAAAAIAAAAAAAAAACopKPhXRyb/imgk/4po + JP9XRyb/Kiko+AAAAAAAAAAAAAAAAicnJw0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAApKSlLKioo8ykpKK4pKSk+KSgopykoKP6OayP/3p8f/96fH/+OayP/KSgo/ikoKKcqKio9KSkorioq + KPMpKSlLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkpKWopKSj9UEMm/SopJ/0oKCj/QTgn+4Nj + I//RlyD/3p8f/96fH//RlyD/g2Mj/0E4J/soKCj/Kikn/VBDJv0pKSj9KSkpagAAAAAAAAAAAAAAAAAA + AAAAAAAAKSkpSykpKP1zWST/250f/7CBIf+gdiL/3J4f/96fH//enx//3p8f/96fH//enx//3p8f/9ye + H/+gdiL/sIEh/9udH/9zWST/KSko/SkpKUsAAAAAAAAAAAAAAAAnJycNKioo9FBDJv3bnR//3p8f/96f + H//enx//3p8f/96fH//EjiD/p3si/6d7Iv/EjiD/3p8f/96fH//enx//3p8f/96fH//bnR//UEMm/Soq + KPQnJycNAAAAAAAAAAAAAAACKSkoriopJ/2vgCH/3p8f/96fH//enx//rH4h/0o+J/8oKCj/KCgo/ygo + KP8oKCj/Sj4n/61/Iv/enx//3p8f/96fH/+vgCH/Kikn/SkpKK4AAAACAAAAAAAAAAAAAAAAKCgoPygo + KP+hdyL/3p8f/96fH/+OayP/KSko/1taWP+7u7v/6Ojo/+fn5/+6urr/W1pY/yopKf+OayP/3p8f/96f + H/+gdiL/KCgo/yoqKj0AAAAAAAAAAAAAAAAAAAAAKScnqUE5J/vcnh//3p8f/6x+If8pKSj/h4eH//7+ + /v///////////////////////f39/4aGhv8qKSn/rX8i/96fH//bnR//QDgn+ykoKKcAAAAAAAAAACsp + KKArKijzKSko/YNjI//enx//3p8f/0o/KP9bWlj//v7+/4R8av+JgnT/9/f3////////////oqKi//39 + /f9bWlj/Sj4n/96fH//enx//gmMj/ykpKP0rKijzKykooC0rKN5VRSb/jWoj/9GXIP/enx//w40g/ygo + KP+8vLz//////2VOH//IiAT/Vkcn/7WyrP//////ZmZm//////+7u7v/KCgo/8WPIf/enx//0Zcg/41q + I/9VRSb/LSso3isqKPWJaCT/3p8f/96fH//enx//pnoi/ygoKP/o6Oj//////2ZOH///qwD//KkA/5Zq + EP9/dmT/ZmZm///////n5+f/KCgo/6h8Iv/enx//3p8f/96fH/+JZyP/Kyoo9CspJ/aKaCT/3p8f/96f + H//enx//pXoh/ygoKP/p6en//////2ZOH///qwD//KkA/5ZqEP9/dmP/ZmZm///////n5+f/KCgo/6d7 + Iv/enx//3p8f/96fH/+JaCT/Kykn9i0rKN5VRSb/jWoj/9GXIP/enx//w40g/ygoKP+8vLz//////2ZP + H//IiAT/Vkcn/7WyrP//////ZmZm//////+6urr/KCgo/8SOIP/enx//0Zcg/41qI/9VRSb/LSso3isp + KKArKijzKSko/YNjI//enx//3p8f/0o/KP9cW1n//v7+/4N6af+IgXP/9/f3////////////oqKi//7+ + /v9bWlj/Sj8o/96fH//enx//g2Mj/ykpKP0rKijzKykooAAAAAAAAAAAKScnqUE5J/vcnh//3p8f/6t+ + If8pKSj/iYmJ//7+/v///////////////////////v7+/4eHh/8qKSn/rH4h/96fH//cnh//QTgn+yko + KKcAAAAAAAAAAAAAAAAAAAAAKCgoPygoKP+hdyL/3p8f/96fH/+MaSP/KSko/1xbWf+8vLz/6Ojo/+jo + 6P+8vLz/W1pY/ykpKP+OayP/3p8f/96fH/+gdiL/KCgo/ykpKT4AAAAAAAAAAAAAAAAAAAACKSkoriop + J/2vgCH/3p8f/96fH//enx//q34h/0o/KP8oKCj/KCgo/ygoKP8oKCj/Sj8o/6x+If/enx//3p8f/96f + H/+vgCH/Kikn/SkpKK4AAAACAAAAAAAAAAAnJycNKioo9FBDJv3bnR//3p8f/96fH//enx//3p8f/96f + H//CjSD/p3si/6d7Iv/DjSD/3p8f/96fH//enx//3p8f/96fH//bnR//UEMm/SoqKPQnJycNAAAAAAAA + AAAAAAAAKSkpSykpKP1zWST/250f/7CBIf+hdyL/3J4f/96fH//enx//3p8f/96fH//enx//3p8f/9ye + H/+gdiL/sIEh/9udH/9zWST/KSko/SkpKUsAAAAAAAAAAAAAAAAAAAAAAAAAACkpKWopKSj9UEMm/Sop + J/0oKCj/Qjkn+4NjI//RlyD/3p8f/96fH//RlyD/g2Mj/0E5J/soKCj/Kikn/VBDJv0pKSj9KSkpagAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApKSlLKioo8ykpKK4oKCg/KScnqCkoKP6OayP/3p8f/96f + H/+OayP/KSgo/iknJ6gpKSk+KSkorioqKPMpKSlLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAJycnDQAAAAIAAAAAAAAAACopKPhXRyb/imgk/4poJP9XRyb/Kiko+AAAAAAAAAAAAAAAAicn + Jw0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkp + KKEtLCjdKSkn9ykpJ/ctLCjdKSkooQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+B + /0H5gZ9B8AAPQeAAB0HAAANBgAABQYAAAUHAAANBwAADQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQcAA + A0HAAANBgAABQYAAAUHAAANB4AAHQfAAD0H5gZ9B/4H/QSgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyLifSLSsn9y0rJ/cyLifSAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMzMFMy4nlioqJ1UrKyhfLiwo+dyeH//cnh//Liwo+Ssr + KV4qKidVMy4nljMzMwUAAAAAAAAAAAAAAAAzMzMFMy8ox2RPJfU5Myj1YU0l87GCIf/enx//3p8f/7CB + If9hTSXyOTMo9WRPJfUzLyjHMzMzBQAAAAAAAAAAMy4nlWRPJfXenx//3p8f/96fH//cniD/vYkg/72J + IP/cniD/3p8f/96fH//enx//ZE8l9TMuJ5UAAAAAAAAAACoqJ1U5Myj13p8f/96fH/+ieCL/PTgt/1dS + Rv9XUUX/Pjgs/6N4Iv/enx//3p8f/zkzKPUqKidVAAAAAAAAAAArKyhfYk4l8t6fH/+jeCL/TUlB/9/f + 3////////////9/f3/9NSUD/o3gi/96fH/9hTSXyKyspXgAAAAAyLyjVLiwn+LCBIf/bnR//PTgt/9/f + 3/+Lelb/q6KS//7+/v+zs7P/3t7e/z03LP/cniD/sIEh/y4sJ/gyLijTLiwn9tyeH//enx//vIkg/1hT + Sf//////mXEf/9yVBf+GcEP/lJSU//////9XUUX/vYkg/96fH//cnh//Liwn9i4sJ/bcnh//3p8f/7yJ + IP9YU0r//////5lxH//clQX/hnBD/5SUlP//////V1FG/72JIP/enx//3J4f/y4sJ/YyLyjVLiwn+LCB + If/bnR//PTgu/+Dg4P+Lelb/q6KS//7+/v+zs7P/39/f/z04Lf/cniD/sIEh/y4sJ/gyLijTAAAAACsr + KGBiTiXy3p8f/6F3Iv9OSkP/4ODg////////////39/f/01JQf+jeCL/3p8f/2FNJfMrKyhfAAAAAAAA + AAAqKidVOTMo9d6fH//enx//ongi/z04Lv9YU0r/V1NI/z04Lf+ieCL/3p8f/96fH/85Myj1KionVQAA + AAAAAAAAMy4nlWRPJfXenx//3p8f/96fH//cniD/vYkg/72JIP/cniD/3p8f/96fH//enx//ZE8l9TMu + J5UAAAAAAAAAADMzMwUzLyjHZE8l9TkzKPViTiXysYIh/96fH//enx//sYIh/2FNJfM5Myj1ZE8l9TMv + KMczMzMFAAAAAAAAAAAAAAAAMzMzBTMuJ5YqKidVKysoYC4sKPncnh//3J4f/y4sKPkrKyhfKionVTMu + J5YzMzMFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyLifSLSsn9y0rJ/cyLifSAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/D+sQcADrEGAAaxBgAGsQYABrEGAAaxBAACsQQAArEEAAKxBAACsQYAB + rEGAAaxBgAGsQYABrEHAA6xB/D+sQQ== + + + \ No newline at end of file diff --git a/source/Program.cs b/source/Program.cs new file mode 100644 index 0000000..991b74b --- /dev/null +++ b/source/Program.cs @@ -0,0 +1,22 @@ +using RyzStudio.IO; +using System; +using System.Windows.Forms; + +namespace CursorGuardRail +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.SetHighDpiMode(HighDpiMode.PerMonitorV2); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + Application.Run(new MainForm()); + } + } +} diff --git a/source/Resources/folder-minus.png b/source/Resources/folder-minus.png new file mode 100644 index 0000000..655cfd8 Binary files /dev/null and b/source/Resources/folder-minus.png differ diff --git a/source/Resources/help-circle.png b/source/Resources/help-circle.png new file mode 100644 index 0000000..fa87ded Binary files /dev/null and b/source/Resources/help-circle.png differ diff --git a/source/Resources/icon_64.png b/source/Resources/icon_64.png new file mode 100644 index 0000000..6c68993 Binary files /dev/null and b/source/Resources/icon_64.png differ diff --git a/source/Resources/refresh-cw.png b/source/Resources/refresh-cw.png new file mode 100644 index 0000000..0a16a9d Binary files /dev/null and b/source/Resources/refresh-cw.png differ diff --git a/source/Resources/save.png b/source/Resources/save.png new file mode 100644 index 0000000..72dfc90 Binary files /dev/null and b/source/Resources/save.png differ diff --git a/source/Resources/settings.png b/source/Resources/settings.png new file mode 100644 index 0000000..e4e4b3a Binary files /dev/null and b/source/Resources/settings.png differ diff --git a/source/Windows/Forms/ScreensLayout.cs b/source/Windows/Forms/ScreensLayout.cs new file mode 100644 index 0000000..4858d9f --- /dev/null +++ b/source/Windows/Forms/ScreensLayout.cs @@ -0,0 +1,219 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using CursorGuardRail.Dtos; +using RyzStudio.Drawing; + +namespace CursorGuardRail.Windows.Forms +{ + public class ScreensLayout : RyzStudio.Windows.ThemedForms.T3UserControl + { + private readonly Pen screenBorderColour = new Pen(Color.Black, 2f); + private readonly Brush screenBackColour = new SolidBrush(Color.FromArgb(218, 218, 218)); + private readonly Brush selectedScreenBackColour = new SolidBrush(Color.FromArgb(0, 120, 215)); + private readonly Pen selectedAreaBorderColour = new Pen(Color.FromArgb(254, 135, 0), 2f) + { + DashStyle = System.Drawing.Drawing2D.DashStyle.Dot + }; + + + public ScreensLayout() + { + this.Font = new Font(this.Font.FontFamily, 20f, FontStyle.Regular); + } + + + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + + var g = e.Graphics; + + for (var i=0; i x.IsSelected)) + { + var area = CalcMaxBound(this.Screens.Where(x => x.IsSelected).Select(x => x.Bound).ToList()); + + g.DrawRectangle(selectedAreaBorderColour, area); + } + + g.Flush(); + } + + protected override void OnMouseDown(MouseEventArgs e) + { + base.OnMouseDown(e); + + if (e.Button == MouseButtons.Left) + { + for (var i = 0; i < this.Screens.Count; i++) + { + if (this.Screens[i].Bound.Contains(e.Location)) + { + this.Screens[i].IsSelected = !this.Screens[i].IsSelected; + break; + } + } + } + } + + protected override void OnResize(EventArgs e) + { + base.OnResize(e); + + this.InvalidateScreens(); + } + + + protected override void UpdateBackground() + { + if (base.ClientRectangle.Width <= 0 || base.ClientRectangle.Height <= 0) + { + return; + } + + var backColour = Color.FromArgb(242, 242, 242); + var backgroundImage = new Rectangoid(base.ClientRectangle, CurrentStyle.Border.Radius, CurrentStyle.Border.Width).ToBitmap(new Pen(new SolidBrush(CurrentStyle.Border.Colour), CurrentStyle.Border.Width), new SolidBrush(backColour)); + + this.BackgroundImage = backgroundImage; + } + + public void InvalidateScreens() + { + var virtualDesktop = SystemInformation.VirtualScreen; + var offsetX = (virtualDesktop.X <= 0 ? -virtualDesktop.X : 0); + + this.Screens.Clear(); + + foreach (var screen in Screen.AllScreens) + { + var bound = screen.Bounds; + bound.Offset(offsetX, 0); + + var newBound = new RectangleF(bound.X, bound.Y, bound.Width, bound.Height); + newBound = newBound.ScaleDown(ScaleRatio); + + this.Screens.Add(new ScreenItem() + { + Bound = newBound, + IsPrimary = screen.Primary, + IsSelected = false + }); + } + + CenterRectangles(this.Screens); + + this.Invalidate(); + } + + + private int ActualWidth + { + get => this.ClientSize.Width - this.Padding.Horizontal; + } + + private int ActualHeight + { + get => this.ClientSize.Height - this.Padding.Vertical; + } + + public List Screens + { + get + { + if (field == null) field = new List(); + + return field; + } + private set + { + field = value; + + //this.Invalidate(); + } + } + + private decimal ScaleRatio + { + get + { + var virtualScreen = SystemInformation.VirtualScreen; + + var widthRatio = decimal.Divide(virtualScreen.Width, ActualWidth); + var heightRatio = decimal.Divide(virtualScreen.Height, ActualHeight); + + return Math.Max(widthRatio, heightRatio); + } + } + + private PointF CalcCentreOffset(List rectangles) + { + if (rectangles.Count <= 0) + { + return PointF.Empty; + } + + // Find the bounds + var left = rectangles.Min(r => r.Left); + var top = rectangles.Min(r => r.Top); + var right = rectangles.Max(r => r.Right); + var bottom = rectangles.Max(r => r.Bottom); + + var bounds = RectangleF.FromLTRB(left, top, right, bottom); + + // Calculate offset + var offsetX = this.Padding.Left + (ActualWidth - bounds.Width) / 2 - bounds.Left; + var offsetY = this.Padding.Top + (ActualHeight - bounds.Height) / 2 - bounds.Top; + + return new PointF(offsetX, offsetY); + } + + private void CenterRectangles(List screen) + { + var offset = CalcCentreOffset(screen.Select(x => x.Bound).ToList()); + + for (var i=0; i bounds) + { + RectangleF? rect = null; + + for (var i = 0; i < bounds.Count; i++) + { + if (rect == null) + { + rect = bounds[i]; + } + else + { + rect = RectangleF.Union(bounds[i], rect.Value); + } + } + + return rect ?? Rectangle.Empty; + } + + } +} diff --git a/source/build.bat b/source/build.bat new file mode 100644 index 0000000..ecf6655 --- /dev/null +++ b/source/build.bat @@ -0,0 +1,17 @@ +RMDIR /s /q "bin\" +RMDIR /s /q "obj\" + +MKDIR bin + +dotnet restore skye.sln +dotnet publish skye.sln -r win-x64 -c Release /p:PublishSingleFile=true /p:SelfContained=false /p:PublishReadyToRunfalse=true /p:PublishDir="bin\" + +REM "C:\B\Portable Files (dev)\Inno Setup\v6.0.4-2\app\ISCC.exe" "build-installer.iss" + +"C:\B\Portable Files\7-Zip (Portable)\23.01\App\7-Zip64\7z.exe" a -t7z "bin\randomfilerunner.7z" ".\bin\randomfilerunner.exe" -mx9 + +RMDIR /s /q "bin\debug" +RMDIR /s /q "bin\release" +RMDIR /s /q "obj\" + +PAUSE \ No newline at end of file diff --git a/source/favicon.ico b/source/favicon.ico new file mode 100644 index 0000000..4e29cac Binary files /dev/null and b/source/favicon.ico differ