読者です 読者をやめる 読者になる 読者になる

Nintendo Switch の有線接続アダプタについて

こういうツイートが回ってきました。これについて、規格の面から言及したいと思います。

f:id:li_saku:20170324122732p:plain

まず、Wii U 純正アダプタの仕様についてです。

周辺機器 | Wii U|Nintendo

Wii Uを有線LANでインターネット接続する場合に必要となるアダプターです。 10BASE-T100BASE-TXに対応しています。

10BASE-T および 100BASE-TX というのは、主に通信速度に関する規格です。

簡潔に言うと、10BASE-T というのは最大 10Mbps の転送速度が実現可能な規格で、100BASE-TX というのは最大 100Mbps の転送速度が実現可能な規格です。
規格というのは、機種によって変わるものではありません。現在、ネットワーク(Ethernet)接続の規格を定めているのは IEEE という機関で、任天堂がいじれるものではありません

純正だから速度が上がるとか、安定するとか、そういうことは理論的に有り得ません。(回線の問題についても色々あるのですが、ネットワークは複雑すぎるので割愛します。)
再度書きますが、純正アダプタだろうが、非純正だろうが、速度差が出ることは考えられません。また、速度差について言及するなら、せめて数十回計測してその平均値を見るべきです。なぜなら、インターネットでは様々な経路でデータが伝わるため、一度の計測だけで必ずその値になるとは限らないためです。また、このタイプのオンラインゲームでは転送速度より応答速度の方が大事なので、それを重要視したほうがよいと思います。

次に、Nintendo Switch の「推奨とされている」HORI アダプタの規格についてです。

LANアダプター for Nintendo Switch

対応規格:1000BASE-T, 100BASE-TX, 10BASE-T

この 1000BASE-T というのが、今回 Nintendo Switch で追加されたネットワーク接続の規格です。簡潔に言うと、最大 1Gbps の転送速度が実現可能な規格です。

もうおわかりかもしれませんが、規格を満たしていれば、どんな USB <-> LAN アダプタを使っても変わりません。純正だろうが、純正でなかろうが、ラグにも同期ズレにも影響はありません

上記の画像で Switch 純正(?)アダプタと Wii U 純正アダプタで速度差がついている理由はもうわかるかもしれませんが、Wii U 純正アダプタは、100BASE-TX(100Mbps) までしか対応していないからです。回線速度の理論値と実測値がかなり違うことは誰でもわかると思います。ただ、Splatoon をやる上で、ここまでの速度が必要かというと疑問です。数十回測定した ping 値(応答速度)と、数 Mbps の転送速度が出ていれば問題ないと考えられます。

また、少しちがう話になりますが、この HORI 社が出している LAN アダプタ、USB 3.0 に対応していません。なぜなら、USB 3.0 のコネクタの前バージョンとの区別のため青色を使用することが推奨されているためです。

Nintendo Switch の公式仕様を見てみます。

機能・仕様 | Nintendo Switch|Nintendo

USB2.0 で動作しますが、将来的に USB 3.0 に対応する予定です。

USB 3.0 というのは最大 5Gbps の転送速度に対応した最新規格です。正直、Splatoon をやるだけならここまでの速度は必要ないと思いますし、かなりのオーバースペックだと思います。
個人的に、Nintendo ライセンス商品とうたっておきながら、将来的に対応する規格で発売していないのは少し微妙な気持ちになります。

USB3.0 <-> LAN(1000BASE-T) の変換アダプタにはこういう商品などがあります。関連商品にも似たようなものがあると思います。USB3.0 対応、1000BASE-T 対応かどうかを調べれば、正直 HORI より性能がよいです。

ただ、知識をつける手間を省くという理由で純正を買う人はもちろんいると思いますし、企業に貢ぐという意味で買う人もいると思います。メーカー保証の点で値段差があったり、チップセットの差だったり、いろいろな観点から議論をするべきだとは思います。
それでも、「純正だからラグくない」とか、「純正じゃないから同期ズレが起きやすい」とか、そういうことを平気で言ったり言われたりするのはおかしいと思います。

何らかの参考になれば幸いです。

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

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

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

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