OmniAICreator/Qiita-1.07M huggingface dataset:
GitBucket 1.9から4.39へバージョンアップしてみる

しばらくバージョンアップしていなかったGitBucket 1.9 を現在の最新バージョン 4.39.0 へアップデートしてみた。
#  検証環境
```bash
% uname -v
Darwin Kernel Version 22.6.0: Wed Jul  5 22:22:05 PDT 2023; root:xnu-8796.141.3~6/RELEASE_ARM64_T6000
% java -version
openjdk version "1.8.0_292"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_292-b10)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.292-b10, mixed mode) 
```
# GitBucket 1.9 から 4.39.0 へバージョンアップ
案の定以下の通りエラーとなる。。まずは3.14へのバージョンアップが必要と出力さてている。
```
22:32:36.220 [main] INFO  g.core.servlet.InitializeListener - Check version
2023-09-03 22:32:36.236:WARN:oejw.WebAppContext:main: Failed startup of context o.e.j.w.WebAppContext@5829e4f4{/,file:///tmp/gitbucket/data/tmp/webapp/,UNAVAILABLE}{file://tmp/gitbucket/gitbucket.war}
java.lang.Exception: GitBucket can't migrate from this version. Please update to 3.14 at first.
```
# GitBucket 1.9 から 3.14 へバージョンアップ
エラーなく無事起動できた。
```
2023-09-03 22:36:14.456:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@6e78fcf5{/,file:///tmp/gitbucket/data/tmp/webapp/,AVAILABLE}{file:/Users/tmp/gitbucket/gitbucket.war}
2023-09-03 22:36:14.485:INFO:oejs.ServerConnector:main: Started ServerConnector@1e6b9a95{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2023-09-03 22:36:14.488:INFO:oejs.Server:main: Started @3559ms
```
# GitBucket 3.14 から 4.39.0 へバージョンアップ
予想に反し問題なくバージョンアップができた。。
```
2023-09-03 22:40:38.045:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@5478ce1e{/,file:///tmp/gitbucket/data/tmp/webapp/,AVAILABLE}{file:/tmp/gitbucket/gitbucket.war}
2023-09-03 22:40:38.065:INFO:oejs.AbstractConnector:main: Started ServerConnector@2d363fb3{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
2023-09-03 22:40:38.072:INFO:oejs.Server:main: Started @7573ms
```
あっけないがやりたいことはできたので、無事終了。
【JavaScript】比較演算子とは？

こんにちは🌕
js基礎学習、今回は`比較演算子`についてアウトプットしていきます！

※webサイトによっては`関係演算子`と呼んでいるようでした。
厳密な違い（もしくは同じものを指しているのか）がまだ理解しきれていないので、今回は総じて比較演算子としています。

## ▼これが理解できると…
比較演算子は、特に条件分岐を行うための制御文（主にif文）でよく使用されています！（筆者も業務でしばしば見かけます）

今までの記事同様に基礎中の基礎だと思うのですが、
>・より正確な条件分岐、より複雑な条件分岐を書けるようになる
>・他のメンバーが書いた比較演算子の意図がわかるようになる
>・思わぬバグを防ぐことができる

などのメリットがありそうです🧐💬
特に等価演算子と厳密等価演算子は似て非なるものですから、きちんと理解していないと想定通りの制御文が書けません。

## ▼比較演算子とは？
プログラミング言語などで用いられる演算子のうち、左辺と右辺の式や値を比較して、結果を真偽値（trueまたはfalse）で返すものです。
一致・不一致や大小の比較など、いくつかの種類があります。　

| 種類 | 演算子 | 条件式 | 意味 |
| --- | --- | --- | --- |
| 大なり | > | A > B | AはBより大きいか |
| 大なりイコール | >= | A >= B | AはB以上か |
| 小なり | < | A < B | AはBより小さいか |
| 小なりイコール | <= | A <= B | AはB以下か |
| 等価 | == | A == B | 同じ値か |
| 不等価 | != | A != B | 異なる値か |
| 厳密等価 | === | A === B | 同じ値、**かつ**同じ型か |
| 厳密不等価 | !== | A !== B | 異なる値、**または**異なる型か |


特にややこしい等価演算子と厳密等価演算子をサンプルコードを見ながら学びます！

## ▼等価演算子
同じ値であればtrueを返し、そうでない場合はfalseを返します。
厳密等価演算子とは異なり、データ型が異なる場合には型の変換を試みてから比較を行います。

``` javascript 
console.log(1 == 1); // true
console.log('apple' == 'apple'); // true
console.log('apple' == 'orange'); // false
```

データ型が異なる場合の比較は、同じ型になるように暗黙的に変換されます。

``` javascript 
// 文字列は数値に変換される
console.log(1 == '1'); // true

// '01'と'1'
console.log(1 == '01'); // true
console.log(1 == 01); // true

// trueは1に変換される
console.log(0 == true); // false
console.log(1 == true); // true

// falseは0に変換される
console.log(0 == false); // true
console.log(1 == false); // false

// nullとundefined
console.log(null == undefined); // true
// （データ型も値も違うけれど…）
typeof undefined // undefined
typeof null // null
```
このように、一見同じようでもfalse、一見違うようでもtrueという挙動をとるため注意が必要です。

そのため、なるべく厳密等価演算子を使うことが推奨されているとのことです。
異なるデータ型を比較したい場合には、あらかじめ型を揃えて比較を行います。

（余談）
`null`と`undefined`の比較がtrueになる理由が気になったのですが:thinking:
探してもなかなかドキュメントにぶつからなかったので、chatGPTに聞いてみました！

:::note info
・歴史的な経緯
　js開発当初は厳密な型付けが考慮されていなかった

・後方互換性
 既存のコードが壊れないように設計上の互換性を維持するためのルールが導入された
:::

↓ヒントになりそうな記事

https://jp.quora.com/JavaScript-no-null-to-undefined-ha-naze-wazawaza-betsuni-na-tte-iru-node-shou-ka


## ▼厳密等価演算子
同じ値、かつ同じ型である場合はtrueを返し、そうでない場合はfalseを返します。

``` javascript 
console.log(1 === 1); // true
console.log(1 === '1'); // false
console.log('apple' === 'apple'); // true
console.log('apple' === 'orange'); // false

// nullとundefined
console.log(null === undefined); // false
```

ちなみに処理速度的にも厳密演算子の方が速いらしいです…！
等価演算子では、場合によっては暗黙的に型変換が行われるからでしょうか。

https://blog.myntinc.com/2018/07/if.html


## ▼さいごに
以上のように、比較演算子のいくつかの種類、厳密等価と等価の違いが理解できました。
演算子を使って判定を行うことももちろんなのですが、自分が今扱っているのはどのようなデータ型なのか意識しながらコードを書く必要性がわかりました！！

基本的には厳密等価演算子が推奨されていますが、逆に等価演算子が推奨されている場面はあるのかな？というのが新たに気になったので、後日調べてみようと思います〜:writing_hand_tone1:

## ▼参考

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Strict_equality

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Equality

https://developer.mozilla.org/ja/docs/Web/JavaScript/Equality_comparisons_and_sameness

https://onl.sc/VM3ZtEn

https://tcd-theme.com/2022/03/javascript-comparisonoperator.html
Dynabook における Screenpresso のショートカット設定

# はじめに
ごきげんよう、百合宮桜です。
突然ですが、私のパソコンは、コロナ給付金10万円を元手にして買いました。
Dynabookさんのノートパソコンです。
ショートカットが少々癖がつよ……ry オリジナリティにあふれてらっしゃるところがあります。
うっかり、ショートカットでハマるというIT業界の人間とは思えないことをしてしまったので記録しておきます。

# PrintScreen キーが End キーと同居している

公式さんのスクリーンショットの撮り方のページです。
https://dynabook.com/assistpc/faq/pcdata2/017203.htm
ご覧頂くとわかる通り、ほとんどの場合、PrintScreen キーが他のキーと同居しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/54974f23-deb0-b25c-887e-8330882bf991.png)

なのでスクショを撮る時は、Windows ロゴキーなど複数のキーを同時に押さないといけません。

# Screenpresso さんは同時押しで反応してくれない💦

Screenpresso は Defaultでは、PrintScreen キー押下で起動するようになっています。
しかし、Dynabook さんのPrentScreen キーは他のキーと同居しています。
それゆえに Windows ロゴキーや FN キーなどとの同時押しを試みますが、どうにもうまく起動してくれません。
私の押し方が気に食わないのか、それともただ単に認識できないのか、原因は不明です💦

# 結論、Screenpresso 側のショートカットを変更しよう
押しても反応してくれないと業務効率が下がります。
致し方ないので、Screenpresso 側のショートカットを変更しました。
変更方法は以下の通りです。

1. Screenpresso を起動させ、「設定」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/19840fe7-3f2d-327d-1ee0-8d3bed655d43.png)

2. ホットキータブに切り替え、スクリーンショットの「変更する」ボタンを押下します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/a48e5a79-4432-a1ec-e475-5dd3b6b1123f.png)

3. 変更したいキーを押して、ウィンドウ右下にある「OK」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/3dc9c891-d331-08bc-e498-523a879c7520.png)

# 終わりに
私は、今回 Endキーに変更しました。
理由は簡単、PrintScreen キーと同居しているからですｗｗ
つまり押すキーは変えずに、複数同時押しの処理をなくしたわけですね。
皆さんも不便を感じたら、躊躇なく変更してみてください。
FastAPI が動く諸々整った Python 環境を Docker で作ってみる

