ふかふかブログ

興味のあることについてゆる~く書きます

2019年振り返り(スプラトゥーン編)

この記事ではスプラトゥーン2に関係あるものに限定して2019年の振り返りを行います。 これ書いている人はもともと日本語が苦手なのと想定外に菊之露を大量摂取しているため文章にまとまりがないかもしれません。

初めてのゲームサークル加入

正確な時期は覚えていませんが、初めてゲームのサークルに加入しました。 スプラトゥーンにはイカナカマという非公式コミュニティがあり、そこで自分に合いそうなチームを探して加入しました。

スプラトゥーンはおろかゲームのサークルに入るという経験が初めてだったため、初めは戸惑いましたが意外と皆さん普通(失礼)で、すぐになじむことができました。 そのサークルは解散してしまいましたがありがたいことにそこでフレンドになったイカタコとは今でも交流があります。

当時はウデマエS+になんとか到達はしたものの、自分のプレイスタイルやガチマッチに少々飽きていたためサークルの人と一緒にやるリーグマッチやプライベートマッチを楽しむスタイルでした。

ちなみに、この時までゲーム上のハンドルネームは特になかったのですが皆さんハンドルネームを持っていたので私もふかふかというハンドルネームを名乗るようになりました。

ウデマエ停滞編

2019年の初めにTwitterで全ルールウデマエX達成を目標にするとつぶやいてはいましたが、当時メインで利用していたスプラシューターコラボではS+帯を勝ち抜くことができず悶々とした日々が続いていました。

今振り返ると、このころはスプラシューターコラボで負ける→ブキ持ち替える→負ける→スプラシューターコラボに持ち帰る→負けるの繰り返しで思考が停止しておりほぼ成長も止まっていたと思います。

修行編そして全ルールX 達成

あるときTwitterYoutubeで「自分のプレイ動画を振り返るって反省することがウデマエ向上には大切」ということを聞き、早速録画環境を整え自分のプレイ動画を見返しましたがまぁひどいものでした。

1試合ごとになぜ勝てたか・なぜ勝てなかったかを記録し、勝ち負けのデータを集め傾向を分析しました。 そうすると以下の傾向をつかむことができました。

  1. 得意・不得意ステージがある
  2. (S+なので)そこまでブキの編成によって勝敗が決まっていない
  3. ゲームをプレイし始めて1~3試合目または2時間以上プレイしたときの勝率が非常に低い

1, 2はなんとなくわかっていましたが3はデータで見るまで気づいていなかったのでガチマッチに入るまでのアップとして試し打ちとステージの散歩(それぞれ1分程度)、ウデマエを上げる目的でプレイするのなら2時間以上ガチマッチをしないを徹底するようになりました。

ステージの厳選をするとさらによいのですが一応正社員として働いているのでそこまではやりませんでした。

試合前のアップ、プレイ時間の制限のほかにも有識者へ基本的な考え方を聞いたり、自分のプレイ動画を添削してもらったりしたのも成長の糧となりました。

そして2019年9月あたり?、ついに目標だったオールウデマエXを達成しました。 記念に妻にTwitterアイコンを書いてもらいました。

名札に"Xたい"と書いているのが非常にお気に入りです。

ちょっと番外編

スプラトゥーンのプレイに関すること以外にも以下のようなことをしていました。

イカタコ分類器を作る

最近機械学習を勉強中ということもあり、イカタコの顔画像からイカかタコか分類するモデルを作ってみました。

nohararc.hatenablog.jp

本来であればTensorFlow.jsに変換してそれぞれの端末上で自分の顔画像なりあげてイカかタコか分類するまで作りたかったのですがまだ手を出せていません。

センパイの友達追加人数が7000人達成

趣味で運用しているスプラトゥーンLINE BOTが友達追加数7000人を達成しました。 友達追加人数だけでなくリアクション送った数もまとめようと思いましたが力尽きた...

f:id:nohararc:20191230232658p:plain
コウハイの友達追加人数

気になる人はここから。

今年もありがとうございました。2020年もよろしくお願いします。

Happy Hacking Keyboard Professional HYBRID Type-S買った話

f:id:nohararc:20191216232807j:plain

2018年3月18日以来にPD-KB620B(Bluetoothのほう)を購入し2年近く利用しましたが この度新モデルがでたということでHYBRID Type-S(黒、日本語配列)のほうを購入しました。

一時間ほど触ってみての感想としてはPD-KB620Bと比べ打鍵音が優しい、指に吸い付く感じがする(キーストロークが若干短いから?)という感じです。 Bluetooth再接続時に押すボタンも少し押しやすくなっておりその点もプラス評価です。

仕事用HHKBもHYBRIDに乗り換えようか迷い中。 サンタさんにお願いすべきか...

golang.tokyo #26 に参加してきた

本日(寝るまでが今日)2019/09/25、golang.tokyo #26にブログ枠で参加させていただいたので珍しく参加レポートを書きます。

golangtokyo.connpass.com

参加まで

