Discord に音楽 bot を導入する

導入したんだけど、色々ハマったのでメモ。

Discord はこれ。導入したのはMusicbot

試し導入段階

手元のMacbook Proのターミナルで試しに起動してた。特にハマることもなく通常起動。

導入はここを参考にした。ここは Windows での導入について書いてあるけど、Mac OS X でも OK。

Python は 3.5+ っぽくて、起動するファイルは runbot.bat じゃなくて ./run.sh の方。環境によっては権限がないので、chmod u+x ./run.sh してから起動する。

でも Permission 周りが結構難しくて、サーバに居る人間全員に権限を渡すために色々調べた。

Discord にはサーバごとに役割(役職?)が存在していて id が割り振られてる。それを元に権限とかあげる感じ。最初は導入者にしか権限なさそう?

権限についてはここ参考に。役職/個人の id 取得についてはここ参考にすると良いと思います。

簡単に書くと、config/permissions.ini で権限を全部管理してて、ある役職の人間全員に権限をあげたかったら GrantToRoles に役職 id を、個人に上げたかったらUserList に id を羅列する。

権限にも色々グループがあって、[Default] / [MusicMaster] / [DJ] / [Limited] の 4 つがある。Default は基本いじらず、残りの 3 つに id を追加する。サーバーに居る人間が信用出来ない場合は Limited に入れるとよい。

ちなみに、権限管理するのめんどいから全員に MusicMaster の権限あげたい!!ってときは、とりあえず bot を起動して、!listids すると bot が DM で id のリストを送ってきてくれるので、その中にある Role IDs: @everyone: ************* を持ってくれば OK。公式では非推奨らしいです。

Ubuntu 14.04.5 LTS に導入

手元でずっと起動しっぱなしなのも面倒になってきたので、Ubuntu on さくら VPS に導入する。

動かしてた Musicbot のファイルをそのままサーバ上にあげて、./run.sh すると次のエラーがでる。

RuntimeError: Could not load an opus lib. Tried libopus-0.x86.dll, libopus-0.x64.dll, libopus-0.dll, libopus.so.0, libopus.0.dylib

色々調べてもよくわからなかったんだけど、色々やってたら直って動いたので直接的に関与してそうなことをメモ。

まず、このエラーって既知で、libsodium-dev がないときに起こるらしい。参考:Unable to locate package libsodium-dev · Issue #296 · SexualRhinoceros/MusicBot · GitHub

$ sudo apt-get install git python3.5 python3.5-dev ffmpeg libopus-dev libffi-dev libsodium-dev -y

をそのまま実行すると、libsodium-dev が見つからんって怒られる。どうやら apt-get の list にないらしい?ので、以下を実行。

$ sudo add-apt-repository ppa:chris-lea/libsodium
$ sudo apt-get update

で、もっかい実行すると無事にインストール出来てハッピー。Musicbot を起動してみると無事に動いてサーバーにも接続してくれた。👏

ついでに、Musicbot に関することを書いておくと、niconico の動画を投げても流してくれる。soundcloudyoutube のプレイリストにも対応。でも audio_cache は自動的に消してくれないっぽいので、手元じゃなくてサーバで動かす場合は自動的に消すなんかを作っておいたほうがよさげ。わたしは tmpwatch を cron で動かすことにしました。

ということで、Splatoon 界隈のみなさんももっと導入しましょう!!!!!!!!!!!!

twitter のリストメンバーに一部改変可能なテンプレDMを送る

今度 Splatoon の大会主催するんですけど、それにあたって需要があったので書きました。

したこと

  • Twitterリストのメンバー一覧を取ってくる
  • 登録データをcsvファイルに落として、パースする
  • 登録データを元にTwitterリストのメンバーにDMを送る
  • DM の内容はテンプレだけど、各自異なった内容になる

使ったもの

Python 3.5.1 で書きました。Python むずい。ライブラリは twitter, csv(標準であるらしい、すごい)。

流れ

はじめにcsvファイルを読み込んで一行一行をリストで保存する(csvファイルの1行 = リストの1要素)。そんで、twitterリストのメンバー一覧を持ってきて、あるメンバーがcsvファイルのどこに居るのかを調べて、もし居たらそのひとに DM を送るって形です。こういう形になってるのは、リストにDMを送らなくてもよいユーザがいるからですね。

