読者です 読者をやめる 読者になる 読者になる

phpdocumenterでpackages下にdefault.html, Default.htmlが出力される問題

phpdocumenterでソースコードからドキュメント自動生成をしたときに起きた問題。

https://github.com/phpDocumentor/phpDocumentor2

# ドキュメント生成コマンド
$ phpdoc run -d <SOURCE_DIRECTORY> -t <TARGET_DIRECTORY> --template=responsive-twig

すると、TARGET_DIRECTORY/packages配下にdefault.html と Default.htmlが出力される。

$ ls TARGET_DIRECTORY/packages
default.html  Default.html

これをwindows環境で展開すると問題となる。 windows環境だと、どうやら大文字・小文字をファイル名としては区別しないようだ。なんてポンコツなんだ…

helpを読む。

$ phpdoc run -h
...
  --defaultpackagename[=DEFAULTPACKAGENAME] Name to use for the default package. [default: "Default"]
...

–defaultpackagename=XX オプションを指定するとDefault.htmlのファイル名を変更できる様子。

$ phpdoc run -d <SOURCE_DIRECTORY> -t <TARGET_DIRECTORY> --template=responsive-twig --defaultpackagename=foo
$ ls TARGET_DIRECTORY/packages
default.html  foo.html

うむ。

MySQLでタグ機能を実装しAND検索する

商品(item)にN個のタグを設定し、tag名(tag id)で商品をAND検索できる機能を実装したい。

table design

以下の3つのテーブルを用意する

  • item: 商品テーブル。タグの設定対象
  • item_to_tag: itemとtagの中間テーブル
  • tag: タグテーブル

f:id:tic40:20170225133709p:plain

item table

mysql> select * from item;
+----+-------+
| id | name  |
+----+-------+
|  1 | item1 |
|  2 | item2 |
|  3 | item3 |
+----+-------+

item_to_tag table(中間テーブル)

mysql> select * from item_to_tag;
+----+---------+--------+
| id | item_id | tag_id |
+----+---------+--------+
|  1 |       1 |      1 |
|  2 |       1 |      2 |
|  3 |       1 |      3 |
|  4 |       1 |      4 |
|  5 |       2 |      4 |
|  6 |       2 |      5 |
|  7 |       3 |      1 |
|  8 |       3 |      6 |
+----+---------+--------+

tag table

mysql> select * from tag;
+----+------+
| id | name |
+----+------+
|  1 | tag1 |
|  2 | tag2 |
|  3 | tag3 |
|  4 | tag4 |
|  5 | tag5 |
|  6 | tag6 |
+----+------+

AND検索

‘tag4'かつ'tag5'が紐付けられているitemを検索する(item.nameはitem.idに置き換えてもよい)

mysql> SELECT item.*
    -> FROM item
    -> JOIN item_to_tag AS itt ON item.id = itt.item_id
    -> JOIN tag ON itt.tag_id = tag.id
    -> WHERE tag.name IN ('tag4','tag5')
    -> GROUP BY item.id
    -> HAVING COUNT(item.id) = 2;
+----+-------+
| id | name  |
+----+-------+
|  2 | item2 |
+----+-------+

AND検索(group_concat と FIND_IN_SET を使う)

mysql> SELECT * FROM item
    -> WHERE EXISTS (
    -> SELECT group_concat(tag_tmp.name) AS tags
    -> FROM tag AS tag_tmp
    -> JOIN item_to_tag AS itt ON tag_tmp.id = itt.tag_id
    -> WHERE item.id = itt.item_id
    -> HAVING FIND_IN_SET('tag4', tags) AND FIND_IN_SET('tag5', tags)
    -> );
+----+-------+
| id | name  |
+----+-------+
|  2 | item2 |
+----+-------+

まとめ

  • 案外素直にAND検索のsqlが書けなかった。もっと良い方法があるかもしれない。

SQLアンチパターン

SQLアンチパターン

実践ハイパフォーマンスMySQL 第3版

実践ハイパフォーマンスMySQL 第3版

第217回TOEIC結果

結果

score: 765

  • listening: 425
  • reading: 320

過去最高点を10点だけ更新した。(755 -> 765) 時間配分は今までで一番良くできた。それだけに800取れてるといいなーと思ったけど現実は非情だった。とはいえ最高点取れたのは多少励みになるかな。 内訳をみると、やはりReadingが弱すぎる。次回まではReading(長文問題)のトレーニングをしてみるかな。 公式問題集でひたすら長文問題を精読して読解力、スピードアップ向上を図ってみようと思う。

