OmniAICreator/Qiita-1.07M huggingface dataset:
Ubuntu 20.04にOpenJDK 21をインストール（OS標準）

# はじめに

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

## サポート

~~[Java Is Still Free](いくつかのベンダがOpenJDK17の長期サポートを表明しているため、OS EOLとなる2025-04まではサポートされると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。~~

[OpenJDK\-Updates \- Ubuntu Wiki](https://wiki.ubuntu.com/OpenJDK-Updates) より、TLSバージョンとしてOS EOLまで保守されると思われる。

Extended Security Maintenanceで保守されるか不明。
[SecurityTeam/ESM/20\.04 \- Ubuntu Wiki](https://wiki.ubuntu.com/SecurityTeam/ESM/20.04) に記載される見込み。


## LOG

### インストール

```shell-session
# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.6 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.6 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

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

### 各種確認

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

# java -version
openjdk version "21.0.1" 2023-10-17
OpenJDK Runtime Environment (build 21.0.1+12-Ubuntu-220.04.1)
OpenJDK 64-Bit Server VM (build 21.0.1+12-Ubuntu-220.04.1, mixed mode, sharing)
```
Ubuntu 22.04にOpenJDK 21をインストール（OS標準）

# はじめに

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

## サポート

~~[Java Is Still Free](いくつかのベンダがOpenJDK17の長期サポートを表明しているため、OS EOLとなる2025-04まではサポートされると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。~~

[OpenJDK\-Updates \- Ubuntu Wiki](https://wiki.ubuntu.com/OpenJDK-Updates) より、TLSバージョンとしてOS EOLまで保守されると思われる。

Extended Security Maintenanceで保守されるか不明。
[SecurityTeam/ESM/22\.04 \- Ubuntu Wiki](https://wiki.ubuntu.com/SecurityTeam/ESM/22.04) に記載される見込み。


## LOG

### インストール

```shell-session
# cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.3 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.3 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

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

### 各種確認

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

# java -version
openjdk version "21.0.1" 2023-10-17
OpenJDK Runtime Environment (build 21.0.1+12-Ubuntu-222.04)
OpenJDK 64-Bit Server VM (build 21.0.1+12-Ubuntu-222.04, mixed mode, sharing)
```
作業用スクリプトファイルをHaskellで書く

# 作業用スクリプトファイルをHaskellで書く

スクリプトファイルの1行目をうまく書けばHaskellを作業用スクリプトファイルとして活用できることがわかったので、導入手順とテンプレートを残しておく。

## インストール

Haskellの処理系をインストールする

```sh
brew install ghc
```

## スクリプトファイル作成

Haskellの拡張子は`.hs`なので、`sample.hs`というファイルを作成する。

ファイルの中身は以下のようにする

```haskell
#!/bin/sh runghc

import System.Process
import System.Environment (getArgs)

main :: IO ()
main = do
    -- 引数取得
    args :: [String] <- getArgs
    print args
    -- プロセス実行
    (_, _, _, handler) <- createProcess (shell "ls")
    exitCode <- waitForProcess handler
    print exitCode
```

この状態で以下のコマンドを実行してファイルに実行権限を与える

```sh
chmod +x sample.hs
```

あとは以下のように実行すればOK

```sh
sample.hs
```

※ 拡張子は無くても動作するので `sample.hs` を `sample` とリネームしてもOKであるが
ファイルのメンテナンスを考慮すると拡張子があったほうが良い。
ESXiからProxmoxへのVM移行（Linux/Windows）

# はじめに

https://qiita.com/bashaway/items/8fb7195bd3601dcf7162

でインストールしたら、ESXiからVMを引っ越さないといけないので、これをやる。


# ESXi上のVMをエクスポートしてインポートする

## 準備（ovftoolのインストール）

proxmox上でESXiからOVFエクスポートする。
なので、proxmoxにログインして操作する。

VMware公式サイトからovftoolをインストールする。
https://developer.vmware.com/web/tool/4.6.0/ovf-tool
（4.6.2が出てましたが、試してません）


```:proxmoxで操作（proxmoxにovftoolをインストール）
apt install unzip -y
unzip VMware-ovftool-4.6.0-*.zip
```

## ESXiからエクスポートしてproxmoxにインポート

```:proxmoxで操作（ESXi上のVMをエクスポート＆インポート）
# OVF仮置き場を作成してそこに移動
mkdir /opt/ovf
cd /opt/ovf

# ESXi上のVMをエクスポート
/root/ovftool/ovftool vi://root@[ESXi-IP-ADDR]/[VM] .

# エクスポートしたovfをインポート
# VMIDは任意の数字 (100 - 999999999)
qm importovf [VMID] [OVF].ovf local-lvm  --format qcow2
```

```:たとえばこんな感じ（ESXi上の ca という名称のVMをエクスポート＆インポート）
# /root/ovftool/ovftool vi://root@10.254.254.xxx/ca .
Enter login information for source vi://10.254.254.xxx/
Username: root
Password: *********
Opening VI source: vi://root@10.254.254.xxx:443/ca
Opening OVF target: .
Writing OVF package: ./ca/ca.ovf
Transfer Completed
Completed successfully

# qm importovf 102 ca/ca.ovf local-lvm --format qcow2
  Logical volume "vm-102-disk-0" created.
transferred 0.0 B of 16.0 GiB (0.00%)
transferred 163.8 MiB of 16.0 GiB (1.00%)
..（省略）..
transferred 16.0 GiB of 16.0 GiB (100.00%)
```

# Linux(Ubuntu)の設定

インポートすると、NICが無くなるので、NICを追加してNW設定を修正すればOK

エクスポートしたてはこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334782/a7187e2c-98d7-26e8-ecba-89b7a5334b42.png)


NICがないので、ESXiと同じく vmxnet3 を追加する。
（タグVLANしてなければ空欄でOK）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334782/73e7d624-3a0f-ab41-cd4f-2daa6005de7c.png)

コンソールから立ち上げるとNICがens18になっている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334782/7c4cdfac-cbe9-fdcd-6b81-d27002862696.png)

netplanの設定を変更して反映させる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334782/c85b4127-ed46-957a-7a5d-d53f29982d15.png)


あとはproxmoxからゲストVMを操作するためにguestエージェントをインストールする

```:ゲストVMで操作
sudo apt install -y qemu-guest-agent
sudo systemctl enable qemu-guest-agent
sudo systemctl start qemu-guest-agent
```


# Windowsの設定

NIC追加のみで実施したら以下のようなエラーがでてしまった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334782/8f43b8db-e599-b665-0bd2-337a6237e561.png)

ので、SCSIコントローラを VMware PVSCSI に変更する。

以下のISOを利用してvirtioドライバをインストールする

https://pve.proxmox.com/wiki/Windows_VirtIO_Drivers

一度適当な大きさのダミーディスクを追加して起動すると、インストールされたドライバが使われる（？）ようになるので、ディスクが認識されたらシャットダウンする。

すると、NICもDISKもvirtioで動作させられるようになる。
NICはモデルをVirtIO（準仮想化）にすればOK。
OSディスクは、一度デタッチして virtio に変更してからアタッチして起動すればOK。

ゲストエージェントは以下を利用すればよい。

https://pve.proxmox.com/wiki/Qemu-guest-agent
Java学習 繰り返し処理 for文

javaでは繰り返し処理を行うとき下記の2種類がある。
* for文
* 拡張for文

今回はfor文についてまとめてみる。

# for文
## for文を実行

```java
class Main {
  public static void main(String[] args) {
    
    int sum = 0;
    for (int i=1 ; i<=10 ; i++){
    sum += i;
    }
    System.out.println("1から10までの合計は" + sum );
  }
}
```

実行結果
```
1から10までの合計は55
```


# for文の使い方
for文の構文
```java
for(初期化式; 条件式; 変化式;){
    実行する処理
}
```

### for文の「初期化式」「条件式」「変化式」について
初期化式：変数の初期化に使われる。最初に1度だけ実行される。
条件式：処理を繰り返し行う条件を指定する。
変化式：条件式で使用している変数の値を変更するときに使用する。中括弧内の処理が実行されるたびに変化式も実行される。

```java
for (int i=1 ; i<=10 ; i++){
    sum += i;
    }
```    
上記のコードの場合
初期化式：`i = 1` 繰り返し処理の始めに i に 1 を代入。
条件式：`i<=10` i が 10以下の場合は繰り返し処理を行う。
変化式：`i++` 処理実行後、i に 1 を足して次の処理に移る。
Zabbix リモートコマンドの実行方法

# はじめに
この記事を作成した意図は、現在Zabbixを扱うシステム設計構築に携わっている為、自身への備忘録として残すことが目的である。
また、Zabbixの機能として大変便利なものである為、初学者やZabbixを業務で扱っている方のためになれば幸いである。

# 環境
|  仮想環境 |  VMware Workstation Player 16    |
| ---- | ---- |
|  Zabbix |  6.0LTS   |
|  OS (マネージャ） |  RHEL8    |
|  OS (エージェント） |   Windows Server 2019   |

# 設定手順

### 1.Zabbix Agentのコンフィグ

まず、リモートコマンドの実行者として選べるのが
- **Zabbixエージェント**
- **Zabbixサーバーまたはプロキシ**
- **Zabbixサーバー**

上記の３つとなるが、今回は　**Zabbixエージェント（監視対象）**　に実行させることが前提となる。

監視対象の**zabbix_agentd.conf**に以下の通り、下記文言を書き加える。

AllowKey=system.run[*]

```
### Option: EnableRemoteCommands - Deprecated, use AllowKey=system.run[*] or DenyKey=system.run[*] instead
#	Internal alias for AllowKey/DenyKey parameters depending on value:
#	0 - DenyKey=system.run[*]
#	1 - AllowKey=system.run[*]
#
# Mandatory: no
AllowKey=system.run[*]
```

この設定を行わないとリモートコマンドを実施することは出来ない為注意。
また、Zabbix Agentの再起動を行わないと設定が反映されないので注意。


### 2.スクリプトを作成 ###

次にZabbixマネージャのコンソールから、実行したいコマンドのスクリプトを作成する。

### 2-1 ###
コンソール画面「**管理**」→「**スクリプト**」を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3600322/a7901b85-ac66-3a83-531b-cbdd07887ac3.png)

### 2-2 ###

画面右上「**スクリプトの作成**」を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3600322/5065101a-db61-bdcc-01bd-e6eef87a2d7e.png)

### 2-3 ###

**名前**：任意
**範囲**：手動ホスト処理
**メニューパス**：※後ほど解説
**タイプ**：スクリプト
**次で実行**：Zabbixエージェント
**コマンド**：任意
※対象サーバのOSが認識できるコマンドを指定すること
```
echo helloworld
```
**説明**：任意
**ホストグループ**：すべて
**ユーザーグループ**：すべて
**必要なホストへのアクセス権**：表示のみ
**確認を有効**：チェック外す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3600322/ed70c76f-1638-50e0-bfab-93193d3830eb.png)