で、ソースを見ればわかるんですがO(n2)になってて、その原因は登録データでは「さく / li_saku」になっていて、twitterリストのメンバー一覧では単なる「li_saku」なので、リストなめるときにいちいち登録データの中身を全探索してました。あと、大文字小文字が面倒だったのであらかじめ全部小文字にしておきました。

登録データを参照して個別にテンプレのいち部分が違う内容の文章を送りたかったので聞いてみたら、どうやらstr.format()がかなり優秀らしいので、それを使いました。使い方はここ見たほうが早いと思います。めっちゃすごい。便利!!!!!

登録データは次のような感じでした。

受理番号, チーム名, リーダー, NNID, 得意ステ1, 得意ステ2, 不得意ステ1, 不得意ステ2

ソースコード

# coding:utf-8

from twitter import *
import csv

t = Twitter(
            auth = OAuth('ここに', '自分の',
                       'アクセストークンを', '入れる')
           )

ret = t.lists.members(owner_screen_name = "li_saku_ika", slug = "sakurako", count = "100")

csv_file = csv.reader(open('data.csv'), delimiter = ',')
user_data = []
for i in csv_file:
    i[2] = i[2].lower()
    user_data.append(i)
    print(i)

send_text = """
      こんにちは、さくらこ杯運営のさくです。2度送ってしまった方はごめんなさい、完全なミスです。申し訳ありません。
      20時時点でのステージ選択や各情報についての最終確認を行います。
      受理番号:{0[0]}
      チーム名:{0[1]}
      得意ステージ:{0[4]}, {0[5]}
      不得意ステージ:{0[6]}, {0[7]}
      以上で問題ないでしょうか?
      """

for now_user in ret['users']:
    cnt = 0
    finded = False
    now_user['screen_name'] = now_user['screen_name'].lower()
    for s in user_data:
        if s[2].find(now_user['screen_name']) != -1:
            print(now_user['screen_name'], ' finded')
            finded = True
            break
        cnt += 1
    print(cnt, now_user['screen_name'])
    if finded == True:
        t.direct_messages.new(
            user = now_user['screen_name'],
            text = send_text.format(user_data[cnt])
        )

リーグ戦を管理するノウハウについて

今まで、なぜか色々なリーグ戦のスコア管理を任されていました。そこで、色々調べたりして便利な(人間が手を動かさなくても良い)関数を一覧としてメモしたいと思います。参考になれば幸いです。

参考までに、いままで管理したリーグ戦の一覧を以下に示します。

  • 第一回、第二回嶺上杯
  • とと太郎さん主催マルチウェポンで遊ぼうの会
  • はんじょうさん主催身内リーグ戦
  • とと太郎さん主催招待制リーグ戦

こんなところでしょうか、意外に少ないですね。でも色々自動で出来るようにしているので、ノウハウを共有したいと思います。

便利な関数群

countif

「第二引数の文字が第一引数の範囲内にいくつ存在するか」を返してくれます。リーグ戦のスコア管理では以下において、勝ち数/負け数の管理に使っていました。シートに入力されるだけで自動的に反映されるので、めちゃくちゃ便利です。

f:id:li_saku:20151231152642p:plain *1

countif(C3:AH3, "o")

rank

「第二引数の範囲内で、第一引数で指定した値がどの順位にいるか」を返してくれます。第三引数は降順にするのか昇順にするのか、です。0が降順、1が昇順だったはず?その辺りは調べたほうが良いかもしれません。 リーグ戦において、順位の管理で使っていました。
また、注意することがあって、大体の場合一番上のセルに入力して下にがーーーってコピーすることが多いんですが、Google Spread Sheet において相対参照(セルに $ がついていないやつ)をすると、範囲まで変わってしまうので、「基準にしたい範囲」については絶対参照(セルに $ がついたやつ)にしたほうが良いです。 画像は *1 参照したほうがわかりやすいと思います。

rank(AL3,$AL$3:$AL$10,0)

セル結合のテク

見やすさ、管理のしやすさ、関数を使いたいがためにわたしはセル結合を良く使用します。 たとえば、countif / 勝数の合計 / 負数の合計を使用したいがために以下のようにしていました。それぞれのチームについて4つのセルが使用されています。

f:id:li_saku:20151231152723p:plain

