OmniAICreator/Qiita-1.07M huggingface dataset:
Playで-WerrorにするためのTips

`-Werror`とは、Scalaコンパイラの警告をエラーと見なす[オプション](https://docs.scala-lang.org/overviews/compiler-options/index.html
)です。Scalaコンパイラの警告はランタイムエラーの予兆ですので、できる限り潰しておきましょう。

https://eed3si9n.com/ja/stricter-scala-with-xlint-xfatal-warnings-and-scalafix/

さて、今回は[Play](https://www.playframework.com/)プロジェクトで`-Werror`を有効にするための、便利なScalaコンパイラオプションを紹介します。

# 便利なScalaコンパイラオプション

## `-Wconf:any&src=target/.*:s`

いきなり呪文みたいなオプションですが、これはtargetフォルダにあるソースコードの警告を抑制するオプションです。Playはroutesや[twirl](https://github.com/playframework/twirl)など、DSLからScalaコードを自動生成しますが、そのいくつかは警告が発生してしまいます（特に多いのが`unused import`）。自動生成コードの警告はアプリケーション側では何とも対処できないため、警告の発生を抑制させてしまいましょう。

https://twitter.com/takezoen/status/1378717430902480899

## `-Wmacros:after`

特に[macwire](https://github.com/softwaremill/macwire)を使っているときに多いのですが、マクロ適用時に警告が出ることがあります。この設定で、マクロ展開時の警告を抑制します。

# 参考

https://docs.scala-lang.org/overviews/compiler-options/index.html
null + null = 0 になるんだけど in JavaScript

JavaScriptを使って画面側で文字列を結合させて、サーバ側で更新処理をしようとしたらなぜか数値の0として受け取っていたのでなぜか調べてみたら、データがどちらもnullで算術演算子の+を使ったら数値に変換されていることがわかりました。
同じことで詰まる人がこれからいなくなるように発生する理由と対策を紹介します。

:::note info
コメント欄に沢山有益なことが書かれているので、そちらの方も是非見てください！
コメントをいただきありがとうございました！！
:::

## null + null = 0 (int型) になる訳
JavaScriptでは、`null`値は空または存在しない値を表します。
`null`値と`+`演算子を使用すると、数値加算として評価されます。
`null`が`0`と評価されるため、2つの`null`値を加算すると`0`になります。

```js
let sFirstName = null
let sLastName = null
let sFullName = sFirstName + sLastName
console.log(sFullName) // 出力： 0 (integer)

```

## 対策

1. Null合体演算子(??)を使用してnullなら空文字を入れる
Null合体演算子(??)を使用して、演算子の両側の値が`null`の場合にデフォルト値を提供することもできます。
```js
let sFirstName = null
let sLastName = null
let sFullName = (sFirstName ?? '') + (sLastName ?? '')
console.log(sFullName) // 出力： ''
```

2.アロー関数で変数を初期化する
```js
const getFullName = (first = '', last = '') => { 
	if (first === null || first === undefined) first = ''
	if (last === null || last === undefined) last = ''
		return `${first} ${last}`
	}
let sFirstName = null
let sLastName  = null
let sFullName = getFullName(sFirstName,sLastName)
console.log(sFullName) // 出力： ''
```

## おわりに

この振る舞いを理解することは、安全で安全なコードを書くために必要なことだと思います！
ESP32: BlueTooth で Lチカ

Ubuntu 24.04 上の Arduino IDE 2.3.2 を使いました。
ボードは、 ESP32 Dev Module です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/5a3289ca-227e-f817-9b1f-bf25a56d6e93.png)


## ESP32 のプログラム

```text:bleutooth_led.ino
// ---------------------------------------------------------------------
//	bleutooth_led.ino
//
//						Jul/28/2024
// ---------------------------------------------------------------------
#include "BluetoothSerial.h"

#define	PROGRAM	"bleutooth_led.ino"
#define	VERSION	"2024-7-28 AM 10:40"

#define LED1 32
#define LED2 33
#define LED3 25
#define LED4 26
#define LED5 27
#define LED6 14
#define LED7 12
#define LED8 13

int leds[8] = {LED1,LED2,LED3,LED4,LED5,LED6,LED7,LED8};

BluetoothSerial SerialBT;
// ---------------------------------------------------------------------
void led_proc (String aStr)
{
	for (int it=0; it<8; it++)
		{
		String str_on = "ON" + String(it);
		String str_off = "OFF" + String(it);
 
		if (0 <= aStr.indexOf(str_on))
			{
			digitalWrite(leds[it], HIGH);
			}
		else if (0 <= aStr.indexOf(str_off))
			{
			digitalWrite(leds[it], LOW);
			}
		}

}

// ---------------------------------------------------------------------
void setup()
{
	SerialBT.begin("ESP32test_01");
	delay(1000);

	Serial.begin(115200);
	delay(3000);
	Serial.println(PROGRAM);
	Serial.println(VERSION);
	Serial.println();
	
	for (int it=0; it<8; it++)
		{
		pinMode(leds[it], OUTPUT);
		}
}

// ---------------------------------------------------------------------
void loop()
{
	String aStr = "";  
	if (0 <  SerialBT.available() )
	{
  
	// 終了文字まで取得
	aStr = SerialBT.readStringUntil('\n');
	Serial.print("Input:");
	Serial.println(aStr);

	if (2 < aStr.length())
		{
		led_proc (aStr);
		}
	}
}

// ---------------------------------------------------------------------
```

動作確認

手動でコマンドを送信
>ON0
>OFF0
>と送信します。

```
$ cu -l /dev/rfcomm1 -s 115200
Connected.
```

Python でコマンドを送信

```py:bleutooth_led_test.py
#! /usr/bin/python
#
#	bleutooth_led_test.py
#
#						Feb/11/2023
# ------------------------------------------------------------------
import sys
import serial
from time import sleep

sys.stderr.write("*** start ***\n")
 
ser = serial.Serial('/dev/rfcomm1',115200,timeout=None)
#
sleep(2.0)
for it in range(8):
	str_on = "ON%d\n" % it
	str_off = "OFF%d\n" % it
	ser.write(str.encode(str_on))
	sleep(2.0)
	ser.write(str.encode(str_off))
# 
ser.close()

sys.stderr.write("*** end ***\n")
# ------------------------------------------------------------------
```
Chrome/Edgeでlocalhostへhttpsアクセス時に警告表示される動作の回避

# 目的

開発中などにローカルでHTTPサーバーを起動して動作確認することはよくあると思います。
証明書も適当なので、Webブラウザからアクセスすると警告ページが表示されますね。
Google Chrome、または、Chromium ベースのMicrosoft Edge における回避方法をメモしておきます。

**確認したバージョン**
- Chrome バージョン: 110.0.5481.78（Official Build） （64 ビット）
- Microsoft Edge バージョン 110.0.1587.41 (公式ビルド) (64 ビット)

※いずれもWindows11で確認しています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53115/dafa7631-efa8-b1af-6b94-4e7ec90f7cb7.png)


# 回避方法1

警告ページで `詳細設定` をクリック、さらに `localhostにアクセスする（安全ではありません）` をクリックすることで回避できます。
当然ですが、危険の可能性を指摘し、これ以上のブラウジングをやめてもらうための警告ページなので、「ああ、ダメなんだ…」と諦めてしまいそうな表示になっています。
内容をよく読めば危険を理解したうえでアクセスできることが示してあります。

# 回避方法2

実験的機能設定ページ `chrome://flags` に、「localhostへのリクエストの場合は無効な証明書を許可する」という、やりたいことそのままの設定がありました。
ただし、flagsの設定は無くなる可能性もあります

```
Allow invalid certificates for resources loaded from localhost.
Allows requests to localhost over HTTPS even when an invalid certificate is presented. 
#allow-insecure-localhost
```

下記を開いて該当項目を有効に設定すればOKです。
無効にすれば元の設定になります。簡単ですね。

- Chrome
    - chrome://flags/#allow-insecure-localhost
- Edge
    - edge://flags/#allow-insecure-localhost

# 補足

## 回避方法1の設定保存場所

**回避方法1** を実施した場合、その指示は記憶されます。つまり、一度許可指示すると次は警告ページが表示されません。
毎回表示されるのも面倒なので妥当な挙動とは思いますが、元の設定に戻したい場合はどうすれば良いのでしょうか。

設定ページなどからの操作は見つけられませんでしたが、プロファイルごとの設定ファイルに設定が保持されていることを見つけました。

設定ファイルはWindowsでは通常、下記になると思います。

- Chrome
    - `%LOCALAPPDATA%\Google\Chrome\User Data\Default\Preferences`
- Edge
    - `%LOCALAPPDATA%\Microsoft\Edge\User Data\Default\Preferences`

※プロファイルを作成している場合は `Default` 部分が `Profile 1` などになります。


ファイルはJSONテキストになっていて、許可したドメインが`ssl_cert_decisions` キー部分に追加されていくようです。
削除対象の設定をエディタなどで削除することで、元の状態を再現することができました。
（ブラウザを終了してから設定ファイルを編集します）

下記は整形してありますが、実際は改行なしのJSONです。

```json
"ssl_cert_decisions": {
  "https://localhost:443,*": {
    "last_modified": "13320488980363510",
    "setting": {
      "cert_exceptions_map": {
        "************************************************": 1
      },
      "decision_expiration_time": "13321093780363497",
      "version": 1
    }
  }
}
```

## もともと何をしようとしていたのか

ローカルでセキュアWebSocket通信を試していたのですが、通信ができず困っていました。
下記のようにエラーになります。

`net::ERR_CERT_AUTHORITY_INVALID` が共通のエラーコード（？）のようです。
なお、理由は追及していませんが、 `Error in connection establishment: net::ERR_CERT_AUTHORITY_INVALID` という大切な部分が表示されないパターンもあるようでした。

```js
const ws = new WebSocket('wss://localhost:8080');

WebSocket connection to 'wss://localhost:8080/' failed: Error in connection establishment: net::ERR_CERT_AUTHORITY_INVALID
```

コードでWebSocketした場合は警告ページも表示しようがありませんので対処できず困っていましたが、本記事の回避設定でlocalhost宛てのwssアクセスも許可できました。
WebSocketも HTTP通信ということで、共通の設定を参照するのかなと推察しています。
homebrewを使い、MySQLをMacOSにインストール

# 初めに
数行程度のクエリが書ける程度のエンジニア。
現在携わっている案件で、ガッツリ内部結合や外部結合を使う必要があるが、DBの知識が全くないためとりあえずMySQLをインストールするための環境づくりをしていきます。

# 環境
- PC ：　MacBook Pro (13-inch, M1, 2020)

# 参考サイト
 > https://style.potepan.com/articles/19020.html

# 内容
- ターミナルを立ち上げ、brewコマンドを実行する  
<code>  brew install mysql  </code>
　　実行の最後に、「/opt/homebrew/opt/mysql/bin/mysqld_safe --datadir=/opt/homebrew/var/mysql」と表示されます。

- mysqlがインストールされてるか確認
<code> brew info mysql </code>
 「mysql: stable 8.0.32 (bottled）　」と表示される。


以上。
OpenFOAMの結果をblenderで可視化してみる#03 paraviewによる可視化

# はじめに
前回からの続き。
今回は，openFOAMの結果をParaviewで表示して，可視化するまでを行う。

# Paraviewによる解析結果の表示
Paraviewによる可視化の際には，OpenFOAMから呼び出す（`paraFoam`）ことが可能。
ただし，今回は，計算はWSL（Ubuntu），可視化はwindowsで行うので，
Paraviewを別途起動して，読み込みようにする。
具体的には，解析したケースフォルダに，`{好きな名前}.foam`を保存して，それをParaviewで開くだけ

``` sh
#paraviewがアクセスできる場所にデータを移す
mkdir /mnt/c/data
cp -r ~/openfoam/dambreak /mnt/c/data/
cp -r ~/openfoam/iobasins /mnt/c/data/
touch /mnt/c/data/dambreak/run.foam
touch /mnt/c/data/iobasins/run.foam 
```
## Paraviewでの可視化例
![dambreak.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601976/691ed77f-adb7-b5e1-bc14-08acc00bcd8e.gif)

## Paraviewでの可視化例　iobasins
![iobasins.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601976/9f1f569f-122a-33d0-6dcf-ed2455ac1a47.gif)

::: note info
Paraviewでは，alpha>=0.5とした水の領域のみを表示するよう，Clipを適用している。  
clipのparameter
- Scalars: alpha.water
- Value:0.5
- Invert:off
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601976/2feb0f7d-b0a2-2b8e-70b1-34341c968ba8.png" width="40%">
:::

# 余談，動画の作成方法
Paraviewでは，動画の作成は，Save_Animationで行うことができる。
保存形式は下記の通りで，画像形式だと連番ファイルが作成される。
- 画像形式
    - bmp
    - jpeg
    - png
    - tif
- 動画形式
    - avi
    - mp4
    - ogv

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601976/c39e2d47-220c-1c04-1255-b8087826cb84.png" width="40%">


![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f323630313937362f33643866343530342d376566322d666536322d633465612d356262303838663135363531.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601976/0bc0b384-1cdd-874f-7ca9-3c7ecb6937f6.png)
Azure にユーザーを追加したい 〜Azure ロールと Azure AD ロールの違い〜

### Azure にユーザーを追加したいけど、どこで権限付与すればいいの？
例えば、あなたが Azure サブスクリプションの管理者になったとしましょう。
まずは、開発者や運用者を追加して Azure リソースを操作させたいです。
ただ、どのメニューからユーザーを追加し、権限設定すれば良いかイマイチわからない。
そんな悩みを解消するには、Azure ロールと Azure AD ロールという 2 種類のロールの存在を認識する必要があります。

### Azure ロールと Azure AD ロール
Azure でリソースを作成したりするために必要な権限は Azure ロールです。
一方で、Azure ロールを付与する実体となるユーザーは Azure AD に存在しています。
この Azure AD を管理するのに必要なロールが Azure AD ロールです。

#### Azure ロール
Azure リソースを操作するために必要なロールです。
主な Azure ロールとして以下があります。
- 所有者
- 共同作成者
- 閲覧者

例えば、Azure サブスクリプション全体でのリソース操作権限を付与するには、サブスクリプションの`アクセス制御 (IAM)`から設定可能です。
![20230211-img1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423135/326b9293-0cb2-adc3-2d90-26bc0f9fc67a.png)
Azure ロールの一覧は[こちらの公式ドキュメント](https://learn.microsoft.com/ja-jp/azure/role-based-access-control/built-in-roles)から確認できます。

#### Azure AD ロール
Azure AD でユーザーやアプリケーションを管理するためには Azure AD ロールが必要です。
主な Azure AD ロールには以下があります。
- グローバル管理
- ユーザー管理者
- アプリケーション管理者

Azure AD ロールは Azure AD のメニューなどからユーザーに権限付与できます。
Azure AD ロールの一覧は[こちらの公式ドキュメント](https://learn.microsoft.com/ja-jp/azure/active-directory/roles/permissions-reference)から確認できます

### Azure リソース操作権限を付与したい場合、基本は Azure ロール
実際に Azure リソースを操作させたい場合は ユーザーに Azure ロールを付与してあげます。
Azure ロールの設定方法は、以下の公式ドキュメントに記載があります。
基本は `アクセス制御 (IAM)`の[追加]から、ロールと割り当てるユーザーを選択し、割り当てすれば OK です。

https://learn.microsoft.com/ja-jp/azure/role-based-access-control/role-assignments-portal

ただし、Azure ロールをユーザーに割り当てようとしたときにメンバーとして表示されない場合、Azure AD にそのユーザーが存在していない可能性があります。
その場合は、Azure AD に対象のユーザーを追加する必要があります。
Azure AD へのユーザー追加は以下の公式ドキュメントをご参照ください。

https://learn.microsoft.com/ja-jp/azure/active-directory/fundamentals/add-users-azure-active-directory

Azure AD にユーザー追加後、改めて Azure ロールを付与してあげましょう。
Azure リソースの操作だけであれば Azure AD ロールの付与は必要無いことが多いです。

一方で、Azure AD でユーザーやグループを管理したり、Azure AD を利用したサービス開発をする場合などでは Azure AD ロールが必要になってきます。
必要なロールを一覧から確認して Azure AD ロールを付与しましょう。

### Azure ロールと Azure AD ロールの違いを意識しましょう
Azure を操作していたり、ドキュメントを読んでいると「所有者」や「グローバル管理者」など様々なロール名が出てきて混同してしまうかもしれません。
まずは、これら 2 つが異なる概念のロールを指していると意識できると、Azure でのユーザー権限管理のハードルが下がると思います。
Fix: Mouse Dictionary が Dark Reader 使用時に背景が白くなり見づらい

デフォルトでは下の画像の左側のようになり、見づらいので右のようにします。
![before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276332/59f45cd6-7d09-c9d0-ea9d-cabe3ee1817b.png)![after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276332/b1a37a5e-fada-6c42-29c2-65ead477ee63.png)

Dark Reader の開発者ツールでテーマエディタを開きます。
テーマエディタの設定の詳細は https://github.com/darkreader/darkreader/blob/main/CONTRIBUTING.md#how-to-use-the-dev-tools にあります。
*セクション（すべてのサイトが対象）の CSS ルールに次の設定を加えます。

```css
div[id^="____MOUSE_DICTIONARY"] {
    background-color:black !important;
}
```
つまり、すべてのサイトで Mouse Dictionary のウィンドウだけ背景を黒くします。
還暦爺がAtCoderにPascalで挑戦③　お助けツール作りました。

お助けツール
---------------------------
コンテストでは早く提出できれば同じ回答数でも順位が違ってきます。
ABC288では3完だったけどいつもより速くできたのでなんと破格の
パフォーマンス1100をいただけてウハウハしてました。
茶色レベルだと提出が1秒早いだけでも結構変わってくるようなので
無駄時間を削減すべくお助けツールを自作しました。
開発ツールはもちろんDelphi11 です＾＾
こんな感じ
![main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625152/49dffa03-121d-7905-dca7-8564b05be01b.png)
![func.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625152/4b733095-034f-0270-bd16-04a3f9cd90dc.png)

機能
---------
・コードテストだとコンパイルエラーが出ないのでコンパイルエラー表示
・ソースを分割指定して変数宣言を追加したい場合にカーソル移動を不要にする。
　（これはPascalの弱点です）
・問題URLを指定してHTMLを解析し入力例、出力例を自動取り込み。
・実行結果と出力例を比較して自動判定。（結果を背景色で表示）
・URLごとにソース、入出力例を保存しておさらいを簡易化。
・用意しておいた関数を簡単に取り込める。

追加したい機能
--------------
・エディタの自動インデントができないのが結構しんどい
・デバッグできたらなあ（具体案無しw）
・CPU時間の表示

勉強を進めていって関数を充実させないとね。
めでたしめでたし。
PHP導入、MAMPで「The requested URL was not found on this server.」で1時間溶かした話。

タイトル通り、PHPの導入の際、ページが反映されず、1時間と溶かしました。

お急ぎの方は[結論](https://qiita.com/saburo555/items/7db1d62ae9b6237b7441#結論)へ！

# 過程
MAMPをインストールし、起動でき、初期ページも表示されるのに、「The requested URL was not found on this server.」が表示される。

Document rootもhtdocsになっていて、「MAMP/conf/apache/httpd.conf」内のDocumentRootも同じになっていて、間違いがない。

参考
https://qiita.com/vber_program/items/962d32ece552d4ebeacf

エラーログも見るも、以下のサイトのようなエラーはなく、お手上げ状態に。。。

参考
https://teratail.com/questions/288997


# 結論

もう一度コードを見ると、明らかなミスを発見！

```php:NGコード
<?php

echo 'aaa'

?>
```

```php:OKコード
<?php

echo 'aaa';

?>
```

お分かりだろうか？

そうecho 'aaa';の「;」忘れでした。

あ〜、時間がもったいない！


（追記）
現在、一度表示されてから「;」を抜いても、画面はしっかり表示されるようです。
導入の初期表示で、「;」なしだと「The requested URL was not found on this server.」となる模様です。
BlazorをAzureにデプロイする方法


とりあえず書き殴り、いつか清書する。

# 前提条件
1. Githubのアカウントを持っている
2. Azureのアカウントを持っている
3. Blazorアプリを作成済み
※デプロイだけ試してみたい場合はテンプレートがあるのでそちらをクローンして試してみて下さい。

https://github.com/staticwebdev/blazor-starter

# Azureでの操作

* リソースの作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/fb4ff2f5-8fde-bce2-b5bc-8e98ffe93b09.png)

* 静的Webアプリを選択し作成ボタンをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/ca51b461-cdfd-af1d-eb89-f09c432634d0.png)

* 基本タブを入力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/e2577e3b-c411-8ad1-c891-fcca54e0d572.png)

Github アカウントでサインイン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/7b8c8216-4c2f-9b36-6e78-0fc72f3745a6.png)

Authorize Azure-App-Service-Static-Web-Appsをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/98461544-5069-9a24-5b82-e8c5155b8a39.png)