設定が完了したら「**更新**」を選択。

以上で下準備は完了！！
めちゃくちゃ簡単ですね。

### 3.実行 ###

### 3-1 ###
「**監視データ**」→「**ホスト**」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3600322/af008aef-35f8-a2c8-49d6-073063024414.png)

### 3-2 ###
リモートコマンドを実行したいホスト名を左クリックし、実行したい**スクリプト**を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3600322/5a43a3c9-d1ac-4582-3a04-9bb9eb0a29b2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3600322/1216d760-582e-edd8-2481-680abc5baeb7.png)

以上のように簡単にリモートコマンドを実行できちゃいます！


### 4.おまけ ###

**2-3**で設定項目にあったメニューパスに関して解説を致します。

以下の様に**メニューパス**に任意の文字を指定すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3600322/19f866cf-124a-4479-9e7a-11a9c148a08d.png)

この様に階層化ができます。スクリプトの整理が簡単にできちゃいますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3600322/66f8cc79-abd5-1663-6c65-9dbcfd30384f.png)


### 5.最後に ###

私も最近Zabbixに触れ始めたばかりでまだまだ初心者です。
今後も実務を通し何か便利な機能があれば発信していこうかと考えています（上手く組み合わせたトリガー等）
jUnitを作成するときのTips

テストコードを作成する際のTipsをまとめておこうと思う。

テストコードはしっかり組むべきではあるが、たまにカバレッジを達成するためだけに
テストコードを書く必要のあるタイミングがあるので
それ用にアプローチや作成方法などをまとめた。

## テストクラスの対象で、別クラスをnewしてインスタンス作っている場合

### 案1：インスタンス作成を該当クラスに移す。

```
// setterでインスタンスを作成するように変える
private クラス 変数名

public void setInstance() {
    this.変数名 = new クラス()
}

public クラス getInstance() {
    return this.変数名
}
```

### 案2:　mockConstructionを利用して、newInstanceのモックを作る

下記のようにmockConstructionを利用して、new Instanceの部分をモックにすることで一応可能。
一部だけモックにしたい場合は、`withSettings().defaultAnswer(CALLS_REAL_METHODS)`を利用して、実際の処理を動かすようにしよう。
```
//
try (MockedConstruction<クラス> mockedClass =
        Mockito.mockConstruction(クラス.class, 
        (mock, 
        //下に記述したスタブ以外のメソッドをモックではなく実態で処理させるための設定
        withSettings().defaultAnswer(CALLS_REAL_METHODS)
        context) -> {
          //スタブにしたいメソッド(羅列可能)
          Mockito.doReturn(適当な戻り値).when(mock).メソッド();
          Mockito.doReturn(適当な戻り値).when(mock).メソッド();
          ....
        }); // 1-1
    ) {
        //テストを実行
    }
```

もしdefaultAnswerを利用する場合は、以下の記事で描かれてある通りスタブの記述の仕方に注意

https://qiita.com/tamanugi/items/0944100548b4e19b9688

### 案3：@Inject を利用して依存性を注入する
本来あるべき姿はおそらくこれだと思う。
こうすることで、テストのときに依存するクラスのインスタンスを無理矢理コントロールさせるなどが必要なくなるはず。

## staticのメソッドを処理する場合

### mockStaticを使う

```
//
try (MockedStatic<クラス> mockedClass =
        Mockito.mockStatic(クラス.class)
    ) {
        //staticメソッドのスタブを作る
        mockedClass.when(
            () -> クラス.staticメソッド()).thenReturn(戻り値)
        //テストを実行
    }
```

## finalクラス

そもそもFinalクラスをモック化する必要がある実装が良くない…という話も多分あると思う。

### 案1：ラップするクラスを作る
おそらくこれが最善の策かと思われる？

### 案2:mockConstructionを使う

同じく`mockConstruction`を使えば、理屈上可能ではあるが
このFinalクラスになっているものは色んなソースで呼ばれていると思われるので、別のクラスで異常終了してしまう可能性がある。

## private, protectedのメソッド、フィールド変数をテストする場合

privateなフィールド変数に依存しているクラスはそこそこあると思うので
フィールド変数を設定するテストコードは割と書くかもしれない

### リフレクションを使う

#### フィールド変数を設定する場合

```
//テストしたいクラスのインスタンス作成
テストしたいクラス test = new テストしたいクラス();
// private変数のフィールドを取得
Field field = test.getClass().getDeclaredField("privateなフィールド変数名");
// private変数へのアクセス制限を解除
field.setAccessible(true);
// 値を書き換え
field.set(target, 設定したい値);
```

#### フィールド変数を取得する場合

getterがあるなら、getterを利用するべき。
ないなら極力入れたほうがよい。

一応やるなら下記でできるはず

```
//テストしたいクラスのインスタンス作成
テストしたいクラス test = new テストしたいクラス();
// private変数を受け取りたい場合
Field field = test.getClass().getDeclaredField("privateなフィールド変数名");
// private変数へのアクセス制限を解除
field.setAccessible(true);
// 値を取得
field.get(test);
```

#### private, protectedメソッドを呼び出す場合

以下で実行し、テストを実行はできる。
が、そもそもprivateメソッドをテストしなければいけないとなるとソースのリファクタリングを考えるべき。

おそらく、メソッド内の処理がごっちゃになっているか、うまく分割ができていない。

```
テスト対象クラス test = new テスト対象クラス();
Method method = テスト対象クラス.class.getDeclaredMethod("<メソッド名>", 引数の型1, 引数の型2...);
method.setAccessible(true);
int actual = (戻り値の型)method.invoke(<インスタンス>,引数1,引数2...);
```


## voidメソッドに対しての検証
基本的にvoidと言っても、privateフィールド変数への設定や、ログ出力などの処理をしているはず。
おおよそ以下のことをテストすることになるはずだ。

- メソッドの呼び出し回数をチェックする
- フィールド変数に設定するなら、その設定が予想通りかを検証する 
- ログに出力するメッセージをチェックする

## できないテストはもちろんある
例えば、実際にHTTPリクエストを送信してどんな結果を返しても大丈夫か？みたいなテストをするなら
実態を知らないと想定値や実際のリクエストを書くことはできない

また、それらは環境が影響し予想外の結果が返ってくる可能性もある。
そうなるとさすがにテストコードではなく、実際にリクエストを渡した方がいい。

カバレッジを全部で〇〇％や、100％担保するとかなっているなら
モックして適当なテストを書いて、実際のテストもやる…みたいなことをする必要があると思われる。
Core ML モデルのメタデータを編集する

