OmniAICreator/Qiita-1.07M huggingface dataset:
【DateTime】DateTime型を比較するためのcompareTo, isEqual, equalsの違い

# TL;DR
リソースが公開状態かどうかを判定するために、SQLのカラムにopenTime,closeTime等を設けていて、isOpenedみたいな判定をしたい。
そこでcompareToを使ってみたが、isBefore等を使っているケースもあり、このあたりのそれぞれの使い方や違いなどを少し調べてみたのでメモ。

compareTo,isEqual,equalsはそれぞれ戻り値とTimeZoneの扱いにおいて違いがあるため、必要に応じて適切に使う必要がある。

#isEqual (isAfter, isBefore)
A.isEqual(B) -> true : AとBは同じ
A.isAfter(B) -> true : AはBより未来
A.isBefore(B) -> true : AはBより過去

DateTime.isHogehogeを使った場合のisOpenedな判定は以下のようになる

```java:
(now.isEqual(openTime) || now.isAfter(openTime)) && now.isBefore(closeTime)
```

isAfter,isBeforeは一致の際にfalseなため、isEqualと組み合わせて使う必要がある。

また、DateTime.isHogehogeはTimeZoneを考慮しないことにも注意。

```scala:
A:DateTime = 2017-01-05T15:00Z
B:DateTime = 2017-01-05T15:00+09:00
```
のとき

```scala:
A.isEqual(B) // true
```

#compareTo
A.compareTo(B) -> -1 : AはBより過去
A.compareTo(B) -> 0 : AとBは同じ
A.compareTo(B) -> 1 : AはBより未来

compareToを使った場合のisOpenedな判定は以下のようになる

```scala:
now.compareTo(openTime) >= 0 && now.compareTo(closeTime) < 0
```
こっちのほうがシンプルでいいように感じる。

また、DateTime.isHogehogeはTimeZoneを考慮しないことにも注意。

```scala:
A:DateTime = 2017-01-05T15:00Z
B:DateTime = 2017-01-05T15:00+09:00
```
のとき

```scala:
A.compareTo(B) // 0
```

#equals
A.equals(B) -> true : AとBは同じ

この3つの中で、唯一このequalsがTimeZoneを考慮する

```scala:
A:DateTime = 2017-01-05T15:00Z
B:DateTime = 2017-01-05T15:00+09:00
```
のとき

```java:
A.equals(B) // false
```

### おわりに
何かご指摘やもっと良い方法等がありましたらコメントお願いします！
docker経由でコマンドを実行するshort hand

処理系をローカル環境にインストールせずに docker 経由で実行する機会が増えてきて、もっと簡単にするためのshell scriptを書いてみました。
`/usr/local/bin/d`

```
#!/bin/sh
IMG_TAG=`echo $1 | awk -F\@ '{print $1}'`
CMD=`echo $1 | awk -F\@ '{print $2}'`
IMG=`echo $IMG_TAG | awk -F: '{print $1}'`
TAG=`echo $IMG_TAG | awk -F: '{print $2}'`
if [ -z "$CMD" ]; then
  CMD=`echo $IMG | sed 's/.*\///'`
fi
docker run --rm -it -v $PWD:/mnt -w /mnt --entrypoint $CMD $IMG_TAG "${@:2}"
```

例えば、 ruby:alpine を実行

```
x> d ruby:alpine -v
ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-linux]
```

私家版の古いやつを実行

```
x> d s21g/ruby:1.8.7-p374-1 -v
ruby 1.8.7 (2013-06-27 patchlevel 374) [x86_64-linux]
```

そこで irb を実行

```
x> d s21g/ruby:1.8.7-p374-1@irb
irb(main):001:0>
```

`$PWD` をマウントしてるので、 `d haron/vim test.rb` で手元のファイルを編集して、`d s21g/ruby:1.8.7-p374-1 test.rb` で普通に実行できます。
kintone フォームクリエイターのカスタマイズ覚書

#kintone フォームクリエイターのカスタマイズ覚書
たまに開発案件でフォームクリエイターを使う機会がありますので、メモしておきます。

CSS と JavaScript は、「高度な設定」タブで指定します。

