OmniAICreator/Qiita-1.07M huggingface dataset:
Create React Appで作られたプロジェクトをParcelにマイグレーション

create-react-appは大変便利なのですが、.babelrcが使えなかったりejectしても複雑怪奇なbuild.jsと付き合わないといけなかったりと、辛みが多いのでParcelに移行できないかと思い試した。

# 環境
- parcel 1.6.2
- windows10
- vs code 1.20.1

# 作成物
https://github.com/MegaBlackLabel/migration-cra-to-parcel

# 1. create react app実行
```powershell
create-react-app migration-cra-to-parcel
```
# 2. Parcelインストール
```powershell
yarn add -D parcel-bundler babel-preset-react-app
```

# 3. npmスクリプト修正
```package.json
+ "start": "parcel ./public/index.html",
- "start": "react-scripts start",
```

# 4. .gitignore追加
```.gitignore
.cache
dist
```

# 5. 【追記】.babelrc追加
```
{
  "presets": ["react-app"]
}
```

# 6. favicon.icoとmanifest.jsonをルートフォルダに移動

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/11672/492b1819-c0d6-d4e5-6807-7aa63aaf22d5.png)

# 7. index.html修正
```index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <!--
      manifest.json provides metadata used when your web app is added to the
      homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
    -->
    <!-- Fixed!!! -->
    <!-- <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> -->
    <link rel="manifest" href="./manifest.json">
    <link rel="shortcut icon" href="./favicon.ico">
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
    <!-- Fixed!!! -->
    <script src="../src/index.js"></script>
  </body>
</html>
```

