OmniAICreator/Qiita-1.07M huggingface dataset:
Laravelとjsのfetchの組み合わせで躓いた話

# 何が起きたか
jsでajax通信がしたく以下のように書いた。

```js
fetch(url, {
  method: "POST",
  headers: { "Content-Type": "application/json; charset=utf-8" },
  body: JSON.stringify(parameters)
})
```
これで、バリデーションエラーで弾かれた場合、Laravelからはステータスコード422とエラーメッセージが帰ってくるはずだった。
なのに、ステータスコードは405でしかもエラーメッセージは何も帰ってこない。
これの解決に3時間くらいかかってしまったのでここに残しておく。

# 結論
headersには`"X-Requested-With": "XMLHttpRequest"`が必要。

# 解説
結論を見れば分かるかもしれないが、Laravel(正確には拡張元のsymfony)はリクエストヘッダーの上記を見てajaxかどうかを判断している。
なのでこれを入れないと、Laravelは通常のリクエストと判断しフォーム画面に戻すべくRedirectResponseを返す。
これにより、何等かの原因で405というおかしなコードが帰ってきた（この時点でおかしいことは分かったのでこれ以上は詳しくは見ていない）。


実際にソースを追ってみたところ以下のようになっている。

1. まず[ここ](https://github.com/laravel/framework/blob/c29c15b2492590299a7f8563dc153456531f277a/src/Illuminate/Validation/ValidatesWhenResolvedTrait.php#L25-L27)で、バリデーションに引っ掛かった場合は`failedValidation()`を実行しValidationExceptionをthrow
2. 例外ハンドラがValidationExceptionをcatchし、[ここ](https://github.com/laravel/framework/blob/50efe099b59e75563298deb992017b4cabfb021d/src/Illuminate/Foundation/Exceptions/Handler.php#L261-L263)でJsonResponseを返すかRedirectResponseを返すかを分岐
3. `expectsJson()`は[ここ](https://github.com/laravel/framework/blob/c29c15b2492590299a7f8563dc153456531f277a/src/Illuminate/Http/Concerns/InteractsWithContentTypes.php#L42-L45)で`ajax()`の結果からajax通信かどうかを見ており
4. `ajax()`は[ここ](https://github.com/laravel/framework/blob/c29c15b2492590299a7f8563dc153456531f277a/src/Illuminate/Http/Request.php#L238-L241)でxmlHttpRequestかを見ており
5. xmlHttpRequestかは[ここ](https://github.com/symfony/symfony/blob/f9411ab4806f7f669deb4bea927cd2f251411c52/src/Symfony/Component/HttpFoundation/Request.php#L1716-L1719)で`"X-Requested-With": "XMLHttpRequest"`かを見ている

# 所感
「laravel fetch 405」とかでググってもヒットしないものだから苦労した。。常識なのだろうか。
常識なのであればこの機会に知ってよかったと思うことにする。
wordpress　contact7にCSSがうまく当たらない場合

制作したプロジェクトをwordpress化する中で
contact7を使用箇所でなぜかCSSが１部分だけ外れてしまう

調べみるとコンタクト７の設定画面からコンパイルされる際に
解釈を付け加えて読み込みされる部分があるようです。

※3Dボタン作成のためinputbuttomタグを２箇所設置している特殊なケースです。

```html
        <div class="form-submit submit">
          <span class="cubic-btn">
            <span class="hovering">
              [submit class:submit-btn "送信"] //inputタグをcontact7タグへ入れ替え
            </span>
            <span class="default">
              [submit class:submit-btn "送信"]　//inputタグをcontact7タグへ入れ替え
            </span>
          </span>
        </div>
```

上記のようなhtmlのインデントをそのままの状態で
コンタクト７のタグで入れ替えをすると

[![Image from Gyazo](https://i.gyazo.com/147b1f66fa24850db3862f7bcbe59335.gif)](https://gyazo.com/147b1f66fa24850db3862f7bcbe59335)

このように３DボタンのCSSが盛大に崩れました

原因はコンタクト７の中でインデントをつけた部分に
brタグが生成されていることでした。

デベロッパーツールで見てみると

[![Image from Gyazo](https://i.gyazo.com/51cdc6f607f693b8e373e311d50da787.png)](https://gyazo.com/51cdc6f607f693b8e373e311d50da787)

このように見覚えのないbrタグが入っています。
右クリックでDeleteElementしていくと

[![Image from Gyazo](https://i.gyazo.com/60717b7943089398ebb8579d3742d78a.gif)](https://gyazo.com/60717b7943089398ebb8579d3742d78a)

このようにCSSが正しく当たっています。

どこでbrタグが入ったかというとcontact7の
プラグインの中でインデントするために改行している箇所が原因でした。

コンタクト７は自動整形機能がデフォルトでonになっているようです。

これをオフにするにはconfig.phpに以下を追記しましょう

```php:config.php
define( 'WPCF7_AUTOP', false);
```

注意点としてはwp-settings.phpよりも前で読み込んでください。

後ろに書いてしまうとプラグインを読み込んだ後なので記述した定数が反映されません。
コロナで暇すぎて競プロと料理ばっかしてたらAtcoderで水色になった話

#はじめに
2020年5月20日にAtcoderのNOMURAプログラミングコンテスト2020に出て、水色になりました！いえい！旧ABCならもう出られないぞ！！
![キャプチャa.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646653/0d889cb2-cfba-c577-e0f6-4b39402770c9.png)
なんでこんなタイトルからしてゴミな記事書こうとしたかというと、自己顕示欲満たすためと、水色が遠いと思ってる人たちにここはやればこれるところだぞっていうことを伝えたかったからです。

#プロフィール
- 所属  
合コンしたくない大学ランキング第二位の通信大学三年生
![キャプチャb.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646653/91a222e9-c9cb-d1da-636d-c1d280ddf46a.png)
- 趣味  
バドミントン、ダーツ、スノボ、邦ロック聴くこと、料理
- 得意料理  
からあげ
- 好きなバンド  
UNISON SQUARE GARDEN, 赤い公園, tricot
- 得意科目  
家庭科、図工、体育
- プログラミング始めた時期  
大学一年生
- 好きな言葉  
下ネタ全般

…いやね、ほんとはqiitaに投稿するんだし、機械学習やってます！(キラッ)みたいなこと書きたいんですけどほんとに何もないんですよ。大丈夫か？？？  スペックだけならそこらへんのfラン私文陽キャと戦える気がします。

#時系列ごとにみていく
さて、時系列ごとに自分のデータを見ていきましょうか、ちょっと恥ずかしいですね。ここから真面目です。
##2018年4月ごろ～
###Atcoderと出会う
電気通信大にはMMAというコンピュータ系なんでもやってるサークルがあって、実はそこにちょっとだけ入ってました。（今は幽霊部員です。）（もし部員いたらメーリス消してもらえたらなんかおごります）
そこでたぶんあちらは覚えてないと思うんですけど先輩（確か編入の先輩）が競プロ布教してくれて、そこで知りました。ここがなければたぶん競プロに出会ってないです。
でもこの当時はプログラミングのプの字も知らなかったのでまったくコンテスト出てませんでした。
##2018年12月～2019年3月
灰色コーダーの時期です。大学の授業しかプログラミング勉強してません。
##2019年4月～11月
###茶色コーダーの時期
ここで変わったのは大学で競プロの授業を取ったことです（今期はない）
合コンしたくない大学ランキング二位の大学には競プロの授業が当時あって、通年で競プロに触って、ICPC出よう！って感じでした。強制的に競プロに触れる機会があったってのと、つよつよの先輩が何人かいたため、こんな世界があるんだー（）って知れました。
あと学生コンの懇親会にだけただ飯食いにいきました。つよつよの人ばっかでモチベ上がりました。あと競プロerの男女比に絶望しました（は？）
##2019年12月～2020年4月
###緑コーダーの時期
ここからちょっと本格的に競プロを始めました。
蟻本片手に簡単な問題埋めてた気がします。
あとライバル？もこの時期に緑になってて、なんだかんだ飲み会がないときは毎回コンテストに出て張り合ってた気がします。

##2020年4月～今
###コロナ自粛、引きこもり、そして…
春休みの期間は合宿免許にいってたりで忙しかったんですけど、コロナで休みが伸び、暇すぎて精進するようになりました。
![キャプチャe.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646653/cec91060-f834-d41e-c7c1-c24d697a9a78.png)
ちょうど連続し始めたところが合宿免許終わって東京に帰ってきたところです。
自分、死ぬほど勉強嫌いですけど人間暇だと何するかわかりませんね。毎日問題解いてました。あと料理めっちゃしてました。
codeforcesにもちゃんと出るようになりました。水色になる前にこっちで青になってました。
そして野村コンで崖をうまく使って水色に…

#習得したアルゴリズム
色別にその色で習得してたアルゴリズムを見ていきたいと思います。ぜひ参考にしてください。
###灰色
- 全探索  

###茶色
- BFS, DFS
- GCD, LCM
- グラフの構築

###緑色
- ダイクストラ（ライブラリ）
- プリム、クラスカル（ライブラリ）
- 繰り返しニ乗法
- 約数列挙（ライブラリ）
- 基本的なDP
- しゃくとり法
- 累積和、imos法
- Union-find
- 逆元計算（ライブラリ）
　　

こう見てみるとやっぱり緑でアルゴリズムの量が段違いに増えてますね。

#勉強法
###緑まで
まず灰色と茶色で停滞している人はそもそも必要なアルゴリズムを知っていない可能性が高いと思います。なので蟻本を見ることをおススメします。
辞書みたいに基本的なアルゴリズムが載ってるので、理解はともかくとして知ることができます。
知ればわかんないときに調べられます、あとは復習したらOKです。
これである程度習得したら抜けられますきっと。

###緑以降
自分がやってきた精進について書きます。
私はABCのC埋め、水パフォ毎日、codeforcesの問題気が向いたら解く、をしました。こどふぉはどうでもいいので置いてきます。前２つに対して話します。
ABCのC問題には難しいやつと簡単なのが混ざってますね。簡単な問題はアウトプットです。なるはやで処理しましょう。
難しい問題でインプットします。解説ACでもいいです。旧ABCの問題だとたまに無理だろこれ！ってなりますけど、こういう機会に無理やり理解してアルゴリズムの習得を図ります。
水パフォは旧ABCのCのむず問と同じ役割です。インプット（できればアウトプット）の機会です。

よく精進の話になると自分の実力で解けなきゃいけない問題解く派（長いので下埋めとします）と自分が解けなさそうな難しい問題解く派（上埋め）の２つに分かれます。私は後者です。理由はそもそもスタートラインに立ててないからです。
青以降の人はそもそも基本装備として特定の問題に対する必要なアルゴリズムを習得していると思ってます。この人たちが下埋めするのは考え方を固めるためってことが大きいと思います。
私たち雑魚が下埋めして得られるのはタイピングスピードだけだと思ってます。灰～緑の人はインプットの機会を作らないとそこから進めないと私は考えてます。
上埋めでアルゴリズム習得していきましょう。まず問題解くスタートラインに立ちましょう。以上調子に乗ったザコーダーからでした。

#最後に
実は水色あたりで競プロ飽きるてやめるかなって思ってたんですけど、まだまだ飽きる気配ないですね。趣味は競プロってしましょうか。また合コンしたくない大学ランキング上げそうなのでやめておきます。
【備忘録】CentOSにpostgreSQLをインストールしたけど、接続できなかった時の対処法

<h2><b>はじめに</b></h2>
<p>
この備忘録は、CentOS7にpostgreSql12をインストールして、自動起動が出来なかった際に対処して解決した手法を記述しています。
基本的には自分向けなので多少説明が雑な部分があるかもしれませんのでご容赦ください。
</p>
<h2><b>概要</b></h2>
忙しい人向け、事象と解決方法を記した項目です。

<h3>事象</h3>
psql -l を実行したところ以下のようなエラーメッセージが出力された。

<b>psql: エラー: サーバに接続できませんでした: サーバに接続できませんでした: そのようなファイルやディレクトリはありません
                              ローカルにサーバが稼動していますか?
                              Unixドメインソケット"/var/run/postgresql/.s.PGSQL.5432"で通信を受け付けていますか?
</b>

<h3>解決方法</h3>
/var/lib/pgsql/12/data/postgresql.conf
の
<b>#listen_addresses = 'localhost'</b>
を
<b>listen_addresses = '\*'</b>
に修正した（コメントアウトを解除し、値を'*'に変更）

再起動かけたら、無事にpsqlコマンドが通るようになりました。
インストールしたバージョンや環境によって多少confファイルの場所は変わるかもしれません。

これ以下の項目は、今回の環境や解決策を見つけるまでに試行錯誤した内容なので、読まなくても問題ないと思います。

<h2><b>開発環境</b></h2>
  ・CentOS Linux release 7.8.2003 (Core)
  ・psql (PostgreSQL) 12.3

<h2>経緯・詳細・その他試したことなど</h2>
ここからは、経緯や今回の解決方法以外に試したことなどをつらつらと書いていきます。

元々は、ラズベリーパイで室温・湿度・気圧を記録していきたいなと思い始めたことがきっかけでした。
その後、テキストファイル形式やDBで記録できたらいいなと思い、使わなくなったノートPCにCentOSをインストールして、それをサーバ機にしたました。
無事にpostgreSQLをインストール出来たまではよかったのですが、いざサーバを再起動し、psqlコマンドを実行すると前述のエラーが発生してしまった、というわけです。

まずは自動起動が出来ていないのでは、と思い自動起動の設定を行い、正しく設定が出来ているのか確認。

<b>自動起動の登録コマンド：sudo systemctl enable postgresql
登録結果確認コマンド：systemctl list-unit-files | grep postgresql
結果：postgresql-12.service                       <font color="red">enabled</font>

問題なく、設定が出来ている様子でした。

一方で、以下のようなコマンドで手動で再起動などを掛けるとちゃんと起動できる状態でした。
<b>service postgresql-12 restart</b>

一体何が悪いんだ、一体何が…。

<br><br><br>
あれ、そういえばインストールするときにそもそもポート番号指定したっけ？？
<br><br><br>
そんな中、ふと思い当たったのは、postgreSQL自体ってどこにインストールされているのだろうか、どこに設定ファイルの類は入っているのだろうか、ということ。
色々調べ、今回のファイルを見つけました。
このファイルでクライアントからの接続を許可する端末などの設定や、ポート番号の設定を行っているようです。
なので今回の解決方法も、<b>とりあえず</b>全ての端末からのアクセスを許可、ポート番号は5432で設定とすることでした。
ここはもうちょっとしっかりと設定をしないといけなさそうなところのような感じがしてます。

この辺りは今後の課題ですね。

あと自動起動がdisabledだったら自動起動してないのか、という検証もしないとなぁ…。
多分、自動起動しないんだろうけど…。
CA Tech Dojo サーバーサイド(Go)編に参加してみて

# CA Tech Dojo サーバーサイド(Go)編に参加してみて

はじめまして!!  takeです。
今回CA Tech Dojo サーバーサイド(Go)編に参加させていただいたのでその振り返り兼感想を残します。
**追記(2021/04)**
コロナウイルスが流行してからはオンライン版で実施されていますが、この記事に書いているCA Tech Dojo サーバーサイド(Go)編はオフライン実施でした。
この記事は長いこと限定公開にしていたため公開日が2021年になっています。


## 参加のきっかけ
今回私が参加したのはCA Tech Dojo サーバーサイド(Go)編の2期でした。申し込んだきっかけは、大学先輩からこのインターンの参加を勧められたことでした。
まさか自分が受かるわけないだろうなと半ば思いつつの応募だったので参加が決まったときはかなり嬉しかったです。しかし、同時に不安に駆られました。不安の要因としては、北海道に住んでいるので東京に移動し２週間インターンに参加するというあまりに大きなイベントであったということと、自分の持っている実力的な面でした。

##インターンの内容
開催場所：東京(CA本社)

期間：2020/02/17 - 2020/02/28
**コロナウイルスの流行により2020/2/21に中断**

内容：課題に沿ったAPIを実装し、そこから自分なりの改善や新機能の追加を行いました。課題を進めていく中で、Webサービスを作る上で基本となる、サーバー構築やデータベースを参照したAPI実装などについて学ぶことができました。

参加者：9人


## インターンに参加した感想
今回のインターンが自分にとって初めてのインターンだったのですが、このインターンが初めてでよかったと自信を持っていえます。参加前はとても不安が大きかったのですが、他の参加者や指導してくださるメンターの方々、インターンを実施してくださる人事の方々全員がとてもいい人たちで楽しく、充実した時間を過ごすことができました。

このインターンで、今後自分がバックエンドエンジニアを目指してプログラミングを行うためのノウハウを得ることができたこと、他大学の同じエンジニアを目指している学生と交流を持てたことがとてもよかったと思います。
また今回のインターンで初めて現場のエンジニアの働く様子や雰囲気などさまざまなことを感じることができました。

もともと私の開発経験は大学の授業で一応プログラミングを学んではいましたが、豊富な方ではありませんでした。Goの開発経験は半年ほどで、DockerやMySQLを用いて簡単なGET、POST処理を行うWebAPIを作成することができる程度でした。

同じ課題に取り組む参加者のプログラミング的思考やGitの使い方、新しい技術に関する知見などを得られました。
またメンターの方々が、たくさんの時間を割いてコードを細かくチェックし、レビューを下さったおかげで、自分のこれまで書いていたコードが大きく変わりました。
今回のインターンでの自分の成長は、自分のこれまでの成長のスピードの何十倍もの成長ができたと思います。

このインターンの経験を生かして今度どんどん開発していきたいと思います！

# 技術的なメモ
今回のインターンの個人的反省を書き残しておきます。  

* WebAPIを書く上でもっとパフォーマンスチューニングを行いたかった。  
DBとしてMySQLを用いていたのですが、複数のデータをinsertしたい時にfor文を愛してinsertするという力技を用いていました。中止になってしまった後半の期間でバルクインサートやトランザクションなどを用いて改善に取り組みたかったです、、、
* 無駄なコードが多かった。  
今回はMVCでWebAPIを作成していたのですが、どうしてもcontrollerとmodelが肥大化してしまっていた。ディレクトリ構成についてもっと考えるべきだった。また不要な処理や、効率の悪い部分を洗い出し改善したかった。
* エラーハンドリングをもっとしっかりしたかった。  
今回エラーの処理を疎かにしてしまっていたことも悔やまれます。エラーコードやlogruｓなどのパッケージを用いて本格的なエラーハンドリングを行いたかった。

自分は大学入学までほとんどPCを触った経験がなく、周りの同じエンジニアを目指す学生に比べてIT全般の知識が乏しいように感じました。もっと通信技術やハードウェアなどに関する知識を得る必要があるなと感じました。
MaixCubeでAIを体験する（顔認識）

# はじめに

MaixCubeを使うと、とても簡単にAIを体験・学習することができます。

# 準備

次のものが必要です

- MaixCube
- MaixPy
- モデル（[ここ](http://dl.sipeed.com/MAIX/MaixPy/model/face_model_at_0x300000.kfpkg) からダウンロード）
- kflash（[ここ](https://github.com/sipeed/kflash_gui/releases) からダウンロード）

kflash を使用して、モデルをフラッシュメモリに書き込みます。拡張子がkfpkgのファイルはモデルと、書き込み方法を指定するjsonのファイルがzip形式で圧縮されています。kflashでファイルを指定すると目的のアドレス（0x300000）に書き込んでくれます。

![MaixPy_20200531_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555397/9b71b847-d7e8-71c9-272b-b4f27b46c9d6.png)

# 実行

MaixPyの「ファイルを開く」を押すと、MaixPyにインストールされたMaixPyのでもが格納されたディレクトリが表示されます。そこで machine_vision フォルダの demo_find_face.py を開きます。

これを実行するだけで顔認識できます。

![MaixPy_20200531_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555397/89d482cd-0aaf-3e55-cd42-f4387c75e374.png)

ただし、元のサンプルのままでは画面に色が反転して表示されましたので、22行目を a = lcd.display(img.negate()) のように反転して表示するようにしてみました。

![MaixPy_20200531_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555397/517d192d-f273-77f0-80cb-a7818e3f269d.png)


簡単ですね。
Next.jsのDynamic Routingでパスパラメータを取得したときにundefinedになるときの対処

# はじめに
Next.jsのDynamic Routingとは/posts/:idみたいなpathでルーティングしたい場合pages/postsディレクトリ配下に[id].tsxを置くことで実現できる機能です。
idの値を使用してデータをフェッチすると思いますが、１回目のレンダリングではidの値を取得できない問題にハマり悩んだので共有しておきます。

# パラメータの取得
パスパラメータはクエリパラメータとしてページに送信され、他のクエリパラメータとマージされます。「はじめに」の例で言うと、idの値は以下のように取得できます。

```react
import { useRouter } from 'next/router'

const Post = () => {
  const router = useRouter()
  const { pid } = router.query

  return <p>Post: {pid}</p>
}

export default Post
```

実際に使用する場合はこんな感じになるかと思います。

```react
import { useRouter } from 'next/router'

const Post = () => {
  const ref = useRef()
  const router = useRouter()
  const id = router.query.id

  useEffect(() => {
    // ここでidの値を使用してデータをフェッチする 
  }, [ref]);

  // fetchしたデータを表示
  return <p>{hoge}</p>
}

export default Post
```

ここで最初のレンダリングrouter.query.idはundefinedとなります。

公式のドキュメントでは以下のように書かれています
> 自動静的最適化によって静的に最適化されたページは、ルートパラメータが提供されないままハイドレーションされます。

> ハイドレーションの後、Next.jsはアプリケーションの更新をトリガーにして、クエリオブジェクトにルートパラメータを提供します。

なので、再レンダリング時にidを取得できるということになります。

ここでuseEffectでデータをfetchするときにidに値が入っていないのでデータを取得できないし、stateも変化しないので再レンダリングできないという問題が起きました。

# 解決方法

最初のレンダリングでは、router.asPathとrouter.routeは等しくなります。ですが、パスパラメータがqueryで利用可能になり、router.asPathに反映されたあとはパスは違うのでそれによって検知することができます。

```react

import { useRouter } from 'next/router'

const Post = () => {
  const router = useRouter()
  const [id, setId] = useState<number>()

  // この部分を追加
  useEffect(() => {
    // idがqueryで利用可能になったら処理される
    if (router.asPath !== router.route) {
      setId(Number(router.query.id));
    }
  }, [router]);

  // idが取得されてセットされたら処理される
  useEffect(() => {
    if (id) {
      // ここでidの値を使用してデータをフェッチする 
    }
  }, [id]);

  // fetchしたデータを表示
  return <p>{hoge}</p>
}

export default Post
```

# まとめ
* Next.jsのDynamic Routingは最初のレンダリングでパスパラメータを取得できない
* router.asPathを使用して処理することでパスパラメータがqueryで利用可能になったときのイベントを発火させることができる

もし、もっと良い実装方法があればぜひコメントで教えてください
ローディングしたStandardScaler で transform するとエラーになる

# 前提

Machine Learningでは、学習の前処理としてデータを標準化します。
よく使われるのが、StandardScalar。
これは、学習時に利用したStandardScalarを保存し、本番データの予測時にも使います。

学習時は以下のような感じ

``` train.py
import pickle
from sklearn.preprocessing import StandardScaler

sc = StandardScalar()
sc.fit(df)
sc.transform(df)
pickle.dump(sc, open("./scaler/scaler.p", "wb"))
```

予測時は以下のような感じで、トレーニング時の標準化と揃える。

``` predict.py
sc = pickle.load(open('./scaler/scaler.p', "rb"))
_df = sc.transform(df)
```

# 問題点

上記のプログラムを実行すると下記のようなエラーが発生。

```
RuntimeError: The reset parameter is False but there is no n_features_in_ attribute. Is this estimator fitted?
```

なんだこりゃ。ググったなかで唯一ヒットしたのが以下。

https://github.com/hyperopt/hyperopt/issues/668

>Workaround: I was using scikit-learn version 0.23.0. Going back to version 0.22.0 solved this for me
>（0.23.0だとうまくいかないから、0.22.0使ってみな）

なるほど。
というわけで uninstall して、0.22をインストール

```
pip uninstall scikit-learn
pip install scikit-learn=0.22.0
```

結果、これでうまくいきました。
一過性のバグだとは思いますが、情報が少ないので残しておこうと思います。
Deviseの上にacts-as-taggable-on を使ったタグ機能　自分メモ

gemインストール

```
gem 'acts-as-taggable-on', '~> 6.0'
bundle install
```
テーブル作成

```
$ rake acts_as_taggable_on_engine:install:migrations
$ rake db:migrate
```
タグ保存
タグを付けたいモデルに以下のように追記する。(今回は Post モデルにタグを付けたかったので post.rb に記述)
modelフォルダから

```
class Post < ApplicationRecord
  acts_as_taggable
end
```

registration editで以下を追加
```
  <div class="field">
    <%= f.label :tag_list %><br />
    <%= f.text_field :tag_list, value: @user.tag_list.join(","), class:"form-control" %>
  </div>
```
スペースなどで区切りたい場合は、config/initializers/ に acts_as_taggable_on.rb を作成して、以下のように記述する。

```
ActsAsTaggableOn.delimiter = ' '
```

users show.html.erb も以下にしておく

```
<% @user.tag_list.each do |tag| %>
  <span class="badge badge-primary mr-1 p-2"><%= tag %></span>
<% end %>
```
もしくは

```
<% @post.tag_list.each do |tag| %>
  <span style="background-color: #e9e9e9; border-radius: 5px;"><%= tag %></span>
<% end %>
```

application.controllerにも以下をついか

```
devise_parameter_sanitizer.permit(:account_update, keys:[:tag_list])
```

追加情報
当たり前ですが、色んなメソッドが用意されている

find_related_skills　　同じタグに関連するタスクが表示される
taggings_count　メソッドではないですが、該当のタグの使用回数が表示されている
tag_counts　全てのタグデータを取得できる
などなど.....他にもまだありました。

使い方等はリファレンスを参照してください。

同じ名前で登録したタグの場合は、同じIDになるようになっている
例：Railsと別々のタスクで登録しても同じidになる


参考URL
https://qiita.com/ddgg7755/items/e1caa8b73d118822a0a2
https://qiita.com/daigou26/items/e67e61bbec338329ffac
https://qiita.com/kazuhj/items/31d3b1751d9c957b789f




Tag-itを使いたい場合

```
# Gemfile
gem "jquery-ui-rails"

bundle install
```

以下をvendor/assetsに追加
```

https://github.com/aehlke/tag-it


curl https://raw.githubusercontent.com/aehlke/tag-it/master/js/tag-it.js -o vendor/assets/javascripts/tag-it.js

curl https://raw.githubusercontent.com/aehlke/tag-it/master/css/jquery.tagit.css -o vendor/assets/stylesheets/jquery.tagit.css

curl https://raw.githubusercontent.com/aehlke/tag-it/master/css/tagit.ui-zendesk.css -o vendor/assets/stylesheets/tagit.ui-zendesk.css

```


application.js
```
//= require jquery
//= require rails-ujs
//= require jquery-ui
//= require tag-it
//= require activestorage
//= require turbolinks
//= require_tree .
```

app/assets/stylesheets/application.css
 *= require_tree .
 *= require jquery-ui
 *= require jquery.tagit
 *= require tagit.ui-zendesk
 *= require_self

おそらく必要
```
gem 'jquery-rails', '4.3.1'
```

edit.html
```
  <!-- #taggable　#tag-itにて追加 -->
  <div class="field",id: "user_tag_list>
    <%= f.label :リスト %>
    <%= f.text_field :tag_list, value: @user.tag_list.join(","), class:"form-control" %>
  </div>
```
```
<%= javascript_tag do %>
var myProject = {
  all_tag_list: <%= raw @all_tag_list %>
};
<% end %>
```

js
```
$(document).on 'ready page:load', ->
  $('#article_tag_list').tagit
    singleField: true,
    availableTags: myProject.all_tag_list
```

オートコンプリートとか以下参照
https://qiita.com/tyamagu2/items/75eeaa8ef208385aa341
http://rochefort.hatenablog.com/entry/2016/10/16/165139
Vue.jsのアプリケーションをAWS上のNginxで公開する。(404エラーの罠)

Vue.jsのアプリケーションをAWS EC2上のNginxで公開する際に役立った情報の備忘録です。
Nginxのインストール等は省略します。

##使用環境
Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type (無料使用枠)


##Nginxの再起動コマンド

```vim
;再起動
sudo nginx -s reload
```

##NginxのConfファイルの場所

```vim
;/etc/nginxフォルダへ移動
cd /etc/nginx

;nginx.confファイルを編集
sudo vi nginx.conf
```

##Nginxのrootフォルダの場所
root(/usr/share/nginx/html)

```vim
server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  localhost;
        root         /usr/share/nginx/html;
```

##公開(RLoginを使用)

nginxが起動していれば、後はVue.jsでnpm buildしたdist直下のデータを、root(/usr/share/nginx/html)直下にコピーすればよい。

RLoginなどのツールを使ってAWSのEC2に接続し、SFTPファイルの転送を行うのがオススメ。
筆者も使ってみてRLoginはかなり使いやすいと感じた。

参考記事
[Windowsターミナルソフト + Rlogin が最高すぎる！！](https://qiita.com/murachi1208/items/d6e4ce7ba75f1625fe51)

##historyモードの罠

Vue.jsのhistoryモードには、ユーザが直接URLをたたくと404エラーが発生する罠がある。
nginx.confに一行追加すれば、問題なく解消する。

公式ドキュメントにもしっかり書かれている。
https://router.vuejs.org/ja/guide/essentials/history-mode.html#nginx

```vue
location / {
  try_files $uri $uri/ /index.html; ←追加
}
```
Azure App Services + Blob Storage + CDNで、WordPressを構築 / [1] 全体編

# Azureで安くWordPressを構築
先日、Azureのいくつかのサービスを組み合わせて、WordPressを構築する、という作業をしました。
そこで備忘録も兼ねて、投稿してみます。

メインの部分としては、

-  Azure App ServiceのWebアプリを作り、WordPressをインストール
-  Azure CDNをフロントエンドにおくことで、
    - SSL化を実現
    - カスタムドメイン(独自ドメイン)を実現
    - アクセス過多でのサーバーダウンを防止

といったことを実現できます。

このアーキテクチャについては、「のりじ」さんのブログの下の記事から学びました。
かなり詳しく解説されていますので、App ServiceからCDNまでの流れについては、補足程度にしたいと思います。

[WebApps ＋ Azure CDNを使い年間1,000円程度で独自ドメイン・SSL対応済み高負荷対策なWordPressサイトを 作ってみた話。](https://zuvuyalink.net/nrjlog/archives/3528)

# プラスαで行ったこと
ここまでのところで、大枠は書いたようなものですが、実際に運用するには、もう少し工夫したいところがあり、その理由から書きましょう。
#### WordPressの管理画面へ入りにくい -> CDNの設定を変える
CDNは、キャッシュを保存して配信する仕組みなので、ユーザーごとにページが変わるようなものは向いていません。
つまり、WordPressの管理画面も、そのままCDNを経由すると不都合が生じます。

そのために、Azure CDNのルールエンジンを設定してあげます。


#### Web Appsのストレージ容量 -> Blob Storageを使う
Azure App Serviceの安いプランは、まず1つはCPUの1日あたりの時間制限で、これはCDNを使えば回避できました。
もう1つはストレージの容量で、データベースを別に用意せずに、MySQL In Appだと、1GBしかストレージしかありません。

そこで、Azure Blob Storageを使います。Azure Blob Storageは従量課金でのストレージサービスです。

#### オリジンサーバーへの直接アクセス -> IP制限をする
CDNのエンドポイントをフロントに置くだけでは、WordPress本体のあるオリジンサーバー(配信元サーバー)へ、誰でも自由にアクセスできてしまいます。

これを解消するためには、Web App側にて、CDNのPOPサーバーからのアクセスのみを許可し、それ以外からのアクセスを禁止しておく必要があります。

# 最終的には、
以下のようなアーキテクチャを目指します。
ここでは、

- Web Appのオリジンサーバーは、cotoso.azurewebsites.net
- CDNのエンドポイントは、www.cotoso.com

と仮定しています。
![architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645515/0ac849ad-38d4-b614-4024-afd08ba9dbde.png)

# つづき
それでは、以下のとおり、記事を分けて投稿していきます！

- [[2] Azure App Service + CDNでWordPressを構築する](https://qiita.com/sm_bd/items/30d025d09cc504ef6af6)
- [[3] Azure Blob StorageをWordPressで利用する](https://qiita.com/sm_bd/items/4aeab758750cf4b89623)
- [4] Azure CDNのPOPサーバーを取得し、Azure Web AppsのIP制限を自動で構成する <作成中>
[C#] Entity Framework Coreのデータベースファーストでエラーが出た時の対処方法


# エラー内容

```powershell
PM> Scaffold-DbContext "[ConnectionString]" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Entities
Build started...
Build succeeded.
Error:
  An assembly specified in the application dependencies manifest (project_name.deps.json) was not found:
    package: 'project_name', version: '1.0.0'
    path: 'project_name.dll'
```

# 対処方法

```powershell
dotnet ef dbcontext scaffold "[ConnectionString]" Microsoft.EntityFrameworkCore.SqlServer -o Entities
```

# 補足

以下は必須。

```powershell
dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.Design
```

# 参考資料

- [Entity Framework Core ツールのリファレンス - .NET CLI](https://docs.microsoft.com/ja-jp/ef/core/miscellaneous/cli/dotnet)
AWS Cloud9で空き容量不足メッセージ

AWS Cloud9を使っていたら、エラーメッセージが表示されるようになった。

>Your environment is running out of quota. Please make some free space.

空き容量が足りないらしい。
ひとまずEC2インスタンスを再起動したが変化なし。
EC2のボリュームを変更しようかと思ったが、その前に。

>sudo /bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
sudo /sbin/mkswap /var/swap.1
sudo /sbin/swapon /var/swap.1

スワップしてみたが変わらず。

以下記事を参考に、キャッシュをクリアしてみたらエラーメッセージは消えた。

https://hodalog.com/clear-memory-cache-or-swap-in-linux/

キャッシュクリアしようとした際に知ったのだが、
AWSのEC2インスタンスにはデフォルトではrootユーザーでログインできない。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/set-change-root-linux/

2020/6/6 追記
上記処理を行って数日後に同様のエラーメッセージが表示されたため、EC2インスタンスのボリュームを拡張することにした。
brew インストール直後にbash: brew: command not foundと出た話

## 目的

- brewをインストールを直後にbrewコマンドがうまく実行されなかったので解決方法をまとめる

## 実施環境

- ハードウェア環境(下記の二つの環境で確認)

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.5) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| Homebrew バージョン | 2.3.0 | 公式ページのコマンドを実行した[Homebrew](https://brew.sh/index_ja.html) |

## 問題

- インストール後に下記コマンドを実行してbrewの導入確認を実施したところ下記のエラーが発生した。

    ```terminal
    brew -v
    > bash: brew: command not found
    ```

## 解決策

1. 下記コマンドを実行してパスを通す。

    ```terminal
    echo export PATH='/usr/local/bin:$PATH' >> ~/.bash_profile
    ```
1. 下記を実行して設定ファイルを読み込む。

    ```terminal
    source ~/.bash_profile
    ```

## 追記

1. 本記事投稿後、かなり時間が経ってから新しいMacにbrewをインストールしてちょっとだけ詰まったのでまとめる
1. ちなみにshellはbashを使っている。
1. 「Next steps」に記載されている内容をbashに合わせて実行する。

    ![_bash_profile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/c6fcd448-7b32-265a-7052-64170737f1f6.png)

1. 下記を実行してみた。

    ```shell
    $ echo '# Set PATH, MANPATH, etc., for Homebrew.' >> ~/.bash_profile
    $ echo 'eval $(/opt/homebrew/bin/brew shellenv)"' >> ~/.bash_profile
    $ eval "$(/opt/homebrew/bin/brew shellenv)"
    ```

1. 問題解決

    ```
    $ brew -v
    Homebrew 3.6.21
    ```
【rails】デプロイ時のUglifier::Error: Unexpected token:　について

#はじめに

デプロイ時にでたエラー
`Uglifier::Error: Unexpected token:`

の解決方法を記載しておきます


#解決方法

```ruby:config/environments/production.rb
config.assets.js_compressor = :uglifier
```
上記の記述を下記の記述に編集します⬇︎

```ruby:config/environments/production.rb
config.assets.js_compressor = Uglifier.new(harmony: true)
```

編集したらコミットプッシュを忘れずに！

以上で解決できました。
インフラ初学者がAWSでポートフォリオを公開するまでに独学で学んだこと

先日、転職向けに作ったポートフォリオをAWSで公開したのですが、思い返すと公開までにかなり(無駄な？)試行錯誤を繰り返したので、備忘としてポイントを残しておきます。

筆者は、インフラ知識は独学なので、かなり使用技術に偏りがあるかもしれませんが、ご容赦ください。対象の読者は同じく独学でAWSを動かしており、アプリケーションの公開に悩んでいる初学者を想定しています。

##進め方の反省点
アプリケーションの作成とインフラの構築を分けてポートフォリオ作成を進めてしまった点。デバッグ環境では動いていたのに、本番環境に移行すると動かない、とかあるあるなので、インフラ構築はアプリケーションの一部として考えるべきでした。

Hello Worldした時点で、ある程度時間をかけてでもインフラ公開できる仕組みを構築しておいて、アプリケーションを作り込みながら、インフラ周りの知識を深めていく、といった進め方が理想的だったと思います。

##AWSを動かすのに必要な前提知識

とりあえず、公開できる程度まではAWSを触ってみた筆者の感想として、TCP/IPなどの通信の仕組み、Linux、Webサーバの知識は、ある程度ベースを固めておくべきだと感じました。

普段使わない知識を3種類も勉強するのは非常に負荷が高いのですが、最低限の知識がない状態で、アプリケーションを公開したい一心でAWSを動かしても、体系だった知識をベースに物事を考えられないので、ひたすら謎のエラーと格闘する不毛な時間に心が折れてしまうかと思います。
###通信

HTTP、TCP/IPなどの知識がないと、AWSのセキュリティ設定(インバウンドルールなど)で相当苦労するはずです。ここが理解できないと、デバッグ環境では動いていたのに本番環境ではファイアウォールでブロックされて動かない、などのトラブル原因が切り分けできないというのも辛いです。

筆者の経験上、通信エラーに関しては、F12の開発者ツールでエラー内容を確認してもあまり有用な情報が落ちていないことが多く、通信が阻害される原因の仮説を立てて、開発を進めていくことが非常に重要です。

勉強するなら、[マスタリングTCP/IP―入門編―(第6版)](https://www.amazon.co.jp/dp/4274224473)が知識としてよくまとまっているので、良いと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625467/bdab3c5d-181a-0d57-fc68-7eead00cc444.png)

###Linux

仕事でLinuxを使う人は少数派だと思いますが、インフラの構築を行う上ではLinuxがまだまだ主流なので、AWSでもLinuxを選択しなるべく操作には慣れておいた方が良いと思います。

勉強するなら、本よりも実際にAWS EC2のLinux AMIなどの環境を手で動かして慣れてみた後、余裕があれば知識を網羅する為に、後述するLinuCという資格試験の勉強をしてみると良いかもしれないです。

筆者も普段Windowsを使用しており、GUIに慣れきっている状態だったのでLinuxのコンソール画面に当初かなり違和感を覚えていたのですが、使用しているうちに少しずつ勘所がつかめてきた気がします。

####Linuxを動かす上で意識していたポイント

* コマンドに慣れる(特にls、cd、pwdコマンド)
 - lsは現在いるディレクトリのファイルやフォルダを一覧表示するコマンド。
 - cdはディレクトリの移動のためのコマンド。
 - pwdは自分が存在するディレクトリを確認する為のコマンド。

* 階層構造に慣れる。
 - 最初のうちはCUIに慣れないと思うので、迷ったらpwdコマンドで自分がどこにいるのか確認して進めていた。

* 環境変数に慣れる。
 - .bashrcなど、基本的な環境変数周りの知識はあった方がいい。
 
* VIMの操作に慣れる。
 - confファイル(後述)の編集にはVimを使用する為、苦手意識を持たない方が良い。

* Linuxにも種類があることを理解する。
 - 混乱するかもしれないが、Linuxにもさまざまな種類があり使えるコマンドも若干異なる。Qiitaなどの記事内容をコマンド入力してエラーが出ても、放り出さずにエラー内容を確認する。(ここが一番辛かったかもしれない)

コツとして書いてみたものの、独学で知識の偏りがあることは否めないので、[LinuC](https://linuc.org/linuc1/)という資格試験には今後挑戦してみたいと思います。

###Webサーバ(今回はNginxを使用)

Webサーバも、普段インフラ運用を行う人でなければ、設定を行うのが難しい所だと思います。

####Webサーバを動かす上で意識していたポイント
* Confファイルの変更箇所をメモしながら進めた点。
 - Nginx.confなど、Linux上でWebサーバの設定を行う機会は多い。
 - その分ネット上の参考記事も多く、却って混乱することが多かった。記事の内容を鵜呑みにせず、何を行いたいのか、その為にどこを編集したのか、振り返って後からでもわかるようにしておくことが重要だと思う。

* Linux上でWebサーバのモジュール(Confファイル等)がどこにあるのか
 - 慣れている人ならともかく、初心者はLinuxのどこに何があるのか分からず、作業の大きなボトルネックになると思うので、Confファイルの場所は常にメモに書いてわかるようにしておいた。

* 変更したらとにかく再起動
 - Webサーバに限らず、ツール系の再起動コマンドは暗記するくらい使いこなす。設定がうまく行っていないのか、再起動待ちで変更が反映されていないのか、考える時間が一番無駄だと感じた。

###その他
細かいテクニックやハマリ所は別記事にもまとめてみました。

[Vue.jsのアプリケーションをAWS上のNginxで公開する。(404エラーの罠)](https://qiita.com/kyamasan/items/05c6b2ac05db5d05a9d9)

[GolangのWebAPIをsupervisorでデーモン化して公開する。](https://qiita.com/kyamasan/items/fe0e10a2fc29dbefdc51)
Coursierで特定のmaven artifactの依存関係を確認する

Androidでの開発やJavaなどのJVM言語での開発で、あれ、このライブラリって何に依存しているんだっけ？って思うことよくありますよね？
皆さんはどのように確認しているでしょうか？
https://mvnrepository.com/ などのサイトを見たり、 `./gradlew dependencies`で確認するなどさまざまだと思います。

今日はScalaで書かれたCoursierというCLIツールが便利だったので紹介します。
https://get-coursier.io/

# 使い方
ターミナル上で `coursier resolve maven_artifact`という感じで確認できます

```
$ coursier resolve io.circe:circe-core_2.12:0.10.0
io.circe:circe-core_2.12:0.10.0:default
io.circe:circe-numbers_2.12:0.10.0:default
org.scala-lang:scala-library:2.12.6:default
org.scala-lang:scala-reflect:2.12.6:default
org.typelevel:cats-core_2.12:1.4.0:default
org.typelevel:cats-kernel_2.12:1.4.0:default
org.typelevel:cats-macros_2.12:1.4.0:default
org.typelevel:machinist_2.12:0.6.5:default
```

`-t`でツリー状にも依存関係を確認できます。

```
$ cs resolve -t io.circe::circe-generic:0.12.3
  Result:
└─ io.circe:circe-generic_2.13:0.12.3
   ├─ com.chuusai:shapeless_2.13:2.3.3
   │  └─ org.scala-lang:scala-library:2.13.0
   ├─ io.circe:circe-core_2.13:0.12.3
   │  ├─ io.circe:circe-numbers_2.13:0.12.3
   │  │  └─ org.scala-lang:scala-library:2.13.0
   │  ├─ org.scala-lang:scala-library:2.13.0
```



# インストール方法

Macだと以下のようにしてインストールできるようです。
https://get-coursier.io/docs/cli-installation

```
brew install coursier/formulas/coursier
```


# Google Maven Reposiotryにあるリポジトリを見る

Androidの開発で欠かせないGoogle Maven Reposiotryを見るには以下のようにして行います。

```
cs resolve -t  -r https://maven.google.com -r https://jcenter.bintray.com androidx.ui:ui-livedata:0.1.0-dev12|view -
└─ androidx.ui:ui-livedata:0.1.0-dev12
   ├─ androidx.compose:compose-runtime:0.1.0-dev12
   │  ├─ androidx.annotation:annotation:1.1.0
   │  ├─ org.jetbrains.kotlin:kotlin-stdlib:^[[33m1.3.70 -> 1.3.71^[[0m
   │  │  ├─ org.jetbrains:annotations:13.0
   │  │  └─ org.jetbrains.kotlin:kotlin-stdlib-common:1.3.71
   │  ├─ org.jetbrains.kotlin:kotlin-stdlib-common:^[[33m1.3.70 -> 1.3.71^[[0m
   │  ├─ org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm:0.3
   │  │  ├─ org.jetbrains.kotlin:kotlin-stdlib:^[[33m1.3.50 -> 1.3.71^[[0m
   │  │  │  ├─ org.jetbrains:annotations:13.0
   │  │  │  └─ org.jetbrains.kotlin:kotlin-stdlib-common:1.3.71
   │  │  └─ org.jetbrains.kotlin:kotlin-stdlib-common:^[[33m1.3.50 -> 1.3.71^[[0m
   │  ├─ org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6
   │  │  ├─ org.jetbrains.kotlin:kotlin-stdlib:1.3.71
   │  │  │  ├─ org.jetbrains:annotations:13.0
 
```

# 終わりに
依存関係を調べるときに手軽に調べられるので便利そうでした。
依存性の確認以外にも、まとめてjarにしてくれる機能や起動してくれる機能などがあって便利だったので、公式サイトを確認してみてください。
https://get-coursier.io/docs/overview
C# ディスプレイサイズを表示する

#やりたいこと
ディスプレイサイズを取得して表示する

```
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace myDisplay
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void button1_Click(object sender, EventArgs e)
		{
			int disp_width = Screen.PrimaryScreen.Bounds.Width;
			int disp_height = Screen.PrimaryScreen.Bounds.Height;

			txtDispWidth.Text = disp_width.ToString();
			txtDispHeight.Text = disp_height.ToString();
		}
	}
}
7年前DynabookタブにAndroidx86入れてゲーム(続き)

![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F543063%2F4c36d16e-f069-6fad-d7fd-6e567e454d70.jpeg?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&s=afb46a3d39eff27935bff95fef3e5343)

前回、「7年前のWinタブにAndroidx86を入れてゲームをする」記事を書いた。

### 7年前 Corei5 WinタブにAndroidx86入れてゲームとか
https://qiita.com/ksmndevelop/items/764307de2e0342137a47

一ヶ月程度経ってしまったが、その後のことについて追記しておく。

# ゲーム動作の様子動画
とりあえず、きらファンとプリコネをプレイした動画を上げた。

Dynabook VT712 Android x86 きらファンテスト - YouTube
[![Dynabookきらファンテスト](http://img.youtube.com/vi/LPobD3Ouj5Q/0.jpg)](http://www.youtube.com/watch?v=LPobD3Ouj5Q)

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">Dynabookタブ Androidx86 on プリコネ テスト<br>ユニオンバースト時グラフィックが出ない🤔<br>高画質にしてるからか？と疑う。。 <a href="https://t.co/44tscvMgVp">pic.twitter.com/44tscvMgVp</a></p>&mdash; ななみん＠ (@kasumin_mikan) <a href="https://twitter.com/kasumin_mikan/status/1256925753259683840?ref_src=twsrc%5Etfw">May 3, 2020</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

動画を見た通り、微妙なところである・・・

# ベンチ
Antutu (Google Playストアからは削除された)は公式サイトから入手しようとしたが、インストールできなかった。(提供不明元のアプリ許可はしているのに・・・)

GeekBenchもインストールはできたが、起動不可。

唯一、3DMarkが動いた。しかし、スクショするのを忘れたため大体のベンチを記述しておく。

### 3DMarkのベンチ
大体、1500ぐらいであった。相当下。最近のミッドレンジより酷かった。
確かに、グラフィックは負荷がかかると、相当カクカクになる。

# 最後に
7年前のCorei5は最新のミッドレンジスマホにコテンパンであることがはっきり分かった。
今のミッドレンジスマホは、「1万円でもこんなに動くのか！」という感じではある。
結局、このDynabookタブの使い道が今の所あまりない。どうするか。
熟考。
予測変換を非表示にする

##フォームの予測変換機能をオフにする
問題を解くアプリを作成しているときに、フォームに文字を打ち込むときに予測変換が出てしまい、答えが事前にわかってしまうケースがあったため調べた。
##結果
＜input＞のautocomplete属性をoffにすると予測変換が消えるみたいです。
`autocomplete: 'off'`
予測変換のことをオートコンプリートと言うと。

```ruby:form.rb
<%= text_field_tag "word#{word.id}","", {class: 'form-control',autocomplete: 'off'} %>
```
[C++]Effective C++ 第3版 1項

# About me
この物語は、**C言語からC++に進化したいエンジニア**の平凡な**考察**を淡々と描くものです。過度な期待はしないでください

#C++を複数の言語の連合と見なそう

##問題
バファリンの半分は**やさしさ**でできていますが、C++は何からできているでしょうか？

##答え
C++は、
    #include < **C言語** >
    #include < **オブジェクト指向** >
    #include < **テンプレート** >
    #include < **STL(Standard Template Library)** >

##解説
**C言語とは**
C言語である。別の物語を読むことを推奨したい。

**オブジェクト指向とは**
最初のパラダイムシフト。なんでC言語じゃダメなのか分からないあなたに読んでほしい。

この例を見てほしい。
南さんちの子供たちは、高校生・中学生・小学生のかわいい女の子だ。朝にはそれぞれ別の学校に出発する。
Cさん
　「はるかは、高校に行きなさい」
　「かなは、中学高に行きなさい」
　「ちあきは、小学校に行きなさい」
C++さん
　「みんな、学校へ行きなさい」

**テンプレート**
型の話。2つの数で大きい方を返す数を考えよう。
Cさん
型ごとにMAX関数作らなくっちゃ。
 short ShortMax(short num1, short num2){実装}
 int IntMax(int num1, int num2){実装}
 float FloatMax(float num1, float nun2){実装}
 double DoubleMax(double num1, double num2){実装}
  ・・・・
C++さん
大きい方を返したいのね。T型のMAXテンプレートが完成したわ。
template <typename T>　
T Max(T x, T y){実装}

**STL(Standard Template Library)**
恐れることはない。上で説明したテンプレートのライブラリだ。ライブラリを使いこなせば効率的にプログラミングできる。
**「すみません3個の数の和を求めたいのですが」**
Cさん
型毎に配列準備しなくっちゃ。
 int IntArray[3]
 for(i = 0; i < 3 ; i++){実装}

C++さん 
テンプレート型の可変長配列ベクターがあったっけ。範囲内の総和を求める関数もあったけけ
 std::vector<int> v(3)
 std::accumulate(v.begin(),v.end,0)

**「すみませんdouble型も使えますか？」 **
Cさん
　double型も作ります。
C++さん
　承知いたしました。5秒お待ちください。

**「すみません4個の数の和にしてもらえますか？」 **
Cさん
　ええ。それってint型もdouble型もですか
C++さん
　　承知いたしました。5秒お待ちください。
　　v.push_back()で要素追加できたよね。
PythonでNOMURAコンテスト2020を解きたかった

### はじめに
おひさしぶりです。学校の課題に追われてなかなか精進できませんでした(言い訳)
A,Bの二完でした。しかも、それぞれ1ペナずつ生やした。

### A問題
[問題](https://atcoder.jp/contests/nomura2020/tasks/nomura2020_a)

**考えたこと**
$m1>m2$のときはそのまま引き算できないので、$h1$から1取ってくる。

```python
h1, m1, h2, m2, k = map(int,input().split())

if m1 > m2:
    m2 += 60
    h2 -=1
    ans_m = m2 - m1
else:
    ans_m = m2 - m1

ans_h = h2 - h1
ans = 60 * ans_h + ans_m

print(ans-k)
```
引き算の順序を間違えて1WAした。もったいない

### B問題
[問題](https://atcoder.jp/contests/nomura2020/tasks/nomura2020_b)

**考えたこと**
~~ヒタチコンの悪夢再来~~、こういう系の問題は苦手。
全てDにするのが最適ですが、私は気付かなかったので、if文でごり押ししてます。

```python
t = list(input())
n = len(t)

if t[0] == '?':
    if n > 1:
        if t[1] == '?':
            t[0] = 'P'
        else:
            t[0] = 'D'
    else:
        t[0] = 'D'
if t[-1] == '?':
    t[-1] = 'D'
for i in range(1,n-1):
    if t[i] == '?':
        if t[i-1] == 'P':
            t[i] = 'D'
        else:
            if t[i+1] == '?' or t[i+1] == 'D':
                t[i] = 'P'
            else:
                t[i] = 'D'

ans = ''.join(t)
print(ans)
```

### まとめ
C解けたらかっこよかった。
明日のABCが不安です。ではまた、おやすみなさい。
nuxt+firebaseで匿名ログインした際にランダムでアイコンを割り当てる

# やりたいこと

- nuxt+firebaseauth+firestoreでチャット
- 匿名ログインでログインしなくてもアカウントを作る
- このアカウントにアイコンを自動で割り当てて、セッションが切れるまでそのアイコンを使えるようにすることでチャットでどのユーザーのコメントかわかるようにする

# 要件

- ユーザーがランディングしたらログイン完了する
- チャットができ、チャットで投稿したのが誰かわかるようにコメントの横にアイコンを表示する
- アイコンは永続的に表示される
- そのためユーザー情報（アイコンの情報）は永続保持

# 全体の流れ

- firebase.auth().signInAnonymouslyで匿名ログイン
- firebase.auth().onAuthStateChangedで状態を感知
    - この際に下記をfirestoreに入れる。アイコンと背景色を分けてランダムにすることでパターン数を増やす
        - icon_image_url（アイコン画像のurl）→ランダムで画像のurlを
        - icon_back_color（アイコン画像の背景色）→ランダムでcolorコードを。そのままcssに使えるようにしておく
- viewに出す

## signInAnonymouslyによるログイン

```javascript
  created() {
    firebase.auth().signInAnonymously().catch(function(error) {
      // Handle Errors here.
      let errorCode = error.code;
      let errorMessage = error.message;
      // ...
    }),
}
```

createdのタイミングで上記を発火させてログイン。

## onAuthStateChangedでログインを検知してiconの画像urlを保存

```javascript
      let photoid = Math.floor( Math.random() * 10 )
      if (photoid === 0) {
        user.photoUrl = process.env.ICON_IMAGE_00
      }else if (photoid === 1) {
        user.photoUrl = process.env.ICON_IMAGE_01
      }else if (photoid === 2) {
        user.photoUrl = process.env.ICON_IMAGE_02
      }else if (photoid === 3) {
        user.photoUrl = process.env.ICON_IMAGE_03
      }else if (photoid === 4) {
        user.photoUrl = process.env.ICON_IMAGE_04
      }else if (photoid === 5) {
        user.photoUrl = process.env.ICON_IMAGE_05
      }else if (photoid === 6) {
        user.photoUrl = process.env.ICON_IMAGE_06
      }else if (photoid === 7) {
        user.photoUrl = process.env.ICON_IMAGE_07
      }else if (photoid === 8) {
        user.photoUrl = process.env.ICON_IMAGE_08
      }else if (photoid === 9) {
        user.photoUrl = process.env.ICON_IMAGE_09
      }
```

ICON_IMAGE_09は環境変数で本番環境と開発環境で読むurlを変えている。

# つまったところ

## 画像を相対パスで出せない

匿名ログイン自体はfirebaseが便利すぎて一瞬でできたが意外にも画像を相対パスで出すところでつまった。どうしても表示できなかったのでfirestoreに置いて絶対パスで出すことにした。
Exception: The script does not have permission to perform that action. Required permissions


# :scream: エラー  

## 画像
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253014/3dd5f5a4-c115-48fa-d6d0-88073deb9bfe.png)

## Detailsをクリックしたら表示された
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253014/a49b0f1e-ce11-2264-45e6-54f0c66a699d.png)

## メッセージ
Message details
Exception: The script does not have permission to perform that action. Required permissions: (https://www.googleapis.com/auth/gmail.send || https://www.googleapis.com/auth/gmail.compose || https://www.googleapis.com/auth/gmail.modify || https://mail.google.com/ || https://www.googleapis.com/auth/gmail.addons.current.action.compose) (line 12, file "sendGmail")

# :o: 解決法
## appsscript.jsonを修正する
### 1. 既に、appsscript.jsonに"oauthScopes"が存在していれば何もしない。なければ、作成する。

```json:appsscript.json

{
  ...
  "oauthScopes": []
}
```

### 2. エラーメッセージの()内部を切り出す
今回はこれ

```:errorMessage
https://www.googleapis.com/auth/gmail.send || https://www.googleapis.com/auth/gmail.compose || https://www.googleapis.com/auth/gmail.modify || https://mail.google.com/ || https://www.googleapis.com/auth/gmail.addons.current.action.compose
```

### 3. 2を読み取る
全て、|| でつながっているので、どれかを使用すれば良いことがわかる。
今回は試しに `https://www.googleapis.com/auth/gmail.send`を使う

```:errorMessage
https://www.googleapis.com/auth/gmail.send || https://www.googleapis.com/auth/gmail.compose || https://www.googleapis.com/auth/gmail.modify || https://mail.google.com/ || https://www.googleapis.com/auth/gmail.addons.current.action.compose
```

### 4. 1で作成した"oauthScopes"の[]に追記する。

```json:appsscrips.json

{
  ...
  "oauthScopes": [
    "https://www.googleapis.com/auth/gmail.send"
  ]
}
```

メールが送信できた :cake:
GitHub Actions上でPuppeteerを動かす


GitHub ActionsでPuppeteerを動かしたいなと思い試してみたメモです。

**結果、特にそこまで気にせずに起動してくれました。**

## 準備

割と普通ですね。

```
yarn add puppeteer
```

## プログラム

[GitHubのPuppeteer Headful](https://github.com/marketplace/actions/puppeteer-headful)のページを見ると`process.env.PUPPETEER_EXEC_PATH`でバイナリを指定しろみたいな記載があるけど、特に指定せずに普通インストールして使えました。

```app.js
const puppeteer = require('puppeteer');

(async () => {
    const URL = `https://twitter.com/n0bisuke`;

    const browser = await puppeteer.launch({});
    const page = await browser.newPage();
    await page.goto(URL); //URLにアクセス
    // Get the "viewport" of the page, as reported by the page.
    const dimensions = await page.evaluate(() => {
        return {
            width: document.documentElement.clientWidth,
            height: document.documentElement.clientHeight,
            title: document.title,
            deviceScaleFactor: window.devicePixelRatio
        };
    });

    console.log('Dimensions:', dimensions);
    console.log('タイトル:', dimensions.title); 

    await browser.close();
})();
```

ちなみにローカルでもこのままnode app.jsで使えます。

## ymlの記述

`.github/workflows/run-puppeteer.yml`を作成

```run-puppeteer.yml
name: RUN puppeteer

on:
  push:
    branches: [ master ]

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [14.x]

    # 以下が実際のステップ
    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js 14.x
      uses: actions/setup-node@v1
      with:
        node-version: '14.x'
    - name: install command
      run: yarn install

    - name: RUN app.js
      run: node app.js
```

## デプロイして確認

ちゃんと動いてるっぽい

> ![](https://i.gyazo.com/12e70ea1047bb77b1670dd2d6d682de7.png)

## 所感

Vercelなどserverless環境で動かすときとは変更あったけど、今回は特に無さそうですね。

> 参考: [Vercel上でPuppeteerを動かす](https://qiita.com/n0bisuke/items/d3b45cb33351e68d9c86)

ファイル書き込みがどうなるかとかは試せてないのでその辺気になりますね。

全体コードはこちらにまとめておきます。

> https://github.com/n0bisuke/github-actions-puppeteer
PowerShell IEで自動ログイン

#やりたいこと
毎日のようにアクセスするページにＩＤとＰＷを毎回入れるのが面倒なので、
簡単に自動ログインしたい

#前提
ホームページはHTMLのものが対象。
Flashのページはできない。（というかやり方がわからない）

#事前準備
ホームページのソースコードを表示して以下の項目を調べておく
1．ログインＩＤ入力BOXのID属性
2．ＰＷ入力BOXのID属性
3．ログインボタンのID属性（※）

ログインボタンにIDが付与されていない場合がある。
その場合は、name属性などを対象にする

#コード
```login.ps1

##=======================================================
## パラメータ設定
##=======================================================
$user_id = "user"
$user_pw = "pw"
$url = "http://test.aspx"

##=======================================================
##事前設定
##=======================================================
#IE
$ie = New-Object -ComObject InternetExplorer.Application

##=======================================================
##スクリプト本体
##=======================================================
#--------------------------------
# IEを起動する
#--------------------------------
# IE起動
$ie.Visible = $true

# ウィンドウハンドル
$hwnd = $ie.HWND

#URLへアクセス（キャッシュ無効）
$ie.Navigate($url,4)

#待ち
While($ie.Busy){start-sleep -milliseconds 100}
$doc = $ie.document

#--------------------------------
# ID PW　入力
#--------------------------------
# ID入力(idがある場合、getElementByIDで指定)
$dom_userID=$doc.getElementByID("UserId")
$dom_userID.value=$user_id

# PW入力(idがある場合、getElementByIDで指定)
$dom_userPW=$doc.getElementByID("Password")
$dom_userPW.value=$user_pw

# ログインボタン(idがある場合、getElementByIDで指定)
$btn=$doc.getElementById("LoginButton")
$btn.click()


```

#実行方法
PowerShellの使い方はググれば出てくるが、.ps1ファイルはダブルクリックで一発実行ができない。
セキュリティポリシーがあるようでおまじないが必要である。
簡単に実行する方法はいくつかあるが以下がおすすめ。

同じフォルダにps1とbatを用意する
ファイル名は２つとも同じにすること（理由は後で述べます）
login.ps1
login.bat

bat（バッチファイル）は以下のように記載

```login.bat
powershell -ExecutionPolicy RemoteSigned -File .\%~n0.ps1
```

#バッチファイル解説
##-ExecutionPolicy RemoteSigned
ローカルのps1の実行を許可
##%~n0
バッチファイルのファイル名を取得する。上記の場合は、"login"

バッチファイル自身の名前のps1ファイルを管理者権限で実行するバッチになります。
別のページにログインするスクリプトを作る場合はバッチファイルのファイル名だけ変えれば流用できます。
【Kotlin】面積当たりの容量が大きいpngを生成したかった【Java】

# やりたかったこと
とある案件で大量の重めの`png`画像サンプルが必要になりました。
一方、単純に四角を`fill`するような形で画像を生成した場合、圧縮されてしまって高々数KB程度になってしまうなど、容量が確保できませんでした。
必要な画像のフォーマットも決まっていたため、単純に面積を増やして容量を稼ぐことも難しかったです。

# 方針
圧縮というものは大概以下2点に当てはまる場合強く作用します。

- 同じパターンが連続する
- 同じ色が連続する

よって、「ランダムな色のランダムな線を沢山引けば圧縮しにくいだろう」というノリでやりました。

目標は1940 x 500のサイズで1枚2MBです。
それを達成していれば一旦構わないため、更なる大容量化や処理時間に関しては気にせずにやっていきます。

# 実装
`${プロジェクトルート}/build/generated`ディレクトリに2000枚の画像を生成するサンプルです。
`lines`が100000有れば安定して2MBを超えてくれました。

`parallelStream()`しているのは「ちょっとは早くなるんじゃね」程度のノリで、実際に早くなってるのかは確認していません。

```kotlin
import java.awt.Color
import java.awt.Graphics2D
import java.awt.image.BufferedImage
import java.io.File
import javax.imageio.ImageIO
import kotlin.random.Random

const val width = 1940
const val height = 500
const val lines = 100000 // ライン数
const val count = 2000

fun main() {
    val generateTarget = System.getProperty("user.dir") + "/build/generated/"

    List(count) { it }.parallelStream().forEach { index ->
        val img = BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR)
        (img.graphics as Graphics2D).apply {
            repeat(lines) {
                // 色は少しでも大容量化することを狙って透過度も指定
                this.color = Random.nextBytes(4).let {
                    Color(it[0] + 128, it[1] + 128, it[2] + 128, it[3] + 128)
                }
                this.drawLine(Random.nextInt(width), Random.nextInt(height), Random.nextInt(width), Random.nextInt(height))
            }
            dispose()
        }
        ImageIO.write(img, "png", File("$generateTarget${index}.png"))
    }
}
```

## 実行結果
2000枚で4.81GB、平均2.4MBでした。
負荷は高く実行時間はそれなりにかかったので、暇なときに回しておく位がちょうどいいと思います。

こんな感じの画像が生成されます。
![0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280230/d82d9d8a-090b-b739-c961-637feecefb80.png)
Nuxt.jsのAuth Module（@nuxtjs/auth）を使って手軽にGoogle Login機能を実装する

Nuxt.jsのAuth Moduleを使ってGoogle Loginを実装してみましたので、そちらの紹介になります。

以下のような手順で実装しました。

1. [@nuxtjs/auth](https://auth.nuxtjs.org/) をインストールして設定をする
2. GCPのコンソールから本アプリの設定を作成する
3. pageを実装する

# Auth Moduleのインストールと設定

```
% yarn add @nuxtjs/auth
```

```client/nuxt.config.js
  modules: [
    '@nuxtjs/auth' // ここの行を追加します。
  ],
  // routerを追加
  router: {
    // See https://auth.nuxtjs.org/guide/middleware.html
    middleware: ['auth']
  },
  // authを追加
  auth: {
    redirect: {
      login: '/login',
      logout: '/login',
      callback: '/oauth2_callback',
      home: '/'
    },
    strategies: {
      app: {
        _scheme: 'oauth2',
        authorization_endpoint: 'https://accounts.google.com/o/oauth2/auth',
        userinfo_endpoint: `https://www.googleapis.com/oauth2/v3/userinfo`,
        scope: [
          'email',
          'profile',
          'openid',
          'https://www.googleapis.com/auth/drive.metadata.readonly'
        ],
        access_type: undefined,
        access_token_endpoint: undefined,
        response_type: 'token',
        token_type: 'Bearer',
        client_id: process.env.GOOGLE_CLIENT_ID, // .envで定義しておく
        token_key: 'access_token'
      }
    }
  },
```

# GCPでアプリを作成する

1. Google Cloud Platformにログインしてプロジェクトを作成します（既存のプロジェクトでもOKです）
2. APIとサービス > ライブラリからGoogle Drive APIを有効化します
3. APIとサービス > OAuth同意画面から同意画面を作成します。
4. APIとサービス > 認証情報からアプリケーションを作成します。

こちらで、.envに定義するクライアントIDが作成されます

# ログイン関連のpageを実装する

以下を実装していきます。

- pages/login.vue
- pages/oauth2_callback.vue (callbackは割愛します）

```pages/login.vue
<template>
  <v-row align="center" justify="center">
    <v-col cols="12" sm="8" md="6" lg="4">
      <v-card class="elevation-12">
        <v-toolbar color="primary" flat>
          <v-toolbar-title>App Name</v-toolbar-title>
          <v-spacer />
        </v-toolbar>
        <v-card-actions>
          <v-spacer></v-spacer>
          <v-btn
            color="secondary"
            large
            class="mr-2 mb-2"
            @click.stop="authenticate"
            >Login with Google</v-btn
          >
        </v-card-actions>
      </v-card>
    </v-col>
  </v-row>
</template>

<script>
export default {
  auth: false,
  layout: 'centered',
  methods: {
    authenticate() {
      this.$auth.loginWith('app')
    }
  }
}
</script>
```

`$auth.loginWith('app')` を呼び出すと、Auth Moduleが良い感じにGoogleログインを処理してくれます。


より詳細な実装については、[こちらの記事](https://kumano-te.com/series/develop-gdrive-manager-with-nuxtjs-and-fastapi/nuxtjs-vuetify-google-oauth2-login)もご覧ください。

以上になります。
【Mac】つい忘れがちな機能

Macで定期的にググってしまう、つい忘れがちな機能をまとめます。

####フォルダのパス名を表示

1. フォルダの上で右クリック
2. optionキーを押すと、「コピー」が「"フォルダ名"のパス名をコピー」に変わります。

####バックスラッシュの打ち方
option + 「¥」

####文章の先頭・最後に移動

![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626568/5e9c2271-dbb7-2fbd-b896-600033b33186.gif)

先頭：control + a
最後：control + e

####隠しファイルの表示
lsコマンド（list）の後に-aオプションをつけて実行

```
ls -a
```
MacBookの移行とベンチマーク

タイトルは釣りです…と言えるくらい情報量が少ないですが、I/O速度にかなり差が出てしまったので記録しておくことにしました。他にも測定したら書き足すかもしれません。

## MacBook Air

![Screen Shot 2020-05-30 at 22.18.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50780/b934eb92-4b1e-47e1-8493-cfa6d5e4a8d3.png)

```bash
% ruby -ve 't = Time.now; i=0;while i<100_000_000;i+=1;end; puts "#{ Time.now - t } sec"'
ruby 2.6.3p62 (2019-04-16 revision 67580) [universal.x86_64-darwin19]
1.538574 sec

% dd if=/dev/zero of=tmpfile bs=1m count=1000
1000+0 records in
1000+0 records out
1048576000 bytes transferred in 2.771232 secs (378379018 bytes/sec)
```

## MacBook Pro 13-inch

<img width="698" alt="Screen Shot 2020-05-30 at 22.21.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50780/c8f214ad-64d1-3d14-22db-540be3611271.png">

```bash
% ruby -ve 't = Time.now; i=0;while i<100_000_000;i+=1;end; puts "#{ Time.now - t } sec"'
ruby 2.6.3p62 (2019-04-16 revision 67580) [universal.x86_64-darwin19]
1.572779 sec

% dd if=/dev/zero of=tmpfile bs=1m count=1000
1000+0 records in
1000+0 records out
1048576000 bytes transferred in 0.414705 secs (2528487736 bytes/sec)
```

## 移行作業
Macの移行ツールは使わず、アプリは全て新たにインストールし直して、rsyncコマンドで必要なファイルだけ転送しています。wifi経由のrsyncがやたらと遅い印象があったため、転送速度を検証しようとしたのが発端でした。LANケーブルで直結したところ5.5倍速になりましたが、それでもちょっと物足りない感じ。何が足を引っ張っているのでしょうか？（まあでも高々100G弱のデータだったので、これで済ませましたが）

```bash
% scp 10.250.85.144:tmpfile ./Downloads/
tmpfile    21%  212MB   2.0MB/s   06:33 ETA
```

```bash 
% scp 169.254.3.115:tmpfile ./Downloads/
tmpfile    6%   67MB  11.2MB/s   01:23 ETA
```
MyCollection

```C#
using System.Collections.Generic;
using System.Linq;

public class MyCollection<T>
{
    private readonly List<T> items = new List<T>();
    public IReadOnlyList<T> All => items;

    public void Add(T item)
    {
        items.Add(item);
    }

    public void Remove(T item)
    {
        items.Remove(item);
    }

    public T Pop()
    {
        var item = items.Last();
        Remove(item);
        return item;
    }

    public void Push(T item)
    {
        items.Add(item);
    }

    public T Shift()
    {
        var item = items.First();
        Remove(item);
        return item;
    }

    public void Unshift(T item)
    {
        items.Insert(0, item);
    }

    public void Insert(int index, T item)
    {
        items.Insert(index, item);
    }
}
```