OmniAICreator/Qiita-1.07M huggingface dataset:
Raspberry Pi と安価なWebカメラで静止画を撮影する

# この記事は？
Raspberry Pi には純正のカメラモジュールがありますが、微妙にお値段高いですよね。
USB接続のWebカメラのほうが安価ですし、入手性もいいですし、それにRaspberry Pi以外の機械にも流用が効くので、USBカメラのほうが便利な気がします。
ということで、今回はUSB接続の安価なWebカメラを使用して静止画を撮影しよう、と言うシンプルな内容です。

# 環境
## 使用する機器
- Raspberry Pi (機種は問わず)
  - OSは最新版(stretch)を使用します
- Webカメラ
  -  zoomするときに使うようなUSB接続のWebカメラであればなんでも大丈夫だと思いますが、今回は [Buffalo BSW200MBK](https://www.buffalo.jp/product/detail/bsw200mbk.html) を使用します。実売価格2,000円くらいです。

## 事前準備
- Raspberry Pi にOSをインストールします。
- とりあえず `sudo apt-get update` `sudo apt-get upgrade` しておきます
- Raspberry Pi のUSBポートにWebカメラを接続します

## 追加でパッケージをインストール
今回使用するパッケージを追加でインストールしておきます。

```bash
$ sudo apt-get install v4l-utils fswebcam
```

## カメラの接続確認
`lsusb` を実行して、カメラ（らしきもの）が認識されていることを確認します   
下記例では `KYE Systems Corp. (Mouse Systems) Genius WideCam F100` が認識されているカメラです。
```bash
$ lsusb
Bus 001 Device 005: ID 0458:708c KYE Systems Corp. (Mouse Systems) Genius WideCam F100
Bus 001 Device 004: ID 8086:0808 Intel Corp.
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```

`v4l2-ctl --list-devices` を実行し、カメラのデバイスが存在することを確認します。   
下記例ではUSBカメラが `/dev/video0` として認識されています。

```bash
$ v4l2-ctl --list-devices
USB_Camera: USB_Camera (usb-3f980000.usb-1.5):
        /dev/video0
```

# 実際に試してみる

## 静止画を撮影する
静止画の撮影は `fswebcam` コマンドを実行します。コマンド一発でOKです。

```bash
$ fswebcam -r 1920x1080 hoge.jpg
```

撮影した静止画が `hoge.jpg` として保存されます。

## 上記コマンドで撮影できない場合
上記コマンドで撮影したつもりが、真っ黒・真っ白な画像になってしまう場合があります。
カメラにオートフォーカスや絞り自動調整機能が付いているような場合、`fswebcam` コマンドを実行してカメラが起動されるタイミングで調整が始まります。この自動調整が終わる前に画像を取得してしまうのが原因のようです。
そのような場合は、`-S` `-D` パラメータで調整します。

```
$ man fswebcam
-----(中略)-----
       -S, --skip <number>
              Set the number of frames to skip. These frames will be captured but won't  be
              use.  Use this option if your camera sends some bad or corrupt frames when it
              first starts capturing.
 
              Default is "0".
 
       -D, --delay <delay>
              Inserts a delay after the source or device has been opened  and  initialised,
              and  before the capture begins. Some devices need this delay to let the image
              settle after a setting has changed. The delay time is specified in seconds.
-----(中略)-----
```

`-S` `--skip` は、指定の回数だけ空撮影してから本撮影を行う。
`-D` `--delay` は、カメラをオープンしてから指定の秒数待ってから撮影を行う。
...という意味です。
tensorflow 重みの更新について 

##Deep Learning 重みの更新について
今回は私がtensorflowでDeep Learningのコードを書いていた際に困った重みの更新についての問題について書きたいと思います。

今回起きた問題は以下のようなものです。

<img width="139" alt="スクリーンショット 2019-05-24 13.44.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423140/0bd95503-5fe6-a86a-ed34-df938c687fe0.png">

epoch数が8000回前半で学習がやや落ちていき、その後学習が出来なくなると行ったものです。
初めは学習回数が多いため、メモリがいっぱいになったことが原因であると考えましたが学習を分割して行なった際も同じ現象が起きたためメモリの問題でないことは分かりました。

・分割した時の結果
<img width="149" alt="スクリーンショット 2019-05-24 14.21.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423140/d77d3990-0e3b-8cc0-586f-291d85a6f882.png">


次に考えたのは重みの更新が間違っているのではないかと考えました。
重みに正しい値が入らないことによって学習が出来なくなることを防ぐために重みの更新の部分のコードを以下のように訂正しました。

・訂正前

```
tf.log(output)
```

・訂正後

```
tf.log(tf.clip_by_value(output,1e-10,1.0))
```

訂正前のものでは重みの値の範囲が指定されていないため重みの値に正しくない値が入ってしまうことがあります。
しかし、訂正後のものでは重みの値に範囲を指定しているため重みに正しくない値が入ることを防ぐことが出来ます。
訂正後の結果は以下のようになった。

<img width="139" alt="スクリーンショット 2019-05-24 14.19.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423140/a249f6ef-b21b-55b6-33a0-ba2db17b7c2e.png">

この結果の画像だけでは信憑性に欠けますが、重みの値を更新する際に範囲を指定することによって途中で学習が出来なくなることはなくなりました。

使っている教材としてオライリー・ジャパンのDeep Learningシリーズや初めてのtensorflowなどを使用しています。
Conoha の VPS にシリアルで接続

Conoha の VPS がうまく立ち上がらなくなった時の対応です。

私は、5.1.3-arch1-1-ARCH　から、5.1.4-arch1-1-ARCH
にあげた時に、サーバーが応答しなくなりました。

そこで、まずシリアルで接続してみました。
まだ、問題の解決方法は見出していません。

1) https://manage.conoha.jp/Dashboard から、コンソールを立ち上げます。

![conoha_may2401.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/f1c98ac6-9412-4df0-8db8-cd009fbda46f.png)

2) テキスト送信の右のコンソールをクリック
![conoha_may2402.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/12f0a56c-e12f-e5e8-2084-84d47f45eab0.png)

3) シリアルをクリック
![conoha_may2403.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/5d832c32-0ec7-0b9e-052a-8f257f4dbab6.png)

4) ルートのプロンプトが出てきます。
![conoha_may2404.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/17b869eb-315f-8ee8-8d14-793dbba2374e.png)

5) コマンドを入れてみます。

```text
[rootfs ]# uname -a                                                                              
Linux archlinux 5.1.4-arch1-1-ARCH #1 SMP PREEMPT Wed May 22 08:06:56 UTC 2019 x86_64 GNU/Linux  
[rootfs ]# pwd                                                                                   
/                                                                                                
[rootfs ]# ls                                                                                    
VERSION         etc             lib64           sbin                                             
bin             hooks           new_root        sys                                              
buildconfig     init            proc            tmp                                              
config          init_functions  root            usr                                              
dev             lib             run             var                                              
[rootfs ]# df                                                                                    
Filesystem           1K-blocks      Used Available Use% Mounted on                               
dev                     496764         0    496764   0% /dev                                     
run                     504240         4    504236   0% /run                                     
[rootfs ]#
```

6) ネットワークは使えません。

```text
# ip addr                                                                               
1: lo: <LOOPBACK> mtu 65536 qdisc noop qlen 1000                                                 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 
```

7) 問題解決のヒント
次が問題解決のヒントになりそうなのですが、まだ解決に至っていません。

```text
ERROR: device 'UUID=78985e03-71ce-4190-9a64-2754bf549ca3' not found. Skipping fsck.              
mount: /new_root: can't find UUID=78985e03-71ce-4190-9a64-2754bf549ca3.
```
JavaScriptのDOM操作で行うアラート表示をまとめてみた

###hrefでJavaScriptを動かしてアラートを出す方法

１．htmlで下記のコードを記述

```index.html
    <a href="Javascript:window.alert('OK')">アラート</a>
```

２．ブラウザで「アラート」をクリックすると、下記のようにアラート表示されます。
<img width="702" alt="スクリーンショット 2019-05-24 13.58.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314346/73b2ae61-f817-a3e8-dc01-8a92cfdd3728.png">

###DOM操作でfunctionを動かしてアラートを表示させる方法

１．任意のidを指定する

```index.html
  <button id="alertbtn">ボタン１</button>
```

２．jsファイルでfunctionのコードを記述

