目的は自己管理と習慣化
リングフィットアドベンチャーは、家にいながらにして運動ができるという素晴らしいゲームです。 ただ一点、個人的に気になっていることがあります。それは、運動ログがソフトウェア内に閉じていることです。 もし出力することができれば、過去の実績や継続日数を記録として残し、PCやスマホで可視化できます。これにより習慣化につながったり、「もしかして私、アームツイストばかりやってる...?」みたいなトレーニングの偏りに気づくことができるのではないかと考えました。
システム要件
そうしたことを考えて、要件として抽出した結果が以下です。気づけば仕事とやっていることが一緒
- 運動ログをゲーム外に出力すること
- 運動ログを時系列データとして蓄積すること
- 運動ログをグラフや表などで可視化すること
- 可視化の結果はインターネットでいつでも見れること
- 原則として自動化し、最小の手数で行うこと
- できる限り低コストで行うこと
完成図
できあがったものがこちらです。
ゲーム終了後に表示される「本日の運動結果」のスクリーンショットを、Nintendo Switchの機能を使ってTwitterへ投稿します。 それだけで、その日の運動ログを記録できるようにしました。 処理対象となるスクリーンショットは、この2種類です。
必要なもの
- 決済可能なクレジットカード
- そのクレジットカードを紐付けたGoogle Cloud Platform アカウント
- Twitter 開発者アカウント
- スケジューラ機能をもつGo実行環境
- https://github.com/tosh223/rfa
運用コスト
運用コストは、画像の投稿頻度とデータの蓄積量に依存します。 プレイ頻度は多くても1日に数回だと思いますので、個人で使う分には何百年かは0円で運用できると思います。*1
グラフ
DataStudioを使用しています。BigQueryに保存された最新データを常に表示できるうえに、PC・スマートフォンなどから参照できて便利です。ダッシュボードへのリンクをスマートフォンに登録したり、毎日見るようなページに埋め込むのがおすすめです。Gmailへの定期通知も簡単にできますので、合わせて設定しておくと忘れにくくなると思います。
僕の場合は、Notionを毎日複数回見ますので、トップページに埋め込んで必ず視界に入るようにしています。
Goプログラム
どんなことをしているのか、簡単にご紹介します。
help
$ ./rfa --help Usage of ./rfa: -l string bigquery_location (default "us") -p string gcp_project_id -s string search_size (default "1") -u string twitter_id
ツイート検索
以下の条件でツイートを検索しています。
- 指定した
twitter_id
のツイートであること - リツイートでないこと
#RingFitAdventure
ハッシュタグがついていること- BigQueryに保存されている最新日時より後にツイートされていること
- 画像が添付されていること
Twitter 開発者アカウントの認証キーは、下記 ini ファイルの[DEFAULT]
セクションに保存している前提です。
$ cat $HOME/.twitter/config.ini [DEFAULT] CONSUMER_KEY = **************** CONSUMER_SECRET = **************** ACCESS_TOKEN = **************** ACCESS_TOKEN_SECRET = ****************
画像内のテキスト解析
Cloud Vision API の TEXT_DETECTION を使っています。抽出したツイートに添付されている画像が、上述の2種類であるかをチェックします。
具体的には、画像内に本日の運動結果
という文字列が存在するかを判定条件にしています。
Trueである場合は解析結果を確認し、日本語としてあやしいものや特定の条件下で発生する読み取りミスを補正します。
解析結果の登録
BigQuery へのデータ登録は、CSVファイルを経由して行います。github.com/gocarina/gocsv を使用して、構造体に詰め込んだテキスト解析結果をCSVファイルとして出力しています。そしてこの構造体が、そのままBigQueryのテーブル定義になっています。 1枚目の画像と判定されたら Summary、2枚目の画像の場合は Details として出力されます。
type Summary struct { TwitterId string `json:"twitter_id" csv:"twitter_id"` CreatedAt time.Time `json:"created_at" csv:"created_at"` ImageUrl string `json:"image_url" csv:"image_url"` TotalTimeExcercising time.Duration `json:"total_time_excercising" csv:"total_time_excercising"` TotalCaloriesBurned float64 `json:"total_calories_burned" csv:"total_calories_burned"` TotalDistanceRun float64 `json:"total_distance_run" csv:"total_distance_run"` } type Details struct { TwitterId string `json:"twitter_id" csv:"twitter_id"` CreatedAt time.Time `json:"created_at" csv:"created_at"` ImageUrl string `json:"image_url" csv:"image_url"` ExerciseName string `json:"exercise_name" csv:"exercise_name"` Quantity int `json:"quantity" csv:"quantity"` TotalQuantity int `json:"total_quantity" csv:"total_quantity"` }
これからやりたいこと
pixelaで草を生やす
習慣化という点では、いつ・どれだけやったのかをもっとわかりやすく表示する点で改善の余地があります。これは、pixelaを使って草を生やすのがよさそうなので、ぜひ使ってみたいなと思っています。
過去データ移行
僕がやりたいだけなのですが、以前からやっている人は過去データを移行したくなると思います。習慣化に失敗したあの日々も可視化して、今後の戒めとするのです。
GCP Secret Manager 対応
Twitter 開発者アカウントの認証キーの保存先として、GCP Secret Manager を選べるようにしようと思います。 そうすれば Goプログラムを Cloud Functions に引っ越せるので、GCPですべて完結させることができるためです。
英語対応
リングフィットアドベンチャーには英語版もありますので、英語表記のスクリーンショットにも対応中です。*2
風来のシレン5 Plus 対応
いきなり違うゲームの話になりましたが、とても大事なことです。同じ方法で、別のゲームにも応用できると思っています。長らくさぼっているシレンも、しっかりとこなしていきたいものです。