OmniAICreator/Qiita-1.07M huggingface dataset:
Prisma を Google App Engine で使いたい場合

# TL; DR
普通にデプロイしてしまうと`prisma generate`をしていないせいでエラーが出る。解決策は以下の２つ。

## 案1. postinstallスクリプトに登録する
```json-doc:package.json
"scripts": {
  // 中略
  "postinstall": "prisma generate"
},
"dependencies": {
  "prisma": "<version>" // devDependenciesではなく、dependenciesに入れる
}
```

## 案2. prisma generate の出力先を変更する
```tf:schema.prisma
generator client {
  provider = "prisma-client-js"
  // ここを追加するだけ
  output   = "../src/generated/client"
}
```

```ts
// 生成先のパスを参照する
import { PrismaClient } from './generated/client'
```

# 概要
- Node.jsでバックエンドを書いている
- ORMにはPrismaを使っている
- インフラは Google App Engine (以下、GAE)を使う

以上の条件のとき、問題が発生したので、その解決策を残す。

# 問題1 prisma generate しないとクライアントが使えない
prisma　のクライアントを使うときは、事前に`prisma generate`を実行する必要がある。GAE ではインスタンス開始時に npm scripts の`start`に設定したコマンドが実行されるので、`start`を以下のように変更した。

```json:package.json
"scripts": {
  "start": "prisma generate && node dist",
}
```

# 問題2 GAEのファイルは read only
しかし、GAEのファイルは read only であるため、`prisma generate`が失敗してしまった。

```log
Error: EROFS: read-only file system, unlink '/workspace/node_modules/.prisma/client/index.js'
```

# 解決策

## 案1
npm scripts の`postinstall`に指定したコマンドは`npm install`もしくは`yarn install`が実行された後に続けて実行される。ここに`prisma generate`を設定する。
ただし、GAEではデプロイ時に`dependencies`のみがインストールされ、`devDependencies`がインストールされないことに注意したい。`primsa`ライブラリは基本的に`devDependencies`のほうにインストールするが、この解決策を取る場合は、`dependencies`に移動する必要がある。

```json-doc:package.json
"scripts": {
  // 中略
  "postinstall": "prisma generate"
},
"dependencies": {
  "prisma": "<version>" // devDependenciesではなく、dependenciesに入れる
}
```

かんたんに設定できるが、prismaライブラリの分、node_modulesが肥大化する。スピンアップが遅くなり、コールドスタートが長くなる可能性がある。

※一応、本番環境でのみ`yarn remove prisma`を走らせることで回避できそう。

```bash:scripts/prisma_init.sh
#!/bin/bash
yarn prisma generate
if [[ $NODE_ENV = 'production' ]]; then
  yarn remove prisma 
fi
```

```json:package.json
 "postinstall": "bash scripts/prisma_init.sh"
```


## 案2
`prisma generate`の出力先はデフォルトだと、node_modules内だが、GAEはデプロイ時にインスタンス側で`npm install`が走り、その後は read only になるため都合が悪い。つまり、出力先を node_modules外に変更できれば、解決する。
公式ドキュメントを読んだところ、↓を見つけた。
https://www.prisma.io/docs/concepts/components/prisma-client/working-with-prismaclient/generating-prisma-client#using-a-custom-output-path

以下のようにすれば解決した。


```tf:schema.prisma
generator client {
  provider = "prisma-client-js"
  // ここを追加
  output   = "../src/generated/client"
}
```

`PrismaClient`をインポートしているコードも書き換えた。

```ts
import { PrismaClient } from './generated/client'
```

この方法のメリットは`prisma`をdependenciesに入れなくてすむので、サイズが軽くなり、コールドスタートが軽減されること。(ただし、ベンチマークを測ったわけではない)
デメリットは`prisma generate`を実行した環境がWindowsやMacだと、そのOS用の prisma バイナリが生成され、これがGAE環境では実行できないこと。

# 最後に
GAE はインフラにかかる工数を大幅に削減できるメリットがあるが、自由度は低い。
ただ、その低い自由度の中でも解決策は案外見つかる。
YouTube広告の自動スキップ（chrome拡張機能)

Every Qiita #16
のんびり独学初学者の毎日投稿チャレンジ 16日目
今回は・・・
YouTubeで広告を自動スキップとツールバーの広告を自動削除についての備忘録？です


###chrome拡張機能を使って削除する
*※今回はchromeブラウザのみで可能になります。そのほかスマホ等では他の方法がありますので、別記事を参考にしてください。*

**Enhancer for YouTube**
1.chromeウェブストアから上記を検索してください
![スクリーンショット 2021-07-18 14.32.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813099/96df9479-e89d-15bd-2c4f-ce995aa22ea6.png)
2.こちらをインストールすれば様々な設定をカスタマイズすることができます。
![スクリーンショット 2021-07-18 14.05.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813099/516ad479-4cea-212a-0849-fcf6aa94f8f3.png)
広告を削除にチェックを入れるとchrome上でyoutubeを開いた際に広告を削除してくれます。

###javascriptで独自にカスタマイズも可能
設定画面の下の方にエディタがあるので、こちらにスクリプトを書くことでyoutubeが読み込まれた際に自動的に実行することができます。
サイドバーの上部に広告が表示されているので、こちらも自動的に削除してみます。

1. 検証ツールから広告を表示しているidを取得
1. エディターにremoveメソッドを付与
![スクリーンショット 2021-07-18 14.25.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813099/5c1cf89e-738c-3cb4-d342-c10e215d2387.png)
これで完了です。
私がよく使うWindows セキュリティグループ / フォルダアクセス権設定コマンドチートシート

## はじめに

:::note info
私が利用するためのチートシートですが、どなたかのお役に立てるのでは無いかと思い、公開させていただきます
:::
Windows上でActive Directoryのセキュリティグループの操作・設定やフォルダアクセス権の設定に関する`私`が普段よく使うコマンドを以下にご紹介させていただきます。私の場合には以下のコマンドがあれば行いたい作業の大体の８割くらいはまかなえています。


## 環境

* Windows10 Pro + ActiveDirectoryモジュールインストール済
* Windows Server 2016 / 2019

## セキュリティグループの操作

* 利用ターミナル：Powershell

|したいこと    |コマンド|備考|
|-----------|-----|----|
|セキュリティグループ管理者Windows ADアカウントに昇格|**runas** /user:adminhoge@ad.hoge.co.jp powershell.exe|対話でパスワードを聞かれるので入力します|
|新規作成    |**New-ADGroup** *-Name* AD-GROUP-001 *-GroupScope* Global *-Path* "OU=Hoge,OU=Foo,OU=Baa,DC=ad,DC=teruroom,DC=co,DC=jp" *-Description* "ADグループ001"|<ul><li>OU：サブフォルダ</li><li>DC：ドメインコントローラ</li></ul>※階層下位⇨上位順に記述|
|説明確認|**Get-ADGroup** *-Identity* AD-GROUP-001 *-Properties* description &#124; *Select-Object* {$_.**Description**}||
|登録対象メンバアカウント確認|**Get-ADUser** *-LDAPFilter* "(Name=\*ほげ ハゲ子\*)" &#124; *Select-Object* {$_.**Name**}|ワイルドカード`*`を利用可能|
|メンバ追加   |**Add-ADGroupMember** *-Identity* AD-GROUP-001 *-Members* A0000001, A0000002|メンバのWindowsADアカウントをカンマ区切りで列挙|
|登録済メンバ確認|**Get-ADGroupMember** *-Identity* AD-GROUP-001 &#124; *Select-Object* {$_.**Name**}||

* `|`：コマンドパイプで、左のコマンドの出力結果を入力として右のコマンドに渡します

## フォルダアクセス権の操作

* 利用ターミナル：コマンドプロンプト
    * 同様のことができるPowershellコマンドもありますが、私はコマンドプロンプトベースの`icacls`を普段使いしています。

|したいこと|コマンド|備考|
|-------|------|------|
|フォルダアクセス権管理者Windows ADアカウントに昇格|**runas** /user:adminhoge@ad.hoge.co.jp cmd.exe|対話でパスワードを聞かれるので入力します|
|フォルダパス設定|**set** FOLDER_PATH="¥¥ほげ本部¥ハゲ部¥フーチーム¥"||
|アクセス権参照|**icacls** %FOLDER_PATH%||
|［既存]アクセス権[削除]|**icacls** %FOLDER_PATH% **/remove:g** AD-GROUP-001||
|[参照]アクセス権[追加]|**icacls** %FOLDER_PATH% **/grant:r** AD-GROUP-001:(CI)(OI)(**R**)|<ul><li>既存のアクセス権に追加</li><li>下位フォルダに再起的にアクセス権を継承</li></ul>|
|[更新]アクセス権[追加]|**icacls** %FOLDER_PATH% **/grant:r** AD-GROUP-001:(CI)(OI)(**M**)|↑同上|
|[フル]アクセス権[追加]|**icacls** %FOLDER_PATH% **/grant:r** AD-GROUP-001:(CI)(OI)(**F**)|↑同上|
|[参照]アクセス権[新規]|**icacls** %FOLDER_PATH% **/grant:r** AD-GROUP-001:(CI)(OI)(**R**) **/inheritance:d**|<ul><li>新規でアクセス権を設定</li><li>上位フォルダからのアクセス権の継承を切断</li><li>下位フォルダに再起的にアクセス権を継承</li></ul>|
|[更新]アクセス権[新規]|**icacls** %FOLDER_PATH% **/grant:r** AD-GROUP-001:(CI)(OI)(**M**) **/inheritance:d**|↑同上|
|[フル]アクセス権[新規]|**icacls** %FOLDER_PATH% **/grant:r** AD-GROUP-001:(CI)(OI)(**F**) **/inheritance:d**|↑同上|