```app.js
window.onload = function(){
  document.getElementById('alertbtn').onclick = function(){
    window.alert('ボタン１が押されました');
  }
}
```

window.onload
↑ページがロードされたら function(){} の中の処理を実行します。

getElementById()
↑idプロパティが指定された文字列にアクセスします。この場合は、 index.htmlに記述されたidの値である"alertbtn" にアクセスしています。

.onclick
↑index.htmlの「ボタン１」がクリックされたときの動作を定義します。

「ボタン１」押すと、結果は下図のようになります。
<img width="702" alt="スクリーンショット 2019-05-24 14.25.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314346/f92d580a-0c6d-9e99-dce8-c236c7c17ce8.png">

###イベントハンドラを使用したアラート表示
上記の操作を踏まえた上でイベントハンドラを用いて記述すると、
簡潔なコードになります。

1.htmlファイルでDOMイベントを記述

```index.html
  <button onclick="btn_click()">ボタン２</button>
```

2.jsファイルでアラートメッセージを記述

```app.js
function btn_click(){
  window.alert('ボタン２がクリックされました');
}
```
結果
<img width="702" alt="スクリーンショット 2019-05-24 14.28.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314346/cc8f0673-902f-4dbc-c989-14228e1cd59b.png">


###参考サイト
イベントハンドラ解説
https://wa3.i-3-i.info/word11493.html

DOMイベント一覧
https://so-zou.jp/web-app/tech/programming/javascript/event/handler/
アクションシートを表示する

<img width="337" alt="スクリーンショット 2019-05-24 14.28.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325764/a67618d1-f277-d3f2-3d25-2057f8f5473b.png">:point_right_tone1: <img width="338" alt="スクリーンショット 2019-05-24 14.28.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325764/35aacb69-56a5-77f6-733d-6b6e2ec60735.png">

```
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    @IBAction func tapAlert(_ sender: Any) {
        //アクションシートを作る
        let alert = UIAlertController(title: "タイトル", message: "メッセージ", preferredStyle: .actionSheet)
        
        //ボタン1
        alert.addAction(UIAlertAction(title: "追加する", style: .default, handler: nil))
        
        //ボタン２
        alert.addAction(UIAlertAction(title: "さらに追加する", style: .default, handler: nil))
        
        //消去する
        alert.addAction(UIAlertAction(title: "消去する", style: .destructive, handler: nil))
        
        //ボタン３
        alert.addAction(UIAlertAction(title: "キャンセル", style: .cancel, handler: nil))
        
        //アクションシートを表示する
        self.present(alert, animated: true, completion: nil)
        
    }
    

}

```
以上です。
初めてSlack APIを使った(google spread sheetとの連携)

APIとは…トークンとは…

みたいな状態からSlackのAPIを叩いて云々するGoogle spread sheetが作れたのでそのときに得た知見をまとめます。

Web開発初心者だけどなんかやってみたいみたいな人の参考になれば幸いです。


# そもそもWebAPIとは?
辞書的な定義とは少し違いますが、ウェブサービスにおけるAPIとは、**他の外部サービスから、そのウェブサービスの情報を利用するための機能**と考えるといいと思います。

例えば、あるサービスの自分の利用状態とか、グループの活動とかを保存したいとかグラフ化したいなんてときに利用できます。

# どうやって利用するの？
基本的にアドレスとして利用します。例えばSlackの場合であれば、

```
http://[自分のワークスペース]/api/[使いたいwebapi]?[オプション]&[オプション]&...
```

のような形で記述すると、その戻り値が返ってくるわけです。

# トークンとは?

APIを利用するときにはセキュリティの観点から、何らかの登録のような物が必要となります。その認証に使う鍵のようなものがトークンです。Slackの場合にはSlack APIのページから取得することになります。

https://qiita.com/ykhirao/items/3b19ee6a1458cfb4ba21

↑こちらのページがわかりやすいです。

SlackのAPIは安全のため権限を指定して許可したトークンを作成します。
権限はPermissionsのページで確認できます。
このときtokenにどの権限を渡したらいいかは使うAPIによります。
まずどんなAPIがあるかは
https://api.slack.com/methods
↑のリファレンスで確認しましょう。この中の、例えばchannels.archiveを例に取ると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244678/c2f7f6ba-ebd2-39a1-5da7-37adae34b874.png)

required scopeに必要な権限がかいてあります。ちなみにその上のrate limitingは一分間に何回までこの機能を使っていいかの頻度制限です。

使いたい機能に必要な権限をもったトークンを生成したら対象のワークスペースにインストールしましょう。

# いざAPIを使う

Google app scriptからslack APIを使用すると、自前でサーバーを用意しなくてもgoogleさんのサーバーによって定期的な実行ができるという利点があります。これからはchannels.historyを例にします。

まずgasでSlack APIを使うにはUrlFetchApp.fetch([url])を使用します。[url]部分にAPIを使用するアドレスを渡します。たとえば、channels.historyなら

```
https://[ワークスペース]/api/channels.history?token=[トークン]&channel=[チャンネルID]&count=1000
```

みたいな感じです。channel IDはブラウザでチャンネルを開いたときの最後の部分です。count=1000は最大1000件まで取得しますよというだけです。

そしたらこの返り値はJSON形式のテキストになってるので、JSON.perse()などでいい感じに処理します。
まとめるとこんな感じです。


```js
var url = "https://[ワークスペース]/api/channels.history?token=[トークン]&channel=[チャンネルID]&count=1000";
var res=UrlFetchApp.fetch(url);
var txt = res.getContentText("UTF-8");
var histories = JSON.perse(txt);
```

https://qiita.com/KanaSakaguchi/items/fbfe6cd41ccc0a0b55bf
↑具体的には返ってくるJSONはこんな感じになっているようです。感謝。

JSONの分割までできたら後は煮るなり焼くなり好きなように…
GASの時間トリガーとか利用するのもいいですね。

# おわりに
公式のドキュメントがいかんせん情報量が多くて日本人には辛い上に、日本語の情報も超初心者に向けたようなものはあまりない状態なのでまとめてみました。結構いろいろなことができて楽しいです。
[Ruby] fizzbuzzの複数コード紹介

# 概要
fizzbuzz問題はいろんな解法があるな、と思ったので少しまとめ。
今回、３つのパターンを紹介しますが、結果はどれも同じになります。

# パターン１

```ruby
i = 1
while i <= 30
  if i % 15 == 0
      puts "FizzBuzz"
  elsif i % 3 == 0
      puts "Fizz"
  elsif i % 5 == 0 
      puts "Buzz"
  else
      puts i
  end
  i += 1
end
```
素直につくったらこうなりますよね。
数字を配列にせず、1を変数に代入したあと、繰り返しのなかで自己代入演算子を用いてひとつずつ数字を増やしていくパターンです。

# パターン２
```ruby
num = 1
while num <= 30 
  str = ""
  if num % 3 == 0
    str = str + "fizz"
  end
  if num % 5 == 0
    str = str + "buzz"
  end
  if str == ""
    str = str + num.to_s
  end
  puts str
  num += 1
end
```
こちらはelsifを使わないスタイルです。
空の変数を宣言し、各条件に応じてその変数に文字や数値を付け足しています。

# パターン３
```ruby
(1..30).each do |i|
 number = ""
 number = "fizz" if i % 3 == 0
 number << "buzz" if i % 5 == 0
 number = i unless i % 3 == 0 || i % 5 == 0
 puts number
end
```
こちらは範囲になっているので、eachで繰り返しを行なっています。
それ以外はパターン２に似ていますが、文字列と数値をくっつけることを避けているため、to_sメソッドを使わずに済みました。

ただ、unlessはあまり使いたくないですね。

#まとめ
私ごとですが、はじめパターン１の方法でfizzbuzz問題を解き、その模範回答がパターン２だったので、それを改良した（つもり）パターン３をつくりました。

もっとおすすめのfizzbuzzコードがあれば教えていただきたいです。

#追加
コメントより教えていただいたパターンを追加します。

```ruby
puts (1..30).map {|n|
  case [n % 3, n % 5]
  in [0, 0] then 'FizzBuzz'
  in [0, _] then 'Fizz'
  in [_, 0] then 'Buzz'
  else n
  end
}.join "\n"
```
ruby 2.7にするとパターンマッチングがつかえるようになりました。
アラートの表示

