2TBの雑文置き場

ブログというより説明書置き場というか

(アイ)マストドン向けbotシステム「Usa_bot」誕生秘話(?)

まえがき

この記事は、Mastodon 2 Advent Calendar 2017の14日目です。

本日は、数多あるMastodonインスタンスの中で、私がメイン活動場所としているim@stodonにて稼働させている、とあるbotについてお話します。

Usa_bot #とは

Usa_botは、Mastodon向けのbotプログラムです。この文章を執筆している時点では、PHP(ナナ7系)で作られ、im@stodon用にチューニングされたもの1が当方の自宅サーバー(Win)で動作しています。動作している本体はこちら→ウサちゃんロボ(alpha) - im@stodon 現時点ではソースコードは非公開です。

色んな機能がついていますが、一番メインの機能は「簡易辞書」であり、簡単な構文でキーワードとその説明を登録でき、呼び出す際は"公開範囲が「Public」又は「Unlisted2」で、かつ「(キーワード) #とは」(実際には括弧は要りません)というパターンの発言"をすると、キーワードに関する情報を返します。

詳しい動作は説明書を→ウサちゃんロボ 簡易説明書など - 2TBの雑文置き場

開発の経緯

私は、数あるMastodonインスタンスの中で、アイマス好きの人々が集まるim@stodonにばかりよく顔を出しています。なので、他のMastodonインスタンスの雰囲気にはそれほど詳しいわけではないのですが…このim@stodonに関しては、当初から今に至るまで「LTLでチャットのように会話がすすむ」文化がありまして、このような"一定以上の規模のコミュニティ"が発生すると、そこだけで通じるキーワードや言い回しが登場することがあります。会話の流れであったり、既存のキーワードのもじりだったり、その出現パターンは1つではありませんが、それ自体はコミュニケーションを円滑にするために、また楽しい会話をするのにとても便利なものです。

しかし、字面だけでは意味がわからないキーワードやミームが多用されているコミュニティに、新しく人が入って来やすいでしょうか。「よくわからない暗号のような文章」を見て、敬遠して入ってこれなくなったりしないでしょうか。im@stodonでも、かつてそのような懸念が会話に出たことがあります。特に、アイマス関連は既存のキーワード・ミームだけでも相当な数がありますし、それに派生キーワードが増え、更にアイマスとは関係ないim@stodon固有のキーワードまで飛び出しうるとなれば、新規の方の障壁になることは避けられません。私は、何らかの文化が長く続くためにはそれに対する参入への壁は低いほうがいいと考えていますが、アイマスPとしては未熟な立ち位置3のため、自分の手の届く範囲の技術で解決できる方法がないかを考えました。

解決策の1つは、そのようなキーワードを集めた辞書ページを作ることです。ニコニコ大百科ピクシブ百科事典は、まさに典型例と言えるでしょう。とても大きな規模のコミュニティなら有効な手段ですが、Mastodonで使うには、ぱっと思いつくだけでも以下のような問題点があります。

  • 実装とメンテナンスのコスト、参照性の問題
    • 新規キーワードは日々登場し得ます。気軽に使えない登録システムは無視され、放置されてやがて使われなくなるでしょう。
    • ニコニコ大百科ピクシブ百科事典は、もととなるサービスからの連携が前提の仕組みですが、Mastodonに同様の仕組みを組み込むのは無理があります。
      • Wikiのように全部リンクを貼るには負荷が大きそう
      • そもそも、その時にわからない単語だけ調べられればたいてい必要十分
    • 連携させずにまとめサイトだけ作るという考え方もありますが、「見えない」場所にある用語サイトにわざわざ見に行く人がどれだけいるのかはなはだ疑問です。
  • 既存キーワードどうしよう問題
    • すでに指摘したとおり、アイマス関連だけでとんでもない数のキーワードがあります。また、アイマスのコンテンツは大まかに複数のグループに別れており4、別のグループに関しては知らない、ということがよく起こります。それらについても容易に参照できるようにすべきですが、そう簡単にまとめ直せるわけがありません。
    • それに、既存のまとめがあるのにわざわざ改めてデータベースを作るのもなんだかもったいない話です。
  • 荒らし問題・セキュリティ問題
    • だれでも編集できるデータベースでは、荒らし対策を考える必要があります。無認証の場合荒らしに対して無力ですし、認証の仕組みを作るには管理者にセキュリティ情報を抱え込まなくてはならないデメリットがあります。

それらを、(もちろん完全にではないですが)解決、あるいは緩和する策としてUsa_botは誕生しました。