次回は3/12。

コスモプラネタリウム渋谷に行く

桜ヶ丘町の文化総合センターという施設の12Fにプラネタリウムがある。

f:id:tic40:20170219130934j:plain

コスモプラネタリウム渋谷|渋谷区文化総合センター大和田

以前桜ヶ丘町で働いていたことがあって、何度か前を通ったことがあったはずなんだけどその時は存在に全く気づかなかった。

中目黒-代官山でちょっとした用事をしているときに、そういう施設があるということを思い出した。 代官山からなら歩いて行ける。 プラネタリウムは今まで体験したことがないし、星にも詳しくはない。 ふと今日行かなかったら一生行くことないだろうな、と思ったのでこの機会に行ってみた。

文化総合センターの入り口には全くプラネタリウムの案内は見つからなかった。どうりでこの辺来たことがあったも気づかないわけだ。

上映はだいたい2時間間隔、料金は600円で全席自由席。 10分前には入場できる。自由席ということもあってか、入場開始10分前ぐらいには入り口に行列ができた。

自分が行ったときは「ダークマターを探せ」という作品が上映されていたので、それを観ることにした。

http://www.shibu-cul.jp/news.php?eno=852&sno=2&page=1&frm=2

席はリクライニングでかなり後ろまで倒れて、調整はできない。つまりシートを倒したら、一番奥まで倒れる。

上映時間は50分ぐらい。ナレーターがいて、その場で解説をしてくれる。毎回同じ上映なら録音でもいいのでは?と思ったけど、それなりにナレーターをつける理由はあった。*1

  1. ダークマターを探せ」の上映30分程度
  2. 今夜見える星座の解説 20分ぐらい

結構な数の鑑賞者が開始直後から寝ていた気がする。ナレーターのお姉さんの声もなんだか眠気を誘う声だ。自分もかなりうとうとしながら上映を観ていた。でもまあそういうものなのかな。週末の午後にプラネタリウムに来たら意識を保つことなんて無理だし、そもそもうとうとしながら観るぐらいでちょうどいいものなのかも。

ダークマターを探せ、は完全に映像作品を観ているだけという感じだったので、プラネタリウムで観る必要ないと思った。 その後の今夜見える星座の解説は面白かった、というかこういうのを期待していた。ナレーターが今夜見える星座について語ってくれる。星座の多くがギリシャ神話と関係していることすら自分は知らなかった。*2 季節やナレーターによってこの解説は違うものになるし、何度きても楽しめるコンテンツという感じだった。

*1:今夜見える星座の解説コーナーでナレーターが今日の星座を解説してくれる

*2:オリオン座のオリオンはギリシャ神話に登場する狩人が由来、など

親テーブルに紐づく最新のログ1件をJOINしたい

以下のような2つのテーブル(user, user_log)があり、userテーブルに紐づく最新のログ1件をjoinして取得したい。

例えば、ユーザに紐づく直近のアクションログだけをjoinしたい場合に使えるかも。

以下、サンプル。

user table

mysql> select * from user;
+----+-------+---------------------+---------------------+
| id | name  | created_at          | updated_at          |
+----+-------+---------------------+---------------------+
|  1 | user1 | 2017-02-13 12:48:07 | 2017-02-13 12:48:07 |
|  2 | user2 | 2017-02-13 12:48:13 | 2017-02-13 12:48:13 |
|  3 | user3 | 2017-02-13 12:48:16 | 2017-02-13 12:48:16 |
+----+-------+---------------------+---------------------+

user_log table

mysql> select * from user_log;
+----+---------+--------+---------------------+
| id | user_id | action | created_at          |
+----+---------+--------+---------------------+
|  1 |       1 |      1 | 2017-02-13 12:48:59 |
|  2 |       1 |      2 | 2017-02-13 12:49:09 |
|  3 |       1 |      3 | 2017-02-13 12:49:13 |
|  5 |       2 |      1 | 2017-02-13 13:27:11 |
|  6 |       2 |      2 | 2017-02-13 13:27:17 |
|  7 |       3 |      1 | 2017-02-13 13:27:22 |
+----+---------+--------+---------------------+

SQL

mysql> SELECT user.id, user.name, log.action, log.created_at AS log_datetime
    -> FROM user
    -> JOIN user_log AS log ON log.id =
    -> (
    -> SELECT max(log_tmp.id) AS id
    -> FROM user_log AS log_tmp
    -> WHERE log_tmp.user_id = user.id
    -> ) AND log.user_id = user.id;
