CrazyIter_Bin 9 mēneši atpakaļ
vecāks
revīzija
4fa85c89a2

+ 310 - 81
TEAMModelOS.Extension/HTEX.Test/Controllers/LessonRecordController.cs

@@ -5,6 +5,8 @@ using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Extension;
+using StackExchange.Redis;
+using System.Text.RegularExpressions;
 
 namespace HTEX.Test.Controllers
 {
@@ -292,7 +294,12 @@ namespace HTEX.Test.Controllers
                         var studentLessonData = studentLessonDatas.Find(x => x.seatID!.Equals($"{mbr}"));
                         if (studentLessonData!=null)
                         {
-                            studentLessonData.interactRecords.Add(new InteractRecord() { status = InteractStatus.TT, interactType = string.IsNullOrWhiteSpace(item.PickupType) ? "PickupResult" : item.PickupType });
+                            studentLessonData.interactRecords.Add(new InteractRecord() 
+                            {
+                                resultWeight = InteractWeight.TT,
+                                resultType="TT",
+                                interactType = string.IsNullOrWhiteSpace(item.PickupType) ? "PickupResult" : item.PickupType
+                            });
                         }
                     }
                 }
@@ -306,14 +313,53 @@ namespace HTEX.Test.Controllers
             foreach (var irsDataPage in irsDataPages)
             {
                 //检查是否设置正确答案。
-                var answers = irsDataPage.question?["exercise"]?["answer"]?.ToJsonString().ToObject<List<string>>();
+                var answers_q = irsDataPage.question?["exercise"]?["answer"]?.ToJsonString().ToObject<List<string>>();
+                List<string> answers = new List<string>();
+                answers_q?.ForEach(x => {
+                    if (!string.IsNullOrWhiteSpace(x))
+                    {
+                        answers.Add(x);
+                    }
+                });
                 var _objective = irsDataPage.question?["exercise"]?["objective"];
                 var scoreNode = irsDataPage.question?["exercise"]?["score"];
+                var _type = irsDataPage.question?["exercise"]?["type"];
+                var _answerType = irsDataPage.question?["exercise"]?["answerType"];//file,audio,text,image
                 double score = 0;
                 bool objective = false;
+              
                 if (_objective!=null) { 
                     objective = _objective.GetValue<bool>();
                 }
+                //题型
+                string type= string.Empty;
+                if (_type!=null)
+                {
+                    //题型
+                     type  = _type.GetValue<string>();
+                    List<string> types = new List<string>() { "single", "multiple" , "judge" , "sortmultiple" };
+                    if (types.Contains(type))
+                    {
+                        objective = true;
+                    }
+                    else {
+                        objective = false;
+                    }
+                   
+                }
+
+                if (_answerType!=null)
+                {
+                    _answerType.GetValue<string>();
+
+                    //暂不处理,可能存在依然传文字的情况
+                    //不是文本作答的处理,题目不是客观题,答案不记录
+                    //if (!_answerType.Equals("text"))
+                    //{
+                    //    objective=false;
+                    //    answers=new List<string>();
+                    //}
+                }
                 if (scoreNode!=null)
                 {
                     double.TryParse(scoreNode.ToString(), out score);
@@ -344,52 +390,52 @@ namespace HTEX.Test.Controllers
                     //并检查学生集合的长度是否与第一个列表相同
                     if (!isSameLength  && studentLessonDatas.Count()==firstListLength)
                     {
-                        //有设置答案
-                        if (answers.IsNotEmpty())
+                        for (int index = 0; index< clientAnswers[0].Count; index++)
                         {
-                            for (int index = 0; index< clientAnswers[0].Count; index++)
+                            //index  代表学生下标
+                            List<InteractRecord> interactRecords = new List<InteractRecord>();
+                            if (clientAnswers.Count==1)
                             {
-                                //index  代表学生下标
-                                List<InteractRecord> interactRecords = new List<InteractRecord>();
-                                if (clientAnswers.Count==1)
+                                //即问即答
+                                interactType = "PopQuesLoad";
+                                var ans0 = clientAnswers[0][index];
+                                var IS0 = GetInteractResultHasAnswer(answers, ans0, objective,type);
+                                interactRecords.Add(new InteractRecord()
                                 {
-                                    //即问即答
-                                    interactType = "PopQuesLoad";
-                                    var ans0 = clientAnswers[0][index];
-                                    var IS0 = GetInteractResultHasAnswer(answers, ans0);
-                                    interactRecords.Add(new InteractRecord()
-                                    {
-                                        status = IS0,
-                                        interactType= interactType
-                                    });
-                                }
-                                if (clientAnswers.Count==2)
+                                    resultWeight = IS0.weight,
+                                    resultType=IS0.reultType,
+                                    interactType= interactType
+                                });
+                            }
+                            if (clientAnswers.Count==2)
+                            {
+                                //二次作答
+                                interactType="ReAtmpAnsStrt";
+                                var ans1 = clientAnswers[1][index];
+                                var IS1 = GetInteractResultHasAnswer(answers, ans1, objective,type);
+                                interactRecords.Add(new InteractRecord()
                                 {
-                                    //二次作答
-                                    interactType="ReAtmpAnsStrt";
-                                    var ans1 = clientAnswers[1][index];
-                                    var IS1 = GetInteractResultHasAnswer(answers, ans1);
-                                    interactRecords.Add(new InteractRecord()
-                                    {
-                                        status = IS1,
-                                        interactType= interactType
-                                    });
-                                }
-                                if (clientAnswers.Count>2)
+                                    resultWeight = IS1.weight,
+                                    resultType=IS1.reultType,
+                                    interactType= interactType
+                                });
+                            }
+                            if (clientAnswers.Count>2)
+                            {
+                                //三次作答
+                                interactType="TeAtmpAnsStrt";
+                                var ans2 = clientAnswers[2][index];
+                                var IS2 = GetInteractResultHasAnswer(answers, ans2, objective,type);
+                                interactRecords.Add(new InteractRecord()
                                 {
-                                    //三次作答
-                                    interactType="TeAtmpAnsStrt";
-                                    var ans2 = clientAnswers[2][index];
-                                    var IS2 = GetInteractResultHasAnswer(answers, ans2);
-                                    interactRecords.Add(new InteractRecord()
-                                    {
-                                        status = IS2,
-                                        interactType= interactType
-                                    });
-                                }
-                                studentLessonDatas[index].interactRecords.AddRange(interactRecords);
+                                    resultWeight = IS2.weight,
+                                    resultType=IS2.reultType,
+                                    interactType= interactType
+                                });
                             }
+                            studentLessonDatas[index].interactRecords.AddRange(interactRecords);
                         }