Usa_botの外向きの特徴と(私が考えていた)戦略

  • botなので、普段Mastodonを使うのと同じインターフェイスで使える
  • 「(キーワード) #とは」という文面に反応するので、そもそも存在を知らなくても何かのきっかけで気づける可能性がある。そうでなくても、使い方を教えやすい
  • 登録や修正の際にも、簡易な構文で使えるので覚えることが少なくて済む
  • "Usa_botアイキャッチ"という、一定時間ごとにLTLにキーワード解説を流す機能をつけることで、botの存在を広めつつキーワードの意味を知らしめる
  • 登録できる解説文の文字数は400文字までに制限されている。1Tootに収まる長さで、ある程度簡易な文章にまとめることを求められる代わりすぐ読むことが出来、また修正も追加も難しくない
  • 知らなかったキーワードを毎日LTLに報告する仕組みをつけ、検索されているのにデータがないキーワードに気づきやすくする
  • キーワード解説とは直接は関係ない機能も付けることで興味を持ってもらいやすくする
    • 例えば、Usa_botに「@Usa_bot [myinfo]」とリプライを送ると、発言元のMastodonインスタンスに登録してからの日数と平均Toot数が調べられます。
    • 例えば、Usa_botに「@Usa_bot [dice] 2D6」とリプライを送ると、いわゆる2D6ダイス5を振った結果を返します。
  • ニコニコ大百科と勝手に連動することで、既存キーワードの再登録の手間を軽減する
    • Usa_botにもニコニコ大百科にも存在するキーワードの場合は、大百科へのリンクも貼ることでより詳しい情報へ誘導できる
  • キーワードを表示する際、元のTootのURLを提示して「誰が書いたのか」を明示することで荒らし対策とする
    • 悪意ある書き換えについても、直前のキーワード登録者にデータが更新されたことを通知することで緩和策とする

とにかく気軽に使え、また存在に気づいてもらいやすくしつつも、LTLを邪魔しないのを当初の目標としました。

Mastodonの仕組みとキーワード解説に対する連動を考えた時、最も相性が良いのはbotであることは明白です。普段使っている画面からそのまま利用でき、複雑な操作もありません。専用ソフトも要らないので環境依存問題もありません。キーワード解説に長文登録できないことがネックですが、逆に気軽に登録することが出来るメリットと言えるのではないかと考えています。

「○○ #とは」という言い回しはTwitterでも定着したミームであり、使用するにあたって不自然ではない、またUsa_botを知らなくても使用する可能性がある言い回しであることが採用理由となっています。実際、新規にim@stodonにいらっしゃった方の中には、自力でUsa_botに気づいた方もいらっしゃるようです。(ありがたいことです また、im@stodonでは過去のアップデートでハッシュタグ付きの発言が未収載のものでもハッシュタグタイムラインに流れるようになっており(管理者であるフサギコさんの解説記事であるアイマストドン通信 (β) 2017/09/10 | EntyやAdventCalendar記事のこのIP網の片隅で : アイマストドンの7ヶ月半をgithubのPRベースで振り返るも参照)、Usa_botはそれを含めた「#とは」のタイムラインをチェックしているため、LTLに発言を流すことなく(つまりLTLを押し流すことなく)検索を利用できます。前述のとおり、im@stodonではLTLで会話が行われているため、会話を邪魔せずに調べ物が出来るという特徴はとても重要です。

既存キーワードへの参照問題は、既存のWikiやまとめを利用できれば解決します。参照先としてはニコニコ大百科を採用しました。理由は以下のとおりです。

  • 十分な規模がある
  • アイマスは「ニコニコ御三家」と呼ばれるほどニコニコとの相性がよく、情報がとても良くまとまっている
  • キーワードの存在を簡易に調べられるAPIが存在する

幾つかの、本来の機能とは無関係な機能がついています。これも、遊んでもらってついでに本来の機能にも気づいてもらえればと言う戦略です。あと単に面白そうだから

この手の文章登録システムは、荒らしとの戦いの歴史と言ってもいいでしょう。Usa_botでは、登録時のTootのURLを、キーワードが参照された時に同時に提示することで「誰が書いたのか」を明示し、荒らしに対する抑制としています。これは、LTLで会話が進む特殊性と、比較的大きすぎない6規模のコミュニティだからこそ有効な手段と言えるでしょう。

すべてが丸く収まらない:Usa_botの問題点

