OmniAICreator/Qiita-1.07M huggingface dataset:
適合確認システム: モックアップの作成 (その1)

こちらのシステムの実装に向けてモックアップを作成しました。
[地方公共団体情報システム標準化の適合確認システム](https://qiita.com/ekzemplaro/items/2219f9eba1b01953e2f2)

## ChatGPT

[ChatGPT](https://chatgpt.com/) に次の依頼をします。

```text
次のWeb システムを作成して下さい。
csv ファイルをアップロードし、ページに、コラム数と、列数を表示する。
```

## ChatGPT の回答

ChatGPT は、Flask の例を提示しました。

フォルダー構造

```text
$ tree
.
├── app.py
└── templates
    └── index.html
```

```py:app.py
from flask import Flask, request, render_template
import csv
from io import TextIOWrapper

app = Flask(__name__)

# ホームページの表示
@app.route('/')
def index():
    return render_template('index.html')

# ファイルのアップロードと処理
@app.route('/upload', methods=['POST'])
def upload():
    if 'csvfile' not in request.files:
        return "ファイルがありません"

    csvfile = request.files['csvfile']
    if csvfile.filename == '':
        return "ファイルがありません"

    # CSVファイルを読み込み、列数と行数を取得
    try:
        csv_reader = csv.reader(TextIOWrapper(csvfile, 'utf-8'))
        header = next(csv_reader)  # ヘッダーを読み飛ばす
        num_columns = len(header)
        num_rows = sum(1 for row in csv_reader)
        
        return f"アップロードされたCSVファイルの列数: {num_columns}, 行数: {num_rows}"
    
    except Exception as e:
        return f"エラーが発生しました: {str(e)}"

if __name__ == '__main__':
    app.run(debug=True)
```

```html:templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSVファイルアップロード</title>
</head>
<body>
    <h2>CSVファイルをアップロードしてください</h2>
    <form action="/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="csvfile" accept=".csv">
        <button type="submit">ファイルをアップロード</button>
    </form>
</body>
</html>
```

## サーバーの実行

```bash
python app.py
```

```text
$ python app.py
 * Serving Flask app 'app'
 * Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 999-058-055
```

## クライアント
[http://127.0.0.1:5000](http://127.0.0.1:5000) にアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/b101a368-64cc-716d-7956-3ba9bd6b53fe.png)

次のファイルをアップロードします。

```csv:cities_header.csv
id,name,population,date_mod
t1271,千葉,59178,2003-9-21
t1272,勝浦,47215,2003-10-15
t1273,市原,83654,2003-6-14
```

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/73eea105-d5a8-d28c-2530-01da5acddc7e.png)

期待通りの結果が得られました。
ヘッダーのない CSV ファイルだと、列数が、(実際の列数　- 1) になります。


## 次のフェーズ

CSV ファイルが基準に適合するか否かを判断する関数を Python で記述する。
gc9a01_mpy を Waveshare ESP32-S3-Touch-LCD-1.28 用にビルドしたい

GPS とディスプレイ付き ESP32 のおもちゃ ([Waveshare ESP32-S3-Touch-LCD-1.28](https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-1.28)) を手に入れたのでこれ用の Micropython の Firmware を Ubuntu 24.04 上でビルドしたときのメモ。結構バージョンの組み合わせでハマった。試行錯誤ありなので多少不正確な部分はあるかも。

https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-1.28

まずは ESP-IDF は 5.0.6。最新版は 5.2.2 だが gc9a01_mpy と合わせてコンパイルできなかった。

https://docs.espressif.com/projects/esp-idf/en/v5.0.6/esp32/get-started/linux-macos-setup.html#get-started-get-esp-idf

ダウンロードはこんな感じ。Ubuntu 上の各種ビルドツールもそれぞれ準備。

```
mkdir -p ~/esp
cd ~/esp
git clone -b v5.0.6 --recursive https://github.com/espressif/esp-idf.git
```

Micropyhon の ESP-IDF サポート状況はここ。(5.2.0 をサポートしているようだが。。)

https://github.com/micropython/micropython/blob/master/ports/esp32/README.md

gc9a01_mpy の情報はここ。Micropython は 1.23.0 を使用。

https://russhughes.github.io/gc9a01_mpy/index.html

```
# git clone -b v1.23.0 git@github.com:micropython/micropython.git
# git clone https://github.com/russhughes/gc9a01_mpy.git
```

ビルド及びファームウェアの書き込みは S3 を追加。

```
# cd micropython/ports/esp32
# make \
    BOARD=ESP32_GENERIC_S3 \
    BOARD_VARIANT=SPIRAM \
    USER_C_MODULES=../../../../gc9a01_mpy/src/micropython.cmake \
    FROZEN_MANIFEST=../../../../gc9a01_mpy/manifest.py \
    clean submodules all
# make \
    BOARD=ESP32_GENERIC_S3 \
    BOARD_VARIANT=SPIRAM \
    USER_C_MODULES=../../../../gc9a01_mpy/src/micropython.cmake \
    FROZEN_MANIFEST=../../../../gc9a01_mpy/manifest.py \
    erase deploy
```

REPL から gc9a01 をインポートしてエラーが出なければ成功！

```
>>> import gc9a01
>>> 
```

サンプルファイルは以下の Sample demo からダウンロードできる。

https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-1.28

ESP32 は色々面白そうなハードウェアが多く魅力的だが開発環境を揃えるのは大変なのかもと思いました。。あと技適付きで販売してくれることを祈るばかり。
【コミュ障は改善不要】コミュ障のメリットとおすすめの仕事

みなさんはコミュニケーションは得意ですか？実は私はコミュ障で、コミュニケーションに対してものすごく苦手意識があります。

以前は**コミュ障を治さなきゃ**とがんばっていましたが、最近は「コミュ障はコミュ障でメリットがあるよね」と思うようになりました。今回はコミュ障の特徴やメリットについて紹介します❗

## コミュ障の特徴
コミュ障の人は、日常生活においてコミュニケーションに苦手意識を持つ人のことを指します。具体的には、以下のような特徴があります。

- 人前で話すことが苦手
- 人と目が合わせられない
- 上手く話せなくて緊張してしまう
- 相手の気持ちが理解できない
- 自分から話しかけることができない
- 大勢の場が苦手
- 電話やメールでのやり取りも苦手

上記はほんの一例ですが、コミュ障をお感じの方なら共感できる内容が多いのではないでしょうか？

## コミュ障のメリット3選
私がコミュ障のメリットと感じているのは、以下の3点です。

- 自分の時間が増え、好きなことに使える時間が増える
- 嫌われてもいいと思えるので、煩わしい人間関係から開放される
- 他人の常識にとらわれず、自分を見失わない

[>> コミュ障のメリット詳細はコチラ！](https://taishi-official.com/2020/04/29/504/#toc3)

## コミュ障の人にオススメな仕事
コミュ障の人におすすめしたい職業があり、それは**ITエンジニア**です。コミュ障の私自身もITエンジニアをしていますし、周りのエンジニアもコミュ障も多いです。これはコミュ障の人は、ITエンジニアの適性があるからだと思っています。なぜコミュ障の人にITエンジニアをおすすめかというと、以下の3つの理由からです。

- 一人で集中して取り組める仕事が多い
- 対面以外でのコミュニケーションが豊富
- 論理的な思考力や問題解決能力が重視される

[>> コミュ障にITエンジニアをおすすめする理由詳細はコチラ！](https://taishi-official.com/2020/04/29/504/#toc7)

## プログラミング未経験でもITエンジニアになる方法
ITエンジニアになるには、まずプログラミングについて学ぶ必要があります。ただ現在エンジニアとまったく無縁のお仕事をされていると、エンジニアになるなんて無理と思われるかもしれません。

ただエンジニアには、プログラミング未経験からでもなることができます。私自身もプログラミング未経験の状態から、ITエンジニアとなりました。その時の経験を踏まえて未経験からITエンジニアとなる方法を、以下の記事にまとめています。ご興味ありましたら、ぜひ読んでみてください。

[>> プログラミング未経験からITエンジニアになる方法](https://taishi-official.com/learning-programming/#toc5)


## まとめ
今回はコミュ障の私が考えるコミュ障の特徴・メリットとコミュ障におすすめの仕事について紹介しました。コミュニケーションが苦手で、悩んでいる方も結構多いと思います。私も昔はそうでした。

しかしあるとき発想を転換して、**コミュ障はステータス**だと考えることで気持ちが軽くなりました。自由につかえる時間がたくさんあり、強がりでなく実際に得なことも多いです。

なので悲観せず、ありのままの自分を受け入れ人生を楽しみましょう❗

### おまけ

https://qiita.com/taishi_will_be/items/70a8ce8938944286b487


https://taishi-official.com/learning-programming/

<strong>＼Follow me／</strong>

- X（旧Twitter）：https://x.com/taishi_it_blog
- Instagram：https://www.instagram.com/taishi_will_be/
- YouTube：https://www.youtube.com/@Engineer_ILLBE
- TikTok：https://www.tiktok.com/@taishi_will_be
- note：https://note.com/taishi_wii_be/

<br>

最後にいいねお願いします:thumbsup:
Rustでクリップボードを扱う(arboard)

# arboard
`arboard`クレートに関する個人的メモ

> This is a cross-platform library for interacting with the clipboard. It allows to copy and paste both text and image data in a platform independent way on Linux, Mac, and Windows.
>
> ---
> arboardはクロスプラットフォームな、クリップボードを扱うライブラリである。これを使うことで、プラットフォームに依存せず、テキストと画像、両方のデータをクリップボードを通じてコピー、ペーストすることができる。
> [Arboard (Arthur's Clipboard)](https://crates.io/crates/arboard)より引用, 筆者訳

`rust_clipboard`クレートがメンテナンスされていないために生まれたらしい
難しくなくてよい

# 使い方
## テキスト
```rust
use arboard::Clipboard

fn main() {
	let mut clipboard = Clipboard::new().unwrap();
	
	// クリップボードのテキストを取得
	let clipboard_text = clipboard.get_text().unwrap();
	
	// クリップボードにテキストを貼り付け
	let the_string = "Hello, world!";
	clipboard.set_text(the_string).unwrap();
}
```

## 画像 
`ImageData`という構造体を使用する
定義は以下のようになっている
```rust
pub struct ImageData<'a> {
    pub width: usize,
    pub height: usize,
    pub bytes: Cow<'a, [u8]>,
}
```
[Struct arboard::ImageData](https://docs.rs/arboard/3.4.0/arboard/struct.ImageData.html)より引用

以下のように使用可能
```rust
use arboard::ImageData;
use std::borrow::Cow;
fn main() {
	let bytes = [
	    // 赤のピクセル
	    255, 0, 0, 255,
	
	    // 青のピクセル
	    0, 255, 0, 255,
	];
	let img = ImageData {
	    width: 2,
	    height: 1,
	    bytes: Cow::from(bytes.as_ref())
	};
}
```
[Struct arboard::ImageData](https://docs.rs/arboard/3.4.0/arboard/struct.ImageData.html)より引用 コメントのみ筆者が日本語訳

クリップボードにコピー、ペーストする例
```rust
use arboard::{Clipboard, ImageData};

fn main() {
	let mut clipboard = Clipboard::new().unwrap();
	
	// クリップボードから画像を取得
	let image = clipboard.get_image().unwarp();
	
	// クリップボードに画像を貼り付け 
	#[rustfmt::skip]
	let bytes = [
		255, 000, 000, 255,
		000, 255, 000, 100,
		000, 000, 255, 100,
		0, 0, 0, 255,
	];
	let img_data = ImageData { width: 2, height: 2, bytes: bytes.as_ref().into() };
	clipboard.set_image(img_data).unwrap();
}
```

# 参考文献
- [github arboard](https://github.com/1Password/arboard/tree/master)
- [document](https://docs.rs/arboard/3.4.0/arboard/index.html)
なでしこ/プロデル でハーシャッド数判定

## はじめに
日本語のプログラミング言語に**なでしこ**、**プロデル**があります。共に、AtCoderで採用されており、それぞれの言語で解答を提出することができます。
今回、同じ問題を両者で解いてみた時、仕様の違いが興味深かったので紹介します。
やり方としては、まずPythonを用いて解答を作り、それを**なでしこ**、**プロデル**に翻訳するという形をとります。

https://nadesi.com/

https://produ.irelang.jp/docs/syntax/

## 問題
```
整数Xを十進法で表したときの各桁の数字の和をf(X)としたとき、Xがf(X)で割り切れる場合、Xはハーシャッド数です。
整数Nが与えられるので、ハーシャッド数かどうか判定してください。
```
https://atcoder.jp/contests/abc080/tasks/abc080_b

## python解答
```python
X0=int(input())
M=0
X=X0
for i in range(len(list(str(X0)))):
  M+=X%10
  X=X//10
if X0%M==0:
  print('Yes')
else:
  print('No')
```
## 翻訳のポイント
#### 数字を文字列として見た時の字数はいくらか
```python
[python]
len(list(str(X0)))

[なでしこ]
Y0=X0を文字列変換。
LはY0の文字数。

[プロデル]
Lは[X0]の文字数。　・・・・・・[]の用法が便利に使える
```
#### Xを、Xを10で割った時の商で置き換える
```python
[python]
X=X//10

[なでしこ]
X=X/10の整数部分。

[プロデル]
Yは、X/10を切り捨てたもの。
X=Y　・・・・・・後からYをXに代入する
```
#### X0がMで割り切れるならば
```python
[python]
if X0%M==0:

[なでしこ]
もしX0%M=0ならば、

[プロデル] 
ANS=X0%M   ・・・・・・計算は先に済ませる
もしANSの整数が0ならば、 ・・・・・・整数指定が必要
```
これらのポイントに対応することでAC解答できます。

## なでしこ解答
```nako
入力を尋ねて、X0に代入。
Y0=X0を文字列変換。
LはY0の文字数。
M=0
X=X0
i を 0 からLまで繰り返す。
  M=M+X%10
  X=X/10の整数部分。
ここまで。
もしX0%M=0ならば、"Yes"を表示。
違えば、"No"を表示。
```

## プロデル解答
```prod
X0は、コンソールから受け取ったもの。
Lは[X0]の文字数。
M=0
X=X0
iを1から1ずつ増やしながらL+1まで繰り返す。
  M=M+X%10
  Yは、X/10を切り捨てたもの。
  X=Y
繰り返し終わり。
ANS=X0%M
もしANSの整数が0ならば、「Yes」を表示。
そうでなければ、「No」を表示。
```

## 終わりに

AtCorderの簡単な問題をいろいろな言語で解いています。言語間の違いを相互に知ることで、効率的に多言語並行学習を進めることが可能と考えています。皆様にもおすすめします。
IBM Cloud Schematics CLIで使用するtfvarsファイルの制限が改善されました！

# はじめに

[別の記事](https://qiita.com/hirokuda/items/da699abab1968a621bf1)でも記載したのですが、IBM CloudにおけるTerraformのマネージドサービスであるSchematicsについて、CLIで操作する際、tfvarsという拡張子を持つ外部変数ファイルに対するフォーマットチェックが妙に厳密？で困っていた件がようやく解消されました。

# 確認した環境(Mac)

+ IBM Cloud CLI : 2.24.0
    + Schematicsプラグイン : 1.12.21、1.12.23

# 用意するtfvarsファイル

例えば、このようなファイルを用意します。

```Terraform:test-multi.tfvars
multiline_test = {
  "01" = {
    zone   = "jp-tok-1"
    subnet = "zone1-private"
    ipaddr = "10.0.0.xxx"
  }
  "02" = {
    zone   = "jp-tok-2"
    subnet = "zone2-private"
    ipaddr = "10.0.64.xxx"
  }
}
```

# Schematicsプラグイン更新前(1.12.21)の環境で実行

手元に入っていたSchematicsプラグインのバージョン(1.12.21)で`terraform plan`に相当するコマンドを実行すると、このようなエラーになります。key=value の形式、つまり1行で書け、というチェックが働いてしまい、実行出来ませんでした。

```
$ ibmcloud schematics plan -i <Schematics workspace ID> -vf test-multi.tfvars 
tfvars の形式が無効です。 これは key=value の形式でなければなりません
```

そのため、泣く泣く以下のような形式で記述していました。ちなみに、コメントの記載もエラーになってしまっていました。

```Terraform:test-1line.tfvars
multiline_test = { "01" = { zone = "jp-tok-1", subnet = "zone1-private", ipaddr = "10.0.0.xxx" }, "02" = { zone = "jp-tok-2", subnet = "zone2-private", ipaddr = "10.0.64.xxx" }}
```

# プラグイン更新

`ibmcloud plugin update`を実行して、Schematicsプラグインを更新します。

```
$ ibmcloud plugin update
リポジトリー 'IBM Cloud' からすべてのインストール済みプラグインのアップグレードを確認しています...

以下のプラグインは updated.
Select を選択してください (または Enter キーを押してスキップします)。
*** 中略 ＊＊＊
12. 'schematics[sch] 1.12.21' から 'schematics[sch] 1.12.23' へ
13. 上記のすべて
数値を入力してください> 12

'schematics[sch] 1.12.21' から 'schematics[sch] 1.12.23' へ更新
バイナリー・ファイルをダウンロードしようとしています...
 24.97 MiB / 24.97 MiB [=========================================================================================] 100.00% 2s
26178544 バイトがダウンロードされました
バイナリーを更新しています...
OK
プラグインは正常にアップグレードされました。
```

# 更新後に再実行

正常に実行されました！

```
$ ibmcloud schematics plan -i <Schematics workspace ID> -vf test-multi.tfvars
Initiating plan...

アクティビティー ID   9c91a*********************

OK
```

ちなみに、以前はコメントの記載もエラーになっていましたが、このようなファイルも問題なく処理出来るようになっています。

```Terraform:test-multi.tfvars
# コメント
multiline_test = {
  "01" = {
    zone   = "jp-tok-1"      # コメント
    subnet = "zone1-private"
    ipaddr = "10.0.0.xxx"
  }
  "02" = {
    zone   = "jp-tok-2"
    subnet = "zone2-private"
    ipaddr = "10.0.64.xxx"
  }
}
```

この妙な制約のせいで、実運用への適用を躊躇していた感もあるのですが、これで安心してtfvarsファイルを用いたScheamticeによるIaC運用を考えることが出来そうです。
prefix付きの commit を簡単行うシェルスクリプト

# 番号選んでタイトル入れて本文入れたら完成！

```zsh
function com() {
  local prefixes=(
    "fix: 既存の機能の問題を修正する場合に使用します。"
    "hotfix: 緊急の変更を追加する場合に使用します。"
    "add: 新しいファイルや機能を追加する場合に使用します。"
    "feat: 新しい機能やファイルを追加する場合に使用します。"
    "update: 既存の機能に問題がないが、修正を加えたい場合に使用します。"
    "change: 仕様変更により、既存の機能に修正を加えた場合に使用します。"
    "clean/refactor: コードを修正し、改善する場合に使用します。"
    "improve: コードの改善をする場合に使用します。"
    "disable: 機能を一時的に無効にする場合に使用します。"
    "remove/delete: ファイルを削除する場合や、機能を削除する場合に使用します。"
    "rename: ファイル名を変更する場合に使用します。"
    "move: ファイルを移動する場合に使用します。"
    "upgrade: バージョンをアップグレードする場合に使用します。"
    "revert: 以前のコミットに戻す場合に使用します。"
    "docs: ドキュメントを修正する場合に使用します。"
    "style: コーディングスタイルの修正をする場合に使用します。"
    "perf: コードのパフォーマンスを改善する場合に使用します。"
    "test: テストコードを修正する場合や、テストコードを追加する場合に使用します。"
    "chore: ビルドツールやライブラリで自動生成された、その他。"
  )

  echo "コミットメッセージのプレフィックスを選択してください。"
  for i in {1..${#prefixes[@]}}; do
    echo "$i. ${prefixes[$i]}"
  done

  read "number?番号を入力してください: "
  if (( number < 1 || number > ${#prefixes[@]} )); then
    echo "無効な番号です。"
    return 1
  fi

  local selected_prefix="${prefixes[$number]}"
  local prefix=$(echo "$selected_prefix" | cut -d' ' -f1)

  read "title?コミットタイトルを入力してください: "

  echo "コミット本文を入力してください。終了するにはCtrl+Dを押してください。"
  local message_body=""
  while IFS= read -r line; do
    message_body+="${line}\n"
  done

  local commit_message="${prefix} ${title}\n\n${message_body}"
  git commit -m "$(echo -e "${commit_message}")"
}

```



## おまけ： 過去の commit に現状の変更を加える

```zsh
function git-fixup() {
  git log --oneline -n 10

  read "現在の変更を加えたいHashを入力: "
  git add .
  git commit --fixup=$commit_hash
  GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash ${commit_hash}^

  echo "対象のコミットに変更を加えました。"
}
```
ReflexをPWA化する

## はじめに
最近PythonのみでWebアプリを作るためのライブラリが増えてますね。

https://qiita.com/SFITB/items/c3361979b86f441993ff

普段Streamlitを利用しているのですが、今回はReflexを使って作ったアプリをPWA化する方法を[教えてもらった](https://github.com/orgs/reflex-dev/discussions/3553#discussioncomment-9866417)ので共有します。

## やり方
### １．assetsディレクトリに以下のファイルを格納する。

- manifest.json
- service-worker.js
- 各サイズのアイコン

※以下のサイトで```manifest.json```の生成とアイコン画像の変換ができて便利です。

https://app-manifest.firebaseapp.com/


<details>
  <summary>補足</summary>
  
```reflex init```コマンドを実行すると```assets```というディレクトリができていると思います。これはNext.js用のディレクトリである```.web```の中の```public```にコピーされるようです。

</details>

```json: manifest.json
{
    "name": "My PWA",
    "short_name": "PWA",
    "start_url": ".",
    "display": "standalone",
    "background_color": "#ffffff",
    "theme_color": "#ffffff",
    "description": "My awesome Progressive Web App!",
    "icons": [
        {
            "src": "icon-192x192.png",
            "type": "image/png",
            "sizes": "192x192"
        },
        {
            "src": "icon-512x512.png",
            "type": "image/png",
            "sizes": "512x512"
        }
    ]
}
```

``` javascript:service-worker.js
self.addEventListener('install', event => {
    event.waitUntil(
        caches.open('static-cache-v1').then(cache => {
            return cache.addAll([
                '/',
                '/manifest.json',
                '/icon-192x192.png',
                '/icon-512x512.png'
                // キャッシュが必要なものを追記してください
            ]);
        })
    );
});

self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request).then(response => {
            return response || fetch(event.request);
        })
    );
});

```


### ２．rx.Appのhead_componentsを指定する。

```python:app.py
app = rx.App(
    head_components=[
        rx.el.link(rel="manifest", href="/manifest.json"),
        rx.script("""
if ('serviceWorker' in navigator) {
    window.addEventListener('load', () => {
        navigator.serviceWorker.register('/service-worker.js')
        .then(registration => {
            console.log('ServiceWorker registration successful with scope: ', registration.scope);
        }, error => {
            console.log('ServiceWorker registration failed: ', error);
        });
    });
}
"""),
    ]
```

## おわりに
Reflexはフロントエンド(Next.js)とバックエンド(FastAPI)が完全に分かれて管理しているのでこういった拡張も行いやすそうですね。


※最初headにmanifest.jsonをlinkする方法がわからず、無理やりJavaspriptで追加していたのですが、[DiscussionのQA](https://github.com/orgs/reflex-dev/discussions/3553#discussioncomment-9866417)で質問してみたらものの数分でメンテナーの方が回答してくれました。活発に開発も行われているようなので今後の発展に期待です！
Amazon Linux 2にOpenSSL 1.1.1以上をインストールする

# 概要
- Amazon Linux 2では、デフォルトのリポジトリではOpenSSL 1.0.2kが最新バージョンとなっています。OpenSSL 1.1.1以上をインストールするには、追加の手順が必要です。

# インストール方法
- 以下の手順でOpenSSL 1.1.1をインストールできます

```sh
# 必要なパッケージをインストール
sudo yum install -y perl-core zlib-devel gcc

# OpenSSLをダウンロード
curl -O https://www.openssl.org/source/openssl-1.1.1l.tar.gz

# tarファイルを解凍
tar -zxf openssl-1.1.1l.tar.gz

# ディレクトリに移動
cd openssl-1.1.1l

# コンフィギュレーション
./config

# コンパイルとインストール
make
sudo make install

# OpenSSLのバージョンを確認
which openssl

/usr/local/bin/openssl version
```

- これでOpenSSL 1.1.1がインストールされます。ただし、この手順は手動でのインストールですので、適切なバージョン管理とセキュリティアップデートの適用を自身で行う必要があります


# versionコマンドでエラーが出る場合
- `openssl --version` で、libssl.so.1.1のエラーが出る場合は、共有ライブラリの指定を追加します

```
export LDFLAGS="-L/usr/local/lib64"
export CFLAGS="-I/usr/local/include"
```


```
$ openssl --version
openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory
$ find /usr -name "libssl.so.1.1"
find: ‘/usr/libexec/initscripts/legacy-actions/auditd’: Permission denied
/usr/local/lib64/libssl.so.1.1
$ sudo su -
# echo "/usr/local/lib64/" > /etc/ld.so.conf.d/lib64.conf
# ldconfig
# exit
logout
$ which openssl
/usr/local/bin/openssl
$ openssl version
OpenSSL 1.1.1l  24 Aug 2021
 ```
PythonでTelloドローンを操作する

## はじめに

Telloドローンは、その手軽さと高度な機能から、多くのドローン愛好者や開発者に人気です。本記事では、Pythonを使ってTelloドローンを操作する方法について説明します。今回は、ライブラリを極力使わずに、UDPソケットを用いて直接Telloにコマンドを送信するシンプルな方法を紹介します。

## 必要なもの

- Telloドローン
- Python 3.x
- Wi-Fi接続できるPC

## Tello SDKの基本

Telloドローンは、SDK（Software Development Kit）を通じてコマンドを受け取ります。これらのコマンドは、UDPプロトコルを使用して送信されます。以下は、基本的なコマンドの例です：

- `command`：SDKモードを開始
- `takeoff`：離陸
- `land`：着陸
- `forward x`：前進（xはセンチメートル）
- `back x`：後退（xはセンチメートル）
- `cw x`：時計回りに旋回（xは度）

## サンプルコード

https://github.com/yhotta240/tello-python/tree/main


### 1. ソケットの作成

まず、UDPソケットを作成します。このソケットは、Telloドローンにコマンドを送信するために使用されます。

```python
import socket

# TelloのIPアドレスとポート
TELLO_IP = '192.168.10.1'
TELLO_PORT = 8889

# コマンドを送信するためのソケットを作成
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
tello_address = (TELLO_IP, TELLO_PORT)
```

### 2. コマンド送信

次に、Telloドローンにコマンドを送信するための関数を定義します。

```python
def send_command(command):
    """
    Telloにコマンドを送信する関数
    """
    try:
        sock.sendto(command.encode('utf-8'), tello_address)
        print(f"Sending command: {command}")
    except Exception as e:
        print(f"Error sending command: {e}")
```

### 3. レスポンス受信

Telloドローンからのレスポンスを受信するための関数も定義します。

```python
def receive_response():
    """
    Telloからのレスポンスを受信する関数
    """
    try:
        response, _ = sock.recvfrom(1024)
        print(f"Received response: {response.decode('utf-8')}")
    except Exception as e:
        print(f"Error receiving response: {e}")
```

### 4. メイン関数の定義

最後に、ドローンの基本的な操作（離陸、前進、後退、旋回、着陸）を行うメイン関数を定義します。

```python
def main():
    # コマンドモードを開始
    send_command("command")
    time.sleep(2)
    receive_response()

    # 離陸
    send_command("takeoff")
    time.sleep(5)
    receive_response()

    # 前進（100cm）
    send_command("forward 100")
    time.sleep(5)
    receive_response()

    # 後進（100cm）
    send_command("back 100")
    time.sleep(5)
    receive_response()

    # 旋回（時計回りに90度）
    send_command("cw 90")
    time.sleep(5)
    receive_response()

    # 着陸
    send_command("land")
    time.sleep(5)
    receive_response()

    # ソケットを閉じる
    sock.close()

if __name__ == "__main__":
    main()
```

## 実行手順

1. Telloドローンの電源を入れ、Wi-Fiに接続します。
2. 上記のPythonコードを実行します。

このサンプルコードでは、Telloドローンが離陸し、前進、後退、旋回、そして着陸する一連の動作を行います。各コマンドの後にレスポンスを受信しているため、コマンドが正常に送信されたかどうかを確認できます。

## まとめ

今回は、Pythonを使用してTelloドローンを操作するシンプルな方法を紹介しました。ライブラリを使用せずに直接コマンドを送信することで、Telloドローンの基本的な操作を理解することができます。この方法を基に、さらに高度な操作や自動化を実装することも可能です。ぜひ試してみてください。

## 参考

Tello SDK 2.0 User Guide

https://dl-cdn.ryzerobotics.com/downloads/Tello/Tello%20SDK%202.0%20User%20Guide.pdf
M5のタイマーカメラで取った画像をGoogleDriveに保存する


# 使ったもの
* M5Stack Basic
    * Core2ではなくCore使ってます
* M5Go Bottom
* Timer Camera F
* UIFlow 1.0
* Google Drive
* Apps Script

# タイマーカメラをUiflow使えるようにする
今回はこれを使います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/d5b4a725-89b4-588a-c765-409bf47a3e91.png)

# UIFlow
ユニットでTimerCamを追加します（右のやつ）
※これなぜかCore2だと使えない。。。（理由はわかりません）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/eb2aab4a-e713-2e3f-ccc1-2ea0ebb9b434.png)

Setupはこんな感じでカメラの設定をやって６０秒ごとに実行されるタイマーを用意します。
タイマーカラメラの撮影間隔は別で設定することになっていますので、撮影のタイミングとタイマー関数が呼ばれるタイミングには差があるのでそこだけ注意が必要です。（UIFlowの画面だとタイマーカメラのアップロード間隔は最短５秒のようですが、今回使用するタイマーカメラは３０秒が最短のサイクルのようです）
変数urlは画像が保管されている場所のトークン付きのURLです。これをAppsScriptに送ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/5723d8a3-8ae6-ce95-9167-cfb3e5378256.png)

タイマー関数の中身でHTTPリクエストを呼び出して、AppsScriptsを起動します。
要求本文にurlをセットして送ります。
たまにトークンが取れなくなる事があるため、タイマー関数を実行するたびに念の為取得するようにしています
![Screenshot 2024-06-25 12.29.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/0c8a4094-4812-3086-c675-aa8201932f7d.png)

# AppsScriptを実装する
HTTPトリガーで動く関数を作る。
パラメータで受け取ったURLを使って画像ファイルにアクセスし、GoogleDriveに保存するようにします。
```javascript
function doPost(e) {
  try {
    // リクエストのボディをJSONとして解析
    var requestBody = JSON.parse(e.postData.contents);
    var imageUrl = requestBody.url;

    // 画像を取得
    var response = UrlFetchApp.fetch(imageUrl);
    var imageBlob = response.getBlob();

    // タイムスタンプを取得
    var timestamp = new Date().getTime();
    var filename = `${timestamp}.jpg`;

    // Google Driveに画像を保存
    var folder = DriveApp.getFolderById('your Folder ID'); // 保存先フォルダのIDを指定
    var file = folder.createFile(imageBlob.setName(filename));

    return ContentService.createTextOutput(`File uploaded: ${file.getUrl()}`);
  } catch (error) {
    return ContentService.createTextOutput(`Error: ${error.message}`);
  }
}
```

# 実行する
GoogleDriveのフォルダに１分間に１枚画像が保存されていくようになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/f2e2a010-e7ec-e4bc-08e1-e0a1de083b12.png)

# 補足
画質はこのレベルです。
https://camera.m5stack.com/timer-cam/image?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/57562734-8728-c179-a3ed-313810805d30.png)

タイマーカメラはこんな感じで子供が持ってたレゴの部品使って適当に固定しました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/41869b1e-8bac-6a86-2c8c-4b0a5ad5c1bc.png)
アプリケーション開発に「注力」する、超簡単な方法。

本記事はQmonus Value Streamの投稿キャンペーン記事です。

<br>

結論：アプリケーション開発に注力するための方法は、それ以外をしないことです。つまり、<font color="red">**アプリケーション開発のみ**</font>をすることです。ちなみに大真面目です。

<br>

**■この記事の内容**
- 「スマホがそこにあるだけ」で、無意識のうちに脳のパワーが消費されて仕事のパフォーマンスが落ちてしまうことが分かっています。
- Windows95 の基礎をつくった天才プログラマー 中島聡 氏も「メールへの即レス」「マルチタスク」は不要だと言っています。
- 我々は、メールやチャットによって集中力が切れます。さらに、それらを気にするだけでも脳のリソースを使っているのです。
- そういう理由で、「アプリケーション開発に注力する方法は、アプリケーション開発しかしないこと」です。

# スマホがそこにあるだけで…
「スマートフォンがそこにあるだけ」で人間の脳の処理能力が消費され、仕事や勉強のパフォーマンスを低下させる影響があることが明らかになってきています。

出典：The University of Chicago Press Journals. “Brain Drain: The Mere Presence of One’s Own Smartphone Reduces Available Cognitive Capacity”(2017/04/03) - 
https://www.journals.uchicago.edu/doi/full/10.1086/691462

<br>

上記URLは、数人の参加者に”注意力”をはかる課題をあたえ、スマートフォンの位置によって脳の認知能力がどのように影響されるかを調査した研究です。

調査方法として、参加者のスマートフォンを次の4パターンの位置に置き、注意力の違いを確認しました。

①スマートフォンを 机の上に置く
②スマートフォンを ポケットに入れる。
③スマートフォンを バッグに入れる。
④スマートフォンを 隣の部屋に置く。

<br>

その結果、④隣の部屋に置いたグループが最も良い結果を示し、①机の上に置いたグループが最も悪い結果を出しました。また、②ポケットや③バッグに入れたグループは隣の部屋に置いたグループよりも少し悪い結果でした。

このことから、研究チームは「”注意力”が散漫になってしまった原因」は、スマートフォンに通知が届いたからではなく、スマートフォンがただそこにあることだと考えます。

最終的に、これを『ブレイン・ドレイン』（脳資源の流出）と呼び、「自分の近辺にスマートフォンがあるほど意識がそちらに引っ張られ、無意識のうちに脳のリソースは消費されてしまう。」と結論付けました。

<br>

–

<br>

この実験ではスマートフォンでしたが、我々エンジニアがPCをひらいたときに発動するもので、リソースを奪っていくものがあるかもしれません。

そう、例えば「メールアプリ」や「チャットアプリ」です。

<br>

# あなたの仕事はメールを早く返すことではない
つい先日、Windouw95の基礎を作った天才プログラマー 中島聡 氏の著書『なぜ、あなたの仕事は終わらないのか』を読み、特に「スタートダッシュ」が大事だということを認識しました。

本当ならこの本について１記事分語りたいところですが、この記事では、本のおびにも書いてある「2：8の法則」という時間術の話をします。
 
「2：8の法則」を簡単に説明すると…

①10日かかる仕事を振られたら「2日ください」と言う。
②その2日間で8割完成したプロトタイプを作る。
③それができなければ10日というスケジュールを見直す。

というもので、つまりは「10日でやるタスクは、最初の2日間で8割終わらせるべき」という考え方です。

<br>

–

<br>

筆者はその2日間は───スタートダッシュの期間は───飲みの誘いはもちろん、メールも電話も対応せず、できるかぎり会議も避けるといいます。仕事以外のことは何もせず、ほかのことにリソースを使いません。マルチタスクで集中力を分散するより、とにかく今のタスクに集中するのです。

> メールの返信が早くてもメインの仕事が遅い人の評価は高くありません。単に仕事が遅い人だなあという印象を持たれます。逆にメールの返信が遅くてもメインの仕事が早い人の評価は高いです。仕事ができるのだから、多少メールの返信が遅くても気になりません。

<br>

この記事のテーマとなっている「注力」がどれほどのことを意味するのか分かりませんが、これくらい徹底していれば、十分に注力していると言えるのではないでしょうか。

<br>

# 結論
つまり、アプリケーション開発に注力する方法は、こうです。

メールアプリよ…
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758664/2b335d38-5ef4-c67c-cb54-cb24c8a6d6d2.png" width="500">

さらば！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758664/6f71e6b8-0125-b862-3b6e-f466dd3ec2ed.png" width="500">

<br>

まぁ、スマートフォンの例に従うなら、本当は、アプリをアンインストールしなければならないのですが、実際それはできないのでよいです。

この記事で言いたいことは、「開発できる環境を整えないと注力はできない」というあたりまえのことと…「集中するぞー！」という人の意思はそんなに強くないということなのですから。

<br>

以上です。
padding すると要素がはみ出る【HTML・CSS】

# はじめに
　親要素に子要素をきれいにかぶせたいのに、子要素が親要素をはみ出てしまうといった経験はありませんか。
　私は、画面を作っている最中に出合い、「 違う君はここに収まってほしいの！ 」と思いました。
 　ということで、自分のためにも解決方法を記録しておきたいと思います。

# 便利拡張機能の紹介
　HTMLの各タグの要素がどこに位置しているのかワンクリックで可視化できる拡張機能があります。 それが、[IT大学](https://chromewebstore.google.com/detail/ui-build-assistant/clbhieamajlakjobcoiheklaoldcjhjf?hl=ja&utm_source=ext_sidebar) という拡張機能です。ぜひご活用ください。

#### 利用前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657056/a2eeeb57-45e9-b484-7607-d3317c1369b8.png)


#### 利用後

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657056/ae25f2be-afdf-d30b-bc96-8e43f5b7c8ae.png)

拡張機能を利用後も、大手サイトのサイトは見苦しくない気がしています。

# 本題
　今回、私は親要素（手紙の紙）に子要素（記入欄）をかぶせた画面を作成していました。padding を使用すると次の画像のようになんかずれるという事象に遭遇しました。
 
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657056/bc87b434-81cd-c3db-822c-6084897e6ba0.png)

若干タイトルが中央から右にずれていることがわかりますか？
拡張機能で要素の状態を確認したところ次のようになっていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657056/87eff6c1-c083-4d2d-9ff7-a677056a704c.png)

なんだかいらない要素っぽいのが手前にいる気がしますが、今回はおいておきます。
手紙のところに注目していただいきますと、きれいに padding 分右にずれていることがわかります。

今回の解決方法を端的に記述します。
下記の記述のcssを親要素に追加することで改善されました。

```ruby:sample.css
.letter_content {
    box-sizing: border-box;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657056/cef0bf92-bb21-03f3-a91b-d3a38c44884b.png)

要素がきれいに収まるととても気持ちが良いですね。
今後も試行錯誤しながらより良い画面を作っていきたいものです。

# 参考文献

https://www.sejuku.net/blog/58030#index_id3
【C♯】OpenCV で画像がピンボケしているか判定してみる。

今回は画像がピンボケしているか
判定してみようと思います。

申し訳ありませんが
判定は甘いかもしれません。

対戦よろしくお願いします。

***

使用するアルゴリズム

今回使用するアルゴリズムは
「情報量が少ない画像はピンボケしていると判定する」
というものです。

ピンボケしていると
画像の境界線がくっきりしないため
情報量が少なくなるだろうという発想です。

このアルゴリズムは
OpenCV を使用します。

Canny で画像にエッジ検出を行い
FindContoursAsArray で各エッジを取得して
各エッジの Point の数を合計したものが
700 より小さければ
ピンボケしていると判定しています。
ソースコードは下記の通りです。

```Csharp:ピンボケを判定するコード
public static bool isBadImage(string filePath)
{
    using (Mat mat = new Mat(filePath))
    {
        using (Mat Edge_Canny = new Mat())
        {
            Cv2.Canny(mat, Edge_Canny, 10, 410, 3);

            int total = 0;
            foreach (var one in Cv2.FindContoursAsArray(Edge_Canny, RetrievalModes.External, ContourApproximationModes.ApproxSimple))
            {
                total += one.Length;
            }

            return total < 700; //この 700 の数値を下げると判定が厳しくなります。
        }
    }
}
```

***

以上ピンボケ画像を判定してみました。

このコードを使用すれば
「ピンボケしている写真を特定のフォルダに入れる」
といったアプリが作成できるかもしれません。

ピンボケしている写真を
特定のフォルダに入れるアプリは
便利だと思う割に少ないように感じますので
狙い目ではないでしょうか？

ピンボケ画像の判定について Google 検索してみると
Python の記事や、昔の記事がヒットします。

いざ入力してみると
エラーが出て動かず苦戦したため
エラーを全て潰した内容を公開することにしました。

この記事を見て
同じ苦戦をしなくて済んだ人が現れたならば
これ以上嬉しいことはありません。

皆さんの開発の助けになれますように
閲覧ありがとうございました。
〜エンジニアが作る開発研修〜24卒開発研修〜

# 最初に
こんにちは、HRBrain人事本部で新卒エンジニア採用を担当している[pandakano](https://qiita.com/pandakano)です。

この記事は[Qiita Engineer Festa2024の記事](https://qiita.com/official-campaigns/engineer-festa/2024)となります。

この記事では、今年2024年4月にエンジニア主催で行った新卒開発研修についてご紹介しております。今回の新卒研修は弊社のプロのエンジニアが新卒に知っていてほしいことを中心に研修を行いました。

#### 【こんな人におすすめ】
- 新卒エンジニア研修を考えている方
- プログラミング学習をしている学生
- エンジニアとしてのキャリアを始めたての方
- 新卒エンジニアのチューター・メンターになった方
- エンジニア組織のマネジメントをされている方
# 研修の概要
今年度の新卒研修のテーマは「HRBrainでプロのエンジニアとしていち早く成長するための基礎を作る」です。
「プロ」のエンジニアとは何か、開発を行う上での基礎をプロのエンジニア社員から講義やワークを通じて学び、活躍するための基盤を築きます。
#### 研修後目指したい状態一覧
- プロの開発者としての心構え・スタンス・スタイルを理解している
- HRBrainというサービスの全体像を把握している
- HRBrain特有のナレッジを調べられる
- 開発の流れをだいたい理解している
- 開発組織の体制・役割を理解している
- 開発に最低限必要なツールの使い方を理解している
- 設計・実装に関する超基礎的な知識を有する
- プロの開発者として必要最低限のポータブルスキルを理解している
- tiltなどlocalで開発する環境が準備できている
- 障害・インシデント発生時のエスカレーション先や対応の流れを理解している
- HR領域の必要最低限のドメイン知識を有している
## 研修全体の流れ
１日目　HRBrainというサービスや開発組織のことを知る研修
２日目　実際に開発作業をアサインされる前に最低限知っておいてほしいことを知る研修

## 各研修の内容
#### 1日目
##### プロの開発者としての心構え
これまで、内定者アルバイトや長期インターンで就業していた24卒が社会人の「プロ」のエンジニアになるための講義を行いました。
ソフトウェアエンジニアとして働き始める上で大事な5+αを初め、学生→社会人の変化点で重要なものをピックアップして講義しました。

##### サービスの全体像・開発組織の紹介
HRBrainのサービスや開発組織についての講義を行いました。
ここでは新規プロダクトを含めたHRBrainのプロダクトを広く学び、より理解を深めました。
![IMG_7822.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3819091/93e11955-f0fc-cf3c-266b-d8cad45f73e6.jpeg)
##### 開発の流れ - 全体像
プロダクト開発の流れについて講義を行いました。

【プロダクト開発の流れ一覧】
1. ロードマップ作成
2. 要件定義
3. 画面設計
4. 仕様策定
5. 実装
6. QA
7. リリース

弊社の各職種の方がどの工程に携わっているのか、どういう形で開発を行っているのかを学びました。

##### 職種紹介 - PdM, デザイナー、BE, FE、QA, リリース
弊社プロダクト側の職種が実際にどのような業務について講義を行いました。
途中ハンズオンの学習を取り入れ、エンジニア以外の職種体験も行いました。
![2CC7F9A2-6D89-4126-834B-31E3C5B53BC5_1_105_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3819091/865ed5df-350d-7472-8370-91c020e7a850.jpeg)

#### 2日目※一部抜粋
##### プロジェクトマネージメント
タスクを完遂させるために必要なことやQCDS（品質、コスト、納期、安全性）についての講義を行いました。この講義では、実際の当社のテックリードがどのようにプロジェクトマネジメントを行っているかを学び、計画を見積もることとそれを実行することの難しさを学びました。

##### 問合せ対応
HRBrainで一番力を入れている顧客へのサポート業務が実際どのように行われているかを講義しました。この講義では、過去の問い合わせを例に挙げながら、お客様との対話の仕方や適切な対応方法を学びました。
![IMG_0404.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3819091/3e98adcb-5a56-0f85-703b-a9103402b6df.jpeg)

##### 良いPRとは
コードレビューとPull Request（PR）に関する基本的な事項と、PRを行う際の注意点についての講義を行いました。プロのエンジニアが日々どのような点に注意しながらPRを行っているのかを学びました。

##### インシデント対応
インシデントが発生した際の対応や、被害を最小限に抑えるため行うべきことを学びました。
## 新卒からの声
- 「HRBrainのプロダクトの知らなかった部分や、開発フロー、それぞれ意識すべきことなど幅広く知ることができました。」
- 「HRBrainで活躍している人が、話してくれてとても参考になった。」
- 「エンジニアとして、開発に手を上げるだけでなく、チーム内外にどのように振る舞っていくべきなのかを学ぶことが出来た。」
- 「開発チームに加わる際の最低限として色々なことが学べました。」
# 最後に
研修には多くのエンジニアが協力してくださいました。積極的に手を挙げて研修に参加してくださることは、弊社の魅力の一つです。社員一人ひとりが新卒を歓迎し成長させたいと思ってくださっているからこそだと思います。
改めて、ご協力いただいたみなさん、ありがとうございました。
HRBrainではそんな素敵な人と一緒に働く仲間を募集しております！

https://www.hrbrain.co.jp/recruit
AI-900とAI-102試験に同日に合格した体験記

# はじめに

こんにちは。今日は、MicrosoftのAI-900とAI-102試験に同日に合格した経験をシェアしたいと思います。結果は非常に満足のいくもので、AI-900では914点、AI-102では888点を取得しました。これらの試験の満点は1000点で、合格ラインは700点です。

# AI-900とAI-102試験について

## AI-900: Microsoft Azure AI Fundamentals

AI-900は、AIの基本概念とMicrosoft AzureのAIサービスについての知識を評価する入門的な試験です。AIの基本原理や機械学習、Azure上のAIサービスの利用方法を学ぶことができます。

## AI-102: Designing and Implementing an Azure AI Solution

AI-102は、より高度な内容を含む試験で、Azure上でAIソリューションを設計し、実装する能力を評価します。この試験では、実際のビジネスシナリオに基づいたAIソリューションの構築方法を学びます。

## 学習の目的

私がこの2つの試験を受けることにしたのは、AIの働き方を理解し、実際の業務にどのように応用できるかを学びたかったからです。AI技術は急速に発展しており、その知識とスキルを身につけることは今後のキャリアにおいて大きな武器になると考えました。

# なぜ同日にAI-900とAI-102を受験したのか

この挑戦を決めた理由は、無料試験券の有効期限が6月24日までだったことと、友人から追加で試験券をもらったことがきっかけです。そのため、1日で2つの試験を受けるというチャレンジをすることにしました。

# 学習時間とスケジュール

試験は月曜日の午後に予定しており、学習は木曜日の夜から始めました。月曜日の午前までに合計で24時間の純粋な学習時間を確保しました。非常にタイトなスケジュールでしたが、計画的に進めることで効率的に学習できました。

# 学習方法

## 学習の進め方

AI-900はAIの基本知識を問われる試験であり、AI-102はその知識を基にした実践的な内容が含まれています。そこで、AI-900の章を学んだ後に対応するAI-102の章を学ぶという方法を取りました。このアプローチにより、基本を理解しながら実践に活かすことができ、効率的に学習を進めることができました。

## 学習材料

時間が限られていたため、以下の学習材料を利用しました：
- Microsoft公式のLearning Path
- 公式模擬試験
- Exam Topicsウェブサイトでの問題演習

公式のLearning Pathは非常に有用で、試験範囲を網羅的に学ぶことができました。模擬試験は自分の理解度を確認するために役立ちました。Exam Topicsサイトでは、過去の試験問題を通じて実践的な学習ができました。

# 試験時の注意点

## AI-900

AI-900では44問が出題されました。試験中は、まず迅速に解答し、わからない問題はマークして後で見直すようにしました。この方法で、全体的にスムーズに進めることができました。

## AI-102

AI-102では49問が出題されました。こちらも同様に迅速に解答し、わからない問題はマークしました。特にAI-102では、Microsoft Learningを参照してドキュメントを確認できるため、事前にドキュメント内容をよく理解しておくことが重要です。試験中にドキュメントを検索する時間を短縮できるからです。

# 結果と感想

試験結果を見たときの喜びは言葉にできません。同日に2つの試験に合格することができたのは、計画的な学習と効率的な時間管理のおかげです。この経験を通じて、自分の限界を超えることができたと感じています。これからもAIの知識を深めるために、引き続き勉強を続けていきます。
VSCodeで「型'rdbg'のデバッグアダプタを見つけることが出来ません」のエラーが出る

VSCodeのデバッグをやった。 「Ctrl+Shift+P」で開発者ログを見る。

- 下記のようなエラーメッセージが出ていた

```
Remote Extension host terminated unexpectedly 3 times within the last 5 minutes.
```

エラーメッセージで検索していると原因発見した、docker-desktopが原因。docker-desktopの設定変更が必要だった。

- https://github.com/microsoft/vscode/issues/195906
- https://github.com/microsoft/vscode-remote-release/issues/9500#issuecomment-1927176903

docker-desktopの設定で「gRPC FUSE」に切り替えて「仮想化フレームワーク」を無効にした。
【Swift】Strict Concurrency Checking の設定

あらかじめ、様子を見ておきながらのほうがいいですよね。

Swift6 での話だとしても。

```
.xcodeproj

  ↓

TARGETS 選択

  ↓

Build Settings

  ↓

```

ここで検索入力欄を使ったほうが早い。

![sc 2024-06-25 at 12.01.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588914/80386881-a2c3-7572-03ee-e5bd351108f3.png)

自分の非同期処理に関する記述がどんだけクソなのか良く分かるし、だけに深い理解にもつながるし。

https://android.benigumo.com/20231211/modelactor/

https://qiita.com/chanzmao/items/551dd4244a55ecb04a73
Longhorn環境でaccessMode:ReadWriteManyを使いたい場合

# 症状
AWS EC2上に構築したK3sに[Dify](https://dify.ai/jp)を導入しようとしたときに問題が出ました。なお、
[BorisPolonsky / dify-helm](https://github.com/BorisPolonsky/dify-helm)
のhelmファイルを使用させていただきました。
k3sに[Longhorn](https://longhorn.io/)を組み合わせましたので、helmのvalue.yamlファイルに「PVCのstorageClassはlonghornを指定するよ」と設定しました。
```yaml:value.yamlの一部
proxy:
    log:
        persistence:
            persistentVolumeClaim:
                storageClass: longhorn
                accessModes: ReadWriteMany
                size: 1Gi
                subPath: ""
```
これを、storageClassが出てくるところ全てに記しました。
なので
```
helm repo add dify https://borispolonsky.github.io/dify-helm
helm repo update
helm install -n dify -f value.yaml dify dify/dify
```
をやってみて上手く行くかと思いきや、[k9s](https://k9scli.io/)で見てみるとproxyとapiのpodがcontainerCreatingのまま動いてないわけです。どうしたものか。

# 調査
value.yamlをよく見るとこんなことが書いてあります。
```
## Dify App Data Persistent Volume Storage Class
## If defined, storageClassName: <storageClass>
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
##   set, choosing the default provisioner.
## ReadWriteMany access mode required for `api` and `worker`
##
```
apiとworkerにはReadWriteManyのアクセスモードが必要だよ、と書いてあります(workerじゃなくてproxyの間違いじゃないかと思いますが)。これがヒントになりました。Google検索してみると、
[LonghornでReadWriteManyを使用する方法](https://qiita.com/yoshi_mf7/items/024e1079582c00ec6fa9)
という記事が見つかりました。

# 解決
次の手順で解決をみました。k3sがインストールされている各ノードで以下の手順を踏む必要があります。
1.念のため、k3sサービスを止める。
サーバーノード:`sudo systemctl stop k3s`
エージェントノード：`sudo systemctl stop k3s-agent`

2.nfs-commonをaptで導入。
```
sudo apt update
sudo apt install nfs-common
```
3.k3sサービスを再スタート。
サーバーノード:`sudo systemctl start k3s`
エージェントノード：`sudo systemctl start k3s-agent`

以上で、difyが動くようになりました。
Alfred Workflowを使ってNotionにメモを追加し作成したメモを開く方法

# はじめに

Notionは便利なのですが、さっとメモを取りたい時にアプリが起動していないと実際のメモ作成までにかかる時間が結構かかる点が不満でした。

今回はAlfredのWorkflowを使ってNotionのデータベースに新しいメモを追加し、そのメモをNotionアプリで開く方法を紹介します。

# 前提条件

- Alfredがインストールされていて、Powerpackを購入してあること(Workflowを使う)
- Notionアカウントを持っていること
- `jq`コマンドがインストールされていること（Homebrewを使用してインストール可能）

```bash
brew install jq
```

# 手順
## Notion APIトークンとデータベースIDの取得
### APIトークン
Notionの[インテグレーションページ](https://www.notion.so/my-integrations)にアクセスし、名前はAlfred Memo Adderとでもして新しいインテグレーションを作成します。インテグレーションのAPIトークンをコピーします。

### データベースID
Notionのデータベースに移動し、URLからデータベースIDを取得します。データベースURL`https://www.notion.so/workspace_name/XXXXXXX?v=ZZZZZZZZZZZ`のXXXXXXXの部分です。あとで使うのでどこかに保存しておいてください。

## Alfred Workflowの作成
Alfredのアイコンをクリックし、Preferencesを開き、Workflowsタブに移動。
1. 新しいワークフローを作成：
左下の「+」ボタンをクリックし、「Blank Workflow」を選択します。ワークフローに名前（例：「Notion Page Creator」）を付けます。
1. キーワードトリガーの設定
キーワードトリガーを追加：ワークフロー編集画面で、右クリックして「Inputs」 > 「Keyword」を選択します。
**Keyword**: memo with space Argument Optional
**Title**: Add new memo to Notion
**Subtext**: Enter the memo content
と設定します。ここの文章は何にしても自由です。
1. スクリプトアクションの設定
キーワードトリガーの右に、「+」ボタンをクリックし、「Actions」 > 「Run Script」を選択します。
**Language**: /bin/zsh --no-rcs with input as argv running instances Sequentially
として以下のスクリプトを入力します。APIトークンとデータベースIDを適切な値に置き換えてください。
コードをコピーする

```shell
#!/bin/bash

# Alfredの入力からメモの内容を取得。引数がない場合はデフォルトのタイトルを設定
NEW_MEMO_TITLE=${1:-Untitled}

# 必要なAPIトークンとデータベースIDを設定
API_TOKEN="your_notion_api_token"
DATABASE_ID="your_database_id"

# APIリクエストを実行して新しいページを作成
RESPONSE=$(curl -s -X POST "https://api.notion.com/v1/pages" \
    -H "Authorization: Bearer $API_TOKEN" \
    -H "Content-Type: application/json" \
    -H "Notion-Version: 2022-06-28" \
    -d '{
        "parent": { "database_id": "'$DATABASE_ID'" },
        "properties": {
            "Name": {
                "title": [
                    {
                        "text": {
                            "content": "'$NEW_MEMO_TITLE'"
                        }
                    }
                ]
            }
        }
    }')

# レスポンスを表示して確認
echo "API Response: $RESPONSE" >&2

# ページIDを取得
PAGE_ID=$(echo $RESPONSE | jq -r '.id' | sed 's/-//g')

# Notionアプリで開くためのURLを生成
FULL_URL="notion://www.notion.so/$PAGE_ID"

# URLを表示して確認
echo "Generated URL: $FULL_URL" >&2

# URLを出力してAlfredの次のアクションで使用
open $FULL_URL
```
## 実行方法

Alfredで「memo」と入力し、続けて新しいメモの内容を入力します。(入力しない場合はUntitledというページが生成されます。)
Bashスクリプトが実行され、新しいメモがNotionのデータベースに追加されます。
作成されたメモのURLが生成され、`open` コマンドによってNotionアプリで開かれます。
[備忘録]　IT契約関連について学んだこと

# はじめに
こんにちは，Umamusume22です．前回はフリーランスエンジニアについて分かったことを記事に書きました．
詳しくは下のURLを参照してください．(フリーランスエンジニアについて分かったことを書いた記事です)
https://qiita.com/Umamusume22/items/d157de03fe5074bfd34e
今回は請負や業務委託契約などフリーランスエンジニアで働く場合，尚更重要な契約について学んだことを書きます．

# 備忘録
https://qiita.com/tetsuya-imamura/items/d291859ee57b96d4c502

https://qiita.com/front_to_dev/items/34fc0010cca1bfd66d1c

- 業務委託契約
    - 請負契約と準委任契約をひっくるめた実務上の呼称
        - 請負契約と準委任契約がある
    - 法律上，業務委託契約は存在しない
    - 民法によると「贈与」
        - 「売買」
        - 「交換」
        - 「消費貸借」
        - 「使用貸借」
        - 「賃貸借」
        - 「雇傭」
        - 「請負」
        - 「委任」
        - 「寄託」
        - 「組合」
        - 「終身定期金」
        - 「和解」　これら13種類の契約について名前を付けている．典型契約と呼ぶ <br><br>
- 請負契約
    - 民法第632条に規定されている契約の形態
    - ソフトウェアなどを完成させたいのであれば請負契約が適切
    - - 契約内容は仕事の完成
    - 受注側から一方的に契約を打ち切ることは不可
    - 受注側は仕事を完成させなければならない
    - 要件定義が大事
    - 受注側から成果物を受けて，発注側で成果物に問題がないことを確認(検収)した後，一括払いで報酬を支払うのが基本
    - 受注側には瑕疵担保責任がある
        - 成果物を発注側に渡してから1年以内
        - 受注側に非がなくても発注側は修正，損害賠償を請求することができる
    - 発注側に指揮命令権はない
        - 業務の遂行方法や労働時間などを命令することはできない
- 偽装契約
    - 発注側は財政上および法律上全ての責任を負う必要がある
    - 自らの設備や資材を使って作業を行う
    - 指揮命令を受けない

# 準委任契約
- 民法第656条に規定されている契約の形態
- 知恵やノウハウを借りることが目的であれば準委任契約が適切
- 契約内容は業務の処理
- 業務を処理することを約する契約
    - 受注側に仕事を完成させる責任がない
    - 受注側に善管注意義務(善良なる管理者の注意をもって委任された業務を処理する義務)がある
        - 善管注意義務を怠ると債務不履行責任を問われる
    - 発注側に指揮命令権がない
    - 報酬は期間ごとに支払う
        - 受注側は毎月最終日に業務報告書を提出
    - 業務の種類とプロセスの定義が大事
    - 委任契約=準委任契約
    - 委任契約とは法律行為を委託する契約
    - 準委任契約とは法律行為以外を委託する契約<br><br>
# 労働者派遣契約
- 労働者派遣法に規定されている契約の形態
- 指揮命令権が派遣先（発注側）にある
【ChatGPT＋DALL-E3】【Dream Machine】の動画に音声をつける方法です。

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

　今回は、Dream Machineの動画に音声をつける方法です。やはり、音がないと映像としては格段に落ちますからね。たぶん、ほかの動画も可能（未確認）

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

　今日もニュースはありません。
　　いや、細かいことは
　　　ありますけどね😅

　ではさておき、
　　本題に入りましょう。

　前回の最後に書いたとおり、
　　動画に音声ファイルを
　　　追加する方法を書きます。

　動画に音や音声は付き物。
　　音がない動画は
　　　“クリープのないコーヒー”
　　　　みたいなものです（死語？）
　　　　　あっ、クリーム入れない人も
　　　　　　いますけどね😅
　　　　　　　コーヒー飲まない人も。

　とにかく、
　　映像だけでは
　　　説得力に欠けます。

　簡単な例を挙げると、
　　歌手が、歌を歌っているのに、
　　　歌が聞こえてこないようなもの。

　まぁ、そんなわけで
　　動画に音をくっつけよう、と
　　　いう話になるわけです。
***
　では、
　　その方法です。

　もちろん、
　　使うツールは、
　　　ChatGPTです。

　まずは、セッションが
　　GPT-4oであることを
　　　確認します。

　次に、
　　動画と音声ファイルを
　　　アップロード。

　下記のPromptを入力。
```Text:
MoviePyを使って、動画に音声を追加してください。なお、音声が動画よりも長い場合、動画の時間の長さまで追加してください。
```
　これで、送信。

　しばらくすると
　　ダウンロードリンクが
　　　出てきますから、
　　　　ダウンロードします。

　出来上がった動画ファイルを
　　確認してください。

　はい、終了。

　なお、
　　音声が動画よりも短い場合は、
　　　考慮していません。
　　　　ご注意ください。
***
　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
[AWS #14] EBS

<!--
 <font color="c00000"></font> 赤
-->
## はじめに
こんにちは
今回はコンピューティングサービス分野の **「EBS」** についてご紹介いたします。
:rolling_eyes:これもどこかで見たことあるようなサービスですね
:upside_down:とあるAWSの**ストレージサービス**になります。

## Amazon EBS
EBSとは **<font color="c00000">「Elastic Block Store」</font>** の略称です。
EC2インスタンスにアタッチして使用するAWSの**ストレージサービス**になります。
※Elastic → 弾力がある、伸縮性がある（用途に合わせて**柔軟な使用ができる**特徴）

:rolling_eyes:ストレージは確か **「データを保管するもの」** でしたよね
:upside_down:パソコンやスマホ、ゲーム機器などでよく耳にしたり目にしたりするかと思いますね。

:::note info
EBSは、EC2の**インスタンスのデータを保管**しておくことができるサービス
:::

:rolling_eyes:どんなサービスに対応しているのでしょうか？
:upside_down:データベースやアプリケーションなど**様々なサービスに対応可能**です。
でも主に使用されるのは **「仮想マシンサービス」であるEC2のストレージ**ですね。冒頭で少し記載した「アタッチ」と呼ばれる、EC2上の仮想マシンにEBSボリュームを割り当てることで、<font color="c00000">**仮想マシンのストレージ管理を柔軟に行うことができます。**</font>
![AWS14_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/71877d00-5e7c-903b-8333-9d89796bfc04.png)
:upside_down:ちなみに「アタッチ」は**接続する・取り付ける**などの意味があります。
余談ですがFPS関連のゲームをよくやっている人は、「アタッチメント」と書いたらなんとなくピンとくるのではないでしょうか（サプレッサー、スコープ、マガジンやストックなど…）
### EBSの可用性
:::note info
可用性とは、システムを**障害で停止させることなく稼働し続ける性能**のことです。
:::
EBSは、**99.999%の稼働率**があります。
そのため<font color="c00000">**可用性が非常に高いサービス**</font>となっております。
この稼働率はEBSの停止期間（ダウンタイム）が一年間で5~6分程度に収まる計算となります。

また稼働率だけでなく、年間故障率(AFR)も0.001%という低い水準で提供されているのもポイントになります。これは1年間に10万分の1の確率でデータが破損してしまう計算になります。

### ボリュームタイプ
AWSでは、システムの用途によって複数の「EBSボリュームタイプを提供」しています。
・「EBSの利用予算」
・「データの保存容量」
・「スループット」
などから**システムに最適なEBSを選ぶ**ことができます。
![AWS14_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/28d78ef7-edcc-b79c-7f91-4f7f522d4e4e.png)

### スナップショット
EBSはとても高い可用性を誇りますが、**万が一の場合**に備えて **「スナップショット」** というものを作成することが可能です。

スナップショットは差分のみを保存対象として容量を抑えた上で、**Amazon S3という別の安価なストレージサービスに保存されます。**

:::note info
スナップショットは簡単に言うと<font color="c00000"> **「バックアップ」** </font>のようなものです
:::
![AWS14_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/bd25b28a-7ae9-570d-ed38-f421a05f6630.png)
## EBSとS3の違い
EBSとS3の最大の違いは、ストレージの **「種類」** にあります。
Amazon S3は <font color="c00000">**「オブジェクトのストレージ」**</font>
Amazon EBSは <font color="c00000">**「ブロックのストレージ」**</font> というデータの保存方法を取っています。

:::note info
Amazon S3は<font color="c00000">**耐久性が高く**</font>**大量のデータを保存しやすい**です
:::
:::note info
Amazon EBSでは、特に<font color="c00000">**処理速度を高速化したいデータの保存**</font>に適しています
:::

## おわりに
ちょっとしたまとめになります。

:::note info
EBSとは、EC2インスタンスに**アタッチして使用する**AWSのストレージサービス
:::
:::note info
EBSは、**99.999%の稼働率**があり、**可用性が非常に高い**サービス
:::
:::note info
**システムの用途によって選べる複数のEBSボリュームタイプ**がある
:::
:::note info
万が一の場合に備えて**スナップショットを作成することが可能**
:::

可用性が99.999%と非常に高いですが、障害発生の可能性は0ではないため、システム停止が重大な損害に繋がらないように対策（スナップショットなど）をすることが重要であると分かりました。

最後までお読みいただきありがとうございました！

>>日頃より活用している参考書です。
>> **「参考書」**
[AWS認定クラウドプラクティショナー改定第3版](https://x.gd/19i6N)
>
> **「AWS公式サイト」**
[AWS EBS](https://aws.amazon.com/jp/ebs/)
>
> **「参考元」**
[Amazon EBSとは？](https://bcblog.sios.jp/what-is-amazon-ebs/#Amazon_EBS)
>
> **「Youtube」**
[【CLF-C02：AWSクラウドプラクティショナー】第18回 Amazon EBS](https://x.gd/kbJRT)
AZ-900受験体験記

## 目次
1\.AZ-900とは
2\.取り組んだ勉強
3\.結果と感想
4\.今後
5\.余談

## 1\.AZ-900とは
 Microsoft Azureの基礎。
 Microfsoft認定資格のひとつです。
 大まかな試験範囲としては
・クラウドの概念について
・Azureのアーキテクチャとサービスについて
・Azureの管理とガバナンスについて
 の3つから構成されてます。
 主に、Azureのサービスと特定のタスクに対する適切なソリューションについて出題されます。

 試験時間：45分
 問題数：40問程度(私の場合は36問)
 合格点：700点/満1000点


## 2\.取り組んだ勉強

### 1\.参考書学習
**Microsoft Azure Fundamentals 教科書**という参考書を会社から借りて、
学習を行いました。

参考書を1周読み、演習問題を3周解きました。
また、各ページの1,2か所に「試験対策」という箇所があり、
そのページの内容が要約されてあるような感じです。
そこだけ1周することを1度行いました。

![Qiita陽画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760633/c23f161a-b81d-9de8-b89b-8d9c9eecb5d9.png)


### 2\.Microsoft Learn　プラクティス評価
会社の先輩に何か学習に使えるサイトなどを尋ねたところ、
こちらを教えていただきました。

Microsoft公式の学習コンテンツで50問の演習問題に取り組め、
最後は、正答率を出してくれるものです。

![Qiita陽画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760633/6c279a8f-6bdf-5786-d992-03a162d23df5.png)

![画像 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760633/27483ae9-1228-46e8-f15f-fc3b7e90049e.png)
↑私が試験30分前に解いたものです

試験前2日ほどはこちらを重点的に取り組んでいました。
以下にリンクを添付しておきます。
https://learn.microsoft.com/ja-jp/credentials/certifications/azure-fundamentals/practice/assessment?assessment-type=practice&assessmentId=23&practice-assessment-type=certification



### 3\.【AZ-900】Microsoft Azure Fundamentals 勉強アプリ
こちらのアプリは問題数が10問or20問から選択でき、ジャンルも
「アーキテックチャとサービス」「管理とガバナンス」「クラウドの概念」
から絞ることができます。

また、間違えた問題のみに再度取り組むこともできます。

ただ、所々誤字があったり、解説の無い問題があったりする部分は少し使いづらいと感じました。

![Qiita陽画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760633/f5b82486-9e5e-58aa-ca1b-5476120583c5.png)


試験1週間前にこちらをみつけて、取り組んでいました。
以下にリンクを添付しておきます。
https://simple-was-best.com/az-900/



## 3\.結果と感想
受験した結果としては、667点で不合格でした。

受験してみて思ったことは、**いろいろな問題を解くべき**ということです。

試験1週間前までは教科書内の演習問題を繰り返し取り組んでいました。
試験3日前からはプラクティス評価を繰り返し行っていました。
その結果、プラクティス評価でやった問題しかわからないような状態で受験しました。
「教科書にあったけどなんだっけな」が何度もありました。
またプラクティス評価にも教科書内の演習問題にも出てきたことなかった問題も少なくはありませんでした。
プラクティス評価と同じ問題もあまりありませんでした。

参考書の内容をすべて覚えることに越したことはないと思いますが、
私は問題を解くことで覚えていこうという学習方法で進めていました。

そのため、**参考書には書いてあるが、あまり問題にされないワード**などには対応できません。

より多くの問題に対応できるようになるためには、
やはり、いろいろな問題を解くに尽きるかと思います。

参考書の演習問題、いくつかのサイトの問題、その他問題集など
多くの問題数をこなすことが合格につながるのではないかと感じました。

## 4\.今後
合格点に近い点数で不合格となってしまったため、
何とも悔しい気持ちが残ります。
そのため、まだ667点分の知識が頭に入っているうちに再受験しようと考えています。

再受験に向けてUdemyの問題集の購入も検討しています。

## 5\.余談
4月~7月の4か月間で資格をAZ-900＋もう一つとる計画なのですが、
まだなに一つとっていなくてピンチです(笑)

計画としては
4月~5月:2つの資格の学習
6月:AZ-900に集中
7月:AZ-900を終えてもう一つの検定に集中
というような感じだったのですが、
まあうまくいかないものですよね(笑)
努力不足でした。

7月に2つ受けて受かるか不安なところです(+_+;)

問題を解きまくる7月になりそうです。
引き続き頑張っていきます(｀・ω・´)ゞ★
[Excel LAMBDA関数]関数の引数をIS関数で判別する方法

## はじめに
LAMBDA関数の引数の種類（数値、文字列、関数）を判別し、種類ごとに処理を分けると引数を減らせるのではと思いました。あらためてIS関数を調べてみると、引数が関数であることを判別するものがありませんでした。そこで、e\いろいろなIS関数の結果を組み合わせれば判別できるのではないかと思い調べてみました。

## 調査結果と表の見方
調査した結果を表1で示します。
・B2:N2…評価するIS関数名
・A列…評価する数式
・B3:N26…IS関数の実行結果(=IFERROR(eval(B2#&"("&FILTER(A:A, A:A<>"")&")")*1, 0))
IS関数の結果を合計すめため、TRUE/FALSEを1/0に変換。例えば、セルK7は、ISERROR(1/0) の結果が入る。
・B1:N1…IS関数の結果に対する重み付け
・O列…IS関数の実行結果と重み付けをかけた合計(=BYROW(B3#,LAMBDA(a,SUM(a * B1#))))

### 表1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327504/28753d3d-e3d2-2da5-55fa-3ce1c4ef4834.png)

※IS関数の実行は、IS関数名と「( )」でくくった数式をeval関数にて実行
※eval関数はVBAのユーザー定義関数で作りました。引数をEvaluate関数に渡しています。
※IS関数の実行結果がエラーとなる場合は0として処理
## 以下注意が必要な関数
### ISNOTEXT関数
評価対象がテキスト以外はすべてON。ONの条件が多すぎて、単独では使用できないと思われる。
### ISBLANK関数
引数の参照先がブランクの場合(E10)以外に、関数の引数が省略された場合(E6,E19)もONする。
### ISLOGICAL関数
評価対象が論理値の場合(F3,F11)以外にIF関数で「,」が省略されている場合(F20,F24)もONする。
### ISNUMBER関数
評価対象が数値以外では、IF関数の引数先行評価時にON(G23,G25,G26)。
### ISEVEN関数
評価対象が偶数以外にブランクのときにもON(I10)。

## 結論：引数に関数が指定されているかどうかの判定方法は
関数は表1の18行目になります。ISNOTEXT関数のみONで、このパターンは他にないため、判別できそうです。
判別方法は、評価値をnとすると　
=(ISNOTEXT(n)=TRUE)*(ISBLANK(n)=FALSE)*(ISLODICAL(n)=FALSE)*(ISNUMBER(n)=FALSE)*(ISOMITTED(n)=FALSE)*(ISERROR(n)=FALSE)
になります。

## せっかくなので表1をLAMBDA関数にしてみました

「数式」－「名前管理」より関数登録して見てください。

_IS(n)=4　のとき関数判定です。

```_IS.


=LAMBDA(x,[f],LET(
    func, VSTACK(
        LAMBDA(n, ISTEXT(n)),
        LAMBDA(n, ISNA(n)),
        LAMBDA(n, ISERR(n)),
        LAMBDA(n, ISERROR(n)),
        LAMBDA(n, ISOMITTED(n)),
        LAMBDA(n, ISEVEN(n)),
        LAMBDA(n, ISODD(n)),
        LAMBDA(n, ISNUMBER(n)),
        LAMBDA(n, ISLOGICAL(n)),
        LAMBDA(n, ISBLANK(n)),
        LAMBDA(n, ISNONTEXT(n)),
        LAMBDA(n, ISFORMULA(n)),
        LAMBDA(n, ISREF(n))
    ),
    a, REDUCE(0, func, LAMBDA(a, f, 2 * a + IFERROR(f(x), 0))),
    b, (a),
    c, IF(ISOMITTED(f), b, f(b)),
    ret, (c),
    (ret)
))
自作Dockerfileを作るときにハマったこと

GitHub Container Registry(ghcr.io)にDockerイメージPUSHして、そのDockerイメージを参照する別のDockerイメージを作成して使用するときにハマったのでメモします。

## 状態
### ベースDockerイメージ
- `ghcr.io/username/child:latest`

```Dockefile: Dockerfile
FROM python:3.8-slim

RUN echo "foo"
```

### ベースDockerイメージを参照するDockerイメージ
- `ghcr.io/username/parent:latest`

```Dockefile: Dockerfile
FROM ghcr.io/username/child:latest

# 色々インストール
```

## 発生した問題
productionで使用するDocker
```Dockefile: Dockerfile
FROM ghcr.io/username/parent:latest

# 色々ビルド
RUN python -v
```

この状態で`Python`のバージョンを調べると`3.8`になります。
`Python`のバージョンを更新しようとして、`ghcr.io/username/child:latest`の`Dockerfile`を更新しました。

```diff_docker: Dockerfile
+ FROM python:3.9-slim

RUN echo "foo"
```


productionで使用するDockerを再度ビルドすると、`Python`のバージョンが`3.8`のままでした。

## 原因

ベースイメージを`latest`にしていても、常に最新のイメージを取得するわけではありません。
そのDockerfileがビルドされた時点での`latest`のイメージを取得します。
そのため、`ベースDockerイメージ`を更新したら、`ベースDockerイメージを参照するDockerイメージ`も再度ビルドする必要があります。
当たり前のことなのですが、初めてハマりました。

## まとめ
灯台下暗し