ChallengeManagerForPC.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. using ChivaXR;
  2. using JetBrains.Annotations;
  3. using Org.BouncyCastle.Operators;
  4. using QFramework;
  5. using Sirenix.OdinInspector;
  6. using System;
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. using UnityEngine;
  10. using UnityEngine.Networking.Types;
  11. using UnityEngine.TextCore;
  12. public class ChallengeManagerForPC : MonoBehaviour
  13. {
  14. public static ChallengeManagerForPC instance;
  15. /// <summary>
  16. /// 关卡信息
  17. /// </summary>
  18. [TableList(MaxScrollViewHeight = 20)]
  19. public List<LevelItem> m_LevelItems;
  20. /// <summary>
  21. /// 关卡标题对应数据
  22. /// </summary>
  23. Dictionary<LeveInfo, List<OperationStepDataInfo>> tmpDicDataInfos;
  24. /// <summary>
  25. /// 目前正在进行的关卡
  26. /// </summary>
  27. private LevelItem m_CurrentLevelItem;
  28. /// <summary>
  29. /// 闯关完成
  30. /// </summary>
  31. private bool m_ChallengeFinish;
  32. /// <summary>
  33. /// 配置所有关卡
  34. /// </summary>
  35. public void GetChallengeProcessElements()
  36. {
  37. List<ProcessElement> processElements = ProcessManagement.Instance.processes;
  38. m_LevelItems = new List<LevelItem>();
  39. foreach (var item in tmpDicDataInfos)
  40. {
  41. LevelItem tmpLevelItem = m_LevelItems.Find(t => t.leveName == item.Key.leveName);
  42. if (tmpLevelItem == null) tmpLevelItem = new LevelItem() { leveName = item.Key.leveName, time = float.Parse(item.Key.leveTime) };
  43. foreach (var opDataInfoItem in item.Value)
  44. {
  45. ChallengeProcessElement tmpChallengeProcessElement = new ChallengeProcessElement()
  46. {
  47. stepInfo = opDataInfoItem,
  48. };
  49. tmpLevelItem.challengeProcessElements.Add(tmpChallengeProcessElement);
  50. }
  51. m_LevelItems.Add(tmpLevelItem);
  52. }
  53. Debug.Log(m_LevelItems.Count);
  54. }
  55. /// <summary>
  56. /// 闯关开始时间
  57. /// </summary>
  58. private DateTime m_StartTime;
  59. /// <summary>
  60. /// 闯关结束时间
  61. /// </summary>
  62. private DateTime m_EndTime;
  63. private void Awake()
  64. {
  65. instance = this;
  66. }
  67. /// <summary>
  68. /// 初始化
  69. /// </summary>
  70. public void Init()
  71. {
  72. ProcessManagement.Instance.processElementActiveEvent += ProcessElementActive;
  73. ProcessManagement.Instance.processElementDisActiveEvent += ProcessElementDisActive;
  74. StepListProxy tmpStepListProxy = DAL.Instance.Get<StepListProxy>();
  75. tmpDicDataInfos = new Dictionary<LeveInfo, List<OperationStepDataInfo>>();
  76. ChallengeConfigurationManager tmpChallengeConfigurationManager = null;
  77. Dictionary<string, List<OperationStepDataInfo>> tmpDicOperationStepDataInfos = tmpStepListProxy.ProcessingData();
  78. foreach (var item in tmpDicOperationStepDataInfos)
  79. {
  80. LeveInfo tmpLeveInfo = new LeveInfo();
  81. tmpLeveInfo.leveTime = 3.ToString();
  82. tmpLeveInfo.leveName = item.Key.ToString();
  83. tmpDicDataInfos.Add(tmpLeveInfo, item.Value);
  84. }
  85. GetChallengeProcessElements();
  86. StartAndSwitchLevel();
  87. m_StartTime = DateTime.Now;
  88. m_EndTime = DateTime.Now;
  89. }
  90. /// <summary>
  91. /// 开始/切换关卡
  92. /// </summary>
  93. public void StartAndSwitchLevel()
  94. {
  95. foreach (var item in m_LevelItems)
  96. {
  97. if (!item.finish)
  98. {
  99. m_CurrentLevelItem = item;
  100. item.StartLeve(StartAndSwitchLevel);
  101. UIKit.OpenPanel<TimeForCompletingLevelsPanel>(new TimeForCompletingLevelsPanelData() { m_time = item.time });
  102. return;
  103. }
  104. }
  105. EndChallenge();
  106. }
  107. /// <summary>
  108. /// 步骤进入
  109. /// </summary>
  110. /// <param name="element"></param>
  111. private void ProcessElementActive(ProcessElement element)
  112. {
  113. }
  114. /// <summary>
  115. /// 步骤退出
  116. /// </summary>
  117. /// <param name="element"></param>
  118. private void ProcessElementDisActive(ProcessElement element)
  119. {
  120. m_CurrentLevelItem.SetElementStateByFinishID(element.stepID);
  121. }
  122. /// <summary>
  123. /// 记录错误次数
  124. /// </summary>
  125. /// <param name="fault"></param>
  126. public void RecordFault(int faultID)
  127. {
  128. if (m_ChallengeFinish) return;
  129. ChallengeProcessElement tmpElement = m_CurrentLevelItem.challengeProcessElements.Find(t => t.stepInfo.id == faultID.ToString());
  130. if (tmpElement != null)
  131. {
  132. tmpElement.faultCount++;
  133. tmpElement.errorReason = "操作错误";
  134. }
  135. string screenShotName = DateTime.UtcNow.Ticks.ToString();
  136. StartCoroutine(ScrrenCapture(new Rect(0, 0, Screen.width, Screen.height), 0, screenShotName, tmpElement));
  137. //大于3次结束考试
  138. if (GetTotalErrorNum(false) >= 3)
  139. {
  140. UIKit.ClosePanel<PranticePromptPanel>();
  141. if (UIKit.GetPanel<TimeForCompletingLevelsPanel>()) UIKit.ClosePanel<TimeForCompletingLevelsPanel>();
  142. EndChallenge();
  143. }
  144. }
  145. /// <summary>
  146. /// 结束闯关
  147. /// </summary>
  148. public void EndChallenge()
  149. {
  150. if (m_ChallengeFinish) return;
  151. m_EndTime = DateTime.Now;
  152. Debug.Log("<color=yellow>闯关结束</color>");
  153. m_ChallengeFinish = true;
  154. //UIKit.GetPanel<TimeForCompletingLevelsPanel>().StopAllCoroutines();
  155. UIKit.OpenPanel<ChallengeResultPanel>();
  156. }
  157. public string GetChallengeTotalTime()
  158. {
  159. double tmpTotalSecond = ConverOldTiemAndNewTiemDuration(m_StartTime, m_EndTime);
  160. return ConversionTime((float)tmpTotalSecond);
  161. }
  162. /// <summary>
  163. /// 获取总错误次数
  164. /// </summary>
  165. /// <returns></returns>
  166. public int GetTotalErrorNum(bool containNoFinish = false)
  167. {
  168. int tmpErrorNmu = 0;
  169. foreach (var leveItem in m_LevelItems)
  170. {
  171. tmpErrorNmu += leveItem.GetErrorCount(containNoFinish);
  172. }
  173. return tmpErrorNmu;
  174. }
  175. /// <summary>
  176. /// 是否完成
  177. /// </summary>
  178. /// <returns></returns>
  179. public int IsSuccessfullyPassedTheLevel()
  180. {
  181. return m_LevelItems.FindAll(t => t.finish == false) == null ? 0 : 1;
  182. }
  183. /// <summary>
  184. /// 考试用时
  185. /// </summary>
  186. /// <param name="time"></param>
  187. public string ConversionTime(float time)
  188. {
  189. TimeSpan ts = new TimeSpan(0, 0, Convert.ToInt32(time));
  190. string str = "";
  191. if (ts.Hours > 0)
  192. {
  193. str = String.Format("{0:00}", ts.Hours) + ":" + String.Format("{0:00}", ts.Minutes) + ":" + String.Format("{0:00}", ts.Seconds);
  194. }
  195. if (ts.Hours == 0 && ts.Minutes > 0)
  196. {
  197. str = "00:" + String.Format("{0:00}", ts.Minutes) + ":" + String.Format("{0:00}", ts.Seconds);
  198. }
  199. if (ts.Hours == 0 && ts.Minutes == 0)
  200. {
  201. str = "00:00:" + String.Format("{0:00}", ts.Seconds);
  202. }
  203. return str;
  204. }
  205. public double ConverOldTiemAndNewTiemDuration(System.DateTime oldTime, System.DateTime newTime)
  206. {
  207. System.TimeSpan ts1 = new System.TimeSpan(oldTime.Ticks);
  208. System.TimeSpan ts2 = new System.TimeSpan(newTime.Ticks);
  209. System.TimeSpan tsSub = ts1.Subtract(ts2).Duration();
  210. return tsSub.TotalSeconds;
  211. }
  212. Texture2D screenShot;//保存截取的纹理
  213. IEnumerator ScrrenCapture(Rect rect, int a, string screenShotName, ChallengeProcessElement challengeProcessElement)
  214. {
  215. screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);
  216. yield return new WaitForSeconds(0.5f);
  217. yield return new WaitForEndOfFrame();
  218. screenShot.ReadPixels(rect, 0, 0);
  219. screenShot.Apply();
  220. ////推送
  221. //PushHelper.InitBasicData();
  222. //StartCoroutine(PushHelper.SendFileStreamPushRequest(screenShot, screenShotName, (result, msg, flag, cmnAttachId) =>
  223. // {
  224. // if (!result)
  225. // {
  226. // Debug.LogError(msg);
  227. // }
  228. // else
  229. // {
  230. // challengeProcessElement.screenShotNames.Add(cmnAttachId.data.cmnAttachId);
  231. // }
  232. // challengeProcessElement.m_UpLoading.Remove(screenShotName);
  233. // }));
  234. challengeProcessElement.m_UpLoading.Add(screenShotName);
  235. }
  236. /// <summary>
  237. /// 是否上传完成
  238. /// </summary>
  239. /// <returns></returns>
  240. public bool IsFinishUpLoad()
  241. {
  242. foreach (var leveItem in m_LevelItems)
  243. {
  244. foreach (var item in leveItem.challengeProcessElements)
  245. {
  246. if (item.m_UpLoading.Count > 0)
  247. {
  248. return false;
  249. }
  250. }
  251. }
  252. return true;
  253. }
  254. }
  255. /// <summary>
  256. /// 关卡信息
  257. /// </summary>
  258. public class LevelItem
  259. {
  260. /// <summary>
  261. /// 关卡名称
  262. /// </summary>
  263. public string leveName;
  264. /// <summary>
  265. /// 开始时间
  266. /// </summary>
  267. public DateTime startTime;
  268. /// <summary>
  269. /// 结束时间
  270. /// </summary>
  271. public DateTime endTime;
  272. /// <summary>
  273. /// 闯关时间
  274. /// </summary>
  275. public float time;
  276. /// <summary>
  277. /// 关卡包含步骤
  278. /// </summary>
  279. public List<ChallengeProcessElement> challengeProcessElements = new List<ChallengeProcessElement>();
  280. /// <summary>
  281. /// 目前操作步骤
  282. /// </summary>
  283. public ChallengeProcessElement currentChallengeProcessElement;
  284. /// <summary>
  285. /// 是否完成
  286. /// </summary>
  287. public bool finish;
  288. /// <summary>
  289. /// 完成的回调
  290. /// </summary>
  291. private Action m_FinishCallBack;
  292. /// <summary>
  293. /// 是否步骤ID
  294. /// </summary>
  295. /// <returns></returns>
  296. public bool ContainChallengeId(int id)
  297. {
  298. return challengeProcessElements.Find(t => t.stepInfo.id == id.ToString()) != null;
  299. }
  300. /// <summary>
  301. /// 通过完成的ID设置
  302. /// </summary>
  303. /// <param name="id"></param>
  304. public void SetElementStateByFinishID(int id)
  305. {
  306. ChallengeProcessElement tmpElement = challengeProcessElements.Find(t => t.stepInfo.id == id.ToString());
  307. if (tmpElement != null)
  308. {
  309. tmpElement.operationTime = DateTime.Now;
  310. tmpElement.finish = true;
  311. SwitchToNextLevel();
  312. }
  313. }
  314. /// <summary>
  315. /// 开启关卡
  316. /// </summary>
  317. public void StartLeve(Action action)
  318. {
  319. startTime = DateTime.Now;
  320. endTime = DateTime.Now;
  321. m_FinishCallBack = action;
  322. SwitchToNextLevel();
  323. }
  324. /// <summary>
  325. /// 切换下一关卡
  326. /// </summary>
  327. public void SwitchToNextLevel()
  328. {
  329. ChallengeProcessElement tmpChallengeProcessElement = GetReadyOperation();
  330. if (tmpChallengeProcessElement == null)
  331. {
  332. finish = true;
  333. endTime = DateTime.Now;
  334. m_FinishCallBack?.Invoke();
  335. Debug.LogError("当前关卡" + leveName + "已经完成" + ":" + "用时" + ConverOldTiemAndNewTiemDuration(startTime, endTime));
  336. }
  337. else
  338. {
  339. StartOperationByID(tmpChallengeProcessElement);
  340. }
  341. }
  342. public double ConverOldTiemAndNewTiemDuration(System.DateTime oldTime, System.DateTime newTime)
  343. {
  344. System.TimeSpan ts1 = new System.TimeSpan(oldTime.Ticks);
  345. System.TimeSpan ts2 = new System.TimeSpan(newTime.Ticks);
  346. System.TimeSpan tsSub = ts1.Subtract(ts2).Duration();
  347. return tsSub.TotalSeconds;
  348. }
  349. /// <summary>
  350. /// 获取闯关用时
  351. /// </summary>
  352. /// <returns></returns>
  353. public float GetTimeConsumption()
  354. {
  355. return (float)(endTime - startTime).TotalSeconds;
  356. }
  357. /// <summary>
  358. /// 获取未开始Operation,0表示全部完成
  359. /// </summary>
  360. /// <returns></returns>
  361. public ChallengeProcessElement GetReadyOperation()
  362. {
  363. foreach (var item in challengeProcessElements)
  364. {
  365. if (!item.finish)
  366. {
  367. currentChallengeProcessElement = item;
  368. return item;
  369. }
  370. }
  371. return null;
  372. }
  373. /// <summary>
  374. /// 获取关卡用时
  375. /// </summary>
  376. /// <returns></returns>
  377. public float GetLevelTime()
  378. {
  379. return (float)(endTime - startTime).TotalSeconds;
  380. }
  381. /// <summary>
  382. /// 获取错误次数
  383. /// </summary>
  384. /// <returns></returns>
  385. public int GetErrorCount(bool containNoFinish)
  386. {
  387. int tmpError = 0;
  388. foreach (var item in challengeProcessElements)
  389. {
  390. if (containNoFinish && item.faultCount == 0&&!item.finish)
  391. {
  392. tmpError += 1;
  393. }
  394. else
  395. {
  396. //tmpError += 1;
  397. //错误超出1次都算1次
  398. tmpError += Mathf.Clamp(item.faultCount, 0, 1);
  399. }
  400. }
  401. return tmpError;
  402. }
  403. /// <summary>
  404. /// 切换到指定步骤
  405. /// </summary>
  406. public void StartOperationByID(ChallengeProcessElement challengeProcessElement)
  407. {
  408. ProcessManagement.Instance.JumpProcessState(int.Parse(challengeProcessElement.stepInfo.id));
  409. ProcessManagement.Instance.InitProcess();
  410. }
  411. }
  412. [Serializable]
  413. public class ChallengeProcessElement
  414. {
  415. /// <summary>
  416. /// 错误次数
  417. /// </summary>
  418. public int faultCount = 0;
  419. /// <summary>
  420. /// 操作时间
  421. /// </summary>
  422. public DateTime operationTime;
  423. /// <summary>
  424. /// 错误原因
  425. /// </summary>
  426. public string errorReason;
  427. /// <summary>
  428. /// 截图名称
  429. /// </summary>
  430. public List<string> screenShotNames = new List<string>();
  431. /// <summary>
  432. /// 步骤信息
  433. /// </summary>
  434. public OperationStepDataInfo stepInfo;
  435. /// <summary>
  436. /// 是否完成
  437. /// </summary>
  438. [Sirenix.OdinInspector.ReadOnly]
  439. public bool finish = false;
  440. /// <summary>
  441. /// 正在上传的任务
  442. /// </summary>
  443. public List<string> m_UpLoading = new List<string>();
  444. }