勝敗 | 取った本数 | - | 取られた本数 という形ですね。間の - は参加者が見やすいかな、という気持ちで加えましたが、楽さを考えるならなくても良いと思います。はじめに最初の1行目を作成して、ぐいっと下にがーーってコピーしちゃうのが楽だと思います。

対戦順

リーグ戦での対戦順、非自明じゃないですか?なので、Circle - Method というものを使用して対戦順を作るコードを書きました。一応 URL を載せておきます。このコードについてもまた今度別途解説記事を書きます。作成には上智大学理工学部情報工学科 データ構造とアルゴリズムの講義資料の講義資料を参考にさせていただきました、ありがとうございます。

また、わたしが自分で作成するまではこのページを使っていました。チームを入れて、開始時刻、試合間隔を適当に設定するとよいです。また、コート数というのは参加チーム数 / 2 を切り捨てた値を入れると良いです。これ、作成した後の対戦順を csv ファイルでダウンロード出来るので、スプレッドシートにコピペとか出来ていい感じです。結構オススメ。

リーグ戦だと自分の対戦が終わった後に相手が終わってるかどうか確認するのが面倒だと思ったので、参加者の手間を減らすという意図でスコアを管理すると同時に対戦記録も管理していました。
これにより、終わった側が先に部屋を立てたり、まだ終わってないから待つべきだな、という情報がリアルタイムに参加者側へ伝えられるため、かなりスムーズに進行出来たのではないかと思っています。

こんなところでしょうか。思ったよりなかった………参考になれば幸いですが、一応今回の countif や rank を使用したリーグ戦のスコアを載せておきます。とと太郎さん、使用してごめんなさい!関数とか見られると思うので、何か参考になれば。

AOJ 0115 Starship UAZ Advance

アドベントカレンダー(後編)を書くのがつらい.
@に「AOJ 0115ときましょう!!!レイトレーシングするだけ!!!」と言われたのが運の尽きであった……(うちの学校では4年次にCGという講義でレイトレーシングもろもろについて学ぶので,彼はちょうどその辺りについて教わったらしい)
問題URL : Starship UAZ Advance | Aizu Online Judge
解法としては,まず三角形の法線ベクトルを外積とって求めて,その法線ベクトルを用いてUAZ号から敵に向かって伸びる半直線と三角形を含む平面との交点を求める.
その得た交点が三角形内部にあるかどうかを,T1, T2, T3のそれぞれの面積の合計が三角形の合計と等しかったら内部にある = バリアに弾かれるのでMISS,そうでなかったらHITという感じ.
f:id:li_saku:20141224072807p:plain
教訓としては,EPSちゃんと使うというのと,めんどくさがって超破壊的変更をしまくる構造体を使うなということでした(ちゃんとoperatorを定義しようという話)
あと半直線かどうかというのに気をつけようという感じ(UAZ号...敵...バリアみたいなのだと,当たる判定はされるんだけど実際にはバリアに当たる前に敵に当たるので,バリアのどっち側に2頂点があるのかを調べるべき:これは内積の符号でわかるので嬉しい)
これをライブラリに使うのはさすがに苦行なのでちゃんと書きます…

凛と花陽とそれ以外のもの(前編)

ICTアドベントカレンダー3日目です

 学校が廃校になるというニュースは、びっくりするような速度で校内中をかけめぐっていた。ひとつ上の先輩があまりのショックに倒れたという、嘘みたいな話までささやかれている。
 ふたりがその話を聞いたのは、寒さがすこしやわらいできた、四月半ばごろのことだった。

「あっ、ふたりとも聞いた?ここ、廃校になるんだって」

 かばんを机のうえに置いたとたん、隣の席の子にそう言われて、おもわず目をぱちくりとさせてしまう。しってた?ううん、しらない。そんなやりとりをしながら席に座る。

「廃校って……あの、廃校だよね?学校が、なくなっちゃう」

「うん、その廃校」

「学校が、なくなっちゃう……? ええっ!? それじゃあ凛たち、どこかに転校しなきゃいけないの!?」

「わたしたちが卒業するまではあるみたいだけど、もう来年から新入生は来ないみたい。……廊下にある掲示板にくわしく書かれてるよ」

 見てきたらいいんじゃない?と言われ、そろって席を立ち廊下へ向かうことにした。せっかくすこしあたたかくなってきたっていうのに、いやな話をきいて落ち込むふたりのこころをあらわしたように空は灰色に染まっていて、いまにも雨が降り出しそうだった。もともと凛はしとしとと静かに降る雨が好きだったが、今日のような落ち込んでいるときに限って降ってくる雨は嫌いだった。

