いらにか 2023/07/19 22:49

【Mes】チャット風テキスト生成について【書き忘れ小話】

まえおき

Mesにはチャットスタイル形式のHTMLを出力する機能があります。
これは現在のシンプルエディタ(SMWE)でもお試し感覚で使えます。

https://smwe.iranika.info/

ボタンを押すと下記のようなテキストがクリップボードにコピーされます。

<span style="color: #8D9147">いら:</span>どうも、いらにかの半身の"いら"です。
<span style="color: #9E09CA">にか:</span>どうも、もう半分の"にか"です。ってこれは一体なんですか?
<span style="color: #8D9147">いら:</span>今回は対談風テキストをブログに書き起こすときに便利なツールを作ってみたので、それの話をしようかなと。
<span style="color: #9E09CA">にか:</span>なるほど。それで実際にこんなテキストを書いてるのですね。
<span style="color: #8D9147">いら:</span>対談風テキストを書くときって大抵"〈名前〉:〈セリフ〉だよね。
<span style="color: #9E09CA">にか:</span>コロン《:》の代わりに余白とかのケースもありますね。
<span style="color: #8D9147">いら:</span>で、大抵のブログってHTML直書き or WYSIWYGって呼ばれる仕組みを採用してるんだけど、
名前のところを色つけたりとかボールド表示したりとか、いちいちブログのエディタで操作するの面倒くさいんだよね。
<span style="color: #9E09CA">にか:</span>あー、以前”よくわかる道草屋”を作ったときにも苦しめられてましたね
※”よくわかる道草屋”は某サービスの評価試験目的で作られたサイト。スマホじゃないとレイアウトが崩れるのであまり紹介したくない黒歴史。
<span style="color: #8D9147">いら:</span>無駄に思える繰り返し作業が本当にストレスなんだよね。
パソコンに出来ることならパソコンにやらせるべきだし。
あと、シエル学園シリーズは対談系テキストも書く予定だから、いっそのことツール作っちゃおうってことで作りました。

これをCi-enにそのまま貼り付けるとこんな感じ。


いら:どうも、いらにかの半身の"いら"です。
にか:どうも、もう半分の"にか"です。ってこれは一体なんですか?
いら:今回は対談風テキストをブログに書き起こすときに便利なツールを作ってみたので、それの話をしようかなと。
にか:なるほど。それで実際にこんなテキストを書いてるのですね。
いら:対談風テキストを書くときって大抵"〈名前〉:〈セリフ〉だよね。
にか:コロン《:》の代わりに余白とかのケースもありますね。
いら:で、大抵のブログってHTML直書き or WYSIWYGって呼ばれる仕組みを採用してるんだけど、
名前のところを色つけたりとかボールド表示したりとか、いちいちブログのエディタで操作するの面倒くさいんだよね。
にか:あー、以前”よくわかる道草屋”を作ったときにも苦しめられてましたね
※”よくわかる道草屋”は某サービスの評価試験目的で作られたサイト。スマホじゃないとレイアウトが崩れるのであまり紹介したくない黒歴史。
いら:無駄に思える繰り返し作業が本当にストレスなんだよね。
パソコンに出来ることならパソコンにやらせるべきだし。
あと、シエル学園シリーズは対談系テキストも書く予定だから、いっそのことツール作っちゃおうってことで作りました。



この機能は「Mesが脚本特化なら、ブログ向けの対談風テキストとか生成できたら便利なのでは?」 という思いつきで作りました。

地味にキャラごとの色分けが自動化されてたり、個人的に頑張った機能なんですが、シンプルエディタだとサンプルがショボいテキスト生成なので、いまいち便利さが伝わらない感もあったりします。

本題

最近、Ci-enにやってきた川上稔氏がキャラアイコン付きの対談形式っぽい感じで記事を投稿していて、「やっぱり対談形式ならではの面白さってあるなぁ」 と改めて思いました。
※カクヨムで無料公開されている境界線上のホライゾン NEXT BOXもアイコン付きだったのを思い出しました
※参考記事 https://ci-en.dlsite.com/creator/17061/article/914079
※注釈:川上稔氏はR18で活動してるので他記事はえっちなやつが多いです。
 我は大人だぞ?という人はフォローしてヨシ!
 未成年は境界線上のホライゾンを今すぐ買えば、読み終わる頃には大人だと思います(ここ笑うとこ)



さてさて。
シンプルエディタのチャットスタイル形式ではアイコンではなく、色付きテキストの生成になっているので何が関係あるんだという感じですが、実はMesライブラリでチャットスタイル生成を担当しているToChatStyleHTMLメソッドは引数でテンプレート関数を渡せば、好きなテンプレートでテキスト生成ができる仕様になっています。


つまり、ライブラリの利用側が独自のテンプレート関数を作ってメソッドに渡せば自由に変更ができます。



「おい待て、C#で作られたライブラリのメソッド使うにはC#で書かなきゃいけないのでは?サクッと使いたい時に不便じゃねぇか!」

というツッコミをした人に朗報なんですが、11月以降の.NET8対応に向けてリファクタリング中のMesでは強化されたPowerShell用のモジュールも公開される予定です。前の記事でそのことに触れるのを忘れていました。
※ちなみにクラスライブラリは.NET言語ならC#以外でも使えます。あなたもPowerShellに目覚めるのです…(パワーシェル イズ パワー)