+
                     }
                 }
                 //是否抢权作答的模式
@@ -403,13 +449,13 @@ namespace HTEX.Test.Controllers
                         var studentData = studentLessonDatas.Find(x => x.seatID!.Equals(buzzParticipant));
                         if (studentData != null)
                         {
-                            buzzParticipants[buzzParticipant]=new InteractRecord() { status = InteractStatus.T1, interactType= interactType };
+                            buzzParticipants[buzzParticipant]=new InteractRecord() { resultWeight = InteractWeight.T1, interactType= interactType };
                         }
                     }
                     //处理抢权成功的
                     foreach (var buzzClient in irsDataPage.buzzClients)
                     {
-                        buzzParticipants[buzzClient]=new InteractRecord() { status = InteractStatus.TT, interactType= interactType };
+                        buzzParticipants[buzzClient]=new InteractRecord() { resultWeight = InteractWeight.TT, interactType= interactType };
                     }
                     foreach (var studentLessonData in studentLessonDatas)
                     {
@@ -421,61 +467,212 @@ namespace HTEX.Test.Controllers
                         else
                         {
                             //处理未参与抢权的
-                            studentLessonData.interactRecords.Add(new InteractRecord() { status = InteractStatus.T0, interactType = interactType });
+                            studentLessonData.interactRecords.Add(new InteractRecord() { resultWeight = InteractWeight.T0, interactType = interactType });
                         }
                     }
                 }
             }
         }
 