極力簡単に、平和に使えることを目指しているものの、それでも問題点はあります。すぐに思いつくだけでも、

  • データメンテナンスが保証されない
    • Usa_botに限った話ではありませんが、古いデータが古いまま放置される可能性があります。Usa_botアイキャッチなどで中の情報が目につくようにするなど、更新漏れに気づきやすい環境を整えてはいるものの、とうてい完全とはいい難いところです。また、今はまだいいですが、項目数が増えれば増えるほど古い情報により気づきにくくなっていく問題があります。
  • 小規模インスタンスにも大規模インスタンスにも向かない可能性がある
    • たとえばPawooやmstdn.jpクラスの規模では、確率的に悪意に対抗しづらいと考えられます。
    • 事実上LTLの一部を乗っ取ってしまうため、大規模インスタンスの場合、その運営サイドが設置するのでなければ「Twitterで特定キーワードに反応してリプライが届く」みたいなスパムまがいのbotと大差ない動作になってしまいます。
    • 数人~数十人規模の場合、そもそもこの手の仕組みが必要ないかもしれません。内輪ネタであっても、全員が目の届く範囲の人数なら、通じにくいということ自体が起こりにくいでしょう。
  • Usa_bot自体が障壁になりうる
    • Usa_botは、現時点では実質im@stodonで動作する独自機能であるかのように見えてしまいます7。知っていたら便利だけど、知らなくても問題なくim@stodonが使えるのが大前提ですが、Usa_bot自身が内輪ネタ的にとられる可能性は考慮しなくてはなりません。
    • 個人的には、im@stodonを使ううえで、仮にUsa_botを「知っていなければならない」状態に陥ったら「負け」だと考えています。

技術的な話

大層なことを書いていますが、Usa_botは技術的にはそれほど大きな特徴があるわけではありません。PHP7で実装されていることは既に書いたとおりですが、大まかには以下のような環境で動作しています。

  • Win+PHP7+SQLite
  • ソケットを使ったクライアントプログラムとして動作しており、ApacheIISといったhttpdを必要としない
  • その代わりCLIPHPを立ち上げる何らかの仕組みを組んでおく必要がある
    • 運用上は、起動用バッチファイルが組まれていて、サーバー起動時に実行されます。

Mastodonから届くデータはJson形式で、そこにはUsa_botのようなbotを動かす程度なら十分なデータが全て含まれています。発言者の名前や登録日、発言数、今回の発言内容、発言に含まれるハッシュタグの一覧…。Usa_botがやっていることは、それをストリーム接続経由で受信し、応答すべき形式なら然るべき応答を返す。それだけです。 強いていうなら、Usa_botに実装されているコマンドはそれぞれが分割されたファイルであり、プラグインを追加するように機能を足していける構造になっていることが工夫点ではあるのですが、そのへんは将来的にコードを公開できればと思っていますのでそのときにでも。

…真なる目的、そして

先だって、Usa_botは「im@stodonへの参入障壁を低くするために作った」と書きました。これは嘘ではありません。7日に公開した「やきゅべんと」 Advent Calendar 2017 - Adventarの記事であるUsa_botがはじききする話 - 2TBの雑文置き場で文末に載せた以下の記述は、偽らざる気持ちです。

この機能が、あるいはUsa_botが、これまでのアイマストドンユーザーと、これからのアイマストドンユーザーを緩やかにつなげる事ができたら、それはとても幸せなことだと思います。そうなれるよう、今後もUsa_botは進化・変化を続けていきます。

ですが、それが第一目的だったかと問われると、それもまた違ったりします。

…とはいえ、これはMastodonとは本当に一切関係なくなるので、この場でお話するのは止めておきます。もしご興味がありましたら、アイドルマスター Advent Calendar 2017 - Adventarで12/17公開予定の記事をご参照いただけますと幸いです。

最後になりますが、ウサミンこと安部菜々さんをよろしくお願いします8。2TBでした。

バトンタッチ

兄弟カレンダーの中の亀さんの記事もよろしくお願いします。

明日は、カレンダーの2の方は宮原太聖(ミハ)さん、1の方はらりお・ザ・㉅㊛の🈗然㊌ソムリエさんです!


  1. 専用チューニングしてるというと特別なことをしているようですが、(記述時点で)コード非公開プログラムかつim@stodon向けのものしか存在しないので、汎用性を考慮していないだけです。

  2. im@stodonでのみの特徴です。後述。

  3. アイマスAdventCalendarでも書く予定ですが、積極的にコンテンツに触れるようになったのは昨年末くらいからです。

  4. 「765AS」、「シンデレラガールズ」などの分け方のことを意図しています。アイマスをご存じない方は、「アイマス」という大きな枠組みの中に複数の作品があって、それらが大まかにグループ化しているとご理解いただければ。

  5. 6面ダイスを2個振る、という意味

  6. 大きすぎないと言っても、登録2000人を余裕で超えるim@stodonがそのような表現の規模なのかというのはありますが、

  7. 念のためですが、Usa_botは2TBの個人的プロジェクトです。im@stodon公式ではありません(勝手にやっているということです)。LTL上の発言を拾って動作するので、対外的には独自機能と同等に見える、という意味です。

  8. これ、「本当の理由」ほとんど明かしたようなもんですねえ…

Usa_botがはじききする話

実質的に、中身はタイトルで全て語られています

