OmniAICreator/Qiita-1.07M huggingface dataset:
無線技術についての備忘録

無線ハードウェアの開発に向けての知識を現在進行形でまとめておく
BluetoothやZigbeeなどを用いた電子工作用
伸びてきたら分離をする予定

# 微弱無線局
総務省 微弱無線局の規定ページ　ttp://www.tele.soumu.go.jp/j/ref/material/rule/
## 概要
　発射する電波が著しく微弱な無線局で、総務省令で定めるもの
　該当する危機から3mの距離での電界強度が一定値以下であるものは微弱無線局とみなされ
　無線局の免許は必要ない
　しかし、無線通信周波数のすべての範囲で許容値以下でなければならないので
　使用するマイコンのクロックなどが電波として出ているだけでも電界強度を超えているのであれば
　微弱無線局には含まれなくなるので注意がいる
## 用途
　自動車のキーレスエントリ
　イモビライザ
　医療用モニタリングシステム
　オモチャ
## メリット
　規格がないため電界強度が超えていなければ免許が不要
## デメリット
　到達距離が短く妨害を受けやすい
　電界強度を超えている場合使用者が罰せられる(性能証明ラベルがある)
## その他
# 小電力無線局
## 概要
　電波法の無線設備規則の中の第49条の20が
　小電力データ通信システムに関して規定している

## Bluetooth