-        private static InteractStatus GetInteractResultHasAnswer(List<string>? answers, List<string> ans0)
+        private static (double weight,string reultType) GetInteractResultHasAnswer(List<string>? answers, List<string> ans0 , bool objective,string type)
         {
-            InteractStatus status = InteractStatus.T0;
-            if (ans0.IsNotEmpty())
+            //List<string> ans0 = new List<string>();
+            //ans?.ForEach(x => {
+            //    if (!string.IsNullOrWhiteSpace(x))
+            //    {
+            //        ans0.Add(x);
+            //    }
+            //    else { ans.Add("");}
+            //});
+            double weight = InteractWeight.T0;
+            string reultType = InteractReultType.T0;
+            if (answers.IsNotEmpty())
             {
-                //标准答案等于作答的结果
-                if (answers!.Count == ans0.Count)
+                if (ans0.IsNotEmpty())
                 {
-                    if (answers.All(item => ans0.Contains(item)))
+                    if (objective) //客观题
                     {
-                        //完全正确
-                        status= InteractStatus.TT;
+                        //标准答案等于作答的结果
+                        if (answers!.Count == ans0.Count)
+                        {
+                            if (answers.All(item => ans0.Contains(item)))
+                            {
+                                //完全正确
+                                weight= InteractWeight.TT;
+                                reultType= InteractReultType.TT;
+                            }
+                            else
+                            {
+                                //作答错误
+                                weight= InteractWeight.T1;
+                                reultType = InteractReultType.T1;
+                            }
+                        }
+                        //标准答案比作答的结果多
+                        else if (answers!.Count > ans0.Count)
+                        {
+                            if (ans0.All(item => answers.Contains(item)))
+                            {
+                                //部分正确
+                                weight= InteractWeight.TP;
+                                reultType = InteractReultType.TP;
+                            }
+                            else
+                            {
+                                //作答错误
+                                weight= InteractWeight.T1;
+                                reultType = InteractReultType.T1;
+                            }
+                        }
+                        //标准答案比作答结果少
+                        else
+                        {
+                            //作答错误
+                            weight= InteractWeight.T1;
+                            reultType = InteractReultType.T1;
+                        }
                     }
                     else
                     {
-                        //作答错误
-                        status= InteractStatus.T1;
+                        //填空题
+                        if ("complete".Equals(type) && answers!.Count==ans0.Count)
+                        {
+                            bool hasT = false;
+                            bool hasF = false;
+                            for (int i = 0; i < answers!.Count; i++) 
+                            {
+                                if (answers[i].Equals(ans0[i]))
+                                {
+                                    hasT=true;
+                                }
+                                else {
+                                    hasF=true;
+                                }
+                            }
+                            if (hasT && !hasF)
+                            {
+                                //完全正确
+                                weight= InteractWeight.TT;
+                                reultType = InteractReultType.TT;
+                            }
+                            else if (hasT && hasF)
+                            {
+                                //部分正确
+                                weight= InteractWeight.TP;
+                                reultType = InteractReultType.TP;
+                            }
+                            else if (!hasT && hasF)
+                            {
+                                //没有正确的,但有错误的,代表参与了
+                                weight= InteractWeight.T1;
+                                reultType = InteractReultType.T1;
+                            }
+                            else if (!hasT && !hasF)
+                            {
+                                //没有正确的,也没有错误的,代表没有作答
+                                weight= InteractWeight.T0;
+                                reultType = InteractReultType.T0;
+                            }
+                        }
+                        else
+                        {  
+                            //主观题,完全匹配的
+                            if (answers!.All(item => ans0.Contains(item)))
+                            {
+                                //完全正确
+                                weight= InteractWeight.TT;
+                                reultType = InteractReultType.TT;
+                            }
+                            else
+                            {   // 使用LINQ查询来判断是否有匹配的答案
+                                bool hasMatchingAnswer = answers!.Intersect(ans0).Any();
+                                if (hasMatchingAnswer)
+                                {
+                                    //主观题回答正确即为完全正确
+                                    weight= InteractWeight.TT;
+                                    reultType = InteractReultType.TT;
+                                }
+                                else
+                                {
+                                    //没有匹配上答案,则采用Levenshtein距离来评估两个字符串的相似度
+                                    var sc = CalculateSimilarity(answers![0], ans0[0]) * 1.0/100 *(InteractWeight.TT-InteractWeight.T1);
+                                    weight = sc;
+                                    reultType = InteractReultType.TP;
+                                }
+                            }
+                        }
                     }
                 }
-                //标准答案比作答的结果多
-                else if (answers!.Count > ans0.Count)
+                else
+                {
+                    //没有作答
+                    weight= InteractWeight.T0;
+                    reultType = InteractReultType.T0;
+                }
+            }
+            else 
+            {
+                //没有答案的情况
+                if (ans0.IsNotEmpty()) 
                 {
-                    if (ans0.All(item => answers.Contains(item)))
+                    bool hasAns = false;
+                    ans0.ForEach(x => {
+                        if (!string.IsNullOrWhiteSpace(x)) { 
+                         hasAns = true;    
+                        }
+                    });
+                    if (hasAns)
                     {
-                        //部分正确
-                        status= InteractStatus.TP;
+                        //作答了
+                        weight= InteractWeight.T1;
+                        reultType = InteractReultType.T1;
                     }
-                    else
-                    {
-                        //作答错误
-                        status= InteractStatus.T1;
+                    else {
+                        //没有作答
+                        weight= InteractWeight.T0;
+                        reultType = InteractReultType.T0;
                     }
+                   
                 }
-                //标准答案比作答结果少
                 else
                 {
-                    //作答错误
-                    status= InteractStatus.T1;
+                    //没有作答
+                    weight= InteractWeight.T0;
+                    reultType = InteractReultType.T0;
                 }
             }
-            else
+            return (weight,reultType);
+        }
+        #region C# 代码 如何判断两句话是否一个意思,非机器学习的算法。使用Levenshtein距离来评估两个字符串的相似度,但是不能判断它们是否表达了同一个意思,后续借助AI实现
+        public static double CalculateSimilarity(string s1, string s2)
+        {
+            int n = s1.Length;
+            int m = s2.Length;
+            int[,] d = new int[n + 1, m + 1];
+            for (int i = 0; i <= n; i++)
             {
-                //没有作答
-                status= InteractStatus.T0;
+                d[i, 0] = i;
+            }
+
+            for (int j = 0; j <= m; j++)
+            {
+                d[0, j] = j;
+            }
+
+            for (int i = 1; i <= n; i++)
+            {
+                for (int j = 1; j <= m; j++)
+                {
+                    int cost = (s1[i - 1] == s2[j - 1]) ? 0 : 1;
+                    d[i, j] = Math.Min(Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), d[i - 1, j - 1] + cost);
+                }
             }
-            return status;
+
+            return (1.0 - ((double)d[n, m] / Math.Max(s1.Length, s2.Length))) * 100;
         }
 
