OmniAICreator/Qiita-1.07M huggingface dataset:
Gitでローカル&リモートのブランチを削除する時のまとめ

チーム開発時にチケット完了でmasterブランチなどにマージし、不要なブランチ消しといたよ～
て時に自分の環境だと反映されていない事がある。

毎回ブランチの削除コマンドを忘れてググってるので備忘録としてまとめた。



## ローカルブランチの削除

HEADにマージ済みを削除
`% git branch --delete ブランチ名`

マージしたかどうかを問わず削除
`% git branch -D ブランチ名`



## リモートブランチの削除

`% git push origin :ブランチ名`



## 削除したリモートブランチが残ってる

他人が削除したリモートブランチやGitHubでpullrequestがマージされた時にブランチも消すと
`% git branch -a` 
で確認してもリモートブランチが残ってる場合がある。

どうやら追加したブランチはfetchで取れるが、削除したブランチはオプションが必要みたい。

```
% git fetch --prune
x [deleted]         (none)     -> origin/hoge
```
pruneは
>おろす、切り取る、切り払う、(短く)刈り込む、取り除く、切り詰める

などの意味があるみたい
http://ejje.weblio.jp/content/prune


参考サイト
http://qiita.com/k_kinukawa/items/6f6e168ef16b8d1d81a6
http://qiita.com/yuichielectric/items/84cd61915a1236f19221
関係演算子と等価演算子

C90の規格票（「プログラム言語C JISX3010-1993 (ISO/IEC 9899:1990)」）を読んでいます。今回は、関係演算子と等価演算子ついて調べてみました。

##用語
まず始めに、本記事中の用語の定義を示しておきます。
 
- 関係演算子とは「>,<,>=,<=」のことです。
- 等価演算子とは「==,!=」のことです。
- オブジェクト型とは、関数型及び不完全型を除くすべての型（int型、ポインタ型、配列型、共用体型など）を指します。オブジェクト指向の「オブジェクト」とは関係無いです。
- 集成体型とは、配列型と構造体型の総称です。
- スカラ型とは、算術型とポインタ型の総称です。

##異なるオブジェクトへのポインタ、関数ポインタの比較は？

以下は、規格C90ではいずれも未定義の動作となります。

```c:未定義の動作（C90）
int n, m;
&n > &m;    /* 未定義の動作：異なるオブジェクトへのポインタの比較 */
```

```c:未定義の動作（C90）
void f(void){}
int main(void){

    f >= f;    /* 未定義の動作：オペランドが関数型オブジェクトへのポインタ */

    int a[10];
    int b[10];
    a > b;    /* 未定義の動作：異なる配列の要素へのポインタの比較 */

    return 0;
}
```
両オペランドがポインタ型オブジェクトである場合、以下が許容されます。

- 同じ構造体型オブジェクトまたは共用体型オブジェクトの任意のメンバへのポインタの比較。
- 同じ配列型オブジェクトの、任意の要素へのポインタまたは最後の要素を一つ超えた要素へのポインタの比較。

配列型配列（要素型が配列型の配列）の場合、同一オブジェクトの任意の要素へのポインタであっても要素の階層（？）が異なる場合、未定義の動作となります。T型配列型配列の先頭要素へのポインタ（T型配列型へのポインタ型）と、T型配列型オブジェクトの先頭要素へのポインタ（T型へのポインタ）では、型が適合しないためです。

以下の場合、同一配列の記憶領域内の要素を指していても、int型へのポインタ（第一オペランド）とint型配列型へのポインタ（第二オペランド）という適合しない型同士を比較しているため、未定義の動作となります。

```c:未定義の動作（C90）
int a[10][10];
&a[0][0] > &a[0];
```
また、関数型へのポインタは、関係演算子のオペランドに指定すること自体が許されません。ただし、等価演算子（==、=!）はオペランドに関数型へのポインタを指定可能です（そうでないと、空ポインタとの比較ができなくなってしまう）。

##奇妙なコードが必ずしも未定義の動作になるとは限らない？

にわかには信じがたいですが、以下の奇妙なコードは未定義の動作ではありません。

```c:正しいコード（C90）
int n;
&n > &n+1;    /* 正しい：関係演算子・等価演算子では、配列型以外へのポインタは「長さ1の配列」として考える */
```
規格C90の関係演算子及び等価演算子の意味規則の定義においては、int型オブジェクトへのポインタなど「配列型でないオブジェクトへのポインタ」は、要素数1の配列の先頭要素へのポインタと同じ動作をするものとして、演算子の意味規則を定義しています。それを踏まえると、スカラ型や共用体型へのポインタは「（要素数1の配列として考えた時に）任意の要素または最後の要素を一つ越えた要素へのポインタ」同士を比較することは許されるので、上記コードは正しいです（ちなみに、不完全型については陽に禁止されていませんが、配列型の説明において不完全型の配列は作ることはできないと書かれてあるので、不完全型については対象外と考えられます）。

と書いておきながら、正直、ここは半信半疑です。規格（「6.3.8 関係演算子」）を字面通りに読むと許容されるのですが、もし上の解釈で間違ってないのだとすれば、コンパイラ開発者向けに配列の要素型へのポインタと区別せず一括して構文解析できるように気を利かせたのかもしれません。

##評価結果の型

- 関係演算子・等価演算子の評価結果はint型です。
- 関係が真の場合は1、偽の場合は0を返します（「真の場合は0以外を返す」だと思っていたので、ここも意外でした）。
Telnetポートテストと3ウェイ・ハンドシェイクの話（前編）

# 1.はじめに
Telnetポートテスト、便利ですよね。
ネットワーク構築時のテストや運用時のトラブルシュートなどに大活躍します。
ところがつい先日、ネットワーク構築でTelnetポートテストの結果を信じて大変痛い目に遭いました。
ネットワークエンジニアを数年やってきて初めての大変だったため、共有させて頂きます。

この記事は前後編に分けて書く予定です。
前編（本記事）ではTelnetポートテストの使い方をさらっと解説します。
後編ではTelnetポートテストの落とし穴について解説します。

# 2.Telnetポートテストとは何か
Telnetクライアントを利用して、クライアントからサーバへのTCP接続性を確認するテストです。
このテストによってTCPの接続性（＝3ウェイ・ハンドシェイクが行えること）が確認できます。

システム開発の現場にではインフラチームと開発チームが別のチームになっていて、お互いの作業範囲が完全に分かれていることがあります。私の所属する会社ではネットワークおよびサーバに関わる業務はインフラチーム、アプリケーションに関わる業務は開発チームが担当しています。他の会社も恐らく同じ体制になっているのではないかなと思います。
この時のインフラチームの仕事は、「デプロイされたアプリケーションがノード間を要件通りに通信できること」となります。OSI7階層モデルで言うところの第1層～第4層が責任範囲ですね。この4層までの準備が完了していることを手軽に確認できるのが、Telnetクライアントテストです。

# 3.qiita.comとのTCP接続性を確認する
あなたがインフラチームのエンジニアで、http://qiita.com/ というWebサーバを構築し、関連するネットワークの設定を完了したとします。早速インターネットに接続できるPC準備してテストをやっていきましょう。

Telnetクライアントを立ち上げて、以下を実行します。
```c:\>telnet qiita.com 80```
………
……
…
真っ黒な画面が出ただけですか？　成功です。これでクライアントがqiita.comとTCP80番ポートで通信できることが確認できました。

次にポート番号を変えて実施してみましょう。

```
c:\>telnet qiita.com 8080
接続中: qiita.com...ホストへ接続できませんでした。 ポート番号 8080: 接続に失敗しました

c:\>
```

今度は「接続に失敗しました」と出ました。これは、対象のサーバqiita.comとTCP8080番ポートでは通信できなかったことを現しています。

# 4.Telnetポートテストの何が凄いのか
Telnetポートテストの素晴らしさはほぼ1点、クライアント側の事前準備が極めて簡単ということに尽きます。Telnetクライアントは多くの端末やサーバのOSにおいて標準で準備されています。
特に、クライアントアプリケーションを開発する案件でとても役に立ちます。開発予定のクライアントアプリケーションがまだクライアント側に導入されていない状態であっても、サーバ側の準備さえできていればテストの実施が可能です。テストに成功すればインフラチームの仕事は完了したと、胸を張って言えるでしょう。

# 5.Telnetポートテストは素晴らしい、一生着いて行くよ！
そう思っていました。あの恐ろしい事件が起きるまでは……。

というところで後編に続きます。
【Python】OpenCVで取り込んだビデオデータを連番のjpgファイルで保存

正直、フリーツールとか探せばもっと良いのがゴロゴロしてると思う。
仕事とか迂闊にフリーツールを入れれない環境とかで、
毎回似たようなものを作成しているので、備忘録的に記載。

第1引数にビデオソース。
　→Webカメラにアクセスする際は、0-9の数字を指定。
　　動画ファイルにアクセスするときは、相対か絶対パスで動画ファイルを指定。
第2引数にフレームレート。
　→表示する際のフレームレート。cv2.waitKey()の待ち時間を変更しているだけの手抜き処理。
第3引数に縮小率。
　→吐き出すjpgファイルのサイズを変更する際に指定。
　　2を指定すると1/2の横縦幅の画像に。

