OmniAICreator/Qiita-1.07M huggingface dataset:
【インフラ運用経験無しのサーバサイドエンジニア】AWSソリューションアーキテクトアソシエイト合格まで

# 受験前状況
 - インフラ運用経験なし
 - AWS上で本番サービス構築経験なし
 - AWS触り始めて6ヶ月

# 学習方法
### 公式トレーニング
**Architecting on AWS**
https://aws.amazon.com/jp/training/course-descriptions/architect/
AWSを触り始めてすぐに受けたトレーニング。
基本的な内容はここで学習。

### Organizationsで社内勉強用アカウント管理
社内向けのAWSアカウント管理することになったので、以下のようなことをしていました。

 - マスターアカウントから各アカウント発行
 - 各アカウントのCloudTrailログをマスターアカウントのS3バケットに集約
 - ログをlambdaでチェックして通知出したい項目があればSlack通知用SNSにpush

### AWS上でWebアプリケーション構築
オンプレで動いているWebアプリ（Linux、apache、PHP、MySQL）をAWS内で構築。
だいたい以下のような構成で作りました。サブネットは3層です。
<img width="559" alt="スクリーンショット 2019-01-04 15.32.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/42069/a419ab4e-4c1e-85e8-cbd8-a8f9b8227e0c.png">

### 模擬試験
これまで書いてきた状況で大まかな苦手分野の把握と、blackbeltの目処をつけるため、模擬試験を受けました。

| トピックレベル |スコア|
|:-----------------|------:|
|回復性の高いアーキテクチャを設計する|66%|
|パフォーマンスに優れたアーキテクチャを定義する |57%|
|セキュアなアプリケーションおよびアーキテクチャを規定する|66%|
|コスト最適化アーキテクチャを設計する|100%|
|オペレーショナルエクセレンスを備えたアーキテクチャを定義する|100%|
総合スコア： **68%**

上記の結果と、模擬試験中に学習が必要と感じた点をメモっておきました。
私の場合は以下です。

- フォールトトレランス
- S3のI/O周り
- ECS全般

### BlackBelt
https://aws.amazon.com/jp/aws-jp-introduction/
Blackbeltの資料は大量にあるので、
模擬試験の結果を参考に、対象の資料を読みました。

### 認定試験
2018年12月に受けたので、最新版の試験です。
どのくらい問題数があるかわからなかったので、1問1分くらいのつもりで解いていきました。
結果は8割ほどのスコアで**合格**でしたが、以下の点をもう少し勉強しておけばよかったと思いました。 

- 暗号化
- 費用対効果（インスタンスタイプ、ストレージ）
- Redshift
パフォーマンスチューニングの定石

こちらの書籍を読んだので備忘録です。
https://www.amazon.co.jp/dp/B00LHFOTF4/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

#手順
１、どこに問題があるのかを調べる
２、なんで問題が起きているのかを調べる
３、対応（≒実装）する
４、テストして修正の確認

そりゃそうだろうと怒られそうですが、上記にしたがって書いていきます。

#１、どこに問題があるのかを調べる
調べるときは「はさみうちの原理」で調べた方が良いです。
<img width="352" alt="スクリーンショット 2019-01-05 10.38.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/178311/dc0958b3-1b02-1fc8-f994-cc300f1bcfc3.png">
書籍より抜粋
上記のようなシステムを考える場合、レスポンスが遅いところをピックアップしながら探します。
調査する際には様々なコマンドが使えます。

#2~4、原因の調査＝＞対応＝＞テスト
問題が起きている箇所が特定できたら「そこでどんな処理を行なっているのか」を調べます。
この際遅くなっている原因はソート等のアルゴリズム、DBへの書き込み、キャッシュの有無等様々な要素が絡みます。
対応するときの定石として、「大きいものから一つずつ解決する」というものがあります。
大きい問題に埋もれて別の問題が隠れている可能性があるのと、
解決したと思ったらそれが原因で別の問題が起きる可能性があるためです。

なので
原因の調査＝＞対応＝＞解決したと思ったらテスト
を繰り返すことになります。

#対応する際のよくあるパターン
解決パターンとして使える考え方をまとめます。

##できるだけ再利用する
DBのコネクションプール、Webのキープアライブ、APサーバーのスレッドプール等、再利用できる仕組みは多数あります。
パフォーマンスの改善につながるので、できるだけ利用するようにしましょう

##設定をほどほどにする
コネクションプールの最大数、メモリサイズ、スナップショットの間隔など、自分で設定できるものがありますが、大きい方がいいからといってあまり大きくしすぎると他を圧迫することがあります。
設定する際には他との兼ね合いを見ながら少しずついじりましょう

##まとめて処理をする
ログの書き出し、DBへの書き込みなど、回数に比例して時間がかかる処理に関しては、バッチを使う等してまとめてやった方が早いことがあります。
ただし、これもほどほどにしないと大量のデータ更新が起こることになり、かえって遅くなるケースもあります。

##高速化と並列化
CPUのクロック数、コア数を上げる等がこれにあたります。
ただ、高速化は万能ですが並列化に関しては適してるかどうかの吟味が必要です。
並列にしても遊んでいるスレッドがあれば効果は得られませんし、処理の順番、デッドロックに気をつける必要があります。

##スケールアップとスケールアウト
同一サーバーのパフォーマンスを上げるのがスケールアップ、稼働サーバー自体を増やすのがスケールアウトです。
APサーバー等、各々の処理が独立しているものはスケールアウト向けですが、そうでないものはスケールアップの方が向いてます。

##局所性
データの処理に偏りが出ることを局所性といい、時間的、空間的、逐次的の３種類があります。
###時間的局所性
最近アクセスされたデータは近いうちにまたアクセスされるという考え方です。
キャッシュはこの考え方を使っています。

###空間的局所性
使われたデータの近くにあるデータほど使われる可能性が高いという考え方です。
ブロックやページ、エクステント等「塊」で処理する利点がここにあります。

###逐次的局所性
使われたデータの隣が使われることが多いという考え方です。

これらの局所性を考えることでパフォーマンスが向上することが多々ありますが、
開発環境で本番環境並みの局所性を再現するのはとても難しいです…

#現場で用いられるテクニック　
上記の考え方を実現するために、どう実装/対応すればよいのかをまとめます。

##ループ、サーバー間の問い合わせの省略
例えば、

```
for(int i = 0; i < 100; i++){
	selectById(i);
}
```
より、

```
List<Integer> idList;
for(int i = 0; i < 100; i++){
	idList.add(i);
}
selectByIdList(idList);
```
の方が早いことがあります。
前者は100回データの問い合わせが発生するのに対し、後者は一回しか問い合わせが発生しないからです。
また、多くのデータを取ってくる方が結果的にフルスキャンで早く済むこともあります。

##よく使うデータはキャッシュ化
言わずもがなですかね…
よく使うデータはいちいちDBに問い合わせするよりは、APサーバー内においておいた方が余計な通信を減らせます。

##同期を非同期に変える
同期処理は他の処理が終わるまで待つことになるため、独立した処理なら非同期の方が良いことがあります。
また非同期処理なら同期処理で使ってたぶんのリソースを他の部分に咲くこともできます。
ただ管理は大変になるのでそこは注意。

##帯域制御
リクエストが一定まで増えたら帯域制御によって受け付けず、「すいません混んでます」のような画面に飛ばすことも重要です。
こちらはコストも関わってくると思いますが、待ち行列理論のグラフのように全体が重くなるよりはマシという考え方になることが多い気がします。

##LRU方式
Least Recently Usedの略で、しばらく使われなかったデータをすてる仕組みです。
DBMSやストレージの内部でよく使われます。
ただ、「洗い替え」とも呼ばれるデータの総入れ替え処理等、たまにしか使われないデータにキャッシュが汚される可能性もありますので、そこは注意です。

##処理の分割 or ロック粒度の細分化
ロックを大きくしすぎると必要以上に他の処理が待たされることがあります。
安全性の面からロックは大事ですが、必要なぶんだけロックしているか確認した方が良いです。

##負荷分散、ラウンドロビン
複数のサーバーで処理をする際、遊んでいるサーバーが出ないように均等に割り振る仕組みをラウンドロビンといい、これを行う機器をロードバランサと呼びます。
AWS等で採用されており、これをすることによって負荷が分散され、スケールアウトの恩恵が大きくなります。

#まとめ
基本的には、
・不必要な通信を減らす
・待たなければいけないところは最小限に
・それでもだめなら負荷をどこかに分散させる
といった対策になります。
iOS 10 から導入された拡張sRGB色空間 (Extended sRGB Color Space) とは

記事の内容はこちらを参照してください。
https://mishimay.github.io/0f55af3db18ab84870e6/
<!--


iOS 10 からデフォルトとして使用されている _拡張sRGB色空間_ について説明します。

## はじめに、sRGB色空間 (not 拡張) とは
下のCIE色度図 [^1] のうち、点線の三角形で囲まれた部分がsRGB色空間です。
色のついている範囲が人が見ることのできるすべての色なのですが、その中の特定の範囲を限定してsRGB色空間と呼んでいます。
￼
￼<img width="375" alt="srgb.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/23679/d9d8d29c-5532-d359-5ee9-6b9e68ede6e5.jpeg">

sRGB色空間はコンピューターの世界で一般的によく使われており、色空間について特に指定のないときは暗にこのsRGB色空間を指していることが多いです。

CIE色度図やRGB色空間の詳しい説明は別の記事に書いたのでこちらをご覧ください。

> RGB値だけでは色は1つに定まらない
https://qiita.com/mishimay/items/e1e2f536068c3dafd01c

##  sRGB色空間の問題点
上のCIE色度図を見てもわかる通り、sRGB色空間は人が見ることのできるすべての色をカバーしていません。
これを解決するのが拡張sRGB色空間です。

## 拡張sRGB色空間 (Extended sRGB Color Space) とは
sRGB色空間では、R、G、Bそれぞれについて `0.0~1.0` (または `0~255`) の範囲で数値を指定することで特定の色を表現しました。
一方、 **拡張sRGB色空間はマイナスの数値や1を超える数値を許容します。** これにより既存のsRGB色空間での指定値はそのままに、さらにその外側のあらゆる色を表現可能になります。

## 使用方法
iOS 10.0 以上から使用可能です [^2]。
UIColorのデフォルトがこの拡張sRGB色空間なので [^3]、特に意識することなく使うことができます。
実際、今現在意識せず使っている方が多いと思います。

以下のコードは iOS 9 と iOS 10 で異なる値を出力します。

```swift
let color = UIColor(red: 1.2, green: -0.3, blue: 100, alpha: 1)
print(color)
```

iOS 9
`UIDeviceRGBColorSpace 1 0 1 1`

iOS 10
`UIExtendedSRGBColorSpace 1.2 -0.3 100 1`

iOS 9 では `0~1` の範囲に値が丸められている一方で、iOS 10 では表記が*`UIExtendedSRGBColorSpace`* となり負の値も大きな値もそのままであることが分かります。

## 他色空間からの変換方法
iOSには別のRGB色空間への変換メソッドが用意されています [^4] 。

例として Display P3 色空間から拡張sRGB色空間へ変換するコードを書いてみましょう。
下図 [^1] にあるように Display P3 色空間とsRGB色空間では緑色部分にある頂点の位置がかなりずれています。
￼
￼<img width="375" alt="p3.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/23679/089f0fd4-c420-2e5d-fb6d-2e11488127b8.jpeg">
Display P3 色空間における緑色はsRGB色空間の外側に存在する、つまり拡張sRGB色空間においてRGBの値が `0~1` に収まらないはずです。
それを確かめてみましょう。

```swift
let p3Color = UIColor(displayP3Red: 0, green: 1, blue: 0, alpha: 1)
let extendedSRGBColorSpace = CGColorSpace(name: CGColorSpace.extendedSRGB)!
let extendedSRGBColor = p3Color.cgColor.converted(to: extendedSRGBColorSpace, intent: .defaultIntent, options: nil)
print(extendedSRGBColor)
```

iOS 10
`[<CGColorSpace 0x600003d69140> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1; extended range)] ( -0.511767 1.01831 -0.310667 1 )`

このように Display P3 色空間における `(R: 0, G: 1, B: 0)` は、拡張sRGB色空間では `(R: -0.511767, G: 1.01831, B: -0.310667)` となりました。
予想通り `0~1` の範囲を超えています。
Gは約1.02と微増の一方で、Rは約-0.5とかなり大きくマイナスに振れているのが興味深いです。

## 環境
```
Apple Swift version 4.2 (swiftlang-1000.11.37.1 clang-1000.11.45.1)
Target: x86_64-apple-darwin18.2.0
```

[^1]: https://developer.apple.com/videos/play/wwdc2016/712/
[^2]: https://developer.apple.com/documentation/coregraphics/cgcolorspace/1644735-extendedsrgb
[^3]: https://stackoverflow.com/questions/30236619/what-is-the-default-color-space-for-uicolor
[^4]: https://developer.apple.com/documentation/coregraphics/cgcolor/1455493-converted


-->
Google日本語入力ではMacのライブ変換も英語スペルミスの自動修正も使えないからMac標準を使おうか？

Google日本語入力ではMacのライブ変換も英語スペルミスの自動修正も使えないからMac標準を使おうか？

# Google IME のせい？

どちらも使えないのは。

