OmniAICreator/Qiita-1.07M huggingface dataset:
Elixir Image の記述の簡素化

## はじめに

Elixir Image について、最近機能が追加され、一部の記述が簡素化できるようになったので、いくつか紹介します

https://github.com/elixir-image/image

以前書いた記事

https://qiita.com/RyoWakabayashi/items/aa61860882b106f956ff

https://qiita.com/RyoWakabayashi/items/54e92be2e134e0fde0f5

https://qiita.com/RyoWakabayashi/items/34de2207bcf8d745a01a

https://qiita.com/RyoWakabayashi/items/ec5b065cdf74624b1ff5

## 追加された Trailing bang (末尾の `!`)

以下の２つが追加されています

- Image.from_binary! : 0.25.0 で追加
- Image.to_nx! : 0.27.0　で追加

これにより、以下のように簡略化できます

```diff_elixir
ryo_img =
  "https://www.elixirconf.eu/assets/images/ryo-wakabayashi.png"
  |> Req.get!()
  |> Map.get(:body)
- |> Image.from_binary()
- |> elem(1)
+ |> Image.from_binary!()
```

```diff_elixir
- {:ok, nx_ryo_img} =  Image.to_nx(ryo_img)
- Kino.Image.new(nx_ryo_img)
+ ryo_img
+ |> Image.to_nx!()
+ |> Kino.Image.new()
```

:ok と :error で場合わけしたい場合は `!` なしの方を使うべきですが、明示的にエラーを発生させたい場合は `!` ありの方が有用なエラーメッセージが表示されます

https://hexdocs.pm/elixir/1.15.2/naming-conventions.html#trailing-bang-foo

## Livebook の UI (Kino) からの変換の簡素化

0.27.0　で `Image.from_kino` が追加されました

これによって、 Livebook のファイル選択から Image の画像形式に変換する処理が簡素化されます

ただし、 `Kino.Input.image` の `:format` は `:rgb` である必要があります

```diff_elixir
chroma_key_img_input = Kino.Input.image("CHROMA KEY IMAGE", format: :rgb)

chroma_key_img =
  chroma_key_img_input
  |> Kino.Input.read()
- |> Map.get(:data)
- |> Image.from_binary!()
+ |> Image.from_kino!()

Image.Kino.show(chroma_key_img, max_height: 400)
```

## SVG 読込の明示化

0.32.0 で追加された `Image.from_svg` で SVG ファイルの読込が分かりやすく明示化されました

```diff_elixir
svg_img =
  "https://www.elixirconf.eu/assets/images/drops.svg"
  |> Req.get!()
  |> Map.get(:body)
- |> Image.from_binary!()
+ |> Image.from_svg!()
```

## まとめ

ちょっとした変更ですが、可読性が上がるのが嬉しいですね
mysql データベースで空の列を見つける方法

# はじめに
mysqlデータベースで、データの無いすべてのテーブルからすべてのカラムを見つけなければならない問題があります。
この問題を解決する方法はいろいろあるが、mysqlが提供するツールだけで解決した。
例えばpythonのような外部スクリプトを使えばもっと簡単に解決できるかもしれないが、システムの制約上sqlしか使えない。
良いチャレンジだ。

# 解決方法
空の列を見つけるクエリを作成する
 - すべての行を取得
 - クエリを発生
 - 生成されたクエリを1つずつ実行するプロシージャ手順を作成
 - データ表示

# クエリ作成

### すべての列を取得
mysqlですべての列はこのクエリで取得できます：
``` sql
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
```

### クエリを発生
テーブル列に空(NULL)があるかどうかを調べるには、次のようなクエリが必要です：
``` sql
SELECT 
    'table_name', 
    'column_name'
FROM 
    DUAL
WHERE 
    (
        SELECT COUNT(*) 
        FROM `table_name`
    ) = 
    (
        SELECT COUNT(*) 
        FROM `table_name` 
        WHERE `column_name` IS NULL
    )

```

これを基に、データベース内のすべてのカラムに対して同様のクエリを作成することができます。


``` sql
SELECT CONCAT(
  'SELECT \'', TABLE_NAME, 
  '\' AS table_name, \'', COLUMN_NAME, 
  '\' AS column_name FROM DUAL WHERE (SELECT COUNT(*) FROM `', 
  TABLE_SCHEMA, '`.`', TABLE_NAME, '`) = (SELECT COUNT(*) FROM `', 
  TABLE_SCHEMA, '`.`', TABLE_NAME, '` WHERE `', COLUMN_NAME, '` IS NULL)'
) AS query_to_run
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'xxxxxxxxxx'; -- スキーマ名に置き換えてください
```

ちょっと読みにくいですが、クエリ文字列を生成しました。

# 発生されたクエリを実行
小さなデータベースでも数百のカラムがあるかもしれないので、一つ一つ手作業で実行するのは非常に面倒です。

### テーブル作成
最初にデータを保存するためにテーブルを作成
``` sql
CREATE TEMPORARY TABLE Results (
  table_name VARCHAR(64),
  column_name VARCHAR(64)
);
```

### 手順を削除
最後に、すべてのクエリ結果をループして実行し、先に作成したテーブルにデータを挿入するプロシージャーが必要です。


``` sql
DELIMITER $$
CREATE PROCEDURE RunGeneratedQueries()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE query_to_run TEXT;
  DECLARE cur CURSOR FOR 
    SELECT CONCAT(
      'INSERT INTO Results SELECT \'', TABLE_NAME, 
      '\' AS table_name, \'', COLUMN_NAME, 
      '\' AS column_name FROM DUAL WHERE (SELECT COUNT(*) FROM `', 
      TABLE_SCHEMA, '`.`', TABLE_NAME, '`) = (SELECT COUNT(*) FROM `', 
      TABLE_SCHEMA, '`.`', TABLE_NAME, '` WHERE `', COLUMN_NAME, '` IS NULL)'
    ) AS query_to_run
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_SCHEMA = 'xxxxxxxxxx'; -- スキーマ名に置き換えてください
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur;

  read_loop: LOOP
    FETCH cur INTO query_to_run;
    IF done THEN
      LEAVE read_loop;
    END IF;
    SET @s = query_to_run;
    PREPARE stmt FROM @s;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
  END LOOP;

  CLOSE cur;
