OmniAICreator/Qiita-1.07M huggingface dataset:
ひとりふりかえりを楽しむ

この記事は「[ふりかえり Advent Calendar 2021](https://adventar.org/calendars/6327)」の20日目の記事です。

こんにちは。えすです。
普段はいわゆるSESとかいう感じで、客先のどこぞに入ってペチペチやっています。
アドベントカレンダー初参加で、錚々たるメンバーが名を連ねるカレンダーにポチッと勢いでやってみました。拙いながらにアウトプット頑張ります。
どうぞよろしくお願いいたします。

#私の普段のふりかえり
今現在、私自身はチームのふりかえりを促すというようなことはやっていません。
ここ1〜2年は、まずは自分のふりかえり習慣を確立させようぜ、というところに重きを置いているというのもありますが、何よりそういう立場や状況にならないというのが大きいです。

上司に「ふりかえり、定期的にやりんせん？」と、口説いても、落とせたあたりでタイムアウトー!!Next GEMBA へどうぞ〜となるような感じです。

タイムアウトにならないように、信用貯金を爆速で積み立てる方法とか、ちょっと「ふりかえりやっても、良いかも？？」→即「これ良いいねえ」に変えられるように、自分の準備はしたいなーと。

そういう感じで、ゆるゆるコソコソと日々ひとりふりかえりをやっています。

#改めて、今年のふりかえり
では、ここから自分自身のふりかえりを書き出していきたいと思います。

## 手法について少しだけ。
手法ですが、YWT的な何かで書き出していきます。

余談ですが、テキストで書き連ねるとなると、YWT便利だと感じています。
大きく図が書ける状況だったり、付箋があったり、湯船に浸かっているなどで、どういう手法が便利かは変わってきますが。
（決して、個人のふりかえりをYWTでやれという意味ではないので、誤解なきよう・・・）

プライベートをより楽しむためのふりかえり、はいスタート。

## Y：やったこと（今年）。
やったこと、兼、始めたことですが

1. フィットボクシング2
1. 転職
1. 証券口座開設・ふるさと納税

フィットボクシング2は、
リモートワークが増えて運動時間が減ったという課題に対するTugiyarukotoでした。
→体重増えた。疲れやすくなった。一日の睡眠時間が安定しなくなってきた
→何か手っ取り早く運動する方法を取り入れてみると良いのでは？
という感じ。

転職は、この先どうしようかという時、たまたまタイミングよくお声がけ頂いたところに転職した、という感じです。

証券口座開設は、資産形成に興味ありつつも放置していたので、昨年終わりのTugiyarukotoで、在宅時間が増えた時にとりあえず作る、と決めていました。ふるさと納税も同じく興味ありつつ先送りだったので、やって見てもいいかな、というところでした。

## W：わかったこと（今年）
わかったことに限らずですが、ガッサリと思いつくままに書いてみます。具体的な事は若干ぼかしています。
「わかったこと」って見出しじゃないものも混じってますが、キットキノセイデス

- フィットボクシング2楽しい
- 確実に褒められる安定感ありがたい
- 運動しても、歩き回る行為は別に時間を作った方がいいかも？
- 日々のスタンプ「連続〇〇日」効果すごい。続けたくなる。
- 苦手なパンチはやらなくてもいい。そのうちやりたくなる。
- 人間関係は、自分の努力ではどうしようもないところが相当大きい
- あっさり転職は、割とアリ（まあ、過去にすでに何度か転職してますが）
- 有難い上司に巡り会うありがたさ。上司に感謝
- 有難い先輩に巡り会うありがたさ。先輩に感謝
- 有難い後輩に巡り会うありがたさ。後輩に感謝
- 有難いPMに巡り会うありがたさ。PMに感謝
- ファンドの商品は1円から買えるっぽい。便利。
- 個別株の変動、初めは割と落ち着かないままやたらと見てしまう
- 個別株の変動、2ヶ月くらいでほんの少し落ち着いて見られるようになってきた・・・かも？
- ポイント投資ありがたい。ハードル下がるし、落ち着いて眺めてられる
- つみたてNISAの区切りは12月（年の途中から積み立てNISAを始めた）
- つみたてNISA、増額投資というやつが1年めはできるとのこと
- ふるさと納税の返礼品で食べたお肉、おいしかった。「返礼」ってことだけど、こちらこそありがとうございます。
- 地元の振興につながるといいなぁ・・・。
- ふるさと納税、確定申告しないなら「ワンストップ特例制度」というのが便利そう

## T：次やること（来年）
残り10日くらいでフライングしてやることもあるかもです。

- 継続してフィットボクシング。やる量が日々大きくずれるので、振れ幅を安定させたい（安定した時間確保も）
- 現場でのふりかえり。「ふりかえり」として時間を取るのは無理でも、まずはこちらから感謝を自然に口にできる場を作る方向で。
- 証券口座の数字をなるべく毎日みる。数字の上下に慣れて慌てないために。

ふるさと納税は来年もやるだろうけど、また同じお肉食べるような気がしています。

来年のTugiyarukoto数しては、3つもあれば多分お腹いっぱい・・・・。

# おわりに
ふりかえり終わった今この時点の気分は
**｡ﾟ+.(´∀｀○)ﾟ+.ﾟ。**
こんな（↑）感じです。
（※ふりかえりの最後に、顔文字で気分を残すの好きなのです）

個人的に、ひとりふりかえりの成否は、
「明るい気持ちで終われたなら、うまくふりかえりできた」
と大雑把な判断でやっています。
こういう気持ちの積み重ねが、他人と共におこなうふりかえりの資源になる・・・はず。

最後に、プライベートといいつつ、プライベートっぽくないことも混じっているのはご愛嬌ということで何卒・・・（汗
S3+CloudFront Access Deinedの解消

S3にデプロイしたサイトにアクセスした際に、トップページ以外でリロード
または直接アクセスするとAccess Deniedとなってしまう際の解消法
CloudFrontのエラーページの設定で 403/404等該当のエラー時にリダイレクトするように設定をする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1216302/44bcc0e4-66ed-87b7-7c6a-77622c5d6292.png)

上記で解消する場合は、指定したパスが存在しないページを指しているためです。
なので存在するページにリダイレクトしましょうとのこと。

上記で解消しない場合は、S3のポリシーや公開設定の可能性あり。
【PHP8.1】リリースページが日本語訳されてなかったので深い悲しみに包まれた

[PHP8.1のリリースページ](https://www.php.net/releases/8.1/)がありますね。

右上のChange languageに日本語がありませんね。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/cb14f5de-464b-4778-b09e-463eeb046060.png)

深い悲しみに包まれたので[増やした](https://www.php.net/releases/8.1/ja.php)。

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/372bbc11-6e75-8d7f-7bee-37bdd439b93a.png)

# fork