私自身golangはほぼ経験がなく、またgolang.tokyoといえばいつも人気殺到で参加できるイメージがなかったので応募すらしていなかったのですが同僚から「ブログ枠なら空いているぞ」という情報を聞きつけ、内容も『スマートホームにおけるGo』ということで普段IoTかじっている私にとってはドンピシャだったので当日の朝急遽参加申し込みをしました。

会場はメルカリ様で、入場してすぐ軽食+ドリンクをいただきました。メルカリ様、スタッフのみなさまありがとうございますm(__)m

(おにぎり一つ食べた後慌てて写真撮る人) f:id:nohararc:20190926004240j:plain

発表の感想

Go in Nature

songmuさんの発表。

Nature社とNature Remoの紹介でした。

Nature Remoは名前だけ聞いたことあるレベルでしたが具体的な機能やアーキテクチャを聞いて興味を持ちました。

お話の中でもありましたがサーバーとNature Remo間の常時接続、基盤側に何かあった場合は再リクエストが一斉にくるので気を遣うという話はインフラエンジニアとしては胃がキュッとしました。。。

Nature Remo用のGo API Clientを作った話

tenntennさんの発表。

tenntennさんが作成されたAPI Clientをデモを交えながら紹介するという発表でした。 会場からtenntennさん宅の家電を操作するという不思議な(?)デモは会場を沸かせていました。

LINE BOT→GAE→自作Clientで柔軟に家電を操作するデモも面白くて、思わずNature Remo miniをその場で購入してしまいました。

Nature社からAPIも公開されているとのことなので興味がある方は読んでみるといいかもしれません。

LTの感想

Raspberry Pi + Go で IoT した話

yaegashiさんの発表。

goはエッジデバイスや組み込みシステムの開発に適しているというお話でした。

Raspberry Pi + Goで利用できるライブラリについても紹介いただいたので機会があれば利用したいと思います。

Goを使ったセンサーデータ収集基盤のお話

takeshinodaさんの発表。

こちらもgoはIoTの開発に便利という話でした。 クロスコンパイル、非同期データ通信制御が簡単、デプロイ簡単というのは確かに便利。 TSでも同じくかけるが、GoはCっぽくかけるのでGoのほうが好きというのは私もすごく同感でした(TSわからないので)。

Build real world data collecting architecture with goroutine & channel

banana_umaiさんの発表。

センサーからのデータを収集する際にpipeline/debouncing/bufferingの処理を行うがGoだとこういう実装でできるというお話でした。

ボリュームがすごくてもっとゆっくりお話し聞きたかったという感想でした。発表資料が公開されたらゆっくり拝見したいと思います。

まとめ

いつも後から発表資料を拝見させていただくのですが、やはり実際に会場で登壇される方のお話を生で聞くというのはいいものだなぁと感じました。上でも書きましたがNature Remo mini購入しましたので早速弄り倒したいと思います。

【Splatoon2】ディープラーニングでイカとタコを見分ける

最近機械学習の勉強をしているので練習として、スプラトゥーン2イカとタコを見分けてみたいと思います。

といってもすでに実践している方がいらしたので、さらに精度を上げる+実際に間違えた画像を表示して少しでもディープラーニングのお気持ちを理解したいと思います。

参考 tkgstrator.work

概要

↑で参考にあげているページから学習データをいただきまして、図の人工知能部分に学習させます。 最終的には、画像を与えるとイカガール・イカボーイ・タコガール・タコボーイの中からどちらに近いか判定ができるようになります。

f:id:nohararc:20190728132127p:plain

結論

テストデータ999枚に対し、989枚正解(99.9%)を達成しました。

コードはこちら github.com

誤った画像について、目視で確認していきます。 f:id:nohararc:20190701004025p:plain

3行2列目の画像はもうすこし頑張ってほしいところですが、その他の画像は人間でも判断がつきにくく、 概ねいい感じに学習できている気がします。

実装

詳細は実行環境は省きます(GCPで構築した記憶があるのですがメモを紛失しました...)。

  • フレームワーク: keras
  • モデル: EfficientNet
  • 学習方法: 転移学習(ファインチューニング)
  • 学習データの水増し: horizontal flip, random erase

おまけ

f:id:nohararc:20190728133020p:plain

【Splatoon2】Discordのbotを作った話

いつも利用させてもらっているBOTの調子が悪かったのでいい機会だと思って作ってみました。

できたもの

f:id:nohararc:20190728002814p:plain

github.com

招待リンク

諸注意: 現在お試し環境で動かしているため、予告なく停止する場合があります なにかあればTwitterまで

discordapp.com

使い方

仲間内でのプライベートマッチで利用することを想定しているため、ブキランダムしか実装していません。

/buki: ランダムで1つブキを返す
/bukia: ボイスチャンネルに参加している人数分ランダムブキを返す

自分でBOTを作りたい場合

以下のリポジトリからとってきて、my token goes hereを書き換える github.com

参考リンク

Pythonで実用Discord Bot(discordpy解説) - Qiita

Welcome to discord.py — discord.py 1.3.0a documentation

node-redからzabbixにデータを飛ばす

node-redで取得した値をzabbixに飛ばすメモ。

