exam_service

This commit is contained in:
SpecialX
2025-06-11 15:02:20 +08:00
parent 97843ab5fd
commit e26881ec2f
52 changed files with 3510 additions and 1174 deletions

View File

@@ -6,244 +6,244 @@ using System.IO; // 用于 XML 反序列化
namespace TechHelper.Client.Exam
{
[XmlRoot("EP")]
public class StringsList
{
//[XmlRoot("EP")]
//public class StringsList
//{
[XmlElement("Q")]
public List<string> Items { get; set; }
}
// [XmlElement("Q")]
// public List<string> Items { get; set; }
//}
// XML 根元素 <EP>
[XmlRoot("EP")]
public class ExamPaper
{
// XML 特性:<QGs> 包含 <QG> 列表
[XmlArray("QGs")]
[XmlArrayItem("QG")]
[JsonProperty("QuestionGroups")]
public List<QuestionGroup> QuestionGroups { get; set; } = new List<QuestionGroup>();
}
//// XML 根元素 <EP>
//[XmlRoot("EP")]
//public class ExamPaper
//{
// // XML 特性:<QGs> 包含 <QG> 列表
// [XmlArray("QGs")]
// [XmlArrayItem("QG")]
// [JsonProperty("QuestionGroups")]
// public List<QuestionGroup> QuestionGroups { get; set; } = new List<QuestionGroup>();
//}
[XmlRoot("QG")]
public class QuestionGroup
{
// JSON 特性
[JsonProperty("题号")]
// XML 特性:作为 <QG Id="X"> 属性
[XmlAttribute("Id")]
public byte Id { get; set; }
//[XmlRoot("QG")]
//public class QuestionGroup
//{
// // JSON 特性
// [JsonProperty("题号")]
// // XML 特性:作为 <QG Id="X"> 属性
// [XmlAttribute("Id")]
// public byte Id { get; set; }
[JsonProperty("标题")]
[XmlElement("T")] // T for Title
public string Title { get; set; }
// [JsonProperty("标题")]
// [XmlElement("T")] // T for Title
// public string Title { get; set; }
[JsonProperty("分值")]
[XmlAttribute("S")] // S for Score
public int Score { get; set; }
// [JsonProperty("分值")]
// [XmlAttribute("S")] // S for Score
// public int Score { get; set; }
[JsonProperty("题目引用")]
[XmlElement("QR")] // QR for QuestionReference作为 <QR> 元素
public string QuestionReference { get; set; } = ""; // 初始化为空字符串
// [JsonProperty("题目引用")]
// [XmlElement("QR")] // QR for QuestionReference作为 <QR> 元素
// public string QuestionReference { get; set; } = ""; // 初始化为空字符串
[JsonProperty("子题目")]
[XmlArray("SQs")] // SQs 包含 <SQ> 列表
[XmlArrayItem("SQ")]
public List<SubQuestion> SubQuestions { get; set; } = new List<SubQuestion>();
// [JsonProperty("子题目")]
// [XmlArray("SQs")] // SQs 包含 <SQ> 列表
// [XmlArrayItem("SQ")]
// public List<SubQuestion> SubQuestions { get; set; } = new List<SubQuestion>();
[JsonProperty("子题组")]
[XmlArray("SQGs")] // SQGs 包含 <QG> 列表 (嵌套题组)
[XmlArrayItem("QG")]
public List<QuestionGroup> SubQuestionGroups { get; set; } = new List<QuestionGroup>();
}
// [JsonProperty("子题组")]
// [XmlArray("SQGs")] // SQGs 包含 <QG> 列表 (嵌套题组)
// [XmlArrayItem("QG")]
// public List<QuestionGroup> SubQuestionGroups { get; set; } = new List<QuestionGroup>();
//}
// 子题目类
public class SubQuestion
{
//// 子题目类
//public class SubQuestion
//{
[JsonProperty("子题号")]
[XmlAttribute("Id")] // Id for SubId
public byte SubId { get; set; }
// [JsonProperty("子题号")]
// [XmlAttribute("Id")] // Id for SubId
// public byte SubId { get; set; }
[JsonProperty("题干")]
[XmlElement("T")] // T for Text (Stem)
public string Stem { get; set; }
// [JsonProperty("题干")]
// [XmlElement("T")] // T for Text (Stem)
// public string Stem { get; set; }
[JsonProperty("分值")]
[XmlAttribute("S")] // S for Score
public int Score { get; set; } // 分值通常为整数
// [JsonProperty("分值")]
// [XmlAttribute("S")] // S for Score
// public int Score { get; set; } // 分值通常为整数
[JsonProperty("选项")]
[XmlArray("Os")] // Os 包含 <O> 列表
[XmlArrayItem("O")]
public List<Option> Options { get; set; } = new List<Option>();
// [JsonProperty("选项")]
// [XmlArray("Os")] // Os 包含 <O> 列表
// [XmlArrayItem("O")]
// public List<Option> Options { get; set; } = new List<Option>();
[JsonProperty("示例答案")]
[XmlElement("SA")] // SA for SampleAnswer
public string SampleAnswer { get; set; } = "";
}
// [JsonProperty("示例答案")]
// [XmlElement("SA")] // SA for SampleAnswer
// public string SampleAnswer { get; set; } = "";
//}
// 选项类,用于适配 <O V="X"/> 结构
public class Option
{
// XML 特性:作为 <O V="X"> 属性
[XmlAttribute("V")] // V for Value
// JSON 特性:如果 JSON 中的选项是 {"Value": "A"} 这样的对象,则需要 JsonProperty("Value")
// 但如果 JSON 选项只是 ["A", "B"] 这样的字符串数组则此Option类不适合JSON Options
// 需要明确你的JSON Options的结构。我假设你JSON Options是 List<string>
// 如果是 List<string>则Options属性在SubQuestion中直接是List<string>Option类则不需要
// 但根据你的精简XML需求Option类是必要的。
// 所以这里需要你自己根据实际JSON Options结构选择。
// 为了兼容XML我会保留Option类但如果JSON是List<string>Options属性会很复杂
public string Value { get; set; }
}
//// 选项类,用于适配 <O V="X"/> 结构
//public class Option
//{
// // XML 特性:作为 <O V="X"> 属性
// [XmlAttribute("V")] // V for Value
// // JSON 特性:如果 JSON 中的选项是 {"Value": "A"} 这样的对象,则需要 JsonProperty("Value")
// // 但如果 JSON 选项只是 ["A", "B"] 这样的字符串数组则此Option类不适合JSON Options
// // 需要明确你的JSON Options的结构。我假设你JSON Options是 List<string>
// // 如果是 List<string>则Options属性在SubQuestion中直接是List<string>Option类则不需要
// // 但根据你的精简XML需求Option类是必要的。
// // 所以这里需要你自己根据实际JSON Options结构选择。
// // 为了兼容XML我会保留Option类但如果JSON是List<string>Options属性会很复杂
// public string Value { get; set; }
//}
// 独立的服务类来处理序列化和反序列化
public static class ExamParser
{
// JSON 反序列化方法
public static List<T> ParseExamJson<T>(string jsonContent)
{
string cleanedJson = jsonContent.Trim();
//// 独立的服务类来处理序列化和反序列化
//public static class ExamParser
//{
// // JSON 反序列化方法
// public static List<T> ParseExamJson<T>(string jsonContent)
// {
// string cleanedJson = jsonContent.Trim();
// 移除可能存在的 Markdown 代码块标记
if (cleanedJson.StartsWith("```json") && cleanedJson.EndsWith("```"))
{
cleanedJson = cleanedJson.Substring("```json".Length, cleanedJson.Length - "```json".Length - "```".Length).Trim();
}
// 移除可能存在的单引号包围(如果 AI 偶尔会这样输出)
if (cleanedJson.StartsWith("'") && cleanedJson.EndsWith("'"))
{
cleanedJson = cleanedJson.Substring(1, cleanedJson.Length - 2).Trim();
}
// // 移除可能存在的 Markdown 代码块标记
// if (cleanedJson.StartsWith("```json") && cleanedJson.EndsWith("```"))
// {
// cleanedJson = cleanedJson.Substring("```json".Length, cleanedJson.Length - "```json".Length - "```".Length).Trim();
// }
// // 移除可能存在的单引号包围(如果 AI 偶尔会这样输出)
// if (cleanedJson.StartsWith("'") && cleanedJson.EndsWith("'"))
// {
// cleanedJson = cleanedJson.Substring(1, cleanedJson.Length - 2).Trim();
// }
try
{
// 注意:这里假设你的 JSON 根直接是一个 QuestionGroup 列表
// 如果你的 JSON 根是 { "QuestionGroups": [...] },则需要先反序列化到 ExamPaper
List<T> examQuestions = JsonConvert.DeserializeObject<List<T>>(cleanedJson);
return examQuestions;
}
catch (JsonSerializationException ex)
{
Console.WriteLine($"JSON 反序列化错误: {ex.Message}");
Console.WriteLine($"内部异常: {ex.InnerException?.Message}");
return null;
}
catch (Exception ex)
{
Console.WriteLine($"处理错误: {ex.Message}");
return null;
}
}
// try
// {
// // 注意:这里假设你的 JSON 根直接是一个 QuestionGroup 列表
// // 如果你的 JSON 根是 { "QuestionGroups": [...] },则需要先反序列化到 ExamPaper
// List<T> examQuestions = JsonConvert.DeserializeObject<List<T>>(cleanedJson);
// return examQuestions;
// }
// catch (JsonSerializationException ex)
// {
// Console.WriteLine($"JSON 反序列化错误: {ex.Message}");
// Console.WriteLine($"内部异常: {ex.InnerException?.Message}");
// return null;
// }
// catch (Exception ex)
// {
// Console.WriteLine($"处理错误: {ex.Message}");
// return null;
// }
// }
#region TEST
[XmlRoot("User")]
public class User
{
[XmlAttribute("id")]
public string Id { get; set; }
// #region TEST
// [XmlRoot("User")]
// public class User
// {
// [XmlAttribute("id")]
// public string Id { get; set; }
[XmlElement("PersonalInfo")]
public PersonalInfo PersonalInfo { get; set; }
// [XmlElement("PersonalInfo")]
// public PersonalInfo PersonalInfo { get; set; }
[XmlArray("Roles")] // 包装元素 <Roles>
[XmlArrayItem("Role")] // 集合中的每个项是 <Role>
public List<Role> Roles { get; set; } = new List<Role>();
// [XmlArray("Roles")] // 包装元素 <Roles>
// [XmlArrayItem("Role")] // 集合中的每个项是 <Role>
// public List<Role> Roles { get; set; } = new List<Role>();
// 构造函数,方便测试
public User() { }
}
// // 构造函数,方便测试
// public User() { }
// }
public class PersonalInfo
{
[XmlElement("FullName")]
public string FullName { get; set; }
// public class PersonalInfo
// {
// [XmlElement("FullName")]
// public string FullName { get; set; }
[XmlElement("EmailAddress")]
public string EmailAddress { get; set; }
// [XmlElement("EmailAddress")]
// public string EmailAddress { get; set; }
// 构造函数,方便测试
public PersonalInfo() { }
}
// // 构造函数,方便测试
// public PersonalInfo() { }
// }
public class Role
{
[XmlAttribute("type")]
public string Type { get; set; }
// public class Role
// {
// [XmlAttribute("type")]
// public string Type { get; set; }
// 构造函数,方便测试
public Role() { }
}
#endregion
// // 构造函数,方便测试
// public Role() { }
// }
// #endregion
// XML 反序列化方法
public static T ParseExamXml<T>(string xmlContent)
{
string cleanedXml = xmlContent.Trim();
if (cleanedXml.StartsWith("'") && cleanedXml.EndsWith("'"))
{
cleanedXml = cleanedXml.Substring(1, cleanedXml.Length - 2);
}
if (cleanedXml.StartsWith("```xml") && cleanedXml.EndsWith("```"))
{
cleanedXml = cleanedXml.Substring("```xml".Length, cleanedXml.Length - "```xml".Length - "```".Length).Trim();
}
// // XML 反序列化方法
// public static T ParseExamXml<T>(string xmlContent)
// {
// string cleanedXml = xmlContent.Trim();
// if (cleanedXml.StartsWith("'") && cleanedXml.EndsWith("'"))
// {
// cleanedXml = cleanedXml.Substring(1, cleanedXml.Length - 2);
// }
// if (cleanedXml.StartsWith("```xml") && cleanedXml.EndsWith("```"))
// {
// cleanedXml = cleanedXml.Substring("```xml".Length, cleanedXml.Length - "```xml".Length - "```".Length).Trim();
// }
XmlSerializer serializer = new XmlSerializer(typeof(T));
// XmlSerializer serializer = new XmlSerializer(typeof(T));
using (StringReader reader = new StringReader(cleanedXml))
{
try
{
T user = (T)serializer.Deserialize(reader);
return user;
}
catch (InvalidOperationException ex)
{
Console.WriteLine($"XML 反序列化操作错误: {ex.Message}");
Console.WriteLine($"内部异常: {ex.InnerException?.Message}");
return default(T);
}
catch (Exception ex)
{
Console.WriteLine($"处理错误: {ex.Message}");
return default(T);
}
}
}
// using (StringReader reader = new StringReader(cleanedXml))
// {
// try
// {
// T user = (T)serializer.Deserialize(reader);
// return user;
// }
// catch (InvalidOperationException ex)
// {
// Console.WriteLine($"XML 反序列化操作错误: {ex.Message}");
// Console.WriteLine($"内部异常: {ex.InnerException?.Message}");
// return default(T);
// }
// catch (Exception ex)
// {
// Console.WriteLine($"处理错误: {ex.Message}");
// return default(T);
// }
// }
// }
public static List<QuestionGroup> ParseExamXmlFormQG(string xmlContent)
{
// 移除可能存在的 Markdown 代码块标记
if (xmlContent.StartsWith("```xml") && xmlContent.EndsWith("```"))
{
xmlContent = xmlContent.Substring("```xml".Length, xmlContent.Length - "```xml".Length - "```".Length).Trim();
}
// public static List<QuestionGroup> ParseExamXmlFormQG(string xmlContent)
// {
// // 移除可能存在的 Markdown 代码块标记
// if (xmlContent.StartsWith("```xml") && xmlContent.EndsWith("```"))
// {
// xmlContent = xmlContent.Substring("```xml".Length, xmlContent.Length - "```xml".Length - "```".Length).Trim();
// }
var serializer = new XmlSerializer(typeof(List<QuestionGroup>), new XmlRootAttribute("QGs"));
// var serializer = new XmlSerializer(typeof(List<QuestionGroup>), new XmlRootAttribute("QGs"));
using (StringReader reader = new StringReader(xmlContent))
{
try
{
List<QuestionGroup> questionGroups = (List<QuestionGroup>)serializer.Deserialize(reader);
return questionGroups;
}
catch (InvalidOperationException ex)
{
Console.WriteLine($"XML 反序列化操作错误: {ex.Message}");
Console.WriteLine($"内部异常: {ex.InnerException?.Message}");
return null;
}
catch (Exception ex)
{
Console.WriteLine($"处理错误: {ex.Message}");
return null;
}
}
}
}
// using (StringReader reader = new StringReader(xmlContent))
// {
// try
// {
// List<QuestionGroup> questionGroups = (List<QuestionGroup>)serializer.Deserialize(reader);
// return questionGroups;
// }
// catch (InvalidOperationException ex)
// {
// Console.WriteLine($"XML 反序列化操作错误: {ex.Message}");
// Console.WriteLine($"内部异常: {ex.InnerException?.Message}");
// return null;
// }
// catch (Exception ex)
// {
// Console.WriteLine($"处理错误: {ex.Message}");
// return null;
// }
// }
// }
//}
}