### アクセス権指定子

* セキュリティグループ名の後に`:`区切りで指定します

|アクセス権指定子|意味|備考|
|------------|----|---|
|(R)         |参照権限を付与|読み取り権限|
|(M)         |更新権限を付与|読み・書き権限|
|(F)         |フル権限を付与|フォルダ新規作成・削除など全ての操作が可能|
|(CI)        |下位のフォルダにコンテナ継承|下位フォルダにアクセス権を継承|
|(OI)        |下位のフォルダにオブジェクト継承|下位フォルダ内のファイルにアクセス権を継承|

## ご参考まで

* 管理者権限が必要な場合：
    * 必要な管理者権限Windows ADアカウントでWindowsにログインし直すのは面倒です
    * 現在のWindows ADアカウントのまま、適切な管理者Windows ADアカウントに昇格してからコマンドを投入することをお勧めします
Docker構築したことないエンジニアが基本知識をつける

## 概要的なところ
- データやプログラムをOSごと隔離できる仕組み
- docker engineでコンテナを作成、使用できる
- イメージ＝コンテナの元
- Linux OSが必須、理由はLinux上で動かすものだから
- コンテナの中は空ではなく「Linux OS的なの」が入っている
- 元のもの＝イメージ、イメージから作る実際に動いているもの＝コンテナ
- 逆にコンテナからイメージを作ることもできる
- イメージは自分でつくることはない、Docker Hub(https://hub.docker.com/2ww2szxswx3)が提供してくれている
- 一つのコンテナに一つのアプリ
- 長く大事に使うのではなく、使ったら捨てるを繰り返すことが大事
- dockerをインストールしている物理的なマシンのディスクにマウントする
- コンテナのライフサイクル　作成ー＞起動ー＞停止ー＞削除ー＞作成

## メリット
- 複数のコンテナに同じプログラムを入れることができるので、バージョンの影響がでない
- 通常であれば一つのサーバに一つのWEBサーバしか置けないけど、隔離することで複数置くことができる
- コンテナは持ち運ぶことができる 

## Dockerの基礎知識まとめ
- docker-compose up -d で起動
- docker-compose stop で停止
- コマンド基本形＝docker コマンド (オプション) 対象（引数）
- バージョン確認　docker version
- pull、create、startを同時にできるのがrun
- docker container stop 停止
- docker container rm 削除
- コンテナを破棄するためには停止させる必要がある
- docker ps コンテナの一覧を表示できる
- docker image rm イメージ名　イメージの削除
- docker image　ls イメージの一覧表示
- docker network create ネットワーク名　ネットワーク作成
- docker network rm ネットワーク名　ネットワーク削除
- docker cp コピー元パス　コピー先のコンテナ名：コンテナ側パス

## コンテナのイメージ化（２種類ある）
①commitコマンドで書き出す
docker commit コンテナ名　作成するイメージ名
②docketfileでイメージを作成する

## Docker composeとは
- 構築に関わるコマンドの内容を1つの定義ファイルに書き込んで、一気に実行することができる
- 定義ファイル「YAML」を用意し、そのファイルを「up」したり、「down」したりする。
- dockerファイルはイメージをつくるもので、ネットワークやボリュームを作成できない。
- 定義ファイルは「docker-compose.yml」と決まっている
- 定義ファイルは一つのフォルダに一つのみ。
- 複数の定義ファイルを使いたい場合は、フォルダを複数用意する

## Kubernetes(クーべネティス)とは
- コンテナのオーケストレーションツールのこと
- k8sとも書く
- オーケストレーションツールとは複数のコンテナを管理できるツールのこと
- 複数の物理的なマシンを使用し、1台のサーバに複数のコンテナを扱うことが前提
- その時に毎回docker comoseを叩くのは大変なのでその煩雑さを上手くやってくれるツールのこと
DatabricksにてPythonにより現在のノートブックのパスを取得する方法

## 概要
`dbutils.notebook.entry_point.getDbutils().notebook().getContext()`によりノートブックのセッション情報が取得でき、`notebook_path`の値が現在のノートブックのパスであるようです。

```python
import json
notebook_info = json.loads(dbutils.notebook.entry_point.getDbutils().notebook().getContext().toJson())

notebook_info
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/80612f7f-be42-edcd-9eaf-4481e4e7336e.png)

本記事は、下記のStack Overflowの投稿内容を参考にしております。

- [python - How can I reference the path of a notebook in Databricks/what is %run doing? - Stack Overflow](https://stackoverflow.com/questions/50771584/how-can-i-reference-the-path-of-a-notebook-in-databricks-what-is-run-doing)

## 現在のノートブックのパスを取得する方法
### 1. 下記のコードを実行

```python
import json
notebook_info = json.loads(dbutils.notebook.entry_point.getDbutils().notebook().getContext().toJson())

current_notebook_path = notebook_info['extraContext']['notebook_path']

print(current_notebook_path)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/134f9ff3-eeb1-289d-b729-5bc1e8134ca2.png)
Class図 PlantUML on Qiita

QiitaでPlantUMLが使えるようになった。

# 公式
https://plantuml.com/ja/class-diagram

# クラス
```
class Car 
```

```plantuml
class Car
```

# 実装
```
interface Car
class Benz implements Car
```

```plantuml
interface Car
class Benz implements Car
```

# 継承
```
interface Car
class Benz implements Car
class SUV extends Benz
class Sedan extends Benz
```

```plantuml
interface Car
class Benz implements Car
class SUV extends Benz
class Sedan extends Benz
```

# 集約
```
class Parking
interface Car
Parking o-- Car
```

```plantuml
class Parking
interface Car
Parking o-- Car
```

# コンポジション
```
class Parking
class BillingSystem
class ChargeTimeOverNotificationSystem
Parking *-- BillingSystem
Parking *-- ChargeTimeOverNotificationSystem
```

```plantuml
class Parking
class BillingSystem
class ChargeTimeOverNotificationSystem
Parking *-- BillingSystem
Parking *-- ChargeTimeOverNotificationSystem
```

# 依存
```
class BillingSystem
enum BillingPlan
BillingSystem ..> BillingPlan
```

```plantuml
class BillingSystem
enum BillingPlan
BillingSystem ..> BillingPlan
```
PHPを書くときに注意することリスト

PHPは自由度が高く、サクッと動くものを作るのに適した自分のような初心者にも優しい、素晴らしい言語ですよね。

一方で、自由度の高さゆえに意図しない挙動を示すことが多々あり、ある程度サービスの規模が大きくなってくると、思わぬ罠に引っかかったりすると思います。

そこで、PHPを書き始めてから3ヶ月ほど経ち、だんだん知見も溜まってきたので
個人的にPHPを書くときに気をつけたいと思ったことをリストアップしてみたいと思います。
（随時更新予定）

# in_arrayはデフォルトで型の比較をしない
第一引数に指定した値が、第二引数のarrayに含まれているかどうかを判断する`in_array`という関数、けっこう多くの場面で使うのではないでしょうか？

```php
$value = $this->getValue();
$targets = array(
  'hoge',
  'fuga',
  'piyo',
);

if (in_array($value, $targets)) {
  // やりたい処理
}
```

こんな感じで`$targets`に処理を行いたい対象を列挙しておいて、`$value`が対象だったら処理をする、みたいな使い方をすると思います。
しかしこのin_arrayで行われる比較、デフォルトでは型の比較を行わない、`==`での比較になっているので注意が必要です。
例えば

```php
in_array(0, [0, 1, 2]);
// -> true 
// 意図した挙動

in_array(3, [0, 1, 2]);
// -> false
// これも意図した挙動

in_array('hoge', [0, 1, 2]);
// -> true !?
// 意図しない挙動(PHP8.0からはfalseを返すようになりました)
```

このような形で、第二引数のarrayに`'hoge'`という文字列を含んでいないのにもかかわらずtrueになってしまいます。（PHP8.0からは変更になりました。）
これは`==`によって、文字列の`'hoge'`が暗黙的にint型に変換されてから比較されるためです。
PHPでは`'hoge'`のような数字以外の文字列をint型に変換すると基本的に`0`になります。（JSなどではNaNになる）

```php
intval('hoge');
// -> 0
```

では、厳密に比較したい場合、つまり`===`にしたい場合はどうすればいいのかというと、`in_array`関数の第三引数にtrueをつければOKです。すると`===`で比較を行ってくれるようになります。

```php
in_array('hoge', [0, 1, 2], true);
// -> false
// ===で比較している
```

チームでin_arrayを使うときは必ず第三引数を指定する、というルールにしてもいいかもしれません。

参考 https://qiita.com/ritukiii/items/3a6add378ae089ab5d70

## 2021/07/20追記
PHP7.4までは上記の挙動のとおりですが、PHP8.0からは変更になったようです。
（コメントいただきありがとうございます。）
PHP8.0からは、`==` の挙動が変わりました。文字列と数字を比較する際、これまでは文字列を数値に変換していましたが、PHP8.0からは数値を文字列に変換するようになりました。
つまり`"hoge" == 0 `を実行するとき、数値の`0`が文字列の`"0"`に変換され、その上で`"hoge"`と`"0"`が比較されます。これらの文字列は異なっているため、PHP7.4までとは違い、これはfalseを返します。
これに伴い、`==`で比較を行う`in_array`も挙動が変わったということです。

