時間が限られているときに技術書を読むのが苦手

たとえば仕事終わって帰ってきて、寝るまでに3時間あるとすると、3時間で済むようにしなきゃいけない。
(朝起きるのがめちゃくちゃ苦手なので十分余裕を持って寝たい)
そうすると、どれをどのくらい読むか決めないといけなくて厳しい。
なんで決めるかというと区切り悪いところで終わりたくないし、精神力がないから「ここまでやる」がないと数ページで終わってしまいそうだから。
「ここまでは読めそう」ってのも罠で、わからないところ出てくると調べたりして数ページに数時間溶けるとかもあるし、わからないから技術書読んでるから見積もりの精度が悪すぎる。
なので帰ってから生産的なことをするのがあまりにも難しくて、どうしよう…ってなりつつも勉強はしたいから悩ましい…
とりあえず英単語をだらだらやることを始めたんだけど、それより技術力をなんとかしないといけないから、焦る
同期にすごいひとがたくさんいて、会社の人もみんなすごくて、なんか自分だけ見劣りしてるなあ…って感じる
何をしても追いつける気がしない

英単語やる時に眠くなる時の対策

たとえばキクタンとか、基本的に英語が大嫌いな人間はチャンツとか読み上げ聞いてても脳が拒否して眠くなる。

最近かなり悩まされてたんだけど解決したので共有。

Bluetoothイヤホンを買って物理的制約を失くし、ストレッチや筋トレしながらやると起きられる。

もともと身体が固いので、前屈とかしたらめっちゃ痛いから目がさめるし、「英語に対するモチベ」はゼロだけど「ストレッチに対するモチベ」は0.1ぐらいあるので、義務感とモチベをうまく組み合わせるとなんか上手くいく。

キクタンで例えると、復習のために1日に500単語聞くとかすると、1時間とかかかるんだけど、開始3分ぐらいで眠くなるから、それを感じるとすぐ前屈の体勢にして痛みを感じさせることで目を覚ますと続く。で、それを1時間ぐらい精神を殺して、前屈したり開脚したり腹筋したりすると、起きられるし単語も回せる。神。

 

いや、なんでここまでして英語やらなきゃいけないねん、日本語話者以外を滅ぼしたい

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 を使用したリーグ戦のスコアを載せておきます。とと太郎さん、使用してごめんなさい!関数とか見られると思うので、何か参考になれば。