OmniAICreator/Qiita-1.07M huggingface dataset:
CentOS stream8でNginxをインストールする

# はじめに
NginxをCentOS stream8にインストールする機会があったので参考になればと記事にしました。

## step1 Nginxをインストールするためにリポジトリを作成します
` # vi /etc/yum.repos.d/nginx.repo` を入力し、nginx.repoファイルを作成し、リポジトリ [^1]の編集を行います。
下記の内容をすべて記述します。コピペおｋ

```
[nginx-stable]

name=nginx stable repo

baseurl=http://nginx.org/packages/centos/＄releasever/＄basearch/

gpgcheck=1

enabled=1

gpgkey=https://nginx.org/keys/nginx_signing.key

module_hotfixes=true

[nginx-mainline]

name=nginx mainline repo

baseurl=http://nginx.org/packages/mainline/centos/＄releasever/＄basearch/

gpgcheck=1

enabled=0

gpgkey=https://nginx.org/keys/nginx_signing.key

module_hotfixes=true
```
コピペして貼り付けできたら大丈夫です:v:

## step2 nginxをインストールします

`# dnf install nginx` コマンドを入力する。
**※今回はdnfコマンドを使用しています。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724196/fc8bf902-0ea7-d18a-5d1d-fa7508c21021.png)
こんな感じでインストールが始まります。
確認をされるので全てyesでおｋ

## step3 Nginxのバージョンを確認する
Nginxのバージョンを確認します。
`# nginx -v` を打ち、Nginxのバージョンを確認しましょう。
記事時点での実行時のバージョンは、`nginx version: nginx/1.22.0`です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724196/e6595183-a140-0768-8158-6321e3e6d664.png)

## step4 Nginxを自動起動[^3]にしよう♪
```
# systemctl enable nginx 
```
上記のコマンドを入力し、自動起動にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724196/68541add-675e-8e9e-b0c0-47f6f3782d53.png)
` 
Created symlink /systemd/system/multi-user.target.wants/nginx.service  → /usr/lib/systemd/system/nginx.service.
`
上記の文字列が出れば大丈夫です。

## step5 Nginxを起動してみよう！！
```
# systemctl start nginx
```
を入力します。

次に、Nginxが起動できてるか確認します
```
# systemctl status nginx
```
を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724196/31f75f90-cf3a-0cba-8bb0-8835bf64f2ef.png)

上記のように、Activeになっていたら終了です。

## Nginxにアクセスしてみよう
Nginxを起動したら、サーバのIPアドレスをブラウザに入力してアクセスしてみましょう。下のような画面が表示されていれば、アクセスは成功。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724196/e9d4b83b-fc86-0f38-7a7f-91e6934c13b3.png)

[^1]: **リポジトリ**
Linuxが必要なアプリケーションを見つけ出せるようにインターネット上のどこのサーバーにアプリケーションが格納されているかを記載したファイル

[^3]:**自動起動**
サーバー起動、再起動時に自動でスタートを行ってくれるようにするため
kubectrl でクラスタの起動に接続エラーで失敗する

# エラー

クラスタを起動すると以下のようなエラーが表示される。

```shell
Deploy Failed. Could not connect to cluster due to "https://kubernetes.docker.internal:6443/version?timeout=32s": dial tcp 127.0.0.1:6443: connect: connection refused. Check your connection for the cluster.
```

# 原因

Kubernetes が起動していない。


# 解決策

Kubernetes を起動する。

Mac であれば以下の設定をONにする。
![CleanShot 2022-06-28 at 13.58.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547464/0762f480-a224-929b-7824-c35f0a7aff5b.png)


# 余談

Kubernetes が起動していないと、左下の Kubernetes アイコンが表示されないのでそこからも判断できる。
画像は Docker と Kubernetes の両方が起動されている状態。

![CleanShot 2022-06-28 at 13.58.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547464/d92e9f34-9eb0-67f9-2e5d-5c042042f900.png)
Promiseを使う 【TypeScript】

## `Promise`とは

PromiseはES2015で追加された非同期処理のための機能です。

Promiseを使うことで`より便利かつわかりやすい形で非同期処理を扱う`ことができる。

非同期処理においては`終わったあとに何をするか`を表す関数が不可欠であり、コールバック関数ベースの非同期処理の場合は非同期処理を開始する関数（setTimeout,readFile..etc）に直接これをコールバック関数として渡していました。

Promiseベースの非同期処理では非同期処理を行う関数は関数を受け取らず、`Promiseオブジェクト`を返却します。

その`Promiseオブジェクトに対して終わったあとに行う処理を表す関数を登録`します。

これがPromiseベースの非同期処理の基本的な流れです。

## Promiseを利用した例

```typescript
import {readFile} from "fs/promises"

const p = readFile("foo.txt" , "utf8")

p.then((data) => {
  console.log(data)
})
```

## 参考文献
*プロを目指す人のためのTypeScript入門*
（P.353）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/00655691-9f99-21ea-d25a-9415d7994a14.png)
SynologyのNASでMacのTimemachineを利用する際の備忘録

SynologyのNASでTimemachineを利用する際の備忘録をまとめる。
なにかと問題が発生しやすいので。

# エラー: 選択したネットワーク・バックアップ・ディスクで、必要な機能がサポートされていません。

解決策: DSMと関連アプリケーションが最新バージョンであることを確認し、ひとまずNASをリスタート。

# 環境

- DSM: 7.1-42661 Update 1
- Mac: sw_vers
    - ProductName:	macOS
    - ProductVersion:	12.4
    - BuildVersion:	21F79
化学×深層学習

## はじめに

https://qiita.com/official-events/97ae2edf9e1a01bde1fe

仕事で論文を読むことはあったのですが、深層学習関連は読んだことがなく(難しそうだから避けていた)。
上記のようなイベントついでに、何とかついていけそうな？内容で読むことにしました。


## 論文

“Found in Translation”: Predicting Outcomes of Complex Organic Chemistry Reactions using Neural Sequence-to-Sequence Models, Chem Sci., 2018

doi：[10.1039/c8sc02339](https://pubs.rsc.org/en/content/articlelanding/2018/SC/C8SC02339E)

## 10秒で読める概要
seq2seqモデルを使った深層学習で、有機反応予測の正答率が約80%まで向上できた。

## 詳細
さすがに概要だけで終わるのは短すぎるので、もうちょっと書いていきます。

* 有機反応予測の大変な部分は？
化学反応は種類が多く、情報を書き出して規則化するのが大変。
⇒データセット化しにくい

* 先行研究例とその課題
DNNを使ったアプローチ(ちなみにこの研究は日本人の方(東大-船津先生))。
⇒適用できるものに限りがある

* この研究のいいところ
seq2seqモデルを使うことで、約80%の予測精度を出すことができた。また対象となる物質に制限がない。

* データセットの中身
化学構造をSMILES(構造式を文字で表す方法)方式で記述したもの。
⇒実際の構造はPCが認識しにくいので、文字で落とし込んでいる
(ちなみにベンゼンはc1ccccc1という表記になる)


## 感想
* 論文ページ数が少なくて読みやすい
合計10pなので初心者でも比較的読みやすいです。

* データセットで大きく結果が違う
そりゃそうなんですが。この論文では2種類のデータセットで比較を行っています。
**Lowe’s grants set**：米国特許から抽出した有機反応に関するデータセット
**Jin’s USPTO set**：Lowe’s grants setからいらないものを削除したり、新たに別の内容を追加したデータセット
約80%の予測精度はJin’sの方です。Lowe’sはノイズがかなりあったようで(重複など)、同じモデルでも65%まで下がっています。やっぱりきれいなデータセットは大事ですね。

* データセットの作成大変そう
どちらも数十万～数百万というデータ数なので、作るの大変そうですね。
・・・少なくとも自分は作りたくないです。

* 出てくるイラストがちょっとしたオアシス
難しい用語が並ぶ中で、画像が出てくるのは少し嬉しい(意味が分からなくても)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/c0f3765f-69d9-400c-b7c1-1492a307f0e8.png)

## 参照
各用語は詳しい先人が作った資料を見るのが早いので。

seq2seqモデル
https://sinyblog.com/deaplearning/seq2seq-001/

SMILES
https://www.molsis.co.jp/datamanagement/daylight/smiles/

RDKit
化学構造を取り扱う時に使うライブラリ。上記の画像にも使われている。
https://future-chem.com/rdkit-2ddraw-svg/
重い腰を上げてAtcoderを始めた(青)



2022/04/23(ABC249)、重い腰を上げてAtcoderを始めて、05/28のABC253(5回目の参加)で水色、06/26のARC143(10回目)で青になったので一応記事を書きます。

