OmniAICreator/Qiita-1.07M huggingface dataset:
stack level too deepの倒し方

# SystemStackError - stack level too deep
rubyを書いてるとよく遭遇するこのエラーを倒すgemを作りました。

## stack level too deepとは
バグで無限再帰を作ってしまった時や、再帰関数の再帰が深すぎる時に起きるエラーです。

```ruby
def factorial(n)
  # return 1 if n.zero?　を忘れて無限再帰になってしまった時
  n * factorial(n-1)
end
factorial 10 #=> SystemStackError: stack level too deep
```
```ruby
def hoge
  # 数万回の再帰は深すぎてできない
  hoge if rand < 0.99999
end
hoge #=> SystemStackError: stack level too deep
```

こうなったが最後、通常は再帰をやめてループに展開するしかありません。
(環境変数RUBY_THREAD_VM_STACK_SIZEで必要な分指定する方法もあります)

```ruby
# before
def hoge
  do_something
  hoge if rand < 0.99999
end

# after
def hoge
  loop do
    do_something
    break unless rand < 0.99999
  end
end
```

```ruby
# before
def fibonacci i, memo = {}
  return i if i <= 1
  memo[i] ||= fibonacci(i-1, memo) + fibonacci(i-2, memo)
end

# after
def fibonacci i
  a, b = 0, 1
  i.times do
    a, b = b, a+b
  end
  a
end
```

beforeとafterが違いすぎる...

# No Stack Level Too Deep
そこ作ったのが `no_sltd` https://github.com/tompng/no_sltd

```
$ gem install no_sltd
```

```ruby
# before
def hoge
  do_something
  hoge if rand < 0.99999
end

# after
require 'no_sltd'
no_sltd def hoge
  do_something
  hoge if rand < 0.99999
end
```

`def` の前に `no_sltd` をつけるだけでstack level too deepが出なくなります。

## どうやってる?
stackはThreadやFiberごとに確保されてるようです。
なので、stack levelが一定以上深くなる毎に、普通に再帰呼び出しする代わりに `Fiber.new { func }.resume` で新しいstackを使うようにしています。
(stackが残りがどれだけ使えるか測る手段があればメモリ効率よくなりそう)

## 遅くないの?
遅いです。メモリもばか食いします。

## どういう時に使えばいいの?
遅くてもいいから再帰が動いて欲しい時、使い捨てのプログラムがstack level too deepになって困った時などにどうぞ
D3.jsで外部ファイル読み時の型変換

数値に変換する

```js
//型変換
var cast = function(d){
    Object.keys(d).forEach(function(key){
        if (!isNaN(+d[key])) d[key] = +d[key];
    });
    return d;
}

//d3 ver4以前 ////////////////////////////////////////

d3.json("hoge.json", cast , main)

function main(data){
    console.log(data)
}

// d3 ver.5以降 ////////////////////////////////////////

d3.josn("hoge.json", cast).then(main);

function main(data){
    console.log(data)
}

```

D3 ver.5 以降でPromise.Allを使う場合の例

```js

//型変換
var cast = function(d){
    Object.keys(d).forEach(function(key){
        if (!isNaN(+d[key])) d[key] = +d[key];
    });
    return d;
}

var p1 = d3.json("hoge.json", cast);
var p2 = d3.csv("fuga.csv", cast);
Promise.all([p1, p2]).then(function(data){
    console.log(data);
});

```
SwiftでRFC3986に準拠したパーセントエンコードをするやつのSwift 3版です。

アンパサンド（＆）も対象に含めたPercent EncodingをするStringのExtensionが欲しく。

なかなか3以前のものしか見つからず・・・

手元で Swift 3にしたスニペットをメモ。 :bow: ﾂｶｯﾃｸﾀﾞｻｲ。

```swift
extension String {
	func stringByAddingPercentEncodingForRFC3986() -> String? {
		let unreserved = "-._~/?"
		var allowed = CharacterSet.alphanumerics
		allowed.insert(charactersIn: unreserved)
		return addingPercentEncoding(withAllowedCharacters: allowed)
	}
}
```

出典

UTF8 Encoding in iOS / swift for email containing +
http://stackoverflow.com/questions/39093990/utf8-encoding-in-ios-swift-for-email-containing
macでpagedown,pageup

WindowsユーザーでWebページを見る際に、pageup,pagedownをよく利用していた人へ
他のサイトで特に紹介されていなかったので投稿しました:information_desk_person:

###<b>pageup</b>
「space bar」を押す
※「fn + ↑」でも出来ます。

###<b>pagedown</b>
「shift + space bar」を押す。
※「fn + ↓」でも出来ます。
Raspberry Pi ZeroをUSBケーブル1本で接続

# Macです。
### 準備するもの
- [ ] Raspberry Pi Zero(Raspberry Pi Zero Wが待ち遠しいですね)
- [ ] microSDカード
- [ ] SDカードリーダー（Mac mini内蔵のものを使いました）
- [ ] microUSBケーブル（今回の肝です、not OTG）

### RaspbianをSDカードに書き込みます。
micro SDカードがマウントされているか確認、ディスクのマウント解除、Raspbianをpvコマンドで書き込み

```bash:ディスクイメージの書き込み
diskutil list
diskutil unmountdisk /dev/disk1
pv 2017-02-16-raspbian-jessie.img | sudo dd bs=4m of=/dev/disk1
```

### マウントされたままのmicroSDカードにsshファイルの追加、config.txtファイル、cmdline.txtファイルの編集、SDカードのアンマウント

```bash:config.txt、cmdline.txtの編集
ls -la /Volumes/boot
touch /Volumes/boot/ssh
echo "dtoverlay=dwc2" | sudo tee -a /Volumes/boot/config.txt
echo "dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait modules-load=dwc2,g_ether" | sudo tee /Volumes/boot/cmdline.txt
diskutil eject /dev/disk1
```

### microUSBケーブルでMacとRaspberryPi ZeroのUSB端子を接続
※これどういうわけかOTG=ホストケーブルじゃないやーつ
raspberrypi.local宛にpingして返ってくるようならIP接続できます。ssh pi@raspberrypi.localしてみましょう。
※ddコマンドが煩わしかったのにpvコマンドで進捗見られるようになったばかりに勢いで画像もなしに投稿してみました。

### 【追記】こういう接続もできるって？
思ったら、USB-Aポートから給電するだけだった(´・ω・｀)…
でも、とりあえずポチった…
https://amzn.to/399Kivf
ViewのonStart/onPause

AndroidのViewに自動更新ロジックを埋め込む時に、ActivityやFragmentのonResume/onPauseに当たるコールバックを受け取りたい時があるかと思います。
そういう場合はView.onVisibilityChangedやView.onWindowFocusChangedなどを使いましょう、というメモです。

# Viewのライフサイクル

Viewのライフサイクルは[こちら][view-lifecycle]の記事に詳しいです。

- onFinishInflate()
- onMeasure()
- onLayout()
- onDraw()
- onAttachedToWindow()
- onDetachedFromWindow()

などのイベントがあります。
この中で、onAttachedToWindow()がActivity.onCreate()に、onDetachedFromWindow()がActivity.onDestroy()にほぼ、対応しているのかな、と思われます。

## Viewの表示、非表示
Activityに更新ロジックやイベントコールバックを登録・解除する時はonResume()/onPause()で行うことが多いかと思います。
Viewの場合は[こちら][view-onpause]の回答の一つを参考にすると、View.onVisibilityChanged()もしくはonWindowFocusChanged()を確認することで、検知できそうです。


```java:MyView.java
@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
    super.onVisibilityChanged(changedView, visibility);
    switch (visibility){
        case VISIBLE://onResume called
        case INVISIBLE:// onPause() called
    }
}

@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
    super.onWindowFocusChanged(hasWindowFocus);
    if (hasWindowFocus) //onresume() called
    else // onPause() called
}
```
Activityから直接イベントを通知する方が確実ですが、Viewの表示されている間だけ自動更新を行いたい、というケースだとonVisibilityChangedは適切ですね。
ただ、このonVisibilityChangedはViewのvisibilityを動的に変更している場合などにも発火されるので、一時的な非表示時にも更新したい場合は注意が必要です。

## 更新ロジックのタイミング
onResume/onPauseでコールバックやスレッドの開始・停止処理を行うのは、Activityがフロント・バックグラウンドの変化をおおむねトリガーして発行されるイベントで、他のアプリが立ち上がっている最中に無駄な表示更新ロジックを行わないための工夫かと思います。

Viewの場合は、ライフサイクル上のコールバックでは表示・非表示を確認できません。
例えば、onAttachedToWindow()・onDetachedFromWindow()では、二つの間でもホームボタン等でActivityがバックグラウンドに存在するケースも存在します。
表示・非表示という状態変化イベントをトリガーにして処理を行うのがいいですね。

