1118OPSSNew/Assets/Editor/QuestionProfileBatchImporte...

346 lines
13 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
using SK.Framework;
using Newtonsoft.Json;
[System.Serializable]
public class QuestionJson
{
public string type;
public string question;
public List<string> options;
public string answer;
public List<string> answers;
public string explanation;
}
public static class QuestionProfileBatchImporter
{
[MenuItem("Tools/Import Questions/One Profile Per JSON (All Types)")]
public static void ImportEachJsonAsProfile()
{
string folder = EditorUtility.OpenFolderPanel("选择 JSON 文件夹", Application.dataPath, "");
if (string.IsNullOrEmpty(folder)) return;
string[] jsonFiles = Directory.GetFiles(folder, "*.json", SearchOption.TopDirectoryOnly);
if (jsonFiles.Length == 0)
{
EditorUtility.DisplayDialog("提示", "该文件夹中没有 JSON 文件", "OK");
return;
}
string saveFolder = EditorUtility.SaveFolderPanel("选择保存目录", Application.dataPath, "");
if (string.IsNullOrEmpty(saveFolder)) return;
string relativeSaveFolder = FileUtil.GetProjectRelativePath(saveFolder);
if (string.IsNullOrEmpty(relativeSaveFolder))
{
EditorUtility.DisplayDialog("错误", "选择的保存目录不在当前 Unity 项目内", "OK");
return;
}
int totalFiles = 0;
int singleCount = 0;
int multiCount = 0;
int judgeCount = 0;
foreach (string file in jsonFiles)
{
try
{
string json = File.ReadAllText(file);
// 直接解析为 QuestionJson 列表(数组格式)
List<QuestionJson> questions = JsonConvert.DeserializeObject<List<QuestionJson>>(json);
if (questions == null || questions.Count == 0)
{
Debug.LogWarning($"文件没有有效题目: {Path.GetFileName(file)}");
continue;
}
var profile = ScriptableObject.CreateInstance<QuestionsProfile>();
profile.SingleChoices = new List<SingleChoiceQuestion>();
profile.MultipleChoices = new List<MultipleChoiceQuestion>();
profile.Judges = new List<JudgeQuestion>();
int seqSingle = 1;
int seqMulti = 1;
int seqJudge = 1;
foreach (var q in questions)
{
string type = string.IsNullOrEmpty(q.type) ? "single" : q.type.ToLower();
if (type == "single")
{
var single = new SingleChoiceQuestion
{
Sequence = seqSingle++,
Question = q.question,
Analysis = q.explanation ?? "",
choiceType = ChoiceType.Text,
Choices = new List<QuestionChoice>()
};
if (q.options != null)
{
for (int i = 0; i < q.options.Count; i++)
single.Choices.Add(new QuestionChoice(q.options[i], null));
}
single.Answer = ParseAnswerIndex(q.answer, q.options?.Count ?? 0);
profile.SingleChoices.Add(single);
singleCount++;
}
else if (type == "multiple")
{
var multi = new MultipleChoiceQuestion
{
Sequence = seqMulti++,
Question = q.question,
Analysis = q.explanation ?? "",
choiceType = ChoiceType.Text,
Choices = new List<QuestionChoice>(),
Answers = new List<int>()
};
if (q.options != null)
{
for (int i = 0; i < q.options.Count; i++)
multi.Choices.Add(new QuestionChoice(q.options[i], null));
}
if (q.answers != null)
{
foreach (var ans in q.answers)
{
int idx = ParseAnswerIndex(ans, q.options?.Count ?? 0);
if (idx >= 0) multi.Answers.Add(idx);
}
}
profile.MultipleChoices.Add(multi);
multiCount++;
}
else if (type == "judgment")
{
var judge = new JudgeQuestion
{
Sequence = seqJudge++,
Question = q.question,
Analysis = q.explanation ?? "",
Positive = "正确",
Negative = "错误",
Answer = ParseJudgeAnswer(q.answer)
};
profile.Judges.Add(judge);
judgeCount++;
}
else
{
Debug.LogWarning($"未知的题目类型: {q.type},题目: {q.question}");
}
}
string fileName = Path.GetFileNameWithoutExtension(file);
string savePath = Path.Combine(relativeSaveFolder, fileName + ".asset");
// 确保目录存在
string directory = Path.GetDirectoryName(savePath);
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
AssetDatabase.CreateAsset(profile, savePath);
totalFiles++;
Debug.Log($"✅ 成功创建: {savePath} \n(单选题: {profile.SingleChoices.Count}, 多选题: {profile.MultipleChoices.Count}, 判断题: {profile.Judges.Count})");
}
catch (System.Exception e)
{
Debug.LogError($"❌ 处理文件失败: {Path.GetFileName(file)}\n错误: {e.Message}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorUtility.DisplayDialog("导入完成",
$"处理了 {totalFiles}/{jsonFiles.Length} 个 JSON 文件\n" +
$"单选题:{singleCount} 道\n" +
$"多选题:{multiCount} 道\n" +
$"判断题:{judgeCount} 道\n" +
$"保存目录:{relativeSaveFolder}",
"OK");
}
[MenuItem("Tools/Import Questions/Single JSON File")]
public static void ImportSingleJsonFile()
{
string filePath = EditorUtility.OpenFilePanel("选择 JSON 文件", Application.dataPath, "json");
if (string.IsNullOrEmpty(filePath)) return;
string saveFolder = EditorUtility.SaveFolderPanel("选择保存目录", Application.dataPath, "");
if (string.IsNullOrEmpty(saveFolder)) return;
string relativeSaveFolder = FileUtil.GetProjectRelativePath(saveFolder);
if (string.IsNullOrEmpty(relativeSaveFolder))
{
EditorUtility.DisplayDialog("错误", "选择的保存目录不在当前 Unity 项目内", "OK");
return;
}
try
{
string json = File.ReadAllText(filePath);
List<QuestionJson> questions = JsonConvert.DeserializeObject<List<QuestionJson>>(json);
if (questions == null || questions.Count == 0)
{
EditorUtility.DisplayDialog("错误", "JSON 文件中没有有效的题目数据", "OK");
return;
}
var profile = ScriptableObject.CreateInstance<QuestionsProfile>();
profile.SingleChoices = new List<SingleChoiceQuestion>();
profile.MultipleChoices = new List<MultipleChoiceQuestion>();
profile.Judges = new List<JudgeQuestion>();
int seqSingle = 1;
int seqMulti = 1;
int seqJudge = 1;
int singleCount = 0;
int multiCount = 0;
int judgeCount = 0;
foreach (var q in questions)
{
string type = string.IsNullOrEmpty(q.type) ? "single" : q.type.ToLower();
if (type == "single")
{
var single = new SingleChoiceQuestion
{
Sequence = seqSingle++,
Question = q.question,
Analysis = q.explanation ?? "",
choiceType = ChoiceType.Text,
Choices = new List<QuestionChoice>()
};
if (q.options != null)
{
for (int i = 0; i < q.options.Count; i++)
single.Choices.Add(new QuestionChoice(q.options[i], null));
}
single.Answer = ParseAnswerIndex(q.answer, q.options?.Count ?? 0);
profile.SingleChoices.Add(single);
singleCount++;
}
else if (type == "multiple")
{
var multi = new MultipleChoiceQuestion
{
Sequence = seqMulti++,
Question = q.question,
Analysis = q.explanation ?? "",
choiceType = ChoiceType.Text,
Choices = new List<QuestionChoice>(),
Answers = new List<int>()
};
if (q.options != null)
{
for (int i = 0; i < q.options.Count; i++)
multi.Choices.Add(new QuestionChoice(q.options[i], null));
}
if (q.answers != null)
{
foreach (var ans in q.answers)
{
int idx = ParseAnswerIndex(ans, q.options?.Count ?? 0);
if (idx >= 0) multi.Answers.Add(idx);
}
}
profile.MultipleChoices.Add(multi);
multiCount++;
}
else if (type == "judgment")
{
var judge = new JudgeQuestion
{
Sequence = seqJudge++,
Question = q.question,
Analysis = q.explanation ?? "",
Positive = "正确",
Negative = "错误",
Answer = ParseJudgeAnswer(q.answer)
};
profile.Judges.Add(judge);
judgeCount++;
}
}
string fileName = Path.GetFileNameWithoutExtension(filePath);
string savePath = Path.Combine(relativeSaveFolder, fileName + ".asset");
AssetDatabase.CreateAsset(profile, savePath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorUtility.DisplayDialog("导入完成",
$"成功导入: {fileName}\n" +
$"单选题: {singleCount} 道\n" +
$"多选题: {multiCount} 道\n" +
$"判断题: {judgeCount} 道",
"OK");
Debug.Log($"✅ 资源已创建: {savePath}");
}
catch (System.Exception e)
{
EditorUtility.DisplayDialog("错误", $"导入失败: {e.Message}", "OK");
Debug.LogError($"❌ 导入失败: {e}");
}
}
private static int ParseAnswerIndex(string answer, int optionCount)
{
if (string.IsNullOrWhiteSpace(answer)) return -1;
answer = answer.Trim();
char c = char.ToUpperInvariant(answer[0]);
if (c >= 'A' && c < 'A' + optionCount)
return c - 'A';
if (int.TryParse(answer, out int num))
{
int idx = num - 1;
if (idx >= 0 && idx < optionCount) return idx;
if (num >= 0 && num < optionCount) return num;
}
return -1;
}
private static bool ParseJudgeAnswer(string answer)
{
if (string.IsNullOrWhiteSpace(answer)) return false;
answer = answer.Trim().ToLower();
if (answer == "true" || answer == "t" || answer == "正确" || answer == "对" || answer == "√" || answer == "1")
return true;
else if (answer == "false" || answer == "f" || answer == "错误" || answer == "错" || answer == "×" || answer == "0")
return false;
return false;
}
}