OmniAICreator/Qiita-1.07M huggingface dataset:
Next.jsを公式に沿ってインストールしてみる備忘録

[Next.js 公式ページ](https://nextjs.org/learn/basics/create-nextjs-app/setup)のざっくりした日本語訳。
## 環境
+ Windows 10 Pro 21H1
+ VSCode：1.63.2
+ npm：6.14.8
+ Node：v16.13.1

## 手順
###自動でセットアップしたいとき(推奨)  
####新しいAppをインストールする
`npx create-next-app@latest`または`yarn create next-app`をターミナルで打つ。([npxについてはこちら](https://dev.classmethod.jp/articles/node-npm-npx-getting-started/))  
`create-next-app`を使うと自動ですべてセットアップしてくれるので推奨。  
typescriptで開発したい場合は、上記のコマンドに`--typescript`オプションをつければOK。  
途中でどんなプロジェクト名にするか聞かれるの(What is your project named? )で、好きな名前を入れる。  
これら👇を一緒に入れてくれる。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2410508/f01c196a-fdab-305b-c1f1-5802facf2fdc.png)  
今👇こんな感じ  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2410508/dc666082-2252-67e9-2abf-40b77d31f843.png)  

#### 実行してみる
作成したプロジェクトに移動(`cd プロジェクト名`)して、`npm run dev`するとアプリが立ち上がる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2410508/1c7307e6-5c9c-e68f-07fe-12020c0d4bdf.png)

###マニュアルでセットアップしたいとき  

next、react、react-domをインストールする。  
`npm install next react react-dom`または`yarn add next react react-dom`  
今回は以下のバージョンがインストールされた。
  + react：17.0.2
  + react-dom：17.0.2
  + next：12.0.7  

`package.json`を作成して以下の情報を追加する  

  ```json
"scripts": {
  "dev": "next dev",
  "build": "next build",
  "start": "next start",
  "lint": "next lint"
  }
  ```

ためしに`npm run dev`してみると、  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2410508/0ae4819c-064c-d59c-f490-b928e4dc3b63.png)
404になる。  

`pages`フォルダを追加する。  
`pages`フォルダに`index.js`ファイルを追加する。中身は、

```js
  function HomePage() {
  return <div>Welcome to Next.js!</div>
}

export default HomePage
```
 
`npm run dev`で実行する。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2410508/3e8c73ff-ecfc-559a-fa95-301008165a38.png)
ページは、それぞれのファイル名に基づいて関連付けられている。
例えば、`pages/about.js`は、`about.js`にマップされる。
ファイル名を使って、動的なルートパラメータを追加することもできる。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2410508/d1fd9ada-5bc9-1652-d24c-9aff677642f0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2410508/526cd313-d243-457e-224d-7bddbfcefbab.png)
CoreMLToolsで変換できないときは、対応していないオペレーションを書き換えて変換してしまおう pytorch convert function for op '　' not implemented.

#CoreMLToolsで変換できないオペレーションがあった時の対処法
機械学習モデルをiOS用に変換するCoreMLToolsで、変換ができなかった時に、なんとか変換を試みる方法です。
<img src="https://user-images.githubusercontent.com/23278992/147424907-a2063ec2-d4e2-4798-9361-02c0511bd190.jpeg", width=600>

#エラーが出ても変換したい

機械学習モデルを変換していると、エラーが出る時がある。
でも、なんとか変換したい。
変換スクリプトが対応できていないモデルは結構あるが、どうにかして返還できればそれらのモデルをiOSで使える。

>pytorch convert function for op 'var' not implemented.

#CoreMLToolsが対応していないオペレーションがあることが原因
例えば、上記であれば 'var'という分散を求めるpytorch関数を変更する関数がCoreMLToolsにないから変換できない。

#手動で計算を書いてあげて解決する
関数が対応していないなら、対応しているものだけで関数を代替してしまえばいい。
上記であれば、分散を求める計算を書くことによって、CoreMLToolsで変換できる。

なぜなら、
１、分散は平均から求められる。
２、平均は torch.mean という関数で求めることができる。
３、torch.mean は CoreMLTools で変換できる。

したがって、手書き計算に置き換えて、CoreMLToolsで変換できる。

```python
# torch.meanを使って、torch.varを再現
mean = torch.mean(input)
var = torch.mean((input - mean)**2)
```

上記は平均関数を使って、分散を求めている。

>分散を求める
１、平均を計算する
２、偏差（数値 － 平均値）を計算する
３、偏差の二乗平均（＝分散）を計算する

これで、変換できる。

モデルを上記のように書き換えることによって、無事変換できた。
【変換できたPhoto2Cartoonの出力】
<img width="257" alt="スクリーンショット 2021-12-26 6 16 31" src="https://user-images.githubusercontent.com/23278992/147424571-ca12ceda-42bf-43b0-94fa-28a05d255940.png"><img width="256" alt="スクリーンショット 2021-12-26 7 58 18" src="https://user-images.githubusercontent.com/23278992/147395080-a06c1e74-37a0-405c-9378-3151de5b6acd.png">

#留意事項
ただし、pytorchのvar関数が求めるのは不偏分散で、厳密には分散と違う。
なので、出力も少し違う。

【微妙に違う出力。左オリジナル／右手動変換したCoreMLモデル】
<img width="256" alt="スクリーンショット 2021-12-26 7 57 49" src="https://user-images.githubusercontent.com/23278992/147395079-efda9b6f-ebbf-45fe-81f6-78c32b6cd4b3.png"><img width="256" alt="スクリーンショット 2021-12-26 7 58 18" src="https://user-images.githubusercontent.com/23278992/147395080-a06c1e74-37a0-405c-9378-3151de5b6acd.png">

しかし、ないよりはマシ、ということで、変換してしまう。
というか、不偏分散を求める計算を入れればよかったのか。。。

こちらの記事を参考にさせていただきました。