「学校、なくなっちゃうんだね」

「せっかくがんばって入ったのに……残念だにゃ」

「でもたしかに、一年生は一クラスしかないし、納得かも」

「はっ! ねえねえかよちん、もしかして、後輩、もう出来ないってこと!?」

「そうなるかも……」

 そんなの嫌だにゃー、と嘆いているのをなだめながら歩いていると、でかでかと「廃校」の文字が書かれた紙が掲示板にたくさん貼られている様子が目に入ってきた。たしかに、転校はしなくてもいいみたいだけれど、やっぱり、後輩が出来ることはなさそうだった。ますます気分が落ち込んでしまった凛は、不機嫌そうな表情で花陽の手をとり、どこかへ歩きだした。

「えっ、えぇっ、凛ちゃん? どこいくの?」

「もう授業なんかやってらんないにゃ」

「ええええ、さぼっちゃうの!?」

 強引に手を引きながら歩く凛は、なんだかんだ言って花陽がわがままを許してくれることを知っているのだ。屋上へ向かおうとしていたが、ふと目を向けた窓の向こう側で雨が降り注いでいるのを目にして、また少しだけ不機嫌になって、方向転換する。
 入学したてのころに校内案内されたとき、ほとんど使われていないと言っていたコンピュータ室だ。あのときにすこしだけのぞいた室内はほこりっぽくて、いかにも使われていませんといった風貌だったけれど、今はふたりでだらだらとしながら気分を落ち着けることができればどこでもよかった。

「勝手にはいっていいのかなぁ……」

「使ってないって言ってたし、きっと大丈夫だよ」

 そう言いつつ、鍵が閉まっているだろうな、と予想しながらドアを開けると、意外にも途中でひっかかることなく開いてしまう。力をこめてドアを引いていたので、がららら、という勢いの良い音が廊下に響き渡る。

「あっ、やばいにゃ、かよちんはやくはやく」

 授業はもう始まっていた。
 はじめて授業をさぼる凛は、勢いで決めたわりに、さぼる、という行為自体を楽しんでいた。それも、一緒にいるのは花陽だ。きっと一人でここに来ていたらこんなに楽しめていなかったに違いない。それを、音をたてたせいで先生に見つかるというくだらない理由で終わりにしたくはなかった。
 ふたりであわてて教室へ入ると、薄暗い部屋のなか、片隅にぼんやりとした光が見える。部屋の電気を消した状態で見るパソコンのディスプレイの光はなんだかあやしげな雰囲気とともに神聖な雰囲気もあって、パソコンに向かっているのが同級生だと一瞬気づくことが出来なかった。

「あれ、……にしきの、さん?」

「え?」

 呼びかけた途端ぱっとこっちを向いたのは西木野真姫だった。入学早々のテストで、ぶっちぎりの一位をとったと話題で、実家が病院で、西木野さんは医学部に入りたがっていて、と思いつく限りの聞いたことのある情報を頭の中に並べてみたが、凛にはなぜ彼女がここにいるのかまったく思いつかなかった。すくなくとも、廃校という事実に落ち込んで授業をさぼるような人には思えなかった。
 安っぽい椅子をきいきいと鳴らしながら回転させ、こちらを向いた真姫と目が合う。きれいな紫色で、なんだか吸い込まれそう。

「えぇと、……星空さん、と、小泉さん、だったかしら」

「うん、そう、小泉花陽です」

「ねえねえ、西木野さんなにしてたの?授業はいいの?電気つけないの?」

「ちょっと、りんちゃん……」

 興味のおもむくまま、矢継ぎ早に質問してしまった凛は、たしなめられてぱっと口をおさえた。そんなふたりを見ながら、すこしだけ鬱陶しそうな表情を隠そうともせずに真姫は答える。授業は面倒だったからさぼり、電気も面倒だったからつけてない。
 手をつないだまま真姫が座っている椅子のそばにある椅子に腰掛ける。廃校で落ち込んでいた気持ちがうつったのか、先ほどの音より何倍も大きい音でぎいい、と不機嫌そうに鳴いた。

「なにしてるの?」

「べつに、そんな大したことはしてないわ」

「ふーん……つまんないにゃあ」

「つ、つまらないってなによ!」