Githubリポジトリの情報、ビルドの詳細を入力
確認および作成ボタンをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/5b30a54e-7722-5043-83ae-549d55da60fe.png)

こんな画面が表示されて少々時間がかかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/76ed0a49-4ecd-2188-44a3-3b624c697445.png)


問題なければ作成ボタンをクリック

どうやら無事にデプロイできた様子。

リソースに移動をクリックすると詳細情報が見られます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/fcf74677-bbae-0746-4198-645cd9ef5541.png)

Githubの状態を確認する必要があるようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/c173a278-c70f-6d44-ac9e-2cb4bae7be08.png)

Github workflowsにてデプロイ作業が進んでいることが確認できます。そこそこ時間がかかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/9d08d740-a392-da84-3c93-f3ac85285f76.png)

ビルド完了です！5分くらいかかりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/f1912799-8ff2-07db-a679-efebfdd190a3.png)

先程のリソースの画面に戻ってみてURLを叩いてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/52a457b6-3195-655a-5507-48468e8cbe2b.png)



最後にデプロイできてるか実際にURLを叩いて確認してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/cf74ad6a-fb50-0774-bacb-b747fe97caff.png)

問題ないですね！

## 実際は問題ありました
Visual Studio 2022でBlazor WebAssemblyプロジェクトを作成するとフォルダ構成がApi,Client,Sharedという構成で作成されません。

