ExamManagerForPC.cs 15 KB

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