OmniAICreator/Qiita-1.07M huggingface dataset:
PnP PowerShell で Sharepoint を操作しよう: (5) コンテンツタイプの作成と割り当て

皆様こんにちは。

今回は、コンテンツタイプの作成とドキュメントライブラリーへの割り当てをやってみます。
お客様のオーダーは、フォルダーのコンテンツタイプを原型に、色々カスタム属性をくっつけた「属性付きフォルダー」タイプを定義して、これを検索させたいというものです。

使うコマンドは 
[`Get-PnPContentType`](https://docs.microsoft.com/en-us/powershell/module/sharepoint-pnp/get-pnpcontenttype?view=sharepoint-ps)
[`Add-PnPContentType`](https://docs.microsoft.com/en-us/powershell/module/sharepoint-pnp/add-pnpcontenttype?view=sharepoint-ps)
です。


# コンテンツタイプを新規に作成する
```
$ContentTypeGroup="拡張フォルダー情報"
#新規コンテンツタイプ"ExtFolder"を定義する
$ParentCT = Get-PnPContentType -InSiteHierarchy -Identity フォルダー
Add-PnPContentType -Name "ExtFolder" -Description "属性付きフォルダー" -Group "フォルダー コンテンツ タイプ" -ParentContentType $ParentCT
# ここまでで空のコンテンツタイプができる

# 新しいフィールドをサイトに追加する。グループは"拡張フォルダー情報"
Add-PnPField -DisplayName "商品コード" -InternalName "ProductCode" -Type Text -Group $ContentTypeGroup
Add-PnPField -DisplayName "分類コード" -InternalName "CategoryCode" -Type Text -Group $ContentTypeGroup
```

# コンテンツタイプをリスト/ドキュメントライブラリーに割り当てる
```
#ドキュメントライブラリー"Shared Documents"(ドキュメント) にExtFolder コンテンツタイプを割り当てる
$DocumentLibrary="Shared Documents"
Add-PnPContentTypeToList -List $DocumentLibrary -ContentType $MyCT -DefaultContentType 
```
ここまでで、内容のない新しいコンテンツタイプ "ExtFolder"ができました。

#ビューを追加する
ここまでできたので、ビューを追加して、デフォルトのビューに割り当てます。行数がたくさんになるので、-Paged をセットして、
使う命令は
[`Add-PnPview`](https://docs.microsoft.com/en-us/powershell/module/sharepoint-pnp/add-pnpview?view=sharepoint-ps)
[`Set-PnPview`](https://docs.microsoft.com/en-us/powershell/module/sharepoint-pnp/set-pnpview?view=sharepoint-ps)
です。
どうも、名前を英語、日本語で別々に与えることができないようなので、一度英語名でビューを定義しておいて、あとから`Set-PnpView` でTitle を日本語名に書き換えています。`-paged` は行数が増える場合のために必要です。

```
$ViewName="新しいビュー"
$ViewInternalName="NewView"
Add-PnPView -List $DocumentLibrary -Title $ViewInternalName -ViewType Html -SetAsDefault -Fields @("LinkFilename","ProductCode","CategoryCode","Modified") -Paged 

Set-PnPView -List $DocumentLibrary -Identity $ViewInternalName  -Values @{"Title"="$ViewName"}
```
今回はここまでにします。
searchkick gemのマイナーバージョンアップデート時のelasticsearch gemのメジャーバージョンのズレ発生について

Elasticsearchを利用するために、searchkickというElasticsearchを簡単に扱えるようにしたgemを介して利用されている方も多いと思う。

searchkickのマイナーバージョンアップデート(「X.X.X」の3桁目のみをバージョンアップ)を実施した際、
その依存gemであるelasticsearch用gemのメジャーバージョンとElasticsearch本体のバージョンがズレるという現象が発生した。

`Elasticsearch本体のバージョン`
　6.2.4
`searchkickマイナーバージョンアップデート後のelasticsearch用gemのバージョン`
　elasticsearch (7.1.0)
　elasticsearch-api (= 7.1.0)
　elasticsearch-transport (= 7.1.0)

原因は、searchkick依存gemであるelasticsearch用gemのバージョン指定が、5系以上という指定になっていた事だ。

明確には以下の通り。

~~~Ruby:searchkickの依存gemを表示するコマンド
gem dependency searchkick
~~~

~~~Ruby:実行結果
Gem searchkick-3.1.3
  activemodel (>= 4.2)
  bundler (>= 0, development)
  elasticsearch (>= 5)
  hashie (>= 0)
  minitest (>= 0, development)
  rake (>= 0, development)
~~~

実行結果に、`elasticsearch (>= 5)`とある通り、依存gemであるelasticsearch用gemは、
bundle updateすると、強制的に5系以上のバージョンにアップデートされるような設定になっている。

Elasticsearch本体が6系なのにelasticsearch用gemが7系のバージョンという風にズレるのは宜しくない。
[※elasticsearch本体とgemの互換性について](https://www.rubydoc.info/gems/elasticsearch-model/)

対策は以外とシンプルだが、Gemfileに対して依存gemであるelasticsearch用gemの記述をバージョン固定形式で明記し、bundle updateするだけで良かった。

~~~Ruby:Gemfileに新規追加した記述
gem 'elasticsearch', '~>6.1.0'
~~~

利用しているgemのみバージョン固定すれば大丈夫だと油断していたが、利用しようとしているgemの依存gemのバージョンにも気を配らないといけない事を、今回の一件で学んだ。
Ubuntu18 にて Shift + Space で入力言語の切り替えを設定する

# Ubuntu18 にて Shift + Space で入力言語の切り替えを設定する

旧来の入力環境設定を好む自分用メモです。

## 1. Ubuntu18 に Unity をインストール

https://kledgeb.blogspot.com/2018/04/ubuntu-unity-1804-12-ubuntu-1804unity-7.html

## 2. 以下の画像の通り①〜④の設定を実施

![MyInputSetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341107/aeec64b2-8822-cf43-4e17-c9b9573a856a.png)
UbuntuとWindowsでデュアルブートした際にGRUBで引っかかった時の対処法

Ubuntuを入れたけどうまく動かなかったのでアンインストールした後，PCを起動すると真っ黒なGRUBの画面が出てきてWindowsが起動されなくなってしまった．
恐らく
・Ubuntuをインストール→ブートローダーがUbuntuに変更(デフォで)→Ubuntuアンインストール→？？？
となって，バグになってしまったのではと考えられる．
取りあえず対処したのでメモ．

#BIOSを起動
BIOSはPCのかなり低レイヤーの部分で，WindowsやUbuntuを立ち上げる際にブートローダーを選択したり，軌道のオプションを変更できたりするものです．デュアルブートなどをする際は特によく利用すると思います．

・起動時にPCのロゴが表示されている間にファンクションキーを押す(メーカーによってBIOS起動キーが違う．困ったら全部押す．)
・BIOS画面が起動したら，[起動]→[UEFI優先度]に進む．
・起動オプション#1,起動オプション#2...が表示される．これはPCを起動した際にまずどのディスク(UbuntuやWindows)を読み込むかを決定するオプションである．
よってこの順番を[起動オプション#1]=[Windows Boot Manager]にする．これで最初にWindowsが読み込まれるので，UbuntuのGRUBのバグに進まなくなる．再起動してWindowsに自動で進む．

#感想
「細かい話でも助かる人がいるかもだから記事書くべき！」という話を聞いたので書いてみた．役に立ったら幸いです．
ではまた．
Google Colab リセットポイントのメモ

Google ColabでPythonを初めて使う人が、急にエラーが出てきたとき、どうやってリセットするか？どこのポイントにリセットされるか？を知っておくと便利な気がしたのでメモしておきます。

## 全体マップ

リセットするときに使うものは「ランタイムを再起動…」「すべてのランタイムをリセット…」の2つがあります。名前が似ていますが内容が大きく違ってわかりくいので、まずは全体図をみてください。

![imgae](https://samacoba.github.io/images/20190603-1.png)

![imgae](https://samacoba.github.io/images/20190603-2.png)

## 実行中セッションをリセット （ランタイムを再起動…）

実行しているセッションがリセットされるので、最初から実行（▶ボタンを押す or shift＋enter )して、再度パッケージをimportしないと

```
NameError: name 'np' is not defined

```
などでエラーがでます。

入力のコードや出力のテキストは残っています。残っている出力がまぎらわしい場合は「編集」⇒「出力をすべて消去」で消すことができます。


### リセットされるもの

* そのセッションでの実行中プログラム（時間のかかる計算や無限ループが強制終了）
* そのセッションでimport されたパッケージ
* そのセッションで使用した変数（グローバル変数含む） 

### 保持されるもの

* 打ち込んだコードのテキスト
* printなどで表示された出力テキスト
* デフォルトでインストールされているパッケージ
* ! pip install などでインストールしたパッケージ
* 外部から仮想マシン上へダウンロードしたデータ(MNISTなど)



## 仮想マシンをリセット （すべてのランタイムをリセット…）

仮想マシンそのものがリセットされるので、デフォルトでインストールされているもの以外はすべてリセットされます。自分で入れたパッケージや仮想マシン上にダウンロードしたデータは再度入れなおす必要があります。

90分ルールや12時間ルールなど接続が強制的に切れる場合でもこのリセットが適用されるはずです。また、CPU ⇒ GPUでも別の仮想マシンが立ち上がるようです。

### リセットされるもの

* すべてのセッションでの実行中プログラムやimportされたパッケージ、使用した変数
* ! pip install などでインストールしたパッケージ
* 外部から仮想マシン上へダウンロードしたデータ(MNISTなど) 

### 保持されるもの

* Googleドライブに自動保存されている.ipynbファイルのコードと出力テキスト
* デフォルトでインストールされているパッケージ

## ノートブック(.ipynb)ファイルについて

通常、「ファイル」⇒「python3の新しいノートブック」などから始めた場合は「Untitled0.ipynb」などとして、自分のGoogleドライブ上に自動保存されています。

Web上のチュートリアルなど、「Open in Colab」ボタンで開いたものは、実行することはできますが、通常上書き保存はできないので、再度「Open in Colab」ボタンで開いて「すべてのランタイムをリセット」すれば、最初の状態から始めることができます。もし保存したい場合は自分のGoogle ドライブにコピー保存する必要があります。


## 参考

* [【秒速で無料GPUを使う】深層学習実践Tips on Colaboratory @tomo_makes
](https://qiita.com/tomo_makes/items/b3c60b10f7b25a0a5935)

* [Google Colaboratoryを便利に使うためのTIPSまとめ(からあげ)](https://karaage.hatenadiary.jp/entry/2018/12/17/073000)
LambdaとCloudWatchでサーバレスなスケジュールタスク実行

#はじめに
この記事では、LambdaのスクリプトをCloudWatchを使って定期実行する方法を紹介します。
この方法を使うことで、サーバレスなスケジュールタスク実行が可能となります!

#前提条件
AWSアカウントの作成手順や定期実行したいLambda関数の作成は終わっている状態を想定します。
また、用語の説明も省略しますので、わからない方はググってください。

#Lambda関数の定期実行方法
##1. トリガーの指定
定期実行したいLambda関数の設定画面で、「トリガーの追加」から「CloudWatch Events」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254738/46f88105-b87e-e2a6-0bb4-96e1337fa4c1.png)

##2. ルールの作成
定期実行の頻度を指定するCloudWatch Eventsを作成します。
画面下部の「トリガーの設定」から「ルール」のリストボックスをクリックし、「新規ルールの作成」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254738/fae7ca33-d5da-3d98-63ee-ae5fc1c7b613.png)

以下のような画面が表示されるため、各情報を入力します。

- ルール名: 今回のスケジュールに対するルール名を指定します。ルールは再利用可能です。
- ルールの説明： ルールに対する説明です。
- ルールタイプ: 今回は定期実行させるため「スケジュール式」を選択します。
- スケジュール式: 実行間隔を指定するためのcron式またはrate式を入力します。(cron式とrate式については次項目を参照)
- トリガーの有効化: 設定保存時にトリガを有効化するか選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254738/143e42ae-7e0e-deb4-2db3-d0697129b27c.png)

##3. cron式とrate式について
どちらもスケジュールを定義する式です。ざっくりと以下のような使い方をします。

**cron(分 時間 日 月 曜日 年)**
値を問わない(any)にはワイルドカードとして\*と?を使用します。厳密な定義とは異なりますが、数値を問わない場合は*、曜日を問わない場合は?を使えばOKです。

**rate(間隔の値 単位)**
単位にはminute, minutes(値が1以上の場合), hoursなどが使用できます。

>詳細については公式のドキュメントに記載がありますのでご覧ください。
>https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html

##4. トリガーの追加と設定の保存
ルールの設定をすべて入力し終えたら、「追加」ボタンをクリックします。
これによって、Lambda関数にCloudWatch Eventsのトリガが追加されます。
また、このLambda関数に対してCloudWatch Eventsへのアクセス許可が自動的に追加されます。

##5. あとは実行を待つのみ
指定した時間まで待てば、Lambda関数が実行されます！
もしうまく実行されなかったという場合は、CloudWatchにアクセスして、ログやEventの設定を確認してみましょう。なお、corn式で指定した日時はGMTで解釈されますので、時差の影響でないかも念の為チェックです。

CloudWatchを開いて、「ルール」→「作成したルール名」とクリックすると、現在のルールの内容や、次回のスケジュール、参照されているLambda関数等が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254738/11a8232e-2faa-071b-cb1d-b8cacf1ddfe5.png)

さらにモニタリングをクリックすると、このルールが呼び出されたタイミングを確認できます。
トリガの問題か、関数自体の問題かの切り分けとしては、Lambda関数の「テスト」機能も活用できますね。

#おわりに
この記事では、LambdaのスクリプトをCloudWatchを使って定期実行する方法を紹介しました。従来スケジュールタスクの実行にはEC2インスタンスを使ってcronを実行するなどして実現していましたが、この方法であればサーバレスアーキテクチャで完結させることができ、大変便利ですね。私はクローラに応用していますが、用途は様々ありそうです。
Python > ファイルI/O > CR,LF付文字列のwrite()時に余分なCRが追加されてCR,CR,LFになる > 仕様通り

```txt:動作環境
Windows 10 Pro v1809
Anaconda v2019.03
Jupyter Notebook v5.7.8
Python v3.7.3 
```

### 概要

- CR, LF付文字列をwrite()したときにCR, CR, LFとして書出される

### コード

```python
with open('test_190603.txt', 'w') as wfp:
    wfp.write("AAAA" + "\r\n")
    wfp.write("AAAA" + "\r\n")
    wfp.write("AAAA" + "\r\n")
```

### 出力ファイルの構造

[windows > バイナリエディタ > 構造体の情報を得る](https://qiita.com/7of9/items/3a73f879d43c1390d1f8)
にある
Binary Editor BZで確認

![2019-06-03_16h54_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/44cb120e-569f-712c-b660-09e2a3b7e57b.png)

CR(0x0D)が余分にある。

### 関連

下記(2016年の情報)に近い症状のようだ。
バイナリ書出しで対処されている。

- [On Windows, CSV output contains superfluous CR (CR CR LF)](https://github.com/afimb/gtfslib-python/issues/39)


### 不可解な点

- もともとCR,LF付の文字列をreadline()してからwrite()した時には余分なCRはつかない
- CR, LFをつけた文字列をwrite()した時に余分なCRがつく

### 備考

- open()時のnewline指定では解消しなかった


### 対処

`文字列 + CR, LF`
ではなく
`文字列 + LF`
でwrite()すると
`文字列 + CF, LF`として書込まれた。

**ただし、将来Pythonのバージョンが上がったときに不具合修正がされると、振舞いが変わるだろう。**


### 仕様通り
(追記 2019-06-03)

@c-yan さんの[コメント](https://qiita.com/7of9/items/b874eca9ec8789dc3f97/#comment-95a9ccfacde6c668b5b6)にてPythonの仕様について言及されています。

仕様書通りなのですね。

情報感謝です。

### ファイル読書き

https://docs.python.org/ja/3/tutorial/inputoutput.html#reading-and-writing-files

Windowsにおいて、CR, LFのファイルに対して下記となる。

- 読込み: CR, LFはLFに変換
- 書出し: LFはCR, LFに変換
機械学習用語 （随時更新中）

| 日本語 |中国語| 英語 | 
|-----------|------------|------------|------------|
| トレーニングセット| 训练集|training set|
| サンプル |样本|sample|
| 精度|精度|accuracy|
| 音声識別|语音识别|speech recognition|
| クラスタリング|聚类|clustering|
| 次元削減|降维|dimensionality reduction|
|特徴量抽出|特征抽出|feature extraction|
|分類|分类|classification|
|回帰|回归|regression |
|異常検知|异常检测|anomaly / novelty detection|
|相関ルール学習|关联规则学习|association rule learning|
|学習率|学习率|learning rate|
|適応度関数|适应度函数|fitness function|
|コスト関数|代价函数|cost function|
|損失関数|损失函数|loss function|
|誤差関数|误差函数|error function|
|目的関数|目标函数|objective function|
|特徴エンジニアリング|特征工程| feature engineering|
|特徴選択|特征选择|feature selection|
|特徴抽出|特征提取|feature extraction|
|過剰適合（過学習）|过拟合|overfitting|
|学習不足（未学習）|欠拟合|underfitting|
|正則化|正则化|regularization|
|ハイパーパラメータ|超参数|hyper‐parameter|
|交差検証|交叉验证|cross validation|
|単回帰|简单线性回归|simple linear regression|
|重回帰|多元回归|multiple regression|
|単変量回帰|单变量回归|univariate regression|
|多変量回帰|多变量回归|multivariate regression|
|性能評価|性能指标|performance measure|
|相関係数|相关系数|correlation coefficient|
|データクレンジング|数据清洗|data cleaning|
|表現学習|表示学习|representation learning|
|フィーチャースケーリング|特征缩放|feature scaling|
|正規化|归一化|normalization / min-max scaling|
|標準化|标准化|standardization|
|密行列|稠密矩阵|dense matrix|
|疎行列|稀疏矩阵|sparse matrix|
|アンサンブル学習|集成学习|Ensemble learning|
|ファインチューニング|微调|fine tuning|
|グリッドサーチ|网格搜索|grid search|
|ランダムサーチ|随机搜索|randomized search|
ML-Agentsの注意点(0.8.0)

#Unity ML-Agentsのはまったところ
　ほとんどの情報は、古いバージョン0.4.0くらいを対象にしており、最近の0.8.0では変更されていることが多いので、分かる範囲で書いてみます。
１）Unity2018以降だとPythonで学習できない。
２）tensorflow1.7.1はceleronだめ。
３）0.4.0で作成したプログラムは0.8.0では動かない。

#Unity2018以降だとPythonで学習できない。
pythonで学習させるときに、

mlagents-learn config/trainer_config.yaml --env=<app_name> --run-id=firstRun --train

と打ち込んでいると思いますが、これがwindows+unity2018の場合、うまくいきません。Unity2017でbuildしたら、動きました。
理由はわかりません。

#tensorflow1.7.1はceleronだめ。
　デフォルトのtensorflowバージョンは、1.7.1です。これだと、celeronはダメなようです。intelAVXが必要で、i3、i5、i7の第2世代以降は大丈夫なようです。お手軽celeron　G3900はだめでした。
　対策は、tensorflowバージョンを1.5.1にすること。こうすると動きます。

#0.4.0で作成したプログラムは0.8.0では動かない。
　pythonは、mlagents　v0.8.0で動いているようで、0.4.0でビルドしたプログラムは動きません。
仕様が大幅に変更されているようなので、書き直しが必要みたいです。

　そろそろv1.0になるのでしょうか。試みは面白いので、正式バージョンまでたどり着いてほしものです。
brainの設計が難航しているように思えます。
Skinning/rig 論文のメモ

## 最近の技法のまとめ

https://mukai-lab.org/projects/helper-bone-rigging/

向井ラボから.
日本語でまとまっていてありがとうございます.

# linear blend skinning (LBS) 

glTF skinning などで使われている基本的な skinning 手法


# Smooth Skinning Decomposition with Rigid Bones


http://graphics.cs.uh.edu/ble/papers/2012sa-ssdr/

事例 pose(example pose)から deformation  LBS skinning に分解する.


# Detal mush

https://dl.acm.org/citation.cfm?id=2633376

https://vimeo.com/103854005

Mesh に laplancian filter をかけてスムースメッシュを作り, そこからの displacement を求める.
スムースメッシュ上で skinning してから, displacement を復元することで, ディテールのあるキャラクターの rig を可能にする.

https://vimeo.com/103666815

のビデオがわかりやすい.

Maya などに搭載されている.
R&H が破綻したからかどうかは不明であるが, patent は無い模様.

計算コストは高いため, 基本オフライン用途.
 
## Direct Delta Mush

https://www.ea.com/seed/news/siggraph2019-direct-delta-mush

Delta Mush(式的には per-vertex で weighed avarage を取る?)をリアルタイム用途で使えるようにする.
DDV v0 は SVD(Singular Value Decomposition)の計算を頂点ごとに行い, 品質も高いが流石に計算コストはかかる. いくつか簡略化バージョンを提案している.

## Sampling-based Rig Conversion into Non-rigid Helper Bones

https://mukai-lab.org/publications/i3d2018/

## NeuroSkinning: Automatic Skin Binding for Production Characters with Deep Graph Networks

http://kunzhou.net/

機械学習でキャラクタに自動で skinning を割り当て? 


# Pose space deformation: a unified approach to shape interpolation and skeleton-driven deformation

https://dl.acm.org/citation.cfm?id=344862


# Fast and Deep Deformation Approximations

http://graphics.berkeley.edu/papers/Bailey-FDD-2018-08/Bailey-FDD-2018-08.pdf

deformation を linear と nonlinear に分解し, nonlinear を deep learning ベースで近似.

LBS よりより精度よく元の deformation を近似できる.
Libee(DreamWorks の rig evaluation framework. public には公開されていないので比較はしずらいが)より 5 ~ 10 倍高速に評価できるため, 映画クオリティの rig を CPU でもリアルタイムに評価できる.
Jupyter Notebook を Chrome (起動オプション付き) で開く (Win10)

デフォルトブラウザのChromeが拡張モリモリで余計なメモリを食うので、それを避けるためにJupyter Notebookの使用するブラウザを拡張機能の(比較的)少ないシークレットモードに変えてみます。

## 実行環境

Windows 10 Home 64bit
Anaconda 4.6.14

## 手順

1. 設定ファイルを作る

anaconda promptでコマンドを実行し、設定ファイルを生成させます。

```shell
> jupyter notebook --generate-config
```

2. 生成した設定ファイルを書き換える

生成した設定ファイルの99行目付近にある下記の文を書き換えます。

```python
# c.NotebookApp.browser = ''
```

chromeをシークレットモードで開くには、起動オプション `--incognito`を末尾につけます。

```python
c.NotebookApp.browser = u'\"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" %s --incognito'
```

失敗する場合は、

- ブラウザ指定文の先頭に`u`がついているか?

- `u'\"ブラウザへのパス" %s --起動オプション'`の構文に合っているか?

を確かめてみると多分大丈夫です。

## 参考サイト

[Change default browser in Jupyter Notebook](<https://support.anaconda.com/customer/en/portal/articles/2925919-change-default-browser-in-jupyter-notebook>) 

[Jupyter Notebookを起動する時に新しいウィンドウで開く(Windows)](<https://qiita.com/dddmm/items/6935a058cbb5ff3bbe02>)
cookieの先頭のドット

goで

```go
http.SetCookie(w, &http.Cookie{
	Name:     "testcookie",
	Value:    url.QueryEscape("test"),
	MaxAge:   24 * 60 * 60,
	Path:     "/",
	Domain:   ".hogehoge.com",
	Secure:   true,
	HttpOnly: true,
})
```

こんな感じのcookieをセットしても

```sh
$ curl -I http://127.0.0.1:1234
HTTP/1.1 200 OK
Set-Cookie: testcookie=test; Path=/; Domain=hogehoge.com; Max-Age=86400; HttpOnly; Secure
Date: Mon, 03 Jun 2019 07:07:11 GMT
```

と先頭のドットがなくなってしまう。

他のサブドメインからもクッキー読み書きできるようにするには先頭にドットつけないといけないと思っていてどうして何だろうと調べていたら

https://github.com/golang/go/blob/master/src/net/http/cookie.go#L189-L198

ソースコードのコメントに
// A c.Domain containing illegal characters is not
// sanitized but simply dropped which turns the cookie
// into a host-only cookie. A leading dot is okay
// but won't be sent.

と書いてあった。。

```sh
$ curl -I https://google.com

domain=.google.com
```

とかで確認してみると先頭にドットついているけど必要ないてことなのかな。。
tensorflow2.0 + kerasでGPUメモリの使用量を抑える方法

## 解説

tensorflowは普通に使うとGPUメモリを取れるだけ取りにいっちゃいます。大きいモデルを１つだけ学習するならそれでも良いんですが、小さいモデルで学習する場合もガッツリメモリをもっていかれるのがイマイチです。例えばmnistを隠れ層128ノード1層で学習してもこんな感じになっちゃいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/fb99f08f-fdf8-a646-e186-c77435a3cf6a.png)

こんなに必要なわけないので、最小限だけ使うように設定します。

## tensorflow1系

tensorflow1系を使ってた頃はkerasとtensorflowが別packageだったので、keras.backend.set_session()の引数にtf.Session(config=hoge)を渡すことでコントロールしてました。

```python:python
from keras import backend as K
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.Session(config=config)
K.set_session(sess)
```

## tensorflow2.0.0alpha

kerasがtensorflowのモジュールになったおかげで2.0.0alphaでは1行で書けるようになりました。

```python:
#メモリ制限(growth)
import tensorflow as tf
tf.config.gpu.set_per_process_memory_growth(True)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/8ee61f1e-2f24-865a-7eca-f56ff705f71e.png)

## tensorflow2.0.0beta～2.0.0

tensorflow2.0.0beta以降でtf.config.gpuがなくなり、tf.config.experimental.set_memory_growth()で設定するようになりました。tf.experimental.config.list_physical_devices('GPU')でGPUデバイスのリストを取得し、memory_growthを設定したいデバイスすべてに対し実行してやります。

```python:python
physical_devices = tf.config.experimental.list_physical_devices('GPU')
if len(physical_devices) > 0:
    for device in physical_devices:
        tf.config.experimental.set_memory_growth(device, True)
        print('{} memory growth: {}'.format(device, tf.config.experimental.get_memory_growth(device)))
else:
    print("Not enough GPU hardware devices available")
```

## tensorflow2.1.0～2.3.0 (2020.9.15 修正)

tf.config.experimental.list_physical_devices()のexperimentalが取れました。それ以外は上記と同じです。tensorflow2.3.0の時点でまだdeprecatedにもなっていなくてexperimentalが入っていても問題なく動きますので旧いバージョンの入ったマシンと共用で使えるようにしたい場合は上記のコードのままでも大丈夫です。

```python:python
physical_devices = tf.config.list_physical_devices('GPU')
if len(physical_devices) > 0:
    for device in physical_devices:
        tf.config.experimental.set_memory_growth(device, True)
        print('{} memory growth: {}'.format(device, tf.config.experimental.get_memory_growth(device)))
else:
    print("Not enough GPU hardware devices available")
```

## 以前書いていた間違いについて (2020.9.15修正)

すみません、2020.8.5に書いた追記でtensorflow2.3.0ではset_memory_growthが要らないようだと書いていたんですが間違いでした。これまでと同様、set_memory_growthが必要です。書き方は同じで出来ます。


#### 更新履歴
2019.8.13 tensorflow2.0.0beta用のメモリ制限について追記しました
2019.10.21 tensorflow2.0 stableでも動作を確認しました
2020.2.1 tensorflow2.1.0での動作を確認しました
2020.9.15 tensorflow2.3.0での動作を確認しました
フィナンシェでブロックチェーン勉強会、始めました。

こんにちは、Takです。前回までは、ブロックチェーンの実践的な知見の共有を主眼に、[@ku_sukeさんの記事](https://qiita.com/ku_suke/items/20742efd5227889d1f01)  [@rudoさんの記事](https://qiita.com/rudo/items/3902cac2a4436de2c304) [@tomuさんの記事](https://qiita.com/tomu/items/465d7238fced153d698a) を書きました。

今回は趣旨を変え、フィナンシェ社内の取り組みをご紹介します。
ブロックチェーン勉強会を始めました。

# なぜ始めたの？
フィナンシェはテクノロジーファーストを掲げています。そのための第一歩として、まずはメンバーの誰に聞いてもブロックチェーンについて何かしら語れるものがある状態を目指してゆきます。そのため参加者はエンジニアに限らず、非エンジニアも対象にしました。

# どんな事をやったの？
ブロックチェーンに関するトピックをディスカッション形式で議論しました。議論が深まることで、ブロックチェーンの理解が深まる想定です。あえて、スライドによる知識インプット形式では実施しませんでした。

まず、講師が話題を提示　→ 有識者が回答　→ 参加者が質問　→ 講師ないし有識者が回答　→ 参加者が質問...loop
の流れです。

# どんな様子？
講師としてCTOの西出が場をファシリテートしつつ、お昼時だったので、参加者はサブウェイのサンドイッチを頬張りながら、議論を交わしました。

<img width="1209" alt="Screen Shot 2019-05-30 at 15.31.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48954/cb780752-8476-0161-a55f-d52ef43a9aef.png">

<img width="494" alt="Screen Shot 2019-05-30 at 15.31.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48954/5b31a7b8-7385-a409-9c29-4ed1056dc5cf.png">

# どんな感じだった？
「ブロックチェーンとは何か」というトピックに対して「容量的に大丈夫？」とか「量子コンピュータが実用化しても問題ない？」とか「台帳はいったいどこにあるのよ！」のように議論が様々な方向に派生してゆきました。ブロックチェーン知ってる人としては、聞いていて面白かったです。

中でも「スマートコントラクトをロードバランサーのように並列処理すれば早くなるのでは？」という質問に驚きました。
つまりShardingです。Ethereum研究者が目下、研究中のスケーリングソリューションを、ブロックチェーンを知らない人が思いついていましたw

# 最後に
勉強会の内容は、次回以降も記事にしてゆきます。

また、フィナンシェではエンジニアを募集してます。本番運用している、ゲーム関連以外のブロックチェーンを使ったコンシューマー向けサービスは少ないです。実践的な経験が積め、知見が溜まりますよ。

ご興味のある方は是非、[採用フォーム](https://docs.google.com/forms/d/e/1FAIpQLScIWx8Vu3NkOFk0Zc7Qho-eAdyhSQM5CblJgbhLeM7yKCDzGQ/viewform)か[Wantedly](https://www.wantedly.com/companies/company_8586948/projects)からお声がけください。

*勉強会記事一覧*
- [フィナンシェでブロックチェーン勉強会、始めました。](https://qiita.com/tak1827/items/c4db3cdba5f05db1375b)
- [Libraについての勉強会](https://qiita.com/tak1827/items/460533ee917b4911b7cc)
- [フィナンシェのBlockchainアーキテクチャ変遷と今後](https://qiita.com/tak1827/items/cb6d2aa4524bdaacd99f)
【JavaScript】jQueryっぽく使う

#appendTo
```js
if(Element.prototype.appendTo === undefined){
    Element.prototype.appendTo = function(el){
        document.querySelector(el).appendChild(this);
    };
}
```
#prependChild
```js
if(Element.prototype.prependChild === undefined){
    Element.prototype.prependChild = function(el){
        this.insertBefore(el, this.firstChild)
    };
}
```
#parent
```js
if(Element.prototype.parent === undefined){
    Element.prototype.parent = function(){
        return this.parentNode;
    };
}
```
#eq
```js
if(Element.prototype.eq === undefined){
    Element.prototype.eq = function(n){
        return this[n];
    };
}
```
#matches
```js
if (!Element.prototype.matches){
    Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
}
```
#closest
```js
if (!Element.prototype.closest) {
    Element.prototype.closest = function(s) {
        var el = this;
        if (!document.documentElement.contains(el)) return null;
        do {
            if (el.matches(s)) return el;
            el = el.parentElement || el.parentNode;
        } while (el !== null && el.nodeType === 1);
        return null;
    };
}
```
#position
```js
if (!Element.prototype.position) {
    Element.prototype.position = function(s) {
        var el = this;
        return {
            left: el.offsetLeft,
            top: el.offsetTop
        };
    };
}
```
#addClass
```js
if (!Element.prototype.addClass) {
    Element.prototype.addClass = function(str) {
        var el = this;
        el.classList.add(str);
    };
}
```
AngularのCanActivateでログイン成功後にログイン前のページへ遷移させたときのお話

AngularのCanActiveで、未ログイン時にlogin画面へリダイレクトされる際に、リダイレクト前のURLを取得するお話。

そのページのURLを取得する情報はあったりしますが、意外とCanActiveでのURL取得の情報はなかったため書いてみました。

```typescript
export class SessionGuard implements CanActivate {
  constructor(
  	private sessionService: SessionService,
  	private router: Router,
  ) {}

  canActivate(
    next: ActivatedRouteSnapshot,

    state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {

	  if (!this.sessionService.session.token) { //もしセッション・トークンがなければ
			let navigationExtras: NavigationExtras = {
	        queryParams : {
	          'error': 'ログインして下さい。' , //表示するエラーの内容
              'prev_url': next.url //リダイレクト前のURL
	        }
	    };

	    this.router.navigate(['/login'], navigationExtras); //ログイン画面にリダイレクト

      return false;
	  }

    return true;
  }
}
```

どうやら、通常通りのActivateRouterから、URLを取得しようとすると、
もうひとつ前のページのURLを取得してしまうので、
next: ActivatedRouteSnapshot から、URLを取得する必要があるようです。

結構、英語の記事たと、こういった細かい内容の記事を見つけることができますが、
Angularでは、あまりないようですので、今後も書いていきたいと思います。
AWS Tools for PowerShell を使う

# AWS Tools for PowerShell インストール

powershellを管理者で起動して以下を実行する

```powershell
C:\var\aws
[PS]>Install-Module -Name AWSPowerShell

続行するには NuGet プロバイダーが必要です
PowerShellGet で NuGet ベースのリポジトリを操作するには、'2.8.5.201' 以降のバージョンの NuGet プロバイダーが必要です。NuGet
プロバイダーは 'C:\Program Files\PackageManagement\ProviderAssemblies' または
'C:\Users\MichiakiOkada\AppData\Local\PackageManagement\ProviderAssemblies' に配置する必要があります。'Install-PackageProvider
-Name NuGet -MinimumVersion 2.8.5.201 -Force' を実行して NuGet プロバイダーをインストールすることもできます。今すぐ
PowerShellGet で NuGet プロバイダーをインストールしてインポートしますか?
[Y] はい(Y)  [N] いいえ(N)  [S] 中断(S)  [?] ヘルプ (既定値は "Y"): y

信頼されていないリポジトリ
信頼されていないリポジトリからモジュールをインストールしようとしています。このリポジトリを信頼する場合は、Set-PSRepository
コマンドレットを実行して、リポジトリの InstallationPolicy の値を変更してください。'PSGallery'
からモジュールをインストールしますか?
[Y] はい(Y)  [A] すべて続行(A)  [N] いいえ(N)  [L] すべて無視(L)  [S] 中断(S)  [?] ヘルプ (既定値は "N"): y

C:\var\aws
[PS]>Import-Module AWSPowerShell

C:\var\aws
[PS]>get-module

```

## 認証情報の設定

認証情報を保存

```
PS C:\> Set-AWSCredential -AccessKey xxxxxxxxx -SecretKey xxxxxxxx/xxxxxxx/xxxxxxxxxxxxxxxxx -StoreAs MyProfileName
```

_認証情報の管理については別途検討すること_

### 例) S3バケットのオブジェクト一覧

```
C:\var\aws
[PS]>Get-S3Object -BucketName <bucketname> -ProfileName MyProfileName
```
-ProfileName には 保存した認証情報に付けたプロファイル名称を指定する。
-BucketName には -ProfileName で指定するプロファイルがアクセスできる S3バケットの名称を指定する

## 起動スクリプトとショートカットを作成する

### 起動スクリプト

PowerShellを起動して毎回 Import-Module AWSPowerShell を実行するのは面倒なので、起動するクリプトを作成する

```awstools.ps1
Import-Module AWSPowerShell
```
他、必要な環境変数などがあればそれらを設定するコードを awstools.ps1 として保存する。

### ショートカット

以下の内容を持つショートカットを作成する

* リンク先 powershell.exe -noexit C:\(awstools.ps1を保存した場所)\awstools.ps1
* 作業フォルダ 適当な場所

## 起動

作成したショートカットを実行する

## その他

https://aws.amazon.com/jp/powershell/ から インストーラーがダウンロードできるけど、これだと スクリプトセキュリティの警告がでたり PowerShell ISEだと警告がなかったりするので微妙に使いづらいので パッケージ伊マネージャを利用する方が個人的に楽。
Java繰り返し処理：for while 職業の勉強。と、プログラミング言語理解。

今回はfor whileの繰り返し処理を勉強してみました！


繰り返し処理の書き方は「while (条件式) {処理}」のように書きます。

まずは変数の初期化を行い、値を「０」にします

次にwhileと書き()の中に繰り返しの条件式を書きます

そのあとに、数値を表示させる処理を書き、

「i++;」で 「i」 を「 1 ずつ増やして」あげます

今回は、「i が 10より小さい間、次の処理を繰り返しなさい」という意味になります

 

流れ的には、「i」が「10」以下の場合、この「( i < 10)」 条件を満たすので、

10回繰り返し処理が行われ 、最終的に「 i」 が「 10」 になった時に「( i < 10)」 の条件を満たさなくなるので、

ループを抜けて、最終的に 0 から ９ が表示される、 といった流れになります。

繰り返し処理の書き方は「do{処理} while (条件式) ;」のように書きます。

「while文」では二種類の使い方があるので二つとも覚えておくと良いかと思います。



![for文での繰り返し処理.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427747/9b5e76eb-f91b-862f-62ff-a70033052074.png)
![while文の繰り返し処理.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427747/dbb6372f-70b3-9a27-4624-3cf8ddefc630.png)


この処理がどこでどのような場面で使うのか、気になります（笑）


ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
プログラミング言語でどのようなサービスが出来るのか少し深堀してみました。

Java→業務系システムや大規模なシステムで一番使われている。
（作業の自動化、手間のかかる仕事を効率）

Ruby→インターネット上で利用できるアプリケーション。
（例「Amazon」や「ぐるなび」など）

PHP→商品利用のWEBサービスを簡単に作成。
（ショッピングカートや問い合わせフォーム、SNSとの連携など）
・ネットショップを開きたい方、世界に向けて商売をしたい方におすすめ。

Python→最先端アプリ
（人工知能、統計分析、科学技術計算など数学を使う難しい処理の簡略化）
・ビッグデータや人工知能に興味がある人向け。

～スマホアプリ、ゲーム作りに興味がある人向け～
Swift→iosアプリ開発
・ Iosとは？オペレーティングシステムの略。アップルが開発、提供するモノ。
・Macのアプリも作ることができる。Appleユーザーは楽しめる。

Java→Androidのアプリを作りたい人向け。
・システム以外でも活躍。
・AndroidのアプリやPCのソフトも作れる汎用性の高い言語。

Unity（C#）→3Dゲーム
（WindowsやMac、スマーフォンが主）
・オンラインゲームやスマホのゲームアプリが大人気なので覚えとくと便利かも！

～簡単なWEBサイト・ページやゲームを作りたい人～
HTML→webサイト
・WEB上の画面を作る言語
それ以外でも、、、
・WEBアプリやスマホアプリ作成も可



JavaScript→WEBページ、ゲーム
（HTMLとセットで使われる。画面上に動きを付けるなど、応用範囲が広い）

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

感想と興味を抱いた言語
感想
・プログラミング言語を初める前に、何が出来るのか抑えることが大切でした（笑）
・簡単に説明しましたが、プログラミング言語は他にも200以上も存在しているとか💦
・qiitaを利用する上でも、言語の知識があれば楽しく見れそうですね！

職業が興味を持った言語
・PHP
・HTML
・JavaScript
個人的に基礎的要素が含まれている言語かなと思います（笑）
GASでStackdriverする 2019/4/9〜

GASでデバックしようと「表示」「Stackdriver Logging」しようとすると以前と違うダイアログ

<img width="693" alt="スクリーンショット 2019-06-03 15.18.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7370/60189dfc-839c-2f73-1020-f127d5b59939.png">

GCPのプロジェクトが勝手に作成されなくなったみたい

> Warning: Starting on or after April 8, 2019, the Google Cloud Platform Console won't be able to access the default GCP projects created for new Apps Script projects. Older, existing scripts may have default GCP projects that are still accessible, however. If you have a new script and require access to its GCP project from the Google Cloud Platform Console, you must use a standard GCP project.

https://developers.google.com/apps-script/guides/cloud-platform-projects#switch_to_a_different_google_cloud_platform_project

- GCPプロジェクトを作成する
- GASから　「リソース」「Cloud Platfome プロジェクト...」　でGCPプロジェクトの紐づけをする
AWS EC2にAI開発基盤KAMONOHASHIを構築する

OSSのAI開発基盤[KAMONOHASHI](https://github.com/KAMONOHASHI/kamonohashi)をAWS EC2に構築してみます。
オンプレ前提のインストーラのため、構築に少し手間がかかります。

# 手順概要
* EC2インスタンスを用意します
* インスタンス内でデプロイツールを実行します
  * マシン名にはプライベートDNSのものを使用します
* 設定修正
  * 構築完了後にプライベートDNSの設定を書き換えて、外部からアクセス可能にします

お試しで構築する想定なので、セキュリティなどはいろいろ省略します。
KAMONOHASHIはバージョン1.0.0を使います

# 構築手順
## EC2インスタンスを用意
* EC2インスタンスを作ります
  * EC2インスタンスのの作成でAMIは Ubuntu 16.04 x86を選びます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304012/913eadcc-ea85-4784-5656-abd427dcdef5.png)

  * インスタンスタイプは[ドキュメント](https://kamonohashi.ai/docs/install-and-setup#%E6%A7%8B%E7%AF%89%E3%81%AE%E6%BA%96%E5%82%99) の表に従って選択します
      * KAMONOHASHIノードはc5.xlarge、k8s,storageはt3a.small、GPUはg3s.xlargeなどになります
  * インスタンスの設定タブで、cloud init機能による初回起動時のapt updateを設定しておきます。
      * インストーラーがエラーにならないおまじないです。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304012/a5c4491e-7624-d8d4-efb2-c9ab5757953c.png)

        ```text:これをユーザーデータ欄に貼り付けでください
        #cloud-config
        
        package_upgrade: true
        ```
  * 確認と作成からEC2インスタンスを作成します
      * すべて同じキーペアを指定してください

* セキュリティグループを設定します 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304012/c4ae9c4a-7f99-bc33-57bd-15c3c581a28a.png)

  * 内部通信(デフォルトVPCでは172.31.0.0/16)はすべて許可します。このサブネットはVPCに応じて設定してください。
  * 外部からssh, 80(webアクセス)、9000(ストレージアクセス)のTCPポートを開けておきます
    * 簡単のため、すべてのEC2インスタンスで同じ設定とし、任意のGlobal IP を許可します 

* sshでGPU用インスタンスに入り、NVIDIA DRIVERをインストールします

## インスタンス内でデプロイツールを実行
* k8s用のEC2インスタンスにsshします
  * sshに使用したpemファイルをrootユーザーの`~/.ssh/id_rsa`ファイルとして配置します
* [構築マニュアル](https://v1-0-0.kamonohashi.ai/docs/install-and-update)の作業を行います
  * マシン名はプライベートDNSのものを使用します
      ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304012/5b26abc9-f829-71fe-5a5c-bc0cd76980b3.png)
  * デプロイツールへの入力はこんな感じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304012/a35a2544-5b46-0256-cc02-ec65857c2831.png)

* 構築完了まで待ちます。20分ほどかかります
 
## 設定修正
* `/var/lib/kamonohashi/deploy-tools/1.0.0/kamonohashi/deploy-kqi.sh clean`を実行してKAMONOHASHIのコンテナを止めます
* `vi /var/lib/kamonohashi/deploy-tools/1.0.0/kamonohashi/conf/settings.yml`を実行します
  * virtualHostsの部分のプライベートのホスト名をKAMONOHASHI用インスタンスのパブリックのホスト名に書き換えます
      * before  
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304012/07029fe9-8634-1f7a-f6cb-c00c37af0ed6.png)

      * after  
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304012/08fc588e-ba5c-c759-9c78-9b42b9d1eaef.png)

* `/var/lib/kamonohashi/deploy-tools/1.0.0/kamonohashi/deploy-kqi.sh deploy`を実行してKAMONOHASHIのコンテナを起動します

* 上記で設定した外部host名でログインします
  * ストレージ設定の`Default-storage`を編集し、サーバー名URLをストレージ用EC2インスタンスのパブリックのホスト名に書き換えます  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304012/f841620d-ecae-4cd9-830b-813e9835b235.png)


以上です。あとは[チュートリアル](https://kamonohashi.ai/docs/tutorial)を実行して動作確認してみましょう
JS 数値を カンマ区切り かつ 小数点以下をゼロ埋め して表示する

Javascript で数値を カンマ区切り かつ 小数点以下をゼロ埋め して表示する方法につまづいたので備忘録で書いておきます
(今回は小数第4位で切り捨てする形で書きます)

## やりたかったこと
12345 → "12,345.000"
12345.67 → "12,345.670"
12345.6789 → "12,345.678"

## 最初に書いてたコード

```js
const digit = 3;
const number = 12345.67;
number.toFixed(digit).toLocaleString();
// "12345.670"
```

と、カンマが表示されませんでした。

## 解決策
[toLocaleString](http://js.studio-kingdom.com/javascript/number/to_locale_string) が有能だった

```js
const digit = 3;
const number = 12345.67;
number.toLocaleString(undefined, {
    minimumFractionDigits: digit,
    maximumFractionDigits: digit
});
```
わたしの仕事術 on Mac with G suite

社内向けに書いたやつでコンプラな内容を除外したメモ。

## 入れるべきツール
### 必須ツール
#### Google Cloud SDK
* GCPの案件の会社なので入れないと話が始まらない。
* Macの人、`sudo` は使いません。pythonとかでも基本、使わないので覚えておいてください。

#### Visual Studio Code
* terraformの支援プラグインが強い。最近vim-mode pluginもかなりマトモになった。
* markdown書くのに便利
* 軽い。ワークスペースとかリポジトリ連携とか色々全部揃っている。白背景テーマがある(重要)

#### iterm2(ないし、何らかのマトモなterminal)
* tmuxとかscreen的な機能が最初から提供されているのでおすすめ。

#### スクショ・画像加工
* monosnap
  * Macではあると便利
* FireAlpaca
  * プレビュー.appでもいいけど。あると便利

### 趣味のツール
* fish shell
  * agnoster/bobthefishテーマを入れるとプロンプトにgitのbranch名とmerge状況を出せる。これが無いとつらい。
  * bash派にも `agnoster for bash theme` を入れれば同じことはできます。
* brew
  * MacはMacのbrew、WinはCloud Shell上でLinux Brewを推奨。
* Magnet for Mac
  * キーボードでウインドウを1/3とか2/3とか最大化・復元とかできるやつ。
* Clipy (クリップボード履歴、定型文入力) for Mac
  * 日報とかコマンドのカンペとか色々できる。
* Karabiner-Elements
  * リマップするやつ
  * terminal/vimで日本語入力するときに困る、とかを解決できる
  * 日本語キーボードを英語配列で使ったり…まあ趣味ですね

## chromeアドオン
### GCPの日本語ドキュメントが更新日付2年前なんですが…？
* よくある。英語版だけ更新される。
  * そんなアナタに[GCP outdated docs checker](https://chrome.google.com/webstore/detail/gcp-outdated-docs-checker/pmiiahfejcjiilbfmagplnchilclgdgh)

### gmailの左側でハングアウトはマジで使いづらい
* [ハングアウトクライアント](https://chrome.google.com/webstore/detail/google-hangouts/nckgahadagoaajjgafhacjanaoiihapd)

### ウッ！英語サイト！頭痛が…
* [Google飜訳使えや](https://chrome.google.com/webstore/detail/google-translate/aapbdbdomjkkjkaonfhkkikfgjllclebkj)

### タブ開きすぎて動作が遅い！困った
* [One Tabでいったん閉じましょう](https://chrome.google.com/webstore/detail/onetab/chphlpgkkbolifaimnlloiipkdnihall)

### アホほど開いてしまったタブの中から要るタブを探す
* [MacだとCmd-e WinならCtrl-eで起動](https://chrome.google.com/webstore/detail/quick-tabs/jnjfeinjfmenlddahdjdmgpbokiacbbb)

### わざわざGoogleドライブのページを開かずに直接アドレスバーから検索したい
* [omni drive](https://chrome.google.com/webstore/detail/omnidrive/gpnikbcifngfgfcgcgfahidojdpklfial)

### あのカッコイイ日報が何なのか気になる
* [markdown + CSSでデコメールできるやつ](https://chrome.google.com/webstore/detail/markdown-here/elifhakcjgalahccnjkneoccemfahfoa)

### ちょっとマニアックなやつ
#### タブバーが細過ぎてタイトルが何なのか、コレガワカラナイ
* [表示するやつ](https://chrome.google.com/webstore/detail/show-title-tag/pkbffbhglicfngmppdlpmpblfgnkdgio)

#### Hit-A-Hintしたい(キーボードでページナビゲーション)
* [これ](https://chrome.google.com/webstore/detail/moly-hah/pjoacnohgednppackhamgfalpkffeeek)

#### Google検索結果にスクショくっつけるやつ
* [これ](https://chrome.google.com/webstore/detail/searchpreview/hcjdanpjacpeeppdjkppebobilhaglfol)

## gmailおすすめラベリング & テクニック
以下のような観点で設定してます。(あくまでも目安)

1. 英字のprefix(`a`自動メール 等)をつけておくとフィルタジャンプしやすい( `g l` と押してタイプしてジャンプ)
2. 多過ぎる報告メールは、チームメンバー等読んでおきたい人だけ特別なラベルに振り分け、ほかは一括で既読化 & アーカイブ
  * 読み終えたら `y`を押すとタグを抜くことができるので、どんどん消していく
1. 機械送信メールは自動メールに分ける
Three.jsの勉強で参考にしたサイトまとめ

#座標軸の作成
http://ailaby.com/three_axis/

#DOMについて
https://eng-entrance.com/what-is-dom
DOMとはJavaScriptでhtmlの要素を操作するための仕組みのこと。

#three.jsのOrbitControls.jsで簡単にカメラをマウスコントロールする
https://qiita.com/FumioNonaka/items/92db20635d751f093421

#css overflowについて
overflowとはCSSのプロパティの１つで「要素のボックスからはみ出た部分をどう扱うか」を指定する。
https://saruwakakun.com/html-css/basic/overflow

#Ajaxの理解
https://qiita.com/hisamura333/items/e3ea6ae549eb09b7efb9
AWS WorkSpaces に固定 IP アドレスを付与する


[Concrete CMS](https://concrete5-japan.org) を実装している弊社のメインPCはMacなのですが、時々Windows表示確認が必要です。

AWS WorkSpaces を活用してみましょう。

しかし、お客さんのサイトを確認する時に、アクセス制限をかけている場合があります。IPアドレス制限をする際、WorkSpacesの端末も固定IPにする必要がありました。

固定IPを Elastic IP で付与する方法です。

## STEP 1: WorkSpace のネットワークインターフェース ID を確認する。

1. AWS コンソールに、必要な権限のあるユーザーでログイン
2. WorkSpace メニューに行く
3. 固定IPアドレスを紐づけたい WorkSpace の `WorkSpace IP` の値を確認。あと、起動して WorkSpace 内から、[IP アドレスを判別するサービス](https://whatismyipaddress.com/) にアクセスして今のパブリックIPアドレスを確認する。
2. EC2 メニューに行く
3. 左ペインの「ネットワーク・セキュリティ」の中の「ネットワーク・インターフェース」をクリック。
4. いっぱい出てくると思うので、`Created By Amazon Workspaces`というキーワードで検索。
5. 結果を右にスクロール。さきほど取得した `IPv4 パブリック IP` と `WorkSpace IP` と `プライマリー IP4v` の数値が同じネットワークインターフェースを探す。
6. 見つけたネットワークインターフェースID 例: `eni-xx000000` をコピー・メモ

## STEP 2: EIP を取得＆関連付ける 

7. Elastic IP メニューに訪問
8. 新しい IP アドレスをリクエスト
9. 新しく取得した IP アドレスをクリック。
10. `アクション`メニューから`アドレスの関連付け`を選択
11. リソースタイプは`ネットワークインターフェース`
12. `インスタンス`はさきほどコピペしたネットワークインターフェースIDで検索して出ていたものを選択。
13. 「関連付け」ボタンで実行。
14. 固定 IP が付与されたかを確認
    - AWS Management Console 内の WorkSpaces インスタンスを探して IP アドレスが変わっているかを確認
    - 起動して WorkSpace 内から、[IP アドレスを判別するサービス](https://whatismyipaddress.com/) にアクセスして今のパブリックIPアドレスを確認する。

これで WorkSpace に固定 IP アドレスが付与されます。
R言語でアニメーション

研究室で得たデータの動きが見たかったからRでアニメーションを作れないかな？と思った。
できるね。

animation
ggplot2
gganimation
gifski
png
ここら辺入れておけば多分大丈夫

あとはいつも通りに
ggplot()+geom_point()+transition_reveal()またはtransition_time()

レンダリングにちょっと時間かかる。俺の扱ったデータだと十数秒くらい。


transition_time()のほうが使いやすい感じ。
で、これだと早すぎて困ったから遅くする方法を探してきた。
https://stackoverflow.com/questions/52899017/slow-down-gganimate-in-r
animateで指定すればいいんだな。
とりあえずaにアニメーションを1回入れた後にduration（再生秒数）とfps（1秒当たりのコマ数）を指定すればレンダリングしたあとにアニメーションが見れる。
30fpsとかにするとレンダリング1時間とか言われてしまうので注意。


例

```
a = ggplot(data=kohinatamiho,aes(x=Length,y=Width)) + geom_point() +  labs(title = 'Date: {frame_time}')+shadow_wake(wake_length = 0.05, alpha = FALSE) + theme_bw() + transtion_time(Time)
```

```
animate(a,duration=300,fps=2)
```

あとshadow_wakeのwake_lengthは全体のフレーム数に対して何%のフレームを残像として残すかを指定できる（0～1の間の値で）
とマニュアルには書いてあるから全体で27000フレームある時に0.01を指定したら270フレーム分の残像が残る‥？のかな？とりあえず値小さくすれば残像の数が減りますということだけ。

参考にした記事
https://qiita.com/YM_DSKR/items/8899faef67f393a8fca4
Panasonic製ネットワークカメラの画像を取得して顔検出をしてみる

# はじめに

ネットワークカメラの画像を分析する必要がでてきたのですが、試してみた内容がそこそこ面白かったのでまとめてみました。

# 必要なもの

- [Panasonic製I-PRO SmartHD](https://sol.panasonic.biz/security/camera/ipro_hd/)
- [仕様書(ネットワーク カメラCGIコマンドインターフェース仕様書)](https://sol.panasonic.biz/security/cgi-bin/ipro/download/tbookmarka_m.cgi?m=%20&mm=2012100910461872)
- Python3
- OpenCV


# 画像の取込から顔画像の保存

以下のスクリプトを作成。

```py:face_detection.py

import requests
from requests.auth import HTTPDigestAuth

import io
from PIL import Image
import numpy as np
import cv2

# カメラのIPアドレス　192.168.0.10
# 画像データの取得　　/cgi-bin/camera
# 解像度の指定　　　　resolution
url = "http://192.168.0.10/cgi-bin/camera?resolution=1280"

# 認証情報
user = "*****"
pswd = "*****"

# 顔を識別するためのファイル
cascade_file = "haarcascade_frontalface_alt2.xml"
cascade = cv2.CascadeClassifier(cascade_file)

while True:
    
    # 画像の取得
    rs = requests.get(url, auth=HTTPDigestAuth(user, pswd))
    
    # 取得した画像データをOpenCVで扱う形式に変換
    img_bin = io.BytesIO(rs.content)
    img_pil = Image.open(img_bin)
    img_np  = np.asarray(img_pil)
    img  = cv2.cvtColor(img_np, cv2.COLOR_RGBA2BGR)
    
    # 顔検出のためにグレイスケール画像に変換
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 検出した顔の位置情報を取得
    face_list = cascade.detectMultiScale(img_gray, minSize=(100, 100))

    # 顔を検出したらループ処理を終了
    if len(face_list) != 0:
        break

cat = 0
now = "{:%Y%m%d%H%M%S}".format(datetime.datetime.now())

for (pos_x, pos_y, w, h) in face_list:
    
    # 顔の切出
    img_face = img[pos_y:pos_y+h, pos_x:pos_x+w]
    
    # 顔画像をリサイズし、サイズを統一
    img_face = cv2.resize(img_face, (200, 200))

    # 番号を付けて保存
    cv2.imwrite("{}_{}.png".format(now, cnt),img_face)
```    

# 実行

コマンドプロンプトなどで以下のとおり実行。

```sh:
python face_detection.py
```

スクリプトと同じフォルダに検出した人の顔があれば成功！

はい、できました。
[Ruby]pluckメソッド

書き方

```
@post = Post.pluck(:id,:title)
```
例

```
pry: @post
=> [[1,abc], [2,cde], [3,efg], ...]
```




下記ようにPostモデル内のtitleカラムを一覧表示することができる。

```
Post.pluck(:title)
=> ["Tote",
 "Bag",
 "Baseball Jersey",
 "Jr.Spaghetti",
 "Ringer T-Shirt",
 "Ruby Baseball Jersey",
 "Apache Baseball Jersey",
 "Mug",
 "Stein"]
```
また、このように第二引数を設定することも可能。

```
Post.pluck(:id,:title)
=> [[1, "Tote"],
 [2, "Bag"],
 [3, "Baseball Jersey"],
 [4, "Jr. Spaghetti"],
 [5, "Ringer T-Shirt"],
 [6, "Ruby Baseball Jersey"],
 [7, "Apache Baseball Jersey"],
 [8, "Mug"],
 [9, "Stein"]]
```

ちなみに下記は同じ意味のコード

```
Post.select(:id, :title).map { |c| [c.id, c.title] }
```
シンプルに出来る


参考
https://qiita.com/k-o-u/items/31e4a2f9f5d2a3c7867f
Ayana の使い方(導入編)

#Ayana とは？
Ayana(以後アヤナ)とは__Discord__の総合エンターテイメントBOTです

#何ができるの？
アヤナでは以下の機能を使うことができます

- 絵文字を利用したテキストの拡大
- コインを投げる
- 占いを行う
- アヤナに喋らせる(テキスト返してくれる)
- ギルド機能
- ネットミーム等の画像をランダムで表示
- をボイスチャンネルにYoutubeの音声を流してくれる
- 特定のユーザーのアイコン取得
- など

#どうやって招待するの？

まず公式サイトのアクセスします

Ayana公式サイト
[リンク](https://ayana.io/)

1.右上のメニューにある[invite]をクリックしてください
![Frame.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126732/a97c7cc5-4f94-fafa-9d0f-448caec44b39.png)

2.タブから招待したいサーバーを選択し[認証]をクリックしてください
![421782e6fed3201c6431b2ed06536155.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126732/63e0c801-8dd1-eb05-939b-fb2415b4a8b2.png)


3.私はロボットではありませんのチェックを入れてください
![f5e83f25820dd27e642c7814d694c27f_Trim.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126732/3afb2cf3-2a66-3deb-b623-ea6aad79afa7.gif)

これで導入は完了です、次は基本的にな操作であるコマンドについて記載する予定です
【AWS】SESで受信したメールをGmailなどへ転送する方法

#参考にするべき記事
参考記事
https://tech.taiko19xx.net/entry/2018/05/01/195119
元となったGithubライブラリ
https://github.com/arithmetric/aws-lambda-ses-forwarder
#方法
方法に関しては上記記事を参考にすれば完璧にこなせます。
特にGithubライブラリの【README.md】に関して熟読しつつ行えば良いでしょう。
#エラーへの対処
```CloudWatch
sendRawEmail() returned error
-----
{ AccessDenied: User `arn:aws:sts::01234567:assumed-role/SesForwarder-role-aaaooo/SesForwarder' is not authorized to perform `ses:SendRawEmail' on resource `arn:aws:ses:us-east-1:1234567:identity/contact@example.com'

```
このようなSESに関するエラーが出てくるのですが、これへの対処方法を説明します。

###対処方法
まず、紐づけているポリシーを確認するためにIAMへ行き、「ポリシーの編集」から「ポリシーのビジュアルエディタ」を確認してみてください。
SESの所に【警告】が表示されていると思いますので、その警告を解除するためにリソースなどを設定してください。
（私の場合はリソースを「すべて」に変更することで警告はなくなりました。）


警告がなくなり、リソースを「すべて」に変更したことによってきちんとエラーがない状態で転送することができました。
Windows , MacOS , Linux で一番使いやすいOSとは？

#はじめに
私は、大学４回生でプログラミングを勉強しています。
現在、未来電子テクノロジーでプログラミング開発コースでインターンを行なっています。
今回は、OSについて勉強している時に理解した部分をお話しします。

プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。

#OSとは
OSは、「Operating System」の略で、コンピュータを支える最重要ソフトウェアです。
コンピュータで当たり前の機能を、OSが担っています。
・キーボードで打った文字を画面に表示させる
・マウスを移動すると、画面上の矢印の位置が移動する

また、プログラミングを行う際にもOSは、重要な機能です。
OSの仕組みを知っていないと、バグが生じる可能性があります。
プログラミングを始める方は、ぜひ勉強することをオススメします。

#3つの特徴とは？
1, Windows
Windowsは、開発環境を整えるのが、難しい。
RudyやGitを使用すると、困難である。

2, Mac OS
Mac OSは、zsh、Vim、tmuxを問題なく使えて、ターミナルで簡単に開発できる。
この１つで残り２つの機能を補えるので、Mac OSだけでも開発に困ることは無い。

3, Linux
Linuxは、zsh、Vim、tmux、gitが問題なく動くOSです。
テキスト処理やプログラミング開発に関しては、一番使いやすい。
一番簡単に扱えます。

#まとめ
OSは、まだまだわかっていない部分が多いです。
まずは、MacOSでプログラミングを勉強します。

#参考文献
Linux, Mac, Windows 3つのOSの使いどころ比較
http://mollifier.hatenablog.com/entry/2015/03/13/222033
DifferencesBetweenLinux vs MAC vs Windows
https://www.educba.com/linux-vs-mac-vs-windows/
misfit ray分解記


2018/2/7に届いたmisfit rayが、先日反応しなくなった。

せっかくなので、分解して、中を見てみます。



![IMG_0878.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26886/c0e9f982-fa2f-0fff-e49c-8dddd8ba3116.jpeg "IMG_0878.JPG")



電池側を外す
![IMG_0880.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26886/eb245dcb-74e0-5f7e-6760-8ea398aaa615.jpeg "IMG_0880.JPG")


普段は外れない方(基盤が詰まっていると思われる方)をコネコネしてたら、外れた。
![IMG_0881.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26886/c843ad5e-ea92-8fde-8e2b-325050de1f17.jpeg "IMG_0881.JPG")


こんな感じ。接着剤で付いている。
![IMG_0882.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26886/95de3ad9-6a9a-cebb-2d4e-3215cff57f77.jpeg "IMG_0882.JPG")


接着剤は溶けてた。シャワーOKだが、アチアチな湯に浸かったことが原因かなぁ。


中身はこんなかんじ。
![IMG_0883.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26886/a0b16448-c681-2325-5bb9-961d45966d3a.jpeg "IMG_0883.JPG")
縁が白いのは、壁とかにぶつけて、塗装が剥げているから。ゴミとかじゃない。


基盤をピンセットで引っ張ったら、外れた。
![IMG_0886.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26886/b4b43054-0c26-d997-e774-732c3a2f58f6.jpeg "IMG_0886.JPG")

亀の子になってる。
ちいちゃい。下の方の真鍮色のはGNDっぽい。
![IMG_0885.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26886/133634fa-7d25-f96e-7a70-0fb62d6c0569.jpeg "IMG_0885.JPG")

ケーブルが切れたので、もう終わり。


![IMG_0887.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26886/2a1759dc-9c0d-1a18-727a-33e8c4744261.jpeg "IMG_0887.JPG")

QRっぽいもの。
QR読み取りでは反応しなかった。

本体の筒
![IMG_0888.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26886/0df43084-d74d-32c8-87e9-9508a8a7bd84.jpeg "IMG_0888.JPG")

ただのアルミの筒になった。



----
misfitの良かったところ、悪かったところ

【良かった】
・軽い
・充電しなくていい


【悪かった】
・心拍は測れない

・同期に難あり
　→遅い
　→トラッキング中とかで失敗することが多い
　→同期を1日忘れると、前日のデータが？！

・隙間にめっちゃゴミが溜まる
　→歯ブラシで掻き出すべし
　
・電池交換の際に、気密に失敗して錆々にした人を2人知っている
　→Ｏリングがちゃんとハマっているか、きちっと確認すべし
cocoapodsでgem installのpermissionErrorがでたので解決法まとめ(2019)

# 問題
cocoapodsを使いたくてgem installしようとしたらpermissionErrorが出て少しハマったのでまとめ

# 解決方針
僕の場合は以下のどちらかを試したらできました
①シンプルに管理者権限を与える
②rbenvでrubyを管理するようにし、gemをインストールする権限を与える
homebrewをインストール→brewでrbenvインストール→rbenvでruby管理できるようパスを通す
# 解決法①
・シンプルに管理者権限を与える

```
$ sudo gem install cocoapods
```

こうなったら解決です、お疲れ様でした

```
$ gem install cocoapods
Password:
Fetching: thread_safe-0.3.6.gem (100%)
、、、、、、、、
?? gems installed
```
# 解決法②
・rbenvでrubyを管理するようにし、gemをインストールする権限を与える
まずはgemとrubyの場所を見てみましょう
今はシステムのパスを指しているので、これをrbenvの管理下になるよう設定していきます

```
$ which gem
/usr/bin/gem
$ which ruby
/usr/bin/ruby
```
homebrewを入れます

```
$ brew update
-bash: brew: command not found
```
こんな感じでダメだった場合は、以下を直接試すか[homebrew](https://brew.sh/index_ja)のサイトの指示に従いましょう

```
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
command Line Toolsが入ってなければそれもインストールする流れになります(結構待たされますが気長に待ちましょう)
コマンドが入力できるようになったらインストールできてるか確認しましょう、以下なら成功です

```
$ brew update
Already up-to-date.
```
rbenvを入れます

```
$ brew install rbenv ruby-build
、、、、、、、、
$ rbenv versions
* system (set by /Users/ユーザー名/.rbenv/version)
$ rbenv install -l
Available versions:
  1.?.?-p??
  1.?.?-p??
　、、、、、、、、
  2.6.3
  2.7.0-dev
  、、、、、、、、
$ rbenv install 2.6.3
ruby-build: use openssl from homebrew
Downloading ruby-2.6.3.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.3.tar.bz2
Installing ruby-2.6.3...
Installed ruby-2.6.3 to /Users/ユーザー名/.rbenv/versions/2.6.3
```
バージョンを確認した際、以下なら成功です、2.6.3というバージョンが最後にしっかり書かれてます

```
$ rbenv versions
* system (set by /Users/ユーザー名/.rbenv/version)
  2.6.3
```
最後にbashスクリプトにPATHを通します

```
$ touch ~/.bash_profile
$ touch ~/.bashrc
$ echo '# rbenv' >> ~/.bash_profile
$ echo 'export PATH=~/.rbenv/bin:$PATH' >> ~/.bash_profile \
> eval "$(rbenv init -)"
$ source .bash_profile
```
rubyとgemの場所を確認した際、以下なら成功です(rbenvのパスになっていてrbenvの管理下になってます)

```
$ which ruby
/Users/ユーザー名/.rbenv/shims/ruby
$ which gem
/Users/ユーザー名/.rbenv/shims/gem
```
こうなったら解決です、お疲れ様でした

```
$ gem install cocoapods
Password:
Fetching: thread_safe-0.3.6.gem (100%)
、、、、、、、、
?? gems installed
```

# 参考文献
・[gem installでpermissionエラーになった時の対応方法]
(https://qiita.com/nishina555/items/63ebd4a508a09c481150)
・[rbenvによるRubyのインストールからHello, World!まで]
(https://qiita.com/krtsato/items/3d77501434f623092893)
・[【Homebrew】Command Line Toolsのインストールについて]
(https://sutepulu.com/homebrew-about-command-line-tools-installation/)
・[Homebrew の処理ですごく時間がかかる場合]
(https://qiita.com/tearoom6/items/470e16540e3deaae5efa)
Scrapyで2種類のアイテムを別々のファイルに出力する

## 前提の環境
- Python 3.7.0
- Scrapy 1.6.0

## 動機
- Scrapyでスクレイピングして，同じページから種類の違う情報を集めて別のCSVに保存したい．

## 要点
- Exporterを複数用意してそれぞれにアイテムを保存する．

## 例
```python:my_process.py
import scrapy
from scrapy.exporters import CsvItemExporter
from my_project.items import MyItemA
from my_project.items import MyItemB

class MyProcessSpider(scrapy.Spider):
    name = 'my_process'
    allowed_domains = ['qiita.com']
    start_urls = ['http://qiita.com']

    def __init__(self, *args, **kwargs):
        super(MyProcessSpider, self).__init__(*args, **kwargs)
        self.file_a = open('file_a.csv', 'w+b')
        self.file_b = open('file_b.csv', 'w+b')
        self.exporter_a = CsvItemExporter(self.file_a)
        self.exporter_b = CsvItemExporter(self.file_b)
        self.exporter_a.start_exporting()
        self.exporter_b.start_exporting()
        ## 他に初期化の処理が必要ならここに書く

    def parse(self, response):
        ## 情報収集するURLのリストがurlsに出来ているとする
        for url in urls:
            yield scrapy.Request(url, callback = self.parse_item)

    def parese_item(self, response)
        item_a = MyItemA()
        item_b = MyItemB()
        ##
        ## item_aとitem_bにデータを格納
        ##
        self.exporter_a.export_item(item_a)
        self.exporter_b.export_item(item_b)
        return

    def closed(self, reason):
        self.exporter_a.finish_exporting()
        self.exporter_b.finish_exporting()
        self.file_a.close()
        self.file_b.close()
```

- CSV以外の形式にしたい場合は適切なExporterを使う．

## 追記
- `start_exporting()`の前に`fields_to_export`を設定することで，どのフィールドを出力するかや，出力時のフィールドの並び順を指定することができる．

```python
        self.exporter_a = CsvItemExporter(self.file_a)
        self.exporter_b = CsvItemExporter(self.file_b)
        self.exporter_a.fields_to_export = ['field1', 'field2', 'field3']
        self.exporter_b.fields_to_export = ['field_x', 'field_y']
        self.exporter_a.start_exporting()
        self.exporter_b.start_exporting()
```

## 参考にしたページ
- [Scrapy 1.2 ドキュメント-アイテムエクスポーター](https://scrapy-ja.readthedocs.io/ja/latest/topics/exporters.html#topics-exporters)
量子位相推定とショアのアルゴリズム

#量子位相推定とショアのアルゴリズムを学習しました
こんにちは。テラスカイの須郷です。

普段、MDR様の勉強会等で理研の中田真秀さんにお世話になっています。
今回、中田さんのアドバイスで、量子位相推定とショアのアルゴリズムの内容を学習し口頭発表する機会をいただきました。今回は[その発表で使用したスライドを公開しました](https://speakerdeck.com/seiyasugo/liang-zi-wei-xiang-tui-ding-tosiyoafalsearugorizumu)。口頭発表用に作成したため、読んでわかりやすいかどうかは自信がありませんが、何かしら誰かの役に経てば幸いです。
また、これは以前MDRの加藤さんが[こちら](https://blog.mdrft.com/post/2896)の記事で書かれている経緯と同じですので、こちらも併せてご覧ください。

#少し感想
量子位相推定は汎用性がある重要なアルゴリズムだということは理解していたのですが、ここまでしっかりと勉強する機会はありませんでした。ショアも同様に、数学部分が難しそうだしNISQ時代にわざわざ勉強せんでもええやろ・・・という気分で敬遠して(逃げて)いたというのが本音です。
しかしやってみると、当たり前ですが人に説明することは重要だと改めて気づかされました。理解の度合いが全く違います(その分結構時間がかかりましたが・・・)。
巷には量子アルゴリズムを解説した本や記事は溢れていて、しかもだいたい取り上げられているものは似通っています。改めて自分が(みなさんが)スライドや記事を作るまでもないという気がするかもしれませんが、やってみて損はないかと思います(勉強し始めてみるとわかりやすい解説記事というのは思ったより巷に溢れていないと気づくかもしれません)。