ExamManagerForPC.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. using ChivaXR;
  2. using ChivaXR.Op;
  3. using I2.Loc;
  4. using QFramework;
  5. using Sirenix.OdinInspector;
  6. using System;
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using UnityEngine;
  11. public enum ErrorReason
  12. {
  13. SelectWrongTool,
  14. SelectWrongTarget
  15. }
  16. public class ExamManagerForPC : MonoBehaviour
  17. {
  18. public static ExamManagerForPC instance;
  19. /// <summary>
  20. /// 考试代理
  21. /// </summary>
  22. public ExamProxy m_ExamProxy;
  23. /// <summary>
  24. /// 记录考试时长
  25. /// </summary>
  26. private int m_RecordExamDuration;
  27. /// <summary>
  28. /// 开始时间
  29. /// </summary>
  30. private DateTime m_StartTime;
  31. /// <summary>
  32. /// 结束时间
  33. /// </summary>
  34. private DateTime m_EndTime;
  35. /// <summary>
  36. /// 允许错误次数
  37. /// </summary>
  38. public int m_maxErrorCount;
  39. private ProcessElement currentProcessElement;
  40. #region 场景配置模块
  41. [BoxGroup("场景配置模块", CenterLabel = true, Order = 0), GUIColor(0, 1, 0, 0.6f)]
  42. [Button("1.获取流程信息")]
  43. public void GetEaxmProcessElements()
  44. {
  45. List<ProcessElement> processElements = ProcessManagement.Instance.processes;
  46. if (m_examProcessElements == null)
  47. {
  48. m_examProcessElements = new List<ExamProcessElement>();
  49. }
  50. ////临时转存,用户数据恢复
  51. List<ExamProcessElement> tmpExamProcessElements = m_examProcessElements;
  52. //重建考试信息列表
  53. m_examProcessElements = new List<ExamProcessElement>();
  54. foreach (var item in processElements)
  55. {
  56. ExamProcessElement examProcessElement = tmpExamProcessElements.Find(t => t.elementDescript == item.processBase.GetPBDescribe());
  57. if (examProcessElement != null)
  58. {
  59. m_examProcessElements.Add(examProcessElement);
  60. }
  61. else
  62. {
  63. StepListProxy tmpProxy = DAL.Instance.Get<StepListProxy>();
  64. OperationStepDataInfo tmpInfo = tmpProxy.GetOpStepDataInfoById(item.stepID);
  65. m_examProcessElements.Add(new ExamProcessElement()
  66. {
  67. id = item.stepID,
  68. elementDescript = item.processBase.GetPBDescribe(),
  69. stepName = tmpInfo.stepName
  70. });
  71. }
  72. }
  73. }
  74. [BoxGroup("场景配置模块", CenterLabel = true, Order = 0), GUIColor(0, 1, 0, 0.6f)]
  75. [Button("2.将所有的CurvedUI和箭头置为禁用(不影响编辑器跳步)")]
  76. public void GetCurvedUIAndDiasable()
  77. {
  78. //将环形UI置为禁用状态
  79. List<ProcessElement> processElements = ProcessManagement.Instance.processes;
  80. //将箭头提示置为禁用状态
  81. JianTouManager.Instance.SetJianTouActive(false);
  82. }
  83. [BoxGroup("场景配置模块", CenterLabel = true, Order = 0), GUIColor(0, 1, 0, 0.6f)]
  84. [Button("3、初始化流程分数")]
  85. public void SetEaxmProcessScore()
  86. {
  87. if (m_examProcessElements.Count <= 0)
  88. {
  89. return;
  90. }
  91. foreach (var item in m_examProcessElements)
  92. {
  93. if (m_examProcessElements.Count <= 100)
  94. {
  95. item.scores = 1;
  96. }
  97. else
  98. {
  99. //item.scores = 100 / examProcessElements.Count;
  100. item.scores = 0.5f;
  101. }
  102. }
  103. RefreshScore();
  104. }
  105. #endregion
  106. [Space(5)]
  107. #region 配分模块
  108. [BoxGroup("配分模块", CenterLabel = true, Order = 1)]
  109. /// <summary>
  110. /// 考试信息
  111. /// </summary>
  112. [TableList(MaxScrollViewHeight = 20)]
  113. public List<ExamProcessElement> m_examProcessElements;
  114. [BoxGroup("配分模块", CenterLabel = true, Order = 1)]
  115. [LabelText("配置总分"), GUIColor(0, 1, 1, 1)]
  116. [Sirenix.OdinInspector.ReadOnly]
  117. public float examSetTotalScore;
  118. [BoxGroup("配分模块", CenterLabel = true, Order = 1)]
  119. [Button("刷新总设定分数")]
  120. public void RefreshScore()
  121. {
  122. examSetTotalScore = 0;
  123. foreach (var item in m_examProcessElements)
  124. {
  125. examSetTotalScore += item.scores;
  126. }
  127. }
  128. #endregion
  129. [Space(5)]
  130. #region 成绩模块
  131. [BoxGroup("成绩模块", CenterLabel = true, Order = 3)]
  132. [LabelText("最终得分"), GUIColor(1, 0.92f, 0.016f, 1)]
  133. [Sirenix.OdinInspector.ReadOnly]
  134. public float score;
  135. [Space(5)]
  136. [BoxGroup("考试时长", CenterLabel = true, Order = 4)]
  137. [LabelText("考试时长(分钟)"), GUIColor(1, 0.1f, 0.016f, 1)]
  138. public int examTime;
  139. #endregion
  140. /// <summary>
  141. /// 是否上传结果
  142. /// </summary>
  143. private bool m_ResultUpload = false;
  144. /// <summary>
  145. /// 服务器下发的分数
  146. /// </summary>
  147. private float m_DistributeScores;
  148. private void Awake()
  149. {
  150. instance = this;
  151. GetEaxmProcessElements();
  152. GetCurvedUIAndDiasable();
  153. //如果没有读到考试数据自动非分/手动配分
  154. AutoEaxmProcessScore();
  155. Init();
  156. }
  157. public void Init()
  158. {
  159. ProcessManagement.Instance.processElementActiveEvent += ProcessElementActive;
  160. ProcessManagement.Instance.processElementDisActiveEvent += ProcessElementDisActive;
  161. ProcessManagement.Instance.processFinishEvent += ExamFinish;
  162. m_ExamProxy = DAL.Instance.Get<ExamProxy>();
  163. m_ExamProxy.StartExam();
  164. m_StartTime = DateTime.Now;
  165. }
  166. /// <summary>
  167. /// 步骤进入
  168. /// </summary>
  169. /// <param name="element"></param>
  170. private void ProcessElementActive(ProcessElement element)
  171. {
  172. currentProcessElement = element;
  173. }
  174. /// <summary>
  175. /// 步骤退出
  176. /// </summary>
  177. /// <param name="element"></param>
  178. private void ProcessElementDisActive(ProcessElement element)
  179. {
  180. JianTouManager.instance.SetJianTouActive(false);
  181. ExamProcessElement tmpElement = m_examProcessElements.Find(t => t.elementDescript == currentProcessElement.processBase.GetPBDescribe());
  182. if (tmpElement.finish == false)
  183. {
  184. tmpElement.finish = true;
  185. tmpElement.result = tmpElement.faultCount > 0 ? false : true;
  186. tmpElement.operationTime = DateTime.Now;
  187. }
  188. SetelementScore();
  189. }
  190. /// <summary>
  191. /// 自动配分
  192. /// </summary>
  193. public void AutoEaxmProcessScore()
  194. {
  195. if (m_examProcessElements.Count <= 0)
  196. {
  197. return;
  198. }
  199. int score = 200 / m_examProcessElements.Count;
  200. int count = 200 % m_examProcessElements.Count;
  201. for (int i = 0; i < m_examProcessElements.Count; i++)
  202. {
  203. if (count > i) m_examProcessElements[i].scores = ((float)score + 1) / 2;
  204. else m_examProcessElements[i].scores = (float)score / 2;
  205. }
  206. RefreshScore();
  207. }
  208. public float GetDistributeScores(StepInfoManager stepInfoManager)
  209. {
  210. float tmpScore = 0;
  211. for (int i = 0; i < m_examProcessElements.Count; i++)
  212. {
  213. m_examProcessElements[i].scores = stepInfoManager.S[i];
  214. }
  215. foreach (var item in stepInfoManager.S)
  216. {
  217. tmpScore += item;
  218. }
  219. RefreshScore();
  220. return tmpScore;
  221. }
  222. /// <summary>
  223. /// 根据接收到的数据进行分数填充
  224. /// </summary>
  225. public void ExamProcessScoreByReceiveData(StepInfoManager stepInfoManager)
  226. {
  227. for (int i = 0; i < m_examProcessElements.Count; i++)
  228. {
  229. m_examProcessElements[i].scores = float.Parse(stepInfoManager.S[i].ToString());
  230. }
  231. }
  232. /// <summary>
  233. /// 记录操作错误
  234. /// </summary>
  235. public void RecordFault(int processId, ErrorReason errorReason)
  236. {
  237. ExamProcessElement tmpElement = m_examProcessElements.Find(t => t.id == processId);
  238. if (tmpElement != null)
  239. {
  240. tmpElement.errorReason = errorReason.ToString();
  241. tmpElement.faultCount++;
  242. m_maxErrorCount--;
  243. UIKit.GetPanel<PC_OperatePanel>().ExamInfo.ErrorCount.text = "x" + m_maxErrorCount.ToString();
  244. if (m_maxErrorCount <= 0)
  245. {
  246. ExamFinish();
  247. }
  248. string screenShotName = DateTime.UtcNow.Ticks.ToString();
  249. Debug.Log(screenShotName);
  250. StartCoroutine(ScrrenCapture(new Rect(0, 0, Screen.width, Screen.height), 0, screenShotName, tmpElement));
  251. }
  252. LocalizedString stepName = processId + "stepName";
  253. string wrongErrson = "操作错误";
  254. switch (errorReason)
  255. {
  256. case ErrorReason.SelectWrongTool:
  257. if (LocalizationManager.CurrentLanguage == "Chinese")
  258. {
  259. wrongErrson = "工器具错误";
  260. }
  261. else
  262. {
  263. wrongErrson = "ToolError";
  264. }
  265. break;
  266. case ErrorReason.SelectWrongTarget:
  267. if (LocalizationManager.CurrentLanguage == "Chinese")
  268. {
  269. wrongErrson = "操作点错误";
  270. }
  271. else
  272. {
  273. wrongErrson = "OperationError";
  274. }
  275. break;
  276. }
  277. UIKit.GetPanel<PC_OperatePanel>().ExamInfo.ShowWrongInfo("<color=#FF9F00>" + stepName + "</color> : " + wrongErrson);
  278. }
  279. /// <summary>
  280. /// 分数结算
  281. /// </summary>
  282. private float SetelementScore()
  283. {
  284. score = 0;
  285. foreach (var item in m_examProcessElements)
  286. {
  287. if (item.finish == true && item.result == true)
  288. {
  289. score += item.scores;
  290. }
  291. }
  292. //StopAllCoroutines();
  293. return score;
  294. }
  295. /// <summary>
  296. /// 上传考核结果
  297. /// </summary>
  298. public void UploadExamResult()
  299. {
  300. ExamProxy examProxy = DAL.Instance.Get<ExamProxy>();
  301. examProxy.UpLoadExamResult(SetelementScore());
  302. m_ResultUpload = true;
  303. }
  304. /// <summary>
  305. /// 成绩展示
  306. /// </summary>
  307. public void ExamFinish()
  308. {
  309. m_EndTime = DateTime.Now;
  310. CountExamDuration();
  311. if (UIKit.GetPanel<PC_OperatePanel>())
  312. {
  313. UIKit.GetPanel<PC_OperatePanel>().ExamEnd(m_examProcessElements, SetelementScore(), m_RecordExamDuration);
  314. }
  315. ProcessManagement.Instance.StopCurrentProcess();
  316. if (!m_ResultUpload)
  317. {
  318. UploadExamResult();
  319. }
  320. if (UIKit.GetPanel<ArrowTipsPanel>())
  321. {
  322. UIKit.GetPanel<ArrowTipsPanel>().Clear();
  323. }
  324. }
  325. /// <summary>
  326. /// 统计考试时长
  327. /// </summary>
  328. private void CountExamDuration()
  329. {
  330. // 记录结束时的时间
  331. DateTime finishTime = DateTime.Now;
  332. m_RecordExamDuration = (int)(finishTime - m_ExamProxy.startTime).TotalSeconds;
  333. }
  334. private void OnDisable()
  335. {
  336. ProcessManagement.Instance.processElementActiveEvent -= ProcessElementActive;
  337. ProcessManagement.Instance.processElementActiveEvent -= ProcessElementDisActive;
  338. ProcessManagement.Instance.processFinishEvent -= ExamFinish;
  339. }
  340. Texture2D screenShot;//保存截取的纹理
  341. IEnumerator ScrrenCapture(Rect rect, int a, string screenShotName, ExamProcessElement examProcessElement)
  342. {
  343. Debug.Log("截图:" + screenShotName);
  344. screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);
  345. yield return new WaitForSeconds(0.5f);
  346. yield return new WaitForEndOfFrame();
  347. screenShot.ReadPixels(rect, 0, 0);
  348. screenShot.Apply();
  349. //推送
  350. //PushHelper.InitBasicData();
  351. //StartCoroutine(PushHelper.SendFileStreamPushRequest(screenShot, screenShotName, (result, msg, flag, cmnAttachId) =>
  352. //{
  353. // if (!result)
  354. // {
  355. // Debug.LogError(msg);
  356. // }
  357. // else
  358. // {
  359. // Debug.Log("考试模块图片上传成功" + cmnAttachId.data.cmnAttachId);
  360. // examProcessElement.screenshotList.Add(cmnAttachId.data.cmnAttachId);
  361. // }
  362. // examProcessElement.m_UpLoading.Remove(screenShotName);
  363. //}));
  364. examProcessElement.m_UpLoading.Add(screenShotName);
  365. }
  366. /// <summary>
  367. /// 获取该ID的分数
  368. /// </summary>
  369. /// <param name="id"></param>
  370. /// <returns></returns>
  371. public float GetScoreById(int id)
  372. {
  373. float tmpScore = 0;
  374. //PullProxy tmpPullProxy = DAL.Instance.Get<PullProxy>();
  375. //StepInfoManager tmpStepInfoManager = tmpPullProxy.GetExamStepInfoManager();
  376. //if (tmpStepInfoManager == null)
  377. //{
  378. // tmpScore = m_examProcessElements[id - 1].scores;
  379. //}
  380. //else
  381. //{
  382. // tmpScore = tmpStepInfoManager.S[id - 1];
  383. //}
  384. return tmpScore;
  385. }
  386. /// <summary>
  387. /// 获取总分比值
  388. /// </summary>
  389. public float GetTotalScore()
  390. {
  391. float tmpTotalScore = 0;
  392. foreach (var item in m_examProcessElements)
  393. {
  394. if (item.finish && item.result)
  395. {
  396. tmpTotalScore += item.scores;
  397. }
  398. }
  399. if (m_DistributeScores == 0)
  400. {
  401. return tmpTotalScore / examSetTotalScore;
  402. }
  403. else
  404. {
  405. float ratio = (float)tmpTotalScore / (float)examSetTotalScore;
  406. return ratio;
  407. }
  408. }
  409. /// <summary>
  410. /// 是否上传完成
  411. /// </summary>
  412. /// <returns></returns>
  413. public bool IsFinishUpLoad()
  414. {
  415. foreach (var item in m_examProcessElements)
  416. {
  417. if (item.m_UpLoading.Count > 0)
  418. {
  419. return false;
  420. }
  421. }
  422. return true;
  423. }
  424. }