この記事は、「やきゅべんと」 Advent Calendar 2017 - Adventarのナナ日目の記事です。のっけから余談ですが…私は今年のAdventCalendarは今日以外には14日のMastodon 2 Advent Calendar 2017 - Adventar、17日のアイドルマスター Advent Calendar 2017 - Adventarに参加しており、日付には一定の法則があったりしますがまあどうでもいいですね。

「やきゅべんと」の昨日の記事は、ばりっぴさんの無駄に歴が長いだけのP目線で見るこの12年でした。先達の方々がいるから、今私はここにいますよ。

はじきき #とは

そもそも「はじきき」とはなんでしょうか。Usa_botには、この記事を投稿する時点では次のように登録されています1

「はじめましてとききまして」の略。新規参加者の方が「はじめまして」(に類する言葉)を話すと、どこからかPが沸いて出て来るとか来ないとか。
https://imastodon.net/@twoterabytes/1504430

私が入り浸るMastodonインスタンスであるところのim@stodonでは、新たな参加者を発見すると、場にいる他の参加者やROMってた人たちが一斉に湧いて出てきては、わいわい歓迎したり隙を見て自らの担当(ファン・推し・係その他を含む)アイドルのダイマに持ち込んだりする風習があります。ご新規の方がこれをどう感じるかは人それぞれでしょうが、おおむね良い方向に受け入れてもらえている印象を受けます。

さて。上の説明のとおり、ご新規の方が「はじめまして」とか「こんにちわ」とかわかりやすい発言をしてくれたなら、その存在には気付きやすいといえるでしょう。あるいは、初回発言時にデフォルトアイコンのままであるとか…。しかしながら、中には「初手ダイマ」「ふわっと流れに乗る」など、高度なムーブをする方もたまにいらっしゃいまして、稀ではあるものの、ご挨拶すらままならないまま会話が流れていくのを目の当たりにしたこともあります。

ところで、im@stodonの中には「自作クライアント勢」とも言える、WebUIや一般公開のスマホアプリに頼らないでMastodonにアクセス・投稿をするグループの人種の方がおり、そのような方の中には「はじきき検知機能」を持つクライアントを使用している方もいらっしゃるようです。なんとぉ!、MastodonAPI2で受信できる投稿には、その投稿をしたユーザーが過去に何回投稿をしたかの情報が含まれているので、それが小さければ必然的に新規の方だとみなすことが出来るわけですね。つまり、みんながそのようなクライアントを使用すれば、容易にはじききを知り、挨拶も可能となります。でも、自作クライアントなんて誰でも作れるわけではない…。

じゃあ、だれでも使える検知機能があれば良いんじゃない?

Usa_bot「はじきき」

ということでUsa_botが今日からはじききを検知します。使い方は簡単、Usa_botをフォローしておくか #Usa_botはじきき を監視していると、ご新規と思われる方が見つかったときにUsa_botがこっそり発言しているのを確認することが出来るでしょう。なお、発言は未収載で行われますから、検知がLTLに流れることはありません。現状の仕様は以下のとおりです。

  • 発言回数が3回以下のときにLTLにコメントが流れてきた場合、ご新規の方とみなします。
  • ただし、過去数時間以内にすでに発言している場合を除きます。
    • わかりやすく言うと、1回目を検知していたら2回目3回目の発言は通常検知しません。
  • 検知しかしません。IDをわかりやすく表示したりはしません。

いろいろ穴のある仕様だとは自覚しています3が、まあ大きな問題になることではないかなあとか。とはいえ、正直なところ、im@stodonに対してごく小さな変化にとどまるか大きな違いになるかは読み切れていないところはあります。この機能を継続して有効にするか、範囲は、などは様子を見て調整する予定です。

おわりに

この機能が、あるいはUsa_botが、これまでのアイマストドンユーザーと、これからのアイマストドンユーザーを緩やかにつなげる事ができたら、それはとても幸せなことだと思います。そうなれるよう、今後もUsa_botは進化・変化を続けていきます。お気づきの点があれば、im@stodonで2TB宛にメッセージを頂くか、鳥ことTwitterででもお知らせください。

明日はBitconnectさんです。お楽しみに!


  1. 自分で書いておいて「登録されています」もないもんですが

  2. Application Programming Interface。そのプログラムの機能に簡単にアクセスできるよう設計された窓口みたいなもの。Mastodonでは、投稿を受け取ったり投げたりするのに使える。

  3. 例えば、あらかじめ未収載で3回以上TootやBTしていれば検知されませんし、初tootから次に発言するまで半日とか置いていると再検知したりします。

Usa_botに、「ウサミンコード」というプログラミング言語を実行する機能をつけました

概要

ウサミンコードは、たった8種類の文字の並びだけで構築できるプログラミング言語です。おそらくピンときた方もいらっしゃると思いますが、これはいわゆる「Brainf*ck」(以降BF)の文字を別のものに置換した派生言語に相当するものです。