[pyTorch torch.var()の値が分散ではない](https://qiita.com/mathlive/items/69b00937d37c2faea1a5)

https://qiita.com/mathlive/items/69b00937d37c2faea1a5

#いろんなモデルを変換できる
対応していないオペレーションに出会ってつまづくことはあるが、上記のように変換可能な形に置き換えることによって、
いろんなモデルをモバイルに変換できる。


🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
簡単な開発内容をお書き添えの上、お気軽にご連絡ください。
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
Laravel + Amazon S3で、複数のバケットを使いたい

# まえがき
いや、我ながらやり方分かっちゃうと、結構低レベルな話...となったのですが、同じことで困っている人のために書いておきます。
（ググっても全然出てこなかったのは、簡単すぎるせいか...）

もともとAmazon S3はDBのバックアップで使用していたのですが、動画のストリーミング再生もしたいということで、動画をAmazon S3に置くことになりました。
というわけで、いつもは一つしか使っていなかったバケットですが、今回は２つ使うことになって、え！？でも違うバケットってどうやって設定するん！？ということになりました。


# とりあえずデフォルトのバケット設定して

[Laravel 公式](https://readouble.com/laravel/8.x/ja/filesystem.html)

.envにAWSのリージョンとか、キーとか、バケット書けばOK!!

```

AWS_ACCESS_KEY_ID=自分のやつ
AWS_SECRET_ACCESS_KEY=見て
AWS_DEFAULT_REGION=書いて
AWS_BUCKET=バケット名

```


# もう一つのバケットは...??
うーん、.envにはバケットひとつしか書けないじゃん...あたいどうすんのよ。。

`config/filesystems.php`に書けるよ!!
これを追加したらいいんだよ↓

```php

/** こちら、もとからある方です */
's3' => [
    'driver' => 's3',
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION'),
    'bucket' => env('AWS_BUCKET'),
    'url' => env('AWS_URL'),
    'endpoint' => env('AWS_ENDPOINT'),
],

/** こちら、追加した方です */
's3_movie' => [
    'driver' => 's3',
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION'),
    'bucket' => 'ここにもう一つのバケット名入れてくれ', //★★★ この行見て★★★
    'url' => env('AWS_URL'),
    'endpoint' => env('AWS_ENDPOINT'),
],

```

実際にS3に接続する処理

```php

//disk名を、新しく追加した方の名前にするよ
$disk = \Storage::disk('s3_movie');

```


# まとめ
この方法を応用すれば、違うS3に接続するのも簡単だ!!
bucket名が環境によって違うのであれば、直書きではなく、.envに書いて取得してくれ！

やり方が分かってしまえば、大したことない話なんですがね...こういう記事も需要あるんでは？？
備忘録 M1Mac+Lima+DockerでDocker compose開発する際のポイント

# tl;dr

* 多くのイメージはarm64v8でimageを探すと見つかることがあるよ
* mysqlはmysql-serverはmysqlと動きが異なるので、arm64v8/mariadbを使ったほうが良いよ
* lima + dockerに接続するならunix socketが良いよ

# Lima+Docker+Docker Compose+OSX環境

DockerDesktopがおもすぎる問題は非常に言われており、ベンチマークも各所に上がっている。DockerDesktopが重いシンプルな理由としては以下が挙げられる

* 別アーキテクチャ(Intel x64)のエミュレートをしているため、動作が超非効率
* Macのディスクをマウントして動作させているため、これまた動作が非効率（Intel macでも同様の現象あり）

この問題はひとえにCPUのアーキテクチャが全く異なることからきている。

筆者は Lima + Docker + DockerCompose 環境でPython/PHPの開発が多いのだが、全てをubuntuから独自イメージを作ってない人にとっては、ハマりがちという問題がある。
２日ハマりきった経験をもとに知りたかった情報をまとめます。

# arm64v8を使おう

M1MacのCPUのアーキテクチャ名は linux/amd64 でも、 linux/x86_64 でもなく、 「linux/arm64v8」であることをしっかりと念頭に置く必要がある。
現在M1Macのような新しいアーキテクチャ対応のDockerプログラムは徐々に出つつあり、メジャーなDocker imageでは対応されつつあるが、mysql（8のみ限定的に対応）やphpmyadmin（公式では非対応）などのDockerを使っている場合など、そのままでは動作しないケースも多い。

2021年12月時点では、「arm64v8 <ソフト名> docker」のような検索をすることで野良docker imageが出てくることが多いので、それを使うという手もある。

以下は、よく行う変換のルールだ
* mysql -> [arm64v8/mariadb](https://hub.docker.com/r/arm64v8/mariadb/) (mysql5.7の場合はmariadb10.3, mysql8の場合は mariadb10.7)
* phpmyadmin/phpmyadmin -> arm64v8/phpmyadmin
* wernight/ngrok -> athombv/ngrok (ルールの書き換えが必要)

# ~/work などを作ってwritableにmountしよう

Limaの仕様上、~をwritableにするのは推奨されていないため、~/workなどをwritableにするのが良い
Limaは内部ではsshfsを使っているのだが、sshfs + Docker Volumeの組み合わせはdocker側を止めて置かないと、dockerが保持しているvolumeデータを残したまま次に接続しようとしてしまう。再起動して「volume notempty」のエラーが出た場合は、
1. dockerを全部削除
2. limaで入って、 /Users/<username>/work などのフォルダを削除（中身を確認、だいたいdockerでマウントされているものがはいっている）
というフローで解決できる

# limaのインストール後に出てくるunix socketを使ってdockerしよう

limaの公式のdockerの設定を使うと、最後にunix socketの情報が出てくる。
このunix socketの情報を正しく設定すると、非常にうまく動作する。一方、ipアドレスベースでの指定は非常にバグが多く、うまく動作しないことが多い。
reTerminalの保護シート

reTerminal、タッチパネルということもあり、LCDに指紋がベタベタに残ってしまいます。
イヤだなぁと思っていたのですが、、、株式会社ミヤビックスに相談したところ、超速アッという間に保護シートを作ってくれました。

左は保護シート無しの素reTerminal、右は**低反射タイプ（OverLay Plus）の保護シート付き**reTerminalです。

<img width="600" alt="image.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/8a490ba5-7489-1f4a-5d5c-95e3f7534e5d.png">

違いは一目瞭然ですね。

LCD表示もくっきり見えますし、タッチパネルも問題なく動作します。スバラシイ。

<img width="400" alt="image.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/3587477f-e2e5-b1a0-213b-4c35eb9506d4.png">

そして、この保護シートですが通販で購入できるようになりました。

https://twitter.com/visavis_miyavix/status/1475730755145846786

以下店舗で購入可能です。

* [ビザビ本店サイト](https://www.visavis.jp/)で「reTerminal」を検索
* [Amazon](https://www.amazon.co.jp/s?k=OverLay+Seeed+reTerminal&crid=F5926Z3SP7B1&sprefix=overlay+seeed+reterminal%2Caps%2C315&ref=nb_sb_noss)
* [楽天](https://search.rakuten.co.jp/search/mall/Seeed+reTerminal/?sid=218240)
* [Yahoo](https://store.shopping.yahoo.co.jp/visavis/search.html?p=Seeed+reTerminal#CentSrchFilter1)
* [スイッチサイエンス](https://www.switch-science.com/catalog/list/1093/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/72df7d6c-4c65-da2e-f725-c720c2df9d1a.png)
Raspberry Pi pico で main.py を書き込んだあとに工場出荷時に戻す方法

BOOTSEL を押しながら USB 接続して flash_nuke.uf2 を書き込む

( main.py を書き込むと ' USB デバイスが認識出来ません ' 状態になって Thonny からも接続出来なくなったので回復方法について調べた結果 )
Databricksから AWS S3,  Azure Blob,  ADLS へのアクセス（サンプルノートブック集)



AWS, Azureのデータレイクストレージ (S3, Blob, ADLS gen2) 上にあるデータを、データブリックス上にロードする際のサンプルノートブックを作ったのでここにまとめておきます。

みなさまご自由にご利用ください。

### AWS S3 
参考：<a href="https://qiita.com/maroon-db/items/f91165612c4d43e53c87" target="_blank"> Databricksから S3 bucket へのアクセス方法を整理してみた</a>

- AccessKey認証: <a href="https://sajpstorage.blob.core.windows.net/maruyama/qiita_s3/AWS_S3_accessKey_import.html" target="_blank">サンプルノートブック</a>
- Instance Profile設定: <a href="https://recipe.kc-cloud.jp/archives/17000" target="_blank">参考サイト(ナレコム様)</a>

### Azure Blob 

- Storage Account認証: <a href="https://sajpstorage.blob.core.windows.net/maruyama/qiita_blob/Azure_Blob_storageaccount_import.html" target="_blank">サンプルノートブック</a>
- SAS認証: <a href="https://sajpstorage.blob.core.windows.net/maruyama/qiita_blob/Azure_Blob_SAS_import.html" target="_blank">サンプルノートブック</a>


### Azure Data Lake Storage gen2

- Storage Account認証:  <a  href="https://qiita.com/maroon-db/items/8cbb8bb14adeead7bed0" target="_blank">(参考: Qiita記事)</a>
    - <a  href="https://sajpstorage.blob.core.windows.net/maruyama/qiita_adls/notebook/ADLS_StorageAcount/ADLS_DBFS_AccountKey_import.html" target="_blank">サンプルノートブック[DBFS]</a>
    - <a  href="https://sajpstorage.blob.core.windows.net/maruyama/qiita_adls/notebook/ADLS_StorageAcount/ADLS_DirectFromNotebook_AccountKey_import.html" target="_blank">サンプルノートブック[Direct Access]</a>
    - <a  href="https://sajpstorage.blob.core.windows.net/maruyama/qiita_adls/notebook/ADLS_StorageAcount/ADLS_DirectFromCluster_AccountKey.html" target="_blank">サンプルノートブック[Cluster資格]</a>

- SAS認証：<a  href="https://qiita.com/maroon-db/items/1df46d0c088a550ab053" target="_blank">(参考: Qiita記事)</a>
    - <a  href="https://sajpstorage.blob.core.windows.net/maruyama/qiita_adls/notebook/ADLS_SAS/ADLS_DBFS_SAS_import.html" target="_blank">サンプルノートブック[DBFS]</a>
    - <a  href="https://sajpstorage.blob.core.windows.net/maruyama/qiita_adls/notebook/ADLS_SAS/ADLS_DirectFromNotebook_SAS_import.html" target="_blank">サンプルノートブック[Direct Access]</a>
    - <a  href="https://sajpstorage.blob.core.windows.net/maruyama/qiita_adls/notebook/ADLS_SAS/ADLS_DirectFromCluster_SAS_sample.html" target="_blank">サンプルノートブック[Cluster資格]</a>

- Service Principal:<a  href="https://qiita.com/maroon-db/items/84f47e8ca28056202d0e" target="_blank">(参考: Qiita記事)</a>,  <a  href="https://sajpstorage.blob.core.windows.net/demo-asset-workshop2021/blog/adls_container_level_ac_by_secrets.html" target="_blank">(参考：構築Blog)　</a>
    - <a  href="https://sajpstorage.blob.core.windows.net/maruyama/qiita_adls/notebook/ADLS_ServicePrincipal/ADLS_DBFS_ServicePrincipal_import.html" target="_blank">サンプルノートブック[DBFS]</a>
    - <a  href="https://sajpstorage.blob.core.windows.net/maruyama/qiita_adls/notebook/ADLS_ServicePrincipal/ADLS_DirectFromNotebook_ServicePrincipal_import.html" target="_blank">サンプルノートブック[Direct Access]</a>
    - <a  href="https://sajpstorage.blob.core.windows.net/maruyama/qiita_adls/notebook/ADLS_ServicePrincipal/ADLS_DirectFromCluster_ServicePrincipal_import.html" target="_blank">サンプルノートブック[Cluster資格]</a>


(*) _もし問題や改善点があればお知らせください。_
【React】useRefとforwardRefを両立する方法【関数コンポーネント】

Reactで関数コンポーネントを作成する際、同じDOMノードに対して

* forwardRefでDOMノードをフォワーディングする
    * 参考: [ref のフォワーディング – React](https://ja.reactjs.org/docs/forwarding-refs.html)
* useRefを使ってDOMノードを操作する
    * 参考: [フック API リファレンス – React](https://ja.reactjs.org/docs/hooks-reference.html#useref)

を両立させたい場合があります。
その良い方法が見つかったので、ここに残しておきます。

# useImperativeHandleを使います

気付いてみれば当たり前のことですが、useImperativeHandleを使えばうまく実装することができます。
useRefで保持しているDOMノードを、useImperativeHandleを使ってフォワーディングします。

```typescript
const RefSample = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
	// DOMノードを保持するref
	const inputRef = useRef<HTMLInputElement>(null);
	// useImperativeHandleでフォワーディング
	useImperativeHandle(ref, () => inputRef.current!);

	const focusHandler = useCallback(() => {
		inputRef.current?.focus();
	}, []);
	return (
		<div>
			<button onClick={focusHandler}>focus</button>
			<input ref={inputRef} type={"text"} />
		</div>
	);
});
```

これで、このコンポーネントを使う際にrefを渡すことができるようになります。

```typescript
const App = () => {
	const ref = useRef<HTMLInputElement>(null);
	const blurHandler = useCallback(() => {
		ref.current?.blur();
	}, []);
	return (
		<div>
			<RefSample ref={ref} />
			<button onClick={blurHandler}>blur</button>
		</div>
	);
};
```

# 補足: useImperativeHandleについて

useImperativeHandleの第2引数には関数を渡しますが、この関数がいつ実行されるのか公式ページには載っていないようなので、軽く調査しました。
どうやら、HTMLのレンダリングが終了してから、useLayoutEffectに渡した関数が呼び出されるまでの間のタイミングで、かつReactのUIツリーの末端にあるエレメントから実行されていくようです。

# 関連

これに関連して、以下の記事も作成しました。

* [【React】複数のrefを扱う方法 ver.2【createRef不要】](https://qiita.com/costeka/items/3e2464749b54dc86bc54)
Ajax（非同期通信）


#GETで通信

```
var xhr = new XMLHttpRequest();
 
xhr.open('GET', http://xxx?param=value);
xhr.send();
 
xhr.onreadystatechange = function() {
 
    if(xhr.readyState === 4 && xhr.status === 200) {
        //処理
    }
}
```

#POSTで通信

```
var xhr = new XMLHttpRequest();
 
xhr.open('POST', http://xxx);
xhr.send('param=value');
 
xhr.onreadystatechange = function() {
 
    if(xhr.readyState === 4 && xhr.status === 200) {
        //処理
    }
}
```

##イベント毎に非同期通信をする場合の例（入力がある毎に通信）

```
function_ajax();
function function_ajax() {

    var xhr = new XMLHttpRequest();

    const $input = document.querySelector('#id');
    //#idを持たないページはここで処理が終わる
    if (!$id) {
        return;
    }

    $input.addEventListener('input', function () {

        xhr.onreadystatechange = function() {
            if(xhr.readyState === 4 && xhr.status === 200) {
                //処理
            }
        }

        xhr.open('GET', 'http://xxx?param=value');
        xhr.send();
    });
}
```
シンボリックリンク作成メモ

##### シンボリックリンク作成

A のパスでNFSディレクトリを参照できるように設定する。(A -> B)

```
#### ln -s (参照する実際のディレクトリ:B) (仮のディレクトリ名:A)
$ ln -s B A
$ ls -l
lrwxrwxrwx 1 {username} {grpname}   36 Mar 29 11:24 A -> B
#### もしシンボリックリンクを外したい場合: unlink (リンク名)
#### (ex) unlink A
```


##### 表記
(A → B): Aというディレクトリで、実はBのディレクトリを参照している(実際のファイルはBのディレクトリに存在する)
Resource(CPU & Memory) monitoring/


```
### Get the pid of the relevant batch.

$ ps -aux  | grep java
top command to monitor CPU and memory information (the target in the example is pid: 3067)
$top -p 3067
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239544/0be2b18c-5428-0b10-86d4-722950810b5c.png)

##### For All Process

```
① 3872540 total > All physical memory(約3.8GB)
② 4190204 total > Memory in the swap space(約4.1GB)
③ 1562088 free > empty space (約0.15GB)
④ 2406996 used > Memory used by all (batch) processes on the server.(約2.4GB)
⑤ 1308640 > Buffer/cache area memory allocated by the OS(約1.3GB)
```

The formula is

```
TOTAL(①) = free(③) + used(④) + buff/cache(⑤)
For Each pid Process
Column for each PID: Memory allocated for each PID
VIRT: amount of virtual memory: ex) 3136304  (約3.1GB) 
RES : physical memory ex) 316760  (約0.31GB) 
%CPU:  used CPU(%) (約0.0%)
```

The formula is

```
%MEM(約8.2%) =  Amount of physical memory allocated to pid: 23819 (約0.31GB)  / All physical memory(約3.8GB)
Check the actual used memory by JSTAT command.
$ jstat -gc 46702
Automatically execute commands one second at a time with the watch command.
```

```
$ watch -n 1 jstat -gc 46702
Check the used space.

（709[S0U]　+　0.0[S1U]　+　11459.1[EU]　+41758.9[OU]） / 1024　　= 52.66MB ...*1
*1: 52.66MB is much lower than allocated to this pid (約0.31GB). This is thought to be Java application is allocating the enough memory as a buffer space
```
Ref: https://qiita.com/kaikusakari/items/9b7c3d1fb524eb6aa348

### Result of Migration test on batch
While file(about 10000 lines at each file) is continuously sent to server and batch is processing...

```
%CPU is roughly 50%. 
If large amounts of data are linked in other batches at the same time, delays may occur, but if large amounts of data are linked in a single batch, there is no problem.

%VIRTUAL MEMORY is same as normal(8.2%)

Memory while file processing do not exceed the amount of allocated memory by java application. 
Real used memory is about 100 MB while batch is processing. 
```
今日の単語 entrepreneurial

 今月は例のDeepLearningテキスト(https://pythonrepo.com/repo/minitorch-minitorch-python-machine-learning
から進めていて、コーネル大学のプログラマ向けの教材をやっている
（もちろん英語の勉強だけでなく、プログラム教育を大学生に戻って受けるつもりである。
今は本当に、いい時代になったとおもう。こうして５０代のオッサンでさえ、彼らと肩を並べて現役でいられるなんて・・・）

#conel大学の動画
 https://youtu.be/Z37vjH-42cE

　ＡＩを学ぶ動機として、動画の中でお姉さん達が力説しているが、この単語が実に重要と言うらしい。これからの世の中を象徴している気がする。もちろん、こんな単語、いまの日本人は知っている人はゼロパーに近いんではないか？

` 途中に出てくる単語が、分からない、読めない、発音できないと、三重苦であった。
èn・tre・pre・néur・i・al　→　あんた　プレなあ
`

この単語の答えは、ずばり「起業家」らしい

```
ESTRIN: Our one year masters of engineering program in computer 
science is designed for people who want to take their basic background 
from their undergraduate degree and really develop that next stage of 
deep technical expertise and who are interested in learning how to do 
that in the context of real problems. 

DELL: Our computer science students are able to take a wide variety of 
deep technical courses and what they learn is a core set of technical 
skills that will enable them to go and be a successful software 
engineer or computer scientist in almost any field. 

MARINO: My Cornell Tech education has definitely prepared me for the 
outside world. It's mapped onto things like product and business that 
really helps you take those computer science skills to the next level. 

BELONGIE: Through the co-curriculum and through the studio-style 
education system, Cornell Tech encourages both technical mastery and 
effective communication. 

DELL: Many of our computer science students are focused on trying to 
complement their computer science background with a set of 
entrepreneurial skills that will really allow them to go and start 
their own organization or participate in founding a startup company. 

NZEOCHA-IMASOGIE: It's extremely entrepreneurial so if ever had even 
an inkling of an entrepreneurial bone in your body, I think Cornell 
Tech is for you. Cornell Tech really exposes you to the outside tech 
industry. They bring in practitioners that are the movers and the 
shakers and the industry leaders in the tech field. 

ESTRIN: We need creative solutions, but practical solutions to the 
world's problems and we're trying educate a type of student who has 
not only the technical skills to implement good solutions, but the 
creative and problem definition skills that you need to define what 
the problem you should be solving is. 
```
【Java】logback.xml でINFOログの圧縮

### 概要
JavaのシステムログとしてINFOレベルのログも大量に出力する際、最大バイト数で区切りログファイルを圧縮し保存する。

### 修正前

```logback.xml
...
    <appender name="SYSTEMLOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>./logs/maker/system.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>./logs/maker/system.log.%d{yyyy-MM-dd}.gz</FileNamePattern>
            <!-- keep 7 days' worth of history -->
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder>
            <charset>UTF-8</charset>
            <!-- <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</Pattern> -->
            <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5le %marker %lo{36} [%file:%line] - %msg %n</Pattern>
        </encoder>
    </appender>
...
```

### 修正後

```logback.xml
....
    <appender name="SYSTEMLOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>./logs/receiver/system.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>./logs/receiver/system.log.%d{yyyy-MM-dd}.%i.gz</FileNamePattern>
            <!-- keep 7 days' worth of history -->
            <maxHistory>7</maxHistory>
        <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
        <!-- or whenever the file size reaches 1000MB -->
            <maxFileSize>1000MB</maxFileSize>
        </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <charset>UTF-8</charset>
            <!-- <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</Pattern> -->
            <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5le %marker %lo{36} [%file:%line] - %msg %n</Pattern>
        </encoder>
    </appender>
....
```

#### 修正点（差分）

- ファイル名に %i を追加。
- 以下のコードを追加する。

```logback.xml
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- or whenever the file size reaches 100MB -->
    <maxFileSize>1MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
```
 

$ du -sh ./*
540K    ./system.log
548K    ./system.log.2021-03-26.gz
544K    ./system.log.2021-03-27.gz
544K    ./system.log.2021-03-28.gz
548K    ./system.log.2021-03-29.gz
552K    ./system.log.2021-03-30.gz
552K    ./system.log.2021-03-31.gz
548K    ./system.log.2021-04-01.gz
296K    ./system.log.2021-04-02.0.gz

### 参考: 
http://logback.qos.ch/manual/appenders_ja.html
awk Unique IP survey/


```
$  cat ssl_error.log | grep -e "2021/11/04 12:5" -e "2021/11/04 13:0" -e "2021/11/04 13:1" | grep "GET /item/" | head
2021/11/04 12:50:00 [warn] 30817#30817: *5389725 an upstream response is buffered to a temporary file /var/cache/nginx/proxy_temp/4/87/0000019874 while reading upstream, client: {ip}, server: {server_name}, request: "GET /item/{id} HTTP/1.1", upstream: "http://{IP}:80/item/{id}/, host: {server_name}
2021/11/04 12:50:00 [warn] 30817#30817: *5389742 an upstream response is buffered to a temporary file /var/cache/nginx/proxy_temp/6/87/0000019876 while reading upstream, client: {ip}, server: {server_name}, request: "GET /item/{id} HTTP/1.1", upstream:
...
```

```

$ cat error.log | grep -e "2021/11/04 12:5" -e "2021/11/04 13:0" -e "2021/11/04 13:1" | grep "GET /item/" | awk -F "," '{print $2}' | sort | uniq -c | wc -l
    1378
12:50 ~ 13:19 のWebApp 全体のエラー件数(UU Unique User): 2665
$ cat error.log | grep -e "2021/11/04 12:5" -e "2021/11/04 13:0" -e "2021/11/04 13:1" | awk -F "," '{print $2}' |  sort | uniq -c | wc -l
    2665
```
プロセスに残っているエクセルを強制終了する

Excel はすべて閉じたはずなのにまだプロセスに残っている場合がある。
それが原因でフォルダの削除や移動、名前の変更ができなかったりする。

コマンドプロンプトで以下のコマンドを実行すると、
プロセスに残っている Excel をすべて強制終了する。

```bat
taskkill /f /im excel.exe
```
kubectl get pods でstatusの情報を取得できない

## 現象
kubectl get pods でstatus などの情報が取得できない。

### 現象の原因
kubectl のバージョンが1.18.0だと出ない模様。

##### OKのバージョン

```
$ ./kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.0", GitCommit:"fc32d2f3698e36b93322a3465f63a14e9f0eaead", GitTreeState:"clean", BuildDate:"2018-03-26T16:55:54Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.6+coreos.0", GitCommit:"c2aac694c2c7373dfe3ad81f47fc3cbc70a5a8fa", GitTreeState:"clean", BuildDate:"2018-03-21T21:54:22Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
```

##### NGのバージョン

```
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.8", GitCommit:"9f2892aab98fe339f3bd70e3c470144299398ace", GitTreeState:"clean", BuildDate:"2020-08-13T16:12:48Z", GoVersion:"go1.13.15", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.6+coreos.0", GitCommit:"c2aac694c2c7373dfe3ad81f47fc3cbc70a5a8fa", GitTreeState:"clean", BuildDate:"2018-03-21T21:54:22Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
```

### 解決法

kubectl のバージョンをv1.10.0にダウングレードする

```
curl -LO curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.10.0/bin/darwin/amd64/kubectl
chmod +x ./kubectl
./kubectl get pods
```

(ちなみに)これしてもだめだった、、、

```
kubectl get pods -o wide
```

### 参考

https://github.com/kubernetes/kubernetes/issues/65575#issuecomment-401319830
数ヶ月AWS勉強用アカウントを運用してみて、金額のかかったサービス

# 記事を書くにあたったきっかけ

AWSを仕事で使う際に、プライベートで持っていた方が色々と便利で、そのプライベートアカウントで遊んでいたら想定以上にお金のかかったサービスを紹介します。

## ほぼ利用していないAWSアカウントなのに、　２ヶ月連続で良い額の請求書が来た

### EC2多重起動

要因はEC2を複数台起動したまま停止し忘れ、利用時間が増えたため金額が増加しました。
直接の原因としてはBIツールのCloudFromationをいくつか試しており、その中でEC2を起動するものがありました。そのCloudFormationを消し忘れていたために、性能の良いEC2を多重に起動し、起動したまま放置したため、金額が嵩みました。

![スクリーンショット 2021-11-30 16.48.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217551/f7d3fc14-aaca-a904-b32d-89b74f88f87e.png)

### プライベート証明書

EC2は先月のままサーバー停止忘れて$30かかり、今度はCertificate Managerが料金を伸ばしてきました。[Certificate Managerのプライベート証明書は月$400の定額サービスだそうで、作ったまま放置してました。](https://aws.amazon.com/jp/certificate-manager/pricing/)
まさか個人で遊ぶ範囲でこんなにお金のかかるサービスがあると予想しておらず、気になって再度プライベート証明書を発行してみたところ、確かにプライベート証明書を発行する段階で、月額$400かかる注意書きがありました。

![スクリーンショット 2021-11-30 16.49.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217551/fa6524b2-fc86-8cfc-08a5-e835a41b6278.png)
----
![スクリーンショット 2021-11-30 17.55.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217551/4ed6e3b3-4d42-c781-c3d9-754b2ce4c194.png)
**証明書は発行しただけで使ってないのに、良い額きますわね...。**

## まとめ

私は仕事でAWSを使っており、よく金額のかかると言われている「データ転送」「CloudFront」「EC2/RDS」あたりさえ気をつければ良いと思っていましたが、個人で勉強用も兼ねて使ってる分には、どれくらい料金がかかるのかわからなくて怖いとかよくありますが、
AWSで一年以上試してみた感覚としては、上に書いた「Serverを立てる系」と「プライベート証明書を発行する」さえ気をつければ、月数ドルのAWS無料範囲枠に収まると思います。（$1もかからないことがおおい。）

次回はAWSから料金設定での通知方法３種類を記載したいと思います。
【技術書まとめ】本気で学ぶ Linux実践入門 サーバ運用のための業務レベル管理術

# Chapter 1: Linuxの概要と導入

- Linuxオペレーティングシステムの構成
    - ![スクリーンショット 2021-11-18 18.53.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/4ff45ae0-47bc-7073-0cd3-1a4499169d4f.png)


# Chapter 2: Linuxの起動・停止を行う

- ブートシーケンスの概要
    - ![スクリーンショット 2021-11-24 8.03.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/a54a1260-2f2c-7224-2527-01d050a1c1a7.png)
- ブートローダ
    - `GRUB2`
- カーネル
    - ![スクリーンショット 2021-11-24 8.28.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/f2deefe7-03ad-18a3-3dd7-0bcb8789e26e.png)
    - ![スクリーンショット 2021-11-25 8.23.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/4a12fbb0-ab9f-4a3e-0235-3d4afa38e71a.png)
- systemd
    - カーネルが生成する最初のユーザプロセス
        - プロセス番号[1]
    - ターゲットまで立ち上げる
        - ![スクリーンショット 2021-11-25 8.23.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/c24e20f1-93a5-4727-8fc0-71e0e71dec6e.png)
    - ![スクリーンショット 2021-11-26 8.59.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/860cf2e3-ee55-8592-c97c-dc2ff9c94b8a.png)
- 組み込みコマンドと外部コマンド
    - 組み込みコマンドは`cd`や`echo`など
    - ほとんど外部コマンド
        - `/usr/bin`や`/usr/sbin`などにある
            - `ls`や`cat`
        - シェルは環境変数PATHにあるディレクトリ下を探して実行する
            - 例：`PATH=/usr/bin:/usr/sbin`
            - PATHが通ってなくても相対パスで指定すれば実行できる
- デーモン（daemon）
    - システム上で常時稼働してサービスを提供するプログラム


# Chapter 3: ファイルを操作する

- FHS(Filesystem Hierarchy Standard)
    - 共有可、共有不可、静的、可変、でディレクトリを振り分ける
        - ![スクリーンショット 2021-11-29 8.06.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/c7663ea4-9fe3-7a68-974f-f55dbf6f98b4.png)
- エラーを別ファイルに出力する
    - `ls fileA fileX 2> error`
        - 2が標準エラー出力
- グループ
    - １次グループ
        - ログイン直後の作業グループ
    - ２次グループ
        - 必要に応じて１次グループ以外を割り当てられる
- パーミッション
    - umask
        - 割り当てたくないパーミッション
            - `0002`だと2が引かれる
- ハードリンクは元ファイルが削除されてもiノードが同じなのでアクセスできる
 

# Chapter 4: ユーザを管理する

- ユーザの追加や削除、ログ表示など


# Chapter 5: スクリプトやタスクを実行する

- シェルスクリプト
- crontabでの操作など
- pythonでの操作


# Chapter 6: システムとアプリケーションを管理する

- パッケージ管理
    - rpm（Ubuntuではdpkg）
        - 依存関係は自動解決されない
            - バージョンを明示的に指定してインストールできる
    - yum（Ubuntuではapt）
        - 依存関係含めて管理される
- プロセス管理
    - `ps`や`top`の説明
- ログ管理
    - セレクタで何を出すか選んで、プライオリティで絞る
        - それを`/var/log/secure`などアクション先に出す



# ディスクを追加して利用する

- パーティションやファイルシステムなど



# ネットワークを管理する

- ネットワーク設定方法など


# システムのメンテナンス

- システムにアクセスできない時など


# セキュリティ対策

- 公開鍵をsshサーバに登録する
    - `$ mkdir .ssh`
    - `$ chmod 700 .ssh`
    - `$ cat id_rsa.pub >> .ssh/authorized_keys`
    - `$ chmod 644 .ssh/authorized_keys`
        - ![スクリーンショット 2021-12-24 8.22.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/0fd3922f-f666-26ce-7278-32335fc97118.png)
大量のPDFファイルからテキストデータを一括で取り出すバッチファイル

大量のPDFファイルからテキストデータを一気に取り出したい場合は、[xdoc2txt](http://ebstudio.info/home/xdoc2txt.html) を使うのが便利。
[xdoc2txt](http://ebstudio.info/home/xdoc2txt.html) は、ダウンロードして解凍するだけで使えるのでインストール権限も不要。

`xdoc2txt.exe`が`C:\Software\xd2tx220_x64\command`フォルダにあると仮定する。
以下のバッチファイルをPDFファイルが保存されているフォルダに入れて実行する。

＜カレントフォルダ一括バージョン＞

```bat:xdoc2txtPDF.bat
@echo off
REM カレントフォルダ内のすべてのPDFファイルからテキストを抽出して、
REM それぞれ同名のテキストファイルとして保存する

set xdoc2txt=C:\Software\xd2tx220_x64\command\xdoc2txt.exe
for %%f in (*.pdf) do %xdoc2txt% "%%f" > %%~nf.txt
```

＜選択ファイル一括バージョン＞

```bat:xdoc2txtPDF_DnD.bat
@echo off
REM 選択した複数のファイルをこのバッチファイルにドラッグアンドドロップする
REM または、バッチファイルを sendto ファルダに入れて、右クリックメニューの
REM［送る］から実行する

set xdoc2txt=C:\Software\xd2tx220_x64\command\xdoc2txt.exe
for %%f in (%*) do %xdoc2txt% "%%f" > %%~dpnf.txt
```

抽出したテキストを一つにまとめたいときは、

```bat:MargeTxt.bat
@echo off
type *.txt > all.log
```

<font color="Red">
［注］`"%%f"`と、ダブルクォーテーションで囲むのは、パスに空白が含まれている場合のため
</font>
---
- ［参考］[「%~dp0」の意味は？](https://web.plus-idea.net/2016/09/know-dp0-windows-meaning/)
- ［2021/12/28］DnDのテキストの出力先を修正：%%~nf ⇒ %%~dpnf
NiFiのセットアップ手順(Ubuntu20.04)

Ubuntu20.04にApache NiFiをインストールした際の手順メモ。

## NiFiのダウンロード
NiFiの公式サイト(https://nifi.apache.org/index.html)からダウンロードする。
2021/12/25時点で最新のver1.15.2を使用した。


## NiFiのユーザ登録
```
tar xvzf nifi-1.15.2-bin.tar.gz 
cd nifi-1.15.2
```

最初にユーザアカウントを作成する。アカウントはnifi.shを使用して作成可能。
```./bin/nifi.sh set-single-user-credentials <UserName> <Password>
```


## NiFiの起動・ログイン
Nifiを起動する。起動もアカウント作成と同様にnifi.shを使用する。
```./bin/nifi.sh start
```

起動後、ブラウザを用いてNifiにアクセスする。ブラウザを立ち上げ、以下のURLを入力するとログイン画面が表示される。
![login.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367655/86fdaea3-ae35-5b7b-3937-f616febb3cee.png)


ポート等はデフォルトのまま使用している。設定ファイルはconf/nifi.propertiesで、これを変更することで
ポート番号等を変更が可能。httpでなくhttpsなので注意。
```nifi.web.https.host=127.0.0.1
nifi.web.https.port=8443
```

ログイン画面で先ほど作成したアカウント情報を入力するとログインできる。
![home.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367655/eb8a911d-b08d-6e50-e908-52005d8b39bc.png)
「良い技術的負債と悪い技術的負債」

https://mtx2s.hatenablog.com/entry/2021/12/21/084227

の中で紹介されていた、「負債ベースライン（debt baseline）」 と 「負債上限（debt ceiling）」による許容範囲を設けることについてのサマリ。(引用部分はDeepL翻訳を使用しています)

記事には以下のような象限の図がある。良い負債とは、このうち「意図的」かつ「慎重」な負債 について指す。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/m/mtx2s/20211218/20211218194916.png)


## Good and Bad Technical Debt (and how TDD helps)

良い技術的負債と悪い技術的負債（そしてTDDがどのように役立つか）

https://blog.crisp.se/2013/10/11/henrikkniberg/good-and-bad-technical-debt

ポイント: 

- 技術的負債（Technical Debt）は通常、「悪いもの」。
- しかし、常にそうだろうか？良い負債と悪い負債を区別するにはどうすればいいのか？

## 技術的負債曲線を描く

ポイント: 

- 技術的負債とは、長期的に開発速度を低下させるようなコードに関するもの。読みにくいコード、テスト自動化の欠如、重複、依存関係のもつれ、など。悲しいかな、ほとんどのシステムで技術的負債は増え続けている。

## 負債曲線をどのようにしたいか？

ポイント: 

- あなたは「パーフェクト」を追究できるとしたら、「技術的負債ゼロ！」としたいだろうか？
- もし、製品ライフサイクル全体を通して技術的負債をゼロにすることができたら、それは最高？
- 実はそうではない。技術的負債を常にゼロにすれば、おそらくスピードも落ちる。「技術的負債とは、長期的に速度を低下させるコードに関するあらゆるもの」。しかし、短期的な話となると話は別である。

## どんな場合に「良い」のか？ 料理をしているときの例

> 材料や調味料、調理器具がそこらじゅうに転がっています。音楽を録音していると、楽器やケーブルやメモが転がっています。絵を描くときも、ペンや絵の具、道具が転がっています。

> 野菜を切るたびに、包丁を洗って取り替える。野菜を切れば、包丁を洗って交換し、絵を描けば、筆を洗って交換する。音楽のテイクが終わるたびに、楽器のプラグを抜いてケースに入れ直す。これでは、仕事のスピードが落ち、創造性やフロー、生産性が完全に失われてしまいます。

ポイント: 

- 実は「散らかっている」ことで、フロー状態を維持することができる。


## 一方、問題になるのは、古いゴチャゴチャである

> 新しいことを始めようとパソコンを開いたとき、昨日までやっていた仕事のウィンドウや文書が何十枚も開いていたら、仕事のスピードが落ちます。夕食を作ろうと思って台所に行ったら、古い食器や昨日の残り物でキッチンがこんがらがっていた、というのと同じです。

> 新しい機能をコーディングする場合、様々なやり方がある。どこかに非常にシンプルでエレガントな解決策があるはずですが、それを前もって見つけ出すのは本当に難しいことです。それよりも、実験し、遊び、問題に対するさまざまなアプローチを試し、それがどのように機能するかを確認する方が簡単です。

ポイント: 

- 過程で蓄積された技術的負債は「良い負債」であり、それを整理することで創造性が制限される。また、技術的な品質よりも、初期のユーザーからのフィードバックが優先されることがある。手早くプロトタイプを作り、その機能が気に入られれば、次の機能に移る前に、コードを修正すればよい。
- **問題は、キッチンと同じように、私たちはしばしば、次の作業に移る前に片付けることを忘れてしまうこと。そして、これが技術的負債を悪化させる原因である。「一時的な」実験的なコード、重複したコード、テストカバレッジの欠如など、そういったものはすべて、後で次の機能を構築するときに、あなたの足を本当に遅くすることになる。**
- ではこの「短期間」とはどのくらいまでなのか？
    - 経験では、ソフトウェアでは、「良い混乱」は数日、間違いなく1週間以内までしか通用しない。それをこえると陳腐化し、汚れた食器が台所に詰まり、食べ残しが臭くなり、インスピレーションも生産性も下降線をたどる。

## 理想的な技術的負債曲線

ポイント:

- 理想的な曲線は次のようなもの
- 各サイクルがわずか1日か2日のノコギリ歯のパターンであるべきです。
- 新しい機能を実装する際には一時的な混乱を許容し、次の機能の前に必ずそれを片付ける。

引用 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/89fc4ee6-b285-4a9a-bb87-ab18d9ea6ca6.png)



## より現実的で理想的な技術的負債曲線

ポイント:

- **「債務上限」を設けましょう。** 
- あらゆるメトリクスの中で、筆者は、**主観的な品質測定基準を好むチームが多い**ことに気づいた。
    - 開発者の多くが深く気にかけられる。つまり自分のコードの品質を、可視化できるため。
- 客観的な測定基準（テストカバレッジ、重複など）を議論のインプットとして使用することも可能です。しかし、結局のところ、**開発者の主観的な意見こそが重要である。**
- 重要なのは、品質に対する姿勢を貫くこと。品質をどのように測定するか、あるいは負債の基準値と上限値をどこに置くかにかかわらず、**定期的に議論し、自分たちがどうありたいかを明確に決定すること。**
- 例: [割れ窓理論 - Wikipedia](https://ja.wikipedia.org/wiki/%E5%89%B2%E3%82%8C%E7%AA%93%E7%90%86%E8%AB%96)

## まとめ: 良い品質＝人々の幸せ

> 結局のところ、技術的負債は技術に関するものではないのです。人間に関することなのです。

> きれいなコードベースは、作業が早いだけでなく、より楽しくなります。そして、やる気のある開発者は、より良い製品をより早く作る傾向があり、その結果、顧客と開発者の両方がより幸せになるのです。ポジティブなサイクルを！

まとめ: 

この「良い技術的負債と悪い技術的負債」はつまり、素早く仮説検証するために生じた、数日から一週間以内の技術的負債を「良い技術的負債（good technical debt）」と呼んでいる。あらゆるメトリクスの活用と、大事なのは品質に関する開発者の主観的な意見との話。

以上、参考になりましたらさいわいです。
【HTML】インライン要素とブロックレベル要素について

## はじめに
　本記事は、プログラミングの学習を始めて1ヶ月の初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
　そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
　間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。

##HTML5のブロックレベル要素とインライン要素について

###ブロックレベル要素とインライン要素の分類はHTML5から廃止
　見出しに記載したとおり、HTML５からブロックレベル要素とインライン要素という分類は廃止されております。
　代わりに以下の7項目で分類されるようになり、従来のインライン要素に該当する要素でも、body要素の直下に配置することができるようになりました。

HTML5の7カテゴリー

- フロートコンテンツ
- フレージングコンテンツ
- インタラクティブコンテンツ
- 組み込みコンテンツ
- メタデータコンテンツ
- 見出しコンテンツ
- セクショニングコンテンツ

　HTML5からインラインとブロックレベルという分類が廃止されたとはいえ、CSS3ではインラインとブロックレベルという考えが残っているため、無視することはできません。
　そこで、以下にインライン要素とブロックレベル要素についてまとめます。


###インライン要素
　インライン要素とは、文章の一部として含むことのできる要素のことで、以下の特徴があります。

|  | インライン要素 |
|:-:|:-:|
| 横幅と高さの指定 | 不可能  |
| 横幅の初期値  | 内容で決まる  |
| 高さの初期値  | 内容で決まる  |
| 他の要素との並び方  | 改行が入らない（横並び）  |
| 余白のつき方  | 上下に特殊なつき方をする  |

####インライン要素一覧

```
 <a>
 <abbr>
 <acronym>
 <applet>
 <b>
 <basefont>
 <bdo>
 <big>
 <br>
 <button>
 <cite>
 <code>
 <dfn>
 <em>
 <font>
 <i>
 <iframe>
 <img>
 <input>
 <kbd>
 <label>
 <map>
 <object>
 <q>
 

 <samp>
 <script>
 <select>
 <small>
 <span>
 <strike>
 <strong>
 <sub>
 <sup>
 <textarea>
 <tt>
 <u>
 <var>
```

###ブロックレベル要素
　ブロックレベル要素とは、インライン要素のまとまった単位をいい、以下の特徴があります。

|  | ブロックレベル要素 |
|:-:|:-:|
| 横幅と高さの指定 | 可能  |
| 横幅の初期値  | 親要素と同じ  |
| 高さの初期値  | 内容で決まる  |
| 他の要素との並び方  | 改行が入る（縦並び）  |
| 余白のつき方  | デフォルトでつく場合がある  |

####ブロックレベル要素一覧

```
 <address>
 <blockquote>
 <center>
 <dir>
 <div>
 <dl>
 <fieldset>
 <form>
 <h1>-<h6>
 <hr>
 <isindex>
 <menu>
 <noframes>
 <noscript>
 <ol>
 <p>
 <pre>
 <table>
 <ul>
```

## まとめ
インライン要素とブロックレベル要素の特徴は以下のとおりです。

|  | インライン要素 | ブロックレベル要素 |
|:-:|:-:|:-:|
| 横幅と高さの指定  | 不可能  | 可能  |
| 横幅の初期値  | 内容で決まる  | 親要素と同じ  |
| 高さの初期値  | 内容で決まる  | 内容で決まる  |
| 他の要素との並び方  | 改行が入らない（横並び）  | 改行が入る（縦並び）  |
| 余白のつき方  | 上下に特殊なつき方をする  | デフォルトでつく場合がある  |
計測時間（分秒）を返す VBScript

※ 一応、コンマ何秒（小数点以下3桁）まで計測するが、ミリ単位は正確ではない

```vb:GetLapTime.vbs
Option Explicit
'// 実行結果
Dim startTime, num, msg
startTime = Timer
num = 304250263527210
msg = num & " の素因数分解は［ " & PrimeFact(num) & " ］"
msg = msg & vbCrLf & "計測時間: " & GetLapTime(startTime)
Msgbox msg
```

```vb
'// 引数 start_time に開始時間を与えてやると、
'// 開始時間からこのスクリプトが実行されるまでの
'// 時間を分秒で返す。

Function GetLapTime(ByVal start_time)

    Dim lapTime, m, s, f

    lapTime = Timer - start_time
    m = Int(lapTime / 60)
    s = Int(lapTime) Mod 60
    f = Int((lapTime - Int(lapTime)) * 1000)

    GetLapTime = m & " 分 " & s & " 秒 " & f

End Function
```

```vb
'// 素因数分解の結果を返す（15桁以下）

Function PrimeFact(ByVal num)

	Dim i, str

    i = 2
    Do While num / i = Int(num / i)
        If num = i Then Exit Do
        str = str & i & " "
        num = num / i
    Loop

    For i = 3 To Int(num^0.5) Step 2
        Do While num / i = Int(num / i)
            If num = i Then Exit Do
            str = str & i & " "
            num = num / i
        Loop
    Next

    PrimeFact = str & num

End Function
```
【Mac】Gstremerで接続デバイスを確認する方法

本記事ではGstremerのコマンドの一つをご紹介します。
今回のコマンドを使用することで、Macに接続されているデバイス（video/audio）を確認することができます。

##環境
macOS Monterlay 12.0.1
GStreamer Core Library version 1.18.4

##下記のコマンドを実行する。

```
$ gst-device-monitor-1.0
```

##結果は以下のとおり。
```
Device found:

	name  : FaceTime HDカメラ（内蔵）
	class : Video/Source
	caps  : video/x-raw(memory:GLMemory), width=1280, height=720, format=UYVY, framerate=[ 1/1, 10000000/333333 ], texture-target=rectangle
	        video/x-raw(memory:GLMemory), width=640, height=480, format=UYVY, framerate=[ 1/1, 10000000/333333 ], texture-target=rectangle
	        video/x-raw, width=1280, height=720, format={ (string)UYVY, (string)YUY2, (string)NV12, (string)BGRA }, framerate=[ 1/1, 10000000/333333 ]
	        video/x-raw, width=640, height=480, format={ (string)UYVY, (string)YUY2, (string)NV12, (string)BGRA }, framerate=[ 1/1, 10000000/333333 ]
	properties:
		device.api = ~~~
		avf.unique_id = ~~~
		avf.model_id = ~~~
		avf.has_flash = ~~~
		avf.has_torch = ~~~
		avf.manufacturer = "Apple\ Inc."
	gst-launch-1.0 avfvideosrc device-index=0 ! ...


```
Gstremerのパイプラインを作成する際に、主に確認する項目は下記の部分です。

### デバイス番号の確認
```
# 下記をそのまま活用すればOK。Webカメラなどは device-index=1 ! 等が割り当てられていることが多い。
gst-launch-1.0 avfvideosrc device-index=0 ! ...
```
### スペック確認
```
# 仕様を指定する際に必要な項目。※ fps=10000000/333333 と書いてあるが30/1でうまくいく場合もあり表記方法があいまい。うまくいかない場合、両方の表記方法を試してみるといいかも。
 caps  : video/x-raw(memory:GLMemory), width=1280, height=720, format=UYVY, framerate=[ 1/1, 10000000/333333 ], texture-target=rectangle
```

以上で終わりです。
このコマンドはパイプラインを作成する際によく利用することになると思います。ちなみにコマンドの末尾に「Vidio/Source」または「Audio/Source」を追加すると検索結果を絞ることができるので、ぜひお試しください。
未経験からエンジニアになる方法の一つとしての社内SEへの異動という手段


未経験からエンジニアになろうと思った場合、

* ポートフォリオを作成してWEB系自社開発企業への転職活動をする
* 未経験可のSES・Sler企業へ転職する

等主に他社への転職を考える方が多いと思いますが、ここでは選択肢の一つとして、社内のシステム部、いわゆる社内SEへ異動する選択肢をご紹介したいと思います。

<h2>自己紹介</h2>

* 1992年生まれ
* 大学の工学部卒業後、大学院へ2年通うも中退
* 社会人4年目
* 証券会社で機関投資家営業2年半
* 同証券会社で社内SE（社内システムの開発）へ異動（当時28歳）し、1年間経験後、現職へ転職。引き続き社内システムの開発を担当。

<h2>社内SEの業務</h2>
大前提として、社内SEには下記の業務があります。

* ヘルプデスク
* インフラ構築・運用
* システム企画
* **自社システム開発**

この中で多くの未経験の方が経験を得たいと思っているであろう、アプリケーション作成のコードを書く機会のある**「自社システム開発」**の部門がある企業に話を絞ります。

<h2>社内SEの自社システム開発部門に異動するメリット</h2>

* ドメイン知識はあるので、技術さえ習得すればキャッチアップが早くできる
* モダンな技術に触れられる可能性がある
* ユーザーの声を身近に聞くことができるのでモノづくりの醍醐味が味わえる
* クライアントワークではないのでワークライフバランスは良い
* 給料の良い業界ならその業界の給与水準のままエンジニアになれる

それぞれ解説していきます。

<h3>ドメイン知識はあるので、技術さえ習得すればキャッチアップが早くできる</h3>
一般的に転職をする際は「業界」「職種」の2軸で見る切り口があるわけですが、転職のしやすさ、年収の上がりやすさ等でいうと、下記の通りになるわけです。
同業界・同職種＞他業界・同職種＞同業界・他職種＞他業界・他職種
この中で未経験エンジニアになろうと考えているということは、基本的に他職種を目指しているわけで、難易度は高いわけです。
他職種の選択肢の中でも難易度の低い同業界を選んでいくことが考えられるわけですが、同業界の同じ会社の中での異動となった場合、比較的動きやすく、かつその会社内での業務経験や業界知識（これがドメイン知識）はあるので、新たに学ぶことがシステム開発の手法や技術的な部分に絞られ、ドメイン知識に当てはめていくだけなので、短期間でキャッチアップすることができます。

<h3>モダンな技術に触れられる可能性がある</h3>
顧客に提供しているシステムを開発する場合は既存技術に縛られ難しい場合が多いですが、社内システムを開発する場合、開発部門の社員は自身の市場価値を高めようというインセンティブが働くため、モダンな技術に挑戦しようという機会がある可能性があります。

私の場合、基本的に下記の構成でシステム開発をしておりました。

```:基本的な環境
アプリケーション開発：WebPerfomer(ローコード開発ツール、HTML.CSS.JavaScriptを書く機会あり)
データベース　　　　：OracleDB、SQLServer
APサーバー　　　　　：Tomcat
```
しかし、社内であるシステムを開発した際、下記構成で開発する機会をいただけました。

```:新規アプリ開発の環境
静的コンテンツ　　　　：HTML.CSS.JavaScript(jQuery、Vue.js等のキメラ)
静的コンテンツの置き場：AWSのS3
認証　　　　　　　　　：AWSのAPIGateway、Lambda（AzureADのLDAP）
データ取得　　　　　　：Linux環境にGraphQLを使用してOracleDBからのデータを取得
```
4名体制でしたが、主要なコード、データベースとの接続部分等ほとんどのコードを書かせてもらい、アプリ開発や、AWS、GraphQLの知見も得ることができました。

ちなみに、現職では2021年11月から2か月程度経った時点ですが、下記環境で開発しております。

```:現職の環境
フロントエンド　　　　：Nuxt.js
バックエンド　　　　　：Firebase
```

このように、運が良ければモダンな技術を使用して開発する経験が得られます。
もちろん、一番大切なことは課題を解決することであるのは前提です。

<h3>ユーザーの声を身近に聞くことができるのでモノづくりの醍醐味が味わえる</h3>
これは良くも悪くも、ユーザーが社内の人間なので、使用感や要望などがダイレクトにフィードバックされる機会が多いです。
自身が担当している部分に関してはまるでわが子を育てるような感覚でシステム開発ができると思います。
（人によるでしょうか）

<h3>クライアントワークではないのでワークライフバランスは良い</h3>
時と場合によりますが、一般論として、人件費はかかっているものの、会社対会社で契約してお金を払っているわけではないので、納期はあるようでないです。
そのため、開発がどうしても間に合わない場合は、優先順位を下げて納期を延ばすということがしやすいです。
ただ、法律の改定に間に合わせる、経営層が大々的に発表している等大人の事情がある場合は間に合わせなければならないため、一時的にハードワークになる局面はあります。

<h3>給料の良い業界ならその業界の給与水準のままエンジニアになれる</h3>
多くの場合、WEB系自社開発企業に未経験で転職する場合、経験が得られる代わりに給与が低い場合が多いです。
一般的には300～350万円で、低い場合には200万円代になるようです。

実際私も営業からエンジニアに転職しようとした際にオファーをもらった年収は270万円～320万円がほとんどで、1社だけ500万円だけれども激務といった状況でした。

しかし、社内異動の場合は、今までの給与水準からほぼ下がることなくエンジニアになれると思います。
私の場合は、営業と給与テーブルが違ったので下がった面と、会社内でのグレードが上がった面で前年と変わらない水準でした。
また、家賃補助として借上社宅で月6万円もらえていた状況が変化しなかったのも大きかったです。

<h2>まとめ</h2>

未経験からエンジニアになる場合、自社の社内SEになる選択肢もある。
条件として、自社開発をしている部門があること。


以上です。
PhoenixLiveViewのProgress animationはNProgressからtopbarに切り替わっていた

1年以上前に行われた修正だったので、今更ではあるのですが。

[elixir-desktop](https://github.com/elixir-desktop/desktop)の[サンプル](https://github.com/elixir-desktop/desktop-example-app)を動作確認していた際に、たまたま気づいたこと。

PhoenixLiveViewでプログレスバーを表示する際に利用していたJavaScriptのライブラリが、「**NProgress.js**」から「**topbar.js**」に変わっていました。
変更タイミングは、「**0.15.1**」からのようです。

「0.15.0」のHexDocsに書かれている「**Progress animation**」の説明はこちら。

```
f you want to show a progress bar as users perform live actions, we recommend using nprogress.
First add nprogress as a dependency in your assets/package.json:
```

https://hexdocs.pm/phoenix_live_view/0.15.0/installation.html#progress-animation

一方、「0.15.1」のHexDocsに書かれている「**Progress animation**」の説明はこちら。

```
If you want to show a progress bar as users perform live actions, we recommend using topbar.
First add topbar as a dependency in your assets/package.json:
```

https://hexdocs.pm/phoenix_live_view/0.15.1/installation.html#progress-animation


なお、「0.15.1」のCHANGELOGには記載はありませんでした。

https://github.com/phoenixframework/phoenix_live_view/blob/master/CHANGELOG.md#0151-2020-12-20

切り替わったきっかけは、こちらのIssue。

https://github.com/phoenixframework/phoenix_live_view/issues/828

「`nprogress`は強引にブラウザのレイアウトリフローを強制しているからなんとかならんか？」的な感じの投稿が発端。
結果、いい塩梅の`topbar`が選ばれて置き換えられた様子。
この対応は、Livebookの方にも[横展開](https://github.com/livebook-dev/livebook/pull/229)されていましたね。


JavaScriptを意識しないで済むようになっているPhoenixLiveViewなので、ここが変更は利用者には影響しないと思われたのでしょうかね。[^1]

それとも、Issueの中でJose氏が発言していたように、アニメーションで全てのケースにうまくいくことは100％ないから必要なら自分たちなんとかしてね、なのかも。

[^1]: 実際、気がつかなかったわけですが...
自分の作ったモジュールをインストール時に"module declares its path as:"というエラーが出た

### エラー

```
> go get github.com/okaponta/slack-kintai
go get: github.com/okaponta/slack-kintai@v1.1.0: parsing go.mod:
	module declares its path as: slack-kintai
	        but was required as: github.com/okaponta/slack-kintai
```

### 原因

`go.mod`宣言時にモジュール名を外部公開を想定しない名前にしていたため発生しておりました。

`go mod init hogehoge`の`hogehoge`に`importpath`を入力するべきなのですが、リポジトリ名をいれていたため、外部から`go get`できなくなっておりました。
今回は外部公開する予定ですので、`github.com/okaponta/hogehoge`のように`github.com`のユーザつきで宣言するのが正解みたいです。

修正完了後は再度タグ切るのを忘れずに・・・！！(私はここでまた悩んでました笑)

### 修正後

```
> go get github.com/okaponta/slack-kintai@v1.1.1
go: downloading github.com/okaponta/slack-kintai v1.1.1
go get: installing executables with 'go get' in module mode is deprecated.
	Use 'go install pkg@version' instead.
	For more information, see https://golang.org/doc/go-get-install-deprecation
	or run 'go help get' or 'go help install'.
```

無事ダウンロードできましたが、`go install github.com/okaponta/slack-kintai@latest`を使いなさいと怒られました。次回からはそちらでインストールします。


蛇足ですが、以下が作成したモジュールです。slackの勤怠投稿を自動化したくて作成しました。

https://github.com/okaponta/slack-kintai
数学の検索エンジン「WolframAlpha」の紹介

# WolframAlpha
サイトはこちらです。
[WolframAlpha](https://ja.wolframalpha.com/)
![Screenshot_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431212/5d50b1ee-5b50-d421-52a0-6579b1ed20e0.png)

##使い方
検索窓に数式を入力して、検索ボタンもしくはEnterで計算してくれます。

```
solve x^2 + 4x + 6 = 0
```
![Screenshot_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431212/698e5545-f147-900f-5adc-fdd476b48f5c.png)
x = -2±i√2　だそうです。

```
solve 2x+y=1, 3x-2y=5
```
![Screenshot_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431212/656b7ac2-c61b-0b4f-710b-f252caae5595.png)

解のほか、プロットまで出してくれます。

このサイトの凄さは情報量です。抽象的な検索をすれば多くの情報を提示してくれます。
試しに√2を検索してみます。√はsqrt(Square Root)です。

![Screenshot_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431212/450cedb7-f1fe-fe5a-02e2-bfa5db5ad505.png)

ピタゴラス数とも言うそうです。初めて知りました...。

## 入力例

入力例はトップから閲覧できます。

![Screenshot_15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431212/6bf35e4a-1fed-736e-aac7-e4ae09ab0b3b.png)


![Screenshot_9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431212/b9dae836-a85c-70a5-acf1-6c541fa4f965.png)

どうやら日本語も受け付けてくれるみたいですね。

![Screenshot_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431212/60b64cd3-5106-0123-edd0-7d22c390140e.png)

![Screenshot_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431212/e0deaabb-9f3e-0d4c-8382-01bf8c07e951.png)

ご丁寧に極値とプロットまで...すごいです。

## 数学入力
最近、Wordの数式のような入力ができるようになったようです。

![Screenshot_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431212/0621d84c-10f2-8be5-cbce-4ab0606ebadd.png)

3x3の行列の積の計算をしてみます。

![Screenshot_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431212/b2448762-b256-8efb-1b6d-92dd4ba802b6.png)

自然言語で同じ計算をしようとしたら、ちょっぴり大変な式を書くことになります。

![Screenshot_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431212/6539e449-7938-f120-e4e3-37ccf1da1fa1.png)

GUIのような入力ができるのはありがたいですね。

## まとめ
このサイトはそんなに頻繁に使うものではないかもしれませんが、知っているといざという時に助かります。実際、自分は2回ほどお世話になりました。

ぜひ、使ってみてください。
rustの深さ優先探索

# 深さ優先探索
AtCoder Beginner Contest 233のCが解けなくて解説見たら
DFSを使うと書いてあったので勉強してみた。幅優先探索と同じqiitaを参照した
https://qiita.com/drken/items/a803d4fc4a727e02f7ba

※追記　23/1/8　もうちょっと実装が分かりやすい奴を下のほうに入れたぞ

ここのグリッドグラフのところを実装してみた。
ちなみにこの問題はAtCoder Typical Contest A - 深さ優先探索　らしく
~~実装したのでコード提出してみたら83個中9個がWAだった。つまりいくつかのパターンではうまく動いていないらしい
なぜ・・・と思ったが一旦置いておく。~~
22/10/23 jh.jwをキャストするときにi8にしてたせいだった。i32にすることで無事AC
面倒なのはDFSの関数へ渡す引数が多いこと。
参照したqiitaもそうだが渡すのは次の探索箇所くらいでここでいうｃやseenは渡す必要ないが
rustではなかなか難しそうだったので渡す方針にした。
また、dfsの再帰のところでfor文の途中で再帰に入ってまた１からfor文回す・・・というイメージがなかなかわかず
書くのに苦労した。あとは範囲外の処理。この書き方だと負の値がただのでかい値になる。
つまり実はjh <0 || jw <0　はいらない。個人的には幅優先探索のほうが分かりやすくて良い。
使い分けはまだよくわかっていない

```rust
use proconio::{input};
use proconio::marker::{ Chars};
fn dfs(c:&Vec<Vec<char>> ,mut seen:&mut Vec<Vec<usize>>, vh:usize,vw:usize )  {
  seen[vh][vw] = 1;
  let d = vec![(-1, 0), (0, -1), (0, 1), (1, 0)];
  for (i,j) in &d{
    let jh = (vh as i32 + i) as usize;
    let jw = (vw as i32 + j) as usize;
    if jh <0 || jw <0 || jh >= seen.len() || jw >= seen[0].len(){continue}
    if c[jh][jw] == '#' as char {continue}
    if seen[jh][jw] == 1{continue}
    
    dfs(&c,&mut seen,jh,jw);
  }
}


fn main() {
  input!{
 H:usize,
  W:usize,
  c: [Chars;H]
  }
  let mut seen = vec![vec![0;W];H];
  let mut s = vec![0,0];
  let mut g = vec![0,0];
  for i in 0..H{
    for j in 0..W{
      if c[i][j] == 's' as char{
        s[0] = i;
        s[1] = j;
      }
      if c[i][j] == 'g' as char{
        g[0] = i;
        g[1] = j;
      }
    }
  }

  dfs(&c,&mut seen,s[0],s[1]);
  if seen[g[0]][g[1]] == 1{
    println!("{}","Yes");
  }else{
    println!("{}","No");
  }

}
```


ちょっと上はグリッドグラフの実装でわかりにくいのでグラフの実装も。
探索出来たら-1以外の値になるあとはこの実装だと到達するか否かしかわからないが
探索順番も求められるみたい

```rust
fn dfs(gra:&Vec<Vec<usize>>,v:usize,mut dist:&mut Vec<i32>,mut d:&mut usize){
   //探索順番を求めるときに使う（行きがけ）,このとき下の再帰関数の変数は`d*+1->dとすること
  //*d +=1;
  dist[v] = *d as i32;
  for i in &gra[v]{
    if dist[*i] != -1{
      continue;
    }
    dfs(gra,*i,&mut dist,&mut (*d+1));
  }
  //探索順番を求めるときに使う（帰りがけ）
  //*d +=1;
  //dist[v] = *d as i32;
}

fn main() {
 input! {
    n:usize,
    m:usize,
    v:[(usize,usize);m] 
  }

let mut gra = vec![vec![]; n];
let mut dist = vec![-1;n];
let mut d = 0;
//let mut queue =VecDeque::new();

  for (i,j) in v{
    gra[i-1].push(j-1);
    gra[j-1].push(i-1);
  }
  

dfs(&gra,0,&mut dist,&mut d);
println!("{:?}",&mut dist);

}
  

```