OmniAICreator/Qiita-1.07M huggingface dataset:
Git 最後コミットした状態にbranchの先頭、インデックス、作業ツリーの全てを戻す


# 現在のbranchの先頭、インデックス、作業ツリーを全部リセットするコマンド
```
git reset --hard HEAD
```

# 経緯
コマンドはもうタイトルに書いてしまっているので、怖い話でも書きます。


>ある晩、夜桜は恐ろしいミスを犯してしまいました。彼は魔法のような開発ツール、Xcodeを使っていましたが、あるプロジェクトにファイルを追加しようとしたとき、彼は手を滑らせてしまったのです。なんと、その追加すべきはずのファイルではなく、プロジェクト自体を内包するフォルダを追加してしまったのです。
そして、恐ろしいことに、そのフォルダ内にはさらに同じプロジェクトが入っており、その中にまた同じフォルダが存在していたのです。恐ろしい再起構造が幾重にも形成されていました。



![スクリーンショット 2023-06-02 16.57.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/11a82752-ee65-c135-0dd6-5aa5a2461225.png)
（絶望）
>夜桜は慌ててその誤って追加したフォルダをプロジェクトから削除しようとしました。ゴミ箱に移動させると、とんでもないことが起こりました。なぜか、プロジェクト自体のファイルまでもが次々とゴミ箱に入ってしまうのです。

<img width="100" alt="スクリーンショット 2023-06-02 17.00.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/e328ae02-39a3-e739-c2e3-ba7519c32bbf.png">

（絶望）
>幸いなことに、夜桜はまだコミットしていなかったので、Gitの魔法を使うことにしました。彼は恐る恐る「git reflog」という魔法のコマンドを唱え、Gitの操作履歴を確認しました。そして、大切なものを見つけました。それは「HEAD」という名の魔法のポイントでした。夜桜はホッと一息つきました。彼は短期間でたくさんのコミットを行っていたため、失われたプロジェクトを戻すことができるのです。
夜桜はすぐさま「git checkout HEAD .」という魔法のコマンドを試しました。すると、Git上の操作は取り消され、彼は一番最後のコミットの状態に戻りました。しかし、なんということでしょう。作業ツリー、つまり実際のファイルやディレクトリの配置は元に戻りませんでした。消えてしまったファイルは戻ってこなかったのです。

参考：https://www-creators.com/archives/1290


>夜桜は絶望しましたが、あきらめることはありませんでした。彼は再び魔法の記事を参考にしました。今度は「git reset --hard」という最強の魔法を試すことにしました。そして、奇跡が起こりました。失われたファイルが無事に復元されたのです。


| モード指定| 動作 |
|:-:|:-:|
git reset --soft	|現在のbranchの先頭だけをリセット。（インデックスはそのまま）|
|git reset          |                                                   |
|(git reset --mixed)|	現在のbranchの先頭と、インデックスをリセット          |
|git reset --hard	|現在のbranchの先頭、インデックスも作業ツリーも全部リセット |


引用：https://www-creators.com/archives/1282#git_add-2
>しかし、まだ夜桜の試練は終わりませんでした。そのフォルダには他の大切なファイルも含まれており、それらもGitで管理されていたのです。夜桜はこれからもがんばって戻すことを決意しました。彼の戦いはまだ続いていくのでした。


本物語はChatGPT先生に書いてもらいました。夜桜って誰だよ。
列が`MultiIndex`であるDataFrameに対して、`rename`関数で列名をタプルで指定しても列名は変更されない

# 環境
* Python 3.11.2
* pandas 2.0.2


# 何が起きたか
列が`MultiIndex`であるDataFrameがあります。このDataFrameの列名を、[pandas.DataFrame.rename](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rename.html)関数で変えたいです。

```
In [303]: data = {("japan","male"):[1,2,3], ("japan","female"):[11,12,13], ("us","male"):[2,3,4]}

In [304]: df = pandas.DataFrame(data)

In [305]: df
Out[305]: 
  japan          us
   male female male
0     1     11    2
1     2     12    3
2     3     13    4

```


`columns`にタプルで列を指定しても、列名は変更されませんでした。
```
# 列名は変更されない
In [310]: df.rename(columns={("us","male"):("US","MALE")})
Out[310]: 
  japan          us
   male female male
0     1     11    2
1     2     12    3
2     3     13    4
```

# 解決

## `rename`関数の`columns`引数にタプルではなく文字列を指定する
タプルで複数要素（ヘッダ1行目と2行目）を指定するのではなく、文字列で1個の要素を指定すれば、変更できました。

```
In [308]: df.rename(columns={"japan":"JAPAN"})
Out[308]: 
  JAPAN          us
   male female male
0     1     11    2
1     2     12    3
2     3     13    4

In [309]: df.rename(columns={"male":"MALE"})
Out[309]: 
  japan          us
   MALE female MALE
0     1     11    2
1     2     12    3
2     3     13    4

```

`level`引数を指定すれば、rename対象のヘッダ行を指定することもできます。

>In case of a MultiIndex, only rename labels in the specified level.


## `rename`関数を使わずに`columns`プロパティに直接指定する

`columns`引数に直接`MultiIndex`を指定するのが、たぶん一番分かりやすくてハマらないと思います。


```
In [319]: df2.columns = pandas.MultiIndex.from_tuples([("japan","male"), ("japan","female"), ("US","MALE")])

In [320]: df2
Out[320]: 
  japan          US
   male female MALE
0     1     11    2
1     2     12    3
2     3     13    4
```


# 試したけどできなかったこと

## mapperを指定する
`rename`関数には変換用の関数も指定できます。しかし、関数はヘッダの要素ごとに関数が呼ばれるので、期待通り変更できませんでした

```
In [49]: def mapper(col):
    ...:     print(col)
    ...:     if col == ("us","male"):
    ...:         return ("US","MALE")
    ...:     return col
    ...:

In [50]: df.rename(mapper, axis="columns")
japan
japan
us
male
female
male

Out[50]:
  japan          us
   male female male
0     1     11    2
1     2     12    3
2     3     13    4
```
Elastic Stack一式をelastic-packageコマンドを使ってローカルに一発で立ち上げる

# 概要

