OmniAICreator/Qiita-1.07M huggingface dataset:
PHPMailer 6.1で件名の日本語表示が失敗した件

PHPMailerを6.0.7から6.1.4にバージョンアップしたところ、
件名が文字化けした（というか日本語表示がうまく処理できなくなった）ので調査しました。

# 検証コード

```php
<?php
require 'vendor/autoload.php';
use PHPMailer\PHPMailer\PHPMailer;

$mail = new PHPMailer();

$mail->SMTPDebug = 2;
$mail->isMail();
$mail->Host = '127.0.0.1';
$mail->Encoding = "7bit";
$mail->CharSet = 'ISO-2022-JP';

$mail->setFrom('test_from@example.com', mb_encode_mimeheader('ＦＵＬＬＷ－ＦＲＯＭ'));
$mail->Subject = mb_encode_mimeheader('ＦＵＬＬＷ－ＳＵＢＪＥＣＴ');
$mail->Body = 'ＦＵＬＬＷ－ＢＯＤＹ';

$mail->addAddress('test_to@example.com');

$mail->isHTML(false);
$mail->send();
```

少なくともPHPMailer 6.0.7以前では、メールヘッダに日本語を送信するために
件名等を`mb_encode_mimeheader`で変換する必要がありました。

参考：日本語メールの仕組み
https://sendgrid.kke.co.jp/blog/?p=10958

# 検証結果

## PHPMailer 6.0.7

Subject: ＦＵＬＬＷ－ＳＵＢＪＥＣＴ

```
Received: by app.example.com (Postfix, from userid 1000)
	id 1A4B42E157A; Wed, 22 Jan 2020 18:21:34 +0900 (JST)
To: test_to@example.com
Subject: =?UTF-8?B?77ym77y177ys77ys77y377yN77yz77y177yi77yq77yl77yj77y0?=
X-PHP-Originating-Script: 0:PHPMailer.php
Date: Wed, 22 Jan 2020 18:21:34 +0900
From: =?UTF-8?B?77ym77y177ys77ys77y377yN77ym77yy77yv77yt?= <test_from@example.com>
Message-ID: <ReFYcsIbmzkYl7kzQVqcJHLhrcbf2KxJ5PHVYKu2k@app>
X-Mailer: PHPMailer 6.0.7 (https://github.com/PHPMailer/PHPMailer)
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-2022-JP

ＦＵＬＬＷ－ＢＯＤＹ
```

## PHPMailer 6.1.4

Subject: =?UTF-8?B?77ym77y177ys77ys77y377yN77yz77y177yi77yq77yl77yj77y0?=

```
Received: by app.example.com (Postfix, from userid 1000)
	id F32282E1579; Wed, 22 Jan 2020 18:18:07 +0900 (JST)
To: test_to@example.com
Subject: =?us-ascii?Q?=3D=3FUTF-8=3FB=3F77ym77y177ys77ys77y377yN77yz7?=  =?us-ascii?Q?7y177yi77yq77yl77yj77y0=3F=3D?=
X-PHP-Originating-Script: 0:PHPMailer.php
Date: Wed, 22 Jan 2020 18:18:07 +0900
From: =?UTF-8?B?77ym77y177ys77ys77y377yN77ym77yy77yv77yt?= <test_from@example.com>
Message-ID: <tGMMwDmGQjcmzuOcScE3gGXWoqqwYbZ7SR6ALGYE@app>
X-Mailer: PHPMailer 6.1.4 (https://github.com/PHPMailer/PHPMailer)
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-2022-JP

ＦＵＬＬＷ－ＢＯＤＹ
```

PHPMailer 6.1.4では件名がうまく日本語表示できなくなっています。
PHPMailerのソースを調べてみましたが、この文字化けは、
`$mail->isMail();`を設定したときに発生しました。
（`$mail->isSMTP();`では発生せず）

# GitHub Issueで問い合わせ

非互換になるので、PHPMailerのGithub Issueで問い合わせたところ、
mb_encode_mimeheaderで変換する必要はないとの回答。
https://github.com/PHPMailer/PHPMailer/issues/1945

しかしながら、mb_encode_mimeheaderをしないと、この検証コードでは
PHPMailer 6.0.7でも6.1.4でも件名が文字化けしてしまう。

# 解決方法

CharSetをISO-2022-JPからUTF-8にすれば文字化けしないです。

```php

<?php
require 'vendor/autoload.php';
use PHPMailer\PHPMailer\PHPMailer;

$mail = new PHPMailer();

$mail->SMTPDebug = 2;
$mail->isMail();
$mail->Host = '127.0.0.1';
$mail->CharSet = 'UTF-8';

$mail->setFrom('test_from@example.com', 'ＦＵＬＬＷ－ＦＲＯＭ');
$mail->Subject = 'ＦＵＬＬＷ－ＳＵＢＪＥＣＴ';
$mail->Body = 'ＦＵＬＬＷ－ＢＯＤＹ';

$mail->addAddress('test_to@example.com');

$mail->isHTML(false);
$mail->send();
```

旧メーラーに対応させるため、ISO-2022-JPでメールを送信してきたが、そろそろUTF-8に対応させても良いかも。

参考：メールに関するよくある誤解 その2
https://sendgrid.kke.co.jp/blog/?p=8400
drawをオーバーライドした大きいUIViewはクソほど重い(Swift5)

# はじめに
XCodeをしぶしぶ11にあげました。
開発環境をちょこちょこ変えたくはないんだけど開発者は立ち止まるなってことなんだろうな、きっと。

さて、表題の通りめちゃくちゃ重いので気をつけてください。
アプリが時々落ちるっていう現象からようやくたどり着いた。
最近のハードは性能いいので気づかなかったけど、実はかなり負荷かけてたりってこともあるんだと思う。
何が重いかというとメモリ使用量が重かったです。
先に実測の数字をざっくりと出すと

drawをそのまま  14MB
drawをオーバーライド　120MB


ひえっ・・・
こんなつもりじゃなかったのにという感じです。
さらにこんなViewを2枚、3枚と重ねていくと1枚で100MBほどづつ増えて非力なモバイル端末だと落ちました。
なんでこんなことしてるかというと、ベースとなるUIViewの上に表示用の絵だったり図形を特定の位置に表示する時に相対座標を計算してとかが面倒臭くてやっつけで載せてました。実装が安易といえばそれまでだけど、そんなに悪意がない割にリターンが酷いです。


# サンプル
ダメパターンのサンプルいらんだろ、なんだけどせっかくなので載せておきます。
極端な例ですが、まずベースのUIViewとして5000 * 5000 のサイズを用意してControllerに乗せます。以下のContainerViewをstoryboard上でControllerに乗せておきます。（ここは割愛）



```view:CustomView
class ContainerView :UIView {    
    //---------コンストラクタ---------
    required init?(coder aDecoder: NSCoder) {
        super.init(coder :aDecoder)
        
        // 画面サイズ
        self.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: 5000, height: 5000))        
    }
}
```

用意したContainerViewに乗せる用の無駄に大きいだけのViewを定義します。

```view:TadadekaiView
class TadadekaiView :UIView {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = UIColor.clear
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        self.backgroundColor = UIColor.clear
    }
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)

        let vecInit = CGPoint(x: 100, y: 100)
        let vecRight = CGPoint(x: 100, y: 0)
        let vecUp = CGPoint(x: 0, y: -100)
        let vecLeft = CGPoint(x: -100, y: 0)
        let vecDown = CGPoint(x: 0, y: 100)
        var vecNow = CGPoint(x: 0, y: 0)

        UIColor.yellow.setStroke()
        let pen = UIBezierPath()
        pen.lineWidth = 5
        vecNow = vecInit
        pen.move(to: vecNow)
        vecNow = vecNow + vecRight
        pen.addLine(to: vecNow)
        vecNow = vecNow + vecDown
        pen.addLine(to: vecNow)
        vecNow = vecNow + vecRight
        pen.addLine(to: vecNow)
        vecNow = vecNow + vecDown
        pen.addLine(to: vecNow)
        vecNow = vecNow + vecRight
        pen.addLine(to: vecNow)
        vecNow = vecNow + vecDown
        pen.addLine(to: vecNow)

        pen.stroke()
    }    
}
```

そしてViewController上で配置します。

```view:ViewController
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let list = self.view.subviews.filter({ $0 is ContainerView }).map({ $0 as! ContainerView })
        if list.isEmpty { return }
        let c = list.first!

        let frame = CGRect(origin: .zero, size: c.frame.size)
        let v = TadadekaiView(frame: frame)
        c.addSubview(v)
        let v2 = TadadekaiView(frame: frame)
        c.addSubview(v2)

    }
}    
```

上のサンプルは２枚のせた場合です。
これでめでたく数百MBも意味なく使用する実装の出来上がりです。

回避方法はその気になったら紹介します。
CarrierWaveを使って本番環境からS3に画像をアップロードする方法【heroku】

大変恐れ入りますが、こちらの記事は下記ブログに移転いたしました。
以下からご確認お願いいたします。m(_ _)m
↓
https://kodyblog.com/rails-carrierwave-s3-heroku/
【macユーザ向け】Android Studioの実機デバッグで認識されない時にやったこと

## これは何

