OmniAICreator/Qiita-1.07M huggingface dataset:
[Swifty]カスタムセルを作る

<p>今回のテーマは、少し取り上げにくい。なんとか頑張ってみる。</p>

<p>カスタムセルの実装をMVVM (Model - View - ViewModel)でと説明されているが、ここがスムーズにいかない。</p>

<p>MVVMは、Microsoftの.Netフレームワーク側のWPF(Windows Presentation Foundation)やSilverlightの設計方法で、WindowsのXAMLでViewを構成する場合にあったやり方。なので、異なるフレームワークのCocoaでもあるし、MVCやモジュール化、関数化の流れの物だと思うので、わざわざ、Cocoaの世界でMVVMというのは。</p>

<p>MVVM化として説明されているのが、セルに値を設定するメソッド。</p>

<pre><code>class CardCell: UITableViewCell {
    @IBOutlet var titleLabel: UILabel?
 
    public func fillWith(card: Card) {
        titleLabel?.text = card.title
    }
}
</code></pre>

<p>セルの設定でビューコントローラのプロパティを使うのを避けたいという事のようだが、自分の場合は、Model（Dataコントローラ）を用意しているので、ちょっと状況が異なる。</p>

<p>これ以外に、自分の知らなかった、役立つ手法が紹介されていた。</p>

<p>先ずは、guard let。</p>

<pre><code>guard 条件節 else { /* breakやreturn */ }</code></pre>

<pre><code>func demo() -> Cell {
    guard let cell = crateCell else {
        fatalError("Could not create cell")
    }
    cell.setTitle("表題")
    return cell
}
</code></pre>

<p>Eiffel言語の事前条件のような利用を想定しているようで、ブロックの頭で、条件に合わない場合は弾く処理を記述するようの構文のようだ。</p>

<p>次は、subscript。</p>

<pre><code>class Hand {
    private var cards = [Card]()

    subscript(index: Int) -> Card {
        return cards[index]
    }
}
 
var card = Hand[0]
</code></pre>

<p>配列は辞書の添字の多重定義、といったところか。例の場合は分かりにくくなっているが、C言語のマクロで簡素化していたコードなどをこれで置き換えることができそうだ。</p>

ソースコード
GitHubからどうぞ。<br />
<a href="https://github.com/murakami/workbook/tree/master/ios/Hand">https://github.com/murakami/workbook/tree/master/ios/Hand</a> - GitHub<br />

関連情報
<a href="https://realm.io/jp/news/tryswift-daniel-steinberg-blending-cultures/">文化を調和させる</a><br />

【Cocoa練習帳】
<a href="http://www.bitz.co.jp/weblog/">http://www.bitz.co.jp/weblog/</a><br />
<a href="http://ameblo.jp/bitz/">http://ameblo.jp/bitz/</a>（ミラー・サイト）<br />
<a href="https://t.co/6P3h2jtbRk</a>note<br />
CS開発ってなーに？

[mixiグループ Advent Calendar 2016](http://qiita.com/advent-calendar/2016/mixi) の10日目の記事です。


？？ 「グアアアア！！」 
@manji602 「？？がやられたようだな…」 
@otoyo 「フフフ…奴は四天王の中でも最弱のポエマー…」 
@upscent 「CS開発ポエマーのツラ汚しよ…」 

[5日目](http://qiita.com/otoyo/items/964b2e4731306263ef11)の @otoyo さんに引き続き、XFLAG CS部門開発チームからの3人目の刺客、 @upscent もポエムをお送りいたします！

CS部門で開発チームをもっている会社は少ないようで、なかなかCS開発と言ってもどういうことをやっているのかイメージが湧きづらいところです。
そこで、我々CS開発メンバーが日々どんな業務を行っているのかをまとめてみます。
(自分が社外の方に聞かれたとき用のカンペ代わりに・・・^q^)

# 管理ツールの開発・運用
問い合わせ対応をするオペレータが、ユーザ様のサービス利用状況を確認したり、必要に応じてデータを操作するためのツールです。
管理ツールの立ち上げから、運用・保守までをCS開発が行います。

**立ち上げ**
アプリケーション開発、インフラの整備をまるっと対応します。
インフラ周りは、AWSでのEC2インスタンスの立ち上げやデプロイ環境の整備などです。
開発言語・フレームワークはサービスで利用しているものに依存するため(そのほうがメンテナンスコストが低いので)、様々です。

**運用・保守**
サービスのバージョンアップに伴う機能追加や、オペレータから要望を吸い上げて機能改修などを行います。
後者の機能改修というのが結構重要で、ちょっとしたUI改修でも思った以上にオペレータの作業効率に直に影響があります。定期的にやることで、オペレータの作業効率が上がり、そうするとユーザ様への返答も早くできてみんなハッピーになれます😊

# 問い合わせ内容に関する調査

問い合わせ対応時に、管理ツールで確認できない項目がある場合、CS開発に調査依頼がきます。調査依頼が来るのは以下のようなケースです。

**管理ツールでは見られないデータを確認したい場合**
管理ツールに表示していないデータや、アクセスログ、アプリケーションログなどを確認し、ユーザ様の利用履歴を確認します。
調査依頼の頻度が高ければ、DBに乗っているデータは管理ツールで表示できるよう機能開発をします。

**不具合のご報告を頂いた場合**
申告の不具合が発生する可能性があるかコードを確認します。不具合であった場合、サーバ側のみの修正であれば軽微な修正であればCS開発で修正を行います。クライアント側の修正や仕様の調整などが必要であればサービス開発者に修正依頼をします。

# 問い合わせサイトの運用・保守

CS開発で唯一ユーザ様に見えるコンテンツの開発です。
お問い合わせにお答えするために必要な情報を入力していただけるよう、フォームの調整を行います。入力不備などがあり問診を挟むと、問題解決までの時間を要するため、フォームの調整も重要なところです。
また、ユーザIDやOS名などアプリケーションから取ってこられる情報は、アプリから問い合わせサイトを開いた場合には自動で入力されるようにするなど、なるべくユーザ様の問い合わせの負担を減らすようにしています。

# 健全化対応のためのツール開発

データ改ざん等で有利に進行を進めるなどの不正行為への対応もCSで行っています。
そう、**彼らがかの有名なモンストポリスです。略してモンポリです。**
(※モンスト以外の対応もやってますがゴロが良いのでこう呼んでいます)

もちろんサービス開発者側でも不正行為を防ぐために日々対策は講じていますが、いたちごっこになっているため事後対応も欠かせません。
モンポリでは、事後対応として、不正行為を繰り返し行なっている悪質な業者等に対してアカウントの利用停止を行っています。また、不正行為であることを理解していないユーザ様に対する啓蒙活動も行っています。
これらの対応を行うためのツールもCS開発で開発しています。

# おわりに

初Qiita投稿がまさかの業務紹介ポエムでした＾＾
今度はポエムタグの付かない・・・記事を書きたい・・・です・・・・・(ﾊﾞﾀｯ

次は @natsu1211 さんが書いてくださるようです！お楽しみにmm
コンソールで動くエディタを作る(10日目) カーソル位置の編集その１

本稿は[自作エディタをつくる Advent Calendar 2016](http://qiita.com/advent-calendar/2016/make_editor)の10日目です、レポジトリは[こちら](https://github.com/tinyco/tiny_code_editor)

更新遅れました・・・。言い訳ですが、今日は私用があり殆ど進んでません。明日頑張ります！

# 色々な人のコメントについて

とてもありがたいです！

ずっと疑問に思っているのは、なぜみなさんこんなに文字コードに詳しいんだろう、ということで
オススメの本や資料等があれば教えて欲しいです。
個別のわからないことは、みなさんのご指摘で僅かながら理解が進むのですが、文字コードの全体像みたいなものが見えないなと思っています。
体系だって理解できていないというか。

それとは別に、文字コードに詳しくなるきっかけってなんだろう、とか思ったりします。仕事上で重要になる業界があるのでしょうか。出版とか？

返事ができていないコメントもあるのですが、頂いた参考リンクを読み終え次第、返事します。

# 文字の挿入(途中)

とりあえず、ずっとやりたかった文字の挿入をできるようにしたいです。
前回まででカーソルを移動できるようになっているのですが、十字キーをハンドリングできていないので(u/d/l/rキーと、終了でeキーを使用している)
それ以外の文字を全て挿入できるようにしてみます。

再掲ですが

```
enum CommandType {NONE, UP, DOWN, LEFT, RIGHT, EXIT};

typedef struct _command {
  enum CommandType command_key;
  mbchar command_value;
} command;
```

いまキーボードの文字はこういう風にラップされていて、valueにutf8として1文字の、数バイトのcharがはいっています。
CommandTypeにInsertを加えて、カーソルの位置に文字を追加してみます。


# 行の取得

```
line* getLineHeadFromPositionY(text* head, unum position_y)//PUBLIC;
{
	unum i = position_y-1;
	text* current_text = head;
	while(i-- > 0 && current_text)
	{
		current_text = current_text->next;
	}
	if(current_text) return current_text->line;
	return NULL;
}
```

こんな感じに挿入したい行の先頭を取得しますが、カーソル移動・行の取得ともに折り返し行がまだ考慮できてないです。

また、開発時にデバッグ用のおまじないとして
`context->filename = (char*)(getLineHeadFromPositionY(context->text, context->cursor.position_y)->string); // TODO`
を書いたりしています。
自分のプログラムはコンソールをクリアしてしまうので、printfデバッグしようとしても消されてしまいます。
filenameはプログラムの行頭に表示する仕様(という名の現状動作)なので、そこに突っ込んでいますが
デバッグ用の仕組みを検討する必要がそろそろありそうですね。

# 今日のまとめ

- 文字挿入用に、カーソルの先頭行のポインタを検索できるようになりました

・・・進捗ダメです。
明日もゲームマーケットに行くので全然進まない気がします。申し訳ない。

昨日分に頂いたコメント(半角・全角の判別)は積み残しているので、やらないとですね。
文字コード周りの各種判定(後続文字判定含む)は、そこだけ切り出して別レポジトリにすると需要があったりするのでしょうか？
ないかな・・・。
[Swifty]mutatingを取り除く

<p>ClassからStructに変更すると、プロパティを変更するメソッドにはmutatingキーワードをつけなければいけない。参考にしている発表では、これが格好悪いのでつける必要がない方法を選択したい。それが関数型プログラミング。SwiftではCopy-On-Writeに実装されていものがあるので、コストを気にしなくてもという事のようだ。</p>

<pre><code>struct Deck {
    public func nextCard() -> Card {
        let card = Card()
        return card
    }
}
 
struct Hand {
    private let deck = Deck()
    private var cards = [Card]()
    
    public init(deck: Deck, cards: [Card]) {
        self.deck = deck
        self.cards = cards
    } }
</code></pre>

<p>Handのプロパティcardsにカードを追加する場合、プロパティに変更を加えるメソッドを用意するのではなくて、内容をコピーして、カードを追加されたハンドを生成して返す。それとハンドを差し替えればいいじゃないの、という考えだ。</p>

<pre><code>    private func insertCard(card: Card, at index: Int) -> Hand {
        var mutableCards = cards
        mutableCards.insert(card, at: index)
        return Hand(deck: deck, cards: mutableCards)
    }
</code></pre>

<p>これを利用すれば、新規カードの追加はこうなる。</p>

<pre><code>    public func addNewCard(at index: Int) -> Hand {
        return insertCard(card: deck.nextCard(), at: index)
    }
</code></pre>

<p>カードの削除はこうだ。</p>

<pre><code>    public func deleteCard(at index: Int) -> Hand {
        var mutableCards = cards
        mutableCards.remove(at: index)
        return Hand(deck: deck, cards: mutableCards)
    }
</code></pre>

<p>これらを組み合わせれば、カードの移動もこうなる。</p>

<pre><code>    public func moveCard(fromIndex: Int, toIndex: Int) -> Hand {
        return deleteCard(at: fromIndex).insertCard(card: cards[fromIndex], at: toIndex)
    }
</code></pre>

<p>単なる配列操作だが、美しさを取るか！君はどっちだ！</p>

ソースコード
GitHubからどうぞ。<br />
<a href="https://github.com/murakami/workbook/tree/master/ios/Hand">https://github.com/murakami/workbook/tree/master/ios/Hand</a> - GitHub<br />

関連情報
<a href="https://realm.io/jp/news/tryswift-daniel-steinberg-blending-cultures/">文化を調和させる</a><br />

【Cocoa練習帳】
<a href="http://www.bitz.co.jp/weblog/">http://www.bitz.co.jp/weblog/</a><br />
<a href="http://ameblo.jp/bitz/">http://ameblo.jp/bitz/</a>（ミラー・サイト）<br />
<a href="https://t.co/6P3h2jtbRk</a>note<br />
PlayFrameworkで二重サブミット対策

この記事は[PlayFramework(Java) Advent Calendar 2016](http://qiita.com/advent-calendar/2016/play_java)の記事です。

PlayFrameworkにはCSRF対策のアノテーションは存在しますが、
CSRF以外にも対応出来るようにしていきたいと思います。

そこで、二重サブミットに関してはとても参考になるのが[さいきょうの二重サブミット対策](http://qiita.com/syobochim/items/120109315f671918f28d)です。
この記事の中のトークンによるチェックの方式をPlayFrameworkでどのように実装するか書いていきます！！

## トークンの生成
トークンの要件は色々あると思いますが、今回は英数字の32文字のトークンを生成します。

```Java
public static String setToken(){
  String token = RandomStringUtils.randomAlphanumeric(32);
  Cache.set("token", token);
  return token;
}
```
Javaある乱数を生成してくれるクラスを用いて、生成したトークンをCacheに格納します！！

## トークンのチェック
生成したトークンはクライアント側でhidden属性で持たせといて、
サブミットした時に、Cacheに格納したトークンと確認をします。

```Java
public static Boolean isToken(String clientToken) {
  Boolean isToken = true;
  String cacheToken = (String) Cache.get("token");
  if (cacheToken == null || "".equals(cacheToken)) {
    isToken = false;
  } else {
    if (!cacheToken.equals(clientToken)) {
      isToken = false;
    }
  }
  Cache.remove("token");
  return isToken;
}
```
クライアントから返ってきたトークンと一致していればtrueを返して、
一致していなければfalseを返します。

これで、二重サブミットに対応出来ます！！
AWSアクセスキー作成

TerraformでAWSリソースの自動作成を行うためには、ACCESS_KEY_ID, SECRET_ACCESS_KEYが必要になります。事前準備として以下の手順が必須になります。

# 1. グループ作成
1.  AWSマネージメントコンソールに接続します。
2.  IAM コンソールにアクセスします。
3.  左ペインから[グループ]を選択します。
4.  画面上部から[新しいグループの作成]ボタンを押します。
5.  グループ名を入力して、画面下の[次のステップ]ボタンを押します。
6.  ポリシー名が一覧で表示されます。必要なポリシーを選択して[次のステップ]ボタンを押します。（複数選択可）
      ・AmazonRoute53FullAccess
      ・AmazonEC2FullAccess
      ・AmasonS3FullAccess    ...etc
      ※ ELBはEC2に含まれています。 ※ 間違ってたらコメントください。

7.  確認画面となります。問題なければそのまま[グループの作成]ボタンを押します。戻りたい場合には、[ポリシーの編集]をクリックしましょう。

# 2. ユーザー作成
1.  左ペインから[ユーザー]を選択ます。
2.  画面上部から[ユーザーを追加]ボタンを押します。
3.  ユーザー名を入力します。
4.  アクセスの種類では、[プログラムによるアクセス]を選択して、画面下の[次のステップ：アクセス権限]ボタンを押します。
5.  ユーザーをグループに追加します。「1.グループ作成」で作ったグループ名のチェックボックスをONにして[次のステップ：確認]ボタンを押します。
6.  [ユーザーの作成]ボタンを押します。

# 3. アクセスキーID、シークレットアクセスキーの確認
1.  アクセスキーIDが表示されているので、確認します。
2.  シークレットアクセスキーは、[表示]をクリックすることで表示させます。
3.  （必要であれば）[.csvのダウンロード]を押すことで、以下の内容が表示されたファイルをダウンロードできます。

      ・User name
      ・Password
      ・Access key ID
      ・Secret access key
※ シークレットアクセスキーは、作成時にしか確認できません。忘れた場合は、再度アクセスキーIDの再作成を実施します。

4.  [閉じる]ボタンを押して終了。
なんでimgの下に隙間が入るか問題の原因究明とその解決方法

## 今回シェアしたい問題点
濃いめの色の背景色をつけたdivタグにimgタグを挿入して、見るとなぜか下部にうっすらと線が入る問題がありました。その際に仕方なしに下の要素にネガティブマージンを効かせるなどして対応していたのですが、今回調べて原因がわかったので、そのことについて初心者向けにシェアしたいと思います。

## 具体例
例えば、こんな感じのコードを書くと、
`
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div style="background:#000">
    <img src="https://placehold.jp/150x150.png" alt="テスト画面">
  </div>
</body>
</html>
`
画像のように下に隙間ができてしまいます。

<img width="150" alt="c3925109109620d4054f545b62dda7ae.png" src="https://qiita-image-store.s3.amazonaws.com/0/87142/7fde1745-21d7-48e2-b7bc-20867c87ea59.png">

こちらのような現象について、原因がわからないまま周りのdivタグの高さを調整していたのですが、ようやく原因を突き止めました。次の章でご説明します。

## 現象の原因
原因はimgタグのvertical-alignでした。こちら、デフォルトでは、baselineになってしまっていました。これが原因でした([参考](https://w3g.jp/css/text/vertical-align))。そのためこちらの値をbaseline以外に変更してあげたら、問題は解決します。

具体的には以下のようにimgタグのstyleをmiddleやtopなどbaseline以外に設定してあげてください。

`
<img style="vertical-align:bottom" src="https://placehold.jp/150x150.png" alt="テスト画面">
`

そうすると、画像の下に隙間がなくなること確認できるかと思います。

## まとめ
今回はなんでimgの下に隙間が入るか問題の原因究明とその解決方法について記載しました。baselineという初期設定が悪さをしていた原因でした。また、この問題はimgタグに限らず、inline要素ならば、起こる問題です。「なんか隙間できるな」って思った際には、ぜひともこちらの方法お試しいただければ幸いです。
QStackedWidgetで、ウィジェットを切り替える方法

# はじめに
Qtを使って、ウィジェットの一部を動的に切り替える方法を探していたところ、QStackedWidgetを見つけたので、使い方を簡単にまとめます。

# QStackedWidgetの使い方
QStackedWidgetを使うには、`QStackedWidget`をインクルードする必要があります。

```cpp
#include <QStackedWidget>
```

`QStackedWidget`にウィジェットを追加して、特定のウィジェットを表示させるには、`addWidget(QWidget *widget)`と`setCurrentIndex(int index)`を使います。

```cpp
QWidget *page1 = new QWidget;
QWidget *page2 = new QWidget;

QStackedWidget *stackedWidget = new QStackedWidget;

// ウィジェットを追加して、そのインデックスを受け取る
int idx_page1 = stackedWidget->addWidget(page1);
int idx_page2 = stackedWidget->addWidget(page2);

// 表示したいウィジェットのインデックスをセット
stackedWidget->setCurrentIndex(idx_page1);
```

インデックスの他に、ウィジェットを指定することもできます。

```cpp
stackedWidget->setCurrentWidget(page1);
```

さらに詳しい解説は、公式のドキュメントを参照してください。
[Qt Documentation - QStackedWidget Class](http://doc.qt.io/qt-5/qstackedwidget.html)


# QtDesignerを使う場合

QtDesignerのウィジェットボックスにある、**Stacked Widget**がQStackedWidgetです。
![スクリーンショット 2016-12-10 18.24.55.png](https://qiita-image-store.s3.amazonaws.com/0/141789/6d1b925f-576b-7234-abbf-e642a62d5b1b.png)

配置すると、カラのページを二つ持ったQStackedWidgetができます。
これらのページを直接編集しても良いですし、表示させたいウィジェットを別で作成しておいて、ページを格上げすることもできます。
![スクリーンショット 2016-12-10 18.26.25.png](https://qiita-image-store.s3.amazonaws.com/0/141789/8c9cd5cd-e2ff-ce9f-f1fd-3ebdeeccea4d.png)

# QStackedWidgetを使ったサンプル

ページを進めたり、追加・削除ができるサンプルを、GitHubに上げておきました。
[GitHub - QStackedWidgetを使ったサンプル](https://github.com/tatsuteb/QStackedWidget_Sample)

# おわりに

QStackedWidgetを使えば、インストーラでよくある、次へを押して進んでいくようなアプリケーションや、モードに応じてウィジェットの一部が変わるようなアプリケーションを作れそうです。他にも便利な機能があると思うので、機会があればさらに探ってみたいと思います。また、使い方について、アドバイス等を頂けたらありがたいです。
GitHub Markdown + Tex記法で数式中に通常のローマン体の欧文を出す

GitHub Markdown + $\TeX$ 記法で数式を書く際に調べた事について覚書き
# 数式中に通常のローマン体の欧文を出したい

$$a_{ij}=0 \hspace{ 5pt }  \mathrm{for\ all} \hspace{ 5pt } i,j$$
のように $\mathrm{for\ all}$ を書きたい．

```lang:
$for all$
```
は $for\ all$ になってしまう．
# `\mathrm` を使う方法と `\textrm` を使う方法がある．

## `\mathrm` は数式用のローマン体フォント  

```
$\mathrm{for\ all}$
```
$\mathrm{for\ all}$

数式用フォントでは

```
$\mathrm{for all}$
```
と書いてもスペースが入らない．
$\mathrm{for all}$
スペースを入れるために `\` が必要．

## `\textrm` は本文用のローマン体フォント
```
$\textrm{for all}$
```
$\textrm{for all}$
***
### 参考文献
[1] 奥村 晴彦:『[LaTeX2ε美文書作成入門](http://amzn.to/2gvRWGK)』改訂第6版，技術評論社，2013，97頁．
***
よりスマートな方法があれば教えていただけると嬉しいです.
Androidでクリエイティブコーディング。


AndroidではOpenGLES2.0が使えるので、今回はスクリーンセーバーみたいなものを作って見たいと思います。まずはOpenGLのViewを表示するところまで。

## 環境
とりあえずは、手元にAndroid4.4のXperiaがあるので、この端末をターゲットにします。

開発環境

+ Android Studio 2.1
+ Android4.4 (確認用端末)

Android端末でOpenGLの情報はあまり多くはないですが、ほとんど変わっていないとおもうので、2.0〜6までほとんどかわらないのかなと。そう考えるとかなり広いバージョンで動作が保証できる可能性がありますね。(実際はそうでもないかもしれませんが...)


### コード解説
それでは、早速コーディングを進めます。Android Studioでプロジェクトを作ります。
OpenGLはGLSurfaceView、Renderer、描画オブジェクト、シェーダーの4つが必要になります。


### Viewを作る
OpenGLを利用するには、GLSurfaceViewの派生クラスが必要です。ここにOpenGLは描画するようです。


```java
import android.content.Context;
import android.opengl.GLSurfaceView;

public class GLView extends GLSurfaceView {

    /**
     * Constractor
     * @param context Context
     */
    public GLView(Context context) {
        super(context);
    }
}
```

### Activityを編集
メインのActivityでGLViewを作り、表示エリアに設定します。

```java
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.glView = new GLView(this
    setContentView(this.glView);
}
```


### Rendererを作成
Redererのクラスを作ります。かならずGLSurfaceView.Rendererを実装します。
いかが最低限の内容にになります。

```java
public class GLRenderer implements GLSurfaceView.Renderer {

    @Override
    public void onDrawFrame(GL10 gl) {

        GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // 画面をかならずここで指定した色でリフレッシュします。
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);　// とりあずは、これを記述しないといけないぐらいで良いです。

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {

    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    }
}
```

コンパイルすると、画面が真っ赤になると思います。ActivityでGLViewを作り、GLViewの内部でRendererが毎フレーム実行され、画面を真っ赤に描画しています。
とりあえずここまではつまづく要素はないと思いますが、OpenGL専門用語がわからない場合があると思います。とりあえずはこう言ったコードをかならず記述しなければいけない程度にとどめるのが良いと思います。興味があれば検索して調べてみるのも良いかと。

次回からゴリゴリ描画していきます。
QUICを使ったWebサーバを立ててみたい(導入編)

これは、[http2 Advent Calendar 2016](http://qiita.com/advent-calendar/2016/http2)の11日目の記事です。前日は @flano_yuki さんの投稿分でした。
導入編ということで、今回はHTTP/2とQUICについての簡単な概要でも書くことにします。

#はじめの前のおまけ
[これ](https://chrome.google.com/webstore/detail/http2-and-spdy-indicator/mpbpobfflnpcgagjijhmgnchggcjblin)は是非入れておきましょう。

# はじめに
昨年、HTTP/2が正式に[文書化](http://httpwg.org/specs/rfc7540.html)され、Web界隈では大きな話題となりました。
早くもChromeでは従来のSPDYを使った通信はすっかり封印され、
現在はHTTP/2またはQUICを使った通信がサポートされています。

そこで、HTTP/2とQUICについて、一旦おさらいしてみたいと思います。

# HTTP/2
元々はSPDY(スピーディ)という名前で、Googleを中心としたワーキンググループによって開発されていた、
従来のレガシーなHTTP通信を向上させるための新しい通信プロトコルです。

簡単に言えば、**実に16年以上前に規格の作られた**古くて遅いHTTPを、完全な後方互換性を保ったまま
現代っぽく改善しようとする試みの結果です。

ストリームの多重化やフロー制御などの概念を取り入れつつも、従来の規格を完全に包括するよう作られているため、
エンジニアサイドとしては導入のハードルがかなり低い規格となっているはずです。
強いて言えば、規格上ではなく実装上の問題として[TLSの導入が必須](https://blog.sakurasaku-labo.jp/http2-beginners/#index01-02)であるため、必然的にHTTPS化が必要である点は重要です。

[こちら](https://techblog.yahoo.co.jp/infrastructure/http2/introduction_to_http2/)や[こちら](http://www.seojapan.com/blog/everyone-moving-http2)などをご参照いただければ、より詳しく書かれているかと思います。

# HTTP/2の限界とQUIC開発の意味
さて、上記で説明したように、HTTP/2では非常にシームレスな環境移行ができ、確実にWebの高速化を見込めます。
しかしながら、高速化という観点において、HTTP/2には致命的な欠点が存在します。
それは、**TCPの上に成り立っている**ということです。

TCP/UDPはOSI参照モデルにおける第4層(トランスポート層)のプロトコルです。
知らんって人はググってください。

ものすごくざっくり説明すると

- TCPは遅いが、データのエラーチェック等を含み、データ到達の信頼性を重視したプロトコル
- UDPは速いが、データを100%の精度で届けることは保障されていないプロトコル

一般的に、メールやWeb閲覧においてはデータが確実に到達することが重視されます。Webページの内容が確実に届かないと、文字化けしてしまったり、あるいは予期せぬ動作を呼び込むことになるからです。
それにもかかわらずQUICはUDP上で実装されています(????)
どういうことなのかみてみましょう。

## QUICの立ち位置
QUICは、HTTP/2の高速化における限界を超える目的で開発されています。[Wikipedia](https://www.wikiwand.com/ja/HTTP/2)を引用すると
>TCPの改善はGoogleにとって長期的な目標であり、QUICの目的は独立したTCP接続と同等に近づけることだが、できるだけレイテンシを削減し（目標はラウンドトリップタイム無しの一般的な接続）とSPDY対応の推進で、もしQUICの機能が効果的に実証されたらTCPとTLSの後継バージョンに移行することができる。
>
>QUIC開発の動機の1つが、TCPにおけるシングルパケットの遅延がSPDYストリームの集合体全体でヘッド・オブ・ライン・ブロッキングを引き起こす事実であり、QUICでは多重化に対応することでストリームを1つだけ一時停止することができる。


図で説明すると以下のようなかんじです。
![tcp_udp_quic_http2_compared.png](https://qiita-image-store.s3.amazonaws.com/0/100275/58a39432-46f6-d82a-2c5e-2ea1c3ddadf9.png)
(引用元:　https://ma.ttias.be/googles-quic-protocol-moving-web-tcp-udp/)

つまり、QUICは厳密に言えばHTTP/2と同等のレイヤに位置するのではなく、UDP通信のもと、HTTP/2 APIによって渡されたリクエストをQUIC独自の規格でリクエストの処理、暗号化、エラーチェック等まで行いながら通信しているのです。
文字通り、従来の互換性を犠牲にしつつWebのさらなる高速化を計った新しいプロトコルであると言えます。

QUICはまだ実験段階である故、日本語のドキュメントもあまり充実しておらず、実装した例も多くはありません。
実際、QUICをサポートしているWebサーバは非常に少なく、[GWS](https://www.wikiwand.com/ja/%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB%E3%83%BB%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B5%E3%83%BC%E3%83%90)(Google独自のWebサーバ)や[Caddy](https://caddyserver.com/)くらいしか私は知りません。他にあれば教えてください！
ただし、QUICに対応している[リバースプロキシ](https://www.wikiwand.com/ja/%E3%83%AA%E3%83%90%E3%83%BC%E3%82%B9%E3%83%97%E3%83%AD%E3%82%AD%E3%82%B7)としては、[Dockerイメージ](https://hub.docker.com/r/devsisters/quic-reverse-proxy/)はあったりします。
しかしながら、nginx、Apache、h2oなどのメジャーなサーバは軒並み非対応の状態です。

次回の投稿(カレンダーの最後の方だと思います)では、Caddyをつかって実際にQUIC通信を行うサーバを立ててみるところまでやってみたいと思います。
クイックソートの考え方

#始めに
ネット上で解説しているクイックソートの実装がいまいちぴんと来なかったので、自分なりにまとめた記事をアップすることにします。
アルゴリズムの方針は関数型言語の解説でよく取り上げられる、要素の分解と再集約を採用し、Javaで実装してみてクイックソートの実装が命令型言語でどのくらい面倒くさいか確認して見ることにします
#クイックソートの考え方
例として、[6,1,8,5,9]という数字の集合のソートについて考えてみる
クイックソートを行う時、要素を分割する基準が必要になるが、ここではその基準に集合の1番目の要素を使うことにする
## リストの分解イメージ
![image](https://qiita-image-store.s3.amazonaws.com/0/136860/dc120638-53eb-c0c5-3de7-ddde0ead7ccc.png)

## 分解後のリストの集約のイメージ
![image](https://qiita-image-store.s3.amazonaws.com/0/136860/3905ab4a-2014-b7b8-e43b-3308f89ea1e7.png)


#実装コード

```Qsort.java
package test;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.List;

public class QSort {

	public static void main(String args[]){
		System.out.println(qsort(Arrays.asList(1,5,6,2,11,9,4)));
	}

	public static List<Integer> qsort(List<Integer>list){
		if(list.size()==1){
			//配列の含まれる要素が一つならば、再帰処理を抜ける
			return new ArrayList<Integer>(list) ;
		}else{
			//リスト内の要素を分割する処理を呼び出す
			Divive div = splitList(list);
			//分割後の配列を格納するリストを生成する
			List<Integer>newList = new ArrayList<Integer>();
			//小さい数の集合を再度、切り分けるために再帰処理を行う
			newList.addAll(qsort(div.leftList));
			//大きい数の集合を再度、切り分けるために再帰処理を行う
			newList.addAll(qsort(div.rightList));
			return newList ;
		}
	}

	//リストを分割する関数
	public static Divive splitList(List<Integer>list){
		int size =list.size();
		Divive div = new Divive();
		//要素数が二つの場合は、要素間の大小を比較して要素分割を行う
		if(size==2){
			if(list.get(0)<=list.get(1)){
				div.leftList.add(list.get(0))  ;
				div.rightList.add(list.get(1))  ;
			}else{
				div.leftList.add(list.get(1))  ;
				div.rightList.add(list.get(0))  ;
			}
			return div;
		}

		int pivot = list.get(0);
		List<Integer>smallIntList =new ArrayList<Integer>();
		List<Integer>largeIntList =new ArrayList<Integer>();
		//引数で与えられたリストを所定の基準に従って、小さい集合と大きい集合に分ける
		for(int i=0;i<size;i++){
			//基準より小さい数の集合を生成する
			if(pivot>=list.get(i))smallIntList.add(list.get(i));
			//基準より大きい数の集合を生成する
			if(pivot<list.get(size - 1- i))largeIntList.add(list.get(size - 1- i));
		}
		
		//小さい集合と引数で与えられたリストの引数が一致しない場合、分割したリストの組み合わせを呼び出し元に戻す
		if(smallIntList.size()!=list.size()){
			div.leftList.addAll(smallIntList);
			div.rightList.addAll(largeIntList);
		}
		//小さい集合と引数で与えられたリストの引数が一致する場合は基準となる数字が一番小さいので、
		//リストの一番左とそれ以外でリストを分割する
		else{
			Deque<Integer> que  = new ArrayDeque<Integer>(smallIntList);
			div.leftList.add(que.pop()) ;
			div.rightList.addAll(new ArrayList<Integer>(que))  ;
		}
		return div;
	}
	
	//Javaは戻り値に2値を設定できないため、分割後の集合を表すデータ構造を定義しておく必要がある
	static public class Divive{
		List<Integer>leftList =new ArrayList<Integer>();
		List<Integer>rightList =new ArrayList<Integer>();
	}
}
PYNQ-Z1を購入して動かしてみる

http://qiita.com/kazunori279/items/a9e97a4463cab7dda8b9
を見て面白そうと思ったので購入してみました。とりあえず動かすところまでを記録しておきます。

## 購入する
PYNQ-Z1ボードはDIGILENT社からから購入できます。初めて海外からの購入だったのでドキドキしていましたが、特に問題なく一週間ほどで届きました。電話での問い合わせ等もなかったので簡単な英語が読めさえすれば購入できると思います。

ボード以外で必要なものは

- micro SDカード
- LANケーブル
- micro usbでの充電ケーブル(スマホの充電ケーブルで十分でした)

です。


## 準備する
PYNQ-Z1ボードはFPGA+CPUが乗ったボードでLinuxが動きます。Linuxはmicro SDカードに記録して読み込みますので、まずはイメージを書き込む必要があります。イメージは
https://files.digilent.com/Products/PYNQ/pynq_z1_image_2016_09_14.zip
から入手できます。解凍するとイメージファイルになりますが、これをそのままmicro SDカードにコピーしても動きませんので下記の手順で書き込んでください。手順はOS X El Capitanのものです。

1. まずはmicro SDカードのデバイスファイル名を確認します。左上のりんごマークから「このMacについて」を選びます。次にシステムレポートを選択します。ハードウェア->USBを選択してmicro SDカードが刺さっているリーダのBSD名がデバイスファイルの名前なのでメモっておきましょう。
2. コマンドラインを開き以下のコマンドを実行してください

```shell
diskutil unmountDisk /dev/:デバイス名
sudo dd bs=1m if=path_of_your_image.img of=/dev/:デバイス名
```

数分ほどで書き込みが完了するので気長に待ちましょう。

## 起動する
http://pynq.readthedocs.io/en/latest/1_getting_started.html#setup-the-pynq-z1
の図を見ながら各ケーブル、micro SDカードを挿していきます。一番・二番のジャンパを変更するのを忘れないようにしましょう。準備ができたら電源を入れてください。数十秒ほどでLinuxが起動すると青と緑のLEDが光ります。

Linuxが起動するとJupyter notebookが自動起動するので接続してみましょう。ルータ経由で接続している場合、http://pynq:8080 で接続できるらしいのですが私の環境では接続することができませんでした。ルータの設定画面からPYNQ-Z1に払い出されたipが分かったのでipで接続すると無事にJupyter notebookの画面を表示させることができました(パスワードはxilinxです)。

この段階でJupyter nodebook上や直接sshで接続して色々遊ぶことができます。

## 参考URL
http://www.pynq.io/
http://store.digilentinc.com/pynq-z1-python-productivity-for-zynq/
http://pynq.readthedocs.io/en/latest/index.html
SurfaceViewを使用するために４

#はじめに
SurfaceViewのダブルバッファを使用して描画したとき
期待した描画結果となりませんでした。
そのときの失敗についてまとめました。

#事例
ダブルバッファをバッファA、バッファBとして動作を考えます。

手順1)バッファAに描画内容を設定する
手順2)バッファAの内容が画面に表示される
手順3)バッファBに描画内容を設定する
手順4)バッファBの内容が画面に表示される

描画用のメモリ領域が2つあるので、
バッファAとバッファBの内容は同じではありません。
そのため画面の一部を書き変える場合には注意が必要でした。

バッファAに対して行った変更はバッファBには反映されていません。
手順3ではバッファAに行った変更が反映された画面に対して、
画面を更新していると考えていたため、手順4では手順1と手順3の
内容が反映された画面が表示されると考えていました。

実際の結果は手順3で行った内容のみが反映された画面が表示されました。

![example.jpg](https://qiita-image-store.s3.amazonaws.com/0/148400/b32fede9-9c84-0cd4-e622-4e1e494b9f33.jpeg)

**手順1から手順4を繰り返していると**
**手順4で手順1と手順3の内容が反映された画面が表示されるようになります。**
**内部でバッファAとバッファBが同期している？ようです。**

#まとめ
温度を表示する折れ線グラフは大した描画をしていないので、
再描画するたびにSurfaceViewを全面書き変えています。

画面をビットマップ化してビットマップ上で書き変える方法に
することも検討した方がいいのかもと考えています。

以前は初めて画面を表示するとき同じ描画を２回行うことで、
この問題に対応しました。
DOMを拡張してみる

この記事は[J2complexed Advent Calendar 2016](http://qiita.com/advent-calendar/2016/j2complexed)の10日目です。

#DOMをprototypeで拡張してみよう

ArrayやObjectをprototypeで拡張してしまうとfor inループで意図しないメソッドが挙がってしまいました。（人これを、プロトタイプ汚染という）
参考：[プロトタイプ汚染とループ](http://uupaa.hatenablog.com/entry/2012/11/07/143947)

ですが、DOMのprototypeを精査するようなことはまずないので、DOMだけはprototypeで拡張してしまいましょう。[^but]
なお、ここではES5の記述でいきます。ES2015でもそのまま使えます。

##addClass,removeClassを実装
jQueryで頻出するメソッドです。
###addClass
```js
Element.prototype.addClass = function(classname) {
  if(classname == null || classname typeof classname !== "string") return this;
  var parse = classname.split(" "),
      len = parse.length;
  for(len;len--;) {
    this.classList.add(parse[len]);
  }
  return this;
};

var el = document.querySelector("#identify"); // <div id="identify"></div>
el.addClass("hoge"); // <div id="identify" class="hoge"></div>
```

###removeClass
```js
Element.prototype.removeClass = function(classname) {
  if(classname == null || classname typeof classname !== "string") return this;
  var parse = classname.split(" "),
      len = parse.length;
  for(len;len--;) {
    this.classList.remove(parse[len]);
  }
  return this;
};

var el = document.querySelector(".hoge"); // <div class="hoge foo bar"></div>
el.removeClass("foo"); // <div class="hoge bar"></div>
```

同じ要領で`hasClass`も作れます。
Elementに対して`addClass,hassClass`はぶっちゃけコードにもあるように`classList`を使えば済みます。
ですが、NodeListやHTMLCollectionそのものに`classList`はないのでループさせる必要があります。なのでNodeListに`addClass,removeClass`を拡張してしまうのが便利です。

##NodeListにaddClass,removeClassを実装
※Elementが拡張されてる前提のコードです。
###addClass
```js
NodeList.prototype.addClass = function(classname) {
  [].forEach.call(this, function(el) {
    el.addClass(classname);
  });
};

var div = document.querySelectorAll("div"); // [<div></div>, <div></div>];
div.addClass("hoge"); // [<div class="hoge"></div>,<div class="hoge"></div>];
```
###removeClass
```js
NodeList.prototype.addClass = function(classname) {
  [].forEach.call(this, function(el) {
    el.removeClass(classname);
  });
};

var div = document.querySelectorAll(".hoge"); // [<div class="hoge"></div>, <div class="hoge"></div>];
div.addClass("hoge"); // [<div></div>,<div></div>];
```

[^but]: ただし将来的に同じ名前のメソッドが実装された場合、それをオーバーライドしてしまうので注意です。
Bluemix で ClearDB MySQL Databaseを使ってみた

IBM ContainersのDockerコンテナでMySQLを立ち上げようと企んでいたのですが
systemdでサービスを起動させようとトライ中にdocker --privilegedでコンテナを立ち上げる必要があり、
googleセンセイに聞いたところ、共有インフラである以上、サポートしないよ。という回答があり、
あれ？これ記事成り立たなくなるんじゃ・・・とショゲていたのですが、

間違ってました。コンテナを目的とするんじゃなくて、
ゴールはbluemixを使ってゴニョゴニョすることだったので。

[Can IBM Containers run in privileged mode ( docker --privileged) ? ](https://developer.ibm.com/answers/questions/231457/can-ibm-containers-run-in-privileged-mode-docker-p.html)

## MySQL使ってみよう
### 1. カタログがからMySQLを探す
Bluemixカタログ画面の検索フィールドに「mysql」と入力して検索しました。
![image](https://qiita-image-store.s3.amazonaws.com/0/126158/f5e9bfc9-7cb8-0a7e-d859-59d806874485.png)

MySQLのSaaS用パッケージでClearDBという物が利用できるようです。

### 2. 利用プランの選択
プランが幾つかあるようですが、今回はFREE!バージョンを利用します。
![image](https://qiita-image-store.s3.amazonaws.com/0/126158/15debc10-d2bf-a01c-4e5d-e2b12f27f0c0.png)
作成ボタンをクリックして進みます。

### 3. CLEARDB MYSQL DATABASE ダッシュボードを開く
作成ボタンを押した後は画面が変わっていきなり以下のボタンが真ん中にデデンと表示されます。
![image](https://qiita-image-store.s3.amazonaws.com/0/126158/d6ce600d-5f20-b7ba-0eb4-d137161e04ed.png)
恐る恐るクリックして開きます。

### 4. ここで気づく  Clear DBの正体
開くと、外部のDB SaaS(DBaaS?)サービスでしょうか。　cleardb.comに飛ばされます。
シングル・サインオン済みのの状態で、契約プランに則ったDBが表示されます。
Name欄は単純にユニークな英数字なので、公開されても問題なさそうなのですが黒塗りしておきます。
ここが、DB名となります。
![image](https://qiita-image-store.s3.amazonaws.com/0/126158/721e08d0-91f6-1e5f-133a-b1a002685ec2.png)

ここをクリックするとインスタンスの詳細画面に移ります。

### 5. MySQL接続情報の取得
画面上部メニューの「Endpoint Information」をクリックします
![image](https://qiita-image-store.s3.amazonaws.com/0/126158/476a3b2c-f4e2-1e1b-39fa-de6ed7683ddd.png)

開くとDB情報が表示されます。
![image](https://qiita-image-store.s3.amazonaws.com/0/126158/c9cc5f4f-b724-9c9e-c215-0a90fe43188b.png)
ProviderにAから始まるあの会社が。
bluemixで動く時代がそう遠くない未来やってくることを願って。

とりわけここで重要なのは、GatewayとClusterNodesって。
いいですね。Gatewayにつなぎに行けば、３つのノードで冗長化されていて、
冗長性・可用性の心配をせずに運用できるということです。

これだけでもお金出してDBaaSとして使うメリット大ですね。

### 6. Spark DB、Price:FREE!の限界？
EC-CUBE3をIBM Containersでルンルンで導入してみたのですが、
導入Step5のデータベース初期化中に落ちてしまう場面に何度も遭遇。
あれ？活動限界・・・？

## まとめ
・ただより高いものはない。(エラーの原因探るのに３０分以上悩む）
・でも冗長性とか維持費考えると月額10$でも全然安いと思う。
Xcodeからの実行時にのみ特定のUserDefaultsを設定する

(色々な値の引数での指定方法を追記しました）

#これは何？

NSBindingDebugLogLevelのようにデバッグ時やテスト時にだけ、特定のUserDefaultsを設定したいときがあると思います。
こういう時はUserDeaultsのArgument Domainが便利です。

Argument Domainはその名の通り、実行時に引数として指定することのできる、**非永続的**なドメインです。
またArgument Domainは**最も優先度が高い**ドメインのため、保存されたUser Defaultsが存在していたとしても、それを無視します。

#使い方は？

引数としての指定方法は
`$ ./App.app/Contents/MacOS/App -NSBindingDebugLogLevel 1`
のように実行ファイル名に続けて`-Key Value`と指定します。

#毎回それするの面倒くさくない？

Argument Domainを利用してXcode上での実行時にのみ特定のUserDefaultsを設定するようにします。

## 設定方法（Xcode8.1）
まず、Scheme の Edit Scheme...から目的のSchemeを選択します。
<img width="1046" alt="スクリーンショット 2016-12-10 18.53.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/2117/51b142cc-11f0-7b3f-c244-1c865d7b6970.png">


次にRunのArgumentsを選択します。そして先ほどのUserDefaultsを設定します。
<img width="1129" alt="スクリーンショット 2016-12-10 18.54.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/2117/6b6c4f24-5f9c-285f-9113-e75faf9919fb.png">


**ここで注意！**
`-Key Value`は１か所に両方書くこと。ばらばらにすると正しく認識されません。



以上です。
設定方法さえ知っていれば簡単ですが、ここまでたどり着くのが割とややこしいですね。特にSchemeのEdit Scheme...出すところが。


# 値の指定方法いろいろ
引数での値の指定はProperty ListのXML形式およびASCII形式を使用します。複雑な辞書や配列でない限りASCII形式を利用した方が楽だと思います。

以下に指定方法を例示します。
また値に空白文字が含まれる場合はシングルクォーテンションまたはダブルクォーテーションで囲みます。

## 数値
数値はそのまま数字を指定します。
`-key 1`

## 文字列
これもそのままです。空白文字を含む場合はクォーテーションで囲みます。
`-key Hellow`
`-key 'Hellow World!'`

## 真偽値
YES, NOを指定します。1,0でも有効です。
`-key YES`
`-key 0`

## 配列
カッコ内にカンマ区切りで要素を並べます。
`-key '(dog, cat, "Mountain gorilla")'`

## 辞書
中カッコ内に=で結ばれたペアを;区切りで並べます。
`-key '{a="Mountain gorilla"; b=cat;}'`

## おまけ
XML形式も一応使えます。
`-key '<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict>     <key>Name</key>     <string>John Doe</string>     <key>Phones</key>     <array>         <string>408-974-0000</string>         <string>503-333-5555</string>     </array> </dict> </plist>'`

## おまけのおまけ
NSDataとNSDateはASCII形式では指定できません。XMLで頑張りましょう。

#メリット
- マクロなどを使いソースコードで設定を入れ替えるなどしなくていいため、ソースコードを汚さない。
- 非永続なためUserDefaultsデータベースを汚さない。

#デメリット
- 設定方法がややこしい。
- つまり、変更するのもややこしい。
- 設定したこと忘れそう。
- 複数人での開発のとき設定方法を周知するの面倒くさい。
- 設定する暇があったらターミナルからやった方が早くね？


#資料
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/UserDefaults/AboutPreferenceDomains/AboutPreferenceDomains.html
JAVAの正規表現の基本

#はじめに
皆様、お疲れ様です。
今年の4月に入社した姫川です。
正規表現で忘れてしまってこれなんだっけってなったりしてしまうことがあるの
で正規表現についてまとめていこうと思います。

#正規表現とは
正規表現とは、文字列のパターンを表現する表記法。文字列の検索・置換を行うときに利用される。
通常の文字と、メタキャラクタと呼ばれる特別な意味を持った記号を組み合わせて表記される。例えば「^」という文字は「行頭」、「.」は「任意の1文字」、「+」という文字は「直前の要素の1回以上の繰り返し」を意味する。
正規表現を使えば、文字列を直接指定せず、「特徴」（パターン）を指定することができるため、表記の揺れを吸収して検索を行ったり、複数の異なる文字列を一括して置換したりすることができる。<a href="http://e-words.jp/w/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE.html">(IT用語辞典e-Words引用)</a>


#正規表現の基本
##位置の指定
文字列の先頭や末尾にあるかどうかなどを指定することができます。

| 文字 | 意味 |
|:-:|:-----------------|
| ^  |行の先頭  |
| $  |行の末尾 |
| ¥A 　|文字列の先頭 |
| ¥Z  |最後に行末文字がある場合、それを除く文字列の末尾 |
| ¥z 　|文字列の末尾 |
| ¥B  |非単語境界 |
| ¥b 　|単語境界 |

##任意の文字と繰り返し

任意の文字を使用することや、指定した文字が繰り返し出現するようなパターンを作ることができます。

| 文字 | 意味 |
|:-:|:-----------------|
| .  |任意の一文字  |
| *  |直前の文字が0個以上にマッチする |
| + 　|直前の文字が1個以上にマッチする |
| ?  |直前の文字が0または1個にマッチする |
| {n}  |直前の文字にn回マッチする|
| {n,} 　|直前の文字にn回以上マッチする |
| {n,m}  |直前の文字にn回以上m回以下マッチする |

##文字クラス
複数の文字からどれか一つにマッチするパターンを作ることができます。

| 文字| 意味 |
|:-:|:-----------------|
| [abc]  |a、b、cのいずれかの文字にマッチ|
| [0-9a-zA-Z]  | 0～9、a～z、A～Z のいずれかの文字にマッチ|
| [^abc]  | a、b、c が以外の文字にマッチ|
| [a-c[x-z]]|a～c と x～zのいずれかの文字にマッチ|
| [a-c&&[b-e]]|a～c 且つ b～eのいずれかの文字にマッチ|

##定義済みの文字クラス
文字クラスの略記。

| 文字| 意味 |
|:-:|:-----------------|
| \d  |0~9のいずれかの文字にマッチ|
| ¥D  | 0~9以外の文字にマッチ|
| ¥w  | 0～9、a～z、A～Z、"_"のいずれかの文字にマッチ|
| ¥W  | 0～9、a～z、A～Z、"_"以外の文字にマッチ|
| ¥s  | 空白文字にマッチ|
| ¥S  | 空白文字以外にマッチ|

##POSIX文字クラス

US-ASCIIでのみ使用できます。

| 文字| 意味 |
|:-:|:-----------------|
| ¥p{Lower}  |a～z のいずれかの文字にマッチ|
| ¥p{Upper}  |A～Z のいずれかの文字にマッチ|
| ¥p{ASCII}  |すべての ASCII 文字にマッチ|
| ¥p{Alpha}  |a～z、A～Z のいずれかの文字にマッチ|
| ¥p{Digit}  |0~9のいずれかの文字にマッチ|
| ¥p{Alnum}  |0～9、a～z、A～Z のいずれかの文字にマッチ|
| ¥p{Punct}  |句読文字のいずれかの文字にマッチ|
| ¥p{Graph}  |表示できる文字にマッチ|
| ¥p{Print}  |プリント可能文字にマッチ|
| ¥p{Blank}  | 空白またはタブにマッチ|
| ¥p{XDigit}  | 16 進数字にマッチ|
| ¥p{Space}  | 空白文字にマッチ|

##サンプルソース

実際のプログラミングの中で利用する正規表現の記述例
「12345」が半角数値のみであるかチェックする

    public static void main(String args[]) {

        //判定する文字列
        String str = "12345";

        //判定するパターンを生成
        Pattern p = Pattern.compile("^[0-9]*$");
        Matcher m = p.matcher(str);

        //画面表示
        System.out.println(m.find());

    }


以上です。
特定のLANの中にいるかどうかに応じて異なる ssh_config を適用する方法。

`<localhostname>`をあるLAN内でのみ解決できるホスト名として、ssh_config の Matchディレクティブを用いて

```
Match exec "test x$(dig +short <localhostname> | wc -l) == 1"
  Lan 内で使用したい設定
Match exec "test x$(dig +short <localhostname> | wc -l) == 0"
  Lan 外用の設定
```

とします。

`httpbin.org/ip` などのグローバルIPチェックAPIを使わないのは外部依存性が高くなるのと、だいぶ遅いからです。

ローカルネットワーク内のドメイン情報というのもモノによってはコンフィデンシャルかもしれませんのでウェブ上の公開リポジトリにssh_configをおいているというような場合には念の為ご注意を（dns.yourcompany.local とか自明に存在しそうなものなら大丈夫でしょう）。
テンプレートとUFCSでメソッドチェーン型パーサコンビネータを作ってみた

今時パーサコンビネータ？みたいなところはあるかと思いますが紹介をしたいと思います。

## 概要

現在絶賛ストール中のプロジェクトである[MapleLatte](https://github.com/Pctg-x8/MapleLatteFE)の内部で使用された独自のパーサコンビネータです。同様のものとして[ctpg](https://github.com/youxkei/ctpg)がありますが、ctpgはコンパイル時に文字列を処理してパーサコードを生成するのに対して今回紹介するものはUFCSとテンプレートを使用して、D言語の式で文法を表現するものとなります。
解析できる文法としてはPEGで表せる範囲となっています(Packrat Parsingを使用しています)。通常のPackrat Parsingと違ってトークン列を扱うようになっており、文法をシンプルに書き下すことが可能となっています。

## 用例

例えば

```
ImportStmt <- Import identifier ("." identifier)* ["." "*"] ";"
```

という規則があったとして、`identifier`および`Import`をトークン(`TokenType.Identifier`および`TokenType.Import`)とするとソースコード中では次のように書くことができるようになっています。

```d
auto parseImportStmt(ParseResult input)
{
  return input.matchToken!(TokenType.Import).matchToken!(TokenType.Identifier)
    .matchUntilFail!(r => r.matchToken!(TokenType.Period).matchToken!(TokenType.Identifier))
    .ignorable!(r => r.matchToken!(TokenType.Period).matchToken!(TokenType.Asterisk))
    .matchToken!(TokenType.Semicolon);
}
```

## 特徴

- 即時実行型(rangeのように遅延実行ではなく)なので実行が追いやすいようになっています
- Packrat Parsingを採用しているので分岐が書きやすくなっています(テンプレート引数を左から試していって成功したら抜けるような戦略を採用しているため書き方によって望みどおりの文法をパースできないことがあります)
- テンプレートをふんだんに使っているため実行時のパフォーマンスが期待できます
    - ただし現状ではメモ化を行っていないので文法と対象次第では遅くなります

## 欠点/未実装

これがストールの原因になっているのですが、致命的な問題として還元処理を書くことができません。まずパーサの途中の状態を保持する`ParseResult`構造体が値を保持できる状態になっていないのでそこから実装する必要がありそうです。それから`matchToken!T`でトークンを保存してほしいパターンと保存しないでほしいパターンの2通りを実装する必要があるのですが、保存してほしいパターンの場合は「前の値と合成するかどうか」という問題があるのでまだ未実装となっています(ただ、前の値を捨てるパターンが思いつかないので合成する方向(`Tuple`を使って`tuple(前の値, トークン)`とまとめる)で実装してしまってもいいかもしれません)。
あとはトークン列を処理するようになっているため予めソースコードをトークンで分割しておく必要があります。そのため単独で利用するには若干つらい部分がありますが、ライブラリ化する際はなんとか両方まとめて使えるような仕組みを作る必要があります。

## まとめ

自身のプロダクトでの用例という言語系Advent Calendarの記事としては異色(たぶん)なものになりましたが、以上で紹介を終わりにします。現在未実装の還元処理をうまい形で実装することができたら(あと需要があれば)ライブラリとしてまとめてdubに登録すると思います。
IPAの情報処理試験全区分合格したので整理してみた（アプリ屋の視点）

#はじめに
IPAの情報処理試験全区分合格したので、ざっくりまとめてみました。
ただし、アプリ屋さんの視点なのでかなーり個人的見解（偏り）があります・・・
受ける人の参考になれば。

#情報処理試験とは
以下のような区分になってます。（2016年度現在）
参考：[IPA　情報処理試験区分一覧](https://www.jitec.ipa.go.jp/1_11seido/seido_gaiyo.html)

![shiken.png](https://qiita-image-store.s3.amazonaws.com/0/153873/ca66b4b3-e308-adf3-5a69-0a08133c7a8d.png)

#全区分取得してしまった背景

学生時代に、今でいう応用情報技術者試験、基本情報技術者試験、ITパスポートの3つを取得して、入社。
SEなので、DB、ネットワーク、セキュリティ、アプリ開発（システムアーキテクト）くらいは30歳になるまでは
取得しておきたいなーっというボンヤリした感じで受験開始。（いつ会社クビになってもいいように）

結果的には、30の歳（受験時、合格通知来たとき31・・・）に、
最後に残っていたITストラテジストに合格してコンプリート。

**これで職には困らない！？**

実際受けてみると、基礎知識は応用技術者試験の物を理解していれば全区分対応できて、
論文試験は基本的に勉強いらない感じの試験なので、暇つぶしに受けてたら受かってしまいました。
（ストレートじゃなく何度も不合格にはなってますけど）

#各試験（高度区分）の特徴

**この単語でたら、これが答え。**
的なものもあるのですが、キリがないので、試験の特徴的なものだけまとめました。
なんか**かっこいい**ので、レーダーチャート。

　　**知識量**：合格するのに覚えておいた方がいい知識の量
**パターン量**：回答パターンの数
　　**専門性**：応用技術者試験の基礎範囲から外れて試験固有がどれくらいあるか
　**スピード**：問題解くのに回答スピードが必要かどうか
**文章読解力**：問題文を読む力（国語力）が必要かどうか

## ITストラテジスト
普段のSE業務とはちょっとかけ離れた試験。サービスオーナーの視点が必要。

- 難易度：高
- おすすめ度（アプリ屋視点）：低
![ST.png](https://qiita-image-store.s3.amazonaws.com/0/153873/a87cc6c4-8fa3-1bdd-3fc3-d22d9a200793.png)

## システムアーキテクト
開発全般（マネジメント含む）を広く浅く知っておく必要がある。

- 難易度：中
- おすすめ度（アプリ屋視点）：高
![SA.png](https://qiita-image-store.s3.amazonaws.com/0/153873/54a6b18c-7148-862d-68b9-cee55ce5a926.png)

## プロジェクトマネージャ
かっちりしたプロマネの試験。技術系の知識あまりいらず。

- 難易度：低
- おすすめ度（アプリ屋視点）：中
![PM.png](https://qiita-image-store.s3.amazonaws.com/0/153873/351d914e-6644-7f61-cfe6-cee75afea0d5.png)

## ネットワークスペシャリスト
アプリ屋にちょっと難しいイメージ（インフラより）。新規技術の取り込みが早い印象。でも細かい所は扱われない。

- 難易度：高
- おすすめ度（アプリ屋視点）：中
![NW.png](https://qiita-image-store.s3.amazonaws.com/0/153873/325c86f4-b0e1-4795-b949-c74be495341a.png)

## データベーススペシャリスト
データベースに関わる上位工程の作業（要件整理、設計）が対象。普段DB使って開発してる人向けより設計者向け。

- 難易度：中
- おすすめ度（アプリ屋視点）：高
![DB.png](https://qiita-image-store.s3.amazonaws.com/0/153873/4640c382-b57a-6c43-ec0e-68fc08a66bb7.png)

## エンベデッドシステムスペシャリスト
エンベデッドだけど組み込みOSは当時はでなかった。フリップフロップとかモーターとか電気電子の基礎知識若干必要。

- 難易度：中
- おすすめ度（アプリ屋視点）：低
![EB.png](https://qiita-image-store.s3.amazonaws.com/0/153873/fb5463ea-cf2e-9d43-2674-315b1e19487e.png)

## 情報セキュリティスペシャリスト
基礎知識が多いイメージ。文章解読できてITのリテラシーそこそこあると合格できそう。
ただし、来年から別の枠組みへ・・・

- 難易度：低
- おすすめ度（アプリ屋視点）：高
![SC.png](https://qiita-image-store.s3.amazonaws.com/0/153873/6c6bf9e7-736f-3dd5-e370-21a9cfd67656.png)

## ITサービスマネージャ
サービス運用者向けの試験。ITILとかでてくるけど、専門性は高くない。普段の運用業務ぽい。

- 難易度：低
- おすすめ度（アプリ屋視点）：低
![IS.png](https://qiita-image-store.s3.amazonaws.com/0/153873/c61e4f48-712e-2dfb-8508-9c05e6828d6c.png)

## システム監査技術者
監査系の知識が若干必要、回答へのロジックは割と常識範囲で、知識を使わないパターン多め。

- 難易度：低
- おすすめ度（アプリ屋視点）：低
![AU.png](https://qiita-image-store.s3.amazonaws.com/0/153873/cb3d9a8c-907d-ad59-1d99-08eb17c801a2.png)


# 最後に
IPAの回し者ではありません。
後、資格マニアでもありません。
python3　数値の精度に関するメモ

pythonで1/100000000を実行すると1e-08となってしまい自分の期待している物にはならなかった。
こんな時は
```test.py
print('{0:.10f}'.format(1/100000000))
```
0.0000000100　こんな感じになる。（これを期待してた）

なお、fはfloatのfで文字列でやるとsで文字数を制限できるみたい
KerasのSequentialモデルでInputLayerを明示的に追加する

#InputLayer(入力層)を追加
```py
from keras.models import Sequential
from keras.layers import InputLayer

model = Sequential()
model.add(InputLayer(input_shape=(784,)))
```
これだけですが，Sequential modelチュートリアルで触れられていないので記事にしておきます．

Python 3.5.2, Keras 1.1.2 にて確認しました．


###InputLayer なし
```py
from keras.models import Sequential
from keras.layers.core import Dense

model = Sequential()
model.add(Dense(256, activation='relu', input_dim=784))
model.add(Dense(128, activation='relu'))
model.add(Dense(10, activation='relu'))
```
チュートリアルの通りの書き方です．
この場合，中間層の中で入力層の形状を定義することになってしまいます．
また，Dense(256)層を消すために最初のaddをコメントアウトすると，
入力形状が未定義になってしまいます．

###InputLayer あり
```py
from keras.models import Sequential
from keras.layers import InputLayer
from keras.layers.core import Dense

model = Sequential()
model.add(InputLayer(input_shape=(784,)))
model.add(Dense(256, activation='relu'))
model.add(Dense(128, activation='relu'))
model.add(Dense(10, activation='relu'))
```
入力層→中間層→出力層の流れがわかりやすくなりましたね．
メッセージングシステム Pulsar を使ってみる

# 概要
メッセージングシステムについて調べていて見つけたので試してみる。

Yahoo！inc.が提供するOSSのメッセージングシステム
https://github.com/yahoo/pulsar
常駐型プロセスを使って高速なメッセージングのやり取りが可能っぽい。

# Pulsarとは
下記にわかりやすくまとまってた。
https://techblog.yahoo.co.jp/infrastructure/pulsar_introduction/

詳しくは、上記の記事を見てもらえればと思います。

ざっくりな感じで

* メッセージングシステム
* 非同期的なやり取りが可能
* メッセージは
* producer　=> メッセージ送信者
* consumer　=> メッセージ受信者
* topic => メッセージを管理するグループ  

producerがnewsというトピックで“円安”というメッセージを送るとnewsというトピックを受け取る準備をしているconsumerが“円安”メッセージを受信する。


# とりあえず使ってみる
tar.gzファイルを落としてくる(現時点では1.15.2が最新っぽい)

```
$ wget https://github.com/yahoo/pulsar/releases/download/v1.15.2/pulsar-1.15.2-bin.tar.gz
```
最新バージョンは下記から確認してみてください。
https://github.com/yahoo/pulsar/releases

解凍

```
$ tar xvfz pulsar-1.15.2-bin.tar.gz
```
pulsarをstandaloneモードで立ち上げます。
>PulsarにはStandalone（Broker, BookKeeper, Zookeeperが一つのサーバー上ですべて起動する）モードが用意されています。

```
$ cd pulsar-1.15.2
$ bin/pulsar standalone
```

次に、consumerプロセスを立ち上げます。

```
$ bin/pulsar-client consume -s 'sub' 'persistent://sample/standalone/ns1/my-topic'
```
次に、producerプロセスでメッセージを送ってみます。

```
$ bin/pulsar-client produce -m 'hello' 'persistent://sample/standalone/ns1/my-topic'
```

すると、producerから送った hello というメッセージがconsumer側に届きました。

下記のgifは左側の画面がconsumer,右側の画面がproducerとなります。
![pulsar-movie-gif.gif](https://qiita-image-store.s3.amazonaws.com/0/57545/be6138ee-a51c-579d-7757-79f508acd6a4.gif)


# まとめ
* 簡単にメッセージングシステムを実感することができた。
* サポートされているのはまだJavaだけ。
* あとでCLIからではなくJavaでも試してみる。
* 非同期的なシステムの構築はレスポンス的な部分として、キューイングシステムは落とせない大切な情報（決済情報など？）にも有用的に活用できそう？
* 他のメッセージングシステムとの差も理解を深めたい。
iOS 動画からサムネイル画像を取得

複数の動画ファイルを画面に一覧で表示させる時にサムネイル画像で表示させたい場合がありましたのでそのコードを下記に記載します。

1.AVFoundation.frameworkをプロジェクトに追加してください

2.下記のコードで動画からフレームを取得してそれを画像にします

```objc:xxxxx.m
NSURL *url = サムネイルを取得したい動画ファイルのパス;

NSDictionary *assetOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
AVAsset *localAsset = [AVURLAsset URLAssetWithURL:url options:assetOptions];
AVAssetImageGenerator *imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:localAsset];

CGImageRef thumbImage = [imageGenerator copyCGImageAtTime:kCMTimeZero actualTime:NULL error:&error];
UIImage *thumbnailImg = [UIImage imageWithCGImage:thumbImage];

```
micro SD に焼いて起動するまで

お次は、いよいよ Windows IoT Core を micro SD に焼いて起動するまでの話です。

# micro SD カードに OS を焼く...その前に

Raspberry Pi も買って micro SD カードの準備もできました（ああ、micro SD のカードリーダーも用意してくださいね）。これで、micro SD カードに OS を焼く準備ができたのですが、ちょっと待ってください。
実は、micro SD カードってよく部分的に壊れてしまった復旧できないことがあります。

![SDFormatter](https://qiita-image-store.s3.amazonaws.com/0/32488/b4c36fc3-304e-6235-dab4-5a763bf179bc.jpeg)

そのようなときに備えて [SDカードフォーマッター - SD Association](https://www.sdcard.org/jp/downloads/formatter_4/ "SDカードフォーマッター - SD Association") をダウンロードしておきましょう。micro SD カードにあれこれ焼いていると（特に Linux 系のもの）、途中で SD カードで見える容量が小さくなることがあります。16GB あるはずなのに、500MB ぐらしか見えない、というアレです。こういう場合は、SDカードフォーマッタの「オプション設定」→「論理サイズ調節」を ON にすると、元の容量に復帰できます。
通常の Winodws のフォーマットでうまくいかないときに試してみてください。

あと、Windows IoT Core では使われませんが、データの書き込みには、[Win32 Disk Imager](https://ja.osdn.net/projects/sfnet_win32diskimager/ "Win32 Disk Imager") を使うことがよくあります。

![Win32 Disk Imager](https://qiita-image-store.s3.amazonaws.com/0/32488/c752d6fc-d4bf-18c0-a318-b244c0838ced.jpeg)

これでデスクイメージを micro SD カードに焼き込むことがよくあります。

# OS イメージをダウンロードする

[Get Started | Windows IoT](https://developer.microsoft.com/ja-jp/windows/iot/GetStarted# "Get Started | Windows IoT") から、Windows IoT Core のイメージをダウンロードします。焼き込むには、PC の Windows 10 が必要という極悪...素直な仕様なので素直に Windows 10 にしてください。
Windows 7 ではできないのか！？という問題もあるのですが、そもそも、Windows IoT Core のアプリケーションは UWP（Universal Windows Platform）でできていて、これを作るのは Windows 10 上の Visual Studio 2015 以上が必要になるので、Windows 10 の PC は必須なのです。

![IoT Dashboard](https://qiita-image-store.s3.amazonaws.com/0/32488/1ebc9b82-3d10-2172-6b7a-03100cc58375.jpeg)

# micro SD カードに焼く

デバイスドライバーで「Raspberry Pi 2&3」を選択して、micro SD カードに焼き込みます。最新の Windows IoT Coreをダウンロードするのでインターネット接続が必要ですね。
ここで設定するパスワードは、デバイスモニタでログインするときにパスワードになります。ユーザー名「Administrator」でパスワードが入力したものを使います。

![](https://qiita-image-store.s3.amazonaws.com/0/32488/db965fbf-7574-df6f-7a3b-5fd8d6f71142.jpeg)

カスタムを選択すると、あらかじめ起動イメージをダウンロードしてあるファイルを使って書き込むこともできます。

# Raspberry Pi を起動する準備

micro SD カードに OS を焼き込めたら、Raspberry Pi にカードを差し込んで電源を入れる訳ですが、Raspberry Pi にモニタとキーボード、マウス、有線LANを接続しておきましょう。

![](https://qiita-image-store.s3.amazonaws.com/0/32488/2a31aeef-8a98-f76e-1cf8-e0aca6fe74f8.jpeg)

のような感じで接続します。Raspberry Pi には電源スイッチがないので、micro USB に 5V2A のケーブルを差し込むと電源が入った状態になります。
電源を落とすときはどうするかというと...素直に micro USB を抜くしかないですよね。

# Windows IoT Core を起動する

うまく起動できるとこんな画面になります。

![](https://qiita-image-store.s3.amazonaws.com/0/32488/ec28dcf5-b616-f8b1-39d8-c2e7c2da609c.jpeg)

このディスプレイは Aliexpress で買った 800x480 でのディスプレイですね。$30 ぐらいで購入が可能です。

[Raspberry pi 2 model B/B+/A+ 5inch 800X400 HDMI GPIO](https://ja.aliexpress.com/item/Raspberry-pi-2-model-B-B-A-5inch-800X400-HDMI-GPIO-Resistive-Touch-Screen-display/32347712977.html?isOrigTitle=true&amp;isOrig=true#extend "Alibaba グループ | AliExpress.comの Lcd モジュール からの Configuration Checklist: 5inch HDMI LCD &amp;times; 1 HDMI connector Resistive touch screen pen &amp;times; 1 RPi pillars p 中の Raspberry pi 2 model B/B+/A+ 5inch 800X400 HDMI GPIO Resistive Touch Screen display")

という訳で、Windows IoT Core を起動するところまでできたのですが、PC の Windows 10 と違って、これだけで何ができるという訳ではありません。
プログラムを作ってインストールして動作という手順があるので、それをこの次にお話しします。
CakePHP3で簡単にFileCacheからfindできるようにするプラグイン

m-shimaoと申します。
この記事は[CakePHP3 Advent Calendar 2016](http://qiita.com/advent-calendar/2016/cakephp3)の10日目の記事となります。
（[Fusic Advent Calendar 2016](http://qiita.com/advent-calendar/2016/fusic)の記事でもあります。）
本日は稚拙ながら私が~~ついさっき~~作ったFileCacheを使ったプラグインの紹介をさせて頂きたいと思います。

## プラグイン
[m-shimao/find-in-file-cache](https://github.com/m-shimao/find-in-file-cache)

## できること
* 特定のテーブルでaddBehavior()すれば、そのテーブルへのfind()がFileCacheを利用したものになる
    * まだテストが書けてないので全パターンを確認できてないけど、複雑なクエリじゃなければ大丈夫なはず…
* そのため、そのテーブルに対してselectクエリをたくさん投げてもパフォーマンス的にはあまり気にしなくてよくなる。
* 作ったばかりでまだサービスでの稼働実績がないので、使われる方はお気をつけください:bow:


## インストール方法
[m-shimao/find-in-file-cache](https://github.com/m-shimao/find-in-file-cache)のREADMEをご参照ください

## 使い方

いま使いたいテーブルがcategoriesテーブルだとすると、
Model/Table/CategoriesTable.phpにてaddBehavior()を追加すれば使えます。

```
<?php
class CategoriesTable extends Table
{
    public function initialize(array $config)
    {
        $this->addBehavior('FindInFileCache.FindInFileCache');
    }
}
```

find()を投げると、beforeFind()の中で既にFileCacheにデータがあるかをチェックし、
該当するデータが有ればそのデータを返して以降のイベントを行わないような動きをします。
FileCacheに無ければ、通常通りfindを実行後FileCacheにデータをキャッシュします。
キャッシュの有効期間はデフォルトで15分としています。
その他キャッシュの設定を変更したい場合はapp.phpでfind-in-fileというキーでキャッシュの設定を追加して頂ければ
そちらの設定を見に行くようになります。設定例↓です。

```
<?php
return [
...
    'Cache' => [
        ...
        'find-in-file' => [
            'className' => 'File',↲
　　　　　　　　　　　　　　　　　　　　　　　　'className' => 'File',↲
　　　　　　　　　　　　　　　　　　　　　　　　'prefix' => 'myapp_cake_static_record_',↲
　　　　　　　　　　　　　　　　　　　　　　　　'path' => CACHE . 'models/',  //pathをmodelsと同じにする↲
　　　　　　　　　　　　　　　　　　　　　　　　'duration' => '+1 hours',↲    // cacheの有効期間を1時間にする
        ],
        ...
    ],
...
];
```


## 注意点
* 対象のテーブルは基本的に**データが変わらないもの** or **データが変更されてもすぐに反映される必要が無いもの**を想定しています。
例えばbookmarksなど頻繁に更新されるテーブルに対して設定しても使いものにならないと思うので、
お使いの際はテーブルの性質をご考慮ください
* join等にも対応しているはずですが、まだテストできていません…。余り複雑なクエリでは使わないほうがよいかもしれません。

## 開発でハマった点
もともとQueryオブジェクトに

```
$query->cache($cacheKey);
```

とするとcacheからデータのfetch・データのstoreをうまいことfindの前・後に挟んでくれるようになるメソッドがあるので
それを使えば簡単に実装できそうだと思っていたのですが、
cacheからのfetchのタイミングがbeforeFindの前だったので、うまく使えませんでした…。
結局上述のようにbeforeFindの中でキャッシュにアクセスして、あったら以降のイベントをStopするような実装にしました。

## （2017/1/31追記） コメント頂いた件の改修
* 間が空いてしまいましたが…、@chinpei215さんよりご指摘頂いた下記の2点に対して対応しました:bow:
    * mapReduce(), formatResults()がセットされているクエリの場合に実行の度にデコレードが実行されてしまい、結果セットが壊れてしまうバグ
    * 同じクエリオブジェクトで二回以上クエリが実行される場合に、2回目以降はcacheを無効化する対応

## 今後の改修予定
* テストコードの追加。合わせてある程度複雑なクエリへの対応
* cacheを使用しないオプションの追加。
* データがsaveされたらキャッシュを削除する処理を追加。
* いまはクエリの内容毎にキャッシュのキーを変えているのですが、クエリはfind()->all()だけに統一して、その結果セットをwhere句やorder句などの内容に応じてゴニョニョして返すようにしたいです。

## 雑記
* 昨日は[ymm1x](http://qiita.com/ymm1x)様の[CakePHP3のbakeによるコード自動生成のプラクティス](http://qiita.com/ymm1x/items/12ced37212636b09de19)でした。
ちょうど業務で「そろそろbakeいじるか〜」と思っていたタイミングだったので、大変参考になりました:bow:
* 実は元々クエリログを簡単に出すプラグインを作ろうと思っていたのですが、4日目の[YKEI_mrn
](http://qiita.com/YKEI_mrn)様の[CakePHP3 のログをためす](http://qiita.com/YKEI_mrn/items/913a48f9211a550c4788)を見てapp.phpの設定だけでできることを恥ずかしながら初めて知りました。
* 何が言いたいかというと、Advent Calendar登録すると内容が被らないようにこれまでの記事を一通りみるので、すごくためになるなぁと思ったのでした:grin: