From 528c105b3aea0e6e00477365f16f57c1e3d7eb1c Mon Sep 17 00:00:00 2001
From: WJC <wjc@hdlchina.com.cn>
Date: 星期四, 24 十月 2019 15:31:28 +0800
Subject: [PATCH] 2019-10-24-3

---
 ZigbeeApp/Shared/Phone/UserCenter/Device/DeviceListMainForm.cs |  298 ++++++++++++++++++++++++++++++-----------------------------
 1 files changed, 153 insertions(+), 145 deletions(-)

diff --git a/ZigbeeApp/Shared/Phone/UserCenter/Device/DeviceListMainForm.cs b/ZigbeeApp/Shared/Phone/UserCenter/Device/DeviceListMainForm.cs
old mode 100755
new mode 100644
index facfeba..7e67cc1
--- a/ZigbeeApp/Shared/Phone/UserCenter/Device/DeviceListMainForm.cs
+++ b/ZigbeeApp/Shared/Phone/UserCenter/Device/DeviceListMainForm.cs
@@ -16,13 +16,13 @@
         /// 缃戝叧鎺т欢
         /// </summary>
         private MyGatewayControl gatewayViewRow = null;
-        /// <summary>
-        /// 鍒楄〃鎺т欢
-        /// </summary>
-        private VerticalListControl listView = null;
+        /// <summary>
+        /// 鍒楄〃鎺т欢
+        /// </summary>
+        private VerticalScrolViewLayout listView = null;
         /// <summary>
         /// 琛屾帶浠剁殑淇℃伅(Keys锛歁ac鍦板潃)
-        /// </summary>
+        /// </summary>
         private Dictionary<string, DeviceObjRowInfo> dicRowInfo = new Dictionary<string, DeviceObjRowInfo>();
         /// <summary>
         /// 閲嶆柊鑾峰彇璁惧鐨勫湪绾跨姸鎬�
@@ -37,22 +37,22 @@
 
         #region 鈻� 鍒濆鍖朹____________________________
 
-        /// <summary>
-        /// 鐢婚潰鏄剧ず(搴曞眰浼氬浐瀹氳皟鐢ㄦ鏂规硶锛屽�熶互瀹屾垚鐢婚潰鍒涘缓)
-        /// </summary>
-        public void ShowForm()
-        {
-            //璁剧疆鏍囬淇℃伅
-            base.SetTitleText(Language.StringByID(R.MyInternationalizationString.DeviceManagement));
-
-            //鍙充笂娣诲姞鎸夐挳
+        /// <summary>
+        /// 鐢婚潰鏄剧ず(搴曞眰浼氬浐瀹氳皟鐢ㄦ鏂规硶锛屽�熶互瀹屾垚鐢婚潰鍒涘缓)
+        /// </summary>
+        public void ShowForm()
+        {
+            //璁剧疆鏍囬淇℃伅
+            base.SetTitleText(Language.StringByID(R.MyInternationalizationString.DeviceManagement));
+
+            //鍙充笂娣诲姞鎸夐挳
             var btnAddDeviceIcon = new MostRightIconControl(69, 69);
-            btnAddDeviceIcon.UnSelectedImagePath = "Item/Add.png";
-            topFrameLayout.AddChidren(btnAddDeviceIcon);
-            btnAddDeviceIcon.InitControl();
-            btnAddDeviceIcon.ButtonClickEvent += (sender, e) =>
-            {
-                ZbGateway realWay = null;
+            btnAddDeviceIcon.UnSelectedImagePath = "Item/Add.png";
+            topFrameLayout.AddChidren(btnAddDeviceIcon);
+            btnAddDeviceIcon.InitControl();
+            btnAddDeviceIcon.ButtonClickEvent += (sender, e) =>
+            {
+                ZbGateway realWay = null;
                 if (GatewayResourse.NowSelectGateway == null || HdlGatewayLogic.Current.GetRealGateway(ref realWay, GatewayResourse.NowSelectGateway) == false)
                 {
                     //缃戝叧瀵硅薄寮傚父,璇烽噸鏂伴�夋嫨缃戝叧
@@ -63,26 +63,26 @@
                         form2.AddForm();
                     });
                     return;
-                }
-                GatewayResourse.NowSelectGateway = realWay;
-
-                var form = new DeviceDirection.AddDeviceTypeListForm();
-                form.AddForm();
-            };
-
-            //鍒濆鍖栦腑閮ㄦ帶浠�
-            this.InitMiddleFrame();
-        }
-
+                }
+                GatewayResourse.NowSelectGateway = realWay;
+
+                var form = new DeviceDirection.AddDeviceTypeListForm();
+                form.AddForm();
+            };
+
+            //鍒濆鍖栦腑閮ㄦ帶浠�
+            this.InitMiddleFrame();
+        }
+
         /// <summary>
         /// 鍒濆鍖栦腑閮ㄦ帶浠�(澶栭儴鍙互璋冪敤)
         /// </summary>