　Android Studioでいざ開発しようと思った時に実機が認識されなくて泣きそうだったので今後起こらないように、世界中で泣く人が減るように(大袈裟)残しました。


## 動作環境
OS: macOS Catalina 10.15.3
実機: Huawei p10 (Android 9.0)



## 問題詳細

＜before＞
<img width="330" alt="スクリーンショット 2020-02-01 15.16.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/4bb29a6c-a79a-54fb-4984-c5897a12ed87.png">

実機接続してるのに認識されんやん...という状態

## 解決方法

1. USBデバッグをONにする
2. 接続方法を<font color="red">ファイルを転送</font>か<font color="red">写真を転送</font>にする
3. USBデバッグを許可をONにする(*これが出たらほぼ確実に認識される)


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/2b065c67-763a-404b-2b92-cb43a7a06b31.jpeg" width=400 >




＜after＞
<img width="350" alt="スクリーンショット 2020-02-01 15.18.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/5fe0e7a0-8503-d5ee-b9c9-03731ca74a9e.png">

無事認識された...やっと開発ができる...！

## 参考サイト

https://www.bioerrorlog.work/entry/android-studio-detection
https://sp7pc.com/google/android/39763#toc10
LaTeXでコンパイルする度に番号を振りつつファイルサイズを圧縮したPDFを出力するMakefile


## 背景
大抵の人はLaTeXのソースファイルについては，gitとかで管理していると思うけど，PDFファイルまでgit addしている人はなかなかいない気もする（必要なリビジョンでソースを再コンパイルすれば良いだけだから）

その関係もあって，作業中のPDFについては出力の度に上書きされてしまうから，適当なタイミングで適当に名前を変えたりしてPDFはそのまま残してGoogle Driveなりで保存していたりするのでは無いだろうか？だけど，毎回ファイル名を書き換えるのはダルい．自動化したい．

加えて，共有したり，保存する時には普通にLaTeXで出力すると元の素材画像が大きかったりするとファイルサイズは馬鹿でかくなってしまったりするので，共有する時などはAdobe Acrobatなんかでファイルを圧縮したり最適化していると思います．これもGUIじゃなくてコマンドでやりたい．

**↑これをコマンド一発でやりたい**

## 環境
- 自分はmacでしか動作確認をしていないです．
- PDFを圧縮するために```ghostscript```が必要です．

## Makefileを書く

```makefile:Makefile
FILE=main
V=0

.SUFFIXES: .tex .dvi .pdf

all: $(FILE).pdf
	gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/prepress -sOutputFile=$(FILE)_min.pdf $(FILE).pdf
	open $(FILE).pdf
	open .

generate: $(FILE).pdf
	$(eval V := $(shell find -E . -maxdepth 2 -type f -regex '.*$(FILE)_*v*[0-9]*\.pdf' | sed -e 's/[^0-9]//g' | sort -n | tail -n 1| awk '{print "v"$$1+1}'))
	cp $(FILE).pdf $(FILE)_$(V).pdf
	gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/prepress -sOutputFile=$(FILE)_$(V)_min.pdf $(FILE).pdf
	open $(FILE)_$(V).pdf
	open .

clean:
	rm -rf *.aux *.dvi *.log *.bbl *.blg *.lof *.toc *.idx *.ind *.out *.fls *.ilg *.tdo *.gz *fdb_latexmk
	find . -name "*.aux" | xargs rm

.tex.dvi:
	uplatex $<
	upbibtex $(FILE)
	mendex $(FILE).idx
	uplatex $<
	uplatex $<

.dvi.pdf:
	dvipdfmx -p a4 $<

$(FILE).pdf: $(FILE).dvi
$(FILE).dvi: $(FILE).tex

```

## 作ったもの
まず，前提としてtexファイルの名前は```main.tex```を想定していますので，```FILE=main```としていますが，適宜書き換えてください．```main.tex```をコンパイルすると```main.pdf```ができますが，このファイル名に対して```main_v1.pdf, main_v2.pdf```というように番号を振って出力できます．

カレントディレクトリから深さ2まで範囲でファイル名が，```main_v<番号>.pdf```となるようなものを見つけて，その番号のうち最大のものに1を足した番号で新しいPDFを作ります．デフォルトの形式は```main_v2.pdf, main_v3.pdf```の様な形式ですが任意の文字列にも対応しています．

また，同時に，PDFのファイルサイズを縮小したもので，```main.pdf```に対して```main_min.pdf```のようなものを作成します．

```terminal:使い方
# 1. 普通にコンパイル+圧縮したファイルを出力したい
$ make
// → main.pdf main_min.pdf ができる

# 2. 番号のついたファイルを出力したい
$ make generate
// → main.pdf main_v1.pdf main_v1_min.pdf ができる

# （main.texを編集する）

# 3. 編集したので，また番号のついたファイルを出力したい
$ make generate
# → main.pdf main_v2.pdf main_v2_min.pdf ができる
```

のような感じです．ちなみに，
```V=```と言うオプションを渡してあげると任意の文字列にできます．

```terminal:使い方
# 任意の文字を入れたい
$ make generate V=10
# → main.pdf main_10.pdf main_10_min.pdf ができる

$ make generate V=提出用
# → main.pdf main_提出用.pdf main_提出用_min.pdf ができる
```

体感としては少なくともファイルサイズが半分以下くらいにはなると思います．

誰かの参考になれば幸いです．
MATLABからtoioを動かしてみた

#はじめに
toioのフリー走行モードで遊んでいたのだけども、速度を変えてみると想像以上にしっかり微調整できた。BLEで繋げばtoioを操作できるとのことだったので、制御ガチ勢ご愛用のMATLABで動かしてみた。

#この記事のターゲット
- MATLABからBLEを使ってみたい人
- toioをMATLABで動かしたい人

#つかったもの
- MATLAB R2019b(R2019b以降からble関数がつかえるっぽい)
- toio cube v02.0003
- BLEが使える環境のPC(僕はMacbook Air 2018をつかった)

一番驚いたのが、MATLABに何か別途Toolboxを入れなくてもBLEにつなげるところ。やるなぁ〜

#MATLABとtoioをつなげる
まずは、つなげる先のtoioを見つけてみる。

```MATLAB:blelist
blelist  %BLEデバイス探す
```

多分こんなリストが出てくる。toio Core Cubeって書いてあるところのAddressをメモする。
また、複数のtoio Core Cubeがでてきたら、(自分がおそらくもっているであろう)RSSIがゼロに近いtoioのAddressをメモする。
(もくもく会などではご注意を。。。)

<img width="834" alt="スクリーンショット 2020-02-01 13.31.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271381/b4be911d-8a74-e23a-bd3c-75f9bfd61010.png">

次にtoioとつなげてみよう。toioとMATLABをつなげる際にはble関数を用いる。
たったワンコマンドでつなげるのはホントすごい。

```MATLAB:ble
% 引数にメモしたアドレスを入れる。
b = ble("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
```
ここからtoioに対して様々な操作を行うことができる。これから行う作業の前に
toioの技術仕様を読んでみよう。
https://toio.github.io/toio-spec/docs/ble_communication_overview

"キューブの機能を利用"にあるService UUIDをメモする。
そのあと、自分がやりたい操作をCharacteristicsから選んで様々な操作をしていくが、ここではモータを動かしてみる。リンク先のページにあるCharacteristic UUIDをメモする。
それぞれのUUIDを、bleで出力したオブジェクトのbからcharacteristicメソッドを呼び出す。引数には先程のSerice UUIDとCharacteristic UUIDを順に指定する。

<img width="557" alt="スクリーンショット 2020-02-01 13.51.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271381/3af18d54-be8d-a909-6774-e55ef3e78998.png">

<img width="658" alt="スクリーンショット 2020-02-01 13.55.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271381/b02680a2-a8d2-47bb-f7e2-548d95494262.png">

```MATLAB:toioSetting
c = b.characteristic(...
    "10B20100-5B3B-4571-9508-CF3EFCD7BBAE",...
    "10B20102-5B3B-4571-9508-CF3EFCD7BBAE");
```

このあとにオブジェクトのcからwriteメソッドを呼び出せば、モータに対して様々な操作を行える。writeメソッドに与える情報はデータ位置の0から順に書いた設定パラメータと
プロパティである。詳細は下記ページを参照すること。
https://toio.github.io/toio-spec/docs/ble_motor

例として、toio cubeがクルクル回りだすコマンドの例を示す。
今回は操作を一方的に指定したかったため、'withoutresponce'を追加した。

```MATLAB:toioTurn
% 例: 出力0x64で回転する
c.write([1,1,1,100,2,2,100],'withoutresponse');
```

![P_20200201_142402_vHDR_On.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271381/fcf94c40-d97d-29b8-e30b-5765be1f9196.jpeg)
すっごいまわるよ！

操作が終わったら、clear関数で作ったオブジェクトを削除する。
これで　toioとの通信も自動的に解除される。

```MATLAB:clear
clear
```

#MATLABへtoioの情報をおくる

情報の読み取りも基本的にはwriteとやることは同じ。
何も考えずに、ble関数でオブジェクトを作っておく。

```MATLAB:read準備
blelist
% 引数にメモしたアドレスを入れる。
b = ble("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
```

そして、Service UUIDとCharacteristic UUIDを設定する。
今回はお試しでモーションセンサを使ってみる。

```MATLAB:toioSetting
c = b.characteristic(...
    "10B20100-5B3B-4571-9508-CF3EFCD7BBAE",...
    "10B20106-5B3B-4571-9508-CF3EFCD7BBAE");
```

その後、セミコロンなしで何も考えずにreadを呼び出す。
すると現在のtoioの姿勢などに関する情報が出力される。

```MATLAB:read
c.read()
```

![P_20200201_144538_vHDR_On.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271381/23021640-cfcc-423d-89ce-5a40d0ea1d7b.jpeg)

出力結果は以下サイトに示されたデータ位置に該当する情報となる。
(toioのバージョンが古いと３つしか値が出てこないかも。)
https://toio.github.io/toio-spec/docs/ble_sensor

#おわりに
- MATLABからtoioをBLEを介して操作した。
- toioの情報をMATLABへ送信した。
javaのhello world、コンパイル、実行

完全に忘れてたので覚え直し。

classの中にmain()がある。

class名とファイル名は一緒にして、拡張子は `クラス名.java`

コンパイルすると `クラス名.class`ができる

# **実行は `java クラス名` で、拡張子をつけない！！！**


```java
$ cat HelloWorld.java
public class HelloWorld {
	public static void main(String[] args) {
		System.out.println("Hello World!");
	}
}

# compileする
$ javac HelloWorld.java


# ファイルができる
$ ll HelloWorld.class
-rw-r--r--  1 root  staff   426B  2  1 15:18 HelloWorld.class

# 実行時、拡張子はつけない！！！
$ java HelloWorld
Hello World!

# 拡張子をつけると、こんなエラーが出る
$ java HelloWorld.class
エラー: メイン・クラスHelloWorld.classを検出およびロードできませんでした
原因: java.lang.ClassNotFoundException: HelloWorld.class
```
GOSTを使ってコマンド2つで簡易ゲートウェイをつくる

# GOSTとは

Go言語でかかれたトンネリングツールです．GOSTの概要は以下の記事を参照してください．

