OmniAICreator/Qiita-1.07M huggingface dataset:
【VSCode】インストールしたライブラリが could not be resolved となった場合の対処法

# 事象
pythonで`matplotlib`をimportしようとしたら、`could not be resolved`という警告が表示された
なお、`matplotlib`は既にインストール済みであり、プログラムは問題なく動作する

# 環境

| 項目 | 情報 |
| ---- | ---- |
| OS | Windows 10 |
| Python | 3.9.13 |
| VSCode | 1.73.1 |

# 原因
VSCodeが`matplotlib`を見つけることができていない

# 対処方法
以下サイトを参考に以下二つの対応を実施

https://startlab.jp/learning-python/vscode-settings/

## 1. ライブラリがインストールされている場所を調べる
### 入力
```
pip show matplotlib
```

### 出力
```
Name: matplotlib
Version: 3.6.2
Summary: Python plotting package
Home-page: https://matplotlib.org
Author: John D. Hunter, Michael Droettboom
Author-email: matplotlib-users@python.org
License: PSF
Location: c:\git\.venv\lib\site-packages
Requires: contourpy, cycler, fonttools, kiwisolver, numpy, packaging, pillow, pyparsing, python-dateutil
Required-by:
```

## 2. VSCodeの設定追加
1. 「ファイル」-「ユーザ設定」-「設定」を選択
1. 「設定の検索」の欄に`extra path`と入力
1. 「項目の追加」をクリックして、1で調べたLocationのパスを入力する
Excel PowerQueryのすゝめ

# ネ申
JTCに横行する闇、VBA。
VBAや複雑怪奇な関数を叩き込んだExcelブックを生み出し、局所最適を図る人々。
日本ではこういった人々をExcelネ申と呼ぶ。

## モダンExcel
https://qiita.com/k_maki/items/a733e8e72e02d10cb1a0

この記事に感銘を受けて、執筆することにしました。
伝えたい事が全て書かれている気がするものの、実務で感じた私の思いの丈を記載する事とする。

## つまづくシーン
便利なPowerQuery、いざ使ってみると実務では頭を抱えるシーンも多い。
ずらずらと書いてみると、
- データが揃わない
    - 実務では個人管理のデータが多すぎたり、補完方法が定まっていない事が多い。
            - いわゆるデータのサイロ化
            
- 手に入ったデータもいわゆるネ申資料
    - Ver.管理が意味不明(Git？？　SVNすら聞いたことない。)
    - 形式がコロコロ変わる紙のようなエクセル帳票
    - 形式が揃ってないならまだしも、糞VBAがくっついてたりする。
    - というかPPTにテキストボックスだったりもする。

- テーブル(風)データでも頭を抱える
    - なんのために作ったか分からない列(変数)
        - 巷では巻物と呼ぶ。
    - 整然データになってない(よくあるのは、年度ごとにピポット化されたデータ)。
        - もはやIT系の部門でもないと整然データなんて言っても無駄。

- 切り口が定まらない。
    - データはあるが、何が欲しいか明確でない。
        - 要件定義だいじ。

上記の様な状況ではETL(抽出・変換・書出し)がうまく行かず可視化や分析といった次のステップへ進めないため、工夫や断捨離が必要となる。

## じゃ、どうすればいいのさ
- データの準備フェーズ
    - 入力にブレが生じにくく、分析しやすい入力フォーマットを配布する。
        - Webサービス(Officeしか使えないなら、SharePointのリストなど)
        - Excelフォーマット（テーブル化や入力規則）


- ETL・分析フェーズ
    - **ヒアリング**を頻繁に行い、アウトプットを明確にする。
        - 手戻りを防ぐため
        - アウトプットが明確なら、インプット(変数やER)も定義しやすい。


# 最後に
結局のところ、効率的なやり方も導入するまでの壁がいっぱいある。
くじけない心が一番だいじ。
DockerのVolume作成時にどこに実ファイルが存在するか(WSL2)

## Dockerで名前付きVolumeの実ファイルが見つからない
という事象が発生し、探すのに大分時間が掛かってしまったので備忘録として。

## 環境
* OS
    * Windows11 Home 21H2
* WSL2
    * Ubuntu 22.04.1 LTS
* Docker
    * 20.10.20
* Docker Desktop for Windows 
    * 20.10.20

## 結論
```
\\wsl$\docker-desktop-data\data\docker\volumes
```
にありました。

## その他
OSによって異なったりするのか、ググると他のフォルダに存在しているような記事が多かったです。