```py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
video2jpg.py.

Usage:
  video2jpg.py [<video source>] [<fps>] [<resize_rate>]
'''

import numpy as np
import cv2
import sys

print(__doc__)

try:
    fn = sys.argv[1]
    if fn.isdigit() == True:
        fn = int(fn)
except:
    fn = 0
print fn

try:
    fps = sys.argv[2]
    fps = int(fps)
except:
    fps = 30
print fps

try:
    resize_rate = sys.argv[3]
    resize_rate = int(resize_rate)
except:
    resize_rate = 1
print resize_rate

video_input = cv2.VideoCapture(fn)
if (video_input.isOpened() == False):
    exit()

count = 0
while(True):
    count += 1
    count_padded = '%05d' % count

    ret, frame = video_input.read()

    height, width = frame.shape[:2]
    small_frame = cv2.resize(frame, (int(width/resize_rate), int(height/resize_rate)))

    cv2.imshow('frame', small_frame)
    c = cv2.waitKey(int(1000/fps)) & 0xFF

    write_file_name = count_padded + ".jpg"
    cv2.imwrite(write_file_name, small_frame)

    if c==27: # ESC
        break

video_input.release()
cv2.destroyAllWindows()
```
5分で始めるAngular2とUIフレームワークをいれるまで

以前[こちら](http://qiita.com/hatappi/items/94d6f2746f853e67ce58)に書いたものがあったのですが、
`angular-cli` のビルドツールがSystemJSからWebpackになったので
それ用に書き直したものです。

今回はAngular2をはじめる上でベースとなるプロジェクトを作成してくる`angular-cli`と、
UIフレームワークをいれるまでを紹介します。

## **Angular2が動くまで**

### まずは`angular-cli`をインストール

```
npm install -g angular-cli
```

### プロジェクトを作ってみます

```
ng new PROJECT_NAME
```
処理が終わった後に

```
ng serve
```

で何もエラーがでなければ、`http://localhost:4200/`で下記のような画面になるはず

<img width="234" alt="スクリーンショット 2016-06-16 23.22.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/44247/21efff4b-107b-f3c5-7f27-a2c48365904c.png">

### これで一旦セットアップ完了！
特に何も手を加えることなくAngular2がさわれる環境ができる

## **UIフレームワークをいれてみる**
今回SalesforceがリリースしたCSSフレームワークの[`Salesforce Lightning Design System(SLDS)`](https://www.lightningdesignsystem.com/)を使用する。

[ng-lightning](https://github.com/ng-lightning/ng-lightning)はSLDSのボタンやモーダルなどをAngular2のコンポーネントとして提供してくれるライブラリ

### package.json
今回必要な`ng-lightning`とSLDSに必要なcssやiconなどが入ったdesing-systemなどを追加します。

```bash
$ npm i @salesforce-ux/design-system --save
$ npm i ng-lightning --save
```

### cssを読み込む

`angular-cli.json` に読み込ませたいcssを設定する
[公式](https://github.com/angular/angular-cli#global-library-installation)だとbootstrapで解説されている

```diff
--- a/angular-cli.json
+++ b/angular-cli.json
@@ -15,7 +15,8 @@
       "prefix": "app",
       "mobile": false,
       "styles": [
-        "styles.css"
+        "styles.css",
+        "../node_modules/@salesforce-ux/design-system/assets/styles/salesforce-lightning-design-system.min.css"
       ],
       "scripts": [],
       "environments": {
```

### NgModuleのimportsにmoduleをimportする

`src/app.module.ts`

```ts
import { NglModule, provideNglConfig} from 'ng-lightning/ng-lightning';

@NgModule({
  〜〜〜
  imports: [
    〜〜〜
    NglModule
  ],
  providers: [
    provideNglConfig()
  ],
  〜〜〜
})

```

### サンプルコード記載

`src/app/app.component.html`

```html
<ngl-badge>Badge</ngl-badge>
<ngl-badge type="default">Default</ngl-badge>
<ngl-badge type="info">Info</ngl-badge>
<ngl-badge type="success">Success</ngl-badge>
<ngl-badge type="warning">Warning</ngl-badge>
<ngl-badge type="error">Error</ngl-badge>
```

## 起動
サーバーを立ち上げたら終わりです

```bash
ng serve
```

<img width="387" alt="スクリーンショット 2016-09-28 1.21.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/44247/30d772d8-918f-b1d4-e689-f52cc535be70.png">


## 最後に
今回はUIフレームワークをいれるところまでやりましたが、[angular-cli](https://github.com/angular/angular-cli)がとにかく便利です。
プロジェクトを作成してくれるだけでなく、github pageのデプロイなどの機能をついています。
Angular2さわってみたいけど、どこからやろうかの人は実際にさわるのでおすすめです。
【Tips】MTAppJSONTableのテーブルを初期状態で表作る方法

MTAppJOSONTableを初めて使ったのでメモTipsとして残しておきます。
個人的にmtAppJSONTableのイメージは追加で行や列を追加していくものだと思っていました。
要件として、新規記事を押した段階ですでに既存行や列が出た状態で表示させるという仕様があったためbit partの皆さんにやり方を教えて頂きました。
（たぶん、これからいっぱい触る機会あると思うので、技術メモをストックとして残していければいいなって思っています。。）


# 要件

* 新規作成時に決められた行・列のテーブルを表示させる

# 解決方法

* 新規で作成するカスタムフィールドに決めた行や列のJSONをフィールドに入れる
* 行や列を追加できない状態でMTAppJSONTableを初期化する


# 手順

簡単に説明するとデフォルトの段階で表示するデータ（JSON）をカスタムフィールドに入れておき、MTAppjQueryで初期化してあげれば完成します。記事作成時には、自分が想定する行や列が表示されています。

## カスタムフィールドを作成する

* カスタムフィールドのタイプは、ブログ（今回のケースの場合）
* 種類は複数行（JSONを入れるため）
* ベースネームとテンプレートタグを設定する
* 既定値に表示させたいテーブルのJSONをいれる

![mtappjsontable01.png](https://qiita-image-store.s3.amazonaws.com/0/34020/b3020248-578e-5115-8d07-ed8435b8a778.png "mtappjsontable01.png")

## テーブルに出力するためのJSONを用意する

* keyを指定（任意）
* valueを指定（ここに入る値がtableのtdに出力されるため、既存の値がある場合はいれておくと良いかもしれません。）

```
{
  "items": [
    {
      "number01": "既存のテキスト表示",
      "number02": "",
      "number03": "",
      "number04": ""
    },
    {
      "number01": "既存のテキスト表示",
      "number02": "",
      "number03": "",
      "number04": ""
    },
    {
      "number01": "既存のテキスト表示",
      "number02": "",
      "number03": "",
      "number04": ""
    },
    {
      "number01": "既存のテキスト表示",
      "number02": "",
      "number03": "",
      "number04": ""
    }
  ]
}
```

サンプルのJSONデータを用意しておきます。
手書きで書いたので、以下のジェネレータサイトが使いやすかったので簡易的にJSONを書く際は使ってみるのはよいかもしれませんね。

* [JSON-GENERATOR](http://www.json-generator.com/)

## user.jsを記述する

出来上がったカスタムフィールドをuser.jsに組み込む

* ブログのテンプレートにuser.jsとuser.cssをインストール
* user.jsに以下のソースを組み込む（addをfalseしておけばOKのようです。）
* ※thやtdの幅を変える場合は、user.cssで行うことができます。

```
(function($){
  $('カスタムフィールドのクラス名をセット').MTAppJSONTable({
    headerPosition: 'top',  // 見出しの位置をセット
    inputType: {
      number01: "textarea",  // tdに入る値は、input or textarea
      number02: "textarea",
      number03: "input",
      number04: "textarea"
    },
    header: {
      number01: "見出し1",  // thのラベルを指定する
      number02: "見出し2",
      number03: "見出し3",
      number04: "見出し4"
    },
    headerOrder: [
      "number01",  // headerOederはkeyの並び順を指定します。
      "number02",
      "number03",
      "number04"
    ],
    add:   false,    // add（追加）できないようにセットすること
    clear: false    // add・checkboxを出していないので意味はありませんが、削除もfalseしておきます。念のため
    // cbAfterBuild: function(cb, $container){
      // コールバック関数
    // },
  });
})(jQuery);
```

cbAfterBuildは、tableが構築し終わったときに呼ばれる関数のようです。
案件ではプルダウンとか実装があったので記述しました。（サンプルでは不要）

user.jsを再構築をして完成になります。（新規記事作成画面でtableが表示される）

やり方を教えて頂いた bit part の皆さんに感謝致します。m(_ _)m
【git】 authorを間違えてcommitした上で、pushしてしまった時の対処法と再発防止策

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">自宅から会社のリポジトリにpushしたら、なんでかauthorが個人用のアカウント名になってて顔面蒼白なんだけど……</p>&mdash; 黒鍵 (@blac_k_ey) <a href="https://twitter.com/blac_k_ey/status/769648947270864896">2016年8月27日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ぐわーっ、また会社のリポジトリに個人アカウントのauthorでpushしとる…</p>&mdash; 黒鍵 (@blac_k_ey) <a href="https://twitter.com/blac_k_ey/status/780454961427603456">2016年9月26日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

gitのuser.name/user.emailの設定を誤ってpushしてしまうと、GitHub上で空のアイコンになったり、アカウントが紐づけされて、別の用途に使っているアカウントがバレてしまう。
その対処法と再発防止策。

# やらかしたコミットを修正する

![範囲を選択_045.jpg](https://qiita-image-store.s3.amazonaws.com/0/138793/0d263fd6-76a7-e4fc-f1c8-074b4113d427.jpeg)

「commit 002」を修正したい。

```bash
$ git rebase -i 【間違えたコミットのひとつ前のコミット】
```

ここでは acedb...を指定

参考： [rebase -i でコミットを修正する](http://www.backlog.jp/git-guide/stepup/stepup7_6.html)

![sample : emacs – Konsole_046.jpg](https://qiita-image-store.s3.amazonaws.com/0/138793/ea484bcd-3f42-105d-dbe7-beb434947015.jpeg)

修正したいコミットの「pick」を「edit」に修正して保存。

![範囲を選択_047.jpg](https://qiita-image-store.s3.amazonaws.com/0/138793/c7fb6b92-b36d-2628-deea-7292e88d64f6.jpeg)

こんな感じのメッセージがでてくる。
コミットを修正できる状態になったので、authorを上書きしてコミットする。

```bash
$ git commit --amend --author="example <example@example.com>"
```

rebase から復帰する

```bash
$ git rebase --continue
```

![範囲を選択_048.jpg](https://qiita-image-store.s3.amazonaws.com/0/138793/d9a014c2-d23c-3969-ab35-08bad2c83ee5.jpeg)

無事修正された。
あとはpushすればおk

```bash
$ git push -f
```

forceする覚悟をキメるんだ

# 再発防止策をとる

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/blac_k_ey">@blac_k_ey</a> それ防止するために、commitのhookにgit config --local user.{name,email}の設定を要請するやつ入れてるw</p>&mdash; あいや (@public_ai000ya) <a href="https://twitter.com/public_ai000ya/status/775116299357696001">2016年9月11日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>


gitにhookの概念があることを知らなかった(´ω`;)
というわけでパクらせてもらおう

参考: https://github.com/aiya000/dotfiles/blob/master/.git_templates/hooks/pre-commit

**.git/hook/pre-commit**

```bash
#!/bin/sh
if [ -z "`git config --local user.name`" ] ; then
  echo '名無し(´・ω・`)'
  exit 1
fi

if [ -z "`git config --local user.email`" ] ; then
  echo 'メールアドレスがない(T_T)'
  exit 1
fi
```

※ 原因が分かりやすいメッセージで置き換えましょう

実行権限の付与も忘れずに。

```bash
$ chmod u+x .git/hook/pre-commit
```

![範囲を選択_049.jpg](https://qiita-image-store.s3.amazonaws.com/0/138793/cfdbd35c-d7b2-b20b-f99e-2e73a6d2b6ae.jpeg)

上手くいった。

とはいえ、いちいちpre-commitのスクリプトを配置するのも面倒。
git initの際に配置されるようにする。

テンプレート用のディレクトリを作成してスクリプトを配置

```bash
$ mkdir -p ~/.git_template/hook
$ touch ~/.git_template/hook/pre-commit

(上記のスクリプトを仕込む)

$ chmod u+x ~/.git_template/hook/pre-commit
```

gitにテンプレートとして認識させる

```bash
$ git config --global init.templatedir
```

![範囲を選択_050.jpg](https://qiita-image-store.s3.amazonaws.com/0/138793/0e25962f-e6d4-86a3-0931-ce41f8e3feec.jpeg)

おk
これでヒヤヒヤすることも無くなるだろう。たぶん。
カーネルが新しくなってCUDAが動かなくなったときのtips

tensorflowに限りませんが、GPUを使ったdeeplearningは環境構築がちょっと面倒です。
一度構築した環境も、何らかのタイミングでapt-get updateなどしたときにnvidiaのドライバが読み込めなくなることがあります。

### ハマったのでメモ
自分の場合は、PCを再起動したらドライバが認識せず、CUDAが動かなくなりました。
たぶん試行錯誤してインストールしていたときに何かしてた。

```
> ls /dev/nvidia*

なにもなし
```

エラーとしてはこのように表示されます。

```
> nvidia-modprobe

modprobe: ERROR: ../libkmod/libkmod-module.c:809 kmod_module_insert_module() could not find module by name='nvidia_352'
modprobe: ERROR: could not insert 'nvidia_352': Function not implemented
```

自分の場合、新しいカーネルヘッダをインストールすることで解決しました。

```
apt-get install linux-headers-$(uname -r)
```
内蔵HDDをexFATでフォーマットする方法

## ユースケース
* windowsと他のOSで共用で使う。

## やり方

1. コマンドプロンプトを管理者モードで起動
1. FORMATコマンドを実行する。

```bat
FORMAT ドライブレター: /FS:exFAT
```
※ドライブレターはコロン付きで指定すること

## 補足
エクスプローラ・ディスクの管理からはNTFSしか選べません。
Mac初心者がXamarin Studioを使用してSimulatorでデバッグ出来るまで

# この記事はMac初心者の自分が躓いた箇所を記載しています。
もしかするとこんな初歩でと思われた方もいらっしゃるかと思いますが、
暖かい目で見守って頂けると幸いです。
では始ま〜り〜始ま〜り〜

---
# なんてこった！！ダウンロードする物がとにかく多い
---
# ではまず云々言う前に下記の物をダウンロードしましょう
<dl>
    <dt>Android</dt>
    <dd>SDK</dd>
    <dt>iOS</dt>
    <dd>Simulator</dd>
</dl>
---
# 全然ダウンロード点数が少ないと思ったあなた！！
<div style="text-align: center;">
<span>　　　　　　</span><img src="https://qiita-image-store.s3.amazonaws.com/0/43058/aad115bd-e6f4-128b-30d5-618082995b61.png"/>
</div>
---
# まずはAndroidのSDKから!!
1. XamarinのツールからSDK Managerを選択
2. SDK Managerウィンドウで必要なSDKをインストールします。
3. とりあえずAndroidのSDKはVersion毎にあるので、全てダウンロードするとパケット制限値に引っ掛かるかもしれないので最新のSDKだけダウンロードして下位バージョンはひっそりちょくちょくダウンロードすると良いと思います。

---
# iOSのSimulatorダウンロードしましょう
1. XCodeのPreferencesからCompornentsタブにある物をダウンロードしましょう。
2. 対象としているiOSのバージョンを選択してダウンロードしましょう。
3. こちらもAndroidと同じで１つのSimulatorのサイズが大きいので、気をつけてダウンロードしましょう

---
# ダウンロードには気をつけて！
<span>　　　　　</span><img src="https://qiita-image-store.s3.amazonaws.com/0/43058/aad115bd-e6f4-128b-30d5-618082995b61.png"/>

---
# デバッグ
ここまでくればあとはXamarinでDebugを<br>Simulatorにすれば何の問題もなくデバッグ出来ます。
あとは煮るなり焼くなり好きに出来ますので、快適なXamarin生活を堪能して下さい.
出来ればこれからXamarinについて記事を上げていきたいと思います。
Mac: pecoでカーソルキーを使ったら表示がバグったときの対処法


ターミナルの出力をフィルタリングしてくれる[peco](https://github.com/peco/peco)をMacでインストールしたのですが、カーソルキー（矢印キー）を使うと、下記のように表示がバグりました：

| 入力 | pecoの入力ラインに表示される出力 |
|--------|--------|
| ↑ （上キー）  | `[A`       |
| ↓ （下キー） |  `[B`      |
| → （右キー） |   `[C`     |
| ← （左キー）  |  `[D`      |

調べた結果、iTerm2の設定が悪かったようなので、それを直す方法をシェアします。

## 環境（この話の前提）

- OS X El Capitan 10.11.6
- iTerm2 3.0.9
- zsh 5.2 (Homebrewで入れたもの)

## 原因

自分のケースでは、実際に叩いているキーと、ターミナルがプログラムに送るコードが違うことが原因でした。

[FAQ - iTerm2 - macOS Terminal Replacement](https://www.iterm2.com/faq.html)

> Q: Why my arrow/HOME/END keys are not working?
> 
> A: When the terminal type of your sessions is set to one of those "xterm" types, iTerm2 handles the arrow keys, the home key, and the end key in a special way. 

つまり、 **iTerm2で「Terminal Type」を「xterm」（あるいはxterm-256colorなど）にすると、矢印キーとHomeキーとEndキーが、特殊な形でプログラムに送信される** 、とのことです。

もっと詳しい原理については下記で説明されているので、気になる方はご覧ください。

[terminal - Caret square bracket square bracket `A ^[[A` - What does it mean? - Unix & Linux Stack Exchange](http://unix.stackexchange.com/questions/222901/caret-square-bracket-square-bracket-a-a-what-does-it-mean)

## 対処法

iTerm2のキーマップを変更します。

1. 設定画面(Preferences)で下記の設定箇所に移動する：
    - 「Preferences... > Profiles > （自分が使っているプロファイル） > Keys」
2. 「Key Mappings」の表の下に並んでいるボタン「Load Preset...」を選択し、「Terminal.app Compatibility」に設定する。

この設定をして再びpecoを使うコマンドを叩くと、カーソルキーが使えるようになっているはずです。

以上です。
"JetPack for L4T"公式ドキュメントの和訳

#記事の目的
Jetson TX1およびJetson TK1に開発環境をインストールするJetPack L4Tに関して、
NVIDIA公式ドキュメントが英語だったので、日本でのJetson普及に一役買うために頑張って和訳してみました。
意訳を含むので間違い等ありましたらバシバシご指摘ください。
NVIDIA公式ドキュメントリンク：https://developer.nvidia.com/embedded/downloads

#JetPack L4Tとは
「Tegra向けのLinuxを対象としたJetson開発環境(=JetPack L4T)」は「Jetson組込みプラットフォーム」に必要な開発環境の自動インストールとセットアップを行うインストーラである。また、インストール実行時に「Jetson開発キット」を最新のOSイメージに書き換える。「JetPack L4T」は「Jetson TX1開発キット」および「Jetoson TK1」向けのインストーラである。

「JetPack L4T」はホストPC(Ubuntu14.04)とターゲットデバイス(Jetson開発キット)両方に対するツールやAPI群、パッケージ(ミドルウェアやサンプル、ヘルプなどのドキュメント)が含まれており、これにより開発環境の準備ができ、「Jetson開発キット」の開発を始めることができる。これら一式の開発ツールは「Jetson組込みプラットフォーム」をターゲットにしており、LinuxのUbuntu 14.04(64bit版)でのみ使用可能である。

#動作環境(System Requirements)

##ホストPC
* LinuxのUbuntu 14.04(64bit版)
 * インターネットに接続可能
 * 最低10GBの容量の空きが必要(JetPackのインストールに必要)

##ターゲットデバイス
* Jetson開発キット
 * ホストPCとJetson開発キットを接続するためのUSB(Micro-Bケーブル)が必要(Jetson開発キットに同梱されている)
 * USBハブやUSB接続のキーボード、マウスなどが必要(Jetson開発キットには同梱されていない)
 * 外部のHDMI対応ディスプレイに接続するためのHDMIケーブルが必要(Jetson開発キットには同梱されていない)
 * ホストPCと直で接続もしくは同じローカルネットワーク内でホストPCと接続するためにイーサネットケーブルが必要(には同梱されていない)
Windows+Git Bash環境でPython文字化け


Git BashとCmderで快適bash生活始めようとしたらPythonが文字化けした。

```bash
$ python -c "print('日本語')"
譌･譛ｬ隱・
```

## 結論

+ `chcp.com 65001`でコードページをUTF-8にする
+ `export PAGER=less`でページャにlessコマンド(Git for Windowsに付属)を指定する

つまり以下の二行を`.bashrc`に追加だ。

```bash:.bashrc
chcp.com 65001
export PAGER=less
```

結論としては以上だが、そこに至った背景も残しておく。

## 問題1: 文字化け

```bash
$ python -c "print('日本語')"
譌･譛ｬ隱・
```

### 調査

思いつく限りの文字エンコーディング確認コマンドを打った。

```
$ echo $LANG
ja_JP.UTF-8
$ echo $PYTHONIOENCODING
utf-8
$ python -c "import sys; print(sys.stdout.encoding)"
utf-8
$ python -c "import sys; print(sys.getdefaultencoding())"
utf-8
$ python -c "import locale; print(locale.getpreferredencoding(False))"
cp932
```
ほとんどUTF-8と返ってくる。
`locale.getpreferredencoding()`だけはcp932っぽい応答をしたが、[ドキュメント](http://docs.python.jp/3.5/library/locale.html#locale.getpreferredencoding)によるとこれは:

> テキストデータをエンコードする方法を、ユーザの設定に基づいて返します。ユーザの設定は異なるシステム間では異なった方法で表現され、**システムによってはプログラミング的に得ることができないこともあるので、この関数が返すのはただの推測**です。

とのことでいまいちあやしい。
そうこうしている中で`sys.stdout`の[ドキュメント](http://docs.python.jp/3.5/library/sys.html#sys.stdout)に以下の記述を見つけた:

> 文字エンコーディングはプラットフォーム依存です。**Windows では、ストリームが対話型 (isatty() メソッドが True を返す場合) であれば、コンソールのコードページが**、それ以外では ANSI コードページが使用されます。その他のプラットフォームでは、ロケールのエンコーディングが使用されます (locale.getpreferredencoding() を参照)。

コードページ…！

### 対処: コードページ変更
コードページを知らなかったのでググった。`chcp`コマンドで設定するものらしい。
Git Bash上からでも`/C/windows/system32`にパスが通っていれば、拡張子付きの名前`chcp.com`で呼び出せる。

```
$ chcp.com          # コードページ確認
現在のコード ページ: 932
$ chcp.com 65001    # コードページ設定(UTF-8)
$ python -c "print('日本語')"
日本語
```

晴れて文字化けを退治した。

### 問題2: ヘルプ表示エラー

Pythonでヘルプが見れなくなってしまった。`Not enough memory.`と表示される。

```python
>>> import sys
>>> help(sys.argv)
Not enough memory.
```

### 調査

`chcp 65001`の環境下ではWindowsの`more.com`がうまく動作しないらしい。
表示したい内容が数ページに跨る時に、`-- More (40%) --`とか表示してキー入力を促すもの。こういう機能はページャと呼ばれる。

Linuxでは通常`less`コマンドがその役割をする。
使えなくなった`more.com`の代わりに`less.exe`を使いたい！

## 対処: ページャ変更
Pythonは環境変数`PAGER`に指定しておけばそれを使ってくれるっぽい。
ドキュメントでは特にページャへの言及は見つけきれなかった。自明の事なのか、Python以外の機能だからなのか。

```bash
$ export PAGER=less
$ python
```
```python
>>> import sys
>>> help(sys.argv)  # ここから下はlessの画面で表示されるため、一旦Pythonインタプリタは隠れる
Help on list object:

class list(object)
 |  list() -> new empty list
 |  list(iterable) -> new list initialized from iterable's items
 |
 |  Methods defined here:
 |
...
```

めでたくhelpが復活した。
今回はPythonのヘルプ表示で気がついたが、他にも`more.com`を使っているものは同じ問題にぶつかりそう。
その場合も`export PAGER=less`で解決するものもあるかも。

## 余談

### getpreferredencodingいまいち
解決した状態で再び`locale.getpreferredencoding()`を実行してみる。

```
$ python -c "import locale; print(locale.getpreferredencoding(False))"
cp932
```

やっぱり`getpreferredencoding`による取得はいまいちあやしい。

### cmd /? が英語になる
`chcp 65001`を設定した状態だと`cmd /?`の結果などは英語になります。
`start cmd /?`とすれば日本語が表示されます。

参考:
[コマンドプロンプト/英語モード・日本語モードの切り替え方法・chcp - Windowsと暮らす](http://win.just4fun.biz/%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%97%E3%83%AD%E3%83%B3%E3%83%97%E3%83%88/%E8%8B%B1%E8%AA%9E%E3%83%A2%E3%83%BC%E3%83%89%E3%83%BB%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%83%A2%E3%83%BC%E3%83%89%E3%81%AE%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88%E6%96%B9%E6%B3%95%E3%83%BBchcp.html)

### PAGERの仲間
gitでは環境変数`GIT_PAGER`も使えるらしい。

## 履歴
2016/09/27 chcpについて記載
2016/10/09 PAGERについて追記
Xcode8 + Swift3 + CocoaPods で pod trunk push が失敗する場合の対処法

# 概要

CocoaPodsに新しいバージョンを更新しようとしたらいくつかハマったので共有します。

# ケース1

## 状況

Swift3対応したライブラリをアップしようとしたら、大量のエラーが発生。
--verbose で見るとどうやら Swift2.3でコンパイルされている。

## 解決策

プロジェクトフォルダ直下で下記コマンドを実行後、再度アップすることで解決。

~~~bash
$ echo 3.0 > .swift-version
~~~



# ケース2 

## 状況

次のようにバージョンアップ作業をしていたら

```bash
$ pod trunk push ライブラリ名.podspec
```

下記エラーが発生しました。

> ERROR | [iOS] unknown: Encountered an unknown error (Simulator iPhone 4s is not available.) during validation.

エラーを検索すると、いくつかヒットします。

Can't do `pod trunk push` for a Swift 3.0 library #5515
https://github.com/CocoaPods/CocoaPods/issues/5515

[Xcode 8 beta] pod spec lint: "iPhone 4s is not available" #5519
https://github.com/CocoaPods/CocoaPods/issues/5519

Fix linting with Xcode 8 #5529
https://github.com/CocoaPods/CocoaPods/pull/5529

最後のURLを見る限り、どうやら解決済みのようです。

GitHubに飛ぶと
https://github.com/CocoaPods/CocoaPods/releases
修正済みバージョンが上がってます。

## 解決策

Homebrewの人は

```bash
$ brew info cocoapods
```

を叩くと確認できると思いますが。

実は修正済みバージョンはまだ、安定版ではなく開発版です。

> cocoapods: stable 1.0.1 (bottled), devel 1.1.0.rc.2

## 開発版をアップグレードする場合

```bash
$ brew upgrade --devel cocoapods
```

で、開発版がインストールされます。
raspberrypiでredisとphpredisadminを使う


### 概要

- redisのインストール
- phpとapacheのインストール
- phpredisadminをインストールするためのcomposerのセットアップ
- phpredisadminのインストール
- phpredisadminの設定


### redisのインストール
raspberrypiで運用しているOSがraspbian whezzy/jessieの場合は、

```
# apt-get install redis-server
```

でインストールできます。
それぞれの場合においてインストールされるバージョンは、raspbian whezzyの場合、

```
# redis-server -v
Redis server version 2.4.14 (00000000:0)
```
raspbian jessieの場合は、

```
# redis-server -v
Redis server v=2.8.17 
```

です。
raspbian whezzyの場合はphpredisadminを使用するにあたり、設定ファイルを作成する必要があります。
詳細は「phpredisadminの設定」のセッションで説明します。


### phpとapacheのインストール

すでにapacheをインストールされている方はphp5ともにインストールされているはずなのでインストールせずに次のセッションへ進んでください。

phpredisadminを実行するにはブラウザ経由で表示させる必要があるので、phpとapacheをインストールします。
以下のコマンドでインストールできます。

```
# apt-get install php5 apache2
```

もし、上記のコマンドを実行した際に、「パッケージの取得ができませんでした。」という旨の通知があった場合は、

```
# apt-get update
```

を実行してから、再度試してください。


### composerのセットアップ
phpredisadminはaptのパッケージにはまとめられていないので、composerを用いてインストールします。

まず、composerのスクリプトファイルをcurlコマンドで取得します。

```
# curl -sS https://getcomposer.org/installer | php
```

次にこの取得したcomposerのスクリプトファイルをパスを通すために```/usr/local/bin```に移動させます。

```
# mv composer.phar /usr/local/bin/
```

そして、移動させたフォルダへ移動させ、シンボリンクをcomposerで作成し、以降はcomposerで通せるようにします。

```
# cd /usr/local/bin
# ln -s composer.phar composer
```

以上で

```
# composer ...
```
で使えるようになります。


### phpredisadminのインストール
先ほど導入したcomposerを用います。

インストールしたいフォルダに移動させます。
以下の場合は、apacheのデフォルトドキュメントルートにインストールする設定です。

```
# cd /var/www/html
# composer create-project -s dev erik-dubbelboer/php-redis-admin phpredisadmin
```


### phpredisadminの設定
前述したとおり、raspbian whezzyの場合は、phpredisadminで用いるコマンドが異なるため、使うコマンドを変更するように設定ファイルに記述する必要があります。
そこで、phpredisadminをインストールしたディレクトリへ移動します。

```
# cd phpredisadmin/includes
```

以下のコマンドでサンプルの設定ファイルをコピーします。

```
# cp -p config.sample.inc.php config.inc.php
```

コピーしたファイルを開き、以下の箇所を変更します。

```
# nano config.inc.php
```

```php:config.inc.php
'keys' => true
```

最後にapacheとredisを起動させ、

```
http://localhost/phpredisadmin
```

にアクセスすると、redisをブラウザから操作できます。
UnsafeMutableRawPointer から UnsafeMutablePointer<T> にキャストする方法

`UnsafeMutableRawPointer` から `UnsafeMutablePointer<T>` にキャストする方法をずっと悩んでいましたが、やっとわかったので、ここにメモしておきます。

わざとらしいコードですが、一旦 `UnsafeMutableRawPointer` にしたポインタを `UnsafeMutablePointer<T>` にキャストして、`pointee` を更新する事で、オリジナルも更新された事がわかります。Playground でも動作します。

```.swift
// Swift 3.0 - Playground Ready
struct Context {
	var city = "Tokyo"
}

var context: Context = Context()
let rawPtr = UnsafeMutableRawPointer(&context)
let opaquePtr = OpaquePointer(rawPtr)
let contextPtr = UnsafeMutablePointer<Context>(opaquePtr)

context.city // "Tokyo"
contextPtr.pointee.city = "New York"
context.city // "New York"
```
localStorage のキー一覧をコンボボックスに表示、復元、削除する


コンボボックスの実装は`datalsit`で簡単にできる。

一覧出すだけでは芸が無いので

* ページを開いたとき最後に使用したキーで復元  
* 不要なキーを削除
* 入力したキーで保存

```html
<input type="text" id="storageKey" list="storageKeys">
<datalist id="storageKeys"></datalist>

```

```js
const DEFAULT_KEY = 'default', LAST_KEY = '__lastkey__';

$(function(){
    updateStorageKeys();
    loadContent(LAST_KEY);
});

/* datalistの更新 */
function updateStorageKeys() {
    var list = '', keys = Object.keys(localStorage);
    for (var i = 0, l = keys.length; i < l ; i++) {
        list += `<option value="${keys[i]}">${keys[i]}</option>`;
    }
    $('#storageKeys').html(list);
}

/* [-_a-zA-Z0-9] は許可 */
function getStorageKey() {
    var key = $('#storageKey').val().replace(/[^-\w]/g, '');
    if (key === '') key = DEFAULT_KEY;
    if (key === LAST_KEY) key = DEFAULT_KEY;
    return key;
}

function saveContent( value ) {
    var key = getStorageKey()
    localStorage.setItem(key, JSON.Stringify(value));
    localStorage.setItem(LAST_KEY, key);
    updateStorageKeys()
}

function loadContent( key ) {
    return JSON.parse(localStorage.getItem(key));
}

function removeStorageKey(){
    var key = $('#storageKey').val(), keys = Object.keys(localStorage);
    if (key === LAST_KEY)  return;
    if (keys.indexOf(key) !== -1)  {
        localStorage.removeItem(key);
        updateStorageKeys();
        $('#storageKey').val('');
    }
}
```
VagrantとVirtualBoxでCentOS-6.7の仮想マシンを作成


# VagrantとVirtualBoxでCentOS-6.7の仮想マシンを作成

Vagrantfileを生成する。

```bash:hostOS
$ vagrant init
```

共有フォルダ用のディレクトリを作成する。

```bash:hostOS
$ mkdir rails
```

Vagrantfileの中身を以下に書き換える。

```rb:Vagrantfile
Vagrant.configure(2) do |config|
  config.vm.box = "bento/centos-6.7-i386"
  config.vm.network :forwarded_port, guest: 3000, host: 3000
  # config.vm.synced_folder "rails", "/home/vagrant/rails", ownner: "vagrant", group: "vagrant"
  config.vm.provider "virtualbox" do |vb|
    vb.gui = false
    vb.memory = "1024"
  end
end
```

vagrantを起動してVirtualBoxのマシンを作成する。
作成したマシンにSSHでログインする。

```bash:hostOS
$ vagrant up
$ vagrant ssh
```

# Rubyのインストール
### Gitのインストール
```bash:guestOS
$ sudo yum install -y git
```

### 必要なパッケージのインストール
```bash:guestOS
$ sudo yum install -y gcc-c++ glibc-headers openssl-devel readline libyaml-devel readline-devel zlib zlib-devel sqlite-devel kernel-devel
```

### `rbenv`のインストール
Rubyのバージョン管理ツール

```bash:guestOS
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ echo 'export RBENV_ROOT="/home/vagrant/.rbenv"' >> ~/.bashrc
$ echo 'export PATH="${RBENV_ROOT}/bin:${PATH}"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
```

### `ruby-build`のインストール

`rbenv install`コマンドを使えるようにする。

```bash:guestOS
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
$ source ~/.bashrc
```

### Ruby2.3.1をインストール

```bash:guestOS
$ rbenv install 2.3.1
```
rbenvに設定を反映させる

```bash:guestOS
$ rbenv rehash
```

Macでの標準のRubyバージョンを2.1.2に設定する

```bash:guestOS
$ rbenv global 2.3.1
```

設定を反映させる

```bash:guestOS
$ rbenv rehash
```

Rubyのバージョンが変更されたか確認

```bash:guestOS
$ ruby -v
```

Railsのインストール

```bash:guestOS
$ gem update --system
$ gem instal rails --version="4.2.0"
```

nodejsのインストール

```bash:guestOS
$ git clone https://github.com/creationix/nvm.git ~/.nvm
$ source ~/.nvm/nvm.sh
```

```bash:guestOS
$ NODE_VER=6.2.0
$ nvm install $NODE_VER
$ nvm alias default $NODE_VER
```

### ゲストOSとホストOSのフォルダを共有する。

ホストOSのVagrantfileの下記の行のコメントアウトを解除する。

```rb:Vagrantfile
config.vm.synced_folder "rails", "/home/vagrant/rails", ownner: "vagrant", group: "vagrant"
```
もう一度ゲストOSを再起動する。

```bash:hostOS
$ vagrant reload
```
ここで何もErrorが出ないで仮想マシンが立ち上がったら成功。

### 共有フォルダ設定がうまくいかない場合の処理
主な原因は
ゲストOSとVirtualBoxのGuestAdditionsのバージョンが異なるため、
GAの共有フォルダモジュールがうまく機能していない。

そのため、それぞれのバージョンをマッチさせるために、
`vagrant-vbguest`をインストールし、再起動する。

```bash:hostOS
$ vagrant plugin install vagrant-vbguest
$ vagrant reload
```

まだErrorが発生する場合（主にMacBook）、Kernelのセットアップをする必要がある。

```bash:hostOS
$ vagrant ssh
```
```bash:guestOS
$ sudo yum update kernel -y
$ exit
```
もう一度ゲストOSを再起動する。

```bash:hostOS
$ vagrant reload
```

### Railsプロジェクトを作成する
Railsプロジェクトを作成する。

```bash:hostOS
$ cd ~/rails
$ rails new sample
```

無事にRailsプロジェクトを作成できたら、以下のコマンドを実行して、ブラウザから確認する。( http://0.0.0.0:3000 )

```bash:hostOS
$ cd ~/rails/sample
$ rails server -b 0.0.0.0
```
git リポジトリ移行 管理構成変更など　

### gitリポジトリ管理ツールはたくさんあります。管理ツールを切り替える際に必要となりそうな移行作業をまとめてみました。

#1.そのまま移行する場合

```
git clone --mirror [移行元リポジトリurl]
cd [リポジトリ]
git push --mirror [移行先リポジトリurl]
```

こちらを参考にさせていただきました。
http://qiita.com/tanacasino/items/901723e3463bac38f40e

# 2.コミットログを書き換えてから移行する場合

例えば、使用したメールアドレス、ユーザ名等を書き換える必要がある場合。
以下では全ブランチに対してユーザtestがコミットしたログのメールアドレスを一律でtest@com更新します。これをやると新しいコミットに作り直されるのでtagもあわせて更新しています。

```
git clone --mirror [移行元リポジトリurl]
cd [リポジトリ]

git filter-branch --tag-name-filter cat --commit-filter '
        if [ "$GIT_AUTHOR_EMAIL" = "test@com" ];
            then
                GIT_AUTHOR_NAME="test";

git push --mirror [移行先リポジトリurl]
```

# 3.リポジトリの切り方を変えてから移行したい

例：
【移行前の管理構成】
CreateMenuAppという1つのリポジトリで管理。

```
CreateMenuApp(リポジトリ)
 |-CreateMenuFrontEnd    ---------> サブフォルダ
 |-CreateMenuMail        ---------> サブフォルダ
 |-CreateMenuServerSide  ---------> サブフォルダ
```

【移行後】
CreatemenuAppリポジトリ配下のサブフォルダが大きくなってきたので、リポジトリとして切り出したい。
以下のように3つのリポジトリで管理したいとする。

```
CreateMenuApp(プロジェクト)
 |-CreateMenuFrontEnd    ---------> リポジトリ
 |-CreateMenuMail        ---------> リポジトリ
 |-CreateMenuServerSide  ---------> リポジトリ
```

以下コマンドで対応
filter-branchは、--allがないとmasterブランチのみしか置き換わらなかったので追記(2016/10/13)

```
# CreateMenuFrontEndをリポジトリとして切り出す
git clone --mirror [移行元リポジトリurl] CreateMenuFrontEnd
cd CreateMenuFrontEnd
git filter-branch --subdirectory-filter CreateMenuFrontEnd HEAD --all
git push --mirror [移行先リポジトリurl]
```

残りのリポジトリ管理させたいサブディレクトリについても同様の処理を行うと完了です。

以下記事を参考にさせていただきました。
http://qiita.com/uasi/items/77d41698630fef012f82
陳腐化しにくいテーブル設計のコツ


## (0.ゼロからやる場合)
### なにはともあれ、まずは**項目**集めから。
項目が集まらなければ何もしようがないので、とにかく要求／要望を持っている人から
そのシステムを作るにあたり必要となる項目を聞き出す。※実はここが一番難しいけど。

## 1. 項目が集まってきたらテーブルを作成する。
マスタ系とトランザクション系で大きく分類し、関連する項目をまとめテーブルにする。

例）　社員、品目　など固定的に参照されるものはマスタ系
　　　お知らせ、記事　など常にデータが入れ替わっていくものはトランザクション系

※この段階というより、要件定義フェーズでこの意識で聞けるとスムーズかも。

## 2. 主キーを決めて、参照関係を決める。
作るシステムの性格やデータベースにもよるが、
id列が主キーになるパターンが増えてきている。よく企業システムなどで利用される複数の項目でキーを表す複合主キーのアプローチは、少し下火になってきているような気がする。（個人的には）

参照関係の決め方は大体下記パターン。
　１：１　例）国：首都
　１：多　例）会社：社員
　多：多　例）工場：種類

さらに覚えておくといいのが、　一方が 0 の場合も成立しうるかどうか。
例）運転者：違反履歴　
１：多ではあるが、違反歴がない人も当然いるので、厳密には 1: 0もしくは多となる。
この違いは、画面設計などにも影響してくるので、要注意。


## 3. 項目ごとの属性を決める
NotNull属性　
　⇒　盲目的に全てにつけると面倒なコーディングになるので、
　　　業務上はもちろん、画面上も必須入力であるべき項目に対してのみ付けたほうがよい。
Default値
　⇒　insert時に特に指定しなかった場合に、自動で設定される値。地味に重宝する。
桁数を確認
　⇒　データベースによって桁数の許容範囲等々は変わってくるのできちんと確認すること。

## 4. ER図にして推敲する。
**ここからが本番!**
むしろ、このフェーズでいかに悩み改良できるかが、システムの良し悪しをきめる！
色々あるが、個人的には下記のようなポイントに注目して行う。

・　○○が１に対して、△△は複数であっているか？
　　ない場合もある？等の参照関係のシミュレーション。

・　削除した場合に残された参照関係をもつデータはどうなるか？
　　そのデータがなくなった場合にシステムはどう動くことになるか？

・　データ階層は適切か
　　例）ECサイトならルートのデータは、　店舗　なのか　販売エリア＞店舗　なのかetc..
　　
・　そうめったに変動しないのであれば、マスタに持たなくてもプログラムの定数でどうか？

・　列持ちテーブルになっていないか？
　　特殊な理由がない限り、基本的には行持ちテーブルで行うこと。

・　必須な項目／あると便利な項目／無くてもいい項目　この区別をしっかりと付ける。

・　検索処理を考えた時に、結合が増えることでコストが高くなる。
　　その場合は、検索条件をあえて検索対象テーブルに保持するのも考え方の１つ（正規化を崩す）


## 5. （日をおいて）さらに推敲＆他の人にもみてもらう

実際に、いくつかデータパターンを作ってみると、いろんなケースに気づけるので、オススメ。
Excelでもなんでもいいので、レコードの動きを視覚化することが大切。

## 6. クイックモデリングチェック項目
- データが入ってないカラムが多い
- １つのカラムに複数以上の意味がある
- データが重複している
- 名前から意味が分かりづらい
- 他のカラムに依存して値が変わるカラムがある
- 型が適切ではない。例）整数で１０桁＝１０億？
- NOT NULL制約を使っているか
- 外部参照キーの設定があるか
- 導出項目をもっていないか（持っている場合は理由があるか）
- フラグがありすぎるときは、少しでも減らせないか検討する

おわり。
とにかくイマジネーション＆経験を重ねるのみ！！
俺はAWSのキーをプログラム中に書きたくなかった

# 書いたもの

なので~/.aws/credentialsから読み込むことにした

```aws_credentials.py
import sys
import os

aws_profile = sys.argv[1]

credentials_path = os.path.expanduser("~/.aws/credentials")
with open(credentials_path, "r") as f:
    line = f.readline()
    while line:
        if "[{}]".format(aws_profile) in line:
            line_access_key = f.readline()
            aws_access_key = line_access_key.split("=")[1].strip()
            line_secret_key = f.readline()
            aws_secret_key = line_secret_key.split("=")[1].strip()
            break
        line = f.readline()

print "aws_access_key: %s" % aws_access_key
print "aws_secret_key: %s" % aws_secret_key
```

# 実行

```bash
$ python aws_credentials.py default
aws_access_key: xxxxxxxxxx
aws_secret_key: zzzzzzzzzzz
```

# おまけ

~/.aws/credentialsの中身はこんな感じだとする

```~/.aws/credentials
[default]
aws_access_key_id = xxxxxxxxxx
aws_secret_access_key = zzzzzzzzzzz
[fuck]
aws_access_key_id = shit
aws_secret_access_key = bitch
```
Laravel 5.3で認証関連機能を実装する方法


* Laravelにはユーザー認証に必要な機構を標準で備えていて、artisanコマンドを叩くだけで使えるようになるらしい。

	``` 公式マニュアルより抜粋
	Tip!! さっさと始めたいですか？
	インストールしたてのLaravelアプリケーションでphp artisan make:authを実行し、
	ブラウザでhttp://your-app.dev/register、もしくはアプリケーションに割りつけたその他のURLへアクセスするだけです。
	このコマンド一つで、認証システム全体のスカフォールドを面倒みます。
	```

## 参照

* 公式マニュアル
	* [Laravel 5.3 認証](https://readouble.com/laravel/5.3/ja/authentication.html)

	* 上記マニュアルにも記載があるが、以降の手順は「新しくインストールしたアプリケーションでのみ実行すべき」なので注意。
		* templateファイルとか、平気で上書きされます…。

## artisanコマンドによるscaffoldingの実行

* 以下のartisanコマンドで、認証に必要な設定が全て行われる。

	``` console
	cd /your/laravel/project/path
	php artisan make:auth
	(結果)
	Authentication scaffolding generated successfully.
	```

* 追加・編集されたファイルは以下のとおり。

	``` console
	# git add .
	# # git diff --name-status  origin/master
	A       app/Http/Controllers/HomeController.php
	A       resources/views/auth/login.blade.php
	A       resources/views/auth/passwords/email.blade.php
	A       resources/views/auth/passwords/reset.blade.php
	A       resources/views/auth/register.blade.php
	A       resources/views/home.blade.php
	A       resources/views/layouts/app.blade.php
	```
	
## 確認

* 「[http://your-app.dev/home](http://your-app.dev/home)」へアクセス。

	![login.png](https://qiita-image-store.s3.amazonaws.com/0/102123/36ca5186-72ee-c4d5-ca1d-402510aa2cd2.png "login.png")

* 「[http://your-app.dev/register](http://your-app.dev/register)」へアクセス。

	![register.png](https://qiita-image-store.s3.amazonaws.com/0/102123/4171bf3e-ee6e-f74a-ad31-c6a6ab0dd26a.png "register.png")


* 以上、本当にたった1コマンドで認証機能ができてしまった。。。恐るべし。

* 認証に使用するテーブル名を変更したい場合は、[Laravel 5.3の認証関連機能のテーブル名を変更する方法](http://qiita.com/LowSE01/items/cd30a9236156f8b15abd)を参照。
ディープラーニングフレームワーク Caffe 初心者のお試し報告

学習の実行

./build/tools/caffe train --solver=data/mytest0/mytest0_solver4.prototxt

ここでエラーとなります。
たとえば、diffが。（英文です）
Ubuntu 14.04　です。
実行できた方はよろしくお願いします。
MacでPDFを複数の画像ファイルに変換する一番簡単な方法

# PDFの各ページを画像ファイルにしたい

意外とありますよね。そんな場面。Macなら、何も追加でインストールする必要はありません。
Automatorを使うだけです。

## Automatorで設定する項目

以下のように、画面の左側にある項目を右側にドラッグ＆ドロップしていきます。PDFの分割は、「PDF > Split PDF」にあります。

![automator-pdfsplit.png](https://qiita-image-store.s3.amazonaws.com/0/33180/27c2912b-97c4-8acd-f0ae-d8dd03c645f4.png)

備忘録なので、あまり詳しくなくてすみませんが、Automator最高です！
【自分なりのNOTE】Controllerの概念。区切り方。MVCモデル設計の話し。

## Controllerの概念

モデルやビューは実体が複数あることは明確だ。
一方controllerは、**実体がなく**、モデルとビューの橋渡し役だ。区切り方は作り手に委ねられている。

controller自体が1つの実体とするなら、
人間の可読性を無視するなら、1つのファイルにまとめてもいいのだ。（パスだって変えようと思えば/usersや/messagesなど変えられるのでエンドユーザーにはユーザーフレンドリーが担保される）
逆説的に述べると、可読性のためにも分割していると言っていい。（開発者のためのForDeveloper設計）

## 今までの色々な意見（分け方）

**a. controllerはあくまで人間の認識に合わせる。ユーザーやチームが想定しやすいところに置くのが一番。(ForDeveloper, ForHuman設計)**

- URLからcontrollerが想定できるようにしたい(ForDeveloper設計)
- でなければ、/rankingsなのにusers_controllerは特定がしんどい（チームの共通認識だいじ。）
- しかし、コンテキスト(意味合い)に重きをおくと、人によって想定するものが違う可能性は多いにあり、こわい。

**b. 1つのモデルに対する一連の操作をまとめたものがcontrollerだ。(モデル依存)**

- メインとして出力するモデルがxxxならxxx_controllerという考え。
  - では、companiesとusers両者同じ画面に同じ重要度でだす場合は？
- カテゴリ一覧は/categories。だが、カテゴリに入っているユーザー一覧はusers_constrollerから出すべき
  - なぜならそのユーザー一覧は、Viewにとっては同じusersを出力してるに過ぎないのだから。
  - ソートとフィルターはクエリ（?filter=xxxx)を使う

**c. 可読性向上のために分割する。(ForDeveloper設計)**

- ファットになったり混沌としてきたら、aのように適材適所に分ける。


# controllerの分け方。あなたはどうする？

以下はあなたの想像力を膨らませるための例材。

model

- messages
- users
- categories
- **inquiries(問合せ一覧)**

view

- メッセージ一覧
- ユーザー一覧
- メッセージをくれたユーザー一覧
- ユーザーのランキングを表示
- カテゴリ一覧
- カテゴリ一覧をみながら特定のユーザーのメッセージ一覧を見て、メッセージが気に入ったらそのユーザーをカテゴリに追加する画面
- **問合せ一覧**
- **カテゴリ一覧をみながら特定のユーザーのメッセージ一覧を見て、メッセージが気に入ったらそのユーザーをカテゴリに追加する画面。ついでに問合せ一覧も出力しちゃう♡**
iOSで気軽に音をループさせる


#BGMとか環境音をループ再生させる

##はじめに
BGMをずっとループして使いたいとか、効果音を指定した回数だけ繰り返して鳴らしたいとか、そう言った時に気軽に使いたいなと思い、クラス化して楽に使えるようにしました。AVAudioPlayerをもとに自分なりに扱いやすくしただけです。

##準備
使いたい音源のファイルはナビーゲータエリアに追加しておく。
aif, caf, mp3, aac, m4a, mp4, wavに対応

##ちなみに
ループの際、最後まで再生し終えて最初に戻る時に、若干のラグが起こることがあります。
僕の場合は環境音をずっと鳴らしたかったので困っていたんですが、ファイル形式がmp3などの圧縮したファイルの場合に起こるようでした。wavやcaf,aifの非圧縮のファイルは大丈夫！
詳しくは`AVAudioPlayer gap`とかでググると出て来ます。


```swift:Sound.swift

import AVFoundation

class Sound{
    
    //playerを作成
    var player: AVAudioPlayer!
    
    init(fileNamed:String,volume:Float,numberOfLoops:Int){
        let fileNameStrings = fileNamed.componentsSeparatedByString(".")
        let fileName = fileNameStrings[0]
        let fileType = fileNameStrings[1]
        let url = NSBundle.mainBundle().URLForResource(fileName, withExtension: fileType)
        if let url = url {
            do {
                player = try AVAudioPlayer(contentsOfURL: url)
                player.numberOfLoops = numberOfLoops/* 0なら一回、自然数ならその数だけループ、負の数なら永久ループ */
                player.prepareToPlay()     //再生準備 (タイミングがシビアな時のみ)
                player.volume = volume
            } catch {
                //プレイヤー作成失敗
                fatalError("Failed to initialize a player.")
            }
            
        } else {
            //エラーを表示させる
            fatalError("Error loading sound resource: " + fileNamed)
        }
        
    }
    
    convenience init(fileNamed:String){
        self.init(fileNamed:fileNamed,volume:1.0,numberOfLoops:0)
    }

    //AVAudioPlayerのメソッドを流用。これで〇〇.player.play()でなく〇〇.play()で済む
    func play(){
        self.player.play()
    }
    
    func pause(){
        self.player.pause()
    }
    
    func stop(){
        self.player.stop()
    }
}

```
##使ってみる
再生とかvolumeのプロパティの扱いは基本的にはAVAudioPlayerと同じです。インスタンス化する際に少しは楽になったかと。

```swift:使用例
let bgm = Sound(fileNamed: "bgm.wav",volume:0.5,numberOfLoops:-1)
/*bgm.wavを0.5のvolumeで永久ループで再生できる*/

bgm.play()//再生
bgm.pause()//一時停止
bgm.stop()//停止

let se1 = Sound(fileNamed: "se1.wav")
/*se1.wavをvolume1.0で１回のみ再生する。*/

se1.play()//再生
```
##終わりに
BGMとかSEつける時に使えるかなぁ。不具合とかありましたら教えてください。
強化学習(DQN)

強化学習を勉強したのでまとめてみます。勉強時間はかなり短時間ですが、割と分かった気になったので、ポイントを記載してみたいと思います(数式は一切用いません)。このポイントを押さえてソースコードを読むと、理解が早いです。一部用語は私が勝手に定義したものもありますが、その他間違えていたら遠慮なくご指摘お願いします。

# 強化学習
強化学習を理解するにあたって、**環境**・**エージェント**・**トレーナー**の3人が登場します。その登場人物をベースに説明します。環境、エージェントは一般的に使われる用語ですが、トレーナーは筆者が勝手に名付けています。

## 環境
　エージェントが学習を行う舞台です。オセロだったりシューティングゲームだったりブロック崩しだったり。環境は**定量的な状態**と**行動パターン**、**ルール**(状態と行動を入力として次の状態と報酬を決定)を持ちます。ブロック崩しの場合を例に説明してみます。

 - **定量的な状態**: 現在のブロックの数やボールの位置。
 - **行動パターン**: バーを右に動かすか左に動かすかの2種類。
 - **ルール**: バーがボールに当たれば報酬は+5、ブロックを1つ崩せば+1、ボールを落とすと-50。

といった具合です。[Open AI Gym](https://gym.openai.com/)というサービスがありますが、これは**環境**を提供しているため、エージェントとトレーニングを実装すれば試すことができます。

## エージェント
　実際に学習を行って成長する個体です。ブロック崩しの場合、バーを操作する仮想のプレイヤーということになります。環境の定量的な状態を入力として、取るべき行動を決めます。ここでの行動決め(**ポリシー**)を学習によって最適化していくわけです。行動を決定する方法としては、**ε-greedy法**がよく使われます。
　学習した結果を元にポリシーを決定するのは無難な選択ですが、実はそれ以外にもっと良い選択肢があるかもしれないのに、その可能性を潰すことにもなります。ε-greedy法では、一定の確率でランダムに行動を決めます。こうすることで、より良い結果を得る可能性が高まります。

## トレーナー
　トレーナーは環境とエージェントをコントロールし、**エピソード**という単位で学習を繰り返します。1回のエピソードの中で、環境を初期化し、エージェントに行動をさせ、受け取った報酬を元にエージェントの行動モデルを最適化していきます。最適化の方法としては、**TD学習**がよく使われます。ある時点の行動の価値は、その次の行動、さらにその次の次の行動、と繰り返し予測していって最終的にゴールにたどり着けるかどうかによって初めて分かります。しかしこれでは計算コストが大きいため、ある時点の行動と次の行動の予測結果によってのみ決めようというのがTD学習です。

# Q学習とDQN
　最後に深層学習による強化学習の手法の変化について簡単に記載します。
　深層学習が登場する以前のQ学習では、ポリシーを状態と行動のマトリクスで保持していました。ある状態に対するある行動の価値はどれくらいかというのをマトリクスで管理し、より価値の高い行動を選択します。そのため、例えば定量的な状態に座標のような連続した値を持たせようものなら、マトリクスが膨れ上がってしまうため、限度がありました。
　深層学習の登場によって、ポリシーをマトリクスの代わりにニューラルネットワークで管理できるようになりました。これがDQNです。周知の通り、深層学習では特徴量を抽出できるため、環境の定量的な状態を人が選定してあげる必要はなく、画像をそのまま渡すことができます。つまり人が視認して学習するのに近い学習の形が可能となったわけです。
openFrameworks 0.9.2 を El Capitan + Xcode8 で動かしてみる

# 環境
- El Capitan
- Xcode8
- of_v0.9.2_osx_release

# エラー
El Capitanの環境でXcode8にあげたら、openFrameworksでこんなエラーが出ました。
```'QuickTime/QuickTime.h' file not found```
   
# 対応
1. リンク先からMacOSX10.11sdkをダウンロードします
https://dl.dropboxusercontent.com/u/92337283/OF/MacOSX10.11.sdk.zip     
      

2. Finerを開き、アプリケーション -> Xcode -> パッケージの内容を表示 を選択します
<img width="1280" alt="スクリーンショット 2016-09-27 16.30.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/96807/3dc44695-7ebd-4ab8-8e34-737271ae220e.png">   
   

3. 開いたフォルダの中の以下の階層に、ダウンロードして解凍したMacOSX10.11.sdkをコピペします
<img width="1280" alt="スクリーンショット 2016-09-27 17.00.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/96807/0389ac66-f435-a0a4-292f-0a06b3a3ea97.png">   
      
4. Base SDKを、OSX10.11に変更します
<img width="2560" alt="スクリーンショット 2016-09-27 19.58.22 のコピー.png" src="https://qiita-image-store.s3.amazonaws.com/0/96807/0d35ffc2-ef7b-7e79-14d9-488bab3baaa9.png">   
   <img width="2560" alt="スクリーンショット 2016-09-27 19.52.31 のコピー.png" src="https://qiita-image-store.s3.amazonaws.com/0/96807/98b983b3-b221-74df-e8ff-4af82f64d84a.png">

なかなか上手くいきませんでしたが、どちらもOSX10.11にすれば大丈夫でした！
5. 完成！


# 参考リンク
- [リンク](https://forum.openframeworks.cc/t/quicktime-quicktime-h-file-not-found/24494/3)
UISearchBarのカスタマイズ

**iOS13では禁止になっているようです。**
[UISearchBarのプライベートなプロパティにアクセスするコードがiOS 13では禁止になったようです](
https://qiita.com/ktanaka117/items/1a30c4c6052cd8e1a0b7)

---




#下準備

##ブラー無効化

```swift
extension UISearchBar {
  func disableBlur() {
    backgroundImage = UIImage()
    translucent = true
  }
}
```

##textField取得

```swift
extension UISearchBar {
  var textField: UITextField? {
    return valueForKey("_searchField") as? UITextField
  }
}
```

##アクセサリ取得

```swift
extension UITextField {
 //クリアボタン
  var rightButton: UIButton? {
    return valueForKey("_clearButton") as? UIButton
  }
 //虫眼鏡
  var lupeImageView: UIImageView? {
    return leftView as? UIImageView
  }
}
```

##ViewのRenderingModeをalwaysTemplateに変更

```swift
extension UIButton {
  func becomeImageAlwaysTemplate() {
    if let image = imageForState(.Highlighted) {
      let paintedImage = image.imageWithRenderingMode(.AlwaysTemplate)
      setImage(paintedImage, forState: .Normal)
      setImage(paintedImage, forState: .Highlighted)
    }
  }
}

extension UIImageView {
  func becomeImageAlwaysTemplate() {
    image = image?.imageWithRenderingMode(.AlwaysTemplate)
  }
}
```

#カスタマイズ

## 角丸

```swift
searchBar.textField.layer.cornerRadius = searchBar.textField.bounds.height / 2.0
searchBar.textField.layer.masksToBounds = true
```

毎回masksToBoundsを設定する必要あり

##背景色透過

```
searchBar.disableBlur()
searchBar.backgroundColor = UIColor.clearColor()
```

##placeholderの文字色変更

```
searchBar.placeholder = placeholder
searchBar.textField?.attributedPlaceholder = NSAttributedString(string: searchBar.placeholder ?? "", attributes: [NSForegroundColorAttributeName: UIColor.whiteColor()])
```

##入力部分の背景色変更

```
searchBar.textField?.backgroundColor = UIColor.redColor()
```

##入力文字色変更

```
searchBar.textField?.textColor = UIColor.blackColor()
```

##クリアボタンの色変更

```
searchBar.textField?.rightButton?.becomeImageAlwaysTemplate()
searchBar.textField?.rightButton?.tintColor = UIColor.whiteColor()
```

##虫眼鏡アイコンの色変更

```
searchBar.textField?.lupeImageView?.becomeImageAlwaysTemplate()
searchBar.textField?.lupeImageView?.tintColor = UIColor.whiteColor()
```

##カーソル・選択範囲色の変更

```
searchBar.tintColor = UIColor.whiteColor()
```
iOS10のSafariでuser-scalable=no が効かなくズームがされる問題への対策

iOS10から、Safariで `viewport` の `user-scalable=no` が効かなくなりました。
ブラウザゲームなどを開発してる場合、ダブルタップで拡大されてしまうためクリティカルな問題になります。
~~Appleへの恨みを込めつつ~~、対策方法を調べました。

なお、
参考サイト： http://stackoverflow.com/questions/37808180/disable-viewport-zooming-ios-10-safari
に近いですが、このままではうまくいかなかったので、ちょっとアレンジしています。


# 複数指で拡大縮小が出来てしまうのを防ぐ

`touchstart` のイベントを見て防ぎます。
なお、子要素で、`stopPropagation()`をしてる場合、バブリングフェーズで`preventDefault()`をしても効果がなくなるため、意図的にキャプチャフェーズで`preventDefault()`をしています。
（`addEventListener`の第三引数が`true`になります。）

```js

document.addEventListener('touchstart', event => {
  if (event.touches.length > 1) {
    event.preventDefault();
  }
}, true);
```

# ダブルタップを防ぐ
`touchend` のイベントを見て防ぎます。
こちらも同様に、意図的にキャプチャフェーズで`preventDefault()`をしています。
（`addEventListener`の第三引数が`true`になります。）

なお、いくつかのサンプルサイトでは0.3秒の判定で対策されてましたが、私の環境では0.45秒は必要でした。
バッファも考慮し、0.5秒(500ms)としました。
時間測定もあえて`DateTime`ではなく、`performance.now()`を使っています。

```js

let lastTouch = 0;
document.addEventListener('touchend', event => {
  const now = window.performance.now();
  if (now - lastTouch <= 500) {
    event.preventDefault();
  }
  lastTouch = now;
}, true);
```

もしくは、setTimeoutを使ってもいいです。

```js

let flag = false;
document.addEventListener('touchend', event => {
  if (flag) {
    event.preventDefault();
  } else {
    flag = true;
    setTimeout(() => {
      flag = false;
    }, 500);
  }
}, true);
```

# ~~フォームにカーソル移動時に拡大される~~

この問題は`user-scalable=no`とは関係ありませんでした。
情報提供を頂いた harapeko_wktk さんありがとうございました。

> iOS10未満はviewportにinitial-scale=1, minimum-scale=1, maximum-scale=1でも拡大防止できていましたが、できなくなったようです。
> iOS10からはfont-sizeを16px以上にするかuser-scalable=noが必要という結果でした。

~~`16px`未満のフォントサイズのときに拡大がされてしまうようになりました。~~
~~こちらに関しては、`16px`以上に`font-size`を指定する事で拡大を阻止出来ます。~~

~~`16px`未満のまま防止する方法はもしかするとあるかもしれませんが、Safariの仕様変更の意図を考えるとあまり`16px`以下に拘る必要性は無いかなと個人的には解釈しています。~~


# 困った問題

さて、これで基本的には解決するはずですが、解決しないこともあります。

 - 時々ダブルタップをすると、`lastTouch`の値が2000を超え、上記処理では拡大を防ぐことができない。
 - 時々ダブルタップをすると、touchendイベントが1回しかこないのにダブルタップ扱いになる。

~~もうこれ完全にSafariのバグだろと思いつつ、~~
私はいろいろ試行錯誤したあげく、最終的に以下の手段を取りました。

# （最終手段） 拡大されたくない要素に対して、touchendイベントをキャンセルする

```js
element.addEventListener('touchend', event => {
  event.preventDefault();
}, false);
```

これをすると、いくら連打してもダブルタップしてもズームはされなくなりました。
但し、touchendイベント自体がキャンセルされてしまうため、この後に`addEventListener` でイベントが登録できなくなります。
`preventDefault` をするのは処理の最後に書きましょう。

# (追記）cssで対応する

コメント欄で教えていただきました。これがもっとも対応簡単だと思います。

```js
touch-action: manipulation;
```