たくみん成長日記

開発とか趣味とかラブライブとかラブライブとかラブライブとか

CIのテスト結果は黒澤ダイヤちゃんに言われたい

はじめに

こんちか!!たくみんです。久しぶりに記事を書きますが、今回はSlackBot(厳密にはBotではない)です。そろそろ僕もCircleCIとか使って、開発して自動でテストが走って、また開発してといういい感じの奴がしてみたいと思っていました。そこで、CircleCIについて調べているとテストの結果をSlackに通知してくれる奴(Chat Notifications)があるみたいなので、早速自分のSlackに導入してみました。 f:id:takuminv:20190524210110p:plain:w500

なんやこのおもんない通知は!

というわけで、自作で作ってみました。それが黒澤ダイヤBOTです。 f:id:takuminv:20190524210351p:plain:w500 f:id:takuminv:20190524210405p:plain:w500

各種バージョンと動作環境

このBotSinatraを使用しており、動作環境としてPaasのherokuを使用しました。

jp.heroku.com

Slackに通知する情報

テスト結果の情報として表示するのは以下の5つです。

  1. テスト結果
  2. ブランチ名
  3. コミットしたユーザ
  4. GitHubのコミットページのURL
  5. CircleCIのジョブページのURL

ソースコード

やってることはとても単純で、CircleCIから送られてきたJSONデータから、上記の5つの情報を抜き取り、SlackにPOSTしているだけです。 Sinatraを動作させるapp.rbとSlackに通知する情報を管理するpayload.rb(Payloadクラス)の2つを作成しました。

app.rb

require 'sinatra'
require 'json'
require 'dotenv'
require './payload.rb'

Dotenv.load

get '/' do

end

post '/' do

    params = JSON.parse request.body.read # 受け取ったJSONデータを格納 

   # JSONデータから必要な情報のみを取得
    payload = Payload.new(params['payload']['reponame'],
                          params['payload']['outcome'],
                          params['payload']['branch'],
                          params['payload']['committer_name'],
                          params['payload']['subject'],
                          params['payload']['all_commit_details'][0]['commit_url'],
                          params['payload']['build_url'],
                          params['payload']['build_num'],
                          ENV["WEBHOOKURL"])

    payload.post # SlackにPOST
end

payload.rb

require 'net/http'
require 'uri'

class Payload

    # コンストラクタ
    def initialize(reponame, outcome, branch, commiter_name, commit_message, commit_url, build_url, build_num, webhook_url)
        @reponame = reponame
        @outcome = outcome
        @branch = branch
        @commiter_name = commiter_name
        @commit_message = commit_message
        @commit_url = commit_url
        @build_url = build_url
        @build_num = build_num
        @webhook_uri = URI.parse(webhook_url)
        
        # CI結果によって、通知するコメントと、Payloadの色を変更
        @color = "good"
        @pretext = "テストが成功しましたわ!!"
        if @outcome === "failed"
            @color = "danger" 
            @pretext = "テストを失敗するなんてブッブーですわ!!"
        end
    end

    def post
        @post_data = {
            attachments: [
                {                   
                    title: "#{@title} CircleCI結果",
                    pretext: "<!channel> #{@pretext}",
                    text: @outcome,
                    fields: [
                     {
                         title: "branch",
                         value: @branch,
                         short: "true"
                    },
                     {
                         title: "committer_name",
                         value: @commiter_name,
                         short: "true"
                    },
                    {
                         title: "commit_url",
                         value: "<#{@commit_url} | #{@commit_message} >",
                         short: "true"
                    },
                    {
                         title: "build_url",
                         value: "<#{@build_url} | ##{@build_num} >",
                         short: "true"
                     }
                    ],
                    color: @color
                }
            ]
        }
        self.log # log出力
        Net::HTTP.post_form(@webhook_uri, {payload: @post_data.to_json}) # SlackにPOST
    end

    def log
        puts "reponame: #{@reponame}"
        puts "outcome: #{@outcome}"
        puts "branch: #{@branch}"
        puts "commiter_name: #{@commiter_name}"
        puts "commit_message: #{@commit_message}"
        puts "commit_url: #{@commit_url}"
        puts "build_url: #{@build_url}"
        puts "webhook_uri: #{@webhook_uri}"
        puts @post_data
    end

end

Githubのページ

github.com

おわりに

CircleCIから送られてくるJSONデータの構造を理解するのにとても手間取り、3日くらい作業がストップしてしまいました。最終的にpryで確認すれば良いことに気づいてなんとかBotを作ることができました。この表示が見やすいかどうかは人それぞれですが、僕は満足です。

参考ページ

api.slack.com

blog.excite.co.jp

SECCON Beginners CTF 2019 WriteUp

はじめに

こんちか!たくみんです。2019年05月25日 15:00から26日 15:00まで行われたSECCON Beginners CTFに友人と2人で参加しました。 結果は以下の通りで、666チーム中150位でした。 f:id:takuminv:20190526201904p:plain:w500

今回僕が解くことができたのは、以下の2問なのですがMisc Welcomeは解説してもしょうがないので、WebのkatsudonだけWriteUpしていきます。

  • Web katsudon
  • Misc Welcome

Web katsudon

問題文

Rails 5.2.1で作られたサイトです。

https://katsudon.quals.beginners.seccon.jp

クーポンコードを復号するコードは以下の通りですが、まだ実装されてないようです。

フラグは以下にあります。 https://katsudon.quals.beginners.seccon.jp/flag

# app/controllers/coupon_controller.rb
class CouponController < ApplicationController
def index
end

def show
  serial_code = params[:serial_code]
  @coupon_id = Rails.application.message_verifier(:coupon).verify(serial_code)
  end
end

解法

とりあえず、https://katsudon.quals.beginners.seccon.jp/flagにアクセスすると以下のようなページに飛ぶ。

f:id:takuminv:20190526202834p:plain:w500

ここに表示されているコード(クーポンコード)を復号するとフラグ(シリアルコード)がゲットできると思うため、どのように暗号化されているかを調べる。 暗号化に関わってくるのは、問題文中の以下のコードである。

