ExamManager.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. namespace ChivaXR.Op
  2. {
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. using Sirenix.OdinInspector;
  7. using System;
  8. using ChivaXR;
  9. using QFramework.TimeExtend;
  10. public enum DeductionRules
  11. {
  12. //操作错误持续扣分,
  13. 操作错误单扣操作点分
  14. }
  15. public class ExamManager : SerializedMonoSingleton<ExamManager>
  16. {
  17. [ReadOnly]
  18. [LabelText("总分数")]
  19. public int totalScore;
  20. [LabelText("考试时长(分钟)")]
  21. public int examTime;
  22. [ReadOnly]
  23. [LabelText("剩余时长")]
  24. public string remainingDuration;
  25. [LabelText("扣分规则")]
  26. public DeductionRules deductionRules;
  27. [LabelText("课程名称")]
  28. public string courseName;
  29. //用于保存考试所有步骤
  30. [TableList(AlwaysExpanded = true, MaxScrollViewHeight = 300,NumberOfItemsPerPage = 10)]
  31. public List<ExamDataContainer> examDataContainers = new List<ExamDataContainer>();
  32. //计分池(用于保存本次考试选择错误工具或者目标后扣分项)
  33. private List<ExamDataContainer> ScoringPool = new List<ExamDataContainer>();
  34. //计时回调/1s一次(boo:是否完成、 string:解析后的时间(格式:00:00:00))
  35. public event Action<bool, string> timeHandle;
  36. //每次扣分的回调
  37. public event Action<ExamDataContainer> deductionScoreHandle;
  38. private void Start()
  39. {
  40. StartExam();
  41. }
  42. /// <summary>
  43. /// 开始一个场考试
  44. /// </summary>
  45. public void StartExam()
  46. {
  47. OperateSetting.Instance.ToolPackUILogic.SetHintButtonActive(false);
  48. OperateSetting.Instance.ToolPackUILogic.SetHint(false);
  49. StartCoroutine(StartTime(examTime * 60, (finish, time) =>
  50. {
  51. remainingDuration = time;
  52. timeHandle?.Invoke(finish, time);
  53. if (finish) StopAllCoroutines();
  54. }));
  55. ScoringPool.Clear();
  56. }
  57. /// <summary>
  58. /// 得到当前减了多少分
  59. /// </summary>
  60. public int GetCurrentScoreReportScore()
  61. {
  62. int tmpReportScore = 0;
  63. foreach (var item in ScoringPool) tmpReportScore += item.score;
  64. return tmpReportScore;
  65. }
  66. /// <summary>
  67. /// 扣除分数
  68. /// </summary>
  69. public void DeductionScore()
  70. {
  71. ExamDataContainer examDataContainer = examDataContainers.Find(t => t.processElement.active);
  72. switch (deductionRules)
  73. {
  74. case DeductionRules.操作错误单扣操作点分:
  75. if (!ScoringPool.Contains(examDataContainer))
  76. {
  77. ScoringPool.Add(examDataContainer);
  78. deductionScoreHandle?.Invoke(examDataContainer);
  79. }
  80. break;
  81. default:
  82. break;
  83. }
  84. }
  85. /// <summary>
  86. /// 分数结算
  87. /// </summary>
  88. public int ScoreSettlement()
  89. {
  90. int tmpTotalScore = totalScore;
  91. foreach (var item in GetExamDataContainers()) tmpTotalScore -= item.score;
  92. StopAllCoroutines();
  93. return tmpTotalScore;
  94. }
  95. /// <summary>
  96. /// 计时器
  97. /// </summary>
  98. /// <returns></returns>
  99. private IEnumerator StartTime(int Seconds,System.Action<bool,string> callBack)
  100. {
  101. while (Seconds > 0)
  102. {
  103. yield return new WaitForSeconds(1);
  104. Seconds--;
  105. //为完成
  106. callBack(false,SerialiTime(Seconds));
  107. }
  108. //完成
  109. callBack(true, SerialiTime(Seconds));
  110. }
  111. /// <summary>
  112. /// 序列化时间
  113. /// </summary>
  114. /// <param name="time"></param>
  115. private string SerialiTime(int time)
  116. {
  117. TimeSpan ts = new TimeSpan(0, 0, Convert.ToInt32(time));
  118. string str = "";
  119. if (ts.Hours > 0)
  120. {
  121. str = String.Format("{0:00}", ts.Hours) + ":" + String.Format("{0:00}", ts.Minutes) + ":" + String.Format("{0:00}", ts.Seconds);
  122. }
  123. if (ts.Hours == 0 && ts.Minutes > 0)
  124. {
  125. str = "00:" + String.Format("{0:00}", ts.Minutes) + ":" + String.Format("{0:00}", ts.Seconds);
  126. }
  127. if (ts.Hours == 0 && ts.Minutes == 0)
  128. {
  129. str = "00:00:" + String.Format("{0:00}", ts.Seconds);
  130. }
  131. return str;
  132. }
  133. #region Editor
  134. [Button("刷新")]
  135. public void RefreshDataInfo()
  136. {
  137. List<ProcessElement> processElements = ProcessManagement.Instance.processes;
  138. for (int i = 0; i < examDataContainers.Count; i++) if (examDataContainers[i].processElement == null) examDataContainers.Remove(examDataContainers[i]);
  139. StepListProxy stepListProxy = DAL.Instance.Get<StepListProxy>();
  140. List<OperationStepDataInfo> operationStepDataInfo = stepListProxy.ReadStepMsgInfoFromTable(courseName);
  141. for (int i = 0; i < processElements.Count; i++)
  142. {
  143. ExamDataContainer tmpExamDataContainers = examDataContainers.Find(t => t.processElement == processElements[i]);
  144. if (tmpExamDataContainers == null) tmpExamDataContainers = new ExamDataContainer(processElements[i], operationStepDataInfo[i].stepName);
  145. else
  146. {
  147. tmpExamDataContainers.Refresh(operationStepDataInfo[i].stepName);
  148. continue;
  149. }
  150. tmpExamDataContainers.id = processElements[i].stepID;
  151. examDataContainers.Add(tmpExamDataContainers);
  152. }
  153. //重新排序
  154. ExamDataContainersShort();
  155. totalScore = 0;
  156. foreach (var item in examDataContainers) totalScore += item.score;
  157. }
  158. /// <summary>
  159. /// 获取扣分以及没有完成的列表
  160. /// </summary>
  161. /// <returns></returns>
  162. public List<ExamDataContainer> GetExamDataContainers()
  163. {
  164. List<ExamDataContainer> tmpExamDataContainers = new List<ExamDataContainer>();
  165. foreach (var item in ScoringPool) tmpExamDataContainers.Add(item);
  166. foreach (var item in examDataContainers)
  167. {
  168. if (!tmpExamDataContainers.Contains(item) && !item.processElement.finished) tmpExamDataContainers.Add(item);
  169. }
  170. return tmpExamDataContainers;
  171. }
  172. private void ExamDataContainersShort()
  173. {
  174. for (int i = 0; i < examDataContainers.Count - 1; i++)
  175. {
  176. for (int j = 0; j < examDataContainers.Count - i - 1; j++)
  177. {
  178. if (examDataContainers[j].id > examDataContainers[j + 1].id)
  179. {
  180. ExamDataContainer temp = examDataContainers[j];
  181. examDataContainers[j] = examDataContainers[j + 1];
  182. examDataContainers[j + 1] = temp;
  183. }
  184. }
  185. }
  186. }
  187. #endregion
  188. }
  189. [Serializable]
  190. public class ExamDataContainer
  191. {
  192. [HideInInspector]
  193. public int id;
  194. [ReadOnly]
  195. public string OpDataName;
  196. [ReadOnly]
  197. public string OpDataDescription;
  198. [ReadOnly]
  199. public ProcessElement processElement;
  200. public int score;
  201. public ExamDataContainer(ProcessElement _processElement, string opDataName)
  202. {
  203. OpDataName = opDataName;
  204. processElement = _processElement;
  205. PB_OpData pbOpData = (PB_OpData)_processElement.processBase;
  206. OpDataDescription = pbOpData.GetPBDescribe();
  207. }
  208. public void Refresh(string opDataName)
  209. {
  210. OpDataName = opDataName;
  211. PB_OpData pbOpData = (PB_OpData)processElement.processBase;
  212. OpDataDescription = pbOpData.GetPBDescribe();
  213. }
  214. }
  215. }