OmniAICreator/Qiita-1.07M huggingface dataset:
ヒアドキュメント内で変数を展開しない方法

以下のEOTを" or ' でくくると展開されない
```
#!/bin/bash

MSG1="HELLO WORLD.(test1)"
MSG2="HELLO WORLD.(test2)"
MSG3="HELLO WORLD.(test3)"

echo "here document test 1."
cat << EOT # $MSG1展開される
<HTML>
<BODY>
$MSG1
</BODY>
</HTML>
EOT

echo "here document test 2."
cat << 'EOT' # $MSG2展開されない
<html>
<body>
$MSG2
</body>
</html>
EOT

echo "here document test 3."
cat << "EOT" # $MSG3展開されない
<html>
<body>
$MSG3
</body>
</html>
EOT
```

# 参考
* [ヒアドキュメント内の変数を展開しない方法](https://linux.just4fun.biz/?%E9%80%86%E5%BC%95%E3%81%8D%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88/%E3%83%92%E3%82%A2%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88%E5%86%85%E3%81%AE%E5%A4%89%E6%95%B0%E3%82%92%E5%B1%95%E9%96%8B%E3%81%97%E3%81%AA%E3%81%84%E6%96%B9%E6%B3%95#p99bb83b)
【XD】便利なショートカットキー


AdobeのXDショートカットキーを紹介します。
Adobe製品で共通して使えるものもあるので、是非覚えていただきたいショートカットキーとなります！
## 目次
* [ツールの切り替えショートカットキー](#ツールの切り替えショートカットキー)
* [基本的な編集時のショートカットキー](#基本的な編集時のショートカットキー)
* [レイヤー操作時のショートカットキー](#レイヤー操作時のショートカットキー)
* [ズームモードのショートカットキー](#ズームモードのショートカットキー)
* [フォントサイズのショートカットキー](#フォントサイズのショートカットキー)


## ツールの切り替えショートカットキー
| ツール |  ショートカットキー |  
|:-----------|------------:|
| 選択   　 |V    | 
| 四角   　 |  R  |
| 楕円形    |  E  | 
| 線     　　|  L  | 
| ペン       |  P  | 
| テキスト    |  T   | 
| アートボード    | A  | 
| ズームモードに切り替え    | Z  | 


## 基本的な編集時のショートカットキー
| 内容 | Mac  | Windows| 
|:-----------|------------:|------------:|
| コピー   　 |command + C|ctrl + C|
| カット   　 |command + X|ctrl + X|
| ペースト    | command + V|ctrl + V|
| 取り消し   | command + Z|command + Z |
| やり直し    | command + Shift + Z |ctrl + Shift + Z |
| 複製    | command + D|ctrl + D|
| 削除    | Delete | Delete|
| すべて選択    | command + A  | ctrl + A|
| すべて選択解除    | command + Shift + A  | ctrl + Shift ＋ A|

## レイヤー操作時のショートカットキー
| 内容 | Mac  | Windows| 
|:-----------|------------:|------------:|
| レイヤーのロック / ロック解除   | command + ＋ | cctrl + L|
|レイヤーの表示 / 非表示    | command + ;| ctrl + ;|
|最前面へ  | command + Shift + ]| ctrl + Shift + ]|
|前面  | command + ]| ctrl + ]|
|背面へ  |command + [|ctrl+ [|
|最背面へ  |command + Shift + [|ctrl + Shift + [|

## ズームモードのショートカットキー
| 内容 | Mac  | Windows| 
|:-----------|------------:|------------:|
| ズームイン    | command + L | ctrl + ＋|
| ズームアウト    | command + – | ctrl + –|

## フォントサイズのショートカットキー
| 内容 | Mac  | Windows| 
|:-----------|------------:|------------:|
| フォントサイズを上げる   | Command + Shift + >| Ctrl + Shift + >|
| フォントサイズを下げる  | Command + Shift + > | Ctrl + Shift + >|


---------------------------------------
以上、XDで使えるショートカットキーとなります。
illustratorやphotoshopでも共通として使えるものもあるので、覚えると作業効率が上がると思います！
【AWS】S3 暗号化方式まとめ


| 暗号化方式 | 特徴 | 
| --- | --- | 
| SSE-S3 | ・S3標準の方式<br>・暗号化キーをS3が <font color="darkorange">**自動管理**</font> してくれるので、ローテーションも気にする必要がない<br>・運用コストを最大限に抑えられる | 
| SSE-KMS | ・KMSを利用してユーザー側で暗号化キーを管理する<br>・KMSに設定されている暗号化キーを使って暗号化<br>・コンプライアンス等で、キーの管理を自分たちで行う必要がある場合に使用 | 
| SSE-C | ・ユーザー自身が指定した暗号化キーで暗号化<br>・管理が煩雑になるデメリット | 
| クライアントサイド暗号化(CSE) | ・S3への送信前に <font color="darkorange">**クライアント側で暗号化**</font><br>・KMS等で暗号化キーを管理 | 

※SSE = Server Side Encryption
よく使っているExcelマクロ

ツールをインストールできない場合に使っているマクロです。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/732af2c0-7fba-4260-ee09-563f64220fab.png)

``` vb
Option Explicit

Public Sub myRename()
    Dim Row As Long
    Dim CntBlankRow As Long '空白行の数
    Dim CntReplace As Long 'リネームした回数
    Dim CntError As Long 'エラーの回数（※エラーとは：リネーム前のファイルが存在していない、リネーム後のファイルが既に存在している）
    
    Do
        Cells(1 + Row, 1).Interior.ColorIndex = 0 '塗りつぶしなし
        Cells(1 + Row, 2).Interior.ColorIndex = 0 '塗りつぶしなし
        
        If Cells(1 + Row, 1).Value <> "" And Cells(1 + Row, 2).Value <> "" Then
            CntBlankRow = 0
            
            If Dir(Cells(1 + Row, 1).Value) = "" Then 'リネーム前のファイルが存在していない
                Cells(1 + Row, 1).Interior.ColorIndex = 3 '赤
                CntError = CntError + 1
            ElseIf Dir(Cells(1 + Row, 2).Value) <> "" Then 'リネーム後のファイルが既に存在している
                Cells(1 + Row, 2).Interior.ColorIndex = 3 '赤
                CntError = CntError + 1
            Else
                Name Cells(1 + Row, 1).Value As Cells(1 + Row, 2).Value 'リネーム処理
                CntReplace = CntReplace + 1 'リネームした回数を数える
            End If
        Else
            CntBlankRow = CntBlankRow + 1 '空白行を数える
        End If
        
        Row = Row + 1 '1行下に移動
        
        If CntBlankRow > 10 Or Row >= Rows.Count Then   '空白行が連続した場合、もしくは、シートの最下端に到達した場合は、ループから抜ける（※空白行の既定値：10回）
            Exit Do
        End If
    Loop
    
    MsgBox CntReplace & "件をリネームしました。", vbInformation
    
    If CntError <> 0 Then
        MsgBox CntError & "件のエラーが発生しています。", vbExclamation
    End If
End Sub

```
【Windows】SQLiteのインストールからテーブル作成まで

# SQLiteの環境構築

## SQLiteをインストール  
- 参考記事
  - https://sukkiri.jp/technologies/databases/sqlite/sqlite_install.html
  - https://www.javadrive.jp/sqlite/install/index1.html

- コマンドラインツールを [SQLite公式サイト](https://www.sqlite.org/download.html) からダウンロード

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711955/ab17089e-df6a-bf42-13a9-189dd8057900.png)


- ダウンロードファイルの配置  
  ダウンロードしたzipファイルを展開後、今回は「C:\pg\sqlite\sqlite-tools-win32-x86-3420000」といったディレクトリ構成にしてsqlite実行ファイルを格納

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711955/46c70ced-ea29-fc16-52a7-6aada29fde2b.png)

## データベースとテーブルの作成
- データベースの作成
  - コマンドプロンプトから`cd`コマンドでダウンロードしたファイルの階層へ行き、 `sqlite3 データベース名(任意)` を実行して、SQLiteにデータベースを作成する

```
# sqlite実行ファイルが存在するフォルダに移動
cd C:\pg\sqlite\sqlite-tools-win32-x86-3420000

# データベースの作成(存在する場合は実行)
sqlite3 construct.db
```

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711955/d0d99114-6537-6ca3-647c-eaaf86a13dcf.png)

- dbファイルが生成されていることを確認

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711955/85ce2bcf-7bed-d99b-f4c7-570f6a319c59.png)

- テーブルの作成
  - 以下のCREATE文を実行してテーブルを作成
```
# テーブルの作成
CREATE TABLE user_tb (
  id integer primary key, 
  name varchar(10)
);
```

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711955/27dcfcd9-0ed3-5a83-928a-536eeeaf6822.png)

- `.schema user_tb`コマンドを実行して作成したテーブル情報を確認

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711955/f15d1b2d-5d8b-25c7-e39d-d7a2950ad960.png)
CloudFront で インデックスドキュメント を実現 (Lambda@Edge Python版)

