OmniAICreator/Qiita-1.07M huggingface dataset:
ランダムフォレストの各特徴量の重要度をfeature_importanceから可視化してみた


## はじめに
ランダムフォレストでモデルを作成した後に、各特徴量がどれぐらいの重要度で扱われているかを可視化する方法がわかったので、備忘録としてまとめておきます。
誰かの参考になれば幸いです。

## まずランダムフォレストモデルの構築
タイタニックでランダムフォレストを構築します。
わかっている方は、ここは飛ばしていただいて、[各特徴量の重要度を確認](https://qiita.com/yasui83/items/a83428361fce6b6fbb42#%E5%90%84%E7%89%B9%E5%BE%B4%E9%87%8F%E3%81%AE%E9%87%8D%E8%A6%81%E5%BA%A6%E3%82%92%E7%A2%BA%E8%AA%8D) まで飛んでいただいて問題ありません。

### データの読み込み
まずkaggleからタイタニックのtrainデータとtestデータをgoogle colaboratoryにuploadします。
その後、下記のコードを記載して、データの読み込みを行います。

```
import numpy as np
import pandas as pd

train_data = pd.read_csv("train.csv")
test_data = pd.read_csv("test.csv")
```

### 特定の列のみを特徴量とする
生存に明らかに関係ない特徴量を省いていきます。

```
labels = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]
train_data = train_data[labels + ["Survived"]]
test_data = test_data[labels]
```

### AgeとFare、Embarkedの欠損値を埋める
ランダムフォレストはGBDTと違い、基本的に欠損値を埋めた状態で対応しないといけないので、欠損値の穴埋めをtrainデータの代表値で行う。

```
age_mean = train_data["Age"].mean()
train_data["Age"] = train_data["Age"].fillna(age_mean)
test_data["Age"] = test_data["Age"].fillna(age_mean)

fare_mean = train_data["Fare"].mean()
train_data["Fare"] = train_data["Fare"].fillna(fare_mean)
test_data["Fare"] = test_data["Fare"].fillna(fare_mean)

embarked_mode = train_data["Embarked"].mode()
train_data["Embarked"] = train_data["Embarked"].fillna(embarked_mode)
test_data["Embarked"] = test_data["Embarked"].fillna(embarked_mode)
```

### カテゴリ変数をget_dummies
機械学習に処理を行わせるためには、基本的に文字などは数字に変換する必要がある。
なので、タイタニックの性別などのカテゴリはget_dummies関数でダミー変数(0と1で構成される数値のデータ)に変換する必要があります。

```
cat_labels = ["Sex", "Pclass", "Embarked"]
train_data = pd.get_dummies(data = train_data, columns = cat_labels)
test_data = pd.get_dummies(data = test_data, columns = cat_labels)
```

### 入力と正解の用意

モデルの学習を行わせるために、目的変数と説明変数で分けます。
```
t_train = train_data["Survived"]
x_train = train_data.drop(labels = ["Survived"], axis = 1)
x_test = test_data
```

### ランダムフォレストのモデル構築

下記のコードでランダムフォレストとして、学習させます。
```
from sklearn.ensemble import RandomForestClassifier

model = RandomForestClassifier(n_estimators = 100, max_depth = 5)
model.fit(X = x_train, y = t_train)
```

## 各特徴量の重要度を確認
feature_importances_という変数が、modelには付与されています。
feature_importances_は、各特徴量をそれぞれどのくらいの重要度で利用したかがわかるものです。
今回はこれをグラフ化します。

```
import matplotlib.pyplot as plt

labels = x_train.columns
importances = model.feature_importances_

plt.figure(figsize = (10,6))
plt.barh(y = range(len(importances)), width = importances)
plt.yticks(ticks = range(len(labels)), labels = labels)
plt.show()
```

出力結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201104/2aaafab1-f5bd-1cb6-7fbe-993d0e0c96ea.png)

今回で言えば、他の特徴量より圧倒的に性別の影響が大きそうです。
逆にEmbarkedはあまりランダムフォレストの分類に大きな影響を与えていなそうです。

このようにして、ランダムフォレストで使われている特徴量の重要度をfeature_importances_を利用して可視化することで、何が目的変数に寄与しているかが判断できるようになります。

他のデータでも実践できるので、興味がある方はぜひ実践してみてください。