Integrationをテストする場合、例えば今Ingestion Pipelineの修正であれば少なくともElasticsearchが必要で、他に例えばダッシュボードに修正を入れる場合は当然Kibanaなどそのほかのコンポーネントも必要になります。Elasticではその辺りの一式を揃えるための [elastic-package](https://github.com/elastic/elastic-package) というツールを提供しています。

そして別の[Integrationsのテスト関連の記事](https://qiita.com/daixque/items/7f3502c4dfb2da427064)を書いていて気づいたのですが、おそらくElasticsearch / Kibana / FleetなどElastic Stack一式をローカル環境にセットアップする一番手っ取り早い方法はIntegrationsのパッケージ開発用に提供されている`elastic-package`コマンドを利用することじゃないでしょうか。

一回セットアップして仕舞えばコマンド一発でローカルに特定バージョンのElastic Stackを構築できます。

# 前提

この記事では以下を前提にしています。

- macOS (他でも動くと思いますが、試していません)
- Dockerデスクトップインストール済み

# セットアップ

[最新版のリリースページ](https://github.com/elastic/elastic-package/releases/latest)から適切なパッケージをダウンロードします。展開すると`elastic-package`コマンドの実行ファイルがあるので、これをパスの通ったところに配置します。

macOSの場合、ダウンロード後そのまま実行しようとするとセキュリティーの設定で起動できないため、以下のコマンドで実行を許可します。

```sh
$ xattr -r -d com.apple.quarantine elastic-package
```

以下のコマンドで動作確認します。

```sh
$ elastic-package -h
elastic-package - Command line tool for developing Elastic Integrations
...(略)...
```

動いているようですね。

# Elastic Stackの起動

コマンドが使えるようになったら以下のコマンドでElastic Stackを一気に起動できます。

```sh
$ elastic-package stack up -v \
  --version=8.8.0 \
  --services="kibana,package-registry,elastic-agent,elasticsearch,fleet-server"
```

起動できたらKibanaには[https://127.0.0.1:5601](https://127.0.0.1:5601/app/home#/)でアクセスできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628554/10d7ec48-152c-f8a9-e7b6-983ed30c713a.png)

Elasticsearchに直接アクセスする場合、ユーザー名: elastic, パスワード: changeme で認証できます。

```
$ curl -k https://elastic:changeme@127.0.0.1:9200
```

`-h` オプションでヘルプを見ると、`stack up`コマンドでは以下のオプションが使えるようです。

```
Usage:
  elastic-package stack up [flags]

Flags:
  -d, --daemon             daemon mode
  -h, --help               help for up
      --provider string    service provider to start a stack (compose)
  -s, --services strings   component services (comma-separated values: "kibana,package-registry,elastic-agent,elasticsearch,fleet-server")
      --version string     stack version (default "8.6.2")

Global Flags:
  -p, --profile string   select a profile to use for the stack configuration. Can also be set with ELASTIC_PACKAGE_PROFILE
  -v, --verbose          verbose mode
```

ここにあるように`-d`オプションをつけて起動するとdaemonで起動します。その場合には以下のコマンドで停止できます。

```sh
$ elastic-package stack down
```

これで好きな時に好きなバージョンのElastic Stackが起動できていつでもテストできますね！

# 制限

`elasticsearch.yml`や`kibana.yml`のような設定ファイルをカスタマイズする方法は用意されていません。設定周りの動作確認のために利用するのは難しそうです。
AWS Systems Managerの基本

AWS　Systems Managerについてまとめてみました。

一言でいうと、
オンプレミスまたはマルチクラウド(複数のクラウドサービスを使っている環境のこと）上に構築されたアプリやリソースを丸っと管理してくれるソリューション。

AWS System Managerのパラメータストアに各種ライセンスコードなどをセキュアに保管しておける。
標準パラメータと詳細パラメータがあり、標準だと10,000個を無料で登録できる。
KMSキーで暗号化も可能。

データベースの接続情報もパラメータストアに登録しておけばいいじゃん？と一瞬思うが、認証情報をローテーションさせたい場合もあるので、その場合はSecrets Managerを使う。

さらにS3にライセンキー登録するのはどうか？保存自体はできるが、運用のオーバーヘッドが問題になる。どのライセンスをどのS3バケットに保存したのか、プログラムでS3オブジェクトを読み取る処理を書かないといけないなど。
FarmRPG　Unity Inventory&Item まとめ　Part1 ~ Part11

# 参考
Section 7 Inventory & Items

https://www.udemy.com/course/unity-2d-game-developer-course-farming-rpg/learn/lecture/19849066#content


# 一覧

## Part1　1/2 　InvnetoryManager ScritableObjectのデータを読み込む
https://qiita.com/RYA234/items/f9bf6320af23996be9d1

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/3e5e8949-7605-1fac-fee8-b12de904f07b.png)

## Part2  2/2 InventoryManager  playerがItemに接触したときの処理を実装

https://qiita.com/RYA234/items/a273f9662c9d3003e1a4

![ffffffffffffdsafdasnjlkljllkklll.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/b042abc0-bd96-e2a5-30de-7f0cc288603b.gif)


## Part3 　1/2 インベントリにアイテムを加える　インベントリにそのアイテムがない場合

https://qiita.com/RYA234/items/4219155ad4a16e788328

![ffffffffffffdsafdasnjlkljllkklllnmn.,mn.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/40164697-73eb-d50a-0bda-d7e00bb3641f.gif)


## Part4 　2/2 インベントリにアイテムを加える　インベントリにアイテムが既にある場合

https://qiita.com/RYA234/items/7fcf866ffb8380fe2d1c

![ffffffffffffdsafdasnjlklj.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/fdc147b4-7ab2-8880-37c2-4fd59602a6fc.gif)

## Part5 InventoryをuGUIで作成する

https://qiita.com/RYA234/items/56bd6b6b4eb06e38b38c

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/44cac849-38eb-7345-06ec-5d291497e184.png)


## Part6 Inventoryの情報をUIに反映 オブサーバーパターンを使用

https://qiita.com/RYA234/items/ade3d2487739f06d1a3f

![0601.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/b94c8eca-4e2f-0dfa-b849-b915bdb06064.gif)


## Part7 1/2 インベントリのアイテムをドラッグ　ドラッグ中アイテムがマウスが追従する

https://qiita.com/RYA234/items/2fc460dd1da83aa2f9ed

![0602.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/c9f03d10-9be6-5092-18bf-1b973af3c6f1.gif)


## Part8 2/2 ドラッグ終了時の処理を追加

https://qiita.com/RYA234/items/08113e60243e84f6b8df

![0603.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/e82b89b0-577c-eec9-bf80-13e74ff20648.gif)

## Part9 inventorySlotのアイテムを交換

https://qiita.com/RYA234/items/73d2be77bf5453e4bca0

![0604.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/939a34b4-aaf3-cfce-9059-219df336f38d.gif)


## Part10 InvenotrySlotにカーソルを合わせると説明欄を表示する

https://qiita.com/RYA234/items/7e6044d45ab6a6a14a97

![0605.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/17ce5ade-7801-3275-01eb-0d2b1c6e0387.gif)


## Part11 　InventorySlotのハイライト線（赤線）を表示

https://qiita.com/RYA234/items/b977ebb9480381423c2c

![0606.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/ea6bc11f-f78b-de48-6991-3f49d0c0f779.gif)
Doctrine のインストールからマイグレーションまで（Symfony 5.4）

この記事は、以下の環境で動作確認しています。

```
OS: macOS Venture 13.3.1
Chip: Apple M1 Pro
PHP: 8.1.19
Symfony: 5.4.24
```

### 参考
以下の公式ドキュメントを参考にしています。

https://symfony.com/doc/5.4/doctrine.html

### Doctrineのインストール

まずは以下を実行。
```shell
symfony composer require symfony/orm-pack
```

環境によって、依存パッケージのエラーが出力される可能性があります。
> Your requirements could not be resolved to an installable set of packages.

各パッケージに必要なバージョンを探索してくれるように`--with-all-dependencies`のオプションを付与します。

```shell
symfony composer require symfony/orm-pack --with-all-dependencies
```

### MakerBundleのインストール
```shell
symfony composer require --dev symfony/maker-bundle
```

### Databaseの構成

`symfony/orm-pack`をインストールすると、おそらく`docker-compose.yml`ファイルが自動生成されています。（なければ作成する必要あり。）

デフォルトで`postgres`の構成で記述されているので`POSTGRES_USER`と`POSTGRES_PASSWORD`のみ任意の値に変更して起動します。

```yaml
# docker-compose.yml
version: "3"

services:
  database:
    image: postgres:${POSTGRES_VERSION:-15}-alpine
    environment:
      POSTGRES_DB: ${POSTGRES_DB:-app}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password}
      POSTGRES_USER: ${POSTGRES_USER:-user}
    volumes:
      - database_data:/var/lib/postgresql/data:rw

volumes:
  database_data:
```

[ドキュメント](https://symfony.com/doc/5.4/doctrine.html#configuring-the-database)に記載のように、`.env`ファイルも忘れず修正します。
```env
DATABASE_URL="postgresql://user:password@127.0.0.1:5432/app?serverVersion=15&charset=utf8"
```

コンテナを起動します。
```shell
docker-compose up -d
```

### Databaseの作成

Databaseを作成します。

```shell
symfony php bin/console doctrine:database:create
```

ただし、`docker-compose up`のタイミングで作成済みの為かエラーが出力されます。
> An exception occurred while executing a query: SQLSTATE[42P04]: Duplicate database: 7 ERROR:  database "app" already exists

以下コマンドで確認すると、確かに作成されてそう！
```shell
docker exec -it container_id psql -U database_user database
```

問題なさそうなので、Entityの作成に進みます。

### Entityクラスの作成

ここはドキュメントに沿ってコマンドを実行し、各設定値もドキュメントに従います。
```shell
symfony php bin/console make:entity
```

### マイグレーションファイルの生成と実行

```shell
symfony php bin/console make:migration
```

上記コマンドでマイグレーションファイルが生成されるので、つづけて実行します。

```shell
symfony php bin/console doctrine:migrations:migrate
```
> [OK] Successfully migrated to version : DoctrineMigrations\VersionXXX

テーブルが作成できたはずなので、確認します。

```shell
docker exec -it container_id psql -U database_user database
```
もう一度、コンテナに接続して、`\dt`や`\d product`を実行すると確かに想定通りのテーブルが生成されています。

| Column | Type | Collation | Nullable | Default |
| --- | --- | --- | --- | --- |
 id     | integer                |           | not null |
 name   | character varying(255) |           | not null |
 price  | integer                |           | not null |

### まとめ

テーブル定義に変更があった場合でも、以下の流れは変わりません。
- Entityクラスの作成
- マイグレーションファイルの作成
- マイグレーション実行

コマンドベースでは以下の順序です。
```shell
# 1: Entityクラスの作成
symfony php bin/console make:entity

# 2: マイグレーションファイルの作成
symfony php bin/console make:migration

# 3: マイグレーション実行
symfony php bin/console doctrine:migrations:migrate
```
【Amazon ECR】AWS CLI を使ってリポジトリへプッシュする

タイトルのとおり、ECRリポジトリにCLIでプッシュする方法です。
「ブラウザ上のGUIでイメージ選択してアップロード」みたいなことは出来ないので、コマンド実行して作業する必要があります。最初はマネジメントコンソール上で簡単にできるものだと思っていました。。。

## IAMユーザー・アクセスキーを用意する
ECRリポジトリにプッシュするため、リポジトリ更新権限を持つユーザーが必要です。
なければ以下の手順で作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3412108/e2e2d0d1-96c1-1ca8-304f-102f8012ff5a.png)

許可のオプション：ポリシーを直接アタッチ
許可ポリシー：AmazonElasticContainerRegistryPublicFullAccess
　　　　　　　※更新権限があればよいので PowerUser でもOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3412108/ed068c9e-f3df-dca2-0c53-4e43e330c9ad.png)

AWSに接続するための認証情報（アクセスキー・シークレットアクセスキー）を取得します。
ユースケース：その他
タグ：分かれば何でもOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3412108/3759dff8-b8fd-9fb6-1dd2-2b764dfd3d47.png)

作成されたアクセスキー・シークレットアクセスキーをコピーして控えておく
※後述のECRリポジトリへのプッシュ設定時に使用します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3412108/79ca1b46-1699-17f3-f94e-639618c7ded9.png)