END$$
DELIMITER ;
```

### 結果
``` sql
select * from Results
``` 
はデータベース内のすべてのNULL列をリストアップされます。
結果が空の場合は、未使用の列がないことを意味します。

# まとめ
空欄を見つけるのは意外に難しかった。
他のデータベースにはもっと簡単な方法があるのだろう。
何か良い方法をご存知でしたら、コメント欄にお書きください。
【VSCode】任意のホットキーで名前付きファイルを作成する


## はじめに
MacのVSCodeでは`cmd + n`で新規ファイル作成ができます。
しかし、デフォルトでは以下のように無名のファイルが作成されます。

![スクリーンショット 2022-04-20 0.12.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/b9777aae-cf94-f13c-4638-cc8eeab0deee.png)


そこで、`cmd + n`で名前をつけて新規ファイル作成ができないか調べました。
結果、`keybindings.json`を編集することで設定が可能でしたので設定方法を以下に記載します。

## 設定方法

### `keybindings.json`を開く
`cmd + sft + p`でコマンドパレットを表示します。
`Preferences: Open Keyboard Shortcuts (JSON)`と入力し、`keybindings.json`を開きます。

![スクリーンショット 2022-04-20 1.03.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/f47f6f9e-7cba-2442-a769-5f6b9f956de1.png)


### `keybindings.json`に設定を書く
`keybindings.json`に以下のように記述します。

```keybindings.json
[
  {
    "key": "cmd+n",
    "command": "explorer.newFile",
  },
  {
    "key": "ctrl+n",
    "command": "explorer.newFolder",
  }
]
```

すると`cmd + n`でエクスプローラーに新規ファイルが作成されるようになります。
また、`ctrl + n`を入力すると新規フォルダを作成できるように設定しました。
実際には以下のようになります。

`cmd + n`を入力
![スクリーンショット 2022-04-20 1.16.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/b29769eb-d4f8-aa7a-1f2e-671780c6b634.png)


`ctrl + n`を入力
![スクリーンショット 2022-04-20 1.15.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/30ff3278-ecbf-776d-3b24-0f6bdb6e9d5f.png)



## `when`を追加で設定する
`keybindings.json`に`when`を記述することで、キーバインドを有効にするタイミングを設定できます。
以下のように記述するとフォーカスがエクスプローラーにあるときのみキーバインドが有効になります。

```keybindings.json
[
  {
    "key": "cmd+n",
    "command": "explorer.newFile",
    "when": "explorerViewletFocus"
  },
  {
    "key": "ctrl+n",
    "command": "explorer.newFolder",
    "when": "explorerViewletFocus"
  }
]
```
シナリオで理解するGitを使ったチーム開発における新機能の追加とブランチの管理方法

本記事では、新人エンジニアのタカノリくんが、初めてのチーム開発でGitを使ってタスクをこなすシーンを通じて、`git checkout` コマンドの使い方と新しいブランチを作成する理由、作業後のブランチの切り替えについて学んでいきます。

**【シナリオ】**

タカノリくんは、仮想通貨の取引を行うWebアプリケーションを開発するプロジェクトチームに参加しました。今日から彼は、新たな機能の開発に取り組みます。開発する機能は"ユーザープロフィール表示"です。

**STEP 0: ブランチの状態を確認する**

まず、タカノリくんは自分が現在どのブランチにいるのか確認します。これには `git branch` コマンドを使用します。

```bash
$ git branch
```

このコマンドを実行すると、以下のような出力が得られます：

```bash
* main
```

ここで `*` は現在のブランチを示しており、タカノリくんは現在 `main` ブランチにいることがわかります。


**STEP 1: 新しいブランチを作る**

次に、新しい機能を追加するための新しいブランチを作ります。この操作は `git checkout -b` コマンドを使って行います。

```bash
$ git checkout -b user-profile
```

これで `user-profile` ブランチが作成され、そのブランチに切り替えられました。タカノリくんはこのブランチでユーザープロフィール表示の新機能を開発します。

**STEP 1.5: `git log` を確認し、`HEAD`の位置を理解する**

タカノリくんは `git log` コマンドを使って、自分が今どのブランチにいるのか、最新のコミットは何かを確認します。

```bash
$ git log
```

そして、こんな出力が得られます。

```bash
commit a1b2c3d4e5f67890g
Author: Takanori <takanori@example.com>
Date:   Fri Jul 7 14:53:40 2023 +0900

    Add user-profile feature