「あわわわ、西木野さん、ごめんね、凛ちゃんもだめだよ」

 花陽に怒られたのは今日で三回目だ。怒られたといっても、軽い注意程度のものだが。それでもすこしむくれて、かよちんのばか、とつぶやきながら椅子をきいと回転させて前を向く。

「……にしきのさん」

「なに?」

「あれなに?」

「あぁ……入学したころからあったわよ」

 赤い、きみょうな形をしたゆるキャラのような見た目をしたキャラクターが描かれていて、そのしたにでかでかと「パソコン甲子園」と書かれている。凛の知っている甲子園は、あちこちで開催される予選を勝ち抜いた高校が一ヶ所に集って決勝戦をし、そして優勝した高校は強豪として名を馳せる。それぐらいだ。そのパソコン版、といってもまったく予想がつかなかった。
 近くによって見てみると、二名一チームで、七月までに参加登録しなきゃいけなくて、十一月に本選がある、ということが書かれている。
 そこで、凛は思いついた。甲子園というぐらいだから、優勝したところの学校は有名になるはずだ。ふたりでチームを組んで、もし優勝すれば名前が広まって入学希望者がたくさん来て、廃校はやめになって、後輩が出来る。完璧な計画だと思った。

「よし!凛、かよちんと一緒にこれに出ることにする!」

「えぇっ!?」

「優勝して、後輩がっぽがっぽ作戦にゃ!」

 この完璧な計画の前にひれふすがいいにゃ、とばかりに腰に手を当てて振り向いた。困った顔と、呆れたようなため息。凛は花陽の手を取り、ぶんぶんと振りながら出ようよぉ、とねだる。
 そんなふたりを見ながら、真姫が言った。

「出るのは別にどうでもいいんだけど、どれで競うのか知ってるの?」

「知らないにゃ」

「知らないのに優勝するって言ったの!? ……なんというか、すごいバカね……」

「西木野さんひどい! 凛はバカじゃないにゃ!」

「凛ちゃん、どうどう…… ね、西木野さん、なにで競うの?」

「うーん……まあ、プログラミング、かしら」

 ぷろぐらみんぐ?しってる?ううん、しらない。朝みたいな会話をして、ふたりで真姫をじいっと見つめる。目線にたじろいだ真姫は、ため息をつきながらパソコンに向き直り、かたかたとキーボードを打ち始める。
 座っていた椅子を鳴らしながら近づいてディスプレイを見てみると、黒い画面に白い文字がたくさん打ち込まれていて、なんだか頭が痛くなってしまった。全部記号や英数字で書かれていて、英語が苦手な凛にとってはまったく意味がわからないものばかりだった。いっぽう花陽は英語が得意だったが、書かれているものを読んでみても、色付けされているものとされていないもので差がまったくわからないし、知っている英単語は「include」や「main」ぐらいのもので、ほかに見知った単語はなかったのだ。

「小泉さん、好きな数字二つあげてもらえる?」

「え、えーっとえーっと、じゃあ、11 と 1 、で」

 かたかた、と 11 と 1 のあいだにスペースを入れて入力し、エンターを押すと、次の行に 12 という数字が表示された。

「いま、私が 11 と 1 って入力したでしょ? それで、次の行にその合計が表示されたってわけ。 こういうことをするのがプログラミング」

「全然わかんないにゃ」

「そう言うと思ったわ……」

 もう面倒だからこれでも読んでなさい、と渡された本の表紙にはかわいらしい猫の絵が書かれていて、わあっ、凛ちゃんみたい、かわいい、と喜んでいる花陽を尻目にぱらぱらと本をめくると、日本語と英語と記号が入り混じって色々と書かれている。読むのが大変そうで、すぐに諦めたくなった。しかし、花陽がなんだか楽しそうに本を読んでいるのをみて、ころっと気が変わる。お互いにとって楽しかったものはたいていお互いにとって楽しかったし、きっと今回もそうだと思った。

「一応言っておくけど、その本、今までの知識で理解しようとしないで、こういうものだ、と思って読んだほうがいいわよ」

「ねえねえ、西木野さんのこと真姫ちゃんって呼んでいいかにゃ?」

「あっ、わたしも、良い、かな……?」

「ふたりとも私の話聞いてた!? ……別にいいわよ」

「やったーっ、まきちゃんまきちゃーん」

「えへへ、わたしのことも花陽、って呼んでほしいな」