変換元のリポジトリとかライセンスとか書くのに便利

```python
import coremltools as ct

model =  ct.models.MLModel('LaMa.mlpackage')

# Set the model metadata
model.author = 'https://github.com/advimman/lama'
model.license = 'Apache2.0 License'
model.short_description = 'LaMa: Resolution-robust Large Mask Inpainting with Fourier Convolutions.'


# Get the interface to the model
model.input_description
model.output_description

# # Set feature descriptions manually
# model.input_description['input'] = "input image of scene to be classified"
# model.output_description['output'] = "Probability of each category"

# Save the model
model.save('lama.mlpackage')
```

🐣
****
フリーランスエンジニアです。
AIについて色々記事を書いていますのでよかったらプロフィールを見てみてください。

もし以下のようなご要望をお持ちでしたらお気軽にご相談ください。
AIサービスを開発したい、ビジネスにAIを組み込んで効率化したい、AIを使ったスマホアプリを開発したい、
ARを使ったアプリケーションを作りたい、スマホアプリを作りたいけどどこに相談したらいいかわからない…

いずれも中間コストを省いたリーズナブルな価格でお請けできます。

お仕事のご相談はこちらまで
rockyshikoku@gmail.com

機械学習やAR技術を使ったアプリケーションを作っています。
機械学習／AR関連の情報を発信しています。

[X](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
(解決済み) [悲報] WSL2 がハングアップした時の備忘録

# それは突然に？？

いつもローカルで開発をしていて以下のツールを使ってます

- docker desktop
- WSL 2
- vscode

前からその兆候はあったもののそれは突然でした。
WSL 2 を起動すると、VmmemWSL というプロセスがWSL 2 上にひょこんと現れると思います。

docker desktop を立ち上げて、docker を起動して、よし開発しようと思っていた矢先、、、タスクマネージャーを見ると、ディスクが100%!!???

vscode がフリーズして、

    > wsl --shutdown

のコマンドをpowershell からたたき続ける。本当にとほほって感じでした。

# なんで起こったのかな？？

disk が急に100% になる現象なんて見たことないぞと思いましたが、原因が分からず、
docker volume が悪さしてるのかな？？とかcontainer image ?? とか全然検討違いの所を見ていました。

結論、原因はメモリ不足でした。

    top -c
をWSL 上で叩いてみると、メモリが97% swap が99%。。。。おっと。。。
これはhung up 寸前ではありませんか。

# 解決方法

今までは、.wslconfig でかなりメモリの制限をしてました

    [wsl2]
    memory=2GB

これでは全然足りなかったみたいです。
なので、この上限をあげて、様子を見ることにしました。


    [wsl2]
    memory=3GB
    swap=3GB

これくらいにしてみるかと。設定を変更してあげて、wsl の再起動をして反映させてあげます。これで反映させてからは、WSL2 で安定して開発をすることができました。

# まとめ

皆さんもdocker desktop で環境構築をする場合はWSL2 を使ってると思います。もしかしたら、自分のPC のスペックにもよるかもしれませんが、WSL 2 のプロセスでdisk100% になって困っているという方がいましたら .wslconfig で色々リソースの値を変えて試してみることをお勧めします。

(注意)*他にもいいやり方があるかもしれません
Livebookプラグイン開発①：コード実行時、好きな出力にアレンジする

[piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

@RyoWakabayashi さんの下記コラムで紹介されているLivebookプラグイン「kino_benchee」のソースコードを見て、Livebookプラグインを開発するのがカンタンだということが分かったので、試しに作ってみました

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

# Livebookプラグインを作る

PJを作成します

```
mix new kino_httpoison
cd kino_httpoison
```

Kinoを使えるようにします

```diff_elixir:mix.exs
 defmodule KinoHttpoison.MixProject do
…
  defp deps do
    [
      {:kino, "~> 0.12"}
…
```

`HTTPoison.Response` がLivebookコードブロック上で返却されたときに走る `Kino.Render` を作ります

Livebookプラグインが無効なときは、下記のような表示です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/1da4aea3-dd6f-fce0-ed17-9bfb69acb6e7.png)

これを、`headers` や `body` を「content」タブ、それ以外の情報を「attribute」タブに表示するコードは、下記の通りです

```diff_elixir:lib/render.ex
defimpl Kino.Render, for: HTTPoison.Response do
  def to_livebook(httpoison) do
    header = httpoison.headers
      |> Enum.map(fn {k, v} -> %{key: k, value: v} end)
      |> Kino.DataTable.new(name: "header")

    content = Kino.Layout.grid([header, httpoison.body |> Jason.decode!])

    request = httpoison.request
      |> Map.from_struct
      |> Enum.map(fn {k, v} -> %{key: k, value: v} end)
      |> Kino.DataTable.new(name: "request")

    attribute = Kino.Layout.grid([httpoison.request_url, request, httpoison.status_code])

    Kino.Layout.tabs(content: content, attribute: attribute)
    |> Kino.Render.to_livebook
  end
end
```

ここで、`Kino.Layout.tabs` はLivebook上でタブを出力し、`Kino.Layout.grid` は複数の表示エリアを区切り、`Kino.DataTable.new` はテーブル出力を行う処理です

これらで構成されたパーツ群を `Kino.Render.to_livebook` で返すと、Livebookコードブロック上で `HTTPoison.Response` が返却されたときに表示されるようになります

なお、VegaLiteによるチャートやEvision／Image（vix）の画像、MapLibreの地図など、Livebook上で表示できる形式であれば、何でも乗せることができるので、「kino_benchee」のような美しいグラフ化も簡単に実現できます

# Livebookで作成したLivebookプラグインを使う

下記のように、ローカルに置いているLivebookプラグインをロードできます（Livebook起動フォルダからの相対パスを指定してください）

なお、`mix hex.publish` でのOSS化や、Githubからのロード等も、Livebookプラグインを各々にアップすれば可能です

```diff_elixir:Reconnect and setup
Mix.install([
  {:httpoison, "~> 2.0"},
  {:jason, "~> 1.4"},
  {:kino_httpoison, path: "../kino_enumurable"},
])
```

`HTTPoison.Response` を返すコードブロックを実行します

```diff_elixir
HTTPoison.get!("https://api.github.com/repos/wojtekmach/req")
```

すると、「content」タブには、`headers` や `body` が下図のように整形されて表示されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/328b06b1-163e-4311-4cf0-be505b4e258b.png)

それ以外の情報は「attribute」タブにやはり整形されて表示されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/4f268a66-9980-c405-41cf-21f503ddcad1.png)

こんな簡単なコードでLivebookプラグインが実現できます、すばらしい
p5.js のフィルター用シェーダー「createFilterShader()」を使ってメインキャンバスとオフスクリーンキャンバスの描画をまぜる

## はじめに
以下の「p5.js の createFilterShader()」を扱った　3つの記事に引き続き、また 「createFilterShader() を扱います（この createFilterShader() を使ったシェーダーをあれこれ試すことに、個人的にハマり中ですｗ）。