HEAD -> main, origin/main, origin/HEAD
```

ここで `(HEAD -> main)` と表示されています。これは現在 `HEAD`（つまり私たちが作業している位置）が `main` ブランチにあることを示しています。もし、この位置が `user-profile` ブランチであれば `(HEAD -> user-profile)` と表示されます。


**STEP 2: 新しい機能の開発**

タカノリくんは `user-profile` ブランチで新機能の開発を進めます。コードが書き終わったら、`git add` と `git commit` コマンドを使って変更をコミットします。このブランチはタカノリくんが自由に変更できるので、試行錯誤しながらコーディングを進めることができます。

**STEP 3: `git checkout` で元のブランチに戻る**

新機能の開発が完了し、テストも無事に通ったとします。タカノリくんは次に、自分の変更をメインブランチにマージするために、まず `main` ブランチに戻ります。このときも `git checkout` コマンドを使います。

```bash
$ git checkout main
```

これでタカノリくんは `main` ブランチに戻ることができました。`main` ブランチに戻る理由は、新たに作成した機能をメインブランチに統合（マージ）するためです。これにより他の開発者もタカノリくんが追加した新機能を利用することができます。

**STEP 4: `main` ブランチへのマージ**

タカノリくんが `main` ブランチに戻ったら、次に新たに作成した `user-profile` ブランチを `main` ブランチにマージします。この操作により、`main` ブランチにタカノリくんが追加した新機能が反映されます。このマージ操作は `git merge` コマンドを使って行います。

```bash
$ git merge user-profile
```

これで `main` ブランチに `user-profile` ブランチの変更が統合されました。

**STEP 5: 変更をリモートリポジトリにプッシュする**

最後に、ローカルリポジトリの変更をリモートリポジトリに反映します。これにより、チームメイトもタカノリくんが追加した新機能を利用することができます。この操作は `git push` コマンドを使って行います。

```bash
$ git push origin main
```

これでリモートリポジトリの `main` ブランチにも新機能が反映されました。

**STEP 6: チームメイトが新機能を利用する**

タカノリくんが新しい機能を `main` ブランチにマージし、リモートリポジトリにプッシュした後、その新機能を他のチームメイトが使いたい場合、彼らは次の手順を踏む必要があります。

**STEP 6.1: 最新の `main` ブランチを取得する**

まず、他のチームメイトは自分のローカルリポジトリが最新の状態であることを確認する必要があります。これには `git pull` コマンドを使用します。

```bash
$ git checkout main
$ git pull origin main
```

これにより、リモートリポジトリの最新の `main` ブランチ（タカノリくんが追加した新機能がマージされた状態）が、チームメイトのローカルリポジトリの `main` ブランチに反映されます。

**STEP 6.2: 新機能を使うための新しいブランチを作成する**

次に、チームメイトは新機能を使うための新しいブランチを作成します。ここでも `git checkout -b` コマンドを使います。

```bash
$ git checkout -b new-feature-using-profile
```

これで `new-feature-using-profile` ブランチが作成され、そのブランチに切り替えられました。チームメイトはこのブランチで新機能（ユーザープロフィール表示）を利用した開発を行います。

**まとめ**

git checkout コマンドは、ブランチの作成と切り替えを行う非常に便利なツールです。新しいブランチを作成し、そこで作業を行うことで、他のメンバーとの作業の干渉を防ぎます。作業が完了したら、main ブランチに戻り、新機能を main ブランチに統合します。そして、その変更をリモートリポジトリにプッシュすることで、チーム全体で新機能を利用できるようになります。ぜひ参考にしてみてください。
郵便番号から自動で都道府県などの情報を取得したい！

# 始まり

システム入力画面で
郵便番号、都道府県、市区町村、町域など分けて入力するようになっていたので、ユーザーの入力がとても大変だったので、
郵便番号を入力されたらその他の項目が自動で入力できたら楽だなと思いライブラリを探すことになりました。

更新自体は4年前で止まっていますが、システムの安全性の調査値はそこまで低くないみたいなので、こちらのライブラリを使うことにしました！
[yubinbango-core2](https://snyk.io/advisor/npm-package/yubinbango-core2)

## 導入

```
npm install yubinbango-core2
```

## Vue側のscriptタグ辺りにimport文を追可

```
import {Core as YubinBangoCore} from "yubinbango-core2"
```


## Vueの使いたいところでYubinBangoCoreを呼び出す

ESLint入れていて書き方について少し詰まりました笑


```
methods() {

    // 郵便番号から住所自動入力
    changeAddress() {
      const yubinBangoCoreClass = new YubinBangoCore();

      yubinBangoCoreClass.constructor(this.form.postcode, (addr) => {
        this.form.prefecture_id = addr.region_id;
        this.form.address = addr.locality + addr.street;
      });
    },
```


### 参考文献
[Vue.js3系(composition API)で郵便番号から住所検索機能(yubinbango-core2)を実装する](https://saunabouya.com/2022/02/08/vue-yubinbango/)
Viva Sales をSalesforce に接続した際の初期挙動

こんにちは。日本マイクロソフト向井です。

こちらの記事では、Viva Sales をSalesforce に接続した際の初期挙動についてご紹介します。

アーキテクチャについては以下の記事をご参考ください。
[Viva Sales で使用されるCRMデータの保持場所とアクセス権限について](https://qiita.com/kumukai/items/4204500014f4c114406c)

# 初期挙動
まず、Outlook 内の Viva Sales アプリを開き、Salesforce CRM にサインインするを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/c2e260c9-4aeb-3dc2-4223-8c44814a5828.png)

ポップアップウィンドウが表示されるので許可を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/2f96b356-77f0-9b07-4b52-9a6927f78d82.png)

Salesforce のサインイン画面が表示されるので、Salesforceのアカウント情報を使用してサインインをします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/27f4474d-f0e5-32d0-d77b-d9f188582561.png)

アクセスを許可しますか？というメッセージが表示されるので、許可します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/a1de2c76-41a8-03a1-c369-e5114d3aa0d8.png)

もう一つポップアップが表示されるのでこちらもアクセスを許可します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/3fc224d7-f91e-d860-bfcf-384575478d6f.png)

これで、Salesforceへの接続が完了します。

これらの挙動についてはViva Sales のアーキテクチャの文章の以下の部分(p.24)に記載されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/558af4b5-e7b2-5a56-65c0-871077b635c1.png)



# 接続の確認と取り消し
個人設定の接続から接続済みのアプリケーションの一覧を確認できます。
こちらから接続を取り消しすることも可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/49671929-eca0-84af-9dc0-76772701d31d.png)
AFCのデイトピッカーを公開期限として使う

カスタムフィールドに入力した日時と現在の日時を比較して
期限が来たら自動で公開終了〜とかしたいとき。

```php:page-template.php
//カスタムフィールドの日付を取得（AFC）
$due_date = get_field('due_date');
 
//日付が空は無期限とする
if(!empty($due_date)) {
    $now_date = new DateTime(wp_date('Y-m-d G:i:s'));
    $close_date = new DateTime($due_date);

    if($close_date < $now_date){
        wp_redirect(esc_url(home_url('/closed/')));
        exit;
    }
}
```

`wp_date()`を使わないと日時が9時間ずれるみたい。
AmplifyでLayer付きのFunctionをローカル実行(Amplify Mock)したい

## 対象のLambda Function

Layerが設定されています。
Layerには共用のNPM Packageがインストールされています。

## 課題

Amplify MockではLayer付きFunctionのローカル起動をサポートしていません。
起動時に以下のようなエラーが吐き出されます。

> Unable to mock myFunction. Mocking a function with layers is not supported. To test in the cloud: run "amplify push" to deploy your function to the cloud and then run "amplify console function" to test your function in the Lambda console.

### 1. Mock起動前にLayerを外す

Amplify CLI GitHub Issueにコメントがあります。
amplify-meta.jsonからjqを利用してLayerを外すことで起動できるようです。

https://github.com/aws-amplify/amplify-cli/issues/4826#issuecomment-1508986267

### 2. FunctionにLayer環境を移植する

1でLayerを外すことで、そこにインストールされているライブラリが利用できなくなります。
今回のケースでは、NPM Packageを利用できるようにする必要があります。

該当Functionのpackage.jsonに記載していればMock起動時にインストールしてくれるので、
Layerのpackage.jsonの `depndencies` を転記すれば良さそうです。

## 具体的な対応方法

手動対応は当然やりたくないので、コマンドで実行します。
必要に応じてファイルのバックアップは取っておきましょう。

### 1. Mock起動前にLayerを外す

```bash
FUNCTION_NAME="myFunction"
MOCK_META_JSON=`jq ".function.$FUNCTION_NAME.dependsOn = []" /path/to/amplify-meta.json`
echo "$MOCK_META_JSON" > /path/to/amplify-meta.json
```

### 2. FunctionにLayer環境を移植する

以下はFunctionのpackage.jsonのdependenciesをLayerのもので置き換えるケースです。

```bash
LAYER_DEPENDENCIES=`jq .dependencies /path/to/layer/package.json`
PKG_JSON=`jq . /path/to/function/package.json | jq ". + {\"dependencies\": ($LAYER_DEPENDENCIES) }"`
echo "$PKG_JSON" > /path/to/function/package.json
```

## Amplify Mockでローカル実行する

```bash
$ amplify mock function $FUNCTION_NAME --event src/event.json` 
```

amplify-meta.json, package.jsonを戻すのをお忘れなく。
NIMサーバー備忘録

# はじめに

NIM = ネットワーク・インストール・マネージャーの略で、AIX環境で使います。
NIMを使うと色々便利なことがあります。
たとえば、バックアップやリストアがオンラインで実行できたり、NIMサーバー上に配置したアップデート・イメージ(lpp_source)を使ってAIXをアップデートできたり、などなど。
特に、AIXのLPAR数が多いときには重宝します。

一方、個人的には最近あまりNIMサーバーを使っていなかったので、細かい使い方をすっかり忘れていました。
そこで、「あれ、どうやるんだっけ？」と思って探してしまった情報を備忘録的に書いておこうと思います。

# mksysbをリストア&TL/SP更新するとき、「マイグレーション・リストア」が使えるのか？

### AIXのマイグレーションとは？

AIXのマイグレーションとは、AIX 7.1から7.2への移行のように異なるバージョンへアップグレードすることを言います。

>NIMを使ったAIXのマイグレーション
>https://www.ibm.com/docs/ja/aix/7.3?topic=installing-migrating-aix

NIMサーバーがない場合、AIX導入メディアから起動してマイグレーションを行う必要がありますが、NIMサーバーがあればネットワーク・ブートしてマイグレーションを行うことができます。

>Q9. NIMでマイグレーションをするときの手順は？
>https://www.ibm.com/support/pages/power-systems-aix-faq%E9%9B%86-nim#Q9

### マイグレーション・リストアとは？

すでに導入済みのAIXのマイグレーションだけでなく、mksysbにバックアップを取ったAIXをリストアしながらマイグレーションすることもできます。これを、マイグレーション・リストアと言います。このとき、BOSINST.DATAの"INSTALL_METHOD = migrate"にして、mksysbのリストアを実施します。

>mksysb マイグレーション
>https://www.ibm.com/docs/ja/aix/7.3?topic=aix-mksysb-migration

どうしてこういう手段が用意されているかというと、移行前のバージョンのAIXをサポートしていない新しいハードウエアへリストアしたいとき、リストアと同時にマイグレーションが必要になるからです。マイグレーション・リストアの実行時には、移行後の新しいAIXのSPOTで起動するため、移行前のバージョンをサポートしていないハードウエアへもリストア可能なのです。
ちなみに、この記事でも使っています。

>AIX 5.3をPower Systems Virtual Server上に移行インストールしてみる(移行後はAIX 7.2)
>https://qiita.com/hiroyuki_z_tanaka/items/bf5b0de4062db9d047f6

### TL/SP更新に使えるか？

この方法は、mksysbをリストアしつつTL/SPを更新する(AIXのバージョンは同じ）場合にも使えるような気がします。
が、結論からいうと、同じAIXのバージョンのTL/SP更新には使えません。
デバッグモードで起動するとわかりますが、マイグレーションリストアでは移行前後のAIXのバージョンを比較していて、同じだとエラーになるようになっています。

mksysbリストアと一緒にTL/SP更新を行いたいときには、BOSINST.DATAに"INSTALL_METHOD = overwrite", "INSTALL_DEVICES_AND_UPDATES = yes"を設定してリストアを行います。

>bosinst.data control_flow スタンザの説明
>https://www.ibm.com/docs/ja/aix/7.3?topic=file-bosinstdata-control-flow-stanza-descriptions


# TLアップグレード時、導入メディアとFix CentralからダウロードしたTLのどちらを使うべきか

TLアップグレード時、導入メディアとFix CentralからダウロードしたTLのどちらを使うべきでしょうか。どちらも使うことができますが、奨励はFix CentralからダウロードしたTLを使う方法のようです。

>Updating to a new Technology Level or Service Pack
>https://www.ibm.com/support/pages/updating-new-technology-level-or-service-pack

実際、やってみると新しい導入メディアには含まれないファイルセットがあったりします（たとえば、「古い」Javaの最新ファイルセットは、新しい導入メディアには入っていないことがありました。そのため、アップデートしたのに"oslevel -s"の出力が目的のTL/SPまで上がってなかったりすることがあります）。

一方、Fix CentralからダウンロードしたTLアップデートでは、spotが作れないようなので要注意です。

>lpp_source リソースの使用：spotを作る時のlpp_sourceにはsimages属性が必要
>https://www.ibm.com/docs/ja/aix/7.2?topic=resources-using-lpp-source-resource

ちなみに、lpp_sourceにはファイルセットを追加することもできます。この方法を使って、ESSからダウンロードした導入メディアとFixCentralからダウンロードしたTLアップデートをマージして、simages属性のあるlpp_sourceを作ることもできます。

>2023/12/1追記：同じレベルのベースメディアとアップデートメディアを結合するのはNGだそうです。Base filesetとUpdate filesetが混ざっちゃうからかな？
>https://www.ibm.com/docs/en/aix/7.3?topic=resources-using-lpp-source-resource
>Note: Do not combine an lpp_source resource that was created from a technology-level base media with images from the same technology-level update media.


>Q10. NIMでアップデートをするときの手順は？
>https://www.ibm.com/support/pages/power-systems-aix-faq%E9%9B%86-nim#Q10

# まとめ
ここに書いたことは、日頃からNIMサーバーを使って運用されている方には、当たり前のことかと思います。が、たまーにしかNIMサーバーを使わない身としては、結構忘れがち・・・。こうして記事にしておいて、また忘れた時に参照したいと思います。
Debian 12 にOpenJDK 17をインストール（OS標準）

# はじめに

Debian12にOpenJDKを標準インストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)

## サポート

不明
OpenJDK 17 プロジェクトをリードするベンダまたはコミュニティが示すサポート期日とDebian側のOS EOLに依存する。

## LOG

### インストール

```shell-session
# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

# apt update;apt install -y openjdk-17-jdk
... 略
```

### 各種確認

```shell-session
# which java
/usr/bin/java

# java -version
openjdk version "17.0.7" 2023-04-18
OpenJDK Runtime Environment (build 17.0.7+7-Debian-1deb12u1)
OpenJDK 64-Bit Server VM (build 17.0.7+7-Debian-1deb12u1, mixed mode, sharing)
```
「Qiita × Fast DOCTOR Health Tech Hackathon」で優秀賞をいただきました

7月1日・2日に開催された[Qiita × Fast DOCTOR Health Tech Hackathon](https://increments.connpass.com/event/275754/)に参加し、優秀賞を受賞することができました。具体的に作成したものについての詳細は他のチームメンバーが説明する予定なので、参加背景と私の感想に焦点を当てレポートさせていただければと思います。  
![HealthTech Hackathon](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3501414/7b6a8af1-08e6-4e01-3927-b5f2540c7484.png)  

# Who

今回参加した5人のメンバーは会社の同僚で、[株式会社ヘンリー](https://corp.henry-app.jp/)という電子カルテを作っている会社に勤めています。ただし、今回のハッカソンへの参加は会社を代表するものではなく、会社の#randomチャンネルに「Qiita × Fast DOCTOR Health Tech Hackathon」の情報が流れてきたところ、面白そうと思ったメンバーが自発的に集まり、参加を決めたものです。そのため、ハッカソンでは「ヘンリー」という名前は一切使いませんでした。どちらかというと、社会人サークルのノリでした。

# Why

では、なぜ私たちは参加を決めたのでしょうか。その主な理由は、やはりテーマへの興味が一番でした。  
まず、我々は普段医療ITのサービスを作っているということもあり、この分野の課題の大きさと解決の価値を深く感じています。しっかりと課題を解決するために、着実に進める実行力と柔軟な発想力が必要です。今回のハッカソンは、発想力を活用して新しいアイデアを見つける絶好の機会だと考えていました。  
また、ChatGPTというトピックが非常に魅力的でした。LLMが世界に与えた影響は言うまでもなく、医療IT分野でも活用してみたいとずっと考えていました。一方、患者情報保護の観点から、我々の製品にOpenAIのソリューションを組み込むことは容易でない現状があります。そのため、このハッカソンは私たちにとって非常に良いチャンスだったのです。

# What

自分を含め、チームにハッカソンの熟練者が居ませんでした（むしろ初参加が多かった）が、2日間とても楽しめました。  
まず、運営はとてもスムーズだと感じました。最初の応募から担当の方が親切にメールで対応してくださいました。その後のDiscordへの案内や毎日のアナウンスも適切で、基本的には指示に従うだけで迷うことなく行動できました。会場の設営や昼食の手配など、関係者が多いため大変だったと思いますが、参加者としては何の不便も感じず、ハッカソンに集中することができました。  
また、チームでひたすらアイデアを考えて実装するだけでなく、主催者であるファストドクターさんの医師の皆様がチームに入り、情報のインプット及びアドバイスを下さった点はとてもありがたいと感じました。我々は普段医療ITの知識に触れていますが、医者ではないため、利用者視点からの実用性判断が難しい部分がありました。様々な知識を親切に教えていただいたので大変学びになりました。ハッカソンの場だけでなく、今の業務でも活用できると感じました。

# 終わりに

医療分野はドメインが深い故に、多くの方に敬遠されがちだと感じております。実際に医療と言っても範囲が広いので、調べてみたら意外と面白いセグメントも多かったりします。ぜひ皆さんに興味を持っていただきたいと思っています。（タイムリーですが、ファストドクターさんも参加したオンラインイベント「[医療スタートアップ開発裏側](https://note.com/henry_app/n/n6f61804f84d0)」は参考になると考えます）  
秋頃にHealth Tech Hackathonの第二弾が開催されるとのことです。医療ITに携わっている方はもちろん、そうでない方も、この分野を知るきっかけとして捉えて参加してみてはいかがでしょうか？
Debian 12 にNginx stable最新版をインストール（公式repository）

# はじめに

公式repositoryを利用してDebian12にNginx stable最新版をインストール
親記事：[Nginxの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/df4a0baaaad9c932ea30)
参考：[nginx: Linux packages](https://nginx.org/en/linux_packages.html#Debian)

## サポート

本手法で導入した場合、nginxの開発が停止するまでサポートされると思われる。
特定のバージョンを指定しなければ、stable最新版が常に提供されると思われる。

## LOG

### レポジトリ登録

```shell-session
# apt update; apt install -y curl gnupg2 ca-certificates lsb-release debian-archive-keyring
# curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
# gpg --dry-run --quiet --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
gpg: keyblock resource '/root/.gnupg/pubring.kbx': No such file or directory
pub   rsa2048 2011-08-19 [SC] [expires: 2024-06-14]
      573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62
uid                      nginx signing key <signing-key@nginx.com>
# echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/debian `lsb_release -cs` nginx" | tee /etc/apt/sources.list.d/nginx.list
```

### インストール

```shell-session
# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

# apt update; apt install -y nginx
... 略
```

### 各種確認

```shell-session
# which nginx
/usr/sbin/nginx

# nginx -v
nginx version: nginx/1.24.0

# apt show nginx
Package: nginx
Version: 1.24.0-1~bookworm
Priority: optional
Section: httpd
Maintainer: NGINX Packaging <nginx-packaging@f5.com>
Installed-Size: 3117 kB
Provides: httpd, nginx, nginx-r1.24.0
Depends: libc6 (>= 2.34), libcrypt1 (>= 1:4.1.0), libpcre2-8-0 (>= 10.22), libssl3 (>= 3.0.0), zlib1g (>= 1:1.1.4), lsb-base (>= 3.0-6), adduser
Conflicts: nginx-common, nginx-core
Replaces: nginx-common, nginx-core
Homepage: https://nginx.org
Download-Size: 898 kB
APT-Manual-Installed: yes
APT-Sources: http://nginx.org/packages/debian bookworm/nginx amd64 Packages
Description: high performance web server
 nginx [engine x] is an HTTP and reverse proxy server, as well as
 a mail proxy server.

N: There is 1 additional record. Please use the '-a' switch to see it
```
Elixirの対話モードで内包表記の動作を確認してみた

# 概要
Elixirの対話モードで内包表記の動作を確認してみました。以下のページを参考にしました。

https://dev.to/gumi/elixir-17--5gci

# 実行
以下のコマンドを実行しました。
```
$ iex
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> for n <- [1, 2, 3, 4, 5], do: n * n
[1, 4, 9, 16, 25]
iex(2)> for n <- 1..5, do: n * n
[1, 4, 9, 16, 25]
iex(3)> for {_key, val} <- [one: 1, two: 2, three: 3], do: val
[1, 2, 3]
iex(4)> for {key, val} <- %{one: 1, two: 2, three: 3}, do: {key, val}
[one: 1, three: 3, two: 2]
iex(5)> for <<char <- "hello">>, do: <<char>>
["h", "e", "l", "l", "o"]
iex(6)> numbers = [identity: 1, prime: 2, prime: 3, normal: 4, prime: 5]
[identity: 1, prime: 2, prime: 3, normal: 4, prime: 5]
iex(7)> for {:prime, n} <- numbers, do: n * n
[4, 9, 25]
iex(8)> for i <- [:a, :b, :c], j <- [1, 2], do:  {i, j}
[a: 1, a: 2, b: 1, b: 2, c: 1, c: 2]
iex(9)> for i <- [1, 2, 3], j <- 1..i, do: [i: i, j: j]
[
  [i: 1, j: 1],
  [i: 2, j: 1],
  [i: 2, j: 2],
  [i: 3, j: 1],
  [i: 3, j: 2],
  [i: 3, j: 3]
]
iex(10)> multiple_of_3? = fn(n) -> rem(n, 3) == 0 end
#Function<44.65746770/1 in :erl_eval.expr/5>
iex(11)> for n <- 0..10, multiple_of_3?.(n), do: n * n
[0, 9, 36, 81]
iex(12)> import Integer
Integer
iex(13)> for n <- 0..10, is_even(n), do: n
[0, 2, 4, 6, 8, 10]
iex(14)> for n <- 0..100,
...(14)> is_odd(n),
...(14)> rem(n, 7) == 0,
...(14)> do: n
[7, 21, 35, 49, 63, 77, 91]
iex(15)> pixels = <<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>>
<<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>>
iex(16)> for <<r::8, g::8, b::8 <- pixels>>, do: [r: r, g: g, b: b]
[
  [r: 213, g: 45, b: 132],
  [r: 64, g: 76, b: 32],
  [r: 76, g: 0, b: 0],
  [r: 234, g: 32, b: 15]
]
iex(17)> for c <- [104, 101, 108, 108, 111], into: "", do: <<c>>
"hello"
iex(18)> for <<char <- " to be, to be, ten made to be ">>, char != ?\s, into: "", do: <<char>>
"tobe,tobe,tenmadetobe"
iex(19)> for {key, val} <- %{a: 1, b: 2, c: 3}, into: %{}, do: {key, val * val}
%{a: 1, b: 4, c: 9}
iex(20)> stream = IO.stream(:stdio, :line)
%IO.Stream{device: :standard_io, line_or_bytes: :line, raw: false}
iex(21)> for line <- stream, into: stream do
...(21)> String.upcase(line) <> "\n"
...(21)> end
elixir
ELIXIR
```

# まとめ
何かの役に立てばと。
M1 に numjs が入らなかったのでメモ

## numjs

行列計算用のライブラリ。名前から分かる通りnumpyちっくなやつ。

https://github.com/nicolaspanel/numjs

## M1(arm64)でビルドが通らない
そもそもの原因は依存関係ではいる`sharp`のビルドが転けること。
いくつか理由はあって以下の通り

- 依存関係でインストールしようとするvipsがarm64用でない
- pythonが最新だとnode-gypが実行できない
  - そもそもMacにpython, xcode(gcc)が入ってない可能性もある

## 解決策
xcode, python, pyenv のインストールは割愛

### vipsをbrewでインストール
```sh
brew install vips
```

### python3.9をインストールしてグローバルにセット
```sh
pyenv install 3.9.17
pyenv global 3.9.17 
```
- 3.9系の最新を入れてください
- 必要に応じて後でglobalを戻してください


で、`num i numjs` が成功するんじゃないかと思います！
基本情報技術者試験（FE） 科目A試験免除の過去問の解説あつめたい

基本情報技術者試験（FE）の科目A試験免除の過去問の問題、解説はIPAがサイトで公開してくれてます
問題自体はFE, AP, その他と同じ問題が出てるので勉強してる人のために解説集めたいなと考え中．．．
問題にアクセスする枠組みを作っては見たのですが解説の先を集める方法を試行錯誤中。。

一旦はマンパワー使って３回分が確認できるサイト作ってみました
どうにか解説してるリンクを楽して集めたい。。

https://sueasen.github.io/javascript-exercise/work/feapass/
Debian 12 にNginx mainline最新版をインストール（公式repository）


公式repositoryを利用してDebian12にNginx mainline最新版をインストール
親記事：[Nginxの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/df4a0baaaad9c932ea30)
参考：[nginx: Linux packages](https://nginx.org/en/linux_packages.html#Debian)

## サポート

本手法で導入した場合、nginxの開発が停止するまでサポートされると思われる。
特定のバージョンを指定しなければ、mainline最新版が常に提供されると思われる。

## LOG

### レポジトリ登録

```shell-session
# apt update; apt install -y curl gnupg2 ca-certificates lsb-release debian-archive-keyring
# curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
# gpg --dry-run --quiet --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
gpg: keyblock resource '/root/.gnupg/pubring.kbx': No such file or directory
pub   rsa2048 2011-08-19 [SC] [expires: 2024-06-14]
      573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62
uid                      nginx signing key <signing-key@nginx.com>
# echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/mainline/debian `lsb_release -cs` nginx" | tee /etc/apt/sources.list.d/nginx.list
```

### インストール

```shell-session
# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

# apt update; apt install -y nginx
... 略
```

### 各種確認

```shell-session
# which nginx
/usr/sbin/nginx

# nginx -v
nginx version: nginx/1.25.1

# apt show nginx
Package: nginx
Version: 1.25.1-1~bookworm
Priority: optional
Section: httpd
Maintainer: NGINX Packaging <nginx-packaging@f5.com>
Installed-Size: 3476 kB
Provides: httpd, nginx, nginx-r1.25.1
Depends: libc6 (>= 2.34), libcrypt1 (>= 1:4.1.0), libpcre2-8-0 (>= 10.22), libssl3 (>= 3.0.0), zlib1g (>= 1:1.1.4), lsb-base (>= 3.0-6), adduser
Conflicts: nginx-common, nginx-core
Replaces: nginx-common, nginx-core
Homepage: https://nginx.org
Download-Size: 1003 kB
APT-Manual-Installed: yes
APT-Sources: http://nginx.org/packages/mainline/debian bookworm/nginx amd64 Packages
Description: high performance web server
 nginx [engine x] is an HTTP and reverse proxy server, as well as
 a mail proxy server.

N: There are 2 additional records. Please use the '-a' switch to see them.
```
*args, **kwargsとはいったい何なのか

# 背景
Pythonコードを書いていると関数に*args, **kwargsという引数を使う場面に出くわすと思います。

初見だと一体これは何をやっているの？？と感じたため、まとめてみます。

# 本文
*args, **kwargsとは何なのか？結論

**引数の大きさを自由に変更できる引数のこと**。


詳しく説明します。引数が固定長の場合、例えば２つの入力のみ想定していたが、３つや４つの入力の合計を出力したいとなった時、新たに３引数、４引数の関数を作るのは面倒ですよね。

そこで*argsや**kwargsが登場します。

*argsでは複数の引数をタプルとして受け取り、**kwargsでは複数のキーワード引数を辞書として受け取ります。これらは可変長引数と呼ばれているので覚えておきましょう。

ちなみにargsとかkwargsって何なの？って思う方いると思います。おそらくですが、
args: **arg**ment**s**
kwargs: **k**ey**w**ords **arg**ment**s**
の略だと思います。知っている方いらっしゃれば教えてください。

それではサンプルコードを見てみます。

~~~python
def func_args(*args):
    return sum(args)

print(num_sum(1, 2, 3))
# 6
print(num_sum(1, 2, 3, 4, 5, 6))
# 21

def func_kwargs(**kwargs):
    print('kwargs: ', kwargs)

func_kwargs(key1=1, key2=2, key3=3)
# kwargs:  {'key1': 1, 'key2': 2, 'key3': 3}
~~~

確かに引数を何個も受け取れてますね。非常に便利な機能であることが分かります。

# 注意点
可変長引数は非常に便利な機能ですが、何でも使えばいいわけではありません。具体的に問題例を見てみます。

~~~python
class User:
    def __init__(self, **kwargs):
        self.name = kwargs['name']
        self.mail = kwargs.get('mail')

user = User(name="hoge", address="hogehoge") # エラーが起きない

print(user.mail)
# None

~~~
上記のコードでは、クラスが期待していない`address=`も引数として受け取れてしまいます。さらに`user.mail`はNoneになるため、別のプログラム上でエラーになる可能性があります。

実用を考えると注意が必要ですね。

もう一つ例を見てみます。

~~~python
def hoge(a, b, *args):
    print(a)
    print(b)
    print(args)

a="Hello!"
b="World!"
c=["I am a", "nooby", "programmer!!"]

hoge(a,b,c)
# Hello!
# World!
# (['I am a', 'nooby', 'programmer!!'],)
~~~

可変長引数は位置引数と組み合わせることもできます。この場合、位置引数より後ろ側で指定した値が`args`にタプルとして渡されます。

この時、位置引数のみ記述すればどうなるでしょうか。

~~~python
hoge(a, c)
# Hello!
# ['I am a', 'nooby', 'programmer!!']
# ()
~~~

`args`には空のタプルが入力されています。これは可変長引数が自由な長さを持てることにより起こります。エラーの原因になりそうですね。

このままだとよくないので解決策として、

~~~python
def hoge(a,b,*args):
    if len(args)==0: raise TypeError("args is not given") # argsがタプル型なのを利用する
    print(a)
    print(b)
    print(args)

a="Hello!"
b="World!"
c=["I am a","nooby","programmer!!"]

hoge(a,c)
# TypeError: args is not given
~~~

こうすることで引数が想定より少ないとき、エラーコードを出力できるようになりました。

# 参考サイト
https://note.nkmk.me/python-args-kwargs-usage/
https://itstudio.co/2019/08/05/9454/#toc10
https://pg-chain.com/python-function-args
[https://jisou-programmer.beproud.jp/関数設計/9-関数の引数に可変長引数を乱用しない.html](https://jisou-programmer.beproud.jp/%E9%96%A2%E6%95%B0%E8%A8%AD%E8%A8%88/9-%E9%96%A2%E6%95%B0%E3%81%AE%E5%BC%95%E6%95%B0%E3%81%AB%E5%8F%AF%E5%A4%89%E9%95%B7%E5%BC%95%E6%95%B0%E3%82%92%E4%B9%B1%E7%94%A8%E3%81%97%E3%81%AA%E3%81%84.html)
https://qiita.com/heat_exchange/items/ad730e02f429992b06dd
複数に分割された OpenAPI の yaml から TypeScript の型を自動生成する方法

# 実現したかったこと
複数に分割された OpenAPI 定義 yaml ファイルから [openapi-typescript](https://www.npmjs.com/package/openapi-typescript) を使って、TypeScript の型を自動生成すること。

# 課題
openapi-typescript は単一の OpenAPI 定義ファイルからのインポートに対応しています。
OpenAPI 定義ファイルを yaml で分割している場合はうまく型定義を作ることが出来ません。

# 解決方法
package.json に下記を追記します。

```json
{
  "scripts": {
    "generate-api-schema": "npx swagger-cli bundle --dereference sample.openapi.yml | npx openapi-typescript --output src/generated_types/api_schema.ts"
  }
}
```

# 解説
[swagger-cli](https://www.npmjs.com/package/swagger-cli) で yaml を一つの json に統合して出力します。

```sh
npx swagger-cli bundle --dereference sample.openapi.yml
```

それをパイプで渡して任意のファイル名で型定義ファイルを出力しています。

```sh
npx openapi-typescript --output src/generated_types/api_schema.ts
```
Debian 12 にNginx 1.22 をインストール（OS標準）

# はじめに

Debian12にNginxを標準インストール
親記事：[Nginxの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/df4a0baaaad9c932ea30)

## LOG

### インストール

```shell-session
# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

# apt update; apt install -y nginx
... 略
```

### 各種確認

```shell-session
# which nginx
/usr/sbin/nginx

# nginx -v
nginx version: nginx/1.22.1

# apt show nginx
Package: nginx
Version: 1.22.1-9
Priority: optional
Section: httpd
Maintainer: Debian Nginx Maintainers <pkg-nginx-maintainers@alioth-lists.debian.net>
Installed-Size: 1362 kB
Provides: httpd, httpd-cgi, nginx-abi-1.22.1-7
Depends: libc6 (>= 2.34), libcrypt1 (>= 1:4.1.0), libpcre2-8-0 (>= 10.22), libssl3 (>= 3.0.0), zlib1g (>= 1:1.1.4), iproute2, nginx-common (<< 1.22.1-9.1~), nginx-common (>= 1.22.1-9)
Breaks: nginx-core (<< 1.22.1-6~), nginx-extras (<< 1.22.1-6~), nginx-light (<< 1.22.1-6~)
Replaces: nginx-core (<< 1.22.1-6~), nginx-extras (<< 1.22.1-6~), nginx-light (<< 1.22.1-6~)
Homepage: https://nginx.org
Tag: implemented-in::c, interface::daemon, network::server, network::service,
 protocol::http, role::program, use::proxying
Download-Size: 527 kB
APT-Manual-Installed: yes
APT-Sources: http://deb.debian.org/debian bookworm/main amd64 Packages
Description: small, powerful, scalable web/proxy server
```
Debian 12 にPHP-FPM 8.2 をインストール（OS標準）

# はじめに

Debian12にPHP-FPMを標準インストール
親記事：[PHP, PHP-FPMの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/dfe3823554b7caba6f6a)

## LOG

### インストール

```shell-session
# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

# apt update -y;apt install -y php-fpm
... 略
```

### 各種確認

```shell-session
# which php
/usr/bin/php

# which php-fpm8.2
/usr/sbin/php-fpm8.2

# php-fpm8.2 -v
PHP 8.2.7 (fpm-fcgi) (built: Jun  9 2023 19:37:27)
Copyright (c) The PHP Group
Zend Engine v4.2.7, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.7, Copyright (c), by Zend Technologies

# apt show php-fpm
Package: php-fpm
Version: 2:8.2+93
Priority: optional
Section: php
Source: php-defaults (93)
Maintainer: Debian PHP Maintainers <team+pkg-php@tracker.debian.org>
Installed-Size: 10.2 kB
Depends: php8.2-fpm
Download-Size: 3712 B
APT-Manual-Installed: yes
APT-Sources: http://deb.debian.org/debian bookworm/main amd64 Packages
Description: server-side, HTML-embedded scripting language (FPM-CGI binary) (default)
```
Debian 12 にPHP 8.2 をインストール（OS標準）

# はじめに

Debian12にPHPを標準インストール
親記事：[PHP, PHP-FPMの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/dfe3823554b7caba6f6a)

## LOG

### インストール

```shell-session
# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

# apt update;apt install -y php
... 略
```

### 各種確認

```shell-session
# which php
/usr/bin/php

# php -v
PHP 8.2.7 (cli) (built: Jun  9 2023 19:37:27) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.7, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.7, Copyright (c), by Zend Technologies

# php -i | grep php.ini
Configuration File (php.ini) Path => /etc/php/8.2/cli
Loaded Configuration File => /etc/php/8.2/cli/php.ini

# apt show php
Package: php
Version: 2:8.2+93
Priority: optional
Section: php
Source: php-defaults (93)
Maintainer: Debian PHP Maintainers <team+pkg-php@tracker.debian.org>
Installed-Size: 10.2 kB
Depends: php8.2
Download-Size: 3628 B
APT-Manual-Installed: yes
APT-Sources: http://deb.debian.org/debian bookworm/main amd64 Packages
Description: server-side, HTML-embedded scripting language (default)
```
【SQL】AS句の使い方〜長いカラム名にはASで別名を付けよう〜

SQLについての学習記録を残しておきます。

今回は、SQLの練習ができるWebツール「SQLab」での学習記録になります。（めちゃ便利で重宝してます）
毎日少しずつでも練習することでSQLへの苦手意識を克服していきたいと思います。

https://sqlab.net/


# SQLで使われるAS句とは？
AS句とは、SQLにおいて、カラムまたはテーブルに別名をつける事ができるコマンドです。


# AS句の使用例

`categories`というテーブルに`name`というカラムがあった場合、
categoriesという名称が長くて面倒な時がありますが、そんな時にはAS句を指定する事で、別名をつけて検索することができます。

```ruby
SELECT cat.name
FROM categories AS cat
```

# 上記コマンドの解説

- `FROM categories AS cat`とする事で、`categories`のテーブル名を`cat`と置き換える事ができる。
- `SELECT cat.name`　で`categories`テーブルの`name`カラムを呼び出す事ができる。



# AS句をつかうメリット

- 社員テーブルの給料 → `employee.salary`
- カテゴリーテーブルのカテゴリー名`categories.category_name`


例えば上記のように、テーブル名、カラム名ともに長い名称を検索する場合、クエリが冗長（じょうちょう）になってしまいます。

短く、スマートにSQLコマンドを打ち込みたい時に、ASを使うのが便利です。

SQLを頻繁に扱う業務では重宝されるコマンドなのかなぁと思います。


# 参考資料

https://style.potepan.com/articles/24708.html


https://style.potepan.com/articles/17997.html
Debian 12 にMariaDB 10.11 をインストール（OS標準）

# はじめに

Debian12にMariaDB10.11をインストール
親記事：[MySQL, MariaDBの各種インストール方法とEOLまとめ \- Qiita](https://qiita.com/witchcraze/items/72291ee035437ec83273)

## LOG

### インストール

```shell-session
# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

# apt update; apt install -y mariadb-server
... 略
```

### 各種確認

```shell-session
# service mariadb start
# mysql -u root -e'select version();'
+-------------------+
| version()         |
+-------------------+
| 10.11.3-MariaDB-1 |
+-------------------+
```
RockyLinux 9にNginx 1.20をインストール（OS標準？）

# はじめに

OSパッケージを利用してRockyLinux9にNginx1.20をインストール
親記事：[Nginxの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/df4a0baaaad9c932ea30)

## サポート

本手法で導入した場合、[Red Hat Enterprise Linux Application Streams Life Cycle \- Red Hat Customer Portal](https://access.redhat.com/support/policy/updates/rhel-app-streams-life-cycle)に掲載されていないので、OS EOLまで保守される可能性がある。

## LOG

### インストール

```shell-session
# cat /etc/redhat-release
Rocky Linux release 9.2 (Blue Onyx)

# yum install -y nginx
... 略
```

### 各種確認

```shell-session
# which nginx
/usr/sbin/nginx

# nginx -v
nginx version: nginx/1.20.1

# yum info nginx
Last metadata expiration check: 0:00:12 ago on Fri Jul  7 05:38:09 2023.
Installed Packages
Name         : nginx
Epoch        : 1
Version      : 1.20.1
Release      : 14.el9
Architecture : x86_64
Size         : 147 k
Source       : nginx-1.20.1-14.el9.src.rpm
Repository   : @System
From repo    : appstream
Summary      : A high performance web server and reverse proxy server
URL          : https://nginx.org
License      : BSD
Description  : Nginx is a web server and a reverse proxy server for HTTP, SMTP, POP3 and
             : IMAP protocols, with a strong focus on high concurrency, performance and low
             : memory usage.
```
AlmaLinux 9にNginx 1.20をインストール（OS標準？）

# はじめに

OSパッケージを利用してAlmaLinux9にNginx1.20をインストール
親記事：[Nginxの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/df4a0baaaad9c932ea30)

## サポート

本手法で導入した場合、[Red Hat Enterprise Linux Application Streams Life Cycle \- Red Hat Customer Portal](https://access.redhat.com/support/policy/updates/rhel-app-streams-life-cycle)に掲載されていないので、OS EOLまで保守される可能性がある。

## LOG

### インストール

```shell-session
# cat /etc/redhat-release
AlmaLinux release 9.2 (Turquoise Kodkod)

# yum install -y nginx
... 略
```

### 各種確認

```shell-session
# which nginx
/usr/sbin/nginx

# nginx -v
nginx version: nginx/1.20.1

# yum info nginx
Last metadata expiration check: 0:00:24 ago on Fri Jul  7 05:35:53 2023.
Installed Packages
Name         : nginx
Epoch        : 1
Version      : 1.20.1
Release      : 14.el9.alma
Architecture : x86_64
Size         : 148 k
Source       : nginx-1.20.1-14.el9.alma.src.rpm
Repository   : @System
From repo    : appstream
Summary      : A high performance web server and reverse proxy server
URL          : https://nginx.org
License      : BSD
Description  : Nginx is a web server and a reverse proxy server for HTTP, SMTP, POP3 and
             : IMAP protocols, with a strong focus on high concurrency, performance and low
             : memory usage.
```
[GCP] Cloud Functions 機能x実装

## GCPのCloud Functionの概要と機能について

Google Cloud Platform (GCP) の Cloud Functionは、イベントドリブンのコンピューティングサービスで、自動的にスケーリングされるサーバーレスの環境で実行される。
Cloud Functionを使用すると、コードを簡単に展開し、特定のイベントに応じて実行でき、さらに、様々なイベントトリガーや言語をサポートしているため、幅広いユースケースに適用することが可能。
以下にCloud Functionの主な機能を紹介します。

1. トリガーの多様性: Cloud Functionは、HTTPリクエスト、ストレージイベント、Pub/Subメッセージ、Firebase Authenticationのトリガーなど、さまざまなトリガーをサポートしています。これにより、適切なトリガーに合わせて関数を自動的に起動することができる。

2. スケーラビリティ: Cloud Functionは、必要なときに自動的にスケーリングされるため、コードのパフォーマンスやトラフィックの急増に合わせて処理能力を調整することができる。これにより、高い可用性とスケーラビリティを実現している。

3. 言語のサポート: Cloud Functionは、Java、Go、C#を含む複数のプログラミング言語をサポートしている。これにより、開発者は自分の選ぶ言語でコードを書き、Cloud Functionで実行することができる。

4. 環境の設定: Cloud Functionは、実行環境を柔軟に設定できるたとえば、関数が使用するリソースの制限、関数のタイムアウト、環境変数の設定などを指定することが可能。

以下に、Java、Go、C#の各言語でのCloud Functionのサンプルコードを記載する。

### Java
```java
import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class MyFunction implements HttpFunction {
  @Override
  public void service(HttpRequest request, HttpResponse response) throws IOException {
    PrintWriter writer = new PrintWriter(response.getWriter());
    writer.write("Hello, World!");
    writer.flush();
  }
}
```

### Go
```go
package helloworld

import (
	"fmt"
	"net/http"
)

func HelloHTTP(w http.ResponseWriter, _ *http.Request) {
	fmt.Fprint(w, "Hello, World!")
}
```

### C#
```csharp
using System;
using System.IO;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;

namespace MyNamespace
{
    public static class MyFunction
    {
        [FunctionName("MyFunction")]
        public static IActionResult Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");
            return new OkObjectResult("Hello, World!");
        }
    }
}
```

以上が、Cloud Functionの概要と機能、およびJava、Go、C#のサンプルコードです。Cloud Functionを使用することで、イベントドリブンなアプリケーションやタスクを簡単に実装することができる。
[ServiceNow] ReferenceフィールドのReference qualifierをScriptで制御する

Reference qualifierは、Referenceフィールドの選択肢をFilterする機能です。Reference先のテーブルのレコードを、特定のフィールドの値で絞るなど静的条件ではなく、例えばUserのRoleによって条件を変更する場合などは、Scriptingによる実現が現実的です。
ここでは、UserのCompanyフィールドについて、adminロールユーザーなら、すべてのCompanyが選択でき、user_adminロールユーザーならば、そのユーザーのCompanyしか選択できないようなReference qualifierを設定してみます。
まずは、Reference qualifierから呼び出すFunctionを、Script includeで定義します。

* Name: ReferenceQualifierUtils
* Accessible from: All application scopes

```javascript: Script include - script
var ReferenceQualifierUtils = Class.create();
ReferenceQualifierUtils.prototype = {
    initialize: function() {},

    //For referece fields to core_compnay
    getManagingCompanies: function() {
        var encodedQuery = "";

        if (!gs.hasRole('admin')) {
            var grUser = new GlideRecord('sys_user');
            grUser.get(gs.getUserID());

            if (gs.hasRole('user_admin')) {
                encodedQuery = "sys_id=" + grUser.getValue('company');
            } else {
                encodedQuery = "sys_id=NULL";
            }
        }

        return encodedQuery;
    },

    type: 'ReferenceQualifierUtils'
};
```

次に、この関数を、UserのCompanyフィールドでReferenceQualifierから呼び出します。

![Reference Qualifier＿１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490802/564d8bf5-ad9f-17a4-9ec1-c9cfa70664d3.png)

:::note info
Functionを作成するポイントは、必ずReference先のテーブルの対するEncoded query stringを返すようにすることです。Encoded query stringの記載内容によっては、複雑な条件を設定することができます。
:::

sys_idの一覧を返す場合は、sys_idのカンマ区切り文字列をIN句で絞るような条件にします。

```javascript: Script include - script
(前略)
    return "sys_idIN" + <ここにsys_idのカンマ区切り文字列>;
(後略)
```
[Android] Media3を使って.mp4の容量を減らす

AndroidではVideoのファイルを圧縮したりするのは大変な苦しみを伴う（と思ってる）

FFmpegのライセンスの関係もあり、有効なライブラリはとても少ない。

ライブラリとしても
LightCompressor
https://github.com/AbedElazizShe/LightCompressor
が目立つぐらいで他はメンテナンスされてなかったりするのでとても不安だ。

上記のLightCompressを使用してみたが、
特定の端末の動画ではどうにも挙動がおかしく圧縮サイズがうまくいかず、想像以上にガビガビになったため中々手放しでは喜べない状況になってしまった。

なお、Coroutineなど使って実装しなおそうと試みたがMediaCodecAPIが激烈に使い辛くすぐやめた。

とにかく簡単に動画の容量を落としたいと思い、別の方法を模索した

#### Jetpack Media3ライブラリ
https://developer.android.com/jetpack/androidx/releases/media3

動画、音声などを扱うライブラリ（ExoPlayerなど）を統合し、Android Jetpackとして用意された新たなライブラリ群。

これを使い動画の容量を落としてみる。

対象の動画ファイル
1920*1080の1080pのMP4
総ビットレート12944kbps
61.4MB
最近の端末のカメラから直接撮ると大体こんな感じになると思います。
奇麗ですが、送信したりするにはちょっと大きい＆奇麗すぎ。

#### 実装
media3ライブラリ
```build.gradle
    def media3_version = "1.0.2"
    implementation "androidx.media3:media3-transformer:$media3_version"
    implementation "androidx.media3:media3-common:$media3_version"
```
stable版の1.0.2を利用しました。
プレイヤーに表示したりはしないので、コアなモジュールだけです。

```VideoCompress.kt
        @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
        fun videoFileResizeByMedia3(context: Context, videoUri: Uri) {
            val transformationRequest = TransformationRequest.Builder()
                .setVideoMimeType(MimeTypes.VIDEO_H264)
                .setAudioMimeType(MimeTypes.AUDIO_AAC)
                .setResolution(1280) //720p
                .build()

            val inputMediaItem = MediaItem.fromUri(videoUri)
            val outputPath = context.applicationInfo.dataDir + File.separator + "sample.mp4"

            val transformer = Transformer.Builder(context)
                .setTransformationRequest(transformationRequest)
                .addListener(object : Transformer.Listener {
                    override fun onTransformationCompleted(inputMediaItem: MediaItem, transformationResult: TransformationResult) {
                      super.onTransformationCompleted(inputMediaItem, transformationResult)
                    }

                    override fun onTransformationError(inputMediaItem: MediaItem, exception: TransformationException) {
                        super.onTransformationError(inputMediaItem, exception)
                    }
                }).build()
                transformer.startTransformation(inputMediaItem, outputPath)

        }
```

#### 内容
Transformer.startTransformationを使って動画をリサイズします。
RequestにはVideoのコーデックタイプ(主にMP4)
setAudioMimeTypeのコーデックタイプ(主にAAC)
setResolutionにビデオのサイズをセットします。 もう一辺は代表的なサイズで推論してる？のだと思います。
今回は1080pを720pにしたかったので1280をセット

あとは保存すべきUriを作りstartTransformation

処理が成功した場合、onTransformationCompleted
失敗したら、onTransformationErrorが返ってきます。

結果
1280*720の720pのMP4
総ビットレート4082kbps
19.96MB

結構小さくなりました。

#### 問題点
- Android13（SDK33）を要求される。
それですら実験的な機能なため、100％動作が保障されていない発展途上の状態な点

- APIの仕様がコロコロ変わる
まだまだ実験的なのでよくAPIの仕様が変わります。
onTransformationCompleted、onTransformationErrorは既に非推奨になってる。
バージョンアップ毎に確認が必要になりそう。

- 結局細かい指定ができないまま
ビットレートを落として容量をさらに調整したり、なんてことはできない。
どちらかというとこちらだけやりたいケースもありそうなのでこれは惜しい...。

#### 感想など
解像度を投げるだけで指定のサイズにリサイズによってファイル容量を多少落とした。
しかし、ビットレート、フレームレートを落とす術がないのがまだまだイマイチな点だと感じる。
 ~~そもそもこれが圧縮的な用途にも使えるのか知らない~~

まぁ結局のところMediaCodecAPIが複雑で使い勝手が悪すぎるのが諸悪の根源だと感じる...。
Media3については今後に期待です。
【備忘録】AWSタグ

# はじめに
AWSのタグについて、「じぶんの言葉で説明できる」をゴールとし、調べつつ整理しました。

# タグとは
* AWSのリソースを整理するためのもの
* ほとんどのリソースで作成時にタグ追加できる
* `キー`と`値`で構成される

# 一般的なユースケース
* リソースの整理
タグで**リソースを検索、フィルタリング**できる
リソースの**グループを作成**できる
`リソースグループ`と`タグエディタ`を使うことで、複数のサービス・リソース・リージョンで構成されるアプリケーションの**データを1つにまとめて表示**できる

* コスト配分
`AWS Cost Explorer`と`請求詳細レポート`を使い、**コストをタグ別に分類**できる

* オートメーション
**自動タスクの`オプトイン` `オプトアウト`**　※（承認、拒否？）
アーカイブ、更新、削除の対象となる**リソースのバージョンの特定**に使用する

以下、AWSドキュメントより抜粋
`オートメーションにした start または stop スクリプトを実行して業務時間外に開発環境をオフにすれば、コストが削減できます。このシナリオで Amazon Elastic Compute Cloud (Amazon EC2) インスタンスタグを使うと、このアクションからオプトアウトするインスタンスを簡単に指定できます。古くなった、out-of-date Amazon EBS スナップショットを検索して削除するスクリプトの場合、スナップショットタグで検索条件にディメンションを追加することができます。`

* アクセス制御
IAMポリシーで、**タグベースの条件**をサポート
特定のタグや、タグの値に基づいた**アクセス許可の制限**ができる

（例）`タグキー：Name`　`タグ値：test` のEC2インスタンスだけが**スタート・ストップ権限**
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:StartInstances",
                "ec2:StopInstances"
            ],
            "Resource": "arn:aws:ec2:*:*:instance/*",
            "Condition": {
                "StringEquals": {"ec2:ResourceTag/Name": "test"}
            }
        },
        {
            "Effect": "Allow",
            "Action": "ec2:DescribeInstances",
            "Resource": "*"
        }
    ]
}
```

# タグの命名制限と要件（要約）
* 各リソース最大50個のタグを持つことができる
* `aws:`で始まるタグはAWSに使用するために予約されている
* タグキーは、どれぞれリソース毎に一意であること
* `UTF-8`では
タグキー：1文字以上、最大128文字のunicode文字
タグ値　：0文字以上、最大256文字のunicode文字
* 使用できる文字はAWSのサービス毎に異なる(それぞれリソースドキュメントを参照)
* キーと値は、大文字と小文字で区別される

# コスト配分タグ

Billing > コスト配分タグ　より有効化できる。
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3501605/ddd684c1-5446-bf41-2a68-5b224604b4db.png)

* `AWS生成のタグ`と`ユーザ定義のタグ`の２種類が存在する
* CostExplorerやコスト配分レポートで使用するためには両方を有効化しておく

タグを有効化することで、有効化されたタグ毎に使用料・コストをグループ化した「コスト配分レポート」が作成される。これには利用中のすべてのサービスコストが出力され、リソース別の請求額を確認できる。

# 参考
* [AWS リソースのタグ付け](https://docs.aws.amazon.com/ja_jp/tag-editor/latest/userguide/tagging.html)
* [AWS リソースのタグ管理 〜タグ付けと統制〜（前編）](https://aws.amazon.com/jp/blogs/news/aws-tagging-and-governance-part1/)
* [AWS タグの活用方法と命名ルールを考える](https://dev.classmethod.jp/articles/aws-tagging-basic/) 
* [AWS コスト配分タグの使用
](https://docs.aws.amazon.com/ja_jp/awsaccountbilling/latest/aboutv2/cost-alloc-tags.html)