-        /// <param name="i_reGetDeviceOnlineStatu">閲嶆柊鑾峰彇璁惧鐨勫湪绾跨姸鎬�</param>
-        public void InitMiddleFrame(bool i_reGetDeviceOnlineStatu = true)
+        /// <param name="i_reGetDeviceOnlineStatu">閲嶆柊鑾峰彇璁惧鐨勫湪绾跨姸鎬�</param>
+        public void InitMiddleFrame(bool i_reGetDeviceOnlineStatu = true)
         {
             this.reGetDeviceOnlineStatu = i_reGetDeviceOnlineStatu;
             //娓呯┖bodyFrame
-            this.ClearBodyFrame();
+            this.ClearBodyFrame();
 
             //鍒濆鍖栫綉鍏宠鎺т欢
             GatewayResourse.NowSelectGateway = HdlGatewayLogic.Current.GetLocalGateway(GatewayResourse.AppOldSelectGatewayId);
@@ -95,13 +95,12 @@
             //鍒濆鍖栨悳绱㈡帶浠�
             this.InitSearchControl();
 
-            new System.Threading.Thread(() =>
+            HdlThreadLogic.Current.RunThread(() =>
             {
                 //鍒濆鍖栬澶囧垪琛ㄦ帶浠�
                 this.InitDeviceListControl();
-            })
-            { IsBackground = true }.Start();
-        }
+            });
+        }
 
         #endregion
 
@@ -128,7 +127,7 @@
             txtSearchControl.BindEvent(this.SetRowDataBySearchKeys);
 
             //鍒楄〃鎺т欢
-            listView = new VerticalListControl(29);
+            listView = new VerticalScrolViewLayout();
             listView.Y = txtSearchControl.Bottom + Application.GetRealHeight(29);
             listView.Height = frame.Height - txtSearchControl.Bottom - Application.GetRealHeight(29);
             frame.AddChidren(listView);
@@ -140,8 +139,8 @@
 
         /// <summary>
         /// 鍒濆鍖栬澶囧垪琛ㄦ帶浠�
-        /// </summary>
-        private void InitDeviceListControl()
+        /// </summary>
+        private void InitDeviceListControl()
         {
             //鑾峰彇璁惧鍒楄〃
             string gwID = HdlGatewayLogic.Current.GetGatewayId(GatewayResourse.NowSelectGateway);
@@ -186,41 +185,41 @@
                 //寮�鍚綉鍏冲湪绾跨洃娴嬬殑绾跨▼
                 this.StartGatewayOnlieCheckThread();
                 //妫�娴嬭澶囨柊鐗堟湰
-                this.CheckDeviceNewVersion(listOta);
-            });
+                this.CheckDeviceNewVersion(listOta);
+            });
         }
 
         #endregion
 
         #region 鈻� 娣诲姞璁惧鑿滃崟琛宊____________________
 