# メソッドやクラスで大文字と小文字の区別をしない

プログラミング言語の一般的な話として、関数名や変数名などで大文字、小文字の区別をすることをcase-sensitive、逆に区別せず同一視することをcase-insensitiveといいます。
PHPでは関数名、メソッド名、クラス名などがcase-insensitiveになっているので注意が必要です。
例えば

```php
function hoge() {
   echo 'some message';
}

hoge();
// -> some message

Hoge();
// -> some message

hOgE();
// -> some message
```

こんな感じでも関数が呼び出せてしまいます。ここまでわざとらしい書き方をすることはないと思いますが、`URI`とか`ID`などの表記揺れが起こりそうな関数名の場合、普通に動いてしまってタイポに気づかないことがありそうです。

```php
function getUri(){
   // 
}

getURI();
// -> エラーなく動いてしまう
// Uriとかで検索したときにヒットしない

```

特にリファクタリングなどの際、この関数使ってるかな？ということで小文字で検索し、引っかからなかったから消したら実は大文字で使っていた箇所があって障害に繋がる、なんてことがありそうなので注意しましょう。

参考 https://qiita.com/tadsan/items/6c6329eeb43929271119

# &&とand, ||とor

一般的に使われている`&&`や`||`の他に`and`, `or`という演算子も存在しているそうです。
そしてこれらは演算子としての優先順位が異なるため、注意が必要です。

ハマりそうな優先順位としては、上から順に

- &&, ||
- = (代入演算子)
- and, or

となっているので`and`や`or`をつかうと下記のように、意図しない挙動を示すことがあります。

```php
$a = false || true;
// -> $aはtrue
// 意図した挙動

$b = true && false;
// -> $bはfalse
// 意図した挙動

$c = false or true;
// -> $cはfalseになる
// 意図しない挙動
// orの評価よりも先に$c = falseの代入が行われるため

$d = true and false;
// -> $dはtrueになる
// 意図しない挙動
// andの評価よりも先に$d = trueの代入が行われるため
```

基本的には`and`, `or`を使わず`&&`, `||`を使えばいいと思いますが、「どうせ同じだろ〜」といきおいで使うと痛い目をみそうです。


参考 https://www.php.net/manual/ja/language.operators.logical.php

# 最後に
いかがだったでしょうか？
今後も数を増やしていきPHPを書くときのチェックリストのようにしていきたいと思っています。
バージョンxxからは改善されてるよ！みたいなことがあればコメントなどで教えていただけると嬉しいです。
LaravelのMVCモデルについて理解する

#環境
PHP 7.3.24
Laravel 6.20.30
MAMP

#MVCモデルとは
MVCモデルとは、プログラムを役割ごとに分けて開発するという概念のことです。

M・・・Model(モデル)
V・・・View(ビュー)
C・・・Controller(コントローラ)
MVCモデルは上記の頭文字をとったもので、それぞれ役割が決まっていてその役割が作用しあっています。

#各機能の役割と処理の流れ

![スクリーンショット 2021-07-18 13.23.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916260/284deb3b-3a69-82b1-5019-e894e78b6c19.png)

MVCモデルにおける処理の流れを図で表してみました。
それぞれの流れについてみていこうと思います。

①でリクエスト処理を行なっています。お問い合わせフォームの入力やショッピングサイトでの商品購入、Googleでの検索などを行うとリクエスト処理が走ります。

②のルーティング処理とは、①で送られてきたリクエストURLをどのControllerで処理するのかを振り分ける処理のことです。

③ではルーティングで指定されたコントローラが実際に処理を行なっていく過程になります。①のリクエストで送られてきたデータはModelで処理するものなのかViewで処理するものなのかを判断して指示を出します。

④はModelがControllerから受けた指示によってDBの処理を行います。

⑤で④で行なった処理結果をControllerに返します。

⑥ではModelから返却された処理結果をView用に変換して実際にユーザーの画面上に表示できるようにします。

⑦で⑥で行なった処理に基づいて出力するように指示を出します。（View用に変換はできてもControllerで画面表示させることはできない）

⑧ViewがControllerからの指示を実行することでユーザーの画面に表示されます。

以上を踏まえて、ModelとViewとControllerの役割を一言で表してみました！
・ModelはDBの処理を行う役割
・Viewは画面の表示部分を作る役割
・ControllerはModelとViewに指示を出しつつ、中心となる処理を担う役割


#参考
[MVCモデルについて](https://qiita.com/s_emoto/items/975cc38a3e0de462966a)
[MVCモデルとは！概念やそのメリットをわかりやすく解説！](https://www.geekly.co.jp/column/cat-technology/1911_040/)
[MVCモデルとは？フレームワークを使う前に知っておきたい！](https://snome.jp/framework/mvc-model/)
[MVCパターンについて](https://laraweb.net/surrounding/922/)
ローカルにgit cloneしたSpring Boot プロジェクトをSTSに表示する方法

githubからローカルリポジトリにクローンしたSpring BootプロジェクトをSTS上に反映させるのに手こずったため、
こちらで手順を共有します。

#環境
STS：4.11.0.RELEASE
java：16
Spring Boot：2.5.2


#前提

こちらがクローン後のローカルリポジトリになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413385/989e6dd1-0aac-3c14-c03c-a5024722fbda.png)

#手順
###1. STSを起動し、「ファイル」>「インポート」>「Gradle」(※)>「既存のGradleプロジェクト」を選択し、「次へ」をクリック
※プロジェクトで採用しているビルドツールを適宜選択して下さい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413385/84c5305b-9aa8-e2a7-0d83-117b339c0720.png)
####<font color = "Red">ここで、「一般」を選択してしまうと、インポート後にSpring Bootプロジェクトとして認識されないので注意！！</font>


###2. Gradleプロジェクトのインポートダイアログの「参照」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413385/16f58459-a73e-dccb-28b5-a5bfa90fdc5f.png)

###3. エクスプローラが表示されるので、インポートしたいプロジェクトを選択
今回は「demo-1」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413385/bd767b5d-4d13-2dc1-f1e8-10614f034752.png)

###4. Gradleプロジェクトのインポートダイアログの「完了」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413385/017537ef-9411-8a61-0300-66b4c45b5329.png)

###5. STSの「パッケージ・エクスプローラ」を見ると、3.で選択したプロジェクトが表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413385/e707982b-5342-4ff1-bafe-15a138823127.png)

###終わりです。
toCアプリ開発を１年やってみた感想まとめ

# toCアプリ開発を１年やってみて学んだ知見まとめ

業務委託案件にて約１年間（実際には10ヶ月）toC向けアプリ開発を経験しました。

toC向け（一般ユーザー向け）アプリ開発は初めての経験でしたので、そこで感じた（学んだ）内容を退職を機会にアウトプットしてみようと思います。


## どんなアプリを開発してた？

ライブ配信アプリを開発していました。

有名なライブ配信アプリでいうと、17LIVE (イチナナ) 、LINELIVE、Pococha（ポコチャ）があります。

そこまでの最大手とはいきませんが、DAU（Daily Active User）が１万人ほどの中規模ライブ配信アプリを開発していました。

## 技術スタックはどんな感じ？

```
クライアントサイド：Unity
バックエンド:Rails
クラウドインフラ: GCP, K8s,Firebase
音声配信: Agora
```

AWSではなくGCPを選択した理由はシンプルに料金体系がAWSより安かったからです。

自分はバックエンドのRailsでAPI開発（DB設計、API設計、テスト、バグ改修）をメインに担当していました。

## toC向アプリ開発して楽しかったことは？
toC向けアプリ開発を経験して楽しかった（身になった）ことをまとめます。

### 1. ユーザーのリアクションがダイレクトに見える
toCアプリの最大の醍醐味は本番リリースした後にすぐにユーザーのリアクションが見えることだと思います。

自分はTwitterなどで自分が担当した機能がリリースされる度に必ずユーザーリアクションを確認していました。

実際にユーザーが面白いなどの感想をTwitterで書き込んでくれることがあるので、それはすごくやりがいを感じることができました。

無論、ネガティブな感想などもあるのですが、それはそれで勉強になるので良い経験になりました。

### 2. 開発スピードが速く、エンジニアとして成長できる
次々に生まれるライバルアプリに対抗するためには、新機能を開発してユーザーを飽きさせないようにするフローを高速で回すことが大事です。

そのため開発で一番大事になるのはスピードです。新機能をスピーディーにリリースする必要があります。

その上で保守性やパフォーマンスを意識して開発する必要があります。

エンジニアとしてはきつい環境ではあるのですが、その分成長するスピードが速いです。

スピーディーに開発する貴重な経験を積めました。

### 3. 友達に自慢できる

toC向けアプリ開発をしていると友達に自慢できるのもメリットの一つかもしれません。（あまり自慢しすぎると嫌われるかもですが笑）

自分の開発しているアプリを利用している友人がいるときに、このアプリ自分が開発したんだよ〜と伝えると、結構の割合ですげ〜と言ってくれます笑


## toC向けアプリ開発して辛かったことは？
逆にtoC向けアプリを開発して辛かったこともあるので記載します。

### 1. 大規模アクセスを見越してパフォーマンス意識してコード書く必要がある

toB向けアプリや社内向けアプリだと、ユーザー数が多くても1000未満のケースが多いですが、toC向けアプリだとユーザー数が数万人になるケースが多いです。

例えばアクセスが少ないアプリだと最悪N+1が発生していてもアクセスが少ないので最悪スルーしても問題にならないケースが多いです。（本当は良くないけどね....)