![ezgif.com-optimize.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325764/d9477194-aef9-c8ab-0f82-4d40093c47e2.gif)


iOSアプリを作成していく中で必須のアラートの作り方について説明していきます。

```
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    @IBAction func tapAlert(_ sender: Any) {
        //アラートを作る
        let alert = UIAlertController(title: "タイトル", message: "メッセージ", preferredStyle: .alert)
        
        //ボタン1
        alert.addAction(UIAlertAction(title: "追加する", style: .default, handler: nil))
        
        //ボタン２
        alert.addAction(UIAlertAction(title: "さらに追加する", style: .default, handler: nil))
        
        //消去する
        alert.addAction(UIAlertAction(title: "消去する", style: .destructive, handler: nil))
        
        //キャンセルボタン
        alert.addAction(UIAlertAction(title: "キャンセル", style: .cancel, handler: nil))
        
        //アラートを表示する
        self.present(alert, animated: true, completion: nil)
    }
}
```
以上です。
https://github.com/matushinn/AlertController
UIWebViewでよく使うデリゲートメソッド一覧(Swift)

## UIWebViewでよく使うデリゲートメソッド一覧

### webView(_:shouldStartLoadWith:navigationType:)

__概要__
ロードの開始前に呼ばれる
ロードするかどうか
`false` を返すとロードしない

__用途__
特定のURLの場合にロードしないようにする、など

```swift:FooViewController.swift
import UIKit

final class FooViewController: UIViewController, UIWebViewDelegate {

    func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool {
        if let url = request.url?.absoluteString, url.lowercased() == "https://example.com".lowercased() {
            return false
        }
        return true
    }

}
```

### webViewDidFinishLoad(_:)

__概要__
ロードの完了後に呼ばれる

__用途__
インジケータを消す場合、など

```swift:FooViewController.swift
import UIKit

final class FooViewController: UIViewController, UIWebViewDelegate {

    @IBOutlet private weak var indicatorView: UIActivityIndicatorView!

    func webViewDidFinishLoad(_ webView: UIWebView) {
        self.indicatorView.stopAnimating()
    }

}
```

### webView(_:didFailLoadWithError:)

__概要__
ロード時にエラーが発生した場合に呼ばれる

__用途__
エラーハンドリング
インジケータを消す場合、など

```swift:FooViewController.swift
import UIKit

final class FooViewController: UIViewController, UIWebViewDelegate {

    @IBOutlet private weak var indicatorView: UIActivityIndicatorView!

    func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
        self.indicatorView.stopAnimating()
    }

}
```
js.erbファイルにコメントを書くときは//を使わない

# 修正前
```js:index.js.erb
// コメントが見えてるよ！
$("#ajax_panel").html("<%= escape_javascript(render partial: "ajax_panel") %>");
```

# 結果
ツールを使ってファイルを見ると...
(画像はChromeのデベロッパーツールのNetworkパネルから確認)
![スクリーンショット 2019-05-24 14.01.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237203/bdc6ab0f-6abf-0e96-988b-82962bde65ad.png)

コメントに重要な内容が含まれていると、敵の攻撃を手助けしてしまう可能性があり危険です。

# 修正
erbファイルのコメントの書き方に修正します。

```js:index.js.erb
<%# コメントが見えないだと... %>
$("#ajax_panel").html("<%= escape_javascript(render partial: "ajax_panel") %>");
```

# 修正後
コメントが表示されなくなりました。
![スクリーンショット 2019-05-24 14.04.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237203/78f2f652-9cd4-8f90-bd0e-6dcb1ac96ea9.png)
iOS12.2よりdevicemotion, deviceorientationがデフォルトで取得できなくなったことと、その検知方法


iOS12.2より、safariに「モーションと画面の向きのアクセス」項目が追加され、デフォルトでOFFの状態となったため、devicemotionイベント等を取得することができなくなりました。

### 設定はどうやって変えるの？
設定＞Safariから「モーションと画面の向きのアクセス」項目が追加され、デフォルトでOFF
をONにすることで


### どうやって検知したらいい？
ググると

```javascript
if('ondevicemotion' in window) {}
```

的なコードが出てくるんですが、実際にiOS12.2の設定をOFFにしていても検知してくれません。

```javascript
const id = setTimeout(() => {
                 //ここに動かない時にさせたい挙動を書く
             }, 500);
             window.addEventListener('devicemotion', (e) => clearTimeout(id));
```

このようなコードをかくことで、
つまり、デバイスオリエンテーションイベントが発生したときにタイマー処理をしているものをクリアしてキャンセル=>動かない時だけsetTimeout()の中身が実行される、ということができるようです。

### 参考
https://www.macrumors.com/2019/02/04/ios-12-2-safari-motion-orientation-access-toggle/
https://github.com/w3c/deviceorientation/issues/57#issuecomment-481039307
【Django】renderとreverse_lazyの使い分けについて

#概要
Djangoでアプリ作成のときに、`render`と`reverse_lazy`の違いがわからなかったので、備忘録として書きます。

#TemplateView or Function
結論からいうと、`reverse_lazy`は`TemplateView`で使い、`render`は`function`で実装する場合に使用します。

下記にて、投稿サイトをイメージした例になります。

- `PostClass`と`listfunction`に注目してください
 
```python:myapp/models.py
from django.db import models

class PostModel(models.Model):
    title = models.CharField(max_length=50)
    memo = models.TextField()
```

```myapp/views.py
from django.views.generic import CreateView
from django.urls import reverse_lazy
from .models import PostModel

class PostClass(CreateView):
    template_name = 'post.html'
    model = PostModel
    fields = ('title','memo')
    success_url = reverse_lazy('list')

def listfunction(request):
    object_list = PostModel.objects.all()
    return render(request, 'list.html')
```

```python:myapp/urls.py
from django.urls import path
from .views import PostClass, listfunction

urlpatterns = [
    path('post/', PostClass.as_view(), name='post'),
    path('list/', listfunction, name='list'),
]
```

```html:post.html
<form action="" method="POST">
{% csrf_token %}
  <p>タイトル：<input type="text" name="title"></p>
  <p>メモ：<input type="text" name="memo"></p>
  <input type="submit" value="投稿する">
</form>
```

```html:list.html
<div class="container">
  {% for post in object_list %}
  <div class="post">
    <p>タイトル：{{ post.title }}</p>
    <p>メモ：{{ post.memo }}</p>
  </div>
  {% endfor %}
</div>
```

#まとめ
上記でも書いたように

- `reverse_lazy`は`TemplateView`の場合
- `render`は`function`の場合になります

参照：
https://docs.djangoproject.com/ja/2.2/ref/urlresolvers/
https://teratail.com/questions/103080
https://teratail.com/questions/50683

以上
RailsのCI環境でChildProcess::Errorが発生する場合の対処法

結構長いこと悩まされていたエラーだったのですが、原因がわかりましたので共有します。

# CircleCIが安定しない

テストは全て通っているのですが、時々というか結構な頻度で以下のようなエラーが出てCIがコケていました。

> /home/circleci/project_name/vendor/bundle/ruby/2.6.0/gems/childprocess-1.0.1/lib/childprocess/abstract_process.rb:188:in `assert_started': process not started (ChildProcess::Error)
	6: from /home/circleci/project_name/vendor/bundle/ruby/2.6.0/gems/selenium-webdriver-3.141.5926/lib/selenium/webdriver/common/platform.rb:150:in `block in exit_hook'
	5: from /home/circleci/project_name/vendor/bundle/ruby/2.6.0/gems/selenium-webdriver-3.141.5926/lib/selenium/webdriver/common/service.rb:110:in `stop'
	4: from /home/circleci/project_name/vendor/bundle/ruby/2.6.0/gems/selenium-webdriver-3.141.5926/lib/selenium/webdriver/common/service.rb:110:in `ensure in stop'
	3: from /home/circleci/project_name/vendor/bundle/ruby/2.6.0/gems/selenium-webdriver-3.141.5926/lib/selenium/webdriver/common/service.rb:163:in `stop_process'
	2: from /home/circleci/project_name/vendor/bundle/ruby/2.6.0/gems/selenium-webdriver-3.141.5926/lib/selenium/webdriver/common/service.rb:180:in `process_exited?'
	1: from /home/circleci/project_name/vendor/bundle/ruby/2.6.0/gems/childprocess-1.0.1/lib/childprocess/unix/process.rb:31:in `exited?'
/home/circleci/project_name/vendor/bundle/ruby/2.6.0/gems/childprocess-1.0.1/lib/childprocess/abstract_process.rb:188:in `assert_started': process not started (ChildProcess::Error)