## Amazon CLI インストール
以下のページから CLI をダウンロードしてインストールします。
https://aws.amazon.com/jp/cli/


CLI を使って先ほど取得した認証情報を設定します。
```shell
$ aws configure --profile {任意のプロファイル名}
AWS Access Key ID [None]: {アクセスキー}
AWS Secret Access Key [None]: {シークレットアクセスキー}
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

## ECRリポジトリにプッシュ

マネジメントコンソール上でプッシュに必要なコマンドを表示・取得する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3412108/312db5ce-0293-6eb8-248d-cda6fb3156c4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3412108/5853e952-b09d-9207-0f84-6069531b30c3.png)

先ほど設定した認証情報を使って AWS にログイン
```shell
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ********.dkr.ecr.ap-northeast-1.amazonaws.com
```
　
以下のように表示されたら成功
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3412108/97051d08-b8a7-c5dc-cd5b-641a3bd643c9.png) 


イメージのビルド・タグ付け
--no-cachでキャッシュを使用しない
※イメージ名：rails7-mysql で書いていますが、適宜置き換えてください。
```shell
$ docker build --no-cash -t rails7-mysql .
$ docker tag rails7-mysql:latest ********.dkr.ecr.ap-northeast-1.amazonaws.com/rails7-mysql:latest
```
　
ECR にプッシュ
```shell
$ docker push ********.dkr.ecr.ap-northeast-1.amazonaws.com/rails7-mysql:latest
```
※認証情報の有効期限(30日)が切れるとプッシュ時にエラーとなるので、再度上述のログインコマンドを実行する
FarmRPG　Unity Inventory&Item Part5 InventoryをuGUIで作成する

# 概要
今回はインベントリバーをUnityEditor上で実装します。
以下実装後の様子です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/44cac849-38eb-7345-06ec-5d291497e184.png)


# 開発環境

IDE:Rider
Unity:2020.3.42(LTS)
OS:Windows10

# UnityEditor上の設定

## UIInventoryBarを作成

### MainGameUICanvas UIの表示と当たり判定をつけるため
UIの表示:Canvasコンポーネント
当たり判定:Graphic Raycaster コンポーネント


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/4fbee427-92cc-5295-6043-17a42e345e94.png)




### UICanvasGroups　 子オブジェクトにUIを設置
後に実装する時間のUIなども実装します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/e82903a7-5d90-55cd-c236-7e3c37b30a9a.png)


### UIInventoryBar インベントリバーの画像を定義

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/686d4a61-64c8-0614-a82a-fb5c2458d669.png)




## inventorySlotのプレハブを作成

### UIInventorySlot　位置サイズの定義 アイテムの画像を表示するため
RectTransform


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/71fded00-ae88-7b54-46b8-ece02ac5b137.png)


### InventorytHighlight スロットを選択時に赤枠の強調線を表示する
通常はImageの透過度を0にして見えないようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/4de96118-839d-b1d8-899e-7ed426d403e0.png)



### Text　アイテムの個数を表示
アイテムの個数を表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/08f0b506-65eb-348c-c1e6-6d5dfadc1478.png)


# 実装のポイント
スクリプトの追加は無し

# 参考

## C#

## Unity Editor コンポーネント

### RectTransform コンポーネント

https://docs.unity3d.com/ja/2019.4/Manual/class-RectTransform.html

### Canvas Renderer

https://docs.unity3d.com/ja/2019.4/Manual/class-CanvasRenderer.html

Imageコンポーネントとセットになっている印象

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/3f512e10-6fac-a61c-4041-3e3c8ce176ba.png)


### Graphic Raycaster

https://docs.unity3d.com/ja/2019.4/Manual/script-GraphicRaycaster.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/a2cac912-41b7-2e90-4b0c-1df26503fc3c.png)


### Aspect Ratio Fitter

https://docs.unity3d.com/ja/2019.4/Manual/script-AspectRatioFitter.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/3f9e2756-066c-c20c-02eb-7357341c19c6.png)


### Canvas Group

https://docs.unity3d.com/ja/2018.4/Manual/class-CanvasGroup.html

### Canvas

https://docs.unity3d.com/ja/2019.4/Manual/class-Canvas.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/584ca0a3-f38f-8a05-e418-4de3558b7f05.png)

## Unity スクリプト

## その他

Section7 27


github コミット分（個人確認用　privateなので見れません）

https://github.com/RYA234/LearnFarmRPG/commit/1a2fdc4228d41792d06824be92b51d307e4c35a3

https://github.com/RYA234/LearnFarmRPG/commit/9a642a88cf74325e179c6f96e2af8712e2756010
FarmRPG　Unity Inventory&Item Part1　1/2 　InvnetoryManager ScritableObjectのデータを読み込む

# 概要
今回はItemのScriptableObjectのデータを読み込むInventoryManagerクラスを作成します。

インスペクター上では確認できないのでRiderのデバッグ画面で読み込みを確認
Startメソッドの終了時点を見ています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/3e5e8949-7605-1fac-fee8-b12de904f07b.png)





# 開発環境

IDE:Rider
Unity:2020.3.42(LTS)
OS:Windows10

# UnityEditor上の設定
新規オブジェクトInventoryManagerを作成して　InventoryManagerスクリプトをアタッチします。
itemListの引数はScriptableObjectを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/aa6df86b-231e-5762-d7ea-013788115707.png)


# コード部分

## InventoryManager

```diff_c_sharp:InventoryManager.cs
using System.Collections.Generic;
using UnityEngine;


public class InventoryManager : SingletonMonobehaviour<InventoryManager>
{
    private Dictionary<int, ItemDetails> itemDetailDictionary;
    [SerializeField] private SO_ItemList itemList = null;

    private void Start()
    {
        CreateItemDetailsDictionary();
    }

    private void CreateItemDetailsDictionary()
    {
        itemDetailDictionary = new Dictionary<int, ItemDetails>();

        foreach (ItemDetails itemDetails in itemList.itemDetails)
        {
            itemDetailDictionary.Add(itemDetails.itemCode,itemDetails);
        }
    }
}