まぁ難しいことを多少抜いて話すと、↓こんな感じでPowerShellで独自に作ったテンプレート関数を渡して画像付きチャットスタイルが生成できるようになります。

コンパイラ要らずの動的言語(というかシェル言語)でも拡張しやすくてやったね!

ちなみに、上記は整理前の安定バージョンのライブラリを使っているので、少し冗長なメソッド呼び出しになっています。これはいずれ$mes.ToChatStyleHTML($fn)みたいな感じで簡単に呼び出せるようになります。
MesではC#とPowerShellでの利用を前提に開発を進めているので、ガッツリプログラミングにもサクッとスクリプティングにも耐えられるような設計で進めています。
(まぁ僕が便利なように作ってるだけなのですが)


ただ、この機能をWebエディタに組み込むとなると少し話が変わってきて、色々と難しい感じになるのでそこは今後の課題になっています。
(関数ではなくテンプレートテキストで渡すような仕組みになるので、テンプレートエンジンを組み込んだりetc...な感じで少し厄介なのです)


とまぁ、これを書き忘れていたので今回記事にしました。
まだみなさんが上記の機能を簡単に使える状況にはないですが、使えるようにする予定があるよというご報告でした。


前の記事にも書きましたが、Mesは11月まで開発を凍結してリファクタリングに集中しています。そこから.NET8への移植があるので、年内と年始くらいまではほぼ新たな動きは無いと思ってください。

ぶっちゃけ、ユーザーファーストに開発を考えるならWebエディタの機能拡張に注力して「リファクタしてる暇があったら機能拡張しつづけろ」というのがビジネス的には正解で最適解です。これが仕事ならエディタ開発に注力してる。
ただ、Mesは僕にとって砂場なので、現状はユーザーファーストで動いていません。
Mesは記述言語としてもまだまだ未熟なので、時間をかけて熟成させる必要があると思っています。
エディタに利用しているMAUIも発展途上中ですし、エディタの開発はいま急いでも良くない気がしています。覚えたことが無価値になったり、負の遺産になったりするのが継続的にGUIアプリ開発するときの怖いところです。MAUIの噂を聞いたとき、Xamarinで作り始めなくてほんと良かった……
(Xamarinは.NETに多大な貢献をした素晴らしい技術です)


では、また。


余談 : チャットスタイル形式のテキスト生成のコードの抜粋

ここからは少し高度(?)なプログラミングの話です。
わかる人向けに書くので日本語少なめ。

リファクタリング中のチャットスタイルテキスト生成のコードはインターフェースのデフォルト実装で拡張メソッドが参照されるようになっています。
要はミックスインみたいな感じで、インターフェースを継承するだけでデフォルト実装がクラスに実装される仕組みです。
開発中のMesでは、データ加工処理をクラスの外(外部ファイル)に切り出して、Mesクラスではインターフェースを継承するだけのミックスイン実装を採用しています。
拡張メソッドと違ってMesクラスに実装されるので、PowerShellや他言語からも呼び出しができるのがポイントです。
モックのテストをパスしたミックスイン(インターフェース)だけをMesクラスに継承させていくことで、機能追加が安全かつ安定してできるようになります。
データ加工処理を追加したい外部の開発者は、新しいファイルにミックスインを実装→プルリク送る→OKなら僕がMesクラスに継承させて機能追加→リリースみたいな流れになると思います。
編集するファイルが分離されているので不用意な変更が起こりにくくなり、安全性も高くなるのが個人的に嬉しいです。


下記は開発途中のコードですが参考にどうぞ(参考になるか分かりませんが)

//ChatStyleExtension.cs
using Mes.Core;
using System.Drawing;
using System.Text;
using System.Security.Cryptography;


namespace Mes.Core.Extension;

public interface IChatStyleExtention
{
    public IEnumerable<MesPiece> GetMesPieces();
    public IEnumerable<string> ToChatStyleHTML() => ChatStyleExtension.ToChatStyleHTML(this, ChatStyleExtension.DefaultTemplate);

    public IEnumerable<string> ToChatStyleHTML(Func<MesPiece, string> TextTemplate) => ChatStyleExtension.ToChatStyleHTML(this, TextTemplate);
}

internal static class ChatStyleExtension
{
    internal static IEnumerable<string> ToChatStyleHTML(this IChatStyleExtention mes)
    {
        return mes.ToChatStyleHTML(DefaultTemplate);
    }

    internal static IEnumerable<string> ToChatStyleHTML(this IChatStyleExtention mes, Func<MesPiece, string> TextTemplate)
    {
        foreach (var piece in mes.GetMesPieces())
        {
            yield return TextTemplate(piece);
        }
    }

    internal static string DefaultTemplate(MesPiece piece)
    {
        return $"<span style=\"color: #{CharactorNameToColorCode(piece.charactor)}\">{piece.charactor}:</span>{piece.dialogue}";
    }
    private static string CharactorNameToColorCode(string charactorName)
    {
        using (var sha1 = new SHA1Managed())
        {
            byte[] hashBytes = sha1.ComputeHash(Encoding.UTF8.GetBytes(charactorName));
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 3; i++) // 3バイト分のハッシュ値を使用して6桁の16進数表記に変換する
            {
                sb.Append(hashBytes[i].ToString("X2"));
            }
            return sb.ToString();
        }
    }
}

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

月別アーカイブ

記事を検索