このエラーメッセージ等でググっていたのですが、解決方法が見当たらず…。時々失敗するけれど時々成功するため、ときどき調査しようとしては諦めていました。

## 他のエラーメッセージに気づく

弊社の他のプロジェクトでも同様の症状が出ており、同僚が調査していたのですが、そのときに見つけたメッセージがこれ。

> Text file busy - /home/circleci/.webdrivers/chromedriver

私はエラーメッセージのほうばかりを見ていて気づいてなかったのですが、RSpecが落ちたテストをリトライするところに出ていました。

こちらでググると、Rails 6.0系のissueとPRがヒットしました。

https://github.com/rails/rails/pull/36292

Rails 6系ではデフォルトで並列テストをサポートするという認識ですが、弊社のCIもparallel_testsでテストを回していて、同じ症状のようです。

症状の詳細は、**webdriversがchromedriverのアップデートをしようとするが、並列でそれが行われてしまい、片方のプロセスが起動できなかった**ということです。

そこで、並列テストが実行される前にchromedriverのアップデートをしておけば、この問題は発生しなくなると考えました。（上記のPRもそういうことをやっていますが）

# 修正方法

並列テストが実行される前にchromedriverを更新するよう.circleci/config.ymlを修正しました。parallel_tests等でテストを起動するとその時点で並列化されているから、その前にやっておきます。

```yaml:.circleci/config.yml
steps:
  # 略。ただし、DB作成後でないとrails runnerが失敗するので注意。
  - run:
      name: Update chromedriver
      command: env RAILS_ENV=test bin/rails runner "Webdrivers::Chromedriver.update"
  # 略。テストを実行
```

## 結果

10回連続で同じテストを実行しましたが、全部成功しました:v:

もし並列テストが不安定だ〜という方はこれを追加してみましょう！
RubyのString#%について

#はじめに

以下のようなRubyのコードを見かけました。

```ruby:sample.rb
names = ['Jon', 'Bob', 'Alice']
puts "Their names are %s, %s and %s" % names

#=> Their names are Jon, Bob and Alice
```
文字列中に含まれている%sやその後の%namesが何を意味しているのか分からなかったため、調べてみました。

#String#%
リファレンスを確認したところ、Stringクラスのインスタンスメソッドで%がありました。
https://docs.ruby-lang.org/ja/2.5.0/method/String/i/=25.html

> self % args -> String
printf と同じ規則に従って args をフォーマットします。
args が配列であれば Kernel.#sprintf(self, *args) と同じです。 それ以外の場合は Kernel.#sprintf(self, args) と同じです。

引数argsを変換してくれるようです。
文字列 % argsというのが最初に見たコードの

```ruby
"Their names are %s, %s and %s" % names
```
の部分と一致してそうですが、イマイチよく分かりません。
printfと同じ規則に従ってとは？
printfって何だっけ？
ということで調べてみました。

## printfとは

こちらもリファレンスを確認すると、Karnelモジュールのモジュール関数に定義されていました。
https://docs.ruby-lang.org/ja/2.5.0/method/Kernel/m/printf.html

> C 言語の printf と同じように、format に従い引数を文字列に変換してportに出力します。

どうやらprintfは元々C言語の関数で、ある規則に従って引数を変換し、文字列として出力してくれるようです。C言語は全く分からないのでスルーします。

つまり、String#%はprintfで使われている規則に従って引数のargsを変換してくれるメソッドのようです。

では、printfで使われている規則とは何か？

## sprintf フォーマットとは
String#%のリファレンスに規則について記載されていました。
Rubyの場合はC言語のものと少し違うが、ほとんど一緒のようです。
このsprintfフォーマットの中で指示子という項目があり、その中に文字列を表す指示子としてｓがありました。
> 指示子は引数の型の解釈を示します。指示子を省略することはできません。 指示子には大きく分けて
・文字列を表す指示子: c, **s**, p
・整数を表す指示子: d, i, u, b, B, o, x, X,
・浮動小数点数を表す指示子: f, g, e, E, G
があります

こちらのサイトが分かりやすかったです。
http://www9.plala.or.jp/sgwr-t/c/sec05.html

#まとめ
以上の知識を得てレベルアップしたため、最初に書いたコードを再度見てみると、以下の事が分かりました。

```ruby
names = ['Jon', 'Bob', 'Alice']
"Their names are %s, %s and %s" % names
```
- 二行目でString#%メソッドが使用されて、 self % args　の形になっている。
- 一行目で定義された配列 names が%メソッドの引数(args)になっている。
- self（文字列）の中で文字列を表す指示子sが使用されている。