```

## SO_ItemList

```diff_c_sharp:SO_ItemList.cs
[CreateAssetMenu(fileName = "so_ItemList", menuName = "Scritable Objects/Item/Item List")]
public class SO_ItemList : ScriptableObject
{
    [SerializeField]
    public List<ItemDetails> itemDetails;
    
}


```


## ItemDetail

```diff_c_sharp:ItemDetail.cs
using UnityEngine;

[System.Serializable]
public class ItemDetails
{
    public int itemCode;
    public ItemType itemType;
    public string itemDescription;
    public Sprite itemSprite;
    public string itemLongDescription;
    public short itemUseGridRadius;
    public float itemUseRadius; 
    public bool isStartingItem;
    public bool canBePickedUp;
    public bool canBeDropped;
    public bool canBeEaten;
    public bool canBeCarried;
}



```







# 参考

## C#

### Dictionary<TKey,TValue> 

https://learn.microsoft.com/ja-jp/dotnet/api/system.collections.generic.dictionary-2.add?view=net-7.0

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/e689dd18-a920-e36d-56eb-d385e5037ae9.png)


### Dictionary<TKey,TValue>.Add(TKey, TValue)

https://learn.microsoft.com/ja-jp/dotnet/api/system.collections.generic.dictionary-2.add?view=net-7.0

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/ef203fb6-a4b3-6221-6fd5-943205915487.png)


## Unity Editor コンポーネント

## Unity スクリプト

## その他

Section7 22


github コミット分（個人確認用　privateなので見れません）

https://github.com/RYA234/LearnFarmRPG/commit/994b41379983a7f6f161a3c98efa0290486f0907
macでterraformがマルウェア判定されてしまう

## 経緯
terraformコマンドを実行したら以下が表示された
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298811/a863f76c-ec52-7d25-fa68-1c37a73191fa.png)

## 対策

terraformを一度アンインストールして再度インストールする

自分の場合はtfenvで管理してたので以下の手順でterraformコマンドを入れ直した
1. `tfenv uninstall x.x.x(terraformコマンドのバージョン)`
1. `tfenv install x.x.x(terraformコマンドのバージョン)`
Mayaを起動するとOneDriveに「hL g」フォルダが作られ画面が点滅する

Maya起動時にXGenプラグインが読み込まれ、XGenプラグインがフォルダを作成します。
OneDriveを使用していると、ドキュメントのパスに日本語が含まれるためフォルダ作成時に文字化けし、OneDriveが扱えないフォルダ名になってしまい、エクスプローラがクラッシュ→再起動、を繰り返し画面が点滅しているのだと思います。

画面が点滅し始めるとエクスプローラがクラッシュするので、Windowsの操作がほとんどできなくなります。Ctrl+Alt+Delでタスクマネージャーを起動してOneDriveのタスクを終了します。
画面の点滅が無くなり、Windowsの操作もできるようになります。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52118/81744764-e174-5110-a1d8-5f43f8c5d42b.png)
OneDriveにある「hL g」フォルダを削除しましょう。
![22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52118/2f622996-fa4f-ebe6-596a-515f7c2eb0c6.png)
「hL g」フォルダの文字列をバイナリエディタで確認したところ、このような値になっていました。おそらく文字化けしています。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52118/d11867be-7935-c8c9-935c-bdb780eb3a1d.png)

# 解決策１：OneDriveでドキュメントフォルダを同期させない
ドキュメントフォルダの同期を外せば、この問題が起きなくなります。

# 解決策2：XGenプラグインの自動ロードをOFFにする
「hL g」フォルダはXGenプラグインが作成するので、プラグインをOFFにすれば大丈夫です。
XGenを使用しないのであれば、この方法でも良いでしょう。
1. プラグインマネージャを開き
![33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52118/21fa64ab-7a3e-d095-9a9f-d711d7d53766.png)
2. XGenプラグインのロードのチェックをOFFにします。
![44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52118/995474ae-3204-df36-b922-e34c0b79b09e.png)

# 解決策3：環境変数「HOME」を設定する
XGenプラグインを見てみると、xgGlobal.pyのinitXGen関数内でフォルダを作成していました。
この時に渡されるパス（xgen.XgExternalAPI.userRepo()で取得）が文字化けしているようです。
C:\Program Files\Autodesk\Maya2024\plug-ins\xgen\scripts\xgenm\xgGlobal.py
![130.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52118/135602c6-8ee1-def5-5c15-f1030dc42669.png)
「XGen userRepo」で検索してみると、userRepoは環境変数HOMEを使用しているようです。
https://help.autodesk.com/view/MAYAUL/2024/JPN/?guid=GUID-6ED517C7-7346-4A6E-A9CF-37D2B8511C36
OneDriveを使用するとHOMEに日本語の文字列が含まれてしまうので、別の場所に設定しましょう。

環境変数の設定方法はいくつかありますので、お好きな方法で設定してください。
この例では、あらかじめCドライブに「maya_home」フォルダを作成しています。

## 1. Mayaをバッチファイルから起動する場合
Mayaを起動する前に、環境変数HOMEを設定します。
```bat
set HOME=c:\maya_home
"C:\Program Files\Autodesk\Maya2024\bin\maya.exe"
```

## 2. userSetup.melで設定する
scriptsフォルダにuserSetup.melファイルを置くと、Maya起動時にMelスクリプトを実行できます。
![101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52118/7ccc8272-7eab-4e1b-9b24-c2b253de43b1.png)
userSetup.melで環境変数を設定します。
```userSetup.mel
putenv "HOME" "c:/maya_home";
```

## 3. userSetup.pyで設定する
scriptsフォルダにuserSetup.pyファイルを置くと、Maya起動時にPythonスクリプトを実行できます。
![100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52118/3c0934f6-d4e2-2761-2434-3137d0b0a469.png)
userSetup.pyで環境変数を設定します。
```python:userSetup.py
import maya.mel as mel

mel.eval('putenv "HOME" "c:/maya_home"')
```

## 4. Windowsの環境変数を設定する
「新規」ボタンで、新しいユーザー変数を作成します。
WindowsもこのHOMEを使用しているので、ご注意ください。
![131.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52118/cd3d0996-d124-f986-d1e2-fbe9c2456b53.png)
Ubuntuで環境変数とエスケープ文字でプロキシ認証を行う

# 一般ユーザーへのプロキシ認証設定
プロキシ認証はお好きですか？　<b>俺は大嫌いだ。</b>
社内プロキシとの戦いは終わりません。
前回は`apt`コマンド単体に対するプロキシ認証方法についてでした。

https://qiita.com/kztktr/items/3a68b8754e99bb3f8e0e

当たり前ですが、`apt.conf.d`で設定したプロキシ認証は`apt`コマンドに対してのみ機能するので、`curl`や`pip`といった一般ユーザー状態で他のインターネットへのアクセスを伴うコマンドには機能しません。
というわけで今回は一般ユーザーの環境変数からプロキシ認証を行っていきます。
また、その際にプロキシ認証のパスワードに記号を使っている際の注意点も提示します。

# 環境
Ubuntu.20.04 LTS
プロキシサーバーを経由する際はパスワードによるユーザー認証を要求する

# 手順
* `printenv`で現状の環境変数を出力し、proxyに関する記述が無いことを確認します。
```
$ printenv
```

* `~/.bashrc`または`~/.zshrc`に以下の記述を追記。今回はbashrcにやっていきます。
```
$ cp ~/.bashrc ~/.bashrc_org #念のためバックアップ
$ vim ~/.bashrc
--------------------------------------------------------
# http://<id>:<password>@X.X.X.X:<port番号>
_PROXY=<プロキシURL>

# httpおよびhttpsを使う際に参照するプロキシのURLをexport
export http_proxy=${_PROXY}
export https_proxy=${_PROXY}

# localhostなどの、プロキシを経由しない社内ネットワークなどのアドレス
export no_proxy=localhost,127.0.0.1