+----+-------+--------+---------------------+
| id | name  | action | log_datetime        |
+----+-------+--------+---------------------+
|  1 | user1 |      3 | 2017-02-13 12:49:13 |
|  2 | user2 |      2 | 2017-02-13 13:27:17 |
|  3 | user3 |      1 | 2017-02-13 13:27:22 |
+----+-------+--------+---------------------+

これでそれぞれのユーザー情報に、user_logの最新のログ1件(action, log_datetime)がjoinできる。

数字の森を観に行く。国立新美術館 10th anniversary

数字の森*1という展示が観たくて、平日の仕事の昼休みに観に行ってきた。*2

さすがに平日月曜の昼は空いている様子。

入り口の木が草間彌生っぽくなってる。何かそれ関連の展示でもあるんだろうか。 f:id:tic40:20170130142100j:plain

数字の森は10th anniversary展示の1つ。 国立新美術館はちょうど10年前、2007年1月に開館した。

f:id:tic40:20170130140210j:plain

大量の数。数字の集合体。 f:id:tic40:20170130140852j:plain

f:id:tic40:20170130141721j:plain

バイナリデータか何か?

f:id:tic40:20170130141518j:plain

2Fのカフェ サロン・ド・テ ロンド。毎回気になってはいるが、どうも一人で行く気にはなれないので未だに入ったことはない。

f:id:tic40:20170130140506j:plain

雑感

  • 単体では意味をもたないものも、集合となることで意味を持つことができる。
  • 労力をかけて作られたもの(労力をかけて作られたと鑑賞者に思わせられるもの)はそれだけで存在感がある。
  • 色(グラデーション)
  • 国立新美術館の開館時間は平日10-18時まで

とても充実した昼休みになった。

*1:https://togetter.com/li/1073351

*2:会社から自転車で15分なので昼休みに行くことができる

hackerrank.com でベーシックアルゴリズムを(英語で)復習する

introduction

昨年、RSSだか社内チャットだかどこだったか忘れたが、とある海外エンジニアのブログを読んだ。 job interview をどう突破したのかが書かれていて、非常に刺激になった。

そこに、面接対策として、hackerrank.comで基本的なアルゴリズムを復習した〜ということが書かれていた。 ああ、binary treeや、sort、search アルゴリズムは当然学生時代に散々勉強したけど、実務でこれらを使うことは無かったし すぐ説明しろと言われてもできないなあ(英語面接ならなおさら)と気づいた。

というわけで昨年、業務後にhacker rankのアルゴリズムコースの問題をひたすら解いていた。

これからアルゴリズムを勉強、あるいは復習してみたい(英語で)という人は参考にしてみるといいかもしれない。

Hecker Rank とは?

www.hackerrank.com HackerRank - Wikipedia

how to begin

  1. サイトにアクセスし、まず sign up する。無料なので安心して欲しい。
  2. 登録できたら、practice へ行く。いきなりアルゴリズムコースへ行ってもいいが、まずはどういうものか慣れるためにもTutorialをやってみるといいだろう。 30 days of code は、1問5分以内で終わるのでコツを掴むのにおすすめ。 https://www.hackerrank.com/domains/tutorials/30-days-of-code

  3. tutorialを終えたら、algorithmsへ。 https://www.hackerrank.com/domains/algorithms Subdomains にアルゴリズムのカテゴリがわけられているので、たとえば探索アルゴリズムをやりたい場合は、'Search' カテゴリへ行けばいい。

問題の選び方

各問題には、Success Rate、Difficultyと言うものが表示されている。Success Rate、Difficultyを見て問題の難易度を先にチェックしてから挑戦しよう。Mediumでも結構難しい問題は多い。とりえあずEasyから始めることをおすすめする。さらに言えばEasyの中でもSuccess Rateの高い問題は易しい。英語に慣れていなければEasy問題の問題文を読むだけでも割りと大変かもしれない。

問題を解く

セレクトボックス内にある言語であれば、自由に選択できるので、好きな言語を選択できる。 問題がどうしても解けない場合、問題の Discussions へ行くといい。過去のログをみればEasy, Medium問題は大抵は解決する。たまに解答コードが直に貼られてあったりする。

バッジがもらえる

いっぱい問題を解くとポイントが溜まり、バッジを貰える。 何の役に立つのかはわからない。

Algorithms badge lv3 f:id:tic40:20170128183545p:plain

関連書籍。去年読んだ。買っておいて損はないという感じ。