OmniAICreator/Qiita-1.07M huggingface dataset:
chatworkの履歴をcsvにする

さよならchatworkという方針が仲間たちの意向で決まったので
chatworkのマイチャットのダウンロードを以下の方法で実施しました。
ツール作成してくれたかたに感謝。

・dockerが入ってるホストにログインしsudo su -
・以下のgitリポジトリをcloneしてdocker buildしてrunした

```
git clone https://github.com/kheiakiyama/goodbye-chatwork-web.git
cd goodbye-chatwork-web/
docker build .
docker images
docker tag 7dafa379320b goodby-chatwork:latest
docker run -d --name goodby-chatwork goodby-chatwork:latest
docker ps
```
・コンテナにログイン

```
#  docker exec -i -t adbee5b39e60 bash
```
・goodbychatworkで自分が所属する部屋のIDを取得し、マイチャットをcsvにはく

```
# goodbye_chatwork -i myuser＠mydomain -p <パスワード>
2018-10-05T02:02:41+00:00 login as myuser＠mydomain ...
2018-10-05T02:02:41+00:00 load initial data...
3019503 mychat 594
～略～
# goodbye_chatwork -i myuser＠mydomain -p <パスワード> -e 3019503
2018-10-05T02:34:35+00:00 login as myuser＠mydomain ...
2018-10-05T02:34:35+00:00 load initial data...
2018-10-05T02:34:36+00:00 mkdir chatwork_logs
2018-10-05T02:34:36+00:00 export logs 3019503 ...
2018-10-05T02:34:36+00:00 get old chat 0- ...
2018-10-05T02:34:38+00:00 get old chat 1099627917400342528- ...
～略～
2018-10-05T02:47:04+00:00 get old chat 93909861- ...
2018-10-05T02:47:06+00:00 create chatwork_logs/3019503_mychat.csv
```
・別窓でホストからファイルをコピー

```
# docker cp adbee5b39e60:/usr/src/app/chatwork_logs/3019503_mychat.csv .
```
コピーしたファイルをコンテナから消してログアウト

```
rm chatwork_logs/3019503_mychat.csv
ls -lh chatwork_logs/        
```
さらにwinscpかなにかでローカルにダウンロードしてホスト側のファイルも消しとく
中身のログは厳密に時系列ではないようでした。（最近のもちゃんとあった）

ホストとコンテナにログインすれば他のかたもツールを使えるので共用のサーバに入れとくといいかも。
ローカルに落とすのがめんどくさくてローカルにdocker入ってればcloneしてビルドするとこからでいいけどマシンリソースを食うかもと思います。
マイチャット一括削除は無理っぽかったです。（パスや個人情報っぽいのだけ検索で消しました。
マイチャットは自分の作業メモみたいな感じで使ってたのですが、次Teamsなので一人チーム作って＋ボタンでPlannerでカンバンぽいタスク管理とかwiki書いたりなどできるっぽいのでたぶん便利そうかな。
Teamsでwebhookをgitlabと連携さすのとかもChatwork比較だとびっくりするほど簡単でした。
https://qiita.com/tsgkdt/items/e1148fd2f5960500d7d9

もしWindowsでVirtualboxとかの影響でHyper-vを無効にしてる場合は以下の感じで切り替えられるようです
https://qiita.com/centipede/items/8891a8f033fe2ac788b9  

Hyper-v有効化したい(Dockerつかいたい)場合

```
#管理者権限でコマンドプロンプトを開いて以下を実行しOS再起動する
> bcdedit 
> bcdedit /set hypervisorlaunchtype auto
> bcdedit
#hypervisorlaunchtype    Autoであることを確認
#OS再起動
```

Hyper-v無効化したい(Vagrantつかいたい)場合

```
> bcdedit /set hypervisorlaunchtype off
> bcdedit 
#hypervisorlaunchtype    Noneであることを確認
#OS再起動
```
Dockerはもううええわふつうにruby入れてgemインストールしてつかうよって人はrbenvとかでruby2.4入れてgemで入れられるっぽいです。

参考
https://qiita.com/hirokishirai/items/29bfdfc6d61b911aacc1
https://github.com/kheiakiyama/goodbye-chatwork-web
https://qiita.com/centipede/items/8891a8f033fe2ac788b9
毎回やってるオレ流 Git 設定

自分のコピペ用です。<font color="Gainsboro">（マシン（環境）が変わるごとに毎回調べたり打ち込んだりしているのが面倒なので）</font>
Gitをコマンドで操作している方、且つ「特に何も設定してないよー」って方は同じ様に設定してみてください。結構楽になります。

動作環境： Mac ターミナル（WebStorm上）・標準搭載のGit

# 事前確認・準備
１：
ホームディレクトリに`.bash_profile`と`.bashrc`がなければ作成しておく

``` bash
# ホームディレクトリに移動
$ cd

# `.bash`で始まるファイルを確認
$ ls -a | grep ^.bash
```

２：
`.bashrc`が起動時に読み込まれる様に`.bash_profile`に以下コードを追加しておく
（vimか好みのエディタで編集する）

``` bash
source ~/.bashrc
```

※`.bash_profile`と`.bashrc`が気になる方は　→　[.bash_profileと.bashrcについて](https://qiita.com/shyamahira/items/260862743e4c9794b5d2)

# 常時ブランチ名表示

![スクリーンショット 2018-10-05 13.04.30.png](https://qiita-image-store.s3.amazonaws.com/0/100188/ad0c3e83-d457-d65a-b92b-13306968798d.png)


ホームディレクトリで操作する

１：
`git-prompt.sh`作成

``` bash
# ファイル作成
$ touch git-prompt.sh
```

作成したファイルに [git-prompt.sh](https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh) をコピペ

２：
`git-completion.bash`作成

``` bash
# ファイル作成
$ touch git-completion.bash
```

作成したファイルに [git-completion.bash](https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash) をコピペ

３：
上ファイルを読み込むように`.bashrc`を編集

``` bash
source ~/git-prompt.sh
source ~/git-completion.bash
GIT_PS1_SHOWDIRTYSTATE=true
export PS1='\[\033[32m\]\u@\h\[\033[00m\]:\[\033[34m\]\w\[\033[31m\]$(__git_ps1)\[\033[00m\]\$ '
```

４：
再読み込み

``` bash
$ source .bashrc
```

---

参考： 
- [bashでgitのブランチ名を表示](https://qiita.com/tanishi/items/2adb71024d675bc43177)
- [MacのターミナルでGitのブランチ名を表示する](http://blog.ruedap.com/2011/07/06/mac-terminal-git-branch-name)

# Gitコマンドエイリアス作成

![スクリーンショット 2018-10-05 13.06.14.png](https://qiita-image-store.s3.amazonaws.com/0/100188/685b2581-aa27-b6b8-478c-548eaefd550d.png)

１：
`.bashrc`に任意のエイリアスを追加

``` bash
alias gs='git status'
alias gb='git branch'
alias gc='git checkout'
alias gl='git log'
alias gps='git push origin'
alias gpl='git pull origin'
```

２：
再読み込み

``` bash
$ source .bashrc
```

---

参考：
- [【Mac】ターミナルで使うコマンドのエイリアスを設定する](https://qiita.com/YusukeHigaki/items/67a17995c8a4e1329d11)

--- 

毎回やってるなーって思ったものがあったら追記していきます。
[Python入門~ライブラリ] サンプルコードでimportの使い方を学ぶ


# 開発環境
- Python3.6.6
- Pycharm
- Linux Mint 19

# Pythonの基本的なコードを読みたい!
。。。であれば、Pythonクイズサイト[Finxter.com](https://app.finxter.com/learn/computer/science/)がおすすめです。本記事は、このサイトからPythonの基礎知識と着想を得て書いています:books:

サンプルコードは[GitHub](https://github.com/Yukiya025/20181004LibraryNamespace)で公開しているので、これらのコードを参照しながら本記事をお楽しみください:sparkles:

# 各コードの説明から見る`import`のさまざまな書き方

- main.py

一番の基本となる。`import wordifier`は、このコード内で使われていないと認識される。
理由は`import [ライブラリ名]`という形でライブラリをインポートするときは、その後`[ライブラリ名].[関数名]`とするから。

- main1.py

「ではそのdir()の中には何が?」と疑問に思った人のためのファイル。同じファイル(main1.py)で定義された`add_yes(word)`関数がdir()に入っていることがわかる。

- main2.py

このファイルでやっと`import wordifier`が認識される書き方を紹介。`import wordifier`の後に`print(wordifier.verb(word))`と書く。

- main3.py

`from wordifier import verb`と書くと、`wordifier.verb(word)`という書き方ではなく、直接`verb(word)`と書くだけでよい。

- main4.py

このコード (`from wordifier import *`) もmain3.pyと同じく`wordifier.verb(word)`という書き方ではなく、直接`verb(word)`と書くだけでよい。

- wordifier.py

mainファイルにインポートするために用意したライブラリ。

# `dir()`とは
引数がない場合、現在のローカルスコープにある名前のリストを返す。
参考サイト: [Python3.6.5ドキュメント](https://docs.python.jp/3/library/functions.html#dir)
PINRemoteImageでキャッシュされているイメージを消す


こんな感じに画像を読み込んで。。

```
let u=imageurl
view.imageview.pin_setImage(from: URL(string: u)!, processorKey: "rounded") { (result, unsafePointer) -> UIImage? in
.
.
```

URL指定でキャッシュを消す時はprocessorKey指定と未指定でなぜか二回キャッシュクリア。。

```
let u=imageurl
PINRemoteImageManager.shared().cache.removeObject(forKey: u)
let u2=PINRemoteImageManager.shared().cacheKey(for: URL(string:u)!, processorKey: "rounded")
PINRemoteImageManager.shared().cache.removeObject(forKey: u2)
```

どこにも書いてなかったので、面倒だけどソース見た。
もっと良い方法がありそうだけど。。
[Azure] ポータルの検索機能についての小ネタ

Azureポータルの「すべてのサービス」には検索機能がありますが、サービス名が日本語表記だったり、英語表記だったり、ローカライズのタイミングで日英が入れ替わったり、目的のサービスを少し見つけづらい部分があります。

本日(2018/10/05)時点で271サービス、スクロールバーも大分短くなりました・・・

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/3ade92e5-2517-723d-9924-1db38fbb91b3.png)|
|:-:|

検索については、意外な方法で検索できます。AWSのサービス名を入れてみると・・・

S3 : 

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/f1ee1a3e-43ce-c3e5-a623-ded20a37824e.png)|
|:-:|

Glacier : 

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/d7b38320-07ae-9aee-1fbd-2ee40f4515b6.png)|
|:-:|

Cloud Watch : 

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/4b552841-4bb7-9876-7f9f-7d7a8798fa3f.png)|
|:-:|

Cloud Formation : 

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/c054f177-e5f6-c0d1-e44a-6a32f28502fd.png)|
|:-:|

Dynamo DB : 

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/6cffcbeb-087e-8bff-a7e2-20de33b84e83.png)|
|:-:|

Redshift : 

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/70d9177c-0c01-96e6-3115-52d630635404.png)|
|:-:|

Elastic Beanstalk : 

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/172826/c1c116b8-c88f-d750-5667-049c4bbdc106.png)|
|:-:|

最近はaws対抗の話もあまり出てこなくなりましたが、意識している様子は伺えますね。サービスが多くて迷った場合は、同じ用途のAWSサービス名を入れてみてもいいかもしれません。
mac os Mojave にアップグレードしたら bundle install が失敗する事象を解決した

# 環境
- MacBook Pro (Retina, 13-inch, Mid 2014)
- MacOS mojave(10.14)
- ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-darwin14]
- rails 4.2.1