unset _PROXY
```
`_PROXY`で定義したプロキシURLを`${_PROXY}`に渡していることになります。
また開発などでlocalhostを使用している際には、`no_proxy`でプロキシを経由しない設定を行う必要があります。
<b>「Apacheのlocalhost:xxxxが出てこないんだけど！？」</b>と私はここでハマりました。

* `source`コマンドで設定を読み込ませます。
```
$ source ~/.bashrc
```
* あとは`printenv`でproxyに関する記述があるか確認したり、`wget`や`curl`がインターネットに届くかを確認してください。

# パスワードに記号を使ってる際の注意点
もうひとつのハマったポイントです。
どこの職場とかでも、「パスワードは大文字小文字の英数字と記号で◯文字以上」といったセキュリティルールがあると思いますが、その際には<b>記号の前にエスケープ文字を差し挟む必要があります。</b>
例えば、下記のパスワードでexportからプロキシ認証を行おうとしても、エラーが出ます。
```
パスワード例：Hogehoge1234!
$ export http_proxy=http://<ユーザー名>:Hogehoge1234!@x.x.x.x:<port番号>
-bash: !@x.x.x.x: even not found
```
これは、パスワードの中にある`!`が文字列ではなく、`history`コマンドのオプションとして機能しているためによるものです。
このため、`!`や`"`といった、シェル上では何らかの機能を持つ記号を文字列として認識させる際はその文字の前に`\`バックスラッシュ(windowsの日本語環境なら`¥`)といった<b>エスケープ文字</b>を差し込む必要があります。

というわけで、パスワードが「Hogehoge1234!」なら、`export`コマンドは下記のように記述する必要があります。
```
$ export http_proxy=http://<ユーザー名>:Hogehoge1234\!@x.x.x.x:<port番号>
```
これで、一般ユーザー状態で用いるコマンドのほとんどはインターネットへ到達すると思います。
また、ユーザー名とパスワードに関しては平文で保存されるので、設定を記述したファイルはパーミッションでアクセスを制限するなどの措置を取ってください。

# 参照サイト

https://shogo82148.github.io/blog/2012/04/09/no-proxy/
RxSwiftを学ぶ③BehaviorRelayについて

