OmniAICreator/Qiita-1.07M huggingface dataset:
[Rust] 文字列をコピーせずに文字列の一部を置換する (in-place replacement)

Rustの文字列型には[replace](https://doc.rust-lang.org/std/string/struct.String.html#method.replace)というメソッドが実装されており、部分文字列の置換を行うことが出来る。
しかし、この関数は元の文字列を変更するのではなく、新たな文字列を生成するようだ。

この文字列の生成が無駄なように感じたので、Rustの練習も兼ねて元の文字列を書き換える関数を実装した。

# 実装

```rust
unsafe fn replace_inplace(s: &mut String, from: u8, to: u8) {
    let sv = s.as_bytes_mut();
    sv.iter_mut().filter(|x| **x == from).for_each(|x| *x = to);
}
```

# 使用方法

```rust
    let mut s = String::from("a\\b\\c");
    unsafe { replace_inplace(&mut s, b'\\', b'/'); }

    println!("{}", s);  // => "a/b/c"
```

## ポイント

~~`str`型は`as_bytes_mut`メソッドを実装しており、このメソッドによってミュータブルなバイト列を取得できる。~~

```rust
let sv = s.as_bytes_mut();
```

~~しかし、これによって得られたバイト列を使えば、元の文字列を書き換えることが出来てしまう。しかももとの変数は借用されていないので、この関数を呼び出した後は、同じアドレスへの書き込み権限を有する変数が同時に2つ存在することになる。~~

~~したがって、いずれかの変数のライフタイムが切れるまではこのコードはunsafeであり、データ競合が起こらないように注意しなければならない。~~

~~例えば元の文字列を変更しようとした時に、メモリの再確保が行われるかもしれない。~~

```rust
// 文字列の長さを増やしているので、領域が足りない場合はメモリの再確保が行われる
s += "/d/e"
```

~~このとき、文字列の内部のデータのアドレスも新しいアドレスに置き換わるので、svが指すアドレスはもはや有効なアドレスではなくなる。またこの逆のパターン（取得したバイト列のメモリの再確保）もあるので注意しよう。~~

## 追記 (2019/7/16)

- 変数の借用についての記述を修正
- この実装だとUTF-8シークエンスを破壊する可能性があるので、関数自体をunsafeに変更

## おわりに

今回は1文字だけの置換だったが、もっと複雑な置換も実装してみたいと思う。
CSS transformは順番にご注意を

## 基本
CSSでは、transform属性に複数の変換関数をつなげることができる。その際、関数は左から右に順番に適用される。transformは2次元、もしくは3次元のアフィン変換である。つまりどういうことかというと、こういうことである。

たとえば以下のようなCSSがあると仮定しよう。

```css:transform.css
.transform {
  transform: rotate(90deg) scale(2);
}
```

この時、座標(x,y)について、以下のような計算を行う。

```math
V = \begin{pmatrix}
2 & 0 & 0 \\
0 & 2 & 0 \\
0 & 0 & 1
\end{pmatrix} \begin{pmatrix}
\cos(90°) & -\sin(90°) & 0 \\
\sin(90°) & \cos(90°) & 0 \\
0 & 0 & 1
\end{pmatrix} \begin{pmatrix}
x \\
y \\
1
\end{pmatrix}
```

これにより求まった(x,y)がその地点が変換されて置かれる座標である。

なお、べた書きで行列を記述することも可能であるが、何が起きるか直感でわからない(=メンテナンスできない)からやめたほうがよい。

## 本題

transformは複数の変換関数をつなげることができるのだが、線形代数をやっている人にはわかると思うが、基本的に**交換法則が成立しない**という点に留意する必要がある。
交換法則が成り立つためには、ややこしい条件[^1]が必要だが、2D transformに関して言えば、rotateとscaleの間、およびtranslate相互間については交換法則が成立する。
つまり、たとえば以下のようなCSSがあったとする。

```css:sample.css
.test {
  transform: translate(20px,30px) rotate(45deg) scale(1.5) rotate(-15deg) scale(3) translate(10px,5px) translate(-20px,0) scale(2);
}
```

このようなCSSがある場合、こんな感じに交換できる。

```css:sample2.css
.test {
  transform: translate(20px,30px) rotate(45deg) rotate(-15deg) scale(1.5) scale(3) translate(10px,5px) translate(-20px,0) scale(2);
}
```

簡単な行列計算で、rotate同士は角度の合算ができ、scaleは倍率が乗算ができる。また、translateは各座標値の合算ができるので、結局こうなる。

```css:sample3.css
.test {
  transform: translate(20px,30px) rotate(30deg) scale(4.5) translate(-10px,5px) scale(2);
}
```

これ以上の簡略化はできないという点に注意せよ(translateとscale、translateとrotateの間には交換法則が成立しないため)。

[^1]: つまり、変換行列が$A$と$B$であるとする。その時にこの2つの行列が可換であるための必要十分条件はこの2つに、$P^{-1}AP$と$P^{-1}BP$がどちらも対角行列になる共通なある正則行列(逆行列が存在する行列)$P$が存在することである。
KryptonでFIDO U2F

個人的にSSHの鍵管理で利用している[krypton](https://krypt.co/)がFIDOのU2F(Universal Second Factor)をサポートしていたので使ってみました。

## 仕組み
[この説明](https://krypt.co/blog/posts/krypton-our-zero-trust-infrastructure.html)がわかりやすい。
データの流れなどが簡単な説明とともに記載されている。
ブラウザ拡張がウェブページのU2Fに対する通信をフックして〜みたいな感じで動く模様。
これにより手持ちのスマホがU2F認証用のデバイスに変身する。

## 準備
1. スマホにKryptonアプリをインストール
2. ブラウザにKrypton拡張機能をインストール
3. ブラウザに拡張機能を選択
4. ペアリング用のQRコードが表示されるのでスマホアプリで読み込みして承認

これで準備完了。簡単。

## U2Fデバイスとしての登録
ここではGithubを例に設定方法を説明。（他も基本は同じ）
1. ログイン → setting → Security → Two-factor authentication → Security keys
2. Register new deviceボタンを押下
3. デバイス名を登録後、Addボタンを押下
4. スマホアプリに通知がくるので認証

これで登録完了。

## U2F認証
利用方法はシンプルでログイン後、セキュリティキーの利用が求められるとスマホアプリに通知が来るので承認すればシステムにログインすることができます。

設定自体はスマホアプリに登録されるので、Chormeの拡張機能でU2Fデバイスとして登録sれば、Safariで同じスマホアプリでペアリングしておけば同じようにスマホをU2Fデバイスとして利用可能になります。

スマホアプリ側でペアリングを信頼済みにするとスマホへの認証確認の通知が省略されて認証されます。
セキュリティと利便性のバランスを考えてユーザーがペアリング毎に設定を変更できるのは嬉しいところ。

## その他
[FAQ](https://krypt.co/faq/)にぱっと思いつきそうな疑問に対する回答がのってます。
krypto.coがスマホの中にある秘密鍵にアクセスできるようになってないか？
　とか
スマホなくしたらどうするの？
　とか
利用時に気になるところやリスクについてのっているので一読しておいたほうがよいです。

## まとめ
- 個人利用でカジュアルにスマホをセキュリティキーとして利用したい場合はとても有効
- 事前にブラウザ拡張をインストールしてペアリングしてという作業が発生するのでU2Fデバイスを利用するよりも手間がかかる
- スマホがあってもブラウザ拡張をインストールしてペアリングしないとU2Fの認証はできない
- 当然のことながらスマホが電池切れしたりネットワークにつながってなかったり壊れてたら使えない
- Kryptonに技術的な課題や事故が発生する可能性は0ではないので利用する場合はリスクがあることを理解しておくこと
cv.glmnetで並列処理するために必要な設定

#はじめに
Lasso回帰をRでやろうと思うと、glmnetを使うのが一般的と思いますが、
これでクロスバリデーションをする時、**事前の設定をしないと並列処理になりません。**
また、エラー等も出ないので気付きにくいかもしれません。
と言うことで、この対応の備忘録です。

#cv.glmnetのマニュアル確認

[glmnet公式ドキュメント](https://cran.r-project.org/web/packages/glmnet/glmnet.pdf)をよく見ると、次のように事前に設定が必要と書いてありました。。

> parallel
> If TRUE, use parallel foreach to fit each fold. Must register parallel before hand, such as doMC or others. See the example below. 

しかし、doMCは[doMC公式ドキュメント](https://cran.r-project.org/web/packages/doMC/index.html)によると、OSタイプがunixのみと記載されています。
また、並列処理パッケージは、OSの種類問わず使える[doParallel](https://cran.r-project.org/web/packages/doParallel/doParallel.pdf)が普通はよく使われるのではと思います。
ということで、doParallelをmacOSで試しました。結論から言うと問題なく並列処理が実行できました。
他のOSでは試してませんが、多分問題ないのではと思います。

#事前の設定とcv.glmnetの実施
並列処理時に、何コア使うかを事前に登録します。
下記の場合だと、Rが認識できるコア全てを使って並列処理を実行します。

```R
> library(doParallel)
> library(parallel)
> registerDoParallel(detectCores())
```

その後parallel = Tを設定してcv.glmnetを実行するだけです。


```R
> library(glmnnt)
> cvfit <- cv.glmnet(as.matrix(data1$X), as.matrix(data1$y), parallel = T)
```

ちなみに、glmnetライブラリのQuickStartExampleで並列処理しようとしてもデータが小さすぎて、並列処理になっているか確かめにくいので、大きなデータを適当に取得して確認するのが良いです。

# 検証環境
- macOS Mojave 10.14.5
- R 3.6.0
- RStudio 1.2.1335

#参考文献
- [glmnet公式ドキュメント](https://cran.r-project.org/web/packages/glmnet/glmnet.pdf)
- [doMC公式ドキュメント](https://cran.r-project.org/web/packages/doMC/index.html)
- [doParallel公式ドキュメント](https://cran.r-project.org/web/packages/doParallel/doParallel.pdf)
iptablesでやりたいことをやるためのリンク集

# iptablesって何？
- [iptablesで見かけたNATって何？ - ponsuke_tarou’s blog](https://ponsuke-tarou.hatenablog.com/entry/2019/07/17/003304)
- [iptablesはファイアウォールとパケット転送ができる - ponsuke_tarou’s blog](http://ponsuke-tarou.hatenablog.com/entry/2019/07/17/233526)
- [firewalldをインストールする方法 - Qiita](https://qiita.com/ponsuke0531/items/b90a837fc1e839d905c3)

# 状態を確認したい
```bash
$ sudo service iptables status
$ sudo systemctl status iptables
$ sudo /etc/rc.d/init.d/iptables status
```

# 動かしたい
```bash
$ sudo service iptables start
```
- [iptables](http://itref.fc2web.com/unix/linux/iptables.html)

# 設定を〇〇したい

```bash
# 設定を保存したい
$ sudo iptables-save > {ファイル名}

# 設定を読み込みたい
$ sudo iptables-restore < {ファイル名}
```

- [iptables の設定を保持する（iptables-save と iptables-restore）](http://www.turbolinux.co.jp/products/server/11s/user_guide/iptablesboot.html)
- [CentOSで起動時にサービスが起動するように設定する - Qiita](https://qiita.com/ponsuke0531/items/290433bf40de7e93c4eb)
- [ポートフォワードをしないでiptablesのNATテーブルに設定をしてみた - Qiita](https://qiita.com/ponsuke0531/items/a78545e2c36c006295d6)

# ポートフォワードしたい
- [ポートフォワードをする - Qiita](https://qiita.com/ponsuke0531/items/6b6255c0402e6ea4a950)
- [認証用の鍵でやりたいことをやりたい時にみてみるリンク集 - Qiita](https://qiita.com/ponsuke0531/items/ab437177558056c68147)
- [Puttyで踏み台を使ったポートフォワードを設定する方法 - Qiita](https://qiita.com/ponsuke0531/items/d046fc98af1930560200)
- [ポートフォワードをする - Qiita](https://qiita.com/ponsuke0531/items/6b6255c0402e6ea4a950)
- [~/.ssh/configについて - Qiita](https://qiita.com/passol78/items/2ad123e39efeb1a5286b)

# 困った
- [書き方を間違えて怒られた時の原因集 - Qiita](https://qiita.com/ponsuke0531/items/56a3eb7b5228bd7f53e3)

# 他のことをやりたい
- [Linuxコマンドでやりたいことをやるためのリンク集 - Qiita](https://qiita.com/ponsuke0531/items/73895dcdbb5ddd7d3331)
- [CentOSに挑戦する初心者の助けになればいいと思うサイト集 - Qiita](https://qiita.com/ponsuke0531/items/c6fff1452537ad3709e6)
[JS]様々な値をINT型にキャストするのに、「 | 0 」が便利すぎな件

# はじめに
Javascriptでキャストする場合に、めっちゃ簡単な方法を聞いたので、ここに共有しておきます。**注意点もあるので、使われる方は最後まで読んでください。**
# 何はともあれコード

```javascript:INT型にキャストした例
console.log('aaa'|0) //  => 0
console.log(null|0) //  => 0
console.log(NaN|0) //  => 0
console.log(false|0) //  => 0
console.log(true|0) //  => 1
console.log(0|0) //  => 0
console.log(1234|0) //  => 1234
console.log('1234'|0) //  => 1234（半角数字ならINT型にしてくれる）

// 注意！！
console.log(9.9999|0) // => 9（少数点以下除外）
console.log('１２３４'|0) //  => 0（全角数字は0になる）
```
全て数字にしてくれます。
文字列の数字も、半角であればキャストしてくれます。
なんと、**trueは1にしてくれる**という、親切っぷり。
もちろん、0は0のままで、当然ながら**変数にも使えます。**
# 少数と全角数字の扱いに注意
少数は切り捨てになるようです。
もし、少数が入りそうな変数などに付ける際は、ご注意を。

また、全角数字も0になってしまうので、ご注意を。

以上です。ありがとうございました。
awk を使ってアクセスログから平均・最小・最大・タイル値を取得した話

株式会社オズビジョンのユッコ (@terra_yucco) です。
業務面でちょっとばたついており更新はぱたりと止まりましたが、また折に触れて発信していくつもりでいます。

# ログ集計

本日のお題はログ集計です。
特定のエンドポイントのアクセスのみを grep した後のアクセスログから、所要時間の平均・最小・最大・タイル(近似値) を求めるライナーを書いたので。
ファイルは所要時間の昇順にソートされている前提とします。

## Tile の元になる行数取得

awk に変数を渡せばたぶんワンライナーで行けますが、今日は速度が求められたので、まず行数は先に取りました。

```terminal
$ wc -l target.log
188703
```

## Tile に当たる行数を取得

```terminal
$ echo $(( 188703 / 10 * 9 ))
169830
```

## 実際の値を取得

所要時間はスペース区切りのフィールド 6 番目です。
以下は読みやすいように適宜改行を入れていますが、実際は改行なしで使いました。

```terminal
$ cat target.log | /
  awk -F' ' '
BEGIN {
  i = 0;
  sum = 0;
  min = 0;
  max = 0;
  tile90 = 0;
} 
{
  i++;
  sum += $6;
  if (i == 1) { min = $6 };
  if (i == 169830) { tile90 = $6 };
  if (i == 188703) { max = $6 };
} 
END {
  print i;
  print (sum / i);
  print min;
  print max;
  print tile90;
}'
188703
4403
2401
124023446
450234
```

# Conclusion

もちろん PHP などでもいいのですが、こういった簡易集計には awk はとても便利です。
もし手軽に集計する必要が出た場合にはぜひ使ってみてください！
reduceList（reduce の途中経過をリスト出力）

こんにちは
```reduceList``` を作ってみました（Python）。```reduce``` の処理経過をリスト出力するもので、```itertools.accumulate``` と同じ動作となります。試した関数は二項の和です（```sum_f```）。

```python
>>> import functools, itertools
>>> def reduceList(f, arr, init=None):
>>>     if init is None:
>>>         init = arr.pop(0)
>>>     return functools.reduce(lambda x, y: x + [f(x[-1], y)], arr, [init])
>>>
>>> sum_f = lambda x, y: x + y
>>>
>>> functools.reduce(sum_f, range(1, 5))
10
>>> list(itertools.accumulate(range(1, 5), sum_f))
[1, 3, 6, 10]
>>> reduceList(sum_f, range(1, 5))
[1, 3, 6, 10]
>>> reduceList(sum_f, range(1, 5), 0)
[0, 1, 3, 6, 10]
```
[JS]reduceは、オブジェクトが入っている場合、returnをオブジェクトで返さなければならない件

# いきなり成功したコード

```javascript:成功コード
let array = [
  {id:1, amount:100},
  {id:2, amount:200},
  {id:3, amount:300}
];

let res = array.reduce((v,cur) => {
  return {amount:v.amount + cur.amount}
})

console.log(res)  // => Object {amount: 600}
```
# 出力確認用
<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="js,result" data-user="riotam4" data-slug-hash="VowMqb" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="reduce">
  <span>See the Pen <a href="https://codepen.io/riotam4/pen/VowMqb/">
  reduce</a> by riotam (<a href="https://codepen.io/riotam4">@riotam4</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
# さらっと説明
配列の足し算などをしたい場合、reduceはとても使い勝手が良い。
しかし、

```javascript:配列の中にオブジェクト
let array = [
  {id:1, amount:100},
  {id:2, amount:200},
  {id:3, amount:300}
];
```
このような配列の場合、reduceの書き方にひと工夫がいる。
ずばり、**returnはオブジェクトで返す！**

```javascript:オブジェクトでreturnする
return { key : v.key + cur.key }
```
すこしわかりにくい書き方だが、こうなります。
成功したコードと併せて読んでみると、わかりやすいかと思います。

以上です。
さらっとですが、最後までありがとうございました。
# ちなみに
オブジェクトではなく、合計した値だけを取りたい場合（サンプルコードでいうところの、600だけを取りたい場合）は、

```javascript:値だけ取りたい場合
console.log(res.amount) // => 600
```
こうすると取れます。
shellで今いるディレクトリの名前を取得する

# Shellで今いるディレクトリ名を取得する方法
今いるディレクトリ名でデータをまとめてcsvファイルを作りたいなって思ったときに、そういえばどうやって今いるディレクトリ名を得ればいいかなって考えたものを備忘録代わりに置いときます（大したものじゃないです）

## 追記(2019/09/10)
sugartarouさんからコメント頂いて、こっちのほうが圧倒的に楽だと思うので記載させていただきます。

```shell
basename `pwd`
```

`pwd`で現在のディレクトリ情報を得たあと`basename`でパスの最後をとってくることで目的を達成しています。

## コマンド
```pwd | tr '/' '\n' | tail -n 1```

### やっていること
例：ディレクトリを　```~/hoge/fuga```　とすると、
```pwd```コマンドで今いるディレクトリのフルパスを取得

```:pwd
/home/user/hoge/fuga
```

`tr`コマンドでsplit処理、第一引数を第二引数に置換する処理をしています。スラッシュをデリミタとしてsplit処理しているイメージです。

```:出力結果


home
user
hoge
fuga
```

目的のディレクトリ名は一番下の行に出てくるので最後に```tail```コマンドを利用して、一番下の行だけを取り出します。

```:出力結果
fuga
```

これで目的の行を取り出すことが出来ました。

shellについてはまだまだ浅学なのでもっと効率の良いやり方があるかもしれませんが一つの方法として！
HTML の ボタン を クリック した時に ボタンが押されたように見せる

# 目的
- HTMLファイルのボタンをクリックした時にボタンが押されたように見える設定方法をまとめる。

# 押さえるポイント
- 影が設定されたボタンに対してクリックされたら影を消し、影の分だけ要素を下に下げることにより押されているようなアニメーションを付ける。
- クリックしたときに変化させたいbutton要素かクラス名をCSSファイルで設定する際に「要素名かクラス名:active」と指定する。
- activeになった時に「影を消す」と「要素を影の分だけ下げる」を設定する。
- 影を消す設定はbox-shadowプロパティでnoneを与える。
- 要素を影の分だけ下げる設定はpositionプロパティでrelativeを与え、その後にtopプロパティにピクセル数を与えて設定する。  
※positonプロパティにrelativeを与え、その後でtopプロパティでピクセル数を与えることでpositon: relative;を設定した要素を本来の位置からtopで指定したピクセル数だけ下げることができる。

# 書き方の例
- 下記にCSSファイルの内容を記載する。

``` css
要素の名前かクラス名:active {
  box-shadow: none;
  position: relative;
  top: クリックした時に要素を下げたいピクセル数;
}
```

# より具体的な例
- 下側に10pxのbox-shadowが設定されたbutton要素がクリックされた時にボタンが押下されたように見せる設定をする。(10ピクセルの影が設定された要素に対して設定されている影を消し、要素を影の分だけ下に下げることによりあたかも立体的なボタンが押されたように見せる)
- 下記にHTMLファイルの内容を記載する。

``` html
<button>新規登録</button>
```

- 下記にCSSファイルの内容を記載する。

``` css
button:active {
  box-shadow: none;
  position: relative;
  top: 10px;
}
```
【JavaScript】classListの使い方まとめ(add.remove.contains.toggle)

#classListとは
特定の要素のクラス名を追加したり、削除したり、参照したりすることが出来る便利なプロパティです！
classListの後にメソッドを定義することにより、追加削除などの機能を指定することができます！

###主なclassListのメソッド

| メソッド名       |      機能 |
|:-----------------|------------------:|
| add             |    クラスを追加する |
| remove           |   クラスを削除する |
| contains           | クラスが含まれているか確認する |
| toggle          | クラスが含まれていれば削除、<br>含まれていなければ追加する|

#例で解説！
##まずは下準備
では上記のメソッドを指定した際のclassListの挙動を、簡単な例で解説します！
例えば以下のようなhtmlファイルとCSSファイルがあるとします。

```classList.html
<!DOCTYPE html>
<html lang ="ja">
  <head>
    <meta charset = "utf-8">
    <link rel="stylesheet" type="text/css" href="../style/classlist.css">
    <title>クラスリストテスト</title>
  </head>
  <body>
　　<!-- ここから -->
    <div id = "test">ここの色が変わるよ！</div>
    <div id = "btn">押して！</div>
　　<!-- ここまでに注目 -->
　　<!-- jsでidを取得したいので、id名をここで指定しています。 -->
    <script src = "../js/classlist.js"></script>
  </body>
</html>
```

```classList.css
body {
  margin: 20px 100px;;
}

#test {
  width: 250px;
  height:100px;
  text-align: center;
  line-height: 100px;
  font-size:20px;
  border:2px solid black;
}

#btn{
 width: 250px;
 height:50px;
 border-radius: 25px;
 background-color: black;
 color: white;
 text-align: center;
 line-height: 50px;
 margin-top: 15px;
 cursor: pointer;
}

```
ブラウザに表示すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419062/2faea5e0-c8ac-a2f5-95e2-edea38e81500.png)
このような感じ！
黒いボタンを押すことで、白い四角の背景色を変えたいと思います。
今はjsファイルも、押した後のcssプロパティも何も指定していないので押しても変わりません。

##jsファイルの編集
ボタンを押した時にボックスの色が変わるように設定していきます。
流れとしては、
①ボタンをクリックすると、`classList.add`によって新しくtest2クラスが追加される。
②もう一度クリックすると、`classList.remove`によってtest2クラスが削除される。

以下にjsファイルとcssファイルを載せておきます！

```test.js
'use strict'
{
  const test = document.getElementById('test');
  const btn = document.getElementById('btn');
  btn.addEventListener('click', () => {
    if(test.classList.contains('test2')){
　　//　containsメソッドで、test2クラスが既に付与されているか判定 
      test.classList.remove('test2');
　　//　test2クラスがついている場合、test２クラスを削除する 
    }else{
      test.classList.add('test2');
　　//　test2クラスがついていない場合、test２クラスを追加する 
    }
  });
}
```

CSSファイルに追加するクラス(test2)のプロパティを追加！

```test.css
.test2 {
  background-color: hotpink;
}
```
`addEventListener`で、ボタンがクリックされた時の内容を指定しています。
クリックされた時に`test2`クラスがついていなければ`test2`クラスを追加。
`test2`クラスが既についていたら削除です。
ついているかいないかを、`classList.contains('クラス名')`を使うことで判定しています。

うまくいくと、１回目クリックした時は以下のようにボックスがピンク色になります。
さらにクリックすると白に戻るはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419062/7b8f2c34-85db-ccb9-a368-96aae0a4d68a.png)

## toggleメソッド
今回は条件分岐を使用して色を変更しましたが、
条件分岐を使用せずに上記の動作を実装できるのが`toggle`です！
最初にもちらっと説明しましたが、toggleを使用すると
**test2クラスがついている時は削除して、ついていない時は追加するという判断を自動で行ってくれます！**
つまり上記のjsファイルが以下だけになります。

```test.js
'use strict'
{
  const test = document.getElementById('test');
  const btn = document.getElementById('btn');
  btn.addEventListener('click', () => {
  　test.classList.toggle('test2');
　});
}
```
#さいごに
classListは簡単にクラスの追加や削除ができて便利ですね！
状況に応じてメソッドを使い分けてマスターしましょう:girl_tone1:
HTML の 要素 を クリック したときだけ反映される設定をする

# 目的
- HTMLファイルの要素をクリックした時だけ見た目が変化したりする設定方法をまとめる。

# 押さえるポイント
- クリックしたときに変化させたい要素やクラスをCSSファイルで指定する際に「要素名かクラス名:active」と指定する。
- 必要な情報は①「クリックされた時に変化させたい要素かクラス名」と②「クリックした時どのように変化させたいか(文字の色を変えたい、背景色を変えたいなど)」

# 書き方の例
- 下記にCSSファイルの内容を記載する。

``` css
要素の名前かクラス名:active {
  クリックされた時の要素をどのように変化させたいかの設定
}
```

# より具体的な例
- button要素がクリックされた時に背景色をredに設定する。
- 下記にHTMLファイルの内容を記載する。

``` html
<button>新規登録</button>
```

- 下記にCSSファイルの内容を記載する。

``` css
button:active {
  background-color: red;
}
```
HTML の ボックス要素 に 影 を 設定する

# 目的
- HTMLファイルのボックス要素に影を設定する方法をまとめる。

# 押さえるポイント
- ボックス要素に影を設定するにはbox-shadowプロパティを使用する。
- box-shadowプロパティに水平方向への影のピクセル数、垂直方向への影のピクセル数、影の色を与える。
- 影の色はカラーコードで設定する。

# 書き方の例
- 下記にCSSファイルの内容を記載する。

``` css
ボックス要素の名前かクラス名 {
  box-shadow: 水平方向の影のピクセル数 垂直方向の影のピクセル数 影の色;
}
```

# より具体的な例
- h1要素に垂直方向に10pxの黒い影を設定する。
- HTMLファイルの内容を下記に記載する。

``` html
<h1>おはようございます。</h1>
```

- 下記にCSSファイルの内容を記載する。

``` css
h1 {
  box-shadow: 0 10px black;
}

p {
  font-weight: boid;
}
```
HTML の 要素 を 画面上 に 固定する(スクロールされないようにする)

# 目的
- HTMLファイルの要素(headerメニューなど)を画面上に固定する方法をまとめる。

# 押さえるポイント
- 要素を固定するにはpositionプロパティにてfixedを与える。
- topプロパティで基準からどれくらいの位置で要素を固定したいのを指定する。
- topプロパティでの位置の設定にはピクセル数で設定する。
※基準は設定しないと画面左上がデフォルト設定となる。

# 書き方の例
- 下記にCSSファイルの内容を記載する。

``` css
画面に固定したい要素の名前かクラス名 {
  position: fixed;
  top: 基準から設置場所までの距離(ピクセル数)
}
```

# より具体的な例
- headerをが画面上から10ピクセルのところで固定する。
- 下記にCSSファイルの内容を記載する。

``` css
header {
  position: fixed;
  top: 10px; 
}
```
HTML の 要素 に 乗った時 カーソルの見た目 を 変える

HTML の 要素 に 乗った時 カーソルの見た目 を 変える

# 目的
- HTMLファイルの要素にカーソルが乗った時にカーソルの見た目を変更する方法をまとめる。

# 押さえるポイント
- カーソルの見た目を変更するにはcursorプロパティを使用する。
- 見た目は「text」「pointer」「default」の三種類より指定する。

# 書き方の例
- 下記にCSSファイルの内容を記載する。

``` css
要素の名前かクラス名 {
  cursor: カーソルの見た目の名前;
}
```

# より具体的な例
- h1要素にカーソルが乗った時にカーソルの見た目をtextに設定する。
- p要素にカーソルが乗った時にカーソルの見た目をpointerに設定する。
- 下記にHTMLファイルの内容を記載する。


``` html
<h1>おはようございます。</h1>
<p>これは日本の朝の挨拶です</p>
```

- 下記にCSSファイルの内容を記載する。

``` css
h1 {
  cursor: text;
}

p {
  cursor: pointer;
}
```
Lightning Design System（SLDS）

**随時更新**
---
#■勉強内容
- [Lightning Design System](https://lightningdesignsystem.com/)
- [Trailhead：開発者のための Lightning Design System](https://trailhead.salesforce.com/ja/content/learn/modules/lightning_design_system)
- [visualforce-lightning-design-system-sample](https://github.com/msrivastav13/visualforce-lightning-design-system-sample)
- [Salesforce Lightning Design System(SLDS) examples](http://sfdcsrini.blogspot.com/2016/05/salesforce-lightning-design-systemslds.html)
- [Lightning Design Systemを使ってVisualforceでLightning風のページを作ってみる](https://dev.classmethod.jp/client-side/javascript/salesforce-slds/)
- [Using the Salesforce Lightning Design System](https://bluecanvas.io/blog/2017-05-02-salesforce-lightning-design-system)
- [Saleforce Lightning Design System (SLDS)](https://www.appshark.com/saleforce-lightning-design-system-slds/)
- [SFDC：Lightning Design Systemと入力フォーム](https://tyoshikawa1106.hatenablog.com/entry/2016/03/10/012709)
- [tyoshikawa1106/visualforce-and-lightning-design-system](https://github.com/tyoshikawa1106/visualforce-and-lightning-design-system)

#■メモ作成

- [Visualforce Template (SLDS)](https://qiita.com/xuwenzhen/items/133b0c2d8e50e08e5594)
[Scala]AkkaHttpでPostリクエスト

ScalaはRestAPIサーバーとしての役割にすることが多くて、Postするのは初めてで無駄に時間がかかったのでメモします。

```scala
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpEntity, HttpMethods, HttpRequest, ContentTypes}

def postTest = {
  implicit val system = ActorSystem("on")

  Http().singleRequest(
    HttpRequest(
      method = HttpMethods.POST,
      uri = "http://example.com/hogehoge/fugafuga"
    )
    .withEntity(
      HttpEntity(
        ContentTypes.`application/json`,
        """{"test":"hoge"}"""
      )
    )
  )
}
```

## 解説
```scala
  implicit val system = ActorSystem("on")
```
* Akkaのお約束です

```scala
    HttpRequest(
      method = HttpMethods.POST,
      uri = "http://example.com/hogehoge/fugafuga"
    )
```
* HttpRequest: そのままリクエストを投げる構文です。Akka公式をみましょう
* method: POSTなのでPOSTです。AkkaのHttpMethodsを使います
* uri: POSTしたいURLをStringで定義

```scala
    .withEntity(
      HttpEntity(
        ContentTypes.`application/json`,
        """{"test":"hoge"}"""
      )
    )
```
* .withEntity: Entityを追加するときの構文です。PostはEntityを使うので、使用します。
* HttpEntity: Entity構文
* ContentTypes.\`application/json`: あまり見慣れない書き方ですが、中身を見ればこの書き方であっているのが理解できます。(下記に記述）
* """{"test":"hoge"}""": Postしたい物をStringで記述します。ContentTypeと合わしてください

```scala
object ContentTypes {
  val `application/json` = ContentType(MediaTypes.`application/json`)
  val `application/octet-stream` = ContentType(MediaTypes.`application/octet-stream`)
  val `text/plain(UTF-8)` = MediaTypes.`text/plain` withCharset HttpCharsets.`UTF-8`
  val `text/html(UTF-8)` = MediaTypes.`text/html` withCharset HttpCharsets.`UTF-8`
  val `text/xml(UTF-8)` = MediaTypes.`text/xml` withCharset HttpCharsets.`UTF-8`
  val `text/csv(UTF-8)` = MediaTypes.`text/csv` withCharset HttpCharsets.`UTF-8`

  // used for explicitly suppressing the rendering of Content-Type headers on requests and responses
  val NoContentType = ContentType(MediaTypes.NoMediaType)
}
```

## 詰まったポイント
##### ContentTypesは必ず akka.http.scaladsl の物を使う

* akka.http.javadls とか、 play.api.http のやつを使うと一生エラーになる

##### HttpEntityの第二引数はString

* Jsonだし、JsValueで渡そう〜と思ったらStringしか受け付けないみたい。シリアライズする時とかに型を意識したほうがいいかも
* JsValueとかで渡してしまった場合は、 `toString` で対応しよう（動くかはわかりません。。）

##### HttpRequestのkeyはしっかり書く

* `method = HttpMethods.POST` を、単に `POST` として書いているコードがgithubに多かったが、僕の環境が悪かったのか動かなかったが定義して書いてやると動いた。
* 同じ悩みを抱えている人は一回このように書いてみて試してみてもいいかも

##### .wiithEntity(HttpEntity(~~~)) の順番 

* あんまり使わないので、ごっちゃにならないように注意
syntax errorの正体は不可視文字だった

よくあることなのだろうか？
厄介なトラブルなのでメモっとく。

WordPressでテンプレートを編集していた。
画像が存在する場合はそれを表示して、存在しない場合はダミー画像を表示する。
下記のようなコードを書いた：
<pre>// プログラム画像
$img_url = '';
$upload_dir = wp_upload_dir();
$file_path = $upload_dir['basedir'] ."/images/{$pg_number}.jpg";

if ( file_exists( $file_path ) ) {
      $img_url = home_url( "/images/{$pg_number}.jpg" );
} else {
      $img_url = home_url( "/images/dummy.jpg" );
}</pre>

特段難しいことではないし、コードもシンプル。
だが、なぜか<b>file_existsの行でsyntax error</b>になる。

```file_exists Fatal error: syntax error, unexpected '￼' (T_STRING), expecting ')'```
￼
file_existsに渡っている値がおかしいのか、そもそも使い方が間違っているのか、など小一時間Webを彷徨ってたどり着いたのは、不可視文字によるいたずら（？）だった。

file_existsの行をカーソル移動していくと、$file_pathの後の閉じ括弧の手前で、<b>カーソルが足踏みする…二度点滅する。Codaで不可視文字を表示しても何も表示されない</b>（画像ほぼ中央）。
![スクリーンショット 2019-07-18 19.13.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30249/eaeffa14-18f0-6a4e-bd3e-738e776160a7.png)

この時点で不可視文字のせいだと気づいたので、Shift+矢印キーで選択＆コピーし、Macの文字ビューアにペーストしてみると
![スクリーンショット 2019-07-18 19.04.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30249/af699da2-d90d-d0c5-ae46-d206bdf1aa46.png)


<pre>OBJECT REPLACEMENT CHARACTER
Unicode: U+FFFC, UTF-8: EF BF BC</pre>

https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1240887022
…日本語だと「〓」みたいなものらしい。表示はできないが、そこに文字はある。

どこかからコピペした記憶もないのだが、どこで混じってしまったのだろう。。。
不可視文字による不具合は過去何度か経験しているが、「不可視文字を表示」しても見えないやつに遭遇したのは初めてだ。
厄介なのは、手元のローカル環境ではとくに不具合は出なかったのに、サーバにアップしたらsyntax error発生。
むしろそれがヒントだったのか？

カーソル合わせて、deleteで解決。
テスト自動化はなぜ新種のバグを見つけにくいのか　WebAppの現状

# Outline

テスト自動化研究会にて、テスト自動化の8原則が掲げられています。
その８項目の中で
``「自動テストで新種のバグが見つかることは稀である」``
とあります。

https://sites.google.com/site/testautomationresearch/test_automation_principle

テストエンジニアになり、ISTQBを勉強している人にこれを説明する機会がありました。
その時の持論がとても理解してもらったので、忘れないためにブログに残しました。

# 前提

テスト自動化の前提は以下の通りです

- Webアプリケーション
- Ranorex等のcapture方式で実装、もしくはwebdriverでスクリプトを組む
- ウォーターフォール、もしくはアジャイル
- テスト自動化の実装部隊は、いわゆるQA部署（開発ではない）

# テスト自動化の工程

なぜ、新種のバグを見つけにくいのかを知るには、工程を知るとわかりやすい

自動化の工程は単純に言うと

1. テスト対象を構築する
2. テスト対象からオブジェクトを抽出しながら（XPathやID、イメージ等）スクリプトを実装する
3. テスト自動化が正しいかを検証する
4. テスト自動化が仕様通りにならない場合、テスト対象にバグがあるため、テスト対象を改修し、テスト自動化のテストを再開する
5. テスト自動化スクリプトが完成

Step3の”テスト自動化が正しいこと”を検証するフェーズは重要になります。

大きく２つポイントがあり

- テスト自動化が最後まで動くことを確認
- テスト自動化が仕様通りに動くことを確認

２番目は、当たり前なんですが、別の見方をすると
「テスト対象がバグがあると、それを元に作ったテスト自動化が動いても、テスト自動化が正しいとは言えない」
のです。

そのため、Step4の工程が発生します。
自動化を作る過程でバグが見つかり、テスト対象をエンジニアに直してもらう。

この過程で、Step5　テスト自動化が完成します。
ここから、このテスト自動化がテストとして動かすことができます。

ただ、ここで考えてみてください。
このときに、テスト自動化を実施して、何が起きるでしょうか？

``基本的に、テスト自動化を実施したときバグはあまり出てきません。``

なぜなら、上記工程でテスト自動化を作ってるからです。

ただ、完全にバグゼロかと言うと、そうではありません。

- 繰り返し実施することで見つかるバグ
- バリエーションテスト（データ・ドリブンなど）で見つかるバグ

などは、見つけることはあります。
ただ、新種のバグはやはり見つけることは稀になります。

正しく動くテスト対象に対してテスト自動化を作ることから、そこから逸脱しない、リグレッションテストとしては非常に有効になります。
TypescriptでENUM日本語化

## 背景
フロント→サーバー間でのやり取りで起きた事象。
ドロップダウンの選択肢での問題frontでの表示は日本語だがサーバーにリクエストする際は英語にしなくてはいけない場面があり
文字列一致でベタがきするのは非常にコード量も多くなるし、可読性低いので何かいい方法ないか探してた

### 実装するにあたっての前提
選択肢はフロントとしては`Enum`で管理したい

## Typescript公式
なんかないかなと探していると、公式に静的メソッドをEnum内で定義するExample発見!!
>宣言enumとnamespaceを合体させて、静的メソッドを列挙型に追加することができます

https://typescript-jp.gitbook.io/deep-dive/type-system/enums#wotsuenum-with-static-functions

上記を参考に実装してみる

~~~typescript
enum Sample {
  TOP = 'top',
  BOTTOM = 'bottom'
 }

namespace Sample {
  export default toJapanese(val: string) {
    switch(val) {
      case Sample.TOP:
        return '上';
      default:
        return '下';
    }
  }
}

export default Sample;
~~~
みたいに実装してみた。

処理的には問題なさそうだったんですが、build時に **ts-lint** に怒られる始末。。

内容
`‘namespace’ and ‘module’ are disallowed.`
「名前空間とモジュールは使っちゃダメだよっ」ということらしい。

なぜに？

エラー文で検索すると、[ts-lint](https://palantir.github.io/tslint/rules/no-namespace/)の公式サイトに載ってた。

## 書き直し
結局Enum風のクラスを定義してそこに静的メソッドを追加

~~~typescript
export default class Sample {
  public static TOP: string = 'top';
  public static BOTTOM: string = 'bottom';

  public static toJapanese(val: string): string {
    if (val === Sample.TOP) {
      return '上';
    } else {
      return '下';
    }
  }
}
~~~~
処理的には問題ない

ts-lint通るか。。。

**通った〜!!!**

## 結論
**どうやら名前空間とモジュールというのは、JavaScriptで最近定義されたモジュール化の書き方からかけ離れているのでダメ、ということらしい。
きちんとJavaScript（ECMAScript6）のimport / exportの書き方に則って書きなさいだってさ**
画像再構成を必要とするイメージング装置

#はじめに

世の中には、画像再構成を必要とするイメージング装置と必要としないイメージング装置があります。

簡単に言えば、観測データそのものが観たい画像データであれば画像再構成は不要です。数学的に言えば、システム方程式$E[\boldsymbol{y}]=H(\boldsymbol{x})+\boldsymbol{b}$において、システム関数$H(\*)$が画像$\boldsymbol{x}$の要素(画素)毎の変換である場合、つまり、$j$を画素番号としたときに$E[y_j]=h_j(x_j)+b_j$と表現できる場合、画像再構成は不要です。なぜなら、$x_j=h_j^{-1}(y_j-b_j)$という画素毎に独立な処理(１変数関数の零点を計算する処理)で済んでしまうからです。逆関数 $h_j^{-1}(\*)$を解析的に計算できない場合も数値的に解けばよく、最悪、網羅的な探索でも近似解は得られます。

この意味で、画像再構成が必要なイメージング装置とは、システム方程式が$E[y_j]=h_j(x_j)+b_j$という要素毎に独立した方程式で記述できない装置といえます。


#画像再構成を必要とするイメージング装置

* Ｘ線ＣＴ(x-ray computed tomography)
* トモシンセシス(tomosynthesis)
* ＭＲＩ(magnetic resonance imaging)
* ＰＥＴ(positron emission tomography)
* ＳＰＥＣＴ(single photon emission computed tomography)
* 拡散光ＣＴ(diffusion optical computed tomography)
* などなど

ここでは医療分野で用いられる装置を中心に列挙しましたが、他にも画像再構成を必要とするイメージング装置は様々あります。活躍する分野も医療分野だけでなく、産業分野や自然科学研究など非常に多岐に渡ります。Wikipediaで[トモグラフィー]や[tomography]のページを見てみると、色々な装置が列挙されています。

「◯◯トモグラフィー」や「◯◯ＣＴ」という名称の装置や撮影法は、基本的に画像再構成を必要とします。世間的には「ＣＴ」といったらＸ線ＣＴを指しますが、ＣＴの本来の意味は「計算機断層撮影」であり、計算によって断層画像を撮影する装置や撮影法のカテゴリー名になります。つまり、上で列挙した装置は全て(広義の)ＣＴです。


#画像再構成を必要としないイメージング装置

* レントゲン撮影
* Ｘ線動画像撮影
* ガンマカメラ
* 超音波撮影(sonography)
* デジタル顕微鏡
* デジタルカメラ(スマホにも付いてるやつ)
* などなど

ここで列挙した装置は画像再構成を必要としませんが、画質を向上する(見やすくする)ための画像処理(≠画像再構成)は組み込まれています。


#ブラックホールと画像再構成

2019年4月に「ブラックホールの直接観測に成功！」というビッグニュースが世界を駆け巡りました。

実は、あのブラックホールの画像は望遠鏡で直接的に観測した画像ではなく、電波望遠鏡の観測データを画像再構成した結果です。

技術的には、ＭＡＰ再構成(正則化付き最小二乗推定)であり、再構成問題が劣決定である(観測データの情報量が不足している)ため、天体画像のスパース性(L1ノルム)と局所平滑性(方向差分のL2ノルム)を先見情報に利用しているようです[^1]。再構成問題の様式としては、Ｘ線ＣＴやＰＥＴでは昔から存在していたものであり、何か特別な画像再構成技術を駆使したからブラックホールを画像化できた訳ではない、と私は理解しています。

本質的に特別なことは、超長基線電波干渉計(Very Long Baseline Interferometry)という仕組みで、世界中に散らばる望遠鏡を同期させ、地球サイズの望遠鏡を構成したことだと思います。

画像再構成の対象は「人体」から「ブラックホール」にも及ぶということです。

おわり

[^1]: http://mns.k.u-tokyo.ac.jp/~sparse2017/pdf/6.pdf
GASに日本語をpostする

##目的
Excel VBAからpost経由でGASに日本語を送りつけたい。
転送データは最終的にスプレッドシートに保存する。

##対応
1. Excel VBA(Shift-JIS)
2. COM経由でDLL呼び出し(UTF-16に変換、コードユニットに変換する)
3. POSTする
4. GASで受け取ったコードユニットを文字列変換
5. スプシに書き込み

##詳細
GASのREST APIを使ってpostできるが、英数字のみ送信可能。
BASE64とか使えよって話なんだけどね。

Excel VBAから送る要件があったのと、GAS側であまり処理時間かけたくなかったので簡易的な実装を行った。
VBAから直接日本語を送ると、Shift-JISなのでGAS側で文字として扱えない。
そこでGAS(というよりもJSの内部表現の話)で使っているUTF-16に変換する必要がある。

VBAでは.Netの処理がフルに使えないので、C#でサクっと作成。

###C#側
```変換.cs
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace CCC
{
    [ComVisible(true)]
    public interface ICCC
    {
        [Description("文字列をユニコード表記に変換する")]
        string ConvertUnicodeCode(string target);
    }

    [ClassInterface(ClassInterfaceType.None)]
    public class CCC:ICCC
    {

        public string ConvertUnicodeCode(string target)
        {
            String str = target;
            if (str == null)
            {
                Console.Write("input arg. ex) ccc.exe \"No problem. Everything's fine.\"");
                return "none";
            }

            string retStr = "";

            char[] chars = str.ToCharArray();
            foreach (char c in chars)
            {
                retStr += String.Format("{0:x4}", (int)c);
            }

            return retStr;
        }
    }
}

```
intにキャストするだけでコードユニットとれるって便利。
[参考にした記事](https://stackoverflow.com/questions/13894021/return-code-point-of-characters-in-c-sharp:wq)

注意点は
・インターフェースを実装する事
・[できたライブラリを64bitなのか32bitかで合わせてレジストリに登録する事]
(https://qiita.com/aoi_erimiya/items/aa9160017660b1830891)

###VBA側

```VB:conv.vb
    'パラメータ
    Dim str_Parameter As String
    str_Parameter = POST_CSV_Convert(str_SheetName)
        
    '文字コードをUnicodeコード表記に変換
    Application.StatusBar = "送信情報をエンコードしています..."
    Dim cuc As New CCC.CCC
    
    Dim encodeDat As String
    encodeDat = "data=" & cuc.ConvertUnicodeCode(str_Parameter)
        
    '--------------
    'POST実行
    '--------------
    DoEvents
    Dim xmlhttp As Object
    Set xmlhttp = CreateObject("msxml2.xmlhttp")
    xmlhttp.Open "POST", url, False
    xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    xmlhttp.send (encodeDat)

```

登録したDLLを呼び出して使う。

注意点は
postのパラメータ名(data=とか)の部分は変換しない。
GASで受け取れなくなるので。

[参考文献](http://supermab.com/wp/excel-%E3%81%8B%E3%82%89%E4%BD%BF%E3%81%86%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8dll-%E3%82%92%E4%BD%9C%E3%82%8B%E3%80%82/)

###GAS側

```変換.js
function codeConvert(charCodeStr) {
  uniString = [];

  var idx = 0;
  while(idx < charCodeStr.length){
    var sliceChar = String.fromCharCode("0x" + charCodeStr.slice(idx, idx + 4))
    uniString.push(sliceChar);
    idx = idx + 4;
  }
  return uniString.join('');
}

function doPost(e) {
  var paramData = '' + e.parameters.data;
  var datas = codeConvert(paramData).split(':');

  // スプシに書き込みとか
}
```
受け取ったコードユニットを4文字毎に切り出して、[String.fromCharCode()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/fromCharCode)を使う。

##課題
日本語のやり取りはできるようになったけど、どうしても転送量が増えてしまう。
一回で済んでたところを、分割して送信せなあかん場合もある。
zipかなにかしてやりたい。
あとは、コードユニットに変換しただけでほぼ平文なので、重要な情報を扱う際には何かしら暗号化もしてあげればよいかなーと思う。
Go 1.12でgopdf使ってテンプレートのPDFに色々埋め込み

「Webのフォームの値を受け取ってPDFを生成したい」という案件があり、**Go** v1.12に対応してて動作も軽快で日本語フォントでも文字化けやズレがでないタイ製のライブラリを使ってみました。

https://github.com/signintech/gopdf/releases/tag/v.0.9.2

## 同じマルチバイト文化圏だから安心
GoのPDFライブラリ、 **gopdf**はタイのSignin Technologyが開発しているGo用のPDF生成ライブラリです。
同じマルチバイト言圏だからなのか、中華系の仕事が多いからなのかわかりませんが、日本語フォントのカーニングにも対応しているので、ズレたりせずに綺麗に日本語のPDFが生成できます。

> gopdf is a simple library for generating PDF document written in Go lang.

> Features
- Unicode subfont embedding. (Chinese, Japanese, Korean, etc.)
- Draw line, oval, rect, curve
- Draw image ( jpg, png )
- Password protection
- Font kerning

## 他のPDFをテンプレートとして使える
[gofpdi](https://github.com/phpdave11/gofpdi)が組み込まれているので、Wordやエクセル等で出力したPDFファイルをテンプレートファイルとして使えます。差し込み印刷みたいな感じですね。
今回の要件は、今までMS Officeで生成していたPDFの作成業務を自動化したい、けどPDFの見た目は変えたく無いという要件だったので、バッチリでした。
ただ、一旦Macのプレビューで変更したPDFは読み込みエラーが出てしまったので、ベースにするPDFのバージョンとかにある程度制限はあるかもです。

## 使い方

### import
まず、gopdfをインポートします。 v.0.9.2以降を使っていればv1.0.5以上のgofpdiがimportされてテンプレートが使えるようになります。

```golang
import(
    "github.com/signintech/gopdf"
)
```

### 初期化
```golang
pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4
pdf.AddPage()
```
### テンプレート読み込み
テンプレートのPDFを描画してから文字とかを追加するとテンプレートのPDFの上のレイヤーに追加されます。逆に要素を追加後にテンプレートPDFを描画すると、テンプレートのPDFの下のレイヤーに追加されます。

```golang
// テンプレートファイルをインポート
tpl := pdf.ImportPage("./template.pdf", 1, "/MediaBox") // 1はページ
// Draw pdf onto page
pdf.UseImportedTemplate(tpl, 0, 0, 595.28, 841.89)// テンプレート構造体, x座標, y座標, 横幅, 高さ
```
上記の通り、描画時に描画する座標とサイズを選択できるので、縮小して埋め込むとかも可能です。

### フォント読み込み
日本語を表示させるためには日本語フォントが必要です。サーバー上の適当なディレクトリにフォントファイルを置いて下記の様に読み込みます。
今回は信頼と実績の[IPAフォント](https://ipafont.ipa.go.jp/old/ipafont/download.html)を利用しました。
TrueType以外のOpenTypeとかも使えそうですが今回は試していません。また、GoogleフォントのCJKフォントは漢字の字形が変わって、なんか胡散臭くなるので嫌いです。

```golang
err := pdf.AddTTFFont("ipagp", "./font/ipagp.ttf")
if err != nil {
    panic(err)
}
```
### 文字列追加

```golang
pdf.SetFont("ipagp", "", 12)//フォント、文字サイズ指定
pdf.SetX(10)//x座標指定
pdf.SetY(10)//y座標指定
pdf.Cell(nil, "ありがとう！ signintech & phpdave11")//Rect, String

//行揃え指定する場合
op := gopdf.CellOption{Align: gopdf.Center}//中央寄せ
rect := gopdf.Rect{W: 400, H: 20}
pdf.CellWithOption(&rect, "ありがとう！ signintech & phpdave11", op)

```

### byteデータからの画像追加
サンプルでは画像ファイルを読み込んでPDFに追加していたのですが、今回はQRコードを生成して追加したかったので、byteデータを埋め込みました。
QRコード生成についてはまた別に書きます。

```golang
ih, err := gopdf.ImageHolderByBytes(generateQRcode())//generateQRcode()は[]byteを返します
pdf.ImageByHolder(ih, 517, 325, nil)//イメージホルダーを使って画像を埋め込み
```
### 出力
```golang
pdf.Write(w) //このケースではwはhttp.ResponseWriter
```

上記のコードではブラウザにPDFファイルが表示されます。ちゃんとHTTPヘッダーを出力して上げれば、ダウンロードが始まる感じになります。
フィアルとしてサーバ上に保存したい場合は

```golang
pdf.WritePdf("thankyou.pdf")
```
とします。

今回、初めてGoでPDFいじくってみたのですが、想像以上に簡単にできて楽しかったです。
とはいえ、gopdfで指定していたgofpdiのバージョンが合ってなくてちゃんとPDF読み込めないとか少々地雷踏みましたが、想定内な感じでした。 https://github.com/signintech/gopdf/pull/113

# Google Cloud のAppEngineでも動くよ！
今回、開発にはGoogle CloudのAppEngineを使ったのですが、快適に動作して開発楽でした。
AppEngineで使う場合には、app.yamlに

```yaml
runtime: go112
```
を書いて、 google.golang.org/appengine を使わない様にしまししょう。 appengine.Main()も使っちゃだめです
VisualStudioCodeでC#のunsafeブロックを実行する

Visual Studio Codeでunsafeブロックを実行するときに悩んだので残しておきます。

やり方はcsprojに以下を記載するだけ。

```
<PropertyGroup>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
```

VSCodeの再起動が必要なので忘れずに。

以上。
AWS Elasticsearch でも SQL でリクエストを投げる

👉 最近 AWS の Elasticsearch でも SQL を投げられるようになりました: https://aws.amazon.com/jp/about-aws/whats-new/2019/05/amazon-elasticsearch-service-sql-support/

バージョン 6.5 以降でないと使えませんが、いままで Query DSL の入れ子が難しすぎて悩んでいたので朗報です。

ただし、AWS の SQL 用のエンドポイントは、公式のリファレンスページのエンドポイントと異なるようなので、使い方を交えて紹介したいと思います。

(確認に使った環境は AWS Elasticsearch 6.7 です)

## クエリを投げる: `_sql`

AWS でのエンドポイント: `/_opendistro/_sql`

SQL でドキュメントのクエリを行う API です。
(👉 https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-rest-overview.html)

例として以下のような SQL でクエリを投げたいと思います:

```sql:test.sql
SELECT
  _id,
  description
FROM
  my_index
WHERE
  posted_at BETWEEN '2019-06-01T00:00:00+09:00' AND '2019-07-01T00:00:00+09:00' 
;
```

`GET` or `POST` でエンドポイント `/_opendistro/_sql
` にリクエストを投げます:

`GET /_opendistro/_sql`:

```json:request
{
  "query": "SELECT _id, description FROM my_index WHERE posted_at BETWEEN '2019-06-01T00:00:00+09:00' AND '2019-07-01T00:00:00+09:00'"
}
```

(※ SQL の末尾に `;` があると `Invalid SQL query` エラーになります)

Query DSL のときと同じように該当したドキュメントの結果が返りました:

```json:response
{
  "took" : 26,
  "timed_out" : false,
  "_shards" : {
    "total" : 6,
    "successful" : 6,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 11893,
    "max_score" : 0.0,
    "hits" : [
        // 略...
    ]
  }
}
```

使い勝手的には通常のクエリより楽で、慣れ親しんだ RDB のように SQL でクエリを投げられるのはものすごい便利ですね。

## 変換した結果を得る (`_sql/translate`)

AWS でのエンドポイント: `/_opendistro/_sql/_explain`

SQL から Query DSL に変換した結果を返してくれる API です。
(👉 https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-translate.html)

これは、Query DSL を使いたいがうまく書けない場合や、どんな風に解釈されるか確認したいとき便利です。

取得とおなじように以下のような SQL を変換したいと思います:

```sql:test.sql
SELECT
  _id,
  description
FROM
  my_index
WHERE
  posted_at BETWEEN '2019-06-01T00:00:00+09:00' AND '2019-07-01T00:00:00+09:00' 
;
```

同様に `GET` or `POST` でエンドポイント `/_opendistro/_sql/_explain` にリクエストを投げます:

`GET /_opendistro/_sql/_explain`:

```json:request
{
  "query": "SELECT _id, description FROM my_index WHERE posted_at BETWEEN '2019-06-01T00:00:00+09:00' AND '2019-07-01T00:00:00+09:00'"
}
```

変換された結果が返ります:

```json:response
{
  "from": 0,
  "size": 200,
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "must": [
              {
                "range": {
                  "posted_at": {
                    "from": "2019-06-01T00:00:00+09:00",
                    "to": "2019-07-01T00:00:00+09:00",
                    "include_lower": true,
                    "include_upper": true,
                    "boost": 1
                  }
                }
              }
            ],
            "adjust_pure_negative": true,
            "boost": 1
          }
        }
      ],
      "adjust_pure_negative": true,
      "boost": 1
    }
  },
  "_source": {
    "includes": [
      "_id",
      "description"
    ],
    "excludes": []
  }
}
```

若干 `bool` 気味っぽいですが、いい感じに変換してくれましたね。

しかしながら、そのフィールドが存在するかや、日付のフォーマット等の妥当性の検証は行われず、単純に SQL から変換した結果を返すだけのため、実際にクエリとして有効かは投げてみないとわかりません。

---

いままで複雑な条件のクエリで、鬼のように入れ子になった Query DSL を悩みながら書いてたこともありましたが、MySQL などと同じように SQL ですっきりと書けるようになったのは嬉しいですね。
< nuxt-link > をpreventしたい

## 便利だけど難しい \<nuxt-link\>
リンクタグを自動生成してくれるわ、VueRouterの操作もよしなにやってくれるわ、とめちゃくちゃ便利な `<nuxt-link>` 。
ただちょっと細かいことをやろうとすると、少しひねくれた手段が必要になる。

例えばクリックしたとき画面遷移と同時に何かしらイベントを起こしたい場合、
そのまま普通にイベントリスナをバインドするだけではダメで、`.native`修飾子をつけなくてはいけない。

```vuejs
<!-- ダメ -->
<nuxt-link to="/hogehoge" @click="fuga"> hogefuga </nuxt-link>
<!-- 良い -->
<nuxt-link to="/hogehoge" @click.native="fuga"> hogefuga </nuxt-link>
```
これは`<nuxt-link>`がルートに`<a>`要素が配置されたコンポーネントとして扱われるため。

## \<a\>タグは prevent で遷移を握りつぶせるけど...
で、今回の本題はクリックした時に処理を走らせて、本来のルーター処理を握りつぶすにはどうしたらいいか。
例えばログイン状態でないと遷移しないリンクとかを作りたい時には、標準の画面遷移処理はなかったことにしないといけない。

こういう時`<a>`タグで実装する場合は、`.prevent`修飾子を使ったり、Eventインスタンスの`preventDefault`を使うと標準処理を握りつぶせる。

```vuejs

<!-- HTMLでprevent指定を行う -->
<a href="/hogehoge" @click.prevent="fuga"> hogefuga </a>

<script>
...
  methods: {
    fuga(e) {
      // jsでpreventする
      e.preventDefault();
    }
  }
...
</script>
```

ところが`<nuxt-link>`では上記の方法でイベントを握りつぶすことができない。
VueRouterが入っているのが原因なのだとは思うが、何とかできないだろうか？

## Routerイベントのトリガーを書き換える
`<nuxt-link>`はVueRouterのコンポーネント`<router-link>`の糖衣構文なわけだが、
このコンポーネントには`event`という、Routerが何のイベントをトリガーとして処理を行うかを設定するプロパティがある。

参考: [Vue Router APIリファレンス](https://router.vuejs.org/ja/api/#event)

というわけで、このトリガーに対して全く無効なイベントタイプを指定してやれば、クリックしても動かなくなるという寸法。

```vuejs
<!-- eventトリガに何も指定しないので、/hogehogeに遷移するRouterイベントが発生しない -->
<nuxt-link to="/hogehoge" @click.native="fuga" event=""> hogefuga </nuxt-link>
```

この`event`プロパティを動的に指定してやることで、条件に応じた`nuxt-link`の操作を行うこともできるので、
例えばログイン時には`"click"`、未ログイン時には`""`を与えるようバインドする、といった条件わけも可能である。


### 参考リンク
* https://github.com/vuejs/vue-router/issues/916
each_with_indexしつつinjectしたい


こうやる。

```ruby
(1..3).each.with_index.inject([]) { |r , (val, idx)| r << [val , idx] }
=> [[1, 0], [2, 1], [3, 2]]
```

rubyは「これできないかなー？」って思ったことがだいたいできるのがいいなと常々思います。

参考 https://www.ruby-forum.com/t/enumerable-inject-with-index/202156/3
EC-CUBE4で納品書ロゴを変更する(4.0.3〜)


EC-CUBE4で4.0.3から管理画面で納品書のロゴ画像を変更できるようになります。

[Github 納品書に表示されているロゴの変更をファイル管理から出来るようにする #4105](https://github.com/EC-CUBE/ec-cube/issues/4105)

# ファイル管理からロゴ画像をアップロード

EC-CUBEの管理画面「コンテンツ管理/ファイル管理」から「assets＞pdf」のフォルダを追加し、「logo.png」のファイル名で画像をアップロードしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72858/b94ca661-7419-6a53-0082-46042b6be623.png)

**※ 画像のサイズは、「横：286px 縦：38px」を推奨します。画像の比率が異なると、表示を崩す恐れがあるのでご注意ください。**

以上の操作で、納品書のロゴ画像を更新することができます。
jQuery plugin datetimepicker 覚書

# 公式からDL
- xdan/datetimepicker: jQuery Plugin Date and Time Picker https://github.com/xdan/datetimepicker
    - Releaseのところから 最新ソースをzipで取得
- ドキュメント
    - DateTimePicker https://xdsoft.net/jqplugins/datetimepicker/

# Quick start
```html

<!-- this should go after your </body> -->
<link rel="stylesheet" type="text/css" href="/jquery.datetimepicker.css"/ >
<script src="/jquery.js"></script>
<script src="/build/jquery.datetimepicker.full.min.js"></script>
```
- この３つを書かないと動かない `jquery.js` も読み込まないとだめ
- zipの中には `jquery.datetimepicker.min.js` とかいろいろあるけど、 `full.min.js` を使わないとエラーで動かない
開発でよく使う docker-compose コマンドたち

なんかよく聞かれるのでまとめておきました。

## バックグラウンドで起動。

```console
$ docker-compose up -d
```

## ${name} のログを表示（追従）

```console
$ docker-compose logs -f ${name}
```

ログ多すぎて、表示行数指定したい場合。（以下は１０行）

```console
$ docker-compose logs -f --tail=10 ${name}
```

## 全部止める

```console
$ docker-compose stop
```

`restart: always` の場合、stopしても再起動しちゃうので

```console
$ docker-compose down
```


## ${name} だけ止める

```console
$ docker-compose stop ${name}
```

## 最新にして綺麗さっぱりする

```console
$ docker-compose down -v # 色々削除
$ docker-compose pull # イメージを最新に
$ docker-compose build --no-cache # キャッシュを利用せずビルドし直し
```
CircleCI 2.1 の job をローカルの CLI で実行する

CircleCI の CLI はまだ 2.1 に対応していないようで、実行しようとするとエラーが発生する（Ver0.1.5725+b0a23c0）。

```bash
$ circleci local execute
Error: 
You attempted to run a local build with version '2.1' of configuration.
Local builds do not support that version at this time.
You can use 'circleci config process' to pre-process your config into a version that local builds can run (see 'circleci help config process' for more information)
```

回避策として

* `circleci config process` コマンドで config.yml を CircleCI 2.1 形式から 2.0 形式に変換
    * このコマンドは config.yml をバリデーションしつつ同時に `executors` や `orbs` などを展開して出力してくれる
* 変換後のファイルを使って job を実行

すればよい。

```bash
$ circleci config process .circleci/config.yml > process.yml
$ circleci local execute -c process.yml
```

ref: [CircleCI のローカル CLI の使用 - CircleCI](https://circleci.com/docs/ja/2.0/local-cli/#%E3%82%B3%E3%83%B3%E3%83%95%E3%82%A3%E3%82%B0%E3%81%AE%E5%87%A6%E7%90%86)
【Unity】マウスクリックで3Dオブジェクトを消すまで苦労した話

# はじめに

こんにちは。
今回はUnityに関することです。
Unityは初心者ですので、そこらへんのご理解お願いします。:bow:

この記事では、私が実際に、マウスクリックで3Dオブジェクトを消そうとした際に、とても苦労した話です。

最初に、消せるだろう手順を踏んだ流れを説明し、その次に消すための方法を記載しています。
この記事は一連の流れに沿って進むので、どうか飛ばさずに読んでいただけるとありがたいです。


# 環境
- Windows 10 home
- Unity 2018.2.15f1


# 消せるだろう手順を踏んだ流れ...

<img width="900" alt="クリック1.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309633/9e629a34-6437-a51e-438d-598f67947c96.png">

このCubeを消すぞ！！:facepunch:


<img width="900" alt="クリック2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309633/9dbb47d0-fdbd-f517-d26c-64852121dd29.png">

Add Componentで「Event Trigger」を追加する。

<img width="900" alt="クリック4.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309633/bd394429-c677-431f-62cd-d16ce31b7b2e.png">

Add Componentでスクリプトを追加するぞ！
とりあえず名前は「cubeDestory」にした。

以下のコードを記述。

```cubeDestroy.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class cubeDestroy : MonoBehaviour {

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}

    public void Destroy(){
        Destroy(this.gameObject);
    }
}
```

<img width="900" alt="クリック5.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309633/eb94eacf-9c55-914c-850d-581ec493aeb9.png">


Event TriggerのAdd New Event Typeで「Pointer Click」追加し、+マークからリストを追加。
そして、自身のCubeオブジェクトを選んで、先ほど作ったDestroy関数を選択する。

よし！これでクリックしたら消えると思ったけど、消えない...........:worried:
なぜだーーーーーーーーーー！！！！！:tired_face: :tired_face: :tired_face: :tired_face:

# あと2つの作業で解決！

ここから、この問題を解決していきます。

<img width="900" alt="クリック6.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309633/892c8445-c907-c6c9-52e1-56fe0b2da37b.png">

Main CameraにAdd Componentで<font color="Red">**「Physics Raycaster」**</font>を追加！

<img width="900" alt="クリック7.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309633/c5ece4ad-b5a3-a727-34ab-71e083358d1c.png">

最後に、Hierarchy → Create → UI → Event Systemで<font color="Red">**「Event System」**</font>を追加！！！

これでやっと、マウスクリックで3Dオブジェクトを消すことができた！！！！！！！:satisfied: :satisfied: :satisfied: :satisfied:


# おわりに

解決できて、めっちゃ嬉しかった！:relaxed:
割と解決するまで、時間がかかったので、同じ悩みを抱えてる人がいたら、ぜひこの記事を見て、解決してほしいです！
ここまで読んでいただき、ありがとうございました。
findを使ったファイル内検索を強くしてみた

みなさんは複数のファイルからあるワードを検索したい時、どのような手法を用いていますか？
私は`find`コマンドを使っています。

`find`はファイル"名"の検索によく用いられますが、`find`の実行結果をパイプで`xargs grep`に渡すことでファイルの中身を検索することもできます。
以下のコマンドを打つことで、カレントディレクトリ以下に存在する.ccファイルの中から、`hoge`というワードが含まれる行が出力されます。

```bash
find . -name "*.cc" | xargs grep "hoge" -n
```

このコマンドを応用して、以下のようなaliasを作ってみました。

``` bash:.bash_aliases
function ff_orig(){
	# 正規表現による条件指定で、拡張子が.ccまたは.hであるファイルについて検索
	find . -type f -regextype posix-egrep -regex ".*\.(cc|h)" | xargs grep "$1" -n | nl | grep $1
}

function ff(){
	# 第一引数：検索ワード
	# 第二引数：エディタ(=vim)で開きたいファイルのindex
	if [ $# -eq 1 ]; then
		ff_orig $1
	elif [ $# -eq 2 ]; then
		vim `ff_orig $1 | sed -n $2p | cut -f 2 | cut -d: -f 1`
	else
		echo "error"
	fi
}
```

例えば、`ownerName`という名前の変数がどこで使われているか探したくなったとき、
上記のaliasを用いることで、カレントディレクトリ以下で`ownerName`が使われている.cc, .hファイルおよびその行が出力されます。

```
$ ff ownerName
     1	./qtenv/inspectorutil.cc:218:                const char *ownerName = owner->getFullName();
     2	./qtenv/inspectorutil.cc:222:                label = ownerName + QString(".") + name + " --> " + nextGateOwnerName + "." + nextGateName;
     3	./envir/sectionbasedconfig.cc:889:        std::string ownerName;
     4	./envir/sectionbasedconfig.cc:891:        splitKey(key.c_str(), ownerName, suffix);
     5	./envir/sectionbasedconfig.cc:895:        if (!ownerName.empty())
     6	./envir/sectionbasedconfig.cc:896:            entry2.ownerPattern = new PatternMatcher(ownerName.c_str(), true, true, true);
     7	./envir/sectionbasedconfig.cc:1176:                std::string ownerName;
     8	./envir/sectionbasedconfig.cc:1178:                splitKey(key, ownerName, suffix);
```

実際には、下画像のように検索ワードに色が付きます。
![qiita投稿用.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262518/f514c271-696e-a6ab-302f-16a95fefe747.png)

また、

```
$ ff ownerName 3
```

と打つと、`sectionbasedconfig.cc`をvimで開くことができます。



筆者は一日100回は使っています。
Boost.Pythonを使って書いたC++拡張をwheelで配布する

[前回のscikit-build](https://qiita.com/termoshtt/items/28c2784d71d5692e8ca3)の続きです。

Pythonのwheelとして配布する場合、拡張モジュールは共有ライブラリとして配布されますが、この時外部の共有ライブラリ（今回はlibboost_python.so）に依存していると、実行時にこの共有ライブラリが必要になります。しかしwheelにはこの共有ライブラリが含まれていないので、`import`時に失敗することになります。

それを避けるために今回はBoost.Pythonを静的にリンクして配布する方法をまとめます。
この内容は以下のリポジトリに含まれています

https://gitlab.com/termoshtt/flat_ffi_example

Boostのビルド
--------------
aptで入れた`libboost-python-dev`に含まれる静的ライブラリをリンクしようとすると`-fPIC`をつけて再コンパイルしろとリンカーに言われるので、おとなしくBoostの再コンパイルから行います。

- [Boostライブラリのビルド方法 - boostjp](https://boostjp.github.io/howtobuild.html)

を参考に作業していきます。今回必要なのはBoost.Pythonだけなので、他のモジュールについてはビルドしません。

```
curl -LO https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz
tar xf boost_1_70_0.tar.gz
cd boost_1_70_0
./bootstrap.sh --with-python=/usr/bin/python3 --with-python-version=3.7
./b2 cxxflags=-fPIC link=static --with-python --prefix=/usr install -j 12
```

- Boost 1.70とPython3.7に対して行います
    - 普通ビルドしようとするとPython2を探してきてしまうので、所々にPythonのパスの指定があります
- コンテナ上で行う予定なので `--prefix=/usr` にしています
- `link=static`で静的ライブラリをビルドするように設定します
- `cxxflags=-fPIC`をつけることによって静的ライブラリ作成時にも強制的にPosition-Independentなコードを生成させることができます。

これでBoost.PythonなC++拡張をビルドしてwheelで配布するための作業コンテナが出来上がります

```dockerfile
FROM debian:buster
LABEL maintainer "Toshiki Teramura <toshiki.teramura@gmail.com>"

RUN apt-get update      \
 && apt-get install -y  \
    curl                \
    g++                 \
    make                \
    cmake               \
    ninja-build         \
    python3             \
    python3-pip         \
    python3-numpy       \
    libpython3-dev      \
 && apt-get clean       \
 && rm -rf /var/lib/apt/lists/*
RUN pip3 install --upgrade pip scikit-build
RUN curl -LO https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz \
 && tar xf boost_1_70_0.tar.gz \
 && cd boost_1_70_0            \
 && ./bootstrap.sh --with-python=/usr/bin/python3 --with-python-version=3.7 \
 && ./b2 cxxflags=-fPIC link=static --with-python --prefix=/usr install -j 12 \
 && cd .. \
 && rm -rf boost_1_70_0*
```

これは一応

```
docker pull registry.gitlab.com/termoshtt/flat_ffi_example/boost_python:latest
```

で取得できるようにGitLabでホストされていますが、今後も使えるかは保障しかねるので何かで使うときは独自にビルドしてください。

cmake
------
Boostを静的にリンクしたい場合は`find_package`する前に `Boost_USE_STATIC_LIBS` を指定してあげます

```cmake:CMakeLists.txt
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost COMPONENTS python numpy REQUIRED)
```

いまいちよく理解していないのですが、上のようにPythonを指定してビルドすると、`python`, `numpy`のコンポーネント名でPython3が指定できます（aptで入れると`python3`等にする必要がある）。

GitLab CI
-----------

このコンテナを使えば以下のようにして、Boost.Pythonを静的にリンクしたwheelをartifactにできます。

```yaml:.gitlab-ci.yml
build_cpp_wheel:
  image: registry.gitlab.com/termoshtt/flat_ffi_example/boost_python
  script:
    - python3 setup.py bdist_wheel
    - mv dist/*.whl ..
  artifacts:
    paths:
      - ./*.whl
```

あとは後段のstepで使うなり、GitLab Pagesで公開するなり、PyPIに公開するなり自由です。