OmniAICreator/Qiita-1.07M huggingface dataset:
torch.Tensor 後、日付情報の復元結果が微妙にずれる

# サマリ

- 日付情報の整数値をDL（`torch.Tensor`）に通したあと、復元すると微妙にずれる現象の概説
- 微妙にズレた日付を復元するサンプルを提供

## 環境

- jupyter notebook
    - たぶん、Colab でも動くと思う
- pytorch: 1.7.0

# 現象

## 準備

```python
import numpy
import pandas
import torch
```

```
index_date = pandas.date_range("2016-01-01", "2018-12-31")
index_date

DatetimeIndex(['2016-01-01', '2016-01-02', '2016-01-03', '2016-01-04',
               '2016-01-05', '2016-01-06', '2016-01-07', '2016-01-08',
               '2016-01-09', '2016-01-10',
               ...
               '2018-12-22', '2018-12-23', '2018-12-24', '2018-12-25',
               '2018-12-26', '2018-12-27', '2018-12-28', '2018-12-29',
               '2018-12-30', '2018-12-31'],
              dtype='datetime64[ns]', length=1096, freq='D')

```

```
df = pandas.DataFrame([])
df["time_index"] = index_date.astype(numpy.int64)
df.time_index[:5]

0    1451606400000000000
1    1451692800000000000
2    1451779200000000000
3    1451865600000000000
4    1451952000000000000
Name: time_index, dtype: int64
```

## 現象の確認

series/numpy のデータを `to_datetime` すると正しく復元できる

```
pandas.to_datetime(df.time_index)[:5]

0   2016-01-01
1   2016-01-02
2   2016-01-03
3   2016-01-04
4   2016-01-05
Name: time_index, dtype: datetime64[ns]
```

一方で、`torch.Tensor` で、テンソルに変換してから復元しようと、`to_datetime` をすると微妙にずれる（型変換時の精度誤差っぽい）

```
pandas.to_datetime(torch.Tensor(df.time_index))[:5]

DatetimeIndex(['2016-01-01 00:00:49.632313344',
               '2016-01-01 23:59:21.295093760',
               '2016-01-03 00:00:10.396827648',
               '2016-01-04 00:00:59.498561536',
               '2016-01-04 23:59:31.161341952'],
              dtype='datetime64[ns]', freq=None)
```


# 対策例

対策として、以下のような関数を作成する

```
import datetime


def to_date(ti: numpy.array):
    _ti = pandas.to_datetime(ti)
    ti_ser = pandas.Series(_ti, name="time_index")

    def _adjust_date(ts):
        dte = ts.to_pydatetime()
        dte += datetime.timedelta(hours=1)
        return datetime.datetime(year=dte.year, month=dte.month, day=dte.day, hour=0, minute=0, second=0)

    return ti_ser.apply(_adjust_date)
```

series に対しては、`to_datetime` と同じ結果になる

```
ti = to_date(df.time_index)
ti.head()

0   2016-01-01
1   2016-01-02
2   2016-01-03
3   2016-01-04
4   2016-01-05
Name: time_index, dtype: datetime64[ns]
```

```
(ti == pandas.to_datetime(df.time_index)).all()

True
```

`torch.Tensor` を通した後も、同じ結果になる

```
ti_restored = to_date(torch.Tensor(df.time_index))
ti_restored.head()

0   2016-01-01
1   2016-01-02
2   2016-01-03
3   2016-01-04
4   2016-01-05
Name: time_index, dtype: datetime64[ns]
```

```
(ti == ti_restored).all()

True
```

## まとめ

- 微妙にめんどくさいので、参考になれば幸いです
RealSenseD435の視野角と図形的なイメージ

RealSenseD435の視野角を調べたものの, 視野角 (水平 x 垂直 x 斜め)の図形的なイメージがわからなかったため, 調べた結果をメモ

# RealSenseD435の視野角

|  センサ  |  視野角（水平 x 垂直 x 斜め)  |
| ---- | ---- |
|  深度センサ  |  85.2°x 58°x 94°（±3°)  |
|  RGBセンサ  |  69.4° x 42.5° x 77°（±3°） |

# 視野角のイメージ
この表現方法はFoV (Field of View)という方式である.
図で表すと以下のようなイメージ. (画像引用元: [3])

<img width="400" src="https://upload.wikimedia.org/wikipedia/commons/thumb/7/72/Angle_of_view.svg/1920px-Angle_of_view.svg.png">


Horizontal FOVとVertical FOVに限れば以下のイメージがわかりやすい. (画像引用元: [4])

<img width="400" src="https://www.researchgate.net/publication/322192140/figure/fig3/AS:578066114383872@1514833109843/Meaning-of-horizontal-FOV-and-vertical-FOV-in-projection-matrix.png">