## はじめに
前回はSubjectの3種類について書きました。
今回は、BehaviorRelayについて書きたいと思います。
なぜBehaviorRelayについて書こうかと思ったかというと、KodecoのRxSwiftを学ぶページ(
[Getting Started With RxSwift and RxCocoa](https://www.kodeco.com/1228891-getting-started-with-rxswift-and-rxcocoa))でいきなりBehaviorRelayが出てきたからです。この手順通りにやると、確かにModelの変更が即座にViewに反映するようになるのですが、なぜBehaviorRelayなのか、どういった機能を持っているのかがわからなかったので、調べました。

## BehaviorRelayについて
前回行ったSubjectと違い、BehaviorRelayはRxSwiftではなくRxCocoaで提供されています。

### 特徴
・BehaviorSubjectの一部をラッパーしている(挙動はBehaviorSubjectに似ている？)
・エラーやコンプリートで終了しない
・外部から直接値の変更を防ぐため、asObservableというメソッドで読み取り専用のObservableを生成する
・valueプロパティを持つ
・valueプロパティの変更にはacceptメソッドを使用

まだあるかもしれませんが、とりあえず主要な特徴を書いてみました。
ざっくりメリットをいうと、エラーや完了イベントを発行しないので、使用場面は選ぶ必要があると思いますがエラーハンドリングの必要もなく、常にデータの変更を観察し続けられること。
オブザーバーには読み取り専用のObservableを渡すので、予期せず値が変更されることを防ぐことができることなどが挙げられると思います。
特にUIの更新などに適していると思われます。

```swift
let relay = BehaviorRelay(value: "Initial value")
let observable = relay.asObservable()
observable.onNext("New value")  // エラー: 'onNext' is inaccessible due to 'internal' protection level
```

使い方は以下
```swift
let relay = BehaviorRelay(value: "Initial value")
  let subscription = relay.asObservable()
        .subscribe(onNext: { value in
            print(value)  // ここで初期値の"Initial value" が出力される
        })
    relay.accept("New value") // "New value"が通知される
    })
```

ちなみに、私はSubjectのシーケンスと混合してしまっていたのですが、
BehaviorRelayのvalueプロパティは値を保持しその変更を通知することができます。
なので上記サンプルのように文字列単体を入れることができますし、整数も配列も入れることが可能です。


## 最後に
ここまでRxSwiftを学んできて、大事なのは「何が」発生したときに「何を」すべきかを実装できる点だと思いました(個人の感想です)。RxSwiftの説明を最初に読むと、時間の流れがとか、シーケンスがといった説明が出てくるので最初かなり混乱しました。これらの説明はおそらく正確で正しく理解する必要があるかと思いますが、まずは「あるイベントが発生したときに何をすべきか」を実現できるものとして進めていくのが良いのではないかと思いました。

引き続きRxSwiftについて書いて行きたいと思います。

ここまで読んでくださりありがとうございます！
【LightGBM】lgb.trainメソッドで学習したモデルのPermutation Importanceの計算方法

# 概要
LightGBMで学習したモデルのPermutation Importanceを計測したい場合に
例えば
```python
model = lgb.LGBMRegressor(objective="regression")
gbm = model.fit(**params)
```
のように`fit`メソッドを使ってトレーニングを行えばPermutation Importanceを計算できるのですが
```python
model = lgb.train(params, lgb_train)
```
のように`train`メソッドを使った場合に、Permutation Importanceを計算すると以下のエラーが出る問題があります。
```
TypeError: estimator should be an estimator implementing 'fit' method,  was passed
```
本記事では、このエラーの対処方法を記載します。

# 起こる事象
サンプルとして、ボストンデータセットでLightGBMのモデルを作成します
```python
import lightgbm as lgb
import numpy as np
from lightgbm import LGBMRegressor
from sklearn import datasets
from sklearn.inspection import permutation_importance
from sklearn.model_selection import train_test_split

# データセットの読み込み
boston = datasets.load_boston()
X = boston.data
y = boston.target

# データセットの分割
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# LightGBMデータセットに変換
lgb_train = lgb.Dataset(X_train, y_train)
lgb_eval = lgb.Dataset(X_test, y_test, reference=lgb_train)

# パラメータ設定
params = {
    "boosting_type": "gbdt",
    "objective": "regression",
    "metric": "rmse",
}

# モデルの学習
model = lgb.train(
    params,
    lgb_train,
    num_boost_round=20,
    valid_sets=lgb_eval,
    early_stopping_rounds=5,
)
```

このモデルに対しPermutation Importanceを計算します
```python
result = permutation_importance(
    model,
    X_test,
    y_test,
    n_repeats=10,
    n_jobs=-1,
    random_state=0,
)
```
この時、以下のエラーが発生します
```python
TypeError: estimator should be an estimator implementing 'fit' method,  was passed
```
どうやら、fitメソッドを持つモデル（LGBMRegressorなど）にしかPermutation Importanceは対応していないため、モデルの形式を変換する必要がありそうです。

# 対処方法
以下の方法で計算できるようになります。
```python
regressor_model = LGBMRegressor()
regressor_model._Booster = model
regressor_model._n_features = X_test.shape[1]
regressor_model.fitted_ = True
```

改めてPermutation Importanceを計算します
```
result = permutation_importance(
    regressor_model,
    X_test,
    y_test,
    n_repeats=10,
    n_jobs=-1,
    random_state=0,
)
```
今度はエラーなくうまく行きました。
例えばoptunaのLightGBM Tunerを使った場合はtrainメソッドでしか学習ができないと思いますので、こちらの方法を採用すれば良いかと思います。
ちなみに、今回はscikit-learnのpermutation_importanceを利用しましたが、eli5でも同様のエラーは発生するため、同様の対処が必要になります。
列が`MultiIndex`でかつ重複しているDataFrameで、`fillna`に重複している列を指定するとRecursionErrorが発生する

# 環境
* Python 3.11.2
* pandas 2.0.2
* numpy 1.24.2


# 何が起きたのか？
列が`MultiIndex`で、かつ列が重複しているDataFrameがあります。

```
In [194]: data = [[numpy.nan, 2, 3], [4, numpy.nan, 6], [7, 8, numpy.nan]]

In [195]: data
Out[195]: [[nan, 2, 3], [4, nan, 6], [7, 8, nan]]


In [196]: df = pandas.DataFrame(data, columns=pandas.MultiIndex.from_tuples([("x","a"),("x","a"),("y","b")]))

In [197]: df
Out[197]: 
     x         y
     a    a    b
0  NaN  2.0  3.0
1  4.0  NaN  6.0
2  7.0  8.0  NaN

In [198]: df.columns
Out[198]: 
MultiIndex([('x', 'a'),
            ('x', 'a'),
            ('y', 'b')],
           )

```

[pandas.DataFrame.fillna](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.fillna.html)で欠損値を0で埋めます。
重複している列`("x","a")`を指定すると、RecursionErrorが発生しました。
```
In [256]: df.fillna({("y","b"): 0})
Out[256]: 
     x         y
     a    a    b
0  NaN  2.0  3.0
1  4.0  NaN  6.0
2  7.0  8.0  0.0

In [257]: df.fillna({("x","a"): 0})
# 数分経った後にRecursionError発生
...
RecursionError: maximum recursion depth exceeded while calling a Python object
```


# 検証したこと

## `fillna`で`inplace=True`を指定する
`inplace=True`を指定すれば、問題なく実行できました。

```
In [259]: df.fillna({("x","a"): 0}, inplace=True)

In [260]: df
Out[260]: 
     x         y
     a    a    b
0  0.0  2.0  3.0
1  4.0  0.0  6.0
2  7.0  8.0  NaN
```


## 列が`Index`の場合
列が`MultiIndex`ではなく`Index`であるDataFrameで検証しました。

```
In [261]: df2 = pandas.DataFrame(data, columns=["a","a","b"])

In [263]: df2
Out[263]: 
     a    a    b
0  NaN  2.0  3.0
1  4.0  NaN  6.0
2  7.0  8.0  NaN

In [264]: df2.columns
Out[264]: Index(['a', 'a', 'b'], dtype='object')

```

問題なく実行できました。

```
In [265]: df2.fillna({"b":0})
Out[265]: 
     a    a    b
0  NaN  2.0  3.0
1  4.0  NaN  6.0
2  7.0  8.0  0.0

In [266]: df2.fillna({"a":0})
Out[266]: 
     a    a    b
0  0.0  2.0  3.0
1  4.0  0.0  6.0
2  7.0  8.0  NaN
```


# 補足
issueを作成しました。

https://github.com/pandas-dev/pandas/issues/53498
AWS　SAA勉強記録

◎リージョンとアベイラビリティーゾーン

１リージョン
　→AWSがサービスを提供している拠点（国とか地域）

２アベイラビリティーゾーン（AZ)
　→複数のデータセンター

■関係性
複数のデーターセンターがAZを構成し、複数のAZが集まったものがリージョンとなる

※AZ間のネットワークレイテンシは２ミリ秒以下
※１箇所の停電でAZ内のすべてのデータセンタが一斉にダウンすることはない設計

◎マルチAZによる可用性

可用性を高めるためには、複数のAZを利用してシステムを構築する。→マルチAZと呼ぶ
週一でPython勉強会やってみる⑦

前回の続き

https://qiita.com/Waddy675/items/c56b2e67eac80cf34285

6月になり、新人さん達をプログラミング勉強会に ~~（強制）~~ 参加してみたり・・・（パワハラにならないかビクビク

参考書によると今回は前回の復習も兼ねてエクセルを操作するタスク回でした。

## おさらい
年齢適応表？的なものを作れという指示だったのでサクッと。
他のメンバーはコツを掴みつつあるのかパッとできた人と、色々調べながらちょっとずつ進む人とまちまち（2人しかいないけどね！）
```py
import openpyxl as excel
import datetime

book = excel.Workbook()

sheet = book.active

# 2023年ベタでも可
this_year = datetime.date.today().year
print(this_year)

for i in range(121):
  sheet.cell(row=i + 1, column= 1, value=str(i) + "才")
  sheet.cell(row=i + 1, column= 2, value=str(this_year - i) + "年")

book.save("test-year.xlsx")
```
かなりあっさりだったので、二重ループの問題「A1:Z10の各セルに応じて『A1』と座標を入力したエクセルを作りなさい」と問題追加。
案の定どっちがどっちか分からなくなりパニックな模様。（しめしめ
そして宿題として「行ごとに値を出力する」を追加して終了。

## Unit Testの話
別件でPythonでUnitTestを書くという勉強会があったので喜んで参加。
モックを使うのはいいものの、初期化をテスト毎にできないのだろうか？
引数に追加する必要がでてきたり、何かしら面倒が増えるとのことだったが。。。
絶対解決策あるはず！（探す余裕があれば

ついでにGoogleコラボラトリーでやってやるかということで書いてみたところ、結論はうまくできた。
ただ、実行のところでmainの引数がなかったことによりエラーが出ていた。
```py
if __name__ == "__main__":
  unittest.main(argv=['first-arg-is-ignored'], exit=False)
```
ググるとカーネルプロセスがどうたらということらしい。。。
コラボラトリー環境がどうなってるのか分からないまま使っているのでいかんなぁ・・・

UnitTestはTDDやるならガンガン書いてこう！
UbuntuのGUI環境にPython + GOの環境を爆速で構築

## 目的

https://qiita.com/engishoma/items/dc85fad6fd30f7a67381



前回の記事ではUbuntuのGUI環境にPythonの環境を用意した。
用意したと言ってもpipをインストールするだけだったので、今回はGOの環境も追加しようと思う

## TL;DL
```
version: '3.3'
services:
    docker-ubuntu-desktop:
        ports:
           - '6080:6080'
        image: shomaigu/guiubuntugopy:latest
        container_name: 'guiubuntupy'
        working_dir: /root/Desktop
        volumes:
           - ./work:/root/Desktop
```
```
docker-compose up
```
アクセス
- http://localhost:6080/vnc_auto.html

## 自分でビルドする場合
```docker-compose.yml
version: '3.3'
services:
    docker-ubuntu-desktop:
        ports:
           - '6080:6080'
        build: .
        container_name: 'guiubuntupy'
        working_dir: /root/Desktop
        volumes:
           - ./work:/root/Desktop
```

```dockerfile
FROM akarita/docker-ubuntu-desktop
RUN apt-get -y update && apt-get -y install python3-pip nano
RUN wget https://go.dev/dl/go1.20.4.linux-amd64.tar.gz
RUN mkdir -p /usr/local/go/bin
RUN tar -C /usr/local -xzf go1.20.4.linux-amd64.tar.gz
ENV PATH $PATH:/usr/local/go/bin
```

```
docker-compose up
```

## 前回のDockerfile
このDockerfileをGoも動く様にする。
```
FROM akarita/docker-ubuntu-desktop
RUN apt-get -y update && apt-get -y install python3-pip nano
```

## Go構築

aptで入れてしまうと、更新が遅い場合があるため、今回はソースからインストールしていく。
#### 最新版の検索
以下のサイトにアクセスして、最新版のURLを手に入れる
https://go.dev/dl/

```
FROM akarita/docker-ubuntu-desktop
RUN apt-get -y update && apt-get -y install python3-pip nano
RUN wget https://go.dev/dl/go1.20.4.linux-amd64.tar.gz
RUN mkdir -p /usr/local/go/bin
RUN tar -C /usr/local -xzf go1.20.4.linux-amd64.tar.gz
ENV PATH $PATH:/usr/local/go/bin
```

ビルド・起動
```
docker-compose build
docker-compose up
```


## go確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738475/9a33af22-a558-a9dc-3b21-7b40c711761e.png)


## python確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738475/d743d9cd-8522-2b2c-10a4-c8fbf643df60.png)
Flutterの環境構築

## はじめに

こんにちは！ 
今回はFlutterの環境構築について書こうと思います。


## 構築環境&手順

・macbook pro


##### HomeBrewインストール
HomebrewはmacOS向けのオープンソースのパッケージ管理システムであり、ターミナルを通じてソフトウェアパッケージのインストール、アップデート、管理できます。Homebrewを使うためには、まずmacOSにHomebrewをインストールし、コマンドラインからパッケージを検索してインストールできます。また、パッケージのアップデートやアップグレードも可能であり、バージョン管理もサポートしています。Homebrewは、macOS上でのソフトウェアパッケージ管理を簡素化する便利なツールです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391664/7a8721d8-47b9-ae04-8028-ca0cf13198b0.png)

https://brew.sh/