Windows10の場合はこちらの記事が参考になるかもしれません。
[[Docker] WSL2で作成した名前付きボリュームがない](https://qiita.com/daemokra/items/edef4b1518fb8f6baf07)
今更Dockerの素晴らしさについて書いてみる

# Dockerとは
コンテナと呼ばれる仮想環境を作成、実行、配布するプラットフォームのこと

## 何が良いの？
「プログラミングは環境構築が一番難しい」
この言葉を打破する技術、それがDocker。
開発環境を用意するとき、どのVer.をDLすればいいか迷った事はないだろうか。
以前入れたVer.の環境が悪影響して、新しく入れた環境が動作しなかったことはないだろうか。

Dockerを使えば、複数の独立した環境を、１つの物理的なマシンに同居させられる。
環境構築を行うコード(DockerComposeやコマンド)をコピペすれば、速やかに任意の環境を用意できる。


## とは言っても難しいんでしょ？
https://book.mynavi.jp/ec/products/detail/id=120304

この本１冊を読んでみよう。
1日３０分＊２週間程度で読了できるはず。とにかくまず使ってみたい、って人には良書。

## VSCodeとの連携
https://qiita.com/Yuki_Oshima/items/d3b52c553387685460b0

上記を参考に、VSCode拡張機能Remote Developmentを入れればGUI操作によってDocker RunやImageの操作、ボリュームの操作などを行う事もできるため、コマンドと並行して使える様になるとよい。

他にもGitやMysqlなどの拡張機能を入れるとDockerで環境用意→クエリやDBをMysqlで接続→分析コードをGit/GitHubで履歴管理という一連の過程をすべてVSCode上で行う事ができるようになる。
「青空エンジニア」のすすめ

「青空エンジニア」とは、**屋外でエンジニアリングをすること・人**を意味する造語です。

私は屋外でエンジニア業を嗜むことを好み、そして青空エンジニアの普及を密かに企んでいます。
今回は、私が青空エンジニアをする理由と注意点をまとめました。

### 理由1. 日光を浴びる
ほんの一昔前に「SEうつ病」なんて言葉が流行りました。その本質は、エンジニアはうつ病になりやすいとのものでした。
原因はさまざまですが、日光を浴びないことがそのひとつとしてよく挙げられます。

日光を浴びないということは、本来得られるはずのビタミンDやセロトニンが分泌されないということです。
特にセロトニンは、脳の神経伝達物質の一種で夜にはメラトニンと呼ばれる睡眠物質へと変化します。脳の安定に関わるセロトニンが分泌されないことで、精神不安定や意欲低下、不眠、不安などを引き起こすという訳です。

したがって、意識的に日光を浴びることが大切だと思っています。

### 理由2. 歩く
オフィスワーカーは運動不足になりがちです。オンラインワークが運動不足にさらなる拍車をかけていることは間違いないでしょう。

私は主に自宅近くの公園で青空エンジニアしています。
公園との往き復り（と買い物などのちょっとばかりの寄り道）は僅かな運動と気分転換になっています。現に、ビジネスロジックの実現方法に公園で暗中模索したのち、自宅への帰り道でその方法をひらめいたことが何度かあります。

したがって、屋内だけでなく屋外へと歩き出すことに意味があると思っています。

### 注意点1. 情報の漏洩
エンジニアはしばしば企業・個人の秘匿情報を扱います。背後からの覗き込みや、オンラインミーティングによる会話での情報の流出には留意が必要です。

### 注意点2. 場所
青空エンジニアすることのデメリットに、怪しい人と見られる場合があるのは言及が避けられないでしょう。よって、青空エンジニアをする場所には注意が必要です。ひと気があり、なるべく大きな場所を選ぶとよい気がします。

### まとめ
「屋外で仕事をしています」なんて言うとまだまだ不思議がられるのが実情ですが、**新しい働き方のひとつとして意義があるもの**と社会的にも定義・認識されていくといいなって思います。
JavaScript すっきりリファクタリング 1

ネット上で見かけたJavaScriptのコードをリファクタリングしていく企画です。

## 元コード

食べ物のラジオボタンを選択したら、それに合わせて&lt;select&gt;タグの内容(&lt;option&gt;タグ)が変わる。
細かな仕様として、未選択の&lt;option&gt;タグは常に表示する。

https://gistpreview.github.io/?987d2d085c8a4f2d927706073676fa0d

```html:元コード
<ul id="foodList">
  <li>
    <input type="radio" value="fruits" name="foods" id="fruits">
    <label for="fruits">果物</label>
  </li>
  <li>
    <input type="radio" value="vegetables" name="foods" id="vegetables">
    <label for="vegetables">野菜</label>
  </li>
  <li>
    <input type="radio" value="meats" name="foods" id="meats">
    <label for="meats">肉</label>
  </li>
</ul>

<select id="foodSelect">
  <option value="">未選択</option>
</select>

<script>
const FOOD = {
    "fruits": ["りんご", "みかん", "ぶどう"],
    "vegetables": ["キャベツ", "じゃがいも", "なす"],
    "meats": ["鶏肉", "豚肉", "牛肉"]
};

// イベント部
$('[name="foods"]').on('change', function() {
    let foodSelect = $('#foodSelect');
    let val = $(this).val();
    let html = "";
 
    // 未選択以外を削除
    foodSelect.find('option:not(:first)').remove();
    // カテゴリ一覧を配置
    $.each(FOOD[val], function(i, value){
        html += `<option value="${value}">${value}</option>`;
    });
    foodSelect.append(html);
});
</script>
```

## 新コード
イベント部のみの変更です。

```js:新コード
foodList.onchange = function(event){
    foodSelect.replaceChildren(foodSelect[0], ...FOOD[event.target.value].map(v => new Option(v, v)))
}
```



- 他の問題は「[スッキリリファクタリング](https://qiita.com/tags/%e3%82%b9%e3%83%83%e3%82%ad%e3%83%aa%e3%83%aa%e3%83%95%e3%82%a1%e3%82%af%e3%82%bf%e3%83%aa%e3%83%b3%e3%82%b0)」タグからどうぞ。
【gulp版】node-sass（Libsass）からdart-sassにする

# はじめに

業務でやったので。
gulp版のsassを、node-sass（Libsass）からdart-sassに変更する手順の覚え書き。ほぼ自分用です

## 確認方法

まずはsassのコンパイルに何を使っているか確認してみる。

``` terminal
$ cd {ProjectDirectory}/

$ npm list --depth=0 | grep sass | cut -f 1 -d "@"
```

▼gulpの入っているリポジトリでは最初からこれらが入っていました。

``` terminal
├── gulp-sass
├── gulp-sass-inheritance
```

<small>参考：[Sassのコンパイルに何を使っているかターミナルから知る方法](https://iwb.jp/using-compile-dart-sass-scss-ruby-terminal/)
</small>


# アンインストール&インストール

`gulp-sass`をアンインストールし、
 `gulp-dart-sass`をインストールします。

``` terminal
$ cd {ProjectDirectory}/

// アンインストール
$ npm uninstall gulp-sass

// インストール
$ npm install gulp-dart-sass --save-dev
```

<small>（nodeやらnpmのバージョンで警告が色々でてきましたがとりあえずスルーで進めます…）<small>

<small>参考：[さようならLibSass、こんにちはDart Sass。](https://devlog.atlas.jp/2021/09/14/3974)</small>

---

▼再び確認すると下記のようになります。

``` terminal
├── gulp-dart-sass
├── gulp-sass-inheritance
```


### compassも不要なのでアンインストールしました

``` terminal
$ npm uninstall compass-importer
```

#### compassを廃止した理由

* （当時のプロジェクトの場合）`@include`でベンダープレフィックスつけるのに使っているだけのため
    * 昔は必要だったけど、今はベンダープレフィックスいらないものがほとんどのため
        * 該当の`@include`の記述は修正する
* compassのSVGのサポート（`$experimental-support-for-svg: true;`）の記述もあったがIE9用のため削除した

<small>参考：[Compass の送別会](https://tech.pepabo.com/2018/03/15/bye-bye-compass/)
</small>


## gulpfile.jsの中を変更する


``` js
        .pipe(plugins.sass({
            includePaths: [cfg.path.scss],
            importer: plugins.compassImporter,
            outputStyle: 'expanded'
        }))
~
        // エラー部分
        .on('error', plugins.sass.logError)
```

↑このへんの`plugins.sass`を

``` js
        .pipe(plugins.dartSass({
            includePaths: [cfg.path.scss],
            importer: plugins.compassImporter,
            outputStyle: 'expanded'
        }))
~
        // エラー部分
        .on('error', plugins.dartSass.logError)
```

↑`plugins.dartSass`に書き換えます。
（`sassInheritance`とか別のもあるので全置換しないように注意）



既存の `node_modules`フォルダを消し、`npm install`します。

これでgulpの準備は完了です。

# @importを@useと@forwardに書き換える

いつもどおりにgulpする。

gulpするとscssファイルに`Deprecation Warning`エラーがいっぱい出るので修正します。
上記の通りcompassも廃止したので関連の記述を消していきます。

<small>参考：[node-sassからDartSassへsassコンパイラの移行](https://developers.gmo.jp/12920/)</small>
<small>参考：[【Sass】@importの廃止に伴い@useと@forwardに書き換える](https://zenn.dev/micronn/articles/12a0ae70975ad1)</small>




### baseフォルダのファイルをまとめる（当時のプロジェクトの場合）
baseフォルダの直下に`_index.scss`ファイルを新規作成、下記のようにする

```
@forward "setting";
@forward "reset";
@forward "mixin";
@forward "base";
```

scssファイルごとに下記のように記述してある部分があったため、書き換えた。

```
@import "base/setting";
@import "base/reset.scss";
@import "base/mixin.scss";
@import "base/base.scss";
```
↓
```
@use "base" as b;
```

これで、baseフォルダにあるSCSSで設定している`変数（$〜）`、`mixin（@include）`などの頭に`b.`をつけると呼び出すことができる。

コマンドライン上でエラーが出ない・表示に問題なければOKです。
MySQL Shell で AttributeError: unknown attribute: がでたときにはモードを疑う

MySQL運用初心者です。
MySQL Shellを試している中で公式ドキュメントや書籍と異なる場面がでてきて、ネットで検索しても同様の事例がみつからずすこし困ったので、どなたかの助けになればと気付いたことを書いておきます。

### 環境

- Ubuntu22.04
- MySQL Server version: 8.0.31-0ubuntu0.22.04.1
- MySQL Shell 8.0.23 (snap でインストールした。これが根本原因)


## 起きたこと

`mysqlsh -u root`でログインし、レプリケーションの設定を試そうとすると以下のような実行結果となる。

```sh
mysql-py []> dba.configureReplicaSetInstance()
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AttributeError: unknown attribute: configureReplicaSetInstance
```

公式ドキュメントでは、同じコマンドなのになぜだろう（よくみるとJSかPyかが違う）

https://dev.mysql.com/doc/mysql-shell/8.0/en/configuring-replicaset-instances.html

いろいろ参考にしていてたいへん有用なこの書籍 MySQL徹底入門 第4版 でもこのコマンドで特に注釈はない。

https://www.shoeisha.co.jp/book/detail/9784798161488

## 原因

Pyモードだからっぽい。ヘルプをみると下記のようにスネークケースのコマンドがでてきた

```sh
>\? dba
(略)
configure_replica_set_instance([instance][, options])
    Validates and configures an instance for use in an InnoDB
            ReplicaSet.
(略)
```

というわけでこれで動作します。

```sh
mysql-py []> dba.configure_replica_set_instance()
```

ちなみに公式ドキュメントだと `\js` でjsモードに変更できるとあるが、手元の環境では `Unknown command` になるし、`\?` でもそんなコマンドはなさそうだった。

https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-shell-commands.html

調べると、snapでインストールしているとjsモードはないらしい・・・。バージョン難しいよ～
https://dba.stackexchange.com/questions/302402/how-to-start-mysql-shell-in-mysql-js-javascript-mode
[備忘録] WindowsマシンのHDD→SSD化の際のddコマンド

# 動機

知人のデスクトップPCの動作が遅いと相談があり、見てみたところHDDを使っていた。
Coffee Lakeなi7を使っていてまだ現役で行けるだろうという判断でSSD換装をすることになった。
UbuntuのLiveUSBを使ってddコマンドでクローンすることに

# 以下メモ

使ったコマンド

```sh
ubuntu@ubuntu:~$ sudo dd if=/dev/source of=/dev/dist bs=4M conv=sync,noerror status=progress
# 最終的な出力は以下の通り
50010786016bytes (500GB, 466Gib) copied, 5492.7 s, 91.0 MB/s
```

- 500GB HDD → 500GB SSD(WD青 SA510)
- 大体 90Mb/s ~ 110MB/sで遷移。
- bs=512でやってたけれど、これだと512byteでめっちゃ遅い(17MB/sくらいだった)

# 感想

人様のPCだったのでわりとドッキドキでした。無事に終わってよかった。
あと富士通の法人向けPC、パーツ変えやすくていい。3.5インチベイアクセスめっちゃ楽だった。
【初心者】モデリング用のデータをサニタイズおよび準備を整理してみた

# 背景・目的
私は、現在データエンジニアリングを生業としています。普段は、データ基盤の構築や、パフォーマンスチューニングなどビックデータに関する業務に従事しています。
ビックデータの収集や、蓄積、分析などの環境構築の経験はそこそこありますが、機械学習による予測や分類などのスキルは持ち合わせていませんでした。
今まで機械学習を避け続けてきましたが、一念発起し学ぼうと思います。

学び方としては、AWS Certified Machine Learning – Specialty（以降、ML試験という。）の勉強を通して、理解を深めていきます。
今回は、モデリング用のデータをサニタイズおよび準備について学習します。

# まとめ
- 機械学習では、事前のデータセットの把握やサニタイズが十分に必要。
- データの把握では、以下のような方法を用いる。
    - 列と行の数を把握
    - 多変量統計により、属性間の相関を把握
    - 属性統計により、属性毎の特徴を把握
- データを把握した後のサニタイズでは、以下のような方法を用いる。
    - 言語・文法の標準化
    - 同一スケールに揃える
    - 同一特徴に揃える
    - 異常値を把握し対応する
    - 欠損を把握し対応する


# 概要
## 目的
データを取り込んでから、変換しデータを保存した状態では、以下の状態から理解ができません。そのためモデリング用に効果的にトレーニングができるようにサニタイズする必要があります。
- ノイズ
- バイアス
- 不均衡

## 手法
### 記述統計を使用する
データに関する重要なインサイトを得るために記述統計を使用します。

#### 全体の統計を把握する
データセットの行と列の数を把握する。（行はインスタンス、列は特徴・属性とも言われる。）
特徴量が多い場合、次元が高くなりモデルのパフォーマンスに影響を与える可能性がある。

#### 多変量統計を使用し相関を把握する
属性間の相関を特定する。2つの属性間の相関が高い場合、モデルのパフォーマンスに影響を与える可能性がある。
散布図により数値間数間の関係を可視化したり、相関行列により変数間の線形関係を定量化できる。

#### 属性統計を使用して把握する
数値属性に関する統計。平均・標準偏差、分散、最小値・最大値などを求めてデータの特徴を把握する。

### サニタイズする
記述統計によりデータ載り会ができた後、更にデータを詳しく調べてデータのクリーンアップを開始する。

#### 言語と文法を標準化する
同一の属性内で以下のような状態の場外に、標準化する必要があります。
- 英語と日本語等他の言語が混在
- 大文字、小文字が混在
- 特殊文字

#### 同じスケールか確認する
同一属性で、スケールが異なる場合に修正する必要がある。
例えば、km、m、マイル等

#### 同一属性に複数の特徴が含まれていないか確認する
温度、距離、時間などが含まれるような場合、修正する必要がある。

#### 異常値の存在を確認する
異常値は、必ずしも修正する対象にはならないが、予測結果などを歪める原因になるので、適宜判断が必要とのこと。

#### 欠損データを確認する
データの欠損は、関連する特徴量とターゲット変数の関係を正確に解釈することが困難になるため、適切に対応する必要があるとのこと。
対応には、以下の方法が考えられるが、結果が変わるので適宜判断する必要がある。
- 欠損しているデータを含む列や行を削除する。
- 同一列の他の値の平均値や0等で補完する。

# 考察
機械学習では、学習前に事前にデータセットを準備することが必要になってくる。適切に行われないことでモデルの精度が正しく把握できない。

# 参考
https://d1.awsstatic.com/ja_JP/training-and-certification/docs-ml/AWS-Certified-Machine-Learning-Specialty_Exam-Guide.pdf
AWS Kinesis Video Streamsを使ってブラウザでビデオチャット

AWS Kinesis Video Streamsを使って、ブラウザでビデオチャットをしてみます。
通信プロトコルは、WebRTCです。
最近のブラウザは、カメラやマイクも使えるので、ブラウザだけでビデオチャットできてしまいます。

以下の環境で、動作を確認しました。

・Windows10：Chromeブラウザ
・Amazon Fire：Silkブラウザ
・Android：Chromeブラウザ
・iPhone：Safari、Chromeブラウザ

以下は、Windows10のChromeブラウザでの画面です。こんな感じで、同時に接続している端末の画面を並べてみることができます。すべての端末でこのような画面でみれるのは、WebRTCのおかげです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/fbbec44e-50e0-f3e9-65b2-cb036ffec6b0.png)


以下の構成となりまして、御覧の通り、AWSを使うことで、ブラウザだけで実現できます。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/e3e32289-22b6-f399-2c29-d2090f0d3b97.png)

ソースコードもろもろは、以下のGitHubに上げておきました。

poruruba/WebRTC_VideoChat

https://github.com/poruruba/WebRTC_VideoChat

また、ブラウザだけで実現できるので、皆さんがすぐに触れるように、Webページとして公開しておきました。

https://poruruba.github.io/WebRTC_VideoChat/

# 準備

AWSを利用するため、事前にAWS側に設定が必要です。

①	IAMアカウントの作成
②	シグナリングチャネルの作成

①	IAMアカウントの作成
まずは、IAMアカウントを作成します。
以下の、AWS管理コンソールからユーザを作成します。AWS認証情報タイプは、アクセスキー - プログラムによるアクセスです。

https://us-east-1.console.aws.amazon.com/iamv2/home?region=ap-northeast-1#/users

AmazonKinesisVideoStreamsReadOnlyAccess と、インラインポリシで kinesisvideo:ConnectAsMasterとkinesisvideo:ConnectAsViewer を加えます。

そうすると、アクセスキーIDとアクセスキーシークレットが払い出されます。後で使うので覚えておきます。

②	シグナリングチャネルの作成
次に、Kinesis Video Streamsの管理コンソールから、シグナリングチャネルを作成します。

https://ap-northeast-1.console.aws.amazon.com/kinesisvideo/home?region=ap-northeast-1#/signalingChannels

名前は、接頭辞として、「VC-」の後に、好きな名前を付けてください。今回は、適当に、VC-Client1、VC-Client2、VC-Client3、VC-Client4の4つを作成しておきます。

準備はこれだけです。

# 使い方

以下のページにアクセスして下さい。

https://poruruba.github.io/WebRTC_VideoChat/

最初に、端末ごとに名前等を設定します。
さきほど、Client1から4まで作成しましたので、そのうちの1つを選択してください。選択したものはlocalStorageに記憶します。他の端末からアクセスする場合は同じものを選択しないようにしてください。
また、IAMで払い出したアカウントのアクセスキーIDとアクセスシークレットをAWS_ACCESSKEY_IDとAWS_SECRET_ACCESSKEYに指定します。

これで設定は完了です。
開始ボタンを押すと、カメラ録画が開始され、Client1にアップロードされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/11482576-8541-225c-3136-124754017d2b.png)

別の端末から同じようにアクセスします。名前はかぶらないようにClient2を選択します。
今度は、左上のセレクトから、Client1を選択し、追加ボタンを押下します。
そうすると、パネルが表示され、そこに別の端末でアップロードした動画が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/40ff82db-7307-bf45-3685-797978995024.png)

動画を双方向に送受信することも可能で、開始ボタンを押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/7b854fbb-5310-ea39-f4b7-af37390b1b30.png)

もとに端末に戻って、左上のセレクトからClient2を選択して追加ボタンを押下すれば、双方の動画が表示されたはずです。
さらに、別の端末で、Client3を選択して開始ボタンを押下して動画をアップロードした状態で、元の端末で、左上のセレクトからClient3を選択して追加ボタンを押下すれば、さらに動画表示のパネルが増えたかと思います。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/03d24ba2-199e-e0d7-92a7-1dcf976d09ee.png)

各パネルの右上のセレクトで、パネルの大きさを変えられます。
3番目の動画は、スマホからの動画であり、縦画面の動画になっています。

# 仕組み

特に難しいことはしておらず、以下のページに書いてある通りです。

　[AWS Kinesis Video StreamsでMMDをWebRTCで配信する](https://qiita.com/poruruba/items/7a52d5f01f0f46ec3c63)


# 補足

・音声もアップしていますが、PCのスピーカとマイクで再生すると、エコーが発生してしまうため、その場合は、ヘッドホンで使うとよいです。右上のmuteのチェックボックスをOffにしてください。

・チャットもできるようにしています。各パネルの右下のチャットボタンを押して、メッセージを入力すると、対象の端末にメッセージが送信され、対象の端末ではトーストが表示されるようにしてあります。

以上
Javaで何か作ってみる(2022/11/22 Day33)

## 今日やった事
- Javaの動画教材の演習問題である、ケーキ屋プログラムの作成を行った。  
&rarr;コミットした内容は[こちら](https://github.com/takamatsuryota3/Java/commit/4e891f4fedc4fbed3bb844dd47bb3fff3ff84d3e)
## 参考にしたもの
- [【超絶丁寧解説】Javaプログラミングをゼロから学ぶ！絶対挫折させない「基礎入門」講座【講師評価4.3】](https://www.udemy.com/course/uz-java-kiso/)  
&rarr;今回取り組んだのは、この動画教材の中の、**J1-EX1_総合演習（アルゴリズム）** の**総合演習（ケーキ屋プログラムの作成）** になる。
## 所感
- 例外処理も含めて、ケーキ屋プログラムを完成させる事が出来た。
## 明日の予定
- 動画教材の続きから進めていく。
Javaで何か作ってみる(2022/11/21 Day32)

## 今日やった事
- Udemyの動画教材を少し見た。（**J1-16_パッケージ** まで見た。）
## 参考にしたもの
- [【超絶丁寧解説】Javaプログラミングをゼロから学ぶ！絶対挫折させない「基礎入門」講座【講師評価4.3】](https://www.udemy.com/course/uz-java-kiso/)
    &rarr; Javaの勉強に使用しているUdemyの動画教材。
## 所感
- 内容理解は完璧。
- springそろそろ着手したいな。
&rarr;動画教材探しておくか。
## 明日の予定
- 引き続き、動画教材を進めていく。
特定のタグがついたEC2インスタンスを自動停止する

# ゴール

特定のタグがついたEC2インスタンスを自動停止する。

# 参考

基本は以下ページを参考にさせていただき実施しました。

https://qiita.com/uzresk/items/504d52bf1042c1067dde

が、ハマりポイントもあったので、ハマりポイントだけ忘れないために残しておきたいと思います。

# 構成

構成はシンプルに以下の通りです。

![ssm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/61a40953-3e1d-567e-1c06-01273153ac0e.png)

なお、EventBridge の新機能に、[Amazon EventBridge Scheduler](https://aws.amazon.com/jp/about-aws/whats-new/2022/11/amazon-eventbridge-launches-new-scheduler/)という機能も登場しましたが、今回は既存の Amazon EventBridge rules でも、SSM Automation は実行できるため、既存のものを利用しています。

Amazon EventBridge rules と　Amazon EventBridge Scheduler の違いについては以下の記事が参考になります。

https://dev.classmethod.jp/articles/amazon-eventbridge-scheduler-new-way-to-launch-tasks/

# SSMドキュメント

SSMドキュメントの箇所は、パラメータとタグだけ修正して以下の通り作成しました。

```yaml
description: StopEC2Instances Using Tags:StopTime
schemaVersion: "0.3"
assumeRole: "{{ AutomationAssumeRole }}"
parameters:
  StopTime:
    type: String
    default: test
    description: (Required) test
    allowedValues:
    - test
  AutomationAssumeRole:
    type: String
    description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf.
    default: ""
mainSteps:
  - name: StopEC2Instances
    action: aws:executeAwsApi
    inputs:
      Service: ssm
      Api: StartAutomationExecution
      DocumentName: AWS-StopEC2Instance
      TargetParameterName: "InstanceId"
      Targets:
        -
           Key: tag:env
           Values: 
             - "{{ StopTime }}"
```

# IAMロール

IAMロールには、AWS管理マネージドポリシーの`AmazonSSMAutomationRole`を付与しました。

# 実行1

SSM Automation から実行結果を確認してみます。

失敗しました。

![スクリーンショット 2022-11-23 17.59.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/be809bdc-27f5-6c05-732b-60adccf24fa7.png)

上記の「ステップID」をクリックしてみます。

![スクリーンショット 2022-11-23 17.59.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/bf9fec99-2a16-4420-1fca-a353919a2c9b.png)

**tag:GetResources** のIAMポリシーが足りないようです。

# IAMポリシーの追加

**tag:GetResources** のIAMポリシーを作成し、IAMロールにアタッチします。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "tag:GetResources",
            "Resource": "*"
        }
    ]
}
```

# 実行2

次の通り、正常に特定のタグがついたEC2インスタンスが停止されたことが確認できました。

SSM Automation から。
![スクリーンショット 2022-11-23 18.06.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/6ab8502b-27e7-17dd-8c4e-afe8cd3a1445.png)

EC2 から。
![スクリーンショット 2022-11-23 18.07.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/9618df8c-f376-1a39-6239-9656c8090b73.png)
createrepo_c と RHEL8



RHEL8サーバへのパッケージ導入のため、ローカルにdnf(yum)リポジトリを作成したときの失敗談。

:::note info
とりあえず結論、というか注意点だけ先に書いておくと、
「createrepo_c コマンドで作成された RHEL8 のリポジトリーミラーは、モジュール情報を正しく処理しません。」
つまりRHEL8で下手に createrepo_c を使ったら面倒なことになるので注意、というお話です。
:::

リポジトリサーバにて createrepo_c コマンドでメタデータを作成した後、
お目当てのサーバで、下記のようにインストールを実行した。

```
dnf install javapackages-filesystem
```

すると、見慣れないエラーが出る。

```
CRITICAL モジュラーパッケージ 'javapackages-filesystem-5.3.0-1.module+el8+2447+6f56d9a6.noarch' のモジュラーメタデータは利用不可です、システムにインストールはできません
(合わせて右記も出力された「No available modular metadata for modular package」)
```

よくわからないが、どうやら新しく導入された概念(Modularity)が関係しているようだ。

> RHEL 8/Fedora 28で導入されたModularity
> https://rheb.hatenablog.com/entry/201812-modularity

上記の記事を参考に、createrepo したディレクトリを見てみると、
どうやら下記が存在していないといけないようだが、ない。

```
modules.yaml.gz
```

調べてみたところ、下記の「既知の問題」の影響で、createrepo_c コマンド実行時に削除されてしまった模様。
https://access.redhat.com/ja/solutions/6319191

上記記事の解決法ではキャッシュから作成しているが、今回はRHEL8のメディアから対象ファイルを復元。
無事エラーが解消し、パッケージ導入成功！
DynamoDBのlimit値によるAppSyncのエラーと対処方法

# 概要
この記事では、DynamoDBのlimit値によるAppSyncのエラーと対処法について紹介します。

# 内容
AppSyncをウィザードで作成すると、自動でリゾルバーを生成します。
これはlist機能も同様で、下記のようなリクエストマッピングテンプレートが記載されます。

```
{
  "version": "2017-02-28",
  "operation": "Scan",
  "filter": #if($context.args.filter) $util.transform.toDynamoDBFilterExpression($ctx.args.filter) #else null #end,
  "limit": $util.defaultIfNull($ctx.args.limit, 20),
  "nextToken": $util.toJson($util.defaultIfNullOrEmpty($ctx.args.nextToken, null)),
}
```

ただ、このまま使用すると、DBのデータが20件を超えた時点で、
期待の挙動をしなくなります。

例えば、全データを取得したくても20件しか返ってこない、
filterで条件を絞ってクエリを送っても何も返ってこない、などが起きます。

これは``limit``に``20``が設定されていることが原因です。

仮に、filterで条件を絞ってクエリを送った場合、
DBの中から20件取得して、そこ中から条件を絞った結果を返します。
そのため、DBにはデータはあるにもかかわらず、
取得した20件にないことで指定のデータが返ってこないことになります。

単純な解消方法は、limit値を上げることです。

```
{
  "version": "2017-02-28",
  "operation": "Scan",
  "filter": #if($context.args.filter) $util.transform.toDynamoDBFilterExpression($ctx.args.filter) #else null #end,
  "limit": $util.defaultIfNull($ctx.args.limit, 500),
  "nextToken": $util.toJson($util.defaultIfNullOrEmpty($ctx.args.nextToken, null)),
}
```

この方法で、ひとまず500件を取得するように変更できます。
データの数が決まっている場合や、ある程度想定できる場合は、
この方法で、数値を直接変更すれば問題ありません。

また、
ScanではなくQueryで取得することで解決できることもあります。
詳しくは、[ScanではなくQueryで取得するAppSyncのリゾルバー](https://qiita.com/inoue-mn/private/e3234a1679123b99d1b2)を参照ください。
Voltaで特定バージョンのNode.jsをUninstallしたい

# はじめに

[Volta公式のUninstallコマンドに関するリファレンス](https://docs.volta.sh/reference/uninstall)には、packageのUninstallについては言及があるものの、Node自体については特にナシ
Nodeバージョンを増やしすぎて、`volta list all`した時にわんさか出てくるのも嫌なので、削除方法をメモ

2019年3月にはIssueが発行されているが、まだVoltaビルトインの機能としては対応されていないみたい
[Support volta uninstall for node and yarn #327](https://github.com/volta-cli/volta/issues/327)

# 方法

以下パスにあるバージョン番号のディレクトリを削除

- Mac - `~/.volta/tools/image/node/`
- Win - `%LOCALAPPDATA%\Volta\tools\image\node\`

`rm -rf ~/.volta/tools/image/node/x.x.x`
Finderで消しに行ってもいいが、コマンドで実行すると楽

## 例

```terminal
$ volta list node
⚡️ Node runtimes in your toolchain:

    v16.13.0
    v16.17.1 (default)
    v18.12.1

$ rm -rf ~/.volta/tools/image/node/16.13.0

$ volta list node                         
⚡️ Node runtimes in your toolchain:

    v16.17.1 (default)
    v18.12.1 
```

# 参考

- [VoltaでNodeをアンインストールする](https://blog.70-10.net/2021/09/29/volta-uninstall-node/)
- [Unclear how to remove Node.js version #855](https://github.com/volta-cli/volta/issues/855#issuecomment-713218171)
通信スタブ化に利用できるOHHTTPStubsの公式ドキュメントが古い(iOS)

<h1>OHHTTPStubsの公式ドキュメントが古い (iOS)</h1>

HTTP通信をスタブ化するのに、OHHTTPStubsを使うことはよくあると思います。しかし、<a href="https://github.com/AliSoftware/OHHTTPStubs/wiki/Usage-Examples">公式ドキュメント</a>が古いです。コンパイルエラーを解消できずそのまま諦めた人も多いのでは?

<h2>結論</h2>

以下のような処理を
```
import OHHTTPStubs

stub(condition: pathEndsWith("/niwaka")){
   _ in
   let data = "niwaka".data(using: .utf8)!
   return OHHTTPStubsResponse(data: data, statusCode:200, headers:nil)
}
```

以下のように変更すると動きます。
```
import OHHTTPStubs

stub(condition: pathEndsWith("/niwaka")){
   _ in
   let data = "niwaka".data(using: .utf8)!
   return OHHTTPStubs.HTTPStubsResponse(data: data, statusCode:200, headers:nil)
}
```
<h3>何が変わったのか?</h3>

```
OHHTTPStubsResponse(data: data, statusCode:200, headers:nil)
```
を

以下のように変えるのです。
```
OHHTTPStubs.HTTPStubsResponse(data: data, statusCode:200, headers:nil)
```

終わり。
ActiveRecordにおけるattributeの参照

## そもそもActiveRecordとは
Railsが使っているORマッパーです。
これによって、RailsのモデルクラスとDBのテーブルが結び付けられます。
Railsアプリケーション内ではSQL文を書く必要はなく、ActiveRecordに則った書き方をすればいい感じにSQL文が発行されます。

## instance.attributeの形でなぜ参照することができるのか?
例えばfirst_name, last_name, email, password, age属性を持つUserクラスがあるとすると, Railsでは下記のように簡単にattributeを参照することができます。

```.rb
    user = User.last
    user.first_name # <= これ
    user.email # <= これ
    user.password # <= これ
```
なぜActiveRecordでは、このような参照の仕方ができるのでしょうか。
=> ActiveRecordがいい感じにattributeの値を返すインスタンスメソッドを自動で定義してるから。

#### インスタンスメソッドを見てみる
![スクリーンショット 2022-10-16 11.32.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849988/d03585eb-769c-566f-20a3-1c2a9f79ae74.png)
↑ attributeがメソッドとして定義されていることがわかると思います。

#### メソッドはどこに定義されているのか
ローカルのモデルには定義されておらず、Rails本体に定義されています。

https://github.com/rails/rails/blob/main/activerecord/lib/active_record/attribute_methods.rb#L57

#### オーバーライド
インスタンスメソッドなので、しようと思えばオーバーライドもできます。(しなくてもいいです)

試しにやってみます。(RSpecの勉強中なのでRSpecを使ってやってみます。)
**オーバーライド以前**
![スクリーンショット 2022-10-16 11.45.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849988/54002f49-bada-7d04-3d6c-17df0224fc75.png)
first_nameメソッドがインスタンスのfirst_name attributeを返すため返り値が"hello"になってれば正しい挙動です。
![スクリーンショット 2022-10-16 11.51.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849988/fa5e8c07-2699-c74a-ac84-4aeb6f562280.png)

**オーバーライド後**
![スクリーンショット 2022-10-16 11.43.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849988/ffcf54a8-1d6a-15e4-91c7-790365780e80.png)
![スクリーンショット 2022-10-16 11.55.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849988/12b44939-7125-672d-034f-e4131908e6ee.png)
結果を見るとオーバーライドされていることがわかると思います。

## 参考にしたサイト

https://railsguides.jp/active_record_basics.html

## 終わりに
インターンをしてみて特に感じているのが、コードを追うことの重要性です。
以前はただなんとなく便利なものを使っている状態でしたが、それだと根本的に理解できておらず伸び悩むことに気付かされました。
できる限りロジックを理解することはかなり大事なのかなと思います。
GitHub Actionsのワークフローの一部を無効化する

# 1. ワークフロー全体を無効化する

`on.<push|pull_request|pull_request_target|workflow_run>.branches-ignore`
```yaml
on:
  push:
    branches-ignore: ['**']
```

# 2. ジョブを無効化する

`jobs.<job_id>.if`
```yaml
jobs:
  test:
    if: false
```

# 3. ステップを無効化する

`jobs.<job_id>.steps[*].if`
```yaml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - run: echo 'Hello, world!'
        if: false
```

# 参考

- [GitHub Actions / Using workflows / Workflow syntax for GitHub Actions
](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions)
- [GitHub Actions / Using job / Using conditions to control job execution](https://docs.github.com/en/actions/using-jobs/using-conditions-to-control-job-execution)
MinIO(S3互換環境)をDockerで構築する

## 概要

- ローカルでS3環境が欲しいのでDockerで簡易に構築する
- あくまで学習用なので必要最低限の設定としておく
- MinIOの操作はCLIから行うのでmcコマンドもインストールする

## Docker設定

- docker-composeは下記の通り
  - コンテナイメージは[DockerHub](https://hub.docker.com/r/minio/minio)から最新をPullする
  - "MINIO_ROOT_PASSWORD"は短いとコンテナが起動しないので注意

``` yaml:docker-compose.yml
version: '3.7'

services:
  minio:
    image: minio/minio:RELEASE.2022-11-17T23-20-09Z
    container_name: minio
    hostname: minio
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - ./data:/data
    command: "server /data --console-address :9001"
    environment:
      MINIO_ROOT_USER: minio
      MINIO_ROOT_PASSWORD: minio1234
```

## mcコマンド設定

- 公式ドキュメントがあるので一読しておく >> [MinIO Clinet](https://min.io/docs/minio/linux/reference/minio-mc.html?ref=docs-redirect#test-your-setup)
  - 環境(Linux,Mac...)ごとに用意されているみたいなので今回はLinuxを選択

```
# cd /tmp
# wget https://dl.min.io/client/mc/release/linux-amd64/mc
# ls -l
# chmod +x mc
# ls -l
# mv mc /usr/local/bin/
```

- 次にコンフィグファイルを用意する

```
# mdkir ~/.mc
# touch ~/.mc/config.json
# vi ~/.mc/config.json
```

``` json: config.json
{
	"version": "10",
	"aliases": {
		"minio": {
			"url": "http://localhost:9000/",
			"accessKey": "minio",
			"secretKey": "minio1234",
			"api": "S3v4",
			"path": "auto"
		}
	}
}
```

- Minioコンテナを立ち上げてCLI操作できるか確認する

```
# docker-compose up -d
Creating network "minio_default" with the default driver
Creating minio ... done

# mc mb minio/sample01
Bucket created successfully `minio/sample01`.
# mc ls minio/sample01
# mc ls minio
[2022-11-23 17:30:45 JST]     0B sample01/
```

- バケットの作成ができれば環境構築完了
- ブラウザで<http://localhost:9001>へアクセスしてGUIからも確認

## 参考

- <https://hub.docker.com/r/minio/minio>
- <https://min.io/docs/minio/linux/index.html>
- <https://min.io/docs/minio/linux/reference/minio-mc.html?ref=docs-redirect#>
[Node.js] TypeScriptコードの変更を検知し再起動する方法

# はじめに

TypeScriptを使ってアプリケーション開発をしている時、以下のことに煩雑さを覚えたので解決方法をメモ

1. TypeScript→JavaScriptにトランスパイル
1. サーバを起動
1. コードを修正
1. サーバを止める
1. TypeScript→JavaScriptにトランスパイル
1. サーバを起動

`console.log()`を一個増やしたいなって思うだけでもこれだけの手順を踏まないといけないのは効率が悪すぎる

# `ts-node-dev`を使用する

公式はこちら

https://www.npmjs.com/package/ts-node-dev

## インストール

`npm i ts-node-dev --save-dev`
`yarn add ts-node-dev --dev`

## 使い方

`ts-node-dev [node-dev|ts-node flags] [ts-node-dev flags] [node cli flags] [--] [script] [script arguments]`

サンプル
`ts-node-dev --respawn src/index.ts`

これをnpm scriptsに登録しておくと、楽に呼び出せる

```package.json
  "scripts": {
    "dev": "ts-node-dev --respawn src/app.ts",
  }
```

### 例

```terminal
% npm run dev

> yourapp@1.0.1 dev
> ts-node-dev --respawn src/app.ts

[INFO] 17:40:21 ts-node-dev ver. 2.0.0 (using ts-node ver. 10.8.1, typescript ver. 4.7.3)
Node.js app listening on port 3000. Or Access http://localhost:3000
```

ソースをいじって保存すると勝手に再起動された

```terminal
[INFO] 17:43:55 Restarting: {PATH}/src/app.ts has been modified
Node.js app listening on port 4000. Or Access http://localhost:4000
```

## フラグ

- `--respawn` - スクリプトが終了しても引き続き監視を続ける(参考: [node-devのGitHub](https://github.com/fgnass/node-dev#command-line-options))

## 公式によると

node-devのTypeScriptサポートや、nodemonより早いらしい......
サクラエディタでファイルの中身をCSV形式に変換する作業の覚書

# 背景
業務でファイルを手作業でCSV形式に変換する機会があったので、その作業手順を記録しておきます。
また、初学者の方は正規表現に慣れるのにもちょうどよいと思います。
※本記事では正規表現についての解説は割愛させていただきます。

# 使用するツール
- サクラエディタ（バージョン：2.4.1.2849）

# 手順
- 以下のような、タブ区切りのデータを例に実施します。
![edit_to_csv_example.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378829/ea3d0281-ecd5-ee5a-43be-889ef7c9d1b0.png)


1. 変換するファイルをサクラエディタで開く。
2. ctrl + R で置換ウインドウを開く。「正規表現」のボックスにチェックを入れる。
3. 以下の項目を順次置換していく。置換前には「該当行をマーク」を実行しておくとよい。
    ・行頭（正規表現：^）を「"」に置換する。置換前に「^」、置換後に「"」を入力し、置換する。
    ・タブ区切り（正規表現：\t）を「","」に置換する。置換前に「\t」、置換後に「","」を入力し、置換する。
    ・行末（正規表現：\\$）を「"」に置換する。置換前に「$」、置換後に「"」を入力し、置換する。
    ※以下は任意
    ・改行コードCRLF（正規表現：\r\n）を「\n」に置換する。置換前に「\r\n」、置換後に「\n」を入力し、置換する。
4. 置換が完了したら、「ファイル」から「名前を付けて保存」をする。適宜、ファイル名、文字コード、CP、BOMなどを設定します。
5. 変換後は以下のようになります。
![edited_csv.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378829/d7ac925b-650f-da9c-e3d6-2719886b4fae.png)

# まとめ
変換箇所、置換後の一覧は以下の通りです。
|変換箇所|置換後|説明|
|:--:|:--:|:--:|
|^|"|行頭に「"」をつける|
|\t|","|タブ区切りを「","」に置換する|
|\\$|"|行末に「"」をつける|
|\r\n|\n|改行コードCRLFをLFに変換する|

以上となります。覚書ではありますが、何らかのお役に立てば幸いです。
便利だけど知られていないレアなluaスクリプト関数紹介：ProjectOnPlane()

## 記事の狙い
vciのスクリプトはいろいろ便利なAPIが搭載されているのですが、一見して使い道がわからなかったり、文書や使用例が少なかったりして知られていない関数があるように思います。
実際、知っていれば結構簡単に実装できるのに、知らないというだけで大変な労力をかけて自作するというもったいない例を見ることも多いです。
本記事では、そのような**便利だけど隠れた関数を発掘**し、皆様の開発時間の節減や品質の向上によってVCI界隈全体に貢献することを目的とします。（という前文が書かれた備忘録）

## 今回紹介する関数
***Vector3.ProjectOnPlane(vector: Vec3, planeNormal: Vec3) :Vec3***

## 使用率（レア度）
他人使用例0例　(レア度SSR)
調査方法：VScodeでvci scriptが保存されるフォルダ内の全ファイルを検索した
対象：2019年6月より筆者のいる空間で出たVCIスクリプト共有を可能にしている全VCI(208ファイル)

## 何をする関数なの？
planeNormalを法線ベクトルとする面へのvectorベクトルの投影ベクトルを求めます。(virtualcast wikiより引用)

## 使いどころ
- UIなどの**平面上にオブジェクトを拘束**する。
- **向いている方向を求める**
- 平面上での距離を求める

以下解説します。

### UIなどの**平面上にオブジェクトを拘束**する
もっとも単純な使い方です。この関数を使うと、指定平面に対してオブジェクトを垂直に落とした場所が求まります。
これはUIなどで多用します。<!-- 図を入れよう -->
![2022113023174658.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494837/70a0f716-45ee-7f43-b41e-bc7270ff7629.png)
上記は、[前回のアドベントカレンダーの記事](https://qiita.com/sakkinonana/items/1150b11ae4df479a3635)で作ったカラーピッカーですが、パレット上からの色を拾うためのスタイラスペン（画像の円錐）でパレット表面を動くポインター球の位置を動かしています。

そのほか、VRCのゲームワールドなどでよくある、マップ上にキャラクター現在位置を表示するようなUIなど、使い道は様々です。

###  **向いている方向を求める**
これは応用になりますが、現在向いている方向を求めることもできます。
基準面が座標系に直立であればEulerのy軸だけ指定などで事足りるのですが、斜めだったりするとオイラー角では途端に計算が複雑になります。
以下は、平面plainに対して棒状のarrowというオブジェクトの角度を求めます。
dummyというオブジェクトをplainの子オブジェクトにしてコメントアウトを外せば、arrowに追従してぐるぐる回ります。
またUIの話になってしまいますが、時計のようなぐるぐる回すUIには便利です。

```lua: main.lua
-- arrowの平面plain(法線ベクトルがNplain)上での向いている方向を求める
local plain = vci.assets.GetTransform("plain")
local arrow = vci.assets.GetTransform("arrow")
--local dummy = vci.assets.GetTransform("dummy")

function update()
    local Nplain = plain.GetUp()
    local Darrow = arrow.GetForward()
    local PDarrow = Vector3.ProjectOnPlane(Darrow, Nplain)
    -- dummy.SetLocalRotation(Quaternion.AngleAxis(Vector3.SignedAngle(plain.GetForward(),PDarrow,Nplain),Vector3.up))
    print(string.format("direction of projected arrow:%f"
        ,Vector3.SignedAngle(plain.GetForward(),PDarrow,Nplain)))
end

```

### 平面上での距離を求める
また、当然**基準点からの位置・距離も取得できるため、柔軟なUIを作ることも可能**です。よくある実装では衝突判定などでボタンの操作を検知しますが、ボタンの形状や数が変わってしまうため画面遷移のようなものがむつかしくなります。製作上もオブジェクトを多数管理せねばならず煩雑です。位置を読み込む形式にすれば、変化に対する管理が格段に楽になります。（例えば、公式のホワイトボードなどはおそらくこの関数を使っているものだと思われます）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494837/76c8a2ee-2f77-0710-76e3-e0130b830973.png)
上記のように、useしたときのポインターの位置をとることで、作動させることができます。キーボードのようなボタンが多いUIや、可変形状のものの際でも柔軟に対応することができます。


<!--
```lua: main.lua
local panel = vci.assets.GetTransform("panel")
local pointer = vci.assets.GetTransform("pointer")

function Onuse(use)
    local npanel = panel.GetUp()
    local pos_panel = panel.GetPosition()
    local pos_pointer = pointer.GetPosition()

    local prj_pointer = Vector3.ProjectOnPlane(Darrow, Nplain)
    
    
end
```-->
GOで最初につまづいたこと

# GOのパス設定がよくわからない
GOの勉強を始めようとしたが、つまづいたところがあったのでメモがてらに投稿。
## 問題：GOPATHやGOROOTとか何が何かわからない

### $GOPATH
goのワークスペースのルートディレクトリ
GOPATHの中の構造は以下のようになっている
`src/` : Go ソースコードの場所（例: .go、.c、.g、.s）。
`pkg/` : コンパイルされたパッケージコードの場所（例: .a）。
`bin/` : Go によってビルドされたコンパイル済み実行可能プログラムの場所。

### $GOROOT
異なるGoバージョンを変更する必要がないなら気にしなくていい。

### $PATH
インストールしたパッケージのコマンドなどが記述されたバイナリファイルが格納される場所です。コマンドなどはここから参照してくる。


## 結論
私はgoの開発をする際以下のようなディレクトリ構造で開発することにした。
（合っているかはわからないが…）

### 階層構造
```
home
├──そのほか
go ← ここがGOPATH
├── src
│   ├──goプロジェクト1
│   ├──goプロジェクト2
│   └──goプロジェクト3
├── pkg
└──　　bin
```

### コマンドライン
```
export GOPATH=$HOME/go;
export PATH=$PATH:$GOPATH/bin;
```
Amazon Time Sync とは

## 勉強前イメージ

最近出たやつな気がする

## 調査

### Amazon Time Sync とは

AWSのサービスで、EC2のインスタンスに時刻情報を送るサービスを提供していました。
[NTP](https://qiita.com/miyuki_samitani/items/68dd667e8b400f8b5732) と呼ばれるサービスでネットワークに接続される機器に時間を同期します。

プライベートサブネットにいるインスタンスでインターネットに接続できないEC2がいてもAmazon Time Syncで時間の同期を行うことができるのがこのサービスのメリットになります。
追加でNTP用にNatGatewayなどを構築する必要がありません。

今回、2022/11に発表されたのはAmazon Time Syncの対象をEC2のみでしたが
AWS以外の全世界のコンピュータがAmazon Time Syncを使えるようになりました。
公開NTPサービスとして使えるようになったということです。

## 勉強後イメージ

最近でたサービスちゃうやん・・・たまたま見たから。。。。。
誰でも使えるようになったということね。

## 参考

- [Amazon Time Sync が公開 NTP サービスとしてインターネット経由で利用可能に](https://aws.amazon.com/jp/about-aws/whats-new/2022/11/amazon-time-sync-internet-public-ntp-service/)
- [Amazon Time Sync Service のご紹介](https://aws.amazon.com/jp/about-aws/whats-new/2017/11/introducing-the-amazon-time-sync-service/)
Dockerを用いてYOLOXの環境を構築する

前提条件 [ここ](https://qiita.com/HarunobuEnami/items/de1c15406820ceacff08)の手順に従いnvidia-container-toolkitが使えること
# GitHubからDockerfileなどを入手
[ここ](https://github.com/HarunobuEnami/new_YOLOX)からclone

```
$ git clone https://github.com/HarunobuEnami/new_YOLOX
$ cd new_YOLOX
$ docker build .
```
ビルドが完了したら

```
$ docker run --gpus all -it -v /home/user/E/gpgpu/:/root/ --shm-size 8g (imageid)
```
のように起動．(gpusの後ろは使用するgpuの数に合わせて適時変えてください)

すると /workspaceで起動するので cd new_YOLOXとしてYOLOXのマニュアルにしたがって使えます．
ScanではなくQueryで取得するAppSyncのリゾルバー

# 概要
この記事では、AppSyncのlist機能をScanではなくQueryでおこなうリゾルバーを紹介します。

# 前提条件
- DynamoDBが用意されていること
- AppSyncのスキーマが作成されていること

# デフォルト
AppSyncをウィザードで作成すると、デフォルトで下記のようなリクエストマッピングテンプレートが生成されます。
```
{
  "version": "2017-02-28",
  "operation": "Scan",
  "filter": #if($context.args.filter) $util.transform.toDynamoDBFilterExpression($ctx.args.filter) #else null #end,
  "limit": $util.defaultIfNull($ctx.args.limit, 20),
  "nextToken": $util.toJson($util.defaultIfNullOrEmpty($ctx.args.nextToken, null)),
}
```
``operation``が``Scan``になっていることが見て取れます。

# 変更後
Scanではテーブル内の全データを確認しますが、
Queryに変更することで、指定された値（ここでは``broadcaster``）と一致するデータのみ確認をします。

## スキーマ
対象箇所のみ抜粋。
```graphql
type Radio {
	broadcaster: String!
	program_name: String
	cast: [String!]
	datetime: String!
	favorite: Boolean
}

type RadioConnection {
	items: [Radio]
	nextToken: String
}

input TableRadioFilterInput {
	favorite: TableBooleanFilterInput
}

input TableBooleanFilterInput {
	ne: Boolean
	eq: Boolean
}

type Query {
	listRadio(
		broadcaster: String!, #ここにキーを追加
		filter: TableRadioFilterInput,
		limit: Int,
		nextToken: String
	): RadioConnection
}
```

## リゾルバー
```
{
  "version": "2017-02-28",
  "operation" : "Query",
    "query" : {
        "expression" : "#broadcaster = :broadcaster",
        "expressionNames" : {
            "#broadcaster" : "broadcaster"
        },
        "expressionValues" : {
            ":broadcaster" : $util.dynamodb.toDynamoDBJson($ctx.args.broadcaster)
        }
    },
  "filter": #if($context.args.filter) $util.transform.toDynamoDBFilterExpression($ctx.args.filter) #else null #end,
  "limit": $util.defaultIfNull($ctx.args.limit, 500),
  "nextToken": $util.toJson($util.defaultIfNullOrEmpty($ctx.args.nextToken, null)),
}
```

# 実行結果
## DB
![DB](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318120/71ed88bc-a64c-9b46-f7ed-9a167119dfa7.png)
## クエリ
![クエリ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318120/250863e0-0166-390e-5de5-dedc13ef0734.png)
取得できることを確認できました。
Kotlin エンジニアが Java を書き直して感じたことまとめ

【完走賞】MxShun ひとりマラソン 🏃 Advent Calendar 2022 毎週金曜日は Kotlin の記事を書こう！2記事目です。

1年あまりサーバサイド Kotlin を書いていましたが、この度の転職で Java8 時代のシステム保守も行うようになりました。
Kotlin エンジニアのバックグラウンドを持つ私が、改めて Java を書き始めて感じたことをまとめます。

### 1. 基本ミュータブルで怖い + 都度 `final` を付けるの面倒
Kotlin のクラス・関数・変数はデフォルトで `final`、つまり不変で継承不可です。スコープは最小限でイミュータブルに保つという思想から来ているのでしょうか。コードの見通しのたてやすさから私もこの思想を好みます。

他方、Java は気にしないとミュータブルで継承可能です。都度 `final` を付ける必要があるので書くのも面倒ですし、かなり冗長です。
って言うか、型宣言や末尾の `;` がないのも改めて素敵ですね。

```kotlin
// in Kotlin
companion object {
    private val USER_ID = 1
    private val USER_NAME = "MxShun"
}
```

```java
// in Java
private static final Integer USER_ID = 1;
private static final String USER_NAME = "MxShun";
```

### 2. 名前付き引数 使いたい
Kotlin は他のモダン言語と同様に名前付き引数を利用することができます。特に引数が多い関数では、処理のどのインプットにどの値を使うのかが分かりやすくなるので私は好きです。プロダクトコード全体で名前付き引数を使うルールとしたほどです。

Java では名前付き引数が使えません。なので、同じようなことを実現しようとすると説明変数に値を入れるなどちょっとばかし工夫が必要な気がします。

```kotlin
// in Kotlin
val id = assignIdFromBio(
    name = "MxShun",
    birthDate = LocalDate.of(1997, 11, 23)
)
```

```java
// in Java
final String id = assignIdFromBio(
    "MxShun",
    LocalDate.of(1997, 11, 23)
);
```

### 3. `Kotlin.Collection` 使いたい
Kotlin は Collection 関数が豊富です。さながら、Kotlin の中核機能と言っても遜色はないと思っています。

Java では SE8 での stream 関数の追加で幾分ましになっていますが、それでもメソッドチェーンや `.stream()` と `toList()` を開始・終端処理として挟むのは冗長です。

```kotlin
// in Kotlin
val ids = users.map {
    it.id
}
```

```java
// in Java
List<String> ids = users.stream()
    .map(user -> user.id)
    .toList()
```

### 4. スコープ関数 使いたい
これは意見が分かれそうです。Kotlin の表現方法のひとつとしてあって然るべきものだと私は思います。

```kotlin
// in Kotlin
val ftpDto = FtpDto().apply {
    setHostName(FTP_HOST_NAME)
    setUserName(FTP_ACCOUNT_NAME)
    setPassword(FTP_PASSWORD)
    setOutputFilePath(FTP_PATH + outputFileName)
    setLocalFilePath(localFilePath)
}
ftpService.get(ftpDto)
```

```java
// in Java
FtpDto ftpDto = new FtpDto();
ftpDto.setHostName(FTP_HOST_NAME);
ftpDto.setUserName(FTP_ACCOUNT_NAME);
ftpDto.setPassword(FTP_PASSWORD);
ftpDto.setOutputFilePath(FTP_PATH + outputFileName);
ftpDto.setLocalFilePath(localFilePath);
ftpService.get(ftpDto);
```

### まとめ
改めて、Kotlin は Java の「ちょっと不便だな」ってところを上手くラップしてくれているのが分かりました。Kotlin の思想を逆に Java が取り込む例も増えていますが、やっぱり Kotlin っていいなってなりました。
Db2 on CP4Dへの接続 - "データベース詳細"を使用して"プラットフォーム接続"を作成する

Cloud Pak for Data 内のDb2サービスへ接続できた4つの方法をご紹介しています。 使用頻度が高いと思われる順に記事を並べました。

1. ["データベース詳細"を使用して"プラットフォーム接続"を作成する](https://qiita.com/mi-shimo/items/7abf2bb699c7c4267cce)
1. [NodePort サービスを使用して接続する](https://qiita.com/mi-shimo/items/f52aea45dad0835b29cc)
1. [ClusterIP サービスを使用して接続する](https://qiita.com/mi-shimo/items/2f0d5caa654e5721271d)
1. [Db2 Podに直接接続する](https://qiita.com/mi-shimo/items/32f8609975caf0015b56)

ここでは Db2サービスへの接続情報を Cloud Pak for Data コンソールの"データベース詳細"から得て "プラットフォーム接続"を作成します。
(2023/04/07 追記) 同じ手順がCloud Pak for Data 内のDb2 Warehouseサービスでも使えます。

## "データベース詳細"からDb2サービスへの接続情報を得る
CP4Dコンソールのメニューから データ→ データベースを選択します。 
接続したいDb2サービスの詳細を開きます。 そこで データベース名、HOSTNAME、アクセス情報を確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/855502/921cf903-ebff-4b4f-6d80-0bf27eac83cf.png)

- データベース名 : BLUDB 
- HOSTNAME : 10.248.64.33
- アクセス情報 ここでは 例としてJDBC Connection URLを使用します。 (上図では encryptionAlgorithm=2の後に ";"セミコロンがないので注意しましょう） 

```
 - JDBC Connection URL 
   jdbc:db2://<CLUSTER_ACCESSIBLE_IP>:32320/BLUDB:user=-;password=<password>;securityMechanism=9;encryptionAlgorithm=2;
```
- JDBC Connection URL から ポートが32320であることと ２つの接続プロパティーがついていることがわかります。 ２つの接続プロパティーの意味は次の通りです
        - securityMechanism=9 .. 暗号化されたユーザー ID およびパスワード
        - encryptionAlgorithm=2 .. 256 ビット AES 暗号化

(参考) [IBM Data Server Driver for JDBC and SQLJ の構成プロパティー](https://www.ibm.com/docs/ja/db2/11.5?topic=information-data-server-driver-jdbc-sqlj-configuration-properties)

もし Dbサービスへ接続するユーザーIDがない場合は　ユーザーIDの追加についての記事[Db2 on CP4Dへの接続 - ユーザーを追加する](https://qiita.com/mi-shimo/items/4543945d1a659514554c)を参照いただいて作成してみてください。　(2023/04/17 修正) 


## "プラットフォーム接続"を作成する
CP4Dコンソールのメニューから データ→ プラットフォーム接続を選択します。 
新規接続→ IBM Db2を選択します。
接続の作成で"データベース詳細"から得た情報を入力していきます。
- データベース : BLUDB 
- ホスト名または IP アドレス : 10.248.64.33
- ポート : 32320
- 資格情報設定 : デフォルトの"共有"使用する
- ユーザー名 : 指定されたものや 作成したものを使用する
- パスワード  : 指定されたものや 作成したものを使用する  
- ユーザー名とパスワードのセキュリティー・メカニズム : 暗号化されたユーザー ID およびパスワード
- ユーザー名とパスワードの暗号化アルゴリズム : 256 ビット AES 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/855502/161393d0-d7cf-ed78-59bc-9fc54ae6e705.png)

最後に接続のテストをおこなってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/855502/782c4ab0-40e6-1a3e-197f-d745ff0b5288.png)

テストが正常に終了すれば 保管します。

## おわりに
ここでは Db2を Cloud Pak for Dataのコンソールで "データベース詳細"から情報を得て "プラットフォーム接続"を作成しました。
Cloud Pak for Dataのコンソールの"データベース詳細"で表示されるDb2情報は Db2 NodePort サービスのものです。

### 実施環境 Db2 
- IBM Cloud VPC Gen2
- OCP 4.10.32
- CP4D 4.5.3 
  - Db2 Version 11.5.7.0-cn7

### 実施環境 Db2 Warehouse (2023/04/07 追記)
- CP4D 4.6.4 
  - Db2 Warehouse Version 11.5.8.0-cn2



### 参照文献
- [Working with integrated IBM Db2 databases](https://www.ibm.com/docs/en/cloud-paks/cp-data/4.5.x?topic=database-db2-databases#work-with-db-db2aese)
- [IBM Data Server Driver for JDBC and SQLJ の構成プロパティー](https://www.ibm.com/docs/ja/db2/11.5?topic=information-data-server-driver-jdbc-sqlj-configuration-properties)
- [Db2 on CP4Dへの接続 - ユーザーを追加する](https://qiita.com/mi-shimo/items/4543945d1a659514554c)　(2023/04/17 追加)
cudaをdockerで使う方法

本記事ではyoloを使うことを例として，cudaを実行できる環境をubuntu上にdockerで構築する方法を説明します．
#イントロ

cudaの上で動くアプリケーションはそのバージョンごとに必要とするcudaや依存するパッケージのバージョンがバラバラである．例えば，tensorflowには2系と1系があるが，それによって必要とするcudaのバージョンが異なり，また，yoloが要求するtensorflowのバージョンも異なる．すなわち依存関係が極めて複雑であり，直接OS上にパッケージをインストールして使うのは困難かつ，既存の環境を破壊する恐れがあり危険である．そこで，dockerというコンテナ方式の仮想環境を用いることでその作業専用の依存関係を満たした環境を作成し，他の環境に影響を与えないうようにすることが求められる．本記事ではdockerのインストールが完了している環境においてgpgpuをdockerで使う方法を解説する．


# 前提条件
dockerインストールが完了していること．(必要に応じて docker-composeもインストールする)

#nvidia-smiを実行してnvidiaのドライバが正しくインストールされているか確認する

```
$ nvidia-smi 

Thu Oct 28 15:18:41 2021       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 460.91.03    Driver Version: 460.91.03    CUDA Version: 11.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  GeForce GTX 166...  Off  | 00000000:01:00.0  On |                  N/A |
| N/A   47C    P8     5W /  N/A |   1001MiB /  5944MiB |     10%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

```
のように表示されればドライバはインストールされている．されていない場合には先にドライバのインストールを行う．Ubuntuの場合には sudo ubuntu-drivers autoinstall コマンドでインストール可能

```
$ sudo ubuntu-drivers autoinstall

```

# nvidia container toolkitをインストールする
[公式サイト](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker)のやり方通り

```
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
   && curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - \
   && curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
```

```
$ sudo apt update
```
```
$ sudo apt install -y nvidia-docker2
```

```
$ sudo systemctl restart docker
```

docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smiで確認してgpuが認識していればOK．
.NETで暗号化

# はじめに
最近ならAES256/GCMを使っておけば大丈夫な気がするので、その使い方。

.NETの場合、.NET Framework では最新の4.8でもAesGcmが無いので使えないことに注意、.NET Frameworkでなければならない場合はAES256/CBCとかにするのかな。CBCではパディングオラクル攻撃に注意。パディングのエラーをそれとわかるように通知してはいけない。
.NET Core 3.0 以降なら大丈夫、もちろん .NET 5, 6, 7もOK。

Javaで暗号化、.NETで復号化とかしようとすると、tagが別になっているのでうまくいかない、注意。
Java版の話はこちら⇨ [Javaで暗号化](https://qiita.com/jkomatsu/items/baf25bf86f815f6da8b3)

# 暗号鍵
Javaと違って単なるbyte配列で良い。パスワードから作る場合はSHA256で。

```c#
using System.Text;
using System.Security.Cryptography;
    .
    .
    .
    public byte[] generateRandomKey()
    {
        byte[] key = new byte[32];
        RandomNumberGenerator.Fill(key);
        return key;
    }

    public byte[] getKeyFromPassword(string pass)
    {
        SHA256 sha = SHA256.Create();
        byte[] ret = sha.ComputeHash(Encoding.UTF8.GetBytes(pass));
        return ret;
    }

```

# IVとtag
GCMでは改ざんを検知するために暗号文と同時にtagが出力される。Javaでは暗号文と一緒のbyte配列になって出力されたが、.NETでは別に領域を用意しておく必要がある。
IVをnonceから作るのはJavaと同じ。
バッファサイズは一応定数定義があるので、それを使っている。
nonce, tag, 暗号文は復号側にそのまま送って構わない。

```c#
using System.Security.Cryptography;
    .
    .
    .
    public byte[] generateNonce()
    {
        byte[] nonce = new byte[AesGcm.NonceByteSizes.MaxSize];
        return nonce;
    }

    public byte[] getTagBuffer()
    {
        byte[] tag = new byte[AesGcm.TagByteSizes.MaxSize];
        return tag;
    }
```

# AAD
AADについてもJavaと同じで、任意のbyte配列を使う。
サンプルでは「AADは追加認証データ、中身はなんでも良いが64kBytes以内にする」の文字列をUTF-8のバイト列として使っている。

# 暗号化
AesGcmを使って暗号化する。暗号文とtagが別々になっていて、tag用の領域は先に確保しておく必要がある。

```c#
using System.Security.Cryptography;
    .
    .
    .
    public byte[] encrypt(byte[] src, byte[] key, byte[] nonce, byte[] tag_dest)
    {
        AesGcm aes = new AesGcm(key);
        byte[] dest_buf = new byte[src.Length];
        byte[] aad = Encoding.UTF8.GetBytes("AADは追加認証データ、中身はなんでも良いが64kBytes以内にする");
        aes.Encrypt(nonce, src, dest_buf, tag_dest, aad);
        return dest_buf;
    }
```

# 復号化
暗号化とほぼ変わらないが、tagは入力になる。

```c#
using System.Security.Cryptography;
    .
    .
    .
    public byte[] decrypt(byte[] src, byte[] key, byte[] nonce, byte[] tag_src)
    {
        AesGcm aes = new AesGcm(key);
        byte[] dest_buf = new byte[src.Length];
        byte[] aad = Encoding.UTF8.GetBytes("AADは追加認証データ、中身はなんでも良いが64kBytes以内にする");
        aes.Decrypt(nonce, src, tag_src, dest_buf, aad);
        return dest_buf;
    }
```

# まとめ
実際に使う場合はこんな感じ。

```c#
    // 暗号化
    byte[] key = getKeyFromPassword("P@ssW0rd");
    byte[] nonce = generateNonce();
    byte[] tag = getTagBuffer();
    byte[] encdata = encrypt(srcdata, key, nonce, tag);

    // 復号化
    byte[] key = getKeyFromPassword("P@ssW0rd");
    byte[] nonce = <送られてきたnonce>;
    byte[] tag = <送られてきたtag>;
    byte[] decdata = decrypt(encdata, key, nonce, tag);
```