# Motivation

CloudFront + S3 でインデックスドキュメント動作を実現する。Lambda@Edge ではランタイムのサポート期間の長いPythonを使いたい。

# 背景

CloudFront + S3 で Static Website hosting を使わない場合、インデックスドキュメントの動作を行うためには CloudFront Function または Lambda@Edge での対応が必要になる。

Pythonで実装したいが Lambda@Edge - Python 版実装の情報は少ない。

インデックスドキュメントの動作は CloudFront Functions でも実現可能だが、アプリケーションの構成上、 Lambda@Edge を使いたいこともある。

静的ウェブサイトホスティングはS3バケットをpublic accessにする必要があり、最近のセキュリティ施策で有効にすることの多い Block Public Access と相性が悪い。


# 実装

appy.py:

```python
def lambda_handler(event, context):
    request = event["Records"][0]["cf"]["request"]
    old_uri: str = request["uri"]
    if old_uri.endswith("/"):
        new_uri = old_uri + "index.html"
    else:
        new_uri = old_uri
    request["uri"] = new_uri
    return request
```

https://github.com/umorigu/cloudfront_lambda_edge_index_document_python

* CloudFront の S3オリジンに対し オリジンリクエスト にこのLambda関数を設定する。
* `event` オブジェクトに対して `event["Records"][0]["cf"]["request"]` をreturnするのがデフォルトの動作と同じになる。
* `event["Records"][0]["cf"]["request"]["uri"]` を変更することで、リクエストに対し、S3オブジェクトを変国することができる。

# 参考

* https://dev.classmethod.jp/articles/directory-indexes-in-s3-origin-backed-cloudfront/
    * できた！S3 オリジンへの直接アクセス制限と、インデックスドキュメント機能を共存させる方法
* https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/example-function-add-index.html
    * index.html を追加してファイル名を含まない URL をリクエストする
* https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/lambda-generating-http-responses-in-requests.html
    * リクエストトリガーでの HTTP レスポンスの生成
* https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/lambda-event-structure.html
    * Lambda@Edge イベント構造
【React】list要素のkeyにindexを指定してしまい痛い目を見た話


list要素のkeyにうっかりindexを指定してしまい、実務でハマったので教訓をまとめておきます。
「listのkeyなんてレンダリングを最適化してくれるだけでしょ？」と甘く考えていたところ、痛い目に会いました。

## 結論(今回の教訓)
#### list要素の"key"にはデータの主キー等の"ユニーク"かつ"不変"な値を設定すること！

## 参考：なぜ"ユニーク"かつ"不変"な値を設定する必要があるのか
#### reactがkeyの値で同一コンポーネントかどうかを識別しているため。

いろいろな方がまとめられているため、詳細はそちらを確認ください。
簡単に言うと、reactはkeyの値を元に要素の追加、変更、削除を追尾するため、keyにユニークな値を設定することで不要な再レンダリングを防ぐことができます。
また意図せずにindexを指定すると、↓のように思わぬバグに遭遇する可能性があります。


## 実務でハマった内容

**バグが発生した機能**
受注した契約情報の一覧ページ

<詳細>
・1ページあたり10件の契約を表示。
・各行に編集ボタンがある。
・編集ボタンを押下すると、その契約の受注金額を一覧上で編集できる。（ReactHookFormにより編集を実現）

かなり雑ですが、↓こんな感じのイメージです。
![cost_edit_table1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2453728/7090c3f5-c095-b4e7-f4d0-cdeef243aa22.png)

「料金編集」を押すと、その行の料金が一覧上で編集できるようになります。
![cost_edit_table2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2453728/333b12c9-1770-46c3-f3e9-da5a3f823e9f.png)



**バグの概要**
**2頁目1行目**の契約の編集ボタンを押下すると、**1頁目1行目**の契約の金額が表示される。

**原因**
list要素の`key`に配列の`index`を指定していたため、2頁目1行目（`key=1`）が1頁目1行目(同じく`key=1`)を参照していた。

表示中の頁が何頁目であれ配列のindexは常に1~10。
そのため`key`に`index`を指定すると、**1頁目1行目、2頁目1行目共にkey=1となる。**
1頁目の表示時には、1行目の金額編集フォーム(RHFのdefaultValues)に1頁目1行目の契約の金額が正しく紐づけられる。
しかし2頁目に切り替えても、1行目は`key=1`であるためreactから既存の要素と認識されてしまい、要素の新規作成(defaultValuesの設定)が行われず、1頁目1行目の金額を参照するままとなってしまった。


**対応内容**
`key`に契約情報の主キーを設定。
これによりページ切り替え時に各行が新規追加の要素として認識され、フォーム(defaultValues)に対応する契約の金額が正しく設定されるようになった。
【Docker】マウントについて

## マウントの種類について
マウントには以下の４つがあります。
- バインドマウント
- ボリューム
- tmpfsマウント
- 名前付きパイプ

中でもよく使用するのはバインドマウントとボリュームだと思います。

### バインドマウント
バインドマウントは、ホスト側のディレクトリやファイルがコンテナにマウントされます。
マウント時にホスト側の情報がそのまま反映され、マウント後にコンテナ内で変更があればホスト側に反映されます。

`docker-compose.yml`では以下のように記述することで設定できます。

```docker-compose.yml
version: '3.9'
services:
  app:
    build: .
# 以下バインドマウントのための記述
    volumes:
      - .:/myapp
```

上記のように記述することでホスト側の`docker-compose.yml`の配置されているディレクトリ以下のディレクトリやファイルがコンテナにマウントされます。

### ボリューム
ボリュームはDockerによって管理されてます。
ボリュームはバーチャルマシン上の/var/lib/docker/volumes/ボリューム名/_dataに保存されます。
よって、基本的にはホストマシンから参照することはできません。
ホスト側に同名のフォルダやファイルが存在していてもコンテナ側には変更が反映されません。

Dockerによって管理されているため、`docker volume ls`で一覧を表示できます。
また、`docker volume rm ボリューム名`で削除もできます。

ボリュームには匿名ボリュームと名前付きボリュームの２つがあります。
違いは任意のボリューム名を設定するかしないかです。
`docker-compose.yml`ではそれぞれ以下のように記述することで設定できます。
- 匿名ボリューム
```docker-compose.yml
version: '3.9'
services:
  app:
    build: .
# 以下匿名ボリュームのための記述
    volumes:
      - /myapp/node_modules
```

- 名前付きボリューム
```docker-compose.yml
version: '3.9'
services:
  app:
    build: .
# 以下名前付きボリュームのための記述
    volumes:
      - node_modules:/myapp/node_modules
volumes:
  mode_modules:
```

### ２つを同時に使った際の優先順位
バインドマウントとボリュームを同時に設定した際にはボリュームが優先されます。
例えば`docker-compose.yml`を以下のように記述します。

```docker-compose.yml
version: '3.9'
services:
  app:
    build: .
    volumes:
      - .:/myapp
      - node_modules:/myapp/node_modules
volumes:
  mode_modules:
```

名前付きボリュームの方が優先されるため、`node_modules`はバインドマウントではなく、ボリュームで管理されます。
【Azure】リソースを作成するためのツール

Azureではリソース(VM,Resource groupなど)を作成するためのツールが複数あります。今回は、それぞれのツールの違い利点を備忘録としてまとめます。

<br>


<h1>ツール比較</h1>

<ul>
<li>AzurePortal…すべてのリソース構築、管理監視できる。GUIベース</li>
<li>Azure Cloud Shell…ローカルコンピューターに依存することなく、クラウドならではの操作可能。</li>
<ul>
    <li>Bash…Linuxユーザー向け。</li>
    <li>Power Shell…Windowsユーザー向けAzurePortal>Azure Cloud Shell　から操作の方法とローカルにインストールの方法がある。</li>
</ul>
<li>AzureCLI…ローカル(Windows,Linux,macOs)のターミナル、コマンドプロンプトを介して実行可能。Azure Cloud Shell を介してブラウザーから使用することもできる。</li>
</ul>
【JavaScript】プリミティブとオブジェクトとは？

こんにちは！
js基礎学習第2回は「プリミティブとオブジェクト」について学んでいきます。
なんとなくわかるけれど言葉で表現するとなると、、うーん・・・というレベルです🐥
（そもそも言語化がとても苦手）

※私が使用する言語（JavaScript）に特化した内容となっています！
   　他の言語では違う点があるかもしれませんが、ご了承ください、、

ちなみに前回はこちら👇

https://qiita.com/sakuc47/items/f00032201c10793e5ff6

