فهرست منبع

補上一些中文註解

0x0001F36D 5 سال پیش
والد
کامیت
c0a7b5dd69

+ 13 - 0
src/Yuuna.Contracts/Interaction/Mood.cs

@@ -6,10 +6,17 @@ namespace Yuuna.Contracts.Interaction
     using System.ComponentModel;
 
 
+    /// <summary>
+    /// 情緒。
+    /// </summary>
     [EditorBrowsable(EditorBrowsableState.Never)]
     public struct Mood : IEquatable<Mood>
     {
         private const string NormalString = "Normal";
+        /// <summary>
+        /// 建立新情緒結構實體。
+        /// </summary>
+        /// <param name="name">情緒的名稱。</param>
         public Mood(string name)
         {
             if (string.IsNullOrWhiteSpace(name))
@@ -18,8 +25,14 @@ namespace Yuuna.Contracts.Interaction
         }
         private readonly string _name;
 
+        /// <summary>
+        /// 取得是否為預設情緒。
+        /// </summary>
         public bool IsNormal => this._name is null;
 
+        /// <summary>
+        /// 情緒名稱。
+        /// </summary>
         public string Name
         {
             get

+ 15 - 0
src/Yuuna.Contracts/Interaction/Moods.cs

@@ -4,6 +4,9 @@ namespace Yuuna.Contracts.Interaction
 {
     using System;
 
+    /// <summary>
+    /// 提供多個預設靜態情緒結構實體。
+    /// </summary>
     public static class Moods
     {
         //public static Mood Random(Mood first, Mood second, params Mood[] rest)
@@ -28,15 +31,27 @@ namespace Yuuna.Contracts.Interaction
         //}
 
 
+        /// <summary>
+        /// 一般。
+        /// </summary>
         public static readonly Mood Normal = default;
 
+        /// <summary>
+        /// 快樂。
+        /// </summary>
         public static readonly Mood Happy = new Mood(nameof(Happy));
+        /// <summary>
+        /// 難過。
+        /// </summary>
         public static readonly Mood Sad = new Mood(nameof(Sad));
         //public static readonly Mood Angry = new Mood(nameof(Angry));
         //public static readonly Mood Tender = new Mood(nameof(Tender));
         //public static readonly Mood Excited = new Mood(nameof(Excited));
         //public static readonly Mood Scared = new Mood(nameof(Scared));
 
+        /// <summary>
+        /// 混亂。
+        /// </summary>
         public static readonly Mood Confuse = new Mood(nameof(Confuse));
     }
 

+ 17 - 2
src/Yuuna.Contracts/Interaction/Response.cs

@@ -4,17 +4,30 @@ namespace Yuuna.Contracts.Interaction
     using System;
     using System.ComponentModel;
 
+    /// <summary>
+    /// 回應物件,表示插件回覆的資訊。
+    /// </summary>
     public sealed class Response
     {
+        /// <summary>
+        /// 情緒。
+        /// </summary>
         public Mood Mood { get; }
+        /// <summary>
+        /// 訊息。
+        /// </summary>
         public string Message { get; }
 
 
-
+        /// <summary>
+        /// 建立新回應物件實體。
+        /// </summary>
+        /// <param name="mood">情緒。</param>
+        /// <param name="message">訊息。</param>
         public Response(Mood mood, string message)
         {
             this.Mood = mood;
-            this.Message = message ?? "";
+            this.Message = message ?? string.Empty;
         }
         public static implicit operator Response(ValueTuple<Mood, string> full)
         {
@@ -31,5 +44,7 @@ namespace Yuuna.Contracts.Interaction
             mood = this.Mood;
             message = this.Message;
         }
+
+        public override string ToString() => this.Message;
     }
 }

+ 17 - 38
src/Yuuna.Contracts/Plugins/PluginBase.cs

@@ -12,6 +12,7 @@ namespace Yuuna.Contracts.Plugins
     using Yuuna.Contracts.Patterns;
     using Yuuna.Contracts.Semantics;
     using Yuuna.Contracts.TextSegmention;
+    using Yuuna.Contracts.Utilities;
 
     public sealed class Fake : PluginBase
     {
@@ -24,7 +25,7 @@ namespace Yuuna.Contracts.Plugins
 
             p.Build(g["open"], g["door"]).OnInvoke(score =>
             {
-                var DOOR = new { IS_OPENED = new[] { true, false, true, false }.Random() };
+                var DOOR = new { IS_OPENED = new[] { true, false, true, false }.RandomTakeOne() };
                 // 開門
                 if (!DOOR.IS_OPENED)
                     return (Moods.Happy, "已經開好門囉 <3");
@@ -34,7 +35,7 @@ namespace Yuuna.Contracts.Plugins
 
             p.Build(g["open"], g["light"]).OnInvoke(score =>
             {
-                var LIGHT = new { IS_OPENED = new[] { true, false,true,false }.Random() };
+                var LIGHT = new { IS_OPENED = new[] { true, false,true,false }.RandomTakeOne() };
                 // 開門
                 if (!LIGHT.IS_OPENED)
                     return (Moods.Happy, "已經開好燈囉 <3");
@@ -54,25 +55,6 @@ namespace Yuuna.Contracts.Plugins
         }
     }
 
-    public static class RandomHelper
-    {
-        public static T Random<T>(this IEnumerable<T> collection)
-        {
-            if (collection == null)
-                throw new ArgumentNullException(nameof(collection));
-            var list = collection.ToArray();
-            if (list.Length == 0)
-                return default(T);
-            else if (list.Length == 1)
-                return list[0];
-            else
-            {
-                var rnd = new System.Random(Guid.NewGuid().GetHashCode());
-                var index = rnd.Next(0, list.Length);
-                return list[index];
-            }
-        }
-    }
 
     public class PluginHub
     {
@@ -87,9 +69,7 @@ namespace Yuuna.Contracts.Plugins
         {
             // Send("打開門");
             // Send("開燈");
-             Send("打開燈");
-
-
+            // Send("打開燈"); 
         }
 
         public static void Send(string text)
@@ -128,8 +108,8 @@ namespace Yuuna.Contracts.Plugins
                 {
                     case 1:
                         {
-                            sb.Append("你" + new[] { "是想", "想要" }.Random() + " ");
-                            sb.Append(choices.Select(x => x.Contrast.ToImmutable().Aggregate(string.Empty, (s, g) => s += g.ToImmutable().Random().ToImmutable().Random())));
+                            sb.Append("你" + new[] { "是想", "想要" }.RandomTakeOne() + " ");
+                            sb.Append(choices.Select(x => x.Contrast.ToImmutable().Aggregate(string.Empty, (s, g) => s += g.ToImmutable().RandomTakeOne().ToImmutable().RandomTakeOne())));
                             sb.Append(" 嗎?");
                         }
                         break;
@@ -137,8 +117,8 @@ namespace Yuuna.Contracts.Plugins
 
                     case 2:
                         {
-                            sb.Append("你" + new[] { "是想", "想要" }.Random() + " ");
-                            sb.AppendJoin(" 還是 ", choices.Select(x => x.Contrast.ToImmutable().Aggregate(string.Empty, (s, g) => s += g.ToImmutable().Random().ToImmutable().Random())));
+                            sb.Append("你" + new[] { "是想", "想要" }.RandomTakeOne() + " ");
+                            sb.AppendJoin(" 還是 ", choices.Select(x => x.Contrast.ToImmutable().Aggregate(string.Empty, (s, g) => s += g.ToImmutable().RandomTakeOne().ToImmutable().RandomTakeOne())));
                             sb.Append(" ?");
                         }
                         break;
@@ -152,16 +132,6 @@ namespace Yuuna.Contracts.Plugins
 
             Console.WriteLine(sb);
 
-            //foreach (var topmost in list.Where(x=>x.IsCompacted))
-            //{ 
-            //    Console.WriteLine(topmost.IsCompacted);
-            //    Console.WriteLine("coverage: " + topmost.Coverage * 100.0 +" %");
-            //    Console.WriteLine("missing: "+topmost.Missing.Count);
-
-            //    Console.WriteLine(string.Join(",", topmost.Contrast.SequentialKeys));
-            //    Console.WriteLine();
-            //}
-            //Console.ReadKey();
         }
     }
 
@@ -177,10 +147,19 @@ namespace Yuuna.Contracts.Plugins
             this._groupManager = new GroupManager();
         }
 
+        protected virtual void PreInitialize(ITextSegmenter segmenter)
+        { 
+        }
+
         internal void Initialize(ITextSegmenter textSegmenter)
         {
+            this.PreInitialize(textSegmenter);
             this.BuildPatterns(this._groupManager, this._grammarSet);
             textSegmenter.Load(this._groupManager);
+            this.OnInitialize();
+        }
+        protected virtual void OnInitialize()
+        {
         }
 
         protected abstract void BuildPatterns(IGroupManager groupManager, IPatternBuilder grammarBuilder);

+ 18 - 2
src/Yuuna.Contracts/TextSegmention/ITextSegmenter.cs

@@ -6,13 +6,29 @@
     using System.Collections.Immutable;
     using System.Globalization;
 
+    /// <summary>
+    /// 文字分詞器。
+    /// </summary>
     public interface ITextSegmenter
     {
+        /// <summary>
+        /// 文化資訊,用以表示此分詞器適用的語言,詳細請看 <see cref="https://tools.ietf.org/html/bcp47"/> 。
+        /// </summary>
         CultureInfo Culture { get; }
+        /// <summary>
+        /// 名稱。
+        /// </summary>
         string Name { get; }
-
+        /// <summary>
+        /// 分詞。
+        /// </summary>
+        /// <param name="text">要切分的文字。</param>
+        /// <returns></returns>
         IImmutableList<string> Cut(string text);
-
+        /// <summary>
+        /// 從 <paramref name="manager"/> 載入字典。
+        /// </summary>
+        /// <param name="manager">群組管理器。</param>
         void Load(IGroupManager manager);
     }
 

+ 60 - 0
src/Yuuna.Contracts/Utilities/RandomHelper.cs

@@ -0,0 +1,60 @@
+
+namespace Yuuna.Contracts.Utilities
+{
+    using System;
+    using System.Collections.Concurrent;
+    using System.Collections.Generic;
+    using System.Linq;
+
+    public static class RandomHelper
+    {
+        private static ConcurrentDictionary<object, int> s_binarySwitcher = new ConcurrentDictionary<object, int>();
+        private static ConcurrentDictionary<object, int> s_manySwitcher = new ConcurrentDictionary<object, int>();
+
+        /// <summary>
+        /// 隨機從集合中取得一個成員。
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="collection">集合。</param>
+        /// <returns></returns>
+        /// <exception cref="ArgumentNullException"/>
+        public static T RandomTakeOne<T>(this IEnumerable<T> collection)
+        {
+            if (collection == null)
+                throw new ArgumentNullException(nameof(collection));
+
+
+            var list = collection.ToArray();
+            if (list.Length == 0)
+                return default(T);
+            else if (list.Length == 1)
+            {
+                return list[0];
+            }
+            else if (list.Length == 2)
+            {
+                if (!s_binarySwitcher.ContainsKey(collection))
+                {
+                    var rnd = new Random(Guid.NewGuid().GetHashCode());
+                    s_binarySwitcher.TryAdd(collection, rnd.Next(0, list.Length));
+                }
+
+                return list[(s_binarySwitcher[collection] ^= 1)];
+            }
+            else
+            {
+                GenRnd:
+                var rnd = new Random(Guid.NewGuid().GetHashCode());
+                var newIndex = rnd.Next(0, list.Length);
+                if (!s_manySwitcher.TryGetValue(collection, out var index))
+                    s_manySwitcher.TryAdd(collection, newIndex);
+                else if (index.Equals(newIndex))
+                    goto GenRnd;
+                else
+                    s_manySwitcher[collection] = newIndex;
+                return list[newIndex];
+            }
+        }
+    }
+
+}