上記のリンクてhomebrew手順に従い、インストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391664/e465fa75-a5ee-8b20-47ef-04b49f1bedfc.png)


##### flutterインストール


```shell
$ brew install --cask flutter
```
上記のコマンドラインをコピペしてインストールをする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391664/7f5b4e56-ee46-9e19-4951-b05e8f8c5a9b.png)


上記以外にandroid emulatorとかxcodeインストールはネットで検索すると色々出ると思います。

インストールが終わった後、flutter docterでインストール状況を確認すること。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391664/699e44b2-e57c-4446-b604-0eaee1b67bc7.png)

> 参照リンク: https://docs.flutter.dev/get-started/install/macos


##### flutterインストール以外に
flutterコードを作成することができる「datrpad」があるらしい。
単純にコード作成だけしたい場合、使えば良いかと思います。

・https://dartpad.dev/?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391664/6b84c887-33b5-1238-d2ca-0fafc33ca236.png)


##### ターミナルでflutterプロジェクトを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391664/96ebfcd7-a282-a473-a314-24442a84972b.png)

※ プロジェクト作成後、確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391664/48eb875c-b798-4b54-8458-43f75cbf9da9.png)


##### visual studio codeで確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391664/8e09066b-3713-af72-a161-ccb0cc03cbfd.png)

##### ※ visual studio codeで必要なextenstionをインストールする
・Dart
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391664/a72cffed-66e1-4c21-2216-7ee2fcb56f95.png)
・Flutter
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391664/3c599b51-d028-397b-b674-395837838652.png)
vim操作まとめ

## はじめに
活用しきれていないvimの基本操作についてまとめます。
チートシートとして使用し、作業の効率化を図ることを目的としています。

## vimとは
- Vim（Vi IMproved）は、**テキストエディタ**の一種で、主にUnix系OSで使用される。
- VimはViエディタの互換性を保ちつつ、多くの機能や拡張性を追加したもの
- コマンドラインで起動でき、**テキストファイルの編集やプログラミングコードの記述**など、さまざまな用途に使用される。
- 通常は**コマンドモード、挿入モード、ビジュアルモード**の3つの主要なモードを持つ
- 非常にカスタマイズ性が高く、様々なプラグインや設定オプションを利用してエディタの機能を拡張することができる
- がっつり開発をするにはIDE（VSCodeやJetbrainsなど）が良いが、補助的にvimを使用することで効率化が図れる

### 3つのモード
- コマンドモード（Command mode）: エディタの初期モードであり、コマンドを入力してファイルの保存や移動、削除などの編集操作を行う
- 挿入モード（Insert mode）: テキストの挿入や編集を行うモードであり、キーボードの入力がそのままテキストとして挿入される。
- ビジュアルモード（Visual mode）: テキストの選択や範囲指定を行うモードであり、コピー・切り取り・貼り付けなどの操作を行うことができる



## vimの基本操作
### 環境
Windows 11 Home（wsl2）
Ubuntu 20.04 LTS
Cmnder

### カーソル移動などの基本操作
| コマンド | 動作 |
|:-:|:-:|
|vim   |起動   |
|i   |Insert Mode   |
|esc   |Normal Mode   |
|k   |↑に移動   |
|j   |↓に移動   |
|h   |←に移動   |
|l   |→移動   |
|:q!   |保存しないで編集終了   |


### ファイルの保存
| コマンド | 動作 |
|:-:|:-:|
|:w ファイル名   |名前を付けて保存   |
|:w   |上書き保存   |
|:q  |編集終了|
|:q!   |保存しないで編集終了   |
|:wq   |保存して終了   |
|i   |Insert mode   |
|a   |次の文字からInsert mode   |
|view   |Viewモードで起動   |

### 削除系の編集
| コマンド | 動作 |
|:-:|:-:|
|vim ./test.txt   |ファイル指定で開く   |
|i   |インサートモード   |
|a   |次の文字からInsert mode   |
|x   |１文字削除   |
|dd   |１行削除（コピー可能）   |
|dw   |単語削除   |
|2 dd  |２行削除  |
|u   |Undo   |
|Ctrol + r   |Undo redo   |

### コピー＆ペースト
| コマンド | 動作 |
|:-:|:-:|
|yy   |一行コピー   |
|p   |下にペースト   |
|P   |現在行にペースト   |
|2 yy   |２行コピー   |
|.   |操作をリピート   |

### コマンドモードで実行する
| コマンド | 動作 |
|:-:|:-:|
|: or /   |Command mode|
|!python ./a.py(Command mode)   |コマンド実行|
|!!   |前のコマンドを実行|

### vimの移動
| コマンド | 動作 |
|:-:|:-:|
|:set number   |行番号を表示する   |
|:10   |10行名に移動   |
|$   |行末に移動   |
|0   |先頭に移動   |
|^   |インデントの先頭に移動   |
|{   |段落ごとに上に移動   |
|}   |段落ごとに下に移動   |
|[[   |セクションごとに上に移動   |
|]]   |セクションごとに下に移動   |
|:1 or gg   |ファイルの先頭に移動   |
|G   |ファイルの最後に移動   |
|ctrl + o   |移動前に戻る   |

### 検索と置換
| コマンド | 動作 |
|:-:|:-:|
|/{pattern} ex) /test   |検索（例はtestを検索している）   |
|n   | 次の検索結果に移動  |
|N   |  前の検索結果に移動 |
|R   | 置換  |
|dw   |  Rよりも単語削除をよく使うケースが多い |
|:%s/search/replace/g   |一括置換   |
|:%s/search/replace/gc   |確認しながら置換   |

### Visualモードやインデント
| コマンド | 動作 |
|:-:|:-:|
|o   |選択行の下に空白を入れ、インサートモード   |
|O  |選択行に空白を入れ、インサートモード   |
|J   |行の連結   |
|>   |右にインデントを移動   |
|<   |左にインデントを移動   |
|v (visual mode) 移動してからy   |カーソル指定コピー   |

### vimのコンフィグ設定
- vimの挙動を自動的に設定することが可能
- 下記のように、設定ファイルに適宜設定を記載する
```
// Neovimの場合は、vim ~/.config/nvim/init.vim
vim ~/.config/nvim/init.vim
```


| configファイルに記載する設定 | 説明 |
|:-:|:-:|
|set shell=/bin/zsh   |コマンドの際にはzshを使う   |
|set shiftwidth=4   |indentの幅   |
|set tabstop=4   |タブに変換されるサイズ   |
|set expandtab   |タブの入力の際にスペース   |
|set textwidth=0   |ワードラッピングなし   |
|set autoindent   |自動インデント※set pasteで解除可能   |
|set hisearch   |Searchのハイライト   |
|set clipboard=unnamed|クリップボードへの登録   |
|synatax on   |SuntaxをEnable   |