## ▼これを理解するメリット
- メモリ効率
    - 適切なデータ型選を選ぶことができ、、コンピュータのメモリを節約し効率的なプログラムを作成できるようになる
- 正確な比較ができ、コードの品質が上がる
    - データ型の違いを理解することで、データの操作や比較が正確に行え、予期しない結果を避けることができる
- オブジェクト指向プログラミングの理解
    - オブジェクト理解は、コードを整理し、再利用可能な部品を作成するオブジェクト指向プログラミングの理解につながる

## ▼データ型（Data Type）とは
データ型は、プログラムで扱うデータの種類や性質を定義するものです。
どのようにメモリ上に格納され、操作されるかを示します。プリミティブ型とオブジェクト型は、その基本的な分類を表しています。

## ▼プリミティブ型 (Primitive Types)
基本的なデータ型であり、単純な値を表します。これらは単純な値であり、それぞれが一つのデータを表します。
JavaScriptには以下のプリミティブなデータ型があります。
|データ型  |概要  |例  |
|---|---|---|
|Number  |整数や小数点数を含むすべての**数値**を表します。  |`42`, `3.14` など|
|String  |テキストを表現します。シングルまたはダブルクォートで囲まれた**文字列**です。  |`'Hello!'`, `"apple"` など  |
|Boolean  |**真偽値**と呼ばれます。true（真） / false（偽）で表し、条件式や論理演算に使用されます。  |`true`, `false`  |
|Symbol |**シンボル**を表します。`ES2015`から導入されました。  |let Sym1 = Symbol("Sym");|
|null  |何も値がないことを表します。変数が存在するが値がない場合に使用されます。 |
|undefined |値が代入されていないことを表します。変数がまだ初期化されていない場合に使用されます。  |

:::note warn 
何もない空の状態を作る時は明示的にundefinedを変数に代入するのではなく、一般的にnullを代入するために使うことが推奨されています。
:::


## ▼オブジェクト型 (Object Type)
オブジェクトは、複数の値や情報を組み合わせて表現するためのデータ型です。プロパティと呼ばれるキーと値のペアを持ち、様々なデータや機能をまとめることができます。
さまざまな型のデータを複数格納できるのが特徴です。
JavaScriptでは、オブジェクトは中括弧 {} で表現されます。

|データ型  |概要  |例  |
|---|---|---|
|Object  |	キーとバリューから成るデータの集まりを表します。オブジェクトと呼ばれます。  |`const obj = {name: 'Bob'}` など|


## ▼最後に
今まではこれはプリミティブかオブジェクトか、無意識で判断していたような気がします:frowning2:
きちんと理解することで、難しいコードを書く時にバグを防いだり、運用性の高い実装につながりそうです！複数人で作業する時にも役立ちそう。
意識していきます💪

## ▼参考

https://zenn.dev/doxper/articles/7082ffe429d5ee

https://qiita.com/makotoo2/items/9566cebf205ef8b42505

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

https://www.javadrive.jp/javascript/ini/index6.html#section2
【SwiftUI】迷路を描画する方法

## やりたいこと
以下のような迷路を描画する方法を紹介します。
あくまで一例です。
<img width=250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658262/6927288c-c927-8016-60a1-2caf76d66809.png">

## 迷路データの定義
mazeData という2次元の配列を定義します。
`1`は壁を、`0`は通路を示します。
```swift:ContentView.swift
    let mazeData: [[Int]] = [
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1],
        [1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1],
        [1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1],
        [1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1],
        [1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1],
        [1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1],
        [1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1],
        [1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1],
        [1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1],
        [1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1],
        [1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1],
        [1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1],
        [1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1],
        [1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1],
        [1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1],
        [1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1],
        [1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1],
        [1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1],
        [1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1],
        [1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1],
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
    ]
```

## UI作成
```swift:ContentView.swift
    var body: some View {
        VStack(spacing: 0) {
            ForEach(0..<mazeData.count, id: \.self) { rowIndex in
                HStack(spacing: 0) {
                    ForEach(0..<self.mazeData[rowIndex].count, id: \.self) { colIndex in
                        Rectangle()
                            .fill(self.mazeData[rowIndex][colIndex] == 1 ? Color.black : Color.white)
                            .frame(width: 20, height: 20)
                    }
                }
            }
        }
    }

```
### 解説
このコードは、小さな四角形を組み合わせて大きな迷路を作るための絵を描いています。

#### ①VStack:
内部のビューを垂直に配置します（迷路の行）。

#### ②最初のForEach:
```swift:
ForEach(0..<mazeData.count, id: \.self) { rowIndex in ... }
```
このForEachはmazeDataの各行に対して反復処理を行っています。
`rowIndex`は現在の行のインデックスを表しています。

#### ③HStack:
内部のビューを水平に配置します。

#### ④2つ目のForEach:
```swift:
ForEach(0..<self.mazeData[rowIndex].count, id: \.self) { colIndex in ... }
```
現在の行内の各セルに対して反復処理を行っています。
`colIndex`は現在のセルのインデックス（列のインデックス）を表しています。

#### ⑤四角形のビュー：
```swift:
Rectangle()
  .fill(self.mazeData[rowIndex][colIndex] == 1 ? Color.black : Color.white)
  .frame(width: 20, height: 20)
```
`Rectangle()`は四角形のビューを生成します。
`.fill`でmazeDataの現在のセルの値に基づいて四角形の色を決定しています。
値が1の場合、四角形は黒で塗りつぶされ、そうでない場合は白で塗りつぶされます。



小さな四角形の組み合わせで迷路の絵を描くことが出来ました！
Flask で、templates と static 以下のファイルをキャッシュされないようにする

## 背景
Python + Flask で簡単な Web アプリを開発していたのですが、
* templates 以下の html ファイルを更新しても、プログラムを再起動しないと反映されない
* static 以下の css やスクリプトも同様

となってしまい、開発効率がすこぶる悪かったので、なんとかしたいのが発端でした。
## 環境
* macOS Ventura
* Python 3.11.4
* Flask==2.3.2

## 調査
static 以下のファイルについてはこちらの方法でうまく行きました。:pray:

https://qiita.com/kenmaro/items/14f893ec2e2e30a1cf85

```
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0
```
ところが templates 以下はまた別の設定が必要なようです。色々探した結果、見つけたのはこちら。
```
app.config['TEMPLATES_AUTO_RELOAD'] = True
```

