OmniAICreator/Qiita-1.07M huggingface dataset:
PLATEAU が 配信する3D Tilesデータを利用する

# はじめに
PLATEAUのデータを利用したwebアプリを作る中で、3D Tiles の利用について悩んだのでまとめておきます

# 結論
PLATEAUが公開しているデータを利用してアプリに組み込める

# データを利用する方法

https://github.com/Project-PLATEAU/plateau-streaming-tutorial

データについての詳細は上に記したレポジトリに記載されています

ダウンロードをするだけなら、このレポジトリの `3d-tiles` ディレクトリのREADMEの通りに実装すれば利用できます
（2024/05/02現在、サンプルコードには誤りがあるのでコピペでは動かないので注意）

利用可能なデータは、[**同README内に記載**](https://github.com/Project-PLATEAU/plateau-streaming-tutorial/blob/main/3d-tiles/plateau-3dtiles-streaming.md#4-%E9%85%8D%E4%BF%A1%E3%83%87%E3%83%BC%E3%82%BF3d-tiles%E4%B8%80%E8%A6%A7)されているのでそちらをご確認ください


# Three.jsで利用する
ただこの方法ではNext.js と Three.js を用いた場合の描画がうまくいかなかったので、それに対応したデータを利用できないか模索した

以下のパスにアクセスすることで3D Tiles データが利用できる
```
https://plateau.geospatial.jp/main/data/3d-tiles/${path}/tileset.json
```

`${path}`で欲しいデータを示すらしい

## path の指定
サンプルの中では以下の設定が用いられている
`path='bldg/13100_tokyo/13101_chiyoda-ku/notexture'`

これらの設定は PLATEAU が公開している [`3dtiles_url.json`](https://github.com/Project-PLATEAU/plateau-streaming-tutorial/blob/main/3dtiles_url.json)に対応している

| path | summary|
| --- | --- |
|`bldg` | `${type_en}`に対応（固定） |
|`13100_tokyo`| `${city_code}_${city(英語表記)}`に対応すると思われる *|
| `13101_chiyoda-ku` | `${ward_code}_${ward_en}`に対応 |
| `notexture` | `notexture`に対応 |

\* `city`には `city_en` のカテゴリがなく、厳密には `city` を英語表記にした訳ではないものもある

# 終わりに
[PLATEAUが公式で用意している React と three.js のデモ](https://www.mlit.go.jp/plateau/learning/tpc12-2/)では、どこかからデータををダウンロードして使っているので、それがどこのデータを利用しているのかを調べた

`plateau-streaming-tutorial`レポジトリのREADMEでは、3DTiles のデータを利用するためには Cesium の利用が必要だと書かれていたが、登録などもろもろ大変だったので、何か利用できる方法がないか探した

ただこの方式でデータの利用がいつまで可能であるかは不明なので、実際に実装するときには自前で用意する必要がありそうですね

# 参考文献

https://www.mlit.go.jp/plateau/learning/tpc12-2/

https://www.mlit.go.jp/plateau/learning/tpc06-1/

https://github.com/Project-PLATEAU/plateau-streaming-tutorial
【Next.js】yarnでnextjs + typescriptをインストールしてみた

## はじめに
yarnでnextjsをインストールしてみたのでの備忘録として書き留めておく。

## 1. yarnのインストール
インストールコマンドを実行する。
```shell
sudo npm install -g yarn
```

正常にインストールされたか確認する。
```shell
# バージョン確認
yarn -v

#実行結果
1.22.22
```

## 2.nextjs + typescript環境作成
以下コマンドを実行
```shell
yarn create next-app --typescript .
```

上記コマンドを実行したら下記を聞かれるのでお好みでNo/Yesを選択。
```shell
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias (@/*)? … No / Yes
```

下記メッセージが出力されたらとりあえずOK。
```shell
Success! Created samplenextjs at ディレクトリパス

✨  Done in 122.95s.
```

## 3. 画面で確認
下記コマンドを実行する。
```shell
yarn dev
```

その後下記URLへアクセス。
```
http://localhost:3000
```

下記画面が表示されれば完了。
![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3176842/8be81eda-1793-e1b5-bcc5-ea8bc899dc61.png)


## 終わりに
nextjsかっこいい。。。
いいねの非同期化　全て変わってしまう時の対処法

いいねの非同期化を実装し、課題も提出完了していたものの…
クリックしていない投稿も画面が変わってしまうことが発覚

![スクリーンショット 2024-04-30 15.04.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782860/98d824c9-0c8d-03f7-7f6a-42cda1174603.png)
![スクリーンショット 2024-04-30 15.04.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782860/0efb08fc-411d-1ae2-d531-bb9727e6a606.png)

問題だったのはこの箇所↓

```create.js.erb
$('.favorite-btn').html("<%= j(render 'favorites/favorite-btn', book: @book) %>");
```
createやdeleteを実行したときのjs.erbファイルの記載が誤っていました。
<%= @favorite.book_id %>の記載がなかったため選択していなかった投稿にも更新が適用されてしまっていたようです。
↓

```create.js.erb
$('.favorite-<%= @favorite.book_id %>').html("<%= j(render 'favorites/favorite-btn', book: @book) %>");
```
htpasswd コマンドのオプション

## とりあえずの使い方
##### ユーザーの追加
```bash
htpasswd -c /var/www/.htpasswd username
```
##### パスワードの検証
```
htpasswd -v username
```

## 使用方法
```
	htpasswd [-cimBdpsDv] [-C cost] passwordfile username
	htpasswd -b[cmBdpsDv] [-C cost] passwordfile username password

	htpasswd -n[imBdps] [-C cost] username
	htpasswd -nb[mBdps] [-C cost] username password
 ```

## オプション
### 操作
|オプション|説明|
|:-:|---|
| `-c` | 新しいファイルを作成する。 |
| `-n` | ファイルを更新せず、結果を標準出力に表示する。 |
| `-v` | 指定したユーザーのパスワードを検証する。 |
| `-D` | 指定したユーザーを削除する。 |
| `-b` | プロンプトによるパスワード入力ではなく、コマンドラインのパスワードを使用する。 |
| `-i` | 検証なしで標準入力からパスワードを読み込む（スクリプト処理用）。 |
https://www.jsf.or.jp/event/202403sgkz/
### 暗号化
|オプション|説明|
|:----:|---|
| `-B` | パスワードを強制的に bcrypt で暗号化する（非常に安全）。 |
| `-5` | パスワードを強制的に SHA-512 `crypt()` ハッシュにする（非常に安全）。|
| `-2` | パスワードを強制的に SHA-256 `crypt()` ハッシュにする（非常に安全）。 |
| `-m` | パスワードを強制的に MD5 で暗号化する（デフォルト）。 |
| `-s` | パスワードを強制的に SHA-1 で暗号化する（安全ではない）。|
| `-d` | パスワードを強制的に CRYPT で暗号化する（最大8文字、安全ではない）。 |
| `-p` | パスワードを暗号化しない（平文、安全でない）。Windows と NetWare 以外ではおそらく機能しない。 |

#### 暗号化オプション
|オプション|説明|
|:----:|---|
| `-C` | bcrypt アルゴリズムに使用する計算時間を設定する（大きいほど安全だが遅い、デフォルト: 5、有効: 4～17）。 |
| `-r` | SHA-256、SHA-512 アルゴリズムに使用されるラウンド数を設定する（高いほど安全だが遅い、デフォルト: 5000）。 |

※SHA-1 アルゴリズムはソルトを使用しないため、MD5 アルゴリズムよりも安全性が低い。


|アルゴリズム|オプション|Apache    |Nginx      |備考|
|---------|------|----------|------------|---|
| MD5     | `-m` | 全バージョン | 1.0.3以上[^nginx-1.0.3] |  |
| CRYPT   | `-d` | 全バージョン | 全バージョン |  |
| SHA-1   | `-s` | 全バージョン | 1.3.13以上[^nginx-1.3.13] | `SSHA` は Nginx 1.0.3以上 [^nginx-1.0.3] |
| SHA-256 | `-2` |           | OS依存 |  |
| SHA-512 | `-5` |           | OS依存 |  |
| bcrypt  | `-B` | 2.4以上   | OS依存 |  |

[^nginx-1.3.13]: <q>Changes with nginx 1.3.13                                        19 Feb 2013</q><q>*) Feature: the "`auth_basic_user_file`" directive supports "`{SHA}`" password encryption method.</q><cite>[nginx.org/en/CHANGES](https://nginx.org/en/CHANGES) - <i>nginx.org</i></cite>

[^nginx-1.0.3]: <q>Changes with nginx 1.0.3                                         25 May 2011</q><q>*) Feature: the "`auth_basic_user_file`" directive supports "`$apr1`", "`{PLAIN}`", and "`{SSHA}`" password encryption methods.</q><cite>[nginx.org/en/CHANGES](https://nginx.org/en/CHANGES) - <i>nginx.org</i></cite>
【初心者】TypeScript文法を理解していくvol.7

## はじめに
TypeScriptを一通り勉強してきた。今回はオブジェクト指向を学び直したい

## オブジェクト指向
再利用するための仕組みである。

### オブジェクト指向の用語

プロパティ：クラスが持つデータ・フィールド・メンバ変数

```.tsx
class Person {
  // => add: プロパティ
  name: string
  age: number
}
```


メソッド：クラス内で宣言して利用できる関数のこと

```.tsx
class Person {
    // プロパティ
    name: string
    age: number
    
    // => add: メソッド
    introduceMyself(): void {
    // thisを使う（クラスの中にある、物を参照している）
    // thisがないと外部から参照していることを意味してしまう
    console.log(`My name is ${this.name}. I am ${this.age} years old`)
}
}
```

`${this.name}`はクラスの中の物を参照する

- thisがあると、クラスの中にある物を参照する

- thisがないと、外部から参照していることを示す




インスタンス：クラスから生成されたオブジェクト　
（クローンみたいな感じ）

```.tsx
// => add: インスタンス
// クラスから生成されたオブジェクト
const me = new Person("Takaaki", 30)
```


コンストラクタ：クラスからインスタンスを生成する際に行う初期化の作業

```.tsx
class Person {

  name: string
  age: number

  // => add: コンストラクタ
  // クラスからインスタンスを生成する際に行う初期化
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  
  // メソッド
  introduceMyself(): void {
    console.log(`My name is ${this.name}. I am ${this.age} years old`);
  }
}

  // インスタンス
  // クラスから生成されたオブジェクト
  const me = new Person("Takaaki", 30)
  me.introduceMyself();
```

## おわりに
TypeScriptのキャッチアップ一通り終了。GWはアプリを作ります！
生成AIを利用した自動プルリク（PR）レビューを試してみた

一人開発をしている時に書いているコードに問題がないか気になったことはありませんか？
チーム開発しているときに、PRレビューが遅すぎて、モチベーションが下がったことはありませんか？
PRレビューの概要を作成するのが面倒だと思ったことはありませんか？
PRレビューでタイポなど基本的なことの指摘が面倒ではありませんか？

私は全部あります。
そこで今流行りの生成AIを利用したPRレビューをやろうと思い、感想を記事にしました。

# Bedrock × Claude3 で自動レビューする
下記の記事の内容をほとんどそのまま利用しました。
https://tmokmss.hatenablog.com/entry/introducing_bedrock_ai_review

なお、いくつか自分用にカスタマイズするため、コードやyamlを修正しました。
具体的には以下を変更しています。
- OpenAPIなどを利用し自動生成するコードをレビューから除外する
- developブランチがソースブランチの場合はレビューしない

# 結果
### PRの概要
![スクリーンショット 2024-05-02 11.11.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1005574/665df258-6489-7cfc-7b87-d8287b14654b.png)
複数の目的があるプルリク（そもそも１つの目的にしろというのはおいといて）でもそれぞれの意図を読み取ってサマライズしてくれています。
特に、「新機能」「機能改善」「リファクタリング」のように内容を分類してくれているのでとても分かりやすいです。
（私が書いているように見えますが、すべて自動で生成されています（generatedとなってます））


### ウォークスルー
![スクリーンショット 2024-05-02 11.11.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1005574/31589d14-129f-6a0c-e013-3105c41d0999.png)
変更されたファイルの一覧とそれぞれの内容のサマリーがまとめられています。
これも驚くほど、精度高くまとまってました。すごい。。。


### コードコメント
![スクリーンショット 2024-05-02 11.24.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1005574/6111a85f-838b-5082-fe1b-793a6796bf84.png)
すべて「コメント」として書かれます。LGTM のようなあまり意味のないコメントから、コードに対する肯定的なコメント（「適切です」のようなコメント）、改善提案のコメントなどいくつかのコメントの種類があるようです。
人によって意見の分かれるところではありますが、改善提案以外のコメントはちょっと邪魔かなと思いました。
（思っていたよりもコメントがたくさん書かれたため）
この点はAIレビュー自体のコードを変更し、対応するのが良さそうです。
一方で、簡単なタイポやエラー処理の対応漏れなどはかなり有用そうでした。

# 感想
rails、vuejs、reactjs、python、golang のプロジェクトで試してみましたが、かなり良いレビューがされていました。
特に単純なミスは自動PRレビューを使うことで、人に指摘される前に修正できそうです。
個人的にはサマリーが分かりやすくまとまっており、細かなレビューを行う前に全体を把握できるため、便利でした。
チームの反応も良かったため、このまま利用する予定です。
Node.jsをWSL2のUbuntu 22.04にインストールする手順

WSL2上のUbuntu 22.04にNode.jsのバージョン20、Node.jsのパッケージマネージャーであるYarnをインストールする手順を説明します。Node.jsのバージョン管理には`nvm`（Node Version Manager）を使用し、特定のバージョンを簡単に切り替えられるようにします。

## 前提条件

- Windows 10 または 11 がインストールされていること。
- WSL2が有効になっており、Ubuntu 22.04がインストールされていること。

## 手順1: WSL2とUbuntuの準備

Windows上でWSL2が有効化されているか確認し、Ubuntu 22.04をインストールします。これはMicrosoftの公式ドキュメントに従って行えます。

## 手順2: 必要なパッケージのインストール

Ubuntuを起動し、次のコマンドを実行して必要なパッケージをインストールします。

```bash
sudo apt update && sudo apt install curl build-essential
```

これにより、`curl`やビルドに必要な基本的な開発ツールがインストールされます。

## 手順3: NVMのインストール

`nvm`をインストールすることで、複数のNode.jsバージョンを管理できます。以下のコマンドを実行して`nvm`をインストールします。

```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
```

インストール後、ターミナルを閉じて再開するか、次のコマンドを実行して`nvm`コマンドを有効にします。

```bash
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
```

## 手順4: Node.jsのインストール

次に、`nvm`を使ってNode.jsのバージョン20をインストールします。

```bash
nvm install 20
nvm use 20
```

## 手順5: Yarnのインストール

Node.jsがインストールされたら、次にYarnをインストールします。Yarnの公式指示に従い、次のコマンドを使用します。

```bash
npm install --global yarn
```

このコマンドは、npmを使ってYarnをグローバルにインストールします。

## 手順6: インストールの確認

Node.jsとYarnが正しくインストールされたかを確認します。次のコマンドを実行してバージョンを確認します。

```bash
node -v
yarn -v
```

Node.jsが`v20.x.x`、Yarnが`1.x.x`または`2.x.x`と表示されれば、インストールは成功しています。

以上で、WSL2のUbuntu 22.04環境にNode.jsとYarnをインストールする手順は完了です。これにより、効率的な開発環境が整いました。これでNode.jsやYarnを使ったプロジェクトの開発がスムーズに行えるようになります。
『mysql_native_password』周りで詰まった時の解決方法

# はじめに

下記エラーによってMySQLが起動しなくなった場合の解決方法を紹介します。

```
unknown variable 'default-authentication-plugin=mysql_native_password'.
```

# 解決方法

my.confを下記のように修正すればOK。

```diff_conf:my.conf

　- default-authentication-plugin=mysql_native_password
　+ mysql_native_password=ON

```

# 背景

複数のDockerコンテナでMySQLサーバーを起動していたので、ポート被り解消のためにポート番号を変えて起動しましたが上手くいかず。
記述を元に戻すと上記バグが発生しました。
バージョンをlatestで指定していたので、コンテナを再ビルドする際に使用バージョンが変わったのかもしれない。

# おわりに

GPT4だけでなく、Google検索も並行して使った方が、より早く問題解決しますね。

# 参考

記事内の『Deprecation and Removal Notes』を参照

https://dev.mysql.com/doc/relnotes/mysql/8.4/en/news-8-4-0.html
Dockerfileでnode.js(Express)のHELLOWORLDを10分で出力！

## やりたかったこと
Dockerが提供するNodeイメージからコンテナを作成しexpressのインストールを行いブラウザ上で「HELLO WORLD」表示までできたが、毎回立ち上げるたびに作業が発生して面倒くさい(楽したい)ので、Dockerfileを使ってみました


## やったこと
- 環境構築
・Dockerインストール
・自身のPCに作業用ディレクトリ作成
- コーディング
・expressのルーティングで使用するindex.js作成
・コンテナ作成時に使用するDockerfileの作成 ★今回のメイン
- Dockerfileからコンテナを作成
・DockerfileからDockerImageを作成
・作成したImageからコンテナを立ち上げ
・立ち上げたコンテナへブラウザからアクセス Fin

### 環境構築/Dockerインストール & 自身のPCに作業用ディレクトリ作成
まずはとりあえずDockerを使えるようにインストールをしていきます。

[Docker公式サイト](https://docs.docker.com/desktop/install/windows-install/)よりDocker Desktop on Windowsをインストール

適当なパスに作業用のフォルダを作成してください。
私はドキュメント配下に「node」というフォルダを作成しています。

### コーディング/expressのルーティングで使用するindex.js作成
作成したnodeフォルダ配下に以下のファイルを作成
```javascript:index.js
const express = require("express");
const app = express();

app.get("/", (req, res) => {
    res.send("HELLO WORLD");
});

app.listen(80, () => {
    console.log("Start server on port 80");
});
```
### コーディング/コンテナ作成時に使用するDockerfileの作成
index.jsと同様にnodeフォルダ配下に以下のファイルを作成
```Docker:Dockerfile
FROM node:latest

WORKDIR /var/www

RUN npm install express
COPY ./index.js /var/www/.

CMD ["node","index.js"]
```

### Dockerfileからコンテナを作成/DockerfileからDockerImageを作成
コマンドプロンプトor PowerShellより以下のコマンドを実行しDockerImageを作成する
```bash:
cd <自身で作成したnodeフォルダ>
docker build -t express-image .
```
:::note warn
cdでnodeフォルダに移動しないと```docker build```コマンドがDockerfileが見つからないためエラーとなるので注意してください。
:::

### Dockerfileからコンテナを作成/作成したImageからコンテナを立ち上げ
コマンドプロンプトor PowerShellより以下のコマンドを実行し作成したImageをベースにしたコンテナを作成
```bash:
docker container run -it --name express -p 8000:80 -d express-image
```
:::note warn
自身のPCですでに8000ポートを使用している場合、同一ポートを複数アプリで使用することになりエラーが発生します。その際には8000の部分には使用していないポート番号を指定してください。
:::

### Dockerfileからコンテナを作成/立ち上げたコンテナへブラウザからアクセス
任意のブラウザ(GoogleChrom/safari/InternetExplorerなど)から```http://localhost:8000```へアクセス
以下の画面が表示されればExpress環境の構築完了です！お疲れ様でした～
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678667/da9acae4-44f1-ae86-5d34-96958ccdaeb9.png)
AWS Lambdaに画像を送信する

# この記事は？
AWS Lambdaエンドポイントに画像を送って処理をする方法のメモ。結論、base64でエンコードしてjsonとして画像を送れば良い。

# 本文
## リクエストの方法
Lambdaではバイナリとして画像を受信できないようである。バイナリとして画像を送信すると次のようなエラーが出る。

```bash
Unable to unmarshal input: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte
```

エラー内容からすると、Lambdaはリクエストをutf-8として解釈するようだ。なので、画像を送信するときはbase64でエンコードして、jsonとして送ってやる必要があると推察される。サイズの大きい画像を送る場合、curlにエンコードした画像をそのまま渡すと、引数が長すぎてエラーが出るため、一度jsonファイルに変換してやる必要がある。

```画像ファイルをbase64でエンコードしてjsonに変換.bash
echo "{\"body\": \"$(base64 path/to/image)\"}" > sample.json
```

```jsonに変換した画像をcurlで送信.bash
curl -X POST "lambda/endpoint" \
    -H "Content-Type: application/json" \
    -d @sample.json 
```

## Lambdaの実装
`body` キーにbase64でエンコードした画像を割り当てたので、値を取り出してデコードする。以下はデコードした画像のサイズを返すサンプル関数。

```py
import base64
import io
import os

from PIL import Image


def handler(event, context):
    image_b64 = event['body']
    image_bytes = base64.b64decode(image_b64)
    image = Image.open(io.BytesIO(image_bytes))
    return str(image.size)
```
ExcelVBA　勉強メモ

# VBA勉強メモ（2024/4/30）
勤務先で使えるかな～？って思ったのでメモ程度に残しておく

## 基本
```vb
Sub プロシージャ名()
    Dim 変数名
    Dim 変数名 as 型
    '型名は色々ある。DateとかVarriantとか
    Const 定数名 As 型名

    '比較演算子
    '下記例　Modとかあるよ。後「かつ」はAndね
    Range("A1").Value < Range("A2").Value

    '文字列結合　"+"も使えるけど、"&"で全部解決
    Dim x
    Dim y
    Dim z
    x = "どうも"
    y = "よろしくお願いします"
    'どうもよろしくお願いします
    z = x & y

    '改行
    Range("B2") = "札幌市" & vbLf & "中央区"
End Sub

Sub セル出力()
   Worksheets("出力練習シート").Range("B2") = "札幌市" & vbLf & "中央区"
End Sub

Sub object_colection()
    'オブジェクトで主に使うのは下記
    Application：Excelアプリ全体
    Workbook：Excelブック
    Worksheets：ワークシート
    Range：行とかセル
    Chart：グラフ
    Dialog：組み込みダイアログ

    'コレクションは下記　オブジェクトの複数みたいなもん
    Workbooks：開いているすべてのブック
    Worksheets：ブックに含まれるすべてのシート

    '任意のワークシートを変数として指定
    Dim ws as Worksheets
    Set ws = Worksheets("ワークシート名")

    'こんなこともできる　下記の階層参照
    Dim sell As Range
    Set sell = Worksheets("別のワークシート").Range("B5")

    'VBAはTrueは-1でFalseは0
End Sub
```
代替こんな階層
Application
 |
 +- Workbook(s)
     |
     +- Worksheets
         |
         +- Range
             |
             +- Font など

## 条件分岐

```vb
Sub 条件分岐()
   If Worksheets("条件分岐シート").Range("B2").Value > 70 Then
      MsgBox "条件分岐シート選択ができました" & vbCrLf & "値は70以上です"
   ElseIf Worksheets("条件分岐シート").Range("B2").Value > 60 Then
      MsgBox "条件分岐シート選択ができました" & vbCrLf & "値は60以上です"
   End If
End Sub

Sub Case条件分岐()
   Select Case Worksheets("条件分岐シート").Range("C2").Value
   Case 0
       MsgBox "値は0です!"
   Case 1
       MsgBox "値は1です!"
   Case 2
       MsgBox "値は2です!"
   Case Else
       MsgBox "値はその他です。" & vbCrLf & "値:" & Worksheets("条件分岐シート").Range("C2")
   End Select
End Sub

Sub 継続条件分岐()
   Dim num As Integer
   num = 0
   Worksheets("条件分岐シート").Range("D2").Value = 0
   
   Do While num < 5
      Worksheets("条件分岐シート").Range("D2").Value = Worksheets("条件分岐シート").Range("D2").Value + 1
      num = num + 1
   Loop
End Sub

Sub FOR繰り返し()
   Dim sum As Integer
   Dim i As Integer
   
   sum = 0
   For i = 0 To 9
      sum = sum + 1
      MsgBox "現在の値は" & sum
   Next
End Sub

' 5回しか行わない
Sub FOR繰り返し_STEP()
   Dim sum As Integer
   Dim i As Integer
   
   sum = 0
   For i = 0 To 9 Step 2
      sum = sum + 1
      MsgBox "現在の値は" & sum
   Next
End Sub

' Exit DoがBreakの代わりになる
```

## 配列
```vb
' B2から値が入ってます。
Sub 配列()
   Dim pref(4) As String
   Dim i As Integer
   Dim n As Integer
   
   Dim src As String
   
   i = 2
   n = 0
   src = 3
   Do Until IsEmpty(Worksheets("配列シート").Range("B" & i).Value)
      pref(n) = Worksheets("配列シート").Range("B" & i).Value
      i = i + 1
      n = n + 1
   Loop
   
   For i = 0 To UBound(pref)
      If src = pref(i) Then
         MsgBox "一致しました" & vbCrLf & "セル位置:" & "B" & i + 2
      End If
   Next
End Sub
```
Crystalで正規分布に基づく乱数を生成する

## はじめに

Crystal言語で正規乱数が出したくなった。しかし、Crystalは数値計算を目的としたプログラミング言語ではないので標準ライブラリにはなかった。

## Box-Muller法

ボックス=ミュラー法というものを使えば、一様分布に従う確率変数から、標準正規分布に従う確率変数を生成できるそうだ。

## 実装

Seedを設定して毎回同じ乱数が出るようにしたかった。

- 標準ライブラリのRandomをオープンクラスで拡張する
- 標準ライブラリのRandomを継承してRandom2を作る
- 新しくRandクラスを作り、知らないメソッドが呼ばれたらRandomに委譲する

の3つのパターンが考えられて、一番最後のものを採用することにした。

```crystal
class Rand
  def initialize
    r = Random.new
    initialize(random: r)
  end

  def initialize(seed : UInt64)
    r = Random.new(seed)
    initialize(random: r)
  end

  def initialize(random : Random)
    @random = random
    @iset = 0.to_i32
    @gset = 0.to_f64
  end

  forward_missing_to @random

  # Generates a random number from a standard normal distribution.
  def randn : Float64
    if @iset == 0
      rsq, v1, v2, fac = 0.0, 0.0, 0.0, 0.0
      loop do
        v1 = 2.0 * @random.next_float - 1.0
        v2 = 2.0 * @random.next_float - 1.0
        rsq = v1 * v1 + v2 * v2
        break if rsq < 1.0 && rsq != 0.0
      end

      fac = Math.sqrt(-2.0 * Math.log(rsq) / rsq)
      @gset = v1 * fac
      @iset = 1
      return v2 * fac
    else
      @iset = 0
      return @gset
    end
  end

  # Generates a random number from a normal distribution with the specified mean and standard deviation.
  def randn(mean, std_dev) : Float64
    mean = mean.to_f
    std_dev = std_dev.to_f
    raise "std_dev must be positive" if std_dev.negative?
    mean + std_dev * randn()
  end
end
```

Cのコードなどを見ながら見よう見まねで書いている。何か間違っている部分を発見したらコメント欄で指摘してほしい。

## ライブラリにした

https://github.com/kojix2/randn.cr

このコードは再利用する機会がありそうなのでShardにした。Crystalは発展途上の言語なので、自分で書いたコードを再利用しやすいように積極的にライブラリとして公開していきたい。

この記事は以上です。
Rucksäcke: Stilvoll, Funktionell und Unverzichtbar

Einleitung:
Rucksäcke sind nicht mehr nur praktische Gegenstände zum Tragen von Gegenständen. Sie sind zu unverzichtbaren Accessoires in der modernen Welt geworden. Die Entwicklung von Rucksäcken hat sich stark weiterentwickelt, wobei Funktionalität und Stil gleichermaßen berücksichtigt werden.
Rucksack-Trends für Damen und Herren:
Die Welt der Rucksack Damen Herren unterscheidet sich deutlich zwischen den Geschlechtern. Designs und Merkmale variieren erheblich für Damen und Herren. Die vielseitigen Einsatzmöglichkeiten im Alltag und im Geschäftsleben machen sie zu einem Must-have.
Eleganz und Stil: Moderne Rucksäcke für Business-Zwecke:
Besonders in geschäftlichen Umgebungen werden elegante Rucksäcke zunehmend beliebt. Die Kriterien für diese Rucksäcke kombinieren Funktionalität und Design auf eine Weise, die professionellen Anlässen gerecht wird.
Praktische Aspekte von Laptop-Rucksäcken:
Die Anforderungen an Rucksäcke für Laptops sind spezifisch. Der Schutz, Komfort und ausreichender Stauraum für technologische Geräte sind essenziell für moderne Rucksäcke.
<a href="https://rucksack-damen-herren.com/collections/rucksack-herren-alltag">Visit Website</a>
モデルの精度以前に特徴量が適しているかを疑う

私が保有している資格の一つにビジネス統計スペシャリストというものがあって、その内容にあまりにも実データと乖離している予測結果のデータは説明変数で説明しきれていないというものがありました。
それは重回帰分析を使った回帰とそれを使った分類で行っていましたが、せっかくPythonが使えるのでより精度の高い勾配ブースティング回帰木を使って目的変数に対して説明変数が妥当な変数なのかを実際に確かめてみようと思います。
やり方としては交差検証を使って満遍なくデータを調べてみようと思います。

# 乳がんデータセット
この乳がんのデータセットはScikit-LearnではなくlifelineというライブラリにあるRCTなのかコホート研究なのかのデータセットになります。
ここではガンのサイズについてを目的変数として他を説明変数にします。
## ライブラリのインポート
```Python3
from sklearn.model_selection import cross_val_score as cvs
from sklearn.ensemble import GradientBoostingRegressor as GBR
import pandas as pd
```
## データの読み込み
```Python3
df = pd.read_csv("gbsg2.csv")
df.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782889/ec3a9fd6-3a3f-d816-fb25-937bfb4e582e.png)

## 説明変数と目的変数を分ける
なお質的変数が入っているため多重共線性を考慮して削除します。
```Python3
y = df["tsize"]
x = pd.get_dummies(df.drop("tsize", axis=1))
x = x.drop(["horTh_no", "menostat_Pre", "tgrade_II"], axis=1)
x.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782889/f6528e62-d1c0-216c-73e5-d0ee91d5127c.png)

## 交差検証
データを100分割して検証してみます。
```Python3
model = GBR()
score = cvs(model, x, y, cv=100, scoring="r2")
df_score1 = pd.DataFrame(score).describe()
```

# ボストン住宅価格のデータセット
次にScikit-Learnで用意されている回帰用データセットのボストン住宅価格のデータセットではどうなっているか見てみましょう。
## データの読み込み
```Python3
df = pd.read_csv("boston.csv")
df.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782889/6d3ef609-00d5-6fc3-140a-ec60ae2217f9.png)

## 説明変数と目的変数を分ける
```Python3
y = df["PRICE"]
x = df.drop("PRICE", axis=1)
```

## 交差検証
```Python3
model = GBR()
score = cvs(model, x, y, cv=100, scoring="r2")
df_score2 = pd.DataFrame(score).describe()
df_score = pd.concat([df_score1, df_score2], axis=1)
df_score.columns = ["gbsg2", "boston"]
df_score
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782889/ad4b4b75-8b36-750c-8f34-da76dd27e8fd.png)
R2を指標にしていますが、物凄く精度が悪いとマイナスの値になる事もあるそうです(値域は－∞から1)。
精度の分布を見てみると最小値など外れ値でボストン住宅価格のデータセットは平均値が低いですが下位25%から最大値まで見てみると精度の違いが明らかだと思います。

# まとめ
よく精度を意識するならGBDT→ディープラーニング→他機械学習→数理モデルなど言われていますが、そもそもデータセットが正しいかどうかも検討しないといけません。

# 参考文献
<a href="https://www.scsk.jp/sp/mwai/blog/cat/r2.html">回帰分析における評価指標―⑤R2(決定係数)― | 評価指標(回帰) | ブログ | SCSK AI AutoML</a>
ボタンのカスタムショートコードを作る

ボタンのカスタムショートコードの作り方を解説します。

## ボタンのカスタムショートコード

```php
[btn link="https://www.example.com"]クリック[/btn]
```

投稿画面でブロック挿入ツールからショートコードを選択します。次に、上記のショートコードを記述します。

## functions.phpに記述するコード

```php
function my_shortcode($attrs, $content = '') {
	return '<div class="entry-btn"><a class="btn" href="' . $attrs['link'] .'">' . $content . '</a></div>';
}
add_shortcode('btn', 'my_shortcode');
```

functions.phpに上記のコードを記述します。

## コードの解説

### my_shortcodeという名前の関数を定義

```php
function my_shortcode($attrs, $content = '') {
```

- `my_shortcode`という名前の関数を定義しています。この関数は、`$attrs`と`$content`という二つのパラメータを受け取ります。これらのパラメータは、ショートコードが展開される際に、どのような内容が表示されるかを制御するために使用されます。 <br><br> 
- `$attrs`はショートコードに指定された属性を格納する連想配列です。例えば、ショートコード`[btn link="https://www.example.com"]クリック[/btn]`の場合、`$attrs`配列には`link` ⇒ `https://www.example.com`というキーと値のペアが含まれます。これにより、`link`属性に設定されたURLにアクセスすることができます。<br><br> 
- `$content`はショートコード内のコンテンツ（今回の例では「クリック」）を表します。デフォルトでは空の文字列です。

### $attrs['link']と$content **: ショートコードのキー要素の理解**

```php
return '<div class="entry-btn"><a class="btn" href="' . $attrs['link'] .'">' . $content . '</a></div>';
```

- 関数はHTMLの構造を文字列として返します。<br><br> 
- `$attrs['link']` ：これは`$attrs`配列から`link`キーに対応する値を取り出します。ショートコードに`[btn link="https://example.com"]` のように記述されていれば、`https://example.com` がこの部分に代入されます。<br><br> 
- `$content`: これはショートコードの開始タグと終了タグの間のコンテンツを表します。例えば、ショートコード`[btn link="https://www.example.com"]クリック[/btn]`の場合、「クリック」が`$content`に代入され、ページに表示されます。

### add_shortcode 関数

```php
add_shortcode('btn', 'my_shortcode');
```

`add_shortcode` 関数は、第一引数にショートコードの名前（この場合`btn`）と、第二引数にこのショートコードが呼ばれたときに実行する関数（`my_shortcode`）をWordPressに登録します。これにより、投稿やページ内で`[btn]`というショートコードを使用すると、`my_shortcode`関数が実行され、指定したリンクとテキストでボタンが表示されます。
TerraformでDynamoDBに一気にデータを突っ込みたい時のやつ

### 結論から
TerraformでMapをListにして突っ込む方法があまり検索に引っかからないのもあり、残しておくことにした。

```terraform:main.tf
resource "aws_dynamodb_table" "example" {
  name         = "ExampleTable"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "PartitionKey"
  range_key    = "SortKey"

  attribute {
    name = "PartitionKey"
    type = "S"
  }

  attribute {
    name = "SortKey"
    type = "S"
  }

  tags = {
    Name = "ExampleTable"
  }
}

locals {
  list = [
    { PartitionKey = { S = "hoge" }, SortKey = { S = "1" }, Content = { S = "サンプルデータ1" } },
    { PartitionKey = { S = "hoge" }, SortKey = { S = "2" }, Content = { S = "サンプルデータ2" } },
    { PartitionKey = { S = "hoge" }, SortKey = { S = "3" }, Content = { S = "サンプルデータ3" } },
  ]
}

resource "aws_dynamodb_table_item" "example" {
  for_each   = { for i in local.list : "${i.PartitionKey.S}#${i.SortKey.S}" => i }
  table_name = aws_dynamodb_table.example.name
  hash_key   = aws_dynamodb_table.example.hash_key
  range_key  = aws_dynamodb_table.example.range_key
  item       = jsonencode(each.value)
}
```

### 解説
`for_each`に `"${i.PartitionKey.S}#${i.SortKey.S}"`を渡してる理由はDynamoDBの使用上`PartitionKey`と`SortKey`を合わせてPrimaryのためMapのキーで文字列結合させているためである。
【DRF】 Django rest_frameworkを使って10分で簡単なCRUDを実装してみた

## はじめに
Djangoのrest_frameworkを使用して簡単にCRUD処理を実装してみたのでその備忘録として書き留めておく。思った以上に書かなくて最低限なら爆速で実装できるので個人的には使いやすい。

## 1.Djangoやrest_frameworkその他install
```python:requirements.txt
Django==4.2
djangorestframework==3.14.0
mysqlclient
uwsgi
```

必要なものはrequirements.txtに記載して一括でパッケージやライブラリを追加するやり方を取った。

```python:shell
pip install -r requirements.txt
```

これで指定したパッケージやライブラリの追加が完了する。

## 2.Djangoのプロジェクトやアプリケーションを作成
1.下記コマンド実行
```shell
django-admin startproject config .
```
※configはお好きな名前をどうぞ

2.下記コマンドを実行
```shell
python manage.py startapp todo
```
※todoはお好きな名前をどうぞ

3.下記コマンド実行
```shell
python manage.py makemigrations
```

4.下記コマンド実行
```shell
python manage.py migrate
```

5.下記コマンド実行
```shell
python manage.py collectstatic --noinput
```

とりあえず一通り実行しておく。

## 3.models.pyを作成
```python:models.py
from django.db import models

class Todo(models.Model):
    title = models.CharField(max_length=100)
    detail = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = 'todo'

```

db_tableでテーブル名を指定することが可能。

models.pyの記述ができたら下記コマンドを実行する。
```shell
python manage.py makemigrations
```

その後下記コマンドを実行する。
```shell
python manage.py migrate
```

これでテーブル作成が完了する。

次章「4」が本題。

## 4.rest_frameworkでCRUD処理実装
主に5ファイルで完結する。
・ urls.py ← configフォルダ
・ urls.py ← todoフォルダに新規で作成
・ views.py
・ TodoSerializer.py ← これは自分で作成
・ models.py ← 3章で作成したmodels.py

```python:config/urls.py
from django.urls import path, include

urlpatterns = [
    path('api/v1/todo/', include('todo.urls')),
]

```

```python:todo/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('item/', views.TodoList.as_view()),
    path('item/<int:pk>/', views.TodoDetail.as_view()),
]

```

```python:todo/views.py
from rest_framework import generics
from .models import Todo
from .serializers import TodoSerializer

class TodoList(generics.ListCreateAPIView):
    queryset = Todo.objects.all()
    serialzier_class = TodoSerializer.TodoListSerializer

class TodoDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Todo.objects.all()
    serializer_class = TodoSerializer.TodoListSerializer

```

```python:todo/serializers/TodoSerializer.py
from rest_framework import serializers
from todo.models import Todo

class TodoListSerializer(serializers.ModelSerializer):
    class Meta:
        model = Todo
        fields = '__all__'

```
※serializersフォルダを作成しているが作成しなくてもできる。

```todo/models.py
from django.db import models

class Todo(models.Model):
    title = models.CharField(max_length=100)
    detail = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = 'todo'

```
※3章で作成したmodels.pyを使用する。特に変更点はなし。

## 5. URLにアクセス
これでローカル環境であれば下記にアクセスする。
※個人的に作成したdocker環境で自分は実行した。
```shell
http://localhost/api/v1/todo/item/
```
上記URLにアクセスをすると

・　GETは全件取得処理
・　POSTは登録処理

が行える。

```shell
http://localhost/api/v1/todo/item/2/
```
idが２のレコードがあることがまず前提。
上記URLにアクセスをすると

・　GETで詳細取得処理(今回でいうとidが２のレコード情報)
・　PUTで更新処理
・　DELETEで削除処理

が行える。

## 終わりに
書く量少なっ。。。
GCEに「NGINX Unit」を入れる ver.2024

前回の記事は、こちら
[https://yamayoshi.blogspot.com/2020/04/gcenginx-unitweb.html](https://yamayoshi.blogspot.com/2020/04/gcenginx-unitweb.html)
セキュリティが強化されたようで、config.json に user を追加しています。
一旦動いてしまえば、Unit 最高。 

## Flask
```
$ cd
$ mkdir project1 && cd project1
$ python3 -m venv venv
$ source venv/bin/activate
V pip install Flask
V nano main.py
```
```main.py
from flask import Flask
application = Flask(__name__)
@application.route("/")
def index():
    return "Hello Project1!"
if __name__ == "__main__":
    application.run()
```
```
V deactivate
```
## Unit - Ubunt22.04
```
$ cd
$ sudo -i
# curl --output /usr/share/keyrings/nginx-keyring.gpg https://unit.nginx.org/keys/nginx-keyring.gpg
# nano /etc/apt/sources.list.d/unit.list
```
```/etc/apt/sources.list.d/unit.list
deb [signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://packages.nginx.org/unit/ubuntu/ jammy unit
deb-src [signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://packages.nginx.org/unit/ubuntu/ jammy unit
```
```
# apt update
# apt install unit unit-dev unit-python3.10
# systemctl restart unit
```

## Unit 設定
```
# nano config.json
```
```config.json
{
    "listeners": {
        "*:80": {
            "pass": "applications/flask_app"
        }
    },
    "applications": {
        "flask_app": {
            "type": "python",
            "user": "<user>",
            "path": "/home/<user>/project1",
            "home": "/home/<user>/project1/venv",
            "module": "main"
        }
    }
}
```
```
# curl -X PUT --data-binary @config.json --unix-socket /var/run/control.unit.sock http://localhost/config
# service unit restart
```
以上です。
input type="date" に元号で入力する方法

type="date"のinputタグに元号で日付を入れたいという需要はたびたびありまして，いろいろと解決方法を探していく中で1つ方法を見つけました。

対策はいろいろと公開されていますが，どれもほしいものとちょっと違いました。

1. セレクトボックスを使う方法
 100年分とか全部optionにするのも....うーん
1. 西暦・元号をセレクトボックスにして年月日を別inputにする方法
 月日だけの入力インターフェースがないので，セレクトボックス増えちゃうし，2月31日みたいなのを選ばせないようにスクリプトを組むのも面倒....
1. 西暦で入れたあとにそれを元号で表示する方法
 そもそも元号で入力したいので，これも違う....

ということで実装です。
```javascript:hoge.js
window.addEventListener('DOMContentLoaded', ()=> {
    document.getElementById('genDate').addEventListener('blur', ()=>{
        var genStr = document.getElementById('genDate').value;
        var gen = genStr.substr(0,1);
        var year = Number(genStr.substr(1,2));
        var month = genStr.substr(3,2);
        var day = genStr.substr(5,2);
        if(gen === 'M' || gen === 'm')year += 1867;
        else if(gen === 'T' || gen === 't')year += 1911;
        else if(gen === 'S' || gen === 's')year += 1925;
        else if(gen === 'H' || gen === 'h')year += 1988;
        else if(gen === 'R' || gen === 'r')year += 2018;
        document.getElementById('date').value = String(year)+'-'+month+'-'+day;
    });
});
```

元号入力用のテキストボックス(id:genDate)に S400502 のようにいれると，本命の日付入力ボックス(id:date)に西暦変換して埋めてくれるという方法です。
見栄えは多少悪いですが，西暦で入れたければ直接入力すればOKです。

年を変換しているだけなので，例えば R010401 とか S990501 とかも通ってしまいますが，S400231 のような実在しない日付はブラウザで弾いてくれます。
openflowとNETCONFの位置付け

# 目的
SDNにおけるopenflowやNETCONFIGの位置付けがよくわからなかったので整理。

## SDN(Software Defined Networkking)に含まれる技術要素 ##
以下が含まれる。本記事では、Openflowとネットワーク装置のAPIに着目する。

* Openflow
* ネットワーク装置のAPI(SNMP,NETCONF,RESTfulAPI)
* NFV
* ベアメタルスイッチ
* ネットワークの自動化
* SD-WAN

## Openflowの意義
1. ネットワーク装置のコントロールプレーンと制御プレーンを分離している点。__これにより、BGP,OSPF,STPといったネットワーク装置間の制御プロトコルが不要になり、コントローラによる一元管理が可能となる。__
1. パケット転送のみを制御する。認証やSNMPなどの管理レイヤの制御はスコープ外。
1. openflowによるデータ転送に、従来のルーティングを組み合わせることが可能。

![sdn.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630941/c51ae49e-e1ea-f66d-aa20-7a801c0b8c49.png)

## ネットワーク装置のAPIの意義
1. コマンド文字列解析をせずに構造化データとして利用できること
    1. 構造化データのフォーマットには、「YAML」「XML」「JSON」などがある。YAMLは人とソフトウエア間向けフォーマットであり、XML、JSONはソフトウエア間のフォーマットである。
    1. データフォーマットについてどのような構造化に基づいてデータを保持することか定義するものがデータモデル。XMLにはXSD、 JSONにはJSONスキーマがあるが共通で利用可能なネットワーク装置向けのデータモデルにYANGモデルがある。YANGモデルで定義したデータはツールによりXML,JSONフォーマットにエンコード可能である。 
1. APIの種類には「SNMP」「NETCONF」「RESTfulAPI」がある
    1. SNMPは、ポーリング式のプロトコルで、サーバからネットワーク装置上で動作するSNMPエージェントに対して、SNMPで利用可能なデータをモデル化したMIBデータについて、取得・設定を行うことが可能。
    1. NETCONFは、SSHコネクションによる型のプロトコル。NETCONFクライアントからネットワーク装置上で動作するNETCONFサーバに対して、送受信するデータは、XMLでエンコードされている。XMLにはRPCを埋め込むことも可能。トランザクションベースの設定制御に対応。
    1. RESTfulAPIは、HTTPベースのシステム同様に、ネットワーク装置であるサーバに対してクライアントが制御をする。HTTP GETにより、JSONやXMLで構造化されたデータを取得できる。




# まとめ
* OpenflowとSNMP/NETCONF/RESTfulAPIは、そもそもの存在目的が異なる。

* Openflowはネットワーク装置の、コントロールプレーンとデータプレーンを分離した点が重要であり、Openflowのプロトコルはデータプレーンを制御するためのコントロールプレーンに関する制御。

* SNMP/NETCONF/RESTfulAPIはネットワーク装置の管理に関する制御。

# 参考
https://www.oreilly.co.jp/books/9784873119816/
画像の輝度ムラ補正（フラットフィールド補正，背景成分除去）

# はじめに
[フラットフィールド補正](https://en.wikipedia.org/wiki/Flat-field_correction)は，画像から背景成分（低周波な輝度ムラ）を除去する処理です。輝度ムラは，画像解析する上で邪魔なので，除去対象になります。

以下のQiita記事で，フラットフィールド補正が取り上げられています。
(参考1) [Flat Field画像処理](https://qiita.com/Gyutan/items/2d82fe71f41fc00cb6f8)

上記のQiita記事では，以下のサイトが参照されています。
(参考2) [背景除去について](https://waku-take-a.github.io/%25E8%2583%258C%25E6%2599%25AF%25E9%2599%25A4%25E5%258E%25BB%25E3%2581%25AB%25E3%2581%25A4%25E3%2581%2584%25E3%2581%25A6.html)

これらの記事では，**画像を強く平滑化**して**低周波成分**を抽出し
(方法1：除算補正) 元画像÷低周波成分×平均輝度値
(方法2：差分補正) 元画像‐低周波成分+平均輝度値
というシンプルな補正方法が紹介されています。

# 試してみた
(参考2)からサンプル画像を拝借して，自分でも試してみました。
低周波成分の抽出には，半値幅40画素の等方的なガウシアンフィルタを用いました。

|サンプル画像|低周波成分|
|---|---|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/c60a189a-ae53-cbbb-b27f-dae3314af78c.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/50c7a3c3-fc00-a5b7-29c6-9a6e0b172799.png)|

|除算補正|差分補正|
|---|---|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/ba0640c9-5e82-1b67-81e3-40ed860c4687.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/fee1ba17-2cd6-2113-d0b2-aa76ac8d5ae8.png)|

想定通り，低周波な輝度ムラはうまく除去できしたが，(参考2)で言及されているように，サンプル画像には**縞状のムラも存在していて，そちらはうまく除去できません**。

(参考2)では，対処方法として，補正後(?)の画像のフーリエ変換を計算し，縞の走行方向（上下方向）に対応する周波数成分をカットして，縞状のムラの除去に成功しています👇

|バンドパスフィルタ|逆フーリエ変換の結果|
|---|---|
|![image.png](https://waku-take-a.github.io/img/SubBack11.bmp)|![image.png](https://waku-take-a.github.io/img/SubBack10.bmp)|

(参考2)では，この方法の注意点が付記されています。その通りと思います。
> - 万能ではありません
> - FFT自体の処理は時間がかかります。さらにパディングなんかしたら処理時間はさらにup。

今回の記事では，**万能ではないけど，処理時間を増やさずに（むしろ減らせる）** ，縞状のムラも除去できる補正方法を紹介します。

はじめに言っておくと，全くもって大したものではありません :smiley: 

# 解決策：非等方な平滑化

**非等方な平滑化フィルタ**を用いたら，**余計な成分**をうまく抽出できました。 以上です！

(参考2)では等方的な平滑化フィルタを用いていますが，**縦方向のフィルタ幅だけを小さくした「非等方的な平滑化フィルタ」** を用いたら，縞状のムラも抽出できるはずと思い，試してみたという感じです。

処理結果は以下です。ここでは，横方向の半値幅40画素，縦方向の半値幅2画素の非等方なガウシアンフィルタ（非常に横長なフィルタ）を用いました。

|サンプル画像|余計な成分（低周波成分＋縞成分）|
|---|---|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/c60a189a-ae53-cbbb-b27f-dae3314af78c.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/a6aaccc8-4c40-f27a-e783-f79687641c39.png)|

|除算補正|差分補正|
|---|---|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/dcb4ca5c-034d-3438-b4a3-18cf87124fae.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/f5da141d-cff2-05da-dc7a-ea6fe3a452b3.png)|

期待通り，「余計な成分」として，低周波な輝度ムラだけでなく，縞状のムラも抽出できています:clap: 補正結果もいい感じです:clap:


# 最後に
今回紹介した方法も，先験情報として縞の走行方向を利用しているので，**決して万能ではありません**が，非等方的なフィルタ処理の計算コストは，等方的なフィルタよりも小さく，**処理時間は減ります**。フィルタのウィンドウサイズが小さいためです。

なお，縞状のムラの除去は，画像処理分野では「**Stripe removal**」と呼ばれていて，伝統的に研究されており，数多くのアルゴリズムが提案されています。
[Google Scholar検索 "Stripe removal"](https://scholar.google.co.jp/scholar?hl=ja&as_sdt=0%2C5&q=%22stripe+removal%22&btnG=)

X線CTの投影データや衛星画像を対象にした研究が多いイメージです。最近は，深層学習ベースの帰納的な手法が多いようですが，縞模様の行列・テンソルとしての低ランク性に着目した演繹的な手法も結構あり，色々と勉強になりそうです。

以上です。
JavaScript ファイル名が意図した拡張子であるか判定する処理

## やりたいこと

ファイル名を与えられた時、それが期待する拡張子のものか判定します。
今回はファイル名`aaa.拡張子`が、テキストファイル`.txt`であるか判定します。

## 結論
1. ファイル名を`toLowerCase()`で小文字に寄せる
1. 末尾が`.txt`と一致するか`endsWith()`で判定する


この方法に至るまで少し手間取りましたので記事を書きました。

---

## ことの経緯

最初このように書いていました。

```javascript
// あまり良くない例
const fileName = 'aaa.txt';

if(fileName.includes('.txt')) {
  console.log('テキストファイル　です')
} else {
  console.log('テキストファイル　ではない')
}
```
ファイル名の中に期待する拡張子が見つかればよしとするものです。
これならば以下のパターンを網羅できます。
| ファイル名 | ファイル種類 | 結果 |
| :-      |:-          |:-    |
| aaa.txt | テキストファイル | テキストファイル判定 |
| aaa.hoge| テキストファイル以外 | テキストファイルではない判定 |

しかし、以下パターンで意図しない結果になります。

| ファイル名 | ファイル種類 | 結果 |
| :-      |:-          |:-    |
| aaa.txt.hoge |テキストファイル以外 | テキストファイル判定（ミス） |
| aaa.TXT |テキストファイル | テキストファイルではない判定（ミス） |
| aaa.Txt |テキストファイル | テキストファイルではない判定（ミス） |
| aaa.tXt |テキストファイル | テキストファイルではない判定（ミス） |
| aaa.txT |テキストファイル | テキストファイルではない判定（ミス） |
| aaa.TXt |テキストファイル　　| テキストファイルではない判定（ミス） |
| aaa.tXT |テキストファイル | テキストファイルではない判定（ミス） |
| aaa.TxT |テキストファイル | テキストファイルではない判定（ミス） |

## 解決
方法はいくつか考えられます。簡単に思えた方法を記載します。
今回狙うのは「.txtであるか?」です。そのため以下の方法を使います。
1. ファイル名を`toLowerCase()`で小文字に寄せる
1. 末尾が`.txt`と一致するか`endWith()`で判定する

```javascript
const fileName = 'aaa.TXT';

if(fileName.toLowerCase().endsWith('.txt')) {
  console.log('テキストファイル　です')
} else {
  console.log('テキストファイル　ではない')
}

// 出力：テキストファイルです

```

うまくいきました。
以上です。

<br><br><br>

### 蛇足
最終系にたどり着く前、以下のバージョンを挟んでいました
```javascript
const fileName = 'aaa.png.TXT';

if(fileName.slice(-4).toLowerCase() === '.txt') {
  console.log('テキストファイルです')
} else {
  console.log('テキストファイルではない')
}
```
やりたいことはできますが、スマートさに欠けます。ミスも起きやすそうです。
蛇足終わり
VSCodeの便利な拡張機能

# 概要
VSCodeで便利な拡張機能を記載していきます。
※新しい拡張機能を見つけ次第、随時追加予定です。

# 目次
#### 言語パック
- [Japanese Language Pack](#japanese-language-pack)
#### コード補間・整形
- [Prettier - Code formatter](#prettier---code-formatter)
- [IntelliCode](#intellicode)
#### 操作性向上
- [Bracket Select](#bracket-select)
#### エディタ表示
- [indent-rainbow](#indent-rainbow)
- [Better Comments](#better-comments)
- [zenkaku](#zenkaku)
- [TODO Highlight](#todo-highlight)
#### 背景表示
- [background-cover](#background-cover)
- [GlassIt-VSC](#glassIt-vsc)
#### ファイル出力
- [Markdown PDF](#markdown-pdf)
#### 開発・作成
- [PlantUML](#plantuml)
- [Markdown All in One](#markdown-all-in-one)
- [Marp for VS Code](#marp-for-vs-code)
#### その他
- [vscode-pets](#vscode-pets)

# 言語パック
## Japanese Language Pack
VSCodeの表示を日本語化してくれます。

https://marketplace.visualstudio.com/items?itemName=MS-CEINTL.vscode-language-pack-ja

# コード補間・整形

## Prettier - Code formatter
コードを綺麗に整形してくれます。

https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode

## IntelliCode

AIを使用してコードを補完してくれます。
IntelliSenseのような感じでコード保管をしてくれます。
GitHub上にある沢山のオープンソースのソースコードを使用して学習されたAIを使用しています。

https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.vscodeintellicode

# 操作性向上
## Bracket Select
括弧やクォーテーションの内側にあるテキストを一括で選択できます。

https://marketplace.visualstudio.com/items?itemName=chunsen.bracket-select

# エディタ表示

## indent-rainbow
インデントに色付けしてくれるので見やすくなります。

https://marketplace.visualstudio.com/items?itemName=oderwat.indent-rainbow

## Better Comments
コメントを色分けして表示してくれます。

https://marketplace.visualstudio.com/items?itemName=aaron-bond.better-comments

## zenkaku

全角スペース箇所を強調表示してくれます。

https://marketplace.visualstudio.com/items?itemName=mosapride.zenkaku

## TODO Highlight

TODOコメントをハイライトで強調表示してくれます。

https://marketplace.visualstudio.com/items?itemName=wayou.vscode-todo-highlight

# 背景表示

## background-cover
VSCodeの背景画像の変更ができます。

https://marketplace.visualstudio.com/items?itemName=manasxx.background-cover

## GlassIt-VSC
VSCodeの背景を透明化できます。
「background-cover」と併用も可能でした。

https://marketplace.visualstudio.com/items?itemName=s-nlf-fh.glassit

# ファイル出力

## Markdown PDF
MarkdownをPDFに変換できます。

https://marketplace.visualstudio.com/items?itemName=yzane.markdown-pdf

# 開発・作成

## PlantUML
UML図をテキストで記述できるようになります。

https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml

## Markdown All in One
markdownに関する様々な拡張機能が入っています。
マークダウンの見出しの内容から目次の作成ができる便利な機能もありました。

https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one

## Marp for VS Code
Marp (Markdownの文法でスライドの作成が可能なツール) を使用できます。

https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode

# その他
## vscode-pets
VSCode上でペットを飼うことができます。
犬、猫、鶏など、飼える動物の種類も沢山あります。

https://marketplace.visualstudio.com/items?itemName=tonybaloney.vscode-pets
Solidityで配列を使う方法(構造体も触れるよ)

今回はSolidityで配列を宣言する方法についてまとめようと思います。

# 宣言方法
```
uint[] array;
```
要素数を決めたいときは[]内に要素数を書きます。
また、publicと書くことでSolidityが自動的にgetterメソッドを作ってくれます。
```
uint[3] public array;
```

# 構造体を作って配列にしてみる
## 構造体宣言
```
struct Person {
    string name;
    uint age;
}
```
## 構造体配列を新たに作成して配列に格納
```
// 構造体の配列を作成
Person[] public people;

// 新しいPersonを作って、配列に格納する
Person tarou = Person("Tarou", 12);
people.push(tarou);
```

ぜひご参考に
C# で ワイルドカードを実装する

C# で ワイルドカードを実装してみます。

ワイルドカードは、「?」が任意の1文字にマッチし、「*」が任意の文字列（0文字以上）にマッチする仕様とします。

## WildCardクラス

IsMatch メソッドで入力文字列と、ワイルドカードを含む文字列を渡し、マッチするか判定します。
内部実装としては、ConvertToRegexで正規表現に置換します。具体的には ? を . に、 * を .* に変換しています。

```csharp
    public class WildCard
    {
        public bool IsMatch(string input, string wildCard)
        {
            var pattern = ConvertToRegex(wildCard);
            return Regex.IsMatch(input, pattern);
        }

        private string ConvertToRegex(string input)
        {
            string pattern = string.Empty;

            foreach (char c in input)
            {
                pattern += c switch
                {
                    '?' => ".",
                    '*' => ".*",
                    _ => Regex.Escape(c.ToString()),
                };
            }
            return pattern;
        }
    }
```


## テストクラス
xUnitによるテストコードとしていくつかマッチするパターンと、マッチしないパターンを用意します。
「?」が任意の1文字、「*」が任意の文字列（0文字以上）にマッチするか確認します。

```csharp
   public class WildCardTests
   {
       [Theory]
       [InlineData("abc", "abc", true)]
       [InlineData("a?c", "abc", true)]
       [InlineData("a?c", "a123c", false)]
       [InlineData("a?c", "ac", false)]
       [InlineData("a*c", "a123456c", true)]
       [InlineData("a*c", "ac", true)]
       [InlineData("a*c", "def", false)]
       [InlineData("*abc", "123456abc", true)]
       [InlineData("log?.txt", "log1.txt", true)]
       public void WildCard_ShouldMatchCorrectly(string pattern, string input, bool expected)
       {
           // Arrange
           var wild = new WildCard();

           // Act
           var actual = wild.IsMatch(input, pattern);

           // Assert
           Assert.Equal(expected, actual);
       }
   }
```


## 備考

ワイルドカードの仕様としては ~ (チルダ) もあるみたいです。
使ったことがないですね。

https://support.microsoft.com/en-us/office/using-wildcard-characters-in-searches-ef94362e-9999-4350-ad74-4d2371110adb
Ruby on Railsのyaml.h not found解決方法(Windows11)

# STEP 0
基本的なインストールは、こちらの記事を参考に

https://qiita.com/tks_00/items/711a022c6234fc495724

ただ、新規プロジェクト作成時にyaml.hが無いというような以下のようなエラーが出たので修正
~~~
C:/Ruby32-x64/lib/ruby/site_ruby/3.2.0/bundler/installer/parallel_installer.rb:123:in
`block in worker_pool'
  C:/Ruby32-x64/lib/ruby/site_ruby/3.2.0/bundler/worker.rb:62:in `apply_func'
C:/Ruby32-x64/lib/ruby/site_ruby/3.2.0/bundler/worker.rb:57:in `block in
process_queue'
  C:/Ruby32-x64/lib/ruby/site_ruby/3.2.0/bundler/worker.rb:54:in `loop'
  C:/Ruby32-x64/lib/ruby/site_ruby/3.2.0/bundler/worker.rb:54:in `process_queue'
C:/Ruby32-x64/lib/ruby/site_ruby/3.2.0/bundler/worker.rb:90:in `block (2
levels) in create_threads'

An error occurred while installing psych (5.1.2), and Bundler cannot continue.

In Gemfile:
  debug was resolved to 1.9.2, which depends on
    irb was resolved to 1.13.0, which depends on
      rdoc was resolved to 6.6.3.1, which depends on
        psych
         run  bundle lock --add-platform=x86_64-linux
Fetching gem metadata from https://rubygems.org/...........
Resolving dependencies...
Writing lockfile to C:/Users/username/Desktop/project/project/Gemfile.lock
         run  bundle binstubs bundler
Could not find importmap-rails-2.0.1, turbo-rails-2.0.5, stimulus-rails-1.3.3,
debug-1.9.2, web-console-4.2.1, irb-1.13.0, rdoc-6.6.3.1, psych-5.1.2 in cached
gems or installed locally
       rails  importmap:install
Could not find importmap-rails-2.0.1, turbo-rails-2.0.5, stimulus-rails-1.3.3, debug-1.9.2, web-console-4.2.1, irb-1.13.0, rdoc-6.6.3.1, psych-5.1.2 in cached gems or installed locally
Run `bundle install` to install missing gems.
       rails  turbo:install stimulus:install
Could not find importmap-rails-2.0.1, turbo-rails-2.0.5, stimulus-rails-1.3.3, debug-1.9.2, web-console-4.2.1, irb-1.13.0, rdoc-6.6.3.1, psych-5.1.2 in cached gems or installed locally
Run `bundle install` to install missing gems.
~~~

# STEP1
以下からlibyamlのzipをダウンロードし、解凍
    
https://github.com/yaml/libyaml/releases/tag/0.2.5
    

# STEP2
以下のコマンドを実行
~~~
gem install psych --platform=ruby -- --with-libyaml-dir=[libyamlのディレクトリパス]
~~~

# STEP3
インストールが完了したのでダウンロードしたzipファイルとそれを解凍したフォルダは削除してよし。
再度、プロジェクト作成、bundle installするとエラー吐かずに実行終了した。
【DBS-C01】DBS合格体験記


## はじめに
先日、AWS Certified Database – Specialtyを受検し、合格しました。
本試験は、2024/04/29を最終受検日として廃止されているので、今後の受検の参考にはならないと思いますが、記録として残しておきます。

https://aws.amazon.com/jp/blogs/news/aws-certification-retirements-and-launches/

## 受検時の状態
- 入社3年
- 業務でAWSを触る環境
- AWS CLF, SAA, SOA, DVA, SCS取得済み

## 勉強期間
2か月

## 勉強時間
合計30時間ほど

内訳
就業後0.5~1時間　電車移動時2時間

## 使ったもの

:::note
AWS Certified Database - Specialty Official Practice Question Set (DBS-C01 - Japanese)
:::
:::note
[AWS 認定データベース — 専門知識 AWS Certified Database – Specialty(DBS-C01) 認定試験の質問例](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-database-specialty/AWS-Certified-Database-Specialty_Sample-Questions.pdf)
:::
:::note
[Cloud Licence](https://cloud-license.com/)
:::

- 毎度のことながら、CloudLicenceでの問題演習と復習に時間をかけました。問題演習は[SCS受検時の反省](https://qiita.com/am_i-12/items/bd043e4643ec6f27d6d8#%E3%81%A9%E3%81%86%E3%81%99%E3%82%8C%E3%81%B0%E9%AB%98%E5%BE%97%E7%82%B9%E3%82%92%E7%8B%99%E3%81%88%E3%81%9F%E3%81%8B) を活かして、3周しました。そのため、前回より自信を持って受検できました。
  - その一方で、1カ月ほどでコンスタントに8割正答できるようになり、残り1カ月はだらだら勉強してしまったので、点数が取れるようになってきたタイミングで、試験日を早めても良かったかもと思いました。

- DBは仕事であまり使わず、なじみのない分野なので、AWSコンソールで実際のサービス画面を見ながら学習することを意識しました。そのおかげで、知識の定着がスムーズになったと思います。
- 毎回愛用しているAWS Skill Builderの模擬試験のDBS用がなかったので、少し残念でした。調べてみたところ、CLF, SAA, SOA, DVA, SAP, DOP, SCSは日本語で模擬試験が用意されているようです。英語でも同じラインナップでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851817/ffb907a9-5b49-7dca-6b6c-16a74ca8ef81.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851817/08940045-8b7d-4ca1-571d-be5fc38fb802.png)


## 本番のスケジュール
9:30 会場着　本人確認や写真撮影を済ませる　
テスト前の受付は30分前からとのことで、10時予約で9時半から受付し始めしました

9:45-12:30ごろ　受検

19:18にバッジ認定メール
→この段階でAWSのサイト行ったらスコアレポート見れました。
19:28にスコアレポートのメールが来ました。（結果：816点）
今回はバッジのメールもスコアレポートのメールも来るのが早かったです。

## 感想
これで通算6個目のAWS資格となりました。実務経験や資格数が増えてきたおかげで、対策にかかる時間や単純な暗記で正解する問題が減っていることを実感できて嬉しいなと思います。引き続き、次のSpecialityやProfessional資格取得のために勉強頑張ります！

以上です。ありがとうございました。
format-tableの出力カラム数

## 概要
format-tableは通常は10までのcolumnしか出せないが、-property *をつけると10を超えて表示できる。

## 詳細
まあ、概要がすべてなんだが、昨日はChatGPTにも聞いたんだが、カラムが１０は「知らない」と言われた。

・・ということは、まだWEBに蔓延している情報ではないのだということで公開

以下の内容だとp10まで出さないが、Format-Tableに-property *つけるとp11までいく
```powershell:test.ps1
[pscustomobject] @{
  'p1'=1;
  'p2'=1;
  'p3'=1;
  'p4'=1;
  'p5'=1;
  'p6'=1;
  'p7'=1;
  'p8'=1;
  'p9'=1;
  'p10'=1;
  'p11'=1;
  } | Format-Table
  ```

  けっこうググったが確かにあまり情報はなかったなあ
LambdaのGETリクエストとNode.js Expressでのレスポンス


LambdaでのGETリクエストの自分用の覚書です。

LamdaでGETリクエストをすると、Node.jsで書かれたサーバーから「hello world」という文字を返すということをやります。

<br>

### レスポンス側　（Node.js）

フレームワークはexpressを使用

``` index.js
const express = require('express');
const app = express();

app.get('/hello', function(req, res) {

    res.send('hello world')
    
    }
)

```

### リクエスト側 （Python）

``` lambda_function.py
import urllib.request

def lambda_handler(event, context):
    hello = get_hello()
    print(hello)

def get_hello():
    request = urllib.request.Request(
        '<URL>',
        method='GET',
        headers={'User-Agent': 'Mozilla/5.0'}
    )
    response = urllib.request.urlopen(request, timeout=30)    
    data = response.read().decode('utf-8')
    
    return data
    
```
<br>

これで、Lambdaを実行すると

「hello world」という文字列を取得できます。