node-red初めて触ったのでおかしいところあればこっそり教えてください。

方針

すぐ思いつくのは以下の二つだと思います。

  1. node-redからcsv等でログを吐いて、zabbix-agentを使ってアクティブチェックで値を送り付ける
  2. node-redから直接zabbixに値を送り付ける(zabbix_senderのような感じ)

今回は2番目の node-redから直接zabbixに値を送り付ける を実装してみます。

実装した後気づいたのですが、すでにnpmのパッケージとして存在しているようです(未検証)

環境

公式のdockerコンテナを利用

Zabbix: 4.2.4
node-red: 0.20.6

準備

  1. node-redを準備します

    docker run -it -p 1880:1880 --name mynodered nodered/node-red-docker

  2. zabbixサーバーを用意します

    docker run --name some-zabbix-appliance -p 80:80 -p 10051:10051 -d zabbix/zabbix-appliance

  3. zabbixサーバー側にアイテムを登録します

    f:id:nohararc:20190703002913p:plain
    item

    zabbix_sender使う時と同じですが、TypeをZabbix trapperとしているところだけ注意

node-red側の実装

全体図

f:id:nohararc:20190703003202p:plain
node-red全体図

  1. 入力部 Injectノードのペイロードに以下のjsonを記入

    複数の値を飛ばしたい場合は、data配列の中に追加すればよい

     {
         "request": "sender data",
         "data": [
             {
                 "host": "Zabbix server",
                 "key": "node-red",
                 "value": 20
             }
         ]
     }
    
  2. 関数部 functionノードのコード部分に以下を追加

     var payload = new Buffer(JSON.stringify(msg.payload), 'utf8'),
           header  = new Buffer(5 + 4); // ZBXD\1 + packed payload.length
    
     header.write('ZBXD\x01');
     header.writeInt32LE(payload.length, 5);
     msg.payload = Buffer.concat([header, new Buffer('\x00\x00\x00\x00'), payload]);
    
     return msg;
    
  3. 出力部 zabbixの待ち受けポート(デフォルトは10051)にtcpでデータを送り付ける

     ホスト: zabbixサーバーのIP
     種類:  接続
     ポート: 10051
     メッセージを送信するたびに接続を切断: チェック
    

完成

(Injectノードで値を色々変えてます)

f:id:nohararc:20190703005141p:plain
グラフ

おまけ

ハマったところ

  • Zabbix公式でheaderのpython実装はPython2
  • headerという単語だけをみてなぜかhttpでつなぎに行ってしまう(ドキュメント読みましょう)

node-redで実装する前に簡単にPython3で実装したなにか

import struct
import telnetlib
import json

data = {"request": "sender data", "data": [{"host":"Zabbix server", "key": "test_zabbix_sender", "value": 100}]}
data_json = json.dumps(data)
header = b"ZBXD\1" + struct.pack("<Q", len(data_json))

packet = header + data_json.encode()

tn = telnetlib.Telnet(host="127.0.0.1", port="10051")
tn.write(packet)
print(tn.read_all().decode())
tn.close()

参考

GitHub - shamil/node-zabbix-sender: A zabbix_sender implementation, to send zabbix item(s) using the zabbix trapper protocol.

node-red-contrib-zabbix-sender (node) - Node-RED

GolangでPythonのrandom.sampleを実現する

最近趣味でPythonしか書いていなかったので、素振りとしてGoを勉強しているのですが

任意のグループからa個選ぶという処理で少し詰まったので忘備として書いておきます。

Pythonのrandom.sampleについて

任意のグループからa個選ぶというもの。

引数として渡されたリストは変更されません。 [1, 2, 3]部分

>>> random.sample([1, 2, 3], 2)
[2, 1]
>>> random.sample([1, 2, 3], 2)
[1, 3]
>>> random.sample([1, 2, 3], 2)
[3, 1]

9.6. random — 擬似乱数を生成する — Python 3.6.5 ドキュメント

golangで実現

こんな感じになると思います。

func randomSample(s []string, num int) []string {
    rand.Seed(time.Now().UnixNano())
    var sample []string
    n := make([]string, len(s))
    copy(n, s)

    for i := 0; i < num; i++ {
        index := rand.Intn(len(n))
        sample = append(sample, n[index])
        n = append(n[:index], n[index+1:]...)
    }
    return sample
}

ポイントとしては、n := make([]string, len(s)) として元のスライスを変更しないようにしています。

go始めたばかりで右も左もよくわかってないのでツッコミあればこっそり教えてください。

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    s := []string{"a", "b", "c", "d"}
    fmt.Println(randomSample(s, 2)) // [a b] or [a c] or ...
    fmt.Println(s)                  // [a b c d]
}

func randomSample(s []string, num int) []string {
    rand.Seed(time.Now().UnixNano())
    var sample []string
    n := make([]string, len(s))
    copy(n, s)

    for i := 0; i < num; i++ {
        index := rand.Intn(len(n))
        sample = append(sample, n[index])
        n = append(n[:index], n[index+1:]...)
    }
    return sample
}