## 結果
シンプルな app.py を例にするとこんな感じです。
```python:app.py
from flask import Flask, render_template

PORT = 5000

app = Flask(__name__)
app.config['TEMPLATES_AUTO_RELOAD'] = True
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == "__main__":
    app.run(port=PORT)
```
無事、Flask を動かしつつ、html | css | script を修正してはチェックの繰り返しが効率よくできるようになりました。
## 参考
* [設定の処理の仕方（Configuration Handling）](https://msiz07-flask-docs-ja.readthedocs.io/ja/latest/config.html)

:point_up:もしかしたら、開発中はちゃんと DEBUG モードを有効しなさいよ、と言うことかもしれません。
ListとIteratorのメモ

個人の備忘録メモ（リストで複数行読み込んだ際の次行ブレイク判定のやり方）
※@Slf4jアノテーションが付与されている前提

```java
List<String[]> tmpList = new ArrayList<String[]>();

tmpList.add(new String[]{"test01-01", "test01-02"});
tmpList.add(new String[]{"test01-01", "test01-02"});
tmpList.add(new String[]{"test02-01", "test02-02"});
tmpList.add(new String[]{"test02-01", "test02-02"});

for (int i = 0; i < tmpList.size(); i++) {
    String[] data1 = tmpList.get(i);
    
    if (i < tmpList.size() - 1) {
        String[] data2 = tmpList.get(i + 1);
        if (!data1.equals(data2)) {
            log.info("break list");
            break;
        }
    }
}

Iterator<String[]> tmpIterator = tmpList.iterator();

while (tmpIterator.hasNext()) {
    String[] data1 = tmpIterator.next();
    
    if (data1 != null) {
        if (tmpIterator.hasNext()) {
            String[] data2 = tmpIterator.next();
            
            if (data2 != null) {
                if (!data1.equals(data2)) {
                    log.info("break iterator");
                    break;
                }
            }
        }
    }
}
```
Splideのアクセシビリティの意識が高くてついていけなかったのでゆっくり咀嚼する

Splideは「アクセシビリティに配慮した軽量・高機能スライダー」と謳っています。
使ってみると、その謳い文句に劣らず、確かにアクセシビリティに非常に気をつかわれていることが分かります。

このSplideの公式ドキュメントにはアクセシビリティに関するページが単独で存在し、（当たり前ですが）そもそもWebアクセシビリティに明るくないと半分も理解できません。少なくとも私は完全に理解した状態でした。

そこで、W3Cのドキュメント等も踏まえカルーセルのアクセシビリティについて理解を深めつつ、Splideについても噛み砕いていきたいと思います。（かなり時間がかかった）

カルーセルのW3Cデザインパターンを確認
バージョン4から、W3CのCarousel Design Patternに準拠した上で、スクリーンリーダーが動的にコンテンツを読み上げられるようライブリージョンも導入しました。

まずは、Splideが準拠しているという、W3Cのカルーセルのデザインパターンを確認していきます。
今後の話は、これを前提に進められていきますので、ここが理解できないことには何も始まりません。

WAI-ARIAについても記載がありますが、こちらのセクションにはまとめず、Splideの説明に組み込みながら見ていきます。

“十分な”カルーセル制御に必要なもの
カルーセルに必要な機能は以下の通りであると示されています。

前と次のスライドを表示するためのボタン
オプションとして、表示する特定のスライドを選択するためのコントロール、またはコントロールのグループ
カルーセルを自動スクロールさせる場合
回転を停止・再開するためのボタンがある
キーボードのフォーカスがカルーセルに入ると回転が停止する
マウスがカルーセルの上に乗っている間は回転を停止する
キーボードインタラクション
自動スクロールさせる場合
カルーセル内の要素にキーボードのフォーカスが当たった時は、スライドの自動スクロールは停止させます。
ユーザが自動スクロールの再生・停止ボタンを押さない限り、回転は再開されません。

TabキーとShift + Tab
通常のタブ順序によって指定されたカルーセルのインタラクティブ要素にフォーカスを移動します。
Tabキーのためのスクリプトは必要ありません。

ボタン要素
ボタン要素は、ボタンパターンで定義されたキーボードインタラクションを実装します。

自動スクロールの開始・停止、スライドを次・前へ動かすボタンは、何度でも繰り返し押せるようにします。

自動スクロールの開始・停止コントロール
自動スクロールコントロールは、カルーセル内のタブ順序中で最初の要素にします。
回転するコンテンツの前に置くことが重要です。

ページネーションをタブ要素で使う場合
ここで言うページネーションは、カルーセルの下についてるドットなどで表示される、任意のスライドに移動できるコントロールのことです。

これをタブ要素で使う場合は、<a title="Media Web Terpercaya" href="https://timelines.id/"><b>Media Web Terpercaya</b></a> Tabsパターンで定義されたキーボードインタラクションを実装します。


share
Kotlinいろいろまとめ

# 数列から一番大きい数字を求める
```kotlin
fun main() {
    val numbers = listOf(10, 5, 25, 3, 15)
    val maxNumber = numbers.maxOrNull()

    println(maxNumber) // 25
}
```
逆に、数列から最小の数を求めるには minOrNull（またはKotlin 1.5以降ではminが使用されます）という拡張関数を使用します。

# 特定の数字が文字列内で何回含まれるかを数える
```kotlin
fun main() {
    val text = "123112341"
    val targetDigit = '1'
    val count = text.count { it == targetDigit }

    println(count) // 4
}
```

# リストや配列の一部を抽出する
```kotlin
val list = listOf(1, 2, 3, 4, 5)
val sublist = list.subList(1, 4) // インデックス1から3までの要素を含む部分リスト
// sublist: [2, 3, 4]
```

# 文字列の一部を切り出す
```kotlin
val str = "Hello, World!"
val substr = str.substring(7, 12) // インデックス7から11までの文字列を含む部分文字列
// substr: "World"
```

# 文字列の中からN番目までの文字を切り出す
```kotlin
fun main() {
    val s = "Hello, World!"
    val n = 5
    val substring = s.substring(0, n) // 0からn-1までの範囲の文字列を切り出す

    println(substring) // "Hello"
}
```

# リスト内の数列をすべて2倍にして出力する
```kotlin
fun main() {
    val numbers = readLine()!!.split(" ").map { it.toInt() }  // 数列を読み込んでリストに変換

    val doubledNumbers = numbers.map { it * 2 }  // 数列の各要素を2倍する

    for (num in doubledNumbers) {
        println(num)  // 2倍にした数列を出力
    }
}
```

# 逆順に文字列を出力する
```kotlin
fun main() {
    val input = readLine()
    if (input != null) {
        val reversed = input.reversed()
        println(reversed)
    }
}
```
RenderでPythonバージョンを指定する方法

# Renderとは？
- PaaSとしてPythonなどを実行する環境
- だいぶ前ですが[Herokuが有料プラン](https://forest.watch.impress.co.jp/docs/news/1435422.html)になったことから使用するようになった人もいいかと思います

# 設定方法

- Settings > Environment > Environment Variables
    - Key: PYTHON_VERSION
    - Value: [任意のバージョン]

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187750/c54f0643-f0ba-b86f-b7e3-c1bb3d3cdc1e.png)

- 例えば、RenderでDeployを実行した際に、以下のようなエラーで必要なパッケージが取得できない場合はPythonのバージョンをローカルに合わせて設定することで解決することがあります。

```
WARNING: You are using pip version 20.1.1; however, version 23.1.2 is available
```
【執筆中】Kotlin + SpringBootでCSV出力APIを実装する

# 環境

- OS: Windows11
- Kotlin: 1.8
- SpringBoot: 3.1.2

# 実装例

```kotlin:FileDownloadController.kt

package com.example.demo.presentation.controller

import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody
import java.io.OutputStream
import java.nio.charset.StandardCharsets

@RestController
class FileDownloadController {

    @GetMapping("/api/customers/export")
    fun get(): ResponseEntity<StreamingResponseBody>
    {
        val data = (1..100000).map {
            "$it,user_$it"
        }
        val responseBody = csvData(data)
        return toResponseEntity(responseBody)
    }

    private fun toResponseEntity(csvData: StreamingResponseBody): ResponseEntity<StreamingResponseBody> {
        return ResponseEntity.ok()
                .header("Content-Type", "text/csv")
                .header("Content-Disposition", "attachment")
                .header("X-File-Name", "sample.csv")
                .body(csvData)
    }

    private fun csvData(data: List<String>): StreamingResponseBody {
        return StreamingResponseBody {outputStream: OutputStream ->
            data.forEach{ it ->
                outputStream.write((it + "\n").toByteArray(StandardCharsets.UTF_8))
            }
        }
    }
```

各メソッドについて別途記述予定
AtCoder過去問: Python～第一回アルゴリズム実技検定（随時更新）

AtCoderの過去問解いていきます。
競技プログラミングの練習というよりは、Pythonのコーディング学習の一環として。
できる限り無駄のないコーディングになるよう、一問ずつ試行錯誤しながら、
随時更新していきます。

[第一回 アルゴリズム実技検定 過去問](https://atcoder.jp/contests/past201912-open)


# A - 2倍チェック
[問題リンク](https://atcoder.jp/contests/past201912-open/tasks/past201912_a)

    S = input()
    if S.isdecimal():
        print(int(S)*2)
    else:
        print("error")

Sが数字か、小文字かという可能性のみなのでこれでよいかなと。
3桁以外が来るなら len() でチェックが必要になりますが。
0始まりもこれで問題なし。

# B - 増減管理

[問題リンク](https://atcoder.jp/contests/past201912-open/tasks/past201912_b)

### 解法1
実行時間：197 ms
メモリ：13836 KB

    N = int(input())
    A_list = [int(input()) for _ in range(N)]
    prev_a = A_list[0]
    for a in A_list[1:]:
        if a == prev_a:
            print("stay")
        elif a < prev_a:
            print("down %d" % (prev_a - a))
        else:
            print("up %d" % (a - prev_a))
        prev_a = a

### 解法2
実行時間：233 ms
メモリ：12900 KB

    N = int(input())
    A_list = [int(input()) for _ in range(N)]
    for i in range(len(A_list)-1):
        if A_list[i] == A_list[i+1]:
            print("stay")
        elif A_list[i] > A_list[i+1]:
            print("down %d" % (A_list[i] - A_list[i+1]))
        else:
            print("up %d" % (A_list[i+1] - A_list[i]))

わずかに解法1の方が速かった。
わかりやすさでも解法1のほうが個人的にはいいのかなとは思ってます。


# C - ３番目

[問題リンク](https://atcoder.jp/contests/past201912-open/tasks/past201912_c)

    l = list(map(int, input().split(' ')))
    l.sort()
    print(l[-3])

mapという関数を初めて知りました。便利。

# D - 重複検査

[問題リンク](https://atcoder.jp/contests/past201912-open/tasks/past201912_d)

問題文、制約からわかるのは
・元の整数列は　1, 2, 3, ... , N　のように連続した整数列
・1～Nの範囲のうち、書き換えられた整数に存在しない値が x
・書き換えられた整数列のうち、重複した（複数存在する）値が y

このように整理したうえで下記。

    N = int(input())
    A_list = [int(input()) for _ in range(N)]

    x = 0
    y = 0
    for i in range(1, N+1):
        if not i in A_list:
            x = i
        if A_list.count(i) > 1:
            y = i
        if x != 0 and y != 0:
            break

    if x == 0 and y == 0:
        print('Correct')
    else:
        print("%d %d" % (y, x))

ところがこれで提出したら実行時間制限超過してしまった。。
現在改善調査中です。

    N = int(input())
    A_list = [int(input()) for _ in range(N)]

    A_list_union = set(A_list)
    if len(A_list_union) == N:
    	print("Correct")
    	exit()

    A_dict = {}
    for i in range(N):
        if A_list[i] in A_dict:
            A_dict[A_list[i]] += 1
        else:
        	A_dict[A_list[i]] = 1

    x = 0
    y = 0

    for i in range(1, N+1):
        if not i in A_list_union:
        	x = i
        	continue
        if A_dict[i] > 1:
        	y = i
        if x != 0 and y != 0:
        	break

    print("%d %d" % (y, x))

上記のようにしたところ実行時間クリアしました。
countがかなり時間かかるみたいです。
Googleカレンダーから、名称に特定の文字を含むスケジュールだけをGoogleスプレッドシートに自動転記する

# 1.目的と課題
* **スケジュールの数や人数が多い組織で、
すべての予定をGoogleカレンダーから取得すると、
転記先のGoogleスプレッドシートの動作が重くなる**

「営業メンバー全員の当日以後30日までの商談スケジュールを、
Googleスプレッドシート（以下スプシ）上で把握したい」
という要望があり、
GASを用いて、Googleカレンダーから
各メンバーのスケジュールを自動取得して、
スプシに転記するようなシステムを作ることになりました。

しかし、筆者の所属先は商談の回数が多く、
またMTGなど商談以外のスケジュールや、スケジュールの取得対象となる人数も多いため、
彼らのすべてのスケジュールを取得・転記した場合、
・GASの実行完了までに時間がかかる
・スプシの動作自体も重くなる
など、業務に支障が出ることが分かりました。

# 2.改善策

そこで、「**スケジュール名が特定の条件を満たした場合のみ（商談のスケジュールのみ）、
自動取得してスプシに転記**」というシステムに改良しました。

今回は、取得したスケジュールの先頭1文字が
「◎」の場合のみ取得、という形にしてみました。
（他のスケジュール名と被らなければ、「◎」に限らず任意の文字列で大丈夫です）

# 3.コード作成

```
function calendar() {
  const sp = SpreadsheetApp.getActiveSpreadsheet();
  const startTime = new Date();  //引数省略により現在日付時刻を取得
  const endTime = new Date(Date.parse(startTime) + (30 * 60 * 60 * 24 * 1000));    
　　 // parseで日付を文字列に変換     

  const ash = sp.getSheetByName('スケジュール転記先のシート名');
  const lastRow = ash.getLastRow ();  //シートの最終行取得
  ash.getRange(2,1,lastRow,4).clearContent();  
    //実行前に、A～D列の2行目以降（前回の内容）をクリアして初期化
　　//（1行目は項目名、2行目以降にデータが入っているものと仮定）

  const cal = CalendarApp.getCalendarById('【メールアドレス】'); 
  const event = cal.getEvents(startTime,endTime); 

  let i = 2  //予定転記先シートの行数カウント用の変数
  let j = 0  //カレンダー上のスケジュールの数カウント用の変数
  for (j in event){
    if (event[j].getTitle().substring(0, 1) == "◎"){
      //スケジュール名の先頭1文字が「◎」の場合のみ取得
      ash.getRange(i,1).setValue(event[j].getTitle());         　　　//A列：イベントタイトル
      ash.getRange(i,2).setValue(event[j].getStartTime());     　　　//B列：イベント開始時刻　　
      ash.getRange(i,3).setValue(event[j].getEndTime());       　　　//C列：イベント終了時刻
      ash.getRange(i,4).setValue("=round((rc[-1]-rc[-2])*24)");　　　//D列：所要時間
      i += 1
    }else{  //スケジュール名が条件を満たさない場合、何もせず次の繰り返し処理へ
    }
  }
}
```

if (event[j].getTitle().substring(0, 1) == "◎"){
substringメソッドを使用して、「一番左から数えて1文字目」を取得し、
「◎」である場合のみ、スケジュールを取得して各要素をA～D列に記載、という内容にしています。


# 4.ルールの周知徹底

今回はコード作成自体は簡単なものでしたが、
むしろ、**多忙な営業メンバーに忘れずにスケジュール名の先頭を「◎」にしてもらう、
ルールを徹底してもらうためにはどうするか**、という点の方がポイントになるように思います。

筆者の場合は、
・予定を取得・表示したスプシを営業メンバー自身が閲覧する場合、
　見出しなど目立つ箇所に、Googleカレンダー上でのスケジュール作成の際のルールを記載する
・GASを用いて上記スプシを検索し、1週間（5営業日）以内に「◎」のある予定が一切入っていない
　営業メンバーに対して、Slack等に自動でメッセージを投稿して警告する
等の対策を実践しています。
【AWS】DynamoDB パフォーマンスチューニング

## スループット低下が原因の場合

#### 一時的な問題の場合
`Auto Scaling` を有効かして、自動的にスケーリングされるようにする。
これにより、テーブルとインデックスを監視して、アプリケーショントラフィックの変化に応じて自動的にスループットが調整されるようになる。
一時的な負荷増加に対して、DynamoDBテーブル処理パフォーマンスの管理が容易になり、アプリケーションの可用性を最大化しつつ、DynamoDBのコストを削減にも繋がる。

#### 恒久的な対応が必要な場合
`DynamoDB Accelerator(DAX)` を有効化することを検討する。
 DAX はインメモリ型のキャッシュ機能で、追加のキャッシュレイヤーによってミリセカンドからマイクロセカンドへの最大 10 倍のパフォーマンス向上が期待できる。
ただし費用が高いので、常時利用に値するかどうか慎重に検討が必要。
Reactでchrome拡張機能を作成 ~サイドパネルを用いて、mermaidに対応させる~

# mermaidの図を表示してくれるchrome拡張機能

## 背景
最近だと、Githubがmermaid記法に対応しました。
ただ、現在でも、mermaid記法に対応していないサービスはいくつかあります。
そのため、どのサービスでもmermaid記法を図で確認できるように、chrome拡張機能を作成しようと思いました。

※ 作った後に気づいたのですが、すでに以下の拡張機能が存在しているようです。
もし、私と同じ悩みをお抱えの方は、以下の拡張機能の使用をご検討ください。

https://chrome.google.com/webstore/detail/mermaid-previewer/oidjnlhbegipkcklbdfnbkikplpghfdl?hl=ja



## 完成図
![chrome-extension-mermaid-3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669831/10c44ae8-d989-dd0a-fdc5-ce89c2ed2a3c.gif)

## 作成コード
https://github.com/shokiogawa/mermaid-chrome-extension-react

### 使用技術
- React
- Typescript
- Webpack
- Sass

### 使用chrome機能
- content_script
- sidepanel
- background
※ content_script → sidepanelへのメッセージパッシングは、content_script → popupと同じやり方でできるよう。

https://kisshi06.com/easy-to-start-chrome-extension-development-message-passing/

## 処理フロー
主に、chromeのcontent_scriptとsidepanelを用いて実現しました。
流れは、以下のよう。
```mermaid
sequenceDiagram
    participant ユーザー
    participant content_script
    participant sidepanel
    ユーザー->>content_script: mermaid記法の文字列を選択
    content_script->>ユーザー: ボタン表示
    ユーザー->>content_script: ボタン押下
    content_script->>sidepanel: 選択文字列を送信
    sidepanel->>sidepanel: mermaid apiでsvgタグ作成
    sidepanel->>ユーザー: 図を表示
```

### サイドパネル(sidepanel)とは？
サイドパネルとは、2022年3月頃に導入された、ブラウザ右上の四角アイコンを押下した際に開かれるパネルのこと。
[Google公式 サイドパネルの説明](https://support.google.com/chrome/answer/13156494?hl=ja)

最近だと、chromeの拡張機能でサイドパネルを使用できるようになったようです。
[chrome.sidePanel](https://developer.chrome.com/docs/extensions/reference/sidePanel/)

## 参考記事
https://zenn.dev/alvinvin/books/chrome_extension

https://kisshi06.com/easy-to-start-chrome-extension-development-message-passing/

https://zenn.dev/tesla/articles/6d17245bc81079

https://developer.chrome.com/docs/extensions/reference/sidePanel/
機械学習の関数まとめ

## 活性化関数
闘値を境に出力が変わる関数。中間層や出力層の値を変換する際に用いる。
活性化関数を用いて変換を行うと様々な値の出力が行えるため、モデルの表現力を増すために用いられる。

## 損失関数
学習時にモデルが出した予測値と、実際の値がどれくらいズレているのかを計算するための関数。
損失関数の値を小さくする方向にモデルを調整する。


## 評価関数
評価時にモデルが出した予測値と、実際の値がどれくらいズレているのかを計算するための関数。
作ったモデルが、どれくらい良いモデルなのかを評価する。




https://zenn.dev/nekoallergy/articles/machinelearning-func
#0018 list in listから指定の行を取り出す方法

## はじめに
- pytorchの勉強中に多次元の行列から指定の次元を一行で取り出しており、この方法を知らなかったため記事とする。
- 状況としては、shape(3,2)の行列から0番目と2番目だけを抽出したい場合などだ。
- list in listでも需要がありそうだと思った。（リスト形式ではできないが...）

## 【pytorch】 list in listから指定の行を取り出す方法
```
a = [[0,1,2], [3,4,5],[6,7,8]] 
a = torch.Tensor(a) 
b = [0,2] 
print(a[b])
>>> tensor([[0., 1., 2.],
           [6., 7., 8.]])
```
## numpyやarrayではできるか
- numpyはpytorchと同じようにできた。
- listはできなかった。リスト内表記やfor文を使えば書ける。

```
# numpy
a = [[0,1,2], [3,4,5],[6,7,8]] 
a = np.array(a) 
b = [0,2] 
print(a[b])
>>> [[0. 1. 2.]
    [6. 7. 8.]]
```

```
# list
a = [[0,1,2], [3,4,5],[6,7,8]] 
b = [0,2] 
print(a[b])
>>> TypeError: list indices must be integers or slices, not list

print([a[j] for j in b])
>>> [[0, 1, 2], [6, 7, 8]]
```

## おわりに
- 多次元行列から指定の行だけ取り出したい場合はありそうなため、使っていきたい。
- listでもlist内表記やfor文を使うよりは、numpyに変換後、a[b]で書いたほうがスッキリ書けると思う。
ISO/IEC JTC1SC22WG14 Documents

C言語規格審議文書のリンク切れを探す作業の記録。　


 ＜この記事は書きかけです。順次追記します。＞
 This article is not completed. I will add some words in order.


Index of /jtc1/sc22/wg14/www
https://www.open-std.org/jtc1/sc22/wg14/www/

C99RationaleV5.10.pdf	2004-02-20 09:13 
https://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf

[TXT]	wg14_document_log.htm	2023-08-16 02:14 
https://www.open-std.org/jtc1/sc22/wg14/www/wg14_document_log.htm


N3149 2023/07/09 Meneide, Working Draft, Post-June Meeting
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3149.zip


 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
This article is an individual impression based on the individual's experience. It has nothing to do with the organization or business to which I currently belong. 

# 文書履歴(document history)
ver. 0.01 初稿　　20230820

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

####  Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.

 AUTOSAR, Vehicle, 小川メソッド, DoCAP, English
#0017 numpy.reshape(-1, ...) の使い方

## はじめに
- 最近画像処理の勉強をしており、pytorchで実装されたPadimやpatch coreを実装している。
- その中で画像のshapeを操作することがしばしばあり、`x.reshape(-1, ...)`に頻繁に出会った。
- 初見、なんのための「-1」かが分からなかったため、調べてまとめることにした。

## numpy.reshape(-1, ...) の使い方
- 結論から言えば、-1を入れると平坦化される。
- そして、-1以降に数字xを入れると、(平坦化したlength/x, x)で返される。
- 上手な説明ができないため、以下に例を示す。

```
a = np.zeros((3,4,5,6))

print(type(a))                              # <class 'numpy.ndarray'>
print(a.shape)                              # (3, 4, 5, 6)
print((a.reshape(-1).shape))                # (360,)
print((a.reshape(-1, 1).shape))             # (360, 1)
print((a.reshape(-1, 5).shape))             # (72, 5)
print((a.reshape(-1, 1, 5).shape))          # (72, 1, 5)
print((a.reshape(-1, *a.shape[2:])).shape)  # (12, 5, 6) *がないとtupleで読まれてエラーとなる
```

## おわりに
- pytorchの次元の操作にもっと慣れていきたい。
【SwiftUI】点線の枠線をつける

# はじめに
![simulator_screenshot_94C3A659-28C7-4BF3-B798-057360E5CF18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/2cdeebeb-cef5-726b-7333-72984575fdb3.png)

# 実装
```diff_swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("点線の枠線")
            .frame(width: 180, height: 60)
+           .overlay(.black, in: RoundedRectangle(cornerRadius: 10).stroke(style: .init(lineWidth: 2, dash: [2, 4])))
    }
}
```

# おわり
割と簡単に実装できました
サイト新設時の.htaccessの設定メモ

`dokuji-domein.com`というドメインのサイトと仮定。

:raised_hand_tone1:やること

<ol>
<li>httpからhttpsへの転送（301リダイレクト）</li>
<li>wwwなしURLに統一</li>
<li>index.htmlのファイル名をURL上で非表示</li>
</ol>

<h2>.htaccess 完成形</h2>

```.htaccess
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} ^www\.dokuji-domein\.com
RewriteRule ^(.*) https://dokuji-domein.com/$1 [R=301,L]
RewriteCond %{THE_REQUEST} ^.*/index.html
RewriteRule ^(.*)index.html$ https://dokuji-domein.com/$1 [R=301,L]
```
ドメイン名、書き換え箇所は３箇所

以下詳細:point_down_tone1:

<h3>httpからhttpsへの転送（301リダイレクト）</h3>
<p>書き換え箇所なし</p>

```:2~3行目
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
```

<h3>wwwなしURLに統一</h3>
<p>上段：スラッシュに注意して書き換え、下段：URL形式で書き換え</p>

```:4~5行目
RewriteCond %{HTTP_HOST} ^www\.dokuji-domein\.com
RewriteRule ^(.*) https://dokuji-domein.com/$1 [R=301,L]
```

<h3>index.htmlのファイル名をURL上で非表示</h3>
<p>下段：URL形式で書き換え</p>

```:6~7行目
RewriteCond %{THE_REQUEST} ^.*/index.html
RewriteRule ^(.*)index.html$ https://dokuji-domein.com/$1 [R=301,L]
```
git push時のerror: src refspec master does not match anyについて

Git Hubの学習中、リモートリポジトリへの送信する際、ターミナル上でpushしようとした際に出たエラーについて、少してこづった為、解決策として備忘録を残そうと思います。

git psuh origin master
をターミナル上に入力し、実行した結果、下記のようなエラーが表示されました。
![スクリーンショット 2023-08-20 21.48.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515122/5462fa4f-cd2e-6650-4842-ab2e911af694.png)
masterが一致しないということなのですが、初学者の私には理解できませんでした。
ググった結果、
![スクリーンショット 2023-08-20 21.50.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515122/da6e5f33-61b4-38a9-cb69-789043ef6ff2.png)

とすることで、無事pushされました！

原因
2020/10以降、masterブランチから、mainブランチへ変更されたということでした。。。

参考記事
https://blog.deepblue-ts.co.jp/git/git-push-error/

※ちなみにudemyの「Git：はじめてのGitとGitHub」を学習中にこのエラーに遭遇し、「またエラーかよぉ〜」と深夜に嘆きかけました。。
（幸い、こちらはリサーチ３分ほどで済んだので大きなロスには至りませんでした😌)

ぜひ、参考になれば幸いです！
正規化

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/f14cd6c3-1f63-4f55-68bb-35a892f3327e.png)
１：関数服属
　「学生番号を特定すれば、学生氏名が特定される」といったように「Aを特定すればBが特定される」という関係を関数従属と言います。
　この場合、BはAに関数従属する　
　といい、A→Bとかきます。日本語での表現と矢印の向きが一見すると逆に思えますから注意してください。

２：非正規形
　非正規形の表は、繰り返し項目を持つ表です。関係データベースでは、非正規形の表を扱えません。最低でも第一正規形に変形する必要があります。

３：第１正規形
　第１正規形の表は、繰り返し項目を持たず、単純な表です。単純であるとは、１行に複数数件のデータが入っていない状態です。第１正規形では、同じ情報が重複して記録されていますから、不整合の防止効果はありません。
　第１正規形を作る時のポイント→非正規形の表の１行を複数行に分割する。
Django + heroku で非同期処理をするとき, 別プロセスからdjangoのデータベースにアクセスする方法

heroku公式が非同期処理の方法を公開している.

https://devcenter.heroku.com/ja/articles/python-rq

しかし上記サイトのworkerをそのまま使用したとき別スレッドでの処理で
データベースにアクセスできなかった

時間がかかる処理を別プロセスから行い結果をデータベースに保存したいとき
にdjangoのsetupを呼び出す必要があった.
下記プログラムのyour_appは自分のアプリ名を入力

```python
import os
import redis
from rq import Worker, Queue, Connection

# 以下3行でdjangoのセットアップを行う
# your_appは自分のアプリ名を入力
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_app.settings')
django.setup()


listen = ['high', 'default', 'low']

redis_url = os.getenv('REDIS_URL', 'redis://localhost:6379')

conn = redis.from_url(redis_url)

if __name__ == '__main__':
    with Connection(conn):
        worker = Worker(map(Queue, listen))
        worker.work()
```


## 2023/08/23 追記

以下のツールを使用すると上記のような対応を
しなくても使用することができるようです

https://github.com/rq/django-rq
C#のコードを自動でUML生成

# はじめに
Unityの入門書が楽しかったので、UMLに整理しようと思っております。
まずはPlantUMLを使ってUMLを作成する方法を得ました。
PlantUML自体のインストール方法は、別記事で語らせていただきました。

https://qiita.com/anthony1012/items/98a2bf64ddbf5eed6957

でもいざPlantUMLでUMLを作成しようとしましたところ、コードの量が多いと相応にUMLを作成するのが大変だということが分かりました。そこで、PlantUMLをダウンロードしようとした時に見つけた、C# to PlantUMLという拡張機能を使うことにしました。
こちらの記事では、このC# to PlantUMLという拡張機能の使い方を説明させていただきます。
参考とさせていただきましたサイト様は以下となります。

https://soft-rime.com/post-3293/#google_vignette


# 目次
<!-- タイトルとアンカー名を編集 -->
1. [C# to PlantUMLのインストール方法](#Chapter1)
1. [UMLの生成方法](#Chapter2)
1. [生成したUMLの保存方法](#Chapter3)


<!-- 各チャプター -->
<a id="Chapter1"></a>
# C# to PlantUMLのインストール方法 

インストールの方法はシンプルです。
VS CodeのExtensionsで拡張機能を探して、インストールします。



<a id="Chapter2"></a>
# UMLの生成方法

UMLの生成には、VSCodeのファイル -> Add folder to workspaceを選択します。
するとフォルダを選択することができますので、UnityのScriptsフォルダを選択いたします。
これによりScriptsフォルダがVSCodeのワークスペースに追加されているはずです。

次にVSCodeでShift + Command + Pでコマンドの実行をします。
実行するコマンドはcsharp2plantuml.classDiagramとなります。

実行しますと、Scriptsフォルダの中にplantumlフォルダが作られているはずです。
plantumlフォルダの中にinclude.pumlとクラスごとのファイルが作成されております。
include.pumlはその他クラスのファイルを参照する形式となっておりましたので、こちらでUMLを作成しますと、全体図が見えるようになります。
UMLの生成には、Macでしたらoption + Dで生成することができます。
生成しますと、ダイアグラムのビューが表示されます。


<a id="Chapter3"></a>
# 生成したUMLの保存方法

include.pumlファイルを開いた状態で、そのファイルの内容の上で右クリックをします。
「ファイル内のダイアグラムをエクスポート」を選びます。
そのあとに保存するファイル形式を選びますと、out/plantumlというフォルダが作成されます。
この中に出力結果が表示されます。
なんと素晴らしい機能でしょう！

![include.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494391/011c7f6a-deb6-319d-6859-ffd391113431.png)
Oracle SQL Developerのインストール

## はじめに
SQL Developerは、データベース・オブジェクトの参照、作成、編集および削除や、データのエクスポート・インポートといったデータベースの管理や操作に加え、PL/SQLのデバックが行えるGUIツールです。
Oracle XE (Oracle Database Express Edition) には同梱されていないため、使用する場合はダウンロードしてインストールする必要があります。

本記事では、SQL Developerをインストールし、OracleXEに接続させた際の手順をまとめます。

#### 今回使用した環境
・OS Windows2016
・Oracle SQL Developer 23.1
・Oracle Database 18c Express Edition（以前[こちら](https://qiita.com/mi_h/items/cd089647cd95caafc78d)で記事にした環境です）

## 1. パッケージのダウンロード

Webブラウザから以下のダウンロードサイトにアクセスします。
[Oracle SQL Developerサイト](https://www.oracle.com/database/sqldeveloper/)

[Download SQL Developer]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/8956f5c9-3ab8-9023-f52a-32023a8a60d5.png)
”Windows 64-bit with JDK 11 included”をダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/bfb8404f-a7e6-9afc-cd42-18b3f2752cfd.png)
ライセンスの確認ポップアップが表示されるので、同意します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/bade5383-0b3e-3282-1cac-cd744d304b93.png)
Oracleアカウントへサインインしていない場合は、ここでサインインが求められます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/ac9b2356-b9a5-2582-14a7-c7af538e21c6.png)
ダウンロードしたファイルを任意のフォルダで解凍します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/ee53d818-1338-fa77-23be-31526139230a.png)
展開フォルダにある、sqldeveloper.exeを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/af24d5a9-9013-c40b-3315-bf00db5ccf25.png)
SQL Developerが起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/5580bbe6-2531-d236-9935-0d267a961297.png)
インポート・プリファレンスの確認ポップアップが表示されるので、必要に応じて指定します。
本環境では、デフォルトのまま[いいえ]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/6b6cc49f-dd33-2ddf-19e7-548fcd351f21.png)
Oracleに使用状況のレポートを送付するかの確認ポップアップが表示されるので、必要に応じて設定し、[OK]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/3cd48f37-4b5c-e815-5ff2-770a2c25d3d3.png)
Oracle Database 18c Express Edition（XE)上のPDB1を接続先として登録します。
左ペインにある「接続」メニューの「+」ボタンをクリックして”新規データベース接続”を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/b9ede30b-ddf9-bae3-6dff-dece2b62cb59.png)
「データベース接続の作成／選択」の画面で、必要項目を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/aa26a5be-3dc3-27b0-d386-36b561a102c1.png)
|Name|任意の接続先名を入力  |
|-|---|
|ユーザー名|データベース接続するユーザー名|
|パスワード|データベース接続するためのパスワード|
|ホスト名|データベースサーバーのホスト名|
|ポート|データベースのポート（基本は1521）|
|SID ※|データベースのSID|
|サービス名　※|データベースのサービス名|