-        /// <summary>
-        /// 娣诲姞璁惧鐨勮彍鍗曡
-        /// </summary>
-        /// <param name="deviceMac">璁惧Mac鍦板潃</param>
-        private void AddDeviceMenuRow(string deviceMac)
+        /// <summary>
+        /// 娣诲姞璁惧鐨勮彍鍗曡
+        /// </summary>
+        /// <param name="deviceMac">璁惧Mac鍦板潃</param>
+        private void AddDeviceMenuRow(string deviceMac)
         {
             var rowInfo = this.dicRowInfo[deviceMac];
 
             //鍒涘缓涓�涓彲浠ュ睍寮�鍜屾敹缂╃殑FrameLayout,鐩稿綋浜庤彍鍗曟爮
             var frameTable = new FrameListControl(29);
-            frameTable.Height = ControlCommonResourse.ListViewRowHeight + frameTable.rowSpace;
-            listView.AddChidren(frameTable);
-            rowInfo.frameTable = frameTable;
-
+            frameTable.Height = ControlCommonResourse.ListViewRowHeight + frameTable.rowSpace;
+            listView.AddChidren(frameTable);
+            rowInfo.frameTable = frameTable;
+
             //鎺т欢
-            var rowMenu = new DeviceObjectControl(deviceMac, listView.rowSpace / 2);
-            frameTable.AddChidren(rowMenu);
+            var rowMenu = new DeviceObjectControl(deviceMac, 0);
+            frameTable.AddChidren(rowMenu);
             rowMenu.InitControl();
-            rowInfo.MenuRow = rowMenu;
-            //鍚戝彸鍥炬爣
-            var btnRight = rowMenu.frameTable.AddRightIconControl();
-            btnRight.SelectedImagePath = "Item/Down.png";
-
-            //鎻愮ず鏂扮増鏈�
-            var btnNew = new InformationTipView(rowMenu.btnIcon);
-            btnNew.Visible = false;
-            rowMenu.frameTable.AddChidren(btnNew, ChidrenBindMode.BindEventOnly);
+            rowInfo.MenuRow = rowMenu;
+            //鍚戝彸鍥炬爣
+            var btnRight = rowMenu.frameTable.AddRightArrow();
+            btnRight.SelectedImagePath = "Item/Down.png";
+
+            //鎻愮ず鏂扮増鏈�
+            var btnNew = new InformationTipView(rowMenu.btnIcon);
+            btnNew.Visible = false;
+            rowMenu.frameTable.AddChidren(btnNew, ChidrenBindMode.BindEventOnly);
             rowMenu.AddTag("btnNew", btnNew);
 
             //妫�娴嬭澶囨槸鍚︽嫢鏈夊畾浣嶇殑鍔熻兘
@@ -258,29 +257,29 @@
                     //灞曞紑鎴栬�呮姌鍙犳槑缁嗗垪琛�
                     this.ShowDetailList(deviceMac, btnRight.IsSelected);
                 }
-            };
+            };
         }
 
         #endregion
 
         #region 鈻� 灞曞紑鎶樺彔___________________________
 
-        /// <summary>
-        /// 灞曞紑鎴栬�呴殣钘忓垪琛�
-        /// </summary>
-        /// <param name="deviceMac">璁惧Mac鍦板潃</param>
-        /// <param name="isShow">鏄惁灞曞紑</param>
-        private void ShowDetailList(string deviceMac, bool isShow)
-        {
-            var rowInfo = this.dicRowInfo[deviceMac];
-            //瀹冨師鏉ョ殑楂樺害
-            int oldHeight = rowInfo.frameTable.Height;
-            //鍙樻洿鐨勯珮搴�,榛樿涓哄垪琛ㄩ殣钘�
-            int heightValue = ControlCommonResourse.ListViewRowHeight + rowInfo.frameTable.rowSpace;
-            var listDevice = Common.LocalDevice.Current.GetDevicesByMac(deviceMac);
-            if (isShow == true)
-            {
-                //灞曞紑妯″紡鏃讹紝鎵╁ぇ渚濇嵁涓�:瀹冩湁鍑犱釜瀛愭帶浠�
+        /// <summary>
+        /// 灞曞紑鎴栬�呴殣钘忓垪琛�
+        /// </summary>
+        /// <param name="deviceMac">璁惧Mac鍦板潃</param>
+        /// <param name="isShow">鏄惁灞曞紑</param>
+        private void ShowDetailList(string deviceMac, bool isShow)
+        {
+            var rowInfo = this.dicRowInfo[deviceMac];
+            //瀹冨師鏉ョ殑楂樺害
+            int oldHeight = rowInfo.frameTable.Height;
+            //鍙樻洿鐨勯珮搴�,榛樿涓哄垪琛ㄩ殣钘�
+            int heightValue = ControlCommonResourse.ListViewRowHeight + rowInfo.frameTable.rowSpace;
+            var listDevice = Common.LocalDevice.Current.GetDevicesByMac(deviceMac);
+            if (isShow == true)
+            {
+                //灞曞紑妯″紡鏃讹紝鎵╁ぇ渚濇嵁涓�:瀹冩湁鍑犱釜瀛愭帶浠�
                 heightValue = (listDevice.Count + 1) * (ControlCommonResourse.ListViewRowHeight + rowInfo.frameTable.rowSpace);
                 //鏍囬鑷繁灏辨槸涓�涓瓙鎺т欢
                 if (rowInfo.frameTable.ChildrenCount == 1)
@@ -290,10 +289,10 @@
                         //鍔犺浇瀹冪殑鍒楄〃
                         this.AddDeviceDetailRow(rowInfo.frameTable, info);
                     }
-                }
-            }
-            //鑷韩楂樺害鍙樻洿
-            rowInfo.frameTable.Height = heightValue;
+                }
+            }
+            //鑷韩楂樺害鍙樻洿
+            rowInfo.frameTable.Height = heightValue;
         }
 
         /// <summary>