@coupon_id = Rails.application.message_verifier(:coupon).verify(serial_code)

message_verifierについて調べると以下のQiitaの記事が見つかった。

qiita.com

この記事には、 Rubyオブジェクトを文字列化しBase64エンコードした文字列と、Base64エンコードしたものを鍵と組み合わせてSHA1でハッシュ化した文字列を--で繋げます。 と書かれているため、暗号化されたコードの最初から、--までの文字列をBase64で復号すれば、フラグがゲットできる事になる。

よって以下のように、暗号化されたコードのうち、--までのBAhJIiVjdGY0YntLMzNQX1kwVVJfNTNDUjM3X0szWV9CNDUzfQY6BkVUBase64で復号することでフラグゲット!!

$ echo "BAhJIiVjdGY0YntLMzNQX1kwVVJfNTNDUjM3X0szWV9CNDUzfQY6BkVU" | base64 -D
I"%ctf4b{K33P_Y0UR_53CR37_K3Y_B453}:ET%

おわりに

ほとんど足を引っ張ったまま終わってしまったなという印象でした。来年にはWebの問題をもっと解けるようになりたいなと思ったので、他の人のWriteUp等を参考にしながら勉強しようかなと思います。ではでは。

プレゼン中にニコニコ動画のような流れるコメントを流したい

はじめに

こんちか!!たくみんです。 今回は、PowerPoint等のプレゼン資料の上に、ニコニコ動画のようなコメントを流すアプリを開発したので、紹介していきたいと思います。 このアプリを使うことにより、以下の画像のように講者の声がリアルタイムで発表者に届くので、LTがとても面白くなりました。 画面の左側が発表者用アプリ(コメントを画面に流すやつ)で、右側が聴講者用アプリ(コメントを送信するやつ)です。

f:id:takuminv:20190327223010g:plain:w500

開発の経緯

通常のプレゼンや学会発表では、指定された時間(15分や20分)発表を行なった後、質疑応答が行われます。しかしながら、LTといった発表では、発表中にリアルタイムで聴講者の意見や感想を聞ける方が盛り上がりやすいと考えます。そのため、このアプリを作成することにしました。

アプリ構成

このアプリは、聴講者がコメントを送信する用のWebアプリ(Rails製)と、発表者の画面にコメントを表示させるデスクトップアプリ(Electron製)の2つで構成されています。アプリ構成は以下のようになっています。

f:id:takuminv:20190327223456p:plain:w500

2つのアプリの詳細は、別の記事にまとめていきたいと思います。

おわりに

今回は、作った経緯とアプリ全体の概要についてまとめました。それぞれのアプリの概要を説明する記事を早く書きたいと思います。 ではでは。

Sinatraのdatabase.ymlでdotenvを使いたい

こんちか!! たくみんです。最近はSinatraを使って、ちょっとしたWebアプリを作っています。その際にハマったポイントがあるので、備忘録として記事を書いています。

開発中のアプリケーションの構成は、以下のような感じです。

  • rbenv : 1.1.1-39-g59785f6
  • ruby : 2.6.0
  • sinarra : 2.0.5
  • mysql : Ver 8.0.13 for osx10.14 on x86_64 (Homebrew)
./
├── app.rb
├── config.ru
├── database.yml
├── Gemfile
└── Gemfile.lock

ハマったポイント

今回開発中のアプリケーションでは、databaseに接続するための情報を、database.ymlに記述することにしました。

qiita.com

しかしながら、ユーザネームやパスワードなどの情報を、GitHubのpublicリポジトリにpushするのは、あまりよくありません。 そこで、.envgem dotenvによる管理を行うことにしました。

Railsのdatabase.ymlには、erb記法が利用できるという記事を発見したので、Sinatraでも行けるでしょと思い、やってみることにしました。

shuzo-kino.hateblo.jp

そのときのdatabase.ymlとSinarraのapp.rbは以下のような感じです。

adapter: mysql2
encoding: utf8
reconnect: false
database: sqlapps
pool: 5
username: <%= ENV["MYSQL_USERNAME"] %>
password: <%= ENV["MYSQL_PASSWORD"] %>
host: localhost
require 'sinatra'
require 'sinatra/reloader'
require 'mysql2'
require 'dotenv'
require 'yaml'

set :bind, '0.0.0.0'
Dotenv.load
sql_client = Mysql2::Client.new(YAML.load_file('./database.yml'))

get '/' do
  # 省略
end

Sinatraを起動してみると、以下のように、erb記法がうまく解釈されておらず、接続ができていないことがわかります。

Access denied for user '<%= ENV["MYSQL_USERNAME"] %>'@'localhost' (using password: YES) (Mysql2::Error::ConnectionError)

解決方法

解決方法が以下の記事に乗っていました。

www.ohmg.tokyo

この記事によると、以下の手順を踏むことで、解決できるようです。

  1. File.readでdatabase.ymlを読み込む
  2. ERB.new()の引数に、1.を与える
  3. 2.の結果をresult methodで取り出し、yamlとして読み込ませる
  4. 3.の結果をmysql2の引数として与える

コードにすると以下のような感じです。

Mysql2::Client.new(YAML.load(ERB.new(File.read("./database.yml")).result))

修正結果

解決方法を踏まえて、Sinatraのapp.rbを以下のように修正しました。

require 'sinatra/base'
require 'sinatra/reloader'
require 'mysql2'
require 'dotenv'
require 'yaml'
require 'erb'

class SQLApplication < Sinatra::Base

Dotenv.load
yaml_file = File.read("./database.yml")
sql_client = Mysql2::Client.new(YAML.load(ERB.new(yaml_file).result))

  get '/' do
    query = "select * from test1"
    output = ""
    result = sql_client.query(query)
    result.each do |a|
      output =  a["text"]
    end
    return output
  end
end

疎通確認として、適当なテーブルを作成し、表示させてみます。 テーブルは以下のような感じです。