### どうして今更
 - 昔Project Eulerをやってて、300問くらい解いた
 - AtCoderの存在は知ってたが、4問時代は全問正解しても、その中の速さで決まってたのを見て、(のんびりやりたいタイプなので)あんまりやりたくならなかった
 - 最近見たら、いつの間にか8問になってて、全問正解までの時間より純粋に解ける数が重視されるようになってたのでやってみることにした(しかも毎週あるABCで2000まで上がれる)
 - cargo-atcoderやcargo-competeのようなツールが充実していて、安全で、高速な**Rust**を使ってやってみたかった
    - コンパイル有りなのでCEで済む場合がある、てきとうに書いててもCのように危険な落とし穴を踏みづらい。型が強力で抽象化しやすい。

### 練習方法
一応ProjectEulerからの転生組なので**あんまり参考にしないほうがいいかも**しれないけど、私のやり方

 - 解けることがわかっているクラス(300以下など)はあんまりやらない
    - 他の人はたくさん埋めたりStreakを稼いだりしているけど、飽きっぽくてめんどくさがりな私には向いてなさそうだと思った。
 - 解けるけどちょっと時間がかかる問題の方針を速く立てることを重視して、問題を見て方針が思いつかなかったら解説を見るトレーニングをやる
     - これに使うのは典型の多いとされるABCがよい。ARC以降は考察ウェイトが多くネタバレが致命的かもしれないので、後の練習に取っておいたほうが良さそう？
     - とりあえずはコーディング速度を上げるよりこっちのほうが楽そうだと考えた。
     - 難易度を見積もるのが早くなると、前から順にABCDEF(2000)ではなくABCD+(EorF)+(GorEx)(2100)、というふうな選択肢ができる上に点数有利な目標ができる
 - たまにライブラリ整備兼ねてAtcoder ProblemsのRecommendationのModelate,Difficultを適当にバチャコン化して解いてみる
     - 解説を読んだらその問題は寝かせて、後日再挑戦する

 - ちなみに、私は持ち込みライブラリがないと時間内に正しく実装できないタイプなので、整備は時間外にやってる
 - 作ったライブラリ
   - (関数を渡しての)二分探索。答えを決めて二分探索とかに重宝する。
   - LazySegTree(抽象化つき, 一番のお気に入り)
   - SparseTable
   - 座標圧縮
   - Union Find (高さを持ってない手抜き)
   - Convex-Hull (Monotone Chain)
   - グラフアルゴリズムは概ねpetgraphで解けるが、なぜかDinicとか、ベルマンフォードの到達不能な負の閉路を除外したものとかがないので、そこは自分で書いた
   - 連立方程式
   - 素因数分解, GCD, 拡張ユークリッドなど

 - 自分に合った解法を見つける、その上で広げる
     - 例えば、解説に公式解説とユーザー解説でニ種類以上の解法が載ってたりする。正解は一つではないということ。
     - ぐちゃぐちゃだろうと自力で解ければえらい。その上で他の解法を見ると思考の幅が広がるし、いつか似た問題が出たとき使える考え方が身につく。
     - コンテストは短いので、(自分にとっての)難易度の見積もりが重要。(特にA-Dが絶対解けてEFGExから選ぶ場合)得意技が使える問題、不得意な問題を見極められると楽。
         - ちなみに私はLazySetTree抽象化による区間クエリはどちらかというと得意技のつもりだったけど、ABC256で区間が2問出たにもかかわらずそれ以外しか解けなかったいうことがある。
     - これはどこかの色変記事で見た「想定解で解けるようにしろ」(意訳)に対するカウンター

### 今後
しばらくはライブラリ整備のために毎回は出ないつもり。今年中に黄色くらいを目標に。
test

# 観点
## controller
### GET
- ステータスが200であること
- ステータスが500であること

### POST
- ステータスが200であること
- ステータスが400であること
  - リクエスト不正
- ステータスが500であること
- サービスから投げられる例外のケース
  - 登録対象が既に存在している場合など

### PUT
- ステータスが200であること
- ステータスが400であること
  - リクエスト不正
- ステータスが500であること
- サービスから投げられる例外のケース
  - 更新対象がない場合など

### DELETE
- ステータスが200であること
- ステータスが400であること
  - リクエスト不正
- ステータスが500であること
- サービスから投げられる例外のケース
  - 削除対象がない場合など
pipでインストールしたライブラリをrequirements.txtを作らずに一括で最新に更新する方法

## 背景
pipでインストールしたライブラリを一つずつ更新したい際は以下のように指定する

```zsh
$ pip install -U ライブラリ名
```

ただ意外と一括ですべてのライブラリを最新にする方法は提供されていない。
requirements.txtで管理すれば一括更新は可能なのだが、globalでinstallしているパッケージを更新したい場合にrequirements.txtを作成してどこかのディレクトリで管理するのもなんか違う気がしたのでやり方を考えてみた。


## pipでインストールしたライブラリを一括で最新に更新する方法
```zsh
$ pip list --outdated | awk 'NR>=3 {print $1}' | xargs pip install -U
```

- `pip list --outdated`は最新版に追いついていないライブラリを出力してくれる
- それを`awk`コマンドで3行目以降（ヘッダー除去）&1列目のみに加工し
- `xargs`で`pip install -U`を全行に適用させた
iframeから親フレームにデータを投げる(クロスオリジン対応)

ローカルのhtmlでiframeから親フレームに処理を飛ばそうとしたところ、

```javascript:test.js
window.onload = onLoad;

function onLoad() {
     var filename = window.location.pathname.match(".+/(.+?)\.[a-z]+([\?#;].*)?$")[1];
     window.parent.changeMenu(filename);
}
```

```javascript:エラー
Uncaught DOMException: Blocked a frame with origin "null" from accessing a cross-origin frame.
```
というエラーが発生。
クロスオリジンが発生して親の関数が実行できないらしい。


## 対策
データの受け渡しにparent.window.postMessage()を使用。
```javascript:子フレーム
window.onload = onLoad;

function onLoad() {
   		var filename = window.location.pathname.match(".+/(.+?)\.[a-z]+([\?#;].*)?$")[1];
      	window.parent.postMessage(filename, "*");
}
```

```javascript:親フレーム
window.addEventListener("message", function (e) {
			if($('.thisTopic').attr("id") == e.data){
		   		return;
		 	}
	    	$('.topic').removeClass('thisTopic');
	    	$('#' + e.data).addClass('thisTopic');
});
```
こうすることで無事に解決。
受け渡したデータはe.dataに入ってた。

## 参考資料
https://qiita.com/TakamiChie/items/aaa435be2ca08ecdcb61
ぼくのかんがえたさいきょうのふれーきーてすとはっけんほうほう - Jenkins+Jestの例 - 