しかし大規模アクセスになってくると、一つのAPIに数万アクセスされるケースがあります。

そんな状況でN+1が発生している、もしくはクエリ発行回数を意識しないで書かれたパフォーマンスが低いコードを書いてしまうとユーザー体験を著しく落としてしまいます。

とりあえず動けばいいかで書かれたコードではなく、パフォーマンスを意識したコードを書かなければならないのは結構負荷が高いです。

### 2. バグ出した時が辛い

toCアプリでユーザー数が増えてくると、バグを出した時辛いです。

ユーザー数が多いので、バグでアプリ落としてしまうと多くのユーザーに迷惑をかかってしまうのでバグに常に最新の注意が必要です。

バグを出さないためにも、バグ検知ツールを導入したりQAテストを本番リリース前に行う必要があります。

### 3. 開発しているアプリのファンになる必要がある

これは盲点だったのですが、toC向けアプリを開発する上で自分の開発しているアプリのコアユーザーになる必要があります。

なぜなら、自分の開発しているアプリのファンにならなければ開発モチベーションを保つのがしんどいからです。

このアプリをもっと多くの人に届けたいという気持ちがtoCアプリ開発では大事になります。

実際に自分の開発していた会社のエンジニアの多くは仕事外でもアプリを趣味で利用していました。

### 4.　アクセス負荷分散が大変
ライブ配信のようなtoCアプリでは負荷分散システムの構築が重要になります。

例えばライブ配信アプリのようなエンタメ系のアプリでは、何かのバズが起きた時に急に普段の数倍のアクセス発生するケースがよくあります。

大量アクセスがあったので、アプリ落ちましたすいません！ではユーザーが激怒するのでインフラアークテチャ設計をミスると取り返しがつかないことになります。

私たちの会社ではアクセス負荷システム（オートスケール）にk8sを利用して、アクセスに応じてコンテナオーケストラレーションシステムでコンテナ管理を負荷に応じて自動化できるようなシステムを採用していました。

ユーザーが爆増した時にもスムーズにオートスケール出来るようなアークテクチャシステムを設計を考えるのが大事になります。

## まとめ
今までのお仕事ではtoB向けアプリや社内ツールアプリの開発が多かったのですが、toCアプリ開発を通して多くのことを学ぶことが出来ました。

ただ、toCアプリ開発する上ではそのアプリのファンにならなければ開発モチベーションを保つのがしんどいなと感じました。
Introduction to Time Series and Forecasting, Springer, Peter J. Brockwell and Richard A.Davis

```{r}

#5.1.4 Hannan-Rissanen Algorithm p.154

#ARMA

data("AirPassengers")

values=c(AirPassengers)

k=3;q=3;m=max(q,k)+1

x=array(0,dim=c((length(values)-k),k))

y=c()

for(j in 1:(length(values)-k)){

vec=values[j:(j+k-1)]  

x[j,]=vec

y=c(y,(values[k+j]))

}

pthi=solve(t(x)%*%x)%*%t(x)%*%y

Z=y-x%*%pthi

Z=c(rep(0,k),Z)

X=array(0,dim=c((length(values)-(m+q)),k))

z=array(0,dim=c((length(values)-(m+q)),q))

count=0;yy=c()

for(j in (m+q):(length(values)-1)){

vec=values[j:(j+1-k)]  

count=count+1

X[count,]=vec

vec=Z[j:(j+1-q)]

z[count,]=vec

yy=c(yy,(values[1+j]))

}

mat=cbind(X,z)

beta=solve(t(mat)%*%mat)%*%t(mat)%*%yy

pthi=beta[1:k]

print(sum((yy-mat%*%beta)^2))



```
Next.js + TypeScriptで開発時に型チェックが走らない件

## TL;DR

https://github.com/vercel/next.js/issues/14997

- 議論中(2021-07-18時点)のIssueです
- バグというよりは機能を追加するという議論、メンテナー側はあまり乗り気ではなさそう

### 迂回策の案

- ``tsc --watch``を実行しておけば、型エラーを検知できる（Next.js側でエラーにはならない）
- 以下の例みたいにコンソールを並べておけばエラーは見つけられるかと

![スクリーンショット 2021-07-18 13.29.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73197/9e45899c-5efe-cf88-74aa-99aacabcbdf9.png)

## 詳細

- ``next``で開発する際、型エラーを起こすコードを書いてもNext.jsアプリケーション上でコンパイルエラーにならない（JavaScriptライクにゆるふわに解釈される）
- ``next build``でビルドする際には型チェックが入るので、その時点ではエラーになる
- これはIssueも登録されているが、まだ議論中で未解決
    - メンテナー側はパフォーマンス低下の観点からあまり乗り気ではないが、開発時にも型チェックは必要でしょうという意見も多く、今後に期待
Windows で MikanOS (その6:メモリマップの確認)

お疲れ様です！お久しぶりです！いつも大変お世話になっております。！！
なんだかんだと6回目になりました！今回もどうぞよろしくお願いいたします！！！

#【前回から】
前回の「その5」では MikanOSのとっかかり(まだ言うか!)
MikanLoader パッケージを更新してビルドしました。

"みかん本" の章が進むにつれて、「Windows環境だけで
進めようとすると」(ここ大事!)、ちょっとずつ何かしないと
ビルドできなかったり、確実に動作確認がしにくかったり
してきているような気がします。

今回はVMwareのディスクイメージに記録されている メモリ
マップ の情報が記録されたファイルを参照する方法について
となります。

Windows10 ではVMwareのディスクイメージファイルである
vmdkファイルを直接マウントして参照することができません
でした。
そのため、「その１」で使用させてもらったツールを使用して、
vmdkファイル を VHDXファイル へ変換したのちマウントする
方法をとることとしました。


#【今回の目標】
・"みかん本" の「2.7章 メモリマップの確認」を Windows環境 で行う。

#【結果】
！確認できました！
ツールのお世話になりっぱなしです。

#【必要なもの】
・「その5」までで記載した「【必要なもの】」一式

#【手順】
1. コマンドプロンプトを開く

2. 「その1」で使用した NHCC が格納されたディレクトリに移動する
　- cd c:\WinMikanOS\osbook\day01\bin

3. 変換後のVHDXファイルの格納先フォルダを作成する
　- md c:\WinMikanOS\osbook\day02

4. 以下のような設定で NHCC.exe を実行する
　- nhcc.exe -o 4 "C:\WinMikanOS\Virtual Machines\MikanOS\MikanOS.vmdk" ..\..\day02\ResultMikanOS.VHDX
　※nhcc.exeのオプションについては
　　-o : ファイルシステムの情報を利用してできる限り小さいサイズにする。(トリム済みになる)
　　4 : 変換先の形式番号、4はHyperV VHDX 
　　"C:\WinMikanOS\Virtual Machines\MikanOS\MikanOS.vmdk" : 変換元のファイル
　　..\..\day02\ResultMikanOS.VHDX : 変換後のファイル

5. エクスプローラで変換後のVHDXファイルをダブルクリックして
マウントする

6. マウントしたドライブのルートにある memmap ファイルを
お好みのテキストエディタで開く


#【紆余曲折】
・VMwareの仮想ディスクであるvmdkファイルは、1パーティション目で
　あれば簡単にWindowsで直接マウントできる!と思い込んだのが失敗
　でした。
・3章～4章にかけて先行して進めていたのですが、どうしてもうまく
　いかず、そちらに気を取られていたため今回の記事が大変遅くなって
　しまいました。
・VMwareってVHD指定でもイケたんですね(滝汗)


#【次回の目標】
・"みかん本" の「3.3章 初めてのカーネル(osbook_day03a)」を
　Windows環境 で行う。
　にしようと思っています。
　- Visual Studio 2017(2015)でKernelがビルドできていない
　　->Win版LLVMを使用したビルドがイケました！
　- Win版LLVMを使用したKernelに制御が渡せない
　　->ここで難航していましたがなんとか解決しました！


ありがとうございました！
2.15(標準) 変数変換6

## 方針

変数変換はまず分布関数から考える．分布関数ができたらそれを微分することで確率密度関数を求める．

## 答案

Yの分布関数は，

```math
\begin{align}
F_Y(y)&= P[Y\leq y]\\
&= P[X^2\leq y]\\
&= 
\begin{cases}
P[-\sqrt{y}\leq X\leq \sqrt{y}]\ \ \ (0\leq y\leq 1)\\
P[X\leq\sqrt{y}]
\end{cases}
\end{align}
```

(i)0<=y<=1の時，

```math
\begin{align}
F_Y(y)&= \int_{-1}^{\sqrt{y}}\frac{2}{9}(x+1)dx-\int_{-1}^{-\sqrt{y}}\frac{2}{9}(x+1)dx\\
&= \left[\frac{x^2}{9}+\frac{2}{9}x\right]_{-1}^{\sqrt{y}}-\left[\frac{x^2}{9}+\frac{2}{9}x\right]_{-1}^{-\sqrt{y}}\\
&= (\frac{y}{9}+\frac{2}{9}\sqrt{y}-\frac{1}{9}+\frac{2}{9})-(\frac{y}{9}-\frac{2}{9}\sqrt{y}-\frac{1}{9}+\frac{2}{9})\\
&= \frac{4}{9}\sqrt{y}
\end{align}
```