test1
+---------------+-------------+
| id(integer)   | text (text) |
+---------------+-------------+
|    1          | test        |
+---------------+-------------+

表示結果が下の画像です。 f:id:takuminv:20190115020854p:plain

成功です。うまくQueryの結果を表示していることがわかります。

終わりに

Railsだと、コマンド叩いてけばdatabase.ymlが勝手に作られ、 dotenv-railsのおかげで、勝手にerbを解釈してくれるので、楽なのですが、 Sinatraだと全部自分でやらないといけないので、勉強になりました。

やっぱりRailsってすごい…

Unityちゃんを英雄王にしてみた

こんちか!! たくみんです。この記事は、SLP KBIT Advent Calendar 2018の18日目の記事になります。

qiita.com

本題に入りますが、Fateに興味をもちまして、Fate/stay night [Unlimited Blade Works]を視聴しました。

一応最後まで見たんですが、「王の財宝」がかっこよすぎるんですよね。まず、「王の財宝」と書いて、「ゲートオブバビロン」というのが、かっこいいし、迫力も凄いし、もう半端じゃないって思いました。 f:id:takuminv:20181216215245j:plain:w400

そして、思いました。

そうだ、Unityでやろう。

「王の財宝」の確認

まず、「王の財宝」を確認して、どのような要素で構成されているのか、確認してみましょう。 確認すると、「王の財宝」は3つの要素で構成されていることがわかります。

  1. 宝具(剣とか槍とか)
  2. 宝具を射出するやつ
  3. 英雄王本人

f:id:takuminv:20181216220921j:plain:w400

これをUnityで再現します。 つまり、「Unityちゃんが「王の財宝」を使って、的に対して攻撃する」を再現します。 この記事では、「王の財宝」を生成する部分まで紹介します。

Assetの準備

まずは、「王の財宝」を再現するための、Assetを探します。

1. 宝具

宝具に見えるAssetは、下記のものにしました。これなら、無料で使用できますし、それっぽいですからね。 assetstore.unity.com

2. 宝具を射出するやつ

宝具を射出するやつは、下記のものにしました。AssetStoreには、無料でいいものがなかったので、こちらにしました。 ktk-kumamoto.hatenablog.com

3. 英雄王本人

英雄王は、Unityちゃんにしました。ほとんど初めてのUnityなので、下記のQiitaの記事を参考にしました。

qiita.com

assetstore.unity.com

assetstore.unity.com

今回作成したObjectの紹介

今回Scene上に生成するObjectは以下です。

  • Player(Playerが操作するUnityちゃん)
  • target(「王の財宝」の的になるObject)
  • aura_ground(宝具を射出するやつ)
  • sword(宝具)
  • mask_sword(後述)

「王の財宝」を生成するスクリプト

生成するスクリプトは、PlayerにAddしているSwordGeneratorというスクリプトです(くそコードなのは許してください)。とりあえず、Hキーを押すことで、「王の財宝」を生成することにしました。

public class SwordGenerator : MonoBehaviour {

    GameObject sword;
    GameObject mask_sword;
    GameObject sword_circle;
    GameObject player;
    GameObject target;
    // Update is called once per frame

    private void Start()
    {
        sword = (GameObject)Resources.Load("Prefabs/WeaponSword002");
        mask_sword = (GameObject)Resources.Load("Prefabs/Cylinder");
        sword_circle = (GameObject)Resources.Load("Prefabs/aura_ground");
        player = GameObject.Find("Player");
        target = GameObject.Find("target");
    }
    void Update () {
        if (Input.GetKeyDown(KeyCode.H) )
        {
            //---- arua_ground(宝具を射出するやつ)の生成
            Vector3 pos = new Vector3(Random.Range(-20.0f, 20.0f) + player.transform.position.x, player.transform.position.y + Random.Range(2.0f, 12.0f), player.transform.position.z);

            Vector3 pos_circle = pos;

            Vector3 aim = target.transform.position - pos;
            
            Quaternion look = Quaternion.LookRotation(aim);

            pos_circle = pos_circle + (look * new Vector3(0f, 0f, 1.1f));
            Instantiate(sword_circle, pos_circle, look);

             //---- sword(宝具)とmask_swordの生成
            switch(Random.Range(0,11))
            {
                case 0: sword = (GameObject)Resources.Load("Prefabs/WeaponSword000"); break;
                case 1: sword = (GameObject)Resources.Load("Prefabs/WeaponSword001"); break;
                case 2: sword = (GameObject)Resources.Load("Prefabs/WeaponSword002"); break;
                case 3: sword = (GameObject)Resources.Load("Prefabs/WeaponSword003"); break;
                case 4: sword = (GameObject)Resources.Load("Prefabs/WeaponSword004"); break;
                case 5: sword = (GameObject)Resources.Load("Prefabs/WeaponSword005"); break;
                case 6: sword = (GameObject)Resources.Load("Prefabs/WeaponSword006"); break;
                case 7: sword = (GameObject)Resources.Load("Prefabs/WeaponSword007"); break;
                case 8: sword = (GameObject)Resources.Load("Prefabs/WeaponSword008"); break;
                case 9: sword = (GameObject)Resources.Load("Prefabs/WeaponSword009"); break;
                case 10: sword = (GameObject)Resources.Load("Prefabs/WeaponSword010"); break;
            }

            Vector3 axis_x = new Vector3(1f, 0f, 0f);
            Quaternion q_x = Quaternion.AngleAxis(90f, axis_x);

            Vector3 axis_y = new Vector3(0f, 1f, 0f);
            Quaternion q_y = Quaternion.AngleAxis(90f, axis_y);

            look = Quaternion.LookRotation(aim, Vector3.up);
            look = look * q_x * q_y;

            Instantiate(sword, pos, look);
            Instantiate(mask_sword, pos, look);

        }
        
    }
}

ひとつずつ説明していきます。

aura_ground(宝具を射出するやつ)の生成