しかし、githubからAzureにデプロイする際はそれらのディレクトリがある前提でビルドが行われるので私の場合はビルドエラーのためデプロイできませんでした。

初めから下記のテンプレートを使って開発すれば問題なくデプロイできるはず！初めから知っていれば…。そういうこともあるよね。

https://github.com/staticwebdev/blazor-starter
【サブスクあるあるうっかり更新防止】PMI®本部会員の自動更新停止方法

# はじめに
Project Management Professional (PMP)® の資格試験を受験する / した人は、受験料の節約や勉強のためにPMI®本部会員に登録し、最初の1年のみ有料会員となり、翌年以降は登録を解除する人も多いと思います。

しかし、サブスクあるあるですが、更新の時期が迫るまで登録解除のことを忘れていて、気づいたときには自動更新済み、となる人もいるでしょう。
・・・ええ、かくいう私がそれでした。

望まぬ自動更新を減らすため、PMI®本部会員の自動更新停止方法をご紹介します。この手順は __「自動更新」の停止方法__ となるため、即座に会員登録が解除されるわけではありません。自動更新停止後も有効期間内は悠々自適な本部会員ライフ(？)を送ることができますので、次回更新を考えていない場合にはすぐに実施することをおすすめします。

なお、以下に示す手順については本稿記載時点のものであり、画面レイアウトや手順はこれまでも不定期で変更となっているようです。
また、著作権に配慮し対象ページの画像は掲載しません。
なるべくわかりやすい記載を心がけますが、予めご了承ください。