リリースページの最下段、`View Source`ってところから[ドキュメントのソース](https://github.com/php/web-php)に進めます。
そこで右上の`Fork`ボタンを押せば、[自分のスペースにforkされます](https://github.com/NurseAngel/web-php)。

# branch

作業用にブランチを切ります。

左上の`master`からプルダウンを開いて`japanese-translation-of-release-page-81`と入力、`Create branch`する。
プルリクメッセージとかの方が重要なので、名前はあんまり気にしなくていいと思います。

# Add Japanese translation

今回はローカルで作業するほどでもない内容だったので、GitHub画面でおもむろに`.`を押します。
すると[オンラインエディタが起動](https://www.itmedia.co.jp/news/articles/2108/12/news145.html)します。

あとは`releases/8.1/languages/en.php`が本体なので、`ja.php`にコピペして中身を和訳するだけです。
それ以外にメニューとかに出す用の変更も必要になりますが、そのへんは[過去](https://github.com/php/web-php/pull/475)[の](https://github.com/php/web-php/pull/473)[プル](https://github.com/php/web-php/pull/471)[リク](https://github.com/php/web-php/pull/465)をコピペしました。

最後に[commit](https://github.com/php/web-php/commit/0fbd71c0221b5c09e89b07550ad77d09c7a5b003)して終了です。


# pull request

深く考えずともGitHubがよしなにやってくれるので[適当にプルリク出します](https://github.com/php/web-php/pull/480)。
適当といっても、何をやったかのメッセージだけはきちんと書きましょう。

```text
Add Japanese translation of PHP 8.1 release page.
```

…of？


# merge

プルリクから4分で[マージされました](https://github.com/php/web-php/pull/480#event-5784178928)。

はや！！！

# release

プルリクから10分後には既に[リリースされていました](https://www.php.net/releases/8.1/ja.php)。

クッソはや！！！


# 感想

いくらドキュメントとはいえ、リリースまで早すぎてびっくりですよ。
訳が適切かとか、おそらく一切確認してないですよね。
Collaboratorに日本語を解する人はいないでしょうから素通しするしかないのでしょうけど、これもし私がデタラメな中身を送ってたらどうなってたんでしょうか。
せめて翻訳に突っ込んでざっと見るくらいはしてもよいのでは。

ってここまで書いておいて実は日本語全然読めるとかだったらごめんなさい。

そんなわけで、単に日本語訳するだけでもOSSに貢献できるのでみんなやりましょう。
あと[金も出す](https://qiita.com/rana_kualu/items/eaf97694f25a62f93a7e#open-collective)ともっといいぞ。



しかしプルリクした後で、ちょっと訳が硬いというか気に入らないところとかちらほら出てきたんだけど、そんな細かいことでいちいちプルリク出すのはどうなんだろうと躊躇っている。
応用情報技術者試験勉強法

令和3年秋期試験で合格しましたので記事に残そうと思いました。
この手の資格試験に資格の本を読んでひたすら暗記する…という形式をとらず、
体系的に学びたい、という方向けであり、効率的に短期間で合格したい！という方向けにはなりません。（一応短期決戦向けも書きましたが）
かわりに、やり切れば試験受験の際に試験のためだけの勉強はあまりしなくてもよくなるかと思います。
もちろん基本情報もカバーしてます。
私の場合、基本も応用も試験直前に後述の過去問道場をやるくらいで済みました。

## よくいわれること
**資格なんて取らなくていい**
と言われるのはその通りで、資格自体が役に立つことはほぼありません。
合格してもあまりうまみのない試験です。[^1]

基本情報や応用情報は別に持っていなくてもいいけれど、
もしもこの業界で生きていくのならば、そのレベルの知識はないよりあった方が良いのです。
でも、これまで情報工学の勉強なんてしたことがない、という方には学び方すらよくわからないのではないかと思います。

私がそうだったのです。
そのため、資格うんぬんより先に書籍で学び、
今なら取れる気がしたので試験を受けるうまみがなくとも腕試しして達成感を得よう、ということで今回合格できました。
よかった！

資格取得できるレベルに知識を身につけるための導とになれば…という記事です。

## 短期決戦で臨む方へ
短期間で受かりたい人向けではないと書きましたが、
私は怠惰で可能なら楽をして受かりたい気持ちが大変わかるので、一応載せておきます。
とにかく[応用情報技術者試験ドットコム](https://www.ap-siken.com/)で過去問道場を周回しましょう。
知識ゼロだったとしても暗記が得意であれば何とかなると思います。
解説もあり、わからなくても掲示板で質問できるため最悪参考書を買わなくても。
午後は午前の過去問で知識を得たうえで長文読解ができれば合格点には乗ると思います。
ただ、その状態で臨むと基礎知識が足りないと思うので午後の分野はあらかじめ選んだほうがいいかと思います。[^2]

## 知識を得るため本を読もう
本や記事よりも間違いなく信頼すべきは[公式シラバス](https://www.jitec.ipa.go.jp/1_04hanni_sukiru/_index_hanni_skill.html#syllabus)です。

ですが、これからこの知識を身に着けたいという方が、これを見て参考書を選ぶのは容易ではないと思います。
そこで、前回私の書いた[記事](https://qiita.com/4door/items/935e91a420668a189db0)です。
その他にカテゴライズした本は基本的に試験に関係ないですが、[プログラムはなぜ動くのか](https://qiita.com/4door/items/935e91a420668a189db0#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AF%E3%81%AA%E3%81%9C%E5%8B%95%E3%81%8F%E3%81%AE%E3%81%8B)はぜひ読むべきです。

また、余裕があれば試験の参考書を読むのもいいと思います。
こまごましたものがカバーしきれていないためです。
文字コードなども、シラバスに挙げられていることですし関連書籍をブックリスト入れようかとも思ったのですが、
そこまで専門的に知っている必要があるか…？と思ったため省いているのです。

とはいえ、そのような取りこぼした知識たちは先に紹介した過去問道場の解説で十分学ぶことができるはずなので、
買うほどでもないとも思います。

これだけ読んでいると、いつの間にか過去問道場を試しにやってみると合格点前後くらいとれるようになってきているのではないでしょうか。
その上、きっと本の探し方もわかってきたのでは…？！

もし、学んだうえで腕試ししたい！と思ったときに、過去問道場をいくらかやれば仕上がるかと思います。

## 資格試験を受けるうえで気を付けるべきこと
試験を受けるにあたって気を付けること。
資格試験を受けなれている方なら当たり前だと思うのですが、私はうっかりしていたので記載します。

1.試験時間が長いということ

当たり前のことなのですが試験はとにかく長いです。
応用情報に関しては、以下の通りです。

|         |        午前        |      午後    |
|:---------|:-------------------:|:------------:|
| 試験時間 | 9:30～12:00(150分) |13:00～15:30(150分) |

普段仕事をしていても、150分ピリピリした環境で黙って集中し続けることなどなかなかないのではないでしょうか。
私はないのでかなり苦痛でした。
試験を受ける前に模試を時間通りにやって時間になれることは人によっては必要そうです。
一時間経過すれば提出することで途中退室ができます。
私は集中しきれずに出てしまいましたが、見直しする体力はつけておくべきですね…。

2.会場によっては時計・上履きが必要であること

基本情報を受けたときに会場が高校で室内履きが必要になり、
応用情報では会議室が会場で時計が必要になったにもかかわらずどちらも持ち物を見落としわすれました…。
よく読みましょう。
時計を忘れた人はあまり見ませんでしたが室内履きを忘れた人はかなり見かけました。


[^1]: 会社によっては昇格要件になどなっていることもありますが、資格自体が役に立つことはほぼないと思うので世間的には、と濁します
[^2]: 恐ろしいことに私は何問の中から選ぶかなど知らずに受けたので確認しておくと驚かずに済みます。
2年目に入ったエンジニアが大切にしているキーワード3つ

## はじめに

本記事は [with Advent Calendar 2021](https://qiita.com/advent-calendar/2021/with) 21日目の記事です。

こんにちは [with](https://with.is/welcome) でAndroid エンジニアをしている石田です。今年は僕がAndroidエンジニアになって丸1年が経ち、エンジニアとしての2年目がスタートした年でした。そこで今回は3つのキーワードを通して僕が今仕事をする上で大切にしていることをシェアしたいと思います。

タイトルに「エンジニア」が入っていますが、エンジニアに限定される話ではないのでどなたでも参考になれば幸いです。

## Lazy

![lazy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56635/b34556fd-a39c-5410-2109-bcf28fae4918.png)

### 【完璧を追求しない】

完璧を求めていたら、いつまで経っても仕事が終わらずプライベートの時間が削られます。人は **ディティールよりもシルエット** を見ているもの。細かいところはざっくりで。

### 【1人でやらない】

周りの優秀な仕事仲間をとことん頼りましょう。利用可能なリソースは使わないのはもったいないです。 **シングルコアとマルチコア、どちらが優れたパフォーマンスを発揮するか** は言うまでもないでしょう。

### 【環境を変えていい】

僕は1年目にして転職を経験しました。僕のような若手(≒新卒)は、環境を変えたい(≒転職) と思ってもなかなか踏み切れないものです。しかしながら、 **やる気のない状態で同じ環境に留まることの方が周りの人に迷惑をかける** と考えることもできます。どうしても上手くいかなければ元の環境に戻ればいいだけのこと。やり直しが利くのなら考えすぎるよりもまずトライしてみては。

## Split in two

![split_in_two.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56635/c4b2f82c-a73d-2976-95e8-b5fe985f19e8.png)

業務時間を2つに区切って **8割くらいを今すべきこと、2割くらいを未来のためにすべきこと** のために使います。2割の時間の使いみちは、最新の技術トピックについて調べたり、何か実験的なことをしてみたり、自分の職種以外のことをしてみたり... などなど自由に好きなことをやってよしです。

極端に言えば、明日の仕事に向けて休憩をとったり散歩したりするのに使うもよしです。この2割の時間的余裕が精神的な余裕にも繋がるはずです。

## Note
![note.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56635/a1e63638-5f9f-f15b-4f91-3861ce955333.png)

素晴らしいアイデアからちょっとした悩みまで、頭の中に浮かんだことを何でもノートに書き綴ります。**文字に起こすことで頭の中が整理されるだけでなく、記憶する必要もなくなる** ので脳みそに余白を作ることができます。ノートアプリは **[Notion](https://www.notion.so/ja-jp)** がおすすめ。整理しやすく、動作も軽快ですぐに書き始められます。
pecoを使って少しでも仕事を早くする

# はじめに

この記事は [Ateam Lifestyle Inc. Advent Calendar 2021](https://qiita.com/advent-calendar/2021/ateam-lifestyle) 21日目はエイチームライフスタイル @otama がお送りいたします｡

普段`Ruby on Rails`や`docker`, `yarn`等を利用したり、最近はdockerが進み減っては来ていますがメンテナンスや構成変更等でサーバにsshログインしたりCLI上での操作をすることがあります。様々な技術スタックやサーバに触れていくと「あれ、あのコマンドどうだったっけ？オプションどうやって書くんだっけ？」「あのサーバー名前どうだったっけ？」ということがしばしばありました。。。

調べればすぐに解消はするんですが毎回調べていると時間がもったいないですよね(覚えなさいw)。コマンド一つとっても日々の積み重ねでとんでもなく大きな時間になるのではないでしょうか。
今回ご紹介するものは数年前に隣で開発していた同僚の画面を見ながら教えてもらい便利さに心を打たれ使い続けているので紹介していきたいと思います。
とはいえ、CLIでの操作は本番環境のサーバーオペレーション時に焦らないようにするため、個人の環境でもゴリゴリのカスタマイズはしておらずショートカットやエイリアス等の設定は最小限にとどめています。
中には見た目をカラフルにしたり派手にしたりしてモチベーション上げたりしている方も多いかと思いますが今回は見た目というより効率化に少しでもつながるお話です｡
(派手派手な見た目に憧れはありますw)

## pecoとは

https://github.com/peco/peco

> Simplistic interactive filtering tool

シンプルなインタラクティブフィルタリングツール､対話しながらフィルタリングしていくよってツールです｡
この記事では私が使っているものを2つ紹介しようと思います。

### 環境

- OS: macOS Big Sur
- Homebrew 3.3.8
- peco version v0.5.10 (built with go1.16.4)

### インストール方法

- 使用端末がMacのためMacのみ紹介 (2021年12月現在)
- brew入っていれば以下コマンドでインストール
    - `brew install peco`
- これでpecoが使えるようになっているはず!
![text.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46384/83e28f23-777a-84b2-52f7-fa7dd67cf3bc.gif)

## 1.コマンド履歴

- コマンドのヒストリーから検索してバッファに出力
![history.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46384/c9bff98f-596d-37b0-e0d8-e85627194a45.gif)


### 設定

- 以下を`.zshrc`の適当なところに貼り付け
- ターミナル開き直すか再読み込みする `source ~/.zshrc`

```config:.zshrc
# peco history
function peco-select-history() {
    local tac
    if which tac > /dev/null; then
        tac="tac"
    else
        tac="tail -r"
    fi
    BUFFER=$(\history -n 1 | \
        eval $tac | \
        peco --query "$LBUFFER")
    CURSOR=$#BUFFER
    zle clear-screen
}
zle -N peco-select-history
# Ctrl + r に割当
bindkey '^r' peco-select-history
```

### 使い方

- `Ctrl + r`で履歴を表示して検索したい文字を入力
- 選択したあとバッファに出力されます
- 下で紹介するsshのものはすぐに実行されるがこちらはされないので選択後に編集できるようになっています

## 2. サーバーへのssh

- `.ssh/config`からHostをリスト化してそのままsshログインしちゃう
![ssh.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46384/2b2e84dd-d833-f616-3e93-4e2efb19833d.gif)

### 設定

- 以下を`.zshrc`の適当なところに貼り付け
- ターミナル開き直すか再読み込みする `source ~/.zshrc`

```conf:.zshrc
# peco ssh
function peco-ssh () {
  local selected_host=$(awk '
  tolower($1)=="host" {
    for (i=2; i<=NF; i++) {
      if ($i !~ "[*?]") {
        print $i
      }
    }
  }
  ' ~/.ssh/config | sort | peco --query "$LBUFFER")
  if [ -n "$selected_host" ]; then
    # ここでsshのオプションを指定できる
    BUFFER="ssh ${selected_host}"
    zle accept-line
  fi
  zle clear-screen
}
zle -N peco-ssh
# Ctrl + \ に割当
bindkey '^\' peco-ssh
```

### 使い方

- ターミナル上で`Ctrl + \`を押下したあと接続したいhostを選択するだけ
    - このときうろ覚えでも最後の一つまで絞り込まなくてもOK
    - webサーバーであればとりあえず`web`を入力するだけで絞り込みができるので上下キーもしくは`Ctrl +n`or`Ctrl + p`で選んで接続できる
- 決定後はそのままsshされる

## まとめ

- まわりの仕事早い人のオペレーションを観察してインプットするの大事！
- これらを活用すると複数のワードに引っ掛けて検索できるので日々の業務がちょっと便利になるのでは!?
- 活用方法は無限にあるので探してみよう!
- こんな使い方してるよーというのがありましたらコメント残していただけると嬉しいです:santa_tone1:
- 明日は @mistolteen さんです。お楽しみに!
調べる技術　調べる時に自分が心がけている5つのこと

この記事は [**セゾン情報システムズ Advent Calendar 2021**](https://qiita.com/advent-calendar/2021/sisco) 21日目の記事です。

[はじめに](#はじめに)
[自分のやりたいことを細分化する](#自分のやりたいことを細分化する)
[Googleの完全一致検索を使う](#Googleの完全一致検索を使う)
[とりあえずドットをつけてみる](#とりあえずドットをつけてみる)
[とりあえず英語で検索してみる](#とりあえず英語で検索してみる)
[デベロッパーツール、WireShark、IDEのデバッグ実行などのツールを使ってみる](#デベロッパーツール、WireShark、IDEのデバッグ実行などのツールを使ってみる)
[まとめ](#まとめ)

# はじめに

自分のITエンジニアとしてのキャリアもいよいよ二年目が終わりそうになってきていますが、ありがたいことにすごいと本気で思えるエンジニアの方たちと働く機会に恵まれた日々を過ごせております。
そのような方たちを見ているとその人が何もかもを知っているように自分には見えたことが幾度かありました。

ただ実際にそういう方たちと働いてみて知識量もすごいですが調べることに関してとてもうまく、その調べる力のうまさゆえにその人が何もかも知っていると感じてしまう部分もあるのではないかと感じました。

現に自分が一緒に働いている方で初めて触れる技術（と本人は少なくとも言っている）もすぐにキャッチアップして実務で使いこなしているような方もいます。

このようなことを通じて技術の知識をつけることもそうですが、調べる技術を高めることも大事だと感じましたのでここに自分がエンジニアリングに関わっている際に何かを調べる時に考えたり試みていることをまとめていきます。

# 自分のやりたいことを細分化する

[こちらの記事](https://qiita.com/brightcat/items/d194c496ad58ebe9f87d)にも書きましたがブラックジャックを作るうえでもいきなり「ブラックジャック　作り方」と調べることも可能です。

しかしその場合ですとサンプルコードは出てくるかもしれませんがそれらの詳細について知ることができずに応用もきかせにくいかもしれません。

「SQLite Rust」等要件を細かくしてそれらについて調べた方が自分が成し遂げたいことに関することに必要なステップ一つ一つがイメージしやすくなりますしより解像度の高い検索が可能だと思います。

# 間接的でもやりたいことを実現できないか考える

Aというツールを用いてBを実現できないか調べる際に「A B 方法」等の直接的なワードで検索をかけたところそのような機能が調べても調べても見つからなかったとします。

この時点で
直接的にBを実現する機能はAにはなさそう
ということまでわかります。

しかし本当にAを用いてBの実現は不可能なのでしょうか？
例えばですがAには直接Bの実現機能はなくともそのツールがCは実現可能でありかつC→Bの実現は可能な場合A→Bと直接の実現はできずともA→C→Bとやることで間接的にA→Bを実現できます。

その場合はCをAから実現する方法を調べればよくなります。



# Googleの完全一致検索を使う
ダブルクォーテーション("")で囲んだワードは検索で必ずヒットします。
調べる際自分のワードと若干ズレた結果になる時がありますがそのような時はこちらのやり方を使っています。
例えばですがエラーコードやメッセージで検索をかけた時に似ているが若干異なる結果が出てくる時があるのでそのような場合に該当メッセージやコード番号をダブルクォーテーションで囲むことで確実にヒットさせることができます。

# とりあえずドットをつけてそれっぽい名前のメソッドを探してみる
Javaのコードの例になりますが例えばList型の変数のサイズを知りたい際.size()というメソッドを用いると取ることが可能ですが、このメソッドを知らない場合でもIntelliJ等のIDEですとその変数名にドットをつけるとそのクラスにあるメソッド一覧が出てくるのでその一覧を見るとsizeという名前を見つけることができるのでこれで実現できそうだなという推測が立ちます。

```
ArrayList<String> list = new ArrayList<>();
list.add("hoge");
list.add("hogehoge");
list.add("hogehogehoge");

//この時点で候補一覧が出てきてそこからメソッドを探してlist.size();と補完できる。
int listSize = list. 
```

上記例ですとListの公式ドキュメントを読むでも済む話ですが他の方が書いたオリジナルのクラスをコード上で使う時に使えます。
そのクラスの実装を見に行くでも大丈夫ですがドットを用いる方が実装を意識せずに直感的に自分が実現したい振る舞いのメソッドを探すことができるのでオススメです。

加えてこれは自分の場合ですがこのようなやり方でメソッド探しをやっていると実際のコードの実装を意識せずにメソッドを探す側の感覚（？）を得られるのでクラス設計の際も直感的にわかりやすいメソッド名にしようという心構えが前よりできるようになったような気がします。

# とりあえず英語で検索してみる

日本語で検索しても得られない情報が英語で検索するとあっさり得られることは結構あります。

最近はDeepL等便利な翻訳ツールも増えてきているので英語で検索する敷居は下がってきているのかなと感じています。

特にエラーの調査の時は英語での検索の方がよくヒットする印象があります。

あと稀にライブラリ自体のバグが原因でエラーが起きている場合もあるのでそのような場合は英語で検索をかけるとGithubのIssueが引っかかりライブラリのバージョンの問題であるとわかる場合もあります。

# デベロッパーツール、WireShark、IDEのデバッグ実行などのツールを使ってみる
Webツールの開発時にデベロッパーツールのNetwork部分やWireShark等で通信経路を調べたりリクエストヘッダーの中身を見る等することで謎のエラーの原因が突き止められる時があります。

デバッグ実行でコードの動きを追ってみて、変数の中身を逐一チェックしていくことも有効です。

これらのツールの使い方の詳細に関してはググってみてください。
~~ググり力の特訓もかねてというオチをつけてみようとしましたが実際は書くのがめんどくさかっただけです。~~

# まとめ

調べることというのは簡単なようでかなり難しいと思っておりますし奥が深いと思っています。

実際過去に自分も何時間も調べてわからなかったことが検索ワードの方向性を変えたらあっさり見つかったこともありました。

何かを調べる時はその検索ワードは本当に正しいのか？自分が本当に実現したいことは何なのかを考えながら調べると自分の調べたい情報の解像度が上がり得られる情報の質も上がるのではないかと思っております。

この記事が何かを調べる際の参考に少しでもなれば幸いです。
グローバル環境でpip installできないように制限する

# 概要
環境変数 `PIP_REQUIRE_VIRTUALENV` に `true` を設定することで、グローバル環境で `pip install` コマンドが実行されないようにできる。

```bash
$ export PIP_REQUIRE_VIRTUALENV=true
```

# 問題
`venv` を利用して仮想環境ごとに `pip` でのパッケージの管理を行う場合を考える。アクティベートをし忘れたまま `pip install` コマンドを実行してしまい、意図せずグローバル環境にパッケージがインストールされてしまうことがある。

```bash
$ python -m venv .venv # 仮想環境の作成

# 仮想環境にパッケージをインストールする場合、ここで仮想環境をアクティベートしなければならない。
# source ./.venv/bin/activate

$ pip install numpy
Collecting numpy
  Using cached numpy-1.21.5.zip (10.7 MB)
  Installing build dependencies ... done
  ...
# 仮想環境がアクティベートされていないため、グローバル環境にパッケージがインストールされてしまっている。
```

# 解決方法
環境変数 `PIP_REQUIRE_VIRTUALENV` に `true` を設定する。

```bash
$ export PIP_REQUIRE_VIRTUALENV=true
```

この環境変数が設定されていると、グローバル環境で `pip install` した場合にエラーとなり、意図せずパッケージがインストールされるのを防ぐことができる。

```bash
$ pip install numpy
ERROR: Could not find an activated virtualenv (required).
```


# 参考URL
https://python-guideja.readthedocs.io/ja/latest/dev/pip-virtualenv.html
Twilio Flex&Studioで営業時間外に着信した時に留守電音声を流す

## はじめに

Twilio Flexを用いたコールセンターを運用し始めて、営業時間外に留守電音声を流したいという要望がありました

この記事では、Twilio FlexとStudioを利用して営業時間外に着信した場合留守電を流す機能を作る方法について紹介します

## やりたいこと

・営業時間は9~20時
・営業時間内に着信があった場合コールセンターへ繋ぐ
・営業時間外に着信があった場合は留守電音声を流す

## 最終成果物

Twilio Flexを作成した状態で着信時のアクション(`Trigger`)とコールセンターへの接続(`Send To Flex`)は作成されているので割愛します

今回追加したのは下記の2つのWidgetです
① `Say/Play`
② `Split Based on...`


![スクリーンショット_2021-12-20_18_55_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18783/36d60a52-2f47-a5b7-29d9-74f6f252c3b9.png)

### Say/Play

こちらは音声読み上げのSayと音声ファイルの再生のPlayをするためのwidgetです

今回は留守電音声ファイルを再生するので、Playを利用します

![スクリーンショット_2021-12-20_19_06_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18783/a3cfba7a-9d1f-0838-fe90-3e60e2072d55.png)



### Split Based On...

`Split Based On...` は条件分岐をするためのwidgetです

評価対象の値( `VARIABLE TO TEST` )を指定し、この値の比較条件を設定することで後続の処理を分けます

評価対象の値は `Liquid Template` という形で値を埋め込むことが可能で、今回は現在時刻を評価対象とするので `'now' | date: "%H"` を設定しています

(比較条件として `is Before Time` などがあるので文字列ではなく時刻を生成できれば、もっとスマートにできるので、どなたかご存知であれば教えて下さい... )

https://jp.twilio.com/docs/studio/user-guide/liquid-template-language


![スクリーンショット_2021-12-20_19_01_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18783/2a985f43-cab5-0148-3778-54dd02f5b6ea.png)


注意すべき点としては、Twilio内部で生成される現在時刻はサンフランシスコ時間になるため、JSTに対して-17時間することで変換する必要があります。
今回の場合20~9時が営業時間外なので、一致する文字列をカンマ区切りで、`04,05,...,15`と設定しました
(Twilio Flex内のタイムゾーンをJSTに変える方法があれば、どなたか教えて下さい...)


そして、上記の条件以外の場合は、Flexへ繋ぐ条件を設定したら完成です

<img width=500 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18783/5c0781ec-f1f0-9cd9-6953-42e36b1bcab7.png" />

## その他TIPS

Studio内にあるLogsから実際に通ったフローや詳細な値を確認できます

評価対象の値として利用可能なものやLiquid Templateで評価された値が見ることができるので、非常に便利です

![スクリーンショット_2021-12-20_19_37_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18783/24c68969-8092-1430-3b4c-9dd6c37137d8.png)


## まとめ

Twilio FlexとStudioを使って、営業時間内・外で留守電音声を流すかどうかを分ける方法について紹介しました

Twilioは奥が深いので、まだまだ使い切れてない機能がたくさんある反面、まだまだネット上に情報が少ないので、正しい情報を発信できていない部分があるのでFBをいただけると幸いです
MUI-v5のスタイルエンジンについて

# MUI-v5のスタイルエンジンについて

mui-v5をNext.jsで使おうと思ってエラーが出たので調べてみました。

## 結果

mui-v5には2つのスタイルエンジンが採用されている

- @mui/styled-engine・・・[emotion](https://emotion.sh/docs/introduction)をwrapしたもの
- @mui/styled-engine-sc・・・[styled-components](https://styled-components.com/)をwrapしたもの

**[Styled engines](https://mui.com/guides/understand-mui-packages/#styled-engines)**

(そもそもエラーというよりは、自分が雰囲気でライブラリを使ったり開発してるから起きたことであって、mui-v5の[installation](https://mui.com/getting-started/installation/)をちゃんと読めばエラーは起きないと思われます。)

styled-componentsを使おうと思い下記をinstallしました。

```bash
yarn add @mui/material @mui/styled-engine-sc styled-components
```

するとこんなエラーが。

```jsx
Import trace for requested module:
../../node_modules/@mui/styled-engine/GlobalStyles/index.js
../../node_modules/@mui/styled-engine/index.js
../../node_modules/@mui/system/esm/index.js
../../node_modules/@mui/material/styles/index.js
../../node_modules/@mui/material/index.js
./src/pages/_app.tsx

https://nextjs.org/docs/messages/module-not-found
wait  - compiling...
error - ../../node_modules/@mui/styled-engine/GlobalStyles/GlobalStyles.js:3:0
Module not found: Can't resolve '@emotion/react'
```

どうやら_app.tsxでエラーが起きてるらしい。

なので、node_modulesを遡ってみると確かに**node_modules/@mui/styled-engine/GlobalStyles/index.js**で**@emotion/react**をimportしていました。

mui-v4ではこんなエラーは出なかったので不思議に思いdocument読みました。

## MUIのstyled-engineでは

ページ上部の結論と一緒のことを書くのですが、mui-v5には2つのスタイルエンジンが採用されています。

- @mui/styled-engine・・・[emotion](https://emotion.sh/docs/introduction)をwrapしたもの
- @mui/styled-engine-sc・・・[styled-components](https://styled-components.com/)をwrapしたもの

スタイルソリューションが見直された経緯は[RFC](https://github.com/mui-org/material-ui/issues/22342)にあります。

簡単に言うと、JSSの動的にスタイルを変更するパフォーマンスが悪かったり、ReactコミュニティがJSSを大規模に使うことに賛成していなかったりするため見直したとのことです。

その中で14.3kb以下だと嬉しいよねとか、パフォーマンスは良いに越したことはないけどDXとトレードオフになるなら多少の性能差は仕方ないねとか、スタイルソリューションを変更するにあたって何を必須とするのかがまとめられていました。

そこで候補となったのが以下のライブラリです。

- styled-components
- emotion
- JSS (currently wrapped in material-ui)
- styletron
- Aphrodite
- fela

このライブラリの中から何を使うかというのを決めていくのですが、ライブラリを選定する目線も勉強になりました。

もちろんPerformanceだったりnpmのダウンロード数だったりもあるのですが、Userが何を使っているのかという基準も設けていました。

あとはSSRに対応してるのか等。

そして、選定後styled-componentsとemotionが残ったのですが公式としては、複数のエンジンに対応することになったとしても、ドキュメントではどちらか一方のデモは用意する必要があるよねと。

結果的にemotonが採用されたのですが、採用理由は以下。

- styled-componentsからの移行コストが小さいこと

これはemotionとstyled-componentsのドキュメント見てもらうと分かるのですが、記述方法にあまり違いがありません。

- emotionはcxが使用できるのでオーバーライドする際に、ラッパーコンポーネントを作成したくない場合有効
- emotionでは複数のクラスを使ってスタイルを定義するのではなく、一つのクラスにCSSをまとめることを推奨している。また、emotionではスタイルが一つにまとめられるため、muiで定義されたスタイルの順序の問題が解決される。

とのことでした。

## エラーが出た背景
もちろん@emotion/reactをinstallしていなかったという理由なのですが、そもそもmuiのシステムを理解していなかったり「styled-componentsが使いたいのになぜemotionがいるんだ？」と思ってinstallationを飛ばしたことが原因です。

今は、@mui/styled-engine-scとstyled-componentsはremoveして@mui/styled-engineで開発していくようにしたので解決はしています。

## まとめ

document読むって大事だなと思いました。

また可能であればissueを読んで背景を含め理解すると自分の知見が増えるんだろうなと感じました。


でも、support concurrent modeというのがいまいち理解できなかった。。。

分かる方がいればご教授いただけると嬉しいです。
オミクロン株の重症化についてのインペリアルカレッジ論文の問題点

#はじめに

先にインペリアルカレッジから公開されたオミクロン株についての[レポート](https://www.imperial.ac.uk/mrc-global-infectious-disease-analysis/covid-19/report-49-Omicron/)に
>We find no evidence (for both risk of hospitalisation attendance and symptom status) of Omicron having different severity from Delta, though data on hospitalisations are still very limited

という一文がありこれが「オミクロン株とデルタ株の重症化の程度は同じくらいだという報告が出た」という誤った解釈が流布しているのでこれを正すためにこの文章を書きました。
#問題点1：重症化データの欠落
そもそもこのレポートには重症化のデータは一切含まれていません。扱われているのは症状のあるなしと入院のデータだけです。症状のあるなしや入院のしやすさは重症化と関係はしているかもしれませんが、同じではありません。まして、症状の有無や入院のしやすさに「差がなかったこと」をもってして重症化の程度が同程度だと類推などできないのは明らかだと思います。
#問題点2:正確にオミクロン株を同定していない
レポート内にも触れられていますが
> SGTF had over 60% specificity for Omicron over the date range analysed in the SGTF analysis (and close to 100% by 10th December). 

とあるようにこのレポートで「オミクロン株感染した」と扱われている人たちは本当にオミクロン株に感染した確認がどれていません。結果が「感染の有無や入院しやすさにデルタ株とオミクロン株で差がない」というものであるなら、そもそも、デルタ株とオミクロン株の区別が十分な精度でできていないことを疑ってしかるべきでしょう。さらにこの論文には
>A total of 208,947 S+ and 15,087 S- cases with complete data were included in the SGTF analysis, and 142,340 Delta and 6,184 Omicron cases were included in the genotype analysis. 

という記述があり、数が少ないもののオミクロン株に感染したことがちゃんとわかっている集団があるのにわざわざ不確かな集団を使って解析しています。おそらくオミクロン株に感染したことがちゃんとわかっている集団は個体数が少なく統計的に有意な結果が出なかったものと思われます。この点からもこの解析は信用することが難しいように思います。
#問題点3:なぜロジスティック回帰をつかうのか？
ここで問題にしているのは「デルタ株感染者」と「オミクロン株感染者」という2群と「無症状対有症状」という2群や「入院対非入院」という2群の重なり具合です。このような場合は２×２の表を使ってフィッシャーの正確確率検定を行うのが常道です。

|  |S+  |S-  |
|---|---|---|
|有症状 |119284  |8171  |
|無症状  |89663  |6916 |


|  |S+  |S-  |
|---|---|---|
|非入院 |207555  |15063  |
|入院  |1392  |24 |

ここでS-がオミクロン株、S+がデルタ株としてレポート内で扱われているものです。これを普通にRを使ってフィッシャーの正確確率検定を行ってみました。

```Fisher.R
y <- data.frame(a=c(rep(1,119284+8171),rep(0,89663+6916)),b=c(rep(0,119284),rep(1,8171),rep(0,89663),rep(1,6916)))

fisher.test(table(y[,1],y[,2]))

Fisher s Exact Test for Count Data

data:  table(y[, 2], y[, 1])
p-value = 2.597e-12
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
 0.8589658 0.9181627
sample estimates:
odds ratio 
 0.8880803 

y <- data.frame(a=c(rep(0,207555+1392),rep(1,15063+24)),b=c(rep(0,207555),rep(1,1392),rep(0,15063),rep(1,24)))

fisher.test(table(y[,2],y[,1]))

Fisher s Exact Test for Count Data

data:  table(y[, 2], y[, 1])
p-value < 2.2e-16
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
 0.1516330 0.3550949
sample estimates:
odds ratio 
  0.237572 



```

みたいになりますこの結果を言葉でいうと

- 無症状の割合はデルタ株の方がオミクロン株の88.8%（95%信頼区間は85.8%以上、91.8%以下）と少ない
- 入院する割合はオミクロン株の方がデルタ株の23.8%（95%信頼区間は15.1%以上、35.5%以下）と少ない

ということになります。いずれも統計的に有意にオミクロン株の方が軽症だということを示唆します。

一般に２つの検定があり、一方が有意差がなく一方がある場合には無い方は「検定力が不足していた」と判断されるのであり、有意差がないことをもってして「同じだ」といってはいけないことになっています。なのでこのデータからもし、なにか結論をだすならむしろ「オミクロン株の方が有意に軽症」であるべきでしょう。
#おわりに
そもそも、有意差がないのですから「オミクロン株の方が軽症だという証拠がなかった」と言っても「オミクロン株の方が重症だという証拠がなかった」と言ってもよかったはずです。それをこのレポートではあえて前者の表記を使いました。なんか偏向しているのではないでしょうか？
margin と col は同時に使ってはいけないのはスタイルが崩れるから．

タイトルの通り，Bootstrap 利用の際に margin と　col は同時に使ってはいけません．スタイルが崩れるので，


##問題

具体的には，

```
<div class="row">
    <div class="col-6 m-2"></div>
    <div class="col-6 m-2"></div>
</div>
```

のようにすると．

子divは横並び2つにはなりません．

![IMG_0547.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/f8dc34f0-f490-fe39-e8b0-306b141e9192.png)


##解決策

以下のように，「colで分けた」子divに．「margin」孫divを適用してあげるのです．


```
<div class="row">
    <div class="col-6">
        <div class ="m-2"></div>
    </div>
    <div class="col-6 m-2">
        <div class ="m-2"></div>
    </div>
</div>
```

![IMG_0548.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/af9dd9fa-e204-3eab-65bf-8489418da10d.png)

##終わり
文字変換

変換

```
こうま→
あの時→あのあの時
あの後→あのあの後
あの→
こういう→こうこういう
こうやって→こうこうやって
こうして→こうこうして
こう→
その→
まあ→
だし→だし。
けれども→けれども。
ますよね→ますよね。
けども→けども。
とかね→とかね。
もんね→もんね。
よね→よね。
ね、→ね。
ないし、→ないし
ないし→ないし。
凄い→すごい
凄く→すごく
れてる→れている
ってる→ってる
ってる→っている
んでる→んでいる
いでる→いでいる
ってて→っていて
してる→している
いてる→いている
ってた→っていた
てる→ている
、、→、
。。→。
てます→ています
けれども→けれど
てまし→ていまし
てた→ていた
るもん→るもの
みたいな。→みたいな感じですね。
でても→
だし。→です。
```


```
こう→
うんうん→
こうまあ何ていうのかな→
こうなんていうのかな
うんまあ
```
2021年に出会ったバグ

# はじめに
今年もあと少しで終わりますね！
今年1年コーディングをしてきていくつかバグに遭遇したので備忘録ついでに残しておこうと思います

## safari transparentがグレーになる
これはよく知られているバグですね
iOSが15系になっても存在しています


よく出会うパターンとしては、透過のcssグラデーションでtransparentを使うときでしょうか

```
例）
background: linear-gradient(to left, transparent 0%, #fff 50%);
```

こういった場合にsafariだとtransparent指定した箇所がグレーになってしまいます
解消方法は簡単でtransparent指定の代わりにrgbaを使うだけです

```
解消方法）
background: linear-gradient(to left, rgba(0,0,0,0) 0%, #fff 50%);
```

### なぜグレーになるのか
時間があったので少し原因を調査してみました
なぜグレーになってしまうのかはmozillaやW3Cのドキュメントに記載があります

> transparent は完全な透明色を表すキーワードです。この色が付いた項目の背後の背景は完全に見えます。厳密には、transparent は rgba(0,0,0,0) のショートカットです。

https://developer.mozilla.org/ja/docs/Web/CSS/color_value#transparent_%E3%82%AD%E3%83%BC%E3%83%AF%E3%83%BC%E3%83%89

> transparent
> Fully transparent. This keyword can be considered a shorthand for transparent black, rgba(0,0,0,0), which is its computed value.

https://www.w3.org/TR/css-color-3/#transparent

要するにtransparentは`rgba(0,0,0,0)`と同義になるということです
先ほどの指定を言い換えると`rgba(255,255,255,1)`から`rgba(0,0,0,0)`へのグラデーションとなります
すなわちアルファは透明になっていき、色は白から黒へと変わるという意味になります
さらにmozillaにはtransparentについてNoteが記載されており、古いブラウザーについてはアルファが0の値である場合に黒として扱うとの記載もあります。

> Note: グラデーションの場合の同様、予期しない動きを避けるために、現在の CSS の仕様書は transparent をアルファ乗算色空間で計算するように定めています。しかし、古いブラウザーはアルファチャンネルが 0 の値である黒として扱うかもしれません。

これによりsafariでtransparentがグレーになってしまうようです

はじめにも書きましたが最新のOSでも解消はされていないため、今後もtransparentではなくrgba指定で記載するのが良さそうです

## lottieを使ったときにiOS15系でsafariがクラッシュする

これは記載の通りなのですが、lottieを使った場合にiOS15系でsafariがクラッシュするバグがありました
原因としては、lottieで使うjsonファイルの書き出しに何らかの原因があるようです
解決方法としては、jsonファイルの書き出し内容を調整するか、その部分だけlottieを使わないで別の方法で実装するかになると思います

まだ詳細な原因までは追い切れていませんが、iOS14までは正常に動作していたため内部的な部分が何か変わったのではないかと思っています
もし既に何か知っている人がいらっしゃったらコメントいただけると幸いです

## safariでflex gapが効かない

gapとはcssのプロパティで、行や列の隙間を定義するものです
使い道としては、flexやgridを使うときに大体の場合アイテムの隙間を定義すると思いますが、それを簡単に定義することができるものです
特にflexと組み合わせて使われることが多いんじゃないかなと思います

ただそこには少し落とし穴があり、flexを使った場合のgapはsafariだと14.5以降でないと使えません
便利なプロパティですが、iOSは直近2バージョンのサポートをすることが多いため、気軽に使えるようになるにはもう少し時間がかかりそうです

https://caniuse.com/?search=gap



## さいごに
今年も1年間お疲れ様でした
振り返ってみると個人としてはあまりバグに出会わなかった年な気がします
これもIEが動作保証から消え始めていることが大きいですね

それでは来年以降もよりバグに出会わない年になることを願って...
githubで「.」を押してみよう

## ある日の出来事
不可視ファイルを`command + f`で検索しようと思ったのだが...
肝心の`command + f`を叩き忘れていた。
なんなら検索するリポジトリも間違えていた。
何故なら...
眠かったからだ
![スクリーンショット 2021-12-20 19.02.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224153/abf67337-36e7-c79a-091a-1172787d41f1.png)

そして「.」を入力
![スクリーンショット 2021-12-20 19.12.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224153/d4cfbf78-f6f6-aeb1-5bcc-14b45ad27c45.png)


「...」
「...」
「何...だと...！？」

こうして深い眠りから解放されるのであった。
めでたし、めでたし
企業に刺さりそうな企画書を考える

プランナー（ゲームデザイナー）としてゲーム系企業を目指す際に9割の会社が求めてくるもの。
それはゲームの企画書！
でも企画書をもって企業にカチコミをかけると、めちゃめちゃ褒められることもあれば門前払いを食らうこともある。

企業によって評価は様々だが、共通している部分やそんなところ見てるんだ。と、それを知って企画書を書けばめっちゃ有利に就職活動できるんじゃね？？？？と思ったので優しい私はこの記事を書くことに決めた。**ありがたく受け取れ！**


#最低限の文章構成能力があれば書類選考は通る
小規模のデベロッパーの会社であればその人の最低限の文章力や見やすさに配慮した企画書を作れるかといった**最低限のスキル**を計っていることが多い。
だから
１，発想をゲームに落とし込めている
２，企画書を見てゲーム内容が伝わる
の2点ができていれば書類選考は通る！

また、デベロッパーであればゲームの一部を受託開発する
####仕様書の方が重要なこともある
なので仕様書があるとめちゃめちゃ評価されるし、応募書類で必須にしている企業も多い！
自分の得意なコトを意識して、企画書と仕様書どちらに重きを置くかを考えよう。

目安として、目指している企業によって変わるが、小規模なデベロッパーであれば企画書２つに仕様書１つあれば安心して就職活動に臨める！多分！~~正直仕様書とかまともに作った事ないからワカンネ~~

#スマホ向けゲームの企画書にマーケティングは必要か
スマホゲームの開発をしている企業は多く、目指している人もいるだろう。
そんな中結構疑問に思うことが一つ。
『スマホ向けゲームの企画書にマーケティングは必要なのか』
結論を言うとあったほうが良い。ただし優先度は低め。
基本的に現在のスマホのマネタイズは動画広告とアプリ内課金がほとんど。
**うまい課金のさせ方**を思いついたのであれば組み込んでも良いかもしれないが、それを考えるくらいならゲームの中身をしっかり固めたほうが良い。

ちなみに「緑のほしぼし」というゲームはゲーム内とリンクして、広告を再生し、広告終了後にゲーム内で報酬を与えるという結構うまい広告のさせ方をしているので一度プレイしてみると良い。

#まとめると結局どうなるんだ
ここまで見たら疑問にみんな思うであろう。
大手企業は？？？？天才って言ってるんだからわかるんだろ？？？？
って
皆が思い浮かべるであろう大手企業はかなり求めるものにバラつきがある！

例えば、RPGを作っている場所であれば、プランナーの仕事は細かいキャラクターのセリフやゲームを彩る細部のシステムを担当するなどだろうか。そういった時に求められるのは文章力や、プレイヤーに対する細かい配慮を多く詰め込んだ企画や仕様を考える力だろう。

多くの版権を扱う会社であればそのコンテンツを見ている人の需要を満たす物やよりコンテンツの価値を上げるような企画を思いつくマーケティング能力を持つような人だろう。

当然、今までにないまったく新しいゲームを作ることができる才能にあふれた人間は当然どこの会社も欲しがる。

ただ、正直大手企業の求めるレベルはどれも高いし、身に着けよう！と思って身につけれるものは少ない。
結局は、求められるスキルを最低限のラインまで取得し、自分の得意分野を誰にも負けないレベルにまで上げることが重要なのだ。

**だからみんなまずはこんな記事を見ていないで企画書を描け！！！！！！そして人に見せろ！！！！！！！！！！！！**

以上！！！！！！！
C#でカノジョをつくる（20日目）

お疲れ様です。たなしょです。
今日はユーザーの発言をランダム辞書に記録できるようにします。
## 辞書のクラスをリファクタリングする
コンストラクターの書いた処理を下記のメソッドに2分割します。
### MakeRandomList
ランダム辞書を呼び出します。

```c#
private void MakeRandomList()
{ 
    string[] r_lines = File.ReadAllLines(
        @"dics\random.txt",
        System.Text.Encoding.UTF8
        );

    foreach (string line in r_lines)
    {
        string str = line.Replace("\n", "");
        if (line != "")
        {
            _randomList.Add(str);
        }
    } 
}
```

### MakePatternList
パターン辞書を呼び出します。

```c#
private void MakePatternList()
{ 
    string[] p_lines = File.ReadAllLines(
        @"dics\pattern.txt",
        System.Text.Encoding.UTF8
        );

    List<string> new_lines = new();

    foreach (string line in p_lines)
    {
        string str = line.Replace("\n", "");
        if (line != "")
        {
            new_lines.Add(str);
        }
    }

    foreach (string line in new_lines)
    {
        // add code
        // line replace \\t -> \t
        string rep_line = line.Replace("\\t", "\t");
        string[] carveLine = rep_line.Split(new char[] { '\t' });
        _patternList.Add(
            new ParseItem(
                carveLine[0],
                carveLine[1])
            );
    }
}
```

## ユーザーの発言をランダム辞書に追加する処理
1.ランダム辞書に存在しない場合は辞書に追加します。

```c#
public void Study(string input)
{
    string userInput = input.Replace("\n", "");
    if (_randomList.Contains(userInput) == false)
    {
        _randomList.Add(userInput);
    }
}
```
2.ファイルに書き込みます。

```c#
public void Save()
{
    File.WriteAllLines(
        @"dics\random.txt",
        _randomList,
        System.Text.Encoding.UTF8
        );
}
```

## 本体クラスを改造してユーザー発言を記録できるようにする。
1.Dialogueメソッドにstudyメソッドを追加します。

```c#
string resp = _responder.Response(
    input,
    _emotion.Mood);
_dictionary.Study(input);
return resp;
```
2.saveメソッドを追加します。

```c#
public void Save()
{
    _dictionary.Save();
}
```

## フォームを閉じたときに記録するか質問するようにする
イベントのFormClosedに処理を追加します。

```c#
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
    const string message = "記憶しちゃってもOK?";
    const string caption = "質問でーす";
    var result = MessageBox.Show(message,
                                 caption,
                                 MessageBoxButtons.YesNo,
                                 MessageBoxIcon.Question);
    if (result == DialogResult.Yes)
    {
        _chan.Save();
    }
}
```
これでユーザーの発言を記録できて少しは会話っぽいことができるようになりました！

## 最後に
発言を簡易的ではありますが記録することができました。
次回からはMecabを使った形態素解析を用いてパターン辞書に記録していくように実装していきます。
【初心者SQL】JOINと友達になりたい！

こんにちは。
最近業務でSQLをめっちゃかきはじめました。初心者SQLerです。
だいたい構文は理解してますが、joinを使うことが苦手すぎてこれまで避けてきた私が、ついに**JOINと友達になる**ことができましたｗ

結果、JOINを使うときにここには注意したいという点が見えたので、記事にしたいと思います。
※この記事は、JOINの考え方は知っている人向けです。JOINを使うときに気を付けたほうがいいことをサンプル付きでまとめています。

## JOINができると解決できるケース

* 1回のSQLではデータが出ないとき。
* 1回のSQLでデータを出すときに、別々のTBを結合しないと検索できないとき。

私はこれまで、
SQL書いて抽出→スプレッドシート→値をカンマにして in()…の繰り返し
という不毛なことをしていました。。。
それに疲れ切った私は、JOINと友達にならないとまずい！と重い腰を上げたのであった。

## JOINとは？（当たり前のおさらい）
複数のTBを1つにリレーションしたいときに使えばいい。ただそれだけ。

```ruby
TB1 join TB2 on TB1.col1 = Tb2.col2
```
↑Fin！イッツJOIN！（超初心者の書き方で失礼します。）


## JOINがなんか使いにくい（面倒）と思っていた理由

* 記述が長くなるのエラーが多くなりそう　→面倒
* 考え方の整理が難しい　→面倒
* 複数TBのイメージがしづらい　→面倒

これらの面倒により避けてきていました。
今回私なりのJOINを書くときの自分のルールを作る、ことでJOINは簡単だと思えるようになりました。

## 自分なりのJOINを使うときのルールを決めた
SQL初心者の私はselect→from→…と上から順に構文を作る傾向があります。
結果、JOINをする！と決めたタイミングで、あれ？selectには何を入れるといいんだっけ…となりがちでした。
以下のようなルールを個人的に設けると考えが整理できました。

* JOINの構文を作るときは、**先にfromから**作る
* fromにあるJOINしたい**TB同士で検索したいものをイメージしてから**、selectにあとから書いていく
* JOIN対象の**TB.col1**を上記で記述したselectに漏れがないかを確認する。
* （なんなら、With句は全部必要なTBを作ってから、最後に付ける）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1706758/e508c978-9dfa-5110-4594-fc78a494bbb8.png)

## With句もセットで覚えると良い！
JOINでSQLを書くときは、ほぼ複数のTBでデータを一時作成するケースがほとんどかと思います。

そのため、**With句** もセットで覚えるととても便利！

* Withは**文頭の1レコードのみ**記載する。
* それ以外のTBは**as(),のみ**でよい。
* 1つのSQLでTB作成の**as(),は何個も使ってよい**。
* 最後にまとめるときのTBはas()**（カンマを付けない！）**

## JOINしたTBを1つのSQLに複数作ってもよいか？
作って大丈夫です！！

例えば、
リレーションを複数行う過程でJOINが複数回必要になった場合

```ruby
with TB_1 as(
select * from TB_a where hoge 
)
,
TB_2 as(
select * from TB_b where hoge
)
,
TB_3 as(
select * from TB_a join TB_b on TB_a.col1 = TB_b.col1
)
--↑カンマは最後のasには不要です！

-- 別のTBで再度joinしたい
select * from TB_3 join TB_4 on TB_3.col1 = TB_4.col1
```

##クロージングのために縦結合のunion allも使ってみる
JOINを複数回使った一時TB同士で結果のレイアウトが合えば、
union all で結合するととてもきれいな集計結果を作れました。

```ruby
with TB1_1 as(
select * from TB_a where hoge 
)
,
TB1_2 as(
select * from TB_b where hoge
)
,
-- 1回目のjoin
TB1_3 as(
select * from TB_a join TB_b on TB_a.col1 = TB_b.col1
)
,

TB2_1 as(
select * from TB_c where hoge 
)
,
TB2_2 as(
select * from TB_d where hoge
)
,
-- 2回目のjoin
TB2_3 as(
select * from TB_c join TB_d on TB_c.col1 = TB_d.col1
)
-- 2つを結合
select * from TB1_3
union all
select * from TB2_3
```

## JOIN便利。心の友…
1回覚えてしまえば、もう怖くなかった。
集計を複数回やるときに毎回スプレッドシートに貼るアクションが不要になりました。
最高！
bookmarkletを使ってみて

#古き良きbookmarkletについて

##bookmarkletとは

JavaScriptで動作するものである。（JavaScriptで書けることはだいたい書ける）

bookmarkletはブラウザのブックマークに保存するものである。

##bookmarkletはいつ使うの？

開いているブラウザの画面上のHTMLをJSで操作


- HTML要素の解析に使える（はず）

-  HTML要素の変更に使える（INPUTタグとかにデータを入れるとか）

***重要な使い方として個人情報や入力したいデータを特定のinputに入れたいときとかによく使う。***

これをすることにより、

例えば、**個人情報入れて申請するサイト**があるとすれば、
申請状況のステータスを確認するページも有り、そこで個人情報を再度いれて申請状況ステータスを確認したいとかある。（何度も入れて確認するのは面倒だから）

（個人情報入れて申請する時も然り）

##注意事項
どうもchormeさんは動かない模様、、、、


##事前準備
テキトーに作ったブックマーク一個作っておく



##bookmarkletを使ってみる

まずは雛形として


```js
javascript:(function(f,s){

    s=document.createElement('script');
    
    s.src='//ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js';
    s.onload=function(){
        f(jQuery.noConflict(true))};
    document.body.appendChild(s)})(
    function($){
    //ここからやりたい処理を記述
    alert(1223);
});
```

テキトーに作ったブックマークのアドレスを編集してこれを貼り付ける（インデントは気にしないでください）

ブックマークを押して実行するとjsのアラートが出る

jQueryをロードしておるのでjQueryの書き方も可能です。

##bookmarklet応用

jQueryの記述も含めてそれらしいのをつくります

```js
javascript:(function(f,s){

    s=document.createElement('script');
    
    s.src='//ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js';
    s.onload=function(){
        f(jQuery.noConflict(true))};
    document.body.appendChild(s)})(
    function($){
	$('body').css('background-color', 'red');
	$('.gLFyf').val('test');
});
```
これを[Google先生](https://www.google.co.jp)の検索で実行すると

![スクリーンショット 2021-12-20 18.45.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214221/20a9d951-8172-514b-5456-958321562e89.png)

bookmarkletで

bodyに対して背景色をRED

検索入力欄にtestを入力（検索入力欄のIDがなくて、クラスがgLFyfだった）

ってな感じになりました。

##これであなたもbookmarkletマスター

これを応用して自分のサイトとかで使ってみよう

aタグに仕込むなら

```
<a href="javascript:(function(f,s){

    s=document.createElement('script');
    
    s.src='//ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js';
    s.onload=function(){
        f(jQuery.noConflict(true))};
    document.body.appendChild(s)})(
    function($){
	$('body').css('background-color', 'red');
});"
>
```


良いお年を
スキーマ とは

## 勉強前イメージ

よく聞くけど正直あんまりわかってない・・・
範囲のこと？

## 調査

### スキーマ とは

データベースの構造を定義したもので、データベースのデータをどう管理するかを記載しているものになります。
リレーショナルDBのテーブルを設計する際にデータ型やどれを主キーにするかなどもスキーマ定義の一種になります。
スキーマレスDBというのもあり、定義が必要ないDBを意味します。
スキーマが必要かどうかはDBによって違うので確認が必要です。

### スキーマの種類

データベースのスキーマは3階層に分けられ、その思想を3層スキーマと呼ばれます。
3層に分けるのは一つの変更があった際に、他に影響を及ぼさないようにして独立性を保って
変更が局所的になるようにしています。

- 概念スキーマ

データベース上の論理データで
保持するデータの要素やデータ同士の関係を定義する部分。
開発者から見たデータベースでこの設計を論理設計と呼びます。

- 外部スキーマ

概念スキーマで定義された論理データから
必要なデータを取り出したビューの部分
ユーザやアプリケーションから見たデータ構造やデータの関係を定義します。

- 内部スキーマ

概念スキーマで定義された論理データから
どのように格納するのかを定義した部分
DBMSから見たデータベースでこの設計を物理設計と呼びます。

## 勉強後イメージ

定義してるものはスキーマなのか。
だからどれを主キーにしてるとかもスキーマで、
テーブル作る際もスキーマ作ってるのと一緒って感じかな？

## 参考

- [3層スキーマ](http://db-study.com/archives/36)
- [データベースのスキーマとは？初心者でも理解できる解説](https://offers.jp/media/programming/a_786)
Rubyでnull文字を正規表現でひっかけたいとき

個人的に結構ハマってしまったのでメモ


```
# null文字の定義
null_string = "\0"
=> "\u0000"

# null文字を引っ掛ける
null_string.match(/\0/)
=> #<MatchData "\u0000">
```
WindowsでTerraformをバージョン管理する(tfenv)

## tfenvのインストール方法(マニュアルインストール)

### 1: ソースをクローンする

```bash
$ git clone https://github.com/tfutils/tfenv.git ~/.tfenv
```

### 2: パスを通す

```bash
$ echo 'export PATH="$HOME/.tfenv/bin:$PATH"' >> ~/.bash_profile
```

### 3: ターミナルを再起動する

ターミナルを再起動すれば利用可能
```tfenv install latest``` で最新バージョンがインストールされる

#### 引用元

> [tfenv - GitHub](https://github.com/tfutils/tfenv)
CLIが利用できない初歩的な見落とし


①エラー

```
An error occurred (InvalidClientTokenId) when calling the GetCallerIdentity operation: The security token included in the request is invalid.
```

②対処

```
rm -r ~/.aws
aws sts get-caller-identity

```

③解説

aws configureを見てみると過去に手動で入力した一時的なキー情報などが記載されているとそちらのキー情報を読み取るためエラーになることがあります。

そういう時は②を参考にaws configureの設定削除を行ってみましょう
また、再設定したい場合は

```
 aws configure
```

※補足
以下のエラーでも上記内容が原因の可能性があります。
ポリシーが足りてないのでは？とか考えてしまいますがそうでないかもしれません

```
An error occurred (InvalidAccessKeyId) when calling the ListBuckets operation: The AWS Access Key Id you provided does not exist in our records.
```
FreeBSDでpy-yubikey-managerを使う

# ことの始まり
自宅のFreeBSDでYubikeyを使ったいろいろなことをする準備でyubikey管理ツールの`py-yubikey-manager`を入れたが、次のように表示され認識できていなかった。
会社のFedoraではpy-yubikey-managerをインストールするだけで使えた[^1]ので同じ感覚で使えるものと思っていたがFreeBSDでは勝手が違ったのでメモ& Advent Calendar 2021の穴埋めとして書きます[^2]。


```
% ykman piv info
WARNING: PC/SC not available. Smart card protocols will not function.
WARNING: No OTP HID backend available. OTP protocols will not function.
Error: No YubiKey detected!
```



## 環境
- FreeBSD 13.0-RELEASE-p5
- Yubikey 5 NFC

## 使用するパッケージ
Yubikeyツール
- py-yubikey-manager
- yubico-piv-tool
　確認する上ではどちらでもOK。本記事では`py-yubikey-manager`を利用します。

PC/SCを認識するためのデーモン
- pcsc-lite (PC/SC Smart Card Daemon)


## 事前に起動するデーモン

pcscdを自動起動させるため、rc.confに追記する。

```
sysrc pcscd_enable=YES
```

pcscd をテストで手動起動する。

```
/usr/local/etc/rc.d/pcscd start
```

## 動作確認

Yubikeyを挿してコマンド実行。
次の様に挿したYubikeyが認識されていればOK。

```
% ykman piv info
PIV version: 5.4.2
WARNING: Using default PIN!
PIN tries remaining: 3/3
WARNING: Using default Management key!
Management key algorithm: TDES
CHUID:	No data available.
CCC: 	No data available.
```

## 終わりに
Yubikeyを使ったいろいろなことは来年やりたいと思います。

[^1]: Fedoraでは、yubico-piv-tool等をインストールするとPC/SCDが起動するようにsystemdに設定されているようです。
[^2]: 日本語検索では見つかりませんでしたが、本家のFAQで同じことが書かれていました・・・。
リーマン多様体の上で最適化してみる

# はじめに
この記事は、物工/計数 Advent Calendar 2021 22日目の記事です。

初めましての方は初めまして。計数工学科B4のまさよしです。B4なので当然卒論に追われているため、typoとかは許してください（理論パートもめっちゃ端折りました）。
テーマは最近流行りの？多様体上の最適化です。直交行列からなる多様体上の最適化により、混合された画像から元の画像を復元することを目標にします。

# 問題設定 
画像が3枚あるとしましょう（もちろん3枚じゃなくても構いません）。$\mathrm{img}$を画像を格納した配列として、$\mathrm{img}[i]$ $(i=0, 1, 2)$ が各画像を表すとします。突然ですがその画像たちがなぜかある直交行列$A$によって混合されてしまったとします。つまり、それぞれの画像の$i$番目の画素の値を並べたベクトルを
$$
 x = (\mathrm{img}[0]_i, \mathrm{img}[1]_i, \mathrm{img}[2]_i)^\top
$$
として

$$
y = Ax
$$

と変換された$y$の要素を第$i$成分に持つような画像が観測として得られるとします。

![mix.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339162/d8935b18-0c88-0161-9fd9-7168ab8f1579.png)

この直交行列$A$がわからない時に混合されてしまった画像から元の画像を復元するという問題を考えます。つまり、ある直交行列$W$であって
$$
x = Wy = WAx
$$
つまり、$W = A^\top$となるような$W$を見つける問題です。もちろん何の仮定もなしに復元することはできないわけですが、今回は画像それぞれが独立な信号だと思って、いわゆる独立成分分析を行います。詳細は省きますが、目的関数として以下のような4次のモーメントを考えます。
$$
f(W) = \sum_{i=0}^3\sum_{j}\mathrm{img}[i]_j^4
$$

$A$は直交行列なので、$W$として考える行列も直交行列に限ってしまって良いでしょう。よって最適化問題としては、
$$
\min_{W:\text{直交行列}} f(W)
$$
と書くことができます。

# リーマン多様体上の最適化
上で定義した問題は行列全体の空間（線型空間）で見れば制約付き最適化となります。しかし、そもそも直交行列しかいないような世界を考えれば制約なし最適化になるはずです。そうした直交行列からなる空間はStiefel多様体と呼ばれるリーマン多様体の一種になります。よって今回の問題をStiefel多様体上の最適化問題と考えれば、扱いやすい制約なし最適化として定式化できます。

# manoptを使ってみる
実際にこの問題をPythonで解いてみましょう。[manopt](https://www.manopt.org/)はMatlab, Python, Juliaで使えるリーマン多様体上の最適化のためのライブラリです。今回は手っ取り早くこれを使うことにします。詳細は[gist](https://gist.github.com/masayoshi64/4d5dea909792b26f0bdcfd8e120e8ff4)をみてください。

まずコスト関数を定義します(`observed_data`は画像を一次元化して並べたものです)。

```python
def cost(W):
    tmp = np.dot(W, observed_data)
    res = (tmp**4).sum()
    return res
```

これは自動微分できる必要があるので、`import autograd.numpy as np`をしておきましょう（torchも使えるらしいが動かなかった）。

次に多様体 (manifold) とソルバを定義します。今回は最急降下法を使うことにしました。manifoldはもちろんStiefel多様体です。

```python
manifold = Stiefel(n, n)
problem = Problem(manifold = manifold, cost = cost, verbosity = 1)
solver = SteepestDescent()
```

あとはソルバを走らせるだけです。

```python
W_opt = solver.solve(problem)
```
# 結果
上で示したコードで得られた復元結果は以下のようになりました。![recover.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339162/e14e76c7-cacf-8c6a-cc4a-5c90e8e89251.png)
国税庁には少しルフィーが映り込んでしまっていますが、結構ちゃんと分離できていることがわかりますね。
# 内部で何をやっているのか？
線型空間上の通常の最急降下法と比較しながら、リーマン多様体上の最急降下法が何をしているかを確認しましょう。
通常の最急降下法では$\alpha$をstep sizeとして

$$
W_{i+1} = W_i - \alpha\nabla f(W_i)
$$
と暫定解$W_i$を更新します。$\nabla f(W_i)$は$W_i$における最急降下方向ということができます。実はリーマン多様体上の各点$W$には接空間が付随し、そこには内積$\langle\cdot, \cdot\rangle_W$が定められています。そこで、この接空間上で、$\langle\cdot, \cdot\rangle_W$に関する最急降下方向を$\operatorname{grad} f(W)$としましょう。するとリーマン多様体上の最急降下法はナイーブには以下のように書けると予想できます。
$$
W_{i+1} = W_i - \alpha\operatorname{grad} f(W_i)
$$
しかし、線型空間の場合とは違って、$W_i - \alpha\operatorname{grad} f(W_i)$が多様体に含まれているとは限りません。そこで、$W_i - \alpha\operatorname{grad} f(W_i)$を多様体に引き戻す（retraction）ことが必要になります。式で書けば、
$$
W_{i+1} = R_{W_i}(- \alpha\operatorname{grad} f(W_i))
$$
のようになります。$R_W$がretractionです。
今回の場合はQR分解を用いてretractionを定義します。つまり、$W_i - \alpha\operatorname{grad} f(W_i) = QR$（$Q$: 直交行列、$R$: 上三角行列）という分解を考えたときの$Q$を$W_{i+1}$とします。


# 終わりに
いらすとやには何でもあることがわかりました。卒論からは逃げられない！

# 参考文献
金森 敬文・鈴木 大慈・竹内 一郎・佐藤 一誠: 機械学習のための連続最適化, 講談社(2016)
サイモンのアルゴリズムの試行回数の期待値求めてみた

#求めたかった期待値
サイモンのアルゴリズムについては、
https://qiskit.org/textbook/ja/ch-algorithms/simon.html
このサイトを見ていただければ一番わかりやすいです~~(丸投げ)~~
このアルゴリズムについて私が知りたかったのは、
**およそ何回繰り返せば$n$個のデータが得られるのか**、という点です。
#まず確率を求めてみた
$n$量子ビットのオラクルについて考えます。
取り出したいデータが$x_1,\cdots ,x_n$の$n$個あるとします。一回の試行でどのデータを取り出すかは等確率です。
$k$を$k\geq n$なる整数として$k$回の試行ではじめてすべてのデータが取り出される確率を求めます。
$1\leq l\leq n$なる整数$l$に対して次の命題を定めます。

```math
A_l:「k-1回の試行で少なくとも一回x_lを取り出す」\\
B_l:「k回目の試行でx_lを取り出す」
```

$A_l,B_l$は独立な試行によるものですから求める確率$p_k$は

```math
p_k = P(\bar{A_1}\cap A_2\cap \cdots A_n)P(B_1) + P(A_1\cap \bar{A_2}\cap \cdots A_n)P(B_2) +\cdots + P(A_1\cap A_2\cap \cdots \bar{A_n})P(B_n)
```

まず第1項について考えましょう。データ$x_2,\cdots,x_n$に関する対称性と包除原理より

```math
P(\bar{A_1}\cap A_2\cap \cdots \cap A_n)\\
=P(\bar{A_1}\cap \overline{\overline{A_2\cap \cdots \cap A_n}})\\
=P(\bar{A_1}\cap \overline{\bar{A_2}\cup \cdots \cup \bar{A_n}})\\
=P(\bar{A_1})-P(\bar{A_1}\cap (\bar{A_2}\cup \cdots \cup \bar{A_n}))\\
=P(\bar{A_1})-\sum_{m=1}^{n-1} (-1)^{m-1}{}_{n-1}\text{C}_m P(\bar{A_2}\cap\cdots\cap\bar{A_{m+1}})\\
=\left(\frac{n-1}{n}\right)^{k-1}+\sum_{m=1}^{n-1}(-1)^m{}_{n-1}\text{C}_m \left(\frac{n-m-1}{n}\right)^{k-1}\\
=\sum_{m=1}^n (-1)^{m-1}\left(1-\frac{m}{n}\right)^{k-1}.
```
また明らかに$P(B)=\frac{1}{n}$です。
これについてほかの項についても考えれば

```math
p_k = \sum_{m=1}^n (-1)^{m-1}\left(1-\frac{m}{n}\right)^{k-1}.
```
#期待値を求めてみた
期待値$E_n$は

```math
E_n = \sum_{k=n}^\infty kp_k\\
=(級数計算は省略)\\
=\sum_{m=1}^n(-1)^{m-1}{}_{n-1}\text{C}_{m-1}\frac{n}{m}\left(1-\frac{m}{n}\right)^{n-1}\left(n+\frac{n}{m}-1\right)
```
#Maximaでプロットしてみた
ゴリゴリ計算して出たはいいものの...あまり意味が分からない。ということでMaximaでプロットしてみる。
$n=2から100$の範囲でプロットした。
![expectation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685561/e050c1c4-4420-5e54-8870-66518b183cac.png)
おおお！大体$O(n)$か？
古典計算における試行回数$2^{n-1}+1$と比較。驚いたのは、$n=2$のとき完全一致。
まず$n=2から5$の範囲。赤が古典計算、青が量子計算。
序盤は古典コンピュータが優勢かもしれないが、終盤劣勢。
![exp_and_bin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685561/de730604-b4ad-cdb8-909d-73ebf4ea270e.png)
そして$n=2から100$の範囲。古典計算のほうには壁がそそり立っているかのように見える。
![exp_and_bin2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685561/b1ab9318-22a7-bb46-ec03-533703fcd965.png)
ContentfulのTechnical Limit(API call数制限 429 Too Many Requests)をapollo clientで回避する方法

# はじめに
こんにちは。 KDDIアジャイル開発センターの小板橋です。 この記事は、[KDDI Engineer&Designer Advent Calendar 2021](https://qiita.com/advent-calendar/2021/engineer-designer)の20日目の記事です。

今回は、[Contentful](https://www.contentful.com/)というHeadlessCMSを利用した際に起こるTechnical Limit(API call数制限 429Too Many Requests)をApollo clientで回避する方法についてまとめていきたいと思います。

# なぜこんな記事を書いたのか
現在、Next.jsとContentfulを利用したポータルサイトの開発を行なっているのですが、その中でContentfulにおけるTechnical Limitの制限により問題が発生した為、今回その原因と解決方法について記事にしてみました。

## ContentfulにおけるTechnical Limit
Contentfulにおける[Technical Limit](https://www.contentful.com/developers/docs/technical-limits/)は、ここに記載があるのですが、今回ボトルネックになったのは、「Content Delivery API (CDA) calls (includes GraphQL calls)」の秒間55requestという制限になります。
これは、秒間に55request以上の負荷がcontentful側にかかった場合に、HTTPステータスが429で返却されてしまうというものです。

* 現在開発しているポータルサイトでは、contentfulのエンドポイントで提供しているGraphQLを利用しています。
* また、ポータル自体はNext.jsを利用し全ページSSG構成をとっています。

この時、何が発生するのかというと静的ページの生成時に、下記のようなコードで非同期に画面生成に必要なデータをbuildする際にContentfulのエンドポイントに対しRequestします。
そうすると、各画面に必要なデータをNext.jsは非同期にfetchしにいくので、ページ数が多ければ多いほど、このContentfulにおけるTechnical Limitである、秒間のRequestに達する可能性が高くなるのです。

```getStaticProps_sample.js
export async function getStaticProps(context) {
  return {
    props: {}, // will be passed to the page component as props
  }
}
```

## 解決策
* 色々この問題を解決する方法を検討した中で、一番簡単に対処できた方法というのが、GraphQLのクライアント向けライブラリであるApollo clientのoption機能を利用した方法です。

* Apollo clientには、[Retry Link](https://www.apollographql.com/docs/react/api/link/apollo-link-retry/)という機能がoptionで設定することができます。

これが何かというと、ネットワークまたはサーバーのエラーが原因でRequest操作が失敗した場合に、Request操作を複数回リトライすることができるという機能です。
Apollo ClientはデフォルトではRequest操作のリトライを行いません。
なので、ReqponseでHTTPステータスが429のToo Many Requestsが返却された場合には、エラーで落ちてしまいます。

* @apollo/client/link/retryのRetryLinkを使用することで、Request操作のリトライを行うことができます。

```RetryLink_sample.js
import { RetryLink } from "@apollo/client/link/retry";

const link = new RetryLink();
```

このRetryLinkではさらに細かいリトライ処理の条件を指定することができます。
今回は、delay.initialというoptionとdelay.maxというオプションを利用し、秒間55requestに達しないように調整しました。
![スクリーンショット 2021-12-20 18.18.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/d739ce44-a62a-7a86-1d32-2ebdea62d7b3.png)


# まとめ
今回ポータルサイトの開発にSaaSであるHeadless CMSのcontentfulを利用させていただいたのですが、SaaSを利用する際のデメリットとして、このようなTechnical Limitの制約で詰まることがあるのがネックだなと感じました。