aura_ground(宝具を射出するやつ)の生成を行います。 このコードで行っている処理は、以下の通りです。

  1. playerの座標と、Random.Range()により、aura_groundを生成する座標を決定
  2. aura_groundの座標とtargetの座標の差と、Quaternion.LookRotation()によりtargetの方向を向くようにする
  3. aura_groundの座標を、targetがいる方向に1.1fずらす(宝具の先っぽの方で、aura_groundを生成するため)。
  4. aura_groundの生成
 //---- sword(宝具)を射出するやつの生成
//-- 1.
Vector3 pos = new Vector3(Random.Range(-20.0f, 20.0f) + player.transform.position.x, player.transform.position.y + Random.Range(2.0f, 12.0f), player.transform.position.z);
Vector3 pos_circle = pos;
//-- 2.
Vector3 aim = target.transform.position - pos_circle;
Quaternion look = Quaternion.LookRotation(aim);
 //-- 3.
pos_circle = pos_circle + (look * new Vector3(0f, 0f, 1.1f));
//-- 4.
Instantiate(sword_circle, pos_circle, look);

1. aura_groundを生成する座標を決定

aura_groundを生成する座標を決定します。Unityちゃんの周りに生成してほしいため、Unityちゃんの座標とRandom.Range()を使用します。これにより、Unityちゃんの座標が中心として、一定の範囲内にarua_groundが生成されるようになります。また、今回はZ座標は、Unityちゃんの座標のままにしているので、aura_groundは、XY平面上に生成されます。 イメージとしては、下図のような感じです。赤丸がUnityちゃんだとすると、赤四角の範囲内に、aura_groundが生成されます。

f:id:takuminv:20181217003216p:plain:w500

2. targetの方向を向くようにする

targetの方向を向かせるために、以下のサイトを参考にしました。

code.hildsoft.com

3. targetの方向に座標をずらす

Vector3型のベクトルにQuaternionを掛け合わせることで、ベクトルを回転させることができます。これにより、「現在の座標」に「target方向に向いた大きさ1.1fのベクトル」を足すことで、座標をずらしています。

4. aura_groundの生成

Instantiate()で生成しているだけです。

sword(宝具)の生成

sword(宝具)の生成を行います。 このコードで行っている処理は、以下の通りです。

  1. 生成するsword(宝具)をランダムで決める
  2. aura_groundと、Object自体の向いている方向?が異なっているため、補正
  3. sword(宝具)とmask_swordの生成
//---- sword(宝具)とmask_swordの生成
//-- 1. 
switch(Random.Range(0,11))
 {
    case 0: sword = (GameObject)Resources.Load("Prefabs/WeaponSword000"); break;
    case 1: sword = (GameObject)Resources.Load("Prefabs/WeaponSword001"); break;
    case 2: sword = (GameObject)Resources.Load("Prefabs/WeaponSword002"); break;
    case 3: sword = (GameObject)Resources.Load("Prefabs/WeaponSword003"); break;
    case 4: sword = (GameObject)Resources.Load("Prefabs/WeaponSword004"); break;
    case 5: sword = (GameObject)Resources.Load("Prefabs/WeaponSword005"); break;
    case 6: sword = (GameObject)Resources.Load("Prefabs/WeaponSword006"); break;
    case 7: sword = (GameObject)Resources.Load("Prefabs/WeaponSword007"); break;
    case 8: sword = (GameObject)Resources.Load("Prefabs/WeaponSword008"); break;
    case 9: sword = (GameObject)Resources.Load("Prefabs/WeaponSword009"); break;
    case 10: sword = (GameObject)Resources.Load("Prefabs/WeaponSword010"); break;
 }
//-- 2.
Vector3 axis_x = new Vector3(1f, 0f, 0f);
 Quaternion q_x = Quaternion.AngleAxis(90f, axis_x);

Vector3 axis_y = new Vector3(0f, 1f, 0f);
Quaternion q_y = Quaternion.AngleAxis(90f, axis_y);

 look = Quaternion.LookRotation(aim);
 look = look * q_x * q_y;

//-- 3.
Instantiate(sword, pos, look);
Instantiate(mask_sword, pos, look);

1. ランダムでsword(宝具)を生成

Random.Range()とswitch文により、生成するPrefabを変えています。でもこの書き方はちょっとダサい気がするので、何かいい方法を知っていれば教えてください。

2. 向きの補正

「王の財宝」を再現するためには、sword(宝具)とaura_groundが同じ方向を向いている必要があります。では、以下の2つの画像を見てください。この2つの画像では、2つとも同じ上方向を向かせているつもりなのですが、ObjectのRotationを確認すると、まったく違う方向を向いていることがわかります。そのため、ただ、targetの方向を見るだけでは不十分であり、向きの補正が必要なのです。

f:id:takuminv:20181217005629p:plain:w300f:id:takuminv:20181217005635p:plain:w300

4. 宝具の生成

sword(宝具)をInstantiate()するわけですが、このままでは、aura_groundの裏側にもsword(宝具)が表示されてしまいます。「王の財宝」を再現する場合、以下の画像のように、aura_groundの裏側になる部分は、隠れていないとダメなのです。

f:id:takuminv:20181217195247p:plain:w400

では、どのようにして、指定の部分のみを非表示にするのか。その答えが以下の記事にありました。 つまり、別のオブジェクトを重ねることで、見かけ上隠すということです。

nn-hokuson.hatenablog.com

今回は、swordより少し大きいCylinderをswordに重ねることで、隠すことに成功しました。

f:id:takuminv:20181217225523p:plain:w400

スクリプトの実行結果

実行してみると、かなりそれっぽくなっていることがわかりますね。個人的には大満足です。 f:id:takuminv:20181217014143p:plain:w500

感想

ほとんど初めてのUnityだったので、Prefabってなに?Assetってなに?からのスタートでした。一番わからないのは、Quaternionですね。定義やリファレンスを見てもワケワカメ状態でした(そもそもベクトルがわからん)。3Dゲームを作るとなると、数学の知識が必要になってくるらしいので勉強しないとまずいかなって感じです。