+         
+        #endregion
         /// <summary>
         /// 获取课中评测数据
         /// </summary>
@@ -651,38 +848,70 @@ namespace HTEX.Test.Controllers
 
     public class InteractRecord
     {
+       
+        /// <summary>
+        ///    { "PopQuesLoad", "ReAtmpAnsStrt", "BuzrAns", "BuzrLoad", "PickupResult" };
+        /// </summary>
+        public string? interactType { get; set; }
+        /// <summary>
+        /// 互动结果权重,纳入学习状态计算
+        /// </summary>
+        public double resultWeight { get; set; }
+        /// <summary>
+        /// 互动结果类型,如:T0没有作答, 没有参与,T1作答错误,有参加,有抢权,TP部分正确,TT作答正确,抢权成功,被抽到
+        /// </summary>
+        public string? resultType { get; set; }
+         /// <summary>
+         /// 互动结果分值
+         /// </summary>
+        //public double resultScore { get; set; }
+        /// <summary>
+        ///  互动积分,试题评分
+        /// </summary>
+        public double interactScore { get; set; }
         /// <summary>
         /// 基准分值
         /// </summary>
         public double criterion { get; set; }
+    }
+    public static class InteractReultType 
+    {
         /// <summary>
-        ///    { "PopQuesLoad", "ReAtmpAnsStrt", "BuzrAns", "BuzrLoad", "PickupResult" };
+        /// 没有作答, 没有参与0
         /// </summary>
-        public string? interactType { get; set; }
-
+        public static readonly string T0 = "T0";
         /// <summary>
-        /// 互动结果状态,纳入学习状态计算
+        /// 作答错误,有参加,有抢权1
         /// </summary>
-        public InteractStatus status { get; set; }
+        public static readonly string T1 = "T1";
+        /// <summary>
+        /// 部分正确1.3
+        /// </summary>
+        public static readonly string TP = "TP";
+        /// <summary>
+        /// 作答正确,抢权成功,被抽到1.5
+        /// </summary>
+        public static readonly string TT ="TT";
+
     }