## 参考文献
1. [スイッチサイエンスのカタログ](https://www.switch-science.com/catalog/3633/)
1. [Realsenseのデータシート](https://www.intel.com/content/dam/support/us/en/documents/emerging-technologies/intel-realsense-technology/Intel-RealSense-D400-Series-Datasheet.pdf)
1. [Field_of_view (Wikipedia)](https://en.wikipedia.org/wiki/Field_of_view)
1. [Meaning of horizontal FOV and vertical FOV in projection matrix. ](https://www.researchgate.net/figure/Meaning-of-horizontal-FOV-and-vertical-FOV-in-projection-matrix_fig3_322192140)
herokuからファイルをダウンロードするには？

これだけです。
めちゃくちゃ簡単でした...

```
heroku ps:copy <filename> -a <アプリ名>
```

参考
-
[dynoからファイルをコピーする](https://devcenter.heroku.com/articles/exec#copying-files-from-a-dyno)
[Heroku bashからファイルをダウンロードするにはどうすればよいですか？
](https://stackoverflow.com/questions/21465789/how-can-i-download-a-file-from-heroku-bash)
サーバーサイドをやるなら知っておくべきこと。

##まず初めに
自分は主にクライアントでの作業を行うことが多いのですが機会もあり詳しい方からお話を伺えたので
もし自分がやる立場になったら覚えておかないといけないと思ったので記事を書きました。
もし間違っている箇所は補足がありましたら教えていただけると助かります。

##実際に考えてみる
データベースは一旦は１つだけと考えAとBのプレイヤーが同時にリクエストを送った場合を考える。
これをするとどうなるのか。
<img width="300" alt="db.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/712841/eebee82a-c7e1-5a15-a6e5-09a63ad1e44c.png">
おそらくユーザー数が少ないとほとんどの場合は問題が発生しません。
ですがユーザー数が多くなってくると問題が発生する可能性が出てきます。
それはなぜかというと厳密な確率的のは話は今回しないのですが限りなくユーザー数が多い場合衝突する可能性がでてきます。
この場合だと時間とIdで計算しているため最終的にCreateItemされるデータも同じになってしまいます。
ではなぜ同じになってしまうのか。
インクリメントしてるしお互い数値違うし大丈夫じゃないの？と考えているかもしれませんが考え方的には合っていているのですが同じタイミングで行った場合どうなるでしょうか。
<img width="300" alt="同時処理の危険性.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/712841/547c8a50-d7e6-b691-abda-095332bd8e97.png">
同時に行うとAのプレイヤーの４という数値とBのプレイヤーの5という数値が１つの箱に衝突します。
そうすると....データが破損、消える、上書きされるなんてことが！？
ではどうするのか。
それを一番上の画像をもとに応用すると....。
<img width="300" alt="db2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/712841/603d5b5c-af30-36db-c69d-20a7a552b8f6.png">
同時でもAが行っている場合はB側に処理を一旦止め、Aの処理が終わってからBの処理を再開することにより衝突を避けることが可能になります。
このような考え方を**トランザクション**と言い、トランザクションはDB（データベース）によってもともと備わっている機能だったりもします。
※必ずしもある機能ではないのでそこは確認しながら進めましょう。

もし途中でエラーになってしまったら？
トランザクションの機能ん一つで途中でエラーになってしまった場合巻き戻すことが可能なのです！
そして
<img width="300" alt="Rollback.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/712841/dcc8f0ae-50ff-9057-5e35-07ba37d561e4.png">
巻き戻したらその状態でもう一度やり直せばいいのです！

**注意点!**
<img width="300" alt="デットロック.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/712841/ad4f3e4a-fe18-05ff-613b-c41dac7d8d46.png">

Aの作業中Bをロック。Aの作業が一過程を終えBを実行Aをロックすると無限に再開、停止を繰り替えし**デットロック**状態になります。
そうなると何がまずいか。
〇ロック待ち
〇待機時間が長いためタイムアウト
回避するためにはPlayerIdやItemIdなどでソートを行い若い順から実行していくなどのことでデットロックを防ぐことができます。


ただここで問題点もあり一番最初に話しているのですがDB（データベース）が１つの場合、なんらかの理由で死んでしまったら....もしくはアクセスが多くて重くなるなんてことがあります。
たとえ１つのDBが壊れても２つ目又は開けて空いたDBに入れるなどすることが可能になり、万が一問題が起きた場合のリスクの分散を行えます。
<img width="300" alt="リスクの分散.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/712841/27eb1647-5cc0-eab3-08c3-7ac2689a8fa6.png">
※これをやることにより整合性をとることが難しくなるなるので注意

今回はここまでです。
みなさんも注意しましょう。
オープンソースライセンスと戦う

# オープンソースライセンス
Webシステムを開発する上でオープンソースなライブラリだったり、ビルドツールだったり、テストツールだったりは必ず使うことになると思います。  
ライセンスで使う条件など記載されていますが、読んでも読んでも結局どうすればいいかわからなかったので、備忘として残しておきます。
# わからなかったこと
## MITライセンス
>
以下に定める条件に従い、本ソフトウェアおよび関連文書のファイル（以下「ソフトウェア」）の複製を取得するすべての人に対し、ソフトウェアを無制限に扱うことを無償で許可します。これには、ソフトウェアの複製を使用、複写、変更、結合、掲載、頒布、サブライセンス、および/または販売する権利、およびソフトウェアを提供する相手に同じことを許可する権利も無制限に含まれます。
>
上記の著作権表示および本許諾表示を、ソフトウェアのすべての複製または重要な部分に記載するものとします。

- 頒布：使用して作られたソフトウェアを渡すのは「頒布」にあたるのか？  
  頒布（原文: distribute）が普段使い慣れない言葉なので、しっくりきていないのもありますが、例えば、typescriptで型定義をしっかりしないとビルドが通らないようにしていた場合、ビルドする過程で「使用（use）」はしたけど、ビルドしたものを人に渡す場合、「頒布」になる？
- 重要な部分に記載？結局どこ？  
  誰が見るために記載するのか？使う人？受け取った人？作者？目的が見えない上に具体的にどこに書けばいいかも明記されていないので、どこに書くべきかが想像ができない。なので、裏を返せば、どこでもいいとも解釈できます。（重要と言い張ればそこが重要な部分になる）

## 修正BSDライセンス
>
ソースコード形式かバイナリ形式か、変更するかしないかを問わず、以下の条件を満たす場合に限り、再頒布および使用が許可されます。
>
1. ソースコードを再頒布する場合、上記の著作権表示、本条件一覧、および下記免責条項を含めること。
2. バイナリ形式で再頒布する場合、頒布物に付属のドキュメント等の資料に、上記の著作権表示、本条件一覧、および下記免責条項を含めること。

- 再頒布とは？  
  - ここでいう再頒布（原文: redistribution）はどういうケースを指すのか？
  - 使用だけなら著作権表示いらない？
  - でも、使用してソフトウェア作って、人に渡したら、それは「再頒布」？

## Apache ライセンス 2.0  
これが一番わけわからない
>
「成果物」とは、ソース形式であるとオブジェクト形式であるとを問わず、製作物に挿入または添付される（後出の付録に例がある）著作権表示で示された著作物で、本ライセンスに基づいて利用が許されるものを指します。
>
「派生成果物」とは、編集上の改訂、注解、推敲など、成果物を基にしていて全体としてオリジナル著作物と呼べるような製作物全般を指します。本ライセンスでは、成果物や派生成果物から分離できる製作物や、成果物や派生成果物のインタフェースへの単なるリンク（または名前によるバインド）を、派生成果物に含めません。 

という前置きがあって、（この時点で不安しかない）

>
4\. 再頒布
>
あなたは、ソース形式であれオブジェクト形式であれ、変更の有無に関わらず、以下の条件をすべて満たす限りにおいて、成果物またはその派生成果物のコピーを複製したり頒布したりすることができます。
>
1. 成果物または派生成果物の他の受領者に本ライセンスのコピーも渡すこと。
2. 変更を加えたファイルについては、あなたが変更したということがよくわかるような告知を入れること。
3. ソース形式の派生成果物を頒布する場合は、ソース形式の成果物に含まれている著作権、特許、商標、および帰属についての告知を、派生成果物のどこにも関係しないものは除いて、すべて派生成果物に入れること。

- 派生成果物：ライセンスついたライブラリを使って作ったソフトウェアは「派生成果物」？  
誤訳なんじゃないか（英語わからないけど）  

    >
    "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. 

「派生成果物」とは、thatを指します。thatは成果物を元にしている（または、成果物から派生している） 
 and for which 編集上の改訂、注解、推敲や他の変更が表す、全体として、著者のオリジナルな成果物...
高校の時の英語の授業で特攻の拓を読んでた私にはハードラックとダンスっちゃってますが、ライブラリとして使うだけなら「派生成果物」にならない雰囲気も感じます。

# distribute
この解釈の仕方が肝な感じがします。 
単語自体の意味は、
1. ～を分配する、～を分け与える
2. 〔特定の地域や領域に〕～をばらまく、～を広げる、～を分布させる
3. 〔異なる種類に〕～を区分する、～を割り振る
4. 〔卸売業者が小売業者に商品を〕卸す、流通させる
5. 《論理学》〔名辞を〕周延する
6. 《数学》～を分配する
だそうです。
「ばらまく」とか「広げる」とか「流通させる」とかが意味合い的には合いそうです。 
とすると、ライセンスつきのライブラリを使って作ったものを頒布するのは、
ライセンスつきのライブラリを頒布するということにはならない
という解釈もできるかなと思いました。



# 結局

- ライセンスつきのライブラリやツールを使って作ったものを人に渡すことを「頒布」とするなら
- Webシステムを不特定多数の人が見れる状態にすることを「頒布」とするなら

ライセンス表示するための画面が必要なのではないか  
（ライブラリを使用して作られたソフトウェアを受け取った人が、ライブラリの著作権と使用許諾条件をどこかで読めればいい 
と解釈しました）  
まあ、記載しろとは書いてあるけど、記載するなとは書いてないので、 
書いてあるところがわかるように書いておけば問題おきないよね
というお話でした。

# 参考
https://licenses.opensource.jp/
https://opensource.org/licenses/MIT
https://opensource.org/licenses/BSD-3-Clause
https://opensource.org/licenses/Apache-2.0
[PHP]フォームのデータを受け取る

#PHPでフォームのデータを受け取る
```java:PHP
 <?php echo $_POST['name属性に指定した値']; ?>
 <div class="form-item">■ 内容</div>
```
#$_POST['name']
フォームで送信した値を受け取るには「$_POST」を使用する。
「$_POST」は連想配列になっていて[ ]の中に、<input>と<textarea>のname属性に指定した値を入れることで、それぞれの送信した値を受け取ることが出来る
#以上！
Xcodeのコンソールから変数を確認＆設定

<h1>Xcodeのコンソールから変数を確認＆設定</h1>

すぐ忘れてしまうので自分用のメモとしてまとめておく

<b>0.準備</b>
メニューバーから View -> Debug Area -> Activate Console をクリック
![スクリーンショット 2020-11-28 0.29.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212257/e0637d25-2aa3-584f-c341-859b52177930.png)

<b>1.変数を確認する</b>
<code>po 確認したい変数</code>
![スクリーンショット 2020-11-28 0.25.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212257/19021c03-eafd-e21e-10f0-a171814cb78e.png)

<b>2.変数を設定する</b>
<code>expression 代入したい変数 = 代入したい内容</code>
![スクリーンショット 2020-11-28 0.26.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212257/0fd262ac-c5d2-83da-b850-7d442a87e52b.png)


※注意事項
・コンソールは All Output または Debugger Output のモードにしておく。
・ブレークポイントで一時停止中でないと確認＆設定できない。

参考：https://dev.classmethod.jp/articles/ios-debug/
このページに安全に接続できません（IE SSL）

IEを使用していて”このページに安全に接続できません”と表示されてしまう

#SSLからTSLに設定を変更する
コントロール パネル\ネットワークとインターネット\詳細設定\セキュリティ
SSLを使用するのチェック外し、TSLの使用にチェックを入れる。

オフラインのネットワークで古いバージョンのIEしか使えず、困っていました。
初歩的な設定の問題でつまずいてしまったようで、自分用にメモを残しておく。
現在利用しているシェルの種類を確認する(GNU BashなのかZ Shellなのか)

## 実現したいこと

ターミナルで現在利用しているがbash(GNU Bash)なのかzsh(Z-shell)を表示する
※macOS Catalinaから標準シェルがzshになっている。

## 実行コマンド

### CentOS Linux release 7.9.2009 の場合

```
$ uname
Linux 
$ ps -p $$ | tail -1 | awk '{print $NF}'
bash
$
```

### macOS Catalina の場合

```
% uname
Darwin
% ps -p $$ | tail -1 | awk '{print $NF}'
-zsh
% 
```


## 補足

```
echo $SHELL
```

* 上記の方法は、あまり良い方法ではない。

```
$ echo $SHELL
/bin/bash
$ SHELL="hoge"
$ echo $SHELL
hoge
```

```
% echo $SHELL
/bin/zsh
% SHELL="hoge"
% echo $SHELL
hoge
% 
```


## 情報源

* 使っているシェルを調べる方法 | マイナビニュース
  * https://news.mynavi.jp/article/20181121-727279/
高可用性と耐障害性の違いと稼働率について

システムを構築する上で、規模が大きくなればなるほど考える必要が出てくるのが可用性や耐障害性です。
クラウドを用いるのが当たり前になった昨今は、ある程度この辺を意識しなくてもシステムを構築できるようになりましたが、
1つのリージョンがダウンした場合でもサービス全体が止まらないような構成を考えなければならないこともあります。
（AWSの障害で〇〇が使えなくなった！などは記憶に新しいです・・・）

高可用性と耐障害性、どっちがどっちかよくわからなくなってしまうのでまとめました。

# 高可用性と耐障害性という言葉の意味
<dl>
  <dt>高可用性</dt>
</dl>
> 高可用性（こうかようせい、英: High Availability; ハイ・アベイラビリティ、HA）は可用性が高いことを示すIT用語。
> システムなどにおいて、サービス提供が出来なくなる事態の発生頻度が少ないことを指す。
> また、そのようなシステムをHA構成などと呼称する。
> システム的には冗長化構成を組んでいたり、バックアップ手段の確立、災害対策システムを講じることでHAを実現させる。
> IT業界においてはほぼクラスタリングあるいはクラスタサーバと同義で使用される用語。
> Wikipediaより[^1]

つまり、高可用性とはサービスが停止する時間がどれくらい短いか。
もっというと「利用者がどれだけサービスを利用できるか」を指します。
引用元にも記載の通り、クラスタリングなどを用いて実現します。

<dl>
  <dt>耐障害性</dt>
</dl>
こちらはいい引用元が見つかりませんでしたが、英語にするとFault Tolerant(フォールトトレラント)
どれだけ障害に耐えれるか、ということを指します。
またフォールトトレラントシステムといった場合、それはどんな障害にも耐えられる、つまり無停止のシステムであるということです。
ハードウェアの耐障害性を高める方法としては冗長化があります。
RAIDを組む、LANを冗長化する（リンクアグリゲーション）などです。
例えばディスクが1つ故障した場合でも、自動でスペアディスクをRAIDに組み込んだりできる機器などがあります。

# 稼働率について
可用性をはかる尺度として、稼働率という指標があります。
稼働率とはサービスが提供できている時間の割合のことです。
例えば、Googleが提供するmBaaSであるFirebaseは月間稼働率が99.5%未満で99.0%以上の場合は10%の返金、
99.0%未満だった場合は30%の金額を返金すると定めています。[^2]
月間稼働率99.0%というのは月間で7.2時間までサービスがダウンする可能性があるということです。
月間稼働率99.5%だとダウンタイムは3.6時間です。

# 実現方法を考えてみる

クラウドを用いる場合はもちろん、オンプレミスの場合でも一般的にハードウェアは単一障害点が無いように設計し、
ハードウェア耐障害性は担保されていることが多いです。（無停止で部品を交換することが出来る仕組みを使う）
なので、ソフトウェアの可用性を高める以下のようなクラスタリングシステムについて例を用いて解説します。
![プレゼンテーション1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/712683b5-ebb0-d69f-db6b-00b7d05e2269.png)
Active-Standby構成のクラスタリング。共有ストレージを切り替えて、サービスを上げ下げすることで切替を行
います。
このようなシステムの場合、障害が発生してからスタンバイ側でサービス再開するまでに以下のようなことが起こります。

#### 1. 監視
サービスが起動しているかどうかを定期的にクラスタリングソフトが監視します。
監視間隔は設定できることが多いですが、短すぎると誤検知してしまう確率が上がり、長すぎると気づくのが遅くなるので稼働率が下がってしまいます。

#### 2. サービスの停止
監視で異常に気付いた後は、サービスを停止します。
サービスが異常になっている場合、正常に停止できないこともあるので、まずは普通に止めてみて、ダメだったら強制終了する　というような動きになることが多いです。
この場合も、強制終了に移行するまでの時間を決めれることが多いですが、短すぎると正常稼働時でも強制終了してしまい、DBに不整合が起きてしまったり、逆に長すぎるとその分、稼働率が下がることになります。

#### 3. リソースの切り離し
共有ストレージやVIPの切り離しを行います。LinuxでLVMだとアンマウント⇒LVダウン⇒VGダウン　といった感じです。
それなりに時間がかかります。上２つと同様にタイムアウトが設定できるようになっていることが多いです。

#### 4. スタンバイ側でのリソースの取り付け
Active側の切り離しが完了したら、Standby側でリソースの取り付けを行います。

#### 5. サービス起動
正常にリソースが取り付けられたら、決められた順番に沿ってサービスを起動していきます。
これでDBサーバとしてはサービス再開できるわけです。

![プレゼンテーション２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/eef561bd-25b1-d890-5bc7-07734c720f6f.png)
# 稼働率はどのくらいになるか
この例の場合、気にすべきタイマ値は以下です。

- 監視間隔(ソフトウェアで制御可能)
- サービス停止時間(タイムアウトはソフトウェアで制御可能）
- リソース切り離し時間（マシンスペックや構成に大きく依存）
- リソース取り付け時間（マシンスペックや構成に大きく依存）
- サービス起動時間（マシンスペックや構成に大きく依存）

仮に監視間隔120(s)、サービス停止の最大値が240(s)、リソース切り離し+リソース取り付けが120(s)、サービス起動に120(s)かかるとすると
切替に10分かかるということになります。

仮に月に1回障害が発生し切替が行われるとすると（発生しすぎですが、一旦）


```math
稼働率 =1 - \frac{10分}{(30日 \times 24時 \times 60分)} = 99.976...\%

```
となり99.9%以上の稼働率となります。

[^1]: 高可用性 - Wikipedia (https://ja.wikipedia.org/wiki/%E9%AB%98%E5%8F%AF%E7%94%A8%E6%80%A7)
[^2]: Service Level Agreement for Hosting and Realtime Database - Firebase (https://firebase.google.com/terms/service-level-agreement)
WindowsOSをUSBにインストールしようとしたら原因不明のエラー(0x80070002)で失敗


どうも、たかふみです。
現在、UWPアプリの開発案件に携わっており、アプリのプリインをするためにWindowsOSの再インストールをしようとしたところ、原因不明のエラーで詰まってしまいました。今回はそのエラー解決までの記事です。

## 現象
Windows OSのインストールを行うために「Windows 10 セットアップ」を使用して、インストールメディアをUSBにインストール使用としたところ、下記エラーが発生しました。
<img width="521" alt="原因不明のエラー.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250884/8c3bcef1-40d0-3aa2-4a7c-024e229a9bd9.png">

## 結論
インストールメディアのダウンロード中にUSBの接続が切れていた。

## 原因の判明まで
WindowsOSのインストールを[公式サイト](https://www.microsoft.com/ja-jp/software-download/windows10ISO)を参考に行った所、ダウンロード中にエラーが発生しました。エラーメッセージなのに「原因不明」と書いてあるのがウケますね。

**■エラーメッセージ**
>このツールの実行中に問題が発生しました
>理由は不明ですが、お使いのPCでこのツールを実行することができません。引き続き問題が発生する場合は、カスタマ>ーサポートに連絡する際にエラーコードをお伝えください。エラーコード：0x80070002 - 0xA001B

「繰返し発生する場合は」とあるので、もう一度実行してみましたが、同じエラーが発生しました。

エラーコードについて調べてみたら、"WindowsUpdate中に発生した"という記事が多く見られたため、WindowsUpdateに関係があるのかもと思い、WindowsUpdate実行後に再度試してみたが解決せず。

そこで、一旦インストール中の様子をしばらく観察してみたところ、ダウンロード中にUSBの接続が切れていることに気づきました。インストール中に切れないように定期的にUSBのファイルをクリックしながら見ていると、無事にダウンロード完了。それを使って別PCにWindowsOSのインストールも完了しました。

<img width="521" alt="USB_インストールメディア.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250884/19808956-ae05-7997-8614-a0d9b185b61c.png">

## 対策：USBの電源が切れないように設定
USBの接続が切れた原因として、USBの不良をまず考えました。「USB 接続不良」などで調べていると、下記の記事を発見。

>Q．USBの電源が切れてしまう／電源管理の無効操作／USBのセレクティブサスペンド設定
>URL：http://qa.elecom.co.jp/faq_detail.html?id=5731

USBに電源ってあるんですね。
サイトに従い、PCに電源がつながっているときはUSBの電源が切れないように設定しておきました。

<img width="521" alt="USBの電源が切れないように設定する.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250884/a345320a-5a04-c04b-4ed6-fe93d7700b91.png">

### まとめ：WindowsUpdateは関係なかった
出てきたエラーコードで調べてもWindowsUpdateの際に発生する旨の記事が多かったので時間がかかってしまいましたが、無事に解決することができました。WindowsOSのインストールをする際にも「ファイルが見つかりません」というエラーが何度か発生したことがあったので、もしかしたらUSBの電源が切れてしまったことにより起きているのかもしれません。

また、USBについてはPCに認識がされていなくてもインストールが続くので一見順調に見えても実は失敗する、みたいなこともありました。同じような現象が起きた時にはご注意ください。

それでは！

### ■参考サイト
Windows 10 のディスク イメージ (ISO ファイル) のダウンロード
https://www.microsoft.com/ja-jp/software-download/windows10ISO

Q．USBの電源が切れてしまう／電源管理の無効操作／USBのセレクティブサスペンド設定
URL：http://qa.elecom.co.jp/faq_detail.html?id=5731
AWSのIAMユーザーでCostExplorerやBillingにアクセスできないとき

## 困っていたこと
IAMユーザで請求情報にアクセスできない
↓
毎回ルートユーザになって確認

## 問題点
- めんどくさい

アカウント切り替えが本当に手間だった

- セキュリティ的にまずい

ルートユーザ使うのはNG

## 解決策

Googleで検索したところ、3秒で解決。

#### やり方

①ルートユーザでログインし、AWSコンソールから「マイアカウント」に移動

②[IAM ユーザー/ロールによる請求情報へのアクセス] の横の[編集] をクリック

③[IAMアクセス有効化]チェックボックスをオンにし、[保存]をクリック

④IAMユーザで請求情報にアクセス可能に 

下記リンク参照
[AWS公式ドキュメント アクセス許可の管理の概要](https://docs.aws.amazon.com/ja_jp/awsaccountbilling/latest/aboutv2/control-access-billing.html)

## まとめ

なんで今までやらなかったんだろう。。。。
ActiveHashを使ってカテゴリーの選択を実装

ActiveHashとは「基本的に変更されないデータの取り扱い」があったとします。このデータはデータベースに保存する必要がありません。一方、ビューファイルなどにそれらのデータを直接書いてしまうと、可読性に欠けます。そのようなケースでは、ActiveHashが有用です。

ActiveHashをインストール

```ruby:Gemfile
 gem 'active_hash'
```

```ruby:ターミナル
bundle install
```

モデル生成(今回はカテゴリー選択を"genre"とします)

```ruby:ターミナル
rails g model genre --skip-migration
```

この時のモデル作成には「--skip-migration」を使用しております。
これはモデルファイルを作成するときに、マイグレーションファイルの生成を行わないためのオプションです。
選択したジャンルの情報はデータベースに保存しないため、マイグレーションファイルを作成する必要がないためです。

##ActiveHash::Base
ActiveHash::Baseは、あるモデル内（クラス内）でActiveHashを用いる際に必要となるクラスです。

```ruby:app/models/genre.rb

class Genre < ActiveHash::Base
 self.data = [
   { id: 1, name: '--' },
   { id: 2, name: '経済' },
   { id: 3, name: '政治' },
   { id: 4, name: '地域' },
   { id: 5, name: '国際' },
   { id: 6, name: 'IT' },
   { id: 7, name: 'エンタメ' },
   { id: 8, name: 'スポーツ' },
   { id: 9, name: 'グルメ' },
   { id: 10, name: 'その他' }
 ]
   include ActiveHash::Associations
   has_many :articles

 end
```

マイグレーションファイル内

```ruby
class CreateArticles < ActiveRecord::Migration[6.0]
 def change
   create_table :articles do |t|
     t.string     :title        , null: false
     t.text       :text         , null: false
     t.integer    :genre_id     , null: false
     t.timestamps
   end
 end
end
```

```ruby:ターミナル
% rails db:migrate
```

親モデルのアソシエーションを設定
belongs_toの記述を行います。

```ruby:app/models/article.rb
class Article < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :genre
  validates :title, :text. presence: true
  validates :genre_id, numericality: { other_than: 1 } 
end
```


```ruby:app/views/articles/new.html.erb
<%= form_with model: @article, url:articles_path, local: true do |f| %>
  <div class="article-box">
    記事を投稿する
    <%= f.text_field :title, class:"title", placeholder:"タイトル" %>
    <%= f.text_area :text, class:"text", placeholder:"テキスト" %>
    <%= f.collection_select(:genre_id, Genre.all, :id, :name, {}, {class:"genre-select"}) %>
    <%= f.submit "投稿する" ,class:"btn" %>
  </div>
<% end %>
```

以上備忘録でした。
【JavaScript】Promiseについて簡単に説明した

#Promiseとは
**要は`非同期処理`の完了を待つ為の仕組みのことです。**
#非同期処理とは
例えば、仕事中に上司から「これ1000枚コピーしといて」と言われたら、
コピー機を使いコピー機が勝手に1000枚作っている間は他の仕事を行い、
コピーが終わったところで1000枚の用紙を上司に渡すと思います。

**これが非同期処理です**

もし会社のコピー機が安物で一枚一枚手動でコピーするタイプのものだったら、1000枚できるまで他の仕事はできません。

**これが同期処理です**

***

非同期処理の方が便利で良いじゃんと思いきや、
これをコードで表すと不都合が起こります。

非同期処理である`setInterval()`を使って見てみます。

```javascript:main.js
const copy = () => {
  const id = setInterval(() => {
    console.log(`${paper} 枚目`);
    if (paper >= 10) {
      clearInterval(id);
    }
    paper++;
  }, 100);
};

console.log('上司:これ10枚コピーしといて');
copy();
console.log(`コピー${paper}枚できました！`);

```

このコードでは元の用紙`paper`を用意し、
上司からの指示があった後、`copy`関数（コピー機）を実行。
`setInterval()`で`paper`が10になるまで繰り返し、
10になったら上司に提出する。

という処理を行いたいものとします。

しかし結果を見てみると・・・
![demo](https://gyazo.com/dddf215d20f2af341a6ad8c7d55c2c9c/raw)

これはマズイです。
コピー機の完了を待たずに提出してしまっています。
これでは査定に響きます。

ではコピー機の完了を待つにはどうすれば良いでしょうか？

そう、ここで**Promise**の出番です
***
ではさっきのコードに`Promise`を追加します。

```javascript:main.js
let paper = 1;

const copy = () => {
  return new Promise((resolve) => {//・・・・・・・・・・・・①
    const id = setInterval(() => {
      console.log(`${paper} 枚目`);
      if (paper >= 10) {
        clearInterval(id);
        resolve(paper);//・・・・・・・・・・・・・・・・・・・・・・・・・・②
      }
      paper++;
    }, 100);
  });
};

console.log('上司:これ10枚コピーしといて');
copy().then((paper) => {//・・・・・・・・・・・・・・・・・・・・・・・・・③
  console.log(`コピー${paper}枚できました！`);
});

```

変更点が３つあります。
***
**①**

```javascript:main.js
const copy = () => {
  return new Promise((resolve) => {//・・・・・・・・・・・・①
    //非同期処理
  });
};

```
非同期処理を`new Promise`のコールバック関数で包んでいます。

これを**ラップする**と言ったりします。

`return new Promise`とすることで`copy`関数に`Promise`を返しています。

引数に`resolve`を渡しています。

他に`reject`という引数も渡せます。
***
**②**

```javascript:main.js
      if (paper >= 10) {
        clearInterval(id);
        resolve(paper);//・・・・・・・・・・・・・・・・・・・・・・・・・・②
      }

```

ここで引数の`resolve`が呼ばれています。
`Promise`のコールバック関数では`resolve`もしくは`reject`が呼ばれるまで**次の処理に移りません**
ここでは`paper`が10になった時点で`resolve`が呼ばれています。
つまり**`paper`が10になるのを待っている**ということです。
***

**③**

```javascript:main.js
copy().then((paper) => {//・・・・・・・・・・・・・・・・・・・・・・・・・③
  console.log(`コピー${paper}枚できました！`);
});

```

`copy`関数の後ろに`.then`と続いています。
**thenメソッド**は`Promise`のメソッドですが、
①で`new Promise` を返しているので使用できます。
`then`の引数の`paper`は②で`resolv`に渡したものです。
この中に10枚の用紙が入っています。

#結果
![demo](https://gyazo.com/2b8d143e2ad244b03756c87f9607a409/raw)

無事に10枚の用紙を提出できました！

***

以上です。
間違えてたら遠慮なくご指摘ください！
ウィンドウズ環境用のアプリをmacで開発する為に、windows10 virtualboxをダウンロードする

##ウィンドウズ環境用のアプリをmacで開発する為に、windows10 virtualboxをダウンロードする

１，バーチャルボックスをダウンロード
https://www.virtualbox.org/wiki/Downloads

２，OSXを選択


３，マイクロソフトのサイトからウィンドウズ１０用のバーチャルボックスをダウンロード
get windows 10 development environmentで検索しないとなかなかヒットしない

https://developer.microsoft.com/ja-jp/windows/downloads/virtual-machines/

４，バーチャルボックス用をダウンロード

５，１８ギガもある。インストールに３０分ぐらいかかりました



で、いざ起動したら

```
Kernel driver not installed (rc=-1908)
Make sure the kernel module has been loaded successfully.
```
```
The virtual machine 'WinDev2010' has terminated unexpectedly during startup with exit code 1 (0x1).
```

というエラー出た。。。

![スクリーンショット 2020-11-28 0.08.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/898667/4b498a29-52f6-364a-f76b-30821df23d14.png)


このサイトの方法で治った
https://shikasen-engineer.com/virtualbox-kernel-driver-not-installed/

起動完了
![スクリーンショット 2020-11-28 0.45.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/898667/128d38ca-6338-2d3b-34c7-252ac198b362.png)


と思ったら、

```
 App · ⚠️  [FAIL] electron-packager could not build Error: Could not find "wine64" on your system. Wine is required to use the appCopyright, appVersion, buildVersion, icon, and  win32metadata parameters for Windows targets. Make sure that the "wine64" executable is in your PATH."
```

とか言うエラーが出たので、
wine６４をインストールする必要があるっぽい。


/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"


でbrewをインストールし、

```
brew -v                                                                                          
Homebrew 2.5.12
Homebrew/homebrew-core (git revision 1fed3ba; last commit 2020-11-27)
```
入ってるのが確認できたので、

その後、
このサイトを見ると
https://wiki.winehq.org/MacOS/Building

Homebrew
Homebrew no longer provides a wine formula instead opting to use there cask system to install Winehq provided packages.

The following would cover basic requirements;

```
brew cask install xquartz
brew install bison flex mingw-w64 pkgconfig
```

と書いてあるので、実行

やたら大量にダウンロードしてる、、、１０分ぐらい

```
installer: Package name is XQuartz 2.7.11
installer: Installing at base path /
installer: The install was successful.
🍺  xquartz was successfully installed!

```

でもだめ！！


ひとまず、、、
ウィンドウズ環境用は今の所そんなに必要はないので、諦めて、必要になったら再学習しよう。
いまはレベル高い。。







MacでMac用アプリ適応
Macでウィンドウズ用アプリ適応
MacでiPhone用アプリ適応
Macでアンドロイド用アプリ適応
この辺をやると、エラーだらけでまじで疲れる・・・
deviseを使って、ユーザー情報の編集・更新について

#はじめに
　昨日、deviseでユーザーマイページの詳細ページがない、ということを投稿したが、アプリの制作を進めていると、編集ページは見つけたので、記録しておく。

##ユーザー情報の編集ページはdeviseにあった!
ターミナルで

```bash
rails routes
```
をすると、

```bash
edit_user_registration GET      (URI略)      users/registrations#edit
     user_registration PATCH    (URI略)      users/registrations#update
```

`views/devise/registrations/edit.html.erb`
ファイルに、ユーザーの編集ページとして、デフォルトであり、パスワードやメールアドレスの編集ができるようになっている。このファイルに`link_to`で飛ばすと、簡単に編集・更新できる。
デフォルトであるビューで、更新機能も備わっている。
更新が成功すると、ルートパスにリダイレクトもされる。

##最後に
おそらく、コントローラーに記述があるんだろうけど、どの部分か見つけられない今日この頃。
第0回　AWSに自動でテスト/デプロイしてくれるインフラの設定・構築（目標・やりたいこと）

#はじめに
　都内某所に住む大学院生です！
　休学しているということもあり、空いてる時間が多いので、今のうちにインフラ周りであるテスト・デプロイの自動化(CI/CDパイプラインの構築)方法について学ぼうと思ったので勉強し、その結果をまとめました！
　ブログ感覚で書き始めました。ちなみに初投稿なんで優しい目で見ていただけるとありがたいですm(_ _)m
　（あと、本記事はまだ本編スタートしないので読まなくても構わないです。。）

# 前提知識
　この記事を読む上で、知っておいて欲しいこと一覧。（というか、各ツールの詳細部分までは__説明しない__ので、詳細を知りたい方は、他の記事を参考にして欲しい。）（付け足すかも）
__〜ネットワーク編〜__
　・ サブネット
　・ ルートテーブル
　・ CIDR
__〜Docker（docker-compose）編〜__
　・`run` / `exec` 等基本コマンド
__〜CircleCI編〜__
　・YAML（.yml）ファイルの記法

# 本シリーズ集
　この__『AWSに自動でテスト/デプロイしてくれるインフラの設定・構築』__シリーズは、今のところは6回くらいほど続く予定

|  | タイトル |
|:-:|:-:|
| 0 | __`目標・やりたいこと`__ |
| 1 | [AWS編](https://qiita.com/Dadadada-TT/items/86e0a578f934e6578c04)|
| 2 | [rails開発環境構築編](https://qiita.com/Dadadada-TT/items/f4ce8d997cc0bb3e0aca)|
| 3 | [Nginx・MySQL編](https://qiita.com/Dadadada-TT/items/4a7edd61a5d7c75f772d) |
| 4 | [Capistrano編](https://qiita.com/Dadadada-TT/items/79e33659eacda1cd0510) |
| 5 | [CircleCI編](https://qiita.com/Dadadada-TT/items/a9530630782c6f4c7cbc) |
| 6 | [総集編](https://qiita.com/Dadadada-TT/items/3d1fa7854d562ae1db1b) |


# 使用するツール
- __AWS__
- __CircleCI__（version-2.1）
- __Docker__（version-19.03.5, docker-compose: version-1.24.1）
- __Github__
- __Nginx__（version-1.19.5（Dockerのlatestタグ））
- __Rails__ （rubyのgem。　version-6.0.3.4）
- __Capistrano__(gem。　version-3.14.1)
- __puma__　(gem。　version-4.3.6)
- __MySQL__（version-5.7。　Docker）

　__rails__ などのgemも基本はDocker（docker-compose）を使用します。



# 目標・やりたいこと

1. AWSでEC2インスタンス（後述）3つを立てて、その中で__Docker__を使用して、__Nginx（Webサーバ）__・__puma(APサーバ）__・__MySQL（DBサーバ）__それぞれの本番環境を構築する。
2. また、__Github__と__CircleCI__・__Capistrano__を利用して、AWSのEC2に自動でテスト&デプロイしてくれる（所謂、__『CI/CDパイプラインの構築』__）よう設定する。

# Dockerとは?
　終わる前にDockerについて一言。
　
　近年流行っている__仮想化技術__の一つ。
　コンテナを作成し、その中で、ローカルの環境とは別の、__独立した環境__で開発等々を行う技術。

↓参考になったサイト・記事

・[Dockerとは何か、何が良いのか](https://knowledge.sakura.ad.jp/13265/)
・[Docker超入門①〜Dockerってなに？〜【初心者向け】](https://datawokagaku.com/whatisdocker/)

⬇️このツール群で唯一参考にしたudemyの講座。すごく助かりました。
・[米国AI開発者がゼロから教えるDocker講座](https://www.udemy.com/share/103aTRBkQSdV1RR3g=/)

# 最後に、筆者について
　とあるSI系の会社でインターンとして働いており、これまではふんわりと『普通にどこかの企業に就職するかな〜っ』て考えていました。
　ですが、休学を機に、自分は何をやりたいか？と考えた結果、IT系に進もうと決心しました。
　そして、『このままではダメだ！基礎から勉強しよう！』と思い、__基礎情報処理__や__応用情報処理__、__ネットワーク周り__を勉強し始めました（ちょっとネットワーク周りは勉強しすぎた感ありますが）。
　一通り、基礎固めが終了し、言語の習得もそこそこにして（元々インターンで培っているので、他の人よりはプログラミング言語の習得は早いと思います）、次はインフラ周りの勉強するぞ！という段階です。
　まだ本腰入れて勉強し始めて3ヶ月ほどなので、間違ったことを書いていれば、コメントで指摘していただければ有難い限りです。
MatplotLibでループして図を書き、あとからX軸を変更する


#目的
MatplotLibにてループでfigureを描く場合に、あとから軸を修正する方法を記述

#動作環境
Python 3.7 (Anaconda) Spyder

#方法
axesを保存しておいて、あとからaxes.set_xlim(start,end) で変更すれば、軸をあとから修正
できるらしい。
ウインドウが別枠で出ない場合は、コンソール上で　%matplotlib qt　と打つ

#実行コード
```python

import matplotlib.pyplot as plt
import numpy as np

plt.close('all')

#Make Data
Time =np.arange(0,1,0.001);
Data = np.sin(2*np.pi*10*Time);

#３回のループで３つのFigureを描画
fig = {}
ax ={}
for idx in range(1,4):
    fig[idx] = plt.figure()
    ax[idx]  = plt.subplot(311)
    plt.plot(Time, Data)
    
#２番目のfigureの軸を変更
ax[2].set_xlim(0,0.5)
plt.show()

````
python でKMPの前処理テーブルを書く[備忘録]

# イントロ
競プロの問題でKMPを書いたので備忘録

今まで書いたことがなかった割にはアルゴリズムは単純で、一方で少し混乱するところもあったのでそこに関しても記述する

# KMPalgorithmとは
>クヌース–モリス–プラット法（Knuth–Morris–Pratt algorithm、KMP法と略記）とは、文字列検索アルゴリズムの一種。テキスト（文字列）Sから単語Wを探すにあたり、不一致となった位置と単語自身の情報から次に照合を試すべき位置を決定することで検索を効率化するアルゴリズムである。
[wikipediaの説明](https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%8C%E3%83%BC%E3%82%B9%E2%80%93%E3%83%A2%E3%83%AA%E3%82%B9%E2%80%93%E3%83%97%E3%83%A9%E3%83%83%E3%83%88%E6%B3%95)より

文字列から単語（モチーフ）を検索する際にだいたいBrute-forｔｈの次に説明されるアルゴリズムな気がします。
そこからBM法、Z-algorithm, SA-ISとかにつながって線形や対数時間（SA-IS、ただし前処理には線形）と計算量が改善していきます。（この辺はあまり中身理解できていない）

今回はKMPについて説明していきます


# 問題の定式化
検索対象の文字列をref,探したい文字列をmotifとします。
説明のためそれぞれの長さをS,Tとおきます。

問題としてはrefの中でmotifに一致した部分文字列の位置
つまり`ref[i:i+T]=motif`となるi をすべて出力することが目標です。


#naiveな（愚直な）解法　Brute-Forth
まず文字列から単語を計算する際に一番愚直な方法を考えます。
refからmotifの長さと一致するすべての部分文字列を先頭からとって比較すれば良いです。

```brute_forth.py
S = len(ref)
T = len(motif)
motif_count = 0
# brute force
for i in range(S - T):
  if ref[i:i+T] == motif:
    print(i+1,end=" ")#1_idxでのpositionを出力する

```

文字列の比較を丁寧に書くと以下のようになります

```brute_forth_2.py
S = len(ref)
T = len(motif)
motif_count = 0
# brute force
for i in range(S - T):
  for j in range(T):
    if ref[i+j] != motif[j]:
      break
    elif j == T-1:
      print(i+1)  
```

この計算量は部分文字列とmotifの比較にO(T),motifの長さと一致する部分文字列がS-T個あるため、O(ST)になります。

# KMPアルゴリズムイメージ
Brute Forthの処理の中で改善できそうな箇所を考えます。

Brute Forthではrefの文字列の同一のpositionをループのたびに（開始位置i が変わるたびに)何度も比較していることがわかります

一度比較しているならばどの文字がその場所にあるかはわかっているはずなので、開始位置が変わった次のループではその箇所の比較はうまくやればskipできそうです。

例えばref="bakanabanana",motif="banana"というケースを考えると

i=0(先頭から始まる部分文字列の比較）ではbakana とbananaを比較することになりますが3文字目でref[i+j]="k",motif[j]="n"となり一致しないことがわかります。

ここでbrute forthなら開始位置を一つずらしますが、先程の比較でrefの先頭に文字がb,aであることはわかっています。

そして、今回のmotif"banana"は先頭が"b"なので、開始位置を１つずらしても絶対にそこからの部分文字列は一致しないことが比較する前からわかります。

以上のことからmotifとの3文字目の比較でmismatchが起こったならば、次の文字列の比較では先頭位置を先程より２文字ずらせばいいいことがわかります。

このように**前回のmotifとの比較際のmismatch(match) の場所から次にどれだけずらす(開始位置をskipする）ことができるかを予め前計算して高速化したもの**がKMP法となります

計算量としては前処理テーブル作成（今回の記事）でO(T),実際にrefの探索でO(S)となります

#実装イメージ
尺取法のようなイメージでどれだけskipできるかを考えていきます。

前処理テーブルにおいて、長さ2以上のmatchを作るためにはそのpositionの１つ前が1以上のmatchであることを利用します。

#実装
motifの文字列からテーブルをつくる所の実装です。

```make_kmp_table.py
def make_kmp_table(motif):
    """return kmp failure table

  params  : motif
  return : kmp table(1 dimensional-array)
  """
    match_len = [0]
    table = [0] * len(motif)
    for i in range(1, len(motif)):
        next_match_len = []
        for current_match_len in match_len:
            if motif[i] == motif[current_match_len]:
                current_match_len += 1             
　　　　　　　　　 next_match_len.append(current_match_len)
            
        match_len = next_match_len
        match_len.append(0)
        table[i] = match_len[0]
        
    return table
```

# 参考
[
いかたこのたこつぼ（ブログ）]
(https://ikatakos.com/pot/programming_algorithm/string_search)
文字列アルゴリズムについて簡単な説明とpythonでの実装が記載されています
[Wikipedia]
(https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%8C%E3%83%BC%E3%82%B9%E2%80%93%E3%83%A2%E3%83%AA%E3%82%B9%E2%80%93%E3%83%97%E3%83%A9%E3%83%83%E3%83%88%E6%B3%95)
Tensorflow インストールでWARNING, numpy, metadata,...なんとかかんとかを解決。

```
pip install tensorflow
```

でインストールしようとすると、
こういうエラーが出ました。

```
FileNotFoundError: [Errno 2] No such file or directory: '/Users/-/anaconda3/lib/python3.6/site-packages/numpy-1.19.4.dist-info/RECORD'
```

とか、

```
No metadata found in ./anaconda3/lib/python3.6/site-packages
```

とか、

```
WARNING: Error parsing requirements for numpy: [Errno 2] No such file or directory: '/Users/-/anaconda3/lib/python3.6/site-packages/numpy-1.19.4.dist-info/METADATA'
```

# 解決策
外国に解決された方がいました。
[Installation problem :Could not install packages due to an EnvironmentError: [Errno 2] No such file or directory: #6647](https://github.com/googleapis/google-cloud-python/issues/6647)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276138/0ac3f529-d581-b856-675c-e67c1d2a4a81.png)
翻訳...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276138/10536b93-1db4-adab-575c-4836efb451a6.png)

つまり、/Users/-/anaconda3/lib/python3.6/site-packages/ に存在する他のライブラリのフォルダーにあった、METADATA、metadata.json、RECORDを持ってきて入れました。そしたらなんか解決します。
なんじゃこりゃ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276138/e76ec1e5-993e-3d01-afcb-8eafb4f13a29.png)
Rails RSpec による画像添付結合テスト

#はじめに
RSpecによるオリジナルアプリの結合テストを行っています。画像投稿機能において、「テスト用の画像を添付する」、「添付したテスト用の画像が画面上にあるか」の2つを忘れていたので、備忘録として書き記します。

＃目次
1.テスト用の画像を添付する
2.添付したテスト用の画像が画面上にあるかテストする


#1.テスト用の画像を添付する
ここではimage_pathという変数にテスト用画像(test_image.jpg)を添付する。この時相対パスで指定する。
attach_fileメソッドはアップロードのinput要素にテスト用画像を添付することができる。第一引数にアップロードするinput要素のname属性の値、第二引数にアップロードする画像のパス、第三引数にオプション(ここではmake_visible: trueで一時的に表示)を設定する。

```ruby:spec/system/◯◯_spec.rb
# 添付する画像を定義する
image_path = Rails.root.join('public/images/test_image.jpg')
      
# 画像選択フォームに画像を添付する
attach_file('desk[image]', image_path, make_visible: true)
```

#2.添付したテスト用の画像が画面上にあるかテストする
画像を投稿すると、画像一覧ページに遷移する。遷移先で投稿した画像があるかの確認は下記コードに記す。have_selectorで要素があるか判断する。ちなみにhave_content()で文字列があるかのマッチャになる。

```ruby:spec/system/◯◯_spec.rb
expect(page).to have_selector("img[src$='test_image.jpg']")
```

以上
yukicoder contest 276 参戦記

# yukicoder contest 276 参戦記

## [A 1298 OR XOR](https://yukicoder.me/problems/no/1298)

C = N とすると、求める A, B の条件は A or B = N, A xor B = 0 となる. つまり、N を2進数で考えた時に立っているビットが A と B のどちら片方で立っていれば条件を満たせる. そのようなものの一つとして、N の MSB だけ落とした整数と、N の MSB だけが立った整数がある. ただし、前者は N が MSB だけが立っている場合には 0 となってしまうので、答えとならない.

```python
N = int(input())

c = -1
t = N
while t != 0:
    c += 1
    t >>= 1

B = 1 << c
A = N ^ B
C = N

if A == 0:
    print(-1, -1, -1)
else:
    print(A, B, C)
```

## [B 1299 Random Array Score](https://yukicoder.me/problems/no/1299)

ある A<sub>i</sub> が選ばれる可能性は 1 / N で、選ばれたときは A の要素の総和は A<sub>i</sub>×N 増える. これを積算すると結局1回の操作で A の要素の総和が増える期待値は A の要素の総和そのものである. つまり1回の操作毎に倍になるので、最終的に求める解は A の要素の総和×2<sup>K</sup>となる.

```python
N, K, *A = map(int, open(0).read().split())

m = 998244353

print(sum(A) * pow(2, K, m) % m)
```
Codeignater3を使ったMPAサイトからNuxt.js+Vueへのサイトリニューアル

# はじめに
　Vue.js(CDN版)を採用したPHP動的サイトから、Nuxt.js+Vueを使ったいわゆるSPAサイトへのリニューアルを敢行した。

## 経緯と歴史
　最初は、フレームワークを使わないサイトとして設計したが、のちにSmatryを採用し、Viewとロジックを分離した第二世代をリリース。その後、Codeignater3を採用し、本格的にPHPフレームワークを採用した第三世代と進化していったが、リプレースの切っ掛けはいずれも機能拡張を繰り返し、いずれも **現状に限界を感じよりモダンな技術を採用**していった経緯がある 。

## 今回は何が限界だったのか

### Vueライブラリの複雑化
　当初はJqueryを採用していたが、Vue.jsの導入に合わせライブラリが複雑化し、バージョンアップへの不安と煩雑さがつきまとうことになった。

### 痒いところに手が届かないフレームワークとViewのカスタマイズの煩雑化
　UIフレームワークとして採用していたMaterializeはVue前提ではないため、開発を進めるにつれCSSをカスタマイズを行う面が多くなり、フレームワークのメリットが少なくなるとともに、CSSの開発に多くの時間が取られることになった。

### 更新手順およびViewの煩雑化・複雑化
　ページが複雑化するに伴い、PHPのinclude機能で使い回すView画面がスパゲティ化するようになり、速度向上で導入したPWAのServiceWorkerのバージョンを手作業で書き換えるなどの更新の手間が極めて煩雑になりつつあった。

### ベストプラクティスな技術を試したい
　こうした状況が重なり、最新のフロントエンドのベストプラクティスとも言える技術で再構築を検討することとなった。当初はログインシステムの関係からVue-Cliのみを導入し、MPAのままの構築を行う事も検討したが、ユーザーへのID・パスワードの再設定のデメリットを考慮しても、Firebase Authenticationを採用した方が、セキュリティ面やプログラミング・維持などあらゆる場面でメリットがあると判断。Nuxt.js+VueによるSPAを採用することとなった。

## 開発
### バックエンド
　SPAとなれば、必然的にフロントとバックエンドが分離されるが、リニューアル前より無限スクロールを採用していたことから部分的にCodeignaterにAPIを実装し、axiosを用いた非同期通信で情報を取得ていたこともあり、開発時間短縮のために、バックエンドは引き続きCodeignaterを改良およびリファクタリングしてそのまま採用することとなった。

### フロントエンド
　Vue3およびTSの採用については現時点では見送ることとして、Webにサンプルなどのドキュメントが豊富なVue2.6.11とJSを採用した。
UIフレームワークはvuetifyを採用。最初はとっつきにくかったけど、高機能でデザインの完成度が高いので慣れてしまえば本当に楽。最初からコンポーネント至高なので、こちらも楽だが、無秩序にやってしまうとまたスパゲティになるので注意したい。

### 開発
　10月頭に開発がスタートをして、形になるリリースまで1ヶ月半。細かな機能追加と調整に二週間程度で完成することになった。

## 感想
　今回のリニューアルは技術的に本当に勉強になりましたし、サイトの管理と開発が本当に楽になりました。フロントとバックを分離した疎結合化は精神的にも楽になった感があります。Nuxt.jsは現時点でのベストプラクティス的な技術ではありますが、技術的に未熟で採用できないという事情はあるにしろ、基礎を習得しないと応用はできないとはいえ、随分と遠回りした印象もあります。これまでは煩雑な保守管理に時間を浪費していましたが、今後のページはペラ1でも無い限りNuxt.jsファーストで行きたいと思います。
Oculus Integration Unity2019


◆環境
Unity2019.4.16f1
IDE VS2019 free

[Unity]
Vulkanの削除
Android6.0
ネットワークパーミッション

Oculus Integrationのインストール

Oculus XR
XR Plugin 
Oculus Android　-> これで⇓画像の衝突が起こる
Swich Platform (10分くらいかかる）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/c1be4c76-c991-c538-fe3d-335f9c8487ed.png)

Assembly with name 'Unity.XR.Oculus.Editor' already exists (Packages/com.unity.xr.oculus.android/Editor/Unity.XR.Oculus.Editor.asmdef)
Assembly with name 'Unity.XR.Oculus.Editor' already exists (Packages/com.unity.xr.oculus/Editor/Unity.XR.Oculus.Editor.asmdef)


◆解決（これだっけ？）
C:\AndroidProject\2000\2010\OcuAndroid2\Library\PackageCache\com.unity.xr.oculus.android@2.38.6\Editor の当該ファイルを削除

Unity2018だと発生しない？
トリボナッチ数列のn番目を求める関数をメモ化してみた！(JavaScript)

## はじめに
最近、Udemyでアルゴリズムの講座とかをやってたりするのですが、JavaScriptでフィボナッチ数列のプログラムを書いて、それをメモ化するのが面白かったので、トリボナッチ数列でも少し変えてやってみました。

Stephen Grider先生の講座はどれも分かりやすいです。
参考：[The Coding Interview Bootcamp: Algorithms + Data Structures
](https://www.udemy.com/course/coding-interview-bootcamp-algorithms-and-data-structure/)

## トリボナッチ数列とは

>トリボナッチ数列は 0、0、1 で始まり、以後の項がその前の3つの項の和となる数列です。

引用：[フィボナッチ数列（９）：　トリボナッチ数列とテトラナッチ数列の計算](http://www.enjoy.ne.jp/~k-ichikawa/Fibonacci9.html)

## 確認用のテスト
少し冗長かもですが、こんな感じに書いてみました↓

```js:src/test.js
const tri = require("./index");

test("関数が定義されているか", () => {
  expect(typeof tri).toEqual("function");
});

test("n=1の時", () => {
  expect(tri(1)).toEqual(0);
});

test("n=2の時", () => {
  expect(tri(2)).toEqual(1);
});

test("n=3の時", () => {
  expect(tri(3)).toEqual(1);
});

test("n=4の時", () => {
  expect(tri(4)).toEqual(2);
});

test("n=5の時", () => {
  expect(tri(5)).toEqual(4);
});

test("n=50の時", () => {
  expect(tri(50)).toEqual(3122171529233);
});

```

## for文を使ったやり方

一番最初に思い付いたのはfor文を使った基本的なやり方でした。

```js:src/index.js
function tri(n) {
  const arr = [0, 0, 1];
  for (let i = 3; i <= n; i++) {
    arr[i] = arr[i - 3] + arr[i - 2] + arr[i - 1];
  }
  return arr[n];
}

module.exports = tri;
```

次のコマンドでテストを実行！

```zsh
jest src/test.js
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697143/91808cf2-4979-6ddb-e9fc-258f7e0d50bd.png)
うまくいきました！

## 再帰関数を使ったやり方

再起的なやり方を使って、コードを短くできました！

```js
function tri(n) {
  if (n < 3) return n === 2 ? 1 : 0;
  return tri(n - 3) + tri(n - 2) + tri(n - 1);
}

module.exports = tri;
```

しかし、このやり方だと、どんどん枝分かれしていって、nが50の時には何回も同じ呼び出しをテストがなかなか終わりません。
なので、以下のようにメモ化をしてみます。

```js
function memorize(fn) {
  const cache = [];
  return function (args) {
    if (cache[args]) return cache[args];
    const result = fn.call(this, args);
    cache[args] = result;
    return result;
  };
}

function slowTri(n) {
  if (n < 3) return n === 2 ? 1 : 0;
  return tri(n - 3) + tri(n - 2) + tri(n - 1);
}

const tri = memorize(slowTri);

module.exports = tri;
```

少し複雑で分かりにくいかもしれません。一応説明↓

* triの宣言のところから見ていくと、memorizeはfunction(args){...}を返すので、argsにはnが入る。
* memorizeの中の関数では、配列cacheにnの時の値があればそれを返して、なければfnの引数nにargsに入っていたnが入って呼び出せれます。その後に求められた値がcacheに格納されます。
* fnはmemorizeの引数なので、slowTriです。
* slowTriのなかでnが３以上なら、枝分かれしてtriが呼び出されます。枝分かれしていきnが３より小さくなるまで繰り返されます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697143/6bb6aae5-1f4c-a717-cab9-c82fcf87c0ad.png)

テストがうまくいきました！

## 終わりに
ここまで読んでいただきありがとうございました！私の説明が下手で少し分かりにくかったらごめんなさい！
結果的にfor文のやり方より長くなってしまいましたが、素のJavaScriptを使って、関数のメモカを書いたの初めてなので勉強になりました。アルゴリズムの問題は人によって時方が結構違って、毎回何かしら学べるので楽しいです。
感想やご要望などお待ちしております！
matplotlibを使ったpythonジョブでsshサーバーを抜けたあとでもエラーが出ないようにbackendをうまく切り替える

# エラーになる条件

以下のmatplotlibで図を保存するpythonコードを考える。

```py:check.py
import time
import matplotlib
import matplotlib.pyplot as plt

# あとでsshサーバーを抜けるための猶予
time.sleep(10)

print(matplotlib.get_backend())

fig = plt.figure(figsize=(3.0, 3.0))
plt.plot([0, 1, 2, 3], [0, 1, 2, 3])
plt.savefig("hoge.png")
```

このコードを

```console
$ python3 check.py
$ python3 check.py $ 
```

のように普通にフォアグラウンド、バックグラウンドで実行しても問題なく図は保存される。
しかしながら、sshサーバー上で次のようにバックグラウンドジョブで投げたあとにサーバーを抜けるとtkinterのdisplay周りのエラーで落ちる(sshの-Xや-Yオプション関係なく)。

```console
$ nohup python3 check.py > log 2>&1 & # sleepで止まっている間にサーバを抜ける
```

```txt:log
TkAgg

Traceback (most recent call last):
  File "check.py", line 9, in <module>
    fig = plt.figure(figsize=(3.0, 3.0))
...
    window = tk.Tk(className="matplotlib")
  File "$path/lib/python3.7/tkinter/__init__.py", line 2023, in __init__
    self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: couldn't connect to display "localhost:10.0"
```

これは今のbackendにTkAggのようなGUIを使うbackendを指定していることが原因なので、コード内で明示的に`matplotlib.use('Agg')`を指定するか、

```console
$ python3 -c "import matplotlib ;print(matplotlib.get_configdir())"
```

で確認できる場所にある`matplotlibrc`のbackendをAggにするか、`plt.ioff()`を使いインタラクティブモードをoffにするかなどをして回避する必要がある。


いずれにしてもサーバーを抜けるようなバックグラウンドジョブを実行するときだけbackendを書き換える方法では反映し忘れたり、戻し忘れたりするので`nohup`を使いバックグラウンドジョブを実行するときだけbackendをAggに切り替えられるようにしたい。

# 解決策

`nohup`を指定したバックグラウンドジョブを実行しても特に新たな環境変数は作成されないので自分で環境変数を適当に指定する。
このときに`export`コマンドで指定してしまうとログアウトするまで環境変数が残ってしまうので上記のように実行時にのみ反映されるようにする。

```console
$ BG=1 nohup python3 check2.py &
or
$ alias nohup=`BG=1 nohup` # bashrcやzshrcに追加
$ nohup python3 check2.py &
```

pythonコードは次のように環境変数`BG`の有無によってbackendをAggに変更する処理を入れる。

```py:check2.py
import os
import time
import matplotlib

# 環境変数BGがある場合のみ実行される
if os.getenv('BG') != None:
    matplotlib.use('Agg')  # backendを明示的に指定する場合は import matplotlib.pyplot より前に書く

import matplotlib.pyplot as plt

time.sleep(10)

print(matplotlib.get_backend())

fig = plt.figure(figsize=(3.0, 3.0))
plt.plot([0, 1, 2, 3], [0, 1, 2, 3])
plt.savefig("hoge.png")
```

`BG`という環境変数が存在しなければ`os.getenv('BG')`で`None`が返るので、存在するときだけ上記の`matplotlib.use('Agg')`が実行され、サーバーを抜けたあとでも正常に図が保存できる。なお、`plt.show()`があるようなコードではbackendがAggの場合はエラーになるので上記の環境変数か`matplotlib.get_backend()`結果を使い実行させないようにする必要がある。
VS Codeのショートカットをいい感じにいじった 

# 概要

VS Codeでのコーディングのストレスを減らすために少し設定をいじった話を書きます。
筆者は某l社の外付けキーボードを使っているのですが、十字キーがかなり小さく、度々打ち間違えてはストレスをためています。
今回はそのストレスを減らすため、十字キーを使わなくてもカーソル移動ができるよう（十字キーを使ってもできるよう）ショートカットの設定をいじりました。


# 実現したいこと

- 既定の設定通り十字キーを使ってカーソル移動ができる
- vimっぽく、下記のような組み合わせでカーソル移動ができる（ctrl+kは他のショートカットに使うので要検討…)

| キー       | コマンド      |
| -------- | --------- |
| Ctrl + h | カーソルを←に移動 |
| Ctrl + j | カーソルを↓に移動 |
| Ctrl + k | カーソルを↑に移動 |
| Ctrl + l | カーソルを→に移動 |

## キーボードショートカットから設定しようと試みる

まずはサイドバー下部の`管理`から、キーボードのショートカットをクリックし、キーボードショートカットを開きます

![キーボードショートカット一覧](https://paper-attachments.dropbox.com/s_6898AD9035ED7203B2244A27EF4AD9AE360B8F24B8A46494821078C942F5E1C1_1606432668915_image.png)


既定では、←の矢印キーに`cursorLeft`が割り当てられてます

![割り当てを変更できる](https://paper-attachments.dropbox.com/s_6898AD9035ED7203B2244A27EF4AD9AE360B8F24B8A46494821078C942F5E1C1_1606432312387_image.png)


編集して`cursorLeft`にctrl+kを割り当てることもできますが、そうすると←の矢印キーでカーソル移動ができなくなってしまいます。
今回はショートカットの変更ではなく、追加がしたいためこの画面からは難しそう….


## keybinding.jsonから設定を変更する

VS Codeのショートカット設定ファイルである、`keybinding.json`を編集することでショートカットの追加を行うことが出来ました。

Ctrl + Shift + P（macは command + shift + P）でコマンドパレットを開き、`keyboard shortcuts`と入力し、キーボードショートカットを開きます。（**既定のキーボードショートカットではありません！**）

![コマンドパレットから「基本設定: キーボードショートカットを開く (JSON)」を選択](https://paper-attachments.dropbox.com/s_6898AD9035ED7203B2244A27EF4AD9AE360B8F24B8A46494821078C942F5E1C1_1606432823101_image.png)


下記のようにそれぞれの`key`に対し、`command`と`when`を入力して、保存をすることでショートカットの追加をすることができます。

![カスタマイズをしたkeybinding.json](https://paper-attachments.dropbox.com/s_6898AD9035ED7203B2244A27EF4AD9AE360B8F24B8A46494821078C942F5E1C1_1606432962517_image.png)


ツールを自分用にカスタマイズするの良いですね。


# 参考

[【VSCode】ショートカットを設定・変更・確認する方法｜コマンドパレットのコマンドなど](https://blog-and-destroy.com/25197)
Thymeleafの？（クエスチョンマーク）ってなんぞや


Thymeleafを業務で使っていて、\${user?.name}とか${object?.id}みたいな記法を見かけて
使い方が分からなかったのでメモ

※誤りがありましたらご指摘ください。
##結論

Safe Navigation operatorと呼ばれるいわゆるNullチェックをしてくれる
Spring Expression Language (SpEL)の記法の一種です。

ちゃんとSpringのドキュメントにものっていますね。

https://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/expressions.html#expressions-operator-safe-navigation

訳してみると、以下のとおりです。

>
セーフナビゲーション演算子は、NullPointerExceptionを回避するために使用され、Groovy言語に由来する。通常、オブジェクトへの参照がある場合は、オブジェクトのメソッドまたはプロパティにアクセスする前に、それがnullでないことを確認する必要があります。これを回避するために、安全なナビゲーションオペレーターは、例外をスローする代わりに単にnullを返します。

##使い方

~~~html:hoge.html

<tr th:each="o: ${object}">
    <td th:text="${o.id}"></td>
    <td th:text="${o.user?.name?}"></td>
    <td th:if="${o.address?.contains('Tokyo')" th:text=""></td>
    <td th:if="${o.salary? gt 10000}" th:text=""></td>
</tr>
~~~

例えば、objectエンティティにuserエンティティやaddressエンティティを埋め込んで、
埋め込んだエンティティのフィールドを取得するときにこのように使います。

このように参照したいオブジェクトの後ろに？をつけることで、本来nullであればNullPointerExceptionが帰ってくるところを、nullの場合は空を返してくれます。

上記のように連続でつけることもできますし、必要であれば？のあとにJavaのメソッドを使うこともできます。
（Thymeleaf内でJavaメソッドが使えるのは、ThymeleafがはOGNLというJavaの値にアクセスするための式言語で書かれているため）
##注意点

値や配列を扱うフィールドでセーフナビゲーション演算子を使うときは注意が必要です。
この演算子はnullだけでなく、0もfalseと判断するようです。
##ちなみに

似たような演算子にエルビス演算子という演算子があるみたいです。

https://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%AB%E3%83%93%E3%82%B9%E6%BC%94%E7%AE%97%E5%AD%90

PHPやKotlinでサポートされているそうですが、そういう言語だと普通に使う演算子なのかしら。

以上です。
LinuxでDiscordの画面共有がうまくいかない問題

ゲームバイスチャットをはじめ、あちこちで使われている、コミュニケーションツールのDiscord。

手元のLinux上(KDE) では画面共有があまりうまく動いていませんでした。ちょっと本腰を入れて解決策を探ったので、その記録です。

Discordで画面共有をしようとすると、アプリケーション単位で配信したりする機能があると思うのですが、それがうまく動作しません。
配信対象にするためのアプリケーションを選択する画面に、アプリケーション一覧が出てこないんですね。
それから、デスクトップ全体を配信するモードの方も、マルチモニター環境では複数台のモニターが一画面にまとめられて配信されてしまいます。

この問題、実はデスクトップ上の仮想ターミナルからDiscordを起動することで回避可能です。おそらく、起動方法によって何らかの環境変数が未設定になってしまうんだと思います。

とりあえずシェルを経由するように自分でデスクトップエントリを作成して、それを使うようにすることで回避できました。
問題の根本原因はなんなんでしょうね…

参考までに、作成したデスクトップエントリを書いておきます。
`Exec = zsh -c hogehoge` として、シェルを一度通して起動するのがミソです。

```
#!/usr/bin/env xdg-open
[Desktop Entry]
Version=1.0
Name=Discord PTB
StartupWMClass=discord
Comment=All-in-one voice and text chat for gamers that's free, secure, and works on both your desktop and phone.
GenericName=Internet Messenger
Exec=zsh -c ${HOME}/.local/DiscordPTB/DiscordPTB
Icon=com.discordapp.Discord
Type=Application
Terminal=false
StartupNotify=true
Categories=Network;InstantMessaging;
```
Gatsby+contentfulでRichTextのjsonが見当たらない...

#状況
リッチテキストを扱うためにgraphqlでbodyのjsonを取得したいが、データが無いといわれる

```pages/index.jsx

import { documentToReactComponents } from "@contentful/rich-text-react-renderer"

export default ({ data }) => {
  return (
    {documentToReactComponents(data.contentfulBlogPost.content.json)}
  )}

export const query = graphql`
  query {
    contentfulBlogPost {
      title
      content {
        json <-これが無い!!!!!!!
      }
    }
  }
`
```

#gatsby-source-contentful `v4`
2020/11/9にRichText関連の大きなアップデート、`BREAKING CHANGES`(互換性を破る変更)があったようです。

> ・Refactor Rich Text implementation in gatsby-source-contentful (#25249) (a256346), closes #25249 #24221
`BREAKING CHANGES`
This major release improves Contentful's Richtext experience. If you are not using the Rich Text Contentful field type there are no breaking changes.

詳しくはリリースノートを確認ください。
https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-contentful/CHANGELOG.md#400-next0-2020-11-09

### 変更点
今回関係ありそうなのは以下の通り

> Use the `raw` subfield instead of `json`

- `json`の代わりに`row`を使ってね

> To render Rich Text fields use the new `renderRichText()` function from `gatsby-source-contentful/rich-text`

- `gatsby-source-contentful/rich-text`の`renderRichText()`をRichTextの描画に使ってね

#簡単なサンプル
基本的には`documentToReactComponents`と使い方は同じ
引数は`row`までは参照しないように注意
基本的には`rich-text-react-renderer`のラッパーのようですね
https://github.com/contentful/rich-text/tree/master/packages/rich-text-react-renderer

```index.jsx

import { renderRichText } from "gatsby-source-contentful/rich-text"

export default ({ data }) => {
  return (
    <p>{data.contentfulBlogPost.title}</p>
    {renderRichText(data.contentfulBlogPost.content⭕️, {})}
  // renderRichText(data.contentfulBlogPost.content.raw❌, option)
  )}

// graphql
export const query = graphql`
  query {
    contentfulBlogPost {
      title
      content {
        raw
      }
    }
  }
```

#まとめ
ほかにもrichTextの体験が向上しているそうなので詳しくはGithubのリリースノートをご確認ください。
公式ドキュメントがまだ追いついてないらしいので、日本語での情報も探すの大変だとおもいます。。

**とは言ったものの、issueを読み漁って見るとわかりますが、なんなら公式のreadmeも間違っている箇所があるみたい。**


気が向いたら別記事に`v4`でのリッチテキストの詳細をまとめたいところですが、
実際どれくらいの人がこの記事を見ているかわからないので、モチベーションが正直ないです。

#余談
これでjsonにしても問題なさそう

```
JSON.parse(data.contentfulBlogPost.content.raw)
```

## 画像が表示されない問題
公式のissueにて画像が表示されない場合の対応が書かれていました。

https://github.com/gatsbyjs/gatsby/discussions/28098
`__typename`と追加しないと`raw`の中にある`"nodeType": "embedded-asset-block"`の画像の参照が解決されないようです。

```index.jsx
export const query = graphql`
query{
  body {
        raw
        references {
          ... on ContentfulAsset {
            contentful_id
            __typename
            file {
              url
            }
          }
        }
      }
    }
`
```
ストレージの整理をしてたらFlutter iOSビルドができなくなった件。

#症状
Macのストレージがいっぱいになってきたので、いらなそうなファイルを消していたら、iOSビルドができなくなった。

#エラーメッセージ
ld: framework not found Flutter
clang: error: linker command failed with exit code 1 (use -v to see invocation)

とか。
その後flutter cleanしたら、Pod　installでもエラーが出た。
Flutter: Cocoapods The 'Pods-Runner' target has transitive dependencies that include static binaries: Flutter.framework

#解決
①ホーム直下に置いてあったflutterフォルダ内を、再インストールで更新してから、
②flutter cleanして、
③ios/Flutter/Flutter.frameworkを丸ごと削除して再ビルドしたら、自動生成してくれてビルド完了した。
https://stackoverflow.com/questions/50306019/flutter-cocoapods-the-pods-runner-target-has-transitive-dependencies-that-inc

①の大元のflutterSDKフォルダが狂ってて、生成されるios/Flutter/Flutter.frameworkも狂ってたってことだね。