コード例 #1
0
        /// <summary>
        /// アンケート用の選択肢を生成
        /// </summary>
        private List <string> GenerateChoices(UserStorage.UserRecord storage)
        {
            var rnd        = core?.Random ?? new Random();
            var nouns      = storage.Get("freetalk.nouns", new List <string>()).ToList();
            var verbs      = storage.Get("freetalk.verbs", new List <string>()).ToList();
            var adjectives = storage.Get("freetalk.adjectives", new List <string>()).ToList();

            return(Enumerable.Range(0, rnd.Next(2, 5)).Select(_ =>
            {
                var dice = rnd.Next(100);
                // 20% 名詞
                // 20% 形容詞+名詞
                // 20% 動詞+名詞
                // 20% 動詞+形容詞+名詞
                // 20% ネイティブラッキーアイテム
                return
                dice < 20 ? nouns.Random() :
                dice < 40 ? adjectives.Random() + nouns.Random() :
                dice < 60 ? verbs.Random().Split(',')[1] + nouns.Random() :
                dice < 80 ? verbs.Random().Split(',')[1] + adjectives.Random() + nouns.Random() :
                GenerateNativeLuckyItem(3);
            }).ToList());
        }
コード例 #2
0
        /// <summary>
        /// 文法を学習します。
        /// </summary>
        private async Task LearnAsync(string text, UserStorage.UserRecord storage, DateTimeOffset now, string apiKey)
        {
            var result = await AnalysisAsync(apiKey, text);

            storage.Set("freetalk.lastLearnedAt", now);

            var    nouns      = storage.Get("freetalk.nouns", new List <string>()).Where(t => !t.IsMatch(@"^[a-z\-_0-9]+$")).ToList();
            var    verbs      = storage.Get("freetalk.verbs", new List <string>()).ToList();
            var    adjectives = storage.Get("freetalk.adjectives", new List <string>()).ToList();
            string?prefix     = null;
            string?noun       = null;

            for (var i = 0; i < result.Length; i++)
            {
                // ルール1: 名詞が連続する場合、その連続する名詞は1語として記憶する
                // ルール2: 接頭辞がある場合、登録時にくっつけて登録する
                // ルール3: next が接尾辞を指す場合、登録時にくっつけて登録する
                // ルール4: 名詞+助動詞(する)を検出した場合、動詞として登録する
                var(surface, reading, pos, baseform, group1, group2) = result[i];
                var next = i < result.Length - 1 ? result[i + 1] : default;

                void RegisterNoun()
                {
                    if (noun != null)
                    {
                        noun += pos == "接尾辞" ? baseform : null;

                        if (!noun.IsMatch(@"^[a-z\-_0-9]$"))
                        {
                            nouns.Add(noun);
                            lastLearnedWord = noun;
                        }
                        prefix = null;
                        noun   = null;
                    }
                }

                switch (pos)
                {
                case "形容詞" when baseform != null:
                    RegisterNoun();
                    adjectives.Add(baseform);
                    lastLearnedWord = baseform;
                    break;

                case "接頭辞":
                    prefix = (prefix ?? "") + baseform;
                    break;

                case "名詞":
                    noun += baseform;
                    break;

                case "助動詞" when baseform == "する":
                    noun += baseform;
                    if (!noun.IsMatch(@"^[a-z\-_0-9]+$"))
                    {
                        verbs.Add("サ変する," + noun);
                        lastLearnedWord = noun;
                    }
                    prefix = null;
                    noun   = null;
                    break;

                case "動詞":
                {
                    RegisterNoun();
                    var verb = prefix + baseform;
                    lastLearnedWord = verb;
                    verbs.Add(group1 + "," + verb);
                    prefix = null;
                    noun   = null;
                    break;
                }

                default:
                    RegisterNoun();
                    break;
                }
            }

            if (noun != null)
            {
                if (!noun.IsMatch(@"^[a-z\-_0-9]+$"))
                {
                    nouns.Add(noun);
                    lastLearnedWord = noun;
                }
            }

            const int limit = 200;

            storage.Set("freetalk.nouns", nouns.Distinct().TakeLast(limit).ToList());
            storage.Set("freetalk.verbs", verbs.Distinct().TakeLast(limit).ToList());
            storage.Set("freetalk.adjectives", adjectives.Distinct().TakeLast(limit).ToList());
        }
コード例 #3
0
        /// <summary>
        /// トークを生成し投稿
        /// </summary>
        private async Task Talk(UserStorage.UserRecord storage)
        {
            if (core == null)
            {
                return;
            }
            if (shell == null)
            {
                return;
            }

            var recent    = storage.Get("freetalk.recent", new List <string>());
            var pollRatio = storage.Get("freetalk.config.pollRatio", 30);

            var now   = DateTime.Now;
            var today = now.Date;
            var hour  = now.Hour;

            var lastBreakfastAt = storage.Get("freetalk.lastBreakfastAt", DateTime.MinValue.Date);
            var lastLunchAt     = storage.Get("freetalk.lastLunchAt", DateTime.MinValue.Date);
            var lastSnackTimeAt = storage.Get("freetalk.lastSnackTimeAt", DateTime.MinValue.Date);
            var lastDinnerAt    = storage.Get("freetalk.lastDinnerAt", DateTime.MinValue.Date);

            // ごはん投票は、毎tickごと抽選する
            var win = core.Random.Next(100) < pollRatio;

            if (win && lastBreakfastAt != today && hour >= 7 && hour <= 10)
            {
                await shell.PostAsync("朝ごはんどうしよ", choices : GenerateChoices(storage));

                storage.Set("freetalk.lastBreakfastAt", now.Date);
            }
            else if (win && lastLunchAt != today && hour >= 11 && hour <= 13)
            {
                await shell.PostAsync("昼ごはんが決まらないので投票", choices : GenerateChoices(storage));

                storage.Set("freetalk.lastLunchAt", now.Date);
            }
            else if (win && lastSnackTimeAt != today && hour == 15)
            {
                await shell.PostAsync("おやつの時間〜.何食べよう", choices : GenerateChoices(storage));

                storage.Set("freetalk.lastSnackTimeAt", now.Date);
            }
            else if (win && lastDinnerAt != today && hour >= 17 && hour <= 19)
            {
                await shell.PostAsync("夜,何食べようかな", choices : GenerateChoices(storage));

                storage.Set("freetalk.lastDinnerAt", now.Date);
            }
            else if (lastLearnedWord != null && core.Random.Next(100) < 10)
            {
                await shell.PostAsync(Topics.Learned.Random().Replace("$word$", lastLearnedWord));
            }
            else
            {
                // ダブリが頻発しないように、直近の抽選履歴を見てかぶらないトピックを抽選する
                string s;
                var    count  = 0;
                var    topics = ExtractTopics().ToArray();
                do
                {
                    s = topics.Random();
                    count++;
                } while (recent.Contains(s) && count < 1000);
                // 1000回超えても被ってしまうのなら諦めて最後に試行したものを採用

                await shell.PostAsync(MapVariables(s));

                // if (!s.Contains("$"))
                recent.Add(s);
                storage.Set("freetalk.recent", recent.TakeLast(topics.Length).ToList());
            }
            lastLearnedWord = null;
        }