命令と言語としての仕様

BFの各命令を、以下の文字で代替します。

BF命令 ウサミンコード命令 実行内容
> ポインタをインクリメントします。
< ポインタをデクリメントします。
+ ポインタ位置の値をインクリメントします。
- ポインタ位置の値をデクリメントします。
, 入力から1オクテット読み込んで、ポインタ位置に代入します。
. ポインタ位置の値を出力します。
[ ポインタ位置の値が0なら、次の「々」の直後の命令までジャンプします。
] ポインタ位置の値が0でない時、直前の「菜」の直後の命令までジャンプします。

その他の言語としての仕様は基本的にBFと同じです。

実行環境と、処理系としての仕様と制限

アイマストドン上で稼働している、Usa_botが実行機能を持っています。また、BFを実行できる環境において、命令を別の文字に変更できる処理系があれば、そちらで実行させることが出来ます。

Usa_botについては→http://twoterabytes.hatenablog.com/entry/2017/05/25/091430

Usa_botで稼働するウサミンコード処理系には、言語としての仕様や制限とは別に、以下の仕様・制限があります。

  • 入力できるコードは480文字まで
  • 「安」で標準入力をわたしたい場合、複数回に分けて渡すことは出来ない。実行時にすべて渡す必要がある
  • 1命令の実行を1ステップとして、10000ステップまで
  • コードの実行時間は0.1秒まで
  • 文字コードUTF-8を用いる
  • 出力もUTF-8として解釈し、それでは解釈できない場合は16進文字列に変換して出力する

実行例

こんな感じ

実装の理由

いやその、Halloween ❤ Codeって曲があるし、usamin ❤ codeってのも面白いかなって…

Usa_botの「とは検索」の適用範囲の変更と、その意図について

Usa_botは、「○○ #とは」というキーワードに反応して説明文を返していますが、従来はUsa_bot自身に登録されている完全一致するキーワードか、ニコニコ大百科に登録されている、やはり完全一致するキーワードのみに反応していたため、よく似たキーワードなどでは反応せず、必ずしも最適な結果が返せているとは限りませんでした。これを、本文なども含めキーワードがヒットすれば結果が返るようにし、より広範なパターンで調べやすい状態となるようにしました。

これには、以下のような意図があります。

  • より簡単に検索できるようにすることでもっと気軽にUsa_botを使って欲しい
  • 本文でもヒットするようにすることで、略称などを本文に含めておけば調べられるようにしたい

これにより、使う人にとっても、キーワードを登録する人にとっても負担を減らすことができるのではないかと考えています。特に登録については、従来は略称を反応させようと思ったら細かな表記違いの略称・別称をすべて新規キーワードとして登録する必要がありましたが、これからは本文に含めておけばいちいち登録する必要はありません。

懸案事項

概ね利点が大きいと考え今回の変更を行いましたが、懸念がないではないです。

  • 従来より反応しやすくなったため、おせっかい度が上がった
  • 意図しないキーワードで反応することがある

様子を見つつ、過剰反応するようであれば対策を考えたい所存です。

緊急時・極小ロット向け セブンイレブン名刺作成のすすめ

問題設定

  • 名刺を切らした場合に、緊急時に用意する方法がほしい
  • 「名刺 コンビニ」などで検索すると幾つか手法が出てくるが一般には写真印刷を使うようで、そうではなく普通の名刺っぽい紙に作りたい

大前提:名刺は発注したほうが断然・確実に、格段に安く便利で仕上がりも良い

先だって、とある目的のため1に自作の名刺を作成しました。こんなの↓

f:id:twoterabytes:20170805095632j:plain

発注先は、先輩Pの間で有名だというマヒトデザイン様にお願いしました。 片面カラー上質紙180kgで、390(制作費)+160(送料)=550円。100枚ですので、1枚5.5円。土曜日に発注したのに翌水曜に届く素早さでこれです2

つまり、発注して届くタイムラグが許容でき(しかもそれは最大で1週間程度)、1単位100枚が多すぎなければ、外部発注のほうが圧倒的にローコストです。 これから紹介するコンビニ印刷の方法は、カラーの場合2枚ごとに60円、単価で30円と実に5.4倍以上の価格であり、しかも印刷後に自分でカッターなどを使って 切り離す必要があります。発注名刺は当然裁断された状態で届きますので、仕上がりもよく手間もありません。さらに、今回の方法は現状で幾つかの問題を抱えています(後述)。

それでもコンビニ名刺を用意しておく意味はあります。なにしろ、データはスマホに入れておけばいいので可搬性抜群。 名刺を切らしていたり、そもそも名刺を持っていないタイミングでも、そこにセブンイレブンがあれば簡単に名刺を用意することが出来ます。 データ作成に関しても、複雑な作業は殆どありませんし、発注名使用のデータが有ればそれを流用できます。