## 参照
[Udemy_みんなのkaggle講座](https://www.udemy.com/course/learning-kaggle/)
→こちらで学んだことを今回の記事でアウトプットさせていただきました。
Kaggle初心者にも大変わかりやすい講座でしたので、ぜひおすすめです！
Docusaurus でブログサイトを作成する

ブログの作成手法を色々調べた結果(WordPress Hexo 等)、Docusaurusが最も簡単にそれなりのサイトが作成できそうだという結論に至りました。(当方所感)

## Docusaurus とは

- facebook が開発のベースとなってます。
- コンテンツをMarkdownで記載すればWebサイトの体裁が出来上がります。
- [Docusaurus](https://docusaurus.io/)のサイト自体がDocusaurusで出来ているので、このサイトを見るのが手っ取り早いです。
つまりこのサイトと同じような構成で独自のWebサイトが作成できます。

## この記事の目的

- Docusaurus をインストールします。
- 最低限のカスタマイズを実施します。
- ローカルでWebサイトを起動し、動作を確認します。

## 導入手順

### Node.js インストール

[Nodeダウンロードサイト](https://nodejs.org/en/download/)  
![image](https://user-images.githubusercontent.com/38905609/174221507-415108dd-d73a-497a-aef4-ebc27dd99e27.png)
![image](https://user-images.githubusercontent.com/38905609/174221619-1cf64e4b-97d4-4d72-99e5-0dcee2c20a60.png)

## Docusaurus プロジェクトの作成

- <https://docusaurus.io/docs/installation>

```sh
npx create-docusaurus@latest my-website classic
```

## サイト起動

```sh
cd my-website
npm run start
```

`http://localhost:3000/` で起動イメージが確認できます。
![image](https://user-images.githubusercontent.com/38905609/179373520-d2cd61f4-c581-402b-820e-7fc000833ad8.png)
![image](https://user-images.githubusercontent.com/38905609/179373538-c7499db2-69db-4b3b-bfc1-7ce469d57b5d.png)

## Docs-only mode へ切り替え

- blogレイアウトを削除します。
(blogレイアウトが必要な場合はこの手順は不要です。)  
<https://docusaurus.io/docs/docs-introduction#docs-only-mode>

- `docusaurus.config.js`を下記のとおり編集します。

```js:docusaurus.config.js
module.exports = {
  // ...
  presets: [
    '@docusaurus/preset-classic',
    {
      docs: {
        routeBasePath: '/', // Serve the docs at the site's root
        /* other docs plugin options */
      },
      blog: false, // Optional: disable the blog plugin
      // ...
    },
  ],
};
```

- `docs/intro.md`を以下のとおり編集します。

```md:docs/intro.md
---
slug: /
---

This page will be the home page when users visit https://example.com/.
```

- `/src/pages/index.js`を削除します。  
※ サイトの初期ページをdocsサイトにするため`index.js`の削除が必要です。

- 設定後イメージ
![image](https://user-images.githubusercontent.com/38905609/179373727-c1dc4e1c-c58d-469f-941c-473d19c82500.png)

## コンテンツの追加

- コンテンツの追加はMarkdownファイルを追加するだけです。

`/docs/サンプル/サンプル.md`　　
![image](https://user-images.githubusercontent.com/38905609/179375106-728cf3c6-a338-4b6f-a113-c709a583d3d3.png)


## 👇GitHubはこちら

- <https://github.com/jun-knd/docusaurus.github.git>  

## 👇参考URL

- [Docusaurus サイト](https://docusaurus.io/docs)
D言語でEinsum（アインシュタインの縮約記法）

## はじめに
いままでpythonに触る機会がなかったものの、機械学習方面に強くテンソルの計算なんかが得意らしいということぐらいは知っている。
しかもアインシュタインの縮約記法に則った計算が出来ると聞いた。

アインシュタインの縮約記法とは、例えばn次元の行列$A$とベクトル$x$の掛け算$y = Ax$を考えた時に、
$$
y_{i} = \sum^n_j{A_{ij} x_{j}} = A_{ij} x_{j}
$$
というように同じ添え字($j$)が掛け算の中に現れたらn次元和算しようという規則だ。
これを用いることでとても式を簡潔に記載することができる。

これをプログラム中で書けたら、とても便利だ。


pythonのnumpyというライブラリにあるeinsumという機能を使うと

``` python
import numpy as np
A = np.arange(9).reshape(3,3)
x = np.array([1,2,3])
y = np.einsum("ij,j -> i",A,x)

print(y)
# [ 8 26 44]
```
と書けるらしい。

> ``` python
> y = np.einsum("ij,j -> i",A,x)
> ```
この部分がそうである。

D言語でも是非欲しい機能である。
これをそのままD言語で再現してもいいのだが（[すでに実装している方はいる](https://github.com/ShigekiKarita/mir-einsum/blob/9e1ac02a1100a881b88eb744f59b9226024e09bf/source/einsum.d#L186)）、~~見た目がちょっとアレである~~ せっかくならもっと数式っぽく自然に書きたい。

というわけで[ggedライブラリ](https://qiita.com/Zenww/items/870905c9dd7265704325)内に実装した。この記事はその紹介だ。

## 使い方
### 行列とベクトルの積
pythonの例をと同じものを書いてみよう。

``` D
import std.stdio : writeln;
import ggeD;
void main()
{
	auto A = tensor([0.,1.,2,3,4,5,6,7,8],3,3);
	auto x = tensor([1.,2,3],3);

	auto y = Einsum | A.ji*x.j;
	foreach(ijk;y)
	{
		writeln(ijk ," | ", y[ijk]);
	}
}
// 0 | 8
// 1 | 26
// 2 | 44
```
となる。
> ``` D
> auto y = Einsum | A.ji*x.j;
> ```
は
$y_{i} = A_{ij} x_{j}$

と対応しており似たような書き方になっている。が、添え字が`i,j`と逆だ。これは仕様である。<details><summary>(どうしようか悩み中)</summary><div>
  
$A_{xy}$と書いたときに添え字のイメージと横縦が合わないのに納得いかないし、そもそも$A_{ijk}$と増えていったら、関係ないし...でも世にある行列の式と齟齬があるのは問題があるし...
万が一、自分のライブラリを使う人が居て今の書き方だと不都合だなんてリクエストが来たら考える。

</div></details>


### 行列のトレースや内積
``` D
auto trA = Einsum | A.ii;    // 12
auto dot = Einsum | x.i*x.i; // 14
```

### 足し算や関数適用も
``` D
Einsum | A.ij*x.i + x.j;    // [9 28 48]
Einsum | BroadCast!sin(x.i); // [0.841471 0.909297 0.14112]
```

### クロネッカーのデルタやエディントンのイプシロン

[クロネッカーのデルタ](https://ja.wikipedia.org/wiki/クロネッカーのデルタ)や[エディントンのイプシロン](https://ja.wikipedia.org/wiki/エディントンのイプシロン)はこんな感じで書ける。
``` D
auto delta = tensor!double(3,3);
auto epcilon = tensor!double(3,3,3);
foreach(i,j;delta)
{
    delta[i,j] = i == j ? 1. : 0.;
}
foreach(i,j,k;epcilon)
{
    epcilon[i,j,k] = sgn((1.*j-i)*(1.*k-j)*(1.*k-i));
}
writeln(Einsum | delta.ij*A.ij);
writeln(Einsum | epcilon.ijk*A[0,0..$].i*A[1,0..$].j*A[2,0..$].k );
```

## まとめ
アインシュタインの縮約記法は便利。
Arduino UNOの時間関数で遊ぶ1


![o_con580.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/b45f35ff-2943-a40d-eb07-e0bbcea7ed03.jpeg)



```c++


#include <time.h>

void setup() {

Serial.begin(9600);

time_t t=3600*4+60*3+2;

struct tm *tm = localtime(&t); 

    Serial.print( "時" );Serial.println( tm->tm_hour );
    Serial.print( "分" );Serial.println( tm->tm_min );
    Serial.print( "秒" );Serial.println( tm->tm_sec );
    
}

void loop() {
  // put your main code here, to run repeatedly:

}

```
Arduinoのタイマー割り込みで遊ぶ2(1秒)


目的
C言語系の時間関数のテストをしたい

https://qiita.com/suzukinori/items/939cc9f49e535c4eadd7


![o_con579.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f84e2b38-bc71-676c-994a-dcf92f195f2e.jpeg)




xそのまま研究調査目的で引用しました。

normalMode_002.ino


```c++

void setup() {
  Serial.begin(115200);
  TCCR1A = 0; // 初期化
  TCCR1B = 0; // 初期化
  TCNT1 = 3036; 
  TCCR1B |= (1 << CS12); // CS12 -> 1  prescaler = 256
  TIMSK1 |= (1 << TOIE1); //TOIE -> 1
}

ISR(TIMER1_OVF_vect) {
  Serial.println(millis());
  TCNT1 = 3036;
}

void loop() {
}


```
【Bun】Windowsで肉まんを使ってみる

# Bunとは
最近**Node.js**だったり**Deno**だったりを調べていて、Youtubeで**かわいい肉まんがロゴのBun**というJavaScriptランタイムを見つけました。

**Bun**は**バンドラー、トランスパイラ、パッケージマネージャ**が備わっているJavaScriptランタイムです。

https://bun.sh/

# Windowsで環境を構築
早速、Windows環境で環境を構築してみます。

実行環境は以下の通りです。
- Windows 10 / 11
- Ubuntu 20.04 / 22.04

## 1 WSLのインストール

以下のリンクを参考にWSLをインストールします。

https://docs.microsoft.com/ja-jp/windows/wsl/install

```powershell
wsl --install
```
上記のコマンドを**管理者権限**でコマンド入力をし、WSLをインストールします。
その後、PCを再起動するとWSLを実行できるようになります。

デフォルトで**Ubuntu**がインストールされています。

次に、Ubuntuで**ユーザー名**と**パスワード**の設定をします。
```plaintext
== 略 ==

Enter new UNIX username: _ユーザー名の設定_
New password: _パスワードの設定_
Retype new password: _パスワードの再入力_
passwd: password updated successfully
Installation successful!

== 略 ==
```

## 2 Bunのインストール

続いて、Bunのインストールをします。
インストールしたUbuntu上でおこないます。

まず、**unzip**が必要なのでインストールします。
```plaintext
sudo apt install unzip
```

次に以下のコマンドを入力してBunをインストールします。

```plaintext
curl https://bun.sh/install | bash
```
完了すると以下のような表示が出ます。

```plaintext
bun was installed successfully to /home/<ユーザー名>/.bun/bin/bun

Manually add the directory to your $HOME/.bashrc (or similar)

    export BUN_INSTALL="/home/<ユーザー名>/.bun" - ①
    export PATH="$BUN_INSTALL/bin:$PATH"       - ②

To get started, run

    bun --help 
```

**上記にあるように$HOME/.bashrcのファイル内に①、②を追記**します。

:::note alert
Ubuntu-18.04だとエラーが発生します。
Ubuntu-20.04以上のバージョンで再度、実行をしてみてください。
:::

インストール後、一度Ubuntuを閉じて、再度開きます。

## 3 bun --helpの実行

再度開いたUbuntu上で以下のコマンドを実行します。

```plaintext
bun --help
```

問題なければ、以下のように出力されます。
```plaintext
    --use <STR>   ...

    == 略　（オプションのヘルプ表示） ==

-------

bun: a fast bundler, transpiler, JavaScript Runtime and package manager for web software.

  dev       ./a.ts ./b.jsx        Start a bun Dev Server
  bun       ./a.ts ./b.jsx        Bundle dependencies of input files into a .bun

  create    next ./app            Start a new project from a template (bun c)
  run       test                  Run JavaScript with bun, a package.json script, or a bin
  install                         Install dependencies for a package.json (bun i)
  add       @remix-run/dev        Add a dependency to package.json (bun a)
  remove    redux                 Remove a dependency from package.json (bun rm)

  upgrade                         Get the latest version of bun
  completions                     Install shell completions for tab-completion
  discord                         Open bun's Discord server
  help                            Print this help menu
```

ここまでできたら、Bunが使用可能になります。

# まとめ
以上が簡単な環境構築フローです。

以下のリンクはドキュメントになっています(英語)。

https://github.com/oven-sh/bun#using-bun-with-create-react-app

「Table of Contents」の「Using bun with Create React App」を参照すると、簡単にReactのプロジェクトが作成できます。

ぜひ、試してみてください ^ ^
Google Assistant向け対話型スキル(Actions on Google) の終了について

(遅報)

# 2023年6月13日にConversational Actionsが利用不可能に
Actions on Google（の特にConversational Actions）は、サードパーティに対してAlexa Skillと同等の対話型UIを提供する機能です。
しかしGoogleは2022年6月13日に、"[Conversational Actions sunset overview](https://developers.google.com/assistant/ca-sunset)"としてこのConversational Actionsの機能を削除することを発表しています。

これによると、遅くとも2023年6月13日にはすべてのConversational Actionsが利用不可能になるようですね。
Qiita内外の日本語情報でもConversational Actionsはいくつも紹介されていましたし、私自身Conversational Actionsを実装をしている真っ最中だったので驚きが隠せません。お陰で情報の精査に2週間、学期末の忙しさで2週間取られて発表の1ヶ月後にこれを書いています。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218242/ef1bbd4b-133b-0146-9f72-75765a1a9f27.png)
専用アプリストアも用意されていました。こういう技術に全部乗っかるヤマト、さすがですね。
このストアは今後もスマートホーム機能とかのために残されるのでしょうか？

# 4つのカテゴリーでのみアプローチが可能になる

Conversational Actions sunsetの後は、開発者は以下の4カテゴリーの機能のみアプローチ可能なようです。

### - Androidアプリの操作 (App Actions)
SiriでiOSアプリが操作できるのと同じようなやつですね。
Conversational Actions sunset overviewと同時期に[App Actions overview](https://developer.android.com/guide/app-actions/overview)という記事でActionsからAndroidアプリのショートカット操作を行う機能の正式版を発表しているので、こっちに移行しろということでしょう。

今思うとGoogleはAlexa SkillほどこのConversational Actionsをはやらせようとしていなかったし、Androidアプリ連携に注力したいのは自然な気もします。でもiPhoneユーザーは放置するんですかね？それはそれでGoogleらしくないというか…

### - WEBサイト上の構造化データによる情報提供 (Actions from web content)
Google Assistantに調べ物にさせると「〇〇のサイトによると、こう書かれています」みたいな読み上げをしてくれるやつですね。さすがGoogleと言うか、ここは削らないようです。

### - スマートホーム操作 (Smart home)
これに関してはSDKも公開されるようです。まあこれを売りにしてる家電とかもあるし、削りたくても削れないでしょう。

### - Media Actions
Spotifyの曲送りとかのことでしょうか。いちユーザーとして有難いです。

# まとめ
開発者にとってGoogleAssistantはAlexaと比較するものではなくなった、と言うと大げさでしょうか。とにかく「対話型UIによる自由なアプリ開発のできるプラットフォーム」ではなくなるようですね。これに対してスマホOSやWEB検索のプラットフォームを持たないAlexa側に今後動きがあるのか、機になります。

最後に、この記事に誤りや補足事項等がありましたらコメントいただけると大変助かります。

参考：[voicebot.ai](https://voicebot.ai/2022/06/13/google-assistant-actions-voice-apps-to-sunset-focus-shifts-to-android-apps/) [androidcentral.com](https://www.androidcentral.com/apps-software/google-shutting-down-conversational-actions)
【Zsh】特定のディレクトリに移動した時にaliasを設定する

# 課題

複数のGoプロジェクトで異なるバージョンのGoを使用している。

記事と関係ないけど複数の異なるGoバージョンをインストールする方法はこちら↓
https://go.dev/doc/manage-install#installing-multiple

これで例えば `go1.11.13` みたいなバージョン付きコマンドでGoを実行できる様になるが、出来れば各プロジェクト内では `go` というコマンドで実行したい。

# 解決策

そこで、各プロジェクトのディレクトリに移動した際に自動でエイリアスを設定する。
.zshrcにディレクトリ移動する度に実行されるhook関数を記述する。

```zsh
function aliasgo {
	case $PWD/ in
		~/some-project/*) alias go=~/go/bin/go1.11.13;;
		*)
			if alias go &> /dev/null
			then
				unalias go
			fi
			;;
	esac
}
chpwd_functions+=(aliasgo)
```

ディレクトリから外れるとunaliasする様にしたけどイマイチ感ある(´･ω･`)
もっとスマートな方法あったら教えて欲しい。
Node.Js

Node.js とは？
⇨本来フロントエンドの言語であるjavascriptをサーバーサイド言語として使うための仕組み。

Node.jsを使わなかった場合↓
![スクリーンショット 2022-07-09 16.13.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602256/4fddd1f0-5ddf-6f5f-efab-580b2f27fc01.png)

使った場合↓![スクリーンショット 2022-07-09 16.16.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602256/d7ffe383-e136-aa2a-90cf-a1ee650da37c.png)


Node.jsのメリット
①リアルタイムな処理が速い　
⇨ツイッターなどのリアルタイムで画面が更新されるアプリ開発に向いている

Node.jsのデメリット
①対応しているサーバーが少ない

基本用語
①ルーティング＝クライアント側からリクエストが飛んできた時に、そのリクエストを処理することをルーティングという
コードで見てみると
```a.get('url',()=>{//トップ画面表示してね（リクエスト）})```
{//トップ画面表示してね（リクエスト）⇦この処理をすることを「ルーティング」

②req(リクエスト）res(レスポンス)　⇨リクエスト、レスポンスにはリクエスト・レスポンスに関する情報が入っています。
a.get('url',(req,res)=>{//トップ画面表示してね（リクエスト）})
reqにはこのURLの情報等が入っている

```③res.render（’ファイル名’）＝指定したurlの中身を画面に表示するねって意味```
a.get('url',(req,res)=>{res.render（’ファイル名’）})
resにはurlの中身のファイルの情報が入っている。
paizaでsympy その7

# 概要
sympyが、魔法なので、paizaで、やってみた。

# 参考にしたページ

https://qiita.com/mrrclb48z/items/0ea9d1ed55b117947108

# 実行結果

```
#(1) -4*x/3 - 8 , 4*x/3 + 8
#(2) 168
#(3) 10 39 35
#(4) 4
#(5) Point2D(-1, 0)
#(6) -8*x - 8
```

# 成果物

https://paiza.io/projects/N5wBQf0I34lTo17jaMVVmg?language=python3

以上。
AWS提供でないベースイメージからLambdaを作る

# はじめに
以前、コンテナイメージからLambdaを作りました。

https://qiita.com/a_b_/items/d9398fd6efe0f66b6c6f

ところが諸事情（Amazon Linuxでは、PowerShellが十全に動かせず、MS365の監査ログが取得できない）のため、Ubuntuをベースとしたコンテナを作ろうとした際に、わかったことややったことを記事にします。

# 参考

コンテナイメージを使ったLambdaの仕組みについての解説は以下になります。

https://aws.amazon.com/jp/builders-flash/202104/new-lambda-container-development-2/?awsf.filter-name=*all

Dockerfileの作り方の参考にしたのは以下です。

https://github.com/nickadam/powershell-lambda

# Lambda動作の仕組み

公式の解説に書いてある内容の自分なりの解釈です。

- Lambda関数を実行するには、Lambdaサービスとランタイムの間で対話が必要
    - 普通のコンテナイメージそのままでは、この対話ができないのでLambdaでは動かない
    - AWSが提供するLambdaのベースイメージには、これらが実装済み
- 自前のコンテナの場合は、AWS提供の言語ごとのRuntime Interface Client(RIC)を組み込むと楽

# 環境
以前と同じ、Cloud9だけになります。



# やったこと
以前と同じようにディレクトリやファイルを作っていきます。

```bash
# プロジェクトディレクトリ作成
mkdir sample-ecr-lambda
cd sample-ecr-lambda

# リージョンとアカウントIDを環境変数にセット
## 記事の中では直接使いませんが、ECRを作成したりPUSHしたりする際に使います
REGION="ap-northeast-1"
ACCOUNTID=$(aws sts get-caller-identity --output text --query Account)

# ファイル作成
touch app.py
touch Dockerfile
```

```python:app.py
import json

def handler(event, context):
    return {
        "statusCode": 200,
        "body": json.dumps(
            {
                "message": "hello world",
            }
        ),
    }
```

ベースイメージを素のUbuntuから作るので、Dockerfileは以前のものと異なります。
- 素のUbuntuには、Pythonとpipが入っていないのでインストール
- Python用のRICをインストール
- エントリポイントとして、インストールしたRICを指定

```Dockerfile:Dockerfile
FROM ubuntu:20.04

RUN apt-get update && apt-get install -y python3-pip

RUN mkdir /function && \
  pip install --target /function awslambdaric
  
COPY app.py /function/

WORKDIR /function

ENTRYPOINT [ "/usr/bin/python3", "-m", "awslambdaric" ]

CMD [ "app.handler" ]
```
このDockerfileでイメージを作成します。
```bash
docker build -t func1 .
```

あとは以前と同じような流れになります。

1. ECRリポジトリ作成
1. イメージPUSH
1. Lambada作成

https://qiita.com/a_b_/items/d9398fd6efe0f66b6c6f#ecr%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E4%BD%9C%E6%88%90%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8push


# おわりに
今回はLambdaの実行に必要なRICの話と、Ubuntuで動かす方法について記事にしました。

自前のイメージから作成する方法の情報収集の最初にRICのことが知れ、大きく時間を無駄にしなくて済んだので、自分と同じような方の参考になれば幸いです。
RxSwiftデータバインディング2

# はじめに
RxSwift勉強中です。
RxExampleを参考に、

https://github.com/ReactiveX/RxSwift/tree/main/RxExample/RxExample/Examples/Numbers

今回は、TextFieldに入力した値の合計値がリアルタイムでLabelに反映されるアプリを製作してみました。
そのままのコードだとあまり勉強にならないと感じたので、ViewModelに処理を分けて書いてみました!
![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2428088/ce273885-66d4-e8f0-4195-6ae43b6d0aa1.gif)

https://github.com/masatakasumida/NumbersApp

```swift:NumbersViewController
import UIKit
import RxSwift
import RxCocoa

class NumbersViewController: UIViewController {
    
    @IBOutlet private weak var textField1: UITextField!
    @IBOutlet private weak var textField2: UITextField!
    @IBOutlet private weak var textField3: UITextField!
    
    @IBOutlet private weak var answerLabel: UILabel!
    
    private var viewModel: NumbersViewModel!
    private let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupViewModel()
    }
    
    func setupViewModel() {
        viewModel = NumbersViewModel()
        textField1.rx.text.orEmpty
            .bind(to: viewModel.textField1)
            .disposed(by: disposeBag)
        
        textField2.rx.text.orEmpty
            .bind(to: viewModel.textField2)
            .disposed(by: disposeBag)
        
        textField3.rx.text.orEmpty
            .bind(to: viewModel.textField3)
            .disposed(by: disposeBag)
        
        viewModel.sumNumber()
            .bind(to: answerLabel.rx.text)
            .disposed(by: disposeBag)
    }
    
}
class NumbersViewModel {
    
    let textField1 = BehaviorRelay<String>(value: "")
    let textField2 = BehaviorRelay<String>(value: "")
    let textField3 = BehaviorRelay<String>(value: "")
    
    func sumNumber() -> Observable<String> {
        return Observable.combineLatest(textField1.asObservable(), textField2.asObservable(), textField3.asObservable())
            .map{ value1, value2, value3 in
                return "\(((Int(value1) ?? 0) + (Int(value2) ?? 0) + (Int(value3) ?? 0)))"
            }
    }
}

```
### 解説
```swift:NumbersViewModel
func sumNumber()
```
では、**combineLatest**で3つのtextFieldの値の最新値を取得して、その値の合計値をObservable(String型)の値で返しています。
その値を、UILabel(answerLabel)にバインディングして、反映させています!!
単純な処理だと思いますが、初心者の自分には理解するまでに時間がかかりました😥
引き続き、勉強していきたいと思います。
以上です!!
[Raspberrypi Docker compose] E: Unable to locate packageが解決できないんですけど！

# 概要
以前から気になっていたMisskeyを導入しようとRaspberry piでDockerを用いて公式通りに構築しようとしたら以下のようなエラーを吐かれた

```.console
~
E: Unable to locate package
```

このエラーの解決に永遠に悩んでいたので自身への戒めも含めて記事を書きました。

# 環境
- Raspberry pi 4B 8GB
- Docker version 20.10.17, build 100c701
- Docker Compose version v2.6.0

# 基本のDockerfile
https://github.com/misskey-dev/misskey/blob/develop/Dockerfile

MisskeyをCloneした後に何も弄っていないDockerfileを用いて以下のコマンドを入力

```.sh
$ docker compose build
```

その結果が冒頭のエラーへ。

# 途中のログを見てみる

流れ作業なのでコマンドログを全然見なかったが、よくよく見てみると```apt-get update```の時に一瞬何かしらエラーが出ていた。(しかもエラー文は処理が進むと消える)
ここまでで3時間程度経っていたが、エラーを見てみると

```console
 => # rg'
 => => # W: Failed to fetch http://security.debian.org/debian-security/dists/bullseye-security/InRelease  Temporary failure
 => => # resolving 'security.debian.org'
 => => # W: Failed to fetch http://deb.debian.org/debian/dists/bullseye-updates/InRelease  Temporary failure resolving 'deb.
 => => # debian.org'
 => => # W: Some index files failed to download. They have been ignored, or old ones used instead.

```

...名前解決できてないな？

ということで名前解決が悪さしてそうなので```/etc/resolv.conf```を見てみると

```./etc/resolv.conf
# Generated by resolvconf
search flets-east.jp iptvf.jp
nameserver 2400:4053:121:e400:a10:86ff:fef3:87e0
```

ネームサーバーについては勉強不足なのでなんにもわからんですが、1.1.1.1とかのIPがないので関連のIPを付け足してあげると


```./etc/resolv.conf
# Generated by resolvconf
search flets-east.jp iptvf.jp
nameserver 2400:4053:121:e400:a10:86ff:fef3:87e0
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 1.1.1.1
nameserver 208.67.222.222  # OpenDNS address
```
(参考: [「/etc/resolv.conf」ファイル](https://linuc.org/study/knowledge/507/))


以上を付け足したら今までの時間は何だったんだと思うくらいスイスイ処理が進んでくれました。


# 終わりに
ネームサーバーはしっかり確認しよう！！！！！！！


# その他ひっかかったこと
## ビルドと初期化
ビルドと初期化にて

```
sudo docker-compose run --rm web yarn run init`
```

のコマンドを打つが、この時DBとRedisのHost名を初期値から変えてあげないと起動途中でエラーが発生してしまう。

参考：
https://issuehunt.io/r/syuilo/misskey/issues/7312

default.ymlのdbとredisのhost名をdocker-compose.ymlで指定した識別子に設定してあげると良い感じになります。
【Linux】主な環境変数

## 主な環境変数

| 変数 | 説明 |
|:-:|:- |
| EDITOR  | デフォルトエディタのパス  |
| HISTFILE  |  コマンド履歴を格納するファイル |
| HISTFILESIZE  |  HISTFILEに保存する履歴数 |
| HISTSIZE  | コマンド履歴の最大数  |
| HOME  | 	カレントユーザのホームディレクトリ  |
| HOSTNAME  |  	ホスト名 |
| LANG  |  ロケール（言語処理方式） |
| LOGNAME  | ログインシェルのユーザ名  |
| PATH |  コマンドやプログラムを検索するディレクトリリスト |
| PS1  | プロンプトの文字列  |
| PS2    | 複数行にわたる入力時のプロンプト |
| PWD     |  カレントディレクトリ |
| TERM | 端末の種類 |
| USER | 現在のユーザ |

## 環境変数の設定方法
　`export`コマンドで設定することができます。
```
$ export EXAMPLE=foo
```

## 環境変数の確認方法
`printenv`コマンドで環境変数の一覧を表示できます。
```
$ printenv
SHELL=/bin/bash
COLORTERM=truecolor
TERM_PROGRAM_VERSION=1.69.1
HOSTNAME=2a7he2yh2e11
SSH_AUTH_SOCK=/tmp/vscode-ssh-auth-e2e82b9c3ddc252tg049ga2521e37h310t2e3d33.sock
RUBY_DOWNLOAD_SHA256=ca10d017f8a1b6d247556622c841fc56b90c03b1803f87198da1e4fd3ec3bf2a
REMOTE_CONTAINERS_IPC=/tmp/vscode-remote-containers-ipc-e2e82bdc7ddc252fa056fs5235v87c110c5a0d66.sock
RUBY_VERSION=3.1.2
PWD=/myapp-backend
BUNDLE_APP_CONFIG=/usr/local/bundle
RUBY_MAJOR=3.1
TZ=Asia/Tokyo
VSCODE_GIT_ASKPASS_NODE=/vscode/vscode-server/bin/linux-arm64/b06ae3b2d2dbfe28bca3134cc6be65935cdfea6a/node
HOME=/home/ruby
LANG=C.UTF-8
HISTFILE=/bashlog/.bash_history
 ・
 ・
 ・
```
C# + Html Agility Pack で基本的なことを少し触ってみる

# 目的
[Yahoo!ニュース](https://news.yahoo.co.jp/)の主要トピックスに対してHtml Agility Packを試したときのメモ
・Copy XPathの出力＋Linqの組み合わせ


## 追加パッケージ
.NET6でプロジェクトを作成後
プロジェクト -> NuGetパッケージの管理より以下を追加する(作成日のバージョン)
```cs
HtmlAgilityPack(1.11.43)
System.Text.Encoding.CodePages(6.0.0)
```

## CSのサンプルコード

```cs
    using System.Net.Http;
    using System.Diagnostics;
    using HtmlAgilityPack;

    private async void btnYahooNews_Click(object sender, EventArgs e)
    {
        var builder = new UriBuilder("https://news.yahoo.co.jp/");

        var client = new HttpClient();
        client.Timeout = TimeSpan.FromSeconds(10.0);

        string htmlString = await client.GetStringAsync(builder.Uri);

        HtmlAgilityPack.HtmlDocument html = new HtmlAgilityPack.HtmlDocument();

        html.LoadHtml(htmlString);

        var root = html.DocumentNode;
        //
        // XPathを使用してトピック全８項目を取得する
        //
        var nodes = root.SelectNodes("//*[@id=\"uamods-topics\"]/div/div/div/ul/li[1 or 8]/a")
            .Select(s => new { ctxt = s.InnerText.Trim(), href = s.Attributes["href"].Value.Trim() });

        foreach (var item in nodes)
        {
            //Debug.WriteLine(item.ctxt + " " + item.href);

            //
            // 各記事へ移動する -> 記事全文を読むのURLを取得する
            //
            var ndbuilder = new UriBuilder(item.href);

            var ndclient = new HttpClient();
            ndclient.Timeout = TimeSpan.FromSeconds(10.0);

            string ndString = await ndclient.GetStringAsync(ndbuilder.Uri);

            HtmlAgilityPack.HtmlDocument ndhtml = new HtmlAgilityPack.HtmlDocument();
            ndhtml.LoadHtml(ndString);

            var ndroot = ndhtml.DocumentNode;
            // 記事全文を読む
            var node = ndroot.SelectNodes("//*[@id=\"uamods-pickup\"]/div[2]/div/p/a")
                .Select(s => new { ctxt = s.InnerText.Trim(), href = s.Attributes["href"].Value.Trim()});

            foreach (var nd in node)
            {
                Debug.WriteLine(nd.ctxt + " " + nd.href);
            }
        }
    }
```
# 参考にしたのは以下のサイト
[C#でHTMLを解析する(Html Agility Packライブラリ)](https://araramistudio.jimdo.com/2020/11/30/c-%E3%81%A7html%E3%82%92%E8%A7%A3%E6%9E%90%E3%81%99%E3%82%8B-html-agility-pack%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA/)
[Html Agility Packを使ってWebページをスクレイピングするには？［C#、VB］](https://atmarkit.itmedia.co.jp/ait/articles/1501/27/news140.html)
[Html Agility Pack を使用してサイトのHTMLを解析する](https://todosoft.net/blog/?p=367)
[C# + AngleSharp で基本的なことを少し触ってみる](https://qiita.com/tabizou/items/6492dd6bd227afc61ea6)
[Windows10 + Python3 + BeautifulSoup4 を試してみる](https://qiita.com/tabizou/items/a546d0762c3e0a8d6678)
Gmailのメールを自動削除する

利用しているアプリで未読通知メールがGmailに多く届くのだが、なぜか通知設定で止めることができないという謎仕様で溜まるのが嫌だったのでGASを使って自動削除できるようにしてみた。


```
function deleteNoReply() {
  const query = "削除したいメールを検索するときの検索条件";
  const start = 0;
  const max = 10;

  const threads = GmailApp.search(query, start, max);
  const messageThreads = GmailApp.getMessagesForThreads(threads);
  for(let messages of messageThreads) {
     messages[0].moveToTrash();
  }
}

```

思ったよりかなり簡単にできた。

最初に検索条件、検索結果の何件目から取得するか、検索結果の何件目まで取得するかをそれぞれセットしておく。

GmailApp.searchでスレッドの情報を取得することができ、GmailApp.getMessagesForThreadsでスレッドからメールを二次元配列で取得する。

最後にfor文で取得したメールをゴミ箱に移動する処理を書けば受信トレイから削除することができる。

あとは自動実行するためにトリガーの設定で実行したい時間を指定すれば完了。(トリガーの設定の仕方はググれば出てくるので省略)
HTMLの基礎知識（バリデーションの応用）

複数の投稿をさける機能になります！

注意：ここでは投稿機能まで実装していることが条件となります。:frowning2:


Step1：コントローラー(create)の変更
![スクリーンショット (48).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738887/2bb04b05-18ba-d052-6071-354052a77173.png)

Step2：バリデーションの追加
![スクリーンショット (49).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738887/ee4258d5-0a1b-4a6f-f280-1a5468708e97.png)

Step3：View(new)を変更
![スクリーンショット (50).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738887/7e7bd0ab-e480-dff6-ab74-5fcf354686a6.png)

Step4：対応するViewで（_error_messages.html.erb）を追加・編集
![スクリーンショット (51).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738887/d78fc39e-18da-9833-e90f-f292c3c15140.png)

Step5：確認！！
①仮のデータとしてチーズバーガーを事前に登録
![スクリーンショット (54).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738887/796efb63-d6be-da51-c102-826a2db9f26c.png)
②投稿でチーズバーガーを入力して以下のような画像になれば
　被らないバリデーションの応用の完了！！
![スクリーンショット (53).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738887/55b0989e-72ea-ba29-8bc8-a4bca188033c.png)

以上がバリデーションの応用になります！！
ぜひぜひ実装してみてください！！
隣接する都道府県の一覧表

隣接している都道府県の一覧表を作成しました。
この表を生成した JavaScript のソースコードは Gist [jp-neighboring-pref.js](https://gist.github.com/kawanet/96b7ba1e61caac7b6022f34866fdfb91) にあります。（MITライセンス）

|都道府県ID|都道府県名|隣接都道府県ID|隣接都道府県名|
|---|---|---|---|
|01|北海道|||
|02|青森県|03, 05|岩手県, 秋田県|
|03|岩手県|02, 04, 05|青森県, 宮城県, 秋田県|
|04|宮城県|03, 05, 06, 07|岩手県, 秋田県, 山形県, 福島県|
|05|秋田県|02, 03, 04, 06|青森県, 岩手県, 宮城県, 山形県|
|06|山形県|04, 05, 07, 15|宮城県, 秋田県, 福島県, 新潟県|
|07|福島県|04, 06, 08, 09, 10, 15|宮城県, 山形県, 茨城県, 栃木県, 群馬県, 新潟県|
|08|茨城県|07, 09, 11, 12|福島県, 栃木県, 埼玉県, 千葉県|
|09|栃木県|07, 08, 10, 11|福島県, 茨城県, 群馬県, 埼玉県|
|10|群馬県|07, 09, 11, 15, 20|福島県, 栃木県, 埼玉県, 新潟県, 長野県|
|11|埼玉県|08, 09, 10, 12, 13, 19, 20|茨城県, 栃木県, 群馬県, 千葉県, 東京都, 山梨県, 長野県|
|12|千葉県|08, 11, 13|茨城県, 埼玉県, 東京都|
|13|東京都|11, 12, 14, 19|埼玉県, 千葉県, 神奈川県, 山梨県|
|14|神奈川県|13, 19, 22|東京都, 山梨県, 静岡県|
|15|新潟県|06, 07, 10, 16, 20|山形県, 福島県, 群馬県, 富山県, 長野県|
|16|富山県|15, 17, 20, 21|新潟県, 石川県, 長野県, 岐阜県|
|17|石川県|16, 18, 21|富山県, 福井県, 岐阜県|
|18|福井県|17, 21, 25, 26|石川県, 岐阜県, 滋賀県, 京都府|
|19|山梨県|11, 13, 14, 20, 22|埼玉県, 東京都, 神奈川県, 長野県, 静岡県|
|20|長野県|10, 11, 15, 16, 19, 21, 22, 23|群馬県, 埼玉県, 新潟県, 富山県, 山梨県, 岐阜県, 静岡県, 愛知県|
|21|岐阜県|16, 17, 18, 20, 23, 24, 25|富山県, 石川県, 福井県, 長野県, 愛知県, 三重県, 滋賀県|
|22|静岡県|14, 19, 20, 23|神奈川県, 山梨県, 長野県, 愛知県|
|23|愛知県|20, 21, 22, 24|長野県, 岐阜県, 静岡県, 三重県|
|24|三重県|21, 23, 25, 26, 29, 30|岐阜県, 愛知県, 滋賀県, 京都府, 奈良県, 和歌山県|
|25|滋賀県|18, 21, 24, 26|福井県, 岐阜県, 三重県, 京都府|
|26|京都府|18, 24, 25, 27, 28, 29|福井県, 三重県, 滋賀県, 大阪府, 兵庫県, 奈良県|
|27|大阪府|26, 28, 29, 30|京都府, 兵庫県, 奈良県, 和歌山県|
|28|兵庫県|26, 27, 31, 33, 36|京都府, 大阪府, 鳥取県, 岡山県, 徳島県|
|29|奈良県|24, 26, 27, 30|三重県, 京都府, 大阪府, 和歌山県|
|30|和歌山県|24, 27, 29|三重県, 大阪府, 奈良県|
|31|鳥取県|28, 32, 33, 34|兵庫県, 島根県, 岡山県, 広島県|
|32|島根県|31, 34, 35|鳥取県, 広島県, 山口県|
|33|岡山県|28, 31, 34, 37|兵庫県, 鳥取県, 広島県, 香川県|
|34|広島県|31, 32, 33, 35, 38|鳥取県, 島根県, 岡山県, 山口県, 愛媛県|
|35|山口県|32, 34, 40|島根県, 広島県, 福岡県|
|36|徳島県|28, 37, 38, 39|兵庫県, 香川県, 愛媛県, 高知県|
|37|香川県|33, 36, 38|岡山県, 徳島県, 愛媛県|
|38|愛媛県|34, 36, 37, 39|広島県, 徳島県, 香川県, 高知県|
|39|高知県|36, 38|徳島県, 愛媛県|
|40|福岡県|35, 41, 43, 44|山口県, 佐賀県, 熊本県, 大分県|
|41|佐賀県|40, 42|福岡県, 長崎県|
|42|長崎県|41|佐賀県|
|43|熊本県|40, 44, 45, 46|福岡県, 大分県, 宮崎県, 鹿児島県|
|44|大分県|40, 43, 45|福岡県, 熊本県, 宮崎県|
|45|宮崎県|43, 44, 46|熊本県, 大分県, 鹿児島県|
|46|鹿児島県|43, 45|熊本県, 宮崎県|
|47|沖縄県|||

## 技術解説

Node.js の [jp-city-lookup](https://www.npmjs.com/package/jp-city-lookup) モジュールでは、隣接する市区町村を取り出せます。その実態は、総務省統計局の [市区町村別メッシュ・コード一覧](https://www.stat.go.jp/data/mesh/m_itiran.html) から 1km メッシュを共有する市区町村 ID を取り出す機能です。

そこで、都道府県内の全市区町村の隣接市区町村から、隣接都道府県を取り出しました。
つまり、上記の一覧表は、1km メッシュ単位で隣接都道府県を求めた結果です。

このため、「1km メッシュ内に 2県が存在する」パターンが発生しない北海道・沖縄は、隣接都道府県がありません。

また反対に、「1km メッシュ内に 3県が存在しているものの、厳密には県境を共有していない県の組」があれば、入ります。（実際にそうしたパターンが存在するかは未確認）
D言語で多次元配列ライブラリを書いた

## はじめに
D言語には[mir](https://tour.dlang.org/tour/ja/dub/mir-algorithm)という多次元配列のパッケージを提供する数値計算用のライブラリがある。が、実は使ったことない。
[D言語で数値計算 mir-algorithm](https://karita.xyz/blog/2017/09/22/026.html)を読むとなんだか難しそうで、使う前から諦めてしまった。mapとかreduceとか便利だが、バグが入り込みやすいところで多用したくない。
なんだかんだfor文（foreach文）で書くのは分かりやすい。

しかし多次元配列のライブラリは欲しい。
自分はいままでFortranで流体用の計算コードを書いたりしているのだけれど、D言語で流体計算やりたいなと思っていて、その為にも多次元配列を簡単に使うためのライブラリが欲しい。

そんなわけで[gged](https://github.com/Zero-error-no-warning/gged)というライブラリを書いたのでその紹介である。

### 多次元配列
もともとD言語は多次元配列を扱う機能がある、気がする。たとえば

``` D
auto array = new double[][](3,5,10); /// 3x5x10の配列
```

こう配列をつくることができる。ただこれを扱うには

``` D
foreach(i;0..3){
    foreach(j;0..5){
        foreach(k;0..10){
            // array[i][j][k]に関する処理
        }
    }
}
```
と、まあ面倒くさい。何が嫌って
- foreachが入れ子になる。
- 3,5,10と要素数に注意しなくてはならない。

何故かというと、D言語の多次元配列は正確にはジャグ配列(jagged array)と呼ばれる配列の配列でしかないからだ。
今は欲しいのは「**ja**gged**じゃ**ない配列」である。


## ggedライブラリ
### 基本的な使い方

ggedで多次元配列はこのように宣言する。

``` D
Gged!(double,3) ggarray = gged!double(3,5,10); /// 3x5x10の配列
```
ここで型に出てくる3は,配列の（3,5,10）の長さ、つまり次元数だ。

gged配列の要素を扱うには次のようにする。

``` D
foreach(i,j,k;ggarray)
{
    /// ggarray[i,j,k]に関する処理
}
```
すっきり！

arrayが要素数の情報を持っているので、要素数なんて気にする必要が無いのだ。
ちなみに処理内で要素数が欲しい場合はこのように書ける。

``` D
foreach(i,j,k;ggarray)
{
    ggarray[i,j,k] = 1.*i/i.max + 1.*j/j.max + 1.*k/k.max;
}
```

### 途中で処理を挟むとき

ところで、こんな風に書きたいときもある。

``` D
foreach(i;0..3){
    foreach(j;0..5){
        f();/// kのループが始まる前にやっておきたい処理
        foreach(k;0..10){
            // array[i][j][k]に関する処理
        }
        g();/// kのループが終わった後にやっておきたい処理
    }
}
```

これに対してはこう書ける。
``` D
foreach(i,j,k;ggarray.Serial)
{
    if(j.once)
    {
        /// jのループ時に一度だけ行う処理
    }
    /// ggarray[i,j,k]に関する処理
    if(k.last)
    {
        /// kのループが終わるときに行う処理
    }
}
```
ここでSerialと書いてるのは、ggedのループをforeachを入れ子構造で書いたとき同じ順序で実行するという宣言である。
gged内では一次元配列でデータを保持しているので、Serialを使わない時は`std.parallelism`をつかって並列化している。

### さらに簡便に書く

次元数を気にしたくない時もあるかもしれない。
``` D
auto A = gged!double(1,2,3);
auto B = gged!double(1,2,3,4);

foreach(i,j,k;A){
    /// A[i,j,k] に関する処理
}
foreach(i,j,k,l;B){
    /// B[i,j,k,l] に関する処理
}
```
配列の次元数に合わせて、`i,j,k...`と書かなきゃいけないのも面倒くさい時には、こう書ける。
``` D
foreach(ijk; A)
{
    /// A[ijk] に関する処理
}
foreach(ijk; B)
{
    /// B[ijk] に関する処理
}
```
このとき`ijk`は`i,j,k`の情報をまとめた構造体となっており、配列のように扱うことができる。
``` D
foreach(ijk; A)
{
    assert(A[ijk] == A[ijk[0],ijk[1],ijk[2]]);
}
```

## まとめ
ジャグじゃない配列を扱うggedライブラリの紹介をした。
今後、流体計算コード書いていくときに欲しいと思った機能を盛り込んでいく予定だ。
実行速度のことは……とりあえず二の次で。
ARC144 A問題 解法


https://atcoder.jp/contests/arc144/tasks/arc144_a

まず最初にわかったのは、各和の総和を求める関数fnがあったとき、

> * f(x)=N かつ f(2x)=M を満たす正整数 x が存在するような，最大の正整数 M．
> * そのような M に対して，f(x)=N かつ f(2x)=M を満たす最小の正整数 x．

ということから、

```
2 * fn(x) = fn(2i)
```

が成り立つ最初のxを見つけられればOKということ。

なのだけど、これを全て探そうとすると、例3の入力値100が与えられた時でさえTLEで追いつかない。

なので考え方を変えて、

```
f(x)=N
```
を満たす、xの中から `fn(2x) = M` になるものを探す作戦を次に思いついた。

f(x)=Nを満たすものは、

N=3のとき、
```
3, 12, 21, 102, 111, 120, 201, 210, ...
```

N=6のとき、
```
6, 15, 24, 33, 42, 51, 105, 114, 123, 132, 141, 150, ...
```

という塩梅。

これに2番目の条件、 `f(x)=N` かつ `f(2x)=M` に当てはめると、

N=3のとき、
```
x : 3, 12, 21, 102, 111, 120, 201, 210, ...
2x: 6, 24, 42, 204, 222, 240, 402, 420, ...
M : 6,  6,  6,   6,   6,   6,   6,   6, ...
```

N=6のとき、
```
x : 6, 15, 24, 33, 42, 51, 105, 114, 123, 132, 141, 150, ...
2x:12, 30, 48, 66, 84,102, 210, 228, 246, 264, 282, 300, ...
M : 3,  3, 12, 12, 12,  3,   3,  12,  12,  12,  12,   3, ...
```

と、xの全ての桁の数字が4以下の場合、 `2N = M`が成り立ち。
5以上の数字が1つでもあると、`2N > M`が成り立つことがわかり、
Mは最大のMを求めるので、`2N`が最大値である。（→1行目に出力する。）

また最大のMのときのxなので、Mは4以下の数字で構成されているということがわかるので、
`4413` `3324` `4441` のような数字になるのがわかる。

 *  大きい位に大きい数字が入るより、1の位から大きい数字が入っているものの方が数字が小さくなる。
    * `N%4`が1~3の時、`3444`と　`4344`なら、`3444`の方が小さいxとなる。
    * 桁は少ない方がいい。
 * `N%4`が0の時は、先頭には0がつけられない。

から、xの最小値は一番下の桁から4埋めして先頭に `N%4` をつければよい。
以上により、下記でACになる。

```
#include <bits/stdc++.h>
using namespace std;

int main() {
  int n;
  cin >> n;
  int m = 2 * n;
  cout << m << endl;
  
  int f = n%4;
  int c = n/4;
  
  if (f != 0) {
    cout << f ;
  }
  for (int i=0; i<c; i++) {
    cout << "4" ;
  }
  
  cout << endl;
  
}
```
Chrome をコマンドプロンプトから起動

#### 動機
Visual Studio Code で［Ctrl］＋［K］→［V］とタイプすると編集中の Markdown をプレヴューすることが出来る訳だが、編集画面を塞ぐし今ひとつ美しくない。そこで以下の方法で Chrome に表示させることにした。

#### 処方 

お使いの chrome に [Markdown Viewer](https://chrome.google.com/webstore/detail/markdown-viewer/ckkdlimhmcjmikdlpkmbgfkaikojcbjk) がインストールされているものとして、次の chrome.bat

```chrome.bat
@echo off
C:/Progra~2/Google/Chrome/Application/chrome.exe "%~f1"
```

をサーチパス上に配置したうえで、Visual Studio Code のターミナル・ウィンドウで

```sh
% chrome hoge.md
```

とすると chrome に hoge.md が表示される。hoge.md を編集した場合、chrome で F5 をタイプすればそれが反映される。

以上、子ネタ。
ubiquiti USW-16-POE(おそらくコンソールポートのない第2世代のUnifiスイッチ全般)でCLIにアクセスする手順

**注意: ubiquitiのスイッチは基本的にUnifiコンソールの配下で使用するものになります**
**この記事の方法だとSWを再起動すると設定はすべて飛ぶのでその点はご注意ください・・・**

スイッチのCLIにアクセスする方法が最初わからず戸惑ったので、手順を忘備録として残します。
試した環境は以下のとおりです。

機種: USW-16-POE
Version: 5.6.0.11463
PC: Windows 11 Home

https://jp.store.ui.com/products/usw-16-poe

### 1, PCをスイッチへ接続し、固定IPアドレスを設定する
スイッチのデフォルトのIPアドレスを確認します。SWに搭載されているタッチパネルをタッチして点灯させ、左下の`i`のアイコンをタップすると表示されます。
自分の環境では`192.168.1.20`でした。
これのIPアドレスにアクセスできるよう、これと同一サブネットの(多分/24にしとけばいいと思います)IPアドレスを設定します。
![2022-07-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213714/8ffea855-fc94-309b-1e84-8055b3d8480a.png)



### 2, スイッチへSSHでログインする
ユーザー名・パスワードはどちらも`ubnt`になります。

ちょっと趣旨は違いますが、以下の記事とかで知りました。。。
https://community.ui.com/questions/The-default-username-password-of-ubnt-ubnt-doesnt-work/eff6ed7f-d496-4c0f-a955-94c2b0317f3c

```
C:\Users\yuuri>ssh ubnt@192.168.1.20
The authenticity of host '192.168.1.20 (192.168.1.20)' can't be established.
RSA key fingerprint is SHA256:yYDa7yDcpXcUXJO+P9RKlWJ3w5GLh4hDdl8aTbIGy/Q.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.1.20' (RSA) to the list of known hosts.
ubnt@192.168.1.20's password:


BusyBox v1.25.1 () built-in shell (ash)


  ___ ___      .__________.__
 |   |   |____ |__\_  ____/__|
 |   |   /    \|  ||  __) |  |   (c) 2010-2020
 |   |  |   |  \  ||  \   |  |   Ubiquiti Networks, Inc.
 |______|___|  /__||__/   |__|
            |_/                  https://www.ui.com/

      Welcome to UniFi USW-16-POE!

UBNT-US.v5.6.0#
```

### 3, `cli` コマンドを実行する。
SSHでログインしたSWのシェル上で`cli`コマンドを実行することで、CLIでSWを操作するモードに入れます。
```
UBNT-US.v5.6.0# cli
Switch#?
  clear             Reset functions
  clock             Manage the system clock
  configure         Configuration Mode
  copy              Copy from one file to another
  debug             debug
  delete            Delete a file from the flash file system
  disable           Turn off privileged mode command
  end               End current mode and change to enable mode
  exit              Exit current mode and down to previous mode
  no                Negate command
  ping              Send ICMP ECHO_REQUEST to network hosts
  reboot            Halt and perform a cold restart
  renew             Renew functions
  restore-defaults  Restore to default
  save              Save running configuration to flash
  show              Show running system information
  ssl               Setup SSL host keys
  terminal          Terminal configuration
  traceroute        Trace route to network hosts
  udld              Configure global UDLD setting
Switch#
```
https://community.ui.com/questions/switch-command-line-in-gen2-switch/81b77d55-3505-4acc-81d5-aa2d93cb8303

Unifiの機器でも機種によっては、SSHでログインしたターミナルから`telnet localhost`で自分自身にtelnetするとCLIで各種コマンドが叩けるようになる機種もあるようです。

## 追記
CLIリファレンスがまだ見つけられていないのですが、おそらくコマンド体系が似ている機種のやつとかで、このあたりが参考になるのかなと思います。
* https://help.ui.com/hc/en-us/articles/231468088-EdgeSwitch-Command-Line-Interface-CLI-and-Admin-Guides
* https://help.ui.com/hc/en-us/articles/360041377413-UniFi-USW-Leaf-CLI-Command-Comparison-
シフト演算と、２進数のかけ算割り算

# シフト演算
５５１０という１０進数の数字がある。
左に１桁ずらすと５５１００になり１０倍になる。
右にずらすと５５１になり１/１０倍になる。

２進数の110の数字がある。
１１０を左にずらすと１１００になり２倍になる。
右にずらすと１１になり１／2倍になる。

この左、右にずらす操作を```シフト操作```という。

## 気づき
このシフト操作が掛け算、割り算に使えるらしいがどういうことだろうか？
次を見ていこう。

# 論理シフト
仮に８ビットの数値```00101100```（１０進数は４４)をシフト操作してみる。
一桁左にシフト操作すると```２^n倍```になる。
一桁右にシフト操作すると```1/2^n倍```になる。

## 左に2桁シフト操作
```10110000```(１０進数は176)
## 右に２桁シフト操作
```00001011```(１０進数は１１）

こうシフト操作していると先頭の１が０に０が１になったりする。
なので符号が反対になる場合がある。
このように符号を考慮せずに行うシフト操作を```論理シフト```という。

## 気づき
論理シフト頭が混乱しそうだ。
演習問題はどんなものになっているのか不安だ。

# もし論理シフトでずらされてた数字が１の場合
## 左論理シフトではみ出した場合
そのビット数で表せる範囲を超えたことを意味する。(オーバフロー)

## 右論理シフトではみ出した場合
はみ出した数字は余りになる。

## 気づき
2^nで掛けるとになるとオーバフローになる。
2^nで割ると余りになる。
ずらしただけで掛け算割り算ができるなんてすごいな。
あまりになるのは想像するのは何か違和感があるけどとりあえず覚えよう。

# 算術シフト
上では符号に考慮せずにシフト操作を行っていた。
それだけでなく考慮するシフト操作がある。それが```算術シフト```だ。
仮に```111001100```（１０進数では−28）で試してみる。

## 左に算術シフト
```10010000```(１０進数では−１１２）
４倍になる。

## 右に算術シフト
```11111101```（１０進数では−７）
1/4倍になる。

# 掛け算と割り算を見てみよう
## 掛け算を行う
=x*(4+2+1)
=x*(2^2+2^1+2^0)
でそれぞれ分配して計算を行う。

## 仮に3*7を行う。
=3*(4+2+1)
=3*2^2+3*2^1+3*2^0
2^2倍は２桁上げるので
11が1100（１０進数は１２）になる。
このように桁を上げて、足していく。

# 割り算を行う
１５／3
1111/11
1111から１１は何回引けるかで割り算が成立する。
1111/11をするときは1111ー1100(4回分)
１１/11をする時は11-11（一回分)
これを繰り返す5回引けたので5で割ることができた。
自宅の Mac に VSCode をインストールしてみた

# 概要
せっかくの３連休、なにも予定がないのでプログラミングの勉強でもしようと思い、とりあえず自宅の Mac に Visual Studio Code をインストールしてみました。

# 環境
![環境.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/013a048e-5d0d-6db7-7c60-6cc7fbb9b026.png)

# Visual Studio Code のダウンロード
まずはダウンロード サイトを検索して開きます。
![検索結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/70fc0cd6-8ca6-0913-cb35-b729d571d7c8.png)

今すぐダウンロードをクリックします。
![今すぐダウンロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/a83b5a06-2a92-b723-6a67-a825d010281d.png)

Mac をクリックします。
![Macをクリック.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/06f6201f-dc30-a2bc-dab0-5ad7c10cf7aa.png)

zip ファイルのダウンロードが完了しました。
![ダウンロード完了.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/e1c0d35d-b765-553a-4d44-f672aac97d98.png)

Mac のダウンロード フォルダで zip ファイルをダブルクリックすると、app ファイルが解凍されます。
この app ファイルを Dock に追加して、アプリケーション フォルダに移動します。
![zipを解凍.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/0e013d9a-fae1-e36c-b01d-61c0c0572926.png)

Dock から Visual Studio Code を起動します。
![起動.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/ed01a452-0457-e5a9-657b-352c4af57059.png)

[開く] をクリックします。
![開く.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/9586de92-c218-3e6b-d8bd-1318c42a1a9a.png)

Visual Studio Code が起動しました。
![GetStarted.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/5ff5a575-41c3-8ee7-5a9e-2b9cc3ec86e2.png)

表示言語を日本語に変更したり、初期設定があるようですが、続きは後日に。
クリックジャッキング とは

## 勉強前イメージ

クリックするものをジャックする・・・？

## 調査

### クリックジャッキング とは

webサイト上に偽装したボタンやリンクを設置して、視覚的にユーザを騙して誘導する手法になります。
webサイトにアクセスすると一見なんの問題もなさそうなサイトですが
実はサイト上にiframe(インラインフレーム)を使って他のサイトを重ね合わせており見た目が透明になっています。
偽装したリンクやボタンをユーザにクリックさせてウイルスに感染させるためや意図していない広告をクリックさせるのに行われたりしています。

### クリックジャッキングの対策

ユーザ向けの対策としては以下2点です。

- JavaScriptやFlashをブラウザで無効にする
- OSやブラウザのアップデートは頻繁に行う

flashを無効にしたからと言って表示されないわけではないですが有効な手段になります。

webサイト向けの対策としては

- HTTPレスポンスヘッダーにX-Frame-Optionsを付ける
- OSやミドルウェアのアップデートは行う

X-Frame-Optionsヘッダの制御でiframeの表示制御を行い、クリックジャッキングの防止に繋がります。

## 勉強後イメージ

iframeで上に表示できないようにしないと・・・ってことね。

## 参考

- [安全なウェブサイトの作り方 - 1.9 クリックジャッキング](https://www.ipa.go.jp/security/vuln/websecurity-HTML-1_9.html)
- [クリックジャッキングとは？その攻撃の概要と対策方法を解説](https://cybersecurity-jp.com/security-measures/6935)
【Webクリエイター能力認定試験エキスパート】試験内容の概要と対策(令和4年度版 )

令和4年度のwebクリエイター能力を初受験しました。
試験対策等についてまとめたため、試験受験を検討されている方の参考となれば幸いです。

## 目次

[試験内容](#試験内容)
[試験対策](#試験対策)
[試験申し込み/当日の流れ](#試験申し込み/当日の流れ)
[試験を受けた後の感想](#試験を受けた後の感想)

## 試験内容/試験レベル
#### （１）試験内容

詳細は公式HPにてご確認ください。
[■Webクリエイター能力認定試験](https://www.sikaku.gr.jp/web/wc/)
- 筆記試験(20分)：Web知識に関する問題20問
↑知識レベルは一般常識に近く、Webに関心のある方なら勉強不要です。
- 実技試験(90分)：5ページ程度のサイト作成
↑時間が短いように見えますが、実際は指示書のコピペで進める部分が多いです。

#### （２）試験レベル
合格率9割、と言われています。ページ作成の経験のある方なら20時間くらいの勉強でまず問題ないと思います。全くWebページを作成したことがない方にとっては難しいかもしれませんね。

## 試験対策

試験対策は以下の2点で問題ないでしょう。
- 公式サイトのサンプル問題を実施
- 公式テキストを読み込み

公式テキストに則った試験内容で、このテキスト以外に勉強は不要です。（私が勉強に使用したのは「Webクリエイター能力認定試験 HTML5対応　エキスパート　公式テキスト　FOM出版」です。）
サンプル問題だけは必ず解くこと！試験の形式がかなり特殊なので、慣れておきましょう。本番に比べて指示が多いので、3時間くらいかかりました汗。公式テキストは初歩的な内容も含んでいるので、300ページ以上ありますが、大体は読み飛ばせると思います。

　実技では、馴染みのない指示をされた場合は、指示ページの上側に用意された「リファレンス」でコードが確認できます。そのため、みっちり覚える必要はなく、本番で調べたコードを使いこなすことができればOKです。基本のHTML構文は用意されていますが、メディアクエリはコードを記述する必要があるので覚えましょう！

## 試験申し込み/当日の流れ

#### （１）試験申し込みについて

　公式サイトより申し込みを行います。①年に2回実施される公開試験、②随時実施している随時試験の2種類があります。思い立ったらいつでも受けれる随時試験がオススメです！
　臨時試験会場では、PCのOS、Webブラウザ、エディターなどの条件が絡みます。いつも使っているツールが使えるところだと安心ですね。会場探しは時間をかけて検討しましょう！

#### （２）当日の流れ

　試験会場に着いたら、まずはサーティファイのアカウント取得から始めます（事前に取得されている方は、ログインするだけで大丈夫です）。実行ファイルを落として、あとはボタン操作など指示通りに進めます。サンプル問題と同じような画面構成なので、事前に対策ができていれば特に面食らうことはないでしょう。
　試験結果は2,3週間後にサーティファイのページで連絡してくれるようです。

## 試験を受けた後の感想

　筆記はWebデザインの一般常識の問題が多く、9割は正答できました。
　実技では、普段使わない指示が出ましたが、リファレンスで調べられるので、見本通りのページを作ることができました。指示はサンプル問題よりも少なく、チェック時間を含めても60分くらいで終わりました。合格率9割、というのも納得ですね。
【Swift】スマホを喋らせる(合成音声)

# 実装
```swift
import SwiftUI
import AVFoundation

struct ContentView: View {
    let synthesizer = AVSpeechSynthesizer()
    var body: some View {
        Button("スピーチ") {
            speech()
        }
    }
    func speech() {
        let text = AVSpeechUtterance(string: "こんにちは、ここの文字を読み上げます")
        let language = AVSpeechSynthesisVoice(language: "ja-JP")
        text.voice = language
        synthesizer.speak(text)
    }
}
```

# 解説
## AVFoundationのインポート
```swift
import AVFoundation
```

## インスタンスの生成
```swift
let synthesizer = AVSpeechSynthesizer()
```

## 読み上げ文を設定
```swift
let text = AVSpeechUtterance(string: "こんにちは、ここの文字を読み上げます")
```

## 言語の設定
```swift
let language = AVSpeechSynthesisVoice(language: "ja-JP")
text.voice = language
```

## 読み上げ開始
```swift
synthesizer.speak(text)
```
Slack APIを用いた絵文字使用回数ランキングの取得

## Slack API アプリの作成、およびトークンの取得手順

https://api.slack.com/

の Create an app からアプリを作成。
App Name は`emojiRanking`などにしておく。
Permissions > User Token Scopes に下記のスコープを追加する。
>`channels:history`
>`channels:read`
>`emoji:read`
>`reactions:read`

Install to Workspaceで絵文字データを取得したいワークスペースにアプリをインストールする。
User OAuth Token に`xoxp-.......-........-..........`のような長いトークンが発行されているので、他人に見られない形で保管しておく。

## WebアプリにAPIトークンを入力
[絵文字ランキングアプリ](https://yonetashoichi-emojiranking-main-574seu.streamlitapp.com/)

## 注意点
・文字化け(?)で「:thumbsup:(+1) の`+`が消える」などのバグがあります。

・カスタム絵文字のみのランキングを作る場合は、各自でカスタム絵文字名のリストを用意していただく必要があります（Slack APIでカスタム絵文字名一覧を取得する方法が分からなかった）。

## 参考にした記事
Slack API アプリの作成手順

https://qiita.com/Senple/items/0e4626307b4559d26bc5

## おわりに
本記事に関してアドバイス等ありましたらありがたいです。
【#31 エンジニア転職学習】Go WebApplications　DB操作

# はじめに
富山県に住んでいるChikaといいます。
毎日投稿を目標に、バックエンドエンジニア転職に向けた学習内容をアウトプットします。

本日より使用しているGoのUdemy教材後半部分である、
Webアプリ作成演習を学習していきます。

バックエンドエンジニアになるまでの学習内容は以前投稿した以下の記事を基にしています。


https://qiita.com/Chika110/items/ef54dddd565a0193ef44

# 本日の学習内容
本日はアプリ開発演習前の各ソフトウェアインストール、GoでのDB操作を中心に学習しました。

* 必要ソフトウェアインストール
* **GoでのDB操作　←Topics!!**

# GoでのDB操作
標準パッケージであるsqlパッケージを使用しました。DBMSはsqlite3です。
以下ポイントをまとめます。
* importでは"github.com ~ go-sqlite3"の前に`_`を付けて、一緒にbuildしてコンパイルするようにしておく
* SQLインジェクションを防ぐために、各SQL文のvalue指定には`?`を使い、ユーザ入力をエスケープするようにしておく
* マルチSELECTの一連の構文はパターンとして覚えておく

使用している教材はこちら↓


https://www.udemy.com/course/go-fintech/


# おわりに
最後までお読みいただきありがとうございました。
アドバイス・応援コメント等いただけますと幸いです。
Ubuntu で Python3 アンインストールしたら画面死んだ

# 状況
ubuntu（alienware）でpython3をアンインストールして再起動すると、画面が一生つかない

# 解決方法
- CTRL+ALT+F2を押してコマンドモードに入る
- sudo apt-get install --reinstall ubuntu-desktop

ubuntuではpythonを消してはいけないという掟があるらしい

# 参考文献
https://blog.goo.ne.jp/field_light/e/9ce9e30c333d6eae8a8d88fa815902a3
初めてのRailsチュートリアルに挑戦！第4・5章

# 第4章の学習内容
1. 組み込みヘルパー
1. カスタムヘルパー
1. 文字列
1. オブジェクトとメッセージ受け渡し
1. メソッドの定義
1. titleヘルパー、再び
1. 配列と範囲演算子
1. ブロック
1. ハッシュとシンボル
1. CSS、再び
1. コンストラクタ
1. クラス継承
1. 組み込みクラスの変更
1. コントローラクラス
1. ユーザークラス

# 第5章の学習内容
1. ナビゲーション
1. BootstrapとカスタムCSS
1. パーシャル（partial）
1. アセットパイプライン
1. 素晴らしい構文を備えたスタイルシート
1. Contactページ
1. RailsのルートURL
1. 名前付きルート
1. リンクのテスト
1. Usersコントローラ
1. ユーザー登録用URL

# 学習を終えて
第4章ではRailsでありながら、以前学習したRubyの基礎を学ぶような内容であった。テキストや動画の通りに進めることで、解決できないエラーも発生しなかったので、学習しやすかった。
第5章ではwebページのレイアウトの学習であったため、HTMLやCSSの知識を活用しながら進められた。webページの見た目を変更していくので視覚的に変化を感じることができ、webページの構造も理解できたのでよかった。
JavaScriptのforEachをGoで再現する

Goでは標準でJavaScriptのforEachのような配列の中身をコールバック関数で操作する機能が無いため自力で実装する必要がある。

# 今回再現する元のJavaScriptのコード
元のコード

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

```js
const array1 = ['a', 'b', 'c'];

array1.forEach(element => console.log(element));
```

# Goで再現したコード
rangeの中身即時関数を配置する形で再現した。
```go
package main

import "fmt"

func main() {
	array1 := [3]string{"a", "b", "c"}

	for _, v := range array1 {
		func(element string) {
			fmt.Println(element)
		}(v)
	}
}

```

# 余談
~~rangeの中身即時関数を配置するのなら、そのままrangeに処理を書けばいい話なるな.....、~~
PhysBonesのColliders項目のMissingやNoneを一括で削除する

# はじめに
VRChatアバターのPhysBoneColliderを削除すると、そのColliderを参照しているPhysBoneコンポーネントのColliders項目にMissingやNoneが表示されます。
MissingやNoneのままだと、VRChatのパフォーマンスランクのコライダー数制限としてはカウントされたままとなってしまうため、一つ一つ削除する必要があります。

この削除作業がなかなか面倒なため、CollidersのMissingやNoneを一括で削除するUnityEditor拡張を作成しました。

本記事では一括削除の手順を説明します。

**※スクリーンショットは旧版（DynamicBone）のものとなっています。**
**※スクリーンショットの「DynamicBone」は「PhysBone」に読み替えてください。**

![mendo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945857/89b9bd8b-7f93-178c-522d-04ff57e95d9d.png)

# CollidersのMissingやNoneの一括削除手順

## 作業の前提
- プロジェクトのバックアップをとっていること
- VRChat SDK3-Avatarをインポートしていること

## VRoidAvatarSetupUtilsの導入
1. 以下のURLから最新版（右上の赤いボタン）を入手します。  
https://jirko.booth.pm/items/3232745
2. ダウンロードしたファイルを展開（解凍）します。
3. 中に入っている**unitypackage**ファイルを、**Assets**にドラッグ＆ドロップし「import」します。
![new_capture1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945857/286c3e31-4e4f-1928-0aeb-1d9ae84e5c35.png)


## MissingやNoneの一括削除
VRoidAvatarSetupUtilsでCollidersのMissingやNoneの一括削除を行います。

1. 上の**VRoidAvatarSetup**メニューから**Remove MissingPhysBoneColliders**を選択します。
![1_new.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945857/677699b6-ebb6-a53d-5e0e-fe64598b1abe.png)


2. ダイアログウィンドウが開くので、Destination AvatarにMissingやNoneを削除したいアバターをヒエラルキーからドラッグします。
![2_new.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945857/cb250901-c1da-a20d-ed75-75bd822834b9.png)


3. ウィンドウ下部の**Delete**ボタンを押下します。
![3_new.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945857/3a2509ed-4793-b8aa-f543-83e52c15c3ae.png)


4. 正常に削除が完了すると、**Delete**ボタンの下に「削除しました」を含むメッセージが表示されます。
![4_new.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945857/d12d6b4a-624a-568a-7f12-ec0b2c25bf97.png)


以上で手順は完了です。
![kanryo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1945857/07a0753e-8be7-3187-464f-94dc8d934f07.png)