# PMI®本部会員の自動更新停止方法
## 1. 会員アカウントでログイン
[PMI®のサイト(https://www.pmi.org/)](https://www.pmi.org/)にアクセスし、画面上部の「__Log in__」から「Username」「Password」を入力し、ログインします。

## 2. 「Dashboad」画面から「View Details」に移動
画面上部のアカウント名を押下すると表示される「Dashboad」を押下します。
画面遷移後に「Membership」の「ID」右上に表示される「<ins>__View Details__</ins> 」を押下します。

## 3. 「Membership Automatic Renewal」の設定確認
「Membership Overvie」画面の「Membership Details」に表示されている「__Membership Automatic Renewal__」が既に「__Off__」であれば本部会員の期間終了後に自動更新されません（作業完了です）。
「__On__」の場合はその右の「<ins>__Manage__</ins>」を押下します。

## 4. 「Manage Membership」画面で設定変更
「Manage Membership」の「Your membership will automatically renew in ～」の左に表示される __トグルスイッチ__ を押下します。
確認画面「Turn Off Membership Automatic Renewal?」に遷移し、表示される「__Turn Off Auto-Renewal__」ボタンを押下します。
トグルスイッチ左に「__Off__」と表示されていることを確認します。
再び「Dashboad」画面から「View Details」に移動し、 __3. 「Membership Automatic Renewal」の設定確認__　で確認した「__Membership Automatic Renewal__」が「__Off__」になったことを確認します。

# おわりに（余談）
以上がPMI®本部会員の自動更新停止方法となりますが、PMI®本部会員であるうちにやるべきこととして個人的におすすめしたいのが「 __On-Demand Webinars__ 」の視聴です。
ここまで読んだ方の多くはご存じかと思いますが、PMP®資格は更新のために __PDU__ （プロジェクトマネジメントに関する学習や専門家としての活動を測定する単位）を60取得する必要があります。PMI®の配信する「On-Demand Webinars」を視聴すると自動でアカウントにPDUが反映されますが、PMI®本部会員は「Premium」動画を無制限に視聴できます（「Free」動画はPMI®本部会員でなくても視聴可能です）。こちらで60PDUを取得してしまうのがおすすめです！
（現時点で動画は日本語非対応ですが・・・。）

# 関連ページ
https://qiita.com/TakuyaSuzuki/items/7e80e6e7d6665a2d9632
Cloud Storage for Firebaseのエミュレーターに接続して画像をアップロードしたら失敗した話

開発中のAndroidアプリで、ローカルで起動したFirebase Emulator SuiteのCloud Storageに接続するように設定しました。

```shell
FirebaseStorage.getInstance().useEmulator("10.0.2.2", 9199)
```

しかし、通常通り画像のアップロード処理を行なってみたところ次のようなエラーが発生しました。

```shell
StorageException has occurred.
	User does not have permission to access this object.
		Code: -13021 HttpResult: 403
            ...
            ...
com.google.firebase.storage.StorageException: User does not have permission to access this object.
```

調べてみたところ、自動的に読み込まれた**storage.rules**の内容がデフォルトのままになっており、書き込みと読み取りに対するアクセスがすべて`false`に設定されていました。

```rules
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if false;
    }
  }
}
```

なので、一時的にアクセス可能にするために`allow read, write: if true;`に書き直しました。

```rules
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if true;
    }
  }
}
```

エミュレーターを再起動して、もう一度アップロード処理を実行したところ問題なくローカルのストレージにファイルがアップロードされました。

:::note alert
このルールを本番環境にデプロイしないでください。正しくルールを設定した上でデプロイすることを心がけましょう。
:::
ESP32: BlueTooth とシリアルポートの相互通信

Ubuntu 24.04 上の Arduino IDE 2.3.2 を使いました。
ボードは、 ESP32 Dev Module です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/2b911eb1-6dfb-59d2-e0a6-8cf7078c2551.png)


## ESP32 のプログラム

```text:bluetooth_terminal.ino
// ---------------------------------------------------------------------
//	bluetooth_terminal.ino
//
//						Feb/11/2023
// ---------------------------------------------------------------------
#include "BluetoothSerial.h"

BluetoothSerial SerialBT;

// ---------------------------------------------------------------------
void setup()
{
	Serial.begin(115200);
	SerialBT.begin("ESP32test_01");
}

// ---------------------------------------------------------------------
void loop()
{
	if (Serial.available())
		{
		char data = Serial.read();

		SerialBT.print(data); 

		if (data == 0x0d)
			{
			SerialBT.println(""); 
			}
		}

	if (SerialBT.available())
		{
		char chx = SerialBT.read();

		Serial.print(chx); 

		if (chx == 0x0d)
			{
			Serial.println(""); 
			}
		}
}

// ---------------------------------------------------------------------
```

## 動作確認

BlueTooth 側

```text
$ cu -l /dev/rfcomm1 -s 115200
Connected.
```

シリアルポートがわ

```text
$ cu -l /dev/ttyUSB0 -s 115200
Connected.
```
【Next.js】好きな画像データをfaviconに設定する方法 〜TSでも怒られない〜

# 【はじめに】
先日Next.jsの環境構築を終えて、さあ開発していくぞ！と思った矢先、
「faviconを好きな画像に変更したいけど、どうしたらいいんだろう、、？」
と、ふと思い調べてみても、なかなか自分の求めている情報に出会えなかったため、備忘録も兼ねてここにまとめておきます。

# 【環境】
 - Node.js - 16.14.0
 - Next.js - 13.1.4
 - React - 18.2.0
 - TypeScript - 4.9.4

# 【faviconを設定する方法】
1. public/favicons内にfaviconに設定したい画像を用意
1. src/pages/_document.tsxで、faviconを設定

```_document.tsx
~~~
<Head>
    <link rel="icon" href="/favicons/sample.png" />
</Head>
~~~

// <link rel="shortcut icon" href="/favicons/sample.png" />
// rel属性にshortcutの記述が必要なのは、IE8以下への対応が必要な時のみなので、
// 基本的には記述しないようにしましょう。
```

# まとめ
Next.jsでfaviconを設定する方法をまとめてみました。
faviconは開発時に何かと忘れられがちな印象がありますが、とても重要なのでぜひこの記事を参考に設定してみてください！

最後まで読んでくださりありがとうございました。
この記事が少しでも、Next.jsでfaviconの設定方法で悩んでいる人の役に立てば幸いです。
もっと良い方法や間違いなどあれば、優しく指摘していただけると嬉しいです。
この記事がいいなと思えば、「いいね」と「フォロー」よろしくお願いします！
GaugeでIntellijから実行するとFailed to get configuration from Gauge properties fileというエラーが出る

# はじめに

転職して最初に利用することになったテストフレームワーク`Gauge`を導入するのにつまづいたところをまとめます
今後ずっと利用していく技術になりそうです

# 問題

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/1596385e-ab9b-6d49-1d4d-e16ae7f42bc2.png)

Intellijで`Gauge`をUI上から実行すると以下のエラーが発生しました

```
/usr/local/bin/gauge run --machine-readable --hide-suggestion --simple-console /home/watanabejin/workspace/gauge-e2e/specs/example.spec
Testing started at 11:20 ...
2023/02/11 11:20:02 Failed to get configuration from Gauge properties file. Error: open /usr/local/bin/gauge /config/gauge.properties: no such file or directory
2023/02/11 11:20:02 Failed to get configuration from Gauge properties file. Error: open /usr/local/bin/gauge /config/gauge.properties: no such file or directory
2023/02/11 11:20:02 Failed to get configuration from Gauge properties file. Error: open /usr/local/bin/gauge /config/gauge.properties: no such file or directory
2023/02/11 11:20:02 Incorrect value for check_updates in property file. Cannot convert  to boolean.
2023/02/11 11:20:02 Failed to get configuration from Gauge properties file. Error: open /usr/local/bin/gauge /config/gauge.properties: no such file or directory
2023/02/11 11:20:02 Failed to get configuration from Gauge properties file. Error: open /usr/local/bin/gauge /config/gauge.properties: no such file or directory
Compatible version of plugin html-report not found. Installing plugin html-report...
Failed to install plugin 'html-report'.
Reason: Could not construct plugin install json file URL. Could not find gauge repository url from configuration.
Compatible version of plugin java not found. Installing plugin java...
Failed to install plugin 'java'.
Reason: Could not construct plugin install json file URL. Could not find gauge repository url from configuration.
Installing required plugins.
Error ----------------------------------

[Gauge]
Failed to start gauge API: Plugin 'java' not installed on following locations : [/usr/local/bin/gauge /plugins]

Get Support ----------------------------
	Docs:          https://docs.gauge.org
	Bugs:          https://github.com/getgauge/gauge/issues
	Chat:          https://github.com/getgauge/gauge/discussions

Your Environment Information -----------
	linux, 1.4.3, f98dd40
	Could not retrieve plugin information.

プロセスは終了コード 1 で終了しました
```

`mvn test`だとうまくいっており、原因が不明でした

# 解決方法

これはIntellijのgaugeプラグインが実行するバイナリを知らないのが原因でした

設定から`Gauge`のプラグインを開いて、`Gaugeのバイナリーのパス`を設定すれば動くようになりました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/a127a900-2649-cea8-975a-a67aeccf61d8.png)

パスの位置は

```
$ which gauge
```

でわかります

# おわりに

やっとGaugeの設定が終わりました。一苦労でしたが次のステップに進めるのでよかったです
IntellijのKotlin実行で失敗するときにみたところ

# はじめに

この記事を書こうと事前にエラーをメモっておいたのですが、わかりやすいエラーの部分をコピーしておらず微妙なタイトルになりました
もし実行できなくて困った方はこの可能性があるかもしれないので、確認してみてください

# 問題

Intellijで実行をUIからすると以下のエラーがでました