そういうわけで、あくまで緊急用ではありますが名刺作成の方法などを以下に。

コンビニ名刺用データの作り方と印刷方法

まず、以下のテンプレートを保存します。ただの画像です。幾つかの理由により、350dpi相当のデータとなっています。 枠線版とトンボ版がありますが好みでどうぞ。2重トンボになっていないのは、そんなスペース無いからです。 2重トンボ(相当)に出来ないので、ちょっと小さく切らない限り、切り離した名刺には必ず枠線が含まれます。これが1つ目の問題。 (※サムネイルが黒くなっていますが、オリジナル画像ではちゃんと枠線が見えます。左が枠線版、右がトンボ版です。透過画像の関係ですシクシク)

 

要は、この枠の中に印刷したいデータを描いて、それを保存しておけばよいわけです。印刷時の注意点は以下。

  • セブンイレブン専用の方法
    • はがき印刷を使う関係で、標準ではがきが用意されているコンビニで印刷する必要があります。調べた限りセブン以外の大手ははがき印刷に対応していないようです。これは2つ目の問題点です。
  • レイアウト印刷ではなく、そのまま印刷を選ぶ
    • すでに最適な大きさに設定されています。
  • 「ちょっと小さめ」に「しない」
    • フチが切れるのを防止する機能があるのですが、そうすると画像の大きさが変わってしまうため一般的な名刺サイズではなくなります。

そうして刷ってみたはがきを、光に透かしてみたのがこちら。

f:id:twoterabytes:20170805095930j:plain

わかりづらいかもしれませんが、上の名刺は表の切手貼り付けスペースとかぶってしまっていますね。印刷位置のズレの 可能性を考えた時、これはいくら調整しても回避は難しいと考えます。これが3つ目の問題3。 なお、切手スペースを避けようとテンプレ位置を下に下げすぎると、こんどは名刺データそのものが印刷スペース外に出てしまい 切れてしまう可能性があり本末転倒な結果になります。現在のテンプレは名刺として完成できる方を優先したものです。 私の現行の名刺のように、背景が白いタイプなら枠線が消えることを許容して下にずらすのは有りかもしれません。

あと、仕様上両面印刷に対応しません。人によっては問題になる可能性があります。

コンビニ名刺まとめ

まず利点。

  • データをスマホに入れておけば、その他の媒体(USBメモリとかSDカードとか)を持ち歩かなくても印刷できる
    • クラウドサービスに入れておくようにすれば、スマホに転送する手間すら無い
  • 例えば名刺を切らしてしまった場合に、その場で準備できる
  • 発注名刺のデータがあれば流用できるので制作の手間はほとんどない
  • 発注名刺を頼む前に、どんなふうになるか試して妄想できる
    • 実際には印刷方法が同一とは限らないため、仕上がりには差があります。でも妄想はできるでしょ?

そして欠点。

  • 高い
  • 印刷後切り離す必要があり手間、また切り離す道具が要る
  • 完成名刺に枠線が入ってしまう
  • 手法の関係でセブンイレブン限定の方法
  • 1枚目の名刺の裏に切手スペースがかぶるか、2枚目の名刺の一番下が切れるかどちらかを許容しなくてはならない
  • 両面印刷は出来ない

幾つかの欠点については、工夫の余地があります。たとえばセブン限定でなくするためには、写真用紙に印刷するようテンプレートを新しく作る方法があります。 光沢紙への印刷になるので名刺っぽさが失われる欠点がありますが汎用性が高まりますし、L版に1枚ずつ出力したりA4印刷にして一度に10枚出力するなどの考え方も使えるでしょう。 このあたりは、名刺がどのようなシーンで、どう必要になるか、またそれに対してどこにどういうこだわりを持ちたいかで話が変わってくるところかと思います。

個人的にはやはり発注名刺をおすすめしたいところですが、それはそれとして、保険としてのこういうデータを持っておくのもいいんでないかい?というご提案でした。

余談1

実は、冒頭に示した発注名刺を作った時に、裏面に「特殊な光を当てるとウサちゃんロボが浮かび上がる」というのをやりたくて、こんな小細工用道具を作ったんですよ。

f:id:twoterabytes:20170805100134j:plain

結局そちらの計画はうまく行かず頓挫しました4が、その際に「この紙の感じだったら、名刺そのもの作れるんじゃね?」と思い今回の記事に至りました。

余談2