より，確率密度関数は

```math
f_Y(y)=\frac{2}{9\sqrt{y}}
```

(ii)1<=y<=4の時，

```math
\begin{align}
F_Y(y)&= \int_{-1}^{\sqrt{y}}\frac{2}{9}(x+1)dx\\
&= \left[\frac{x^2}{9}+\frac{2}{9}x\right]_{-1}^{\sqrt{y}}\\
&= \frac{y}{9}+\frac{2}{9}\sqrt{y}-\frac{1}{9}+\frac{2}{9}\\
&= \frac{1}{9}(y+2\sqrt{y}+1)
\end{align}
```

より，確率密度関数は

```math
f_Y(y)=\frac{\sqrt{y}+1}{9\sqrt{y}}
```

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
超初心者がPythonでHistData.comから為替レートの1分足チャートを通貨ペア毎に取得してみた

タイトル通りだが、取得先は[HistData.com](https://www.histdata.com/)で、histdataというライブラリを使用している。histdataはpipでインストールできます。

## 参考

https://qiita.com/fxst24/items/b2d803ca68684f1d2b8a

## コード

``` download_histdata.py
import glob
import os
import pandas as pd
import zipfile

from datetime import datetime
from histdata import download_hist_data as dl

# FXデータをダウンロードして1つに結合する関数
def download_forex_data(symbol, start_year, folder):

    #　去年以前のデータをDL(ファイルは年ごと)して解凍
    for year in range(start_year, datetime.now().year, 1):
        filename1 = (folder + '/DAT_ASCII_' + symbol + '_M1_' + str(year) +
                     '.zip')
        #print("[01]" + filename1)
        if os.path.exists(filename1)==False:
            dl(year=str(year), pair=str.lower(symbol), output_directory=folder)
            zip_f = zipfile.ZipFile(filename1)
            zip_f.extractall(folder)
            zip_f.close()
    
    #　今年のデータをDL(ファイルは月ごと)して解凍
    for month in range(1, datetime.now().month, 1):
        if month < 10:
            filename1 = (folder + '/DAT_ASCII_' + symbol + '_M1_' + str(datetime.now().year) + '0' + str(month) + '.zip')
        else:
            filename1 = (folder + '/DAT_ASCII_' + symbol + '_M1_' + str(datetime.now().year) + str(month) + '.zip')
        #print("[02]" + filename1)

        if os.path.exists(filename1)==False:
                dl(year=str(datetime.now().year), month=str(month), pair=str.lower(symbol), output_directory=folder)
                zip_f = zipfile.ZipFile(filename1)
                zip_f.extractall(folder)
                zip_f.close()
    
    # 上で解凍したCSVを通貨ペアごとに結合
    filenames = sorted(glob.glob(folder + '/DAT_ASCII_' + symbol + '*.csv'))
    df = pd.DataFrame()
    for filename in filenames:    
        #print("[03]" + filename1)

        temp = pd.read_csv(filename, sep=';', header=None, index_col=0)
        df = df.append(temp)
    df.to_csv(os.path.expanduser(folder + '/' + symbol + '.csv'))



start_year = 2018
folder = './temp_historical_data'
#　for symbol in ['AUDUSD', 'EURUSD', 'GBPUSD', 'NZDUSD', 'USDCAD', 'USDCHF', 'USDJPY']:
for symbol in ['USDJPY', 'GBPJPY', 'AUDJPY']:
    download_forex_data(symbol, start_year, folder)

```

## ちょっと説明

1. 年間のデータをzipでダウンロードしてみて、あったら解凍し、csvにしておく
2. 年間データがなければ月毎データをzipでダウンロードして解凍し、csvにしておく
3. 通貨ペアごとにcsvを結合

という流れ。ダウンロード先、解凍先はtemp_historical_dataディレクトリなので実行前に作成しておく。
privateメソッドの記述。

このようなエラーが出ました。確認したところ、sessions_controllerのdestroyの記述は問題ありません。

![スクリーンショット 2021-07-18 12.45.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1286751/389876ab-0a51-d626-65a4-a98546ee2e9e.png)




```sessions_controller.rb
  private
  
  def login_form_params
    params.require(:admin_login_form).permit(:email,:password)
  end

  def destroy
    session.delete(:administrator_id)
    flash.notice = "ログアウトしました。"
    redirect_to :admin_root
  end
end
```
上記のように記述すると、private以下すべての処理に適応されてしまいます。




```sessions_controller.rb
  private  def login_form_params           <==ここを変更。
    params.require(:admin_login_form).permit(:email,:password)
  end

  def destroy
    session.delete(:administrator_id)
    flash.notice = "ログアウトしました。"
    redirect_to :admin_root
  end
end
```

これで指定した処理にのみprivateが適応されます。
M1 Mac で fish terminal を使ってる人がSBTを使えるようにする


M1チップのMacだとHome BrewでSBTをインストールできなさげだった。

# Setup SDKMAN!

ということなのでSDKMAMNを使うことに。

https://www.scala-sbt.org/1.x/docs/Installing-sbt-on-Mac.html

### Install SDKMAN!

```sh
curl -s "https://get.sdkman.io" | bash
```

### Install fish plugin for using SDKMAN!

fish terminalでSDKMANを実行できるようにプラグインをインストール。

https://github.com/reitzig/sdkman-for-fish

```sh
fisher add reitzig/sdkman-for-fish@v1.4.0
```

ここまででSDKMANのセットアップは終了。

# Install SBT

SBTをインストール。

```sh
sdk install sbt
```

おしまい。
レンタルサーバからエンハンスドDBに接続する形でWordPressを動かしてみた

## はじめに
レンタルサーバからエンハンスドDBに接続する形でWordPressを動作させることができそうか確認してみました。

エンハンスドDBはMySQLと互換性のあるデータベースサービスです。
2021年7月現在さくらのクラウドユーザーはLabプロダクトとして無料で利用可能です。
https://www.sakura.ad.jp/information/pressreleases/2021/07/08/1968207460/

## エンハンスドDBの準備
クラウドコンパネでDBを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44791/1b932141-b44d-a026-6f38-d6cfee76815d.png)

データベース名（これがデータベースサーバーへ接続する際のユーザー名としても使用されるようです）：****
パスワード：****

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44791/9507b6f6-a177-6f9f-98bd-2a47612290ca.png)

作成すると接続先ホスト名がわかりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44791/b62fde7f-7abd-65b7-a014-e8cced7853b3.png)

## WordPressの(クイックじゃない)インストール

今回はレンタルサーバにSSHログインして[公式の手順](https://wordpress.org/support/article/how-to-install-wordpress/)を見ながらインストールしました。

実行コマンドイメージ

```
適当なディレクトリを作成
% mkdir tekitou
% cd tekitou

zip をダウンロード
% wget https://wordpress.org/latest.tar.gz

zip を展開
tar -xzvf latest.tar.gz

展開されたファイル等を1階層上に移動
% cd wordpress
% mv * ..
% cd ..
% rmdir wordpress
```

ブラウザからアクセスし言語を設定後DBを設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44791/58cbf10e-e3b5-c54f-828a-9a927a226574.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44791/e86d3f09-bb37-e1aa-d477-a60204fb4812.png)

WordPressの有名な5分間インストールプロセスを実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44791/341a3416-3a44-6ebf-8923-017998146c9b.png)

無事インストール完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44791/81a3b425-9848-85b5-0757-e065a0210ef1.png)

#おわりに

以上により、レンタルサーバからエンハンスドDBに接続する形でWordPressを動作させることができそうであることを確認しました。
php artisan migrate でハマった件

Mamp環境でLaravelの学習用にローカル環境でphp artisan migrate 実行した際、エラーが出てしまいハマったので備忘録として残しておきます。

###発生したエラー①&nbsp;&nbsp;SQLSTATE[HY000] [2002]

コマンドを実行した際、初めに下記のようなエラーが発生しました。

```
Illuminate\Database\QueryException  : SQLSTATE[HY000] [2002] Connection refused 
```

###解決策①
.envファイルの下記の設定を見直すことで解決しました。

* DB_HOST=127.0.0.1をlocalhostへ変更
* DB_PORTの設定を確認する（3306 or 8889）

```.env
DB_HOST=localhost
DB_PORT=8889（自分の環境に合わせる）
```

###発生したエラー②&nbsp;&nbsp;SQLSTATE[HY000]: General error: 1273 Unknown collation

次に発生したのは下記のエラーです。

```
Illuminate\Database\QueryException  : SQLSTATE[HY000]: General error: 1273 Unknown collation: 'utf8'  
```

###解決策②
config/database.phpファイルのcharsetとcollationの設定をデータベースの文字コードに合わせることで解決しました。
私が作成していたデータベースの文字コードはutf８ではなくutf8mb4_unicode_ciで作成していたためこの部分でエラーが発生していました。

```config/database.php
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
```
            
###設定ファイル修正後はキャッシュをクリアする
上記の設定ファイルを修正後、以下のコマンドでキャッシュをクリアし、再度php artisan migrateを実行することで上手くいきました。

```php
php artisan cache:clear
php artisan config:clear 
```

以上です。
JavaScriptとPythonの基礎文法を比較してみた


好きな髪色は銀髪、**プラチナ☆みゆき**である。

さて、今回はフロントエンドとしてJavaScript、バックエンドとしてPythonを学ぶ人用にその基礎文法の違いをまとめてみた。

また、両者はどちらも**動的型付けのスクリプト言語**であるが、JavaScriptの場合はブラウザで動作し、Pythonの場合はターミナルで動作するという点で大きな違いがある。



## 変数宣言・代入

### Python

```python
x = 'hoge'
```

Pythonは変数の宣言と代入に特に区別がなく、変数作成時に宣言と代入を一緒に実行する。
また、変数と定数を内部的に区別せず、変数は小文字、定数は大文字で書くという記法のルールがあるくらいである。

### JavaScript

```javascript
let x;
x = 'hoge';
```

JavaScriptはまず、処理の終端に; を付ける必要がある。省略することも可能だが、付けるのが慣例となっている。
そして、変数宣言時に前にletもしくはvarを付けないとグローバル変数として宣言される。
定数の場合は前にconstを付ける。
また、宣言と代入を同時に実行し
let x = 'hoge';
としてあげることももちろん可能である。

## 制御フロー

### Python

```python
# if文
if x > 60:
    print('good')
elif x > 80:
    print('great')
else:
    print('bad')

# for文
for i in range(3):
    print(i)
```

Pythonは処理のブロックをインデント（字下げ）によって行い、インデントが正しくなければエラーが発生する。

### JavaScript

```javascript
// if文
if (x > 60) {
    cosole.log('good');
} else if (x > 80) {
    console.log('great');
} else {
    console.log('bad');
}

// for文
for (let i=0; i<3; i++) {
    console.log(i);
}
```

JSは処理のブロックを波括弧で表す。**JavaScriptのJavaは、JavaのJavaではない**が、JavaやC++などのサーバサイド言語も波括弧で処理のブロックを規定する。


## 例外処理

### Python

```python
try:
   x / y
except as e:
   print(e)
finally:
   print('done')

```

### JavaScript

```javascript
try {
    x / y;
} catch(e) {
    console.log(e.message);
} finally {
    console.log('done');
}
```
例外を捕捉する時にPythonではexceptだが、JSではcatchになるので注意。


## 配列

### Python

```python
li = [1,2,3]

print(li[1])
# 2
li.append(4)
# li = [1,2,3,4]
li.pop()
# li = [1,2,3]
li.pop(0)
# li = [2,3]
li.insert(0,1)
# li = [1,2,3]

# slice

li[1:3]
# [2,3]

```

### JavaScript

```javascript
let array = [1,2,3];

console.log(array[1]);
// 2
array.push(4);
// array = [1,2,3,4]
array.pop();
// array = [1,2,3]
array.shift();
// array = [2,3]
array.unshift(1);
// array = [1,2,3]

// slice

array.slice(1,3);
// [2,3]

```

細かい違いだが、Pythonでlistのインデックス外の値を指定するとIndexErrorが返ってくるが、JSではインスタンス外の値はundefinedが返ってきてエラーにはならない。


## 関数

### Python

```python
def somefunc():
    print('')
```

### JavaScript

```javascript
function somefunc() {
    cosole.log('');
};
```

## クラス

### Python

```python
class Class:
    def __init__(self, args):
        self.args = args
    def method(self):
        print('')

instance = Class(1)

```

### JavaScript

```javascript
class Class {
    constructor(args) {
        this.args = args;
    }
    method() {
        console.log('');
    };
};

let instance = new Class(1);

```

JSではインスタンスの宣言時にnewが必要なので注意。また、インスタンス引数としてPythonではself, JSではthisを使用するが、Pythonのselfはユーザが明示的に指定する変数でありselfでなくても動作には影響がないのに対して、JSのthisは暗黙的に設定される変数であり予約語なのでユーザが任意に設定することはできない。


## まとめ

JavaScriptは一番人気の言語だけあって、Pythonで書けることはほとんどJavaScriptでも書ける印象であった。
しかし、JavaScriptの方がオブジェクトの操作がデータ型によって書き方がバラバラであったり、少々覚えづらいものが多かったりしたように感じた。
JavaScriptの記法はnode.jsによってサーバサイドでも使われたり、BaaSであるFirebaseを使うにはnode.jsを書けないといけなかったりでサーバサイドでも扱わないわけにはいかないようになってきているので是非マスターしていきたいところである。
JavaScript　様々なメソッド

#pushメソッド

pushメソッドは配列の最後に新しい要素を追加するメソッドです。
メソッド名.push(追加要素);です。

#forEachメソッド

forEachメソッド配列の要素を1つずつ取り出して、全ての要素に繰り返し同じ処理を
行うメソッドです。

配列.forEach((引数) => {処理});
このようにアロー関数が入っています。そして、関数に引数が入っています。

```JavaScript 
const numbers = [1,2,3];
numbers.forEach((number) => {
  console.log(number);
});
```
出力結果 

```JavaScript
1
2
3
```
引数に入っている関数はコールバック関数と言います。

#find

findメソッドとは条件に合う要素を配列から取り出すメソッドです。

``` JavaScript
const numbers = [1,2,3];
const foundNumber = numbers.find((number)=> {
  return number < 3;
});

console.log(foundNumber);
```

#filterメソッド

filterメソッドとは条件に合う要素を取り出して、新しい配列を作るメソッドです。

```JavaScript
const numbers = [1,3,5,7];
const filteredNumbers = numbers.fileter((number) => {
  return number > 3;
});
console.log(number);
```
出力結果はこちらです。

```
[5,7]
```

#mapメソッド

mapメソッドとは配列内の全ての要素に処理を行い、戻り値から
新しい配列を作るメソッドです。

```JavaScript
const numbers = [1,2,3];
const doubledNumbers = numbers.map((number) => {
 return number * 2;
});

console.log(doubledNumbers);
```
出力結果はこちらです。

```
[2,4,6]
```

#最後に

初心者ですので、拙い文章や書き方だと思いますが、最後まで見て頂き
ありがとうございました。もし、ご指摘等がございましたらよろしくお願い致します。
バッチを利用して当日の日付けファイルを作成する方法(.bat)

バッチファイルを利用して当日の日付けファイルを作成する方法を解説します。

#作成の背景
普段の業務で引継ぎをする機会が多いのですが、毎回引継ぎ用のメモ帳を日付けごとに保存するのがとても面倒に感じた為、バッチファイルで自動化しようと考えました。

#手順
１、下記コマンドを任意のテキストファイルにコピペする。

```
REM/* YYMMDD形式で日付を取得 */
set TODAY=%DATE:~0,4%%DATE:~5,2%%DATE:~8,2%

copy nul 日付ファイル作成%TODAY%.txt
```

２、ファイル名の末尾に「.bat」指定してバッチファイルとして保存する。
![バッチ１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/211b44c2-d7d0-dae5-a61c-22a5191835d8.png)

#動作確認

１、作成したバッチファイルをダブルクリックしてバッチを実行する。
![バッチ２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/df05722d-2593-1636-7b29-e1c182a5f4e8.png)

２、当日日付のファイル名のテキストファイルが作成されたこと確認。
![バッチ３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/bff5ee9d-31d7-8624-95e4-4fe8a1a60172.png)

#終わりに
今回は日付ファイルを業務で毎回作成するのが面倒だったので、工数を削減する為に作成しました。
また、面倒な作業の自動化を実現することが出来たらQiitaに投稿します♪
アプリケーションテストをUiPath Action Centerで人と協働する #2

# はじめに

みなさん、こんにちわ！

この記事はUiPathブログ発信チャレンジ2021サマーの18日目です。
UiPath Test Suiteによるアプリケーションテスト自動化において、UiPath Platform のシナジー効果を活かした活用法を、いくつかの構成でご紹介します。本記事はUiPath Action Centerを利用し、人と協働してテストを行うステップです。

:::note warn
2021年4月時点のコミュニティ向けAutomation Cloud及びUiPath Studio Pro Community Edition v21.4を利用しています。今後、UiPath Test Suiteは、Action Centerと連携する予定ですが、先んじて独自のアイデアで連携したものです。将来は、もっと画期的な連携になっていることでしょう。
:::

#前提

スクリーンショットによる画面の比較テストを想定しています。
比較する元の画像を作成するのが非常に手間なので、自分では作成せず、初回テスト実行すると、検証の代わりにスクリーンショットを取得して画像を保存する様にしています。
そうすることによって、次のテスト実行では、この画像と比較して同じかどうかで回帰テストができると言うことです。
この仕組みをテンプレート化したものが下記の記事に掲載しています。

https://qiita.com/Jun96427231/items/6dc41df8be321825db94


#Action Centerと連携して見る

ただ、初回テスト実行では取得保存された画像が正しいか確認する必要がありますよね。
もし、初回テスト実行の際に既に画面に不具合があったら、回帰テストで不具合のある画面のままOKとされてしまいます。
そこで初回のテスト実行時はテストコード実行途中でAction Centerに取得した画面の画像を投げて人が確認する仕組みを構築します。
Action Centerで画面を確認し、OKなら、期待画像（比較する元画像）として格納します。
ここまで読んで何か気づいたことはないでしょうか。
そう、初回テスト実行時は、人と協働してテストをしているんですよね。
なので、１回目のテストは、これで実施完了と言うことです。
更に、ここで、Action Centerを使うメリットが、もう１つ出てきます。
Action CenterでOK、NGを判定した結果を、後続処理で記録できると言った点です。
下図は、ここまで解説した流れを図にしたものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/9475150d-e8e0-179d-a5b9-d0a58bcc48e4.png)