## 状況
Railsで動いているプロジェクトをMacにインストールしていたが、Mojaveにアップデートした途端、`bundle install`が動かないことに...

## bundle installで出てきたエラー
    Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    /Users/kabushikikaisharijobu/.rbenv/versions/2.2.1/bin/ruby -r ./siteconf20181005-1426-8xywg0.rb extconf.rb
    checking for ffi.h... no
    checking for ffi.h in /usr/local/include,/usr/include/ffi... no
    checking for rb_thread_blocking_region()... no
    checking for rb_thread_call_with_gvl()... yes
    checking for rb_thread_call_without_gvl()... yes
    checking for ffi_prep_cif_var()... no
    creating extconf.h
    creating Makefile
    
    make "DESTDIR=" clean
    
    make "DESTDIR="
    
    (中略)
    
    make: *** ["/Users/kabushikikaisharijobu/rejob-v2/vendor/bundle/ruby/2.2.0/gems/ffi-1.9.10/ext/ffi_c"/libffi-x86_64/.libs/libffi_convenience.a] Error 2
    
    make failed, exit code 2
    
    Gem files will remain installed in /Users/kabushikikaisharijobu/rejob-v2/vendor/bundle/ruby/2.2.0/gems/ffi-1.9.10 for inspection.
    Results logged to /Users/kabushikikaisharijobu/rejob-v2/vendor/bundle/ruby/2.2.0/extensions/x86_64-darwin-14/2.2.0-static/ffi-1.9.10/gem_make.out
    
    An error occurred while installing ffi (1.9.10), and Bundler cannot continue.
    Make sure that `gem install ffi -v '1.9.10' --source 'https://rubygems.org/'` succeeds before bundling.
    
    In Gemfile:
      webdriver-user-agent was resolved to 7.4, which depends on
        selenium-webdriver was resolved to 3.1.0, which depends on
          childprocess was resolved to 0.6.1, which depends on
            ffi

## 対応法
```sh:command-line
open /Library/Developer/CommandLineTools/Packages/
```
上記、openコマンドにより、command-line-toolのパッケージフォルダを開く。
その後、`macOS_SDK_headers_for_macOS_10.14.pkg`が存在するので、クリックしてインストール。

参照元:
https://blog.driftingruby.com/updated-to-mojave/

#### その後、`bundle install`を実行。 無事、完了した。
macOS Mojave の起動可能なインストーラを作成する

macOS の起動可能なインストーラを作成する
https://support.apple.com/ja-jp/HT201372

上記ページにMavericks〜High Sierraの手順例は書いてあるがMojaveのものはない。
試しに.appのファイル名だけ書き換えれたところHigh Sierraなどと同様に起動可能なインストーラが作成ができた。

```
$ sudo /Applications/Install\ macOS\ Mojave.app/Contents/Resources/createinstallmedia --volume /Volumes/MyVolume --applicationpath /Applications/Install\ macOS\ Mojave.app
```
fastlane match で既存の証明書とプロファイルを使用する

- 既存のプロジェクトに fastlane で CD 環境を構築したい
- 証明書とプロファイルの管理は match を使いたい
- 既存の証明書とプロファイルを使いたいけど公式ドキュメントには新規作成しか載っていない

ということで既存の証明書とプロファイルを match で管理する方法をまとめました
諸々の環境構築は既にされている前提です

## 手順
証明書だけ既存のものを使いたい場合はプロファイルに関する手順をスキップ
#### 1. 必要なファイルを用意する
- キーチェーンアクセスを起動して管理したい証明書(.cer)と秘密鍵(.p12)をそれぞれエクスポートする
 - ファイル名は証明書 ID にする
   - 証明書 ID は Developer Console から該当証明書の `Download` ボタンにカーソルを当てた際に表示される URL の `certificateId=xxxx` の xxxx の部分
- Developer コンソールから管理したいプロファイルをダウンロードする
 - プロファイルの用途に合わせてファイル名をつける

|用途|ファイル名|
|:--:|:--|
|Development|Development_{AppID}.mobileprovision|
|App Store|AppStore_{AppID}.mobileprovision|
|Ad Hoc|AdHoc_{AppID}.mobileprovision|
|In House|InHouse_{AppID}.mobileprovision|

#### 2. match のリポジトリをクローンする

```terminal:ターミナルでRubyシェルを起動
> irb
```
```terminal:matchコマンドを使えるようにする
irb(main):xxx:x> require 'match'
```
```terminal:matchで証明書を管理するgitリポジトリのURLを設定
irb(main):xxx:0> git_url = 'match 用リポジトリの URL'
```
```terminal:shallow_cloneしない
irb(main):xxx:0> shallow_clone = false
```
```terminal:decrypt用パスワードの指定
irb(main):xxx:0> manual_password = 'パスワード'  // match コマンドで使用するパスワード
```
```terminal:リポジトリをクローン
irb(main):xxx:0> workspace = Match::GitHelper.clone(git_url, shallow_clone, manual_password: manual_password)

[xx:xx:xx]: Cloning remote git repo...
[xx:xx:xx]: 🔓  Successfully decrypted certificates repo
=> "クローン先のパスが表示される"
```

#### 3. エクスポートした証明書とプロファイルを配置する
- 用途にあった場所に証明書とプロファイルを配置する
 - フォルダが無い場合は下の構造を参照して作る
 - 不要なフォルダはわざわざ作る必要は無い
- match リポジトリの構造

```
├── certs
│   ├── development    // Development 用証明書のフォルダ
│   ├── distribution   // Production 用証明書のフォルダ
│   └── enterprise     // Production 用証明書のフォルダ (Enterprise Program）
├── profiles
│   ├── adhoc          // Ad Hoc 用プロファイルのフォルダ
│   │   └── AdHoc_{AppID}.mobileprovision
│   ├── appstore       // App Store 用プロファイルのフォルダ
│   │   └── AppStore_{AppID}.mobileprovision
│   ├── development    // Development 用プロファイルのフォルダ
│   │   └── Development_{AppID}.mobileprovision
│   └── enterprise     // In House 用プロファイルのフォルダ (Enterprise Program）
│   │   └── InHouse_{AppID}.mobileprovision
├── README.md
└── match_version.txt
```

#### 4. 証明書とプロファイルを Push する
```terminal:pushする
irb(main):xxx:0> Match::GitHelper.commit_changes(workspace, "任意のコメント", git_url)
```

<br>
以上

