OmniAICreator/Qiita-1.07M huggingface dataset:
【Unity】トラブルシューティング集

Unityを利用していて、何か困ったことがあって解決法を見つけたらここに書き残すことにします。なお、初めてこの記事を書いたときはまだUnity入門〜初級みたいなレベルです。どんどん書き足したいと思います。あまりに増えたときは記事を分けるかもしれません。

#オブジェクトを積み上げた時に安定しない
2018.11.22 Unity2018.2.3f1
###RigidbodyのDragを大きくする
Dragは空気抵抗のことを指します。これを10のように大きくしてみましょう。高く積めば積むほど大きくしないと安定しにくいです。なお、公式では
>Drag の通常の値は、.001 (金属の塊) と 10 (羽) の間です。

とあります。

###物理演算を無効にする
上記の方法だと、衝突などで現実的な動きをしてくれないでしょう。別の方法は、スクリプトで以下の関数を用いることです。上から物理演算を止める・始める関数です。

`this.GetComponent<Rigidbody>().sleep()`
`this.GetComponent<Rigidbody>().WakeUp()`

"this"はGameObject型の変数です。安定させたいオブジェクトに付けたスクリプトで利用すればいいです。

参考サイト：
ほぼ上側のサイトの情報です。画像や動画付きで解説しています。
[Unityの物理演算(Rigidbody)を設定したオブジェクトが崩れたりバラけたりして安定しない](http://code.hildsoft.com/entry/2017/06/21/095629)
[Rigidbody - Unityマニュアル](https://docs.unity3d.com/ja/current/Manual/class-Rigidbody.html)

#オブジェクトの名前を変えたい
2018.11.22 Unity2018.2.3f1

###GameObject型のクラスメンバーに文字列代入
Instantiate関数でオブジェクトを複数生成すると同じ名前のオブジェクトが生成した分だけできてしまいます。これでは検索ができなくて不便になる時があるでしょう。
GameObject型の変数を用意して、そのクラスメンバーnameに文字列を代入しましょう。例えば、GameObject型の変数objに生成したオブジェクトを代入したならば、

`obj.name = "block1"`

とすると名称は"block1"になります。これで検索がしやすくなります。

#どのmaterialを使ったかコンソールに表示させたい
2018.11.24 Unity2018.2.3f1

###GetComponent< Renderer >().materialを使う
オブジェクトをスクリプトで生成して名前変えたとなったら、もともとどのprefabやmaterialを使ったかは一つずつしか見られなくなります(Inspectorビューで参照可)。多数生成させた時にコンソールで一気に参照したいこともあるでしょう。オブジェクトobj(GameObject型)のmaterialについては次のような文で参照できます。
`obj.GetComponent<Renderer>().material`
prefabについても調べましたが、やってもうまくいかなかったので見つけたら追加します。
Raspberry PI自動運転車

##概要
Raspberry PIを利用した自動運転車です。
超音波センサーで、障害物を回避して進みます。
![DSC_0279.JPG](https://qiita-image-store.s3.amazonaws.com/0/219051/83ce8809-49cc-d93b-37c6-89f5d0bf30ed.jpeg)

##ロジック
①赤外線センサーで前面距離をチェック
②左右度の

※後進から前進までの動作の間はLEDが点灯します。

##必要なもの
- タミヤ テクニクラフトシリーズ No.8 4速ウォームギヤボックスHE 72008
- タミヤ 楽しい工作シリーズ No.111 スポーツタイヤ 56mm径 (70111)
- タミヤ 楽しい工作シリーズ No.172 ユニバーサルプレートL 210×160mm (70172)
- 自在キャスター（G-32N）
- TA7291P
- EasyWordMall HC-SR04 超音波距離センサーモジュール
- 抵抗
- 0.1μfコンデンサ
- LED
- ブレッドボード
- モバイルバッテリー（Anker PowerCore 10000）
- 配線材など
- みのむしクリップがあると便利です

##ソースコード
[https://github.com/type89/auto_control_tank/blob/master/moter/kubifuri_pigpio.py](https://github.com/type89/auto_control_tank/blob/master/moter/kubifuri_pigpio.py)


##動作デモ
壁への角度が浅い場合はうまく検知できません。
![0.jpg](https://qiita-image-store.s3.amazonaws.com/0/219051/59227d57-8dee-64ce-2325-e7d9f364bee7.jpeg)
[https://www.youtube.com/watch?v=QIKCg3oyTNU](https://www.youtube.com/watch?v=QIKCg3oyTNU)
[https://www.youtube.com/watch?v=sfBYlbHv37g](https://www.youtube.com/watch?v=sfBYlbHv37g)

##苦労したところ
- テクニクラフトシリーズのギアボックスは4mmシャフトなので、「トラック＆ホイールセット」のキャタピラが使えません。やむなく「スポーツタイヤセット」を利用しました。
- 「ラダチェーン＆スプロケットセット」を使用して４輪駆動にしましたが、曲がれませんでした。
    - 結局、キャスターを使って３輪車にしました。こちらのほうが旋回性は良好です。
    - 段差はほとんど上がれません。家で走らせるには踏破性がほしいです。
- 左右同じ出力にしても曲がってしまう
    - カット＆トライで左右モータのデューティー比を調整しました。
- 首振りした後にサーボが正面を向かない
    - pigpioを使用することで解決しました。

##今後の改良事項
- モバイルバッテリーでRaspberryPIとモータを両方給電する
    - ピンヘッダから給電する

##作者のサイト
- [https://neo-momopi-blog.herokuapp.com/](https://neo-momopi-blog.herokuapp.com/)
Goのsliceやmapの型宣言省略

mapを一気に定義する場合、途中の型は省略して書いていくことができる。

```go
	j := map[string]map[string][]string{
		"foo": {
			"aaa": {
				"bababa",
			},
		},
		"foo3": {
			"aaa": {
				"bababa",
				"bababa",
				"bababa",
				"bababa",
			},
		},
	}
```

これ、丁寧に書くとこうなるんだけど、

```go
	j := map[string]map[string][]string{
		"foo": map[string][]string{
			"aaa": []string{
				"bababa",
			},
		},
		"foo3": map[string][]string{
			"aaa": []string{
				"bababa",
				"bababa",
				"bababa",
				"bababa",
			},
		},
	}
```

自明な部分は省略できるというわけだ。

sliceや配列でも同じように省略が効く。

```go
type person struct {
	Name string
	Age  uint
}
// ...
	p := []person{
		{
			Name: "taro",
			Age:  10,
		},
		{
			Name: "hanako",
			Age:  12,
		},
	}
// ↓丁寧に書くと
	p := []person{
		person{
			Name: "taro",
			Age:  10,
		},
		person{
			Name: "hanako",
			Age:  12,
		},
	}
```

ちょっと感動したのだが、構造体のポインタであっても省略が効くようだ。&をつけたりする必要はない。

```go
	p := []*person{
		{
			Name: "taro",
			Age:  10,
		},
		{
			Name: "hanako",
			Age:  12,
		},
	}
// ↓丁寧に書くと
	p := []*person{
		&person{
			Name: "taro",
			Age:  10,
		},
		&person{
			Name: "hanako",
			Age:  12,
		},
	}
```

## 言語仕様リンク

> Within a composite literal of array, slice, or map type T, elements or map keys that are themselves composite literals may elide the respective literal type if it is identical to the element or key type of T. Similarly, elements or keys that are addresses of composite literals may elide the &T when the element or key type is *T. 

https://golang.org/ref/spec#Composite_literals

というわけで、書かなかったがmapのキーに対しても同じように省略が効くらしい。

## 何故か構造体は省略が効かない

省略が効くのはmapとsliceとarrayだけである。構造体の中に構造体があるような場合、そこの省略は効かない…。ちょっと不便。

```go
type Birthday struct {
	Year, Month, Day int
}

type person struct {
	Name     string
	Birthday Birthday
}
//...
	p3 := map[string]person{
		"taro": { // personの型は(mapだから)省略できている
			Name: "taro",
			Birthday: Birthday{ // Birthdayの型は省略できない
				1990, 1, 1,
			},
		},
		"hanako": {
			Name: "hanako",
			Birthday: Birthday{
				1990, 1, 2,
			},
		},
	}
	p4 := map[string]person{
		"taro":   {"taro", Birthday{1990, 1, 1}}, //この書き方でも同じ。
		"hanako": {"hanako", Birthday{1990, 1, 2}},
	}
```
groveの光センサをESP32で使用する

# 目的
懸賞であたったのでgrove のセンサをいろいろ持っていて使いたいが、
ESP32のシールドなんか持ってないので（そもそもあるのか？）、
直接ESP32に配線してgroveユニットを使用することにした

# 光センサの接続 (Light-Sensor-v1.2)

今回使用する光センサがアナログ出力なので、
アナログ入力ができるらしいADCと書かれている端子に接続する（今回はADC0）
ちなみに、ESP32のADコンバーターは12bitらしい
赤：電源　　　　　　3.3 V
黒：グラウンド　　  GND
黄色：信号出力　　　ADC0
https://www.seeedstudio.com/Grove-Light-Sensor-v1.2-p-2727.html

ピン配置は以下の画像やサイトを参考にした
<参考：スイッチサイエンス>
https://trac.switch-science.com/wiki/esp32_tips
<img src="https://qiita-image-store.s3.amazonaws.com/0/317476/4e813346-ac60-a7d9-d8c4-50b3a1bd66fb.png" width=70%>
<img src="https://qiita-image-store.s3.amazonaws.com/0/317476/6baae614-e7d4-f20c-f338-2c0b7d86b56e.png" width=70%>

# プログラム

grove の　starter kit 用のコードを参考に温度取得をシリアルモニタで監視できるように書き換え
シリアルのセットアップを書き忘れて動かなくてびっくりした
https://github.com/Seeed-Studio/Sketchbook_Starter_Kit_for_Arduino/blob/master/Grove_Light_Sensor/Grove_Light_Sensor.ino

```
uint64_t chipid;  

void setup() {
    Serial.begin(115200);
}

const int pinLight = A0;

void loop()
{
    int sensorValue = analogRead(pinLight);    //the light sensor is attached to analog 0
    Serial.printf("Light Strength = %d\n",sensorValue);

    delay(2000);
}
```
シリアルモニタで明るさを読み取ることができるようになった
昼間の窓際で2350程度、スマホのライトを直接当てても2360程度にしか上がらなかった
<img src="https://qiita-image-store.s3.amazonaws.com/0/317476/fcded34e-579b-69d7-ce93-6100716c496d.png" width=70%>

電源電圧を 3.3V から 5V にすると、
暗いときは0、通常が2000程度、明るい（スマホのライト照射）時は4095となった
ADコンバーターが12ビットと考えると妥当な値である
電源電圧が3.3ボルトのときは、センサ側の出力が足りてなく、明るさ上限値が低かったと思われる
<img src="https://qiita-image-store.s3.amazonaws.com/0/317476/2447987a-8d66-d004-d7ed-14bcc57ba215.png" width=70%>

#まとめ

アナログ入力の読み取りができた
I2CとかSPIの接続も比較的簡単にできそうで Arduino の便利さに感激
ESP32を買ってしまった

#目的

IoT系の部署に配属になったので、個人的に勉強しないと行けない気になり、
Arduinoで開発できwifiも積んでいて安いESP32を購入した
とりあえず Arduino IDE のインストールと書き込みまでやってみた
<img src="https://qiita-image-store.s3.amazonaws.com/0/317476/c84cce3a-2c0e-eab6-9ace-43d8a1d345fc.jpeg" width=70%>
ESP32 (Github)
https://github.com/espressif/arduino-esp32#esp32dev-board-pinmap

# ESP32シリーズ
購入した最新型のＥＳＰ－ＷＲＯＯＭ－３２Ｄは前行機と価格・性能は変わらないが、
サイズが小さくなった利点と、最低電源電圧が上昇した欠点があるらしい。
秋月電子で並んで売ってあり、適当に買ったけど良かった。。。

ESPシリーズの紹介
https://ht-deko.com/arduino/esp-wroom-32.html
esp32シリーズデータシート
https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf

●秋月電子
[ＥＳＰ－ＷＲＯＯＭ－３２]
ＥＳＰ３２－ＤｅｖＫｉｔＣ　ＥＳＰ－ＷＲＯＯＭ－３２開発ボード
http://akizukidenshi.com/catalog/g/gM-11819/
[ＥＳＰ－ＷＲＯＯＭ－３２D]　←買ったほう
ＥＳＰ－ＷＲＯＯＭ－３２Ｄ開発ボード
http://akizukidenshi.com/catalog/g/gM-13628/


# 開発環境の構築

以下のサイトを参考にした
バージョンが違うが、操作そのものはほぼ一緒なので助かった

（参考：ESP32 用 Arduino 開発環境の初の安定版 1.0.0 がリリースされたのでセットアップした 20180730 版
https://qiita.com/Guwashi/items/1009faab2d3db24d80d5）

Aurduino IDEを公式からダウンロード
最新バージョン ARDUINO 1.8.7 (181118 時点)
https://www.arduino.cc/en/Main/Software

設定 > 環境設定に行き、追加のポートマネージャーに入力
https://dl.espressif.com/dl/package_esp32_index.json
<img src="https://qiita-image-store.s3.amazonaws.com/0/317476/718f264b-dce0-60ca-e1df-2d8622860c66.png" width=70%>

ツール > ボード > ボードマネージャー > esp32 を検索しインストール
<img src="https://qiita-image-store.s3.amazonaws.com/0/317476/c3d2f5e3-a136-d886-4163-fcdd4d33cd13.png" width=70%>

ツール > ボード > ESP32 Dev Module　に変更
これで、ESP32用にコンパイラされる
<img src="https://qiita-image-store.s3.amazonaws.com/0/317476/c861da13-7320-32e5-050a-6c6f2263cfa3.png" width=70%>

＊書き込み時にエラー発生（ポート設定されていないと言われている）
　（Please select a Port before Upload）

ドライバをインストールすると、ポートで認識される様になった。
UARTをUSBで送信？

CP210x USB - UART ブリッジ VCP ドライバ
https://jp.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers
<img src="https://qiita-image-store.s3.amazonaws.com/0/317476/4c41a05e-1ca0-9bd5-165c-1e16e88441b3.png" width=70%>

ツール > シリアルポート > デバイス番号（今回は COM6）に変更
指定したシリアルポートに書き込み

以下のようにbpsを設定することで文字化けせずに読み取れる
ツール > UploadSpeed = 115200 
シリアルモニタ > 1152000 bps

<img src="https://qiita-image-store.s3.amazonaws.com/0/317476/8ca9f1dd-1690-75a8-ca89-6b23a6d17d41.png" width=70%>

# まとめ

Arduino IDE の環境構築とサンプルプログラムを使用した通信ができた
DockerでGitlabのプライベートリポジトリをsshでcloneする方法

いつかDockerやらなきゃな～と思っていたのですが、先日ようやくこちらでDocker童貞を卒業しました。
https://training.play-with-docker.com/beginner-linux/
ブラウザだけで使えるのでまだDTの方はぜひご利用ください。

で、Dockerを "完全に理解した" 私はさっそくコンテナの中でGitlabからcloneしようとしたのですが、なかなかハマってしまいました。。
ひたすらググり続けてなんとか完成しましたがすごく辛かったです。
まあごちゃごちゃ言ってないではよ完成したDockerfile見せれやって感じだと思うので、以下の通りです。

前提
・ssh公開鍵をGitlabに登録してあること
・ssh秘密鍵(id_rsa)を/root/.ssh/id_rsaに置いていること
・GitlabのUser名：hoge
・プロジェクト名：foo
・コンテナのタグ：piyo
・port:3000

```Dockerfile

FROM node:8.11.3
ENV HOST 0.0.0.0
EXPOSE 3000
RUN mkdir /root/.ssh && \
  touch /root/.ssh/config && \
  chmod 600 /root/.ssh/config && \
  echo " Host gitlab.com" >> /root/.ssh/config && \
  echo " User hoge" >> /root/.ssh/config && \
  echo " IdentityFile /root/.ssh/id_rsa" >> /root/.ssh/config && \
  ssh-keyscan -H gitlab.com >> /root/.ssh/known_hosts && \
  ssh-keyscan -H 35.231.145.151 >> /root/.ssh/known_hosts
CMD chmod 600 /root/.ssh/id_rsa && \
  git clone git@gitlab.com:hoge/foo.git && \
  cd foo && \
  npm install && \
  npm run dev

```

・DockerfileからImage作成
`docker build ./ -t piyo`

・Imageからコンテナ実行
`docker run --rm -p 3000:3000  -v /root/.ssh/id_rsa:/root/.ssh/id_rsa -it piyo`


これで`localhost:3000`で起動されます。
そもそもいつもhttpsでcloneしてたのでssh鍵を生成するところから頑張りました。
よ～しこの調子でDocker達人になるぞー！

ではでは。
【エッセイ】ちょっとしたツールを作る際に気を付けること

## ちょっとしたツール
開発をしていると、テストなどを行う際に、「ちょっとしたツール」を作成することはよくあると思います。テストのほかにも、ちょっとしたビルドツールやデプロイスクリプトなどプロダクトコード以外のコードも「ちょっとしたツール」に含まれます。今回はこの「ちょっとしたツール」について話していきたいと思います。

## 自分のためのツールが...
上記のツールなのですが、まず、最初は自分しか使わないのですが、ほかの人が使いたいといった場面が必ず訪れます。（私の経験上、必ず訪れます...）
しかし、このようなツールは自分しか使うことを想定していないので、コードや設計が適当に作られることが多いです。他人に引き渡す際に適当なコードで恥ずかしいこと思いをすることが多々あります。
自分が恥ずかしい思いをするだけなら、まだいいほうですが、そのようなツールは「オレオレな使い方」になっていることがほとんどです。ツールを適当に引き渡して、その引き渡した人が本番環境でそのツールを使ってしまい、DBにテスト用データをぶち込んでしまうこともあるかもしれません。

## プログラマとしての心構え
プログラマとしてコードを書くなら、いつ・どんなコードもどんな使い方をされるかわからない、または、いつ人に見られてもいいようにコードを書くべきです。また、どんな使い方をされてもいいように設計しないといけません。
ロックしないでファイル読み込み

少し特殊ですが、ファイルをロックしないで読み込みしたくなりました。PowerShellで実装してみましたので、メモしておきます。

# 実装方法

ファイルをロックせずに、ファイル内容を標準出力します。ポイントは、ファイルオープン時に指定するFileShareのReadWrite、Deleteです。

```powershell:no_locked_read.ps1
$inpath = 'D:\tmp\dummy.txt'
$sr = [System.IO.StreamReader]::new(
    [System.IO.FileStream]::new(
        $inpath,
        [System.IO.FileMode]::Open,
        [System.IO.FileAccess]::Read,
        # 他プログラムの読み書き、削除をロックしない
        [System.IO.FileShare]::ReadWrite + [System.IO.FileShare]::Delete))
echo $sr.ReadToEnd()
$sr.Close()
```

ファイルオープン部分は、次のように書くこともできますね。

```powershell
$fs = [System.IO.File]::Open(
    $inpath,
    [System.IO.FileMode]::Open,
    [System.IO.FileAccess]::Read,
    [System.IO.FileShare]::ReadWrite + [System.IO.FileShare]::Delete)
$sr = [System.IO.StreamReader]::new($fs)
```

テキスト読み込み部分は、次のようにして、1行ごとに処理することもできますね。

```powershell
while (($line = $sr.ReadLine()) -ne $null) {
    echo $line
}
```

# ワンライナー

Windowsのコマンドプロンプトから、ワンライナーで実行する場合は、次のように書けました。

```bat:
powershell -Command "$sr = [System.IO.StreamReader]::new([System.IO.FileStream]::new('D:\tmp\dummy.txt', [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite + [System.IO.FileShare]::Delete)); echo $sr.ReadToEnd(); $sr.Close()"
```

# 動作確認方法

上述のファイル読み込み中に、ロックがかかっていないことを動作確認するときは、読み込み処理の途中で、`Start-Sleep 10`（10秒のスリープ）などを入れると便利です。当プログラムを実行して、スリープ中に、他のプログラムから読み書き、削除ができることを確認できるはずです。なお、他のプログラムがファイル削除した場合、削除処理成功しますが、ファイルはまだ残っていて、当プログラムがファイルクローズ後に、ファイルが削除されました。

# 動作確認環境

- Windows10
- Powershell 5.1

# 参考

- [PowerShell: ◆参照モードでのテキストファイルの読み込み](http://mtgpowershell.blogspot.com/2011/05/blog-post_27.html)
- [FileStream Class (System.IO) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.io.filestream)
- [FileMode Enum (System.IO) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.io.filemode)
- [FileAccess Enum (System.IO) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.io.fileaccess)
- [FileShare Enum (System.IO) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.io.fileshare)
hostsを変更するためのコマンド

2018/12/15 : 使用中のhostsパターンを確認できるようなコードを追記
# 作った理由
Macでhostsを変更するたびに、vimで変更させるのだるい...って思ったので、コマンド作りました。

# GitHub
https://github.com/prune2525/change_hosts

# コード
```
var=$1

#check
if [ -z $var ]; then
  exit
else
  case "$var" in
    #your host key
    "xxx" ) : ;;
    "chk" )
	if [ -d $HOME/hosts/.chk/ ]; then
		basename $HOME/hosts/.chk/*
		exit
	else
		:
	fi
	;;
    * ) exit ;;
  esac
fi

mm=`date +'%Y%m%d'`

cd $HOME
if [ -d "hosts" ]; then
  :
else
  #Initial activation
  #mkdir
  mkdir hosts
  cd hosts
  mkdir backup .chk "your directory"
  find . -name "hosts*" -type d -exec cp /etc/hosts {} \;
  echo "hosts update..."
  exit
fi

#backup
cp -f /etc/hosts $HOME/hosts/backup/hosts_bk_$mm

#check
if [ -d $HOME/hosts/.chk/ ]; then
 rm $HOME/hosts/.chk/*
fi
touch $HOME/hosts/.chk/$var

#main system
#change_hosts
case "$var" in
  "xxx" ) cp $HOME/hosts/"your directory"/"xxx" $HOME/hosts/"xxx"/hosts && sudo cp -f $HOME/hosts/"your directory"/hosts /etc/hosts && rm $HOME/hosts/"your directory"/hosts ;;
  #Add as you like
esac

exit
```

#処理の流れと使い方
コマンドの使用方法

```
change_hosts {key}
```

keyとは切り替えるための文字列になります。
下記の箇所でkey(```$var```)を実行時にチェックしています。
正しくない場合は、処理を終了させています。
```chk```が入力された場合は、ディレクトリの存在チェックを行い、.chkにあるファイル名を表示させる。

```
#check
if [ -z $var ]; then
  exit
else
  case "$var" in
    #your host key
    "xxx" ) : ;;
    #hosts check!
    "chk" )
	if [ -d $HOME/hosts/.chk/ ]; then
		basename $HOME/hosts/.chk/*
		exit
	else
		:
	fi
	;;
    * ) exit ;;
  esac
fi
```
該当のkeyの場合は、下記の通り処理をします。
ここでは、```$HOME```直下に```hosts```ディレクトリが存在するかチェックします。
このコマンドを最初に実行した場合は、```else```の処理に入り、```hosts```ディレクトリ及びディレクトリに現在のhostsをコピーし、処理は終了します。
※ディレクトリ生成・コピー後に処理を中断させる理由としては、hostsは人によって設定するものが違うため、各々で修正することをかねてです。（不親切かもしれませんが...）

```
cd $HOME
if [ -d "hosts" ]; then
  :
else
  #Initial activation
  #mkdir
  mkdir hosts
  cd hosts
　　　　#ここは任意のディレクトリを追加指定ください。
  mkdir backup .chk "your directory"
  find . -name "hosts*" -type d -exec cp /etc/hosts {} \;
  echo "hosts update..."
  exit
fi
```

上記で、ディレクトリ生成・hostsのコピー・修正などが完了した後、実行すると下記が実行されます。
実行内容は、```backup```ディレクトリにbackupされます。
$varに一致した内容のhostsを```/etc/hosts```に上書きを行います。
```.chk```ディレクトリはchkeck用のファイルを格納します。
下記の、#checkはディレクトリ存在チェックを行った後、.chkの中を削除します。
削除が完了したら、この時の引数で```touch $HOME/hosts/.chk/$var```します。
```touch```でできたファイルが、現在のhostsを確認するためのファイルになります。

```
#backup
cp -f /etc/hosts $HOME/hosts/backup/hosts_bk_$mm

#check
if [ -d $HOME/hosts/.chk/ ]; then
 rm $HOME/hosts/.chk/*
fi
touch $HOME/hosts/.chk/$var

#main system
#change_hosts
case "$var" in
  "xxx" ) cp $HOME/hosts/"your directory"/"xxx" $HOME/hosts/"xxx"/hosts && sudo cp -f $HOME/hosts/"your directory"/hosts /etc/hosts && rm $HOME/hosts/"your directory"/hosts ;;
  #Add as you like
esac

exit
```

# 最後に
GitHubで提供はしていますが、hostsは人によって違うものなので同じhostsは組織とかでなければ存在しないかと思っています。（いじらない人にとっては一緒ですが）
なので、このコードは基本的にはいじらないと機能しませんので、お手数ですが使用したい方は修正して使用してあげてください。

# 引用
[Macで自作コマンドを使う方法](https://qiita.com/HiDARi/items/a1fca8ab45bdd762ae52)
Node-redに出てくるmsg._eventってなんだ？

#いきなり本題です

Node-redでデバッグしてたらmsg._eventに`"node:96d64a7f.51b938"`的な値が入っていました。
これどこから来たんだろうと追っていたら、Link inノードの直後から発生してました。
勝手に入ってくる値のようです。

どこで使うのか、なんの為に使うのかわからん（かつ、このIDを調べても特に検索で引っかからないっぽい）ので、一旦スルーしてみます。

何か気付いたら追記します。
Wiresharkの基本的な使い方

Wiresharkのバージョンは3.2.1を使用しています。
バージョンによってはUIが変わっているかもしれません。
#起動画面
![スクリーンショット (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274361/66a97e7b-072d-fff2-4b60-59c22aa05e78.png)
####ファイルを開く
上のファイルアイコンをクリック、もしくはファイル ⇒ Openを選択。
ファイル ⇒ Open Recentで一度開いたことのあるファイルを選択できる。
####キャプチャを開始する
wiresharkのアイコンをクリック、もしくはキャプチャ ⇒ 開始を選択。
####キャプチャを止める
wiresharkのアイコンの横のアイコンをクリック、もしくはキャプチャ ⇒ 停止を選択。
####キャプチャのオプション
左から４番目のアイコンをクリック、もしくはキャプチャ ⇒ オプションを選択。
####キャプチャを取得しながらファイルに保存する
左から４番目のアイコンをクリック、もしくはキャプチャ ⇒ オプションを選択し、出力を選択。
分割して保存する場合、…後に自動的に新ファイルを作成 を選択。
リングバッファは保存ファイルが指定したファイル数に到達したら古いファイルから上書き保存する機能。保存キャプチャサイズが大きすぎてHD容量を圧迫する場合に使用する。
#メイン画面
![スクリーンショット (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274361/b656c564-9080-5cc1-bbe2-8e32cb99d6a0.png)
###ペインの種類
####パケットの一覧
![スクリーンショット (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274361/a89f0598-5490-5249-dd69-0947f7290673.png)
キャプチャしたパケットの一覧が表示される。
####パケットの詳細
<img width="885" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274361/b4d8eec2-0239-7a58-ed41-6886c547f969.png">
それぞれのパケットの詳細が表示される。
####パケットのバイト表記
<img width="960" alt="キャプチャ1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274361/1cac5b4e-2ca2-e6bf-5fa5-5d974e40e0e9.png">
パケットを16進数で表示している。
###時刻の表示形式の変更
表示 ⇒ 時刻表示形式で変更できる。
![スクリーンショット (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274361/5d07c126-aaf0-2245-2b13-25e76bacc204.png)
###時間の調整
編集 ⇒ 時間調整で調整できる。
![スクリーンショット (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274361/1cbc8889-0230-a554-57c1-e46fa4d44ba9.png)
#パケット検索
###BPF構文
例１：80番ポートで送受信されるTCPトラフィック
tcp port 80

例２：TCPのSYN-ACKパケット
tcp[13] == 18

例３：80番ポート以外で通信されるトラフィック
!port 80

例４：HTTPリクエストのメソッドがGET
http.request.method == "GET"

例５：送信元のIPアドレスが192.168.1.10
src host 192.168.1.10

詳しい内容は[こちら](http://www.runsurunet.com/2017/11/06/wireshark-%E8%A1%A8%E7%A4%BA%E3%83%95%E3%82%A3%E3%83%AB%E3%82%BF%E3%81%AE%E4%BE%BF%E5%88%A9%E3%81%AA%E4%BD%BF%E3%81%84%E6%96%B9/)を参考にすると良いです。
###フィルタの保存
1.キャプチャ ⇒ キャプチャフィルタを選択。
2.左下の「+」ボタンをクリック。
3.Filter name、Filter Expressionに名前と式を入力。
4.OKをクリックする。
#エンドポイントの一覧
統計 ⇒ Endpointsを選択
![スクリーンショット (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274361/7cd2c4e1-d15a-c351-c146-53dbd9b6e158.png)
#対話の一覧
統計 ⇒ Conversationsを選択
![スクリーンショット (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274361/21e7c667-cb7b-5323-a989-d005afce8b6f.png)
#プロトコルの統計
統計 ⇒ プロトコル階層を選択
![スクリーンショット (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274361/54e6c3a6-d231-85e2-4d3b-122445b1fa96.png)
#ストリームの表示
調べたいパケットを選択 ⇒ 右クリック ⇒ 追跡を選択
![スクリーンショット (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274361/9070ae7f-7ad9-57c1-4369-d802a6a9eeda.png)
#パケットキャプチャの練習になりそうなもの
[The Wireshark Wiki](https://wiki.wireshark.org/SampleCaptures)
[Malware-Traffic-Analysis](https://www.malware-traffic-analysis.net/)
VRはいいぞ！！！

はじめましての方のほうが多いですね！
情報通信システム工学科2年のmorihikoと申します。

![9oLORJRH_400x400.jpg](https://qiita-image-store.s3.amazonaws.com/0/319030/08f33a47-7e2a-1ec9-b9fc-08cc4ca811c6.jpeg)


何を書こうかな～～とずっと思っていたのですが、今回は学科上下間の繋がりということで、自己紹介も含めてVRについてご紹介させていただければと思います。
よろしくお願いします！

##自己紹介
そもそもなぜVRについて？と疑問に思う方のほうが多いと思いますが、実は「SushiVR」という寿司屋のVRゲームの開発をしております。
見ていただいたほうが早いと思うので、プレイ動画をご覧ください！


＜プレイ動画＞
https://youtu.be/e0yA_7l_FYI

はい、ご視聴ありがとうございます。

津田沼祭の展示で200人を超える多くの方々にプレイしていただいており、非常に感謝しております...！

このゲームをだいたい5人のチームで開発しています。

普段VRゲームを開発している関係上、もっとVRやMRが世の中に広まる未来が来ないかなと待ち遠しく思っています。
というわけで今回はVRのHMDについて紹介したいと思います！(どういうわけだ)

##VR機器について

VRも割と一般的になってきたこともありVR自体を紹介する必要はないと思うので、自分が使っているOculus社のHMDを紹介しようと思います。


自分が使っているのはOculus Riftです。

他社製HMDよりも
・価格が安い
・トラッキングするスペースが狭くて済む
・比較的軽い

ところにメリットがあるんじゃないかなと思います。

OculusにはOculus Homeというプラットフォームがあり、そこでゲームを購入したりプレイすることができます。
ちなみによく聞かれるのですが、Steamで販売されているゲームもSteamVRを経由することによりRiftでもプレイすることができます。


2018年12月現在ではOculus Riftは5万円で買うことができ、発売された当初よりは段々安くなってきています。

Oculus RiftはPCに接続して使うものなので、ある程度のPCのスペックが必要です。
グラフィックボードはNVIDIA Geforce GTX1060相当のスペックであれば十分に動くので、最近のデスクトップPCならだいたい動くんじゃないかなと思ってます。(ちなみに自分は先日GTX970からRTX2080に乗り換えました)

しかし、PCに繋がないとプレイできないのは割と面倒ですよね。
そこで、現在はPCなしのスタンドアロンで動作するHMDを開発しています。

##スタンドアロン型HMDとは！？

先ほど紹介したOculus RiftはPCに接続して使用する機器のため、PCがないとプレイできません。
しかし、9月にスタンドアロン型VRとして「Oculus Go」が発売されました。

もちろん自分も買ったのですが、持ち運んで外で使うことができるので大学等でVRを布教するのにすごくいいんです！！

しかし、Oculus Goは3DoFのトラッキングしかできないため、両手を使って動き回ったりなどのVRゲームで遊ぶというよりはYouTubeを見たりなどのVRコンテンツを見たりというような用途がメインだと思います。
もちろん簡単な片手でプレイできるようなゲームであればたくさんあります。


##もちろん後継機種が...
というわけで、後継機種として先日11月に「Oculus Quest」が発表されました。2019年の春に発売されるようです。
これは外側に付いている4個のカメラにより6DoFのトラッキングができ コントローラーも両手なので、Oculus Riftと同じVR体験がスタンドアロンですることができます。
値段も$399となっており、より一般の方々が気軽にVRを触れられるようになってきているなぁと思います。
持ち運ぶことによってより布教しやすくなりますね！！


皆様もVRデビューしてみてはいかがでしょうか！！！


##おわりに

VRの紹介なのにあまりVR自体の魅力について書けませんでしたが、やはりこれはプレイしてもらうのが一番早いんじゃないかなと思います。

今回は得に準備もなく深夜に書いているので、所々記述や主張がおかしいところがあるかもしれません。。
次回参加時はもっとしっかり書けるように準備しておこうと思いますので。。

このような機会をご用意していただきありがとうございました！
コントロールパネル等(*.cpl)

Windows10 Pro x64 ja-JP 1809
%windir%\System32\

|   ファイル名   |対象|
|:--------------------------------------------------|:-------|
|appwiz.cpl|コントロールパネル\すべてのコントロール パネル項目\プログラムと機能|
|bthprops.cpl|設定 : Bluetooth とその他のデバイス|
|desk.cpl|設定 : ディスプレイ|
|Firewall.cpl|コントロールパネル\すべてのコントロール パネル項目\Windows Defender ファイアウォール|
|hdwwiz.cpl|デバイスマネージャー|
|igfxCPL.cpl|インテル(R) HD グフラフィックス・コントロール・パネル|
|inetcpl.cpl|インターネットのプロパティ|
|intl.cpl|地域|
|irprops.cpl|赤外線|
|joy.cpl|ゲーム コントローラー|
|main.cpl|マウスのプロパティ|
|mmsys.cpl|サウンド|
|ncpa.cpl|コントロールパネル\すべてのコントロール パネル項目\ネットワーク接続|
|powercfg.cpl|コントロールパネル\すべてのコントロール パネル項目\電源オプション|
|RTSnMg64.cpl|Realtek HD オーディオマネージャ|
|sysdm.cpl|システムのプロパティ|
|TabletPC.cpl|ペンとタッチ|
|telephon.cpl|電話とモデム|
|timedate.cpl|日付と時刻|
|wscui.cpl|コントロールパネル\すべてのコントロール パネル項目\セキュリティとメンテナンス|
AndroidStudioのエラーメッセージをコピーする小技

AndroidStudioでプログラムを書いていると、ソースにエラーが表示され、赤線が引かれることがあります。
赤線にマウスカーソルを合わせると吹き出しにエラー内容が表示されますが、そのエラー内容のコピーを吹き出しから取ろうとすると、少しずれるだけで吹き出しが消えてしまい、とても面倒です。
しかもGradleファイルになると、吹き出しからコピーすることもできません。
![err1.png](https://qiita-image-store.s3.amazonaws.com/0/252283/fd6dcdfe-4db3-6815-352e-354b000a1af6.png)

そこで、赤線をクリックすると一番下にエラーメッセージが表示され、そこを右クリックすると、「コピー」というメッセージが出るので、そこでコピーできます。

![err2.png](https://qiita-image-store.s3.amazonaws.com/0/252283/aca7ff74-8057-a7b5-5594-00c021787518.png)

意外とわかりづらい、エラーをググりたいときの小技。
Unreal Engine 4.19 を使ったスマホ向けARアプリの開発でつまづいたポイント

> [Unreal Engine 4.19 を使ったスマホ向けARアプリの開発でつまづいたポイント | Orime](https://blog.umeru.ma/post/traps-i-stuck-in-developing-an-ar-application-for-smartphones-using-unreal-engine-4-19/)

自分のブログ記事への流入が少なそうなので、内容を短くしたものをこちらに投稿。
詳細を読みたい方は上のリンクからどうぞ。

## つまづき： AR機能を利用しないレベルのカメラが、意図しない位置に移動してしまう
対象プラットフォーム： iOS & Android

AR機能を利用するレベルAと、そうでないレベルB間を遷移するアプリを制作していて、Bに配置しているカメラが想定外の位置へ移動してしまった。

### 対処： AR機能を利用しないレベル上のカメラの設定を変更

カメラコンポーネントの ”Lock to HMD” を `False` に変更する。

AR Start関数が呼ばれ、ARトラッキングがアプリ内で開始された後は、”Lock to HMD”が`True`になってるカメラはぜんぶトラッキング情報の位置・角度に固定される仕様になっている。

## つまづき： ARKit関連のコードを理由にAppStore審査でリジェクトされる
対象プラットフォーム： iOS

（Unreal Engine 4.20以降では解決されているはず。）

空間にオブジェクトを配置するだけのような、ARKitのフェイストラッキング機能を使わないアプリの場合、Epic Games Launcherから落とせる、Unreal Engine 4.19.2を使ってアプリをビルドするとストア審査で止められる。

「TrueDepth APIを利用しないアプリのはずなのにAPIにアクセスしているので、修正してね」（意訳）といったメッセージを受け取るはず。

### 対処： ARKitプラグイン周りをカスタムしたエンジンでビルドしなおす

Unreal Engine自体のソースコードから、TrueDepth API関連のコードを消す必要あり。アプリをビルドしなおせば審査通る。

UE4 ANSWERHUBのこのスレッドに、修正したコードをアップしてくれているユーザーがいるのでチェックしてみてください。

> [ARKit app rejected because of TrueDepth APIs usage - UE4 AnswerHub](https://answers.unrealengine.com/questions/778388/arkit-app-rejected-because-of-truedepth-apis-usage.html)

（一番上で引用した元のブログ記事に、修正した4.19.2バージョンのGitHubリポジトリへのリンクあるので、カスタム済みソースが欲しい方はそちらを参照ください）
The method 'updateProfile' isn't defined for the class '#lib1::FirebaseAuth'.


# 解決策
FirebaseUserクラスのupdateProfileメソッドを利用する


# 背景
本日、firebase_authを0.6.6にしたら、以下のようなエラーメッセージが出ました。

```
Error: The method 'updateProfile' isn't defined for the class '#lib1::FirebaseAuth'.
Try correcting the name to the name of an existing method, or defining a method named 'updateProfile'.
      await FirebaseAuth.instance.updateProfile(userUpdateInfo);
```

エラーメッセージで調べても、それっぽい記事が見つからなかったので、
投稿しました。
(少しでもエラー解決するの面倒くさい勢のお役に立てれば幸いです。）

# 所感？
いつから変わったんだろう...

ちょっと調べてみましたが、わかりませんでした。

by [高木徹](https://twitter.com/TTrpbm)
scriptをより便利に使うためコマンド

# 作った理由
普段、scriptを使用して、作業ログをとるとき、いちいちフォルダを指定したり、
ファイル名を指定するのって面倒だな〜...よし作るかという感じで作ってます
# GitHub
https://github.com/prune2525/log_script/blob/master/log_script
#　コード
```
# 日付取得
mm=`date +'%Y%m%d'`
cd $HOME/
if [ -d $mm ]; then
  :
else
　　　　# 日付ディレクトリ作成
  mkdir $mm
fi
cd $mm
# 日時取得
dt=`date +'%Y%m%d%H%M%S'`
# ファイル名作成
file_name="scriptlog_$dt.log"
# 実行部
script ./$file_name
```
OCSP Staplingの調査

# OCSP Staplingの概要
## OCSPとは？
* Online Certificate Status Protocol
* オンラインで証明書の状態を検証するプロトコル
* [RFC2560](https://www.ipa.go.jp/security/rfc/RFC2560JA.html)
* 応答する証明書の状態は有効(good)、失効(revoke)、不明（unknown)の3通り。それに加えて、OCSP応答状態（無応答）も考慮する必要がある。

## OCSP応答の例
* openssl s_clientコマンドで以下のように確認できる。
 
```
> openssl s_client -connect www.office.com:https -CApath /etc/ssl/certs -status

CONNECTED(00000005)
OCSP response: 
======================================
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response
    Version: 1 (0x0)
    Responder Id: 546D834E713BB4ED0E57829451B0BED494F9E833
    Produced At: Nov  9 04:03:09 2018 GMT
    Responses:
    Certificate ID:
      Hash Algorithm: sha1
      Issuer Name Hash: 2985FC613DBE2FB0120F5E420E4C9EC3D59EFD7C
      Issuer Key Hash: 08FE259F74EA8704C2BCBB8EA8385F33C6D16C65
      Serial Number: 2D000084B7E83E2BB6EC8EA1920000000084B7
    Cert Status: good
    This Update: Nov  9 04:03:09 2018 GMT
    Next Update: Nov 13 04:03:09 2018 GMT
        Response Single Extensions:
            OCSP Archive Cutoff: 
                Nov  9 04:03:09 2017 GMT

```  

  * この例では、サーバ証明書の状態は：good
  * 直近の状態確認は2017/11/9 04:03:09 GMTに実施。次の更新は11/13予定。

## OCSPアクセス情報をもつサーバ証明書の例
* OCSPアクセスを要求するかどうかはTLSサーバ次第。（サーバ証明書次第）
* chromeなどのブラウザでアクセスし、URLバーにある証明書アイコンをクリックするとOCSPへのアクセス先が確認できる。以下の図では、拡張領域、認証局情報アクセスというのが確認できる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/282300/0b333194-7f5b-a3ee-c685-2d1baf594348.png)

　  * 上記例では、方法１としてCA発行者の証明書へのURI（この例では中間CAの証明書）、方法２としてオンライン証明書状況プロトコルによるURIが提示されている。
　  
## OCSPの問題点
* HTTPSクライアントとCAとの間にOCSPリクエスト・レスポンスの通信が発生する。
 * 通信負荷の増加
 * 通信のための穴が必要 
 * 通信できない場合、失効確認ができない。
* HTTPSクライアントのアクセス履歴がCAに漏れる。


## OCSP Staplingとは？
* Staple(ホッチキスでとめる）：SSLハンドシェイク中にサーバ応答に添付するという意味。添付される情報は、CAがこのサーバ証明書の失効状態を確認してますよ、という証明。
* 上記の意味からわかるように、失効状態の取得・更新は、WebサーバとCAとの間で行われ、クライアント（ブラウザ）は、SSLハンドシェイク中にサーバから応答された証明書の有効状態を検証・判断するだけで、Webサーバ以外に問い合わせはしない。
* 上記で述べたOCSPの問題点２つがクリアされる。

### TLS拡張ハンドシェイク
* [TLS拡張：RFC6066](https://www.ipa.go.jp/security/rfc/RFC6066JA.html)
* TLSクライアントは、ClientHelloにCertificateStatusRequestを含める。下の図はTLSサーバ側でキャプチャしものでClient Helloに拡張status_requestとして、OCSP Status Requestが乗っているのが確認できる。

![スクリーンショット 2018-11-23 20.45.26.png](https://qiita-image-store.s3.amazonaws.com/0/282300/23812b3a-68fe-40fa-ae0e-bb6d30458b76.png)

* TLSサーバは、TLSクライアントのOCSP Status Requestに対して、Server HelloにCertificate Statusを応答、その中にOCSP応答を含む。

![スクリーンショット 2018-11-23 20.56.49.png](https://qiita-image-store.s3.amazonaws.com/0/282300/6f98fda5-e840-6549-03d8-07f46d87f72a.png)

# まとめ
* OCSPはTLSハンドシェイクの過程で、サーバ認証を行う際に、そのサーバ証明書（または中間証明書）が有効かどうかを判定するプロトコル。
* OCSPでは、TLSクライアントが、そのサーバ証明書の発行母体に対して、OCSPで問い合わせするが、通信負荷の問題、プライバシーの問題がある。
* OCSP Staplingは、OCSP要求をTLSサーバが適切なタイミングで行い、OCSP応答をキャッシュ、TLSハンドシェイク時に、TLSクライアントから要求(ocsp status request)があれば、Certificate StatusとしてOCSP応答データを応答する。
* TLSクライアントが、ocsp status requestを要求するかどうかは、サーバ証明書の拡張領域に認証局情報アクセスが登録されているかどうかよる。
* 証明書の拡張領域に認証局情報アクセスを付与するのは、その証明書を発行するCA。アクセス先、証明書の状態（有効、無効、不明）管理も、発行CAの役割となる。
Blazor(ASP.NET Core hosted)とBlazor(Server-side in ASP.NET Core)とBlazorの違い

Blazorのセットアップ等は@Nossaさんの記事
[WebAssembly でシングルページアプリケーションが開発できる Blazor フレームワークの公式チュートリアルをやったら近未来感が凄かった](https://qiita.com/Nossa/items/f0e2fc1c91d8cb95ead4)に記載されているのでそちらをご覧いただくとして、ここではプロジェクト作成中のダイアログに表示される3種類のBlazorの違いです。

![NewBlazor.png](https://qiita-image-store.s3.amazonaws.com/0/157704/06ea0e18-90f6-ccf9-e286-ab6487b3e420.png)

1. Blazor
  * ダウンロードしてきたネイティブコードをブラウザー上で動かします。
  * サーバーサイドには動的なコンテンツを置きません。
  * Fetch dataのサンプルも、サーバー上に置かれた静的なJSONファイルをHttpClientで読み込みます。
2. Blazor(ASP.NET Core hosted)
  * ダウンロードしてきたネイティブコードをブラウザー上で動かします。
  * サーバーはASP.NETのAPIサーバーです。
  * Fetch dataのサンプルは、HttpClientでAPIサーバーからJSONを読み込みます。
3. Blazor(Server-side in ASP.NET Core)
  * Blazorは（ネイティブコードは）ダウンロードされず、サーバー上で実行します。
  * そのため、WebAssemblyに対応しないブラウザーでも実行可能です。
  * オフライン実行には向きません。
  * サーバーとの通信はSignalRが使用されます。

SignalRの説明はこちら。[ASP.NET SignalRを知る(@IT)](http://www.atmarkit.co.jp/ait/articles/1303/19/news099.html)
iOS Safariのアクションバー表示エリアが、タップイベントをブロックするのでCSSで対処する

![タップエリアのDEAD ZONE](https://qiita-image-store.s3.amazonaws.com/0/9289/6683ec1f-78c6-51cd-b173-fdfe3f967d3e.png)

> [iOS Safariのアクションバー表示エリアはタップイベントをブロックする | Orime](https://blog.umeru.ma/post/ios-safaris-action-bar-area-block-tap-event/)

自分のブログ記事への流入が少なそうなので、内容を短くしたものをこちらに投稿。
長い文章を読みたい方は上のリンクからどうぞ。

## TL;DR
- iOS Safariは、アクションバーが隠れた時、バーの高さ+セーフエリア分のタップイベントをブロックしてしまう。
- それゆえ、ウィンドウ下固定のボタン要素は、1回でタップできない場合がある。
- CSSで解決する場合、`44px + env(safe-area-inset-bottom)`分のマージンを取る。

## 問題
Webページで下固定のメニュ—要素を採用した場合、iOS Safariからブラウジングしていて、スクロールしてアクションバーが隠れた状態だと1回でタップできない。

ストレスになりうるので対処する。

## CSSで対処する例

ポイントは metaタグのviewportに追加する`viewport-fit=cover` 。この記述があると、CSS変数の `safe-area-inset-*` にセーフエリアのサイズが返ってくるようになる。

```index.html
<meta name='viewport' content='initial-scale=1, viewport-fit=cover'>
```

```style.css
.bottom-button-bar {
  position: fixed;
  left: 0;
  bottom: 44px;
  /* calc、env関数が使えない環境用にフォールバック */
  bottom: calc(env(safe-area-inset-bottom) + 44px);
  /* タップできないエリア分要素を上げる 
     あくまで一例。paddingやmarginなど利用することもできますね。 */
}
```
## 自分のブログで指定した結果

![MobileSafari_DeadZone_03.png](https://qiita-image-store.s3.amazonaws.com/0/9289/ed352044-0f9a-068f-b3dd-7b7756ce0dfd.png)
浮いてるボタンだといいけど、バータイプのメニュー要素だと見た目が微妙になるかもしれないですね。
Now を Ver1 から 2 へ移行してみた

Zeit の Now が Ver2 を発表して、Paas から Faas 的なのに変わりました。
[Now 2.0](https://zeit.co/blog/now-2)
React のアプリを Ver1 で使用していたものを Ver2 へ移行してみました。

## 要約

React アプリを Ver2 にするには、

- `package.json`の`script`に`now-build`を追加
- `now.json`に `"version":2`、`"builds": [{ "src": "package.json", "use": "@now/static-build" }]`を追加

することで `now`コマンドで build ができます。

※ build したファイルは`/dist`フォルダに出力されるようにしないとダメ

## Ver1 の設定

 以前は、static に利用するために、

```bash
yarn build
```

してから、

```bash
now public/ -n XXX
```

※ XXX はアプリ名

して

```bash
now alias
```

を行って公開してました。

## Ver2 にするにあたって

### 設定

- `public/`配下に build したファイルを出力していたのを`dist/`配下に出力するように変更
- `pacakage.json`の`script`に `now-build`を追加

```json
  "scripts": {
    "build": "webpack -p --mode production",
    "start": "webpack-dev-server --hot --inline --devtool source-map --mode development",
    "now-build": "webpack -p --mode production"
  },
```

- `now.json`に `version`、`build`を追加

```json
{
  "version": 2,
  "name": "XXX",
  "alias": "XXX.now.sh",
  "builds": [{ "src": "package.json", "use": "@now/static-build" }]
}
```

###  実行

上記の設定をしたら、以下のコマンドで公開できます

```bash
now
```

```bash
now alias
```

## 参考情報

- [Upgrade to 2.0](https://zeit.co/docs/v2/platform/upgrade-to-2-0)
- [Ver2 の example](https://zeit.co/examples/)
- [https://github.com/zeit/now-examples](https://github.com/zeit/now-examples)
ScalaでList[LocalDateTime]をソートする

### LocalDateTimeリストのsortedでエラーが出た

LocalDateTimeのリストをsortedでソートしようとしたら以下のようなエラーが出た

```scala
List(time3, time1, time2)
> List[java.time.LocalDateTime] = List(2018-11-23T19:18:28.758, 2018-11-23T19:18:22.479, 2018-11-23T19:18:25.296)

List(time3, time1, time2).sorted // time*はLocalDateTime
> error: No implicit Ordering defined for java.time.LocalDateTime.
       List(time1, time2, time3).sorted
```

ガッデム。
REPLでとりあえずsortedの定義を出す

```scala
def sorted[B >: java.time.LocalDateTime](implicit ord: scala.math.Ordering[B]): List[java.time.LocalDateTime]
```

Ordering型クラスのLocalDateTimeインスタンスを定義すれば良さそうだ
実装が必要なメソッドはcompare

```scala
 /** Returns an integer whose sign communicates how x compares to y.
   *
   * The result sign has the following meaning:
   *
   *  - negative if x < y
   *  - positive if x > y
   *  - zero otherwise (if x == y)
   */
  def compare(x: T, y: T): Int
```

compareを正しく動作させるためには
※第一引数xが第二引数y

xがyより小さい時、負の数を返す
xがyより大きい時、正の数を返す
xとyが同じ時、0を返す

このように実装すれば良いらしい


### インスタンスを定義
compareToはLocalDateTimeのメソッドで、都合の良いことにxがyより小さい時-1、xがyより大きい時1、同じ時0を返してくれるのでそれをそのまま利用する

```scala
implicit val localDateTimeOrdering = new Ordering[LocalDateTime] {
  def compare(x: LocalDateTime, y: LocalDateTime): Int = {
    x.compareTo(y)
  }
}
```

このインスタンスをsortedを利用するスコープ内で読み込めば最初エラーになっていた処理がちゃんとソートされるようになる

```scala
List(time3, time1, time2).sorted
> List[java.time.LocalDateTime] = List(2018-11-23T19:18:22.479, 2018-11-23T19:18:25.296, 2018-11-23T19:18:28.758)
```


### おまけ
Orderingのcompareを正しく動作させるには負の数、正の数を返すとあったが-100, 50, 0を返すような場合でも正しく動作するのかやってみた

```scala
case class Player(number: Int, name: String)
val player1 = Player(13, "Alisson")
val player2 = Player(4, "Virgil van Dijk")
val player3 = Player(14, "Henderson")
val player4 = Player(11, "Salah")

val players = List(player1, player2, player3, player4)
// ソートはnumber順
players.sorted // この時点ではエラー error: No implicit Ordering defined for Player. players.sorted

// Playerインスタンスの定義
implicit val playerOrdering = new Ordering[Player] {
  def compare(p1: Player, p2: Player): Int = {
    if (p1.number < p2.number) -100 // -1ではなく-100
    else if (p1.number > p2.number) 50 // 1ではなく50
    else 0
  }
}

players.sorted
> List[Player] = List(Player(4,Virgil van Dijk), Player(11,Salah), Player(13,Alisson), Player(14,Henderson))
```

このように-100, 50, 0を返すような実装でも動作する(気持ち悪いが)
※LocalDateTimeのcompareToメソッドのように-1, 1, 0を返すのが作法ぽい


### 参照
[型クラスをOrderingを用いて説明してみる](http://kmizu.hatenablog.com/entry/2017/05/22/224622)
[Angular] ルーティングモジュールのオシゴト

# 前フリ

ルーティングモジュールを作ってはいるけれど、中身は空っぽ。

```ts:app-routing.module.ts
@NgModule({
  imports: [RouterModule.forRoot(ルーティング設定した配列)],
  exports: [RouterModule]
})
export class AppRoutingModule {}
```

# 疑問

空っぽのルーティングモジュールいるんかなぁと思っていました。
もしかしたら、なんかいろいろ楽しい機能追加できるん？

# 回答

とか考えていたら、答えが書いてありました。

[Do you need a routing module](https://angular.io/guide/router#do-you-need-a-routing-module)

曰く

> The Routing Module replaces the routing configuration in the root or feature module. Either configure routes in the Routing Module or within the module itself but not in both.
> 
> The Routing Module is a design choice whose value is most obvious when the configuration is complex and includes specialized guard and resolver services. It can seem like overkill when the actual configuration is dead simple.

ルーティングモジュールは、ルートモジュールや機能モジュール内のルーティング設定を置き換えます。ルーティング設定はどちらか一方に書けばよいです。両方はいりません。

ルーティング設定が複雑かつ特別なガードやサービスリゾルバを含む場合は、設計的にルーティングモジュールを作成することも選択肢です。ルーティング設定がめちゃくちゃ簡単であればオーバーキル[^1]かもしれません。

[^1]: （筆者のどうでもいい感想）ゲームとか戦闘モノ以外の文脈で「オーバーキル」って初めて見たかも。

> Some developers skip the Routing Module (for example, AppRoutingModule) when the configuration is simple and merge the routing configuration directly into the companion module (for example, AppModule).

開発者によっては、設定が単純であればルーティングモジュール（例えば、`AppRoutingModule`）は作成せず、その随伴モジュール（例えば、`AppModule`）に直接設定を書くかもしれません。

> Choose one pattern or the other and follow that pattern consistently.
> 
> Most developers should always implement a Routing Module for the sake of consistency. It keeps the code clean when configuration becomes complex. It makes testing the feature module easier. Its existence calls attention to the fact that a module is routed. It is where developers expect to find and expand routing configuration.


どちらかのパターンを選択し、一貫してそれに従いましょう。

ほとんどの開発者は、一貫性のためにルーティングモジュールを作成します。ルーティング設定が複雑になってきたとき、コードをシンプルに保つことができるからです。また機能モジュールのテストが容易になります。ルーティングモジュールが存在することで、その(ルート|機能)モジュールにルーティングがあるという事実に注意を惹けます。ルーティング設定がどこにあってどこをいじればよいのか、開発者はの期待に沿うことにもなるでしょう。

# 結論

オーバーキルかもしれんけど、人に見せる機会があるモジュールならルーティングモジュール作っておいたほうがよい。

# さらなる疑問

実は、イベントハンドラ定義したりして、色々楽しいことできたりする？？？そんなことない？？
↑
しつこい
IEでJqueryのAjaxを使うと、「XMLHttpRequest: ネットワーク エラー 0x2f78, エラー 00002f78 のため操作を完了できませんでした。」

#### 問題
Chromeで問題なく動いている以下のコードが、IEでは動かない。

```JavaScript
condition = "&condition=" + $('#condition').val();
$.ajax({
  url: "/xxx",
  type: "get",
  contentType:"application/json; charset=UTF-8",
  data:condition
}).done(function (data, status, jqXHR) {
```

IEのデベロッパツールに表示されたエラー

```
XMLHttpRequest: ネットワーク エラー 0x2f78, エラー 00002f78 のため操作を完了できませんでした。
```

* `$('#condition').val()`が日本語の時にだけ発生
* 入力した`ああああ`がqueryパラメータでは`ã????ã????ã????ã????`となる

#### 解決方法
以下で直る。

```JavaScript
condition = "&condition=" + encodeURI($('#conditionText').val());
```

Chromeでは自動でURIエンコードするが、IEではしてくれない。

#### 参考
https://www.okushin.co.jp/kodanuki_note/2010/07/url.html

#### 所感
IEだとデフォルト引数も使えないし、いろいろとChromeと差異があってハマる。
[論文メモ] Item2Vec: Neural Item Embedding for Collaborative Filtering

[Item2Vec: Neural Item Embedding for Collaborative Filtering](https://arxiv.org/abs/1603.04259)

# 簡単にまとめると
- word2vecを単語ではなく商品の分散表現を求める手法を提案している。
- 文章から単語の分散表現を求めるときは、文章の前後の単語との組み合わせを使ったが、商品では文書のような時系列関係がない。
- そこで時系列関係等を無視して、**同時に購入された**商品の組み合わせを正例として用いる。
- アルゴリズムはword2vecとほぼ同じ。
ansible-containerで登場する概念的なやつの個人的メモ

# これは何？
ansible-containerの技術メモです。

ansible-container
https://github.com/ansible/ansible-container

## 概念
* conductorコンテナ
 * ansibleホストの役割含む
 * `container.yml`のベースイメージをもとにする
 * 対象となるコンテナはこのコンテナのファイルシステム内にマウントされる
* 対象となるコンテナ
 * python不要

## コマンド
* ansible-container init
 * 実行ディレクトリ名がPJ名になる
 * 下記が作られる
     * container.yml
            * 核となるymlで、基本的にこれを編集する
            * `docker-compose.yml`と似た役割
     * ansible.cfg
            * conductorでコマンドを実行する際の設定
     * requirements.yml
     * ansible-requirements.txt
            * この二つにはリポジトリから取得する必要のあるモジュールや、実際にansible-containerを実行する際に必要なモジュールを記載する
     * meta.yml
            * メタ情報を記載する。ansible galaxyで使われると思われる

* ansible-container build
    * container.ymlに基づいてビルド

* ansible-container run
    * container.ymlに基づいてコンテナを起動

* ansible-container stop
* ansible-container restart
* ansible-container destroy
* ansible-container deploy

## container.yml

* from : ベースとするコンテナイメージでconductorも作業対象コンテナもこれがベースとなる
* volume : マウントするボリュームの設定。`docker run -v`だと思う
* ports : 開放するポートの設定。`docker run -p`だと思う
* command : Dockerfileの`CMD`だと思う
* depends_on : 依存相手のコンテナを明示する
* roles : roleを適用。もちろん複数も可
* environment : Dockerfileの`ENV`だと思う
* expose : `docker run –expose`だと思う

## 参考にさせていただいたもの

* [docker上でansible-containerを実行する時の5つのポイント](https://qiita.com/uramotot/items/b95dd5908cd9e489c731)
左と右は対称的ではなかった！？ Haskellのfoldrでアハ体験

# 概要

foldlとfoldrについて、

- foldrなら無限リストを扱える
- 逆ポーランド記法ならfoldlとfoldrは入れ替わる？

というような話題に関して少し掘り下げた記事です。

# 注意

この記事を読むと、**左と右が本質的に対称的でない概念であるような錯覚を起こします。**子どもに左右の概念を教育しているママ/パパの方はご注意ください。

また、もともと[Qiitadon](https://qiitadon.com/)のトゥートだったので多少文体が変ですが、ご容赦ください。

# 左右の難しさとfoldrの"操作"と無限リスト

## 元トゥート（の一部）

> foldl/foldrと左右って難しくて、記法に対する単純な左右ということでもない。
> 
> foldlは、二変数関数fを第一引数に受け取って、fに第二引数と第三引数のリストの頭を適用した結果をさらにfに適用する。ので、仮にfoldlという関数を素朴に逆ポーランド記法で書くと、リストの表現の仕方にもよるけど、**多分左右が"逆"になる**。foldlというよりは、**foldhead**なんだよね。
> 
> ではfoldrはというと、**foldtail**で、単純なSumみたいなものは当然無限リストには適用できないんだけど、結果がリストになるような場合には、リストの先頭からi番目みたいなものの計算までは実は非正格であればうまく有限ステップで終わらせることができて、その意味で無限リストから無限リストを得るような場合にはうまく使える。

この話を、もう少し詳しくします。実際のHaskellのコード断片を眺めます。

## すりぬけの術

```haskell
foldr (+) 0 (1:2:3:[])
          == 1 +           foldr (+) 0 (2:3:[])
          == 1 + (2 +      foldr (+) 0 (3:[])
          == 1 + (2 + (3 + foldr (+) 0 []))
          == 1 + (2 + (3 + 0))
```

これ、foldr (+) 0という演算子がすり抜けていると思ってほしい。
foldr=Fとして、ちょっと違う書き方をすると、

```haskell
             F (+) 0 (1 : 2 : 3 : [])
          == 1 + F (+) 0 (2 : 3 : [])
          == 1 + (2 + F (+) 0 (3 : [])
          == 1 + (2 + (3 + F (+) 0 []))
          == 1 + (2 + (3 + 0))
```

もっとわざとらしく、F (+) 0 = Gと書いて、1:2:3も括弧を補って書くと、

```haskell
             G (1 : (2 : (3 : [])))
          == (1 + G (2 : (3 : [])))
          == (1 + (2 + G (3 : [])))
          == (1 + (2 + (3 + G [])))
          == (1 + (2 + (3 + 0)))
```

こういうことになって、foldrが右（末尾）方向にすり抜けているというような見方もできる。foldrがせき止めているのか、foldr自体が右に抜けているのか、まあ式の見方としてはどちらでも良いといえば良いんだけど…。

## 無限リストとfoldr

`[1..] == 1:2:3:[4..]`であることに注意する。

```haskell
foldr (+) 0 (1:2:3:[4..])
          == 1 +           foldr (+) 0 (2:3:[4..])
          == 1 + (2 +      foldr (+) 0 (3:[4..])
          == 1 + (2 + (3 + foldr (+) 0 [4..]))
```

これは、足し算だと無限に続いてしまうので計算は終わらない。のだけど、

```haskell
foldr (:) [] (1:2:3:[4..])
          == 1 :           foldr (:) [] (2:3:[4..])
          == 1 : (2 :      foldr (:) [] (3:[4..])
          == 1 : (2 : (3 : foldr (:) [] [4..]))
```

これは、..の部分を計算しなくても、先頭の要素とか二つ目の要素とかは確定するよね、ということ。
その意味でfoldrは無限リストを扱える、tailまで行かなくても！

実例を挙げてみる：

```haskell
a = foldr (:) [] (1:2:3:[4..])
main = putStrLn $ show (take 10 a)
-- [1,2,3,4,5,6,7,8,9,10]
```

こんなことは、**素朴な**foldlではできない。

これはとても興味深い話で、「関数」というものを素朴に捉えると、中学校の数学で習うような写像を想像してしまい、**foldrはリストの末尾から再帰的に計算をしなければならないようなイメージを持つ**（場合がある）。

しかし、それはfoldrの性質の一部であって、この例のように引数として与える関数によっては末尾まで計算を行わなくても必要な計算が終了する事がある。**foldlの素朴な実装は、実際にリストの先頭から正格的な評価をするにも関わらず。**

**ただの左右じゃん、と思ったら全然そんなことはない！**

そういう話でした。おしまい
tar.gzファイルの解凍

# はじめに
[Wikipedia方式で記載されているHP](http://www.momiage.com/wiki/index.php/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8)を自分でも作成したくなったので、
調べてみると「MediaWiki」にて作成できるらしい。

それで、MediaWikiの[ダウンロードページ](https://www.mediawiki.org/wiki/Download/ja)にいくと、ファイル形式は .tar.gz のようだ。

7.zipで解凍できる様子だが、ほかにも解凍手段あるだろうと思ったので調べた。
以下は解凍手段になります。

### 1.ツールの場合:7.zip
ダウンロードページでも推奨されている手段。[ここ](https://sevenzip.osdn.jp/)からダウンロードできる。

### 2.linuxの場合:コマンド tar -zxvf xxxx.tar.gz
```
tar -zxvf xxxx.tar.gz
```
というコマンドを使用すれば解凍が可能。xxxx.tar.gzは任意のtarファイル。
### 3.powershell:コマンド Expand-Archive
引数付きコマンドとしては以下

```
Expand-Archive -Path <圧縮ファイルパス> -DestinationPath <ファイル解凍先フォルダ>
```
->できないっぽい。
いや、windowsもtar対応しているらしい？[この記事](https://kledgeb.blogspot.com/2017/12/windows-14-windowscurltar.html)

#あとがき
昨日、Googleストアに展開されていないChrome拡張ツールをインストールする際に同じことではまったので、2日に二回はさすがに調べるべきと感じ、まとめた。
すなおに7.zip使ったほうがはやいか。。。
開発者でもなくデータアナリストでもなく企画職が使うべきSQL①

#はじめに
TableauなどのBIツールなどが普及していていて、いまやSQLなどかけなくても簡単にデータマートからデータ抽出して可視化して、というのがとても簡単になっています。
とはいえ、僕は企画職がSQLを触れることはとても大事だと思っています。
本記事は、企画職が使うべきSQLについて記載していきたいと思います。

#なぜこんな記事を書くのか。とりあえず思っていること
-普段仕事でデータ分析をしていて、企画者から「このデータ出して」という依頼をとても多くもらう
- 偏見もありますが、BIの普及があるもののまだまだ浸透はしていません。そのため、DWHがあっても用途別マートを用意している企業はまだまだ少ない印象
- マートはあれど、必ずしも全てのデータがマートに存在しているわけではない
- BIツールも安くていいものがどんどんできていて、ツールの切り替えが早く、都度キャッチアップが必要なため定着していない
- 結果として多くの企画者は、SQLを叩ける人にデータ抽出をしてもらい、抽出してもらったexcelやcsvで仕事をしていたりします(excel自体はとても便利です)
- 一方でデザイン思考などの考えから、MVP(検証可能な最低限のプロダクト)を量産するという考え方が広まっていることから、いちいちデータ抽出してもらうのを待っているわけにも行かず

などなどサラリーマンならではの悩みというか煩わしさというか、ありそうだなと思っているので、僕はデータ抽出をあまり拒まないようにしてます。苦笑

でも本当は**難しい関数はいいとして最低限のSQLは使えた方がいい**と思っています。何なら営業職だって使えた方がいいと思ってます。
服の採寸だって、エアコンの温度だって、体調管理だって、データとして保持されている世の中でデータを活用できることは武器になると思っているからです。

#SQLの書き方の前に、その前提を記載しておきます
※テーブル名はmy_infoと仮定します。10日分の以下データとします。
※カラム(要素) は毎晩夜に記録している１体重２身長３体脂肪４睡眠時間5摂取カロリー6宿泊エリアとします
※特に何でもいいですがpostgresqlとします

#ということで大基本select

###とりあえず全部抽出

テーブルから(from)から見たい項目を選ぶだけ(select)
全部の場合はアスタリスクで大丈夫。

```sql
select * from my_info;
```
###体重と身長だけ抽出

```sql
select weight,height from my_info;
```

###とりあえず３日分（=3行分=3レコード分）
みるレコード数のlimit(上限)を追記するだけ

```sql
select weight,height 
     from my_info
         limit 3;
```

###(このテーブルだと必要ないけど)レコード数を見てみる

```sql
select count(*) from my_info;
```

#条件をつけて絞る

###whereで条件をつける

```sql
select weight
       from my_info
            where weight >= 75;
```

###演算子の書き方

```sql
等しい:=
等しくない:<>
より大きい:>
未満:<
以上:>=
以下:<= 
aとbの間:between a and b
```

###複数条件
and,orでくっつけるだけ

```sql
select weight
       from my_info
            where weight >= 75　
               and kcal >= 3000;
```

###条件の否定

notをつけるだけ

```sql
select weight
       from my_info
            where not weight >= 75;
```

###条件を複数項目指定

in ()の中に合致するものはありませんかーとするだけ

```sql
select weight
       from my_info
            where sleeping_area in ('living','dining','bedroom');
```

###条件の文字列指定

文字が部分的にあってればOKという時は以下のようにします。

「%」の所には0文字以上の文字が入ります。
1文字以上にしたい時は「_」を使います。

```sql
select weight
       from my_info
            where sleeping_area = '%room';
```

#並び替え

csvかエクセル出力することがほとんどなので、sqlで並び替えも必要ないということも言われますすが、どうせやるならsqlからやってしまった方がいいといつも思ってます。

###体重の軽い順

order byに続く要素で、並び替え

```sql
select weight
       from my_info
            order by weight;
```

###体重の重い順

```sql
select weight
       from my_info
            order by weight　desc;
```

###身長も高い順で、さらに体重の重い順

```sql
select weight
       from my_info
            order by height desc, weight　desc;
```

#基本の基本はこれだけ
ここでの注意点は、where節はorder by節の前に書くという点です。
limitは全部の条件を書いた上で最後に記述を行います。

まとめると

```sql
select kcal
       from my_info 
            where sleeping_area = '%room'
                order by height desc, weight　desc
                      limit 3;
```

#終わり
テーブルちゃんと作ってから記事を書いた方がよかったなと反省。
集約関数を続きとして記載したいと思います。
自分用メモ: Typescriptの!と?とnullの使い分け

## !
ライブラリとかによって絶対に挿入されるパラメータにつける。
[リンク](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html)

### 所感
Vue.js2.5.16の$refsとかに重宝しそう。
サンプル

```typescript
@Component
export default class LoginPage extends Vue {
  public $refs!: {
    form: VForm,
  }
}
```

これで$refsに型がついた。

## ? 呼称: Optional Parameters
これは任意引数とかによく使う。
挿入されなかったらundefinedになる。
`lastName: string | null`と意味合いは全く違う

サンプル

```
function buildName(firstName: string, lastName?: string) {
    if (lastName)
        return firstName + " " + lastName;
    else
        return firstName;
}

let result1 = buildName("Bob");                  // works correctly now
let result2 = buildName("Bob", "Adams", "Sr.");  // error, too many parameters
let result3 = buildName("Bob", "Adams");         // ah, just right
```

## ?と | nullの使い分け
デフォルト値として使うなら`any | null`とか。?ではない。

## 所感
コード直さないとなぁ。。。
macOSデータ移行メモ

ほぼ衝動的にMacBook Pro(2017) 13in TouchBar無しモデルを購入した。

![mbp.jpg](https://qiita-image-store.s3.amazonaws.com/0/229548/1d65befd-2618-fc65-c676-98f3cc7ab791.jpeg)

それまで使っていたMacBook Airより環境やデータを移行するのに試行錯誤があったのでメモ。

## 使用したモデル

|    | モデル              | ストレージ | メモリ |
|----|--------------------|-----:|-----:|
| 旧 | MacBook Air (2015) | 128GB | 8GB |
| 新 | MacBook Pro (2017) | 256GB | 16GB |

ちなみにAirはJISキーボード，ProはUSキーボード。

さらに旧マシンデータのバックアップに AirMac Time Cupsle (2T)を使用した。

## 移行方法（失敗）

今回は使用マシンの完全移行を目的としていたので，Time Cupsleを使い，

1. データバックアップ
2. バックアップデータからの移設

で移行を行った。

### アプリとデータの移行

1. 旧AirでTime Cupsleにバックアップを作成する。
2. 新Proを初期化。
   - このとき「移行アシスタント」でAirのバックアップからデータ移行しようとするも，
     OSのバージョンが異なっていたためエラーになってしまった。
3. OSをアップデートすべく，一旦通常の初期化。
   - ここで旧Airで使っていたアカウント（例：nrmnr）を設定したのが失敗だった。
4. 新ProのOS起動後にOSをアップデート
5. アプリケーション→ユーティリティ→移行アシスタント.app を起動。
6. 手順にしたがい，旧Airのバックアップからアプリケーションやデータをまるっと移行。
   - 移行対象データの選択時に「競合」があると表示されるが，この時点で新Proにある
     `/Users/nrmnr/` は消えても構わないので「上書き」処理を実行。
7. 移行そのものはLAN接続，100GB程度で2時間ほどで完了。
8. Dropboxへのログインやらアプリ周りの設定をして終了。

### 事後のあれこれ

1. ところがよく見るとHOMEのディレクトリパスが`/Users/nrmnr 1/`になっている！
   - 新Proの`/Users/nrmnr/`は消えていたので，「上書き」はされたことになるのだろうが，気になるしパス指定とかも面倒臭くなる。
2. 仕方がないのでHOMEディレクトリ名を変更するために一時ユーザー（管理者）を作成。
3. 一時ユーザーでログインしたのち
「[macOSのユーザアカウントやホームフォルダの名前を変更する](https://support.apple.com/ja-jp/HT201548)」
にしたがい，`/Users/nrmnr 1`を`/Users/nrmnr/`に改名
4. 改めて`nrmnr`でログインしてみると，Dropbox起動時に「`/Users/nrmnr 1/.dropbox/`の権限を変更しろ」とのエラーになる。
5. アプリ再インストールも効果なし。
6. [こちら](https://soundsupport.biz/2017/01/01/fix-dropbox-after-changing-the-name-of-your-macs-home-folder/)の手順で修正すると，正常に同期できた。
7. しかしさらに悪いことに，Apple IDにも正常にログインできなくなっていた。
   - ログインしようにも「すでにログイン済みです」と言われるばかり。
8. 下記を試すも解消せず。
   - 「Macを探す」が解除されないままだとログオフしきれていない（？）→強制解除するためにPVRAMリセット（？）（そうなの？）
   - Apple IDのパスワード変更

## 移行方法（一応成功）

二進も三進も行かなくなったので，新Proを一度初期化し，再度データ移行する。

### macOSの再インストール（省略）

- 先に行なったOSのアップデートは再度しなくてもよかった。

### アプリとデータの移行

- 原則，先ほどの手順と同様だが，初期ユーザーは`dummy`とした。
  （初期設定時のデータ移行については，LAN設定をするためにスキップせざるを得なかった。）
- 今回は競合もなく，正常終了できた。

### 事後のあれこれ

- 一時的に作成した`dummy`ユーザーの削除

## まとめ

- 新マシンの初期設定時に何らかの理由でデータ移行ができず，一旦ユーザーを作成する必要がある場合は，
  旧ユーザー名とは別名にしておく。
- Apple IDのパスワードを変更すると，1年以内は元のパスワードに戻せない。（使ってる端末全部変えて回るハメに）（「[1Password](https://1password.com/jp/)」買おうかな）