From 6973d39cada1e41f7707dd57b5b9974954616292 Mon Sep 17 00:00:00 2001 From: Admin Date: Thu, 24 Apr 2025 15:45:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DH.Commons/Base/GlobalConfig.cs | 40 ++++++- DH.Devices.Camera/Do3ThinkCamera.cs | 3 + DH.Devices.PLC/XinJEPLCTcpNet.cs | 86 +++++++++++++- DHSoftware/DHSoftware.csproj | 12 +- DHSoftware/MainWindow.cs | 14 ++- DHSoftware/Views/GlobalControl.Designer.cs | 107 +++++++++++++++++- DHSoftware/Views/GlobalControl.cs | 7 +- DHSoftware/Views/SettingWindow.cs | 87 +++++++++++++- .../VisualLocalizationWindow.Designer.cs | 1 - DHSoftware/Views/VisualLocalizationWindow.cs | 2 +- DHSoftware/db/db.sqlite | Bin 475136 -> 475136 bytes 11 files changed, 332 insertions(+), 27 deletions(-) diff --git a/DH.Commons/Base/GlobalConfig.cs b/DH.Commons/Base/GlobalConfig.cs index 0141774..50d93b0 100644 --- a/DH.Commons/Base/GlobalConfig.cs +++ b/DH.Commons/Base/GlobalConfig.cs @@ -11,6 +11,9 @@ namespace DH.Commons.Base { public class GlobalConfig : NotifyProperty { + bool _EnableVibrator=false; + bool _EnableBelt = false; + int _ClearTime=0; string _name; private BindingList _InitProcessList = new BindingList(); private BindingList _StartProcessList = new BindingList(); @@ -29,7 +32,42 @@ namespace DH.Commons.Base } } } - + public bool EnableBelt + { + get => _EnableBelt; + set + { + if (_EnableBelt != value) + { + _EnableBelt = value; + OnPropertyChanged(nameof(EnableBelt)); + } + } + } + public bool EnableVibrator + { + get => _EnableVibrator; + set + { + if (_EnableVibrator != value) + { + _EnableVibrator = value; + OnPropertyChanged(nameof(EnableVibrator)); + } + } + } + public int ClearTime + { + get => _ClearTime; + set + { + if (_ClearTime != value) + { + _ClearTime = value; + OnPropertyChanged(nameof(ClearTime)); + } + } + } public BindingList InitProcessList { get => _InitProcessList; diff --git a/DH.Devices.Camera/Do3ThinkCamera.cs b/DH.Devices.Camera/Do3ThinkCamera.cs index 67aea35..756ffa6 100644 --- a/DH.Devices.Camera/Do3ThinkCamera.cs +++ b/DH.Devices.Camera/Do3ThinkCamera.cs @@ -156,7 +156,10 @@ namespace DH.Devices.Camera } //全画幅 if (!IsAllPicEnabled) + { SetPictureRoi((int)ROIX, (int)ROIY, (int)ROIW, (int)ROIH); + } + //// 设置 触发延迟 if (TriggerDelay > 0) diff --git a/DH.Devices.PLC/XinJEPLCTcpNet.cs b/DH.Devices.PLC/XinJEPLCTcpNet.cs index 25ad03e..d3a7a81 100644 --- a/DH.Devices.PLC/XinJEPLCTcpNet.cs +++ b/DH.Devices.PLC/XinJEPLCTcpNet.cs @@ -822,25 +822,73 @@ namespace DH.Devices.PLC //流程开启操作配置 // ProcessInitialAction(); // if (_PLC?Enabled == true) - //皮带 - // _PLC.Belt(true); + // LogAsync(DateTime.Now, LogLevel.Information, $"写入流程加载点位配置"); + + bool? enableBelt = ConfigModel.GlobalList?.FirstOrDefault()?.EnableBelt; + if (enableBelt == true) + { + Belt(true); + } + Thread.Sleep(1000); + bool? enableVibrator = ConfigModel.GlobalList?.FirstOrDefault()?.EnableVibrator; + if (enableVibrator == true) + { + Vibrator(true); + } + Thread.Sleep(1000); + //转盘使能 + TurnEnable(true); + //转盘启动 + TurnStart(true); + Thread.Sleep(1000); //计数清零 CountToZero(); LogAsync(DateTime.Now, LogLevel.Information, $"状态复位-关闭定位-写入流程加载点位配置-计数清零"); - //转盘启动 - TurnStart(true); + + Thread.Sleep(200); } + public void StopProcess() { StatusReset(); VisionPos(false); CountToZero(); + bool? enableVibrator = ConfigModel.GlobalList?.FirstOrDefault()?.EnableVibrator; + if (enableVibrator == true) + { + Vibrator(true); + } + Thread.Sleep(1000); + bool? enableBelt = ConfigModel.GlobalList?.FirstOrDefault()?.EnableBelt; + if (enableBelt == true) + { + Belt(false); + } + Thread.Sleep(1000); StopProcessAction(); TurnStart(false); - // LogAsync(DateTime.Now, LogLevel.Information, $"PLC断开连接"); + LogAsync(DateTime.Now, LogLevel.Action, $"流程停止"); + Task.Run(async () => { + + await ExecuteClearDelayAsync(); + }); + + } + + public async Task ExecuteClearDelayAsync() + { + int? clearTime = ConfigModel.GlobalList?.FirstOrDefault()?.ClearTime; + if (clearTime != null) + { + LogAsync(DateTime.Now, LogLevel.Action, $"转盘清料开始"); + TurnClear(true); + await Task.Delay(clearTime.Value * 1000); + LogAsync(DateTime.Now, LogLevel.Action, $"转盘清料完成"); + TurnClear(false); + } } public void CloseProcess() { @@ -850,6 +898,7 @@ namespace DH.Devices.PLC TurnStart(false); TurnEnable(false); StopProcessAction(); + TurnClear(false); OpenHeartbeat(false); PLCDisConnect(); // LogAsync(DateTime.Now, LogLevel.Information, $"PLC断开连接"); @@ -1014,6 +1063,25 @@ namespace DH.Devices.PLC WriteBool(pLCItem.Address, b); Thread.Sleep(30); } + + public void Belt(bool b) + { + PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "皮带"); + if (pLCItem == null) + return; + WriteBool(pLCItem.Address, b); + Thread.Sleep(30); + + } + public void Vibrator(bool b) + { + PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "振动盘"); + if (pLCItem == null) + return; + WriteBool(pLCItem.Address, b); + Thread.Sleep(30); + + } public void Motor(bool direction, int speed, int pos) { @@ -1143,7 +1211,13 @@ namespace DH.Devices.PLC elapsedTime += checkInterval; } - + BarrierToZero(false); + Thread.Sleep(300); + // 检查是否不在原点,如果不在,则回原点 + BarrierClockwise(false); + Thread.Sleep(300); + BarrierCounterclockwise(false); + Thread.Sleep(300); // 无论是刚回到原点还是已经在原点,执行目标位置、速度和方向设置 BarrierSpeed(speed); Thread.Sleep(300); diff --git a/DHSoftware/DHSoftware.csproj b/DHSoftware/DHSoftware.csproj index 76aa129..c54fbfc 100644 --- a/DHSoftware/DHSoftware.csproj +++ b/DHSoftware/DHSoftware.csproj @@ -93,10 +93,12 @@ - - - PreserveNewest - - + + + PreserveNewest + + !Exists('$(OutputPath)\db\db.sqlite') + + \ No newline at end of file diff --git a/DHSoftware/MainWindow.cs b/DHSoftware/MainWindow.cs index 102e791..928fe63 100644 --- a/DHSoftware/MainWindow.cs +++ b/DHSoftware/MainWindow.cs @@ -656,6 +656,7 @@ namespace DHSoftware cam.Exposure = cameraBase.Exposure; cam.Gain = cameraBase.Gain; cam.RotateImage = cameraBase.RotateImage; + cam.IsAllPicEnabled=cameraBase.IsAllPicEnabled; cam.ROIX= cameraBase.ROIX; cam.ROIH= cameraBase.ROIH; cam.ROIW= cameraBase.ROIW; @@ -1083,6 +1084,8 @@ namespace DHSoftware { if (_monitorThread == null || !_monitorThread.IsAlive) { + //关闭按钮自身功能(比如按按钮转盘自己启动等) + PLC.WriteBool("M40", true); _isRunning = true; _monitorThread = new Thread(MonitorPlcButtons); _monitorThread.IsBackground = true; // 后台线程 @@ -1144,6 +1147,7 @@ namespace DHSoftware { _monitorThread.Join(1000); // 等待线程退出 } + PLC.WriteBool("M40", false); } private bool _isClosing = false; // 状态标志 @@ -1269,6 +1273,7 @@ namespace DHSoftware LogAsync(DateTime.Now, LogLevel.Information, "流程启动中,请稍候..."); ResetAllCameraCounts(); //开始流程 + StartProcess(); LogAsync(DateTime.Now, LogLevel.Action, "流程启动完成!"); } @@ -1371,9 +1376,8 @@ namespace DHSoftware //mOfflineImageTimer.Start(); #endregion 虚拟相机 - //流程执行时PLC - PLC.StartProcess(); - LogAsync(DateTime.Now, LogLevel.Action, "流程启动11111111111完成!"); + + ///这里会执行完成后,会造成后台线程断断续续,会造成界面UI卡顿 //var settings = ConfigModel.DetectionList.Where(u => u.IsEnabled && u.IsAddStation).ToList(); //if (settings != null) @@ -1417,7 +1421,8 @@ namespace DHSoftware InitialOEEStatistic(); - + //流程执行时PLC + PLC.StartProcess(); CurrentMachine = true; } catch (Exception ex) @@ -1863,6 +1868,7 @@ namespace DHSoftware // Add the code for the "停止" button click here PLC.StopProcess(); CurrentMachine = false; + //sLDMotion.Stop(); } diff --git a/DHSoftware/Views/GlobalControl.Designer.cs b/DHSoftware/Views/GlobalControl.Designer.cs index dff5110..7dfd36d 100644 --- a/DHSoftware/Views/GlobalControl.Designer.cs +++ b/DHSoftware/Views/GlobalControl.Designer.cs @@ -28,7 +28,7 @@ /// private void InitializeComponent() { - AntdUI.Tabs.StyleLine styleLine1 = new AntdUI.Tabs.StyleLine(); + AntdUI.Tabs.StyleLine styleLine2 = new AntdUI.Tabs.StyleLine(); tabs1 = new AntdUI.Tabs(); tabPage6 = new AntdUI.TabPage(); tabPage1 = new AntdUI.TabPage(); @@ -56,7 +56,16 @@ panel5 = new AntdUI.Panel(); btnStopResetDelete = new AntdUI.Button(); btnStopResetAdd = new AntdUI.Button(); + panel6 = new AntdUI.Panel(); + panel7 = new AntdUI.Panel(); + uiLabel1 = new Sunny.UI.UILabel(); + swhEnableVibrator = new AntdUI.Switch(); + swhEnableBelt = new AntdUI.Switch(); + uiLabel2 = new Sunny.UI.UILabel(); + uiLabel3 = new Sunny.UI.UILabel(); + iptClearTime = new AntdUI.Input(); tabs1.SuspendLayout(); + tabPage6.SuspendLayout(); tabPage1.SuspendLayout(); panel1.SuspendLayout(); tabPage2.SuspendLayout(); @@ -67,6 +76,7 @@ panel4.SuspendLayout(); tabPage5.SuspendLayout(); panel5.SuspendLayout(); + panel6.SuspendLayout(); SuspendLayout(); // // tabs1 @@ -81,13 +91,14 @@ tabs1.Pages.Add(tabPage4); tabs1.Pages.Add(tabPage5); tabs1.Size = new Size(898, 530); - tabs1.Style = styleLine1; + tabs1.Style = styleLine2; tabs1.TabIndex = 26; tabs1.Text = "tabs1"; - tabs1.SelectedIndex = 1; // // tabPage6 // + tabPage6.Controls.Add(panel7); + tabPage6.Controls.Add(panel6); tabPage6.Location = new Point(3, 28); tabPage6.Name = "tabPage6"; tabPage6.Size = new Size(892, 499); @@ -372,6 +383,86 @@ btnStopResetAdd.Type = AntdUI.TTypeMini.Primary; btnStopResetAdd.WaveSize = 0; // + // panel6 + // + panel6.Controls.Add(iptClearTime); + panel6.Controls.Add(uiLabel3); + panel6.Controls.Add(swhEnableBelt); + panel6.Controls.Add(uiLabel2); + panel6.Controls.Add(swhEnableVibrator); + panel6.Controls.Add(uiLabel1); + panel6.Dock = DockStyle.Left; + panel6.Location = new Point(0, 0); + panel6.Name = "panel6"; + panel6.Size = new Size(427, 499); + panel6.TabIndex = 0; + panel6.Text = "panel6"; + // + // panel7 + // + panel7.Dock = DockStyle.Fill; + panel7.Location = new Point(427, 0); + panel7.Name = "panel7"; + panel7.Size = new Size(465, 499); + panel7.TabIndex = 1; + panel7.Text = "panel7"; + // + // uiLabel1 + // + uiLabel1.Font = new Font("宋体", 12F, FontStyle.Regular, GraphicsUnit.Point, 134); + uiLabel1.ForeColor = Color.FromArgb(48, 48, 48); + uiLabel1.Location = new Point(28, 36); + uiLabel1.Name = "uiLabel1"; + uiLabel1.Size = new Size(63, 23); + uiLabel1.TabIndex = 0; + uiLabel1.Text = "振动盘"; + // + // swhEnableVibrator + // + swhEnableVibrator.CheckedText = "启用"; + swhEnableVibrator.Location = new Point(97, 26); + swhEnableVibrator.Name = "swhEnableVibrator"; + swhEnableVibrator.Size = new Size(94, 33); + swhEnableVibrator.TabIndex = 50; + swhEnableVibrator.UnCheckedText = "关闭"; + // + // swhEnableBelt + // + swhEnableBelt.CheckedText = "启用"; + swhEnableBelt.Location = new Point(97, 82); + swhEnableBelt.Name = "swhEnableBelt"; + swhEnableBelt.Size = new Size(94, 33); + swhEnableBelt.TabIndex = 52; + swhEnableBelt.UnCheckedText = "关闭"; + // + // uiLabel2 + // + uiLabel2.Font = new Font("宋体", 12F, FontStyle.Regular, GraphicsUnit.Point, 134); + uiLabel2.ForeColor = Color.FromArgb(48, 48, 48); + uiLabel2.Location = new Point(28, 92); + uiLabel2.Name = "uiLabel2"; + uiLabel2.Size = new Size(63, 23); + uiLabel2.TabIndex = 51; + uiLabel2.Text = "皮带"; + // + // uiLabel3 + // + uiLabel3.Font = new Font("宋体", 12F, FontStyle.Regular, GraphicsUnit.Point, 134); + uiLabel3.ForeColor = Color.FromArgb(48, 48, 48); + uiLabel3.Location = new Point(17, 142); + uiLabel3.Name = "uiLabel3"; + uiLabel3.Size = new Size(74, 23); + uiLabel3.TabIndex = 53; + uiLabel3.Text = "清料时间"; + // + // iptClearTime + // + iptClearTime.Location = new Point(97, 131); + iptClearTime.Name = "iptClearTime"; + iptClearTime.Size = new Size(94, 43); + iptClearTime.TabIndex = 54; + iptClearTime.Text = "0"; + // // GlobalControl // AutoScaleDimensions = new SizeF(7F, 17F); @@ -380,6 +471,7 @@ Name = "GlobalControl"; Size = new Size(898, 530); tabs1.ResumeLayout(false); + tabPage6.ResumeLayout(false); tabPage1.ResumeLayout(false); panel1.ResumeLayout(false); tabPage2.ResumeLayout(false); @@ -390,6 +482,7 @@ panel4.ResumeLayout(false); tabPage5.ResumeLayout(false); panel5.ResumeLayout(false); + panel6.ResumeLayout(false); ResumeLayout(false); } @@ -421,5 +514,13 @@ private AntdUI.Button btnAdd; private AntdUI.Button btnDelete; private AntdUI.TabPage tabPage6; + private AntdUI.Panel panel7; + private AntdUI.Panel panel6; + private Sunny.UI.UILabel uiLabel1; + private AntdUI.Switch swhEnableBelt; + private Sunny.UI.UILabel uiLabel2; + private AntdUI.Switch swhEnableVibrator; + private Sunny.UI.UILabel uiLabel3; + private AntdUI.Input iptClearTime; } } diff --git a/DHSoftware/Views/GlobalControl.cs b/DHSoftware/Views/GlobalControl.cs index aac402f..e66f3b5 100644 --- a/DHSoftware/Views/GlobalControl.cs +++ b/DHSoftware/Views/GlobalControl.cs @@ -690,8 +690,11 @@ namespace DHSoftware.Views private void InitData() { - - + + // 启用状态绑定 + swhEnableVibrator.DataBindings.Add("Checked", global, "EnableVibrator", true, DataSourceUpdateMode.OnPropertyChanged); + swhEnableBelt.DataBindings.Add("Checked", global, "EnableBelt", true, DataSourceUpdateMode.OnPropertyChanged); + iptClearTime.DataBindings.Add("Text", global, "ClearTime", true, DataSourceUpdateMode.OnPropertyChanged); TableInitProcess.Columns = new ColumnCollection() { new ColumnCheck("Selected"){Fixed = true}, diff --git a/DHSoftware/Views/SettingWindow.cs b/DHSoftware/Views/SettingWindow.cs index ce53ebd..08a1a0c 100644 --- a/DHSoftware/Views/SettingWindow.cs +++ b/DHSoftware/Views/SettingWindow.cs @@ -59,6 +59,19 @@ namespace DHSoftware.Views switch (clickedItem.PARENTITEM.Text) { case "相机设置": + bool b = false; + if (ButtonPermissionList.Count > 0) + { + foreach (var item in ButtonPermissionList) + { + if (item.EnCode == "sys-cameraset") + { + b = true; + break; + } + } + } + if (!b) { AntdUI.Message.warn(this, $"对不起,无权限访问相机设置!", autoClose: 3); return; } foreach (var tab in tabs1.Pages) { if (tab is AntdUI.TabPage existingTab && existingTab.Text == $"{clickedItem.PARENTITEM.Text}-{clickedItem.Text}") @@ -99,6 +112,19 @@ namespace DHSoftware.Views break; case "工位设置": + bool b1 = false; + if (ButtonPermissionList.Count > 0) + { + foreach (var item in ButtonPermissionList) + { + if (item.EnCode == "sys-stationset") + { + b1 = true; + break; + } + } + } + if (!b1) { AntdUI.Message.warn(this, $"对不起,无权限访问工位设置!", autoClose: 3); return; } // 检查是否已存在同名 TabPage foreach (var tab in tabs1.Pages) { @@ -146,6 +172,19 @@ namespace DHSoftware.Views break; case "运控设置": + bool b2 = false; + if (ButtonPermissionList.Count > 0) + { + foreach (var item in ButtonPermissionList) + { + if (item.EnCode == "sys-motionset") + { + b2 = true; + break; + } + } + } + if (!b2) { AntdUI.Message.warn(this, $"对不起,无权限访问运控设置!", autoClose: 3); return; } foreach (var tab in tabs1.Pages) { if (tab is AntdUI.TabPage existingTab && existingTab.Text == $"{clickedItem.PARENTITEM.Text}-{clickedItem.Text}") @@ -185,6 +224,19 @@ namespace DHSoftware.Views } break; case "其他设置": + bool b3 = false; + if (ButtonPermissionList.Count > 0) + { + foreach (var item in ButtonPermissionList) + { + if (item.EnCode == "sys-globalset") + { + b3 = true; + break; + } + } + } + if (!b3) { AntdUI.Message.warn(this, $"对不起,无权限访问其他设置!", autoClose: 3); return; } foreach (var tab in tabs1.Pages) { if (tab is AntdUI.TabPage existingTab && existingTab.Text == $"{clickedItem.PARENTITEM.Text}-{clickedItem.Text}") @@ -329,15 +381,30 @@ namespace DHSoftware.Views } return null; } + private List _buttonPermissionList = new List(); + private readonly object _permissionLock = new object(); + + /// + /// 按钮权限列表(线程安全) + /// public List ButtonPermissionList { + get + { + lock (_permissionLock) + { + return new List(_buttonPermissionList); // 返回副本避免外部修改 + } + } set { - List list = value; - SetPermission(list, this.Controls); + lock (_permissionLock) + { + _buttonPermissionList = value ?? new List(); + SetPermission(_buttonPermissionList, this.Controls); // 应用权限到控件 + } } } - private void SetPermission(List list, Control.ControlCollection controls) { foreach (Control control in controls) @@ -453,7 +520,19 @@ namespace DHSoftware.Views { if (e.Button == MouseButtons.Right) { - + bool b = false; + if (ButtonPermissionList.Count > 0) + { + foreach(var item in ButtonPermissionList) + { + if (item.EnCode == "sys-setright") + { + b= true; + break; + } + } + } + if (!b) { return; } var menu = sender as Menu; if (menu == null) return; diff --git a/DHSoftware/Views/VisualLocalizationWindow.Designer.cs b/DHSoftware/Views/VisualLocalizationWindow.Designer.cs index 50360a5..8317a24 100644 --- a/DHSoftware/Views/VisualLocalizationWindow.Designer.cs +++ b/DHSoftware/Views/VisualLocalizationWindow.Designer.cs @@ -462,7 +462,6 @@ // iptBarrierPos.Location = new Point(284, 0); iptBarrierPos.Name = "iptBarrierPos"; - iptBarrierPos.ReadOnly = true; iptBarrierPos.Size = new Size(175, 43); iptBarrierPos.TabIndex = 20; iptBarrierPos.Text = "0"; diff --git a/DHSoftware/Views/VisualLocalizationWindow.cs b/DHSoftware/Views/VisualLocalizationWindow.cs index bc6d3b7..52e6959 100644 --- a/DHSoftware/Views/VisualLocalizationWindow.cs +++ b/DHSoftware/Views/VisualLocalizationWindow.cs @@ -175,7 +175,7 @@ namespace DHSoftware.Views AntdUI.Message.warn(this, "挡料电机速度值无效"); return; } - if (!int.TryParse(iptBarrierPos.Text, out int barrierPos) || speed == 0) + if (!int.TryParse(iptBarrierPos.Text, out int barrierPos) || barrierPos == 0) { AntdUI.Message.warn(this, "挡料电机位置值无效"); return; diff --git a/DHSoftware/db/db.sqlite b/DHSoftware/db/db.sqlite index f16095bd76ff5608e3f2d45be9ef6623028a5fe4..8cff70ad1776195890a67228724d72aa1b09c18d 100644 GIT binary patch delta 8506 zcmbW6dsGzH9mn_Hxw{L5Whlx+b`eQzqPF79>^!k1zD_hz5d@S4dHDndMKlTVwXnw2 z{9&*qdTpB2(32+qWu=~mBvng#PES4doK#QSr0r=NL?PN&v?n%NliE9T7g*))oE5`#)m5+r4& zAkSnB<%``P6lLK6+Qg@T|Of+&vyXz;N^QGnkBR7@Oyt{&{0 zRSkas3fB#F?7a?t9QO8mk9!Y!+r9PP#a_Xi<8^tidM>nT-U@z-dI`UfOkV}dnZ5#wnZ68`S^hW7r*TXQlpt8jJV63W@bxc1X5T-* z0G}m+(BZ$p-6*uPv+3{v^y78_YfaT?shd%?(Nb*?)`Aee2;puJ>MQ2pJAs@O@34!1 zGVLYbuO2#@TAuPzN?!8Xq_@4py`AU1Gddq%m??_j>vLSbB$qE4^1Qe}T)^|=cMkYc z2F!kV`}!SiO&c3`Ts?92(=#WAx=vkt<;2yl*M<%r9zJ^Z(>LFr?(Z)6VHWPsf}V`% zV=-71GzvvsQbf7C_urY;*qrfWQmDAoSYQV8n8*xfY`=m($$*pcHa2fv)6h%;8rpw+ zsJG+V{(~fbUBm5ZosTR}6t!ptx(F0)ofWFZ~ARz^=Xhdg7|p_MLa>>&`NsH<5YeWm2;>pTSZ5|Mdbw|2|}o(h$8BqucQYV zR4xipshiS|e;J}dX;jXyvVKobmGyfjS5uNq2j8ov#|EiXS5qlbc`7PJDuo)0)Kxtt;_^}6%5vCf8!O9#nR6Lh}QwXxQY zDh^XBStIh}@jJLiNKgV|3zEa$rT zRJ?5v1-e^4CvUT9(C0MV+W24%ld>Z(p{rrGQ)-PJl~h~+FRgJtwX5S(RkPUqI2|I# zQ(GOMiU;~o9)1}j$E%*TCP@S&W zRq?6#f>~U<2S5fs_Fd?9Itwe~lT}PAEP(GK=NYT8qgtD=U2f#K5X$YSq`U(7wi`K~ z+p_pn+;3Lb!9nMtu80p+%<2kspZqczUr*v3-(yN`$mB^Dz^z{A`6{u2nh!CHnuLqf zQ0lVLK47AI=jC>A@+=E<|Mjb696sXwep_ruCdKB*|GVNmcgyUkhv3{JB@l6bc=50oYQ3G^FuZf0=l)B@_7H=DB9W%4q!@}2BrjP( zb$pMR{Wc`2g@!EKjgdE{eF3-4)$xt5ab!c};}AZd%K4X$KDZNOBOA1WMIR@Q-To3I zayCR<@DsA-B*Dh)-V&oiJF4L0a_|dfFxTm?2R2m6{PkJ*Y#QfxIt4BpEbh5xZZ*w( z&E_4WBVjvqLnp|>eLNR%I1iD%@u{+5&BGA{olZk!j|~;~@FZt@k>i|2cH2-jGuBM} zGJpYxIg9MF!J0J|z`sdF6N_VR)d?-!$W9xsSzu^Z?Cn1>=JPg8v&01F$oBh@W6e^- zdgt0SzA47OZzcBr|D4_R%(t=V^~U;MYMlFIV%K}t?t0cM8fj%9oKYIP%o9UDV}~B; zk|5kg&`vk0JL01;X+P!Q)D_O5+ijqr3rsYdItaf+$YV8>*i5v=CmZI=n$;sg*hBh$ zPSM-!&?7w(g!erFx-~wUbh)BE5_F{8`Alz(Psa1ANc#2=sMDF)5+AD5?ueDY|2_b^ z#SU$?NGx>S_nb%FY=<7HzkFwVHQK7|Bdy8|pZQH-8~F;5i)Z;bvn|`@{OnTz`eihp8Nl$^t6uhLF{$ q9-@eR>V}5tIg@e0-;w{@9}lCxkB8mDAKg!q&)w7dQu{rhhyM>~qWuQ| delta 1269 zcmZwHUr19?90%~7bFa=jz20T1wKa7qrjgtIv$;9?Ym!>9@?UP6PL%!#StdP5L~etM zo;1u(^biP950N#DMo-m4Bn4tnT9IU0mi;xze2}Pn&u<8kjQj98zjMC#cklhNV9*i_ zT6)aJd} zSnIKgOjhH7`e5O$z(5TSs1f&SAYwDD`uD)5O~BC@Hv+3_p}GM$qEd|zeGuV+)yF>A zR0J&b1Kk?U~mTRQ;-u_q36@V`N{CXy0cY zG_x?lYTLs3z|Ob8Jm6f6Yk?h;EFH{AmX5^~tMwAj(cXcHe4JwGhtCG?dk0(toQ%;5 t47_LQSiFabOjz|#!n~mRgAf1!