「あっ、凛も凛も!」

「はいはいわかったわよ、凛に花陽ね」

 ぶっきらぼうにそう言い放つ真姫にちょっとだけ申し訳なく思う花陽だったが、その耳がすこし赤く染まっているのをみつけて、ほんわりとした気持ちに包まれる。まきちゃん、かわいいな。そう思いながら帰ることを促す。気づけばもう一限目が終わってしまう時間だった。
 読み終わったらまたくるね、わからなかったらくるね、と言い続ける凛の手を引きつつ、うんざりした表情の彼女にごめんね、と告げてコンピュータ室を出た。
 窓の向こう側にある空は、この教室にはいったときとうってかわってすきとおるような青空で、花陽はなんだか楽しくなりそうだな、とこれからの生活を思ってふんわりと微笑んだ。

「まきちゃん!まきちゃーん!」

 ばあん、とコンピュータ室のドアを開けると、最初この部屋へ来た時のように薄暗い部屋の中で唯一真姫の座っているところだけぼんやりと光っていた。
 ここに来ることもずいぶん慣れたし、真姫ちゃんともだいぶ仲良くなったな、と思いながらドアを開けたまま中に入っていき、しょうがないなあ、と静かにドアを閉めてから中に入る。凛はいつもこの部屋のドアを勢い良く開けるし、そのたびに真姫はうんざりした顔をするし、花陽は苦笑しながらドアを静かに閉める。ある種のお約束のようなものだった。そういった「お約束」が出来る程度にはこの部屋に訪れていて、凛に似たかわいらしい猫が描かれた本はすでに読み終わっていた。
 あの日言われたとおり、「こういうものだ」と思って読み進めると意外にすらすらと読めて、気合をいれて夜通し読むつもりが早々に終わってしまい、ふたりでお菓子をつまみながらおしゃべりに興じたのは記憶に新しい。久しぶりにおとまりすることが出来た花陽は、別の意味でも真姫に感謝していた。高校に入ってまでおとまりに誘うのは少しだけ恥ずかしかったのだ。

「ところでふたりとも、本当にパソコン甲子園に出場するの?」

「あったりまえにゃ!優勝して後輩がっぽがっぽ!」

「ふふ、凛ちゃん、それ好きだよね」

「優勝は置いといて、チーム名どうするつもり?」

 まったく考えていなかった、と言わんばかりにぽかんとした表情で、どうしようりんちゃん……と困った表情で目をやる。そんな視線を受けて、凛はふふん、と腰に手をあて胸を張り、実はもう考えてあるにゃ、と言った。
 
「かよちんが小泉だから、spring なんていいんじゃない!?」

「却下よ」

「えええええっ、真姫ちゃんひどいにゃー! かよちんはこれがいいって思うよね?」

「う、うーん、それはちょっと……」

「かよちんまで……もう凛いきていけないにゃ……」

 落ち込む凛をよしよし、と撫でながら、必死に代替案を考える。自分の苗字をそのままチーム名にしてしまうのはなんだか恥ずかしいし、小さいという単語を入れたチーム名にするのもなんだか縁起が悪いようで、凛はそこを考えてくれたのかちゃんと外してくれていたけれど、それでも元のものを考えるとやっぱり縁起が悪いように感じてしまった。今からあれこれ考えるのは面倒だし、凛ちゃんの苗字を英語にするのはどうだろう、たしか真姫ちゃんもも凛ちゃんの苗字が綺麗で好きと言っていたはず、と考えて口に出す。

「凛ちゃんが星空だから、Starry Sky とかどうかな……?」

「えぇっ凛の苗字つかうの? なんだか恥ずかしいよ…」

「……私はいいと思うけれど」

「うん、真姫ちゃんもそう言ってくれるとおもった」

「凛の苗字、とても綺麗だし私は好きよ」

「えっ、えっ、なんか照れるにゃ……」

 気が抜けたように、ぽすんと椅子に座った凛の頬がすこし染まっていて、なんだか鼓動が少しだけうるさく感じた。それと同時に落ち着かない気持ちになって、焦燥感で胸がいっぱいになる。凛ちゃんがああいう表情をするのは、わたしの前だけだとおもっていたのに。そういうことを一瞬思ってしまい、振り払うように頭をふるふると振る。
 心配そうに見てくる真姫の視線を振り払うように、もう登録しちゃうね、と言って、家から持ってきていた薄いノートパソコンを開いて電源を入れる。いつもはなんとも思っていなかったけれど、こんなときばかりは起動がはやいものを選んで正解だった、と過去の自分を褒める。
 登録は思いの外すぐにすんで、パソコンを閉じて振り向くと、凛と真姫がじゃれあっている様子が目に入る。ずき、と痛むような感覚を無視して、二人に声をかけた。