| 技術仕様 |      項目     |
|:--------:|:-------------:|
| 　規格　 | IEEE 802.15.1 |
| 周波数   | 2.4Ghz        |
| 到達距離 | 10m ~ 100m    |
| 伝送速度 | 1Mbps         |
| 消費電量 | 120mW         |
| 接続数   | 7(ピコネット  |

### バージョン
- 2.1
- 3.0
- 4.0 BluetoothLE対応

### CLASS
- Class1 100m
- Class2 10m
- Class3 1m

####※電波減衰について (要検証)
高周波電波を反射・吸収する物質干渉度
- 低 (木材・合成物質・ガラス)
- 中 (水・煉瓦・大理石)
- 高 (土壁・コンクリート・防弾ガラス)
- 最高 (金属)


### プロファイル
- SPP Serial Port Profile
- HID Human Interface Device Profile
- A2DP Advanced Audio Distribution Profile


### 特徴
- 伝送スピードは1 Mbpsと、ある程度の速さがある
- 消費電力は無線LANよりは少ないがZigBeeよりは上
- 接続数は7接続と少なめ
- 音声とデータのアプリケーションで利用できる
- ネットワークへの参加・離脱が簡単
- 周波数ホッピングによる無線技術間の干渉を軽減する
- スリープからの復帰に1 Sec データ送信できる状態になるまで2~3 Sec

### キーワード
<details><summary>周波数ホッピング・スペクトラム拡散(FHSS)</summary>
ある一定の周期で搬送波の周波数を切り替えて(ホッピング)通信を行う。
送信側と受信側も全く同様に周波数(チャネル)を変更することで正常な通信が行われる。
Bluetoothでは2.4Ghz帯の広帯域を(2402~2480Mhz)!Mhzごと
合計79のチャネルを設定しており、秒間1600回チャネルの切替行いながら通信を行う。
このことで干渉する周波数を発生させる機器が周囲に存在していても
極力影響を減らすことができる。
しかし
ホッピング通信している中でWiFiチャネルと衝突した場合
一般的なWiFiの送信出力が15dBm(30mW)前後に対して
Bluetoothは4dBm(2.5mW)以下なので
衝突するとBlue Toothが負ける
その結果
WiFiはパケット損失を検出して送信レートを下げる(性能微減)
Bluetoothはパケット損失をタイムアウトで検出・再送(性能大減)
</details>

<details><summary>セントラルとペリフェラル</summary>
Bluetoothにおいての役割
セントラルとペリフェラルについて
セントラルは中心機器　ペリフェラルは周辺機器
リモコンがペリフェラル　中央機がセントラルとなる
通信の流れとしては
1.ペリフェラルからセントラルに自分の存在をコネクタ
2.セントラルがそれを検出する
3.アドバタイジングの終了
4.セントラルからペリフェラルへどのような機器なのか調査をする
5.ペリフェラルからセントラルへプロファイルの送信
6.セントラルからペリフェラルへデータ要求
7.ペリフェラルからセントラルへデータ送信
※:アドバタイジング
自分の存在を定期的に発信し続ける
</details>

<details><summary>AFH</summary>
Adaptive Frequency Hopping
パケット損失が頻発するチャネルを検出し
そこを使わないようにして信号を送信する
周波数の住み分け
</details>

## ZigBee

| 技術仕様 |      項目     |
|:--------:|:-------------:|
| 　規格　 | IEEE 802.15.4 |
| 周波数   | 2.4Ghz        |
| 到達距離 | 10m ~ 75m     |
| 伝送速度 | 250kbps       |
| 消費電量 | 60mW          |
| 接続数   | 65535         |


### 特徴
- 伝送スピードは250kbpsとあまり高速ではない
- 消費電力は一番小さい
- 接続数は一番多い
- 消費電力の少なさから数か月から数年の動作が可能である
- デジタル信号がメインなことから音声信号を送信するのは難しい

### NFC
### IrDA


# キーワード
スペクトラム拡散　バーカー符号
grib2をpython(matplotlib)で地図上で可視化

[前回](http://qiita.com/mhangyo/items/8494a8039973ba220ce5)はgrib2ファイルをpythonから操作する環境の構築について説明しました。
今回は読み込んだデータを。matplotlib+basemapで可視化する手法について紹介します。
特にJupyterについては説明しませんが、基本的にJupyter上で試しています(普通にpythonコマンドからでも大丈夫だとは思います)。

# インストール
Anaconda環境であれば

```
apt-get -y install libgl-dev
conda install matplotlib
conda install basemap
```
でmatplotlibとBasemapがインストールできます。
apt-getのところは環境によって変わりますが、ないとmatplotlibのimport時にlibGL.soがないと言われてしまいます。
dockerの場合は、前回のDockerfileに上記の各行の頭にに`RUN`を付けて追記すればOKです。

```bash:Dockerfile
...以下を追記...
RUN apt-get -y install libgl-dev
RUN conda install matplotlib
RUB conda install basemap
```

# grib2データ読み込み
前回説明したpygribを使って、gribデータを読み込みます。前回と同じサンプルを使います。

```
wget -P somepath/ http://database.rish.kyoto-u.ac.jp/arch/jmadata/data/gpv/original/2017/01/02/Z__C_RJTD_20170102000000_MSM_GPV_Rjp_Lsurf_FH00-15_grib2.bin
```
ここからはpython内で作業していきます。
dockerで作業する場合には前回と同様、以下でcontainerを立ち上げて、その中でpythonを起動してください。

```bash
cd path_of_Dokcerfile
docker build -t pygrib_ubuntu .
docker run -it -v /somepath:/temp pygrib_ubuntu
```


```python
import matplotlib
matplotlib.use('Agg') # サーバーでx環境がない場合などはこれがないとmatplotlibが動かない
import pygrib
import matplotlib.pyplot as plt
import numpy as np
import math
from mpl_toolkits.basemap import Basemap


grbs = pygrib.open('/temp/Z__C_RJTD_20170102000000_MSM_GPV_Rjp_Lsurf_FH00-15_grib2.bin')

# selectメソッドで指定した要素(forecastTime=0)にマッチする要素の配列が返ってくる。
# forecastTime=0の要素は複数あるが先頭([0])は海面更生気圧(mslp)が入っている
grb = grbs.select(forecastTime=0)[0]

# lats,lonsは二次元配列で緯度経度が入っている
lats, lons = grb.latlons()

# 中に含まれているデータ(海面更生気圧)を二次元のndarrayで取り出す
mslp = grb.values
```
これで可視化に必要な、緯度経度とその地点のデータ(海面更生気圧)をgribから取り出すことができました。

# 可視化
続けて、天気図っぽく等圧線を描いていきます。

```python
# 等圧線をひく間隔をlevelsにリストとして入れる
# MSLPの単位はPaなので、2hPaごとに線をひく場合、200おきに線をひくことになる。
levels = range(math.floor(mslp.min()/100)*100, math.ceil(mslp.max()/100)*100+1,200)

# lat,lonを一次元に変換
# 何故か二次元のままでは描画できない
flat_lats= np.ravel(lats)
flat_lons= np.ravel(lons)

fig = plt.figure()

# マップを作成。4つのパラメータは描画する範囲の指定
m = Basemap(llcrnrlat=lats.min(),urcrnrlat=lats.max(), llcrnrlon=lons.min(),urcrnrlon=lons.max())

# 等圧線をひく
m.contour(flat_lons, flat_lats,mslp,latlon=True,tri=True,levels=levels)

# 海岸線をひく
m.drawcoastlines() 

fig.savefig('/temp/mslp.png')
```

![mslp.png](https://qiita-image-store.s3.amazonaws.com/0/113628/8f9ab0b8-6cad-1642-18da-581db0100ee1.png)

こんな感じで絵が出来上がります。

出力の際に以下のようなwarningsが出ますが、とりあえずは影響ないので気にしないことにしましょう。

```
/root/.pyenv/versions/anaconda3-4.1.1/lib/python3.5/site-packages/mpl_toolkits/basemap/__init__.py:3505: MatplotlibDeprecationWarning: The ishold function was deprecated in version 2.0.

  b = ax.ishold()

/root/.pyenv/versions/anaconda3-4.1.1/lib/python3.5/site-packages/mpl_toolkits/basemap/__init__.py:3572: MatplotlibDeprecationWarning: axes.hold is deprecated.

    See the API Changes document (http://matplotlib.org/api/api_changes.html)

    for more details.

  ax.hold(b)
```
C | C++ > comment > HACK: > 「とりあえず動いているけど、良い実装ではない」ような状況に今後の改善を期待して付けるコメント |  C++:[[deprecated]] 属性

関連 [Ruby | アノテーションコメント（TODO、FIXME、OPTIMIZE、HACK、REVIEW）](http://qiita.com/tbpgr/items/1c046a877c6be4d89876)

Ruby Style Guideにおいて「HACK」というキーワードが紹介されている。

過去に読んだ本で「HACKME」があったかと思っていたが、「HACK」の間違いだったようだ (FIXMEとごちゃまぜに記憶)。

@ The Art of Readable Code 
No. 1756 / 6036

> TODO: Stuff I haven't gotten around to yet
> FIXME: Known-broken code here
> HACK: Admittedly inelegant solution to a problem
> XXX: Danger! major problme here

「とりあえず動いているけど、良い実装ではない」ような状況に今後の改善を期待して付けるコメントと認識している。

`HACK:`というキーワードは検索しやすいだろうか。

すでに記事にしていたようだ。
[comment > FIXME: / HACK:](
http://qiita.com/7of9/items/c7920e8b1539f01b4b84)


### 教えていただいた事項
(追記 2017/08/02)

@SaitoAtsushi さんの[コメント](http://qiita.com/7of9/items/cb7e302d9c7f388c09af/#comment-547186fd9c7fdd451d6e)にて[[deprecated]] 属性を教えていただきました。

情報感謝です。
ベースイメージのENTRYPOINTを無効化

## 問題

ベースイメージのDockerfileに`ENTRYPOINT [...]`が書かれているものを使うときとか。
Dockerfileをbuild後、確認で一旦`docker run -it ... bash`とかで入りたくても、ベースイメージの`ENTRYPOINT`の引数みたいになってしまい入れない。

## 解決

書いてるDockerfileのどこかに`ENTRYPOINT []`と書くだけ。


---

追記

次の２つの方法でもできます。

## `docker run`時に`--entrypoint ''`を渡す

```bash:例
docker run --entrypoint '' --rm -it <image> <command>
docker-compose run --entrypoint '' --rm <service> <command>
```

## `docker-compose`で`entrypoint: []`を設定する

```yaml:例
services:
  <service>:
    image: ...
    entrypoint: []
```
Just my memo

 - How to create pip private repository
    - https://gist.github.com/Jaza/fcea493dd0ba6ebf09d3
 - How to install docker on ubuntu 16.04
    - https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-16-04
 - How to run docker registry
    - https://hub.docker.com/r/hyper/docker-registry-web/
Bluemix の Cloudant に ruby で画像ファイルをアップロード

次のページで行うことと同じことを、ruby で行いました。
[Bluemix の Cloudant に python3 で画像ファイルをアップロード](http://qiita.com/ekzemplaro/items/89e831e30c56e0773d2d)

```rb:to_cloudant.rb
#! /usr/bin/ruby
# -*- encoding: utf-8 -*-
#
#	to_cloudant.rb
#
#					Jul/28/2017
#
require 'json'
require 'restclient'
#
# ---------------------------------------------------------------------
puts "*** 開始 ***"
#
url="https://44b508dd-f312-4f91-81f2-78369c7d29d9-bluemix:9dacdfdee142c2a5c16596fc621012e08a61e7132d3b21ecaaf1f63a835fae64@efc189dc-f332-4f91-81f2-72569c7d39d9-bluemix.cloudant.com"
#
#
url_collection = url + '/jpg'
RestClient.delete url_collection
RestClient.put url_collection, '{}'
#
keys=["A0001","A0002"]
#
keys.each {|key|
	puts key
	file_jpg = key + '.jpg'
	url_target  =  url_collection + '/' + key + '/' + file_jpg
	puts url_target
	io = open(file_jpg,"rb")
	image = io.read()	
	RestClient.put url_target, image
	}
#
puts	"*** 終了 ***"
#
# --------------------------------------------------------------------------
```
Bluemix の Cloudant から、 ruby で画像ファイルをダウンロード

次のページで行うことと同じことを、PHP で行いました。
[Bluemix の Cloudant から、python3 で画像ファイルをダウンロード](http://qiita.com/ekzemplaro/items/5fcc8643a8a7711bca5b)

```rb:from_cloudant.rb
#! /usr/bin/ruby
# -*- coding: utf-8 -*-
#
#	from_cloudant.rb
#
#					Jul/28/2017
#
require 'restclient'
require 'json'
#
# ---------------------------------------------------------------------
#
puts	"*** 開始 ***"
#
#
url="https://44b508dd-f332-4f91-81f2-78369c7d29d9-bluemix:9dacdfdee131c2a5c16596fc371012e08a61e7132d3b21ecaaf1f63a265fae64@efc189dc-f332-4f51-81f2-78391c7d29d9-bluemix.cloudant.com"
#
url_collection = url + '/jpg'
url_docs  =  url_collection + '/_all_docs'
puts url_docs
str_json = RestClient.get url_docs
#
list_aa=JSON.parse(str_json)
#
dict_aa={}
list_aa['rows'].each {|row|
	key = row['key']
	file_jpg = key + '.jpg'
	puts key
	url_target  =  url_collection + '/' + key + '/' + file_jpg
	puts url_target
	image = RestClient.get url_target
	File.open(file_jpg,"w") do |fp_out|
		fp_out.puts image
	end
	}
#
puts	"*** 終了 ***"
#
# ---------------------------------------------------------------------
```
【質問】HTML・JavaScriptを自動解釈してくれるライブラリやツールを探しています。

■概要
HTML・JavaScriptを自動解釈してくれるライブラリやツールを探しています。

■詳細
疑似WEBブラウザを開発中です。

指定したURLへのHTTPリクエストを飛ばして返ってきたレスポンス(HTML・JavaScript)を自動処理して、
後続のHTTPリクエストも飛ばす、というものです。

1回目のクリエストを飛ばしてレスポンスを取得するところまでは開発が完了していますが、
そのレスポンスを自動で解釈して次のHTTPリクエストを発行する機能を作りたいのです。

これを愚直に行うと、
レスポンス内容の中からURLに該当する文字列をピックアップしてURLを抽出して後続のリクエストを飛ばす・・となってしまいますが、
近年JavaScriptが自動的にリクエストを飛ばす処理も多くみられますので、現実的ではありません。

なので、2回目以降のリクエストを自動的に行うために、
HTML・JavaScriptを自動解釈して、2回目以降のリクエストURLを抽出してくれるようなライブラリやツールを探しています。

良いライブラリやツールをご教授下さい。(URLやライブラリ名など)
厳密じゃなくても似たようなものでも結構です。
※ちなみにWEBブラウザのような表示機能は不要です。あくまでHTTPリクエストを飛ばしたいだけです。

■開発環境(本質問とはあまり関係ないですが一応掲載します)
Microsoft Visual Studio Express 2012 for Windows Desktop
C++ CLI(NET Framework)
Swift3でアプリのバージョンを比較する


# はじめに

Swift3でのバージョンの比較方法で、基本的にはSwift2時代やObjective-Cの時と同じだがいつも調べてしまうので、備忘録的に残しておきます。

# バージョンの比較

Playgroundにコピペすれば動きます。


```swift
import Foundation

let currentVersion = "0.9.25"
let targetVersion = "0.10.1"
let shouldUpdate = currentVersion.compare(targetVersion, options: .numeric) == .orderedAscending

if shouldUpdate {
    print("current version (\(currentVersion))", "<", "target version (\(targetVersion))")
}
else {
    print("current version (\(currentVersion))", ">=", "target version (\(targetVersion))")
}
```
kotlinでHashMapの実装

#HashMap
HashMapをkotlinで実装した。
idがkeyで名前がvalue


```kotlin:maptest.kt

import java.util.Scanner
import java.util.InputMismatchException

var map = kotlin.collections.HashMap<Int , String>()

fun main(arg : Array<String>) {
    val input = Scanner(System.`in`)
    var i : Int
    try {
    loop@ while(true) {
            println("何をしますか?\n" +
                    "入力 =>1" + "表示=>2" + "探す=>3" + "削除=>4"+ "終了=>5")
            i = input.nextInt()
            when (i) {
                1 -> {
                    Scan()
                }
                2 -> {
                    println(map)
                }
                3 -> {
                    search()
                }
                4 -> {
                    delete()
                }
                5->{
                    break@loop
                }
            }
    }
    }catch(e : InputMismatchException){
        println("型が違います : " +e)
    }
}

```

```kotlin:map.kt
import java.util.*
val input = Scanner(System.`in`)

fun search(){
    val key : Int
    println("idを入力してください")
    try {
        key = input.nextInt()
        if (map.containsKey(key)) {
            println("$key =" + map.get(key))
        } else {
            println("そのidは存在しません")
        }
    }catch (e : InputMismatchException){
        println("型が違います : ")
    }
}
fun Scan(){
    println("名前を入力してください")
    val name =  input.next()
    println("idを入力してください")
    val key : Int = input.nextInt()
    try {
        if (map.containsKey(key)) {
            println("上書きしますか?\n" +
                    "はい=>1いいえ=>2")
            when (input.nextInt()) {
                1 -> {
                    map.put(key, name)
                }
                2 -> {
                }
            }
        } else {
            map.put(key, name)
        }
    }
    catch (e : InputMismatchException){
        println("型が違います : ")
    }
}
fun delete() {
    println("全削除=>1　１データ削除=>2 キャンセル=>3")
    try {
        when (input.nextInt()) {
            1 -> {
                map.clear()
            }
            2 -> {
                println("削除するidを入力してください")
                val keyid: Int = input.nextInt()
                map.remove(keyid)
            }
            3 -> {
            }
        }
    }catch (e : InputMismatchException){
        println("型が違います : ")
    }
}


```

名前を日本語で入力やリトライなどの実装はまたこんど。
日本語・漢字を2byteとして換算してtruncateする

Railsには、`truncate`というメソッドがある。
http://api.rubyonrails.org/classes/String.html#method-i-truncate

まぁ長い文字列を短縮してくれるメソッドなのは言わなくてもわかると思われるが、
半角英数字と日本語が混ざったりしていると、思ったところで短縮してくれなくて困る・・・・

```
"0001: 僕は新世界の神となる".truncate(10)
"なにがなんだかわからない・・・".truncate(10)
"fafafa!!! 無とは一体...".truncate(10)
=>
"01: 僕は新..."
"なにがなんだか..."
"fafafa!..."
```

そこで、マルチバイトを2byteとして換算して、`truncate`してくれるメソッドを書いてみた。

```ruby
class String

  # 全角文字を半角の2個分と扱ってtruncateを行う
  # truncate_atで指定された字数を超えない(切り捨て)
  #
  # @return [String] 短縮された文字列
  def my_truncate(truncate_at, options = {})
    omission = options[:omission] || '...'

    if size == bytesize
      truncate(truncate_at, options)
    else
      size.times do |i|
        str_size = (self[0..i].bytesize - self[0..i].size) / 2 + self[0..i].size
        next if str_size < (truncate_at - omission.size)

        return "#{ self[0..i] }#{ omission }" if str_size == (truncate_at - omission.size)
        return "#{ self[0..(i - 1)] }#{ omission }"
      end

      return self
    end
  end
end
```

実行してみる・・・

```
"01: 僕..."
"fafafa!..."
"なにが..."
```

いい感じ。
Railsなので、`config/initializers/string_extension.rb`とか作って、
書いておけば、Stringで実行できる
Dockerコンテナにsshアクセスしたいけど忘れるのでコマンドをまとめとく

少しずつ利用する場面が増えてきてやり方を覚えてはきたけど、
ググる頻度が高いコマンドをメモっておく。

## イメージのビルド

```sh
docker build . -t イメージ名
```
[オプション説明]
-t イメージに名前つける

## コンテナの起動

- バックグラウンドで起動しつつ、execでssh接続したい

```shell-session
docker run -id --rm --name コンテナ名 イメージ名
```

- コンテナを起動しつつ、(即)コマンドを実行したい

```shell-session
docker run --rm イメージ名 実行したいコマンド
```

- ホストのディレクトリをマウントして利用したい

```shell-session
-v [マウントしたいホストのパス]:[マウントしたいコンテナパス]

(e.g.) docker run -id -v $(pwd):/tmp --rm --name コンテナ名 イメージ名
```

[オプション説明]
-i ホストの入力をコンテナの標準出力をつなげる。指定なしだと起動してすぐ停止しちゃう。
-d バッググラウンドで起動する。指定なしだと制御が戻ってこない。
--rm コンテナが停止した時にプロセスも削除する。
--name 起動したコンテナに名前をつける。
-v ホストのディレクトリを、コンテナ内でマウントする。

## コンテナへのアクセス

- バックグラウンドで起動したコンテナにsshアクセスしたい

```shell-session
docker exec -it コンテナ名 実行コマンド

(e.g.) docker exec -it container1 bash
```
Cloud9 で開発言語をpython3に変更しても python --version　でバージョン２と表示される件

こちらを参考にさせていただきました。

https://teratail.com/questions/32152

##質問
Cloud9を利用してPythonを学習しているところですが、Pythonのバージョンを2.7から3.xに変更しようと思い、PROJECT SETTINGSのLanguage SupportでPython VersionをPytyon3に変更しても、Python -Vで確認すると2.7.6と表示されます。他に何か必要な手順があるかどうかご教示ください

##回答
PROJECT SETTINGS を変更する方法はわかりませんが、terminal で変更するのであれば 
以下でできました。

python コマンドは which python とすると 
/usr/bin/python 
にあることがわかります。 
ls -l /usr/bin/python 
でこれがシンボリックリンクになっていることがわかります。 
このシンボリックリンクの実体を変更することで他のバージョンのpython を使えます。 
$ ls -l /usr/bin/python 
lrwxrwxrwx 1 root root 18 Apr 12 13:43 /usr/bin/python -> /usr/bin/python3.5* 
$ python -V 
Python 3.5.1

シンボリックリンクの変更は以下のような方法でできます。 
$ sudo bash 
$ rm /usr/bin/python 
$ ln -s /usr/bin/python3.4 /usr/bin/python 
$ python -V 
Python 3.4.3
sshfsの接続が切れた時のエラーの対処

## 概要

前回紹介した記事で【[vimからVisual Studio Codeへの乗り換え方【Mac】](http://qiita.com/nrainiero/items/475c299905b3f89222b0)】というものを紹介したのですが、
PCが長時間スリーブになったときとかにsshfsの接続が切れてしまう時があります！

接続が切れてしまうと...どうなるかというと...

```
$ ls hoge/                   // sshfsでマウントしたディレクトリ
ls: : Device not configured  // Errorがでます
```
ディレクトリが壊れています:persevere:(正しい表現かは分かりませんが)

もう一度sshfsでマウントしようとしても...

```
sshfs [username]@[domain]:/ hoge/
mount_osxfuse: mount point hoge is itself on a OSXFUSE volume  // マウント失敗...
```
エラー...:sob:

こんなときは、一旦アンマウントします！

```
umount -f hoge/ // -f で矯正的にアンマウントします！
```

そして、もう一度マウントしましょう！

```
sshfs [username]@[domain]:/ hoge/
```

これで成功するはずです！:ok_hand:

快適なGUIライフを♬
C++ Builder > property > float型のpropertyの場合、String型の引数を持つsetterは使えないようだ

```txt:動作環境
C++ Builder XE4
```

以下を考えていた。

- 入力: L"1e-7" : String
- 出力: L"1e-7" : String
- 保持変数: float

float型のpropertyに対してはString型の引数を持つsetterは使えなさそう。

下記にて質問をしていて、回答いただいた。
https://stackoverflow.com/questions/45341664/c-builder-property-with-setterstring-causes-error-e2034-cannot-convert

全部をString型にする場合、ToDouble()などを使うことになり、それは自分が考えていたこととは合わない。
[クイズ]javascriptと仲良くなるための一歩　第１１話「if文」

#問題

```js
var hoge=0
var piyo=1
var fuga="fuga"

if(hoge==0)
  if(piyo==0)
    fuga="a";
else
  fuga="c";

fuga //=> ?
```

:mouse:
:cow:
:tiger:
:rabbit:
:dragon_face:
:snake:
:horse:
:sheep:
:monkey_face:
:bird:
:dog:
:boar:
:mouse:
:cow:
:tiger:
:rabbit:
:dragon_face:
:snake:
:horse:
:sheep:
:monkey_face:
:bird:
:dog:
:boar:


#答え

```js
var hoge=0
var piyo=1
var fuga="fuga"

if(hoge==0)
  if(piyo==0)
    fuga="a";
else
  fuga="c";

fuga //=> "c"
```

インデントの違いはコードの意味に影響を与えない。
このコードのelse節は、
`if(hoge==0)`には対応せず
`if(piyo==0)`に対応している。
見た目のインデントと実際の動作に乖離がある。


以下のコードのように、
ブロック文を使えば、曖昧さを回避できる。

```js
var hoge=0
var piyo=1
var fuga="fuga"

if(hoge==0){
  if(piyo==0){
    fuga="a"
  }
}else{
  fuga="c"
}
```
RectTransformを動かす

RectTransformのTransformは読み取り専用
（アンカーを基準点として位置を決めているから）

RectTransformの持つ変数
anchoredPosition:アンカー基準点に対する RectTransform の相対的なピボットの位置
を動かせばよい。



```csharp:test.cs

Vector2 v1 = new Vector2 (-50.3f, -5.45f);
GetComponent<RectTransform>().anchoredPosition = v1;
```
Python > 実装 > 数値が入っているか | alphabet(upper and lower case)が入っているか > sum(), map(), str.isalphaの使用

```txt:動作環境
Python3
```

特定の文字列に以下の確認をする。

- 数値が１つでも入っているか
- alphabetが１つでも入っているか

### v0.1

http://ideone.com/H6gVVV

```py
checkalpha = lambda t:[e for e in t if e.isalpha()]
checkdigit = lambda t:[e for e in t if e.isdigit()]

atxt = '1234b'
print(checkalpha(atxt))
print(checkdigit(atxt))

btxt = '12345'
print(checkalpha(btxt))
print(checkdigit(btxt))
if len(checkalpha(btxt)) == 0:
	print("no alphabet")
```

```txt:run
['b']
['1', '2', '3', '4']
[]
['1', '2', '3', '4', '5']
no alphabet
```

正規表現使う方が楽だろうか。

### v0.2

len()をlambda式に入れた。

```py
numalpha = lambda t:len([e for e in t if e.isalpha()])
numdigit = lambda t:len([e for e in t if e.isdigit()])

atxt = '1234b'
print(numalpha(atxt))
print(numdigit(atxt))

btxt = '12345'
print(numalpha(btxt))
print(numdigit(btxt))
if numalpha(btxt) == 0:
	print("no alphabet")

```

```txt:run
1
4
0
5
no alphabet
```

### v0.3

- Upper, lower case letterのチェック

http://ideone.com/C74yMc

```py
numlower = lambda t:len([e for e in t if e.islower()])
numupper = lambda t:len([e for e in t if e.isupper()])
numdigit = lambda t:len([e for e in t if e.isdigit()])


def checkfunc(txt):
	print("===%s===" % txt)
	print("lower:%d, upper:%d, digit:%d" % 
	      (numlower(txt), numupper(txt), numdigit(txt)))
	if numlower(txt) == 0:
		print("no lower case letters")
	if numupper(txt) == 0:
		print("no upper case letters")	
	if numdigit(txt) == 0:
		print("no digits")

atxt = '1234b'
checkfunc(atxt)
btxt = '12345'
checkfunc(btxt)

```

```txt:run
===1234b===
lower:1, upper:0, digit:4
no upper case letters
===12345===
lower:0, upper:0, digit:5
no lower case letters
no upper case letters

```

### 参考

https://docs.python.org/3/library/stdtypes.html

### v0.4 

@SaitoTsutomu さんの[コメント](http://qiita.com/7of9/items/b5a307fed35f333f1d29/#comment-08652be67cebfb281ecf)にてsum(), map(), str.isalphaなどの使用方法を教えていただきました。

情報感謝です。

http://ideone.com/oTCBE4

```py
numlower = lambda s:sum(map(str.islower, s))
numupper = lambda s:sum(map(str.isupper, s))
numdigit = lambda s:sum(map(str.isdigit, s))


def checkfunc(txt):
	print("===%s===" % txt)
	print("lower:%d, upper:%d, digit:%d" % 
	      (numlower(txt), numupper(txt), numdigit(txt)))
	if numlower(txt) == 0:
		print("no lower case letters")
	if numupper(txt) == 0:
		print("no upper case letters")	
	if numdigit(txt) == 0:
		print("no digits")

atxt = '1234b'
checkfunc(atxt)
btxt = '12345'
checkfunc(btxt)

```

```txt:run
===1234b===
lower:1, upper:0, digit:4
no upper case letters
===12345===
lower:0, upper:0, digit:5
no lower case letters
no upper case letters

```

### 参考 > map()

https://docs.python.jp/3/library/functions.html#map
Rustでソートアルゴリズム (0)まとめ

## 記事一覧
[(1)バブルソート・コムソート](http://qiita.com/chalharu/items/c18f98635f1c52d5c662)
[(2)挿入ソート・シェルソート](http://qiita.com/chalharu/items/3fe582b2fde39f45bf1e)
[(3)選択ソート・ヒープソート](http://qiita.com/chalharu/items/0d1abd098b902a821775)
[(4)マージソート](http://qiita.com/chalharu/items/71434d8c0cf40815327f)
[(5)クイックソート・イントロソート](http://qiita.com/chalharu/items/40b4da4d4a88d509a214)
[(6)バケットソート・基数ソート](http://qiita.com/chalharu/items/17e81a674ed590ba997b)
[(7)バイトニックソート (SIMDで高速化)](http://qiita.com/chalharu/items/d08b6b93b29e1f5d0951)

## ベンチマーク

[i32]をソートした際の速度
![ベンチマークグラフ](https://docs.google.com/spreadsheets/d/1qHc6WlESQGLWURCrliuBnYB0u9qkyzT6zwjomCz0qWc/pubchart?oid=1758926128&format=image)
https://docs.google.com/spreadsheets/d/1qHc6WlESQGLWURCrliuBnYB0u9qkyzT6zwjomCz0qWc/pubchart?oid=1758926128&format=interactive
都道府県名の一覧取得 【プログラミングに使いやすい形で】

[都道府県一覧のページ](http://elze.tanosii.net/d/kenmei.htm)から都道府県名だけ抽出して整形するコマンド


```
curl http://elze.tanosii.net/d/kenmei.htm | nkf -w80 | grep -e "都" -e "道" -e "府" -e "県" | grep -e "^   <TD>" | cut -d ">" -f 2 | cut -d "(" -f 1 | perl -pe "s/^(.*)$/\'\1\',/g"
```

**出力**

```
'北海道',
'青森県',
'岩手県',
'宮城県',
'秋田県',
'山形県',
'福島県',
'茨城県',
'栃木県',
'群馬県',
'埼玉県',
'千葉県',
'東京都',
'神奈川県',
'新潟県',
'富山県',
'石川県',
'福井県',
'山梨県',
'長野県',
'岐阜県',
'静岡県',
'愛知県',
'三重県',
'滋賀県',
'京都府',
'大阪府',
'兵庫県',
'奈良県',
'和歌山県',
'鳥取県',
'島根県',
'岡山県',
'広島県',
'山口県',
'徳島県',
'香川県',
'愛媛県',
'高知県',
'福岡県',
'佐賀県',
'長崎県',
'熊本県',
'大分県',
'宮崎県',
'鹿児島県',
'沖縄県',
```
#1 久しぶりのPerlことはじめ。Mojoliciousを利用する。

何年、いや１０年ぶりくらいにperlの世界へ訪れることになりました。
シンタクス等も大幅に変更が見られ、何から手を付けていこうかと考えては見ましたが、同時にワクワクが止まりません。
CGIを利用したWEBサービスという意味では今も昔も変わらないと思うので、代表的なWEBフレームワークの中から

Mojoliciouを選択（発音は、モジョリシャスが有力。）

これは、開発用に、Nodeに似たイベント駆動型のビルトインWEBサーバを内包しているようで、
ホットデプロイ（インタプリタではあるが、プリコンパイルされたコードがオンメモリされるためか？）等に対応しているらしい。
なるほど。

なんにせよまずは、環境のインストールを行います。
以下のサイトを参考にさせていただきました。
https://github.com/yuki-kimoto/mojolicious-guides-japanese/wiki/Mojolicious%3A%3AGuides%3A%3ACookbook
Mojoliciousを始めるにあたって公式の次に読むべきサイトとして最適と思います。有用な情報を発信してくださっている偉大な先人の方々に感謝です。

自前の開発サーバがCentOS7(64bit)なので、yumによる作業が続くことになるでしょう。

私の持論として、
「どのような開発環境もまずは公式を見て。環境の条件が合う限り、公式に沿ってインストールする。」
というものが（おぼろげながら）あります。
最近はこちらのQiitaさんや海外でいえばStackoverflow等、大量のアウトプットがなされていますが、
同時にOSを始めとしたサーバ環境も多種多様で、さらにはバージョンの差異も絡んできます。
適当にシングルワードで検索し、「入門」や「インストール」などの記事をなぞって実行しても
まずうまくいきません。

私の場合、常識かもしれませんが、意外と利用されていないTIPSとして、目的のキーワードを用いて、Google検索の結果を得た後に、上部メニューの「ツール」から「期間指定なし」のプルダウンで期間を選択すると
指定した期間で更新順のソートがなされるので、変化の激しい情報をお探しの方はこれを利用することで、
かなり早く、少しでも正確な目的の情報を取得しやすいのではないかと思います。


話を戻してインストールの準備ですが、Mojolicious以前に、Perlには、「perlbrew」や「cpanm」と呼ばれる、便利なパッケージマネージャがあり、perl自身のアップグレード等も楽に行えるようです。かつ、スコープをローカルにとれるため、NodeJSのようにディレクトリ完結ですっきり開発できるのは嬉しいところです。

まずはお約束

```bash
$ yum update
$ yum install perl perl-devel
```


「perlbrew」は、公式（https://perlbrew.pl/）
を参考に該当するOS用のインストール方法からさくっとインストールしてください。
その後、実行ディレクトリに「perl5」ディレクトリが作成され、基本的にはそこに、perlbrewの実行ファイルや、インストールしたモジュールがおかれるようです。
インストール後のログにもありますが、~/perl5/perlbrew/etc/bashrcへのパスの追加をお忘れなく。

```bash:~/.bash_profileへ追記
echo "source ~/perl5/perlbrew/etc/bashrc" >> $HOME/.bash_profile
```
プロファイルを再読込するとperlbrewコマンドが利用可能になりますので、
perlのバージョンもここでアップデートしておきました。

```bash
$ perlbrew install perl-5.20.2
```

こちらは非常に時間がかかります、動いているか不安になるほどです。
しかし、ログの最後に別端末からインストールプロセスをtailで参照しろとありますので、下記コマンドで詳細を確認できます。
（以下コマンドは別端末で実行します）

```bash:
$ tail -f ./perl5/perlbrew/build.perl-5.20.2.log
```

「cpanm」もperlbrewでインストール。
```
$ perlbrew install-cpanm
```




そして本題のMojolicious、まずは公式サイトに行ってみます。
http://mojolicious.org/

Instllationの部分には早くも、他サイトでご紹介いただいている内容とは違う、ワンライナーが見て取れます。（それらが間違っているとは限りませんので初心者の方はご注意を）

```
$ curl -L https://cpanmin.us | perl - -M https://cpan.metacpan.org -n Mojolicious
```
繰り返しになりますが、公式サイトが上記と違う場合はすでにこの記事は古いので、これ以降は読まない方が無難です。


cpanmによるインストールは

```
$ cpanm Mojolicious
```
でした。


それでは早速実行テストを。
公式のサンプルプロジェクトとして表記されているヘロワの実行ですが、
適当なプロジェクト用ディレクトリを作成し、その中にapp.plとして書きました。


```perl:~/helloworld/app.pl
use Mojolicious::Lite;

get "/" => {text => "HelloWorld!"};
app-start;
```


そして、Mojoliciousのビルトインサーバで確認するため、サーバの実行です。

```bash
$ morbo ~/helloworld/app.pl
```

起動に成功すればURLが表示されます。デフォルトではhttp://127.0.0.1:3000ですのでブラウでで確認し、
「HelloWorld!」の文字列が確認できれば成功です。

次回はリバースプロキシにnginxを用いたSSLへの対応です。
clara-rulesの世界(3)

[前回](http://qiita.com/iku000888/items/17ad5f7fa2f0da069997)

clara-rulesは異るエンティティ間のジョイン操作に使えるという知見を講演の動画から得たので、自分で簡単な例を実装してみた。

## 問題
- TypeA
    - 属性attr-aとjoin-keyを持つ
- TypeB
    - 属性attr-bとjoin-keyを持つ
- TypeC
    - 共通のjoin-keyを持つTypeA.attr-aとTypeB.attr-bを属性に持つ


## コード

```clj
(ns  clara-rules.join
  (:require [clara.rules :refer [defrule fire-rules insert insert! mk-session]]))

(defrecord TypeA [attr-a join-key])

(defrecord TypeB [attr-b join-key])

(defrecord TypeC [attr-a attr-b join-key])

(defrule Join
  [TypeA (= ?jk-a join-key) (= ?a attr-a)]
  [TypeB (= join-key ?jk-a) (= ?b attr-b)]
  =>
  (insert! (->TypeC ?a ?b ?jk-a)))

(defrule Print
  [?result <- TypeC];; Will always match
  =>
  (println ?result))

(-> (mk-session)
    (insert (->TypeA "a1" :foo)
            (->TypeA "a2" :bar)
            (->TypeA "a3" :baz)
            (->TypeB "b1" :foo)
            (->TypeB "b2" :bar)
            (->TypeB "b3" :baz)
            (->TypeB "b4" :qux))
    (fire-rules))
;;#clara_rules.join.TypeC{:attr-a a1, :attr-b b1, :join-key :foo}
;;#clara_rules.join.TypeC{:attr-a a2, :attr-b b2, :join-key :bar}
;;#clara_rules.join.TypeC{:attr-a a3, :attr-b b3, :join-key :baz}
```

- 狙いの通り共通の`:join-key`を持つTypeAとTypeBのペアに対してTypeCがプリントされている。やったね!
- `(->TypeB "b4" :qux)` は同じ`:join-key :qux`を持つTypeAのファクトが無いため結果に表れない。なるほど。

## `defrule左辺`の`<-`の説明
ファクトの属性ではなく、ファクトそのものを変数に束縛する。
`[?result <- TypeC]`を例にとると、マッチしたTypeCのインスタンス全体が?resultに束縛される

## 感想
* インメモリのジョインのロジックを、SQLとは異るアプローチで宣言的に書くことができる
* 例えばDB上のジョイン操作が水平スケーラビリティのボトルネックになっている場合に、ジョイン操作をアプリケーションの方でインメモリで行うように変更するのに使えるかもしれない。
    * あるいはデータはあるけどそれクエリをかけることができない環境とかで役に立つかもしれない

[続編](http://qiita.com/iku000888/items/67bcf71602c3d2af315f)
[Unity] ComputeShaderをShader.Find()のように取得する

![unity.jpg](https://qiita-image-store.s3.amazonaws.com/0/127402/dae70c33-dfa6-4cdc-5d8f-9fdb73a57a56.jpeg)

# まえがき
ComputeShaderには、Shaderクラスに用意されているFind()関数のような、オブジェクト取得用の関数がありません。
通常はインスペクタから直接アタッチすることでComputeShaderを利用します。

しかしながら、この手法では、
ComputeShaderが用いられたパッケージを使用する際、
ユーザーが誤って別のComputeShaderをアタッチしてしまう問題が発生してしまいます。

# 解決方法
任意のファイル階層にResourcesフォルダを作成し、
目的のComputeShaderファイル (MyComputeShader.compute) を置きます。

その結果、以下のスクリプトで目的のファイルを取得をすることが可能になります。

```csharp:Sample.cs
ComputeShader cs = (ComputeShader)Resources.Load("MyComputeShader");
```
TensorFlowの教師データ画像を効率的に収集する為にChrome拡張機能(Thumbnail Zipper)を作った

#Thumbnail Zipper
GoogleやBingの画像検索, Instagram, Tumblr, Pinterest, その他多くのサイトから画像をDownloadできます。
この拡張機能は、画像認識の教師データを効率的に集める為に作りました。

#使い方
- [Chromeウェブストア](https://chrome.google.com/webstore/detail/thumbnail-zipper/pdoifakofdpigaogingadnffcnldlmep
)から「Chromeに追加」
- 画像をダウンロードしたいサイトを表示
- 下にスクロールして、「Download zip file」をクリック

![download.png](https://qiita-image-store.s3.amazonaws.com/0/120681/e068cd28-34a5-11cc-306f-7dec8f664944.png)

※何故か英語ですがシンプルなので気にしないでください

#作ることになったきっかけ
TensorFlowの勉強を始めたところ、教師データを用意することが凄く面倒である事が分かってきた。
私は面倒なことは出来ないので楽できる方法を探した結果、Chrome拡張作成に繋がった話が以下に続きます。

はじめはGoogleの画像検索などからゲットしてこれば良いと単純に思っていたのですが、検索結果の画像を
一括で得る良い方法が無く、手作業で集める方法しか思いつかなかった。

他の人の例を調べてみると、クローラー的な方法で集めている記事をいくつか見た。
みんな泥臭いことしてるなと尊敬の念を感じつつ、私も例に習ってクローラーを組むことに。

クローラーで最初に使ったのはTumblrのAPI。
使い始めは特に問題が無かったのだが、Tumblrでは特定のタグだと結果が返ってこない問題に出会った。
具体的には、「美少女」タグでは結果が返って来るが、「女子高生」タグでは結果が返ってこない。

謎である。

タグを色々と変えて調べてみると、結果的にはエロ系のタグが駄目な様子。
女子高生はエロワードなのかよ・・・というツッコミを入れたいが、Tumblrではそうなのかと自己完結。
Tumlbr側の設定で、何かしらの制限を解除するような項目も無さそう。
何かしら制限やってる可能性あるなぁと思える[記事](https://nihongo.tumblr.com/post/56281520452/tumblr%E3%81%8Cnsfw%E3%82%A2%E3%83%80%E3%83%AB%E3%83%88%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%E3%82%92%E6%A4%9C%E9%96%B2%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%81%A8%E3%81%84%E3%81%86%E6%87%B8%E5%BF%B5%E3%81%8C%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AE%E9%96%93%E3%81%A7%E5%BA%83%E3%81%BE%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E3%81%93%E3%81%A8%E3%81%AF%E7%A7%81
)も見つけた

APIではなくHTMLを解析する方法も考えたが、クローラーはいったん諦め、仕切り直しすることに。

#状況整理

改めて、その時の状況を整理すると

- TensorFlowでどれだけのことが出来るかを知りたい
- キーワードごとに数百枚程度の画像をダウンロードしたい(解像度は低くても良い)
- サイト、キーワードごとに出てくる画像のキーワードとの関連度も異なるので複数のサイトから取りたい
- とりあえずはGoogleやBing画像検索, Tumblr, Instagram, Pinterest, Flickrあたりを想定
- 可愛い女の子の画像でテストしたい(重要)＝つまり女子高生という分類も重要になる(諦めれない)

という状況だった

#調査

上記を実現していく為に、複数サービスのクローラーを作っていくのは大変だなぁと思った
そこで考えたのがブラウザの拡張機能で、ブラウザ上に表示されている画像を全て取得する方法である
その方法だとTumblrの制限も回避できると考えた

最初は自分で作るつもりなどなくて、そういう拡張機能はあるだろうと思い、Chromeで探していたのだが、中々要望を満たせるものを見つけることが出来なかった。惜しい物は沢山あったが、Ajaxなどを使った画面更新や、無限スクロールの先の画像まで追ってくれるものは中々無さそう。

※ちなみに、諦めが早いタイプなので調べると他にあるかも(ついでにChromeしか調べていない)

#作った
要望を満たすものが、見つけれなかったので試行錯誤しながら作ることに
どのようにして作ったか、技術的な話はまた別の機会にしようと思う
拡張機能はほぼ初挑戦だったので色々勉強になった。JavaScriptの時代だなと改めて感じた。

#特徴
- 無限スクロールなどで画面更新した場合の画像も追う(スクロール毎にDOMをチェック)
- ~~imgタグのsrcの中身しか見ていない(divのbackground-imageなどは見ていない。その為Flickrは未対応)~~ divとulのbackground-imageも見るように修正しました (2017-07-28追記)
- 画像全てを見るのでゴミ画像も含まれる
- まとめてzipファイルでダウンロード
- GoogleやBing画像検索, Tumblr, Instagram, Pinterest, Flickrで動作を確認



#最後に

最後まで目を通してくれて感謝です、ちなみにこの記事がQiitaで初投稿だったりします。
良かったら拡張機能も利用していただけると幸いです。
Google Maps Android API の GoogleMap.getProjection はシングルトンじゃないから注意

Android で Google Maps を使用するときに使用する Google Maps Android API の話です。

* [Google Maps Android API / Google Developers](https://developers.google.com/maps/documentation/android-api/?hl=ja)

この SDK の機能の一つに「地図座標（緯度経度）と画面座標の相互変換」というものがあります。
これを使うと、

* 画面中心の緯度経度を取得して、任意の外部APIを呼び出す（カーナビみたく中心位置の住所を検索するとか）
* 地図上のマーカーの位置に任意の View を吹き出しのように配置する

で、これを行うには ``GoogleMap.getProjection()`` で ``Projection`` クラスのインスタンスを使用して、``fromScreenLocation`` または ``toScreenLocation`` を呼び出します。

* [Projection  /  Google APIs for Android](https://developers.google.com/android/reference/com/google/android/gms/maps/Projection?hl=ja)

この ``GoogleMap.getProjection()`` で取得できるインスタンス、シングルトンというか、いつ取得しても同じインスタンスな気がしませんか？ ``GoogleMap.getUiSettings()`` がそうであるように。 ``map.getProjection().fromScreenLocation``と書くのはダルいので地図の生成時に一度だけ取得して使いまわしたいと思いませんか？

```java
private Projection _proj;

@Override
public void onMapReady (GoogleMap map) {
    // 最初に取得して使い回せばいいよねー、そう思っていた時期が私にもありました・・・
    _proj = map.getProjection();
}
```

ところがこれが間違いです。

ためしに「地図の位置が変わったら、画面の左上(0, 0)の緯度経度を得る」というのを書いてみます。

```java
private Projection _proj;

@Override
public void onMapReady (GoogleMap map) {
    // 最初に取得して使い回せばいいよねー、そう思っていた時期が私にもありました・・・
    _proj = map.getProjection();

    // カメラの移動が完了してアイドル状態になったときのイベント（RetroLambda使用） 
    map.setOnCameraIdleListener(() -> {
        // 画面原点の緯度経度を得る
        LatLng latlng = _proj.fromScreenLocation(new Point(0, 0));
        Log.d("TEST", "lat:" + latlng.latitude + ", long:" + latlng.longitude); 
    });
}
```

地図をスクロールさせると ``setOnCameraIdleListener`` のハンドラが呼び出されますが、期待した結果が得られません。たぶんマイナスとかゼロに近い値になっていると思います。

正しい結果を得るには、

```
map.setOnCameraIdleListener(() -> {
    // 画面原点の緯度経度を得る
    Projection prj = map.getProjection();
    LatLng latlng = prj.fromScreenLocation(new Point(0, 0));
    Log.d("TEST", "lat:" + latlng.latitude + ", long:" + latlng.longitude); 
});
```

のように、「その時点での」 ``Projection`` インスタンスを得る必要があります。

さてではここで API Reference の説明を見てみましょう。

* [GoogleMap.getProjection / Google APIs for Android](https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.html?hl=ja#getProjection())

> The Projection returned is a snapshot of the current projection, and will not automatically update when the camera moves. As this operation is expensive, you should get the projection only once per screen. Google Maps uses the Mercator projection to create its maps from geographic data and convert points on the map into geographic coordinates.

*The Projection returned is a snapshot of the current projection, and will not automatically update when the camera moves.*

*現在の投影のスナップショットを返します。カメラの移動で自動的に更新されません！！！*

しっかり書いてあったー！

Projection とは投影法（メルカトル図法）を示すもの、その投影法（＝投影を行う公式）は不変なものだから取得の度にスナップショットが作られるとは思いませんでした。
この挙動に気づけなくて、３時間くらい悩みつづけました。

悩んだら、固定概念を捨ててキホンを見直そうぜ、という教訓になりました。が敢えて言わせてもらえれば、 ``getCurrentProjection()`` のようなメソッド名だったら、「最初に取得して使いまわす」という発想にはならなかったかも知れません。SDK作る身として、命名にも配慮したいと思いました。
LM35を使った温度計測をBeagleBoneでやるときの回路図

# 回路図
パスコンは1uFにすること。0.1uFでは足りません。
![fullsizeoutput_2d2.jpeg](https://qiita-image-store.s3.amazonaws.com/0/124209/f2ee9826-1ff0-9e60-afec-76fe2522d461.jpeg)
favicon 取得 超簡単

#状況
いざデプロイ！
favicon入れ忘れた
追加しなくては
ん？その画像手元ににゃい.........

#したいこと
favicon画像が欲しい

#やり方
[http://www.google.com/s2/favicons?domain=](http://www.google.com/s2/favicons?domain=)ここにドメインを指定する

表示させたいドメインを渡すだけで、faviconをpng画像に変換して取得してくれるサービス

#コメント
Googleさんありがとう。
[参考ページ](http://9ensan.com/blog/webservice/favicon-google-api/)
sympy.plottingでaspect_ratioが変えられない？　件について

#sympy.plottingでaspect_ratioが変えられない？　件について

~~私の勘違いだったらすいません．~~
私の知識不足でした．@SaitoTsutomu 様にコメントをいただき[解決](#解決)しました．

`jupyter notebook`を起動します．まずは下準備．

```py3
from sympy.plotting import plot, plot_implicit, plot_parametric
from sympy import symbols, sin, cos, pi
x, y, t = symbols('x y t')
```

##plot

```py3
plot(x**2, (x, -2, 2))
```

とすれば， $-2\leqq x\leqq 2$ の範囲における $y=x^2$ が描写されます．

![Unknown.png](https://qiita-image-store.s3.amazonaws.com/0/191414/9a720164-8bc6-1965-0187-c19a24c4ec9b.png)

複数の関数のグラフを同時に表示することも可能です．$y=x^2$ と $y=x$ を同じ座標空間に描写します．

```py3
plot(x**2, x, (x, -2, 2))
```

![Unknown2.png](https://qiita-image-store.s3.amazonaws.com/0/191414/a92e86a7-5696-096a-897f-25bc03fe8db5.png)

##plot_implicit

$f(x, y)=0$ の形の図形（いわゆる陰関数）も描写できます．次は $x^2+y^2-1=0$ すなわち原点を中心とする半径 $1$ の円です．

```py3
plot_implicit(x**2+y**2-1)
```

![Unknown3.png](https://qiita-image-store.s3.amazonaws.com/0/191414/e5f0733b-32c4-a665-6b25-2878e4f1f18a.png)

縦横のアスペクト比が気になりますが，一応円です．`plot_implicit` は二つ以上の式を設定して，複数の曲線を描くことができないみたいです．陰関数はそれだけプロットが面倒だということでしょうか．

##plot_parametric

これが本命．$y=f(x)$ だとどうしても表現が制限されます．そこで媒介変数表示で表される図形の描写です．例えば
$$
x = \cos t,\ y = \sin t\quad (0\leqq t\leqq 2\pi)
$$
は同じく原点を中心とする半径 $1$ の円ですが，これをプロットするには次のようにします．

```py3
plot_parametric(cos(t), sin(t), (t, 0, 2*pi))
```

![Unknown-2.png](https://qiita-image-store.s3.amazonaws.com/0/191414/c6224aa9-2901-7058-9187-7fcda455fc49.png)

複数の曲線も同時に描写できます．

```py3
plot_parametric((cos(t), sin(t)), (cos(t)+1, sin(t)+1), (t, 0, 2*pi))
```

![Unknown-3.png](https://qiita-image-store.s3.amazonaws.com/0/191414/6ad2f01f-d517-43f1-ab68-200acf2d3078.png)

個別にパラメータの範囲を設定することも可能．

```py3
plot_parametric((cos(t), sin(t), (t, 0, 2*pi)), (cos(t)+1, sin(t)+1, (t, 0, pi)))
```

![Unknown-5.png](https://qiita-image-store.s3.amazonaws.com/0/191414/1f800e06-91fd-1b8d-41b6-b823ba46e859.png)

ところで，さっきからずっと気になっている方がいらっしゃると思いますが，円をプロットしているはずなのに楕円が映っています．[公式ドキュメント](http://docs.sympy.org/latest/modules/plotting.html)によれば

>aspect_ratio : tuple of two floats or {‘auto’}

とあるんですが，これを設定しても何も変わらず……

```py3
plot_parametric((cos(t), sin(t)), (cos(t)+1, sin(t)+1), (t, 0, 2*pi), axis=False, aspect_ratio=(1, 1))
```

![Unknown-4.png](https://qiita-image-store.s3.amazonaws.com/0/191414/d9ab4e64-cd87-2cdd-8adb-5fd72e907b9a.png)


`axis`オプションは適用されているのは確認できますが，`aspect_ratio`は応答なし．Googleで検索してみたんですが，英語サイトばかりで，一応，少し目を通してみましたが，すっきりした解答は得られず．

そもそもsympyのplotはmatplotlibを仲介しているらしく，matplotlibの設定を無理矢理変更する？　みたいな解答があったんですが，それをやるなら最初からmatplotlibで図示した方がよいのではないかと思う始末でした．

## **kwargsって……

プログラマでもなんでもない素人の私の意見なんですが，`**kwargs`って想定していないキーワードを突っ込んでも特にエラーが出ないんですね．結構危ない仕様なのではないだろうか……`aspect_ratio`のスペルミスなども考えたんですが，うんともすんとも言わないから，`aspect_ratio`というオプションを認識しているかどうかすらよく分かりませんでした．

##解決

aspect_ratioと画面サイズは違うとのこと．

```py3
from sympy.plotting import plot_parametric
from sympy import symbols, sin, cos, pi
t = symbols('t')

import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (8,8)

plot_parametric(cos(t), sin(t), (t, 0, 2*pi))
```

![Unknown6.png](https://qiita-image-store.s3.amazonaws.com/0/191414/9f37e809-38ed-8a2b-08d5-f0457e60c0b4.png)

無事 $1:1$ で表示されました．@SaitoTsutomu 様，ありがとうございました．
join と (>>=) と、時々、fmap

# 諸君　私はモナドが好きだ

諸君　私はモナドが好きだ
諸君　私はモナドが大好きだ

随伴対が好きだ
Kleisli圏が好きだ
EM圏が好きだ

あるF代数からの忘却関手の随伴に Freeモナドが現れたときなど心がおどる

「モナド！！モナド！！モナド！！」

よろしい　　ならばモナドだ

---

というわけで、今後モナドに関わる話をする準備としてまずは必要な関数の整理をしておきます。
「モナドとは何か」という話はしません。ごめんね。

（以下、型に現れる `m` はモナドを表すことにしていちいち `Monad m` は書きません）

# モナドの基本関数

Haskell でモナドを扱うときには基本的に2つの関数

```
(>>=) :: m a -> (a -> m b) -> m b
return :: a -> m a
```

を使います。

しかしモナド則の確認などのときは `(>>=)` よりも `join` という関数を使う方が簡単なことが多いのでその `join` を紹介しましょう。
`join` の `(>>=)` を使っての定義は以下のとおりです。

```
join :: m (m a) -> m a
join m = m >>= id
```

型が示すとおり2重にモナドに包まれた値から1重にモナドに包まれた値を作りだす関数です。

# 有名なモナドの join

いくつか有名なモナドでの `join` を `(>>=)` を使わずに書いてみると

- リストモナド

```
join :: [[a]] -> [a]
join xss = concat xss
```

- Readerモナド

```
join :: (r -> (r -> a)) -> r -> a
join f r = f r r
```

- Writerモナド（`w` にモノイド制約が必要ですがその記述は省略します。`Writer` のような構築子も省略してます）


```
join :: ((a, w), w) -> (a, w)
join ((a, x), y) = (a, x `mappend` y)
```

- Stateモナド（`State` のような構築子は省略してます）

```
join :: (s -> (s, s -> (s, a))) -> s -> (s, a)
join f s = let (s', f') = f s in f' s'
```

などとなります。

# return, (>>=), fmap, join, id の絡み合い

先ほど `join` を `(>>=)` と `id` を使って書きましたが、モナドでの `fmap` も `(>>=)` と `return` を使って書くことができます。

```
fmap :: (a -> b) -> m a -> m b
fmap f m = m >>= (return . f)
```

逆に `join` と `fmap` を使って `(>>=)` を書くこともできます。

```
(>>=) :: m a -> (a -> m b) -> m b
m >>= f = join (fmap f m)
```

# モナド則

モナド三則を `join` と `return` と `fmap` を使って書くと

```
join (return m) == m
join (fmap return m) == m
join (join m) == join (fmap join m)
```

となります。

3番目の法則は、外から内に向かって `join` していっても、内から外に向かって `join` していっても同じ値になるということを言っています。
具体的に

```
xss :: [[[Int]]]
xss = [ [ ], [ [1,2], [], [3] ], [ [4], [5], [6] ] ]
```
で確かめてみましょう。

```
join (join xss)
  = join [ [1,2], [], [3], [4], [5], [6] ]
  = [1,2,3,4,5,6]

join (fmap join xss)
  = join [ join [], join [[1,2],[],[3]], join [[4],[5],[6]]]
  = join [ [], [1,2,3], [4,5,6] ]
  = [1,2,3,4,5,6]
```

よし。

---

May Monad be with you
Arch Linux で、 pacman -S openssl したら何もできなくなったがダウングレードで解決

# トラブル概要

`nping` を入れて、使おうとしたら `libssl.so 1.0.1` が無いと言われたので、反射的に `sudo pacman -S openssl` した。
途中「バージョンアップするけど本当にいいの？」みたいなこと聞かれたが、即 `y`

無事に `nping` はできた。めでたしめでたし。となるはずが・・・

```
$ curl http://example.com
curl: error while loading shared libraries: libssl.so.1.0.0: cannot open shared object file: No such file or directory

$ git
git: error while loading shared libraries: libcrypto.so.1.0.0: cannot open shared object file: No such file or directory

$ sudo pacman -Syyu
sudo: error in /etc/sudo.conf, line 0 while loading plugin "sudoers_policy"
sudo: unable to load /usr/lib/sudo/sudoers.so: libssl.so.1.0.0: cannot open shared object file: No such file or directory
sudo: fatal error, unable to load plugins
```

詰んだ＼(^o^)／

# 解決方法

Arch Linuxでは、アップグレードによって壊れる時の復旧が便利なよう、各パッケージのスナップショットを保存しておく機能がある。

[pacman#パッケージキャッシュの削除 | ArchWiki](https://wiki.archlinuxjp.org/index.php/Pacman#.E3.83.91.E3.83.83.E3.82.B1.E3.83.BC.E3.82.B8.E3.82.AD.E3.83.A3.E3.83.83.E3.82.B7.E3.83.A5.E3.81.AE.E5.89.8A.E9.99.A4)

これは `/var/cache/pacman/pkg/` に保存されているので、下記のコマンドを実行すればよい。

```
su -
cd /tmp
cp /var/cache/pacman/pkg/openssl-1.0.2.k-1-x86_64.pkg.tar.xz openssl.tar.xz
tar xJvf openssl.tar.xz
cp usr/lib/{libssl.so,libcrypto.so}.1.0.0 /usr/lib
```

`sudo` さえ使えなくなるので注意。

`/usr/lib` は環境によって変わる。 `ldd $(which pacman)` で確認。


# 参考

ArchLinux界隈ではよくあることらしい。というかやったことこれと全く同じだ

[「私はArch Linuxインストール一週間で環境を破壊しました。」(直しました)](http://mysticdoll.hatenablog.com/entry/2017/04/27/234436)

https://wiki.archlinuxjp.org/index.php/Pacman#.E3.83.91.E3.83.83.E3.82.B1.E3.83.BC.E3.82.B8.E3.82.AD.E3.83.A3.E3.83.83.E3.82.B7.E3.83.A5.E3.81.AE.E5.89.8A.E9.99.A4
GPUImageでフィルターを重ねがけ


カメラアプリでフィルターを掛けたい場合、GPUImageはお手軽にサクッと実装できて、とても良い感じだと思いました。
下記のように複数フィルターを重ねて数行でそれなりの良い感じのフィルターを作成することができます。

```swift:CameraViewController.swift
import GPUImage
class CameraViewController: UIViewController {

    var videoCamera: GPUImageVideoCamera?
    var filterGroup: GPUImageFilterGroup?
    
    override func viewDidLoad() {
    
        videoCamera = GPUImageVideoCamera(sessionPreset: AVCaptureSessionPresetHigh, cameraPosition: .back)
        videoCamera!.outputImageOrientation = .portrait;
        
        // 明るさ
        let brightnessFilter = GPUImageBrightnessFilter()
        brightnessFilter.brightness = 0.01
        
        // コントラスト
        let contrastFilter = GPUImageContrastFilter()
        contrastFilter.contrast = 1.1
        
        // 彩度
        let satureationFilter = GPUImageSaturationFilter()
        satureationFilter.saturation = 0.8
        
        // フィルターを重ねる
        brightnessFilter.addTarget(contrastFilter)
        contrastFilter.addTarget(satureationFilter)
        
        // フィルターグループ生成
        filterGroup = GPUImageFilterGroup()
        filterGroup?.addFilter(brightnessFilter)
        filterGroup?.addFilter(contrastFilter)
        filterGroup?.addFilter(satureationFilter)
        
        filterGroup?.initialFilters = [brightnessFilter]
        filterGroup?.terminalFilter = satureationFilter
        
        videoCamera!.addTarget(filterGroup)
        filterGroup?.addTarget(self.view as! GPUImageView)
        
        videoCamera?.startCapture()
    }
}
```
indexがArrayの範囲内かチェックする色々な書き方

# はじめに

Swiftで配列の要素を取得する際に、指定したインデックスがArrayの範囲外を指す場合、
以下のように、**実行時エラー**となります。

```swift
let array = [1, 2]
array[0] // 1
array[1] // 2
array[2] // fatal error: Index out of range
```
意図しない実行時エラーを防ぐためには、なるべく配列の要素にアクセスする際にはインデックスのチェックが必要となります。インデックスのチェックする方法をいろんなパターンで書いてみました。

# パターン

```swift
// 1. array.count（要素数）を利用する
guard index >= 0 && index < array.count else { return }

// 2. array.indices（インデックスの配列）とcontains（配列に含まれるか）を利用する
guard array.indices.contains(index) else { return }

// 3. 半区間演算子..<とarray.count（要素数）とcontains（配列に含まれるか）を利用する
guard (0..<array.count).contains(index) else { return }

// 4. array.indices（インデックスの配列）と~=（パターンマッチ）を利用する
guard array.indices ~= index else { return }

// 5. 半区間演算子..<とarray.count（要素数）と~=（パターンマッチ）を利用する
guard 0..<array.count ~= index else { return }
```
ベーシックな書き方としてはパターン1の`index >= 0 && index < array.count`をよく見るように思います。個人的には、パターン2の`array.indices.contains(index)`でチェックするのが可読性が高くて良いかと思います。

また、その他の方法として、新しいsubscript構文をArrayのエクステンションに追加するという方法もよく見かけられます。

 - インデックスが配列の範囲内の場合は配列の要素を返す
 - インデックスが配列の範囲外の場合はnilを返す

```swift
// エクステンション
extension Array {
    subscript (safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

// 利用方法
let array = [1, 2]
array[safe: 0] // Optional(1)
array[safe: 1] // Optional(2)
array[safe: 2] // nil
```
このパターンの場合は、subscriptの実装でインデックスのチェックが担保されるため、安全に要素が取得できます。戻り値はオプショナル値となるため、適宜アンラップが必要となります。
「ドラッカー風ふりかえり」を実践しよう

# はじめに

このスライドは @TAKAKING22 さんの「 [心理的安全性について本気出して考えてみたら普段やってるチーミングの話だった #DevLOVE by TAKAKING22](https://speakerdeck.com/takaking22/xin-li-de-an-quan-xing-nituiteben-qi-chu-sitekao-etemitarapu-duan-yatuterutimingufalsehua-datuta-number-devlove) 」で紹介されている「ドラッカー風ふりかえり」をチームで実践するために独自の解釈でテンプレ化したものです。

----
# ドラッカー風ふりかえりとは？

![スクリーンショット_2017-07-26_12_35_44.png](https://qiita-image-store.s3.amazonaws.com/0/3324/ec4c3d88-2a0d-0a1a-c56a-116c6befb4fd.png)

----

## 参考：ドラッカー風エクササイズ

「内側の期待」と「外側の期待」の2つの期待をすり合わせる

* 「組織の中のチーム」と「チームから見た組織」
* 「チームの中の個人」と「個人から見たチーム」

[チームメンバーの期待をあわせる「ドラッカー風エクササイズ」](https://devtab.jp/entry/internal/20)

----

# 1. チームについて考えてみてください

----

## 4つの質問（５分）

1. 何が得意か？
2. どうやって貢献するか？
3. 大切な価値は何か？
4. どんな成果を期待されているか？

----

## 次に向けてすり合わせましょう

* 何ができるか
* 何を改善するか

----

## 完成イメージ

![team.png](https://qiita-image-store.s3.amazonaws.com/0/3324/db164d85-4d58-669c-cbe2-5f75a0a7e0bc.png)

----

# 2. 自分自身について考えましょう

----

## 4つの質問（5分)

1. 何が得意か？
2. どうやって貢献するか？
3. 大切な価値は何か？
4. どんな成果を期待されているか？

----
## 完成イメージ

![self.png](https://qiita-image-store.s3.amazonaws.com/0/3324/16e5251b-38e1-d3a8-3347-b72b8726cf14.png)

----

# 3. メンバーについて考えてみてください

----

## それぞれのメンバーに向けて（5分）

1. 感謝
2. 期待

----

# 4. 次に向けて

自分自身についての４つの質問と、メンバーからもらった感謝と期待の内容を踏まえて次に向けて貢献したい事を全員で共有しあいましょう。

----

# お疲れ様でした！！

----
# 補足

----
## やってみた感想

* ドラッカー風ふりかえりの手順はチームのふりかえりで毎回活用できるのでは？と考えてテンプレ化してみた
* 1については、考えるのはわりとスムーズだったがチームですりあわせて議論してみると思いのほか時間がかった（ファシリ力が重要）
* 2以降は特にメンバー同士の価値観を改めて共有できたのは新鮮だった
* チーム内でメンバーの意見や価値観が統一できている部分も再確認できた
* 順番的にチーム観点が先か個人観点が先かは悩んだが（既にチームが形成されている）ふりかえりなのでチーム観点からのほうが進めやすいと考えた（ただし逆の順番は未検証）
    * プロジェクトの切れ目でいったんチーム意識から開放され徐々に個人の観点を強める流れになるのでこの順番で良かったように思う
    * ただしチームとしては1の議論で今後のアクションを出しておく必要があるので1はおざなりにできない（なので時間がかかった）
* 心理的安全性についても色々気づきはあったが書き始めるともう１つ投稿できてしまいそうなので割愛（気づきを得るためにもまずは実践してみるのが良いと思います）
スクレイピング時におけるDynamoDBテーブル設計

#前提
毎日スクレイピングしたデータをDynamoDBに格納しているので、日々一定量のデータが増加している。
主にデータは98%がその日に利用され、1か月以降の利用率は1%未満。
つまり、新しいデータほど利用頻度が高く価値があり古いデータにかかるコストを抑えたい。

Time Based Partition Tablesパターンを利用
（AWS Summit 2014で安川さんが話していたテーブルパターン）

#テーブル名

まずスクレイピデータを蓄積するテーブルを作成します。

例
`2017-07-Article`

テーブル名に年月を入れ、スクレイピングしたデータはその月のテーブルに格納します。
テーブルは毎月作成し、古く利用率の低いテーブルはスループットを抑えたり、アーカイブしてS3などに書き出しdrop tableで削除し、費用を抑えることができます。

awsのdynamodbはテーブルをグループでまとめて管理できないので、名前によって整理をつけます。
使用できるプレフィックスは`. `, `_ `, `-`

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Limits.html


#Primary key

- Primary key:
 - Hash key: articleId
 - Range key: timeStamp

| articleId |       timeStamp |    Title    |
|:----------|----------------:|:-----------:|
| xxxzzzz   |      1501165697 |      xxxx   |
| yyydssd   |      1501165693 |      yyyy   |
| zzfafdf   |      1501165297 |      zzzz   |
| sasgddd   |      1501145697 |      aBBf   |
| gewgggg   |      1501165657 |      fdsa   |
| etdgdsd   |      1501165677 |      drag   |

Range keyはNumber型にしておくことで、データ取得時に時刻順にソート可能です。

キー条件式は

a = b - 属性 a が値 b と等しい場合、true
a < b - a が b より小さい場合、true
a <= b - a が b 以下である場合、true
a > b - a が b より大きい場合、true
a >= b - a が b 以上である場合、true
a BETWEEN b AND c - a が b 以上で、c 以下である場合、true。
次の関数もサポートされます。

begins_with (a, substr) - 属性の値 a が特定のサブ文字列から始まる場合、true。

参考
http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Query.html#QueryAndScan.Query
zshをfish shellっぽくする

### fish shellは使いやすいけど，やっぱzsh
[fish shell](https://fishshell.com/)は宣言通りユーザーにfriendlyなシェルですが，シェルの文法，特に変数，が違うことろが多数あって結局`zsh`に戻った．しかし，どうしても`fish shell`のfriendlyな`Autosuggestions`を忘れられず，`zsh`で再現する方法を探したら [zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions)を見つけた．
### Install
Macの場合は以下でインストールできる

```bash
brew install zsh-autosuggestions
```
最後は`.zshrc`にパスを追加する

```bash
source /usr/local/share/zsh-autosuggestions/zsh-autosuggestions.zsh
```
### Usage
`fish shell`と同様に履歴を参照しながら`suggestion`をしてくれる

![Untitled.png](https://qiita-image-store.s3.amazonaws.com/0/83857/670b3baf-321e-e75e-696f-81e377c53f3b.png)

その状態で，右キーを押せばコマンドの補完ができる．もちろんキーを変更することもできる．自分の場合は`Ctrl + F` と設定した．

### 設定の変更
`/usr/local/share/zsh-autosuggestions/zsh-autosuggestions.zsh`　を編集すればいい．例えば．suggestionsの色は `ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE` 

### fish shellでも bashスクリプトは実行できるけどね
[bass](https://github.com/edc/bass)を使えばいいが使いにくい時もある．
変数`$`も実行できる

```bash
> bass export X=3
> echo $X
3
```
WordPressのソースコードを読んでいたら、組み込み関数にジャンプした

##WordPressまたは、PHP内での、組み込み関数の宣言について記述します。
WordPressのソースコードを読んでいたら、組み込み関数にジャンプしました。
例えば、以下のような部分で定義元にジャンプしたら、

```
/** WordPress Administration Bootstrap */
require_once( dirname( __FILE__ ) . '/admin.php' );
```
例えば、dirnameでジャンプするとします。そうすると、以下のような部分にジャンプします。

```
function dirname(string $path, int $levels = 1): string {}
```
これは、何も記述されていないように見えますが、組み込み関数であることを示しています。
最初のstringは、1個目の引数の型として、stringを受け取る。次の: stringは、戻り値として、stringを返すことを示しています。: stringはPHP7で追加された文法です。
dirname( \_\_FILE\_\_ ) では、引数は、一個しか取ってないので、組み込み関数の二つ目の引数\$levelは、デフォルトの１の値を取ります。

謝辞
僕の質問に快く答えていただいた、PHPユーザーズ（日本）の方に深く感謝します。
http://www.msng.info/archives/2016/02/phpusers-ja-on-slack.php