OmniAICreator/Qiita-1.07M huggingface dataset:
Missing :controller key on routes definition, please check your routes.　即解決できた。（自分用）

dockerを使いrailsのdeviseを入れている時のエラー。

$ docker-compose exec web rails g devise User


Missing :controller key on routes definition, please check your routes.
とエラーメッセージ表示された。



routes.rb内では

Rails.application.routes.draw do
  devise_for :users
  root 'pages/index'     ⇦　⭕️　root 'pages#index'  これで解決した。
  get 'pages/index'
  get 'pages/show'

  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Defines the root path route ("/")
  # root "articles#index"

end
UiPathで文字列を反転させる

# はじめに
文字列を反転させる処理を仕事で使うことがあったので、
メモとして残します。
調べ方わからな過ぎて「文字列　逆から出力　UiPath」とかやってました。
我ながら恥ずかしい。。。

# 結論
Strings.StrReverse(String) メソッドを使って文字列を反転させます。
~~~
Strings.StrReverse("abcdefg")
~~~

# 参考文献
https://learn.microsoft.com/ja-jp/dotnet/api/microsoft.visualbasic.strings.strreverse?view=net-6.0

Microsoftのドキュメントは個人的に難易度が高く敬遠していたのですが、
少しでも読めるようになろうと最近頑張っています。

# 実際にやってみた
実際にUiPathで本当に文字列が反転できるのかやってみました。

## 作成したワークフロー
文字列「abcdefg」を反転させてコンソールに記載するというシンプルなものです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846796/3127909f-7866-0f9f-a133-d641ef9834b8.png)

## 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846796/8fd00824-14ac-e612-e4fd-9cc96d414479.png)
無事に文字列が反転して出力されました。

# おわりに
Microsoftのドキュメントをもっと読みこなせるようになりたいと思います。
引き続き頑張ります。
go.mod で Go のバージョンを更新する

# 概要

go.mod で Go のバージョンを上げたくなったときの方法がわからなかったのでメモ。
なお、 Go 自体のバージョンを上げる方法もついでに書いておく。

# 起きた現象

VS Code で Go の開発をしていて、ジェネリックを使おうと思ったら以下のエラーが出た。
Goのバージョン1.18以上で動作するとのこと。

```
type parameters require go1.18 or later
```

それでは Go のバージョンを上げようかと思ったら、 Go 自体は1.18になっていた。

```bash
> go version
go version go1.18.3 darwin/amd64
```

答えは、単に go.mod でバージョンが低く設定されていただけであった。

```go.mod
module sample

go 1.17

...
```

# go.mod の更新方法

Go のバージョンは既に上がっているが、 go.mod のバージョンが低い場合はどのように更新するか。
go.mod は基本は手で触らないので、以下のコマンドで変更できる。
1.18にしたい場合↓

```bash
> go mod tidy -go=1.18
```

go.mod を開いてみると

```go.mod
module sample

go 1.18

...
```

ちゃんと更新されていた。

# 一応、Go 自体のバージョンアップ

ついでなので Go 自体のバージョンアップ方法も書いておく。
OSX で Homebrew を使ってインストールしている場合は以下でOK。

```bash
> brew update
> brew upgrade go
```

その他は自分で調べてください。
gitがダメないくつかの理由

gitのダメなところを記載する

* 品質が悪い
  * pythonのパッケージ？とかもともと突っ込んで、普通に使ってたら3000？10000コミットとかになったらcloneで固まるようになった。こんなん仕事で使えるの？
    ※ 下は試しにcloneを分解して実行してみたところctrl-cたまにfetch完了してる

    ```bash
    $ git fetch --depth 1
    remote: Counting objects: 727, done
    remote: Finding sources: 100% (727/727)
    remote: Total 727 (delta 31), reused 554 (delta 31)
    Receiving objects: 100% (727/727), 1.21 GiB | 13.53 MiB/s, done.
    Resolving deltas: 100% (31/31), done.
    ```
    → これあれだな、リモートをsshで拾うときの問題だな
    → あれかsshの何かのタイムアウトかてことはsshプロトコルのエラー実装が~~ごみ~~ざるなgitがギルティ
  * 設計思想がだめ
    なんだろうな、ワーキングコピー、ステージング、ローカルリポジトリのHEAD、リモートリポジトリのHEADとfetchされたリモートリポジトリのHEADがあってそれぞれのコマンドがどれにアクセスしてるかわからんgit diffはどれとどれを比較してるんだい？
  * git diff の引数でもわかる
    ```
    git diff ファイル名
    git diff コミットID1 コミットID2 ファイル名
    ```
    → git statusがワーキングとリモートとのチェックをしないのが感覚とずれてるんだな
ことごとく感覚と違う動きをする

CUIじゃなかったらそんなに違和感は無いのだろうか

(2025年3月1日)追記
重複するところはあるけれどいまいまの感想を書いてみる
* 設計思想がゴミ
  * ワーキングディレクトリの内容を全くまったく大事にしないのがだめ
  * ブランチの切り替えでどのファイルが継続されてどのファイルが切り替わるのか意味不明。恐怖しかない
  * コマンドが不明、複雑すぎるのでそれを改善するまとめたコマンドを追加してさらに意味不明になっている。
  * svn lsの代替がない。このファイルがどのコミットと認識されているか分からんvscodeがあればなんとか
  結局編集しててどこかの過去コミットと同じファイルになったらそれになる？いままでのコミットすっ飛ばして最新の内容にしたら最新のコミットとして扱ってくれるの？rebaseかけると壊すけど？

* なんか最新の断面を管理というよりチェンジセットの管理をしている訳でそれが周知されていない

カーネルだけに使ってろ
特徴点群で動画を作ってみた

# 特徴点群で動画を作ってみたとは？
GitHubレポジトリ：https://github.com/yskfukui/PointFlow

### サンプル
<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2697721/265747e2-6f03-8f19-4220-1df09d21f3a1.gif">
</div>

### 主な処理
1. 元動画を準備
2. 特徴点を抽出
3. 単色背景画像に特徴点を描画

### 原理
AKAZE特徴点をプロットして作成
Git 復習　その２


## はじめに
gitを扱う中で、経験した間違いをメモすることにしました。

## 間違えた内容
### リポジトリを作るタイミング
プログラムを書き終わった後に、githubにリモートリポジトリを作り始めることが度々あり、git status を使うと

```
fatal: not a git repository (or any of the parent directories): .git
```
と表示されて戸惑いました。

原因は、git clone は、リモートリポジトリと同名のフォルダを、使用中のフォルダ内に作る　といった内容を忘れていたからです。


1. リモートリポジトリを作る
1. git cloneで、使用中のフォルダ内に、リポジトリをコピーする（新しくリモートリポジトリ名のフォルダが作成される
1. ファイル等を作成し、add, commit, pushなど作業を進める。

後で、ファイルを移動させなくていいので、先にこの流れでやった方が間違えにくかったと思いました。

## 最後に
チーム開発では、分担して作業するので、git checkout, git brunch, git pull などを学習したい。
git format-patch/git am で emoji shortcode が消えてしまう問題を解決する

# TL;DR
```
git format-patch -k
git am -k
```

を使え

# とは

`git format-patch` でコミットたちをファイルに書き出して `git am` でほかのリポジトリ or ブランチに移植出来て便利なんですが、その際

```
:tada: Add hogehoge
```

みたいなコロンで書かれた絵文字があると、`git am` のときに

```
tada: Add hogehoge
```

となってしまいます。