おわりに

とりあえず「王の財宝」の生成までの記事を書いてみました。次は、射出する話であったり、背景と地形(Unlimited Blade Works再現)の話などを書いていこうかなと思います。ではでは。

ラブライブ!サンシャイン!! Aqours 4th LoveLive! ~Sailing to the Sunshine~に現地参加してきました!!

こんちか!!たくみんです。2018年11月17日、18日に東京ドームで行われたラブライブ!サンシャイン!! Aqours 4th LoveLive! ~Sailing to the Sunshine~の1日目に現地参加してきました!! f:id:takuminv:20181121004502p:plain:w500

いままで、1st、2nd、3rdと現地参加してきましたが、いままでで一番素晴らしく感動したライブになりました!この記事では、ライブの内容と感想について書いていこうかなと思います。

ライブ概要

  • 日時 : 11月17日 17:00~20:30、18日 16:00~19:30
  • 場所 : 東京ドーム
  • 動員数 : 15万人(ライブビューイング含め)

日時は、最初に書いた通り、11月17日、18日で、場所は東京ドームです。動員数は、ライブビューイング含め15万人とかなり大規模なライブとなりました。いままで行ってきたライブの中でもトップの動員数です。チケットの選考抽選申込券は、1日目、2日目それぞれ「ラブライブ!サンシャイン!!」TVアニメ2期Blu-ray第7巻特装限定版(1)とAqours 4th LIVE テーマソングCD「Thank you, FRIENDS!!」(2)に封入されています。また、4thライブでの初の試みとして、加藤達也氏率いる浦の星交響楽団によるオーケストラ演奏がありました。加藤達也氏は、ラブライブサンシャインの楽曲を担当している人で、今回のライブでは、アニメに使用されたBGMを生オーケストラで聞くことができました。

(1)f:id:takuminv:20181120225522j:plain:w300 (2)f:id:takuminv:20181120225524j:plain:w200

1日目の流れ

1日目は、以下のように進行しました。アンコール含め以下の22曲が披露されました。

ーMCー(コーレス)

ーアニメ振り返り映像(with フルオーケストラ)ー

ーMCー

ーアニメ振り返り映像(with フルオーケストラ)ー

  • 12.MY舞☆TONIGHT
  • 13.待ってて愛のうた
  • 14.未熟DREAMER

ーアニメ振り返り映像(with フルオーケストラ)ー

  • 15.MIRAI TICKET
  • 16.キセキヒカル(with オーケストラ)

ーMCー(浦の星交響楽団撤収+Saint snow登場)

  • 17.Awaken the power

ーMCー(Saint snow挨拶)

ーMCー(劇場版最新情報・最後の挨拶)

  • アンコール3.Thank you, FRIENDS!!

これから、それぞれの感想を話していきたいと思います。

OP. Main theme of Lovelive! Sunshine!(フルオーケストラ)

ラブライブのライブは、開始時間になると同時に、メンバー紹介のムービーが入ります。今までは、ムービーのBGMはCD音源??であり、生の演奏ではありませんでした。 ライブが始まる前から、オーケストラの楽器が見えていたのでまさかとは思っていましたが、生演奏が聞けるとは思いませんでした。 やはり、生オーケストラだと、迫力が違いましたね(笑)今までのライブにはなかったものをいきなりぶっこんで来たので、「今回のライブは今までと違う!」感がすごかったです!

1. 君のこころは輝いてるかい?

「君のこころは輝いてるかい?」は、記念すべきAqoursの1stシングルに封入されているAqoursのデビュー曲です。1曲目はアニメ1期のOPである「青空Jumping Heart」かアニメ2期のOPである「未来の僕らは知ってるよ」のどちらかだと思っていたため、いきなり予想を外されました。1曲目が「君ここ」だったため、1stライブのことを思い出してすごく感動したとともに、テンションが上がって叫びまくっていました(笑)

f:id:takuminv:20181121032908j:plain:w200

2.Step!ZERO to ONE

「Step!ZERO to ONE」は、「君のこころは輝いてるかい?」と同じCDに収録されており、1stライブの代表曲にもなっています。Aqoursの目標の一つである「0を1にする」に対する思いが込められており、「君ここ」と同様にAqoursはここから始まったといえる曲です。「君ここ」と「Step!ZERO to ONE」が最初に来たのは、Aqoursの原点を思い出させるためなのかもしれません。

3. 恋になりたいAQUARIUM

恋になりたいAQUARIUM」は、「君ここ」の次に発売した2ndシングルの曲です。この曲のセンターは、事前に行われた第1回人気投票で1位となった渡辺曜が担当しました。「恋になりたいAQUARIUM」にはPVがついているのですが、そのPVでの曜ちゃんが可愛すぎて、全国の渡辺曜推しは、天に召されたことでしょう(私は、津島善子推しなのでセーフでした)。いつものライブでは、中盤に歌われることが多い印象だったのですが、3曲目でぶっこんできましたね。私の周りにいた人たちも、「恋アクくるのはやくないか!?」や「今回のセトリやばいかも」と言っていました。

f:id:takuminv:20181121032918j:plain:w200

MC(コーレス)

ライブ恒例のコール&レスポンスです。メンバーごとにコール&レスポンスが決まっていて、Aqoursラブライバーでやり取りが行われます。楽曲ごとのコールは覚えられなくても、最悪このコーレスを覚えていればなんとかなります。なので、ライブに参加する人は、メンバーとのコーレスは覚えておいた方がいいかもしれません。 今回のコーレスで最高によかったのは、黒澤ダイヤ役の小宮有紗さんとのコーレスですね。小宮さんはいつも、ファンに対して、「好きよ」と言うのですが今回はアドリブで「しゅき」に変えてきたんですね。もうこれはやばかったです。もうやばかったです。まあこのあと肝心のコーレスをするのを忘れてしまったのが小宮さんっぽくておもしろかったです(笑)

4. 少女以上の恋がしたい