したがって、%メソッドの引数に指定された配列namesの各要素が、文字列中の%s(指示子）により、文字列として表示されているようです。（間違っていたらすいません）

#おまけ
今回の例のように配列を引数にする場合、配列の要素数に対して文字列中の指示子の数が多いと、引数が不足しているというエラーになりました。

```ruby
names = ['Jon', 'Bob', 'Alice']
puts "Their names are %s, %s, %s and %s" % names
# 配列の要素数は３に対して、%sを４つ使用しています。

#=> too few arguments (ArgumentError)
```

逆に、配列の要素数が多い場合は余剰分が無視されます。

```ruby
names = ['Jon', 'Bob', 'Alice']
puts "Their names are %s and %s" % names
# 配列の要素数は３に対して、%sを２つ使用しています。

#=> Their names are Jon and Bob
#余計な存在の'Alice'は無視されます。
カラムを追加するか別テーブルとして切り出すか（メモ）


カラムを追加するべきか別テーブルとして切り出すべきかの指針をまとめる。


## カラムを追加する
### メリット
 - 運用が楽（SQLでJOINする必要がない）
 - 用意に1対1の関係性が担保できる

### デメリット
 - カラム数が増えて分かりづらくなる

## 別テーブルをつくる
### メリット
 - 1対Nの関係をとれる
 - 既存のテーブルを使った処理に影響を与えない

### デメリット
 - 運用が大変（SQLでJOINする必要がある）


## 指針
以下の場合は別テーブルとして分けた方が良い。逆にそれ以外の場合はカラム追加で大丈夫。
 - 1対Nの関係になるとき
 - 履歴を管理したいとき
 - 追加カラム数が多いとき

1対1の関係の場合でも、セキュリティ上の理由からテーブルを分けた方がいい場合もある。
マイナンバーなど。
アジャイル開発の現場を体験して思ったこと

アジャイル開発についての個人的な感想
![scrum.png](https://qiita-image-store.s3.amazonaws.com/0/379491/d062eda7-edd2-217d-2ebd-c65238565c1b.png)
##はじめに
近年よく耳にするようになったソフトウェア開発手法のひとつであるアジャイル開発。
企業の注目度も高く、[KDDIなど3社、アジャイル開発専門の新会社を設立](https://www.nikkei.com/article/DGXMZO42290840R10C19A3000000/)のニュースもあります。
でも実際にどのような開発手法かと聞かれると、はっきりと答えられる人は少ないのではないでしょうか。
今回、自分が関わったプロジェクトがアジャイル開発で行われる事から、概要と個人的な感想をまとめてみました。

##代表的な開発手法について 
アジャイル開発を説明する前に、代表的なソフトウェア開発手法を挙げてみます。

- ウォーターフォールモデル  
現状、最も多くの現場で使用される代表的な開発手法。
開発の段階を川の流れに例えているところから名づけられています。

#####メリット
工程の進捗管理が容易であるところ。
詳細な定義を開発初期に決定し、その定義を実装するためプロジェクト全体として何を作っているか明確となっています。

#####デメリット
製造の段階に入るまでに時間がかかる。
開発途中での定義変更が難しい。

- スパイラルモデル  
よくアジャイルと比較される手法です。
設計・実装・テストの一通りの工程を繰り返してシステムの質を高めていく開発モデルになります。

##アジャイル開発とは
アジャイルとは『すばやい』『俊敏な』という意味で、2001年に提唱された[アジャイルソフトウェア開発宣言](http://agilemanifesto.org/iso/ja/manifesto.html)を基に確立され、宣言内容は心構えのような哲学的な内容になっており、明確な手法があるわけではありません。
複数の開発手法があり、共通して反復 (イテレーション) と呼ばれる短い開発期間単位を採用する反復型開発手法になります。
具体的には「計画」「要件定義」「設計」「実装」「テスト」といった工程を分割した機能単位毎に反復的に行い、小さな機能を1つずつ追加開発していくことで、最終的にシステム全体の完成を目指します。

###アジャイル型開発手法
- スクラム（Scrum）
ネット上の実例でよく見かける代表的な開発手法です。
>スクラムのカギとなる基本原則は、プロジェクト開発の途中で、顧客は、要求や必要事項を変えられるという認識である。予想できない変更について、計画に基づく方法で対処することは、容易ではない。したがって、スクラムは経験に基づくアプローチを採用する。問題を十分に理解することも、定義することもできないので、現れた要求へ素早く対応するためのチームの能力を最大化することに集中する、というアプローチである。

- エクストリーム
ネット上の実例ではあまり見かけない方の代表的な開発手法です。
>柔軟性の高い開発手法であるが、古典的には開発が進むにつれ変更コストは大きくなると言うことを前提に開発手法が構築されているのに対して、自動テストを導入するなど様々な対策をすることにより開発が進んでも変更コストが大きくならないような工夫を持ち込むことにより、変更に対する柔軟性を実現している。この変更コストが増大しないという前提[1]が破綻すると、この手法も破綻する。
>XPは比較的少人数の開発にもっとも適用しやすく、5つの価値と19の具体的なプラクティス（実践）が定義されている。XPはドキュメントよりもソースコードを、組織的開発の歯車となることよりも、個人の責任と勇気を重んじる人間中心の開発プロセスであるとしている。

##アジャイル開発でのメリット
従来のウォーターフォールモデルと比べ迅速に開発に入ることができます。
実装途中の仕様変更にも対応しやすく、製品への柔軟性と高品質を両立した開発が可能です。

##アジャイル開発でのデメリット
全体の設計が未確定の状態で開発がスタートするため、期限までに全ての機能を実装できるかが不確定です。
明確な設計が無いため、統率が取れない場合は保守性の低い製品になってしまう。

##実際の現場での印象
詳細設計を書かなくて済む分、開発のスピードはウォーターフォールモデルと比べ体感で1か月近く早く始まったように感じた。その反面、場当たり的な対応が多く、アジャイルであっても初期の実施計画の重要性が伺えた。
どのアジャイル型開発手法を見てもチーム内でのコミュニケーションが強く求められるが、実際はあまり無く各々の裁量で開発が進んでいる。そのため実装方法がバラバラであったり、共通認識の齟齬など後々に与える影響が大きくなりそうに感じた。
メンバー内にスクラムなどの開発手法をよく理解した人が数人でも居れば、メンバー全員のスキル向上や製品の品質に対しても従来の開発手法より良いアプローチが出来そうな雰囲気は感じられた。
逆に上手く機能していないアジャイル開発は、設計書なし、急な仕様変更、スケジュールが見えないなどの悪循環に陥る可能性がある。


---
- [スクラムの概要を1分で理解できるイラスト【2018版】](https://www.ryuzee.com/contents/blog/7124/)
- [アジャイル開発
～顧客を巻き込みチーム一丸となってプロジェクトを推進する～ （前編）](https://www.nec-solutioninnovators.co.jp/column/01_agile.html)
- [wikipedia アジャイル開発](https://ja.wikipedia.org/wiki/%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA)
- [wikipedia スクラム (ソフトウェア開発)](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%AF%E3%83%A9%E3%83%A0_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA))
- [wikipedia エクストリーム・プログラミング](https://ja.wikipedia.org/wiki/%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%88%E3%83%AA%E3%83%BC%E3%83%A0%E3%83%BB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)
最新版TensorFlow (2.0 Alpha) 動作環境構築 : Mac編

# はじめに
MacにTensorflow 2.0 Alphaの動作環境を構築した過程を記載します。
。
基本的には[こちら](https://www.tensorflow.org/install/pip)の公式チュートリアルの流れに沿って導入しています。

---

**本記事は概要版となります。**
**詳細は[最新版TensorFlow (2.0 Alpha) 動作環境構築 : Mac編（詳細版）](https://instanttry.com/2019/05/24/post-360/)で紹介しています。**

---

# 構成
MacBook Pro (13-inch, 2016, Two Thunderbolt 3 ports)

# TensorFlowインストール事前準備

アプリケーション→ユーティリティ→ターミナル.appを開き、以下を1行ずつ実行してください。


Python諸々のバージョン確認

```
python3 --version
pip3 --version
virtualenv --version
```
なお、現時点（2019/5/24）での私の環境では以下の通りになりました。
Python 3.7.3
pip 19.0.3
virtualenv 16.6.0

# 仮想環境の作成（推奨）
Mac本体のシステムから独立した環境を構築したほうが、色々といじるのに便利なため、virtualenvというツールを使った仮想環境の導入をします。


```
virtualenv --system-site-packages -p python3 ./venv
```

```
source ./venv/bin/activate
```


```
pip install --upgrade pip
pip list  # 仮想環境内でインストールされているパッケージを表示
```
仮想環境を終了する場合は以下を実行してください。
なおTensorFlow使用時は有効になっている必要があります。

```
deactivate  
```

# TensorFlow 2.0 Alpha導入
以下コマンドを実行するとインストールが開始されます。

```
pip install --upgrade tensorflow==2.0.0-alpha0
```


# 動作確認

以下を入力し対話モードに入ります。

```
python
```

Tensorflowをtfとして読み込みます。

```
import tensorflow as tf
```

手書き数字のデータセットであるMNISTを読み込みます。

```
mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
```

tf.keras.Sequentialモデルをビルドします。

```
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
```

学習と評価を行います。

```
model.fit(x_train, y_train, epochs=5)

model.evaluate(x_test, y_test)
```

このような感じで学習と評価がなされていれば導入完了です。

```
>>> model.fit(x_train, y_train, epochs=5)
Epoch 1/5
60000/60000 [==============================] - 4s 59us/sample - loss: 0.3015 - accuracy: 0.9122
Epoch 2/5
60000/60000 [==============================] - 3s 54us/sample - loss: 0.1462 - accuracy: 0.9564
Epoch 3/5
60000/60000 [==============================] - 3s 54us/sample - loss: 0.1100 - accuracy: 0.9662
Epoch 4/5
60000/60000 [==============================] - 3s 57us/sample - loss: 0.0910 - accuracy: 0.9722
Epoch 5/5
60000/60000 [==============================] - 3s 53us/sample - loss: 0.0765 - accuracy: 0.9760
<tensorflow.python.keras.callbacks.History object at 0x1123d6748>
>>> 
>>> model.evaluate(x_test, y_test)
10000/10000 [==============================] - 0s 32us/sample - loss: 0.0730 - accuracy: 0.9781
[0.07304580859981943, 0.9781]

```

# まとめ
TensorFlow 2.0 Alphaの導入、サンプル動作まで一通り実現できました。
今後は、オリジナルの学習モデルの構築を目標に勉強したいと思います。

---

**本記事は概要版となります。**
**詳細は[最新版TensorFlow (2.0 Alpha) 動作環境構築 : Mac編（詳細版）](https://instanttry.com/2019/05/24/post-360/)で紹介しています。**

---
.present?の判定結果

3日未来のわたしへ。

|オブジェクト|記述|結果|
|---|---|---|
|nil|nil.present?|<font color="#ff9933">false|
|空文字|"".present?|<font color="#ff9933">false|
|空配列|[].present?|<font color="#ff9933">false|
|空ハッシュ|{}.present?|<font color="#ff9933">false|
|false|false.present?|<font color="#ff9933">false|
|0|0.present?|<font color="#9933ff">true|
|1|1.present?|<font color="#9933ff">true|
|true|true.present?|<font color="#9933ff">true|
[jQuery]複数のライブラリの使用時にコンフリクトを回避する方法

自分用メモです

参考サイト
[WordPressでjQueryを使うときに、問題なく動作させる為の基礎知識やTipsと、動かない場合の対処例](http://kachibito.net/web-design/wordpress-with-jquery.html#toc4)
[【WordPress】複数のjQueryプラグインを1ファイルに収める](http://wild-cards.net/jquery-source-allinone/)
上記サイトからの引用です。

>この2つのライブラリは共通して\$を関数に使っています。詳細は省きますが、この\$が原因で衝突・・コンフリクトというんですが、これを起こすことで上手く動作しない事が大半だったりします。

関数部分を下記に書き換えて対応

```javascript:jQuery
jQuery(document).ready(function($){
  // foo
});
```
git rebase 使いたい案件に初めて遭遇した

# 背景
- 結構前にcommitしてしまったものにデカイファイルがあった
- commitをかなりした後にリモートにpushしようとしたら「デカイファイルがあるのでremote rejectしました」エラーが出た
- git rm そのファイル をしてcommitしても、一度commitされてるファイルなので、pushしようとする
- 最初にcommitした時点に戻って、ファイルを取り除かないといけない！

```command
$ git push -u origin local-staging-darkorange
Enumerating objects: 149, done.
Counting objects: 100% (149/149), done.
Delta compression using up to 8 threads.
Compressing objects: 100% (114/114), done.
Writing objects: 100% (114/114), 115.08 MiB | 1.85 MiB/s, done.
Total 114 (delta 81), reused 0 (delta 0)
remote: Resolving deltas: 100% (81/81), completed with 29 local objects.
remote: warning: File sheets-export.zip is 55.36 MB; this is larger than GitHub's recommended maximum file size of 50.00 MB
remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
remote: error: Trace: 501288f695fd5ee39c76eee83cda62a8
remote: error: See http://git.io/iEPt8g for more information.
remote: error: File wnjpn.db is 193.70 MB; this exceeds GitHub's file size limit of 100.00 MB
To https://github.com/***
 ! [remote rejected]   local-staging-darkorange -> local-staging-darkorange (pre-receive hook declined)
error: failed to push some refs to 'https://github.com/***'
```

# したこと
```command
$ git log -p wnjpn.db
commit 239b04ceb8b988a900af5100734c07314ca1d44a
Date:   Fri May 17 11:52:12 2019 +0900
    ボタン変更など

$ git log --oneline
4492c9c4 (HEAD -> local-staging-darkorange) modify
bab5be53 *** テストスクリプト作成
a4e50bd1 項目数に制限がない項目を同等に扱う
9afb0a4c rule_form_element.csv変更
ecefa5ac trush iconの表示方法の変更
d2bcc121 *** テストスクリプト
239b04ce ボタン変更など

$ git rebase -i HEAD~7
Checking out files: 100% (20/20), done.
Stopped at 239b04ce...  ボタン変更など
You can amend the commit now, with
  git commit --amend 
Once you are satisfied with your changes, run
  git rebase --continue

$ git rm --cached wnjpn.db
rm 'wnjpn.db'
$ git commit --amend
$ git rebase --continue
Successfully rebased and updated refs/heads/local-staging-darkorange.
```

# 参考
http://shuzo-kino.hateblo.jp/entry/2014/05/22/222251
https://chaika.hatenablog.com/entry/2016/03/22/181243
https://qiita.com/megu_ma/items/a438a71c84145f14d04e
【ハマり】S3事前署名で発行されたURLがAccessDeniedで弾かれる事象について

#説明
個人開発中にS3の事前署名URL関連でハマった。

本当にクソしょーもないハマり方なので、記事にするべきか判断に迷いました。
でも塵も積もればということで。

先言っておくと、原因はバケットポリシー関連のやらかしです。

#事象説明
Node.js。

```js:zizen.js
    //事前署名URL取得
    var params = {
        Bucket: 'バケット名',
        Expires: 3600,
        Key: 'test.png',
        ContentType: 'image/png'
      };
      
    var res = await new Promise((resolve, reject)=>{
    S3.getSignedUrl('putObject', params, (err,url)=> {
        if(err){
            logger.level='error';
            logger.error(err);
            return reject(err);
        }
        else{
            logger.info(url);
            return resolve(url)
        }
          });    
    })  
    
    const response={'statusCode':'200',
        'body':JSON.stringify({'sign_url':res }),
        'headers': {'Content-Type':'application/json'},
    };
    
    callback(null,response);
```
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property
上記の公式リファレンスに沿ってPutObjectオペレーションに対して、3600秒の有効期限を持った事前署名urlを発行。
そして、3600秒以内に以下のコマンドでtest.pngのアップロードを試みるも

```
curl -H "Content-Type: image/png" --data-binary "@test.png" -X PUT "発行されたURL"
```
AccessDeniedが返ってくる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302014/17c2054b-30a0-ac1b-d903-b77b36b0ab2c.png)

(＾ω))))))))＾<なんで～っ

#結論
パケットポリシーで明示的にPutObjectを禁止していると、事前署名Urlに対してのアクションも禁止されます。
されました。
この明示的禁止ポリシーを削除する事で無事アップロードに成功します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302014/fae1549d-868a-5113-52f6-6591a774d89a.png)

デフォルトでも禁止なのですが、バケットポリシーの明示的禁止とデフォルトの禁止には違いがあるようです。
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/example-bucket-policies.html

>明示的な拒否は、ACL やユーザーポリシーなどの他の方法を使用して examplebucket バケット内のオブジェクトに付与したすべてのアクセス許可よりも優先されます。

へ～…ふ～ん…そうなんすか…

以上です。
シンプルな再帰下降のサンプル


+-*と数字1文字だけを受け付ける再帰下降パーサ
===

再帰下降は計算機業界のロンダートからの後方宙返り。
プログラムを書く人は知っていて決して損はしません。

再帰下降はオペレータの優先順位をどこかにデータで持っているのではなくて、**より優先順位の高いオペレータを処理する関数を呼び出す親子関係で、優先順位の高い・低いを表現します。**

再帰下降で検索すると立派なパーサはいっぱい出てくるけど、結局どういう事か良くわからないで終わりそうです。ここはひとつ、シンプルに + - * の3つのオペレータと、数字1文字だけを受け付けるパーサを書いてみましょう。
+-に対応するのは、優先順位の同じオペレータの処理の例として、それと * に対応するのは優先順位の高いオペレータをどう処理するかを示すためです。2桁以上の数字の対応は字句解析の範囲なので、1桁で充分でしょう。
あと、せっかくですから、結果を計算するためにスタックを用意します。
短いソースなので、読み解くのは難しくないと思います。

この例ではexpr()は一度しか呼ばれませんが、優先順位を指定する()を実装したら、括弧のなかで再帰的にexpr()を呼ぶようになるでしょう。
再帰は無いので、ただの下降パーサですが、優先順位をどう処理しているのか、感じはつかめると思います。


```t1.c
/*
再帰下降サンプル
cc -o t1 t1.c
*/

#include <stdio.h>

char* text="2-3*4+5*6" ;
char* ptr ;
char token ;

//	計算結果を積むスタック
int stack[32] ;
int sp=0 ;

void push(int value){
	stack[sp]=value ;
	sp++ ;
}

int pop(void){
	sp-- ;
	return(stack[sp]) ;
}


void get_token(void){
	token=*ptr ;
	if(*ptr!=0){
		ptr++ ;
	}
}


//	数値
void digit(void){
	get_token() ;
	if(token>='0' && token<='9'){
		push(token-'0') ;
		printf("number(%d)\n", token-'0') ;
		get_token() ;
	}
}

//	掛け算	
void mul(void){
	digit() ;
	while(1){
		if(token=='*'){
			digit() ;
			printf("mul\n") ;
			push(pop() * pop()) ;
		}
		else{
			break ;
		}
	}
}

//	足し算と引き算
void add(void){
	mul() ;
	while(1){
		if(token=='+'){
			mul() ;
			printf("plus\n") ;
			push(pop() + pop()) ;
		}
		else if(token=='-'){
			mul() ;
			printf("minus\n") ;
			int top=pop() ;
			push(pop() - top) ;
		}
		else{
			break ;
		}
	}
}

//	式の評価
void expr(void){
	while(*ptr!=0){
		add() ;
	}
}

int main(void){
	ptr=text ;
	expr() ;

	printf("answer=%d\n", pop()) ;

	return 0 ;
}
```

実行結果

```
$ ./t1
number(2)
number(3)
number(4)
mul
minus
number(5)
number(6)
mul
plus
answer=20
```

---

()に対応したバージョンの [シンプルな再帰下降のサンプル(2)](https://qiita.com/niQSun/items/06dcc7134eea66972ef4) を載せました。
【Android】altbeaconでBeaconからの距離(Proximity)を測りたかった話

[前回](https://qiita.com/rm__rf/items/0509684ed04195e99df1) Macから無事Beaconを発射できるようになった。

Beaconの仕様を知らないまま、BeaconからAndroid端末の距離って測れるよね？と軽い気持ちで試してみようとした記録とメモを兼ねて。。。。

# 結論から言うと
色々調べてみると、どうやら電波強度や建物の干渉などで正確な距離は測れないみたい。

一応 `BeaconManager#addRangeNotifier` で受け取れるbeaconに生えてるdistance(メートル単位)があるけど
本当にメートル？？？ってなるくらい誤差がひどかった。

# どうやったか
ググラーエンジニアなのでこのQiitaを発見。
[RSSI と TxPower からビーコンとの距離および近接度（Proximity）を推定する](https://qiita.com/shu223/items/7c4e87c47eca65724305)
この記事によると

> RSSI と TxPower から推定距離を計算する
> 
> 自由空間では受信信号強度は距離の二乗に反比例して減衰していく（フリスの伝達公式）ので、RSSI と TxPower と距離（d）の関係は次のようになります。
>
> ```
> RSSI = TxPower - 20 * lg(d)
> ```
>
>（lg は底を 10 とする常用対数）
>
>というわけで、距離 d の計算式は以下のようになります。
>
> ```
> d = 10 ^ ((TxPower - RSSI) / 20)
> ```

なんかすごい物理法則的なアレを加味して計算しないといけないっぽかった。(語彙力)
先人の知恵を頂戴して、Kotlinで便利そうな関数を作る。 

``` Sample.kt
fun beaconDistance(txPower: Int, rssi: Int): Double = 10.0.pow((txPower - rssi) / 20.0)
```

実際に観測してログに出すだけのコードはこちら

``` Sample.kt
    override fun onBeaconServiceConnect() {
         ~ 略 ~

        beaconManager?.addRangeNotifier { beacons, region ->
            beacons
               .map {
                   "Distance:"+beaconDistance(it.txPower, it.rssi)
                   // it.distanceもあったけど誤差がやばい(私的見解)
               }
               .forEach { Log.d(TAG, it) }
        }
         ~ 略 ~
    }
```

# 測ってみてどうだった？
端末持ってウロウロしてみたけど外の交通量やノイズ？や建物の作りでまあまあ誤差がでるみたい。
`beacon.distance` 使えないな〜、もうちょっと正確なのがいいな。
くらいの時に目安に使うのならいいかもね。
Convert.ToDouble(floatValue)での誤差

浮動小数点数で誤差が出るという知識自体は持っているのに、実際出るまで忘れてることが多いですね。

Convertは意識しないで使うとたまに躓きます。

```C#
Console.WriteLine((double)1.234f);
Console.WriteLine(Convert.ToDouble(1.234f));
Console.WriteLine((double)Convert.ToDecimal(1.234f));
//出力結果
//1.23399996757507
//1.23399996757507
//1.234
```

こんなことにいまだに躓くので恥さらしの記事。

[小数（浮動小数点数型）の計算が思った結果にならない理由と解決法
Decimal型はいつ使うか？](https://dobon.net/vb/dotnet/beginner/floatingpointerror.html)
【日記】全然違うブランチにコミットしてしまったミスをcherry-pickで解消できなかった話

#事の始まり
ブランチAにコミットするはずの内容を間違えてブランチBにコミットしてしまった。
チームのSlackで助けを求めたところ、cherry-pickコマンドでなんとかするのが良さそうということが判明。

#チェリーピックってなんすか
ブランチβにあるコミットの更新内容を、ブランチαに取り込むことができるgitの機能とのこと。
この説明を見たときは**正直「マージでも同じなんじゃね？」と思ったけど、どうやらそうではなく、あくまでコミット単位で取り込めるというのがチェリーピックの特徴**ということがわかった。

例えば**ブランチβに分岐してから１０個のコミットが生まれていた場合**を考えてみる。
これをαに「マージ」しようとすると、それまでの１０個のコミットでの変更内容が全てαへと適用されてしまうことになる。
一方、**これを「チェリーピック」で処理すれば、5個目と6個目のコミットで生じた変更分だけをαに取り込むことができる**ということ。

#どうすれば使えるんだい
打ち込むコマンドは次の通り。

```
git cherry-pick　[commit-ID]

//一連の複数コミットをまとめてチェリーピックしたい場合は始点コミットと終点コミットをピリオド二つで結ぶ
git cherry-pick　[commit-ID-start]..[commit-ID-end]
```

※複数コミットをまとめる場合、始点コミットは「取り込みたいコミットの一つ前」を指定する必要がある。

[git]複数のcommitをまとめてcherry-pickする
https://dackdive.hateblo.jp/entry/2016/06/06/203542

このコマンドを打ち込むことで、現在チェックアウトしているブランチに、指定したコミットIDの内容を適用させることができる。

コミットIDそのものは`git log`コマンドを実行すると確認可能。

#なんかコンフリクト出ましたけど
実際にコマンドを実行してみたところ、コンフリクトが発生してしまった。
どんなときもすんなり行けるという訳ではないらしい。というか、私のコミットの粒度がおかしいんだと思う。

```
error: could not apply b80f80c... [コミットメッセージ]
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
```

`vi [file]`コマンドでコンフリクトを解消すればいいよ！みたいな情報を見かけたので、実行してみる。
viを実行してから`/<<<`コマンドでコンフリクト箇所を検索。

```
E486: Pattern not found: <<<
```

えええ・・・コンフリクト箇所が見つからないってこと？

#結局
このファイルは４０万行くらいあるファイルだったので、キャパオーバーを起こしてしまったのかも。
試しにVSCodeで検索をかけてみたところ、ちゃんと見つかった。１万３０００箇所くらい。
とても人力ではやっていられないので、チェリーピックでの方法は諦めることに。トホホ。
今後似たようなケースに遭遇したら、チェリーピックって方法もあったなあぐらいに覚えておくことにします。

さて、そもそもの問題は解決していないままなんですけどどうしましょうかね（頭抱え）
kintoneのラベルフィールドの要素を取得

# はじめに

先日こんな記事を書きました。
[kintoneの内部パラメータ「フィールドID」を使いこなす](https://qiita.com/the_red/items/702d8f3672f277c5eac7)

入力するフィールドはこれで全部行けるんですが、
「ラベルフィールド」のDOMを取得したいときは、これでも無理。
どうやらラベルには、フィールドIDがそもそも付与されないっぽいです。

# 解決方法

100% DOM操作で行います。
例のごとく、今後動かなくなる可能性は大なので自己責任で。

`div`タグが多重になってますが、`.control-label-field-gaia`クラスがラベル1個単位の大元のようです。
jQueryを使わずに書くなら、以下の2ステップで。

* 全ラベルを取得
* その中から特定の文字列のラベルを探す


こんな風に用途別に関数を作ってやると、取り回しやすいと思います。

```js
// 全ラベルの取得
const allLabelElements = () => Object.values(document.querySelectorAll('div.control-label-field-gaia'))

// 特定の文字列と一致するラベルを1つ抽出
const findLabelElement = label => allLabelElements().find(_ => _.textContent === label)

// 特定の文字列を含むラベルを複数抽出
const filterLabelElements = label => allLabelElements().filter(_ => _.textContent.includes(label))
```

# 使用例


アプリストアの「旅費精算申請」の場合

## 「旅費」と一致するラベル

マッチしたElementオブジェクトが返る

<img width="1186" alt="スクリーンショット 2019-05-24 11.53.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24333/fdf02515-0649-b34e-2023-c352163b7d1e.png">

## 「旅費」を含むラベル

マッチした3つのElementが配列で返る

1. 「旅費精算申請」にマッチ
<img width="1232" alt="スクリーンショット 2019-05-24 11.55.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24333/8e676481-2f6a-633f-4ae7-72da86763fe9.png">

2. 「旅費」にマッチ
<img width="1232" alt="スクリーンショット 2019-05-24 11.55.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24333/c34e8645-188d-36d3-043a-67a442128986.png">

3. 「旅費合計（円）」にマッチ
<img width="1232" alt="スクリーンショット 2019-05-24 11.55.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24333/cd74d720-dda2-7af5-7dd7-0dea2075a9d6.png">

あとは好きなようにhackしてくださいませ！
ではまた〜。
chcsvコンパイルメモ

##前準備
ProCを使うため先にOracle DatabaseあるいはOracle Clientを入れておく。
demo_proc.mkも必要なのでOracle Examplesを入れておく。

##コンパイル

```shell
$ export LD_LIBRARY_PATH=$ORACLE_HOME/lib
$ git clone https://github.com/moriyasujapan/chcsv.git
$ cd chcsv
$ make
$ strip ./chcsv

demo_proc.mk / proc.mk絡みのエラーの場合は
Oracle Examplesをインストールしていないか、インストールしたパスが参照できていません。

Cライブラリが参照できていないエラーが出る場合は下記ファイルのsys_includeを修正する
$ vim $ORACLE_HOME/precomp/admin/pcscfg.cfg

```
Maven Repository に jar, war を 登録するコマンド（備忘録）

```:jarの登録
$ mvn deploy:deploy-file -Durl=file:///**Maven Repos の パス**/ -Dfile=**Jarファイル.jarパス** -DgroupId=**グループID** -DartifactId=**アーティファクトID** -Dversion=**バージョン** -Dpackaging=jar -DgeneratePom=true
```

```:warの登録
$ mvn deploy:deploy-file -Durl=file:///**Maven Repos の パス**/ -Dfile=**Warファイル.warパス** -DgroupId=**グループID** -DartifactId=**アーティファクトID** -Dversion=**バージョン** -Dpackaging=war -DgeneratePom=true
```
【AWS】ローカルVimからAWSファイルを編集する

サーバーのファイルを触るときにいつものシンタックスとかプラグインが適応されておらず不便さを感じていた

ネットで調べたら出来るらしいので [vim.jp](https://vim-jp.org/) の師匠方に相談したら丁寧に教えてくれたので共有

# configファイルの作成

現状、vimでは鍵の指定をした接続が出来ないので`~/.ssh` 配下にconfigファイルを作成する

```
$ mkdir ~/.ssh
$ touch ~/.ssh/config
```
作成したconfigファイルに接続情報を書き込む

```
Host sample
    HostName ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com
    User xxxx
    IdentityFile ~/.ssh/xxxx.pem
    TCPKeepAlive yes
    IdentitiesOnly yes
```

| 名前 | 意味 |
|:--|:--|
| Host | アクセス時に宣言するホスト名 |
| HostName | ホストのアドレスかorアドレス |
| User | ユーザ名 |
| IdentityFile | 秘密鍵のパス |
| TCPKeepAlive | 接続状態を継続するかどうか |
| IdentitiesOnly | IdentityFileの要否 |

# 実行
以下コマンドでリモートファイルをローカルのVimで編集することが出来る

```
$ vim scp://sample//path/to/file.txt
```

ローカルのシンタックスとかプラグインが既に適応されているので便利
ますますVim愛が増してしまいそうだ
#Slack に使う「文字」絵文字をシェルから「絵文字ジェネレーター」でダウンロードしたい雛形

今はコンソールから「へぇ」の絵文字を「hexe.png」としてダウンロードするっていう指定を、コマンドごとにしている状態。コンソールの文字コードの扱いによってはうまく動かないかも。

ここから

- URLエンコード部分を自動化する
- 4文字絵文字を作るときの改行も入れるようにする

ってしたら素敵に自動化できるかも。


 ```
$ curl -s 'https://emoji-gen.ninja/emoji_download?align=center&back_color=FFFFFF00&color=000000FF&font=notosans-mono-bold&public_fg=true&size_fixed=false&stretch=true&text=うん' --output ~/Downloads/un.png
```

![image](https://user-images.githubusercontent.com/13635059/58294903-7ab40600-7e07-11e9-841f-0f66e19e2584.png)


```
$ curl -s 'https://emoji-gen.ninja/emoji_download?align=center&back_color=FFFFFF00&color=000000FF&font=notosans-mono-bold&public_fg=true&size_fixed=false&stretch=true&text=へぇ' --output ~/Downloads/hexe.png
```

![image](https://user-images.githubusercontent.com/13635059/58294907-7d166000-7e07-11e9-9555-016a71eacd52.png)


# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1986








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Swiftで指定ディレクトリ内のファイル一覧取得（メモ）

```sample.swift
func getFiles(dirName: String) -> [String] {

        do {
            files = try fileManager.contentsOfDirectory(atPath: dirName)
        } catch {
            for path in files {
                print(path as NSString)
            }
            return files
        }
        
        return files
    }
```

以上(ㆁωㆁ*)
オープンソースのTOPPERSプロジェクトのSWOT分析。仮説(81) 

SWOT分析って、強み (Strengths)、弱み (Weaknesses)、機会 (Opportunities)、脅威 (Threats)。

SWOR分析という言葉を使う人もいる。
RはRisk。経済学徒は、Riskをプラスとマイナスと両方考える。
そのため、SWOR分析よりはSWOT分析の方が馴染みやすい。

この文章は、個人による分析です。組織による分析ではありません。

# 強み (Strengths)
多くのCPUに対応している。

### 対応
最新の流行のCPUにはなるべく早く対応する

# 弱み (Weaknesses)
商用の道具、サービスとの連携に偏りがある。

### 対応
AWSなど利用顧客の多いものから順に対応する。

# 機会 (Opportunities)
IoTの流れに乗り、githubで英語で情報発信すれば飛躍的に拡大する可能性がある。

### 対応
IoT連携、英語化に取り組めば成果は、、。

# 脅威 (Threats)
やる気のある優秀な技術者が疲弊する。

### 対応
なにをやるか、個々人の意欲と、小集団の意欲をうまく均衡させ、
関連団体と連携して、やりたいことをやる。
# 参考資料(reference)
「オープンソースプロジェクトで上手いことやってくための10の方法」を拝読し
https://qiita.com/kaizen_nagoya/items/81265788e7cf8f7b230b

# 文書履歴(document history)
ver. 0.01 初稿 20190524 朝
ver. 0.02 対応、参考資料追記 20190524 午前
ver. 0.03 標題追記 20190601

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

#### Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
<a href="http://b.hatena.ne.jp/entry/s/qiita.com/kaizen_nagoya/items/102c8b6b2ff7dfd920c9" class="hatena-bookmark-button" data-hatena-bookmark-layout="basic-label-counter" data-hatena-bookmark-lang="ja" title="このエントリーをはてなブックマークに追加"><img src="https://b.st-hatena.com/images/v4/public/entry-button/button-only@2x.png" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;" /></a><script type="text/javascript" src="https://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script>  http://b.hatena.ne.jp/guide/bbutton
javaでaudioファイルの長さを取得する方法

# audioファイルの長さを取得する方法
###背景を簡単に説明
LINE Messaging APIを使って、[チャネルトーク](https://channel.io/ja)という弊社ウェブ接客チャットツールとLINE公式アカウントを連動※させる際に、音声ファイルの長さ(duration)を取得するところでつまづいたので、共有。

※LINE公式アカウントでのエンドユーザーとの対話を、接客チャットプラットフォームである[チャネルトーク](https://channel.io/ja)で返信、声かけが可能になる。
サイトに設置した接客チャットからの問い合わせと、LINE公式アカウントからの問い合わせに、チャネルトークの管理者画面から対応可能

チャネルトークでアップロードされた音声ファイルをLINE公式アカウントでエンドユーザ側からも見えるように同期するのに、Messaging APIに音声ファイルを送るのだが音声ファイルの長さ(duration)も送らなくてはならない。

##実装方法

ただ、この音声ファイルの長さをファイルから取得するようなAPIはない。

でも方法は簡単。自分で実装すれば良い。
音声ファイルから取得できる総フレーム数とフレームレートから計算すれば良い。

```java
File file = new File(fileUrl);

try {
    //　音声ファイルのmetadataを取得する準備
    AudioInputStream stream = AudioSystem.getAudioInputStream(file);

    // 音声ファイルの総フレーム数
    long length = stream.getFrameLength();
    AudioFormat format = stream.getFormat();

    // frame -> 1秒あたりに処理するフレーム数
    float frame = format.getSampleRate();
    // 総フレーム数➗1秒あたりに処理するフレーム数　= 長さ 
    int duration = (int)(length/frame);

} catch (UnsupportedAudioFileException e) {
    return false;
}
```

色々探さないで、素直に最初からこれやればよかったかも。。。
とりあえず思ったよりも簡単でした！