@@ -304,7 +303,10 @@
         private void AddDeviceDetailRow(FrameListControl frame, CommonDevice device)
         {
             var rowInfo = this.dicRowInfo[device.DeviceAddr];
-            rowInfo.dicDetailRow = new Dictionary<string, DeviceRoomControl>();
+            if (rowInfo.dicDetailRow == null)
+            {
+                rowInfo.dicDetailRow = new Dictionary<string, DeviceRoomControl>();
+            }
 
             //琛屾帶浠�
             var rowDevice = new DeviceRoomControl(device, frame.rowSpace / 2);
@@ -314,7 +316,9 @@
             //搴曠嚎
             rowDevice.frameTable.AddBottomLine();
             //鍙崇澶�
-            rowDevice.frameTable.AddRightIconControl();
+            rowDevice.frameTable.AddRightArrow();
+            //鍦ㄧ嚎鐘舵��
+            rowDevice.isOnline = device.IsOnline == 1;
 
             //淇濆瓨鎺т欢
             string maikey = Common.LocalDevice.Current.GetDeviceMainKeys(device);
@@ -349,13 +353,13 @@
 
         #endregion
 
-        #region 鈻� 閿�兼悳绱__________________________
+        #region 鈻� 閿�兼悳绱__________________________
 
-        /// <summary>
-        /// 鏍规嵁鎼滅储閿�硷紝璁惧畾鍒楄〃鏁版嵁
-        /// </summary>
-        /// <param name="searchKey">Search key.</param>
-        private void SetRowDataBySearchKeys(string searchKey)
+        /// <summary>
+        /// 鏍规嵁鎼滅储閿�硷紝璁惧畾鍒楄〃鏁版嵁
+        /// </summary>
+        /// <param name="searchKey">Search key.</param>
+        private void SetRowDataBySearchKeys(string searchKey)
         {
             lock (dicRowInfo)
             {
@@ -397,8 +401,8 @@
                         frameTemp.Height = Application.GetRealHeight(23);
                         listView.AddChidren(frameTemp);
                     }
-                });
-            }
+                });
+            }
         }
 
         #endregion
@@ -416,7 +420,7 @@
             }
 
             string selectGwId = HdlGatewayLogic.Current.GetGatewayId(GatewayResourse.NowSelectGateway);
-            new System.Threading.Thread(() =>
+            HdlThreadLogic.Current.RunThread(() =>
             {
                 ZbGateway zbGateway = HdlGatewayLogic.Current.GetLocalGateway(selectGwId);
                 if (zbGateway == null)
@@ -436,14 +440,13 @@
                         this.StartDeviceListControlThread(online);
                     }
                 });
-            })
-            { IsBackground = true }.Start();
+            });
         }
 
         /// <summary>
         /// 缃戝叧鍦ㄧ嚎鐘舵�佸彉鏇�
         /// </summary>
-        /// <param name="gateWay">缃戝叧瀵硅薄</param>
+        /// <param name="gateWay">缃戝叧瀵硅薄</param>
         /// <param name="online">鍦ㄧ嚎鐘舵�佸彉鏇村悗鐨勭姸鎬�</param>
         public override void GatewayOnlinePush(ZbGateway gateWay, bool online)
         {
@@ -519,33 +522,32 @@
                 return;
             }
             string gwId = HdlGatewayLogic.Current.GetGatewayId(GatewayResourse.NowSelectGateway);