この曲は、Aqoursの3rdシングル「HAPPY PARTY TRAIN」に収録されているカップリング曲の一つです。いままでのAqpursの曲とは違い、かなり恋愛を意識した曲で、全体的にかわいいかんじの曲となっています。ですが、この曲が来るとはまったく思っていませんでした。今回のライブは、「アニメの曲」+「シングルの曲」が中心になると思っていたので、来るとしても「HAPPY PARTY TRAIN」だと思っていました(「HAPPY PARTY TRAIN」は2日目に披露されたようです)。曲が可愛いのもそうなのですが、振り付けもかなりかわいいので、ぜひライブ映像を見ることをおすすめします。

5. 青空Jumping Heart

この曲は、アニメ1期のOPであり、アニメ2期13話のラブライブ本選のアンコールでも歌われた曲です。1期のOPだったので、この曲でAqoursを知った人も多いんじゃないでしょうか。私自身も、アニメ1期が始まったころはそこまでハマっていなくて、せっかくアニメが始まったんだから見ようかなくらいだったのですが、今では生活の7割がAqoursに染まってしまいました。この曲は必ず来るとはおもっていたのですが、「少女以上の恋がしたい」の次に来るとはおもっていなかったので、「ここで来るのか!」って感じでしたね。コールがかなりお盛り上がる曲の1つなので、全力で大声を出していました。

f:id:takuminv:20181121033325j:plain:w200

アニメ振り返り映像(with フルオーケストラ)

Aqpursのメンバーが次の衣装に着替えてる間に、アニメ1期のダイジェスト映像が流れました。しかもフルオーケストラ付きです。1期のダイジェストだったので、「次は1期の曲か!?何が来るんだ!?」って感じでした。

6. 決めたよ Hand in Hand

この曲は、アニメ1期1話のエンディング(挿入歌)です。Aqoursの2年生3人の曲で、テンポが速く、かなり明るい曲になります。個人的に好きな曲の一つなので、この曲が来てくれたことがとてもうれしかったです。

f:id:takuminv:20181121033533j:plain:w200

7. Waku-Waku-Week!

この曲は、アニメ1期ブルーレイの3巻に収録されている1年生3人の曲です。1年生3人の仲の良さが伝わってくるような楽しい曲になっています。この曲は、2ndライブのブルーレイでは見たことがあったのですが、生で見たのは初めてだったので、とてもうれしかったです。

8.G線上のシンデレラ

この曲は、アニメ1期ブルーレイの5巻に収録されている3年生3人の曲です。1年生の曲とは打って変わって、大人っぽいワルツをテーマにした曲です。ライブでは、3年生3人と1年生3人がペアとなって、ワルツを踊っていました。個人的に好きな楽曲ランキングベスト5に入る曲なので、「Waku-Waku-Week!」同様、生で聞けて良かったです。

9. 想いよひとつになれ(9人バージョン)

もうこの曲を聴くだけで泣きそうになってしまいます。この曲は、アニメ11話の挿入歌であり、ラブライブの予備予選で、Aqoursが披露した曲です。桜内梨子が出場するピアノコンクールとラブライブの地区予選の日にちがかぶってしまい、梨子がピアノコンクールへの出場を辞退しようとしていたところに、主人公である高海千歌が「ピアノコンクールに出てほしい」と、背中をおし、梨子はピアノコンクール、他8人は、ラブライブ地区予選に出場します。そして、梨子はコンクール入賞、Aqoursは地区予選突破を果たすアニメ屈指の感動話です。また、梨子がコンクールで発表した曲に歌詞をのせたのがこの「思いよひとつになれ」となっています。1stライブでは 桜内梨子役の逢田梨香子さん(通称りきゃこ)がピアノ未経験にもかかわらず、「思いよひとつになれ」のピアノ演奏を行うなど、Aqoursの曲のなかでも1位、2位を争う曲なのではないでしょうか。今回の4thライブでも、りきゃこがピアノとともに登場したので、ピアノ演奏かと思ったのですが、今回は違いました。なんと、8人の曲だった「思いよひとつになれ」を桜内梨子含めた9人の曲として、披露したのです。フォーメーションや、歌う順番もすべて9人用に作り直しており、この時点で私は泣いていました。振り付けの途中で、りきゃこが高海千歌役の伊波杏樹さんの手を奪う部分があったのですが、そこも感動しました。

f:id:takuminv:20181121033552j:plain:w200

MC

このMCでは、6. 7. 8. 9.の楽曲についてのMCでした。このMCでりきゃこが「思いよひとつになれをみんなと一緒に踊るのがゆめだった。Aqoursのメンバーがフォーメーションなどを一緒に考えてくれた。」と言ったときに、Aqoursのメンバーの絆がとても強いこと、メンバーがラブライブにかけている気持ちが伝わってきて、号泣してしまいました。1stライブのときも泣きそうになってましたが、今回は、泣いちゃいましたね。

10. 聖なる日の祈り

この曲は、「ジングルベルがとまらない」に収録されているカップリング曲です。クリスマスをテーマとするバラードとなっています。Aqoursからの早めのクリスマスプレゼントということで披露されました。いままでの1st、2nd、3rdは5月から9月に行われることが多かったため、ライブで披露されることはなかったのですが、今回初のお披露目となりました(ミニライブなら披露されています)。歌っているときにメンバーがランタン??のようなものをもっていて、かなり幻想的な雰囲気となっていました。また、最初に「聖なる日の祈り」がきたため、「ジングルベルがとまらない」は2日目に来るのかなと思っていました。

11. ジングルベルがとまらない

と思ったら、「聖なる日の祈り」の次に来ましたね。こちらは「聖なる日の祈り」とは違い、かなりアップテンポで明るい曲となっています。「ジングルベルに乾杯!!」と「ジングルベルとまんない!!」はかなり印象にのこるフレーズで、コールも大盛り上がりでした。

f:id:takuminv:20181121033633j:plain:w200

アニメ振り返り映像(with フルオーケストラ)