# なんで？
`git am` はメールで来たパッチを適用するように作られてるので、 [git mailinfo](https://git-scm.com/docs/git-mailinfo#Documentation/git-mailinfo.txt--k) が気を効かせて

> - Leading and trailing whitespace.
> - Leading `Re:`, `re:`, and `:`.
> - Leading bracketed strings (between `[` and `]`, usually `[PATCH]`).

を削除してくれるせいです。

# どうするの？
`git am -k` を使いましょう。

ただ、`git format-patch` はデフォルトでは `[PATCH 01/03]` みたいなのを頭につけてくるので、`git format-patch` で出力したパッチはそのまま `git am -k` するとコミットメッセージの頭に余計なものがくっつきます。
`git format-patch` にも `-k` があるので `git format-patch -k` で書きだしましょう。

# Ref
- [別リポジトリのコミットをパッチとして当てる (git format-patch & git am) - syon/til](https://syon.github.io/til/2019/01/14/git-format-patch-git-am/)
- [git am - git am should ignore something in commit message startswith "[]"? - Stack Overflow](https://stackoverflow.com/questions/13339027/git-am-should-ignore-something-in-commit-message-startswith)
SRT(Secure Reliable Transport)について色々ためす(2)

# 1. 概要
SRTを使った映像伝送に関して、色々を実験したい。そこで、手ごろな環境でどのようなことができるのか調べていく。とりあえずの目標は以下のような構成とする。
```
┌──────────────────┐      ┌────────────┐     ┌──────────────────────┐
│CAM = Caller(RPI) │-LAN- │Listener(PC)│-LAN-│Caller(RPI) : Monitor │ > 人
└──────────────────┘      └────────────┘     └──────────────────────┘
```
前回、Raspberry Pi＋GStreamerでSRT配信できることがわかったので、今回はListenerを含む構成を試す。

https://qiita.com/tetsuoMikami/items/6f27de55b86b888f2fb4

# 2. 機材
* Raspberry Pi 3B もしくはZero WH
* OSはBuster(Debian 10), Liteではない
* Linux PC(仮想マシン)
* ホストPCのWindows11

# 3. 準備
## 3.1 Linux(仮想マシン)
VMwareにUbuntu-ja 20.04をインストールした。22系でもよかったのだが、手元にあったISOが20系だったため。実験なのでNICはブリッジとした。
インストール直後に確認したところGStreamerは1.16.2だった。
```
$ gst-inspect-1.0 --version
gst-inspect-1.0 version 1.16.2
GStreamer 1.16.2
```
SRTはbad pluginなので、インストールされていなかった。以下のコマンドでインストール。
```
$ sudo apt install libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-bad
```

インストールされているか確認。SRTのsinkとsourceがあるのでOK。
```
$ gst-inspect-1.0 | grep srt
srtp:  srtpdec: SRTP decoder
srtp:  srtpenc: SRTP encoder
srt:  srtserversink: SRT sink
srt:  srtclientsink: SRT sink
srt:  srtserversrc: SRT source
srt:  srtclientsrc: SRT source
srt:  srtsink: SRT sink
srt:  srtsrc: SRT source
subenc:  srtenc: Srt encoder
dtls:  dtlssrtpdemux: DTLS SRTP Demultiplexer
dtls:  dtlssrtpenc: DTLS-SRTP Encoder
dtls:  dtlssrtpdec: DTLS-SRTP Decoder
subparse: subparse_typefind: srt, sub, mpsub, mdvd, smi, txt, dks, vtt
```

## 3.2 Raspberry Pi
前回から引き継ぎのRaspberry Pi 3B

## 3.3 Windows11
別にWindows10でもなんでもいいが、同じネットワークのVLC Playerが動くマシン

# 4. 配信と再生をやってみる 

1. Listener(Ubuntu)で待ち受け
1. Raspberry Piで配信開始
1. Windows11のVLC Playerで再生

今回の構成
```
┌─────────────┐     ┌──────────────────────────────┐     ┌─────────────┐
│192.168.1.128│     │         192.168.1.2          │     │ 192.168.1.1 │
│Caller(RPI)  │-LAN-│:17001 Listener(Ubuntu) :17002│-LAN-│Caller(Win11)│ > 人
└─────────────┘     └──────────────────────────────┘     └─────────────┘
```

Listenerで待ち受け状態を作る。
srtserversrcにポート17001で受信させる。
srtserversinkからポート17002で送信させる。
```
gst-launch-1.0 -v srtserversrc uri="srt://:17001" latency=100 ! srtserversink uri="srt://:17002"
```

次にRaspberry Piからテスト映像(カラーバー)を送信する。送信先はIPアドレス 192.168.1.2 のListener(Ubuntu) 
```
gst-launch-1.0 videotestsrc ! videoconvert ! x264enc key-int-max=15 \
! mpegtsmux ! srtclientsink uri="srt://192.168.1.2:17001" latency=100
```

映像を再生してみる。
VLC Player で「ネットワークストリームを開く」に以下をいれる。IPアドレスは当然Listenerのもの。
```
srt://192.168.1.2:17002
```

## 4.1 エラー？

listner側でいっぱい出る。一度再生して、停止すると出てくるようだ。また、各機器のlatencyが大きく違ったりしても出るようだ。
原因は調べていない。
```
06:00:19 AM.952163/SRT:RcvQ:worker*E:SRT.c: %1071413438:No room to store incoming packet: offset=0 avail=0 ack.seq=1443803767 pkt.seq=1443803767 rcv-remain=8191
```

# 5. まとめ
とりあえずCallerとListenerを使ってSRTの送受信ができた。
次回はカメラ映像とかも混ぜて試す。

以上
オブジェクトを分割代入する際の変数名を別名にする記法に思うこと

オブジェクトの分割代入自体は特段難しいことではありませんが、変数名が重複してしまい別名をつけなければならない場合の記法がちょっとひっかかったので覚えも兼ねて記事にしました。

## ひっかかった理由
TypeScriptの型付けと記法が似ており混同してしまったため

## 書き方及びユースケース
分割代入の代表例はフックですが、同一コンポーネント内にフックを複数用いる場合がユースケースの一例として考えられます。
下記例は一つのコンポーネント内に似て非なるデータフェッチ用のフックが必要となり、変数名が丸被りしてしまった時のものです。
書き方は変数名の後ろに「: 新しい変数名」とします。
この記法がTypeScriptの型付けと紛らわしく感じさせます。

```javascript
//カスタムフックによるデータフェッチ
  const { data, error, isLoading } = useGitHub();
```

```javascript
//ApolloClientによるデータフェッチ。重複する変数名は別名で対処。
  const {
    data: dataApollo,
    error: errorApollo,
    loading: loadingApollo,
  } = useQuery<ジェネリクスの型定義>(gqlのクエリ);
```
ちなみに以下はTypeScriptの型付けです。【変数名+：】というスタイルがややこしくないですか？
```javascript
//ちなみに以下の場合はstringをつけなくても型推論でstringが自動付与されます。
const aa: string = "hogehoge";
```
## TypeScriptの型付けとのすみ分け
TypeScriptの型付けを次のようにしています。
- フック側（右側）で全体に対して型付けをする。
- 個別の変数単位で型付けをする場合は、その変数を活用する次の段階で型付けをする。


## 個人的に思うこと
整理も兼ねて記事を書きましたが、正直ややこしいなーと思います。
が、記法はどんどん変わっていくのであまりこだわらずその時々に沿って対応していく所存です。
Google UXデザイン：バリュープロポジションを定義する

# はじめに

わたしが[Google UX Design Certificateで得られた素晴らしい体験][google]を、特に重要だと思われるポイントを小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ Google UX Design Certificateを受講してみてください。

[google]: https://qiita.com/mapami/items/7a0d0a3d4661c50f8bec

https://www.coursera.org/professional-certificates/google-ux-design

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/bddf54d2-10de-1b0d-0b37-21ba00cfb1df.png" width="800">

# バリュープロポジションとは

製品やアプリに出会って、「これじゃなきゃダメだ！」と思ったことはありませんか？ それは偶然ではありません! 

共感マップ、ペルソナ、ユーザーストーリー、プロブレムステートメント、仮説ステートメントなど、これまでに作成したものすべてを使って、ユーザーに「これじゃなきゃダメ！」と思わせるにはどうしたらいいでしょうか？

バリュープロポジションとは、

***<font color="MediumVioletRed">『消費者がなぜその製品やサービスを使うべきかをまとめたもの』</font>***　

です。これにより、ユーザーは現在入手可能な他の製品とは異なり、あなたが作ろうとしている製品を使う理由があることを保証することができます。

# バリュープロポジションを組み立てる

まず、次の2つの質問に答えるために、いくつかの調査をする必要があります。

***あなたの製品は何をするものですか？***
    - 製品がユーザーに提供するものを明確に説明すること。
   
***なぜユーザーが関心を持つのか？***
    - あなたの製品がどのようにユーザーのペインポイントに対応しているかを説明する。

### ステップ１： 製品の特徴と利点を説明する

大小さまざまな製品の素晴らしい特徴と利点をすべてリストアップしてください。我慢せず、思いつくものをすべてリストアップし、後で絞り込みましょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/c286d75d-9ea9-9df0-cee5-4deb3c55da31.png" width="700">

### ステップ2: 製品の価値を説明する

価値提案として特定するものは、ユーザーにとって有益である必要があります。この例では、犬の散歩アプリの場合、ユーザーインタビューの中で、
- アクセスしやすい
- 犬の散歩のプロの経験
- コスト
- 信頼性

という4つのカテゴリーの製品価値が特定されました。ステップ1で作成したリストは、この4つのカテゴリーに分類されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/2f1cc2e5-ac5e-e30b-7fb8-148fb41cd136.png" width="700">

この4つのカテゴリーに当てはまらず、ユーザーにとって本当の意味での「価値」が得られないものは横にどこかします。

- ペットのためのオーガニックグッズや新商品の毎月の配信
- 犬の散歩に特化（他の種類のペットは不可）
- ウォーカーの評価システム
- しつけのコツ

### ステップ3: これらの機能やベネフィットを、ユーザーのニーズと結びつける

目的は、ユーザーが求めてもいないクールな機能ではなく、<font color="Teal">ユーザーにとって本当に価値のあるものを見極める</font>ことです。

価値を見極めるには、作成したペルソナをもとに、それぞれのペルソナの最大のペインポイントを満たすバリュープロポジションをペアにしてください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/0e002aaf-638c-70da-20b4-65820be9d8f7.png" width="700">

### ステップ4: 公式バリュープロポジションリストを見直す

今度は、あなたの製品が提供するバリュープロポジションのリストを見直す番です。犬の散歩アプリの場合、先に作成したペルソナとマッチしたバリュープロポジションは以下のとおりです。

- ウォーカーのための徹底的なトレーニング
- ドッグウォーカーをドッグナニーにアップグレードし、定期的に散歩をさせる。
- ウォーカーの地理的な追跡
- カレンダー予約
- 遅刻時のキャンセル料
- 家の鍵を収納できる便利なロッカー
- 使いやすいアプリのデザイン

これで、バリュープロポジションのリストが完成しました。

### ステップ5: アプリの独自の価値提案を特定する

しかし、これらの機能やメリットの中には、競合他社も提供しているものがあります。では、自社製品が競合他社に差をつけるにはどうすればよいのでしょうか。それには、バリュープロポジションのリストから、競合他社も提供しているものを取り除きます。

製品の競合他社をチェックする方法の1つは、レビューを読むことです。レビューを低いものから高いものへと並べ替え、レビュアーが競合製品について何を共有しているかをよく調べます。ここに、競合の犬の散歩アプリについてのレビューがあります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/f225ff89-5d0c-f02a-af26-9d579f794379.png" width="700">

最大のペインポイントを特定することができますか？　口コミに共通しているのは、
- ドッグウォーカーにしっかりと仕事を覚えてもらうために、対面でのトレーニングが必要である
- ドッグウォーカーが信頼できる人である

他のドッグウォーカーアプリはこのニーズに応えていないので、私たちのアプリが提供できるユニークなバリュープロポジションです。

# 重要事項

バリュープロポジションについて知っておくべき最も重要なことの1つは、<font color="Teal">短く、明確で、要点</font>を押さえていることです。
wsl2で環境構築してみたけど2点で躓いたので。



環境
　Ubuntu


1. apt updateでエラーになる。
　→/etc/resolv.confを書き換えてから実行することで解決
　　nameserver 8.8.8.8

　参考URL：https://yoshinorin.net/articles/2020/08/22/wsl2-network-error/

2. curlコマンドでlaravelをインストールする際に
docker is not runningのエラーが発生する。
　→dockerが権限で利用できないらしい。
　　sudo usermod -aG docker $USER　を実行することで解決

　参考URL：https://zenn.dev/rhene/articles/docker-on-wsl2-without-docker-desktop
eccube4がdocker-composeで立ち上がらない【services.ec-cube.depends_on contains an invalid type, it should be an array】とか出る

## リポジトリからcloneしてきてそのままdocker-composeしても立ち上がらない
https://doc4.ec-cube.net/quickstart/docker_compose_install
公式より、そのまま実行。しかし

``` bash
ERROR: The Compose file './docker-compose.pgsql.yml' is invalid because:
services.ec-cube.depends_on contains an invalid type, it should be an array
```

と出て立ち上がらない。

### 調べた
https://stackoverflow.com/questions/71060072/docker-compose-depends-on-with-condition-invalid-type-should-be-an-array
どうやらこういうことらしい。
バージョンによって微妙に文法変更。つらい。

``` diff
@@ -7,8 +7,7 @@ volumes:
 services:
   ec-cube:
     depends_on:
-      postgres:
-        condition: service_healthy
+      - postgres
     environment:
       DATABASE_URL: "postgres://dbuser:secret@postgres/eccubedb"
       DATABASE_SERVER_VERSION: 14
```

このような感じに変更、これで動く。ただ、上記URLにもある通り3.9以上だとまた使えるみたい。
dateコマンドがGNU dateなのかBSD dateなのか見分ける方法

dateコマンドがGNU dateなのかBSD dateなのか見分ける方法です。

## 結論

```bash
date -d 0hour > /dev/null 2>&1 && echo "GNU date" || echo "BSD date"
```

※ 10/19追記: `--version` でも同じ結果が得られます。GNU dateには `--version` がありますが、BSD dateにはありません。

#### Linux系OS(Ubuntu)での実行結果

```bash
date -d 0hour > /dev/null 2>&1 && echo "GNU date" || echo "BSD date"
#=> GNU date
```

#### BSD系OS(macOS)での実行結果

```bash
date -d 0hour > /dev/null 2>&1 && echo "GNU date" || echo "BSD date"
#=> BSD date
```

※ シェルがcsh系だと `Ambiguous output redirect.` となります。

### 条件判定を逆(True側に BSD date を持ってきたい)場合

```bash
date -v+0H > /dev/null 2>&1 && echo "BSD date" || echo "GNU date"
```

## どういうことだってばよ

dateコマンドは、主にLinuxで動く [GNU date](https://linuxjm.osdn.jp/html/GNU_sh-utils/man1/date.1.html) と、主にmacOSで動く [BSD date](https://www.freebsd.org/cgi/man.cgi?date) でオプションが異なります。
特にLinuxとmacOSでは共にBashが動くこともあり、書いたBashスクリプトの99.9%は共通なのに、dateコマンドのせいでションボリというわけです。

※ "[date コマンドつらい](https://bearmini.hatenablog.com/entry/2017/06/19/115255)" なんて話もありますね。
※ top(1) も似たような話がありますね。

そのための判定基準を探したというのが経緯です。

### それぞれのdateの違い

最大の違いは、"今から2時間後" といった相対日時算出のオプションがあります。
GNU date は `-d` (`--date`) で、BSD date は `-v` で相対日時を算出します。

また、それぞれに対応するオプションが存在しないので、必ずどちらかで失敗するのを利用して見分けています。

### 実際にやるとしたら

date コマンドの実行結果 `$?` を見て分岐することになるでしょう。
下の例では変数に入れてますが、一回しか使わないのであれば `$?` の直接参照でも良さそうです。

```bash
date -d 0hour > /dev/null 2>&1 # inspect
readonly _IS_DATECMD=$([[ "$?" -eq 0 ]] && echo "GNU" || echo "BSD") # judge (likes ternary operator)

echo $_IS_DATECMD
if [ "$_IS_DATECMD" == "GNU" ]; then
  TWO_HOUR_AGO=$(date --date "2 hours ago") # GNU date option
else
  TWO_HOUR_AGO=$(date -v-2H) # BSD date option
fi
echo $TWO_HOUR_AGO
```

## あとがき

さて、私が見分けられるかな…？！ (お疲れ

「dateコマンドつらい」ブログは、同僚エンジニアのブログでした。めちゃんこ役立ちました！！あざます ogu++ ！！

EoT
AmazonLinux2においてremi-php80からphp8.0をインストールする

最初にremiのrepositoryを導入。
過去に導入済みであればskip。

```
yum install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
```

必要なpackageをinstall。

このとき、`--enablerepo=remi-php80`を指定する。
php8.1をinstallしたい場合は`--enablerepo=remi-php81`とする。

依存関係でエラーが出る場合は`--disablerepo=amzn2-core`を指定する。

```
sudo yum install --disablerepo=amzn2-core --enablerepo=remi-php80 php.x86_64 php-cli.x86_64 php-common.x86_64 php-devel.x86_64 php-fpm.x86_64 php-intl.x86_64 php-json.x86_64 php-mbstring.x86_64 php-pdo.x86_64 php-pecl-mcrypt.x86_64 php-pecl-pcov.x86_64 php-pecl-xdebug.x86_64 php-process.x86_64 php-soap.x86_64 php-sodium.x86_64 php-xml.x86_64  
```
Azure LogicAppsのforeachでまわしても思った順番で処理されていないとき

## 起こり
AzureのロジックアプリでInsightのクエリ結果からぐるぐる回してSlack通知にしていた。
ところが、クエリで出てきた順番とメッセージ内容が合わない。
（クエリ結果はソートされてるのに、メッセージは順番ばらばらになってる）

## 調べた

https://stackoverflow.com/questions/68128323/azure-logic-app-append-variable-within-for-each-is-incoherent
どうやらForeachは順番に処理されるのでなく、いくつか並行で行われるみたい。
なので上記URLの通りに並行実行を１にすると順番どおりにメッセージが出てきた。
【AWS認定試験】受験の流れと感想@ピアソンVUE【クラウドプラクティショナー】

## はじめに 
初めてクラウドプラクティショナーの試験を受けてきました！
ピアソンVUE(武蔵小杉テストセンター)も初めてのためせっかくなので記事を書いてみました。
AWSでは現在、AWS認定取得応援キャンペーンを実施中で、試験が通常金額の半額で受けられたためお得でした。

## 試験の予約について
- 24時間後以降の試験であればいつでも受験可能、つまり予約した次の日に試験を受けることもできる。
そのためスケジュールが非常に組みやすかった。
自分は50%割引のバウチャーが届いたあと最短で受験可能な試験を予約した。
(朝9時30分〜16時45分の間、15分刻みで申し込める)
- 名前をローマ字で求められるが、大文字小文字は多分どちらでもよい。
名前がクレジットカードと一致してないと申し込めない、みたいな記述があったからちょっと悩んだけど自分は頭文字のみ大文字にした。
特に問題なかったけどどっちが主流なのかは地味に気になる。
ちなみに試験画面で自分の名前を選択する際、他の人の名前を見たら４人中2人は全部大文字、残り２人は頭文字のみ大文字だった。

## 当日の注意点
- 身分証明書を2点持っていく（1つは顔写真入り）
    - 自分は保険証と運転免許証を提示した。
- 試験開始15分前には会場に到着しておく

## 当日の流れ
試験は一斉に始まるのではなく、パーティションで区切られたPCを使って各自試験を開始、終了する。
そのため、私は30分早くついたが<strong>試験開始時間を早めてもらえて待ち時間は発生しなかった。</strong>

- 試験開始15分前に会場に到着

- 受付で名前と受けにきた試験の種類を伝える
※試験の種類はAWSとだけ言えばOK。

- 身分証を2点提示

- 受付の人に用紙を渡されるので、署名(ローマ字)と時刻を用紙に記入
署名は姓と名の順序どうするのかな〜、これまた大文字かどっちがいいんだ？って思ったけど何も言われなかったから恐らくどっちでも大丈夫。
自分は姓＋名、頭文字のみ大文字にした。

- 受付に用紙を返却

- 顔写真を撮影して、デジタル署名する(ペンタブみたいなので漢字で名前を書いた)

- 荷物をロッカーに入れる、腕時計も持ち込み禁止！！
時間はPCに表示される。

- 試験の始め方の説明を受ける
指定の席に座ったらPCで自分の名前を選択して試験を開始してね〜、というような説明。
試験中のメモ用にA4サイズくらいのボードとペンを２本貸してもらった。
- 試験室に入室
***
- 指定の席に座ったら自分の名前を選択し、以下の内容を回答
    - 注意事項を読む
    - 試験を受ける
    - アンケートに答える
アンケートは５問くらいあった気がする。
問題文の日本語は分かりやすかったか、試験環境はどうだったかなど５段階評価で回答。
試験時刻はカウント方式で表示されているが、<strong>最後のアンケート回答時間も含めての時間なので終了時刻は一応注意。</strong>
- アンケート回答後すぐに合否が表示される
- 試験が終わったら退室
***
- メモ用のボードを受付の人に返却
- 用紙を渡されるのでもう一度署名と時刻を記入
- 受付の人から紙をもらって帰宅！
紙はAWS認定試験の受験ありがとね、試験の結果の反映まで最長５営業日かかるよ、という内容。
<strong>クリアファイルに入れて渡してくれたので、手ぶらで来ちゃうと手で持って帰ることになる、注意。</strong>
自分は小さいカバンだったので丸めて無理やり突っ込んで帰った。

## 試験中のPC画面について
- 右上に試験時間が表示される
- 試験時間の少し下に[後で確認する🏳]みたいなボタンがある
チェックした問題をあとでまとめて見直すことが可能。
便利なのにボタンがあること自体分かりづらかった、気づかない人もいるかも。
- 左上に[English]ボタンがある
押下すると試験問題が英語で表示されるので微妙な日本語訳は英語で確認するのがおすすめ。
- 画面下部に問題一覧に移動できるボタンと、[前へ][次へ]ボタンがある

## 所感
- 思っていたより複数選択問題が少なかった。
- AWS Well-Architectedは絶対覚えていくべし！
オペレーショナルエクセレンスやパフォーマンス効率は選択肢でしか出なかったが、信頼性については2,3問出た。
AWSのこの機能はWell-Architectedのどれに当てはまるか、ってのが２問は出た。

## その他出た問題
- IAMユーザーを８人分作成して、開発メンバーに割り当てる時、IAMポリシーはどうやって付与するか
- VPCのセキュリティの設定方法について（アクセスACL or セキュリティグループ or...)
- Amazon Cognitoの問題が1問出た
- リザーブドインスタンス、オンデマンドインスタンスの違いによるコスト最適化、2問は出た
- VPCを使わないサービスを選択肢から2つ回答
(例：EC2はVPCを指定する必要があるが、S3はVPCの中に置かないので指定不要)
- S3のストレージの種類
- 見積もりはどのサービスですればいいか（AWS Cost Explorer)
- 使用状況レポートをS3に保存　したい時に使えるサービス(Cost and Usage Report)
[コストと使用状況レポート用にS3バケットをセットアップする](https://docs.aws.amazon.com/ja_jp/cur/latest/userguide/cur-s3.html)
- コンプライアンスレポートが入手できるサービス(AWS Artifact)
- SSL/TLS証明書がデプロイできるサービス(AWS Certificate Manager)
- EC2インスタンスを停止したのに費用請求が来た時に考えられる原因(2つ選択)

その他まだまだありましたが終わりが見えないのでここまで・・・！
基本、対策本で勉強していれば大丈夫な問題ばかりだったと思います。

## 受験した夜にバッジ届きました
仕事が早い！
嬉しい〜〜♪
![スクリーンショット 2022-10-19 22.02.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2574529/50adba24-e4b9-1a04-951a-a95cd3f1fd92.png)

閲覧ありがとうございました。
駅メモイベントで最適化

## 駅メモで最適化
https://twitter.com/ekimemo/status/1577176695974551556

今の駅メモのイベント。

「材料を集めて美味しいご飯を作るとポイント獲得」のところで、最適化ができそうでした。

## ルール概要

TODO：画像を貼る

- ゲームを進めると秋っぽい食材が手に入る。
    - 薪、栗、皿、魚、きのこ、ぶどう、調味料、あけび、まつたけ
- 9種類の材料の組み合わせで作る5種類のメニューがある
    - 焼き栗=薪+栗、魚の塩焼き = 薪+栗+魚、etc...
- メニューを1つ作成すると、材料が1つずつ消費されて、当該メニューに割り当てられたポイントが獲得できる
    - 焼き栗は30ポイント、魚の塩焼き120ポイント、etc...


## 最適化の定式化
変数を以下のように定義して、
```math
\begin{align}
x_i &= \text{(メニュー$i$を作る個数)}, \\
y_{ij} &= \text{(メニュー$i$が材料$j$を使うなら1)}, \\
z_{j}  &= \text{(材料$j$の個数)}, \\
P_{i}  &= \text{(メニュー$i$を1つ作る時のポイント)},
\end{align}
```

以下のように定式化できます。
```math
\begin{align}
\max & \sum\limits_{i=1..5} P_i x_i, \\
\mathrm{s.t} \ \  x_i &>=0, \\
                \sum\limits_{i=1..5} x_i y_{ij} &<= z_j \ (j = 1..9)
\end{align}
```

## 実行環境
ColaboratoryとPulpで最適化します。↓を読みましょう。
https://www.y-shinno.com/pulp-intro/
よくわかりました。

## 実装
TeXをいい感じに書くよりも、実装する方が簡単です。

https://colab.research.google.com/drive/1CRZrhwshlqh7_94fqqv1jukC8YeOM0KH?hl=ja


```python
!pip install pulp
import pulp
# 問題の定義
problem = pulp.LpProblem(name="EKIMEMO_2022_Autumn", sense=pulp.LpMaximize)

# 変数の定義
A = pulp.LpVariable(name = "Yakiguri", lowBound = 0, cat="Integer")
B = pulp.LpVariable(name = "Shioyaki", lowBound = 0, cat="Integer")
C = pulp.LpVariable(name = "Kinoko-Jiru", lowBound = 0, cat="Integer")
D = pulp.LpVariable(name = "Moriawase", lowBound = 0, cat="Integer")
E = pulp.LpVariable(name = "Matsutake-Gohan", lowBound = 0, cat="Integer")

# 目的関数(得られるスコア)
problem += 30 * A + 120 * B + 200 * C + 500 * D + 700 * E
  
# 制約条件の定義
problem += A+B+C  +E <= maki ## maki: 材料「薪」の個数
problem += A+B  +D   <= kuri ## kuri: 材料「栗」の個数
problem +=     C  +E <= sara ## sara: (以下同様)
problem +=       D   <= budou 
problem +=   B  +D   <= sakana
problem +=         E <= chomiryo
problem +=     C  +E <= kinoko
problem +=       D   <= akebi
problem +=         E <= matsutake

# 解く
status = problem.solve()
print(pulp.LpStatus[status])

# 結果表示
print("Result")
print("Yakiguri:", A.value())
print("Shioyaki:", B.value())
print("Kinoko-Jiru:", C.value())
print("Moriawase:", D.value())
print("Matsutake-Gohan:", E.value())
```

## UI
https://qiita.com/john-rocky/items/e5802cdd15dc2e34cb84
これを参考に、今持っている材料の個数を入力するためのフォームを作りました。便利ですね。

![スクリーンショット 2022-10-19 21.42.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5897/47ee2a23-cd47-d05e-6c98-5a024b03654d.png)

## 解く
解きましょう
![スクリーンショット 2022-10-19 21.45.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5897/2e9e6c7c-a120-f4fa-0716-93ba388d7a54.png)
解けました。材料足りないので、解がつまらんです。

## 今後の取り組み

- Webアプリにする
- pulpの目的関数や制約を、for文で書く
- ゲームを頑張って材料を集める
二等辺三角形「岐阜大学応用生物科学他2022年度数学第5問」をsympyでやってみたい。

①距離計算で、いい方法がありませんか？距離計算は厳しいですか？
②定理に従って、計算しかありませんか？

オリジナル 

https://www.youtube.com/watch?v=_647a4Oce6I


上と同じです。大学入試数学問題集成＞【5】

https://mathexamtest.web.fc2.com/2022/202210441/2022104410100mj.html#q-0105


# sympyで
Aを原点にしました。
```python
from sympy import *
def cosd(deg):
    return cos(deg*pi/180)
def sind(deg):
    return sin(deg*pi/180)
def tand(deg):
    return tan(deg*pi/180)
def herons(a, b, c):
    s = (a+b+c) / 2
    return sqrt(s*(s-a)*(s-b)*(s-c))
AB,AC=2,2
BAC=30
CBE=60
A=Point(0,0)
B=Point(AB*cosd(270-BAC/2),AB*sind(270-BAC/2))
C=Point(AB*cosd(270+BAC/2),AB*sind(270+BAC/2))
D=Line(A,B).intersection(Line(C,C+Point(-1,1          )))[0]
E=Line(A,C).intersection(Line(B,B+Point( 1,1*tand(CBE))))[0]
F=Line(C,D).intersection(Line(B,E))[0]
print("# ○(1)ABC",(Rational(1,2)*(C.x-B.x)*(-B.y)).simplify())
print("# △(2)BC ",sind(75),C.x-B.x)
print("# ✕(3)BD ",B.distance(D).simplify(),float(B.distance(D)),(6-2*sqrt(3))/3,float((6-2*sqrt(3))/3))
print("# ✕(4)CE ",C.distance(E).simplify(),float(C.distance(E)),3-sqrt(3),float(3-sqrt(3)))
print("# ○(5)CF ",C.distance(F).simplify())
print("# ✕(6)DEF",       herons(D.distance(E),E.distance(F),F.distance(D)).simplify() , \
                   float(herons(D.distance(E),E.distance(F),F.distance(D)).simplify()), \
                  (42-24*sqrt(3))/6,float((42-24*sqrt(3))/6))
# ○(1)ABC 1
# △(2)BC  sqrt(2)/4 + sqrt(6)/4 -sqrt(2) + sqrt(6)
# ✕(3)BD  2*sqrt(12 - 6*sqrt(3))/3 0.8452994616207484 2 - 2*sqrt(3)/3 0.8452994616207484
# ✕(4)CE  sqrt(12 - 6*sqrt(3)) 1.2679491924311228 3 - sqrt(3) 1.2679491924311228
# ○(5)CF  -6 + 4*sqrt(3)
# ✕(6)DEF sqrt(97 - 56*sqrt(3)) 0.07179676972449082 7 - 4*sqrt(3) 0.07179676972449082
```

# 参考

https://qiita.com/mrrclb48z/items/c2e38d2717b1bc0d7600
GASを使ってSlackに好きな動画をお知らせしてくれるBotを作ってみる

# はじめに
今回はGASを使ってスクレイピングした情報をSlackに自動的に飛ばしてもらうBotの作成をしてみます。
この実装ではスクレイピングに限らずGASとSlackの連携ができるようになるのでスプレッドシートの情報を使ったり、その他のツール作成にも役に立つかと思います！



# 実装開始

## Slack側の手順

まずはSlackにアクセスするために必要なAPIの設定を行います。
こちらのSlack APIのページにて以下の手順通り操作してみてください。

### 1. Create New App(緑色のボタン)→From Scratchを選択する
![スクリーンショット 2022-10-19 21.06.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918805/09764864-b13e-c047-b2e2-ac0d2667d913.png)

### 2. Name app & choose workspace → プロジェクトの命名と自身が使用しているチャンネルを選択する
![スクリーンショット 2022-10-19 21.07.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918805/46f86406-a997-cded-296c-359a232b5380.png)


これでbotを動かすためのアプリケーションが作成されました。
続いてはこのアプリにアクセスできるよう認証周りの設定です。

### 3. OAuth & Permissionsを選択する
![スクリーンショット 2022-10-19 21.11.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918805/2747a33a-32ec-dce5-ee44-98873008597d.png)

### 4.Scopesにある以下三つの権限を追加して保存する
![スクリーンショット 2022-10-19 21.13.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918805/90bb8427-4d53-580c-fbcd-817b573c14c2.png)

### 5. 左のSettingからAppHomeを選択しYour App’s Presence in SlackにてEditボタンを押すとbotの命名ができるので適当に編集する

### 6. Install Appから発行されたトークンをコピーしておけば完了！！
![スクリーンショット 2022-10-19 21.23.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918805/27d1e850-8d3f-1245-4c05-f4f63ed45281.png)


これでSlack側の設定が終わりです！！

## GAS側の手順
Slackへの通信ができるライブラリが用意されているのでそれのインストールから始めます！

### 1. GoogleAppScriptを開き、ライブラリタブを選択する
### 2. SlackAppというライブラリをインストールする
![スクリーンショット 2022-10-19 21.27.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918805/b3e03c3f-2227-eba7-181b-380d0bf46c26.png)

スクリプトIDに以下を入れて検索してください

```
1on93YOYfSmV92R5q59NpKmsyWIQD8qnoLYk-gkQBI92C58SPyA2x1-bq
```

### あとはコードを書くだけ！

```js
function sendMessage(url) {
  const token = ''; // Slackの設定画面からコピーしたトークンを変数に入れる
  const slackApp = SlackApp.create(token);
  const channelId = ''; // 通知を送りたいチャンネル名を変数に入れる
  const message = 'Hello World' // 通知したいメッセージを変数に入れる
  slackApp.postMessage(channelId, message);
}
```
こんな感じで書いてあげればこの関数を呼び出した時に自身のSlackにメッセージが届きます！！

## 応用(?)
ここからはそれを自動、定期的に通知させるためにGASで定期実行を設定します。

### 画面左にある時計マークのトリガーを選択し時間手動型で関数を実行する
![スクリーンショット 2022-10-19 21.34.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918805/d40313dc-1181-0a84-97ec-48d5e94069e7.png)

この画面で自分の好きなタイミングで実行するよう設定すればどんなタイミングでも勝手にこの関数が実行されるので自動かつ定期的に通知したいものが送られてくるようになります！

私はこの機能を使用して友人と話すチャンネル内に定期更新される動画サイトの最新動画をURLとして拾ってきて通知する仕組みを作りました！
スクレイピングの方法に関しては「GAS Parser」とかで調べてみるとわかりやすいと思います！
これで業務改善や仕事を楽にする試みとして使ってみてはいかがでしょうか？　では！！
Rustでベクタの配列(array of vec)を作りたかった 


# 概要
タイトル通り、ベクタを要素に持つ配列を作りたかったが、エラーに悩んだのでメモ。
rustは配列を宣言すると、初期化することが求められるが、その初期化がうまくいかなかった。

# やりたいこと
```rust:main.rs
struct  Point{
    x: f32, 
    y: f32, 
    z: f32, 
}

fn main() {
    let array: [Vec<Point>; 100] = [vec![]; 100];
    // Error : the trait bound `Vec<Point>: Copy` is not satisfied
}
```
```Point```構造体を確保するベクタを要素として、配列に確保したかった。

- 座標情報を持つ```Point```構造体
    - x, y, zの座標情報を持つ
- 格納するベクタ```Vec<Point>```
    - 点群データを管理したい -> **要素数が未知のため、ベクタで確保**
- そのベクタを要素とする要素数```100```の配列
    - 座標により、100つの格子分けをしたかった
    - 格子別に処理を行う際、配列に確保されていれば便利だと考えた

# 解決策
# 1 : ```Default::default()```を使う
```rust:main.rs
fn main() {
    let array: [Vec<Point>; 10] = Default::default();        
    // これはOK

    // let array: [Vec<Point>; 100] = Default::default();        
    // これはNG (要素数が32を超えるため)
}
```
手っ取り早く解決するならこれ。
**ただし要素数が```32```を超えるとNGの模様。**
他にはrustのバージョンによって動作しないらしい。
自分の場合、要素数を```100```にしたかったため、別の方法を探した。


# 2 : 要素、サイズを ```const``` で宣言する **(非推奨？)**
**初期化はできるが要素の追加ができないため、ほぼ意味のないコードになっている**
```rust:main.rs
fn main() {
    const INIT_ELEMENT: Vec<Point> = vec![];
    const ARRAY_SIZE: usize = 100;
    // 初期化に使用するパラメータをあらかじめ const で宣言
    let array: [Vec<Point>; ARRAY_SIZE] = [INIT_ELEMENT; ARRAY_SIZE];
    // これでOK
}
```
要素数に縛られることなく初期化したいならこれ。
配列を初期化する際、**要素の型** (ここでは```Vec<Point>```)、**要素数** (```usize```) を```const```であらかじめ宣言しておき、それを使う。
ただしこちらもバージョンによって動作しないらしい。

追記
**```const```で```vec```を確保しているので、```push```ができない。何やってんだこのコード...**

# 3 : ```unsafe``` を使い、初期化する
```rust:main.rs
fn main() {    
    // 1
    const SIZE: usize = 100; 
    let mut uninit_array: [std::mem::MaybeUninit<Vec<Point>>; SIZE];
    // 変数が初期化されないことを宣言する

    uninit_array = unsafe{
        std::mem::MaybeUninit::uninit().assume_init()
    };
    // 配列分確保のみをする    
    // 2
    for element in &mut uninit_array{        
        unsafe{std::ptr::write(element.as_mut_ptr(), vec![])};
        // 各要素を vec![] で初期化
    }
    // 3
    let mut array = unsafe{std::mem::transmute::<_, [Vec<Point>; SIZE]>(uninit_array)};            
    // std::mem::MaybeUninit<Vec<Point>> 型から、Vec<Point> に変換する
}
```

どうやっても ```safe Rust``` では再現できない気がしたので、 ```unsafe Rust``` で作ってみた。
手順としては、

1. ```std::mem::MaybeUninit<T>```を使い、配列を初期化なしで宣言する。**C で言う```int array[10];```みたいなもの**
1. その配列を ```for``` ループで回し、各要素に初期価値を代入する
1. ```std::mem::transmute```を使い、```std::mem::MaybeUninit<T>``` を ```<T>``` の配列に変換する


という風に、Cライクに配列を初期化することで対応した。
このようなことでも```unsafe```を使わないといけないので、メモリ管理を意識しないといけないと分かった。

# 参考
https://doc.rust-lang.org/std/default/trait.Default.html
https://doc.rust-lang.org/nightly/std/mem/union.MaybeUninit.html#initializing-an-array-element-by-element
https://www.joshmcguigan.com/blog/array-initialization-rust/
Window最大化　C++

# 最大化ボタンで最大化したい
PCでフルスクリーンではなく、ウィンドウモードでゲームを作りたいと思いました。
ウィンドウサイズはSCREEN_WIDTH, SCREEN_HEIGHTの値で変更できましたが、
PCのサイズ1920x1080にすると、タスクバーと被って大きすぎます。
私は普段1280x720してウィンドウモードを最大化してゲームをプレイすることが多いです。
そこで、今回は私が作っているゲームにも実装しました。
# WS_MAXIMIZEを追加する
winmain関数の一部です。
CreateWindowの第三引数にWS_MAXIMIZEを追加します。
```WinMain.cpp
INT WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, LPWSTR cmd_line, INT cmd_show)
{
	RECT rc = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
	AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
	HWND hWnd = CreateWindow(_T("Sample"), _T(""), WS_OVERLAPPEDWINDOW ^ WS_MAXIMIZE ^ WS_THICKFRAME | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, instance, NULL);
	ShowWindow(hWnd, cmd_show);

}
```
【Git】保護ブランチをCLIで設定する方法

## 保護ブランチをCLIで設定する

以下を実行するとCLIで保護ブランチを設定できます。

`OWNER_NAME`と`REPO_NAME`は適宜変更が必要です。

``` protect-branch.sh
owner="OWNER_NAME"
repo="REPO_NAME"
repositoryId="$(gh api graphql -f query='{repository(owner:"'$owner'",name:"'$repo'"){id}}' -q .data.repository.id)"

gh api graphql -f query='
mutation($repositoryId:ID!,$branch:String!,$requiredReviews:Int!) {
  createBranchProtectionRule(input: {
    repositoryId: $repositoryId
    pattern: $branch
    requiresApprovingReviews: true
    requiredApprovingReviewCount: $requiredReviews
    isAdminEnforced: true
  }) { clientMutationId }
}' -f repositoryId="$repositoryId" -f branch="main" -F requiredReviews=1

```

実行後は以下のように設定され`main`ブランチには直接`push`できなくなります。

![image221019_204133.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/1b99abce-e6e7-f189-b5c4-abdc02535297.png)

上記以外の設定をしたい場合には以下のページを参照して設定を追加します。

https://docs.github.com/en/graphql/reference/input-objects#createbranchprotectionruleinput
Springs,ボッシュ自動車handbook 11版(24)p.362

Springs, ボッシュ自動車handbook 11版(24)

人生で影響を受けた本100冊。
https://qiita.com/kaizen_nagoya/items/16af53acbb147a94172e

に掲載した本のうち、「新人プログラマ応援」企画で「私の推薦書３３冊」として３３冊紹介した。

新人プログラマ応援　私の推薦書３３冊
http://qiita.com/kaizen_nagoya/items/98c62f051dbdb4f8aca2
残りの６７冊から、順に過去の読書感想を引用し、新たな読書感想文を追記する。

 <この項は書きかけです。順次追記します。>


# ボッシュ自動車ハンドブック version 11, 2022

Automotive Handbook  May 2, 2022

https://www.amazon.co.jp/dp/1119911907/

ボッシュ自動車handbook(英語)11版(0)＜エンジニア夏休み企画>【読書感想文】

https://qiita.com/kaizen_nagoya/items/dfa35aa6f669e5df983e

# Springs
p.362

## Basic principles 
### Spring characteristics

### Spring damping

### Spring combinations
## Metal springs 
### Spring subjected to tensite and compression stress
### Spring subjected to bending stress
### Spring subjected to torsional stress

# Reference
[1] DIN EN 13906
DIN EN 13906-1:2013 Cylindrical helical springs made from round wire and bar - Calculation and design - Part 1: Compression springs

DIN EN 13906-2:2013 Cylindrical helical springs made from round wire and bar - Calculation and design - Part 2: Extension springs

DIN EN 13906-3:2014 Cylindrical helical springs made from round wire and bar - Calculation and design - Part 3: Torsion springs

[2] DIN EN 10089:2003 Hot rolled steels for quenched and tempered springs - Technical delivery conditions

[3] DIN EN 10132 Cold rolled narrow steel strip for heat treatment - Technical delivery conditions

part1, part2, part3, part4を統合。 

[4] DIN 2092:2006 Disc springs - Calculation

[5] DIN 2093:2013 Disc springs - Quality specifications - Dimensions

[6] DIN 2091:1981 Circular section torsion bar springs; Calculation and design



 
# 自己参考資料(self reference)

ボッシュ自動車ハンドブック 

https://qiita.com/kaizen_nagoya/items/8e330ce57880f04d71d9
ボッシュ自動車handbook(英語)10版　目次

https://qiita.com/kaizen_nagoya/items/57c799ff544c96efdea9

自動車工学とBosch Vehicle Handbook

https://qiita.com/kaizen_nagoya/items/d13ff6b0e4d7c8907c0d

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴(document history)
ver. 0.01 初稿 　20221019
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
####  Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
Amazon EKSでHelmを利用する

# はじめに
Amazon EKSでHelmを利用する方法をまとめます。
Mac環境を想定しています。

# 環境設定
1.  Helmのインストール

    ```sh
    brew install helm
    ```

1.  Helmのバージョンを確認する

    ```sh
    helm version --short | cut -d + -f 1
    ```

1.  公式の [Helm Stable](https://charts.helm.sh/stable) チャートリポジトリを追加する

    ```sh
    helm repo add stable https://charts.helm.sh/stable
    ```

1.  [bitnami](https://charts.bitnami.com/bitnami) チャートリポジトリを追加する

    ```sh
    helm repo add bitnami https://charts.bitnami.com/bitnami
    ```

1.  リポジトリを更新する

    ```sh
    helm repo update
    ```

1.  リポジトリでチャートを検索する

    ```sh
    # 例: helm search repo nginx
    helm search repo ${キーワード}
    ```

# 実行環境の準備
1.  AWS CLIの設定
[AWS CloudFormationを動かすためのAWS CLIの設定](https://qiita.com/miyabiz/items/fed11796f0ea2b7608f4)を参考にしてください。

1.  EKSクラスタの構築
[Macでeksctlを利用してAmazon EKSのクラスターを構築する](https://qiita.com/miyabiz/items/75f83237795b0b7d52bd)を参考にしてください。

1.  EKSのコンテキストの設定
[MacにてAmazon EKSの設定をする](https://qiita.com/miyabiz/items/b98d145cedb35dab9524)を参考にしてください。


# Helmを利用する

※事前にKubernetesクラスターのコンテキストの設定をします。

1.  チャートをインストールする
    ```sh    
    # 例: helm install nginx bitnami/nginx
    helm install ${リリース名} ${チャート名}
    ```

1.  インストールしたチャートを確認する
    ```sh    
    helm list
    ```

1.  インストールしたチャートを確認する
    ```sh
    # 例: helm status nginx
    helm status ${チャート名}
    ```

1.  アップグレードする
    ```sh    
    # 例: helm upgrade nginx bitnami/nginx
    helm upgrade ${リリース名} ${チャート名}
    ```

1.  チャートの履歴を確認する
    ```sh    
    # 例: helm history nginx
    helm history ${リリース名}
    ```

1.  ロールバックする
    ```sh    
    # 例: helm rollback nginx 1
    helm rollback ${リリース名} ${REVISION番号}
    ```

1.  インストールしたチャートのマニフェストを取得する
    ```sh    
    # 例: helm get manifest nginx
    helm get manifest ${リリース名}
    ```

1.  インストールしたチャートのValuesを取得する
    ```sh    
    # 例: helm get values nginx
    helm get values ${リリース名}
    ```

1.  チャートをアンインストールする
    ```sh    
    # 例: helm uninstall nginx
    helm uninstall ${リリース名}
    ```

# 参考
[Amazon EKS での Helm の使用](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/helm.html)
Android 通知バイブレーションのパターンを変更する

# はじめに

通知チャンネルごとの設定で通知バイブレーションのパターンを変更することができます。
日本語の記事が思いのほか少なかったのと、ドキュメントに記載のないちょっとしたポイントがあったのでメモをまとめてみます。

# サンプル

以下のアプリで試せます。

https://github.com/kmachida12345/BuzzBuzz

# パターンを設定する

[setVibrationPattern()](https://developer.android.com/reference/android/app/NotificationChannel#setVibrationPattern(long[]))メソッドで設定します。

createNotificationChannel()で通知チャンネルを生成する前に設定される必要があります。
アップデートでバイブレーションパターンが変わるようにしたい場合などは、すでにある通知チャンネルを消去して新しく生成してやる必要があります。
引数vibrationPatternに設定した値は、[インターバル、鳴動時間、インターバル、鳴動時間・・・] と交互に使われます。

# さいごに

やってみるとかなり簡単です。
変更するときはいろいろ試して心地いいパターンを検討してみるのがよいと思います。
セレクトボックスのchangeイベントで遷移した場合のブラウザバックの制御

# はじめに

セレクトボックスの`change`イベントで
ページ遷移するよう実装した場合のブラウザバック時の制御についてまとめました

# 問題
セレクトボックスを変更した(changeイベント)でページ遷移をした場合、
ブラウザバックでセレクトボックスの選択が初期化されない

## 例
```html
...
<select class="target">
    <option class="option1" value="1">1</option>
    <option class="option2" selected value="2">2</option>
    <option class="option3" value="3">3</option>
</select>
...
```

```js
const target = document.querySelector(".target");

target.addEventListener('change', function(e) {
    // 任意のURLに遷移
});
```

1. ページアクセス時はセレクトボックスは `.option2`が選択されている状態
1. セレクトボックスの値を変更 `.option2 → .option1`
1. ページ遷移
1. ブラウザバック
1. セレクトボックスは`.option1`が選択された状態になってしまう

#### .option2が選択されている状態にしたい

# 対策

**Window: pageshow** イベントを利用する

## pageshow イベントとは

https://developer.mozilla.org/ja/docs/Web/API/Window/pageshow_event

>pageshow イベントは、操作によってブラウザーがウィンドウの文書を表示したときに Window へ送られます。これには以下のようなものがあります。
>
>最初にページを読み込んだとき
>同じウィンドウまたはタブの中で、他のページからそのページへ移動してきたとき
>モバイル OS で凍結されたページを復元したとき
>ブラウザーの進む、戻るボタンを利用してこのページに戻ったとき

## サンプル
```js
// const target = document.querySelector(".target");


window.addEventListener('pageshow', function() {
    target.value = target.querySelector('.target option[selected]').value);
});
```

## サンプル ※jQuery利用
```js
$(window).on('pageshow', function() {
    $('.target').val($('.target option["selected"]').val());
});
```
※`option:selected`の書き方だと、`.option1`の値が取得されてしまう

# さいごに
`pageshow`イベントはあまり馴染みがなかったですが、
このイベントを利用することで対応できました
SudachiPyで発音を取得【Python】

# 概要
Sudachiで発音を取得する関数を作りました。
# 背景
形態素解析ライブラリのうちMeCabでは発音を取得できますが、[Sudachi](https://github.com/WorksApplications/SudachiPy#dictionary-edition)では「読み」のみで発音は取得できません。
そこで「読み」の結果を少し調整して、発音（っぽい文字列）を取得する関数を作りました。
# 実装
ライブラリをインストールします。
辞書はなんでもよいですが、今回はfullでやってみます。

```
pip install sudachipy
pip install sudachidict_full
```
関数を作ります。以下がポイントです。
* 表層系、読み、品詞はそれぞれ`surface`、`reading_form`、`part_of_speech`メソッドで取得可能
* 記号の発音は取得しない。品詞が「補助記号」かどうかで判定
* 助詞の「は」「へ」は「ワ」「エ」になおす

```Python
from sudachipy import tokenizer
from sudachipy import dictionary

tokenizer_obj = dictionary.Dictionary(dict="full").create()
mode = tokenizer.Tokenizer.SplitMode.A

def get_word_pronunciation(text):
  tokens = tokenizer_obj.tokenize(text ,mode)
  prons = []
  for token in tokens:
    pron, surface, pos = token.reading_form(), token.surface(), token.part_of_speech()[0]
    if pos == "補助記号": #記号は発音しないので結果に含めない
      continue  
    if surface == "は" and pos == "助詞": #助詞の「は」は「わ」になおす
      pron = "ワ"
    elif surface == "へ" and pos == "助詞": # 助詞の「へ」は「え」になおす
      pron = "エ"
    prons.append(pron)
  return prons

print(get_word_pronunciation("吾輩は猫であるaseaewf123。「どこへ」いきますか"))
```

```
['ワガハイ', 'ワ', 'ネコ', 'デ', 'アル', 'aseaewf', 'イチニサン', 'ドコ', 'エ', 'イキ', 'マス', 'カ']
```
gdal2tilesでGeoTIFFをラスタタイルに変換

## 今回やりたいこと
GeoTIFFをgdal2tilesを用いてXYZタイルに変換する。

## 動作環境
- MacBook Pro (13-inch, M1, 2020) macOS Monterey バージョン12.6
- Python 3.10.4
- GDAL 3.5.2, released 2022/09/02

## GDALのインストール
（すでにPCにGDALをインストールしている人は飛ばしていただいて結構です。）

筆者はMacを使用しているので、以下のQiitaを参考にGDALのインストールを進めました。
https://qiita.com/mits003/items/8684603da4a8fc4a367a

上記の記事は ##インストール方法 の部分で記載されているtarコマンドの実行部分で以下の通りに記述されています。
```
tar -xpzf GDAL-3.3.0.tar.gz
```
GDALのバージョン数の記載は自身がダウンロードしたものによりますので、単純にコピペせずに以下の通りにコマンドを実行しましょう。

```
brew install gdal
pip download GDAL
tar -xpzf GDAL-<GDALのバージョン>.tar.gz  
cd GDAL-3.3.0
python setup.py build_ext --gdal-config /usr/local/Cellar/gdal/<GDALのバージョン>/bin/gdal-config
python setup.py build
python setup.py install
```

## gdal2tilesのインストール
[公式Webページ](https://pypi.org/project/gdal2tiles/#:~:text=libgdal%2Ddevel%20packages.-,Installation,-To%20install%20gdal2tiles)を参考にして以下のコマンドを打ちます。

```
pip install gdal2tiles
```

## gdal2tilesを用いてXYZタイル化
以下のQiita記事を参考にしました。
https://qiita.com/Kanahiro/items/4b5f8db5743c69741220

```
gdal2tiles.py source.tif target_dir -z3-18 --xyz --processes=4
```

"--xyz"を指定しないと、TMS形式で出力されてしまいます。 "--processes"で使用するプロセス数を決めます。今回は4で設定しました。
2.53 GBのGeoTIFFをXYZタイル化するのに約10分程度かかりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467847/b0ce885a-252c-55c5-73d3-7cb9c9a62123.png)
思えばちゃんと理解していなかったJavaScirpt関連基礎知識 17問


初めは動かすことだけを意識し過ぎていて、当時は何となく使うことも多かった.


全部答えられますでしょうか?
簡単なもの多いですが、力試しにどうぞ.

※参照リンク貼っていますが、怪しいブログやプログラミングスクールは極力抜いています.
含んでいたら教えてください.

# JavaScript関係なく

### 0.1 + 0.2 == 0.3はFalse

英語 : Why 0.1 + 0.2 ≠ 0.3 in JavaScript
https://javascript.plainenglish.io/why-0-1-0-2-0-3-in-javascript-d7e218224a72

日本語 : Pythonで、0.1+0.1+0.1==0.3 がFalseなのは何故でしょうか？
https://jp.quora.com/Python%E3%81%A7-0-1-0-1-0-1-0-3-%E3%81%8CFalse%E3%81%AA%E3%81%AE%E3%81%AF%E4%BD%95%E6%95%85%E3%81%A7%E3%81%97%E3%82%87%E3%81%86%E3%81%8B

# JavaScript文法まわり
### そもそもjavaScriptのCallbackはどう動く?
英語 : 
How JavaScript works: Event loop and the rise of Async programming + 5 ways to better coding with async/await
https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with-2f077c4438b5

日本語 : 
【概要速修】JavaScriptはどう動く?仕組みをさっと知りたい【初心者向け】
https://youtu.be/a948hCqo324

### console.logの内容がおかしい(Chrome等々)
英語 : Why Chrome’s Developer Console Sometimes Lies
https://medium.com/young-coder/why-chromes-developer-console-sometimes-lies-9487e45e91ae

### const vs let vs varの違い

Var、Let、Const – その違いとは？
https://www.freecodecamp.org/japanese/news/var-let-and-const-whats-the-difference/

【JavaScript】var / let / const を本気で使い分けてみた
https://qiita.com/cheez921/items/7b57835cb76e70dd0fc4

### nan vs undefined vs null

undefinedとnullの違い
https://typescriptbook.jp/reference/values-types-variables/undefined-vs-null

NaN
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/NaN

### async と await

async/await 入門（JavaScript）
https://qiita.com/soarflat/items/1a9613e023200bbebcb3

### Promise

4歳娘「パパ、Promiseやasync/awaitって何？」〜Promise編〜
https://qiita.com/Yametaro/items/0d29df53d9ac2a779595

### onClickへの関数の渡し方とどう動くか

英語 : onClick anonymous function with arguments vs onClick(function(arguments))
https://stackoverflow.com/questions/63455337/onclick-anonymous-function-with-arguments-vs-onclickfunctionarguments?noredirect=1&lq=1

### import と requireの違い

jsのimportとrequireの違い
https://qiita.com/minato-naka/items/39ecc285d1e37226a283

### カリー化って何?

カリー化 | 中上級者になるためのJavaScript - kenju
https://kenju.gitbooks.io/js_step-up-to-intermediate/content/content/part03/currying.html

### windowって何?

windowオブジェクト
https://qiita.com/tsukishimaao/items/39d22fd9178546d6cdeb

### use strict;

モダンなモード, "use strict"
https://ja.javascript.info/strict-mode

### this?bind?

英語 : What is the use of the JavaScript 'bind' method?
https://stackoverflow.com/a/10115970

日本語 : 【JavaScript】Function.prototype.bind() とthis束縛の歴史
https://inside.estie.co.jp/entry/javascript-bind-this

### globalThisとは?

globalThis
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/globalThis


### クロージャー

JavaScriptでクロージャ入門。関数はすべてクロージャ？
https://qiita.com/takeharu/items/4975031faf6f7baf077a



# JavaScriptの周辺知識

### ECMA Scriptって何? ES6って?

ECMAScript
https://ja.wikipedia.org/wiki/ECMAScript

### V8エンジン

V8 エンジンについて
https://zenn.dev/estra/books/js-async-promise-chain-event-loop/viewer/e-epasync-v8-engine
人に何かお願いごとをする時の話


自身も気をつける！という意味でここに書いておく。

ITの仕事のことだけじゃないけれど。。
人に何か頼むとき、
•たのむ人
•たのまれる人
二役が出てくる。
頼まれた通りやってないと、たのむ側が怒り出すというのはあるあるだと思う。
このときたのまれる側だけでなく、たのむ側も工夫できることはたくさんあるなあと思う😆

きょう仕事のなかで、あるAさんのお願いテストをボクとBさんでやることになった。
テストする際に参考にする資料の説明があいまいなところがあり、BさんがAさんの思っていた通り検証できてないということで怒り出した😅

ただこの時、Aさんも下のような工夫ができたのでは、と思った。
•人によってとらえ方が変わる部分は、お願いする前にかみ砕いて説明。
•テストの最初の試験だけいっしょにやる
•Aさんの確認用に、試験書にBさんがどうやってテストしたか、書ける場所を用意する

ぼくも気をつけようと思いました😆
TradingViewのアラート機能から自動売買botを作る その１

# 目的
* できる限り簡単にシステムトレードを行いたい
* できる限り安くシステムトレードを行いたい
　GMOコインのAPIを使用して発注する、APIKey等は事前に用意が必要です。

# 技術選定
【TradingView】
TradingView ではストラテジーテスターを使用することで
バックテストを簡単に行うことができる。
またアラート機能でWebhookを使用することができる。
**※現状は有料プランしかWebhookは使用できない**

【AWS APIGateway,lambda】
Webhook(アラート発生)➡APIGateway➡lambda　
という流れで自動売買が可能になる。
Zapier( https://zapier.com/ )というWebhookを受け取れるサービスの使用も考えたが、
料金が円安で地味に高いので、一番料金のかからなさそうなAWSを使用することとした。

## lambdaの作成
まずlambdaの作成を行います。
今回はpython3.7で作成を行いました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703168/5de8746e-f7e5-8333-6231-2b475f81082c.png)

pythonコード　デプロイするのを忘れない。
~~~
 #!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging
import requests
import json
import hmac
import hashlib
import time
from datetime import datetime as dtOrder

logger = logging.getLogger()
logger.setLevel(logging.INFO)

apiKey    = 'GMOコインのAPIKeyを設定してください'
secretKey = 'GMOコインのsecretKeyを設定してください'

def lambda_handler(event, context):
    # TODO implement
    side = event['side']
    symbol = event['symbol']
    amount = event['amount']
    
    # 発注する
    reqBody, res = order(side,symbol,amount)

    # ログ
    logger.info(str(reqBody))

# GMOコインにて発注する
def order(side,symbol,amount):

    timestamp = '{0}000'.format(int(time.mktime(dtOrder.now().timetuple())))
    method    = 'POST'
    endPoint  = 'https://api.coin.z.com/private'
    # 発注
    path      = '/v1/order'
    reqBody = {
        "symbol": symbol,
        "side": side,
        "executionType": "MARKET",
        "size": amount
    }

    text = timestamp + method + path + json.dumps(reqBody)
    sign = hmac.new(bytes(secretKey.encode('ascii')), bytes(text.encode('ascii')), hashlib.sha256).hexdigest()

    headers = {
        "API-KEY": apiKey,
        "API-TIMESTAMP": timestamp,
        "API-SIGN": sign
    }

    #発注する
    res = requests.post(endPoint + path, headers=headers, data=json.dumps(reqBody)) 
    return str(reqBody), res
~~~

## APIGatewayの設定

REST APIにてPOSTメソッドを作成し、
Lambda関数に先ほどのgmoBTCTradingを設定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703168/878918d3-fafc-6606-2401-2526462371d7.png)
APIのデプロイを行うとURLが発行される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703168/b90e0931-8ac1-ff18-c2c8-2bbb5854b339.png)





## TradingViewでWebhookの設定
トレーディングビューのアラート機能にてWebhook URLに先ほどのAPIGatewayのURLを設定する。
メッセージ部分にJSON形式で、各パラメータを設定します。
テストのため金額が安いXRP_JPYを10成行買い注文します。(ビットコインの場合はBTC_JPYに変更します)
※設定してアラートが実行されるとレバレッジ取引として購入されるので注意してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703168/cccf85e1-34bf-65bf-cbd1-0ad71002ebc2.png)

アラートが実行されるとWEbhook URLにJSONがポストされ、発注される
できていない場合はCloudWatchでエラーが出ていないか確認しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703168/b3492364-8929-2199-6970-8800af4cd65b.png)


## 補足
セキュリティ的なところを考えると、IP制限を追加したほうがよい。
TradingViewからPOSTされる際のIPアドレスはこちらに記載があります。
https://jp.tradingview.com/support/solutions/43000529348/

AWS API GatewayのIP制限に関してはこちらが参考になりました。
**AWS API GatewayにおけるIP制限**
https://qiita.com/koharu_s/items/18dcf26a6209d25b59c7
エンジニア向けインターンシップ開催

# はじめに 

Supership株式会社は初となるエンジニア向けインターンシップを開催しました。 
インターンシップでは二つのコンテンツがありましたが、今回はプロダクトコースについてお話しします。 

https://paiza.jp/student/job_offers/14517

https://super-stories.com/n/n1ddb6b624ea6


# インターン概要 
#### 検索ログデータを用いたサジェストシステムの開発
以上の課題をチーム分かれて開発してもらいました。

* 期間：9月2日（金）〜　9月15日（木） (１０日間)
* 場所：全日オンライン

### サジェストシステムとは？
**キーワードの入力途中に検索の候補となるキーワードやカテゴリーを表示し、入力を補助する機能**
![スクリーンショット 2022-10-19 17.42.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714345/3ca7f29b-919a-34ad-3868-799952f46d13.png)

https://www.s4p.jp/products/suggest/

# インターンで利用された技術

### インターン生の方が選定した技術
**技術選定は自由であったため、インターン生の方に自由に設定してもらいました**
以下はチームで利用された技術例になります。

* **Typescript/React**
* **Python/FastAPI・Django**
* **Docker/Docker-Compose**

フロントエンドにはReact、バックエンドにはデータ処理が得意な
Python系列のフレームワークの利用が目立ちました。
開発環境には必須なDockerの利用も多くありました。

### 必要技術として利用してもらった技術
**Elasticsearch**
弊社で扱っている**検索ソフトウェア**になります。
検索をどう実現するか、Elasticsearchで学ぶことができます。

**Google Cloud**
クラウドサービスとして弊社負担で利用してもらいました。
Google Cloudの様々なサービスに挑戦することができます。

# インターン中のコンテンツ

### 開発に関するコンテンツ

#### 事業・技術紹介
弊社のリードエンジニアの方から事業や技術について紹介がありました。
特に技術紹介では、検索に関する貴重なお話をしてもらいました。

#### 中間発表会
インターン生の方に途中経過をプレゼンしてもらいました。
現場エンジニアの方から**フィードバックや開発課題のアドバイス**がありました。

#### 最終発表会
インターン生の方が作り上げたシステムをプレゼンしてもらいました。
CTOを含め多くの現場エンジニアの方からレビューをいただきました。

### 開発以外のコンテンツ

#### 会社の制度利用
会社の制度として月曜日の午前中が休みになるHAPPY MONDAYがあります。
エンジニアのほとんどの方が毎週使っているため、インターン生の方にも利用してもらいましたが好評でした。

https://dime.jp/genre/742356/

#### ボードゲームやスマブラ会(自由参加)
弊社では部活動があるため、活動にインターン生の方も参加してもらいました。
ボードゲームたスマブラなどを社員の方と楽しんでもらいました。

#### 社員の方との座談会
インターン生の方から現場エンジニアの方に質問をしてもらいました。
会社や事業、技術的な話題やキャリアについてお話ししてもらいました。

# インターンに参加するメリット

#### 大量のログデータが使える
学生で扱うことが稀な検索のログデータを扱えます。
大量のデータを扱う貴重な経験と現場でのデータの取り扱いを学ぶことができます。

#### 新しい技術に触れる
課題内容は検索領域に関わってくるため、
検索技術のElasticsearchや検索システムの土台を学ぶことができます。
また、Google Cloudを予算以内で扱えるので、新しいサービスを試すことができます。

#### 技術選定からプロジェクトの進め方まで自由
スケジュールはありますが、チームで自由に分担をしてもらい自分達のペースで開発できます。
技術選定も自由なので比較的自由な開発を行うことができます。
技術選定で詰まらないように最低限の開発環境は弊社で用意しています。

#### サポートがいつでも受けられる状態
１チームには１名のメンターが付いており、インターン生の質問に答えれる体制があります。
そのため未知の領域でわからないことがあっても、必ずサポートします。
また、現場エンジニアのフィードバックのタイミングもあるのでそちらも利用してもらって開発を進めることができます。

#### 目標設定とフィードバック
インターン前にそれぞれの参加する方に技術的とそれ以外について目標を設定してもらいます。
中間発表や最終発表の現場エンジニアからのフィードバックや、
インターン後にはメンターなどからフィードバックがあるため、成長できる内容になっています。

# 終わりに

メンターからの感想ですが、サジェスト機能の開発による検索技術を学べるだけでなく、
Google Cloudやチーム開発も含めて、多くの学びのあるインターンだと思います。
もし学生時代にあれば参加したいと思わせる内容でした。

[Supership](https://supership.jp/)ではプロダクト開発やサービス開発に関わる人を絶賛募集しております。
ご興味がある方は以下リンクよりご確認ください。
[Supership株式会社 採用サイト](https://supership.jp/recruit/)
是非ともよろしくお願いいたします。