-            new System.Threading.Thread(async () =>
+            HdlThreadLogic.Current.RunThread(async () =>
             {
                 //杩欓噷涓昏鍙槸鑾峰彇鍦ㄧ嚎鐘舵��
                 var zbway = HdlGatewayLogic.Current.GetLocalGateway(gwId);
-                var result = await Common.LocalDevice.Current.GetDeviceListFromGateway(zbway, this.ReceiveDeviceStatuPush);
-            })
-            { IsBackground = true }.Start();
+                var result = await Common.LocalDevice.Current.GetDeviceListFromGateway(zbway, false, this.ReceiveDeviceStatuPush, ShowErrorMode.NO);
+            });
         }
 
         /// <summary>
-        /// 鎺ュ彈璁惧鍦ㄧ嚎鎺ㄩ�侊紙缃戝叧鍦ㄧ嚎鎺ㄩ�佸嵆鍦ㄧ嚎锛�
+        /// 鎺ュ彈璁惧鍦ㄧ嚎鎺ㄩ��
         /// </summary>
         /// <param name="device"></param>
         private void ReceiveDeviceStatuPush(CommonDevice device)
         {
             lock (dicRowInfo)
             {
-                if (device == null || this.Parent == null)
+                if (this.Parent == null)
                 {
                     return;
                 }
-                DeviceObjectControl row = null;
+                DeviceObjRowInfo rowInfo = null;
                 if (this.dicRowInfo.ContainsKey(device.DeviceAddr) == true)
                 {
-                    row = this.dicRowInfo[device.DeviceAddr].MenuRow;
+                    rowInfo = this.dicRowInfo[device.DeviceAddr];
                 }
-                if (row == null)
+                if (rowInfo == null || rowInfo.MenuRow == null)
                 {
                     return;
                 }
@@ -564,11 +566,18 @@
                     localDevice.ReSave();
                 }
 
-                Application.RunOnMainThread(() =>
+                HdlThreadLogic.Current.RunMain(() =>
                 {
-                    if (row != null)
+                    if (rowInfo != null)
                     {
-                        row.isOnline = device.IsOnline == 1;
+                        rowInfo.MenuRow.isOnline = device.IsOnline == 1;
+                        if (rowInfo.dicDetailRow != null)
+                        {
+                            foreach (var detailRow in rowInfo.dicDetailRow.Values)
+                            {
+                                detailRow.isOnline = rowInfo.MenuRow.isOnline;
+                            }
+                        }
                     }
                 });
             }
@@ -604,7 +613,7 @@
         /// <param name="list">ota璁惧</param>
         private void CheckDeviceNewVersion(List<OTADevice> list)
         {
-            new System.Threading.Thread(async () =>
+            HdlThreadLogic.Current.RunThread(async () =>
             {
                 await System.Threading.Tasks.Task.Delay(2000);
                 foreach (var ota in list)
@@ -644,17 +653,16 @@
                         }
                     });
                 }
-            })
-            { IsBackground = true }.Start();
+            });
         }
 
         #endregion
 
-        #region 鈻� 浼犳劅鍣ㄦ姤璀________________________
+        #region 鈻� 浼犳劅鍣ㄦ姤璀________________________
 
         /// <summary>
         /// 寮�鍚紶鎰熷櫒鎶ヨ鐩戣
-        /// </summary>
+        /// </summary>
         private void StartCheckDeviceAlarm()
         {
             HdlDeviceAttributeLogic.Current.AddAttributeEvent("DeviceListFormSensor", "IASInfoReport", (device) =>
@@ -676,13 +684,13 @@
 
         #endregion
 
-        #region 鈻� 瀹炵幇澶栭儴璋冪敤_______________________
+        #region 鈻� 瀹炵幇澶栭儴璋冪敤_______________________
 
-        /// <summary>
-        /// 娣诲姞鏂扮殑璁惧鍒扮晫闈㈡甯冧腑
-        /// </summary>
-        /// <param name="deviceAddr">璁惧Mac鍦板潃</param>
-        public void AddDeviceToFormTable(string deviceAddr)
+        /// <summary>
+        /// 娣诲姞鏂扮殑璁惧鍒扮晫闈㈡甯冧腑
+        /// </summary>
+        /// <param name="deviceAddr">璁惧Mac鍦板潃</param>
+        public void AddDeviceToFormTable(string deviceAddr)
         {
             //鏂板缓涓�涓璞�
             if (this.dicRowInfo.ContainsKey(deviceAddr) == false)
@@ -698,8 +706,8 @@
                 this.AddDeviceMenuRow(deviceAddr);
 
                 return;
-            }
-        }
+            }
+        }
 
         #endregion
 
