From 244b0af6c83ecd50ca567bb654e02bf09eda025c Mon Sep 17 00:00:00 2001 From: ykkokluo <984278063@qq.com> Date: Mon, 24 Aug 2026 14:55:35 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A3=81=E5=AF=BC=E8=88=AA1.0=E5=86=85?= =?UTF-8?q?=E9=83=A8=E4=BA=A4=E7=AE=A1=E5=92=8C=E4=BF=A1=E5=8F=B7=E4=BA=A4?= =?UTF-8?q?=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Directory.Build.targets | 15 + Doc/磁条交管逻辑与策略说明.html | 355 ++++++++++ Doc/磁条交管逻辑与策略说明.pdf | Bin 0 -> 443041 bytes .../InterLock/MagControlReleaseHook.cs | 75 +++ .../Fass2SimConfig.cs | 2 +- .../Fass2SimFileLogger.cs | 4 +- .../MainWindow.xaml.cs | 4 +- .../appsettings.car2.json | 2 +- StandardScene.Fass2Simulator/appsettings.json | 2 +- StandardScene.MagCarSimulator/MagCarSimLog.cs | 131 ++++ StandardScene.MagCarSimulator/MainForm.cs | 630 ++++++++++++++++++ .../Map/MagControlAreaFile.cs | 83 +++ .../Map/MapPathFinder.cs | 213 ++++++ .../Map/SimpleLiteMap.cs | 324 +++++++++ .../Net/MagCarSimTcpServer.cs | 242 +++++++ StandardScene.MagCarSimulator/Program.cs | 15 + .../Protocol/MagCarSimProtocol.cs | 144 ++++ .../Runtime/MagCarSimConfig.cs | 114 ++++ .../Runtime/MagCarSimHost.cs | 335 ++++++++++ .../Runtime/MagCarSimVehicle.cs | 499 ++++++++++++++ .../StandardScene.MagCarSimulator.csproj | 24 + .../appsettings.json | 574 ++++++++++++++++ StandardScene.Magnetic/CarTypes/Mag2Car.cs | 2 +- StandardScene.Magnetic/CarTypes/MagCar.cs | 271 +++++++- .../Tasking/Fass2ControlAreaOccupancy.cs | 1 + .../Tasking/Mag2CarFileLogger.cs | 6 +- .../Config/Signal/handshake-points.json | 27 +- .../Config/Signal/mag-control-areas.json | 134 ++++ .../Signal/mag-control-areas.复杂交管.json | 134 ++++ .../Config/Signal/signal-tables.json | 40 ++ .../Config/Signal/station-docks.json | 62 ++ .../Config/Signal/stations.json | 22 +- StandardScene.Signal/Logic/CarScanWorker.cs | 21 +- .../Logic/JgControlHandler.cs | 55 +- .../Logic/MagControlAreaGate.cs | 189 ++++++ .../Logic/MagControlRuntime.cs | 479 +++++++++++++ .../Logic/MagTrafficFileLogger.cs | 136 ++++ .../Logic/PointControlHandler.cs | 8 +- StandardScene.Signal/Logic/SignalStopSpec.cs | 107 ++- .../Mission/MagTrafficMission.cs | 193 ++++++ .../Mission/SignalInteractMission.cs | 78 ++- .../Model/HandshakePointModel.cs | 48 +- .../Model/MagControlAreaModel.cs | 60 ++ .../Model/PlcStationDockModel.cs | 106 +++ StandardScene.Signal/Model/PlcStationModel.cs | 92 +-- .../Model/ReleasePointModel.cs | 1 + StandardScene.Signal/Model/SignalEnums.cs | 28 + .../Model/SignalSelectAttribute.cs | 18 + .../Model/SignalTableAttribute.cs | 27 + StandardScene.Signal/Plc/PlcAddress.cs | 63 ++ StandardScene.Signal/Plc/PlcConfigLoader.cs | 89 +++ StandardScene.Signal/Plc/PlcStationLogic.cs | 30 +- StandardScene.Signal/Plc/PlcStationRuntime.cs | 53 +- StandardScene.Signal/Plc/PlcStationWorker.cs | 263 ++++++-- StandardScene.Signal/Plc/SiemensPlcSession.cs | 22 +- StandardScene.Signal/Plc/SignalCarAdapter.cs | 16 + StandardScene.Signal/SignalConfigStore.cs | 2 +- .../StandardScene.Signal.csproj | 3 +- .../StandardScene.Signal.scene.json | 2 +- StandardScene.sln | 14 + 60 files changed, 6395 insertions(+), 294 deletions(-) create mode 100644 Doc/磁条交管逻辑与策略说明.html create mode 100644 Doc/磁条交管逻辑与策略说明.pdf create mode 100644 StandardScene.Core/InterLock/MagControlReleaseHook.cs create mode 100644 StandardScene.MagCarSimulator/MagCarSimLog.cs create mode 100644 StandardScene.MagCarSimulator/MainForm.cs create mode 100644 StandardScene.MagCarSimulator/Map/MagControlAreaFile.cs create mode 100644 StandardScene.MagCarSimulator/Map/MapPathFinder.cs create mode 100644 StandardScene.MagCarSimulator/Map/SimpleLiteMap.cs create mode 100644 StandardScene.MagCarSimulator/Net/MagCarSimTcpServer.cs create mode 100644 StandardScene.MagCarSimulator/Program.cs create mode 100644 StandardScene.MagCarSimulator/Protocol/MagCarSimProtocol.cs create mode 100644 StandardScene.MagCarSimulator/Runtime/MagCarSimConfig.cs create mode 100644 StandardScene.MagCarSimulator/Runtime/MagCarSimHost.cs create mode 100644 StandardScene.MagCarSimulator/Runtime/MagCarSimVehicle.cs create mode 100644 StandardScene.MagCarSimulator/StandardScene.MagCarSimulator.csproj create mode 100644 StandardScene.MagCarSimulator/appsettings.json create mode 100644 StandardScene.Signal/Config/Signal/mag-control-areas.json create mode 100644 StandardScene.Signal/Config/Signal/mag-control-areas.复杂交管.json create mode 100644 StandardScene.Signal/Config/Signal/signal-tables.json create mode 100644 StandardScene.Signal/Config/Signal/station-docks.json create mode 100644 StandardScene.Signal/Logic/MagControlAreaGate.cs create mode 100644 StandardScene.Signal/Logic/MagControlRuntime.cs create mode 100644 StandardScene.Signal/Logic/MagTrafficFileLogger.cs create mode 100644 StandardScene.Signal/Mission/MagTrafficMission.cs create mode 100644 StandardScene.Signal/Model/MagControlAreaModel.cs create mode 100644 StandardScene.Signal/Model/PlcStationDockModel.cs create mode 100644 StandardScene.Signal/Model/SignalSelectAttribute.cs create mode 100644 StandardScene.Signal/Model/SignalTableAttribute.cs create mode 100644 StandardScene.Signal/Plc/PlcAddress.cs create mode 100644 StandardScene.Signal/Plc/PlcConfigLoader.cs diff --git a/Directory.Build.targets b/Directory.Build.targets index 468cd84..99b416f 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -33,12 +33,27 @@ Condition="Exists('$(TargetDir)IoTClient.dll')" /> + + + + + diff --git a/Doc/磁条交管逻辑与策略说明.html b/Doc/磁条交管逻辑与策略说明.html new file mode 100644 index 0000000..290f374 --- /dev/null +++ b/Doc/磁条交管逻辑与策略说明.html @@ -0,0 +1,355 @@ + + + + + 磁条交管逻辑与策略说明 + + + +
+

FASS 2.0 / scene.signal

+

磁条交管逻辑与策略说明

+

MagCar 管控区排队、兼容组并行与扫车放行

+
+ 适用对象:现场实施、调度配置、软件维护
+ 配置文件:SimpleLite 工作目录 Config/Signal/mag-control-areas.json
+ 进程名称:磁条交管进程(MagTrafficMission)
+ 文档日期:2026-08-18 +
+
+ +

1. 文档目的与适用范围

+

本文说明 FASS 2.0 磁导航场景中,磁条交管进程如何根据管控区配置表对 MagCar(FASS 1.0 磁条车)进行停车等待、排队和放行。读者按本文即可完成十字路口、汇合点、单入口限流的配表,并理解扫车每一拍在做什么。

+

1.1 适用

+
    +
  • 车型仅 MagCar。类型名必须恰好为 MagCar。
  • +
  • 车在配置的管控触发站点停稳后,由本进程发 FASS 1.0 启动指令(StartMagCar)。
  • +
  • 配置表由迷毂数据中心「磁条管控区」或进程内「打开管控区列表」维护,保存到上述 JSON。
  • +
+

1.2 不适用

+
    +
  • Mag2Car 不走本进程。Mag2 仍使用地图字段 Fass2_ControlArea / Fass2_ControlCapacity,以及任务报文 StartStop=12→11,本进程不改 Mag2 报文。
  • +
  • 内核 TrafficControl.TryLock 点锁、交通管制进程 traffic.json、环线任务的流量字段,与本表独立。
  • +
  • 不负责让车在触发点停车。车必须先由任务/站点策略停在触发点,本进程只负责「满足条件后发启动」。
  • +
+ +

2. 总体策略

+

交管策略可以概括为四句话:

+
    +
  1. 按区绑定:同一「管控区名称」的多行表示同一个物理路口(或汇合区)。
  2. +
  3. 按线占用:每一行有自己的内部站点列表和容量,占用只统计本行站点,不把整个路口并成一份。
  4. +
  5. 冲突才互斥:同区里,兼容组相同,或两行内部站点有交集,视为冲突,不能同时放;否则可并行。
  6. +
  7. 冲突才排队:优先级、到达时刻、等待时长只在冲突线路之间生效。不冲突的线路互不插队、互不占名额。
  8. +
+
+ 兼容组留空且同区多行都为空时,视为同一组,整区互斥,与早期「同区容量 1 只放一辆」的行为兼容。旧 JSON 不填兼容组即可沿用。 +
+ +

3. 配置表(交管策略字段)

+

主键是管控触发站点。同一触发点多条启用记录只保留第一条。未启用(IsUse=false)的行保留在文件中但不参与判定。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
字段JSON 键含义与配法
管控触发站点TriggerSitMagCar 必须停稳在此站点后才进入本行排队。应对齐现场停车点,不要把路口内部行驶点当成触发点。
管控区名称AreaName同名多行绑成一个路口,共用等待时长(取最长)。空则该触发点自成一区,相当于单入口限流。
兼容组CompatGroup同区里互不干扰的线路填不同组名(如东西 EW、南北 NS)。会交叉、会抢同一段路的填同组。空字符串与其他空组视为同组。
优先级Priority整数,越大越先放。干道高、支路低。只在冲突线路之间比较。
等待时长WaitSeconds秒。同区多行不一致时取最长。≤0 表示不做插队。用于防止支路被干道一直堵住。
管控区站点列表ControlArea本线路穿过路口的内部站点,逗号分隔,如 10,11。不要把各方向排队触发点写进来。空则回退为触发点本身。
区内最多几辆ControlCapacity本行容量。小于 1 按 1 处理。统计范围:占用本行内部站点的车 + 与本行冲突、已发启动但未进区的在途车。
放行后启停字节ControlReleaseStartStop兼容字段。MagCar 放行发 FASS 1.0 启动指令,不使用该字节。
启用IsUsefalse 时本行不生效。
+

3.1 运行态(不入库)

+ + + + + + + + + + +
名称说明
到达时刻进程第一次扫到该 MagCar 停在该触发点的时间。开走后再回来重新计时。不写入 JSON。
在途占额已对该车发过启动,但尚未占用本行内部站点。避免「刚放行、车还在触发点」时下一拍又放一辆冲突车。
+

3.2 进程参数

+ + + + + +
参数默认说明
TickMs1000扫车周期(毫秒),下限按 200ms 夹紧。
PendingTimeoutSeconds8在途超时(秒)。超时后取消占额,防止启动失败把名额卡死。
AreasPathConfig\Signal\mag-control-areas.json相对路径只解析 SimpleLite 工作目录,不读 plugins 目录。
+ +

4. 交管逻辑(扫车每一拍)

+

进程启动或点「重新加载配置」后,读取启用规则。此后约每秒执行一次 ScanAndRelease

+
+ 单拍流程 +
    +
  1. 快照全场车辆:站点(siteID / GetLastSite)、占用站点(siteID + holdingLocks)、是否 MagCar、是否停稳。
  2. +
  3. 启用规则按管控区名称分组(空名称则按「#sit:触发点」自成一区)。同区等待时长取各行之最长。
  4. +
  5. 清理到达时刻:已离开原触发点的车重新计时。
  6. +
  7. 清理在途:车消失、超时、或已经踩到本行内部站点 → 去掉在途标记(进区后改由占用统计)。
  8. +
  9. 收集本区停在各触发点上的停稳 MagCar,记为等待队列;已在途的不再重复发启动。
  10. +
  11. 按第 6 节规则排序,然后从队头到队尾贪心:本行有空位则发启动并登记在途;无空位则跳过,继续看后面不冲突的车。
  12. +
  13. 放行动作:先尝试停充,再 StartMagCar(FASS 1.0 启动)。
  14. +
+
+

4.1 何谓停稳

+

状态不是「运行中 / Running」。下列视为可排队:停止中、充电中、WaitPass,以及没有 pendingLocks、没有 occupied 标签的非运行状态。充电中的车放行前会尝试 StopCharge。

+

4.2 占用怎么数

+

对某一等待车辆,只统计占用该行 ControlArea 的他车。排队触发点上尚未放行的 MagCar 不计入占用(它们还在区外等候)。本车不计。

+

占用站点来源:车辆当前 siteID,以及 status.holdingLocks。任一命中列表即算 1 辆。

+

4.3 可放行数(空位)

+

空位 = 本行容量 − 占用本行站点的车 − 与本行冲突的在途车

+

空位 ≥ 1 才对该车发启动。容量 1 表示:本线路内部(含冲突在途)最多一辆。

+
+ 在途车若已经进入本行内部站点,只算「占用」,不再重复算「在途」,避免一名额扣两次。 +
+ +

5. 冲突判定(能否并行)

+

只比较同一管控区名称下的两行(或一行与一条在途记录)。不同区互不影响。

+

满足下面任一条件即冲突(互斥):

+
    +
  1. 兼容组相同(不区分大小写,去首尾空格)。两边都为空也算相同 → 整区互斥。
  2. +
  3. 两行的管控区站点列表有交集。
  4. +
+

两组都不同、且站点列表不相交 → 不冲突,可同时放行

+ + + + + + + +
场景兼容组内部站点结果
旧表、未填兼容组都空任意同区全部互斥
东西对向直行都填 EW可不相交同组,互斥(对向若也要并行,应拆成不同组且站点不相交)
东西 / 南北互不交叉EW 与 NS10,11 与 20,21不冲突,可并行
组名不同但抢同一段EW 与 NS都含 15站点相交,仍互斥
左转与对向直行交叉建议同组,或站点列出交叉段有交集或同组互斥
+
+ 若四个方向都复制同一份内部站点(例如都写 10,11,12,13),则即使兼容组不同也会因站点相交而全部互斥。要对向并行,必须按方向拆开内部点,且不要把触发点写进列表。 +
+ +

6. 排队规则(仅冲突线路)

+

同一管控区内,先按下列比较函数排序,再贪心放行。不冲突的车排序先后不影响能否同时过,只影响扫描顺序。

+

6.1 插队(等待时长)

+

当同区等待时长 W > 0,且两车优先级不同:

+

高优先级到达时刻 − 低优先级到达时刻 > W,则低优先级先走。

+

含义:低优先级更早到达,且已经比高优先级早到超过 W 秒,避免支路饿死。差值未超过 W 时,仍让优先级高的先走。

+

使用「>」而不是「≥」。例如 W=10,恰好早到 10 秒时仍按优先级。

+

6.2 默认顺序

+
    +
  1. 未触发插队时:优先级数值大的在前。
  2. +
  3. 优先级相同:到达时刻早的在前。
  4. +
  5. 仍相同:车号小的在前(稳定次序)。
  6. +
+

6.3 贪心,而不是只放队头

+

排序后从前往后看。队头因本线已满或冲突在途没有空位时,跳过队头,继续检查后面的车。这样南北已占用时,队头若是南北,不会挡住后面可以走的东西向车辆。

+ +

7. 放行与在途生命周期

+
    +
  1. 判定可放 → StopCharge(若有)→ StartMagCar。
  2. +
  3. 登记在途:记录区名、触发点、兼容组、本行内部站点、放行时刻。
  4. +
  5. 下一拍该车仍停在触发点:不再重复启动,但作为冲突在途占额。
  6. +
  7. 车进入本行内部站点:清除在途,改为占用统计。
  8. +
  9. 超过 PendingTimeoutSeconds(默认 8 秒)仍未进区:清除在途,避免卡死。车若仍停在触发点,下一拍可再次进入排队。
  10. +
  11. 车离线或从系统消失:清除在途与到达时刻。
  12. +
+

重新加载配置会清空到达时刻和在途表,请避免在路口有车等待时频繁重载。

+ +

8. 配置示例

+

8.1 十字路口:东西与南北并行

+

区名均为「十字路口A」。东西兼容组 EW,南北 NS。内部站点按方向拆开,容量均为 1。东西对向若现场确实会在同一段交汇,应把对向也拆站点或改为同组。

+
[
+  { "TriggerSit": 8,  "AreaName": "十字路口A", "CompatGroup": "EW", "Priority": 10, "WaitSeconds": 15, "ControlArea": "10,11", "ControlCapacity": 1, "IsUse": true },
+  { "TriggerSit": 18, "AreaName": "十字路口A", "CompatGroup": "EW", "Priority": 10, "WaitSeconds": 15, "ControlArea": "12,13", "ControlCapacity": 1, "IsUse": true },
+  { "TriggerSit": 9,  "AreaName": "十字路口A", "CompatGroup": "NS", "Priority": 5,  "WaitSeconds": 15, "ControlArea": "20,21", "ControlCapacity": 1, "IsUse": true },
+  { "TriggerSit": 19, "AreaName": "十字路口A", "CompatGroup": "NS", "Priority": 5,  "WaitSeconds": 15, "ControlArea": "22,23", "ControlCapacity": 1, "IsUse": true }
+]
+

效果:东西一辆与南北一辆可同时过;同一兼容组内容量 1,同向或同组第二辆要等;南北优先级较低,但若已等待超过 15 秒且比干道更早到达,可以插队。

+

8.2 单入口限流(旧用法)

+

只配一行:触发点 8,区名为空,兼容组空,ControlArea 写内部点,容量 1。该点自成一区,他车占用内部点时不放行。

+

8.3 支路防饿死

+

干道 Priority=10,支路 Priority=1,同区 WaitSeconds=20。支路先到、干道后到且时间差大于 20 秒时放支路;否则放干道。

+ +

9. 现场操作

+
    +
  1. 确认已加载信号插件 StandardScene.Signal.dll,进程栏中有「磁条交管进程」。
  2. +
  3. 将 JSON 放到 SimpleLite 工作目录 Config\Signal\mag-control-areas.json。可用迷毂数据中心「磁条管控区」编辑(含兼容组列,需较新的 MiGu.Server)。
  4. +
  5. 添加并启动磁条交管进程。改表后点「重新加载配置」,或进程内打开列表保存后重载。
  6. +
  7. 状态栏可见:规则条数、触发点等待数、在途数、扫车拍数。
  8. +
  9. 诊断通道 MagTraffic 会记录放行:区名、兼容组、触发点、本线占用/容量、冲突在途。
  10. +
+
+ 交管不会替任务系统停车。请保证 MagCar 到达触发点时处于停止,否则不会进入排队,也不会发启动。 +
+ +

10. 与 Mag2 / 其他交管的边界

+ + + + + + +
机制对象关系
本进程 mag-control-areas.jsonMagCar触发点停稳后发 StartMagCar
地图 Fass2_ControlArea 等Mag2CarStartStop=12 等待,放行改本车报文,本进程不介入
TrafficControl 点锁MagCar / Mag2 路径执行锁站点资源,与本表并行存在
交通管制 traffic.json区域互斥钩子需单独启动「交通管制」进程
+ +

11. 常见问题

+

十字路口空着,四个方向却一起冲出去?

+

兼容组未区分,或内部站点写成同一串。请按方向拆兼容组并拆开 ControlArea。

+

四个方向谁也不走?

+

把四个停车触发点写进了 ControlArea,容量又为 1,等待车被当成区内占用。触发点不要写入内部列表。

+

改了 JSON 不生效?

+

必须点「重新加载配置」或重启进程。路径必须是工作目录 Config/Signal,不是插件目录。

+

Mag2 在同一路口不停不等?

+

本策略不管 Mag2。Mag2 需在地图配置 Fass2_StartStop=12 及管控区字段。

+

容量填 0?

+

当前实现小于 1 按 1 处理,不会变成不限流。

+

对向也要并行,但写成了同一兼容组?

+

同组即互斥。对向要并行:不同组名,且内部站点不相交。

+ +

12. 逻辑对照(维护用)

+ + + + + + + +
内容位置
表字段StandardScene.Signal / MagControlAreaModel
冲突、占用、容量MagControlAreaGate
扫车、排队、在途、贪心放行MagControlRuntime.ScanAndRelease
进程与重载MagTrafficMission
迷毂列定义MiGu.Server / SignalDataStore(表 id: mag-control)
+ + + diff --git a/Doc/磁条交管逻辑与策略说明.pdf b/Doc/磁条交管逻辑与策略说明.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0e78d23df6f73041042d18d9a01b87cc5ff357d5 GIT binary patch literal 443041 zcma&N1CVGjkTyEDZQHhI?%1|%+qP}b+?hMJZQHhOz1e+Rwfm~}{qVi64~kyc(Zs;n&XIsZ#?I5i+S-7g zm5zZxn?lXP*4WO?i9lAFfRTZYft%nrgN=ooz@3dno034#-rm|o&BRd3!kM0xnVpWA z?YD@OxU!5i4S}_Vl?j2EiIJ7vFHqdXz}VWv$w}DU(ay$%o{^Q2?pNAx4N3;4296g0 zRhSZrUf$8p*u}`?w;f7W76$aciW1oTqJKI6*+2_BTM+|i69NhmE+z&hHUqvu;$-ZM|IZLUJ}8r4rG7h%`M*0(Sdf4bir&cJKd7`Y0mCnq{7Odajl3ba0fG$%=63eeW&_j{9<(wMIt|1JASuoynVD77gtxZMN>peN%Zwj zs}9NImv+11@OkxW|KRKLaC*7g%lZI0yW05rGAQhCBLR`kd+#!McW)2Tu8dI3{82-* zWkRD@G1YJ(uwz0XD|%$H!lFto&P}QOD7>m(7E!b^kx?c=Mpj6gVrQbB`1B`f(g1e% ztzWAnvr4sMRyU1XH+F)Fx~LyqE_Q0<;O9JHm_Tx2;FSr~d9K?sHKl2VSl`j~_o-bl z*0t<rQ8|`FU2&m zsS{RWRqvsKo?=qRFMCl0!DH6L)1Gc!uPGo8b|bTDx!bg%3G^qv4Z_l5svHu!WhdSn zxw#{<%T+1|Vf^tKo!|0xh$IWzP>s z)gcC+t_DlG4x}4m|M(Q)X3C(jA@vS@r2RIgaMv;}i}G{h+NC4vvJdCKRS&rr6P=gW zg~yFY-*zwZDr}q{UTL?TueXs8Kfa%j$C)-}{TrB%k+bUplEcYH=f)8|a_x2;vI<&> zg+%RzgR(PN0Nm};k)5(kg<$E8qB#CCuu~X!Qx_TnGk+g27Bw@~zx2Sp%)M)W(gkJ! zG*=ju;sOcu0^^g0 zk6#1pmjzI=@~wDZlO8msd`V)c<>oyB`sjKj2J3ztpA0cBUrHOlX5-~XWm4)e!ZHS- z+8;FOy+TsThRV`oQ@gGkmoK&-HcV+VC320oy|mI_T3hI(*4{)@=kL0%4k1TzXAVG5G2 z%pWJ~JcF-DuY#dw&>C;$MYfrzSN-#c_}d5{zr`o?svJT+7@Huw_DB4R_!>)L#KxF( zU33xUtqzO8D*}N(b%WS_79hbf`g7AsIfxG^E)G#={NfZSUdr&&=gO}b1`CZrmZo(4 zjK)~Q@*>eHizm(=oCF6>q69r+W37?pJTJkMD?-H)=MW|RoE&Z<+EQ8dM7pd9f>C8f zO{D1}Cmj^v4wcXICUx?k>K>1hC1i$CpDaLGd9Mq)!#Rq8m8$OOg1gPsx#VgVY7t4O zD}r5F;0K5HCeIDHIpS<*f_Nxpe25^Zh^c;TIWkNEC5h14bU^J}-7ej7*qm(}K zC?4XHmIsvdKUtT?Wjh#8D}&R}iDwW86KT7F`9G10t&Rbt1m+Z+bi5 zXLhChU0-i8(GS@^#U)ekEmqJycM(AnsZtHY9_VCBni()+sb}y#IimYB{M|k;TDiWT zH7z&a%W^w@KU+7`elL7$XJPoVHz(}eoD)1D;tNdCzqrrq%}*({pAv*KKMN*A88R{Y zq_N9SCjWrfhqx8CpFRGc$2h;Yx1OGF6RY)=(jqshg#bI7h7z6(4C~D3mpiVu|3F@h zX!G;Zr1@4Tk0cGk31O1=w!q8kZFhGBk8PYy;O}gz;Ew-rO4+{OFKoOlx0_cPS<$Xx z6vp7Ml}a_A5oj3EG^D*@R7l6cZ zG`RT_KR`nM7z2jcHQ;cf$X2ccra)D-1E<_4N6Tk8t5jXiUhYFq1z=7Qf|De?0Xs02 zfHy>ivB4y;A|(;Ca<>tvoItcJ9tCpX%;7MdlQUV$;H>A9i)L~8K_uD)I*OeDHIQ7cf;_8WC21Htkj=l-vh47=4j;WE6kW~W%bpCM|vNY6yVB~6##R4M~pih zma*D4fj=g;ILNLC&qe_@r|p2@$ZEjW+|XX{)c~AZ)eJ|ppC1CA_Ffny9v=7bV^!U& zhpqlxNM;Mmj}{-1a9%rc=k&Ohc|@}}mh~UNd^BpKvz)op2g&-Y9+-=?hn1R4hKxI8 zwYh-oaC%@3P634C9IoZv%q4}trqu!K;bLrESS$jCwkv0wdszXT!soY1f)>i^)gl+> z?e{bDqhQu4dR8q>6_s#S)?#h@79Nr~T9;QphC%{?Zpa|}FHVVV>^Q!t2gzg4&u4;+ zB=55+K;Q88FAKqP2gzTA16H4e7&%D4roE=sVXER7_b?#(iyxrp`YHLi_0=4?z;yq><&Jfrw;z zHs&8N!%B^=xDPJwhK>+|-pj~{$YWmjSJ^}Mv16zNEs$a`ZKslSf)WbR6RH1FRQC<7 z3F!3xF70hFMe2%aq`h5ejkp!;HkXppA?2?=kN*K-qwlIftiMA^MXdNMj~L+GP3mrZ7JxO1fgN*iAdLnjOn&G1~ccqnZono9; zdsTI^K;vovVnnpBYI5GwwwrIWJQ)84Z;Wp{{hV9e)#w zb+}H8ZPWT%mnYC1G2JsWOByeTHhvRAMdTMNnkANEG0#;&mXD8Yo>j9OEZ9>mMR8U2 zR?kW)P7N>1tQPENE_df--8V)94)_-b!uZg@RH#MIaC^cCCun!u4hnbiFH?WG(RVsz z4JPX2=7f3imZ%^K$9j?X*+Lz$f#&vBJ&3+`lw2)+lK)V&xMjXhK)*14|N?I8gaB8lC{*(>KF* zblKoj41@8!v}cHXa8-u|rzp1jM5UsICNzw?ZAzp z^y$wybYmcWcSN0q6;0XQh_3+*bl35lAI=CZV<24sXJqRQYp@*3vaaA`Y1{}aCtPkr zgk`hDX{Fx`B}UvT6Nz<28DVAIS`|ASzri)$K1n-_!hP(>bAlT^=7DbHxZRhY?aDw_ z)}<{=2;Y`1gyYB=(wa0uc}SRc;GttGi#x6jV6v2aWmTeFL0sjxk>6NqJD|o@Wm?hX zmlU~8p7r^dt60DMVW*YmTC}V^-QMqJU+PDcM(oJSSfekha>o&^A`7>R-Hsqc!icyp z@UI?MZcW0-KO+=cWDygMXnFol_a1bgHB`SpV7cE!bRH7l90cntB+zEDFRhdnRN!^; zBU_Zq#%d3Ub1l%9>x?2cRdypYRd!-84np(7xiLddbl!u!Hv&$)Y~)I_aEWhx5EdB8>j@*;MM*PA-dQE z)=uiOWiEF$apF#`*p{c;Y6LHLHFNIU>Ub~rmRYLKB2uwp1i>Tf%UafA{m^SA!9*?| zP~CG8lvxEQ)pT>@SRgr-NGNlQ2x@s%HL<>y_SkwlC*T_>i{F|K)GMe5a};$5;Y+yg z4T9Z5T7MZH{%#>0y&XcE0d65Yy&dxhE*U=Ndpd;XGHczck|kX8?=7&BR_AQqB@33N znjh?cSw2W&OSot+On-(7l-1B{Z4WH3|iYspM1jU z|DnD=p}K#_F#B;{$By95$<2K$>fm#xxx)3RDebI-uxNPY|Kww>@__8C>Qn^UwO1 zK5zueZ5Lh36gWf0y=wvcSBZoQ&z{-4))V|T3O%^>x)BsZeTc86Jd)8YnxbHVN(wUn zSobirRlqJx6*aPY05!m{h8-l%H(LVF{J3H6K#wWM2Gg~AArm^K7qTxK$5 z(-x1oEr&-GYg{>`F=<4c+oVG1GEN9pvp%C_!l<}Tx@lG!kJ!beVthr=5oWh5Y=2TjFv^Ug**<1e+_&M-M8wy?Iff z0B|ohdV# zLNeNS?*`bkHR#2fqh}#3|*l5bb!7tf$BTg(QLMr`s6fJ;3gj|?DiWb`BkAt$0dG9Yj8qJPB=nea1Tpd8i-Cey_=DPFNZ8IBX zPQ>Pmbf4U7rmR*h9lJZfAI~9@gK?x}oulRtsQe4gWv`nnLfo}lNZgZv!GNA*#sVCAF3lI6 zzKq>+(AarO+T_i;AH=N=n*pum_m;K977HF31`XBZERv^g4Kpe>I?4J6>CL;-2%92r zZA9w-!1}tE>t(jX|A6z6a{}tvdvafJx>pFnGtOF+z0~yq160ueP~Ut>@aieH&8#!) z;qf%QvTL&~XoZ4+b!v-jezUe6VD6m;TD6D#v6a#s)Fi~0y198Nb=&EYH`78tGGkzS z(EChEZr;uNE{aPiX2kPrOk7X1DPQgGyl24Jc0o*aHuVk@%f}Bz15AsRh57Ok(fyK5 zf4uATL8Q0G%JlAHd5mCtUQOzbiqRSA zW9Z7>6NSIIt>)`vdA{-p<1XTVw!V2b9%c(cuie6(blFF*e=&0x#nvo_SfK*TOA}7(e{0x>O9uVQy)7OR-%io5-LAMHJ z-`j(bMI=+%jVa=u0UaO*ZK^s~10+%jpI;^3@QN&Nau&?SnE9xBB1Q67=GFpDa3cq{ z8N;nl9VuRj@z?ELIajEuwv6|;yL3^0aWV(7Ve^aegELtx>N1IRm_By~Yc;LC=LS1h zKc5L1`=c8blNU9<3mJp6CnNB|lh~02>rE)-X1EAH?SJs5Um0>&CaNChbQ^Xbyrs)W zto`~*?iviwX?Jg&DlC%~`6oHFD+%x?6+;O8lD zx+ihYWABRlH4)dj4G}Pp+XPrjU{6nSeFt)Wv+qDJsxA83#L44iP-s$o>stGQ>##}rrbixU3o#aQHA#5*~q)h zk?C;IwbV^2V7w+aB~5MxtA)0dx2^wxYjMRd`9?jl8is8P>h_YYjVw(<`%5Ot9FTlE zPB$dQ2$Jjg{#n?8Wy5{3q1LA+c(^DxR|SV#5iZ`yUt{G2_$c??Enp8}au# z)tWiS#)2y|UAbo%W-*+UsPi5VaHhEvolphhFNKeKd>1h0CIeBNqkOJdPYEjwKr9zo z0s8Avtnqxk1%&3H<2q5G5aGmtO_Z{vEK8XsGw#?f4P`dti8E#wQnxNl{3PQqnh7j& zjid}Er1hU*Cl^-lb`Nq#M$WHUJEs^m{vVeK#;Ce6dRJGYeCod~R-MM!Vtn>eTU%f;%ec{9Z3Elc%>~8HEHsm9v889KTa$w_l9^q(4Z|Wxjo8z3x5Tx<=Wxv) zb^^Bc_mEv}`h&;{qQf2(?UPU%iB_cgLQb$BD8YH_1_lWegyc3Q2$AyA0t=%d?es{% zN=!M;byvVjl<+*yQC;N8QbfeQuzckIDq0HHC_<1nkVLn-NEl15Db+~ymn5E+>yboA zGiuybk|3H&)G7rDCY^XKWavIG+Jw2VrEzR0_F!lr;-KgADUW|jN$jY2 zTJ>F0Wf*Q@7+h1$(w#|jC%GK|3V#h@%vpVsHPdkCfj3d3ERPnmRdK;UzOe}u9&@f& zSWNXkKEdRf^`JmqF{%6>Fog$2Wb0HQ^+7)V>0~7Vm4_xxc@dHfOCWNY?Szp0+~af% z3eT~AvcL3~^H{B4(U3>_--2Ly+&c~nv=y1t;L+aY5uSJ+jX~i#HB9xC@X(~N6pw;R z_zp#Q;dwRsgk{;(*)-1w9LK&3jp0+@|519R+02{%dgPw_qjsP|M`5z&;QLf!NDbVwQ;m1d?uN(eo9#GeQ|sSETd9aNt?8! z_;*+3>G|P^SECSqX@j5cfO>m9vZAF&i{H^N=pxkTf(qRdYPjSg5p%hzshQ5% z5I>C+`5jO%>0Y-k6Wn+=`CMSz0`(XXPgL2BJZF>#GsAaqu`dC!>OjB>4?BywQK|gW z>ZqYBq6;Xae%U-22*V;JAK5TAs~q*r@_PaM?kGdEeJnFDqkFf(2f< zk9X^^kSc*M%XMgM(5&?oE@dS{W=xHEjF#wmh)PLUflIBkb|3egWkqa9^CoQC2P5&`%R!q>6>l8IU(5*5AjxXyVx6%ay2A6O8f62><>|E#UD3b5a*$Niz@qe`k8?oDvCNX0~gRIyj3j$^F@wg5(e=y#(bwHjQW0w zb33MV!!?S#hCAU>WtPn;2thFhISCeF#^|zj?6StJHhjkZB{qzM*9Q6Ax}8Ds{Xn2v zRLVV>WS-#vWNmt2IPanvQJ(q za}xK{WPze-5V3p-6Tu6SYWOY25hDuk5YZtc;b4$(M7ZjPfwKKA#O_iCp@2W{ldy^Q z<{nWA2XpPE>bVNDJDk~oBeqj_fAh;$Y#|Tq8~Ji#gWQHaiUl}E&28mz4aT8+f}RFA z^OdYHRZi`jz^)p*4kl@%J8^%PQWgBo-`lJx zy5ECvR0Zq^DHLPyAT9ABVudQ2MpbJHz|kLyu@I!u=fo0}y?23S8ShN#O3j(eUua6u zPc+iuUZl+JMFqPc|@md&!Iegz)jV%F*$q;}jw-ynT)P^8$TcNq49fm=@2)m)6rNJUK;<$EoJ z&`T1rCoKqR8|dAQtg~q5dN1P}~s}mkw%(#V;DB-0cN)o#4sp7#BY)LftGjLn5+K>ycsbv7>?%cG2 zR*N&nb12aO>J(xS3{!HeN!gI3-@six=G7g!&R=^~cN&mTU)2fOfVS5jWKYH+YG|uE z2xxXVk!t$U+5sBAWZ?B|^@l0?q>l$p8R+{g&NO@Hbr2JX%06wnB)Lo)>RW<@5V7M3 zYJThga~S%3ia1%bW|2N&&GU!^`-o()(jeGoigb#%C;t{*nq$Goi=0gQeS1wkSlq(p ztHxsPZjzxOXt!&*#o2~89a?kvRn?oxBVtp>uo()A0`qaciTZ9nE3655;ed;^jIIgW zKrhbg`ihnM{ElU(huz}U8wY*MxEDuipV2<2wUevivI=d0+bv5kA_xyi#x$!u zqE#`lH)K!%JPt(<7vkPJ9taPW`=;uYvz4YQT|l7Q&8(CB+TM$oiMq3U@h*9hTo;&L zKX2xWnEEYCEE&tNszA1vWN^5o!tVetzvkQgALC7AHP)yXm8)cj0kwl8;m^I+ zra#9!d`q3zD;S2FDTM>lO|Jha>xznE4%Q=HLeU|Q$!ns)dtGWZXJ)cCT0a8t`H8iV zX*D5 z8MJ5#T~BUgFzTXQuptg@tGj)MYcN-RFsrY{xE9qZ%`j41K%BlFc-M8qjYfWqE`X(4 z=%byQn+M=6Cp&uYto*l1`ht$bntW~2=j!0oN5YVXck&F_&ng|Y9Uh~UKsNA?x=Jq< zis`eNW(a89DkF~v*H9;fV){{`XMLooP~N!zloGliC!rM7#UcMJ&hm|A>sREDGv{d(xMR~z7v)U&+Wyd6E z+3|C+(xou5@mfN-9pCru^9nypPxsd|S!|an{!y&c`wsAc86~*W z_$03GNUrb!7fZ}S`SRycrRm$*ikEa=1(I=d0`2F^|=_@B#*24DZ2kw;fH}$Yl~fc84_~J6#wGR$9_{&i>Fy9RHI! zJ+UU{7;0go(DkA+wBt=o+M#Sr6~W6~D?y7b4jEDUsci7jQ)wMZq17g009ILIxYxnq z$S~b@Oa1HBvh|&Vc0{o>7B?UYTj)SM3rH z3-la)n78%Tr|>_Ea;&Eg3@fY(Q(V|MQztCd(8btt1D6~8&%{uTB5>IAG?vLsUh~t; zC6-0u?KU$};b~~B;}|@a!_Itz?Mp%7m4Af>j3ip=@R)czrmsFfHbTvMr<-ecR{Rl& zSQ!ePFEXbbrt#2Ud*oNXNq(at??!Qr7x?#GJ?7VpB+aX>#r-i-3H`VO`v*E`lH|}i zTXh^(*Aqp52OhSv4nFKHDOu_22S*;y<3gmr9(sJgu3zGQ-o9Tf3WIuieB3`i(Xim? z)XOjwANEGrea)k;>GNpW@O?c#0>dBDro#NX89DKnkS&CNqb#^0HwZ3sisz>|fRHYP zXB~&TUyof~_eCQ?xyhp9sUQSo>;Msaf~!vhS|d1{w2KG$1KTzKqUqH_eFpXi`IAlC zSQK>Hql$3wE|?SV%=3iQ34vj$KER$5aAv}Ib9gbDn;serTy|=Q$1Kw0Hin~1vy3rT z7~f3a+aAs?Cx-ddC9(+T9f?U6oyr?u0*au=`*{>a-dC|4O6STreEcQ}TjLiy*C80L z89k!-CKiQ_(^)-AIPS1Ce4Ez|R-!rnDz!LAi@V+hb-?H4&g6Ce@!lc)fU0V)s>3XVbwB+KV1iJmY*6?(>p?$=kiM>YZY z#KpAaI(02b8yfVr^*NC2J!aE%fHjU^dEg@1zP(4^&0izqTXWnESO=Y?LwyyN;pq$V zIOLLj=*J)OP?Kglr!@2SdNWWN10vyJEP(2B(d6Cc?!9U7w~DG92^Hr6v@OS0aJcV7 z5_k}>M~T4BfREgxD7v_F=T5A7D^JH>4$inQE*R`_5VW90!o(3=9R&tUh!&zjkD!a} zx?Asru|bQkW)-rEOUUELNyjf>h8Msl_)3O1lZY2`$zv}Px`wdfHa-&- zL}&7JDA3bS+CZ#8)uiJYfY}#Aco|Afac(yZRlk3D{Ar^5=;z?ZYCVbk}h|ho+S0!OGp{@s8|G5A01p8oL z9pte_)WU!fMU(kkYxl)PRZi~dg0HO@+1(2gffek_)G+TPK%D;s5o*mYV=m0p7$_7) zQ${<2W?;2(&}1X=aDQSm z+O*i*dGZG`7hAS0qQV;aI7X2rIAM$bDQk^U7S7@jhXjg#<#N9NVUmEgJs+R~uB{o% zLZ3uUod>svNWcuh20?9mP}Y=N#`)PxLU%Ra^N3o-D@)QNXi1lvgA3%J{KzzG*>^QMV7OuRS9`9=f9BpZ?Ia>MCwywM2jq( zIS%;)S-?q9edCI>WKk=oS3n1#9CI_a_(Iw|Mlj>LfeG0fI9 ziE?F3bILn}wvplhM99oIrfP569P}`r%!=M{U)IB;p+5W1HlQuFp6YD*j3?18u zN01wC2za}&$%zW`5|KlfkKI+m>s>ssOGGG-IQy%Dw?m`p2;mtKcWRFPv}XMwLO6m^ z5tAURGSK1RyvjH4##3U1Su~T;z5oeVXpB)*`l@G9=WRQCa>!UbI_{MEonasSueC0K zL2J@5_v>w(P9c2%%SqbDc$+H*bF4Rj`bl*)20vK1Vn6`&@NweInYil7d<^@LTf$`ypSO^{oagW=iR@Eg#z11UCIecSc zZC3*E`2&_sn3^-1Pr4OV;huJ+hBBb2V&Q%-8jvelq8V2Y$7t^ITZ@c1dL~ehYpDkH z7F>wlgg~-lYoN>8Z6393)|o3!y@GQeP$bH(gJa->MS>6V2?~nj0SaO>6_t|EC0K3K zY_~$(K1JP(=#8SRqz_GNp;wJ}brRXkp_7^dH?_8p+S|X5qX%&@$x%N^b`o|}4e~B`fN^W=+x9Rz#1JOy+`~o`3rRuM1U5pKxX=Wy_ye$4?QIPY zKynS(_MohHVIz=c%unBeyab&{2YBn4{3C&fhyn-$$k04x*AX+!K;@xdYv z{?407JYlv8l|-mhhD!+`giPP_=qm}GW(c=a9mkTjNe_4UoVcMoweyd$&etJoN{R#6 z4z|q|%f~Gn-5iE+WDr3j6HONPxtnnbk8N7L#Z;Bsc@Yigf8-2X@Gs^!7>CJN%wuN) z4Wpqv)={Ip?>#yTx`wK8ayBz?Q?1^tn(?pr=;I&`i zc!|qR=x~U34aJM-Xkj+=s9--2`?Q}R)+J?A(TMZaStXTZ zymh7qslJQnQnyuWGt3+bpTjWncuW_Pu(`kRXM9&Gs_*8p1jNu;!&<_4{|i|3w~oNA z7S^)YeZo`1RufcuEcplnARaQ_%Nr(>DT4?_k*Y#r0zvn$Z|(}PE(b*q$>;wZ*Y_IwvVc1J|qUX5jiHu~BS=2ovpg*N4PeV1!^ zuzLeiG`QNdZSNePU5|9l$~FfF z7X1eeRf^ZbM4Tl(BVLB$C=z6;z1c~U)qmgZJd)DTvYzPl1UFAWg(Y&gK(XE2=EB7e z26JVE@2bKg^nstiak`ArH;zNg&n2quDwAKR9d{l8F1Q^h{hK|yD}*MLCQD_bNUHHf zQtET@Aq}%6u`R71FImAi(zN$B?>2e6m~17nQ4^>D z1<2rHNiqg&AmT=?+lfL0&CxV?x>ItFlS{ls{$0_=TodJ5{wtBR|A#|brTtGmdM|*J zF<5&wA#E305E>klG&!OL10C&UnCwdC)tPLJSDeRozHyf@^CnSHYD(=YArqGmB&53< z{xn(aAHkn}pT2X%x^^OQ1rLRpF!?+JbJ%@M1s(IB%ya+YJ}cN3GrOkYNkL)s$mbNR zJ~(m7sz!q@LPUq_Rc*yNy_>)n)hGbL7nXv?@;(U=1+Ckt9xh< zk@Q57jh}ukD_S9!M?$Vo5%6QX^ylC;na6K@GW6W`iDx2PoD?6@Ny+{CsZ}Fk2MYis zU)QK=F45CxRb1lCB~rqN0@zy7wSn=(=;U+gziP9{X+QB3zJwf6F^1+uC`>LWGvRv-`gY>f)a}lGrxa^ zbhT2A`I~pTTEM6J@J=u#W}=VN4jqz9IKEd-McMWKUgq^-qRK=UyzQM#)Sx4G?hj*e ze_K{kXj+InDQAwd<@t7gKDkZNr|HobN4v~u!>4bt`;Zsl=3#lopMrcO_P8MYrdPfWoTvUa=oGX$+B!Hb z=V^i$eB;c2GK7B_(}L9e?^4g)>T~A?^@Tk?KMQdaiw+KDbJy63BaIKh2iVLZ@WiZ2 zd-TXzPt~Rqye9iZ5v*!^#K>9h9iY+0j1qvJu7OY%eah*60gd_-uss5r_NZuj1Ui6G z%KWuf#h?qoXT7S#w5xdHMLLAEt^e^Nt_t8>UJ9C%k}4)u+RNpfPo#aBz_A!p;V_PM z290j2!5@XP7<;@O3#by(tmn;Ekcw$M^mH#sMV)75aCidNB&JP|JXIi|UA?dUrLB?f z3ItUF5mnk-ax;!7pYEx&XJrLzpH!k&*r*Za@3={tUkGW~u7CBj5#lg)H*qe8&qp-( zMKcKh#MV{&zLs-@_Ss^-dk-a`3g~L(7}jTAo(;2NALuXJf|Z z28U@fv(O9ov7zM;=%GktrsdJ!G_hTU9UtYP7o|K+TV7#pb$)hXQrH%A9C3m;8W4)G zh%B&>L^e%09gip@=OQ2tIYCp=D3@}u9w|V23)UPx zm84a*{Ik~Wlyc57UKtboDI82+$vGhy;j~RcU%YX#RQxri%G1s)W;ws&DV5!dt3uS{ z+NS4ZgcIH*YxNc0G&i%mEJy(~j-(jjjgZ4)Dx6+qe=DMSY9G$#O9C=9XO)9E3(>~h zOWF*a-2BIAojWlvM+~KnI1+9HrELUTqzbUa$vlT$*^C-O-54Y~-{Q49eM(7_+%<}U zsaGPPt_xJap$oXdWf}-70=%J4dymU4cpW+4K1$vVO+g$eed4S&d2+HS${(f^Q5g3OYhJYDu>MdZReE3Sxv2& zHDAAqFTpL?jYdvxtX+g*_=AV0Uo1D0#GsQNg2t)s6*R(a{;K14_eRwH9Q>$$T^E;Z&Ch`s ze%kjUrFWwt<4~Cf)tLy?9I7&L@kpESxqoyWu51sRIw4J%a4Q3|K=5;QVUUy0S*X%d119UuWI&LVD*tz=g$6+hfz ziGj?w(}l_8V)}DBKs;uPILAX`kyD{KlA(zVfaFuO8w@G$YbNoWtdja_zGgr}QV z{YZh?dBXDU9|$BT!n4r_8SC(BiH!Z3Fxy{y_V<%6fgOa4uZFV&m2lv~!YhG{W>kd> zK$*Gr*6$IGjYCmvEkLS z<)dw2DC^_E=J!hjP>006)~{c+@Ti=KT!Qlu2S5Qg+f_H#{-z6#z}nviRKC&p!L za~D$_f6s+{?zOvQfLQay*Jp~>WTm+jCd5{YY3wX%_<3pE3tBKY`qNI7{_EV91#W3T zK8%A4iB-m}fu+LPT5h*rKF--|D;EqXcpCLx;J$030^xKCHaf;~6Z^-7ii>TL2#-zq z+~1Z+fSN;GnRf4o)K5)Ddud2C`y>EXZMO>t%NNl*IjVY`X(ha6{_y((ukff!qLD91 zDn|17BY_Sn*V?~qJqnapxBj^99y3+gy5lK=2)_~lQR_-V5aS8V>t-9}9zx06Q1;+( z$e?v3D&lL4FGN&^Jdx$upE^H~5VyE8%rWoz;axnGFltXEN{X_Uesn%UWMv5ag8#n$ zZ=E?MEb74n@;tR{vZZL_UGhz&H7~^*qX3o?O-wlKIU#nzsz%Lv!aJctg}}~w`LD#C z_@xu5RW4!T;(|`QTAzDP6SgIBxIQ`LKezzty&;Y_Yn-YX+hcHC}8NW~e3(*xmD8j;%`w-)cVm?wr~>9&2k8gqKhaa@KmgLtga@ z$QBXXi;bsB86ubOIjo%Nw!uJMJPKhq>?s?EbT?9q@tvKUnE+H zq@pY>+L20|QvJ_7=L}~a(>&&T-TV9B*ZqFy&dlS?=X}olvz&9@=W}#bKA1iGwuhu9=z+g{lWEoO>)@i-;_ zC!Z9ygss!R_dtI2k8Zx(E>soyPRKkkwYG@m=3KbBF?7U)I@OUUgFACB-3`mtNV4%& zyqS8cTE^69YRv0rdZ%87+uSrNy+wq?tRL~|i%pz?McFX7yF2?1aLZ8*U$XMa*Ow!& z_lh(QJ1Y4^^8Lw5qcW4mmtnWu3?`TicRjc=x%+yRFMX1l;&VTIdKWOj*1(5EF7L+*=@m=*LA)R{IW+Sr2iRGKj2Ktvtx^& zEIZvW;9Jg%r3Sq^yo;E#`{>3mr>BnE`0e!8Q5*B;6#G2r|0%p+-k~XE{GL;9OTKAUxh%Mm>h$n&<+bliqk~I7S6X#7s9g9v_Oe|RU_^>t@`BtB>D1+%ww01eaKM1GfGqOx2L*B+T(#gQ{4OJsM>uEuRQCTcH&rt+tDFD_iBdUkKXEQ@P6{I_n#{J z`u>q|e;2T&^{j;1#^caTLw&yE(3Q?Jk5-@Vu@ulUgI9PNsd=uE>MgGJ$V!IYA<-qJ ze&Ws!(HiEb-~Q2ccX}T6^_a&|{~jR&-ail1x%DhO@KwN@hik)|O3&tTW}SLfs&MGe zrr>$YzI%Vm-;j8^V)3UNy9>{#F7b}6t~f6j-q2Wo;Yw3xW9YYhos%!-eC@X(c*_$T zR=9bsy^pfTE)Bn18`*X2NhRZAE5iRw34F^4bv7bk;cB`0($<+q0rIer_G6-e;$Nkk!Nth0oVbet{+q82$Nt zboZa8n%94tKGZNzjh<9_rEXNrz4(*YHg_i8nE>Az4o`0(`t;ukn$CoZs#%B$Awq~H?_=3TkEniPk%H1(&mq!pd zkzpHT6)~_<#g;ulZ2wfYQ}NQyJFXX-cFt#RcMMAXIW|0L*ii4zHrIZss#%!MGs*~F zEtlF!$-;nf`_X4ztx8L;7YiI4minPi&KulnY7zv`2Y@l|jcY3sVOx9vj+Y)c*KE!&J3?h-vPb7CbV|@@QITB?mP-yO_^I zqQ7=ByA?26y=m&EDy_%f$5O&h2Z>EqaJxQ6MatHG)kWp_t}a812fuh&SG=uC_1tE? ztERUGhpIhrRlVb_>OLmP?a~)15BtPM#Xs5oPcv{%8lsZ)+r_1QV2Zmn0s zn1ZOiIbw4&KF`(MTvg!X^hIOL`|fsUi>&+??)C{$UKcuE`vSYr?&Gqu^&!$rj&^&M zH@=4W{C)VWAhFatog#Lvzq#$M>TYFA4fk4C^%cjLD;le<8?krCq1&mx_af(B$lkd- z<51nj>01wnPSD&l`|NJdcZVAlE)P9WxWCE#!Dllg^|3_W0=H{5dv7VQUR^(^3H~?t zf}O;cJC-)YtS4PRE}g!^;aOz0(PNE-Cz}^)9dt!>PydZlIl+xZj_L=FtZ!??C_*F0Xen~XYJ}Qe|kFE zxr?Vl&EmKeR`@j52*>A(>)&iUb(uNpPs+#rxppNrvHtxFLfMzM$CaiNOWbew-` zE%%zWx@xY&hCxy`pZu@JpU#e4uNr#bgzC%E{yqKmQ&-C_`E>b!o$H6KimIb}s!Xcc zZJQ+%S-_M@Tw$`!IP~NO&6v{8tHZrrOpkMjkF{4A#H~1Wjqq(2&Kim%C2#LNk*}S( zLQMUgv0jk{7xO>thg3J00> zdm`2k7&N6pV?b=r#|j6u4_`}P(Pds}eZsF7BR}0Vi`qMAuWMZGk~bNv*nS&+*ST2V zJRV|JmFpst+iCwx%jdxlFL&76)z44eb(0Ho#4}a*MHy389+b;$vewLK7`pgvS5;%} zvpY;RcbW2@9-dBA2&~1_Fks${X*ss_B)M6z~+ul>Hw8QqU*8&e@_J6S7 zE#&aKY5Phtb%%~x!D#eNxnsY?eDAlh@lE<>Zt0hLk9sbiE9E?MnoQ=;&hbyi9DLXy zZ`tVG%a`?2t6^5>*G((R<&p;tDYf<75ZqtWvlq*BZshkvhx~pwDY*piO!Cq^7OHU^fQkubzLse~(2bGgf`6 zGCrgxeQ4PA_qQg@xRGS}`G@0NlSknnR_u%9)Q+06_uCHrH_8)F9o#xNXNGl+hI{py zY+rSsRiBrY?S8UmfO1Y=frZAZs0E5&4Na$Aca$p6Ryw;OByQ34<6;I0JqCssnbdaK z-@)MFI?0Md7Kf@NOh#mFIK--1C7#wHP}!yH{y3F_Efa^IN^`uYb>e|@xy(rOF7YqV zpTFxg_*%yN2`iK;0$%&3cm{et`!?3~*Xb$ez+s&5p$8p(6?QEN>8;7WoH@2JJNBzn zl=zMAM^;MSo-niFAxAQk)$ydw0Jn*qezKC9;cE1Vi8y{Q_}^P<7p zrIH<$(raS62fD^ZrpsgxvZ(K5TU4>|v2W+OfsZdfEv~FdUg%U(SnTaNDvR|+>VkJl zLiw9nM)KCigRFIYKOeQxm}Wh?Izme|^Jmxmt)8Fcy7t%H)Lpge^a_K`tZst>w(EQ; z+V)33Ab?n&He%=UKS2$$<^2eahFRa=JXOB@*0sXrO2M#ks-Xi;eOB2syC5)0CR7?)mz`}S^70CEx1mpzs{1% z(AvDs}hSev(-YR>~6PgSE@%ZhYl4d}!h7H}&~Ptk%}q?2CNlI&5zJP5o6heV^>R zepOD*=3=13b%#cKGhf9Iw_m&pRZ=laobFwz^6_57V&lY%A6AqU7wA>KwVOFdXP@p6 z^KCPpfBhtWWTWf1r{PzAI9XflTX`?^OrF8wGb??(YVy6eoa@nbYu=6k@vaFsdvrMz z=Vd+W>RAbGvBM!HJ3owea8OtFN-x?rb8y@&#vM{EdcXEPymCH}6 zyP`9xZt?3*7DwM`cKu?!pv=y2!JGo0M1RkD2QAQ=0usl4aiOHU(|)o%SvD=eeEt9f?Oh0z)&r-bc){3SBeH zu4~?jv@!#)FFq$bDFjMsYMg&?!koRcVf`(pOz4oQ8`bU7&lN5{5P#;LjeVS!!PGA{ z6XwpcE4VZH((X@N98a7GSg|`$YWKy4L(Y#2C%rqXZsRRIf9vbX!zPtvPp;|q*7eSI z@y%OwO>b^8)vx#PG&4&+uy{HnX{+VSZYe8f433_q?;rngUeuTwrDLtVr*&<*FR`)iBe%<%XfKTFH1>z#z`TbxPHP-T?aaK)EUn$Et@r5Ok&UK%gNELh zKCxbIT58bN2O2A`J!E#bxy^c?wJGS^*p%B^QfZR4o;7mnIZIe8euWx(hpn0S!pQx3v3-trxsxUrs6YHtnbt+a4_RFYo-7%x^Pr~Rk_Cr0WEOrL>AK&j ze4nA1UVhsCCv}&NcYXTP;meyl7X)P8%(gKInMQ_u48l4m-#EY^{5|T*wcRq;Eyk;< zi?0>?dNH-b4hiq>Z@#6~iJNa6So---AC)V1{YIbI^~gNT@I^%OC60xHdGw31R(?xw zmM-tcxgY*u$7uNr`WKQM8gk;+?v~Zbozkzq>C49O{>Mu-;$Lhr{cz{Nl>xs$U3hgM zr)cfn;YE*b1iU==n-lc?w)%}d-Ku26%MUB{|JnH3e@FS+-J?{hmgd~K@kgoZ*V`wf zm;T8=@aOl32@T*#lz-fEL-1?A7AzmGaxg*RT(MjF;gu$T3{Q^d=zk4C;y3>bBE_>o;pe;CTXT#(ZL z^2u=Lt37bv%G}(%##cF6r)y3J#mdB{D(#dVtx_ewx}g-%>r@H{yk9!f zc-Lhcx9_2DQGJZf3QP1&a+%no+QmI@7aMIIc;bTX>uZL;f4p4(?2y^>8#j7tEK9h#sM>kzjDFs|mVa8O z8FFUC*lDFplyz(Ry_|Mr=MFW<21r5bys=15k-W{nw)er$`aBZoX| z%90;C)}>C$+31?T%?EA66?vtGEBX$;tDD>9UiEgyrRf@m%YJWn-8R~1+E3NNmS<|3 zmK&|;dCoK0#9AX>cd)$XISbYb#ZMaBpMDSZjMOda5_vhV%XPzS&)r?V9vu5BzA(RZ z3~}vr--Nut45s6$L#|e_!}lh5#@x^@dX~{ozSvfL`FE#=UC)gqtfCZc%ZyCk-W}l* zc4cDmIp@dQ)($u65trI~Yn3giGNjPWa-U*g&7rmD*JztJ+^-3I*XNRQ-L`FJp3z|v zo5Dll`%6l{df3px_SM}&U)OaC6{Z3E#yezOCoEh-_Kkcx`E8!1M!$rD*M5D@EIof~ ze8NN1$FHW;=^Ib#Gs!a2v3B0WvzLOSzbK5dw^e$cwLa;U6@(q zUS~9|s+<2Z>Fr9T9mW@G4cmD@229IrB4%%%8Tcrd_&x7^Q%T&|26KImP`KwcRR5sW@S$dOM7Uc5?^?J z{^G|EKEaA!@thUv{0 z*LEb;7ZC5S-klp%^%2yklQZ=VNP6@!f8&Rw7m@34ZCASyJR?NG%Q#`nl9)JU+kG8Q z?SHrAYlOXTP)@g<8IOA(@0KvZ>ReKd(VW=$rMJ(^ZMhzt50appyOQ?imJuD5wD5s^^xkZ_!7tp)BYjSG{@8a>LsZ{Oae1$*l^*A*87c1Dn)Ye#SFLrjRfOx_i*?Eg z{^_N+24-B`yri$g9}qN z<&}reOGiJR7rso%eq?dkknD$5HNj$oU-a||JzpHYLpHx6V~iXXdDYc!(=6z)*T z(_Y?GbLF8-_(_>`OYQ7#Yme5x&Y7CDHZ=P3bB98mhfX~P1Q?x}(6>HTX}g_g)`Wva zQA@6xMxUK|cgu^IA(B1Vd0!Q^{UV(U-W!0T&E#m5;M zjT$;Ru5+W?q4=I9jdp>@_K0O{4;UQ2YUZ;+tL}E}Ui|)!Scz4A{36fQU0z4_>~Czg z?qEa8*6y*lVxEKW;?-eNC^Kfxq&FtI%Be5z#hVX*yy%A8L<{CDZT8JKckU(BPO>25BFc%PkHgWSmuOk^(+09-{^!qeQ>I3|1?9rF(FS?Y#iPmvESplDRxwT z$okxgTi3o8dp>+cFyni}*$%1$S9x_ST(PH%^NniT9?y&mq~E;j?rJJ^{hj%#C%3`_ zXZ2fnFKwV~pSslZeNC4}G^Wm#Su8fKw~lz^QK_S;SM7V`FzXgPe9&DXzA1IJ!D^qr z+suQvP4g}n_v^dOZcWdSKJE`9y6?ACaA`0aDD!AeiPh;r7w?8t1#=EQo~nFa%A-E> z!Oz zHJ2<7o0)sdRSi13(I)Kh87YSx`H?nDx*WMzt~kM0r&k~G6Ve45u8-$GR?nT0DSajS z)giy&vQQmHS^Qknidt>?4*QRvzT~|_dB@tjVYS^4y-(TlP`_eGeqGmHRipck*gAEQ zM##r4*(LQgRWnz<9%?Z>+f?y+hl-?}&ZpMj+%9oBQ!@Xj@!-jNWn&zjl2RV_H1X+} zpm(|8bHSJIo~ga%Yt!rM6H2BuD3t$^I(sPlIUO zc6`!#@oLHU{)=>iLJSQ|olBN%^LSb=HEGeAdnufc6RnTd`8F=SbY#;M%TqIIK6aO# z*V}0ECaInB0o}_qmRww}q3fHuRC)EY3frLlBOT3%!}aI8YFn3?EPej`W%3)@n)>I3 zKdQEUPwUlibTje3Kt4{>=f&llCpE4;-g&u~n3~k1HKnUOyM@j>A$!qp_pWTmMTs2; zxXCjj6&%%0N|%Jizw=AXTQjy!J3LuGojvnOXxi*+2AhxlG_N>pcXDQj%g;6k=Ddq? zRb1q?t9$ai%0msq%XHE|EbS3#D^^ynVDG;nxpuNex$BN0kssePj@I@0e!lZX_PQTT z!=`={rJiTzbW{sKdab06#TXsravn zpH({~s-zV8?f|P^3V|hmbk*z>rapf3;78I~KP9E|eu=E4pR4^O_kX<7v7gsvuZ%0> z^7P%Tjy3*%opZEP%tI@Ay_nIeCpSgvOC`==NZ(mIp!@R1u?_jpN+nPAHSDnOW5G-R zk}k8Py2{Pyrk_+k+r;+>PjSc^x>-Bu*0`Wcxnbryk1R9K zlu7sK7`bR&RIeV@&zG2`Mn?q(PBfdp?{3C!$s+v$GDW|CoLT-m%krFkl+>Q=H6g?G zmv^qd@o_?L|4UvGHoG^y_L!dag=wEWsz=#H>tPk9c=f>dRa+!sgXUK=61>}qW8pfuW7^j zd)*u!VxH4m-L&7TK@ZlR-SaH0*fJ-}XJXEm;|Xir9_?5&%qngECbu687hJY^lAiPR z=gne`A)VGu>v~NhHFj-N$(3b|4gLduH~jL?-|*x_nVRUH>lN+Jwr6 zXK(K*t6QJbzw3;wD92|H?iww=P&V?K_RkN}mKl345Bqj$C1-llvD2OROkWl=WZ{>W z8`MswS&z78zi+&%%+tjSE#DQ(PrUcSM9gcI?apml5xpX;#kvj~%&^muJKbaUutVyJ zSzOAxJ$JpiH)YU-gA1cx>?_-*s4eDcVzQ=lpt$vntG@Q# zB6=|j#Z08u8wac^kav?QepqUFrB-fg*GCU$`kf02+`TBuUd%d9QJ2-fI6_b7o_V1` z7r8+XtXDKfOG{;|4ESO>a8W_gLaoq<`x@J7{iiHs?C8};Vr6crmz$+x{F)27%097i ze!Uk}#>6~U(93%_cP9IW+Uk*(wYd$Kl+UIu|NP+Z{# z&DFVnC+>oCN=4a97tNCgi=KG;uko7}9+q-|`om~`TF1n0eKse$?l;`6CKZ;t!1KxGuW%Xy%W870S9*yIv%}y5P}K_t0f|=KYli`$sgT?0?GfN?o$;!%Y|e zm{pG&PxPq|JF|UD;*+Wd#-cDw*{0{7y}FND?=rruRPJ!s3sFvYhxJ=hv|(F?nnqZ> z%f*n1I$JGD%S)xxohO`gsXsrq%Pz@vgNwq=M{enC*nPTg^6T``3H#sfZ^Ecm z^xgf|R>;i?*Q?e`$|+!1XECd7M~=PW`R3f(QNz?$&;7AH#r=1Kvcx@(xTe7u&%TfK z?#xa2GVb*IzDky*J0*L3wV6RbXD2JNHT)ds7S8^@jdji2+nH(F?WxJV9?DV5 zaotlF*LGV~q|!nC%AfnsWnL3FT2V;lrG0*hd6X(5A57du`_m^AB5n)7a(q^0M_beSQR;QF@8@|{xWeWCH)l`OrPeyYXB zM+(aIm{J0Dk!%iYpJ%j%Jx>4!D3xe5NOul1Sweb+U;U5nPuUp&<@x@`Na>!y7d-gORZ zEH4i^@OpE_h+ZXy4*7{nKA|f!y;Vkz=$W|4At3ccYPTzAiX$zYJXMY^9sAn2FuU4j z{P%HDt3C41o$N5ccyes8Zt?gtF7j&L{_#qYUtW~w%9xG#w$LCxca>SMROXT$C$Fy= zC70_cK6h$g2@R{sl1BNeC$C*|z7l;iD5W<;tRZdpl`-|59xM*A;^;LdPdK<>Y}tdZ zX(QYpRQb*C_}Sv)V9u7qtKMGCR4YZ{V}h`HiPO&9YfCF($E+xE;dLQ&!1l zGM~6EQW_J!Px7>)CxSqU?GTdnhdu{z`6z~pkT`vLufj*5TpQD-+gGw{>%9ajdg zv&imme(_7+yx7GOr^B{h`f{y!zL>^`9X{F@4t-NAD*yRACc29)qxdP?=v`XD=2F)g z87@BRiYD2CgHysKYJWfYS?GKDypeh6(oo6gr#wav9DTOW@(t=8%-t(SSc0YMbh}jZ z@kxFKnxzriQ}#Lf-W&XH9h; z%s+E{Wnad9*>~@3?@Uf9C{{m}sycaTM3Z0lJ+YvqO=l~+OLHgZj-8lbAZw?e*z0Rz z!sh9v&*F8vr|ueX*k1F)kGzDW_aEk8+f&zVZBBmPp;0D9Z@;~@VAGn|9^Tx18%qoi^#;eE4!!MUeQ&slAHcv!gCJTcod`sagQ|Gw7I@kTRmRb+FW8qn(EW16?AS1N@(Yy%q7zKO24y(s#A`3 ze8;S~IL@T9!ilrs>U^pFPbVJFUzxFFdcm2s{uaId=pKs;i58IN>bGran_w~d>U`Br z&yTJgCs$dc9j2U>mj0vL$}#sg*A7(*2vV)Neyo#e?bCG)f5sG*hb5gmb4N`oak|%t znUx1@w%SZS^?3gq!zNApRF_S+c4r4D8s()_Egd?lk5ahz=B%!h674Mltv1H0dk=f} zap}iugLe)e&)rpDzwY^$h|tFQW{XwFDQ&fz5a)C}%fUl-pH+42Nrfiow9p` zUY3mH+vJ(M2CcmFR9x~xC+)Tf=MEv&ioew)8W?9+uen#8pIqHY^*8G7;3kM6gd-hZ1kIy|(gp>pf` z;jiaS-@X1qp_b}`-?kshtbfcJHSIv*fb~lTel=5yDw9h{OETwq!wN|xFo3Jj${0s;GJ{!+V(pe^P!n(z|_QT5?I%^Ny>+8Mm>#qyNBi7&O_B1nQ!{KShOZG=~ z9kZ|3swpqVZg*LFHZ-=j3oUpp(7R(H;j?g81$oG=*A-cVf6{~ z0ee=R*t4ra``eR7#obRNj_c0;baZXNCl{l-Gq2w!>W*zRb?!Jnx4`wDb)!Mtn}vz@ zyY6186BxUpSLAB3=hyXTCM=6T8h-e4ow2*gw@%uiTdNF%X6R^*e6>|53;4gTZ&N z6MMpS6r|T3Q!yj@b==aJAL37Rt;(ty81`-R!>hBC%`0po@6L1oD86UdpYenC2QNLi z#YDHy-0FTuL*4G`Wt}~JUfkDr`_U&~y(Yh0;W5gwuJ~leirli!cTEo$+sG^X+)X@l z=~&Xx=nWP>k9Dsb?6tnhEcSWtey-y)?)DpY#8f+fZ`D`li^HnAtAErzlHqG7z~#1h zT*uG=4~DL-n*EaBDZ(OY2&&8Qet-dvL>+?l^zH5bn3*I1Fw%6!7gh zeFoR}bN|bLVE~`wJ~`3D-P_I7e=);}%QfT}v2~0%Mn?J!LpGsfL>L(vf*%|UTJ!J= z31)B)Nr4s|z@=VuLTufF$PdBIUyg3GgBiLG;4(7uGX@j=09PB_Yr~Ad-*I1oME{Bo z{{5bl7t^%rI=JYJuImJT*WAA`{v!4rj6cC-fPYD(h>QRNfsG#m%r@u&TVVTFFz`Ry z!9UdqGBAFPu-c#zEEoG%H1ZFS!PSWY1N{3xqC}vh02cz%TFd_zo?;aEM?}v^GPPUz z2M&FYng6zb_(yi}4=}(aT?{o?=(j;5SS{lJQ@i*lev(OsVruUV+R%Hh&9#b^!Q3Fc z0K{}dY269l?!gQvQo9VUx!5zv7z19&-((PEoM#a5I}%^^3?}KfK`iG*XwpIf%u$49 zVpY@rPnC|66Wl5PLubT9c@MvX28wLujHo){zW@7B7&Q+C=_VPZ3higM=#+)=$e>Q4 z2z5p5A8&Un>Ctz3@EUqH}9>ms@fh=bNgTNYVEvAh9DQ;S;S@ zG^Vu1FB%H^xM<+K2@gB0Rt8IH%o5~Dpo2)Z2@DnqRIGtkk&w~=zceV|;?jV{ie_nA zA(_$`pQ3;;Bs{RcZ#C+azvmZ*9DDvzV`GiAif5uW#%XDcjhzN+1D*s(rjIp7hbP)@ z8eolyhI9dv0U~Ad0CKJ-!%jvA4SLr`Nl zYPjMG(;6QH1vQ4Dh9i=32x<)M>+>K;el1KgiVtxjM+|_CL^gvBfygF@gF#A$4=+a~ zYvHuSh34TUKn)U}tmOB?WVHlykrwPtV30r0T_r%FpF`&`t!MjiTi}phn{;(8f?yGf zBNA!_wuS{2j!3W-*cuiTI3nRzU~8DUliv$dx%GHbVaRDrU^tOFwr7wk0xu9Iq)<38 z^yx6n8wsR;+>a2L$?J>c+c|<-!)#t(G`I?C4KsRux@3XR=mpA#S-rkUUR+>nnAz*o zSpuzWOx!TJnh*&ktm22@?nO~P7r4F$ux)GdYPE@>WgF{ z0$anZm;7F|zC)WJ#lZW=p~H(c*VI~aODAZ&U?r2A2{WLeVBRx^;RIG6Coy!by@Nxf z$^W-m;5*wR$lK48p=;(HJZID>EIlxwGetfq=nDWncLR;*V#)7?se|gH$)Cr3v;nOa zppP~nF+&+;%ySutWG@0+!~BeaNcJMIHO$W#h!j5rwubo`13J6l8$f}rVSdIyB+>IffdGIMzU~8DQ8j55j0$amO&QK&H5!f1La)u%q ziNMw{lOw+u2|DEX+cU`F120^?gBKW^$ex0CWTe3{LuWiZ%#hIIcU~;aqzy$f8$&^@ zVJ1y}FIwNZ{Q&)=+5~A?LR+GQDCi#;aC8_@P|-t_5uGXWf!;`vL1I3M{9afmgiK)x z1}O_3wv9xxNFxDZi;cNB@_S*zQRZXhuVdj8>}S%XVlaFfk*<&*fo#lc8Hp5B1h$5G zEh9R+;2%IivSD6}{54@Zf?>djv{mls-WgD7f9%d6gvb;hxtJAdy(`86$94W$$oKPN%-=qjxK~C)e(B62c_r^^Ld1x zNZ~_pdzjZF^yo~14|Iat!`udZKt%PyZ~?o^6{TI1O<*wKSp149d07T}e%6l`b-a&u1vxdj9b4(9v_g3i4N3HvM{U@Oxl=uDR~ z@PZ5k_kZLzrU)Gt)E@5t@RDlunoi?9=4i=v2?TG?9^kU2C9p$5!0l|@6@blCA3$SsnB&jo zw2k%mS>Wpj4#vSX7WAdPKcMrw`Ej=~`M&^<^S%IWjyGdy`uV$i=#l?$47D)-O>W+b zpo$i}w{(Dsk5}uBZi=A_RRsZ50U?jADE)h?Fyd2%XqE*zcobCN>jnh*gfQI-RRwTY zOqeqM7plok4(JWPp|!~ZF>|Bc%BQHHW!}~z zI1A5jXgLr^Z=Y{EkqS%&5j$sSW;aJ=!gf)n;1sNXPDK7yj0<9g^ zzhzINQ8oxjU7-4GJkKPb5TVa}uyoP~95FasXrl_+!JbIwg)oWvhaK`Ys4BoyR`Lm9 z4YnS3$o^SHQCXm?uW6wkqEQBeRq5?8kqk;*~jA^MhLRDZ0Q~=Y6wqc9Y9`;1%oGB_G zb2O?7@QheA<_rPJEtCfF#ae=vknvM4gs^!^V>U@`*MW95(KdUDLKcw}%DMvcv>f5aNj;5P*Rq-2$Ejh{m5HAc=^I zCOiqCrFS7TK~@r_C9s+W&Krp0o7y7_5RIorKi{f;AYNA6(A6Gk zfIi*ihu@+w!WL#xcp4xY0gMpXAm7#tE$OKZ5_0gp7g|!8@KFNmDWuXsRD~=v@CwbV zZKKv6K7p2*DZnQn9w34-5W3ZxJ1qlsslWm5{)$X zmj>}vMKs>rUmC>YJ}u>tGD?8vKp?9J99o9z8wnru)8u5>Sv^9$496S@C z@vM!O zwMpqSC9Z-cHb`A;BbwSHx2B~V^6LPSA1M~ay^yV$g+xo$r04*wQt&8|Z5j9WupnAu zv49u_0S_#P1Obql+-}8ZtF)v>*HA(Et^%S4glSRfRxX+>YyEB6fMb;f&)Q|*7|s2Nz0uTt^=@Y0oiVC z)Iob#7%e4QfQ3P}E)W*2sJ15QwyqyS<+DJdPRki7ii3rmAHat|MhtgL!Qw4SJkfb7 z0-Z`D;G7R6r097VtAL2`c_tIHf2L^6Una>o=0<9qf25D)|L_T6fu4Gj3W{Lg;*6Q1 zF>0B50(}yeH^V1{$pm>cOpNQ>k{>t$UJ4Y+UH}%`on8e6j3CX-v z&0<+Od_t&rB$_2W5@xSXp zALsy5_1lzB17i9=*8we+9eRC!R6*B@6oUIxTDmU3y+Zyl1yu%EcFv^bLBlx8$_!jn~-zk)FUw%OOTQW_Gm1XNrQ!ct=$*Hr->=Gg4vl0~zU*mH?BQ3F)Z<%uZ15 z0}SUM=RUN=XMPo6)!$nD1%c0eXxZr~QVUiANUTv2xV8l`U@-q&1zckh<|`>GASaNN zu_N$_7A-qns0u&^j7Z6CRKY)A_h6EPAxs4*j`Nup%KjiEfY78~@JLHbe5NQ?p#Q>W zZS;IqXkL(s&Yk)&AzihNnrshy5-q#n5xx1t7e1e&rK2M-;eAGasts$h;FQ-tHy~Q3 zGygb4YB$Az@QOrCS~_~`KJ)n4ZR&G7SPZFd5iJHSSux?DGhjFIY6MJLrZYv8f?N?^ zEs04_kAxP(W1jQj5b*G!L~Wgnw?{ytWja$-KqhBYFyW~%EgcRY5zL7wu^b0RaiE1T!Jq9|#STRV?2l z!iHz{*CmLU!37OSYAmiCP`Ghd(Tb+S! zNzt6ZIv=xDg-51njCCef=DECCoMV6lLW6=*8UQ4^VhCB!`_EiJDt65<|IG~(c2B*eW4Ew8oJK=Vjlh=;~RmExF) zkH$nqLd0kl+^y zvkw+Yq!T6*rH|ZHnF0(a0tiYj4e=>Yq%gw5No>u-!o&;@J|Rrf)(b+-4S_O#EJR_$ zl_^qGVc{IE=9Zb5DYHbQm;I$dESj@O@|CbYQ$`1iDlHOXu^9fOum&jzbYh``mauR3 z;6g0wY>7oni{Td%lD#Mx!WUgw?JQ%)Y!V;}K<6j!Y9T#mqML2C>waDYdLKPLEF!=PEMN4ns z^^~^(%jdrEB@-4c^M@ZQf*ZuW4DF)1fS#gtawrU6Pf2|U!wGdlgvJ8g4cDq7RGTL{ zELsi_MJd=4T(j4}OT4p0V<~}K>IFmz7Vg(*sX1+t5cg}el(JR^38_>-(WD`QSF-DP z1QU%f!-7gQ#2vY^z!DT^8A$d#z zISe2)+-7A#sDSsaQUluhf)vaNN(1qQN>&?bHY^^Wh%W$x8gndI4^IH*1Tpu3F9Ck_ zAJsr*iN?BN;jEh$4}?#A+Q_>3iwX?Eb*V5BZjCj8DqyvP3bTffHOQ=RDkC? z^t1z#F7p=^7y%WKfxfLMV7G$`xTYb33It7m@g-aqEd>d3MgF1!FyCW|Qf(2`i}>d{ zpye3~a5ad7h0Fp74VTkl_xUnb+M0P3kYQUGEg-{Fy*9FOSde$b^^7dYziFdkwS#XF zjl06axhpMw#%TmibcDFh){&rplrq?x9%Mal7!kCliI_3h_;Fd*+EoP;aM;(A4<3mz)~k- z9<|Z3+QFO95}WvOfU}XBM~{OqIMK3^gzEszl_58&tvF~0??Ou}qUZoQKYm-lGgMlN zmv9|`Niy6`Z>tX4Avd8f{7N2N;+qCRrvN}p&RT%bkP5(p74~p%LrZ6(XjssE6TfGN zMN2J18s^oi1i1;1bk!#R-45PGG)@=`)>5Q;7krO`maitD&uBi`rarfWH=!k(QO21J zQ`A1=IVdeVtaYCuIjoHyv>m($Eoq9s&ycf5?K7T((o*aM^jVaAtR1`sElE^BZUPCI zzz)fY2Y5v}N-Gi{OEjV!3o_3r8pZ2`!6({~?LjUZr6q19J}6RKkC(K^stGOKi-IZ? zjQL^`UN?+IOBO_^`il<05*=jGwKXQShc^)|KZA8BDWiwi4P((V5QXaite&9@oc}xT zA{vj71sQ%+9pE`CEz?oB4#4u6C{-!jW!;39)GNT-AUZ09J=pw)-~htI-8qa)Kzn*! zU^R#4P>-Ov`u_$_oKAMpPFQmr*qC3QmD+kr7{M zrKLbpwkKJzh#xMJXkH8_ETZ%XFu3scxH+A$0j3hTSddd) zP9{}Jkl=_*B-#o&&K_)*2%m+DMsH*ZY!8R3XzWJ8?cuNznL5Zq)Ik=a4zf_)MO=rX zVIOi1DWi(dH)si%twxn}fVf1WK_4eCHjgSk8=&Pbwvvc!rbQyQXw*eEPF-x42+P&s z1ELrsl)xSri5nh-HGw!aY`orGvoHi!&x={rPzMj(7!lLq|5b6Lv$Uz3Lq?q`$ zqRo6MwrB)KHck(0Q4Z#p;S<7?Lk+G_1l*oQqb#y{2bB2{fcarIEftL)>w+7^+$fut z6WEppaW6ChkaTKBhShq&5$Y_?r3RQaQs6exIx@O(la%o=jQP$xt<#pqGF?(YFLb-r4csw z6x+9N)*fEtfh`(=kd4<(YiSU7khGjh$opjT^%PFcpfLPnN|#+X_mp)0)G@^!Ep3r4 z%9sjl5O+?rGgU!7g=_O{$Z^CCjJ5z4ucrbn0%y;&MI#xq1viL$DDnwmwkn{fh>Qh= z;Tu!h8-tsBO3u)!V~Tq^TAmyKnBpA5X7u8Wc{VMFP*6|df&#l0-Hc7kFlp|opbQHy zQ^2Mrno)WxutD4-(H6xL)KipUK^6>-UecO{A_RBlq<4d4J>*dsY)I&1AT)wkxIDvd z%|vW_K0-@PqbLnwf-m;t=KQnKHg!@}sK40rqn`Y>P z14nGgV8X|emdZsDQIM75XA9W0)udWwaqy~5Ty0!D3&R&hCTz#Dxwm*l2R3bar&c3L zS`;o4U1*|+)Dlm4=>pgV#oOaP(B>{;PP?T!ZeG;tR#LWTtSmOh%4%tu4{=h=eBxv=xn7DT$0CxJ05s z9wYL!NQBQ@XekA)l|+R+Eun^@BtekJ^9owlQ!6Er=@X_TT6zmbq81O|q9i<_psjn< z%A2;d!}X?+bAfwPS~d$W2Y@sUGTUislW#qVcAJ;Kvw|DMr#ZB=jkYw1Cl#U*OW1-X z#GNAfgfL%&vJ^;CB98;GQRxdd+UQ}Uoo+T{obZheoeOUs8$n3MYb3L2nGqCK3TzPf zX`*pA*ce|0Ll5qeXn726kq~z%v;-JIV}s^Dh;6_|rGwb5SO;v{T}Iy6V1;?Gp5tyt zw9-Lr!42YGLNrE%;0E~?LulCm{9_|fLcD+{{7Dh*25pG4(OxYZ-pR;dw<;aPrro%2 z9veY0$Lk-kMJpY|#!3gZ3^w0_1}#%V04mXLG!%w!u1dS#&+93+(~k*;r%kj)ZurMo zaD%vq5N)rTEx1A4L(pyjw?#tSLy$iyA_^g$fx(7b>);j51L6KPpZDg@AceM0opZu? z1EMquOMq;6dIO;f{MP?|R+vq@Gfh!m%M1m>3+}Z<+~03u4z#ofsx?5l_%Tfv^(c~J zHjJiv;3f+^>eJr)*g9!yZiqW&fqU%u(9-V5@{0)fuVL!c+%kTf1Dke>9iA9wV|(ko z!`EQ30wi{DOB&x6`M1u7g2JKL*-*AoLX*h_W?md}i(Oc&6vYbkU)Vf^LrXA$ ziskSwd7J>GB0W}{2(#^DPa-8799Ub5;t24m5`03K5(V@b`KdM>yJ!~!qNSTq#u;0b zYK~L*Y>q>6GDPb$q=>X}od3DSK!^zyv6aO@_}T+Z!gL&V6Hiq+q7h0s7@?%a72(rO z_=Hd~NpH-7#knXr1oaxAL~ZuQ?GTVe+ z)-C~wmXky2Gm1j|ea04cIHYS4vCkw5+vqgfAt2FK0c<@(g75_a2@X1Vg?T5o-$c%* zgmzrORWL1%*aD9kvq3p{0klQWF*6q7j@pu-F(?O?UvO zB{;QG6P4k_5sl%*!5B`Mn(zQi%W$Hq2~wJ{krR#4#DUegsA|IFA3dXq>YJ#HCJt>q z8Gc6qt7B1R!hO1^j3y`n?wdp_S;c|XZKxvQ>l3skt6HOpig3}$OB|fM)I68QYlp%o zggHAZnyBn0j%e&94$fXeD?0r9C-4bjBDIdj%?*M56DSbhyqUK84?nnY?oe~f`2Gop zmOKPk$~o|oGl+@imcafA2Now0Fk@=>f|B5l32gs_BN}IkgI$frOQXPO;a;1Tv?Np& zOrQ!9avRwBf&&jyVpI(ZbE=}1D&jz96a^Us9(!oHTxjwL zi!xDK0#$uEqEss4qU0ZM7SM9L_{|KbJ2e{zehW5-mhL1}1#F-KIAdwsG|TXx-?+)4 zCCmxH6odj0w$%!`X#6n_WOh-Iz_px8wwNoY0MR{~d^EiH(9lM2ZZAg-damV-k(%#^Dtx;!^{Gr!lltJf1?a z`D2Sh!TuFux3y8B?ckVb$#eXU3FnhF3(mLeLOvlhbihR}$m^q6BzN5$lFI}HJwY3} z?ctbc37G;gh1iH3s1JMvMl^yR2U6!KYT(<_p`{QaO!2BI0mlS+c>f`YL~~3yHLnFk z__6>kHILF~K8th$I}ebj_aB0YmN_a2M948gec&LXB@^;nB~I9DQ7FEZL(8w@DO8|i z0{a-E)DCKwU?&=9k%QIOX$et$TRF6>N}(#?F1Mn}I&HM8c1W3MDX#)R1+f5xZIv?7 z9yAeDFR4YDAj3y1&@inA0TsPR6m1To19Q-=l?1^DX)Z8@#RUqa$+oF}5uXIma!{$$ zbLzE=v}?X*{&N=idiaG%>sq_{c``J^yoQan(E>7oi~c}oz&;w7_n_0O=nx`YUIZnh zxZi`LiSPy4Ib67hb0!8-8VvXh$R=b!?jQq|iXq_MGJ`;e?g_Y=2q=}XB_`w)F_@4* z!eGMv0B~&_N$~`?#*<=#oDDq>XYb%WxnRja_ich#IFL+ORSCQ&=bfOJB!<8%e2*@K z0}JW!b9j>(sL_QgLZI8Vz)ef&dsHL<-A)58e1U2~#jrpbDEPZ9^t&wdyQppv16AVz zuTWkVk^@zD;Z-jIC;Z{>p^^;XJ(L%n90$Vy^}vQJh~VTK8W*@!2HvCLLi$3-$QW!i zRBWU-Hk{gm&ry4D8VP8raDdscgcNuWzen3EV7mdf4>twC6d7R#u6}dhBY+^-pw(9f zTJZ$0P+ks_7p0wkb==TqwYZz@svjX!Axln zKXLsLMSMgxT8hd%^Q+JOZG@=1hIq;gcL7R?8d-VsR~ zo#H{>2%X_U#BDf1VW4ykom)VD3Y}Vj$r1wwVFn`jBNv7!=7?dA2<8a2XwVUM5p>bW zBLXGjPa^oDjXVTm0vRs>FF|Aw$fyWZhKGPjSVDsEVx7JM8IWr@CY0N0^yc`M@Sh2+z$e;5H$p{D*}x% zfd-j?CrcRw8ax6G6oH0_fD>m1fyRSCF^fQYCXj{+q)me750N4Xo(h}&Ae4uRRK-Lp zVj};^^N$3&fQo>7lAxauh6J)l0y%L4*&~7Oa3J8$1z6lesz!E5AiqH%J0#!&Fz7eh zqD6=%kRKrsrU`^*0>PO;2qqAA2?SmOp_f3hf8sz=V+$@Ilc}p&?)*r@}<4W+GL$3T+70Oaxsff-Vz5mx-XuM9^g-=rWP3 zWg-YOk(Xm4C^He1nFz{EG_-)}NU9!?Ezm21UUO)LkYb_`!9=c#iA;crOn`}onu&&* ziH4eqJQWk=1x#cjf4QX{+|rGH4>>H#P2nJvBRLTSm?%X3<>q1#>e2Ja3lg|10{uQR5p;(O&=+b4L6wElc63bx_#U-`povP>^XjaF zS0q1zA`5vPR7x4>8|ei>4waSV6&~dk_XMxxb1i|U`D6{KA_aefmyn@CmmtxDUf?e^ z6T$cBr_s=%ntUJ;gsMWN>%e>X94hbz5<;jFR0a*ahpPKaH7oEvR1u}H5-2?ahYXb; z0`E~j5X9NYi=k3BAn`j8p zQNbDx;3v@Nv(f0YkrlC#6`}LzATL9zK#qxW1{!>iL`5-(at;@qj6;8qtdMdR6nu~V z9-)PeV$)wv?KPi5YjH5#_F>m~>9yeFDS#;je~QAZ2Q(?@vnlk(R%tpqT?X2L&!gi@ z;62J+5$e!63*KP^9#bB?qTfeoLkwW>`w%sV3ks$KaMTgG54?vcK~yOoI|)n+&~qqu zaS)m~$RThLia01efqV)uoj@o;+xFl+k_$Qp3{~9UB~^>IowOQaB%;4^eqa+^eKJ(%u_%En6 zuv>`IP_Su+5+|_pfiMV`>=9bP$~B6eVEGXpe8aXHNDLuCti64`L%;2z3vu)D_vE(Y2~Y$hm9*|ex1jms{pR{}&%Qx};C%wW^KfSX zF+D)jy8QAsuX#=J_E_W*WEoaUqCY$X!Y##kQy7M*jRh!JSGloV=4~aH@uPHGw%hx94D#vL;H>xIx4l^B|=#$epHZq zwrkzhb^DjU^3;zQH|WO1ORqnc9_S->$FEa)Lv2}?v7K})mlTcpP%}Wh{6uKQ(9oRR<~UtG}2_ z-Ls!Y?JH5~RMzipSPA$E&)J{W)?Kxk8K2pyql&bdNt~RWnPFc&H~IO|JMZ=n3b@Nq z{3UK4`d$3P)2lh_wyj(enCyKa^C;7V*!O%1<8ax>PXo-|?xc>qZ2f)fNsHg7t9?zx zj~yy={CG$^dAZWfC7)*<+_6_VweX@lTQkYxw9D;^A*-J_Z#Ss?7?is|Yi_ikm}z!} z=hMcbM?p7J;ztfS(bRZ-R={fK-fM#M6_`5CdBI6n10xltX1i{#+Pf)hiT}PHQ~H{( zym;_A)3g`s?6l5a3}yMCmqXsZjg*v&y!K=I!$Bf-1H0JCLHtOq8d2W7} zLBm~#<_$kOT6&OPPX{75d8byP@%9Z8U4!##-&)s=*Un83f4QNsA|_8W=0@kf#U14J zx>XYep(=xp>-Fx?H~LWF#n?r!f})N6?={w6b^Nw@-p;|(mMmR5Vz|b$oVdMndP;j* z^q2O$ap~K#5bJB76^n^3)f(e&sKq49DR0!9`~O&X%c!=4=Wi5h(Bj2fv}kb(6t@;i zacFUuQk>urG*BpREflxnMS}$h7Mwz`V!=XiC&7brx%Zy?zb}60d0sr{cfR|bvoCgM zKRdfSGdpKCpx$!mJb&O&yF_7|{9|nV_-jH&$|6mU7cZ?jUWf;21uXp9GR$646O!yr zmnf{`;~|%NZkQsuw?`}q?T$xRhf3Brcb}mT^ngAwlC87!4IU9MdC2LWr-v0euaaZ; zzohH&8sCtn8eEd5o_~6o+Ef;+x;K^>XVIN~7*Y4Y)}SL?yxY?0j}YBpxL7xnQ?(G? z&{6jCE1=jIJ+W)V4boCJ#Rd8IbqdegbLx@J=NR6V=bIF6Q3}V$oSf@Pn7U#|M_WW>6@; z)kBC;fo^zs8238UGdBLezbvxGJ9bLH$gk-7smH3k{!p4o#KT$VYg0GGo*pMiYeOTn zYfB?&C3KqJtmb87S1gq@`oTt1mC*)a&C;T&=+6rO=#7c@R{e6ux0vRrsXWvWakiJL zKQg10iA=QHq}uzkWkpT3w=&jWwL95pzQ{-Qnm)&6hN#bCbR-wnlagjID#OzP%xP=N z8O~v@-M7;oLcg2W&K;BRt-0woExOuY-L-<7s!5)gcASYCfhW;WM1o9ayr$N zOnoiAOZ>idi#B1t?`^WtZGY9R8n;!gp%5&l(IeO>22JdzC<#vmeGH;y~M}M(+{%M6I4F9p50-hWh zpWZ7%l|!1YY*jX$72!X>slZGRXbx#6M~a>p9n#c~Md|0s7y3~CjC>Aee&%=h>?D#3 z{EDV#g|bI1wI-4r{EGPSzRvQ#l`zyJJ=kx>dQv{{kYrNv;UUS};Lq0&Kc@A_T7(#0 zKP396bWLybmMTb*WwTZwBN|rlG$RU@$Lah$NM7hIbx^nZh_wf6RO*k&lod8s@l@U) zJZ5sLtTEI-WA#=P?6a86J~$fmm=}>noOAOikq0SojrW@W3>R4eD=8WuQrEu^KPQ-D z*1mrEa>QD4f%!Hz)2-YGH+^KCw>p~Im0Kc`dW?a-C)Ywj@$j|hyVv*RL&`b1L|)7} zi^QtPq2gEZR8!ZMa~5ZL{X;2d#ReY+Q@02o24oi8X)SWo70)knbBw;N$K$UXpZ_a; zshFHC-W&z~6S7feYG9P@KU!dn>~E5z9!A&KPAeo$aA+%SV6V_$dD%lkrx&ks-kTFr zjQ(bP5{)X5eG-MT!g&&dvij{IjxXOk@fXO4XO-qdBmc%kDlYE@Q%>T}Z=Yw6U-0I1 zxo)~Y>Wh3W@Z735=|z~^igIk9&mn7{MgBQ`pG4~F8|7;ahteKQ;m<;!2jl|kQs0zE z*1xJzYg#vbuV;0J}Kr*VTq4LP2}-ZMq_uBOHL z-;+?^6}O>YsY6GKWzap5OvSFeKXfduB!%@!@sPs0ZVWg;VHX@^u&##&tROZB%Zk21 zFxyJ1L1fWNDo3Z_p(;<8`yoMT92u13Jraj6a=QEu(XoG4^Fg+|sTq+Ww!PiJ^Q-)*zuL_TKM__Q^; z*Q9qLrq`sIpZGwLn_2MT8FoBPz`g^;@!dF+A0-{}d3>^vQrc%MV2N6Cv)UJjBl(MVQ=Ukvp-9z2$XvdZErpRY*vV5IP z=zbT{-kbC6_X`QKFUYaWf~!4&OH|x5?sg$FJT^y$Cl~+G*gtJ?P zUYk7DO;}~{u5_+w;UytdwPclp)$`j!#pRyW4&~hcDt!P+G+a5{$LgX zGHHM8rJ7CUzeFd;<#_85rfJR=BU}H7==AlMT6qN0VyKoNZePyI zqp`DlZ`l1<&1Seie77IaK&5pn;#46GE3kDZhn>i(GT@r;k0Aos^~+rR(X^O?sPedRb~=P_OV`K(E!`>1X7 zBxE-#BbKc%aY3rG*Wx~GoehwkR-=|e7JkOH+#6Yz;u)t|DXQ`j@Iz?!` zatPYRSvQyL@#&8d>#UcScO9$Zd}YkhzKNBGZPLIb^8mxPbgk+_;|!K`uld8MQK92- z^3#^qBh(-Ue)w5vFplLDpZ(p3nfs#dz$ae(ygyIsJc=?OZ>dgkmYKIyw?A0 zxb8Tvj`diPrU-$Yh5j(h5pXQ5=~*z85D`R;h>8GH%>0UOx<68_srG(f&y;Lbs*Ug- z^dGAqwLo|c`oDo!sn?eeW$%|6qF$aSR?K|Z*4amAF9iV~Zt4==U&r}{|2>L&NrU)B|JJOS1;yfjgm2UkqBf2ZaboWYnn z(au&WBqHY)?$2bJjqSzA-1zI!n_qJ@3lODdJ^gJxE=Jfbg|u6l402B()d)ziy>GU4c?z>JWfu6?c zdmMPw;1;|43-wQLF_L#Hxp5xfAlqNu9$c?I_eO>GugxsfcU~+^sNJ%WlEa&UGD|XR zULGhQhUJvHdJ&FZF}ZqMMIh{E_V*dFJn(51i=L(vt~`*_TrvJl-W_8M2G<9^a#E%*#A>gd<;k?@Wu_PK#o$5U8{>7>jl+8ho$e zqwzsQM?+4dAZtUM*Imoqd1N~yDO-qR^IKN0xT=TVS_OPI_1I{{SRAt!kmVt`X)@v> zuJ6I+*K-z$`B$WvzyLhkLKXb!&u1_{J1_1}kY4q(Ioq4B3j$Y|HDY%b%YP&OnkD(E zV}x4}*Ji4Im1syMVz(_G+dN**te-=hM4LO$(WvX}haQF^J#t5oGm^!?mPL9$)a(^{ zG1Omk`$h*7gatvcnQf@u8#jzqo92nk>{Y~~?CEV=!kFT}*ZBzznn^NIfr(eKdqO3n zD>91c%j+sIS^|XVZJ`5-wzNzk_tEY9Xa!(Uc4~@fAN!0>gPn0}WoadZcPhm))2an* zJ__=^**G;`!2APgp3NgM?l8xj^_!`i)honq&~C8yLlE5oykp>D35kh_>w1SRp4rRq z@7wT@;&$V|SKc4v(Z4vE`(1az6SQJ+N;>>wiwPNV!XW7RHN2zBBys2BY zTw9mEc5a6VJ%$k_yvUIX=sJjDdBg1aA(U)bku~mxRK7*e5m`cln8eE3-yc7Be!gT8 zQY5B_x=aRIsab{J2Pd?}Y&O&M`&%V9x&>_e7e&stYyA7YUNl-POdZx9!ux}S+^~fw z$}H>&8P{EF9@=}_>k~9;jv|$(_4W1*_KznBN>H*l{oB+fcLFTe4Bn&X{%503qQ@v9 zRIab3-Z>Av!muvd1}V8)X_!kT!l}l!XXK;5ywDXvkeg#FcD0jL>>)XXd;`QRgnFQ| zuND`;n>jiDAarm3R{mjc?H6me-Zt3<|HJkTEE0$s@VyR^q>42;Sm??R!}2Y_4wkwQ z)Hwz|4*%v9cByV0|D`CLDO^#vLAMGN%=sjsTi5w9F(7kKF9Dd(LE;nDAypcF`}V@) z#32bD^k-cFzM6_PGpoP8TBj^RswVtuZ#gozuBfm!{5;#MOQcs+u>*CODN8Ol3wl99 z65#WfB`o2W%u&xy{!}?b_U%^9>jdd3Z9>ZA{Pz^uFtUuF9Dy$r+b@(*Za;Rb6vn}} zIYw_QC>@K2-fI}dmuc}jqMa9au4nuUFe$+^vR{8!`P z@NZstGT%_w;isHV^kF_n4ymT@73yYXZ1pNWb6$4w_E587zhcH0u*oRNzu#JYd_7Vp z2}4~VM@GFt&Bxi<#@^107Yidn`vG4z6SE0`BPidyk^F3JpvH{2yKU!)rKJD<9z@96 zc6=n$TV#u8NProiXjp3LRuv46lADLHlW~^zm@E_e5pKk$Rnr|BR_Zu7M7ybO( z_ICiOjoAxl$OisKdZf4KeCGU_i@)zYtP!v%5@38Qq6ccdjyWn=SA>(K!c1yS?Co{*CLTbh`Ql*XVI~#;vh=vvsLaeoN!}b0;0ezL_?F z42XSC@h|mCQ8s6X*3!;mzs&QvB+>YJF&mb~pMZ1w?hB%R(O&?A_PqY^ETV1N3>Ukz zJ@Dx5(caZ4+TVNZ5{RHT#x6I2O0%jPEPda-d=8N=G-1^Q|B%&U%RYM zaOdWndPWGlRQY-h!w^!9Hv1V6N1Lkj_TtfuJ>gTtpPb9>QX$Q@+sV$7Y1!nfwT#yk z35rhY&IoN@kUCZm6xq3v=jT9I0Yrri(IjbPyOZNij&E+4Xn z{X(`LEy(vXN}P@PleArZx{x2O@^Mm_jn34sH~iV0?^fz{Q39vtPcS=MtF?v~^V2r* zSZ!legG?{s_)c4eLXIR z?8UE+_E0vAX-KH+=jD*D$6+4NFyhVSt|pe)uBxzX0vApv-Ad-@VcMseEZ)a0->CTq@LW%`$h zb|UJ=!M)^OvvT&o>~ki4qI`F8CoB5s{UqhAiW9cN<6&rz!0*qH&GV;-8Q-^?C97`U z3_|AuD+oF9%ctw-pE&vn^XTB;-R;8MoyZ0SOgZ`=<j)&+@#vBd#T+d!F;5 zrutb_EqsP^U;C~5O)f*{l0H=KK3pv(&+xeRl7m#`Q%75T!^r9J%wYP#8(S*v@1T)W zUM7VZuItFkT04rr&zG))&d>3k)`1q!ft0*qj5S8puev-<%Axok}~nFW1tg*>a}KHVB#LDb-NCdy&%^?;8g!KWS-q0TtYgPhw5#QV@}6 zCa*gLtc4Mur#&(6tMnN`qutmAG?t8mKkm9=_X?njIRfPF7h2da>rdaDy}kh8@qmL; zhEtKtTz6M)E{eW#kKfE=(x$L74;G9oM*Xq}8ztl9aKCc~vwNxU0&{$TO{2EvDn#~D zr@~W|g4?$)M5Hd~L>ru4{?40{E-Rq$k1(Ga882|&=q+X;j|_Lw<+trd=Ax~6ntArZ z8VHed){Ulyjh}`<@IYRYdCd~VIA{{@J7nKuI9g$#Fblvq}LZ=NIe~(G_dX2jNa;#tEssI+jN&r1i$j>O;gv^CifjV z;_YRHzOSrIf54T7Lh$M!S5#SFsX0=3C*;8kj5+`H&X1B&{psS0D@2LKrULJvoiO5$ zNA|Jud~3=fGil-7A9i(?+*6g&u@c$x@z;}YH_Goe=3)!Wa1%`Y=A zDmZddsj8b}{KH#{X{P4RoFh2p+3!r&viQ#KGUd(m362NJnwn6prn|ys+r?GMMSQwk zh?fhadqid7C7K%h)8UBn^KeZ~XS{9%%7?GBB=G4B<3+5zRNxPRPpuAB)aIFj2J?cn z7OfbRx8D)1UAq~oq-t7cv;2hU{R-06I5GnRnRBBF*q}gr%TCw^$-{iwM-f6f4469b zpcG37BqXKZVf+z*`<8rR$){TH;;9G%_VXC^x2~es%fVC>X;pgyTh5RZ?tgF!@dC*1 zAP$hb9|sFh7>t_{DDMc|yFQZb79-P*Xpq&>fY-3`x`%)!L*}CwvXfAAu-|RRCjPYk zrOfVJt0KxpSUCHBM+N*|{dTm*NBemy7C7&_GWAQ}2Oeg-@NyS8Gy(o_v8VdSD!Y7Y z2JyNb133zq&b;V#)aeiKX}8Ct*?n8y>m#}dY}J>)sqhl7gfB2Iihs7@&7V%E&8EF5 zyn84-WWHk*5jrd$8gN{xZFuF9-&{*q0j}!xsj3_`XcP}Q;r#|mbxo)YfCm&|1ccWR zck^W!F&?JBCfsA~?C(cDXL`>B#Rf>Dyed8ZSRoItOe^wGfjXkEg)SjMmNL7_xFh@X zF6SUTJH1p)I(qj~mVfkm6x-G_eI{D*&LcCU{m!?&6XAtkYm{BOp5)gMg1LC%ZsMYW zo4&*lzdKQh5%79z$sERWDh@!|@$lOj=hAg1V(0s7b#;43x7OmLPe{>WJ#@8RVBVEz zn8Q5L-KKFWW=h6>?h=5nYt-_ucQ83rRUCh=MrQ8{J+KTo{w+=j^N$4 z)PD`)e?t3?_xQ(w=H|Co_#v;J>O2+Lyta#IC2E6iolNoTc~)4);MYtVTcy0vZPDP@NYu*n>^wHPO!BRGMQ6a@sU z`UXu@Qeb$2b1YSW>B+!7^4u$bSTXj)|1GbcApU2r3D*<8=PjRu1oPK407CvygTIxc7C=5KuA%?EnMXglJa-j20};u7$1*~wJk32#~qG( zOkro8nE{9mOoBF!@)Vsv^hm_97{?o$Ku?rdtPzxe&fRp}J(iNV^&M7IM)@B?UvK*e zVZFI?#W-^U+pj`Rz{!#oXOe0^>N&@6lrf#hd`nnD>5J1@=M5M*+_6w)wA&;1cJs&( z%l}YoG2dk=C-!#pco_VkT4hxFU9%c&p8^KhehE3A1ufX#{KMIFM8ihgWanI3RE)5< zd}vqB2fySWkIm9A=HZNot|LuHt`n}N2hQIiz{HQojz*g+o_Z&EiH%mG55nI0k|eTE z(>EM{*8)B0nGXo{HQMx*8E?51O7OpR+FiUBGM~R*QC_#iz0S#daNbKl4UEXV9&dZO zl!3)-)Zt5WdiqU$5Y#6snce@{d$-AWl=uBZYkckBQtGU ztr(CbQo71TUp>nkG+#57E%ffvp?^^3Fyp+j(+f)cAhzaul>E=|$#&))?4>nD0`oNnauKKf0kv@OBR$n{GMX+WRivn2*#6LUwF)%)KbO$q9i z8#8Mb{bk))KeWKOlg@EKq4;C2)KG~V=}okoDPWElC7|Io+7slo1w#ssfzBt1fc~EV zIc4Q=(4lh^@Apv;BKL~Enz&KAmMHVwmVW+4rQA~=RQ(@o|20kmug*sP<5@&w)n;k; z>6++|;<=g(O{v|u>v{Q{iwab`MBJ*QZ?+La9VmIx5p}!JJ(6ka7lG5F(<|3g zpw*)x$1-T2Pwpw#e$thsoRjcH+&kgpCY(d^fOf$7=%&h04N1jSkWyl~p--Q7EY~-~}ucb_wJS1?IA% z%dI!PZqN>#ro9|KUA>t&zm8wKGM&eY#%ArHX}`@2j*4r$6ec9@1ktZtjtpd8L2~QL zl&LYm+;)_=^syw$Wuo1~4CQMMw>S(jY19qIu;yIkVOn-qN37ytmKQg-Q~mUdpXDXW zTLScGNv04{H1pJ0>GSr2;7Ip-in^Me3{yymE+xTc|S__XQ(9zUNIs1 z64=~}uC^sQjCK?=+jr3w9*UBNl}?xO|5~(C9~JAsI6xRS&kLhY=ZPisQ`*T8r`Iy} zN!JbAs0g_+<=(%16)%w=G6Z; zKQ%o1Rbo>11$Ro?+58c6A1>Kz+*6%*H%Y3)93kPA1^&j6T{4T7`6) zB(f?evfe5B?*!%cT?BI`vknCHJnuM(M}$YydeV#?yj7l7KYsYG;Pp3lKydK|UnZpv z->ZGWvBOFQUqzGc~^N-v(xIsSq#cywfk@3cvd7gc&7_gm<< zP}DEZaev5m?f!UT7Ex8YcR**cmOdxhhZ8G=Lw;vE#VOyaVXQmrZ}T9G$qT4qo2uXk z#%i4Tp^zP|=H(JFb8E(cnp!r^2Qj*4se7l*JZ)ugEZ!NDqqV-sQ>R(NR1&Z^^m2Jn zMsMXPD)U>3g#Ouflv(b@Q=bM?Yf+iaQ*l!yvK4P;j)4Ppf>>~NhgvlwvYU4T|1G&= zv-!+b9^Ohflz}Un1h5J?R|seT?;{^+N*^n7*QP(UE^WB29!c;5cw0NL9FBznFY=(Z zjOrCT{nTZCdprlT4&dCF4t=Vn-F3bM^NPL3+?MOAuJzLWZ#TEmh&rNg$8McBrQ3Im z{A!OtW)H3%D))-yz(FT}cGm0oz(``TXfXUB0J$bpS=MTM8XoSiYl9exJmZ6~w0_(O z-p)Oyxlz%zDhcgPILP>+=f5laz$VKas2*dQaokCRdcMFe`?z7Yp-d##XqKvMM}1Mt z-x%XElMW91f)86SK1paFJ1&9_AWgLDG(|Cn((%6I8V~ zuIg2H5WIc(swI?F-Oa7{HQtGfsy~{Sdguhtp4GnViod(59-Z-w?ic%G9XVkcPa1^!9>Cv$TA_vza3#Y$Wm;dg={x8%Sg78MFY1w?L!o3KNFD<4XqHl^A-0Am= zqely()xoFC4h^>l&5qGkW#XH%wn>LxSaz#@wH*RJUw0&AO%I}e14G4DK}3(8U8g?= zA>$Q8=P&ll78~lFy?OCcZ>(HBnh{6_{%^Zp3GfAbzN<-sJ!E6>?tIG`vC^T0-MG0> zPz{{vrjrO>v4=ll4%G3s=#PK4*VAtHdcSP8)LaJ>yHYl?v+gwlFvIBTpSGhqhVMuh zLjHX-Z5m$BkAZj?;xWFplEjJMBybR|>Cuq~5AUZwD7&N^z=1wg;JUHrv2e;sdHOf#5UGf0}9+!q`@ zIvvL|G60miv(tE{MmZ0184Q8*5)Ljcg5buXM=sJ!5G#;tU2_QRrVt@n+qUtwdGGTE zq;YUJ`>Jj3Nhl-fy71lA4!!%!>*@q9$!pWpf*pVQ3DWB(rvq|5T}&bQQVH>i#EogH z(7Z0jiR~Q99}2@lGTLM#2^yyN@|l)Wi~V_ZA9?qR99UoQF&b)1GIGNNa-|IF9L>uY zy>3EVZu`reUp&4wC*MJP@Ha2i*80Iy^)T@jJArO`uE2fQ3$41ji=)aV>|XieO*i+I zkrOhoK-HQ=GUV#)4=r}w5v+go$&ddB z@a-{3IOTs0y%r6+a`_Ji19zr5pMqrtU@7gmx01o#-tWZtBp)*{*_jbrQad(wKcOd> z?VU61c8Z0WvJ+4`D<1ipemwGJea+ku_@#WBs#1A=rcf9_ZDf*pp9Gedl->Ls_R)um zj%FFO9BcCQA&o_ZS5wv|pb0ZxnVscOu{TewSF`H4Zd0O_)&FS*(5eh1vfPwhYSfQ;ohfevD32LX($I)UWZi#8iI9}9n;CrU z-3Yx(!^kMnurwc!!U+-f5-Kw-3D&GAkL#Il=__>RXT1Bn=juk+FZ%N(#M)!6Y>Z3e z!e&(fnRGBO3ro3My8dr+5pjSYJYO4!EHmi?SvSRqgO_O-NI}$S1+j|hCzd$aXD&p` z)`B_uoW3~&Yqio1Z=fGLDV~WZ@(v``R~bjEPwyCfto5Wm%sA#8;H)$fN}8?^E=sSz z7w0+h-;JdriQes-`4PxZJ-s@2MUppffdT#DD}p{f#@#Ra4};Z~#90~Lat@SKj(+M@ z(jIRpiJU-->iG4u)=w;avSKzzT-TS#07Q?!##;G1(It`_I@R*A7&iN4L`iDbWbcmj z$`XdZT){d~X|T{e)k_X2r~Jez@7u!rmS&&4h`X1)Ki6fdS>2(Tjm?OWO;prLu)sL8 z0oiO_zb(PsX6$X`;4PAN4v}Bm{Hwb}W=ph5t*md>VK^=Q(1UBm zY)u2M8+85rIWF-{k9LUqB8BDHGJCmM!>7vlXXbWca*(;=$W=%=AOL?(5-ynJ&YZlj zSIHv$<|TwCjh0!9r7}JCCN11;FKcx#*&{w$o+q?OViCBv*>0Oqdy3EyN4pW)ur4TUTMOR zn6mgMP5};aytoLKqsm08Pv@_%r3DhfCCosYemTKE*j%D7|5meaot7!+b-Z9p?f*kc zPSpo)2n*}^P}$Ji(~MCmm;d-AMqNW$C1pR43ztr zAx+{ko)^h@4!qb~xv?-{&w0MGrf%6qSgw%wDdR1Tc9&c_k6)g!hP_tC5Rs)3AV&9l zIG5i1@An*X(7#U>9E?N7;=Cd1b*ilvL{oOm%q)8I%tfjBVQeDMN-W=(q@;NXM3$!d zTzyaOsB3#*W!;{_M`Nw=iMQ+?8NGkhg@p-~J*c?i)EMb26GEVt6V{saM#nCSFn@yC zxBXGJDY8e?yVP_p&QeR~OM}!Tg6#)USB6Ot9u+#6BnEjJUjQU%?k-;>|4Be>^p4|a z`S0&~WqEXBv&`j!a(oFooReJm&yv4D;=;;w-2bkR!>6oSTa4%{HT-U=HodPeC^iYk zj81H9+0+$jZN>-1LHk$~rqr$`SNhXhqzx?L`g2ut-?W5YZB4oC`Z&M2)k5Q)w-ix0 z?}~C>yGfYA0sv4tVQJ~()B2Hpg1^?`l`&xA!w1ERhV6oN8sB;;iH~q@z4>!7z@$T_ z9@?0>(01G5y~+CGDZXh@_eJ4&)~FU22h&gXwkVe*X8conMll)M;~pVLln*wUaze0) zgnLnl?;@_Z2CN|l+H$o!KTGCDl=~oU6!kCIT+{e+o?i}RGSd*bHBRAt=daKQ|KzdB z)8!W8iY*5`QwX5Q*PnmY<|o{t;8qU!%tUrr4j^;OS!jOt?br6qS9^Fm^4D%U;EVI$ z!xT@|=#h)?ys3^~&%5)hY|Tf^(|zxjW3rsCM&A8$ii>Sjc4BkQch$IFCQJ2Jf@-xj5RpXZYpNn3Ot%Gb~jmSs2I zZYpQ~=aym*O`Vk=4ecjAtRItKq#;#FSn64a}O|-CB5t$N73LwpPsQ;tV~{-W2{xk#YE!9SM;$_ znKoCEYP(M6>+nLzb`tSu*6BtMXZNOzIQD9My(Ah7Fw&}p1ayX;HE{RG8r_V2KP(!$ z?P#nNY>1<~>-tN^ulAz7&2-mg6Lq&ZS&HH3^F1>sp>hd~hrcvzaOn9%3GaYPJhr6h zA`2~^=D5&%*Em%+S-vk4_?FS3@sI}fadx&@@$!V!2(`EpUw$v?zZI$wC~si*Ihjv#g!RI&hyGqSf^nwy#3i>!tvx%Nx{dUl-H!}rQi2D zR~ac2%F<8Ca}*D#4INgQxsxZ}Kg9Fd@t)tc*7JKFx6WSB!nd25mR+9mOQZ|BNk`o8 z-T$>AVYZzs@Qg??Y?W<#r%^kzB5?M}bgsH>#2gHPs_8t0uHyBhe=fP=|JeUk{yTVD z94C#OjO?Y}*T)3B5CI0uB9W~!VjLbL?7DAdFT_2vt>YHnlfm;N=n z`Av{Yl^lm)<*B&u=SbaV2PGvXpR{8KlSsKv6~Hr@51UREWhNtDyc^B&hK?(m&?@&x zF#oQ;Td&za%_?`w2kDay{Y;}7q~ryN?-2z`U{NInCXwPvDq6TNL5Re?fdAm@ILv`% zZzzB+W~KOP3%vfcrOyX112N}amOzSX#OzqPv6*`$WxQzxo7H+9y*Hop$<3a*69;YQ z;27(r}kMvw^(5Gv=D z1jQ#vzuk_Qh$f1D`~IKbAM(x=TyLU9y$!2E2tSq^u@jI*SH!NSFY!_gomynEb>s^l zrh?o2BWc<6O$|3y81jFVTfB2|jLnlG{>Su;|_@cGYye);@7V0E}i?KBkiBy_CUWL@MV1JbJw_yM_;=K?}w`9%h`$% zIFDR69Mf zLTi+u_KC%izuvhp?*R%n{Z>%&6|b}!zQ5^=y|S`tkQdm*OBkl9)-T+pzEt>y+l9kr zXV1sEc4ytgvsrANj$3Z3s9{XW%-mr$?9~LW?S&AtmP6!H1}&jgxq<9-RI*r~M1z=_ zs~RX*SnLK*NNnUbVDa!J@aM1vzoa|eE**(Pb2Y%JVzqwNH>H=RhIP8P=HHaqQ+Rg4 zGkTus^B>|g>c0{x4aM*CDOK3|kC%%?fEN`ynp&O+c$qRyR{V2hnw`?p7)jUsWAt|s^obv#y9c6Q~X zE1p42z^SQoCw>Zcb~>fJzx10V$z2M*5u!S0$N=HfU)0`L(%~1S z@m!G7uy=9s+>=Jv5gkAO{iCuna!6uVFZ!p&5>rR+z=2Ry=vR8k-Z@#VJh3tlqU&z< zOoto}sic6=Co{c_{79KAB*x5@&cg&9RLU!anmfKCX7NAEx%_x|>oN}#@#)+8HW86< z<e;>v^twa$PQGPGfki^tOlRu5f)B4w17eCn>jbf%L|4QgP zRr&0b`Uek7^$h<>>lj|ig-xS=4wEH1NvGpQX;dv1MHvbHen?p@cK8xY(238c%Hq@HrWtqxq3TwWEA`6uM@r+UTVeM>t%nyL^?^QWl??5>8F@R!=sI`(RzZ;8PI z`XuJM%(37?mogRoI0AQt^VZ6eCw~lwZMtR0@$2!ryY`+`vM`rQkqhZ!usx0N)s%oqN@(d` znx+a7-aojsa=Iw5}Ic?Pk`0LBik){dTx71pVgAZ-%56leQ^NfNQM z?eNom0jK_ue-<31nunQTHDd*t5M`exGa*fzsa>nD%a+y+2dl&?k&MWLPt{;IS=_l-;dvkOrcKQvikKmA*%%5LfTS--gC8ajID=YYXweV z^`xp=cXJ8M50S2qWuV2^7)*Ne-VBFmCodZUlBV1cnto-Iqnr29M<<=vge8W*ZXn+` zIePowVm{mzLcMs4Z7p~6km2J~-+A(d$A}=;Pg-c(zUzBvm)hZttifI*ikO<1VaDkC zJbp8kA6c^-n6hOdkpkGf^{VW>-nS*j+^&VbUVy4l_Q^$vdDe*#Jng*xt0YgCX{$RZ zKj`FEF~pAeySnBUVnlChqwOdcCWt7h8#Gr4@Oz99?0TdnEO@f*6oWHoN z)76W$BDRY#rX#?;i6^Q=#$WPNl+6XQbNRJRCVsPTg!{EQ;y7s36)M-Yy+G^G?(+3X za+w9LC$ngtDgWFr#Ud{u2*0Bfc-)%Tbz(a8n+29u@y{rGq!wY&~-u!OEHPFC9&{0_HVZ>+&Sr56nQ~nZg z&Cz)+9Boz{S#JJm679+h2SoU_kC!d5-CF7@x+0TRE=UdX{<$NwG1H`Z%jjU{tX<+{ zqf$iLIql10@=gfd!=|6~G;9gGlF_V%V< zhzH|~7N^;Gg}HZCf|#&7RIXoCdNCD~=|u)=)egzW1qDU1c97t%>{NO(2Q;zLOF-F5 zbIVcTM9QouO*S9b$I5uFx>E9xuVc~{Kn)3Ua-{Vev%$)skAaGZ37*OxAmgp03xpzi zD`R3kR&q6kuhBFeb3S!g3T>s#WcKuiwSkTvaQvI2=?|_xIKVHGOXJr*P%)z_PLbd6 z4Qx&$ObL)-Q`nizGLKbbxAAV1w6TTkys)?A zp-}=n-w=}Dx_(2|*QMsSA5dPEQ!%8cX*E{`DXs09v? zkzeKdRaLCDt1WRlp4zhYqBL?)lQGLc>g-=AOe0`x>AmG;)YDA0u+$l`D%XB1mlT~} zuJD=Rt3fWRr%+>(QJRa&RXwawJABr!*-=SnohH9Zm&k4XJ^zB&(*0vL1}ToAi^DMK zg}2_D?Gap5&!GJ6zzs*ByeVI7n~Yo9YjwH}Wpcby>5WrsP;NylIo{~kPHd(TuBzn` zd}zrBbr`WalXo-fR6j3Tg@R96NqEPsn)ZX^x#OiPc$4;TR+7417_O-38YFxyQ{PO_ z23Z@?ejkmAvj3f2bD>B4ne4N5L!_NyE3?^-zOS%t@KuggAbKHiHx7)d)8MzR;KU>e zNN2hq{B}hplLUERdtMfl*76=RG=hzdF2`3XS=OY_Ks)Da(W_Yn*N;<9me2%@&Oy7` zC8jRlB0k{=3s#Z^i>S$Vc0$?bZUGl&Rj#5#iH#@Oc)6H|6F zhzqYY@zyrN)n8Wzpx3IWTKddEmIFhxnuJ-P&1fXn6cp%jsA;8V=x^)EO@H{wcURwU z!+U3@(sX*zEx~F3z!nMM1dXBrrg{M`lA$S88kKa?stG_ysdg z9`r|yE32`U+>BKGYBz4O#d`Nt>)fpHZkrG_3X?iy8^He-=;@FAc_$F_X29CgZRpi0 ziyRul_{8wu!{`rvuY1^HLFP^t#V~ENbMV)fN6O^smaa;HX$&WiVzr(3K0>zy z`C!Ivpyva|CcgoeLLO(v{wH4VH$Nhkqld2MAt#jQF8} z=O>NFV-e2et@SGA@Bal?K&ZbuayQvY#)!@&5}DBAFa|q4^2i|T4NsT#DmUeIi!al% z;y{02W}vUXFE75-0U53Gq26hfwgViXmOoye`ZMx)bum7lq6|7n@Xw!x=@ZJ|Fv?j) z9+~}mS@rAPEiYnOJ%C=1bUH%o#u!+RK|I6RxdOL{TgTna?c~O|Ynq(@;{L=0glsziEGuje1cnXCCsF;8!(=O@_~K#~Y~ddH0_55X5tC=bK! z$`ROw8*mGJTlq@$SJnSezViP7cSSjZ|Bw1tt>+L&SWfpK$z1(OPWv;_*}t>y1l*xK z@)+Eq9D!k+!T~s-{AKlDsxKjcR^>nNUFc&(P(YRlK3&d`9)d3rAOsMm(+Fky`qEm3 zAK&$Zyvn$OiDUA6^gU{Y(L z%{K2b#;r@2w6`x=+S`)UG)!t^Ho zW$qiuh=ybX#~F+UgW1UFDzIJ-$dsHH@JWnKS-c-(ghd>}gZLC?1%fNn7tZ-ZC5(B7 zuR!;iGJ}j2=ssQ6A(Y9{?^FvY1O0uQ`}=B4unOz6xz(=Hw;F|CAmTV_n|gs<`gpy- z-CaF?WNOzD_3HuuB1fI#YqC+t^Vov1Xkm=>`z@4BCQ;}yEi*l0B7*6p=@ru(CdPpW zOq)#i(<>PheR7lOk=k>5FEPmtO(m0Tw3kebfi+ZMfvi_^A7tYBC#NTn4)M@^wyYx- zWT`-pTwl(h9<&MFj~+m5MtyJ+J%c_#(}<_fEJK^nN%R5Y5X$sz-ZB$Ii&8CV($3W} zptl=GK`o`xalO{E~v}sh>hsvbhf0Eqp6Zk_J&J3*(8*7HaaYJWTV4kcZ!m;0v&R& zEa?UIB#X_2l^a@0tn7`HSXpqCScx?wGkuQ{nPI`XvRyP15s4MJNzRvphz=T|hXHjk zA5n+%4Rt_`^n^ZSkldUrA=xOD5Xz*}vjc1GphIiz(6IVIe_x)CwYzqwT^g7jWh!mz z$f-_8%1f$;%jD@w>D!!b>Fc8d&+&OFDj`TD5rlzZc@!`4TdJYKBX^%r9#gWpZhQ~y zm|DcV4EMmAEy_COm+bFHk6*d&Wgb;lE3cMHum|6#6tBE@7;<9>qsVlSf0g?I@}N32 zE(^7@1j#UH?#K(EPQR(d1t=tD8re z=X06jRSnRoz>ZdHYLcZ^s_AlsNf;B3=c0*tBFVUzcB>7-jxgNadpyW~d-6*`HsKEV z`&a+VKPigI3E6{Sa(k_x>|Q4U^OQo`J#yPVj11q`rOd42>j zC@_5of0@gup-n(GGlXwLl|!E@0%r)=xLhXYT!JV*SN17Wma8bNp)XwwHPjiX`L_tcJ>g6A1{P4 zX7%;sb2mL#{N(xJVc5MFc3_KgA0o&)ZR4+T|A2xhff`}6?6i7`)u1yPc@t(?4tWDn zgJ`xt3F}Y*aj@4t{X`RNIif>q}ND4t9?-YofYUAE8CDsoszM#2qu%C@p^mw%lz2SBTnQ(+z_{&V>ymN7BCVE z{Up7VDp@Q>!Vvm4TUi%mmNEA;q?Z|FPB9l4hM}HwM!lC-3EIqNs#?rQv!Wr5g`)P5 z^6C=aJkX~CmX1uC61+ufocD{=Hr9@gtHoR=fs^Xntb{ly!ui6LbXkq z+WDx-x^rZYV&8Q|xm@T510xTC9qjii@8jD>uzduqvG+%+@4>jTWTbj}65qOB0(byB zx2{*NDOZZcsnLyBChr3(&nrwz{EOU8s10?&7i71?>$Ul#sZ_YZY!*8=?a+wPC)9q|7XGShMUEIh8h4FI0@7E{d^g;r~p(yLi?u0vGY!mb} zZW_vhU^KV17|llN+f8LNb^qoCqz$#v=Y3@w9Wg>#B%|$UKe~V}BK{Pbpw}{eoBL)g zt}Q#&lrxJ?^YZRYe)hpkYDZ0{UeIz6?^V_0t`6$#bD8&xs;O%SZT`@^Im2u5*2#w@ zdsH=ZKG!ORIo|2w6G_Y`lIX@Wn_6CKONN2o*$ezgbrcx5`u2wB4A!UD-lu#|AH4kF zorezH{;S4b*rxOw?8oj}wP9%WrR*YDs#m^$5Pr`chiCW_g-K7HnVu8 zWgB_tCy%`N_|T6YQa-$#>x5O<|MOM5`gaa}S^4na+q$3t%5}`{yKkRz?f$>nk1+Bo z|HZ$}{RJXOLO(sL=XoP5Rp733jL0x%LBJFh)yo7KS=KB)LjW%$17s5+L{8^QME2E} z2o32(kU)@x%JjrI62M8!H29n?o6VA*S1emyMHpVVUt<3oDVtKY7F zlO6{36MCYrOkX(Dlq=~`h6d@r%_^N(lvKN_58avmJ{o%Z1~#kXp8+i})991WCLz$Qya1$8M>>9kNjt1VL}+ zd9&S2JyTcNYP5sV{5v&E*AWaucss_MXb1`6EFQ!|_y|6Q zd5ac;eKZ8SkgEb+XUj|vEsJIPa`OW5<}Fe_lkOYn+mh+;%h#rTUKrQLwNn(*n z&IUZCFffH!^qBGqzmof&sydINBuYb_Yz&AA0~3aNo^e)S?P*uiL}RVl9JE$o?Kzjv zW^3}LXed6zvLSB;*2+HFhkT+h8%O!+@p-hMvNhqG?()3+*Wdql% z8`N#rUDUm)V|BV^+ymSj+y@-9odXVKHuvQ-eNuilV&^k`eVe5@o%>w8$jyWg^>uW( z`_%EKz(-QU#npVC=B8I&c~_1Odu!N1E6RC?I{1!1HbL$17-6a(9>yn*;wKJQCkS`A zI&!pn=rCugj^H~d_v7`|L#(?xfyL`Gwp2gF|Mc^Pc-_12R!0~9yt;mgvJ>uIf-TDP zP{h}ikHCNkDk*R9gWL~M9g3oQD9I*4aM!uL-nv*sjNGh;+fWz0FuXMT1%d$juA+{e7D0sD+NrnK?zi9%>Q4B{a+BMx>>hnp=X`2>!sORg7yoUwuecCz{M%|h8Q*we^xi{L zu?@!$Z5w7D`v0L$`NeOm2bGP=9>c90yzjwos7&osmM^{)Hjz4IWbNq_L*vZib^AxQ z97Pyqr#JBzxs%9-Jm|P=HdqL6uviIiGqECdQ+lvkePDNsZo2$jE}w&9IR^~NqHMRh z+-{xS?r`XgypAH*v9eGDR@SnKVbFjMkWSQL3(+B)ifqN1Y@FsjG#<{Z2PyB?f@2;s zbVO;>K#^)zGBkKfYL`exMM>>7blWOU!SV<^KQf{eN2(WwxobGcMKleH0t zMYL4li>Czv(f@4({bwBxHxUW-L3)e>KBrS1nmc5t>=7&$kH_smND|y&MsBbWH;qW~ zREZwP-O-ZU?R3%^?n6!}%I2~U6S*!_B1Eq@RN!XWRMzWR>fu>l;wvDZE8FOqO+uNx zicHe^St28^CHA#^zF!?pEwQ8?g<{Uy7-s0nRW(u7(#|5~yKHm0LJ*55 zl5zD>g1rQm50A99PA&P*!~M&*ZNUcE^Muk?y#{}dU;Mj$lNWI#3>{N8R$tEHuPHl} zZR>9PLc7D_JeAvkMSS0?>Wb<|LgM$A?t~}smgUt|%F1qpQAoMYzr&qG4&+1EWHYhb zS*xJe^O9HeJ_)xY4|2i4xYH@|EQ>0z?wkjp&S*AUD{#B)mnDzaYjgtA3j!}mRy!dq z70Fp$#@Y1#CfQjw8hIym=mRc-T%zlUi&%(@S|OY&(c`!;P;$9gmcEBaEZi*H${+C4 zJYL2R@SAwT%fU#AR{_NQ;q6nG{7klALvZ=IgEr`Sb<8`oR9{{C^PwKNFfc5~$Kni2 zVLT%3RzT2hb@7;Up7^G+2=chFvaR~O^6$zos^g6d@lxQlZ7Kf|9ao<^5fsPJ8!?%=O*KSW*>LO+&G zjLW67dA&AWPz=%`H3oE^0LBrk&E`L^g7?AGvQOn#tjGpEXUkTrfiqC=8Z5gQ#=D8T zpTk@r7(_lF@{4}i-|HXrvv%UAj@95#mHd8$y~s-)fT6q$!K`!bn_1#2OQMcfrjL%w zEJLOF(b@pg5LnD;og+1njKIk8yFk=?!f?p24@Et2smcxQ44J~q63{pbodeX#n9@;{yxb+)_Pbs|{Z&inQrKe!~z z!7+FTUR-j|V=G1wAn)|2_$%CZQ63y;%w`u`f!oj6aNhMKtVM1VgLSgm=1xZbv)LTVWpF-|ZzfI6T9Vo5^*Fsw2WkQ%X=)Ya1*MPH6ZB6UVRO<-=4 zgJrW>5bB8AT_*=qrMkP(Fgk_^gLa}}M9heevEYuBXaX^law?aU5515&46kwDRqDT?tbTj!))KRH zjfugj#K!kuT{m?vS-)!P;-mX_J{s{qHS`{YNFg`U4&PG#*D3_)uIVJdhLey3eN)y; zl7nE5bLlIveq44C!E7^E;O28>K?g<_=_=4HJIV;z7)h$ZNhh&!YBcMS-Q^5(Kl2PT z%`h3JhgrsKVoow2Fr3O2%tL)@)<_eLT3t8erRu1>rkI9UoW?AMmFzsn&m{HaMOX=m z$q4tMa!A>;bjkA@Uo+XC-(Mj={`uwO&wcc6HT2xlUd*lQcVb*Y7?G#@K5!V|B0EyhpSVEtIKzHEoShV)ndfI7T=99S~~r0 z{wcPKL}W)#%95Vb3r4HK#!u!*En z4Jvimh#H_M`^&M$SYv2D6ab0^P{`;EY0<}X#CySe(M!D4Z(7~qlGj^z!3oHjbz&oN z&S8cz3K?eMfGj)9&+xDCn3rRz5-$W@{h{Z>JJ)=I1hp69@zDbpPsw^*W?G8Rl_S6 z4w0iDZ^ymcm3Ne%=enVpyb2p%F3N8yr^sg)DnGpR`oOwHyZ`eSrxvf+_p=w^Q%jX! z{B)dbUAwomb!X@Bnmd(WzSF(%RcKJ&e73mc9k3&e{K_={7Wbf9uB@CjavTG+#4x7U zdu)~ptQ!{uqtj%v(gK8RvzweIih?6$r(SQP2Cz{BXb@PiVElCpFqSJ8Y@}4~nMkUn z9(_UeC<|t>ge(xo77OByYWeS6naOChUoF9_4SzbFrkIY7Z#tdMXXbhrDH)W@)RtOK zU0*Om#YUwti)=2Am!cBKC-5%3<}tjo`q*RDW7UJu@YrL$tB-Bm79#(IU#u36T))i3 z?u1d?m3`-@lb>NWK0CUSa_q|Q`S-XVAe)LIT4XEha`6tyXw)NQ^Xqw@I4BslAs?(g z6y83HNBr~^eRK$mBptxf`%Q`#u zwdJ6}=b0HV%>&V`VFv~$o%~5ugVEuz6%e%yp0UhhOr@;syar#nHLE;K^;&xp%i(^& z%JCw3Xll9#n&Hnr`5ttQ9v#>`x^_c={pQ}?)eTD5Cx6?&@Q2gN^|NjLr>5X3e4u(- z`AZo7EIfvpHs$wMCjWxj`0%$hJN^s*Hur5rdwukP? zR0*-YEXFL#3~W(LnVM~8%EVgTGCk+0`uj8wl$qs9XN+<+r)D|Dm-4hF?FPma@*>Z% z35wAvoyzQQfL@%HDSLWJxm0~L*NIm`ud?;Xx?W|fAWxK5;J1z*<-Xln{pij9UMRp7 zC9517ycI$?GWB6~==_PXMGHp`9>Rmy@2Po}J=}Lt6lK6I>;3)^XEvLX67?)mPN%~Z zqMMK%){cilV$_rdN=1ocOQHg6&nA=2u~TxXP=4P)so!03%&K+>8 z)z3h{>zASx=sH(MlH|8|{n{%9F9^gddr~EDGC@bxXcS6`ghj+=i%Q)F%Na|LWtnA@ z<)np07SWQm$d+EqcFTSXKVbpYXT?$_i<)H4EtYhRQ__%7eqK|x*5|4%mU(VU+gU+U zvwB)oqM@T!UZ7sf78Z#{Dp^(LaHfD-L!P!a+YR1~?SECVtXQhNU0evdg-fq6k=J0m zK@>|%PHnhgv5p=&Z!j5@dnTU-%h4mH6{Bm10_6K}v1(F&u2ht3UEQFA6qxXZ;bEm& z=~CW)Z{=#k%GGX+!88WD7sCPEmc8=R$z{x4=N?*#FtRG2@b7TnK_UvF-^mU=K_0v0 zaynU>^z%NRWeLzcRgX|a^3~N*q`CIAEY)cQN*xsCrt(SOGd?W%g1(H8n0;~}Qu67Y zPLJernI(jfBucW>D-BAln@E-E3uEC_Nt%uQMcGg`%5|yId<1ZlES2w9!5X3P4PWGe zry1-V9iUeCXYszZgRTO#CR@v5bF&L1SEICM?j$SKqvh?y3LKAStOI$GAhpD!oii_t z@;fkJ>Qwq4`f62Kn1hejr>5RMYyxbYo+E z(TrOhG{1Fbn>s;Sb@QFaz|%-Ygbo} zMj@fx+?;LAHsO}0mPV3pr0c+5Zg9KoZhP9+mF`L>Z5aaPqx!U8RkVZ=He*US#*YM+n(-0lXd0F4UBGn44}LSbgSqSB zZ_;RIQvQp-!u>t+s>*=R$Q};^I$Z-wH#9J*WKv@E949a+49t^2^m?z313PR5gBDp`TNES968cpy+$ zmy!fQ7vXi9kL7t^iV$N8%lgi;X4skpBK3(u6} z4ilYKji|k*?dS47+*w;RA7y454)r~Q4}3E8xt0Fy12*Z3!Ya?L#t({ z9KZ&H2?a7i2nM-2mn3=W1XP)RQ??rr7*SY=1S8l)A`wos5jP((BM(u?mt56tx}dumE~b?y3X%00>fd?Eo6 zymoOz^}O=3@^tm-hHktOI!CvTZr`~BzPkJHd9WWmsC=ZnwWzcUa__MR3d*fh{fi+B zk12!7(~Ei`3old;_a8biMD4sz`7J-eeIH3Eh~khq9TlUhyN^UTyFI|@^+x<-xC2Qj zG(CYr&@Y?gQe2ArjAnCy7x@bGpW(PpArbe}Nq9yU-)uMQnCLwArlDS$`UAjoDYSgA#h|NmC=|U3~7U5xR81;gAx^P>4y!lGuooU?Rz+PW0L8Y!$d=yj)i& za+0d5bd?3^ehC|Au-A5Jzr@*9^d%dEsge{7dcB;1slZL+WrKm!={OZ`59l`Ou#WbC z-2i+uwSw%tt7-sNFRDt)JXP;#huI>`Y&=%IuU3LpuhPB?${unmd+1cz!`3j&_q0-8 z(iR`TwM#y{^(meE_}>1QvpR(z{rD&pc8}iLe|T`C8y`P*_@437o~55Xv3N1Z=(^UM za4s^)OpQ)mftO*T``7-^i?Lv$MNF7p>(orF9Ap)9hjupF~6;%q8Hjbrl%XXq0` zOK>(~qLPX6vS@PokWXbQ?Q_D!{7fq*9eR~g=~wr$nM1rYa7)8mFqgH==p1r6y7b;J z<}+7oI7?$&!W^GSTB%9qX|mPbE#|W?LwH>I#^(k*mpr}tXtD{G9)Z`D2o6=>JW^d! zJr4Fqk1bhwc>Uc0{3)3H#Se-(xD`g5AN(d;xw7fR=bNpz-plClX0IfU=>+A<--Bu!HC-(&_pT0P+i35 zLtfE)%6q}f_=wkQ5ID2WL^TRyWs@P|uE4_aawMX28FUp&KH6#p^OmwW%>ct7!2lsc z*3fGhGz=M7WRMNp4HpcINDM*Qn<@pVe+vdRVb2W)NvBo#x>*fJ^Eq|o7N47euUhb; zgFSDlP@;>vHBEV|+ApWo+F7mE&Z$I;i(_Z&?eh(B0+*`8c*Doagu#lBVkYpOat$x3 zj^oD3E7c9qHgX4cFg<|^uo`7h zfF_K=Trkplvor zUSFtRSHH7gm+Ey)eW8A={z^S_r2bSr#`X2-j8F&`u#prBNYoa^*)l?DW17aM zCX}XC0lMyJMwCc!f?Dy5MxA!2rdy|Fe@odehf*aw%i9TO$z&F zrt0jp0^QvC%+gbBna>Pt?%Uj_ExH;_Jl_wxIC&r3w0-AWOP%CtcOze?W0ex362v26zXp1sdvQKxist2Zbg7i49{a{X_s3n6fN z^!EQbvSwX?d4A_}FuF9MESy>d#S8n+D;8R`4ETK++OZKmdD=aLX=`Zkic@@i2npPx-dc`iv))mAAwBTJe; z4d_b}NnC<61~`HZBvie8_l}(w(a^g>bh_oPy~p+zJJ;H)6Ga)`u_=F6y+qT|JN|rR z;L8Da$E*8_*<+`eZ(M<_@~^)=FtuuE_m*cvp%c5d=W@7M*hj{zCIv5);d%V1GO6XF z@4h>EkXdzT$4c_v?t8iy9-wM^`V5sP^vp|BYCSX3p?8d)EqTqF9C0<1)Xb(iGv(|4zPSuF zpGoH-Q}kZd_;_oF3WjMiqs}5a^Kz1w)Y5HUYSLy+SVS=~ElyGY(XLh{F;B%sL`!V) zTAIVsDpfN?e!fFqp;)RPuUNTy?V=}+R@d{5Q^gmbh4XM=&BkYyA;psI#@(>))dZ}@ z#jZm2si|S6_xdSlSCqHzUa~rn(8Z3&x*oeSJgg|sJMH}&S-+A}-YhMF1iY0~aKqIms1pPr;D$$n-Pk7dEXH~%Db6^gky@MRWw?))9T2&yGI7T>?dmpsv_-n{R#Hqdi0Ba@6D#^3FL)7y5aC`sy6KjWe zDI*HX!n?2yG03D`<*#v%tKqW)^}s>dh6%Bw z9Tm`m=?Sy|zHqv;-Tx#Eq9kg7fwSqG(#?8n1qNhuva>)kqIh#Hs1C@IoVlr+wq$g7 z$F%TT0a><}bGcYsCsmVSBk?a-5Q+stnl{QRiZO$)-AALUQ0ChMvRNzz+5_!z6xXx@ zaVVZHJI(avb!DeBCS-yc>?IjmG0S9Pvgjzq3ar}y(J7nClwGuuh6aR*MnYp%AtS0C zA-%IbA^Ki)N_{{pYiei6%X12!8I5p$rZXr#j|i0JQlc5Ua7OJm2fx#QfX&{YX$;D# zS*oh;pxU<^GAUa348>gxYjuSk;dw-1G?K(5EYUMf%h`HEpyqffoTxELuiI*o=qi+3)n7NGFhfjhpof9(c0^KTdb z37#R_=G3!&?Mo$5cJE~pxu3po9pg&RA*|`ND zf+N^eP~LlY@;+wA!{6-1Z<{#9|Bu)IYWZDT`{~|XUgbJ}nR^`BRNBcRi&T7UQ`N`d zwVGH8?$;tf;pqt!hBYXJoN&iE7leG)m>8pTO7DtBleU1}?xo(kPWDA(F`Y9M4mX*-z zMI`%kY8&WWe_m$3jyZ3g5S=fYKglzuO&=t2kq!VR&nJSP2YQ4-bjR^1jl0cqJFIz>A}w=cmJ7&x7X zGxWexSbh7s1RJp1Qvu2yo%MRdE>|5jgjEg*Y>>^c#7x+rKkSXGtrudMC9)6?#xrqZ zCh@RK6|99(j6P{C3n+uInV_)KBw8)1CZt<-luaff067wny_r%#HaSWGuSYFq8-?&0p|9^goZqcYWJxM_~fa6Q~IZWDKs`+(!P*@ozuT5GLgSG_VrDa~X5 zz2ZwVah7g5@(1ii2VJkZIXqn>E*w!p+ciYC#xJ!>f8g7tFushBSKr-VWV=r(6a8&UrTJI+5%G5?UX#4TRL>BG75C&(-sTCaNn`a0`kjh3h%CN z#Ye0Cqu<+nuvpy(-ebo;`-RajZVr&I!v?qzIJAGSa&)gUyjRh&zr6Np+r4lUcV*vu zW%3s0Yd;=cO8bXt2R!$ERF7IwC+dMqPf~1y0QycN)T8!3a{frf9ZM0Cpw-lKZqe=T zunBGS@q(L7x&;P9BYmB|sVN%@1SH8p&qQatlUv|)F5pPZ&9OuxTY-Mr)FKxe8d@^B zrb3}XTPB5qL9L<~*+?oCLM<(c*sP+i<7_z=3(>gRGgj{C=DVqF>dQ8sAwc~80No-n z1_i((00RKv=BV$aGC3#L!_imA%56P-58q>aBLG4Gd;!_$CUKfWJaDYB`?=X)8Ikhp&vIybecE)cwY=rj z_MMr6p1ScE&28G9t~Raxq_xIOYW-NWwyWv!RHm#wF+U2^ZfrZ>)*6=ZtGjO7Tk=&u z!v5-Zy!{Z~Ro#ZYBg$8Us{x=5-s{RKb;>`TRDRgp37`7j=+v8F8XjK0cHhdu04u_7 z<-Q}FaxXlvOeQa^RmlF2VyUakW?ry>Yb8Fr50DQ`jL+lXZ0e+o zmW9?}D?Zu!Oe-b=fGGxmAPX`K!Vv5S&P)|(Z^~x3uha@Q8?+LS#dEV^dIGtS2a2eS z4C)>l2528E$Lo@HG&_ivbxB>)EVzO$Ylv5w^U52uZcbGa)Lb3K3&pD%pEJwhWM)WPRUN0zP^|LjYP%qHgKF2fEfJp|iSp8o zWsqc4%Hzr2+wS^oK>5w);|*Zg+IM_@3H-RrruLxU5l^4!q5E< z#p79mMakzD-BNRa&P7Ym;|V5+6bwp)P|4STY)Z-v zp-?iOiZ(P*H+Z((&|q$wrDWUWblGk(SauIT9p6FI(4Kr$suU8BE06>}@t8qgJpssvOM&W)RHJn6XIAs7Z~K(FmRVbyRZ@ zL8|&`0x?=&IvGN=Bb}(t9{Q$isb@yKO6!%mOgdi!CtGf0|88tA&Cj{dfxdJ;Guyf3 z{zE@l^MTfmjCeIC<%_ECD{5TMJij=@8c1sL!SOL7MJ285se)8TbiVjf1v!_PH6zL? zJY0RV0$aNi%I@b6e5edJFNAfkSFhm_WqhQ%P<3vD`&ah+xxuMRq>;P1YFVm$xLbMo z)XMHFuybmXSd^t#iVJ@NgS)}9dJF8wosG)JZ%^LKtUSDX1?f`OBTnTRE^|Mq(K->7 zKn<`?7UK1RL_;JV4g|wNkEhn*)OW_$KpRtUKg~xdf~9OvxZb6*JtiNedm4qrAM-su z<7KNg!nz~W*1odQU~v18|A-&c#5Lrf@G~aj_q&lpHE^;)vvY#JTBdza2tiNsf#e%W zGLSr(d?xupl35mgBziJRHbq~Fz7hQ(%AjO4nnc7Iq%E&_&^_cn;wBf}KsyIzw?9~N z3j*PJfq*~;2sRQzSSPF2=axAKoY<*WPSLFBmbL~^Nkd+-l=Cv_w{4=Z@O;YRa*Q7d}ea{MrQQ-I(mbjRbyMXk`G}Fi;c>E{m0~b=Fh*o zYlU)JIl(^qr7tetu(f&b`Q7JtBOZB`U-MVE@2lFRCe(t8s0S^^56U+Er#@x8#UTi0 zm)U6S=nC83gqNl%R&x(xdl1w z%cXM*a*yYJmit}qdXC?jyOhJh4){#RZ5?0fc&Ov?jwd@fd&i; zTGOrgq1MM+@grT}>w?F-p6vQr*YCQRu8?3Y#k!!-1*i**RF;EHtzB`mIo{RE+}sd} z2o1r8OvC*R4>U|Sa5mCFeP{!JGkbFd+GT4wFjNP1bu1aefbj$iY)wn99=*X5Thn7{ zmHqr2vrW?hbxLPwcF?z(PV#w8Sba0DZbor6ze#g`WS&X*W`p#A_V*~JRFy#5zZ=!I zRP3pCc;{-dIj>gK=7<_i@ku|gc;k63K5JEN2ghp)_8MGF(v@SK7oD~C4canSduVg1 zogSd>2GWMFeYAalGL477{gdY*6G|u#{-0kdk0+X;?U&zL+k0E%)LS2K8@}n&`#wM5 z%?=M?*0vA+SgaM8X5l%J*N*sqohHebid5#8xqB&EfFJ4e?&1^!C zARNp9GG{VoL|j5Xn8zkDAIfL*z4^iXP@Y41Ip3S#p5LFpkiVFJGp`d#K1i2g9STx0 zWJ5z;oyVnV*<4f>OWXmy#I5z2k;dV4OVkxYo>aA@ms^g@XufV?v6WC4VS2fNg9ujHwfa7!f-Pwll z19H8LSCBqAHCsNE)X4;Ae5*(ft_b2*(H(t$v9I?k*rF*{^i*>FDxbO~UY zgCXt|hbfh|rSAsOwANLe&(yjZY93XcrCX?jrpLZMy5mfGZsWHE=N&f|rm2)m?SIs$Q_Q^puT`JIi$?H0)je?K>B*QPQq?WfcFoCIhJ-sOm$t26&M(6f&$B_HLa$)n@DSS_u^K%Q`Xs*mSS^rp#pv9p(<4nM zn~2tu-X(Ww^U%M5+T2i1`IAo384LyKsks~rb@@Xfe-|+j1O2NeWPmQJ#x(^^8PfwM z#!O6dJXbQ&b}|#!Lwe}@66Ka`B(f|Ez1hJm&SuHnjsW`!AR-ccs@A*SlvR7z&xGUJ z(H|@kt>co)G-|FG}u>a18s zQscX-;h#ye)t1b;K(1-kYFm=fc1-H>qL^sH2-O$1(`K7Q(h7NLmMl{5qw}4iR(a)k ztIf)uKM-q%U#|B*vHiJ1!_)Wey_D+uaQpUHwk=k8dFu5m%Cpct4Bg7J6H01-^(VmG zJ1j5Vy?VW$Oehs7;q%JJI-Ps#J={a?r;qQbKC6sg-nnGS$csNe-?`|;S3!jS^{cxU z!ClH4*tZ*YD);VIwp1f~NIx9L_Qbm{PUe_{r-yqZN&~~Vol3v*8blC>+)9;yjytDj zS25Ix+E6FFcsdqKSD^oNV+Z#n^wVF-fjh?XVm{wefxfY9AYgIRDnX&V=$unqXPeKojn50--6>gpH)h?-c|u-KuJVY$*o^Z3NO@AtXo1fOJ>w+fs8O@=JSM%zx zWY88PnX{j~Y*LI|9rMnTTFS2Q=9j#5%tnPjC{@!ZC-f9DQ?;BpS za`&1$1NbNtP`17{IBK%**m!q!@_F|3-s|i47Vuy?zx$Rp{Kd%;MptdXuQLClENpA* zg!9-EyZ+kb=a?O5A6)g`cIEYVFlI_CEIU7jN0sN!pJzI6`$E^B|HbzA>7E>cY2aVy zeux&q;8EGHMDnWt)hJX=(~$ zLQH&Jngr#bMi4GykR4$oLivTVY$~*)B6vu#Sm@3d@-%;v$_s`HfC__!p~8^@W6`u= z-bkqsr&6FOibEGFqv-U7b2e8g8g-l8+Ru5bdN7OcMm^YE*)D+$v!s8Z8;mDsLrCNL}FsR>0?ArHq(c9(OWGAyd;!Z=>j2*%pm+Btqs>@%DB zb1c>Tu-l+;es8xtywmCJeR`*8(UtDB*h3#p9V`}~J8b;(!^&W)3-;}~!?1IpbN%wW zdVg}V`f2jS;;wzA-n+=bDeE)Jb^KKr+I$c59p#1h*MDvq!&IMG?T)QmaoQi+yXCyx zwjZzOIpwJzDf<^LzxVZrKjApWf5Kh*(XWQ@UD3OCXXo($H*GfT{ssahD*ws9&wUTI zgGV-5+q1bGuL`f#t*shFv;Aqf0|9D;wWtm0;r6oz1M9Sg={8t~HfSJxFxb&PBhNl9 z^Eny{vnU4(&X%*;ls8pTyRL&lZ=on*6jY*6f~ipmrNr?uSYV-G8>=pHU6&f-x*X~{ zwo0f&9UH5}u`$vt{m)u^W+al+2Z@=H1U$@Md#&$#zxN`v%wz|K!<@wwsw@FZD38~Z z(ArH4a%0<%)n(w5C(-*wH|{BJ*B`#J&uCOHT&Zf=|DCsEwv`4kZ8gAHk*MnE|qFp!oVxgfgn5CJtnhP$6L*HBovrp8O#$1q63M~CEql@8f#QIiXR5Tdkgzr$gO ziK3o*R~SqNlYwiY5TKzcEZdrzY;u_6=f!stgxHsTG}Xuw}~#8!!Efxk#|vzlS?++@-7OYxJ)rI#%RZeE-9b2S#ey% zi$y2`RxH(4P?OpRNq=QGiflGjnY}9hblDO{GQ*OIiCMF`GUg)PDG6dqL}P_ooMmSV z9h2q$Io;rhSm+R(E~AK28mW{i86TsyP7P{qVMPyZ0O{s3Qvpdgmjs&s3fX*g-hAg$ zxDKX|G&f`87#urVJaDnto8#{m?-=7KKd}N{N^6N4KT%xPy&fH%chnzT4VU*@o$5sk zjrJh9Lwb+oatANL(+kn^w#KTpcj1e<&IJd?ijjo`O?Gof-#m5VI(%a5`l6QHSndsO z-E|`9KGyekN8?cdfp@A}^}g^IzyuD;lBCrFtXA`SqY(%^4==LW?#dw<7?pb1$gY}R zuayKKLAVj_gjXS!ArxT%A}fYau^bba<(RH8CBT#bH!}A~+9OT7gfL{bH8bsrrBE=l zO5Ir+@<70=D4kMa=OVOV_ZZZ}EpT{0SwQyteYcB$-aHTe`G5SikXpU3`0C^v=g&e8 z&wKcx$^Rr@?3@q3kN*e?)WUV@OU%W<0z%L&N3|-fbxA58h5@6+XqGGiv)SsRu74q# zcH#>Jm@VLAvP*^@o6QG8!B9GcK`0&S4_ym!MjWF1RBe5pJ`P9Y`B2C;4R2g1_Z56Jbl;I`scw72*QA1RKaeZ?&} zckedmjl)iq>_`^J$x-q~@#%OwS`XVpaOEM`c<2zha)_K9P{|pRe|LEva&VYzCL{Bf zz-BlMI1rgKsBQ><$)*~95CLPdEf{dR07<4)n?vflUSS0{FTsW-gBMm_D*4rY_grqG$N~PBB{!In=QRAfu^mBrDoaU ziP_9n&K){D#|rkzY_B76#F2&Y{7JO>B(<sVXIqcX> zE~CXLegyWBKDdkQI8wZEeusT?6vqr*U6~;6soSqR@pUZ5s)oa!2nwna@zP8ruG|}^AST<^_rC9X{Y&~BH zN}(WoV%2EWBa|G@Yn%=?7V=Wjh-@jOV?D9HSbywnY&3Q)HXc*Q=qy{KGv?Ew@epD+ zlHE&hq%pZwXUvNlC_2|TH##x3MP2M%<9yjU^mmm9fe4N`ki1 z@=C^MWC{-gk7+nya`v_TL_ntH(~uzd~Gs4^Anv~4sYFFN}is4 zs*CI=?S8SbMyh!UcCq2kS3&jExU8?P?wFHq z<>uuVQvb2lvR;Tj{KYSECacrSY1kLEiEv{*0w6PYRx|yAPS94hv~*TcpCH9>e}(Lp zs}i6F*3<;54u&BJLn97{1B+7rfSu0k><2B4uU04W8cCxAs9SRlJS?h%S8H9a&R z+a2~1=E;?r^F{1%SUj!fmKI%5r{;p3*!&Rkj2UWpk{~p$o^MbV}1TG}ZY( zuu@B7r;4DvJQ1bz+|pQ-8Z;}vE36FKN0r!~G)#qY0?WhlPRX3%S8odhK)MPeSt6Iy#gj<~E=v!`O{GV6T7<8d%rhJz{P zv;~JlUu87vwagbRP>4jdYPG0^Ijogyl6kG{sLE?)qb;vBv!PA9~QJFl$Om5_#zprV~~6qQ>e zQ}_zHc@n*QfA^^1ytHFSaa0|FYv0~>o!r_>b}jY7`CGfB;^hcgl?o z*lo~gHS}*X6=rJ}Yf+jhS@F0QYAcBgN};Au6lfq(saRvbmu}D*m#1Wfn8{8nh%1JO z%DlH!ut640t4s@QGh8DptlVft@}hXCzxEU%Xz%1jRbp}k?S}%nf35E|z4_$UZ4(F3 z9{3@#7Pr90s5Rwq4Yj%9NV{VZ1V0ta`_#E(7dI3ZUc<%qkjVw;2tsw zIez9D3%#c-pu)$^PS@AU#iE0DMPXJ(AY020 zVWq87u|TKSN2#Wj>(XS&(tVD(pYs(9PfHnuWMY`d_nvOxzBlpZEbq3utH`xWpJ>fD zZk%^pjh}y_vY))4Ik|+te7_z2en0BFGjNZrCU?nAr0rbo92|vh_$JwV^XB9+s`zRo zpQ#=feprfN@Pi1%=Q%U9QBCNOjs`D0dQM~>CSB)3PRaQaTuZ?OW?ZuB`AEp^rA)*} zWlcoXVV_DBE76E(T!U{$T*E9mRWMt9Ubiz;6$yChq2+Z}1p-x0FNZ`O^eCwf06`x{ z$i&3kvt)OHTMS@XcQOWeIvk^;XX`fkATM7#Ac5VDIF1*h>zO;L=6? zgQo_Cp*=?qAL2c5FWEX7>?*EAC%bTGaS(NpzFZaAO6<$wdVay3E8XNWP=O@*wd#g& z0l0x5L_rOx1C5{!{#e$jbfQYMXbiR0CMqrRGQn*#TshRlBQ|gK#1dFBr^-l~5xDw% z+66#>asWagOfN+wVsG+tjh0rabp)=y5K3d5%eB|jOH~gad0uXm{4u}6c{ao%;jrE1 zNTf53^_luieRHTWFfXt)fJ+om9S#J*G!)Z3TyVMcHHjMf$1?>@LW~7sYhqZJO3Y3m zN^x17IG*@8!5eTa5leV@J5_euWveG|w_81o1@AAIJak2Pa;>dRP0g4R-CgJ`2D}wN3OGvi+cvS&vtC;m>h%i;pv2%tR>wG;1j1|VjoPvEw9|rZg}&? zfhAr2EBl$5w@r0h$bta)=8FKqZeRvF_!U`e4rnx?fXm~tjlk|9IZ&|?nni7dBu-)` zqB@NRaKK8HW)>w!C=L3+D8MuGgTS<#@icr^sU7c>Xq46mv2>FuWRl7-stMk}@AUTc zNLFc4m)jb-b@qO7``QiU?eu(TT)te$-f!Nut?y!$|J4mQp~TN60*T!CbWC3I+O>=D z6oBBxDU)iR@MpjSe)ALHf!*hvEK#icyqZ%xFdcVjjaH-Ds5bhv)XR8CqUjmka)+#S zxkM98nGTw+n%*-_nRt_IcIQndi)8Dxp-~%r*#;$B(3ZCK**Kd`;(-q8u})_|l0{Ms zxg06W8p}Zo4p>r_*%oY}$qzv_rl^kApjC93IAvIDSYy~|;0$8`E(T{x_V5*k7v17Y zpyUjL0}3|K^Pdib=?>S*rnRjl`aXjnQ`wK0IVb}U!X+4?0w$QUCZVf%7cDq_`hM_f z)KOgYG*Ul{j8CHr3ns@=+vNLs^k(r@ETK1wucJFfGisi^4FqtQOsLiivw;S9KnPTW zI*^4MWUIsB4d|1#wR}xH?%^9UnR=;y1Quj%N+*V^s=Pj*i7`VwDUpvwqk@K2za9iY z6AA=_dY--x$|%sVrU9uNpiWFKP9i;y1samchCqx%qSADqFW4+Divqzo94>kYejUZLknhM<8q=^QY~ zhCV~TVbpNVAW&j5KyI)`I?3I3p+vI|RPEIXWXSCF-D) zDB<U#IihIc0IYhSy#;T3#y z^HY}}KT9UM_=OXBZsh(_et7cGDf0T{hxfU8tEH`QV8{N``?lsb?>n{U8PvOB-=XcN z-r2C{NbfG@Lhwt~xbPhCfGSV}mkdRv=m=ar9E(YzK!Bs+cn08uYh;_(;5B$_Jsx*F z9uB*$cDq}nVc4BpcE_$oAp%jUG=e@G6?8Zn4TtGw6bE70Dn|-Gi9>bV8AtKB5b|F0 zK?HnhpX}@MaXRet1r#?Dij0Z?8ZZC>9RprN6nH&fI2(c?HY;%W@?t0unjP90;&eDv z;lQ`jKWT*?Y_$q14fBxaRVqP8{Yj{;`xN!tGR2v-R_{!&qV^fig>#O?j>p!kY-@$LJs!DBFTfLtTX5;#kqAup1B z2%JlTTN-!H!WFf%g^_KO~nr00vg_v1*<0 z=fF!V8uwic#achfjrrJ>L$>RLRJY4oh zFLz?_{U>f{?Qg8zPR5QNMVorQwe>a>$q_QPt_>bW!T$cg`Tn8FD`aka$IoF^5BJ>X z`w2qa%H`%gC%M;X6+r$|wNCgp&;toLK^*#J(Gv@+UGccl;tK?vY6G1-8i55qI%JJS zlrbct9yDRA5j*wz1hqSmMcHX}Iz66P%oi3oYKPV#n+s~SRt{6xOLFA3+JLDtJIM_f zjK;X#6{mn(tl)AT^g+=V@TGh^eINUH3--yWOx{O#Z(lepiguI9{sQa(1puZ-Wv`w^ z*P3RV7Mn0I$)NXTP>_?Sb zIa~6#%+Bb$=|zf$6g&);o%5Ihjhz=>9UOn+b*=r%^4(M5*s=TX<84Qa7mwlx$P6XiT%nOh)989J za^>PDfCJm7bgI3=UjYgDKm%xk1zB`ywKa9Mp;#=PHUd{8?IoH32fNN0YowYHxN0aK z55ELggGi|tEDZVmb@UFcgDcL}N9a7|QCU-OY{JmzYXS7E56iH=u1;H~6Rih$myAd} zQ){dIH4zmxYQMtV@xY#I7I=?(+fK@$TFHOzjWA}6m6OVsmuzoq`J9< z-ojyMJ;JqJUw=t!9a_0%@>BlCvAaty>#c(;`|r=+ysP(#1^YJj9s0(eHJkqUPq+Tf z&Rux;$dTWuyq{mci8@y5*Yo@Cecnq@=V~M3`nkULv40%!B76>#-#mk3&@wqxoww1Qz-Hulj&TKaojl~h zw2tBdXVaO^6`AP`ds=8gak-NAr|fZBSrp2OaAXz9EQ_zml>+eC@@P$!;#(L!$ZX0o z!xPp=D%*I7I%!tc3|kNk4Oc2U8UBL{lP|(c+G9w7BjgLn20tl|f1UiKO@{8r$qM1f zG17feYd+d@h%7sLw0QqW_ksSt$@AOyY}vO9&DnEgKUBj((o5do|5tyupUfq9=eOO2 z>$&$o-$Dqte2H|7@14lu;fq7d-+Bse>3n8r^*byN+N9bq{4H>TBvZ(q{Ryy6jmsXZ zTCLF};!UP#AZau`1nh#qIg`eCQ?#8@%^nJH5=UVS1OOwUtvcuQxkHR#gv==hiYJ^8 z;nvpK)$zDt1U~+}Y?jPTS$4oTHMLNnyp<;FST$WLh3X!%?QUedwWZFzI3*+|B~<1U+d_pQqn5=n-U3r>Dy^?%_Oa zyy(u;N4d%%s zE%u3{A|6*LCzXAt?2A*1l}afCJ4#!slnEtU9m-m)Y)5oSRuBy32cWa;LDiZnZ9&XV zH+6^ZMA_Ezz(s)xrx%pxzygmqDC(R$;R~KI|Uap^l7LpM5pSru` zO}+VS*ABAi#0kFo!zmC+F32b1r#kj-?jIN^UbO|j@rT9yy?X;>&|fuw+5Dxa-68l5 zUi!TIK3cL?Lc96H69UDH$$zW12!93A;2|&v{;4drsyVY-&&_tFVs-JV)(%=$%%+NL zS!dS@$jk*JY3zD|xglmL*zdN_#{P#Mde~1*10{0}>UVjl$E*NKs_N1P1}l_=2dJ^8QZ-ZZ1en&rWFOepn7VrHF*rmPA#L$f zIDEO|ajkW2$5Qg{G4kO6JY9SRb&wm`IdkVf)iK}>eavkhytC+%-gw zU#d2JqL&NXNKASCIPc=5yHT#4B7k3(+9iTav(;$x1#2=!|rGp`@j|??5v{8O{ z9SFeH=Yd_4EOZfB;OZf>*+AhWjZ1R5Kppl}Q3gbZCYh9to)_TPfDANKKIhZ?FXvlEN*q4Jjxv9{Y zN;TKjwPjFS8_Hm#*bJwdVKY7Knq{3m-#i$E!Jrvf`Ynhi0gEo9Xr#T3RG2l(zEgy0 z5q64QB4T?LOKzG$qRpmOu^p=H3SlZo)ntF?m^76Mwll=~x$@lOBf1=O3_WH1+H$d! zo!RBiknERG4&^BPf6!==syW)+@<68pQ7I6dSE5!-VSI1AxINPbzw*o5uO`w}-&jLV zqwK8wzGaOoQLy;!qksJSF!b0L@Ds;A={=#f9_u<#yz#B)UVdr&!K-)4NV)@Ufoa%y z_%K%}UMKPSZNG#;y=iy6@kf8x|CO)L-?KW?PwovN-FFA!C!g;gM~GXr%)B36B%j@Q z?$VaiKO++(b35RCvy^9|{P+1lC={iol`&;CW>cxG(aJrPYi1?42<56O zD2AaEQzVsbIL?CAW;6MKchq~$JLctd*y}abRM%CHz=xhM)YjJJBqnreWCrS2aXQ_EP!s*?LxnSSurCK^H!p5J-h8H+Tim>+`Qv6xdGB0WVbESrx4NNOj z?5w@1Xvn8k_!tUzu3vOy zX81$;s;g12y?C)qdePP%-F5^;{jILp_`nsKcuY znBilx#f?>Nw+iD_tfrN3fe}6?n`KRm%IQ^5!pyU=s^ZYvD(eeXbcj<` zrQoj}Lxm*I@K}G1x`tj;d%>tqs*`FLa5&zhU=8$O7pPU7<{wj=Q5=VT~g#6*%_MrP;+(G%EqkG z(nY1lzJf|&j5fEh2{<=^?mb23JvA{*vuU3~@J+3xCifN{F`D-;-=nv4nwa>OVsU18>4fp4RZ?|*&rE?Lo$ha1qF zU;ECw32N1&22<#3pQiT)cRFwxpX6m=RM)rf=(oX6@xx`aog@gy)7lYwL^iDM`!8>0E7 zjc>zkBP_cDcCqVDrEh7BdT<{;i%0P|=5ZNWo0&mgp0hvbX_T#;LCo5SMLIiEC1aW2 zru$dGcFI{&DF3X2W_bH_mv5R5CsFnSMWW6>kTA$pZ2*UwTe5(2lNG4fxk zr-UDZ5G#ScBRd{?s8-B|I?`ExRW2TnwT1kR9qHO;svT%fP_ohm2t~i!>vdg%UBC}w zunR;$60aTAJi?&9#YI z+SZGOh!}%9J{C(PI&`x-l%Y$TPz80M3L0@$mA5h7phyDjArMmRp#{(Y8h~jQ3$U*- z(*S#MR$x|Y*5X-fW^J4$&=>US!CA*=U7hvbtdD1D%y^cUu2whj(tgtIHt0+=5K-0? zMA1ZZluS%pG(9n{r1d?p3r)}An66~HRjYJrwI!WVrBQ1wrT5)QeN>+DPys_e0H=^x^o1B_CyQQZ;_0w;)pPh^dc<9Utd>y%Fc(wb}h3&bQesbsHGVJ z+F+0x3n3#0fafKSSJ);LKS*;j*T?m9qnwI9oaIJ2PKo2K3}z@tcbZee7DH~@a+rl3 zDMT#C%;9#%RIwD#nj$SUE8xLVchD4#L`wwkuu0&#^CzI`qwX7I%i;a~X0vhm600-z z$qjO6Vjbk+SBj%ZK5=4{92O21AKCx6{d<2}4DH>!htA@$ARVwk8@5GCsQ}&%Rk5g&`5GG)Mn1nQ)PEj_^Lp+>)6Yf^y?NtvsM~jU3Xu26zot83 z8}v*Fj$`-tAK}yM-}v+<)UGAtw|_y3`-`8Ee}AuI-gW5v2tbe_pQ)}1PXZm-@Vr3n z*3={Lt8zfrXbgJYM$Jymdm5~v)Fur;U1$)UMV#>gqsI%>=<$EbVl8bRsoGU=X6SR7 zRH;OMWN_~Y-aNT~Wby$13A$PIpO_fqf`A8c@{#I>@caxCN%q%Nz|~^Wa1d@qwBmqS!Fj;C8~9Z#Q}sl(LkbaoWiMeCx# zBuRqinwC16XtfrDBm@N{3NS5n3SC0KzzHnE*5S@m%Mql*f;R|)^v3lTru;DF-{?n+ z{cHRi{RjOo`>*<^{3^fSMLnuBWnMdEswX!~l2#> zzuE=Af28;p-Z#1B*yI*2hLXj%ift%Syw2S%zJ-z#M*19vZ?49#_iR~xU~9*rXO?~I z>yyo^Z}yWF@DwDsZ{LO+ZruVHG?L$_UKPFzydVQ|aGz|htC514ny6$=1+xyp8<8TE zTOS40@G(#|HGaOTs@9*PP=A^&=*P~vTcnnk;7ZV34iXv8Mw=Z%9gB|8W!-7)v|8IT zUI$$^va>$p%Z$*8T&*t=q&knBY%NrWnp>igY-3BLu`$wu?I9Oq*V+ndm*`9RkOBKb zE?3BhC1BRmgIHfko6}~asRN&ZsRg+=& z)wy7dJ<2wRJCD#}@G+$%$pDr76=*$~p&aL#H`>e{oo+uB+atw3rfj94{F>(BmPof{ zQemcy`RB?phuISSyF!Scxtli+T$woZ0Yd5p zEA*T3ixUZc?UhOJ_U`^?mh9=?{q}Cs2m8<)om+aAYz7F@>HS&ZyNn)s_&JWQg&}C6 zSA7_YI-SjIqzk|-i=rs%0=kqAyC~&}LSJn|1z@6gr-KFFo9Vd4ETRBHc8ripIV;SC zG}p(WF0O|iwBsDlO&hsKa(SQJ=TVzUsVPmaKWZ-3)X}ET0+xsK)@9IMxiAfr;td z6_;SFH=3alo0b24yg=P&WYmc``Xr5H)P;IbAG(IdkS2)EB7{(APcMP*z{KNZoCHtf zAEHTeeSo}jB>(>Uw@(k8x?QXX99Ty_Qavt&fTMJ-?6?rL@jP|}t0^=US3*P1p>&N% z_Z6u$=_#CZAd8#fQVuDO^^r(MuhD8#Nelf`vOZO-EQwSqY2a-(>~KgDFw03Z{qmO! z8m+lj>+B|)HUb5%C&KUit!~!LOr<^#Aolb+HUO{H5Zfh~)<*6)m z-sHAeG%^1e{MM*}qoQ`hEIjEYB1qgrR!4l?)b+L<%PO)170>t(Ji zZ)8%LN&}#jkeSSklp<4^bE?plEA1$o7nkhqOT6Xg7Fzz#0N5F$z!Wku^U2XqPxdWb zM6SO!H}^ybjvXP|%eNPHqLpa$(-r+%^Wg=%NzW0ok7(hi^b=XgyJM>#U%#(Amfqd5 zoPTxVUZyy{Wc|8sZo$O-DS(zOm-gd(pKrw{0z+ovADkahBZTYZ; zlQ@Nol#*skizS?vphPJO30a^kW6iXsK?w$#Vb@o?YI-QGnCi3G z4N78WISR^5I#PjQM~(K2it+of%?6Dw z$;Ci+r?WaDN}{Od^>lb+lws7VmYSD~7gO`uM)#Stx(tdF>E#KFDwSFd zlPQyAayabvkkw)d8rs_1Q;B3S8V+~No*km8IMq|*=c@IRp5E$4Lv?+yp(U5gHZ`TC z^axyj!4Pj~nD4>cbq4GMZ}?gkihfSctSWwhgr5+Br|oL9^z3eGcO0z{s4i@%o@^q*s1T* zBfZ{Am!cz{w=xKffnK$n%BmX0DR)yT4Y*8dq#qA@jww-0%rJBfGo!C8SjMJOq-&H8 z$%t5NHdBGfa!RL5W3?0)QB!F_)5#&DL(_n*8Ej}%Hur!%Po)!^;lATg_zf+b62Rq{ zwqb-Jh77cXN@k*!2Zrq~L4VTGGJL+Rt8v|uXWx42=9_Q}{Q2WwTMILzJ#%Don*5)h zc!En5|Nb7_IX6ZYkqMF~?~&b!9Q@Ka;rUxn6faM{8;RpI46ZJ|Q@ojQqBdw0INUDX@7(`-^Z9`TKvG*EaY; z@y0r`V_Uv`4{GcoSDsiM-;C6cf3SV-+-`tCj42;!z3v2mCz}jrj*|qf)oM5B)d&Fl z2wXQTNp3-{cDw)|12WK4e<;1xYz7X8fzxV{#2Byblr&{rY+PeJZhX(ki^hO4Wn64L zXuN6^bl9j?tUA;*v{MkK)yH#XU4c#kH=?VEL)3A3Mvxj?4{Q&sxXvoDs51F2NkL`; z?KALofWs^anuEX+GONZG$i<(NtK@ERuwF*3Fh=%&XPCdTmwX+j$Wr(x8z&$B<`-5k zdvWsJn+uly&40sP=+%KE#jlb7^#ObY?naA?e+e+~lcMUDfZ3bn2X|%3!Z{p*P10)B z7PHYO`CfvnfR|Yay5Wjpm&>dc1nUU=$^|b%LA}vvdjWO>8JH>9Xx2)S+UxUK^cBaG zhm<*|gX097pzx9fIG5UXr~~Sh`k5WZi!Aw<@2y<+ z(_h>l&M*DJ7(9kvDES|97%`dZxCWpi2@_0mKvsgq?uTKV|bhEdqWyEPT9H(~pe6~QqqY)E^gwlD1fC1{U z!QjzWSP_&WgFLQj&C+n8+GMhXE7|9=94Xjrnnzr4!UYeyAfhsnlxwGpvtSq96p)i1^fQ#=ZD*tfBPD=!taw$;Z}HTymjV=5v>ebt|9_;(uIz`TT}wxnKP3Gy5;D4(#5xkNo7$(_iSGxBkkHzu!5p z@8EyHWyN>M;KFwJSLma|mqwFki!%AuYuC9)d$#Y{H2?(QC7-Eo3ts?kwvrTX%y(o* zRaLdU+GG-Ibai!xS`{Z63>pql=W1E2s`dDzsisy;&4$m@$wY#>mT5E(fm|ac%g7!X znX0Qrk1ZOtI2>ZcS>;BVl%E4ZH(-)}x4SA>#W1VJ2G-T(T4)tGw-A(Qobl|&#f_ZU zm};EexUq3(#pXO!0lkemEnd)_n*Yxmb z`Eefe6>9*6yZ0as!bICU=d@W&uC~I6p#Y}hWams}v*m3_!5A3FueDX-DW~3P{U}wE znap6jvx2InxupbTBTP%D7;~_;g-sj}o5H5%7QrT{Oc4vhp^({Prieo`E-7BU%U2%8 zZ{hWuZ@vUIxw+S`y-q%8tvgJZi|6_L6Ncya4ym ztS_?dpLKffU-!@7QS_4^lHUxptvCjqs3Qg%Cht~JMZ%$+!Bwk*k+Oytr@7=S(K zr^O58Nf;#$!wC7I2fhL`eJ}%fP{m-0bHD;(jO3n!M`W+t9rW;tgeq>*=`4%I8dLAf^Ffcz=A5H}Ygm}rqjb6g*8$7a_&E!MDptt)tR>#-aKdB~<8e@eT6MgR=M5MGs%&bLV+9CRo;6n3Y3;K1TQRUo)-G$0wa+?e zJ!>7aj$1WGY^}J+v_D@k7&J`CHe68Av?>*-u&2t^+N!eOT_q_>dB#+XWyao`il3q~ zJE1Hrdax-%CR%}%Q3qDPGm-^k{$)!!j%DT_9e6*m*kIG|vMgp~XOxMhlvUAeVP!pJ zn(Ah#=Q}Tv-@q>*eLh*dO@2V0E&fNQ5$Rz2+fR`K?(b;qUmN=}{)^(aqvX=j;vRlc z(eT}W82|exAUL`Gm5Ii!S6S?YsZ%u~_%K-}}dBdl$`L(f`9KJlL~j{*iqA z0G+}Vuc7qhowv6gz{2YH&pz=stY7!RrCjbjK;YKY7gbLF-+>C~z&D?xxjfzHF*Z=O zV7IK1RVo$6ypA7%?dJ+Qz|_A@<87V4^BFMtCVE7(rWQ;u z_A&_?mOUNI5ZM&DJVowm?PTO=u0t>j6FtXXZ(IoTh!hW@C-8ek=N_RWv%R<2O*lfjHzW0e$L;gv zS5O+hLdI`*%!A9xHj-wc!M|3$BZPqp7=aDAz-!Oh(M#|#fPqMl8o1(|O)aUZ9jC@6 z&bg)Zqlno{e#x|R%QL9BDN+Pm|7Lhm59fpR^ozY#@ zP3crR9S>AchgB-xrL0&Na4KG|N`Jy~n5S2uf?3hcgU(i!+nd<}u`Pk_2zPR9Kgd+( zWHW4*9g1Nfpu$ziAnQ0kdU9g#NqG1u86v0TWpEeX0k^^h(mryX?1d*M_6p&NS5~j) z){*UGGB+Qp;S=OF@|JN2?0{|XaWqoQQ;yS=N%gLPS$3xz{Ax%|GdjD^StW@wBQLmV z%Z`0A#Il zf0qf6y$>wn@?Jf2^_JM*)7ULrsT}StCZBp&HA2pl`!5b@?Kig! z+;7K2#n(|Y_weKg2l(zI_lL<{gjTMQ26;1CK&SwtYAT=_6Mhe z%HqL53m-dAfmEvBeqN2$Dq~;-uDf88Os1%=N??>8mD|n`Rkzz^b1=c*`GQ806gNOo zr`ORpUZePw>#KN0g`1XS3DF?ORMpE>SF3nEmh@FsdIV%G{Y&}(xm8VRFtI^ zqB{h~b_iMs!R7p-rzY+^75iW0%c@KFk1pe$cG}Zq%<+-Ec{+^ z!;+Q7Q-|I-bm-dc0di42Z@u%C&RyK&7Fsk_Q#Y$eWetQON)U}P9iGPTud5PGrYN<*x*%6oRr&ov*9)Z!M8`n~ zGGd1#7>@>(K|N!ELOV7D4N~5aNW?v!$R#+72`v@c=R;H@FG4pikw53sa#pigvr&UZ zO-l2!220qZ@n~?A9$irzAIEV;fl#4-_TaM^;ZoKSdvunf4pu!t0G$qdpCPel*UpqJ zwOZ2*qDnN(%+39yY=!k%36h@f#Y%0I<9FJpX{P7&z!@`M=fY#P4P5>W@*-Rg-tJC z2*LPsUb=yu!#<631b$t%t0i^7giS$}L8l9~nI!Ip#!0>~xv}CdH9o45R``2LiAP2PzH-9p`BXU?se-L#{4}2B-@fWCH?*PD7tz z(7>6nL8ZcSb$uSo4sRY~9x#`GLxHlqX?`)_d6rpjDQx6-@&|d$%hk1c#aDw~=NVL; z$_(s5>)L4#!^)3t>NU5vR<3R~)tW6kUb4G2^S}|KIMc?eZJ{Q1DIwbk5g&@cJl{Jw z@x~xto`#E1yd!zy(8LpmPARsuXvM@ET&DQp6*A1#lWXX)$-R5_sZO?$Mei)nFIwB% z-L+Ejrk$8i>iKuc{o7Pt^z@WQwM57QiJdxra8K6y{63?_ZwJ(3rfbOUve7cj4mkMe zu-gue#vr|8pNDpodKn?9!jo7*6FHlu9Dzgy!5uZkVXcXbIXdEG==-w+8)TS9; zfHMoGX;K0W7J;l-QvA(I$(;X__*prX6q7ky2+lhyoc`d@MXmYOT|M{rLn~fTTrhx! zi|?YU$y40G#D>pQiO(;+tDe8Y+{5oF9xm>C94#VGpN0DU{pL1~{dT=9H8%9I z4R+c3ZP#qL%XZC%e$NK&HmIW?jz?&F21V?gu5e|0ArR2}j7F^-ughy?r#G+F>h)22 zdBTNRdid{pcvTP48U4$8BAc8nZ$^Sm9v4u8r4SCP8Aka zvsK4cXH=XHtK^#cyo#52ANDETqKE?+ZNz8rdl+N6t|8xpA%^|bK4=X<%-T@`{Q!4P zXJ?-C21}j8rd}qoP-=@3Ow~J+^sE#cYc@?+AK9`MWXV7)yP8G9(eNTzqMhW*GfTzJ zm~OJ=NEl_4EpM%$d`~KF=uy_(MWP{rFICbQ9h*B36SBYf6n=AX;^yG7)5$a(g^zFV z-+FpK?1J3n>YL=~^F#8qI#XR}QHHbXOf#nK2HjU94m=+w3eO z+Gg?d3dPCCsAsN{ib)YrU>EiSmkao@(PD8@(ra}=w9K|Fwyd%2v>db?x4dk*YI)D1 z71>MrV#*@uu%$9MXpD5xHGR>1J zx7gErAeK}DE{*mhQ3uDHsGF)OgjRB+gOh!OBe~pgy?h{(!5h%AuF1>AEkc@{p6tVY z=$n(<_wMChExtYa4*7Im{`D)D;dXSwyYkdhC%Jc+BuNBdaCS%E5pm z;E)ijyDt22+pXEn+-iUc*SF%Uc zGGpZ8PSi&qP)YHPl=rw&bZ1#UK&iE!t_~{|_X7qWxsOWfSY^K}Q9u8OU2owrv?x>m zOk)P0zPV#aYkp?y6ZelnGj1=gJc3RZKSBD>g!Ka_()+jF-*uClzs$IqdzFk8=k7xz zWG&!8kbI`PC1gv5Ko#{@&}xy>Y4iJh4l143NjjZDq@+wK6b!N|LDoqsj3X+G&BjWC zAz5W(IJgDa*z7sTJduJhC%X%x;#4MvQlZ%)tizU&CB*BTYA0*um4n?{kmwF3Nx&40 z*XB(IpF~OeO>$cS0C%Wp?o(e= zb5^WY%7gmCgLQ<+2ly1Plneq-bF^5=K%vnRDq361u2nYm+g_ZtwaTnITdVjWPcwZ> zd6*AmIh5`i=G4H#{z~lf?2HOuv1p(?ePvLrv{H;v2b28i6BEZyyr>Emt@D>JJ3;o5 zxmEK}4(^}a&%ZKpjO!*#m%$;pY(04zeS_5y?fpxa7B3=1UVo!~*(Y%Qq)Zarw$1On zyYCL*ft&nBbxZhbpaLe~px%)1Tj$g!oq--*2KdN1(M~~?6&Gv)SJWvvOA_Sevd-+Z z>9FAQcw#KS*C3iz7}u&*p>Vi{*>qACJ=>dq7X!bQ8_vo z=J7833P2-if*LGoRI1r{F^Ai>)4c375Y8s0m2BTs1+@I< zvZ+EU`#_sVb4uwRs#tMY9tb>O$VHAHI5u(e*gWoh-*DU9?OTd(KheE@>#}$1;at={ zFH$@~Zjl4U_v4Ky1D`-!CQic7is*@6ZpprVM^0suYj?o@rH^l4-HYaC$kuDi=0PLe zO;(V*3+6&K9Qu4Y+)VZZj(MzY5MBaiR$*4b=I4A)YIWcOCivC!Si-mz$gz3|(4@sj zhioC{)o&17z$OSb;Nl{hAl)A9qO3C*M4RY>aqN<#6`Ouhe+=pKFUG*W+4Rt1-sj9rIoQjq0NZEV=md(GWslSRVOH0}9OA*sjuB`wgQPE`bM_{=+p+0mb zzX|U+xbPWt{n*4c`F_)!kI;t=_$S9E4ab;+lLq`~;treV{UA8-W>d~WJ$$?>6ANePX_&IFJL%M zVGfx@#%^x}G>>Z{^Z;`fA_`j3T!=)RA+3`RWQ``M zWy~f8R}Z|9$hg)rM3kp>xai8#2Va^>t0aAiU?@nR#zKr4Qc3#7o(TtTjPt2!EcVbh$;oAA?s74g>W|<81tDxC`68hRZ^|Q`&_QTPy~)g z;0@xhx+;P|1R8K8lBjaP+eV6kfQOPOJ-|)W13aDt$} zmyi-YiQ5SVB)Ss4iM~XC;zoiKaDwMCTc^0S_tf>)Aq8>k4it=aum;nw^d@UTG2jqH zrRH-LuREZFm>pys(BUwYi@$Q6oFF8hM0JQz7GHD-Z)PjLtE6GQHZ2(7_`(^XmQIh{5Ir735Yw@d)&C*dJs_VLz-!RW+w1nI zguM&;<#^6E}m>ns-FQ1d&Dhp5CpD_k&P)str z3NcA56k-V-68#YsjweIT`Ew2^Ir<&QLE^ygtSuNFQ18HL{t*9=pW+!RQNT-XUxC+1tcDf{ zQ&iAPxyb)U6GWC21uKYMsz=J@ zqU63HF<>I471@0&%`LHyBr|wgEkudq1&%NlymhE_Z3x{gT|@cLGk5pOC*X_6hC~+} zf_qahpMl%t{e_nXw`@N=xb2rd_Gh2(c>Q(u(c_*IFa@{lgR>o$&O&P0fq+Loy-$`4 z`v$k}@1I;0fwuG8HOvP?T29^ zNL~*CD_l8ji#dt7jSHxVn@SRfY%bO#im7NVp?7N}((NKG_IRixQYc>VxI8YKn?w!K z1Q6UlcgBq=%fcC?EDOnHv=-b9z`eL158*5L2Ic@B$4G}Mbz5g~6fm}jLIEKW7=z8j zMQ@xw5NT;*gvEh`m;52e9wlo8ii_-*?GNqPXy0W&Yrkw~bOg6UCf7Eb#$XUMbkbE* z)UDEN(x62e@^D?lXru^Hk*p0+nGq5dRh7T;v}-2gt9pEp0a%#@UKV+!y&xpNQ*OBF zK|+OXs@-6DIZ$Z^pU4U{Sb|EhSc8y=bdt=Vf;}zC6Zt$^d}G~!M%=e{!{jdyly<_q z2d*8!Cy^j;-&Y#Bb`9SoE??~59NZsyaqC3S9fVL}iS9+_!RPn6GZRM#NAbPM@or}4 z>4;dwfNa*;CL&5}c0EE3bDw0jZNmnlo{&LPVHum~tiZgv{k zco|#=Jdo_J@=VF?J$%AR;zB}8@2YroCcra4IYs)3>(y56f zr&zGr}7=#(J9}_7oZ{Eh~++Zy}Xk%fA-P#?Ks1ne1smAt_|NFo6~vX)!oQ5 zF~s(iLhAqn2B&y_1DB@Rlz1n+PV?!SVQeR+3ByL4Na|~?85_-JBgRe*UHoe#-e@+O zO&XhtW;vZz(d1D`WjdQq14!5Fs3C)M4O?D4YP_1XW|4-`VvUj(?L{K4PGJIz04DDv zc@LF^*5>L)5L7uLWf|IPz`~htUsfrEpE$YvGjrG=ck|T5&Qn}+Vkf)j@nO99Sn1v| zG+MfcTwMCIcl-Ld!xKB1#gj*Rd(j872VihY{w=?hOVBsR5Azotb~_eDdf;5dR+r1{ zHd8Nn$`aROeUNv1Jbr)q^pSX%)oOOTsRNU?Xmmp@<90iUJs1f&!p&Obz}V=3TE=1a z>-=Ri7NZX8u#TnU@3vwW+r##F2H}JZ7!f*PY{xzMlil*x zraV%)WCxe{>}p>hH#D&YPZC3;16}iP%abpD_>ug^mHD$jgu?)XBl2(f4O|DkWO?|v zG@5&caXLtg#Cn&<<-s+?D9h(|G?3TqSrW;d)uhkj`fRoy<0d|z*HCYEt;9#ex-itD zM3}BB>Jpi}E>C+3pH4aYThABWg00-L(20STGAY%T8neYrpm4>a!(vOklRzi|;T0X+ zL|k759lAk$UpMJ?=?>|x>lpgd6#*_1HVFs_f`G;axJx)BpvxAR&InDFk%^^8IB8-jdwSwDl;!2{q#TFu44_cyeRxOqAP1)tZY*1?v8-RbUd17K z_kfJJj?YF{ui;*s$fKcCdtTmiihkO0@Gduhv4FUBEpucW{19+pzg*%sa(_faCjycn z2U=lCvbQuh=9}})dCVo^aqP6)u|J#jQW}=Ql*t5x_2GJo;5CfF<)b8+j2xm_L5uM$ zJ{FDEdc9$tj)v5EiH}8T$|TUtHpx)@!xjiyppI#2$v2Y7l5$0VO{@lLYieqcwkE5} z!fc~62!k1m6>?Unx9T#faM){3fs~N)rLYZ~Qe&`LYAhNJ29vrg2E`cUV$j#v-#FBW z7dJv@Bh)rR9BVY08e>=kmc%I%4{6y%{57ig=`E{Iw_YI5odm={uuZ!XFyXT~3sM3` z5={vN5>ST|&V-XyQ`nc1*!9IHBX5?ZDN=TNFG2K8T^aSq3X959t`$#a^%+Th1?g%k z%?k~w6;%Qt^-3pS6Y`i6Z6pxIR=TnwFuv9mrW`d$u10c2yCkddZnD!W92$l+O=YWy z=YMBxaxaH7DDO&oyY zxjo?odgBLo{~cyi7Wv1&{jK~>cMPujpMSGcjW+|`K)9)A<+<}^2M8$R?*Y}xFuuHE=T=bXZdufO=*AH_@A{hi%| ztMO+H{y%y)mHy}6WXpk0fPiBP^Y3#12&^Csoj-$?pTo644KRHEBExWMwa!C@wp>K1 zS{Dkbd_I+`#%_=5tyV!4_2ICN8eZzP2DKoPdPx8xrFRHI*lN_n7OW>~cY4WMQ_z#1 zR<94+!b;ujc3WM3r^~6}**q?S@UX!aOmgJK+E~G+wgPKeX$50$96;*y>WLJ506ruN zYKnN;=EUYLfmK+9Glb`r;pudB)mrv+tH`IdrgIfD#{%3 zCS`>O%yb?ylVaF~7Boa(4#t?jdff8uUQ3eO4!K|GzvWM`C*@rCAmd!iDr$)uVkOjWLleu zl;=e$n{Cf@Je?V%=#^9gr4#8mu8S)hJ&VN|i`lHAO{_CLUH5cd*yJQE&(WgK<8gL8 zMRlmuyq+I}?W0Alem2cTZBn9`OoGG4|oII1)l)5 zmfY%+r8ZU|TUrV9f=M7?}$>fI3`R=}n)_!R=V!;3J&0tV@p6$y|? zR0d&+Fj3_csQ`DY5GLB@mg_$S243cw(-##*3-YY2W--IlF-w)I=xi)oHmEfzx+!Jd z*DxYx_hk{ire@X@G!b#5nYPtFlZlTun{uWwY-%ot2QhLaKftieXUE_@olbXcdACmN znYWJ7A^Fu~^4q83hhr9p(6!X<%E+IV-jr`2ah*E`Q;%(jzAwuV9ln2m*LN9>JSM-! z{iO8x2lBQF0#rlum+R2c(fi++{4vh0oc#RQ;l9&8*Ol#ep$m|EoCj%*BNu(9Ma<)TUW>C zumR}|L@>X$s4?oiI^;(>l3sL@!&lG|rFj` z=3tqxqC5l}e_sf3VDb|tHu(`g;IO%-K=-J@vLCt)7Rx)u(*N7i0>_I};7{bXObdKz z;+j7ZaFyym|uqSJ7 zVQtuv$fr_KkE>N^eM$|NgBD_W0dU#Ot$VmJT!x~o904sjN*!$VjlgX-&vw_lTtTX> zaZz%+qprHT1l2;zWEH(S;BeGMs9`Osi-O*|jMtl~!zQ-gMdPcnsVQa4r^pXmi}m^X zyw=uYY~9p~bhx$EU?ZU;T`X#JI<1LF;I&KYqDc~B1ruvi8c@F(14*Zc~GQt&|B~C9!lr1%Pkn>u{V$EEZi?ojTtOr=?~Uyo>KxpJVXNn zGV^$}=&a569+H#KglTLk&f1CRru!AVbQ~CUF zNcKQl%hxdWKt#*8>uW>?+M|(ZdiEGxb-vwK8zM)VQ{6;l*@g`fN_{dJob4Fqave~# zSfY)Bt%c?pXi=1BEDDfQ^omH2MKQ`aqLdpKtf3a$BSoLPAwdtbhKBldx}F4xrP$tX zPXhxqVvoUNa0@!>#n>u&i;Zdk+)#(zX#mo09CAqBSi#ZO#74I@;D3I$>agsvf{^$NWX}@vX1I zuSy0}VUu)7Ixb-#LGAomUzHj-u0i_htofV^JPX0I{m%|Pd+u4rfuAk!BcG*u>ouOj zvmhQ1xrpqfWF_U^lnbU^&_xbb7b)3YWN=L2L6!2VJPE37A*luI3}rb-dM3WOqG3G4 zVTN>HGvLgXzjUU&@#dL_Y>pb5&Rl7yg$Ly}jgFKm4Vl6xPM5uC1WLg$<>=<3s+7Ps zH6u)g)pMMk=pvYjY$9+rJW%MSj-&p(GPXy<_wmquScAh*f? z`a2k(EpL(k+e^TR+IfQza|K0V&8MrPM$A$w$Nbf)?6pGkhT)Pc_S{g{r z`>lyY*^Q|erYcSS(o?^xF3OtVoeW!CAphgnp%uvpeAci)MTA`yC_;L z#(W~m25?wW=&-?WjdB9V`D#OCP45J%sqvAHb`>^|EN%n>7=tS=K*-LKl;x|@8OC*5 z?cBPyXf#uwr|G+{n!Z~lOEDutQPkHEfi)0=`IHIy1pVI5AT+~pHR zsww(*xzD;$hx@GimK$Gj!!GwZ_Z9cJn{m_pzd1KUnSFD)zf5mVY_2*cCRS{2sg#-3 z-em@dwRL(_q5S%aFISxQit{zKYHd*zom)OmxBOc+J>9^Ft*sSH6pBwK`bECL6vD-YcUD&UfT#XsVX12eU8QXB^6fVrq! zii>9P>8Cq81#^3QON$WIg@az!A$4@b+GfqFi?QBdn1OzWMZ=STy@2z{EFoyD9EG~Z z`W*3eS}Ex7N95B~ zI~H*}L36c}^x5vWS%Oi^7;HXYj1rf=<_pEJ&*5~8!RFCot+PXrI;dlxB(=>F+GdTx zJXr>`K^<;uGv^ayFh5*OHq(b}ntV4@BxLP$9%u4W9ucWHL=@r>$U>04ogL3&EzXkc zZmLTa^2uyAna9W+6Mz|zIbcUIZQf)?1eA+9%)89j%{XJ0%t$c%%zfq?W(Ju1%(u;0 zXRfIMs$SI<)eVAN^k9{W)6)~ESuzwgfRng>4m&W18puoWq9Ki-5v7qLjB*)WN4Jnl zdBFV$`Y7~%NYP8#OaP}dmk86E!wO(c!Dd%Rd~_K}(ASCSS@cYjM72qCRFSJ?@>unU zzFdRbNeN}ArId;Om!>^Or#*xe+OC4^50{PPt7?`xt3UjEdbG;D6t4IpP~dSSOsTtQ z>lHXm2(|raPU&@c=GBSArI!yLA$Ljtg9kfya~k=odHpfr-UCGAY=m~)=n z9@ORO^&n3fT;=f~qDq(`(N)FAD*G#H5>y`EmPG+t%0)^`W#OvmnUq!Y%Zm9qg&CWk z2K85n+qsHXGvUip{uH*cOqk=DaENlJLd_9O9z`>oGtrA5CW~;67wsYn#Pi73@@Nz? zFpK5~9HsZ=8}eH>&V1I{2@S*jOXkdr&;N8AUh;A`bl=@@Q@;PQyiQ*3a4bH2mD~0D z@IYx&-u+gp$+fWCGCTjl-E(tVMn8N9O8Z}ISqw+fQdMd7+AEj#U%EQEl$l$YEAM>( z7f_7tulal2SzrYjkS8V#Xu&YX>=^v&dE|7~jKL+6%i*0p+uxQ5hlBM&zhBo@U*DQ; zt*zyG9r3u+w`BE*w(wKqk^?#PdI!R$j%Zz7I&HH6V6$nO8)yc#Nv4E1Yz%wDi^7}2 zjFt({p4}F$Bf$^_b>!TRMuRpA%1#3t%u|m_vT_HoS+W&7(hwWd-gG*RwM^QQwggrF zARP#3ntl$OK@o^krzE4{4}d6$J`roNsA~p_Y{7m~Nc$z7Sn#td z@_&&iA_Q3BOTrhLbM(nL%WNWmewbEf5Gxc4cLkwSu7JswdqrXemE+mGnI^^GgCi)v zI=v8A7PS-zK8^pW7)X@&A+5QxE5tMotfe9covjjEX5I|sI|>2U95Uy)FI5+~{Oa#< zl7MAVMeMh+As6(#dM=Y=cTL2a+StAWkJs)0#->0U?7cmlOfhY*%WuP0_>-oX?37Q+ z$7DXz1jnK6SA(zJO2R$N;Nx}5$I{6yXQ2pf%%9wb%a<(dn?JYY%NNjVo1br+OpQRX zCBNaH_AT}NQg1c6+QIg?iFOj`bUHB++eHWotVE-Yse~S(jGR+6S4ilg zvn=eb#2o4OR^%!)xI`}fq|Or^Ydn!Om9}mbl^x%_WlL4QzC6*Ya-@{a%Ey(BTBgAa zl)YKm%a`z?L~8U4r*ozb#*duL*Zna&0G;IeHycI;dU5nL$0B)_tlSzPK`_QBZUH$HgWM1_(6 zliy1(a|1kiK`RKN+CXxffvB74^J5Tct2V32cX^?MFT z;z%>SSldhv(W)BTv^ZP2rzbH(1rcTxbXD1j@-NYTUg2pe@WK}IMK#Nm^9gC+DOMy+ zm#}3;H-b5&i3G6I9J*#j(@@DU6m$9nxh}-K{N{2}OznL9R;UTyhr8Q0Y+t(sc0DRB zmWSjWq1h-oaCPl^e5TYj8INb-F<2;U>)o~nZiJS}6F1~L$xe6`e|K5eKxy8o!oqo{ z7HsTZzwVXKp?G?5eN=T7Q)ne|vK8L2O%_E&b^)kCk$_1YkV@j+ra*FdQ8*mLPVDpq{eDjr0G&x? z)OZZkMAvB4xa=M*@@|rLSvHQ#b`H-COFE#`5rBqtG#bY@5 zW+H>LP^>^7-2v*GLqtMnm{QU%KQXOau6%1+7|)cOVai0Q`8m77%r{kNqsoUO7ewq! z?ICgzn&{9!s;mPP=cTfDF4grUm&J$feSh-r@t^6q(*L(?ORDR^mSgp;@c%^cG{c~e zN&?5@Z%&?k4PBC2NDI?UJc@*>K%}3|79aNR>$OOM~-;ucs4=P|dGd&TB_H-zk#dmzK zc(88rU4st}z?as_Yvi5drJhg$FWoxX`6hIKxcZ)a9|mCR+8X(j+vw}?Fgj5hl`Z|9 zomW3R3eh$B&eb_RAHp^0{nID+zcP$sWBvQC_EX8whx}dcIPiinNWj#2t2JmN{hG~& z+-?^ZRM_Qk1U&%Yh`~ho{cFy%aUnhiS4i4AHX;PWK3_lxkTGCgFj%iDAC1LfDFPHG z1)y4!9*-*=j>j3d;I`2_wr#X%W*CRsq4bdsI7bQ=)2viGwRA#raYxCPoarE5)tX zkE%E8$BMic)#$AV^eP~Ms-jorhNbMu>OD*50%h39%v*J)ueAsL>U)#Jcs&Cr{{x54 zK!{V5Z)1%2P9FPz(BI8(D*f4eL#5^vbMo5mz570R+`qN|mAwbPGX=kM;Gf{X9Dt6$ z{q6xdbohYWe5ku{9{yHdC%-#~NsS!YzV}tQr02lM)>nv&@RXUq%l!jz5kYErOo})$ zwzKNlvzz&hugTidVs6t5f~d_v01Pb8=M6DK#2qJG@Vu{yqDz{A2v!)&J$w9xAdNfSqi%WRN3qs$s9rjpqtWiw|o*}A5hCbDxC zi;)^{7-FO1kE3O3!(%WxQf#4?tweFiYV;X1M#+e?HMK@#ZB3Tp{X|9UhKNO~-s~=j zW93!9D6aBDqu=XK`xp5cE%x)|e}!l|wMfq5Ll&Yb7A|5}v76Xi>_e7iC2xdkaVWxK z)6Qp!%~i+q@&W_U&dF4*Y@QIz0W%~i%SykBGzZNMA5(fQ+1E|qAC$5B~bt_Y1Rc ze(b9~5%R$u^?$o(4vM^aa&nA`y!$qsB*0Iy?o-b$ zfp)q__#MB7`#Zo>ot}DFki0gV*{{`l^`>Mpsy7snZVW@c z5Qb$sMA#m-8$nh6uWh7=F|T@!_DCv9{N@!XE>EJyE|?3vnpcO2?IW^aJxTa_MN(BP zcDZ_7$mL2?xLF^Cn{6ia8ikBk(K)TM^qw^6thnh^afD@WyfW?Dq(nx#!o{9;Va(0^ zVwzV>P?Z@5tk$mS-&$pl%KoFba`P*C$IKdgoXlBfI#;GN;X*Fu7r#uR~(@am_ zK!LI93P?2uQ<6{w2q4xf>8%ATPnYdPrS^Zb zV=uQQ$~6FqCw&SD;j!W)mMfE)6el7DctdX>Va5#{L@NL5&^SG0#V}+8_b`>qE8nP{>}3V{wKd%D<8`COMt4+8e~0w9C`u!Gvw(s=P}s z`Ywr9Wp`DhN~jPvs-Tu7?^=>rNyb7kmM1@M{<^&{E?$NI@Wg~`2&rHEY~X}^qv^2RFEb0)+73dA z;a>RjW&5{D@_K@V0SMTpAb*cL53Ha8&XF`KRWRsDBy@`RwAP+ZyYwzkO$|ZHenUaZ zN+t@G^>}g$D7K;D_k&`|=-XNs)$6GV_3V*isKM5tz@hy%pP&^A4j(=IJao%AOG+1g zHh9?qN!O1IHiz5ou;F@;NZhK2#(G$T>xtAvJ<&9+uV7_`BGZK-##|2|`fs$YAGOy^ z1FQ+u{t08ADx{xctm#>on2DxTAeO%mGn-3SA+oKNeIvb!Wos4l3~lC_sM*FRPq7&n zwh3kHf+xKJ=D$2n?sX5%${qH(8AL2-3_A};mY#$rG@Oj z^=^yzEI%y2`}ifiV_@gJ`EV8dj}o(I-`;@}Cr-{Dkmuax7A&=_ho=Any;JS{5$>OX z14Losyw~e9k;c;KbGd5CU0VxR4!g-s_56r~VOa`&Ry*8A91RBRB4hCRi&7K-6ei}I z9cA-PGtY-@o1(j-2t=WXqtP%0&Ptx58`MH=ZLQN7g!Ul0NFeA7W`g}e#({%0D+Z&5 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 W?f<-+0B+A?a0Ci2t{ZX^6#oaCfw4OP literal 0 HcmV?d00001 diff --git a/StandardScene.Core/InterLock/MagControlReleaseHook.cs b/StandardScene.Core/InterLock/MagControlReleaseHook.cs new file mode 100644 index 0000000..aef402e --- /dev/null +++ b/StandardScene.Core/InterLock/MagControlReleaseHook.cs @@ -0,0 +1,75 @@ +using System; + +namespace StandardScene +{ + /// + /// 磁条管控区放行判定结果。由信号插件「磁条交管进程」填写,Mag2Car 在 StartStop=12 停稳后消费。 + /// + public sealed class MagControlReleaseDecision + { + /// 当前触发点在交管表里有启用规则。false 时 Mag2Car 回退地图 Fass2_ControlArea 字段。 + public bool RuleFound { get; set; } + + public bool CanRelease { get; set; } + + public string AreaId { get; set; } = string.Empty; + + public int Capacity { get; set; } = 1; + + public int OthersInArea { get; set; } + + /// 放行后写入本车报文的 StartStop,通常 11(管控启动)或 1(过站)。 + public byte ReleaseStartStop { get; set; } = 11; + + public string Reason { get; set; } = string.Empty; + } + + /// + /// Mag2Car 与信号插件之间的管控放行钩子。不让 Magnetic / Signal 互相引用。 + /// + /// + /// 磁条交管进程启动时 ,停止时 。 + /// Mag2Car 在管控停止点调用 :有规则用表判定,没有则用地图字段。 + /// + public static class MagControlReleaseHook + { + private static readonly object Sync = new object(); + private static object _owner; + private static Func _check; + + /// 注册判定函数。 用于停止时只清自己的注册。 + public static void Register(object owner, Func check) + { + if (owner == null) throw new ArgumentNullException(nameof(owner)); + lock (Sync) + { + _owner = owner; + _check = check; + } + } + + public static void Unregister(object owner) + { + if (owner == null) return; + lock (Sync) + { + if (!ReferenceEquals(_owner, owner)) + return; + _owner = null; + _check = null; + } + } + + /// + /// 询问当前注册的交管进程。未注册返回 null;已注册但该触发点无规则时 + /// 返回 = false。 + /// + public static MagControlReleaseDecision TryCheck(int carId, int triggerSiteId) + { + Func check; + lock (Sync) + check = _check; + return check?.Invoke(carId, triggerSiteId); + } + } +} diff --git a/StandardScene.Fass2Simulator/Fass2SimConfig.cs b/StandardScene.Fass2Simulator/Fass2SimConfig.cs index e21b3fc..c400baf 100644 --- a/StandardScene.Fass2Simulator/Fass2SimConfig.cs +++ b/StandardScene.Fass2Simulator/Fass2SimConfig.cs @@ -24,7 +24,7 @@ namespace StandardScene.Fass2Simulator public bool AutoCompleteStationActions { get; set; } public string NodeProfilesPath { get; set; } = "sim-nodes.json"; public bool EnableFileLog { get; set; } = true; - public string LogDirectory { get; set; } = "logs"; + public string LogDirectory { get; set; } = "log"; public Dictionary NodeProfiles { get; set; } = new Dictionary(); } } diff --git a/StandardScene.Fass2Simulator/Fass2SimFileLogger.cs b/StandardScene.Fass2Simulator/Fass2SimFileLogger.cs index fb553d3..5c8a719 100644 --- a/StandardScene.Fass2Simulator/Fass2SimFileLogger.cs +++ b/StandardScene.Fass2Simulator/Fass2SimFileLogger.cs @@ -86,7 +86,7 @@ namespace StandardScene.Fass2Simulator public static string GetLogDirectory() { - return _logDirectory ?? ResolveLogDirectory("logs"); + return _logDirectory ?? ResolveLogDirectory("log"); } private static void EnsureDefaultWriter() @@ -129,7 +129,7 @@ namespace StandardScene.Fass2Simulator { if (string.IsNullOrWhiteSpace(configuredPath)) { - return Path.Combine(AppContext.BaseDirectory, "logs"); + return Path.Combine(AppContext.BaseDirectory, "log"); } return Path.IsPathRooted(configuredPath) diff --git a/StandardScene.Fass2Simulator/MainWindow.xaml.cs b/StandardScene.Fass2Simulator/MainWindow.xaml.cs index 49ba71a..049146b 100644 --- a/StandardScene.Fass2Simulator/MainWindow.xaml.cs +++ b/StandardScene.Fass2Simulator/MainWindow.xaml.cs @@ -43,7 +43,7 @@ namespace StandardScene.Fass2Simulator Fass2SimFileLogger.Shutdown(); }; - AppendLog("就绪。配置参数后点击「启动模拟」开始联调。完整日志将写入 logs 目录。"); + AppendLog("就绪。配置参数后点击「启动模拟」开始联调。完整日志将写入 log 目录。"); } private void StartButton_Click(object sender, RoutedEventArgs e) @@ -317,7 +317,7 @@ namespace StandardScene.Fass2Simulator AutoCompleteStationActions = AutoCompleteBox.IsChecked == true, LogRawFrames = LogRawFramesBox.IsChecked == true, EnableFileLog = _config?.EnableFileLog ?? true, - LogDirectory = _config?.LogDirectory ?? "logs" + LogDirectory = _config?.LogDirectory ?? "log" }; } diff --git a/StandardScene.Fass2Simulator/appsettings.car2.json b/StandardScene.Fass2Simulator/appsettings.car2.json index 2fae109..9c72e3a 100644 --- a/StandardScene.Fass2Simulator/appsettings.car2.json +++ b/StandardScene.Fass2Simulator/appsettings.car2.json @@ -20,6 +20,6 @@ "AutoCompleteStationActions": false, "NodeProfilesPath": "sim-nodes.json", "EnableFileLog": true, - "LogDirectory": "logs\\car2" + "LogDirectory": "log\\car2" } } diff --git a/StandardScene.Fass2Simulator/appsettings.json b/StandardScene.Fass2Simulator/appsettings.json index 1b0ddd4..3162adc 100644 --- a/StandardScene.Fass2Simulator/appsettings.json +++ b/StandardScene.Fass2Simulator/appsettings.json @@ -20,6 +20,6 @@ "AutoCompleteStationActions": false, "NodeProfilesPath": "sim-nodes.json", "EnableFileLog": true, - "LogDirectory": "logs" + "LogDirectory": "log" } } diff --git a/StandardScene.MagCarSimulator/MagCarSimLog.cs b/StandardScene.MagCarSimulator/MagCarSimLog.cs new file mode 100644 index 0000000..29bc440 --- /dev/null +++ b/StandardScene.MagCarSimulator/MagCarSimLog.cs @@ -0,0 +1,131 @@ +using System; +using System.IO; +using System.Text; + +namespace StandardScene.MagCarSimulator +{ + /// + /// 模拟器日志:UI 回调 + 写入 exe 旁 log/ 目录。 + /// + public static class MagCarSimLog + { + private static readonly object SyncRoot = new object(); + private static StreamWriter _writer; + private static bool _enabled = true; + private static string _logDirectory; + + public static event Action MessageWritten; + + public static string CurrentFilePath { get; private set; } + + public static void Configure(MagCarSimConfig config) + { + lock (SyncRoot) + { + _enabled = config == null || config.EnableFileLog; + _logDirectory = ResolveLogDirectory(config?.LogDirectory); + if (_enabled) + { + EnsureWriterUnlocked(); + } + else + { + CloseWriterUnlocked(); + } + } + } + + public static string GetLogDirectory() + { + return _logDirectory ?? ResolveLogDirectory("log"); + } + + public static void WriteLine(string message) + { + if (string.IsNullOrEmpty(message)) + { + return; + } + + MessageWritten?.Invoke(message); + + if (!_enabled) + { + return; + } + + lock (SyncRoot) + { + EnsureWriterUnlocked(); + _writer?.WriteLine(message); + } + } + + public static void Shutdown() + { + lock (SyncRoot) + { + if (_writer != null) + { + try + { + _writer.WriteLine($"===== 会话结束 {DateTime.Now:yyyy-MM-dd HH:mm:ss} ====="); + } + catch + { + } + } + + CloseWriterUnlocked(); + } + } + + private static void EnsureWriterUnlocked() + { + if (!_enabled) + { + return; + } + + if (_writer != null) + { + return; + } + + Directory.CreateDirectory(GetLogDirectory()); + var fileName = $"magcar-sim_{DateTime.Now:yyyyMMdd}.log"; + CurrentFilePath = Path.Combine(GetLogDirectory(), fileName); + _writer = new StreamWriter(CurrentFilePath, true, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)) + { + AutoFlush = true + }; + _writer.WriteLine($"[{DateTime.Now:HH:mm:ss}] 文件日志已启用: {CurrentFilePath}"); + } + + private static void CloseWriterUnlocked() + { + try + { + _writer?.Flush(); + _writer?.Dispose(); + } + catch + { + } + + _writer = null; + } + + private static string ResolveLogDirectory(string configuredPath) + { + if (string.IsNullOrWhiteSpace(configuredPath)) + { + return Path.Combine(AppContext.BaseDirectory, "log"); + } + + return Path.IsPathRooted(configuredPath) + ? configuredPath + : Path.Combine(AppContext.BaseDirectory, configuredPath); + } + } +} diff --git a/StandardScene.MagCarSimulator/MainForm.cs b/StandardScene.MagCarSimulator/MainForm.cs new file mode 100644 index 0000000..c6dc87d --- /dev/null +++ b/StandardScene.MagCarSimulator/MainForm.cs @@ -0,0 +1,630 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Text; +using System.Windows.Forms; + +namespace StandardScene.MagCarSimulator +{ + public sealed class MainForm : Form + { + private const int MaxLogLines = 400; + private const int MaxPendingLogs = 300; + + private readonly MagCarSimConfig _config; + private readonly MagCarSimHost _host; + private readonly StringBuilder _logBuffer = new StringBuilder(); + private readonly Queue _pendingLogs = new Queue(); + private readonly object _logLock = new object(); + private readonly Timer _uiTimer; + private bool _logFlushScheduled; + private int _logLineCount; + + private TextBox _mapPathBox; + private CheckBox _useTagValueBox; + private Label _mapInfoLabel; + private DataGridView _grid; + private ListBox _siteList; + private TextBox _logBox; + private Button _listenButton; + private Button _loopButton; + private Button _stopButton; + private Button _releaseButton; + private Button _addButton; + private Button _removeButton; + private Button _saveButton; + + public MainForm() + { + _config = MagCarSimConfig.Load(); + MagCarSimLog.Configure(_config); + _host = new MagCarSimHost(_config); + + Text = "MagCar 模拟器(FASS 1.0 / SimpleLite 地图循环)"; + Width = 1280; + Height = 820; + MinimumSize = new Size(980, 640); + StartPosition = FormStartPosition.CenterScreen; + Font = new Font("Microsoft YaHei UI", 9F); + + BuildLayout(); + LoadConfigToUi(); + + MagCarSimLog.MessageWritten += OnLogMessage; + _uiTimer = new Timer { Interval = 250 }; + _uiTimer.Tick += (_, __) => RefreshGridStatus(); + _uiTimer.Start(); + + FormClosed += (_, __) => + { + MagCarSimLog.MessageWritten -= OnLogMessage; + _uiTimer.Stop(); + _host.Dispose(); + MagCarSimLog.Shutdown(); + }; + + AppendLog($"就绪。文件日志目录: {MagCarSimLog.GetLogDirectory()}。加载 SimpleLite 地图后启动监听,再开始循环。普通站可叠车;停止点和交管点同时只允许一辆。"); + TryLoadMap(_config.MapPath, silent: true); + } + + private void BuildLayout() + { + var root = new TableLayoutPanel + { + Dock = DockStyle.Fill, + ColumnCount = 1, + RowCount = 4, + Padding = new Padding(8) + }; + root.RowStyles.Add(new RowStyle(SizeType.AutoSize)); + root.RowStyles.Add(new RowStyle(SizeType.Percent, 42)); + root.RowStyles.Add(new RowStyle(SizeType.AutoSize)); + root.RowStyles.Add(new RowStyle(SizeType.Percent, 58)); + Controls.Add(root); + + root.Controls.Add(BuildToolbar(), 0, 0); + _grid = BuildGrid(); + root.Controls.Add(_grid, 0, 1); + root.Controls.Add(BuildVehicleButtons(), 0, 2); + + var split = new SplitContainer + { + Dock = DockStyle.Fill, + Orientation = Orientation.Vertical, + SplitterDistance = 280 + }; + _siteList = new ListBox { Dock = DockStyle.Fill, IntegralHeight = false }; + var sitePanel = new Panel { Dock = DockStyle.Fill, Padding = new Padding(0, 4, 4, 0) }; + sitePanel.Controls.Add(_siteList); + sitePanel.Controls.Add(new Label + { + Text = "地图站点(带 [停止] 的为 Mag_NeedStop)", + Dock = DockStyle.Top, + Height = 22 + }); + split.Panel1.Controls.Add(sitePanel); + + _logBox = new TextBox + { + Dock = DockStyle.Fill, + Multiline = true, + ReadOnly = true, + ScrollBars = ScrollBars.Both, + WordWrap = false, + Font = new Font("Consolas", 9F) + }; + var logPanel = new Panel { Dock = DockStyle.Fill, Padding = new Padding(4, 4, 0, 0) }; + logPanel.Controls.Add(_logBox); + logPanel.Controls.Add(new Label + { + Text = "协议 / 运动日志", + Dock = DockStyle.Top, + Height = 22 + }); + split.Panel2.Controls.Add(logPanel); + root.Controls.Add(split, 0, 3); + } + + private Control BuildToolbar() + { + var panel = new TableLayoutPanel + { + Dock = DockStyle.Top, + AutoSize = true, + ColumnCount = 8, + RowCount = 2, + Padding = new Padding(0, 0, 0, 6) + }; + panel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); + + panel.Controls.Add(new Label { Text = "地图", AutoSize = true, Anchor = AnchorStyles.Left }, 0, 0); + _mapPathBox = new TextBox { Dock = DockStyle.Fill, Width = 480 }; + panel.Controls.Add(_mapPathBox, 1, 0); + + var browse = new Button { Text = "浏览…", AutoSize = true }; + browse.Click += (_, __) => BrowseMap(); + panel.Controls.Add(browse, 2, 0); + + var load = new Button { Text = "加载地图", AutoSize = true }; + load.Click += (_, __) => TryLoadMap(_mapPathBox.Text, silent: false); + panel.Controls.Add(load, 3, 0); + + _listenButton = new Button { Text = "启动监听", AutoSize = true }; + _listenButton.Click += (_, __) => StartListen(); + panel.Controls.Add(_listenButton, 4, 0); + + _loopButton = new Button { Text = "开始循环", AutoSize = true }; + _loopButton.Click += (_, __) => StartLoop(); + panel.Controls.Add(_loopButton, 5, 0); + + _stopButton = new Button { Text = "停止模拟", AutoSize = true, Enabled = false }; + _stopButton.Click += (_, __) => StopSim(); + panel.Controls.Add(_stopButton, 6, 0); + + _saveButton = new Button { Text = "保存配置", AutoSize = true }; + _saveButton.Click += (_, __) => SaveConfig(); + panel.Controls.Add(_saveButton, 7, 0); + + _useTagValueBox = new CheckBox { Text = "用 TagValue 作为节点号", AutoSize = true, Anchor = AnchorStyles.Left }; + panel.SetColumnSpan(_useTagValueBox, 2); + panel.Controls.Add(_useTagValueBox, 0, 1); + + _mapInfoLabel = new Label + { + Text = "未加载地图", + AutoSize = true, + Anchor = AnchorStyles.Left, + ForeColor = Color.DimGray + }; + panel.SetColumnSpan(_mapInfoLabel, 6); + panel.Controls.Add(_mapInfoLabel, 2, 1); + return panel; + } + + private Control BuildVehicleButtons() + { + var panel = new FlowLayoutPanel + { + Dock = DockStyle.Fill, + AutoSize = true, + WrapContents = false, + Padding = new Padding(0, 4, 0, 4) + }; + _addButton = new Button { Text = "添加车辆", AutoSize = true }; + _addButton.Click += (_, __) => AddVehicleRow(); + _removeButton = new Button { Text = "删除选中", AutoSize = true }; + _removeButton.Click += (_, __) => RemoveSelectedVehicle(); + _releaseButton = new Button { Text = "放行选中车", AutoSize = true }; + _releaseButton.Click += (_, __) => ReleaseSelected(); + panel.Controls.Add(_addButton); + panel.Controls.Add(_removeButton); + panel.Controls.Add(_releaseButton); + panel.Controls.Add(new Label + { + Text = "普通站可叠车。停止点和交管点同时只允许一辆,后车停在上一站保持运行中。仅 Mag_NeedStop 停车等 0x01。", + AutoSize = true, + Padding = new Padding(12, 8, 0, 0), + ForeColor = Color.DimGray + }); + return panel; + } + + private DataGridView BuildGrid() + { + var grid = new DataGridView + { + Dock = DockStyle.Fill, + AllowUserToAddRows = false, + AllowUserToDeleteRows = false, + RowHeadersVisible = false, + SelectionMode = DataGridViewSelectionMode.FullRowSelect, + MultiSelect = false, + AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill, + BackgroundColor = Color.White + }; + grid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Name", HeaderText = "名称", FillWeight = 80 }); + grid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Code", HeaderText = "车号", FillWeight = 50 }); + grid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Port", HeaderText = "端口", FillWeight = 55 }); + grid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Start", HeaderText = "起点", FillWeight = 50 }); + grid.Columns.Add(new DataGridViewTextBoxColumn { Name = "End", HeaderText = "终点", FillWeight = 50 }); + grid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Interval", HeaderText = "间隔ms", FillWeight = 60 }); + grid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Site", HeaderText = "当前站", ReadOnly = true, FillWeight = 55 }); + grid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Node", HeaderText = "节点", ReadOnly = true, FillWeight = 50 }); + grid.Columns.Add(new DataGridViewTextBoxColumn { Name = "State", HeaderText = "状态", ReadOnly = true, FillWeight = 70 }); + grid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Wait", HeaderText = "等待", ReadOnly = true, FillWeight = 55 }); + grid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Clients", HeaderText = "连接", ReadOnly = true, FillWeight = 45 }); + grid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Path", HeaderText = "循环路径", ReadOnly = true, FillWeight = 160 }); + return grid; + } + + private void LoadConfigToUi() + { + _mapPathBox.Text = _config.MapPath ?? ""; + _useTagValueBox.Checked = _config.UseTagValueAsNode; + _grid.Rows.Clear(); + foreach (var vehicle in _config.Vehicles) + { + _grid.Rows.Add( + vehicle.Name, + vehicle.VehicleCode, + vehicle.ListenPort, + vehicle.StartSiteId, + vehicle.EndSiteId, + vehicle.IntervalMs, + "", + "", + "", + "", + "", + ""); + } + } + + private List ReadVehiclesFromGrid() + { + var list = new List(); + foreach (DataGridViewRow row in _grid.Rows) + { + if (row.IsNewRow) + { + continue; + } + + var code = ToUShort(row.Cells["Code"].Value, 1); + list.Add(new MagCarSimVehicleConfig + { + Name = Convert.ToString(row.Cells["Name"].Value), + VehicleCode = code, + ListenPort = ToInt(row.Cells["Port"].Value, 5001), + StartSiteId = ToInt(row.Cells["Start"].Value, 1), + EndSiteId = ToInt(row.Cells["End"].Value, 2), + IntervalMs = ToInt(row.Cells["Interval"].Value, _config.DefaultIntervalMs), + LoopSiteIds = PreserveLoop(code) + }); + } + + return list; + } + + private List PreserveLoop(ushort vehicleCode) + { + var existing = _config.Vehicles?.Find(v => v.VehicleCode == vehicleCode); + if (existing?.LoopSiteIds == null || existing.LoopSiteIds.Count == 0) + { + return null; + } + + return new List(existing.LoopSiteIds); + } + + private void BrowseMap() + { + using var dialog = new OpenFileDialog + { + Filter = "SimpleLite 地图 (*.json)|*.json|所有文件 (*.*)|*.*", + Title = "选择 SimpleLite 地图" + }; + if (!string.IsNullOrWhiteSpace(_mapPathBox.Text) && File.Exists(_mapPathBox.Text)) + { + dialog.InitialDirectory = Path.GetDirectoryName(_mapPathBox.Text); + dialog.FileName = Path.GetFileName(_mapPathBox.Text); + } + + if (dialog.ShowDialog(this) == DialogResult.OK) + { + _mapPathBox.Text = dialog.FileName; + TryLoadMap(dialog.FileName, silent: false); + } + } + + private void TryLoadMap(string path, bool silent) + { + if (string.IsNullOrWhiteSpace(path)) + { + if (!silent) + { + MessageBox.Show(this, "请先选择 SimpleLite 地图文件。", "加载地图", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + return; + } + + try + { + _config.UseTagValueAsNode = _useTagValueBox.Checked; + var map = _host.LoadMap(path); + _mapPathBox.Text = map.FilePath; + RefreshSiteList(map); + var stops = map.ListNeedStopSiteIds(); + _mapInfoLabel.Text = $"站点 {map.Sites.Count},路径 {map.Tracks.Count},停止点 {(stops.Count == 0 ? "无(循环将一直过站)" : string.Join(",", stops))}"; + } + catch (Exception ex) + { + _mapInfoLabel.Text = "地图加载失败"; + if (!silent) + { + MessageBox.Show(this, ex.Message, "加载地图失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + else + { + AppendLog("地图未加载:" + ex.Message); + } + } + } + + private void RefreshSiteList(SimpleLiteMap map) + { + _siteList.Items.Clear(); + foreach (var site in map.Sites.Values) + { + var tag = site.NeedStop ? " [停止]" : ""; + var node = map.ResolveNode(site.Id); + _siteList.Items.Add($"站 {site.Id} node={node}{tag}"); + } + } + + private void StartListen() + { + try + { + ApplyGridToHost(); + _host.StartListen(); + SetRunningUi(true, looping: false); + AppendLog("TCP 监听已启动。请在 SimpleLite 中把 MagCar 的 address/Port/VehicleCode 配成与上表一致。"); + } + catch (Exception ex) + { + MessageBox.Show(this, ex.Message, "启动监听失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void StartLoop() + { + try + { + if (!_host.IsListening) + { + ApplyGridToHost(); + } + + _host.StartLoops(); + SetRunningUi(true, looping: true); + } + catch (Exception ex) + { + MessageBox.Show(this, ex.Message, "开始循环失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void StopSim() + { + _host.StopAll(); + SetRunningUi(false, looping: false); + AppendLog("模拟已停止。"); + RefreshGridStatus(); + } + + private void ApplyGridToHost() + { + _config.MapPath = _mapPathBox.Text; + _config.UseTagValueAsNode = _useTagValueBox.Checked; + _config.Vehicles = ReadVehiclesFromGrid(); + if (!string.IsNullOrWhiteSpace(_config.MapPath)) + { + TryLoadMap(_config.MapPath, silent: false); + } + + _host.RebuildVehicles(_config.Vehicles); + } + + private void AddVehicleRow() + { + if (_host.IsListening) + { + MessageBox.Show(this, "运行中不能改车辆列表,请先停止模拟。", "添加车辆", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + + var nextCode = _grid.Rows.Count + 1; + _grid.Rows.Add($"AGV-{nextCode}", nextCode, 5000 + nextCode, 1, 6, _config.DefaultIntervalMs, "", "", "", "", "", ""); + } + + private void RemoveSelectedVehicle() + { + if (_host.IsListening) + { + MessageBox.Show(this, "运行中不能改车辆列表,请先停止模拟。", "删除车辆", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + + if (_grid.CurrentRow == null) + { + return; + } + + _grid.Rows.Remove(_grid.CurrentRow); + } + + private void ReleaseSelected() + { + if (_grid.CurrentRow == null) + { + MessageBox.Show(this, "请先选中一辆车。", "放行", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + + var code = ToUShort(_grid.CurrentRow.Cells["Code"].Value, 0); + if (!_host.TryRelease(code)) + { + MessageBox.Show(this, $"未找到车号 {code},请先启动监听。", "放行", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + + private void SaveConfig() + { + try + { + _config.MapPath = _mapPathBox.Text; + _config.UseTagValueAsNode = _useTagValueBox.Checked; + _config.Vehicles = ReadVehiclesFromGrid(); + _config.Save(); + AppendLog("配置已保存到 " + MagCarSimConfig.SettingsPath); + } + catch (Exception ex) + { + MessageBox.Show(this, ex.Message, "保存失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void SetRunningUi(bool listening, bool looping) + { + _listenButton.Enabled = !listening; + _loopButton.Enabled = !looping; + _stopButton.Enabled = listening; + _addButton.Enabled = !listening; + _removeButton.Enabled = !listening; + _grid.ReadOnly = listening; + _useTagValueBox.Enabled = !listening; + } + + private void RefreshGridStatus() + { + var snapshots = _host.Snapshots(); + if (snapshots.Count == 0) + { + return; + } + + for (var i = 0; i < _grid.Rows.Count && i < snapshots.Count; i++) + { + var snap = snapshots[i]; + var row = _grid.Rows[i]; + row.Cells["Site"].Value = snap.CurrentSiteId; + row.Cells["Node"].Value = snap.Node; + row.Cells["State"].Value = snap.StateText; + row.Cells["Wait"].Value = snap.WaitingRelease ? "等放行" : (snap.HoldingForStop ? "让行" : ""); + row.Cells["Clients"].Value = snap.ClientCount; + row.Cells["Path"].Value = snap.PathText; + row.DefaultCellStyle.BackColor = snap.WaitingRelease + ? Color.FromArgb(255, 236, 179) + : snap.HoldingForStop + ? Color.FromArgb(207, 232, 255) + : Color.White; + } + } + + private void OnLogMessage(string message) + { + lock (_logLock) + { + while (_pendingLogs.Count >= MaxPendingLogs) + { + _pendingLogs.Dequeue(); + } + + _pendingLogs.Enqueue(message); + } + + if (_logFlushScheduled || !IsHandleCreated) + { + return; + } + + _logFlushScheduled = true; + try + { + BeginInvoke(new Action(FlushLogs)); + } + catch + { + _logFlushScheduled = false; + } + } + + private void FlushLogs() + { + _logFlushScheduled = false; + List batch; + lock (_logLock) + { + if (_pendingLogs.Count == 0) + { + return; + } + + batch = new List(_pendingLogs.Count); + while (_pendingLogs.Count > 0) + { + batch.Add(_pendingLogs.Dequeue()); + } + } + + foreach (var line in batch) + { + _logLineCount++; + _logBuffer.AppendLine(line); + } + + while (_logLineCount > MaxLogLines) + { + var text = _logBuffer.ToString(); + var firstBreak = text.IndexOf('\n'); + if (firstBreak < 0) + { + break; + } + + _logBuffer.Remove(0, firstBreak + 1); + _logLineCount--; + } + + _logBox.Text = _logBuffer.ToString(); + _logBox.SelectionStart = _logBox.TextLength; + _logBox.ScrollToCaret(); + } + + private void AppendLog(string message) + { + lock (_logLock) + { + while (_pendingLogs.Count >= MaxPendingLogs) + { + _pendingLogs.Dequeue(); + } + + _pendingLogs.Enqueue(message); + } + + if (IsHandleCreated) + { + if (!_logFlushScheduled) + { + _logFlushScheduled = true; + BeginInvoke(new Action(FlushLogs)); + } + } + else + { + FlushLogs(); + } + } + + private static int ToInt(object value, int fallback) + { + return int.TryParse(Convert.ToString(value), out var n) ? n : fallback; + } + + private static ushort ToUShort(object value, ushort fallback) + { + return ushort.TryParse(Convert.ToString(value), out var n) ? n : fallback; + } + } +} diff --git a/StandardScene.MagCarSimulator/Map/MagControlAreaFile.cs b/StandardScene.MagCarSimulator/Map/MagControlAreaFile.cs new file mode 100644 index 0000000..9704146 --- /dev/null +++ b/StandardScene.MagCarSimulator/Map/MagControlAreaFile.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using Newtonsoft.Json.Linq; + +namespace StandardScene.MagCarSimulator +{ + /// 读取 mag-control-areas.json,收集触发点与管控区站点。 + public static class MagControlAreaFile + { + private static readonly char[] SiteSeparators = { ',', ';', '|', ' ', '\t' }; + + public static HashSet LoadSiteIds(string path) + { + var ids = new HashSet(); + if (string.IsNullOrWhiteSpace(path) || !File.Exists(path)) + { + return ids; + } + + var root = JToken.Parse(File.ReadAllText(path)); + if (root is not JArray rows) + { + return ids; + } + + foreach (var row in rows) + { + if (row is not JObject obj) + { + continue; + } + + if (obj.Value("IsUse") == false) + { + continue; + } + + AddIfPositive(ids, obj.Value("TriggerSit") ?? 0); + foreach (var part in (obj.Value("ControlArea") ?? "").Split(SiteSeparators, StringSplitOptions.RemoveEmptyEntries)) + { + if (int.TryParse(part.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var id)) + { + AddIfPositive(ids, id); + } + } + } + + return ids; + } + + public static string GuessPath(string mapPath, string configuredPath) + { + if (!string.IsNullOrWhiteSpace(configuredPath) && File.Exists(configuredPath)) + { + return Path.GetFullPath(configuredPath); + } + + if (string.IsNullOrWhiteSpace(mapPath)) + { + return configuredPath; + } + + var mapDir = Path.GetDirectoryName(Path.GetFullPath(mapPath)); + if (string.IsNullOrWhiteSpace(mapDir)) + { + return configuredPath; + } + + var guessed = Path.GetFullPath(Path.Combine(mapDir, "..", "config", "Signal", "mag-control-areas.json")); + return File.Exists(guessed) ? guessed : configuredPath; + } + + private static void AddIfPositive(HashSet ids, int id) + { + if (id > 0) + { + ids.Add(id); + } + } + } +} diff --git a/StandardScene.MagCarSimulator/Map/MapPathFinder.cs b/StandardScene.MagCarSimulator/Map/MapPathFinder.cs new file mode 100644 index 0000000..868f8a8 --- /dev/null +++ b/StandardScene.MagCarSimulator/Map/MapPathFinder.cs @@ -0,0 +1,213 @@ +using System.Collections.Generic; +using System.Text; + +namespace StandardScene.MagCarSimulator +{ + public static class MapPathFinder + { + /// + /// 生成往返循环:起点→终点→起点(终点不重复,回到起点靠下标回绕)。 + /// + public static List BuildLoop(SimpleLiteMap map, int startSiteId, int endSiteId) + { + if (map == null) + { + throw new System.InvalidOperationException("尚未加载地图"); + } + + if (startSiteId == endSiteId) + { + throw new System.InvalidOperationException($"起点和终点不能相同(站点 {startSiteId})"); + } + + if (!map.Sites.ContainsKey(startSiteId)) + { + throw new System.InvalidOperationException($"地图中没有起点 {startSiteId}"); + } + + if (!map.Sites.ContainsKey(endSiteId)) + { + throw new System.InvalidOperationException($"地图中没有终点 {endSiteId}"); + } + + var forward = FindPath(map, startSiteId, endSiteId); + if (forward == null) + { + throw new System.InvalidOperationException($"找不到路径 {startSiteId} → {endSiteId}"); + } + + var back = FindPath(map, endSiteId, startSiteId); + if (back == null) + { + throw new System.InvalidOperationException($"找不到返回路径 {endSiteId} → {startSiteId}"); + } + + var loop = new List(forward.Count + back.Count); + loop.AddRange(forward); + for (var i = 1; i < back.Count - 1; i++) + { + loop.Add(back[i]); + } + + if (loop.Count < 2) + { + throw new System.InvalidOperationException("循环路径至少需要两个站点"); + } + + return loop; + } + + public static List NormalizeLoop(IEnumerable siteIds) + { + var loop = new List(); + if (siteIds == null) + { + return loop; + } + + foreach (var id in siteIds) + { + if (id <= 0) + { + continue; + } + + if (loop.Count > 0 && loop[loop.Count - 1] == id) + { + continue; + } + + loop.Add(id); + } + + if (loop.Count >= 2 && loop[0] == loop[loop.Count - 1]) + { + loop.RemoveAt(loop.Count - 1); + } + + return loop; + } + + public static List ResolveLoop(SimpleLiteMap map, MagCarSimVehicleConfig config) + { + if (map == null) + { + throw new System.InvalidOperationException("尚未加载地图"); + } + + if (config?.LoopSiteIds != null && config.LoopSiteIds.Count >= 3) + { + var loop = NormalizeLoop(config.LoopSiteIds); + if (loop.Count < 3) + { + throw new System.InvalidOperationException($"{config.Name} 环线站点不足"); + } + + foreach (var id in loop) + { + if (!map.Sites.ContainsKey(id)) + { + throw new System.InvalidOperationException($"{config.Name} 环线站点 {id} 不在地图中"); + } + } + + return loop; + } + + return BuildLoop(map, config.StartSiteId, config.EndSiteId); + } + + public static string FormatPath(IReadOnlyList siteIds, int maxShow = 0) + { + if (siteIds == null || siteIds.Count == 0) + { + return ""; + } + + var show = siteIds.Count; + var truncated = false; + if (maxShow > 0 && siteIds.Count > maxShow) + { + show = maxShow; + truncated = true; + } + + var sb = new StringBuilder(); + for (var i = 0; i < show; i++) + { + if (i > 0) + { + sb.Append("→"); + } + + sb.Append(siteIds[i]); + } + + if (truncated) + { + sb.Append("→…共").Append(siteIds.Count).Append("站"); + } + else + { + sb.Append("→").Append(siteIds[0]); + } + + return sb.ToString(); + } + + public static List FindPath(SimpleLiteMap map, int fromSiteId, int toSiteId) + { + if (fromSiteId == toSiteId) + { + return new List { fromSiteId }; + } + + var queue = new Queue(); + var prev = new Dictionary(); + var visited = new HashSet { fromSiteId }; + queue.Enqueue(fromSiteId); + + while (queue.Count > 0) + { + var current = queue.Dequeue(); + if (!map.Adjacency.TryGetValue(current, out var nexts)) + { + continue; + } + + foreach (var next in nexts) + { + if (!visited.Add(next)) + { + continue; + } + + prev[next] = current; + if (next == toSiteId) + { + return Reconstruct(prev, fromSiteId, toSiteId); + } + + queue.Enqueue(next); + } + } + + return null; + } + + private static List Reconstruct(Dictionary prev, int fromSiteId, int toSiteId) + { + var path = new List(); + var current = toSiteId; + path.Add(current); + while (current != fromSiteId) + { + current = prev[current]; + path.Add(current); + } + + path.Reverse(); + return path; + } + } +} diff --git a/StandardScene.MagCarSimulator/Map/SimpleLiteMap.cs b/StandardScene.MagCarSimulator/Map/SimpleLiteMap.cs new file mode 100644 index 0000000..14fcdc2 --- /dev/null +++ b/StandardScene.MagCarSimulator/Map/SimpleLiteMap.cs @@ -0,0 +1,324 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using Newtonsoft.Json.Linq; + +namespace StandardScene.MagCarSimulator +{ + public sealed class SimpleLiteSite + { + public int Id { get; set; } + public string Name { get; set; } + public double X { get; set; } + public double Y { get; set; } + public int? TagValue { get; set; } + public bool NeedStop { get; set; } + public IReadOnlyDictionary Fields { get; set; } + } + + public sealed class SimpleLiteTrack + { + public int Id { get; set; } + public int SiteA { get; set; } + public int SiteB { get; set; } + public int Direction { get; set; } + } + + /// 解析 SimpleLite maps/*.json 的 Sites / Tracks。 + public sealed class SimpleLiteMap + { + public const string NeedStopField = "Mag_NeedStop"; + + public string FilePath { get; private set; } + public string FileName { get; private set; } + public IReadOnlyDictionary Sites { get; private set; } + public IReadOnlyList Tracks { get; private set; } + public IReadOnlyDictionary> Adjacency { get; private set; } + private readonly HashSet _singleOccupancySites = new HashSet(); + + public static SimpleLiteMap Load(string path, bool useTagValueAsNode) + { + if (string.IsNullOrWhiteSpace(path) || !File.Exists(path)) + { + throw new FileNotFoundException("找不到 SimpleLite 地图文件", path); + } + + var root = JObject.Parse(File.ReadAllText(path)); + var sites = ParseSites(root["Sites"] as JObject); + var tracks = ParseTracks(root["Tracks"] as JObject); + var adjacency = BuildAdjacency(sites, tracks); + + var map = new SimpleLiteMap + { + FilePath = Path.GetFullPath(path), + FileName = Path.GetFileName(path), + Sites = sites, + Tracks = tracks, + Adjacency = adjacency, + UseTagValueAsNode = useTagValueAsNode + }; + map.ResetSingleOccupancyFromStops(); + return map; + } + + public bool UseTagValueAsNode { get; private set; } + + public bool TryGetSite(int siteId, out SimpleLiteSite site) + { + return Sites.TryGetValue(siteId, out site); + } + + public ushort ResolveNode(int siteId) + { + if (!Sites.TryGetValue(siteId, out var site)) + { + return (ushort)Math.Clamp(siteId, 0, ushort.MaxValue); + } + + if (UseTagValueAsNode && site.TagValue.HasValue && site.TagValue.Value >= 0) + { + return (ushort)Math.Clamp(site.TagValue.Value, 0, ushort.MaxValue); + } + + return (ushort)Math.Clamp(site.Id, 0, ushort.MaxValue); + } + + public bool NeedStop(int siteId) + { + return Sites.TryGetValue(siteId, out var site) && site.NeedStop; + } + + /// 停止点或交管点:同时只允许一辆。普通站可叠车。 + public bool SingleOccupancy(int siteId) + { + return _singleOccupancySites.Contains(siteId); + } + + public IReadOnlyList ListSingleOccupancySiteIds() + { + var list = new List(_singleOccupancySites); + list.Sort(); + return list; + } + + public void ResetSingleOccupancyFromStops() + { + _singleOccupancySites.Clear(); + foreach (var site in Sites.Values) + { + if (site.NeedStop) + { + _singleOccupancySites.Add(site.Id); + } + } + } + + public void AddSingleOccupancySites(IEnumerable siteIds) + { + if (siteIds == null) + { + return; + } + + foreach (var id in siteIds) + { + if (id > 0 && Sites.ContainsKey(id)) + { + _singleOccupancySites.Add(id); + } + } + } + + public IReadOnlyList ListNeedStopSiteIds() + { + var list = new List(); + foreach (var site in Sites.Values) + { + if (site.NeedStop) + { + list.Add(site.Id); + } + } + + list.Sort(); + return list; + } + + private static Dictionary ParseSites(JObject sitesNode) + { + var result = new Dictionary(); + if (sitesNode == null) + { + return result; + } + + foreach (var property in sitesNode.Properties()) + { + if (property.Value is not JObject obj) + { + continue; + } + + var id = obj.Value("id") ?? ParseInt(property.Name); + if (id <= 0) + { + continue; + } + + var fields = ReadFields(obj["fields"] as JObject); + var site = new SimpleLiteSite + { + Id = id, + Name = obj.Value("name") ?? "", + X = obj.Value("x") ?? 0, + Y = obj.Value("y") ?? 0, + TagValue = TryReadInt(fields, "TagValue"), + NeedStop = IsNeedStop(fields), + Fields = fields + }; + result[id] = site; + } + + return result; + } + + private static List ParseTracks(JObject tracksNode) + { + var result = new List(); + if (tracksNode == null) + { + return result; + } + + foreach (var property in tracksNode.Properties()) + { + if (property.Value is not JObject obj) + { + continue; + } + + var siteA = obj.Value("siteA") ?? obj.Value("_siteA") ?? 0; + var siteB = obj.Value("siteB") ?? obj.Value("_siteB") ?? 0; + if (siteA <= 0 || siteB <= 0) + { + continue; + } + + result.Add(new SimpleLiteTrack + { + Id = obj.Value("id") ?? ParseInt(property.Name), + SiteA = siteA, + SiteB = siteB, + Direction = obj.Value("direction") ?? 0 + }); + } + + return result; + } + + private static Dictionary> BuildAdjacency( + Dictionary sites, + List tracks) + { + var mutable = new Dictionary>(); + foreach (var id in sites.Keys) + { + mutable[id] = new List(); + } + + foreach (var track in tracks) + { + AddEdge(mutable, track.SiteA, track.SiteB, track.Direction); + } + + var result = new Dictionary>(); + foreach (var pair in mutable) + { + result[pair.Key] = pair.Value; + } + + return result; + } + + private static void AddEdge(Dictionary> graph, int from, int to, int direction) + { + // 0 双向;1 仅 A→B;2 仅 B→A。其它值按双向处理。 + var aToB = direction != 2; + var bToA = direction != 1; + if (aToB) + { + AddUnique(graph, from, to); + } + + if (bToA) + { + AddUnique(graph, to, from); + } + } + + private static void AddUnique(Dictionary> graph, int from, int to) + { + if (!graph.TryGetValue(from, out var list)) + { + list = new List(); + graph[from] = list; + } + + if (!list.Contains(to)) + { + list.Add(to); + } + } + + private static Dictionary ReadFields(JObject fields) + { + var result = new Dictionary(StringComparer.OrdinalIgnoreCase); + if (fields == null) + { + return result; + } + + foreach (var property in fields.Properties()) + { + result[property.Name] = property.Value?.Type == JTokenType.Null + ? "" + : property.Value.ToString(); + } + + return result; + } + + private static bool IsNeedStop(Dictionary fields) + { + if (!fields.TryGetValue(NeedStopField, out var raw)) + { + return false; + } + + raw = (raw ?? "").Trim(); + return raw.Equals("true", StringComparison.OrdinalIgnoreCase) + || raw.Equals("1", StringComparison.OrdinalIgnoreCase) + || raw.Equals("yes", StringComparison.OrdinalIgnoreCase); + } + + private static int? TryReadInt(Dictionary fields, string key) + { + if (!fields.TryGetValue(key, out var raw) || string.IsNullOrWhiteSpace(raw)) + { + return null; + } + + return int.TryParse(raw, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value) + ? value + : (int?)null; + } + + private static int ParseInt(string text) + { + return int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value) + ? value + : 0; + } + } +} diff --git a/StandardScene.MagCarSimulator/Net/MagCarSimTcpServer.cs b/StandardScene.MagCarSimulator/Net/MagCarSimTcpServer.cs new file mode 100644 index 0000000..3c638f0 --- /dev/null +++ b/StandardScene.MagCarSimulator/Net/MagCarSimTcpServer.cs @@ -0,0 +1,242 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; + +namespace StandardScene.MagCarSimulator +{ + public sealed class MagCarSimTcpServer : IDisposable + { + private readonly IPAddress _address; + private readonly int _port; + private readonly Func _handler; + private readonly object _clientsLock = new object(); + private readonly HashSet _clients = new HashSet(); + private TcpListener _listener; + private CancellationTokenSource _cts; + private int _clientCount; + private bool _running; + + public MagCarSimTcpServer(IPAddress address, int port, Func handler) + { + _address = address ?? IPAddress.Any; + _port = port; + _handler = handler ?? throw new ArgumentNullException(nameof(handler)); + } + + public bool IsRunning => _running; + public int ClientCount => Volatile.Read(ref _clientCount); + + public void Start() + { + if (_running) + { + return; + } + + _cts = new CancellationTokenSource(); + _listener = new TcpListener(_address, _port); + _listener.Server.NoDelay = true; + _listener.Start(); + _running = true; + _ = Task.Run(() => AcceptLoop(_cts.Token)); + } + + public void Dispose() + { + _running = false; + try + { + _cts?.Cancel(); + } + catch + { + } + + try + { + _listener?.Stop(); + } + catch + { + } + + List clients; + lock (_clientsLock) + { + clients = new List(_clients); + _clients.Clear(); + } + + foreach (var client in clients) + { + try + { + client.Close(); + } + catch + { + } + } + + _cts?.Dispose(); + _cts = null; + _listener = null; + } + + private async Task AcceptLoop(CancellationToken token) + { + while (!token.IsCancellationRequested) + { + TcpClient client; + try + { + client = await _listener.AcceptTcpClientAsync(token).ConfigureAwait(false); + } + catch (OperationCanceledException) + { + return; + } + catch (ObjectDisposedException) + { + return; + } + catch (SocketException) + { + if (token.IsCancellationRequested) + { + return; + } + + continue; + } + + lock (_clientsLock) + { + _clients.Add(client); + } + + _ = Task.Run(() => HandleClient(client, token), token); + } + } + + private void HandleClient(TcpClient client, CancellationToken token) + { + Interlocked.Increment(ref _clientCount); + try + { + client.NoDelay = true; + client.ReceiveTimeout = 0; + using (var stream = client.GetStream()) + { + var buffer = new byte[MagCarSimProtocol.FrameLength]; + while (!token.IsCancellationRequested) + { + if (!ReadExact(stream, buffer, token)) + { + return; + } + + byte[] response; + try + { + response = _handler(buffer); + } + catch (Exception ex) + { + MagCarSimLog.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] TCP 处理异常: {ex.Message}"); + return; + } + + if (response == null || response.Length != MagCarSimProtocol.FrameLength) + { + continue; + } + + stream.Write(response, 0, response.Length); + stream.Flush(); + } + } + } + catch (Exception ex) when (IsBenign(ex)) + { + } + catch (Exception ex) + { + MagCarSimLog.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] TCP 连接异常: {ex.Message}"); + } + finally + { + lock (_clientsLock) + { + _clients.Remove(client); + } + + try + { + client.Dispose(); + } + catch + { + } + + Interlocked.Decrement(ref _clientCount); + } + } + + private static bool ReadExact(NetworkStream stream, byte[] buffer, CancellationToken token) + { + var offset = 0; + while (offset < buffer.Length) + { + token.ThrowIfCancellationRequested(); + int read; + try + { + read = stream.Read(buffer, offset, buffer.Length - offset); + } + catch (Exception ex) when (IsBenign(ex)) + { + return false; + } + + if (read == 0) + { + return false; + } + + offset += read; + } + + return true; + } + + private static bool IsBenign(Exception ex) + { + for (var current = ex; current != null; current = current.InnerException) + { + if (current is ObjectDisposedException || current is OperationCanceledException) + { + return true; + } + + if (current is SocketException socketEx) + { + switch (socketEx.SocketErrorCode) + { + case SocketError.OperationAborted: + case SocketError.Interrupted: + case SocketError.ConnectionAborted: + case SocketError.ConnectionReset: + case SocketError.Shutdown: + return true; + } + } + } + + return false; + } + } +} diff --git a/StandardScene.MagCarSimulator/Program.cs b/StandardScene.MagCarSimulator/Program.cs new file mode 100644 index 0000000..1cb796a --- /dev/null +++ b/StandardScene.MagCarSimulator/Program.cs @@ -0,0 +1,15 @@ +using System; +using System.Windows.Forms; + +namespace StandardScene.MagCarSimulator +{ + internal static class Program + { + [STAThread] + private static void Main() + { + ApplicationConfiguration.Initialize(); + Application.Run(new MainForm()); + } + } +} diff --git a/StandardScene.MagCarSimulator/Protocol/MagCarSimProtocol.cs b/StandardScene.MagCarSimulator/Protocol/MagCarSimProtocol.cs new file mode 100644 index 0000000..8713d95 --- /dev/null +++ b/StandardScene.MagCarSimulator/Protocol/MagCarSimProtocol.cs @@ -0,0 +1,144 @@ +using System; + +namespace StandardScene.MagCarSimulator +{ + /// + /// FASS 1.0 32 字节帧,字段布局与 MagCar.MagCarReport 对齐。 + /// + public static class MagCarSimProtocol + { + public const int FrameLength = 32; + public const byte Begin = 0xBB; + public const byte End = 0xEE; + + public const byte CmdQueryState = 0x00; + public const byte CmdStart = 0x01; + public const byte CmdStop = 0x02; + public const byte CmdSpeed = 0x03; + public const byte CmdAngle = 0x04; + public const byte CmdLegacyNode = 0x05; + public const byte CmdTask = 0xA1; + + public const byte StateIdle = 0; + public const byte StateRunning = 1; + public const byte StateStopping = 2; + public const byte StateCharging = 3; + + public static bool TryParse(byte[] bytes, out MagCarSimRequest request) + { + request = null; + if (bytes == null || bytes.Length < FrameLength) + { + return false; + } + + if (bytes[0] != Begin || bytes[FrameLength - 1] != End) + { + return false; + } + + request = new MagCarSimRequest + { + Command = bytes[1], + VehicleCode = ReadUInt16(bytes, 2), + Data0 = ReadUInt16(bytes, 4), + Data1 = ReadUInt16(bytes, 6) + }; + return true; + } + + public static byte[] BuildStatus( + byte command, + ushort vehicleCode, + ushort node, + byte state, + byte charge, + float current, + float voltage, + byte speed, + ushort angle, + byte task, + byte lift, + byte roll) + { + var bytes = new byte[FrameLength]; + bytes[0] = Begin; + bytes[1] = command; + WriteUInt16(bytes, 2, vehicleCode); + WriteUInt16(bytes, 4, node); + WriteUInt16(bytes, 25, angle); + WriteSingle(bytes, 16, current); + WriteSingle(bytes, 20, voltage); + bytes[14] = state; + bytes[15] = charge; + bytes[24] = speed; + bytes[27] = task; + bytes[28] = lift; + bytes[29] = roll; + bytes[31] = End; + return bytes; + } + + public static string CommandName(byte command) + { + switch (command) + { + case CmdQueryState: return "Query(0x00)"; + case CmdStart: return "Start(0x01)"; + case CmdStop: return "Stop(0x02)"; + case CmdSpeed: return "Speed(0x03)"; + case CmdAngle: return "Angle(0x04)"; + case CmdLegacyNode: return "LegacyNode(0x05)"; + case CmdTask: return "Task(0xA1)"; + default: return $"Unknown(0x{command:X2})"; + } + } + + public static string StateText(byte state) + { + switch (state) + { + case StateIdle: return "未准备"; + case StateRunning: return "运行中"; + case StateStopping: return "停止中"; + case StateCharging: return "充电中"; + default: return $"未知({state})"; + } + } + + public static string ToHex(byte[] bytes) + { + return bytes == null ? string.Empty : BitConverter.ToString(bytes).Replace("-", " "); + } + + public static ushort ReadUInt16(byte[] bytes, int offset) + { + return (ushort)((bytes[offset] << 8) | bytes[offset + 1]); + } + + public static void WriteUInt16(byte[] bytes, int offset, ushort value) + { + bytes[offset] = (byte)(value >> 8); + bytes[offset + 1] = (byte)(value & 0xFF); + } + + public static void WriteSingle(byte[] bytes, int offset, float value) + { + var raw = BitConverter.GetBytes(value); + if (BitConverter.IsLittleEndian) + { + Array.Reverse(raw); + } + + Buffer.BlockCopy(raw, 0, bytes, offset, 4); + } + } + + public sealed class MagCarSimRequest + { + public byte Command { get; set; } + public ushort VehicleCode { get; set; } + public ushort Data0 { get; set; } + public ushort Data1 { get; set; } + } +} diff --git a/StandardScene.MagCarSimulator/Runtime/MagCarSimConfig.cs b/StandardScene.MagCarSimulator/Runtime/MagCarSimConfig.cs new file mode 100644 index 0000000..27d541f --- /dev/null +++ b/StandardScene.MagCarSimulator/Runtime/MagCarSimConfig.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Newtonsoft.Json; + +namespace StandardScene.MagCarSimulator +{ + public sealed class MagCarSimVehicleConfig + { + public string Name { get; set; } = "AGV"; + public ushort VehicleCode { get; set; } = 1; + public int ListenPort { get; set; } = 5001; + public int StartSiteId { get; set; } = 1; + public int EndSiteId { get; set; } = 2; + public int IntervalMs { get; set; } = 2000; + + /// 显式环线站点序列(不含回到起点的重复点)。有值时优先于起点/终点寻路。 + public List LoopSiteIds { get; set; } + } + + public sealed class MagCarSimConfig + { + public string MapPath { get; set; } = ""; + public bool UseTagValueAsNode { get; set; } + public string ListenAddress { get; set; } = "0.0.0.0"; + public bool LogRawFrames { get; set; } + public bool LogQueries { get; set; } + + /// 文件日志根目录(相对 exe 或绝对路径),默认 log。 + public string LogDirectory { get; set; } = "log"; + + /// 是否写入 log 目录下的 magcar-sim_yyyyMMdd.log。 + public bool EnableFileLog { get; set; } = true; + + public int DefaultIntervalMs { get; set; } = 2000; + + /// 同一环线后车相对前车的发车间隔。≤0 时用该车 IntervalMs。 + public int LaunchStaggerMs { get; set; } + + /// 磁条交管表。空则按地图目录推断 SimpleLite/config/Signal/mag-control-areas.json。 + public string ControlAreasPath { get; set; } + public List Vehicles { get; set; } = new List(); + + public static string SettingsPath => Path.Combine(AppContext.BaseDirectory, "appsettings.json"); + + public static MagCarSimConfig Load(string path = null) + { + path ??= SettingsPath; + if (!File.Exists(path)) + { + return CreateDefault(); + } + + var json = File.ReadAllText(path); + var config = JsonConvert.DeserializeObject(json) ?? CreateDefault(); + if (config.Vehicles == null || config.Vehicles.Count == 0) + { + config.Vehicles = CreateDefault().Vehicles; + } + + if (config.DefaultIntervalMs <= 0) + { + config.DefaultIntervalMs = 2000; + } + + foreach (var vehicle in config.Vehicles) + { + if (vehicle.IntervalMs <= 0) + { + vehicle.IntervalMs = config.DefaultIntervalMs; + } + + if (string.IsNullOrWhiteSpace(vehicle.Name)) + { + vehicle.Name = $"AGV-{vehicle.VehicleCode}"; + } + + if (vehicle.LoopSiteIds != null && vehicle.LoopSiteIds.Count > 0) + { + vehicle.LoopSiteIds = MapPathFinder.NormalizeLoop(vehicle.LoopSiteIds); + } + } + + return config; + } + + public void Save(string path = null) + { + path ??= SettingsPath; + var json = JsonConvert.SerializeObject(this, Formatting.Indented); + File.WriteAllText(path, json); + } + + public static MagCarSimConfig CreateDefault() + { + return new MagCarSimConfig + { + DefaultIntervalMs = 2000, + Vehicles = + { + new MagCarSimVehicleConfig + { + Name = "AGV-1", + VehicleCode = 1, + ListenPort = 5001, + StartSiteId = 1, + EndSiteId = 6, + IntervalMs = 2000 + } + } + }; + } + } +} diff --git a/StandardScene.MagCarSimulator/Runtime/MagCarSimHost.cs b/StandardScene.MagCarSimulator/Runtime/MagCarSimHost.cs new file mode 100644 index 0000000..8792e1e --- /dev/null +++ b/StandardScene.MagCarSimulator/Runtime/MagCarSimHost.cs @@ -0,0 +1,335 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; + +namespace StandardScene.MagCarSimulator +{ + public sealed class MagCarSimHost : IDisposable + { + private readonly object _syncRoot = new object(); + private readonly List _vehicles = new List(); + private Timer _timer; + private SimpleLiteMap _map; + private int _tickBusy; + + public MagCarSimHost(MagCarSimConfig config) + { + Config = config ?? throw new ArgumentNullException(nameof(config)); + } + + public MagCarSimConfig Config { get; } + public SimpleLiteMap Map => _map; + public bool IsListening { get; private set; } + public bool IsLooping { get; private set; } + + public IReadOnlyList Vehicles + { + get + { + lock (_syncRoot) + { + return _vehicles.ToList(); + } + } + } + + public SimpleLiteMap LoadMap(string path) + { + var map = SimpleLiteMap.Load(path, Config.UseTagValueAsNode); + var controlPath = MagControlAreaFile.GuessPath(map.FilePath, Config.ControlAreasPath); + var controlSites = MagControlAreaFile.LoadSiteIds(controlPath); + map.AddSingleOccupancySites(controlSites); + lock (_syncRoot) + { + _map = map; + Config.MapPath = map.FilePath; + if (!string.IsNullOrWhiteSpace(controlPath)) + { + Config.ControlAreasPath = controlPath; + } + + foreach (var vehicle in _vehicles) + { + vehicle.AttachMap(map); + } + } + + var exclusive = map.ListSingleOccupancySiteIds(); + MagCarSimLog.WriteLine( + $"[{DateTime.Now:HH:mm:ss.fff}] 已加载地图 {map.FileName},站点 {map.Sites.Count},路径 {map.Tracks.Count},停止/交管点 {(exclusive.Count == 0 ? "无" : string.Join(",", exclusive))}"); + return map; + } + + public void RebuildVehicles(IEnumerable configs) + { + if (IsListening) + { + throw new InvalidOperationException("请先停止模拟再改车辆列表"); + } + + lock (_syncRoot) + { + DisposeVehiclesUnlocked(); + foreach (var config in configs ?? Array.Empty()) + { + if (config == null) + { + continue; + } + + var vehicle = new MagCarSimVehicle(Clone(config), Config); + if (_map != null) + { + vehicle.AttachMap(_map); + } + + _vehicles.Add(vehicle); + } + } + } + + public void StartListen() + { + List vehicles; + SimpleLiteMap map; + lock (_syncRoot) + { + if (IsListening) + { + return; + } + + if (_map == null) + { + throw new InvalidOperationException("请先加载 SimpleLite 地图"); + } + + if (_vehicles.Count == 0) + { + throw new InvalidOperationException("没有可启动的车辆"); + } + + EnsureUniquePortsUnlocked(); + vehicles = _vehicles.ToList(); + map = _map; + EnsureTimerUnlocked(); + IsListening = true; + } + + foreach (var vehicle in vehicles) + { + vehicle.AttachMap(map); + vehicle.StartListen(); + } + } + + public void StartLoops() + { + if (!IsListening) + { + StartListen(); + } + + List vehicles; + lock (_syncRoot) + { + vehicles = _vehicles.ToList(); + IsLooping = true; + } + + var now = DateTime.Now; + foreach (var group in vehicles.GroupBy(RingKey).OrderBy(g => g.Key)) + { + var members = group.OrderBy(v => v.VehicleCode).ToList(); + var dispatchAt = now; + foreach (var vehicle in members) + { + vehicle.StartLoop(dispatchAt); + dispatchAt = dispatchAt.AddMilliseconds(StaggerMs(vehicle)); + } + + MagCarSimLog.WriteLine( + $"[{DateTime.Now:HH:mm:ss.fff}] 同环依次发车 {members[0].Name} 等 {members.Count} 台,间隔 {StaggerMs(members[0])}ms"); + } + } + + public void StopAll() + { + Timer timer; + List vehicles; + lock (_syncRoot) + { + timer = _timer; + _timer = null; + IsListening = false; + IsLooping = false; + vehicles = _vehicles.ToList(); + } + + try + { + timer?.Dispose(); + } + catch + { + } + + foreach (var vehicle in vehicles) + { + vehicle.StopLoop(); + vehicle.StopListen(); + } + } + + public bool TryRelease(ushort vehicleCode) + { + lock (_syncRoot) + { + var vehicle = _vehicles.FirstOrDefault(v => v.VehicleCode == vehicleCode); + if (vehicle == null) + { + return false; + } + + vehicle.Release(); + return true; + } + } + + public List Snapshots() + { + lock (_syncRoot) + { + return _vehicles.Select(v => v.Snapshot()).ToList(); + } + } + + public void Dispose() + { + StopAll(); + lock (_syncRoot) + { + DisposeVehiclesUnlocked(); + } + } + + private void EnsureTimerUnlocked() + { + _timer ??= new Timer(_ => OnTick(), null, 50, 50); + } + + private void OnTick() + { + if (Interlocked.Exchange(ref _tickBusy, 1) != 0) + { + return; + } + + try + { + List vehicles; + SimpleLiteMap map; + lock (_syncRoot) + { + vehicles = _vehicles.ToList(); + map = _map; + } + + var occupancy = SnapshotExclusiveOccupancy(map, vehicles); + var now = DateTime.Now; + foreach (var vehicle in vehicles) + { + vehicle.Tick(now, occupancy); + } + } + finally + { + Interlocked.Exchange(ref _tickBusy, 0); + } + } + + private void EnsureUniquePortsUnlocked() + { + var seen = new HashSet(); + foreach (var vehicle in _vehicles) + { + if (!seen.Add(vehicle.ListenPort)) + { + throw new InvalidOperationException($"端口 {vehicle.ListenPort} 被多辆车占用"); + } + } + } + + private static Dictionary SnapshotExclusiveOccupancy( + SimpleLiteMap map, + IEnumerable vehicles) + { + var occupancy = new Dictionary(); + if (map == null) + { + return occupancy; + } + + foreach (var vehicle in vehicles) + { + if (vehicle.CurrentSiteId <= 0 || + !map.SingleOccupancy(vehicle.CurrentSiteId) || + occupancy.ContainsKey(vehicle.CurrentSiteId)) + { + continue; + } + + occupancy[vehicle.CurrentSiteId] = vehicle.VehicleCode; + } + + return occupancy; + } + + private int StaggerMs(MagCarSimVehicle vehicle) + { + if (Config.LaunchStaggerMs > 0) + { + return Math.Max(200, Config.LaunchStaggerMs); + } + + var interval = vehicle.Config.IntervalMs > 0 ? vehicle.Config.IntervalMs : Config.DefaultIntervalMs; + return Math.Max(200, interval); + } + + private static string RingKey(MagCarSimVehicle vehicle) + { + var ids = vehicle.Config.LoopSiteIds; + if (ids != null && ids.Count > 0) + { + return string.Join("-", ids); + } + + return $"s{vehicle.Config.StartSiteId}-e{vehicle.Config.EndSiteId}"; + } + + private void DisposeVehiclesUnlocked() + { + foreach (var vehicle in _vehicles) + { + vehicle.Dispose(); + } + + _vehicles.Clear(); + } + + private static MagCarSimVehicleConfig Clone(MagCarSimVehicleConfig source) + { + return new MagCarSimVehicleConfig + { + Name = source.Name, + VehicleCode = source.VehicleCode, + ListenPort = source.ListenPort, + StartSiteId = source.StartSiteId, + EndSiteId = source.EndSiteId, + IntervalMs = source.IntervalMs, + LoopSiteIds = source.LoopSiteIds == null ? null : new List(source.LoopSiteIds) + }; + } + } +} diff --git a/StandardScene.MagCarSimulator/Runtime/MagCarSimVehicle.cs b/StandardScene.MagCarSimulator/Runtime/MagCarSimVehicle.cs new file mode 100644 index 0000000..0282fbf --- /dev/null +++ b/StandardScene.MagCarSimulator/Runtime/MagCarSimVehicle.cs @@ -0,0 +1,499 @@ +using System; +using System.Collections.Generic; +using System.Net; + +namespace StandardScene.MagCarSimulator +{ + public sealed class MagCarSimVehicleSnapshot + { + public string Name { get; set; } + public ushort VehicleCode { get; set; } + public int ListenPort { get; set; } + public int StartSiteId { get; set; } + public int EndSiteId { get; set; } + public int IntervalMs { get; set; } + public int CurrentSiteId { get; set; } + public ushort Node { get; set; } + public byte State { get; set; } + public string StateText { get; set; } + public bool WaitingRelease { get; set; } + public bool HoldingForStop { get; set; } + public bool Looping { get; set; } + public bool Listening { get; set; } + public int ClientCount { get; set; } + public string PathText { get; set; } + } + + /// + /// 单车循环:普通站可叠车;停止点与交管点同时只允许一辆,后车停在上一站并保持运行中;仅 Mag_NeedStop 停车等 0x01。 + /// + public sealed class MagCarSimVehicle : IDisposable + { + private readonly object _syncRoot = new object(); + private readonly MagCarSimConfig _hostConfig; + private MagCarSimTcpServer _server; + private SimpleLiteMap _map; + private List _loopSiteIds = new List(); + private int _index; + private DateTime _nextHopAt = DateTime.MaxValue; + private DateTime _dispatchAt = DateTime.MinValue; + private DateTime _lastHoldLogAt = DateTime.MinValue; + private bool _looping; + private bool _dispatched; + private bool _waitingRelease; + private bool _pausedByStopCommand; + private bool _holdingForStop; + + public MagCarSimVehicle(MagCarSimVehicleConfig config, MagCarSimConfig hostConfig) + { + Config = config ?? throw new ArgumentNullException(nameof(config)); + _hostConfig = hostConfig ?? throw new ArgumentNullException(nameof(hostConfig)); + Name = string.IsNullOrWhiteSpace(config.Name) ? $"AGV-{config.VehicleCode}" : config.Name; + Charge = 100; + Voltage = 24f; + Speed = 50; + } + + public MagCarSimVehicleConfig Config { get; } + public string Name { get; } + public ushort VehicleCode => Config.VehicleCode; + public int ListenPort => Config.ListenPort; + public int CurrentSiteId { get; private set; } + public ushort Node { get; private set; } + public byte State { get; private set; } + public byte Charge { get; private set; } + public float Current { get; private set; } + public float Voltage { get; private set; } + public byte Speed { get; private set; } + public ushort Angle { get; private set; } + public byte Task { get; private set; } + public byte Lift { get; private set; } + public byte Roll { get; private set; } + public bool WaitingRelease => _waitingRelease; + public bool HoldingForStop => _holdingForStop; + public bool Looping => _looping; + + public bool Listening => _server != null && _server.IsRunning; + + public void AttachMap(SimpleLiteMap map) + { + lock (_syncRoot) + { + _map = map; + if (!_looping) + { + PlaceAtStartUnlocked(); + } + } + } + + public void StartListen() + { + MagCarSimTcpServer server; + lock (_syncRoot) + { + if (_server != null && _server.IsRunning) + { + return; + } + + _server?.Dispose(); + var address = string.IsNullOrWhiteSpace(_hostConfig.ListenAddress) + ? "0.0.0.0" + : _hostConfig.ListenAddress; + server = new MagCarSimTcpServer(IPAddress.Parse(address), Config.ListenPort, HandleFrame); + _server = server; + PlaceAtStartUnlocked(); + Log($"监听 {address}:{Config.ListenPort},当前站={CurrentSiteId} node={Node} {MagCarSimProtocol.StateText(State)}"); + } + + server.Start(); + } + + public void StopListen() + { + MagCarSimTcpServer server; + lock (_syncRoot) + { + server = _server; + _server = null; + } + + server?.Dispose(); + } + + public void StartLoop(DateTime dispatchAt) + { + lock (_syncRoot) + { + if (_map == null) + { + throw new InvalidOperationException($"{Name} 尚未加载地图"); + } + + _loopSiteIds = MapPathFinder.ResolveLoop(_map, Config); + _index = 0; + if (Config.StartSiteId > 0) + { + var found = _loopSiteIds.IndexOf(Config.StartSiteId); + if (found >= 0) + { + _index = found; + } + } + + _looping = true; + _dispatched = false; + _holdingForStop = false; + _pausedByStopCommand = false; + _waitingRelease = false; + _dispatchAt = dispatchAt; + PlaceAtStartUnlocked(); + // 待命阶段若起点是停止点,先报运行中,避免交管误放行并占住 pending,导致真发车后长时间不放。 + if (_map != null && _map.NeedStop(CurrentSiteId)) + { + State = MagCarSimProtocol.StateRunning; + _waitingRelease = false; + } + + var delayMs = Math.Max(0, (int)(dispatchAt - DateTime.Now).TotalMilliseconds); + Log($"待命发车,环线 {MapPathFinder.FormatPath(_loopSiteIds, 16)},间隔 {IntervalOrDefault()}ms" + + (delayMs > 50 ? $",{delayMs}ms 后启动" : ",立即启动")); + } + } + + public void StopLoop() + { + lock (_syncRoot) + { + _looping = false; + _dispatched = false; + _waitingRelease = false; + _holdingForStop = false; + _pausedByStopCommand = false; + _nextHopAt = DateTime.MaxValue; + State = MagCarSimProtocol.StateStopping; + Log("已停止循环"); + } + } + + public void Release() + { + lock (_syncRoot) + { + ApplyStartUnlocked("界面放行"); + } + } + + public void Tick(DateTime now, Dictionary occupancy) + { + lock (_syncRoot) + { + if (!_looping || _pausedByStopCommand) + { + return; + } + + if (!_dispatched) + { + TryDispatchUnlocked(now, occupancy); + return; + } + + if (_waitingRelease) + { + return; + } + + if (State != MagCarSimProtocol.StateRunning) + { + return; + } + + if (now < _nextHopAt) + { + return; + } + + AdvanceUnlocked(now, occupancy); + } + } + + public MagCarSimVehicleSnapshot Snapshot() + { + lock (_syncRoot) + { + return new MagCarSimVehicleSnapshot + { + Name = Name, + VehicleCode = VehicleCode, + ListenPort = ListenPort, + StartSiteId = Config.StartSiteId, + EndSiteId = Config.EndSiteId, + IntervalMs = Config.IntervalMs, + CurrentSiteId = CurrentSiteId, + Node = Node, + State = State, + StateText = MagCarSimProtocol.StateText(State), + WaitingRelease = _waitingRelease, + HoldingForStop = _holdingForStop, + Looping = _looping, + Listening = Listening, + ClientCount = _server?.ClientCount ?? 0, + PathText = MapPathFinder.FormatPath(_loopSiteIds, 12) + }; + } + } + + public void Dispose() + { + lock (_syncRoot) + { + _looping = false; + } + + StopListen(); + } + + private byte[] HandleFrame(byte[] request) + { + lock (_syncRoot) + { + if (!MagCarSimProtocol.TryParse(request, out var parsed)) + { + Log("收到非法帧"); + return BuildStatusUnlocked(MagCarSimProtocol.CmdQueryState); + } + + if (parsed.VehicleCode != 0 && parsed.VehicleCode != VehicleCode) + { + Log($"帧车号 {parsed.VehicleCode} 与本车 {VehicleCode} 不一致,仍按本车应答"); + } + + if (_hostConfig.LogRawFrames) + { + Log($"RX {MagCarSimProtocol.CommandName(parsed.Command)} {MagCarSimProtocol.ToHex(request)}"); + } + else if (parsed.Command != MagCarSimProtocol.CmdQueryState || _hostConfig.LogQueries) + { + Log($"RX {MagCarSimProtocol.CommandName(parsed.Command)}"); + } + + switch (parsed.Command) + { + case MagCarSimProtocol.CmdStart: + ApplyStartUnlocked("0x01"); + break; + case MagCarSimProtocol.CmdStop: + _pausedByStopCommand = true; + State = MagCarSimProtocol.StateStopping; + Log("收到停止,暂停循环"); + break; + case MagCarSimProtocol.CmdSpeed: + Speed = (byte)Math.Clamp((int)parsed.Data0 >> 8, 0, 100); + break; + case MagCarSimProtocol.CmdAngle: + Angle = parsed.Data0; + break; + case MagCarSimProtocol.CmdLegacyNode: + case MagCarSimProtocol.CmdTask: + Log($"忽略路径命令 {MagCarSimProtocol.CommandName(parsed.Command)}(本模拟器按 WinForm 循环跑)"); + break; + } + + return BuildStatusUnlocked(parsed.Command); + } + } + + private void ApplyStartUnlocked(string source) + { + if (!_dispatched) + { + Log($"待命中忽略放行({source})"); + return; + } + + if (_waitingRelease) + { + _waitingRelease = false; + _pausedByStopCommand = false; + State = MagCarSimProtocol.StateRunning; + _nextHopAt = DateTime.Now.AddMilliseconds(IntervalOrDefault()); + Log($"放行成功({source}),站点 {CurrentSiteId} 改为运行中,{IntervalOrDefault()}ms 后前往下一站"); + return; + } + + if (_pausedByStopCommand && _looping) + { + _pausedByStopCommand = false; + State = MagCarSimProtocol.StateRunning; + _nextHopAt = DateTime.Now.AddMilliseconds(IntervalOrDefault()); + Log($"从暂停恢复({source})"); + return; + } + + if (_looping && State != MagCarSimProtocol.StateRunning) + { + State = MagCarSimProtocol.StateRunning; + _nextHopAt = DateTime.Now.AddMilliseconds(IntervalOrDefault()); + Log($"启动运行({source})"); + } + } + + private void PlaceAtStartUnlocked() + { + CurrentSiteId = Config.StartSiteId; + Node = _map == null ? (ushort)Math.Clamp(Config.StartSiteId, 0, ushort.MaxValue) : _map.ResolveNode(Config.StartSiteId); + State = MagCarSimProtocol.StateStopping; + _waitingRelease = false; + _pausedByStopCommand = false; + } + + private void ArriveUnlocked(int siteId, bool isStart) + { + CurrentSiteId = siteId; + Node = _map.ResolveNode(siteId); + var needStop = _map.NeedStop(siteId); + if (needStop) + { + State = MagCarSimProtocol.StateStopping; + _waitingRelease = true; + _nextHopAt = DateTime.MaxValue; + Log($"{(isStart ? "起点" : "到站")} {siteId} node={Node} Mag_NeedStop=true → 停止中,等待放行"); + return; + } + + State = MagCarSimProtocol.StateRunning; + _waitingRelease = false; + _nextHopAt = DateTime.Now.AddMilliseconds(IntervalOrDefault()); + if (isStart) + { + Log($"起点 {siteId} node={Node} 过站,{IntervalOrDefault()}ms 后下一地标"); + } + } + + private void TryDispatchUnlocked(DateTime now, Dictionary occupancy) + { + if (now < _dispatchAt) + { + return; + } + + if (_loopSiteIds.Count == 0) + { + return; + } + + var startSite = _loopSiteIds[_index]; + if (IsOccupiedUnlocked(startSite, occupancy)) + { + HoldForOccupiedUnlocked(now, startSite, "发车"); + return; + } + + OccupyUnlocked(occupancy, startSite); + _dispatched = true; + _holdingForStop = false; + ArriveUnlocked(startSite, isStart: true); + } + + private void AdvanceUnlocked(DateTime now, Dictionary occupancy) + { + if (_loopSiteIds.Count < 2) + { + return; + } + + var nextIndex = (_index + 1) % _loopSiteIds.Count; + var nextSite = _loopSiteIds[nextIndex]; + if (IsOccupiedUnlocked(nextSite, occupancy)) + { + HoldForOccupiedUnlocked(now, nextSite, "进站"); + return; + } + + MoveOccupancyUnlocked(occupancy, CurrentSiteId, nextSite); + _holdingForStop = false; + _index = nextIndex; + ArriveUnlocked(nextSite, isStart: false); + } + + private bool IsOccupiedUnlocked(int siteId, Dictionary occupancy) + { + if (_map == null || occupancy == null || !_map.SingleOccupancy(siteId)) + { + return false; + } + + return occupancy.TryGetValue(siteId, out var occupier) && occupier != VehicleCode; + } + + private void OccupyUnlocked(Dictionary occupancy, int siteId) + { + if (occupancy == null || siteId <= 0 || _map == null || !_map.SingleOccupancy(siteId)) + { + return; + } + + occupancy[siteId] = VehicleCode; + } + + private void MoveOccupancyUnlocked(Dictionary occupancy, int fromSiteId, int toSiteId) + { + if (occupancy == null) + { + return; + } + + if (fromSiteId > 0 && + occupancy.TryGetValue(fromSiteId, out var occupier) && + occupier == VehicleCode) + { + occupancy.Remove(fromSiteId); + } + + OccupyUnlocked(occupancy, toSiteId); + } + + private void HoldForOccupiedUnlocked(DateTime now, int occupiedSiteId, string action) + { + _holdingForStop = true; + State = MagCarSimProtocol.StateRunning; + _waitingRelease = false; + _nextHopAt = now.AddMilliseconds(200); + if ((now - _lastHoldLogAt).TotalMilliseconds >= 5000) + { + _lastHoldLogAt = now; + Log($"停止/交管点 {occupiedSiteId} 已有车,{action}受阻,保持站点 {CurrentSiteId} 运行中"); + } + } + + private int IntervalOrDefault() + { + var value = Config.IntervalMs > 0 ? Config.IntervalMs : _hostConfig.DefaultIntervalMs; + return Math.Max(200, value); + } + + private byte[] BuildStatusUnlocked(byte command) + { + return MagCarSimProtocol.BuildStatus( + command, + VehicleCode, + Node, + State, + Charge, + Current, + Voltage, + Speed, + Angle, + Task, + Lift, + Roll); + } + + private void Log(string message) + { + MagCarSimLog.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] [{Name}/{VehicleCode}] {message}"); + } + } +} diff --git a/StandardScene.MagCarSimulator/StandardScene.MagCarSimulator.csproj b/StandardScene.MagCarSimulator/StandardScene.MagCarSimulator.csproj new file mode 100644 index 0000000..9762141 --- /dev/null +++ b/StandardScene.MagCarSimulator/StandardScene.MagCarSimulator.csproj @@ -0,0 +1,24 @@ + + + + WinExe + net8.0-windows + StandardScene.MagCarSimulator + StandardScene.MagCarSimulator + latest + disable + disable + true + true + + + + + + + + + + + + diff --git a/StandardScene.MagCarSimulator/appsettings.json b/StandardScene.MagCarSimulator/appsettings.json new file mode 100644 index 0000000..ec60897 --- /dev/null +++ b/StandardScene.MagCarSimulator/appsettings.json @@ -0,0 +1,574 @@ +{ + "MapPath": "D:\\工作\\stand\\SimpleLite\\maps\\复杂交管.json", + "UseTagValueAsNode": false, + "ListenAddress": "0.0.0.0", + "LogRawFrames": false, + "LogQueries": false, + "LogDirectory": "log", + "EnableFileLog": true, + "DefaultIntervalMs": 2000, + "LaunchStaggerMs": 0, + "ControlAreasPath": "D:\\工作\\stand\\SimpleLite\\config\\Signal\\mag-control-areas.json", + "Vehicles": [ + { + "Name": "西环-1", + "VehicleCode": 1, + "ListenPort": 5001, + "StartSiteId": 1, + "EndSiteId": 7, + "IntervalMs": 1800, + "LoopSiteIds": [ + 1, + 2, + 3, + 4, + 5, + 104, + 100, + 103, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 201, + 13, + 14 + ] + }, + { + "Name": "西环-2", + "VehicleCode": 2, + "ListenPort": 5002, + "StartSiteId": 4, + "EndSiteId": 7, + "IntervalMs": 1880, + "LoopSiteIds": [ + 1, + 2, + 3, + 4, + 5, + 104, + 100, + 103, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 201, + 13, + 14 + ] + }, + { + "Name": "西环-3", + "VehicleCode": 3, + "ListenPort": 5003, + "StartSiteId": 8, + "EndSiteId": 7, + "IntervalMs": 1960, + "LoopSiteIds": [ + 1, + 2, + 3, + 4, + 5, + 104, + 100, + 103, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 201, + 13, + 14 + ] + }, + { + "Name": "西环-4", + "VehicleCode": 4, + "ListenPort": 5004, + "StartSiteId": 12, + "EndSiteId": 7, + "IntervalMs": 2040, + "LoopSiteIds": [ + 1, + 2, + 3, + 4, + 5, + 104, + 100, + 103, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 201, + 13, + 14 + ] + }, + { + "Name": "西环-5", + "VehicleCode": 5, + "ListenPort": 5005, + "StartSiteId": 13, + "EndSiteId": 7, + "IntervalMs": 2120, + "LoopSiteIds": [ + 1, + 2, + 3, + 4, + 5, + 104, + 100, + 103, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 201, + 13, + 14 + ] + }, + { + "Name": "东环-1", + "VehicleCode": 6, + "ListenPort": 5006, + "StartSiteId": 15, + "EndSiteId": 23, + "IntervalMs": 1900, + "LoopSiteIds": [ + 15, + 16, + 17, + 18, + 19, + 20, + 202, + 21, + 22, + 23, + 24, + 25, + 26, + 6, + 103, + 100, + 104, + 5 + ] + }, + { + "Name": "东环-2", + "VehicleCode": 7, + "ListenPort": 5007, + "StartSiteId": 18, + "EndSiteId": 23, + "IntervalMs": 1980, + "LoopSiteIds": [ + 15, + 16, + 17, + 18, + 19, + 20, + 202, + 21, + 22, + 23, + 24, + 25, + 26, + 6, + 103, + 100, + 104, + 5 + ] + }, + { + "Name": "东环-3", + "VehicleCode": 8, + "ListenPort": 5008, + "StartSiteId": 20, + "EndSiteId": 23, + "IntervalMs": 2060, + "LoopSiteIds": [ + 15, + 16, + 17, + 18, + 19, + 20, + 202, + 21, + 22, + 23, + 24, + 25, + 26, + 6, + 103, + 100, + 104, + 5 + ] + }, + { + "Name": "东环-4", + "VehicleCode": 9, + "ListenPort": 5009, + "StartSiteId": 22, + "EndSiteId": 23, + "IntervalMs": 2140, + "LoopSiteIds": [ + 15, + 16, + 17, + 18, + 19, + 20, + 202, + 21, + 22, + 23, + 24, + 25, + 26, + 6, + 103, + 100, + 104, + 5 + ] + }, + { + "Name": "东环-5", + "VehicleCode": 10, + "ListenPort": 5010, + "StartSiteId": 25, + "EndSiteId": 23, + "IntervalMs": 2220, + "LoopSiteIds": [ + 15, + 16, + 17, + 18, + 19, + 20, + 202, + 21, + 22, + 23, + 24, + 25, + 26, + 6, + 103, + 100, + 104, + 5 + ] + }, + { + "Name": "北环-1", + "VehicleCode": 11, + "ListenPort": 5011, + "StartSiteId": 35, + "EndSiteId": 28, + "IntervalMs": 2000, + "LoopSiteIds": [ + 35, + 36, + 9, + 37, + 38, + 27, + 101, + 100, + 102, + 28, + 29, + 30, + 24, + 31, + 32, + 33, + 203, + 34 + ] + }, + { + "Name": "北环-2", + "VehicleCode": 12, + "ListenPort": 5012, + "StartSiteId": 37, + "EndSiteId": 28, + "IntervalMs": 2080, + "LoopSiteIds": [ + 35, + 36, + 9, + 37, + 38, + 27, + 101, + 100, + 102, + 28, + 29, + 30, + 24, + 31, + 32, + 33, + 203, + 34 + ] + }, + { + "Name": "北环-3", + "VehicleCode": 13, + "ListenPort": 5013, + "StartSiteId": 29, + "EndSiteId": 28, + "IntervalMs": 2160, + "LoopSiteIds": [ + 35, + 36, + 9, + 37, + 38, + 27, + 101, + 100, + 102, + 28, + 29, + 30, + 24, + 31, + 32, + 33, + 203, + 34 + ] + }, + { + "Name": "北环-4", + "VehicleCode": 14, + "ListenPort": 5014, + "StartSiteId": 32, + "EndSiteId": 28, + "IntervalMs": 2240, + "LoopSiteIds": [ + 35, + 36, + 9, + 37, + 38, + 27, + 101, + 100, + 102, + 28, + 29, + 30, + 24, + 31, + 32, + 33, + 203, + 34 + ] + }, + { + "Name": "北环-5", + "VehicleCode": 15, + "ListenPort": 5015, + "StartSiteId": 203, + "EndSiteId": 28, + "IntervalMs": 2320, + "LoopSiteIds": [ + 35, + 36, + 9, + 37, + 38, + 27, + 101, + 100, + 102, + 28, + 29, + 30, + 24, + 31, + 32, + 33, + 203, + 34 + ] + }, + { + "Name": "南环-1", + "VehicleCode": 16, + "ListenPort": 5016, + "StartSiteId": 39, + "EndSiteId": 28, + "IntervalMs": 2100, + "LoopSiteIds": [ + 39, + 40, + 204, + 41, + 42, + 43, + 17, + 44, + 45, + 28, + 102, + 100, + 101, + 27, + 46, + 47, + 2, + 48 + ] + }, + { + "Name": "南环-2", + "VehicleCode": 17, + "ListenPort": 5017, + "StartSiteId": 204, + "EndSiteId": 28, + "IntervalMs": 2180, + "LoopSiteIds": [ + 39, + 40, + 204, + 41, + 42, + 43, + 17, + 44, + 45, + 28, + 102, + 100, + 101, + 27, + 46, + 47, + 2, + 48 + ] + }, + { + "Name": "南环-3", + "VehicleCode": 18, + "ListenPort": 5018, + "StartSiteId": 42, + "EndSiteId": 28, + "IntervalMs": 2260, + "LoopSiteIds": [ + 39, + 40, + 204, + 41, + 42, + 43, + 17, + 44, + 45, + 28, + 102, + 100, + 101, + 27, + 46, + 47, + 2, + 48 + ] + }, + { + "Name": "南环-4", + "VehicleCode": 19, + "ListenPort": 5019, + "StartSiteId": 45, + "EndSiteId": 28, + "IntervalMs": 2340, + "LoopSiteIds": [ + 39, + 40, + 204, + 41, + 42, + 43, + 17, + 44, + 45, + 28, + 102, + 100, + 101, + 27, + 46, + 47, + 2, + 48 + ] + }, + { + "Name": "南环-5", + "VehicleCode": 20, + "ListenPort": 5020, + "StartSiteId": 47, + "EndSiteId": 28, + "IntervalMs": 2420, + "LoopSiteIds": [ + 39, + 40, + 204, + 41, + 42, + 43, + 17, + 44, + 45, + 28, + 102, + 100, + 101, + 27, + 46, + 47, + 2, + 48 + ] + } + ] +} \ No newline at end of file diff --git a/StandardScene.Magnetic/CarTypes/Mag2Car.cs b/StandardScene.Magnetic/CarTypes/Mag2Car.cs index b0c633b..c9e2bd4 100644 --- a/StandardScene.Magnetic/CarTypes/Mag2Car.cs +++ b/StandardScene.Magnetic/CarTypes/Mag2Car.cs @@ -79,7 +79,7 @@ namespace StandardScene.CarTypes [FieldMember] public bool EnableDetailLog = true; [FieldMember] public bool LogRawFrame = true; [FieldMember] public bool EnableFileLog = true; - [FieldMember] public string LogDirectory = "logs"; + [FieldMember] public string LogDirectory = "log"; [FieldMember] public float CarLength = 1200; [FieldMember] public float CarWidth = 800; diff --git a/StandardScene.Magnetic/CarTypes/MagCar.cs b/StandardScene.Magnetic/CarTypes/MagCar.cs index 246ca4d..c0e533a 100644 --- a/StandardScene.Magnetic/CarTypes/MagCar.cs +++ b/StandardScene.Magnetic/CarTypes/MagCar.cs @@ -17,6 +17,7 @@ using System.Drawing.Drawing2D; using System.Globalization; using System.IO; using System.Linq; +using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; @@ -101,6 +102,9 @@ namespace StandardScene.CarTypes /// private DateTime _lastPollTime = DateTime.MinValue; + /// 最近一次与 AGV 通讯成功的时间;用于「断开超过 OfflineAfterMs → 离线」。 + private DateTime _lastCommOkTime = DateTime.Now; + /// /// AGV 服务端监听端口,默认 5000。 /// @@ -135,6 +139,12 @@ namespace StandardScene.CarTypes /// [FieldMember] public int PollIntervalMs = 1000; + /// + /// 连续通讯失败超过该毫秒数后,概况显示「离线」。 + /// 默认 20000(20 秒);期间失败会显示「连接中」。 + /// + [FieldMember] public int OfflineAfterMs = 20000; + /// /// 移动任务的预留超时时间,单位秒。 /// 当前 MagCar 不下发脚本,保留该字段用于后续任务调度或界面配置兼容。 @@ -280,11 +290,28 @@ namespace StandardScene.CarTypes } catch (Exception ex) { - lstatus = IsBenignSocketFault(ex) ? lstatus : "离线"; - if (!IsBenignSocketFault(ex)) - { - DetailLog($"keepAlive poll failed: {ex.Message}"); - } + ApplyOfflineAfterDisconnect(ex); + } + } + + /// + /// 通讯失败时:未满 显示「连接中」,满 20 秒(可配)后显示「离线」。 + /// + private void ApplyOfflineAfterDisconnect(Exception ex) + { + var offlineAfter = OfflineAfterMs < 1000 ? 1000 : OfflineAfterMs; + if ((DateTime.Now - _lastCommOkTime).TotalMilliseconds >= offlineAfter) + { + lstatus = "离线"; + } + else if (lstatus != "离线") + { + lstatus = "连接中"; + } + + if (!IsBenignSocketFault(ex)) + { + DetailLog($"keepAlive poll failed: {ex.Message}"); } } @@ -590,6 +617,13 @@ namespace StandardScene.CarTypes try { ConnectWithTimeout(client); + if (IsLoopbackSelfConnect(client)) + { + AbortClientQuietly(client); + throw new IOException( + $"TCP self-connect {address}:{Port} (local ephemeral hit listen port); refuse and retry"); + } + client.SendTimeout = SendTimeoutMs; client.ReceiveTimeout = ReceiveTimeoutMs; _persistentClient = client; @@ -619,7 +653,51 @@ namespace StandardScene.CarTypes { try { - return _persistentClient != null && _persistentClient.Connected; + if (_persistentClient == null || !_persistentClient.Connected) + { + return false; + } + + // 本机动态端口若从 1024 起,连 500x 且模拟器未监听时,Windows 可能自连成功且 Connected=true, + // 之后会一直把自身请求当响应(State=0 → 未准备),必须主动拆掉重连。 + if (IsLoopbackSelfConnect(_persistentClient)) + { + ClosePersistentConnection("loopback self-connect"); + return false; + } + + return true; + } + catch + { + return false; + } + } + + /// + /// 检测 Windows/localhost 上「源端口=目标端口」的自连(无真实服务端)。 + /// + private static bool IsLoopbackSelfConnect(TcpClient client) + { + try + { + if (client?.Client == null) + { + return false; + } + + if (!(client.Client.LocalEndPoint is IPEndPoint local) || + !(client.Client.RemoteEndPoint is IPEndPoint remote)) + { + return false; + } + + if (local.Port != remote.Port) + { + return false; + } + + return IPAddress.IsLoopback(local.Address) && IPAddress.IsLoopback(remote.Address); } catch { @@ -680,6 +758,13 @@ namespace StandardScene.CarTypes { DetailLog($"short connect begin {address}:{Port}, timeout={ConnectTimeoutMs}ms"); ConnectWithTimeout(client); + if (IsLoopbackSelfConnect(client)) + { + AbortClientQuietly(client); + throw new IOException( + $"TCP self-connect {address}:{Port} (local ephemeral hit listen port); refuse and retry"); + } + DetailLog($"short connect ok {address}:{Port}"); client.SendTimeout = SendTimeoutMs; @@ -785,11 +870,17 @@ namespace StandardScene.CarTypes if (!string.IsNullOrEmpty(message) && (message.Contains("已中止 I/O", StringComparison.Ordinal) || message.Contains("I/O operation", StringComparison.OrdinalIgnoreCase) || - message.Contains("operation was aborted", StringComparison.OrdinalIgnoreCase))) + message.Contains("operation was aborted", StringComparison.OrdinalIgnoreCase) || + message.Contains("self-connect", StringComparison.OrdinalIgnoreCase))) { return true; } } + + if (current is TimeoutException) + { + return true; + } } return false; @@ -899,6 +990,7 @@ namespace StandardScene.CarTypes private void ApplyReport(MagCarReport report) { LastReport = report; + _lastCommOkTime = DateTime.Now; lstatus = report.Alarm != 0 ? "报警" : report.State == 0 ? "未准备" : "上线"; th = report.Angle; @@ -925,12 +1017,108 @@ namespace StandardScene.CarTypes haveCoordination = true; siteID = site.id; - x = site.x; - y = site.y; + ApplyStackedSitePose(site); SyncTrafficFromReport(site, report); DetailLog($"report applied, node={report.Node}, site={siteID}, x={x:0.###}, y={y:0.###}, th={th:0.###}, state={StateText(report.State)}, soc={report.Charge}, current={report.Current:0.###}, voltage={report.Voltage:0.###}, speed={report.Speed}, task={report.Task}, lift={report.Lift}, roll={report.Roll}, alarm=0x{report.Alarm:X}"); } + /// + /// 同一普通站多车时,沿路网方向按车号依次错开坐标,避免 SimpleLite 地图上完全重叠。 + /// 站点逻辑仍用 ,不改变交管占用。 + /// + private void ApplyStackedSitePose(Site site) + { + if (site == null) + { + return; + } + + var ids = SameSiteCarIds(site.id); + var index = Math.Max(0, ids.IndexOf(id)); + var (ux, uy) = SiteSpreadAxis(site); + var step = Math.Max(CarLength * 0.9f, 900f); + var centered = index - (ids.Count - 1) * 0.5; + x = (float)(site.x + ux * step * centered); + y = (float)(site.y + uy * step * centered); + } + + private List SameSiteCarIds(int siteId) + { + var ids = new List(); + try + { + foreach (var car in SimpleLib.GetAllCars().OfType()) + { + if (car != null && car.siteID == siteId && !ids.Contains(car.id)) + { + ids.Add(car.id); + } + } + } + catch + { + } + + if (!ids.Contains(id)) + { + ids.Add(id); + } + + ids.Sort(); + return ids; + } + + private static (double ux, double uy) SiteSpreadAxis(Site site) + { + double bestDx = 0; + double bestDy = 0; + double bestLen = 0; + try + { + foreach (var track in SimpleLib.GetAllTracks()) + { + if (track == null) + { + continue; + } + + var otherId = track.siteA == site.id ? track.siteB + : track.siteB == site.id ? track.siteA + : 0; + if (otherId <= 0) + { + continue; + } + + var other = SimpleLib.GetSite(otherId); + if (other == null) + { + continue; + } + + var dx = other.x - site.x; + var dy = other.y - site.y; + var len = Math.Sqrt(dx * dx + dy * dy); + if (len > bestLen) + { + bestLen = len; + bestDx = dx; + bestDy = dy; + } + } + } + catch + { + } + + if (bestLen < 1) + { + return (1, 0); + } + + return (bestDx / bestLen, bestDy / bestLen); + } + /// /// 将 AGV 上报的当前地标同步到交通锁(holdingLocks)。 /// GhostCar 调度依赖 holdingLocks/GetLastSite,仅改 x/y/siteID 会导致“画面在动、初始化占点不动”。 @@ -954,6 +1142,25 @@ namespace StandardScene.CarTypes return; } + // 他车仍占本站锁但物理站已离开 → 回收陈旧锁,否则 TrafficReset 失败,画面占点不跟着走。 + var holder = FindOtherCarHoldingSite(site.id); + if (holder != null) + { + if (!TryReleaseStaleHolder(holder, site.id)) + { + if (_lastSyncedTrafficSiteId != -site.id) + { + DetailLog( + $"traffic sync skip, site={site.id} held by car={holder.id}, selfLock={lockedSite}, node={report.Node}"); + _lastSyncedTrafficSiteId = -site.id; + } + + return; + } + + DetailLog($"traffic sync released stale holder car={holder.id}, site={site.id}"); + } + try { DetailLog($"traffic sync TrafficReset, lock={lockedSite}, targetSite={site.id}, node={report.Node}, state={StateText(report.State)}"); @@ -966,6 +1173,52 @@ namespace StandardScene.CarTypes } } + private Car FindOtherCarHoldingSite(int siteId) + { + foreach (var other in SimpleLib.GetAllCars().OfType()) + { + if (other == null || other.id == id) + { + continue; + } + + if (other.status?.holdingLocks != null && + Array.IndexOf(other.status.holdingLocks, siteId) >= 0) + { + return other; + } + } + + return null; + } + + private bool TryReleaseStaleHolder(Car other, int siteId) + { + if (other == null) + { + return false; + } + + var online = other.tags?.Contains("Online") == true; + var physicalSiteId = other.siteID > 0 ? other.siteID : other.GetLastSite(); + var stale = !online || (physicalSiteId > 0 && physicalSiteId != siteId); + if (!stale) + { + return false; + } + + try + { + TrafficControl.Leave(other, siteId); + return Array.IndexOf(other.status.holdingLocks ?? Array.Empty(), siteId) < 0; + } + catch (Exception ex) + { + DetailLog($"traffic sync release stale holder failed: car={other.id}, site={siteId}, {ex.Message}"); + return false; + } + } + /// /// 将 AGV 返回的节点号解析为场景站点。 /// 根据 决定优先匹配站点 TagValue 还是直接匹配站点 id。 diff --git a/StandardScene.Magnetic/Tasking/Fass2ControlAreaOccupancy.cs b/StandardScene.Magnetic/Tasking/Fass2ControlAreaOccupancy.cs index 6563346..daed672 100644 --- a/StandardScene.Magnetic/Tasking/Fass2ControlAreaOccupancy.cs +++ b/StandardScene.Magnetic/Tasking/Fass2ControlAreaOccupancy.cs @@ -9,6 +9,7 @@ namespace StandardScene.Magnetic.Tasking { /// /// 按 holdingLocks + 物理 siteID 统计管控站点列表上的他车占用。 + /// Mag2 仍读地图 Fass2_ControlArea 字段;磁条交管进程只放行 MagCar,不介入本路径。 /// internal static class Fass2ControlAreaOccupancy { diff --git a/StandardScene.Magnetic/Tasking/Mag2CarFileLogger.cs b/StandardScene.Magnetic/Tasking/Mag2CarFileLogger.cs index 24c920c..8713f69 100644 --- a/StandardScene.Magnetic/Tasking/Mag2CarFileLogger.cs +++ b/StandardScene.Magnetic/Tasking/Mag2CarFileLogger.cs @@ -6,17 +6,17 @@ using System.Text; namespace StandardScene.Magnetic.Tasking { /// - /// Mag2Car 本地文件日志,按协议车号分目录:logs/car{VehicleCode}/mag2_yyyyMMdd.log + /// Mag2Car 本地文件日志,按协议车号分目录:log/car{VehicleCode}/mag2_yyyyMMdd.log /// public static class Mag2CarFileLogger { private static readonly ConcurrentDictionary CarLocks = new ConcurrentDictionary(); - private static string _baseDirectory = "logs"; + private static string _baseDirectory = "log"; private static bool _enabled = true; public static void Configure(string baseDirectory, bool enabled) { - _baseDirectory = string.IsNullOrWhiteSpace(baseDirectory) ? "logs" : baseDirectory.Trim(); + _baseDirectory = string.IsNullOrWhiteSpace(baseDirectory) ? "log" : baseDirectory.Trim(); _enabled = enabled; } diff --git a/StandardScene.Signal/Config/Signal/handshake-points.json b/StandardScene.Signal/Config/Signal/handshake-points.json index d732469..2ad4688 100644 --- a/StandardScene.Signal/Config/Signal/handshake-points.json +++ b/StandardScene.Signal/Config/Signal/handshake-points.json @@ -2,31 +2,46 @@ { "Sit": 98, "SignalType": "JGControl", - "SignalParams": "上线机构1;RequestIn" + "JgName": "上线机构1", + "DockId": "dock1", + "Action": "RequestIn" }, { "Sit": 100, "SignalType": "JGControl", - "SignalParams": "上线机构1;Arrived" + "JgName": "上线机构1", + "DockId": "dock1", + "Action": "Arrived" + }, + { + "Sit": 108, + "SignalType": "JGControl", + "JgName": "上线机构1", + "DockId": "dock2", + "Action": "RequestIn" }, { "Sit": 199, "SignalType": "JGControl", - "SignalParams": "下线机构1;RequestIn" + "JgName": "下线机构1", + "DockId": "dock1", + "Action": "RequestIn" }, { "Sit": 201, "SignalType": "PointControl", - "SignalParams": "UP1;下线机构1" + "JgName": "下线机构1", + "DockId": "dock1", + "Action": "UP1" }, { "Sit": 50, "SignalType": "TimedCharging", - "SignalParams": "300;95;20" + "ExtraParams": "300;95;20" }, { "Sit": 60, "SignalType": "RateFlowControl", - "SignalParams": "缓存区;A;2;60,61,62" + "ExtraParams": "缓存区;A;2;60,61,62" } ] diff --git a/StandardScene.Signal/Config/Signal/mag-control-areas.json b/StandardScene.Signal/Config/Signal/mag-control-areas.json new file mode 100644 index 0000000..ea67120 --- /dev/null +++ b/StandardScene.Signal/Config/Signal/mag-control-areas.json @@ -0,0 +1,134 @@ +[ + { + "TriggerSit": 4, + "AreaName": "路口中", + "CompatGroup": "NS-W", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "5,104,100,103,6", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 26, + "AreaName": "路口中", + "CompatGroup": "NS-E", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "6,103,100,104,5", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 38, + "AreaName": "路口中", + "CompatGroup": "EW-N", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "27,101,100,102,28", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 45, + "AreaName": "路口中", + "CompatGroup": "EW-S", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "28,102,100,101,27", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 1, + "AreaName": "西南角", + "CompatGroup": "SW-W", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "2", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 47, + "AreaName": "西南角", + "CompatGroup": "SW-S", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "2", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 8, + "AreaName": "西北角", + "CompatGroup": "NW-W", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "9", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 36, + "AreaName": "西北角", + "CompatGroup": "NW-N", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "9", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 16, + "AreaName": "东南角", + "CompatGroup": "SE-E", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "17", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 43, + "AreaName": "东南角", + "CompatGroup": "SE-S", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "17", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 23, + "AreaName": "东北角", + "CompatGroup": "NE-E", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "24", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 30, + "AreaName": "东北角", + "CompatGroup": "NE-N", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "24", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + } +] diff --git a/StandardScene.Signal/Config/Signal/mag-control-areas.复杂交管.json b/StandardScene.Signal/Config/Signal/mag-control-areas.复杂交管.json new file mode 100644 index 0000000..ea67120 --- /dev/null +++ b/StandardScene.Signal/Config/Signal/mag-control-areas.复杂交管.json @@ -0,0 +1,134 @@ +[ + { + "TriggerSit": 4, + "AreaName": "路口中", + "CompatGroup": "NS-W", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "5,104,100,103,6", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 26, + "AreaName": "路口中", + "CompatGroup": "NS-E", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "6,103,100,104,5", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 38, + "AreaName": "路口中", + "CompatGroup": "EW-N", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "27,101,100,102,28", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 45, + "AreaName": "路口中", + "CompatGroup": "EW-S", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "28,102,100,101,27", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 1, + "AreaName": "西南角", + "CompatGroup": "SW-W", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "2", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 47, + "AreaName": "西南角", + "CompatGroup": "SW-S", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "2", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 8, + "AreaName": "西北角", + "CompatGroup": "NW-W", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "9", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 36, + "AreaName": "西北角", + "CompatGroup": "NW-N", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "9", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 16, + "AreaName": "东南角", + "CompatGroup": "SE-E", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "17", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 43, + "AreaName": "东南角", + "CompatGroup": "SE-S", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "17", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 23, + "AreaName": "东北角", + "CompatGroup": "NE-E", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "24", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + }, + { + "TriggerSit": 30, + "AreaName": "东北角", + "CompatGroup": "NE-N", + "Priority": 10, + "WaitSeconds": 12, + "ControlArea": "24", + "ControlCapacity": 1, + "ControlReleaseStartStop": 11, + "IsUse": true + } +] diff --git a/StandardScene.Signal/Config/Signal/signal-tables.json b/StandardScene.Signal/Config/Signal/signal-tables.json new file mode 100644 index 0000000..0c92692 --- /dev/null +++ b/StandardScene.Signal/Config/Signal/signal-tables.json @@ -0,0 +1,40 @@ +{ + "version": 1, + "tables": [ + { + "id": "stations", + "title": "PLC机构", + "category": "PLC数据管理", + "fileName": "stations.json", + "model": "PlcStationModel" + }, + { + "id": "docks", + "title": "机构工位", + "category": "PLC数据管理", + "fileName": "station-docks.json", + "model": "PlcStationDockModel" + }, + { + "id": "handshake", + "title": "握手点", + "category": "握手点数据管理", + "fileName": "handshake-points.json", + "model": "HandshakePointModel" + }, + { + "id": "release", + "title": "放行点", + "category": "放行点数据管理", + "fileName": "release-points.json", + "model": "ReleasePointModel" + }, + { + "id": "mag-control", + "title": "磁条管控区", + "category": "磁条交管", + "fileName": "mag-control-areas.json", + "model": "MagControlAreaModel" + } + ] +} diff --git a/StandardScene.Signal/Config/Signal/station-docks.json b/StandardScene.Signal/Config/Signal/station-docks.json new file mode 100644 index 0000000..5398a3d --- /dev/null +++ b/StandardScene.Signal/Config/Signal/station-docks.json @@ -0,0 +1,62 @@ +[ + { + "JgName": "上线机构1", + "DockId": "dock1", + "AllowInByte": 0, + "AllowInBit": 0, + "AllowOutByte": 0, + "AllowOutBit": 1, + "EnteringByte": 2, + "EnteringBit": 0, + "ArrivedByte": 2, + "ArrivedBit": 1, + "LeavingByte": 2, + "LeavingBit": 2, + "LeftByte": 2, + "LeftBit": 3, + "JgInPointId": 99, + "JgInContains": "99,100", + "JgPointId": 100, + "JgContains": "100,101" + }, + { + "JgName": "上线机构1", + "DockId": "dock2", + "AllowInByte": 0, + "AllowInBit": 2, + "AllowOutByte": 0, + "AllowOutBit": 3, + "EnteringByte": 2, + "EnteringBit": 4, + "ArrivedByte": 2, + "ArrivedBit": 5, + "LeavingByte": 2, + "LeavingBit": 6, + "LeftByte": 2, + "LeftBit": 7, + "JgInPointId": 109, + "JgInContains": "109,110", + "JgPointId": 110, + "JgContains": "110,111" + }, + { + "JgName": "下线机构1", + "DockId": "dock1", + "AllowInByte": 0, + "AllowInBit": 0, + "AllowOutByte": 0, + "AllowOutBit": 1, + "EnteringByte": 2, + "EnteringBit": 0, + "ArrivedByte": 2, + "ArrivedBit": 1, + "LeavingByte": 2, + "LeavingBit": 2, + "LeftByte": 2, + "LeftBit": 3, + "JgInPointId": 200, + "JgInContains": "200", + "JgPointId": 201, + "JgContains": "201,202" + } +] diff --git a/StandardScene.Signal/Config/Signal/stations.json b/StandardScene.Signal/Config/Signal/stations.json index 004df13..6259680 100644 --- a/StandardScene.Signal/Config/Signal/stations.json +++ b/StandardScene.Signal/Config/Signal/stations.json @@ -3,26 +3,20 @@ "JgName": "上线机构1", "Ip": "192.168.1.10", "Port": 102, - "ReadDb": "DB1.DBB0", - "WriteDb": "DB1.DBB1", - "HeartDb": "DB1.DBX2.0", - "JgInPointId": 99, - "JgInContains": "99,100", - "JgPointId": 100, - "JgContains": "100,101,102", + "PlcType": "S7_1500", + "DbNumber": 100, + "HeartByte": 32, + "HeartBit": 0, "LineType": "上线机构" }, { "JgName": "下线机构1", "Ip": "192.168.1.11", "Port": 102, - "ReadDb": "DB1.DBB0", - "WriteDb": "DB1.DBB1", - "HeartDb": "DB1.DBX2.0", - "JgInPointId": 200, - "JgInContains": "200", - "JgPointId": 201, - "JgContains": "201,202", + "PlcType": "S7_1500", + "DbNumber": 100, + "HeartByte": 32, + "HeartBit": 0, "LineType": "单牵引下线机构" } ] diff --git a/StandardScene.Signal/Logic/CarScanWorker.cs b/StandardScene.Signal/Logic/CarScanWorker.cs index ddb25b0..0501873 100644 --- a/StandardScene.Signal/Logic/CarScanWorker.cs +++ b/StandardScene.Signal/Logic/CarScanWorker.cs @@ -139,13 +139,26 @@ namespace StandardScene.Signal.Logic release = _release; } - PlcStationRuntime Find(string name) + PlcStationRuntime Find(string name, string dockId) { if (string.IsNullOrWhiteSpace(name)) return null; var list = _runtimes() ?? Array.Empty(); - return list.FirstOrDefault(x => - string.Equals(x.Config.JgName, name, StringComparison.OrdinalIgnoreCase)); + var ofStation = list.Where(x => + string.Equals(x.JgName, name, StringComparison.OrdinalIgnoreCase)).ToList(); + if (ofStation.Count == 0) + return null; + if (!string.IsNullOrWhiteSpace(dockId)) + { + var hit = ofStation.FirstOrDefault(x => + string.Equals(x.DockId, dockId.Trim(), StringComparison.OrdinalIgnoreCase)); + if (hit != null) + return hit; + } + + return ofStation.FirstOrDefault(x => + string.Equals(x.DockId, PlcConfigLoader.DefaultDockId, StringComparison.OrdinalIgnoreCase)) + ?? ofStation[0]; } foreach (var car in SignalCarAdapter.All()) @@ -192,7 +205,7 @@ namespace StandardScene.Signal.Logic /// 停稳分发。TimedCharging 优先:充电点不应再走机构逻辑。 /// 未识别的 SignalType 按站点节流打日志,避免刷屏。 /// - private void DispatchStopped(Car car, SignalStopSpec spec, Func find) + private void DispatchStopped(Car car, SignalStopSpec spec, Func find) { if (spec.Is("TimedCharging")) { diff --git a/StandardScene.Signal/Logic/JgControlHandler.cs b/StandardScene.Signal/Logic/JgControlHandler.cs index e9382d4..7e16f94 100644 --- a/StandardScene.Signal/Logic/JgControlHandler.cs +++ b/StandardScene.Signal/Logic/JgControlHandler.cs @@ -30,11 +30,12 @@ namespace StandardScene.Signal.Logic public static class JgControlHandler { /// 停稳:可选限流 → RequestIn 或 Arrived。 - public static void OnStopped(Car car, SignalStopSpec spec, Func find, IDictionary rateFlowLog) + public static void OnStopped(Car car, SignalStopSpec spec, Func find, IDictionary rateFlowLog) { - var jgName = spec.Part(0).Trim(); - var action = spec.Part(1).Trim(); - var rateFlow = spec.Part(2).Trim(); + var jgName = spec.JgName; + var action = spec.Action; + var dockId = spec.DockId; + var rateFlow = spec.ExtraParams; if (string.IsNullOrEmpty(jgName)) { Diagnosis.Log($"AGV{car.id}停在地标{SignalCarAdapter.PositionId(car)},读取配置机构名称为空", "JGControl", true); @@ -48,29 +49,25 @@ namespace StandardScene.Signal.Logic } if (string.Equals(action, "RequestIn", StringComparison.OrdinalIgnoreCase)) - RequestIn(jgName, car, find); + RequestIn(jgName, dockId, car, find); else if (string.Equals(action, "Arrived", StringComparison.OrdinalIgnoreCase)) - Arrived(jgName, car, find); + Arrived(jgName, dockId, car, find); } /// 行驶中只做 RequestIn 安全闸:未允许进入且不是本车占用请求槽则停车。 - public static void OnMoving(Car car, SignalStopSpec spec, Func find) + public static void OnMoving(Car car, SignalStopSpec spec, Func find) { - var jgName = spec.Part(0).Trim(); - var action = spec.Part(1).Trim(); + var jgName = spec.JgName; + var action = spec.Action; if (string.IsNullOrEmpty(jgName)) return; if (string.Equals(action, "RequestIn", StringComparison.OrdinalIgnoreCase)) - RequestInJudge(jgName, car, find); + RequestInJudge(jgName, spec.DockId, car, find); } - /// - /// 请求进入。锁机构运行态,避免与 PLC Worker 同时改写字节 / 车号。 - /// 后半段与 相同,覆盖「刚放行后又被调度层启动」的竞态。 - /// - private static void RequestIn(string jgName, Car car, Func find) + private static void RequestIn(string jgName, string dockId, Car car, Func find) { - var rt = find(jgName); + var rt = find(jgName, dockId); if (rt == null) { Diagnosis.Log($"{jgName} 未能找到机构", "JGControl", true); @@ -83,19 +80,19 @@ namespace StandardScene.Signal.Logic rt.RequestInAgvNo == 0 && rt.ReadWriteSignal == SignalWriteValue.无状态) { - if (rt.Config.LineType is SignalLineType.单牵引下线机构 or SignalLineType.双牵引下线机构) + if (rt.Station.LineType is SignalLineType.单牵引下线机构 or SignalLineType.双牵引下线机构) { - var inside = SignalCarAdapter.CarsAt(rt.Config.JgPointId); + var inside = SignalCarAdapter.CarsAt(rt.Dock.JgPointId); if (inside.Count > 0) { Diagnosis.Log( - $"{jgName} 机构内有AGV【{string.Join(",", inside.Select(x => x.id))}】暂不放行AGV{car.id}", + $"{rt.DisplayName} 机构内有AGV【{string.Join(",", inside.Select(x => x.id))}】暂不放行AGV{car.id}", "JGControl", true); return; } } - Diagnosis.Log($"{jgName} 机构允许进入,通知AGV{car.id}启动,通知机构AGV进入中", "JGControl", true); + Diagnosis.Log($"{rt.DisplayName} 机构允许进入,通知AGV{car.id}启动,通知机构AGV进入中", "JGControl", true); rt.WriteSignal = SignalWriteValue.进入中; rt.RequestInAgvNo = car.id; SignalCarAdapter.StopCharge(car); @@ -108,15 +105,14 @@ namespace StandardScene.Signal.Logic SignalCarAdapter.IsMoving(car)) { SignalCarAdapter.Stop(car); - Diagnosis.Log($"{jgName} 机构不允许进入,监控到AGV启动,暂停AGV{car.id}", "JGControl", true); + Diagnosis.Log($"{rt.DisplayName} 机构不允许进入,监控到AGV启动,暂停AGV{car.id}", "JGControl", true); } } } - /// 行驶中的 RequestIn 安全闸,条件与 RequestIn 后半段一致。 - private static void RequestInJudge(string jgName, Car car, Func find) + private static void RequestInJudge(string jgName, string dockId, Car car, Func find) { - var rt = find(jgName); + var rt = find(jgName, dockId); if (rt == null) { Diagnosis.Log($"{jgName} 未能找到机构", "JGControl", true); @@ -130,17 +126,14 @@ namespace StandardScene.Signal.Logic SignalCarAdapter.IsMoving(car)) { SignalCarAdapter.Stop(car); - Diagnosis.Log($"{jgName} 机构不允许进入,监控到AGV启动,暂停AGV{car.id}", "JGControl", true); + Diagnosis.Log($"{rt.DisplayName} 机构不允许进入,监控到AGV启动,暂停AGV{car.id}", "JGControl", true); } } } - /// - /// 到位。InAgvNo 已是本车则认为已报到,避免每秒重复写「到位」把 WriteSuccess 清掉。 - /// - private static void Arrived(string jgName, Car car, Func find) + private static void Arrived(string jgName, string dockId, Car car, Func find) { - var rt = find(jgName); + var rt = find(jgName, dockId); if (rt == null) { Diagnosis.Log($"{jgName} 未能找到机构", "JGControl", true); @@ -151,7 +144,7 @@ namespace StandardScene.Signal.Logic { if (rt.InAgvNo == car.id) return; - Diagnosis.Log($"AGV{car.id}已到达机构{jgName}", "JGControl", true); + Diagnosis.Log($"AGV{car.id}已到达机构{rt.DisplayName}", "JGControl", true); rt.WriteSignal = SignalWriteValue.到位; rt.InAgvNo = car.id; rt.RequestInAgvNo = 0; diff --git a/StandardScene.Signal/Logic/MagControlAreaGate.cs b/StandardScene.Signal/Logic/MagControlAreaGate.cs new file mode 100644 index 0000000..943374f --- /dev/null +++ b/StandardScene.Signal/Logic/MagControlAreaGate.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using SimpleLite.RCS.CarTypes; + +namespace StandardScene.Signal.Logic +{ + /// + /// 磁条管控区占用判定:他车占用「当前策略」管控站点列表的数量 ≥ 容量则不放行;本车不计入。 + /// 磁条交管进程只对停在触发点的 MagCar 调用,满足后发启动。 + /// + public static class MagControlAreaGate + { + public const byte StartStopPass = 1; + public const byte StartStopControlStart = 11; + + private static readonly char[] SiteIdSeparators = { ',', ';', '|', ' ', '\t', '[', ']', '(', ')', '{', '}' }; + + public static byte NormalizeReleaseStartStop(byte value) + { + if (value == StartStopPass || value == StartStopControlStart) + return value; + return StartStopControlStart; + } + + public static int NormalizeCapacity(int capacity) + { + return capacity < 1 ? 1 : capacity; + } + + public static int[] ParseSiteIds(string text, int fallbackSiteId) + { + var ids = new List(); + if (!string.IsNullOrWhiteSpace(text)) + { + var parts = text.Split(SiteIdSeparators, StringSplitOptions.RemoveEmptyEntries); + foreach (var part in parts) + { + if (int.TryParse(part.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var id) && + id > 0 && !ids.Contains(id)) + { + ids.Add(id); + } + } + } + + if (ids.Count == 0 && fallbackSiteId > 0) + ids.Add(fallbackSiteId); + + return ids.ToArray(); + } + + public static string NormalizeCompatGroup(string value) + { + return (value ?? string.Empty).Trim(); + } + + public static bool SitesIntersect(IReadOnlyList a, IReadOnlyList b) + { + if (a == null || b == null || a.Count == 0 || b.Count == 0) + return false; + for (var i = 0; i < a.Count; i++) + { + var left = a[i]; + if (left <= 0) + continue; + for (var j = 0; j < b.Count; j++) + { + if (b[j] == left) + return true; + } + } + + return false; + } + + public static MagControlReleaseDecision Evaluate( + int selfCarId, + int triggerSit, + IReadOnlyList areaSiteIds, + int capacity, + byte releaseStartStop, + IReadOnlyList<(int CarId, IReadOnlyList OccupiedSiteIds)> occupancies) + { + var sites = areaSiteIds == null || areaSiteIds.Count == 0 + ? (triggerSit > 0 ? new[] { triggerSit } : Array.Empty()) + : areaSiteIds; + capacity = NormalizeCapacity(capacity); + releaseStartStop = NormalizeReleaseStartStop(releaseStartStop); + + var others = 0; + if (occupancies != null) + { + foreach (var occupancy in occupancies) + { + if (occupancy.CarId == selfCarId) + continue; + if (OccupiesListedSites(occupancy.OccupiedSiteIds, sites)) + others++; + } + } + + var canRelease = others < capacity; + var areaId = string.Join(",", sites); + return new MagControlReleaseDecision + { + RuleFound = true, + CanRelease = canRelease, + AreaId = areaId, + Capacity = capacity, + OthersInArea = others, + ReleaseStartStop = releaseStartStop, + Reason = canRelease + ? "area clear" + : $"area occupied cars={others}, capacity={capacity}" + }; + } + + /// 统计占用管控区内部站点的车辆数,可排除排队车和在途车。 + public static int CountOccupyingCars( + IReadOnlyList<(int CarId, IReadOnlyList OccupiedSiteIds)> occupancies, + IReadOnlyList areaSiteIds, + HashSet excludeCarIds) + { + if (occupancies == null || occupancies.Count == 0 || + areaSiteIds == null || areaSiteIds.Count == 0) + return 0; + + var others = 0; + foreach (var occupancy in occupancies) + { + if (excludeCarIds != null && excludeCarIds.Contains(occupancy.CarId)) + continue; + if (OccupiesListedSites(occupancy.OccupiedSiteIds, areaSiteIds)) + others++; + } + + return others; + } + + public static bool OccupiesListedSites(IReadOnlyList occupiedSiteIds, IReadOnlyList areaSiteIds) + { + if (occupiedSiteIds == null || occupiedSiteIds.Count == 0 || + areaSiteIds == null || areaSiteIds.Count == 0) + return false; + + for (var i = 0; i < occupiedSiteIds.Count; i++) + { + var occupied = occupiedSiteIds[i]; + if (occupied <= 0) + continue; + for (var j = 0; j < areaSiteIds.Count; j++) + { + if (areaSiteIds[j] == occupied) + return true; + } + } + + return false; + } + + /// 统计一辆车占用的站点:物理 siteID + holdingLocks。 + public static IReadOnlyList CollectOccupiedSiteIds(Car car) + { + var ids = new List(); + if (car == null) + return ids; + try + { + if (car.siteID > 0) + ids.Add(car.siteID); + } + catch + { + } + + var holding = car.status?.holdingLocks; + if (holding == null) + return ids; + foreach (var lockId in holding) + { + if (lockId > 0 && !ids.Contains(lockId)) + ids.Add(lockId); + } + + return ids; + } + } +} diff --git a/StandardScene.Signal/Logic/MagControlRuntime.cs b/StandardScene.Signal/Logic/MagControlRuntime.cs new file mode 100644 index 0000000..c593db5 --- /dev/null +++ b/StandardScene.Signal/Logic/MagControlRuntime.cs @@ -0,0 +1,479 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SimpleCore.Library; +using SimpleLite.RCS.CarTypes; +using StandardScene.Signal.Model; +using StandardScene.Signal.Plc; + +namespace StandardScene.Signal.Logic +{ + /// + /// 磁条交管运行态:按管控区名称分组排队;放行按「本线 + 冲突对向线」站点并集查当前占用。 + /// 不维护 pending 在途占额。 + /// + public sealed class MagControlRuntime + { + private readonly object _lock = new object(); + private Dictionary _byTrigger = new Dictionary(); + private readonly Dictionary _releaseLog = new Dictionary(); + private readonly Dictionary _arrivals = new Dictionary(); + + public int RuleCount + { + get + { + lock (_lock) + return _byTrigger.Count; + } + } + + /// 已不再使用 pending;保留属性避免旧 UI 绑定报错,恒为 0。 + public int PendingCount => 0; + + public void Replace(IEnumerable rows) + { + var map = (rows ?? Array.Empty()) + .Where(x => x != null && x.TriggerSit > 0 && x.IsUse) + .GroupBy(x => x.TriggerSit) + .ToDictionary(g => g.Key, g => g.First()); + lock (_lock) + { + _byTrigger = map; + _arrivals.Clear(); + } + } + + /// + /// 同名区排队;放行前查本线 + 冲突对向线站点并集上的当前占用。 + /// 另计:已放行仍停在冲突触发点上的运行中车辆(避免 site 未进区时空窗连放)。 + /// + public (int Waiting, int Released) ScanAndRelease() + { + List rules; + lock (_lock) + rules = _byTrigger.Values.ToList(); + + if (rules.Count == 0) + return (0, 0); + + var snapshots = SnapshotCars(); + var occupancies = snapshots + .Select(s => (s.CarId, s.OccupiedSiteIds)) + .ToList(); + + var groups = rules + .GroupBy(AreaKey, StringComparer.OrdinalIgnoreCase) + .Select(g => BuildGroup(g.Key, g.ToList())) + .ToList(); + + lock (_lock) + SweepArrivals(snapshots); + + var waiting = 0; + var released = 0; + foreach (var group in groups) + { + var waiters = CollectWaiters(group, snapshots); + waiting += waiters.Count; + if (waiters.Count == 0) + continue; + + // 停稳排队的车不计入区内占用;本拍已放行的车单独记冲突占额 + var exclude = new HashSet(waiters.Select(w => w.CarId)); + var releasedThisScan = new List(); + + waiters.Sort((a, b) => CompareWaiters(a, b, group.WaitSeconds)); + foreach (var waiter in waiters) + { + var checkSites = BuildConflictSites(group, waiter); + var capacity = MagControlAreaGate.NormalizeCapacity(waiter.Capacity); + var others = CountConflictingOccupancy( + group, waiter, checkSites, occupancies, snapshots, exclude, releasedThisScan); + if (others >= capacity) + continue; + + SignalCarAdapter.StopCharge(waiter.Car); + SignalCarAdapter.StartMagCar(waiter.Car); + released++; + exclude.Add(waiter.CarId); + releasedThisScan.Add(waiter); + NoteRelease(waiter, group, others, capacity, checkSites); + } + } + + return (waiting, released); + } + + /// + /// 冲突占用 = 并集站点上的当前车 + /// + 本区冲突触发点上仍「运行中」的车(刚放行、site 尚未进 ControlArea) + /// + 本拍已放行且与本线冲突的车。 + /// + private static int CountConflictingOccupancy( + AreaGroup group, + Waiter waiter, + IReadOnlyList checkSites, + List<(int CarId, IReadOnlyList OccupiedSiteIds)> occupancies, + List snapshots, + HashSet exclude, + List releasedThisScan) + { + var others = MagControlAreaGate.CountOccupyingCars(occupancies, checkSites, exclude); + var counted = new HashSet(); + + foreach (var snap in snapshots) + { + if (snap == null || exclude.Contains(snap.CarId) || counted.Contains(snap.CarId)) + continue; + if (!snap.IsMagCar) + continue; + + // 已在并集站点上:CountOccupyingCars 已计,这里补「运行中仍在冲突触发点」 + if (snap.IsStopped) + continue; + if (snap.Sit <= 0 || !group.Triggers.Contains(snap.Sit)) + continue; + if (!group.RouteByTrigger.TryGetValue(snap.Sit, out var route)) + continue; + if (!Conflicts(waiter.CompatGroup, waiter.AreaSites, route.CompatGroup, route.AreaSites)) + continue; + + // 若 site 已在 checkSites 里,上面 others 可能已计(触发点一般不在列表) + if (MagControlAreaGate.OccupiesListedSites(snap.OccupiedSiteIds, checkSites)) + continue; + + counted.Add(snap.CarId); + others++; + } + + foreach (var releasedCar in releasedThisScan) + { + if (releasedCar == null || counted.Contains(releasedCar.CarId)) + continue; + if (!Conflicts( + waiter.CompatGroup, waiter.AreaSites, + releasedCar.CompatGroup, releasedCar.AreaSites)) + continue; + counted.Add(releasedCar.CarId); + others++; + } + + return others; + } + + /// 单车判定:本线 + 同名区内冲突对向线站点并集的当前占用。 + public MagControlReleaseDecision Decide(int carId, int triggerSit) + { + MagControlAreaModel rule; + List sameArea; + lock (_lock) + { + if (triggerSit <= 0 || !_byTrigger.TryGetValue(triggerSit, out rule) || rule == null) + { + return new MagControlReleaseDecision + { + RuleFound = false, + Reason = "no mag-control rule" + }; + } + + var key = AreaKey(rule); + sameArea = _byTrigger.Values + .Where(r => string.Equals(AreaKey(r), key, StringComparison.OrdinalIgnoreCase)) + .ToList(); + } + + var group = BuildGroup(AreaKey(rule), sameArea); + if (!group.RouteByTrigger.TryGetValue(triggerSit, out var route)) + { + return new MagControlReleaseDecision + { + RuleFound = false, + Reason = "no mag-control route" + }; + } + + var waiter = new Waiter + { + CarId = carId, + TriggerSit = triggerSit, + CompatGroup = route.CompatGroup, + AreaSites = route.AreaSites, + Capacity = route.Capacity + }; + var checkSites = BuildConflictSites(group, waiter); + var occupancies = new List<(int CarId, IReadOnlyList OccupiedSiteIds)>(); + foreach (var car in SignalCarAdapter.All()) + { + if (car == null) + continue; + occupancies.Add((car.id, MagControlAreaGate.CollectOccupiedSiteIds(car))); + } + + return MagControlAreaGate.Evaluate( + carId, + triggerSit, + checkSites, + rule.ControlCapacity, + rule.ControlReleaseStartStop, + occupancies); + } + + internal static string AreaKey(MagControlAreaModel rule) + { + if (rule == null) + return "#sit:0"; + var name = (rule.AreaName ?? string.Empty).Trim(); + return name.Length > 0 ? name : "#sit:" + rule.TriggerSit; + } + + internal static int CompareWaiters(Waiter a, Waiter b, int waitSeconds) + { + if (waitSeconds > 0) + { + if (a.Priority < b.Priority && + (b.ArrivedAt - a.ArrivedAt).TotalSeconds > waitSeconds) + return -1; + if (b.Priority < a.Priority && + (a.ArrivedAt - b.ArrivedAt).TotalSeconds > waitSeconds) + return 1; + } + + var byPriority = b.Priority.CompareTo(a.Priority); + if (byPriority != 0) + return byPriority; + var byArrival = a.ArrivedAt.CompareTo(b.ArrivedAt); + if (byArrival != 0) + return byArrival; + return a.CarId.CompareTo(b.CarId); + } + + internal static bool Conflicts( + string compatA, + IReadOnlyList sitesA, + string compatB, + IReadOnlyList sitesB) + { + if (string.Equals(compatA ?? "", compatB ?? "", StringComparison.OrdinalIgnoreCase)) + return true; + return MagControlAreaGate.SitesIntersect(sitesA, sitesB); + } + + /// + /// 本线站点 + 同名区内所有与本线冲突的对向/交叉线路站点并集。 + /// 例如西环 NS-W 会并入东/北/南列表,100/101/104 有车时都能挡住触发点 4。 + /// + private static IReadOnlyList BuildConflictSites(AreaGroup group, Waiter waiter) + { + var set = new HashSet(); + if (waiter?.AreaSites != null) + { + foreach (var site in waiter.AreaSites) + { + if (site > 0) + set.Add(site); + } + } + + if (group?.RouteByTrigger == null) + return set.OrderBy(x => x).ToList(); + + foreach (var route in group.RouteByTrigger.Values) + { + if (route?.AreaSites == null) + continue; + if (!Conflicts(waiter.CompatGroup, waiter.AreaSites, route.CompatGroup, route.AreaSites)) + continue; + foreach (var site in route.AreaSites) + { + if (site > 0) + set.Add(site); + } + } + + return set.OrderBy(x => x).ToList(); + } + + private static AreaGroup BuildGroup(string key, List rows) + { + var ordered = rows.OrderBy(r => r.TriggerSit).ToList(); + var triggers = new HashSet(ordered.Select(r => r.TriggerSit)); + var waitSeconds = 0; + var routeByTrigger = new Dictionary(); + foreach (var row in ordered) + { + waitSeconds = Math.Max(waitSeconds, row.WaitSeconds); + var sites = MagControlAreaGate.ParseSiteIds(row.ControlArea, row.TriggerSit); + routeByTrigger[row.TriggerSit] = new RouteInfo + { + CompatGroup = MagControlAreaGate.NormalizeCompatGroup(row.CompatGroup), + Capacity = MagControlAreaGate.NormalizeCapacity(row.ControlCapacity), + AreaSites = sites, + Priority = row.Priority + }; + } + + return new AreaGroup + { + Key = key, + WaitSeconds = waitSeconds, + Triggers = triggers, + RouteByTrigger = routeByTrigger + }; + } + + private List SnapshotCars() + { + var list = new List(); + foreach (var car in SignalCarAdapter.All()) + { + if (car == null) + continue; + list.Add(new CarSnapshot + { + Car = car, + CarId = car.id, + OccupiedSiteIds = MagControlAreaGate.CollectOccupiedSiteIds(car), + IsMagCar = SignalCarAdapter.IsMagCar(car), + IsStopped = SignalCarAdapter.IsStopped(car), + Sit = SignalCarAdapter.PositionId(car) + }); + } + + return list; + } + + private List CollectWaiters(AreaGroup group, List snapshots) + { + var waiters = new List(); + var now = DateTime.Now; + foreach (var snap in snapshots) + { + if (!snap.IsMagCar || !snap.IsStopped) + continue; + if (snap.Sit <= 0 || !group.Triggers.Contains(snap.Sit)) + continue; + + DateTime arrivedAt; + lock (_lock) + { + if (!_arrivals.TryGetValue(snap.CarId, out var arrival) || arrival.TriggerSit != snap.Sit) + { + arrival = new Arrival { TriggerSit = snap.Sit, ArrivedAt = now }; + _arrivals[snap.CarId] = arrival; + } + + arrivedAt = arrival.ArrivedAt; + } + + if (!group.RouteByTrigger.TryGetValue(snap.Sit, out var route)) + continue; + + waiters.Add(new Waiter + { + Car = snap.Car, + CarId = snap.CarId, + TriggerSit = snap.Sit, + AreaKey = group.Key, + CompatGroup = route.CompatGroup, + Capacity = route.Capacity, + AreaSites = route.AreaSites, + Priority = route.Priority, + ArrivedAt = arrivedAt + }); + } + + return waiters; + } + + private void SweepArrivals(List snapshots) + { + var present = new HashSet(); + foreach (var snap in snapshots) + { + if (!snap.IsMagCar || !snap.IsStopped || snap.Sit <= 0) + continue; + if (_arrivals.TryGetValue(snap.CarId, out var arrival) && arrival.TriggerSit == snap.Sit) + present.Add(snap.CarId); + } + + var stale = _arrivals.Keys.Where(id => !present.Contains(id)).ToList(); + foreach (var id in stale) + _arrivals.Remove(id); + } + + private void NoteRelease( + Waiter waiter, + AreaGroup group, + int others, + int capacity, + IReadOnlyList checkSites) + { + var groupName = string.IsNullOrEmpty(waiter.CompatGroup) ? "-" : waiter.CompatGroup; + var carName = waiter.Car?.name; + var namePart = string.IsNullOrWhiteSpace(carName) ? "" : $" name={carName}"; + var sites = waiter.AreaSites == null || waiter.AreaSites.Count == 0 + ? "-" + : string.Join(",", waiter.AreaSites); + var conflict = checkSites == null || checkSites.Count == 0 + ? "-" + : string.Join(",", checkSites); + var message = + $"放行 MagCar={waiter.CarId}{namePart} 区={group.Key} 组={groupName} 触发点={waiter.TriggerSit} " + + $"本线={sites} 冲突并集={conflict} 当前占用={others}/{capacity}"; + + MagTrafficFileLogger.Write(carName, waiter.CarId, message); + + if (_releaseLog.TryGetValue(waiter.CarId, out var last) && (DateTime.Now - last).TotalSeconds < 5) + return; + _releaseLog[waiter.CarId] = DateTime.Now; + Diagnosis.Log($"磁条交管{message}", "MagTraffic", true); + } + + internal sealed class Waiter + { + public Car Car; + public int CarId; + public int TriggerSit; + public string AreaKey; + public string CompatGroup; + public int Capacity; + public IReadOnlyList AreaSites; + public int Priority; + public DateTime ArrivedAt; + } + + private sealed class Arrival + { + public int TriggerSit; + public DateTime ArrivedAt; + } + + private sealed class RouteInfo + { + public string CompatGroup; + public int Capacity; + public IReadOnlyList AreaSites; + public int Priority; + } + + private sealed class AreaGroup + { + public string Key; + public int WaitSeconds; + public HashSet Triggers; + public Dictionary RouteByTrigger; + } + + private sealed class CarSnapshot + { + public Car Car; + public int CarId; + public IReadOnlyList OccupiedSiteIds; + public bool IsMagCar; + public bool IsStopped; + public int Sit; + } + } +} diff --git a/StandardScene.Signal/Logic/MagTrafficFileLogger.cs b/StandardScene.Signal/Logic/MagTrafficFileLogger.cs new file mode 100644 index 0000000..fe58f52 --- /dev/null +++ b/StandardScene.Signal/Logic/MagTrafficFileLogger.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Concurrent; +using System.IO; +using System.Linq; +using System.Text; + +namespace StandardScene.Signal.Logic +{ + /// + /// 磁条交管放行留档,按车名分目录:log/mag-traffic/car{name}/release_yyyyMMdd.log + /// 进程启停等写到 log/mag-traffic/_sys/sys_yyyyMMdd.log + /// + public static class MagTrafficFileLogger + { + private static readonly ConcurrentDictionary CarLocks = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private static readonly object SysLock = new object(); + private static readonly char[] InvalidNameChars = Path.GetInvalidFileNameChars(); + private static string _baseDirectory = "log"; + private static bool _enabled = true; + + public static void Configure(string baseDirectory, bool enabled) + { + _baseDirectory = string.IsNullOrWhiteSpace(baseDirectory) ? "log" : baseDirectory.Trim(); + _enabled = enabled; + } + + public static string GetLogDirectory() + { + return Path.Combine(ResolveBaseDirectory(), "mag-traffic"); + } + + /// 目录名 car{name};名称为空时回退 car{id}。 + public static string GetCarFolderKey(string carName, int carId) + { + var safe = SanitizeName(carName); + if (string.IsNullOrWhiteSpace(safe)) + { + safe = carId > 0 ? carId.ToString() : "unknown"; + } + + return "car" + safe; + } + + public static string GetCarLogDirectory(string carName, int carId = 0) + { + return Path.Combine(GetLogDirectory(), GetCarFolderKey(carName, carId)); + } + + public static string GetCurrentCarLogFilePath(string carName, int carId = 0) + { + return Path.Combine(GetCarLogDirectory(carName, carId), $"release_{DateTime.Now:yyyyMMdd}.log"); + } + + public static string GetCurrentSysLogFilePath() + { + return Path.Combine(GetLogDirectory(), "_sys", $"sys_{DateTime.Now:yyyyMMdd}.log"); + } + + /// 按车名写入放行记录。 + public static void Write(string carName, int carId, string message) + { + if (!_enabled || string.IsNullOrWhiteSpace(message)) + { + return; + } + + var folderKey = GetCarFolderKey(carName, carId); + var carLock = CarLocks.GetOrAdd(folderKey, _ => new object()); + lock (carLock) + { + try + { + var directory = Path.Combine(GetLogDirectory(), folderKey); + Directory.CreateDirectory(directory); + var path = Path.Combine(directory, $"release_{DateTime.Now:yyyyMMdd}.log"); + File.AppendAllText( + path, + $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {message}{Environment.NewLine}", + new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); + } + catch + { + } + } + } + + /// 进程启停、重载配置等非单车事件。 + public static void WriteSystem(string message) + { + if (!_enabled || string.IsNullOrWhiteSpace(message)) + { + return; + } + + lock (SysLock) + { + try + { + var path = GetCurrentSysLogFilePath(); + Directory.CreateDirectory(Path.GetDirectoryName(path) ?? GetLogDirectory()); + File.AppendAllText( + path, + $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {message}{Environment.NewLine}", + new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); + } + catch + { + } + } + } + + private static string SanitizeName(string name) + { + if (string.IsNullOrWhiteSpace(name)) + { + return ""; + } + + var chars = name.Trim().Select(ch => InvalidNameChars.Contains(ch) || ch <= 31 ? '_' : ch).ToArray(); + var safe = new string(chars).Trim('.', ' '); + while (safe.Contains("__")) + { + safe = safe.Replace("__", "_"); + } + + return safe.Length > 80 ? safe.Substring(0, 80) : safe; + } + + private static string ResolveBaseDirectory() + { + return Path.IsPathRooted(_baseDirectory) + ? _baseDirectory + : Path.Combine(AppContext.BaseDirectory, _baseDirectory); + } + } +} diff --git a/StandardScene.Signal/Logic/PointControlHandler.cs b/StandardScene.Signal/Logic/PointControlHandler.cs index 1ff2fb1..bd7cc14 100644 --- a/StandardScene.Signal/Logic/PointControlHandler.cs +++ b/StandardScene.Signal/Logic/PointControlHandler.cs @@ -18,10 +18,10 @@ namespace StandardScene.Signal.Logic public static class PointControlHandler { /// 停稳:先判机构是否允许离开,再下发销钉,全部到位后启动。 - public static void OnStopped(Car car, SignalStopSpec spec, Func find) + public static void OnStopped(Car car, SignalStopSpec spec, Func find) { - var action = spec.Part(0).Trim(); - var jgName = spec.Part(1).Trim(); + var action = spec.Action; + var jgName = spec.JgName; if (string.IsNullOrEmpty(action)) { Diagnosis.Log($"AGV{car.id}停在地标{SignalCarAdapter.PositionId(car)},读取配置特殊点名称为空", "SetPin", true); @@ -31,7 +31,7 @@ namespace StandardScene.Signal.Logic var waitLeave = false; if (!string.IsNullOrEmpty(jgName)) { - var rt = find(jgName); + var rt = find(jgName, spec.DockId); if (rt != null) { lock (rt.Sync) diff --git a/StandardScene.Signal/Logic/SignalStopSpec.cs b/StandardScene.Signal/Logic/SignalStopSpec.cs index 03d0e85..4e55b22 100644 --- a/StandardScene.Signal/Logic/SignalStopSpec.cs +++ b/StandardScene.Signal/Logic/SignalStopSpec.cs @@ -4,30 +4,24 @@ using StandardScene.Signal.Model; namespace StandardScene.Signal.Logic { /// - /// 一条握手点配置的解析结果。参数格式与反编译 SignalStop.SignalParams 一致。 + /// 一条握手点配置的解析结果。新列(机构/工位/动作/附加参数)优先,旧 SignalParams 作回退。 /// - /// - /// 按分号切成 ,缺段时 返回空串。 - /// 各类型约定: - /// - /// JGControl:机构名;RequestIn|Arrived;[区域-车组-限额-点列表] - /// PointControl:UP1|UP2|Down1|Down2;机构名 - /// TimedCharging:最长秒数;上限电量;下限电量 - /// RateFlowControl:区域;车组;限额;点1,点2 - /// - /// public sealed class SignalStopSpec { - /// 握手类型名,与 Handler 的 比较时忽略大小写。 public string SignalType { get; init; } = ""; - /// 原始参数串,限流独立类型会整段交给 public string SignalParams { get; init; } = ""; - /// 按 ';' 切分,保留空段(与 Split None 一致,方便 Part(n) 按下标取)。 public string[] Parts { get; init; } = Array.Empty(); - /// 取第 段;越界或 null 返回空串。 + public string JgName { get; init; } = ""; + + public string DockId { get; init; } = ""; + + public string Action { get; init; } = ""; + + public string ExtraParams { get; init; } = ""; + public string Part(int index) { if (index < 0 || index >= Parts.Length) @@ -35,29 +29,102 @@ namespace StandardScene.Signal.Logic return Parts[index] ?? ""; } - /// 从类型名和参数串构造;类型会 Trim,参数保持原样以便日志对照现场 JSON。 public static SignalStopSpec Parse(string signalType, string signalParams) { var type = (signalType ?? "").Trim(); var raw = signalParams ?? ""; - return new SignalStopSpec + var parsed = new SignalStopSpec { SignalType = type, SignalParams = raw, Parts = raw.Split(new[] { ';' }, StringSplitOptions.None) }; + return EnrichFromParts(parsed); } - /// 从握手点 Model 构造;model 为 null 时返回 null。 public static SignalStopSpec From(HandshakePointModel model) { if (model == null) return null; - return Parse(model.SignalType, model.SignalParams); + + var type = (model.SignalType ?? "").Trim(); + if (string.Equals(type, "TimedCharging", StringComparison.OrdinalIgnoreCase) || + string.Equals(type, "RateFlowControl", StringComparison.OrdinalIgnoreCase)) + { + var raw = First(model.ExtraParams, model.SignalParams); + return Parse(type, raw); + } + + var parsed = Parse(type, model.SignalParams ?? ""); + var jg = First(model.JgName, parsed.JgName); + var action = First(model.Action, parsed.Action); + var dock = First(model.DockId, parsed.DockId); + var extra = First(model.ExtraParams, parsed.ExtraParams); + return new SignalStopSpec + { + SignalType = parsed.SignalType, + SignalParams = parsed.SignalParams, + Parts = parsed.Parts, + JgName = jg, + DockId = dock, + Action = action, + ExtraParams = extra + }; } - /// 类型名是否匹配(忽略大小写)。 public bool Is(string type) => string.Equals(SignalType, type, StringComparison.OrdinalIgnoreCase); + + private static SignalStopSpec EnrichFromParts(SignalStopSpec parsed) + { + var type = parsed.SignalType; + if (string.Equals(type, "TimedCharging", StringComparison.OrdinalIgnoreCase) || + string.Equals(type, "RateFlowControl", StringComparison.OrdinalIgnoreCase)) + { + return new SignalStopSpec + { + SignalType = parsed.SignalType, + SignalParams = parsed.SignalParams, + Parts = parsed.Parts, + ExtraParams = parsed.SignalParams + }; + } + + var point = string.Equals(type, "PointControl", StringComparison.OrdinalIgnoreCase); + var jg = point ? parsed.Part(1).Trim() : parsed.Part(0).Trim(); + var action = point ? parsed.Part(0).Trim() : parsed.Part(1).Trim(); + var dock = ""; + var extra = ""; + var p2 = parsed.Part(2).Trim(); + if (LooksLikeDock(p2)) + dock = p2; + else if (LooksLikeRateFlow(p2)) + extra = p2; + if (string.IsNullOrEmpty(extra)) + extra = parsed.Part(3).Trim(); + return new SignalStopSpec + { + SignalType = parsed.SignalType, + SignalParams = parsed.SignalParams, + Parts = parsed.Parts, + JgName = jg, + DockId = dock, + Action = action, + ExtraParams = extra + }; + } + + private static string First(string a, string b) + { + if (!string.IsNullOrWhiteSpace(a)) + return a.Trim(); + return (b ?? "").Trim(); + } + + private static bool LooksLikeRateFlow(string s) => + !string.IsNullOrEmpty(s) && s.IndexOf('-') >= 0; + + private static bool LooksLikeDock(string s) => + !string.IsNullOrEmpty(s) && s.IndexOf('-') < 0 && s.IndexOf(',') < 0; } } diff --git a/StandardScene.Signal/Mission/MagTrafficMission.cs b/StandardScene.Signal/Mission/MagTrafficMission.cs new file mode 100644 index 0000000..ca1ea86 --- /dev/null +++ b/StandardScene.Signal/Mission/MagTrafficMission.cs @@ -0,0 +1,193 @@ +using System; +using System.IO; +using System.Threading; +using LessokajiWeaverUtilities.Utilities; +using Newtonsoft.Json; +using SimpleCore; +using SimpleCore.Library; +using SimpleLite.RCS; +using StandardScene.Signal.Logic; +using StandardScene.Signal.Model; +using StandardScene.Signal.Ui; +using StandardScene.Utils; + +namespace StandardScene.Signal +{ + /// + /// 磁条交管进程:只针对 MagCar。同区名排队后,按「本线 + 冲突对向线」站点并集查占用,容量允许则发启动。 + /// + /// + /// 配置 Config/Signal/mag-control-areas.json。 + /// 同「管控区名称」绑成一个路口排队;放行时合并本线与冲突对向线的管控站点列表统计当前占用。 + /// 不使用 pending 在途占额。不处理 Mag2Car。 + /// + [MissionType(Name = "磁条交管进程", editor = typeof(MagTrafficMission))] + [I18N.DocumentTranslation(Name = "Magnetic Traffic Mission", locale = "en")] + public class MagTrafficMission : Mission + { + /// 扫车周期(毫秒)。停在触发点的 MagCar 每拍排队判定一次。 + [FieldMember] public int TickMs = 1000; + + /// 管控区表路径。相对路径只解析工作目录 Config/Signal + [FieldMember] public string AreasPath = @"Config\Signal\mag-control-areas.json"; + + /// 放行日志根目录。实际按车名落在其下 mag-traffic/car{name}/release_yyyyMMdd.log。 + [FieldMember] public string LogDirectory = "log"; + + /// 是否把交管放行写入本地文件留档。 + [FieldMember] public bool EnableFileLog = true; + + [JsonIgnore] private bool _started; + [JsonIgnore] private readonly MagControlRuntime _runtime = new MagControlRuntime(); + [JsonIgnore] private CancellationTokenSource _cts; + [JsonIgnore] private Thread _thread; + + public class MagTrafficMissionStatus : MissionStatus + { + public int RuleCount { get; set; } + public int WaitingAtTrigger { get; set; } + public int PendingInFlight { get; set; } + public int ScanTickCount { get; set; } + public string AreasFile { get; set; } + } + + public override MissionStatus status { get; set; } = new MagTrafficMissionStatus(); + + public static Mission Create() => new MagTrafficMission(); + + [MethodMember(Name = "启动进程", Description = "加载管控区表,按区名排队后对 MagCar 发放行")] + public override void Execute() + { + try + { + MagTrafficFileLogger.Configure(LogDirectory, EnableFileLog); + ReloadConfig(); + _started = true; + StartWatch(); + MagTrafficFileLogger.WriteSystem($"进程启动 规则={((MagTrafficMissionStatus)status).RuleCount} 配置={((MagTrafficMissionStatus)status).AreasFile}"); + Diagnosis.Post( + $"磁条交管进程已启动,规则={((MagTrafficMissionStatus)status).RuleCount}(仅 MagCar),放行日志={MagTrafficFileLogger.GetLogDirectory()}", + "MagTraffic", true); + } + catch (Exception ex) + { + status.status = "启动失败"; + Diagnosis.Post($"磁条交管进程启动失败:{ExceptionFormatter.FormatEx(ex)}", "MagTraffic", true); + throw; + } + } + + [MethodMember(Name = "重新加载配置", Description = "重新读取 mag-control-areas.json")] + public void ReloadConfig() + { + var file = SignalConfigStore.Resolve(AreasPath); + var rows = SignalConfigStore.Load(file); + _runtime.Replace(rows); + + var st = (MagTrafficMissionStatus)status; + st.AreasFile = file; + st.RuleCount = _runtime.RuleCount; + st.PendingInFlight = _runtime.PendingCount; + status.status = _started ? "运行中" : "配置已加载"; + MagTrafficFileLogger.Configure(LogDirectory, EnableFileLog); + MagTrafficFileLogger.WriteSystem($"重新加载配置 规则={st.RuleCount} 文件={file}"); + Diagnosis.Post($"磁条交管配置已加载:启用规则 {st.RuleCount} @ {file}", "MagTraffic", true); + } + + [MethodMember(Name = "停止进程")] + public new void Stop() + { + _started = false; + StopWatch(); + status.status = "已停止"; + MagTrafficFileLogger.WriteSystem("进程停止"); + Diagnosis.Post("磁条交管进程已停止", "MagTraffic", true); + } + + [MethodMember(Name = "打开放行日志目录", Description = "打开 mag-traffic 目录(按 car{name} 分子目录),便于按车查阅放行记录")] + public void OpenReleaseLogFolder() + { + try + { + MagTrafficFileLogger.Configure(LogDirectory, EnableFileLog); + var dir = MagTrafficFileLogger.GetLogDirectory(); + Directory.CreateDirectory(dir); + System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo + { + FileName = dir, + UseShellExecute = true + }); + } + catch (Exception ex) + { + CycleUiHelper.Alert("错误", $"打开放行日志目录失败:{ex.Message}"); + } + } + + [MethodMember(Name = "打开管控区列表", Description = "编辑区名 / 兼容组 / 优先级 / 等待时长 / 触发点 / 区内站点 / 容量")] + public void OpenAreas() + { + try + { + var path = SignalConfigStore.Resolve(AreasPath); + ModelListPanel.Open( + "磁条管控区配置", + path, + x => x == null ? "" : x.TriggerSit.ToString()); + } + catch (Exception ex) + { + CycleUiHelper.Alert("错误", $"打开管控区列表失败:{ex.Message}"); + } + } + + private void StartWatch() + { + StopWatch(); + _cts = new CancellationTokenSource(); + _thread = new Thread(WatchLoop) + { + IsBackground = true, + Name = "MagTrafficWatch" + }; + _thread.Start(); + } + + private void StopWatch() + { + try { _cts?.Cancel(); } + catch { } + try { _thread?.Join(2000); } + catch { } + _thread = null; + } + + private void WatchLoop() + { + var token = _cts.Token; + var tick = 0; + var interval = Math.Max(200, TickMs); + while (!token.IsCancellationRequested) + { + try + { + var (waiting, _) = _runtime.ScanAndRelease(); + var st = (MagTrafficMissionStatus)status; + st.WaitingAtTrigger = waiting; + st.PendingInFlight = _runtime.PendingCount; + st.RuleCount = _runtime.RuleCount; + st.ScanTickCount = ++tick; + if (_started) + status.status = $"运行中 规则{st.RuleCount} 等待{waiting}"; + } + catch (Exception ex) + { + Diagnosis.Log($"磁条交管扫车异常:{ex.Message}", "MagTraffic", true); + } + + try { Thread.Sleep(interval); } + catch (ThreadInterruptedException) { break; } + } + } + } +} diff --git a/StandardScene.Signal/Mission/SignalInteractMission.cs b/StandardScene.Signal/Mission/SignalInteractMission.cs index 33db39c..1540e11 100644 --- a/StandardScene.Signal/Mission/SignalInteractMission.cs +++ b/StandardScene.Signal/Mission/SignalInteractMission.cs @@ -16,7 +16,7 @@ using StandardScene.Utils; namespace StandardScene.Signal { /// - /// 第三方信号交互进程(场景 scene.signal 的唯一 Mission)。 + /// 第三方信号交互进程(场景 scene.signal:PLC 握手 / 放行;磁条交管见 MagTrafficMission)。 /// /// /// @@ -65,9 +65,9 @@ namespace StandardScene.Signal /// /// 西门子系列,传给 IoTClient SiemensVersion。 - /// 常用 S7_1500 / S7_1200 / S7_300;连字符会当成下划线解析。 + /// 机构表 PLC类型为「跟随进程」时使用本项;机构单独指定则用机构值。 /// - [FieldMember] public string PlcVersion = "S7_1500"; + [FieldMember] public SignalPlcType PlcVersion = SignalPlcType.S7_1500; /// 机构未单独填 Port 时使用的 S7 端口,默认 102。 [FieldMember] public int PlcPort = 102; @@ -84,6 +84,9 @@ namespace StandardScene.Signal /// 握手点表路径。按站点配置 JGControl / PointControl / TimedCharging / RateFlowControl。 [FieldMember] public string HandshakePointsPath = @"Config\Signal\handshake-points.json"; + /// 机构工位表。相对路径只解析工作目录 Config/Signal。 + [FieldMember] public string DocksPath = @"Config\Signal\station-docks.json"; + /// Execute 成功后为 true;ReloadConfig 仅在已启动时重启 Worker / 扫车。 [JsonIgnore] private bool _started; @@ -126,6 +129,12 @@ namespace StandardScene.Signal /// 实际解析到的握手点文件绝对路径。 public string HandshakePointsFile { get; set; } + /// 实际解析到的工位文件绝对路径。 + public string DocksFile { get; set; } + + /// 工位 JSON 条数。 + public int DockCount { get; set; } + /// 各机构运行态快照,供监视列表展示。 public List Stations { get; set; } = new List(); } @@ -170,23 +179,26 @@ namespace StandardScene.Signal public void ReloadConfig() { var stationsFile = SignalConfigStore.Resolve(StationsPath); + var docksFile = SignalConfigStore.Resolve(DocksPath); var releaseFile = SignalConfigStore.Resolve(ReleasePointsPath); var handshakeFile = SignalConfigStore.Resolve(HandshakePointsPath); - var stations = SignalConfigStore.Load(stationsFile); + var bundles = PlcConfigLoader.Load(stationsFile, docksFile); var points = SignalConfigStore.Load(releaseFile); var handshake = SignalConfigStore.Load(handshakeFile); var st = (SignalInteractMissionStatus)status; - st.StationCount = stations.Count; + st.StationCount = bundles.Count; + st.DockCount = bundles.Sum(b => b.Docks.Count); st.ReleasePointCount = points.Count; st.HandshakePointCount = handshake.Count; st.StationsFile = stationsFile; + st.DocksFile = docksFile; st.ReleasePointsFile = releaseFile; st.HandshakePointsFile = handshakeFile; - st.Stations = stations.Select(s => new PlcStationSnapshot { JgName = s.JgName }).ToList(); + st.Stations = bundles.Select(b => new PlcStationSnapshot { JgName = b.Station.JgName }).ToList(); status.status = _started ? "运行中" : "配置已加载"; Diagnosis.Post( - $"信号配置已加载:机构 {stations.Count};握手点 {handshake.Count} @ {handshakeFile};放行点 {points.Count} @ {releaseFile}", + $"信号配置已加载:机构 {bundles.Count},工位 {st.DockCount} @ {docksFile};握手点 {handshake.Count} @ {handshakeFile};放行点 {points.Count} @ {releaseFile}", "Signal", true); if (_started) @@ -224,6 +236,24 @@ namespace StandardScene.Signal } } + /// CycleGUI 独立窗体编辑工位表;主键为机构名+工位编号。 + [MethodMember(Name = "打开工位列表", Description = "按 PlcStationDockModel 增删改工位点位")] + public void OpenDocks() + { + try + { + var path = SignalConfigStore.Resolve(DocksPath); + ModelListPanel.Open( + "机构工位配置", + path, + x => x == null ? "" : $"{x.JgName}/{x.ResolvedDockId}"); + } + catch (Exception ex) + { + CycleUiHelper.Alert("错误", $"打开工位列表失败:{ex.Message}"); + } + } + /// CycleGUI 独立窗体编辑握手点;主键展示为「站点号 + 信号类型」。 [MethodMember(Name = "打开握手点列表", Description = "按站点配置 JGControl / PointControl / TimedCharging / RateFlowControl")] public void OpenHandshakePoints() @@ -266,7 +296,7 @@ namespace StandardScene.Signal get { lock (_workerLock) - return _workers.Select(w => w.Runtime).ToList(); + return _workers.SelectMany(w => w.Docks).ToList(); } } @@ -285,25 +315,28 @@ namespace StandardScene.Signal /// /// 先停全部旧连接,再按机构表为每个非空名称建 。 - /// 机构 Port<=0 时回退进程级 。 + /// 机构 Port<=0 时回退进程级 ;PLC类型跟随进程时用 。 /// private void RestartWorkers() { StopWorkers(); - var stationsFile = SignalConfigStore.Resolve(StationsPath); - var stations = SignalConfigStore.Load(stationsFile) - .Where(s => !string.IsNullOrWhiteSpace(s.JgName)) - .ToList(); + var bundles = PlcConfigLoader.Load( + SignalConfigStore.Resolve(StationsPath), + SignalConfigStore.Resolve(DocksPath)); var created = new List(); lock (_workerLock) { - foreach (var station in stations) + foreach (var bundle in bundles) { + var station = bundle.Station; var port = station.Port > 0 ? station.Port : PlcPort; - var runtime = new PlcStationRuntime(station); - var session = new SiemensPlcSession(PlcVersion, station.Ip, port, PlcSlot); - var worker = new PlcStationWorker(runtime, session, PlcPollMs, RefreshStatus); + var sync = new object(); + var runtimes = bundle.Docks + .Select(d => new PlcStationRuntime(station, d, sync)) + .ToList(); + var session = new SiemensPlcSession(ResolvePlcType(station), station.Ip, port, PlcSlot); + var worker = new PlcStationWorker(station, runtimes, session, sync, PlcPollMs, RefreshStatus); _workers.Add(worker); created.Add(worker); } @@ -315,6 +348,15 @@ namespace StandardScene.Signal PushStatus(); } + /// 机构选跟随进程(含旧 JSON 缺省 0)时用进程 PlcVersion;进程若也是跟随进程则按 S7_1500。 + private string ResolvePlcType(PlcStationModel station) + { + var type = station.PlcType == SignalPlcType.跟随进程 ? PlcVersion : station.PlcType; + if (type == SignalPlcType.跟随进程) + type = SignalPlcType.S7_1500; + return type.ToString(); + } + /// 清空列表后再 Stop,避免扫车在停连接过程中仍拿到旧 Runtime。 private void StopWorkers() { @@ -345,7 +387,7 @@ namespace StandardScene.Signal { List snaps; lock (_workerLock) - snaps = _workers.Select(w => w.Runtime.ToSnapshot()).ToList(); + snaps = _workers.SelectMany(w => w.Docks.Select(d => d.ToSnapshot())).ToList(); var st = (SignalInteractMissionStatus)status; st.Stations = snaps; diff --git a/StandardScene.Signal/Model/HandshakePointModel.cs b/StandardScene.Signal/Model/HandshakePointModel.cs index 57b3b9e..3228cc0 100644 --- a/StandardScene.Signal/Model/HandshakePointModel.cs +++ b/StandardScene.Signal/Model/HandshakePointModel.cs @@ -1,41 +1,47 @@ using System.ComponentModel; +using Newtonsoft.Json; namespace StandardScene.Signal.Model { /// - /// 握手点配置。对应老地图点上的 SignalStop(SignalType + SignalParams)。 + /// 握手点。JGControl / PointControl 填机构、工位、动作;定时充电 / 限流走附加参数。 + /// 旧 JSON 仅有 SignalParams 时仍可解析。 /// - /// - /// 站点 fields 若已填写同名键,扫车优先用站点字段,本表该站点不再生效。 - /// SignalParams 按分号切分,各类型格式见 。 - /// 列表主键展示为「站点号 + 类型」,同一站点建议只配一条。 - /// + [SignalTable("handshake", "handshake-points.json", "握手点", Order = 3)] [Category("握手点数据管理")] [DisplayName("握手点配置列表")] public class HandshakePointModel { - /// 地图站点号,与车 PositionId(siteID / GetLastSite)对应。 [DisplayName("站点")] public int Sit { get; set; } - /// - /// 握手类型:JGControl 机构进出、 - /// PointControl 销钉升降、 - /// TimedCharging 定时充电、 - /// RateFlowControl 区域限流。 - /// 其它字符串会每 10s 打一次「未找到业务模块」日志。 - /// + /// JGControl / PointControl / TimedCharging / RateFlowControl。 [DisplayName("信号类型")] + [SignalSelect("JGControl", "PointControl", "TimedCharging", "RateFlowControl")] public string SignalType { get; set; } = "JGControl"; + [DisplayName("机构名称")] + public string JgName { get; set; } = ""; + + [DisplayName("工位编号")] + public string DockId { get; set; } = ""; + + /// JGControl:RequestIn / Arrived;PointControl:UP1 / UP2 / Down1 / Down2。 + [DisplayName("动作")] + [SignalSelect("RequestIn", "Arrived", "UP1", "UP2", "Down1", "Down2")] + public string Action { get; set; } = ""; + /// - /// 类型参数。示例: - /// JGControl 上线机构1;RequestIn / 上线机构1;Arrived / 第三段限流 缓存区-A-2-60,61; - /// PointControl UP1;下线机构1; - /// TimedCharging 300;95;20; - /// RateFlowControl 缓存区;A;2;60,61,62。 + /// TimedCharging:最长秒;上限电量;下限电量。 + /// RateFlowControl:区域;车组;限额;点列表。 + /// JGControl 可选限流:区域-车组-限额-点列表。 /// - [DisplayName("信号参数")] - public string SignalParams { get; set; } = ""; + [DisplayName("附加参数")] + public string ExtraParams { get; set; } = ""; + + /// 旧字段。新配置可空,加载时由上面几列拼回。 + [Browsable(false)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public string SignalParams { get; set; } } } diff --git a/StandardScene.Signal/Model/MagControlAreaModel.cs b/StandardScene.Signal/Model/MagControlAreaModel.cs new file mode 100644 index 0000000..85f5ce7 --- /dev/null +++ b/StandardScene.Signal/Model/MagControlAreaModel.cs @@ -0,0 +1,60 @@ +using System.ComponentModel; + +namespace StandardScene.Signal.Model +{ + /// + /// 磁条管控区一行。仅 MagCar:车在触发点停稳等待,进程按区名排队后发启动。 + /// + /// + /// 主键为 。同 的多行绑成一个路口排队。 + /// 区名为空时,该触发点自成一区(兼容旧表)。 + /// 放行时查本行 与同区冲突对向线站点的并集当前占用;不用 pending。 + /// 保留兼容,MagCar 放行走 FASS 1.0 启动指令,不使用该字节。 + /// + [SignalTable("mag-control", "mag-control-areas.json", "磁条管控区", Order = 5)] + [Category("磁条交管")] + [DisplayName("管控区配置列表")] + public class MagControlAreaModel + { + /// 管控触发站点。MagCar 到此停稳后进入该区排队。 + [DisplayName("管控触发站点")] + public int TriggerSit { get; set; } + + /// 管控区名称。同名多行绑成一个路口;空则本触发点单独成区。 + [DisplayName("管控区名称")] + public string AreaName { get; set; } = ""; + + /// + /// 兼容组。同区里互不干扰的线路填不同组名;会打架的填同组。 + /// 空则与同区其他空组互斥。站点列表有交集时即使组名不同也互斥。 + /// + [DisplayName("兼容组")] + public string CompatGroup { get; set; } = ""; + + /// 优先级,数值越大越先放。干道高、支路低。只在冲突线路之间生效。 + [DisplayName("优先级")] + public int Priority { get; set; } + + /// + /// 等待时长(秒)。同区取最长;≤0 不做插队。只在冲突线路之间生效。 + /// + [DisplayName("等待时长")] + public int WaitSeconds { get; set; } + + /// 本线路路口内部站点,如 10,11。不要把排队触发点写进来。空则回退触发点。 + [DisplayName("管控区站点列表")] + public string ControlArea { get; set; } = ""; + + /// 本线路区内最多几辆。含占用本行站点的车和与本行冲突的在途车。默认 1。 + [DisplayName("区内最多几辆")] + public int ControlCapacity { get; set; } = 1; + + /// 兼容字段,MagCar 放行不使用。 + [DisplayName("放行后启停字节")] + public byte ControlReleaseStartStop { get; set; } = 11; + + /// false 时该条保留在 JSON 里但不生效。 + [DisplayName("启用")] + public bool IsUse { get; set; } = true; + } +} diff --git a/StandardScene.Signal/Model/PlcStationDockModel.cs b/StandardScene.Signal/Model/PlcStationDockModel.cs new file mode 100644 index 0000000..516266d --- /dev/null +++ b/StandardScene.Signal/Model/PlcStationDockModel.cs @@ -0,0 +1,106 @@ +using System.ComponentModel; +using Newtonsoft.Json; + +namespace StandardScene.Signal.Model +{ + /// + /// 机构工位:一块 DB 上的一组 BOOL 点 + 地标。同一机构可多行(dock1 / dock2 / …)。 + /// + [SignalTable("docks", "station-docks.json", "机构工位", Order = 2)] + [Category("PLC数据管理")] + [DisplayName("机构工位列表(机构名称+工位编号不能重复)")] + public class PlcStationDockModel + { + /// 外键,对应 + [Category("基本")] + [DisplayName("机构名称")] + public string JgName { get; set; } = ""; + + /// 机构内唯一。空则按 default。 + [Category("基本")] + [DisplayName("工位编号")] + public string DockId { get; set; } = "dock1"; + + [Category("PLC 读 BOOL")] + [DisplayName("允许进入字节")] + public int AllowInByte { get; set; } + + [Category("PLC 读 BOOL")] + [DisplayName("允许进入位")] + public int AllowInBit { get; set; } + + [Category("PLC 读 BOOL")] + [DisplayName("允许离开字节")] + public int AllowOutByte { get; set; } + + [Category("PLC 读 BOOL")] + [DisplayName("允许离开位")] + public int AllowOutBit { get; set; } = 1; + + [Category("PLC 写 BOOL")] + [DisplayName("进入中字节")] + public int EnteringByte { get; set; } = 2; + + [Category("PLC 写 BOOL")] + [DisplayName("进入中位")] + public int EnteringBit { get; set; } + + [Category("PLC 写 BOOL")] + [DisplayName("到位字节")] + public int ArrivedByte { get; set; } = 2; + + [Category("PLC 写 BOOL")] + [DisplayName("到位位")] + public int ArrivedBit { get; set; } = 1; + + [Category("PLC 写 BOOL")] + [DisplayName("离开中字节")] + public int LeavingByte { get; set; } = 2; + + [Category("PLC 写 BOOL")] + [DisplayName("离开中位")] + public int LeavingBit { get; set; } = 2; + + [Category("PLC 写 BOOL")] + [DisplayName("已离开字节")] + public int LeftByte { get; set; } = 2; + + [Category("PLC 写 BOOL")] + [DisplayName("已离开位")] + public int LeftBit { get; set; } = 3; + + [Category("地标")] + [DisplayName("进入地标")] + public int JgInPointId { get; set; } + + [Category("地标")] + [DisplayName("进入包含地标")] + public string JgInContains { get; set; } = ""; + + [Category("地标")] + [DisplayName("机构地标")] + public int JgPointId { get; set; } + + [Category("地标")] + [DisplayName("机构包含地标")] + public string JgContains { get; set; } = ""; + + /// 旧配置合成:按一字节枚举读写,不走 BOOL。 + [Browsable(false)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public bool UseByteIo { get; set; } + + /// 仅 UseByteIo 时使用的读字节地址。 + [Browsable(false)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public string ReadDb { get; set; } + + /// 仅 UseByteIo 时使用的写字节地址。 + [Browsable(false)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public string WriteDb { get; set; } + + public string ResolvedDockId => + string.IsNullOrWhiteSpace(DockId) ? "default" : DockId.Trim(); + } +} diff --git a/StandardScene.Signal/Model/PlcStationModel.cs b/StandardScene.Signal/Model/PlcStationModel.cs index e215aff..6520722 100644 --- a/StandardScene.Signal/Model/PlcStationModel.cs +++ b/StandardScene.Signal/Model/PlcStationModel.cs @@ -1,17 +1,17 @@ using System.ComponentModel; +using Newtonsoft.Json; namespace StandardScene.Signal.Model { /// - /// PLC 机构静态配置,对应反编译 PLCModel 可存档字段。 - /// 读写运行态(当前字节、机构内车号)在 ,不进本类、不进 JSON。 - /// 机构名称不能重复,列表编辑器用 JgName 做主键。 + /// PLC 机构:一把 S7 连接 + 一块 DB。点位和地标在 。 /// + [SignalTable("stations", "stations.json", "PLC机构", Order = 1)] [Category("PLC数据管理")] [DisplayName("PLC配置列表(机构名称不能重复)")] public class PlcStationModel { - /// 逻辑名,握手点 SignalParams 第一段、Worker 线程名都用它。不能空、不能重复。 + /// 逻辑名,握手点机构名、Worker 线程名都用它。不能空、不能重复。 [DisplayName("机构名称")] public string JgName { get; set; } = ""; @@ -23,53 +23,55 @@ namespace StandardScene.Signal.Model [DisplayName("端口")] public int Port { get; set; } = 102; - /// - /// 读字节地址(PLC→调度:允许进入/离开)。 - /// 支持 DB1.DBB0 或 Hsl 风格 DB1.0。空则跳过读取。 - /// - [DisplayName("读地址")] - public string ReadDb { get; set; } = ""; + /// 西门子系列。跟随进程则用信号交互进程的 PlcVersion。 + [DisplayName("PLC类型")] + public SignalPlcType PlcType { get; set; } = SignalPlcType.跟随进程; - /// - /// 写字节地址(调度→PLC:进入中/到位/离开中/已离开)。 - /// Worker 会先回读再按需写入。空则跳过写和回读。 - /// - [DisplayName("写地址")] - public string WriteDb { get; set; } = ""; + /// DB 块号。工位 BOOL 与心跳都拼到这块 DB。 + [DisplayName("DB块号")] + public int DbNumber { get; set; } = 100; - /// - /// 心跳位地址,如 DB1.DBX2.0。 - /// Worker 每拍读当前值再写反码,让 PLC 判断调度进程存活。空则不做心跳。 - /// - [DisplayName("写心跳地址")] - public string HeartDb { get; set; } = ""; + /// 心跳字节偏移。未填 HeartDb 时拼 DB{n}.DBX{HeartByte}.{HeartBit}。 + [DisplayName("心跳字节")] + public int HeartByte { get; set; } = 32; - /// 机构进入地标(预留,与老 PLCModel 字段对齐;上线跟车主要用 JgInContains)。 - [DisplayName("机构进入地标")] - public int JgInPointId { get; set; } - - /// - /// 进入过程包含的站点列表(逗号/分号/空格分隔)。 - /// 上线:写字节=进入中 且车已不在此列表 → 视为到位。 - /// - [DisplayName("机构进入包含地标")] - public string JgInContains { get; set; } = ""; - - /// - /// 机构工作地标。下线 RequestIn 用它查「机构内是否已有车」; - /// 下线/等待通行离站时,车必须停在此点才响应允许离开。 - /// - [DisplayName("机构地标")] - public int JgPointId { get; set; } - - /// - /// 机构占用包含的站点列表。车已不在此列表且写字节还不是已离开 → 写已离开。 - /// - [DisplayName("机构包含地标")] - public string JgContains { get; set; } = ""; + /// 心跳位,0~7。 + [DisplayName("心跳位")] + public int HeartBit { get; set; } /// 上线 / 单牵引下线 / 双牵引下线 / 等待通行,决定 AutoLeave 分支。 [DisplayName("上下机构")] public SignalLineType LineType { get; set; } = SignalLineType.未知; + + /// 旧配置读字节地址。有工位表后不再使用;无工位表时合成 default 工位。 + [Browsable(false)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public string ReadDb { get; set; } + + /// 旧配置写字节地址。 + [Browsable(false)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public string WriteDb { get; set; } + + /// 旧配置心跳位整段地址,优先于心跳字节/位。 + [Browsable(false)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public string HeartDb { get; set; } + + [Browsable(false)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public int JgInPointId { get; set; } + + [Browsable(false)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public string JgInContains { get; set; } + + [Browsable(false)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public int JgPointId { get; set; } + + [Browsable(false)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public string JgContains { get; set; } } } diff --git a/StandardScene.Signal/Model/ReleasePointModel.cs b/StandardScene.Signal/Model/ReleasePointModel.cs index ed36a1d..b86df6b 100644 --- a/StandardScene.Signal/Model/ReleasePointModel.cs +++ b/StandardScene.Signal/Model/ReleasePointModel.cs @@ -10,6 +10,7 @@ namespace StandardScene.Signal.Model /// 同一站点不要同时配握手点:扫车先握手再放行,可能把还在等允许进入的车开走。 /// 站点号不能重复,列表编辑器用 Sit 做主键。 /// + [SignalTable("release", "release-points.json", "放行点", Order = 4)] [Category("放行点数据管理")] [DisplayName("放行点配置列表")] public class ReleasePointModel diff --git a/StandardScene.Signal/Model/SignalEnums.cs b/StandardScene.Signal/Model/SignalEnums.cs index 20bb6a3..cea3474 100644 --- a/StandardScene.Signal/Model/SignalEnums.cs +++ b/StandardScene.Signal/Model/SignalEnums.cs @@ -38,6 +38,34 @@ namespace StandardScene.Signal.Model 已离开 = 4 } + /// + /// 西门子系列,名称与 IoTClient SiemensVersion 对齐(不含 None)。 + /// 机构表选「跟随进程」时用信号交互进程的 PlcVersion。 + /// + public enum SignalPlcType : byte + { + /// 0:未单独指定,建连时用进程字段 PlcVersion。 + 跟随进程 = 0, + + /// S7-1500,现场最常见。 + S7_1500 = 1, + + /// S7-1200。 + S7_1200 = 2, + + /// S7-300。 + S7_300 = 3, + + /// S7-400。 + S7_400 = 4, + + /// S7-200 Smart。 + S7_200Smart = 5, + + /// S7-200。 + S7_200 = 6 + } + /// /// 机构类型。对齐反编译 ENUM_JGTYPE。 /// 决定 走哪套离站,以及 RequestIn 要不要查机构内是否有车。 diff --git a/StandardScene.Signal/Model/SignalSelectAttribute.cs b/StandardScene.Signal/Model/SignalSelectAttribute.cs new file mode 100644 index 0000000..3626111 --- /dev/null +++ b/StandardScene.Signal/Model/SignalSelectAttribute.cs @@ -0,0 +1,18 @@ +using System; + +namespace StandardScene.Signal.Model +{ + /// + /// 迷毂数据中心把该字符串字段渲染成下拉。反射列定义时读取。 + /// + [AttributeUsage(AttributeTargets.Property)] + public sealed class SignalSelectAttribute : Attribute + { + public SignalSelectAttribute(params string[] options) + { + Options = options ?? Array.Empty(); + } + + public string[] Options { get; } + } +} diff --git a/StandardScene.Signal/Model/SignalTableAttribute.cs b/StandardScene.Signal/Model/SignalTableAttribute.cs new file mode 100644 index 0000000..5e94eb4 --- /dev/null +++ b/StandardScene.Signal/Model/SignalTableAttribute.cs @@ -0,0 +1,27 @@ +using System; + +namespace StandardScene.Signal.Model +{ + /// + /// 标记一张迷毂数据中心表。迷毂从插件 DLL 反射本特性,不再依赖 signal-tables.json 的列定义。 + /// + [AttributeUsage(AttributeTargets.Class, Inherited = false)] + public sealed class SignalTableAttribute : Attribute + { + public SignalTableAttribute(string id, string fileName, string title) + { + Id = id ?? ""; + FileName = fileName ?? ""; + Title = title ?? ""; + } + + public string Id { get; } + + public string FileName { get; } + + public string Title { get; } + + /// 侧栏顺序,越小越靠前。 + public int Order { get; set; } + } +} diff --git a/StandardScene.Signal/Plc/PlcAddress.cs b/StandardScene.Signal/Plc/PlcAddress.cs new file mode 100644 index 0000000..64fae20 --- /dev/null +++ b/StandardScene.Signal/Plc/PlcAddress.cs @@ -0,0 +1,63 @@ +using System; +using System.Text.RegularExpressions; + +namespace StandardScene.Signal.Plc +{ + /// 西门子 DB 字节/位地址拼装与缓冲区位操作。 + internal static class PlcAddress + { + private static readonly Regex Addr = new Regex( + @"^DB(\d+)\.(?:DBB|DBX|DBW)?(\d+)(?:\.(\d+))?$", + RegexOptions.IgnoreCase | RegexOptions.Compiled); + + public static string Bit(int db, int absByte, int bit) => + $"DB{Math.Max(1, db)}.DBX{Math.Max(0, absByte)}.{ClampBit(bit)}"; + + public static string Byte(int db, int absByte) => + $"DB{Math.Max(1, db)}.DBB{Math.Max(0, absByte)}"; + + public static int ClampBit(int bit) + { + if (bit < 0) return 0; + if (bit > 7) return 7; + return bit; + } + + public static bool TryParse(string address, out int db, out int absByte, out int bit) + { + db = 0; + absByte = 0; + bit = 0; + if (string.IsNullOrWhiteSpace(address)) + return false; + var m = Addr.Match(address.Trim()); + if (!m.Success) + return false; + db = int.Parse(m.Groups[1].Value); + absByte = int.Parse(m.Groups[2].Value); + if (m.Groups[3].Success) + bit = ClampBit(int.Parse(m.Groups[3].Value)); + return true; + } + + public static bool GetBit(byte[] buffer, int originByte, int absByte, int bit) + { + var i = absByte - originByte; + if (buffer == null || i < 0 || i >= buffer.Length) + return false; + return (buffer[i] & (1 << ClampBit(bit))) != 0; + } + + public static void SetBit(byte[] buffer, int originByte, int absByte, int bit, bool value) + { + var i = absByte - originByte; + if (buffer == null || i < 0 || i >= buffer.Length) + return; + var mask = (byte)(1 << ClampBit(bit)); + if (value) + buffer[i] |= mask; + else + buffer[i] = (byte)(buffer[i] & ~mask); + } + } +} diff --git a/StandardScene.Signal/Plc/PlcConfigLoader.cs b/StandardScene.Signal/Plc/PlcConfigLoader.cs new file mode 100644 index 0000000..3eb9b58 --- /dev/null +++ b/StandardScene.Signal/Plc/PlcConfigLoader.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using StandardScene.Signal.Model; + +namespace StandardScene.Signal.Plc +{ + /// + /// 加载机构 + 工位。没有工位表时,用旧机构行的 ReadDb/WriteDb/地标合成 default 工位(一字节枚举)。 + /// + internal static class PlcConfigLoader + { + public const string DefaultDockId = "default"; + + public sealed class StationBundle + { + public PlcStationModel Station { get; init; } + public List Docks { get; init; } + } + + public static List Load(string stationsPath, string docksPath) + { + var stations = SignalConfigStore.Load(stationsPath) + .Where(s => s != null && !string.IsNullOrWhiteSpace(s.JgName)) + .ToList(); + var docks = SignalConfigStore.Load(docksPath) + .Where(d => d != null && !string.IsNullOrWhiteSpace(d.JgName)) + .ToList(); + + var byName = docks + .GroupBy(d => d.JgName.Trim(), StringComparer.OrdinalIgnoreCase) + .ToDictionary(g => g.Key, g => g.ToList(), StringComparer.OrdinalIgnoreCase); + + var list = new List(); + foreach (var station in stations) + { + if (!byName.TryGetValue(station.JgName.Trim(), out var rows) || rows.Count == 0) + rows = HasLegacyIo(station) ? new List { Synthesize(station) } : new List(); + list.Add(new StationBundle { Station = station, Docks = rows }); + } + + return list; + } + + public static int ResolveDb(PlcStationModel station) + { + if (station == null) + return 100; + if (station.DbNumber > 0) + return station.DbNumber; + if (PlcAddress.TryParse(station.HeartDb, out var db, out _, out _)) + return db; + if (PlcAddress.TryParse(station.ReadDb, out db, out _, out _)) + return db; + if (PlcAddress.TryParse(station.WriteDb, out db, out _, out _)) + return db; + return 100; + } + + public static string ResolveHeartAddress(PlcStationModel station) + { + if (station == null) + return ""; + if (!string.IsNullOrWhiteSpace(station.HeartDb)) + return station.HeartDb.Trim(); + return PlcAddress.Bit(ResolveDb(station), station.HeartByte, station.HeartBit); + } + + private static bool HasLegacyIo(PlcStationModel station) => + station != null && + (!string.IsNullOrWhiteSpace(station.ReadDb) || + !string.IsNullOrWhiteSpace(station.WriteDb) || + station.JgPointId > 0 || + !string.IsNullOrWhiteSpace(station.JgContains)); + + private static PlcStationDockModel Synthesize(PlcStationModel station) => new PlcStationDockModel + { + JgName = station.JgName, + DockId = DefaultDockId, + UseByteIo = true, + ReadDb = station.ReadDb, + WriteDb = station.WriteDb, + JgInPointId = station.JgInPointId, + JgInContains = station.JgInContains, + JgPointId = station.JgPointId, + JgContains = station.JgContains + }; + } +} diff --git a/StandardScene.Signal/Plc/PlcStationLogic.cs b/StandardScene.Signal/Plc/PlcStationLogic.cs index 0b09f86..fc4fb29 100644 --- a/StandardScene.Signal/Plc/PlcStationLogic.cs +++ b/StandardScene.Signal/Plc/PlcStationLogic.cs @@ -48,8 +48,8 @@ namespace StandardScene.Signal.Plc /// 分发四套离站逻辑;未知类型不处理。 public static void AutoLeave(PlcStationRuntime rt) { - if (rt?.Config == null) return; - switch (rt.Config.LineType) + if (rt?.Station == null || rt.Dock == null) return; + switch (rt.Station.LineType) { case SignalLineType.上线机构: AutoLeaveUpLine(rt); @@ -77,12 +77,12 @@ namespace StandardScene.Signal.Plc if (rt.RequestInAgvNo > 0) { Diagnosis.Log( - $"{rt.Config.JgName} {(fromReadback ? "回读已离开" : "写已离开成功")},清空请求进入车 {rt.RequestInAgvNo}", + $"{rt.DisplayName} {(fromReadback ? "回读已离开" : "写已离开成功")},清空请求进入车 {rt.RequestInAgvNo}", "JGControl", true); rt.RequestInAgvNo = 0; } else - Diagnosis.Log($"{rt.Config.JgName} 已离开,清空信号", "JGControl", true); + Diagnosis.Log($"{rt.DisplayName} 已离开,清空信号", "JGControl", true); } /// @@ -102,12 +102,12 @@ namespace StandardScene.Signal.Plc { var car = SignalCarAdapter.Find(rt.RequestInAgvNo); if (car == null) return; - if (!ContainsSite(rt.Config.JgInContains, SignalCarAdapter.PositionId(car))) + if (!ContainsSite(rt.Dock.JgInContains, SignalCarAdapter.PositionId(car))) { rt.WriteSignal = SignalWriteValue.到位; rt.InAgvNo = car.id; rt.RequestInAgvNo = 0; - Diagnosis.Log($"AGV{car.id} 已到达机构 {rt.Config.JgName}", "JGControl", true); + Diagnosis.Log($"AGV{car.id} 已到达机构 {rt.DisplayName}", "JGControl", true); } } else if (rt.WriteSuccess && rt.WriteSignal == SignalWriteValue.到位) @@ -119,7 +119,7 @@ namespace StandardScene.Signal.Plc else if (rt.WriteSuccess && rt.WriteSignal == SignalWriteValue.离开中) { var car = SignalCarAdapter.Find(rt.InAgvNo); - if (car == null || !ContainsSite(rt.Config.JgContains, SignalCarAdapter.PositionId(car))) + if (car == null || !ContainsSite(rt.Dock.JgContains, SignalCarAdapter.PositionId(car))) rt.WriteSignal = SignalWriteValue.已离开; } } @@ -145,7 +145,7 @@ namespace StandardScene.Signal.Plc if (car == null) return; var pos = SignalCarAdapter.PositionId(car); - if (rt.ReadSignal == SignalReadValue.允许离开 && pos == rt.Config.JgPointId) + if (rt.ReadSignal == SignalReadValue.允许离开 && pos == rt.Dock.JgPointId) { if (rt.WriteSignal == SignalWriteValue.离开中) return; var pinOk = SignalCarAdapter.IsActionFinish(car, "SetPin1Up") @@ -156,7 +156,7 @@ namespace StandardScene.Signal.Plc SignalCarAdapter.StopCharge(car); SignalCarAdapter.Start(car); rt.WriteSignal = SignalWriteValue.离开中; - Diagnosis.Log($"{rt.Config.JgName} 允许离开,通知 AGV{car.id} 启动,写离开中", "JGControl", true); + Diagnosis.Log($"{rt.DisplayName} 允许离开,通知 AGV{car.id} 启动,写离开中", "JGControl", true); } else { @@ -165,8 +165,8 @@ namespace StandardScene.Signal.Plc SignalCarAdapter.Control(car, "StopCharge"); } } - else if (!string.IsNullOrEmpty(rt.Config.JgContains) - && !ContainsSite(rt.Config.JgContains, pos) + else if (!string.IsNullOrEmpty(rt.Dock.JgContains) + && !ContainsSite(rt.Dock.JgContains, pos) && rt.ReadWriteSignal != SignalWriteValue.已离开) { rt.WriteSignal = SignalWriteValue.已离开; @@ -193,20 +193,20 @@ namespace StandardScene.Signal.Plc if (car == null) return; var pos = SignalCarAdapter.PositionId(car); - if (rt.ReadSignal == SignalReadValue.允许离开 && pos == rt.Config.JgPointId) + if (rt.ReadSignal == SignalReadValue.允许离开 && pos == rt.Dock.JgPointId) { if (rt.WriteSignal == SignalWriteValue.离开中) return; if (SignalCarAdapter.IsActionFinish(car, "StopCharge")) { SignalCarAdapter.Start(car); rt.WriteSignal = SignalWriteValue.离开中; - Diagnosis.Log($"{rt.Config.JgName} 允许离开,通知 AGV{car.id} 启动,写离开中", "JGControl", true); + Diagnosis.Log($"{rt.DisplayName} 允许离开,通知 AGV{car.id} 启动,写离开中", "JGControl", true); } else SignalCarAdapter.Control(car, "StopCharge"); } - else if (!string.IsNullOrEmpty(rt.Config.JgContains) - && !ContainsSite(rt.Config.JgContains, pos) + else if (!string.IsNullOrEmpty(rt.Dock.JgContains) + && !ContainsSite(rt.Dock.JgContains, pos) && rt.ReadWriteSignal != SignalWriteValue.已离开) { rt.WriteSignal = SignalWriteValue.已离开; diff --git a/StandardScene.Signal/Plc/PlcStationRuntime.cs b/StandardScene.Signal/Plc/PlcStationRuntime.cs index d949260..7278608 100644 --- a/StandardScene.Signal/Plc/PlcStationRuntime.cs +++ b/StandardScene.Signal/Plc/PlcStationRuntime.cs @@ -5,91 +5,88 @@ using StandardScene.Signal.Model; namespace StandardScene.Signal.Plc { /// - /// 单个机构的运行态(不进 JSON)。扫车线程改写目标写字节,PLC Worker 负责真正下发。 + /// 单个工位运行态(不进 JSON)。扫车改写目标写状态,PLC Worker 负责下发 BOOL(或旧一字节枚举)。 /// - /// - /// 赋值 会把 置 false,下一拍 Worker 发现 - /// 目标与回读不一致就会重写 PLC。回读与目标一致后再标成功,AutoLeave 才继续往下一状态走。 - /// 所有读写应在 内进行。 - /// public sealed class PlcStationRuntime { private SignalWriteValue _writeSignal; private SignalReadValue _readSignal; private SignalWriteValue _readWriteSignal; - public PlcStationRuntime(PlcStationModel config) + public PlcStationRuntime(PlcStationModel station, PlcStationDockModel dock, object sync = null) { - Config = config ?? throw new ArgumentNullException(nameof(config)); + Station = station ?? throw new ArgumentNullException(nameof(station)); + Dock = dock ?? throw new ArgumentNullException(nameof(dock)); + Sync = sync ?? new object(); } - /// 本机构静态配置(IP、DB 地址、地标、机构类型)。 - public PlcStationModel Config { get; } + public PlcStationModel Station { get; } - /// 扫车线程与 PLC Worker 共用运行态,写入时加此锁。 - public object Sync { get; } = new object(); + public PlcStationDockModel Dock { get; } + + /// 兼容旧代码:机构连接配置(不含工位地标)。 + public PlcStationModel Config => Station; + + public object Sync { get; } + + public string JgName => Station.JgName ?? ""; + + public string DockId => Dock.ResolvedDockId; + + public string DisplayName => + string.IsNullOrEmpty(DockId) || string.Equals(DockId, PlcConfigLoader.DefaultDockId, StringComparison.OrdinalIgnoreCase) + ? JgName + : $"{JgName}/{DockId}"; - /// PLC→调度:允许进入 / 允许离开 / 无状态。变化时打诊断。 public SignalReadValue ReadSignal { get => _readSignal; set { if (_readSignal != value) - Diagnosis.Log($"{Config.JgName} 读信号 {_readSignal} → {value}", "PLC", true); + Diagnosis.Log($"{DisplayName} 读信号 {_readSignal} → {value}", "PLC", true); _readSignal = value; } } - /// - /// 调度→PLC 的目标写字节。赋值即视为尚未写成功,驱动 Worker 重写。 - /// public SignalWriteValue WriteSignal { get => _writeSignal; set { if (_writeSignal != value) - Diagnosis.Log($"{Config.JgName} 写信号 {_writeSignal} → {value}", "PLC", true); + Diagnosis.Log($"{DisplayName} 写信号 {_writeSignal} → {value}", "PLC", true); _writeSignal = value; WriteSuccess = false; } } - /// 从写地址回读到的当前值,用来确认 PLC 是否已吃进目标字节。 public SignalWriteValue ReadWriteSignal { get => _readWriteSignal; set { if (_readWriteSignal != value) - Diagnosis.Log($"{Config.JgName} 回读写值 {_readWriteSignal} → {value}", "PLC", true); + Diagnosis.Log($"{DisplayName} 回读写值 {_readWriteSignal} → {value}", "PLC", true); _readWriteSignal = value; } } - /// 已报到在机构内的 AGV 号;0 表示没有。Arrived / 上线自动到位 时写入。 public int InAgvNo { get; set; } - /// 已获准进入、正在往机构开的 AGV 号;到位或离站清空后为 0。 public int RequestInAgvNo { get; set; } - /// 最近一拍 PLC 读写是否成功。心跳或读写失败会立刻变 false。 public bool IsConnected { get; set; } - /// 目标写字节是否已与 PLC 回读一致。改 WriteSignal 时自动清掉。 public bool WriteSuccess { get; set; } - /// 内存侧心跳翻转标志,供监视面板看到 Worker 在跑;真正写 PLC 的是 HeartDb 位翻转。 public bool Heart { get; set; } - /// 最近一次断线或周期异常原因,连接正常时清空。 public string LastError { get; set; } = ""; - /// 拷贝一份给 MissionStatus / 监视列表,避免 UI 直接绑运行态。 public PlcStationSnapshot ToSnapshot() => new PlcStationSnapshot { - JgName = Config.JgName, + JgName = DisplayName, IsConnected = IsConnected, ReadSignal = ReadSignal.ToString(), WriteSignal = WriteSignal.ToString(), diff --git a/StandardScene.Signal/Plc/PlcStationWorker.cs b/StandardScene.Signal/Plc/PlcStationWorker.cs index 93566b8..0b43600 100644 --- a/StandardScene.Signal/Plc/PlcStationWorker.cs +++ b/StandardScene.Signal/Plc/PlcStationWorker.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Threading; using SimpleCore.Library; using StandardScene.Signal.Model; @@ -6,41 +8,43 @@ using StandardScene.Signal.Model; namespace StandardScene.Signal.Plc { /// - /// 单机构 200ms 循环:心跳、读允许进出、回读写值、按需写入、自动离站。 - /// 对齐反编译 PLCManager.ExcuteThreadMethod。 + /// 单机构 200ms 循环:心跳、按工位读 BOOL(或旧一字节)、回写变化位、自动离站。 /// - /// - /// 一拍顺序固定,失败则本拍标断线并 return,避免用脏数据推进状态机: - /// 1. 翻转内存心跳标志;若配置了 HeartDb,读当前位再写反码(PLC 侧看翻转判断调度活着)。 - /// 2. 读 ReadDb → 。 - /// 3. 回读 WriteDb → ReadWriteSignal;与目标 WriteSignal 一致则 WriteSuccess=true。 - /// 4. 目标与回读不一致且尚未成功时写入目标字节。 - /// 5. 。 - /// 读写均在 内,与扫车 Handler 互斥。 - /// public sealed class PlcStationWorker : IDisposable { private readonly SiemensPlcSession _session; private readonly int _pollMs; private readonly Action _onTick; + private readonly PlcStationModel _station; + private readonly List _docks; private CancellationTokenSource _cts; private Thread _thread; - - /// 断线日志节流起点,避免 200ms 打满诊断。 private DateTime _lastFailLog = DateTime.MinValue; - public PlcStationWorker(PlcStationRuntime runtime, SiemensPlcSession session, int pollMs, Action onTick = null) + public PlcStationWorker( + PlcStationModel station, + IEnumerable docks, + SiemensPlcSession session, + object sync, + int pollMs, + Action onTick = null) { - Runtime = runtime ?? throw new ArgumentNullException(nameof(runtime)); + _station = station ?? throw new ArgumentNullException(nameof(station)); + _docks = (docks ?? Array.Empty()).Where(d => d != null).ToList(); _session = session ?? throw new ArgumentNullException(nameof(session)); + Sync = sync ?? new object(); _pollMs = Math.Max(50, pollMs); _onTick = onTick; + foreach (var d in _docks) + d.Heart = false; } - /// 本机构运行态,扫车线程按 JgName 查找后加 Sync 读写。 - public PlcStationRuntime Runtime { get; } + public object Sync { get; } + + public IReadOnlyList Docks => _docks; + + public PlcStationRuntime Runtime => _docks.Count > 0 ? _docks[0] : null; - /// 启动后台线程。重复 Start 若仍存活则忽略。 public void Start() { if (_thread != null && _thread.IsAlive) return; @@ -48,13 +52,12 @@ namespace StandardScene.Signal.Plc _thread = new Thread(Loop) { IsBackground = true, - Name = $"PlcStation:{Runtime.Config.JgName}" + Name = $"PlcStation:{_station.JgName}" }; _thread.Start(); - Diagnosis.Log($"{Runtime.Config.JgName} Worker 已启动 → {Runtime.Config.Ip}:{Runtime.Config.Port}", "PLC", true); + Diagnosis.Log($"{_station.JgName} Worker 已启动 → {_station.Ip}:{_station.Port} 工位{_docks.Count}", "PLC", true); } - /// 取消循环、最多等 2s、关闭 S7 连接并标断线。 public void Stop() { try { _cts?.Cancel(); } @@ -63,8 +66,9 @@ namespace StandardScene.Signal.Plc catch { } _thread = null; _session.Close(); - Runtime.IsConnected = false; - Diagnosis.Log($"{Runtime.Config.JgName} Worker 已停止", "PLC", true); + foreach (var d in _docks) + d.IsConnected = false; + Diagnosis.Log($"{_station.JgName} Worker 已停止", "PLC", true); } public void Dispose() => Stop(); @@ -76,14 +80,17 @@ namespace StandardScene.Signal.Plc { try { - lock (Runtime.Sync) + lock (Sync) Tick(); } catch (Exception ex) { - Runtime.LastError = ex.Message; - Runtime.IsConnected = false; - LogFail($"{Runtime.Config.JgName} 周期异常 {ex.Message}"); + foreach (var d in _docks) + { + d.LastError = ex.Message; + d.IsConnected = false; + } + LogFail($"{_station.JgName} 周期异常 {ex.Message}"); } try { _onTick?.Invoke(); } @@ -94,17 +101,18 @@ namespace StandardScene.Signal.Plc } } - /// 单拍 PLC 交互。心跳地址为空则跳过心跳;读写地址为空则跳过对应步骤。 internal void Tick() { - var cfg = Runtime.Config; - Runtime.Heart = !Runtime.Heart; + var heart = !_docks.Select(d => d.Heart).FirstOrDefault(); + foreach (var d in _docks) + d.Heart = heart; - if (!string.IsNullOrWhiteSpace(cfg.HeartDb)) + var heartAddr = PlcConfigLoader.ResolveHeartAddress(_station); + if (!string.IsNullOrWhiteSpace(heartAddr)) { - if (_session.TryReadBool(cfg.HeartDb, out var bit)) + if (_session.TryReadBool(heartAddr, out var bit)) { - _session.TryWriteBool(cfg.HeartDb, !bit); + _session.TryWriteBool(heartAddr, !bit); Thread.Sleep(20); } else @@ -114,56 +122,183 @@ namespace StandardScene.Signal.Plc } } + var boolDocks = _docks.Where(d => !d.Dock.UseByteIo).ToList(); + var byteDocks = _docks.Where(d => d.Dock.UseByteIo).ToList(); + + if (boolDocks.Count > 0 && !TickBoolDocks(boolDocks)) + return; + + foreach (var rt in byteDocks) + { + if (!TickByteDock(rt)) + return; + } + + foreach (var rt in _docks) + { + rt.IsConnected = true; + rt.LastError = ""; + PlcStationLogic.AutoLeave(rt); + } + } + + private bool TickBoolDocks(List docks) + { + var db = PlcConfigLoader.ResolveDb(_station); + var bytes = new List(); + foreach (var rt in docks) + CollectBytes(rt.Dock, bytes); + if (bytes.Count == 0) + return true; + + var origin = bytes.Min(); + var last = bytes.Max(); + var len = (ushort)(last - origin + 1); + if (!_session.TryReadBytes(PlcAddress.Byte(db, origin), len, out var buffer) || + buffer == null || buffer.Length < len) + { + MarkDisconnected("BOOL 块读失败"); + return false; + } + + var changedBytes = new HashSet(); + foreach (var rt in docks) + { + var dock = rt.Dock; + var allowIn = PlcAddress.GetBit(buffer, origin, dock.AllowInByte, dock.AllowInBit); + var allowOut = PlcAddress.GetBit(buffer, origin, dock.AllowOutByte, dock.AllowOutBit); + rt.ReadSignal = allowIn + ? SignalReadValue.允许进入 + : allowOut + ? SignalReadValue.允许离开 + : SignalReadValue.无状态; + + var readWrite = DecodeWrite(buffer, origin, dock); + rt.ReadWriteSignal = readWrite; + if (readWrite == rt.WriteSignal) + rt.WriteSuccess = true; + + if (rt.WriteSignal != readWrite && !rt.WriteSuccess) + { + Diagnosis.Log( + $"AGV→机构 {rt.DisplayName} 写入【{rt.WriteSignal}】请求进入{rt.RequestInAgvNo} 到达{rt.InAgvNo}", + "JGControl", true); + EncodeWrite(buffer, origin, dock, rt.WriteSignal, changedBytes); + } + } + + foreach (var abs in changedBytes) + { + var i = abs - origin; + if (i < 0 || i >= buffer.Length) + continue; + if (!_session.TryWriteByte(PlcAddress.Byte(db, abs), buffer[i])) + { + MarkDisconnected("BOOL 写失败"); + return false; + } + } + + return true; + } + + private bool TickByteDock(PlcStationRuntime rt) + { + var cfg = rt.Dock; if (!string.IsNullOrWhiteSpace(cfg.ReadDb)) { if (_session.TryReadByte(cfg.ReadDb, out var rb)) - Runtime.ReadSignal = PlcStationLogic.ConvertRead(rb); + rt.ReadSignal = PlcStationLogic.ConvertRead(rb); else { - MarkDisconnected("读地址失败"); - return; + MarkDisconnected($"{rt.DisplayName} 读地址失败"); + return false; } } - if (!string.IsNullOrWhiteSpace(cfg.WriteDb)) + if (string.IsNullOrWhiteSpace(cfg.WriteDb)) + return true; + + if (!_session.TryReadByte(cfg.WriteDb, out var wb)) { - if (_session.TryReadByte(cfg.WriteDb, out var wb)) - { - Runtime.ReadWriteSignal = PlcStationLogic.ConvertWrite(wb); - if (Runtime.ReadWriteSignal == Runtime.WriteSignal) - Runtime.WriteSuccess = true; - } - else - { - MarkDisconnected("写地址回读失败"); - return; - } - - if (Runtime.WriteSignal != Runtime.ReadWriteSignal && !Runtime.WriteSuccess) - { - Diagnosis.Log( - $"AGV→机构 {cfg.JgName} 写入【{Runtime.WriteSignal}】请求进入{Runtime.RequestInAgvNo} 到达{Runtime.InAgvNo}", - "JGControl", true); - _session.TryWriteByte(cfg.WriteDb, (byte)Runtime.WriteSignal); - } + MarkDisconnected($"{rt.DisplayName} 写地址回读失败"); + return false; } - Runtime.IsConnected = true; - Runtime.LastError = ""; - PlcStationLogic.AutoLeave(Runtime); + rt.ReadWriteSignal = PlcStationLogic.ConvertWrite(wb); + if (rt.ReadWriteSignal == rt.WriteSignal) + rt.WriteSuccess = true; + + if (rt.WriteSignal != rt.ReadWriteSignal && !rt.WriteSuccess) + { + Diagnosis.Log( + $"AGV→机构 {rt.DisplayName} 写入【{rt.WriteSignal}】请求进入{rt.RequestInAgvNo} 到达{rt.InAgvNo}", + "JGControl", true); + _session.TryWriteByte(cfg.WriteDb, (byte)rt.WriteSignal); + } + + return true; + } + + private static void CollectBytes(PlcStationDockModel dock, List bytes) + { + if (dock == null) return; + bytes.Add(dock.AllowInByte); + bytes.Add(dock.AllowOutByte); + bytes.Add(dock.EnteringByte); + bytes.Add(dock.ArrivedByte); + bytes.Add(dock.LeavingByte); + bytes.Add(dock.LeftByte); + } + + private static SignalWriteValue DecodeWrite(byte[] buffer, int origin, PlcStationDockModel dock) + { + if (PlcAddress.GetBit(buffer, origin, dock.LeftByte, dock.LeftBit)) + return SignalWriteValue.已离开; + if (PlcAddress.GetBit(buffer, origin, dock.LeavingByte, dock.LeavingBit)) + return SignalWriteValue.离开中; + if (PlcAddress.GetBit(buffer, origin, dock.ArrivedByte, dock.ArrivedBit)) + return SignalWriteValue.到位; + if (PlcAddress.GetBit(buffer, origin, dock.EnteringByte, dock.EnteringBit)) + return SignalWriteValue.进入中; + return SignalWriteValue.无状态; + } + + private static void EncodeWrite( + byte[] buffer, + int origin, + PlcStationDockModel dock, + SignalWriteValue value, + HashSet changedBytes) + { + void Set(int abs, int bit, bool on) + { + var before = PlcAddress.GetBit(buffer, origin, abs, bit); + if (before == on) return; + PlcAddress.SetBit(buffer, origin, abs, bit, on); + changedBytes.Add(abs); + } + + Set(dock.EnteringByte, dock.EnteringBit, value == SignalWriteValue.进入中); + Set(dock.ArrivedByte, dock.ArrivedBit, value == SignalWriteValue.到位); + Set(dock.LeavingByte, dock.LeavingBit, value == SignalWriteValue.离开中); + Set(dock.LeftByte, dock.LeftBit, value == SignalWriteValue.已离开); } private void MarkDisconnected(string reason) { - Runtime.IsConnected = false; - Runtime.LastError = reason; - LogFail($"{Runtime.Config.JgName} {reason}"); + foreach (var d in _docks) + { + d.IsConnected = false; + d.LastError = reason; + } + LogFail($"{_station.JgName} {reason}"); } - /// 同一机构失败日志最少间隔 5 秒。 private void LogFail(string msg) { - if ((DateTime.Now - _lastFailLog).TotalSeconds < 5) return; + if ((DateTime.Now - _lastFailLog).TotalSeconds < 5) + return; _lastFailLog = DateTime.Now; Diagnosis.Log(msg, "PLC", true); } diff --git a/StandardScene.Signal/Plc/SiemensPlcSession.cs b/StandardScene.Signal/Plc/SiemensPlcSession.cs index 0063919..8fa591b 100644 --- a/StandardScene.Signal/Plc/SiemensPlcSession.cs +++ b/StandardScene.Signal/Plc/SiemensPlcSession.cs @@ -25,7 +25,7 @@ namespace StandardScene.Signal.Plc private SiemensClient _client; private readonly object _sync = new object(); - /// 进程字段 PlcVersion,如 S7_1500。 + /// 西门子系列名,如 S7_1500;空或无法解析时默认 S7_1500。 /// 机构 IP。 /// S7 端口,通常 102。 /// 机架槽号,S7-1500 常见 1。 @@ -103,6 +103,26 @@ namespace StandardScene.Signal.Plc } } + /// 从起始字节连续读 length 字节,用于工位 BOOL 拆位。 + public bool TryReadBytes(string startAddress, ushort length, out byte[] data) + { + data = Array.Empty(); + if (string.IsNullOrWhiteSpace(startAddress) || length == 0 || !EnsureOpen()) + return false; + try + { + var r = _client.Read(NormalizeByteAddress(startAddress), length, false); + if (r == null || !r.IsSucceed || r.Value == null) + return false; + data = r.Value; + return true; + } + catch + { + return false; + } + } + /// 读心跳位。地址不做 DBB 转换。 public bool TryReadBool(string address, out bool value) { diff --git a/StandardScene.Signal/Plc/SignalCarAdapter.cs b/StandardScene.Signal/Plc/SignalCarAdapter.cs index 8c15b50..f6143d7 100644 --- a/StandardScene.Signal/Plc/SignalCarAdapter.cs +++ b/StandardScene.Signal/Plc/SignalCarAdapter.cs @@ -224,6 +224,13 @@ namespace StandardScene.Signal.Plc return 0; } + /// 类型名恰好为 MagCar(不含 Mag2Car)。磁条交管只放行这种车。 + public static bool IsMagCar(Car car) + { + if (car == null) return false; + return string.Equals(car.GetType().Name, "MagCar", StringComparison.Ordinal); + } + /// 放行:Mag2 → Mag → SendStart(0)。 public static void Start(Car car) { @@ -233,6 +240,15 @@ namespace StandardScene.Signal.Plc TryInvoke(car, "SendStart", new object[] { (ushort)0 }); } + /// 仅 MagCar 发 FASS 1.0 启动(0x01)。不调 StartMag2Car。 + public static void StartMagCar(Car car) + { + if (!IsMagCar(car)) return; + if (TryInvoke(car, "StartMagCar")) + return; + TryInvoke(car, "SendStart", new object[] { (ushort)0 }); + } + /// 急停:Mag2 → Mag → SendStop(0)。机构未允许进入时调用。 public static void Stop(Car car) { diff --git a/StandardScene.Signal/SignalConfigStore.cs b/StandardScene.Signal/SignalConfigStore.cs index a5191cc..ac4ef75 100644 --- a/StandardScene.Signal/SignalConfigStore.cs +++ b/StandardScene.Signal/SignalConfigStore.cs @@ -7,7 +7,7 @@ using Newtonsoft.Json.Converters; namespace StandardScene.Signal { /// - /// 信号插件三张 JSON 的路径解析与读写。 + /// 信号插件 JSON 的路径解析与读写。 /// /// /// 只使用 SimpleLite 工作目录 Config/Signal/*.json,不读、不拷 plugins/Config/Signal。 diff --git a/StandardScene.Signal/StandardScene.Signal.csproj b/StandardScene.Signal/StandardScene.Signal.csproj index db5711c..720eef2 100644 --- a/StandardScene.Signal/StandardScene.Signal.csproj +++ b/StandardScene.Signal/StandardScene.Signal.csproj @@ -26,7 +26,8 @@ - + + diff --git a/StandardScene.Signal/StandardScene.Signal.scene.json b/StandardScene.Signal/StandardScene.Signal.scene.json index 38cb979..f6cd8ad 100644 --- a/StandardScene.Signal/StandardScene.Signal.scene.json +++ b/StandardScene.Signal/StandardScene.Signal.scene.json @@ -5,6 +5,6 @@ "coreVersion": ">=1.0.0", "requiresCore": "StandardScene.dll", "provides": { - "missionTypes": [ "SignalInteractMission" ] + "missionTypes": [ "SignalInteractMission", "MagTrafficMission" ] } } diff --git a/StandardScene.sln b/StandardScene.sln index edbff4b..9db748e 100644 --- a/StandardScene.sln +++ b/StandardScene.sln @@ -19,6 +19,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StandardScene.Magnetic.Test EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StandardScene.Signal", "StandardScene.Signal\StandardScene.Signal.csproj", "{7E5050AA-0009-4A11-9C22-0A0B0C0D0E09}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StandardScene.MagCarSimulator", "StandardScene.MagCarSimulator\StandardScene.MagCarSimulator.csproj", "{7E5050AA-000A-4A11-9C22-0A0B0C0D0E0A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -125,6 +127,18 @@ Global {7E5050AA-0009-4A11-9C22-0A0B0C0D0E09}.Release|x64.Build.0 = Release|Any CPU {7E5050AA-0009-4A11-9C22-0A0B0C0D0E09}.Release|x86.ActiveCfg = Release|Any CPU {7E5050AA-0009-4A11-9C22-0A0B0C0D0E09}.Release|x86.Build.0 = Release|Any CPU + {7E5050AA-000A-4A11-9C22-0A0B0C0D0E0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7E5050AA-000A-4A11-9C22-0A0B0C0D0E0A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7E5050AA-000A-4A11-9C22-0A0B0C0D0E0A}.Debug|x64.ActiveCfg = Debug|Any CPU + {7E5050AA-000A-4A11-9C22-0A0B0C0D0E0A}.Debug|x64.Build.0 = Debug|Any CPU + {7E5050AA-000A-4A11-9C22-0A0B0C0D0E0A}.Debug|x86.ActiveCfg = Debug|Any CPU + {7E5050AA-000A-4A11-9C22-0A0B0C0D0E0A}.Debug|x86.Build.0 = Debug|Any CPU + {7E5050AA-000A-4A11-9C22-0A0B0C0D0E0A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7E5050AA-000A-4A11-9C22-0A0B0C0D0E0A}.Release|Any CPU.Build.0 = Release|Any CPU + {7E5050AA-000A-4A11-9C22-0A0B0C0D0E0A}.Release|x64.ActiveCfg = Release|Any CPU + {7E5050AA-000A-4A11-9C22-0A0B0C0D0E0A}.Release|x64.Build.0 = Release|Any CPU + {7E5050AA-000A-4A11-9C22-0A0B0C0D0E0A}.Release|x86.ActiveCfg = Release|Any CPU + {7E5050AA-000A-4A11-9C22-0A0B0C0D0E0A}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE