社会人学生を挫折した話

はじめに

この記事は【増枠】社会人学生 Advent Calendar 2020 - Adventarの21日目の記事となります。 はじめまして。2018年に通信制の大学(学士)に入学し、1年で退学してしまいましたのでその経験を踏まえこれから入学される方にはそのようなことにならないよう反面教師にしていただければと思います。

どこの大学に入学したか

自分の職業はソフトウェアエンジニアです。なので情報科学科のある帝京大学の通信課程に入学することにしました。 www.teikyo-u.ac.jp 通信課程ということもあり志望動機を書く程度で入学できますのでもし興味のある方は応募されてみてはいかがでしょうか?(突然の勧誘)

入学して良かったこと

結局1年しか在籍しなかったので一般教養科目が多かったです。なので普段そこまで興味関心がない学問に対して外部要因により学ぶことができる点です。 社会人になると学びたいことしか学ばなくなるため知識が偏ったり視野が狭くなりがちです。そういった偏りから強制的に(少しは)解放されるので、そういう意味で良かったなと感じてます。

学割を使えるのは良かったですね。さまざまな商品を学割で享受できましたが、なかでもJetBrainsのIDEが無料で使えるのは神だと思いました。 今は学生ではないので無料ではないですが、引き続き利用させていただいてます。 JetBrains: ソフトウェア開発者とチームに欠かせないツール

これは乱用すると良くないですが、会社の飲み会に誘われたときに「あ、今日課題の締め切りなんですよね~・・・。」的な言い訳で回避することも可能です。 いやな印象を与えるどころか「お、がんばってるな」と良い印象を与えつつ欠席できるので良いです。

あ、あと学費が安いです。年20万円程度(教科書代込み)なので、4年でストレート卒業した場合80万円と私立大学の1年未満の金額で卒業できてしまうコスパの塊です。

入学悪かったこと

確実にプライベートの時間が減少します。スケジュール的には平日は仕事が終わってひと段落したらデスクで期日までに課題が出されていたのでそれを完了するために、教材を調べたりプログラミングしたりしてました。休日も平日とやることは変わらないですが、平均半日はそれらの作業をしました。勉強量的にはそこまでではないですが、やはりたまには息抜きというものをしたいなと常に感じてました。こうした生活をしているとやはり人間関係にウエイトがおけなくなるため、徐々に友人が減るというか連絡を取り合うような人は少なくなったように感じます。

悪いことはそのくらいであまりないです。

今後社会人学生を予定している人が気を付けたほうが良いと感じたところ

環境の変化に気を付ける

大学に入学した年の夏ころに諸事情で東京から福岡に引っ越しするしました。 居住地とともに職場も変わったので、職場でのインプットが優先度的に高くなったり環境の変化でストレスも増え、これを機に徐々に課題をほったらかしにすることが増えました。

教訓としては大学卒業するまでは転職や居住地を大幅に変えるといったストレスがかかること、インプットが大学以外に増えることは避けるべきかなと思いました。 いや、これは私がストレス耐性ないことやインプットが効率的でなかったことが要因としてあるので、そんなもの関係ないという強い方はどんどん環境を変えつつ大学もチャレンジできると思います。

プライベートで趣味の時間を意識的に用意する

大学の悪かったことに書きましたが、プライベートが終了しますので、意識的に月に一回はチートデイを用意するなど工夫があってもよいかなと思いました。

忙殺されそうになったら留年や休学をする覚悟をあらかじめ持っておくこと

自分はストレートで4年で卒業しようとして失敗しました。もし転職したタイミングで「今年はインプットが増えそうだから一年休学しよう」とスイッチできたらまだ継続して大学に在学していたかもしれません。普通の大学生なら留年、休学の選択はやや難しい(親御さんから入学金などを払ってもらってるケースが多いため)が、社会人学生は基本的には自分でお金を投じてます。なので、柔軟にそのあたりの選択ができるかと思います。

まとめ

単位を落としてもよい、留年してもよい、ゆっくり自分のペースで勉強することができるのが社会人大学生の良いところです。 豊かな人生にするためにこの記事が少しでもお役にたてば幸いです。

さよならQiita、こんにちはhugo × github pages

対象

  • Qiitaから脱したい
  • Qiitaにはエモ記事が書けないので、そういった記事を独自のブログの方に書きたい

hugoとは

https://gohugo.io/

Hugo is one of the most popular open-source static site generators.
With its amazing speed and flexibility, Hugo makes building websites fun again.

Hugoは人気のあるオープンソースの静的サイトジェネレータの1つである。 半端ないスピードと柔軟性で、Hugoは再びウェブサイトの構築を楽しくするぜ。

と公式HPには書いてあります。

インストール

プラットフォームによってインストール方法が異なります。 Mac

$ brew install hugo

Win choco

$ choco install hugo -confirm

Win scoop

$ scoop install hugo

Linux snap

$ snap install hugo

などなど、、、。さまざまなPFに対応しています。 https://gohugo.io/getting-started/installing

さっそくブログを作ってみる

雛形作成

雛形を作成するために以下のコマンドを実行します。

$ hugo new site site-demo && cd site-demo

なにやら生成されたようです

$ tree
.
├── archetypes
│   └── default.md
├── config.toml
├── content
├── data
├── layouts
├── static
└── themes

6 directories, 2 files

できました。現時点だと空のディレクトリが掘られているだけのようです。

テーマの選定

なんと、サイトの雛形は完成しました。これからどんなデザインのページにするかを決定していきます。https://themes.gohugo.io/ に主要なテーマが列挙されています。今回は hugo-classicでdemoを進めたいと思います。

先ほど作成したthemesというディレクトリにテーマをgit submoduleの形として入れるとGOODです。

$ git init && git submodule add https://github.com/goodroot/hugo-classic.git themes/hugo-classic;

themesにはhugo-classic以外にも使いたいテーマをどんどん追加していっても良いでしょう。ただ、そのままだとどのテーマを使って良いかわからいので、config.tomlにhugo-classicを使いますということを宣言しておきましょう。

baseURL = "http://example.org/"
languageCode = "en-us"
title = "My New Hugo Site"
theme = "hugo-classic" #######################ここが追加した行

テーマの選定はなんと、以上です。

これで記事はまだないですが画面になにかしら表示されるようにはなります。早速画面を表示して見ます。

hugo server

localhost:1313にアクセス!!

hugo-demo-starting.png

何か表示されました。まぁ、記事も書いてませんし、テーマのカスタムも行なっておりませんので、及第点とさせてください。

記事をついに書く

雛形作成 -> テーマ選定まで終わりました。ので、あとは記事を書くだけです。markdownで記事を書いていきます。

$ hugo new post/starting-demo.md

content/post直下にコマンドで指定したファイルが生成されました。

$ tree
.
├── archetypes
│   └── default.md
├── config.toml
├── content
│   └── post
│       └── starting-demo.md ######################################ここ
├── data
├── layouts
├── resources
│   └── _gen
│       ├── assets
│       └── images
├── static
└── themes
    └── hugo-classic
        ├── LICENSE.md
        ├── README.md
        ├── archetypes
        │   └── default.md
        ├── exampleSite
        │   ├── config.toml
        │   ├── content
        │   │   ├── _index.md
        │   │   └── post
        │   │       ├── 2012-01-23-juicy-code.md
        │   │       ├── 2012-04-23-hacker-with-horn.md
        │   │       ├── 2015-07-23-command-line-awesomeness.md
        │   │       └── 2018-08-30-markdown-guide.md
        │   └── static
        │       └── css
        │           └── theme-override.css
        ├── images
        │   ├── partywizard.gif
        │   ├── screenshot.png
        │   └── tn.png
        ├── layouts
        │   ├── 404.html
        │   ├── _default
        │   │   ├── list.html
        │   │   ├── single.html
        │   │   └── terms.html
        │   └── partials
        │       ├── foot_custom.html
        │       ├── footer.html
        │       ├── head_custom.html
        │       └── header.html
        ├── static
        │   └── css
        │       ├── fonts.css
        │       └── style.css
        └── theme.toml

24 directories, 27 files

初期状態は以下のような状態です。下書き状態のようです。

---
title: "Starting Demo"
date: 生成した日時
draft: true
---

適当に内容を書いた後、draft: falseにして

$ hugo

で、記事の内容を反映させます。

$ tree
.
├── archetypes
│   └── default.md
├── config.toml
├── content
│   └── post
│       └── starting-demo.md
├── data
├── layouts
├── public
│   ├── 404.html
│   ├── categories
│   │   ├── index.html
│   │   └── index.xml
│   ├── css
│   │   ├── fonts.css
│   │   └── style.css
│   ├── index.html
│   ├── index.xml
│   ├── sitemap.xml
│   └── tags
│       ├── index.html
│       └── index.xml
├── resources
│   └── _gen
│       ├── assets
│       └── images
├── static
└── themes
    └── hugo-classic
        ├── LICENSE.md
        ├── README.md
        ├── archetypes
        │   └── default.md
        ├── exampleSite
        │   ├── config.toml
        │   ├── content
        │   │   ├── _index.md
        │   │   └── post
        │   │       ├── 2012-01-23-juicy-code.md
        │   │       ├── 2012-04-23-hacker-with-horn.md
        │   │       ├── 2015-07-23-command-line-awesomeness.md
        │   │       └── 2018-08-30-markdown-guide.md
        │   └── static
        │       └── css
        │           └── theme-override.css
        ├── images
        │   ├── partywizard.gif
        │   ├── screenshot.png
        │   └── tn.png
        ├── layouts
        │   ├── 404.html
        │   ├── _default
        │   │   ├── list.html
        │   │   ├── single.html
        │   │   └── terms.html
        │   └── partials
        │       ├── foot_custom.html
        │       ├── footer.html
        │       ├── head_custom.html
        │       └── header.html
        ├── static
        │   └── css
        │       ├── fonts.css
        │       └── style.css
        └── theme.toml

28 directories, 37 files

新たにpublicディレクトリが生成され、その中にいろいろとファイルができました。

after_post.png

トップページにも記事が出てきました。このリンクをクリックすると記事のページに遷移することができます。

github pagesで公開

いままでのプロセスで記事を簡単に書くことができます。あとはアクセスできるようにするだけです。VPSを借りて己でWEBサーバーを立てるのもひとつの手段ではあると思いますが、今回はもっと簡単なgithub pagesを利用して秒速で構築したいと思います。

公開ディレクトリを指定

今回はmasterブランチのdocsディレクトリ直下を公開ディレクトリとして指定します。その宣言をconfig.tomlに書きます。

baseURL = "https://katamotokosuke.github.io/site-demo/" ####### 追加: {user_name}.github.io/{repository_name}/ を指定する
languageCode = "en-us"
title = "My New Hugo Site"
theme = "hugo-classic"
publishDir = "docs"  ######################### 追加
canonifyurls = true  ######################## 追加(相対URLを絶対URLに変換できるようにします。)

記述を変更した後hugoコマンドを実行します。

$ tree
.
├── archetypes
│   └── default.md
├── config.toml
├── content
│   └── post
│       └── starting-demo.md
├── data
├── docs
│   ├── 404.html
│   ├── categories
│   │   ├── index.html
│   │   └── index.xml
│   ├── css
│   │   ├── fonts.css
│   │   └── style.css
│   ├── index.html
│   ├── index.xml
│   ├── post
│   │   ├── index.html
│   │   ├── index.xml
│   │   └── starting-demo
│   │       └── index.html
│   ├── sitemap.xml
│   └── tags
│       ├── index.html
│       └── index.xml
├── layouts
├── public
│   ├── 404.html
│   ├── categories
│   │   ├── index.html
│   │   └── index.xml
│   ├── css
│   │   ├── fonts.css
│   │   └── style.css
│   ├── index.html
│   ├── index.xml
│   ├── post
│   │   ├── index.html
│   │   ├── index.xml
│   │   └── starting-demo
│   │       └── index.html
│   ├── sitemap.xml
│   └── tags
│       ├── index.html
│       └── index.xml
├── resources
│   └── _gen
│       ├── assets
│       └── images
├── static
└── themes
    └── hugo-classic
        ├── LICENSE.md
        ├── README.md
        ├── archetypes
        │   └── default.md
        ├── exampleSite
        │   ├── config.toml
        │   ├── content
        │   │   ├── _index.md
        │   │   └── post
        │   │       ├── 2012-01-23-juicy-code.md
        │   │       ├── 2012-04-23-hacker-with-horn.md
        │   │       ├── 2015-07-23-command-line-awesomeness.md
        │   │       └── 2018-08-30-markdown-guide.md
        │   └── static
        │       └── css
        │           └── theme-override.css
        ├── images
        │   ├── partywizard.gif
        │   ├── screenshot.png
        │   └── tn.png
        ├── layouts
        │   ├── 404.html
        │   ├── _default
        │   │   ├── list.html
        │   │   ├── single.html
        │   │   └── terms.html
        │   └── partials
        │       ├── foot_custom.html
        │       ├── footer.html
        │       ├── head_custom.html
        │       └── header.html
        ├── static
        │   └── css
        │       ├── fonts.css
        │       └── style.css
        └── theme.toml

36 directories, 53 files

docsディレクトリが生成されました。宣言をしなければpublicディレクトリが生成されます。なので、すでに作られているpublicディレクトリはこれから不要となりますので、削除しても良いと思います。

github側の設定

  • 以上の成果物をgithub上にpushします。
  • リポジトリSetting (https://github.com/#{user_name}/#{repositoryn_name}/settings )のGitHub Pagesという設定の項目を見つける。(おそらく設定を指定なければNoneという値が選択されていると思います。)
  • master branch docs/ folder を選択
  • save

少し時間をおくと https://katamotokosuke.github.io/site-demo/ にアクセスできるようになりました。

まとめ

hugoとgithub pagesを用いて簡単にQiitaを脱することができました。これでエモ記事が書けるようになりました。 この記事では扱いませんでしたが、テーマをカスタマイズすることも可能です。そうすることでよりオリジナリティのあるWebページが構築できます。

参考

今回のデモで作成したgithubのソース: https://github.com/katamotokosuke/site-demo デモで作成したWebページ: https://katamotokosuke.github.io/site-demo/ Hugo: https://gohugo.io/

JSON Web Tokenを完全に理解する

はじめに

JSON Web Tokenを完全に理解する - Qiita この記事を書いた本人です。 はてなブログにもコピーを掲載します。

JSON Web Tokenとは

ざっくり言うと「2者間で安全にクレームを表現するための方式」です。RFC7519で技術仕様の標準化が行われています。JSON Web Token(以下JWT)は大きく分けて3つの属性に分割できます。ヘッダー、ペイロード、署名の3つです。ペイロードには実際に2者間(クライアント・サーバー間と考えると分かりやすいかもしれません)で受け渡しがしたいJSONが入り、ヘッダー、署名を使って改ざんの検証に用いられます。

まだぼんやりしていて分かりにくいですが、各属性がどのようなものなのかもう少し具体的に見ていくことにします。その後、実際にどのように使っていくかを見ると理解はしやすくなります。

ヘッダー属性

ヘッダーにはどのようなアルゴリズムを用いて署名を行っているかやトークンのタイプの2つで構成されています。

例:

{
  "alg": "RS256",
  "typ": "JWT"
}

この文字列をbase64urlエンコードしたものがJWTのヘッダーとなります。プログラムっぽく書くならばこんな感じです。

header = base64url_encode('{"alg":"RS256","typ":"JWT"}')

ヘッダーに関しては以上です。とても単純な仕様ですね。

ペイロード

実際に2者間で受け渡ししたい実体の入る属性です。要領はヘッダーと同じです。 例:

{
  "exp": "1550905975",
  "name": "k_k_hogetaro",
  "is_engineer": true
}

ヘッダーと同じくペイロードもbase64urlエンコードしたものとなります。 ヘッダーと違う点を挙げるとするといくつか予約語が定義されています。上の例であるとexpは仕様で定められた予約のkeyとなります。その他の予約語仕様書を参照してみてください。

署名

ペイロード属性はbase64urlエンコードされているだけですので、このままだとデコードすれば中身を確認でき、改変できてしまいます。それだと困る場合がいろいろあります。例えばCookieの値とか。そこで署名を行い、改変の有無を検証可能なものにします。 ハッシュアルゴリズムHS256のケースを例とします。他のアルゴリズムのケースも後述します。 HS256は共通の秘密鍵で署名、検証を行います。

プログラムのように書くと以下のようになります。

value = header + "." + payload + "." # base64urlエンコード済みのヘッダーとペイロードを「.」で繋いだ形のものを用います。
signature = hash256(value, secret_key);

これが署名のすべてです。

JWTの完成形

これでJWTのすべてが揃いました。ヘッダー、ペイロード、そして署名です。これらを「.」で繋いだものがJWTとなります。

JWT = "#{header}.#{payload}.#{signature}"

JWTの使われ方

↑まででJWTの具体的な形を見てきました。しかし、まだどのように使われるかが全くわかりません。なので、実際にどのような使われ方があるのか見ていきます。

アルゴリズムHS256の場合

署名のところでもHS256は扱いましたが、共通の鍵を用いて署名と検証を行います。なので、以下のようなケースが想定されます。あくまで一例です。

1, まず、どのサービスにでもあるようなログインを行います。利用可能ユーザーであればJWTを返却します hoge.png

2, ユーザーはJWTを用いてサービスのAPIにアクセスします。 hoge.png

となります。2の検証ですが、署名部は秘密鍵保有しているコンピューターにしか生成できません。そしてヘッダー、ペイロードが改変されていると、その署名と食い違いが発生するので、改変がわかる仕組みになっています。例えば次のJWTが発行されたとします。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDJ9.UqRu8fGnUAmn-Z_wwsgGVNTXANkIiDdEbj-BdZRafks
$ echo eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 | base64 -d
{"alg":"HS256","typ":"JWT"}
$ echo eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDJ9 | base64 -d
{"sub":"1234567890","name":"John Doe","iat":151623902}

もしペイロード

{"sub":"1234567890","name":"cat dog","iat":151623902}

に変えた場合、payloadが

c3ViOjEyMzQ1Njc4OTAgbmFtZTpjYXQgZG9nIGlhdDoxNTE2MjM5MDIK

に変わります。ですが署名はクライアント側では改変不可です。(秘密鍵が漏洩している場合はその限りではない) なので、サーバー側で、もう一度、ヘッダーとペイロードから署名を作成し、送られてきた署名と一致するかどうかで検証が可能となります。(実際にはそのような処理を書くのはやめて、ライブラリに処理を任せましょう。)

以上がHS256の場合の一例です。認証サーバーを独立させている場合はこの方法だといろいろ辛くなってきます。共通鍵を認証サーバーとその他Webサーバーで共有することは漏洩の危険性が高まります。よって認証サーバーを立てている場合、公開鍵暗号方式を用いるアルゴリズムを使ったJWTを生成するほうが賢明に思えます。

RS256の場合

RS256はHS256と異なり、公開鍵、秘密鍵のペアを使用します。

こちらも具体例を想定してみます。 hoge.png 1, 認証サーバーにログインに必要な情報を送る 2, 秘密鍵を用いてJWT生成 3, クライアントにJWTを返却 4, 3のJWTを用いてサービスのAPIを叩く 5, JWTの検証 6, サービスの処理 7, クライアントにレスポンス

と言った感じになります。

公開鍵暗号方式を用いたため、署名を生成する認証サーバー以外は公開鍵を保持するだけでよくなりました。 これでサーバーやサービスが増えても公開鍵を保有するだけでJWTの検証が可能になりました。

まとめ

今更感はありますが、JWTについてまとめました。もしかしたら、現在使っているサービスのCookieにJWTが付与されているケースもあるかもしれません。そういう時はbase64 -d でどんなものか確認してみると面白いかもしれません。

韓国(ソウル近傍)旅行記 トラブルメーカー編

はじめに

2020/1/24~26の2泊3日で韓国に旅行をしてきました。2020年初旅行を韓国にキメた理由としては - 美味しいもの食べたい - カジノ(主にホールデムポーカー)というものを体験したい - 旅費が安い - 3日程度の短期旅行が可能 - 福岡にも韓国のかたが多いので、私も行ったるわ!という雑なメンタリティ です。

当日までの準備

まず2019年の12月前半にJEJU airにて福岡 <-> 仁川 の航空券を購入しました。往復11000円くらいだったと思います。地元への帰る新幹線が往復12000円なのでなかなかの衝撃的価格です。 次にホテルです。2泊で5000円(1泊2500円)という、これまた圧倒的安い価格でかつ、booking.comで見た感じまぁまぁきれいなホテルだったので即決しました。 忠武路(チュンムロ)駅(地下鉄4号線で明洞駅の隣)が最寄り駅のairtview hotelというホテルです。(詳しくは後述) 合計約20000円で韓国に3日も滞在できるというわけです。素晴らしい。

準備はこれくらい。あとは丸腰で行くだけです。

Day1

移動

12:50(FUK出発) - 14:15(ICN到着)の飛行機に乗り、遅延等無く無事到着しました。 前日はワクワクしてしまって3時まで眠れませんでした。ははh・・。よって寝不足。

早速、ICN空港からソウルへ向かうべく電車に乗りました。勝手な妄想で30分くらいで着くだろうと思って予定を立ててましたが、 1時間くらいかかりました。予定は余裕もって計画的にどうぞ。

韓国の電車は日本で言うところのpasmosuicaのようなカードでゲートを通るカードがあるみたいです。 こんな感じ Imgur

LINEのブラウンですね。そうかLINEはNAVER社の子会社だったことを今思い出す。 ソウルで降車して乗り換え明洞に到着。

昼食とホテルにチェックイン

とりあえず明洞でウォンをゲットしてちょっと遅めの昼食に。明洞餃子というところに行きました。 写真撮るの忘れてしまいましたが、とにかくめっちゃ美味しかったですね。確実に今回の旅行で一番美味しかった。 まぁ有名なところではあるので、みなさんも明洞に行ったら食べてみてください。 https://www.konest.com/contents/gourmet_mise_detail.html?id=748

カルグクスと餃子を食べました。餃子が最高。小籠包かよ、って思うくらいジューシーでした。 メニューも4品しか無く、素人には優しい。餃子とカルグクスで19000W(= 1900円)。

お腹もいっぱいになったところで、ホテルにチェックイン。ここで異変に気が付きました。

「ん?部屋小さいし、トイレとシャワーが一緒なのは許せるとしても、シャワー浴びるところ無いくらい狭くない?」

教訓その1: ホテルはケチらない

ゴミ箱とか無いし。暖房もつかない!!(冷房と除湿のみ) でも小さい電気ストーブみたいなやつがあったからセーフ!(と思いたい)

てか、時間見たら17:00くらいになっていたと思う。あれ、時間経過速すぎではと思いました。はい。 本当はこの日、景福宮というところに行こうと思っていましたが、営業時間調べたら18:00までとなっていたので断念。

いざカジノへ

忠武路駅から地下鉄4号線に乗り、乙支路4街(ウルチロサガ)駅まで行き、そこで5号線に乗り換えクァンナル駅に向かいました。 韓国の人、結構黒いベンチコート着てるなぁーと勝手に思った。まぁ寒いもんね。 ぼーっとそんな感想を抱いているとクァンナル駅に到着しました。30~45分くらいだったような。 そこからはシャトルバスに乗ってウォーカーヒルに向かいました。 カジノの中は写真が撮れないので写真はないですが、キラキラしてる。それだけ。外はこんな感じ

Imgur

賭け事に興味がないのでサラッとしか見ていないですが以下のようなゲームがありました。 - スロット - サイコロ(の目を当てるやつ) - ルーレット - ブラックジャック - バカラ(?) - ホールデムポーカー - 名前のわからないゲームが色々

私がプレイしようと考えていたのはもちろんホールデムポーカー。わざわざ海外まで行ってカジノするなんてただのギャンブル好きじゃないか。と思う方もいると思うので弁解させてください。 ポーカーというのは意思決定と確率を考えるゲームです。

  • 目の前にいる相手がどのようなプレイをする人なのか
  • 目の前にいる相手はどのようなプレイを苦手として、得意としているのか
  • ゲームのある状況でこのチップの量ではどのようなプレイスタイルがベストなのか
  • べットの量はいくらが適切なのか
  • etc...

もっとありますが、ルールがわからないと何言ってるかわからないので割愛します。ですが、どれも共通点があります。 それは「未来の意思決定が楽になる方向に意思決定する」ということです。(トートロジー的なこといってすみません。) これは実は現実社会でも役に立つ考え方です(おそらく)。ポーカーも現実社会も運次第で結果が良くなったり、悪くなったりすることがあります。 ですが、その確率を捻じ曲げるようなことは不可能です。可能であるとしたら神様ぐらいでしょうか。 そのような残酷で冷徹な世界で確率的に正しい、または確率的にちょっと正しくなくてもタフな決断を迫られる状況を回避するというのは生きていく上でとても大切なスキルです。 それをテーブル上で再現しているというだけです。そして私はそういう考え方の訓練をしているだけです。 なのでお金がかかっていないほうが本当は望ましいのです。これは言ってみれば社会見学みたいなものです。

さてと、そんなことはさておき、1日目のテーブル状況は以下のような感じだったと思います。(ポーカーわからない人は読み飛ばしたほうが時間の節約になるかとw) - 基本的にタイトなテーブル - タイトパッシブが多め - 私を含めて少数人がルース寄り

まず私の基本スタイルはルースアグレですが、テーブル着席後タイトアグレ的な動きをしました。 ですが、数回プレイして「CBが相当効くぞ。。」と思ったのでハンドレンジを緩めて、ルースアグレ寄りのプレイスタイルに変更しました。 セカンドバレルも打てばブラフバレバレでも降りてくれるのでボーナスタイム突入。 それからずっとハンドレンジやプレイスタイルは相手によって微調整しながら3時間くらいプレイしたようなしてないような。 結果3万円でチップを購入し、それが6万円まで増えたところで集中力が切れたので終了。お疲れ様でした。 あとはプレイせずにサイコロとかで遊んでいるお客さんをぼーっと眺めてました。うーん、これの何が面白いのか私には理解できない。私が知らないストラテジーがあるのかもしれんなぁ。と思いつつポーカーテーブルで一緒だった中国の人とプレイについて談笑してた。

飲酒タイム

その後は明洞に戻リました。さて待ちに待った飲酒タイムです。あまり時間見てなかったけど、多分夜の12時くらいだったかな。

まずはこれ!!!! Imgur ビタミン炭酸マッチっていうジュースが日本にあるじゃないですか。あれ、微炭酸じゃないですか。アレよりもっと微炭酸にしたマッコリみたいなイメージです。 めっちゃ美味しくてがぶ飲みした。サムギョプサルとプルコギを胃に放り込みました。

そしてせっかくなので韓国のクラブにも行こうかな!と思い、カンナムにあるオクタゴンにタクりました。 値段は覚えていないけど、日本より安い印象。

いざオクタゴンに入ると耳がおかしくなりそうなくらいデカイ音が。 あ、今気がついたけど写真撮るの忘れた。(動画は撮ったけど)。 普段クラブに行くと踊り散らかして汗だくになって「あー、いい運動だったなぁ」とかそういう感じになって翌日筋肉痛になり後悔するのが常ですが、 さすがに旅行中なのでおとなしくしておきました。 ですが、すると横にいた韓国の人に手招きされてお立ち台みたいなところに案内されたので快諾して上がりました。 そこにはお酒がたくさんあったので「ちょっとくれ」って言ったらくれました。謎の酒をレッドブルで割ったやつ。 味はまったく意味不明で美味しくなかったけど、感謝しながらグイッと飲酒させていただきました。あのときの人、ありがと!

お立ち台、気に入ったのでずっといたろ。って思っていたら直後にその韓国の人の友達らしき人がきて、降ろされました。悲しみです。 これも確率です。ポーカーみたいなものなので、こういうことをされることだって当然あります。 また、ずっといようと決断したのが良くない決断だった可能性だってあります。凹みましたが仕方ありません。寛容に生きましょう。いちいち腹を立ててはいけません。

音楽は私の好きな感じではなかったので1時間くらいして帰ったような。1日目はこれくらい。楽しかった。おやすみなさい。

Day 2

9時に起きてまずは朝食。近くにあったカフェに行きました。

Imgur カフェラテがハート!私、おっさんだよ?フォークでくるくるしてやろうかと思いましたが、せっかくなのでこのままいただきました。美味しかったです。

で、そのカフェの壁に張ってあったのがこのポスター。何か良いことが書いてありそうだったので写真撮っておきました。

Imgur

以下、Google翻訳の結果です。

旅行をまろやかに 
moments of travel

昨年10月、パリとベルリンでの短い旅に行った。
旅行中に私を魅了させたのは2つの都市に住む人々であった。

自分に似合う福を着て、それぞれの位置で生きる人々、
主人に似た僧侶犬と一緒に散歩する人、
一人でいる時間を充実に過ごす様子。
平凡な日常が異邦人である私に素敵な瞬間に近づいてきた。

今この瞬間が、別の誰かにとって旅行の瞬間になるように願って。

実銃

さて、カフェで一息ついたところで明洞に行き、前からずっと興味があった実銃体験をしに行きました。

建物。 Imgur

撃たしてもらった銃の名前はワルサーしか思い出せない。。(あとで思い出したら追記する) ルパン三世に登場する峰不二子が使っている拳銃だった気がする。

肘をピンと張ってトリガーを引きました。撃った瞬間に火薬の匂いがして、「おおおお!!!」という感じ。 あれ、肘しっかり張ってないと肩怪我するよ。。。

日本からもタレントさんが訪れたみたい。草生えた。

インパルス板倉 Imgur

インパルス堤下 Imgur

はんにゃ金田 Imgur

日本では出来ない体験なので撃ててよかったです。

その帰りのエレベータで韓国人のおじさん(60歳くらい)に「君、何点スコアだった?」と声をかけられたので、 15分くらいその後も話していた。韓国語わからないし、英語と韓国語と混ざって聞こえるので何言っているかほぼ聞き取れなかった。 「japan」と「birthday」と「emperor(天皇?)」、「ABE(安倍総理のことだと思う)」という単語は聞き取れた。何か政治的なメッセージを伝えようとしてきてそうな雰囲気。 俺が政治に詳しいと思うな。全く知らん。

景福宮

そんな政治的なメッセージは明洞の実銃射撃場に置いて、前日断念した景福宮に行くことに。 明洞から忠武路駅まで歩き、地下鉄3号線に乗って景福宮に行きました。乗り継ぎなくて良かった。 やけに人が多いなと思ったらこの日は1/25日です。何の日でしょうか。はい、旧暦のお正月です。ソルラルとも言ったりします。 日本ではあまり意識しないため全く考慮の外にありました。無知なのでてっきり中国だけがソルラルをお祝いするものだと勝手に勘違いしてました。 あとで調べたのソルラルをお祝いするのは以下の国もあるようです。 - 北朝鮮 - 韓国 - 台湾 - マレーシア - ベトナム - シンガポール - インドネシア - モンゴル - ブルネイ

なるほど。知らなかった。他国の文化に触れて自分の無知を発見できるのはとても良いことじゃありませんか。

景福宮の中。撮るの忘れてたけど、この右側で太鼓を叩いていたり、行進みたいなのが行われていて、とても人がいた。 Imgur

一番奥にあるラスボスのような建物 Imgur

ラスボスの中 Imgur

韓服を着ている人がたくさんいました。韓国の人より東南アジア系のほうが韓服着てる人が多かったような。 この日はソルラルだったので無料で入れましたが、通常営業のときは有料みたいです。 https://www.konest.com/m/spot_menu.html?id=265

さてと、ちょっとだけ感じたことを真面目に書きます。

旧正月を祝うことや景福宮内での一連の催しごとは文化だろう。 文化にはそれを支える世界観がある。世界観とは文化がなぜ存在するのか、という理由というか存在意義みたいな考え方。 私は文化の一部を見た。この目で見たし感じた。けど世界観はわからない。旅行という短期間でその国や地域に根付いているものを理解は出来ない。そんなに簡単な話でもない。

これを日本の文化に置き換えるとどう世界観が見えるか考えてみよう。 日本だと初詣とかお盆など色々あると思う。これは文化である。あと、ご飯を食べるときに「いただきます」や「ごちそうさまでした」とか言うのも一応文化。 それらを支える世界観はある。一部は知っているし、知らない世界観もある。知らなくても生活の一部として取り入れている。 でも世界観は生活の一部として取り入れ、咀嚼して考えなければわからない。

そういうさまざまな世界観を理解したいと私は感じた。 多分現実世界で起こっている衝突とかは文化が衝突しているように見えて、実は本質的には世界観の衝突だったりする気がするのかも。いや、知らないけど。

南大門市場

さて、景福宮で一通り観光を終えて、市場にでも言って買い物やご飯でも食べようかな。 ソウル市内は似たような市場みたいなのがいくつかあるようですが、景福宮から比較的近くにあった南大門市場に行くことに。 タクシーに乗って行きました。余談ですが、このタクシーがとても臭かったです。

あ、市場の写真撮るの忘れてた。写真無いです。有名ブランドのパチモンを売っていたり、屋台みたいな感じで料理を振る舞っていたりしてました。 ええと、再度思い出していただきたいのですが、この日はソルラルです。めっちゃお店が閉まっていました。

またカジノへ

南大門市場が賑わっていなかったため、30分くらいブラブラして先日も行ったウォーカーヒルへと行きました。 昨日は電車で行きましたが、タクシーも安いということがわかったので、リッチにタクシーで行きました。

もちろんプレイするのはホールデムポーカーのみ。16時くらいだったかな。 まだテーブルが2,3卓くらいしか立っていなくて、waiting listが数人だったような。 とにかく次のテーブルが立つか、既存のテーブルが空くのを待っていました。

ここで小さなトラブルが。この日実は朝食から何もご飯を食べておりません。そう、低血糖になってしまいました。 バッグの中にチョコレートのようなお菓子を入れてなかったし、まだカジノで遊んでいないので、カジノ内の食事も食べれません。 カジノ周辺にもご飯が食べられる施設がありません。困った、困った。 何か食べないとと探し回ったらグレープジュースが無料で提供されているのを発見し、数杯いただきました。ひとまず生き延びました。

で、1時間くらいしたらテーブルが立ったので座り、アイスを注文。生き返りました。

さてと肝心のポーカーです。この日のテーブルは以下のような感じ - とてもタイトな人がいる - タイトアグレがいる - タイトパッシブが少ない - 私を含めて少数人がルース寄り

昨日ブラフがとても効き「あー、キャッシュゲームちょろいわ」と調子に乗っていました。 結果から言うと7万円ほど敗北しました。いろいろな箇所で意思決定が良くなかったし、運もそこまで良くなかった。 運はどうしようもないとして、意思決定が悪かったのは問題です。時間を見つけて一人反省会を開催しましょう。

飲酒タイム

カジノで大敗をしてしまったのでタクシーに乗る余裕などありません。電車でソウル駅まで帰りました。 で、ソウル駅近辺のちチキン屋で飲酒!!嫌なことは飲酒で忘れよう!

チキンで即飲酒奴!

Imgur

美味しかった。店員の韓国人は福岡によく来るとのことだったのでLINEを交換しておきました。 機会に恵まれれば会いましょう!

事件発生

飲酒も一段落したので後はホテルに帰って寝ようとしてソウルから明洞へタクりました。 無地到着して降車。ポケットからスマホを取り出してホテルの場所を確認しようとしたら。。

「ん、無い!」

多分ですが、スマホをタクシーの中に忘れてしまいました。まぁ壊れかけのスマホだし?良いか。

そんな訳ありません。あのスマホには大事な情報が山ほど蓄積されています。 - クレジットカードの情報 - 各SNSのログイン情報 - その他決済可能な情報 - 預金口座や証券口座の資産情報

などなど。企業がこれらの情報を漏洩したら企業の存続に関わる情報ばかりです。 そんな情報をタクシーに置いてきてしまったのです。 速攻で明洞の警察に紛失届を提出しました。酔いなんてどこかに行った。

とはいえホテルに戻ればサブのスマホがあるので生きていられました。もしサブのスマホがなければ。。。

教訓2: 旅行には情報端末は最低2つ、準備できれば3つ持っていこう

まずはメイン端末。2つ目はバッグの中に入れておくだけのスマホ。もし1つ目が壊れたり、なくしたりしたら使う用。 3つ目がホテルに置いておく用。バッグごとなくしたときに予備として持っておく。

別途、旅行中でスマホを紛失したときにとった行動は記事にします。

Day3

帰国!(特記事項なし。移動が主)

まとめ

巡った観光地が少なかったので、もう少し早起きしたり、行く時間を早めたり、帰る時間を遅くしたりすれば良かったかもです。 日韓関係は最近よろしくないようですが、市民レベルでは特にそういうのは感じなかったです。航空券が安いうちにみなさんも行っておきましょう。 あと、寒いのでちゃんと防寒対策はしましょう。福岡基準で防寒すると普通に寒いです。韓国の人がベンチコートを着ているのも納得。

総括するととても楽しかった。

おまけ

福岡空港に到着してターミナルから駅までシャトルバスが出ているのですが、その中でもサブのスマホを紛失しました。 はぁ。。。。。。。。。。。。。。。。。。社用スマホだったのでさすがに!です。速攻で近くのスタッフに手当たりしだい声をかけ、 なんとか発見できました。本当に社会的に死ぬところだった。以上。

mysql 5.6~でのalter tableでやらかさない

はじめに

mysql5.6の話をします。それ以上のバージョンでも通じる話ではあると思います。 どんなシステムでも本番稼働中にindexを貼りたい、テーブル定義(カラム名、型、並び順...etc)の変更をしたいことは往々してあると思います。そんな時はalter tableコマンドを叩きたい気分になります。安直にコマンドをぶっ叩くとやらかしてしまう可能性があります。今後もやらかさないためにまとめておきます。

環境

mysql> status;
--------------
mysql  Ver 14.14 Distrib 5.6.42, for Linux (x86_64) using  EditLine wrapper

Connection id:      3
Current database:   
Current user:       root@localhost
SSL:            Not in use
Current pager:      stdout
Using outfile:      ''
Using delimiter:    ;
Server version:     5.6.42 MySQL Community Server (GPL)
Protocol version:   10
Connection:     Localhost via UNIX socket
Server characterset:    latin1
Db     characterset:    latin1
Client characterset:    latin1
Conn.  characterset:    latin1
UNIX socket:        /var/run/mysqld/mysqld.sock
Uptime:         2 min 34 sec

Threads: 2  Questions: 10  Slow queries: 0  Opens: 67  Flush tables: 1  Open tables: 60  Queries per second avg: 0.064
--------------

5.6で追加されたやらかさない技術

結論から言うとonline DDLと呼ばれる機能です。これは2つの要素から成り立っています。 1. 高速index作成(こちらは5.5から存在する) 2. alter table実行中にDML処理が可能にする拡張

高速index作成とは

すでに書きましたが5.5からある機能ではあります。 そもそもalter tableは結構忙しい処理です。ざっくり言うと 1. alter tableの内容を元に新テーブル定義されたテンポラリテーブルを作成 2. 既存テーブルからテンポラリテーブルにデータを登録 3. 旧テーブルを削除 4. テンポラリテーブルの名前を旧テーブル名にrename

このような手順を踏んでいます。

セカンダリインデックスのadd dropに関してはテーブルコピーのようなことをせずに速度に最適化が行われています。

DMLの実行が可能とは

ざっくり言うと以前まではread(SELECT)は可能ですが、write(INSERT, UPDATE, DELETE)をブロックされていたのがどちらもブロックされなくなったということです。 とはいえすべてができるようになったわけではありません。詳しくはドキュメントを参照してみてください。 https://dev.mysql.com/doc/refman/5.6/ja/innodb-create-index-overview.html

というわけで

online DDLがあるとメンテモードにせずにDMLをぶっ叩くことができるようになるということです。しかしwriteブロックする場合もあるのでそちらは依然として注意が必要です。

やらかす事象

とはいえonline DDLがあったとしてもやらかす時はやらかします。例えば実行時間の長いtransaction中のプロセスがある平気でやらかします。なぜかと言うとmysqlにはメタデータのロックという機構があり、それによりalter tableがロックされて解放するまで待ちの状態になり、その後のDMLコマンドも待ち状態になって事故ってしまうケースがあります。

メタデータのロック??

主な目的としてはデータの一貫性を確保するためです。 明示、暗黙的問わず開始されたトランザクションメタデータロックを保持し、利用されてるテーブルに対してDDLを実行を禁止します。 またこれはトランザクション終了まで保持されます。  詳しくは: https://dev.mysql.com/doc/refman/5.6/ja/metadata-locking.html

試す

実際にメタデータロックを意図的に起こしてみたいと思います。 とりあえずmysqlが動く環境を作りましょう。

$ docker pull mysql:5.6.42
$ docker run --name mysql-tx -e MYSQL_ROOT_PASSWORD=secret -d mysql:5.6.42

めちゃくちゃ適当ですが、できました。

$ docker exec -it mysql-tx bash

からの

実験なのでrootでmysqlに繋ぎにいきます。普段はそんなことしないようにしてください。

$ mysql -u root -p

testデータベースを作ります。

mysql> create database test;
mysql> use test;

テーブルを作ります。

mysql> create table users (id int, name text, age int);

適当にデータを登録しておきます。

mysql> insert into users (id, name, age) values (1, "a", 22), (2, "b", 23), (3, "c", 24), (4, "d", 25);

お待たせしました。ここからがメタロックの実験です。

まず遅いselectを実行してみましょう。

mysql> select sleep(20), id  from users;

このクエリが実行中はメタデータロックを保持していますので、別セクションからDDLを叩くとロックされているはずです。実際にやっています。 別の端末からmysql-txにログインして同様にmysqlに接続して次のコマンドを叩いてみます。

mysql> alter table users add index idx_id(id);

やはり全然返ってきません(何も返ってこないので見せるものがありません。)。予定通りDDLがブロックされているみたいです。 もう一つ別のセクションから以下のコマンドを叩いて確かめてみましょう。

mysql> show processlist;
mysql> show processlist;
+----+------+-----------+------+---------+------+---------------------------------+-----------------------------------------+
| Id | User | Host      | db   | Command | Time | State                           | Info                                    |
+----+------+-----------+------+---------+------+---------------------------------+-----------------------------------------+
|  4 | root | localhost | test | Query   |   28 | Waiting for table metadata lock | alter table users add index idx_idb(id) |
|  5 | root | localhost | test | Query   |   38 | User sleep                      | select sleep(20), id  from users        |
|  6 | root | localhost | NULL | Query   |    0 | init                            | show processlist                        |
+----+------+-----------+------+---------+------+---------------------------------+-----------------------------------------+
3 rows in set (0.00 sec)

ついにきました。Waiting for table metadata lock。 これが本番で発生するとすみません状態になります。

まとめ

mysql5.6からonline DDLによってindexをサービスインさせたまま貼ることができて便利です。 とはいえindexを貼る時も長いトランザクションがあったりする時は気をつけましょう。 また、今回やらかす事象にメタデータロックだけを取り上げましたが、もちろん他にもたくさんあると思います。実際にこんなのにハマりましたみたいなのがあればぜひ教えていただきたいです。

Railsのautoload_pathsでの定数探索

環境

autoload_pathsの概要

例:

class Hoge < SuperHoge; end

のようにモデルを定義したとします。Hogeは未定義の場合定数作成され、定義済みであればオープンクラスされるためautoload_pathsの出番なしですが、SuperHogeのほうが未定義だった場合autoload_pathsを元に定数を探索しに行きます。 autoload_pathsがあるので

require 'super_hoge'

といちいち書かなくてもよくなっています。

puts ActiveSupport::Dependencies.autoload_paths
RAILS_ROOT/app/assets
RAILS_ROOT/app/channels
RAILS_ROOT/app/controllers
RAILS_ROOT/app/controllers/concerns
RAILS_ROOT/app/helpers
RAILS_ROOT/app/jobs
RAILS_ROOT/app/mailers
RAILS_ROOT/app/models
RAILS_ROOT/app/models/concerns
...etc

みたいにActiveSupport::Dependencies.autoload_pathsの結果が探索の対象になります。 詳しくはwebで(https://railsguides.jp/autoloading_and_reloading_constants.html)

実際のソースコードを見てみる

rubyにはさまざまなフックメソッドが提供されていてその一つに定数が見つからないときにModule#const_missingというものがあります。これをActiveSupport::Dependencies::ModuleConstMissingではオーバーライドしています。このmoduleはrubyModuleincludeされているのでRailsを使う際に定数が見つからないとこのメソッドのconst_missingが呼ばれることになります。なのでこれを見ていくことにします。

https://github.com/rails/rails/blob/5-2-0/activesupport/lib/active_support/dependencies.rb#L191

def const_missing(const_name)
  from_mod = anonymous? ? guess_for_anonymous(const_name) : self
  Dependencies.load_missing_constant(from_mod, const_name)
end

from_modはどの名前空間に属するかを特定しています。そして定数探索の旅が始まる!

ActiveSupport::Dependencies#load_missing_constant

https://github.com/rails/rails/blob/master/activesupport/lib/active_support/dependencies.rb#L489

2018/05/23時点のソースをのせる。

    def load_missing_constant(from_mod, const_name)
      unless qualified_const_defined?(from_mod.name) && Inflector.constantize(from_mod.name).equal?(from_mod)
        raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
      end

      qualified_name = qualified_name_for from_mod, const_name
      path_suffix = qualified_name.underscore

      file_path = search_for_file(path_suffix)

      if file_path
        expanded = File.expand_path(file_path)
        expanded.sub!(/\.rb\z/, "".freeze)

        if loading.include?(expanded)
          raise "Circular dependency detected while autoloading constant #{qualified_name}"
        else
          require_or_load(expanded, qualified_name)
          raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{file_path} to define it" unless from_mod.const_defined?(const_name, false)
          return from_mod.const_get(const_name)
        end
      elsif mod = autoload_module!(from_mod, const_name, qualified_name, path_suffix)
        return mod
      elsif (parent = from_mod.parent) && parent != from_mod &&
            ! from_mod.parents.any? { |p| p.const_defined?(const_name, false) }
        begin
          return parent.const_missing(const_name)
        rescue NameError => e
          raise unless e.missing_name? qualified_name_for(parent, const_name)
        end
      end

上から適当に見ていくとqualified_name_forHoge::Fuga::Barのような文字列取得して、underscorehoge/fuga/barのような文字列を生成しています。それをsearch_for_file(あとでみる)でファイルを探しています。 その絶対パスを取得して、require_or_loadを呼びだして定数をrequireかロードし、その後そのmoduleがreturnされます。

もしsearch_for_fileの返り値がなければautoload_moduleを呼び出す。 autoload_moduleは --> 予想されるパスサフィックスに一致するディレクトリを検索して、提供されたモジュール名を自動ロードしようとします。 見つかった場合、モジュールは作成され、+ const_name +という名前の定数に+ from_mod +の定数に代入されます。 ディレクトリが再ロード可能なベースパスからロードされていれば、アンロードされる定数セットに追加されます。

らしいです。何かしらが代入されて場合、そのmoduleを返します。あとは例外処理なので省略。

search_for_fileを読む

https://github.com/rails/rails/blob/5-2-0/activesupport/lib/active_support/dependencies.rb#L414

def search_for_file(path_suffix)
  path_suffix = path_suffix.sub(/(\.rb)?$/, ".rb".freeze)
  autoload_paths.each do |root|
    path = File.join(root, path_suffix)
    return path if File.file? path
  end
  nil
end

やっと出現しましたautoload_paths。 実装は単純で、autoload_pathsをぶん回してpath_suffix(探索対象のモジュールの名前空間に対応するファイルパス)と各要素を結合します。それがファイルならばその文字列を返します。

まとめ

支離滅裂に書いてきたが、ActiveSupport::Dependencies::ModuleConstMissing#const_missingでは未定義の定数をautoload_pathsをもとに読み込んでいます。