```
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  33.558 s
[INFO] Finished at: 2023-02-11T10:29:35+09:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal com.thoughtworks.gauge.maven:gauge-maven-plugin:1.3.1:execute (default) on project hoge-e2e: Gauge Specs execution failed -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
```

# 解決方法

`JDK`が`Kotlin SDK`になっていたのが原因でした

正常に動作するには`openjdk-19`にする必要がありました

`外部ライブラリ`->`Kotlin SDK`を右クリック(一番上にあります)->プロジェクト

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/9ab581f5-6fe4-f777-772c-b78562e5664a.png)

`SDK`を`openjdk-19`に変更して適応しました

変更後は以下のようになっています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/cd44af7a-d09f-9570-7967-1666daa9668c.png)

# おわりに

言語仕様を全然理解していないのでこういった小さなことでもかなりの時間躓いてしまいます
はやくなかよくなりたいです
Ubuntu 22.10にNode.jsとnpmをインストール

```bash
sudo apt install -y npm
```

環境

```bash
$ cat /etc/os-release 
PRETTY_NAME="Ubuntu 22.10"
NAME="Ubuntu"
VERSION_ID="22.10"
VERSION="22.10 (Kinetic Kudu)"
VERSION_CODENAME=kinetic
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=kinetic
LOGO=ubuntu-logo
```
java.lang.IllegalStateException: Unable to load cache itemエラーが発生する

# はじめに

Javaのテストツールを導入しようとした際に発生したエラーです

# 問題

`mvn test`をしたところ以下のエラーが発生しました

```
watanabejin@watanabejin-Latitude-3520:~/workspace/gauge-e2e$ mvn test
[ERROR] Error executing Maven.
[ERROR] java.lang.IllegalStateException: Unable to load cache item
[ERROR] Caused by: Unable to load cache item
[ERROR] Caused by: Could not initialize class com.google.inject.internal.cglib.core.$MethodWrapper
[ERROR] Caused by: Exception com.google.inject.internal.cglib.core.$CodeGenerationException: java.lang.reflect.InaccessibleObjectException-->Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @49c43f4e [in thread "main"]
```

# 解決方法

`JAVA_HOME`を設定したところ治りました

```
$ sudo update-alternatives --config java

There are 2 choices for the alternative java (providing /usr/bin/java).

  Selection    Path                                         Priority   Status
------------------------------------------------------------
  0            /usr/lib/jvm/java-11-openjdk-amd64/bin/java   1111      auto mode
  1            /usr/lib/jvm/java-11-openjdk-amd64/bin/java   1111      manual mode
* 2            /usr/lib/jvm/java-11-oracle/bin/java          1091      manual mode

$ sudo vi /etc/environment
```

以下を追加して保存(値は各自の環境に合わせてください)

```
JAVA_HOME="/usr/lib/jvm/java-11-openjdk-amd64"
```

```
$ source /etc/environment
$ echo $JAVA_HOME
```

# おわりに

Javaほとんどやったことがないので環境依存のエラーにたくさん遭遇します
コンテナ化できないのが毎度悩ましいです

# 参考

https://www.digitalocean.com/community/tutorials/how-to-install-java-with-apt-on-ubuntu-20-04-ja
Vue備忘録 with Flask　～ディレクティブ

# Mustache

マスタッシュ

と読みます。
jinjaとは別のテンプレートエンジンみたいなもの。
HTMLタグに追記できる独自の属性(v-...)

ディレクティブに関しては以前テストページとして作ったものがあるので
それを参考に

https://raisack.com/flask-MyWebApp/vuejs/vue/index.html

# v-if
```html
v-if = "bool型の変数"
```
trueだったらそのタグ内を表示し、
falseだったら
```html
<div v-else>...</div>
```
else説のタグを表示する

# v-for
```
v-for = "item in data"
```
とすることで、for内のタグを
dataの個数分だけ表示する。
なお、data型は配列
```
data:[
    {name: "Taro", age: 30},
    {name: "Hanako", age: 28},
    {name: "Satoshi", age: 22}
]
```
というdata配列だとしたら、
__item.name__
とすることで、名前にアクセスできる。

# v-bind
属性に変数を設定する
```html
v-bind:属性 = "値"
// 属性には"class"、"name"とか
```
ソースを見た方が分かりやすいと思うので
```html
<!-- Vue.js container -->
<div id="app">
  <mycomp kind="0" />
</div>

<!-- mycomp's template -->
{% raw %}
<script type="text/x-template" id="mycomp-template">
  <div v-bind: class="'h5 alert alert-' + data[kind]">
    This is {{ data[kind] }} alert!!
  </div>
</script>
{% endraw %}

<!-- Vue.js script -->
<script>
// mycomp object
Vue.component('mycomp',{
  template: '#mycomp-template',
  props: [kind],
  data: function(){
    return{
      kind: this.kind,
      data: ['primary', 'secondary']
    }
  }
});  
</script>
```

v-bindを使うことで、属性値に変数を使うことができる。
```
 <div class="h5 alert alert-{{ data[kind] }}">
```
ではだめなのでしょうか...?

# v-model
コントロールの値と、変数の値が相互に関連づいている。
例えば、入力された値が変わると変数の値も変わり、
変数の値が変わると入力値も更新される。
```
v-model="変数名"
```

おもにinputとかと一緒に使うのかな？
```html
<input type='text' v-model="msg">
```

とすると、Vueオブジェクト内の変数が変わった時にinputの値も変わるし、
inputの値が変わったら変数の値も変わる。

# v-on
イベントを組み込む。
```html
v-on: イベント名="メソッド名"
```

```html
method:{
    メソッド名: function(e){
    },
...
}
```
コンポーネント側でmethodを宣言する。
引数の __e__ も忘れずに
dataとかを上手く活用してイベント関数を作成すればいい。

作成したらhtml側でメソッド名をv-on:clickとかに渡してあげればいい。

# class/style とオブジェクト構文
classやstyleでは色んな変数を設定することも多々あると思うので、
classとstyleにはオブジェクト構文なるものが用意されている。

```html:classのオブジェクト構文
v-bind:class="{クラス名:真偽値, クラス名:真偽値,...}"
```
クラスに属させるか属させないかで表示を変える。
たとえば __class="red"__ を赤色に染めるCSSを記述していた場合、
__red: true/false__ で色を変えられる、ということか。

```html:styleのオブジェクト構文
v-bind:style="{スタイル名:値, スタイル名:値,...}"
```
サイズ等の値をJSで書き換える。

なお、クラス名やスタイル名がハイフンで繋がれていない場合にはそのまま書けばいいが、
__ハイフンで繋がっている場合は""や''でくくる必要があるので注意__

### dataのオブジェクトをバインドする

クラス名:真偽値, クラス名:真偽値,...と書くのは見づらくなることもあるので、
```js
data: function(){
    return{
        styleObj:{
            fontWeight:'bold',
            fontSize:'16px'
        };
    }
}
```
と書いてあげて、
```
v-bind:style="styleObj"
```
と書いてあげればJS側に記載した値でスタイルが適用される。
この場合、 __fint-size__ と書くのではなく、
__fontSize__ と書く必要があるので注意。

#### 参考文献
https://www.amazon.co.jp/Python%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF-Flask%E3%81%A7%E5%AD%A6%E3%81%B6Web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E3%81%97%E3%81%8F%E3%81%BF%E3%81%A8%E3%81%A4%E3%81%8F%E3%82%8A%E6%96%B9-%E6%8E%8C%E7%94%B0%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4802612249
vue3 サーバーの立ち上げ方法

vue3 サーバーの立ち上げ方法

- ディベロッパーモード

プログラムの変更がサイトに反映されます．
```
npm run serve
```

- プロダクト用ビルド

プロダクト用のビルドで html css js のファイルが生成されます．

```
npm run build 
```

ファイルは`dist`内に生成され,生成後は`python3`を使ってサーバを立ち上げることもできます．

```
python3 -m http.server
```
JupyterLabの設定ファイルの要点

# 概要
JupyterLabの設定は以下のようにコマンド引数として与えることができます。

```bash:Bash
jupyter lab --ip=* --no-browser
```

しかし、設定したい項目が増えてくるとコマンド引数では窮屈なので設定ファイルが必要になってきます。ここでは設定ファイルの使い方について簡単に紹介します。

# 環境
- JupyterLab 3.5.3

# JupyterLabの設定ファイル
## 設定ファイルの生成
JupyterLabの設定ファイルのテンプレートは以下のコマンドで生成できます。

```bash:Bash
jupyter lab --generate-config
```