-    public enum InteractStatus
+    public static class InteractWeight 
     {
         /// <summary>
         /// 没有作答, 没有参与0
         /// </summary>
-        T0,
+        public static readonly double T0 = 0;
         /// <summary>
         /// 作答错误,有参加,有抢权1
         /// </summary>
-        T1,
+        public static readonly double T1 = 1;
         /// <summary>
         /// 部分正确1.3
         /// </summary>
-        TP,
+        public static readonly double TP =1.3;
         /// <summary>
-        /// 作答正确,抢权成功,被抽到
+        /// 作答正确,抢权成功,被抽到1.5
         /// </summary>
-        TT
+        public static readonly double TT = 1.5;
 
         /// 互动参与指数(按倍数的权重设计)
         /// 无二次作答的互动,且未设置正确答案:1.未作答0

+ 80 - 3
TEAMModelOS.Extension/HTEX.Test/Program.cs

@@ -1,5 +1,7 @@
 using MathNet.Numerics;
 using System.Configuration;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 namespace HTEX.Test
@@ -37,14 +39,89 @@ namespace HTEX.Test
             app.Run();
         }
 
-        public  static string Test()
+        public static string Test()
         {
-            List<string > a = new List<string>() { "a","d"};
+            string originalString = "这 是 一      个 测 试。\n \r\t  ";
+            string stringWithoutSpaces = Regex.Replace(originalString, @"\s+", "");
+            // 标准答案集合
+            List<string> standardAnswers = new List<string> { "apple", "banana", "cherry" };
+            // 学生作答集合
+            List<string> studentAnswers = new List<string> { "bana1na", "orange", "grape", "111" };
+
+            // 使用LINQ查询来判断是否有匹配的答案
+            bool hasMatchingAnswer = standardAnswers.Intersect(studentAnswers).Any();
+
+            // 输出结果
+            Console.WriteLine("学生答案中是否有符合标准答案的? " + (hasMatchingAnswer ? "是" : "否"));
+
+
+            string sentence1 = "学生答案中是否有符合标准答案的";
+            string sentence2 = "学生答案中是否有标合标准答案的";
+
+            double areSimilar = AreSentencesSimilar(sentence1, sentence2);
+            Console.WriteLine($"Are the sentences similar? {areSimilar}");
+
+            List<string> a = new List<string>() { "a", "d" };
             List<string> b = new List<string>() { "b", "a", "c" };
-            var v = ( a.All(item => b.Contains(item)));
+            var v = (a.All(item => b.Contains(item)));
             string c = "[\r\n  1\r\n]";
             List<int> d = c.ToObject<List<int>>();
             return "Hello World!";
         }
