using DefaultNamespace.ProcessMode; using Framework.ProcessMode; using MotionFramework; using Newtonsoft.Json; using SGUnitySDK; using SGUnitySDK.Configs; using SGUnitySDK.Etys; using SGUnitySDK.Services.HTTP; using SGUnitySDK.Services.SGStartParams; using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Text; using UnityEngine; using UnityEngine.UI; public class LoadConfigNew : MonoBehaviour { public static LoadConfigNew loadConfigNew; /// /// 启动参数 /// List infos; /// /// 启动信息 /// public SGAppStartMode startMode; /// /// 平台人员信息 /// public MyUserData userData; /// /// /// public string testMode; /// /// /// public string testToken; /// /// /// public string strAnsers; public List sGAnswerMies = new List(); /// /// 案例编号 /// public int examNum; /// /// 考试信息 /// public CreatedAtExam createdAtExam; /// /// 倒计时显示 /// public Text currentTimeText; public int inputSeconds = 3661; // 举例:3661秒 private string strmain; public string[] strings; private void Awake() { if (LoadConfigNew.loadConfigNew == null) { loadConfigNew = this; } else { Destroy(gameObject); } } void Start() { // DontDestroyOnLoad(this); ////infos = Environment.GetCommandLineArgs().ToList(); ////string[] commandLineArgs = Environment.GetCommandLineArgs(); ////// 聚合命令行参数(忽略第一个元素,即应用程序路径) //////text2.text = "参数: "; ////strmain += string.Join(", ", commandLineArgs.Skip(1)); ////Debug.Log(strmain); ////strings = RemoveWhitespaceAndNewlines(strmain).Split(','); ////if (strings.Length == 2) ////{ //// testMode = strings[0]; //// testToken = strings[1]; //// Debug.Log("获取到mode:" + testMode); //// Debug.Log("获取到Token:" + testToken); ////} // string mod = "eyJtb2RlIjozLCJwbGFuTG9jYWxQYXRoIjoiQzpcXFVzZXJzXFxQdWJsaWNcXE53dFxcY2FjaGVcXHJlY3ZcXOWNouS9s+WBpVxc5Lu/55yf6LWE5rqQ5a+55o6l5pa55qGI77yIMjAyNOeJiO+8iVxc5qGI5L6L5qC35byPXFxjb25maWcuemlwIiwicHJhY3Rpc2VJZCI6Ii0xIiwic3R1VXNlcklkIjoiMjc0IiwiYXBwSWQiOiI0MiIsImV4YW1JZCI6IjI1IiwidGVhY2hwbGFuSWQiOiIxMjMiLCJjb3Vyc2"; // string token = "a64ddf9b-e5c8-474a-abb2-9b1257105e97"; // string url = "http://localhost:8099"; // SGUSdk sGUSdk = new SGUSdk(); // sGUSdk.InitSDKWeb(mod, token, url); // sGUSdk.GetAppStartMode().getTeachplanId(); StartExam(); } private void Update() { if (Input.GetKeyDown(KeyCode.K)) { GetUploadExamAnswer(); } //if (Input.GetKeyDown(KeyCode.L)) //{ // EndExamSevice(); //} } string RemoveWhitespaceAndNewlines(string input) { // 移除所有空格、制表符和换行符 return input.Replace("-mode, ", "").Replace(", -token, ", ","); } public void StartExam() { SGStartParamsService.GetInstance().Init(testMode, testToken); SGUConfig config = new SGUConfig(); SGUSdk.GetInstance().InitSDK(config); startMode = SGUSdk.GetInstance().GetAppStartMode(); Debug.Log("启动信息:" + JsonConvert.SerializeObject(startMode)); //获取用户信息 HttpAuthService getUserInfo = new HttpAuthService(); HttpService.UpdateServerUrl("http://localhost:8099"); //ResponObject responObject2 = HttpExamService.GetInstance().GetExamInfo(80); //Debug.Log(responObject2.code); Debug.Log("rooturl:" + SGStartParamsService.GetInstance().GetStartMode().rootUrlPath); ResponObject responObject1 = getUserInfo.GetUserInfo(); if (responObject1.code == "0") { string data1 = responObject1.data.ToString(); Debug.Log("GetUserInfo:" + data1); userData = JsonConvert.DeserializeObject(data1); Debug.Log("agencyId" + userData.agencyId); //判断模式 if (startMode.examId > 0) { //考试 Debug.Log("考试模式:" + startMode.examId); HttpExamService getPractiseInfo = new HttpExamService(); ResponObject responObject = getPractiseInfo.GetExamInfo(startMode.examId); string data2 = responObject.data.ToString(); Debug.Log("获取考试详情1:" + data2); createdAtExam = JsonConvert.DeserializeObject(data2); Debug.Log("获取考试详情2:" + data2); inputSeconds = (int)createdAtExam.left_time; Debug.Log("获取考试时间:" + inputSeconds); InvokeRepeating(nameof(CountDown), 5, 1); if (responObject.code == "0") { ResponObject respon = HttpExamService.GetInstance().StartExam(startMode.examId, userData.id); string data3 = respon.data.ToString(); Debug.Log(data3); GetZip(); } else { Debug.LogError("获取考试失败:" + responObject.msg); } } else if (startMode.practiseId > 0) { Debug.Log("练习模式:" + startMode.practiseId); } } else { Debug.LogError("获取用户失败:" + responObject1.msg); } } // /// // /// 提交成绩 // /// // /// // public IEnumerator LoadGetUploadExamAnswer(List studentAndExams) // { // yield return new WaitForSeconds(0.1f); // Debug.Log("teachplanId" + startMode?.teachplanId); // if (startMode != null) // sGAnswerMies[0].LessonPlanId = startMode.teachplanId; // for (int i = 0; i < studentAndExams.Count; i++) // { // SGAnswerInfoMy sGAnswerInfoMy = new SGAnswerInfoMy(); // sGAnswerInfoMy.EventId = examNum; // sGAnswerInfoMy.EventTitle = studentAndExams[i].kaodian; // sGAnswerInfoMy.AutoScore = studentAndExams[i].defen; // sGAnswerInfoMy.ManualScore = 0f; // List
detailsList = JsonConvert.DeserializeObject>(studentAndExams[i].r1); // // 创建 LinkedList // LinkedList
detailsLinkedList = new LinkedList
(); // // // 将列表元素添加到链表中 // foreach (var detail in detailsList) // { // detailsLinkedList.AddLast(detail); // } // Debug.Log(studentAndExams[i].r1); // if (detailsLinkedList != null) // { // List StepArr = new List(); // foreach(var details in detailsLinkedList) // { // SGStepMy sGStepMy = new SGStepMy(); // sGStepMy.StepName = details.daan; // sGStepMy.TotalScore = details.fenzhi; // sGStepMy.Score = details.dsc == "未完成" ? 0 : details.fenzhi; // StepArr.Add(sGStepMy); // } // sGAnswerInfoMy.StepArr = StepArr; // } // sGAnswerMies[0].AnswerInfo.Add(sGAnswerInfoMy); // if (i == studentAndExams.Count - 1) // GetUploadExamAnswer(); // } // } /// /// 提交考试 - 参考FileComponent.cs的逻辑,从ProcessManager获取流程数据并转换为目标格式提交 /// [ContextMenu("GetUploadExamAnswer")] private void GetUploadExamAnswer() { // 获取流程管理器 var processManager = MotionEngine.GetModule(); if (processManager == null) { Debug.LogError("ProcessManager未初始化,无法提交考试"); return; } // 获取当前流程集合中的所有步骤 var steps = processManager.CurrentProcessCollection?.Steps; if (steps == null || steps.Count == 0) { Debug.LogError("流程步骤为空,无法提交考试"); return; } // 从config.json加载的事件数据中获取事件信息 string jsonContent = File.ReadAllText(Path.Combine(Application.streamingAssetsPath, jsonFileName)); EventDataMy events1 = JsonConvert.DeserializeObject(jsonContent); if (events1 == null) { Debug.LogError("事件数据为空,无法提交考试"); return; } ////// 使用第一个事件数据(或根据examNum匹配) //EventDataMy eventData = events1.FirstOrDefault(e => e.eventid == examNum) ?? events1[0]; //// 转换为目标格式(参考用户提供的JSON格式) EventDataSubmit eventDataSubmit = ConvertProcessStepsToEventDataSubmit(steps, processManager, events1); //if (eventDataSubmit == null) //{ // Debug.LogError("转换流程数据失败,无法提交考试"); // return; //} // 输出新格式的JSON用于调试 List eventDataSubmitList = new List { eventDataSubmit }; string newFormatJson = JsonConvert.SerializeObject(eventDataSubmitList); Debug.Log("新格式提交数据:" + newFormatJson); //Events events = new Events { }; //events.events = new List() { eventDataSubmit }; //string newFormatJson = JsonConvert.SerializeObject(events); //Debug.Log("新格式提交数据:" + newFormatJson); //// 转换为SDK格式并提交 List sgAnswers = ConvertEventDataSubmitToSGAnswer(eventDataSubmitList); //List sgAnswers = ConvertEventDataSubmitToSGAnswer(events.events); if (sgAnswers != null && sgAnswers.Count > 0) { Debug.Log("转换后的SDK格式数据:" + JsonConvert.SerializeObject(sgAnswers)); HttpExamService getPractiseInfo = new HttpExamService(); Debug.Log("考试ID:" + startMode.examId); Debug.Log("用户ID:" + userData.id); //SGStartParamsService.GetInstance().GetStartMode().rootUrlPath= "http://localhost:8099"; ResponObject responObject = getPractiseInfo.UploadAnswer(startMode.examId, userData.id, "{\r\n\t\"prac_info_id\": 91003,\r\n\t\"user_id\": 10019,\r\n\t\"answer_list\": [{\r\n\t\t\"lesson_plan_id\": 10078,\r\n\t\t\"workconditions\": \"\",\r\n\t\t\"veto\": 0,\r\n\t\t\"rule\": \"\",\r\n\t\t\"answer_info\": [{\r\n\t\t\t\"eventTitle\": \"取用10KV验电棒 \",\r\n\t\t\t\"eventid\": “27”,\r\n\t\t\t\"auto_score\": 89.0,\r\n\t\t\t\"manual_score\": 0.0,\r\n\t\t\t\"veto\": 0,\r\n\t\t\t\"res\": \"\",\r\n\t\t\t\"stepArr \": [{\r\n\t\t\t\t\"stepName\": \"设备选择\",\r\n\t\t\t\t\"score\": 20,\r\n\t\t\t\t\"totalScore\": 10\r\n\t\t\t}, {\r\n\t\t\t\t\"stepName\": \"检查材料\",\r\n\t\t\t\t\"score\": 15,\r\n\t\t\t\t\"totalScore\": 10\r\n\t\t\t}]\r\n\t\t}, {\r\n\t\t\t\"eventTitle\": \"工单填写 \",\r\n\t\t\t\"eventid\": “2”,\r\n\t\t\t\"auto_score\": 89.0,\r\n\t\t\t\"manual_score\": 0.0,\r\n\t\t\t\"veto\": 0,\r\n\t\t\t\"res\": \"\",\r\n\t\t\t\"stepArr \": [{\r\n\t\t\t\t\t\"stepName\": \"设备选择\",\r\n\t\t\t\t\t\"score\": 20,\r\n\t\t\t\t\t\"totalScore\": 10\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"stepName\": \"检查材料\",\r\n\t\t\t\t\t\"score\": 15,\r\n\t\t\t\t\t\"totalScore\": 10\r\n\t\t\t\t}\r\n\t\t\t]\r\n\t\t}]\r\n\t}]\r\n}\r\n"); Debug.Log("提交成绩响应:" + JsonConvert.SerializeObject(responObject)); if (responObject.code == "0") { string data = responObject.data.ToString(); Debug.Log("提交考试成绩成功:" + data); EndExamSevice(); } else { Debug.LogError("提交考试成绩失败:" + responObject.msg); } } else { Debug.LogError("转换SDK格式失败,无法提交"); } } /// /// 将流程步骤转换为目标格式(参考FileComponent.cs的逻辑) /// /// 流程步骤列表 /// 事件数据 /// 流程管理器 /// 转换后的事件提交数据 private EventDataSubmit ConvertProcessStepsToEventDataSubmit(List steps, ProcessManager processManager, EventDataMy eventData = null) { if (steps == null /*|| eventData == null*/) { Debug.LogError("输入参数为空,无法转换"); return null; } EventDataSubmit eventDataSubmit = new EventDataSubmit(); // 设置事件基本信息 eventDataSubmit.eventTitle = eventData.eventTitle; eventDataSubmit.eventid = eventData.eventid; eventDataSubmit.totalscore = eventData.totalscore; eventDataSubmit.workconditions = eventData.workconditions ?? ""; eventDataSubmit.veto = eventData.veto; eventDataSubmit.stepArr = new List(); // 转换步骤数据(参考FileComponent.cs中遍历步骤的逻辑) for (int stepIndex = 0; stepIndex < steps.Count; stepIndex++) { var step = steps[stepIndex]; StepDataSubmit stepData = new StepDataSubmit(); stepData.stepName = step.StepDescription ?? ""; // 计算步骤分数(参考FileComponent.cs的逻辑) float stepScore = (float)step.Score; int actionCount = step.Actions.Count; // 计算每个动作的分数 float actionScorePerAction = 0f; if (actionCount > 0) { actionScorePerAction = stepScore / (float)actionCount; } // 计算步骤实际得分(累加所有动作的实际得分) float stepActualScore = 0f; for (int actionIndex = 0; actionIndex < step.Actions.Count; actionIndex++) { var action = step.Actions[actionIndex]; // 计算每个答案的分数 int answerCount = GetTotalQuestionsCount(action); float answerScorePerAnswer = 0f; if (answerCount > 0) { answerScorePerAnswer = actionScorePerAction / (float)answerCount; } // 计算动作实际得分(考虑错误扣分) float actionActualScore = 0; if (action.IsCompleted) { var currentActionErrors = processManager._incorrectClicksPerStep .Where(kvp => kvp.Key.stepIndex == stepIndex && kvp.Key.actionIndex == actionIndex) .SelectMany(kvp => kvp.Value) .ToList(); if (currentActionErrors.Count > 0) { // 每个错误答案扣一个答案的分数 float totalDeduction = answerScorePerAnswer * (float)currentActionErrors.Count; totalDeduction = Math.Min(totalDeduction, actionScorePerAction); // 扣分不超过动作总分 actionActualScore = Math.Max(0, actionScorePerAction - totalDeduction); } else { actionActualScore = actionScorePerAction; } } stepActualScore += actionActualScore; } // 转换为整数分数 stepData.score = (int)Math.Round(stepActualScore); eventDataSubmit.stepArr.Add(stepData); } // 如果totalscore为0,则从步骤分数累加 if (eventDataSubmit.totalscore == 0 && eventDataSubmit.stepArr.Count > 0) { eventDataSubmit.totalscore = eventDataSubmit.stepArr.Sum(s => s.score); } return eventDataSubmit; } /// /// 获取动作的总题目数量(参考FileComponent.cs的逻辑) /// /// 动作对象 /// 题目总数 private int GetTotalQuestionsCount(ProcessStepDescription action) { switch (action.ActionType) { case ProcessActionType.默认: return action.TargetObjects?.Count ?? 0; case ProcessActionType.判断题: return action.JudgmentQuestions?.Count ?? 0; case ProcessActionType.多选题: return action.MultipleChoiceQuestions?.Count ?? 0; default: return 0; } } /// /// 将新格式的事件提交数据转换为SDK的SGAnswer格式 /// /// 新格式的事件数据列表 /// SDK格式的答案列表 private List ConvertEventDataSubmitToSGAnswer(List eventDataSubmitList) { if (eventDataSubmitList == null || eventDataSubmitList.Count == 0) { Debug.LogError("事件数据列表为空,无法转换"); return null; } List sgAnswers = new List(); // 获取教学计划ID int lessonPlanId = startMode?.teachplanId ?? 0; List answerInfos = new List(); foreach (var eventData in eventDataSubmitList) { // 计算自动评分总分(从步骤分数累加) double autoScore = eventData.stepArr?.Sum(s => s.score) ?? 0; List stepArrs = new List(); if (eventData.stepArr != null) { foreach (var step in eventData.stepArr) { // 使用score作为Score和TotalScore(因为新格式只有score字段) SGStep sGStep = new SGStep(step.stepName, step.score, step.score); stepArrs.Add(sGStep); } } // 创建答案信息 SGAnswerInfo sGAnswerInfo = new SGAnswerInfo( eventData.eventid.ToString(), // EventId转换为字符串 eventData.eventTitle, // EventTitle autoScore, // AutoScore 0, // ManualScore eventData.veto, // Veto eventData.workconditions, // Res stepArrs // StepArr ); answerInfos.Add(sGAnswerInfo); } // 创建答案对象 SGAnswer sGAnswer = new SGAnswer(lessonPlanId, answerInfos); sgAnswers.Add(sGAnswer); return sgAnswers; } /// /// 结束考试 /// public void EndExamSevice() { HttpExamService getPractiseInfo = new HttpExamService(); ResponObject responObject = getPractiseInfo.EndExam(startMode.examId, userData.id); string data = responObject.data.ToString(); Debug.Log("结束考试" + data); Application.Quit(); } //private string zipPath = "E:\\项目资料\\泰州仓储安全\\仿真资源对接方案(2024版)\\Web端资源接入\\config.zip"; private string jsonFileName = "config.json"; private string streamingAssetsPath; void GetZip() { streamingAssetsPath = Path.Combine(Application.streamingAssetsPath, jsonFileName); string extractPath = Path.Combine(Path.GetTempPath(), "ConfigExtract"); Debug.Log(extractPath); // 删除已存在的文件 if (File.Exists(Path.Combine(extractPath, jsonFileName))) { File.Delete(Path.Combine(extractPath, jsonFileName)); } ZipFile.ExtractToDirectory(startMode.planLocalPath, extractPath); string jsonFilePath = Path.Combine(extractPath, jsonFileName); // 删除已存在的文件 if (File.Exists(streamingAssetsPath)) { File.Delete(streamingAssetsPath); } // 复制新文件到 StreamingAssets File.Copy(jsonFilePath, streamingAssetsPath); string jsonContent = File.ReadAllText(streamingAssetsPath); EventDataMy events = JsonConvert.DeserializeObject(jsonContent); //EventDataMy[] events = JsonConvert.DeserializeObject(jsonContent); //foreach (var eventData in events) //{ // Debug.Log("eventid: " + eventData.eventid); // examNum = eventData.eventid; // break; // 只取第一个事件 //} } /// /// 倒计时 /// public void CountDown() { Debug.Log("left_time:" + createdAtExam.left_time); //Debug.Log("剩余时间: " + inputSeconds); inputSeconds--; // currentTimeText.text = FormatCountdown(inputSeconds); // 如果当前时间在目标时间前10秒内,调用 Add() 方法 if (inputSeconds <= 0) { CancelInvoke(nameof(CountDown)); Debug.Log("提交试卷"); //ModelControl.instance.SubmitConfirm(); } } // 将 TimeSpan 格式化为天数、小时、分钟、秒的字符串 string FormatTimeSpan(TimeSpan timeSpan) { return string.Format("{0:D2}:{1:D2}:{2:D2}", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds); } // 方法:接收秒数并输出格式化的倒计时时间 public string FormatCountdown(int totalSeconds) { // 获取小时、分钟和秒数 int hours = totalSeconds / 3600; int minutes = (totalSeconds % 3600) / 60; int seconds = totalSeconds % 60; // 格式化为 "00:00:00" 的形式并返回 return string.Format("{0:D2}:{1:D2}:{2:D2}", hours, minutes, seconds); } } [System.Serializable] public class StepMy { public string stepName; public int score; } [System.Serializable] public class EventDataMy { public string eventTitle = "测试"; public long eventid= 27; public int totalscore; public string workconditions; public int veto; public StepMy[] stepArr; } /// /// 人员数据 /// [System.Serializable] public class MyUserData { public long id; public string name; public string avatar; public string mobile; public string mail; public string login_code; public string roleName; public string sRoleId; public string agencyId; public string agencyName; } [System.Serializable] public class ExamNum { /// /// /// public int examinee_num; /// /// /// public int join_exam_num; /// /// /// public int check_num; } [System.Serializable] public class RootExamInfo { /// /// /// public string exam_room; /// /// /// public string code; /// /// /// public ExamNum examNum; /// /// /// public double pass_socre; /// /// /// public string agency_code; /// /// /// public int? hidden_question; /// /// /// public string remark; /// /// 电力调度员(配网) /// public string profession_name; /// /// /// public int duration; /// /// /// public DateTime createdAt; /// /// /// public string left_time; /// /// /// public DateTime pushed_time; /// /// /// public int? start_enter; /// /// /// public int? open_join; /// /// /// public int? id; /// /// /// public int? app_id; /// /// /// public DateTime updatedAt; /// /// 国网江苏省电力有限公司 /// public string agency_name; /// /// /// public int? open_type; /// /// /// public int? push_task; /// /// 电力调度控制中心 /// public string department_name; /// /// /// public List lessonArr; /// /// /// public DateTime end_time; /// /// /// public DateTime ready_start_time; /// /// /// public int? ready_start; /// /// /// public int? create_uid; /// /// /// public string exam_icon; /// /// /// public int? approve_rid; /// /// /// public DateTime start_time; /// /// /// public string app_name; /// /// /// public int? approve_uid; /// /// /// public string name; /// /// /// public int? status; } [System.Serializable] public class SGAnswerMy { public int LessonPlanId; public List AnswerInfo; } [System.Serializable] public class SGAnswerInfoMy { public string EventId; public string EventTitle; public double AutoScore; public double ManualScore; public int Veto; public string Res; public List StepArr; } [System.Serializable] public class SGStepMy { public string StepName; public double TotalScore; public double Score; } /// /// 事件提交数据(新格式,匹配目标JSON结构) /// [System.Serializable] public class EventDataSubmit { /// /// 事件标题 /// public string eventTitle; /// /// 事件ID /// public long eventid=27; /// /// 总分 /// public int totalscore=100; /// /// 工作条件 /// public string workconditions; /// /// 否决标志 /// public int veto; /// /// 步骤数组 /// public List stepArr; } public class Events { public List events; public string[] models = new string[] { }; } /// /// 步骤提交数据(新格式) /// [System.Serializable] public class StepDataSubmit { /// /// 步骤名称 /// public string stepName; /// /// 步骤分数 /// public int score; } [System.Serializable] public class CreatedAtExam { /// /// /// public string createdAt; /// /// /// public string updatedAt; /// /// /// public int? ready_start; /// /// /// public string start_time; /// /// /// public string end_time; /// /// /// public int? id; /// /// /// public double pass_socre; /// /// /// public int? app_id; /// /// /// public int? create_uid; /// /// /// public int? start_enter; /// /// /// public int? open_type; /// /// /// public int? push_task; /// /// /// public int? open_join; /// /// /// public string agency_code; /// /// 泰州作业考试 /// public string name; /// /// /// public string exam_icon; /// /// /// public int? exam_room_id; /// /// /// public string code; /// /// /// public string remark; /// /// /// public int? hidden_question; /// /// /// public int? develop_unit; /// /// /// public ExamNum examNum; /// /// /// public string ready_start_time; /// /// /// public string exam_room; /// /// /// public string pushed_time; /// /// /// public int? status; /// /// /// public int? approve_uid; /// /// /// public int? approve_rid; /// /// /// public int? duration; /// /// public double left_time; /// /// 泰州仓储作业资源 /// public string app_name; /// /// /// public int? app_type_id; /// /// /// public int? is_web; /// /// /// public string web_url; /// /// 建设部 /// public string department_name; /// /// 变电二次安装工 /// public string profession_name; /// /// 电网仿真 /// public string app_type_name; /// /// 国网江苏省电力有限公司 /// public string agency_name; /// /// /// public List lessonArr; }