設定ファイルは以下のような内容で `~/.jupyter/jupyter_lab_config.py` に生成されます。`jupyter lab` コマンド実行時にはデフォルトでこのファイルが参照されるようになっています。

```~/.jupyter/jupyter_lab_config.py
# Configuration file for lab.

c = get_config()  #noqa

#------------------------------------------------------------------------------
# Application(SingletonConfigurable) configuration
#------------------------------------------------------------------------------
## This is an application.

## The date format used by logging formatters for %(asctime)s
#  Default: '%Y-%m-%d %H:%M:%S'
# c.Application.log_datefmt = '%Y-%m-%d %H:%M:%S'

# ~~~ 以下略 ~~~
```

このファイルは生成時には全てコメントアウトされており、必要な項目をアンコメントすることで設定を反映することができます。

## 任意の設定ファイルの指定
`jupyter lab` コマンド実行時はデフォルトで上記の `~/.jupyter/jupyter_lab_config.py` が参照されるようになっていますが、 `--config` オプションで設定ファイルを指定することもできます。

```bash:Bash
jupyter lab --config="./jupyter_lab_config.py"
```

# 設定内容
## 設定項目の参照
コマンド引数や設定ファイルで設定可能な項目はヘルプコマンドで参照できます。

```bash:Bash
jupyter lab --help
jupyter lab --help-all
```

## 設定ファイルの一例
私がよく使う設定ファイルとしては以下のようなものです。Dockerコンテナをサーバーとして、小規模な使用を想定した設定内容です。

```jupyter_lab_config.py
# 接続を許可するIPアドレス
c.ServerApp.ip = "*"

# ポート番号
c.ServerApp.port = 8888

# アクセス時に必要なトークンを無効化
c.ServerApp.token = ""

# コマンド実行時にブラウザを開かない
c.ServerApp.open_browser = False

# ルートユーザーで使用する
c.ServerApp.allow_root = True

# ルートユーザーのホームディレクトリをJupyterLab上のルートディレクトリに設定
c.ServerApp.root_dir = "/root"

# JupyterLab上のファイルツリーで隠しファイルを表示するオプションを使用可能にする
c.ContentsManager.allow_hidden = True

# チェックポイントファイルを /tmp に保存する
c.FileContentsManager.checkpoints_kwargs = {
    "root_dir": "/tmp/ipynb_checkpoints",
}
```

`jupyter lab --generate-config` で生成したテンプレートの先頭には `c = get_config()` がありましたが、ここでは無くても問題ありません。

前述の通り、`--config` オプションでこのファイルを指定することで設定が反映されます。

```bash:Bash
jupyter lab --config="./jupyter_lab_config.py"
```

ちなみに、上記の設定内容をコマンド引数で指定すると以下のようになります。コマンド引数で与えるにはちょっと窮屈です。

```bash:Bash
jupyter lab --ip=* --port=8888 --IdentityProvider.token="" --no-browser --allow-root --notebook-dir="/root" --ContentsManager.allow_hidden=True --FileContentsManager.checkpoints_kwargs="root_dir"="/tmp/ipynb_checkpoints"
```

# 参考文献

https://docs.jupyter.org/en/latest/use/config.html
Azure CLI をインストールする手順

# Azure CLI をインストールする手順

## 目的