Action Centerを利用すると、画像を確認して、ボタン一つでクイックに判定して行けるので、とっても便利ですね！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/b1dc1724-3ed6-0888-bf97-854e2d270265.png)

この仕組みはデータドリブン型のテストで、より効果を発揮しそうです。
順次実行型のテストの場合は、もっとシンプルです。手順書通りに手動テストを実施する感覚で、レコーディングしながらサクサク作成して、検証部分を後で差し込んで作成して行けます。不具合は、この間でを見つけているので、この時点で１回目のテストになっているとも言えますね。しかも、テストは自動化されているので、いつでも何回でも工数を掛けずに再テストが出来ます。

UiPath Community 2021.6 Previewの新しい機能でレコーディングするとオブジェクトリポジトリにも要素が自動登録されます。これによって、高い生産性に加えて、変化しやすい要素のメンテナンス性向上が両立できそうです。
RPA開発で便利な機能は、そのままテスト自動化でも便利ですね！一般のテストツールと異なり、RPAのイノベーションが、そのままテスト自動化のイノベーションに直結して行くので、どんどん便利になって行きます！

:::note info
この内容は2021年6月15日 - 7月16日の間で開催された「UiPath Developer Conference 2021」の「UiPath Test Suite がよくわかる！テスト10選」のセッションでも、本デモを交えて解説させて頂きました。
:::

#終わりに
UiPath Test Suiteでテスト自動化を進められる方は、UiPath Platformの製品も広く理解して置くと、効率的な活用方法が実現できたりします。UiPath Studio Proでの開発手法も熟知していれば、安定動作するテストコードが作成できる、メンテナンス性や生産性も高めることもできる、Activityを幅広く知っていれば、それだけ色々な独自機能も付加できます。一般のテストツールと異なり、ツールの機能提供を待つ必要がない！
UiPat Test Suiteで、あなたの最適なテスト自動化の環境を構築して見ませんか。

UiPath Test Suiteによるアプリケーションテスト自動化については、下記コラムもご参考に！

https://www.fsi.co.jp/blog/5942/

https://www.fsi.co.jp/blog/5963/
JavaParserでメソッド定義を出力する


この記事ではIntelliJ IDEA 2021.1.3 (Community Edition) Runtime version: 11.0.11+9-b1341.60 amd64を使っています。


ディレクトリ以下のjavaファイルをParseします。

javaparserを使用するには、build.gradleのdependenciesに追加します。

```gradle:build.gradle
dependencies {
    implementation 'com.github.javaparser:javaparser-core:3.3.0'
}
```

## コード

```java:Main.java
import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Main {
    public static void main(String[] args) {
        Path path;
        if (args.length == 0) {
//            path = Paths.get("");
            path = Paths.get("src/main/java/");
        } else {
            path = Paths.get(args[0]);
        }

        try {
            parsePath(path);
        } catch (IOException e) {
            System.out.println("file not found!");
        }
    }

    static void parsePath(Path path) throws IOException {
        if (Files.isDirectory(path)) {
            Files.list(path).forEach(p -> {
                try {
                    parsePath(p);
                } catch (IOException e) {
                    // nop
                }
            });
        } else {
            parse(path);
        }
    }

    static void parse(Path path) throws IOException {
        CompilationUnit cu = JavaParser.parse(path);
        new MethodVisitor().visit(cu, null);
    }
}
```


```java:MethodVisitor.java
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;

class MethodVisitor extends VoidVisitorAdapter<Object> {
    /* Class name or interface name */
    @Override
    public void visit(final ClassOrInterfaceDeclaration n, final Object arg) {
        System.out.println(n.getName());
        super.visit(n, arg);
    }

    /* Method Declaration */
    @Override
    public void visit(final MethodDeclaration n, final Object arg) {
        System.out.println("  " + n.getDeclarationAsString());
        super.visit(n, arg);
    }

    /* Constructor declaration */
    @Override
    public void visit(final ConstructorDeclaration n, final Object arg) {
        System.out.println("  " + n.getDeclarationAsString());
        super.visit(n, arg);
    }
}
```

```console:出力結果
Main
  public static void main(String[] args)
  static void parsePath(Path path) throws IOException
  static void parse(Path path) throws IOException
MethodVisitor
  public void visit(final ClassOrInterfaceDeclaration n, final Object arg)
  public void visit(final MethodDeclaration n, final Object arg)
  public void visit(final ConstructorDeclaration n, final Object arg)
```


##参考サイト
https://qiita.com/opengl-8080/items/50ddee7d635c7baee0ab

http://blog.64p.org/entry/2015/05/21/075549
[Python] 2部グラフ ABC210C

#[ABC210C](https://atcoder.jp/contests/abc210/tasks/abc210_c)
問題文通りの全探索を実装すると、計算量は$O(K(N-K+1))$でありTLE。
連想配列を用いたしゃくとり法をすれば、$O(N\log N)$


```python:サンプルコード
from collections import Counter

N, K = map(int, input().split())
C = list(map(int, input().split()))
counter = Counter(C[:K])  # 最初のK個の連想配列
ans = len(counter)  # 最初のK個の種類数
for i in range(K, N):
    left = C[i - K]  #  1回目が K - K = 0（一番左）になるようにします
    right = C[i]
    counter[left] -= 1
    counter[right] += 1
    if counter[left] == 0:
        del counter[left]  # 0個でもlenで数えられてしまうので、delで消します
    ans = max(ans, len(counter))  #  現在の種類数で答えを更新します
print(ans)
```

時間は掛ったが、しゃくとり法や連想配列という意識なく、模範解答通りのアルゴリズムには辿り着いた。しかし試験時間の制約でデバッグ出来ずにTLEで終わった。
結構精神的ダメージを負ったが、その分、頭に刻み込まれたと思う。
select * from mysql.userを実行するとMysqlコンソールが文字化けたときのお話

# はじめに
激しい文字化けがおきたので対処法をメモ。
何気なくMySQLユーザ一覧を出そうとしたところ最初は調子よかったけど、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/5f3297c6-cdef-3080-5f50-b4a03bcc09d0.png)
rootユーザの内容を表示していてauthentication_stringのあたりから文字化けが起きた。。。
![image.png](https//qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/56780c27-72c5-c8aa-2202-dbf89192799a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/65a06852-35ad-dd24-59a2-44edcd5d9fb9.png)


# MySQLでこれが起きるとTeratermを落とすしかないそうです。。。

https://yoneyore.hatenablog.com/entry/2020/04/08/210114

によると、シェルプロンプト上であればなんとかなるけど、MySQLコンソール上ではどうにもならず
Teratermをいったん落としてログインしなおせばOKだそうです。。。

# 色々さがしたけど決定的な情報は見つからなかった…
　authentication_stringを出さなければよさそうなんで、
　ここはひとつ、

```
  select Host, user from mysql.user
```

  でいいような気がしてきた。残念だけどこれで終わりにしておこう。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/e2ab448b-c2a6-aa33-b95b-e4add031ec14.png)

～おしまい～
ReduxとRedux toolkitについて

## はじめに
Reactでアプリを作成する際、状態を管理する方法は
いくつかあると思います。
Context APIや、Recoilなど、便利なものが数多くある中で、
今でももっとも使用率が高いのがReduxだと思います。

今回はRedux、またRedux toolkitについてまとめてみようと思います。

## Reduxとは
Reduxとは状態（state)を管理するためのライブラリーです。
状態管理をFluxの概念で行なっており、Reactとの相性がいいです。

管理する方法として、Reduxには主に4つの要素があります
- Action
- Action Creator
- Store
- Reducer

## Action, Action Creator
値を新しく作りたい、値を更新したい！などのイベントを発生させたい時、
そのイベントで「何をしたいのか」をReduxに伝えなければなりません。
それがActionです。
ActionのオブジェクトはAction Creatorメソッドに値が渡されて生成されます。
Actionは何をしたいのかという情報がないといけないので、
必ず「type」プロパティを持つ必要があります。


## Store
Storeは状態（State）を管理する倉庫のようなものです。
Actionを無事作成できたら、その情報はStoreに渡されます。
そしてstateを更新するためのdispatch(action)を提供してくれます。

## Reducer
さきほどStoreで提供されたdispatchを受け取り、新しいStateを作成
してくれます。
これがReduxによる状態管理の一連の流れです。

## Redux toolkit
正直に言うと今の説明だけではReduxを使うのは結構大変です。
ですがその悩みをある程度解決し、簡単にReduxを使えるようにしたのが
Redux toolkitです。
Redux toolkitはまずAction　Creatorを書く必要がなくなります。
またActionとReducerを同じオブジェクト内に書くことができるので
見やすさも向上します。
また、個人的に一番嬉しいのが、Stateの不変性を意識しなくても良い点です。
Reduxのreducerは同じ引数を渡されたら必ず同じ結果を返す関数（純粋関数）となるように書かなくてはいけません。
しかしtoolkitではこの点を意識しなくても大丈夫です。
またTypeScriptの型制御を効かせながらコードを書くことが
できるので、TypeScriptとの相性もいいです。
私の中でReduxを使うならtoolkitを使わないのは
もったいない！という考えになってますw