※SIDもしくはサービス名どちらかを設定

入力が完了したら、「テスト」ボタンをクリックして、正常にデータベースと接続できるか確認します。
接続テストが成功すると、画面左下に、ステータス：成功と表示されるので、[接続]ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/b08bec95-b42c-a932-55cb-14b7630a8131.png)
Oracle接続先に設定したDBが表示されれば、接続は完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/21ae8d28-efa2-d0ce-cd2e-d6b42c651642.png)
Oracle Database 18c Express Edition(XE)のインストール


## はじめに
Oracle Databaseの無償版である[Express Edition(XE)](https://www.oracle.com/jp/database/technologies/appdev/xe.html)をWindowsにインストールした際の手順をまとめます。
## システム構成
今回使用したソフトウェアとバージョンは、以下の通りです。
・Oracle : Oracle Database Express Edition (XE) Release 18.4.0.0.0 (18c)
・OS : Windows2016



## 1. パッケージのダウンロード

OracleをダウンロードするにはOracleアカウントが必要です。
Oracleアカウントは無料で作成できる為、ダウンロードに際しては、事前にアカウントを作成しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/f03dc4fa-3bf7-2df8-1d49-ba50183d3d98.png)



#### 1.1 日本オラクルのダウンロードサイトにアクセス
Webブラウザから以下のダウンロードサイトにアクセスします。
[Oracle Database Express Edition (XE) 18ダウンロードサイト](https://www.oracle.com/jp/database/technologies/xe18c-downloads.html)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/d2f0f6e6-83d7-ecb1-f75f-bce9b3700d22.png)


#### 1.2 インストールパッケージのダウンロード
Windows用のパッケージをクリックします。
ライセンス確認のポップアップが表示されるので、同意にチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/01653948-2acd-99b0-c8b4-20f914ba9411.png)

