生涯未熟

生涯未熟

プログラミングをちょこちょこと。

ポーカーやり始めて2ヶ月でポーカーチェイスの最高ランク帯到達した

ひょんなことから世界のヨコサワさんの動画を観て、「そういやポーカーやりたい欲求あったな〜」って思い出したので3月からポーカーを開始。

※エンタメに富んでて面白い

ルールや基本的なことを覚えてからエムホールデムから始めたが、演出がくどいのと役成立確率の表示が気に食わなくて他にポーカーゲーム無いかな〜と探していたところ、ブラウザでもできるポーカーチェイスを発見し、3月末からガツガツとプレイしていきました。

で、今日ようやく最高ランク帯のダイヤモンドに到達しました。

どういうことを考えていたか?

まずは基本的なルールを覚えてから慣らし運転。そこからこちらのスターティングハンド表とハンドレンジの記事眺めたりとか

raq-hiphop.com

ヨコサワさんのポーカー解説チャンネルの動画見たりして、ポジションの重要性を学んだりしました。

基礎的なことは理解できたので、そこからはランク戦をバンバンこなしつつ「何故そのアクションをしたのか?」をキチンと言語化し、出来ない場合には何が分からなかったのか?を突き詰めるようにしました。(全部が全部言語化出来るわけじゃなく「それ運ゲーじゃん!」って思考を投げ棄てたりもしてます:-)

それ以外でなんとなく心がけるようにしてたのは以下です。

  • 人読みされないようにする
  • カモられてるのを早めに察する、バレないようにカモる
  • ルースプレイヤーが多い時はタイトに、タイトプレイヤーが多い時はルースに
  • 相手のVPIPをアクションの判断の一つにする
  • スタックの価値が希釈化する前に多く勝負をする
  • なんだかんだで最後は直感

人読みされないようにする

個人的にポーカーは人読みを煮詰めたゲームだなーと思っているので、人読みはかなり重要なファクターだと考えています。
大別するとルース・タイト・アグレ・パッシブの4つのスタイル組み合わせでプレイスタイルを分けれますが、場のプレイヤーをそれぞれのプレイスタイルで当てはめてアクションの参考にするのは重要です。

で、それを踏まえて自分が一番やられて困るのは大別したプレイスタイルから大きくハズレた行動をされることでした。
めちゃくちゃ固く打ってたプレイヤーがとんでもないブラフしてたり、逆にルースアグレな人に乗ったら相手のハンドがナッツだったりとか・・・
ボードゲームの基本だと思いますが、他人からされて嫌なことは戦術的に有効なので、自分も読まれてるな〜と思ったら全く違う行動で相手を驚かせてチップをぶん獲っていきましょう。

カモられてるのを早めに察する、バレないようにカモる

ポーカーはチップをカモったりカモられたりしてスタックを増減させていきますが、当たり前の話でカモられないようにしてカモりましょうというお話。
中でもカモられないようにするのが一番大事かなと。自分よりももっと経験値の高い方がその辺りの記事を色々と書かれていますが、その中でもリンプはしないってのは絶対に守っていました。あとは熱くなって相手のレイズに乗らないってのはありますかね、熱くなるとロクなことにならないので時間いっぱい使って深呼吸&思考の整理してからアクションしましょう。

逆にバレないようにカモるってのは自分がナッツハンドの時にそう見せないようにアクションすることです。よくあるのが時間を使って悩んでるフリするとかですかね。自分はリンプするとか追い込まれた状態で泣く泣くオールインしたって感じに見せるとかをやってました。
弱く見せるのはコミュニティカードの出目によってもやり方が変わるので、本当に難しいなとまだまだ研鑽中です・・・(こういうのを"アドバタイズ"と呼ぶのをさっき知りました :-)

ルースプレイヤーが多い時はタイトに、タイトプレイヤーが多い時はルースに

これは書いてある通りで、場に参加するプレイヤーのプレイスタイルの多さで戦略を変えています。
ルースプレイヤーが多いときに一番嫌なのが「弱い手で勝ちまくられること」と「たまたま入った強い手で勝たれること」です。この2つの封じ手としては単純に強いカードでのみ勝負するタイトに徹することです。弱い手には勿論勝てますし、強い手でも勝負にはなります。こういう時は稼ぎ場ですので、強い手でどんどんバリューベットしていきましょう。

次に、タイトプレイヤーが多い時はブラフベットで相手を落としやすいです。ルースプレイヤーが多い時と違って、単純にどんどんブラフをかましていきましょうというよりはヘッズアップの際にワンペアのみとかでも強気にベットしていきましょうくらいの感覚です。

相手のVPIPをアクションの判断の一つにする

相手に雰囲気の違うアクションをされた時に、よくVPIPをチェックしてアクションの判断材料にしています。
なんとなくですが、

  • 60%以上: ブラフの可能性が非常に高い
  • 50%以上: ブラフの可能性が高い
  • 40%以上: ブラフの可能性が少し高い
  • 35%以上: もしかしたらブラフ?くらいの可能性
  • 30%付近: ほぼほぼブラフをしない

といった感じで見ていました。
一つの参考程度なので必ずしも当てはまらないことがあるかもですが、何も情報がないよりかはマシかなと。

スタックの価値が希釈化する前に多く勝負をする

ランク戦では3分毎にブラインドレベルが上がります。つまり1BBの価値がゲームが進むにつれて希釈化されていくことになります。何もしなくてもスタックサイズは下がっていくので、序盤に多く勝負することを心がけていました。弱めのスーコネなど勝ち目が少なからずありそうなものでも、ベットしていくようにすることで割と勝率が上がっていきました。
めちゃくちゃ弱い手でもガンガンいけとは言いませんが、勝ち目がある場合は勇気を出していきましょう。

なんだかんだで最後は直感

結局はこれに行き着きます。どれだけ考えても意図が読めんことも多々あるので、際どい判断が求められる際は直感に委ねます。 第六感を磨きましょう:-)

ポーカーたのしい

ずっとプレイしながらポーカーたのしいなぁとモチベが上がったり下がったりしながらもずっと思ってました。麻雀よりも読みが求められるゲームで、個人的にはポーカーの方が向いてました。
ライブポーカーや実際にお金を賭けてやるとまた違った体験が得られそうなので、気が向いたらやってみたいですね。暫くは飽きなさそうなので、もっと腕を磨いていきます💪

エンジニアはもっと図を書こう

たまには軽い話題をば。

自分の中で信頼できるエンジニアかどうか?を見極めるひとつの指標で「込み入った議論の時に図を書くかどうか」というのがあります。
今までの経験上、図を書く派のエンジニアは割と良い感じの人が多かったので採用している指標なのですが、何故これが機能しているかというのを改めて考えてみた。

  • 他者の認知負荷を理解している
  • コンテクストを合わせることにコストをかけられる意識がある
  • 自分の思考の整理するツールとして図を扱えている

ザッと挙げましたが、この3つが機能している要因なのかなという気がしています.

他者の認知負荷を理解している

あれやこれやエンジニア間で技術議論している中で、「Aさんはこの領域に詳しいけどBさんはこの領域にはほどほど詳しいくらいだな」という個々のレベル差に応じて認知の負荷がかかります。ただでさえ議論していると結構なスピードで話が展開されていくので、認知負荷が更に加速してついていけなくなる人も多くなることでしょう。
そういった人を話のラインに合わせてあげるために一回議論を止め、図を書いて「こういうイメージで話合っていますかね?」とワーキングメモリのリセットがかけられる人はチームのために動けてるなと信頼がおけます。

コンテクストを合わせることにコストをかけられる意識がある

先述と似たような話なのですが、きちんとコンテクストを揃えることにコストを払える人は良いエンジニアと考えています。たまに自分の知識レベルでガーッと喋って満足しちゃう人もいますが、そういった人は正直あまり好みません。
ある主題に関して全員の認識を合わせることが、将来的なチームの協調行動の強化に繋がるのでそういったチームの未来という絵図を描いて行動できるエンジニアは良いですね。

自分の思考の整理するツールとして図を扱えている

これは完全に主観なのですが、パッと頭の中で考えてることを整理された状態で図に書き起こせる人は能力が高い印象があります。普段からちゃんと思考が論理的に頭の中で組み立てられているので、図に起こすのもスッと出来るんだろうなーという気はしています。

図 > 文章

文章だけよりも図があることで理解度の向上の助けになっているということが感覚値では持っているものの、なんらかのアカデミックな論拠が無いかなと調べていたらこんなの見つけました。

jiotower.org

“マルチメディアの原則”として知られている原則は、”人々は言葉だけからよりも言葉や絵からより深く学ぶ”(p.47)と述べている。

あとはJohn Swellerさんの認知負荷に関する文章とか読んでいけば、もしかしたら似たようなことが書いてあるかも。(未調査)

薄ぼんやり考えてることをたまにはつらつらと書いてみるのは良いですね。また何か良いトピックがあったら書いてみます。

GitHub Projects(beta)からバーンダウンチャートを生成する君を作った

所属しているチームで本格的にスクラムを回していくにあたって、タスク管理しているGitHub Projectsでバーンダウンチャートを生成出来ないか?という話になったのでサクッと作ってみた。

前提

目的としてGitHub Projects(beta)にあるスプリントバックログにプランニングポーカーでポイント付けをしたタスクを置き、これをデイリースクラムで理想的な進捗で終わらせているのか?を可視化したかった。
初めはGitHub Projectsにあるチャートで実現できないか?と試してみたが、表現力に幅がなくtodo, in progress, doneなどのステータス毎のタスク数による折れ線グラフなどを作ることは出来るが、ポイントを考慮したチャートは作成できなかった。

そのため、GitHub APIを叩いてバーンダウンチャートを生成するのが良さそうという話になり、調査&作成することとなった。

要件として、 - GitHub Projects上にあるタスクのポイントを使って、バーンダウンチャートを生成する - バーンダウンチャートの表示先は問わない - 日毎の進捗データをどこかに保存する - 定期実行だけでなく手動実行でも最新の進捗データを反映する - なるべく運用の手間はかけない(データ反映に複雑な手順を踏まない)

と定めて開発をスタートさせました。

実装

最終的に出来たのはこんな感じ。

f:id:syossan:20220327125014p:plain

これだけ見たらただのスプレッドシートにあるグラフですが、裏では色々やっているので解説していきます。

技術概要図

f:id:syossan:20220327130953p:plain

ザックリこんな感じで、先程の要件と照らし合わせるとこうなりました。

  • GitHub Projects上にあるタスクのポイントを使って、バーンダウンチャートを生成する
  • バーンダウンチャートの表示先は問わない
  • 日毎の進捗データをどこかに保存する
  • 定期実行だけでなく手動実行でも最新の進捗データを反映する
    • 定期実行はCloud Scheduler、手動実行はGASを通してCloud Functionsを実行
  • なるべく運用の手間はかけない(データ反映に複雑な手順を踏まない)
    • 普段はノーオペでグラフ見るだけ、直近でタスクを動かした時(in progress -> doneの移動など)は最新データ取るためボタンを2回押すだけ

なんとか良い形で要件をまとめることが出来ました(なるべく手を動かさないで)。
では一つずつ詳細に見ていきましょう。

GitHub API v4でGitHub Projectsからデータ取得

最初の取っ掛かりとしてCloud FunctionsからGitHub APIを通して、GitHub Projectsのタスク一覧を取得してきました。
GraphQLを用いたv4でデータを取ってこようと思い立ち、Goのgithubv4を使って取ってくることに。

github.com

サンプルコードとしてはこのように、1Queryで100件までのタスクしか取れてこないので、PageInfoにある情報を使って全てのタスクを取ってくるようにしてあります。

あと、説明が必要なのはGitHub ProjectのノードIDについてでしょうか。これはProjectごとに設定されているIDで取得方法は以下公式ドキュメントを参照。

docs.github.com

で、取得してきたタスクの情報を元に全タスクの総計ポイントと残タスクの総計ポイントを集計。集計したデータをBigQueryに入れるように実装しました。この辺りは特段説明のいる実装をしていないので解説は割愛。

Cloud SchedulerでCloud Functionsを定期実行

これも特に説明することはなし。一点、Cloud FunctionsをSchedulerからもGASからも実行させるために、HTTPトリガーに設定しておくこと。

GASでCloud Functionsを実行

こちらの記事を参考に実装。

qiita.com

記事通りに実装していけば詰まることもなく実装出来るはず。

スプレッドシートとBigQueryを連携

スプレッドシートはBigQueryと連携することが出来、データを引っ張ってくることでスプレッドシート上で利用することが出来ます。今回だと引っ張った日毎データをグラフに起こすところで使用しました。連携の仕方は公式ドキュメントを参照。

support.google.com

そして、連携したBigQueryではクエリを元にスプレッドシート上に展開してくれるので、今回では以下のようなクエリを実行しています。

このクエリでは単純に日毎データを引っ張ってくるのではなく、重複レコードがあった場合にtimestampが最新のレコードのみを利用するようにしてあります。こうしないと、BigQueryへinsertする際に「既に実行日のレコードがあった場合にupdate」とか「既に実行日のレコードがあった場合にdeleteしてからinsert」とかやらなきゃいけないので、面倒だなと思い重複レコードを許容しています。

そして、あとは日毎データを元にバーンダウンチャートを起こします。

f:id:syossan:20220327141656p:plain

抽出して貼り付けたデータは表示のフィルタリングが出来、それを使って「○日〜○日のデータのみ表示」とすれば柔軟にスプリントの変化に対応することが出来ます。

ちょっと詰まったところといえば、理想線をどうやって表現するか悩んだところです。一番簡単なのは総計ポイントの系列に対してトレンドラインを引く手法でした。トレンドラインを「総計ポイント -> 0」へ遷移する系列へ適用してあげればOKです。

また、BigQueryからデータを引っ張る際には連携したシートか、抽出して貼り付けたセル上で更新ボタンを押下しないと更新されないので、連携機能内にある定期更新を設定しておくとよいと思います。

スプレッドシートからGASの実行

最後にスプレッドシートからGASを実行します。これはボタンから実行するようにしてあり、やり方は以下を参照。

www.acrovision.jp

運用

これで普段はCloud SchedulerとBigQuery連携したデータとの定期更新、デイリースクラム時などで最新のデータを見たい時にはCloud Functionsを実行するボタンの押下とBigQuery連携したデータの手動更新を行えば使える簡単なシステムになりました。

まとめ

久々にGoを書いて実装してみましたが、やっぱりGoは書くの楽しいですね。
どうやって運用を簡単にするか?が結構右往左往悩みましたが、これが一番簡単だと思います。

GCPのIAP周りの隠れ仕様

dev, staging環境のアクセスを社内の人間のみに制限したいな〜って時にGCPのIAPを使っているのですが、そんなIAPの隠れ仕様を見つけたのでメモ✍

どんな仕様?

IAPはOAuth2 Client IDを必要とし、IAPを有効化することによってOAuth2 Client IDが増えていきます。 その様子は"APIとサービス"の"認証情報"を見ると分かるのですが、実はこのOAuth2 Client IDは36個までしか登録出来ません

stackoverflow.com

こちらのスタックオーバーフローを読むと色々と書いてありますが、公式なやり取りだと以下を読むといいかもしれません。

issuetracker.google.com

私もこの質問者と同じくIAPを新規作成する際に36個制限を越えてしまい、エラーとなってしまいました。
36個を越えて登録したい場合はGoogleに問い合わせてくれと回答している方もいますが、公式なやり取りを読むと「制限があり、上限を上げる予定はない」って書いてありますね🤔

正直、この辺りに関する情報が全く見つからず公式ドキュメントを漁っても見つかりませんでした・・・
現状では必要のないIDについては削除していくしかないようです、というお話でした。

cloud_sql_proxyをv1.15からバージョンアップさせたら大怪我した

cloud_sql_proxyをかませてCloud SQLへの接続を行っているのですが、v1.15からエイヤッでv1.28.1に上げたら事故ったので簡単にメモ。

何が起きた?

全てがこれに詰まってます。

github.com

で、このissueにも書いてあるような nc を使ったLivenessProveを行っていたのでまんまと撒いた環境全部落ちました・・・
cloud_sql_proxyがSIGTERMを受信して死んでたので、ムムッ!?と思いましたがまさかそこが原因とは🤔
「そんな変更加えるなら1.15->2.0にしろや!」って感じで怒ってらっしゃる方がいるように、マイナーバージョン上げるくらいなら大丈夫だろ〜と油断してたらやられました。

対策

health checkどうすっぺかな〜と探してたら、 -use_http_health_check オプションという便利なものを発見したのでこれを使うことに。

zenn.dev

これでなんとか通すことが出来ました。めでたしめでたし。