### 参考
- [Using fastlane match with existing certificates without revoking them](https://medium.com/@jonathancardoso/using-fastlane-match-with-existing-certificates-without-revoking-them-a325be69dac6)
「いや、これはもう改修じゃなくて一から作り直しましょう」「は？」

どうも経営陣の皆様方には、僕らが今までの資産を活用せずに無駄なリソースを食いつぶす無能に見えているらしい。
まあ、言いたいことは大体わかるよ。大方、

> 「今ある機能を流用して、登録するデータと通知の内容をちょっと変えれば済む話じゃないのか！」

とか、そんなところなんじゃないか。元技術者的な、中途半端にその辺の理解がある人だとたまに口うるさいよね。

わかる。わかるよ。僕だって、できることならそうしたい。
というか、プロジェクトの引継ぎと新機能の実装を伝えられたその時は僕も全くおんなじプランだったんだ。

**流用しようと思っていた機能の内部実装を見るまでは。**

## こいつを崩さずに直せだと？？？

ジェンガを思い浮かべてほしい。
実によくある、3本のブロックを縦横交互に積み重ねていく、あのジェンガだ。

仕様書にはこうある。「ブロックの素材は木製とする」「縦横交互に3ピースずつ積む」「計100段積む」etc。
君はその仕様書に則って、大きさｎミリの木製ブロックを発注し、ズレの無いように丁寧にブロックを積み……。
途中手元が狂って崩したりしながらも、君は何とか100段積み上げた。 **やったぞ、完成だ！** 早速部長に見せに行こう。

> 部長「なんか違うな。3ピース並べたうちの真ん中だけ赤いプラスチックのブロックにするとかどうよ？」
> 部長「そうだ！縦横だけじゃなくて、斜めに積んでいくのも面白いんじゃないか！？縦・斜め・横・斜め！これで行こう！！！」
> 部長「あと100だとちょっと足りないな。やっぱり200段にしよう。」
> 部長「よし、この3点の修正を今週中に頼むよ」
> 部長「ああ、もちろん一からやり直せとは言わないよ。こいつの形を保ったまま、ちょっとずつ直してくれればいいさ」

**やってられるか！！！！！！！！！！！！！！！**

どうも部長は今あるものを直すだけだから最初から組むより楽などと思っているようだが、とんでもない。
真ん中のブロックだけ抜き取って赤いプラスチック製のものに置き換え、
縦・斜め・横・斜め・縦……の順番でブロックを直し、
さらに追加で100段も増やすのを、
**崩さないように** 細心の注意を払いながらだなんて、多分気が狂うどころの話じゃないだろう。

そういうことなんだよ。
僕らが一からシステムを作り直そうとするのは、 **今あるものを崩さないようにの部分が一番しんどいから** なんだ。

ちなみに今回の流用予定だった機能の場合、ありとあらゆる情報をグローバル変数に突っ込んで管理しているみたいだった。
もう何べんも読み返したけど、処理の全貌がいまだにつかめない。
しかも変にグローバル変数を使いまわしているせいで変数名と値の内容が矛盾しまくってたりするのが読む側としては最高に憎たらしい。
この全く理解の及ばぬブラックボックスをそのままパクる勇気は僕にはない。
ここまでくるとバグが見つかってないのが異常なレベル。ってかこれ、書いた本人ももうわかんないだろ、絶対。

## そんなこと言ったって、この業界じゃよくあることだろ？⇒その通り

実に、実によくあることだ。最初に上がった要求がプロジェクトの終わりまで増えも減りも変わりもしないなんてことは絶対にないし、
プロジェクトの面倒を見る人が最初から最後まで一貫しているということもない。
そして引き継いだソースコードが新しい家主となった君を暖かく出迎えてくれるという保証も、ない。

じゃあ一体どうすればいいんだろう？？？
僕らにできることは多くない。すでに手遅れとなったスパゲッティコードに立ち向かうのは並大抵の苦労では済まない。そのまま心が折れてしまうことだってざらだ。
だから、せめてこれだけは心がけよう。これ以上の犠牲者を増やさないために、 **常日頃から変更が容易な、他人がすんなり理解できるコードを書くんだ。**
そのための設計やら開発やらの手法だなんだっていうのは、探せばいくらでも出てくる。
その中のどれが最適かまでは残念ながら僕にもわからないが、その手の手法がいくらでも出てくるということは **その数だけ先人の墓標が立ってるってことだ。**

君も、君の後を続く後輩や部下たちも、そうなりたくはないだろう？
　　
　　
　　
　　
※追伸　このお話は7割ぐらいフィクションです。
Netlify のデプロイにおける注意点

静的サイトホスティングサービスのNetlifyをテスト環境として使うときに注意したほうがいいこととか。

## netlify.toml はGUIの設定内容より優先される
netlify の GUI で環境変数を設定しても、デプロイしたプロジェクトに netlify.toml が入っていたらそちらが優先される。

## GUIではBranch ごとに環境変数をかえることはできない
なので、netlify.tomlを使うしかない。
netlify.tomlについてはこちら https://www.netlify.com/docs/netlify-toml-reference/

## Settings > Build&deploy > Deploy settings > Branch deploys を Allにしないとブランチごとのデプロイができない
![Screen Shot 2018-10-05 at 12.38.05.png](https://qiita-image-store.s3.amazonaws.com/0/109241/444f43a6-ec84-ff8b-a6b9-7c70cc8abe52.png)
Ad Exchange/Data Exchangeについて

![image.png](https://qiita-image-store.s3.amazonaws.com/0/257568/19729221-05f3-fb01-3311-f77b89616b2c.png)


DSP/RTBオーディエンスターゲティング入門を読んだまとめ。
DSP/RTBだけといわず広告システムについて体系的に記されていたので小分け。
アドエクスチェンジ(Ad Exchange)とデータエクスチェンジ(Data Exchange)について。

##総論
「枠」から「人」への大きなパラダイムシフトを理解する

## Ad Exchangeとは
- メディア枠・クリエイティブ在庫取引市場
- アドネットワークを束ねているもの。
- アドネットワーク自体が複数のメディアと広告主を束ねたシステムであるが、それを更に複数束ねているシステム。
- 複数束ねることによってアドネットワーク同士で空いているメディア枠を融通できるようになる。
- 複数束ねることによってメディアが一律価格(アドネットワーク単体の場合)ではなく、需要と供給に伴い、1インプレッションごとに価格が変動する。

つまりRTBの機能によって、**価値化したメディア枠・クリエイティブ在庫**を量産できるようになり、その**価値度合が高まった分だけ取引の全体量が増えたことでアドエクスチェンジの存在意義が出てきた**ということになる。

## Data Exchangeとは
- ターゲットデータ取引市場
- ターゲットデータに含まれるもの
  - デモグラフィックデータ
  - ソーシャルグラフデータ
  - 行動ターゲティングデータ
  - 広告クリックデータ  

など

広告主がDSPに効果の高いクリエイティブを入稿するために、DMPなどを活用するようになり、より良いデータ(オーディエンス)の必要性が生まれる。配信時にデータを分析できるようになり、その分析したデータも更にマーケティングの分析用としての価値が生まれる事になり、新たなデータエクスチェンジというプレイヤー(システム)も登場することになる。


そしてこのように**それぞれのシステムが価値となり得るデータを産み出しつつも必要とする関係性**から、**自前の機能としてもつ範囲が事業者単位でかなりバリエーションがあって重複する。**これが、カオスと言われる背景にある


## 書籍情報
横山 隆治, 菅原 健一, 楳田 良輝　DSP/RTBオーディエンスターゲティング入門
https://amzn.to/2xUJEQ5

## 雑感
本ではアドエクスチェンジにはDSPの機能が付いているものがあると書いてある。
また、実際に提供しているサービスをみれば「○○という機能を付けられる。」のようなカスタマイズ性もある事が多いので一言で表現するのは難しい。仮に一言で表現するとかなり広義になり、それだけ聞いても漠然としてしまうので結局補足が必要になる
【PHP】array_searchとarray_keysの速度比較

#array_searchとarray_keysの速度比較
* 速度比較には https://paiza.io/ を使用
* 繰り返し回数は1000回
* for文は含まず、処理にかかる時間を計算

## 単純に比較

```
<?php
// 処理を繰り返すための関数
$repeatTestFunc = function ($func, $limit) {
    $time = 0;
    for ($i = 0; $i < $limit; $i++) {
        $start = microtime(true);
        $func();
        $time +=  (microtime(true) - $start);
    }
    return $time;
};

// 平均時間を取得するための関数
$averageTimeFunc = function ($processTime, $limit) {
    return ($processTime / $limit);
};


$array = ['red', 'blue', 'green', 'white', 'black'];

$func1 = function () use ($array) {
    $key = array_search('red', $array);
};

$func2 = function () use ($array) {
    $keyArr = array_keys($array, 'red');
};

$limit = 1000;

$t1 = $repeatTestFunc($func1, $limit);
$t2 = $repeatTestFunc($func2, $limit);

var_dump('array_search:' . $t1);
var_dump('array_keys:' . $t2);
?>

```

結果

```
string(32) "array_search:0.00043582916259766"
string(30) "array_keys:0.00046944618225098"
```

## 返り値を同じ条件にするため、array_keysの返り値の1つ目の要素を代入する想定で検証

```
<?php
// 処理を繰り返すための関数
$repeatTestFunc = function ($func, $limit) {
    $time = 0;
    for ($i = 0; $i < $limit; $i++) {
        $start = microtime(true);
        $func();
        $time +=  (microtime(true) - $start);
    }
    return $time;
};

// 平均時間を取得するための関数
$averageTimeFunc = function ($processTime, $limit) {
    return ($processTime / $limit);
};


$array = ['red', 'blue', 'green', 'white', 'black'];

$func1 = function () use ($array) {
    $key = array_search('red', $array);
};

$func2 = function () use ($array) {
    $keyArr = array_keys($array, 'red');
    $key = $keyArr[0];
};

$limit = 1000;

$t1 = $repeatTestFunc($func1, $limit);
$t2 = $repeatTestFunc($func2, $limit);

var_dump('array_search:' . $t1);
var_dump('array_keys:' . $t2);
?>

```

結果

```
string(32) "array_search:0.00042223930358887"
string(24) "array_keys:0.00048828125"
```
Atomで重いファイルを開いてしまったときに、起動強制終了ループから脱する方法

## できごと
ふいに、Atom上でクソ重いファイルを開いてしまい、


```
Editor is not responding
```

となり、強制終了させるしかなくなった。

でもAtomを強制終了させて、新たに起動させようとすると、前回開いていたファイルを開こうとするので、またクソ重ファイルを読み込もうとしてしまい、強制終了のループに陥った。


## 解決方法
atomのあるフォルダで、

```
atom --clear-window-state
```

で実行すると、まっさらな状態のAtomが立ち上がる。これでループは脱せた。

前回の状態が保存されるのは便利っちゃ便利だが、消すのをサボっているとタブが無限に増えてうざいので、ctrl + ,でsettingを開いて、

Restore Previous Windows On Start

の項目をnoにしておく。

![atom_setting.png](https://qiita-image-store.s3.amazonaws.com/0/250105/d53270c1-ab5d-dffd-fc31-198c3c6d07ef.png)

これで、強制終了ループしなくなる。
VisualStudioCode＋JavaScriptでクラス構文を使おうとしたらエラーが出た件

オブジェクト指向言語ばかり使ってきた人間がJavaScriptを10数年ぶりに触ることなりました。

あれクラスが使えない…？？
prototype構文はよくわかんない（覚えるのがめんどくさい）のでどうしたらいいのか調べたところ、「ES6からClass構文が使える」とのこと。うれしい。

VisualStudioCodeで、[こちらの記事](https://html5experts.jp/takazudo/17355/)を参考にCatクラスを作ってみる。

実行した。
エラーが出た。＿|￣|○
![image.png](https://qiita-image-store.s3.amazonaws.com/0/249926/6d70d093-2ae8-db02-417f-c4a25b723fd8.png)

Node.jsってなに？というレベルですが、とりあえず新しいバージョンにすればよいのかな。
[こちらの記事](https://qiita.com/basictomonokai/items/f9b0c1e7a8d8d175bf09)を参考にさせて頂き、最新版のインストーラーを持ってきました。

インストーラーを実行。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/249926/d2649bc3-ca87-1583-53e3-8338299feaf7.png)

無事完了。バージョンが上がったようです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/249926/a144ffb5-7c89-29ef-ec87-20466ef73e4a.png)

StartDebug（F5)してみたら
![image.png](https://qiita-image-store.s3.amazonaws.com/0/249926/0fbb63c4-7655-0165-9c1e-f9d1b769f208.png)

動きました。
【個人的備忘録】Eclipseによる　javafxのボタンの配置　コントロール　オブジェクトの生成

```
◎実行環境
・windows7
・Eclipse4.6 Neon
◎コード
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;


public class Main extends Application {
	public void start(Stage stage){
		stage.setWidth(500);　　//横幅を500に指定
		stage.setHeight(300);　　//高さを300に指定


		Button button1 = new Button("1");　　//ボタンコントロールを6つ生成
		Button button2 = new Button("2");
		Button button3 = new Button("3");
		Button button4 = new Button("4");
		Button button5 = new Button("5");
		Button button6 = new Button("6");


		button1.setPrefSize(300,100);　　//横幅を300, 高さを100に指定
		button2.setPrefSize(300,100);
		button3.setPrefSize(300,100);
		button4.setPrefSize(300,100);
		button5.setPrefSize(100,50);　　//横幅を100, 高さを50に指定
		button6.setPrefSize(100,50);

		GridPane subPane = new GridPane();　　　//GridPaneオブジェクトを生成
		subPane.setConstraints(button4,0,0);　　//0,0の位置に配置指定
		subPane.setConstraints(button5,1,0);　　//1,0の位置に配置指定
		subPane.setConstraints(button6,1,1);　　//1,1の位置に配置指定


		subPane.getChildren().addAll(button4,button5,button6);
　　　　　　
　　　　　//4,5,6をsubPaneに追加

		GridPane root = new GridPane();　　　//ルートペインとなるオブジェクトを生成
		GridPane.setConstraints(button1,0,0);　　//ボタンの配置を指定
		GridPane.setConstraints(button2,1,0);
		GridPane.setConstraints(button3,0,1);
		GridPane.setConstraints(subPane,1,1);　　//subPaneの位置を指定

		root.getChildren().addAll(button1,button2,button3,subPane);

　　　　　//ルートペインにsubPane,すべてを追加

		Scene scene = new Scene(root);
　　　　　//シーンオブジェクトを生成


		stage.setScene(scene);　　//ステージにシーンを配置
		stage.show();　　　　　　　//アプリケーションウィンドウを表示
	}






	public static void main(String[] args){
		launch();
	}
}
```
Juliaで数値計算　その3：コードサンプル〜2次元プロット・可視化編〜

Juliaで数値計算　その1：コードサンプル〜基本的計算編〜
https://qiita.com/cometscome_phys/items/31d0b811345a3e12fcef
Juliaで数値計算　その2：コードサンプル〜わかりやすい書き方編〜
https://qiita.com/cometscome_phys/items/dfd63f1f7b51bdda4ca4
に引き続いて、FortranやCからやってきた人のためにJuliaの書き方を紹介する。
この記事はその3である。使いそうなものを適宜追加して更新する予定。

計算した結果をグラフにする時、FortranやCであれば、計算したデータをファイルに書き出してgnuplotなどで可視化することが多いだろう。Juliaであれば、ファイルに書き出さなくてもその場でグラフを出力させることができる。
http://docs.juliaplots.org/latest/

Juliaでプロットする場合、基本的には、Plotsライブラリを使う。その際、様々なバックエンドライブラリがある。どのようなものがあるかは
"プログラミング/julia/グラフの書き方"
https://dora.bk.tsukuba.ac.jp/~takeuchi/?プログラミング%2Fjulia%2Fグラフの書き方
が非常に詳しい。
この記事では、いくつかにしぼって紹介する。
なお、Juliaのバージョンは1.0.0を使用している。

#JuliaBoxの紹介
プロットに関して述べる前に、Juliaを気軽に試したい人のためのJuliaBox
https://juliabox.com
を紹介しておく。GoogleかgithubかLinkedInのアカウントを持っていればすぐにログインできて、ブラウザ上でJuliaを試すことができる。最近Julia 1.0も導入された。自分のPCにインストールする必要がないので、とても簡単。
この記事ではJuliaBox上で動くことを確認している。

# 2次元プロット
## シンプルな場合
まず、一番シンプルな場合。

```julia
using Plots
f(x) = cos(x)
x=0.0:0.2:2π #x=0からx=2πまで、0.2刻みの配列を生成
y=f.(x) #関数fをxに適用
plot(x,y)
```
とすると、JuliaBoxであればグラフが出力される。ここで.はある関数を要素ごとに演算するもので、f.(x)はxのそれぞれの要素にfを適用させたものになる。

![cos.png](https://qiita-image-store.s3.amazonaws.com/0/246113/67eb69ff-d8de-b307-9aef-9751282c3c9b.png)

## グラフのファイル書き出し

グラフは、

```julia
savefig("cos.pdf")
```
でpdfファイルに、

```julia
savefig("cos.png")
```
でpngファイルに書き出される。

## 複数のプロット
グラフを追加させたければ、先ほどのあとに、

```julia
f2(x) = cos(2*x)
y2=map(f2,x)
plot!(x,y2)
```
とplotのかわりにplot!を使うことで重ねることができる。

![cos2.png](https://qiita-image-store.s3.amazonaws.com/0/246113/fb6aed89-32b2-4312-c1b8-1b926be8cb88.png)

また、plot!で追記するのではなく、同時にプロットしたければ、

```julia
using Plots
f(x) = cos(x)
x=0.0:0.2:2π #x=0からx=2πまで、0.2刻みの配列を生成
y=f.(x) #関数fをxに適用
f2(x) = cos(2*x)
y2=map(f2,x)
plot(x,[y,y2])
```
と[y,y2]と並べればよい。

## 範囲指定

プロットの範囲指定をするには、

```julia
using Plots
f(x) = cos(x)
x=0.0:0.2:2π
y= f.(x)
plot(x,y,xlims=(0,1),ylims=(0.5,1))
```
とxlimsとylimsを使えばよい。これをプロットすると、

![cos3.png](https://qiita-image-store.s3.amazonaws.com/0/246113/cf99a060-cf43-ca01-d3c7-23a61b9b03ce.png)

となる。



## 修飾してみる

次に、プロットを修飾してみよう。

```julia
using Plots
f(x) = cos(x)
x=0.0:0.2:2π #x=0からx=2πまで、0.2刻みの配列を生成
y=f.(x) #関数fをxに適用
f2(x) = cos(2*x)
x=0.0:0.2:2π
y2=map(f2,x)
xticks_values = [0,π/2,π,3π/2,2π]
xticks_labels = ["0","pi/2","pi","3pi/2","2pi"]
yticks_values = [-1.0,-0.5,0,0.5,1.0]
yticks_labels = ["-1","-1/2","0","1/2","1"]
plot(x,[y,y2],labels=["cos(x)","cos(2x)"],xticks = (xticks_values,xticks_labels),
    yticks = (yticks_values,yticks_labels),
    shape = [:circle :star5],color=[:green :orange],
    xlabel="t[sec]",ylabel="f(t)") 
```
とすると、

![cos3.png](https://qiita-image-store.s3.amazonaws.com/0/246113/47ced84e-932e-d31c-5c1d-ac881975e191.png)


が得られる。labelsを使うとグラフのラベルが、xticksを使うとx軸の目盛りが、追加される。
ざっくりECMAScriptとBabelの話

## ECMAScriptとは？
**ECMAScript**は、JavaScriptを元にして標準規格化されたスクリプト言語です。

JavaScriptはNetscapeによって開発されましたが、それをベースにしたJScriptをマイクロソフトが独自に開発していたりと、互換性に乏しい状態でした。そこで、1990年代後半に、情報通信システムの分野における国際的な標準化団体である**Ecma International**によって、JavaScriptを元にした標準規格のECMAScriptが策定されました。

## ECMAScriptのバージョン
ECMAScriptは、ECMA-262という規格番号で標準化されています。
1997年に、1st editionである、ECMAScript 1が策定され、2009年に5th editionの**ECMAScript 5**（以下、**ES5**）とアップデートをしてきました。
（4th editionは仕様がまとまらず、破棄されました）

2015年の6th editionから、それまでのECMAScript 番号というeditionベースの略称から、**年号ベースの仕様書名で呼ばれることが推奨**されるようになり、**ECMAScript 2015**（以下、**ES2015**）と表記されています。

**JavaScript系のブログ等で、ES6/ES2015と、2つの表記が混在しているのは、そのためです。**

また、ES2015からは毎年改訂が行われるようになり、2018年10月現在は、ES2018までが策定されています。

## Babelの機能と役割
ECMAScriptは、ES5からES2015で大きく変化しました。
クラスやモジュール、イテレーター、アロー関数、分割代入等、とても便利な記法が追加されたわけですが、**ECMAScriptの変化にブラウザやクローラーがピッタリとついてきているわけではありません。**
たとえば、Internet Explorer 11（以下、IE11）やGooglebotのレンダリングはES5相当なので、ES2015以降のバージョンでかかれたJavaScriptは、それらの環境では正しく動作しません。

しかし、ES2015以降の便利な記法は、どんどん利用したい。。
そこで、**Babel**の出番です。

Babelは、**ES2015〜2018の記法を、ES5に自動的に変換してくれるツール**です。
（変換することを**トランスパイル**とも言います）

Babelを利用することにより、モダンなJavaScriptの記法を使用しながら、レガシーな環境にも対応できるわけです。
便利ですね！

### Babel使用時の注意点
BabelはES2015〜2018をES5相当までトランスパイルしてくれますが、**機能を追加するわけではありません。**
たとえば、async/awaitとかそのまま使うと「Promiseねえよ！」って、IEで怒られたりします。
そういった場合は、**@babel/polyfill**等のポリフィルを使う必要があります。

## まとめ
- ECMAScriptは、JavaScriptを元にして標準規格化されたスクリプト言語
- 5th editionまではES5のようにバージョン表記で、6th editionからはES2015のように年号表記
- ES2015から多くの機能・記法がついかされたが、ブラウザやクローラーが追いついていないので、レガシー環境に対応する場合はBabelでトランスパイルしてあげる必要がある
- 機能まで欲しい場合は、@babel/polyfill等のポリフィルが必要
PHPでカタカナの濁点の違いを吸収する


カタカナの濁点には種類があるので、その濁点を統一したい。
例えば下記、これは文字コード `UTF-8` と `UTF-8-MAC` の違いらしい。
（なぜDBデータに`UTF-8-MAC`の文字列が紛れ込んだかは不明。。。）
<img width="444" alt="スクリーンショット 2018-10-05 10.01.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/56193/08c255bf-bd0b-567d-0e36-532b71debc2e.png">
で、今回この２つの文字を比べて、同じ文字として扱いたかった。
`$str1 === $str2` でTRUEになるように。

---

まず試したのは、`mb_convert_kana`　で `V` オプションで濁点を１つの文字として変換することでしたが、うまくいきませんでした。。。

```
var_dump( mb_convert_kana($str1,"KV","utf-8") === mb_convert_kana($str2,"KV","utf-8"));
```

---

次に試したのが、`iconv()`で `UTF-8-MAC` を `UTF-8` に変換する方法でしたが
`UTF-8-MAC` は通常MAC上でしか使えないようで、Linux上では下記のようなエラーが出てしまいます。

```
iconv("UTF-8-MAC", "UTF-8", $str1)
 => iconv(): Wrong charset, conversion from `UTF-8-MAC' to `UTF-8' is not allowed
```

## 解決策

でいろいろ検索したが、最終的に下記のようにシンプルに
`半角カナに変換` → `濁点を置換` → `全角カナに変換`
することで解決しました。
<img width="445" alt="スクリーンショット 2018-10-05 11.52.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/56193/81c474de-89d4-8ae8-1576-1fcf343dbfe1.png">

iconvで `UTF-8-MAC` を `UTF-8` に変換する方法も試しましたが、 `UTF-8-MAC` は通常MACでしか使えません。

他にもっと良い方法があれば、知りたいです。

@tadsan さんからコメント欄にてご指摘いただいていますのでそちらも合わせてお読みください。
【Vue.js】ブラウザリロードした時に、queryのオブジェクトを取得する

## はじめに
Vue Routerを使った時に以下のように、queryを設定してしまうと遷移先の画面でリロードでqueryのオブジェクトを取得できない。

原因はrouter.pushはJSなのでオブジェクトが使えるが、　ブラウザリロードでURLを取得する時はqueryは文字列となるため。
Vue Router固有の問題というよりはURLの扱い方の問題だった。

```.js
const obj = {
  fuga: 'fuga'
}

this.$router.push({
  path: `/exmaple/${this.hoge}`,
  query: {
    param: obj
  }
})

// 遷移先でリロードするとparamのオブジェクトは取得できない
```

## 対応方法
queryをエンコードして渡せば問題は解決した。

```遷移前.js
const obj = {
  fuga: 'fuga'
}

this.$router.push({
  path: `/exmaple/${this.hoge}`,
  query: {
    param: encodeURIComponent(JSON.stringify(obj))
  }
})
```

遷移先でオブジェクトを使う時はディスコードする。

```遷移先.js
computed: {
  obj() {
    return JSON.parse(decodeURIComponent(this.$route.query.param))
  }
}
```
WindowsでGrepする方法（ワンライナーで）

パワーシェルのコマンドレットを使うと、Windowsでも簡単に横断検索できます。

```powershell:grep風コマンド
Select-String "検索キーワード" C:\file\*.xml | Out-File -FilePath C:\file\検索結果.txt
```

正規表現を使う場合は、
Select-String -Pattern "[\d]{,2}"

のようにオプションを付けます。
【Laravel】LaravelでDISTINCTを使用する、かつ実行されているSQLを確認してみる


# Laravelで`DISTINCT`を使用する

例として**あるユーザーのチームIDの重複を消したい場合**

```php
self::where('user_id', $user_id)->distinct()->select('team_id')->get();
```

`self` ・・・ 自身のModelを指す（テーブル名は`tables`とする）


# SQLはどうなってるの

以下のように`toSql()`関数で実行されるSQLを吐き出すことができる

```php
var_dump(self::where('user_id', $user_id)->distinct()->select('team_id')->toSql());
```

var_dump出力

```
select distinct `team_id` from `tables` where `user_id` = ?
```

# おわり
- SQL見ることなんてあんまりないけど、どんなSQL実行されてるのかきになるよね

# 参考
- [データベース：クエリビルダ 5.6 Laravel](https://readouble.com/laravel/5.6/ja/queries.html)
- [Laravel5でSQLを確認する(お手軽版) - Qiita](https://qiita.com/torut/items/c21ec0ed9a2e9a426920)
【MYSQL】指定したカラム名をもつテーブルを検索する

調べたい時いつも忘れる。`information`スキーマから調べられる。

```
SELECT
  table_name, 
  column_name 
FROM information_schema.columns 
WHERE 
  column_name like '%clumn_name%' 
AND 
  table_schema = 'db_name';
```
Two-dimensional Cell Averaging Constant False Alarm Rate (CA-CFAR)の実装

# 0. 概要
CFARとは得られた信号からピーク値を抽出する閾値アルゴリズムのことである。例えば、以下のような図がCFARを説明するのによい。
![CFARDetectionExample_02.png](https://qiita-image-store.s3.amazonaws.com/0/95636/a4389977-9b13-26df-1299-dbf9114c9bd7.png)
https://jp.mathworks.com/help/phased/examples/constant-false-alarm-rate-cfar-detection.html

基本的にピーク値を抽出するのであれば、ある一定の閾値を設ければよいが、上記の図のような右肩上がりの（局在的変化する）信号情報の場合は固定値の閾値を設けたところで上手くピーク値を抽出することは出来ない。

そこで、閾値をAdaptiveに調整する必要があるということで生まれたのがCFARである。簡単にいうと、ある領域における背景ノイズ(偶然誤差や統計誤差)を計算して、それを閾値としている。最も単純なものがCA-CFARであり、他にもワイブルCFARなど様々な手法が提案されている。

ここまでは1次元の信号処理の話であるが、これを2次元に拡張したものもあり、それが2d-CA-CFARである。主に、信号を画像化したようなノイズのある画像から対象物を抽出するのに向いている。今回はこの2d-CA-CFARを実装していく。個人的にはめちゃくちゃよく使う方法なのに、なんでどこにも実装がないのか不思議である。

# 1. 理屈
理論は凄く簡単である。下のブロック図を参考にすると、すぐに理解ができる。
![cfar_fig1.png](https://qiita-image-store.s3.amazonaws.com/0/95636/c3985087-144e-d32d-342b-e96a118f6f72.png)
https://awrcorp.com/download/faq/english/docs/vss_system_blocks/cfar.htm
まず、あるWindowサイズを決定し、そのWindowsサイズに含まれる信号値の平均を計算する。
ここで重要なのは、ピーク値周辺のデータというのは、その周辺の信号値もピーク値に引っ張られて、全体的に高い値を示す傾向がある。このため、Guard Cellというものを使う。これは、ピーク値近傍の信号値は平均値に混ぜないといったものである。

なお、今回は2dなのである画素 (Pixel under test)に着目した時のGuard cell及びBackgroundは以下のようになる。
![Sliding-windows-for-CFAR-algorithm.png](https://qiita-image-store.s3.amazonaws.com/0/95636/1b004604-3949-9eb5-4e62-86f1dee15d54.png)
https://www.researchgate.net/figure/Sliding-windows-for-CFAR-algorithm_fig1_26548024

数式的に表現すると以下になる。0は不採用という意味。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95636/9a07180f-bd40-0e22-4e51-d46dba7ad004.png)

# 2. 実装
実装は以下である。上手く動作しない場合はハイパーパラメータを調整するとよい。

``` python
# import
import sys
import cv2
import numpy as np
import random

# fields
GUARD_CELLS = 5
BG_CELLS = 10
ALPHA = 2
CFAR_UNITS = 1 + (GUARD_CELLS * 2) + (BG_CELLS * 2)
HALF_CFAR_UNITS = int(CFAR_UNITS/2) + 1
OUTPUT_IMG_DIR = "./"

# preparing
inputImg = cv2.imread("YOUR_IMAGE", 0)
estimateImg = np.zeros((inputImg.shape[0], inputImg.shape[1], 1), np.uint8)

# search
for i in range(inputImg.shape[0] - CFAR_UNITS):
  center_cell_x = i + BG_CELLS + GUARD_CELLS
  for j in range(inputImg.shape[1] - CFAR_UNITS):
    center_cell_y = j  + BG_CELLS + GUARD_CELLS
    average = 0
    for k in range(CFAR_UNITS):
      for l in range(CFAR_UNITS):
        if (k >= BG_CELLS) and (k < (CFAR_UNITS - BG_CELLS)) and (l >= BG_CELLS) and (l < (CFAR_UNITS - BG_CELLS)):
          continue
        average += inputImg[i + k, j + l]
    average /= (CFAR_UNITS * CFAR_UNITS) - ( ((GUARD_CELLS * 2) + 1) * ((GUARD_CELLS * 2) + 1) )

    if inputImg[center_cell_x, center_cell_y] > (average * ALPHA):
      estimateImg[center_cell_x, center_cell_y] = 255

# output
tmpName = OUTPUT_IMG_DIR + "est.png"
cv2.imwrite(tmpName, estimateImg)
```

Enjoy !
Androidのデバッグ版とリリース版でパッケージ名、バージョン名、アプリ名、アイコンを変更する

## はじめに
通常デバッグ版とリリース版の署名が違うことから、同パッケージ名でそれぞれをインストールしようとすることにより、毎回新規インストールが必要となってしまい、データの再入力などがメチャクチャ面倒です。
また、単純にパッケージ名だけを変えただけではランチャーアプリ上でリリース版とデバッグ版の見分けがつけづらく、この辺りを情報を毎回調べ直してしまっていたので自分用メモを残しておきます。

※デバッグビルド用のアイコンは適宜用意してください。

## 変更方法
### パッケージ名
例えばパッケージ名の末尾に`.debug`と付けたい場合は、`app/build.gradle`の
`buildTypes` > `debug` に `applicationIdSuffix`という項目を追加します。

```app/build.gradle
    buildTypes {
        debug {
            debuggable true
            applicationIdSuffix ".debug" //←追加
        }
    }
```

`com.masaibar.sample `というパッケージ名だとしたら、デバッグビルドは`com.masaibar.sample.debug`というパッケージ名になります。

パッケージ名が変わると端末内で別アプリとして扱われるため、リリース版とデバッグ版が共存できるようになります。

### バージョン名

`buildTypes` > `debug`に`versionNameSuffix`という項目を追加すると、バージョン名の末尾に任意の文字列を追加できます。

```app/build.gradle
    buildTypes {
        debug {
            debuggable true
            versionNameSuffix "debug"  //←追加
        }
    }
```
端末内にバージョン名を表示している際など「これ何ビルドだっけ？」が一目瞭然で分かるので地味に助かります。

### アプリ名
アプリ名は、`AndroidManifest.xml`上で`android:label`として`strings.xml`を参照しているものとします。

```app/AndroidManifest.xml
<application
        android:label="@string/app_name"
 />
```

`main`に並列する形で`debug`というディレクトリを掘り、その中に同じ構造で`strings.xml`ファイルを作成し、`main`側と同じ`name`に対してデバッグビルド時に表示したいアプリ名を設定します。

```app/src/main/res/values/strings.xml
<string name="app_name">アプリ名</string>
```

```app/src/debug/res/values/strings.xml
<string name="app_name">アプリ名[Debug]</string>
```

あくまで個人的な意見なのですが端末内のランチャーで横並びになってくれるよう、`アプリ名+デバッグと分かる識別子`にしておくのが無難です。
（奇をてらって全く別のアプリ名を設定したり、上で挙げた例とは逆の`デバッグと分かる識別子+アプリ名`だと頭文字が別物になってしまい、ランチャー内で見失いがちだったりします。）

### アイコン
アプリ名は、`AndroidManifest.xml`上で`android:icon`として`@mipmap/ic_launcher`を参照しているものとします。

```app/AndroidManifest.xml
<application
        android:icon="@mipmap/ic_launcher"
 />
```
こちらもアプリ名同様、`debug`ディレクトリ配下に、同じパス（今回は`@mipmap/ic_launcher`）で参照できるよう設置することにより、デバッグビルド時にはそちらの画像が参照されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/68671/5a8ede86-298b-01c2-5e76-a5166139047e.png)



## おわりに
アイコンに関しては[gradle-android-ribbonizer-plugin](https://github.com/maskarade/gradle-android-ribbonizer-plugin)というプラグインを使うことにより、専用のアイコン画像を用意せずに対応する方法もあるようです。

共存した上で見分けも付きやすくなり、開発におけるストレスが少しでも軽減できれば幸いです :pray: 

今回のコードはこちらで参照できます。
https://github.com/masaibar/DistinguishableAppSample
Goでhttp.Redirectを使用した時SetCookieが無視されてしまう

## 事象
いつもコードを書く時に見た目がスッキリするので画面表示と内部の処理を別のメソッドで書いていたのですが
Cookieを使用する際にsetCookieの後http.redirectを使用したらCookieが登録できていなかったというものです。

## ダメだったコード
main.go

```
package main

import (
	"html/template"
	"net/http"
)

func main(){
    server := http.Server{
        Addr: "localhost:8080",
    }

    http.HandleFunc("/set", setCookie)
    http.HandleFunc("/cookieComp", cookieCompleteHandler)

    server.ListenAndServe()
}

func setCookie(w http.ResponseWriter, r *http.Request) {
    cookie := &http.Cookie{
        Name: "Taro",
        Value: "たなかたろうです！",
    }

    http.SetCookie(w, cookie)

    http.Redirect(w, r, "/cookieComp", http.StatusFound)
}

func cookieCompleteHandler(w http.ResponseWriter, r *http.Request){
    var templatefile = template.Must(template.ParseFiles("./cookieComplete.html"))
	templatefile.Execute(w, "cookieComplete.html")
}
```

cookieComplete.html

```
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>team</title>
    </head>
    <body>
        <p>cookie</p>
        <p> name: {{.Name}} </p>
        <p> value:{{.Value}} </p>
    </body>
</html>
```

## 正しいコード
main.go

```
package main

import (
	"html/template"
	"net/http"
)

func main(){
    server := http.Server{
        Addr: "localhost:8080",
    }

    http.HandleFunc("/set", setCookie)

    server.ListenAndServe()
}

func setCookie(w http.ResponseWriter, r *http.Request) {
    cookie := &http.Cookie{
        Name: "Taro",
        Value: "たなかたろうです！",
    }

    http.SetCookie(w, cookie)

    tmpl := template.Must(template.ParseFiles("./cookieComplete.html"))
    tmpl.Execute(w, &cookie)
}
```

cookieComplete.html

```
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>team</title>
    </head>
    <body>
        <p>cookie</p>
        <p> name: {{.Name}} </p>
        <p> value:{{.Value}} </p>
    </body>
</html>
```

## 実行
runした後に`localhost:8080/set`で動きます！
json-serverのDELETEで全てのアイテムや予期しないアイテムが削除される問題

[json-server](https://github.com/typicode/json-server)は非常に便利なのですが、あるアイテムを削除しようとしたときに、なぜか全てのアイテムが削除されてしまう現象に出くわしました。

# TL;DR
デフォルトで設定されている外部キーのサフィックス`Id`と自動的に実行されるcascading deleteの組み合わせで起きる現象なので、外部キーのサフィックスを変えてやれば（一応は）解決します。

```bash
json-server db.json --fks _id
```

 - [DELETE not working properly](https://github.com/typicode/json-server/issues/760)

# 問題の再現

```json:db.json
{
  "customers": [
    {
      "id": 1,
      "customerId": "顧客ID1",
      "name": "顧客1"
    },
    {
      "id": 2,
      "customerId": "顧客ID2",
      "name": "顧客2"
    },
    {
      "id": 3,
      "customerId": "顧客ID3",
      "name": "顧客3"
    }
  ]
}
```

何の変哲もないDBです。サロゲートキー`id`を自動生成、ナチュラルキー`customerId`を手入力することを想定した、よくある設計です。

```bash
json-server db.json
```

普通にjson-serverを立ち上げます。

```bash
curl -XDELETE http://localhost:3000/customers/1
```

普通に`id=1`のアイテムを削除します。

```json:db.json
{
  "customers": []
}
```

なんということでしょう、**全アイテムが削除されました**。

# 原因
自動的に外部キーを設定し、自動的にcascading deleteしてしまう仕様が原因でした。

1. デフォルトでは、`Id`が自動的に外部キーのサフィックスとみなされるようになっており、
1. `customerId`は`customer`への外部キーとみなされ、
1. 任意の`customer`を削除すると、
1. `customerId`によって参照されていない`customer`はcascading deleteによって全て削除されてしまう…

ということのようです。

試しに、`customerId`を外部キーと考え、以下のように`id=1`と`id=2`のアイテムがお互いを参照するように`customerId`を設定し、`id=3`を削除すると、無事に`id=3`のみが削除されます。

```json:db.json
{
  "customers": [
    {
      "id": 1,
      "customerId": 2,
      "name": "顧客1"
    },
    {
      "id": 2,
      "customerId": 1,
      "name": "顧客2"
    },
    {
      "id": 3,
      "customerId": 1,
      "name": "顧客3"
    }
  ]
}
```

# 対策
外部キーのサフィックスはオプションで設定できるので、適当な値に変えてやれば解決します。

```bash
json-server db.json --fks _id
```

ただし、実際の外部キーのサフィックスとして`Id`を利用することはできなくなってしまうので、外部参照をせずアイテムを埋め込んでおくか、apiのpayloadの設計を変える必要があります。
しかし、モックサーバーの制限に合わせて本体の設計を変えるのは、控えめに言ってもおかしな話です。
個人的には、埋め込みによる対応でモックサーバーとしての役目は十分に果たせるので、問題ないといえばないのですが。

例外的なユースケースというわけでもないと思うので、公式に対策してほしいところです。しかし、現状ではcascading deleteはドキュメントにも記載されておらず、制御する方法もありません。
issueも上がっており、従属的なアイテムのみを削除+カスケードしないフラグを追加するプルリクも上がっているのですが、もう半年近く放置されています…。

 - [DELETE not working properly](https://github.com/typicode/json-server/issues/760)
Amazon RDS の削除保護の有効化・無効化でダウンタイムが発生するかサポートに確認した

# TL; DR
RDS の削除保護の有効化・無効化ではダウンタイムは発生せず、また削除保護は即時に反映される。

# 経緯
先日 Amazon RDS の削除保護機能の提供が開始された。

Amazon RDS がデータベース削除保護の提供を開始
https://aws.amazon.com/jp/about-aws/whats-new/2018/09/amazon-rds-now-provides-database-deletion-protection/

Web コンソールの設定画面
<img width="850" alt="設定画面で「削除保護の有効化」にチェックを入れたときのスクリーンショット" src="https://qiita-image-store.s3.amazonaws.com/0/487/cacb1ab9-1cbe-6ce1-8340-5f6ffade7362.png">

これを変更して適用しようとすると「変更のスケジュール」の確認画面が出る。

<img width="883" alt="変更のスケジュールの確認画面で、次のメンテナンス ウィンドウで適用することを説明する画面" src="https://qiita-image-store.s3.amazonaws.com/0/487/80837433-de6d-04d3-4ff7-78e8d8b6d1e7.jpeg">

「すぐに適用」を選択すると、予期しないダウンタイムの可能性の警告も出る。
<img width="874" alt="変更のスケジュールの確認画面で、「すぐに適用」を選択すると、予期しないダウンタイムが生じることの警告が出ている画像" src="https://qiita-image-store.s3.amazonaws.com/0/487/67f76dbd-4e54-824a-b54f-f352f94a3270.jpeg">

削除保護を有効化したいような重要な DB でダウンタイムが発生すると困るので、実際はどうなのかサポートに尋ねてみた。

# 問い合わせ
## 質問

>Web コンソールから、削除保護の有効化にチェックを入れて「Continue」を押すと、「Scheduling of modifications」の選択画面が出ます。
> 削除保護の値を変更した際に、変更が適用されるタイミングでダウンタイムが発生することはありますか。

## 回答
> 削除保護の設定を変更された際に、ダウンタイムは発生いたしませんのでご安心ください。
> また、「Scheduling of modifications」の選択画面にて、「Apply during the next scheduled maintenance window」を選択いたしましても、削除保護機能の変更は即時に適用されます。

# 所感
安心して削除保護を有効にできる。
【Laravel】Feature テストをする際に unique バリデーションの結果を Mock する

テストする際に次の記述を入れておくことで、DB アクセスを発生させずに `unique` バリデーションルールをパスすることができる。

```php
$presenceVerifierMock = \Mockery::mock(\Illuminate\Validation\PresenceVerifierInterface::class);
$presenceVerifierMock->shouldReceive('getCount')
    ->andReturn(0);
$presenceVerifierMock->shouldReceive('setConnection');
\Validator::setPresenceVerifier($presenceVerifierMock);
```

3 行目を `->andReturn(1)` に変えれば逆に `unique` バリデーションルールに引っかかるようになるはず（未確認）。
Go製マイグレーションツールsql-migrate

## 概要
Go製のデータベースmigrationツールとして`sql-migrate`を使って開発しているのでコマンドや動作仕様などを簡単に書く。

## 公式リポジトリ
https://github.com/rubenv/sql-migrate

## 特徴
- CLIツール
- SQLite, PostgreSQL, MySQL, Oracleなどの色々なデータベースをサポート
- スキーマの作成/変更/ロールバック機能
- ソースコードからの実行制御
- その他色々

## インストール
```
$ go get github.com/rubenv/sql-migrate/...
```

## 詳細
公式のREADMEを見れば分かる事だけど日本語で書いていく

### 設定ファイル
デフォルトは`dbconfig.yml`というファイル名で参照される。yml内の`env`キーでは`development`, `production`など環境ごとに設定を定義できる。migrationの実行を管理するテーブル名は`gorp_migrations`。`dir`は作成されたmigrationファイルの保存先。
オプションでこの辺りの名前は色々変更ができるし、デフォルトのままでも問題ない。

```dbconfig.yml
development:
    dialect: mysql
    dir: db/migrations
    datasource: user_name:password@tcp(127.0.0.1)/dbname?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true

production:
    dialect: postgres
    dir: migrations/postgres
    datasource: dbname=myapp sslmode=disable
    table: migrations
```

## コマンド色々

```
# ヘルプ
$ sql-migrate --help
```

```
マイグレーション作成
# 以下のコマンドでは「20181005103536-create_users.sql」みたいなマイグレーションファイルが作成される
# ファイル名のdatetimeは自動で付与

$ sql-migrate new create_users
```

```
# マイグレーションの実行
$ sql-migrate up
```

```
# マイグレーションをdryrunで実行。実行予定のsqlが出力される
$ sql-migrate up -dryrun
```

```
# マイグレーションのロールバック
$ sql-migrate down
```

```
# マイグレーションの実行状態確認
$ sql-migrate status
```

## マイグレーションファイルの内容
マイグレーション作成すると`.sql`としてファイルが生成される。sqlコメント文を使用し`up`の処理なのか`down`の処理なのかを`-- +migration Up`、`-- +migration Down`でそれぞれ指定する。

```20181005103536-create_users.sql
-- +migrate Up
CREATE TABLE IF NOT EXISTS users (id int);

-- +migrate Down
DROP TABLE IF EXISTS users;
```

## migrationの実行管理テーブル
マイグレーション初回実行時に`gorp_migrations`というテーブルが自動で作成される。
このテーブルには実行したマイグレーションファイル名をインサートして実行済みか否かを管理してる。

## 終わり
本番環境でも使っていて特に問題はなし。
他にも色々な機能があるので詳しくは公式リポジトリのREADMEを読んでください
Atomでコード自動整形をしてみる

##経緯
はてなブログをhtmlで書いてると、下書き保存したあと崩れて嫌だったので、コードをAtomにコピペすることに。めんどいから自動整形しようかなと思った次第

##使うもの
[atom-beautify](https://atom.io/packages/atom-beautify)

##使えるもの
>HTML, CSS, JavaScript, PHP, Python, Ruby, Java, C, C++, C#, Objective-C, CoffeeScript, TypeScript, Coldfusion, SQL, and more in Atom

結構いろいろいける

##インストール
Atom > Preferences > install
フォームに'atom-beautify'を入力
install

##実際使ってみる
エディタ上で右クリック > Beautify editor contentsをクリック
ショートカットキーは control + option + B(eautify)
整形楽で気持ちいい
Jenkinsにインストール済みのpluginをlistで出す

スクリプトコンソールに貼り付けて実行すれば OK.

```groovy:Jenkins_script_console
Jenkins.instance.pluginManager.plugins.each {
  p-> println ("\"${p.getLongName()}\":${p.getShortName()}:${p.getVersion()}")
}
```

表示を変えたいときは [Jenkins Main Module API](https://javadoc.jenkins-ci.org/) の PluginWrapper クラスを見ましょう。
Xcode 10でのUniversal frameworkビルドエラーについて

# 問題

Xcode 10でUniversal frameworkビルドをしようとして、iphoneos/iphonesimulatorを連続ビルドすると、一つ前のDerivedDataが消えてしまう。これは-derivedDataPathを指定しても同様です。

# なぜ？

Xcode 10 betaで確認したときは、何もなかったので、Xcode 10のリリース版までに何らかの変更があった模様。なかなか迷惑な変更ですね。。

# 解決方法

iphoneos/iphonesimulatorで、連続ビルドするときは、最初のプロダクト(DerivedData//Build/Products/内のデータ)を一時退避する。

# おまけ

relax https://github.com/scenee/relax というビルド・パッケージツールのv0.6.8で対応済みで、こちらもぜひ使ってみてください。

※ relaxは、fastlaneのgymと同等の機能をもっていますが、provisioning profileでのマニュアルビルドとInfo.plist/Build Settingsのカスタマイズが、かなり簡単にできます。

Step 1. Install Relax 

```
$ brew install scenee/formulae/relax
```

Step 2. Relfileを配置

```
$ touch Relfile
$ cat <<-EOF > Relfile
version: '2'
xcodeproj: MyLib

distributions:
  myframework:
    scheme: MyLib
EOF
```

Step 3. Frameworkをビルド

```
$ relax build myframework
# For your release build
$ relax build myframework --no-simulator
```
GitHub用語

#GitHubと14の用語

- コミット 
- コミットメッセージ 
- マスターブランチ 
- ブランチ 
- 機能ブランチ 
- リリースブランチ 
- マージ 
- タグ 
- チェックアウト 
- プルリクエスト 
- 問題 
- wiki 
- クローン 
- フォーク

GitHubの用語は**小難しい英語だらけ**だ。
GitHubはプロジェクトのバージョンや履歴を管理できる基盤であるが、用語のイメージがし辛い。なぜならこれらを日本語に翻訳すると誤解してしまうからだ。ここでGitとGitHubの違いを理解しておいてほしい。

このページを読み終えたときにはしっかりと記憶に残っているはずだ。

###コミット(Commit)
みなさんはスクリーンショットをご存知ですか。実はコミットはこれと同じことです。なぜならスクリーンショットは、全体を撮影し日付や名前を付けます。それと同様にコミットはプロジェクト全体を保存し理由を付けます。

具体的には、
例えば「この変更をコミットして、GitHubに保存しておこう」と言います。
###コミットメッセージ(Commit message)
ファイルを編集し、その1週間後に作業に戻ると「**なぜ**先週に編集したんだろう」と思ったことはないですか。「コメントを残したり付箋に端書しとけばよかった」なんてことになったことはありませんか。
![名称未設定-1.png](https://qiita-image-store.s3.amazonaws.com/0/245159/cda14df3-e8fd-eff9-a48d-f329d159ed18.png)

コミットメッセージは、このコメントや付箋と同じです。
具体的には、振り返ったときになぜ実装したのかを再確認できます。

例えば「田中さんのコミットメッセージのおかげで次の指針について理解できましたよ」と言います。

###ブランチ(branch)
ブランチは日本語にすると枝や分岐を意味します。枝分かれをイメージするとなにかに似ていませんか。
ブランチはディレクトリ(フォルダ)と同系です。しかし、厳密には機能ごとに分けられたコミットの集まりを表しています。
つまり新しい機能を作成するときは、そのブランチを新たに作成することになります。
例えば「新しい検索機能を実装するためにブランチを作ろう」と言います。
###マスターブランチ(master branch)
新しいGitプロジェクトを作成すると、必ずmasterと言うブランチがデフォルトになります。
このmasterは成果物の一番トップになります。例えば「masterに直接コミットするなよ」と言います。
###機能ブランチ(feature or topic branch)
新しい機能の一部を作成するときは、その機能のブランチ上で作業するでしょう。
これは機能ブランチと言います。例えば「かなりたくさんの機能ブランチがあるな。1つずつ機能を実装していこう」と言います。
###リリースブランチ(release branch)
もしあなたのソフトウェアが古いバージョンをサポートしているなら、更新や修正のためにリリースブランチを作成する必要があるでしょう。
技術的には機能ブランチとリリースブランチに変わりはありません。しかし、区別することはあなたのチームのプロジェクトについての話が早く進むでしょう。
例えば「全てのリリースブランチのセキュリティバグを治そう」と言います。
###マージ(merge)
マージは様々なブランチを1つにまとめたり、他のブランチに組み込んだりする方法です。一般的にはマスターブランチに機能ブランチをマージするでしょう。例えば「アカウントの機能の実装が終わったよ。masterブランチに君の機能とマージできるかな？」と言います。
###タグ(tag)
タグは特別なコミット(履歴)を参照したりするときに使います。タグは成果物をリリースする際の文書に多く使われます。どのバージョンのコードが成果物になったかを確認したり区別したりできます。
例えば「このリリースにタグを付けよう。成果物にプッシュしよう」と言います。
###チェックアウト(checkout)
チェックアウトはプロジェクトのコミット(履歴)の様々なバージョンを調べることです。履歴ごとにファイルを確認します。一般的にはブランチを調べて全ての作業が終わったことを確認できます。どんなコミットでも調べることができます。例えば「最新リリースのタグを調べられる？成果物にバグがあって、直してほしいんです」と言います。
###プルリクエスト(pull request)
本来プルリクエストはあなたがブランチ上で編集し終えた作業をレビューし、マスターにマージします。実装可能な機能について議論が始まる段階でプルリクエストは使用されます。例えば「新しい投票の機能のためにプルリクエストをしよう。他のチームにも知らせたいからね」と言います。
###問題(issue)
GitHubは問題を議論したりバグ追跡する機能です。例えば「ログイン機能がiPhoneでできないんだ。GitHubの文書にバグをレプリケートしておいてくれない？」と言います。
###Wiki
本来Ward Cunninghamによって開発されたWikiは互いを簡単にリンクさせウェブページを手軽に作成するツールです。GitHubプロジェクトには文書を書くためにWikiを使うことがあります。
例えば「多様なサーバー上で実行するプロジェクトの設定の仕方についてwikiのページに追記しておいてくれない？」と言います。
###クローン(Clone)
よくGitHubからプロジェクトのコピーをダウンロードしたいことがあります。クローンはあなたのコンピュータにレポジトリをコピーしてダウンロードすることです。ローカル環境で作業ができます。例えば「バグ直したいから、レポ(repo)をクローンできる？できれば、今夜までにGitHubに修正版のバックアップをプッシュしておいてくれない？」と言います。
###フォーク(Fork)
プロジェクトを直接変更する権限が必要ないときがあります。それは見知らぬ人が書いたオープンソースのプロジェクトや全然知らない会社のグループが書いたプロジェクトなどです。
あなたがプロジェクトの変更を提出したい場合、まずGitHub上のユーザアカウントでプロジェクトをコピーする必要があります。この流れを「レポジトリをフォークする」と言います。クローンして編集してプルリクエストで元のプロジェクトに提出します。例えば「君がホームページをどうやって書き直したのか見てみたいんだ。レポ(repo)をフォークして君の変更内容をプルリクエストで提出してくれないか」
全ての専門用語に圧倒されても気にしないで下さい。自分のプロジェクトを作成し始めればもっともっとたくさん理解できるでしょう！次の章では、様々なGitHubの要素やどのようにプロジェクトの進行を確かめるのかを見ていきましょう。
processing(android mode)でKeyStoreの作成とapkの署名(一部変更すればjavaでもOK)

#目的
processingで署名する
IDEの作成とかに使えるかも(IDE作ってる人はこんなの見ないでも作れそうだけど…)
#library
ZipSignerとSpongyCastleを導入しといてください
#import
```
import java.security.KeyStore;
import java.io.*; 
import android.os.Environment;
import javax.crypto.SecretKey;
import javax.crypto.KeyGenerator;
import kellinwood.security.zipsigner.ZipSigner;
import java.io.InputStream;
import kellinwood.security.zipsigner.optional.CustomKeySigner;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import java.net.*;
```

#権限

processingなら

```
if (!hasPermission("android.permission.WRITE_EXTERNAL_STORAGE"))requestPermission("android.permission.WRITE_EXTERNAL_STORAGE", "initLocation");
```

でできます
javaなら勝手にWRITE_EXTERNAL_STORAGE追加してください

#Keystoreの作成
```
KeyStore ks;
void createKey(String keyName,String keyPassword,String Alias,String AliasPassword){
  try{
    String directory=Environment.getExternalStorageDirectory()+"/"+keyName+"."+KeyStore.getDefaultType();
    ks = KeyStore.getInstance(KeyStore.getDefaultType());
    ks.load(null, keyPassword.toCharArray());
    KeyGenerator keyGen = KeyGenerator.getInstance("AES");
    keyGen.init(128);
    SecretKey mySecretKey=keyGen.generateKey();
    KeyStore.SecretKeyEntry skEntry = new KeyStore.SecretKeyEntry(mySecretKey); 
    ks.setEntry(Alias, skEntry, new KeyStore.PasswordProtection(AliasPassword.toCharArray()));
    File file=new File(directory);
    FileOutputStream fos = new FileOutputStream(file);
    ks.store(fos, keyPassword.toCharArray());
  }catch(Exception e){
    e.printStackTrace();
  }
}
```

でいける

#署名
```
void sign(String keystore,String keystorePassword,String keyAlias,String StringkeyAliasPassword,String inFilename,String outputFilename){
  try {
    ZipSigner signer = new ZipSigner();
    CustomKeySigner.signZip(signer, keystore, keystorePassword.toCharArray(), keyAlias, keyAliasPassword.toCharArray(), "SHA1WITHRSA", inFilename, outputFilename);
  }catch (Exception e) {
     e.printStackTrace();
  }
}
```

でいける

#あとがき
日本語の解説が少ないから手間取ったがやること自体は単純だった