#### 1.3 インストールパッケージの解凍
ダウンロードしたパッケージを任意のフォルダで解凍します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/eafb9c27-8973-4ef2-d354-0c4546410370.png)

## 2.インストール
#### 2.1 インストーラーの起動
パッケージが展開されたフォルダ内のsetup.exeを管理者として実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/022ed51f-ba0b-6f39-fda8-1676126ba5d0.png)

#### 2.2 ウィザードに従い設定を入力

”ウィザードへようこそ”画面が表示されたら、[次へ]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/5c0372d6-314b-3e82-6aaa-df2b8484f664.png)

使用許諾に合意し、[次へ]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/c7fb3b8d-1c0e-82c1-6f57-15951148d768.png)

インストール先フォルダを指定し、[次へ]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/d4dad8d5-f117-e6d6-d39a-d529c59564f0.png)

データベース・パスワードを指定し、[次へ]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/f314b858-f4fd-7417-0eb4-021419d6da2b.png)

インストール設定のサマリ-が表示されるので、内容を確認し、[インストール]をクリックしてインストールを開始します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/a9b078b5-38ea-d2f6-867e-fe367a49c100.png)

”Oracle Databaseが正常にインストールされました”と表示されていることを確認し、[完了]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281123/3cf04e98-99ac-eb85-d97f-f1fc52470f18.png)

