diff --git a/BPASmartClient.ScreenLib/BPASmartClient.ScreenLib.csproj b/BPASmartClient.ScreenLib/BPASmartClient.ScreenLib.csproj
index 1a104f1b..c8f6e028 100644
--- a/BPASmartClient.ScreenLib/BPASmartClient.ScreenLib.csproj
+++ b/BPASmartClient.ScreenLib/BPASmartClient.ScreenLib.csproj
@@ -19,7 +19,7 @@
-
+
diff --git a/BPASmartClient.ScreenLib/Helper/Main.cs b/BPASmartClient.ScreenLib/Helper/Main.cs
index 171082cf..033bfe83 100644
--- a/BPASmartClient.ScreenLib/Helper/Main.cs
+++ b/BPASmartClient.ScreenLib/Helper/Main.cs
@@ -1,5 +1,6 @@
using BPA.Communication;
using BPA.Helper;
+using BPA.Message;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
@@ -18,9 +19,9 @@ namespace BPASmartClient.ScreenLib
{
#region 接口继承变量
///
- /// Redis连接信息
+ /// MQTT连接信息
///
- public string RedisConnection { get; set; }
+ public string MQTTConnection { get; set; }
///
/// 业务名称
///
@@ -46,9 +47,13 @@ namespace BPASmartClient.ScreenLib
///
public bool IsRunning { get; set; }
///
- /// Redis是否运行
+ /// Mqtt是否运行
///
- public bool IsRunningReids => RedisHelper.GetInstance.IsConnected();
+ public bool IsRunningMqtt = false;
+ ///
+ /// Mqtt
+ ///
+ public MqttHelper mqttHelper = new MqttHelper();
///
/// 主函数
///
@@ -57,23 +62,23 @@ namespace BPASmartClient.ScreenLib
public Main()
{
ReadPZ();
- if (PZdic.ContainsKey("RedisConnection"))
- RedisConnection = PZdic["RedisConnection"];
+ if (PZdic.ContainsKey("MQTTConnection"))
+ MQTTConnection = PZdic["MQTTConnection"];
if (PZdic.ContainsKey("DeviceMC"))
Name = PZdic["DeviceMC"];
}
///
/// 设备数据
///
- public Dictionary> redisDatasDic = new Dictionary>();
- ///
- /// 告警数据
- ///
- public Dictionary> redisAicDatasDic = new Dictionary>();
+ public Dictionary> mqttDatasDic = new Dictionary>();
///
/// 配置数据
///
public Dictionary PZdic=new Dictionary();
+ ///
+ /// Mqtt消息队列
+ ///
+ public ConcurrentQueue msg = new ConcurrentQueue();
#endregion
#region 线程处理函数
@@ -86,44 +91,17 @@ namespace BPASmartClient.ScreenLib
{
try
{
- if (IsRunning && IsRunningReids)
+ if (IsRunning && IsRunningMqtt)
{
- //1.读取Redis变量
- if (!string.IsNullOrEmpty(Name))
+ if (msg.Count > 0 && msg.TryDequeue(out string s))
{
- redisDatasDic = new Dictionary>();
- redisAicDatasDic = new Dictionary>();
- if (Name.Contains(","))
+ SendScreenDataModel read= JsonConvert.DeserializeObject(s);
+ if (read != null)
{
- Name.Split(',')?.ToList().ForEach(x =>
- {
- Dictionary valuePairs = new Dictionary();
- RedisHelper.GetInstance.Read>($"{x}[Device]").Content?.ToList().ForEach(k => {
- valuePairs[k.VarName] = k;
- });
- redisDatasDic[x]= valuePairs;//设备数据
-
- Dictionary valuePairsAic = new Dictionary();
- RedisHelper.GetInstance.Read>($"{x}[Alarm]").Content?.ToList().ForEach(k => {
- valuePairsAic[k.VarName] = k;
- });
- redisAicDatasDic[x] = valuePairsAic;//告警数据
+ read?.mqttAicDatasDic?.ToList().ForEach(data => {
+ mqttDatasDic[data.Key]= data.Value;
});
}
- else
- {
- Dictionary valuePairs = new Dictionary();
- RedisHelper.GetInstance.Read>($"{Name}[Device]").Content?.ToList().ForEach(k => {
- valuePairs[k.VarName] = k;
- });
- redisDatasDic[Name] = valuePairs;//设备数据
-
- Dictionary valuePairsAic = new Dictionary();
- RedisHelper.GetInstance.Read>($"{Name}[Alarm]").Content?.ToList().ForEach(k => {
- valuePairsAic[k.VarName] = k;
- });
- redisAicDatasDic[Name] = valuePairsAic;//告警数据
- }
}
}
}
@@ -162,6 +140,7 @@ namespace BPASmartClient.ScreenLib
{
//0.设置运行标志
IsRunning = false;
+ mqttHelper.CloseConnect();
}
catch (Exception ex)
{
@@ -177,11 +156,11 @@ namespace BPASmartClient.ScreenLib
{
string msgage = string.Empty;
bool IsTrue = false;
- if (IsRunningReids && IsRunning)
+ if (IsRunningMqtt && IsRunning)
IsTrue = true;
else
{
- if (!IsRunningReids)
+ if (!IsRunningMqtt)
msgage += "Redis断开连接.";
IsTrue = false;
msgage = $"{Name}:健康检查失败,原因:{msgage}";
@@ -208,17 +187,36 @@ namespace BPASmartClient.ScreenLib
{
try
{
- //1.连接Redis,如果已经连接过了 那么自动不会去连接
- if (!string.IsNullOrEmpty(this.RedisConnection) && this.RedisConnection.Contains(','))
+ //2.Mqtt连接
+ if (!string.IsNullOrEmpty(this.MQTTConnection) && this.MQTTConnection.Contains(','))
+ {
+ string[] mqttcom = this.MQTTConnection.Split(',');
+ if (mqttcom != null && mqttcom.Count() == 4)
+ {
+ mqttHelper.Connect(mqttcom[2], mqttcom[3], mqttcom[0], int.Parse(mqttcom[1]), $"{Name}:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
+ }
+ }
+ mqttHelper.Disconnect = new Action(() =>
+ {
+ IsRunningMqtt = false;
+ MessageLog.GetInstance.ShowEx($"{Name}:MQTT异常断开....");
+ });
+ mqttHelper.ConnectOk = new Action(() =>
{
- string[] rediscom = this.RedisConnection.Split(',');
- if (rediscom != null && rediscom.Count() == 4)
- RedisHelper.GetInstance.Connect(new ConfigurationOptions()
+ IsRunningMqtt = true;//连接成功
+ if (Name.Contains(","))
+ {
+ Name.Split(',')?.ToList().ForEach(x =>
{
- ServerAddress = $"{rediscom[0]}:{int.Parse(rediscom[1])}",
- Password = rediscom[2]
+ mqttHelper.Subscrib(x);
});
- }
+ }
+ else
+ {
+ mqttHelper.Subscrib(Name);
+ }
+ });
+ mqttHelper.MessageRecive = new Action((s) => { msg.Enqueue(s); });
}
catch (Exception ex)
{
@@ -228,31 +226,4 @@ namespace BPASmartClient.ScreenLib
}
#endregion
}
-
-
- ///
- /// Redis 数据存储格式
- ///
- public class RedisDataModel
- {
- public string VarName { get; set; }
- public string VarVaule { get; set; }
- public EDataType DataType { get; set; }
- }
-
- ///
- /// 数据类型枚举
- ///
- public enum EDataType
- {
- Bool = 1,
- Byte = 2,
- Int = 3,
- Word = 4,
- Dint = 5,
- Dword = 6,
- Float = 7,
- Double = 8,
- String = 9,
- }
}
diff --git a/BPASmartClient.ScreenLib/分餐机/ScreenSplitMealsControl1.xaml b/BPASmartClient.ScreenLib/分餐机/ScreenSplitMealsControl1.xaml
index 57b7f60c..de972084 100644
--- a/BPASmartClient.ScreenLib/分餐机/ScreenSplitMealsControl1.xaml
+++ b/BPASmartClient.ScreenLib/分餐机/ScreenSplitMealsControl1.xaml
@@ -47,23 +47,12 @@
设备是否运行
-
-
-
-
-
-
- 设备当前状态
+
+
+ 今日刷卡数
-
+
@@ -71,25 +60,23 @@
-
- 今日刷卡数
+
+ 前一位刷卡人
-
- 异常刷卡数
+
+ 当前刷卡人
-
-
+
-
-
+
@@ -105,13 +92,8 @@
-
-
-
-
-
-
+
@@ -165,23 +147,12 @@
设备是否运行
-
-
-
-
-
-
- 设备当前状态
+
+
+ 今日刷卡数
-
+
@@ -189,25 +160,22 @@
-
- 今日刷卡数
+
+ 前一位刷卡人
-
- 异常刷卡数
+
+ 当前刷卡人
-
-
-
-
+
diff --git a/BPASmartClient.ScreenLib/炒锅/ScreenMaxWokControl.xaml b/BPASmartClient.ScreenLib/炒锅/ScreenMaxWokControl.xaml
index f5c5f605..c6d22b3f 100644
--- a/BPASmartClient.ScreenLib/炒锅/ScreenMaxWokControl.xaml
+++ b/BPASmartClient.ScreenLib/炒锅/ScreenMaxWokControl.xaml
@@ -63,111 +63,122 @@
设备当前状态
-
+
+ 炒制作中
+
+
+
+
+
+
+
+
+
-
- 今日订单数
+
+
+
+
+
+ 炒锅加热挡位
-
- 异常订单数
+
+
+
+
+
+ 炒锅搅拌挡位
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 炒锅翻转速度
+
+
+
+
+
+
+
+ 当前锅底温度
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
@@ -175,74 +186,11 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -280,117 +228,93 @@
设备当前状态
-
+
+ 炒制作中
+
+
+
+
+
+
+
+
+
-
- 今日订单数
+
+
+
+
+
+ 炒锅加热挡位
-
- 异常订单数
+
+
+
+
+
+ 炒锅搅拌挡位
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 炒锅翻转速度
+
+
+
+
+
+
+
+ 当前锅底温度
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/BPASmartClient.ScreenLib/炒锅/ScreenMinWokControl.xaml b/BPASmartClient.ScreenLib/炒锅/ScreenMinWokControl.xaml
index b533a084..6713b78f 100644
--- a/BPASmartClient.ScreenLib/炒锅/ScreenMinWokControl.xaml
+++ b/BPASmartClient.ScreenLib/炒锅/ScreenMinWokControl.xaml
@@ -25,7 +25,45 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 设备当前状态
+
+
+
+
+ 今日订单数
+
+
+
+
+ 炒制作中
+
+
+
+
+
+
+
+
@@ -45,7 +83,7 @@
- 设备是否运行
+ 炒锅加热挡位
@@ -60,120 +98,48 @@
- 设备当前状态
+ 炒锅搅拌挡位
-
-
+
-
- 今日订单数
+
+
+
+
+
+ 炒锅翻转速度
-
- 异常订单数
+
+
+
+
+
+ 当前锅底温度
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -184,33 +150,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -223,7 +163,7 @@
-
+
@@ -242,7 +182,45 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 设备当前状态
+
+
+
+
+ 今日订单数
+
+
+
+
+ 炒制作中
+
+
+
+
+
+
+
+
@@ -262,7 +240,7 @@
- 设备是否运行
+ 炒锅加热挡位
@@ -277,120 +255,48 @@
- 设备当前状态
+ 炒锅搅拌挡位
-
-
+
-
- 今日订单数
+
+
+
+
+
+ 炒锅翻转速度
-
- 异常订单数
+
+
+
+
+
+ 当前锅底温度
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/BPASmartClient.ScreenLib/煮面机/ScreenMorksControl.xaml b/BPASmartClient.ScreenLib/煮面机/ScreenMorksControl.xaml
index 1ed5f368..566f2349 100644
--- a/BPASmartClient.ScreenLib/煮面机/ScreenMorksControl.xaml
+++ b/BPASmartClient.ScreenLib/煮面机/ScreenMorksControl.xaml
@@ -118,13 +118,8 @@
-
-
-
-
-
-
+
@@ -137,7 +132,7 @@
-
+
@@ -167,55 +162,201 @@
- 异常订单数
+ 机器人当前状态
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 煮面炉1号
+
+
+
+
+
+
+
+ 煮面炉2号
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 煮面炉1号
+
+
+
+
+
+
+
+ 煮面炉2号
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 煮面炉5号
+
+
+
+
+
+
+
+ 煮面炉6号
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 温度状态
+
+
+
+
+
+
+
+ 料仓位置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 料仓上下物料检测
+
+
+
+
+
+
+
+ 落碗机构缺碗检测
+
+
+
+
diff --git a/BPASmartClient.ScreenLib/煮面机/ScreenMorksControlViewModel.cs b/BPASmartClient.ScreenLib/煮面机/ScreenMorksControlViewModel.cs
index a6af7f0b..4c151d0f 100644
--- a/BPASmartClient.ScreenLib/煮面机/ScreenMorksControlViewModel.cs
+++ b/BPASmartClient.ScreenLib/煮面机/ScreenMorksControlViewModel.cs
@@ -187,9 +187,6 @@ namespace BPASmartClient.ScreenLib
}));
Thread.Sleep(5000);
}), $"{DateTime.Now},线程服务");
-
-
-
}
///
@@ -199,113 +196,116 @@ namespace BPASmartClient.ScreenLib
{
string Dev = "MorkS";//当前设备名称
string name = Main.GetInstance.PZdic.ContainsKey($"{Dev}_Name") ? Main.GetInstance.PZdic[$"{Dev}_Name"].ToString(): DateTime.Now.ToString();
- ThreadManage.GetInstance().StartLong(new Action(() =>
- {
- System.Windows.Application.Current?.Dispatcher.Invoke((Action)(() =>
- {
- if (!string.IsNullOrEmpty(name) && Main.GetInstance.redisDatasDic != null && Main.GetInstance.redisDatasDic.ContainsKey(name) && Main.GetInstance.redisDatasDic[name]!=null)
- {
- List list=new List { "IsRun", "RunStatus", "OrderCount", "ErrorOrderCount", "OrderMakeList", "OrderMakeListOver", "AlarmList" };
- list?.ForEach(x => {
- if (Main.GetInstance.PZdic.ContainsKey($"{Dev}_{x}"))
- {
- if (Main.GetInstance.redisDatasDic[name].ContainsKey(Main.GetInstance.PZdic[$"{Dev}_{x}"]))
- {
- string _value = Main.GetInstance.redisDatasDic[name][Main.GetInstance.PZdic[$"{Dev}_{x}"]].VarVaule;
- #region 执行更新界面数据
- switch (x)
- {
- case "IsRun"://是否运行
- DevIsRun = _value == "0" ? DevIsRun.停止 : DevIsRun.运行;
- break;
- case "RunStatus"://运行状态
- DevIsRun = _value == "0" ? DevIsRun.停止 : DevIsRun.运行;
- break;
- case "OrderCount"://是否运行
- try
- {
- DdCount = int.Parse(_value);
- }
- catch (Exception ex)
- {
- DdCount = 0;
- }
- break;
- case "ErrorOrderCount":
- try
- {
- YCDdCount = int.Parse(_value);
- }
- catch (Exception ex)
- {
- YCDdCount = 0;
- }
- break;
- case "OrderMakeList":
- try
- {
- OrderMakeList = new ObservableCollection();
- JsonConvert.DeserializeObject>(_value)?.OrderBy(l => l.SortNum)?.ToList().ForEach(par => {
- OrderMakeList.Add(par);
- });
- }
- catch (Exception ex)
- {
- OrderMakeList = new ObservableCollection();
- }
- break;
- case "OrderMakeListOver":
- try
- {
- OrderMakeListOver = new ObservableCollection();
- JsonConvert.DeserializeObject>(_value)?.OrderBy(l => l.SortNum)?.ToList().ForEach(par => {
- OrderMakeListOver.Add(par);
- });
- }
- catch (Exception ex)
- {
- OrderMakeListOver = new ObservableCollection();
- }
- break;
- case "AlarmList":
- try
- {
- AlarmList = new ObservableCollection();
- JsonConvert.DeserializeObject>(_value)?.OrderBy(l => l.AlarmTime)?.ToList().ForEach(par => {
- AlarmList.Add(par);
- });
+ //ThreadManage.GetInstance().StartLong(new Action(() =>
+ //{
+ // System.Windows.Application.Current?.Dispatcher.Invoke((Action)(() =>
+ // {
+ // if (!string.IsNullOrEmpty(name) && Main.GetInstance.redisDatasDic != null && Main.GetInstance.redisDatasDic.ContainsKey(name) && Main.GetInstance.redisDatasDic[name]!=null)
+ // {
+ // List list=new List { "IsRun", "RunStatus", "OrderCount", "ErrorOrderCount", "OrderMakeList", "OrderMakeListOver", "AlarmList" };
+ // list?.ForEach(x => {
+ // if (Main.GetInstance.PZdic.ContainsKey($"{Dev}_{x}"))
+ // {
+ // if (Main.GetInstance.redisDatasDic[name].ContainsKey(Main.GetInstance.PZdic[$"{Dev}_{x}"]))
+ // {
+ // string _value = Main.GetInstance.redisDatasDic[name][Main.GetInstance.PZdic[$"{Dev}_{x}"]].VarVaule;
+ // #region 执行更新界面数据
+ // switch (x)
+ // {
+ // case "IsRun"://是否运行
+ // DevIsRun = _value == "0" ? DevIsRun.停止 : DevIsRun.运行;
+ // break;
+ // case "RunStatus"://运行状态
+ // DevIsRun = _value == "0" ? DevIsRun.停止 : DevIsRun.运行;
+ // break;
+ // case "OrderCount"://是否运行
+ // try
+ // {
+ // DdCount = int.Parse(_value);
+ // }
+ // catch (Exception ex)
+ // {
+ // DdCount = 0;
+ // }
+ // break;
+ // case "ErrorOrderCount":
+ // try
+ // {
+ // YCDdCount = int.Parse(_value);
+ // }
+ // catch (Exception ex)
+ // {
+ // YCDdCount = 0;
+ // }
+ // break;
+ // case "OrderMakeList":
+ // try
+ // {
+ // OrderMakeList = new ObservableCollection();
+ // JsonConvert.DeserializeObject>(_value)?.OrderBy(l => l.SortNum)?.ToList().ForEach(par => {
+ // OrderMakeList.Add(par);
+ // });
+ // }
+ // catch (Exception ex)
+ // {
+ // OrderMakeList = new ObservableCollection();
+ // }
+ // break;
+ // case "OrderMakeListOver":
+ // try
+ // {
+ // OrderMakeListOver = new ObservableCollection();
+ // JsonConvert.DeserializeObject>(_value)?.OrderBy(l => l.SortNum)?.ToList().ForEach(par => {
+ // OrderMakeListOver.Add(par);
+ // });
+ // //OrderMakeListOver?.ToList().FindAll(m => m.GoodName).di
+ // }
+ // catch (Exception ex)
+ // {
+ // OrderMakeListOver = new ObservableCollection();
+ // }
+ // break;
+ // case "AlarmList":
+ // try
+ // {
+ // AlarmList = new ObservableCollection();
+ // JsonConvert.DeserializeObject>(_value)?.OrderBy(l => l.AlarmTime)?.ToList().ForEach(par => {
+ // AlarmList.Add(par);
+ // });
+
- //Histogram=new
- //if (AlarmList.Count > 0)
- //{
-
- //}
- }
- catch (Exception ex)
- {
- OrderMakeListOver = new ObservableCollection();
- }
- break;
- default:
- break;
- }
- #endregion
+
+ // //Histogram=new
+ // //if (AlarmList.Count > 0)
+ // //{
- }
- }
+ // //}
+ // }
+ // catch (Exception ex)
+ // {
+ // OrderMakeListOver = new ObservableCollection();
+ // }
+ // break;
+ // default:
+ // break;
+ // }
+ // #endregion
- });
- }
+ // }
+ // }
+
+ // });
+ // }
- //Histogram = new[] {
- // new KeyValuePair(name_s[0], new Random().Next(0,400)),
- // new KeyValuePair(name_s[1], new Random().Next(0,400)),
- // new KeyValuePair(name_s[2], new Random().Next(0,400)),
- // new KeyValuePair(name_s[3], new Random().Next(0,400)),
- // new KeyValuePair(name_s[4], new Random().Next(0,400))};
- }));
- Thread.Sleep(500);
- }), $"{name},线程服务");
+ // //Histogram = new[] {
+ // // new KeyValuePair(name_s[0], new Random().Next(0,400)),
+ // // new KeyValuePair(name_s[1], new Random().Next(0,400)),
+ // // new KeyValuePair(name_s[2], new Random().Next(0,400)),
+ // // new KeyValuePair(name_s[3], new Random().Next(0,400)),
+ // // new KeyValuePair(name_s[4], new Random().Next(0,400))};
+ // }));
+ // Thread.Sleep(500);
+ //}), $"{name},线程服务");
}
}
}
diff --git a/BPASmartClient.ScreenMaxWok/App.config b/BPASmartClient.ScreenMaxWok/App.config
index 8d057181..7eeaad9e 100644
--- a/BPASmartClient.ScreenMaxWok/App.config
+++ b/BPASmartClient.ScreenMaxWok/App.config
@@ -1,188 +1,10 @@
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file