## はじめに
- この記事では、最近 WSL2 を使い始めた私が、FastAPI が動く諸々整った Python 環境を Docker で作る方法を、メモとして残します。
- FastAPI で単に Hello, World するためだけの環境ではなく、フォーマッタ、リンタ、型チェック、ユニットテスト、パッケージ管理などを導入した環境を用意しました。
  - また、VSCode 上でのテストカバレッジの可視化についても実施できるようにしました。
- この記事は、[nikkie さんの Hatena Blog](https://nikkie-ftnext.hatenablog.com/) を参考にして作成しました。いくつかの記事の Tips をまとめたものを作成したイメージです。
  - 都度ブログへのリンクを貼っていますので、詳細はそちらを参照いただければと思います。
  - こちらのブログには、よくお世話になっています。ありがとうございます。mm


## Dockerfile を作成する
- まずは、必要なモジュールがインストールされた Docker イメージを用意します。
  - [作成した Dockerfile](https://github.com/0machi/FastAPI_demo_app/blob/main/Dockerfile)
- パッケージ管理には、pyproject.toml と Poetry を使用しています。
  - [作成した pyproject.toml](https://github.com/0machi/FastAPI_demo_app/blob/main/pyproject.toml)
  - 参考
    - [Pythonで自作ライブラリを作るとき、setup.pyに代えてpyproject.tomlを使ってみませんか？](https://nikkie-ftnext.hatenablog.com/entry/why-dont-you-write-pyproject-toml-instead-of-setup-py)
- Docker イメージは、マルチステージビルドを適用しています。
  - 参考
    - [PythonプロジェクトをDockerイメージにビルドする（マルチステージビルドでsite-packagesをCOPY！）](https://nikkie-ftnext.hatenablog.com/entry/python-docker-multi-stage-build-202306)
    - [michaeloliverx/python-poetry-docker-example](https://github.com/michaeloliverx/python-poetry-docker-example/tree/master)
  - 今回は Poetry の仮想環境を必ずしも使用する必要がないため、仮想環境を無効化しています。


## フォーマッタ、リンタ、型チェック、ユニットテストを楽に適用できるようにする
- Python向けのタスクランナーである taskipy を使用して、`$ task test` を実行した際に、以下のモジュールを順に実行するようにしています。
  - 実行するモジュール
    - autoflake
    - black
    - isort
    - pyupgrade
    - mypy
    - pytest
  - 参考
    - [Python開発環境共有、今の私はtaskipyで一連のコマンドをつないでいます](https://nikkie-ftnext.hatenablog.com/entry/python-development-environment-taskipy-example-202306)


## VSCode 上でのテストカバレッジの可視化を実施できるようにする
- .vscode 配下に必要な設定を記述します。
  - VSCode のサイドバーの Testing から、ユニットテストの実行後、画面下部の Watch を押下することで、カバレッジを可視化することができます。
![スクリーンショット 2023-09-03 175641.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242339/e42c8f70-9693-fc91-a11c-8a63895cc497.png)


## おわりに
- この記事では、FastAPI が動く諸々整った Python 環境を Docker で作る方法を、メモとして残しました。
- FastAPI に限らず、諸々整った Python 環境を Docker で作りたい方の参考になればと思います。

## 参考
- [今回のGitHub](https://github.com/0machi/FastAPI_demo_app)
【Rust】rust-analyzerを使ったVSCodeのフォーマット設定

# import
https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer

# フォーマッターの有効化
```settings.json
"[rust]": {
	"editor.defaultFormatter": "rust-lang.rust-analyzer",
	"editor.formatOnSave": true,
	"editor.inlayHints.enabled": "off"
}
```

# フォーマッターの設定
プロジェクトルートに`rustfmt.toml`を追加して、設定を記述していきます。（`.prettierrc`みたいな感じです）

```rustfmt.toml
tab_spaces = 2
max_width = 160
chain_width = 160
```
詳細は👇参照。

https://rust-lang.github.io/rustfmt/?version=master&search=
LANとWAN（物理層〜データリンク層）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/bac6ead5-6e52-e773-2818-63df392fe0c4.png)
１：ネットワークの形態
　ネットワークの形態のことをトポロジーと言います。代表的なトポロジーには、パス型、スター型、リング型があります。

２：イーサネット（有線LAN）
　イーサネットは、当初、米国ゼロックス社が開発した独自のLAN規格でしたが、のちに、IEEE802.3として標準化され、広く普及しました。時代とともに、当初のイーサネット（IEEE802.3）からファストイーサネット（IEEE802.3u）。Gビットイーサネット（IEEE802.3ab）という形で発展していき、より高速な伝送が行えるようになっています。
　イーサネットの各規格は次の命令規則に従って名前がついています。

　データ伝送速度（Mbps）　+　伝送方式（BASE）　＋　　　伝送距離　伝送媒体
　　　　　　　　　　　　　　　BASE：ベースバンド方式　　２：約200ml
　　　　　　　　　　　　　　　　　　　　　　　　　　　　５：５００m
　　　　　　　　　　　　　　　　　　　　　　　　　　　　T：ツイストペア
　　　　　　　　　　　　　　　　　　　　　　　　　　　　F：光ファイバ

　　イーサネットでは、MACアドレスを用いてフレームの届け先を指定します。MACアドレスは、ネットワークカード（NIC：Network Interface Card）につけられている４８ビットのアドレスです。ネットワークカードごとに異なる番号のMACアドレスがつけられています。MACアドレスは、00:12:34:56:7a:bc
のように１６進数値を「：」や「-」で区切って表記します。MACアドレスの前半２４ビットはベンダ番号、後半２４ビットはベンダが管理する製造番号です。

３：無線LAN
　周波数2.４GHz、５GHzの電波を用いて通信を行います。市販の機材（認定された機材）であれば、免許不要で利用できます。

　無線LANには、アドホックモード、インフラストラクチャモードの２つの運用方式があります。
　アドホックモードは、機器間で直接通信をする運用方式です。携帯用ゲーム機機などで多く使われています。
　インフラストラクチャモードは、アクセスポイント（新規）を設置して、アクセスポイントを介して通信を行う運用方式です。パソコンの接続に多く使われています。
　パソコンをアクセスポイントに接続する際には、ESS-IDと呼ばれるグループ識別子を設定する必要があります。接続するアクセスポイントに設定されているESS-IDと同じものをパソコンに設定します。

「無線LANの規格」 
①規格：IEEE802.11n 周波数：2.４GHz/５GHz  最大伝送速度６００MBps 通称名：Wi-Fi4
②規格：IEEE802.11ac 周波数：５GHz  最大伝送速度６.9Gbps 通称名：Wi-Fi5
③規格：IEEE802.11ax 周波数：2.４GHz/５GHz  最大伝送速度9.６GBps 通称名：Wi-Fi6

４：無線LANの高速化技法
　無線LAN通信を高速化する技法には次のものがあります。

①MIMO：複数のアンテナを用いて通信することによって、通信品質を向上させたり、複数のデータの流れ（データストリーム）で同時に通信することで、高速通信を実現する技術である。

②チャネルボンディング：隣接するチャネルを束ねて同時に利用する技術である。どうをに例えれば、１車線道路から２車線道路にするというイメージである。チャネルを束ねて使うことにより、通信帯域（単位時間に送信できるデータの量）を増やせる。

５：無線LANセキュリティ
　無線LANは電波で通信をおこなっています。電波は誰でも傍受することができますから、無線LAN端末とアクセスポイント間の通信を安全に保つために暗号通信を行います。
「無線LANの暗号通信の規格」
①WPA2：WEPやWPAの後継として用いている方式である。プロトコルにIEE802.11iで規定されてるCCMPを利用する。暗号方式にはAESを用いる。KRACKsと呼ばれる攻撃手法があり、危険性が指摘されている。

②WPA3：WPA2の後継として策定された方式である。WPA２との相互運用が考慮されている。CCMP/AESによる暗号化を行う点はWPA2から変わりがないが、ハンドシェイク手順（無線LAN端末とアクセスポイント間の制御情報の交換手順）の改善やロックアウト機能の追加などがされている。
17歳が独学でCPUの仕組みを完全解説した

というサイトを翻訳し[cpudotland.com](https://cpudotland.com)として公開しました。

CPUにはレジスタがあって、アセンブリは機械語に翻訳されて、リトルエンディアンがあって、といった基礎的な内容から、
シェルでプログラムを実行したときCPUでは実際に何が起こっているのかというコアな内容に突っ込んでいます。
【Photoshop】話題の新AI画像生成機能「ジェネレーティブ塗りつぶし」を使用してみた！！

# 目次
* [話題のPhotoshopの新AI画像生成機能「ジェネレーティブ塗りつぶし」について](#話題のphotoshopの新ai画像生成機能ジェネレーティブ塗りつぶしについて)
* [Photoshop（Beta版）とは](#photoshopbeta版とは)
* [新AI画像生成機能「ジェネレーティブ塗りつぶし」でできること](#新ai画像生成機能ジェネレーティブ塗りつぶしでできること)
    * [オブジェクトの生成](#オブジェクトの生成)
    * [オブジェクトの削除](#オブジェクトの削除)
    * [背景を生成](#背景を生成)
    * [画像を拡張](#画像を拡張)
* [最後に](#最後に)

## 話題のPhotoshopの新AI画像生成機能「ジェネレーティブ塗りつぶし」について
2023年7月27日のAdobe公式ブログで以下のブログが発表されました！
[Adobe Photoshopに新しい『生成拡張（Generative Expand）』ワークフローを導入、Adobe Photoshopの生成AI機能は多言語に対応」](https://blog.adobe.com/jp/publish/2023/07/27/cc-design-photoshop-releases-new-generative-expand-workflow-and-global-language-support-for-firefly-powered-features "Adobe Photoshopに新しい『生成拡張（Generative Expand）』ワークフローを導入、Adobe Photoshopの生成AI機能は多言語に対応」")

まとめると、**PhotoshopのBeta版**に新AI画像生成機能「ジェネレーティブ塗りつぶし」が標準搭載されました！

## Photoshop（Beta版）とは
今後リリース予定の新機能や新しいUIを試すことができるなどPhotoshopやPremiere ProなどのAdobeソフトの最新機能を利用することが可能になります。

新AI画像生成機能「ジェネレーティブ塗りつぶし」は現在(2023/9/3)の時点ではBeta版のみ使用可能なので、Beta版をダウンロードしていない方はダウンロードから初めてください。


## 新AI画像生成機能「ジェネレーティブ塗りつぶし」でできること
新AI画像生成機能では以下の4つのことができます。
1. オブジェクトの生成：選択範囲内に新しいオブジェクトを生成します
2. オブジェクトの削除：消したいオブジェクトを選択し、自然にオブジェクトを削除します
3. 背景を生成：背景を選択し新しい背景を生成します
4. 画像を拡張：カンバスを広げたときにできる空白の部分を雰囲気に合わせて拡張します。

それぞれのやり方を説明した記事がそれぞれ以下のものなので是非みてみてください。

## オブジェクトの生成
![スクリーンショット 2023-09-03 23.15.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/5fd1e796-362d-a8ee-c317-3c418afd34af.png)

https://qiita.com/fujino_slj/private/6a520720737c3366682e

## オブジェクトの削除
![スクリーンショット 2023-09-03 23.40.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/97a3ff6b-5333-43ce-5390-07a007d7bff2.png)

https://qiita.com/fujino_slj/private/689bf48fde0808dba91c?1

## 背景を生成
![スクリーンショット 2023-09-05 18.51.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/393ead3e-1151-57d6-e4f7-a1f1f0c9aa3d.png)

https://qiita.com/fujino_slj/private/dceb6d23d72ac0249af8?1

## 画像を拡張
![スクリーンショット-2023-09-04-1.43.54.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/8fea313b-25fc-9d67-77db-54cbe2293045.jpeg)

https://qiita.com/fujino_slj/private/b5af29e8e4d7ad67b400?1

## 最後に
いかがでしたでしょうか。
最新のAI画像生成機能を活用してよりデザインの幅が広がるのではないでしょうか。
より自然に画像の加工ができるようになったので上手く活用して行きましょう！！
PowerAutomateForDesktopの技術検証⑤

　今回は、様々な文字列型変数の操作を試してみる。
ワークフローとしては、以下のものを想定している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533364/2c9cde3f-4509-83ab-4ade-4b39363fce6a.png)

　これは、１つ目の変数を「あいうえお」２つ目の変数を「0090」にしてこの２つの変数を使って３つ目の変数を作成して４つ目のメッセージボックスで結果を確認する。ここで、３つ目の中身を色々と変更してみて検証してみたい。

# 検証その１

　３つ目を以下のようにする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533364/6e05876c-2268-1c06-4e50-3487223151f0.png)

　実行すると以下のようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533364/05e56c37-e3e7-7a46-bdcb-48e7c10fe7d1.png)

　というようになる。

# 検証その２

　３つ目を以下のようにする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533364/f4b7e990-492b-b455-4617-654e787a1e54.png)

　結果は以下のようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533364/349feb8e-c1d2-5d6f-b803-a5bc49d62c99.png)

# 検証その３

　３つ目を以下のようにする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533364/d195ba4b-d865-ef8f-1eca-f1a9b0efcfa1.png)

　結果は以下のようになり、改行もできることも判明。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533364/69eb6226-434f-3eda-fb02-f7c853289132.png)

# 検証その4

　３つ目を以下のようにする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533364/3acbd902-11b9-38e3-a126-4315405f7507.png)

　結果は以下のようになり、空白と改行も可能だと判明。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533364/a68202b1-2b48-5674-f8d5-e37aef5d7ecc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533364/2ee3e9d3-8049-c009-ce3f-ac6e5ffb9b2e.png)

# 検証結果

　変数の設定では、いろいろと文字列を視覚的に設定が可能そうである。
AWS SDK for JavaScript v3で大ハマりした件 (API Gateway WebSocket編)

## IoT Coreのendpointも注意 (Update: 2023/09/04)

v3はIoT Coreのendpointも`https://`を付ける必要があります。

https://github.com/aws/aws-sdk-js-v3/issues/4542

## AWS SDK for JavaScript v3

以下のDynamoDBに引き続き、API Gateway WebSocketでもv2->v3への移行で大ハマりしました。

https://qiita.com/ztanakajp/items/97ac1363faa456c97302

## 問題と解決策

解決策を見つけたのはGitHubのissueでした。v3ではendpointに`https://`を付ける必要があります。

https://github.com/aws/aws-sdk-js-v3/issues/999

```js:v2のAPI
const agma = new AWS.ApiGatewayManagementApi({
        apiVersion: "2018-11-29",
        endpoint: event.requestContext.domainName + "/" + event.requestContext.stage
    });
```
```js:v3のAPI
// https://を付ける必要があります
const config = {
  endpoint: `https://${process.env.WEBSOCKET_ENDPOINT}/${event.requestContext.stage}`
};
const client = new ApiGatewayManagementApiClient({
  ...config
});
```
Javaのオブジェクト指向　~Map(連想配列)~

# 目次
[1.Java でmapの値(value)を弄る時によくやるコードの書き方](#Javaでmapの値(value)を弄る時によくやるコードの書き方)
[2.注意点](#注意点)


# Java でmapの値(value)を弄る時によくやるコードの書き方

```Java:Java でmapの値(value)を弄る時によくやるコードの書き方
import java.text.ParseException;
import java.text.SimpleDateFormat;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;

// ~中略~

//　DBからデータを取得する
List<int> targetIdList = new ArrayList(Arrays.asList(1, 2, 5));

SimpleDateFormat sdFormat = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
String strStareDate = "2023/09/03 00:00:00";
String strEndDate = "2023/09/04 00:00:00";
Date startDate = sdFormat.parse(strStareDate);
Date endDate = sdFormat.parse(strEndDate);

List<Entity> entityList = nwe dao().findById(targetIdList,startDate, endDate);

// key:ID value:IDに対応するデータ
Map<String, List<entity>> dbDataMap = new LinkedHashMap<>();
for (Entity entity : entityList) {
    List<Entity> mapEntityList = 
        dbDataMap.get(entity.getId());// ★ここ★
    if (Objects.isNull(mapEntityList) { // keyに対応するものがMapに登録されていない場合
        mapEntityList = new ArrayList<>();
        dbDataMap.put(entity.getId(), mapEntityList);
    }
    mapEntityList.add(entity):
}
```

〇Map
|kye|value|
|---|---|
|Id①|[[Entity], [Entity]]|
|Id②|[[Entity]]|

上記のコードの★ここ★で、Mapから取り出したものがMapに登録されていない(NULLの)場合、
|kye|value(これ!!)|
|---|---|

Mapから取り出したvalueを格納した
mapEntityListがNULLになる。

Mapから取り出したvalueかを変数に格納したモノと、Mapのvalue(Mapのvalue = オブジェクト)は、同じになる。
つまり、Mapから取り出したvaluを格納してあるListに対してaddや+(加算)、-(減算)とかの処理を加えると、Mapの中のValueの値も連動して変わる！！


そのため、わざわざMapから取り出したvalude(オブジェクト)をMapに入れ直したりする必要は無く、この数行で処理が終わる。
(私はいつもこれをやろうとしていつもハマってる。。。)


# 注意点
## 事象
Mapから取り出したvalu(オブジェクト)に対して変更を加えているハズなのに変更されていない！！


```Java:例)Map(key:Id, value:カウントした結果)
//　DBからデータを取得する
List<int> targetIdList = new ArrayList(Arrays.asList(1, 2, 5));

SimpleDateFormat sdFormat = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
String strStareDate = "2023/09/03 00:00:00";
String strEndDate = "2023/09/04 00:00:00";
Date startDate = sdFormat.parse(strStareDate);
Date endDate = sdFormat.parse(strEndDate);

List<Entity> entityList = nwe dao().findById(targetIdList,startDate, endDate);

// key:ID value:IDに対応するデータ
Map<String, Integer> countMap = new LinkedHashMap<>();

for (Entity entity : entityList) {

    Integer	count = 
        countMap.get(entity.getId());

    if (Objects.isNull(count) { // keyに対応するものがMapに登録されていない場合
	    count = 0;
        countMap.put(entity.getId(), count);
    }
    count = Integer.sum(count, 1): // ★countに1を加算★
}


```
```
count = Integer.sum(count, 1): // ★countに1を加算★
```
で **countに1を足した値を代入しているハズなのに、加算がされていない!!**

## 理由：
Integer.sum()は関数(メソッド)であるため、戻り値で返されるモノは、countに格納したオブジェクトとは別なオブジェクトである。
Integer.sum()の仕様↓

https://docs.oracle.com/javase/jp/8/docs/api/java/lang/Integer.html#sum-int-int-

そのため、countに格納したオブジェクトには変更がされず、値が変わらなかった。

## 対策


```
count = Integer.sum(count, 1): // ★countに1を加算★
```
を

```
count += 1: // ★countに1を加算★
```
にする！！
AWS SDK for JavaScript v3で大ハマりした件 (DynamoDB編)

## AWS SDK for JavaScript v3

DynamoDB Document Clientを使ったv2->v3への移行で大ハマりしました。パラメータは変わらないのになぜか以下のエラーが出てネットを調べまくりましたが原因が分からず。

## エラー内容

```js
err: TypeError: Cannot read properties of undefined (reading '0')
      at AttributeValue.visit (/Users/***/Test/aws/dynamo/node_modules/@aws-sdk/client-dynamodb/dist-cjs/models/models_0.js:632:40)
      at se_AttributeValue (/Users/***/Test/aws/dynamo/node_modules/@aws-sdk/client-dynamodb/dist-cjs/protocols/Aws_json1_0.js:2948:38)
      at /Users/***/Test/aws/dynamo/node_modules/@aws-sdk/client-dynamodb/dist-cjs/protocols/Aws_json1_0.js:3149:20
      at Array.reduce (<anonymous>)
      at se_ExpressionAttributeValueMap (/Users/***/Test/aws/dynamo/node_modules/@aws-sdk/client-dynamodb/dist-cjs/protocols/Aws_json1_0.js:3145:34)
      at ExpressionAttributeValues (/Users/***/Test/aws/dynamo/node_modules/@aws-sdk/client-dynamodb/dist-cjs/protocols/Aws_json1_0.js:3352:43)
      at applyInstruction (/Users/***/Test/aws/dynamo/node_modules/@smithy/smithy-client/dist-cjs/object-mapping.js:73:33)
      at take (/Users/***/Test/aws/dynamo/node_modules/@smithy/smithy-client/dist-cjs/object-mapping.js:44:9)
      at se_QueryInput (/Users/***/Test/aws/dynamo/node_modules/@aws-sdk/client-dynamodb/dist-cjs/protocols/Aws_json1_0.js:3346:37)
      at se_QueryCommand (/Users/***/Test/aws/dynamo/node_modules/@aws-sdk/client-dynamodb/dist-cjs/protocols/Aws_json1_0.js:273:27)
}
```

## 原因

結局、試行錯誤した結果がこれ。

```js:元のコード
const { DynamoDBClient, QueryCommand } = require("@aws-sdk/client-dynamodb");
const { DynamoDBDocumentClient } = require("@aws-sdk/lib-dynamodb");
// (中略)
const ddbClient = new DynamoDBClient({ credentials });
const ddbDocClient = DynamoDBDocumentClient.from(ddbClient);
ddbDocClient.send(new QueryCommand(params))
    .then((value) => {
        console.log(value);
    }).catch((err) => {
        console.log({ params, err });
    });
```
```js:修正コード
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
const { DynamoDBDocumentClient, QueryCommand } = require("@aws-sdk/lib-dynamodb");
// (中略)
const ddbClient = new DynamoDBClient({ credentials });
const ddbDocClient = DynamoDBDocumentClient.from(ddbClient);
ddbDocClient.send(new QueryCommand(params))
    .then((value) => {
        console.log(value);
    }).catch((err) => {
        console.log({ params, err });
    });
```
1,2行目を見ていただきたいのですが、`QueryCommand`は`client-dynamodb`と`lib-dynamodb`のどちらにも存在しており、間違いに気付きにくいので要注意です。なお、TypeScriptなら型チェックで容易に見つかるのでこんなことは起きないです。
PythonでWEBの自動化

PythonでHTMLでデータを取得には、requestをインポートする。

以下を実行することで、取得したサイトをテスト.htmlに保存することができる。

最終行は著作権の©が取得できずにエラーとなったため、空欄に変換しました。

import requests

res = requests.get('取得したいサイトのリンク')

#print(res.text)

with open('C:\テスト\テスト.html', 'w',encoding='utf-8') as file:
  #著作権の©（\xa9）を変換
  file.write(res.text.replace('\xa9',''))
ダイエット中でも外食したい人向けのアプリ【作成中】

# アドバイスください。。。

# モチベーション
- ダイエット中でも外食するときってあるよね
    - 友達とごはん
    - ちょっとやらかしたいとき
    - 旅行
    - 出張
- すべての飲食店がダイエットに向いてないわけではないけど、探すのが面倒。。。
- みんなで店を共有できればハッピー

# 作ってみた。

- 起動したら左の画面が出てくる
    - 黒い点が登録されたお店（MySQL）
    - 今回は 1 店舗しか登録してない
- 歯車ボタンを押せば、右のメニューが出てくる
    - 上のほうで1メニューの上限カロリーと下限たんぱく質量を設定
    - 下にはお気に入りした店を表示（sqflite）
- 個人でお店の登録もできるようにしたい（右下の青色ボタン）

![image1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538658/f0ad1c0d-fba2-e2c1-85ca-88427a7c22b6.png)

# やってみて躓くところ
- コードの可読性（ほかの人はどうやっているんだろうか。。。）
    - 個人的には各 widget でファイルを分けると可読性が上がると思っている。
        => これをすると、riverpod の変数が増えすぎて面倒なことになる。

- デバッグ処理
    - Android(ios) の設定がわからない。。。
google cloudvision api を rest 形式 phpで。

google cloud vision を composer でインスコしようとしたら
インスコできなかった。
直書きで挑戦。


```hoge.php
//画像の顔の位置を取得
$projectId = config('app.gcp_project_id'); //プロジェクトIDをLaravel configから読み取る
$keyFile = json_decode(file_get_contents(config_path('gcp.json')), true);
$apiKey = "YOURAPIキー"; // APIキーを取得


$imagePath = storage_path("girl.png"); //storage/girl.png
$imageData = base64_encode(file_get_contents($imagePath));

$payload = json_encode([
    "requests" => [
        [
            "image" => [
                "content" => $imageData
            ],
            "features" => [
                [
                    "type" => "FACE_DETECTION"
                ]
            ]
        ]
    ]
]);

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://vision.googleapis.com/v1/images:annotate?key=" . $apiKey);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);

// レスポンスをデコードして顔の位置情報を取得
$response_data = json_decode($result, true);
$faceAnnotations = $response_data['responses'][0]['faceAnnotations'];

foreach ($faceAnnotations as $face) {
    $vertices = $face['fdBoundingPoly']['vertices'];
    print_r($vertices);
}

```

# 1024 x 1024 の顔写真で利用

返された値は、顔が画像内で占める矩形領域の4つの頂点の座標です。具体的には、次のようになります：

最初の点（[x] => 463, [y] => 206）は矩形の左上の頂点の座標です。
2番目の点（[x] => 830, [y] => 206）は矩形の右上の頂点の座標です。
3番目の点（[x] => 830, [y] => 576）は矩形の右下の頂点の座標です。
4番目の点（[x] => 463, [y] => 576）は矩形の左下の頂点の座標です。

# 返却値

Array ( [0] => Array ( [x] => 463 [y] => 206 ) [1] => Array ( [x] => 830 [y] => 206 ) [2] => Array ( [x] => 830 [y] => 576 ) [3] => Array ( [x] => 463 [y] => 576 ) )

以下のような感じで、顔の座標が返される。

![vision.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/43510e8c-30c6-30f1-cc6a-d2bf281d67e2.png)
pickleについて

## pickle
pickleは、Pythonプログラムで記述したオブジェクトなどをファイル出力するためのライブラリ

```python
import pickle
x = [1,2,3,4]

# save
with open('pickle_file.pkl', 'wb') as f:
    pickle.dump(x, f)

# load
with open('pickle_file.pkl', 'rb') as f:
    y = pickle.load(f)
```

## 複数オブジェクトを保存する
同じファイルに複数回書き込んだ場合、ロードも同じ回数実行するとすべてのオブジェクトがロードできる。  
（1ファイルに複数回書き込むより、ファイル自体を分けたほうがいいような気がする。）

```python
import pickle
a = [1,2,3,4]
b = 'pickle pickle pickle'

# save
with open('pickle_file.pkl', 'wb') as f:
    pickle.dump(a, f)
    pickle.dump(b, f)

# load
with open('pickle_file.pkl', 'rb') as f:
    x = pickle.load(f)
    y = pickle.load(f)
```
RspberryPiにSVNServerを導入する。

RspberryPiにSVNServerを導入した際の覚え書き

Apatch連携はせずにsvnだけで運用する。

以下のサイトを参考にさせてもらった。
https://www.softel.co.jp/blogs/tech/archives/5455

1. subversionのインストール
    ```
    sudo apt install subversion
    ```
2. 設定
    2-1. SVN用のグループを作成する。
    ```
        groupadd svn
    ```
    2-2. リポジトリを作成する。
    ```
        mkdir -p /home/svn/repos
        sudo svnadmin create /home/svn/repos/project
        sudo chown -R :svn /home/svn/repos
        sudo chmod -R g+wr /home/svn/repos
    ```
    2-3. ユーザを追加する。　　
    ```
        sudo adduser svnuser
        sudo usermod -G svn svnuser
    ```
    2-4. 設定ファイルの編集
        /home/svn/repos/project01/conf配下のsvnserve.confとpasswdを修正する。
        svnserve.confの以下の部分をコメントアウトする。
    ```
        anon-access = read
        auth-access = write
        
        password-db = passwd
    ```

    passwdにユーザーとパスワードを追加する。

    ```
        [ユーザ名] = [パスワード]
    ```


3. サーバの起動
    ```
        sudo svnserve -d -r /home/svn/repos/project01/
    ```

4. 接続
    url(svn://[ホスト名 又は IPアドレス])とユーザ名、パスワードを指定して接続する。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653097/38b14eb0-f8c7-65e1-c210-fef6d86bace8.png)
[Chrome] React Developer Toolsにてタイムアウトエラー

#概要
Chrome拡張機能 React Developer Tools でデバッグしようとした所、下記
タイムアウトエラーが発生したので解決した際のメモ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/8002d664-6a14-e1e8-21fa-5a4868e67774.png)

# 原因/解決策
拡張機能の設定を確認しました。
デフォルト設定で、ファイルアクセスの権限がOFFだったので、ONにしてみました。
※ブラウザも一応再起動。

解決しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/80857d56-982f-abf8-049f-7118e26f26fe.png)
【Android】OnTouchListener使用した時の警告への対応【Kotlin】

# はじめに
OnTouchListenerを使っていると
>Custom view ``ConstraintLayout`` has `setOnTouchListener` called on it but does not override `performClick`

という警告が出ます。
このままでも実行するのに問題はありませんが、OnTouchListener内が全て黄色く警告が出たままになってしまうので、いい気はしませんね。
そこでこの警告を消す方法を記事に残します。
# アノテーションを付ける
OnTouchListenerを記述しているonViewCreatedメソッドなどの上に
```
@SuppressLint("ClickableViewAccessibility")
```
をつけることで警告を消すことができます。
一番簡単な方法ですが、暫定的な解決にしかなりません。

# Overrideする
警告を直訳すると
>カスタムビュー ``ConstraintLayout`` には `setOnTouchListener` が呼び出されていますが、 `performClick` はオーバーライドされません

ということなので　カスタムViewを作りそのカスタムView内でperformClick()をOverrideします
```
  override fun performClick() {
        super.performClick()
        return true
    }
```

# performClick()を使用する
そもそもperformClick()は　ボタンが押された時以外でも、コードでクリック操作を実行できるもので、これをそのまま使用することで警告が消えることがあります。
```
view.performClick()
```
これは警告に有無に関わらず、今後役に立ちそうな事なので覚えておきたいですね。
インターネットVPNとIP-VPNの違い①インターネット・広域IP網/閉域網の違いとは？え？専用線？


情報処理安全確保支援士の勉強をしていると、（要約すると）こんな記載を見つけました。

インターネットVPN：インターネットを使ったVPNです。
IP-VPN：広域IP網（もしくは閉域IP網）を使ったVPNです。
専用線：専用だよ。すごくセキュリティに強いよ。

ここで生まれた疑問3点。
・ホニャララIP網etcって正確に言うとどういう意味なんだろう？
・ホニャララIP網と専用線の違いってなんだろう？
・インターネットVPNとIP-VPNはどういう違いがあるんだろう？

こういった疑問を曖昧にしていると、後々つまづくポイントになると思い調べてみました。

今回は第1弾として、インターネット、広域IP網/閉域網、専用線の違いを紹介します。

### この記事でわかること

・インターネット、広域IP網/閉域網、専用線の違い

では順番に調べていきます。

### インターネット、広域IP網・閉域網、専用線の違い

・インターネットとは

まずマスタリングTCP/IP入門編第６版よりインターネットとは？が書かれている箇所を読んでみました。
一部引用させていただきます。
（この後も引用が多くありますが、全体を引用すると長大になるため部分的に意味が伝わるよう引用しています。）

>マスタリングTCP/IP入門編第６版P72より
「もともとは複数のネットワークを結んで１つのネットワークにすることを表していました。」
「現在、インターネットというと、ARPANETから発展し、全世界を接続しているコンピュータネットワークのことを指します」

>マスタリングTCP/IP入門編第６版P73コラムより
「社内LANや自宅のパソコンがインターネットとつながっている場合、これら全部をインターネットの一部と見ることができます。一方、会社のLANや自宅のパソコンから見た場合、接続先のネットワークをインターネットという見方もできます。」

インターネットは自分たちが一般的に使っている通信網で、広域IP網や閉域網、専用線ではないものくらいで一旦理解しました。
（改めてインターネットとは何かを考えると難しかったです）

・広域IP網とは

令和04年 【春期】【秋季】情報処理安全確保支援士合格教本 技術評論社P202のIP-VPNの説明の際に出てきた言葉で、グーグルで検索してもそれらしき言葉がありませんでした。

おそらくですが、WAN（広域通信網）をIP-VPNの説明をする部分だったので、広域IP網と表現したのではないかと推測しています。

WANについてはNTTさんのサイトから引用します。

>「プロバイダーが保有している回線を利用して、WANという広範囲のネットワークを構築する仕組みができたのです。地理的に離れた拠点のLAN同士をネットワークで接続し、事業所間での相互通信を可能にする**WANは、基本的に通信キャリアが構築から管理までを担っています。**」

>「広範囲で接続を行うといった点では、インターネットとWANは混同しやすいかもしれません。**しかし、誰が使うのかといった観点で整理してみると、それぞれの区別が明確になるはずです。WANは、企業が持っているローカルネットワークを相互に接続することで、データの転送などを行う目的で使用するものです。プライベートな通信網が構成されるWANは、限られたユーザーのみがアクセスするネットワークだという点で、インターネットとは全く別のものなのです。**」

https://www.ntt.com/business/services/network/internet-connect/ocn-business/bocn/knowledge/archive_101.html
太字は引用者による強調になります。

・閉域網とは

広域IP網と同じくWANという理解でほぼ良いのではないかと思います。

NTTさんのサイトから引用させていただきます。

>「「閉域網」は「限られた利用者のみが利用可能な広域通信網」のことです。狭義では「物理的または論理的にインターネットに接続していないネットワーク」を指します。」

https://www.nttpc.co.jp/lp/vpn-collabo/column/base_02.html

この時、限られた利用者＝1つの企業や利用者とは限りません。

CCNA完全合格テキスト&問題集P659より
>「IP-VPNは、通信事業者が用意した閉域網を使用するVPNです」
「他の契約ユーザの通信が混在して届いたりしないように、通信事業者側でMPLS（Multiprotocol Label Switching）という技術を使用して宛先を区別します」

マスタリングTCP/IP入門編第６版P134より

>「MPLS（Multiprotocol Label Switching）はラベルと呼ばれる情報をIPパケットに付加して通信を制御します。このラベルを、顧客ごとに異なるように設定し、MPLS網を通過する際に、このラベルで宛先の判断を行います。これによって、複数の顧客のVPNを1つのMPLS網上で区別し、保護されて閉じた形のプライベートネットワークとして利用できます。」

上記2冊の記載から、複数の利用者で閉域網を共用することが考えられます。
（ただし私自身は閉域網を契約したことがないため、契約によっては単一の企業や利用者が閉域網を使えるのかもしれません。）

・専用線とは

NTTさんのサイトより引用します。

>「「専用線」は、2拠点間を物理的に接続し、独占的に使用する回線を指します。利用者自身が回線を設置する「私設回線」と言う形式もありますが、多くの場合は通信事業者が用意した回線を使用し、各拠点に光信号をデジタル回線に変換する「ONU（Optical Network Unit、光回線終端装置）」およびネットワークを中継する「L3スイッチ」などを設置して利用します。」

https://www.nttpc.co.jp/column/network/leasedline.html

広域IP網/閉域網との違いは、専用線は1対1（つまり2拠点間）の通信になることだと思います。
繋ぐのに時間もかかりますし、維持するためのコストも高く着きますが、完全に通信回線を独占使用できるために高いセキュリティを持つというのは納得です。

### まとめ

インターネット：自分たちが使っているいわゆるネット。試験に言葉として出てきたら下記のいずれでもないというイメージ。不特定多数が利用する。
広域IP網/閉域網：通信事業者が構築したWAN。利用者は契約して共用する。契約した特定の利用者しかいない（不特定多数が利用しない）。
専用線：拠点間を1対1で結ぶ。利用者は回線を独占できる。

次回、インターネットVPNとIP-VPNの違い②から本題に入っていきます。
【2023年版】draw.ioでECS・CI/CDのAWS構成図を作成してみた

過去に自分が作成したポートフォリオのメモです。
APIサーバーとしてのLaravel8アプリケーションをECS Fargateに配置するイメージです。

※draw.ioの使い方を覚えるのを含め、作成に4時間ぐらいかかりました。

- CodePipeline, CodeBuildあたりの箇所の表現は、正確には違うかもしれませんが、簡略化したかったため、このような形になりました
- terraformのアイコンは存在しなかったので、ネットから適当に拾いました。
- githubの箇所にLaravelのアイコンを設置したかったのですが、いい感じに表示できるアイコンが存在しなかったため、ネットから適当に拾いました。

![aws-cicd-ecs.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867775/0799cb65-d81b-46b5-6966-d90046b98373.png)

## このAWSアーキテクチャの内容

- 基本的に、AWSのリソースはTerraformを使用して作成強しています。
- CodePipelineを利用しCI/CDを実現しています。
- ソースステージはgithub、ビルドステージはCodeBuild、デプロイステージはECSです。
- ECSはFargateタイプを使用しています。
- データベースはRDS PostgreSQL13.11系を使用しています。
- ドメインは外部のお名前.comから取得し、ネームサーバーの設定をしています。
- Route53では、AWS ACMで要求した証明書を利用しています。エイリアスとしてAレコードでALBを指定しています。
- LaravelのAPIサーバーをAWS ECSコンテナに配置、フロントエンド側のNuxt3アプリケーションはfirebaseにデプロイしています。
IPsecのトランスポートモードとトンネルモード、なぜ二つある？

# こんな人向け
- IPsec、トランスポートモード、トンネルモードを聞いたことがある
- でも詳しくは知らない


# トランスポートモードとは

- 元のIPヘッダが暗号化されない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2922519/4be3fdd6-3a27-d5c2-156d-834048b80620.png)

# トンネルモード
- 元のIPヘッダが暗号化され、新しいIPヘッダが付加される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2922519/4c5ed0b4-59e6-226c-f337-cb66249b5e96.png)
(どちらもグレー部分が暗号化されます)

# 使い分け
**用途の共通点**
この記事ではIPsecでVPNを構築することを前提に、二つのモードの用途の違いを考えます。つまり、プライベートIPアドレス同士でネットワークを超えて(安全に)通信したい場合です。
プライベートIPアドレスはネットワークを超えられないため、グローバルIPアドレス同士で通信できるようにカプセル化する必要があります。


**用途の違い**
VPNを構築するための用途の違いは、ネスぺ参考書によると、以下になります。

- トランスポートモードは、新IPヘッダを付与する必要がない場合に使う
  -  例:他のプロトコルによって既に新IPヘッダが付与されている
- トンネルモードは、新IPヘッダを付与する必要がある場合に使う

## トランスポートモードを使う場合
リモートアクセスによるVPNが想定されます。これはPPPパケットをL2TPでカプセル化し、IPsecで更にカプセル化するケースです。L2TPパケットはIPヘッダをもつため、IPsecでIPヘッダを付与する必要がありません。

**詳しく**
端末のIPアドレスが動的に変化する
→接続ごとに認証を行い、サーバがプライベートIPアドレスを端末に割り当てる必要がある
→認証を行うためにPPPを用いる
→PPPはデータリンク層なので、L2TPでカプセル化する
→L2TPには暗号化機能がないので、IPsecを利用する
→L2TPパケットは新IPヘッダをもつため、IPsecで新IPヘッダを付与する必要がない
→トランスポートモードを利用する


## トンネルモードを使う場合
拠点間VPNが代表例です。これは送信元/宛先IPアドレスがプライベートIPアドレスのパケットをIPsecでカプセル化するケースです。プライベートIPアドレスはネットワーク外とやり取りできないため、新IPヘッダを付与する必要があります。

**詳しく**
端末のIPアドレスが動的に変化しない
→サーバが端末にプライベートIPアドレスを割り当てる必要がない
→PPPやL2TPで認証する必要がない
→送信元/宛先IPアドレスがプライベートIPアドレスのパケットをIPsecでカプセル化する
→IPsecで新IPヘッダを付与して、グローバルIPアドレス同士で通信できるようにする
→トンネルモードを利用する

(ゲートウェイ[^1]のグローバルIPアドレスが動的に変化する拠点間VPNでは、トランスポートモードを利用します)


## 参考
うかる！ネットワークスペシャリスト2023年版 | 翔泳社


[^1]: ゲートウェイ：IPsecの機能を持つIPノード。IPsecで暗号化される経路の始点または終点。
【Python】SeleniumでWeb情報を取得する。 

こんにちは、Mottyです。
久々のpython記事…SeleniumでサクッとWeb情報を取得する方法を記載します。


### Seleniumの概要
SeleniumとはWebアプリケーションのブラウザ操作を自動化するためのテストフレームワークです。2004年にUIテストを自動化することを目的に開発されました。さまざまな言語に対応してます。（JavascriptやPowershellなどでも使えます。）
またSelenium IDEという総合開発環境も用意されています。こちらを利用すれば、機能テストの記録、編集、デバッグができたりします。

### 早速書いてみる

取得や操作には要素指定するので、DOMに関する知識が必要です。
大阪で開催されている個人参加型フットサルイベントの一覧を取得してみましょう。

<a href = "https://labola.jp/reserve/events/search/personal/area-27/">Labola　大阪　個人参加型フットサル一覧</a>

``` getlist.py
from xml.etree.ElementPath import xpath_tokenizer_re
from selenium import webdriver
from selenium.webdriver.common.by import By
import time

browser = webdriver.Chrome()
url = 'https://labola.jp/reserve/events/search/personal/area-27/'
#ページングの表示機能がGETパラメーターに応じているため、5番目まで取得&繰り返し
for i in range(1,5):
    browser.get(url + "?page=" + str(i))

    #親要素を取得
    elements = browser.find_elements(By.XPATH,'//*[@id="event_list"]/li/a')
    print("★☆出力開始☆★")
    for element in elements:
        print("■□個サル会場□■")    
        #会場と日時を取得
        date = element.find_elements(By.CLASS_NAME,'date')[0]
        print(date.text)
        #募集状況を取得
        status = element.find_elements(By.CLASS_NAME,'apply')[0]
        print(status.text)
        print(" ")
    print("★☆出力完了☆★")
browser.close()
```

![XX.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302420/f5076c92-753e-f211-2e52-0ef997faf312.png)

抽出できました！
やはりXPATHは便利ですねｂ

### 終わりに
seleniumはバージョンアップ前後でかなり書き方が違うようですね( ﾟДﾟ)
便利になったのかも定かではないですし、書き換えるとなると面倒そうです・・・。

### 参考ページ

Selenium 概要
https://anken-hyouban.com/blog/2021/07/11/selenium/

XPATHについて
https://www.octoparse.jp/blog/essential-for-web-scraping-xpath-introduction

Seleniumを使って要素を見つける
https://kurozumi.github.io/selenium-python/locating-elements.html
【Android】SearchViewのあれこれ

# はじめに
久しぶりにSearchViewを使った実装を行うことになり作業進めていたのですが、使用頻度の低いUIだと暫く時間が空くと忘れがちですよね。
そこでSearchViewを使う際によく使う機能を備忘録的にまとめておこうと思います。

# 入力された文字列を取得するイベント

文字に変化があった場合のイベントや検索ボタンが押された時のイベントで何か行う場合にはsetOnQueryTextListenerを設定する必要があります。

```main.kt
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
    override fun onQueryTextChange(newText: String): Boolean {
        // text changed
        return false
    }
    override fun onQueryTextSubmit(query: String): Boolean {
        // submit button pressed
        return false
    }
})
```
onQueryTextChangeが入力文字が変更された時、onQueryTextSubmitが検索ボタンを実行された時です。
ほぼほぼ使うのはonQueryTextSubmitだと思いますが、入力文字を監視したい場合などはonQueryTextChangeを使うといいと思います。

# フォーカスの変化を拾うイベント
例えばSearchViewにフォーカスが当たったら検索履歴を出して、外れたら非表示にする。
こんな感じのUIを実現したい場合にフォーカスの変化を取得する必要があるかと思いますが、フォーカスの変化を拾うには以下を実装します。

```main.kt
searchView.setOnQueryTextFocusChangeListener { view, hasFocus ->
    // Focus changed
}
```
# 設定されている文字列の取得
現在設定されている文字列は、以下で取得可能です。

```main.kt
val text = searchView.query
```

# 検索バーが常に表示された状態にする
SearchViewは基本虫眼鏡アイコンだけが見えた状態で検索欄は非表示がデフォルトです。
検索欄が常に見えた状態とするためには、以下を設定する必要があります。

```
android:iconifiedByDefault="false"
```

# Hintの文言を設定する
EditTextのように入力前のヒントを設定したい場合は以下設定することで対応可能です。

```
android:queryHint="ヒント"
```

# さいごに
比較的使用頻度の低いUIは毎回忘れがちですよね。
間が空いた後でもスムーズに対応できるよう、なるべくまとめておこうと思います。
rubyとruby on railsの違いはなんだ

# はじめに
この記事はruby on railsを学び始めた初学者の方向けの記事となっております。

rubyやruby on railsは、初学者の方や、プログラミングをほとんど知らない人でも、全く聞いたことのない人はいないんじゃないかというくらい、日本では、いや、全世界でも有名なプログラミング言語です。

ですが、この違いについてハッキリと自信を持って答えられる初学者の方はそう多くはないのではないでしょうか。
今回は、この違いや、知っておくと学習に役立つ知識をわかりやすく解説していきます。

# rubyとruby on railsの違いとは
後ほどきちんと開設するので超簡単に言うと、
・ruby　→　プログラミング言語
・ruby on rails　→　フレームワーク
です。

## rubyとは
rubyは1995年に一般公開されており、制作者は「まつもとゆきひろ」氏です。世界中に熱心なrubyプログラマーもいる人気プログラミング言語の1つです。
オブジェクト指向プログラミング言語というものに分類されます。

オブジェクト指向スクリプト言語と聞くと難しく感じますが、rubyやJavaScript, Python, PHPといった、プログラミング初心者でも聞いたことのあるような有名な言語がここに分類されます。

ここでオブジェクト指向とスクリプト言語に分けて簡単に解説しておきます。

・オブジェクト指向
「ある役割を持ったモノ」ごとにクラスを分割し、モノとモノの関係性を定義することでシステムを作り上げるシステム構築の考え方

・スクリプト言語
アプリケーションソフトウェアを作成するためのプログラミング言語であり、コードの読み書きが比較的簡単で、実用性に優れている

### プログラムの表現方法
ここで直接ruby on railsには関係ありませんが、前提として知っておくと便利な情報を記載しておきます。


|プログラミング型|方法|例|
|---|---|---|
|オブジェクト指向プログラミング |「モノ」を組み立てるように表現してプログラムを実行する方法 | Java, PHP, PythonなどのWEBアプリ開発で使用される言語|
|手続き型プログラミング |プログラムを上から順に実行する方法　|COBOL, PL/1などの大型コンピュータで開発する、金融機関や政府機関で使用されるシステムの開発に使われる言語|
|関数型プログラミング　|関数の組み合わせによってプログラムを組み立てるように表現する方法　|Haskell, OCamlなどの金融機関やセキュリティ関係、研究施設などの、データ解析などをするのに使用される言語|

### オブジェクト指向とは
・クラス（設計書）
・メソッド（処理）
・インスタンス（完成形）
この3つを組み立てて表現する方法です。

料理をするときに
①レシピを作成する（クラス）
②レシピ通りに具材を切ったり加熱したりする（メソッド）
③完成する（インスタンス）
という流れで考えるとわかりやすいでしょうか。

実際にrubyのコードに落とし込んでみると、
```ruby
class Recipe  # Recipeはクラス名
 def new  # newはメソッド名
  @recipe = Recipe.new  # @recipeはインスタンス名
 end
end
```
こんな感じです。

つまり、ruby on railsでいうコントローラーに書いてあることこそがオブジェクト指向と言っても過言ではないのではないでしょうか。

## ruby on railsとは
ruby on railsはrubyのフレームワークです。

フレームワークとは、WEBアプリケーションを開発する際に不可欠な機能のベース（土台）をまとめたものです。

ruby on railsで使われているフレームワークはMVCフレームワークというものです。

・M　→　モデル
・V　→　ビュー
・C　→　コントローラー

となります。
具体的にどういう動きをしているかというと、

------
コントローラー　→　ビュー
　　↓↑
　モデル
　　↓↑
データベース
------
という感じです。
モデルとビューを繋ぐ役割があるのがコントローラーですね。

ruby on railsを使用する場合は、
モデルファイル、コントローラー、ビューファイルにそれぞれ記述していることを、
rubyを使用する場合は、すべて１つのファイルに記述しなければなりません。
そうすると1つのファイルあたりのコードの量が膨大になってしまうので、フレームワークを使った方が綺麗に書けるということですね。

# まとめ
rubyとruby on railsの違いは、
rubyはプログラミング言語であり、ruby on railsはrubyを使いやすくするためのフレームワークであるということです。

# お願い
最後までお読みいただきありがとうございました。
本記事は、ruby on rrailsを学び始めて数か月で執筆しております。
私のためにも、今後この記事を読む可能性のある初学者の方のためにも、間違っている情報や解釈等ございましたらご指摘いただけると幸いでございます。
お手数おかけしますが、よろしくお願いいたします。
TechBlogまとめ「Active Recordのクエリ発行タイミングについて」

:::note info
SmartHRさんのTechBlogを読んで学びになったので、思考の整理のためにまとめました。
:::

今回読んだTechBlogがこちらです。

https://tech.smarthr.jp/entry/2021/11/11/151444

### クエリが発行されるタイミングについて
:::note info
Active Recordは、そのデータが本当に必要になったときにはじめてクエリを発行するようになっている（遅延実行）。
:::
以下のようなクエリは発行しない。
```ruby
class UsersController < ApplicationController
  def index
    @users = User.where(status: 'active')
  end
end
```

ビューで**インスタンス変数を評価するタイミング**でクエリが発行される。
```ruby
<% @users.each do |user| %> # ここでクエリが発行される!
  <%= user.name %>
<% end %>
```
|クエリを発行するタイミング|メソッド||
|:-----------|:------------|:--|
| 即時実行 |find, find_by, take, first, last, exists? |すぐにクエリを発行し、データベースにアクセスし、レコード(Modelのインスタンス or インスタンスの配列)を返す。|
| 遅延実行|上記以外のメソッド（where,order,selectなど）|ActiveRecord::Relationのオブジェクトを返し、実際にデータが必要になるタイミングまでデータベースにはアクセスしない。|

:::note warn
console環境では、遅延実行するメソッドでもクエリを発行します。これは戻り値をレシーバとしてinspectメソッドを実行し、得られた文字列を表示する仕様があるため。（自分はconsole環境で本来遅延実行するはずのメソッドを実行しても、クエリが発行されて混乱していたので、腑に落ちました。）
:::

:::note warn
**ActiveRecord::Relationのオブジェクトとは？**
クエリを生成するための情報を保持し、メソッドチェーンでつなげることができるため、再利用性が高く、便利なものになっている。
一方でActive Recordのオブジェクトはそれなりに大きいので、たくさん作るとメモリを大量に消費するので、クエリの内容や発行回数だけでなく、オブジェクトそのものの生成も抑える必要がある。
:::

#### クエリ発行タイミングの具体例
**データの取得**
```ruby
users = User.where(name: 'John')  # ここではクエリは発行されない
users.first                       # ここでクエリが発行される
```

**配列への置換**
```ruby
users = User.where(name: 'John')  # ここではクエリは発行されない
users_array = users.to_a          # ここでクエリが発行される
```

**レコードのループ処理**
```ruby
users = User.where(name: 'John')  # ここではクエリは発行されない
users.each { |user| puts user.name } # ここでクエリが発行される
```

**レコードの存在チェック**
```ruby
User.exists?(name: 'John')  # ここでクエリが発行される

```

**関連データの取得**
```ruby
user = User.first          # ここでクエリが発行される
posts = user.posts         # もしキャッシュされていなければ、ここで再度クエリが発行される
```

**集計メソッド**
```ruby
User.count                  # ここでクエリが発行される
User.average(:age)          # ここでクエリが発行される
```

**バッチ処理**
```ruby
User.find_each(batch_size: 1000) { |user| ... }  # ここでクエリが発行される（バッチサイズごとに）
```
時系列モデルのさまざまな推定方法

予測したy_predの値とブロック分けを行うための二つのリストから、ブロックごとの推定値を算出する。
この時、ブロックごとの推定値として、各時点の推定値(y_pred)の最頻値を用いている。

```
import numpy as np
from scipy.stats import mode
from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.ensemble import RandomForestClassifier

def calculate_accuracy(y_true, y_pred):
    return np.mean(y_true == y_pred)

def block_majority_vote(y_pred, begin_list, end_list):
    block_predictions = []  # ブロックごとの予測を保存するリスト

    for begin, end in zip(begin_list, end_list):
        # ブロック内の予測を取得
        block_pred = y_pred[begin:end+1]
        
        # ブロック内の最頻値を計算
        block_mode = mode(block_pred)[0][0]
        block_predictions.append(block_mode)

    return block_predictions

# サンプルデータ
y_pred = np.array([1, 2, 2, 1, 1, 3, 3, 3, 4, 4])
begin_list = [0, 3, 5]
end_list = [2, 4, 8]
y_test = np.array([1, 1, 2, 2, 1, 3, 3, 4, 4, 4])

# ブロックごとの最頻値を計算
block_pred = block_majority_vote(y_pred, begin_list, end_list)
block_test = block_majority_vote(y_test, begin_list, end_list)

# ブロックごとの精度を計算
accuracies = [calculate_accuracy(block_test[i], block_pred[i]) for i in range(len(begin_list))]

# 全体の精度を計算
overall_accuracy = calculate_accuracy(np.array(block_test).flatten(), np.array(block_pred).flatten())

# 混同行列を計算
confusion = confusion_matrix(np.array(block_test).flatten(), np.array(block_pred).flatten())

# ランダムフォレストを使って特徴量の重要度を計算（例）
X = np.random.rand(len(begin_list), 5)  # ダミーデータ、実際のデータに置き換えてください
y = np.random.choice([0, 1], size=len(begin_list))  # ダミーデータ、実際のデータに置き換えてください
rf_clf = RandomForestClassifier(n_estimators=100)
rf_clf.fit(X, y)
feature_importance = rf_clf.feature_importances_

# 結果を表示
print(f"Overall Accuracy: {overall_accuracy:.2f}")
print("Confusion Matrix:")
print(confusion)
print("Feature Importance:")
print(feature_importance)
```
Dropboxのインストール手順（Ubuntu & Debian）

ありがとうございます。手順を清書しましたので、確認してください。

Dropboxのインストールと設定

ステップ1: 基本設定
- ホームディレクトリに移動
```
cd ~
```
- Dropboxのバイナリファイルをダウンロードして展開
```
wget -O - "https://www.dropbox.com/download?plat=lnx.x86_64" | tar xzf -
```

ステップ2: CLIツールの設定
- ローカルのbinディレクトリに移動 (環境に合わせて適切なディレクトリに変更してください)
```
cd ~/bin (ホームディレクトリのbinに保存する場合)
```
- DropboxのCLIツールをダウンロード
```
wget -O ~/bin/dropbox "https://www.dropbox.com/download?dl=packages/dropbox.py"
```
- ダウンロードしたCLIツールに実行権限を付与
```
chmod +x ~/bin/dropbox
```

ステップ3: Dropboxディレクトリのカスタマイズ
- /shareディレクトリを作成
```
sudo mkdir /share
```
- /shareの下にdropboxディレクトリを作成
```
sudo mkdir /share/dropbox
```
- /share/dropboxへのシンボリックリンクをホームディレクトリに作成
```
ln -s /share/dropbox ~/Dropbox
```

ステップ4: デーモンの起動と認証
- Dropboxのデーモンを起動し、認証を行う
```
~/.dropbox-dist/dropboxd
```

ステップ5: Dropboxの起動
- Dropboxを起動
```
~/bin/dropbox start
```

ステップ6: LAN内の同期を無効化
- ローカルネットワーク内でのDropboxの同期を無効にする
```
~/bin/dropbox lansync n
```

ステップ7: 自動起動の設定
- crontabの編集
```
crontab -e
```
- crontabに自動起動のコマンドを追加
```
@reboot ${HOME}/.dropbox-dist/dropboxd
```

以上が、Linux環境でDropboxをインストールし、設定を行う手順となります。


### 事後追記

#### Dropboxのアンインストール手順

1. Dropboxプロセスの停止:
```
~/bin/dropbox stop
```

2. Dropboxのデーモンをアンインストール:
```
~/.dropbox-dist/dropboxd unlink
```

3. Dropboxディレクトリの削除:
```
rm -rf ~/.dropbox-dist
rm ~/bin/dropbox
```

4. Dropboxの設定ファイルの削除:
```
rm -rf ~/.dropbox
```

5. Dropboxの同期フォルダの削除（オプション）:
```
rm -rf /share/dropbox
```

6. crontabから自動起動の設定を削除:
```
crontab -e
```
crontabが開いたら、`@reboot ${HOME}/.dropbox-dist/dropboxd`の行を削除し、ファイルを保存して終了します。
【Unity】MagicaCloth2 検証

# はじめに

MagicaCloth2 という揺れものアセットの検証記事です。初投稿。
有料なので、購入の検討材料にもなれば幸いです。

ユニティちゃんKAGURA を使って、デフォルトで付けられている SpringBone と比較していきます。（DynamicBone との比較が求められそうですが、使ったことがなく、すみません。。）

## SpringBone （UnityChanSpringBone） 
Unity公式で公開されている揺れものシステムです。
各ボーンに動きを与えて揺れを制御します。
パラメータはシンプルで分かりやすいですが、その分表現の幅は広くありません。

## MagicaCloth2
Unityアセットストアで公開されている有料アセットシステムです。

各ボーンを制御する BoneCloth のほかに、直接ポリゴンメッシュを制御する MeshCloth があります。
パラメータは多いですが、細かい動きの調整が可能です。
MeshCloth だと、**ボーンを用意する必要がありません**。
<img width=640 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530151/ae89f7d3-4dcf-2f63-245f-1431d33ee07c.jpeg">

# 使いやすさ

MagicaCloth2 は事前にボーンを作る必要もなく、メッシュ毎に（物理的特性が同じであればまとめて）クロスを追加し、コリジョンを追加するだけで使えます。

パラメータは、SpringBoneのように各ボーンを触る必要はなく、クロス単位で設定するだけでOK。
数は多いですが、「重力」「空気抵抗」「剛性」だけでも動きの表現が広がります。

# 挙動比較

SpringBone と MagicaCloth2 は同じ動きにはなりません。

ここでは、MagicaCloth2 のパラメータを ユニティちゃんKAGURA デフォルト(SpringBone)の動きにできるだけイメージを近づけて比較してみます。

<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530151/c18479d0-0d50-708e-2ee0-f501df4cabea.jpeg">

左が SpringBone、右が MagicaCloth2 です。
腰の前の御幣(ごへい)と後ろのウィング(？)は BoneCloth で、髪の毛、袖、スカートは MeshCloth を付けています。

## 特徴

![01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530151/8d64c0f2-3fc7-bab7-d790-4efc674cd8cb.gif)
右 MagicaCloth2 の袖はひらひらと波打っています。SpringBoneではこういう動きになっていません。
MagicaCloth2 は「揺れる」だけではなく「なびく」ような動きが作れます。

![02.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530151/c1736f88-0db0-0ba0-8bb5-31658e3fe572.gif)
左 SpringBoneの袖が大きく広がっています。
少し不自然ですが、見栄えはこちらの方が良い場面がありました。
SpringBone は親ボーンの姿勢が大きく影響するようです（ローカル姿勢をバネで戻すような計算？）
MagicaCloth2 で固めの動きは作れますが、このように広げることはできませんでした。

## 貫通

<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530151/c2bd33b0-1957-3159-4b32-3e0a6ab7eeb7.jpeg">

SpringBoneの袖が体を貫通してしまっています

| <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530151/cff69e28-af54-2967-88d2-ded0e4b58cb2.jpeg"> | <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530151/1c87e247-82dc-e19c-a08e-bb70dd54de9a.jpeg"> |
|:-:|:-:|
| 袖の２つのラインのコリジョンの間に体がめり込んでいます。SpringBoneでも距離制限パラメータで広がらないように改善できるかもしれませんが、全ボーンに設定するのは手間がかかりそうです。 | MagicaCloth2 の MeshCloth であれば、自動で細かく繋いでくれます |

<img width=640 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530151/4de3a1c4-d44c-b9be-c63f-e9b98095a345.jpeg">

別アニメを適用したところですが、SpringBoneではお腹の下辺りがスカートを貫通しています。
単純にアニメに対して作成されたボーンが足りていないだけですが、MagicaCloth2だとプロキシメッシュを簡単に増減できるので、安定したクロスをすぐに作れます。

# まとめ

MagicaCloth2 は

- 事前準備が不要で設定が簡単
- パラメータはクロス全体を調整するので楽
- プロキシメッシュの粒度も簡単に調整できて、貫通しない安定したクロスができる
- 硬い動きから「さらさら」「ひらひら」なびく動きも可能
- ただし、SpringBoneの挙動を完全に真似ることはできない
- 価格は子供のお小遣い程度？

![03.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530151/cb6e5ce6-8fad-f01b-722f-d6a3378c1cdb.gif)

# 参考

- [Magica Cloth 2 - Unity Asset Store](https://assetstore.unity.com/packages/tools/physics/magica-cloth-2-242307?locale=ja-JP)
- [MagicaCloth2について - Magica Soft](https://magicasoft.jp/mc2_about)
- [コロプラ、Unityの揺れものシステムSpring Boneを使った布表現を紹介する記事を公開](https://gamemakers.jp/article/2022_11_28_24901)
Amazon FSx for Windows File Serverを使ってみた

FSx for Windows File Serverを使う機会があったので備忘録
## 目的
Fsx for Windows File Serverでお手軽にファイルサーバを作る

## 環境
マルチAZ Fsx for Windows File Server
オンプレミスのセルフマネージド Microsoft アクティブディレクトリ

## 通信要件
ここに記載しているものは許可が必要。SecurityGroupやNACLで考慮が必要
https://docs.aws.amazon.com/ja_jp/fsx/latest/WindowsGuide/self-manage-prereqs.html#network-configs

クライアントからの接続はSMBを許可しておけばOK。

## AD側準備
ドメインが作成されていることが前提。FSx for Windowsをドメインに参加させるため、必要な権限を持つドメインユーザを準備。Windows ファイアウォールの穴あけが必要なときはしておく。

## ファイルシステム作成
コンソールからポチッと作成。容量やスループットや参加するドメイン、OU、ドメインユーザやパスワードを入力。ここら辺設定を間違うとエラーになるので注意。
ファイルシステムを作成すると、ADのコンピュータオブジェクトが追加され、DNSにAレコードが追加される。
マルチAZで作成すると、ファイルシステムのENI分の2つAレコードが設定される。(それ以外も追加される。管理アクセス用のやつとか)

## ファイルシステム作成後の設定
ここに書いてあることは実施しておくのが吉
https://docs.aws.amazon.com/ja_jp/fsx/latest/WindowsGuide/admin-best-practices-fsxw.html#one-time-admin-tasks

## 監視について
標準で利用可能なメトリクスのうち、FSx for Windowsのサービス状態を監視できるメトリクスは存在しない。
マルチAZで作成したファイルシステムはフェイルオーバーが発生してもクライアント(Windows PC)は名前解決により透過的に接続できるので監視は必須じゃあないかもしれないが、どうしてもやりたいときはこちらを参考に設定する
https://aws.amazon.com/jp/blogs/news/monitoring-the-health-of-amazon-fsx-file-systems-using-amazon-eventbridge-and-aws-lambda/

## おまけ
ファイルシステムと、AD(兼DNS)サーバ&クライアントPC が別のネットワークに泣き別れているケース。
ネットワーク機器でNATして、DNSに登録されたレコードのアドレスをNATアドレスに書き換えれば一応システム的に利用はできる。
サポートに聞いたけど、「そんな使い方想定してないから検証してね☆」と言われた。まあそりゃそうだ。マニュアルに載ってないし