OmniAICreator/Qiita-1.07M huggingface dataset:
[Laravel]バリデーション前に値を整える

```AddressRequest.php
    public function rules()
    {
        return [
          'street' => ['required', 'string'],
          'number' => ['required', 'string'],
          'city' => ['required', 'string'],
          'postal_code' => ['required', 'string'],
          'country' => ['required', 'string'],
        ];
    }
```

```AddressController.php
public function store(AddressRequest $request)
{
    Address::create([
      'street_name' => $request->street,
      'house_number' => $request->number,
      'postal_code' => $request->postal_code,
      'city' => $request->city,
      'country_id' => $request->country
    ])
}
```

上記のようなコードがあるとします。

これだと、コントローラー内で一つずつ値を整える必要があるので、冗長になってしまいます。
これを回避するために、formRequestクラス内で入力値を整えましょう。

`prepareForValidation()`を使用することで、バリデーション実行前にリクエストに任意の処理を加えることができます。

https://readouble.com/laravel/6.x/ja/validation.html

```AddressRequest.php
    public function rules()
    {
        return [
          // 整形後の名前に変える
          'street_name' => ['required', 'string'],
          'phone_number' => ['required', 'string'],
          'city' => ['required', 'string'],
          'postal_code' => ['required', 'string'],
          'country_id' => ['required', 'string'],
        ];
    }

    // バリデーション前に実行される
    public function prepareForValidation()
    {
        $this->merge([
          'street_name' => $this->street,
          'house_number' => $this->number,
          'country_id' => $this->country,
        ]);
    }
```

こうすることで、コントローラー内で値を整える必要がなくなり、
一行で記述することができます。

```AddressController.php
public function store(AddressRequest $request)
{
    Address::create($request->validated())
}
```
メモリ不足でmysqldが起動しなくなったが、原因特定に苦労した話

# この記事の概要
* 個人のWebサービスで使用している mysqld が、起動・停止を繰り返すようになったよ
* 原因の特定に苦労したよ
* 振り返れば単純なことだけど、知らない自分には気付きにくいことだったので記事にするよ

# 事象の概要
* Webサービスが 500 エラーを返すようになっていた
* DB（MySQL）に原因があることはすぐに特定できた
* 原因を示すログがすぐに見つからなかったので、特定に苦労した
* mysqld ではなく kernel のログを確認したら解決した

# 環境
* CentOS 7
* mysql Ver 14.14

# 詳しい経緯

ある日、個人開発で運営しているWebサービスが、500エラーで動かなくなっていることに気付きました。
同じサーバで動かしている他のサービスは影響がなかったので、DB（MySQL）関係だとは容易に想像が付きました。
実際、```systemctl```で確認したところ```status:start-pre```となっていたので、mysqld が正常に起動していないことが分かりました。

「ほんなら、mysqld をリスタートすれば解決だなー」と思ったのですが、そう上手くはいきませんでした…。
終了・起動をして、再度ステータスを確認するも、またもや```status:start-pre```の表示。
起動しない原因がなにかありそうです。

「ならば、MySQL のエラーログを確認しよう」ということで、my.cnf に書いてあるエラーログを見ることに。
しかし、今回のログは特に吐き出されていなさそうです。

他にログの確認方法が無いかを調べます。
すると、```journalctl```というコマンドがあることを知りました。
というわけで、mysqld のログを確認するために```journalctl -u mysqld```を実行。

```
 2月 03 18:12:59 public-server systemd[1]: Starting MySQL Server...
 2月 03 18:13:58 public-server systemd[1]: mysqld.service: control process exited, code=exited status=1
 2月 03 18:13:58 public-server systemd[1]: Failed to start MySQL Server.
 2月 03 18:13:59 public-server systemd[1]: Unit mysqld.service entered failed state.
 2月 03 18:13:59 public-server systemd[1]: mysqld.service failed.
 2月 03 18:14:00 public-server systemd[1]: mysqld.service holdoff time over, scheduling restart.
 2月 03 18:14:00 public-server systemd[1]: Stopped MySQL Server.
```

エラーに関しては、「code=exited status=1」というログのみ。
これで検索しても今回の問題とは関係なさそうな原因しか見当たりません。
うーん、かなり困りました。

しばらくあれやこれやと試したのですが、問題解決に至らず。
打つ手がなくなったので、```journalctl```をフィルタリング無しで実行してみることに。
すると、次のようなエラーが出てきました。

```
 2月 03 18:46:17 public-server kernel: Out of memory: Kill process 25450 (mysqld) score 81 or sacrifice child
```
ほうほう、メモリ不足とな。```top```で使用率を確認したところ、確かに不足していそうです。
そこで、不要なプロセスをキル。その後、mysqld を再起動すると、見事起動しました！

起動しないのは mysqld だけど、起動させなくしているのは **kernel** でした。
原因が mysqld にあると思いこんでいたばっかりに苦労してしまったというわけでした。

# 学んだこと
* journalctl という、システムログを確認するコマンドがある
* 思い込みによってログを見逃してしまう事がある。全体ログを見ることも重要
RasberryPIにxrdpで繋がらない？ログインできない？

記事に書いた通りなのですがRaspberry Pi4にxrdpを入れてRDP接続したいです。それが何でか上手く行かずググったら対処法があったのでそれを記載します。
## 問題点
xrdpのログイン画面が表示されアカウント情報を入れてもずっとブランクスクリーンのままです。それでも辛抱強く待っていると以下のようなエラーが出ます。
![ooo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537256/0160c160-57d5-7cf0-baaf-af6f661a0254.jpeg)

## 解決策
こちら[^1]に書かれている事をやったら治りました。
以下のよにデバイスが指定されている部分を消せば良いらしいです。

```/etc/X11/xrdp/xorg.conf
#Option "DRMDevice" "/dev/dri/renderD128"
Option "DRMDevice" ""
```

これでちゃんとログインしデスクトップが表示されました。
![hhh.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537256/92b35bb9-c488-d063-d73e-6fb374ef7583.jpeg)

## 検索用
xrdp rdp リモートデスクトップ Rasberry Pi4
connecting to sesman ip 127.0.0.1 port 3350
sesman connect ok

