|
@@ -4,8 +4,7 @@
|
|
|
namespace Yuuna
|
|
|
{
|
|
|
using System;
|
|
|
- using System.Text;
|
|
|
-
|
|
|
+ using System.Text;
|
|
|
|
|
|
using Yuuna.Contracts.Optimization;
|
|
|
using Yuuna.Contracts.Modules;
|
|
@@ -17,110 +16,287 @@ namespace Yuuna
|
|
|
using System.Threading.Tasks;
|
|
|
using System.Reflection;
|
|
|
using System.Linq;
|
|
|
+ using Yuuna.Contracts.Interaction;
|
|
|
+ using System.Diagnostics;
|
|
|
|
|
|
- internal class EntryPoint
|
|
|
+ public class Antonym
|
|
|
{
|
|
|
- public static void Main(string[] args)
|
|
|
+ public enum TypeKinds
|
|
|
{
|
|
|
- //var mc = ModuleManager.Instance;
|
|
|
- //foreach (var m in mc.Modules)
|
|
|
- //{
|
|
|
- // Console.WriteLine(m.Name);
|
|
|
- //}
|
|
|
- //Console.WriteLine("----");
|
|
|
- //Console.ReadKey();
|
|
|
- //mc.UnloadAll();
|
|
|
- //foreach (var m in mc.Modules)
|
|
|
- //{
|
|
|
- // Console.WriteLine(m.Name);
|
|
|
- //}
|
|
|
- //Console.WriteLine("----");
|
|
|
- //Console.ReadKey();
|
|
|
- //mc.ReloadAll();
|
|
|
- //foreach (var m in mc.Modules)
|
|
|
- //{
|
|
|
- // Console.WriteLine(m.Name);
|
|
|
- //}
|
|
|
+ Unknown = default,
|
|
|
+ Positive,
|
|
|
+ Negative,
|
|
|
+ Question
|
|
|
+ }
|
|
|
|
|
|
- Send("打開門");
|
|
|
- return;
|
|
|
+ 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));
|
|
|
+ }
|
|
|
|
|
|
- Send("開燈");
|
|
|
- try
|
|
|
+ /// <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)
|
|
|
{
|
|
|
- var stt = SpeechRecognizer.Create("secret.json");
|
|
|
- stt.RecognizeCompleted += a =>
|
|
|
+ if(sentence.Contains(w.Value))
|
|
|
{
|
|
|
- if (a.Count > 0)
|
|
|
- {
|
|
|
- Console.WriteLine("## Google 語音: " + a[0].Transcript);
|
|
|
- Send(a[0].Transcript);
|
|
|
- }
|
|
|
- };
|
|
|
+ condition = w.Condition;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ condition = default;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- Console.WriteLine("## Proof of Concept Ver.");
|
|
|
- Console.WriteLine("可以叫我開關燈或者開關門,其他的我還不會");
|
|
|
|
|
|
- Console.WriteLine("按下 Enter 鍵開始錄音,任意鍵離開");
|
|
|
- Loop:
|
|
|
- if(Console.ReadKey().Key == ConsoleKey.Enter)
|
|
|
- {
|
|
|
- using (stt.Recognize())
|
|
|
- {
|
|
|
- Console.WriteLine("按下 Enter 停止錄音,任意鍵離開");
|
|
|
- if(Console.ReadKey().Key == ConsoleKey.Enter)
|
|
|
- goto Loop;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- catch (Exception e)
|
|
|
- {
|
|
|
- Console.WriteLine(e.Message);
|
|
|
- Console.ReadKey();
|
|
|
- }
|
|
|
+ public interface IInteractiveView
|
|
|
+ {
|
|
|
+ string Accept();
|
|
|
+ void OnReceive(Response response);
|
|
|
+ }
|
|
|
+
|
|
|
+ public sealed class ConsoleBotInteract : IInteractiveView
|
|
|
+ {
|
|
|
+ public void OnReceive(Response response)
|
|
|
+ {
|
|
|
+ Console.WriteLine("Bot: " + response.Message);
|
|
|
}
|
|
|
|
|
|
- public static void Send(string text)
|
|
|
+ public string Accept()
|
|
|
{
|
|
|
- var segmenter = new JiebaTextSegmenter() as ITextSegmenter;
|
|
|
+ Console.Write("我: ");
|
|
|
+ return Console.ReadLine();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ internal class EntryPoint
|
|
|
+ {
|
|
|
+ public static void Main(string[] args)
|
|
|
+ {
|
|
|
+ var canResponses = new Response[]
|
|
|
+ {
|
|
|
+ (Moods.Sad, "我不清楚你想做什麼 OvQ"),
|
|
|
+ (Moods.Sad, "我不懂你想幹嘛 QAQ"),
|
|
|
+ (Moods.Sad, "我不知道你是什麼意思 OHQ"),
|
|
|
+ };
|
|
|
+
|
|
|
+ var antonyms = new[]
|
|
|
+ {
|
|
|
+ new Antonym("是", "不是"),
|
|
|
+ new Antonym("對", "不對"),
|
|
|
+ new Antonym("是", "否"),
|
|
|
+ };
|
|
|
+
|
|
|
+ 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());
|
|
|
- Console.WriteLine("已載入模組: " + item.GetType().AssemblyQualifiedName);
|
|
|
+ Debug.WriteLine("已載入模組: " + item.Type.AssemblyQualifiedName);
|
|
|
}
|
|
|
|
|
|
- Console.WriteLine("我: " + text);
|
|
|
+ // prepare task completed.
|
|
|
+ LOOP:
|
|
|
+ var text = interactor.Accept();
|
|
|
var cutted = segmenter.Cut(text);
|
|
|
- Console.WriteLine($"來自分詞器 {segmenter.Name} 的分詞結果: [ {string.Join(", ", cutted)} ]");
|
|
|
+ Debug.WriteLine($"來自分詞器 {segmenter.Name} 的分詞結果: [ {string.Join(", ", cutted)} ]");
|
|
|
|
|
|
- IStrategy plan = new DefaultStrategy();
|
|
|
- var alternative = plan.FindBest(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 Status.Invalid:
|
|
|
- Console.WriteLine("無效的模組");
|
|
|
+ interactor.OnReceive(canResponses.RandomTakeOne());
|
|
|
break;
|
|
|
+
|
|
|
case Status.Optimal:
|
|
|
- alternative.Matches[0].Pattern.Owner.Patterns.TryGet(alternative.Matches[0].Pattern, out var bag);
|
|
|
- var r = bag.Invoke(alternative.Matches[0]);
|
|
|
- Console.WriteLine(r.Mood + " | " + r.Message);
|
|
|
+ {
|
|
|
+ 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 Status.Closest:
|
|
|
- Console.WriteLine("closest");
|
|
|
+
|
|
|
+ case Status.Condition:
|
|
|
+ {
|
|
|
+ var sb = new StringBuilder();
|
|
|
+ sb.Append("你是想要");
|
|
|
+ foreach (var matched in alternative.Matches[0].SequentialMatches)
|
|
|
+ {
|
|
|
+ sb.Append(matched.ToImmutable().RandomTakeOne());
|
|
|
+ }
|
|
|
+ foreach (var missing in alternative.Matches[0].Missing)
|
|
|
+ {
|
|
|
+ foreach (var unmatch in missing.ToImmutable())
|
|
|
+ sb.Append(unmatch.ToImmutable().RandomTakeOne());
|
|
|
+ }
|
|
|
+ sb.Append("嗎?");
|
|
|
+ interactor.OnReceive(sb.ToString());
|
|
|
+
|
|
|
+ text = interactor.Accept();
|
|
|
+
|
|
|
+ foreach (var antonym in antonyms)
|
|
|
+ {
|
|
|
+ if(antonym.Judge(text, out var type) && 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ interactor.OnReceive(canResponses.RandomTakeOne());
|
|
|
+ }
|
|
|
+ Leave:
|
|
|
break;
|
|
|
+
|
|
|
case Status.Proposition:
|
|
|
Console.WriteLine("proposition");
|
|
|
break;
|
|
|
+
|
|
|
case Status.Paradox:
|
|
|
Console.WriteLine("paradox");
|
|
|
break;
|
|
|
+
|
|
|
case Status.NoModuleInstalled:
|
|
|
Console.WriteLine("noModuleInstalled");
|
|
|
+ Console.WriteLine("無效的模組");
|
|
|
break;
|
|
|
+
|
|
|
default:
|
|
|
- break;
|
|
|
+ throw new InvalidOperationException();
|
|
|
}
|
|
|
+ goto LOOP;
|
|
|
+
|
|
|
+ //try
|
|
|
+ //{Send("開燈");
|
|
|
+ // var stt = SpeechRecognizer.Create("secret.json");
|
|
|
+ // stt.RecognizeCompleted += a =>
|
|
|
+ // {
|
|
|
+ // if (a.Count > 0)
|
|
|
+ // {
|
|
|
+ // Console.WriteLine("## Google 語音: " + a[0].Transcript);
|
|
|
+ // Send(a[0].Transcript);
|
|
|
+ // }
|
|
|
+ // };
|
|
|
+
|
|
|
+ // Console.WriteLine("## Proof of Concept Ver.");
|
|
|
+ // Console.WriteLine("可以叫我開關燈或者開關門,其他的我還不會");
|
|
|
+
|
|
|
+ // Console.WriteLine("按下 Enter 鍵開始錄音,任意鍵離開");
|
|
|
+ // Loop:
|
|
|
+ // if(Console.ReadKey().Key == ConsoleKey.Enter)
|
|
|
+ // {
|
|
|
+ // using (stt.Recognize())
|
|
|
+ // {
|
|
|
+ // Console.WriteLine("按下 Enter 停止錄音,任意鍵離開");
|
|
|
+ // if(Console.ReadKey().Key == ConsoleKey.Enter)
|
|
|
+ // goto Loop;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ //}
|
|
|
+ //catch (Exception e)
|
|
|
+ //{
|
|
|
+ // Console.WriteLine(e.Message);
|
|
|
+ // Console.ReadKey();
|
|
|
+ //}
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void Send(string text)
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ //Console.WriteLine("我: " + text);
|
|
|
+ //var cutted = segmenter.Cut(text);
|
|
|
+ //Console.WriteLine($"來自分詞器 {segmenter.Name} 的分詞結果: [ {string.Join(", ", cutted)} ]");
|
|
|
+
|
|
|
+ //var alternative = plan.FindBest(allPlugins.Select(x=>x.PatternSet).ToArray(), cutted);
|
|
|
+ //switch (alternative.Status)
|
|
|
+ //{
|
|
|
+ // // 罐頭回應
|
|
|
+ // case Status.Invalid:
|
|
|
+ // view.OnResponsed(s_canResponses.RandomTakeOne());
|
|
|
+ // break;
|
|
|
+
|
|
|
+ // case Status.Optimal:
|
|
|
+ // {
|
|
|
+ // var single = alternative.Matches[0];
|
|
|
+ // single.Pattern.Owner.Patterns.TryGet(single.Pattern, out var bag);
|
|
|
+ // var r = bag.Invoke(single);
|
|
|
+ // view.OnResponsed(r);
|
|
|
+ // }
|
|
|
+ // break;
|
|
|
+
|
|
|
+ // case Status.Condition:
|
|
|
+ // {
|
|
|
+ // Console.WriteLine("proposition");
|
|
|
+ // Console.Write("你是想要");
|
|
|
+ // foreach (var matched in alternative.Matches[0].SequentialMatches)
|
|
|
+ // {
|
|
|
+ // Console.Write(matched.ToImmutable().RandomTakeOne());
|
|
|
+ // }
|
|
|
+ // foreach (var missing in alternative.Matches[0].Missing)
|
|
|
+ // {
|
|
|
+ // foreach (var unmatch in missing.ToImmutable())
|
|
|
+ // {
|
|
|
+ // Console.Write(unmatch.ToImmutable().RandomTakeOne());
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // Console.WriteLine("嗎?");
|
|
|
+ // Console.ReadLine()
|
|
|
+ // }
|
|
|
+ // break;
|
|
|
+
|
|
|
+ // case Status.Proposition:
|
|
|
+ // Console.WriteLine("proposition");
|
|
|
+ // break;
|
|
|
+
|
|
|
+ // case Status.Paradox:
|
|
|
+ // Console.WriteLine("paradox");
|
|
|
+ // break;
|
|
|
+
|
|
|
+ // case Status.NoModuleInstalled:
|
|
|
+ // Console.WriteLine("noModuleInstalled");
|
|
|
+ // Console.WriteLine("無效的模組");
|
|
|
+ // break;
|
|
|
+
|
|
|
+ // default:
|
|
|
+ // throw new InvalidOperationException();
|
|
|
+ //}
|
|
|
|
|
|
|
|
|
|