@@ -708,24 +716,22 @@
         /// <summary>
         /// 鏍规嵁MAC鍚堝苟璁惧鍒楄〃
         /// </summary>
-        /// <param name="listDevice"></param>
-        private void MargeAllDeviceByMac(List<CommonDevice> listDevice)
+        /// <param name="listDevice"></param>
+        private void MargeAllDeviceByMac(List<CommonDevice> listDevice)
         {
-            //璁惧鎺掑簭
-            List<CommonDevice> listSort = Common.LocalDevice.Current.SortDeviceList(listDevice);
             //鏍规嵁Mac鍏ㄩ儴鍒嗙粍
             var dic = new Dictionary<string, List<CommonDevice>>();
-            foreach (CommonDevice device in listSort)
-            {
+            foreach (CommonDevice device in listDevice)
+            {
                 if (device == null || device.DeviceAddr == null)
                 {
                     continue;
-                }
-                if (dic.ContainsKey(device.DeviceAddr) == false)
-                {
-                    dic[device.DeviceAddr] = new List<CommonDevice>();
-                }
-                dic[device.DeviceAddr].Add(device);
+                }
+                if (dic.ContainsKey(device.DeviceAddr) == false)
+                {
+                    dic[device.DeviceAddr] = new List<CommonDevice>();
+                }
+                dic[device.DeviceAddr].Add(device);
             }
             //鑾峰彇淇℃伅
             foreach (var mac in dic.Keys)
@@ -735,7 +741,7 @@
                 info.MacName = Common.LocalDevice.Current.GetDeviceMacName(dic[mac][0]);
                 info.DeviveTypeName = Common.LocalDevice.Current.GetDeviceObjectText(dic[mac]);
                 this.dicRowInfo[mac] = info;
-            }
+            }
         }
 
         #endregion
@@ -744,15 +750,15 @@
 
         /// <summary>
         /// 鐢婚潰鍏抽棴
-        /// </summary>
-        public override void CloseForm()
+        /// </summary>
+        public override void CloseForm()
         {
             HdlDeviceAttributeLogic.Current.RemoveEvent("DeviceListFormSensor");
-            HdlDeviceAttributeLogic.Current.RemoveEvent("DeviceListFormReceivePushOnline");
+            HdlDeviceAttributeLogic.Current.RemoveEvent("DeviceListFormReceivePushOnline");
 
-            GatewayResourse.NowSelectGateway = null;
-
-            base.CloseForm();
+            GatewayResourse.NowSelectGateway = null;
+
+            base.CloseForm();
         }
 
         #endregion
@@ -762,11 +768,11 @@
         /// <summary>
         /// 鑷韩鐨勪笂灞傜晫闈㈠叧闂悗,瀹冭嚜韬浜庢渶涓婂眰鏃�,瑙﹀彂鐨勪簨浠�
         /// </summary>
-        public override void FormActionAgainEvent()
+        public override int FormActionAgainEvent()
         {
             if (this.nowActionDeviceMac == null)
             {
-                return;
+                return 1;
             }
             var rowInfo = this.dicRowInfo[nowActionDeviceMac];
             //妫�娴嬭繖涓澶囨槸鍚﹁鍒犻櫎
@@ -795,6 +801,8 @@
             this.nowActionDeviceMac = null;
             //缃戝叧鎺т欢鍒锋柊
             this.gatewayViewRow.RefreshControl();
+
+            return 1;
         }
 
         #endregion
@@ -891,7 +899,7 @@
                 btnNowGw.TextColor = UserCenterColor.Current.TextGrayColor1;
 
                 //鍚戝彸鍥炬爣
-                var btnRight = this.AddRightIconControl();
+                var btnRight = this.AddRightArrow();
                 btnRight.Name = "btnRight";
                 //缃戝叧绠$悊
                 var btnMament = this.AddMostRightView(Language.StringByID(R.MyInternationalizationString.uGatewayManagement), 300);

--
Gitblit v1.8.0