[^1]: [My raspberry pi 4B can't use xrdp connection #2060](https://github.com/neutrinolabs/xrdp/issues/2060)
【Linuxサーバ不要】自宅のWindows PCとWireguardで直接VPN張る方法

Wireguradを使って、自宅PCへリモートディスクトップで接続する環境を構築しました。

# こだわった点

自宅にLinuxサーバ（Raspiなど）を置きたくない。
自宅PCにWireguardをインストールして直接接続したい。

ネット上のWireguard のサーバ側の説明はLinuxの場合が多いのですが、Windows Clientでも同じなんじゃない？
とおもって設定してみたところ、うまくいきました。

# 接続図

自宅PC(Windows) --- Router --- Internet --- スマホ --- NotePC(Windows)


#設定方法

- WireguardはWindows版を、自宅PC,NotePCそれぞれにインストール。Windows版のWireguardの使い方は省略。
- 自宅PCはIPアドレスが変動しないようにする（固定IPにするなど）
- Routerにはポートマッピング設定をして外部からのUDP 51820ポートを自宅PCのIPに転送する
- DDNSを設定して、自宅のグロバルIPのFQDNを確保する
- Note PC側には、`PersistentKeepalive = 30`の設定を入れる。


NotePCで、10.0.0.1にリモートディスクトップ接続できました。


鍵の生成は、次のコマンドで実行しました。Linux版と同様にできます。保存先のフォルダーは適当に変えてください。

```
PS C:\Program Files\WireGuard> .\wg.exe genkey > c:\tmp\wgclient.key
PS C:\Program Files\WireGuard> cat C:\tmp\wgclient.key| .\wg.exe pubkey > C:\tmp\wgclient.pub
PS C:\Program Files\WireGuard> .\wg.exe genkey > c:\tmp\wgserver.key
PS C:\Program Files\WireGuard> cat C:\tmp\wgserver.key| .\wg.exe pubkey > C:\tmp\wgserver.pub
```

```wgserver.conf
[Interface]

PrivateKey = [wgserver.keyの内容]
ListenPort = 51820
Address = 10.0.0.1/32

[Peer]
PublicKey = [wgclient.pubの内容]
AllowedIPs = 10.0.0.2/32
```


```wgclient.conf
[Interface]
PrivateKey = [wgclient.keyの内容]
Address = 10.0.0.2/32
[Peer]
PublicKey = [wgserver.pubの内容]
AllowedIPs = 10.0.0.1/32
Endpoint = xxxxxxx.ddns.net:51820
PersistentKeepalive = 30
```

# 注意点

ping 10.0.0.1の応答はありませんでした。多分、WindowsのFirewallによるブロックではないかと思いますが、追及していません。
ping応答がなくてしばらく悩みました。
UnityのSceanGizmo（右上のアレ）をゲーム画面に追加する

Unityの右上のアレをゲーム内に追加する方法をメモしておきます
##SceanGizmoとは
Unityの右上のアレは**ScaneGizmo**といいます
![ScaneGizmo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522595/33982327-7e65-05c9-d17b-7359ccea072e.png)
カメラの向きを変えたりするのに使います

##追加方法
###Assetの追加
ここでAssetをMyAsettsにダウンロードします

https://assetstore.unity.com/packages/tools/gui/runtime-scene-gizmo-123040?locale=ja-JP

UnityのWindow>PackageManagerを開いてMyAssetsからRunTimeSceanGizmoをダウンロード，インポートします
![PackageManager2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522595/6b94df48-e131-d657-3832-627936d61947.png)

![PackageManager1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522595/1780ca49-f54d-9fc2-76a8-c9855a1dad5d.png)

:::note info
この画面はインポート済みの画面です
:::
###Canvasの追加
SceanにCanvasを追加します
![CreateCanvas.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522595/45c1d932-70e8-0adf-b38d-a8b246cfabba.png)

ここではCanvasの名前をCanvasGizmoにしています
###GizmoRendererの追加
Projectタブの`Assets > Plugins > RunTimeSceanGizmo > Prefabs`の中のGizmoRendererをCanvasGizmoに追加します
![Project.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522595/0e2e9ea9-d03d-9e34-b223-ae7f2378d554.png)
![CanvasGizmo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522595/52631930-87b4-9af4-bfb9-7de612b6cd2a.png)

CanvasGizmoのRenderModeはScreenSpace-Overlayにしておく必要があります![inspector.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522595/1d12faf9-7ca3-96ef-cc68-5538b4d591e9.png)

なぜGizmo専用のCanvasを作っておくかというと,UIでScreenSpace-Cameraを使いたいときに便利だからです

###CameraParentの追加
次にscriptの仕様上，メインカメラを子オブジェクトにする必要があるのでCreateEmptyでのCameraParentを作り,メインカメラをCameraParentの子オブジェクトにします
![カメラオブジェクト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522595/e637d11e-2c38-71f7-3e5c-69fe7015b022.png)
CameraParentにProjectタブの`Assets > Plugins > RunTimeSceanGizmo > Demo`内にあるCameraGizmoLisnerとCameraMovementをアタッチします

![cameraParent.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522595/27a59ef1-0f9b-cfcc-b9db-fde67b8b7aa4.png)

###GizmoRendererの設定
最後にCanvasGizmo内のGizmoRendererのOnCompornentClikedを画像のように設定します

![GizmoRenderer2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522595/21e0a50e-bcb0-962b-a3a6-ab570629c86f.png)

###完成
完成すると以下のように動きます
![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522595/73b31d60-46a9-f650-9cf9-b26a9242a6ab.gif)

:::note info
これはDemoの映像です
:::
PHP基礎 ~連想配列編~


## はじめに
この記事はフロントエンドエンジニアがバックエンド言語を勉強しようとアウトプット目的で書いている記事になります。
自分用のメモとして書いていきます。

## 配列
```php
$array = ['りんご','みかん','バナナ'];
echo $array[1]; // みかん
```
JavaScriptとあまり変わらないですね。
「$」がつくとテンプレートリテラルっぽいですね。

## 連想配列
```php
$company = [
  '開発部' => [
    '佐藤さん', '鈴木さん', '田中さん'
  ],
  '総務部' => [
    '青木さん', '高田さん', '小林さん'
  ]
];

echo $company['開発部'][1]; // 鈴木さん
```

ふむふむ、オブジェクトのキーとバリューは「=>」で表現するのね。
なんだかアロー関数みたいだ。

### もっと高階層にしてみる
```php
$company = [
  '開発部' => [
    '佐藤さん' => [
      '身長' => 170,
      '体重' => 67,
    ],
    '鈴木さん' => [
      '身長' => 187,
      '体重' => 75,
    ],
    '田中さん' => [
      '身長' => 167,
      '体重' => 60,
    ],
  ],
  '総務部' => [
    '青木さん' => [
      '身長' => 188,
      '体重' => 75,
    ],
    '高田さん' => [
      '身長' => 168,
      '体重' => 95,
    ],
    '小林さん' => [
      '身長' => 175,
      '体重' => 79,
    ],
  ]
];
echo $company['開発部']['鈴木さん']['身長']; // 187
var_dump($company['開発部']['鈴木さん']['身長']); // int(187)
```
ここまで階層が深いと取得するのも大変ですね。。。
var_dumpメソッドを使えば型の情報が取得できます。

## 参考文献
Udemyの講座を購入して学習しています。
PHPの基礎からLaravelまで学習できるようなので、いいですね！
https://www.udemy.com/course/phpbeginnertolaravel/
未経験からフロントエンドエンジニア（受託）になれたフローを解説します

# スペック
アラサー、ギリ第二新卒枠
前職は公務員
ポートフォリオは三つほど作成
使用言語 Vue.js
ホスティングなどはFirebaseを利用
プログラミングを勉強し始めたのは１年前くらい

# 転職活動成績
結論から話すと年収500万以上の受託企業にフロントエンドエンジニアとして内定をいただきました。
応募を出したのは20~30社程度
一次面接までいったところは5社程度
二次面接まで行ったところが3社
内定が２社でした。

転職期間は１ヶ月程度

# 使用したサイトなど
利用したサイトは
・リクルートの転職エージェント
・Wantedly
・Paiza

WantedlyとPaizaはかなり一次面接までやってくれました。体感5割程度。
基本的に気になる企業には片っ端から気になるやお話聞きたいを押しておき、企業からレスポンスがあれば一次面接を行うという流れでした。

PaizaはBランク程度あればかなりの企業にエントリーできるので、Bあれば大丈夫だと思います。Bランクの問題を一問でも解いていればBランクに上がれるので諦めずにやっていれば解ける問題は一つはあります。

結果、内定をいただけたのはPaiza経由だったのでPaizaでBランク以上を取る→気になる企業にいいねを送るということがかなり良いと感じます。
WantedlyでもPaizaでも募集要項に「開発経験一年以上」「実務経験１年」などの記載があっても意外と面接してくれるので、バンバン募集することをお勧めします。

転職エージェントは履歴書や職務経歴書の添削などを行ってくれるため、転職活動が初めてだった私はかなり助けれられました。しかし、募集している求人は希望の条件がほとんどなかったです。（SESがほとんど、自社開発系企業はかなり少なく、また書類選考で落とされる確率がかなり高かったです。体感９割落ちた）


# 勉強したこと
Vue.js、Firebase

ポートフォリオについて詳しく聞かれたのは１社のみでした。
ポートフォリオに関してはかなり考えてユーザーファーストで作ったものが３つほどあったのであんまり開発した際の内容など聞かれなかったのはちょっと悲しかったです。

### 作ったポートフォリオ
・エンジニア自己紹介カード
https://it-intro-67781.web.app/

・スマブラ確定コンボツール
https://smash-62fe6.web.app

・お話作成アプリ
https://relay-composition.web.app/

一応見てはくれていると思いますが、「なぜこれを作ったのか？」という質問をしてくれる企業は１社のみでした。

# 求人の選び方
受託か自社開発に絞って受けました。
年収には特にこだわりがなく350万以上を希望していたが、結果的に企業側から提示された金額が想像より多かったです。
これは単純に運が良かっただけだと思います。

受託か自社開発に絞っている理由は、SESだと自分が学びたい技術が学べない可能性があるから。
目標は自分でWebアプリが作れるフロントエンドエンジニアになること（フルスタック寄り）

そのため、SESで運任せに派遣され、最悪Excel職人になる可能性がある企業はいったん避けて受け、どうしても内定が取れない場合のみSES企業を受けようと考えていました。

結果的にこの考え方が、面接で「なぜこの会社にはいりたいのですか？」という質問に明確に答えられたので良かったと感じます。

# 面接で聞かれたこと

### 前職を辞めた理由
私の場合は病気で退職したのであまり深くは聞かれませんでした。
マイナスは理由は絶対に言わず、プラスな内容を言うべきだと思います。（エンジニアに将来性を感じたなど）

### なぜこの会社に入りたいのか
自分が成長できる企業であるかということを第一に考えてエントリーしていたので、その部分について話しました。（勉強会がある。技術系ブログがある。書籍購入代が出るなど）

### どうやって勉強していたか
私はポートフォリオを作成する際にMENTAを利用しました。
安いと月一万円くらいで質問し放題契約できたりするので、これから転職のためにポートフォリオを作成したい人にはとてもおすすめできます。

### コーディングテスト
Paizaやってたのでなんとかなりました。

### 知識に関して
準備していたのに聞かれた企業は0でした。
https
ip/tcp
git
json
api
ajax
spa
dom

などの知識はあった方が良いと思います。
私は聞かれませんでしたが

https://menta.work/

# 考え方
ある程度しっかり勉強してポートフォリオが３つ以上ある人は、転職成功するかどうかは結局運だと思います。
社風と自分の性格が合わないために落ちたという企業はかなりあると思っていて、20-30社程度なら落ちたとしてもあまり気にしませんでした。
あとは私の場合年齢的にも有利だったことは大きいと感じます。
また、コミュニケーション能力には自信があるので、ハキハキと笑顔で意見を伝えられました。
とにかく「この人と一緒に仕事がしたい！」と思わせるような話をしました。

# 私が考える転職成功フロー
1.ポートフォリオを三つ以上作成
→コピーするのではなく、自分で需要があると思ったもの、自分が「こんなアプリ欲しい！」と思えるものを作る
2.PaizaでBランク以上取る
3.エントリーしまくる

以上です。

# 大切なこと
大半の人がエンジニアを挫折してしまう原因は、エラーが解消できないことだと感じます。
そのため、もしエラーに悩んでしまったらお金を払ってでもメンターを付けるべきだと感じます。
私は運良く素敵なメンターに出会えたために、ポートフォリオを完成まで持っていけました。
一人でやっていてもエラーを解消できずに諦めていたと思います。
人に聞くことができる環境というのは本当に大切でした。

# これから
就業して業務に慣れることはもちろんですが、私の目標は個人開発でたくさんの人に利用してもらえるようなWebアプリを作ること。
そのために勉強して努力していく予定です。

また、一人で作るよりは何人かでワイワイ作りたいし、他人の技術も学びたいので共同開発してくれる方はいつでもお待ちしております。

Twitter
https://twitter.com/js_manabitai
IAMの管理ポリシーとインラインポリシー

## 勉強前イメージ

管理ポリシーはAWSが管理しているポリシー？みたいな感じするよね、名前的に

## 調査

### そもそもIAMとは？

Identity and Access Management の略で、AWSのサービス。
ユーザを作ったり、そのユーザに対してサービスへのアクセス等の制御を行うことができます。

以下簡単に言葉を紹介します。

- 人に対するもの
	- IAMユーザ : AWSアカウントに対してユーザを作成
	- IAMグループ : ユーザのかたまりをグループとする(開発部とかの単位で区切ることができる)

- 権限に関するもの
	- IAMポリシー : 「s3へのアップロードのみの権限」や、「EC2の閲覧のみの権限」など各サービスへの制御を行う
	- IAMロール : ポリシーを固めたもので、例えば「s3へのアップロードのみとEC2の閲覧のみ」の権限をまとめてデプロイ用権限とか作ることができる

詳細は [こちら](https://qiita.com/miyuki_samitani/items/06ac1366d0f3b9987813) を見ていただけますと
図付きでもう少し詳細に載っています。

### 管理ポリシー と インラインポリシー

ここでは管理ポリシーと記載していますが詳細には、以下の3つ？4つ？に別れます。

- インラインポリシー
- 管理ポリシー
	- AWS管理ポリシー
	- カスタマー管理ポリシー

それぞれ詳細書いていきます。

#### インラインポリシー と 管理ポリシー

- インラインポリシー

インラインポリシーとはIAMユーザやIAMグループに直接ポリシーを組み込む方式です。
マネジメントコンソールでは以下のように設定できます。

![1IAM Management Console - Google Chrome 2022-02-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/a28f8069-de37-7a85-7f26-3e354320c4ce.png)


図にすると以下のように権限を直接アタッチしているイメージです。
実際は、ポリシーを作ってそれをユーザにアタッチしてるのですが、 `他のユーザやグループに使い回せない` のが特徴です。

![12022-02-05 # IAMの管理ポリシーとインラインポリシー - diagrams.net -.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/eb84b3a8-2d06-33ed-044d-01d4edab3c9d.png)


- 管理ポリシー

管理ポリシーとはインラインポリシーとは違い、 `他のユーザやグループに使い回せる` ポリシーです。
AWSのコンソールでは以下のように確認できます。

![2IAM Management Console - Google Chrome 2022-02-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/8da2d145-bcce-5996-f09e-4f28e09a530d.png)

また、イメージとしては以下になります。
ポリシーとユーザにアタッチできるのは一緒ですが、他のユーザに使い回せるのが特徴です。

![22022-02-05 # IAMの管理ポリシーとインラインポリシー - diagrams.net -.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/97525c7c-084c-eb60-a356-666585abce93.png)



#### AWS管理ポリシー と カスタマー管理ポリシー

↑で、他のユーザやグループに使い回せるのが管理ポリシーと言いました。
その管理ポリシーの中にもAWS管理ポリシーとカスタマー管理ポリシーがあります。

- AWS管理ポリシー

AWS管理ポリシーは、一般的に使うことあるだろうなとAWSがデフォルトで作ってくれているポリシーです。
マネジメントコンソールからは以下のように見えます。
s3のフルアクセスの権限だったりEC2の部分的な権限だったり、基本的なポリシーは揃っています。

![3IAM Management Console - Google Chrome 2022-02-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/6cb4945b-ad81-9c0d-5781-721e6d22f918.png)


- カスタマー管理ポリシー

カスタマー管理ポリシーは、ユーザが独自で作ったポリシーです。
細かい制御をしたいときに↑のAWS管理ポリシーにない時は自分で作ります、その作ったポリシーとをカスタマー管理ポリシーといいます。
マネジメントコンソールでは以下のように見えます。

![4IAM Management Console - Google Chrome 2022-02-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/6b881c51-e512-af59-cde6-684165febcae.png)

## 勉強後イメージ

cloudformation書いてたときにIAMがインラインポリシーになってこれなに？ってなったやつ。
理解できた。

## 参考

- [管理ポリシーとインラインポリシー](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_managed-vs-inline.html)
docker-composeを使ったMySQLコンテナの作成(メモ)

勉強用メモです．
[初めてのSQL](https://www.oreilly.co.jp/books/9784873119588/)を勉強するためにコンテナで環境構築をしました．

# 実行環境

- WSL
- docker : 20.10.12
- docker-compose : 1.16.1

# sakilaデータのダウンロード

本に載っていたリンクにいき，[sakila database](https://dev.mysql.com/doc/index-other.html#:~:text=US%20Ltr%C2%A0%7C%C2%A0A4-,sakila%20database,-TGZ%C2%A0%7C%C2%A0Zip)のzipファイルをダウンロードした.



# コンテナによる環境構築

- ディレクトリ構造

※data以下はコンテナ起動時に生成される

```
.
├── mysql
│   └── db
│       ├── data
│       │   ├── my_testdb
│       │   ├── mysql
│       │   ├── performance_schema
│       │   └── sys
│       ├── my.cnf
│       └── sql
└── sakila-db
```

- sakila\-db.zip

解凍して，sakila-data.sql, sakila-schema.sqlをdb/sqlに置く．
data/sqlはdocker-entrypoint-initdb.dとしてマウントするため，data/sqlに*.sqlをおいておくと，初期データとして読み込んでくれる．
sakilaの名前は1-sakila-schema.sqlなどにしておき，sakila-schema.sqlが先に実行されるようにする※．

※sqlファイルはアルファベット順で実行されるため，sakila-data.sqlが先に実行されてしまいsakila databaseの中身が空になってしまう

- ./my.cnf

```
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

[mysql]
default-character-set=utf8mb4

[client]
default-character-set=utf8mb4 
```

- ./docker-compose.yml

```yaml
version: '3'

services:
  mysqldb:
    image: mysql:5.7
    container_name: mysql_container
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: my_testdb
      MYSQL_USER: docker
      MYSQL_PASSWORD: docker
      TZ: 'Asia/Tokyo'
    volumes:
      - ./mysql/db/data:/var/lib/mysql 
      - ./mysql/db/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./mysql/db/sql:/docker-entrypoint-initdb.d #初期データのマウント場所
    ports:
      - "3306:3306"
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
```

# コンテナ操作

- 起動

`docker-compose up -d`

- コンテナに入る

`docker exec -it <コンテナ名> sh`
これで読み書き可能なレイヤを作成して，シェルを起動する．

# テーブルの確認

`mysql -u root -p `
パスワードの入力を求められる．今回はrootユーザーのパスワードはrootに設定してあるので，rootと入力してEnter.

`SHOW databases`でテーブルの一覧が確認できる

# 注意ポイント

- ローカルのMysqlが動いていると，portがかぶって起動できないので，ローカルのMysqlを消すか，portのマッピングを変える．
- dockerコンテナを一度起動したあと，同じdocker-compose.yamlを使っているとvolumeが残ったままになっていて，データベースの初期データ読み込みが行われないので，もし，初期化が行われない場合は，`docker volume ls`でvolumeを確認して，`docker volume rm <volume名>`で消してから起動する．

# 環境構築完了

# 参考資料

環境構築の際に参考にさせていただきました．ありがとうございます．

https://www.whizz-tech.co.jp/5472/
https://qiita.com/kondo0602/items/ab0a85fb1e731234eb1a
https://qiita.com/enta0701/items/8e1fd797178c372769c7
https://blog.hiros-dot.net/?p=10469#toc4
https://blog.hiros-dot.net/?p=10469
https://qiita.com/TAMIYAN/items/ed9ec892d91e5af962c6
メモリリーク/ハンドルリークの調査

Windows / VisualStudio での、メモリリーク / ハンドルリークの調査方法についてのメモです。

# 手順概要

1. VisualStudioの診断ツールから、プロセスメモリが増え続けていないかをチェック
2. _CrtSetDbgFlagを使用してメモリリークのチェック
3. タスクマネージャから、ハンドル数が増え続けていないかをチェック
4. ProcessExplorerから、ハンドルの中身をチェック
5. windbgから、リークしたハンドルのスタックをチェック
6. 各種GPU用のデバッガから、グラフィックリソースのリークをチェック

# 手順詳細

### 1. VisualStudioの診断ツールから、プロセスメモリが増え続けていないかをチェック

VisualStudioから実行中に表示される診断ツールを確認して、プロセスメモリが増え続けている場合はなんらかのリークがあるので、調査を行う必要がある。


### 2. _CrtSetDbgFlagを使用してメモリリークのチェック

_CrtSetDbgFlagを使用することでメモリリークのチェックを行うことができる。
https://docs.microsoft.com/ja-jp/visualstudio/debugger/finding-memory-leaks-using-the-crt-library?view=vs-2022

これはメモリリークが疑われない場合でも、常に書いておくと予防になるのでよい。


### 3. タスクマネージャから、ハンドル数が増え続けていないかをチェック

_CrtSetDbgFlagではハンドルリークのチェックはできない。
_CrtSetDbgFlagに引っかからないのに、プロセスメモリが増え続けている場合は、ハンドルリークを起こしている可能性がある。

まずはタスクマネージャからハンドル数を確認して、増え続けていないかどうかをチェックする。


### 4. ProcessExplorerから、ハンドルの中身をチェック

ハンドル数が増えていることが確認出来たら、そのハンドルの中身を確認する。
ProcessExplorer等から、ハンドルの中身を確認することができる。
https://replication.hatenablog.com/entry/2015/06/16/093000
（タスクマネージャのリソースモニターからも確認できるが、情報が少ないかもしれない）

ここでリークしたハンドルの中身が分かったのであれば修正を行う。


### 5. windbgから、リークしたハンドルのスタックをチェック

手順4でハンドルの中身が確認できればよいが、できない場合もある。
その場合はwindbgを使用することで、リークしているハンドルのスタック情報を得ることができる。
https://www.keicode.com/iis/iis504a.php

windbgはWindows Driver Kitからダウンロードできる
https://docs.microsoft.com/ja-jp/windows-hardware/drivers/debugger/debugger-download-tools

ここでリークしたハンドルに目星がついたのならば、修正を行う。


### 6. 各種GPU用のデバッガから、グラフィックリソースのリークをチェック

手順5で例えばnvidia系のスタックが現れた場合などはグラフィックリソースがリークしている。
グラフィックリソースの確認は、各種GPU用のデバッガーを用いることで可能である。
https://www.khronos.org/opengl/wiki/Debugging_Tools

NVIDIA系の場合は、NVIDIA Nsight Graphicsを使用することで確認ができる。
https://blog.techlab-xe.net/check-nvidia-nsight-graphics/

確保済みの全リソースを表示して、開放し忘れているテクスチャなどがあれば修正を行う。
VSCodeで複数のデバッグ構成を使い分ける

# 動機
AtcoderをC++で解く(デバッグする)際に、標準入力をターミナルに直接入力する方法とテキストファイルから入力する方法とで使い分けたかったからです

# 方法
既存の`launch.json`の `configurations`に２つ目のデバッグ構成を追加します
今回は標準入力をテキストファイルから行いたかったので、`args`のみ変更しています
`name`は各自適当なものに変更してください

```json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "g++.exe - アクティブ ファイルのビルドとデバッグ",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
            // "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin\\gdb.exe",
            "setupCommands": [
                {
                    "description": "gdb の再フォーマットを有効にする",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "C/C++: g++.exe アクティブなファイルのビルド"
        },
// 追加ここから
        {
            "name": "hoge",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
            "args": [
                "<",
                "input.txt"
            ],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-+seh-rt_v6-rev0\\mingw64\\bin\\gdb.exe",
            "setupCommands": [
                {
                    "description": "gdb の再フォーマットを有効にする",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "C/C++: g++.exe アクティブなファイルのビルド"
        }
// 追加ここまで
    ],
}
```

## デバッグ構成の切り替え
**実行とデバッグ**のデバッグ開始アイコンの右側で切り替えができます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1092391/c1b20417-9297-5f00-ef6c-fa275e8353d6.png)
paizaレベルアップ問題を紐解く①　文字と整数の組のソート2 Ruby編

#はじめに
　現在積み上げ学習の一環として、paizaのレベルアップ問題に取り組んでいます。
今回は、連想配列に対してソートをするという実装につまづいたので備忘録としてまとめて見ます。

#問題内容　
　問題内容は以下のとおりです。

**文字と整数の組のソート**　
「1行目に行数を表す整数 n、続く n 行の各行で「文字」と「整数」の組が空白区切りで入力されます。
n 個の組について、「文字」の値が同じ組同士の数値を足しあわせてまとめ、まとめた数値の降順で、文字とまとめた数値の組を出力してください。
この際、まとめた数値は重複しません。」

**入力例**
7
A 1
D 6
C 2
G 4
B 70
A 10
B 5

**出力例**
B 75
A 11
D 6
G 4
C 2

問題文は以上です。
簡単に要約すると
「入力された値を、降順で並べ替える。（同じ文字の場合は数値を加算する）」という問題です。

#つまづいてしまった要因
　今回つまづいてしまった大きな要因としては、連想配列について知識が足りていなかったからです。
具体的には
・連想配列についての知識（格納の仕方、加算の仕方、条件指定の仕方など）
・連想配列に対してのsortメソッドの使い方
・連想配列に対してのeach文の回し方。
などです。

またアルゴリズム問題への場数の少なさも大いに関係してると思います。

#回答例

回答の方針としては、

　①連想配列を作る
　②入力された回数分繰り返し処理を行う
　③keyとvalueで値を分ける
　④条件分を作って連想配列に入れていく。
　　もしもvalueが一緒なら、keyを加算する。
　⑤sort_byメソッドとreverseメソッドで降順に並べ替える
　⑥ソートした連想配列をeach文で出力する

という流れです。

以下が回答例です。

```paiza.rb
count = gets.to_i
array = {}

count.times do |i|
    str  = gets.split
    string = str[0]
    points = str[1].to_i
    
    if array[string]
       array[string] = array[string] + points
    else
        array[string] = points
    end
end

array =  array.sort_by{|_,v| v }.reverse

array.each do |key,value|
    puts "#{key} #{value}"
end

```

#学んだこと① 連想配列の基本
　連想配列の基本的な仕組みについて学びました
・array[key] = value で値を入力
・if array[key]　という書き方でkeyが重複しているかをチェックできる
・繰り返し処理をする場合は|key,value|という形で値を取り出せる

参考文献
https://www.javadrive.jp/ruby/hash/index7.html  

#学んだこと② sort_byメソッド
　・sortメソッドで昇順、sort.reverseで降順になる
　・keyに対して降順でソートしたい時はsort_byメソッドを以下の形式で使う

```paiza.rb
array.sort_by{|_,v| v }.reverse
```

参考文献
https://blog.toshimaru.net/ruby-hash-sort/

#編集リクエスト　リファクタリングに挑戦(2/6追記)
　編集リクエストを頂いたのでリファクタリングに挑戦しました！

**①変数名の修正**
今回はハッシュを使っているため、
arrayという変数ではなくそれぞれhashという変数名に変更しました。

**②if文を簡略化**
　ハッシュに初期値を指定することでif文を削除できる

まずはハッシュを作るときに初期値を指定します。

```paiza.rb
hash = {}
↓↓
hash = Hash.new(0)
```

そして繰り返し処理の中のif文を以下のように修正します。

```paiza.rb
 if array[string]
       array[string] = array[string] + points
    else
        array[string] = points
    end

　↓↓
hash[string] += points
```

5行あったコードが1行になりました！


**③sort_byメソッド**
符号反転を使って簡略化

```paiza.rb
array.sort_by{|_,v| v }.reverse
↓↓
array.sort_by{|_,v| -v }

```

**修正したコードの全体**
結果以下のように修正できました！

```paiza.rb
count = gets.to_i
hash = Hash.new(0)

count.times do |i|
    str  = gets.split
    string = str[0]
    points = str[1].to_i
    
    hash[string] += points
end

hash =  hash.sort_by{|_,v| -v }

hash.each do |key,value|
    puts "#{key} #{value}"
end

```

ひと工夫でこんなにも、コードが効率的になるってすごい。
編集依頼ありがとうございました！



#まとめ
　今回はつまづいてしまった、paizaのアルゴリズム問題についてまとめてみました。
思った事は、rubyの基本知識をもっと定着する必要がある事。
アルゴリズム問題にもっと慣れる事。
が必要だという事です。

今後も継続して勉強していきます。
WindowsPCのセットアップの手間を省く「Chocolatey」

# はじめに
- ChocolateyとはWindows用のパッケージ管理ツール
- コマンド一つで必要なソフトウェアをインストールできる
- 新規PCで開発環境を作る際におすすめ

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [Chocolateyのインストール方法](#Chapter1)
2. [各ソフトウェアのインストール](#Chapter2)
3. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# 1.Chocolateyのインストール方法

- 「Windows PowerShell」を管理者権限で起動します。
 （ソフトウェアのインストールになるので管理者権限が必要です。）

- 以下コマンドを実行します。

```powershell
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
```



<a id="#Chapter2"></a>
# 各ソフトウェアのインストール
- インストールコマンドを実行します。
    - **以下コマンドは例ですので、必要なソフトウェアに変更してください！**
    - cinst : ソフトウェアのインストールコマンド
    - -y: cinstのオプション（インストール中のYes/No）
    - 対象ソフトウェアを羅列すればOKです。（指定するソフト名は[公式HP](#reference)で検索）

```powershell
cinst googlechrome git tortoisegit nodejs-lts yarn 7zip visualstudiocode putty winscp -y
```




<a id="#reference"></a>
# 参考文献
- [chocolatey公式HP](https://chocolatey.org/install)
【SpringToolSuite】セットアップ時の設定（ホワイトスペースの可視化、文字コードなど）

#はじめに
訳あってEclipseからSpring Tool Suiteに乗り換えました。
開発を始める前にいくつか設定しておいたほうがよさそうな部分があったので、そのメモになります。

#環境
| ツール             | バージョン   |
|:------------------|:------------|
| Spring Tool Suite | 4.13.1      |

Pleiadesで日本語化されていることが前提でお話しています。
インストール手順については以下が参考になりますので、どうぞ。
[Spring Tool Suite 4(STS)のインストール手順](https://qiita.com/t-shin0hara/items/d60116ab299a4dc8a9d0)

# ホワイトスペースの可視化
`設定＞一般＞エディター＞テキスト・エディター＞空白文字を表示（可視性の構成）`
囲い-空白のチェックだけ外しておくのがおすすめ。
インデントをスペースで行う派は同階層にある設定、「タブでスペースを挿入」にもチェックを入れておくと便利かもしれません。
![185.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522187/d245a985-24b9-2e6b-6bb5-2dbc3b4615aa.png)

# 開発文字コードの変更
`設定＞一般＞ワークスペース＞テキスト・ファイル・エンコード`
おそらく初期設定の`MS932`を利用する人は少ないと思うので、確認しておきましょう。
チーム開発の場合は区切り文字の確認もしておくとなおGOODです。
![186.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522187/cb024259-79f3-4e30-fffb-2e09deaf9b3b.png)

# JREの設定を変更する
`設定＞Java＞インストール済みのJRE`
初期設定ではEclipse（STS）付属のJREを見ています。
ビルドエラーが通らないと思ったら全く違うJREを見ていたということがあるので、もしご自身でダウンロードしたJDKを利用する予定でしたら、設定をお忘れなく。

#おしまい
思いつき次第追記します。
以上
pm2で--tls-min-v1.0オプションを使う

タイトルの通りです。
ネット上に情報があまりないようなので共有します。

~~~
node --tls-min-v1.0 app.js
~~~
で実行しているjsをpm2で使う方法は以下の通りです。

~~~
pm2 start app.js --name app --node-args="--tls-min-v1.0"
~~~
これで起動しておけば、

~~~
pm2 restart app
~~~
で再起動しても「--tls-min-v1.0」オプションは有効のままです。
【TypeScript入門 #5】オブジェクトの型解釈

# 概要

オンラインサロン IT_KINGDOM で、typescript について学んだことを備忘録としてメモしていきます。

# 学習内容

- オブジェクトについて
- オブジェクトの表記方法

# オブジェクトについて

- オブジェクトには下記の 2 種類の意味がある
  - 下記の７種のプリミティブ型に属さないもの(正規表現、配列等）
    - 論理(boolean)型
    - 数値(number)型
    - 文字列(string)型
    - undefined 型
    - null 型
    - シンボル型(symbol)
- `{}`で表現されるもの（辞書型）

# オブジェクトの表記

表記には 4 種類があるが、下記の 2 種類が良い。Index Signature を使う方法がおすすめ。

- 標準ライブラリの`obj:Record<string, unknown> = {};`を使う方法
- Index Signature である`obj: {[key: string]: unknown} = {};`を使う方法

```Typescript:使用例
let obj1: {} = true;      // 使うべきでない(プリミティブも受けとるため)
let obj2: object = [];    // 使うべきでない(辞書型としては適してないため)
let obj3: Record<string, unknown> = {
  a: 1,
  b: "foo",
};
let obj4: {[key: string]: unknown} = {
  a: 1,
  b: "foo",
};
obj3.b = "bar";
obj4.b = "bar";
```

# 参考資料

[IT Kingdom](https://it-kingdom.com/)<br>
[サバイバル TypeScript](https://typescriptbook.jp/reference/values-types-variables/primitive-types)
rubyで正規表現をコンパイルする

ざっと調べたメモ。

```rb
# 正規表現オブジェクトの作成
[10] pry(main)> reg = Regexp.new(".+aaa")   # Regexp.compile も同義
=> /.+aaa/

# =~演算子を使ってマッチするか調べることが可能
###  マッチあり
[28] pry(main)> reg =~ "xxxxaaaaaa"
=> 0
### マッチなし
[29] pry(main)> reg =~ "xxxx"
=> nil

# Regexp#match を使ってマッチするか調べることも可能
### マッチあり
[32] pry(main)> reg.match"xxxxaaa"
=> #<MatchData "xxxxaaa">
### マッチなし
[30] pry(main)> reg.match"xxxx"
=> nil
```

ちなみに、上記の`=~`及び`#match`メソッドは、正規表現リテラル`/.+aaa/`でも同様に使用することができる。
【論文読み】画像特徴量補完の可能性検証

## はじめに

こんにちは。論文を1人で読んだ結果の紹介記事です。  
今回紹介するのは、「地上画像を用いたドローン河川巡視で不足する空撮画像特徴量補完の可能性検証」という論文です。  

- タイトル：地上画像を用いたドローン河川巡視で不足する空撮画像特徴量補完の可能性検証
- 出典：高橋悠太, et al.; 人工知能学会, 2021  
- URL：https://www.jstage.jst.go.jp/article/pjsai/JSAI2021/0/JSAI2021_1F4GS10c02/_pdf/-char/ja  


## 概要
空撮画像に加えて地上画像を用いてゴミの物体検出モデルを構築した。 
地上画像を追加することで、モデルが改善されたため、特徴量補完ができた可能性がある。
追加する地上画像の選定手法を5パターン行い、その内3パターンがモデル改善の結果を得た。

## 技術的特徴
- 空撮画像のデータ不足の課題に対し、地上画像の河川維持管理データベースRiMaDISのデータを利用。
- 物体検出にはFaster R-CNNを使用。
- 追加する地上画像は、5つの手法で選出し、以下３つの手法が有効であった。
    - Bounding Boxの面積が空撮画像の平均と近い画像  
    - ShuffleNetを使用。空撮画像で、ゴミが映っていない部分を切り出して背景画像として切り出し、分類モデルを構築(ImageNetの事前学習済を使用)。そのモデルを用いて地上画像を分類して、ゴミありと判定された画像を、物体検出の追加データとする。  
    - Inception V3を使用。  


## 想定される適用例
- 学習データセットとなる画像データが少ない時の、物体検出・画像分類
JavaScriptめも

```javascript:sample.js

//関数宣言
function add(x, y) {
  return x + y;
};
console.log(add(1, 2));  // => 3

//即時関数
(function (x, y) {
    console.log(x + y);
}(1, 2)); // => 3

//関数代入
var test = function (x, y) {
    return x + y;
};
console.log(test(1, 2)); // => 3

//ラムダ
var test = (x, y) => x + y;
console.log(test(1,2)); // => 3

//配列
var array = [1,2,3]
console.log(array[0]) //=> 1

//連想配列
var array2 = {
            a : true,
            b  : false,
            c : false
        };
console.log(array2['a']) //=> true

//Promise then 非同期処理
var sample = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve();
    }, 1000);
});
sample.then(function(value) {
    console.log("Promise成功!");
});
console.log("先に出力");
```

非同期

asyncとawait
```javascript:sample.js

const test = async () => {
    console.log(1);
    await new Promise((resolve) => {
        setTimeout(() => {
            console.log(2);
            resolve();
        },1000)
    })
}

const main = async () => {
    await test();
    console.log(3);
}

main()
```
testからasyncとawaitを外す
```javascript:sample.js
const test = () => {
    console.log(1);
     return new Promise((resolve) => {
        setTimeout(() => {
            console.log(2);
            resolve();
        },1000)
    })
}

const main = async () => {
    await test();
    console.log(3);
}

main()
```

mainからもasyncとawaitを外す
```javascript:sample.js
const test = () => {
    console.log(1);
     return new Promise((resolve) => {
        setTimeout(() => {
            console.log(2);
            resolve();
        },1000)
    })
}

const main = async () => {
    await test();
    console.log(3);
}

main()
```
Unityを始める：2D RPGゲーム開発１．

Unityで、ゲーム開発をやって見たいと思い、勉強を始めました。
HOILさんと言う方のブログ内容を同じくやって見ながら、勉強しようと思っています。
投稿には参照元を記載しますので、不足部分などは元のものも参考して見てください。

元内容：https://hoil2.tistory.com/5

１．下記のサイトへ接続して、「Unity Personal」を選択してください。

https://unity.com/ja/products

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/f3d4e017-2f12-1c31-a025-dd658d55a130.png)

２．「はじめる」ボタンを押下してください。

https://store.unity.com/ja/products/unity-personal

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/bfb16e96-25fe-5a4d-672a-e6f178ef73e4.png)

３．「他のバージョンをダウンロードする」を押下するか、スクロールして、画面は以下の「1.Unity Hubをダウンロード」が表示されるようにしてください。

https://unity.com/ja/download

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/09cf14d7-551f-40ab-df1f-16174a794c26.png)

４．自分の環境に合わせたものを押下して、ダウンロードを行ってください。
この度に使うバージョンは「3.0.1.0」です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/698ca612-e14d-3b4a-d3ac-0dd7a678181a.png)

５．ダウンロードされた「UnityHubSetup.exe」を二度押下してWindowsなら、管理者権限からの実行を選択して、インストールしてください。
UnityHubインストールはオプション選択などが無いため、諸略します。

６．Unityのアカウントが無い場合は、「Create account」を押下して、アカウントを作成してください。
アカウントがある場合は、「Sign in」を押下して、ログインを行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/0cd3465e-a21b-f66e-e180-468f70e6b3cb.png)

７．インストールする場合は、「Install Unity Editor」を押下して、次へ進んでください。
既にインストールされている場合は、「Locate existing installation」を押下して、インストールされているUnity Editor場所を指定してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/96717b42-a406-0315-db99-5e10e7317b29.png)

８．「Agree and get personal edition license」を押下して、インストールを実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/9876ba27-9287-0b39-d9d9-c485cb3a4bef.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/7520882e-c92a-3839-eb09-dcebac76de7d.png)

９．インストールが終わったら、デスクトップにあるアイコンを二度押下して、Editorを起動させてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/bc1233be-3e10-9f1c-38cf-8bbf5f20b8e2.png)

これで、準備が完了になりました。
これからはプロジェクトを作ってやって見ます。
nodenvでlocalコマンドが反映されない

nodenvのインストールガイドには、Linuxなどbrewが使えない場合は手動でインストールしてくれと書いてあります。

https://github.com/nodenv/nodenv#basic-github-checkout

このマニュアルの通りに進めると`nodenv local {version}`を実行しても反映されません。
nodeコマンドのパスが`/.nodenv`を参照していないようです。

```shell
$ which node
/usr/local/bin/node
```

原因はnodenvの初期化コマンドが実行されていないためのようです。
`/.bashrc`に追記すると反映されました。

```shell:./bashrc
export PATH="$HOME/.nodenv/bin:$PATH"
eval "$(nodenv init -)"
```
---
参考

https://blog.mintsu-dev.com/posts/2020-07-22-install-nodenv-linux/
ReactでAPIから取ってきた背景画像を表示する方法（style attribute, css-modules, tailwindcss, styled-components）

# はじめに
自分が詰まったので。特にtailwind。

## style attributeを使う
一番手っ取り早いのはこれです。

```tsx
<div style={{ backgroundImage: imageUrl }}>
 ....
</div>
```

### 擬似クラス使えない問題
style attibute内では:hoverなどの擬似クラスが使えないので、この手法は背景画像が常に表示されるデザインにのみ使えます。「hover時のみ表示したい」などといった場合は以下から紹介するアプローチが必要になります。

## css-modulesを使う

```jsx:Component.jsx
import style from './Component.module.css'

const Component = ({ imageUrl }) => {
 const cssProperties = {
  '--image-url': `url(${imageUrl})`
 }

 return (
  <div style={{ cssProperties }} className={style.backgroundImage}>
   ....
  </div>
 )
}
```

```css:Component.module.css
.backgroundImage:hover {
 background-image: var(--image-url);
}
```

これでhover時のみ背景画像を表示させることができます。

### TypeScriptの場合
custom propertyを含むオブジェクトに正しい型を付けてあげないとstyle attributeで弾かれます。

```tsx
import { CSSProperties } from 'react'

const cssProperties = {
 '--image-url': `url(${imageUrl})`
} as CSSProperties
```

### ありがちなミス
```tsx:Component.jsx
// ❌
const cssProperties = {
 '--image-url': imageUrl
}

// ⭕
const cssProperties = {
 '--image-url': `url(${imageUrl})`
}
```

```css:Component.module.css
/* ❌ */
.backgroundImage:hover {
 background-image: url(var(--image-url));
}

/* ⭕ */
.backgroundImage:hover {
 background-image: var(--image-url);
}
```

## tailwindcssを使う
注: version3以上が必要です。

```jsx
const Component = ({ imageUrl }) => {
 const cssProperties = {
  '--image-url': `url(${imageUrl})`
 }

 return (
  <div style={{ cssProperties }} className='hover:bg-[image:var(--image-url)]'>
   ....
  </div>
 )
}
```

### ありがちなミス
```jsx
<div className={`hover:bg-[url(${imageUrl})]`}>
 ....
</div>
```

tailwindはコンパイル時にcssを生成しているので、クラス名の一部に動的な値が含まれているとそのクラス名は生成されません。

```jsx
<div style={{ cssProperties }} className='hover:bg-[var(--image-url)]'>
 ....
</div>
```

`bg-[]`の中の`image:`が抜けているので、tailwind側からすると`var(--image-url)`が背景色なのか背景画像なのか分からない状況になっています。

## styled-componentsを使う

```jsx
import styled from "styled-components";

const Component = ({ imageUrl }) => {
 return (
  <DivWithImage url={imageUrl}>
   ....
  </DivWithImage>
 )
}

const DivWithImage = styled.div`
 &:hover{
  background-image: url(${prop => prop.url});
 }
`
```

### TypeScriptの場合
```tsx
const DivWithImage = styled.div<{ url: string }>`
 &:hover{
  background-image: url(${prop => prop.url});
 }
`
```

propの型を定義しましょう。

### ありがちなミス
```jsx
import styled from "styled-components";

const Component = ({ imageUrl }) => {
 return (
  <DivWithImage>
   ....
  </DivWithImage>
 )
}

const DivWithImage = styled.div`
 &:hover{
  background-image: url(${imageUrl}); // ❌
 }
`
```

`DivWithImage`の定義が親コンポーネントの外で行われているので、親のpropである`imageUrl`には直接アクセスできません。
これを可能にするには、`DivWithImage`の定義を親コンポーネント内で行えばよいのですが、レンダーごとに定義し直されてしまうのでパフォーマンスが落ちます。最初の例のように外で定義して別でpropを渡しましょう。

# おわりに
tailwind君、基本的には使いやすいけど動的な値が絡んでくると途端にポンコツになりがち。

なにか間違いがあればコメントで教えてくれると助かります。
僕も Ruby と Python で pagepank をやってみた

# はじめに
https://en.wikipedia.org/wiki/PageRank

上記URLにあります、PythonのコードをRubyでやってみようと思います。

```python:result.py
M = np.array([[0, 0, 0, 0, 1],
              [0.5, 0, 0, 0, 0],
              [0.5, 0, 0, 0, 0],
              [0, 1, 0.5, 0, 0],
              [0, 0, 0.5, 1, 0]])
v = pagerank(M, 100, 1)
print(v)

# output
[[0.26658293] 
 [0.13322816] 
 [0.13322816] 
 [0.20009761] 
 [0.26686313]]
```
ここでは、ダンピング・ファクターを`1`とします。
# 問題の整理（AtCoder風）
ノード数`N`の有向グラフがある。
高橋くんはノード1からスタートして100回ランダムな遷移を行います。
遷移後、高橋くんがどのノードにいるかを答えてください。

```
入力
N M
A1 B1
.
.
.
Am Bm
```
```
入力例
5 7
1 2
1 3
2 4
3 4
3 5
4 5
5 1
```
# Ruby
```ruby
n, m = gets.split.map(&:to_i)
ab = Array.new(n){ Array.new(n, 0) }
m.times do
  a, b = gets.split.map(&:to_i)
  ab[a - 1][b - 1] = 1
end
ab.each_with_index do |x, i|
  s = x.sum
  x.each_with_index do |_, j|
    ab[i][j] /= s.to_f
  end
end
m_hat = ab.transpose

v = n.times.map{ rand(0...1.0) }
vs = v.sum
v.map!{ _1 / vs }
100.times do
  vd = v.dup
  n.times do |i|
    v[i] = 0
    n.times do |j|
      v[i] += m_hat[i][j] * vd[j]
    end
  end
end
puts v

# output
0.2662026143788123
0.13329803377108196
0.13329803377108196
0.20040578221512312
0.2667955358639006
```
ふう、`TLE`にならなければよいのですが。
# [追記] Python
```python
import networkx as nx

N, M = map(int, input().split())
G = nx.DiGraph()
for _ in range(M):
    A, B = map(int, input().split())
    nx.add_path(G, [A, B])

pr = nx.pagerank(G, alpha=0.95, max_iter=100)
print(pr)

# output
{1: 0.26261033194706523, 2: 0.13473925873325307, 3: 0.13473925873325307, 4: 0.20200447126193546, 5: 0.26590667932449313}
```
いやー、python便利、networkx便利ですね。
ちなみに、ダンピング・ファクターである`alpha`は0.95を超えるとエラーになる様です。

https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.link_analysis.pagerank_alg.pagerank.html

# まとめ
+ pegerankに詳しくなった
docker を利用し各種言語のバージョンを使い分ける

# 経緯
今までは [anyenv](https://github.com/anyenv/anyenv) を使用し各種言語のバージョン管理をしていたが、env系の各種設定が面倒くさくなってきた。
docker を使用し、一時的にコンテナを立てて実行すればいいかもしれないと考えたのでやってみた。

## やってみた！
下記は、nodejs14系 を使いたい時の例

```
# project ディレクトにて
docker run --rm -it -v $(PWD):/app --workdir /app node:14 npm install
```

<strong>-v</strong> でプロジェクトを適当なディレクトリにマウントする。
マウントしたディレクトリを、<strong>workdir</strong> で指定し、コマンドを実行すればOK
また、<strong>--rm</strong> を指定し、実行後にコンテナを自動削除すればコンテナの死骸が増えずに済む。

## 開発にて
実際の開発では、長ったらしいコマンドを実行するのが面倒くさいのでシェルスクリプトを作成するのがおすすめ

```
touch npm.sh
chmod +x npm.sh
```
ファイルを作成し、実行権限を付与
<hr>

```npm.sh
#!/bin/bash
docker run --rm -it -v $(PWD):/app --workdir /app node:14 npm $@
```
<strong>$@</strong> で引数を受け取れるようにすることで、npm の各種コマンドに対応できるようにする
<hr>

```
./npm.sh install react
./npm.sh run dev
```
上記のように各種コマンドの実行が可能！

### 注意点
composer を上記のように利用したときは、phpの拡張が足りず一部インストールできないパッケージがあった。
その場合は、自前でphp拡張各種インストールしたdocker image を作成する必要がある。
【2022年版】MacにNodejsをインストールする方法

# はじめに
M1チップのMacbookでNodejsをインストールする方法をまとめた

# Homebrewをインストール

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
※Homebrewをインストール済みの方は次の手順へ

https://brew.sh/index_ja

インストール後は、次のコマンドでbrewコマンドが使えることを確認

```
brew -v
```
コマンドが使えない場合は下記参考

https://qiita.com/wooooo/items/6d8a7de5ffafed1cc66c

# Nodebrewのインストール
```
brew install nodebrew
```

インストール後は下記のコマンドでバージョンを確認

```
nodebrew -v
```


続いて下記のコマンドを実行

```
nodebrew setup
```

下記のコマンドを実行し、Nodejsをインストール

```
nodebrew install-binary stable
```

インストール後に下記のコマンドを実行

```
nodebrew ls
```

実行例

```
v16.13.2

current: none
```
current :node となっているので、バージョンを指定する

# Nodejsを有効化する
"nodebrew ls"のコマンドで出力されたバージョン番号で下記を実行

```
nodebrew use v16.13.2
```

# 環境パスを通す
Macデフォルトのzshをお使いの方

```zsh
echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.zprofile
```

bashをお使いの方

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


ターミナルを再起動し、下記のコマンドでNodejsがインストールされていることを確認

```
node -v
```

終わりです
NestJSクラスタ起動

# Nestのプロジェクト作成
``` sh
npm i -g @nestjs/cli
nest new "プロジェクト名"
```

# 起動確認
```
yarn start
```
localhost:3000にアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296391/d25f416c-7665-bea7-3827-2f88e690e92a.png)



# main.tsの修正
``` main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

import * as _cluster from 'cluster';
const cluster = _cluster as unknown as _cluster.Cluster;
import * as os from 'os';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}

if (cluster.isPrimary) {
  console.log(`Master server started on ${process.pid} cpu len: ${os.cpus().length}`);

  // cpuの数分forkする
  for (var i = 0; i < os.cpus().length; i++) {
    console.log('cluster fork :', i);
    cluster.fork();
  }
} else {
  console.log('boot strap')
  bootstrap();
}
```

# app.service.tsの修正
``` src/app.service.ts
import { Injectable } from '@nestjs/common';

import * as _cluster from 'cluster';
const cluster = _cluster as unknown as _cluster.Cluster;

@Injectable()
export class AppService {
  getHello(): string {
    console.log(cluster.worker.id)
    return `Worker ID: ${cluster.worker?.id} PID: ${cluster.worker.process.pid}`;
  }
}
```

# 起動して確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296391/ad015627-6ffa-bbad-88fe-542a3404c6db.png)
※自身のPCのコア数が4なので、4プロセス分forkされる

# localhost:3000にアクセスし、複数プロセスで動いているのを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296391/24930a5a-6625-e265-afb0-b70676f2d70c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296391/971a234e-9b55-f9b1-0158-4f185f2eea2e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296391/c0a6ed11-cf16-70b9-b2b4-e7fbaa8aef2c.png)

# github
https://github.com/kyosuke12345/NestJS-cluster-sample
Excelでいつも調べている式

# 初めに
覚える気はないが、毎回調べているので、自分のQiitaに書いておこうかと

## シート名表示
```
=MID(CELL("filename",A1),FIND("]",CELL("filename",A1))+1,31)
```
- ファイルを保存しないとエラー表示されることを結構な確率で忘れている
- 右クリック→新規(Windows)で開いた時も、同様

## 行番号
```
=IF(ISNUMBER(INDIRECT(ADDRESS(ROW()-1,COLUMN())))=FALSE,1,INDIRECT(ADDRESS(ROW()-1,COLUMN()))+1)
```
- 先頭は1にして、2行目以降は上のセル+1


## 子番号（的なもの）
```
=IF(ISBLANK(INDIRECT(ADDRESS(ROW(),COLUMN()-1)))=FALSE,1,INDIRECT(ADDRESS(ROW()-1,COLUMN()))+1)
```
- 左に親番号がある（空白ではない）場合は1に、ない場合は上のセル+1


# 最後に
毎回調べたら良いんだけど、自分で書くとどこにあるのかすぐにわかるので便利

# 参考
http://officetanaka.net/excel/function/tips/tips99.htm
https://ak-design.work/excel-%EF%BC%91%E3%81%A4%E4%B8%8A%E3%81%AE%E3%82%BB%E3%83%AB%E3%81%AE%E5%80%A4%E3%82%92%E5%8F%82%E7%85%A7/
paiza PHP Bクラス　過去問の日別訪問者数の最大平均区間（前半）

タイトル通り、paizaのPHP Bクラス　日別訪問者数の最大平均区間を自力で何とかクリアしたのですが
PHPは解答コードがなかったため、自力でやるしかなく足りない頭がパンクしました。笑

もっとスマートな書き方があるとは思いますが、
初学者の方などの参考になればと思いますのでよろしくお願いします。

問題文はこちらから確認してください。
https://paiza.jp/works/mondai/skillcheck_archive/max_range

コードの記入はpaiza.ioを利用して、入力などを行ってます。
paiza.io:https://paiza.io/ja/projects/new

ではコードを書いていきます！
###1.入力値を求める

```
[$n, $kya] = explode(' ', trim(fgets(STDIN)));
$log = explode(' ', trim(fgets(STDIN)));
```
＄nには全n日分の日数、＄kyaにはキャンペーンを行った日数がわかります。
＄logにはn日分の一日分の閲覧数の値が入ります。

paiza内の入力例１を入力した場合、下記のような値が入っています。

```
array(5) {
  [0]=>
  string(1) "1"
  [1]=>
  string(1) "2"
  [2]=>
  string(1) "3"
  [3]=>
  string(1) "2"
  [4]=>
  string(1) "1"
}
```

###2.キャンペーン期間中の平均値を出す

```
for ($i = 0; $i < $n - $kya + 1; $i++) {
        $log_kya = 0;
    // $kya期間の閲覧数の合計を出す(ｎ日期間中)
        for ($j = $i; $j < $kya + $i; $j++) {
            $log_kya += $log[$j];
        }
    // 平均値を出し、四捨五入した値を新しい配列＄aveに代入する
        $ave[] = round($log_kya / $kya, 2);
}
```
キャンペーン期間（＄kya）の平均値を出すのですが、まずキャンペーン期間の連続する値を取る範囲を決めます。

```
for ($i = 0; $i < $n - $kya + 1; $i++) {

}
```
こうすることで０から始まる配列を3つづつ値をとっても配列数を上回るのを防いでいます。
例の場合
[0] から　3つ　1 2 3 
.
.
[3]　から　3つ　2 1 ?
となるのを防いでいます。+1は配列は0スタートなので帳尻を合わせるためにしています。

次に繰り返し処理で＄kya期間の閲覧数の合計を出す処理をします。

私はここでかなり迷走してました

1日目から3日分、2日目から3日分という処理の仕方がわからなかったのですが、下記のように記述することで解決できました。
上手く説明できる気がしなかったのでここは頑張って理解できるようにしてください。
forの処理がどのように行われているのかを理解しているとわかると思いますが、あまりわからない方は参考にこちらをご覧になってみてください。
参考：https://qiita.com/dogennmosenn/items/8acf35866f24ead0d126

```
for ($i = 0; $i < $n - $kya + 1; $i++) {
        $log_kya = 0;//初期化
    // $kya期間の閲覧数の合計を出す(ｎ日期間中)
        for ($j = $i; $j < $kya + $i; $j++) {
            $log_kya += $log[$j];
        }
}
```
あとは平均値を出します。

```
for ($i = 0; $i < $n - $kya + 1; $i++) {
        $log_kya = 0;//初期化
    // $kya期間の閲覧数の合計を出す(ｎ日期間中)
        for ($j = $i; $j < $kya + $i; $j++) {
            $log_kya += $log[$j];
        }
    // 平均値を出す
        $ave[] = round($log_kya / $kya, 2);
}
```

ここまでがわかるとあとはかなり楽になると思いますので是非自力でチャレンジしてみてください！
残りは後半で書かせていただきます！
【Udemy】聴きやすい英語のエンジニア向け優良コンテンツ(順次追記)

技術はサッパリだが英語ができるワイは最近Udemyの英語コンテンツで学んでいます。
その中で**聴きやすい英語**で**内容がとてもいい**と判断したものを追記していきます。
合う講師を見つけて、その講師の他の動画を見るのが効率的だと思っています。


#**Udemy英語コンテンツのメリット・デメリット**
**メリット**
・Udemyの英語コンテンツは日本語コンテンツより充実しているものが多い(独断です)
・日本語コンテンツにない技術スタックを扱っている
・最新技術の動画が出るのが明らかに日本語より早い
・副次的に英語力向上にもつながる

**デメリット**
・ネイティブじゃない訛りまくった英語を話す講師も多いため、聞きやすい英語を話す講師を探す必要あり


#**講師リスト**
・[Jonas Schmedtmann](https://www.udemy.com/user/jonasschmedtmann/)
→比較的ゆっくり話す。自分の老いを自覚し、年齢の話題に触れるのを恐れている節がある。
・[Trevor Sawler](https://www.udemy.com/user/trevor-sawler/)
→比較的ゆっくり話す。ブレスが深い。Ph.D.持ちのプロフェッサー。
・[Colt Steele](https://www.udemy.com/user/coltsteele/)
→話すスピードは結構速い。お茶目なやつである。私のお気に入り講師。
・[Bret Fisher](https://www.udemy.com/user/bretfisher/)
→話すスピードは結構速い。きれいな英語。ひげ。

#**コンテンツリスト**
**JavaScript**
・[The Complete JavaScript Course 2022: From Zero to Expert!](https://www.udemy.com/course/the-complete-javascript-course/)
→講師はJonas Schmedtmann。JavaScript界隈では有名な動画ですね。これだけでVanilla JSは中級レベルに達することができそうです。

**React and Go**
・[Working with React and Go (Golang)](https://www.udemy.com/course/working-with-react-and-go-golang/)
→講師はTrevor Sawler。１２時間ほどでReactとGoを一通り触れる(GraphQLも)。技術選定用に買ったが良さそう。

**Git**
・[The Git & Github Bootcamp](https://www.udemy.com/course/git-and-github-bootcamp/)
→講師はColt Steele。Gitのあやふやな理解を解消し、めちゃくちゃわかるようになる。動画ではGitKrakenを使っているが私は[Fork](https://git-fork.com/)派です。

**Docker**
・[Docker Mastery: with Kubernetes +Swarm from a Docker Captain](https://www.udemy.com/course/docker-mastery/)
→講師はBret Fisher。Dockerの基礎からKubeまで。ただ、Dockerは基礎を日本語で学んでからの方がいいと思われます。

#**今後**
スローペースで追記予定。講師リスト10人目指したい。
Qiita記事の書き方

Qiitaに記事を書きたいが、黒いコーディング画面の書き方や大文字の出し方が分からない。
そんな方の手助けになればと思い本投稿をします。(※本当は自分の備忘録用...)
##1,見出し、太字、斜体、

・　見出し
上記のようなタイトルを作成するには
見出し文章の前に、シャープ「#」をつける。
 #の数が増えると、小見出しになる。
###Qiita
>記述例.)
 #Qiita (見出し1)
 ##Qiita (見出し2)
 ###Qiita (見出し3)←上記サイズ

・　太字
太字表記にしたい時は、文章の前後にアスタリスク「**」をつける。

**Qiita**
>記述例.)
＊＊Qiita＊＊


・　斜体
斜体表記にしたいときは、文章の前後にアスタリスク「*」をつける。

*Qiita*
>Ex.)
＊Qiita＊

##2,コードの記述

コードの記述を行う際には、バッククオーテーション「```」でコードを囲う。
※バッククオーテーションは「Shift+＠」で打ち込み可能。
バッククオーテーションの後に「言語:ファイル名」を記入することにより、ファイル名が表示される。

```python:sample
Qiita
```
>Ex.)

>｀｀｀python:sample
>Qiita

>｀｀｀

##3,リストの表記
リスト表示を使用したいときには、
(+ or - or *)の後に半角スペースを入れて、文章を打ち込む。

+ Qiita1
+ Qiita2
+ Qiita3

>Ex.)
>+ Qiita1
>+ Qiita2
>+ Qiita3

##4,リンクの挿入
文章にリンクを付けたい場合は、［文章］(URL)と記述する。

[Qiita](https://qiita.com/)

>Ex.)
> ［Qiita］(https://qiita.com/)

##5,区切り線の挿入
区切り線を入れたい場合は、(* or -)を3つ以上記述することで挿入できる。

---

Ex.)
> ーーー

##6,データテーブルの挿入
データテーブルを挿入したいときは、「 | 」で囲う。
二行目にて行揃え指定を行う。

| Qi|  i    | ta|
|:--|:---:|--:|
| ta|  Qi   |  i|
|i  |ta     | Qi|

>Ex.)
>
> ｜　Qi　|　i　|　ta　|
>｜:--　|　:---:　|  --:  |
> ｜　ta　|　Qi　|　i　|
> ｜　i　|　ta　|　Qi　|
>

##7,文字色の変更
文章の文字色を指定したいときは、fontタグにて文章を囲う。

<font color=red>Qiita</font>
<font color=green>Qiita</font>
<font color=blue>Qiita</font>

>Ex.)
>＜font color=red＞Qiita＜/font＞
>＜font color=green＞Qiita＜/font＞
>＜font color=blue＞Qiita＜/font＞



Qiitaをより有効活用できるよう今後も使っていきましょう。