- [p5.js の createFilterShader() を使ったフィルター用シェーダーのお試し - Qiita](https://qiita.com/youtoy/items/1083d6319ddab6d525d3)
- [p5.js のフィルター用シェーダー「createFilterShader()」で座標情報を使った着色のお試し - Qiita](https://qiita.com/youtoy/items/b06e65d20aa2f468b8bb)
- [p5.js のフィルター用シェーダー「createFilterShader()」で座標情報を使った着色のお試し 〜その2〜 - Qiita](https://qiita.com/youtoy/items/9ee8385e2134a09de665)

今回は、以下の内容をやろうとした過程で、試した内容の 1つです。
（以下は、今回のオフスクリーンキャンバスの描画をシェーダーで使うという内容に加えて、カメラ画像を使った処理なども組み合わせています）

<iframe width="560" height="315" src="https://www.youtube.com/embed/YpPxT0Agc-M?si=wR24BE5C-3yMI6Z2" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

## 試す内容
今回試すのは、フィルター用シェーダー「createFilterShader()」を使った処理で、「メインキャンバスの描画内容をシェーダーに渡して処理するだけでなく、とオフスクリーンキャンバスの描画をまぜる」というものです。

「createFilterShader()」を使う場合、メインキャンバスの内容はデフォルトで利用できる形（シェーダーの中で `tex0` という記載で取得できる形）ですが、オフスクリーンキャンバスもシェーダー内で利用できる形にします。
そして、そのようにしてシェーダーに渡した　2つのキャンバスの内容を、シェーダーの中で扱う処理を試していきます。

### 書いたプログラム
今回書いたプログラム全体は、以下の通りです。

```javascript
let pg;
let s;

function setup() {
  let fragSrc = `precision highp float;

  varying vec2 vTexCoord;
  uniform sampler2D tex0;

  uniform sampler2D tex1;

  void main() {
    vec4 color = texture2D(tex0, vTexCoord);
    vec4 color2 = texture2D(tex1, vTexCoord);

    gl_FragColor = vec4(color.rgba + color2.rgba);
  }`;

  createCanvas(400, 300, WEBGL);
  background(0);
  noStroke();
  fill(100, 50, 50);
  rect(-50, -50, 200, 150);

  pg = createGraphics(width, height);
  pg.noStroke();
  pg.fill(100, 150, 200);
  pg.circle(120, 120, 190);

  s = createFilterShader(fragSrc);
  s.setUniform("tex1", pg);

  filter(s);
}
```

#### ポイントになる部分
今回のポイントになる部分は、以下です。

```javascript
  s.setUniform("tex1", pg);
```

`pg = createGraphics(width, height)` として作成したオフスクリーンキャンバスを、シェーダーに渡します。

シェーダーでそれを受けとる側は、以下とすれば OK です。

```javascript
  uniform sampler2D tex1;
```

あとは、何らかのシェーダー内での処理を実装して、メインキャンバスの内容とオフスクリーンキャンバスの内容を両方使えているかを確認します。
今回は以下のように、2つのキャンバスのピクセルの値を単純に加算する、というシンプルな内容で試しています。

```javascript
  void main() {
    vec4 color = texture2D(tex0, vTexCoord);
    vec4 color2 = texture2D(tex1, vTexCoord);

    gl_FragColor = vec4(color.rgba + color2.rgba);
  }
```

### 実行結果
上記を実行した結果は以下になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/f1a4b9cb-5255-a407-a5db-9f1946465ab3.png)

2つのキャンバスで行った描画に関しては、以下のように、メインキャンバスとオフスクリーンキャンバスのそれぞれで、特定の色で図形を描画しています。
そして、それをシェーダーで処理した結果が上に示したとおりなのですが、 `blendMode(ADD)` を使ったのと同じように加算合成を行った見た目になりました。

```javascript
  createCanvas(400, 300, WEBGL);
  。。。
  fill(100, 50, 50);
  rect(-50, -50, 200, 150);

  pg = createGraphics(width, height);
  。。。
  pg.fill(100, 150, 200);
  pg.circle(120, 120, 190);
```
MisskeyApi備忘録

:::note warn
注意
自身の備忘録として作成しているのであまりアテにしないで下さい
またAPIは[Misskey-dev](https://github.com/misskey-dev/misskey)のリポジトリを参照しています。
Misskey.io等、カスタマイズされているインスタンスや、バージョンの古いMisskeyサーバーを使用している場合、
記載している内容が正しくても意図しない情報やそもそも取得が出来ない可能性もありますが苦情は辞めてください。
（動作確認した上で編集リクエストを頂ければ、こちらでも**やる気**があれば確認して反映します）
:::

:::note alert
過信しないで
自身がアプリケーションを作成する際の備忘録として作成している為、必須パラメーター以外で使っていない物は
基本**記載していません**。
:::

# 通知

## 通知作成

**リクエスト**

<https://misskey.io/api/notifications/create>

| 要素 | 説明|
| :--- | :--------------------- |
| i    | ユーザートークン       |
| body | （必須）通知に送る本文 |
| header | タイトル |
| icon | 画像 |

**レスポンス**

成功時ステータスコード204

**イメージ**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176908/28363a76-7957-4d9e-377f-8060e8f513cc.png)

## 通知取得

**リクエスト**

:::note warn
URLの`i`はトークンに置き換える必要あり
:::

<https://misskey.io/api/i/notifications>

| 要素 | 説明|
| :--- | :--------------------- |
| i    | （必須）ユーザートークン       |
| limit | 取得件数（1~100、デフォルト10）|
| sinceId | 対象ユーザーID（IDは@から始まる物では無くユーザーに一意に付与されているID） |
| untilId | 除外ユーザーID（IDは@から始まる物では無くユーザーに一意に付与されているID） |
| markAsRead | 既読フラグ（デフォルトtrue） |
| includeTypes | 取得に含める通知の種類、[詳細はioのドキュメント参照](https://misskey.io/api-doc#tag/account/operation/i/notifications) |
| excludeTypes | 取得から除外する通知の種類、[詳細はioのドキュメント参照](https://misskey.io/api-doc#tag/account/operation/i/notifications) |

**レスポンス**

成功時ステータスコード200

| 要素 | 説明|
| :--- | :--------------------- |
| id    | （必須）通知固有のID|
| createdAt | 通知作成日時|
| type | 通知の種類、[詳細はioのドキュメント参照](https://misskey.io/api-doc#tag/account/operation/i/notifications) |
| body | 通知本文 |
| header | 通知タイトル |
| icon | 通知の画像 |
reduce()の使用方法を理解しよう！〜AtCoderのSome Sums問題を解こう〜

# reduce( )とは

```Swift
func reduce<Result>(
    _ initialResult: Result,
    _ nextPartialResult: (Result, Self.Element) throws -> Result
) rethrows -> Result
```
`initialResult`: **初期値**
`initialResult`は、クロージャが最初に実行されたときに`nextPartialResult`に渡されます。

`nextPartialResult`: **結果**
次の`nextPartialResult`クロージャの呼び出しで使用されるか、呼び出し元に返されます。
引数ラベルを省略し、トレイリングクロージャで使用もできます！

**参考文献**:

https://developer.apple.com/documentation/swift/string/reduce(_:_:)

# reduce()をArray型で使用する！
```Swift
let nums = [1,2,3,4,5]
let result = nums.reduce(0) { sum, num in
    let result = sum + num
    //🟩　print(result)
    return result
}
print(result)
```
**出力結果**
```
55
```
🟩 **print(result)の出力結果**
```Swift
1 //sum + num : 0 + 1 = 1
3 //sum + num : 1 + 2 = 3
6 //sum + num : 3 + 3 = 6
10 //sum + num : 6 + 4 = 10
15 //sum + num : 10 + 5 = 15
```
`reduce(0)`:初期値は０
`nums`: 読みこむ配列
`sum`: 現時点の合計
`num`: 一つの要素
`result`: 結果



# reduce()をString型で使用する！
```Swift
let numString = "12"
let result = numString.reduce(0) { sum, num in
    let result = sum + Int(String(num))!
    //🟩print(result)
    return result
}
print(result)
```

**出力結果**
```
3
```

🟩 **print(result)の出力結果**
```Swift
1 //sum + num : 0 + 1 = 1
3 //sum + num : 1 + 2 = 3
```
`reduce(0)`:初期値は０
`nums`: 読みこむ
`sum`: 現時点の合計
`num`: 一つの要素
`result`: 結果

# AtCoderのSome Sums問題を解いてみる！

https://atcoder.jp/contests/abs/tasks/abc083_b

```Swift
func readInts() -> (a: Int, b: Int, c: Int) {
    let value = readLine()!.split(separator: " ").map { Int(String($0))! }
    return (a: value[0], b: value[1], c: value[2])
}

func main() {
    let (N, A, B) = readInts()
    var sum = 0
    for i in 1...N {
        let result = String(i).reduce(0) { (sum, num) in sum + Int(String(num))! }
        if A <= result, result <= B {
            sum += i
        }
    }
    print(sum)
}

main()
```

入力例
```
20 2 5
```
N: 20以下の整数のうち、各桁の和が A: 2 以上 B: 5 以下なのは、
2,3,4,5,11,12,13,14,20 です。これらの合計である 84 を出力します。


出力例
```
84
```


# 参考文献

https://egg-is-world.com/2020/07/15/swift-reduce/
【SwiftUI】棒グラフを選択できるようにする

# はじめに
前回、円グラフを選択できるようにしました

https://qiita.com/SNQ-2001/items/6608c9bd77d49e03efe0

今回は棒グラフを選択できるようにしてみます。

# サンプルアプリ
![Simulator Screen Recording - iPhone 15 - 2024-01-19 at 20.51.46.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/45f9e59b-92e0-f7e4-d616-20581f51cae6.gif)

# 実装
```diff_swift
import SwiftUI
import Charts

struct Temperature {
    let day: Int
    let max: Double
    let min: Double
}

struct ContentView: View {
    @State private var temperatures: [Temperature] = [
        .init(day: 1, max: 17, min: 13),
        .init(day: 2, max: 25, min: 10),
        .init(day: 3, max: 12, min: 11),
        .init(day: 4, max: 21, min: 11),
        .init(day: 5, max: 10, min: 6)
    ]
    
+   @State private var selectedDay: Int?
    
    var body: some View {
        Chart {
            ForEach(temperatures, id: \.day) { temperature in
                BarMark(
                    x: .value("day", temperature.day),
                    y: .value("max", temperature.max),
                    width: 30
                )
                .opacity(selectedDay == nil ? 1.0 : temperature.day == selectedDay ? 1.0 : 0.3)
            }
        }
+       .chartXSelection(value: $selectedDay)
        .frame(width: 300, height: 300)
    }
}
```

# おわり
今回の棒グラフは縦なので`chartXSelection(value:)`を使用しています。
棒グラフが横の場合は`chartYSelection(value:)`で同じことができます。
Java学習 繰り返し処理 拡張for文

# 繰り返し処理の種類

javaでは繰り返し処理を行うとき下記の2種類がある。
* for文
* 拡張for文

拡張for文は、Rubyでのeachメソッドに似た機能を持っている。
Rubyのeachメソッドとは書き方が異なるが、使い方は似ている。

# 拡張for文

## 拡張for文を実行

### 配列から要素を取り出す
```java
class Main {
  public static void main(String[] args) {
    int[] scores = {1, 2, 3, 4, 5};

    for(int score : scores) {
      System.out.println(score);  
    }
  }
}
```

実行結果
```
1
2
3
4
5
```

### ArrayListから要素を取り出す場合
ArrayListから要素を取り出す場合も使い方は同じ。

```java
import java.util.ArrayList;

class Main {
  public static void main(String[] args) {
    ArrayList<Integer> scores = new ArrayList<Integer>();

    scores.add(2);
    scores.add(3);
    scores.add(5);
    scores.add(7);
    scores.add(11);
    scores.add(13);

    for(int score : scores) {
      System.out.println(score);  
    }
  }
}
```

実行結果
```
2
3
5
7
11
13
```

# 拡張for文の使い方
拡張for文の構文

```java
for ( 要素を格納する変数を宣言  :  配列あるいはArrayListの変数名) {
  取り出した要素を使用して行う処理を記述
}
```

この記述を行うと、以下のような流れで動作する。

1. 配列、もしくはArrayListから要素を1つ取り出す。
2. 取り出した要素を変数に代入する。
3. {}内の処理を行う。
4. 配列、もしくはArrayListの要素数分だけ処理を繰り返す。

```java
for(int score : scores) {
  System.out.println(score);  
}
```
上記のようなコードは、変数scoresから要素を取り出し、int型の変数scoreに代入するという動作になっている。
Chrome拡張でVOICEVOXに読み上げさせるためにはdeclarativeNetRequestでOriginを削除したりsendMessageでやり取りする必要がある

# まとめ
declarativeNetRequestでOriginを削除することで、利用者に手間をかけさせずVOICEVOXのAPIを利用することができる。

VOICEVOXのissueにもそういった対策が書かれているが、気づきにくいので本記事を書いて知見として残しておく。

https://github.com/VOICEVOX/voicevox_engine/issues/392#issuecomment-1336530512

またオーディオの再生まわりでも色々な制限が出て来るのでそれについても書いておく。

# 解説
## VOICEVOX側での制限
VOICEVOXのエンジンではCORSの範囲の範囲を制限しておりそのままではブラウザ拡張からのAPI呼び出しが弾かれる。

https://github.com/VOICEVOX/voicevox_engine/issues/392

一応エンジン側にて許可するOriginを追加することができるようになっているが、利用者に `chrome-extension://...` を追加してもらうというのは手間がかかるし好ましくない。

https://github.com/VOICEVOX/voicevox_engine?tab=readme-ov-file#cors-%E8%A8%AD%E5%AE%9A

## declarativeNetRequest
Chrome拡張側でfetch等のリクエストに対して細工を行うための機能が存在する。こちらで細工を行ってVOICEVOXが通してくれるリクエストを投げるようにする。

https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest?hl=ja

これによってbackgroundからVOICEVOXのAPI呼び出しが通るようになる。

## 設定例
```json:manifest.json
{
  "permissions": [
    "declarativeNetRequest"
  ],
  "host_permissions": [
    "*://localhost/*"
  ],
  "declarative_net_request": {
    "rule_resources": [
      {
        "id": "ruleset",
        "enabled": true,
        "path": "rules.json"
      }
    ]
  }
}
```
```json:rules.json
[
  {
    "id": 1,
    "priority": 1,
    "action": {
      "type": "modifyHeaders",
      "requestHeaders": [
        { "header": "Origin", "operation": "remove" }
      ]
    },
    "condition": {
      "urlFilter": "localhost"
    }
  }
]
```

## backgroundではAudioContextが利用できない
ブラウザで音声を再生するにはAudioContextを利用するのがお手軽そう。

https://developer.mozilla.org/ja/docs/Web/API/AudioContext

しかしbackgroundはManifest V3からServiceWorkerとなっているためページを持たなくなり、AudioContextも利用できなくなっている。

そのためoffscreenだったりcontent_scriptsを活用してページ側で音声を再生する必要がある。やり取りにはsendMessageを利用する。

https://developer.chrome.com/docs/extensions/reference/api/runtime?hl=ja#method-sendMessage

ちなみに最初からページ側でAPIリクエストも行っていくというのはOriginヘッダの除去がcontent_scriptsでは機能しないためダメです。(offscreenは未検証)

## メッセージはJSON対応のオブジェクトである必要がある
ArrayBufferをそのまま送ろうとしても失敗する。sendMessageはJSONとして取り扱えるプリミティブなデータしか取り扱えない。そのため送受信で変換する必要がある。

```js:送信側
Array.from(new Uint8Array(arrayBuffer));
```
```js:受信側
const arrayBuffer = Uint8Array.from(array).buffer;
```
```js:再生
let currentSourceNode;

const context = new AudioContext();
const gainNode = context.createGain();
gainNode.connect(context.destination);

context.decodeAudioData(arrayBuffer).then(decoded => {
    if (currentSourceNode) {
        currentSourceNode.stop();
        currentSourceNode.disconnect();
    }
    const sourceNode = context.createBufferSource();
    sourceNode.connect(gainNode);
    sourceNode.buffer = decoded;
    sourceNode.start(0);
    currentSourceNode = sourceNode;
});
```
BizRobo!の繰り返し処理とは~ループとリピートの違い~

就業先では、RPAツールのBizRobo!を使用しています。BizRobo!開発で悩み、BizRobo!ナレッジベースで日々検索しています。

特定の作業を繰り返す作業が得意であるRPA。
BizRobo!でも他のRPAと同じく、繰り返し処理に対応しています。しかし、BizRobo!には繰り返しに対応しているステップが複数あり、自分が間違えてステップを使ってしまうことがありました。

今回は、BizRobo!の繰り返し処理について共有いたします。

※時間が経過して変わってしまった箇所や間違っている箇所、不適切な表現があるかもしれませんが、その時は都度修正いたしますので、ご指摘いただけると幸いです。

## 繰り返し処理の種類
ナレッジベースの下記から引用いたします。
[ロボットフローを理解する（繰り返し処理）](https://knowledge.bizrobo.com/hc/ja/articles/8116467954329)

>「○○ループ（Loop～）」ステップ
>「○○繰り返し（For Each～）」ステップ
>「繰り返し（Repeat）」ステップ
>「次へ（Next）」ステップ

Loopステップ、For Eachステップ、Repeatステップの3種類を説明します。
※Nextステップは、Repeatステップと一緒に使用するため、Repeatステップに含めます。

また、ループの全ステップは下記となります。
※私が持っているBizRobo!バージョンは、10.3.0.7です。
<img width="75%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955689/b81d3933-1c9e-f413-4713-77187589a851.png">


## 「○○ループ（Loop～）」ステップとは
各ステップ名に「ループ」があるステップが、対象になります。
「Excel内ループ」と「フィールド値ループ」の2つあります。

Excelファイルの行、列、セル、シートを対象に、繰り返し処理を行うことができます。
詳細は下記をご参照ください。
[「Excel 内ループ(Loop in Excel)」ステップ](https://knowledge.bizrobo.com/hc/ja/articles/360052096491)

「フィールド値ループ」は使用したことがないため、解説できません。

## 「○○繰り返し（For Each～）」ステップとは
各ステップ名に「ループ」があるステップが、対象になります。
様々な種類が存在しますが、今回は「部分文字列繰り返し（For Each Text Part）」ステップを説明します。

下記のようなCSVファイルが存在したとします。
```
1,2,last
```
「,」という区切り記号をパターンとして認識し、区切り記号が終わるまで繰り返し処理を行います。ループ処理を行った場合、取得できる値は下記となります。
1回目：1
2回目：2
3回目：last

詳細は下記をご参照ください。
[「部分文字列繰り返し（For Each Text Part）」ステップ](https://knowledge.bizrobo.com/hc/ja/articles/360051478931)

また、このステップを用いた、よく使用されるロジックの記事を見つけましたので、ご参考ください。
[CSVファイルのデータを全て取得し、項目を分解する](https://knowledge.bizrobo.com/hc/ja/articles/360050070232)


## 「繰り返し（Repeat）」ステップ
「次へ（Next）」ステップと一緒に使用することで、繰り返し処理を実現させます。
無限ループを生み出すことができるため、「エラー処理(Error Handling)」タブ等を活用し、繰り返し処理を止める必要があります。「次へ(Next)」ステップへ処理を到達させないようにすれば、この繰り返し処理を終わらせることができるからです。

「繰り返し（Repeat）」ステップを用いる代表例は、複数ページにまたがるWebサイトを1ページずつページ移動させる時です。下記のような画面の時に役に立ちます。
<img width="120%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955689/0a7360b0-9697-d056-7bb6-1e536b3d2ea5.png">

詳細は下記をご参照ください。
[「繰り返し(Repeat)」ステップ](https://knowledge.bizrobo.com/hc/ja/articles/360055646571)
[複数ページにまたがるWebサイトで、それぞれのページをクローリングする方法](https://knowledge.bizrobo.com/hc/ja/articles/360033715271)


## 「繰り返し（Repeat）」ステップと他のステップとの違い
#### 「○○ループ（Loop～）」ステップと「○○繰り返し（For Each～）」ステップの場合
対象がなくなるまで繰り返し処理を続けます。
例えば、Excelファイルを行からデータを取得する際、データがなくなったら終了します。
また、条件等によって、何回指定するか回数を決めることができます。指定した回数だけ繰り返します。

#### 「繰り返し(Repeat)」ステップの場合
「次へ(Next)」ステップに到達し続ける限り、無限にループし続けます。
ループ内にあるステップにて、エラー処理タブの設定や条件設定などで意図的にループを終了させない限り、永遠にループし続けます。


## 最後に
BizRobo!の繰り返し処理について解説いたしました。

システム開発に携わっていた時は、繰り返し処理は、Forかwhileのどちらかを用いればよかったので、区別に困ったことはありませんでした。しかしRPAになると、繰り返し処理の使い分けを行わないといけないため、悩むときがあります。
自分の整理もかねて、今回の記事を書いたことで、BizRobo!の繰り返し処理を理解することが出来たと思っています。

今回の記事が、RPA開発で悩んでいる人の為になれば幸いです。
【Excel VBA】行削除・列削除をする方法

# はじめに
Excel VBAで行削除や列削除を行う方法を紹介します。
同じ処理を行う方法が複数ある場合は同様のコードを併記しています。

# 単一行を削除
1行目を削除する場合
```vb
Rows(1).Delete
Range("1:1").Delete
```

## 連続した複数行を削除
1行目から3行目を削除する場合
```vb
Rows("1:3").Delete
Range("1:3").Delete
```

## 離れた複数行を削除
2行目、4行目から6行目、8行目から10行目を削除する場合
```vb
Range("2:2,4:6,8:10").Delete 'Range("行範囲1,行範囲2,行範囲3").Delete　
```

## 指定セルを含む行を削除
C2セルを含む行を削除する場合
```vb
Range("C2").EntireRow.Delete
Cells(2, "C").EntireRow.Delete
Cells(2, 3).EntireRow.Delete
```

## 指定範囲を含む行を削除
B2セルからD4セルの範囲を含む行を削除する場合
```vb
Range("B2:D4").EntireRow.Delete
```

# 単一列を削除
A列を削除する場合
```vb
Columns("A").Delete
Columns(1).Delete
Range("A:A").Delete
```

## 連続した複数列を削除
A列からC列を削除する場合
```vb
Columns("A:C").Delete
Range("A:C").Delete
Range(Columns("A"),Columns("C")).Delete
Range(Columns(1),Columns(3)).Delete
```

## 離れた複数列を削除
B列、D列からF列、HからJ列を削除する場合
```vb
Range("B:B,D:F,H:J").Delete 'Range("列範囲1,列範囲2,列範囲3").Delete　
```

## 指定セルを含む列を削除
C2セルを含む列を削除する場合
```vb
Range("C2").EntireColumn.Delete
Cells(2, "C").EntireColumn.Delete
Cells(2, 3).EntireColumn.Delete
```

## 指定範囲を含む列を削除
B2セルからD4セルの範囲を含む列を削除する場合
```vb
Range("B2:D4").EntireColumn.Delete
```

# DeleteとClearとClearContentsの違い
Delete 以外に Clear や ClearContents でも行や列をクリアできます。

|メソッド|機能|記述例|
|---|---|---|
|Delete|行・列そのものを削除する|Rows(1).Delete|
|Clear|行・列は残して値や書式をクリアする|Rows(1).Clear|
|ClearContents|行・列・書式は残して値をクリアする|Rows(1).ClearContents|
Githubの使い方その2

## Githubの使い方　その2

ローカルリポジトリに関しては[Githubの使い方その1](https://qiita.com/ki_takada/items/275ea40db8e42694a302)

### リモートリポジトリに関しての用語説明
* リモートリポジトリとはGitHubの中にあるファイルを格納する保管庫のこと。つまり、インターネット上のWebサービス（GitHub）でファイルを管理する

### PUSHとPULL
* リモートリポジトリにアップロードすることをPUSH
* 自分のローカルにダウンロードすることをPULL
![スクリーンショット 2024-01-19 18.10.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/3569c4ac-7c43-b3b0-b3a8-1608c8aa5e18.png)

### クローン
GitHubにある既存のリモートリポジトリを更新したいけど、自分のパソコンにローカルリポジトリがない場合はクローンをします。その後の変更に関してはPULLでok。

### プルリクエスト
自分が更新したファイルの内容を、他のチームメンバーにレビュー（更新内容が正しいかチェック）してもらう機能。

### ブランチ
「ブランチ」とは、リポジトリ内でファイルの管理を用途に合わせて分岐させる機能。チームでアプリ開発を行う場合にお互いの作業の影響を受けずに、同時並行で進められるメリットがある。
例えば、アプリの新機能開発のため「新機能開発チーム」を作ったとします。ブランチも「開発用ブランチ」を作り分けておくと、それぞれのチームが並行して作業ができる。
分岐したブランチは他のブランチへ影響を与えないで「既存の保守チーム」のソースコードに誤って「新機能開発チーム」の開発中ソースが混じってしまうような心配もない。
下記はブランチのイメージ。リモートリポジトリ内でmainブランチから開発ブランチを作りファイル3を削除したイメージ。
![スクリーンショット 2024-01-19 19.06.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/d9fc42c1-5358-49f1-ba66-e399db64c36e.png)

### マージ
あるブランチで行った変更を、別のブランチに適用すること。
例えば、「開発用ブランチ」でバグの改修が終わった内容を「mainブランチ」にマージすることで、「mainブランチ」のバグが解消される　など。
![スクリーンショット 2024-01-19 19.27.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/777b7bdb-1116-f232-36f9-33a2b35df6ca.png)

### まとめ　開発での流れ
❶**ローカルリポジトリ**のmainブランチから開発用ブランチを作成し、ファイルを変更。

❷開発用ブランチのファイル3を削除してコミットした後に、開発用ブランチを**リモートリポジトリにプッシュ**。

❸でGitHub上で開発用ブランチへの**プルリクエスト**を作成すると、チームメンバーにレビュー依頼の通知が届きます。

❹チームメンバーの**レビューが通れば**、開発用ブランチの内容をmainブランチに**マージ**して、ファイル3の削除がmainブランチに反映されます。

![スクリーンショット 2024-01-19 19.56.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/50852d1a-9391-801c-aba4-c7d9e863691e.png)

今日はここまで。次の記事では実際にコミットからPULLまで行ってみたいと思います。
nn.Embedding の説明

pytorchのnn.Embeddingに書いてある説明(以下の引用)がわからなかったので調べた
lookup table って何？って感じ

> A simple lookup table that stores embeddings of a fixed dictionary and size. This module is often used to store word embeddings and retrieve them using indices. The input to the module is a list of indices, and the output is the corresponding word embeddings.


一番分かりやすかった記事
https://medium.com/@hunter-j-phillips/the-embedding-layer-27d9c980d124


## 訓練
(seq_length, vocab_size)のワンホットベクトルに対して、(vocab_size, dim) のパラメータを用意することで分散表現に変換する。
訓練時は普通にbackpropするので、毎回行列の積を計算する。

## 推論
vocab_size 個だけ存在する全てのトークンについて、パラメータ行列の積を計算することで得られる分散表現を保存しておくことで、トークンが入力されたときに行列の積を計算せずに済む。これがlookup tableのことです。
qiskit_experiments で Rabi振動

[前回](https://qiita.com/tare_/items/fb14bbd098f7ba534827)同様，qiskit_experimentsを用いて，[Rabi振動](https://qiita.com/tare_/items/203e29ab7c719888d63d)を見ていきたいと思います．

# RoughXSXAmplitudeCal
今回はqiskit_experimentsの```RoughXSXAmplitudeCal```を用いてRabi振動を見ていきます．これはマイクロ波のエンベロープ関数の振幅を変化させていくことによって，$X$ゲートと$SX$ゲートを同時に校正していく関数のようです．Rabi振動を見れば，$X$や$SX$の最適な振幅が分かるということですね．

それではコードを見ていきましょう．
```python
import pandas as pd
import numpy as np
import qiskit.pulse as pulse
from qiskit.circuit import Parameter
from qiskit_experiments.calibration_management.calibrations import Calibrations
from qiskit import schedule
from qiskit import IBMQ
from qiskit_experiments.library.calibration import RoughXSXAmplitudeCal

IBMQ.save_account("") #tokenを入れてください
IBMQ.load_account()
provider = IBMQ.get_provider(hub='ibm-q')
backend = provider.get_backend('') #使用するbackendを指定してください

qubit = 0


def setup_cals(backend) -> Calibrations:

    cals = Calibrations.from_backend(backend)

    dur = Parameter("dur")
    amp = Parameter("amp")
    sigma = Parameter("σ")
    drive = pulse.DriveChannel(Parameter("ch0"))

    with pulse.build(name="x") as x:
        pulse.play(pulse.Gaussian(dur, amp, sigma), drive)

    with pulse.build(name="sx") as sx:
        pulse.play(pulse.Gaussian(dur, amp, sigma), drive)

    cals.add_schedule(x, num_qubits=1)
    cals.add_schedule(sx, num_qubits=1)

    return cals

def add_parameter_guesses(cals: Calibrations):

    for sched in ["x","sx"]:
        cals.add_parameter_value(15, "σ", schedule=sched)
        cals.add_parameter_value(120, "dur", schedule=sched)
        cals.add_parameter_value(0.5, "amp", schedule=sched)

cals = setup_cals(backend)
add_parameter_guesses(cals)

columns_to_show = ["parameter", "qubits", "schedule", "value"]
pd.DataFrame(**cals.parameters_table(qubit_list=[qubit, ()]))[columns_to_show]
```
![param0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/887541/d6e5d39f-e869-b6ef-9c02-0edbfee0b182.png)

```setup_cals```で波形を決めています．今回は[以前](https://qiita.com/tare_/items/203e29ab7c719888d63d)同様Gussianを選択しました．また，各パラメータが指定した値になっていることが分かります．また，```RoughXSXAmplitudeCal```の構成上，$X$と$SX$どちらの波形も指定する必要があります．さて，```amp```をスイープしながらRabi振動を見ていきます．

```python
rabi = RoughXSXAmplitudeCal((qubit,), cals, backend=backend, amplitudes=np.linspace(0, 0.75, 50))

rabi_data = rabi.run().block_for_results()
rabi_data.figure(0)
```
![rabi_result0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/887541/d9d952c6-0fc9-50b1-5416-466c08273ffd.png)

確かに[以前](https://qiita.com/tare_/items/203e29ab7c719888d63d)同様の結果が得られていることが分かります．また，$X$や$SX$に最適な振幅を見てみると，
```python
pd.DataFrame(**cals.parameters_table(qubit_list=[qubit, ()], parameters="amp"))[columns_to_show]
```
![param1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/887541/60a3aba5-e334-d767-d835-7db8ff256662.png)
より，確かに更新されていることが分かります．



# 最後に
２量子ビット操作も実験してみたいですね(2回目)．


#### Version Information
|Software|Version|
|---|---|
|qiskit|0.45.1|
|qiskit_experiments|0.5.4|


||System information|
|---|---|
|Python version	|3.10.12|
【Laravel】ポリシーの実装方法

## はじめに
今まで認可をフォームリクエストに書いていたのですが、どうやらポリシーにまとめて書く方がスマートらしいので、早速試してみました。

https://readouble.com/laravel/8.x/ja/authorization.html

## 環境
Laravel 9.52.16

## 問題
* 特定のモデルの認可のロジックをまとめて実装したい

## 解決法
* Laravelの「ポリシー」を使う
* ポリシーを使えば、認可のロジックを一か所に集約できる
* これにより再利用性とメンテナンス性が向上する

今回は試しにUserDetailsControllerのupdateメソッドに認可を実装したいします。

そのためにまず、○○Policyという名前のポリシークラスを作成します。

これはartisanコマンドを使用して行います。

```php: Tinker
php artisan make:policy UserDetailPolicy --model=UserDetail
```

次に新しく作成したUserDetailPolicyクラスにupdateメソッドを追加します。

このメソッドでは、ユーザーが特定のUserDetailインスタンスを更新できるかどうかを判断します。

updateメソッドの第一引数には、現在認証されているユーザが自動的に渡されます。

第二引数の$userDetailは、コントローラから呼び出す際に引数で渡されることになります。

```php: App/Policies/UserDetailPolicy.php
<?php // 以下抜粋
public function update(User $user, UserDetail $userDetail)
{
    return $user->id === $userDetail->user_id;
}
?>
```

次に、App/Providers/AuthServiceProviderの中の$policiesプロパティに、

$UserDetailモデルとUserDetailPolicyポリシーの対応関係を定義します。

```php: App/Providers/AuthServiceProvider
<?php

namespace App\Providers;

// use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The model to policy mappings for the application.
     *
     * @var array<class-string, class-string>
     */
    protected $policies = [
        UserDetail::class => UserDetailPolicy::class, 
    ];

    // 以下略
}
?>
```

最後に、UserDetailsControllerのupdateメソッドで、authorizeメソッドを使用して認可を行います。

```php: UserDetailsController
// 中略

public function update(UserDetailsRequest $request, UserDetail $userDetail)
{
    $this->authorize('update', $userDetail);

    // 以下略
}
```

これで完成です！
関数の代わりにインスタンスメソッドをコールバックさせる

pythonの小ネタです。
### 概要
* 引数にコールバック関数を渡す代わりにインスタンスメソッドを渡すと、そのままコールバックされるし、`self`も参照できる。

情報量はこの一文で全てです。あまりやる機会もなさそうですが、「やったらどうなるのかな」と思う方がいるかもしれないので試して書きます。

### 関数に関数を渡す
関数Aの引数として関数Bを渡して、関数Aの中から関数Bを呼ぶ。いわゆるコールバックですね。標準ライブラリでも沢山使われているのでお馴染みだと思います。

```python:funcparam.py
def func_caller(func):
    """関数を受け取って呼び出す関数"""
    func('引数を渡します。')

def param_func(text):
    """func_callerから呼び出される関数"""
    print(text)

# 関数に関数を引数で渡す 
func_caller(param_func)
```
実行結果も何の変哲もない。
```
$ python funcparam.py
引数を渡します。
```
printする関数`param_func`を`func_caller`から呼び出すだけなので普通にprintされます。

### 関数にインスタンスのメソッドだけ渡す
今度はクラスのインスタンスの中からメソッド部分だけをコールバック関数の代わりに渡します。引数にインスタンスが含まれないのでメソッドの`self`がどうなるのかちょっと見た感じでは気になる書き方です。
```python:methodparam.py
def func_caller(func):
    """関数を受け取って呼び出す関数（さっきと同じ）"""
    func('引数を渡します。')

class ParamClass:
    """引数にするメソッドを持つクラス"""
    
    def __init__(self, mytext) -> None:
        """インスタンス変数mytextを持つ"""
        self.mytext = mytext

    def param_method(self, text):
        """引数textとself.mytextを一緒に出力する"""
        print(text, self.mytext)

# インスタンスを生成して、メソッドを引数にする
param_class = ParamClass('インスタンス変数も使えます。')
func_caller(param_class.param_method)
```
実行結果はこうなります。
```
$ python methodparam.py
引数を渡します。 インスタンス変数も使えます。
```
`instance.method()`のような呼び出しと変わらず`self`が渡されので、いつも通りに自由な操作が行えます。しかし、これを使って**コールバック内から`self`を操作してインスタンスの状態を変更する**のは混乱を招くのでやめたほうがいいでしょう。せめて`self`の内容を参照する程度にとどめておくべきでしょう。[^悪手]
少なくともpythonの標準ライブラリ内ではこんな使い方をしたいライブラリはほとんどなさそうに思えます。強いて言うなら、コールバック関数が何らかのファクトリとして動作するときにはちょっと検討してもいいかもしれません。[^実は]

[^悪手]: そもそも`self`を参照したいならコールバックよりもインスタンスを受け取った方が素直だと思います。最初からコールバック関数を受け取る仕様になっている汎用的な関数に対してインスタンスの情報を与えるための強引なトリックとしては使えなくもない？
[^実は]: 例えばDB-APIで使う`row_factory`や`json.dump`に渡す`default`などはコールバック経由で`self`の中身を参照することで柔軟な動作を期待できるかもしれない。
pythonの内包表記のメモ

Pythonの内包表記のメモを書きます。英語名で「List Comprehension」と呼びます。

s = ['......', '.#.#..', '......']

上記を、二次配列で表したいときのコードを書きます。
```python
r = [[0 if v == '.' else '#' for v in row] for row in s]
```
上記は下記の内包表記です。

```python
r = []
for row in s:
    r2 = []
    for v in row:
        if v == '.':
            r2.append(0)
        else:
            r2.append('#')
    r.append(r2)
```
メモとして残します。
CircleCIの環境変数の値をログに残さず確認する方法

# はじめに
CiecleCIのプロジェクトで設定されている環境変数の内容を確認したいということがあって、
調べながら試行錯誤しつつ先輩エンジニアの助言もあり無事やり方がわかったので備忘録として残します。

# 方法
### まずCircleCIのジョブでSSHデバッグを行う
手順については以下の記事がわかりやすかったのでご参照ください。

https://blog.mmmcorp.co.jp/2021/03/14/post-1351/

### 次にSSHデバッグ画面で環境変数を出力する

https://dev.classmethod.jp/articles/retrieve-circleci-env/

上記の記事を参考に以下のコマンドで環境変数を出力しました。

```bash
echo ${環境変数名:0:-4}
```

この手順で、環境変数の値をログに残さずに確認することができます。

以上になります。

# おわりに
誰かのお役に立てれば嬉しいです。
ANSYS FLUENTで都市の微小気候をシミュレーションする [1:必要なデータの用意]

近年、[PLATEAU](https://www.mlit.go.jp/plateau/)プロジェクトによって、都市の3Dモデルの公開や、3Dモデルを防災・ヒートアイランドシミュレーション・観光などに役立てることが盛んになっています。

都市環境はとても複雑で、建物の分布、地表面を覆う素材、壁面の素材、建物排熱量によって風の動きや温度が微小なスケールで複雑に変化します。このような都市特有の微小な環境状態を知るにはどうすればよいでしょうか？　ひとつの方法は、流体シミュレーション (CFD simulation) です。この記事では、札幌市の3Dモデルを用いて都市の風の動きや温度分布などをシミュレーションしていきます。

# Ansys Fluentとは
流体/液体解析が行えるソフトウェア。この記事では、3D都市モデルを用いて、風の動きや温度分布などをシミュレーションするために使用する。

![スクリーンショット 2023-11-22 184905.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3015300/4fc5c4ac-2bf4-e877-4e55-5bcb2217bd7d.png)
流体シミュレーションを行うことで、このように温度分布など知ることができる。

# ANSYS のインストール
[Ansysのウェブサイト](https://www.ansys.com/ja-jp/academic/students/ansys-student)からダウンロードする。

学生向けバージョンの「**Ansys Student**」なら無料でダウンロードできる。メッシュ数の限りや、一度に複数のウィンドウを開けないなどの制限があるが、ちょっとしたシミュレーションなら問題なく使用できる。ここでは、Ansys Studentを使用する。

Ansys Studentをダウンロードすると、「Ansys 2023 R2」(2023やR2などはダウンロードしたバージョンによって変わってくる)というフォルダ内にFluent、Discovery、EnSightなど多くのソフトウェアがセットでダウンロードされていることがわかる。流体解析では、主に**Fluent**と**Discovery**を使用する。

# 3D都市データを入手する
流体解析を行うには、まず解析の対象とする区画の3Dデータを作成する必要がある。3Dデータの作成・編集は**Discovery**で行う。

[G空間情報センター](https://front.geospatial.jp/)では、多くのまちの3Dデータが公開されている。解析したいまちを決め、データセットをダウンロードする。ここでは札幌市を例に説明する。

まず、G空間情報センターのホーム画面「データを探す」に「札幌」とキーワードを入力し、検索する。すると、目的の「3D都市モデル (Project PLATEAU) 札幌市 (2020年度)」が検索結果に表示される。さまざまなフォーマットで3D都市モデルのデータが入手できるが、今回は**OBJ形式**のデータをダウンロードする。

![qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3015300/68eb1f6f-d63b-fcb3-767b-902f445bdc3d.png)

ダウンロードした01100_sapporo-shi_2020_obj_3_opフォルダ内の
- 01100_indexmap_op.pdf
- bldgフォルダ内のOBJデータ

を主に使用する。

これで、解析のために必要なソフトウェアとデータのダウンロードが完了した。

以降の手順については、順次投稿する予定。

https://qiita.com/suga3008/items/e75b086aec9aa8654b7d
web版Outlookに表示される広告を消したいです！

# 初めに
突然ですが…私はwindowsユーザーでありまして、メールは基本的にyandex, google, そしてoutlookを使用しています∮

それでして、web版のoutlookを使用する場合、下のように、右側（必ずそうなるのかはわかりませぬが…）に広告が表示されてします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674822/bb3d9847-4eec-851a-6f38-d71e76a26d97.png)


私は広告が大嫌いでして…意識散ってメールの返信できねえ！！！
というときがありました。
その時、即興で広告を削除しようとしたら、案外簡単に出来たので、今回はそれをメモメモしていきたいと思います∮

# 実際に
それでは、やっていきましょう！
といっても、実際にはひどくシンプルな内容です。
広告が入る要素タグを削除すればよいのです！…ってそりゃそうですね(笑)

で、その、「広告が入る要素」とやらを、ブラウザの開発者ツールで調査していきます！
ちなみに、私はブラウザはfirefoxを使用しています。
[Ctrl] + [Shift] + [i]で開きまして、上のタグの内、「インスペクター」で広告の要素を探します！

発見しました！
要素のクラス名は「GssDD」です！
（↑これがめちゃ大事です。）

続いて、上のタグで「コンソール」を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674822/13b207f2-fd4e-dd87-cf12-9485976e07d2.png)

そして、
```javascript:コンソールに書くコード
document.querySelector('.GssDD').remove();
````
と記述。

Enterを押します。

完璧です！
広告を削除することが出来ました♪

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674822/4ab94b63-3127-53f7-8265-2971c6ae4bf5.png)


これで広い場所で心広く、相手にメッセージを送ることができますね！(笑)

# 最後に
この「document.querySelector('.GssDD').remove();」を覚えておけば、いつでも広告を簡単に削除できます。（コードが編集されたりしない限りの話です。あと、ページをリロードしたらまた広告は出現してしまいます。）

しかし、上の括弧内に書いたように、完璧なものではありません。
ページのリロード問題についてはなんとか方法がありそうですので、コメント等（メールでももちろん大歓迎です！）でご意見、提案、注意等々…教えていただけると大変嬉しいです。

ちなみに、デスクトップ版のoutlookを使用すれば、広告は表示されません(笑)
私はもうそれを使っています(笑)
Javaのポリモーフィズム

# ポリモーフィズム
動いているインスタンスをインスタンスの元となった型とは別の型で扱える仕組み

ポリモーフィズムが成り立つ条件は以下二つ

継承関係にある
実現の関係にある

企業組織での例


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3530974/1b090e05-642f-a463-afa1-21b6b31f4e72.png)


実装
子クラス１ーエンジニアクラス

```Engineer.java
public class Engineer extends BuSho {

	public Engineer(String name,String busho,String skill) {
		super(name,skill,busho);
	}
	
}
	
```

子クラス２ーHRクラス

```HR.java
public class HR extends BuSho {

	HR(String name,  String skill,String busho) {
		super(name, busho, skill);	
	}
}

```

親クラス
名前、スキル、部署は共通フィールドなのでまとめておく
部署情報の表示メソッドも処理内容が共通なのでまとめる

```BuSho.java
public  class BuSho {

	String name;
	String busho;
	String skill;
	
	
	BuSho(String name,String busho,String skill){
		this.name=name;
		this.busho=busho;
		this.skill=skill;
	}
	
	public  void display() {
		System.out.println(name);
		System.out.println(busho);
		System.out.println(skill);
	}
	
}
```

部署の情報を取得して、それぞれの情報を表示するクラス

```Shain.java
public class Shain {
	
	BuSho busho;
	
	public Shain(BuSho busho) {
		
		this.busho=busho;
		
	}
	
	public void display() {
		
		busho.display();
	}

}
```

Mainクラス
社員インスタンスの引数に部署の変数を入れるとそれぞれの情報が表示
```Main.java
public class Main {

	public static void main(String[] args) {
		
		Engineer en = new Engineer("斎藤", "開発", "Java");
		HR h = new HR("中村", "人事", "excel");
		
		Shain s = new Shain(en);
		s.display();
	
		Shain s2 = new Shain (h);
		s2.display();

	}

}
```