OmniAICreator/Qiita-1.07M huggingface dataset:
C# での高度なAES暗号化とHMACによるメッセージ認証

## 概要

この記事では、C# を使って高度な暗号化とメッセージ認証を行う方法を紹介します。この例では、AES 暗号化アルゴリズムを使用し、複数のパスワードと HMAC キーによる二重暗号化を行っています。また、暗号化データの整合性を確認するために HMAC を使用しています。

## 実装の概要

この実装では、次のような主要な機能を提供します。

- **AES 暗号化**: データを安全に暗号化するために AES-256 アルゴリズムを使用します。
- **PBKDF2 によるキー派生**: パスワードから暗号化キーを生成するために PBKDF2 を使用しています。
- **複数のパスワードでの二重暗号化**: 暗号化を複数のパスワードを用いて複数回行うことで、セキュリティを強化しています。
- **HMAC によるデータの整合性チェック**: HMAC (SHA-256 または SHA-512) を使用して、暗号化データの改ざんを検出します。

## ソースコードの入手

このライブラリの完全なソースコードはGitHubリポジトリに公開されています。より詳しい実装内容や、他の便利な機能について興味がある方は、以下のリポジトリをご覧ください。

- [Cryptography.NET リポジトリ](https://github.com/SoundOrion/Cryptography.NET)

## コード解説

### 1. AES 暗号化と復号化

まず、AES を使って平文を暗号化し、またその逆に復号化するためのメソッドを見てみましょう。

```csharp
private static byte[] EncryptAes(string plainText, byte[] key, byte[] iv)
{
    using var aesAlg = Aes.Create();
    aesAlg.Key = key;
    aesAlg.IV = iv;

    using var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
    using var msEncrypt = new MemoryStream();
    using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
    using (var swEncrypt = new StreamWriter(csEncrypt))
    {
        swEncrypt.Write(plainText);
    }

    return msEncrypt.ToArray();
}
```

AES 暗号化を行う `EncryptAes` メソッドでは、`Aes.Create()` を使用して AES のインスタンスを生成し、キーと初期化ベクター (IV) を設定します。その後、`CryptoStream` を利用して平文を暗号化します。

### 2. 二重暗号化の流れ

この実装では、複数のパスワードを使用して二重暗号化を行っています。最初のパスワードで暗号化を行い、その結果を次のパスワードでさらに暗号化するというプロセスを繰り返します。

```csharp
for (int i = 1; i < passwords.Length; i++)
{
    var encryptedText = Convert.ToBase64String(encryptedData);
    byte[] key = DeriveKey(passwords[i], salt, hashAlgorithm);
    encryptedData = EncryptAes(encryptedText, key, iv);
}
```

### 3. HMAC によるデータの整合性チェック

暗号化後のデータに対して HMAC を生成し、その HMAC を用いてデータが改ざんされていないかを確認します。

```csharp
if (!HmacHelper.VerifyHmac(encryptedData, mac, hmacKey, hashAlgorithm))
{
    throw new CryptographicException("データの整合性が確認できません。");
}
```

HMAC の生成と検証を行う `HmacHelper` クラスは、`HMACSHA256` または `HMACSHA512` を使用して、データの整合性を確認します。

### 4. 結合データの生成と復元

暗号化データ、Salt、IV、MAC を一つのバイト配列に結合して保存し、復号時にそれらを分離する処理も実装されています。

```csharp
private static byte[] CombineData(byte[] salt, byte[] iv, byte[] data, byte[] mac, string hmacKey)
{
    byte[] result = new byte[salt.Length + iv.Length + data.Length + mac.Length];
    Buffer.BlockCopy(salt, 0, result, 0, salt.Length);
    Buffer.BlockCopy(iv, 0, result, salt.Length, iv.Length);
    Buffer.BlockCopy(data, 0, result, salt.Length + iv.Length, data.Length);

    if (!string.IsNullOrEmpty(hmacKey))
    {
        Buffer.BlockCopy(mac, 0, result, salt.Length + iv.Length + data.Length, mac.Length);
    }

    return result;
}
```

復号時には、このバイト配列から必要な情報を抽出し、復号化を行います。

## まとめ

この実装により、複数のパスワードと HMAC を使用した安全性の高いデータ暗号化が可能になります。セキュリティが重要なアプリケーションにおいて、データの暗号化と整合性チェックは非常に重要です。このコードを活用して、自分のプロジェクトにおけるデータセキュリティを強化してください。
re:GitHub Actions学んでみた①

# はじめに
初めまして！
エンジニアになって数年、今まで本を読むだけでしたが、もっとプライベートで楽しみながら成長したい！自分が学んだ足跡を残していきたい！と思い記事を書きました！
最終的には自在に開発できるようになりたいと思っています。:triumph:
いろいろな記事を参考にさせてもらっています。:bow_tone2:

# 今回の目的
自分の作ったコンポーネントを確認したり検証するための技術を身に付けたい！
公式のクイックスタートを参考に進めていきます。
前回まで辞書のような公式ページを進めていたところガイドが更新されたのでそちらを進めて行きます！

# 主に参考にさせていただいた記事
https://docs.github.com/ja/actions/guides

# GitHub Actions を理解する
## GitHub Actionsとは
Githubのリポジトリなどに対するアクション（プルリクエスト）に対して、ビルド、テスト、デプロイが自動化できるプラットフォーム。
テストを実行する仮想OSは、Linux,macOS,Windowsが提供される。

### ワークフローとは
.github/workflowsで定義されるymlファイル
複数のワークフローを定義することができる。

### イベントとは
ワークフローを実行するためのトリガー

### ジョブとは
ワークフロー内で定義される一連のステップ。順次または並列で実行される。

### アクションとは
GitHub Actions 用のカスタムアプリケーションのこと。公開されてたり再利用性があり、@Checkoutのように利用するもの。

### ランナーとは
ワークフローの実行仮想サーバー。一度に一つのジョブを実行できる。

# ワークフローでカスタマイズされたアクションを使用する
## アクションのメリット
- 再利用可能
    - 呼び出すだけでOK
    - 事前作成済であらゆるケースに対応したアクションがある
- 構成可能
- コミュニティ主導
    - 実績のあるコミュニティが作成したアクションを利用できる

## ワークフローにアクションを追加する方法
### パターン１：Marketplaceからアクション追加
利用したいアクションを選択しコピーして使用する。
![スクリーンショット 2024-09-01 12.11.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/c98ab77b-6c05-cb02-12a8-949fd7023273.png)

### パターン２：同じリポジトリからのアクション追加
・配置方法
![スクリーンショット 2024-09-01 12.14.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/2e1e71d0-acf8-a6f0-f2d4-7a441c13a867.png)

・利用方法
![スクリーンショット 2024-09-01 12.13.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/3064e74d-7546-f801-20b9-a9568f8deee4.png)

### パターン３：DockerHub上のコンテナを参照
コンテナイメージ内でアクションを定義している場合。

# ワークフローについて
## ワークフローの基本
- 一つ以上のトリガー
- ランナーで起動する一つ以上のジョブ
- ユーザーが定義したスクリプトかアクションがあるステップ

### ワークフローのトリガー
- ワークフローのリポジトリ内で発生するイベント
    - Pushやissue、リリースが作成された時など
- Github外部で発生し、repository_dispatchでキャッチするイベント
- スケジュールされた時刻
- 手動実行

### ジョブ
ジョブごとに使用するOSを定義する
```yml
jobs:
  example-job:
    runs-on: ubuntu-latest
    steps:
```
#### 依存性
needsを利用することでjobsが並列ではなく順次に実行されるようにすることが可能。
```yml
jobs:
  setup:
    runs-on: ubuntu-latest
    steps:
      - run: ./setup_server.sh
  build:
    needs: setup
    runs-on: ubuntu-latest
    steps:
      - run: ./build_server.sh
  test:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - run: ./test_server.sh
```

### matrix
下記の場合だと、node14と16の複数バージョンでジョブを起動する
```yml
jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: [14, 16]
```

# 次

https://docs.github.com/ja/actions/sharing-automations/reusing-workflows?learn=getting_started&learnProduct=actions
ラズパイのWiFi接続が切れる

ラズパイ(Raspberry Pi Zero W)とWiFiの接続が定期的に切れる問題に対する対処法です。
ググると[`ifconfig wlan0 up`をする方法](https://elsammit-beginnerblg.hatenablog.com/entry/2021/02/16/213737)や[`Power Management`を変更する方法](https://qiita.com/nanbuwks/items/a06c6c17ecbc3fc5ac79)が出てきますが、私の場合はこれでは解決に至りませんでした。。


# 対処法
```bash:reconnect_wifi.sh
#!/bin/bash
# pingの宛先(192.168.0.1)は環境に合わせてください
ping -c 1 192.168.0.1>/dev/null
if [[ $? -ne 0 ]]; then
    # GUIによるWiFiのON/OFFの操作に該当するコマンド
    sudo rfkill block wifi
    sleep 5
    sudo rfkill unblock wifi
fi
```
上記シェルスクリプトを`cron`で毎分実行させます。
```bash:設定コマンド例
# クーロンの編集
crontab -e

# 以下の設定を記載する(...はファイルへのパス)
* * * * * /.../reconnect_wifi.sh
```
この方法（クーロンで毎分起動する方法）だと最大1分程度接続が切れたまま放置されてしまうので、`while`文で任意の秒数ごとに監視するスクリプトに変更するなどしても良いと思います。その場合、ラズパイの電源を入れたタイミングで自動起動する様にサービス化などをすると良いと思います。（今回はサービス化などが面倒だったのでクーロンを使いました。）

# やってること
`ping`でルーターに向けて疎通を確認し、繋がらない場合は`rfkill`コマンドでWiFiの落とし上げを行なっています。
`rfkill`コマンドによる処理は、ラズパイ内でWiFiを`OFF → ON`する操作に該当します。（下記画像内の`Trun Off Wi-Fi`をクリックする操作）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485256/c39ac67d-f8af-d055-bbcf-e3968cc11154.png)
(画像: [https://zenn.dev/chantakan/articles/babdd4a884df8c](https://zenn.dev/chantakan/articles/babdd4a884df8c))

私が検証した際に`ifconfig wlan0 up`などでは接続が戻りませんでしたが、ラズパイ内でWiFiの落とし上げを行うと繋がる様になりました。そのため、ラズパイ内のGUIで行っている処理に該当するコマンドを探して実装した次第です。


# 最後に
ラズパイは初期セットアップが終わるとssh接続で使うことが多いかと思います。そうした際に接続が切れていて電源の落とし上げが必要になるのは非常に不便です。
なぜ接続が切れてしまうのか？という点は正直よく分かりませんが、上記回避策によって「繋がらない！」と感じることは無くなりました。

本記事が少しでも参考になれば幸いです。
指定PDFを表示するためのウィジェットを作成

※本件、iPhoneでのショートカット作成方法となるため、Androidには対応しておりません。

## 実装
・表示したいPDFを「ショートカット」アプリがアクセスできる場所（今回は、iCloud上のフォルダ）に配置する。
・「ショートカット」アプリを起動
・「+」を押下し、「アクションを検索」＞「ファイル」＞「フォルダからファイルを取得」
・以下のような画面になるので、表示したいファイルについて、ファイルパスとファイル名を選択し、「完了」を押下する。
<img width=50% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865489/ef57627d-fc3c-c53b-80f3-3ba4f371e82c.png">

・その後、以下手順でホームにウィジェットを配置
ホーム画面　＞　画面長押し　＞　「編集」ボタン押下し、「ウィジェットを追加」　＞　「ショートカットアプリ」を選択　＞　今回作成したショートカットを指定　＞　ホーム画面上にドラッグ


## 配置後のイメージ
<img width=50% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865489/afed5ba9-ecd6-d792-0c41-a28869d12e12.png">
Docker環境構築の個人的テンプレート

# 概要
DockerでPython環境とDBを構築する際のテンプレート

いつもディレクトリ構成やファイルマウントどうするか悩んでいたのでテンプレートを作成した．

今後アップデートする可能性あり．

https://github.com/KiYuRo/qiita-docker

# ディレクトリ構成
```
C:.
├─app           # アプリケーション用のコードを格納
└─docker        # dockerで使用するファイルやディレクトリを格納
    ├─app       # appコンテナの設定ファイルを格納
    └─database  # databaseコンテナで使用するファイルやディレクトリを格納
        ├─data  # databaseコンテナのデータを永続化するためのディレクトリ
        └─init  # コンテナ起動時に実行するSQLファイルを格納
```

# 主なファイル
Dockerfile
- アプリケーションサーバー用の設定を記述
- rootではなく一般ユーザーで実行できるようにする
```dockerfile
FROM python:3.12-slim

ARG USERNAME=app-user

# ユーザーを作成し、そのユーザーのホームディレクトリを作成
RUN useradd -ms /bin/bash $USERNAME

# 作業ディレクトリを設定
WORKDIR /home/$USERNAME/app

# ユーザーを変更
USER $USERNAME

# requirements.txt をコピー
COPY requirements.txt /home/$USERNAME/app/

# pip をアップグレードし、必要なパッケージをインストール
RUN pip install --upgrade pip && \
    pip install --no-cache-dir -r requirements.txt
```

docker-compose.yml
- データベースとアプリケーションサーバを定義
```yml
services:
  database:
    image: postgres:14
    container_name: database
    restart: always
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: root
      POSTGRES_DB: root
    ports:
      - "5432:5432"
    volumes:
      - ./database/data:/var/lib/postgresql/data
      - ./database/init:/docker-entrypoint-initdb.d
  app:
    build: ./app
    container_name: app
    depends_on:
      - database
    volumes:
      - ../app/:/home/app-user/app/
    tty: true
```

# コンテナ起動
dockerディレクトリに移動
```
cd docker
```

コンテナ起動
```
docker compose up -d
```


# appコンテナ
appコンテナ接続
```
docker compose exec app /bin/bash
```

プログラム実行
```
python app.py
```


# databaseコンテナ
databaseコンテナ接続
```
docker compose exec database /bin/bash
```

データベース接続
```
psql -U root
```


# コンテナ削除
```
docker compose down
```
面白いデータの保存方法

先日開催した[ギジュツガタリズ](https://www.classact.co.jp/)にて、**面白いデータの保存方法**について話題になりました。

スマホを当たり前に使う現代において、データの保存方法というものは、一般人においてもとても重要な課題かと思います。
一般的なものとして、HDDやSSD,SDカードなどの記憶装置や、GoogleDriveやiCloudなどのクラウドサービスがあります。
しかし、保存する容量が大きければ大きい程にコストがかかってきます。
プライベートにおいては、基本データ保存にかける予算が十分にある方は少ないかと思われます。そのために、昔の写真や動画を削除する作業を強いられる経験があるかと思われます。

そういった状況を解決するために、策を練るエンジニアが世界中にたくさんいます。
面白い方法でデータの保存を図る事例をいくつかご紹介します。

# SOL1.データを動画に変換してYouTubeにあげてしまう

https://www.gizmodo.jp/2024/04/save-data-on-youtube-cloud-1.html

https://github.com/DvorakDwarf/Infinite-Storage-Glitch

https://hackaday.com/2023/02/21/youtube-as-infinite-file-storage/

この記事を初めてみた時、画期的なアイデアだと感じると同時に、データの扱い方に関する考え方が変わりました。

ちなみにYoutubeのコメントで変換効率に関して、
```1GBのデータを変換すると、3.39GBの動画になる（白黒の場合）```
と記述がありました。

動画なので、フルカラーRGBで変換すればさらに圧縮率を向上できますが、
YouTubeの仕様上で動画自体が圧縮されてしまうので、白黒のみ実用に耐えるようです。

# SOL2.音にもデータを忍ばすことができる

https://interestingengineering.com/science/you-could-download-video-games-from-the-radio-in-the-1980s

[Manic Miner on Speccy 48k](https://youtu.be/MZYuGUCrkoU)

https://forest.watch.impress.co.jp/docs/review/582239.html

https://note.com/harai_tama/n/n280a1474672e

動画に変換する技術があるのなら、音にもあるだろうと考え調べてみるといろいろ出てきました。

1980年代から音を使ったデータ転送の技術が活用されていたり、
（ダイアルアップ技術は昔では当たり前でしたね。20代ですが音が懐かしい。）

暗号化技術の一つとしても活用されているのを探している中で、
より研究された分野であることを実感しました。

音楽ファイルとして保存できるので、YouTube Musicが容量無制限なので、
実質無制限ファイルストレージ化できちゃいそうです。


# SOL3.やっぱり紙で管理したい

[A4サイズの紙1枚に1MBのデータを印刷してバックアップできるソフト「PaperBack」を実際に使ってみました - GIGAZINE](https://gigazine.net/news/20120817-paperback/)

https://gigazine.net/news/20120817-paperback/

https://medium.com/@alisinabh/paperify-how-to-backup-data-using-qr-code-and-print-them-36d12eaed8fe

https://github.com/za3k/qr-backup

昔はパンチカードと呼ばれる技術が存在していたが（未だに現役運用しているかも？）、

日本企業開発した[QRコード](https://www.denso-wave.com/ja/system/qr/fundamental/qrcode/qrc/index.html)によって、データの扱い方に革命が起きました。

現在、QRコードの最大容量は、モデル2 で [2,953バイト](https://www.keyence.co.jp/ss/products/autoid/codereader/basic2d-qr-types.jsp)なので、約3キロバイトです。
![qr20240901113318809.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260705/58ccfa2a-0226-0420-dba3-a6d43bfaec7a.png)
とても細かいですね。ここまで細かいとカメラでは読みよりづらいので、

[紙1枚に1MBのデータを保存できるこの技術では](https://gigazine.net/news/20120817-paperback/)、600dpiのスキャナーで読み取っています。

A4用紙という紙で管理できる利点というのは非常に有効的だと思われます。
それこそ、写真を普通に印刷するのではなく、データとして印刷する形でも活用できそうですね。

* * *
今回はギジュツガタリズにて出てきた、話題のみまとめて取り上げましたが、
世界にはもっと面白い保存方法を思いついている人がたくさんいるかもしれません。

ギジュツガタリズでは、色々なデータ保存方法を組み合わせて、
**エンジニア版の謎解きイベント**を企画するのもアリではないかと話に花が咲いていました。（筆者的にはやりたいw）

面白い技術でより楽しいエンジニアライフを！
AIチャレンジ2024 Autowareのパッケージで障害物回避

# はじめに
[こちら](https://qiita.com/Arata-stu/items/df5e2e612dcb940816f2)の記事で作成したコストマップを利用します。まだ見ていない方は先にみることをおすすめします。

この記事では、今回のAIチャレンジのメインでもある障害物回避を目指します。
前回に引き続き、Autowareのパッケージで実装をします。

※私のgithubのリンクをおいておきますが、この記事とは関係のない変更がある可能性もあります。
[github](https://github.com/Arata-Stu/aichallenge-2024-AT.git)

# freespace_plannerの導入、ビルド
前回同様、[Autoware node diagram](https://autowarefoundation.github.io/autoware-documentation/main/design/autoware-architecture/node-diagram/)から発想を得ていますが、costmap_generatorのTopicをfreespace_plannerが受け取っていることが確認できます。つまり、このパッケージはセットで、コストマップの作成->Planningをしていると予想し、導入を試みました。

> **注意**  
> 前回の記事を見てくださった方は、このクローンの手順はスキップしてください。

```bash
git clone -b awsim-stable https://github.com/autowarefoundation/autoware.universe.git
```

クローンができたら、AIチャレンジのワークスペースにfreespace_plannerをコピペしてください。
(universe/planning/freespace_plannerにあります)

次にビルドします。
```bash
./build_autoware.bash
```

※実はすでにAIチャレンジDockerに導入されているパッケージであり、/autoware/install　にあるのですが、ソースコードをカスタムするために再ビルドしています。

#freespace plannerのカスタマイズ
costmap_generatorと同様、Parkingシナリオで動作することを想定しているパッケージなため、通常動作しません。この条件を撤廃します。

```c++
bool isActive(const Scenario::ConstSharedPtr & scenario)
{
  if (!scenario) {
    return false;
  }

  const auto & s = scenario->activating_scenarios;
  if (std::find(std::begin(s), std::end(s), Scenario::PARKING) != std::end(s)) {
    return true;
  }

  return false;
}
```

Rvizでは、デフォルトで、/planning/scenario_planning/trajectoryが表示されるようになっているので、Topicを変えてください。
起動してできた経路がこれ！
![Screenshot from 2024-09-01 11-32-32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3673708/a0c387b3-0c2b-c8d7-129f-d657e4e21cf1.png)
Parking用のReverse経路ですね。freespace_plannerのparamファイルを確認するとそれらしきものが！
```yaml
astar:
      only_behind_solutions: false
      use_back: false
      # use_back: true
      distance_heuristic_weight: 1.0
```
use_backをfalseにしてもう一度起動！
```bash
[freespace_planner-24] [INFO] [1725158270.876270483] [freespace_planner]: Freespace planning: 0.990000 [s]
[freespace_planner-24] [INFO] [1725158270.876350026] [freespace_planner]: Can't find goal...

```
探索に失敗するとこのエラーが出ます。またもやパラメータかと思い調べる。

```yaml
minimum_turning_radius: 5.0 #9.0
maximum_turning_radius: 10.0 #9.0
```
![Screenshot from 2024-09-01 11-41-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3673708/bb91af83-81fa-989d-6a17-fdb7b997a280.png)

ついに経路が出ました。探索には１ラップ分だと１０秒ほどはかかるようで、自己位置から探索するので、リアルタイムに更新させると遅れが生じます。

![Screenshot from 2024-09-01 11-45-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3673708/446f87fb-101b-c742-b2a6-99635b098b8e.png)
安定こそしなかったものの、回避経路もできている！

#さいごに
リアルタイムでの推論がうまくいくかはわかりませんが、回避経路の生成ができました。しかも、すべてAutoware既存のパッケージなので、実装が難しくありません。Autowareすげぇ〜
【ChatGPT＋Code Interpreter】でPDFの指定ページを削除して、新たなPDFを作成します。


　どうも、カーブミラーです。

　今回は、PDFの指定ページを削除して、新たなPDFを作成します。

:::note info
本記事は、ChatGPT（有料版）
で行なっております。画像は
ありません。　あしからず。
:::

　ニュースはないので、
　　さっそく本題です。

　PDFで
　　いらないページがあった場合、
　　　そのページを削除したPDFを
　　　　作成したいときがあります。

　ChatGPTで
　　それをするには
　　　どうしたらいいでしょうか？

　そのページを指定して
　　削除を依頼することになります。

　では、その手順です。
　　ここでは、2ページ目を
　　　削除します。

　手順は
　❶GPT-4oであることを確認
　❷PDFをアップロード
　❸Prompt入力
```Text:
CodeInterpreterで、このPDFからページ番号1を削除したPDFを作成してください。
なお、ページ番号とは、0からはじまる内部の番号です。
コード不要。
必ず実行してください。
```
　❹送信
　❺ダウンロードリンクが表示

　これで
　　削除されたPDFが
　　　作成されます。

　今回、
　　ページ番号について
　　　書いていますが、
　　　　これはChatGPTさんが
　　　　　ページ目と間違えるように
　　　　　　なったための文言です。

　これを考えると、
　　ページ目で指定した方が
　　　使う側としては
　　　　混乱が少ないと思います。

　その場合でも
　　ページ目の文言を
　　　書くべきでしょうね😅

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
FizzBuzz問題で学ぶOCP（Open Closed Principle）

# 動画概要
以下の動画で、SOLID原則の一つであるOCP（Open Closed Principle・開放/閉鎖原則）について、FizzBuzz問題を通じて解説しました。
ソフトウェアの拡張に対して開かれている一方で、修正に対しては閉じているという原則です。

<iframe width="560" height="315" src="https://www.youtube.com/embed/tAOcowwAnUY?si=Eno6fJvp9RuudVvK" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="allowfullscreen"></iframe>

# 内容
## 元々のFizzBuzz
通常、FizzBuzzは以下のような形で実装されますが、新しいルールの追加が求められた場合、このコードでは変更が必要になります。

### コード
```ruby:main.rb
class FizzBuzz
  def convert(number)
    return 'FizzBuzz' if (number % 15).zero?
    return 'Buzz' if (number % 5).zero?
    return 'Fizz' if (number % 3).zero?

    number.to_s
  end
end
```

### 実行例

```ruby:main.rb
require_relative './fizz_buzz'

fizz_buzz = FizzBuzz.new

(1..30).each do |number|
  puts fizz_buzz.convert(number)
end
```

## FizzBuzzの拡張
新たなルール、「2の倍数で"Nizz"を返す」を追加するとなったとき、既存のconvertメソッドに修正を加える必要があります。これはOCPに違反します。

### NewFizzBuzzの実装
動的にルールを適用できるNewFizzBuzzクラスを導入することで、この問題を解決しました。

#### rulesモジュール
```ruby:rule.rb
module Rules
  class Rule
    def initialize(divisor, word)
      @divisor = divisor
      @word = word
    end

    def match(_carry, number)
      (number % @divisor).zero?
    end

    def apply(carry, _number)
      carry + @word
    end
  end

  class DefaultRule
    def match(carry, _number)
      carry.empty?
    end

    def apply(_carry, number)
      number.to_s
    end
  end
end
```

#### new_fizz_buzzクラス
```ruby:new_fizz_buzz.rb
class NewFizzBuzz
  def initialize(rules)
    @rules = rules
  end

  def convert(number)
    carry = ''
    @rules.each do |rule|
      carry = rule.apply(carry, number) if rule.match(carry, number)
    end

    carry
  end
end
```

#### 実行例
```ruby:main.rb
require_relative './new_fizz_buzz'
require_relative './rules'

rules = [
  Rules::Rule.new(2, 'Nizz'),
  Rules::Rule.new(3, 'Fizz'),
  Rules::Rule.new(5, 'Buzz'),
  Rules::DefaultRule.new
]

new_fizz_buzz = NewFizzBuzz.new(rules)

(1..30).each do |number|
  puts new_fizz_buzz.convert(number)
end
```

この新しいアプローチにより、コードの拡張がしやすくなります。
転職活動のふりかえり

## まえがき
昨年10月に現在の会社に入社してから、早いもので1年が経とうとしています。
今回は、転職活動のふりかえりについて書きたいと思います。

## これまでの経歴を簡単に
### 直近(2020年夏から2023年8月まで)
AWS基盤環境構築プロジェクトに参画。
このプロジェクトで初めてTerraformやAnsibleに触れ、クラウド基盤の自動化や構成管理についての知見を深めることができました。

プロジェクト期間中、半年ほどはAWSだけでなく、AzureやOCI（Oracle Cloud Infrastructure）の基盤構築にも携わり、幅広いクラウドプラットフォームの経験を積みました。
ここでの経験した割合としては、AWSが7割、Azureが1割、OCIが2割程度かな。

### コロナ禍以前（2017年から2020年まで）
業務アプリケーション開発案件にアサインされた際、AWS上での構築が求められたため、既存のAWS構成を参考にしながら新たなAWS環境を構築しました。
参画直前に、AWS Certified Solution Architect Associateの資格を取得し、業務に活かせたことが、クラウド構築基盤に従事して初の成果となったと感じています。
並行してアプリケーション開発の実装も行いました。
その後は、Javaを用いたパッケージ製品のカスタマイズ案件にも参画し、製品の適用と顧客の要件に合わせた調整を行いました。

### それ以前
主にJavaを使用した業務アプリケーション開発に従事していました。
特に、直近の約10年間は損害保険業界のシステム構築に携わり、システムの設計・開発を行っていました。

## きっかけ
前述の通り、AWSに業務アプリケーションを導入する案件に従事したことがきっかけです。
それ以前は、沖縄という限られた地域市場を主な舞台として活動しており、クラウド基盤のプロジェクトに関わる機会はありませんでした。
しかし、コロナ禍により状況が一変し、地方在住でもリモートで東京や大阪といった大都市のプロジェクトに参画できるようになったことが、転職への意欲を一層強めました。

## 転職前
### 心に留めたことなど
この業界で50代となると、マネージャー経験の有無が重視されることが多いと思います。
しかし、私はフリーランスとして技術力を活かしてプロジェクトに貢献することに注力してきたため、マネジメントの経験はありませんでした。
そのため、転職活動においては、1年、あるいはそれ以上の期間がかかることを見込んで、気長に取り組む覚悟をしておりました。

今後もAWSを中心としたクラウド基盤構築に携わっていきたいと考え、
当時参画していたプロジェクトで採用されていた Terraform, Ansible, Kubernetes の技術を中心としている企業への転職、またはフリーランスとして従事することを目標としました。

またAWS認定資格の上位資格は保持しておくべき必要があるとも考え、
AWS Certified Solution Architect Professional を取得するまでは転職活動は開始しないとも決めておりました。

## 転職活動中
自分の希望に対しては、最初は妥協せずに進めることを心がけていました。
数社は書類選考で終了することもありましたが、そのことにもめげることなく続けていたところ、ある日、1通のスカウトメールが目に留まりました。
自分の希望に最も近い内容で、ますます興味を惹かれました。
そこで早速カジュアル面談を依頼したところ、気づけばとんとん拍子に最終面接まで進んでいたというのが印象です。

他の面談でもそうでしたが、多くの方に人柄を褒めていただくことが多かったです。
自分のやりたいことや会社にどのように貢献していきたいかについて、しっかりと伝えることを心がけました。
また、マネジメント経験がないというマイナス面についても、入社後にどのように取り組んでいくかを熱意をもってアピールできたと思います。

## 入社後
現在では出張の頻度は少なくなりましたが、入社してからの半年間は、月に一度、沖縄から東京へ2〜5日程度出張していました。
基本的には沖縄でのフルリモートで業務を行っているため、どうしてもオフィスでの他の社員との繋がりが薄くなりがちです。
そのため、会社側も社員同士の繋がりを強めるための配慮をしてくれたのだと思います。

オフィスで他の社員とのつながりは、自分にとっても非常に強い刺激になっています。
自分よりも一回り、二回り若い社員たちが、業務後にKubernetesの勉強会を開催し、メンバー同士で自己研鑽に励み、切磋琢磨している様子を目の当たりにすると、自分もまだまだ負けられないなという気持ちになりました。

そのおかげもあり、AWS認定資格12冠の目標を達成すべく、そのモチベーションを持続しています。

4月からは、チームのプロダクトオーナーの役割も任されるようになりました。
以前から改善しなければと考えていた自分の欠点や、なかなか踏み切れなかったことにも、会社の支えを受けながら取り組むことができています。
まだまだ発展途上の段階ではありますが、少しずつでもチームや会社に貢献できるよう、日々反省し、努力を重ねていきたいと考えています。

## あとがき
私の転職活動は、わずか数ヶ月で成功しました。
運や縁もあったかもしれませんが、数十年前に初めて転職活動を行ったときと比べ、自分が進むべき目標を明確にしていたこと、そして目標に向かってしっかりと段取りを整えたことが、早期の転職成功につながったのだと感じています。
また、曖昧な部分を解消し、資格取得に関しては妥協せずに努力することの重要性を改めて実感しました。
The default interactive shell is now zsh. ~　を非表示させたい

プログラミングを学び始めて半年ほどの初学者です。PHP/LaravelでWebアプリの開発をチームで行なっています。

VSCODEでコーディングしているのですが、最近急にターミナル画面に下記が表示されるようになりました。それなりに調べたのですが、この部分を消すことができません。

The default interactive shell is now zsh. To update your account to use zsh, please run `chsh -s /bin/zsh`. For more details, please visit https://support.apple.com/kb/HT208050.


【試したこと】
https://support.apple.com/kb/HT208050 を参照し、
ターミナル画面で
export BASH_SILENCE_DEPRECATION_WARNING=1 を入力
 => 効果なし


毎回出てくるのがうざったいので、消す方法を教えていただけますか。どうぞよろしくお願いいたします。
【Chakra UI】Buttonでdisabledが効かない問題について

# はじめに
現在、Udemy講座「Reactを使った開発のステップアップ」でChakra UIを使った開発を行っています。 ログインボタンを作成する際、ユーザーが情報を未入力の場合にボタンを無効にするため***disabled属性***を使用しましたが、ボタンが押せてしまうという問題が発生しました。

この問題の解決策をご紹介します。

https://www.udemy.com/course/react_stepup/?couponCode=ST22FS22724

# 問題点
以下のようなボタンコンポーネントを作成しました。 ボタンエリアに***disabled属性***を設定し、propsで受け渡すことで、ログイン情報が未入力の場合にボタンがクリックできないようにしたいと考えました。しかし、現状では未入力の場合でもボタンがクリック可能です。
```react

import { FC, memo, ReactNode } from "react";
import { Button } from "@chakra-ui/react";

type Props = {
  children: ReactNode;
  disabled?: boolean;
  loading?: boolean;
  onClick: () => void;
};

export const PrimaryButton: FC<Props> = memo((props) => {
  const { children, disabled = false, loading = false, onClick } = props;
  return (
    <>
      <Button bg="teal.400" color="white" _hover={{ opacity: 0.8 }} onClick={onClick} disabled={disabled || loading} isLoading={loading}>
        {children}
      </Button>
    </>
  );
});

```

# 解決策
***<font color="Red">disabledではなくisDisabledを使用する</font>***

公式ドキュメントを確認したところ、Chakra UIでボタンを無効化させる場合は、isDisabledプロパティを使用する必要があることがわかりました。

![スクリーンショット 2024-09-01 10.18.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835217/2ade146e-a28c-f4db-4406-ac7eb0cb0ed5.png)

# 終わりに
今回参考にした海外のサイトでは、isDisabledという名前がわかりにくいという意見が見受けられました。 このように、バージョンアップなどによってこれまで使えていたものが急に使えなくなることがありますので、今後も最新情報をキャッチアップしていきたいと思います。

# 参考

https://github.com/chakra-ui/chakra-ui/issues/7269

https://qiita.com/shunii/items/713a9aed57493ddbd82f#%E5%95%8F%E9%A1%8C
【JavaScript】スプレッド構文、レスト構文、分割代入まとめ

## 学習に使用した教材
以下の動画でJavaScriptのスプレッド構文、レスト構文、分割代入について勉強したので、備忘録として残しておきます

https://www.udemy.com/course/the-web-developer-bootcamp-2021-japan/

## スプレッド構文
配列やオブジェクトの要素を展開できる構文
### 複数の配列を1つの配列にまとめる
```javascript:app.js
const backend = ["Ruby", "PHP", "Python"];
const frontend = ["HTML", "CSS", "JavaScript"];

const languages = [...backend, ...frontend, "Java", "TypeScript"];

console.log(languages);

// 出力結果
// ['Ruby', 'PHP', 'Python', 'HTML', 'CSS', 'JavaScript', 'Java', 'TypeScript']
```
### 複数のオブジェクトを1つのオブジェクトにまとめる
```javascript:app.js
const taroSkills = {
    javascript: 80,
    react: 70
};
const hanakoSkills = {
    javascript: 70,
    ruby: 80,
};

const totalSkills = {...taroSkills, ...hanakoSkills, sql: 70};

console.log(totalSkills);

// 出力結果
// {javascript: 70, react: 70, ruby: 80, sql: 70}
```
- 展開するオブジェクト同士で同じパラメータがある場合は、後に展開したオブジェクトのパラメータの値で上書きされる
### 関数の呼び出しにスプレッド構文を使う
```javascript:app.js
function add (a, b, c) {
    return a + b + c;
}

const nums = [1, 2, 3];

const sum = add(...nums);

console.log(sum); // 6
```
## レスト構文（残余引数）
残りの引数を1つの配列に集約できる構文
```javascript:app.js
function awardMedals(gold, silver, bronze, ...others) {
    console.log(`金メダル: ${gold}\n銀メダル: ${silver}\n銅メダル: ${bronze}\n4位以下: ${others}`);
}

awardMedals("Japan", "China", "USA", "GB", "Ukraine", "Italy");

// 出力結果
// 金メダル: Japan
// 銀メダル: China
// 銅メダル: USA
// 4位以下: GB, Ukraine, Italy
```
## 分割代入
配列の要素やオブジェクトのプロパティに割り当てる変数を一度に複数定義できる構文
### 配列の分割代入
```javascript:app.js
const result = ["Japan", "China", "USA"];

const [gold, silver, bronze] = result;

console.log(`${gold}, ${silver}, ${bronze}`);

// 出力結果
// Japan, China, USA
```
### オブジェクトの分割代入
プロパティと同名の変数に値が代入される
```javascript:app.js
const player = {
    name: "Shohei Ohtani",
    team: "Los Angeles Dodgers"
};

const { name, team } = player;

console.log(`${name}, ${team}`);

// 出力結果
// Shohei Ohtani, Los Angeles Dodgers
```
プロパティ名とは別名の変数に値を代入したい場合は、以下のように書く
```javascript:app.js
const player = {
    name: "Shohei Ohtani",
    team: "Los Angeles Dodgers"
};

const { name: playerName, team: belongingTeam } = player;

console.log(`${playerName}, ${belongingTeam}`);

// 出力結果
// Shohei Ohtani, Los Angeles Dodgers
```
### パラメータの分割代入
プロパティと同名のパラメータに値が代入される
```javascript:app.js
const player = {
    firstName: "Shohei",
    lastName: "Ohtani",
    team: "Los Angeles Dodgers"
}

function fullName ({firstName, lastName}) {
    return `${firstName} ${lastName}`;
}

const playerName = fullName(player);

console.log(playerName); // Shohei Ohtani
```
並列で8Queensを解いた話（１）

# デバッグを兼ねて
Easy-ISLispはver5.30をもって一応の完成をみました。バグ発見のテストを兼ねて8Queensを並列で解くことに挑戦してみました。


# ベースはM.Hiroiさんのコード
M.HiroiさんのISLisp入門の記事中のQueens問題のコードを使わせていただきました。これをベースにして逐次のものにプラス、マルチプロセス並列での8queensを書き加えました。コードは下記の通りです。


```lisp
;;; originally written by M.Hiroi

(defun 8queens ()
    (mp-exec (81queens)
             (82queens)
             (83queens)
             (84queens)
             (85queens)
             (86queens)
             (87queens)
             (88queens)))


(defun 81queens ()
    (pqueens '(2 3 4 5 6 7 8) nil 1))

(defun 82queens ()
    (pqueens '(1 3 4 5 6 7 8) nil 2))

(defun 83queens ()
    (pqueens '(1 2 4 5 6 7 8) nil 3))

(defun 84queens ()
    (pqueens '(1 2 3 5 6 7 8) nil 4))

(defun 85queens ()
    (pqueens '(1 2 3 4 6 7 8) nil 5))

(defun 86queens ()
    (pqueens '(1 2 3 4 5 7 8) nil 6))

(defun 87queens ()
    (pqueens '(1 2 3 4 5 6 8) nil 7))

(defun 88queens ()
    (pqueens '(1 2 3 4 5 6 7) nil 8))



;; 衝突の検出
(defun attack (x xs)
    (labels ((attack-sub (x n ys)
                         (cond ((null ys) t)
                               ((or (= (+ (car ys) n) x)
                                    (= (- (car ys) n) x))
                                nil)
                               (t (attack-sub x (+ n 1) (cdr ys))))))
            (attack-sub x 1 xs)))


;; 解法（逐次　オリジナル）
(defun nqueens (nums board)
  (if (null nums)
      (format (standard-output) "~A~%" board)
    (for ((xs nums (cdr xs)))
         ((null xs))
         (if (attack (car xs) board)
             (nqueens (remove (car xs) nums)
                      (cons (car xs) board))))))


;; 解法(並列)
(defun pqueens (nums board n)
    (if (null nums)
        (pqueens1 board n)
        (for ((xs nums (cdr xs)))
             ((null xs))
             (if (attack (car xs) board)
                 (pqueens (remove (car xs) nums)
                          (cons (car xs) board)
                          n)))))


(defun pqueens1 (board n)
    (cond ((attack n board)
           (let ((stm (create-string-output-stream)))
               (format stm "~A~%" (cons n board))
               (mp-report  (get-output-stream-string stm))))
          (t nil)))


(defun remove (x ls)
    (cond ((null ls) nil)
          ((eq x (car ls)) (remove x (cdr ls)))
          (t (cons (car ls) (remove x (cdr ls))))))


```

mp-exec というのはEasy-ISLispの拡張関数です。マルチプロセス並列で各関数を実行します。

並列の計算においてはわざと１つ数が少ないものについて解を計算して、そこに抜けておいた数を当てはめてみてセーフならば解とするという方法をとっています。これにより8queensを８つの計算に分割しています。

(mp-create 8)により8個の子Lispを起動させるのですが、メモリ不足のようです。セルの数を半減させたら動作しました。


# 計測

逐次
![bandicam 2024-09-01 11-01-52-161.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/d9235944-44a0-1427-2afa-080ca4ea34e3.jpeg)

並列
![bandicam 2024-09-01 11-02-09-510.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/9db1849b-1b12-bace-608a-a70e1154e35d.jpeg)


う～ん、おかしいですね。並列の方が遅いですね。なぜでしょう？　解の表示をしている部分が遅いのかもしれません。mp-reportという関数を使って子Lispからメインプロセスの端末に表示させているからです。改良の余地ありです。解を表示しないパターンで計測をしてみようと思います。（続く）


# 参考
M.HiroiさんのISLisp入門記事　http://www.nct9.ne.jp/m_hiroi/clisp/islisp02.html#chap10
Easy-ISLisp https://github.com/sasagawa888/eisl
JavaScript: spread vs apply

spread構文とapply関数の速度比較をしてみます。

```js
for(let loop=1e7,size=10,n=4,fn=a=>a;n--;loop/=10,size*=10){
	let A=Array(size).fill(1),t=new Date;
	for(let a=loop;a--;)fn.apply(0,A);
	t=new Date-t;
	let u=new Date;
	for(let a=loop;a--;)fn(...A);
	console.log("loop:",loop,"size:",size,"time:",t,new Date-u)
}
```
```plaintext:結果
[Google Chrome 128.0.6613.113]
loop: 10000000 size: 10 time: 820 545
loop: 1000000 size: 100 time: 263 222
loop: 100000 size: 1000 time: 184 174
loop: 10000 size: 10000 time: 175 170
loop: 1000 size: 100000 time: 181 173

[Edge 128.0.2739.54]
loop: 10000000 size: 10 time: 834 573
loop: 1000000 size: 100 time: 270 234
loop: 100000 size: 1000 time: 201 177
loop: 10000 size: 10000 time: 181 173

[Fire Fox 97.0.1]
loop: 10000000 size: 10 time: 313 3946
loop: 1000000 size: 50 time: 83 1675
loop: 100000 size: 250 time: 19 938
loop: 10000 size: 1250 time: 63 3478
loop: 1000 size: 6250 time: 29 1756

[Fire Fox 97.0.1]
loop: 10000000 size: 10 time: 320 3897
loop: 1000000 size: 80 time: 119 2479
loop: 100000 size: 640 time: 361 17878
loop: 10000 size: 5120 time: 254 14776
loop: 1000 size: 40960 time: 570 12094
```
GCとEdgeの場合は僅差でspread構文の方が高速、FFの場合はぶっちぎりでapply関数が高速。ちなみにFFでは`size*=5`と`size*=8`で検証(低速過ぎるので)。
それにしてもFFの`loop: 10000 size: 1250 time: 63 3478`の結果が低速なのは疑問

## Object
ついでなので`Object.assign`とも比較
```js
{const a={},z={},loop=1e3;
for(let b=1296,c;a[c=(b*b).toString(36)]=z[c+"_"]=b--;);
//単体
let t=new Date;
for(let b=loop,c;b--;)c={...a};
console.log("spread",new Date-t);

t=new Date;
for(let b=loop,c;b--;)Object.assign(c={},a);
console.log("assign",new Date-t)

//複体
t=new Date;
for(let b=loop,c;b--;)c={...a,...z};
console.log("spread x2",new Date-t);

t=new Date;
for(let b=loop,c;b--;Object.assign(c,z))Object.assign(c={},a);
console.log("assign x2",new Date-t)
}
```
```plaintext:結果
[Google Chrome 128.0.6613.113]
spread 831
assign 903
spread x2 1687
assign x2 1811

[Edge 128.0.2739.54]
spread 886
assign 929
spread x2 1828
assign x2 1939

[FireFox 97.0.1]
spread 829
assign 589
spread x2 1306
assign x2 1070
```
これもFFは関数の方が高速で、FF以外はspreadの方が高速という結果
Android Studio のコード整形による自動改行

コード整形を行った時に不要な改行がいつも入っていました。設定で改行の有無を調整できるので、その方法をメモします。

`Editor -> Code Style -> 対象の言語 -> Wrapping and Braces -> Hard wrap at`の値で改行する行の長さを変更する。999にしてコード整形したとき自動改行させないようにします。

`Editor -> Code Style -> 対象の言語 -> Wrapping and Braces -> Function declaration parameters -> New line after'(' と Place')' one new line`

`Editor -> Code Style -> 対象の言語 -> Wrapping and Braces -> Function call arguments -> New line after'(' と Place')' one new line`

こちらのチェックを外すことで、メソッドを呼び出や引数を設定しているコードでの自動改行を防げます。最初は自動改行される原因が行数の指定（hard wrap)だけかと思っていたけれど、もっと細かく指定できるようです。

既存プロジェクトではわざと改行していないコードをよくみます。gitの差分を減らすため毎回最後にコード整形 -> deleteで改行調整していましたので、その作業量も減りそうです。

参考

https://phoneappli.hatenablog.com/entry/2020/12/11/115925
#009: NSGでBastionへの接続元を制限（Azure Portal）

※本記事は、個人の意見および個人的活動を記したものであり、会社を代表するものではありません

# 1. Bastionへのアクセス制限の１つとして、接続元を制限する

Bastionへのアクセスを制限する方法はいくつかあるが、わかりやすいのはアクセス元のIPを制限する方法。今回はそれを設定する。

やり方は、AzureBastionSubnetに対してNSGを追加登録し、NSGでサブネットへのインバウンドアクセスが可能なIPを特定IPに制限する。

## 1-1. Bicepでの対応方針

BicepではNSGリソースの追加登録とAzureBastionSubnetへの紐付けだけを実施する。具体的なIPの制限は、構築時に実施するのではなく、システムがリリースされ、実際にアクセスする必要のあるIPが具体的になってから運用フローの中で登録すれば良いと思う。

今回はリソース作成後にインバウンドアクセスが可能なIPレンジを登録するスクリプトを作成することで対応してみる。

# 2. NSGの定義

AzureBastionSubnetへ紐づけるNSGは以下のパラメータで作成する。

- リソース名: RagSystem-AzureBastionSubnetNSG-dev

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466853/a6926871-42c8-5353-ec68-0ea0c30b79fe.png)

作成されたリソースは、予想通りNSGだけ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466853/21d9170c-e57b-0386-fb8c-d76a97070cbc.png)

# 3. AzureBastionSubnetとの紐付け

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466853/d84de32b-af81-4b71-8c15-fbb352827c8c.png)

ここまでの手順では、NSGには既定のルールしか定義されていない状態。この状態でAzureBastionSubnetにNSGを追加しようとすると、以下のエラーが発生する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466853/991f9bc5-2eea-087c-92d0-9eec257f8644.png)

このエラーの回避方法は以下のブログで紹介されている。

https://jpaztech.github.io/blog/network/bastion-nsg/

上記のブログに記載のルールについて、過剰に設定されているように思えたので１つ１つ設定したり外したりしながら確認したが、説明されているルール全て必須で、１つでも不足するとAzureBastionSubnetに紐づけることができなかった。

設定内容は以下の通り、ブログの内容とほぼ同じ。（優先度の数字やClientのIPアドレスが異なるぐらい）

## 3-1. NSGのインバウンドルール一覧（設定後）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466853/ccd392c5-3652-24fe-4602-04e38f6253da.png)

## 3-2. NSGのアウトバウンドルール一覧（設定後）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466853/c38bf4c8-5c24-e3e2-672e-9d357681f335.png)

## 3-3. NSGルール設定後にAzureBastionSubnetに紐付け

これでようやく紐付けができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466853/e9d7d312-fa48-7dd0-fcb9-49484d30618d.png)

# 4. 動作確認：Bastion経由でVMにアクセス

ここまでの構築結果により、許可したIPからのみ、Bastion経由でVMにログインできるようになっている。また、VMログイン時のローカルアカウントのパスワードはKeyVaultから取得できるようになっている。

## 4-1. 「Authentication Type」で「Password from Azure Key Vault」を選択

以下のようにAuthentication Typeで「Password from Azure key Vault」を選択すると、Key Vaultに保存したシークレットが選択できるようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466853/05784afc-0bc1-ef9a-3ffb-0c93fd4d9660.png)

## 4-2. アクセス元のIPを許可しない場合の挙動

では、許可されていないIPからアクセスした場合はどのような挙動になるのか。

試してみると、Bastionにログインするところまではできる（Bastion自体にはアクセスできる）が、実際にログインを実行すると、真っ白な画面から先に進まないので、おそらくブロックされていると思われる。

::: note
真っ白な画面のイメージは参考にならないので掲載なし
:::

次回は、NSGの作成、ルールの設定、そしてNSGとAzureBastionSubnetの紐付けをBicepで実施してみる。
オブジェクト配列データ反映

```ts
interface Item {
  id: number;
  title: string;
  name:string;
  isCheck:boolean;
}

const ItemList1: Item[] = [
  { id: 1, title: "Item 1", name:"Item 1", isCheck:false },
  { id: 2, title: "Item 2", name:"Item 2", isCheck:true },
  { id: 3, title: "Item 3", name:"Item 3", isCheck:false },
  { id: 4, title: "Item 4", name:"Item 4", isCheck:true },
  { id: 5, title: "Item 5", name:"Item 5", isCheck:false },
  { id: 6, title: "Item 6", name:"Item 6", isCheck:false },
  { id: 7, title: "Item 7", name:"Item 7", isCheck:true },
  { id: 8, title: "Item 8", name:"Item 8", isCheck:false },
  { id: 9, title: "Item 9", name:"Item 9", isCheck:true },
  { id: 10, title: "Item 10", name:"Item 10", isCheck:false },
];

const ItemList2: Item[] = [
  { id: 1, title: "Item 1", name:"Item 1", isCheck:false },
  { id: 2, title: "Item 2", name:"Item 2", isCheck:false },
  { id: 3, title: "Item 3", name:"Item 3", isCheck:false },
  { id: 4, title: "Item 4", name:"Item 4", isCheck:false },
  { id: 5, title: "Item 5", name:"Item 5", isCheck:false },
];

ItemList1.forEach(item1 => {
  const item2 = ItemList2.find(item2 => item2.id === item1.id);
  if (item2) {
    item2.isCheck = item1.isCheck;
  }
});

console.log(ItemList2);

```

idが一致するデータの値上書き
バンドルってなんだっけとなったので調べました

## はじめに
自分が今参画しているプロジェクト内でES buildが当たり前のように使用されていました。
これって何だろうかと調べるとバンドルツールの一種とのこと。
バンドルって何なんだっけ...!?となったので調べてまとめました。

## バンドルとは
複数のファイルやモジュールを1つのファイルにまとめるプロセスのこと。
主にJavaScriptやCSSのようなWeb開発において使われる概念。
他の言語や環境でも使用されることがある。

## バンドルされたコードってどんなの？
以下が実際にesbuildでバンドルされたコードの一部です。
どんな処理が書かれているのか全然わからないですね。

```javascript
"use strict";var p6=Object.create;var vl=Object.defineProperty;var 
m6=Object.getOwnPropertyDescriptor;var f6=Object.getOwnPropertyNames;var
h6=Object.getPrototypeOf,v6=Object.prototype.hasOwnProperty;var fe=(e,t)=>()=>
(e&&(t=e(e=0)),t);var O=(e,t)=>()=>(t||e((t={exports:
{}}).exports,t),t.exports),Bo=(e,t)=>{for(var n in t)vl(e,n,
{get:t[n],enumerable:!0})},Lb=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof
t=="function")for(let i of f6(t))!v6.call(e,i)&&i!==n&&vl(e,i,{get:
()=>t[i],enumerable:!(r=m6(t,i))||r.enumerable});return e};var Re=(e,t,n)=>
(n=e!=null?p6(h6(e)):{},Lb(t||!e||!e.__esModule?vl(n,"default",
{value:e,enumerable:!0}):n,e)),Oe=e=>Lb(vl({},"__esModule",{value:!0}),e);var
Xn=O((Yye,Gb)=>{var
gl=Object.defineProperty,g6=Object.getOwnPropertyDescriptor,_6=Object.getOwnPrope
rtyNames,y6=Object.prototype.hasOwnProperty,_l=(e,t)=>gl(e,"name",
{value:t,configurable:!0}),x6=(e,t)=>{for(var n in t)gl(e,n,
{get:t[n],enumerable:!0})},b6=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof
t=="function")for(let i of _6(t))!y6.call(e,i)&&i!==n&&gl(e,i,{get:
()=>t[i],enumerable:!(r=g6(t,i))||r.enumerable});return
e},E6=e=>b6(gl({},"__esModule",{value:!0}),e),Bb={};x6(Bb,
```

## なんでJavaScriptで使用されるのか？
JavaScriptは、Webブラウザで動作するクライアントサイドのスクリプト言語です。
複数のファイルがあるとWebブラウザがウェブページ表示するのに複数回のHTTPリクエストが必要となり動作が遅くなります。
バンドルツールによって複数のJavaScriptファイルを1つにまとめることでそういった問題を解消することができるため利用されています。

## バンドルの目的とメリット

### パフォーマンスの向上
バンドルすることで複数のファイルを1つにまとめるため、サーバーとクライアント間のリクエスト数を減らすことができます。これにより、Webページの読み込み速度が向上します。

### 依存関係の管理
多くのプロジェクトは外部ライブラリやモジュールに依存しています。バンドルツールは、これらの依存関係を解析し、適切な順序で1つのファイルにまとめます。これにより、コードの管理が容易になります。

### コードの最適化
バンドルツールは、コードを圧縮（ミニファイ）したり、使用されていないコードを削除したりする機能も持っています。これにより、ファイルサイズが小さくなり、Webページのパフォーマンスがさらに向上します。

## バンドルのデメリット
バンドルはメリットばかりではないようです。
デメリットも理解して利用するかを検討すると良さそうです。

### ビルド時間の増加
バンドルプロセスには時間がかかる場合があります。特にプロジェクトが大規模になると、ビルド時間が長くなり、開発速度に影響を与えることがあります。

### 初期ロードのパフォーマンス問題
バンドルされたファイルが非常に大きい場合、初期ロード時にクライアントが多くのデータをダウンロードしなければならないため、ページの表示速度が遅くなることがあります。この問題を回避するために、Code SplittingやLazy Loadingなど(ここはまだあまり分かっていないです。)のツールがあるそうです。

### デバッグの難しさ
バンドルされたコードは通常、圧縮や難読化されているため、デバッグが難しくなることがあります。
特に、バンドルされたファイルが大きい場合や、多くの異なるモジュールが含まれている場合、問題の特定が困難になることがあります。

## バンドルツールの例
* **Webpack:** 最も一般的なバンドルツールの1つで、JavaScriptやCSS、画像などさまざまなファイルをバンドルすることができます。
* **esbuild:** 高速で効率的なバンドルツールで、主にJavaScriptとTypeScriptのバンドルに使われます。
* **Parcel:** 設定なしで動作することを目指したバンドルツールで、シンプルなプロジェクトに適しています。

## 最後に
複数のファイルを自動でまとめて一つに最適化してくれるバンドルに関してまとめていて
居酒屋で退店時に食器を下げやすいようにまとめてから席を立つ非常にマナーのなっている学生時代の先輩を思い出しました。
バンドルしてくれたら、店員さんが席の片付けする時楽だよね。

![バンドルっていいな.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3369754/efb29abf-f53b-4672-91d3-367527505c1c.png)
[Operating Ratio] 稼働率

# 稼働率
`0R` = `MTBF` / ( `MTBF` + `MTTR` )

# 一覧
|略称|総称|対応|
|:--|:--|:--|
|MTBF|Mean Time Between Failure<br>平均故障間隔|冗長度の高いシステム<br>予防保守<br>自動誤り訂正機能|
|MTTR|Mean Time To Repair<br>平均修理時間|エラーログの取得<br>遠隔地保守<br>保守センタの分散|

# 参考リンク
- [MTBF、MTTR、Operating Ratioとは](https://www.fukudaco.co.jp/support/glossary/mtbf-mttr-operating-ratio.html#:~:text=MTTRとはMean%20Time,示す指標のひとつです%E3%80%82)
- []()
NetBIOSってなに？

<h3>NetBIOSとは。</h3>
昔の名前解決システム。<br>
いまではDNSやLDAPが主流。<br>
一葉今でもwindowsのworkgroup環境で使われている。

昔はNetBIOSとして使われていてTCP/IPには対応していなかった。
RFC 1001およびRFC 1002で「NetBIOS over TCP/IP (NBT)」が定義されてからTCP/IP上で使えるようになった。


図１
 <table border="1">
        <thead>
            <tr>
                <th>プロトコル</th>
                <th>ポート番号</th>
                <th>サービス名</th>
                <th>概要</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>TCP／UDP</td>
                <td>137</td>
                <td>netbios-ns</td>
                <td>NetBIOS名（マシン名）からIPアドレスを導き出す「名前解決」に使用される。「NetBIOS名前サービス」とも呼ばれる</td>
            </tr>
            <tr>
                <td>TCP／UDP</td>
                <td>138</td>
                <td>netbios-dgm</td>
                <td>ネットワーク・コンピュータの一覧を得る「ブラウジング」に使用される。「NetBIOSデータグラム・サービス」とも呼ばれる</td>
            </tr>
            <tr>
                <td>TCP</td>
                <td>139</td>
                <td>netbios-ssn</td>
                <td>ファイル／プリンタ共有に使用される。「NetBIOSセッション・サービス」とも呼ばれる</td>
            </tr>
        </tbody>
    </table>

図1 引用元

https://atmarkit.itmedia.co.jp/fpc/experiments/008bbrouter_sec/block_share_02.html
【AWS認定合格記】AWS ソリューションアーキテクトプロフェッショナル(SAP-C02)

:::note warn
受験は今から約半年も前のことになりますが、当時の勉強方法などの備忘録を記載しています。
:::

## はじめに
軽く自己紹介すると、、
◆学部卒(非情報系)
◆新卒でSIerに入社し、3年目。
◆取得資格
| 資格名 | 取得日 |
|:-----------|:-----------|
| 基本情報技術者 | 2021年11月  |
| AWS クラウドプラクティショナー | 2023年2月 |
| AWS ソリューションアーキテクトアソシエイト | 2023年7月 |
| AWS ソリューションアーキテクトプロフェッショナル | 2024年3月 |
| AWS デベロッパーアソシエイト | 2024年3月 |
| AWS sysOps Administrator アソシエイト | 2024年4月 |


:::note info
sysOpsAdministratorアソシエイトを取得するまでは、業務ではAWSに携わったことはありませんでした。
:::



## 勉強方法
使用した問題集は、**CloudTechのみ**でした。

 https://kws-cloud-tech.com/

個人的なCloudTechの使い方は以下。
　①まずは、CloudTechの問題に目を通してみる。
　②分からないワードを調べる。
　③答えを見てなぜその答えなのか、解説を読む。分からないところは調べる。
　④全ての問題で①〜③を行う。
　⑤実際に答えを見ずに解けるか確認する。


:::note info
実は、SAPは1回落ちているのですが、その時のCloudTechの正答率は約80%ほど。
正答率を90%超えるまで繰り返して、落ちた2週間後に2回目の受験で合格しました。

:::


## 勉強期間
合格までに要した期間は**約1ヶ月半**。

平日：約3時間〜4時間
休日：約7時間~9時間

ざっくりの計算で**約150時間ほど**でした。
SAAを取っているとはいえ、実務としてのAWS経験はなかったため、実務経験がある方はもっと早くに撮れるのかもしれません。


## 試験当日

| 時間 | 流れ |
|:-----------|:-----------|
| 13:30 | 試験開始|
| 16:30 | 試験終了|
| 19:30 | 合格通知メール届く|　


試験は180分間ですが、ギリギリまで時間を使わないといけないほど、問題文が長かったです。
180分となると、だんだん集中力も切れてくるので、気合いで乗り切りました。

試験終了後もあまり自信はなく、合格の場合はいつメールが来るのかとずっとソワソワして受験した人のポストを検索したりしてました。

https://aws.amazon.com/jp/certification/certified-solutions-architect-professional/


## モチベーションの保ち方
:::note info
個人的には、
①**取得後の自分のメリットを考える**こと
②**周りに受験仲間がいる**こと
がモチベーションになりました。
:::

私の場合は、業務として未経験のAWSをやらせてもらうため、やる気を証明するために取得しました。
自分がどうしてAWSを業務でやりたいのかを考え、それが自分にとっても、会社にとってもメリットになることがモチベーションにつながったと思います。

また周りの社員には、すでに12冠持っている人がいたり、AWS認定の試験を受けようとしている人が多かったため、自分も負けていられないなとモチベーションが上がりました。



## 受験〜合格しての所感
### やっぱり嬉しい！

もちろんSAPを取得するだけではAWSのことが何でもわかる訳ではないけれど、AWSに対するやる気があることの証明になり、無事AWS案件に携わることができたので、合格して良かったです。

:::note info
AWS認定試験の中でもかなり難しいと言われているSAPに合格することで、少し自信がついたのと、勉強を継続する忍耐力がついたと思います。
:::
[Python]最適化を用いたモデルマッチング(PIDゲインの調整方法)

# 目的
最適化を用いたモデルマッチング(PIDゲインの調整方法)を行うためのPythonスクリプトを紹介する。また、限界感度法と比較してモデルマッチングの方が調整されたPIDコントローラの目標値追従性能が高いことを示す。

尚、この記事で紹介しているモデルマッチングは制御対象のモデルが必要となる手法であるが、データ駆動型制御といわれる手法を用いれば制御対象のモデルを使用せずにモデルマッチングを行うことも可能である。

参考情報：<a href="https://qiita.com/WandererEng/items/27dae0d4ef0b1195024d">データ駆動型制御(FRIT、VRFT)を図的に理解する</a>

# 本記事のPIDゲイン調整の概要
制御対象のモデルを作成し、PIDゲインを変更したコントローラと制御対象のモデルを用いたシミュレーションをなんども繰り返すことで少しずつPIDゲインを調整していく。
調整するPIDコントローラと制御対象のモデルのブロック線図を以下に示す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111514/b5f2d3a7-8faf-07d8-fbe0-9b59b5635948.png)

# 最適化を用いたモデルマッチング
理想とする閉ループ伝達関数を設定しその閉ループ伝達関数に制御目標を入力したときの応答を理想の応答とする。制御対象のモデルを用いたシミュレーションを行い推定した応答が理想の応答に一致するようにPIDゲインを調整する方法はモデルマッチングと呼ばれている。この記事では最適化を用いてモデルマッチングを行うが、最適化を用いる利点は制御対象のモデルとして単純な伝達関数だけでなく、ニューラルネットワークなど複雑なモデルを用いることができるという点である。尚、伝達関数やニューラルネットワークの作成方法については<a href='https://qiita.com/akahoshi51/items/67d636e42befae097e30'>機械学習や制御工学に関するPythonやRのスクリプト</a>に記載している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111514/bee6b936-4309-a34e-8d07-5d04173ee1a1.png)

# 最適化式
最適化アルゴリズムを用いてPIDゲインの調整を行うために、最適化式を以下のように定める。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111514/ec4f6e87-3a26-dd19-fb59-009ac8f45ffe.png)

# シミュレーション条件
・２次遅れむだ時間系
（<a href="https://qiita.com/akahoshi51/items/459f924037d603a0f682">[Python] 限界感度法で調整されたPIDコントローラの目標値追従性能が低いことを示すスクリプト</a>と同条件）

# 最適化結果
## 動作確認
モデルマッチングで最適化したPIDゲインの応答(y_model_matching)が理想の応答(y_d)と概ね一致しているため、最適化スクリプトは問題なく動作できていると判断できる。尚、理想の応答は普遍的なものでなくドメイン知識を要して設定する必要があるが、今回は１次遅れ系とし時定数は最適化したPIDゲインの応答をみながらを見ながら調整した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111514/641fe982-be8b-2aa1-e795-d584ebc7ab11.png)

## 限界感度法で調整したPIDゲインとの比較
参考のため<a href="https://qiita.com/akahoshi51/items/459f924037d603a0f682">[Python] 限界感度法で調整されたPIDコントローラの制御性能が低いことを示すスクリプト</a>で調整したPIDゲインでの応答の比較を以下に示す。限界感度法(ZN(original)やZN(No overshort))よりもモデルマッチングの方が収束が早く制御性能が高いとできる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111514/215e88ea-7701-57e6-00bd-c42c4b426667.png)
心理学の問題点

# 🍵 エンジニア心理学

https://qiita.com/minegishirei_v2/items/49784ea87ba160ef8065

## 対象者

- 同僚のパーソナリティを理解しようとするエンジニア
- 同僚の一時的な感情を理解しようとするエンジニア
- 信頼関係を構築したいエンジニア
- 同僚に動いてもらえる確率を少しでもあげたいエンジニア

## 概要

心理学が抱える課題を事前に洗い出し、エンジニア心理学を展開するにあたって不安点、疑問点を解消する試みです。

# 🏁 エンジニア心理学の目標

エンジニア心理学の目標は次の二つです。

- プログラマーとチームリーダーの摩擦を解消する方法論をまとめチームの価値を最大化する
- 顧客の言葉を理解し、信頼関係を構築し、品質とコスト面で駆け引きを行う方法論をまとめる

これらを心理学を用いてプロジェクトの成功率を最大限高める試みです。

https://qiita.com/minegishirei_v2/items/260617a0406d31affeef

# 😨 心理学の課題

準備中...


# 心理学の課題

心理学を探求するにあたって、直視しなければならない問題点が現時点で2つあります。

- 再現性の問題
- 定義の難しさ

それぞれ順に見ていきます。


## 再現性の問題点

もう10年前の記事になってしまいますが、心理学の実験において再現性に疑念が生じる研究結果が発表されました。

> > 追試対象となった研究は，Psychological Science（PSCI） 誌，Journal of Personalityand Social Psychology（JPSP） 誌，Journal of Experimental
>
> > 「再現性が確認できた研究は 100 件中の39 件」全体の 39％ だった
>
> > これは，追試を実施した研究者たちの主観的評価，つまり「オリジナルの結果が再現されましたか？」という質問に「はい」と答えた比率が 39％だった点を取り上げたものと思われます。
> > より客観的なデータを見ると，オリジナルの論文のうち 97％は統計的に有意な効果が得られていた（つまり 3％は nullefect〔効果なし〕研究だった）のですが，追試では 36％，追試の効果量の 95% 信頼区間に元論文の効果量が含まれていた（つまり「ほぼ」も含めて再現されたと考えてもよさそうな）研究は 47％でした。

http://chitosepress.com/blog/wp-content/uploads/2019/11/PsyNaviBooklet_Vol001_201911.pdf

上記の内容を解釈すると

- 2008年以降の心理学雑誌で取り上げられた研究100件を対象
- 追試を行った研究者の質問で、「オリジナルの結果が再現できたか？」という主観的な質問に39人が「はい」と答えた（残りの選択肢は不明）
- 統計的には 97% は有効な結果が得られた。

**追試を行った研究者は、オリジナルの実験が有効であると断言できなかったのが61%であるという結果であり、統計的には有効でした。**

統計的には有効であるとはいえ、心理学への再現性の危うさ、ふわっと感は心理学の博士院生でも感じているようです。

> 実際の研究の結論は、だいたいふわふわしているのです。

https://note.com/sugo_ron/n/nff9282091a07


## 定義の曖昧さ

二つ目の問題点は、心の動きを定義することの難しさという点です。

> > 僕は現在生徒の「モチベーション」について研究をしています。モチベーションについて研究をしている人は他にもたくさんいます。こうした研究者を百人同じ部屋に集めて、「モチベーションってなんですか？」という質問をしてみましょう。
> > どうなるでしょうか。
> >
> > 喧嘩です。
> > 全員が全員、眼鏡をクイクイしながら持論を展開することでしょう。モチベーションの研究をしているのに、モチベーションの定義が専門家の間で定まっていないのです。
> >
> > これは他の分野ではありえないことです。例えば幾何学者の間で、「三角形とはなんぞや？」という議論が発生する事はありません。知らんけど。心理学は往々にして研究対象が実体を持たないので、研究対象の定義がなんなのか、さらにはそもそも研究対象が研究対象たりうるものかどうかから考察しなければいけないのです。
>
> https://note.com/sugo_ron/n/nff9282091a07
>
> 心理学の博士院生が語る、心理学ってうさん臭くね？という話


# 心理学の立ち位置

## 心理学は「人の理解の一助」という立ち位置

心理学は、最終的には人の理解の一助としての立ち位置になるかと思います。

> > 心理学専攻で人の気持ちがわかるか、というと、答えはNOです(泣)
> >
> > そして、肝心の授業はというと、学部までですと、まず心理学の歴史と、たとえば◯◯効果などの「こういう現象があります」という説明が大半であり、「相手が髪を触ったらウソをついている」的な人心掌握術はまったく教わりません。というかそういうものがすべて眉唾なのだなあと思うようになります。教育心理学の授業ですと、イメージでは「学級崩壊の立て直し方」みたいなのを学ぶかと思いきや、学ぶのは「発達の最近接領域 - Wikipedia」みたいに、人間の知能がいかにして発達するかみたいなところばかりであり、現場的なものはまったく出てきません。
>
> > 心理学とは、相手が何を感じているか、考えているかを他者から見透かす取り組みではなく、「人間は何を感じ、どう考えるのか」を知っていく取り組みなのだと、今はわかります。
>
> https://jp.quora.com/shinri-gaku-wo-senkou-shitara-nin-no-kimochi-ga-wakaru-no-desu-ka/answers/144194013

上記の引用である通り、「人間は何を感じ、どう考えるか」を探求する取り組みであると考えます。

私個人の考えでは、ある程度確率的に推測することは可能かなとは考えてます。ですがこの方は少なくとも、心象把握は大学で教わらないですし、そのような取り組みに意味がないと考えているようです。


## 心理学にできること

一番わかりやすいのは1on1での有効活用かと思います。

- パーソナリティを理解する
- 一時的な感情を推測する
- 相手に好印象を与え、信頼関係を構築する
- 相手に動いてもらえる確率を少しだけあげる
dakboardの導入

# ラズパイを使ったダッシュボード
を検討しています。
smashingを検討しましたが、インストールで躓きました。
ブラウザをキオスクモードでgoogleカレンダーを表示することで一旦落ち着いていました。

# dakboard

![IMG_5916.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675614/d683e40a-2779-0680-d04e-c1d67c10a816.jpeg)


こちらは、ブラウザで設定、ダッシュボードを表示することができるサービスです。
英語のみの対応ですが、それっぽいのができましたので、紹介します。

# 作り方及び設定

https://dakboard.com/


ここから新規アカウントを作成します。
![スクリーンショット 2024-08-22 123943.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675614/ae8f6b55-60f1-07f4-6bbe-a980d7ca7266.png)


登録完了後、ここからレイアウトを選択します。
![スクリーンショット 2024-08-22 124427.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675614/91a9f47e-cd7f-444b-5c90-2cb196493226.png)



こちらからicalカレンダーを登録します。
![スクリーンショット 2024-08-22 124537.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675614/231cc2a0-5bc2-edde-59b0-d109510ce8de.png)


こちらから天気予報の対象地域を登録します。
![スクリーンショット 2024-08-22 124601.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675614/acd5174f-abe0-fc68-858d-7f15479df967.png)


こちらからRSSを登録します。
![スクリーンショット 2024-08-22 135540.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675614/9d4fe9a0-4ce0-6364-9516-2fbb00ac6f45.png)

VIEW SCREENのリンク先のURLをコピーし下記に反映させます。

    $ sudo nano /etc/xdg/lxsession/LXDE-pi/autostart


    @xset s off
    @xset s noblank
    @unclutter
    @chromium-browser --kiosk --app=https://dakboard.com/app/screenPredefined?p=xxxxxxxxxxx


これで起動時にdakboardを表示させることができます。

# いい点
簡単です。
かつ、ちょっとオシャレですよね。
ical形式で登録できるので、googleアカウントの連携みたいな怖いことも起こりません笑
RSS形式も登録できるので、好きな情報をアップデートさせながら表示させることができます。
ical,RSS形式で出力することができれば、テキストデータになりますが、なんでも表示させることができます。
導入、運用に至るまでこんな感じ！なのを求めていました！！


# 課題
残る問題点として、上記ではカレンダーは２件、RSSは１件しか登録することができません。
任意の情報を出すにはical、RSSのいずれかを使う必要があるわけですが、足りません。
かといって、有料版にするのもしゃくです。
なおかつ、右下にロゴが出てるのがうざい。邪魔です。

# 次は
Magicmirror2に挑戦しようと思います。
勝手な認識では、smashingの代替となると思っています。