## 最後に
Reduxは大規模なアプリになる程重宝しますがそもそも
入門するのが大変でした。
今ではtoolkitのおかげでその敷居は低くなって、
とても使いやすくなったように感じます。
--template redux-typescriptで簡単に導入もできます。
これからもReduxバリバリ使っていこうと思います！

## 参考
[Redux 入門](https://qiita.com/soarflat/items/bd319695d156654bbe86)
[Redux toolkit](https://qiita.com/NeGI1009/items/d553bdb361e755d5986c)
重いクエリを投げるとDockerのDBコンテナが落ちる

ローカルに構築しているDBコンテナ（MySQL）が重いクエリを投げると、落ちてしまうので原因を調査しました。
似た事象で困っている方の助けになれば嬉しいです。

# 事象
約160万件ほどのレコードが入ったテーブルで、PRIMARY KEYを変えたり、パーティション切ろうとすると、途中で失敗してしまう。
エラーは下記。

```
Communications link failure
```

ちなみに、wait_timeoutの設定は28800とかで、そんな時間はかかっていません。

# 原因
メモリ不足でコンテナが落ちたため。
コンテナが落ちたので、MySQLに接続できず、コネクションエラーが起きたという感じです。

# 解決策
DockerDesktopForMacを使っていたので、管理画面でメモリの割り当て量を2GB→4GBにして解決しました。![unnamed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275351/9da833c7-f6ee-a427-3a03-54133ef23399.png)



# 調査
```
docker logs -f {コンテナ名}
```

DBコンテナのMySQLのログを見ると、特に何も書いておらず、最初はコンテナが落ちたのかすらわからなかったです。
ただ、コンテナに入った状態で、上のエラーが起こると、追い出されていたので、コンテナ側で異常が起きたことはわかっていました。

異常があるとすればリソース周りかなと思い、

```
docker stats {コンテナ名}
```

でコンテナのCPU使用率やメモリ使用量を確認したところ、クエリを実行すると、メモリ使用量が上がり、限界値まではいかないものの、6、7割のところで、コンテナが落ちることがわかりました。
![unnamed (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275351/c321974e-ae75-73e0-1ec5-aad366f4c67a.png)

最初この6、7割の数値に騙されて、メモリ不足でもないかと思っていましたが、
これは実は他のコンテナも動いているため、実質1コンテナが使えるメモリが限界値の数値でないだけです。
（この仕様、前も似たような事象が起きて知っていたのですが、ド忘れしてました。）

メモリ不足だと気づき、Dockerのメモリの限界値を上げるため、
[docker-composeのresourcesオプション](https://docs.docker.com/compose/compose-file/compose-file-v3/#resources)の設定しました。
が、なぜか反映されない。

ここで、MacでDocker使っていることに気づき、DockerDesktopForMacの管理画面で、メモリ割り当て量の設定値があり、そちらを変えたら、反映されました。

なお、

```
docker stats -a
```

とすると全コンテナのリソースが確認ができるので、リソース系はこっちで見た方がよさそうです。
2.14(標準) 変数変換5

## 方針

変数変換はまず分布関数から考える．分布関数ができたらそれを微分することで確率密度関数を求める．

## 答案

Yの分布関数は

```math
\begin{align}
F_Y(y)&= P[Y\leq y]\\
&= P[X^2\leq y]\\
&= P[-\sqrt{y}\leq X\leq\sqrt{y}]\\
&= \int_{-1}^{\sqrt{y}}\frac{1+x}{2}dx-\int_{-1}^{-\sqrt{y}}\frac{1+x}{2}dx\\
&= \left[\frac{x}{2}+x^2\right]_{-1}^{\sqrt{y}}-\left[\frac{x}{2}+x^2\right]_{-1}^{–\sqrt{y}}\\
&= \sqrt{y}\ \ \ (0<y<1)
\end{align}
```

なので，確率密度関数は，

```math
f_Y(y)=\frac{1}{2\sqrt{y}}
```

平均，分散は

```math
\begin{align}
\mathbb{E}_{Y\sim f_Y}[Y]&= \int_0^1\frac{y}{2\sqrt{y}}dy\\
&= \left[\frac{1}{2}\frac{2}{3}y^{3/2}\right]_0^1\\
&= \frac{1}{3}\\
\mathbb{E}_{Y\sim f_Y}[Y^2]&= \int_0^1\frac{y^2}{2\sqrt{y}}dy\\
&= \left[\frac{1}{2}\frac{2}{5}y^{5/2}\right]_0^1\\
Var(Y)&= \frac{1}{5}-\frac{1}{9}=\frac{4}{45}
\end{align}
```

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
L1ノルムは◇、L2ノルムは○、L3ノルムは...？の調査過程と備忘録

# L1は◇、L2は○
機械学習の書籍などでリッジ回帰やラッソ回帰のページを開くとでてくるこの図。
見たことある人も多いだろう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1447216/1f9199ca-65ae-8c5c-7159-0209968d6198.png)

正則化項にL2ノルムを使うのがリッジ回帰、L1ノルムを使うのがラッソ回帰。
過学習を防いだり変数選択ができたりするあれだ。

# じゃあL3は...?
詳しい人からしたら「そんなの当たり前だよ」と言われそうだが、
私と同じように機械学習から入った人間からしたらL1、L2しか聞いたことがない、
という人もいるかもしれない（いなかったらごめん）。

L3がそもそもあるのか、あったらどんな形なのか、それを調査したのが本記事である。

# 一般化するとLpノルムだった
もう結論なのだが、一般化するとLpノルムと呼ぶらしい。
つまりp=3の場合がL3ノルムとなる。

Lpノルムの式はこちら。

$ \sqrt[p]{\sum_{i=1}^{n}|x_i|^p}$


L3ノルムを探して真っ先にたどりついた記事がこれ。
[【機械学習】LPノルムってなんだっけ？](https://qiita.com/kenmatsu4/items/cecb466437da33df2870)
pの値をいろいろ変えて描画していて、なにより美しい。

[Githubに描画のコードも置いてくださっていた](https://github.com/matsuken92/Qiita_Contents/blob/master/General/LP-Norm.ipynb)ので、
こちらを利用して描いたL3ノルムの形がこちら。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1447216/6085acb5-c03c-d0c9-4cd8-52293dc4dc15.png)
なるほど、角が丸い四角という感じか...!
そしてp=∞のときに完全な正方形になるらしい。

距離について可視化している記事はほかにもありました。
[ミンコフスキー距離を絵にしてみた](https://qiita.com/scivola/items/ee37b686d0b36d6e9b39)
[位相空間論 - 距離空間(1) - 距離関数の可視化](https://qiita.com/syuuu/items/cc7393b5606316b3cbb7)


# Lpノルムの距離
L3ノルムを調べていて学んだことがもうひとつある。
それはL1ノルムの形状はマンハッタン距離であるということ。
碁盤目状に進むやつね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1447216/08abc74b-b6d5-184d-475f-d36f0f409096.png)
式を見ると確かにそうじゃん！となって少し理解した気になった。

ちなみに
L2ノルムの形状はユークリッド距離
L∞ノルムの形状はチェビチェフ距離ですね。

距離については以下の記事を参考にした。
[【JDLA E資格】Lpノルム・距離関数](https://qiita.com/fridericusgauss/items/f3d8575abfe7f67f1d7d)
[このデータセットにはどの距離を用いればよいの？？～ユークリッド距離・マンハッタン距離・チェビシェフ距離・マハラノビス距離～](https://datachemeng.com/use_of_distance/)
光ファイバーケーブル とは

## 勉強前イメージ

家まで回線を引っ張ってくれる。
中身がガラスとかだった気がする

## 調査

### 光ファイバーケーブルとは

英語では `Optical fiber cable` と呼ばれています。
ガラスやプラスチックを使った繊維状の光ケーブルを束ねて屋外でも使えるようにしたのが光ファイバケーブルで、光を利用した通信になります。
電気信号ではなく、レーザやLEDの光によって通信します。

### 光ファイバーケーブルの種類

光の伝搬モードの数で以下2つのモードがあります。

- シングルモード
- マルチモード

また、それぞれ以下の種類があります。
コアの屈折率分布等によって分けられますが、
一般的に使用されているのは `グレーデッドインデックス` と `汎用シングルモード` になります。

- シングルモード
	- 汎用シングルモード
	- 分散シフト・シングルモード
	- 比零分散シフト・シングルモード
- マルチモード
	- ステップインデックス
	- グレーデッドインデックス

### 光ファイバーの特徴

- 損失が少ない

同軸ケーブルなどと比べて損実が少ないです。

- 伝送できる周波数の帯域が広い

光ファイバーの種類にもよりますが、高い周波数の信号を送ることが出来ます。

- ケーブルが細く、軽い

他の伝送媒体に比べて細く軽いです。
同軸ケーブルの30分の1程度になります。

- 電磁誘導がない

ガラスなどは電気を通さないので電磁誘導がありません
※電磁誘導とは磁界の変化によって電流が流れる現象

## 勉強後イメージ

プラスチックの光ファイバケーブルもあるのか・・・
光回線のケーブル引き込み工事に来てもらったときに、
ケーブル折れるから気をつけてねって言われた覚えがある・・・

## 参考

- [光ケーブル（光ファイバーケーブル）とは](https://www.doujiku-hikari.com/optical/info/)
- [光の基礎知識](https://www.optigate.jp/basic/cable.html)
- [図解でわかる光ファイバーとは｜初心者が2021年に絶対知るべき全知識！](https://tsunaga-ru.net/optical-fiber-55483)