OmniAICreator/Qiita-1.07M huggingface dataset:
ある配列に単要素を加えた配列を破壊的変更を加えずに得る

ある配列に要素を加えて新たに配列を得たいという場合、
pushするともとの値まで書き換わってしまいます。

```ruby
a = [1, 2, 3]
b = 4

c = a << b
p c
# => [1, 2, 3, 4]
p a
# => [1, 2, 3, 4]
```

rubyのArrayメソッドのなかに破壊的変更を加えずに返すメソッドがあればいいのですが見当たりません。
https://ruby-doc.org/core-2.3.0/Array.html

以下に3つやり方を示します。
([@yancha](http://qiita.com/yancya)さん、[@from_kyusyu](http://qiita.com/from_kyushu)さんにご教示いただきました。ありがとうございます。)
# Array#+ を利用する

実はrubyの配列は+記号で簡単に結合することが出来ます。これが一番シンプルでメジャーなやり方のようです。

```ruby
a = [1, 2, 3]
b = 4

c = a + [b] #Array#+を利用
p c
# => [1, 2, 3, 4]
p a
# => [1, 2, 3]
```

# *を用いて変更元の配列を展開
2つ目は*を用いて配列を展開してしまう方法です。こちらもbを配列に入れる必要が無いので、良さそうです。

```ruby
a = [1, 2, 3]
b = 4

c = [*a, b] #*で配列aを展開
p c
# => [1, 2, 3, 4]
p a
# => [1, 2, 3]
```

# Array#dupを使う
dupを使って変更元の配列をコピーしてやるやり方もあります。ですが上記2つに比べるとやや冗長な感じがします。

```ruby
a = [1, 2, 3]
b = 4

c = a.dup << b #dupでコピーした上でpushする
p c
# => [1, 2, 3, 4]
p a
# => [1, 2, 3]
```

# 番外編

## 論理和を利用する(※間違い)
自分がはじめに思いついた方法は論理和を取る方法でした。

```ruby
a = [1, 2, 3]
b = 4

c = a | [b] # 論理和を取る
p c
# => [1, 2, 3, 4]
p a
# => [1, 2, 3]
```
しかしながらこのやり方では入れたい要素がすでに追加されている要素の場合は意図した動作になりません
([@taram](http://qiita.com/taram)さんにご教示いただきました。ありがとうございます。)

```ruby
a = [1, 2, 3]
b = 2 # ここがすでにある値の場合

c = a | [b] # 論理和を取る
p c
# => [1, 2, 3] # 論理和を取っているので [1, 2, 3, 1] こうはならない
p a
# => [1, 2, 3]
```

# 結論
 * 加えたい値を単要素の配列にして+を用いて配列を結合する
 * *を用いて変更元の配列を展開する

のいずれかを用いればよいです。

ちなみに要素を削除したいという場合は-記号を用いれば良さそうです。

```ruby
a = [1, 2, 3]
b = 2 # ここがすでにある値の場合

c = a - [b] # -記号で要素を削除
p c
# => [1, 3]
p a
# => [1, 2, 3]
```

とはいえ結構よくある操作なので、Ruby自体に破壊的変更を加えずに単要素を追加、削除できるメソッドがあればよいのになと感じました。
また、今回投稿していろんな方にコメント頂いたことで間違いに気づくことができた上に正しいやり方も教えていただいてとても勉強になりました。
自分のようなエンジニアの社員1人の孤高系エンジニアにはQiitaはとてもいいサービスです！

# 追記
RailsではHashで同様のことをするためにHash#exceptというモンキーパッチのメソッドがあるようです。

```ruby
class Hash
  # Returns a hash that includes everything but the given keys.
  #   hash = { a: true, b: false, c: nil}
  #   hash.except(:c) # => { a: true, b: false}
  #   hash # => { a: true, b: false, c: nil}
  #
  # This is useful for limiting a set of parameters to everything but a few known toggles:
  #   @person.update(params[:person].except(:admin))
  def except(*keys)
    dup.except!(*keys)
  end

  # Replaces the hash without the given keys.
  #   hash = { a: true, b: false, c: nil}
  #   hash.except!(:c) # => { a: true, b: false}
  #   hash # => { a: true, b: false }
  def except!(*keys)
    keys.each { |key| delete(key) }
    self
  end
end
```
なぜかArray#exceptはないのですが、Hashを真似して書くとこんな感じになります

```ruby
class Array

  def except(*values)
  	dup.except!(*values)
  end

  def except!(*values) 
  	values.each {|v| delete(v)}
  	self
  end
  
end
```

Hashに入れるならArrayにも入れてほしいですね。
MySQLで自己結合の更新をする


MySQLで自己結合して更新する場合は、このような書き方でうまくいきました。

```sql:
update table_name t1, table_name t2
set t1.value = t2.value
where t1.id = t2.id;
```

「達人に学ぶ SQL徹底指南書」の「演習問題2-③：ランキングの更新」は解答のとおりに記述してもMySQLではエラーになります。

```sql:エラーになる
UPDATE DistrictProducts2 P1 
SET ranking = (SELECT COUNT(P2. price) + 1 FROM DistrictProducts2 P2 WHERE P1. district = P2. district AND P2. price > P1. price);
```

このようにランキングの入ったテーブルをサブクエリで作成して、その結果から値を更新すればうまくいきました。

```sql:更新できた
update DistrictProducts2 p1, (select p3.district as district, p3.name as name, (select count(p4.price) + 1 from DistrictProducts2 p4 where p3.district = p4.district and p4.price > p3.price) as ranking from DistrictProducts2 p3) p2 
set p1.ranking = p2.ranking where p1.district = p2.district and p1.name = p2.name;
```

他にいい方法があるかもしれません。
DockerでWordPressのテーマ開発を簡単にするリポジトリ

今回はDockerでWordPressのテーマ開発を行うことができるリポジトリを作りました。

DockerでWordPressのテーマ開発を行うのは検索すれば、たくさん出てくるのですが公式のWordPressのイメージを使いたかったので自分で構築しました。

リポジトリは　Github上で公開しています（[devwp-docker](https://github.com/satotakumi/devwp-docker)）

# 準備

[Docker](https://www.docker.com/)と[docker-compose](https://docs.docker.com/compose/)が入ってない場合はインストールを行います。

その後、クローンしてシェルスクリプトをたたけばコンテナを作ります。

```bash
$ git clone git@github.com:satotakumi/devwp-docker.git && cd devwp-docker
$ ./devwp.sh star
```

起動したら `http://localhost:8080/` で見れるようになるのでインストール後 Sample Themeテーマを選択します。

# 開発

`theme` ディレクトリの中を更新すればWordPressでも適用されるようになります。

# 困ったこと

[WordPressの公式イメージ](https://hub.docker.com/_/wordpress/)は、コンテナを作るときにWordPressをダウンロード&設置しているので、普通にマウントしようとするとエラーになってしまいます。

なので、適当なところにテーマディレクトリをマウントさせて起動したら `docker-compose exec`でシンボリックリンクを張っています。
GitHub のリポジトリを requirements.txt に含める

# 概要
[![English](https://img.shields.io/badge/English-here-lightgrey.svg?style=flat)](https://www.jkawamoto.info/blogs/include-github-repositories-to-requirements-txt/)
[PyPI](https://pypi.python.org/pypi) には登録されていないが，GitHub では公開されているライブラリを依存関係に含める方法．
また，`setup.py` から `requirements.txt` を参照している場合の対応方法について忘備録としてまとめる．

# requirements.txt
GitHub リポジトリの URL が https://github.com/rgmining/common の場合，
requirements.txt には，

```requirements.txt
-e git+https://github.com/rgmining/common.git#egg=rgmining_common-0.9.0
```

のように書く．`#egg=` 以降は <パッケージ名>-<バージョン> という書式にするようだ．
また，`pip-tools` を使って requirements.txt を生成している場合，
`requirements.in` には上記と同じ文字列を記入する．

# setup.py
今まで，`setup.py` では下記のように`requirements.txt`の内容を`install_requires`に渡していた．

```setup.py
from setuptools import setup, find_packages

def load_requires_from_file(filepath):
    with open(filepath) as fp:
        return [pkg_name.strip() for pkg_name in fp.readlines()]

setup(
    # その他の項目は省略
    install_requires=load_requires_from_file("requirements.txt")
)
```

`requirements.txt`にURLが含まれている場合は，もう少し改良してパッケージ名だけをリストアップする．

```setup.py
def take_package_name(name):
    if name.startswith("-e"):
        return name[name.find("=")+1:name.rfind("-")]
    else:
        return name.strip()

def load_requires_from_file(filepath):
    with open(filepath) as fp:
        return [take_package_name(pkg_name) for pkg_name in fp.readlines()]
```

また，URL部分は`setup`関数のキーワード引数`dependency_link`に渡す．

```setup.py
def load_links_from_file(filepath):
    res = []
    with open(filepath) as fp:
        for pkg_name in fp.readlines():
            if pkg_name.startswith("-e"):
                res.append(pkg_name.split(" ")[1])
    return res

setup(
    # 他の項目は省略
    install_requires=load_requires_from_file("requirements.txt"),
    dependency_links=load_links_from_file("requirements.txt"),
)
```

以上で，`python setup.py test`などとすると，GitHubからパッケージを用意してテストを実行できる．

# 参考
- [pip で github のリポジトリをインストール](http://qiita.com/trsqxyz/items/744ba3c8a123d52aa7fe)
Outlook で開くメール > 添付ファイルはUTF-8で

http://hamayu-office.with-web.info/weblog/troubleshooting/gmail

> もし、作られたファイルの文字コードが「Shift-jis」なら、「UTF-8」にしてからGmailで相手に添付ファイル送信すれば、文字化けせずに相手のOutlookできちんと開けます。

Shift_JISのテキストはダメの模様。
SQL migrate



```sql
timestampdiff(ss,xxxx, NOW() ) > 0
↓
timestampdiff(SECOND,xxxx, NOW() ) > 0



CHAR_LENGTH(RTRIM(CONVERT(integer, RIGHT(MAX(xxx), 9)) + 1))
↓
CHAR_LENGTH(RTRIM(CAST(RIGHT(MAX(xxx), 9) as SIGNED) + 1))


CONVERT(CHAR(1), CONVERT(integer, RIGHT(MAX(xxx), 9)) + 1)
↓
cast((cast(RIGHT(MAX(xxx), 9) as SIGNED) + 1) as char(1))


LEN(LTRIM(RTRIM(xxx)))
↓
CHAR_LENGTH(TRIM(xxx))

お金
REPLACE(CONVERT(VARCHAR,CONVERT(MONEY,BidInfo.xxx),1), '.00','')
↓
REPLACE(cast(cast(BidInfo.xxx as DECIMAL(15,4)) as char) , '.00','')

select DATE_FORMAT(NOW() - NOW(),'%d')-1

年
DATE_FORMAT(S.RakuRGPZ ,'%Y')
月
DATE_FORMAT(S.RakuRGPZ ,'%m')
日
DATE_FORMAT(DispInfo.xxx - NOW() ,'%d')-1 
時
DATE_FORMAT(DispInfo.xxx - NOW() ,'%H') 
分
DATE_FORMAT(DispInfo.xxx - NOW() ,'%i') 
秒
DATE_FORMAT(DispInfo.xxx - NOW() ,'%s') 



LEN(CONVERT(INTEGER, MAX(LEFT(xxx, 2)) + 1))
↓
CHAR_LENGTH(cast(MAX(LEFT(xxx, 2)) as SIGNED) + 1)


CONVERT(CHAR(1), CONVERT(INTEGER, MAX(LEFT(xxx, 2)) + 1))
↓
cast(cast(max(left(xxx, 2)) + 1 as SIGNED) as char(1))
```
Docker proxy 設定方法[Ubuntu 16.04]

# はじめに
systemd で立ち上がる Docker の Proxy の設定方法を毎回忘れるので残します。
> upstart であれば `/etc/default/docker` を修正するだけでした。


## 環境
Ubuntu 16.04
Docker version 1.12.1, build 23cf638


## 手順
```
sudo mkdir /etc/systemd/system/docker.service.d

sudo sh -c "cat << EOF > /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://proxy.example.com:8080" "NO_PROXY=localhost,127.0.0.1"
EOF"

sudo systemctl daemon-reload
sudo systemctl restart docker
```


## Document
https://docs.docker.com/engine/admin/systemd
画像のリサイズ(imagecopyresampled)

PHPの`imagecopyresampled`で

0. ユーザがフォームから画像を投稿
0. 縦横どちらも規定サイズ以下ならそのまま保存
0. 縦横比が規定サイズと等しければ縮小して保存
0. 縦横どちらも規定サイズより大きければ差の小さいほうに合わせて一旦縦横比を維持して縮小→はみ出した部分を中心を合わせてカット→保存

という作業をしました。

4のパターンの場合、`imagecopyresampled`1回でやろうとすると先にカットして縮小するため画像に黒い余白ができてしまったのでいったん縮小だけして保存→改めてカットという工程です

```php
// 画像のデータを取得
$data = @getimagesize($_FILES['upfile']['tmp_name']);

// 画像処理に使う関数名を決定する
$create = str_replace('/', 'createfrom', $data['mime']);
$output = str_replace('/', '', $data['mime']);

// 元画像リソースを生成する
$src = @$create($_FILES['upfile']['tmp_name']);

// 画像の縦横,拡張子を取得
$w = $data[0];
$h = $data[1];
$type = image_type_to_extension($data[2]);

// 保存する画像のサイズ
$dst_w = 600;
$dst_h = 900;

// 初期化
$sttX  = 0;
$sttY  = 0;
$src_w = $w;
$src_h = $h;

// 保存する画像に対する元画像の比率
$per_w   = $w/$dst_w;
$per_h   = $h/$dst_h;
$per_dif = $per_w - $per_h;

if ( $w <= $dst_w && $h <= $dst_h){ //　どちらも規定以下ならそのまま保存
    $dst_w = $w;
    $dst_h = $h;
} elseif ($per_w === $per_h) { // 縦横比が規定と等しければそのまま縮小
   // 何もしない
} else {
    // 縦横どちらも大きければいったん縮小して保存
    if ($per_w > 1 && $per_h > 1) {
        if ($per_dif > 0) { 
            // 縦に合わせて縮小
            $src_w = $w / $per_h;
            $src_h = $dst_h;
        } else {
           // 横に合わせて縮小
            $src_w = $dst_w;
            $src_h = $h / $per_w;
        }

        // リサンプリング先画像リソースを生成する
        $dst = imagecreatetruecolor($src_w, $src_h);

        // getimagesize関数で得られた情報も利用してリサンプリングを行う
        imagecopyresampled($dst, $src, 0, 0, 0, 0, $src_w, $src_h, $w, $h);

        // 一旦tmpとして保存
        $output($dst,'upload_img/temp'.$type);

        // tempを元画像としてリソースを再生成
        $src = @$create('upload_img/temp'.$type);

    }

    // 横が$dst_wより大きければ中心点から始点を計算
    if ($src_w > $dst_w) {
        $sttX = ($src_w - $dst_w)/2;
        $src_w = $dst_w;
    } else {
        $dst_w = $src_w;
    }
    
    // 縦が$dst_hより大きければ中心点から始点を計算
    if ($src_h > $dst_h) {
        $sttY = ($src_h - $dst_h)/2;
        $src_h = $dst_h;
    } else {
        $dst_h = $src_h;
    }
}
// リサンプリング先画像リソースを生成する
$dst = imagecreatetruecolor($dst_w, $dst_h);

// getimagesize関数で得られた情報も利用してリサンプリングを行う
imagecopyresampled($dst, $src, 0, 0, $sttX, $sttY, $dst_w, $dst_h, $src_w, $src_h);

// ファイル名を設定して保存する
$fname = "filename";
$photo = $fname.$type;
$output($dst,'upload_img/'.$photo);

// リソースを解放
if (isset($src) && is_resource($src)) {
    imagedestroy($src);
}
if (isset($dst) && is_resource($dst)) {
    imagedestroy($dst);
}
```
JUMAN++をPythonから使う


## はじめに

JUMAN++は[黒橋・河原研究室](http://nlp.ist.i.kyoto-u.ac.jp/index.php?JUMAN++)から発表されたRNNを使用した形態素解析器です．
本記事ではPythonラッパーを通じてJUMAN++を使用する方法を紹介します．
単純にJUMAN(形態素解析器)，KNP(構文解析器)，PyKNP(JUMANとKNPのPythonバインディング)のインストール方法なので，これらの導入の参考にもなるかと思います．


## 導入方法
JUMAN++はPyKNPを通じて利用することができます．
PyKNPはJUMANとKNPに依存しているため，まず先にこれらをインストールしていきます．

### 前提
* ubuntu-16.04
* [こちら](http://qiita.com/riverwell/items/438e88427363511e9f28)を参考にJUMAN++をインストールしていること

### JUMANのインストール

まず以下のコマンドでJUMANをインストールします．

```bash
$ wget http://nlp.ist.i.kyoto-u.ac.jp/nl-resource/juman/juman-7.01.tar.bz2
$ tar jxvf juman-7.01.tar.bz2
$ cd juman-7.01
$ ./configure
$ make
$ sudo make install
```

このままではパスが通っていないので，以下の通りパスを通していきます．

```
$ sudo vim /etc/ld.so.conf
```

ファイルが開けたら以下を追記します．

```
include /usr/local/lib
```

以下のコマンドでパスを読み込み直します．

```bash
$ sudo ldconfig
```

バージョンが確認できたらインストールに成功しています．

```bash
$ juman -v
juman 7.01
```

### KNPのインストール

次にKNPをインストールします．
環境によっては解凍に時間がかかりますが，終わるまで待ちます．

```bash
$ wget http://nlp.ist.i.kyoto-u.ac.jp/nl-resource/knp/knp-4.16.tar.bz2
$ tar jxvf knp-4.16.tar.bz2
$ cd knp-4.16
$ ./configure
$ make
$ sudo make install
```

インストール完了です．
ついでに動作確認も行います．

```
$ echo "外国人参政権" | jumanpp | knp
# S-ID:1 KNP:4.16-CF1.1 DATE:2016/10/19 SCORE:-1.20047
外国──┐
          人──┐
                参政──┐
                          権
EOS
```

構文解析できました．
(jumanppの部分はjumanでも構いません)

### PyKNPのインストール

前提環境ではsetuptoolsがインストールされていないため，以下の通りsetuptools(とpip)をインストールします．
ついでに，PyKNPの依存ライブラリsixも入れています．

```bash
$ sudo apt install python-pip
$ pip install six
```

以下のようにPyKNPをインストールします．

```bash
$ wget http://nlp.ist.i.kyoto-u.ac.jp/nl-resource/knp/pyknp-0.3.tar.gz
$ tar xvf pyknp-0.3.tar.gz
$ cd pyknp-0.3
$ sudo python setup.py install
```

完了です．

## サンプルプログラム

では，PythonからJUMAN++を使用してみます．
以下のようなプログラムを作成します．

```python:test.py
#-*- encoding: utf-8 -*-
from pyknp import Jumanpp
import sys
import codecs
sys.stdin = codecs.getreader(’utf_8’)(sys.stdin)
sys.stdout = codecs.getwriter(’utf_8’)(sys.stdout)
# JUMAN++をsubprocessモードで使用
jumanpp = Jumanpp()
result = jumanpp.analysis(u"ケーキを食べる")
for mrph in result.mrph_list():
	print(u"見出し:{0}".format(mrph.midasi))
```

```bash
$ python test.py
見出し:ケーキ
見出し:を
見出し:食べる
```

PythonからJUMAN++を呼び出せました．

## 参考
JUMAN++ マニュアル v1.01
http://lotus.kuee.kyoto-u.ac.jp/nl-resource/jumanpp/jumanpp-manual-1.01.pdf
Ubuntu 日本語形態素解析システムJUMANのインストール方法
http://www.trifields.jp/how-to-install-juman-in-ubuntu-1404-1375
Ubuntu 日本語構文・格・照応解析システムKNPのインストール方法
http://www.trifields.jp/how-to-install-knp-in-ubuntu-1404-1382
アプリを使わずにphp+mysql開発環境をつくる(mac)

#php
mac osX yosemite version 10.10.4に入っていたのは
5.5.24

wordpress 推奨は 5.6 以上
なのでアップデートをします
（今はちょっと飛ばす）

#mysql

##インストール
```
$ brew update
$ brew install mysql
```

データを入れ込む
http://blog.factory70.com/systems-engineering/sql-file-import-by-terminal

##念のため情報確認

```
$ brew info mysql
or
$ mysql --version
mysql  Ver 14.14 Distrib 5.7.16, for osx10.10 (x86_64) using  EditLine wrapper
```

##起動

```
$ mysql.server start

Starting MySQL
. SUCCESS! 
```

##ルートユーザーでログイン

```
mysql -uroot
```

今回はすでにデータが用意されていたので、それを使用。

```sql
source ******.sql
```

#サーバーを立てる
php のデフォルトコマンド？から立ち上げます。

```
$ php -S localhost:3000
```


#参考記事
- [Mac へ MySQL を Homebrew でインストールする手順](http://qiita.com/hkusu/items/cda3e8461e7a46ecf25d)
- [php update ](http://kimikimi714.hatenablog.com/entry/2013/07/06/233518)
math > 床関数 > mathJaxで記載

読み進めている「深層学習」に出てくる記号。

https://ja.wikipedia.org/wiki/%E5%BA%8A%E9%96%A2%E6%95%B0%E3%81%A8%E5%A4%A9%E4%BA%95%E9%96%A2%E6%95%B0

IMEでの入力方法が分からない。

記載時に毎回mathで囲うことになりそう。

\lfloor x\rfloor 

```math
\lfloor x\rfloor 
```
Xcodeのシミュレーターで ホームボタンを押忍！！！

#shift + command + H (ホームボタン押忍)



![スクリーンショット 2016-10-19 12.33.53.png](https://qiita-image-store.s3.amazonaws.com/0/135794/2eadf39c-236a-01e8-5c21-8d4ddfc57127.png)



#shift + command + H のHを連打(ホームボタンをダブルクリック)

![スクリーンショット 2016-10-19 12.33.23.png](https://qiita-image-store.s3.amazonaws.com/0/135794/0d5c3785-4551-2465-e883-a528f26bb293.png)
onclick時にステップ実行するためのメモ

Railsのjquery-ujsに絡んだ挙動をデバッグしていて、data-methodつきのaタグをクリックしたあとでステップ実行したいんだけど、どこに処理が行くのか追いづらかったとき用

```js
window.startDebug = function() {
  debugger
};
```

```slim
= link_to "Foo", "/foo", method: :post, "onclick": "window.startDebug()"
```
Object.assign ではプロトタイプまではコピーしてくれない

JavaScript でオブジェクトをシャローコピーしようとしたときに `Object.assign({}, obj)` をよく使うのだが、オブジェクトのプロトタイプがコピーされていなくてハマったのでメモ。

``` js
class Foo {
  say() {
    console.log('foo');
  }
}

var foo = new Foo();
foo.say(); // foo

var copy_foo = Object.assign({}, foo);
copy_foo.say(); // TypeError: copy_foo.say is not a function
```

`Object.assign` は列挙可能なプロパティを assign してくるが、 `__proto__` は列挙可能なプロパティではないので assign してくれない。

``` js
var copy_foo = Object.assign({ __proto__: foo.__proto__ }, foo);
copy_foo.say(); // foo
```

このように `__proto__` を無理矢理 assign すれば動くっちゃ動くが、そもそも [`__proto__` を直接扱うのは非推奨](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/proto) なので、もはや [clone](https://www.npmjs.com/package/clone) などのモジュールを使ったほうがいいと思われる。clone 使うとシャローコピーじゃなくてディープコピーになるけど。

``` js
var clone = require('clone');

var foo = clone(foo);
foo.say(); // foo
```
React/Angular/Vueの比較のため各cliツールを試してみた

## 背景
- 新しいプロジェクトに向けてのフレームワーク選定のため
	- プロダクトは BtoBtoC の業務アプリ
- いわゆるフロントエンドエンジニアがチームに少ない (10名弱中に1〜2名)
	- 社内外で探しても圧倒的に少ない。田舎だからか!?
- 既存システムは AngularJS 1.x 系が使われており、2013年末から約3年くらいチーム内の実績がある。


## 結論
- vue-cli、angular-cli、create-react-app それぞれ必要なもの(ビルド、テスト関連)が揃っており、ツール選定に疲れた人や悩みたくない場合には有効
- PJ の取っ掛かり(プロト段階)でフレームワーク検証がてら利用する分には十分。
	- どれを選ぶかはプロダクトの要件しだい。
- angular-cli が scaffold が揃っているので、メンバーには布教しやすそう。  
(若干 Angular 愛によるバイアス有り。)
	- BtoBtoC の業務アプリに TypeScript はオススメです。

## 各cliツール比較

以下、触った順です。

### vue-cli
- http://vuejs.org/guide/installation.html#CLI
	- http://jp.vuejs.org/guide/installation.html#CLI
		- ドキュメントは 1.0 だけど、2.0 にちゃんと対応していた。日本語ドキュメントあるとメンバーには布教しやすい。
	- 構成がわかりやすい。シンプル
	- 必要なものは一通り揃っており、過不足ない感じ
		- babel/karma/mocha/chai/sinon/nightwatch/webpack など
	- `npm run dev` して感動した。
	- 型がほしいので、[flowtype](http://qiita.com/mizchi/items/95ee0101ac22e4b7b662) などを追加したい

```
.
├── build
├── config
├── src
│   ├── assets
│   └── components
├── static
└── test
    ├── e2e
    └── unit

```

#### 参考
- https://speakerdeck.com/potato4d/totutukiyasui-huremuwaku-vue-dot-js-number-jsfes
	- Vuex が気になる。


### angular-cli
- https://cli.angular.io/
- https://github.com/angular/angular-cli
	- このリポジトリがちょっと探しづらい。
	- 構成がやや複雑
	- 必要なものは一通り揃っており、不足ない感じ
		- typescript/karma/jasmine/protractor/systemjs など
	- `ng generate <Scaffold> ` が充実してる
		- これに沿うようにメンバーに周知すればある程度の秩序は保てそう
	- 環境別に build などもできそう。

```
.
├── config
├── dist
│   ├── app
│   └── vendor
├── e2e
├── public
├── src
│   └── app
├── tmp
└── typings
    ├── browser
    └── main
```


#### 参考
- http://blog.teratail.com/entry/angular2_nyumon
- http://albatrosary.hateblo.jp/entry/2016/03/18/101637
- http://qiita.com/kitfactory/items/c95ca84371670b21f4ac


### create-react-app
- https://github.com/facebookincubator/create-react-app
	- https://facebook.github.io/react/blog/2016/07/22/create-apps-with-no-configuration.html
- `create-react-app` コマンドで `npm ERR!`
	- https://github.com/facebookincubator/create-react-app/issues/888
	- `this is a bug in npm 3.3.12.` らしいです。`npm i -g npm@latest` で解決しました。
- 構成がシンプル。
- 依存性は隠蔽されているらしい。
- ここから PJ に合わせて育てていく際に、ベストプラクティスを外すと後々辛そう。。
	- `npm run eject` で隠蔽されてる依存性が展開できる。

```
# npm run eject 前
.
├── public
└── src
```

```
# npm run eject 後
.
├── config
│   └── jest
├── public
├── scripts
└── src

```

#### 参考
- https://speakerdeck.com/adwd/create-react-app-introduction
- http://qiita.com/chibicode/items/8533dd72f1ebaeb4b614
スマートフォンの入力で「確定・予測変換」をトリガーに処理を実行する

#前置き
keydownやinputイベントを張っても、端末によって確定や予測変換は発火したりしなかったりします。
タイマーをセットしてvalueを監視する、でこの問題を回避することができますが、今回どうしても確定や予測変換で発火させたい要件があったので調べました。

#結論
イベント ```compositionend``` を使用する

#サンプル
http://jsdo.it/bgn_nakazato/elmq

#使用例
※jqueryを読み込んでいるものとします。

```js
var $input = $('.input');
$input.on('compositionend', function() {
  // 確定・予測変換時に処理したいイベント
});
```

シンプルに書くとこうなります。

実際にはcompositioneventの対応状況による分岐も必要だと思うので
私が思う実用レベルのコードを記述します。

```js
var $input = $('.input');
if ('CompositionEvent' in window) {
  $input.on('compositionend', function() {
    setTimeout(function() {
      if (!$(this).val().length) return;
      // 確定・予測変換時に処理したいイベント
    },0);
  });
} else {
  // タイマーによるvalue監視など
}
```

簡単にコードの説明をします。

```if ('CompositionEvent' in window)``` によって、対応状況による分岐をします。

対応している場合、 ```compositionend```イベントを張るのですが、発火時には入力内容が
反映されていないため、0タイマーを設定することで入力後の状態で処理を行います。

```if (!$(this).val().length) return;``` は、文字列削除によって０文字になったときに
確定とみなされるのか、イベントが発火するため、そこで処理を行わないための分岐です。

#検証
検証と言えるほどではありませんが
数台のiphoneとandroidで確認した結果、iphone safari、android chrome & 標準ブラウザで
同じように確定・予測変換でイベントが発火しました。

#参考
https://developer.mozilla.org/ja/docs/Web/Reference/Events/compositionend
ruby whenever

railscast

bundle: command not found

https://github.com/javan/whenever/issues/473

```rb
class Lala
  def self.output
    puts "haha"
  end
end
```


```rb
# Use this file to easily define all of your cron jobs.
#
# It's helpful, but not entirely necessary to understand cron before proceeding.
# http://en.wikipedia.org/wiki/Cron

# Example:
#
env :PATH, ENV['PATH']
env :GEM_PATH, ENV['GEM_PATH']
set :output, "#{path}/log/cron_log.log"
#
# every 2.hours do
#   command "/usr/bin/some_great_command"
#   runner "MyModel.some_method"
#   rake "some:great:rake:task"
# end
#
# every 4.days do
#   runner "AnotherModel.prune_old_records"
# end

# Learn more: http://github.com/javan/whenever

every 1.minute do
	runner "Lala.output"
end
```


https://launchschool.com/blog/cron-jobs-and-rails


http://stackoverflow.com/questions/14612818/whenever-gem-i-set-output-but-the-logfile-doesnt-show-up-where-id-expect-it

To verify the cron is running as you expect:

```bash
$ sudo grep CRON /var/log/syslog
```
The grep result should have lines that something like this:

```bash
Jan 1 12:00:00 example.com CRON[123]: (root) CMD (... your command here ...)
```


https://github.com/javan/whenever/wiki/Exclusive-cron-task-lock-with-flock
メモ：Eclipse Pleiades Neon のダークとColor themeの組み合わせでうまくいった件→ダメでした

[メモ：Eclipse Pleiades Mars のダークとColor themeの組み合わせがうまくいかない](http://qiita.com/nekomanma/items/3264d272432b9780df09)

上記記事について、再度開発環境を作ることになったので久々に調査してみたらあっさり。

~~できるようになってた。~~
**できませんでした！！**
↓
それだとあんまりなので、できる方法を今度こそ見つけました。こちらを参考にしてください。
[【解決】Eclipse Pleiades Neon のダークとColor themeの組み合わせで今度こそうまくいった件](http://qiita.com/nekomanma/items/890e6723cecc54972171)



追記：

すみません。スライディング土下座。


＊＊＊以下、出来なかった内容です＊＊＊

>意識したのは、
>
>
>**テーマの選択と、色テーマの選択が完了するまでは「適用」ボタンを押さない。**
>
>
>……というだけなんですけど、実はそういう操作をしなかった場合でもうまくいきました。
>今回はWindows10（最新）＋Neonで環境を作ったらうまくいったので、Neonやマーケットプレイスに更新があったのかなと思っていましたが、前述のリンクの時の環境を引っ張り出して適当にやってみてもうまくいきました。
>
>何が原因でできなかったのか突き止めようと思いましたが結局分からず。
>なんかうまくいったのでよかったね。みたいな感じです。
>
>
>納得いかない。
>
>
>また元に戻るかもしれないので、しばらく意識してみます。
Xcode8時代のメモリリークの原因の探し方

Xcode8から`Debug Memory Graph`という機能が使えるようになったので、それを使ってメモリリークしている箇所を見つけることができます。

詳しくは、以下のStackoverflowの`Rob`さんの回答を見てください。

- [How to debug memory leaks when Leaks instrument does not show them?](http://stackoverflow.com/questions/30992338/how-to-debug-memory-leaks-when-leaks-instrument-does-not-show-them)

# 使い方

1. アプリをシミュレータ等で実行する。
2. `Debug Memory Graph`ボタンをクリックする

<img src="http://i.stack.imgur.com/tzOFk.png" />

また、Breakpointで処理を止めてから`Debug Memory Graph`を押下すると、その時点でのメモリの状況を確認することができます。
これを利用して、複数のBreakpointを設定して、Breakpoint間のメモリの状況を比較することで、どこでメモリリークしているのかを発見できます。
iOSシミュレータの「通信事業者」表記を変更する


ステータスバーに表示されるこれです。

![Simulator-Screen-Shot-2016.10.19-11.29.06.jpg](https://qiita-image-store.s3.amazonaws.com/0/15645/543c81f6-a5dc-1406-3157-8b1cfda7782c.jpeg "Simulator-Screen-Shot-2016.10.19-11.29.06.jpg")

元ネタ：[toursprung/iOS-Screenshot-Automator]
(https://github.com/toursprung/iOS-Screenshot-Automator/blob/master/changeCarrierName)

.stringファイルをコピー・変換してから編集します。


```bash
$ cd ~/Desktop/

$ cp /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator10.0.sdk/System/Library/CoreServices/SpringBoard.app/ja.lproj/SpringBoard.strings ~/Desktop/

$ plutil -convert xml1 SpringBoard.strings 
```

変換した`SpringBoard.strings`をテキストエディタ等で開きます。「通信事業者」で検索し、該当箇所をお好きな文字列に変更します。

通信キャリアっぽくしたい場合は次のようにします。まるはU+2981を使ってます。


```xml
<key>SIMULATOR_CARRIER_STRING</key>
<string>⦁⦁⦁⦁⦁ au</string>
```

編集したら保存して、元の場所にコピーします。


```bash
$ sudo cp SpringBoard.strings  /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator10.0.sdk/System/Library/CoreServices/SpringBoard.app/ja.lproj/
```

シミュレータを起動して確認します。

![Simulator-Screen-Shot-2016.10.19-11.11.25.jpg](https://qiita-image-store.s3.amazonaws.com/0/15645/59cc0b79-b451-1cf7-72a0-0fb22395b708.jpeg "Simulator-Screen-Shot-2016.10.19-11.11.25.jpg")


これでスクリーンショット保存するとそれっぽく見えます。
kintoneで非同期処理結果を受けて画面項目を変更する

# 他のアプリから非同期にデータを取ってくる
kintone.api呼べばいい。

```javascript:.js
kintone.api(path,'GET', data, function (resp) {
    // ここにデータ受信後の処理
    // var hoge = resp['records'][0]['hoge']['value'];
    // とか
});
```

# 画面項目をJavaScriptで変更する
なんらかのイベント発火を受けて処理するはずなので、そのコールバックのパラメータ「event」を使う。

```javascript:.js
kintone.events.on('app.record.create.show', function (event) {
    // event['record']['hoge']['value'] = 'hoge';
    // とか
});
```

# 非同期通信の処理結果を受けて画面項目を変更する
ここまで書いたことの組み合わせで

```javascript:.js
kintone.events.on('app.record.create.show', function (event) {
    kintone.api(path,'GET', data, function (resp) {
        // ここに代入分を記述
        // event['record']['hoge']['value'] = resp['records'][0]['hoge']['value'];
    });
});
```

これでできるよね！
・・・
できなかった　(ノД`)・゜・。

デバッガで見ると確かにJavaScriptの変数上では想定通りに反映されている。
でも、画面には反映されない。。。

こうしましょう！

```javascript:.js
kintone.events.on('app.record.create.show', function (event) {
    kintone.api(path,'GET', data, function (resp) {
        // ここに代入分を記述
        // event['record']['hoge']['value'] = resp['records'][0]['hoge']['value'];
        kintone.app.record.set(event);    // <--これ追加
    });
});
```

kintoneイベントの外で画面項目を更新したら自分で再設定用のメソッドを呼んでやる必要があるようです。
めんどくさいけど、わからなくもない。
CoreTelephony Trace File Errorを解決する

#背景
ある日Macを起動したらCoreTelephony Trace File Errorと表示されAdobe関連が立ち上がらなくなった

#やったこと
まず、ユーザーフォルダの場所を選択し
Macのシステム環境設定->ユーザとグループ->鍵をクリックして変更を行えるようにする
自分のユーザを右クリックすると詳細オプションを選べるのでクリック
ホームディレクトリが/Users/自分のユーザになっているか確認する
違っている場合は修正する

次にMacをリカバリモードで再起動（リンゴマークが表示されるまで⌘+Rを長押し）
ユーティリティ->ターミナルでターミナルを起動し、csrutil disableと入力してEnterを押す
Macを再起動しエラーメッセージが消えたらAdobe関連は起動するはず
無効化したので元に戻すため同じ手順でターミナルでcsrutil enableと入力してEnterを押して有効にしておく

もし、csrutil disableを入力した時点で
failed to modify system integrity configuration. This tool needs to be executed from the Recovery OS.
という文言が出たらOSを再インストールしなければならないのでバックアップをとったあとで
OSを再インストールする

これでエラーメッセージが表示されなくなった

#まとめ
ターミナルとかの理解がまだ怪しいのでわかる範囲の知識で対応した
結果的にcsrutil disableを行う前に問題を解決できたのでそちらの方法は未確認



[参考]
https://discussionsjapan.apple.com/thread/10177668?start=0&tstart=0
https://discussions.apple.com/thread/7695435?start=0&tstart=0
http://qiita.com/zaburo/items/c650cda45c858fe856a9
http://www.macosxblog.com/how-to-fix-coretelephony-trace-file-error-on-mac/
LINE Notify を試したのでメモ


## 必要なもの
PC でログインできる LINE ID

## 手順

* [LINE Notify](https://notify-bot.line.me/ja/) と友だちになる
* [LINE Notifyのマイページ](https://notify-bot.line.me/my/) に LINE ID でログイン
* アクセストークンを発行する
	* トークンは何度も作り直せるので、適当な名前でも大丈夫
	* 送り先は自分（1 on 1）か、グループを指定できる
* [access_token] の部分を発行したアクセストークンに置き換えて、以下を実行
	* `curl -X POST -H 'Authorization: Bearer [access_token]' -F 'message=テストでーす！' https://notify-api.line.me/api/notify`

## この後は

マイページから開発者ドキュメントをダウンロードできますので、それを見ていろいろ試せそうです。
[Ubuntu][Skype for Business][Lync] Ubuntu 16.04からSkype for Businessへ接続する

# 概要

Ubuntu 16.04でSkype for Businessへ接続できるようにします。

こちらで紹介されている内容のなぞりです。
http://chrisjrob.com/2015/09/02/linux-microsoft-skype-for-business-lync-2013-client/

# ステップ 1 pidginプラグインのインストール

最初にプラグインをインストールします。

```
% sudo apt-get install pidgin-sipe
```

インストールが終わったら、Pidginを再起動します。

# ステップ 2 アカウントを追加

次のような内容でアカウントを追加します。

Basicタブ

| 設定項目 | 設定内容 |
|:-:|:-:|
| Protocol  | Office Communicator[^1] |
| Username | Skype for BusinessへログインするIDでです。たぶんにメールアドレスです。 |
| Login | 空でOKです。 |
| Password | Skype for Businessへログインするパスワードです。 |

[^1]: この選択肢が表示されないときは、Pidginを再起動できていません。

Advancedタブ

| 設定項目 | 設定内容 |
|:-:|:-:|
| Server | 空でOKです。 |
| Connection type | Auto |
| User Agent | UCCAPI/15.0.4420.1017 OC/15.0.4420.1017[^2] |
| Authentication scheme | TLS-SDK |

[^2]: なんでかわからないけど必要らしいです。

# おしまい

もし接続できないときは、バージョンを確認してみてください。

自分はこのバージョンで接続できました。

Package: pidgin
Version: 1:2.10.12-0ubuntu5.1

Package: pidgin-sipe
Version: 1.20.1-1


\# それにしても、なぜMicrosoftはLyncという名前を捨ててSkype for Businessにしたのか。。。わかりづらいったらありゃしない。
Composerがない環境でSwiftMailerを利用する

# ソースを入手

[Gitから入手](https://github.com/swiftmailer/swiftmailer)

* **lib**を作業ディレクトリにアップロードする

# config設定

``` php
$config = array(
    'host' => 'smtp.example.com',
    'port' => 465,
    'user' => 'dummy@example.com',
    'pass' => 'password',
    'encryption' => 'ssl',
    'url' => 'http://localhost',
    'mailaddress' => 'dummy@example.com',
    'sendname' => '株式会社Dummy担当',
    'subject_user' => 'お問い合わせありがとうございます',
    'subject_admin' => 'お問い合わせを受信しました',
    'note' => true,  // 送信控え
    'cc' => array(
        'red@example.com',
        'blue@example.com',
    ),
    'bcc' => array(
        'green@example.com',
    ),
);
```

# 送信処理

``` php
	// 日本語に関する初期設定
	Swift::init(function () {
	    Swift_DependencyContainer::getInstance()
	        ->register('mime.qpheaderencoder')
	        ->asAliasOf('mime.base64headerencoder');
	    Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
	});

	// SMTPサーバーとの接続設定
	$transport = Swift_SmtpTransport::newInstance($config['host'], $config['port'])
	    ->setUsername($config['user'])
	    ->setPassword($config['pass'])
	    ->setEncryption($config['encryption']);

	$mailer = Swift_Mailer::newInstance($transport);


	// メール情報をセット
	$subject = sprintf($config['subject_admin'], $posts['nameKanji'], $posts['postKind']);
	$body = $body_header_admin.$mail_data['body_middle'].$body_footer_admin;
	$from = array($config['mailaddress'] => $config['sendname']);
	$to = array($config['mailaddress'] => $config['sendname']);

	// メールの作成
	$message = Swift_Message::newInstance();
	$message->setCharset('iso-2022-jp');
	$message->setEncoder(Swift_Encoding::get7BitEncoding());
	$message->setSubject($subject);
	$message->setFrom($from);
	$message->setTo($to);
	if (count($config['cc']) != 0) {
		$message->setCc($config['cc']);
	}
	if (count($config['bcc']) != 0) {
		$message->setBcc($config['bcc']);
	}
	$message->setBody($body, 'text/plain');

	// 送信処理
	$result = $mailer->send($message);

	// 送信控え送信
	if ($config['note'] == true) {
		$subject = $config['subject_user'];
		$body = $body_header_user.$mail_data['body_middle'].$body_footer_user;
		$to = array('dummy@example.com' => 'dummy');

		$message = Swift_Message::newInstance();
		$message->setCharset('iso-2022-jp');
		$message->setEncoder(Swift_Encoding::get7BitEncoding());
		$message->setSubject($subject);
		$message->setFrom($from);
		$message->setTo($to);
		$message->setBody($body, 'text/plain');

		// 送信処理
		$result = $mailer->send($message);
	}

```
ファイルの先頭と末尾に文字を追加する

ファイルの先頭に追加
sed -i '1s/^/追加する文字列\n/' ファイル名

ファイルの末尾に追加
echo 追加する文字列　>> ファイル名

お世話になったサイト
http://oshiete.goo.ne.jp/qa/5731255.html
Ansible で中継ホストだけ違う同じアドレスのサーバをインベントリで分けるとき

Ansible で下記のようにアドレスが同じで中継ホストが異なるインベントリを使うとき。

**prod**

```
sv01 ansible_ssh_host=192.168.88.11
sv02 ansible_ssh_host=192.168.88.12

[all:vars]
ansible_ssh_common_args = -o "ProxyCommand ssh 192.0.2.100 -l root -W %h:%p"
```

**stage**

```
sv01 ansible_ssh_host=192.168.88.11
sv02 ansible_ssh_host=192.168.88.12

[all:vars]
ansible_ssh_common_args = -o "ProxyCommand ssh 192.0.2.200 -l root -W %h:%p"
```

`control_path` のデフォルトが下記のようになっていると思うので、

```
control_path = %(directory)s/ansible-ssh-%%h-%%p-%%r
```

最初に接続した方のインベントリのホストで下記のような ControlMaster のソケットファイルが作成されて、

```
~/.ansible/cp/ansible-ssh-192.168.88.11-22-ore
~/.ansible/cp/ansible-ssh-192.168.88.12-22-ore
```

別のインベントリファイルを指定してもこのソケットファイルが使用されてしまい、誤ったホストに接続されてしまいます。

ので、下記のようにどちらかのインベントリで ControlPath を変更する必要があります（もしくは無効にする）。

```
sv01 ansible_ssh_host=192.168.88.11
sv02 ansible_ssh_host=192.168.88.12

[all:vars]
ansible_ssh_common_args = -o "ProxyCommand ssh 192.0.2.200 -l root -W %h:%p" -o "ControlPath ~/.ssh/stage-%h-%r"
```
Python3とopenCV3のエッジ検出で水彩錯視を描く

#環境
　windows8.1
　python3.4.4
　opencv3.1.0

#概要
カラー画像を読み込み、水彩錯視を作ります。

水彩錯視というのは、絵画や写真の輪郭にのみ色をのせることで、
実際には色のない領域もうっすらと色づいて見える現象・・・
と、視覚については話すと長くなりますので、リンクをいくつか紹介します。
水彩錯視の例も掲載されています。

[エッジに起因する明暗と色の錯視 - 新井仁之のホームページ](http://www.araiweb.matrix.jp/Exhibition/edgeillusion1.html)
[Illusion Forum](http://www.kecl.ntt.co.jp/IllusionForum/v/watercolorIllusion/ja/)
[CVRM](http://www.cvrl.org/gallery/Watercolor-illusion.html)

#画像
今回使用する画像は、ご存知「いらすとや」さんより

「特産品」
![test1.png](https://qiita-image-store.s3.amazonaws.com/0/144906/19b1e219-983a-bca6-3334-247048152942.png)

なるたけ多彩な画像を血眼で探しました

#本体

```python:edge.py
import numpy as np
import cv2

"""
環境：python3.4.4 openCV
元の画像 : image_name
保存する画像: out_name
image_nameを水彩錯視に変換して出力
"""

image_name = 'test1.png'
out_name = 'out1.png'


#画像の読み込み
Img0 = cv2.imread(image_name)


#後のマスクと都合を合わせるため画像は白黒反転
negImg = 255 - Img0


#画像のサイズを取得し、輪郭の太さを指定
ImgHeight, ImgWidth = Img0.shape[:2]
#縦横長い方/200 + 1
if ImgWidth > ImgHeight:
	lineWeight = ImgHeight // 200 + 1
else:
	lineWeight = ImgWidth // 200 + 1


#エッジを取得(二段階の閾値100 200)
#後から太さの違う輪郭を2つ合わせるので、2つのimageを用意する
edgeImg1 = cv2.Canny(Img0,100,200,4)
edgeImg2 = cv2.Canny(Img0,100,200,4)


#黒い背景から物体(白)の輪郭を検出する
image1, contours, hierarchy = cv2.findContours(edgeImg1,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
image2, contours, hierarchy = cv2.findContours(edgeImg2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)


#黒の輪郭
edge = cv2.drawContours(image1, contours, -1, (255,255,255), 1)
#黒の輪郭周りの色(水彩の素)
mask1 = cv2.drawContours(image2, contours, -1, (255,255,255), lineWeight)


#edgeは黒地に白なので反転して表示
negEdge = 255- edge


#反転画像をマスクで切り取る
negColor = cv2.bitwise_and(negImg, negImg, mask=mask1)


#切り取った反転画像を再び反転
Color = 255-negColor


#出力する画像
output = cv2.bitwise_and(Color, Color, mask=negEdge)
cv2.imshow('image', output)

#escキーを押すと終了
#sを押すと保存する
k = cv2.waitKey(0) & 0xFF
if k == 27:
    cv2.destroyAllWindows()
elif k == ord('s'):
    cv2.imwrite('out01.png',output)

#python edge.pyで実行
```

#出力
いかがでしょう。色づいて見えるでしょうか？
![out01.png](https://qiita-image-store.s3.amazonaws.com/0/144906/46a0a71a-7b5d-53d4-727d-43a4085dce9c.png)

#諸々
エッジ検出は関数が用意されているので簡単です。

ただ、Canny()によるエッジ検出は二つの閾値だけを基準にしているので、人間の目のように微妙な境界判断はできません。そんなわけで、人参の葉が消えたり、稲が一体化してよく分からないつぶつぶの豆みたいになってしまっているわけです。

もう一つ、反転を繰り返しているのはあまり賢い方法ではありません。
しかし、黒のエッジを残したり、エッジ以外を白くしようといじっていたら結果このようになりました。背景を白くすることができれば、もう少し簡単になるのですが・・・

#参考
[いらすとや](http://www.irasutoya.com/)
[OpenCV-Python Tutorials 1 documentation](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_canny/py_canny.html)
[Pythonの学習の過程とか](http://peaceandhilightandpython.hatenablog.com/entry/2015/12/23/214840)
Pinna, B., Brelstaff, G., and Spillmann, L. (2001) Surface color from boundaries: a new ‘watercolor’ illusion. Vision Research, 41, 2669-2676.
AndroidStudioのエディタでTabとSpaceを相互に変換する

# Tab派ですか？Space派ですか？

VisualStudio感覚でTab派だったんですが
githubとかで見るとレイアウトが崩れたりで最近Space派になりました。

デフォルトではSpaceですね。
Javaファイルのデフォルト設定はAndroidStudioのPreferencesあたりから。

<img width="1149" alt="スクリーンショット 2016-10-19 9.49.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/76483/2405b87e-c7d3-5ef5-9dc2-0a854fe6c74c.png">

# 行頭のインデントをタブとスペースで相互に変換

便利な変換機能がそもそもありました。
Pluginも検索＆置換操作も必要なかった。

メニューから
Edit > Convert Indents > To Spaces / To Tabs

<img width="670" alt="スクリーンショット 2016-10-19 10.07.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/76483/ae05b4f7-bdee-31b2-ff95-bfa305390256.png">

# ちなみに
行頭のインデントのみ変換するので
行中や文字列中のタブは変換されないのでご安心を。
Message-IDをDBに保存する際の考察

#### この記事について

emailのMessage-IDをDBに保存する際に、どのような設計が良いのかを調べたので、それに関する考察を記録として残す。


#### 結論

結論から言うとMessage-IDの最大長は995である。
カラムの設定はVARCHAR(995)とすればRFCに基づいたMessage-IDは問題なく格納できる。

おおまかにrailsのマイグレーションコードにおける`add_column`は下記のようになる

```
add_column :table, :message_id, :string, limit: 995
```

---

以下理由

#### Message-IDとは

メールを一意に特定できる識別子のこと

---

##### 995になる理由
メールにおける一行の最大長は998である。
Message-IDを一行の長さに押し込めようとすると
Message-IDを囲む **<** と **>**及び半角スペース**' '**の3文字を取り除く。
すると、 998 - 3 = 995 となる。

この3文字、**<** **>** **' '** がなぜ必要なのかについて解説する、

---

##### <>について

まず<>についてだが
これはRFCに規定があり、Message-IDの定義上含まれるものである。
これらで囲まれているものがMessage-IDとなるため、定義上必要となる。


[RFC5322](http://srgia.com/docs/rfc5322j.html)
> メッセージ識別子(msg-id)の文法は、アングルブラケット("<" と ">")に括られた addr-spec の限定バージョンである。


---

##### 半角スペースについて

半角スペースは:とメッセージボディの間に挿入できるものから来ている。
[ここ](http://srgia.com/docs/rfc5322j.html#A.5)によれば、コロン(:)とヘッダボディの間には空白を挿入可能である。

この空白に対して畳み込みを行うことで、空白が最初にくる行が発生する。

---

##### foldingについて

foldingとは、ヘッダとボディ部分が合わせて998文字を超える時に行われる処理である。
半角スペースの直後にCRLF、改行を挿入することで、複数行を使用してヘッダ情報を記述できる。
Message-IDをメールの1行の長さ制限ギリギリまで長くしようとすると、foldingによる改行が必要になる。


---

#### 995文字
メッセージボディを前述の998文字制限に対応させるためには、コロンとボディの間に空白を挿入し、そこでfoldingを行う必要がある。
よって、畳み込みを行ったボディ部分の一行にはMessage-ID以外に`半角スペース`と `<` `>` の3文字が入る。
よって `998 - 3 = 995` となる。
このようにMessage-IDの最大長は995文字と言える。

---

#### 蛇足
上記の話は受信するメールがRFCを守ってくれているという前提に立っている。
RFCを守らないメールを受信する際はその限りではない。
そして残念なことにRFCを守らないメールは存外多い :innocent: 



[参考]
http://stackoverflow.com/questions/30079128/maximum-internet-email-message-id-length

http://srgia.com/docs/rfc5322j.html
ローカル開発環境でのHTTPSの確認




## 環境

Rails 4.2.6

## Thin


以下のように thin を起動するだけで良い。オレオレ証明書とか不要。

```
$ thin start --ssl -p 3001
```


参考: [Railsのローカル環境でSSL(https)を使う - Qiita](http://qiita.com/ironsand/items/0056d718b9174f516f7b)


## Puma


オレオレ証明書が必要でちょっとめんどくさい。


### オレオレ証明書を作る

```
$ cd ~/.ssh
$ openssl genrsa -des3 -out server.orig.key 2048

(remove the password)
$ openssl rsa -in server.orig.key -out server.key

(generate the csr)
$ openssl req -new -key server.key -out server.csr

(色々聞かれるので入力する)

(self signed ssl certificate)
$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
```


### puma 起動

```
$ puma -b 'ssl://0.0.0.0:3000?key=/home/hoge/.ssh/server.key&cert=/home/hoge/.ssh/server.crt'
```

### puma 起動設定ファイル

いちいち コマンドラインオプションで指定するのも面倒なので設定ファイルに記述する。

```puma.rb
ssl_bind '0.0.0.0', '3000', {
  key: "/home/hoge/.ssh/server.key",
  cert: "/home/hoge/.ssh/server.crt" 
}
```

こうしておけば以下のように起動するだけでOk

```
$ puma -C puma.rb
```

参考: [localhost SSL with puma](https://gist.github.com/tadast/9932075)


## Nginx 

※先の「Puma」で記載したのと同じ内容でオレオレ証明書があって `/home/vagrant/.ssh/server.crt` に保存されている前提

```

server {
    listen 80;
    listen 443 ssl;   # <-- ポート443を待ち受ける

    # 以下SSLを有効化して証明書／鍵を設定
    ssl on;
    ssl_certificate       /home/vagrant/.ssh/server.crt;
    ssl_certificate_key   /home/vagrant/.ssh/server.key;
```

上記設定後、 `https://localhost/xxx` にアクセスできたらOK


参考: [Nginx ～ SSL Terminateの検証 : オラクる。](http://piro-shiki.dreamlog.jp/archives/47141433.html)
組合せ最適化でゲーム理論を解く

# これなに
[ゲーム理論](https://ja.wikipedia.org/wiki/%E3%82%B2%E3%83%BC%E3%83%A0%E7%90%86%E8%AB%96)において、零和ゲームの場合、最適混合戦略は線形最適化(LP)で求めることができるそうです[^1]。
アレンジしたじゃんけんを例にして、Pythonでやってみます。

線形最適化については、[組合せ最適化を使おう](http://qiita.com/Tsutomu-KKE@github/items/bfbf4c185ed7004b5721)を参考にしてください。

[^1]: セミナー[『ExcelソルバーではじめるOR』](http://www.orsj.or.jp/activity/seminar2016.html#semi2)より


# じゃんけんの利得表
利得表(の転置)を次のように決めます。自分がグー(G)で勝つと、得点が4倍になります。

相手＼自分|G|C|P
:--|:--|:--|:--
G|0|-1|1
C|4|0|-1
P|-1|1|0

# 定式化

- 自分がグー、チョキ、パーを出す割合を$x, y, z$ とします。(混合戦略)
- このとき、$x+y+z = 1$ です。
- 期待値は、相手がグーの場合 $-y + z$、相手がチョキの場合 $4x - z$、相手がパーの場合 $-x + y$ になります。
- この3つの期待値の最小値($w$)を最大化しましょう。こうすることによって、相手がどんな手を出そうが、期待値は $w$ 以上になります。

目的関数| $w$ → 最大化
:--|:--
制約条件|$x+y+z = 1$
 |$-y + z \ge w$
 |$ 4x - z \ge w$
 |$ -x + y \ge w$
 |$x,y,z \ge 0, ~~~ w: free$

# Pythonで解く

```py3:python
from pulp import *
from ortoolpy import addvar, addvars

a = [[0, -1, 1], [4, 0, -1], [-1, 1, 0]]
m = LpProblem(sense=LpMaximize) # 数理モデル
xyz = addvars(3) # 変数 x,y,z
w = addvar(lowBound=None) # 変数 w
m += w # 目的関数
m += lpSum(xyz) == 1 # 制約条件
for i in range(3):
    m += lpDot(a[i], xyz) >= w # 制約条件
m.solve() # 求解
print(value(w), [value(v) for v in xyz])
>>>
0.16666667 [0.16666667, 0.33333333, 0.5]
```

自分がグー、チョキ、パーを[1/6, 1/3, 1/2] の割合で出すと、相手がどんな手を出してきても、期待値を1/6にできることがわかります。

非協力ゲームでは、自分に有利な手(グー)の割合を小さくした方が、期待値が高くなるという面白い結果になります。

以上
AWS認定SAA(ソリューションアーキテクト アソシエイト)を受験しました。

10月に入ってAWS認定SAAを受験しました。
すでにたくさんの方が受験記を書かれていますが、ならってみます。

---

## 自分の経験

* 個人でAWSを触った経験はほぼなし
* EC2とRoute53のみ2年ほど前に触ったことがある程度
* 2016/04 より客先で本格的に使用
* 客先業務ではIAMがメイン

## 読んだ資料

* [公式のサンプル問題](https://aws.amazon.com/jp/certification/certified-solutions-architect-associate/)
* [Amazon Web Services 基礎からのネットワーク&サーバー構築](https://www.amazon.co.jp/Amazon-Web-Services-基礎からのネットワーク-サーバー構築/dp/4822262960/)
* AWS公式ドキュメント
  * IAM, EC2, S3, RDS, VPC, Route53, aws-cli あたり
* BlackBeltシリーズ
  * 上記の他、最近更新されたもの
  * CloudWatch, SQS, SNS, AutoScaling, ELB, CloudFront あたり
* [AWS WEB問題集](https://aws.koiwaclub.com/) 50くらいまで
* Qiitaの受験記

## 模試

AWS資格は[模試](https://aws.amazon.com/jp/certification/certified-solutions-architect-associate/)が受けられます。
安いので絶対受験！

* 雰囲気がわかる
* 問題レベルがわかる
* 出題形式がわかる

自分は上記の資料をある程度読んで、ひとまずの理解度を測るために模試を受けました。
その時は85%でした。
どなたかの受験記では、**「本試験では模試より10%下回る」**のように書いてありましたので、
一旦これで受けてみようと思いました。

## 結果

|総合スコア|75%|
|---|:---:|
|トピックレベルのスコア||
|高可用性、コスト効率、耐障害性、スケーラブルなシステムの設計|69%|
|実装/デプロイ|66%|
|セキュリティ|100%|
|トラブルシューティング|75%|

まさに「模試より10%下回り」ました。


## 感想

パブリッククラウドは個人で触ろうとするとハードルが高い部分があるかなと思いますが、
自分の場合、客先で大きなAWS上システムに触れることができたり、詳しい方に教えて頂く機会に恵まれたのがとても良かったです。
電話番号の入力チェックがなかなか通らなくてハマった

* http://itpro.nikkeibp.co.jp/expo/2016/regist/

![スクリーンショット_2016-10-19_08-47-24.png](https://qiita-image-store.s3.amazonaws.com/0/25728/6ad127af-0922-934e-5458-0e8953141548.png)

## エラー


![tel1.png](https://qiita-image-store.s3.amazonaws.com/0/25728/16a99f3c-f4fb-28c2-4d23-f8cd8509a21e.png)

![tel2.png](https://qiita-image-store.s3.amazonaws.com/0/25728/86546358-292e-e814-e81a-79078d094f7d.png)


> お勤め先電話番号1は8桁以内で入力してください。
> お勤め先電話番号は10桁もしくは11桁で入力してください。

* ？矛盾しているぞ？

* ハイフン区切りである必要があったようで、`03-1111-2222`と入力したら先に進めた。
    * 例をよく見ろってことですね。
Info.plistやNSUserDefaultsから手軽に値を取り出す拡張

Swift歴は浅いのですが、

- **Info.plist**
- **NSUserDefaults**
- **NSLocalizedString**

を簡単に取り出す拡張を書いてみました。

以下の3ファイルをプロジェクトに追加すれば、どこでも使うことができます。

もっと良い書き方があれば、ぜひ教えて下さい。

# こんな風に使えます

```swift:AppDelegate.swift
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.
        
        // 「初回起動ですよ」
        UD.setAsDefault("isFirstLaunch", value: true)

        // 開発中なら…
        if InfoPList.get("ShouldResetUserDefaultOnLaunch") as! Bool {
            UD.reset()
        }
        
        return true
    }
```

```swift:ViewController.swift
...

    recordButton.setTitle(local("Preparing"), forState: .Normal)

...
```

# 拡張ファイル

```swift:NSObject+InfoPList.swift
class InfoPList: NSObject {
    class func get(label: String!) -> AnyObject?{
        return NSBundle.mainBundle().objectForInfoDictionaryKey(label)
    }
}
```

```swift:NSObject+UD.swift
import Foundation

class UD: NSObject {
    
    static let ud = NSUserDefaults.standardUserDefaults()

    class func get(key: String!) -> AnyObject? {
        return ud.objectForKey(key)
    }
    
    class func set(key: String!, value: AnyObject!) {
        ud.setObject(value, forKey: key)
        ud.synchronize()
    }
    
    class func remove(key: String!) {
        ud.removeObjectForKey(key)
    }
    
    class func reset() {
        let bundle = NSBundle.mainBundle().bundleIdentifier
        ud.removePersistentDomainForName(bundle!)
    }
    
    class func setAsDefault(key: String!, value: AnyObject!) {
        ud.registerDefaults([key: value])
    }
}
```

```swift:NSObject+local
import Foundation

func local(key: String!) -> String {
    return NSLocalizedString(key, comment: "")
}
```
---
ブログやっています：http://weed.nagoya
DevFest Tokyo 2016に参加しました

# 勉強会の基本情報

* 【日　時】2016年10月09日 13:00~18:00
* 【会　場】東京電機大学 千住キャンパス
* 【参加費】無料
* 【主　催】GDG Tokyo, Shibuya.apk, DroidKaigi, 日本Androidの会, html5j, GTUG Girls, GCPUG, TensorFlow コミュニティ
* 【申し込み】http://gdg-tokyo.connpass.com/event/38927/

# 概要
* DevFest は、Google Developer Group (GDG) コミュニティによって世界各地で開かれるデベロッパー向けイベントである。
* DevFest Tokyo 2016 は、GDG Tokyo, Shibuya.apk, DroidKaigi, 日本Androidの会, html5j, GTUG Girls, GCPUG, TensorFlowなどコミュニティが集まる。
* 新しいノウハウや最新情報を共有するだけではなくコミュニティやプロダクトを超えた交流の場である。

# 内容
## Video Streaming on Android
### 発表者
* wasabeef
* 会社： AbemaTV, Inc.
    * AbemaTVとは、PC・スマートフォン向けのライブストリーミング形式によるインターネットテレビである。GCP上に、システムが構築されたので、AbemaTVの技術者は、googleのイベントによく参加している。

### 発表内容

#### ストリーミング概要

* 専用プロトコル
    * HLS
    * MPEG-DASH
    * Microsoft Smooth Streaming
    * RTMP
* ビデオ圧縮
* ビデオ構成
    * Video
    * Audio
    * Meta
* コンテナフォーマット
    * [コンテナフォーマット \- Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88)
* Video Codec
    * H.264/MPEG-4 AVC
    * H.265
    * VP8
    * VP9
* Audio Codec
    * MP3
    * AAC
    * PCM

#### Android Media APIS

MediaPlayer

* API Level 1から、C や C++ で実装されて、シンプルなAPIである
* カストマイズできない

ExoPlayer

* Google開発しているAndroid向けの新しいメディアプレイヤー
* 全てJavaで実装される
* ライブラリの形式で配布される

* メリット
 * MediaPlayerが対応していないアダプティブストリーミングの形式に対応している
 * カストマイズしやすい
 * 簡単にアップデートできる
* デメリット
 * Android4.1で実装されたMediaCodeに依存しているため、その以前のAndroidで動作できない



## Firebaseのススメ 

### 基礎

#### Firebaseとは

* クラウドでホストされるNoSQLデータベース
* 接続されている全てのクライアントとリアルタイムで同期
* データはJSONとして保存

#### Firebaseの主な機能

* リアルタイム
    * データが更新されると、接続されている全てのデバイスがその更新を数ミリ秒で受信する
    * クライアント側でネットワーク処理のコードを書く必要がない
* オフライン機能
* クライアント端末からアクセス可能

#### 注意

* NoSQLデータベースなので、RDBとは機能とやり方が異なる


### Firebase Analytics


#### Firebase Analyticsとは何か

* Google Analyticsと違い
    *　Firebaseの提供する解析ツール
*　Firebaseの各機能のユーザーリアクションの検証や、特定ユーザに対する「働き」を見る部分に強みがある

#### Firebase Analyticsって何が良いか

* イベントのパラメータを自由に設定可能
* 簡単なトラッキング
* ユーザー情報の設定
 

# 感想

* 今回の勉強会の会場は、東京電機大学千住キャンパスで、若い方が多い
* 久しぶり、Androidについてのstreamingを勉強して、ExoPlayerのことがわかった
 * 今後は、Android streaming作業をやると、androidバージョンを含んで、ExoPlayerやMediaPlayerが、どっち使うことを検討しないといけない
* Firebaseをよく触ったことがあるが、Firebase Analyticsを初めて勉強した
    * Firebaseの機能がどんどん追加されて、強くなる感じである
自宅のIPを監視

FreeBSDのar531xポートのコードをheadへのマージリクエストをしていたので、安定性確認のために連続運転してなにか動かしてみようと思い立ち、自宅のグローバルIPアドレスを監視してみた。

mruby 1.2入りのFreeBSD 12.0-CURRENTは[ZRouter](http://qiita.com/yamori813/items/2fc5b14648029bb4730f)でビルドします。

```sh:reach.sh
#!/bin/sh

HOST="www.yahoo.co.jp"

ping -c 1 ${HOST} > /dev/null

if [ $? == 0 ]; then
  IP=`mruby /tmp/myglobal.rb`
  VAL="OK,${IP}"
else
  VAL="NG"
fi

DAY=`date "+%Y/%m/%d"`
TIME=`date "+%H:%M:%S"`
echo ${DAY},${TIME},${VAL} >> /tmp/reach.log
```

グローバルIPを知る方法はいくつかあると思うのですが、検索してみて知った、以下の方法を使ってみました。

```ruby:myglobal.rb
h = HttpRequest.new()
response = h.get("http://ifconfig.me/", nil,{'User-Agent' => "curl",})

print response.body
```

reach.shをcronで5分おきに起動すると下記のようなログが吐かれます。

```
2016/10/17,23:20:08,OK,x.x.x.x
```
技術英語 > This example is [contrived] to show nesting levels.

@ Code Complete (No. 14660 / 36077)

ifが4段階にネストした例を見せて

> This example <font color=red>is contrived to</font> show nesting levels.

http://ejje.weblio.jp/content/contrive
> (…を)考案する、工夫する、たくらむ、もくろむ、首尾よく(…を)する、どうにかこうにかする、わざわざ(…を)しでかす

上記例文の意訳「この例はネストレベルを見せるために意図的に(こういう風に)作られている」
ErgoDoxのキー配列をカスタマイズしていく話

![IMG_5625.JPG](https://qiita-image-store.s3.amazonaws.com/0/117743/15983524-5bee-dbf9-34f7-4f1028ebb271.jpeg)

---

# ErgoDoxを使うなら

既存のキー配列を根本から問い直しましょう。
そして、己のポリシーで新しい配列を生み出しましょう。

---

## 何故か

---

- ErgoDoxでは物理的に既存の配列はそのまま再現出来ない
- 直線的なほぼグリッド形状
- そもそもキーボードってなんで斜めなの？
- タイプライターだとアームの配置的にずらして並べないといけないけど、コンピューターならそんな必要無いはず

---

![FireShot Capture 1 - Truly Ergonomic Mechanical Keyboard - _ - https___www.trulyergonomic.com_stor.png](https://qiita-image-store.s3.amazonaws.com/0/117743/3d70b3f5-d792-8fb3-2de5-ba2828aac9cb.png)

---

- 1860年代のタイプライターをいまだに引き摺ってる
- まっすぐにしようよ
- 6キーとか左手のほうが近いのに右手の扱いなのは変じゃない？
- エルゴノミクス謳ってて左右セパレートなのに配置が斜めなやつはやる気が足りない

---

## ErgoDox

- 左右セパレート
- 直列配置

→すばらしい

---

## げぇっ、エルゴノミクス信者！

- エルゴノミクスデザインとか理屈ばかりで実用的には大抵ロクなもんじゃないと思ってました
- でもまあ、いろいろと既存の概念を見つめ直す機会が生まれるのでErgoDoxはたのしいキーボード

---

# 現状の配置

---
## ベースレイヤー（QWERTY）
![keyboard-layout qwerty](https://qiita-image-store.s3.amazonaws.com/0/117743/726400c6-906c-b0e5-08ba-fa1d0d0eaabe.png)

---
- ホームポジションを崩さないことを追求
 - 従来の右手端の記号群などは小指伸ばしたりホームポジションずらしたりしてつらい
 - なのでErgoDoxでは端のキーはなるべく使わない
 - デフォルトでいっぱい割り振られているけど押しづらいキーは捨てる

---
- 親指キーに修飾キーを集約
 - 従来小指で扱っていた端のキーを親指化することで、残りの4指はホームポジションをキープ可能になる
 - 親指キーはたくさんあるけど、実用的なのは左右それぞれ4キーほど
 - 大きいキーはホールド用に使う

---
- タップとホールド使い分け
 - 左右の黄色キーは親指のホームポジション
 - それぞれスペースとエンターを割り当てたが、Cmd（Ctrl）キーもここで使いたい
 - ErgoDoxのファームウェアでは1キーにいろいろ機能を設定できる
 - ホールド時のみCmdにしてみたら便利

---
- 中央シフトキー
 - 小指使わないから便利

- Ctrl F3とか
 - MacでDockとかをキー操作する用

---
- 括弧をまとめて1キー化
 - 中央左右に開き括弧と閉じ括弧を設定
 - 通常押しで`[ ]`
 - shift押しで`{ }`
 - レイヤーキー押しで`( )`

---
# レイヤーキーとは

---
- Fnキーみたいなもん
 - Fn + 1 → F1キーになるみたいな
 - あれが好きなように設定できる
 - しかも何レイヤーでも
 - たとえば次のような感じにできる

---
## カーソルレイヤー
![keyboard-layout cursor](https://qiita-image-store.s3.amazonaws.com/0/117743/b1932e2f-a03b-2aec-9891-51281031f3d7.png)

---

- 右親指をホールドしているときだけ発動するレイヤー
 - 右手でカーソル、左手でマウスが動かせる
 - ホームポジションを追求した結果、とうとうマウスを捨てた
 - CUIが効かないアプリでもキーボードのみでいけるぞッ…！

---

## ほんとはマウス使ったほうが速い

---
- でもロマンじゃないですか
 - ErgoDoxは効率より楽しさ
 - あーだこーだと理屈をこねて実践できるのにハマる
 - 辛かったけどわりと慣れてきてホントにマウス使わなくなってきた

---
- カーソル移動がものすごく実用的
 - ホームポジションのまま使えるので一般的なカーソルキーよりも優秀
 - HHKBでも似たような設定はあるけど、ホームポジションじゃないしダイヤ型なのは冗長
 - vimの `HJKL` でも微妙にずれてるし、ゲーマーなら凸型がしっくり来るはず

---
# 残る聖域

---

- 数字＋アルファベットの10列4段
 - いろいろ周縁部はいじったけど、やはり中央の基本的な配置部分にはメスを入れづらい
 - ここを変えてしまうと他のPCが使えなくなりそうな懸念
 - しかしホームポジションを追求していると不満が抑えられなくなってきた

---
## Dvorak override layer

![keyboard-layout Dvorak](https://qiita-image-store.s3.amazonaws.com/0/117743/f5c2a8e3-8414-69e6-5c0f-f40108dc6d97.png)

---
- 昨日試してみたばかりでの感想
 - 中段の使用率がとても高くなり、無駄に指を前後に動かさずに済むことをすぐに実感
 - QWERTYだと`U,I,O`が上段にあることや`,./`が下段にあることが気に食わなかった
 - C-sなどのショートカット配置が変わってしまうのは痛手だが割と右手にまとまってる
 - 基本はDvorakだけど好きにいじってる

---

# レイヤー設定入れ替えについて

---

- Dvorakはあくまで上書き用レイヤーでqwertyにもすぐ切り替えられるようにしてある
- MacベースでCmdキーなど配置しているけど、Windowsで使うときにはCtrlで上書きして同じ感覚で使えるように設定してある
- 詳しくはソースで https://github.com/miyaoka/qmk_firmware/blob/master/keyboards/ergodox/keymaps/miyaoka/keymap.c