# 8. devサーバ起動
```powershell
yarn start
```
![キャプチャ2.PNG](https://qiita-image-store.s3.amazonaws.com/0/11672/ba797654-997f-02c3-3570-30e645f207b3.png)

![Screenshot-2018-2-23 React App.png](https://qiita-image-store.s3.amazonaws.com/0/11672/bf0296e9-c255-999c-4eb9-03f7578a045c.png)

起動しました。
問題点としては、Parcelがまだstatic周りのパスの扱いが調整中なので、その辺が問題ないなら早く移行したほうが幸せになれると思います。
【ColdFusion】文字列を区切り文字で分解してひとつだけ使いたい

知らなかったのでメモ。今まで回りくどいことをしていた…。

例えば`123-456-789`をハイフン区切りで3番目`789`だけ取得したいなんてとき。配列に変換して目的の文字列を取得していましたよ。

```html
<CFSET sTest = "123-456-789">
<CFSET aTest = listToArray(sTest, "-")>
<CFDUMP var="#aTest[3]#">
```

もしくは、以下のように1行にしたり。でもなんかかっこ悪いですね。

```html
<CFSET sTest = "123-456-789">
<CFDUMP var="#listToArray(sTest, "-")[3]#">
```

しかし！`getToken`関数を使えば一発でｎ番目の文字列だけ取得できます。

```html
<CFSET sTest = "123-456-789">
<CFDUMP var="#getToken(sTest, 3, "-")#">
```

しかも配列方式だと存在しない位置の文字列を取得しようとした場合にエラーになるので`ArrayLen`で長さチェックが必須なんですが、`getToken`関数なら[empty string]が返るだけなので便利です。

ただし、分解後の文字列を全て使いたいという場合には普通に`listToArray`で配列にしといたほうが便利ですね。
@font-faceを設定して monacoフォントを入れる。

### ttfファイルは広く配布されているが、cross originで弾かれる可能性があるのでeotにする。
ttfファイルが多いのはms、apple、共同で策定された経緯からだろう。
https://github.com/todylu/monaco.ttf
ttf>eot
https://www.fontsquirrel.com/tools/webfont-generator
```export> eot check.```

```css
@font-face {
    font-family: 'monaco';
    src: url('https://gnjo.github.io/monaco-webfont.eot')
}
@font-face {
    font-family: 'Monaco';
    src: url('https://gnjo.github.io/monaco-webfont.eot')
}
```

上記でも動かない場合。

```css
@font-face {
    font-family: 'monaco';
    src: url('https://gnjo.github.io/monaco-webfont.eot');
  	src: url('https://gnjo.github.io/monaco-webfont.woff') format('woff'),
    url('https://gnjo.github.io/monaco-webfont.woff2') format('woff2')     
}
```
Sourcetree Git ログインポップアップが表示し続ける問題

色々Googleしましたが、最後は自分の方法で対応しました。
疲れました

１）SourceTree は閉めていること
２）C:\Users\<username>\AppData\Local\Atlassian\SourceTree\から　"bookmarks.xml", "opentabs.xml", "userhosts" 　を削除する
３）SourceTree を再起動する

以上のです。
# VBA でセル位置をどう扱うか

# このスライドは...

シート編集の後には必ず VBA の手直しをしていたような効率の悪い VBA コードを撲滅する目的で用意しました、今後の参考になれば幸いです。

----

# セル式 と VBA の間には...

----

# 深くて暗い川があります...

----

# それはセル位置の...

----

# 扱い！

----

# セル式さんは...

----

# セル式中のセル位置を...

----

# アドレス名で指定する！

----

# C1セル =A1 + B1

----

# シート編集で...

----

# 位置がずれても...

----

# 問題ない！

----

# VBA さんは...

----

# アドレス名を...

----

# 文字列で指定する！

----

# Range("C1") = <br>Range("A1") + Range("B2")

----

# または...

----

# 座標位置を指定する！

----

# Cells(1, 3) = <br>Cells(1, 1) + Cells(1, 2)

----

# シート編集で...

----

# 位置がずれても...

----

# Excel さんは...

----

# 変えません！

----

# だから...

----

# 行を増やしました<br>(⋈◍＞◡＜◍)。✧♡

----

# 何故か動きません！<br>(　ﾟдﾟ)ﾎﾟｶｰﾝ

----

# 直してください！<br>(´･ω｀･)ｴｯ?

----

# ならばどうするか？

----

## VBA に扱うセルをどう教える？

1. セルを教えてあげる
1. 範囲名で教えてあげる
1. ボタン位置で教えてあげる

----

## 1. セルを教えてあげる

関数を作りセルを渡す ```=UserFunc(A1, B1)```

```vbnet
' VBA
Function UserFunc(lhs, rhs)
    UserFunc = lhs.Value + rhs.Value
End Function
```

----

## 2. 範囲名で教えてあげる

A1 を **左値** B1 を **右値** C1 を **答え** と名前を付ける

```vbnet
Range("答え") = Range("左値") + Range("右値")
```

----

## 3. ボタン位置で教えてあげる

押したボタン位置から相対位置で判断する

```vbnet
With ActiveSheet
    Set o = .Buttons(Application.Caller)
    r = o.TopLeftCell.row
    c = o.TopLeftCell.Column
End With
Cells(r, c-1) = Cells(r, c-3) + Cells(r, c-2)
```

----

# こんなのが辛い...

----

## 辛い...

式は探すの大変なの

```vbnet
    For i=1 To 100
        Range("A:" & i) = i
    Next i
```

----

## 辛い...

座標も探すの大変なの

```vbnet
    For i=1 To 100
        Cells(i, 1) = i
    Next i
```

----

## Range.Offset を使ってね

検索出来る目視も楽

```vbnet
    Set p = Range("範囲名")
    For i=0 To 99
        p.Offset(i, 0) = i
    Next i
```

----

# おしまい
Amazon linux の docker imageで日本語が文字化けしてしまう場合の対処法

Docker HubからAmazon Linuxを持ってきてイメージを構築したらviでテキストを作成するときやmysqlのコンソールで文字化けしてしまった・・・。ので、その時の行なった対処法をメモします。

Docker image は Amazon Linux AMI release 2017.09 バージョンで確認しています。
## 先に結論
* glibc-common の再インストール
    * これをしないとlocaleで使える言語に`ja_JP.UTF-8`が追加されない。`en_US.UTF-8` で事足りれば下記の環境変数追加だけでOK
* 環境変数に`LANG=ja_JP.UTF-8`を追加すれば解決

```vim:Dockerfileに追加
RUN yum -y reinstall glibc-common
ENV LANG ja_JP.UTF-8
```

[こちらを参考にさせていただきました。](http://gsol.hatenablog.com/entry/2017/02/10/CentOS_Docker%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%83%AD%E3%82%B1%E3%83%BC%E3%83%AB%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95)


## 一応手順
EC2インスタンスで作業
### Dockerインストール手順
```terminal
# Docker インストール
$ sudo yum -y install docker

# Docker 起動
$ sudo /etc/init.d/docker start

# Amazon Linuxのイメージをpull
$ sudo docker pull amazonlinux
```

### Dockerfile作成
```vim:動作確認用
FROM amazonlinux

# locale設定
RUN yum -y reinstall glibc-common
ENV LANG ja_JP.UTF-8

# vim インストール
RUN yum -y install vim

# mysql インストール
RUN yum -y install mysql
```

### イメージ作成
```terminal
$ sudo docker build -t test .
```

### 起動とログイン
```terminal
$ sudo docker run -it test
```
ggplot2で試行錯誤する時は+ NULLで終わろう

# ggplot2はレイヤの順番変更や、削除がやや手間

ggplot2は、便利な作図ツールですが、データや書式をレイヤに分けている関係上、レイヤを足す順番が大事になります。
例えば下記の図は、散布図と回帰曲線を足す順番を前後させたもの。
点を目立たせたいか、回帰曲線を目立たせたいか、考えてレイヤを足さなければなりません。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/149890/56825b49-c8b3-d2ed-765f-c1ed7a1c747c.png)

```r
library(ggplot2)
library(GGally)

gp <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species))

layers <- list(
  geom_point(),
  geom_smooth(alpha = 0.6)
)

ggmatrix(
  list(
    gp + layers,
    gp + rev(layers)    
  ),
  nrow = 1,
  ncol = 2,
  xAxisLabels = c(
    '散布図 + 回帰曲線', 
    '回帰曲線 + 散布図'
  )
)
```

この時、散布図+回帰曲線のプロットをした後に、やっぱり回帰曲線+散布図に直したいと思うと

```r
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  geom_point() +
  geom_smooth(alpha = 0.6)
```

の2行目と3行目を入れ替え、

```r
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  geom_smooth(alpha = 0.6)
  geom_point() +
```

2行目の行末に+を足し、3行目の行末から+を除くという、

```r
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  geom_smooth(alpha = 0.6) +
  geom_point()
```

2、3手間を要します。
これは面倒!

また、ここからやっぱり散布図がいらない! と思うと、
3行目をコメントアウトし、

```r
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  geom_smooth(alpha = 0.6) +
  # geom_point()
```

2行目の+もコメントアウト(or delete)する


```r
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  geom_smooth(alpha = 0.6) # +
  # geom_point()
```

必要があります。

やはり面倒だ。

# + NULLで解決!

この問題は`+ NULL`で解決できます。

```r
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  geom_point() +
  geom_smooth(alpha = 0.6) +
  NULL
```

としておくと、カットアンドペーストでレイヤの順番を変更したり、コメントアウトでレイヤを削除することもできます。

# レイヤのリストを足すとき

同様にリストの最後をNULLにしておくことで解決します。

```r
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  list(
    geom_point(),
    geom_smooth(alpha = 0.6),
    NULL
  )
```

# Enjoy!

ちなみに、同様に順番が命なパイプ演算子については、

```r
%>% return 
```

で終わるとよいことを過去の記事で書きました。

%>%で試行錯誤する時はreturnで終わろう
https://qiita.com/Atsushi776/items/dc3f6f81e9387d375269
Quillでパラメータがある時だけwhereに条件追加したい


filter条件が入力されてればwhereに追加したいけどquillではどうやるのかメモ


フィルター条件にユーザ名が入力されるかもしれない場合を例にしてみる

quoteでそれぞれのクエリ生成部分を囲んで繋げる


```scala
val name: Option[String] = Some("alderweireld") // ユーザ名 ※ある場合
val limit: Int = 20

val q1 = quote(users)

val q2 = name match {
  case Some(n: String) => quote { q1.filter(_.name == lift(n) } // 値があれば条件に追加
  case None => quote(q1) // 値が無ければそのままq1を返す
}

val q = quote { // その他の処理
  q2.sortBy(_.createdAt)(Ord.desc)
    .take(lift(limit))
    .map(_.id)
}

db.run(q)
```

ポイントは`name match {}`ごとquoteで囲まないようにするくらい
以上


### 参照
[explicit bindings using `lift`](https://github.com/getquill/quill/pull/335 "explicit bindings using `lift`")
Javaのサポート期間

Javaのサポート期限。過渡期で非常にややこしいです。Oracle Java SE Advanced が有償で、OpenJDK と Oracle JDK が無償です。 

| バージョン    | LTS | リリース日 | OpenJDK<br>サポート期限<br>RedHatの場合 | Oracle JDK<br>サポート期限 | Oracle Java<br>SE Advanced<br>延長サポート |
|-------------:|-----|------|-----|----|----|
| 6  | ○ | 2006年12月 | 2016年12月 | 2013年4月 | 2018年12月 |
| 7  | ○ | 2011年7月 | 2018年6月 | 2015年4月 | 2022年7月 |
| 8  | ○ | 2014年3月 | 2020年10月 | [商用利用]<br>2019年1月<br>[個人利用]<br>2020年12月 | 2025年3月 |
| 9  | × | 2017年9月 |  | 2018年3月 | なし |
| 10 | × | 2018年3月 |  | 2018年9月 | なし |
| 11 | ○ | 2018年9月 |  | 2023年9月以降 | 2026年9月 |
| 17 | ○ | 2021年9月 |  | 2026年9月以降 | |

LTS(=長期サポート)はバージョン11から開始で、5年サポートで、3年おきにリリース。8以前も長期サポートだったので、同等とし、LTS に ○ を付けました。

このリリースサイクルですと、9もLTSにしないとおかしくないでしょうか？8→11への移行期間が4ヶ月しかないです。まぁ、恐らくバージョン8の商用利用も結局、2020年12月までのサポートに変わるのかもしれません。あと、OpenJDK と Oracle JDK のサポート期限は同一にして欲しいです。全て Java 8 は2020年12月にして欲しいです。

Ubuntu LTS の OpenJDK のサポート期限は発表になっていません。Ubuntu 16.04 の default-jdk は 8 です。Ubuntu 18.04 は default-jdk は openjdk-11-jdk ですが中身は Java 10 で、Java 11 がリリースされ次第 Java 11 に切り替えてこれを長期サポートするという方法になりました。 https://lists.ubuntu.com/archives/ubuntu-release/2018-February/004275.html

短期サポートのJavaは次のがリリースされたら即時サポート終了なので、これは開発者にしか使われなさそうですね。次の長期サポートのJavaに備えるための検証用の扱いになりますね。

Ubuntu LTS のように「5年サポート・2年おきにリリース」にすれば、移行期間3年ありますし、2年おきなら変更点の差も小さいですし、そちらの方が良いのではないでしょうか。

### 出典

-  http://www.oracle.com/technetwork/jp/java/eol-135779-ja.html
-  https://access.redhat.com/articles/1299013
-  https://www.java.com/ja/download/faq/release_dates.xml
休憩時間に音楽を流すポモドーロタイマー

私はポモドーロタイマーをよく使ってます。
休憩時間のタイミングで音楽を流したらリラックスして休憩に入れるのではないかと予想して、軽く script を作ってみました。

## 簡単な方法

```zsh
sleep 1500 && open "https://www.youtube.com/watch?v=SNfXwN5JQvg"
```

ターミナルで↑を実行すれば 25分後に YouTube を再生できます。

## CLI
Break のタイミングで指定した URL を開くポモドーロタイマーの CLI を作りました。

https://github.com/elzup/pomodoron

```
npm install --global pomodoron
```

例: 休憩時間にYouTube でお気に入りの音楽を流す。

```
pomodoron "https://www.youtube.com/watch?v=SNfXwN5JQvg"
```

例: 休憩時間にニュースを確認する。

```
pomodoron "https://github.com"
```

1つ誤算があって、youtube を使うと広告が最初流れてしまうことがあります。
楽天カードマンで休憩を迎えるのは微妙なのでなんとかしたいところです。
terraform-provider-aws を手元で試す


[terraform-provider-awsを改造してbuildして手元で使う](https://hoshinotsuyoshi.com/post/terraform-provider-aws-build/) を参考に書き換えた terraform-provider-aws をローカルで利用しようとした時の補足的なメモ

## [terraform-provider-aws](https://github.com/terraform-providers/terraform-provider-aws) を手元でビルドして設置 

```
go get -d github.com/terraform-providers/terraform-provider-aws
cd $GOPATH/src/github.com/terraform-providers/terraform-provider-aws
make build

mkdir -p ~/.terraform.d/plugins
cp $GOPATH/bin/terraform-provider-aws ~/.terraform.d/plugins
```

## 利用してるプロジェクトで使う

```
cd /path/to/terraform-project
rm .terraform/plugins/darwin_amd64/terraform-provider-aws*
terraform init
```
Raspberry Piでスケジュール実行する方法


Motionを時間指定で実行したい時のためにメモを残します。

# 要件
毎日8:00～19:00の間でMotionを実行したい

*※将来的には平日のみ起動させたいが今は保留*

#用意したもの
Raspberry Pi 3 Model B
cron
Motion（インストール済)

#手順
##1. Motion開始(終了)コマンドが書かれたバッチファイルを作成する

```:Motion開始コマンド用ファイルの作成
sudo touch MotionStart.sh
```


`sudo vim MotionStart.sh`

Motionサービスを開始するプログラムを書きます。

```:MotionStart.sh
sudo Motion
```

<br>

```:Motion終了コマンド用ファイルの作成
sudo touch MotionEnd.sh
```
```sudo vim MotionEnd.sh```

Motionサービスを停止させるプログラムを書きます。

```:MotionEnd.sh
sudo service motion stop
```

##2. cronのログが出力されるようにする
```sudo vim /etc/rsyslog.conf```

該当行のコメントアウトを外します。

```
#cron.* /var/log/cron.log
↓
cron.* /var/log/cron.log
```

保存をしたらログ管理システムを再起動します
```sudo /etc/init.d/rsyslog restart```

##3. cronに登録する
crontab以下のコードを追加します。
```crontab -e```

```
#毎日8時にプログラムを実行
00 8 * * * sh /home/pi/MotionStart.sh
#毎日19時にプログラムを実行
00 19 * * * sh /home/pi/MotionEnd.sh
```

スケジュールされているか下記のコードで確認します。
```crontab -l```
<br>
スケジュールが動いているかはログを見ることで確認できます。
```sudo cat /var/log/cron.log```


##参考サイト
[決まった時間に処理する](http://make.bcde.jp/raspberry-pi/%E6%B1%BA%E3%81%BE%E3%81%A3%E3%81%9F%E6%99%82%E9%96%93%E3%81%AB%E5%87%A6%E7%90%86%E3%81%99%E3%82%8B/)
[crontab で細かいスケジュールの設定](http://tech.junkpot.net/archives/721/crontab-%E3%81%A7%E7%B4%B0%E3%81%8B%E3%81%84%E3%82%B9%E3%82%B1%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%AE%E8%A8%AD%E5%AE%9A.html)
<br><br><br><br>
gem whenever のスケジュール実行設定（毎月1日に実行）


タイトルの通り実行したかったので調べたら、以下に到達。

https://stackoverflow.com/questions/6453618/rails-whenever-gem-each-month-on-the-20th

つまり、以下となる。

```ruby:config/schedule.rb
every 1.month, at: 'start of the month at 0am' do
  rake 'do:something'
end

```
RailsにおけるN:Nの自己結合


# はじめに
自己結合のサンプルとしてディレクトリツリーの表現を考える。

備忘録になってしまっているので、まとめ直したいところ。

# ディレクトリツリーの表現
ディレクトリツリーをモデルで表現する場合以下のような設定を行う。

```ruby
class Directory < ActiveRecord::Base
  has_one :parent,      through: :parent_tree, source: :parent                        
  has_one :parent_tree, class_name: "DirectoryTree", foreign_key: :child_id

  has_many :children,     through: :child_trees,  source: :child
  has_many :child_trees,  class_name: "DirectoryTree", foreign_key: :parent_id
end
  
class DirectoryTree < ActiveRecord::Base
  belongs_to :parent, class_name: "Directory"
  belongs_to :child,  class_name: "Directory"
end
```

```@directory``` にDirectoryモデルのインスタンスが格納されているとして、
親ディレクトリの関連（DirectorTree）は ```@directory.parent_tree``` で取得。
親ディレクトリ自体（Directory）は ```@directory.parent``` で取得。

この説明だけで、定義の意味を理解できる人はどれだけいるだろうか。
個人的に定義が素直に頭に入らない理由が2つある。

## 1つ目: foreign_keyが自身と関連先のモデルのどちらを指しているのか分からないから

答えとしては、

* belongs_toで定義するforeign_keyは自身のカラムを指定。
* has_manyで定義するforeign_keyは関連先のモデルのカラムを指定。

だが、理解するのに大分時間がかかった。

なおhas_manyの場合、foreign_keyの設定がないと、関連付ける外部キーの名前は「自身モデル名_id（例ではdirectory_id）」となるが、
参照先のモデルにはDrectoryモデルのidを示すカラムがparent_idとchild_idとして分けて定義しているので、どちらに紐づくのかを指定する必要がある。
この必要性を理解すればhas_manyのforeign_keyは関連先のモデルのカラムを指定することが自明なのだが、なかなか考えがまとまらなかった。。。

## 2つ目: sourceが自身と関連先のモデルのどちらを指しているのか分からないから

答えとしては、

* 関連先のモデルを指定

だが、sourceという言葉自体に惑わされると理解が難しい。

以下のように定義を簡略化すれば、
配下のディレクトリを取得する場合には「:child_trees」を通して「:directory」を取得するという流れがわかりやすいかも。

```ruby
class Directory < ActiveRecord::Base
  has_many :children,     through: :child_trees,  source: :directory
  has_many :child_trees,  class_name: "DirectoryTree", foreign_key: :parent_id
end
  
class DirectoryTree < ActiveRecord::Base
  belongs_to :directory
end
```

## 参考
* マイグレーション時の外部キー制約指定方法
  * https://suin.io/547
[PHP] E_WARNING: session_start(): Unable to clear session lock record

## session_startでWarningが出る

`[PHP] E_WARNING: session_start(): Unable to clear session lock record`
`[PHP] E_WARNING: session_start(): Failed to read session data: memcached`
というアラートがたまに発生する。（上記２つはセットで吐かれる）
session_start()でセッション復元時に発生している。

### 環境

* Apache 2.4.6
* php 7.1.14
* memcached 1.4.24 (ElastiCache)

### 原因（推測）

[ここ](http://php.net/manual/ja/function.session-write-close.php)にあるように
`セッションデータは、同時書き込みを防ぐためにロックされるため、 ある時点であるセッションの処理ができるスクリプトは、1つだけ`
らしいので、ロック取得できなかった場合に発生しているっぽい。

参考）該当箇所の[Memcachedソース](https://github.com/php-memcached-dev/php-memcached/blob/v3.0.4/php_memcached_session.c#L431)

### 改善策

ロック取得リトライ回数(memcached.sess_lock_retries)はデフォルト5。
リトライ回数を1から10これを1ずつ増やしてWarning発生回数が下がるか確認してみる。

確認コマンドは、 `ab -n 1000 -c 4 -H'Cookie: 〜'https://〜〜` で。
設定は、`ini_set('memcached.sess_lock_retries', 10);`をコードに挿入

| sess_lock_retries | ErrorCount | Req/Sec |
|---:|---:|----:|
| 1 | 22 | 9.33 | 
| 2 | 10 | 7.57 | 
| 3 | 4 | 7.33 | 
| 4 | 2 | 8.00 | 
| 5 | 0 | 7.52 | 
| 6 | 0 | 6.90 | 
| 7 | 2 | 7.42 | 
| 8 | 0 | 7.53 | 
| 9 | 0 | 6.44 | 
| 10 | 0 | 6.10 |

## 結論

sess_lock_retriesをデフォルトの5から10に変えてみると発生が抑えられた。
その代わり、スループットは落ちてる。。けど、機能要件優先で。

[PHP Warning: Unknown: Unable to clear session lock record in](https://qiita.com/Kanaemon/items/b232ae5d3d499a2fa18c)
↑ 他の対処法(リトライ回数増やすのではなく、リトライ間隔で改善する方法)もあります。ご参考までに

ちなみに、memcached.sess_lock_retriesはなぜがphpinfo()には出てこない。
なぜだろ？

# 追記(2018/03/07)

さらに改善するために、リトライ回数と間隔、合わせ技でチューニングした結果、効果あった。
最終的な設定値(php.ini)の内容は以下。

```ini
[memcached]
memcached.sess_lock_wait_min = 100;
memcached.sess_lock_wait_max = 1000;
memcached.sess_lock_retries = 30;
```
ちなみにデフォルト値は以下。

```ini
memcached.sess_lock_wait_min = 1000;
memcached.sess_lock_wait_max = 2000;
memcached.sess_lock_retries = 5;
```
そもそもデフォルトのロック待ちが1秒ってのが長いと思う。
チューニングの結果、システム全体の平均レスポンスタイムも１0%ほど改善した。(当社比)
【JavaFX】Eclipseで、アクセス制限: The type '?' is not API(? ex: JavaFX)と出た時の対処法まとめ

# はじめに
JavaFXを利用しようとした時に、以下のようなエラーが出てしまった。
「アクセス制限: The type '?' is not API」(省略)
鬱陶しいので対策を講じることとした。(記事はJavaFXでのこと中心です)
※検索結果をまとめたまでのものです。

# 対策方法

## ビルド・パスの構成を変える (積極的,たぶんいちばん楽な対処法)
理由はわからないけどなぜか直る。
1. プロジェクトを選択し右クリックをして、「ビルド・パス」→「ビルド・パスの構成」
&nbsp;&nbsp;&nbsp; [この画面への別の行き方(楽)](#この画面への別の行き方楽)
2. 「JRE システム・ライブラリー」を選択した状態で、右側の「編集」
3. 表示された画面のラジオボタンで、「代替JRE」または「ワークスペースのデフォルトJRE」を選択 (プルダウンで適切なもの, ex: jdk1.8.0_121)
&nbsp;&nbsp;&nbsp; ※プルダウンがない時は「[注意](#注意)」を参照
4. 「完了」, 「適応して閉じる」

### 注意
もしもプルダウンに何も表示されていないのならば、自分でJDKを設定しなければならない。(開発をするならJREではなく、JDKの方が望ましいと思う)
1. 画面上部より、「ウィンドウ」→「設定」
2. 表示された画面より、「Java」→「インストール済みのJRE」
3. 画面左の「追加」
4. 「標準 VM」を選択し、「次へ」
5. 「JRE ホーム」: JREのホームディレクトリを入力する。(ex: C:\Program Files\Java\jdk1.8.0_121)
6. 「JRE 名」: 任意の名前を入力する。(ex: jdk1.8.0_121)
7. 「デフォルトのVM 引数」: 空欄でよい。
8. 「完了」, 「適応して閉じる」

#### この画面への別の行き方(楽)
プロジェクトを選択し右クリックをして、一番下の「プロパティ」→「ライブラリー」から 2. に行っても良い。

## アクセス許可を行う (積極的,根本的対処法)
JavaFXなどの基本APIとしてEclipseで扱われないAPIは自分でアクセス許可を行う必要があるようだ。
以下の方法を取ることで、アクセス可能APIとして扱われるようにする。しかし、プロジェクト毎にしか指定できない。
1. プロジェクトを選択し右クリックをして、「ビルド・パス」→「ビルド・パスの構成」
2. 「JRE システム・ライブラリー」の左の△→「アクセス・ルール」
3. 選択した状態で、右側の「編集」
4. 「追加」
5. 「レゾリューション」: 「アクセス可能」を選択し、「ルール・パターン」: 「?/\*\*」(?は目的のAPI, 入力例: 「javafx/\*\*」)
6. 「OK」, 「OK」
7. 「適応して閉じる」

参考元: [Using JavaFX in JRE 8, “Access restriction” error - StackOverflow](https://stackoverflow.com/a/32062263)
参考: [Eclipse javaFXのアクセス制限について - 俺だけの秘密基地 IT系 技術局](http://www.mysecretbase.jp/wp_site/ited/2019/02/15/eclipse-javafx%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E5%88%B6%E9%99%90%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/)
## 警告を消す (消極的,表面的対処法)
ただ警告を非表示にするだけで好きじゃない。しかし、一括で消えるという利点がある。
1. 画面上部より、「ウィンドウ」→「設定」
2. 表示された画面より、「Java」→「コンパイラー」→「エラー/警告」
3. 同様に、「使用すべきでない制限された API」→「禁止された参照 (アクセス・ルール)」の設定を、「無視」に変更。
4. 画面下より、「適応して閉じる」
5. 「フル・ビルドを行うか」を尋ねられるので、「はい」

## Gradleにおいてのエラー対処
以下の方々が書いてくださっています！(追記: 2019年9月21日)
・[【JavaFX】Eclipseのアクセス許可をbuild.gradleに書く方法](https://qiita.com/Teramonte4/items/1bbfc7e7d5e496381c7a)
・[Gradle で JavaFX をコンパイルできるようにする](https://qiita.com/hideoku/items/511a4e91dbc183064fd7)

## 参考元
・[EclipseでJavaFXのコード補完が機能しないときの対処方法](https://blogs.osdn.jp/2016/04/02/JavaFX.html)
・[【トラブル】【Java】エラー「Access restriction:The type XX is not API」が表示される](https://dk521123.hatenablog.com/entry/34073566)
・[EclipseでJavaFXを使おうとするとアクセス制限とでる問題の解決方法](http://informationstudent.blog.fc2.com/blog-entry-20.html)
・[【Java FX】 Java FX ～ 入門編 ～](https://dk521123.hatenablog.com/entry/36207806) - e(fx)clipseを使ったインストールっぽい

~~(上から2番目は、ブログ移転されたようなので改善しました: [旧リンク](https://blogs.yahoo.co.jp/dk521123/34073566.html))~~
１０分以内で環境構築！ラズベリーパイ・机の上が狭いのでmacからリモート操作

#やりたいこと
- MacからRaspberry PiにVNCでリモートデスクトップ接続・操作したい

ラズベリーパイ（Raspberry Pi）にHDMI/ディスプレイ/キーボード/マウスを接続するのは面倒、そして、机の上が狭いので、macから遠隔操作を行いたいと思いました。
インストールソフトは最小限にした方法を紹介いたします。


##結論
- ラズベリーパイ側：tightvncをインストール
- mac側：ソフトのインストールは不要
- mac標準機能を使って、ラズパイへ接続することにより遠隔操作。
- 予定作業時間：１０分

##ラズパイ側
### TightVNCをインストール

```
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install tightvncserver
```

### TightVNC起動

```
tightvncserver
```

### TightVNCパスワード設定（初回のみ）
初回機能時のみパスワードを要求されますので
８文字以内のパスワードを入力してください。

*このパスワードは、macからラズパイ接続する際に入力が必要となりますので
　忘れずに。


##Mac側
Mac側は特にソフトのインストールは不要です。
(標準でVNCサーバー接続機能をサポートしている為)


> Finderメニュー - 移動 - サーバーに接続

サーバアドレスに下記入力
```
vnc://raspberrypi.local:5901
```

パスワードを入力
```
パスワードはラズパイ TightVNC初回起動時に設定したパスワードです。
```

#接続成功
Macのデスクトップに、ラズパイの画面が表示されます。
これで、ラズパイ様にキーボード、マウス、HDMI、ディスプレイを用意する必要がないので
机の上も広々ですね。
なんてったって、普段使い慣れたmacのキーボードがそのまま使えるのがいいですよね。


#まとめ
ラズパイ遠隔操作と言えば、sshでコマンドラインで操作する方法もありますが、
GUIで操作できるのは簡単で良いですよね。
EthFiddleでsolidityコードを共有しよう

#EthFiddleとは？
<a href="https://ethfiddle.com/">
![Снимок экрана 2018-02-23 в 14.02.04.png](https://qiita-image-store.s3.amazonaws.com/0/240034/c4290b89-abe0-791a-f53e-e6d488780710.png)</a>
https://ethfiddle.com/

Solidityを書き始めた方はお気づきかもしれませんが、他の言語周りとは違って便利な開発ツールが多くはないのが現状です。
そこで我々Loom Networkでは、solidity向けのGo PlaygroundまたはJSFiddleともいえるEthFiddleを開発しました。EThFiddleを使えば、<b>ローカルのテストネット上で動作確認したsolidityのスニペットを数秒で共有することができます。</b>

EthFiddleは、面倒な環境設定なしブラウザ内で直接コンパイルが可能です。
さらにその場で素早くスマートコントラクトをテスト＆デバックし、ワンクリックでコードのパーマリンクをシェアできてしまいます。

今回はまず基本的な使い方を説明し、さらに<b>便利な機能</b>もご紹介していきます。

#基本的な使い方
ユーザーフレンドリーなGUIを目指した設計のため、特に迷わず使っていただけるかと思います。

◆まずSolidityコントラクトをコーディングし、画面上部の青い"Compile"ボタンでコンパイルしましょう。コンパイラのバージョンもボタン右側で選択可です。
![compile.png](https://qiita-image-store.s3.amazonaws.com/0/240034/c8b66b7f-50cd-dcef-3136-a6e8762fd98c.png)

◆コンパイル結果（エラー/アウトプット）が画面下部に表示されます。
画面右手イエローの"Deploy"をクリックしましょう。
![Снимок экрана 2018-02-23 в 14.42.04.png](https://qiita-image-store.s3.amazonaws.com/0/240034/0b77b3b4-66f5-d7a6-d401-065c313b4fe1.png)

◆デプロイを行うアドレスを選び"Deploy"をクリックします。
![Снимок экрана 2018-02-23 в 14.47.58.png](https://qiita-image-store.s3.amazonaws.com/0/240034/9b847cc0-bb38-5f96-bf3f-38107fc731a1.png)

◆デプロイが完了し、コントラクトアドレスが生成されました。
右手でイエローの"Call"をクリックし、関数を呼び出してテストしてみましょう。
今回はset関数を呼び出します。
![Снимок экрана 2018-02-23 в 14.48.53.png](https://qiita-image-store.s3.amazonaws.com/0/240034/de89fe31-3d85-041c-de39-34810d3ebe1c.png)

◆関数の引数に適切な値を入力し、"Call"します。
![Снимок экрана 2018-02-23 в 14.49.32.png](https://qiita-image-store.s3.amazonaws.com/0/240034/17ec3cf5-9e08-45c9-644a-6bf649a6cc7c.png)

◆画面右部のフィールドで、無事トランザクションが発行されたことを確認できます。
![Снимок экрана 2018-02-23 в 14.50.06.png](https://qiita-image-store.s3.amazonaws.com/0/240034/df463454-acc1-3533-1a75-2d7b5a152ad2.png)

◆全て動作を確認したら、画面左上"Share"をクリックしてパーマリンクを生成しましょう。リンク生成はコードさえ書いてあればどの段階でも可能です。
![Снимок экрана 2018-02-23 в 14.58.49.png](https://qiita-image-store.s3.amazonaws.com/0/240034/7a804ba1-e9aa-3466-b5eb-12ea1a03dbeb.png)
#EthFiddleのより便利な使い方
##◆チャットで他の開発者達と交流してみよう。
画面右下、ブルーの"OPEN CHAT"ボタンにお気づきですか？
ここをクリックするとたくさんのスマート・コントラクト開発者にコードについてアドバイスを求めたり、または自分の知識を提供したりと、有意義なコミュニケーションが楽しめます！
多くが海外の開発者なので英語で質問を投げかけて見ましょう。きっとすぐにリプライがあるはずです！
##◆Recent Fiddlesで他の人のコードを参考にしよう。
OPEN CHATボタン左手に、あまり目立ちませんが"Recent Fiddles"のリンクがあります。
ここでは他の開発者達がシェアしたコードを見ることができるので、コーディングのサンプルとしてヒントやアイディアが見つかるかもしれません。
![Снимок экрана 2018-02-23 в 15.24.03.png](https://qiita-image-store.s3.amazonaws.com/0/240034/082593e4-035d-cd0d-b1d8-636f275a47e2.png)

####もちろんEthFiddleは無料でお使いいただけます。<br>便利にスマート・コントラクトを開発しましょう！！
---
<a href="https://loomx.io/">![logo.png](https://qiita-image-store.s3.amazonaws.com/0/240034/8a948a91-ffaa-4d81-f15b-1c4e260a782d.png)</a>
よろしければフォローをお願いします！
<a href="https://github.com/loomnetwork">Github</a> | <a href="https://t.me/loomnetworkjp">Telegram</a> | <a href="https://twitter.com/LoomNetworkJP
">Twitter</a> | <a href="https://medium.com/loom-network-japanese">Medium</a>
Visit us at https://loomx.io
Contact us: team@loomx.io
enchant.jsのTips Jsdo.itの環境でサウンドが再生されない

現象：jsdo.itで音の出るゲームが作れない。音声ファイルが再生されない。
原因：jsdo.itで用いられているenchant.jsのバージョンが古い
#jsdo.itでenchant.jsを使う一般的な方法
##プロジェクトへの追加方法
一番簡単な追加方法は、jsdo.itでの編集中に
1)「＋Add Library」ボタンをクリックし
2)表示されるダイアログのMajor Libraryのリストから「enchant.js v0.8.0-js」を選択
3)「Add」ボタンをクリック
これだけで、enchant.jsライブラリをプロジェクトに追加することができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234600/f220c820-7959-c1bc-7afb-412c9abf9078.png)
これでほとんどの機能は問題なく使えるのですが。
##enchant.js v0.8.0-js
これは最新版のライブラリではありません。音声再生が実装されていないので不具合が発生します。
そのため最新版のenchant.js v0.8.3を使う必要があります。
#最新版のenchant.js v0.8.3を使う方法
1.enchant.jsの公式サイトから最新版をダウンロード
2.jsdo.itで新規プロジェクトを作成
3.jsファイルにenchant.jsをコピペ
4.プロジェクト保存
5.ゲーム用のプロジェクトを開く
6.「＋Add Library」ボタンでプロジェクトを追加
（4で保存したプロジェクトを、InputURLで指定します。）
7.古いenchant.js v0.8.0を削除
これで問題なく音声ファイルが再生されます。
Googleカレンダーで他のカレンダー（同僚等）を表示したときのソートの仕方

#はじめに
Googleカレンダーを使って、自分以外のメンバの予定の確認とかをするようになり、
タスのメンバー文を見てると　「いやいや、なんとか順番変更できひんのかい！」となることがあります。

かなりの手動ではありますが、なんとか順序を指定できるやり方を見つけたので、記載します。

#前提条件
* 日単位の表示を利用している

#設定方法
1. Googleにログインして、[Googleカレンダー](https://calendar.google.net/)を開く

2. 他のメンバのカレンダーを追加していく

3. メンバの名前の右側にあるココをクリック
<img width="235" alt="201.png" src="https://qiita-image-store.s3.amazonaws.com/0/105220/343bd004-9efa-f749-4c03-717e4c2244c7.png">

4. 「設定」をクリック
<img width="400" alt="202.png" src="https://qiita-image-store.s3.amazonaws.com/0/105220/80c8961a-8908-bfbe-8d7a-cce962d817fb.png">

5. 「名前」にインデックスをつけて、好きな順番になるようにする
<img width="651" alt="203.png" src="https://qiita-image-store.s3.amazonaws.com/0/105220/81d7da50-b124-5253-ab74-84caad28a160.png">

これだけ。

#さいごに
作業が全て手動になるので、順番を入れ替えたいとかの場合は、再度同じ手順でインデックスをつけ直すとかを考えないといけませんね。
でも、一度設定すればしばらくはそのままなのですごく楽です。
これで他の人の予定も簡単に思い通りに見れますね。
puppeteerを使ったスクレイピング

[puppeteer](https://github.com/GoogleChrome/puppeteer)を使ってスクレイピングを実装したときにはまったポイントをまとめています。

#### ナビゲーション完了の検知方法

あるURLにアクセスしたとき、もしくはボタンをクリックしたときなどにナビゲーションの完了を検知するには、単純にはDomContentLoadedイベントを検知すれば良い。

```javascript
yield page.goto('https://example.com/')
yield page.waitForNavigation({ waitUntil: 'domcontentloaded' })
```

ところが、Webサイトによっては一度クッションとなるURLに遷移（HTTPステータスコード200が返却される）して、JavaScriptの処理で別のURLへ再度遷移する、という振る舞いをするものがある。この場合には、DomContentLoadedイベントを検知するだけでは最初のクッションページでのイベントを検知してしまい、上手くいかない。

この対応としては、以下の3つの方法がある。

##### (1) 一定時間ネットワーク通信のないことで完了を判定する。

```javascript
yield page.goto('https://example.com/')
yield page.waitForNavigation({ waitUntil: 'networkidle0' })
```

一定時間ネットワーク通信がないことを表す2種類のイベントが定義されている。

* `networkidle0`：コネクション数が0個である状態が500ミリ秒続いたとき
* `networkidle2`：コネクション数が2個以下である状態が500ミリ秒続いたとき

##### (2) URLとDOM構築状態を組み合わせて判定する。

より確実にかつ高速化したい場合には、URLが目的のページになっていることと、DOM構築完了状態となっていることを組み合わせて判定することができる。


```javascript
yield page.waitForFunction(() => {
	console.log(window.location.href)
	const locationCondition = window.location.href === 'https://example.com/target/'
	const readyStateCondition = window.document.readyState === 'interactive' || window.document.readyState === 'complete'
	return locationCondition && readyStateCondition
})
```

##### (3) 目的のページにしか存在しないDOM要素の出現を検知する。

もう一つの方法として、目的のページにしか存在しないDOM要素が出現したことを検知して、読み込み完了とすることもできる。

```javascript
yield page.waitForSelector('input[name="xxx"]')
```

#### Cookieのクリア

スクレイピングを行う際には、以前の操作の影響を受けないために、毎回Cookieをクリアした状態で行うのがよい。ところが、現在のpuppeteerのAPIではCookieのクリアが簡単にできないため、毎回ブラウザのインスタンスを新しく生成する必要がある。

* [page.deleteCookie(...cookies)](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagedeletecookiecookies)：Cookieを削除するにはCookie名、URLを指定する必要がある。

この問題はIssueとして登録されているため、将来的にAPIが実装されるかもしれない。

* 参考：https://github.com/GoogleChrome/puppeteer/issues/446

#### 不要なリクエスト送信を防ぐ（高速化）

はまりどころではないが、可能な限りスクレイピングを高速化したい場合に、不要なリクエスト送信を防ぐ方法ががある。例えば、以下のコードではexample.comドメイン以外のリソースと、拡張子がpngのファイルへのリクエストを抑制できる。

```javascript
yield page.setRequestInterception(true)
page.on('request', interceptedRequest => {
	const reqUrl = url.parse(interceptedRequest.url())
	const reqExt = path.extname(reqUrl.pathname)
	const reqHost = reqUrl.hostname
	// Resources from 3rd party domains
	if (reqHost !== 'example.com') {
		interceptedRequest.abort();
	// Images
	} else if (reqExt === '.png') {
		interceptedRequest.abort();
	} else {
		interceptedRequest.continue();
	}
});
```
ビットコインエクスプローラー(ウォレットコマンド:hd-new)

# ビットコインエクスプローラー(ウォレットコマンド:hd-new)

原文(https://github.com/libbitcoin/libbitcoin-explorer/wiki/)


## bx hd new

エントロピーから、HD(非決定性階層:BIP32)秘密鍵を作成する。

```
bx hd-new --help
```
```
Usage: bx hd-new [-h] [--config VALUE] [--version VALUE] [SEED]          

情報:エントロピーから、HD(非決定性:BIP32)秘密鍵を作成する。

オプション (named):

-c [--config]        コンフィギュレーションファイルを指定        
-h [--help]          コマンドの説明を表示
-v [--version]       HD秘密鍵のバージョン、 defaults to 76066276.                                           

引数 (positional):

SEED                 新しいキーを生成するためのBASE16エントロピーを指定。
                     少なくとも、128bitの長さが必要。
                     指定がなければ、STDINより読み込む。

```

#### Example 1 

スター秘密鍵(m)から生成された最初(0)の子秘密鍵を生成
BIP32のTestVector1のデータを使用。

```
bx hd-new 000102030405060708090a0b0c0d0e0f
```

```
xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi
```

#### Example 2

スター秘密鍵(m)から生成された最初(0)の子秘密鍵を生成
BIP32のTestVector2のデータを使用。

```
bx hd-new fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542
```

```
xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U
```

#### Example 3

シードの長さが身近いため、エラー

```
bx hd-new baadf00dbaadf00d
```

```
The seed is less than 128 bits long.
```

#### Example 4

パイプコマンドを使用

```
bx seed | bx hd-new
```

```
xprv9s21ZrQH143K3KDWPNXDFTyieNdyp1ADhcEwqvL7t9CDvvvBaEuwjNVXovz6WXFQPJwWqKe17wNAq3xArJ3qcBZqhVrH2Sq3EQ4en8ig2Fo
```


#### Example 5

testnet(70615956)を利用

```
bx hd-new -v 70615956 baadf00dbaadf00dbaadf00dbaadf00d
```

```
pubD6NzVbkrYhZ4XbUpwb3JpXFpXXa8CrP8cTkqzrnsnPV6Z1v3C15HRcUquADA8CMEawvRMMGoKnwg8fza8pPdFUcJH6uxZJJKkDYJJAGT53e
```
AWS SAMでLambdaとAPI Gateway（編集中）

# 準備
aws cliがインストールされてユーザーとか設定されていること
S3にバケットを用意。
sam-bucket
という名前で。
I AMロール作成。Lambdaで使います。
信頼関係のところでLambdaを設定してあげないとだめ。
あとアクセス権限で一応
S3とLambdaとAPI Gatewayのフルアクセスを付けとく。こんなにいらないかも。
名前は
sam-roleで作ります。
適当なディレクトリを作成
sam_test

<img width="542" alt="スクリーンショット 2018-02-27 12.01.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/216917/2e964c24-bf94-3805-62a3-848b89ee39d6.png">

```bash:console
$ pwd
/Development
$ mkdir sam_test
$ cd sam_test
```

#Lambda関数の作成

```python:sam_func.py
def lambda_handler(event, context):
    return 'AWS SAM test'
```

#テンプレートファイルを作成

```yaml:template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: sample
Resources:
  SamSample:
    Type: AWS::Serverless::Function
    Properties:
      Handler: sam_func.lambda_handler # 実行するハンドラ
      Runtime: python3.6 # lambda のランタイムを書く
      Role: arn:aws:iam::<your acount>:role/sam-role # AM Role の Arn
      Timeout: 60 # Lambda のタイムアウト
      Events:
        GetResource: # API Gateway 側の識別子
          Type: Api
          Properties:
            Path: /api # API Gateway のリソースのパス
            Method: get # API Gateway のメソッド
```

```bash:console
$ ls
```

#デプロイ用のファイル作成

```bash:console
$ aws cloudformation package --template-file template.yaml --output-template-file template-output.yaml --s3-bucket my-bucket
Uploading to <zipped file>  3262 / 3262.0  (100.00%)%)
Successfully packaged artifacts and wrote output template to file template-output.yaml.
Execute the following command to deploy the packaged template
aws cloudformation deploy --template-file /Development/sam_test/template-output.yaml --stack-name <YOUR STACK NAME>
```

デプロイ

```bash:console
$ aws cloudformation deploy --template-file /Development/sam_test/template-output.yaml --stack-name SamTest
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - SamTest
```

# 確認
ウェブコンソールから確認
API Gateway
Lambda

# まとめ
phpでmkdir($path, 01777)というコードは正しいのか？

たまたま見ていた↓のようなコードがあり、これはそもそも失敗するのでは？と手元の環境で実行したところ成功してしまい「はてな、何故成功するのだ？」と疑問に思ったので調べてみた。

```php
mkdir($dir_path, 01777);
```

まずは[公式ドキュメント](http://php.net/manual/ja/function.mkdir.php)を参照する。
`$mode`のデフォルト値はint型の`0777`で8進数を指定している。
ここまでは問題ない。

> モードに関する詳細は chmod() をご覧ください。

とあるので確認する。

> mode 引数は 3 つの 8 進法による数値で構成され、 所有者自身、所有者が属するグループ、その他のユーザーの順で アクセス制限を設定します。一つ一つの数字はそのターゲットに対し 許可を与えます。1 は実行権限、2 はファイルに対する書き込み権限、 4 はファイルに対する読み込み権限を与えます。 必要な権限にあわせ数値を加算してください。

そらそうだと言う感じ。
`$mode`は8進数で表すので先頭の0はファイルを指すことになる。ここまではよい。問題はそのあとの`1`だ。
これは↑の説明をみるに実行権限の設定を行っているだがそれは何に対して行っているのか？

問題はそこだ。

PHPの公式に書かれてないぞー？とか思ったらしたの方にそれらしき記述を発見。

[pmichaud at pobox dot com ¶](http://php.net/manual/ja/function.chmod.php#31383)

どうやら仕様上設定できるのは問題ないらしい、えー。

なるほど、わからん！となったのでググったら出た。

[PHPのディレクトリ権限変更系を3ケタの数字で設定すると陥る罠と理由](https://qiita.com/shinkuFencer/items/f9b8468d4495f1785cac)

つまりSticky BitというLinuxの特殊なアクセス権限を指定しているらしい。

```bash
$ ls -la 
-rw-r--r--  1 luccafort  staff    0  2 23 15:15 test.log
$ chmod 01644 test.log
-rw-r--r-T  1 luccafort  staff    0  2 23 15:15 test.log
```

権限の末尾が`T`になっている、なるほど。
ということで書かれたコードが正しかったというオチになった。

`0xxx`と指定するのが当たり前だと思っていたので疑問にも思わなかったけどたまーにこういうことに遭遇すると自分の知識のなさが恥ずかしい。

恥ずかしいことはドンドン放流して行く所存ということで久しぶりにQiitaにエントリ書いた。
Bootstrap4でボタンを中央寄せする方法

## はまったこと

```haml:haml
.btn.btn-info.mx-auto
　　　保存
```

という感じでボタンを中央寄せしようと思ったができない。

## 原因

bootstrapで.btnをつけると、displayがinline-blockとなっているため.mx-autoが効かなかった。

```css
.btn{
    display: inline-block;
}
```

そのため、.d-blockクラスを追加しておけば無事中央寄せできた。

```haml:haml
.btn.btn-info.mx-auto.d-block
　　　保存
```
CentOS | gcc > default compiler versions

```txt:動作環境
CentOS 6.8 (64bit)
on VMWare workstation
for WRF3.9, WPS3.9
  Open MPI v2.1.1
  gcc version 4.9.2 (とgfortran; devtoolset-3使用)
　NetCDF v4.4.1.1, NetCDF (Fortran API) v4.4.4
WRF3.9
WPS3.9
NCL v6.3.0 (ncl_ncarg-6.3.0.Linux_RHEL6.4_x86_64_gcc447.tar.gz)
```

CentOS6.8からCentOS6.9にするとき、gccのバージョンはどうなるか疑問に思っている。

[CentOS7へ(CentOS6と同じバージョンの)gcc4.4.7をインストール](https://qiita.com/tukiyo3/items/53b946f90d78c3816266)
にディストリ(例: CentOS 6)とgccバージョンの例が紹介されている。

https://access.redhat.com/solutions/19458
にはPrimary compiler packagesというリストはある。

> The following gcc packages are available as the default compiler:
RHEL7 : gcc 4.8.x
RHEL6 : gcc 4.4.x
RHEL5 : gcc 4.1.x

最後の数字(revision? or patch level?)はxとなっており、CentOSの6.8と6.9ではこのあたりの違いなのかもしれない。

Software Collections(SCL)でv4.9.2あたりを使うので、あまり気にしなくてもいいのかもしれない。
Open RTB 3.0ざっくり概要

## 記事の趣旨

ネット広告で使われているRTBというシステムのプロトコルであるOpenRTB。
昨年9月にOpenRTB3.0が発表されたので、OpenRTB2.5での課題を踏まえて概要をながめてみます。

確定版もまだですし、3.0が各所で導入されるのは先のこととは思いますが、いざ導入という時に乗り遅れないよう準備しときましょう。

本当にざっくり書いているのであしからず。

## OpenRTB3.0の指針

プログラマティックバイイングは便利になった一方、複雑化が進んでいるので、RTB3.0により透明化する新しい手続きの設計が進めている。

## 特徴

- 重複したコードを減らし、高速な入札を可能にする
- 関与したimpressionに認証済みの署名を提供することが求められる
- ヘッダー入札やサプライチェーンに複雑化に対応するよう策定された
	- 現在のRTBプロトコルは、オープンエクスチェンジか、OTT動画か、プログラマティックギャランティードのインベントリーかによって仕様が異なる
	- ↑の複数の仕様を指定した場合、重複する変数があり無駄があるので、3.0では繰り返すことがないようにしている
	- トラフィックを処理する計算の負荷が減り、入札の高速化と、処理に必要なサーバーの削減につながる


## 現在（2.5）の課題

### 詐欺の横行

OpenRTBの登場により以前のような詐称はなくなったが、以下のような詐欺が生まれ、広告主が受け取る価値とパブリッシャーが受け取る金額を減らし、業界の信頼を損なっている。

* ドメイン詐欺（より価値の高いサイト運営者にドメインを変更する）
* ロケーションの不正（IPアドレス/ロケーションをより貴重な場所に変更する）
* ユーザーIDの不正行為（デバイスIDまたは購入者IDを、過去に収益を上げたIDに変更する）
* デバイスの不正使用（スマートフォンなど）から収益化しにくいデバイス（デスクトップなど）に変更する場合

### 玉石混交なクリエイティブ

サイト運営者やサイト運営者のプラットフォームでは、従来のディスプレイ広告が送信される不透明な方法のため、サイトで実行されるクリエイティブの種類を制御する能力はほとんどない。

* 望ましくないクリエイティブ
	* 重いペイロード
	* ブランド以外の広告
	* 重いまたはマルウェアのJavaScript
	* 過度のピクセル火災

OpenRTB 3.0では、バイヤーがパートナーやパブリッシャーからの認証された供給を要求し、需要パートナーから安全なパフォーマンス広告を要求するよう促します。


---

参考

- [https://digiday.jp/agencies/what-is-rtb-3-0/](https://digiday.jp/agencies/what-is-rtb-3-0/)
- [OpenRTB 3.0 Framework](https://iabtechlab.com/wp-content/uploads/2017/09/OpenRTB-3.0-Draft-Framework-for-Public-Comment.pdf)



--- 

## 周辺知識おまけ

* アドエクスチェンジ
広告枠をimpressionベースで取引する広告取引市場

* ヘッダー入札
広告サーバー（多くの場合、Googleの「DoubleClick for Publishers」）に掲載する前に、手持ちの広告在庫を複数のアドエクスチェンジに同時に提供するというプログラマティック取引の高等テクニックです。同じ広告在庫を複数の需要元に同時入札させることで、パブリッシャーは収益を増加させ、儲けが多くなるというわけです。

* OTT動画
インターネットによるコンテンツ配信。代表格は、YouTube、Netflix。

* プログラマティックダイレクト
純広を自動買い付けする
Skypeをしようと思ったら内蔵カメラが使えない

# 内蔵カメラが使用できない状況になって沼にはまった。

デバイスマネージャにも表示されない。
Biosでも設定する項目がない。

# `Fn` + `F10`を押すことで解決。

ファンクションキーのカメラマークを探した結果、あった。
（iiyamaのノートブックの場合）

https://support.lenovo.com/jp/ja/solutions/ht118432
ajaxでリトライ処理

ajaxでリトライ処理
done、failでの方法が見つからなかったので自分なりにかいてみました。
jQuery等の読み込み部分は省略します。
下記の実装だと、最初の通信を含め計４回通信を行って、
タイムアウト時間は１秒、２秒、４秒、８秒になっています。

```retry.js

var time = 1000;
var request_cnt = 0;
const request = function(){
	$.ajax({
		url: 'htt://xxx.php',
		type: 'get',
		timeout: time,
		data: {
			//data
		}
	}).done(function (response){
		// 成功時の処理
	}).fail(function (jqXHR, textStatus){
		// リトライ処理
		if(textStatus === 'timeout' && request_cnt < 3){
			time = time*2;
			request_cnt++;
			return request();
		}
	});
}
request();
```

ajaxを触ったのはこれが初めてなので、もっといい方法がありましたら、ご教授いただけると幸いです。
【Java】s3の署名付きURLにアクセスする（署名バージョン2）

awsの公式ページの通りにやっていきます。
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/RESTAuthentication.html

認証ヘッダーに
`Authorization: AWS AWSAccessKeyId:Signature`
をつけるのですが、このSignatureを作るのがなかなか面倒です。

たまたま、Javaの案件で使うことがあったので、メモ代わりに投稿しておきます。

今回は、
https://[BUCKET].[ENDPOINT]/[FILE_NAME]
に証明書付きでアクセスしています。

```java
  protected void getFile() throws NoSuchAlgorithmException, InvalidKeyException, ClientProtocolException, IOException {

    String resource= "/" + BUCKET + "/" +FILE_NAME;
    String contentType = "application/octet-stream";
    String md5 = "";
    String daHeader = "x-amz-meta-user:" + USER_ID;
    
　　// 
    Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
    SimpleDateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
    df.setTimeZone(c.getTimeZone());
    
    // StringToSignの作成
    String now = df.format(c.getTime());
    String stringToSign="GET" + "\n" + md5 + "\n" + contentType + "\n" + now + "\n" + daHeader + "\n" + resource;

    // signatureの作成
    SecretKeySpec sk = new SecretKeySpec(S3_SECRET.getBytes(), "HmacSHA1");
    Mac mac = Mac.getInstance("HmacSHA1");
    mac.init(sk);
    byte[] dataBytes = stringToSign.getBytes("UTF-8");
    byte[] signatureBytes = mac.doFinal(dataBytes);
    String signature = new String(Base64.encodeBase64(signatureBytes), "UTF-8");
        

    // Getリクエスト
    HttpClient client = HttpClientBuilder.create().build(); 
    HttpGet request = new HttpGet("https://" + BUCKET + '.' + END_POINT + "/" + FILE_NAME);
    request.setHeader("Host", BUCKET + '.' + END_POINT);
    request.setHeader("Date", now.toString());
    request.setHeader("Content-Type", contentType);
    request.setHeader("Authorization", "AWS" + " " + S3_KEY + ':' + signature);
    request.setHeader("x-amz-meta-user", USER_ID);        
    
    HttpResponse response = client.execute(request);      
  }
```
phantomJSテスト（seleniumから）


phantomJSテスト（seleniumから）


```
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

driver = webdriver.PhantomJS()

driver.get('https://google.co.jp/')

input_element = driver.find_element_by_name('q')
input_element.send_keys('lemon tea')
input_element.send_keys(Keys.RETURN)


driver.save_screenshot('save.png')

for element in driver.find_elements_by_css_selector('h3 > a'):
	print(element.text)
	print(element.get_attribute('href'))

```

seleniumのインストール
https://qiita.com/kotaaaa/items/82adc6db19910867f351
参考（http://www.virtual-surfer.com/entry/2018/02/09/200000）
利用可能なUSBシリアルデバイスのパスを取得する

macOSにUSBシリアルを繋ぐとポートやチップの種類によってデバイスファイル名がまちまちですが、大抵`cu.usb`ではじまっているので、高々1個しか接続しない場合は、

```sh
ls /dev | grep -e cu.usb | head -n 1 | xargs printf '/dev/%s\n'
```

とか、

```sh
find /dev/cu.usb* | head -n 1
```

みたいにやると、1つめのUSBシリアルポートのデバイスファイルのパスが得られます。

Linuxでも使えるようにしようと思ったら、grepの引数に`-e ttyUSB`を追加して、

```sh
ls /dev | grep -e cu.usb -e ttyUSB | head -n 1 | xargs printf '/dev/%s\n'
```

こんな感じでいけると思います。

シリアルから読込するシェルスクリプトの冒頭で使えるイディオムとしては以下のようになります。
環境変数`SERIAL`になにか指定されていればその値を、指定されていなければシリアルデバイスを探しにいき、それでも見つからなければシェルスクリプトを終了します。

```sh
#!/bin/sh

if [ -z "${SERIAL}" ]; then
  export SERIAL=`ls /dev | grep -e cu.usb -e ttyUSB | head -n 1 | xargs printf '/dev/%s\n'`
fi

if [ -z "${SERIAL}" ]; then
  echo "No serial port found" 1>&2
  exit 1
fi

echo "Read from ${SERIAL}" 1>&2

stty -f ${SERIAL} raw 9600
cat ${SERIAL}
```

FreeBSDでもそのうち試す。
AndroidX をソースからビルドする

Jetpack AndroidX (旧サポートライブラリとアーキテクチャー コンポーネント) をソースコードからビルドする方法です。単に AndroidX を利用する場合は [公式ドキュメント] (https://developer.android.com/jetpack/androidx) を参照してください。

[Jetpack Compose](https://developer.android.com/jetpack/compose) を試すためには、現状 AOSP からソースコードを取得してビルドする必要があります。以下の手順に沿ってプロジェクトを開けばデモ アプリを実行したり、自分でコードを追加して試したりすることができます。

# リポジトリをダウンロードする

AOSP からソースコードをダウンロードするには Repo というツールを使います。Repo は複数の Git リポジトリをまとめ、全体で一つの Repo リポジトリとして扱うためのツールです。Repo コマンドをインストールしましょう。

```shell
$ mkdir ~/bin
$ PATH=~/bin:$PATH
$ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
$ chmod a+x ~/bin/repo
```

AOSP には AndroidX のビルド・開発に必要な Git リポジトリだけをまとめた Repo ブランチ `androidx-master-dev` が存在します。ソースコードは以下のようにして取得できます。

```shell
$ mkdir androidx-master-dev && cd androidx-master-dev
$ repo init -u https://android.googlesource.com/platform/manifest \
            -b androidx-master-dev
$ repo sync -c -j9
```

# プロジェクトを開く

AndroidX の開発は Android Studio で行っています。開発者全員の Studio のバージョンを揃えるためのスクリプトが用意されているので、それを使って Android Studio を起動しましょう。

```shell
$ cd androidx-master-dev/frameworks/support
$ ./studiow
```

[Jetpack Compose](https://developer.android.com/jetpack/compose) のプロジェクトを開くには、他のコンポーネントとは別の特殊な Android Studio が必要です。同じ名前のスクリプトが ui ディレクトリに含まれているので、そちらを実行しましょう。

```shell
$ cd androidx-master-dev/frameworks/support/ui
$ ./studiow
```

# デモ プロジェクトを実行する

AndroidX のプロジェクトにはいくつかのデモ アプリが含まれています。これらは主に内部の開発者のデバッグ・テスト用ですが、API の使い方の参考にはなるでしょう。いずれも Android Studio から実行できます。

- support-v4-demos
- support-v7-demos
- support-transition-demos
- support-emoji-demos
- など

ビルドは Android Studio からもできます。コマンドラインで Gradle を使ってもビルドできます。

```shell
# ビルド
$ ./gradlew assembleDebug

# テスト
$ ./gradlew support-transition:connectedCheck
```

# コントリビュートする

コントリビュートする前に [イシュー トラッカー](https://issuetracker.google.com/issues/new?component=192731&template=842428) に不具合報告や機能要望を登録するのがいいでしょう。

GitHub で言うところのプル リクエストは、AOSP では CL (Change list) と呼ばれます。以下のようにして CL を送ることができます。

```shell
$ cd frameworks/support

# トピック ブランチを作る
$ repo start my-change .

# ファイル編集、デバッグ、テスト

# コミットは git コマンドで
$ git add .
$ git commit

# Gerrit にアップロード
$ repo upload .

# レビューでコメントがついたら、適宜修正してアップロードし直す
$ git add .
$ git commit --amend
$ repo upload .
```

コミット メッセージには自動で `Change-Id: 〜` という行が付きます。この行を変更してはいけません。また、どのテストを実行したかを示す `Test: {テスト クラス名など}` を Change-Id の上の行に追加してください。イシュー トラッカーにバグが登録されている場合 `Bug: {バグ番号}` のようにすることで関連付けることができます。

以上。
ビットコインエクスプローラー(ウォレットコマンド:ec-to-wif)

# ビットコインエクスプローラー(ウォレットコマンド:ec-to-wi)

原文(https://github.com/libbitcoin/libbitcoin-explorer/wiki/)


## bx ec to wif

楕円曲線秘密鍵をWIF(Wallet Import Format)秘密鍵に変換する。
※ウォレットにインポートするときは、この秘密鍵を使う。

```
Usage: bx ec-to-wif [-hu] [--config VALUE] [--version VALUE] [EC_PRIVATE_KEY]                                                         

情報:楕円曲線秘密鍵をWIF(Wallet Import Format)秘密鍵に変換する。
     デフォルトで圧縮公開鍵と関連している。

オプション (named):

-c [--config]        コンフィギュレーションファイルを指定        
-h [--help]          コマンドの説明を表示
-u [--uncompressed]  非圧縮公開鍵と関連させる
-v [--version]       WIFバージョン,デフォルトは128.           

引数 (positional):

EC_PRIVATE_KEY       BASE16楕円曲線秘密鍵を指定。指定がなければ、STDINから読み込む。   
```

#### Example 1

```
bx ec-to-wif 8ed1d17dabce1fccbbe5e9bf008b318334e5bcc78eb9e7c1ea850b7eb0ddb9c8
```

```
5JuBiWpsjfXNxsWuc39KntBAiAiAP2bHtrMGaYGKCppq4MuVcQL
```


#### Example 2

非圧縮

```
bx ec-to-wif -u 0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d
```

```
5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ
```

#### Example 3

ビットコインサンプル

```
bx ec-to-wif -u 0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d
```
```
5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ
```

#### Example 4

パイプコマンドを利用

```
bx seed | bx ec-new | bx ec-to-wif
```

```
L2Kj7UjmWSaJQed5RKLeJk12Ai17CZdmk2svNzi2aUkMTgYC1Tb1
```

#### Example 5

testnet(239)を利用

```
bx ec-to-wif -v 239 1560496d135730f5a1bb39580abba1fe8ea270768a08c49a66732772b0b811e2
```
```
cNJFgo1driFnPcBdBX8BrJrpxchBWXwXCvNH5SoSkdcF6JXXwHMm
```
phpでコマンドラインスクリプトのオプション制御

#$argv
特に説明は無いマニュアルどおり
→[$argv](http://php.net/manual/ja/reserved.variables.argv.php)

##例
```php:cmd.php
#!/usr/local/bin/php -q
<?php
var_dump($argv);

```

##実行
```bash
./cmd.php aaa bbb ccc -ddd -eee
array(6) {
  [0]=>
  string(9) "./cmd.php"
  [1]=>
  string(3) "aaa"
  [2]=>
  string(3) "bbb"
  [3]=>
  string(3) "ccc"
  [4]=>
  string(2) "-d"
  [5]=>
  string(5) "--eee"
}

```



#getopt
bashのgetoptと思うとかなり劣化版（想定外のオプションの制御が効かないなど）だけど人力$argvを解析するより遥かにマシ
ガッチリ組むなら[PEAR::Console_CommandLine](https://pear.php.net/package/Console_CommandLine/)が良い
→解説は「[コマンドラインの引数解析を簡単に！](http://blog.asial.co.jp/424)」が親切


##例
```php:commander.php
#!/usr/local/bin/php -q
<?php
//[-h]など一文字で制御する方法
$shortopts = 'h';//スイッチだけ
$shortopts .= 'a:';//:は値を必須で受け取る
$shortopts .= 'b::';//::は値を任意に受け取る
$shortopts .= 'c:';//:は値を必須で受け取る

//([--help]など長名で制御する方法)
$longopts[] = 'help';//スイッチだけ
$longopts[] = 'aaa:';//:は値を必須で受け取る
$longopts[] = 'bbb::';//::は値を任意に受け取る
$longopts[] = 'ddd::';//::は値を任意に受け取る

$options = getopt($shortopts, $longopts);
if($options === false){
  fputs(STDERR, "There was a problem reading in the options.\n" . print_r($argv, true));
  exit(1);
}
$output='';

if(isset($options['h']) || isset($options['help'])){
  $output =<<<'EOL'
-h [--help]  helpこのコマンド
-a [--aaa]   あああ
-b [--bbb]   ビビビ
-c           シシシ
--ddd        デデデ

EOL;
  echo $output;
  exit(0);
}

var_dump($options);

```

##実行
```bash
$ ./commander.php -h
-h [--help]  helpこのコマンド
-a [--aaa]   あああ
-b [--bbb]   ビビビ
-c           シシシ
--ddd        デデデ

$ ./commander.php --help
-h [--help]  helpこのコマンド
-a [--aaa]   あああ
-b [--bbb]   ビビビ
-c           シシシ
--ddd        デデデ
#一般的なヘルプ

$ ./commander.php -a
array(0) {
}
#↑値が無いがないので空

$ ./commander.php -a ZZZ
array(1) {
  ["a"]=>
  string(3) "ZZZ"
}

$ ./commander.php -aZZZ
array(1) {
  ["a"]=>
  string(3) "ZZZ"
}

$ ./commander.php -a=ZZZ
array(1) {
  ["a"]=>
  string(3) "ZZZ"
}

#↑値の入力はスペース区切り、続けて入力、=区切りで可能

$ ./commander.php -a X -a=Y -aZ
array(1) {
  ["a"]=>
  array(3) {
    [0]=>
    string(1) "X"
    [1]=>
    string(1) "Y"
    [2]=>
    string(1) "Z"
  }
}
#複数の値を受け付けられる

#但し↓のように必須optに引数を与え無いと、後続が引数扱いになる
$ ./commander.php -a -b=XXX
array(1) {
  ["a"]=>
  string(6) "-b=XXX"
}

$ ./commander.php -a= -bXXX --aaa= -bYYY
array(2) {
  ["a"]=>
  string(0) ""
  ["b"]=>
  array(2) {
    [0]=>
    string(3) "XXX"
    [1]=>
    string(3) "YYY"
  }
}
#値指定に `=` を使えば回避できそうだが単optに=をつけると空文字が入る

#↓任意optの場合は正しく解析できる
$ ./commander.php -b -a=XXX
array(2) {
  ["b"]=>
  bool(false)
  ["a"]=>
  string(3) "XXX"
}



$ ./commander.php --aaa=XXX --aaaYYY --aaa ZZZ -c " " --ddd
array(3) {
  ["aaa"]=>
  array(2) {
    [0]=>
    string(3) "XXX"
    [1]=>
    string(3) "ZZZ"
  }
  ["c"]=>
  string(1) " "
  ["ddd"]=>
  bool(false)
}

#長名オプションも扱いはほとんど同じ
#ただ `-aaaYYY` のように長名だと連結指定出来ない（そりゃそうだ）

```

#総括
phpでコマンドオプションの制御をする場合は原則、長名オプションを使った方が誤作動が少ない
on/offのスイッチなら単名オプションでも可
オプションの厳密な制御が必要なら[PEAR::Console_CommandLine](https://pear.php.net/package/Console_CommandLine/)を使うべき