RKZYLayer.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. using Best.HTTP.Shared.Compression.Zlib;
  2. using Newtonsoft.Json;
  3. using Newtonsoft.Json.Linq;
  4. using System;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using System.Text.RegularExpressions;
  8. using System.Threading.Tasks;
  9. using Unity.VisualScripting;
  10. using UnityAsync;
  11. using UnityEngine;
  12. using UnityEngine.Networking;
  13. using UnityEngine.UI;
  14. [System.Serializable]
  15. public class MovePlan
  16. {
  17. public string startPos;
  18. public string endPos;
  19. public int humanNum;
  20. public string time;
  21. }
  22. [System.Serializable]
  23. public class MoveAtten
  24. {
  25. public string title;
  26. public string pos;
  27. public string time;
  28. }
  29. [System.Serializable]
  30. public class ServerMovePlan {
  31. public bool isAfter;
  32. public bool isOut;
  33. public string desc;
  34. public string from;
  35. public float fromLong;
  36. public float fromLttd;
  37. public string to;
  38. public float toLong;
  39. public float toLttd;
  40. public int manNum;
  41. public int homeNum;
  42. public int completeNum;
  43. public string dateTime;
  44. public int villageCount;
  45. public int materialPrize;
  46. }
  47. [System.Serializable]
  48. public class ZYYAData
  49. {
  50. public int totalRoadCount;
  51. public float totalmanNum;
  52. public int totalVillageCount;
  53. public float totalMaterialPrize;
  54. }
  55. public class RKZYLayer : YZTRootLayer
  56. {
  57. public Text timeText;
  58. public LineInfo lineInfo;
  59. //public List<MovePlan> movePlans;
  60. public List<Thing1> movePlans;
  61. public List<MoveAtten> moveAttens;
  62. public static LineInfo lineInfoStatic;
  63. public Button beforeBtn;
  64. public Button afterBtn;
  65. public Button[] allInOut;
  66. public RectTransform beforeC;
  67. public RectTransform afterC;
  68. public List<LinePath> linePaths = new List<LinePath>();
  69. public Sprite[] sprites;
  70. public int inOutIndex;
  71. public int beforeAfterIndex;
  72. public RectTransform title1;
  73. public RectTransform plan1;
  74. public RectTransform movePlanBeforeContent;
  75. public RectTransform movePlanAfterContent;
  76. public RectTransform title2;
  77. public RectTransform plan2;
  78. public RectTransform attenContent;
  79. public List<ServerMovePlan> allServerMovePlans = new List<ServerMovePlan>();
  80. public Text[] zYGKText;
  81. public ZYYAData[] zYYADatas;
  82. public int zYYAIndex = 0;
  83. public Text[] zYYAText;
  84. public Material afterMat;
  85. public LinePath linePathPrefab;
  86. // Start is called before the first frame update
  87. async void Start()
  88. {
  89. lineInfoStatic = lineInfo;
  90. await InitMovePlan();
  91. //TODO 这一块的path应该从movePlan里面生成而不是默认
  92. InitAllPath();
  93. InitButton();
  94. InitAtten();
  95. await InitBaseData();
  96. }
  97. private void OnEnable()
  98. {
  99. CameraManager.SwitchCamera(1);
  100. }
  101. void InitAtten() {
  102. RectTransform title = Instantiate(title2);
  103. title.SetParent(attenContent);
  104. title.localScale = Vector3.one;
  105. for (int i = 0; i < moveAttens.Count; i++)
  106. {
  107. RectTransform plan = Instantiate(plan2);
  108. plan.SetParent(attenContent);
  109. plan.localScale = Vector3.one;
  110. plan.GetChild(0).GetComponent<Text>().text = i.ToString();
  111. plan.GetChild(1).GetComponent<Text>().text = moveAttens[i].title;
  112. plan.GetChild(2).GetComponent<Text>().text = moveAttens[i].pos;
  113. plan.GetChild(3).GetComponent<Text>().text = moveAttens[i].time;
  114. }
  115. }
  116. async Task InitBaseData() {
  117. bool successInternet = true;
  118. UnityWebRequest requestData = UnityWebRequest.Get(ServerAddress.APIGetGeBaseData);
  119. await requestData.SendWebRequest();
  120. try
  121. {
  122. if (requestData.result != UnityWebRequest.Result.Success)
  123. {
  124. Debug.LogWarning("RKZYLayer基础数据联网不成功,原因:返request不成功");
  125. successInternet = false;
  126. }
  127. else
  128. {
  129. JObject jsonObject = JObject.Parse(requestData.downloadHandler.text);
  130. JToken codeToken = jsonObject["code"];
  131. if (codeToken.ToString() == "200")
  132. {
  133. JToken areaToken = jsonObject["data"]["area"];
  134. JToken capacityToken = jsonObject["data"]["capacity"];
  135. JToken populationToken = jsonObject["data"]["population"];
  136. zYGKText[0].text = populationToken.ToString() + "人";
  137. zYGKText[1].text = allServerMovePlans.Count.ToString() + "条";
  138. zYGKText[2].text = areaToken.ToString() + "km²";
  139. zYGKText[3].text = (float.Parse((capacityToken.ToString())) * 100).ToString() + "%";
  140. }
  141. else
  142. {
  143. successInternet = false;
  144. Debug.LogWarning("RKZYLayer基础数据联网不成功,原因:返序列化失败");
  145. }
  146. }
  147. }
  148. catch (Exception e)
  149. {
  150. successInternet = false;
  151. Debug.LogWarning("RKZYLayer基础数据联网不成功,原因:" + e.ToString());
  152. }
  153. }
  154. async Task InitMovePlan() {
  155. bool successInternet = true;
  156. UnityWebRequest requestData = UnityWebRequest.Get(ServerAddress.APIGetGetMovePlans);
  157. await requestData.SendWebRequest();
  158. zYYADatas = new ZYYAData[6] { new ZYYAData(), new ZYYAData() , new ZYYAData() , new ZYYAData() , new ZYYAData() , new ZYYAData() };
  159. try
  160. {
  161. if (true)
  162. {
  163. Debug.LogWarning("RKZYLayer联网不成功,读本地缓存数据,原因:返request不成功");
  164. successInternet = false;
  165. }
  166. else
  167. {
  168. JObject jsonObject = JObject.Parse(requestData.downloadHandler.text);
  169. // 提取data字段的值
  170. JToken dataToken = jsonObject["data"];
  171. JToken codeToken = jsonObject["code"];
  172. if (codeToken.ToString() == "200")
  173. {
  174. allServerMovePlans = JsonConvert.DeserializeObject<List<ServerMovePlan>>(dataToken.ToString());
  175. }
  176. else
  177. {
  178. successInternet = false;
  179. Debug.LogWarning("XHGKLayer联网不成功,读本地缓存数据,原因:返序列化失败");
  180. }
  181. }
  182. }
  183. catch (Exception e)
  184. {
  185. successInternet = false;
  186. Debug.LogWarning("RKZYLayer联网不成功,读本地缓存数据,原因:" + e.ToString());
  187. }
  188. if (!successInternet)
  189. {
  190. WWW www = new WWW(Application.streamingAssetsPath + "/moveplan.json");
  191. await new UnityAsync.WaitUntil(() =>
  192. {
  193. return www.isDone;
  194. });
  195. allServerMovePlans = JsonConvert.DeserializeObject<List<ServerMovePlan>>(www.text);
  196. www.Dispose();
  197. }
  198. int beforeIndex = 0;
  199. int afterIndex = 0;
  200. List<LinePath> beforeLinePaths = new List<LinePath>();
  201. List<LinePath> afterLinePaths = new List<LinePath>();
  202. GameObject shaPan = GameObject.FindGameObjectWithTag("ShaPan");
  203. Transform runtimPointParent = shaPan.transform.GetChild(10);
  204. for (int i = 0; i < allServerMovePlans.Count; i++) {
  205. bool after = allServerMovePlans[i].isAfter;
  206. bool isOut = allServerMovePlans[i].isOut;
  207. if (!after)
  208. {
  209. LinePath linePath = Instantiate(linePathPrefab);
  210. linePath.transform.SetParent(beforeC);
  211. linePath.startPos = allServerMovePlans[i].from;
  212. Vector3 localPos = CoordinateConverter.GeoToUGUISmall(allServerMovePlans[i].fromLong, allServerMovePlans[i].fromLttd);
  213. Vector3 worldPos = runtimPointParent.TransformPoint(localPos);
  214. worldPos.z = -583;
  215. linePath.endPos = allServerMovePlans[i].to;
  216. Vector3 localPos1 = CoordinateConverter.GeoToUGUISmall(allServerMovePlans[i].toLong, allServerMovePlans[i].toLttd);
  217. Vector3 worldPos1 = runtimPointParent.TransformPoint(localPos1);
  218. worldPos1.z = -583;
  219. linePath.SetPath(worldPos, worldPos1);
  220. linePath.lineDir = isOut ? LineDir.Out : LineDir.In;
  221. linePath.linePathContent = allServerMovePlans[i].desc;
  222. linePath.manNum = allServerMovePlans[i].manNum;
  223. linePath.homeNum = allServerMovePlans[i].homeNum;
  224. linePath.completeNum = allServerMovePlans[i].completeNum;
  225. linePath.dateTime = allServerMovePlans[i].dateTime;
  226. if (linePath.lineDir == LineDir.Out)
  227. {
  228. zYYADatas[1].totalmanNum += allServerMovePlans[i].manNum;
  229. zYYADatas[1].totalVillageCount += allServerMovePlans[i].villageCount;
  230. zYYADatas[1].totalMaterialPrize += allServerMovePlans[i].materialPrize;
  231. zYYADatas[1].totalRoadCount += 1;
  232. }
  233. else
  234. {
  235. zYYADatas[2].totalmanNum += allServerMovePlans[i].manNum;
  236. zYYADatas[2].totalVillageCount += allServerMovePlans[i].villageCount;
  237. zYYADatas[2].totalMaterialPrize += allServerMovePlans[i].materialPrize;
  238. zYYADatas[2].totalRoadCount += 1;
  239. }
  240. beforeLinePaths.Add(linePath);
  241. }
  242. else
  243. {
  244. LinePath linePath = Instantiate(linePathPrefab);
  245. linePath.transform.SetParent(afterC);
  246. linePath.startPos = allServerMovePlans[i].from;
  247. Vector3 localPos = CoordinateConverter.GeoToUGUISmall(allServerMovePlans[i].fromLong, allServerMovePlans[i].fromLttd);
  248. Vector3 worldPos = runtimPointParent.TransformPoint(localPos);
  249. worldPos.z = -583;
  250. linePath.endPos = allServerMovePlans[i].to;
  251. Vector3 localPos1 = CoordinateConverter.GeoToUGUISmall(allServerMovePlans[i].toLong, allServerMovePlans[i].toLttd);
  252. Vector3 worldPos1 = runtimPointParent.TransformPoint(localPos1);
  253. worldPos1.z = -583;
  254. linePath.SetPath(worldPos, worldPos1);
  255. linePath.lineDir = isOut ? LineDir.Out : LineDir.In;
  256. linePath.linePathContent = allServerMovePlans[i].desc;
  257. linePath.manNum = allServerMovePlans[i].manNum;
  258. linePath.homeNum = allServerMovePlans[i].homeNum;
  259. linePath.completeNum = allServerMovePlans[i].completeNum;
  260. linePath.dateTime = allServerMovePlans[i].dateTime;
  261. if (linePath.lineDir == LineDir.Out)
  262. {
  263. zYYADatas[4].totalmanNum += allServerMovePlans[i].manNum;
  264. zYYADatas[4].totalVillageCount += allServerMovePlans[i].villageCount;
  265. zYYADatas[4].totalMaterialPrize += allServerMovePlans[i].materialPrize;
  266. zYYADatas[4].totalRoadCount += 1;
  267. }
  268. else
  269. {
  270. zYYADatas[5].totalmanNum += allServerMovePlans[i].manNum;
  271. zYYADatas[5].totalVillageCount += allServerMovePlans[i].villageCount;
  272. zYYADatas[5].totalMaterialPrize += allServerMovePlans[i].materialPrize;
  273. zYYADatas[5].totalRoadCount += 1;
  274. }
  275. afterLinePaths.Add(linePath);
  276. }
  277. zYYADatas[0].totalmanNum = zYYADatas[1].totalmanNum + zYYADatas[2].totalmanNum;
  278. zYYADatas[0].totalVillageCount = zYYADatas[1].totalVillageCount + zYYADatas[2].totalVillageCount;
  279. zYYADatas[0].totalMaterialPrize = zYYADatas[1].totalMaterialPrize + zYYADatas[2].totalMaterialPrize;
  280. zYYADatas[0].totalRoadCount = zYYADatas[1].totalRoadCount + zYYADatas[2].totalRoadCount;
  281. zYYADatas[3].totalmanNum = zYYADatas[4].totalmanNum + zYYADatas[5].totalmanNum;
  282. zYYADatas[3].totalVillageCount = zYYADatas[4].totalVillageCount + zYYADatas[5].totalVillageCount;
  283. zYYADatas[3].totalMaterialPrize = zYYADatas[4].totalMaterialPrize + zYYADatas[5].totalMaterialPrize;
  284. zYYADatas[3].totalRoadCount = zYYADatas[4].totalRoadCount + zYYADatas[5].totalRoadCount;
  285. RefreshZYYAData();
  286. }
  287. movePlans = new List<Thing1>();
  288. RectTransform title = Instantiate(title1);
  289. title.localScale = Vector3.one;
  290. title.SetParent(movePlanBeforeContent);
  291. RectTransform title2 = Instantiate(title1);
  292. title2.localScale = Vector3.one;
  293. title2.SetParent(movePlanAfterContent);
  294. List<ServerMovePlan> serverMovePlans = new List<ServerMovePlan>();
  295. for (int i = 0; i < beforeLinePaths.Count; i++)
  296. {
  297. int tempI = i;
  298. RectTransform plan = Instantiate(plan1);
  299. plan.SetParent(movePlanBeforeContent);
  300. Thing1 thing1 = plan.GetComponent<Thing1>();
  301. thing1.zyTime = ZYTime.Before;
  302. thing1.lineDir = beforeLinePaths[i].lineDir;
  303. thing1.bindLinePath = beforeLinePaths[i];
  304. thing1.GetComponent<Button>().onClick.AddListener(() =>
  305. {
  306. for (int i = 0; i < linePaths.Count; i++)
  307. {
  308. linePaths[i].gameObject.SetActive(false);
  309. }
  310. thing1.bindLinePath.gameObject.SetActive(true);
  311. });
  312. plan.localScale = Vector3.one;
  313. plan.GetChild(0).GetComponent<Text>().text = i.ToString();
  314. plan.GetChild(1).GetComponent<Text>().text = beforeLinePaths[i].startPos;
  315. plan.GetChild(2).GetComponent<Text>().text = beforeLinePaths[i].endPos;
  316. plan.GetChild(3).GetComponent<Text>().text = beforeLinePaths[i].manNum.ToString();
  317. plan.GetChild(4).GetComponent<Text>().text = beforeLinePaths[i].dateTime.ToString();
  318. movePlans.Add(thing1);
  319. }
  320. for (int i = 0; i < afterLinePaths.Count; i++)
  321. {
  322. RectTransform plan = Instantiate(plan1);
  323. plan.SetParent(movePlanAfterContent);
  324. Thing1 thing1 = plan.GetComponent<Thing1>();
  325. thing1.zyTime = ZYTime.After;
  326. thing1.lineDir = afterLinePaths[i].lineDir;
  327. thing1.bindLinePath = afterLinePaths[i];
  328. thing1.GetComponent<Button>().onClick.AddListener(() =>
  329. {
  330. for (int i = 0; i < linePaths.Count; i++)
  331. {
  332. linePaths[i].gameObject.SetActive(false);
  333. }
  334. thing1.bindLinePath.gameObject.SetActive(true);
  335. });
  336. plan.localScale = Vector3.one;
  337. plan.GetChild(0).GetComponent<Text>().text = i.ToString();
  338. plan.GetChild(1).GetComponent<Text>().text = afterLinePaths[i].startPos;
  339. plan.GetChild(2).GetComponent<Text>().text = afterLinePaths[i].endPos;
  340. plan.GetChild(3).GetComponent<Text>().text = afterLinePaths[i].manNum.ToString();
  341. plan.GetChild(4).GetComponent<Text>().text = afterLinePaths[i].dateTime.ToString();
  342. movePlans.Add(thing1);
  343. }
  344. movePlanAfterContent.gameObject.SetActive(false);
  345. }
  346. void ChangeLinePathChannel(int index) {
  347. switch (index)
  348. {
  349. case 0:
  350. for (int i = 0; i < linePaths.Count; i++)
  351. {
  352. linePaths[i].gameObject.SetActive(true);
  353. }
  354. break;
  355. case 1:
  356. for (int i = 0; i < linePaths.Count; i++)
  357. {
  358. if (linePaths[i].lineDir == LineDir.Out)
  359. linePaths[i].gameObject.SetActive(true);
  360. else
  361. linePaths[i].gameObject.SetActive(false);
  362. }
  363. break;
  364. case 2:
  365. for (int i = 0; i < linePaths.Count; i++)
  366. {
  367. if (linePaths[i].lineDir == LineDir.In)
  368. linePaths[i].gameObject.SetActive(true);
  369. else
  370. linePaths[i].gameObject.SetActive(false);
  371. }
  372. break;
  373. }
  374. }
  375. void RefreshZYYAData() {
  376. zYYAIndex = beforeAfterIndex * 3 + inOutIndex;
  377. zYYAText[0].text = zYYADatas[zYYAIndex].totalVillageCount.ToString();
  378. zYYAText[1].text = (zYYADatas[zYYAIndex].totalmanNum / 10000.0f).ToString("0.00");
  379. zYYAText[2].text = (zYYADatas[zYYAIndex].totalMaterialPrize / 100000000.0f).ToString("0.00");
  380. zYYAText[3].text = zYYADatas[zYYAIndex].totalRoadCount.ToString();
  381. }
  382. void InitButton() {
  383. beforeBtn.onClick.AddListener(() => {
  384. beforeAfterIndex = 0;
  385. beforeBtn.GetComponent<Image>().sprite = sprites[0];
  386. afterBtn.GetComponent<Image>().sprite = sprites[1];
  387. beforeC.gameObject.SetActive(true);
  388. afterC.gameObject.SetActive(false);
  389. movePlanBeforeContent.gameObject.SetActive(true);
  390. movePlanAfterContent.gameObject.SetActive(false);
  391. ChangeLinePathChannel(inOutIndex);
  392. RefreshZYYAData();
  393. });
  394. afterBtn.onClick.AddListener(() => {
  395. beforeAfterIndex = 1;
  396. beforeBtn.GetComponent<Image>().sprite = sprites[1];
  397. afterBtn.GetComponent<Image>().sprite = sprites[0];
  398. beforeC.gameObject.SetActive(false);
  399. afterC.gameObject.SetActive(true);
  400. movePlanBeforeContent.gameObject.SetActive(false);
  401. movePlanAfterContent.gameObject.SetActive(true);
  402. ChangeLinePathChannel(inOutIndex);
  403. RefreshZYYAData();
  404. });
  405. allInOut[0].onClick.AddListener(() =>
  406. {
  407. inOutIndex = 0;
  408. ChangeLinePathChannel(0);
  409. for (int i = 0; i < movePlans.Count; i++)
  410. {
  411. movePlans[i].gameObject.SetActive(true);
  412. }
  413. allInOut[0].gameObject.GetComponent<Image>().sprite = sprites[0];
  414. allInOut[1].gameObject.GetComponent<Image>().sprite = sprites[1];
  415. allInOut[2].gameObject.GetComponent<Image>().sprite = sprites[1];
  416. RefreshZYYAData();
  417. });
  418. allInOut[1].onClick.AddListener(() =>
  419. {
  420. inOutIndex = 1;
  421. ChangeLinePathChannel(1);
  422. for (int i = 0; i < movePlans.Count; i++)
  423. {
  424. if (movePlans[i].lineDir == LineDir.Out)
  425. movePlans[i].gameObject.SetActive(true);
  426. else
  427. movePlans[i].gameObject.SetActive(false);
  428. }
  429. allInOut[0].gameObject.GetComponent<Image>().sprite = sprites[1];
  430. allInOut[1].gameObject.GetComponent<Image>().sprite = sprites[0];
  431. allInOut[2].gameObject.GetComponent<Image>().sprite = sprites[1];
  432. RefreshZYYAData();
  433. });
  434. allInOut[2].onClick.AddListener(() =>
  435. {
  436. inOutIndex = 2;
  437. ChangeLinePathChannel(2);
  438. for (int i = 0; i < movePlans.Count; i++)
  439. {
  440. if (movePlans[i].lineDir == LineDir.In)
  441. movePlans[i].gameObject.SetActive(true);
  442. else
  443. movePlans[i].gameObject.SetActive(false);
  444. }
  445. allInOut[0].gameObject.GetComponent<Image>().sprite = sprites[1];
  446. allInOut[1].gameObject.GetComponent<Image>().sprite = sprites[1];
  447. allInOut[2].gameObject.GetComponent<Image>().sprite = sprites[0];
  448. RefreshZYYAData();
  449. });
  450. }
  451. void InitAllPath() {
  452. for (int i = 0; i < beforeC.childCount; i++)
  453. {
  454. if (beforeC.GetChild(i).GetComponent<LinePath>())
  455. {
  456. linePaths.Add(beforeC.GetChild(i).GetComponent<LinePath>());
  457. }
  458. }
  459. for (int i = 0; i < afterC.childCount; i++)
  460. {
  461. if (afterC.GetChild(i).GetComponent<LinePath>())
  462. {
  463. linePaths.Add(afterC.GetChild(i).GetComponent<LinePath>());
  464. }
  465. }
  466. }
  467. // Update is called once per frame
  468. void Update()
  469. {
  470. // 获取当前时间
  471. DateTime now = DateTime.Now;
  472. // 格式化时间字符串
  473. string timeString = now.ToString("yyyy/MM/dd HH:mm");
  474. // 将格式化的时间字符串设置到UI Text组件上
  475. timeText.text = timeString;
  476. }
  477. LinePath lastPath;
  478. private void FixedUpdate()
  479. {
  480. if (lineInfo.linePaths.Count > 0)
  481. {
  482. lineInfo.gameObject.SetActive(true);
  483. }
  484. else
  485. {
  486. lineInfo.gameObject.SetActive(false);
  487. }
  488. Ray ray = CameraManager.instance.secondCamera.ScreenPointToRay(Input.mousePosition);
  489. RaycastHit hit;
  490. if (Physics.Raycast(ray, out hit, 10000))
  491. {
  492. Debug.Log(hit.collider.gameObject.name);
  493. // 检查射线是否击中 LineRenderer 所在的物体
  494. if (hit.collider.transform.parent.GetComponent<LinePath>() != null)
  495. {
  496. if (lastPath != null && hit.collider.transform.parent.GetComponent<LinePath>() != lastPath) {
  497. lastPath.UnShow();
  498. }
  499. hit.collider.transform.parent.GetComponent<LinePath>().OnShow();
  500. lastPath = hit.collider.transform.parent.GetComponent<LinePath>();
  501. }
  502. else
  503. {
  504. if (lastPath)
  505. {
  506. lastPath.UnShow();
  507. lastPath = null;
  508. }
  509. }
  510. }
  511. else {
  512. if (lastPath)
  513. {
  514. lastPath.UnShow();
  515. lastPath = null;
  516. }
  517. }
  518. }
  519. }