## 参考文献
[現役シリコンバレーエンジニアが教える NeoVim(VIM) + Tmux + Zsh 入門](https://www.udemy.com/course/vim-tmux-zsh/)
Spyderをコマンドでアップデートしてみた

# 前提条件
* Windows 10
* Anaconda3-2023.03-1
* Anaconda Navigator 2.4
* Python 3.10.9
* Spyder IDE 5.4.1

# 目的
Anaconda NavigatorからSpyderをアップデートしようとしたが、できなかったので、コマンドによりSpyderをアップデートする。

# コマンドによるSpyerのアップデート
Anaconda3は「C:\anaconda3」にあるとして話を進める。
```
C:\anaconda3\Scripts\conda install spyder=5.4.3
```
>Proceed ([y]/n)?と聞かれるので、yを入力する。
```
The following packages will be UPDATED:

  ipython                            8.10.0-py310haa95532_0 --> 8.12.0-py310haa95532_0
  jupyter_client                      7.3.4-py310haa95532_0 --> 8.1.0-py310haa95532_0
  spyder                              5.4.1-py310haa95532_0 --> 5.4.3-py310haa95532_0
  spyder-kernels                      2.4.1-py310haa95532_0 --> 2.4.3-py310haa95532_0
  tornado                               6.1-py310h2bbff1b_0 --> 6.2-py310h2bbff1b_0


Proceed ([y]/n)?y
```
Spyerを再起動し、Help→About SpyderからSpyderのバージョンが5.4.3となったことを確認する。
![spyer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32439/0a94deb3-6bc7-8215-2587-193c2a8038bb.png)

# コマンドによるAnacondaのすべてのパッケージのアップデート
```
C:\anaconda3\Scripts\conda update --all
```
>Proceed ([y]/n)?と聞かれるので、yを入力する。

参考資料

https://qiita.com/kerobot/items/917dc7027e15f5ff75ac

# 編集後記
下記の影響なのか、Anaconda NavigatorからSpyderのアップデートがGUIからできず、コマンドにより、アップデートした。備忘録として本稿を記した。

https://qiita.com/jinbei230525/items/0a5bb9e5f9d324bffe0d
新しい無料データ分析ツール、Vividata Desktopのご紹介！ 

こんにちは、データ分析を担当されているまたは興味を持っている皆さん！素晴らしいデータ分析ツールを見つけましたので、ご紹介します！その名は[<strong>Vividata Desktop</strong>](https://jp.vividatatech.com/vividata/)。無料で利用できる強力なツールで、興味がある方はぜひ試してみてください。以下にいくつかの特徴をご紹介します。

# ・ドラッグ＆ドロップで簡単レポート作成
煩雑な作業を軽減する優れたツールです。[<strong>Vividata Desktop</strong>](https://jp.vividatatech.com/vividata/)では、シンプルなドラッグ＆ドロップ操作でレポートを作成できます。もうレポート作成に悩まなくて済みますし、営業メンバーでもデータ処理が自由に行え、データ分析が全員参加型になります。皆さんがデータ分析のエキスパートになれます。

# ・豊富なグラフ表現で目を引くレポート
頭の中にある図形を完璧に再現します。美しい可視化表示、20以上のグラフ形式、組み合わせの工夫された配色スキームで、論理的な表現方法を見つけることができます。ワンクリックで見栄えの良いレポートを作成し、PPTやPDF等にエクスポートして報告資料として使用することもできます。

# ・無料で使いやすい
まず最初に、個人ユーザーにとって料金がかからないのは非常に良い点です。また、Vividata DesktopはAIデータマイニング、機械学習、予測、相関分析などの機能も備えています。

# ・すぐに利用可能
ローカルインストールベースのため、面倒なデプロイメントの手間が省けます。インストールしてすぐに使用でき、出張先や自宅でもデータ分析が行えます。

# ・強力な計算能力
小さなツールではありますが、高性能エンジンが組み込まれており、私が数十万件のデータを扱っても応答速度が非常に速いです。これは本当に素晴らしい点です。

# ・簡単にデータ分析を実現
さまざまなデータソースの統合、セルフサービスデータプレパレーション、可視化レポート作成を、1つのツールで簡単に行うことができます。洞察を得るためのデータ分析をスムーズに実現できます。

# ・最後
さらに、無料のツールに加えて、学習とコミュニケーションをサポートする[<strong>コミュニティ</strong>](https://jp.vividatatech.com/)もあります。初めて使用する際に分からないことがあれば、コミュニティで学ぶことができます。効率的に問題を解決し、簡単に始められます。

個人の学習や使用をお考えの方には、[<strong>Vividata Desktop</strong>](https://jp.vividatatech.com/vividata/)を強くお勧めします。無料で使いやすいです！
【Kotlin】スクロールの競合を解決する【Android Studio】

Kotlinを勉強している中で、`SwipeRefreshLayout`と`ScrollView`を同時に使用した際に、スクロールが競合してしまう現象が発生しました。
解決できたので、備忘録として記録しておきます。


# 結論
`ScrollView`を`NestedScrollView`に置き換えた。


# 経緯
冒頭で書いた通り、`SwipeRefreshLayout`と`ScrollView`を同時に使用した際に、スクロールが競合してしまいました。
`SwipeRefreshLayout`とか`ScrollView`ってなんや？という方は、ここでは省略させていただきますので、別途調べていただけると幸いです。

- 具体的に何が起きたか？
レイアウトの都合上、`SwipeRefreshLayout`の入れ子で`ScrollView`を配置していました。
ところが…
`ScrollView`の領域でも、上から下にスワイプをすると、`SwipeRefreshLayout`の機能のほうが優先されて動いてしまい、`ScrollView`のスクロールが一方通行になってしまっていました。


# 解決
ドラえもんよろしくChatGPTに泣きついたところ、
「`NestedScrollView`を使いなさい」
と教えてもらいました。

NestedScrollViewとは（以下ChatGPTより引用）

>`NestedScrollView`は、Androidのサポートライブラリの一部である`ScrollView`の拡張版です。`NestedScrollView`は内部的にネスト可能なスクロール動作をサポートしているため、複数のスクロール可能なビューが組み合わさっている（つまり、ネストされている）場合でも適切に動作します。これは特に、スクロール可能な子ビューが含まれる`CoordinatorLayout`などのコンテキストで便利です。

>`NestedScrollView`は以下のように使用します：
```
<androidx.core.widget.NestedScrollView      
      android:layout_width="match_parent"     
      android:layout_height="match_parent">

     <!-- Child views here --> 

</androidx.core.widget.NestedScrollView>`
```

>`NestedScrollView`は1つの直接の子ビューのみをサポートします。そのため、複数のビューをスクロールする必要がある場合は、それらのビューを`LinearLayout`や`RelativeLayout`などのビューグループに包む必要があります。

>`NestedScrollView`は、スクロールイベントを親ビューと共有することをサポートしているため、スクロールイベントに応じて他のビュー（例えば、`AppBarLayout`）の動作を変更したい場合に特に便利です。

>ただし、大量のビューまたは非常に大きなビュー階層をスクロール可能にする場合は、代わりに`RecyclerView`を使用することを検討してください。`RecyclerView`は、画面外のビューを再利用することでメモリ効率を大幅に向上させることができます。

====引用ここまで====

言われたと通り、`ScrollView`を`NestedScrollView`に置き換えてみると…

う、動く！！動くぞ！！

きちんと入れ子部分を上下にスクロールすることができました。
置き換えるだけで動くようになるとは……これは助かりますね！

# 締め
まだKotlinを触り始めたばかりで、
「何でそうなるの？？！」「さっぱりわからん」
ということが多いですが、触りながら学びながら、もっとグリグリといじれるようになっていきたいです。

スクロールの競合について、どなたかの助けになれば幸いです。
ではまた。
Sinatra でエスケープするための方法

# Sinatra において, エスケープ処理を行う理由
結論から言ってしまうと, XSS [^XSS] の対策のためです. XSS とは, ウェブサイトの脆弱性を突き, HTML に悪質なスクリプトをフォームから埋め込み, ユーザーがそのウェブサイトにアクセスすることで, スクリプトによって情報漏洩などを起こす攻撃のことです.

この XSS の対策の手段の1つとして, フォームから送られてくる文字列のうち, HTML において意味を持つような文字を別の文字に置き換えてしまうという手法があります. この手法のことをエスケープ (サニタイジング) といいます.

例えば, `<` は `&lt;` に, `&` は `&amp;` に置き換えられます. 

---
# 方法1 (Rack::Utils.escape_html を用いる)

`Rack::Utils.escape_html` という関数を用いて, 文字列をエスケープすることができます. この時, 関数名は `h` に置き換えて使うことが多いようです.

```escape_with_Rack.rb
require 'sinatra'

helpers do
  def h(text)
    Rack::Utils.escape_html(text)
  end
end

get '/' do
  h('<script>alert("XSS Test")</script>')
end
```

```test_against_xss_with_Rack.erb
<html>
  <head>
	<meta charset = "UTF-8">
  </head>

  <body>
	<%= h('<script>alert("XSS")</script>') %>
  </body>
</html>
```

# 方法２ (erubi の escape_html を true にする)
まず, gem として, `erubi` をインストールします. そして, 以下のように, `escape_html` の設定を `true` にすることで, 方法1 の時とは異なり,　`<%= =>` で文字列を自動的にエスケープするようになります.


```escape_with_erubi.rb
require 'sinatra'

set :erb, :escape_html => true

get '/' do
  erb :test_against_xss_with_erubi
end
```

```
<html>
  <head>
	<meta charset = "UTF-8">
  </head>

  <body>
	<%= '<script>alert("XSS")</script>'%>
  </body>
</html>
```

[^XSS]: 略: クロスサイトスクリプティング