ソースを参照

RESTful server demo

0x0001F36D 5 年 前
コミット
2f13458837

+ 0 - 20
src/Yuuna.Contracts/Interaction/IInteractiveView.cs

@@ -1,20 +0,0 @@
-// Author: Orlys
-// Github: https://github.com/Orlys
-
-namespace Yuuna.Contracts.Interaction
-{
-    using System;
-
-    public interface IInteractiveView
-    {
-        string Accept();
-
-        void OnReceive(Response response);
-    }
-
-
-    public interface IViewPipeline
-    {
-        Response OnRequest(string text); 
-    }
-}

+ 7 - 5
src/Yuuna.Contracts/Modules/ModuleBase.cs

@@ -36,14 +36,14 @@ namespace Yuuna.Contracts.Modules
         IPatternSet Patterns { get; }
     }
 
-    public abstract class ModuleBase  
-    { 
+    public abstract class ModuleBase 
+    {
 
         protected virtual string ModuleName { get; }
 
         private readonly PatternFactory _patternfactory;
-        
-        internal IPatternSet  Patterns => this._patternfactory;
+
+        internal IPatternSet Patterns => this._patternfactory;
 
         public ModuleBase()
         {
@@ -60,7 +60,7 @@ namespace Yuuna.Contracts.Modules
             get
             {
                 var t = this.GetType();
-                var getMethod = t.GetProperty(nameof(this.ModuleName),  (BindingFlags)52).GetGetMethod(true);
+                var getMethod = t.GetProperty(nameof(this.ModuleName), (BindingFlags)52).GetGetMethod(true);
                 if (!getMethod.GetBaseDefinition().Equals(getMethod))
                 {
                     try
@@ -123,5 +123,7 @@ namespace Yuuna.Contracts.Modules
         /// <param name="g"></param>
         /// <param name="p"></param>
         protected abstract void BuildPatterns(IGroupManager g, IPatternBuilder p);
+
+
     }
 }

+ 2 - 2
src/Yuuna.Contracts/Optimization/DefaultStrategy.cs → src/Yuuna.Contracts/Optimization/Strategy.cs

@@ -14,9 +14,9 @@ namespace Yuuna.Contracts.Optimization
     using Yuuna.Contracts.Semantics;
     using System.Diagnostics;
 
-    public class DefaultStrategy : IStrategy
+    public class Strategy : IStrategy
     {
-        public DefaultStrategy()
+        public Strategy()
         {
 
         }

+ 224 - 0
src/Yuuna/Actor.cs

@@ -0,0 +1,224 @@
+// Author: Orlys
+// Github: https://github.com/Orlys
+
+namespace Yuuna
+{
+    using System;
+    using System.Text;
+
+    using Yuuna.Contracts.Optimization;
+    using Yuuna.Contracts.TextSegmention;
+    using Yuuna.Semantics;
+    using Yuuna.TextSegmention;
+    using Yuuna.Common.Utilities;
+    using System.Linq;
+    using Yuuna.Contracts.Interaction;
+    using System.Diagnostics;
+    using System.Collections.Generic;
+
+
+
+    internal sealed class Antonym
+    {
+        public enum TypeKinds
+        {
+            Unknown = default,
+            Positive,
+            Negative,
+            //Question
+        }
+
+        private struct Word
+        {
+            public Word(string value, TypeKinds condition)
+            {
+                this.Value = value;
+                this.Condition = condition;
+                this.Priority = value.Length;
+            }
+            internal string Value { get; }
+            internal TypeKinds Condition { get; }
+            internal int Priority { get; }
+        }
+
+        private readonly Word[] _words;
+
+        public Antonym(string positive, string negative, string question)
+        {
+            this._words = new[]
+            {
+                new Word(positive, TypeKinds.Positive),
+                new Word(negative, TypeKinds.Negative),
+                //new Word(question, TypeKinds.Question)
+            };
+            Array.Sort(this._words, new Comparison<Word>((x, y) => y.Priority - x.Priority));
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="positive"></param>
+        /// <param name="negative"></param>
+        public Antonym(string positive, string negative) : this(positive, negative, positive + negative)
+        {
+        }
+
+        public bool Judge(string sentence, out TypeKinds condition)
+        {
+            foreach (var w in this._words)
+            {
+                if (sentence.Contains(w.Value))
+                {
+                    condition = w.Condition;
+                    return true;
+                }
+            }
+            condition = default;
+            return false;
+        }
+        //public override string ToString() => (this._words[0].Value + " / " + this._words[1].Value).ToString();
+    }
+
+    public class Actor
+    {
+        private readonly IEnumerable<Response> _canResponses;
+        private readonly Antonym[] _antonyms;
+        private readonly ITextSegmenter _segmenter;
+        private readonly IStrategy _strategy;
+        private readonly IReadOnlyList<ModuleProxy> _allPlugins;
+        private readonly Stack<Match> _session;
+        private readonly object _lock = new object();
+
+        public Actor(ITextSegmenter segmenter, IEnumerable<Response> canResponses, IStrategy strategy = default)
+        {
+            this._segmenter = segmenter ?? throw new ArgumentNullException(nameof(segmenter));
+            this._canResponses = canResponses ?? throw new ArgumentNullException(nameof(canResponses));
+            this._strategy = strategy ?? new Strategy();
+
+            this._antonyms = new[]
+            {
+                new Antonym("是", "不是"),
+                new Antonym("對", "不對"),
+                new Antonym("是", "否"),
+            };
+
+
+
+            this._allPlugins = ModuleManager.Instance.Modules;
+            foreach (var plugin in this._allPlugins)
+            {
+                plugin.Initialize(this._segmenter, new GroupManager());
+                Debug.WriteLine("已載入模組: " + plugin.Type.AssemblyQualifiedName);
+            }
+
+            this._session = new Stack<Match>();
+        }
+
+        public bool Accept(string text, out Response response)
+        {
+            lock (this._lock)
+            {
+
+                if (string.IsNullOrWhiteSpace(text))
+                    return false;
+
+                response = this.OnAccept(text);
+                return true;
+            }
+        }
+
+        protected virtual Response OnAccept(string text)
+        {
+            lock (this._lock)
+            {
+
+
+                var cutted = this._segmenter.Cut(text);
+                //Debug.WriteLine($"來自分詞器 {this._segmenter.Name} 的分詞結果: [ {string.Join(", ", cutted)} ]");
+
+                if (this._session.Count > 0)
+                {
+                    var single = this._session.Pop();
+
+                    foreach (var antonym in this._antonyms)
+                    {
+                        if (antonym.Judge(text, out var type))
+                        {
+                            if (type.Equals(Antonym.TypeKinds.Positive))
+                            {
+                                single.Pattern.Owner.Patterns.TryGet(single.Pattern, out var bag);
+                                var r = bag.Invoke(single);
+                                return r;
+                            }
+                            else
+                                continue;
+                        }
+                    }
+
+                    if (this._session.Count == 0)
+                    {
+                        return this._canResponses.RandomTakeOne();
+                    }
+                    else
+                    {
+                        var sb = new StringBuilder("還是你是想");
+                        foreach (var g in this._session.Peek().Pattern.ToImmutable())
+                            sb.Append(g.RandomTakeOne().RandomTakeOne());
+                        sb.Append("?");
+                        return sb.ToString();
+                    }
+                }
+
+
+
+                var alternative = this._strategy.FindBest(this._allPlugins.Select(x => x.PatternSet).ToArray(), cutted);
+                //Debug.WriteLine(alternative.Status);
+                switch (alternative.Status)
+                {
+                    case AlternativeStatus.Invalid:
+                        return this._canResponses.RandomTakeOne();
+
+                    case AlternativeStatus.Optimal:
+                        {
+                            var single = alternative.Matches[0];
+                            single.Pattern.Owner.Patterns.TryGet(single.Pattern, out var bag);
+                            var r = bag.Invoke(single);
+                            return r;
+                        }
+
+                    case AlternativeStatus.Condition:
+                        {
+                            var sb = new StringBuilder();
+
+                            sb.Append("你是想要");
+                            foreach (var g in alternative.Matches[0].Pattern.ToImmutable())
+                                sb.Append(g.RandomTakeOne().RandomTakeOne());
+                            sb.Append("嗎?");
+
+                            this._session.Push(alternative.Matches[0]);
+                            return sb.ToString();
+                        }
+
+                    case AlternativeStatus.Proposition:
+                        {
+                            this._session.Push(alternative.Matches[1]);
+                            goto case AlternativeStatus.Condition;
+                        }
+
+                    case AlternativeStatus.Paradox:
+                        goto case AlternativeStatus.Proposition;
+
+                    //case AlternativeStatus.NoModuleInstalled:
+                    //    interactor.OnReceive((Moods.Sad, "無效的模組"));
+                    //    break;
+
+                    default:
+                        throw new InvalidOperationException();
+
+
+                }
+
+            }
+        }
+    }
+}

+ 240 - 353
src/Yuuna/EntryPoint.cs

@@ -4,429 +4,316 @@
 namespace Yuuna
 {
     using System;
-    using System.Text;
-
-    using Yuuna.Contracts.Optimization;
     using Yuuna.Contracts.Modules;
-    using Yuuna.Contracts.TextSegmention;
     using Yuuna.Recognition.Speech;
-    using Yuuna.Semantics;
-    using Yuuna.TextSegmention;
-    using Yuuna.Common.Utilities;
     using System.Threading.Tasks;
     using System.Reflection;
-    using System.Linq;
     using Yuuna.Contracts.Interaction;
+    using Yuuna.TextSegmention;
     using System.Diagnostics;
-    using System.Collections.Generic;
-
-    public class Antonym
+    using Microsoft.AspNetCore;
+    using Microsoft.AspNetCore.Hosting;
+    using Microsoft.Extensions.DependencyInjection;
+    using Microsoft.AspNetCore.Builder;
+    using Microsoft.AspNetCore.Routing;
+    using Microsoft.Extensions.Hosting;
+    using Microsoft.Extensions.Configuration;
+    using Microsoft.AspNetCore.Mvc;
+    using Microsoft.Extensions.Logging;
+
+    namespace Controllers
     {
-        public enum TypeKinds
+        public class Yuuna
         {
-            Unknown = default,
-            Positive,
-            Negative,
-            //Question
-        }
+            public class Input
+            {
+                public string Text { get; set; }
+            }
 
-        private struct Word
-        {
-            public Word(string value, TypeKinds condition)
+            public class Output
             {
-                this.Value = value;
-                this.Condition = condition;
-                this.Priority = value.Length;
+                public Output(bool success, string message, Mood mood, string text)
+                {
+                    this.Success = success;
+                    this.Message = message;
+                    this.Mood = mood.Name;
+                    this.Text = text;
+                }
+                public bool Success { get; }
+                public string Message { get; }
+                public string Mood { get; }
+                public string Text { get; }
             }
-            internal string Value { get; }
-            internal TypeKinds Condition { get; }
-            internal int Priority { get; }
         }
 
-        private readonly Word[] _words;
-
-        public Antonym(string positive, string negative, string question)
+        [ApiController]
+        [Route("[controller]")]
+        public class YuunaController : ControllerBase
         {
-            this._words = new[] 
-            { 
-                new Word(positive, TypeKinds.Positive), 
-                new Word(negative, TypeKinds.Negative),
-                //new Word(question, TypeKinds.Question)
-            };
-            Array.Sort(this._words, new Comparison<Word>((x, y) => y.Priority - x.Priority)); 
-        }
+            private readonly ILogger<YuunaController> _logger;
 
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="positive"></param>
-        /// <param name="negative"></param>
-        public Antonym(string positive, string negative) : this(positive, negative, positive + negative)
-        {
-        }
+            public YuunaController(ILogger<YuunaController> logger, Actor actor)
+            {
+                _logger = logger;
+                this._actor = actor;
 
-        public bool Judge(string sentence,out TypeKinds condition)
-        {
-            foreach (var w in this._words)
+            }
+
+            private readonly Actor _actor;
+
+            [HttpGet, HttpPost]
+            public Yuuna.Output Post([FromBody]Yuuna.Input text)
             {
-                if(sentence.Contains(w.Value))
-                { 
-                    condition = w.Condition;
-                    return true;
-                }
+                return new Yuuna.Output(this._actor.Accept(text.Text, out var r), r.Message, r.Mood, text.Text); 
             }
-            condition = default;
-            return false;
         }
-
-        public override string ToString() => (this._words[0].Value + " / " + this._words[1].Value).ToString();
     }
-
-    public class DefaultAcceptor 
+    public class Startup
     {
-        private readonly Response[] _canResponses;
-        private readonly Antonym[] _antonyms;
-        private readonly ITextSegmenter _segmenter;
-        private readonly IStrategy _plan;
-        private readonly IReadOnlyList<ModuleProxy> _allPlugins;
-        private readonly Stack<Match> _session;
-
-        public DefaultAcceptor()
+        public Startup()
         {
-            this._canResponses = new Response[]
-            {
+        }
+
+
+        // This method gets called by the runtime. Use this method to add services to the container.
+        public void ConfigureServices(IServiceCollection services)
+        {
+            services.AddSingleton(new Actor(new JiebaTextSegmenter(), new Response[]
+           {
                 (Moods.Sad, "我不清楚你想做什麼 OvQ"),
                 (Moods.Sad, "我不懂你想幹嘛 QAQ"),
                 (Moods.Sad, "我不知道你想幹嘛 OHQ"),
-            };
+           }));
+            services.AddControllers();
+        }
 
-            this._antonyms = new[]
+        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+        {
+            if (env.IsDevelopment())
             {
-                new Antonym("是", "不是"),
-                new Antonym("對", "不對"),
-                new Antonym("是", "否"),
-            };
+                app.UseDeveloperExceptionPage();
+            }
 
+            //app.UseHttpsRedirection();
+             
+            app.UseRouting();
 
-            this._segmenter = new JiebaTextSegmenter();
-            this._plan = new DefaultStrategy();
 
-            this._allPlugins = ModuleManager.Instance.Modules;
-            foreach (var plugin in this._allPlugins)
+            app.UseEndpoints(endpoints =>
             {
-                plugin.Initialize(this._segmenter, new GroupManager());
-                Debug.WriteLine("已載入模組: " + plugin.Type.AssemblyQualifiedName);
-            }
-
-            this._session = new Stack<Match>();
+                endpoints.MapControllers();
+            });
         }
+    }
+    internal class EntryPoint
+    {
+        
 
 
-        public virtual Response OnAccept(string text)
+        public static IHostBuilder CreateHostBuilder(string[] args) =>
+               Host.CreateDefaultBuilder(args)
+                   .ConfigureWebHostDefaults(webBuilder =>
+                   {
+                       webBuilder.UseStartup<Startup>();
+                   });
+        public static void Main(string[] args)
         {
-            var cutted = this._segmenter.Cut(text);
-            //Debug.WriteLine($"來自分詞器 {this._segmenter.Name} 的分詞結果: [ {string.Join(", ", cutted)} ]");
-
-            if (this._session.Count > 0)
-            {
-                var single = this._session.Pop();
+            CreateHostBuilder(args).Build().Run ();
 
-                foreach (var antonym in this._antonyms)
-                {
-                    if (antonym.Judge(text, out var type))
-                    {
-                        if (type.Equals(Antonym.TypeKinds.Positive))
-                        {
-                            single.Pattern.Owner.Patterns.TryGet(single.Pattern, out var bag);
-                            var r = bag.Invoke(single);
-                            return r;
-                        }
-                        else
-                            break;
-                    }
-                }
+            //var actor = new Actor(new JiebaTextSegmenter(), new Response[]
+            //{
+            //    (Moods.Sad, "我不清楚你想做什麼 OvQ"),
+            //    (Moods.Sad, "我不懂你想幹嘛 QAQ"),
+            //    (Moods.Sad, "我不知道你想幹嘛 OHQ"),
+            //});
 
+            //while (true) 
+            //{
+            //    Console.Write("Me:  "); 
+            //    if (actor.Accept(Console.ReadLine(), out var response))
+            //    {
+            //        Console.WriteLine("Bot: " + response.Message);
+            //    }
+            //    else
+            //    {
+            //        Console.CursorTop --; 
+            //    }
+            //} 
+             
+             
+            //var canResponses = new Response[]
+            //{
+            //    (Moods.Sad, "我不清楚你想做什麼 OvQ"),
+            //    (Moods.Sad, "我不懂你想幹嘛 QAQ"),
+            //    (Moods.Sad, "我不知道你想幹嘛 OHQ"),
+            //};
 
+            //var antonyms = new[]
+            //{
+            //    new Antonym("是", "不是"),
+            //    new Antonym("對", "不對"),
+            //    new Antonym("是", "否"), 
+            //};
 
-                if (this._session.Count == 0)
-                    return this._canResponses.RandomTakeOne();
-                else
-                {
-                    var sb = new StringBuilder("還是你是想"); 
-                    foreach (var g in this._session.Peek().Pattern.ToImmutable())
-                        sb.Append(g.RandomTakeOne().RandomTakeOne());
-                    sb.Append("?");
-                    return sb.ToString();
-                } 
-            }
+            //IInteractiveView interactor = new ConsoleBotInteract( );
+            //ITextSegmenter segmenter = new JiebaTextSegmenter();
+            //IStrategy plan = new DefaultStrategy();
 
+            //var allPlugins = ModuleManager.Instance.Modules;
+            //foreach (var item in allPlugins)
+            //{
+            //    item.Initialize(segmenter, new GroupManager());
+            //    Debug.WriteLine("已載入模組: " + item.Type.AssemblyQualifiedName);
+            //}
 
+            //// prepare task completed.
+            //LOOP:
+            //var text = interactor.Accept();
+            //var cutted = segmenter.Cut(text);
+            //Debug.WriteLine($"來自分詞器 {segmenter.Name} 的分詞結果: [ {string.Join(", ", cutted)} ]");
 
-            var alternative = this._plan.FindBest(this._allPlugins.Select(x => x.PatternSet).ToArray(), cutted);
+            //var alternative = plan.FindBest(allPlugins.Select(x => x.PatternSet).ToArray(), cutted);
             //Debug.WriteLine(alternative.Status);
-            switch (alternative.Status)
-            {
-                // 罐頭回應
-                case AlternativeStatus.Invalid:
-                   return this._canResponses.RandomTakeOne(); 
-
-                case AlternativeStatus.Optimal:
-                    {
-                        var single = alternative.Matches[0];
-                        single.Pattern.Owner.Patterns.TryGet(single.Pattern, out var bag);
-                        var r = bag.Invoke(single);
-                        return r;
-                    }
-
-                case AlternativeStatus.Condition:
-                    {
-                        var sb = new StringBuilder();
-
-                        sb.Append("你是想要");
-                        foreach (var g in alternative.Matches[0].Pattern.ToImmutable())
-                            sb.Append(g.RandomTakeOne().RandomTakeOne());
-                        sb.Append("嗎?");
-
-                        this._session.Push(alternative.Matches[0]);
-                        return sb.ToString();
-                    }
-
-                case AlternativeStatus.Proposition:
-                    {
-
-                        var sb = new StringBuilder();
-
-                        sb.Append("你是想要");
-                        foreach (var g in alternative.Matches[0].Pattern.ToImmutable())
-                            sb.Append(g.RandomTakeOne().RandomTakeOne());
-                        sb.Append("嗎?");
+            //switch (alternative.Status)
+            //{
+            //    // 罐頭回應
+            //    case AlternativeStatus.Invalid:
+            //        interactor.OnReceive(canResponses.RandomTakeOne());
+            //        break;
 
-                        this._session.Push(alternative.Matches[1]);
-                        this._session.Push(alternative.Matches[0]);
-                        return sb.ToString();
-                    }
+            //    case AlternativeStatus.Optimal:
+            //        {
+            //            var single = alternative.Matches[0];
+            //            single.Pattern.Owner.Patterns.TryGet(single.Pattern, out var bag);
+            //            var r = bag.Invoke(single);
+            //            interactor.OnReceive(r);
+            //            break;
+            //        }
 
-                case AlternativeStatus.Paradox:
+            //    case AlternativeStatus.Condition:
+            //        {
+            //            var sb = new StringBuilder();
+                        
+            //            sb.Append("你是想要"); 
 
+            //            foreach (var g in alternative.Matches[0].Pattern.ToImmutable())
+            //            {
+            //                sb.Append(g.RandomTakeOne().RandomTakeOne());
+            //            }
 
-                    break;
+            //            sb.Append("嗎?");
+            //            interactor.OnReceive(sb.ToString());
 
-                //case AlternativeStatus.NoModuleInstalled:
-                //    interactor.OnReceive((Moods.Sad, "無效的模組"));
-                //    break;
+            //            text = interactor.Accept();
 
-                default:
-                    throw new InvalidOperationException();
+            //            foreach (var antonym in antonyms)
+            //            {
+            //                if (antonym.Judge(text, out var type))
+            //                {
+            //                    if (type.Equals(Antonym.TypeKinds.Positive))
+            //                    {
+            //                        var single = alternative.Matches[0];
+            //                        single.Pattern.Owner.Patterns.TryGet(single.Pattern, out var bag);
+            //                        var r = bag.Invoke(single);
+            //                        interactor.OnReceive(r);
+            //                        goto Leave;
+            //                    }
+            //                    else
+            //                        break;
+            //                }
+            //            }
 
+            //            interactor.OnReceive(canResponses.RandomTakeOne());
+            //            Leave:
+            //            break;
+            //        }
 
-            }
+            //    case AlternativeStatus.Proposition:
+            //        {
 
-            return default;
-        }
-    }
+            //            var sb = new StringBuilder(); 
+            //            var current = alternative.Matches[0];
 
-    public sealed class ConsoleBotInteract : IInteractiveView
-    {   
-        public void OnReceive(Response response)
-        {
-            Console.WriteLine("Bot: " + response.Message);
-        }
+            //            sb.Append("你是想要");
 
-        public string Accept()
-        {
-            Console.Write("我: ");
-            return Console.ReadLine();
-        }
-    }
+            //            foreach (var g in current.Pattern.ToImmutable())
+            //            {
+            //                sb.Append(g.RandomTakeOne().RandomTakeOne());
+            //            }
 
+            //            sb.Append("嗎?");
+            //            interactor.OnReceive(sb.ToString());
 
-    internal class EntryPoint
-    {
-        public static void Main(string[] args)
-        {
-            var acc = new DefaultAcceptor();
-            Loop:
-            var rsp = acc.OnAccept(Console.ReadLine());
-            if(!rsp.Equals(default(Response)))
-            {
-                Console.WriteLine(rsp.Message);
-                goto Loop;
-            } 
+            //            text = interactor.Accept(); 
+            //            foreach (var antonym in antonyms)
+            //            {
+            //                if (antonym.Judge(text, out var type))
+            //                {
+            //                    if (type.Equals(Antonym.TypeKinds.Positive))
+            //                    {
+            //                        current.Pattern.Owner.Patterns.TryGet(current.Pattern, out var bag);
+            //                        var r = bag.Invoke(current);
+            //                        interactor.OnReceive(r);
+            //                        goto Leave;
+            //                    }
+            //                    else if(type.Equals(Antonym.TypeKinds.Negative))
+            //                        break;
+            //                }
+            //            }
 
-            return;
+            //            sb.Clear();
 
-            var canResponses = new Response[]
-            {
-                (Moods.Sad, "我不清楚你想做什麼 OvQ"),
-                (Moods.Sad, "我不懂你想幹嘛 QAQ"),
-                (Moods.Sad, "我不知道你想幹嘛 OHQ"),
-            };
 
-            var antonyms = new[]
-            {
-                new Antonym("是", "不是"),
-                new Antonym("對", "不對"),
-                new Antonym("是", "否"), 
-            };
+            //            current = alternative.Matches[1];
+            //            sb.Append("還是");
+            //            sb.Append("你是想"); 
 
-            IInteractiveView interactor = new ConsoleBotInteract( );
-            ITextSegmenter segmenter = new JiebaTextSegmenter();
-            IStrategy plan = new DefaultStrategy();
+            //            foreach (var g in current.Pattern.ToImmutable())
+            //            {
+            //                sb.Append(g.RandomTakeOne().RandomTakeOne());
+            //            }
 
-            var allPlugins = ModuleManager.Instance.Modules;
-            foreach (var item in allPlugins)
-            {
-                item.Initialize(segmenter, new GroupManager());
-                Debug.WriteLine("已載入模組: " + item.Type.AssemblyQualifiedName);
-            }
+            //            sb.Append("?");
+            //            interactor.OnReceive(sb.ToString());
 
-            // prepare task completed.
-            LOOP:
-            var text = interactor.Accept();
-            var cutted = segmenter.Cut(text);
-            Debug.WriteLine($"來自分詞器 {segmenter.Name} 的分詞結果: [ {string.Join(", ", cutted)} ]");
+            //            text = interactor.Accept();
 
-            var alternative = plan.FindBest(allPlugins.Select(x => x.PatternSet).ToArray(), cutted);
-            Debug.WriteLine(alternative.Status);
-            switch (alternative.Status)
-            {
-                // 罐頭回應
-                case AlternativeStatus.Invalid:
-                    interactor.OnReceive(canResponses.RandomTakeOne());
-                    break;
-
-                case AlternativeStatus.Optimal:
-                    {
-                        var single = alternative.Matches[0];
-                        single.Pattern.Owner.Patterns.TryGet(single.Pattern, out var bag);
-                        var r = bag.Invoke(single);
-                        interactor.OnReceive(r);
-                        break;
-                    }
-
-                case AlternativeStatus.Condition:
-                    {
-                        var sb = new StringBuilder();
-                        
-                        sb.Append("你是想要"); 
-
-                        foreach (var g in alternative.Matches[0].Pattern.ToImmutable())
-                        {
-                            sb.Append(g.RandomTakeOne().RandomTakeOne());
-                        }
-
-                        sb.Append("嗎?");
-                        interactor.OnReceive(sb.ToString());
-
-                        text = interactor.Accept();
-
-                        foreach (var antonym in antonyms)
-                        {
-                            if (antonym.Judge(text, out var type))
-                            {
-                                if (type.Equals(Antonym.TypeKinds.Positive))
-                                {
-                                    var single = alternative.Matches[0];
-                                    single.Pattern.Owner.Patterns.TryGet(single.Pattern, out var bag);
-                                    var r = bag.Invoke(single);
-                                    interactor.OnReceive(r);
-                                    goto Leave;
-                                }
-                                else
-                                    break;
-                            }
-                        }
-
-                        interactor.OnReceive(canResponses.RandomTakeOne());
-                        Leave:
-                        break;
-                    }
-
-                case AlternativeStatus.Proposition:
-                    {
-
-                        var sb = new StringBuilder(); 
-                        var current = alternative.Matches[0];
-
-                        sb.Append("你是想要");
-
-                        foreach (var g in current.Pattern.ToImmutable())
-                        {
-                            sb.Append(g.RandomTakeOne().RandomTakeOne());
-                        }
-
-                        sb.Append("嗎?");
-                        interactor.OnReceive(sb.ToString());
-
-                        text = interactor.Accept(); 
-                        foreach (var antonym in antonyms)
-                        {
-                            if (antonym.Judge(text, out var type))
-                            {
-                                if (type.Equals(Antonym.TypeKinds.Positive))
-                                {
-                                    current.Pattern.Owner.Patterns.TryGet(current.Pattern, out var bag);
-                                    var r = bag.Invoke(current);
-                                    interactor.OnReceive(r);
-                                    goto Leave;
-                                }
-                                else if(type.Equals(Antonym.TypeKinds.Negative))
-                                    break;
-                            }
-                        }
-
-                        sb.Clear();
-
-
-                        current = alternative.Matches[1];
-                        sb.Append("還是");
-                        sb.Append("你是想"); 
-
-                        foreach (var g in current.Pattern.ToImmutable())
-                        {
-                            sb.Append(g.RandomTakeOne().RandomTakeOne());
-                        }
-
-                        sb.Append("?");
-                        interactor.OnReceive(sb.ToString());
-
-                        text = interactor.Accept();
-
-                        foreach (var antonym in antonyms)
-                        {
-                            if (antonym.Judge(text, out var type))
-                            {
-                                if (type.Equals(Antonym.TypeKinds.Positive))
-                                {
-                                    current.Pattern.Owner.Patterns.TryGet(current.Pattern, out var bag);
-                                    var r = bag.Invoke(current);
-                                    interactor.OnReceive(r);
-                                    goto Leave;
-                                }
-                                else if (type.Equals(Antonym.TypeKinds.Negative))
-                                    break;
-                            }
-                        }
+            //            foreach (var antonym in antonyms)
+            //            {
+            //                if (antonym.Judge(text, out var type))
+            //                {
+            //                    if (type.Equals(Antonym.TypeKinds.Positive))
+            //                    {
+            //                        current.Pattern.Owner.Patterns.TryGet(current.Pattern, out var bag);
+            //                        var r = bag.Invoke(current);
+            //                        interactor.OnReceive(r);
+            //                        goto Leave;
+            //                    }
+            //                    else if (type.Equals(Antonym.TypeKinds.Negative))
+            //                        break;
+            //                }
+            //            }
                          
-                        interactor.OnReceive(canResponses.RandomTakeOne()); 
+            //            interactor.OnReceive(canResponses.RandomTakeOne()); 
 
-                        Leave:
-                        break;
-                    }
+            //            Leave:
+            //            break;
+            //        }
 
-                case AlternativeStatus.Paradox:
+            //    case AlternativeStatus.Paradox:
 
 
-                    break;
+            //        break;
 
-                //case AlternativeStatus.NoModuleInstalled:
-                //    interactor.OnReceive((Moods.Sad, "無效的模組"));
-                //    break;
+            //    //case AlternativeStatus.NoModuleInstalled:
+            //    //    interactor.OnReceive((Moods.Sad, "無效的模組"));
+            //    //    break;
 
-                default:
-                    throw new InvalidOperationException();
-            }
-            goto LOOP;
+            //    default:
+            //        throw new InvalidOperationException();
+            //}
+            //goto LOOP;
 
             //try
             //{Send("開燈");

+ 6 - 0
src/Yuuna/Yuuna.csproj

@@ -13,6 +13,12 @@
     <Folder Include="Properties\" />
   </ItemGroup>
 
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
+    <PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.8" />
+    <PackageReference Include="Microsoft.NETCore.App" Version="2.2.8" />
+  </ItemGroup>
+
   <ItemGroup>
     <None Update="secret.json">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>