発注名刺に載っている「担当」の名前は、「安部菜々」「佐藤心」です。いずれも、アイドルマスターシンデレラガールズに登場する、両名ともにアイドル活動に直球の 私一押しアイドルです。近年では某ニコニコ動画でちょっと変わった流行り方をしましたがまあそれはいいです。 ウサミンこと安部菜々さんをよろしくお願いします。はぁとさんこと佐藤心さんをよろしくお願いします。


  1. まあ名刺に書いてある内容でおおよその用途はわかりそうですがいわゆるP名刺です。5thSSA後のオフ用です。

  2. 送料の設定から分かる人にはわかることですが、今回はクロネコDM便指定でお願いしています。私は神奈川住まいですので、参考にする場合はそのへんうまいこと読み替えてください。

  3. なお、上手いこと微調整すれば最適な場所が見つかる可能性はありますが、わたしも(数十円とは言え)予算は無限ではないので…

  4. 切り取った部分を名刺にあて、ダイソーで売られている「マジックライトペン」で縁をなぞる方法で試しました。線がガッタガタになる。器用な人ならうまくいくかも…

PHPのimagecropautoが便利な話

タイトル読んだらそれで終わりな記事。

前置き(読まなくても良い

(回り道酷いです)

先日、とある理由でLightning - Digital AVアダプタを入手しました。目的の方はいまいちだったのでこれから試行錯誤なのですが、まあそれはそれとして、既存環境と組み合わせることで副産物的にiOSバイスHDMIキャプチャが可能となりました。で、そうなると例えばアプリの画面を録画したりも出来る(アプリ側で著作権制御がされていない場合)わけで、P1の端くれ的には画像ダイマに便利な環境が整ったといえるでしょう。

しかし。

アプリ側の対応の問題なのか、自分のやり方が良くないのかは調べきれていない為不明ですが、私の環境(後述)でデレステ2のMV3をキャプチャすると以下のような黒枠のある状態になってしまいます(以下は動画として記録したものから画像を取り出したものです)。

f:id:twoterabytes:20170704103157j:plain

オーバースキャン対策でしょうか?まあ理由は重要ではありません。今大事なのは、個人的にこの黒枠が邪魔ということです。画像処理で消してしまいましょう。

課題設定

  • 以下の環境・手順でキャプチャした画像の、上述サンプル画像に現れるような黒縁を画像処理で消去したい
    • iOSバイスからLightning - Digital AVアダプタでHDMI出力し、AVT-C875でPCに取り込み
    • ハードウェアエンコード環境を活かすため、純正ソフトで録画しMP4で出力する
    • 動画から任意フレームの画像をキャプチャし保存する

どうすればいい?タイトル読んでください

そこでimagecropautoです。こうします。

<?php

$original_image = imagecreatefromjpeg('cute_eternal17_origin.jpg');
$cloped_image=imagecropauto($original_image,IMG_CROP_THRESHOLD,0.5,0);
imagejpeg($cloped_image, 'cute_eternal17_crop.jpg');
imagedestroy($cloped_image);

f:id:twoterabytes:20170704103207j:plain

PHP: imagecropauto - Manualを見ると、「この関数は、 現在のところ詳細な情報はありません」と書いてある割にはそれなりに詳細な情報を得ることが出来ます。要は、一定の条件に従って画像の4辺のフチを切り離してくれます。目的や状況によって様々だろうとは思うものの、事実上IMG_CROP_THRESHOLDが一番使い勝手いいと思います。

IMG_CROP_THRESHOLD
threshold と color を用いてクロップします。
threshold
画像の色とクロップする色を比較する際に用いる許容誤差を、パーセントで指定します。 色の違いを判断する際には、RGBキューブ内での距離を用います。

IMG_CROP_THRESHOLD モードのときにだけ利用します。

color
RGB値あるいはパレットインデックスを指定します。

IMG_CROP_THRESHOLD モードのときにだけ利用します。

完全に黒とわかっている場合ならthresholdは0で良いですが、先述の環境の通りMP4からの切り出しですので、フチはほぼ確実に完全黒ではないと断言できます。どれくらいを設定すべきなのかは状況によりけりでしょうが、例えば今回の例に使った画像の場合0.5%指定で上下に黒い線が1本残っています。その辺許容できるかどうかは用途によるでしょう。

補足:絶対位置指定じゃだめだったのか

もちろん、今回の環境のみであればそれでもいいはずですが、自動的に判定してくれる方が応用幅が広いよねと言うだけ。

ちなみに

私はこれをim@stodonでダイマ4するために使っています。実際にはもっと手を入れて画像をcropして縮小しjpgに保存し直すところまで自動化されており、ファイル容量を削りモバイル環境下の人などにも広く画像が行き渡るようにしつつサーバー負荷を抑える効果があるよう工夫しています。

ところで

サンプル画像に写っているのは、アイドルマスターシンデレラガールズに登場するアイドルの一人、安部菜々さんです。もしデレステなりモバマスなりに触れる機会がありましたら、この永遠の17歳アイドルのウサミンこと安部菜々さんをよろしくお願いします。


  1. P:プロデューサー(アイドルマスター)のこと。アイマス関連のゲームプレイヤー/コンテンツ利用者やファンを指す言い方として定着しています。

  2. デレステアイドルマスター シンデレラガールズ スターライトステージの略称。大雑把に言えばいわゆるリズムゲーム

  3. MV:デレステで特定の条件を満たすと、収録楽曲のムービーを自由に好きなだけ見ることができるようになる。そのムービーのこと。

  4. ダイマ:ダイレクトマーケティング。ここでは直接的な、あるいは露骨な宣伝くらいの意味。

漢数字混じりの文字列を半角数字に変換したい

方針

ステートマシンとして実装するのが良い気がする 先頭から文字を抽出してゆき、それぞれの文字に応じた処理をする。

  • 状態メモリ
    • 3個。4桁以下の数値用[C]、5-8桁用[B]、それ以上用[A]。 先頭から数字を処理してく関係上、3つ目のメモリを除いて8桁以上の値になることは(通常の表記を守る限り)ない。
  • 文字の種類別の処理
    • 〇一二三四五六七八九【数字】 [C]を10倍してからこの値を加算する。ただし、フラグが立っている時は加算のみする。フラグを除去する。
    • 十百千【接頭辞1】 [C]が0の時、1にする。[C]を指定倍率分乗算してから[B]に加える。フラグを立てる。[C]をクリアする。
    • 万億兆…【接頭辞2】 (C+B)を指定倍率分乗算してから[A]に加える。フラグを立てる。[C][B]をクリアする。
    • 、(読点),(カンマ) (スペース)【スキップ】 何もせず次の文字に移動する
    • その他の文字【終了】 処理を終了する

この仕組みは、小数点以下の数字を無視する。また、ロケールは日本に最適化されており、例えば小数点をカンマで表現する地域の値には対応しない。

条件

  • コードはUTF-8を前提としており、またPHP7系列でのみ動作の確認を行っている。
  • ライセンスは2条項BSDライセンスとする。

実コード

軽率に作ったのでクラスですらないし、とりあえずblogに貼ってしまう。一発ネタっぽいし。

updated

  • 20170615-0900ごろ
    • 四則演算にbc math使うようにしたので大きい数字でも変になりにくくなった。
<?php

/*
Copyright 2017 2TB/twoterabytes

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

function jnum2num($str){
    $numberlist=array(
        '〇' => '0',    '零' => '0',
        '一' => '1',    '壱' => '1',
        '二' => '2',    '弐' => '2',
        '三' => '3',    '参' => '3',
        '四' => '4',    '肆' => '4',
        '五' => '5',    '伍' => '5',
        '六' => '6',    '陸' => '6',
        '七' => '7',    '漆' => '7',
        '八' => '8',    '捌' => '8',
        '九' => '9',    '玖' => '9'
    );
    $prefix_a=array(
        '十' => '1',    '拾' => '1',
        '百' => '2',    '陌' => '2',    '佰' => '2',
        '千' => '3',    '阡' => '3',    '仟' => '3'
    );
    $prefix_b=array(
        '万' => '4',    '萬' => '4',
        '億' => '8',
        '兆' => '12',
        '京' => '16',
        '垓' => '20',
        '𥝱' => '24' ,'秭' => '24',
        '穣' => '28',
        '溝' => '32',
        '澗' => '36',
        '正' => '40',
        '載' => '44',
        '極' => '48'
    );

    $str=mb_convert_kana($str,'KVa');
    $str=str_replace(array(',','、',' '),'',$str);
    $numstr=preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY);

    $mem_a='0';
    $mem_b='0';
    $mem_c='0';
    $nonpower=FALSE;
    foreach($numstr as $val){
        if(array_key_exists($val,$prefix_a)){
            if($mem_c=='0')$mem_c='1';
            $mem_b=bcadd($mem_b,bcmul($mem_c,bcpow('10',$prefix_a[$val])));
            $mem_c='0';
            $nonpower=TRUE;
            continue;
        }

        if(array_key_exists($val,$prefix_b)){
            $mem_a=bcadd($mem_a,bcmul(bcadd($mem_b,$mem_c),bcpow('10',$prefix_b[$val])));
            $mem_b='0';
            $mem_c='0';
            $nonpower=TRUE;
            continue;
        }

        if(array_key_exists($val,$numberlist)){
            $val=$numberlist[$val];
        }

        if(is_numeric($val)){
            $mem_c=($nonpower)?bcadd($mem_c,$val):bcadd(bcmul($mem_c,'10'),$val);
            $nonpower=FALSE;
            continue;
        }
        break;

    }
    return bcadd($mem_a,bcadd($mem_b,$mem_c));

}