OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerは同じ環境を作れるという安易な認識は間違っていた。

# 経緯

同じはずのDockerコンテナなのにローカル環境とテスト環境でテスト結果が異なっていた。

ファイル操作をするテストケースでLinuxでダメ文字といわれている\0や/周りでファイル・フォルダを作成するテストケースを書いていたところ
ローカル環境ではテストが通る（作成に失敗）開発環境ではテストが失敗した（作成に成功）


## 開発環境

Arch Linux

```
cat /etc/redhat-release

CentOS Linux release 7.4.1708 (Core)

uname -r

4.13.8-1-ARCH
```

## ローカル環境

DockerToolbox

```
cat /etc/redhat-release

CentOS Linux release 7.4.1708 (Core)

uname -r

4.4.89-boot2docker
```

# 結論

OSのベースになっているファイルシステム等までは同じにならないのでカーネルのバージョンも合わせるようにした方が良さそうですが、簡単にできそうにないので、ファイルシステム等に依存する処理は行わないほうが良さそうです。

# 追記
ストレージドライバの設定をデフォルトではなく設定してファイルシステムを揃えてやるという手もあるかもしれませんね、しかし、これだと毎回気にしないといけないので「思考停止で同じ環境ができる！」とはいきませんが。

http://docs.docker.jp/engine/userguide/storagedriver/selectadriver.html#stability

```
ディストリビューションの標準ストレージ・ドライバを使います 。
Docker をインストールする時、システム上の設定に応じてデフォルトのストレージ・ドライバを選択します。
デフォルトのストレージ・ドライバの使用は、安定性に対する重要な要素になります。
デフォルトのものを使わなければ、バグや微妙な差違に遭遇する可能性が増えるかもしれません。
```

# 参考

http://x68000.q-e-d.net/~68user/unix/pickup?%A5%D5%A5%A1%A5%A4%A5%EB%C0%A9%B8%C2%A4%DE%A4%C8%A4%E1
http://docs.docker.jp/engine/userguide/storagedriver/selectadriver.html
Qiita記事の反応をエゴサする方法

#はじめに
こいつは、良くも悪くも「毒」でござる。
世の中広いので、賛否両論あるのが普通でござるよ。
エゴサは用法用量を守って使いましょう。

#検索方法
検索結果のページをブックマークしておくと便利です。
あ、twitterとgoogleだけちょっと特殊だけど、他は「まぁそうだよね」くらいの情報です。

##[twitterさん](https://twitter.com/)
検索キーワード

```
url:qiita.com/ご自身のID
```

例

```
url:qiita.com/nh321
```

補足
urlオプションを使わないとうまくヒットしません。
ちなみに、このやり方でも、稀にヒットしないツイートがあります。
何が問題なのか分からんかったでござる。

##[Google先生](https://www.google.co.jp/)
検索キーワード


```:Aパターン：ゆるい条件
"qiita.com/ご自身のID" -site:b.hatena.ne.jp/entry/s/qiita.com/ご自身のID/items/ -site:qiita.com -site:twitter.com/qiita_rss -site:qiitadon.com/@qithub/
```

```:Bパターン：厳しい条件（twitterやはてブ関連のサービスを全部除外）
"qiita.com/ご自身のID" -site:twitter.com -site:twiblue.com -site:stwity.com -site:whotwi.com -site:trendtwitter.com -site:twetet.com -site:bkuma.hatena.ne.jp -site:qiita.com -site:twstat.org -site:www.trendsmap.com -site:twitter.com/qiita_rss -site:qiitadon.com/@qithub/ -site:b.hatena.ne.jp -site:twilog.org
```


例

```:Aパターン：ゆるい条件
"qiita.com/nh321" -site:b.hatena.ne.jp/entry/s/qiita.com/nh321/items/ -site:qiita.com -site:twitter.com/qiita_rss -site:qiitadon.com/@qithub/
```

```:Bパターン：厳しい条件（twitterやはてブ関連のサービスを全部除外）
"qiita.com/nh321" -site:twitter.com -site:twiblue.com -site:stwity.com -site:whotwi.com -site:trendtwitter.com -site:twetet.com -site:bkuma.hatena.ne.jp -site:qiita.com -site:twstat.org -site:www.trendsmap.com -site:twitter.com/qiita_rss -site:qiitadon.com/@qithub/ -site:b.hatena.ne.jp -site:twilog.org
```


補足
読めばわかりますが、Aパターンは「Qiita本体」「twitterのqiitaアカウント」「qiitadonのqithubアカウント」「はてブ」を除外しています。
Bパターンは関連サービスも全部除外してます。
最近の情報が欲しければ、検索オプションの「ツール」をいじれば良いかとー。

##[はてブ！](http://b.hatena.ne.jp/)
検索キーワード

```
qiita.com/ご自身のID
```
例

```
qiita.com/nh321
```

補足
デフォルトが「新着順」ですが、「すべて」にしましょう。
（「新着順」では表示されない記事がいくつかあった。反応が薄い記事は表示されない？）


##[facebookさん](https://www.facebook.com/)
検索キーワード

```
qiita.com/ご自身のID
```
例

```
qiita.com/nh321
```

補足
本当は、「いいね」した人を探す方法がないか模索したのですが、見つからず・・・
Qiita界隈の方は、「twitter」か「はてブ」に生息していることが多い気がするので、「facebook」ではあまりヒットしないかも。

#最後に
変数はIDのみなので、自分以外の投稿がどれくらい反応しているのかも見れます。
イケてるあの記事は、どんな反応されているのかなーとか、見れます。

エゴサは用法用量を守って使いましょう。（大事なことなので・・・

以上でござるよ。
🚨jestでReasonのテストを書く