Microsoft のクラウド環境 [Azure](https://azure.microsoft.com/ja-jp/) の理解を深めます。  

## 実現すること

ローカル環境 (Ubuntu) に Microsoft のクラウド環境 Azure を操作する為のコマンドラインツール [Azure CLI](https://learn.microsoft.com/ja-jp/cli/azure/what-is-azure-cli) をインストールします。  

## 開発環境

+ Windows 11 Home 22H2 を使用しています。  
+ [WSL](https://learn.microsoft.com/ja-jp/windows/wsl/about) の Ubuntu を操作していきますので macOS の方も参考にして頂けます。  

<details>

WSL (Microsoft Store アプリ版)

```sh
> wsl --version
WSL バージョン: 1.0.3.0
カーネル バージョン: 5.15.79.1
WSLg バージョン: 1.0.47
```

Ubuntu

```sh
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.1 LTS
Release:        22.04
```

</details>

※ この記事では基本的に Ubuntu のターミナルで操作を行います。

## インストール

Microsoft Azure CLI リポジトリを登録

```sh
$ echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/azure-cli.list
```

パッケージ署名キーをインポート

```sh
$ curl -L https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
```

パッケージのインデックス更新

```sh
$ sudo apt update
```

Azure CLI インストール

```sh
$ sudo apt install azure-cli
```

Azure CLI のバージョンを確認

```sh
$ az --version
azure-cli                         2.45.0
core                              2.45.0
telemetry                          1.0.8
Dependencies:
msal                              1.20.0
azure-mgmt-resource             21.1.0b1
```

## サインイン

Azure アカウントにサインイン  

```sh
$ az login
```

※ WSLg でWEBブラウザが立ち上がります。

+ WEBブラウザのフォームに Microsoft アカウントを入力します。

ターミナルの出力

````sh
A web browser has been opened at https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize. Please continue the login in the web browser. If no web browser is available or if the web browser fails to open, use device code flow with `az login --use-device-code`.
[
  {
    "cloudName": "AzureCloud",
    "homeTenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "isDefault": true,
    "managedByTenants": [],
    "name": "Azure subscription 1",
    "state": "Enabled",
    "tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "user": {
      "name": "username@gmail.com",
      "type": "user"
    }
  }
]
````

## 公式リファレンス

[Azure コマンド ライン インターフェイス (CLI) ドキュメント](https://learn.microsoft.com/ja-jp/cli/azure/)
Node-REDのデフォルトの起動ポート番号(1880)を変更する

# はじめに

macOSで複数のNode-REDを立ち上げる場合、デフォルトの起動ポート番号(1880)の重複が発生します。

# Node-REDの変更方法

## settings.jsonの中で指定する

1880を1881などへ変更します。

```json:settings.js
    uiPort: process.env.PORT || 1881,
```

## 起動時の引数(オプション)で指定する

-p、または、--portで指定します。

```bash
$ node node_modules/node-red/red.js -p 1881 -u ./
```

# Node-RED Desktopの変更方法

GUIアプリケーションの環境変数の設定方法です。
~/Library/LaunchAgentsディレクトリにplistファイルを作成します。

```bash
$ cd ~/Library/LaunchAgents/
$ vi setenv.NRD_LISTEN_PORT.plist
```

```xml:setenv.NRD_LISTEN_PORT.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  <plist version="1.0">
  <dict>
    <key>Label</key>
    <string>setenv.NRD_LISTEN_PORT</string>
    <key>ProgramArguments</key>
    <array>
      <string>/bin/launchctl</string>
      <string>setenv</string>
      <string>NRD_LISTEN_PORT</string>
      <string>1881</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
  </dict>
</plist>
```

サービスをロードします。

```bash
$ launchctl load ~/Library/LaunchAgents/setenv.NRD_LISTEN_PORT.plist
```

設定を変更した場合は、サービスをアンロードし、もう一度ロードする必要があります。

```bash
$ launchctl unload ~/Library/LaunchAgents/setenv.NRD_LISTEN_PORT.plist
```

bootstrap、bootoutでも同様に操作可能です。

```bash
$ launchctl bootstrap gui/`id -u` ~/Library/LaunchAgents/setenv.NRD_LISTEN_PORT.plist
$ launchctl bootout gui/`id -u` ~/Library/LaunchAgents/setenv.NRD_LISTEN_PORT.plist
```

### 参考

https://github.com/sakazuki/node-red-desktop/wiki

https://qiita.com/homu-konamilk/items/5886f3e48ffa658f4f78
AnacondaをGit Bashで使う

## はじめに

Windows10のPCでVSCodeを使っているのですが、ターミナルではコマンドプロンプトではなく、Git Bashを普段使いにしてます。そんな中、Anacondaを使い始めたのでcondaコマンドもGit Bashで使えるようにしました。

## 方法

以下のファイルを作成したらGit Bashでもcondaコマンドが使えるようになります。直接 .bash_profileファイルは作れないので、テキストファイル（.txt）を新規作成して名前を変更したら作成できます。

ファイルパス：`C:\Users\[ユーザー名]\.bash_profile`

```bash:.bash_profile
# AnacondaをGit Bashで使うための処理（パスは環境に応じて変更）
. /c/users/[ユーザー名]/anaconda3/etc/profile.d/conda.sh
```

## さいごに

自分の使い慣れているターミナルでコマンド打てるようになると嬉しいですね。ターミナルを切り替えて対応していた方は今回の方法を導入してみるのも良いかもしれません。
応用情報技術者合格記

# はじめに
先日、ようやく応用情報の合格証が届きました。

# やったこと
### 午前試験
- [過去問道場](https://www.ap-siken.com/apkakomon.php)
「文系出身者は応用情報のほうが合格しやすい…」という言説を盲信していたので、「なら大丈夫だな！！！」ということで過去問道場一本で勉強しました。上司からは苦い顔をされたので評価されたい人はちゃんと本を買って勉強したほうがいいと思います。キタミ式とかいうのがおすすめらしいです。

### 午後試験
- [過去問道場](https://www.ap-siken.com/apkakomon.php)
「文系出身者は応用情報のほうが合格しやすい…」という言説を盲信していたので、「なら大丈夫だな！！！」ということで過去問道場一本で勉強しました。上司からは苦い顔をされたので評価されたい人はちゃんと本を買って勉強したほうがいいと思います。キタミ式とかいうのがおすすめらしいです。

# 真面目な話
（過去問道場しかやらなかったのは本当ですが）じゃあどう過去問道場を使っていたのかという話。参考書代なんてもったいないよ～～～という方は参考にしてもらえればと思います。

1. 試験に申し込む
1. 過去問道場のアカウントを作る
1. ただひたすらに午前の過去問を解いて午前試験を通せるくらいの知識を付ける
1. ただひたすらに午後の過去問を解いて合格点を取れるようになる

#### 試験に申し込む
締め切りが先の仕事はやらないのと同じで、資格試験も締め切りがないと一生勉強しません。
なにはさておきとりあえず試験に申し込みましょう。

#### 過去問道場のアカウントを作る
アカウントを作ると、過去の問題の成績照会ができるようになったりします。
過去問を解き続けているとだんだん億劫になってきます。ただ、ちゃんと解き続けていれば少しずつ問題が解けるようになるので成績照会画面に金のトロフィーがどんどん増えてきます。私はこれをモチベーションにして頑張っていました。

#### ただひたすらに過去問を解く
- 午前試験
午後試験の問題の意味を理解できないとなにもできないので、まずは午前試験で知識を身に着けるところから。
通勤時間にスマホで問題を解きましょう。土日にまとめて勉強しようと思っても絶対にやらないので通勤時間で勉強するしかありません。というか、土日に勉強できる人は通勤時間にも勉強してると思います。

- 午後試験
午前試験大体解けるようになったな、というくらい（私は試験の1.5か月前くらい）から午後試験の勉強を始めました。
選ぶ問題は業務内容から決めればいいと思います。私は情報セキュリティ、ＤＢ、ＮＷ、サービスマネジメント、プロジェクトマネジメントを中心に勉強しました。
午後試験、特に勉強したてはなかなか点数が伸びす嫌になりかけましたが、時々午前試験をさくっと解いてモチベーションを回復させていました。実際、午前試験を解くことで知識の抜け漏れのチェックが出来ていたかなと思います。

# 当日
- 仕事より早く起きないといけなかったので気合で起きました。よくある０次試験合格というやつです。
- 午前試験の手応えが全くなかったので半ば諦めムードでした。
- 午後は、選択する予定だったＤＢがあまりにも難しく焦りました。が、経営戦略の問題の題材と全く同じことを実務でやったことがあり、急遽そちらに切り替えてリカバリーできました。

# 感想
- 基本情報取った時も思いましたが、過去問に比べて難しくなっていると思います。
    - 数字が細かくなったり、一歩踏み込んだ知識を問う問題が多くなっている印象
- 午後は余裕持っていくつかの範囲を勉強しておいたほうがいいです。
    - いろんな方が言ってることなので今更の話ですが、私は「ＤＢ、ＮＷ、サービスマネジメント、プロジェクトマネジメントだけやる！」と決めてかかったので他の範囲は勉強しませんでした。そのせいで危うく不合格になりかけました。（経営戦略の問題運に救われました）絶対勉強したほうがいいです。
Linuxの新しいsandbox機構「Landlock」

# はじめに
この記事ではLinuxの新しいsandbox機構であるLandlockのサンプルの使い方を概説します。
詳細で正確な情報は公式のページ https://landlock.io/ やLinux kernelのソースコード中にありますので、必要な場合はそちらを参照してください。


# サンドボックスが欲しいわけ
一般的なLinuxディストリビューションとスマートフォンOSの両方を使い、それぞれで様々なアプリを使っている方は大きな違いに気付くと思いますが、前者はユーザーのデータはホームディレクトリと呼ばれる共通のディレクトリに格納され、他のアプリのためのデータを自由に参照できます。それに対し、スマートフォンの場合は各アプリが独自のデータ領域を持ち、他のアプリのデータを参照するには手間のかかるプログラミングとユーザーの同意が必要になります(バイパスできてしまう場合は脆弱性とみなされます)。
Linux環境上でデータが共有されているのは便利なのですが、ブラウザやSSHが持つ認証情報、あるいは文書やコード等の意図しないアプリからの読み出し(そしてネットへの持ち出し)もしくは改変のリスクに対応する必要があります。
信用できる開発元やディストリビューター経由で入手したアプリしか動かさないというのも一つの方法ですが、サプライチェーンの脆弱性も現実的に存在すること、さらに開発者の場合は管理の緩いパッケージシステムから取得したリソースの利用と生産性のトレードオフを取ることが必要になると考えられます。

要するに、何かのインストール時に
```
$ curl https://…/install.sh | bash -s
```
ってのを見かけるとヤバい！と思いますよね。(普段良くても、運が悪いタイミングでの実行で何か起きるかもしれず)

# 使い方
ここではこの記事の執筆時点でのWindows上のWSL (Ubuntu 22.04.1) での流れを説明します。
Landlock自体はLinux 5.13(2021年6月にリリース)以降で使えます。

WSLなUbuntuでLinuxのAPIを使うにはkernelのヘッダファイルが必要なんで、入れてない人はインストールします。
```
$ sudo apt install linux-headers-5.15.0-58-generic
```

sandbox manager example ( https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/samples/landlock/sandboxer.c ) からsandboxer.cをコピーしてきてコンパイルします。

```
$ gcc sandboxer.c -o sandboxer
```
現時点でのWSLはカーネルがこのコードが想定している最新のものではないので、LANDLOCK_ACCESS_FS_TRUNCATE などの定数を数個コメントアウトします。

次にsandbox (sandboxer) の中で子プロセスとしてbashを動かそうとしてみます。環境変数のLL_FS_ROとLL_FS_RWに読んで良いディレクトリ、読み書きして良いディレクトリを複数指定できます。

```
$ LL_FS_RO="/" LL_FS_RW="" ./sandboxer bash -i
Hint: You should update the running kernel to leverage Landlock features provided by ABI version 3 (instead of 1).
bash: /dev/null: Permission denied
```

bashが/dev/nullに書けないと言ってるので書けるようにします。

```
$ LL_FS_RO="/" LL_FS_RW="/dev/null" ./sandboxer bash -i
```
こんどは大丈夫。

このプロセスから ~/.ssh/ のファイルが見られてネットに送られて心配！という気がするので隠しましょうか。ついでにホームディレクトリ上で開発を続けたいので
```
$ LL_FS_RO="/usr" LL_FS_RW="/tmp:/dev/null:/home/yusuke/llock" ./sandboxer bash -i

bash: /etc/bash.bashrc: Permission denied
bash: /home/yusuke/.bashrc: Permission denied
```

/etc/bash.bashrcは大したことが書かれてないんで、ホームディレクトリのbashrcは読めるようにしましょうか。(書けるようにもしてしまうと悪意のある何かを書き足されるのが心配ですよね)

```
$ LL_FS_RO="/usr:/home/yusuke/.bashrc" LL_FS_RW="/tmp:/dev/null:/home/yusuke/llock" ./sandboxer bash -i
bash: /etc/bash.bashrc: Permission denied
$ cat ~/.ssh/config
cat: /home/yusuke/ssh/.config: No such file or directory
$
$ さんどぼっくすのなかにいる
```
これでネットから来た何かのインストールスクリプトに対してもファイルシステム上は安全！という感じです。


# まとめ
信用できないコードを動かす時は別のマシンを使うとか仮想化を使う、最近だとコンテナを利用するなどといった方法がありますが、ホームディレクトリ内のアクセス権の切り分けだけで簡単に改善できそうな方法であるLandlockの利用例を紹介しました。
将来的にはもっと普通に使える形が模索されるかと思いますが、PCがスマホみたいになるのもイヤだなと思う今日この頃です(だからといってリスクに対して開き直るのもイヤですが)。
Teams 会議の録画をラクに保管する方法

こんにちは。
バレンタインデーに対して歪んだ感情を持つ男です。

Teamsのリモート会議で普通に録画機能を使うと、動画が OneDrive 上に保存されるんですよね。
この録画データを都度 SPO に移動して保管してる人たちもいると思います。
こういった「めんどくせぇなぁ」 と感じる作業は、標準機能で回避できることが多いです。
（マイクロソフトの中の人たちもTeams会議はするはずなので、そりゃ標準機能で実装しますよね）

今回は、会議録画データをラクに保存するための設定方法を説明していきます。

想定するケースはこんな感じ。
- 定例のリモート会議の録画を参加者と共有したい
- 録画ファイルの保存を自動化したい
- 長期的に保存したい

# 手順１）会議用チャネルを作成
まずは 会議参加者がメンバーになっている Team に、定例会議用のチャネルを作成します。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/f4d788a5-7e95-7a02-cc5a-e2813bcb912a.png width=50%>

Teamに参加しているメンバー全員が参加する会議なら「プライバシー」を「<b>標準</b>」に、メンバーを制限する場合は「<b>共有</b>」に設定します。(この例では「<b>標準</b>」を指定)
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/9abcb9da-8fa1-a4c2-a9ba-a48b79e9a2f3.png width=50%>

# 手順２）定例会議を設定
作成したチャネルで定例のTeams会議をスケジュールします。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/43204a47-763f-9861-7f69-9aab1bd94e5d.png width=50%>
日時や頻度など、必要事項を入力して「送信」。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/f24cd733-91b2-7f0c-a845-f4ac6282aecf.png width=50%>

会議の詳細を表示。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/68339437-134a-0693-0a48-9b0232011df0.png width=50%>

会議のオプションを開く。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/4640070c-9444-feaa-b73e-0c7175dcb672.png width=50%>

会議の自動録画をオンにする。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/0b0abc82-5a2a-7a4d-35c6-ccbc11572619.png width=50%>

以上で設定終了です。
これで会議が開催される都度、自動的に録画データが Teams に保存されます。

# 手順３）録画された動画を確認し、保管有効期限を設定
保存されたデータは、会議を設定したチャネルの「Recordings」フォルダに保存されています。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/ad8aa3d9-2ee5-015f-4fe8-00b3b1e46781.png width=50%>

自動的に「会議名」と「開始日時」が付与されたファイル名で保存されます。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/55f1b390-444e-4a43-cd8c-46bf16b5e943.png width=50%>

保存された直後は、デフォルトの有効期限が設定されています（弊社の場合は60日後に削除される設定でした）。

有効期限を変更するには、

対象の動画ファイルの「詳細」を開き、
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/68726c1a-bec1-9aae-cbef-a91737e02324.png width=50%>

日付を指定します（「有効期限を削除します」で無期限することも可能）。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/78fd4120-4ee6-746e-b361-d2d27cbfe50b.png width=50%> 

# 最後に
「会議の録画を全部永続的に残したい」って気持ちもわかるんですが、普通の定例会議はせいぜい１～２か月ぐらい残して削除していった方が良いと思います。
そうしないと、参照されることのない、使い勝手の悪いムダデータが残り続けることになります。

# 追伸（23/2/18）
この記事、某所にて Power Automate で同様の事をしようとしていた人に対する解決策として書いたんですが、
「そのTeamsの機能は知っているんだけど、ある上位役職者が自分で設定した定例会議なので、こちらから変更を申し入れにくい」とのこと。
まぁ、そうっすよね（笑）。
そういったところの心理的安全性を確保する方策を提案すべきでした。
S3 バケットのバージョニング は有効化すべきなのか

こんにちは。パエリアです。

今回は AWS 利用者ならほぼ100%利用しているであろう S3 の機能であるバージョニングについての考察をしていきます。

>Amazon S3 のバージョニングとは、同じバケット内でオブジェクトの複数のバリアントを保持する手段のことです。S3 のバージョニング機能を使用すると、バケットに保存されたすべてのオブジェクトのすべてのバージョンを、保存、取得、復元することができます。バージョニングを使用すれば、意図しないユーザーアクションからもアプリケーション障害からも、より簡単に復旧できます。

[AWSドキュメント：S3 バケットでのバージョニングの使用](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/Versioning.html)

### 結論としてはバージョニングは有効化すると良いと思います。

以下の点について、それぞれ考えていきます。


[1.耐障害性（フォールトトレランス）](#1-耐障害性フォールトトレランス)
[2.AWS ベストプラクティス](#2-aws-ベストプラクティス)
[3.利用料](#3-利用料)
[4.有効化が推奨される利用方法](#4-有効化が推奨される利用方法)
[5.有効化が推奨されない利用方法](#5-有効化が推奨されない利用方法)

## 1. 耐障害性（フォールトトレランス）

S3 バケットのバージョニングを有効化することで、何かしらの理由によりオブジェクトが上書きされたときに、上書き前のオブジェクトを復旧することができるようになり、耐障害性を向上させることができます。
つまり、この点から考えると有効化しない理由はありません。

## 2. AWS ベストプラクティス

AWS のベストプラクティスとしては有効化することが推奨されています。
ちなみに、バージョニングの有効化は AWS Trusted Advisor(耐障害性)でもチェック項目となっています。
ただ、現状バケット作成時のデフォルトチェックは無効状態となっていましたので、作成時の操作には注意が必要です。

[AWSドキュメント：Amazon S3 のセキュリティのベストプラクティス](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/security-best-practices.html)

## 3. 利用料

S3 標準ですと最初の 50TB までは 0.025USD/GB となっております。（東京リージョンの場合）
また、バージョニングを有効化していて、対象オブジェクトに上書きした場合は過去のバージョンについても利用料がかかります。
例えば 2GB のオブジェクトに 2GB　のオブジェクトを上書きしても 4GB 分の利用料がかかります。

>Q: バージョニングの使用に対してどのように課金されますか?
通常の Amazon S3 料金は、格納またはリクエストされるオブジェクトの各バージョンについて適用されます。

[AWSドキュメント：よくある質問](https://aws.amazon.com/jp/s3/faqs/)

思ったより高くつきそうですね、、、
適宜 S3 の利用料金の確認やライフサイクルポリシーの作成は必ず行いましょう。

## 4. 有効化が推奨される利用方法
※あくまで一個人の意見です。

### 4-1. 上書きされては困るバケット
まず、上書きされるべきではないバケットへは、上書きができないように権限やオブジェクトロックをしておけるなら、実装しましょう。
それだけでも十分だと思いますが、何かしらのトラブルで上書きされる可能性はあります。（権限変更やロック設定を解除できるような状況にある可能性もあります。）
万が一、上書きされてしまった時のためにバージョニングを有効化すると良いと思います。
そもそも上書きの前提がないのであれば、利用料金は変わりません。

### 4-2. 変更の多いバケット
変更の頻度が高い、または変更を実行する人が多いバケットについてはまさにバージョニングが有効だと思います。
間違って上書きしてしまった、他の人と同じタイミングで上書きしてしまったなど、復旧させるタイミングが多いと想像します。
また、その場合利用料も高くなるので、更新頻度に合わせてライフサイクルポリシー（例えば1週間）を必ず設定しましょう。

## 5. 有効化が推奨されない利用方法

### 5-1. どうしても利用料を抑えたい場合
場合によっては2-3倍以上の利用料がかかる可能性もあるので、耐障害性は気にせず、とにかく利用料を抑えたい場合は、無効化すると良いと思います。

### 5-2. バックアップとして利用している場合
最悪消されも問題ないようなデータや定期的なバックアップとして S3 を利用している場合は、コストパフォーマンスも考えると有効化しなくても良いかもしれません。

## まとめ
バージョニングの設定はいつでも変更可能ですが、基本的には有効化しておくのが良いかなと考えました。
また、バージョニングを有効化した場合は特にライフサイクルポリシーの設定を内容含めてしっかり設定することを忘れないようにしてください。

## おまけ
S3 といえば、[最近オブジェクトの暗号化がデフォルト有効化となりました。](https://aws.amazon.com/jp/blogs/news/amazon-s3-encrypts-new-objects-by-default/)
バケットの設定はデフォルト有効化が無効化になっているのに中身のオグジェクトは全部暗号化が有効化されている、という謎な事象が起こりがちなので、困ることはないですが、気をつけましょう。
ちなみに SSE-S3 以外でデフォルト暗号化したい場合は、バケット側の設定が必須になります。