From 4be3551c4ca20acafdcead7e9c594e84412d4518 Mon Sep 17 00:00:00 2001
From: zhangxuxutm <951937200@qq.com>
Date: Tue, 5 Sep 2023 09:14:33 +0800
Subject: [PATCH] 0905
---
UI/DelAreaWidget.py | 55 ++--
UI/MainWindow.py | 256 ++++++++++--------
bin.py | 4 +-
model/ClientModel/Client.py | 4 +-
.../__pycache__/Client.cpython-310.pyc | Bin 1061 -> 1058 bytes
model/ProjectModel/AreaManage.py | 16 +-
model/ProjectModel/DeviceManage.py | 90 +++++-
.../__pycache__/DeviceManage.cpython-310.pyc | Bin 2993 -> 4884 bytes
utils/DBModels/DeviceModels.py | 11 +-
9 files changed, 289 insertions(+), 147 deletions(-)
diff --git a/UI/DelAreaWidget.py b/UI/DelAreaWidget.py
index 985be5b..163d771 100644
--- a/UI/DelAreaWidget.py
+++ b/UI/DelAreaWidget.py
@@ -5,36 +5,50 @@ from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap, QIcon
import sys
-
+from model.ProjectModel.DeviceManage import Device
class DelAreaWidget(QDialog):
- def __init__(self, areaLabel, deviceName):
+ def __init__(self, deviceName):
super().__init__()
self.checkbox_data ={}
- self.areaLabel = areaLabel
self.deviceName = deviceName
self.delAreaRowAndColunm = []
self.initUI()
def initUI(self):
-
vorlayout = QVBoxLayout() #主布局
- layout = QGridLayout()
-
- for i in self.areaLabel:
- if self.deviceName in i:
- widget = i[2]
- row = i[3]
- text = widget.text()
- column = i[4]
+ # layout = QGridLayout()
+ jsonCons = Device().getAreaJson(self.deviceName)
+ row = 1
+ if jsonCons is None:
+ return
+ else:
+ for jsoncon in jsonCons:
+ varType = jsoncon["type"]
+ channelNums = jsoncon["nums"]
+ channelBytes = jsoncon["bytes"]
+ text = varType + ": " + channelBytes + 'Byte' + '数量:'+ channelNums
checkbox = QCheckBox(text)
+ vorlayout.addWidget(checkbox)
checkbox.stateChanged.connect(self.checkbox_state_changed)
- if column > 0:
- layout.addWidget(checkbox, row, 1)
- self.checkbox_data[checkbox] = [row, 1]
- else:
- layout.addWidget(checkbox, row, column)
- self.checkbox_data[checkbox] = [row, column]
+ self.checkbox_data[checkbox] = row
+ row += 1
+
+
+ # for i in self.areaLabel:
+ # if self.deviceName in i:
+ # widget = i[2]
+ # row = i[3]
+ # text = widget.text()
+ # column = i[4]
+ # checkbox = QCheckBox(text)
+ #
+ # if column > 0:
+ # vorlayout.addWidget(checkbox)
+ #
+ # else:
+ # vorlayout.addWidget(checkbox)
+ # self.checkbox_data[checkbox] = [row, column]
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
ok_button = button_box.button(QDialogButtonBox.Ok)
@@ -44,14 +58,13 @@ class DelAreaWidget(QDialog):
button_box.accepted.connect(self.getDelAreaRowAndColunm)
button_box.rejected.connect(self.reject)
- vorlayout.addLayout(layout)
vorlayout.addWidget(button_box)
self.setWindowIcon(QIcon('Static/zhjt.ico'))
self.setWindowTitle("删除通道")
self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)#去掉标题栏的问号
self.setLayout(vorlayout)
- self.exec_()
+
def checkbox_state_changed(self, state):
sender = self.sender() # 获取触发信号的对象
@@ -63,7 +76,7 @@ class DelAreaWidget(QDialog):
self.delAreaRowAndColunm.remove(self.checkbox_data[sender])
def getDelAreaRowAndColunm(self):
- self.close()
+ self.accept()
return self.delAreaRowAndColunm
diff --git a/UI/MainWindow.py b/UI/MainWindow.py
index 1e825b7..4321308 100644
--- a/UI/MainWindow.py
+++ b/UI/MainWindow.py
@@ -10,11 +10,11 @@ from PyQt5.QtGui import QPixmap, QIcon
from UI.DeviceWidget import DeviceDialog
from UI.AreaSettingWidget import AreaSettingWidget
from UI.DelAreaWidget import DelAreaWidget
-# from model.ProjectModel.AreaManage import Devices, DevicesManange, Area
+from model.ProjectModel.DeviceManage import DevicesManange, Device
from protocol.ModBus.ModBusThread import MyThread
from utils.DBModels.BaseModel import *
-# from utils.DBModels.ClientModels import DeviceDB
-# from model.ClientModel.Client import Client
+from utils.DBModels.DeviceModels import DeviceDB
+from model.ClientModel.Client import Client
class CommonHelper:
def __init__(self):
pass
@@ -33,10 +33,12 @@ class MainWindow(QMainWindow):
self.sub_windows = [] #存储设备widget
self.nowValue = [] #储存当前值
self.areaLabel = [] #存储通道信息文本
- # self.initAreaWidget()
-
- self.number = 0
+ self.arealist = {}
+ self.widgetList= []
self.initUI()
+ self.initAreaWidget()
+
+
def initUI(self):
self.toolbar = QToolBar()
@@ -68,46 +70,6 @@ class MainWindow(QMainWindow):
self.setWindowTitle("PROFIBUS")
self.setGeometry(1000, 500, 800, 600)
- # def initAreaWidget(self):
- # alldevices = Devices().getAllDevice()
- #
- # for devices in alldevices:
- # layout = self.deviceWidget(devices[0]).widget().widget().layout().itemAt(1).widget().layout()
- # areas = devices[3]
- # number = 0
- # masterSlaveModel = devices[2]
- # if areas is not None:
- # areas = json.loads(areas)
- # for area in areas:
- # varType = area["type"]
- # channelNums = area["nums"]
- # channelBytes = area["bytes"]
- # for i in range(int(channelNums)):
- # if masterSlaveModel == '主站':
- # if (i + number) % 2 == 0:
- # layout.addWidget(QLabel(varType + str(i + 1) + ": " + channelBytes + 'Byte'), (i + number) // 2,
- # (i + number) % 2)
- # layout.addWidget(QLabel('0'), (i + number) // 2, (i + number) % 2 + 1)
- # layout.addWidget(QLineEdit('0'), (i + number) // 2, (i + number) % 2 + 2)
- #
- # else:
- # layout.addWidget(QLabel(varType + str(i + 1) + ": " + channelBytes + 'Byte'), (i + number) // 2,
- # (i + number) % 2 + 3)
- # layout.addWidget(QLabel('0'), (i + number) // 2, (i + number) % 2 + 4)
- # layout.addWidget(QLineEdit('0'), (i + number) // 2, (i + number) % 2 + 5)
- # else:
- # if (i + number) % 2 == 0:
- # layout.addWidget(QLabel(varType + str(i + 1) + ": " + channelBytes + 'Byte'), (i + number) // 2,
- # (i + number) % 2)
- # layout.addWidget(QLabel('0'), (i + number) // 2, (i + number) % 2 + 1)
- # layout.addWidget(QLineEdit('0'), (i + number) // 2, (i + number) % 2 + 2)
- # else:
- # layout.addWidget(QLabel(varType + str(i + 1) + ": " + channelBytes + 'Byte'), (i + number) // 2,
- # (i + number) % 2 + 3)
- # layout.addWidget(QLabel('0'), (i + number) // 2, (i + number) % 2 + 4)
- # layout.addWidget(QLineEdit('0'), (i + number) // 2, (i + number) % 2 + 5)
- #
- # number = number + int(channelNums)
def deviceWidget(self, windowTitle):
@@ -164,13 +126,37 @@ class MainWindow(QMainWindow):
return sub_window
+ def initAreaWidget(self):
+ alldevices = DevicesManange().getAllDevice()
+
+ for devices in alldevices:
+ layout = self.deviceWidget(devices[0]).widget().widget().layout().itemAt(1).widget().layout()
+ areas = devices[3]
+ number = 0
+ masterSlaveModel = devices[2]
+ deviceName = devices[0]
+ if areas is not None:
+ areas = json.loads(areas)
+ for area in areas:
+ varType = area["type"]
+ channelNums = area["nums"]
+ channelBytes = area["bytes"]
+ areaID = area['id']
+
+ if masterSlaveModel == '主站':
+ self.addChannelWidget(deviceName, number, channelNums, channelBytes, varType, layout, areaID)
+ else:
+ self.addChannelWidget(deviceName, number, channelNums, channelBytes, varType, layout, areaID)
+ number = number + int(channelNums)
+
+
def createDeciveWidget(self):
dialog = DeviceDialog()
if dialog.exec_() == QDialog.Accepted:
deviceName, proType, masterSlaveModel, pvUpperLimit, pvLowerLimit, pvUnit = dialog.getParameters()
windowTitle = deviceName + ' ' + proType + masterSlaveModel + ' ' + pvLowerLimit + '-' + pvUpperLimit + pvUnit
- # DeviceDB().createDevice(deviceName = windowTitle, proType = proType, masterSlaveModel = masterSlaveModel, pvUpperLimit=pvUpperLimit, pvLowerLimit=pvLowerLimit, pvUnit=pvUnit)
+ DeviceDB().addDevice(deviceName = windowTitle, proType = proType, masterSlaveModel = masterSlaveModel, pvUpperLimit=pvUpperLimit, pvLowerLimit=pvLowerLimit, pvUnit=pvUnit)
else:
return
@@ -184,34 +170,54 @@ class MainWindow(QMainWindow):
dialog = AreaSettingWidget()
if dialog.exec_() == QDialog.Accepted:
varType, channelNums, channelBytes = dialog.getParameters()
- # devices = Devices()
- # number = devices.getValueLength(deviceName)
- # devices.addAreas(varType, channelNums, channelBytes, deviceName)
- # self.devicesmanage.addDevice(deviceName, channelNums, channelBytes)
+ number = DevicesManange.getChannelLength(deviceName)
+ Device().addAreas(varType, channelNums, channelBytes, deviceName)
+ areaId = Device().getAreaID(deviceName)[-1]
+ # Device().addDevice(deviceName, channelNums, channelBytes)
else:
return
layout = sub_window.widget().widget().layout().itemAt(1).widget().layout() #获取sub_window的widgetArea的areaLayout2
- number = self.number #待从数据库获取具体的数据
- for i in range(int(channelNums)):
+ self.addChannelWidget(deviceName, number, channelNums, channelBytes, varType, layout, areaId)
+ number += int(channelNums)
+
+
+
+
+
+ def addChannelWidget(self,deviceNames, numbers, channelNums, channelBytes , varTypes, layouts ,ID):
+ deviceName = deviceNames
+ number = numbers
+ channelNum = channelNums
+ channelByte = channelBytes
+ varType = varTypes
+ layout = layouts
+ ID = ID
+ widgetList = []
+ arealists = []
+
+ for i in range(int(channelNum)):
if (i + number) % 2 == 0:
- areaLabel = QLabel(varType + str(i + 1 ) + ": " + channelBytes + 'Byte' )
+ areaLabel = QLabel(varType + str(i + 1 ) + ": " + channelByte + 'Byte' )
areaLabel2 =QLabel('0')
areaLineEdit = QLineEdit('0')
editbtn = QPushButton('强制')
- layout.addWidget(areaLabel , (i + number)//2, (i + number) % 2)
+ layout.addWidget(areaLabel, (i + number)//2, (i + number) % 2)
layout.addWidget(areaLabel2, (i + number)//2, (i + number) % 2 + 1 )
layout.addWidget(areaLineEdit, (i + number)//2, (i + number) % 2 + 2 )
layout.addWidget(editbtn, (i + number) // 2, (i + number) % 2 + 3)
editbtn.clicked.connect(lambda checked, btn=editbtn: self.forceEdit(btn))
+ widgetList.append([layout, ID, editbtn, areaLabel, areaLabel2, areaLineEdit])
+
+
+
+ # self.nowValue.append([deviceName, layout, ID, editbtn, areaLabel, areaLabel2, areaLineEdit, (i + number)//2, (i + number) % 2 + 1])
- self.nowValue.append([deviceName, layout, i+1, editbtn, areaLabel2, areaLineEdit, (i + number)//2, (i + number) % 2 + 1])
- self.areaLabel.append([deviceName, i+1, areaLabel, (i + number)//2, (i + number) % 2])
else:
- areaLabel = QLabel(varType + str(i + 1) + ": " + channelBytes + 'Byte')
+ areaLabel = QLabel(varType + str(i + 1) + ": " + channelByte + 'Byte')
areaLabel2 = QLabel('0')
areaLineEdit = QLineEdit('0')
editbtn = QPushButton('强制')
@@ -222,70 +228,105 @@ class MainWindow(QMainWindow):
layout.addWidget(editbtn, (i + number) // 2, (i + number) % 2 + 6)
editbtn.clicked.connect(lambda checked, btn=editbtn: self.forceEdit(btn))
- self.nowValue.append([deviceName, layout, i + 1, editbtn, areaLabel2, areaLineEdit, (i + number) // 2, (i + number) % 2 + 4])
- self.areaLabel.append([deviceName, i + 1, areaLabel, (i + number) // 2, (i + number) % 2 + 3])
- self.number += int(channelNums)
+ widgetList.append([layout, ID, editbtn, areaLabel, areaLabel2, areaLineEdit])
+ arealists.append(widgetList)
+ self.arealist[deviceName] = arealists
- def forceEdit(self, btn):
- for item in self.nowValue:
- if btn in item:
- item[4].setText(item[5].text())
+ # self.nowValue.append([deviceName, layout, ID, editbtn, areaLabel, areaLabel2, areaLineEdit, (i + number) // 2, (i + number) % 2 + 4])
+ self.nowValue.append(self.arealist)
+ print(self.nowValue,'aaaaaa')
+
+
+ def forceEdit(self, btn):
+ pass
+ # for item in self.nowValue:
+ # if btn in item:
+ # item[4].setText(item[5].text())
def delAreaWidget(self, sub_window):
subwindow = sub_window
- if self.areaLabel:
+ if self.nowValue:
self.deviceName = subwindow.windowTitle()
- delAreaWidget = DelAreaWidget(self.areaLabel, self.deviceName)
- rowAndColumn = delAreaWidget.getDelAreaRowAndColunm()
- self.getAreaWidget(rowAndColumn, subwindow)
+ delAreaWidget = DelAreaWidget(self.deviceName)
+ if delAreaWidget.exec_() == QDialog.Accepted:
+ rowAndColumn = delAreaWidget.getDelAreaRowAndColunm()
+ if rowAndColumn == []:
+ return
+ else:
+ self.getAreaWidget(rowAndColumn, subwindow)
+ Device().delAreas(self.deviceName,rowAndColumn)
+ else:
+ return
else:
return
-
-
def getAreaWidget(self, rowAndColumn, sub_window):
- rowAndColumns = rowAndColumn
subwindow = sub_window
areaLayout = subwindow.widget().widget().layout().itemAt(1).widget().layout()
-
- for rowAndColumn in rowAndColumns:
- print(rowAndColumn)
- row = rowAndColumn[0]
- column = rowAndColumn[1]
- if column == 0:
- for i in range(4):
- widget = areaLayout.itemAtPosition(row, i).widget()
- areaLayout.removeWidget(widget)
- widget.deleteLater()
- #删除self.areaLabel列表中的对象
- for label in self.areaLabel:
- if widget in label:
- self.areaLabel.remove(label)
- else:
- for i in range(4,8):
- widget = areaLayout.itemAtPosition(row, i).widget()
- areaLayout.removeWidget(widget)
- widget.deleteLater()
- # 删除self.areaLabel列表中的对象
- for label in self.areaLabel:
- if widget in label:
- self.areaLabel.remove(label)
-
-
-
-
-
+ deviceName = subwindow.windowTitle()
+ for areaId in rowAndColumn:
+ for devicelist in self.nowValue:
+ areas = devicelist[deviceName]
+ print(areas,'sssss')
+ area = areas[areaId - 1]
+ index = areas.index(area)
+ print(index,'index')
+ print(area,'ssss')
+
+ # for area in areas:
+ # for widget in range(2, 6):
+ # print(widget)
+ # print(area[widget])
+ # area[widget].deleteLater()
+ # areaLayout.removeWidget(area[widget])
+ # self.nowValue.remove(areaS)
+ # # print(self.nowValue)
+
+
+
+ # print(rowAndColumn,'sssss')
+ # for areaId in rowAndColumn:
+ # for nowWidget in self.nowValue:
+ # if nowWidget[0] == deviceName and nowWidget[2] == areaId:
+ # for widget in range(3, 7):
+ #
+ # areaLayout.removeWidget(nowWidget[widget])
+ # nowWidget[widget].deleteLater()
+ # delAreaWidgetList.append(nowWidget)
+
+
+
+ # for widget in delAreaWidgetList: #从列表中删除已删除的部件
+ # self.nowValue.remove(widget)
+
+
+ #重置area的id
+ # i = 1
+ # j = 1
+ # for nowWidget in self.nowValue:
+ # if nowWidget[0] == deviceName:
+ # if nowWidget[2] == j:
+ # index = nowWidget.index(nowWidget[2])
+ # nowWidget[index] = i
+ # else:
+ # j = nowWidget[2]
+ # i += 1
+ # index = nowWidget.index(nowWidget[2])
+ # nowWidget[index] = i
def startProtocol(self):
- if self.areaLabel:
- print(1)
- else:
- print(2)
- return
+ a = []
+ for i in range(len(self.nowValue)):
+ a.append(i)
+
+ for i in a :
+ for j in self.nowValue:
+ j[5].setText(str(i))
+ print(a)
def closeEvent(self, event):
@@ -302,8 +343,7 @@ class AreaQMdiSubWindow(QMdiSubWindow):
super().__init__()
self.number = 0
def closeEvent(self, event):
- pass
- # self.devicedb.deleteDevice(deviceName = self.windowTitle())
+ DeviceDB.deleteDevice(deviceName = self.windowTitle())
@@ -312,7 +352,7 @@ class AreaQMdiSubWindow(QMdiSubWindow):
if __name__ == '__main__':
app = QApplication(sys.argv)
- # Client.initDB()
+ Client.initDB()
window = MainWindow()
window.show()
diff --git a/bin.py b/bin.py
index 34de450..d0259db 100644
--- a/bin.py
+++ b/bin.py
@@ -1,6 +1,6 @@
from PyQt5.QtWidgets import QApplication, QStyleFactory
from UI.MainWindow import MainWindow, CommonHelper
-# from model.ClientModel.Client import Client
+from model.ClientModel.Client import Client
import time
import sys
@@ -10,7 +10,7 @@ if __name__ == '__main__':
app = QApplication(sys.argv)
# app.setStyle(QStyleFactory.create('Fusion'))
app.setStyleSheet(CommonHelper.readQss('static/main.qss'))
- # Client.initDB()
+ Client.initDB()
window = MainWindow()
window.show()
sys.exit(app.exec_())
\ No newline at end of file
diff --git a/model/ClientModel/Client.py b/model/ClientModel/Client.py
index 89c4ebc..44c662a 100644
--- a/model/ClientModel/Client.py
+++ b/model/ClientModel/Client.py
@@ -2,10 +2,10 @@ import os
import sys
from peewee import *
from utils.DBModels.BaseModel import *
-from utils.DBModels.ClientModels import *
+from utils.DBModels.DeviceModels import *
class Client(object):
def __init__(self):
- super(Device, self).__init__()
+ super(Client, self).__init__()
@classmethod
def initDB(self):
diff --git a/model/ClientModel/__pycache__/Client.cpython-310.pyc b/model/ClientModel/__pycache__/Client.cpython-310.pyc
index a238958771f703b91e2e8b62232056302ca44db0..2a17bb7524fc8737d814a219f31573d5f7297c19 100644
GIT binary patch
delta 205
zcmZ3=v512^pO=@50SIQ7f1SwvgSChm$ezs2Sjxz{xslO@QJD?Mk77$n3P>!;h~mu6
zPf5)wb}T9?;slCA2(HO5nBvS>f&5$C$vKI|#kr{^8Tlzi;vf;;_;|2ba%xUad_0ma
zc94Fq$u-Q1jJ%WQF>6^zNtc#n<`nC>IQfDt(Q`>H%S=v%aBi{XCuOB3mw=szWD3|7
JT$7nulmK??H3t9y
delta 207
zcmZ3)v6O>5pO=@50SF!le4fbtgX0#POKMqWa_VFb#!^PM&2@|}jLPgl=_t08q=3Yd
zj400B{FKz3V#lJQB9J}^!9DpYQ=AzakbjFiIVZ8WI5)K
}p&gZ4_0gK~=>IDpb2XAXQc0EBe4cz#~ud3IXzr@>U7H?~cdb^(M3uGnzB^
z-nl=|`OZ1tbSEZ!3)lO9eWac{Zdre0W$$I9vWO>KfKZkaZL6BTMOC0K+j7mW+QNFx
zQnqsLTFTj$RR=X!JmF6v0*fnD
zWz(wKN>m*@n5mk>lUGvNcde?Y9OdF&P&t*y+gF|{;9XR{D&k#IB{hNfgql=Scu$(0
zOeeW?2bG4vI@!fCp9^^Y?La7N+4@*iK88q~FlgVeYigT&8J
zh~<*?^HY607JZ;?M?`Yf9w5^p;v!%UsFcU7Icpo}0^)$Ktc7^nkg?meZb|*J0wOU!
zALo>9FeeXUPRV{gcCn`4_u_nv_^@CBqw*!IpWj%(4vGf5Upi0Ot!Vn6o}`$ipvlW6
zeU#;66vU-ILSYc;uIpAON^&|_>)sCZ34S<9L2T)-Q6Rut<$?iVQXKh3nAj~9rl>QW
zzs}BPQqijVbOj>wq8f*ThhSn1^lc0XxtJ#%IV+~ctn>iIdEwyg2_N?!C}yJ?JVAC5
zZUmn(-Rmg8WYPo(nFbOV(Kf+kiq6gO5!*1K)3gvc9H_jI1q>zUEMvN3v5PQZ4^(Ls
zm>W~u9(~SX(Q-a@PlIgZl*NHlhRcyoysVNc%jjtslT#OEprB4JE-hldklyWxNhrY)
zzI5=Wk8Vwm{3Y$YPZ!h!VQqBrJPKb`7qNr$%JjTt_lZZvCliE*r_{#7%2;XK#KpmJ
z-T(kD;d@9_?mf`f%>JXWV|j{Mq=R5tt0jJ|hOEQ;DimHTnL4gtA?W-vmY&w}tbr>=WcbdV0xJgGbV33;jlbpqubpL%33njo3d^&b4;L7*(u;XF;2g5xShI_cbZx2s@=^oyB!X66g
z9%9d|U)X5I1*~64*N=R&7t~c@+a7Qmzmm9t)?NLG8vXlcpa1id-)bs*L@FMd1i=K7
z_WAtR=+k4uc<}DM2k(CJuRs6h!G|ARJ@?>)_m-|c_|qRVs*{Jy*Xr$dGMze{aW}&i
z(^SI5FbbQ<9i2#jk8R(lI1N$u(;SmmhI@sHxTAlB_UdFh<9YC{OWjU05t~UK6zn=k
ztl>e4Ln>CC2}_Rlt)Yf8E1`!5cB
zH{(q|tZ_pk0OczBWt=I+k6|1yvHC-ZvaJ_b9vZmpq`4zajt%^Ibb@w;G`cjX&~D+F
z(UJoAXR7OWFkKpa2S)P6X_(_Q40Q|-OlEH#8#Bvr@PRZrqzp_>Dx(aD$ish+i5N#5
z{%s7tfH=T(h#Nj53Rs|{Y(@-tzucJPh_X{j^}&Q^oT~gkxC3>RWmTh@TncNw$kE@T
zpr59KC{Cu~WfxNIrDXbjw1!l^BWD0)GAO>cPL1heeB6O#!6-nSeicIR2PzHrLHHqu
z7&1RMw&JMIzO{Iuq56M?3e=B4-j^--03L==3o4!i%?7@=MQq3Jf`u~LV-uibf!{ok
z@~lP4Z3)UPQxbz6k
zP6}iLX+|m&vtU@#p^RV**@sDsS?y37x(3xttuU%i@9n^r#J&}5jvIOg1~Z||{4y<*
z>wJXOj0@x;~6O*+GP>U!$F1Laz!}+1uDWG5OKy~;V
zvR6T*SMkrYnrkALLj98l|DcgSz&v2YCXbv&S(73U{#8NE$jVGyH~$J*VE8fmB%-Yu
zoyT=i!YR(R+v(9hMF#_T&-^Tq8=oZLPaHh?a7+bB>UmE50>v2$!vmQU^b!PEPrDw5
zYe96gtMsdEevRTH1!KgXEg6qADdju(a1D>4>mHMe>wQDc_`>r&yELWw9Vq!O$MXj)
vInj$+?eNUfd6O4WFo`a$r24Yim*XC{VB#&LocI-@G~^MuYDrAmGgtl#YXk%_
delta 1116
zcma)5%TE(Q7~kpcw$ttQ0X9^y_y8rYBp$RFNqhieOc1L{6ArzYm6>48wk0zQDhD~h
z#bX^W98C02Fr0{2{{<5>7tfqEa`pRWQNVCuH}l)?{h06D_hX+cg>F9YS@5)~KiNpJ
zSE$x51IH{zBCBaVuvm)On-;S-QcVJ!!(8B8;8KhZ
zcBX+9Y0!xzK2j7w(~vP#${cVq1yCYu#aX`ETI5$zr#kl8o0!vtPTY?RR9NEiLKv;^
zdEQxypBK@?Q(x`c{0W@Bm!cJOQ^zUe2(Z?-U&Vng@YVOs#j?O!wJ+mP#M6ukE~Qre
zG^l6Mw}4>M;{_e+*L03e3v3gQECW!>A%9;=s7)Q;F%~$Rn%beG11!VnrqxWdEc4)-
zVL6zVuhQAa#8C^`xxr&DL|`$M?VaovDQl;*(w5qN_B!Tr7c=h?wU`@U*EH#Ic1CC5
z{+@Ai$Mr1h5)p?
zEI<%=B7GEF>vr)LyPk&MDs?EFWD9aR$t)+mrqia_u~j0vAtQKo~|C
z0SIhy1?hiT1IMHjW9m!(+|bd0It#m$^mL
zYH*VDrjT(o!1jZ*$f&oahq*&Fs2`;YSx|eW`|I_9iaxaMM=<+l76*G4*AZ$6HxLdY
z7|LwV04VTCAAnl0GcFyaW#1Mkg=?w6$83-h{2yaD`R{JEyKE)mckpH