+        public static void  calculate_text_similarity() 
+        {
+            string pythonExe = @"C:\Path\To\Python\python.exe"; // 修改为你的Python解释器路径  
+            string scriptPath = @"C:\Path\To\Your\Script\calculate_similarity.py"; // 修改为你的脚本路径  
+            string text1 = "今天天气真好";
+            string text2 = "今天天气不错";
+
+            ProcessStartInfo start = new ProcessStartInfo();
+            start.FileName = pythonExe;
+            start.Arguments = $"\"{scriptPath}\" \"{text1}\" \"{text2}\"";
+            start.UseShellExecute = false;
+            start.RedirectStandardOutput = true;
+
+            using (Process process = Process.Start(start))
+            {
+                using (StreamReader reader = process.StandardOutput)
+                {
+                    string result = reader.ReadToEnd();
+                    Console.Write(result);
+                }
+            }
+        }
+        public static double CalculateSimilarity(string s1, string s2)
+        {
+            int n = s1.Length;
+            int m = s2.Length;
+            int[,] d = new int[n + 1, m + 1];
+            for (int i = 0; i <= n; i++)
+            {
+                d[i, 0] = i;
+            }
+
+            for (int j = 0; j <= m; j++)
+            {
+                d[0, j] = j;
+            }
+
+            for (int i = 1; i <= n; i++)
+            {
+                for (int j = 1; j <= m; j++)
+                {
+                    int cost = (s1[i - 1] == s2[j - 1]) ? 0 : 1;
+                    d[i, j] = Math.Min(Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), d[i - 1, j - 1] + cost);
+                }
+            }
+
+            return (1.0 - ((double)d[n, m] / Math.Max(s1.Length, s2.Length))) * 100;
+        }
+
+        public static double AreSentencesSimilar(string sentence1, string sentence2)
+        {
+          //  double threshold = 70; // 设置一个阈值,超过这个百分比则认为是相同的句子
+            double similarity = CalculateSimilarity(sentence1, sentence2);
+            return similarity ;
+        }
     }
 }

+ 25 - 0
TEAMModelOS.Extension/HTEX.Test/PythonCode/calculate_similarity.py

@@ -0,0 +1,25 @@
+# calculate_similarity.py  
+import sys  
+import torch  
+from transformers import BertTokenizer, BertModel  
+from torch.nn.functional import cosine_similarity, normalize  
+  
+tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')  
+model = BertModel.from_pretrained('bert-base-chinese')  
+  
+def calculate_text_similarity(text1, text2):  
+    encoded_inputs = tokenizer([text1, text2], padding=True, truncation=True, return_tensors="pt")  
+    with torch.no_grad():  
+        outputs = model(**encoded_inputs)  
+        last_hidden_states = outputs.last_hidden_state  
+    cls_vectors = last_hidden_states[:, 0, :]  
+    cls_vectors_normalized = normalize(cls_vectors, p=2, dim=1)  
+    similarity = cosine_similarity(cls_vectors_normalized[0:1], cls_vectors_normalized[1:2]).item()  
+    return similarity  
+  
+if __name__ == "__main__":  
+    text1 = sys.argv[1]  
+    text2 = sys.argv[2]  
+    print(calculate_text_similarity(text1, text2))
+
+ 

+ 34 - 0
TEAMModelOS.Extension/HTEX.Test/PythonCode/demo.py

@@ -0,0 +1,34 @@
+import torch
+from transformers import BertTokenizer, BertModel
+from torch.nn.functional import cosine_similarity, normalize
+
+# 加载预训练的BERT分词器和模型  
+tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
+model = BertModel.from_pretrained('bert-base-chinese')
+
+# 准备文本  
+texts = ["今天天气真好", "今天天气不错"]
+
+# 编码文本  
+encoded_inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")
+
+# 使用BERT模型获取文本的向量表示  
+with torch.no_grad():
+    outputs = model(**encoded_inputs)
+    last_hidden_states = outputs.last_hidden_state
+
+# 通常取[CLS] token的隐藏状态作为整个句子的表示  
+# 假设batch_size为文本的数量(在这个例子中是2)  
+cls_vectors = last_hidden_states[:, 0, :]  # 取每个序列的第一个token(即[CLS])  
+
+# 归一化向量  
+cls_vectors_normalized = normalize(cls_vectors, p=2, dim=1)
+
+# 计算两段文本之间的余弦相似度  
+# 注意:我们需要将向量reshape为(1, embedding_dim)来匹配cosine_similarity的输入要求  
+similarity = cosine_similarity(cls_vectors_normalized[0:1], cls_vectors_normalized[1:2])
+
+# 打印相似度  
+print(f"两段文本的相似度为: {similarity.item()}")
+
+