##  はじめに
[世界中のITエンジニアが悩まされている原因不明でテストが失敗する「フレイキーテスト」問題](https://www.publickey1.jp/blog/22/itjenkinsdevops_days_tokyo_2022_1.html)

自動テストを実装しているが成功したり失敗したりしていまいち信頼性が無いテストがあります。
文頭の記事からそれらをフレーキーテストと呼ぶということ、世のエンジニアの皆様もそれに苦慮されていることを知り、なにか対応策を考えられないか画策してみました。
本記事では1例としてJenkinsのプラグインを組み合わせると、フレーキーテストを見つけられそうなので、その設定方法を書き記しておきます。

## 環境
jenkins 2.320

## 使用プラグイン
・Jest
[jest-junit](https://github.com/jest-community/jest-junit)
・jenkins
[test-results-analyzer](https://plugins.jenkins.io/test-results-analyzer/)

## Jestの設定

### jestのテスト結果をjunitで出力する
プロジェクトに[jest-junit](https://github.com/jest-community/jest-junit)を追加します。
jest-junit は Jest で実行したテスト結果をJUnitのXML形式のファイルで出力するパッケージです。
jest.config.jsに下記例のように出力設定を追加します。

```
 $ npm install --save-dev jest-junit
```

```jest.config.js
    reporters: [
        'default',
        [
            'jest-junit',
            {
                suiteName: 'jest tests',
                outputDirectory: 'junit/',
                outputName: 'junit.xml',
                classNameTemplate: '{classname}-{title}', //{classname}はdescribeのクラス名を出力します
                titleTemplate: '{classname}-{title}', //{title}はtestまたはitのテスト名を出力します
                ancestorSeparator: ' › ',
                suiteNameTemplate: '{filename}' //{filename}はjestのテストファイル名を出力します
            },
        ],
    ],
```

出力設定をしたあとにjestを実行すると下記のようなJUnit形式のテスト結果が出力されます。
これをjenkinで収集します。

```junit.xml
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name={suiteName} tests="8" failures="0" errors="0" time="XX.XXX">
  <testsuite name={suiteNameTemplate} errors="0" failures="0" skipped="0" timestamp="2022-XX-XXTXX:XX:XX" time="XX.XXX" tests="1">
    <testcase classname={classNameTemplate} name={titleTemplate} time="XX.XXX">
    </testcase>
  </testsuite>
</testsuites>
```

## jenkinsの設定
Jenkinsはデフォルトでビルド毎のJUnitテスト結果が収集可能となっています。
そこにビルドのテスト結果を保存して解析表示する[test-results-analyzer](https://plugins.jenkins.io/test-results-analyzer/)プラグインをインストールします。

### 設定方法
ジョブの設定でビルド後の処理の追加で「JUnitテスト結果の修正」を追加し「テスト結果XML」にjest-junitで出力したxmlへのファイルパスを記載します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726105/6d2ff6d2-f703-b56a-4d00-ad35e27ad1bf.png)


設定後、実際にジョブを実行した後にメニューからのTest Results Analyzerを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726105/51d97d4c-c74d-907a-c205-4ab57d92a978.png)

テスト毎の結果を収集することで、各テストの成功率、よく不安定となるテストを確認することができます。
例えば、②の履歴から、成功したり失敗したりするテストを見つけられます。

<表の説明>
①各テストの一覧とその成功率
②各テストのビルド毎の成功と失敗
③全テスト中最も失敗するテストTOP10

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726105/519816fb-1ed5-6d09-93a2-70f234547dab.png)

## 最後に
本記事では1例としてCIにjenkinsを利用した方法を記載しました。
Jestを使用していますが、JUnitでも同等なことができると思います。
ご参考になれば幸いです。

##  参考
・世界中のITエンジニアが悩まされている原因不明でテストが失敗する「フレイキーテスト」問題
https://www.publickey1.jp/blog/22/itjenkinsdevops_days_tokyo_2022_1.html

・フレーキーテストにまつわるあれこれ
https://qiita.com/seigot/items/bec2c934b762a2f50821
※既存のCIツールにてフレイキーなテストの対策手段が記載されています。

・Detect and track flaky Jest tests 　
https://buildpulse.io/test-frameworks/jest
※Jestのフレイキーなテストを解析、可視化する有料Webサービス
【Golang】recoverについて

# 概要
リリース前のプロジェクトのソースコードを見ていく中で、ふとrecoverが入っていないことに気づきました。recoverについての理解が浅く、どんな挙動をするのか、何のためにrecoverするのか理解できていなかったので備忘としてまとめます。
golangのフレームワークのリファレンスなどに記載されているから、なんとなくrecoverを入れている、使い方や用途は実はいまいちわかっていない方などに読んでいただけますと幸いです。

# recoverでできること
- panicが発生したとしてもプログラムを終了せずに復帰できます。
- 本当にシンプルにこれだけです笑

# 疑問
ここで疑問に思ったのがrecoverの使い方でした。
例えばサーバーでpanicが発生したとして、panic=致命的なエラーなのでこれをrecoverしたところで全ての処理に失敗するのでは・・？
今はどこも実環境でコンテナ技術を用いたサーバーを構築していると思うので、いっそrecoverを入れずにサーバーを落としてしまって、リクエストを処理の成功するコンテナに誘導するほうがいいのでは・・？

# 結論
上記の疑問は間違っていました。recoverは入れるべきだと思います。
[effective go](https://go.dev/doc/effective_go#recover)を読むと下記のように記載されています。

> 原文
One application of recover is to shut down a failing goroutine inside a server without killing the other executing goroutines.

> 日本語訳
recoverの応用例としては、サーバー内で故障したゴルーチンを、他の実行中のゴルーチンを殺すことなくシャットダウンすることが挙げられます。

つまり、サーバーが複数のリクエストを処理していると仮定した時に、golangではこの複数の並行処理をgoroutineを使って捌きます。
recoverを入れておくことで、仮にどれか一つのgoroutineでpanicが発生したとしても他のgoroutineは生き続けることができる、というのがrecoverの代表的な使い方ということになります。
よくよく考えたら[疑問](#疑問)で言っていたパターンだと、panicが発生した時点で他のgoroutineも共倒れで死んでしまいますよね。。。

# 実装
以上を踏まえて実案件のコードでも実装をしてみました。(だいぶ簡略化しています)

main.go
```golang
func main() {
	// DBのコネクションの作成の独自関数
	conn, err := repository.InitDBConnection("qiita")
	if err != nil {
		log.Fatalf("db connection failed: %v", err)
	}

	s := grpc.NewServer(
		grpc.UnaryInterceptor(
			grpc_middleware.ChainUnaryServer(
				middleware.Recover(),
			),
		),
	)

	rpc.RegisterServices(s, conn)

	lis, err := net.Listen("tcp", ":50000")
	if err != nil {
		log.Fatalf("failed to : %v", err)
	}
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}
```

recover.go
```golang
func Recover() grpc.UnaryServerInterceptor {
	return func(
		ctx context.Context,
		req interface{},
		info *grpc.UnaryServerInfo,
		handler grpc.UnaryHandler,
	) (_ interface{}, err error) {
		defer func() {
			if r := recover(); r != nil {
				fmt.Printf("%v", r)
				err = status.Error(codes.Internal, "unexpected error")
			}
		}()

		resp, err := handler(ctx, req)
		return resp, err
	}
}
```

recoverはmiddlewareとして使用しています。これによりリクエストごとにrecoverがdeferで呼び出されます。
recover.go内ではエラーの内容を標準出力しログにのこし、レスポンスとして返す情報としては`HTTPステータス500`の`unexpected error`として返すようにしました。
これでサーバーを落とさずに、かつ根本原因はログに残しつつクライアントには内部の事情を知られないようなレスポンスを返すことができます。

# さいごに

トレタでは一緒に開発する仲間を募集しています。<br>
興味がある方は是非カジュアル面談へお越しください！

https://www.wantedly.com/companies/toreta/projects
css

# Flex
https://qiita.com/dorara/items/89364b0ab9e9d5d5c7b7

```tsx
<SampleCardList flexWrap="wrap">
          {cards.map(([k, { value }]) => (
            <div key={k}>
              <SampleCard
                id={k}
                title={value}
                checked={true}
                pageSize={1}
                onChange={() => {}}
              />
            </div>
          ))}
        </SampleCardList>

const SampleCardList = styled(DFlex)`
  width: auto;
  margin: 10px -5px;
  > div {
    padding: 5px;
    flex-basis: calc(100% / 5);
  }
`;
```
Pythonで正規表現を確認したいときのスニペット

ちょっと確認したい時に使うスニペット

``` Python
import re

text = 'hoge'
pattern = '.g.'
result = re.sub(pattern, 'bar', text)

print(result)
```

### 備忘録
* 置換時にマッチした文字を使いたい場合、`$1,$2...`ではなく`\\1,\\2...`とする
``` Python
text = 'hoge'
pattern = 'h.(g.)'
result = re.sub(pattern, '\\1', text)
```
recoil

https://velog.io/@yiyb0603/Recoil-Selector-useRecoilValueLoadable%EC%9D%84-%ED%99%9C%EC%9A%A9
## atom
```ts
const categoriesAtom = atom<Category[]>({
  key: “categoriesAtom”,
  default: [],
});
const itemsAtom = atom<Item[]>({
  key: “itemsAtom”,
  default: [],
});
```
## selector
```ts
const categoriesSelector = selector({
  key: “categoriesSelector”,
  get: async () => await fetchCategories(),
});
const itemsSelector = selector({
  key: “itemsSelector”,
  get: async () => await fetchItems(),
});
```
## hook
```ts
const useGetCategories = () => {
  const [categories, setCategories] = useRecoilState(categoriesAtom);
  const { state, contents } = useRecoilValueLoadable(categoriesSelector);
  const refresher = useRecoilRefresher_UNSTABLE(categoriesSelector);
  React.useEffect(() => {
    switch (state) {
      case “hasValue”:
        setCategories(contents);
        break;
      case “hasError”:
        // error handling
        break;
      case “loading”:
        // loading
        break;
      default:
        break;
    }
    return () => {
      setCategories([]);
      refresher();
    };
  }, [state]);
  return state;
};
const useGetItems = () => {
  const [items, setItems] = useRecoilState(itemsAtom);
  const { state, contents } = useRecoilValueLoadable(itemsSelector);
  const refresher = useRecoilRefresher_UNSTABLE(itemsSelector);
  React.useEffect(() => {
    switch (state) {
      case “hasValue”:
        setItems(contents);
        break;
      case “hasError”:
        // error handling
        break;
      case “loading”:
        // loading
        break;
      default:
        break;
    }
    return () => {
      setItems([]);
      refresher();
    };
  }, [state]);
  return state;
};
```
open api

- [redoc](https://github.com/Redocly/redoc)

- ドキュメント生成

- [openapi-merger](https://www.npmjs.com/package/openapi-merger)

  - 閲覧性のため分割した OpenAPI document を 1 つのファイルにマージする

  - [openapi-generator](https://github.com/kota65535/openapi-generator)
  - Server Stub & モデルクラス生成

- [openapi-generator option 一覧](https://github.com/OpenAPITools/openapi-generator/blob/master/docs/generators/spring.md)

・OpenAPI 参考

- [公式](https://swagger.io/specification/)
- [参考 1](https://qiita.com/teinen_qiita/items/e440ca7b1b52ec918f1b)
- [参考 2](https://tech-blog.optim.co.jp/entry/2020/04/13/100000)
sql

# mysql
https://zenn.dev/shot606/articles/2f3819c16e3d28
https://qiita.com/inouet/items/4f1d7f299725597d8407

## 関数
全角、半角function
```sql
DROP FUNCTION IF EXISTS zen2han;

DELIMITER //

CREATE FUNCTION zen2han (data TEXT character set utf8) RETURNS TEXT character set utf8 DETERMINISTIC
BEGIN
    DECLARE kana1_len, kana2_len INT;
    DECLARE kana1_h VARCHAR(72) character set utf8 DEFAULT 'ｱｲｳｴｵｶｷｸｹｺｻｼｽｾｿﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎﾏﾐﾑﾒﾓﾔﾕﾖﾗﾘﾙﾚﾛﾜｦﾝｯｬｭｮｧｨｩｪｫ ｰ｡｢｣､･1234567890';
    DECLARE kana1_z VARCHAR(72) character set utf8 DEFAULT 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンッャュョァィゥェォ　ー。「」、・１２３４５６７８９０';
    DECLARE kana2_h VARCHAR(52) character set utf8 DEFAULT 'ｶﾞｷﾞｸﾞｹﾞｺﾞｻﾞｼﾞｽﾞｾﾞｿﾞﾀﾞﾁﾞﾂﾞﾃﾞﾄﾞﾊﾞﾋﾞﾌﾞﾍﾞﾎﾞﾊﾟﾋﾟﾌﾟﾍﾟﾎﾟｳﾞ';
    DECLARE kana2_z VARCHAR(26) character set utf8 DEFAULT 'ガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポヴ';

    SET kana1_len = CHAR_LENGTH(kana1_h);
    SET kana2_len = CHAR_LENGTH(kana2_h);

    WHILE kana2_len > 0 DO
            SET data = REPLACE(data, SUBSTRING(kana2_z, kana2_len, 1), SUBSTRING(kana2_h, kana2_len * 2 - 1, 2));
            SET kana2_len = kana2_len - 1;
        END WHILE;

    WHILE kana1_len > 0 DO
            SET data = REPLACE(data, SUBSTRING(kana1_z, kana1_len, 1), SUBSTRING(kana1_h, kana1_len, 1));
            SET kana1_len = kana1_len - 1;
        END WHILE;

    RETURN data;
END;
//
DELIMITER ;

DROP FUNCTION IF EXISTS zen2han;

DELIMITER //

CREATE FUNCTION zen2han (data TEXT character set utf8) RETURNS TEXT character set utf8 DETERMINISTIC
BEGIN
    DECLARE kana1_len, kana2_len INT;
    DECLARE kana1_h VARCHAR(72) character set utf8 DEFAULT 'ｱｲｳｴｵｶｷｸｹｺｻｼｽｾｿﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎﾏﾐﾑﾒﾓﾔﾕﾖﾗﾘﾙﾚﾛﾜｦﾝｯｬｭｮｧｨｩｪｫ ｰ｡｢｣､･1234567890';
    DECLARE kana1_z VARCHAR(72) character set utf8 DEFAULT 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンッャュョァィゥェォ　ー。「」、・１２３４５６７８９０';
    DECLARE kana2_h VARCHAR(52) character set utf8 DEFAULT 'ｶﾞｷﾞｸﾞｹﾞｺﾞｻﾞｼﾞｽﾞｾﾞｿﾞﾀﾞﾁﾞﾂﾞﾃﾞﾄﾞﾊﾞﾋﾞﾌﾞﾍﾞﾎﾞﾊﾟﾋﾟﾌﾟﾍﾟﾎﾟｳﾞ';
    DECLARE kana2_z VARCHAR(26) character set utf8 DEFAULT 'ガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポヴ';

    SET kana1_len = CHAR_LENGTH(kana1_h);
    SET kana2_len = CHAR_LENGTH(kana2_h);

    WHILE kana2_len > 0 DO
            SET data = REPLACE(data, SUBSTRING(kana2_z, kana2_len, 1), SUBSTRING(kana2_h, kana2_len * 2 - 1, 2));
            SET kana2_len = kana2_len - 1;
        END WHILE;

    WHILE kana1_len > 0 DO
            SET data = REPLACE(data, SUBSTRING(kana1_z, kana1_len, 1), SUBSTRING(kana1_h, kana1_len, 1));
            SET kana1_len = kana1_len - 1;
        END WHILE;

    RETURN data;
END;
//
DELIMITER ;
```
saga


## saga
- apiを使って非同期処理を書く
- actionsで定義したrequest, success, failureのアクションをディスパッチする

```ts
import { createUser, FetchError } from '@/common/api';
import { call, put, takeLatest } from 'redux-saga/effects';
import { getType } from 'typesafe-actions';
import * as actions from '@/actions';

function* createUserAsync(
  action: ReturnType<typeof actions.createUser.request>
): Generator {
  try {
    yield call(createUser, action.payload.request);
    yield put(actions.createUser.success());
  } catch (error) {
    if (error instanceof FetchError) {
      yield put(actions.createUser.failure({ error }));
    }
  }
}

export default [
  takeLatest(getType(actions.createUser.request), createUserAsync)
];
```

## rootSaga
sagasでexportしたものをrootSagaでyield allする
```ts
import { all } from 'redux-saga/effects';

import userSaga from './userSaga';

/**
 * RootSaga
 */
export default function* rootSaga() {
  yield all([
    ...userSaga
  ]);
}
```

## actions
`import { createAsyncAction } from 'typesafe-actions';`を使ってsagasでディスパッチする各アクションを作成するコードを書く
```ts
import { FetchError } from '@/common/api';
import { CreateUserRequest } from '@/models/request';
import { createAsyncAction } from 'typesafe-actions';

enum CREATE_USER {
  REQUEST = '@createUser/request',
  SUCCESS = '@createUser/success',
  FAILED = '@createUser/failed'
}

export const createUserAction = createAsyncAction(
  CREATE_USER.REQUEST,
  CREATE_USER.SUCCESS,
  CREATE_USER.FAILED
)<{ request: CreateUserRequest }, void, { error: FetchError }>();
```

## reducer
getType({createAsyncActionで作成したaction})で、action.typeを判定しreducerの処理記述
```ts
import { ActionType, getType } from 'typesafe-actions';

import * as actions from '../actions';

/** Loadingエフェクトの状態を管理する */

type Action = ActionType<typeof actions>;

export interface LoadingState {
  on: boolean;
  prediction: boolean;
}
const initialState: LoadingState = {
  on: false,
  prediction: false
};

export default function loadingReducer(
  state: LoadingState = initialState,
  action: Action
): LoadingState {
  // tslint:disable-next-line:no-duplicate-case
  switch (action.type) {
    case getType(actions.createUser.request):
      return {
        ...state,
        on: true,
        prediction: false
      };
    case getType(actions.createUser.success):
    case getType(actions.createUser.failure):
      return {
        ...state,
        on: false
      };
    default:
      return state;
  }
}
```

## 疑問
- saga以外でエラーハンドリングしたい時どうする？
    - sagaのargsにcallbackを渡す？
移動平均を作成する(SPSS Modeler データ加工逆引き4-3)

# N期の移動平均を作成（当該行を含む/含まない移動平均）

![スクリーンショット 2022-06-27 17.41.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/2bb5e95a-2f14-6237-7609-acf6b2ccc1a9.png)

## 1.想定される利用目的

・需要予測モデルのための特徴量作成
・不正検知や倒産/解約/ランクアップ予測のための顧客行動の特徴量作成
・異常検知や故障予測のための特徴量作成

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/blob/main/moving_average.str?raw=true

## 3.サンプルストリームの説明

![スクリーンショット 2022-06-27 17.42.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/bb1e7ce1-181a-3666-c98b-b6f859a03fa2.png)

a.入力するデータは以下の通りです。
![スクリーンショット 2022-06-27 18.11.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/ec3d5295-f796-fc0c-495d-85cc46ac8ce0.png)

b.[フィールド作成]ノードを編集します。[派生]モードを[条件付き]にして[If]を通し番号の関数[@&#xFFF0;INDEX]が３以上（３レコード以降）にします。[Then]では[@&#xFFF0;MEAN(フィールド)]を利用しています。[Else]に該当する1か２レコード目には欠損値Nullになるように[undef]と入力します。
![スクリーンショット 2022-06-27 18.12.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/dbd1de4f-bde5-d760-484f-e0e03504f517.png)

式ビルダーのライブラリから@&#xFFF0;関数を探すと簡単に入力できます。
![スクリーンショット 2022-06-27 18.16.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/9554d5f3-cf55-312a-4c06-062aa38ab0e9.png)

[プレビュー]します。３レコード目から計算されています。
![スクリーンショット 2022-06-27 18.25.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/22e80534-45c0-a13b-7eb8-1724ebabcf55.png)

c.自分の行を含めず前期までの3期移動平均を作成します。異常検知や不正検知では当該レコードを含めると異常具合が見えにくくなるため意図的に前期までの移動平均を利用します。関数は@&#xFFF0;SUMを利用しており自分を含む4レコードの和から自分のレコードを引き算して３で割っています。

![スクリーンショット 2022-06-28 10.42.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/ad4e3569-b79e-d600-af27-c79122ffa70c.png)

[プレビュー]します。完成しました。
![スクリーンショット 2022-06-28 10.45.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/d10fd0fb-cea9-4017-f9d8-17043a254ce4.png)

#### オフセットを利用した方法

d.列方向に参照するオフセット関数でbと同じ処理をさせます。[@&#xFFF0;OFFSET（温度,1)]で温度フィールドの1レコード上を参照しますので以下の式で移動平均が得られます。対象レコードがないと欠損値Nullになるためaやbのような条件は不要です。
![スクリーンショット 2022-06-28 10.46.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/a0126059-15bb-6ebb-cd74-7e7dc42d53f4.png)

e.同じ要領で当該レコードを含まないバージョンです。
![スクリーンショット 2022-06-28 10.46.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/71428c5a-c831-6d0a-45cf-841c41ea43a7.png)

#### 注意点

列方向の@&#xFFF0;関数はSQLプッシュバックが効きません。DB側での工夫が必要です。

## 4.参考情報

#### 移動平均を解説した記事

https://www.ibm.com/blogs/solutions/jp-ja/modeler-tips-13/

https://qiita.com/1000aki/items/964e4190cf0ce72867f3

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
1行上/先頭行との値の差を求める(SPSS Modeler データ加工逆引き4-2)

# 1行上/先頭行との値の差を求める（階差とオフセット）

![スクリーンショット 2022-06-27 17.20.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/32ffa7ee-eac2-2968-83c8-1716c478840f.png)

## 1.想定される利用目的

・不正検知や倒産/解約/ランクアップ予測のための顧客行動の特徴量作成
・異常検知や故障予測のための特徴量作成

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/blob/main/diff_offset.str?raw=true

## 3.サンプルストリームの説明

![スクリーンショット 2022-06-27 17.31.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/970965ec-8269-9d47-2e80-c61c87aedc09.png)

a.入力するデータは以下の通りです。
![スクリーンショット 2022-06-27 18.11.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/ec3d5295-f796-fc0c-495d-85cc46ac8ce0.png)

b.[フィールド作成]ノードを編集します。[@&#xFFF0;DIFF1(フィールド)]を利用しています。１つ上のレコード（行）との差分を求めます。
![スクリーンショット 2022-06-27 18.30.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/2341f7ea-55bf-c4af-8111-5731990d6dc8.png)

式ビルダーのライブラリから@&#xFFF0;関数を探すと簡単に入力できます。
![スクリーンショット 2022-06-27 18.32.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/bb74e889-0dd1-f761-a34c-6546a0074f33.png)

[プレビュー]をします。1レコード目は関数が無効になり欠損値Nullになり2レコード目から計算されています。
![スクリーンショット 2022-06-27 18.33.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/66be5809-cbd2-4e91-7216-b5d06a08cf6f.png)

c.[関数@&#xFFF0;DIFF2]を使って差分の差分（２次の階差）を求めます。
![スクリーンショット 2022-06-27 18.45.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/33590f91-9aa8-eb71-3492-af97db40f648.png)

[プレビュー]をします。完成しました。
![スクリーンショット 2022-06-27 18.47.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8f54efd5-0339-de68-d0ed-7c0f7f6d7373.png)

#### オフセット関数を利用する

d.列方向に参照するオフセット関数でbと同じ処理をさせます。[@&#xFFF0;OFFSET（温度,1)]で温度フィールドの1レコード上を参照しますので以下の式で差分が得られます。
![スクリーンショット 2022-06-27 18.50.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/40fa992f-392d-f6e7-8b98-0e2faafe35c2.png)

e.オフセット関数を利用して先頭レコードとの差を求めます。遡るレコード数には通し番号を振る関数@&#xFFF0;INDEXを利用しています。1を引くと先頭行を参照する計算になります。
![スクリーンショット 2022-06-27 18.59.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/d55bae8a-46a0-0255-cd82-6dbcfdbd9605.png)

[プレビュー]をします。

![スクリーンショット 2022-06-27 19.08.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/e6d7a774-3733-3f53-9906-9a9e1e961a9a.png)


#### 注意点

@&#xFFF0;OFFSETは上方参照の関数ですが[@&#xFFF0;OFFSET（温度,-1)]とすると1レコード下を参照します。

## 4.参考情報

#### オフセット関数を解説した記事

https://qiita.com/kawada2017/items/41e8847b280f35fa9aa4

https://qiita.com/kawada2017/items/1385a5d4a83154792c12

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
atomic design

# tips
## atoms, molecules
流用性が高いコンポーネントの特徴としては
props名にドメイン名を含めず、抽象化されている（NG:profileName→OK:name）
margin,top,left,bottom,rightなどのレイアウトの外側の余白、位置（できればサイズも）を決定するスタイルを持たない＆props経由でスタイルを上書きすることができる
Java

# Java
## stream
- distinctByKeys
```java
    /**
     * リストから重複するオブジェクトを除却する関数を取得する
     *
     * @param keyExtractors 重複判定に使用するフィールドのgetter
     * @param <T>
     * @return 重複除却関数
     */
    private static <T> Predicate<T> distinctByKeys( Function<? super T, ?>... keyExtractors ) {
        final Map<List<?>, Boolean> seen = new ConcurrentHashMap<>();

        return t -> {
            final List<?> keys = Arrays.stream( keyExtractors )
                    .map( ke -> ke.apply( t ) )
                    .collect( Collectors.toList() );

            return Objects.isNull( seen.putIfAbsent( keys, Boolean.TRUE ) );
        };
    }

            List<HogeDto> distinctDtos = hogeList.stream()
                    .filter( distinctByKeys(
                            HogeDto::getName,
                            HogeDto::getAge ) )
                    .collect( Collectors.toList() );
```

- map to map

https://stackoverflow.com/questions/25903137/java8-hashmapx-y-to-hashmapx-z-using-stream-map-reduce-collector

## ファイル操作
https://uxmilk.jp/47743

https://stackoverflow.com/questions/1091788/how-to-create-a-zip-file-in-java

# Spring
## jpa
https://stackoverflow.com/questions/40766640/java-spring-unexpected-token

## spring security
### UT
https://reiphiel.hatenablog.com/entry/spring-security-unit-test

## controller
### @InitBinder
- エンドポイントごとに分けたい場合, 例えばカスタムバリデータなど
  - クラス名のキャメルケースで指定すればいい、webfluxだとMonoが必要?
    - WebDataBinderのobjectNameプロパティで判定している模様
  ```java
    @InitBinder("updateUserRequestMono")
    public void initBinder( WebDataBinder binder ) {
        binder.addValidators( this.requestValidator );
    }

    public Mono<ResponseEntity<Void>> updateUser( String organizationSearchId, String branchOfficeSearchId,
            String sessionId, Mono<UpdateUserRequest> updateUserRequest,
            ServerWebExchange exchange ) {
    }
  ```

### 相関チェック
いくつか方法あり
#### 相関チェックのためにValidatorをimpleした場合
- @NotNullをかけているフィールドでも、validateメソッド内ではnullが入ってこれるのでnullチェック必要

# tips
## 値の詰め替えはmapperを介すのが良さそう
- 変換パターンが増えて困る
- シリアライズの実装が必要になる？

https://stackoverflow.com/questions/67340104/dto-entity-mapping-best-practice

https://softwareengineering.stackexchange.com/questions/356964/c-initialize-dtos-in-constructor-or-via-properties

https://www.web-dev-qa-db-ja.com/ja/java/%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%A9%E3%83%93%E3%83%AA%E3%83%86%E3%82%A3%E3%81%A8%E3%83%86%E3%82%B9%E3%83%88%E5%AE%B9%E6%98%93%E6%80%A7%E3%82%92%E8%80%83%E6%85%AE%E3%81%97%E3%81%AA%E3%81%8C%E3%82%89%E3%80%81%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%82%A8%E3%83%B3%E3%83%86%E3%82%A3%E3%83%86%E3%82%A3%E3%82%92dto%E3%81%AB%E9%81%A9%E5%88%87%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/835044303/

## 内部クラスの利用
```java
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Hoge {

    @Required
    @Valid
    private List<Fuga> fugas;

    private Double hoge;

    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    public static class Fuga {

        @Required
        private String uuid;

        @Required
        private Double fuga;
    }
}
```
設計 

https://ikenox.info/blog/inheritance-and-delegation-and-interface/#:~:text=%E7%B6%99%E6%89%BF%E3%81%AF%E5%AD%90%E3%81%8C%E8%A6%AA,%E3%82%92%E4%BD%BF%E3%81%86%E3%81%AE%E3%81%8C%E8%89%AF%E3%81%84%E3%80%82&text=%E9%80%86%E3%81%AB%E3%80%81%E5%AD%90%E3%81%8C%E8%A6%AA,%E3%81%AB%E3%81%AF%E7%B6%99%E6%89%BF%E3%82%92%E4%BD%BF%E3%81%86%E3%80%82
MeCabを利用して２つの文章の類似度を計る（の理屈）

形態素解析ライブラリ　Mecabを使って、仕事をする機会があったので、そのメモ書き

サンプルコードはこの人たちの記事の方が役立つので、コピペして使用してください

https://qiita.com/Takayoshi_Makabe/items/18cefa4b4572d12b5aa9
https://qiita.com/SZZZUJg97M/items/dbdc784b92bde56cde3b

この記事では、理論的な背景と実際にどんなケースで使ったかについて書いていきます。

そもそもMeCabとは何か？から行きます。

ざっくりいうと「分かち書き」を実行するライブラリです。

分かち書きとは？？？　　

英語だと、単語と単語の間にはスペースが入っていて、文章を単語群に分解することは非常に簡単ですが、日本語は全部がつながっているので、結構大変です。どこで区切るか？？例えば

I like a cat
最初から分割されてる！


私は猫が好きです
どこで分割すればいいのか、少なくともコンピュータにはわからない！

日本人であれば、　　私は　/　猫が /　好きです　　　で分割するのは自明なのですが、コンピュータにはできないのです。それを実現するものがMecab

あ、Mecab以外にも色々ライブラリはありますが、一番使われているのがMeCabってだけです。

なんで単語を分割することが必要なのかという根本的な問いですが、答えは

「まだコンピュータは文章の意味を理解できないから」です

ディープラーニングだなんだと言っても、所詮は統計的な処理の上で動いているわけで、本質的に文章の意味というものを理解しているわけではないのです。そもそも意味とか自我とか意識とかは基本的な原理原則すら解明されてない状態

と、話がそれましたが、要するに文章を統計的な処理対象にするためには、「分かち書き」を行い、単語ベースで処理を行えるようにする必要があります。今回の場合は

文章を単語にバラして、マッチする単語の頻度を計る＝文章の類似度を計る　

ということです。

OK！　単語ベースにする理由はわかった。じゃあ具体的にどうやって計るのか

ここでちょっとだけ数学が出てきます。ベクトル（行列）です。

私は/猫が/好きです　　は３つの単語からなっているので、要素が３のベクトルと仮定してみましょう。

(私は, 猫が, 好き）

一方で私は犬が好きの場合は

(私は,犬が,好き）となります。

２つベクトルの類似度を計る方法としてコサイン類似度という手法があります。

これは２つのベクトルがどのくらい、同じ方向を向いているかを計る手法です。これは高校の時に習っていて２つのベクトルの間のコサインの値を出すだけです。
同じ方向を向いていれば１に近く、違う方向であれば0をとります。以下の図を参照
![スクリーンショット 2022-06-28 12.08.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342329/f771721d-9179-9c47-97e1-479f8297d7ec.png)

でも、ここで疑問。行列なら中に入るのは数字だけど今考えているのは単語じゃないか！

はい、そうです。なので単語は存在したら１としてしまいます。存在しなければ０
０、１だけになると犬猫の区別がつかないので、犬猫は別の要素として扱います。
そうすると２つの文章は要素が４のベクトルとして表示できます。

```math
\begin{pmatrix}
私は & 犬が &　 & 好き\\
\end{pmatrix}
\begin{pmatrix}
私は & &　猫が & 好き
\end{pmatrix}
```
０、１で表すと

```math
\begin{pmatrix}
1 & 1 &　0 & 1\\
\end{pmatrix}
\begin{pmatrix}
1 & 0 &　1 & 1
\end{pmatrix}
```


あとは計算式に値を放り込むだけです。この結果が1に近いほどベクトルが同じ方向を向いている＝文章の類似度が高いという結果になります

```math
\frac{{a_1}{b_1}+\cdots+{a_n}{b_n}}{{\sqrt{a_1^2 + \cdots + a_n^2}}{\sqrt{b_1^2 + \cdots +b_n^2}}}  
```



で、この手法をすると何かいいことがあるの？という話ですが、例えばこんな感じで使用できます。

ユーザ投稿系サイト
ユーザの書き込んだ内容を元に、同じ内容と思われるものを同一カテゴリにまとめる


商品比較サイト
いろいろなECサイトから集めた商品名称のうち、同じ商品と思われるものを同一商品と認識

マッチングアプリ
２つのプロフィール文章のマッチ率から、より高いマッチ率の高い人をレコメンド



ただ、コサイン類似度が万能というわけではなく、単語数に沿って要素（行列の次元）が増えていくので、長い文章の比較をする場合は計算量が膨大になります。また単語数が増えるほどマッチ率が落ちる「次元の呪い」なるものがあるようですが、ハマったことがないので詳しくは知らないです。

また確率的に類似度が高いというだけなので、１００％のマッチを求める場合は、人が最終チェックを行ってOK/NGを出すような管理画面が必要になります。

実装する前に、要件とこの辺りの前提条件をよく吟味するといいと思います。
【android】ソフトウェアキーボード出現によりviewportを縮める件

<h2>はじめに</h2>
<p>


webページのレスポンシブ対応をしている時にandroidはソフトウェアキーボード出現によってフッターを持ち上げてしまい、画面の見栄えがよくなかったのでそちらを修正しました。
次回同じ課題にぶつからないように忘記録です。
</p>

<h2>修正方法</h2>

index.htmlファイルに直接`javascript`を記述します。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <title></title>
    <meta
      name="viewport"
      content="width=device-width, height=device-height, initial-scale=1 ,maximum-scale=1"
    />
  </head>
  <body>
   /* ここを追加するだけです */
    <script>
      let viewport = document.querySelector("meta[name=viewport]");
      viewport.setAttribute("content", viewport.content + ", height=" + window.innerHeight);
    </script>
　　/* ここを追加するだけです */　
    　　　　　　　　　　　　　　・・・省略
  </body>
</html>


```

簡単です。上記コードを追加するだけで持ち上がりは解消できます。

<h2>まとめ</h2>
<ul>
<li>持ち上がり自体は解消できましたがiPhoneと同じ挙動にはなりませんでした。(javascriptで他にも制御が必要かもしれません。)</li>
<li>フッターにfixed使っていれば上のコードでも関係なく持ち上げられます。(画面でみてしまうので)</li>

<p>
レスポンシブ対応は他にもアドレスバーの出現で高さが変わる問題など勉強することが多そうです。
めげずに頑張ります。
</p>
</ul>
研修で人を集めるときのアンチパターンとグッドパターン

# この記事で書くこと
研修の参加者募集段階でのアンチパターンとグッドパターンを紹介します。
基本的には、社内での研修開催を想定した内容を書いています。

# 対象とする読者
+ 研修の開催を検討している方
+ 研修でなかなか人が集まらなくて困っている方

# 初めに
どんなに優れた内容の研修でも、
**日程調整や募集の方法がイケていないと、人が集まりません。**
人が集まらなければ、せっかく作った研修も意味を成しません。
日程調整や募集方法のアンチパターン、グッドパターンについて、
筆者の実体験を元に紹介します。

# アンチパターン
## 月末月初を選んでしまう
月末月初はプロジェクトの異動や、
締め処理、月初の集計処理などで、稼働が取れない人がいます。

**例えオンラインでも、作業が逼迫する可能性があるため、
参加をためらう方がいると思います。**

+ 運用者なら月初の集計処理で稼働が取れない
+ マネージャーなら月末月初の締め処理で稼働が取れない
+ などなど

## 連休の前後に入れる
プライベートな予定があるため、参加を見送るパターンです。
お盆、ゴールデンウイークなどの大型連休の前後は、
繋げて休む人が出てきます。
**「全日程参加必須」などの研修には、
参加をためらう方が出てくるかもしれません。**

また、祝日を含めて3連休になるところも危険です。
金曜日も、夜にプライベートな予定を入れる方がいるので、避けた方が良いかもしれません。

## 他の社内行事と被る
オンラインイベントが普及した昨今、
**定時後に登壇イベントなどがあり、
そちらに参加するために、研修の参加をためらうケースもあります。**

技術に興味のある人ほど、こういったイベントに参加される傾向があると思います。
それだけに、日程が被ると、双方のイベントの参加機会損失に繋がるのです。

## 全日程参加必須！
全日程に参加できない方はお断り！、といった前提条件は、
**前述の理由で「1日だけ参加できない方」は参加できず、
また、「業務都合で欠席する可能性が高い方」にとっても、
参加の心理的なハードルが高くなります。**

逆に、欠席しても動画やテキストでの補習が可能、などとしておけば、
参加の物理的、心理的なハードルは下がります。


# グッドパターン
## 参加したい方に声をかけ、都合のつく日程のヒアリングを行う
参加したい、という意思のある方（参加候補者）にお声がけし、
まず、そのメンバーだけで、都合の良い日程をヒアリングします。

募集方法を少し工夫しなければいけませんが、
**参加候補者にとっては、興味のある内容を都合の良い日に受講でき、
開催側にとっては、日程と参加者の募集を確実に行える、**
という双方にメリットのある方法です。

また、メンバーの日程が確定したら、
改めて全体に募集をかける、というのもありです。
※参加枠に空きがあれば

## コネクションを使う
+ **自分が以前いたプロジェクトのメンバーに打診する。**
  - 知り合いが多ければ心理的にも打診しやすく、
    参加候補者も回答しやすいと思います。
+ **研修で学ぶ技術を現場で使っているプロジェクトのリーダー（or マネージャー）にアナウンスしてもらう。**
  - うまくいけば大勢の参加を見込めます。
  - 個人ではなく、マネージャーなどから打診してもらう方が効率的。
    知らない人に直接募集を呼び掛ける、という心理的負担も無くなります。
+ **以前同じような研修に参加した人に打診する。**
  - 同じ技術の研修であれば、募集に応じる人が出る可能性が高いです。
+ **コネのある方に頼む！**
  - 社内に知り合いが多くいる方に、参加呼びかけをお願いする方法。
    （個人的には、効果は抜群だ！ と思います）




# 参考：私の経験談
実際にあった私の経験（失敗談と成功談）です。
読み飛ばして頂いても問題ありません。

```
私は過去に何度か Elasticsearch の研修を行っていました。
その時は、概要レベルや初級レベルの内容だったこともあり、
最低でも5名、最大で10名近く集まることもありました。

で、調子に乗って上級レベルの研修をやろうと思いました。
自分の都合が良い月末に連続で予定を入れ、
基本「全日程参加必須」の上で、募集をかけたところ。。
。。
。。。
参加者ゼロ。。

Slack やメールでも募集を呼びかけましたが、
まあ集まらない。。

そこで、コネのある方に参加呼びかけをお願いし、
集まった方に話を伺うと、
「参加したかったけど、月末は締め処理で忙しいので、連日の参加は厳しい」
「内容は気になったけれど、月初に異動を控えており躊躇した」
というご意見を頂きました。

そこで、一旦日程をリセットし、
参加条件も「全日程参加しなくてもOK。テキストで補修可能」に変更し、
参加してくれそうな人を募りました。
その上で、集まった方に希望の日程をヒアリングしました。
　※研修運営チームにお願いして、ヒアリングの場を設けて頂きました

また、同じプロジェクトの方に参加を打診したり、
別のプロジェクトに知り合いの居る方にも、募集を行って頂きました。

結果として、何とか参加者を確保することに成功。
人のつながりと、参加者目線に立つことの重要さを痛感しました。
```

# サマリ
## 日程調整は参加者目線で行う
自分がやりやすい日程ではなく、
**参加する人が入りやすい日程を選ぶ（or 選んでもらう）** ことが大事です。
これは例えオンラインでも同様です。

## 多くの人を巻き込む
会社の研修運営チームや、上司、旧プロジェクトの人などなど、
**知っている人に声をかけて人を集めましょう。**
周知して待っているだけでは、なかなか人は集まりません。


自分一人では研修はできないのです。
[Unity]ShaderGraphで複数マテリアルをひとつにまとめる


![desktop.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/df6c8cc0-e6c7-41a4-a785-fc9cd10c0542.png)

## はじめに
一つのオブジェクトに複数の異なる色や質感をアタッチしたい
方法は大きく2つある。
**1. マルチマテリアル方式──複数のマテリアルを使って色分けする**
**2. UVテクスチャマッピング方式──1つのマテリアルの中でテクスチャを使って色分けする**
##### 1. マルチマテリアル方式
サブメッシュというメッシュをマテリアルごとに割ってグループ化する仕組み
DCCツールがあれば簡単に作れる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/5ad16859-1b5c-7b30-c3b0-6271ca21ef73.png" width=256>　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/9a911c07-e6ac-e323-e44e-146d3ef22b08.png" width=256>　
こんな感じ↑

複数のマテリアル、その数と同じだけのサブメッシュ
ただし複数マテリアルを使うとそのぶんだけドローコール数が上がってしまい負荷の原因になる
また、オブジェクト数が増えていくとマテリアル数が膨大になり管理がやや面倒

##### 2. UVテクスチャマッピング方式
テクスチャで質感を指定する仕組み
SubstanceやQuixel、簡単なものではPhotoshopのようなペイントツールなどでテクスチャを作成する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/e86f5d88-d0f3-ef3e-0980-29d84b3ae11d.jpeg" width=256>　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/87efc2c5-f433-5c5f-9057-59b13bee28a8.png" width=256>　

アルベド(拡散色)のテクスチャはこんな感じ↑

UVに画像をマッピングしているのでトポロジーに影響されず色分け、質感分けができる
テクスチャを使うのでメモリを使うものの、マテリアルをまとめられるため描画負荷が少ない
UVの編集が必要、テクスチャ編集ツール（Quixel,Substanceなど）が必要
また質感や色の調整をするためにいちいち外部ツールで画像を編集しなければならず修正が手間
画像の解像度に見た目が依存する

## マルチマテリアルとUVテクスチャマッピングのいいところ取りをしたい
本当に最適化したかったり質感を詰めたいのであればもちろんUVテクスチャマッピングがいい
でもいつもUVを開いたりテクスチャを丁寧に描く時間があるわけじゃないし、
いつもモバイル並みの最適化が必要なわけでもない
かといってマルチマテリアルもオブジェクトが増え過ぎるとマテリアルの管理の手間もパフォーマンスへの影響も無視できない

マルチマテリアルのお手軽さを活かしつつ、マテリアル管理やパフォーマンスを改善したシェーダーを考えてみたい

こんなふうにUVの領域を区切って動的に質感を調整できる仕組みにしてみた↓
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/439edfe4-fcd6-d4e5-687c-4b592631aff2.png" width=256>　
マテリアルとしてはひとつにまとめてあるけれどV座標0.1刻みで質感を変更できるようにしており、最大10マテリアルぶんの質感を個別に調整できるようにした

ShaderGraphの中身
左側で10領域ぶんのマスクを作成し、右側でマージしてセットしている
10領域ぶんの処理を作っているのでノード数が多いが、基本的にマテリアルの数だけ同じ処理を繰り返しているだけ↓

![multi.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/87aacc70-91c8-f77e-6424-a6c4ea03a906.png)


DCCツールでオブジェクトの確認
マテリアル領域を分けずに書き出す↓
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/f72bef5a-946d-3385-1790-811e478ed4ea.png" width=256>　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/b4420876-f186-4cb7-8703-d4ab7837561a.png" width=256>　

UVの設定
Substanceで使うほどしっかり開く必要はない
あくまでどのポリゴンがどの質感を拾うようにするのか区分けしているだけなのでUVの重なりもサイズも気にしない↓
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/cfa50d95-9958-6c15-7666-e95f3080fb9d.png" width=256>　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/d1882270-28dc-2fc9-60be-411900783ad0.png" width=256>　

シェーダ設定
6色を1マテリアルにまとめて色調整する↓
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/a16ef6cc-3c0b-ae15-9e29-99be70e21deb.png" width=256><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/669c5d8c-8828-1e6f-0d95-24261ea42a54.png" width=512>

色と質感の変更
マテリアル1つにまとまっているので調整しやすい↓
![cam.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/b84a1cb3-9d8d-5b16-094f-231df2e46139.png)

## まとめ
UV編集だけやや面倒だが一度設定してしまえばその先の作業が簡素化されて楽
Terraform Importメモ


# 概要

* コード化を楽にしたい
* コード化するにあたって記述方法がわからない対象がある

# 前提

* AWSの場合
* コード化されていないリソースが存在すること

# 詳細

## コード化補助として使う場合

* 既存の”dev-documents”という名前のS3バケットをインポートしたい場合
* プロジェクトディレクトリを作成後、その中に簡易な設定のmain.tfを作成
    
```
$ mkdir old_project
$ cd old_project
$ vi main.tf
```


```:main.tf
# ---------------------------------------------
# Main Setting
# ---------------------------------------------
//最低限の設定を記述
provider "aws" {
  region = "ap-northeast-1"
}
terraform {
  required_version = ">= 1.1"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 4.20.1"
    }
  }
}
//importする対象の空リソース定義を記載
resource "aws_s3_bucket" "dev_s3_bucket_sample" {}
```

```
//terraform用ディレクトリに移動
$ cd old_project

//ワークスペースを初期化しstateファイルができている事を確認
$ terraform init
$ ls -l terraform.tfstate

//手動で作られたリソースをterraform下に置く（ここでは”dev-documents”という名ですでに存在するS3バケットをインポート）
$ terraform import aws_s3_bucket.dev_s3_bucket_sample dev-documents #インポートする対象はリソース名を指定する
:
Importing from ID "dev-documents"...
Import prepared!
Refreshing state... [id=dev-documents]
:
Import successful!

//インポートされたリソースがstateファイル内に詳細が記載されている事を確認
$ cat terraform.tfstate

//terraform管理下にあるリソースを出力
$ terraform state list                                                         
aws_s3_bucket.dev_s3_bucket_sample

//コード化が終わった不要なのでterraform管理外にする。stateファイルから内容が消える。
$ terraform state rm aws_s3_bucket.dev_s3_bucket_sample
Removed aws_s3_bucket.dev_s3_bucket_sample
Successfully removed 1 resource instance(s).


```

## 既存の一部リソースを除いてterraform applyしたい場合

* applyしたが既にそのリソースが存在するとしてエラーになってしまった場合、対象のリソースをterraform管理下にしてしまう

* 以下は例としてsecretmanagerのリソースがすでに存在していてapplyできない場合

```
Error: error creating Secrets Manager Secret: ResourceExistsException: The operation failed because the secret dev-secretmanager-rds already exists.
```

```
//terraform管理下に無いことを確認
terraform state list

//既存のリソースをインポートしてterraform管理下に
terraform import aws_secretsmanager_secret.dev_secretsmanager_rds dev-secretmanager-rds

//terraform管理下に入った事を確認
terraform state list

//terraform全体適用
terraform apply

```

* 例：手動作成したRDSをImportする場合
    * ClusterからまずImport

```
//rdsclusterの名前(DB識別子)を引数に指定
$ terraform import aws_rds_cluster.dev_rds_cluster dev-rds-cluster
//rdsライターインスタンスの名前(DB識別子)を引数に指定
$ terraform import aws_rds_cluster_instance.dev_rds_cluster_instance dev-rds-instance-01
//rdsリーダーインスタンスの名前(DB識別子)を引数に指定
$ terraform import aws_rds_cluster_instance.dev_rds_cluster_instance dev-rds-instance-02
```
<%= render @boards %>

部分テンプレートを呼び出す際に使用される。部分テンプレートとは```_board.html.erb```などのことで、この部分テンプレートを繰り返し表示される際にはcollectionを使用する。

例えば

```_board.html.erb
<%= board.title% >
<%= board.body% >
```
この部分テンプレートをcollectionを使用せずに書くと
```index.html.erb
<% @boards.each do |board| %>
  <%= render 'board', board: board %>
<% end %>
```
eachを使い繰り返し呼び出している。

collectionを使用し書くと
```index.html.erb
<%= render partial: 'board', collection: @boards %>
```
collectionに@boardを渡して、内部要素を１つ１つ取り出している。意味的にはにはeach文とほぼ同じように見えるが、まとめて部分テンプレート呼び出すためパフォーマンスが良い！

ちなみにeach文だとレコードの数だけ繰り返し呼び出すため1万件レコードがあった場合パフォーマンスは歴然である。

だってcollectionのほうは１/10000だからね

collectionは省略して書くこともできる。
```index.html.erb
<%= render @boards %>
```
ただし条件があって

部分テンプレートが呼び出し元のテンプレートと同じディレクトリ内にある
```index.html.erb```と_```board.html.erb```（部分テンプレート）が同じディレクトリにある
部分テンプレートのファイル名がオプションで指定した変数の単数形である
オプションで指定した変数名が@boardsであれば、部分テンプレートは```_board.html.erb```である
部分テンプレート内で使用する変数名が、オプションで指定した変数の単数形である
オプションで@boardsを渡したなら、部分テンプレート内で使用する変数名がboardである
オプションで@boardsを渡したなら、部分テンプレート内で使用する変数名がboardである
参考というかほぼパクリ　https://himakuro.com/rails-render-collection
インターン体験談


# 自己紹介
- 私は，九州の国立大学の情報系学科に所属している3年生です．
- プログラミングを始めたのは高校生の時ですが，授業等で基礎的なものを学んだり，趣味で書いたりする程度で実務経験はありませんでした．

# インターンに応募した理由
- プログラミングがどういう風に仕事になるのか知りたかったから
個人や大学で C++ や Python は触っていましたが，簡単なものしか描いたことがなく，これがどういう風に仕事になるのか分からなかったので実際に経験しようと思いインターンに応募しました．

# 具体的な業務内容
- サーバーサイドのシステム開発
動画配信サービスのサーバーサイドのシステムの開発に携わっています．使用しているインフラは AWS で，実際に Python のコードを書くことで Lambda の作成・改良することで機能の追加・修正を行っています

# インターンをして得られたもの
- コードを読む力
自分以外の人が書いた多くのコードを読むことで，そのコードの機能や書いた意図を理解する力が身についたと思います．

- AWS の使用方法
AWS は個人でも利用しようとしたことがありましたが，機能が良く分からない無いままでした．しかし，実際に業務で使用していくことで Lambda や Log の使い方が分かるようになりました．

- 問題を解決する力
コードが動かない，意図した動作をしない事は良くあります．その時に，エラー文やログを見ることで上手く行かない箇所を特定し，調べて上手く動作するように修正する事で問題を解決する力が身についたと思います．また，エラーやログ，ネットの記事は英語で書かれていることが多いので英語に対しての抵抗も減りました．

# まとめ
インターンに参加して実際に業務にかかわると，学べることはたくさんあります．
ですので，プログラミングに興味のある人，大学や個人でアルゴリズムなどは学んだけど，実際にどういう風に利用されているのか知りたい人は，インターンに応募してみてほしいです．
【C#】WebDriverManagerでドライバの自動更新【Selenium】

Windows10
.NET Framework 4.72
上記環境でハマったので備忘録です。

### ハマったポイント

自動更新がうまくいかず、「ドライバが古いよ」エラーがでる。

#### 解決策

ドライバの起動場所を指定してあげる。
-> ___"./Chrome/{driverVersion}/X64/"___
```c#
//Chrome

//ドライバ自動更新
new DriverManager().SetUpDriver(new ChromeConfig(), VersionResolveStrategy.MatchingBrowser);

// WebDriverManagerが保存した場所
var driverVersion = new ChromeConfig().GetMatchingBrowserVersion();
var driverPath = $"./Chrome/{driverVersion}/X64/";

//ドライバの起動場所を設定
using (var driverService = ChromeDriverService.CreateDefaultService(driverPath))
{
    //ドライバの起動
    using (var driver = new ChromeDriver(driverService))
    {
        driver.Navigate().GoToUrl("https://google.com");
    }
} 
```

#### やってみたこと

NuGetから下記をインストール
１．Selenium.WebDriver
２．Selenium.WebDriver.ChromeDriver
３．WebDriverManager

ReadMe通りに書いて動かしてみると

-> ドライバが古いエラー

「なんでやねん」

ということで場所を指定して起動してあげることでうまくいきました。

結果、「２．Selenium.WebDriver.ChromeDriver」はインストールする必要がありません。

自動でダウンロードしてくれますから。

#### この記事が役に立ったと思ったら…
LGTMお願いします！
励みになります！！
よろしくお願いします。