過去に遡って[Reason ML Advent Calendar](https://qiita.com/advent-calendar/2017/reason_ml)の4日目を書く。現在に追いつける気配がない。

jestを用いてテストを書く方法について書く。

## :octocat: ソースコード
https://github.com/mzp/reason-of-work/tree/jest

(別のレポジトリを作るのが面倒だったので、今書いてるReason製プロダクトの別ブランチにした)

## なぜjestか
ほかのテスティングフレームワークではくjestを使うのは、ほかのフレームワークのバンディングが存在しないためです。

正確には[bs-mocha](https://github.com/BuckleScript/bucklescript-addons/tree/master/bindings/bs-mocha)という[mocha](https://mochajs.org)のバインディングが存在している。 しかし特にメンテされていないので利用は現実的でない。 ReasonのDiscordで聞いたたころ「あれはバンディングの書き方の例示だ。ちゃんと使うならbs-jestを使ってくれ」と言われた。

## ライブラリのインストール
yarnで `bs-jest` をいれる。

```sh
yarn add --dev bs-jest
```

`bsconfig.json` に依存を追加する。

```json
{
  ...
  "bs-dev-dependencies": ["bs-jest"],
  ...
}
```

## テストコードの追加
Jestの書き方にあわせるため、 `__tests__` 以下にテストコードを置く。

```ocaml
(*
テスト対象(counter.re):

type t = int;
let zero () = 0;
let value = n => n;
let inc = n => n + 1;
*)

open Jest;
open Expect;
open! Expect.Operators;

describe("Counter", () => {
    let subject =
      Counter.zero ()
      |> Counter.inc;

    test("value", () => expect(Counter.value(subject)) == 1)
  }
);
```

テストコードの書き方は[bs-jest同梱の例](https://github.com/reasonml-community/bs-jest/tree/master/__tests__)や[Jestのドキュメント](https://facebook.github.io/jest/docs/en/expect.html)が参考になる。

## ビルド対象への追加
`__tests__` をビルド対象に追加するよう`bsconfig.json`を変更する。このとき`type`を`dev`にしておくと、ライブラリとしてビルドされるときにはビルドされないようにできる。

```json
{
  ...
  "sources": [
    { "dir": "re" },
    { "dir": "__tests__", "type": "dev" }
  ]
  ...
}
```

## 実行
ビルド後、`jest`コマンドでテストを実行できる。 `package.json` で以下のように設定する。

```json
{
  ...
  "scripts": {
    "test": "bsb -make-world -clean-world && jest",
    ...
  },
  ...
}
```

![Screen Shot 2017-12-12 at 21.35.26.png](https://qiita-image-store.s3.amazonaws.com/0/5920/66e96d3c-774f-c6bf-ecc2-bc2b765101a6.png)
bitnamiでRedmineの環境を作ってみた

ラクス Advent Calendar 2017の12日目です。

さて、今回は自分がRedmineの新しい機能やプラグインを試したい時にどうやって環境を用意したかのお話になります。

[Redmine](http://redmine.jp/)とは、プロジェクト管理ができるオープンソースソフトウェアです。やるべき作業を記録・管理したり社内で情報共有ができるツールになります。
また、提供されているプラグインを導入することで追加の機能を使用することができます。

いろいろなプラグインを実際に動かして試してみたかったのですが、Redmineの環境を用意するには、Redmineのモジュール以外にDBサーバやWebサーバなどを用意する必要があり、最初から挫折しかけました。

そこで他の手順がないか探していた時に見つけたサービスが[bitnami](https://bitnami.com/)でした。
bitnamiとは、いろいろなWebアプリケーションをオールインワンパッケージで提供しているサービスで、Redmineも提供されていましたので、早速試してみました。

# bitnami版 Redmineの準備

### インストールの手順
1. bitnamiの[ダウンロードページ](https://bitnami.com/stack/redmine/installer)からインストール
2. 起動するとセットアップウィザード画面が表示されます
   ![セットアップ.png](https://qiita-image-store.s3.amazonaws.com/0/43709/d5fc69c6-4dca-b859-e065-dd4a998b0500.png)
3. ウィザードに従って、インストールするコンポーネントを選択して、次へを押下します
![セットアップ.png](https://qiita-image-store.s3.amazonaws.com/0/43709/2ddd161d-5d2a-cad9-5ae2-0d5c0d1db415.png)
4. 管理者アカウントのユーザ名やパスワードを入力して、次へを押下します
![セットアップ 3.png](https://qiita-image-store.s3.amazonaws.com/0/43709/47da9b3a-6acb-5e42-9c49-7cdab33f02f2.png)
5. 一通りの設定が終わると、インストールが開始されます
6. ５.が完了後、http://localhost:8080/redmine にアクセスすると、RedmineのTOPページが表示されるようになりました

# Redmineの起動・停止

## アプリケーションから操作する場合
操作したいサーバを選択して、右側に並んでいるボタンを押下します。
![Bitnami_Redmine_Stack_3_4_3-1.png](https://qiita-image-store.s3.amazonaws.com/0/43709/0f2248d3-e4e9-1c4d-8215-054c03f067ff.png)

## ターミナルから操作する場合
### Apacheの操作
```bash
$ cd /path/to/redmine/
$ ./ctlscript.sh (start|stop|restart|status) apache 
```
### DBの操作
```bash
$ cd /path/to/redmine/
$ ./ctlscript.sh (start|stop|restart|status) mysql
```

# プラグインのインストール

### プラグインの配置場所
```bash
$ cd /path/to/redmine/apps/redmine/htdocs/plugins
```

あとは、プラグインの設定手順に従うだけで、プラグインを使用することができます。

# 使ってみた感想
オールインワンパッケージということで、依存関係のソフトウェアは意識する必要がなかったり、DBの初期化なども最初のインストールした際に行われるため、環境の用意に手間がかからなく、検証に注力できました。

また、プラットフォームもWindowsやMac、Linuxが用意されているのも利点です。

しかし、Bitnamiが提供しているRedmineが最新のバージョンのみなので、試したいバージョンを指定することができないということがありますが、新しいリリースされた機能やプラグインを手軽に試せるのは良いなと思いました。
ARKit でワンランク上のアプリを実装するための Tips

この記事は [Akatsuki Advent Calendar 2017](https://qiita.com/advent-calendar/2017/aktsk) の 12 日目の記事です。

## はじめに

ARKit は内蔵カメラのみで AR 環境を提供してくれる素晴らしい機能です。

開発者も利用者も簡単に利用できるため、数多くのアプリがリリースされ、メディアを賑わせています。
私も流れに乗るべく Unity 環境で ARKit を使ったアプリケーション [Measure](https://itunes.apple.com/jp/app/measure/id1280423470?mt=8) をリリースしました。

今回は Measure を開発する中で ARKit について得た知見を共有したいと思います。
※ Measure がワンランク上のアプリだとは微塵も思っていません。改善の途中です。

## 2017.12.12 時点の ARKit にできないこと

開発を始める前に ARKit にできないことを知っておくことが重要です。

### 現実空間での絶対座標の取得できない

ARKit は空間認識を始めた場所からの相対座標で現実空間を認識しています。
なので、部屋の中で今どこにいるかを知ることは ARKit 単体ではできません。

### マーカートラッキングできない

意外かもしれませんが、ARKit ではマーカートラッキングができません。
下記の項目にも関連しますが、マーカーを使って位置を補正したり、面を認識したりすることはできません。

### 事前に用意した情報を与えれない

ARKit では、`事前に用意したデータ` や `以前アプリで取得したデータ` を受け渡すことができません。
なので、ARKit 自体の精度向上のために我々ができることはほとんどありません。

### 他人の空間情報を共有できない

これができたら最高に面白いと思うのですが、残念ながらできません。
1 人ずつ、完全に同じ場所で空間認識を始めれば、擬似的に共有することはできます（苦痛）。

### 動いているモノの位置を把握できない

画像から距離を推定しているので、モノ自体が動くと位置を把握することはできません。
それどころか、色々な情報に狂いが生じるのでその後まともに位置を把握できなくなります。

## 2017.12.12 時点の ARKit の限界

ARKit は内蔵カメラだけを使うにしては精度が高いといえます。
残念ながら、ユーザが納得の行くほどの精度ではありません。

### 任意の点の現実座標を取得する FeaturePoint の限界

様々なアプリを作る上で、FeaturePoint は便利な機能です。
実際に使ったことがあればわかると思いますが、結構ズレますよね？
そうなんです。結構ズレるんです。

FeaturePoint を取得しようとした場所の特徴量が少ない可能性もあるので、
付近の何点かを取得して補完すればいいじゃないか！！と皆さん思うでしょう。
残念ながら、FeaturePoint を複数取得しても大した補完はできません。
FeaturePoint 自体がなんらかのアルゴリズムによる推定値だからです。

私が色々試してみたことによる推測ですが、
FeaturePoint は取得したい点を頑張って補足しようとしているのではなく、
現状把握できている点群からの推定値になっています。

### 現実空間上の iPhone の位置捕捉の限界

ARKit でまず驚くのは、iPhone が動いても相当な精度で位置を補足できることです。
これによって、仮想空間上においたモノを現実空間で回り込んで見たりできます。

しかし、この位置捕捉にも限界があります。
過去の PointCloud を表示したままにしておくと、
時々ガクッと位置がズレて、また戻ることがあります。

これは iPhone の位置を反映しているカメラの位置が飛ぶことでそう見えています。
顕著にこの現象がわかるのが、iPhone を縦持ちから横持ちに変えたりする場合です。

開発者からすると、戻るからいっか！とか思いますが、
ガクッとずれる現象はユーザにとって非常によくない体験になります。

### プレイ環境の限界

ARKit に向いていない環境はいくつかあります。

- 特徴量の少ない空間（真っ白な壁、真っ暗な部屋など）
- 半透明なガラスや反射率の高いモノが多い空間
- 加速度の変化が多い空間（車、電車、飛行機、船など）

この中でも加速度の変化が多い空間でまったく遊べないのは辛いです。
iPhone の位置捕捉にジャイロセンサーや加速度センサーを利用しているので、
空間そのものに加速度がかかっていると、モノが遠くへ消え去って行きます。

電車で初めて使ったときの悲しさを私は忘れません。
※微細な変化でも ARKit には大きな影響があるようです。

### 現実空間把握の限界

もちろんですが、PointCloud や PlaneDetect にも限界があります。
PointCloud は 1 フレームずつ丁寧に確認すると、ズレた点が結構あります。
PlaneDetect は上下に若干ズレていることが多いです。
検出平面にキャラクターを配置したりすると浮いていたり、よくみると突き刺さっていたりします。

## ワンランク上の ARKit アプリを開発するには

以上のことを踏まえてワンランク上の ARKit アプリを作るための Tips を考えてみました。

- 1 人用アプリにする（オレオレ空間共有による体験の劣化を防ぐ）
- 家の中で遊ぶ想定にする（動くモノが少なく、加速度の影響もない）
- 特定の現実座標を利用しない（FeaturePoint を使わない）
- 現実空間と仮想空間の座標的な結びつきを弱くする（カメラのズレや移動による位置の影響を感じにくい）
- 検出平面より若干低めにオブジェクトを出す（めり込みより浮いているのが目立つため）
- オブジェクトを大味なモノにする（現実座標との些細なズレをごまかすため）
- オブジェクトをできるだけ動かす（同上）
- 高精度な空間認識が必要としない（そもそも精度に限界があるため）

アプリの幅が結構制限されているに感じますが、
新しいアプリを考えているとそれなりにアイデアは出てきます。

## おまけ
アイデアだけでは差別化が難しいので、独自の面検出機能を実装しています。
現実空間の大まかな面を高速に取得して利用する予定です。
PointCloud の不要点棄却アルゴリズムや点群をメッシュ化するアルゴリズムを弄くり回しています。
※そのうち、別の記事を書くかも。

![Test2.gif](https://qiita-image-store.s3.amazonaws.com/0/169623/3638b694-5f4c-11b9-16ea-e50b9fbfc365.gif)

## おまけ 2

特段重要ではないですが、気づいたことを書いておきます。

- 新しい iPhone の方が検出精度が高い
- 新しい iPhone の方が検出速度が早い
- CPU や GPU に高い負荷をかけると、空間把握がバグる
D3.js使い方入門

株式会社スマートドライブでフロントエンドエンジニアをしている@takanoripです。
アドベントカレンダー２回めの登場です。

前回はフロントエンド関係ない話だったので、今回はフロントエンドっぽい話をしたいと思います。

ということで、今回は`D3.js`の使い所について書きます。
昨日のアドベントカレンダーで十八番奪われそうとか書かれてましたが、大丈夫です。奪いません。


## D3.js

D3.jsはデータに基づいてドキュメントを操作するためのJavaScriptライブラリです。
D3は"Data Driven Document"の略です。

ドキュメントやチュートリアルは下記のサイトなどを見ると良いでしょう。

日本語ドキュメント
http://ja.d3js.node.ws/

チュートリアルまとまってるサイト
http://deep-blend.com/jp/category/tutorials/tutorial-d3/

フロントエンド界隈の人であれば名前は聞いたことはあると思いますが、一体何に使えば良いのかわからない！！って人多いんじゃないでしょうか？
僕も最初は「でーたびじゅあらいぜーしょん…？」みたいな感じでした…
今回は一体何に使えるのかを具体的な例とともに紹介します。


## D3.jsのいいところ

何に使えるのかの前にD3のいいところを紹介します。

### jQueryに似た書き方ができる

D3はjQueryと同じようにメソッドチェーンを使って書くことができるので、jQueryを書いたことがある人はすんなり始められると思います。
JSONを読み込む場合は下記のように書きます。

```js
d3.json("test.json", (data)　=> {
  console.log(data);
});
```

DOM操作もjQueryを同じように書けます。

```js
draw(num) {
  d3.select('#test')
    .selectAll('svg')
    .data([items[num]])
    .enter()
    .append('svg')
    .call(chart);
}
```

### 配列操作関数が充実してる
D3は配列を操作する関数がたくさんあって便利です。
APIドキュメントにまとまっているので、詳しくはそちらを参照してみてください。
https://github.com/d3/d3/blob/master/API.md#arrays-d3-array

### 要素にデータをバインディングする
D3の大きな特徴として、要素にデータをバインドしていることが挙げられます。上の例では`data`を使って`svg`要素にデータをバインドしています。
要素にデータが紐付いているので、データの値や種類に応じて動きやスタイル変えることができます。
また要素の反復にも強いです。

## 何に使えるの？
### 複雑なチャート
D3は、チャート専用ライブラリでは表現できない複雑なチャートを表現することができます。D3の用途として一番考えられるのもこれですね。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/69864/5b6164cd-6a68-e613-c2aa-f6ecb6cb8743.png)
[Circular heat chart](http://prcweb.co.uk/lab/circularheat/)

弊社サービスの管理画面では自動車の加速度を表すチャートがあり、そのモックなどはD3を使って構築しています。サクッと動くものが作れるのでとても重宝しています。
（Reactとの相性があまり良くないのでプロダクトでは使っていません。）

### ゲージ
![](https://i.gyazo.com/94c79b8b0bb7cfb7a1bc8c6990dbd474.gif)

最近某転職マッチングサービスでよく見るこのゲージもD3で作ることができます。

[D3 Liquid Fill Gauge](http://bl.ocks.org/brattonc/5e5ce9beee483220e2f6)

### ヒートマップ
![](https://www.visualcinnamon.com/wp-content/uploads/2013/07/Hexagonal-Heatmap-in-D3.png)
[SOM - Creating hexagonal heatmaps with D3.js](https://www.visualcinnamon.com/2013/07/self-organizing-maps-creating-hexagonal.html)

### 関係図
分子図のようなものも作れます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/69864/8c403e4f-988f-9540-ea3e-9cb0233e005c.png)
[OrgoShmorgo](http://orgo.stolarsky.com/)



## おまけ：フレームワークとD3
### React
ライブラリがあるらしいです。
http://www.reactd3.org/

### Vue
有名なライブラリはないみたいですね。
組合せて使ってる記事がちらほらありました。
https://bl.ocks.org/lorenzopub/02ccce43d708919ca7c0b242fe1c93f2

Vueも仮想DOMを使っているので自前実装は気を使いそうです。
[Chrome extension] Scrutinizer for GitHub で楽してコードの品質を高めよう！

[Fusic Advent Calendar 2017](http://qiita.com/advent-calendar/2017/fusic)の14日目の記事です。

福岡の[Fusic](https://fusic.co.jp/)にてLAMPでCakePHPでウェブアプリ開発もしくは、AWSをいじいじしております。


みなさんコードの品質を高めるために何をしていますか？
品質といっても、CI、カバレッジ、非推奨関数の撲滅、言語・フレームワークごとのコーディング規約など多岐にわたり、レビューだけでは限界があります。
そこで登場するのが静的解析ツールですが、言語ごとにツールも変わり、各言語にあわせた環境を整えるのには手間がかかってしまいます。


**統一の環境で静的解析ができ、さらにコードレビューのタイミングで解析内容が確認できると**
**エンジニアのレビューはよりロジカルな部分に集中できるようになって**
**最高じゃないですか？**


今回は、GitHubと連携機能を持つ[Scrutinizer CI](https://scrutinizer-ci.com/)の簡単な紹介と
そのChrome Extensionを使ってより効率的にコードの品質を高める方法について紹介します！

# Scrutinizer CI
公式サイト：https://scrutinizer-ci.com/
その他紹介記事

 - https://www.slideshare.net/hinakano/scrutinizer-ciphp
 - https://qiita.com/k-motoyan/items/a63d7add9dc35ae8317a

PHP / Ruby / Python / Java の静的解析に対応しています。
使い方は簡単、Scrutinizerのアカウントを作成し、連携したいGithubのリポジトリを追加するだけです。

**出来ること（一部）**（※プランによりできる内容には差異があります

- 静的解析（PHP/Ruby/Python/Java）
  - 静的解析から推察できる修正内容の自動パッチ作成
  - コードカバレッジ
  - コードの依存度、循環的複雑度の警告
  - リポジトリに対して**点数**をつけてくれる（モチベーションアップ
 
### リポジトリトップ画面（例
点数高いとテンション上がる、逆に低かったりコードのランク（A~F）が下がると悲しい
![2017-12-12_20h17_16.png](https://qiita-image-store.s3.amazonaws.com/0/74129/a5971015-07e2-4ff3-d8c4-70f205ebdfc3.png)

### Issue画面（例
例の画像では、対象の変数が未定義で到達してしまう可能性を警告してくれています。
![2017-12-12_20h26_52.png](https://qiita-image-store.s3.amazonaws.com/0/74129/dd2d41dc-22c1-715c-ef99-285b4968e860.png)


## Scrutinizer for GitHub
Chrome Extension Scrutinizer for GitHub
https://chrome.google.com/webstore/detail/scrutinizer-for-github/jpfnopbpkpaoaoomhmpeiijbcnhkbflg

すでに便利なScrutinizerですが、解析結果の詳細を見るにはScrutinizerのダッシュボードまで行かなければいけませんでした。
しかし、最近Chrome Extensionが公開され、Githubのプルリクのコードレビューの画面でIssueを見ることが出来るようになりました！

Scrutinizerにログインしており、リポジトリをScrutinizerと連携していれば、プルリクの内容が解析された後、レビュー画面に自動で表示されます。

### サンプル画像
![2017-12-12_20h35_04.png](https://qiita-image-store.s3.amazonaws.com/0/74129/5e24cb54-b495-c52e-6446-63b89131b8bd.png)
![2017-12-12_20h35_18.png](https://qiita-image-store.s3.amazonaws.com/0/74129/19d3d976-7ffc-fb21-aea9-d35a504978c2.png)

これで今まではレビューでは気づけなかった内容や、非推奨関数の利用など効率的に修正ができるようになりました。


# 使用してみて

まずは、個人的に利用をしており、チームはては会社のスタンダードにできればなと思っています。
静的解析でさばける内容には注力せず、ビジネスロジックや仕様周りのレビューに集中できるって幸せだなと感じています。

皆さんも出来る限り楽をしてコードの品質高めていきましょう！
iPhoneXのレイアウトについて調べてみた

# はじめに
こんにちは！

12/9の記事に引き続き、iPhoneXについて書こうと思います。
認識違いがありましたらご報告いただけると幸いです。

ご存知の通り、iPhoneXはベゼルレスの全面スクリーンになりホームボタンも廃止されました。
そこで[既存アプリの表示はどうなるのか](https://qiita.com/ryo-ta/items/b556331411c58dc8b5f0)といいますと...ということを一度記事にしておりますので、
一度目を通して頂いてからのほうがわかりやすいかもしれませんｗ

ざっくりした説明ですが、非対応アプリは従来と同じサイズで表示され、
対応アプリでは上下余すことなく情報が表示されるようになります。

さて、本題ですがiPhoneXには画面上部にセンサー類を配置しているため切り欠きがあります。

![koya_iphonex1.png](https://qiita-image-store.s3.amazonaws.com/0/206492/9db70f67-056f-11f3-5d98-8e8a559a50ad.png)


今回はこの切り欠きをどうするのかについて調べてみたいと思います！

# 切り欠きを考慮したレイアウト
iOS11からレイアウトに**SafeArea**という概念が導入されました。
これは主にiPhoneXのレイアウトに必要な概念です。

簡単に説明すると、画面上部の**凹部分**と画面下部の**ホームバー**と呼ばれる操作領域を避けてレイアウトしてね、というものです。

凹部分に何か重要な情報があったとしても表示できませんし、
ホームバーとボタン類が被ればユーザビリティが下がるのは当然ですよね。

ではどうすれば`SafeArea`を考慮したレイアウトができるのか。。。

上下○○ptは配置しちゃダメとか？
え？固定幅なの？

いいえ、違います。（※）

難しいことは考えず、簡単にiPhoneX対応ができちゃうんです。

**そう、AutoLayoutならね。**

# AutoLayoutでのSafeArea導入

ちょっとおふざけが過ぎました...（言ってみたかっただけ）

さて本題に戻りますが！！

ご存知の方だらけだとは思いますが、iOSのレイアウト方法に`AutoLayout`というものが存在します。
もし知らねーよって方は[AutoLayoutについて軽く解説した記事](https://qiita.com/ryo-ta/items/1dff68458776c0baa193)も書いていますので良ければこちらも...^^(宣伝ｗ)

このAutoLayoutを使用していると、自動でSafeAreaを計算し配置してくれる便利な機能を使えます。
SafeArea内に配置すればiPhoneXの各種部分に干渉せず、
大画面かつ新体験をユーザーに提供することができるというわけです。
~~開発者泣かせの端末もこれでOK！~~


# AutoLayoutを使っていなかったらどうすんの？

過去に書いた記事でも言っておりますが、レイアウトを行う上でAutoLayoutが使いにくい場合があります。

~~（あります。と断言しましたが僕はAutoLayoutで事足りるアプリしか作っていないので、あるそうです、が正しい。。。）~~

そんな場合でもSafeAreaを考慮してレイアウトを行わなければなりません。
僕はまだやったことはありませんが、コードからSafeAreaの値を取得しViewの位置を調整する方法が一般的だそうです。（`UIView`の`safeAreaInsets`で取得できるらしい）

上のほうで言った、
> いいえ、違います。（※）

の`※`の意はこれです...。

AutoLayoutばかり使用できるわけではないので、どちらの方法も勉強しなきゃですね。。。

# さいごに

超ざっくりした説明になりましたが、
そんなものがあるんだな～、やってみようかな～、と思っていただければ幸いです！！
僕はまだまだSwiftに苦戦させられる日々です。。。
~~まずXcodeに慣れない。~~

ではではこの辺で！

P.S. iPhoneXが寝起きの顔を認証してくれないのが最近の悩みです。
RxPYをひたすら素振りする

# はじめに

本記事はサムザップAdvent Calendar 2017の1３日目の記事です。
昨日は@takahashi_wataruさんの[Unity2017.2.0p3で.Net4.6を使うとVisualStudioのインテリセンスが効かない対処法+α](https://qiita.com/takahashi_wataru/items/9bff12e49899f209fd78)でした！

今年の9月からサムザップでお世話になっている@mmm_hiroです。

現在関わっているプロジェクトのいろいろによりPython3（使用歴半年）を利用しているのですが
今回はPythonでRxPYを利用したリアクティブプログラミングについて記事を書こうかなと思います。

他の言語に比べて、PythonにおけるReactiveXの記事は少なく、自分もコツを掴むまでに多少の時間を必要としました。
まずはネット上にある有用な記事（言語問わず）を読み、リアクティブプログラミングの概念を把握するところから初めましょう

* http://reactivex.io/
    * 様々な言語でリアクティブプログラミングを実装
* https://github.com/ReactiveX/RxPY
    * その中のPython実装がこのライブラリ

# ReactiveXを理解するために何を読めばよいか？

ネットにあげて下さった記事をひたすら熟読していきましょう。全部読めばなんとなく理解できてくるはずです。

* https://github.com/ReactiveX/RxPY/blob/develop/notebooks/Getting%20Started.ipynb
    * notebookで解説されているので丁寧に見ていけば概要を把握できると思います。


* http://ninjinkun.hatenablog.com/entry/introrxja
    * Python実装ではないでうが、Twitterの「フォローするアカウントを推薦するUIエレメント」を例にした実装手順はとても参考になります。

* https://qiita.com/acple@github/items/8d3a4d3414fa59adff70
    * cold hotについて

* https://qiita.com/acple@github/items/6cfee916f09632037a6e
    * こわくないReactive Extensions超入門

# 導入

```
pip install rx
```

# サンプルをかけるだけ書く

http://reactivex.io/documentation/operators.html#creating

以下、当日、かけるところまでサンプルを書き続けてみる。以下当日中随時更新していきます（2017/12/12、21:05記述中）

## 一番シンプルなもの

```python
# 値を一個ずつ送信、2倍してプリント
xs = Observable.from_([1,2,3])
d = xs.map(lambda x:x*2). \
    subscribe(print)
```

```
2
4
6
```

ちなみに、配列内のデータをそのまま送ってるわけではないことに注意。

```python
xs = Observable.from_([[1,2,3],[4,5,6]])
d = xs.map(lambda x:x*2). \
    subscribe(print)
```

こちらの場合は[1,2,3]と[4,5,6]が一つのストリームとして送信されています。

```
[1, 2, 3, 1, 2, 3]
[4, 5, 6, 4, 5, 6]
```

## 指定の条件に満たない場合は除去する。

```python
from rx.subjects import Subject
print("50以下は無効化してしまう壁\n")

stream = Subject()
d = stream.do_action(lambda x: print(x)) \
    .filter(lambda param: param>50) \
    .subscribe(lambda result: print("壁を貫通！{0}のダメージ".format(result)))

# 攻撃！
stream.on_next(0)
stream.on_next(50)
stream.on_next(51)
stream.on_next(49)
stream.on_next(100)
stream.on_next(-50)
stream.dispose()
```

```
50以下は無効化してしまう壁

0
50
51
壁を貫通！51のダメージ
49
100
壁を貫通！100のダメージ
-50
```

## stream_left,stream_right両方に値が来たときだけsubscribeが動作

```python
from rx.subjects import Subject

stream_right = Subject()
stream_left = Subject()

stream = stream_left.zip(stream_right, lambda x, y: x+y)
d = stream.subscribe(lambda result: print("合算：{}".format(result)))

stream_left.on_next(1)
stream_left.on_next(2)
stream_right.on_next(3)
stream_right.on_next(4)
```
```
合算：4
合算：6
```

## 指定した回数しかsubscribeに到達しないようにする

```
from rx.subjects import Subject

stream = Subject()
stream.take(3).subscribe(lambda member: print("{}".format(member)))

# 
print("先着順です！商品獲得は以下の3名です")
stream.on_next("1さん")
stream.on_next("2さん")
stream.on_next("3さん")
stream.on_next("4さま")
stream.on_next("5さま")


```

```
先着順です！商品獲得は以下の3名です
1さん
2さん
3さん
```



----
明日は@norimatsu_yusukeさんのWPFのビューについてです。
Vue.jsの単一コンポーネントを気軽に試すにはcodesandboxが最高に良い

Vue.jsの2017年アドベントカレンダーとても盛り上がってますね！
しかし、色々な記事がある中で、いちいちプロジェクトを立ち上げてコードを書きはじめたり、npm installしたり、vue initするのは面倒くさいなと思う節があります。

JSをオンラインで試すツールはいくつかありますが、実はVue.jsの公式ドキュメントに載っているツールが有るんです。
ちょっとしたコンポーネントやTipsを試すのにはすごく有用ですよ！

https://codesandbox.io/s/o29j95wx9

> 引用:https://jp.vuejs.org/v2/guide/single-file-components.html#サンドボックスの例


### おまけに
なお、html、JS、CSSを試すのに一番いいと思っている最近のツールはJS Binです。
デベロッパーツールを開かなくともコンソールがあるのがいいとこだなと思います。
https://jsbin.com/?html,output
monacoinをリソースに制限をかけてGPU堀り

# はじめに
 この記事の内容はmonacoinのみではなく、ccminerを使用する仮想通貨全てに応用が効きます。
readmeを読むとか--helpをすることですぐに分かる内容ですが、個人的に気になり、あまりネット上に情報もなかったので纏めました。
# 何をするのか
 タイトル通り、GPUを利用して行うマイニングを、リソースを制限して行います。これによるメリットは  

-  電気代の節約
-  PCが重くなりすぎない

以上二点です。個人的にはGPUをゲームも機械学習もしないで腐らせてるのはもったいないと感じ、マイニングに手を出したは良いものの、掘りながら何かするには耐え難いくらいのストレスが掛かるほどにPCが重くなってしまったので重大でした。

# 方法
ccminerの起動オプションに -i <8~31の整数>を追記してください。windowsでプールマイニングをしているならば

```
ccminer.exe -a <アルゴリズム名> -o <プールのアドレス> -u <ワーカー名> -p <ワーカーのパスワード> -i <8~31の整数>
```
こんな感じになります。

# 解説
-iオプションは使用するGPUスレッド数を指定するためのオプションです。ここの引数をnとすると、2のn乗のスレッドでマイニングがされます。ここの値を丁度いい値にすることである程度マイニングの効率を稼ぎつつPC上で作業をする余力を残させることが出来ます。

# 結論
マイニングはマイニング用のPCで！作業は作業用のPCで行いましょう！
［ C＃］ログの世代管理

実務にてiniに記載したログの世代管理数/サイズを取得して、ログの世代管理を行う必要があるのですが、良いサンプルコードはないでしょうか。。
⇒作ってみました

```c#:Program.cs
        public static void LogGenerateMng()
        {
            long Generation = 5;
            string LogFileName = "LogFile";
            string LogPath = @"c:\test\LOG\";
            string Extention = ".log";

            /**************************************************************/
            // 世代管理開始
            /**************************************************************/
            for (long i = Generation; 0 < i; i--)
            {
                // 指定された最大世代ループ時
                if (i == Generation)
                {
                    string target = LogPath + LogFileName + i.ToString().PadLeft(2, '0') + Extention;

                    // 存在する場合は削除(最大サイズだから)
                    if (File.Exists(target))
                    {
                        File.Delete(target);
                    }
                }

                // 最大未満～当世代未満の場合
                if (1 < i && i < Generation)
                {
                    string target = LogPath + LogFileName + i.ToString().PadLeft(2, '0') + Extention;

                    // 存在する場合はコピーして削除
                    if (File.Exists(target))
                    {
                        // 2世代目の場合
                        if(i == 2)
                        {
                            // 1世代上のファイルがあればコピーして削除
                            if (File.Exists(LogPath + LogFileName + Extention))
                            {
                                File.Copy(target, LogPath + LogFileName + (i + 1).ToString().PadLeft(2, '0') + Extention);
                                File.Delete(target);
                            }
                        }
                        else
                        {
                            // 1世代上のファイルがあればコピーして削除
                            if (File.Exists(LogPath + LogFileName + (i - 1).ToString().PadLeft(2, '0') + Extention))
                            {
                                File.Copy(target, LogPath + LogFileName + (i + 1).ToString().PadLeft(2, '0') + Extention);
                                File.Delete(target);
                            }
                        }
                    }
                }

                // 当世代の場合
                if (i == 1)
                {
                    string target = LogPath + LogFileName + Extention;

                    // 存在する場合はコピーして削除して当世代新規作成
                    if (File.Exists(target))
                    {
                        File.Copy(target, LogPath + LogFileName + (i + 1).ToString().PadLeft(2, '0') + Extention);
                        File.Delete(target);
                        File.Create(target).Close();
                    }
                }

            }
        }
```
時刻表示をゼロパディングする方法と、日本語ロケールの不思議な挙動について

# 時刻表示をゼロパディングする方法

```js
new Date(new Date().setHours(1,1)).toLocaleString('en',{ hour12:false, hour:'2-digit', minute:'2-digit' });
/*
01:01
*/
```

# 以下、余談

```js
//日本語ロケールだと上手くいかない
new Date(new Date().setHours(1,1)).toLocaleString('ja',{ hour12:false, hour:'2-digit', minute:'2-digit' });
/*
1:01
*/

//時間だけにすると謎の挙動
new Date(new Date().setHours(1,1)).toLocaleString('ja',{ hour12:false, hour:'2-digit' });
/*
1時
*/

//12時間表記だとこう
new Date(new Date().setHours(1,1)).toLocaleString('ja',{ hour12:true, hour:'2-digit' });
/*
午前1時
*/

//いやあの、'numeric'ってお願いしましたよね？
new Date(new Date().setHours(1,1)).toLocaleString('ja',{ hour:'numeric' });
/*
1時
*/

```

なぜだろう、と思ってググって見たところ、このような話が。

> In CLDR v28, Japanese simply doesn't have any 2-digit hour date formats 
>
[507037 - Date.toLocaleString ignores hour:2-digit setting - chromium - Monorail](https://bugs.chromium.org/p/chromium/issues/detail?id=507037)

**「単純に日本語には2ケタ時のフォーマットがないみたい」**
マジっすか。

```XML
<dateFormatItem id="h">aK時</dateFormatItem>
<dateFormatItem id="H">H時</dateFormatItem>
<dateFormatItem id="hm">aK:mm</dateFormatItem>
<dateFormatItem id="Hm">H:mm</dateFormatItem>
<dateFormatItem id="hms">aK:mm:ss</dateFormatItem>
<dateFormatItem id="Hms">H:mm:ss</dateFormatItem>
```

~~http://unicode.org/cldr/trac/browser/trunk/common/main/ja.xml#L1399~~
https://www.unicode.org/cldr/charts/44/summary/ja.html#248fbe564acac90d
マジだわ……
なんか不思議な設定ですね。
　
　
　
そういうわけで。
時刻の日本語ロケールは怪しいので触らないほうが無難です。`en`を使いましょう。
One or more resources have the target of 'head', but no 'head' component has been defined within the view.となった時の対応方法

- 環境
    - macOS Hight Sierra
    - Eclipse : Neon.3 Release (4.6.3)
    - GlassFish 4.1
    - Java : JDK1.8
    - JSF : 2.2

# 事象 : JSFでCSSを読み込んだはずなのに適用されなくてserver.logになんか出てた

```xml:修正前のXHTML
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://xmlns.jcp.org/jsf/html"
  xmlns:f="http://xmlns.jcp.org/jsf/core">
<head>
  <title>入力画面</title>
  <h:outputStylesheet library="css" name="base.css"/>
</head>
<body>
<h:form>
  <h:outputLabel>パスワードを入力して下さい。</h:outputLabel>
  <br />
  <h:inputText id="password" value="#{passwordBean.password}">
    <f:validateRequired />
    <f:validateLength minimum="3" maximum="10"></f:validateLength>
  </h:inputText>
  <h:message for="password" errorClass="error" />
<省略>
```

```css:base.css
@CHARSET "UTF-8";
.error {
    color: red;
}
```
![Screen Shot 2017-12-12 at 20.13.28.png](https://qiita-image-store.s3.amazonaws.com/0/159761/4aa3e746-1fae-d2a5-d242-2d71b7b1039b.png)

```text:server.log
[2017-12-12T20:29:46.608+0900] [glassfish 4.1] [INFO] [jsf.non_displayed_message] [javax.enterprise.resource.webcontainer.jsf.renderkit] [tid: _ThreadID=32 _ThreadName=http-listener-1(2)] [timeMillis: 1513078186608] [levelValue: 800] [[
  WARNING: FacesMessage(s) have been enqueued, but may not have been displayed.
sourceId=null[severity=(ERROR 2), summary=(One or more resources have the target of 'head', but no 'head' component has been defined within the view.), detail=(One or more resources have the target of 'head', but no 'head' component has been defined within the view.)]]]
```

## 原因 : `<head>`を使っているから
[user interface - One or more resources has the target of &#39;head&#39; but not &#39;head&#39; component has been defined within the view - Stack Overflow](https://stackoverflow.com/questions/18940644/one-or-more-resources-has-the-target-of-head-but-not-head-component-has-been)

### 対応方法 : `<h:head>`を使う
```xml:修正後のXHTML
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://xmlns.jcp.org/jsf/html"
  xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
  <title>入力画面</title>
  <h:outputStylesheet library="css" name="base.css"/>
</h:head>
<省略>
```
![Screen Shot 2017-12-12 at 20.19.48.png](https://qiita-image-store.s3.amazonaws.com/0/159761/f0e0b9a0-ffa6-8a6e-25cf-b05c3fa312b6.png)
TouchDesignerでGLSLを書く2つの方法

12/2に福岡で開催された Touch in Kyushu vol.1 に参加してきました。
https://peatix.com/event/327787

TouchDesignerではGLSLを直接書けるのですが、ちょっと便利なやり方を教えていただいたので、その時のメモです。

## 前準備
テキストノードでも編集はできますが、`Preferences -> DATs -> Text Editor` でエディタのパスを指定しておくと、コンテキストメニューの `Edit Contents` からエディタで編集できるようになります。


## GLSL TOP で書く
まずはGLSL TOPを使う方法。
シンプルなFragment Shaderが自動で接続されるので、これを修正します。
`info DAT` を接続しておくとエラーなどデバッグ情報を見れて便利です。
<img width="305" alt="td_glsl_top_info.png" src="https://qiita-image-store.s3.amazonaws.com/0/972/18192688-54f8-93ee-0c08-3d0652c24238.png">

デフォルトのFragment Shaderは以下。

``` glsl
// uniform float exampleUniform;

out vec4 fragColor;
void main()
{
    // vec4 color = texture(sTD2DInputs[0], vUV.st);
    vec4 color = vec4(1.0);
    fragColor = TDOutputSwizzle(color);
}
```
GLSLでの `gl_FragColor` が `fragColor` に置き換わってます。
`TDOutputSwizzle()` はWindowsとmacOSのテクスチャのカラーチャンネルの差異を吸収してくれる関数です。
`GLSL TOP` に入力された画像や動画は `sTD2DInputs[0]` で取得可能。
`texture(sTD2DInputs[0], vUV.st)` でUVに合わせたカラー値を取得できます。

外部変数の設定は、 Paremeters で Vector1 などに変数名と値を入力し、コードに対応した変数名を uniform で宣言すれば使えるようになります。

``` glsl
uniform float iTime;
uniform vec2 iResolution;
```

<img width="488" alt="td_glsl_top_parametors.png" src="https://qiita-image-store.s3.amazonaws.com/0/972/0449ca6e-7e4e-36af-1cba-60e1cc5a0bea.png">
iTime には `absTime.seconds` を使用して秒数を取得し、 iResolution には画面解像度を入力してます。

TouchDesignerのGLSLでも `gl_FragCoord` が使えるので、以下のような現在の画素位置を0.0-1.0に正規化するコードなどがそのまま使えます。

``` glsl
vec2 p = (gl_FragCoord.xy * 2.0 - iResolution) / min(iResolution.x, iResolution.y);
```

これでShaderToyのようなシェーダーアートができますね。

GLSL TOPのドキュメントはこちら。
ノイズ関数など便利機能が用意されています。
https://www.derivative.ca/wiki099/index.php?title=Write_a_GLSL_TOP

## GLSL MAT で書く
`GLSL TOP`ではFragment Shaderしか書けないのですが、Vertex Shaderやサーフェイスシェーダを書く場合は `GLSL MAT` を使います。
が、イチからシェーダを書くのは大変なので簡単な方法を紹介しておきます。

`Phong MAT` もしくは `PBR MAT` を配置します。
次に、配置したオペレータの `Parametors -> RGB -> Output Shader` の `Output` をクリックします。
<img width="472" alt="td_output_shader.png" src="https://qiita-image-store.s3.amazonaws.com/0/972/bdf2854e-7523-ea99-471c-1d52c60ebd1a.png">

すると、シェーダコードが出力されるので、これをベースにお好みに修正してくとよいです。
<img width="574" alt="td_glsl_mat_phong.png" src="https://qiita-image-store.s3.amazonaws.com/0/972/58faee47-700d-a3d8-d436-ddde89004cfb.png">

更に詳しい情報はGLSL MATのドキュメントで得られるでしょう。
https://www.derivative.ca/wiki099/index.php?title=Write_a_GLSL_Material
変数のビット配列をみるコード

#変数のビット配列を見てみたいと思い書いた。

[書いてみたコードonGist](https://gist.github.com/trickre/5c6a32846675f965cfb4101532eceeb2)

``` C:print_bits.c(主要関数部)
#include <stdio.h>

void printbits(unsigned char v) {
        int i; // for C89 compatability
        for(i = 7; i >= 0; i--) putchar('0' + ((v >> i) & 1));
}

void printbits_int(int v) {//for 32bit variable
        int i,j;
        for(i=8*sizeof(int)-1; i >= 0; ) {
                for(j=4; j>0; j--) {
                        putchar('0' + ((v >> i) & 1));
                        i--;
                }
                putchar(' ');
        }
}
```

``` bash:実行結果
$ gcc print_bits.c -o printbits
$ ls
printbit.exe  printbits.c
$ ./printbit.exe
This program enable you to see bit of variable.
Ener one character you want see its bit(= ascii code).
R
01010010
Ener variable(int) you want see its bit.
43690
1010 1010 1010 1010

```

##しくみ
###1.ビットシフトで1ビットずつビットAND演算
変数vの中身を一番左端から0なのか1なのか見ていきます。

ビットの中身が0なら((v >> i) & 1)は0b00...000(=0)に、1なら0b00..001(=1)になります。（「0b」はビット表現の意味です。）

``` C
//char v='z' z=0b01111010
((v >> 7) & 0b00000001)//=0 先頭ビットは0
((v >> 6) & 0b00000001)//=1 次のビットは1
...
```

###2.「0」の文字コードに0か1を加えて「0」か「1」を出力
putchar('0')で当然0を出力するわけですが、その'0'に1を加えると'1'を表す文字コードになることを利用します。

``` C
putchar('0' + 1);//"1"
putchar('0' + 0);//"0"
putchar('a' + 1);//"b"

```
PHPエンジニアならComposerが速いほうが良いに決まってるよね

PHPエンジニアはよく利用するであろう Composer ですが、ちょっと遅い。インストール・アップデートで待ってる時間にちょっとブラウザに行ってしまってそのままネットサーフィンが始まってしまうという経験がある人も多いのではないかと思うのですが、そんな時は Composer を速くすると良いです。

光の速さと戦い続けている @Hiraku 先生の努力の結晶で Composer 高速化を活用すると PHP 開発が捗りますよ！


## packagist.jp

まずは、Packagist の URL にミラーサーバーを設定して、物理的に Packagist との距離を縮めます。

```bash
composer config -g repositories.packagist composer https://packagist.jp
```

### 参照

* [packagist.orgのミラーサーバを立ててcomposer updateを18倍速くする #packagist - Qiita](https://qiita.com/Hiraku/items/51961aa49f7a2922011d)


## prestissimo

さらに、パッケージのダウンロードを並列で行うことで、ダウンロードにかかる時間を短縮します。

```bash
composer global require hirak/prestissimo
```

### 参照

* [composerを速くするプラグイン・prestissimoを作った: Architect Note](http://blog.tojiru.net/article/432944706.html)
* [hirak/prestissimo: composer parallel install plugin](https://github.com/hirak/prestissimo)
数十万セルのテーブルをサクサク表示する

## 巨大なテーブル要素を素早く描画する方法

私は普段BIツールのWebUIを開発していますが、BIツールというのは大量のデータをビジュアライズする必要があるので、何も考えずに描画するとすぐブラウザが固まってしまいます。

この記事では、そんなBIツールの中で数十万セルのテーブルをサクサク表示するために行っている工夫について説明します。

## まずはベタに実装するとどうなるか

![集計表.png](https://qiita-image-store.s3.amazonaws.com/0/92696/5482eb91-531f-78d0-436b-e2ceacb77001.png)

こちらがBIツールで表示している表です。固定ヘッダーの表になっていて、白の値セルのあたりをスクロールしてもヘッダーが隠れないようにしてあります。
このスクロールの実装のために下のようにdivで分割しています。

![集計表の要素構成.png](https://qiita-image-store.s3.amazonaws.com/0/92696/14ac9b66-19be-6648-d24f-ebdd5e5af914.png)

この中にそれぞれtable要素を配置しており、右下の値セルのスクロールを行うと、上左のヘッダー部も連動してスクロールするようになっています。

さて、これを特に何も考えずにベタに実装し、縦1000セル、横250セルくらいのテーブルを表示させると、まあFirefoxとChromeは2秒程度で出してくれますが、スクロールはまともにできませんし、IEだと初期表示だけでも9秒程度掛かります。
BIツールのダッシュボードに表示する表はこれ一枚ではないので、ページをすべて表示するのに十秒以上掛かるようなことになってしまいます。

## 早くする

本来ならちゃんと測ってからとなりますが、まあ今回遅いのは追加するノード数が大きすぎなのは自明なのでサクッとノード数を減らします。

![集計表の要素構成.png](https://qiita-image-store.s3.amazonaws.com/0/92696/14ac9b66-19be-6648-d24f-ebdd5e5af914.png)

この図は先ほどのdivの構成ですが、ヘッダーと値セルのtableは実態は数十万ありますが、実際に画面描画する時に必要なのは、この見えている範囲の数えられる程度の要素です。
不要なものを描画しなければサクッと表示できるサイズになります。

というわけで見えてる範囲で切り出して描画するように変えます。

![63c6102d-1c75-76a7-3ebf-1d357540a4ee.png](https://qiita-image-store.s3.amazonaws.com/0/92696/71893446-c447-1e66-77bb-fd164b1c3cb7.png)

これで2秒程度掛かってた描画が100msくらいまで早くなりました。

## スクロール

さて、次はスクロールです。見えている範囲に切り抜いて表示しているので、スクロールする際には当然移動した先の要素に書き換えてやらねばいけません。
ブラウザのスクロールは極力そのまま使いたいため、tableの外側に真の表のサイズのdivを配置し、スクロール量に合わせて描画位置を移動させながらテーブルを作り直します。

![集計表ずらす.png](https://qiita-image-store.s3.amazonaws.com/0/92696/419d338f-99c1-a72c-df2d-58cbdc657043.png)

さすがに60FPSでなめらかスクロールとはいきませんが、まあ実用上問題ない程度のスピードは出ます。

このような感じで巨大なtableをサクサク表示させています。

## 終わりに

ちょっとしたリスト表示のためにtableを使っている時でも気を抜くと要素数が大きくなり表示やスクロールが途端に大きくなってしまいます。
そんな時、ページングできればもっと簡単ですが、それが難しい時にはこのように描画ノードを絞って表示すると高速に表示できるようになります。
TypeScript用ORMapper「typeorm」を試してみる


## 概要
typeormはTypeScriptで記述できるORMapperライブラリ。
mysql, postgresql, mongodbなど主要なRDBMSやNoSqlをサポートしてる。
mongoとmysqlを使ってみたのでその記録。

## Githubリポジトリ
* [typeorm](https://github.com/typeorm/typeorm)

## 設定
ormconfig.json (拡張子は色々と変更できる)にて、各データベースの設定を記述する。connectionを作成する際、引数を指定する事により指定データベース情報を取得できる。
**※ ormconfig.json内の#はコメントアウトだと思ってください**

```ormconfig.json
# 複数指定する場合は配列で定義する。entities配下を検索するため、その中にEntityが存在しないとエラーになる。
{
  "name": "default",
  "type": "mysql",
  "host": "localhost",
  "port": 3306,
  "username": "test",
  "password": "test",
  "database": "test",
  "synchronize": true, # このパラメータをtrueにするとAlter Tableが走る...。
  "logging": false,
  "entities": [
    "src/entity/*.js"
  ],
  "subscribers": [
    "src/subscriber/*.js"
  ],
  "migrations": [
    "src/migration/*.js"
  ],
  "cli": {
    "entitiesDir": "src/entity",
    "migrationsDir": "src/migration",
    "subscribersDir": "src/subscriber"
  }
}
```

## mongodb編
mongodbを使用するには`npm install mongodb --save`
公式リポジトリにある[sample](https://github.com/typeorm/typeorm/tree/master/sample)を見るとわかるが、mongodbのEntity作成方法はmysqlなどとは異なるので注意。

```mongo-sample.ts
import "reflect-metadata";
import {createConnection} from "typeorm";

createConnection().then(async connection => {
    const channel: TChannel = new TChannel();
    channel.channelId = "1111";
    channel.name = "世界部屋";
    channel.description = "全体チャット";
    channel.ownerId = "";
    channel.isDismiss = false;
    channel.maxMember = 10000;

    await connection.mongoManager.save(channel);
});
```

## mysql編
mysqlを使用するには、`npm install mysql --save`でmysql-driverをインストールする必要がある。
`ormconfig.json`の`"synchronize": true,`を設定するとEntityに設定したデコレーターと同期してしまう模様。AlterTableが勝手に走ってしまったので注意。

```sample.ts
import "reflect-metadata";
import {Column, createConnection, getConnectionOptions, PrimaryGeneratedColumn, Entity} from "typeorm";

@Entity()
export class Users {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @Column({
        unique: true,
    })
    email: string;

    @Column()
    password: string;

    @Column()
    remember_token: string;

    @Column()
    created_at: string;

    @Column()
    updated_at: string;
}

async function testConnect() {
    const option = await getConnectionOptions('rdbms');
    const dbCon = await createConnection(option);
    const res = await dbCon.getRepository(Users).findOne({id: 1});
    console.log(res); // Users {id: 1,name: 'oh',email: 'taylor@example.com', password: ''}
}

testConnect();
```
2017年のお気に入り紹介！《Unityアプリの通信用サーバを簡単にたてる＋JekyllでWEBサイト運営》

こんにちは、はじめまして！
Geek Women Japan Advent Calendar 2017に参加させていただきます、yuriと申します。

女性エンジニアの集まりに参加したいー！と思いつつなかなかタイミングが合わず、、ピンポイントで参加する程度だったのですがちょうどカレンダーがまだ埋まっていなかったのでこれを機に！と参加させていただきました:relaxed:　はじめましての方も多いので最後に自己紹介をおいておきます！

今回は、2017年を振り返ってよく使っていて便利だったなー気に入ったなーと感じているものを２つ紹介してみます。同じような活用シーンがありましたら是非使ってみてください。
うまくいかないよ〜という時はTwitterなどで声をかけていただければ何かしらお手伝いができるかもしれません:laughing:


# １）Unityアプリの通信用サーバを簡単にたてる

## なんとかしたかった状況

* Unityで作ったアプリ（GearVRアプリ）の情報を通信して別のアプリ（AndroidアプリやPC）に利用したい、連携したい
* インターネット環境が使えない場所でも利用したかったので、外のインターネットに出ずに解決したい（特定のルーターに繋がってる端末同士のみでやりとりできるようにしたい）

##　やったこと

* 難しいこと考えず、ひとまずチャットで情報をやりとりしよう！→socket.ioを利用する https://socket.io/
* socket.ioサーバ側はMacとかラズパイとかを特定のルーターに繋げて起動する
* Unityアプリ（GearVR）はsocket.ioサーバのクライアント側として動かす。サーバと同じルーターに繋いでおく

##　使ってよかったポイント

* 海外に持っていってもパケ死を怖がらないでデモできる（手元に連携させたいものがすべてある特殊な状態ですが）
* socket.ioは `npm install socket.io` とかでさくっとはじめられる 
* Unity側はアセットもあるので簡単！ ＞ https://assetstore.unity.com/packages/tools/network/socket-io-for-unity-21721
* とりあえずの色々なものの連携に引き続き使いたい、ので最新のバージョンでちょっと動かしてみます

## サンプル

こちらはサンプルになる部分のコードを公開が、間に合いませんでした・・・！（クリスマスまでには駆け込み追記がんばります:cry:）


# ２）JekyllでWEBサイト運営

## なんとかしたかった状況

* 簡単にWEBサイトを運営したい
* 日英とか言語対応したい
* お知らせ的なものはちょいちょい更新したい
* リリース簡単にしたい

## やったこと

* Github Pages[ https://pages.github.com/ ]を利用する
* Jekyll[ https://jekyllrb-ja.github.io/ ]で色々いじる

## 使ってよかったポイント

* githubが使える人なら、リリースがとても楽。プルリク作ってマージするだけ。
* 複数のブランチにリリースしたいものを準備しておける
* githubで差分チェックも簡単
* 意外とJekyllのfor文とか、ymlファイルとかが使える
* パズルみたいにパーツ分けして組み合わせていけるのでなんか楽しい！


## こんな工夫をして活用をすると便利でした

- 基本的にGithubはprivateなリポジトリを利用しているのでネタバレはされない前提です
- いざとなったらGithub上（Webブラウザだけ）でなおしてリリースまでできちゃうので、ネットワークに繋がるパソコンがあればWEBページの更新ができます
- 本番環境用の他に、開発用、ローカル用のymlファイルを準備して、開発環境で起動するときには引数でそのymlをわたして起動する
 - 起動コマンド `jekyll serve --config _config.yml,_config-local.yml` とすると、`_config.yml`を優先に読み込んで、`_config-local.yml`にかいたもので上書きするような動きをしてくれます。なので基本は本番環境用の`_config.yml`を作成し、必要な場所にだけ`_config-local.yml`を作るとらくでした！（例えばGoogleAnalyticeのIDとか、環境別に変えたいもの）
- 静的サイトだけど、別の言語版を作りたい、、けどほぼ同じHTML作るとメンテがつらいというときにもincludeとかでhtmlのタグ自体はテンプレートっぽく書いて、テキストは別管理ができて便利です！

## サンプル

- https://github.com/71713/hello-ghpages

----

2017年で使い込んでいたものの、紹介できていない要素があるな〜とあらためて感じたので、また自分のやったことの整理も含めQiitaも書いていこうと思います。今回の情報は概要だけとなっていて、実際にはじめてみようかなという人には足りないレベルかと思いますので、そのあたりも少しアップデートしてみます。

それでは、貴重な１枠をありがとうございました！！そろそろ後半戦ですね、引き続き楽しみにしております！

----

### さいごに自己紹介

リコーITソリューションズという会社でシステムエンジニアを7年くらい？しています。
スマホアプリやWEBアプリに関わっていることが多く、最近はUnityなどを使って~~遊んだり~~VRの仕事をはじめたりしています。そのため、VR系の集まりやUnityの集まりでお会いしたことがあるかたもいるかもしれません・・・！

Geek Women Japanさんの新年会に顔を出す予定なので、ぜひよろしくお願いします！
エンジニアが知っておくとちょっと幸せになれるかもしれないビジネスモデルの話

@mkataigi です。PLAID Advent Calendarの14日目は先日に引き続きコードが出てこないお話です。いいサービスは利用者の課題を解決できるサービスですが、あなたはどのくらい利用者のことを知ってますか？

弊社のKARTEはB2BのSaaSサービスになります。そのため、KARTEを利用してくださっている企業がどのようなビジネスをしているかを理解することがとても大事になってきます。ビジネスモデルはそれこそ会社の数と同じだけあるのですが、今回は大雑把に分けて「耐久財」モデルと「消費財」モデルで考えて見たいと思います。


# 耐久財モデル

耐久財というのは、「１度購入したら長期間所持し続ける製品」です。家とか車とかがその代表になります。PCや家電なども入りますね。耐久財には以下のような特徴があります。

- 長期間所持し続けるため、買うタイミングは数年から数十年に一回
- 基本的には値段が高い

例えば自分で冷蔵庫を買った時を思い出してください。買うまでにどんな行動をしました？一般的には次のような行動をすると言われています。

1. 欲しくなってから情報を調べ始める
1. まずは大雑把にどんな種類の冷蔵庫があるかを調べる
1. 主なメーカーと製品を調べる。またその製品について比較サイトやレビューサイトを読んでざっくりと情報を集める
1. ２〜３の製品に絞り込む
1. 絞り込んだ製品をより詳細に調べて、購入するものを決める（ここは家電量販店に行く人も多い）

ちなみに、よくAISASと呼ばれるモデルになります。ここでのポイントは、ユーザーは比較的長期間しっかり製品の検討をする、という点です。この検討期間にいかに「他社の検討をさせないか」が大事です。耐久財のビジネス戦略は大きく次の、「購入」モデルと「アフターケア」モデルになります。

### 購入モデル

これは特に説明不要かと思いますが、製品を買ってもらって売り上げをあげるモデルです。このモデルで重要になってくるのは、「製品の買い替え」タイミングです。

検討期間が長く金額も高く、ユーザーがちゃんと検討するため、別のブランドの製品を買う可能性が（次に説明する消費財モデルに比べると）高くなるので、いかにユーザーをつなぎとめておくか、が重要になってきます。N年縛りとか、古い製品を下取り、などはこのつなぎとめ戦略の一つですね。

### アフターケアモデル

もう一つが製品自体は安価に買ってもらった後にアフターケアで稼ぐモデルになります。多くの場合は「補完財」と言われる、別製品を高く売ることによって長期的に稼いで行くモデルになります。

- コーヒーメーカーは格安で提供してコーヒーポーションを継続的に売る
- スマートスピーカーを格安で提供して自社サービスを使ってもらう
- OSを格安で提供して、アプリケーションソフトウェアを売る

このモデルの場合、製品とその補完財はセットで提供されることになるので、製品の市場シェアを高めることが非常に重要になってきます。タダみたいな値段で製品を提供しているのはこの市場シェアを奪いに行く戦略になります。


# 消費財モデル

消費財というのは、食料品とか消耗品のような「定期的に購入し続ける」商品のことを言います。洗剤やノートなどがその代表になります。消費財には次のような特徴があります。

- 定期的に買う
- 基本的には値段は安い

例えば、洗剤を買った時を思い出してください。買うまでにどんなことを考えましたか？

1. 洗剤が切れたのでスーパーに行く
2. 商品の陳列を見る
3. 一番お気に入りの洗剤は定価だが、二番目によく使う洗剤は割引中だった
4. 二番目によく使う洗剤を買った

自分の行動を考えてもらえれば、消費財の場合はほぼ検討をしないで買っている、ということが思い出せるかと思います。実際、既に知っている商品を継続して買いやすい、という特徴があります。そのため、消費財の場合のポイントは、「いかにユーザーに刷り込んでおくか」が大事です。消費財のビジネス戦略は大きく次の「棚割」モデルと「サンプル」モデルになります。

### 棚割モデル

ユーザーが検討しないで買うのであれば、重要になるタッチポイントは次の２点になります。一つ目はまず「ユーザーが知っている商品リスト」に入ること。知らない商品は手に取ってくれません。２つ目が買う直前、つまり商品を「棚からとる瞬間」になります。いかに棚割で良い場所、目立つ場所を使えるかが大きな意味を持ちます。

ところでこの棚割がどのように決められるかですが、商店側も売れるものを売りたい、という希望があります。では売れる商品とは何かというと、棚割以外で考えると結局「ユーザーが知っている商品」というのがよく売れる、ことになります。つまり棚割を抑える上でも結局はこの「ユーザーに知ってもらう」ことを考えていくことになります。一昔前だと、みのさんが取り上げたら商品がバカ売れする、というのはみのさんが紹介すると売れるので商店も積極的に棚を割くため、知名度と棚割の相乗効果で売り上げが上がっていたようです。インフルエンサーの強みが活かされる部分ですね。

### サンプルモデル

消費財のもう一つの戦略が「サンプル」モデルです。テレビCMなどで知名度をあげるのも重要なのですが、ユーザーの知っている商品リストに入る上でもっとも重要なのは実は「その商品を使ったことがあるか」だったりします。このモデルでは、タダもしくは低価格で一度使ってもらうことで、ユーザーの知っている商品リストに入ってしまおう、という戦略です。タダだったら多少怪しくても使ってみようかな、って人多いんじゃないでしょうか。

- 最初の１つは割引で売るテレビショッピング
- 店頭で商品サンプルを配る洗剤
- スーパーのソーセージの試食

棚割モデルではどうしても既存の知名度の影響が大きいため、新商品の場合はこのサンプルモデルから試してみることが多いようです。（流通量を制御しやすいということもあるかと思います）


# まとめ

いくつかのビジネスモデルについて見て見ました。我々が提供しているようなSaaSでは、この中の「どの部分をサポートしてあげられるか」を考えていくのが、プロダクトのビジネスモデルになってきます。
【ethereumjs-tx】署名付きトランザクションデータ作成【Ethereum】

## ブラウザベースのethereumjs-txを使うメモ

ethereumjs-tx読み込み

```html
<script src="ethereumjs-tx-1.3.3.min.js" type="text/javascript"></script>
```

ブラウザベースではグローバル変数 <font color="red">ethereumjs</font> を使う(EthJSでなく)

ex.

```javascript
function createRawTxData(nonce,gasPrice,gasLimit,to,value,data,privateKey) {
  
    var rawTx = {};
    
    rawTx['nonce'] = nonce;
    rawTx['gasPrice'] = gasPrice;
    rawTx['gasLimit'] = gasLimit;
    rawTx['to'] = to;
    rawTx['value'] = value;
    rawTx['data'] = data;
    
    var tx = new ethereumjs.Tx(rawTx);

    // Buffer.Buffer はタイポでないです
    var pk = new ethereumjs.Buffer.Buffer(privateKey, 'hex');

    tx.sign(pk);
    
    return tx.serialize().toString('hex');

    // output
    // 0xf86180820834820a9694a813cb047ffd55848bed64bf8cbaa325b4ea620780802ba025d4323cb9564aab68be0ca3b26b195c26d5b0a0bd0a5c774786e2684e242840a03b0ed69cf748bc7f3e3aacda668fbf7eef6c1f662eb71fc61fe7ab70b76c817d
}
```

github: [ethereumjs-tx(browser-builds)](https://github.com/ethereumjs/browser-builds)
cf(Stack Over Flow). [how to use ethereumjs-tx.js in a browser](https://ethereum.stackexchange.com/questions/8579/how-to-use-ethereumjs-tx-js-in-a-browser)
Macユーザー向け使えるショートカット集10選

# こんにちは
株式会社diffeasyでエンジニアをしている政栄（まさえ）といいます。
技術力は乏しいのですが、ショートカットキーを覚えることは大好きです！！

# この記事の目的
- ショートカットキーとかに興味のない人にショートカットキーを好きになって欲しい。
- 覚えるのが大変そうと思っている人の意識を変えたい 

私が日常使っていて、気軽に使えるショートカットキーを**10個**だけ厳選して紹介します！
10個目はショートカットではなくジェスチャです。
たったの10個なので使ってみて下さい！！

# おすすめショートカット10選
macOS用となっています。

|1|「command」 + 「space」 | spotlight検索 |
|:-----------------|:-----------------|------------------:|

好きな場所でspotlight検索をすることでアプリ等を見つけやすくなります。
文字入力をしなければなりませんが、下記画像のように、[ch」だけでchromeが出たりと割りと使いやすいです。
<img src="https://qiita-image-store.s3.amazonaws.com/0/221884/c3ffa93f-582c-4b79-712c-cf1a1391dcdc.png" width=70%>

---

|2|Finder内で 「space」 | ファイルのプレビュー |
|:-----------------|:-----------------|------------------:|

わざわざ開かなくても「space」押すだけで中身見れます！
閉じるのも「space」押すだけ！
![ 2017-12-12 17.44.59.png](https://qiita-image-store.s3.amazonaws.com/0/221884/9dd11924-03c5-c8e2-d358-cdac552db22f.png)

---

|3|「command」 + 「shift」 + 「.」  | finder内の隠しファイルの表示非表示 |
|:-----------------|:----------------------------|--------------------------:|
隠しファイルの表示非表示を切り替えれます。

---

|4|「command」 + 「shift」 + 「3」  | 全体のスクリーンショット |
|:-----------------|:-----------------|------------------:|
画面全体のスクリーンショットをとることができます。

---

|5|「command」 + 「shift」 + 「4」  | 範囲選択式スクリーンショット |
|:-----------------|:-----------------|------------------:|
好きな範囲を選択してスクリーンショットをとれます。

---

|6|「command」 + 「shift」 + 「4」 + 「space」  | 画面選択式スクリーンショット |
|:-----------------|:-----------------|------------------:|
単一のアプリケーションを選んでスクリーンショットをとることができます。
spaceを押すことでカーソルがカメラアイコンになります。

4,5,6,のコマンドにcontrolキーをプラスして押すとクリップボードにスクリーンショットがコピーされます。

---

### 複数のアプリケーションで使えるもの
Finder,Chrome,Atom,Vscodeなど、多くのアプリケーションで使えます。

|7|「command」 + 「option」 + 「左」or「右」矢印キー  | タブの切替 |
|:-----------------|:-----------------|------------------:|

terminalは「command」 + 「Shift」 + 「左」or「右」矢印キーとなっています。

---

|8|「command」 + 「t」| 新規タブを開く |
|:-----------------|:-----------------|------------------:|

---

|9|「command」 + 「n」|  新規ウィンドウを開く|
|:-----------------|:-----------------|------------------:|

---

|10|トラックパッドのジェスチャを覚えること|
|:-----------------|:-----------------|
システム環境設定のトラックパッド内のその他のジェスチャにある７つは全部覚えて損しないです！！
![ 2017-12-12 18.16.08.png](https://qiita-image-store.s3.amazonaws.com/0/221884/dafa684e-750d-d512-75a1-372b0073f356.png)

10個目に7個ありますが、細かいことは気にしないでください。ジェスチャはジェスチャで1個みたいなものなので。

## Let's Try
Basic認証をかけるとfaviconが反映されないことがある

Basic認証をかけた環境で開発をしていて、しょうもないことで盛大にはまったことに対する備忘

#Basic認証を疑うこと
自分がweb開発をしているとき、iPhon端末にて、ホーム画面にブックマークを置くと表示される、faviconが反映されなかった状況があった。
原因はBasic認証にあったのだが、それには気づかず、1時間以上も悩むことになった。
どうやら、Basic認証をかけていると、faviconが正常に表示されないことがあるらしい。

[こちら](https://realfavicongenerator.net/favicon_checker#.Wi-ipFVl9hE)ではサイトのfaviconの状況を確認することができる。

また、Chromeを利用している場合、通常のキャッシュクリアではfaviconのキャッシュまでは削除されない。以下のディレクトリにfaviconのキャッシュが保存されているので、それを削除しよう。

```
C:\Users\ユーザー名\AppData\Local\Google\Chrome\User Data\Default
```

他に、画像や動画でも不具合が出るようなので、とりあえず表示されない問題が起きたら、Basic認証を疑ってみようと思う。
言葉の正規化に伴うURLの正規化

例えばブログシステム上で引っ越しに関する記事をいくつか書いたとする。
それぞれタグとして「引っ越し」を設定していたのだが、いつの間にかIMEで「引越」が優先して変換されるようになってしまっており、2パターンのタグURLができてしまった。

|パーマネントURL|記事名|タグ|タグURL|
|:--|:--|:--|:--|
|/post/1|荷造りの仕方|引っ越し|/tag/引っ越し|
|/post/2|役所への届け出|引っ越し|/tag/引っ越し|
|/post/3|お隣への挨拶|引越|/tag/引越|

タグテーブルの情報は以下のようになっている。

|ID|name|
|:--|:--|
|1|引っ越し|
|2|引越|

単純「引越」タグがついている投稿のタグを「引っ越し」に付け替えれば表示上は解決するのだが、それだとタグURL「/tag/引越」の方がNot Foundになってしまうので、できれば「/tag/引っ越し」にリダイレクトさせてやりたい。
なのでタグを廃止する仕組みを用意するためにテーブルにカラムを追加する。

|ID|name|normalized_id|
|:--|:--|:--|
|1|引っ越し|null|
|2|引越|1|

これで「/tag/引越」を「「/tag/引っ越し」にリダイレクトすることが可能になる。
またnormalized_idがセットされているタグが新規投稿に付与された場合は、それが非正規なタグであることを警告することも可能になるだろう。