![image](https://user-images.githubusercontent.com/13635059/50743109-49bba600-1257-11e9-9579-71d33437ff69.png)
![image](https://user-images.githubusercontent.com/13635059/50743113-58a25880-1257-11e9-9a5e-e7862cca78e9.png)

# キーボード設定をもとに戻してみる

![image](https://user-images.githubusercontent.com/13635059/50743117-65bf4780-1257-11e9-808e-614aaef75bee.png)

![image](https://user-images.githubusercontent.com/13635059/50743119-6f48af80-1257-11e9-97ef-f4954e787e3f.png)


# Google IME じゃない英語に切り替え

![image](https://user-images.githubusercontent.com/13635059/50743122-7b347180-1257-11e9-8333-4acfcdcf473f.png)

# 直してくれない

![image](https://user-images.githubusercontent.com/13635059/50743128-87203380-1257-11e9-88bb-916f10edd0c5.png)

# note アプリだと直してくれた！

![image](https://user-images.githubusercontent.com/13635059/50743184-14fc1e80-1258-11e9-91ea-87d0c49228de.png)

Google Chrome   からの Web form だと無理なんだろうか。

# Goolge IME じゃない日本語に切り替え

![image](https://user-images.githubusercontent.com/13635059/50743130-91423200-1257-11e9-9fae-fc10d46676d2.png)

ライブ変換できた！

![image](https://user-images.githubusercontent.com/13635059/50743167-c8b0de80-1257-11e9-9128-1f86918e41cb.png)


---

https://twitter.com/yumainaura

https://github.com/YumaInaura/YumaInaura/issues

https://github.com/YumaInaura/YumaInaura/issues/283








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
スタバは好きだがレシートを渡されるのは本当に嫌い。コストの高いアプリケーション。

# JApanese

スタバは好きだがレシートを渡されるのは本当に嫌い。コストの高いアプリケーション。

- スタバの笑顔は精神に低コスト、静かな環境と音楽も耳に低コスト、レシートは高コスト、料理の待ち時間も。
- アプリケーションの赤丸の注意を引く通知は高コスト、クリックして1秒もかかるアクションも高コスト。
- Githubで入力していてMarkDown中のリンク先や画像がわからないのも高コスト。

レガシーは人類を絶滅させる。モダンは人類に優しくて人間を救済する。


# Legacy High cost application kill man kind and Modern low cost service save the earth.

# i love Starbucks but hate receipts sheet it has very high cost

Also High cost application too.

# Starbuck is low cost service i think

- Super Smile does not cost to our mind
- Silence and Music does not cost to our ears
- but i dont need paper receipts never forever more

![image](https://user-images.githubusercontent.com/13635059/50742952-0a8c5580-1255-11e9-8365-57e3533f0f00.png)

# English typo and google it and fix it is so high cost

![image](https://user-images.githubusercontent.com/13635059/50742902-5ee30580-1254-11e9-9a8f-fcbb2dbced87.png)

Web new connection is so high cost even we use MacBook or powerful device 

# Application notification is high cost red symbol e.g Google

it cost to our consiciousness mind 

![image](https://user-images.githubusercontent.com/13635059/50742973-58a15900-1255-11e9-9f4c-d444bf328720.png)
![image](https://user-images.githubusercontent.com/13635059/50742974-5a6b1c80-1255-11e9-8e2a-33f62548f5e3.png)

# Take a photo by iphone and share to mac book cost us

i use both icloud sharing and air drop and google photo
![image](https://user-images.githubusercontent.com/13635059/50742978-5e973a00-1255-11e9-9f71-e2b688e15a19.png)


# Why i very hate high cost all things in the world?

For see beautiful world and dance in the Starbucs Music hole

![image](https://user-images.githubusercontent.com/13635059/50742987-7242a080-1255-11e9-8e16-d6457e5b6df1.png)

ah screenshot macbook is so low cost 

![image](https://user-images.githubusercontent.com/13635059/50743000-84bcda00-1255-11e9-85b6-38fa597fe267.png)


---

https://twitter.com/yumainaura

https://github.com/YumaInaura/YumaInaura/issues



https://github.com/YumaInaura/YumaInaura/issues/282









<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
php-master-changes 2019-01-06

今日はコンパイラの警告潰しの修正があった！

# 2019-01-06
## jvoisin: Fix a warning about comparing signed/unsigned variables
- https://github.com/php/php-src/commit/3d9624e126366fe924f1374206e29c88a75c9361
- ext/hash で、signed と unsigned の比較による警告を潰すよう int を size_t に変更
WindowsからRaspberry Pi 3 Model B+にリモート接続する

Windows（やMac等）からRaspberry Piにリモート接続する場合、SSH接続とVNC接続の2つの接続方法があります。SSH接続は主にCLI環境、VNC接続は主にGUI環境（リモートデスクトップ接続のようなイメージ）になります。これができるようになると、HDMIケーブルやキーボード、マウス等が不要になりほぼワイヤレスのRaspberry Pi環境が構築できます。

## 環境
* Windows10 Home
* Raspberry Pi 3 Model B+
* Raspbian

## Raspberry Pi側の設定
Raspberry Piの設定ウィンドウを開き「インターフェース」タブから、SSHとVNCを有効にします。
![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/6453edfa-2c13-6b63-83ba-68720bbd695d.png)

## Raspberry PiのIPアドレスを確認
Raspberry Piでコンソールを開き、ifconfigコマンドを入力します。
![2.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/dc4a849e-53ee-3aea-3f42-735a5e9d2310.png)
inetのところに表示されたアドレスがRaspberry PiのIPアドレスになるのでこれを控えておきます。
※私の環境は無線LAN環境なのでwlan0がそれに該当します。有線LANの場合はeth0がそれに該当します。

## SSHで接続
以下のサイトからSSHでの接続ツール「Tera Term」をダウンロード&インストールします。
https://ja.osdn.net/projects/ttssh2/releases/
※バージョンは最新版で問題ないと思います。
インストールが完了したらTera Termを開き、「Raspberry PiのIPアドレスを確認」で控えておいたIPアドレスを入力しSSH接続します。
![3.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/917091c9-3dc2-3fce-e71b-5b903e33f0db.png)
※ここでセキュリティ警告が出ることがあるかもしれませんが、その場合「続行」で構いません。

Raspberry Piのユーザー名とパスワードを聞かれるので、自分で設定しているものを入力します。
![4.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/67de4c57-cb14-7c7d-d492-3c35dad19713.png)

以下のようにプロンプトが表示されれば接続成功です。
![5.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/35491d26-01b0-3ae0-58e5-10fa0c388a2f.png)


## VNC Viewerで接続
次にVNC接続です。Windowsのリモートデスクトップ接続でも良いのですが、そちらだと動きがかなりモッサリするので、VNC Viewerを利用して接続します。以下よりVNC Viewerをダウンロード&インストールします。
https://www.realvnc.com/en/connect/download/viewer/windows/
インストールが完了したらVNC Viewerを開き、「Raspberry PiのIPアドレスを確認」で控えておいたIPアドレスを入力します。
![6.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/231b1316-4699-9292-303f-129795b3aca5.png)

Raspberry Piのユーザー名とパスワードを聞かれるので、自分で設定しているものを入力します。
![578.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/9a4283a5-7f30-51b0-91d0-121d9a73f20c.png)

以下のようにRaspberry Pi側のデスクトップが表示されれば成功です。
![3333.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/607dc85f-3767-b4e3-74f2-65025f121885.png)

以上です。
PyQt5をつかってPythonで周期処理

ロボット的な何かを作るときとか、できるだけ正確にタイマー割り込みを行って周期処理をしたいじゃないですか。
Pythonのこの手の処理、ググるとスレッド使ったりOSのシステムコール使ったりといろいろあれどWidnowsでもラズパイでも同じコードでms単位で正確に動くやつってなくて、Qtに頼るやつだと動きそうな雰囲気なので忘備録としてまとめました。

主に以下の記事を参考にしました。
https://www.valuestar.work/news/archives/92

QtのsetInterval()を使っています。
時と場合によってライセンスには注意が必要ですが、PyQt5が入っていればWindowsでもRapbianでも同じコードで動くから便利。

``` python
import sys
from PyQt5.QtCore import *
import time

prevTime = 0

def main():
    app =  QCoreApplication(sys.argv)
    t1 = QTimer()
    t1.setInterval(10) #割り込み周期をms単位で指定
    t1.timeout.connect(TimerTest) #実行する関数を指定
    t1.start()
    sys.exit(app.exec_())

def TimerTest(): #実行される関数
	global prevTime
	currentTime = time.time()
	print(currentTime - prevTime)
	prevTime = currentTime

if __name__ == '__main__':
	prevTime = time.time()
	main()

```

10msごとにTimerTest()が実行されることを意図しています。
TimerTest()では前回実行された時間からどれくらい立っているか計測しています。
結果が以下のものになります。
実行環境はWin8.1のマシンになります。

```
0.012998580932617188
0.010000228881835938
0.010999202728271484
0.011002779006958008
0.008002281188964844
0.009998798370361328
0.010000228881835938
0.00999903678894043
0.010000228881835938
0.010024309158325195
0.009996652603149414
0.010020017623901367
0.009978055953979492
0.010024309158325195
0.00997781753540039
0.010002374649047852
0.010028839111328125
0.010002613067626953
```
まあまあ正確？


## 環境構築(pyqt5を入れる)
python3系の何かとかpipとかは入っている前提で

### Windowsの場合
```bash
pip install PyQt5
```


### ubuntuとかraspbianとかの場合

``` bash
 $sudo apt-get install python3-pyqt5
```

## 参考
https://www.valuestar.work/news/archives/92

https://teratail.com/questions/50115

https://stackoverflow.com/questions/36757752/how-to-install-pyqt5-in-python-3-ubuntu-14-04


https://stackoverflow.com/questions/4180394/how-do-i-create-a-simple-qt-console-application-in-c
トーラス上のライフゲームを、List Zipperを使用して実装してみた

# はじめに
この記事は、「[コモナドを使った抽象化の威力をライフゲームで試してみた](https://qiita.com/lotz/items/fbc4788b8ea8313cbf76)」で言及されている「トーラス上のList Zipper」を実装してみました、という記事です。Comonadとして実装したList Zipperを使用してライフゲームを実装し、メモリ使用量が増加しないことを確認しました。


# トーラスとは
長方形の左辺と右辺、上辺と下辺がそれぞれ繋がっているような構造です。RPGの平面マップで、右端や上端へ行くとそれぞれ左端や下端から出てくるような状況を想像するとわかりやすいと思います(平たく言えばドーナツ状の構造です)。


# 実装のポイント
## List Zipperの定義(1次元)
トーラス上(2次元)のList Zipperを考える前に、リング上(1次元)のList Zipperを考えてみます。
直線上のList Zipperでは、注目点はどこまでもずらすことができますが、リング上では、リストの長さ分だけ注目点をずらしたら、元に戻ります。
そのため、どちらかの方向にだけずらすことができれば十分です。
また、注目点の隣についても、取り出しやすくしておいたほうが後々便利です。
このため、リング上のList Zipperを以下のように定義します。

```Main.hs
data Z a = Z a a [a] deriving Show

next :: Z a -> Z a
next (Z y x xs) = let xss = xs ++ [y]
                  in Z x (head xss) (tail xss)
```

ここで、`Z a a [a]`は(注目点の1つ前) (注目点) (注目点の1つ後:_)となっています。

## Comonadの実装
直線上のList Zipperでは、duplicateするときに`iterate1`関数を使用して、注目点の左右にList Zipperの無限リストを作っています。
一方リング上のList Zipperは、有限回注目点をずらすと元に戻るため、duplicateで作成されるList Zipperのリストは有限の長さであってほしいです。
上記のため、List ZipperをComonadのインスタンスとした場合、以下のようになります。

```Main.hs
iterateN :: Int -> (a -> a) -> a -> [a]
iterateN 0 _ _ = []
iterateN n f x = let z = f x
                 in z : iterateN (n-1) f z

instance Functor Z where
  fmap f (Z y x xs) = Z (f y) (f x) (fmap f xs)

instance Comonad Z where
   extract (Z _ x _) = x
   duplicate zt@(Z _ _ xs) = let ztt = (iterateN (length xs + 1) next zt)
                             in Z (last ztt) zt (init ztt) 

```
`iterateN`関数を使用して、関数の繰り返し適用を有限回で打ち切るところがポイントです。


## List Zipperの定義(2次元)
トーラス上のList Zipperについても、1次元の場合と同じアイデアで実装できます。横方向をリング状にしたので、縦方向もリング状にしてあげます。
具体的な実装は以下の通りです。

```Main.hs
newtype Z2 a = Z2 (Z (Z a)) deriving Show

instance Functor Z2 where
   fmap f (Z2 zz) = Z2 (fmap (fmap f) zz)

instance Comonad Z2 where
  extract (Z2 zz) = extract (extract zz)
  duplicate (Z2 zz) = fmap Z2 . Z2 . roll . roll $ zz
  where roll zt@(Z _ (Z _ _ xs) _) = let ztt = (iterateN (length xs + 1) (fmap next) zt)
                                     in Z (last ztt) zt (init ztt)
```


# 動かしてみると
こんな感じです(撮影の都合で、ちょっと潰れてしまっています。また、変なところで飛んでいます)。
なお、平面上のList Zipperでは注目点の右側/下側のみ描画すれば十分でしたが、トーラス上のList Zipperは注目点も含めて全て描画する必要があります。
![grider.gif](https://qiita-image-store.s3.amazonaws.com/0/115336/c1ed78d9-91dc-6574-d04e-69c6358df523.gif)


# 最後に
今回は、トーラス上にList ZipperをComonadとして実装し、ライフゲームで遊んでみました。[lotz](https://qiita.com/lotz)さんも書いていましたが、`extend life`だけで全体の更新ができるのはちょっと感動しますね。

なお、トーラス上での計算は、言い方を変えると周期的境界条件の下での計算であり、数値シミュレーションとしては割とよくある設定だったりします。今回の応用として、2次元のIsing Modelの計算なども、割と簡単に実装できそうです。

今回のコードは、以下に置いてあります(計算内容だけ、動画と変えてあります)。
そのまま`stack ghc Main.hs`すれば動くと思われます。
https://github.com/chupaaaaaaan/lifegame/blob/master/Main.hs

以上です。
NUC8でESXiを動かすまでの道のり

# 技術の進歩
何か買いたいと思っていたところに、新しいNUC(Bean Canyon)の存在を知る。
現役自宅PCのIvy BridgeやHaswellと同じくらい、いや[それ以上のPassMark CPU Mark値](https://www.cpubenchmark.net/compare/Intel-i7-3770-vs-Intel-i7-4770S-vs-Intel-i5-8259U/896vs1884vs3299)で、半分以下のTDP。
m.2 NVMeなどで遊びながら、故障時の待機PCにしてもよさそう。
[開封の儀blog](https://nucblog.net/2018/11/coffee-lake-i5-nuc-review-nuc8i5bek-nuc8i5beh/)を見た後、ちっちゃくて持ち帰りが楽なのも手伝って、勢いで購入。
…その後、ESXiでハマったので、皆様の時間節約用に、メモ。

# 構成
- NUC: NUC8i5BEH
 - CPU: Core i5-8259U
- MEM: 8GB x 2
- SSD: m.2 NVMe 500GB

# NUCでESXiは動くか
現役自宅PCではESXiが動いているため、待機PCにするならNUCにもESXiを入れておきたい。
[「動くよー」というblog](https://nucblog.net/2018/11/installing-esxi-on-a-bean-canyon-nuc/)なども見て、あっさり動くのでは、と期待。(フラグ)

## ESXi起動ディスクの作成
ESXi 6.7のisoイメージを、RufusでUSBメモリに書き込み。

## 起動…せず
BIOS設定はdefaultのまま、USBメモリからUEFIで起動。
…が、`Shutting down firmware services`なるエラー。
ESXiのインストーラーが起動する前で、止まる。

[こちら](https://www.virtuallyghetto.com/2018/11/update-on-running-esxi-on-intel-nuc-hades-canyon-nuc8i7hnk-nuc8i7hvk.html)や[こちら](https://www.virtuallyghetto.com/2018/11/update-on-running-esxi-on-intel-nuc-hades-canyon-nuc8i7hnk-nuc8i7hvk.html)にお仲間がいらっしゃる模様。
BIOSをアップデートせよとのことらしい。

## BIOSアップデート…ファイル一覧に表示されず
2018/7のBIOSバージョン0041が入っていたので、最新の0056にアップデート。
FAT32のUSBメモリにBIOSイメージ(`.bio`)を入れて挿入。
最初、Visual BIOSの左上にupdateとあるので、ここから書き換えようと思ったが、うまくmount?できず、ファイル一覧に表示されない。

アップデート方法は色々あるが、試しにF7起動で書き換え開始。
自動再起動後、思ったより時間をかけて、成功。
なお、[本家](https://www.intel.co.jp/content/www/jp/ja/support/articles/000005636/mini-pcs.html)によると、F7でのアップデートは、推奨される方法、とある。
最初に読めですねそうですね。

## ESXiのインストール…NICが認識せず
ESXiが起動するようになったので、今度こそインストール。
…と思ったが、今度はNICが認識せず、NICが1つも無いためにインストールできない。

NICはI219-Vなので認識すると思ったが、[こちら](https://tech-mmmm.blogspot.com/2018/08/esxi-67intel-i219-v-id15bc-nic.html)によると、ESXi 6.5u2にあったドライバが、6.7では消えている模様。まぢか。
[こちら](https://www.vmware.com/resources/compatibility/detail.php?deviceCategory=io&productid=45884&vcl=true)で最新情報を確認すると、6.7u1で復活しているらしい。

## 6.7u1のイメージ…見つからず
6.7のイメージはダウンロードできるが、6.7u1のイメージは見つからない。
また、6.5u2のイメージは、自分の権利ではダウンロードできないらしい。

そこで、[ESXi-Customizer](https://www.v-front.de/p/esxi-customizer.html)。vibを埋め込めるし、6.7u1のイメージを作れれば、そのままでインストールできるはず。
…と思ったが、時代は[ESXi-Customizer-PS](https://www.v-front.de/p/esxi-customizer-ps.html)に移行しているらしい。
PSはPowerShellのこと。PowerShellで動く[PowerCLI](https://code.vmware.com/web/dp/tool/vmware-powercli/11.1.0)をベースに動くらしい。

## PowerCLI…動かず
[本家](https://code.vmware.com/docs/7614/powercli-11-1-0-user-s-guide#/doc/GUID-ACD2320C-D00F-4CCE-B968-B3C41A95C085.html)によると、PowerCLIのインストールは、PowerShellから

```
Install-Module VMware.PowerCLI -Scope CurrentUser
```

で良いとのこと。ローカルスクリプトの実行を

```
Set-ExecutionPolicy RemoteSigned
```

で許した後、ESXi-Customizer-PSを動かすと、`The type initializer for 'VMware.ImageBuilder.Impl.IfServer' threw an exception.`とのこと。

PowerCLI単体のコマンドでも同じエラーが起き、通信もしていなそうなので、PowerCLIの問題と切り分け。
PowerCLIを[スタンドアローンのインストーラーである6.5](https://code.vmware.com/web/dp/tool/vmware-powercli/6.5)まで戻したところ、エラーが出なくなる。

## ESXi-Customizer-PSで6.7u1のイメージ作成

```
PS C:¥> .¥ESXi-Customizer-PS-v2.6.0.ps1
```

だけで、最新パッチ適用済みのisoイメージが出来上がる模様。オプション不要。
I219-VのNICとm.2 NVMeも認識し、めでたくインストール。

# 宿題
パススルーなど。
docker + ubuntu + Vue.js + Firebase でチャットアプリした時のメモ

# 環境構築
LIGの[Vue.js+Firebaseでチャットアプリを作る記事](https://liginc.co.jp/378463)を参考にしてdocker + ubuntuで実装。ホストPC(Mac)からのlocalhost確認でハマる箇所があったのでメモ。

dockerでubuntuを構築し、ポートを3つマッピングするコマンド  

	docker run -it -p 8080:8080 -p 9005:9005 -p 5000:5000 --name vuetest ubuntu

ポート8080はVue.js、9005と5000はFirebaseで後ほど使用することになるが、ここでマッピングしておかないとホストPCでlocalhostにアクセスできない。

ubuntuにnpmとvimをインストールするコマンド  
以降全てubuntuコマンド  

	apt-get update
	apt-get install nodejs
	apt-get install npm
	apt-get install vim

Vueをインストール  

	npm install -g vue-cli

# Vue.jsの構築
ubuntuでディレクトリ移動(任意)  

	cd /usr/local/
Vue.jsプロジェクト作成  
色々尋ねられるけど全てエンターでOK

	vue init webpack myapp
作成したフォルダに移動してモジュールインストール

	cd myapp
	npm install

ポートの設定を変更する為にconfig内のindex.jsを編集  

	vi config/index.js

hostをlocalhostから0.0.0.0に変更  

	// Various Dev Server settings
	host: '0.0.0.0', // can be overwritten by process.env.HOST

プロジェクト起動  

	npm run dev

ホストPCのブラウザからhttp://localhost:8080/にアクセスするとVue.jsによって「Welcome to Your Vue.js App」とページが生成されていることがわかる。  

# Firebaseの構築

Firebaseサイトのコンソールからプロジェクトを作っておくところは割愛。  
ubuntuにFirebaseインストール  

	npm install -g firebase-tools

Firebaseにログイン  

	firebase login

生成されたURLをコピーしてホストPCのブラウザで開き、アカウントを選ぶ。「Woohoo!Firebase CLI Login Successful」と表示されればOK。  

コンソールに戻りFirebaseを構築  

	firebase init

選択肢の中から「Database:」と書かれている項目をスペースバーで選択してエンター。自分で作成したプロジェクトを選ぶ(LIGの手順を参照)。

database.rules.jsonを下記の通り書き換える  

	{
		"rules": {
			".read": "true",
			".write": "true"
		}
	}
	
firebase.jsonを下記の通り書き換える  

	{
		"hosting": {
			"public": "public"
		},
		"database": {
			"rules": "database.rules.json"
		}
	}
	
serveコマンドをオプションでアドレス指定して入力  

	firebase serve -o 0.0.0.0

ホストPCのブラウザでhttp://0.0.0.0:5000にアクセス
Windowsレジストリ変更を.bat(バッチ)で行った時のメモ

レジストリ変更を.batファイルで行いたかったが、REG_BINARY形式のデータ変更書式で詰まったので解決メモ。

下記は間違った記述

`reg add HKEY_CURRENT_USER¥Software¥Microsoft¥Windows¥CurrentVersion¥Explorer /v ShellState /t REG_BINARY /d hex:24,00,00,00,33,a0,00,00,00,00,00,00,00,00,00,00,00,¥  	00,00,00,01,00,00,00,12,00,00,00,00,00,00,00,32,00,00,00 /f
`
	
下記は正しい記述

`reg add HKEY_CURRENT_USER¥Software¥Microsoft¥Windows¥¥CurrentVersion¥Explorer /v ShellState /t REG_BINARY /d 2400000033a0000000000000000000000000000001000000120000000000000032000000 /f
`

# まとめ
reg add .... /dまでは一緒。
そこから後はhex:とか,(カンマ)とか¥(改行)とかは不要。数値だけを羅列するのが正解。

## その他注意したところ
例えばControl Panelというディレクトリなど、ディレクトリに空白が入る場合は、ディレクトリの記述全体を"(ダブルクォーテーション)で囲めば良し。  

`reg add "HKEY_CURRENT_USER¥Software¥Control Panel¥CurrentVersion¥Explorer" /v Example /d 1 /f`
さくらレンタルサーバーにsshでpython入れた時のメモ

sshで環境変数をいじる。

python3をインストール後、パスを通した時の手段は下記の通り。

	% vi ~/.cshrc
	set path = ($path $HOME/local/python/bin)
	setenv PYTHON $HOME/local/python/lib

その後.cshrcファイルをリフレッシュすること。  

	% source ~/.cshrc
	% rehash
【TeX】Atomでjplainを使う方法


# 目次
- [環境](#環境)
- [問題](#問題)
- [解決方法](#解決方法)

# 環境
- MacBook Pro 2018 (macOS 10.14.2)
- TeX Live 2018
- Atom (v1.33.1)
- latex (v0.50.2) <- Atomのパッケージ

# 問題
Atomの「latex」パッケージを使ってtexファイルをビルドする際，引用文献のスタイルを決める`\bibliographystyle{jplain}`が効かない問題。

# 解決方法 
「latex」パッケージ内では`latexmk`コマンドを使っているようなので，`latexmk`コマンドの設定をいじってあげると解決する。`latexmk`コマンドの設定は`.latexmkrc`ファイルで変更することができる。ホームディレクトリ（or ユーザディレクトリ or ビルドファイルのあるディレクトリ）に`.latexmkrc`を作成し，以下のように書き込む。

```..latexmkrc
#!/usr/bin/perl

# commands for latex,bibtex,dvipdf. %S : source file, %B : base name, %D : pdf file, %O : option
$latex = 'platex %O -interaction=nonstopmode -synctex=1 -kanji=utf8 %S';
$bibtex = 'pbibtex %O %B -kanji=utf8';
$dvipdf = 'dvipdfmx %O -o %D %S';

# method to make pdf - 0:not making, 1:pdflatex, 2:ps2pdf, 3:dvipdf
$pdf_mode = 3;
```
ぶっちゃけ$bibtexの設定だけでいいと思うけどね^^;

これで設定は終わりです。もう一度ビルドしてみてください。
型パターン(C#7)

# C#7時代の型変換

`C#7.0`から、型変換において、**~~型スイッチ~~** **型パターン**という便利な書き方ができるようになりました。

*コメントで型スイッチは古い呼び方と教えていただきました！*

>pattern-matching
>https://docs.microsoft.com/ja-jp/dotnet/csharp/pattern-matching

こちらの記事様を参考にさせていただきました。
>is、switch の拡張 (型スイッチ) - C# によるプログラミング
>https://ufcpp.net/study/csharp/datatype/typeswitch/

この記事では簡単な使用例を示します。

## is/as演算子

そのまえに、`is/as演算子`を使った従来の型変換について超簡単におさらい。

### is演算子

変数名で指定したクラスにダウンキャスト可能かどうかを調べる。
ダウンキャストできるか否かが、`true/false`で返される。

構文 : `変数名 is クラス名`

```csharp
Object obj = "hoge";
String str = (String)obj;
Console.WriteLine(obj is str); // true      
```

### as演算子

`is演算子`のように前もって診断しなくても安全にダウンキャストできる。ダウンキャストを実行して、ダウンキャスト不可の場合は`null`を返す。

構文 : `変数名 as クラス名`

```csharp
Object obj = "hoge";
String str = obj as String;
Console.WriteLine(str == null); // false        
```

### 使い分け

もし、ダウンキャスト判定するだけなら、`is演算子`だけで十分です。

```csharp
Object obj = "hoge";
if (obj is string) Console.WriteLine("Do something!");
```

ただし、判定した上で、さらにダウンキャストもしたい場合。`is演算子`を使うと以下のような二重処理のコードになってしまい、なんかあんまり良くない感じです。

```csharp
Object obj = "hoge";
// 処理[1]->判定
if (obj is string) {
  // 処理[2]->キャスト
  var s = (string)obj;
}
```

この場合、`as演算子`を使った方がスマートです。

```csharp
Object obj = "hoge";
var s = obj as string;
if (s != null) Console.WriteLine("Do something!");
```

## ~~型スイッチ~~ 型パターン (C#7.0)

やっと本題です。

C#7では、上記の`is演算子`が拡張され「ダウンキャストできるかどうかの判定」と「新しい変数の定義」が同時にできるようになりました。これを**~~型スイッチ~~** **型パターン**といい、さらにスマートな記述ができるようになりました。

ダウンキャスト可能なら`true`が返り、ダウンキャストが実行され変数が定義されます。

構文 : `変数 is 型 変数名`

```csharp
Object obj = "hoge";
if (obj is string str) Console.WriteLine("Do something!");
```

## switch文の拡張 (C#7.0)

型スイッチは`switch文`でも使えます。
caseの後ろに`型`も書けるようになりました。

構文 : `case 型 変数名:`

```csharp
Object obj = "hoge";
switch (obj) {
  case int x:
    Console.WriteLine(x);
    break;
  case string str: // <- このcaseにマッチする
    Console.WriteLine(str); // hoge
    break;
}
```

### whenキーワード

また、`when`による条件フィルターをかけることもできます。

構文 : `case 型 変数名 when 条件式`

```csharp
Object obj = "hoge";
switch (obj) {
  case int x:
    Console.WriteLine(x);
    break;
  case string str when (str.Length == 4):
    Console.WriteLine(str); // hoge
    break;
}
```

## ジェネリックな型スイッチ (C#7.1)

さらにC#は進化を止めず、**C#7.1**では、**ジェネリック型の型スイッチ**が使えるようになりました。つまり、ジェネリック型の引数に対してパターンマッチングすることができます。かなり便利な機能だと思うのですが、C#7.0まではこれをやるとコンパイルエラーとなります。

```csharp
switch (x) {
  case int i:
    Console.WriteLine(i);
    break;
  case string s:
    Console.WriteLine(s);
    break;
  default:
    Console.WriteLine("not match");
    break;    
}
// C#7.0まではコンパイルエラー
```

おわり
Rのgggenesパッケージで原核生物の遺伝子マップを描画する方法

# Rのgggenesパッケージで原核生物の遺伝子マップを描画する方法
* ただし、遺伝子の方向の反映とdummyの併用が下記の方法だとうまくいかない
* エキソン-イントロン構造とかの複雑な遺伝子図の描画にはあまり向かないかも 

Rのgggenesは遺伝子マップを簡単に描くことができる便利なパッケージ。
作者のgggenesの[ページ](https://cran.r-project.org/web/packages/gggenes/vignettes/introduction-to-gggenes.html)



使うにはまずはRで
ggplot2 
gggenes 
ggfittext
パッケージをCRAN経由でインストール。

そして
molecule start end gene strand
genome1 723332 724332 dummy 1
genome1 724333 725097 hogE 1
genome1 725111 726544 hugA -1
genome1 726541 727215 hugU -1
genome2 100 1100 dummy 1
genome2 1101 2104 hogE 1  

といった感じで描画したい遺伝子の情報をtxtファイルで記述し保存（下記ではtestdata.txtとして保存したものを読み込んでいる）。
moleculeは、生物種名等、遺伝子図を1ラインで表示したい単位ごとに別名で記述。
strandは遺伝子の方向。1が+、-1が-。
dummyは、遺伝子図の縮尺をゲノム間であわせるためのダミー遺伝子。

描画は、例えば下記のようなコマンドで可能。

```R
library(ggplot2)
library(gggenes)
library(ggfittext)
example_genes <- read.table("testdata.txt", header=T)
dummies <- make_alignment_dummies(
  example_genes,
  ggplot2::aes(xmin = start, xmax = end, y = molecule, fill = gene, id = gene),
  on = "dummy"
)
ggplot2::ggplot(example_genes, ggplot2::aes(xmin = start, xmax = end, y = molecule, fill = gene, label = gene)) +
geom_gene_arrow(arrowhead_height = unit(3, "mm"), arrowhead_width = unit(1, "mm")) +
ggplot2::geom_blank(data = dummies) +
ggplot2::facet_wrap(~ molecule, scales = "free", ncol = 1) +
geom_gene_label(align = "left") +
theme_genes()
```

残念ながら、dummyがある状態でstrandの情報を参照すると、エラーが出て描画ができないので上記ではstrandの情報を参照していない。dummyが無いならstrandの情報は

```R
ggplot2::ggplot(example_genes, ggplot2::aes(xmin = start, xmax = end, y = molecule, fill = gene, label = gene, forward = strand)) +
```
で反映可能。
上記問題が少なくとも私の中では解決できていないので、-の遺伝子の反転や遺伝子の色分けは、私はこの後イラレでやっている。
そのために、下記のようにとりあえず遺伝子図をpdf形式で保存するのが基本。

```R
pdf("gggenestest.pdf", width=10,height = 5)
ggplot2::ggplot(example_genes, ggplot2::aes(xmin = start, xmax = end, y = molecule, fill = gene, label = gene)) +
geom_gene_arrow(arrowhead_height = unit(3, "mm"), arrowhead_width = unit(1, "mm")) +
ggplot2::geom_blank(data = dummies) +
ggplot2::facet_wrap(~ molecule, scales = "free", ncol = 1) +
geom_gene_label(align = "left") +
theme_genes()
dev.off()
```
CodeBuildを使ったlambda自動更新のメモ

# artifactがよくわからない。。。
`codebuild`を使った`lambda`の更新を調べると、
`artifact`を使って...があったのですが`artifact`がよくわからない。。。
なので使わないメモ
※やり方があっているかは不明です。。。

# リポジトリ構造
```bash:tree.sh
$ tree ./
./
├── README.md
├── buildspec.yml
├── lambda_function.py
└── requirements.txt
```

# やり方
1. `codebuild`で使うroleに適当なS3とlambdaの権限を与える
2. 以下の`buildspec.yml`を使ってビルドする

```yml:buildspec.yml
version: 0.1

phases:
  install:
    commands:
      - pip install -t . -r requirements.txt
  build:
    commands:
      - zip -r {{FUNCTION_NAME}}.zip ./
      - aws s3 cp {{FUNCTION_NAME}}.zip s3://{{LAMBDA_BUCKET}}/
      - aws lambda update-function-code --function-name {{FUNCTION_NAME}} --s3-bucket {{LAMBDA_BUCKET}} --s3-key {{FUNCTION_NAME}}.zip
# artifacts:
#   type: zip
#   files:
#     - "**/*"
#   discard-paths: no
```
HHKB Pro2 英字無刻印 (2017頃〜) 掃除に必要なキートップ裏の印字（型番）

HHKB Pro2 英字無刻印モデルを愛用しているのですが、キーにより形状がバラバラなため, 外して掃除する際は正確に戻す必要があります。
しかし印字がないので、代わりにキートップ裏に刻印されている印字（型番？）を見ながら戻すことになります。

キーと印字の配置の対応表を掲載してるありがたいブログがいくつかあったのですが、
私が買ったバージョン(2017年頃)は型番が変わっていたようなので、止むを得ず自分で対応表を作りました。こちらです。

<img width="1090" alt="スクリーンショット 2019-01-07 1.29.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/58251/7ff041c0-b725-8447-182a-c603b254b375.png">

キートップ裏の印字はとても小さく見難いため、多少誤りがあるかもしれません。

よければご参考にしてください。
Amazon Data Lifecycle Managerを試してみた

Amazon Data Lifecycle Managerを試してみました。

# どんなもの？
EBSスナップショットの作成、保持、削除を自動化する機能です。

# 1. Lifecycle Policyを作成する
AWSコンソールのEC2の所から、12時間毎に特定のタグを持つインスタンスのEBSスナップショットを作成し、スナップショットを2世代保持するように設定します。
<img width="527" alt="1.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/1cdbb5aa-9160-f8f8-690f-9f880b0fce67.png">

<img width="519" alt="2.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/a50ba8b8-29a1-f7a4-c2ab-6530287963f6.png">


# 2. 確認する
スナップショットが2世代出来ていることが確認できます。
<img width="1075" alt="3.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/bab80d7c-4a99-653f-88a0-3d3b24b9f450.png">

# 雑感
- 時間ベースのスケジューリングだけでなく、CodeDeployでデプロイしたタイミングで取得とかも指定できるといいなぁ。
- 話はずれるけど、そろそろEFSにスナップショット取得機能がつかないかな。
datetime型のtimestamp()をWindowsで使用する際の注意点

# 0. 筆者環境

Windows 10 64bit
Python 3.6.7 64bit
datetime 4.2
zope.interface 4.5.0
pytz 2018.4
setuptools 40.6.2

# 1. 問題点・実例

UNIX環境で作業をしていたため、気づかなかったことを備忘として。
上記Windows環境で下記コードを実行すると次のエラーが発生する。

### Windows環境

```python
# Windows環境

from datetime import datetime

date = datetime.fromtimestamp(0)
print(date)

>>> 1970-01-01 09:00:00

print(date.timestamp())

>>> OSError: [Errno 22] Invalid argument
```

実はこのコードと全く同じものをUNIX環境で実行した場合は下記の出力となる。

### UNIX環境
```python
# UNIX環境

from datetime import datetime

date = datetime.fromtimestamp(0)
print(date)

>>> 1970-01-01 09:00:00

print(date.timestamp())

>>> 0.0
```

うーん、OS依存。~~これだからWindowsはクソ。~~
簡潔にこの問題を表すと、Windows環境でtimestamp()に値を渡す場合は86400以上の値を渡さなければエラーになるらしい。
※　max_fold_seconds = 24 * 3600 = 86400

### timestamp()の引数に86399を指定 => エラー出力

```python
# Windows環境

from datetime import datetime

date = datetime.fromtimestamp(86399)
print(date)

>>> 1970-01-02 08:59:59

print(date.timestamp())

>>> OSError: [Errno 22] Invalid argument
```

### timestamp()の引数に86400を指定 => エラー出力無し

```python
# Windows環境

from datetime import datetime

date = datetime.fromtimestamp(86400)
print(date)

>>> 1970-01-02 09:00:00

print(date.timestamp())

>>> 86400.0
```


# 2. 対処法

このバグ、実はもう報告されていた、対処は参考に全て乗っているので割愛。


# 3. 参考
https://bugs.python.org/issue29097
https://github.com/python/cpython/pull/2385
JavaScriptでフローティングウィンドウを表示する方法

# 概要
- JavaScriptでお手軽にフローティングウィンドウを表示する方法を紹介します
- 独立したライブラリなのでjQuery等への依存はありません。
- [拙作ライブラリ](https://github.com/riversun/JSFrame.js)の新機能（ウィンドウの開閉アクションなど）の紹介となります

![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/a27cd920-ec25-a124-46b4-2dcc868ebb1e.png)
(https://riversun.github.io/jsframe/examples/v150/preset_yosemite_auto.html)

# yosemite風フローティングウィンドウを表示する

```html:index.html(フローティングウィンドウを表示する)
<!DOCTYPE html>
<html>
<head>
    <title>JsFrame.js JavaScript Yosemite</title>
    <meta charset="utf-8">
</head>
<body style="background: url('http://upload.wikimedia.org/wikipedia/commons/d/d6/Half_Dome_from_Glacier_Point%2C_Yosemite_NP_-_Diliff.jpg') 50% no-repeat fixed; background-size: cover;">
<script src="https://riversun.github.io/jsframe/jsframe.js"></script>

<script>
        const jsFrame = new JSFrame();//jsFrameオブジェクトを作る
        const frames = [];
        for (let i = 0; i < 3; i++) {
            const frame = jsFrame.create({
                name: `Win${i}`,
                title: `Win${i} - Yosemite style`,
                left: 20 + (320 + 20) * i, top: 50, width: 320, height: 220, minWidth: 200, minHeight: 110,
                appearanceName: 'yosemite',//プリセット名 yosemite を指定
                style: {
                    backgroundColor: 'rgba(255,255,255,0.8)', //背景色は半透明に
                    overflow:'auto'
                },
                //ココに表示したいHTMLを直接設定するか、 url:'' でurl指定するとその内容をiframeで表示
                html: '<div style="padding:10px;">Your contents here.</div>'
            }).show();

            frame.setControl({
                styleDisplay:'inline',
                maximizeButton: 'zoomButton',
                demaximizeButton: 'dezoomButton',
                minimizeButton: 'minimizeButton',
                deminimizeButton: 'deminimizeButton',
                hideButton: 'closeButton',
                animation: true,
                animationDuration: 150,

            });
            frame.control.on('hid', (frame, info) => {
                frame.closeFrame();
            });
            frames.push(frame);
        }
        frames[0].requestFocus();
</script>
</body>
</html>

```

デモ
https://riversun.github.io/jsframe/examples/v150/preset_yosemite_auto.html

見た目を変更した例
https://riversun.github.io/jsframe/examples/v150/preset_material.html

# まとめ

- 見た目はカスタムできるので、ちょっとしたポップアップ用途から、本格的！？マルチウィンドウアプリまで作成可能です。
（が、カスタムが面倒という声をいただいたので、いくつかプリセットを内蔵しました、今回のもその1つとなります）

- ライブラリ自体はこちら[「フローティング・ウィンドウ ライブラリ JSFrame.js の紹介」](https://qiita.com/riversun/items/1adffa5674bc5123b16d)で紹介しています。
salesforceの商談の完了予定日を自動的に変更させない方法

# これは何？
salesforceの商談オブジェクトでは、完了予定日という項目があります。
この項目は、ちょっとくせ者で、フェーズや完了予定日の日付によって、自動で書き換わります。
この導入完了予定日を勝手に変更させない方法を記載します。

[完了予定日の動作仕様]
https://help.salesforce.com/articleView?id=000171052&language=ja&type=1


# やり方
やり方は以下URLに記載の通りです。

https://help.salesforce.com/articleView?id=000004430&language=ja&type=1

ただ、上記設定だと、フェーズに対して、フェーズが進捗100%の他の項目を持たせていた場合、うまく機能しません。
例として、受注 -> 導入準備中(進捗100%) -> 導入完了（進捗100%）のような形で、導入後の進捗も追いたい場合です。

その場合は、以下の画像のようにルール評価のタイミングを、*作成されたとき、および編集されるたび*にしましょう。
<img width="762" alt="スクリーンショット 2019-01-07 1.15.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/30859/4b9ea5fc-f54a-e09f-5a0e-3bc5ab5e00db.png">

以上。
JUCEのStandalone版AudioProcessorでバッファサイズを変更する。

JUCE + Projucerでソフトシンセのプラグインを作ると、スタンドアロン版もProjucerの設定でチェックを入れるだけで作成できて便利だが、オーディオデバイスの設定をシンセのUIから行いたい場合にどうしたらよいか疑問だった。これはStandalonePluginHolderクラスを使って行うことが可能だとわかった。この方法を使えばデバイス設定のUIが（デフォルトでは）用意されていないiOS版のアプリでも独自に設定を追加することが簡単にできる。

##仕上がりイメージ
取ってつけすぎだがこんな感じのUIを作る。ComboBoxには64,128,256,512,1024くらいの値を羅列しておく。
![Simulator Screen Shot - iPhone X - 2019-01-07 at 00.48.28.png](https://qiita-image-store.s3.amazonaws.com/0/107818/f2ef5c8c-588f-f6db-98fa-07e8a59dda6e.png)

##StandalonePluginHolderのインスタンスを取得
スタンドアロン版のアプリはStandalonePluginHolderをインスタンスとして保持していて、これがシングルトンでgetInstance()メソッドで取得できる。ただし、使用するにはヘッダファイルを下記のように指定しておく必要がある。

```MyEditor.cpp
#include <juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h>
```

UIのクラスのコンストラクタに下記のように記述。

```MyEditor.cpp
    //[UserPreSize]
    StandalonePluginHolder* holder = StandalonePluginHolder::getInstance();
    if (holder != nullptr)
    {
        AudioDeviceManager::AudioDeviceSetup setup = holder->deviceManager.getAudioDeviceSetup();
        for (auto i = 0; i < comboBufferSize->getNumItems(); i++)
        {
            if (comboBufferSize->getItemText(i).getIntValue() == setup.bufferSize)
            {
                comboBufferSize->setSelectedItemIndex(i);
                break;
            }
        }
    }
    else
        comboBufferSize->setEnabled(false);
    //[/UserPreSize]
```

StandalonePluginHolderのインスタンスがnullptrでなかったら、スタンドアロンとして起動されていることになる。ただし、スタンドアロンであっても少なくともAudioProcessorのインスタンスが作られるまではnullptrが返ってくるので注意。Editorのコンストラクタでは少なくとも今使ってみてる感じでは作成完了している様子。

StandalonePluginHolderはAudioDeviceManagerを持っているので、あとはそれを使ってバッファサイズの取得なり設定なりすればいい。特定の値だけを変更するには一度AudioDeviceManager::getAudioDeviceSetup()で取得してから変更したい値だけ（この例ではバッファサイズ）を書き換えてAudioDeviceManager::setAudioDeviceSetup()でセットする。2番目の引数はtrueにしておく。

```MyEditor.cpp
    if (comboBoxThatHasChanged == comboBufferSize.get())
    {
        //[UserComboBoxCode_comboBufferSize] -- add your combo box handling code here..
        String text = comboBoxThatHasChanged->getItemText(comboBoxThatHasChanged->getSelectedItemIndex());
        int bufferSize = text.getIntValue();
        StandalonePluginHolder* holder = StandalonePluginHolder::getInstance();
        if (holder != nullptr)
        {
            AudioDeviceManager::AudioDeviceSetup setup = holder->deviceManager.getAudioDeviceSetup();
            setup.bufferSize = bufferSize;
            holder->deviceManager.setAudioDeviceSetup(setup, true);
        }
        //[/UserComboBoxCode_comboBufferSize]
    }
```
gulpでSCSSコンパイル時にgulp-csscombを使っているとsourcemapが正しいファイル・行数を示さない

出る出るといいつつ全然出なくてすっかり忘れた頃にメジャーバージョンがリリースされ、v4になった`gulp`さんを今更ながら最新版で使おうと`gulpfile.js`を再び書き直していた所、表題の件に気づきました。年末年始休暇の最終日を潰していろいろ調べてみたので、自分なりな解釈ではありますがその結果を共有しておきたいと思います。

# 症状

`gulp-sourcemaps` がどうにも正しく動作しておらず、全然関係ないファイルを指していたりしてました[^1]。原因はなにかいろいろ調べては見たのですが、`gulpfile.js`の指定方法はあってそうなので書き方の問題ではなさそうでした。

# 原因

`gulp-csscomb`を使っていたからでした。

## 具体的には

`gulp-sourcemaps` が`gulp-csscomb`に対応していませんでした。整形された後のsourcemapが正常に出力されず、その結果デベロッパーツールで見てもおかしい行数やファイル名が示されていた、ということのようです。

[https://github.com/gulp-sourcemaps/gulp-sourcemaps/wiki/Plugins-with-gulp-sourcemaps-support](https://github.com/gulp-sourcemaps/gulp-sourcemaps/wiki/Plugins-with-gulp-sourcemaps-support)

`gulp-sourcemaps`側では今の所対応予定がなく、issueで同じような問い合わせがあったことに対して「その手の話は対応しないことにしている」とだけ返答してissueをcloseしています。

[https://github.com/gulp-sourcemaps/gulp-sourcemaps/issues/359] (https://github.com/gulp-sourcemaps/gulp-sourcemaps/issues/359)

一方で`gulp-csscomb`側は現在の所対応予定がないというか、そもそもメンテナンスされておらず、作者が後継の方を探しているといったような状態でした。

[https://twitter.com/tonyganch/status/686992436871168000] (https://twitter.com/tonyganch/status/686992436871168000)

# 対処方法

## `gulp-csscomb` と `gulp-sourcemaps`を同時に使わない。

身も蓋もない感じですが、今の所これしかなさそうです。
例えばリリースビルドで圧縮せず綺麗な状態でcssを納品する必要があるのであれば、納品ビルドだけcsscombを適用し、sourcemapは使わないといった形であれば問題なく使えるかと思います[^2]。

# ちなみにgulp 4.xでは

ビルトインでsourcemapsを出力出来るようになっています。ただ、これを使っても`csscomb`と共存出来るというわけではありませんでした（結果は`gulp-sourcemaps`使用時と変わらなかった）。見た限りではそのように明言された箇所が見当たりませんでしたが、`gulp-sourcemaps`自体が内包された形になってるんでしょうか？

[https://github.com/gulpjs/gulp] (https://github.com/gulpjs/gulp)

> Built-in support for sourcemaps was added - the gulp-sourcemaps plugin is no longer necessary!

## gulp 4.xでのビルトインsourcemapの使い方

src指定時と、dest指定時に引数として追記すればOKです（以下の書き方だとcss出力先と同じ箇所にmapファイルが生成される）。手元のgulpfile.jsからそのまま持ってきたので、適時お手元の環境に読み替えて見ていただければと思いますが、要は`src`（gulp.src()）と`dest`（gulp.dest()）に引数が増えているのですぐわかるかと思います。

```js:gulpfile.js
// SASSコンパイル
task('sass', (done) => {
  return src(dir.src + 'scss/**/*.scss', {sourcemaps: true})
  // エラーの場合は停止せずに通知を出す
  .pipe($.plumber({
    errorHandler: $.notify.onError("Error: <%= error.message %>")
  }))
  // scssファイルをまとめて読み込む
  .pipe($.sassGlob())
  // コンパイル
  .pipe($.sass({outputStyle:'expanded'}))
  // cssプラグインの適用
  .pipe($.postcss(project.scss.plugins))
  // productionなら圧縮する
  .pipe($.if(isProduction, $.cleanCss()))
  // 出力先ディレクトリ
  .pipe(dest(dir.dist+dir.assets+'css', {sourcemaps: '.'}))
  // Sassを更新したらリロードせずに直接反映させる
  .pipe(browser.stream())
  // タスクの終了宣言
  done()
});
```

`gulp-postcss`や`gulp-clean-css`は`gulp-sourcemaps`の頃から対応していたためか、併用しても大丈夫のようです。
[https://github.com/gulp-sourcemaps/gulp-sourcemaps/wiki/Plugins-with-gulp-sourcemaps-support](https://github.com/gulp-sourcemaps/gulp-sourcemaps/wiki/Plugins-with-gulp-sourcemaps-support)

# 終わりに。

我ながらよく今の今までsourcemapがおかしいことに気づかなかったなと思います…（browsersyncのlivereload絡みでおかしくなってるんだと勝手に思ってました）。

私なりにいろいろ調べた結果ではありますが、なんとか連休中には出したかったということもあり、調べが足りていない可能性もあります。
もし解決方法をご存知だったり、そもそもの原因や私の理解が間違っている事などありましたら、ぜひご指摘いただけると助かります。

それではまた。

[^1]: object/components/_sample.scss内に記述している内容が、sourcemapを通すとfoundation/mixins.scssになったりしてました。
[^2]: よくよく考えると、私みたいに開発中のみsourcemaps+csscombを使っている方がおかしい気がしてきました。
初めてのペアプロっぽいもの


# はじめに
今年のテーマはアウトプットだ！
まず一歩目としてQiitaに初投稿してみる。

# はじめてのペアプロ
はじめてのペアプロっぽいものに関する感想や課題などあれこれの記録。

新たにチームに合流したメンバーに、既存システムに追加される新画面を担当してもらう。
画面イメージの作成や、HTMLとCSSによる画面作成まではやってもらった。
しかし、PHPによるコーディングにはフォローが必要と判断。
PHPはじめて、というスキル面以前に、既存システムの独自クラスの説明や既存システムの資料不足等の背景もあり。

わたしが教えるということに慣れてないので、自分の業務に熱中しているとフォローがおろそかになってしまいそう・・・
よし、ペアプロを試してみよう！

[ペアプログラミングして気がついた新人プログラマの成長を阻害する悪習](https://qiita.com/hirokidaichi/items/27c757d92b6915e8ecf7)


## まず開発環境を見直そう
色々開発環境が不十分だった。

* ログを表示させるようにNTailを設定
* ログの見方を説明
* xdebugは未設定・・・まずはvar_dumpで。

## 丁寧に
独自クラスの説明などで、習うより慣れろじゃないですが、まずは概要と使い方を知ってもらって詳しい説明はもう少しPHPになれてから、という考えがあった。
だが、連想配列についての説明を２日目にした。連想配列わかってなかったのか・・・
ごめん。何事も思い込みはいかん。しっかりと丁寧に確認しながら進めないと・・・と反省。


## 答えを言い過ぎたかな・・・
直接的な答えを言うのではなく、ヒントにとどめて調べたり考えたりしてもらう量を増やしてもよかったのではないか。
達成感を味わってほしいという思いもあったが、１日目の後半特に課題達成のドーパミンに惑わされて本来のペアプロの目的を見失っていた。

## その他
コーディングすべき内容を先にコメントして書いておくという工夫がされていた点は良かった！
完成した後のコードをレビューしただけだと気付かなかったと思う。

# さいごに
やり方を改善していってより良いものになるようにあがくためにも記録が大事。
と思うが苦手・・・いやがんばれよ。がんばる。と自分を励ます。
Pythonで時間計測

# Pythonで時間計測

処理毎の時間を計測したかったので自分用にメモ。

## timeモジュールを使う

```py:処理計測
from time import time  

start = time()
### Processes ###
end = time() - start
print(end)
```
`end`に処理の実行結果が格納されている。
`time()`は、*Unixtime*を浮動小数点で返す。

>参照
[https://docs.python.org/ja/3.5/library/time.html](https://docs.python.org/ja/3.5/library/time.html)
Androidのthemeにつけられた命名のメモ

Android Framework、AppCompat、MaterialComponentsには、たくさんのテーマが定義されています。
xml上で指定する際には全てのテーマがサジェストされるため、どれを使えばいいのかわかりづらいですね。

テーマにはいくつかの命名ルールがあり、ざっと知っておくことでどれを使えばよいか判断しやすくなるかもしれないので書き留めておきます。間違っているところがあればご指摘ください:pray:

## `Base`
例) `Base.Widget.AppCompat.Light.ActionBar`

Baseを取ったkeyのテーマのparentです。values-v17、values-v21といったバージョンごとに指定する属性が変わるので、親となるテーマを`Base.~`という命名で定義されています。**基本的に、アプリを作る時に`Base.~`のテーマを継承するシーンはないはずです。**

`Base.`がどのような依存関係でバージョン差異を補完しているかは、次の記事のグラフを見るとなんとなくわかると思います。 [AndroidのAppCompat Themeの継承関係がよくわからないので図にしてみた](https://qiita.com/takahirom/items/97f1bde4e89a6fe8ec7f)

## `ThemeOverlay`
例) `ThemeOverlay.AppCompat.ActionBar`

アプリケーション全体に指定しているテーマとは別に、ActionBarやダイアログといった各コンポーネントごとに指定する時に使います。例えば、ActionBarのbackgroundやtitleはアプリケーションで定義したテーマとは違うものにしたい場合に`actionBarTheme`に`ThemeOverlay.AppCompat.ActionBar`、`ThemeOverlay.AppCompat.Dark.ActionBar`を継承したテーマを指定します。

という話がAppCompatのauthorの1人でもあるChris Banesの[Theme vs Style](https://chris.banes.me/2014/11/12/theme-vs-style/)という記事にも書いてあるのですが、実際には`Widget.AppCompat.ActionBar`を継承する時と同じ属性を指定する必要があるので、いまいち使う理由がわかっていません。`ThemeOverlay.~`のテーマを使う必要がある理由がわかる方がいれば教えてほしいです。

## `DayNight`
例) `Theme.AppCompat.DayNight`, `Theme.AppCompat.DayNight.DialogWhenLarge`

`values-night`、`values-nonight`にそれぞれテーマを用意しておくことで日中・夜間で表示を切り替えたい時に使うテーマです。**DayNight対応しないのであれば指定することはないはずです（ダークモード対応とは違います）。**

詳しくは、次の記事を参考にしてください。 [SupportLibrary rev.23.2 で導入された DayNight テーマを使おう](https://qiita.com/KeithYokoma/items/811379a63eaa8cc1d144)

## `Light`、`Dark`
例) `Widget.AppCompat.Light.PopupMenu`, `ThemeOverlay.AppCompat.Dark.ActionBar`

Lightは**背景が明るい**テーマ、Darkは**背景が暗い**テーマです。
アプリケーションのテーマに指定するのはLightのテーマが多いのではないかと思います。文字色やその他の色は`textColor`や`colorPrimary`属性などで指定しましょう。
ActionBarやToolbar、BottomNavigationViewなどは、アプリケーションで定義したテーマのとは別のテーマを適用したくなることも多いと思います。テーマで設定できる属性は下記にまとまっているので、個別に指定できないか確認しましょう。

- [appcompat](https://github.com/aosp-mirror/platform_frameworks_support/blob/master/v7/appcompat/res/values/attrs.xml#L34-L395)
- [framework](https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/res/res/values/attrs.xml#L24)
- [materialcomponents](https://github.com/material-components/material-components-android/search?q=MaterialComponents&unscoped_q=MaterialComponents)

## `Inverse`
例) `TextAppearance.AppCompat.Widget.ActionMode.Title.Inverse`

Inverseなしのテーマと比べて**テキストやアイコンの色の明暗が逆**になっているテーマです。
【Unity】遠くの方を霧のような効果を表現するフォグ(Fog)の利用

環境メモ
⭐️Mac OS Mojave バージョン10.14
⭐️Unity 2018.2.15f1
⭐️Mac book

<font color="Magenta">遠くの方を霧のような効果を表現するフォグ(Fog)の利用する</font>
<img width="502" alt="スクリーンショット 2019-01-06 23.51.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/740217a8-3e2e-8b86-8dd7-9df5877f8f11.png">

1.「Windows」-「Rendering」-「Lighting Settings」を選択する
<img width="987" alt="スクリーンショット 2019-01-06 23.52.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/e22f6b22-2575-75b3-ad04-25aec9c62f9a.png">

2.「Scene」を選択する
<img width="554" alt="スクリーンショット 2019-01-06 23.53.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/3419f81f-48e5-4cd4-fa7d-945a6b996856.png">

3.「Other Settings」-「Fog」チェックONする
<img width="557" alt="スクリーンショット 2019-01-06 23.55.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/87127569-b75b-1bfe-46cd-21104593c8a3.png">

4.「Color」と「Destity」を設定する
<img width="564" alt="スクリーンショット 2019-01-06 23.59.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/503f3d9c-2c20-5610-bf41-d1c444e3e7e0.png">

詳細のプロパティはUnityマニュアル参照
https://docs.unity3d.com/ja/current/Manual/GlobalIllumination.html
<img width="1189" alt="スクリーンショット 2019-01-07 0.28.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/b55b04cb-4a8d-1416-cbdd-dd1ba695cf30.png">


完成！！
<img width="518" alt="スクリーンショット 2019-01-07 0.00.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/6ca89cc7-ab8a-0501-2e23-127b4fc95bd5.png">
</br>
</br>
</br>
</br>

#<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">【Unity】やっとVR用のゲームができました！！<br>シーンの遷移も、スマホにVR用の出力もできました！！<br>やった！！<br>v(≧∇≦)v イェェ～イ♪<a href="https://twitter.com/hashtag/unity?src=hash&amp;ref_src=twsrc%5Etfw">#unity</a> <a href="https://twitter.com/hashtag/unity3d?src=hash&amp;ref_src=twsrc%5Etfw">#unity3d</a> <a href="https://twitter.com/hashtag/VR?src=hash&amp;ref_src=twsrc%5Etfw">#VR</a> <a href="https://t.co/AEsbXdrnhX">pic.twitter.com/AEsbXdrnhX</a></p>&mdash; non (@nonnonkapibara) <a href="https://twitter.com/nonnonkapibara/status/1076511052043448320?ref_src=twsrc%5Etfw">2018年12月22日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>