以上で、Oracle Database 18c XEのインストールは完了です。
[資格勉強]ワイヤレスIoTプランナー ～DXの技術～

DXを支える技術をポンチ絵にしてみました。

# 参考文献
[1] [ワイヤレスIoTプランナー公式HP](https://www.mcpc-jp.org/wip-kentei/kentei_cbt_kiso/) 
[2] [ワイヤレスIoTプランナーテキスト　基礎編](https://ric.co.jp/book/e-books/detail/1360)

# ポンチ絵
業務をデジタル化して、IoTとAI使って、色々予測できるからビジネスの判断も効率的にできるぜ
ワイヤレス、IoTセンサ、AIの技術で、DXを支えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/c0353289-bb26-4047-9f10-65012cfecf89.png)

# ワイヤレスの方式
ワイヤレス通信の各方式の特徴を理解して、業務に必要な帯域、帯域、カバーできる距離、コストを考えてたIOTプランが必要そう。
図の出典： 総務省　令和二年　情報通信白書
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/188753e6-cdf8-7b2c-67a5-fc76233a41f1.png)

# IoT 
梨に着けたセンサーとアメダスの気象情報を、AIで解析して、害虫発生予想を生産者に提供して、
生産者の行動を促す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/e7e20cab-6d07-dde0-5bb5-8cff11458dc2.png)
図の出典：総務省　IoT利用環境構築事例集