ここは確か、アニメ1期後半とアニメ2期前半だったかな??ちがってたらごめんなさい。水分を補給するとともに、アニメの振り返りができるので、よかったです。

12.MY舞☆TONIGHT

この曲は、アニメ2期の3話の挿入歌で、ラブライブの予備予選で披露した曲になります。アニメ2期の2話で、1年生と3年生の6人が力を合わせて作成した曲でもあります。和風な感じの曲で、衣装は花魁を若干イメージしていると思われます。3rdライブでも披露されていたのですが、MY舞☆TONIGHTの衣装が披露されたのは今回が初だったので、迫力が強まっていました。

f:id:takuminv:20181121012949j:plain:w200

13. 待ってて愛のうた

この曲は、Aqours2ndシングル「恋になりたいAQUARIUM」に収録されているカップリング曲です。この曲はCメロがかなり好きで、メンバーひとりひとりがソロで歌うのですが、ライブでも全員が縦一列に並び、ひとりひとり歌いながら移動していくというかなり好きな振り付けになっています。しかし、今回のライブでは、メンバーがステージ横いっぱいに並び、歌いながら中央に戻るといういままでと違ったものだったのでとても驚きました。

14. 未熟DREAMER

この曲は、アニメ1期の9話挿入歌です。Aqoursが9人になって初めて披露した曲でもあります。この未熟DREAMERの衣装は浴衣なので、それに近いMY舞☆TONIGHTの衣装もとてもマッチしていました。今回のライブは、楽曲の順番が本当に読めなくて、次に何がくるのか全然わかりませんでした。

f:id:takuminv:20181121033652j:plain:w200

アニメ振り返り映像(with フルオーケストラ)

おそらくアニメ2期後半だったかな。

15. MIRAI TICKET

この曲は、アニメ1期の13話挿入歌であり、ラブライブの東海地区予選で披露した曲です。今回のライブでは、Aqoursシップと呼ばれる大船に乗って登場し、Aqoursシップ上で踊りました。このときほどアリーナ席がうらやましかったことはありません。

16.キセキヒカル(with オーケストラ)

この曲は、アニメ2期のブルーレイ7巻に収録されている曲です。また、「キセキヒカル」はアニメのBGMに歌が載せられたものとなっており、今回のライブでは、オーケストラ演奏とともに披露されました。ライブでの披露は今回が初でした。この曲のほかアニメ2期ブルーレイ全館購入特典の3曲は卒業や別れがテーマなので、Aqoursの終わりを考えてしまい、すこし悲しくなってしまいます。

MC(浦の星交響楽団撤収+Saint snow登場)

「キセキヒカル」を披露したことで、浦の星交響楽団は会場全員の拍手とともに撤収していきました。オーケストラの迫力はすさまじいもので、ここまで変わるのかと思いました。また、スペシャルゲストとして、AqoursのライバルユニットであるSaint Snowが登場しました。

17. Awaken the power

この曲は、アニメ2期9話の挿入歌であり、Aqoursの9人とSaint Snowの2人を合わせたグループ「Saint Aqpurs Snow」の曲であり、妹である黒澤ルビィと鹿角理亜が、姉である黒澤ダイヤと鹿角聖良に送る曲です。「Awaken the power」はラブライブサンシャインの楽曲の中で一番盛り上がる曲だと思います。サビでの「Hi! Hi! Hi!」のコールは、会場全体が一体となることができるコールです。3rdライブでも披露されましたが、その時も超大盛り上がりでした。

f:id:takuminv:20181121033726j:plain:w200

MC(Saint snow挨拶)

このMCでは、Saint Snowの2人がMCの中心となっており、東京ドームの景色を見せてくれたラブライブAqoursのメンバーに感謝の気持ちを伝えていました。

18. No.10

この曲は、4thライブテーマソング「Thank you, FRIENDS!!」に収録されているカップリング曲であり、ファンのみんなはAqoursの10人目だということを伝えてくれる曲です。この「ファンのみんなはグループの10人目」というのは、μ'sのときから続いているものでラブライブを代表する要素の一つなんじゃないかと思っています。また、Aqoursのメンバーも一緒に歌おうといってくれて、会場の6万人(ライブビューイング含め7.5万人)で合掌しました。

19. ユメ語るよりユメ歌おう

この曲は、アニメ1期のED曲です。ラブライブのED曲は、会場全員で歌うことが恒例となっているため、「No.10」と同様に、全員で歌いました。また、コールも存在しているため、歌いながらコールをするのはなかなか大変でした(笑)2日目には、「ユメ語るよりユメ歌おう」ではなく、アニメ2期のED曲である「勇気はどこに?君の胸に!」が披露されたようです。ここでいったんライブが終了し、Aqoursコール(アンコール)が行われました。 通常のアンコールでは、「アンコール!アンコール!」と叫ぶと思うのですが、Aqoursでは、「Aqours!Aqours!」と叫びます。これは、3rdライブから始まったもので、おそらくアニメ2期11話で、Aqoursコールが行われたことが原点となっていると思います。

アンコール1. 未来の僕らは知ってるよ

この曲はアニメ2期のOPです。コールがかなり盛り上がったのですが、なにより衣装がすさまじかったです。アンコール明けから、「Thank you, FRIENDS!!」の衣装に着替えており、可愛すぎて死ぬかと思いました。 個人的にも好きな曲なので、「ここで、来るかぁ」と思いました。

f:id:takuminv:20181121033934j:plain:w200

アンコール2. WONDERFUL STORIES

この曲は、アニメ2期13話の挿入歌であり、3rdライブのテーマとなった曲です。アニメ2期のOPのあとに、アニメ2期の最後の曲を持ってきたのがとてもいいと感じました。Aqours高海千歌がずっと探してきた「輝き」はいままで歩んできた道、みんなで過ごしてきた時間だったのだと結論付けるこの曲は、Aqoursの集大成ともいえる曲の1つではないでしょうか。いまでも13話のこの曲を聴くたびに鳥肌が立ってしまいます。ライブでも鳥肌バチバチでした。

f:id:takuminv:20181121033951j:plain:w200

MC(劇場版最新情報・最後の挨拶)

まず最初に年明けの1月4日に公開される劇場版の新情報が公開されました。最後のあいさつでは、メンバーがどれだけラブライブというコンテンツが好きなのか、Aqoursが好きなのか、ファンのみんなが好きなのかがとても伝わってきて、これからもずっと応援したいと思いました。ラブライブがみんなの夢の手助けになればうれしいとも言っていて、大学生活や、来年から始まる社会人生活を頑張っていこうと思いました。

Thank you, FRIENDS!!

この曲は、4thライブのテーマソングになっている曲です。この曲に関しては、素晴らしい曲以外の感想が思いつかないくらい素晴らしい曲だと思います。この曲を聴いていると、高校生の時μ'sにであってよかった。大学2年生のときにAqoursに出会ってよかったと、とても思います。ラブライブに出会っていなかったらこんな楽しい経験はできなかったと思いますし、ここまで何かに打ち込むこともなかったと思います。 ライブの3時間半が本当にあっという間で、Thank you, FRIENDS!!を歌い終わって、メンバーが退場した後、ちょっとした虚無感がありました。

f:id:takuminv:20181120225524j:plain:w200

全体の感想

今回のライブは、いままでやってなかったことに多く挑戦しているライブだと感じました。生オーケストラであったり、思いよひとつになれ9人バージョンであったり、Aqoursシップの登場などですね。また、セトリもAqoursの始まりから現在に至るまでを網羅するようなものになっており、Aqoursがたどってきた道を再確認できる素晴らしいライブでした。中でも一番はやはり、「思いよひとつになれ」ですね。私は、映画等を見てもなくタイプではないのですが、今回は本当に号泣してしまいました。このおかげで、AqoursのFinalライブでは絶対に泣くことが確定しましたね(笑)。それだけ私のなかでラブライブというコンテンツは大きなものになっていると再認識しました。本当に最高のライブでした!!ありがとうございました!!1日目には発表されなかったのですが、5thライブの開催が発表されたので、必ず現地参加したいと考えています。

おまけ

ライブ終了後に、会場限定の「Thank you, FRIENDS!! SOLOCONCERT」を購入し、御茶ノ水にある神田明神に行きました。

Thank you, FRIENDS!! SOLOCONCERT

会場限定で発売された「Thank you, FRIENDS!!」の全員のソロ曲が収録されているものです。最高すぎて、通学中は常に車の中で聴いています。正直売り切れると思っていたのであきらめていたのですが、購入することができてとてもよかったです。

f:id:takuminv:20181121031932j:plain:h400

神田明神

ライブ終了後に、神田明神に行ってきました。東京ドームの最寄り駅である水道橋駅神田明神の最寄り駅である御茶ノ水は隣同士なので、歩いていきました。同じことを考えている人が大量にいて、40人ぐらいの人と一緒になって移動しました。実は、6月の3rdライブの時にも神田明神を訪れており、その時の絵馬に「4thライブに当選すること」、「第一志望の企業から内定をもらうこと」の2つを書きました。そのおかげが、両方とも叶えることができたので、そのお礼もかねて(というかそれが目的)参拝しました。本当は、ライブが始まる前に行き、絵馬を書く予定だったのですが、時間の見通しがあまく、ライブ終了後となってしまったため、絵馬は書けませんでした。

RaspberryPi +Sinatra + SlackBotでエアコンを遠隔操作しよう(全体説明編)

こんちか!!たくみんです。最近、とても寒くなってきましたね。私も家にいる間は暖房をつけています。 こうなると問題になるのが、エアコンの消し忘れです。私はとても忘れっぽい性格なので、よくエアコンを消し忘れてしまっています。 というわけで、自分の部屋のエアコンを外から操作できるシステムを開発しました。この記事含め、4つの記事で紹介していきたいと思います。

エアコン遠隔操作の考え方

エアコンやテレビなどの家電製品は、リモコンで操作することが多いです。そしてそのリモコンは、「電源オン」、「電源オフ」等の操作に対応した赤外線を家電製品に送信して動作させています。 つまり、リモコンが送信する赤外線と同じパターンの赤外線を送信することができれば、家電製品を操作できることになります。 今回は、Raspberry Piを用いて、リモコンが送信している赤外線を解析し、まったく同じパターンの赤外線を送信することで、遠隔操作を実現します。また、外部から操作する方法として、SlackBotを採用しました。SlackBotのほかに、デスクトップアプリも開発したのですが、ポート開放をしないといけないことやCSRF(クロスサイトリクエストフォージェリ)の対策を考えないといけないので、今回はSlackBotを採用しています。

使い方

使い方は簡単です。以下のようにSlack上の桜内梨子ちゃんBotに、「冷房」、「暖房」、「電源オフ」と伝えることでそれぞれ、「冷房をつける」、「暖房をつける」、「電源を消す」という動作をさせることができます。現在はまだ開発途中なので、温度を変えることはできません。梨子ちゃんの口調に違和感があるのでこれから直していきます。

f:id:takuminv:20181115000841p:plain:w500

システム構成

このシステムは、Raspberry PiとSlackBot(Ruby製)とSinatraで構成されています。 SinatraはRasberryPi上に構成されており、SlackBotから、SinatraサーバにGETリクエストすることで、赤外線を送信するスクリプトを実行し、エアコンを操作します。操作した後は、json形式でエアコンの状態をSlackBotに返却し、Slack上で通知します。現在は、DB等を使用していないのですが、もしかすると、エアコンの状態や遠隔操作した時間などをDBに保存するかもしれません。

f:id:takuminv:20181115011006p:plain:w500

おわりに

このシステムにより、エアコンを消し忘れたとしても、外から消すことが可能になりました。また、家に帰る直前にエアコンをつけておくことで、家に着いた頃に室温を最適にしておくこともできるようになりました。残る3つの記事は、「Raspberry Pi編」、「Sinatra編」、「SlackBot編」となります。ではでは。