## 外部とやりとりするロジックは分離する
もちろん、ネットワークやデータベースなど、他のサービスとのやりとりなどが含まれるケースでは、Viewではなくコントローラー等にロジックを寄せる方がいいでしょう。
なので、このようなイベントで処理を書くケースは少ないのかもしれません。

# 参考

- [Can a custom View know that onPause has been called?][view-onpause]
- [Android入門 アプリ開発の基本、ビューのライフサイクル(図解)][view-lifecycle]
- [onCreate と　onStart と onResume の違い](http://qiita.com/m2mtu/items/ac0d61e884519a4c61bb)

[view-onpause]:http://stackoverflow.com/questions/22368720/can-a-custom-view-know-that-onpause-has-been-called
[view-lifecycle]:https://www.ecoop.net/memo/archives/android_lifecycle_of_view.html
AtomをVimっぽくしてみた

# VimのキーバインドをAtomでも使いたい

最近Atomを使い始め、インストールしてすぐにVimのキーバインドを使いたいと思っていろいろ調べていた。

あれこれ調べていくと以下のようにトレンド？が遷移しているようだったので、**vim-mode-plus** + **vim-mode-plus-ex-mode**でやってみることに。

vim-mode + ex-mode
-> vim-mode-plus + キーバインド設定
-> vim-mode-plus + vim-mode-plus-ex-mode

# 追記 2017-07-27
コメントでご指摘をいただいたとおり、今はvim-mode-plus-ex-modeではなく、**ex-mode**の利用が推奨されているようです。以下、コメントより抜粋。

> vim-mode-plus-ex-mode のREADMEに

>> I originally released this package for quick workaround of lack of ex-mode support.
>> But now ex-mode works with vim-mode-plus.
>> If you want better ex-mode, don't use this package, use ex-mode instead.

> と書いてありますね。
> 今はex-modeを使ったほうが良さそうです。


# 環境

- OS： Mac OS X EI Capitan 10.11.6
- Software
    - Atom: 1.14.4
    - vim-mode-plus: 0.82.3
    - vim-mode-plus-ex-mode: 0.8.1

# プラグイン紹介

## vim-mode-plus
vim-mode をfork して作られたVim機能を再現するプラグイン。
vim-mode から様々な機能が拡張されているようで、特に理由がなければこちらを選ぶのがよい。

## vim-mode-plus-ex-mode
vim-mode-plus 単体では実現できないEXモードを再現するプラグイン。（調査時点）
:w :wq などと入力して操作することができるようになる。

vim-mode-plus 登場したてのときはこのプラグインの代わりにキーバインド設定でEXモードを実現していたようだが、私のようなヘッポコエンジニアには難しいので、大変助かった。

# インストール

※通常のプラグインインストール手順。また、初期設定なども特になく使っているので、通常手順を知っている方は読まなくても大丈夫だと思われる。

1. Atom を起動する
2. [コマンド] ＋ [Shift] ＋ [P]キーを同時押しして、コマンドパレットを開く
3. コマンドパレットに「settings」と入力して[Enter]キーを押す
4. 設定タブが開くので、左側の[Install]ボタンを押して、インストールしたいプラグイン名で検索する

![atom+vim.gif](https://qiita-image-store.s3.amazonaws.com/0/114828/830518ff-fb8d-2fb2-0973-61b52ed60f0a.gif)

# おわりに

まだヘッポコエンジニアのため、間違っている箇所等があればご指摘いただけたら嬉しいです。

enjoy Atom & Vim Life!
縦横の割合を指定してユーザーフォームのサイズを変更する(メモ)

ユーザーフォームのサイズを変更する時、Zoomを使うと拡大・縮小できるが縦横の比率が固定される
別々に指定して変更したかったのでメモ

```vbnet
'画面サイズをExcelの画面サイズからの割合で変更する
'myForm:変更対象のフォーム
'HeightRate:高さの割合
'WidthRate:幅の割合
Public Sub ReSize(myForm As Object, HeightRate As Integer, WidthRate As Integer)

Dim Control As Variant
Dim ZoomHeight As Double
Dim ZoomWidth As Double
Dim bH As Integer
Dim bW As Integer
    
    '元の高さと幅
    bH = myForm.Height
    bW = myForm.Width
    
    '高さと幅を割合で変更
    myForm.Height = Application.Height * (HeightRate / 100)
    myForm.Width = Application.Width * (WidthRate / 100)
    
    '元のサイズとの比率
    ZoomHeight = myForm.Height / bH
    ZoomWidth = myForm.Width / bW
    
    '位置を中央に移動
    myForm.Top = (Application.Height - myForm.Height) / 2
    myForm.Left = (Application.Width - myForm.Width) / 2
    
    '各コントロールの位置とサイズを比率から修正
    For Each Control In myForm.Controls
        Control.Height = Control.Height * ZoomHeight
        Control.Width = Control.Width * ZoomWidth
        Control.Top = Control.Top * ZoomHeight
        Control.Left = Control.Left * ZoomWidth
    Next

End Sub
```

基準サイズはApplication.Height,Application.Widthで取得している為、Excelウィンドウのサイズとなる
ディスプレイ基準にする時はAPIなどで取得すること
EclipseでHTMLやJSPをフォーマットして残念なレイアウトになったときにする設定

EclipseでJSPやHTMLを実装していて、フォーマットをかけると残念なことになります。
具体的にはこんなソースコードにフォーマット書けると以下のようになります。

[フォーマット前]
![before.png](https://qiita-image-store.s3.amazonaws.com/0/39536/d8aca4e7-c820-bbf5-8722-e30cbfdeeed1.png)

[フォーマット後]
![after.png](https://qiita-image-store.s3.amazonaws.com/0/39536/d568d25b-a465-2724-7056-95d01aed7345.png)

ソースは今使っている[Spring Boot](https://projects.spring.io/spring-boot/)のサンプルを拝借してちょっと手を加えました。
https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples

このフォーマットの何が残念かと言うと、以下の2点が考慮されないことです。
1. 長文になると不要な改行が入る
2. 改行されないHTMLタグがある

![after_red.png](https://qiita-image-store.s3.amazonaws.com/0/39536/fad79f99-93da-7566-f15f-4edc26b76644.png)

そこでEclipseに以下の設定をすると求めるフォーマットをしてくれます。
1. メニューから「Windows」→「Preferences」をクリック
2. 「Preferences」の画面が開いたら、「Web」→「HTML Files」→「Edtor」
3. 「Formatting」の「Line width:」を「72」から「200」にする
4. 同じ設定画面の「Inline Elements:」から改行してほしいHTMLタグを選択して「Remove」を押して消す
　 ※ 今回の場合は「td」と「input」が改行されていないので、削除します。

「Line width:」は1行に表示する文字数の設定です。
200文字はあくまでも目安なので、もっと長文を1行で表示したい場合は適当に調整してください。

「Inline Elements:」はinlieで表示するHTMLタグが登録されています。
そのため、この設定から削除したタグは改行して表示されます。

これで再度フォーマットをするといい感じになりました。
Dockerを使ってTensorFlow環境を作る

# 概要
TensorFlowの開発環境の構築を行います。
Dockerを使ったのは、色々開発するのにPC環境を汚したくないからです。

**環境**
下記のどちらの環境でも動作確認を行いました。

- Windows10
- macOS

#Docker環境の準備
まず、Windowsは[こちら](https://docs.docker.com/docker-for-windows/install/)、Macは[こちら](https://docs.docker.com/docker-for-mac/install/)からStable版のDocker for xxをダウンロードして、インストールしましょう。

指示通りにインストールすると、Windows&Mac共にDockerアイコンがメニューバーに登録されます。

コマンドでもいいですが、色々開発していくとポートが被ったりするので、Kitematicを使います。
アイコンを右クリックし、Open Kitematicをクリック。
<img width="314" alt="スクリーンショット 2017-03-07 23.41.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/168339/0b363726-6ca2-8a28-1002-c00e2433532a.png">

Windowsはダウンロードして、Kitematic.exeを実行
Macは指示通りにインストールし、終わったらOpen Kitematicを再度クリック。

![スクリーンショット 2017-03-07 23.42.17.png](https://qiita-image-store.s3.amazonaws.com/0/168339/d1a0b6c4-e1d4-7b84-88fa-868b8e211cc3.png)

Docker Hubと特に連携はしないので、CLOSEをクリック。
tensorflowで検索するとすでに出来ているDockerコンテナが表示されます。
![スクリーンショット 2017-03-07 23.43.34.png](https://qiita-image-store.s3.amazonaws.com/0/168339/f375c1d4-41d9-06f1-6e80-bb68465c9f92.png)

一番左上にあるItemの・・・をクリックし、「SELECTED TAG:」をクリック。  
GPUを使うなら\*-gpu、python3を使うなら\*-py3、tensorflowのversion1.00を使うなら1.00-*を選びましょう。
よくわからなければ、latestでもok。

選んだらXを押して戻り、「CRAETE」をクリック。

![スクリーンショット 2017-03-07 23.45.07.png](https://qiita-image-store.s3.amazonaws.com/0/168339/bdc84c92-5d46-65e6-9bed-51d301221fb2.png)

右上の「Settings」→「Ports」でDOCKER PORT 8888の隣をクリックすればJupyter Notebookが立ち上がります。
※毎回portが違うため、色々開発するときに被る心配がないので安心です。
※Jupyter Notebookは初回認証があるのでterminalにあるアドレスのportを変えてアクセスし、認証します。

#Jupyter Notebookの使い方
下記を参考にすると良いと思います。
[【初心者向け】MacでDockerを使ってTensorFlowを試す(Jupyter Notebook)](http://qiita.com/hikarut/items/ce0ab9bcc6d2a7d7aa05)

#今後
開発環境が出来たので実際に機械学習をやっていますが、
長くなってしまったり、情報の正確性も怪しくなるため、ブログにでも書きます。
Macでコマンドラインからアプリを使って指定のディレクトリ・ファイルを開く

コマンドラインから、たとえばSourceTreeやエディタなどの指定のアプリでディレクトリやファイルを開きたいときは `-a` オプションを付けて指定すればいい。

```bash
# SourceTreeで開く
$ open -a SourceTree ./

# Visual Studio Codeで開く。アプリ名に空白が入っているのでダブルコーテーションで囲む
$ open -a "Visual Studio Code" ./

```

大体開発者用アプリにはコマンドラインから開くためのコマンドラインツールがあったりするけど、たまにしか使わない場合は名前を忘れがちなので、これ一つ覚えておくとよい。
electron builderでバイナリを組み込む

# 前提

* Electronでバイナリを組み込んでspawnやexecで実行してる
* Electron Builderを使っている

# 問題
* バイナリをアプリ内に組み込む必要
* バイナリのパスを解決する必要

# 解決
以下のissueが参考になる。
https://github.com/electron-userland/electron-builder/issues/751

最後の方のコメントにあるようにextraResourcesの指定とNODE_ENVによるバイナリパスの分岐をする。

## 例

1.app/bin/some_cmdにバイナリ配置
2.package.jsonのbuild.extraResoucesに以下のように指定

```json
{
  "build": {
    "extraResources": [
      "app/bin/"
    ],
    //...
  }
}
```

3.NODE_ENVで分岐

```js:app/src/main/index.js
const cmd = process.env.NODE_ENV === 'development'
  ? path.join(__dirname, '../../bin/some_cmd')
  : path.join(process.resourcesPath, 'app/bin/some_cmd')
```
PC,スマホ間のイベント発火タイミングの違い

PCとスマホ端末のevent発火の違いをまとめました
こちらはtextareaを対象にしています。

# textareaにforcusした際
PC, スマホに差異はありませんでした
## PCの場合
```
touchstart
touchend
touchend
mouseover
mousemove
mousedown
focus
mouseup
```

## スマホ端末の場合(iOS)
```
touchstart
touchend
touchend
mouseover
mousemove
mousedown
focus
mouseup
```

# textareaにキー入力した際
PCでは `keypress` が発生しないこと、`keydown` `keyup` が２回発生すること
などの差違がありました
ついでに `focus`なども発生しません

## PCの場合
```
keydown  - textarea.value = ""
keyup    - textarea.value = "あ"
keydown  - textarea.value = "あ"
keyup    - textarea.value = "あ"
change　　  - textarea.value = "あ"
blur     - textarea.value = "あ"
focus    - textarea.value = "あ"
blur　　    - textarea.value = "あ"
```

## スマホ端末の場合(iOS)
```
keydown   - textarea.value = ""
keypress  - textarea.value = ""
keyup　　    - textarea.value = "あ"
```



# textareaにコピー&ペーストした際

## PCの場合
```
focus       - textarea.value = ""
touchstart  - textarea.value = ""
touchend    - textarea.value = ""
touchend    - textarea.value = ""
mousemove   - textarea.value = ""
mousedown   - textarea.value = ""
mouseup     - textarea.value = ""
keydown     - textarea.value = ""
keydown     - textarea.value = ""
paste       - textarea.value = ""
keyup       - textarea.value = "あ"
keydown     - textarea.value = "あ"
keypress    - textarea.value = "あ"
keyup       - textarea.value = "あ"
change      - textarea.value = "あ"
blur        - textarea.value = "あ"
```

## スマホ端末(iOS)の場合
※ ペーストし、textareaに反映された後のイベントの発火がない

```
touchstart    - textarea.value = ""
touchend    - textarea.value = ""
touchend    - textarea.value = ""
ペースト選択ボタンが出る
ペーストボタン押下
paste    - textarea.value = ""
```
この後タッチなどをしてイベントを発火させるとvalueの中身が入っていることが確認できた
これを防ぐには `setTimeout` などで `0.1` 秒遅らせたりいろいろなんか対応する必要がある・・・（；；
こんな素敵な記事がありました
http://manji602.hatenablog.com/entry/20130829/1377767902


# まとめ
発火タイミング・イベントの種類・発火回数などなど、いろいろと差が確認できました
大変ですね・・・
単純にログを出して見ただけなので、なにかご指摘ありましたらお気軽にお願いいたします。
MySQL INSERT ... ON DUPLICATE KEY UPDATE 時のauto_increment

UPDATE処理が走った場合でも、auto_incrementは増える。
INSERT / UPDATE の挙動に関わらず、ON DUPLICATE KEY UPDATE の実行の数だけ AUTO_INCREMENTされます。
通常のUPDATEとは違うので気を付ける。。

https://dev.mysql.com/doc/refman/5.6/ja/insert-on-duplicate.html
Androidで動くBASICでGoogle Driveと連携する

BASIC!は、Androidで動くBASIC インタープリタです。詳しくは以下をどうぞ。

* [AndroidでBASICを使う](http://qiita.com/basictomonokai/items/25bcb21ec69c00e9ad23)

BASIC!にはインテントを扱う命令が二つしかなく、Androidで動く言語としては貧弱です。それでもGoogle Driveに連携する方法が見つかったので書いておきます。

##1.BASIC!のインテント関連の命令

App.startとApp.broadcastの２つしかありません。今回はApp.startを使いました。命令の詳細はマニュアルをごらんください。

* [マニュアルの場所(bintray)](https://bintray.com/rfo-basic/android/RFO-BASIC/view)


##2.コード

とても短いですがさっそくコードです。ポイントは以下

* grabfile命令でテキストファイルの内容を取得
* bundleを生成しGoogle drive上のファイル名称とファイルの内容をセット
* app.startで暗黙的インテント(android.intent.action.SEND)を指定
* app.startの引数としてmimeやbundleのポインターを指定

``` サンプルコード
REM Start of BASIC! Program

filename$="test.txt"

grabfile datf$,filename$,1

bundle.create bptr
bundle.put bptr,"android.intent.extra.SUBJECT","from basic!"
bundle.put bptr,"android.intent.extra.TEXT",datf$

app.start "android.intent.action.SEND",,,,"text/plain",,bptr

bundle.clear bptr

end
```

##3.まとめ、その他

* BASIC!のプログラムから暗黙的インテント経由でGoogle Driveに連携可能
* Google DriveならできるがDropboxだとファイル名称が連携できない
* 大きなサイズのファイルだとこの方法は無理かも
* 当然ですがGoogle Driveアプリは事前にインストールが必要です
* android5.1のタブレットで動作確認しました

以上です。
"Linux上でシェルが実行される仕組みを，体系的に理解しよう"の記事が勉強になったのでメモ

http://language-and-engineering.hatenablog.jp/entry/20110617/p1

## ログインシェルとは
- ログイン時に実行される
- /etc/passwdに定義
  - 大体/bin/bash

## コマンドの実行は子プロセスの生成
- pstreeはbashの子プロセス
- シェルからのコマンド呼び出しはすべてbashによる子プロセス
  - 子プロセス生成のためにfork()とexec()が行われる
  - (デーモンはinitの子プロセスとなる)

## 変数
- シェル変数: シェルスクリプトだけで有効。サブプロセスでは無効。
- 環境変数: シェルスクリプトの外部でも有効。サブプロセスでも有効。
  - exportで定義
  - 親子では共有できるけど、まったく関係のないプロセスからは見えない


## ttyとは
- Linuxではクライアントが複数ログインできるように複数の”端末を用意している”
- ps -ef すると今接続中のttyが確認できる
- デーモンは端末に属さない
- ttyで遊べる
  - http://takuya-1st.hatenablog.jp/entry/20101024/1287947368
OpenVAS 等からのポートスキャン攻撃をひとまず拒否する方法 (Apache & nginx)


最近、管理しているサイトに、ポートスキャンをしてくるユーザーが多くなってきました。

自分で意図した脆弱性スキャンをしているのなら良いのですが、関係のない人がスキャン攻撃をしてきます。サーバーの負荷を増大させ、迷惑極まりない。

なので、普段は OpenVAS などのOSSツールは、アクセス拒否をするように設定してみました。

（ちなみに、OpenVAS のソフト自体には罪はないですよ。使っている人が悪いです。）

お断り: 実は。Nessus や Nikto のユーザーエージェントは知らないので、どなたか知っている人、間違っていたらご指摘＆編集リクエスト願います。また、このユーザーエージェント良いよという方、編集リクエストをお願いします！


## Apache の .htaccess 設定例

```.htaccess
# AccessControl UserAgent
SetEnvIfNoCase User-Agent "OpenVAS" ua_key=on
SetEnvIfNoCase User-Agent "Nessus" ua_key=on
SetEnvIfNoCase User-Agent "Nikto" ua_key=on

order allow,deny
allow from all
deny from env=ua_key
deny from 127.0.0.1 #おまけで IP アドレスブロックしたい場合
```

.htaccess は設置したらすぐに有効になるので、これでOK。


## nginx のnginx.conf 設定例

```nginx.conf
server {
    server_name www.example.com;
    
    #......
    # いろいろな設定は省略
    #......
    
    set $deny_f 0;
    if ( $http_user_agent ~* 'OpenVAS' ){
        set $deny_f 1;
    }
    if ( $http_user_agent ~* 'Nessus' ){
        set $deny_f 1;
    }
    if ( $http_user_agent ~* 'Nikto' ){
        set $deny_f 1;
    }
    # おまけで IP アドレスを拒否したい場合
    if ( $remote_addr = '127.0.0.1'  ){
        set $deny_f 1;
    }
    if ( $deny_f = 1) {
        return 403;
    }
}

```

※複数のドメインなどを管理している場合、別の conf ファイル（例: /etc/nginx/conf/deny_spambot.conf）として保存して`include /etc/nginx/conf/deny_spambot.conf;`で指定してやると良いかもです。

nginx の場合はサーバーの再起動が必要です。
設定のチェックを行って、再起動しましょう。

```bash
sudo nginx -t
```

以下のどれかで再起動

```
sudo nginx -s reload
sudo systemctl restart nginx
sudo service ngins restart
```

参考記事
https://macareux.co.jp/blog/apachenginx
http://server-setting.info/centos/apache-nginx-5-setting-deny403.html


## アプリ「POSTMAN」を使って動作テスト

きちんと、アクセス拒否できるか、確認するのも必須。
下記のアプリはおすすめです。

POSTMAN
https://www.getpostman.com/

### 手順

- 方式を GET にしてパラメーターをいれる
- Headers タブをクリック
    - User-Agent を選択し `Mozilla/5.0 [en] (X11, U; OpenVAS 9.0.0)` を入力
- "Send"ボタンを押して、Body の HTML の結果が 403 になっているか確認


以上
SassをGulpで自動コンパイルする

Sassで記述したファイルをGulpを使って自動コンパイルする環境を構築するためのメモ書きです。

#Gulpをインストールするまでの手順
npm（node.jsのパッケージ管理ツール）を使用して、Gulpをインストールします。

## node.jsをインストール
以下のサイトより、node.jsをインストールします。
日本語公式サイトhttps://nodejs.org/ja/

## package.jsonを生成
ここからは自動コンパイルの環境を構築したいプロジェクトのディレクトリに移動して作業します。
以下のコマンドを実行してpackage.jsonを生成します。

    npm init

以下のような内容が表示されるので、必要な項目を入力していきます。

```
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (myproject) 
version: (1.0.0) 
description: My Project
entry point: (index.php)
test command: 
git repository: 
keywords: 
author: My Name
license: (ISC) 
```
完了すると、package.jsonが生成されます。

## Gulpをインストール
以下のコマンドを実行してグローバルと開発用の両方にGulpをインストールします。

グローバルにGulpをインストール

    npm install gulp -g

開発用にGulpをインストール

    npm install gulp --save-dev


# Sassを自動コンパイルするまでの手順

## Gulpプラグインをインストール
使いたいプラグインをインストールします。
今回は以下のプラグインをインストールしました。

Sassコンパイラ

    npm install gulp-sass --save-dev

ベンダープレフィックス自動化

    npm install gulp-autoprefixer --save-dev

エラーハンドリング

    npm install gulp-plumber --save-dev


## gulpfile.jsの作成
gulpfile.jsを作成し、以下を記述します。

```javascript
var path = require('path');
var fs = require('fs');
var pkg = JSON.parse(fs.readFileSync('./package.json'));
var assetsPath = path.resolve(pkg.path.assetsDir);

var gulp = require('gulp');

// sass compiler
var sass = require('gulp-sass');

// add vender prifix
var autoprefixer = require('gulp-autoprefixer');

// error handling
var plumber = require('gulp-plumber');

gulp.task('sass', function() {
    gulp.src(path.join(assetsPath, 'sass/main.scss'))
        .pipe(plumber())
        .pipe(sass())
        .pipe(autoprefixer())
        .pipe(gulp.dest(path.join(assetsPath, 'css/')));
});

gulp.task('default', function() {
    gulp.watch(path.join(assetsPath, 'sass/**/*.scss'),['sass']);
});
```

## package.jsonにパスを追記
gulpfile.jsを他のプロジェクトでも使い回したいので、パスはpackage.jsonに記述するようにします。

```json
"path": {
    "assetsDir": "./assets/"
},
```

## SCSSファイル作成
sass/main.scssを作成します。
sassディレクトリ以下に複数のSCSSファイルを作成し、main.scssで@importすることも可能です。

## 実行
以下のコマンドを実行します。

```
gulp
```

すると、監視状態になり、SCSSファイルが変更・保存される度にcss/main.cssに自動でコンパイルされるようになります。
Apexの設定項目メモ

[apex](http://apex.run/)のproject.jsonとfunction.jsonの設定で、function.jsonが優先される項目を整理しました。

## project.jsonのみで設定できるフィールド

|field name|type|required|description|
|---|---|---|---|
|name|string|required|プロジェクト名。nameTemplateのデフォルト値として使われる|
|description|string||プロジェクトの説明|
|profile|string||使用するAWSプロファイル名。~/.aws/credentialsを参照する。AWS_PROFILEや--profileが指定されていないときに使われる|
|defaultEnvironment|string||デフォルト環境|
|nameTemplate|string||関数名に使用するテンプレート。デフォルトは `{{.Project.Name}}_{{.Function.Name}}`|


## function.jsonが優先されるフィールド

|field name|type|required|description|
|---|---|---|---|
|runtime|string||ランタイム。java/python/node4.3/golang など|
|memory|int||メモリ(MB)|
|timeout|int||タイムアウト(秒)|
|role|string||IAMロール|
|environment|object||環境変数|
|retainedVersions|int||関数のバージョン|
|vpc|object||VPCの設定。securityGroups(array)やsubnets(array)|
Autotoolsでアプリを作成しYoctoでビルドする

# 前提

yoctoのフルビルドは１回終わっているものとする

# Autotoolsでアプリを作成

## ファイル作成

main.c, configure.ac, Makefile.amを用意する

```c:main.c
#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("hello, world\n");
    return 0;
}
```

```:configure.ac
AC_INIT([Tutorial Program], 1.0)
AM_INIT_AUTOMAKE
AC_PROG_CC
AC_CONFIG_FILES(Makefile)
AC_OUTPUT
```

```:Makefile.am
bin_PROGRAMS = tut_prog
tut_prog_SOURCES = main.c
```

automakeがエラーしないようにファイルを作成しておく(忘れるとbitbakeが途中で止まる)

```bash
$ touch NEWS README AUTOURS ChangeLog
```

LICENSEファイルも用意してmd5sumを求めておく（レシピファイルで使用）

## ビルド確認

```bash
$ aclocal
$ autoconf
$ automake --add-missing --foreign -c
$ ./configure
$ make
$ ./tut_prog
hello, world
```

# Yoctoでビルド

本来であれば`yocto-layer`でレイヤーを作ったり、既存のレイヤーに追加するのが正しいのだが、今回はソースディレクトリをレイヤーにしてしまう。

ソースディレクトリ以下にrecipes/tut-prog/tut-prog_0.1.bbとconf/layer.confを作成
(bitbakeは最後の`_`(アンダースコア)以下をバージョン名と見るのでtut_prog.bbのような名前はNG?)

```:conf/layer.conf
BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/recipes/*/*.bb \
            ${LAYERDIR}/recipes/*/*.bbappend \
"
```

```:recipes/tut-prog/tut-prog_0.1.bb
DESCRIPTION = "Tutorial Program"
HOMEPAGE = "http://itage.co.jp"

LICENSE = "MIT"
LIC_FILES_CHKSUM = " \
  file://LICENSE;md5=44098158ddc38babf0e3ad46849b7ce3 \
"

inherit autotools

S="<プロジェクトの絶対パス>"

do_fetch() {
}

__BB_DONT_CACHE = "1"
```

`LIC_FILES_CHKSUM`のmd5の値は`$ md5sum LICENSE`した値を記入する。
`__BB_DONT_CACHE = "1"`がないとソースディレクトリがまるごとビルドディレクトリへ移動させられてしまう。

**Yoctoのbuild/conf/bblayers.confの`BBLAYERS`にプロジェクトの絶対パスを追加しておく**のも忘れずに。

後はbitbakeするだけ。

```bash
# 環境変数ファイルは読み込んでいる前提
$ bitbake tut-prog
```

# 問題点

* LISECEファイルなしで済ます方法がわからない
* ~~`make distclean`が必要ですという旨のエラーが発生し、build/tmp/work/cortexa9hf-neon-poky-linux-gnueabi/tut-prog/0.1-r0以下にコピーされたプロジェクト内で`make distclean`する必要がある~~
【iOS】UITabBarControllerとUINavigationController併用時におけるコードからの画面遷移【Swift3.0】

##### コードによる画面遷移のサンプル

```swift

// Swift3.x

// タブバーのインスタンスを取得
if let tabvc = UIApplication.shared.keyWindow?.rootViewController as? UITabBarController  {

  //左から２番目のタブアイコンを選択状態にする(0が一番左)
    DispatchQueue.main.async {
      tabvc.selectedIndex = 1
    }
}
                
// 移動先ViewControllerのインスタンスを取得（ストーリーボードIDから）
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let dstView = storyboard.instantiateViewController(withIdentifier: "destview")

self.tabBarController?.navigationController?.present(dstView, animated: true, completion: nil)

```

ポイントはタブインデックスの切り替えと、tabBarController?.present()、あるいは、navigationController?.push()ではなく`tabBarController?.navigationController?.present()`なところ。

#### 2018.4.24 追記
`tabvc.selectedIndex = 1`をメインスレッド処理化
ActiveRecord::StatementInvalid: Could not find table 'users'と怒られた時

##エラーが出てから、エラーがなくなるまでの経緯
・rails-tutorialの10章2.3を進めていた際に、以下のようなコマンドを使用すると上記のようなエラーがでた。

```rb
bundle exec rake test
```
エラー文を読むと、dbにusersテーブルがないよと言われているので、とりあえず、test環境でのdbのテーブルを確認してみた。

```rb
$RAILS_DEV＝test rails dbconsole
```
実行結果は以下の様になった。

```rb
sqlite> .table
schema_migrations
```

確かにusersのテーブルが存在しない。よってtest環境でuserテーブルを作成するためにdbをresetする。

```rb
$ RAILS_ENV=test bundle exec rake db:migrate:reset                   
RubyDep: WARNING: Your Ruby is outdated/buggy.
RubyDep: WARNING: Your Ruby is: 2.3.0 (buggy). Recommendation: upgrade to 2.3.1.
RubyDep: WARNING: (To disable warnings, see:http://github.com/e2/ruby_dep/wiki/Disabling-warnings )
== 20170118071744 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0019s
== 20170118071744 CreateUsers: migrated (0.0020s) =============================

== 20170123093707 AddIndexToUsersEmail: migrating =============================
-- add_index(:users, :email, {:unique=>true})
   -> 0.0015s
== 20170123093707 AddIndexToUsersEmail: migrated (0.0017s) ====================

== 20170123095430 AddPasswordDigestToUsers: migrating =========================
-- add_column(:users, :password_digest, :string)
   -> 0.0008s
== 20170123095430 AddPasswordDigestToUsers: migrated (0.0009s) ================

== 20170208063309 AddRememberDigestToUsers: migrating =========================
-- add_column(:users, :remember_digest, :string)
   -> 0.0008s
== 20170208063309 AddRememberDigestToUsers: migrated (0.0009s) ================

== 20170216130826 AddAdminToUsers: migrating ==================================
-- add_column(:users, :admin, :boolean, {:default=>false})
   -> 0.0015s
== 20170216130826 AddAdminToUsers: migrated (0.0016s) =========================

== 20170217055846 AddActivationToUsers: migrating =============================
-- add_column(:users, :activation_digest, :string)
   -> 0.0009s
-- add_column(:users, :activated, :boolean, {:default=>false})
   -> 0.0006s
-- add_column(:users, :activated_at, :datetime)
   -> 0.0006s
== 20170217055846 AddActivationToUsers: migrated (0.0024s) ====================

== 20170225054528 AddResetToUsers: migrating ==================================
-- add_column(:users, :reset_digest, :stringreset_sent_at)
   -> 0.0009s
== 20170225054528 AddResetToUsers: migrated (0.0010s) =========================

```
テーブルができたので、もう一度テストを回してみると、以下の様な結果になった。

```rb
$ bundle exec rake test
# Running:

....................................

Finished in 1.803985s, 19.9558 runs/s, 88.6925 assertions/s.

36 runs, 160 assertions, 0 failures, 0 errors, 0 skips
```

エラー文を読むことは重要。
オフラインでLodgeのアカウントを作成する方法

# アカウント作成
Lodgeの仕様として、アカウント作成後はメールで送られたURLで認証する必要がある。  
ただし、オフライン環境でこのメール認証は行えないため回避策が必要になる。

## Lodge本体の設定
envファイルにメールの設定を持っている。  
通常ならSMTPなどを指定するが開発時の試験用の方法で回避させる。
> 回避しなければアカウント登録ボタン押下直後にメールを送信しようとしてエラーになる。

#### 変更前
```yml
DELIVERY_METHOD: smtp
```

#### 変更後
```yml
DELIVERY_METHOD: smtp
```

## アカウント作成方法
[メール以外の新規ユーザ登録の方法がほしい #168](https://github.com/lodge/lodge/issues/168)で話されている結果```bundle exec rails console```でユーザー作成する必要がある。  
※注意点として認証待ちユーザー名と同じものはエラーで弾かれる。

```rails
user = User.new(
  name:     'foo',
  provider: nil,
  uid:      nil,
  email:    'foobar@baz.com',
  password: 'foobar',
  password_confirmation: 'foobar'
)
user.skip_confirmation!
user.save!
```

### Docker Composeを利用してる場合の手順
#### イメージの中に入る
```cmd
docker-compose run rails bash
```
#### railsのコンソール起動
```cmd
bundle exec rails console
```

#### ユーザー登録
```cmd
user = User.new(
  name:     'foo',
  provider: nil,
  uid:      nil,
  email:    'foobar@baz.com',
  password: 'foobar',
  password_confirmation: 'foobar'
)
user.skip_confirmation!
user.save!
```
DockerでLodgeを起動する方法

# Dockerイメージ
[Github](https://github.com/j138/lodge-docker)または[DockerHub](https://hub.docker.com/r/j138/lodge-docker/)に公開されているものを利用する。

# セットアップ方法
#### Cloneする
```cmd
# git clone https://github.com/j138/lodge-docker.git
```

#### ビルド
READMEに記載されているとおりビルドする。

```cmd
# docker-compose build
# docker-compose up -d
# docker-compose run rake db:create
# docker-compose run rake db:migrate
```

ただし以下の箇所が実はうまく行っておらず画面開くとエラーになる。

```cmd
# docker-compose run rake db:create
# docker-compose run rake db:migrate
```

しょうがないので[本体のGithubのページ](https://github.com/lodge/lodge)の手順で行うためupしてるイメージの中に入る

```cmd
# docker-compose run rails bash
```

イメージの中でデータベース作成とテーブル作成

```cmd
# bundle exec rake db:create RAILS_ENV=production
# bundle exec rake db:migrate RAILS_ENV=production
```

無事DBとテーブル作成されているわけだが、絵文字も実は失敗しているため以下もイメージ内で実行する。

```cmd
# bundle exec rake emoji
```
### 他で詰まったこと
ユーザー作成したあと、メールが送信され認証して初めてログインできる仕組みになっているためオフライン環境で利用したい人は苦しむ。

方法はいちおIssueにあったので[こちら](https://github.com/lodge/lodge)を参照。
[Unity]四角ではないボタンを作るには

今のUnityのバージョンは5以上、4.6から新しいUIシステムを導入した。おかけでマスク(mask)を使いたいなら、簡単にComponentを追加すればいい(昔はスクリプトが必要)：
![image](https://qiita-image-store.s3.amazonaws.com/0/124698/b13d0eb6-50c8-1013-8b70-8329262e558e.png)
こうして色んな効果ができ、四角ではないボタンを作るときにも役に立つでしょう。

ここで本題に入る：
ボタンの絵を透明がある絵にすれば見た目が四角ではないボタンを作れるが、実は判定の方は四角のまま。
解決のために、今カーソルにあるピクセルが透明かを判断する必要がある。
方法は　senritsuさんが書いたスクリプト　を追加する：
[RaycastMask](https://github.com/senritsu/unitility/blob/master/Assets/Unitility/GUI/RaycastMask.cs)
そして注意点としては、使うテクスチャーは以下の設定ようにする：
![image](https://qiita-image-store.s3.amazonaws.com/0/124698/6233ba57-2909-bec3-0ac4-617392137854.png)
Cognos でActive Directoryをセットアップする時の虎の巻的な資料

Cognosの認証でActive Directoryと連携させて認証をセットアップする時がありますが、経験上、この資料が一番参考になると思う資料をご紹介します。

ご存知の方はご存知だと思いますが、こちらの資料を良く参照しています。

**The Active Directory Story**
http://www.ibm.com/developerworks/data/library/cognos/page64.html

以下に3章の目次を貼りましたが、以下のようなActive Directoryと連携させる場合の王道の構成の情報がしっかりとカバーされています。
CognosでActive Directoryと来たら、是非この記事を思い出し、この資料を参考にして下さい。
・LDAPネームスペースで認証を行う場合
・ADネームスペースで認証を行う場合
・ケルベロスSSO認証を行う場合
・NTLMでSSO認証を行う場合(下記目次の3.3.3のパターン)
・複数ドメインの場合
・複数フォレストの場合

**3章の目次**
3 IBM COGNOS REPORTNET AND IBM COGNOS 8 BI
3.1 AUTHENTICATION PROCESS
3.1.1 Application Start Up
3.1.2 Basic Sign On
3.1.3 Domain Failover
3.2 BIND USER CREDENTIALS
3.2.1 LDAP Provider
3.2.2 Active Directory Provider
3.3 SINGLE SIGN ON
3.3.1 Kerberos Prerequisites
3.3.2 Verification of the Prerequisites
3.3.3 Single Sign On Using REMOTE_USER
3.4 MULTIPLE DOMAINS
3.5 MULTIPLE FORESTS
3.6 CONFIGURING THE ACTIVE DIRECTORY PROVIDER
3.6.1 Standard Parameters
3.6.2 Advanced Properties
3.7 CONFIGURING THE LDAP PROVIDER
EMRを設定するときに注意すること

# EMRの設定をするときに考えること

- リージョン
- インスタンス（ガイドライン）
    - 数
    - サイズ
    - インスタンスタイプ
        - 汎用
        - コンピューティング最適化
        - メモリ最適化
        - ストレージ最適化
        - GPUインスタンス
    - ノードのタイプ
        - マスターノード
            - タスクの割当。貧弱でよい？
        - コアノード
            - CPU、メモリ、ストレージ必要
        - タスクノード
            - ストレージ不要
    - ストレージ
        - HDFS
        - EMRFS
    - ローカルストレージ
    - 購入方法
        - リザーブド
        - スポット
    - アクセス権限
        - IAM
    - ログ
        - Step logs
        - Hadoop および YARN コンポーネントログ
        - ブートストラップアクションログ
        - インスタンス状態ログ
    - VPC・サブネット
    - タグ
ダミーデータの作成

MySQLのテーブルに挿入するダミーデータを作成するプログラムをRubyでつくってみました

#### プログラム

```create_query.rb
# library

require 'date'

# method

def _increment_()
  count = 0
  Proc.new {count += 1}
end
increment = _increment_

def random_string(length)
  "\"" + (0...length).map { (65 + rand(26)).chr }.join + "\"" 
end

def random_number(length)
  (0...length).map { rand(10) }.join
end

def random_boolean()
  rand(2)
end

def current_datetime()
  "\"" + DateTime.now.strftime("%Y-%m-%d %H:%M:%S") + "\""
end

def setting_datetime(year, month, day, hour, minitute, second)
  "\"" + DateTime.new(year, month, day, hour, minitute, second).strftime("%Y-%m-%d %H:%M:%S") + "\""
end  

def space()
  " "
end

def comma()
  ","
end

def get_insert_statement(table_name, options = {})
  query = "INSERT INTO"
  query <<= space
  query <<= table_name
  query <<= space
  
  block_before_values = "("
  block_after_values = "("
  options.each { |key, value|
    block_before_values <<= key.to_s
    block_before_values <<= comma
    block_after_values <<= value.to_s
    block_after_values <<= comma
  }
  block_before_values = block_before_values[0..-2]
  block_after_values = block_after_values[0..-2]

  block_before_values <<= ")"
  block_after_values <<= ")"

  query <<= block_before_values
  query <<= space
  query <<= "VALUES"
  query <<= space
  query <<= block_after_values
  query <<= ";"

end

puts get_insert_statement("db_name.table_name", {
  "id": increment.call,
  "name": random_string(10),
  "money": random_number(7),
  "active_flag": random_boolean(),
  "created_at": current_datetime(),
  "update_at": current_datetime()                 
})
```

#### 実行方法

```
ruby create_query.rb
```

#### 実行結果

```
INSERT INTO db_name.table_name (id,name,money,active_flag,created_at,update_at) VALUES (1,"GSFTGBZLOH",6206719,0,"2017-03-08 16:20:07","2017-03-08 16:20:07");
```
cordova prepare でXcodeの -info.plistファイルを上書きされないようにする

# なぜ
cordovaベースでアプリを開発しているのですが、iOS用設定をするためにXcodeで直接パラメータを変更し、 -info.plistを更新している。
だけど、cordovaでビルドの準備をするための cordova prepareコマンドを使うと -info.plistが更新されてしまい困っていた。

# 方法
cordovaには[hook](https://cordova.apache.org/docs/en/6.x/guide/appdev/hooks/index.html)という仕組みがあり、様々なフックポイントに任意の処理を実行することができる。

その仕組みを使って、cordova prepareの前に -info.plistのバックアップをとり、cordova prepare後にそのバックアップを戻すという処理を入れ込んで上書きされないようにします。

```bash:scripts/backup-info-plist.sh
#!/bin/bash
# 更新前の-info.plistのバックアップを取る
cp platforms/ios/project_dir/*-Info.plist platforms/ios/project_dir/*-Info.plist.bk

```

```bash:scripts/restore-info-plist.sh
#!/bin/bash
# 更新後の-info.plistをバックアップに戻す
mv platforms/ios/project_dir/*-Info.plist.bk platforms/ios/project_dir/*-Info.plist

```

上記のスクリプトをbefore_prepareとafter_prepareのhookポイントで実行するようにconfig.xmlに以下を記載します。


```xml:config.xml
.
.
    <hook type="before_prepare" src="scripts/backup-info-plist.sh" />
    <hook type="after_prepare" src="scripts/restore-info-plist.sh" />
.
.

```

するとcordova prepareで更新する前の-info.plistを一旦バックアップし、prepare後にそのバックアップを元に戻すことで更新をさせないようにしました。


# あとがき
とりあえずはこの対応をすることでチームでXcodeの設定上をgitで共有した状態で開発を進められそうですが、cordovaを使ったチームを開発のベストプラクティスあれば知りたいっすー。(.gitignoreやXcodeの設定方法など〜）
[Gradle] Java 1.8.0_121以降でJavaScriptを含むJavadocを生成する

Gradleの`javadoc.options.bottom`等でJavaScriptを設定している方向けの内容です。

Java 1.8.0_121で、javadocコマンドはデフォルトでJavaScriptを許可しないようになりました。
http://www.oracle.com/technetwork/java/javase/8u121-relnotes-3315208.html
> The javadoc tool will now reject any occurrences of JavaScript code in the javadoc documentation comments and command-line options, unless the command-line option, --allow-script-in-comments is specified.

javadocタスクを実行するとエラーになります。

```
$ ./gradlew javadoc
[snip]
:javadoc
javadoc: error - Argument for -bottom contains JavaScript.
Use --allow-script-in-comments to allow use of JavaScript.
1 error
:javadoc FAILED

FAILURE: Build failed with an exception.
```

JavaScriptを有効にするには、上記エラーメッセージに記載されているように`--allow-script-in-comments`オプションを追加します。

```groovy:build.gradle
javadoc.options {
    def v = JavaVersion.current()
    def g = System.properties['java.version'] =~ /\d+/
    addBooleanOption '-allow-script-in-comments', v.java9Compatible || v.majorVersion == '8' && g.size() == 4 && ((g[2] as int) > 0 || (g[3] as int) >= 121)
}

```

`addBooleanOption`の第一引数には、オプションから先頭の`-`を除いたものを指定します。
第二引数には、オプションを設定するかどうかの`boolean`値を指定します。
1.8.0_121以前のJava環境で当該オプションを指定すると、javadocタスク実行時にエラーが発生するので、Javaのバージョンを見てオプションを設定するかどうかを判断しています。

以上です。

### 参考

Gradleのissue
https://github.com/gradle/gradle/issues/1393
`javadoc.options.addBooleanOption`の実装
https://github.com/gradle/gradle/blob/master/subprojects/language-java/src/main/java/org/gradle/external/javadoc/CoreJavadocOptions.java
https://github.com/gradle/gradle/blob/master/subprojects/language-java/src/main/java/org/gradle/external/javadoc/internal/JavadocOptionFile.java
https://github.com/gradle/gradle/blob/master/subprojects/language-java/src/main/java/org/gradle/external/javadoc/internal/BooleanJavadocOptionFileOption.java
効率の良いバイト文字列への変換手法

pyserialでシリアル通信するためのリストデータをバイト文字列に変換する処理が、
どうも遅い感じがしたので調べた結果をメモ。


###今までの実装
特に何も考えず、とりあえずバイト文字列が作れればいいやという単純なもの。

```python
    data = [ _ for _ in xrange(0, 10) ]
    byte_str = "".join([chr(x) for x in send_list])
    # byte_str => '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t'
```


###処理速度検証
別の実装方法を模索していた所、参考リンクにあるstackoverflowの記事に書かれていた
処理をテストしてみる事にした。
なお、pythonのバージョンは2系です。

```python
import time
import array
import struct

def main():
    # 計測用メソッド
    def measure_time(data, func):
        post = time.time()
        for _ in xrange(1000000):
            func(data)
        t = time.time() - post
        return t

    # バイト文字列変換メソッド(処理結果は全パターン同じです)
    bytearray_pattern = lambda x : str(bytearray(x))            # パターン1
    array_pattern = lambda x : array.array(b'B', x).tostring()  # パターン2
    struct_pattern = lambda x : struct.pack(b'B' * len(x), *x)  # パターン3
    join_pattern = lambda x : "".join([chr(_) for _ in x])      # パターン4(今までの処理)

    # テスト用リストデータ
    small_data = [ _ for _ in xrange(0,10) ]    # len=10
    huge_data = [ _ for _ in xrange(0,256) ]    # len=256

    # メイン処理
    proc_time = measure_time(small_data, bytearray_pattern) # proc_time:1.18099999428
    proc_time = measure_time(small_data, array_pattern)     # proc_time:0.874000072479
    proc_time = measure_time(small_data, struct_pattern)    # proc_time:0.784999847412
    proc_time = measure_time(small_data, join_pattern)      # proc_time:1.72000002861
    proc_time = measure_time(huge_data, bytearray_pattern)  # proc_time:5.57999992371
    proc_time = measure_time(huge_data, array_pattern)      # proc_time:11.3169999123
    proc_time = measure_time(huge_data, struct_pattern)     # proc_time:11.0810000896
    proc_time = measure_time(huge_data, join_pattern)       # proc_time:32.9349999428

main()
```

###結果
送信するデータ数が多い場合は、パターン1の`str(bytearray(list)`を使うのが良さそう。
また、データ数が少ない場合は、パターン2やパターン3のほうが速くなる場合もある模様。(誤差っぽいですが)

とりあえず確実に言える事は「パターン4だけは無い」という事ですかね・・・(反省)



###参考リンク
http://stackoverflow.com/questions/3470398/list-of-integers-into-string-byte-array-python
Playストアのオープンベータ機能の挙動が変わった

2016年9月ごろに早期アクセス機能とオープンベータが統合されて挙動が変わっていたようで、ちょっとびっくりしたので調べた内容を残しておきます。

オープンベータ（オープンアルファ）の古い挙動を期待して、検索してきただけの人にはインストールできないから大丈夫、という運用をしている方は見直しをご検討ください。

過去に提供されていたオープンベータ機能
----------

![スクリーンショット 2017-03-08 14.07.10.png](https://qiita-image-store.s3.amazonaws.com/0/2276/07659ee1-4073-fa65-6c84-b24d220acace.png "スクリーンショット 2017-03-08 14.07.10.png")

「 **所定のリンクから** 誰でも参加できる一般公開テストを実施します。」

2015年の夏に公開されたオープンベータ機能はこんな感じでした。

* [GoogleのAndroidアプリのベータテストの更新で、Google+への登録が必要なくなる | TechCrunch Japan](http://jp.techcrunch.com/2015/07/31/20150730another-nail-in-the-googleplus-coffin/)

オプトイン用のURLを踏んで、リンク先で「テスターになる」のボタンを押したユーザーだけがアプリをダウンロードできる、というスタイルです。

![スクリーンショット_2017-03-08_14_34_54.png](https://qiita-image-store.s3.amazonaws.com/0/2276/0170ddd7-6053-3eda-78ce-9bdf845f0373.png "スクリーンショット_2017-03-08_14_34_54.png")

オプトインURLはパッケージ名から推測可能なので、部外者のアクセスを防げるものではないですが、ただ検索してきただけの（オーガニックな）人はオープンベータ版をインストールできない挙動になっていたので、こっそりと友達の友達くらいの範囲で触ってもらったりするにはいいバランスになっていました。

現在提供されているオープンベータ機能
----------

![スクリーンショット 2017-03-08 10.29.53.png](https://qiita-image-store.s3.amazonaws.com/0/2276/924f1a2f-3d50-e670-1be1-ce3025bc57ff.png "スクリーンショット 2017-03-08 10.29.53.png")

『所定のリンクや **Google Play上のアプリの掲載情報から** 誰でも参加できる一般公開テストプログラムを実施します」

オープンベータ公開に設定してあるアプリが、ベータテスターではない人の検索結果に引っかかり、かつインストールも可能な状態になっています。

![Screenshot_2017-03-08-09-26-43.png](https://qiita-image-store.s3.amazonaws.com/0/2276/6334ff13-0c1d-d625-ec88-c1ecafd90e95.png "Screenshot_2017-03-08-09-26-43.png")

早期アクセス版という名前で公開されているようです。

* [Google、Google Playストアでアプリの早期アクセス版を配信できるプログラムへの申請プロセスを一般の開発者に公開 | juggly.cn](http://juggly.cn/archives/200063.html)

公式ドキュメントにも言及がありました。

* [アルファ版 / ベータ版テストの設定 - Google Play デベロッパー ヘルプ](https://support.google.com/googleplay/android-developer/answer/3131213?hl=ja)

> オープン ベータ版テストを設定すると、Play ストアにベータ版アプリが表示されます。このテストは、アプリが Play ストアで公開できる状態になってから実施してください。
> 
> * **早期アクセス版アプリ（製品版が公開されていない新しいアプリ）の場合**: ベータ版であっても Google Play で検索でき、ストアの掲載情報から通常のアプリと同じようにインストールできます。
> * **公開中の製品版アプリの場合**: ユーザーはストアの掲載情報からベータ版テストに参加できます。
> 
> また、ウェブサイトやメールで URL リンクを共有し、ベータ版アプリをダウンロードしてもらうこともできます。

というわけで、製品版なしでオープンベータを設定すると、事実上製品版を公開したのと同じような状況になります。

この挙動変更ってアナウンスありました！？という気持ちになっているのですが、[インターネット・アーカイブを掘り返したら](http://web.archive.org/web/20160921174539/https://support.google.com/googleplay/android-developer/answer/3131213?hl=ja)、[公式ブログ](https://android-developers.googleblog.com/2016/09/the-power-of-early-access.html)（[和訳](https://developers-jp.googleblog.com/2016/09/the-power-of-early-access.html)）と同時期の9月にキッチリ更新されていまして、ぐうの音も出ないのです。

ただ、公式ブログでは早期アクセスについては言及してる一方で、オープンベータとの絡みは言及されてないんですよねえ。ちょっと腑に落ちない感じでした。

まとめ
----------

大規模なグループでテストを実施したいけどPlayストアでオーガニック検索してきた人たちにまで入ってきてほしいわけではない、くらいの微妙な立ち位置でテストをしたい場合の選択肢がいつの間にかなくなっていました。（何か代わりに良いサービスがあればどなたか教えてください）

面倒がらずにクローズドテストにしてユーザーのメールアドレスをちゃんと集めるのがよさそうです・・・
[memo] Linuxファイル・検索・置換系コマンド (grep,find,sed ..etc)

## make Symbolic Link: シンボリックリンクの作成
シンボリックリンクの作成

```
$ ln -s <filepath> <linkname>
```
現在のパスの表示

```
$ pwd         :シンボリックリンクをそのまま表示
$ pwd -P　　　：シンボリックリンクをたどる
```

## Replace strings for files :一括文字列置換
non git
`$ find . -type f -print0 | xargs -0 sed -i -e 's/foo/bar/g'`
git directory
`$ git ls-files -z | xargs -0 sed -i -e 's/foo/bar/g'`

<補足:"print0|xargs -0">
http://qiita.com/maskedw/items/2dfdf6fa7eee991ddc45
>xargsが空白文字でなくヌル文字を区切りとして扱うように-0を指定し、
>xargsの形式に合わせるためにfindの-print0を指定する

**Replace URL:URLの置換**
replace http://OLDURL > http://NEWURL
`# find -type f | xargs grep -l 'http://OLDURL'|xargs sed -i "s,http://OLDURL,http://NEWURL,g"`

## Find "string" under current directory :
` $find -type f|xargs grep -l "string"`
Option -l : only file name

## Find recently updated file : 最近更新したファイル
` $ find -type f -mtime -1|xargs ls -l`

Option -mtime : -1= 1day before
プレミアムフライデーを求める関数(JavaScript)

うちの会社では導入されなかった[プレミアムフライデー](https://ja.wikipedia.org/wiki/プレミアムフライデー)を求める関数を作ってみました。

# コード
対象の翌月から1日引いて対象月の最終日を取得。
最終日が何曜日なのかを判定し、金曜日になるように日数を減算して完了
※ 86400000 = 1000*60*60*24

```javascript:premium.js
function premium(year, month) {
  const d = new Date(new Date(year, month, 1) - 86400000);
  const w = d.getDay();
  const n = 5 <= w ? w-5 : w+2;
  return new Date(d - n * 86400000);
}
```

# 最後に
ただライブラリ無しでやってみたかっただけでした。

# 追記
コメントで頂いたもっとかっこいい書き方

```javascript
function premium(year, month) {
    const d = new Date(year, month, 0);
    const w = d.getDay();
    return new Date(year, month, -(w+2)%7);
}
```
MSP430 > I2C > ソフトウェアI2Cでの実装 > SDAの方向制御のタイミング

```txt:動作環境
MSP430
Tektronix TDS 2024C (200 MHz, 2GS/s)
とあるI2Cセンサ
```

とあるセンサのプロトコルは以下に記載。
http://qiita.com/7of9/items/d839e67c6650e012a8fd

### code v0.1

MSP430でのソフトウェアI2Cで実装し、それらしいデータを読み取れる（波形がくずれない）ことを確認できたコードのsnippetは以下。

```c
    int loop;
    // Raspberry Piで動作確認した状況を再現してみる (2017/03/08)

    // 1. 準備
    SDA_0_DIROUT;
    SCK_0_DIROUT;
    SDA_0_HIGH;
    SCK_0_HIGH;
    myDelay();
    myDelay();
    myDelay();

    // 2. start condition
    SDA_0_LOW;
    myDelay();
    SCK_0_LOW;
    myDelay();

    // 3. slave address
    char slvAdr = 0x28;
    bool bitVal;
    for(loop=0; loop<7; loop++) { // 7bit
        bitVal = (slvAdr & 0x40);
        SCK_0_LOW;
        if (bitVal) {
            SDA_0_HIGH;
        } else {
            SDA_0_LOW;
        }
        myDelay();
        SCK_0_HIGH;
        myDelay();
        slvAdr <<= 1;
    }

    // 4. Read-bit
    SCK_0_LOW;
    SDA_0_HIGH; // for read-bit
    myDelay();
    SCK_0_HIGH;
    myDelay();

    // 5. read ACK (ACK=0)
    SCK_0_LOW;
    SDA_0_DIRIN;
    myDelay();
    SCK_0_HIGH;
    bool isAck = is_SDA_0_High(); // read ACK
    myDelay();

    // 6a. read 1st data
    for (loop=0; loop<8; loop++) {
        SCK_0_LOW;
        if (loop == 0) {
            SDA_0_DIRIN;   
        }
        myDelay();
        SCK_0_HIGH;
        // TODO: read bit
        myDelay();
    }
        
    // 6b. send ACK (ACK=0)
    SCK_0_LOW;
    SDA_0_DIROUT;
    SDA_0_LOW; // ACK
    myDelay();
    SCK_0_HIGH;
    myDelay();
        
    // 7a. read 2nd data
    for (loop=0; loop<8; loop++) {
        SCK_0_LOW;
        if (loop == 0) {
            SDA_0_DIRIN;   
        }
        myDelay();
        SCK_0_HIGH;
        // TODO: read bit
        myDelay();
    }

    // 7b. send NAK (NAK=1)
    SCK_0_LOW;
    SDA_0_DIROUT;
    SDA_0_HIGH; // NAK
    myDelay();
    SCK_0_HIGH;
    myDelay();
        
    // 8. stop condition
    SCK_0_LOW;
    SDA_0_LOW;
    myDelay();
    SCK_0_HIGH;
    myDelay();
    SDA_0_HIGH;
    myDelay();
```

以下はマクロで組んでいるが、実コードでは再検討が必要。

- SCK_0_LOW : SCKラインをdeassert
- SDA_0_LOW : SDAラインをdeassert
- SCK_0_HIGH : SCKラインをassert
- SDA_0_HIGH : SDAラインをassert
- SDA_0_DIRIN : SDAラインを入力方向に
- SDA_0_DIROUT : SDAラインを出力方向に

myDelay()においては`__delay_cycles(8);`を使用し、delayを行う。

### はまった点

SDA_0_DIRIN とSDA_0_DIROUT を実行するタイミング。
これが失敗すると、データ読み出しクロックにおいて、SDAラインがHレベルのままとなったり、奇数回目の通信において波形がくずれるなどの症状が見られた。

上記のコードにおいては「SCKラインがdeassertの時に入出力方向を変更」として一貫性を持たせている。

![F0001TEK.png](https://qiita-image-store.s3.amazonaws.com/0/32870/fdaba474-c089-0e53-0c20-ddd9a1e0af8c.png)

入出力方向の切替時にglitchは見られる。
関連 http://electronics.stackexchange.com/questions/286564/i2c-ack-bit-glitch
[Unity] SetPassを減らす-Sprite Packer- テクスチャーを一つにまとめて

Unityのパフォーマンスについて、いつもSetPassというキーワードが出てくる。
<img width="312" alt="setpass.png" src="https://qiita-image-store.s3.amazonaws.com/0/124698/9533ad96-f1e3-3420-0c77-a9769a0f8a40.png">
SetPassは低ければ低いほどいい、これを減るにはいろんな方法がある。
その一つはテクスチャーだ。

違うテクスチャーごとにSetPassが上がる、だから一つのテクスチャーにまとめとSetPassが減る。
詳しく使う方法は：
[【Unity開発】Sprite画像とSprite Packerまとめ【ひよこエッセンス】](http://hiyotama.hatenablog.com/entry/2015/05/11/142628)
[Unity Tutorial: Sprite Packer](https://youtu.be/Pj8Y48ecBZY)

肝心なのはテクスチャーセッティングの　Packing Tag
![image](https://qiita-image-store.s3.amazonaws.com/0/124698/1e6a9319-a9cf-fecc-60c6-5392f9e4e279.png)
全部同じIDを指定した後
Window　－＞　Sprite Packer を開いて
![image](https://qiita-image-store.s3.amazonaws.com/0/124698/a383d389-380a-4882-58ec-9bdd4698dc34.png)
まとめたいテクスチャーを全部選択して　Pack をクリックして完成
![image](https://qiita-image-store.s3.amazonaws.com/0/124698/3c584487-00d9-4c8e-1519-d0f24d05a9a6.png)

以上は直接に図をSpriteRenderでシーンに入れる時、そして実行する後からSetpassが低くなる、エディター状態ならまだ同じ。
ちなみに、unityのcanvasを使う場合は、setpassは増加しない、裏で何かやってるみたい。

では、”すべてのテクスチャーを一つにまとめればいい”か、それはそうでもない。
同じテクスチャーにすると、当然メモリコストが上がる。
もし小さいな部分だけ使いたい場合、まとめたテクスチャーを使うと無駄なメモリが消費する、普通は一緒に使うテクスチャーだけをまとめる。
s3fs-fuseをインスコしようとして、util-linuxのバージョンアップを勧められた

備忘録です。

## s3fs-fuseをインスコしようとしたところ、fuseのバージョンが0.0.1低かった:cloud:

「Requested 'fuse >= 2.8.4' but version of fuse is 2.8.3」

[こちら](https://github.com/libfuse/libfuse/releases)から、libfuse3.0.0がtar.gzで取得してインスコ

## fuse3.0.0をインスコしようとしたところ、util-linuxのバージョンが0.01低かった:cloud:

```shell-session

root@localhost /usr/local/src/fuse-3.0.0
$ ./configure

~ ~ ~

******************************************************************
* Please install util-linux version 2.18 or later which supports *
* --fake and --no-canonicalize options in mount and umount       *
******************************************************************

root@localhost /usr/local/src/fuse-3.0.0
$ yum list installed | grep util-linux
util-linux-ng.x86_64                   2.17.2-12.24.el6_8.3          @updates

```

**これ、素直に、util-linuxの2.18以上をインスコして『yum erase util-linux』とか打っちゃだめです**:raised_hand_tone1:
（開発用VMでやりました。php-fpmやnginxが消えていきました・・・）

なんか、[気にしなくていいメッセージみたい](http://www.linuxfromscratch.org/blfs/view/svn/postlfs/fuse.html)です。