# AI
AIは、センサーとかITシステムからのデータ収集して、学習して、学習したモデルを使って予測したりする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/df7fc917-b9d6-5e68-ccff-3a6dcf7bfb34.png)
図の出典：AIネットワーク社会推進会議 「報告書2022」
情報処理技術者試験の答案の開示請求の流れ

# はじめに
SNS等でIPAに開示請求できると知って、いろいろ調べて実際に開示請求してみた。IPAに(優しくない)流れは書いてあるけど、2回目も出来る気がしないので整理。

以下の内容で実際に開示請求を行ったが、都度都度、最新の内容を確認して手続すること。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527830/f3a91fdf-ab05-2d83-476e-4920be338ad9.png)

https://cbt-s.com/examinee/ipa_pbt-faq/detail/4173.html


### 【1】保有個人情報開示請求書の送付
・上記IPAのページにあるWord/Pdfをもとに作成。
・『開示請求者本人の「令和 X 年度春期情報処理技術者試験 IT サービスマネージャ試験 午後Ⅰ・午後Ⅱ 答案 (受験番号 SMYYY-ZZZZ)」に記録された本人に係る保有個人情報』　※開示したい内容に合わせて適宜読み替え
・写しの送付を希望する。
・開示請求手数料は銀行振込が楽。銀行次第。
・免許証のコピーと、住民票の写しと一緒に送付。
・どうしても届いたことを確認したい場合は簡易書留、そうでもない、忘れた頃でいいやくらいであれば普通郵便で。

### 【2】保有個人情報開示決定通知書の受け取り
・2週間くらい、忘れた頃に届く。IPAからの送付は簡易書留。

### 【3】保有個人情報の開示の実施方法等申出書の送付
・届いた「保有個人情報開示決定通知書」等に書かれている説明をもとに作成。
・答案を送ってもらうための？手数料は切手。84円切手だけでなく140円切手もコンビニに在庫あった。
・どうしても届いたことを確認したい場合は簡易書留、そうでもない、忘れた頃でいいやくらいであれば普通郵便で。

### 【4】答案のカラーコピーの受け取り
・2週間くらい、忘れた頃に届く。IPAからの送付は簡易書留。
・午後1で各設問で何点もらえたかどうかは不開示、黒塗り。

### tips
長いので、コピー代かかっても紙でプリントして印刷した方が楽。
組織体制変わったみたいで、以下が合っているかも分からなかった。IPAでも届きそう？

〒113-6591
東京都文京区本駒込二丁目28番8号
文京グリーンコートセンターオフィス16階
独立行政法人　情報処理推進機構（IPA）
総務部　個人情報保護グループ　御中

# おわりに
時間と手間と、少しのお金はかかる。IPA側もコストかかっていそう。あくまで自己満足でしかなく、答案を見せてもらえるサービスというより個人情報の開示をする手続な感じ。

個人情報として1年しか保存されないみたいなので、ほしいと思ったら合否出た後にでも早めに。

最初っから電子でもらえるとすごい楽なんだけどなー。

# 参考にしたページ

以下の各ページの方がもっと優しい。

https://wktk.jp/entry/disclose-itee-answer-sheet/

https://strangerxxx.hateblo.jp/entry/20230524/1684938486
DNS-IP-Mapper: ドメイン名に自動でIPアドレスを割り当てるツール

DNS-IP-Mapperのソースコードは、以下のGitHubリポジトリで確認できます:  
[https://github.com/kawamurashingo/DNS-IP-Mapper](https://github.com/kawamurashingo/DNS-IP-Mapper)

### はじめに

サービスのデプロイやインフラのセットアップ時、ドメイン名にIPアドレスを割り当てるのはルーチンワークです。特に多数のドメインを扱っている場合には、これらの割り当てを手動で管理し、追跡するのは大変な作業になることがあります。DNS-IP-Mapperは、指定されたサブネットから利用可能なIPアドレスを、完全修飾ドメイン名（FQDN）のリストに自動的に割り当てます。

### 前提条件

- **シェル環境**: Bash (推奨されるバージョンは4以上)。
- **コマンド**: `host` コマンドが利用可能であること（通常は `bind-utils` パッケージに含まれています）。

### 使い方

#### 1. **準備**:

**FQDNファイル**: IPアドレスが必要なFQDNのリストを持つテキストファイルを作成します。それぞれのFQDNを別の行に配置してください。  
**例 (`fqdns.txt`)**:

```plaintext
db01.example.com
db02.example.com
web0[1-2].example.com
```

**サブネットファイル**: IPアドレスを選択するためのサブネットを含む別のテキストファイルを作成します。それぞれのサブネットを別の行に配置してください。  
**例 (`subnets.txt`)**:

```plaintext
192.168.1.0/24
192.168.2.0/24
```

#### 2. **スクリプトの実行**:

以下のコマンドでスクリプトを実行します:

```bash
./assign_ips.sh -f <FQDNファイルへのパス> -n <サブネットファイルへのパス> [-s <IPの開始範囲>] [-e <IPの終了範囲>]
```

### オプション

- `-f` : FQDNファイルへのパス。
- `-n` : サブネットファイルへのパス。
- `-s` : IPアドレスの開始範囲を定義（デフォルトは1）。
- `-e` : IPアドレスの終了範囲を定義（デフォルトは240）。

**例**:

```bash
./assign_ips.sh -f fqdns.txt -n subnets.txt -s 10 -e 100
```

上記を実行すると、指定されたサブネットからFQDNに `.10` から `.100` の範囲のIPアドレスを割り当てることを試みます。

### 出力

結果は、次の形式で各FQDNに割り当てられたIPアドレスをリストします:

```plaintext
<fqdn>,<assigned_ip>
```

出力の例:

```plaintext
db01.example.com,192.168.1.10
db02.example.com,192.168.1.11
web01.example.com,192.168.1.12
web02.example.com,192.168.1.13
```

### IPアドレスの利用可能性の判断基準は？

スクリプトは、IPアドレスの利用可能性を次の基準で判断します:

1. **DNSチェック**: `host` コマンドを使用して、IPアドレスに既にDNSレコードが存在するかどうかを確認します。
2. **Pingチェック**: スクリプトはIPアドレスにpingを送ってその応答を確認します。

両方のチェックが失敗した場合（DNSレコードがなく、pingに応答しない場合）、IPアドレスは利用可能と見なされます。

### 注意点

- このスクリプトのバージョンは、CIDR値として24, 23, 22のみをサポートしています。
- 利用可能なサブネットから各FQDNにユニークなIPアドレスが割り当てられます。

---

DNS-IP-MapperでIPアドレスの割り当て作業を自動化し、シンプルにしましょう🌐