「登録、終わったよ」

「ありがとにゃ! かよちん、今日帰りに駅前のパフェたべてかえろーっ」

「このあいだ行きたいって言っていたところ、だよね? うん、いいよ」

「あ、そうだ、ねえふたりとも、AOJ って知ってる? 会津オンラインジャッジって言って、パソコン甲子園の過去問とかもあるんだけれど……」

「聞いたことないにゃー」

会津って……パソコン甲子園を開催しているところ?」

「そうよ、知らないなら良かったわ… 一度やってみるといいと思う」

「帰ったらやってみる!」

 そう言って真姫にきらきらとした笑顔を向ける凛を見て、また胸が痛くなった。やっぱり、なんかおかしい。体調が悪いのかもしれない。いつもの凛ちゃんなら、体調が悪かったらすぐに気づいてくれていたのに、今日はそんなことはなかった。そう思って凛を見ると、真姫と楽しそうに話している。ずきり。また胸が痛くなって、自分を見てくれないことに言いようのない不安を覚えてしまった。

「……ぁ、わたし、もうかえる、ね」

「えぇっ、かよちん、パフェは!?」

 やっぱり、気づいてくれないんだね、そう思って、返事も早々に急いで荷物をまとめてコンピュータ室を出てしまう。昇降口までどうやって歩いたのかわからないし、どうやって家に帰ってきたのかもわからなかった。かばんを投げ捨てるように床に置いてベッドに寝転がった花陽は、誕生日に貰った黒い猫のぬいぐるみを抱きしめて、泣きたいような気持ちになった。
 花陽と凛は幼なじみだった。物心つく前から一緒にいて、いじめられたときにはいつだって助けてくれて、泣いていたらいつだって涙をふいて抱きしめてくれた。でも今花陽のそばに凛はいない。花陽ではなく真姫のそばにいる。はじめはあんなに仲が悪かったのに、最近はすっかり仲良しだ。それこそ会ったばかりのころは花陽がいないと気まずくて気まずくてしょうがない、と愚痴っていたのに。

 りんちゃんの、ばか。
 ぽつりとつぶやいた言葉は夕闇に溶けて消えるよう。自分がいだいている感情はわがままで、凛がばかでないことは十分わかっていた。ばかじゃなくて、がんばりやで、頭がよくて、聡いから、花陽よりも早くプログラミングについて飲み込んで、本を読むのも早くて、真姫の話についていったのだ。凛と真姫が話をしているのを見ていると、どんどん置いて行かれてしまうんじゃないかという気持ちになって、自分に出来ることはなにもないと思ってしまって、もう感情が爆発してしまいそうだった。
 泣くのを我慢しているとだんだん吐きそうな気持ちになってくる。こんなに苦しいのに、凛はいまごろ真姫とふたりでパフェを食べて、お互いに交換とかしているに違いない、そう思うと今まで以上に視界がゆがむ。ぎゅっと目を強くつむって、必死にこぼれないように我慢していると、いつもふたりでパフェを食べるときに、凛の差し出してくるスプーンと、そのときのはじけるような笑顔と、スプーンをくわえるときの嬉しくてはずかしいときの気持ちがよみがえってきて、胸が突き刺されたように痛くて、ぐちゃぐちゃな気持ちになった。きっと凛と真姫は、凛と花陽がしていたようなことをしているのだ。

「りんちゃん…りんちゃぁん……」

 いちど涙があふれてしまうと、もう我慢できなくて、次から次からあふれてくる。いつも涙をぬぐってくれて、だきしめてぬくもりを与えてくれていた凛は、もう花陽のそばにはいないのだ。

なかがき

これ「あとがき」ではないので間をとってなかがきにします.
そらはー先生,うたた先生,校正 & 意見ありがとうございました.最初に比べてだいぶましな文章になったと思います.
りんぱなには幸せになって欲しいし,まきりんぱなはアイドルが似合うと思いました.
後編もがんばって書きます.