![2017-01-05_17h43_53.png](https://qiita-image-store.s3.amazonaws.com/0/100572/b5f11cb0-51bb-f124-36fe-9f5443da74c3.png)

- URL とファイルの同時指定は可能
- CSS, JavaScript のファイルは、それぞれ１つ指定
- 複数ファイルをアップロード出来ない

CSS,JavaScript が各１ファイルしか指定できませんので、複数ライブラリが必要な場合は、ライブラリをまとめて１ファイルにしてしまうか、動的に読み込む工夫が必要です。


#jQuery 関連について
2017/1/5 時点では、下記のライブラリが読み込まれます。
jQuery のバージョンに問題なければ、JavaScript カスタイマイズでもそのまま使用可能です。

- jQuery v1.7.2 
- iCheck v1.6 チェックボックス、ラジオボタンで使用されている。
- JSCal2, version 1.9　日付入力で使用

#JavaScript カスタマイズ

kintone のイベントのようなものは無く、通常のwindow ロード完了後のタイミングで実行させる。

アンケートなどによく使われる下記ライブラリも同時使用できました。
- 自動かな入力　[autoKana.js](https://github.com/harisenbon/autokana)
- 郵便番号から住所変換　[jquery.jpostal.js](https://github.com/ninton/jquery.jpostal.js)

## autoKana の Firefox 問題

autoKana.js　で Firefox の場合、変換後に入力した文字は無視される問題がありました。

対策としては、下記がありましたが、要検証です。

[CompositionEventを利用してフリガナを取得する(その2)](http://pinch-blog.blogspot.jp/2016/12/compositionevent2.html)

ソース
[https://github.com/VeryPinch/autoKana2](https://github.com/VeryPinch/autoKana2)

デモ
[https://verypinch.github.io/autoKana2/](https://verypinch.github.io/autoKana2/)


#フォームクリエイター関連情報


- [developer network](https://cybozudev.zendesk.com/hc/ja) 

[フォームクリエイター(サイボウズスタートアップス株式会社 Cstap)](https://cybozudev.zendesk.com/hc/ja/articles/203129920-%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%82%AF%E3%83%AA%E3%82%A8%E3%82%A4%E3%82%BF%E3%83%BC-%E3%82%B5%E3%82%A4%E3%83%9C%E3%82%A6%E3%82%BA%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E3%82%B9%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE-Cstap-)


- [kintoneapp BLOG](https://kintoneapp.com/blog/) のカスタイマイズ例

[フォームクリエイターの入力確認画面を自作HTMLで作ろう](https://kintoneapp.com/blog/formcreator_takeispecial/)
[多数のサイトを運営していてもOK！流入元判別カスタマイズ](https://kintoneapp.com/blog/formcreator_multipleform/)
[武井がフォームクリエイターを半日いじるとここまで良くなる](https://kintoneapp.com/blog/form_creator_takei/)
AndroidのLogCatを使用する際のセキュリティ観点について

JSSECが公開している『Androidアプリのセキュア設計・セキュアコーディングガイド』の2016-09-01版を共有用にまとめているもののうち、「4.8. LogCatにログ出力する」のものとなります
詳細やサンプルコードについては原著の方を参考ください
リリース版でも出力し、ユーザーが参照可能であるものを運用ログと表現します
リリース版アプリでは出力せず、ユーザーが参照不可能な想定のログを開発ログと表現します

## チェックポイント
- [ ] リリース版では、センシティブな情報をログ出力をしていない
- [ ] センシティブな情報は運用ログ(Log.e/w/i,System.out /err)で出力しない
- [ ] Throwableオブジェクトのログ出力には、Log.d/vを使用する
- [ ] ログ出力にはandroid.util.Logクラスのみを使用する(推奨)
 * System.out/ errでは運用ログと開発ログを分けれないため。また、LogとSystemを両方使用する場合、考慮することが増えることによるミスの発生を防ぐため、Logのみを使用するのが好ましい

## Tips
### LogCatについて
LogCatとはシステムだけでなく、アプリのログ情報も出力されます
LogCatのログ情報は、4.1未満では同じ端末の他アプリから読み取れたり、ADB経由での参照も可能なため、LogCatにはセンシティブな情報を出力すべきではありません。また、リリース版アプリでは必要のないログは出力しないことが望ましいです

### リリース版のログ出力の考え方
ログ出力の考え方として2パターンあります

* セキュリティ観点と出力することの価値の少なさを考えて、一切ログ出力しないという考え方。リリース後のアプリのLogCatの情報を開発者が取得する方法がなく、センシティブな情報が漏れる可能性があるため
* カスタマーサポートなどの不具合解析の最終手段として、解析に必要な情報をログに出力すべきという考え方。ただし、こちらの場合、センシティブな情報を誤ってログ出力しないように注意する必要があります

### ログレベルと、ログ出力メソッドの選択
運用ログとして

 * アプリが致命的な状況に陥った時に出力するLog.e
 * アプリが深刻な予期せぬ状況に陥った時に出力するLog.w
 * 上記以外で、アプリの注目すべき状態や情報を出力するLog.i

開発ログとして

 * 特定のバグ原因究明のために一時的にログ出力するLog.d
 * 運用、開発含め、上記に当てはまらないログを出力するLog.v

ただし、これらは、あくまで使い分の考え方、作法のようなものであり、Log.dもLog.vも、リリースビルドでもログを出力するため、自前で削除したりする必要があります

### 開発ログの削除
開発ログはリリース時には、出力されてはいけません。そのため、proGuardを用いて、自動で削除してしまうのが好ましいです。ただし、proGuardを使用して削除する場合、以下に関して考慮が必要です

* 戻り値を使用した場合、削除されない
* リリースビルド以外で作成した場合、削除されない
* Logの出力のために作成したString等は逆アセンブルで見ることも可能
* proGuardの設定がされていない他のプロジェクトでコードの再利用すると、漏洩する危険がある

### Intentの内容がLogCatに出力される
Activityを利用する際に、ActivityMangerがIntentの内容のうち、利用先パッケージ名、利用先クラス名、intent#setDataで設定したURIをLogCatで出力するため、どのようなactivityであっても、これらにセンシティブな情報が含まれないようにする必要があります

### System.out /errに出力されるログの抑制
System.out/ errの出力先はLogCatのため、読み取ることが出来ます。また、下記の場合も出力されます

* Exception#printStackTrace()を利用する場合
* 暗黙的に出力される場合(例外をアプリでキャッチしていない場合)

スタックトレースはアプリ固有情報があるため、例外は開発者が正しくハンドリングすべきです

保険的対策として、System.out/ errの出力先を変更、出力をしない方法がありますが、問題がないかを検討する必要があります。また、システムプロセスのエラーログを抑制はできません

## 参考

『Android アプリのセキュア設計・セキュアコーディングガイド』【2016年9月1日版】
https://www.jssec.org/dl/android_securecoding.pdf
JavaScriptでスクレイピングするなら、SpookyJS

# 導入のきっかけ
社長「このサイトのここの情報をシステム的に取れない？」
わたし「楽勝ですよ」

早速PerlのWeb::Queryでスクレイピングするプログラムを作成し、いざ実行。
欲しいコンテンツが、と、取れない。。

コンテンツのソースコードを確認すると、コンテンツの中身が空だ。
どうやらJavaScriptで生成されるコンテンツらしい。
くそっ、静的コンテンツしか取得できないWeb::Queryではどうしようもないではないか。

# CasperJSとの出会い
ググってみたところ、「CasperJS」というサーバーサイドjavascript向けモジュールが存在するらしい。

元々、外部からJavaScriptのAPIを使ってブラウザを操作できるというPhantomJSというヘッドレス(GUIの無い)ブラウザがあって、CasperJSはPhantomJSを便利に使えるモジュールらしい。

ただし、CasperJSは実行する際にnodeコマンドではなくcasperjsコマンドで実行するため、Node.jsで使える機能が使えない。
そこで、Node.jsからCasperJSを使えるようにするモジュールをググってみたところ、SpookyJSに出会った次第。

# CasperJSのインストール
## Node.js、npmのインストール
```shell-session
# npmをインストールするために、いったんnode.jsをインストール
$ sudo apt-get update
$ sudo apt-get install nodejs npm
$ npm cache clean

# nパッケージでnode.jsを管理
$ sudo npm install n -g
$ sudo n stable

# casperモジュールをインストール
$ sudo npm install phantomjs  -g
$ sudo npm install casperjs -g
```

## SpookyJSのインストール
```shell-session
$ sudo npm install spooky
$ sudo npm install tiny-jsonrpc
```

# 困ったこと
## SpookyJSのメソッド内でコメント
Raspberry Pi Cameraで日付＋時間をファイル名にして保存

# 準備
ImageMagickのインストール
この中のconvertを使ってサムネイル用のファイルを作る。

```shell-session
sudo apt-get install imagemagick
```
だと、”いくつかのアーカイブを取得できません。・・・・”というメッセージが最後に表示され失敗。
なので、

```shell-session
sudo apt-get -f install imagemagick
```
で目的のコマンドがインストール出来た。

#あらあらのフロー
日付＋時間.jpgを変数に代入→raspistillで撮影→convertで縮小してサムネイル保存

#シェルスクリプト
で、出来たスクリプトがこれ。
kasha.sh

```shell-session
NOW_TIME=`date '+%Y%m%d-%H%M'`.jpg

raspistill -o $NOW_TIME

convert -resize 320x -quality 100 $NOW_TIME thumb$NOW_TIME
```
DockerとCRIUでCheckpoint & Restore


CRIUを利用することで、DockerでCheckpoint & Restoreが可能だった。試してみたのでメモ。
基本的には以下に書いてあることを実施したのみ。
https://github.com/docker/docker/blob/master/experimental/checkpoint-restore.md


## チェックポイント・リストアとは
チェックポイント機能により、コンテナ状態（メモリ情報など）をdumpして、ディスク上に書き出すことができる。
リストア機能では、書き出した情報を読み込んでコンテナを実行することができる。この機能を活用することにより、

* 高速なアプリケーション起動が可能
	* 予め起動済のアプリケーションコンテナのチェックポイントを利用
* ライブマイグレーションが実現できる
	* VMのライブマイグレーションも同様の仕組み

といったことが可能になる。ライブマイグレーションについては、CRIUの現実装で既に可能らしいが、Dockerとしては優先度は低いらしく、Dockerコマンドのみでの実行は不可能と思われる。

## セットアップ
本機能を利用するには、Docker experimentalフラグをtrueにする必要がある。やり方は色々とあるが、例えば以下参照。
https://github.com/docker/docker/tree/master/experimental

チェックポイント・リストア自体は、Dockerではなく、CRIUという別のOSSの機能を利用している。
CRIUのインストール方法は、
https://criu.org/Installation
を参照。

## Dockerでチェックポイント・リストア
https://github.com/docker/docker/blob/master/experimental/checkpoint-restore.md
に記載されているコマンドを利用。1秒ごとに数字をインクリメントさせることで、checkpoint & restoreが正常に動作しているか確認できる。

まず、コンテナの実行。注意点として、-tオプションをつけないこと。

```
$ docker run --name cr_test -d busybox sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'
dd8ddc91cfcbf4059b72291996f647204b06d21790742665e43154eaf61add15
```

計算状況を確認するために、ログを監視。

```
$ sudo tail -f /var/lib/docker/containers/dd8ddc91cfcbf4059b72291996f647204b06d21790742665e43154eaf61add15/dd8ddc91cfcbf4059b72291996f647204b06d21790742665e43154eaf61add15-json.log
{"log":"0\n","stream":"stdout","time":"2017-01-04T02:18:53.010675677Z"}
{"log":"1\n","stream":"stdout","time":"2017-01-04T02:18:54.012090836Z"}
{"log":"2\n","stream":"stdout","time":"2017-01-04T02:18:55.021312544Z"}
```



まず、試しに `docker stop & start` を利用してみると、ログは、

```
{"log":"29\n","stream":"stdout","time":"2017-01-04T02:19:22.114085491Z"}
{"log":"30\n","stream":"stdout","time":"2017-01-04T02:19:23.115126028Z"}
{"log":"0\n","stream":"stdout","time":"2017-01-04T02:19:47.989991578Z"}
{"log":"1\n","stream":"stdout","time":"2017-01-04T02:19:48.992716272Z"}
```

となっており、計算が0から再開されているのがわかる。詳細はコードを見ないとわからないが、おそらく `docker stop & start` では、コンテナ上のプロセスを落とした後に、startで再起動という流れになるため、メモリ情報が失われてしまうだと思われる。

次に、checkpointを取得した後に、restoreを実行。

```
$ docker checkpoint create cr_test checkpoint1 
...
$ docker start --checkpoint checkpoint1 cr_test
```

すると、ログは、

```
{"log":"29\n","stream":"stdout","time":"2017-01-04T02:20:17.060391105Z"}
{"log":"30\n","stream":"stdout","time":"2017-01-04T02:20:18.061856991Z"}
{"log":"31\n","stream":"stdout","time":"2017-01-04T02:21:05.921558351Z"}
{"log":"32\n","stream":"stdout","time":"2017-01-04T02:21:06.923784094Z"}
```

となっており、計算が途中から再開されていることがわかる。
これを活用することで、例えば、計算時間が長いプログラムなどを走らせてるときに、定期的にチェックポイントを取得することで、プロセスが落ちても途中から計算再開といったことが、Dockerのレイヤで可能となる。
gitignoreを設定する

## gitignoreとはなにか

バージョン管理の対象から外したいファイルを「.gitignore」に記述する
GitHub, BitbucketなどでWeb、Android、iOSのソースコードをバージョン管理したいと思います。
その際に必要なファイルだけ管理して、不必要なファイルは管理しないようにした方が良いです。
そのファイルのためにリリースのたびに余計な作業があって開発の生産性が落ちたり、障害の原因になるからです。

###公式

https://git-scm.com/docs/gitignore

## gitignoreの書き方

gitignoreの書き方は正規表現ベースですがよくわからん場合は下記をみてください
[Git] .gitignoreの仕様詳解
http://qiita.com/anqooqie/items/110957797b3d5280c44f

## GitHub git ignore テンプレート集

けっこう自力で書くのはめんどうくさいのですでに書いてくれてるテンプレート使いましょう

https://github.com/github/gitignore

## gibo

https://github.com/simonwhitaker/gibo

### gibo 使い方

#### インストール(Mac)

```zsh
brew install gibo
```

#### macでJavaでAndroidを作る場合

プロジェクトを新規作成

~/AndroidStudioProjects/GiboTestApp に移動

```zsh

git init 

gibo Android Gradle Java macOS JetBrains >> .gitignore

git status

git add .gitignore
git add .

git commit

git push origin master
```

git add . で変更したもの全部でも、 git add ファイル名で指定するのも場合によって
選択してください

https://github.com/yanap/GiboTestApp

## すでにGitの管理下にあるものを除外したい

```
git rm --cached app/.gitignore
git rm --cached .DS_Store

git rm --cached -r /build

git status

git add .
git commit -m "modify git ignore files"
```
スライサー（FDM式３Ｄプリンタ向け）の作成　其の１０（閉領域の分割アルゴリズム）

* [スライサー（FDM式３Ｄプリンタ向け）の作成　目次](http://qiita.com/isTwt/items/5d40286eec73296ea790)

-----

# １．はじめに
　さて、前回までのアルゴリズムで基本的なことはできるのですが、もう一歩進むため、今回は先にアルゴリズムを説明します。

# ２．やりたいこと
　[其の７](http://qiita.com/isTwt/items/129ee9d06d79ee38d871)や、[其の８](http://qiita.com/isTwt/items/9a0703a4fa27bbcc7379)のアルゴリズムで得た閉領域が２つあります。
　１つは、切られる側とします。（以降の絵では赤枠）
　もう一つは、切る側とします。（以降の絵では青枠）
　切られる側の領域から切る側の領域を切り抜き新たな閉領域を求める（アルゴリズム（考え方）を示します。）。

# ３．考え方
　２つの閉領域の重なり具合により判断します。

# ３．１　領域が重ならない
![a1.JPG](https://qiita-image-store.s3.amazonaws.com/0/157557/3915dcfc-883f-601e-1522-520fdc1df5a6.jpeg)
　この場合、重なる領域は無しと判断します。

* 重なりの有無は、赤枠の全頂点が青枠内か否かを判断する。
* ある点が領域内か否かを判断するには別のアルゴリズムが必要なのですが、機会があれば別途説明したいと思います。

# ３．２　切る側が切られる側の内部に収まる
![a2.JPG](https://qiita-image-store.s3.amazonaws.com/0/157557/b6ba775f-04c8-2c3b-0426-9a13eca12787.jpeg)
　この場合、切る側（青枠）の領域と同じと判断します。

* 青枠の全頂点が赤枠内であるか判断します。

# ３．３　切られる側が切る側の内部に収まる
![a3.JPG](https://qiita-image-store.s3.amazonaws.com/0/157557/3eee4063-b647-54f7-276a-186ac16174d7.jpeg)
　この場合、切られる側（赤枠）の領域と同じと判断します。

* 赤枠の全頂点が青枠内であるか判断します。

# ３．４　双方の領域が一部重なる
![a4.JPG](https://qiita-image-store.s3.amazonaws.com/0/157557/8bb21762-b686-706c-b70f-c73072af0835.jpeg)
　この場合、３．１～３．３に当てはまりません。
　この場合、双方とも、一部頂点は相手の領域内で他の頂点が領域外となります。

![a4-1.JPG](https://qiita-image-store.s3.amazonaws.com/0/157557/2c3bf6c9-e518-0bd2-e12d-1a53c0e1522e.jpeg)
　この条件の場合、赤枠の全稜線について、青枠の全稜線と交差チェックし、交点を求めます。
　※赤P1-P2と青P1-P2/P2-P3/P3-P4/P4-P1　のように

![a4-2.JPG](https://qiita-image-store.s3.amazonaws.com/0/157557/5d9124b5-669e-25cb-facb-e153ab0e2e2c.jpeg)
　これにより、新たなA/Bの２点が求められます。この交点A/Bは各閉領域上どの位置（順番）かも保持します。
　　赤枠の場合、P1,P2,A,P3,B,P4,P1
　　青枠の場合、P1,A,P2,P3,P4,B,P1

![a4-3.JPG](https://qiita-image-store.s3.amazonaws.com/0/157557/8d26624c-de15-84bb-3676-70389b1bed89.jpeg)

1. 赤枠の最初の点から、最初に見つかった交点まで照査します。（交点Aを新閉領域として保持）
1. 赤枠を次の交点まで照査します。（P3,交点Bを新閉領域として保持）
1. 青枠を当該交点(B)から次の交点まで照査します。（P1,交点Aを新閉領域として保持）
1. 最初の交点に戻ったので終了。
　これにより、A,赤P3,B,青P1,Aという閉領域が求められました。

# ３．５　切られる側が切る側により分断される。
![a5.JPG](https://qiita-image-store.s3.amazonaws.com/0/157557/dc22df98-a03d-bb3f-289b-83b5c30fcf30.jpeg)
　この場合、３．１に近く（頂点と相手閉領域の関係）、３．２～３．４に当てはまりません。
　しかし、双方の稜線の交差チェックをすると交差点があります。（３．１は交差点がない）

![a5-1.JPG](https://qiita-image-store.s3.amazonaws.com/0/157557/e535503c-0b43-98bc-6117-c368e6196795.jpeg)
　この条件の場合、赤枠の全稜線について、青枠の全稜線と交差チェックし、交点を求めます。

![a5-2.JPG](https://qiita-image-store.s3.amazonaws.com/0/157557/c0726031-2d6d-da09-965e-6e8cf84eba6d.jpeg)
　これにより、新たなA/B/C/Dの４点が求められます。この交点A/B/C/Dは各閉領域上どの位置（順番）かも保持します。
　　赤枠の場合、P1,P2,A,B,P3,P4,C,D,P1
　　青枠の場合、P1,D,A,P2,P3,B,C,P4,P1

![a5-3.JPG](https://qiita-image-store.s3.amazonaws.com/0/157557/5e41b0de-cbd7-2aed-0ad1-8c9a7af2cb7b.jpeg)

1. 赤枠の最初の点から、最初に見つかった交点まで照査します。（交点Aを新閉領域として保持）
1. 赤枠を次の交点まで照査します。（交点Bを新閉領域として保持）
1. 青枠を当該交点(B)から次の交点まで照査します。（交点Cを新閉領域として保持）
1. 赤枠を当該交点(C)から次の交点まで照査します。（交点Dを新閉領域として保持）
1. 青枠を当該交点(D)から次の交点まで照査します。（交点Aを新閉領域として保持）
1. 最初の交点に戻ったので終了。

　これにより、A,B,C,D,Aという閉領域が求められました。

* 実は３．４と同じ処理です。3,4が繰り返し部分。

# ４．おわりに
　今回の説明では、簡単な閉領域の例でしたが、実際の閉領域は複雑な多角形です。
　よって現状のようなアルゴリズムになっています。（実際はもっと複雑ですが）
　なお、本アルゴリズムはこの後いろいろな場面で利用します。
新しいMacにいい感じのPython開発環境を作りたい

#参考記事（ほぼそのまま使っています）
http://qiita.com/shizuma/items/027167c6257f1c9d2a6f

#1.Homebrewをいれる

コマンド一発。

```
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

#2.pyenvとvirtualenvをいれる

```
$ brew install pyenv
$ brew install pyenv-virtualenv
```

#3. .bash_profileに以下を追記

```
PYENV_ROOT=~/.pyenv
export PATH=$PATH:$PYENV_ROOT/bin
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
```

反映。

```
source ~/.bash_profile
```

#4.anacondaをいれる

このコマンドでインストールできるいろんなpythonがでてくる

```
$ pyenv install --list
```

この中から、僕はPython2系を使いたいので、anaconda2の最新を入れます

```
$ pyenv install anaconda2-4.2.0
```

pyenvが現在指定しているpythonを確認する

```
$ pyenv versions

* system (set by /Users/nakazonor/.pyenv/version)
  anaconda2-4.2.0
```
これでアスターがついてるほうが今指定されてるPython
systemは最初から入ってるPythonってことでしょう

そしたら、以下のコマンドでインストールしたanacondaを指定する

```
$ pyenv global anaconda2-4.2.0
```

これでPython2系のAnacondaが指定された。
せっかくなのでPython3系もいれとこう

```
$ pyenv install anaconda3-4.2.0
```

またpyenv globalでanaconda3を指定すればPython3になる

```
$ pyenv global anaconda3-4.2.0
```

#5.virtualenvでプロジェクトを作る

ディレクトリ作る

```
$ mkdir study-conda
```

こんな感じでインストールしたPythonのバージョンとプロジェクト名を指定すればいいらしい

```
$ pyenv virtualenv anaconda2-4.2.0 study-conda
```

さっき作ったディレクトリの中で

```
$ pyenv local study-conda
```
こうすると、このあとstudy-condaディレクトリに入ると自動的にvirturalenvで指定したstudy-conda環境になる。
（要するにこの中でpipとかcondaでパッケージを入れてけば、他の環境を汚さない)

ちなみに

```
$ pyenv local --unset
```
でlocalの設定を解除できる。

↓virtualenvを削除したいときはこれでおｋ

```
$ pyenv uninstall study-conda
```

#6.pip installしてみる

```
$ pip install numpy
```

```
$ pip list
numpy (1.11.3)
pip (9.0.1)
setuptools (27.2.0)
wheel (0.29.0)
```
numpyが入ったね。

今度はstudy-condaディレクトリを抜けてpip listしてみると・・・
なんかいっぱいでてきたけど、たぶんこれはanacondaで入れたからだと思う。

```
$ cd ..
$ pip list
alabaster (0.7.9)
anaconda-clean (1.0)
anaconda-client (1.5.1)
anaconda-navigator (1.3.1)
appnope (0.1.0)
appscript (1.0.1)
argcomplete (1.0.0)
astroid (1.4.7)
astropy (1.2.1)
Babel (2.3.4)
・
・
・
```


まあ、とにかく、これでディレクトリごとに環境を分けることに成功した。


次はVSCODEを使ってデバッグをできるようにしていきたいと思う。
js 配列に別の配列の新たな数を追加していく

##お題
・配列に別の配列の新たな数を追加していく
・新たな数は最後尾に順に足していく

```js
function uniteUnique(arr) {
//write your code.
   return newArr;                    
}

uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]) // [1, 3, 2, 5, 4]
```

##出力結果　例

```js
([1, 3, 2], [1, [5]], [2, [4]]) // [1, 3, 2, [5], [4]]
([1, 2, 3], [5, 2, 1]) // [1, 2, 3, 5]
([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]) // [1, 2, 3, 5, 4, 6, 7, 8]
```

##使ったもの
[arguments](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments)
reduce()
concat()
indexOf()
slice()

##考え方
・Array.prototype.slice.call(arguments)で複数の引数を変数(args)にいれてまとめて扱う。
・reduce()でargsをはじめから順に比較していく。
・filterにてはじめの引数(arrA)にない値を次の引数(arrB)から選び、concatで付け足す。
・新たな値は新しく用意した変数に入れて、それを返しておわり

##コード

```js
function uniteUnique(arr) {
 var newArr;
  var args = Array.prototype.slice.call(arguments);
  newArr = args.reduce(function(arrA,arrB){
    return arrA.concat(arrB.filter(function(i){
      return arrA.indexOf(i) === -1;
    }));
  });

   return newArr;                    
}
```


###他にもコードが浮かんだ方、コメントお待ちしております。
Laravel5.1のCSRFチェックで一部のURLだけ無効化する方法


```php
<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [ // ←ここ！！
        '/hoge/{id}',
        '/users',
    ];
}
```
Node.jsを使ったやっつけのファイル操作

# 概要

Node.jsを使って「こまけぇこたぁいいんだよ」マインドでファイル操作を実装した。

## 2019/12/13追記

事実を誤認させると感じたのでタイトルを変更

- 変更前「Node.jsを使った簡単なファイル操作」
- 変更後「Node.jsを使った**やっつけの**ファイル操作」

## 2018/08/07追記

以下のように記述の誤りの指摘があったので主にサンプルコードの記述を修正しています。
今「node fs」で検索するとこの記事めちゃくちゃ上に来るんですね！びっくりした！
まだ記述がおかしいところもあると思うので気づいてくれた方はコメントで指摘していただけると幸いです。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">関数の用途もそうではあるけど、説明（fsは関数じゃねえ）もズレてるし、自分で定義したcheck関数呼ぶときに引数与えてないし、いきなりthis書いてあるしで、なんかお前動かしてないだろ！ってのが滲み出てて辛かった</p>&mdash; たっこん (@takkkolive) <a href="https://twitter.com/takkkolive/status/1024975357269557248?ref_src=twsrc%5Etfw">2018年8月2日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 公式モジュール`fs`

Node.jsには公式モジュールの`fs`があるのでそれを使用する。
[File System | Node.js v7.4.0 Documentation](https://nodejs.org/api/fs.html)

ドキュメントにてメソッドを確認するとわかる通り、通常メソッドと、Syncメソッドが存在している。
メソッドの実行は基本的に非同期で行われるため、例えばファイルの存在チェックを行なった場合、`fs.stat`を用いると「ファイルが存在しているのにエラーが返る」ことがある。
今回は速度とか「こまけぇこたぁいいんだよ」マインドで`fs.statSync`などの同期実行メソッドを使っていく。

とりあえず`var fs = require('fs');`するのを忘れないように。

## ファイルの存在確認

ファイルの存在確認には`fs.statSync`を用いる。
ファイルが存在しないとエラーになるのでtryしてcatchしてあげよう。

```js
function check(filePath) {
  var isExist = false;
  try {
    fs.statSync(filePath);
    isExist = true;
  } catch(err) {
    isExist = false;
  }
  return isExist;
}
```

## ファイルの中身を読む

ファイルの中身を読むには`fs.readFileSync`を用いる。
先に実装した存在チェックを用いているが、try/catchで十分な気もする。

```js
function read(filePath) {
  var content = new String();
  if(check(filePath)) {;
    content = fs.readFileSync(filePath, 'utf8');
  }
  return content;
};
```

## ファイルに書き込む

ファイルに書き込むには`fs.writeFileSync`を用いる。
ファイルが存在しない場合はファイル作成からやってくれる。
このメソッドを使う場合、ファイルの内容を丸々書き換えてしまうので注意が必要。
追記には`fs.appendFileSync`とか使うといいのかもしれない。知らんけど。

```js
function write(filePath, stream) {
  var result = false;
  try {
    fs.writeFileSync(filePath, stream);
    return true;
  } catch(err) {
    return false;
  }
}
```

## ファイルを削除する

ファイルを削除する場合は`fs.unlinkSync`を用いる。
rmとかmvとかdeleteとかじゃないんだー。

追記(2019/06/20): deleteが予約語で使えないという指摘をいただいたので修正します

```js
function deleteFile(filePath){
  var result = false;
  try {
    fs.unlinkSync(filePath);
    return true;
  } catch(err) {
    return false;
  }
}
```

# テストケース

テストコードは次のように書くとスムーズ

- ファイルが存在しないことをcheck
- ファイルにwrite
- ファイルが存在することをcheck
- ファイルをread
- ファイルをdelete
- ファイルが存在しないことをcheck

# まとめ

あくまで動かすサービス(で合ってる？)は1こだけ、というミニマルなシステムの中で動かすこと前提で書いたコード。
同時に複数起動する場合、ファイルアクセスの監視(`fs.watch`とか)とかファイル編集のロックとかも実装しなきゃいけないし、それに伴ってdurationの設定とかもしなきゃいけないから注意してほしい。

# 参考
[Node.jsでファイルに書き込むサンプル - 感謝のプログラミング 10000時間](http://blog.codebook-10000.com/entry/20130730/1375204497)
[fs.statSyncでファイルの存在判定 - Qiita](http://qiita.com/tokimari/items/82222e1f99b2b9eb1fb8)
[nodejsでファイルを削除する - みんなのちからになりたい](http://ginzanomama.hatenablog.com/entry/2012/01/19/212016)
cURL, OpenSSLコマンドでTLSのバージョンを指定する方法

## 関連記事
[pythonのrequestsでTLSのバージョンを指定する方法](http://qiita.com/Esfahan/items/7926c97370b6b2930091)
[pythonのrequestsモジュールのデフォルトのTLSバージョンはいくつなのか](http://qiita.com/Esfahan/items/ba811a3c93671420bcd8)

# cURL
## TLSのバージョンを指定してアクセス
TLS1.0

```bash
$ curl -s -v --tlsv1.0 https://xxxx.com > /dev/null
```


TLS1.1

```bash
$ curl -s -v --tlsv1.1 https://xxxx.com > /dev/null
```

TLS1.2

```bash
$ curl -s -v --tlsv1.2 https://xxxx.com > /dev/null
```

# OpenSSL
## TLSのバージョンを指定して接続テスト

TLS1.0

```bash
$ openssl s_client -connect xxxx.com:443 -tls1 < /dev/null
```

TLS1.1

```bash
$ openssl s_client -connect xxxx.com:443 -tls1_1 < /dev/null
```

TLS1.2

```bash
$ openssl s_client -connect xxxx.com:443 -tls1_2 < /dev/null
```

## 結果確認
**成功例**
Protocolが指定したバージョン、Cipherが下記のような値になっていれば成功

```bash
*snip*
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
*snip*
```

**失敗例**
下記のように、Cipherが0000となっていたら失敗

```bash
Cipher    : 0000
```

[参考]
[openssl コマンドで SSL/TLS バージョンを指定した HTTPS 接続テストを実施する](http://sig9.hatenablog.com/entry/2016/07/03/230000)
[HTTPS通信の疎通確認に覚えておきたい３つのコマンド](http://qiita.com/greymd/items/68b0c40044a88171235a)
pythonのrequestsでTLSのバージョンを指定する方法

## 概要
pythonのrequestsモジュールで利用されるTLSのバージョンは、関連モジュールに依存する。

参考： [pythonのrequestsモジュールのデフォルトのTLSバージョンはいくつなのか](http://qiita.com/Esfahan/items/ba811a3c93671420bcd8)
※こちらの記事を先に読むことをお勧めします。

ここでは、あえてTLS1.0を利用したい場合など向けに、requestsモジュールのTLSのバージョンを指定する方法を書きます。

## 環境
- python 2.7.12
- requests 2.12.3

## HTTPAdapterのサブクラスを作成
下記のようにHTTPAdapterのサブクラスを作成し、TLSのバージョンを明記して、requestsモジュールを利用する。
下記はTLS1.0を指定した例。

```
# -*- coding:utf-8 -*-
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
import ssl

# HTTPAdapterのサブクラス
class MyAdapter(HTTPAdapter):
    def init_poolmanager(self, connections, maxsize, block=False):
        self.poolmanager = PoolManager(num_pools=connections,
                                       maxsize=maxsize,
                                       block=block,
                                       ssl_version=ssl.PROTOCOL_TLSv1)


if __name__ == '__main__':
    import requests

    url = 'https://xxxx.com'

    s = requests.Session()
    s.mount('https://', MyAdapter())
    response = s.get(url)
    print(response)
```

各種バージョンの記載方法は下記。

| ver | 記法 |
| :-- | :-- |
| TLS1.0 | ssl.PROTOCOL_TLSv1 |
| TLS1.1 | ssl.PROTOCOL_TLSv1_1 |
| TLS1.2 | ssl.PROTOCOL_TLSv1_2 |

[関連記事]
[pythonのrequestsモジュールのデフォルトのTLSバージョンはいくつなのか](http://qiita.com/Esfahan/items/ba811a3c93671420bcd8)
[cURL, OpenSSLコマンドでTLSのバージョンを指定する方法メモ](http://qiita.com/Esfahan/items/53399964cb76cdb87e60)

[参考]
[Python requests SSLError: EOF occurred in violation of protocol](http://hiropppee.hateblo.jp/entry/2015/11/15/004803)
pythonのrequestsモジュールのデフォルトのTLSバージョンはいくつなのか

## 概要
表題のとおり。
TLS1.0を廃止するサービスも増えてきたので気になった。

## 関連記事
[pythonのrequestsでTLSのバージョンを指定する方法](http://qiita.com/Esfahan/items/7926c97370b6b2930091)はこちら

## 環境
- python 2.7.12
- requests 2.12.3

これらをAWS Lambda上で実行している。

## 調査内容
http://stackoverflow.com/questions/38501531/forcing-requests-library-to-use-tlsv1-1-or-tlsv1-2-in-python

この記事によると、
利用しているopenSSLが1.0系の場合は、自動的にTLS1.2になるようだ。
requestsモジュール自体はSSL/TLSのバージョンをあらかじめ決めておらず、
関連モジュール(この場合はopenSSL)から返ってきたSSL/TLSバージョンを使うようだ。

つまり、requestsがTLSのどのバージョンが使うかは、openSSLのバージョンに依存するらしいということで、Lambda上のopenSSLのバージョンを調べてみる。


## 調査方法
lambdaで下記のpythonコードを実行して結果を得る

```py
# -*- coding:utf-8 -*-
import ssl

def lambda_handler(event, context):
    return ssl.OPENSSL_VERSION
```

## 結果
```
"OpenSSL 1.0.1k-fips 8 Jan 2015"
```

1.0.1なのでTLS1.2が使われていると思われる。

以上

[関連記事]
[pythonのrequestsでTLSのバージョンを指定する方法](http://qiita.com/Esfahan/items/7926c97370b6b2930091)
[cURL, OpenSSLコマンドでTLSのバージョンを指定する方法メモ](http://qiita.com/Esfahan/items/53399964cb76cdb87e60)
typusでActiveRecord::enumに合わせる方法

rails4.1から```ActiveRecord::Enum```が採用されて、困ったことになった。

Typusの標準でつけていた、セレクトボックスの機能に対しては、モデルに```statuses```の様に、カラム名の複数形で選択肢の名前を記述させる仕様が、```ActiveRecord::Enum```の仕様と被ってしまった。

どうやって、この問題をなるべく綺麗に回避しようかと考えた結果の自分なりのログです。



## ```enum_help```を導入する

他のgemだと、rails admin、active adminそれぞれで、カラム名にひと単語加えたエイリアスを貼ったりする方法で管理をしていた。

* [Rails activeadmin enumを設定したモデルを登録する方法](http://qiita.com/rinkun/items/2399c7b4ce09310dc489)
* [rails_adminでenum指定したデータをラベルで選択できるようにする](http://qiita.com/zaru/items/508035b94deb6b57f671)

そもそも、railsが標準でenumを導入したのに、そのi18nの方法は全く手をつけないでしまったのが、railsコミュニティ死ね！と言いたくなる片手落ちの解決方法なのですが、現実策としては、i18nを拡張するgemを採用して、それに合わせてtypusをカスタマイズしてしまう方法でした。

簡単に検索した結果、enum_helpの評判が良さそうなのでそのまま採用してカスタマイズした結果、案外よく動いてしまったので、反芻することなくそのまま使ってしまっています。

https://rubygems.org/gems/enum_help/

まずは、gemfileに記述を行なって、```bundle install```。

```ruby
gem "enum_help"
```

これで、カラム名にi18nを付ければi18nが行われる様になりました。

```ruby
class User < ActiveRecord::Base
  enum status: { retired: 0, entried: 1 }
end

User.statuses_i18n # {"retired"=>"退会済", "entried"=>"入会中"}
user.status_i18n # 入会中
```

あとは、i18nに対応しているメソッドがあるときはそれを実行する様に、typusの内側を書き換えてあげるだけです。

以下のコードを```app/helpers/admin/resources/data_types/selector_helper.rb```というテキストファイルに貼り付けてください。typusの既存の機能を上書きして、先に```_i18n```が付いているメソッドを探して実行する様になります。

```ruby:app/helpers/admin/resources/data_types/selector_helper.rb
module Admin::Resources::DataTypes::SelectorHelper

  def table_selector_field(attribute, item)
    item.try("#{attribute.to_s}_i18n") || item.mapping(attribute)
  end

  def display_selector(item, attribute)
    item.try("#{attribute.to_s}_i18n") || item.mapping(attribute)
  end
end
```

同じ様に編集画面で作成するセレクトボックスも、以下のコードを作成して、```_i18n```の付いたメソッドを先に探す様に、既存の機能を上書きしてしまいます。

```erb:app/views/admin/templates/_selector.html.erb 
<%
  custom = { :rows => @resource.typus_options_for(:form_rows) }
  options = options.merge!(custom)
%>
<div class="control-group" id="<%= attribute_id %>">
  <%= form.label attribute, label_text, { :class => "control-label" } %>
  <div class="controls">
    <% if attribute=="role" and  admin_user.role!="admin"  %>  
      <% html_options.merge!(disabled: true) %>
      <%= form.select attribute, @resource.send(attribute.pluralize), options, html_options %>
    <% else %>
      <%= form.select attribute, @resource.try("#{attribute.pluralize}_i18n").try(:invert) || @resource.send(attribute.pluralize), options, html_options %>    <% end %>
  </div>
</div>
```

これで、i18nの付いた、セレクトボックスを再現出来ました。

![スクリーンショット 2017-01-05 17.58.13.png](https://qiita-image-store.s3.amazonaws.com/0/10715/c53072c4-596f-0a2b-a8a2-92e518b1d437.png)

２ファイルを上書きするだけで、i18nを実現出来たので、typus標準に組み込んでしまいたいのですが、typus自体は、必要最小限のgem以外は取り込まない方針なのでなかなか難しいのでしょうね。
laravel5にてconfig/app.phpに登録したproviderやaliasが読み込まれなかったときにすること

## はまったのでメモ

新規にServiceproviderを登録したのにregister()が動かない。

AppServiceProviderに書いとけばひとまずは動く。

そんな不可解なことに巻き込まれて時間を浪費してしまったので
次はスマートに解決できるよう投稿しておく

## 前提

config/app.phpのaliasやproviderに登録したいサービスプロバイダーないし
サービスは書いてありますよね？
記述がなかったらまずはここに登録してデバッグを行いましょう。

## それでもダメな時

そう私のはまった部分。汗

①

```bash
$ php artisan cache:clear
```

②

```bash
$ php artisan config:cache
```

③

```bash
$ composer dump-autoload
($ php conmoser.phar dump-autoload)
```

キャッシュファイルが悪さしている確率が高いので上記手順を踏んでみたら正常に動くようになりました。

もちろん私の環境はlocalだったのですが、、


意外とキャッシュにはまることあると思うのでお試しください

よいlaravelライフを！
Railsのセキュリティに関して調べたこと

お問い合わせ攻撃対応
google http://tango-ruby.hatenablog.com/entry/2016/01/21/191706
古いやつ https://github.com/plataformatec/mail_form https://github.com/pludoni/simple-captcha
dos対応
https://github.com/kickstarter/rack-attack
https://www.upguard.com/articles/top-7-ways-to-hack-rails-how-to-fix
http://guides.rubyonrails.org/security.html
https://github.com/rauchy/rack-attack-recaptcha

rack attack テスト
http://blog.hayleyanderson.us/2015/06/05/using-and-testing-rack-attack-to-improve-the-security-of-your-rails-app/

https://hakiri.io/blog/ruby-security-tools-and-resources
https://github.com/ankane/secure_rails
Azure functions ログの参照方法まとめ


Azure functionsは実行プログラムのログが（一部だったり全部）表示がされない時があります（デバッグ時に困る。。）そんなとき、別の方法で見れたりするので、複数知っておくと助かります。そこで、複数ある参照方法をまとめました。

## functionsログ参照方法
### functionsのlog window
最も簡単な方法です。azureポータルにログインして該当functionsまで遷移したら、画像のようにログが流れます。
![Azure_functions_log_window.png](https://qiita-image-store.s3.amazonaws.com/0/1533/4e46ea27-218d-2561-6249-b7ae38b378bf.png "Azure_functions_log_window.png")

ストリーム表示なので、過去のログを追うというより、今動いてるログを確認する用になります。ここで（全部or一部）表示されなくても左下の`最新の情報に更新`をクリックで表示される場合があります。
（log windowが無い場合は右上の`ログ`をクリック）

### functionsのモニター
こちらもポータルの機能で、上記画像の`モニター`をクリックで利用可能ですが、特徴として、ストリームではなく、プロセスごとにログが確認できます。実行完了した該当プロセスをクリックすると、ログが確認できます。
欠点として、この画面が重いのと表示エリアが小さいため、やや見にくいです。

### Kuduのlog stream
functionsに付随するKuduサービスにログのストリーム表示があります。内容は１つ目のlog windowと同じですが、そこで確認できない場合の、予備表示ぐらいで捉えてます。

* function Appの設定 -> Kuduに移動

![Azure_functions_to_kuzu.png](https://qiita-image-store.s3.amazonaws.com/0/1533/606042e3-09db-3cd1-e29d-8bc3c9c736f7.png "Azure_functions_to_kuzu.png")

* Tools -> Log stream

![Azure_kudu_logstream.png](https://qiita-image-store.s3.amazonaws.com/0/1533/1e8f8899-39e6-f5ac-1433-21213e9bb5ec.png "Azure_kudu_logstream.png")

最初の表示が遅いという難点はありますが、一度開いておけば、そのままタブ表示で置いておけるという利便性はあります。

### REST API
azureにも様々なapiが用意されており、functionsのログ表示機能もあります。
そこでわざわざブラウザを開かなくて良いように、shを作成しました。

```sh:log_stream.sh
#!/bin/sh
curl \
-X GET \
-H "Authorization:Basic <base64encode(username:password)>" \
https://<functions resource name>.scm.azurewebsites.net/api/logstream/application/functions/function/<function name>

```

`<>`内を適宜置き換えてもらえばいいのですが、

 * `base64encode(username:password)`・・・functionsの認証情報（詳細は以下で説明）の`username`と`:`と`password`をくっつけた文字列をbase64エンコードしたもの
 * `functions resource name`・・・functionsのリソース名
 * `function name`・・・functions内に作った関数名

log_stream.shを叩くと、

```sh
$sh log_stream.sh
```

１つ目のポータルで表示されるlog windowと同じログが参照できます。私はこれを多用してます。わざわざブラウザで遷移しなくてもいいし、他のfunctions作っても、ほぼコピペでそのまま使い回せて楽です。

ちなみにbase64エンコードは、phpであれば`base64_encode()`関数があるので、以下で作成できます。

```php:base64encode.php
echo base64_encode("username:password");
```

他の言語使わずshで完結させたかったのですが、すんなり書けなかったので妥協。。。

### functionsの認証情報

Function app の設定 -> App Service の設定に移動 -> デプロイ資格情報 -> `FTP/デプロイ ユーザー名`と`パスワード`で設定できます。

![functions_auth_setting.png](https://qiita-image-store.s3.amazonaws.com/0/1533/b42d3439-bfe7-b892-3cfd-f37ee8fc72fa.png "functions_auth_setting.png")




## 実際のところ
４つほど参照方法を挙げましたが、以下が、実際の開発でよくあるパターンで、

* functionsをポータルから作ったら、log_stream.shを用意する（参照方法４つ目）
* 表示がおかしいと思ったらポータルのlog window（参照方法１つ目）で最新の情報に更新して確認する

これでほぼ問題なくデバッグできました。
Visual Studio Code上でターミナル起動

今日だけで何度もググってしまったのでメモ

ちなみにググったときに参考にさせてもらったのは↓
[【Visual Studio Code 1.2以降】統合TerminalをコマンドプロンプトからPowerShellに変更する (Windows版)](https://blogs.msdn.microsoft.com/ayatokura/2016/06/10/vscode_terminal_powershell/)

どうやらVSCodeでは統合ターミナルという名前らしい。

## 問題
VSCodeでコードを書いたあとにGolangなどでビルドしたい、runしたいときにVSCode上で完結して欲しい。
どのようにすればいいのか？

## 解決

[表示]->[統合ターミナル]を選択。

…いちいちトラックパッド使うのクソウザイ。
そんなときは↓

```control + shift　+　` ```を実行。

どうでもいいけどMacの```^```マークとかがキーボードのどれに対応しているのかとか全然覚えられんのでホント死んでくれ！って気持ちでいっぱいになる。
CSSだけで作る超軽量アコーディオン開閉「続きを読む」「もっと読む」「more read」（スマホ対応）


![Kobito.mKwpoC.png](https://qiita-image-store.s3.amazonaws.com/0/82372/d009cf91-fa74-e10f-f8dd-18bacc7e5eba.png "Kobito.mKwpoC.png")

* スペースの限られたスマホサイトなどで、見たい人だけに情報を見せることができます。

## デモ
<a href="https://output.jsbin.com/lediyef" target="_blank">jsbin</a>

## html
```html

<div class="accordion-box">
  <input id="ac00" type="checkbox">
  <label for="ac00"></label>
  <div class="accordion-container">
    <h3>タイトル</h3>
	<p>世界中どこを探してもなかったので作りました。</p>
	<p>jsを使っていないのでコンフリクトすることはありません。</p>
	<p>スマホにも対応。iPhone4くらいの小さい画面でも大丈夫です。</p>
	<p>閉じるボタンは要らないときは「.accordion-box input:checked + label」のdisplay:noneを有効にしてください。</p>
  </div><!— accordion-container -->
</div><!— accordion-box -->

```

## css
```css

.accordion-box {
	position: relative;
}
.accordion-box label {
	height: 140px; /* グラデーションの高さ */
	cursor: pointer;
	text-align: center;
	font-size: 12px;
	position: absolute;
	bottom: 0;
	width: 100%;
  
	/* 以下グラデーションは「背景が白」に併せて設定しています */	
	background: -webkit-linear-gradient(top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.95) 90%);
	background: -moz-linear-gradient(top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.95) 90%);
	background: -o-linear-gradient(top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.95) 90%);
	background: -ms-linear-gradient(top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.95) 90%);
	background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.95) 90%);
}
.accordion-box input:checked + label {
	background: inherit; /* 開いた時には背景グラデーションを消す */
}
.accordion-box label:after {
	content: "続きをよむ"; /* ラベルの文字 */
	letter-spacing: .05em;
	line-height: 2.5rem;
	position: absolute;
	bottom: 20px;
	left: 50%;
	-webkit-transform: translate(-50%, 0);
	transform: translate(-50%, 0);
	color: #fff;
	background-color: #000;
	width: 18.75rem;
	-webkit-border-radius: 20px;
	-moz-border-radius: 20px;
	border-radius: 20px;
}
.accordion-box label:before {
	content: "↓";
	font-weight: 700;
	position: absolute;
	bottom: 30px;
	left: 50%;
	-webkit-transform: translate(-140px, 0);
	transform: translate(-140px, 0);
	background-color: #fff;
	z-index: 1;
	-webkit-border-radius: 100%;
	-moz-border-radius: 100%;
	border-radius: 100%;
	width: 20px;
	height: 20px;
	line-height: 20px;
}
.accordion-box input {
	display: none;
}
.accordion-box .accordion-container {
	overflow: hidden;
	height: 200px; /* 開く前に見えている部分の高さ */
    -webkit-transition: all 0.1s;
    -moz-transition: all 0.1s;
    -ms-transition: all 0.1s;
    -o-transition: all 0.1s;
    transition: all 0.1s;
}


.accordion-box input:checked + label {
	/* display: none ; 閉じるボタンは要らないとき */
}
.accordion-box input:checked + label:after {
	content: "閉じる";
}
.accordion-box input:checked + label:before {
	content: "↑";
}
.accordion-box input:checked ~ .accordion-container {
    height: auto;
	padding-bottom: 80px; /* 閉じるボタンのbottomからの位置 */
    -webkit-transition: all 0.1s;
    -moz-transition: all 0.1s;
    -ms-transition: all 0.1s;
    -o-transition: all 0.1s;
    transition: all 0.1s;
}


```


## 関連

こちらも同じ原理で作っています。
[CSSだけで作る超軽量ポップアップモーダルウインドウ（スマホ対応）](http://qiita.com/dangoya/items/4176e8ef22e892570f4e)
Unityで開発するときにフォルダ構成と.gitignoreを作る便利スクリプト

# Unityで開発する時の楽々設定
下記のエントリでUnity開発前に必要な設定項目を説明しているものの、手動で毎回やるのはバカらしいのでスクリプト作りました。

- [Unityフォルダ構成のルールについて](http://qiita.com/takish/items/8608ba9070755da3ae6d)
- [UnityでGit管理するときの設定項目](http://qiita.com/takish/items/08d7281eb1f303985786)

# スクリプト
プロジェクト直下に以下のスクリプトを突っ込んで実行して下さい。
上記のエントリで書いてある作業を実行します。
自動的にフォルダ構成と.gitignoreを生成します。

```init.sh
#!/bin/sh

function init() {
arr=("Scenes" "Prefabs" "Scripts" "Animations" "Materials" "Physics Materials" "Fonts" "Textures" "Audio" "Resources" "Editor" "Plugins")
for var in "${arr[@]}"; do
  #echo $var
  mkdir Assets/"$var"
done

cat << EOT > .gitignore
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/Assets/AssetStoreTools*

# Autogenerated VS/MD solution and project files
ExportedObj/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd


# Unity3D generated meta files
*.pidb.meta

# Unity3D Generated File On Crash Reports
sysinfo.txt

# Builds
*.apk
*.unitypackage
EOT
}

if [ -e Assets ]; then
  echo "Run"
  init
fi
```
<script src="https://gist.github.com/takish/d22e000a02da44b1dc75dc843789edee.js"></script>


# Unity側の設定
以下は手動で設定して下さい。

- [Edit] -> [Project Settings] -> [Editor]を選択
- Inspectorビューを開く
- [Version Control] のModeを [Visible Meta Files] に変更
- [Asset Serialization] のModeを [Force Text] に変更
Docker, MySQL, phpMyAdmin による手軽なデータ可視化

MySQLにたまったデータを使って機械学習チックなことをやろうとしていて、とりあえずデータの構造とか中身をサクッと確認したいなということでやってみた手順を紹介。

MySQLは検証サーバにインストールされていて、ここにあんまり追加のツールをインストールとかしちゃいけないって言われたので、ダンプデータだけもらって手元のMacで可視化することにした。

なお、Dokcer ToolboxでDockerをインストール済みの想定。

まずはmysqldumpでダンプファイル作成。

```
$ mysqldump -uusername -ppassword dbname > dbname.sql
```

続いてMySQLコンテナを起動。

```
$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=password -d -p 3306:3306 mysql
```

データをリストアする。

```
$ mysql -h 192.168.99.100 -uroot -ppassword
mysql> create database dbname;

$ mysql -h 192.168.99.100 -uroot -ppassword dbname < dbname.sql
```

phpMyAdminコンテナを起動する。

```
$ docker run --name phpmyadmin -p 8000:80 --link mysql:db -d phpmyadmin/phpmyadmin
```

あとはブラウザで http://192.168.99.100:8000 にアクセスすればOK。
ユーザ名とパスワードは root/password（MySQLの認証情報なのかな？）

![Kobito.5EaM7K.png](https://qiita-image-store.s3.amazonaws.com/0/81715/0b77dd3e-359a-d9bb-cd74-4221145dc71b.png "Kobito.5EaM7K.png")

Dockerあると何でも簡単。
最新版のGitをインストールする

## 方法１

[公式ページ](https://git-scm.com/)からダウンロードしてインストールする

## 方法２ (Macだけ)

* 1. [Homebrew](http://brew.sh/index_ja.html)をインストール
* 2. brew upgrade git

### 確認

確認して最新だったら完了

```
git --version
git version 2.11.0
```
よく使うAtomショートカットキーまとめ

Atomのキーバインドがなかなか覚えられないので、自分用メモとして作成しています。
随時更新予定です。

# エディタ操作

## カーソル移動
Emacsのキーバインドがベースとなっている。

| キーバインド | 動作 |
|:----|:----|
| `ctrl-A/E` | 行頭・行末 へ移動|
|`ctrl-P/N/B/F` |1文字 上・下・左・右 へ移動|
|`alt-B/F` | 1単語 左・右 へ移動|
|`ctrl-alt-B/F` | サブ単語 左・右 へ移動|
| `ctrl-G` | 行を指定して移動 |  
| `ctrl-M` | 対応する括弧へ移動 | 
| `cmd-↑/↓` | ファイルの 先頭・最後 へ移動|

## 文字列選択(単一選択)
基本的に、カーソル移動のキーバインド＋`shift`で選択可能。

| キーバインド | 動作 |
|:----|:----|
| `ctrl-shift-A/E` | 現在位置から 行頭・行末 まで選択|
|`ctrl-shift-P/N/B/F` |現在位置から1文字 上・下・左・右 まで選択|
|`alt-shift-B/F` | 現在位置から1単語 左・右 まで選択|
| `cmd-shift-↑/↓` | 現在位置からファイルの 先頭・最後 まで選択|
| `ctrl-shift-W` | 現在位置の単語を選択|
| `cmd-A` | 全て選択(All)|
| `cmd-L` | 行選択(Line)|

## 文字列選択(複数選択)
| キーバインド | 動作 |
|:----|:----|
| `cmd-マウスクリック` | 複数列選択|
| `cmd-D` | 選択文字列で検索し、次に現れる同一文字列を選択|
| `cmd-ctrl-G` | 選択文字列で検索し、全ての同一文字列を選択|

## 文字列編集
| キーバインド | 動作 |
|:----|:----|
|`cmd-J` | 行末の改行を削除(Join)|
|`cmd-ctrl-↑/↓` |行を 上・下 に移動|
|`cmd-shift-D` | 一行下に複製(Duplicate)|
| `cmd-K`・`cmd-U` | 大文字に変換(Upper case)|
| `cmd-K`・`cmd-L` | 小文字に変換(Lower case)|
| `ctrl-T` | カーソル前後の文字を入れ替え(Transpose)|

## 文字列削除
| キーバインド | 動作 |
|:----|:----|
| `ctrl-shift-K` | 一行削除|
|`ｃｔｒｌ-H` |一文字前を削除(Backspace)|
|`alt-H/D` |現在位置から 行頭・行末 までを削除|
| `ctrl-K` | 現在位置から行末までを切り取り|

## UnDo・ReDo
| キーバインド | 動作 |
|:----|:----|
| `cmd-Z` | UnDo|
| `cmd-Shift-Z` | ReDo|

## 検索
| キーバインド | 動作 |
|:----|:----|
| `cmd-F` | ファイル内を文字列検索|
|`cmd-shift-F` |プロジェクト内を文字列検索|
|`cmd-T` |プロジェクト内をファイル検索|

## 行折りたたみ
| キーバインド | 動作 |
|:----|:----|
| `alt-cmd-[` |行を折りたたむ|
| `alt-cmd-]` |折りたたんだ行を展開する|

##ペイン
| キーバインド | 動作 |
|:----|:----|
| `cmd-K`・`↑/↓/←/→`|ペインの分割|
| `cmd-K`・`cmd-↑/↓/←/→`|ペインの移動|

## タブ
| キーバインド | 動作 |
|:----|:----|
| `alt-cmd-←/→` |タブの移動|
| `cmd-N` |新しいタブを開く|
| `cmd-W` |タブを閉じる|
| `cmd-shift-T` |最後に閉じたタブを開く|

#参考
- [Atom公式ドキュメント](http://flight-manual.atom.io/)
- [Atom実践入門](http://amzn.to/2iTxRte)  
　<a href="https://www.amazon.co.jp/Atom%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80%E2%94%80%E2%94%80%E9%80%B2%E5%8C%96%E3%81%97%E7%B6%9A%E3%81%91%E3%82%8B%E3%83%8F%E3%83%83%E3%82%AB%E3%83%96%E3%83%AB%E3%81%AA%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF-WEB-DB-PRESS-plus/dp/4774182702/ref=as_li_ss_il?s=books&ie=UTF8&qid=14　　83626572&sr=1-1&keywords=Atom%E5%AE%9F%E8%B7%B5&linkCode=li1&tag=nesheep5-22&linkId=ba93f47fe42961c81290a7f1c74309fe" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4774182702&Format=_SL110_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=nesheep5-22" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=nesheep5-22&l=li1&o=9&a=4774182702" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
TensorFlowのmacでのinstallメモ


### virtualEnv経由でのインストールです

```
$ sudo easy_install pip
$ sudo pip install --upgrade virtualenv
```

下記で、tensorflowディレクトリが作られる
``
virtualenv ~/tensorflow
```

下記でvirtualenvをActivateする。
```
$ cd ~/tensorflow
$ source bin/activate
```

```
$ pip install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.5.0-py2-none-any.whl
Collecting tensorflow==0.5.0 from https://storage.googleapis.com/tensorflow/mac/tensorflow-0.5.0-py2-none-any.whl
  Using cached https://storage.googleapis.com/tensorflow/mac/tensorflow-0.5.0-py2-none-any.whl
Collecting numpy>=1.9.2 (from tensorflow==0.5.0)
  Downloading numpy-1.11.3-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl (4.2MB)
    100% |████████████████████████████████| 4.2MB 263kB/s
Collecting six>=1.10.0 (from tensorflow==0.5.0)
  Downloading six-1.10.0-py2.py3-none-any.whl
Installing collected packages: numpy, six, tensorflow
Successfully installed numpy-1.11.3 six-1.10.0 tensorflow-0.5.0
```

実行pathに移動
```
$ cd ~/tensorflow/tensorflow
```

```sample.py
import tensorflow as tf

def x2_plus_b(x, b):
    _x = tf.constant(x)
    _b = tf.constant(b)
    result = tf.square(_x)
    result = tf.add(result, _b)
    return result

with tf.Session() as sess:
    result = sess.run([x2_plus_b(2., 3.)])
    print result
```

### 動作確認
```
:tensorflow[master]$ python sample.py
can't determine number of CPU cores: assuming 4
I tensorflow/core/common_runtime/local_device.cc:25] Local device intra op parallelism threads: 4
can't determine number of CPU cores: assuming 4
I tensorflow/core/common_runtime/local_session.cc:45] Local session inter op parallelism threads: 4
[7.0]
```
devsimインストール

devsimのインストール方法をメモ。

devsimを以下のコマンドでgitクローンしてくる。

git clone https://github.com/devsim/devsim

その後、INSTALLに記載されている手順に従う。
acmlは以下からダウンロードしてくる。
http://developer.amd.com/tools-and-sdks/archive/compute/amd-core-math-library-acml/acml-archive-downloads/

symdiffは別途、以下からクローンしてくる必要がある。

https://github.com/devsim/symdiff.git

cgnslibのインストールは、INSTALLでは

cmake -DBUILD_CGNSTOOLS=ON -DCMAKE_INSTALL_PREFIX=$PWD/../../cgnslib ..

となっているが、ここではをBUILD_CGNSTOOLSをOFFにして

cmake -DBUILD_CGNSTOOLS=OFF -DCMAKE_INSTALL_PREFIX=$PWD/../../cgnslib ..

とする。ONにするとOpenGLとX関連のヘッダファイルやライブラリが見つからないエラーが出た。必須ではないよう。

あとは特に弊害はなかった。
PHP CS Fixer 2.0がリリースされていた

# PHP CS Fixer 2.0がリリースされていた

composer updateかけた後にcommitしたら怒られて、はてなんじゃらほいと思ったら、今日2.0がリリースされていたようで。

## PHP CS Fixerについて

詳しくは[こちら](http://fivestar.hatenablog.com/entry/2014/12/08/033345)とかで。  

## 1.x -> 2.0 の変更点まとめ

https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/UPGRADE.md


## 刺さった1 .php_csの書き方が変わってた

1.x

```
<?php
$finder = Symfony\CS\Finder\DefaultFinder::create()
    ->exclude('vender')
    ->exclude('server')
    ->exclude('webroot')
    ->in(__DIR__);

return Symfony\CS\Config\Config::create()
    ->level(Symfony\CS\FixerInterface::PSR2_LEVEL)
    ->setUsingCache(true)
    ->finder($finder);
```

2.0

```
<?php
$finder = PhpCsFixer\Finder::create()
    ->exclude('vender')
    ->exclude('server')
    ->exclude('webroot')
    ->in(__DIR__);

return PhpCsFixer\Config::create()
    ->setRules(array(
        '@PSR2' => true,
    ))
    ->setUsingCache(true)
    ->setFinder($finder);
```

```
Symfony\CS\Finder -> PhpCsFixer\Finder  
Symfony\CS\Config -> PhpCsFixer\Config  
```

てな感じでNamespaceが変わっている。
それに合わせてRuleの書き方も変わっているので、ご注意を。
https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/UPGRADE.md#namespace

## 刺さった2 --config-file が --config になっていた

1.x

```
--config-file="/path/to/.php_cs"
```

2.0

```
--config "/path/to/.php_cs"
```

CLIのオプションも結構変わっている。
https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/UPGRADE.md#cli-options
【Python】Microsoft Cognitive ServicesのFace APIを使う

# Microsoft Cognitive Services - Face API
https://www.microsoft.com/cognitive-services/en-us/face-api
画像中に含まれている顔の位置やその人の性別、年齢などを検出することができます。

# Subscription Key
Cognitive ServicesでFace　Preview(無料)のSubscription Keyを入手してください。
Key1とKey2がありますが、Key1のみでいいです。
<img width="1144" alt="key" src="https://qiita-image-store.s3.amazonaws.com/0/123970/c85582f2-d9be-5f42-a14b-892b0a7ce45c.png">

# PythonからAPIを叩く
Versionは2.7です。3でも動くと思います。
予めpipでrequestsをインストールしておきます。

```shell-session
$ pip install requests
```

## 画像ファイル版
``` detect.py
import sys
import requests


url = 'https://api.projectoxford.ai/face/v1.0/detect'
headers = {
    'Content-Type': 'application/octet-stream',
    'Ocp-Apim-Subscription-Key': '[your subscription key]',
}
params = {
    'returnFaceId': 'true',  # The default value is true.
    'returnFaceLandmarks': 'false', # The default value is false.
    'returnFaceAttributes': 'age,gender', # age, gender, headPose, smile, facialHair, and glasses.
}
if __name__ == '__main__':
    argv = sys.argv
    if len(argv) == 1:
        print 'Usage: # python %s [filename]'  % argv[0]
        quit()
    r = requests.post(url ,headers = headers,params = params,data = open(argv[1],'rb'))

    print(r.text)
```

image.pngの顔検出を行いたいときは、以下のように実行します。

```shell-session
$ python detect.py image.png
```

## 画像URL版
画像をURLで指定するときは以下のようにします。

``` detect.py
import sys
import json
import requests


url = 'https://api.projectoxford.ai/face/v1.0/detect'
image_url = 'http://example.com/image.png'
headers = {
    'Content-Type': 'application/json',
    'Ocp-Apim-Subscription-Key': '[your subscription key]',
}
params = {
    'returnFaceId': 'true',  # The default value is true.
    'returnFaceLandmarks': 'false', # The default value is false.
    'returnFaceAttributes': 'age, gender', # age, gender, headPose, smile, facialHair, and glasses.
}

payload = {
    'url': image_url,
}

if __name__ == '__main__':
    r = requests.post(url ,headers = headers, params = params, data = json.dumps(payload))

    print(r.text)
```

image_urlの顔検出を行いたいときは、以下のように実行します。

```shell-session
$ python detect.py
```

## 出力結果
```
[
    {
        "faceId": "xxxxxxxxxxxxxxxxxxxxxxxx",
        "faceRectangle": {
            "top": 119,
            "left": 177,
            "width": 144,
            "height": 144
        },
        "faceAttributes": {
            "gender": "female",
            "age": 17.9
        }
    }
]
```

Jsonで結果が返ってきていることがわかります。
paramsを変更することで顔の部位の位置情報なども取得することができるようになります。
OpenCmsをデバッグ    


gitからソースを持ってくる

```shell-session
git clone https://github.com/alkacon/opencms-core.git
```

イクリプスをインストール
Eclipse IDE for Java Developers
gitで落としてきたソースをGradleとしてインポート

warを作る

```shell-session
gradle war
```

warがここに出来ている
..\BuildCms\distributions\opencms.war

Tomcatをダウンロードする
tomcatのwabappsフォルダーにwarを置く

コマンドプロンプトを立ち上げる

パスを調整する
例）

```bat
set CATALINA_BASE=C:\server\apache-tomcat-8.5.9
set CATALINA_HOME=C:\server\apache-tomcat-8.5.9
set CATALINA_TMPDIR=C:\server\apache-tomcat-8.5.9\temp
set CLASSPATH=C:\server\apache-tomcat-8.5.9\bin\bootstrap.jar;C:\server\apache-tomcat-8.5.9\bin\tomcat-juli.jar
```

jpdaでtomcatを起動

```bat
C:\server\apache-tomcat-8.5.9\bin>catalina.bat jpda start
```

以下のURLにアクセス
http://localhost:8080/opencms/setup/

ウィザードに従ってすすめる
終わったら、以下のURLにアクセス
http://localhost:8080/opencms/opencms/system/login/

user:Admin pass:adminでログイン


イクリプスの設定
Run->Run Configurations...->Remote Java Applicatior
Debugをクリック

これでデバッグ出来ます
Google Chrome 拡張機能の開発シリーズ一覧

# はじめに
シリーズ化しているつもりの記事の一覧です。
こんなことしなくても、ほかに表示方法ありますかね？？

- [Google Chrome の 拡張機能にまったく目を向けてこなかった - Qiita](http://qiita.com/rrryutaro/items/8edb7ae829bae9466e50)
- [Google Chrome 拡張機能の開発 - 1 - はじめのいっぽ - Qiita](http://qiita.com/rrryutaro/items/bcfc0e593914e8ba0a9a#_reference-3bf2614c502705f1a84c)
- [Google Chrome 拡張機能の開発 - 2 - 早速自作したものに機能追加していく - Qiita](http://qiita.com/rrryutaro/items/194bc78ad73a29daef5f)
- [Google Chrome 拡張機能の開発 - 3 - 保存できるようにする - Qiita](http://qiita.com/rrryutaro/items/4b996b4594e3fafcc77d)
- [Google Chrome 拡張機能の開発 - 4 - マウスカーソルにある位置のものをコピー - Qiita](http://qiita.com/rrryutaro/items/f4f129dacdf22ce43d14)
- [Google Chrome 拡張機能の開発 - 5 - コピーした履歴をわかるようにする - Qiita](http://qiita.com/rrryutaro/items/530d5a50dec8436ebb5c)
- [Google Chrome 拡張機能の開発 - 6 - クリップボード履歴を一応それらしく使えるようにする - Qiita](http://qiita.com/rrryutaro/items/990923b40c62a4caba4c)
- [Google Chrome 拡張機能の開発 - 7 - これまでの内容を整理 - Qiita](http://qiita.com/rrryutaro/items/93769ebcb35962821098)
- [Google Chrome 拡張機能の開発 - 8 - (2017年12月)1年ぶりなのでもう一度はじめの一歩 - Qiita](https://qiita.com/rrryutaro/items/e6b98a0354d67c481a93)
- [Google Chrome 拡張機能の開発 - 9 - ページの閲覧を便利にする（アンカー追加、折りたたみ） - Qiita](https://qiita.com/rrryutaro/items/c94d88785205fc929497)

他

- [【随時更新】入れているChrome拡張機能の一覧 - Qiita](https://qiita.com/rrryutaro/items/fb2825e8be092c61480c)
- [Chrome拡張機能開発 覚書 - Qiita](https://qiita.com/rrryutaro/items/3c1ec7e7ed24c97717da)


以上