日頃の行い

個人的な日頃の行いをつらつら書いてます\\\\ ٩( 'ω' )و ////

Splathon#9にAjitoonで参加してきた感想と今までの振り返り

こんばんは、ここのところSplatoonの記事しか書いてませんが、エンジニアです。
最近はScalaを書いています。本当です。信じてください。
さて、先日24日(日)にSplathonの第9回目のイベントがあってそれに参加してきた感想メモろうかなと思いました。

Splathonって?みたいなのは前書いたりしたので、気になったりしたら見てもらえると嬉しいです。

arata.hatenadiary.com

Splathonと書いてるのですが、コミュニティの名前を示しつつも、
オフラインでどこかに集まって行うイベントのことをもともと呼んでたのかな(?)なので、
今回はオフラインで集まって行われた大会の話になります。
自分は単に参加者として1チームとして出たので全体の感想と、
実は3回目(Splathon#7, #8を経て)の参加なのでそれも合わせて振り返りつつ、
チームで大会に出るとこんなに楽しいんだぞ!みたいなのが伝わったら幸いです。

Splathon#9の感想

「やべぇ・・・(語彙力)」

でしたw
前回#8でも準備がすごくて「すっごーい(語彙力)」って思ってたんですけど、
今回到着した際に、「え・・・これどこのe-sportsの大会ですか・・・?」ってなりました。

前回(Splathon#8)の様子です。

kawakubox.hatenablog.com

今回(Splathon#9)の様子です。

やばくないですか?
6卓ですよ6卓。A卓なんて全試合通じて解説入ってるし、
A, B, C, D卓はLogicoolのヘッドセット付きで、チーム会話が出来るんですよ。
チームで会話しながら練習してきた身としては超絶最高でした。
なんと協賛していただけたんですね!ほしいものリストまではすでに入りました。
(別のLogicoolの使ってるんだよなぁ

ちなみに解説の様子は当日のTwitchの配信があるのでちょっと覗いてみてください。
e-sportsの大会にしか見えないと思います。
ちなみに、最後優勝チームが決まってトロフィーが授与されたあと、
イカ研究員さんからアップデートのお知らせが来るって体が勝手に思うくらいやばかったです。
直後に、あ、そうだこれコミュニティのイベントだって我に返りました。
ブキチコレクションはよ。

www.twitch.tv

当日のTwitterの様子もtoggeterにまとめられてるみたいなのでぜひ見てみてください。

togetter.com

Splathon#7, #8, #9の参加を経て

Splathon#7から参加したんですが、今回チームになってきた気がするなぁって思ったのでちょっと振り返ろうかなぁと思います。

Splathon #7

自分たちが初めて参加したのがSplathon#7でした。
ニコ生だったんですけど、もう見れなくなってました。悲しい。

live.nicovideo.jp

この頃の自分のチーム、Ajitoonは単に集まっただけの構成だったんじゃないかなぁって気がします。
自分は確か赤ZAPとか持って、
ローラー2枚とカーリングもう1枚でホッケふ頭を駆け巡っていて、
打開?戦略?チーム連携?何それみたいな構成だった記憶がかすかにありますw

ただ、この時参加してよかったなと思ったのは、
ガチマッチやリーグマッチとは違う、どうしても勝たなければならない一回一回の勝負で勝つとすごい嬉しい。
そして、負けるとすごい悔しいと感じたことでした。
こう思うと勝てるようもっと練習しよう、勝つためにはどうしたらいいんだって考えるのが始まって最高に楽しいです。
スポーツって感じがしますね!

その後チームで練習しようってなりました(確か
そのあたりからチームでの活動が始まって、毎週木曜日の夜を練習日として、リグマに行くようになりました。
そして時を経てSplathon#8に参加しました。
アーカイブ残ってた(・∀・)

Splathon #8

youtu.be

この頃は自分たちが使える武器を使いつつ、
打開時に必ずスペシャルを合わせる動きは出来るようになっていました。
ガチマッチでの基本は出来るようになってた感じですね。
個々人の強さが前より上がっていた気がします。
ただ武器構成は比較的前よりで、この時はスパヒュー、カーボン、プラコラ or ホットブラスター、プライムだったみたいです。
雨だらけですね。

ただ、この時は合わせられるようになりつつも、各々が味方に場所を教えてもらいつつ、
単にガチマッチをやっているような動きになっていたような気がします。
チームとして連携が取れているかというとまだまだ怪しいんじゃないかなと思います。
まだまだ課題は残っていた感じがします。

このあと、Splathon#8が2018年5月開催で、
Splathon#9(今回)が2019年2月開催なため、かなり練習できました。
実際には、いろんな武器を試したりいろんな武器構成を試したりしました。
自分の場合、スパヒュー -> デュアル -> エクスプロッシャー or クーゲルシュライバーと射程が伸びていったり、
もうひとりはホットブラスター -> 96ガロン -> ジェットスイーパーカスタム -> 96ガロン(だったかな) と変わったりしました。
カーボンのプロはカーボン一筋でしたね。さすがや。

非常に嬉しかったのが、徐々に最高リーグパワーが上がっていって成長を感じたことでした。
大事なのは、偶然上がったというよりはちゃんと各々が役割をこなして勝てるという試合が増えてきたと感じたことでした。
あと、SplathonのコミュニティではLadderという、数ヶ月の期間で順位を決めるリーグがあって、
そこでも安定して勝てるようになってきたのもまた一つ自身につながった気がします。
やはり具体的な数字に現れると嬉しいですね。

そんな状態で迎えた今回のSplathon#9でした。
決勝トーナメントに行きたいそんな思いで参加しました。

Splathon #9

https://www.twitch.tv/videos/385725447?t=06h55m10s

配信に辛くも乗ることが出来た試合がこちらでした。
相手にXパワー2700とかいて、「えぇ・・・」とか思ってました。
最終的な結果は2勝1敗1分で10位タイでOMWPを考慮すると11位でした。
配信に載っている試合に勝てれば決勝トーナメントだったので非常に悔しい結果となりました。

ただ、今回よかったなと思ったのが初めの2チームとの試合に全勝出来たことでした。
ルールがナワバリとヤグラだったのですが、
ヤグラは練習してきた構成でちゃんと勝ち、
ナワバリはエリアと同様の動きで最後逆転勝ちをしっかり決めて勝つことが出来ました。
パワーバランスが近いチームに対してしっかり勝ちをものにできたんじゃないかなと思い、
過去の参加からの成長を感じました。

前まではパワーバランスが近いチームに対して危うかったんですよね。
気を抜くと負けてしまうみたいなのがあったりしました。
でも、どうしても勝たなければならない一回一回の勝負で、
しっかり勝てるようになってきたと実感するのは本当に嬉しかったです。
勝ったときにマジ味方ナイス最高って叫べるの本当に楽しいです。
マジ最高、Ajitoonありがとう!

しかし、俺たちの戦いはここからだなーと思いました()
強いチームなんであんなに強いのかわからないんですよねw
3試合目に最終的に優勝したチームにフルボッコでやられたあとの自分の気持ちです。

もうなんかわからないけど、
チームでっていうよりそろそろ個々の力を強くしないといけない気がしてきたんですよね。
そして思ったのがこちら。

まあなんか、Splathonに参加するとモチベーション上がりすぎますね。
本当に良くない。これのせいでテイルズオブヴェスペリアやってる場合じゃなくなりました。
ガチマ、疲弊するから最近逃げちゃってたけど、戦うことにしました。
2700目指すぞ!!!1111(震え声

たまに配信してるから応援してくれよな!

まとめ

  • Splathon#9まじやべぇ
    • 最高に楽しかったです!
    • 趣味のコミュニティだから仕方ないよねーみたいなの一切なかったw
    • 完成度がヤバイ
    • Splathon#10も期待大だけど無理せず行ってほしい
    • botの実装とか手伝うかー
  • 今の完成度とか関係なくチームでとりあえず出るの本当におすすめ!
    • 自分はこのコミュニティで初めてチーム組んだけど、すっごい学び多いし、ガチマッチにもかなり活きてるので本当におすすめ
    • ガチマッチには正直どうでも良い
    • 勝ったことを一緒に楽しんで、負けたことを一緒に振り返られるチーム本当に最高なのでまじおすすめ

Splatoonの企業対抗戦やってるコミュニティに入ったらすごく楽しかった話

これは Splathon Advent Calendar 2018 - Adventar の9日目の記事です。

なんでもどうぞってことだったのでSplathonの思い出を語ろうと思います。
Splathonってなんだろうとか、コミュニティ楽しそうとか、チーム組んで戦うのが楽しそうってのが伝わったら嬉しいです。

Splathonとは

Splathonという単語の意味はこんな感じらしいです。
最近はコミュニティ名として使われてる印象です。

「スプラソン」(Splathon)とは、スプラトゥーンsplatoon)とマラソンmarathon)を組み合わせた 株式会社Speee発祥の造語で、複数の参加チームが、マラソンのように、 数時間から数日間の与えられた時間を徹してSplatoonに没頭し、戦果を競い合うゲームイベントのことをいいます。

オフライン、もしくはオンラインで企業対抗戦をやったり、
企業関係なくチームを組んで一定期間でリーグ戦を行うなど色んなイベントがあったりします。
どんなイベントがあったりするのか気になる方は、
アドベントカレンダー1日目のkawakuboxさんの記事がよくわかると思うので見てみてください!

kawakubox.hatenablog.com

Splathonとの出会い

参加している人がWeb企業の人が多いためか、
参加してる人がフォロー内にいて、
突如Twitterのタイムラインに #splathon というハッシュタグが流れて来たのがきっかけでした。

羨ましがってる様子です。

おもむろにつぶやいてみたら中に人がいたら招待してもらうといいっぽく、
探してみたらいたのでどうにか招待してもらうことに成功しました。
コミュニティが気になる方は中の人の知り合いを探してみてください!w

参加したイベント

会社のメンバーでいろんなイベントに参加したりしました。

Splathon #7, #8

Splathonはオフラインである会場に集まって競い合うイベントですね。
イメージはSplatoon甲子園のような感じです。

www.youtube.com

Splathon eXtreme - Draft Tournament#1

eXtremeはウデマエXの人が集まって、 すっごい強い人(語彙力)がリーダーになってドラフトしたチームで競い合うイベントです。
ウデマエXになったばっかりでそんなに強くないから選ばれんやろーとか思ってたら選ばれて、
スマブラのムービーで驚愕してるイカちゃんみたいな顔をしながら怯えていました。

www.youtube.com

Splathon Ladder League #1 #Spladder

Ladder Leagueはオンラインのイベントで、
数ヶ月の期間で順位を決めるリーグでした。

全試合録画されててすごいw
最終的な順位は25チーム中7位でした。

#Splathon Ladder League #1 #Spladder - YouTube

Splathon Online League #3

Splathon Online Leagueはsolってよく訳されてるんですが、
(初め全然わからなくてsolってなんだ・・・ってなってました。
エンジョイよりのオンラインのイベントで、
参加したい人を運営の人がいい感じ(語彙力)に割り振って数ヶ月で、
順位を決めるようなイベントです。

チームで戦う楽しさ

コミュニティに入って同じ会社のメンバーでチーム作ったんですが、チームでやるのすごいよかったです。
まずは、チームでやるとみんな次勝つためにどうしたら良いかって考えるようになりました。
自分の立ち回りをもう少しこうしてほしいと言ってもらえたり、
対面が強い前線の味方を活かすために塗り拡げるの優先で動いたほうが良かったなー考えたりなど。

あとは、単に練習という名目でリーグマッチに行くのが単に楽しいです。
(今のチームのAjitoonでは練習として毎週木曜日にリーグマッチに行っています。

さらに、自分が使う武器だけではなく、
チームでの武器の組み合わせを試すというのもすごい楽しいです。
Ajitoonは初めメンバーの3/4のスペシャルがスーパーチャクチのチャクチーズで、
打開とは🙄みたいなチームでしたが、
今は色んな組み合わせが試せてすごい楽しいです。
(一人カーボンローラー固定だけど

Splathon #7, #8やLadder League #1のおかげでそんな楽しみ方を出来ました。
チームを作るきっかけをくれたSplathon、そのチームでプレイするきっかけを作り続けてくれるSplathonに感謝!!
コミュニティの楽しさとチームを組む楽しさが伝わったかどうか怪しいですが、
チームを組んで対抗戦するの本当に楽しいんで、
ぜひ皆さんもチーム組んだりしてみてください!

Splatoon2から始めてウデマエXまで行くときにやったりしたことの備忘録

この記事はSplatoon Advent Calendarの1日目として書かれています。
勢いで作ったら結構埋まっててとても嬉しいですw

adventar.org

なにを書こうか悩んだんですが、
Splatoon2が発売されてからウデマエX行くまでを振り返って、
自分がどうやってウデマエXまで行けたかを書いてみようかなと思います。
ウデマエXを目指す方のなにか参考になれば嬉しい限りです。

今のウデマエと使用武器

普段の使用武器はマニューバ系やシューター系の短距離から中距離のブキを持っています。
今現在のXパワーは2100 ~ 2300強くらいをさまよう、一部ではX底辺と言われたりするくらいのウデマエです。

初めS+0までのとき

初めS, S+0まで行ったときはずっとボールドマーカーを使っていました。
特にルールごとになにか考えることもなくプレイしていた気がしますw
唯一やってたことは率先してオブジェクトに絡むことをしていました。
エリアだったらエリアを塗る。
ヤグラだったらヤグラに乗る。
ホコならホコを持つ。
自分以外がやらなそうだったら自分がやるようにしてたら上がれたような気がします。

A+ ~ S+2あたりをウロウロしてるとき

S+0までは発売から3ヶ月ほどですんなり一度上がれたんですが、
その後立ち回りがわからなくなってきてウデマエが上がったり下がったりするようになりました。
正直ボールドマーカーに限界を感じるようになったのでいろんな武器を使うようにしました。

エリアでは

  • ボールドマーカー
  • スクリュースロッシャー
  • N-ZAP85
  • N-ZAP89
  • ダイナモローラーテスラ
  • バケットスロッシャーデコ
  • スパッタリーヒュー

ヤグラでは

  • ジェットスイーパー
  • ホットブラスター
  • もみじシューター
  • スパッタリーヒュー

ホコでは

  • ボールドマーカー
  • バケットスロッシャーデコ
  • スパッタリー
  • スパッタリーヒュー

アサリでは

  • スプラローラー
  • ホットブラスター
  • デュアルスイーパー
  • スパッタリーヒュー

などを使っていました。
かなり迷走気味ですね。
でも、これをやってよかったなと思うことがありました。
使っていた武器との対面の仕方や、その武器がどこに立ちたくなるかのポジションがわかるようになったことです。
どこに潜伏してそうかとか、どういう行動をあの武器はやられたら嫌かがわかると、
それらの武器に対して優位に対面できると思うので、
いろんな武器を持ってガチマッチに潜ったのはつらかったけど本当によかったなと思います。

S+の数字を上げていったとき

いろんな武器を持っていたんですが、
アメフラシが強いなーと思ってたのと、キル性能が高かったのもあり
スパッタリーヒューに使用武器が固定され始めて、
ようやくS+にも数字がついて落ち着くようになってきました。
その頃ちょうどウデマエXが出るという話が出てきたので、
S+10くらいまでなら頑張りたいなと思ってどうやったらよくなるかを考え始めた時期でした。
そこでやったのが上手い人の動画を見て学ぶということでした。
今考えると、もうちょっと早くやっても良かったんじゃないかなとかよぎりますねw

エリア

まずはエリアですが、
スパッタリーヒューを使っていこうと思ってたのでYoutubeで探したら、
あしんさんという配信者さんがガチエリアでの立ち回りを解説している動画や、
よくやってる試し打ちを動画にされていたのでそれを見てとりあえず丸パクリして徐々にアレンジしていくことにしました。

www.youtube.com

www.youtube.com

エリアの立ち回りの動画を見たとき、
打開とか抑えの考えを一切自分は持ってなかったので、本当に参考になりました。
打開時にちゃんと味方と合わせるというのが大事で、
それさえ出来たらあとはサクサク数字が上がって4種の中で一番はじめにXになりました。
途中でX導入されたので元々強かった人々がいなくなったってのもありそうですがw
あとは試し打ちをちゃんとやったらエイムがかなり良くなって対面も勝てるようになったので、
ちゃんとやると効果出てよかったです。
バスケでもシュート練習しないとシュートはいらなくなるし、
ピアノでも練習しないと指動かないしなーとか思ってやっぱ練習大事だなと思いました。

ヤグラ

ヤグラはS+0に行った後に、様々な武器を使ってAまで落ちてしまい、
その際、もみじシューターを使って這い上がってきたんですが、
塗り拡げてキル武器にキルを取らせて、自分がヤグラに乗って、止めるときは雨をはけば勝てると思ってたので、
特段探さず殺傷能力の上がったスパッタリーヒュー+アメフラシでどうにかしていましたw
デュアルスイーパーカスタムが出た後は更に塗りやすくなったので持ち替えて、
塗りながらヤグラに乗ってアメフラシで止めるという方針でXまで行きました。

ホコ

ホコは結構好きだったんですが、
苦戦してたので探したらメシアはボールドさまという配信者さんの動画を見つけて参考にしてました。

www.youtube.com

この時まで何も考えずホコを進めてたんですが、
ゴールから限りなくホコを遠ざけるとか、どこまではホコを進ませても大丈夫とかそういう考え方を気付かされた動画でした。
どこまでには必ず止める。
無駄に突っ込まないが大事ですね。
ホコ持ちが得意だったこともあり、この考え方のおかげでわりとすんなり上がることが出来ました。
ホコではスパッタリーヒューよりスパッタリーをよく使っていました。

アサリ

アサリはエリアのおかげで周りが見えるようになって特段なにもなく上がってしまったので割愛しますw
武器はデュアルスイーパーカスタムがでて使いやすかったのでずっとデュアルスイーパーカスタムを使っていました。

まとめ

所感としては個人的には

  • ある程度ルールなれるまではひたすら同じ武器を使うとよかった
  • ガチマッチはオブジェクトに絡むようにするとよかった
  • ガチマッチ慣れてきたらいろんな武器をいろんなルールで使ってみるとよかった
  • 立ち回りよくわからなくなってきたら動画を見て真似してみるとよかった

という感じでした!
もしSplatoonやっててなにか悩んだ人の参考にでもなればとても嬉しいです!

Scala製ValidationライブラリのAccordを触るぞい

最近Scalaのコードを書いててフレームワークに付随しないタイプのValidationのライブラリなんか無いかなー
と探していたらAccordというものを見つけたので触ってみた備忘録です。

Accord: A sane validation library for Scala

準備

検証用リポジトリはこちらで、使ったライブラリのversionは0.7.2でした。

github.com

installはbuild.sbtのlibDependenciesに追加する感じですね
書いたbuild.sbtはこんな感じでした

val commonSettings = Seq(
  version := "0.1-SNAPSHOT",
  scalaVersion := "2.12.5",
)

lazy val root = (project in file("."))
  .settings(commonSettings)
  .settings(
    name := "scala validation sample",
    libraryDependencies ++= serverDependencies
  )

val serverDependencies = Seq(
  "com.wix" %% "accord-core" % "0.7.2"

)

Accord概要

Accordのvalidationは特定の型に対するValidatorを定義して、
com.wix.accord.validate関数がそのValidatorを利用してvalidationを行い、
最終的にはResult traitを継承した(?)SuccessかFailureを返すみたいな形みたいですね。
validate関数はimplicit parameterでValidatorを渡せるようになっているので、
スコープ内にValidatorを定義しておけば引数から渡さなくても渡せますね。
明示的に渡したい場合は第二引数(?)に渡してあげれば渡せますね。

Ref: http://wix.github.io/accord/api.html#execution

使ってみた

実際に書いてみたコードはこんな感じでした。
APIサーバとかで使うならJSON形式で゚来たRequest Bodyをなんらかのcase classのオブジェクトにマッピングして、
そのオブジェクトをvalidationするみたいな形にするかなーとか思いながら書いてました。

package com.ru.waka

import com.wix.accord.{NullSafeValidator, RuleViolation, Validator, validate}
import com.wix.accord.ViolationBuilder.singleViolationToFailure
import com.wix.accord.dsl._

object Accord {
  implicit val hogeValidator: Validator[Hoge] = validator[Hoge] { h =>
    h.a is notEmpty
    h.b is in(1, 2)
  }

  implicit val FugaValidator: Validator[Fuga] = validator { f =>
    f.as has size > 0
  }

  implicit val PiyoValidator: Validator[Piyo] = validator { p =>
    p.as is notEmpty
    p.bs is myNotEmpty as "その値"
  }

  /**
    * @see http://wix.github.io/accord/dsl.html#combinators
    */
  def main(args: Array[String]): Unit = {
    println(validate(Hoge(a = "", b = 10)))
    // Failure(Set(a must not be empty, b with value "10" got 10, expected one of: [1, 2]))

    println(validate(Fuga(Nil)))
    // Failure(Set(as has size 0, expected more than 0))
    println(validate(Fuga(Seq(1, 2, 3))))
    // Success

    println(validate(Piyo(Nil, Nil)))
    // Failure(Set(as must not be empty, その値 List() は空じゃだめなんじゃ〜))
    println(validate(Piyo(Seq("a"), Seq(1))))
    // Success
  }

  case class Hoge(a: String, b: Int)

  case class Fuga(as: Seq[Int])

  case class Piyo(as: Seq[String], bs: Seq[Int])

  def myNotEmpty[T <: Seq[_]]: Validator[ T ] =
    new NullSafeValidator[ T ](
      test    = x => x.nonEmpty,
      failure = x => RuleViolation(x, s"$x は空じゃだめなんじゃ〜")
    )
}

感想

  • 😁 Validationの成功失敗、失敗はどの項目がどのルールで失敗したかが返るので基本的なValidationの機能は満たしてる
  • 😁 既存のルールが割と多いので時前で定義せずともわりと使える
  • 😁 困ったら自分でも作れるのでまあ便利
  • 😁 レポジトリのStar数もそれなりにあるし、開発も続いてるし息短くはなさそう
  • 😥 エラーメッセージを日本語にしたいと思ったんだけど、既存のものを変える方法が見つけられてなくて困ってる
    • h.a as "変な値" is notEmpty みたいに定義しても 変な値 must not be empty となるのでメッセージ全体は変えられなかった
    • このあたりはもう少し深掘りしながらissueとかも見ていこうかなと思った

PHPのプロファイリングが出来るblackfireでPOSTリクエストもプロファイルする

以前blackfireを試したんですが、そのときはブラウザでページを開いて、
chrome extentionでプロファイリングしてました。
なのでGET以外のリクエストがプロファイルやりづらく、
もうちょっといいやり方無いかなと思って探してみました。

以前の話
arata.hatenadiary.com

やることはblackfire agentをどこかにインストールして、そこからcurlコマンドで計測するという感じです。
今回自分はMacでやったのでbrewで入れました。
インストール手順はこのあたりです。
configのid, tokenとサーバに設定するid, tokenは異なるので注意が必要です。
blackfire.io

実際にやってみるとこんな感じでした。

$blackfire config
--------------------------------------------------------------
 Welcome to the Blackfire CLI utility configuration assistant
--------------------------------------------------------------

Your Blackfire Client ID and Token are available at:
https://blackfire.io/my/settings/credentials#client

Enter your Client ID: XXX
Enter your Client Token: YYY
------------------------------------------------------------------------------
The following configuration has been updated successfully
/path/to/.blackfire.ini

Thank you for using Blackfire
------------------------------------------------------------------------------

サーバの実装として使ったレポジトリはこちら

github.com

blackfireはcurlコマンドをwrapしてくれるみたいです。
curlでのリクエストを取れればいいんですけど、そんなときに便利なのがchromeのdev toolですね。
こんな感じでリクエストをコピーしてきます。

f:id:arata3da4:20180628173432p:plain

実際blackfireでcurlをwrapして叩いてみました。
GraphのURLはごまかしてます。

# 対象のserver起動
$make compose id=xxx token=yyy                                                                         [master]@(blackfire-with-slim)
docker-compose build
Building web
Step 1/10 : FROM php:7.1.10
 ---> c342f917459a
Step 2/10 : RUN apt-get update
 ---> Using cache
 ---> 8f08514cd607
Step 3/10 : RUN apt-get install -y wget
 ---> Using cache
 ---> 558f46f226ce
Step 4/10 : RUN wget -O - https://packagecloud.io/gpg.key | apt-key add -
 ---> Using cache
 ---> dc02abcab12c
Step 5/10 : RUN echo "deb http://packages.blackfire.io/debian any main" | tee /etc/apt/sources.list.d/blackfire.list
 ---> Using cache
 ---> 947920d5728f
Step 6/10 : RUN apt-get update
 ---> Using cache
 ---> 98aa1854625d
Step 7/10 : RUN apt-get install -y blackfire-agent
 ---> Using cache
 ---> d0725ad5b875
Step 8/10 : COPY ./blackfire.ini /etc/blackfire/agent
 ---> Using cache
 ---> 9a8965d48d25
Step 9/10 : RUN /etc/init.d/blackfire-agent restart
 ---> Using cache
 ---> f6360b5dc8d4
Step 10/10 : RUN apt-get install blackfire-php
 ---> Using cache
 ---> 40f8638aca26
Successfully built 40f8638aca26
Successfully tagged blackfire-with-slim_web:latest
docker-compose up
Starting blackfire-with-slim_web_1 ... done
Attaching to blackfire-with-slim_web_1
web_1  | make: Entering directory '/opt/app'
web_1  | /etc/init.d/blackfire-agent start
web_1  | Starting Blackfire Agent: blackfire-agent.
web_1  | /usr/local/bin/php -S 0.0.0.0:8080 -t web

# 別ターミナルで実行してみます
$ blackfire curl 'http://localhost:8080/hey' -H 'Origin: http://localhost:8080' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: ja-JP,ja;q=0.9,en-US;q=0.8,en;q=0.7' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' -H 'Content-Type: application/json' -H 'Accept: */*' -H 'Referer: http://localhost:8080/' -H 'Connection: keep-alive' --data-binary '{"name":"blackfire"}' --compressed
Profiling: [########################################] 10/10
Blackfire cURL completed
Graph URL https://blackfire.io/profiles/XXXXXXX/graph
No tests! Create some now https://blackfire.io/docs/cookbooks/tests
No recommendations

Wall Time     126ms
I/O Wait        n/a
CPU Time        n/a
Memory          1MB
Network         n/a     n/a     n/a
SQL             n/a     n/a

Graph URLで表示されているURLにアクセスするとこんなグラフが見れました。

f:id:arata3da4:20180628173422p:plain

POSTもラクラクプロファイルできて便利!

scalikejdbcを使ってMySQLにクエリを投げるだけのメモ

久しぶりにScalaを触ってMySQLにクエリを投げたいだけなんだけど、
それすらもぱっとは思い出せなかったので備忘録として書いとこうと思います。

scalikedjbc

github.com

検証用レポジトリはこちら。
make run で多分動きます。

github.com

build.sbt

とりあえずおもむろにbuild.sbtにscalikejdbcを追加します。
3系出てたんですね。
長いこと触って無くて知りませんでした。

scalaVersion := "2.12.5"

libraryDependencies ++= Seq(
    "org.scalikejdbc" %% "scalikejdbc" % "3.2.3",
    "mysql" % "mysql-connector-java" % "6.0.6"
)

書いたコードは結局このくらいでした。
localTxの実装を見たらなにかあったらThrowableが投げられるみたいだったのでcatchingで囲むことにしました。
Throwableが投げられたとしても特に何もしなかったらrollbackされなかったので、
投げられたら(Leftが返ってきたら)rollbackするような実装にしました。

package com.ru.waka

import java.time.LocalDateTime

import scalikejdbc.{ConnectionPool, DBSession, NamedDB, SQL}

import scala.util.control.Exception._

object Hello {
  private val connectionSymbol = 'testDB

  Class.forName("com.mysql.cj.jdbc.Driver")

  ConnectionPool.add(connectionSymbol, "jdbc:mysql://localhost/test?characterEncoding=UTF-8", "root", "")

  val repository = new HelloRepository(connectionSymbol)

  def main(args: Array[String]): Unit = {
    val time = LocalDateTime.now().toString
    NamedDB(connectionSymbol) localTx {implicit  session =>
      (
        for {
          _ <- createTable()
          _ <- repository.put(time)
          rs <- repository.fetch()
        } yield rs) match {
        case Right(rs) =>
          session.connection.commit()
          println(rs)
        case Left(th) =>
          session.connection.rollback()
          println(th)
      }
    }
  }

  def createTable()(implicit session: DBSession): Either[Throwable, Boolean] = catching(classOf[Throwable]) either {
    SQL(
      """
        |CREATE TABLE IF NOT EXISTS foo (hello varchar(100))
      """.stripMargin
    ).execute().apply()
  }
}

class HelloRepository(connectionName: Symbol) {
  def put(hello: String)(implicit session: DBSession): Either[Throwable, Int] =
    catching(classOf[Throwable]) either
      SQL(
        """
          |INSERT INTO foo (hello) VALUES (?);
        """.stripMargin
      ).bind(hello).executeUpdate().apply()

  def fetch() (implicit session: DBSession): Either[Throwable, Seq[Map[String, Any]]] =
    catching(classOf[Throwable]) either
      SQL(
        """
          |SELECT hello FROM foo;
        """.stripMargin
      ).map(_.toMap()).list().apply()
}

scalikejdbc.SQLの引数にクエリを渡して、
executeしてapplyすればクエリが走りました。
めでたしめでたし。
implicit parameterってどう使われるのかの理解が浅かったのでこのあたりも参考に読みました。

参考

いちいちsessionを渡さなくてもいい感じに渡してくれるので便利ですね。
(暗黙なのちょっと不安だけど)

PHPのjson_encodeで空オブジェクトを出力する

phpで空オブジェクトを出力したくなって、
おもむろに json_encode([]); とやったら空配列になってしまいました。

$php -a
Interactive shell

php > echo json_encode([]);
[]

さてどうしたものかと思ってふと浮かんだstdClassを突っ込んでみました。
そしたら空オブジェクトがおもむろに表示されました。

php > echo json_encode(new stdClass());
{}

もしかしてオプションある?と思って調べてみたらありました。

http://php.net/manual/ja/json.constants.php

php > echo json_encode([], JSON_FORCE_OBJECT);
{}

php最高!めでたしめでたし。