OmniAICreator/Qiita-1.07M huggingface dataset:
sudo rm -rf / を実行してみた その２

# sudo rm -rf / を実行してみた　その2

何回やってんだよ！
いいから結果だけ教えろって人 → [結果](#結果)

## 前提
[その１](https://qiita.com/SHINE/items/6aee54456645dbf1f48e) では途中で実行停止しちゃったので何が消されて何が残ったのか分からない状態で終わってしまったので、今回はちゃんとそこら辺がわかるようにしたい。

## 実行環境
&emsp;実行環境はその１と同じ

**実行環境**
- `Host OS:` macOS Mojave Version 10.14.2
- `VM 管理:` VirtualBox Graphical User Interface Version 5.2.22 r126460 (Qt5.6.3)
- `Guest(VM) OS` CentOS7 x86 Minimal 18.10

## 予想
&emsp;流石に全部消えるなんてことは無いと思う。消えてもユーザディレクトリとか `tmp` とかだけじゃないかな？
だってねぇ... 全部消えたら立ち上がらないよねぇ...

## 実行
&emsp;実はあの後 `rm` コマンドについてちょっとヘルプを見てみた。
そしたら `--no-preserve-root` の使い方がちょっと違ったっぽい。
エラーは起きなかったけど、その１で実行したコマンドは間違ってたみたい。

```
正： sudo rm -rf --no-preserve-root *
誤： sudo rm -rf --no-preserve-root /
```

ということで実行してみようか！
<img width="722" alt="Screen Shot 2019-01-31 at 14.33.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/239391/24764f8f-322d-24c8-c3ab-7a2168374ae1.png">

## 結果
その１同様に大量に Permission denied 出たけど一応終わったっぽいな
<img width="721" alt="Screen Shot 2019-01-31 at 14.52.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/239391/140a374c-1e18-f25b-bba6-d62092c6a88a.png">

まぁね、残ってると思うけど見てみようか
<img width="720" alt="Screen Shot 2019-01-31 at 14.53.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/239391/d5548aaa-cdaa-286f-d2aa-106df81a7686.png">

え？あれ？今いるのってルートディレクトリじゃなかったっけ？
まぁいいや、ルートディレクトリのパスを指定してもう一回見てみようか
<img width="719" alt="Screen Shot 2019-01-31 at 14.53.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/239391/e3f25ec2-57c7-82df-0f44-ae5eaddafa3c.png">

wwwwwwwwwwwwwwww

え？待って？これ reboot したらどうなるんや？？
<img width="721" alt="Screen Shot 2019-01-31 at 14.54.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/239391/e058e609-cbd6-21dd-da0c-c0f0d5d35b0f.png">

あ、ふーん...（察し
仕方ないからxボタンで power off して再起動してみることにした。
<img width="722" alt="Screen Shot 2019-01-31 at 14.54.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/239391/7969fd77-75ad-1fec-603d-1b965bea70da.png">
grub の rescue mode で起動したw

## まとめ
&emsp;消えるもんは消えるんやなって... でも流石にメモリ内にいる最低限のプログラムは残ってるみたいね。まぁじゃないと起動できないしね。
それにしても結構簡単に消せることに驚きを隠せない。

以上、暇人による検証その２でした。

## 随時更新メモ
- 指摘されて気づいたが確かにこれは `ls` が消えただけっぽい。今度は `ls` だけどうにか入れ直して残されたファイルを見てみたいね
コンフリクトの起きているファイルだけを抜き出したい

```
git diff --name-only --diff-filter=U
```

`diff-filter`は便利。
下記にあるように、`U`以外も試してみてはいかがでしょうか。

>
**--diff-filter=[(A|C|D|M|R|T|U|X|B)…​[*]]**
Select only files that are Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, …​) changed (T), are Unmerged (U), are Unknown (X), or have had their pairing Broken (B). Any combination of the filter characters (including none) can be used. When * (All-or-none) is added to the combination, all paths are selected if there is any file that matches other criteria in the comparison; if there is no file that matches other criteria, nothing is selected.
Google Cloud Platformを使った便利な環境

Google Cloud Platform上に実験用環境を作った話。GitHubでvm作成用シェルスクリプトを公開している。

github: https://github.com/kanatatsu64/mkgc

# 使ったソフト

- BIND9
- OpenLDAP
- Kerberos5
- SSH
- OpenVPN

# 環境の概要

![result.png](https://qiita-image-store.s3.amazonaws.com/0/126131/5a641e8e-782c-ec14-737f-89da705990a6.png)


# 設定概要

## LDAP

- TLSの有効化

## Kerberos5

- LDAPをバックエンドに設定

## OpenVPN

- ローカルマシンをVPCに参加させる

## BIND9

- optionの設定
- zoneの設定
- dynamic dnsの有効化

\* DNSSECはまだ使っていない。

## sshd

- GSSAPI認証の有効化

## controller

- IP forwardingの有効化(既定では無効)
- firewallの設定
  - OpenVPNのtunとVPCのnicの間の通信を許可
  - それ以外のforwardは不許可

## vm

- SSHログイン用ユーザーの作成
- IP routingの設定
  - OpenVPNネットワークへの通信は、controllerを経由させる
- DNSの設定
  - DNSはcontroller上のBIND9を使う
- DDNSの設定
- Kerberosにhost principalを登録
- principalのkeytabをデフォルトkeytabに追加

## ローカルマシン

- sshのGSSAPI認証を有効化
- sshのデフォルトユーザーの設定
- IP routingの設定
  - VPCネットワークへの通信は、controllerを経由させる
- DNSの設定
  - DNSはcontroller上のBIND9を使う
- search domainの設定

# 最終形

まず、Google Cloud Platform上にvmを作る。

```shell
mkgc hoge # mkgcは自作コマンド
```

次に、SSHでアクセスする。

```shell
ssh hoge
```

以上。
価格設定と値引きと消費税計算

消費税計算の計算式処理の課題を検討するにあたって、日常的な価格設定、値引きとの関係を記録する。

#値引きシステム
顧客が店の人の印象が悪いと思ったら値引きしますというシステムを検討。

顔に出たら１割引にしますと書いておいて、２割増しの料金にしておく。

(1 * 1.2) * 0.9 = 1.08 

おお、2019年1月1日現在の消費税分が徴収できる。

１割増しだと値引きの方がおおきくなるため注意。

(1 * 1.1) * 0.9 = 0.99

#消費税システム構築の困難性

##　範囲

法律で定義している税金の対象範囲、納税義務者の範囲など、計算機で容易に定義できる対象であるかどうか。

例えば、都道府県がシステムを構築する場合に、すでに他の税制でデータが存在する対象者だけでよいか、それ以外もふくめなければならないか。

所得税、法人税のように、経費計上した場合に、その金額は、領収証などを発行した対象組織（個人）の収入となるため税務監査で確認可能である。消費税では、相手方の支出であるため経費計上していればよいが、個人等で経費計上していないと補足が難しいかもしれない。

消費税
http://elaws.e-gov.go.jp/search/elawsSearch/elaws_search/lsg0500/detail?lawId=363AC0000000108&openerCode=1

地方税法
http://elaws.e-gov.go.jp/search/elawsSearch/elaws_search/lsg0500/detail?lawId=325AC0000000226

```
（地方消費税に関する用語の意義）
第七十二条の七十七　地方消費税について、次の各号に掲げる用語の意義は、それぞれ当該各号に定めるところによる。
一　事業者　個人事業者（事業を行う個人をいう。次条第二項において同じ。）及び法人をいう。
二　譲渡割　消費税法第四十五条第一項第四号に掲げる消費税額を課税標準として課する地方消費税をいう。
三　貨物割　消費税法第四十七条第一項第二号に掲げる課税標準額に対する消費税額又は同法第五十条第二項の規定により徴収すべき消費税額（消費税に係る延滞税の額を含まないものとする。）を課税標準として課する地方消費税をいう。
```

##　他の制度との関係
他の税務制度、法律と独立した制度であれば、単独で解釈できる。
他の税務制度、法律を参照している仕組みであると、管轄官庁の解釈などを考慮しないとうまくいかないかもしれない。



ps.
常連の店と同じ気分になっている客は大事にするといいかどうかは不明。
ERC一覧(概要)

ERCの規格が多く名称を覚えられないので、よく聞くやつをメモがてら抜粋して概要をまとめました。

# ERC（Ethereum Request for Comment）とは
Ethereumにおける、トークン規格のようなコントラクトの実装を含むアプリケーションレベルの標準/規約のことを言います。
具体的には、EIP（Ethereum Improvement Proposal）として提案された改善案のうち、CategoryがERCとなっているものを指します。

# ERC概要一覧
下記リンクに全て載っています。
https://eips.ethereum.org/erc
有名どころを下記に軽くまとめておきます。

## ERC20: Token Standard
独自トークンを発行するための規格
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md

## ERC165: Standard Interface Detection
ERC20やER721など、どの規格に沿ってインターフェースが設計が実装されているかを認識できるようにする規格
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md

## ERC223: Token standard
ERC20を拡張した規格。
コントラクトアカウントに対するトークンの誤送金を防止する。
https://github.com/ethereum/EIPs/issues/223

## ERC721: Non-Fungible Token Standard
代替不可能トークン(Non-Fungible Token)を発行するための規格。
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md

## ERC725 & ERC735: Identity & Claim Holder
認証の規格。
第三者を介して外部のアカウント（FacebookやGIthub等）とアドレスを紐づけることで、
対象のアドレスが任意の外部アカウントで認証されているかどうかを検証できる。
ERC725とERC735と合わせて使用される。

- ERC725：アドレスとキーとなる情報を紐づける規格。(Identity)
- ERC735：任意のアドレスからの要求を、第三者が(もしくは自身で)管理する規格。(Claim Holder)

https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md
https://github.com/ethereum/EIPs/issues/735

## ERC1155: Multi Token Standard
ERC20とERC721の各トークンを同じ形式で複数管理するための規格。
コントラクト内でトークンを定義・発行できるため、マルチトークンプラットフォームとして機能する。
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md

## ERC1167: Minimal Proxy Contract
最小限のコードで安価に簡単にコントラクトをコピーするための規格。
全ての処理をコピー元コントラクトにdelegateCallする形のProxy Contractであるため、生成されるコントラクトは45バイトととても小さくなる。
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1167.md
【Type Script】Spread構文が使えない！？！？

## こういう

```ts
      notification: {
        title,
        body,
        ...payload,
      }
```

tscすると

```js
notification: __assign({ title: title,
                body: body }, payload),
```

Oops!

## tsconfigを編集するとええで
おそらくtsconfigのcompilerOptionsが`es5`になっている

```json
{
...
  "compilerOptions": {
    "target": "es5",
  }
...
}

```

Array以外のSpreadはes5では対応してない、既知のバグらしい。
https://github.com/Microsoft/TypeScript/issues/8856
![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/2d0a48ad-ba1e-57be-0eb6-139c16c9b35d.png)



これを`es6`にすれば一旦解決する。ただし、es6にtargetを変更して影響があるかはそれぞれの環境によると思うので、注意してほしい。

```diff
-    "target": "es5",
+    "target": "es6",
```


そしてtscすると

```js
notification: Object.assign({ title,
                body }, payload),
```

Object.assignになっていますね！
【React Native】KeyboardAwareScrollViewのTextInputでスクロールトップしちゃう

## 環境
- react-native@0.55.4
- react-native-keyboard-aware-scroll-view@0.7.0

## 事象
TextInputでfocusアウトすると、スクロールトップまで移動してしまう。

## 解決法
`enableResetScrollToCoords={false}`を使用する.

```jsx
      <KeyboardAwareScrollView
        enableResetScrollToCoords={false}
      >
```

https://github.com/APSL/react-native-keyboard-aware-scroll-view/issues/313#issuecomment-423864861
CircleCI2.0でtest.logをArtifactsに保存する

ローカルでは通るのにCircleCIで実行すると落ちるテストが稀にあります。
原因を調査するために`test.log`をArtifactsに保存できる方法がないか調べました。
# 保存方法
`.circleci/config.yml`でテストのrun設定の後に以下を記述するだけで出来ました！

```
      - store_artifacts:
          path: ./log/test.log
          destination: /tmp/test.log
```

# store_artifacts
CIの処理中に出来る成果物をAratifactsに保存できます。
CIのWeb上のビルド画面=>Aratifactsタブから見ることができます。

### path
保存したいファイルのパスを指定します。

### destination
Aratifacts内のどこに保存するか指定します。
destinationを書かなかった場合、元ファイルのパスと同じ場所に保存されます。
上記の場合、`/home/circleci/my_app/log/test.log`に保存されて、見るのが面倒なので指定しました。

# 備考
テストログをダウンロードして見ようとすると色も無く、文字が並んでいるだけで調査する気が失せるかと思います。
以下のようにすると色付きでログが見れます。

```
1. $less test.log
2. -rRと入力する
3. 色付きで表示✨
```
SmartGit > 32bit OS > v18.1.5が最終サポート?

```txt:動作環境
Windows 7 Pro (32bit)
SmartGit
```

SmartGitを32bit OS環境で使う方法は以下にて紹介されている。
https://www.syntevo.com/blog/?p=4558

v18.1.5ではこの方法は有効である。

v18.2.5には32bitの実行ファイルがないようなので、上記の方法は有効ではない。

32bit OS上ではv18.1.5がSmartGitの最終バージョンなのだろう。

Windows 7のEOL (End of Life)も2020年。
2020年に現在の開発環境(ドライバを含む）の64bit環境への移行は別途、検討しないといけない。

### 関連

- [2018-06-28 SmartGit > v18.1から64-bit化 | link > 32-bit対応方法](https://qiita.com/7of9/items/1372693011e4fb59fadb)
couldn't install aws-sam-cli on high sierra

I tried this first

```
brew install aws-sam-cli
```

error occured.

```
==> /usr/local/Cellar/aws-sam-cli/0.10.0/libexec/bin/pip install -v --no-binary :all: --ignore-installed /private/tmp/aws-sam-cli-20190131-18609
Last 15 lines from /Users/xxxxxxx/Library/Logs/Homebrew/aws-sam-cli/03.pip:
  Removing source in /private/tmp/pip-install-__gbtfov/PyYAML
  Removing source in /private/tmp/pip-install-__gbtfov/cookiecutter
  Removing source in /private/tmp/pip-install-__gbtfov/aws-sam-translator
  Removing source in /private/tmp/pip-install-__gbtfov/docker
  Removing source in /private/tmp/pip-install-__gbtfov/dateparser
  Removing source in /private/tmp/pip-install-__gbtfov/python-dateutil
  Removing source in /private/tmp/pip-install-__gbtfov/requests
  Removing source in /private/tmp/pip-install-__gbtfov/aws-lambda-builders
  Removing source in /private/tmp/pip-install-__gbtfov/serverlessrepo
  Removing source in /private/tmp/pip-install-__gbtfov/Werkzeug
  Removing source in /private/tmp/pip-install-__gbtfov/Jinja2
  Removing source in /private/tmp/pip-install-__gbtfov/itsdangerous
  Removing source in /private/tmp/pip-install-__gbtfov/botocore
Removed botocore<1.13.0,>=1.12.86 from https://files.pythonhosted.org/packages/8e/b3/b9f7ffa347057fa44c65197864eec6a8a53f5a24f613b1b7b3f2b755cc65/botocore-1.12.86.tar.gz#sha256=24444e7580f0114c3e9fff5d2032c6f0cfbf88691b1be3ba27c6922507a902ec (from boto3>=1.9.56,~=1.9->aws-sam-cli==0.10.0) from build tracker '/private/tmp/pip-req-tracker-w_xk82fh'
Removed build tracker '/private/tmp/pip-req-tracker-w_xk82fh'

If reporting this issue please do so at (not Homebrew/brew or Homebrew/core):
https://github.com/aws/homebrew-tap/issues
```

So I tried another option:

```
pip install aws-sam-cli
```

error occured again. the error message said like this.

```
python setup.py egg_info failed with error code 1
```

```
pip install --upgrade setuptools --user python
pip install cython --user python
```

after that, I tried again.

```
sudo pip install aws-sam-cli
```

error occured again.

```
Cannot uninstall 'six'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.
```

```
sudo pip install aws-sam-cli --ignore-installed six
```

success..
WordPressではjQueryの$()が使えないことを初めて知った

みんな知っていると思うけど、
私は今さら知った。恥ずかしい。

PC上では動作するのにスマホが反応しない…。
こんなこと初めてで数時間無駄にしてしまった。

##WordPressでは反応しない書き方
```
$(function(){
  // jQuery書く
});
```

##正解の書き方
```
jQuery(function(){
 // jQuery書く（この中は$で書いてオッケイ）
});
```

以上。初めての投稿は恥ずかしい体験から始まる。
CollectionViewで中央寄せを実現する

# 概要
iOSにおけるCollectionViewは、通常左詰めでCellがレイアウトされます。
本記事では `UICollectionViewDelegateFlowLayout` を利用して、CollectionViewの中央にCellを配置する方法を紹介します。

# やりたいこと

##### 中央寄せレイアウト(ゴール)

|![center1.png](https://qiita-image-store.s3.amazonaws.com/0/165931/6f93aa06-2f54-3672-cadf-e9ec4d044787.png)|
|:-:|

|![center2.png](https://qiita-image-store.s3.amazonaws.com/0/165931/081f086d-3dc4-8c64-a272-f213c65b70fa.png)|
|:-:|

|![center3.png](https://qiita-image-store.s3.amazonaws.com/0/165931/e102c798-fe9d-d02d-011e-465ce997121e.png)|
|:-:|

##### 通常のレイアウト(参考)

|![left1.png](https://qiita-image-store.s3.amazonaws.com/0/165931/faf52160-287d-2e14-474b-ba259d3575b8.png)|
|:-:|

|![left2.png](https://qiita-image-store.s3.amazonaws.com/0/165931/b1d9b1ea-44dd-5931-21ea-bcc7d8d7962a.png)|
|:-:|


# 実装
CollectionViewには、セルのsize、spacing、insetなどを設定するための`UICollectionViewDelegateFlowLayout`というプロトコルが存在します。
今回はInsetを設定することで中央寄せを実現します。
基本の`UICollectionViewDelegate`や`UICollectionViewDataSource`と合わせて、上記の実装を組み込むだけで中央寄せを実現することが出来ます。

```swift
extension UIViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
        let cellWidth = Int(flowLayout.itemSize.width)
        let cellSpacing = Int(flowLayout.minimumInteritemSpacing)
        let cellCount = Your Cell Count

        let totalCellWidth = cellWidth * cellCount
        let totalSpacingWidth = cellSpacing * (cellCount - 1)

        let inset = (collectionView.bounds.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2

        return UIEdgeInsets(top: 0, left: inset, bottom: 0, right: inset)
    }
}
```

# 参考
`UICollectionViewDelegateFlowLayout`
https://developer.apple.com/documentation/uikit/uicollectionviewdelegateflowlayout
VSCodeとVetur（TypeScript）でexperimentalDecoratorsの警告が消えない

# 色々やってみた結果
解決できませんでした

2019/02/16
解決しました！

# 概要
VSCode + VeturでVue.jsの開発。
experimentalDecoratorsをtrueにしているのに以下のエラーが消えない。

```
Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning.
```
### スクショ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/93814/3aa36fda-4550-856b-7b95-498f3d5ffcb7.png)

# やったこと
### tsconfig.json の experimentalDecorators をtrue
```json:tsconfig.json
{
  "compilerOptions": {
    "experimentalDecorators": true,
    "allowJs": true,
  }
}
```
だめ

### setting の Javascript › Implicit Project Config: Experimental Decorators を true
![image.png](https://qiita-image-store.s3.amazonaws.com/0/93814/5f3a9f0e-f55a-2a51-d9c9-6725a5b08dcd.png)
だめ

### jsconfig.jsonを置いてみる

https://github.com/Microsoft/vscode/issues/28097#issuecomment-306560817
>To fix it, please try creating a jsconfig.json file at the root of your project with the contents:

```json:jsconfig.json
{
  "compilerOptions": {
      "experimentalDecorators": true
  }
}
```

だめ

# 結論
コンパイルが通らないとかそういうことはないので問題ないっちゃないんですが、うっとおしい。
Veturのバグですかね。。。

諦めてVueはAtomか何かで開発するか

# 追記 2019/02/16
解決しました！
ワークスペースでプロジェクトのフォルダを追加していたのですが、
これをファイル -> 開くでプロジェクトのフォルダを直接開いたらエラーが出なくなりました。

@rema424 さん、ありがとうございました！
Azure CloudShellって何よ

話題に出たので調べてみました

Azure Cloud Shell とはAzure リソースを管理するためシェルで、Bash・PowerShellを選択して使うことができる。

当然Azureのポータルから実行することができる
ポータル右上にボタンがあるのでポチっとする
![azurecloudshell_01.png](https://qiita-image-store.s3.amazonaws.com/0/313446/4aa4b1ea-72f4-072e-6182-5f7fb65a6f95.png)
でもVisualStudioCode経由で実行したほうが便利(個人的見解)

### 仕組み
実行するときCloudShell用マシンが立ち上がります
ファイルを永続化するために、新規または既存のAzureFiles共有をclouddriveとしてマウントする必要があります。

CloudShell の初回起動時にリソースグループ、ストレージアカウント、Azure Files共有を作成するように求められます。
これは初回のみの作業で、それ以降は自動的に接続されます。
1つのファイル共有をマップするとBashとPowerShellの両方で使われます。
![azurecloudshell_02.png](https://qiita-image-store.s3.amazonaws.com/0/313446/206c2f07-9109-15b7-963d-3abf85255423.png)

このマシンは無料ですが、Azure Files共有をマウントすることが前提
(ただしAzureFilesは有料、とはいえ容量的には5GBのイメージプラスアルファ程度)
既存のストレージアカウントを設定することも可能
(ただしCloudShellが利用できるリージョンのみ)
![azurecloudshell_03.png](https://qiita-image-store.s3.amazonaws.com/0/313446/6d71039a-7d87-1136-c41a-3ec85a777e62.png)

新規の場合はこんな感じで専用のストレージアカウントが自動的に作られます
最寄りの利用可能なリージョンが自動的に選択されます
![azurecloudshell_04.png](https://qiita-image-store.s3.amazonaws.com/0/313446/32e55ba7-cfb5-6142-6db6-1954493a56a3.png)

ちなみにCloudShellが使えるリージョンは下記の通り

| 領域 |リージョン|
| ------------ | -------------------------- |
| アメリカ合衆国 | 米国東部、米国中南部、米国西部 |
| ヨーロッパ | 北ヨーロッパ、西ヨーロッパ |
| アジア太平洋 | インド中部、東南アジア|


### 何ができるの？

・AnsibleやTerraformに対応しているので構成管理が楽
　VisualStudioCodeから実行できる
  →わざわざ構成管理用サーバを立てる必要がない
　→AzureDevOpsと連携して、構成情報をGitHub上で管理してDeployできるので、わざわざポータル入らなくてもサーバ管理がほぼできてしまう

この辺りは次回書きたいと思います
そうだ、AWS Loft Tokyo に行こう

2018年10月に目黒駅前にオープンたAmazonのコワーキングスペース[『AWS Loft Tokyo』](https://aws.amazon.com/jp/start-ups/loft/tokyo/)の紹介をしたいと思います。

**平日のみで土日はやっていないので注意してください!**

# AWS Loft Tokyo
AWS Loft は、AWS を利用中のスタートアップおよびデベロッパーのための施設です。

内容としてはコ・ワーキングスペース、セミナーやイベント、AWSのソリューションアーキテクトやサポートエンジニアへいつでも技術的な相談が可能な**「Ask An Expert カウンター」**があります。

私はコ・ワーキングスペースのみ利用していますが、「Ask An Expert カウンター」も利用してみたいなと思います。中の人と対面で話せる機会ってなかなかないですもんね。しかも無料。

*フロアの様子*
<img src="https://d1.awsstatic.com/Startups/Loft%20Photos/tokyo/photo6.0851f9d9db5876b99ac9b7a8dc6adcba15f0f638.jpg" width="70%"> 

## 営業時間、アクセス

営業時間とアクセスは以下の通りです。目黒駅から超近いのでとても便利。

- **オフィス**  : アマゾン新目黒オフィス（目黒セントラルスクエア）17F
- **住所**     : 東京都品川区上大崎 3-1-1
- **アクセス**  : JR 山手線「目黒駅」より徒歩1分
- **営業時間** : 平日（月〜金） 10:00〜18:00（最終受付 17:30）

*Code Happy!*
<img src="https://d1.awsstatic.com/Startups/Loft%20Photos/tokyo/photo1.6e7e95c295419b568e85b5fdbe787bc21ef95104.jpg" width="70%"> 

## ランチ
実は僕は最寄りが目黒駅で、AWS Loftから徒歩五分くらいの所に住んでます。
ですのでついでにオススメのランチスポットも教えます。
全てAWS Loftから近いですよ。
**さあ、Let's 孤独のグルメ**

### [麺や維新](https://tabelog.com/tokyo/A1316/A131601/13161626/)
麺がトゥルトゥル。ワンタンもトゥルトゥル。澄んだスープ。柔らかいチャーシュー。
喉越しにハマるあっさりラーメン、オススメ。
AWS Loftに行ったら絶対に行くべき。

### [蒙古タンメン中本 目黒店](https://tabelog.com/tokyo/A1316/A131601/13013957/)
ラーメンの上に麻婆豆腐的な何かを乗っけた激辛ラーメン。
目黒店は店員さんも親切で味もとても美味しいです。人気店なので行列もしばしば。
仕事残ってるなら北極にするのはやめとけ。

### [麺屋一寸星](https://tabelog.com/tokyo/A1316/A131601/13189651/)
少し珍しい台湾まぜそばのお店。胃袋にガッツリきます。
ぐちゃぐちゃに混ぜた時の卵と絡んだ麺の美味さがまさに犯罪的。
口臭が大変なことになるのでミンティア必須。

### [麺屋　藤しろ](https://tabelog.com/tokyo/A1316/A131601/13143426/)
あっさりしてるのに濃厚、欲張り鶏白湯スープのラーメン。
テーブルセットによる味の可変を楽しめるのも良い。
日曜営業も目黒では少ないので嬉しいポイント。

### [こんぴら茶屋](https://tabelog.com/tokyo/A1316/A131601/13013189/)
カレーうどんの概念が崩れる。牛肉使ってるけど変にクセがない。
お店の前を通ると尋常じゃないくらい美味しそうな匂いを漂わせてる。
値段は少し高いけど後悔はしません。

### [ラクシュミー](https://tabelog.com/tokyo/A1316/A131601/13019575/)
麺ものばっかなんでご飯ものも紹介しとく。
ここのプラウンカレーの美味さは犯罪。あと店主の物腰がすごい柔かい。
雑居ビルの中で少し怖いけど是非とも行ってほしい。

# 準備
さあ、**AWS Loft Tokyo**と目黒駅周辺のラーメン屋の魅力が分かった所で早速利用してみよう。
念のため言いますが、**Amazonプライムのアカウントでは入れない**ので注意してください。以前、知人で勘違いしてる人がいたため一応。

- AWSアカウント : AWSを利用するためのアカウントです。アカウントを有効にするところまでで大丈夫です。また1年間は無料で付与される利用枠と、特定のサービスで定常的に付与される無料枠があるので安心してください。**行く前に必ず作っておくこと**。
- 身分証明書 : 運転免許証でいいです。

初回のみ受付カウンターで職業など個人情報を入力しなければならないですが、2回目以降は受付でメアドを入力するとシールが発行されて、そのシールを胸につけてAWS Loftを利用する形になります。

*受付*
<img src="https://d1.awsstatic.com/Startups/Loft%20Photos/tokyo/photo2.12f9cea6983c9196bf70b65bc2670c1529f40ce3.jpg" width="70%">

# 設備
ここからはAWS Loft Tokyoの設備ついて紹介していきます。
設備も充実してるので余裕で一日入れます。快適、快適。

## カフェ
コ・ワーキングスペース内にカフェが併設されています。パンやお菓子などの簡単な軽食もありますよ。
因みにお値段は、コーヒー(hot/ice)が100円、ラージサイズでも150円なので安いです。
だいたいラージサイズのコーヒーで1日もつ。

*右奥がカフェ*
<img src="https://d1.awsstatic.com/Startups/Loft%20Photos/tokyo/photo3.e3373c94f32cd00d798da18d8d446fbc05295453.jpg" width="70%">

## Wi-Fi
もちろんあります。早いです。
passはシールに記載してあります。

## 自販機
基本的に90円(なぜ90円？)くらい。
ドクターペッパーがあります。分かってらっしゃる。
自販機の隣には**ゴミ箱、電子レンジ、ウォーターサーバー**もあります。

## 要望板
カフェの隣のホワイトボードにAWS Loftの要望を書くことができます。
軽食増やして〜とか、時間延長して〜とか。
しばらくするとAmazonの人がコメントしてくれてます。
住みたいって要望にダメですってコメントが笑えた。

# まとめ
いかがでしたでしょうか？
おそらくAWS Loft Tokyoに遊びに行きたくなったでしょう。
そんなにガヤガヤしていないので本当に快適です。
休日もやってるので仕事以外でプログラミングしたいって人も、これからはスタバじゃなくてAWS Loft Tokyoに行きましょう。
テンプレート実行時に部分文字列を指定してクエリを動的に生成する


BigQueryのSQLをテンプレート実行時に部分文字列を渡して完全に生成したいときのTipsです。
例えば日付分割されたテーブルから、日付をテンプレート実行時に範囲指定したいときに利用します。
これは[NestedValueProvider を使用する - 公式ドキュメント -> テンプレートの作成](https://cloud.google.com/dataflow/docs/templates/creating-templates?hl=ja#nestedvalueprovider-)における、

> 例 2: ユーザーが BigQuery クエリに部分文字列（特定の日付など）を指定します。変換では部分文字列を使用して完全なクエリを作成します。.get() を呼び出すと、完全なクエリが返されます。

に該当します。

```java

public interface MyOptions extends DataflowPipelineOptions {
    ValueProvider<String> getDateRange();
    void setDateRange(ValueProvier<String> value);
}

public static void main(String[] args) {

    MyOptions options =
        PipelineOptionsFactory.fromArgs(args).as(MyOptions.class);
    options.setRunnner(DataflowRunner.class);
    options.setTemplateLocation("gs://<BUCKET_NAME>/<TEMPLATE_PATH>");
    // options.set...

    Pipeline p = Pipeline.create(options);

    p.apply(BigQueryIO.readTableRows()
            .fromQuery(
                NestedValueProvider.of(
                    options.getDateRange(), new SerializableFunction<String, String>() {
                            @Override
                            public String apply(String range) {
                                String[] parts = range.split("_", 2);
                                String sql = "SELECT max FROM `bigquery-public-data.noaa_gsod.gsod*`"
                                    + " WHERE max != 9999.9 AND _TABLE_SUFFIX BETWEEN '"
                                    + parts[0] + "' AND '"
                                    + parts[1] + "' ORDER BY max DESC";
                                return sql;
                            }
                        }))
            .usingStandardSql()
            .withTemplateCompatibility()
            .withoutValidation())
        // .apply()...
```

コンパイル(テンプレートの作成)

```sh
mvn compile exec:java -Dexec.mainClass=<HOGEHOGEHOGE>
```

例えば、テンプレートの実行時に、1994年から2001年分をスキャンしたいときは、
`--parameters dateRange=1994_2001` を付与します。

```sh
gcloud dataflow jobs run jobname --gcs-location gs://<BUCKET_NAME>/<TEMPLATE_PATH> --parameters dateRange=1994_2001
```
Nuxt.js + SkyWayを使ってWebRTCを実装

WebRTCはブラウザ同士で直接動画や音声などのリアルタイムなコミュニケーションを実現するAPIの定義になります。基本的にはICEサーバーを使って自分の情報を取得し、相手のブラウザにそれを認識させる事によってブラウザ同士の通信を実現します。

## WebRTCの仕組み

WebRTCでは**ICEサーバー**という特殊なサーバーを用います。ブラウザ同士の通信にはNATがあるため、ICEサーバーを使ってこの問題を解決します。ICEサーバーにはSTUN、TURNというものがあります。
Googleなども無料でSTUNを公開していますが、今回はSkyWayを使うので、そこはあまり意識しなくてもいいかもしれません。

ICEサーバーでは自分の情報を取得することができます。
そしてその取得した情報を相手に伝えないといけません。

その情報を相手に伝える為に**シグナリングサーバー**というサーバーを使います。
このサーバーは相手に情報を教えてあげる仲介をしてくれます。
自分は**Node.js + socket.io**で実装しました。

> 実際にはシグナリングサーバーは必須ではありません。
> 例えば自分のIDを相手にメールやチャットなどで伝える事で自分のブラウザへ入力する事で通信を開始する事ができます。

## 実際にシグナリングさせる


### 実装

今回はNuxt.jsを用いて実装しました。
ソースコードは長くなってしまうので抜粋しています。
挙動としては、発信側が通信を開始し、受信側が承認することで開始するイメージです。

#### server
```js

  const io = socketio.listen(server)

  io.on('connection', socket => {
    socket.on('send peer id', id => {
      io.emit('emit peer id', id)
    })

    socket.on('answer peer id', id => {
      io.emit('answer peer id', id)
    })

    socket.on('disconnect', () => {
      console.log('disconnected')
    })
  })
```

#### cliant（発信側）

```js
  async created() {
    this.company = services.find(
      service => service.slug === this.$route.params.company
    )
    this.inquiry = this.$route.params.inquiry || 'hoge'
    const constraints = { audio: true, video: true }
    const stream = await navigator.mediaDevices.getUserMedia(constraints)
    this.user.stream = stream
  },
  mounted() {
    this.socket = io()
    this.socket.on('answer peer id', id => {
      this.peer.call(id, this.user.stream)
    })

    this.peer = new Peer({
      key: this.APIKey,
      debug: 3
    })

    this.peer.on('call', call => {
      call.answer(this.user.stream)
      call.on('stream', stream => {
        this.operatorStream = stream
        const el = document.getElementById('video1')
        el.srcObject = stream
        el.play()
      })
    })
  },
  methods: {
    call() {
      this.socket.emit('send peer id', this.peer.id)
    }
  }
```

#### cliant（受信側）

```js

  async created() {
    const constraints = { audio: true, video: true }
    const stream = await navigator.mediaDevices.getUserMedia(constraints)
    this.localStream = stream
  },
  mounted() {
    this.socket = io()
    this.socket.on('emit peer id', id => this.user.id = id)

    this.peer = new Peer({
      key: this.APIKey,
      debug: 3
    })

    this.peer.on('call', call => {
      call.answer(this.localStream)
      call.on('stream', stream => {
        this.userStream = stream
        const el = document.getElementById('videoUser')
        el.srcObject = stream
        el.play()
      })
    })
  },
  methods: {
    answered() {
      const call = this.peer.call(this.user.id , this.localStream);
      call.on('stream', stream => {
        this.socket.emit('answer peer id', this.peer.id)
      });
    },
  },
```

videoタグを`refs`で取得て`srcObject`に入れたかったのですが、うまく取得できなかったので`id`で取得しています。その他にもtemplateで`<video :srcObject='stream'>`もやってみましたがダメでした。

## 最後に
WebRTCを取り扱うのであれば、今回のようなSkyWayやPeer.jsを使うと簡単に実現できます。
実運用を考えるとSTUNサーバーを自前で用意したり、フロントエンドの技術だけではまかないきれない部分も出て来ますが、試してみるにはよいのではと思います。（有料プランもありだと思います）
事前確立、事後確率、尤度、周辺確立（メモ）

例えば、二つの袋A、Bの中に、
それぞれいくつかずつ赤と白のボールが入っていて、
そこからボールを取り出す。


事前確立P(A) = Aの袋を選ぶ確立
事後確率P(A|赤) = 取り出したボールが赤の時、袋Aから出た確率
尤度P(赤|A) = 袋Aから取り出した時、ボールが赤の確立
周辺確立P(赤) = 取り出したボールが赤の確立



事前確立とか事後確率とか尤度とか、
ちゃんとした説明はたくさんあるけど、
数式とか多くてまどろっこしい。

この事後確率が最も大きいクラスに
データを分類するのが
ベイズの識別規則。

あくまでメモ程度に。
pythonのdictのキーの順番の話

# Overview

python 3.6 未満だとdictがキーの序列を保持しないので、 `items()` で取り出すと順番が不定になる。

というのを知らない、あるいは意識してない人が結構多いみたいなので、
現象と再現の方法を書いておきます。

ちなみに 3.7 からは[言語仕様で順序が保証される](https://docs.python.org/3/whatsnew/3.7.html) ようになってます。
＃ 実装レベルではたぶん 3.6 でもなってると思う（出典忘れた）

# 環境

```bash
$ python -V
Python 2.7.15
```

2.7 で試してますが、 3.6 未満だと同じ結果になると思います。
＃ キーの順番自体は変わるはず

# サンプルデータ

適当なdictが見当たらないので、 [swagger](https://petstore.swagger.io/)のサンプル使います。

```bash
$ wget https://petstore.swagger.io/v2/swagger.json

$ jq '.|keys' swagger.json
[
  "basePath",
  "definitions",
  "externalDocs",
  "host",
  "info",
  "paths",
  "schemes",
  "securityDefinitions",
  "swagger",
  "tags"
]
```


# hashのseed値

`hash()` のシード値は環境変数の `PYTHONHASHSEED` の値を参照しており、この値を変えると、

```bash
$ PYTHONHASHSEED=123 python -c "print(hash('hoge'))"
-7331607872126641601

$ PYTHONHASHSEED=12345 python -c "print(hash('hoge'))"
5740883211462535735
```

同じ値でもhash値が変わります。

# dictの items() メソッド

dictのキーも `hash()` の値に依るので、

```a.py
import json

with open("swagger.json") as fp:
    a = json.load(fp)

for k, v in a.items():
    print(k)
```

こんな感じで試すと、

### ex1

```bash
$ PYTHONHASHSEED=123 python a.py
basePath
swagger
externalDocs
info
host
schemes
definitions
securityDefinitions
paths
tags
```

### ex2

```bash
$ PYTHONHASHSEED=12345 python a.py
host
definitions
swagger
externalDocs
info
paths
schemes
tags
basePath
securityDefinitions
```

という感じになります。

再現させたい時は `PYTHONHASHSEED` の値を固定すると良いでしょう。

# 回避方法

3.6未満のdictのキーに序列の保持を期待する場合は [OrderedDict](https://docs.python.jp/3/library/collections.html#collections.OrderedDict) を使いましょう。

# 余談1: python 3.6 の場合

キーの順序が保持されてます。

```bash
$ python -V
Python 3.6.8

$ PYTHONHASHSEED=123 python a.py
swagger
info
host
basePath
tags
schemes
paths
securityDefinitions
definitions
externalDocs

$ PYTHONHASHSEED=12345 python a.py
swagger
info
host
basePath
tags
schemes
paths
securityDefinitions
definitions
externalDocs
```

# 余談2: random の seed

ちなみに `random` の seed はまた別なので、
これを固定したい場合は別途 `random.seed()` で指定する必要があります。

```bash:PYTHONHASHSEEDを指定してもseedの値が同じだと変わらないの図
$ PYTHONHASHSEED=123 python -c "import random; random.seed(42); print(random.random())"
0.639426798458

$ PYTHONHASHSEED=12345 python -c "import random; random.seed(42); print(random.random())"
0.639426798458
```

## cf.

https://qiita.com/okotaku/items/8d682a11d8f2370684c9

おわり。
プッシュ遷移,モーダル遷移の区別


# はじめに
こんにちは！Ayumuです。私はこれまでプッシュ遷移、モーダル遷移をどのように使い分けるべきか分からず、遷移の目的を意識せずに使っていました。（私の場合はモーダル遷移を一切使わずプッシュ遷移だけを行なっていました...)
今回はそれぞれの遷移方法の扱いについて共有させて頂きます。
間違いがありましたら指摘して頂けると幸いです。


#プッシュ遷移
プッシュ遷移は、ある目的までの移動手段に用います。
ここではiPhoneの設定画面を具体例に説明します。<img width="793" alt="スクリーンショット 2019-01-31 10.42.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/282860/9eeff383-e213-e2f2-50d8-f8056b99334b.png">
この写真はiPhoneの壁紙を変更している図です。
この図のシーンにおいての目的は壁紙を変更することです。壁紙を変更することができるページに行くまでの移動手段としてプッシュ遷移が用いられています。

注意しておきたい点として、あくまでプッシュ遷移はスタート地点から目的地点までの移動であり、ある地点で前のページに戻ったからといって、そこで行われた行動が取れ消されるというわけではありません。

#モーダル遷移
<img width="960" alt="スクリーンショット 2019-01-31 10.42.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/282860/47cccb3b-447d-17d2-d73c-f8c048fad340.png">
モーダル遷移は一時的に画面を表示させるものです。プッシュ遷移の移動の中で一時的に分岐して別の画面を表示させるものです。
プッシュ遷移にある写真の続きです。
プッシュ遷移で壁紙を変更することができるページまで移動してきました。（写真の一番左）
あとは画像を選ぶだけです！

ここでモーダル遷移の出番です。
プッシュ遷移はあくまで目的を果たすことができるページにまで移動しただけであり、そこから何か新たなアクションを起こす場合には新たに分岐して別画面に移動してあげる必要があります。

写真の場合、壁紙を変更できるページでユーザーが写真を選択し、壁紙を変更するという決定を行う際にモーダルが表示されています。(写真左から２番目)
ユーザーの決定が済んだあとは再び移動地点に戻る必要があります。（写真左から3番目)
#結論
プッシュ遷移でタスクを進行
モーダル遷移でタスクを補完するために分岐


#最後に
拙い文章で申し訳ありません。
https://qiita.com/usagimaru/items/9b55daa4d88b0bb98f38
こちらの記事を見て遷移の違いを知り、自分自身でも共有したいと思い記事を投稿させて頂きました。とても分かりやすかったので是非ご覧ください！
[python3] 簡易サーバでJSONデータ受け渡し　[POST]

## やりたいこと
python3にて簡単なサーバを立ててJsonでデータを受け渡ししたいだけ。

では始めます。

## ソース

```server.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import http.server as s
import json

class MyHandler(s.BaseHTTPRequestHandler):
    def do_POST(self):

        # リクエスト取得
        content_len  = int(self.headers.get("content-length"))
        body = json.loads(self.rfile.read(content_len).decode('utf-8'))

        # レスポンス処理
        body["answer"] = "晴れです。"
        self.send_response(200)
        self.send_header('Content-type', 'application/json;charset=utf-8')
        self.end_headers()
        body_json = json.dumps(body, sort_keys=False, indent=4, ensure_ascii=False) 
        self.wfile.write(body_json.encode("utf-8"))

# サーバ起動
host = '0.0.0.0'
port = 3333
httpd = s.HTTPServer((host, port), MyHandler)
httpd.serve_forever()
```

## 実行
```
$ ./server.py 
```

## クエリ発行
```
$ curl -XPOST 'http://localhost:3333/test' -d '{ "question": "今日の天気は" }'
{
    "question": "今日の天気は",
    "answer": "晴れです。"
}
```
SPSS Modelerで入出力のファイルパスを一括変更する

SPSS Modelerで他の人からもらったストリームを実行するときにファイルパスが違って実行ができないことがあると思います。
１、２ファイルであれば書き換えても大きな手間ではありませんが、たくさんのファイルを使っている場合は大変です。
そこで入出力のファイルパスを一括変更するpythonスクリプトを書きました。

#1 pythonスクリプト

```python:changepath.py
import modeler.api

oldpath =u'C:\\Program Files\\IBM\\SPSS\\Modeler\\18.1\\Demos\\japanese_ja\\bankloan.sav'
newpath =u'C:\\Program Files\\IBM\\SPSS\\Modeler\\18.2\\Demos\\japanese_ja\\bankloan.sav'

stream = modeler.script.stream()

for node in stream.iterator():
    if (node.getTypeName() == "variablefile"
        or node.getTypeName() == "excelimport"
        or node.getTypeName() == "statisticsimport"
        or node.getTypeName() == "outputfile"
        or node.getTypeName() == "excelexport"
        or node.getTypeName() == "statisticsexport"):
        full_filename=node.getPropertyValue("full_filename")
        full_filename=full_filename.replace(oldpath,newpath)
        print full_filename
        node.setPropertyValue("full_filename",full_filename)
```


oldpath とnewhpathのところに変更したい旧パスと新パスを指定すればOKです。

* パス名のディレクトリの区切りに\（バックスラッシュ。日本語Windows上だと￥マーク）を使う場合は、上の例のように\\\のように二つ重ねてエスケープしてください。
* パス名のディレクトリの区切りには/(スラッシュ)を使うこともできます。この場合はエスケープの必要はありません。Mac版やLinuxのサーバーで使っている場合は/が使われています。
* シングルクォーテーションの前のuを忘れると日本語の入ったファイルパスで失敗します。
* 可変長ファイル、Excelファイル、Statisticsファイルに対応しています。他の形式にも対応したい場合はif (node.getTypeName() == "variablefile"の部分に追加してください。

#2　実行例
18.1のデモディレクトリから18.2のデモディレクトリに変更します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/223763/97111108-d420-a62b-a812-0e833de5f657.png)

ストリームのスクリプトに上のスクリプトをコピーペーストして、oldpath とnewhpathを変更します。そして、「このスクリプトを実行」ボタンをクリックします。
デバッグの欄に変更したパスを表示します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223763/2c792aea-f24e-bace-7d41-6cf721c7f444.png)

以下のように変更されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223763/3dcd764d-d773-bf89-7070-f366a7767a0c.png)

#3 おまけ

* チームでストリームを共有するときには以下の「ディレクトリの設定」「サーバーディレクトリの設定」の機能で上位パスをそろえておいて、相対パスで指定するか、環境変数などをつかって同じファイルパスで指定するようにしておくことをお勧めします。上のスクリプトを毎回実行するのは大変なので。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223763/2b08f6c2-c6ba-9841-cf33-d04265fa2ea3.png)


* 実行例では製品のデモデータのパスのバージョン部分を変更しましたが、デモデータをつかったストリームを他のバージョンでも読めるようにするには$CLEO_DEMOS環境変数を使ったほうがよいです。以下の指定だとバージョンが変わってもパスの変更の必要がありません。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223763/3e7b7c59-bbb4-5e68-0937-a920e8006de5.png)

#テストした環境
汎用的に動くと思いますが、テストしたの以下の環境です
SPSS Modeler 18.1.1
Windows 10 64bit
VRカメラのポジショントラッキングを制限する

## 経緯
乗り物系のVRでプレイヤーのコクピットにHeadの位置を固定したい、ただしある程度の自由度( 移動 )は入れておきたい...というワガママな要求を実現するために色々調べた。

## スクリプト

ほぼ参考資料のコピペ


```csharp
using UnityEngine;
   
   
namespace sample
{
   public class CameraController : MonoBehaviour
   {
       [SerializeField] Transform offset;
       [SerializeField] Transform head;
       [SerializeField] float movableRadius = 0.3f;

       void LateUpdate()
       {
           if (movableRadius < Vector3.Distance(offset.position, head.position))
           {
               Vector3 trackingPos = head.localPosition;
               Vector3 scale = transform.localScale;
               trackingPos = new Vector3(
                   trackingPos.x * scale.x,
                   trackingPos.y * scale.y,
                   trackingPos.z * scale.z
               );

               // 回転.
               trackingPos = transform.rotation * trackingPos;

               // 固定したい位置から hmd の位置を.
               // 差し引いて実質 hmd の移動を無効化する.
               transform.position = Vector3.Lerp(transform.position,offset.position - trackingPos, 0.05f);
           }
       }


       void OnDrawGizmosSelected()
       {
           Gizmos.color = Color.red;
           Gizmos.DrawWireSphere(offset.position, movableRadius);
       }
   }
}
```

**スクリプト修正**
コクピットが移動した後にカメラ位置を調整する必要があるため Update()での処理をLateUpdate()での処理に修正
あるいは ProjectSettings > ScriptExecutionOrder で呼び出し順を通常のUpdate()の後に呼ばれるようにしてもいいかも...


**パラメータ解説**
offset : 基準となる座標
head : 実際にHeadのトラッキングを取得するオブジェクト
movableRadius : 移動可能な距離


![image.png](https://qiita-image-store.s3.amazonaws.com/0/212999/803bc346-6a07-8055-5c78-ec3d25dc4bf9.png)
SteamVRのサンプルの中にあるPlayerプレハブを流用、SteamVRObjects( CameraRig )に上記スクリプトをアタッチ
offset はPlayerをセット、headはVRCameraをセットしてのテストは問題なく動いている。

offsetは親オブジェクトでなくても問題はない、状況に応じて適切なオブジェクトをoffsetとして設定すべし。

## 参考資料
[Unity で VR モード時にカメラの位置を固定する](http://monopocket.net/blog/vr/unity-hmd-position/)
[【Unity】VRカメラのポジショントラッキングを無効化する](https://qiita.com/nkjzm/items/d5cb371a99b0c7e956c2)
Google Indexing APIのRubyのサンプル

## 概要

Googleのお仕事検索が始まってIndexing APIを試してみました。

https://developers.google.com/search/apis/indexing-api/v3/prereqs?hl=ja

公式にはRubyのサンプルがなかったので載せておきます。

## 準備

公式を読めば分かりますが、準備の流れをざっくり流れを書いておきます。

* [Google API console](https://console.cloud.google.com/apis/)でプロジェクトを作成する。既にあればもちろんそれでもOK。
* IndexingAPIを有効にする。
* メニュの「IAMの管理」＞「サービス　アカウント」に行ってサービスアカウントを作成する。この時JSON形式で秘密鍵をダウンロードしておく。
* 作成したサービスアカウントのメールアドレス（自動で生成されるもの）をサーチコンソールで対象サイトの所有者にする。

以上で完了です。

## Rubyのサンプル

[google-auth-library-ruby](https://github.com/googleapis/google-auth-library-ruby)が必要です。

```
gem install googleauth
```

コードはこんな感じ。`service_account.json`は先ほどダウンロードした秘密鍵を含むデータです。

```ruby
require 'googleauth'

authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
  json_key_io: File.open('./service_account.json'),
  scope: ["https://www.googleapis.com/auth/indexing"]
)

tokens = authorizer.fetch_access_token!

uri = URI('https://indexing.googleapis.com/v3/urlNotifications:publish')
req = Net::HTTP::Post.new(uri)
req['Content-Type'] = req['Accept'] = 'application/json'
req['Authorization'] = 'Bearer ' + tokens['access_token']
req.body = {
  url: "http://example.com/jobs/42",
  type: 'URL_UPDATED'
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(req)
end

puts res.body
```
エラーがないはずなのに「1個のローカリゼーションでエラーが発生しました」

App Store Connectでアプリを提出する時に躓いた点について共有できれば、と思いこの記事を書きました。

何に躓いたか
---
iosアプリを提出する時に、何もエラーらしきもの(赤いやつ)が出ていないのに、「1個のローカリゼーションでエラーが発生しました。」と出て、提出が上手くいかなかったところに躓いていました。

何故そのエラーが出ていたか
---
何故このエラーが出ていたのかというと、結論から言うと「ipad pro 第<span style="font-size: 150%"><b>2</b></span>世代 12.9インチ」のスクリーンショットが設定されていなかったためでした。

「バージョン情報」の下の「Appプレビューとスクリーンショット」の欄で設定しているのは「ipad pro 第<b>3</b>世代 12.9インチ」であることに注意してください。

解決方法
---
Apple Watch → メディアマネージャー → iOS App → iPad Pro 第2世代 12.9インチ

でスクリーンショットを設定すれば解決できるはずです。
AWSのEC2インスタンスをコマンドから起動・停止するメモ

# 前提

* EC2インスタンスは作成済みで、そのインスタンスIDを知っていること
* インスタンスにアクセス可能なユーザーを作ってあり、そのアクセス情報を知っていること。特に、次の2点が必要。
    * Access  key ID
    * Secret access key
* AWSコンソールからの起動・停止の操作は行えるが、これをコマンドから行いたい

# 導入

## AWS CLIのインストール

```bash
$ pip install awscli --upgrade --user
```

もしくはcondaユーザーの場合は

```bash
$ conda install -c conda-forge awscli
```

## AWSの設定

```bash
$ aws configure
```

から、プロンプトに従い情報を入力。

# コマンド

## インスタンスを起動して、そのIPを取得

IPが固定でない場合、毎回割り当てられたIPを確認する必要がある。

```bash
$ IID="i-xxxxxxxxxx"
$ aws ec2 start-instances --instance-ids $IID && \
  aws ec2 wait instance-running --instance-ids $IID && \
  aws ec2 describe-instances --instance-ids $IID \
    --query 'Reservations[*].Instances[*].PublicIpAddress' --output text
```
* 1つ目のコマンドで、インスタンスIDを変数に格納
* 2つ目のコマンド、1行目で起動
* 2行目で起動完了を待つ
* 3行目でIPアドレスを取得

正常に動作すれば、しばらくしてインスタンスが起動し、IPアドレスが表示されるので、そのアドレスを使ってSSHなどで接続する。

## インスタンスを停止し、確認

```bash
$ aws ec2 stop-instances --instance-ids $IID && \
  aws ec2 wait instance-stopped --instance-ids $IID && \
  aws ec2 describe-instance-status --instance-ids $IID
```

* 1行目で停止命令
* 2行目で停止完了を待つ
* 3行目で状態確認

正しく停止できていれば、` "InstanceStatuses"` が空になって表示される。
Wrapperパターン[外部APIのやりとりに対して]


アクションの中で直接外部APIをやりとりをしたくない
wrappers/**/client_wrapper.rb

**ClientWrapperの役割**

- 外部APIへリクエストするClientのアプリケーション上でのinterface
- 各interface(publicメソッド)ではアプリケーションの文脈において名前をつける(例1)
- responseをjson.parse、keyのunderscore化(deep_transform_keys)をしてもよい
- publicメソッドでclientからresponseを受け取ったあと、独自のロジックを入れないこと

**Clientの役割**

- 外部APIに直接リクエストし、レスポンスを受け取るオブジェクト
- HttpartyやNet::HTTPなどで直接URLにリクエストする
- レスポンスの加工のロジックは入れない
- 各interfaceは外部APIのエンドポイントに沿った命名にする


**参考**

https://medium.com/selleo/essential-rubyonrails-patterns-clients-and-wrappers-c19320bcda0
https://www.twilio.com/blog/2015/10/4-ways-to-parse-a-json-api-with-ruby.html
System.IO.Pipelinesを使う上での注意点

# はじめに

[System.IO.Pipelines](https://docs.microsoft.com/ja-jp/dotnet/api/system.io.pipelines?view=dotnet-plat-ext-2.1)が世に出てから今までいじってきた結果として、気を付けるべき点を書く

# ReadAsyncまたはTryReadの時にInvalidOperationExceptionが出る

PipeReaderの使い方は基本的には以下のようになる。

```csharp
// PipeReader pr;
// 同期版はpr.TryRead(out var readResult)
var readResult = await pr.ReadAsync();
if(!readResult.Buffer.IsEmpty)
{
    // 読出し
}
if(readResult.Buffer.IsEmpty && readResult.IsCompleted)
{
    // 終了処理
}
// これをしないと次回のReadで例外
pr.AdvanceTo(readResult.Buffer.End);
```

この時、読出し処理のブロックの最後で`pr.AdvanceTo(readResult.Buffer.End)`しないと、ReadAsyncまたはTryReadの時に`System.InvalidOperationException: Reading is already in progress.`という例外が発生する。
データを次回に持ち越したい場合、`pr.AdvanceTo(readResult.Buffer.Slice([次回の開始点]).Start)`か、`pr.AdvanceTo(readResult.Buffer.Slice(0, [使ったデータ長]).End)`を使用すればOK。

# PipeReaderにデータが来ない

非同期でPipeReaderを受けてる時、いつまでたってもデータが来ない時がある。(`await pr.ReadAsync()`で待たされる)。
このような場合、PipeWriterの方でデータをフラッシュしていない場合がある。

`pw.WriteAsync(data)`を使用している場合は、内部的にFlushしているためこの問題は起こりえないが、`pw.GetSpan()`を駆使して同期的に処理している場合、ここに引っかかる可能性がある。なお、

対処としては、ある程度データが溜まったら`pw.FlushAsync()`すれば、実行時点で蓄積されたバッファがPipeReaderの方に流れる。

```csharp
// async内ではSpanが使用できないため別関数にする
// 将来的にはこの制限が緩和される可能性あり
void WriteData(PipeWriter pw, ReadOnlySpan<byte> rsp)
{
    var sp = pw.GetSpan(rsp.Length);
    rsp.CopyTo(sp);
    pw.Advance(rsp.Length);
}
// PipeWriter pw;
// byte[] data;
WriteData(ppw, data.AsSpan());
// 実行時点でPipeReaderにデータが流れるようになる
await pw.FlushAsync();
```

なお、Flushしない場合でも、`Complete()`した時点でバッファも一緒にFlushされるので、
データ長が有限であることがわかっている場合はあえて途中のFlushをしないという選択肢もあり得る。
【自分用メモ】TortoiseGitのリポジトリ接続でハマったときの解決方法

既に出ている知見ではあるが、アウトプット練習も兼ねて自分用メモ。


環境：Windows7
ゴール：TortoiseGitを導入してGitLab上のリポジトリに接続したい。

[こちらの記事](https://qiita.com/SkyLaptor/items/6347f38c8c010f4d5bd2#git-for-windows%E3%81%AE%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97)を参考に設定をしていたのだが…

`gitは正常に終了しませんでした (終了コード 128)`

が出現...。

**試してみたこと**
・[SSHクライアントの変更](https://www.ipentec.com/document/windows-tortoise-git-exit-code-128)
→待って……[msysgit]のフォルダどこだよ……ってなった。

・Windows for Git、TortoiseGitの再インストール
→とりあえずもっかい最初から～ってやってみたけど、やっぱり`(終了コード 128)`出るな…。

・**[認証情報を変更](https://cpoint-lab.co.jp/article/201804/windows%E7%89%88git%E3%81%A7%E8%AA%8D%E8%A8%BC%E6%83%85%E5%A0%B1%E3%82%92%E6%B6%88%E3%81%99%E6%96%B9%E6%B3%95/)**
→これでした。パスワードが間違ってるのを登録しっぱなしだったので、そりゃ何回やっても無駄だよね…っていう。
ちなみに、Windows7久しぶりすぎて探すの手間取ったけど
[コントロールパネル]>[ユーザーアカウントの変更]>[資格情報の管理]>[汎用資格情報]でサクッと変更できる。また消せば、リポジトリ接続に入力を求められるので正しいユーザー名とPWを入力！

まぁ、解決できてよかったけど、早い段階で認証情報合っているかな？って確認できていれば時間無駄にしなかったな…という反省。
Faker使ってみたら面白かった話

#はじめに
今回はFakerというgemを使ってみました。
Fakerはダミーデータを生成したいときに使われると思いますが、
生成できるダミーデータがユニークだったので記事にしてみました。

ただし、今回はFakerの使い方については触れず、
個人的に面白いと思ったところを書いていきます。

手元でも試してみたい方は、Gemfileに下記を追加して``bundle``するか、
直接``gem install 'faker'``でインストールしてください。

```ruby:Gemfile
gem 'faker'
```

#触ってみる
Fakerを使ってダミーデータを生成する場合、
例えばNameであればこのような形になると思います。

```irb:irb
Faker::Name.name
=> "Altagracia Feeney"
```
「他にどんなダミーデータを作れるんだろう」と思い、
Fakerが持つ定数を取得してみました。

```irb:irb
Faker.constants
=> [:LoremPixel, :Stripe, :Lovecraft, :String, :Markdown, :Superhero, :SwordArtOnline, :Name,
 :Team, :TheFreshPrinceOfBelAir, :Matz, :Measurement, :TheThickOfIt, :TheITCrowd, :TwinPeaks,
 :MichaelScott, :Military, :Crypto, :Currency, :MostInterestingManInTheWorld, :Movie, :Music,
 :Demographic, :Myst, :UniqueGenerator, :Dessert, :Device, :Nation, :Dog, :NatoPhoneticAlphabet,
 :NewGirl, :Dota, :Base, :DrWho, :File, :DragonBall, :DumbAndDumber, :Dune, :Educator, :Omniauth,
 :UmphreysMcgee, :University, :ElderScrolls, :Job, :VForVendetta, :Vehicle, :Address,
 :ElectricalComponents, :Ancient, :Color, :Esport, :Ethereum, :Fallout, :FamilyGuy,
 :FamousLastWords, :Internet, :Fillmurray, :Finance, :Twitter, :VentureBros, :App, :Verb,
 :Appliance, :Food, :AquaTeenHungerForce, :Witcher, :Artist, :Avatar, :WorldCup, :Football,
 :Lorem, :WorldOfWarcraft, :BackToTheFuture, :Bank, :FunnyName, :Friends, :Yoda, :Zelda,
 :GameOfThrones, :PhoneNumber, :Gender, :GreekPhilosophers, :Hacker, :Beer, :HarryPotter,
 :HeyArnold, :Hipster, :Bitcoin, :VERSION, :Number, :Source, :BojackHorseman,
 :HitchhikersGuideToTheGalaxy, :Book, :OnePiece, :Hobbit, :HowIMetYourMother, :BossaNova,
 :IDNumber, :Overwatch, :BreakingBad, :Placeholdit, :Business, :ParksAndRec, :Pokemon,
 :PrincessBride, :Cannabis, :ProgrammingLanguage, :RickAndMorty, :Robin, :RockBand, :RuPaul,
 :Char, :Science, :Cat, :Compass, :Seinfeld, :ChuckNorris, :Shakespeare, :Code, :SiliconValley,
 :Simpsons, :SingularSiegler, :SlackEmoji, :Date, :Invoice, :Space, :Coffee, :Time, :Kpop, :Types,
 :Commerce, :Boolean, :LeagueOfLegends, :StarTrek, :Config, :StarWars, :Lebowski, :LordOfTheRings,
 :Community, :Company, :LoremFlickr, :Stargate, :StrangerThings]
```

よく見ると「Pokemon」や「OnePiece」といった見覚えのある文字が...
今回は個人的に好きな「OnePiece」を例に見てみます。
まずは、Faker::OnePieceが扱えるメソッドを取得してみます。

```irb:irb
Faker::OnePiece.methods(false)
=> [:quote, :location, :sea, :island, :akuma_no_mi, :character]
```

何やら悪魔の実やキャラクターなどのダミーデータを生成できそうですね。
まずは、悪魔の実を試してみましょう。

```irb:irb
Faker::OnePiece.akuma_no_mi
=> "Ope Ope no Mi"
```

おーダミーデータとして、オペオペの実が生成されました。
ついでにキャラクターの方も見てみましょう。

```irb:irb
Faker::OnePiece.character
=> "Aokiji"
```
なんと、青キジが生成されましたね！

#まとめ
今回はFakerを使って「OnePiece」のダミーデータを生成してみました。
これらを使って何か面白そうなことができれば、また記事にしたいと思います。
他にもいろいろ面白そうなのがあったので、
興味がある方は試してみてください！
vagrant up 時に出る default: Warning: Authentication failure. Retrying... の解決法

# 前提
* ただvagrant upしてるだけなのに、2回目以降の起動時にこれ↓で詰まってしまうときに見るメモ

``` terminal 
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying... 
    default: Warning: Authentication failure. Retrying... 
    default: Warning: Authentication failure. Retrying... 
    default: Warning: Authentication failure. Retrying... 
```

# 解決策 1 パーミッション（権限）を見直す
* 権限を確認すべき対象は3つ
* 自分以外に権限を与えていたらNG  (home/vagrantについては755まで大丈夫)
    * /home/vagrant
    * /home/vagrant/.ssh
    * /home/vagrant/.ssh/authorized_keys

``` terminal
Windows:
> vagrant ssh

vagrant:
$ chmod 755 /home/vagrant/
$ chmod 700 /home/vagrant/.ssh/
$ chmod 600 /home/vagrant/.ssh/authorized_keys

Windows:
> vagrant reload
```
* 無事に再起動、しなければ別の問題

# 解決策 2 公開鍵ファイル（authorized_keys）があるか確認する
* 誤操作や共有フォルダ設定などによって、稀に消してしまっている場合があるので確認する

``` terminal 
Windows:
> vagrant ssh

vagrant:
$ ll .ssh/
total 4
-rw------- 1 vagrant vagrant 389 Jan 31 10:49 authorized_keys　←このファイル
```
* もしもauthorized_keysがなかった場合は、`vagrant destroy`でvagrantごと作り直すか、下記手順でファイルだけを作り直す。

``` terminal
Windows:
> vagrant ssh-config
Host default
  HostName 127.0.0.1
  User ****
  Port ****
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile c:/***/private_key　←これをコピー
  IdentitiesOnly yes
  LogLevel FATAL
> ssh-keygen -yf c:/***/private_key > public_key
```
* 作成されたpublic_keyファイルの中身をコピー

``` terminal
Windows:
> vagrant ssh

vagrant:
$ vi .ssh/authorized_keys
```
public_keyファイルの中身 + (半角スペース) + (vagrant) という中身にして保存

``` terminal
Windows:
> vagrant reload
```
* 無事に再起動、しなければ別の問題
AmazonSNSをつかってSMSを送信する


### 前提条件

- python3.6.2
- boto3
- AmazonSNSFullAccess権限を付与する

### スクリプト　

``` python
import boto3

sns = boto3.client("sns")

phone_number = '+81[電話番号]'

message = 'Test Message'

message_attributes = {
	'AWS.SNS.SMS.SenderID': {
		'DataType': 'String',
		'StringValue': 'northshore' # 通知者表示に使用される送信者ID
	}
}

sns.publish(
	PhoneNumber=phone_number, 
	Message=message,
	MessageAttributes=message_attributes)

```
HerokuからApache HttpClientでOutbound IP固定で通信

HerokuアプリからSalesforce APIを発行する際、Salesforce側に許可IPを設定したいのでProximoアドオン(HTTP Proxy)でOutbound IPを固定した
Inboundも固定したいならQuotaGuard Static(のMicro以上)の方がいいかも

ProximoのURLは以下の形式
`http://＜Proximoユーザ名＞:＜Proximoパスワード＞@proxy-＜IPアドレス＞.proximo.io`
認証が必要なのでそれなりのコーディングを行った

```
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
// https://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html 2.4. Multithreaded request execution
// TODO: Tuning
HttpClientBuilder httpClientBuilder = HttpClients.custom().setConnectionManager(poolingHttpClientConnectionManager);

URL proxyUrl = new URL(＜環境変数PROXIMO_URLの値＞);
String proxyHostString = proxyUrl.getHost();
int proxyPort = proxyUrl.getPort();
HttpHost proxyHost = proxyPort != -1 ? new HttpHost(proxyUrl.getHost(), proxyPort) : new HttpHost(proxyUrl.getHost());
String proxyUserInfo = proxyUrl.getUserInfo();
String proxyUsername = proxyUserInfo.substring(0, proxyUserInfo.indexOf(':'));
String proxyPassword = proxyUserInfo.substring(proxyUserInfo.indexOf(':') + 1);
httpClientBuilder.setProxy(proxyHost);
httpClientContext = HttpClientContext.create();
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope(proxyHost), new UsernamePasswordCredentials(proxyUsername, proxyPassword));
httpClientContext.setCredentialsProvider(credentialsProvider);
BasicScheme basicScheme = new BasicScheme();
basicScheme.processChallenge(new BasicHeader(AUTH.PROXY_AUTH, "Basic"));
BasicAuthCache basicAuthCache = new BasicAuthCache();
basicAuthCache.put(proxyHost, basicScheme);
httpClientContext.setAuthCache(basicAuthCache);

CloseableHttpClient httpClient = httpClientBuilder.build(); // 同じ相手に何度も通信するならcloseすることなく使い回した方が接続やhandshakeにかかる時間を節約できる

HttpGet request = new HttpGet(XXX);
try (CloseableHttpResponse response = httpClient.execute(request, httpClientContext)) {
    String responseBody = EntityUtils.toString(response.getEntity());
    StatusLine statusLine = response.getStatusLine();
    if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
        log.error("XXX failed. statusLine={}, responseBody={}", statusLine.toString(), responseBody);
        throw new RuntimeException("XXX failed");
    }
    ★responseBodyを使って処理
}
```