- [GOST | GOST](https://docs.ginuerzh.xyz/gost/en/)
- [gost - GO Simple Tunnel がすごい - Qiita](https://qiita.com/tongari0/items/84f630483bef19a2e386)

# コマンド2つで簡易ゲートウェイ

HTTP ProxyとDNS ForwarderをGOSTで作ります．

## 環境/バージョン

- Ubuntu 18.04.3 LTS
- RAM 1GB
- CPU v1コア
- Storage 50GB
- gost 2.9.2 (go1.13.3 linux/amd64)

## 構築(Quick)

インストールと実行は以下の2コマンドで終わります．

```shell
sudo snap install gost
sudo gost -L=udp://:53/1.1.1.1:53,1.0.0.1:53 -L=:8080
```

## ファイアウォール

ufwが有効な場合，ufwで`8080/tcp`と`53/udp`を許可します．

```shell
# TODO: ローカル側のインターフェースを指定
sudo ufw allow 8080/tcp
sudo ufw allow 53/udp
sudo ufw reload
```

## 永続化

永続化にはsystemdのserviceファイルを以下のとおりに書きます．

```unit:/etc/systemd/system/gost.service
[Unit]
Description=Gost Proxy
After=network.target
Wants=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/gost -L=udp://:53/1.1.1.1:53,1.0.0.1:53 -L=:8080
ExecStop=/bin/kill ${MAINPID}
Restart=always
User=root

[Install]
WantedBy=multi-user.target
```

systemdのサービスを読み込んで永続化します．

```shell
sudo systemctl daemon-reload
sudo systemctl enable gost
sudo systemctl start gost
```

# 検証

以下の環境で検証してみました．
![スライド1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/deed4129-c72f-b3ee-226c-6820a11b240e.png)

## クライアントの設定

クライアントも簡易ゲートウェイと同様のスペックです．

netplanの設定ファイルでDNSサーバを指定します．

```yaml:/etc/netplan/01-netcfg.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    ens160:
      addresses:
      - 192.168.210.10/24
      nameservers:
        addresses:
        - 192.168.210.1
```

`sudo netplan apply`で設定を適用させ，`nslookup`で確認します．

```shell
$ nslookup yahoo.co.jp
Server:         127.0.0.53
Address:        127.0.0.53#53

Non-authoritative answer:
Name:   yahoo.co.jp
Address: 182.22.59.229
Name:   yahoo.co.jp
Address: 183.79.135.206
```

環境変数でHTTP Proxyを指定します．`.bashrc`などに以下を記述するとログインのたびに入力が不要になり便利です．

```shell
export http_proxy=http://192.168.210.1:8080/
export https_proxy=$http_proxy
```

wgetやcurlで確認します．

```
$ curl -D - -s  -o /dev/null http://example.com/
HTTP/1.1 200 OK
Age: 393323
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Sat, 01 Feb 2020 06:17:59 GMT
Etag: "3147526947+gzip+ident"
Expires: Sat, 08 Feb 2020 06:17:59 GMT
Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
Server: ECS (sec/96ED)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 1256
```

Ubuntuのaptはプロキシ設定を`/etc/apt/apt.conf`に記述することでプロキシサーバを参照することができます．

```text:/etc/apt/apt.conf
Acquire::http::Proxy "http://192.168.210.1:8080";
Acquire::https::Proxy "http://192.168.210.1:8080";
```
CUIベースの翻訳スクリプトを作ってみた

#動機
最近、CUIで作業することが多くなりました。
CUIは柔軟でとてもいいのですが・・・

#英語をいちいち翻訳していた
（これは自身の英語力の問題ですが)
pythonのトレースバックなどのエラーメッセージはある程度読めるようになりましたが、
Linuxの`man`ページや、`--help`などはほぼほぼ英語なので読めませんでした。
そこで・・・

#パイプを使えば翻訳スクリプトが作れるんじゃないか？
という発想に行きつきました。

#仕様
- googletransを使用
- コマンドライン引数でオプションを受け付ける
- `|`（パイプ）を使った入力にも対応させる



#実際に書いてみた
[gistにも投稿しました。](https://gist.github.com/Tree-frog-code/02e3106079e2955b115c8a84d2e91f30)


```py
#honnyaku.py
# ~ 標準入出力でテキストを受け取って、
# ~ それをprintする
import sys
from googletrans import Translator
from logging import getLogger, StreamHandler, DEBUG
# ~ ログ設定
logger = getLogger(__name__)
handler = StreamHandler()
handler.setLevel(DEBUG)
logger.setLevel(DEBUG)
logger.addHandler(handler)
logger.propagate = False

trans = Translator()

#メイン処理
def convert(text="なし", lang="ja"):
    '''翻訳する関数'''
    #数字以外のものを文字列に変換し、float型などstrに変換できない型を除外する
    try:
        text = str(text)
    except:
        logger.error("文字列か整数以外のものが入力されました。")
    
    conv_text = trans.translate(text, dest=lang)
    return conv_text.text
```
##テストコード
今回はテスト駆動開発風に開発しました。

```py
# ~ テストコード
import honnyaku
try:
    assert "こんにちは" == honnyaku.convert("hello")
except AssertionError:
    print("失敗")

else:
    print("成功")
```
実際の様子
![2020-02-01-151007_1824x984_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384132/4d515457-7c91-700e-c470-30e977b0008a.png)

うまく翻訳できました！
もう少しオプションの実装方法を考えたいので、次回にしたいと思います。
インデントを気にせずyank/copyする

# はじめに
org-modeなど、インデントによって階層を表現するテキストを書いていると、他のアプリケーションとの間でテキストをやりとりするのが不便です。というのも、いちいちインデントを入れたり外したりしなければならないからです。ググってみたところ解決策を見つけたのでシェアします。

# インデントを気にせずにyank/copyする
## yank

```:zannen-yank.org
* ざんねんな例
  #+begin_quote
  他のアプリケーションから複数行のテキストをここに貼り付けようとすると、
こんな風になってしまいませんか。
いちいちインデントするのも面倒ですよね。
これくらいの行だったら手作業でも良いかもしれませんが、
例えばプログラム実行時のログだったらどうでしょうか？
  #+end_quote
```

[org mode - how to paste with indent - Emacs Stack Exchange](https://emacs.stackexchange.com/questions/31646/how-to-paste-with-indent) にインデント付きでyankする関数が掲載されています。インデント幅は、この関数を実行したときのカーソルの位置を参照します。

```elisp:init.el
;; https://emacs.stackexchange.com/questions/31646/how-to-paste-with-indentより転載
(defun yank-with-indent ()
  (interactive)
  (let ((indent
         (buffer-substring-no-properties (line-beginning-position) (line-end-position))))
    (message indent)
    (yank)
    (narrow-to-region (mark t) (point))
    (pop-to-mark-command)
    (replace-string "\n" (concat "\n" indent))
    (widen)))

;; バインド
(define-key org-mode-map (kbd "C-c C-y") 'yank-with-indent)
```

## copy (kill-ring-save)

```:zannen-copy.org
* 他の人に共有したいメモ
  自分の作業メモをorg-modeで取っていて、Slackなどのコミュニケーションツールで他の人にも共有したいとします。
  この領域のテキストをコピペしようとすると、各行の先頭にあるスペースも含まれてしまいます。
  スペースを削除するのに、コピペ後に手動で、あるいはコピペ前にC-x r k (kill-rectangle) するのは面倒ですよね。
```

[killing - copy region without leading indentation - Emacs Stack Exchange](https://emacs.stackexchange.com/questions/34966/copy-region-without-leading-indentation) にインデントを解除しながら領域をコピーする関数が掲載されています。

```elisp:init.el
;; https://emacs.stackexchange.com/questions/34966/copy-region-without-leading-indentationより転載
(defun my-copy-region-unindented (pad beginning end)
  "Copy the region, un-indented by the length of its minimum indent.

If numeric prefix argument PAD is supplied, indent the resulting
text by that amount."
  (interactive "P\nr")
  (let ((buf (current-buffer))
        (itm indent-tabs-mode)
        (tw tab-width)
        (st (syntax-table))
        (indent nil))
    (with-temp-buffer
      (setq indent-tabs-mode itm
            tab-width tw)
      (set-syntax-table st)
      (insert-buffer-substring buf beginning end)
      ;; Establish the minimum level of indentation.
      (goto-char (point-min))
      (while (and (re-search-forward "^[[:space:]\n]*" nil :noerror)
                  (not (eobp)))
        (let ((length (current-column)))
          (when (or (not indent) (< length indent))
            (setq indent length)))
        (forward-line 1))
      (if (not indent)
          (error "Region is entirely whitespace")
        ;; Un-indent the buffer contents by the length of the minimum
        ;; indent level, and copy to the kill ring.
        (when pad
          (setq indent (- indent (prefix-numeric-value pad))))
        (indent-rigidly (point-min) (point-max) (- indent))
        (copy-region-as-kill (point-min) (point-max))))))

;; バインド
(define-key org-mode-map (kbd "C-c M-w") 'my-copy-region-unindented)
```

# おわりに
最近設定ファイルに追加した項目では個人的スマッシュヒットでした。もし同様に困っている人がいれば是非どうぞ。
ほぼコピペ記事になってしまいましたが、時間を見つけて内容をちゃんと理解したいです。
Rails MVC内におけるデータのやりとり

インスタンス変数の定義やActiveRecordの定義時などは、必ず代入する側の**class名**を確認すること。

エラー問題の際、この部分を意識して確認すること。

Rails内のコードもRubyで学んだ基礎の応用に過ぎない。
Ubuntu18.04でgpg6204のビルド

### これは何?

Ubuntu18.04で[PEX-361316](http://www.interface.co.jp/catalog/prdc.asp?name=PEX-361316)を利用したい。
いくつかモジュールを組み込む必要があるが、カーネルが新しいため、ビルドが必要。ビルドを通す際の記録。
いくつかビルドを通す必要があるが、長くなるため、`gpg6204`のみを取り上げます。

### ビルドを通すまで

##### Makefileの編集

```Makefile:Makefile
CFILES = penc_drventry.c
obj-m += cp6204.o
cp6204-objs := $(CFILES:.c=.o) ../ver26/bocp6204noreg.o
KBUILD_EXTRA_SYMBOLS = ~/work/PEX-361316/common/dpg0100/src/Module.symvers

all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
install:
        cp -f cp6204.ko /lib/modules/$(shell uname -r)/misc
```

##### penc_drventry.cの編集

####
```c:penc_drventry.c
static void gpg_timer_fn(struct timer_list *t)
{
        return;
}
void gpg_penc_init_timer(void *ext)
{
        PPENC_EXTERNAL_STRUCT pExt = (PPENC_EXTERNAL_STRUCT)ext;
        // init_timer(&(pExt->timer));
        timer_setup((struct timer_list *)(&(pExt->timer)), gpg_timer_fn, 0); // 追加
}
...
void gpg_penc_add_timer(void *ext, void *function,
                        unsigned long data, unsigned long expires)
{
        PPENC_EXTERNAL_STRUCT pExt = (PPENC_EXTERNAL_STRUCT)ext;
        // pExt->timer.function = function;
        // pExt->timer.data = data;
        timer_setup(&(pExt->timer), function, data); // 追加
        pExt->timer.expires = expires;
        add_timer(&(pExt->timer));
}
...
long gpg_penc_interruptible_sleep_on_timeout(void *ext, long timeout)
{
        PPENC_EXTERNAL_STRUCT pExt = (PPENC_EXTERNAL_STRUCT)ext;
        long lret=0;
        // lret = interruptible_sleep_on_timeout(&(pExt->wait), timeout);
        lret = gpg_interruptible_sleep_on_timeout(&(pExt->wait), timeout);
        return lret;
}
...
#if (LINUX_VERSION_CODE >= VERSION(2,6,36))
// static int penc_ioctl(struct file *file, unsigned int iocmd, unsigned long ioarg)
// 戻り値がintからlongに変わっているため、intのままだとエラーになる。
static long penc_ioctl(struct file *file, unsigned int iocmd, unsigned long ioarg)
#else
static int penc_ioctl(struct inode *inode, struct file *file, unsigned int iocmd, unsigned long ioarg)
#endif
{
        return gpg_penc_ioctl((void*)file, iocmd, ioarg);
}
```

##### いざmake

```
$ ln ../../../../../common/dpg0100/src/dpg0100.h .
$ ln -s ../../include/fbipenc.h .
$ make
$ sudo make install
cp -f cp6204.ko /lib/modules/5.3.0-26-generic/misc
```

### ロード
```
$ sudo depmod -a
$ sudo modprobe cp3300 
$ dmesg
...
[ 2344.919532] ---[ end trace f91d2f1f146998e4 ]---
[ 2344.919798] pci 0000:05:0c.0: enabling device (0000 -> 0002)
[ 2344.919918] cp6204:Interface 3-Mode Pulse Counter Device Driver (Ver4.10.17.00) loaded.
$
```

### 参考ページ

- [Ubuntu18.04でgpg3300のビルド - Qiita](https://qiita.com/ProjectM_TACCMI/items/38380db7c2280fc655a4)
- [Ubuntu18.04でgpg3100のビルド - Qiita](https://qiita.com/ProjectM_TACCMI/items/5d1f2b61297bb87f0dc1)
- [Linux source code: include/linux/fs.h (v5.3.18) - Bootlin](https://elixir.bootlin.com/linux/v5.3.18/source/include/linux/fs.h#L1789)
Android Vulkan 開発のメモ 

## Depth/Stencil buffer

https://vulkan-tutorial.com/Depth_buffering

DEPTH_STENCIL を指定して作成しても,  subresourceRange.aspectMask には `VK_IMAGE_ASPECT_DEPTH_BIT` のみを指定しないとだめっぽい.(Validation Layers でエラーが出る)

ただ, きちんとやる場合はバリア命令を発行して(?), 実際のイメージレイアウトを取得して判定する必要がある.
(Vulkan Tutorials での `transitionImageLayout`

## Uniform buffer のアップデート

共有メモリだからか, uniform buffer を swapchain ごとに用意しないことによる不都合が出やすいです(e.g. uniform buffer に morph や skinning の情報を入れて, CPU COHERENT にしていると, CPU で書き込み中に GPU での読み込みが発生して描画が乱れる).

swapchain ごとに uniform buffer を用意するのがいいでしょうか.

https://www.reddit.com/r/vulkan/comments/auwkqg/handling_postprocessing_and_uniformbuffers_per/
【Rails】トランザクション

```rb
ActiveRecord::Base.transaction do
  user1.save!
  user2.save!
  records.each(&:save!)
end
```

`ActiveRecord::Base.transaction do`で囲んだブロックの中でDBへの問い合わせをすると、途中で不具合が発生した時にそれまでの変更がロールバックされる。

##注意点
`save`メソッドや`create`メソッドを使うと、登録に失敗しても例外が発生しないので、ロールバックが行われない。必ず`save!`、`create!`、`update!`などを使用すること。
fishでもsudoで罵られたい！[元ネタ：sudoするたびに可愛い女の子に罵られたい！！]




元ネタはこれ
出典：[sudoするたびに可愛い女の子に罵られたい！！](
https://qiita.com/onokatio/items/561d544f07c03b26f4d7)

これで自分のシェルちゃんが可愛くなりますね💕

この記事だとzshだったみたいなのでfishでもいけるかなと思ったので確認した時のメモ。

やり方📝

SUDO_PROMPTの変数でこのメッセージを格納しているらいしいので呪文を唱える。

`set -x SUDO_PROMPT "[sudo] さっさとパスワード入れなさいよ、このバカ！ > "`

永続的にしたい場合は以下

`echo 'set -x SUDO_PROMPT "[sudo] さっさとパスワード入れなさいよ、このバカ！ > "' >> ./.config/fish/config.fish`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89244/b8adc5f3-7dc2-480e-65d2-37f332e18ce3.png)


こんな感じにできたらOK

コメント欄にあったtimeoutの値を入れると毎回罵られるので好きな人は入れておけばいいんじゃない

`sudo visudo`

※vim /etc/sudoersでも編集できるけど、良いこはvisudoを使いましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89244/e005faa1-2596-0950-3812-7d887b2616b8.png)
visudo 編集画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89244/9d63e9f7-c84f-48af-1b75-bfef48bf822b.png)
反映できているか確認した図

## おまけ

パスワードを間違えた時に罵られる方法

以下visudoで設定を編集

```
#これを入れると間違えた時罵られる
Defaults badpass_message="パスワードが間違ってるじゃない！正しいの入れなさいよ！！"
```

実験結果

```
 ~  sudo visudo                                              1.5m  Sun Feb  2 10:06:28 2020
[sudo] さっさとパスワード入れなさいよ、このバカ！ > 
パスワードが間違ってるじゃない！正しいの入れなさいよ！！
```

ソース：https://www.tecmint.com/sudo-insult-when-enter-wrong-password/
golang でプログラム内で API から取得したデータを使い回すときの方法を調べてみた

## はじめに

最近 golang 触り始めました。まだまだ勝手がわかっていないことが多いです。
今回は、CLI ツールのようなプログラムで、API から取得したデータをで使い回すときの方法について調べてみました。

## tl;dr

グローバル変数を使うのが良さそうだと思いました。

## 想定するケース

[aws-sdk-go](https://github.com/aws/aws-sdk-go) で、S3 のバケット一覧を取得し、この結果を複数の関数内で何度も利用する場合を考えます。

何度も API からし直すと、そのたびリクエストが走ってしまいます。そのため処理を軽くするために、プログラム内で API から取得したデータを使いまわす方法がないかを調べていました。

## サンプルコード

S3 のバケット一覧を取得するサンプルコードです。

```go
package main

import (
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
)

func fetchS3BucketList(profile, region string) {
	sess := session.Must(session.NewSessionWithOptions(session.Options{Profile: profile}))
	svc := s3.New(sess, aws.NewConfig().WithRegion(region))
	result, err := svc.ListBuckets(nil)
	if err != nil {
		panic(err)
	}
	fmt.Println(result)
}

func main() {
	fetchS3BucketList("SAMPLE_PROFILE_NAME", "ap-northeast-1")
}
```

## グローバル変数を使う

上記くらいの単純なプログラムであれば、プログラム内のグローバル変数として持たせるのが手軽で良いのではないかと思いました。

より規模が大きくなってきたらグローバル変数に持たせた値の影響なども考え始めないといけなくなるので、別案を考えたほうが良さそうです。

## コードのイメージ

こんな感じでしょうか。`fetchS3BucketList` 関数内で取得した API 実行結果を グローバル変数の `bucketList` に保持して、`main` 関数内で使えるようにしています。

```go
package main

import (
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
)

var bucketList s3.ListBucketsOutput

func fetchS3BucketList(profile, region string) {
	sess := session.Must(session.NewSessionWithOptions(session.Options{Profile: profile}))
	svc := s3.New(sess, aws.NewConfig().WithRegion(region))
	result, err := svc.ListBuckets(nil)
	if err != nil {
		panic(err)
	}
	bucketList = *result
}

func main() {
	fetchS3BucketList("SAMPLE_PROFILE_NAME", "ap-northeast-1")
	fmt.Println(bucketList)
}
```

## おわりに

簡単な例だったのですが、グローバル変数以外に関数間で値を使い回す方法があれば教えていただけるとありがたいです。

## 参考

* [s3 - Amazon Web Services - Go SDK](https://docs.aws.amazon.com/sdk-for-go/api/service/s3/#ListBucketsOutput)
* [A Tour of Go](https://tour.golang.org/basics/8)
【React Native】RSSリーダー

# 環境
Expo CLI
TypeScript使用…CLIでTypeScript　Blankを選択

シュミレーター起動の確認ができたら
必要なパッケージをインストール

react-native-xml2js
react-native-elements

```
$ npm add react-native-xml2js
$ npm add react-native-elements
```

```App.tsx
// Expo CLI
// TypeScript要選択

import React, { Component } from 'react';
import { FlatList, Linking, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { Header, Tile } from 'react-native-elements'; // $ npm add react-native-elements
import xml2js from 'react-native-xml2js'; // $ npm add react-native-xml2js

// xml適宜変更
const FEED_URL = 'https://news.yahoo.co.jp/pickup/rss.xml';

type Props = {};

type FeedItem = {
  link: Array<string>,
  title: Array<string>,
};

type State = {
  feedItems: Array<FeedItem>,
};

const renderItem = (params: { item: FeedItem }) => (
  <TouchableOpacity onPress={() => Linking.openURL(params.item.link[0])}>
    <View style={ styles.row }>
      <Text style={ styles.title }>{ params.item.title[0] }</Text>
      <Text style={ styles.link }>{ params.item.link[0] }</Text>
    </View>
  </TouchableOpacity>
);

export default class App extends Component<Props, State> {
  state = {
    feedItems: [],
  }

  componentDidMount() {
    fetch(FEED_URL)
      .then(res => res.text())
      .then((xml) => {
        const parser = xml2js.Parser();
        parser.parseString(xml, (err, result) => {
          this.setState({ feedItems: result.rss.channel[0].item });
        });
      });
  }

  render() {
    return (
      <View style={styles.container}>
        <View style={ styles.base }>
            <Header
                centerComponent={{
                    text: 'RSSリーダー',
                    style: styles.header
                }}
            />
        </View>
        <FlatList
          ItemSeparatorComponent={ () => <View style={ styles.separator } />  }
          data={ this.state.feedItems }
          renderItem={ renderItem }
          keyExtractor={ item => item.link[0] }
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  base: {
    padding: 0,
  },
  body: {
      backgroundColor: '#fff',
  },
  header: {
    color: '#fff',
    fontSize: 20,
    fontWeight: '500',
  },
  container: {
    flex: 1,
    backgroundColor: '#FFF',
  },
  row: {
    flex: 1,
    padding: 20,
  },
  title: {
    color: '#000',
    fontSize: 16,
  },
  link: {
    color: '#db7093',
    fontSize: 12,
  },
  separator: {
    flex: 1,
    height: 1,
    backgroundColor: '#ddd',
  },
});

```
17杯目セキュリティうどん（かまたま）勉強会

17杯目セキュリティうどん（かまたま）勉強会のまとめ
----

# 000 はじめに


「触れてみよう IoT セキュリティ！」というタイトルで東京大学 特任准教授 満永 拓邦氏が
メインのスピーカーでハンズオン形式のワークショップが開催されました。

17杯目セキュリティうどん（かまたま）勉強会
http://sec-udon.jpn.org/doku.php?id=workshop:17th

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47058/0cddc4c1-e687-dc50-bbc8-e3fd7b1849b0.png)

私は「14杯目セキュリティうどん（かまたま）勉強会」から少し間があきましたが2回目の参加になります。

14杯目セキュリティうどん（かまたま）勉強会：Python入門と機械学習によるマルウェア検知
https://qiita.com/taniokah/items/d6825410fc9c5e99eac5

# 001 自己紹介

定員30名（満員御礼）の参加者がそれぞれ自己紹介したと思います。
徳島から参加のたにおかは、遅れて参加なので自己紹介できませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47058/229d8667-8178-8359-10cd-700ec15f818a.png)


# 002 サイバーセキュリティについて

IoTとかDXとかバズワードで世の中動いてる。
クラウド、AI、DX、、、

## ポケベル

1995年 数字しか送れない

0840
0833
...

## IoTの脆弱性

年々脆弱性が増えている。点滴の量もネットワーク経由で変更できる。

## IoTの座学

- IoT基礎: 利用者の視点
- IoT応用: 開発者の視点

- 技適（技術基準適合証明等のマーク）

技適マークが最近変わりました

- IoTとは

半数以上がLinuxが採用されている
TCP/IP(WiFi)
Bluetooth
...

# 003 Webカメラを攻撃しよう1

市販のWebカメラの管理者画面に入るためのパスワードをゲットします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47058/301522ff-9422-e959-bbad-f1b0205abb06.png)

## telnetでパスワードを取得

Windowsの場合は、TeraTermでアクセスします。
ただし、直接telnetでアクセスするとうまくいかなかったので、会場に用意してもらったRaspberryPi経由でやりました。

具体的にはどうやるかというと、以下の場合にはエラーはありませんが、、、

```
GET /index.asp HTTP/1.1
```

次のようにすると怪しげなレスポンスが、、、

```
GET index.asp HTTP/1.1
```

つまりHTTPリクエストの解析ミスがあるというわけですね。基礎中の基礎、ディレクトリブラウズが！？

# 004 Webカメラを攻撃しよう2

OSコマンドインジェクションがあるらしく、wgetを使うだけでtelnetdを起動できたり、
ファイルを作成できたりするらしい、信じられない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47058/4ed2bb27-1faa-c61d-6a0a-5d7feecd31f7.png)

実際、ログインできてしまいましたね。

# 005 Bluetoothリプライ攻撃

- WiFi
- Bluetooth
- BLE(Bluetooth Low Energy) 

## BLE

BLEの通信は暗号化されてないことが多い。

- ペアリング
- RaspberryPi

## PCAPデータ

WiresharkでキャプチャするとGATT形式のデータが得られる。

## GATT

Attributeのハンドルに値を書き込むと動く。

## hcitool

BLEアダプタを制御する機能がRaspberyPiにはあります。

```
pi@raspberrypi:~ $ sudo hcitool lescan | grep "UPQLED1"
F4:B8:5E:E5:17:XX UPQLED1
F4:B8:5E:E5:17:XX UPQLED1
F4:B8:5E:E5:12:XX UPQLED1
F4:B8:5E:E5:96:XX UPQLED1
F4:B8:5E:E5:99:XX UPQLED1
F4:B8:5E:E5:9E:XX UPQLED1
F4:B8:5E:E5:67:XX UPQLED1
F4:B8:5E:E5:A1:XX UPQLED1
F4:B8:5E:E5:17:XX UPQLED1
```

## gatttool

そしてgatttoolでBLEデバイスに接続し、GATTの書き込みをして、青いLEDライトを緑にしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47058/ab392ca9-9833-a663-7da3-3a98e21c63f5.png)

```
pi@raspberrypi:~ $ gatttool -b F4:B8:5E:E5:67:XX -I
[F4:B8:5E:E5:67:XX][LE]> connet
Attempting to connect to F4:B8:5E:E5:67:XX
0000008effff:67:XX][LE]> char-write-cmd 0x002b 0f0d030012ff0f6a0000000
Notification handle = 0x002e value: 0f 04 03 00 00 04 ff ff
```

こんな感じで書き込むと、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47058/ce0ddc5d-bb40-b2db-c29b-5b9a16c6ac37.png)

緑に光ったよ！大成功。


# 111 まとめ

WebカメラをWebサーバの脆弱性をついて制御しました。
LEDライトはBLEのコマンドをたたくことで制御できてしまいました。

Webカメラのほうは、ソフトウェアがしっかり対策すれば問題ないはず。
BLEコマンドの脆弱性は、仕様の問題もありますが、暗号化するなどは必須ですね。
久々のEclipse起動でつまった話

# 現象
フレームワークを勉強しようと思って、Eclipseを起動した。

エラーメッセージが表示されて起動しなかった。
![コメント 2020-02-01 132759.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539265/5e2a59f9-f6dc-62b0-d53f-c3ae58afed94.png)

# 調査
Eclipseのホームページを確認したところ、2018-09版を最後に32bit版のリリースが終わってるらしい。
https://mergedoc.osdn.jp/

ググってOracleのJREをインストールすると、32bit版がインストールされる。
JDKは2019年4月にOracleの無償サポートが終了したので、OpenJDK 64bit版をインストールしている。

32bit版JREで64bit版Eclipseを起動しようとしたことが原因の模様。

# 対策
・下記のURLからOracleのWindows 64bit版用JREをダウンロードしてインストール
https://java.com/ja/download/manual.jsp

# 対策結果の確認
無事、Eclipseが起動した。
![コメント 2020-02-01 134518.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539265/f8c46f02-e844-d780-9d1e-f20c92a98a5d.png)

あれ？tool.jarが無いらしい。
これが無いと、Springが動かないと。。。また調査せな←
JavaFXみたいに、JDKに含まれなくなったやつかな？
分かり次第、コメントに追記しときます
![コメント 2020-02-01 134418.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539265/aaf03ce2-c4fe-2c5e-1586-f05fead0b608.png)



#備考
Eclipseのホームページを確認した時に気づいたのだが、WindowsでのEclipseモジュールの
zip解凍には7-zipを使えとのこと。
案の定、Lhaplusを使ってた私は、解凍時にエラーが発生し、一部ファイルが解凍に失敗していた。

7-zipをダウンロードしてインストールし、再試行したところ、正常に解凍できた。

LhaplusではWindowsの解凍とシステム上の制限は変わらないし、業務上で扱うファイルサイズも大きくなってる。
7-zipでzip以外の圧縮形式が使われるのが普通になる日は近い。。。？？？
Git基本操作

#ファイル編集→Git管理の基本的な流れ
###※commitはアプリが正しく動いてる段階でこまめに行いましょう。




###①最新のリモートのブランチ一覧をローカルに持ってくる。 

```
$ git fetch  
```
  
<br>
###②現在存在するリモートブランチ一覧を確認する。 

```
$ git branch -r 
```
  
<br>
###③利用したいリモートのブランチのローカルブランチを作成し、同時に作成したブランチへ移動する。 

```
$ git checkout -b ローカルに作るブランチ名 origin/リモートから持ってきたいブランチ名 
```
  



<br>
###④(ファイルを編集した後)編集したファイルの前回のcommitからの変更内容（差分）を確認する。 

```
$ git diff ファイルパス/ファイル名 
```
<br>

###⑤編集したファイルをステージングする。 
ステージングしたいファイル全てを選択する。

```
$ git add ファイルパス/ファイル名 
```
<br>
  

###⑥ローカルリポジトリの変更内容をコミットする。 

```
$ git commit -m "コミットメッセージ" 
```
  <br>

###⑦ローカルブランチの変更内容をリモートブランチにプッシュする。 

```
$ git push origin 内容を反映したいリモートブランチ名 
```
  <br>

###⑧ローカルブランチの内容を最新化する。 

```
$ git pull origin 最新化したいリモートのブランチ名 
```
【2020年2月】プログラミングしたい人向けのMac、どれを買うべきか

動画編集はしない、プログラミング目的でMacを使う人に向けた記事です。
動画編集してYouTuberになりたい人は、別の記事を見てね。

## 必要最低限スペック

プログラミング用途で必須のスペックは以下の通り。

- メモリは16GB
- ストレージは512GB
- ノートパソコンつまりMacBook AirかMacBook Pro

メモリは8GBでは足りないと思う。
昔のMBPならSDカード挿すことで容量を増やせたが、今のは出来ないのでSSD 512GBが必須。
プログラミングしたいなら持ち運べるノートパソコンも必須。

## 選択肢

上記のスペックを満たすのを[Apple](https://www.apple.com/)から探すと

- MacBookPro 2019 16インチ(タッチバーあり) i7 6Core 16GB 512GB GPUあり 25万
- MacBookPro 2019 13インチ(タッチバーあり) i5 4Core 16GB 512GB GPUなし 24万
- MacBookPro 2019 13インチ(タッチバーなし) i5 4Core 16GB 512GB GPUなし 20万
- MacBookAir 2019 13インチ(タッチバーなし) i5 2Core 16GB 512GB GPUなし 18万

となる。(価格は四捨五入、税抜き)

MacBookAirのCPUはクソ雑魚なので、18万のAir買うなら20万のProを買った方が長く使えるので良い。また、24万のPro13インチを買うなら、GPU付きでCPUも強くてESCキーも付いた25万のPro15インチのが良い。

## 結論

結果として次の２つしか選択肢はない。

- MacBookPro 2019 16インチ(タッチバーあり) i7 6Core 16GB 512GB GPUあり 25万
- MacBookPro 2019 13インチ(タッチバーなし) i5 4Core 16GB 512GB GPUなし 20万

あとは、カバンに入るのかとか、いつも持ち運ぶのかとかで決めると良い。

## 未来の話

2020年の内にMacBookPro 13インチもESCキーが復活してキーボードも壊れにくくなったモデルが出ると思われる。MacBookPro 13インチを買うならそのタイミングが良いと思う。
ちなみに、MacBookPro 16インチは今が買い時。
応用情報技術者試験　合格への道：システム戦略：業務プロセス、ソリューションビジネス、システム活用促進・評価

システム戦略：業務プロセス、ソリューションビジネス、システム活用促進・評価の攻略となります。

複数個出題されている問題の解説と、個別の問題の回答の考え方を記載していきます。

どうしても多岐にわたっているので、私の個別の問題の回答を参考にするというよりは、どのように理解して記憶しようとしているのかという部分を参考にしていただければ！

私自身このようにまとめて、他の問題も含めて過去問を解き、テスト直前に見直す、というものに使うためにまとめております。

大事なのはここに書いてある内容より、どのようにまとめてそれをご自身がどのように使うのか、ということになると思います。


#■業務プロセス

UML関連の問題が4/8。

※UML関連
ここが非常に参考になります

https://qiita.com/github129/items/80d39f2f043489033076

引用：UML は Unified(統一された) Modeling(モデリング) Language(言語)

ソフトウェアをわかりやすく記載するための言語 → 結局図になってしまう という理解がよさそうです

上記ページに各種図があるので、どのソフトウエアを説明するための図なのかを理解することが必要ですね。

・UMLを採用した場合の活用シーン	H30秋期 問62
　→目的に応じた図である、ということが理解してれば解ける

・UMLの図法はどれか	H28春期 問66
　→ユースケース図 = システムが提供する機能と利用者の関係を表現する、と覚える。

・UMLの活用シーン	H26春期 問63、H24春期 問63
　→目的に応じた図である、ということが理解してれば解ける

※非UML関連

・論理モデルを説明したものはどれか	H25秋期 問63
　→「現物理モデル」→「現論理モデル」→「新論理モデル」→「新物理モデル」 の話。
　　　あるべき姿、なので「新論理モデル」の方。
　　　現状の実際、その論理、新しい論理、新しい実際、をそれぞれ当てはめる。

・BPOを説明したものはどれか	H24秋期 問62
　→BPO(Business Process Outsourcing)、だと分かっていれば解ける

・リエンジニアリング	H23秋期 問63
　→用語として覚える。

・E-R図	H22秋期 問62
　→実体(entity)，関連，属性(relationship)を覚えておけば解ける
　　他の問題で「状態遷移図」がでるがこれは「現在の状態と発生する事象で、状態が変化するシステムを記述する図式化手法」。

#■ソリューションビジネス

SOA関連の問題が5/9。

※SOA関連

SOA：Service-Oriented Architecture

引用元
https://it-trend.jp/words/soa

企業に導入されている様々なアプリケーションまたその機能の一部を一つのサービスとしてコンポーネント化し、そういった部分部分を必要に応じて一つのサービスとして組み合わせることで新たなシステムとして使う、といった設計の手法です。

Oriented→志向

・SOAの説明はどれか	H28秋期 問61、H27春期 問63
・SOAを説明したものはどれか	H28春期 問63、H26秋期 問63、H22秋期 問64
　→上記の説明を理解していても選択肢にズバリそのものはない。ただ他の選択肢が違うなということはわかるはず。

※非SOA関連

・クラウドサービスに切り替える時の留意点	H30秋期 問63
・クラウドサービスの導入事例	H29秋期 問63
　→クラウドサービスの意味が分かっていればわかる

・適切なソリューションはどれか	H31春期 問62
　→ワントゥワンマーケティングは、市場シェアの拡大より、顧客との好ましい関係を築き長期的に利益を得る仕組み
　　CRM(Customer Relationship Management)、Customer=顧客と覚える

・SaaSを説明したもの	H22春期 問63
　→SaaS(Software as a Service)は、事業者が運用するソフトをネットワーク経由で利用するサービス。


#■システム活用促進・評価

出題のされ方が多岐にわたるので、過去問の把握くらいしか費用対効果がある対応がないと思います。

・オープンデータの説明はどれか	R1秋期 問63
　→オープンデータ：ネットワーク経由で加工、編集、再配布等の無償利用ができるように公開されたデータ。

・データサイエンティストのスキルセット	H31春期 問63
　→言葉の定義が問題文に記載されているので問題文をちゃんと理解できれば正解を選ぶことができる

・BIの活用事例	H28秋期 問63
　→BI(Business Intelligence)は、蓄積されたデータを分析・加工し、経営や業務に役立つ情報を見つけ出す手法・技術の総称
　　LMS(Learning Management System:eラーニングに必要な、学習教材の配信や成績などを統合して管理するシステム)とごっちゃになりがちなので注意。
　　BIはデータ、LMSは教材

・情報リテラシを向上させる施策	H24秋期 問63
　→リテラシ(literacy:識字)なので情報に関係する選択肢を選ぶ


#■最後に

前回、今回でシステム戦略の午前過去問の攻略を行いました。

繰り返し出てくる問題も多いですが、そうでない問題も多く出題範囲全部の網羅は厳しいと思います。

逆に全く見たことも聞いたこともない、言葉から意味が想像できない、という用語も少ないでしょう。

みたことがある程度の知識がごっちゃにならないように整理することで、随分と点数の底上げが可能だと思います
オフラインどう書く第7回参考問題解答

問題はこちら
http://nabetani.sakura.ne.jp/hena/ord7xysort/

Prologでは、行でソートするときは転置を交え、
安定ソートのためにリストの先頭にその行の符号（を数に変換したもの）を加え(change/3)、
さらにその前に（リスト内の）カギとなる列の数を加え(change/3)てソートし、
その後先頭の二要素を除去しましたが、
juliaでは組み込みの関数のみで解けます。

Prolog

```Prolog
%swi-Prolog  version 7.4.2
%start.
%:-initialization(start).   % ideone

xy([[4,1,4,2,1,3],[7,3,2,0,5,0],[2,3,6,0,6,7],[6,4,5,7,5,1],[3,1,6,6,2,4],[6,0,5,5,5,1]]).
h([1,2,3,4,5,6]).

trans([[]|_], []).
trans(M, [X|T]) :- row(M, X, M1),trans(M1, T).
row([], [], []).
row([[X|Xs]|Ys], [X|R], [Xs|Z]) :- row(Ys, R, Z).

change(X,L,R):-R=[X|L].
del([_|T],T).

sort1(L,N,R):-
     maplist(nth1(N),L,L1),h(HL),maplist(change,HL,L,L2),maplist(change,L1,L2,L3),
     sort(L3,L4),maplist(del,L4,L5),maplist(del,L5,R).
solve([],L):-xy(L).
solve([H|T],R):-
     solve(T,R1),atom_codes(H,[C]),(C>116->(N is C-116,sort1(R1,N,R));
     (N is C-64,trans(R1,R2),sort1(R2,N,R3),trans(R3,R))).

start:-str(S),split_string(S,"\s\n","\s",L),pre(L),!.

pre([]).
pre([_,B,Q|T]):-
     atom_chars(B,L),reverse(L,L1),solve(L1,[H|_]),
     atomics_to_string(H,R),disp(R,Q),pre(T).

disp(R,A):-(A==R->Str=" pass ";Str=" fail "),write(Str),writeln(R).

str("0  AvEx    305027
1       A       112344
2       C       241413
3       F       134214
4       u       236067
5       w       732050
6       y       414213
7       yx      732050
8       ux      236067
9       EF      131424
10      DF      134124
11      Au      055165
12      uA      023667
13      By      234114
14      yB      114342
15      yBy     357020
16      yByB    350072
17      AuBvCw  131244
18      FAuFBvFCw       300527
19      AuBv    112344
20      CwDx    515056
21      FzyE    324114
22      uAwDyB  114324
23      zExCvF  073520
24      uFxEv   002357
25      DyCwB   076362").
```
Julia

```Julia
#Julia 1.10

str="0 	AvEx 	305027
1 	A 	112344
2 	C 	241413
3 	F 	134214
4 	u 	236067
5 	w 	732050
6 	y 	414213
7 	yx 	732050
8 	ux 	236067
9 	EF 	131424
10 	DF 	134124
11 	Au 	055165
12 	uA 	023667
13 	By 	234114
14 	yB 	114342
15 	yBy 	357020
16 	yByB 	350072
17 	AuBvCw 	131244
18 	FAuFBvFCw 	300527
19 	AuBv 	112344
20 	CwDx 	515056
21 	FzyE 	324114
22 	uAwDyB 	114324
23 	zExCvF 	073520
24 	uFxEv 	002357
25 	DyCwB 	076362"

fi=[4 	1 	4 	2 	1 	3
7 	3 	2 	0 	5 	0
2 	3 	6 	0 	6 	7
6 	4 	5 	7 	5 	1
3 	1 	6 	6 	2 	4
6 	0 	5 	5 	5 	1]


function solve(l)
    f=copy(fi)
    for i in l
        n=Int(i)
        if n>116
            j=n-116
            f=sortslices(f,dims=1,lt=(x,y)->isless(x[j],y[j]))
        else
            j=n-64
            f=sortslices(f,dims=2,lt=(x,y)->isless(x[j],y[j]))
        end
    end
    ans(x)=reduce(x) do a,b
       string(a)*string(b)
   end
    return ans(f[1,1:end])
end

function main()
    str1=split(str,"\n")
    for s in str1

        s1=split(s,"\t")
        ans=string(solve(strip(s1[2])))
        if ans==strip(s1[3])
            sel="pass"
        else
            sel="fail"
        end
        print(sel," ",s1[3]," ",ans,"\n")
    end
end

@time main()

```
lodash備忘録

# lodash知っとくと捗る
##### 調べたら情報は出てくるけど少しでもその時間を少なくするために備忘録をつける。
##### 新しいものを使うたびに増やしていくスタイルにしよう

### ・find
- 文字通り検索系。配列を検索する。
- 例）ユーザーIDをキーに`users配列`を探しpayloadでもらったidに該当したオブジェクトを返却する

```javascript
// payloadがhogeのとき
const user = _.find(this.users, {
      userId: payload.userId
    })
// => user: {userId: 'hoge', userName: 'fuga'}
```

### ・findIndex
- `find`のindex版。こちらはキーに該当するオブジェクトが配列の何番目にあったかを返す。

```javascript

this.TabIndex = _.findIndex(this.tabs, {
      sikCd: node.sikcd
    })
// => 1
```

### cloneDeep
- 文字通りディープコピーする。これは結構使う。
- シャローコピーとディープコピーの違いは[コチラ](https://nansystem.com/shallow-copy-vs-deep-copy/)で。
- 初学者の頃、変更前・変更後の比較の処理でシャローコピーをしていて、値が共有されていてハマりまくっていたのでこれはすぐ覚えた。

```javascript

let obj = {
 title: "HOGE",
 description: "FUGA"
}
const obj2 = cloneDeep(obj) // => obj2: {title: "HOGE", description: "FUGA"}
```

### padStart
- 桁を0埋めとかでそろえたいとき

```javascript

_.padStart(5, 2, '0'); // => '05'
_.padStart(12, 4, '0'); // => '0012'
_.padStart(100, 2, '0'); // => '100'
```

### times
- for文を簡潔にしたもの

```javascript
length = 100
  hoge = _.times(length, i => {
      // やりたい処理
  })
```
Laravelで親モデルのデータを取得する


親テーブルのデータにアクセスできなくて困った。
調べたらいくつか原因になる情報が見つかったので記録しておく。


```php:app/Models/User.php

class User extends Model
{
  protected $fillable = ['name'];
}
```

```php:app/Models/Post.php

class Post extends Model
{
  public function user()
  {
    return $this->belongsTo('App\Models\User');
  }

  public function getUserNameAttribute()
  {
    return $this->user->name;
  }
}
```

```
echo $post->user_name;
```


以上だとうまくいかないらしい。

```diff:app/Models/Post.php

  public function getUserNameAttribute()
  {
-    return $this->user->name;
+    return $this->user['name'];
  }

```

こうするといけるらしい。（上記コード自体は記事のために書いたもので未検証。類似コードで同じ現象が起きることは確認ずみ）

## 参考

https://qiita.com/jacoloves/items/72d425d1b790bfa9b6c2
https://teratail.com/questions/119544
【Rails入門】form_withについて解説！form_tag, form_for との違いは？

#はじめに

● form_tag
● form_for 
これらは Rails5.1で __非推奨__ となり、将来 `form_with` に完全に置き換えられる予定とのこと。
この記事では、`form_tag`、 `form_for` と `form_with` との違いについて触れていきます。
<br>
__まずは一旦おさらいから。__
#form_tag
フォームを作りたいとき、関連するモデルがなかったときは `form_tag` を使用。
→「検索フォーム」など投稿フォームに入力した内容が保存されない場合は`form_tag`を使用します。

```erb

<%= form_tag users_path do %>
  <%= text_field_tag :text %>
  <%= submit_tag %>
<% end %>
```

#form_for
そして、モデルがあったときは `form_for` を使用。
→投稿フォームで投稿した内容が保存されるデータベースが存在する時には`form_for`を使ます。

```erb

<%= form_for @user do |f| %>
  <%= f.text_field :text %>
  <%= f.submit %>
<% end %>
```
---
ただし、`form_for` と `form_tag` では構文が書き方が異なり、使い分けがめんどいですね。
そこで現れた救世主、`form_with`！

#form_with

　関連するモデルがない `form_with`

```erb

<%= form_with url: users_path do |f| %>
  <%= f.text_field :text %>
  <%= f.submit %>
<% end %>
```

　関連するモデルがある `form_with`

```erb

<%= form_with model: @user do |f| %>
  <%= f.text_field :text %>
  <%= f.submit %>
<% end %>
```

関連するモデルがある時(インスタンス変数がある時)は、飛んでいくリンク先が自動で振り分けられます。
→`@user`がDBに存在するときは、`update`アクションが、
ないときは、`create`アクションが動きます。(今までの`form_for` と同じ。)

#非同期通信のAjaxがデフォルトで付く
`form_with` で生成されたフォームは、デフォルトで非同期通信のAjaxが実装されます。
よって、`form_tag` と `form_for` のように、`remote: true` と指定する必要がありません。


もし、リモートフォームを無効にした場合は `local: true` と指定します。

```erb

<%= form_with model: @user, local: true %>
<% end %>
```

#formタグのidとclass属性はhtml: { }で囲まなくてOK

`form_for`では、、

```erb

<%= form_for @user, html: { id: :hoge_id, class: :hoge_class } do |form| %>
<% end %>
```
`form_with`では、、

```erb
<%= form_with model: @user, id: :hoge_id, class: :hoge_class do |form| %>
<% end %>
```

#idとclass属性の自動付与について (Rails5.2)

__Rails 5.1__ の`form_with` では、
`input要素`などのフォームフィールドへの`id`と`class属性`の自動付与が無効となっており、
すべて自分で指定する必要がありましたが、
__Rails 5.2__以降では、今までの`form_tag`　と `form_for` と同様、`id属性`を__自動付与__するようになったので、自分で指定する必要はなくなりました!


#最後に
もう、
あれ？`form_tag` と `form_for` どっちだっけ？
どっちが `f.submit` でどっちが `submit_tag` だっけ？
と悩まなくていいです！！

今後は `form_with` をどんどん使って身につけましょう。
そして`form_tag` と `form_for` は忘れましょう。(忘れなくていい)

この記事が初心者のみなさんの役に立つことを願っています。しばた


##参考
>https://qiita.com/hmmrjn/items/24f3b8eade206ace17e2
ドキュメントは縦書きで書くべきか、横書きで書くべきか

# ドキュメントの用紙の方向について
まず、ドキュメントを作成するときに指定される用紙の向きについて考えたことがあるでしょうか。結論から言えば、縦書きで書くべきです。ただし、見かけるドキュメントの大半は横書きです。

ドキュメントの縦書きか横書きかを検討しているということは、まず印刷することを前提にしていると言えます。マークダウンなど、印刷を前提にしない条件で書く場合であれば、いちいち縦書きか横書きかを考えません。

# 用紙の向きを決める基準
一般的に販売されている書籍は、執筆のプロが書いて編集のプロがレイアウトをした商品です。ドキュメントを書く基準として、一般的な書籍を参考に考えてみます。

## 縦書きで印刷されているもの
* 文章中心の書籍
* 小説

一般的に売られている書籍の大半が縦向きです。文章を中心とした書籍は横向きのものがありません。例外としては、江戸時代以前に書かれた巻物です。横に長い一枚の紙に文章が書かれています。ただし、現代においてこの形式を使用しているのを見たことが無いので除外します。

## 横書きで印刷されていることがあるもの
* 一部の絵本
* 一部の写真集
* 地図
* 設計図

ビジュアルを中心にする場合、横向きに印刷する場合があります。ただ、一般的に売られている書籍のほとんどが縦向きです。設計図は一般的に売られている書籍ではありあせんが、ビジュアルが大事になる印刷物なのでリストに加えました。

# 実際にドキュメントを書くにあたって
ドキュメントの用紙の向きで悩むのであれば、縦向きで作成することをお勧めします。理由は、世の中の書類の大半が縦向きだからです。

![tate.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39277/87721c09-59a8-95b1-5157-a49028fedf2a.jpeg)

同じ文章を横向きにするとこのようになります。

![yoko.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39277/eebfc8c6-a83c-e4c4-2d30-05ae76c8ae22.jpeg)

ドキュメントがしっかりとした文章で構成されているのであれば、大きな差はでませんが、見出しをつけたり箇条書きなど使うと、横書きでは余分な空白が増えてしまいます。

![tate2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39277/210934cb-d863-797d-5942-3d260764a230.jpeg)

縦書きであればきれいに一枚に収まっていても、横書きにするとはみ出ます。

![yoko2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39277/366a6726-5e08-341f-de21-e1e848658188.jpeg)

横書きで書いた場合、余分な余白が入りやすく、レイアウトを構成するのが難しくなります。紙に印刷した場合も、ページめくりがしにくく、あまり扱いがよくありません。用紙のフォーマットが横向きで指定されていない限りは、ドキュメントはの用紙の向きは縦向きで作成しておく方が無難です。

特に、作成する枚数が多くなるほど、レイアウトの重要性は高くなります。ドキュメントの用紙を横向きで作成する場合は、ページ数の少ない画像中心のものにとどめておくといいかもしれません。
眺めて覚えるGo言語 その16 並列処理 「sync.WaitGroupは複数のgoroutineの完了を待つ」

#眺めて覚えるGo言語 その16 並列処理 
##「sync.WaitGroupは複数のgoroutineの完了を待つ」

```thread.go
package main
import ("fmt";"sync";"time")
func main() {
   wg := sync.WaitGroup{}
   for i := 0; i < 10; i++ {
      wg.Add(1)
      go func (i int) {
         defer wg.Done()
         fmt.Println("Thread no",i)
         time.Sleep(1)
      }(i)
   }
   wg.Wait()
   fmt.Println("complete!")
}

実行結果
>go run thread.go
Thread no 0
Thread no 5
Thread no 2
Thread no 3
Thread no 9
Thread no 4
Thread no 6
Thread no 7
Thread no 8
Thread no 1
complete!

```
社内ネットワークからパブリックIP付きのインスタンスでPacker buildする

VPN接続などで社内ネットワーク（というかインスタンスのプライベートIPにアクセスできるネットワーク）に接続しているPCから、パブリックIPを付与したPackerのEC2インスタンスをビルドしたいときは `ssh_interface` に `private` を指定するといい感じに動きます

[ドキュメント](https://www.packer.io/docs/builders/amazon-ebs.html#ssh_interface)を見るとなんとも言えない感じですが、[こちら](https://github.com/hashicorp/packer/blob/f0461da1a1a6234c934ecacf1c16a7458d1a088b/website/source/partials/helper/communicator/_SSHInterface-not-required.html.md)など見るとちゃんと記載があります

>  One of public_ip, private_ip, public_dns, or private_dns.

```json:抜粋
{
  "builders": [
    {
      "type": "amazon-ebs",
      "associate_public_ip_address": true,
      "ssh_interface": "private_ip"
    }
  ]
}
```

自分は指摘してもらって分かったことだったのですが、
作業してて詰まったときはリポジトリそのものを調べるのも大事ですね...！