OmniAICreator/Qiita-1.07M huggingface dataset:
【webサイトを無料で公開できる】GitHub Pagesの使い方について

# はじめに

### 本記事を読んでほしい方
- HTMLやCSSを学び終えた駆け出しエンジニアの方
- GitHub Pagesの使い方がわからない方

### GitHub Pagesとは？
GitHub Pagesとは、自分で作ったwebサイトを無料で公開できるGitHub公式のサービスです。HTMLやCSSを学んだら、自分でサイトを作成し、全世界へWebサイトを公開してみましょう！本記事では、GitHub Pagesを使って、サイトを公開する方法について説明します。

# GitHub Pagesの使い方
### 1. GitHubアカウントを作成
GitHubのアカウントを作成しましょう。

https://github.com/

無料か有料か選択する画面が出てくると思いますが、無料で問題ないです。

### 2. リポジトリを作成
リポジトリとは、自分が作成するWebサイトやアプリケーションのソースコードを一つひとつ管理するためのものです。サイトやアプリを作るときは、まず最初にGitHub上でリポジトリを作成しましょう。ちなみに、公開するサイトのURLは`https://[アカウント名].github.io/[リポジトリ名]/`となります。

画面右側の+ボタンをクリックし、New repositoryをクリックしましょう。

![スクリーンショット 2023-03-12 14.32.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782490/8d9f1aac-0bd0-445d-1300-6819b86ffb83.png)

リポジトリ名を入力し、Publicを選択したらCreate repositoryボタンを押し、リポジトリの作成を完了させましょう。

### 3. HTML, CSSファイルのアップロード
リポジトリを作成したら、サイト公開用のHTML, CSSファイルをアップロードしましょう。Create repositoryボタンを押した後、以下のような画面に移ります。HTML, CSSファイルの作成がまだの方は、Creating a new fileを、すでにHTML, CSSファイルを作成済みの方はuploading an existing fileを選択しましょう。

![スクリーンショット 2023-03-12 15.02.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782490/7ce45f0f-6935-82f4-3ce9-b0a28caa91a7.png)

### 4. Webサイトの公開
HTML, CSSファイルのアップロードが完了したら、いよいよサイトの公開です。リポジトリページのSettingsリンクをクリックしましょう。
![スクリーンショット 2023-03-12 15.32.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782490/503de3dc-134f-3239-97ed-152b6681f041.png)
settingsページに移ったら、Pagesリンクをクリック。
![スクリーンショット 2023-03-12 15.36.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782490/b24aebe4-fcc7-c299-ea17-936448dae7fb.png)
GitHub Pagesに遷移するので、mainブランチとしてsaveをクリックすればWebサイトの公開完了です。(しばらく時間がかかる場合があります。)
![スクリーンショット 2023-03-12 15.43.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782490/29c98922-3868-ef6e-43d0-afc2c50d79a2.png)
公開が完了すると、以下のようにVisit siteと出てくるので、クリックしてサイトを見てみましょう。
![スクリーンショット 2023-03-12 15.48.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782490/6d55d50c-3a80-b92c-ae9f-619630bc47c2.png)
以上で説明を終了します。最後まで読んでいただきありがとうございました！

# 参考文献
より詳細な説明が以下の記事にございますので、ご参照下さい。

https://docs.github.com/ja/pages/getting-started-with-github-pages/about-github-pages

https://prog-8.com/docs/github-pages
【Webスコア爆改善！】CSSとJavaScriptを後読みにすることで表示高速化

昨今、外部のJSやCSSを読み込むと非常に遅くてHTMLのスコアが著しく下がっているサイトも多いでしょう。
解説サイトにあるようなasyncやdeferを使ってもいまいちスコアが解消されない。

そんな場合はworkerを利用して外部ファイルを非同期で後読みにすることでスコアが大きく解消されます。

↓ まずこれをそのまま用意する (コピペでOK)
```worker.js
function doHeavyProcessing() {
}
onmessage = function(event) {
	doHeavyProcessing();
	postMessage('processing completed');
};
```

↓ こちらを該当のHTMLの下のほうに記載する (「読み込みたいjs/css」の部分だけ書き換えてください)
```html
<script>
$(window).load(function(){

	const worker = new Worker('worker.js');
	worker.onmessage = function(event) {
		// 読み込みたいjsを羅列
		js_read("https://platform.twitter.com/widgets.js");
		js_read("https://www.line-website.com/social-plugins/js/thirdparty/loader.min.js");

		// 読み込みたいcssを羅列
		css_read("/css/uikit/xxxx.min.css");
		css_read("/css/xxx/xxx.min.css");
		css_read("/css/xxx.min.css");
		css_read("/css/bulma.min.css");
		css_read("/css/animate.min.css");
	};
	worker.postMessage(null);

	function css_read(v){
	    var link;
	    link = document.createElement('link');
	    link.rel = 'stylesheet';
	    link.href = v;
	    document.head.appendChild(link);
	}
	function js_read(v){
	    var sf;
	    sf = document.createElement('script');
	    sf.src = v;
	    document.body.appendChild(sf);
	}

});
</script>
```

これで完全にバックグラウンドでの非同期の読み込みになるので速度大幅改善、スコア爆改善に繋がります。

※ ただし、cssを後読みにする都合で最初のレンダリング時に画面の見た目が一瞬悪くなります。それでも問題ないケースのみ導入を検討してください。
また、それに伴って逆にCLSが発生してしまうリスクがあるので、ブロック要素には直接styleで高さ指定しておくことをオススメします。

※ jsを直接カスタマイズ出来るかたは「読み込みたいjs/css」の部分を配列組んだりするともっとスマートになると思います。
WindowsFirewallの規則をIPアドレス、ポート番号情報込みで一括取得するPowerShellスクリプト

WindowsFirewallの受信/送信の規則をGUIで確認するようなイメージでCSV出力するPowerShellスクリプトの紹介です。
ネットで見つけたスクリプトを参考に少しだけアレンジしたものになります。
CSV出力ファイル名に実行したマシンのホスト名と日時が含まれるようにしていますので、
サポートなどで他の人のWindowsFirewallルールを確認したい場合などにスクリプトを送付して情報取得依頼をする場合に利用できるかと思います。


```Windows_Firewall_rule_export_csv2 .ps1
Import-Module NetSecurity

$Hostname = $Env:Computername

$Datetime = Get-Date -Format "yyyyMMdd-HHmm"

$Filename = $Hostname + "_" + $Datetime

Get-NetFirewallRule | Where-Object {$_.enabled -eq "true" -and $_.direction -eq "inbound"} |
ForEach-Object{
$Rule = $_
$Port = $_ | Get-NetFirewallPortFilter
$Addr = $_ | Get-NetFirewallAddressFilter
$App = $_ | Get-NetFirewallApplicationFilter
$Sec = $_ | Get-NetFirewallSecurityFilter
[pscustomobject]@{
Name = $Rule.DisplayName
Group = $Rule.Group
Profile = $Rule.Profile
Enabled = $Rule.Enabled
Action = $Rule.Action
Override = $Sec.OverrideBlockRules
Program = $App.Program
Protocol = $Port.Protocol
LocalAddress = $Addr.LocalAddress
LocalPort = $Port.LocalPort
RemoteAddress = $Addr.RemoteAddress
RemotePort = $Port.RemotePort
}

} | export-csv ./WindowsFirewall_Inbound_Rule_$Filename.txt -encoding default

Get-NetFirewallRule |  Where-Object {$_.enabled -eq "true" -and $_.direction -eq "outbound"} |
ForEach-Object{
$Rule = $_
$Port = $_ | Get-NetFirewallPortFilter
$Addr = $_ | Get-NetFirewallAddressFilter
$App = $_ | Get-NetFirewallApplicationFilter
$Sec = $_ | Get-NetFirewallSecurityFilter
[pscustomobject]@{
Name = $Rule.DisplayName
Group = $Rule.Group
Profile = $Rule.Profile
Enabled = $Rule.Enabled
Action = $Rule.Action
Override = $Sec.OverrideBlockRules
Program = $App.Program
Protocol = $Port.Protocol
LocalAddress = $Addr.LocalAddress
LocalPort = $Port.LocalPort
RemoteAddress = $Addr.RemoteAddress
RemotePort = $Port.RemotePort
}
       
}   |  export-csv ./WindowsFirewall_Outbound_Rule_$Filename.txt -encoding default

Write-Output "Success"
```


実行方法
コマンドプロンプトにて
```
powershell

.\Windows_Firewall_rule_export_csv2.ps1
```

処理が終了すると画面に「Success」と表示されます。

スクリプトを配置したフォルダと同じ場所に
下記2ファイルが出力されます。

```
WindowsFirewall_Inbound_Rule_[ホスト名]_[yyyymmdd-HHmm].txt
WindowsFirewall_Outbound_Rule__[ホスト名]_[yyyymmdd-HHmm].txt
```

ネットでイメージ通りの出力をしてくれる書き方がなかなか見つける事が出来なかったので備忘録として残しておきます。
[Rails]CarrierWaveでimageの保存ができない

# 現象
開発環境ではうまく動くのに、本番環境ではなぜかファイルのアップロードが出来ていなくて保存ができない現象が発生したので、その時の解決方法を残しておきます。

# エラー
```:エラー
#<ActiveModel::Errors [#<ActiveModel::Error attribute=images, type=translation missing: ja.errors.messages.mini_magick_processing_error, options={}>]>
```
# 原因
* MiniMagick(ImageMagick)の日本語化が出来ていないため、翻訳に失敗している。
* そもそも、MiniMagick(ImageMagick)がインストールされていないなど、エラーが発生している。

# 解決方法1
* config/locales/ja.yml に, MiniMagick(ImageMagick)のエラーの日本語訳を追加する。
```:config/locales/ja.yml
ja:
  errors:
    messages:
      carrierwave_processing_error: 処理できませんでした
      carrierwave_integrity_error: は許可されていないファイルタイプです
      carrierwave_download_error: はダウンロードできません
      extension_white_list_error: "%{extension}ファイルのアップロードは許可されていません。アップロードできるファイルタイプ: %{allowed_types}"
      extension_black_list_error: "%{extension}ファイルのアップロードは許可されていません。アップロードできないファイルタイプ: %{prohibited_types}"
      rmagick_processing_error: "rmagickがファイルを処理できませんでした。画像を確認してください。エラーメッセージ: %{e}"
      mime_types_processing_error: "MIME::Typesのファイルを処理できませんでした。Content-Typeを確認してください。エラーメッセージ: %{e}"
      mini_magick_processing_error: "MiniMagickがファイルを処理できませんでした。画像を確認してください。エラーメッセージ: %{e}"
```

# 解決方法2
* そもそもインストールされていない場合は、インストール
※私の環境では、こちらでした…😅
```:インストール
sudo apt-get -y install imagemagick
```
* 必要なモジュールが足りていない可能性がある場合は、convertコマンドのバージョン情報を調査して追加
※動いている開発環境との差異をみてください。
```:差異調査
convert -version
```
GItの取説(備忘録)

## はじめに

gitの扱いに苦労した経験があるので、自身がまとめたgitの取説を今回は書いていきます！

## gitの流れ

①cd ファイル名　カレントディレクトリに移動
②git init　ローカルリポジトリ新規作成
③git add ファイル名　ファイル追加(git add .　で一括追加)　　
④git commit -m "コミットメッセージ"　ローカルにコミットし、メッセージを書く
⑤git remote add orign リモートリポジトリURL　リモートリポジトリに移す準備
⑥git push origin main　（git push -u origin mainで次回からgit pushでOKです。）プッシュする

これで、githubに無事コードを保管できます。

## その他のgitのコマンド説明

``確認、変更系``
git branch　ブランチの確認
git log　コミット履歴を確認
git status　ファイルの追加/変更/削除部分の確認
git branch -M main ブランチ変更

### チーム開発の時に使ったコマンド

``ブランチの作成、移動``
git checkout -b ブランチ名　作成と移動両方できる
git branch ブランチ名　ブランチ作成
git checkout ブランチ名　ブランチ移動

``自分のブランチに反映させる``
①git checkout develop　developに移動
②git pull origin develop　プルする
③git checkout 自分の作業ブランチ　作業ブランチに移動
④git merge origin/develop　自分のブランチに反映

``実際の開発フロー``
①git checkout develop　統合ブランチに移動
②git checkout -b　（トピックブランチ）　ブランチ作成
～作業が完了したら～
③git add -A　全てaddする
④git commit -m "コミットメッセージ"　ローカルコミットする
⑤git push origin (自分の作業ブランチ)　リモートにプッシュする


## さいごに
今回は自身がgitで必須で使っていたコマンドを紹介しました。
役に立つと幸いです！ありがとうございました！
Rails7でバリデーションのエラーメッセージが表示されない問題を解決

Rails7でデフォルトになったTurboが絡んだ原因であった。

以下のように
`status: :unprocessable_entity`
を加えればよい。

app/controllers/growth_diaries_controller.rb

before
```html
render("growth_diaries/edit")
```

after
```html
render("growth_diaries/edit", status: :unprocessable_entity)
```
気になるARグラスで開発ができるのか？

### ARグラスって？

---

拡張現実（Augmented Reality）の技術を利用した眼鏡

![ar.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498701/e2b11a18-59d0-6f83-bb88-936582d02022.jpeg)


---

### 最近どうなの？

Google → Google Glass（ビジネスや医療）

Apple　→ Apple Glass　（噂)

BMW → 運転手に情報を提供する試み

---

Nreal Airを買いました

![nreal_air.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498701/b797a894-2a4c-06e6-7049-b67729235b69.jpeg)


---

### Nrealとは？

日本Nreal株式会社（本社中国）から販売されている
メガネ型ウェアラブルデバイス・ARグラス

---

### どんな世界？

---

<iframe width="1512" height="607" src="https://www.youtube.com/embed/aavd7ng1EfA" title="Nreal Air「どこでなに見る？どう遊ぶ？」グローバル編" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

---

### 使ってみた

https://twitter.com/i/status/1626923505018355712

---

### 作業

場所： 自宅・ファミレス・電車・車・飛行機
作業： 開発・ブラウジング・MTG・動画視聴

---

### ARグラスのメリット

---

#### 軽くて移動する時に最適

---

#### どこでも画面を持ち運び(201インチ3画面)

---

#### 自分だけが見える世界に没入

---

### ARグラスのデメリット

---

#### 周りの目がまだ気になる

---

#### 乗り物の移動に合わせて画面が動いてしまう

---

#### 長時間の使用は疲れる

---

## 結論

ディスプレイをフルに代替するのはまだ
局所的にとても便利 ！

---

### おすすめの使い方

- 飛行機の中での作業

- 家で寝転びながら映画を見る

- 公の場所であまり見られたくない作業を行う


---

## 自己紹介

個人開発について発信しています！
Twitterもフォローください👏
[@1026NT](https://twitter.com/1026NT)
なる

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498701/3db40e7d-3213-be1f-8650-c6ad5dff69c9.jpeg" width="300px">
pyautogui で よく使うもの

# key を押す (key)

指定したキーを押す

```key.py
# ctrl と a を同時押し
pyautogui.hotkey('ctrl', 'a')

# 上記の後に e を押す
time.sleep(0.5)
pyautogui.press("e")
```

# スリープ (sleep)

処理の間に1.2秒のスリープ

```sleep.py
time.sleep(1.2)
```

# 画像を探す (img)

opencv インスコ必須
grayscale = True で高速化
confidence= 0.9 で曖昧検索

```img.py

# 画像があるか探す
img = pyautogui.locateCenterOnScreen('your.png', grayscale=True, confidence=0.9)

if img:
    # 画像があれば、中心をクリック
    pyautogui.click(img.x,img.y)
    
    # 画像の位置まで0.5-2秒使い移動させクリック
    pyautogui.moveTo(img.x,img.y, random.uniform(0.5, 2), pyautogui.easeInQuad)
        pyautogui.click()

```

# すべての画像を探す

わかりやすく、座標をx,yに変換。
その後順に画像をクリックしていく。

```imgall.py
imgs = list(pyautogui.locateAllOnScreen('firefox-plus.png', grayscale=True, confidence=0.9))
centers = [pyautogui.center(v) for v in imgs]

i = 0
while i < len(centers):
    pyautogui.moveTo(centers[i].x,centers[i].y,random.uniform(0.5, 2), pyautogui.easeInQuad)
    pyautogui.click()
    i += 1
```


# クリック (click)

```click.py
# クリック
pyautogui.click()

# 右クリック
pyautogui.rightClick()
```

# ランダム (rand)

```random.py

# ランダムで整数を取得
random_int = random.randint(0, 9)

# ランダムで少数以下も取得
random.uniform(0.6, 1.5)

# 配列からランダムで一つ取得
urls = [
    'https://yahoo.co.jp',
    'https://google.co.jp',
    'https://qiita.com/'
]

rand_url = random.choice(urls)

```


# 例外処理 (try)

```try.py
try:
    # 画像をクリックする
    pyautogui.click('button.png')
except Exception as e:
    # ここで、キャプチャが出たかどうかを調べるのも良いかも
    print(f'エラー発生 red: {str(e)}. Exiting...')
```


# 最後に

位置情報の注意

```
locateCenterOnscreen の時は
x , y になる

locateOnscreen の 時は
left , top
```

わかりづらいので、`locateCenterOnscreen` に統一したほうが良い
AWS Security Token Service (STS) メモ



* AWS Security Token Serviceについてメモする

## 概要

* AWS Security Token Serviceの略称

* 一時的なセキュリティ認証情報を発行するためのサービス

  ![STS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/9b151685-249e-7bbc-3c2b-aa805bb0a5c9.png)


## 利点

- アプリにAWS セキュリティ認証情報を埋め込まずに済む
- ユーザーに対してAWS ID を定義せずAWS リソースへのアクセスを許可できる


## IAMアクセスキーとの差異

* 有効期限を設定して一時的なアクセス許可が可能な点
* リクエストの度に作成される点

## ユースケース

### ID フェデレーション

- AWS 以外の外部システム(外部IdP)でユーザー ID を管理し、それらのシステムのアクセス許可からサインインするユーザーに、AWS タスクの実行や AWS リソースへのアクセス権限を付与する
- **エンタープライズIDフェデレーション**
  - 組織・企業のネットワークのユーザーを認証し、ユーザーが AWS にアクセス可能にできる
  - それらのユーザーのために新しい AWS IDを作成したり、異なる認証情報でサインインすることを求める必要がない
- **ウェブ ID フェデレーション**
  - ユーザーに一般的なサードパーティーIDプロバイダーを使用したサインインを求めることができる
  - ユーザーはプロバイダー認証情報をAWSアカウントのリソースを使用するための一時的なアクセス許可に変換できる

## 参考情報

* [IAM の一時的な認証情報](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_temp.html)
A/D変換

# A/D変換
```アナログ信号をデジタル信号に変換```することA/D変換と呼ぶ。
パルス符号変調(PCM)は、アナログ信号をデジタル信号（パルス列)に変換する代表的な方式。
アナログ信号を```標本化```→```量子化```→```符号化```の三段階で変換する。

### 標本化
連続的に変化しているアナログデータに対して、```一定間隔ごとにその瞬間の値を測定```すること。
１秒間に行う標本化の回数を```サンプリング周波数```と呼び、単位はHz（ヘルツ）が使われる。

### 量子化
測定した信号の値を```nビットの適当な整数値に丸める```。

### 符号化
その値をnビットの２進数に変換する。```nの値が大きいほど精度が増し```、アナログ信号の```再現性に優れるが、データ量が多くなる```。

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
[Go Snippet] パスワード生成用のランダムな文字列を返す関数


## きっかけ

海外のサービスではほぼ見ないが、日本のサービスではパスワードに文字数制限があったり、特殊文字が使えなかったりするので、ちゃちゃっと生成できるようにしたいと考えていました。

そんなときちょうど Go　言語のスクレイピングライブラリ Colly でサンプルのコードがあったので、自分用に作り変えてみることに。

http://go-colly.org/docs/introduction/configuration/


## Go で書いてみる

### やりたいことの条件

- ランダムな文字列を返す
- 文字数を指定できる
- 文字のみ、文字+数字のみ、文字+数字+特殊文字 を簡単に選べるようにする

ということで、書いてみる

```go
import "math/rand"

const letters = "abcdefghijklmnopqrstuvwxyz"
const LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
const numbers = "123456789"
const specialChar = "~!@#$%^&*()_-+={}[]:;,.<>?/'"

var letterBytes string

func RandomString(length int, strength int) string {
	b := make([]byte, length)

	switch strength {
	case 3:
		letterBytes = letters + LETTERS + numbers + specialChar

	case 2:
		letterBytes = letters + LETTERS + numbers

	default:
		letterBytes = letters + LETTERS
	}

	for i := range b {
		b[i] = letterBytes[rand.Intn(len(letterBytes))]
	}

	return string(b)
}
```
VSCodeにてJSXコーディング中にattributeの補完候補が表示されない時の対処法

# 目次
[1. 問題解決の経緯](#1-問題解決の経緯)
[2. 開発環境](#2-開発環境)
[3. 解決方法](#3-解決方法)
[4. 実証](#4-実証)
[5. おわりに](#5-おわりに)

# 1. 問題解決の経緯
備忘録として記事を書きます。
動画を見ながらNext.jsの勉強をしていた時です。
VSCodeで`JSX`を記述していると以下のような補完が効きませんでした。
## 1-1. JSX中のHTMLでの補完
![スクリーンショット 2023-03-12 13.27.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3271648/95dceef3-a911-b2cf-2246-ff58b35d9457.png)
## 1-2. コンポーネントでの補完
![スクリーンショット 2023-03-12 13.31.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3271648/ee2e92d8-0bba-6396-803f-bb990c738053.png)

# 2. 開発環境
+ Visual Studio Code 1.76.1
+ React 18.2.0
+ Next.js 13.2.3
+ 編集するファイルの拡張子が"jsx"であること

# 3. 解決方法
以下のコマンドで`@types/react`をインストールしたら補完が効くようになりました。
```console
> npm install --save @types/react
# または
> yarn add @types/react
```

2023/12/12追記
`@types/react`は、TypeScriptプロジェクトでReactライブラリを使用する際に役立つ、Reactの型定義（TypeScriptの型情報）を提供するnpmパッケージです。これにより、TypeScriptを使用してReactコンポーネントを記述する際に、コード補完や型の安全性などが向上します。

# 4. 実証
実際にインストール前後で確認してみましょう！
## 4-1. プロジェクトの作成
まず、Next.jsのプロジェクトを作成します。(プロジェクト名は任意)
```console
> npx create-next-app@latest
# または
> yarn create next-app
```

今回、筆者は「sample01」というプロジェクト名にしました。
```console
# 以下、任意の選択でOK
> ? What is your project named? › sample01
> ? Would you like to use TypeScript with this project? › No
> ? Would you like to use ESLint with this project? › Yes
> ? Would you like to use `src/` directory with this project? › Yes
> ? Would you like to use experimental `app/` directory with this project? › No
> ? What import alias would you like configured? › ~/*
```

作成できたら、プロジェクトに移動してVSCodeを開きます。
```console
> cd sample01
> code .
```

## 4-2. 補完機能の確認(@types/reactインストール<font color="red">前</font>)
以下のHTMLタグとコンポーネントをindex.jsxに追加します。

```javascript:src/pages/index.jsx
<button></button>
<Link></Link>
```
そして、以下を試してみてください。
+ buttonの開始タグ内に「onClick」と入力する。
+ Linkコンポーネントの開始タグ内に「prefetch」と入力する。

すると、筆者の環境では、"onc"まで入力しても補完候補が表示されません。
![スクリーンショット 2023-03-12 14.17.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3271648/e1792e76-5d08-f296-5eaf-ae71c494ffe0.png)

また、Linkコンポーネントでも同様に補完候補が表示されません。
表示されているのはスニペットです。
![スクリーンショット 2023-03-12 14.19.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3271648/236bfd5f-7df4-c38a-6ee5-300005a47893.png)

## 4-3. 補完機能の確認(@types/reactインストール<font color="red">後</font>)

[3. 解決方法](#3-解決方法)で述べたように、`@types/react`をインストールしたら補完が効くようになりました。
```console
> npm install --save @types/react
# または
> yarn add @types/react
```
package.jsonに追加されます。

```json:package.json
{
  "dependencies": {
    "@types/react": "^18.0.28",
  }
}
```

再度、以下を試してみてください。
+ buttonの開始タグ内に「onClick」と入力する。
+ Linkコンポーネントの開始タグ内に「prefetch」と入力する。

すると、補完候補が表示されるようになりました！
![スクリーンショット 2023-03-12 14.34.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3271648/e165926d-72e3-690d-c844-490630bf0df5.png)

![スクリーンショット 2023-03-12 14.33.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3271648/51415130-3116-bde1-cc9c-a31d86a4e370.png)

# 5. おわりに
どのパッケージが必要なのか、判断・理解できるようになるのは、まだまだ先になりそうです。。

以上です。
ChatGPTを使ってiOSサンプルアプリ作成

## 事前準備
openAIのアカウントを作成しておきます。

## APIKeyの発行
以下サイトにて 「Personal」→「View API keys」→「Create new secret key」を行い、`SECRET KEY`をコピーしてローカルにメモします。

https://platform.openai.com/ 

## OpenAISwiftの準備
Xcodeの「File」→「Add Packages...」→検索欄で「https://github.com/adamrushy/OpenAISwift 」を検索し「Add Package」します。


## ソースコード
先程、コピーした`SECRET KEY`は以下のOpenAISwift(authToken:)に設定します。

```swift
import UIKit
import OpenAISwift

class ViewController: UIViewController {

    @IBOutlet weak var aiTextView: UITextView!
    @IBOutlet weak var inputTextField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    private func chat() {
        Task {
            do {
                let chatMessages = [
                    ChatMessage(role: .system, content: "嬉しいときは語尾に「(嬉)」をつけます。楽しいときは語尾に「(楽)」をつけます。寂しいときは語尾に「(寂)」をつけます。不安なときは語尾に「(不安)」をつけます。驚いたときは語尾に「(驚き)」をつけます。"),
                    ChatMessage(role: .assistant, content: "私の名前はアイです。よろしくね！(嬉)"),
                    ChatMessage(role: .user, content: inputTextField.text ?? "")
                ]
                let answer = try await answer(from: chatMessages)
                print(answer)
                self.aiTextView.text = answer

            } catch {
                print(error)
            }
        }
    }

    private func answer(from chatMessages: [ChatMessage]) async throws -> String {
        let openAI = OpenAISwift(authToken: "SECRET KEY")
        let result = try await openAI.sendChat(with: chatMessages)

        return result.choices.first?.message.content ?? ""
    }

    @IBAction func send(_ sender: Any) {
        chat()
    }
}
```

## 動作確認
<img src= "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651213/4c4c4f33-9c7c-3a40-cc52-f0d022f745ee.gif" width=400px>




## 参考
[iOSアプリでサクッとChatGPT APIを利用する方法](https://dev.classmethod.jp/articles/ios-chatgpt-api-daccha/)
強化学習　～目次～

# はじめに

強化学習を中心に良記事と思われるURLを記載しました。
補足的な事項を記事として書いていこうと思います。

https://twitter.com/ogawa_yutaro_22/status/1399831931311644672

# 強化学習
- ゼロから作るDeep Learning④　強化学習編、斎藤 康毅
- Reinforcement Learning: An Introduction Second Edition、Richard S. Sutton、Andrew G. Barto
- [強化学習のコンセプト【テーブル形式の解法】](https://qiita.com/momo10/items/6af778491c508b25e8ef)
- [方策反復法は、なぜ最適方策に収束するの？](https://qiita.com/momo10/items/3191bbc9fec1b363ef31)
- [縮小写像の原理から見た強化学習](https://qiita.com/suikabar/items/2b2de1d274d27f8ba329)
- [Trust Region Policy Optimization: TRPO](https://horomary.hatenablog.com/entry/2020/08/21/001752)
- [Proximal Policy Optimization: PPO](https://horomary.hatenablog.com/entry/2020/10/18/225833#TRPO-KL%E5%88%B6%E7%B4%84%E4%BB%98%E3%81%8D%E6%9C%80%E5%A4%A7%E5%8C%96%E5%95%8F%E9%A1%8C%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AE%E6%96%B9%E7%AD%96%E6%9B%B4%E6%96%B0)


# 逆強化学習
- 機械学習スタートアップシリーズ Pythonで学ぶ強化学習 [改訂第2版] 入門から実践まで、久保隆宏
- [逆強化学習【線形計画】](https://qiita.com/momo10/items/aa0c1419151581c1f529)
- [逆強化学習【Maximum Entropy】](https://qiita.com/momo10/items/7faddbecdecdd7ab59b4)

# 模倣学習

- [Generative Adversarial Imitation Learning: GAIL](https://qiita.com/momo10/items/5e047d17561b082876b2)
- [Generative Adversarial Imitation Learning: GAIL](https://kyo-kutsuzawa.github.io/technical-note/gail.html)

# RLHF
- [Instruct GPTの仕組みについて](https://qiita.com/momo10/items/7c67748623185149b501)
- [https://qiita.com/momo10/items/cf2105f26676a416820a](https://qiita.com/momo10/items/cf2105f26676a416820a)

## GAN
- [GANに入門してみる](https://qiita.com/momo10/items/46e842beada6910c3836)
- [今さら聞けないGANの目的関数](https://qiita.com/typecprint/items/035478748a811dd29721)
- [WGANの実装](https://www.kaggle.com/code/rafat97/pytorch-wasserstein-gan-wgan/notebook)
AOJ DPL_1_I「Knapsack Problem with Limitations II」の解説

<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
<script type="text/x-mathjax-config">
 MathJax.Hub.Config({
 tex2jax: {
 inlineMath: [['$', '$'] ],
 displayMath: [ ['$$','$$'], ["\\[","\\]"] ]
 }
 });
</script>

AOJ の [組み合わせ最適化コース](https://onlinejudge.u-aizu.ac.jp/courses/library/7/DPL/1) の [個数制限付きナップザック問題 II](https://onlinejudge.u-aizu.ac.jp/courses/library/7/DPL/1/DPL_1_I) の解説が見当たらないため、以下に自分なりの解説を書いておきます。

## 問題
https://onlinejudge.u-aizu.ac.jp/courses/library/7/DPL/1/DPL_1_I

## 解説
### 着想
品物 $i$, $j$ について、品物 $i$ を $v_j$ 個増やす代わりに、品物 $j$ を $v_i$ 個減らす操作を考えます。
$v_i / w_i > v_j / w_j$ であれば、価値の総和を変えることなく ( $v_i v_j - v_j v_i =0$ )、重さの総和を減らす ($w_i v_j - w_j v_i <0$) ことができます。

本問題の最適解である、「価値の総和が最大となる品物の選び方」に対して、重さの総和を単調減少させるように、上記の操作を繰り返し行います。

操作を繰り返すと、各品物が以下の3通りのどれかを満たすように、最適解を変形できます。
- なるべく使う品物（可能な限り増やす）
- なるべく使わない品物（可能な限り減らす）
- 半端に使う品物（上記のどちらでもない）

ただし、「なるべく使う品物」「なるべく使わない品物」に関しては、操作の都合上、一度に品物を $v_{max}$ 個増やす・減らす操作を行うことを考えると、最大で $v_{max} - 1$ 個の余りが発生することが分かります。

また、「半端に使う品物」は最大1種類の品物となるよう調整します。そのために、$v_i / w_i = v_j / w_j$ を満たす品物 $i$, $j$ が存在する場合は、品物どうしに何らかの優先順位を持たせるものとします。

### 最適解の範囲

ここまでの情報をまとめると、最適解は以下の範囲に存在することが分かります。

各品物を使う個数を $k_i$ として、

- なるべく使う品物の場合
  - $\max(0, m_i - v_{max}) \le k_i \le m_i$
- なるべく使わない品物の場合
  - $0 \le k_i \le \min(m_i, v_{max})$
- 半端に使う品物の場合
  - $0 \le k_i \le m_i$

ただし、$v_i / w_i$ の値で比較したときに、
$ \lbrace なるべく使う品物 \rbrace \ge \lbrace 半端に使う品物 \rbrace \ge \lbrace なるべく使わない品物 \rbrace $
を満たすものとします。

### ２つの問題に分割

先ほどの最適解の各品物の個数 $k_i$ ですが、$p_i$, $q_i$ を下記のように定義して、$k_i = p_i + q_i$ を満たすように書き直します。

- なるべく使う品物の場合
  - $0 \le p_i \le \min(m_i, v_{max})$
  - $q_i = m_i - \min(m_i, v_{max})$
- なるべく使わない品物の場合
  - $0 \le p_i \le \min(m_i, v_{max})$
  - $q_i = 0$
- 半端に使う品物の場合
  - $0 \le p_i \le \min(m_i, v_{max})$
  - $0 \le q_i \le m_i - \min(m_i, v_{max})$

ここで、$p_i$ と $q_i$ をそれぞれ別の問題として考えます。

$p_i$ については、重さの最大値が $\Sigma_i w_i p_i$、最大個数が $\min(m_i, v_{max})$ である個数制限付きナップサック問題と同じ制約であることが分かります。また、$k_i$ が最適解であることから、$p_i$ もこの制約において価値の総和が最大となる選び方であると分かります。
（つまり、$p_i$ はこの制約の個数制限付きナップサック問題の最適解です。）

$q_i$ については、「半端に使う品物」を可能な限り使うことで、価値の総和を最大にできます。別の見方をすると、 全種類の $m_i - \min(m_i, v_{max})$ 個の品物に対して、重さの合計が $W - \Sigma_i w_i p_i$ を超えないように、$v_i / w_i$ の値が大きい順に貪欲法で選んだ結果とみなすことができます。

したがって、最適解の $\Sigma_{i} w_i p_i$ の値が分かっている場合、$p_i$ と $q_i$ についてそれぞれ解くことで、全体の最適解 $k_i = p_i + q_i$ を求めることができます。

### 実装

$p_i$ の個数制限付きナップサック問題の解き方ですが、価値の総和の最大値が $N \cdot (v_{max})^2$ と小さいため、スライド最小値を利用したDP（[蟻本](https://www.amazon.co.jp/dp/4839941068)の302ページに記載）で解くことができます。

このDPの定義は以下のようになります。

$$dp[n]:=価値の総和がn以上となるように選んだ時の重さの総和の最小値$$

上記の $dp[n]$ は $\Sigma_{i} w_i p_i$ と同義であり、$n$ の値を決めると $p_i$ に関する重さの総和の値が一意に定まることを示しています。また、$q_i$ に関する問題も、残る容量を $W-dp[n]$ として貪欲法で解くことができます。したがって、$n$ の値を決めると $p_i$,$q_i$ に関する問題の価値の和を求めることができます。

$0 \le n \le N \cdot (v_{max})^2$ の範囲で $n$ を変化させて価値の和の最大値を調べることで、最終的な答えを得ることができます。計算量はDPを求める部分がネックとなり、$O(N^2 \cdot (v_{max})^2)$ となります。

## 実装例
https://onlinejudge.u-aizu.ac.jp/solutions/problem/DPL_1_I/review/7163591/monolith/C++14
ローカルグループポリシーで設定した内容をエクスポートし、別の端末でインポートする方法


# 概要
ドメイン環境であれば複数の端末に同時にポリシーを設定することは容易です。
しかしながらワークグループ環境では、個々の端末で設定を行わねばならず工数がかかります。
また手動での操作となる為、設定ミスを起こすリスクが高まります。

OS 標準のツールではローカルグループ ポリシーで設定した内容をエクスポート並びにインポートする機能は含まれておりません。
しかしながら Microsoft Security Compliance Toolkit に含まれる LGPO.exe を使用することで設定したローカルグループ ポリシーの設定をエクスポート並びにインポート可能となりますのでで紹介いたします。

# LGPO.exe について

以前は単独で配布されていたツールのようですが、2023 年 3 月時点ではMicrosoft セキュリティ コンプライアンス ツールキットに含まれております。
設定されたポリシーのエクスポート並びにインポートは LGPO.exe 単独でできますがセキュリティ コンプライアンス ツールキットの概要についてまとめられたページも念のためリンクしておきます。

* [Microsoft セキュリティ コンプライアンス ツールキット 1.0 ガイド | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/security/threat-protection/windows-security-configuration-framework/security-compliance-toolkit-10)

また LGPO.exe 公開当時に機能についてまとめられたと思われる blog があります。
* [LGPO.exe - Local Group Policy Object Utility, v1.0 - Microsoft Community Hub](https://techcommunity.microsoft.com/t5/microsoft-security-baselines/lgpo-exe-local-group-policy-object-utility-v1-0/ba-p/701045)

# 入手先
LGPO.exe は下記より入手が可能です。
* [Download Microsoft Security Compliance Toolkit 1.0 from Official Microsoft Download Center](https://www.microsoft.com/en-us/download/details.aspx?id=55319)

必要なファイルは LGPO.zip のみです。

# 使用方法

エクスポート並びにインポートの手順は下記です。

## エクスポートの手順
1. LGPO.zip をダウンロードします。

1. ローカルポリシーが設定され、エクスポートを行いたい端末でダウンロードした LGPO.exe を任意のフォルダに展開します。

1. コマンド プロンプト を管理者として起動します。
<font color="red">管理者権限が必須です。</font>

1. 以下のコマンドを実行します

    ```
    LGPO /b エクスポート先パス
    ```

    例

    ```
    LGPO /b c:\temp
    ```

1. エクスポート先パスに新規にGUID 名が設定されたフォルダーが作成されますのでインポートをしたい端末へコピーします。


## インポートの手順

1. LGPO.zip をダウンロードします。

1. ローカルポリシーが設定され、インポートを行いたい端末でダウンロードした LGPO.exe を任意のフォルダに展開します。

1. コマンド プロンプト を管理者として起動します。
   <font color="Red">管理者権限が必須です。</font>

   以下どのようにインポートするのかによってコマンドが異なります。

   * 全ての設定を一括でインポートする場合

   ```
   LGPO /g コピーした GUID 名のフォルダのパス
   ```

   例

   ```
   LGPO /g C:\temp\{D8FDF82F-D498-44CA-97FB-088B1AB18CD1}
   ```

   * コンピュータの構成で設定したポリシーのみインポートする方法

   ```
   LGPO /m コピーした GUID 名のフォルダのパス配下の Machine 側の registry.pol
   ```

   例
   ```
   LGPO  /m C:\temp\{D8FDF82F-D498-44CA-97FB-088B1AB18CD1}\DomainSysvol\GPO\Machine\registry.pol
   ```

   * ユーザーの構成で設定したポリシーのみインポートする方法

   ```
   LGPO /u コピーした GUID 名のフォルダのパス配下の User 側の registry.pol
   ```

   ```
   LGPO /u C:\temp\{D8FDF82F-D498-44CA-97FB-088B1AB18CD1}\DomainSysvol\GPO\User\registry.pol
   ```
1. ローカル グループ ポリシー エディターやグループ ポリシーの管理にて設定がインポートされたことを確認します。

## インポート時の注意事項

インポート前の状態に戻す手順は特に用意されていないようです。
その為設定を行いたいポリシーのみを構成した端末を用意し、エクスポートを実施し、コンピューターの構成またはユーザーの構成いずれかの単位でインポートをすることが望ましいと思われます。

# 最後に
ワークグループ環境で多数の端末をポリシー設定をしなければならいない際には LGPO.exe は有益なツールだと思われます。
ただレジストリ操作に慣れ親しんでいる方はレジストリ設定のほうが楽かもしれませんので使い分けていただければと思います。
Generalized Real-World Super-Resolution through Adversarial Robustnessを読んでみた

# 初めに
2021年のICCVに投稿された" Generalized Real-World Super-Resolution through Adversarial Robustness"という論文について解説する．
[今回紹介する論文のURL](https://openaccess.thecvf.com/content/ICCV2021W/AIM/papers/Castillo_Generalized_Real-World_Super-Resolution_Through_Adversarial_Robustness_ICCVW_2021_paper.pdf "論文")，[GitHub](https://github.com/BCV-Uniandes/RSR "GitHub")

# 解説
![IMG_23D751A6EFE8-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3274897/e2ec6ede-fc7f-52c2-8f10-19d408e61c55.jpeg)

### どんなものか?
* 現在の超解像モデルが抱えている**実世界の低解像度画像に対して性能が低い**という問題に取り組んだ研究
* 既存の超解像モデルに**敵対的学習**を行うことで性能を向上させた

### 先行研究と比べて何がすごいのか?
* 既存モデルに敵対的学習を行うだけで，実世界の低解像度画像に対しての超解像性能を向上させた（つまりモデルの大きな変化などはない）
* 実世界の低解像度画像に似るよに作った人工的な画像に対しても超解像性能が向上した（これは割と当たり前）

### 技術の手法や肝は？
1. ESRGANの事前学習モデルを用意する
   [ESRGAN](https://openaccess.thecvf.com/content_ECCVW_2018/papers/11133/Wang_ESRGAN_Enhanced_Super-Resolution_Generative_Adversarial_Networks_ECCVW_2018_paper.pdf "ESRGAN")についてはいずれ解説するかも...？
2. 敵対的攻撃**PGD**を用いて敵対的サンプルを生成する（訓練に使用すると超解像性能が低下してしまうようなノイズの乗った画像）
3. 敵対的サンプルを用いて通常の訓練を行う
4. 2に戻る

このようにして訓練されたモデルを**RSR**と呼ぶ．

つまり，モデルにとって性能が低下してしまうような入力で訓練することでロバスト性を向上させている．例えるなら，毎日過酷な訓練を与え続け，多少のことでは動じないプロレスラーを育成していることと同じ．

### どうやって有効だと検証した？
* 実世界の低解像度画像と人工的に生成した低解像度画像の両方に定性・定量評価を行った
* 定量評価にはPSNR，SSIM，[LPIPS](https://richzhang.github.io/PerceptualSimilarity/"ESRGAN")を用いた


# 実験結果
### 人工的に生成した画像での評価
![IMG_AF744EBDED9C-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3274897/7295060c-4859-52b2-ccf1-cce395080fb3.jpeg)
* ImpressionismとESGAN-FSは実世界の低解像度画像に対して良い性能がある超解像モデルが，訓練データと検証データが一致している場合には性能が良いが，異なる場合には性能の低下が見られたことがわかる（上図の黄色い正方形で囲まれた部分）．
* 提案手法である**RSR**は訓練データと検証データが異なっているにも関わらず，性能の向上が見られた．具体的には，DIV2Kデータセットで訓練したRSRがAIMとNTIREという2つの検証データに対して性能が向上した．

### 実際の低解像度画像での評価
![IMG_011644333BC8-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3274897/441e233a-c4a7-5d40-7ddb-931bc4f6b3b0.jpeg)
* 先ほどと同様な結果が得られた
* ESRGANと比較すると明らかに向上している（**ESRGANに敵対的学習をしただけなのに**）．

### 定量評価
![IMG_20426C0CC338-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3274897/a91f28c7-06b4-af71-43ea-883669e3fd05.jpeg)
* PSNR，SSIMは大きほど良い値，LPIPSは小さいほど良い値
* 提案手法は，PSNR，SSIMが低下しているもののLPIPSが大幅に向上している
* PSNR，SSIMは超解像タスクにおいてあまり当てにならないことがよく知られてるためこれはすごく良い結果
AZURE リソース階層構造について超簡単に書いた

# はじめに

最近、AZ-900の資格取得に向けて学習をしています。
そこで自分の中でごちゃごちゃしているものリソース関連について超簡単に書きました。

# リソースの階層構造

階層の上から、管理グループ、サブスクリプション、リソースグループ、リソースとなっております。
上の階層の内容は継承されるようです。

　　　　管理グループ
　　　　　　↓
　　　サブスクリプション
　　　　　　↓
　　　リソースグループ
　　　　　　↓
　　　　リソース

なお、管理グループは複数のサブスクリプションをグループ化して、効率的な管理を実施するためのグループになります。

学習している中で、しばしばリソースグループってどこに位置しているんだっけ？と思っていたので、超簡単に書きました。
[AWS]SSLサーバー証明書の発行

# SSLとは?
SSLは、通信を暗号化して第三者が万が一盗聴しても内容をわからなくする技術です。よくURLで見かける「https://~」で始まるものがSSL通信に当たります。この暗号化通信を実現するのに、公開鍵方式が採用されています。

(公開鍵方式の詳細記事)

https://qiita.com/tumu1632/items/e7b5357f7c36939209d5

(SSL発行イメージ)
![メール-ページ3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790379/79e27c45-d980-b68c-70b8-df51ece73c41.jpeg)


# SSLサーバー証明書の発行手順
SSL証明書を発行し、ロードバランサーにリスナーを追加した後に、ブラウザでHTTPS通信ができることをAWSコンソール画面にて確認していきます。

![SSL証明書①.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790379/308801d7-afa2-4aa1-ca15-f9ecd3af9250.png)

![SSL証明書②.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790379/e362d4a1-79ee-e5f5-17b5-72d7ca754aac.png)
ドメイン名は、"www.ドメイン名"といったように、ロードバランサーの名前"www"をつけたドメインを入力する必要があります。検証方法は、Route53を使ってDNSサーバーを作成しているため、DNS検証を選択します。

完了したら作成したリクエストを選択し、"Route53でレコードを作成"をクリックし、そのまま"レコードを作成"をクリックします。これで、SSL証明書の発行は完了になります。証明書のステータスが発行済みになるのに、少し時間がかかるため完了するまで待ちます。

次は、ロードバランサーにHTTPS通信を待ち受けるリスナーを追加していきます。
![SSL AddListner.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790379/399ceeca-fb8c-aade-30ca-1182b28f9126.png)

![SSL AddListner②.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790379/3886c922-7a0c-5941-eb13-92dbb61ca3de.png)
ターゲットグループは、事前に作成した"sample-tg"を選択し、SSLは先ほど作成したものを選択します。これで、リスナーの追加は完了です。

# 動作確認
まずは、SSH通信でweb01とweb02に接続します。
```
$ ssh web01

$ ssh web02
```
それぞれをPythonでHTMLサーバーを立ち上げます。
```
$ python -m SimpleHTTPServer 3000
```
ターゲットグループよりステータスがhealthyになるまで、接続し続けます。healtyになったら、ブラウザより　"https://www.<ドメイン名>"　を入力して実際にindex.htmlの中身が表示されていれば、SSL通信ができています。

# 参考
AWSではじめるインフラ構築入門 翔泳社出版
GraphQLのバックエンド側の準備で詰まった時の話

# HOW TO GRAPHQL で起きた問題
最近、Androidアプリでサーバー側でGraphQLをもったAPIを使いたいと思い、GraphQLに入門しました。
そこで、[公式サイト](https://graphql.org/)のチュートリアル（HOW TO GRAPHQL）で、使うまでの準備を進めていました。
その時に理解するのに苦しんだ問題を、備忘録としてここに残します。後から同じ道をたどる人の一助になれば嬉しいです。

# getting started の Backend セクションにて
フロント側の準備を済ませ、バックエンド側の準備に入ろうとした時にその問題が現れました。
以下のコードの入力が求められるのですが、ターミナル上でうまく動きませんでした。
```terminal:$ .../hackernews-react-apollo
curl https://codeload.github.com/howtographql/react-apollo/tar.gz/starter |
 tar -xz --strip=1 react-apollo-starter/server

> tar.exe: Error opening archive: Failed to open '\\.\tape0'
```
出力文を見ると、tar部分でエラーが発生しているようでした。

# やったこと
これを解決するためには、Gitのインストールが必要でした。
Gitインストール時に、同時にインストールされる、GitBash内で同じコードを入力することで、先に進むことができました。
Gitのインストールは[こちら](https://git-scm.com/downloads)から最新バージョインをインストールすれば、問題ないと思います。
私が、今回問題解決できた一番の要因は、該当リポジトリに同じ問題に直面した[issue](https://github.com/howtographql/react-apollo/issues/85)のおかげでした。

今回は、GraphQLのチュートリアルで詰まった時の備忘録を残しました。同じように困っている人の一助になれればと思います。
PSVR2にREEFTOURERの水中ゴーグル用矯正レンズをつける

PSVR2を買いました。PSVR1からいまいちだった点が大幅に改良されており大変に良い体験ができるようになっています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431649/fe5e9c1d-7b25-8271-0658-bb76cabfcf2b.jpeg" alt="PSVR2" width=40% />


しかし、当方ド近眼。眼鏡なしではさっぱり見えません。
また、眼鏡をかけてPSVR2を使うと首を動かしたときなどに眼鏡のレンズとPSVR2のレンズが接触していずれはレンズに引っかき傷ができてしまいそうな不安があります。

PSVR2用の矯正レンズとしては以下のようなものがあるようですが、

https://www.vr-rock.com/ja/products/psvr2-prescription-lens

https://twitter.com/SHOP23527410/status/1628637554424840193

8000円～1万円程度かかるようです。(眼鏡の値段としては妥当だと思います)　また、正確な度数の指定が必要なので、通販で届いたもののもし度数が合わなかった場合無駄になります。眼鏡屋さんで対面でちゃんとした測定器を使ってPSVR2などのVRゴーグル用の矯正レンズを作ってくれるようになればいいのですが。([PICO4用はJINS!でそういうサービスがある](https://www.jins.com/jp/collabo/pico/))　（と思ったら通販のみみたいなので視力測定は眼科か眼鏡屋さんでやらないとダメでした)

なので、以前PSVR1やOcurus Quest2でも使っていたリーフツアラーの水中ゴーグル用強制レンズを使うことにしました。

https://www.amazon.co.jp/dp/B01AJDQ3T4

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431649/ec51faca-46b1-3f8b-0290-fd924c51db6f.jpeg" alt="リーフツアラーのレンズ" width=40% />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431649/5df2e9f0-3f73-b655-1c75-d0aa3467f79b.jpeg" alt="リーフツアラーのゴーグル用フレーム" width=40% />


リーフツアラーの水中ゴーグル用フレームにとりつけた状態でもPSVR2のゴーグルの中に入れてそれなりに使えましたが、PSVR2はPSVR1やQuest2よりもゴーグル部の中が広く、リーフツアラーのフレームのつっぱり部分のテンションがかからず固定にやや難ありというところです。どうしようかなぁ、thingiverseあたりにPSVR2関連でだれかなんか作ってないか？と探していたところ、PSVR2のレンズ用のプロテクタ(外枠)のデータがありました。

https://www.thingiverse.com/thing:5873811

これを流用すれば、リーフツアラーのレンズが付くのでは？と作ってみました。

https://www.thingiverse.com/thing:5905245

![PSVR2_ReefTourerLensAdapter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431649/2b0014e1-e894-a294-b7b2-49c0b4b2b454.png)

デザインのポイントとしては視線トラック用のIRカメラの光源？らしきレンズ周辺のIR LEDの発光部？のところにフレームがなるべくかぶらないような配置をした点です。(それでも片側1つのLEDが隠れてしまっていますが) 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431649/9d9c9216-5397-c53b-0871-0de35257b16b.jpeg" alt="リーフツアラーのレンズをはめた状態" width=50% />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431649/06ce03a2-99d3-bf04-743b-a45bd6c7edcd.jpeg" alt="PSVR2のレンズにはめた状態" width=50% />

鼻の近くのフレームが若干見えるのですこし気にはなるものの、近視眼鏡をかけずにPSVR2の映像をきれいに見ることができました。眼鏡なしでのプレイ体験はなかなか良いものです。

完成に至るまでの試作品の屍
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431649/7385d15e-1ce3-7820-b3ad-a3cb836a5e14.jpeg" alt="試作品の屍" width=40% />
タイピングを上達させるための方法

エンジニアにとってタイピングは切っても切れないものですよね。
タイピングが上達するための方法について書いてみたいと思います。

# 1. 結論
ひたすら練習します。

...落ち着いてください、もう少し真面目に書きます。

# 2. 具体的には
その前に、タイピングとは以下の2つであると思っています。
どちらも大切な要素です。

　・　正確さ

　・　速さ

今すぐに上達する方法は残念ながら無いのですが、近道をする方法はあります。

## 2-1. タッチタイピング
キーボードではなく、画面を見てタイプすることです。
画面を見ると入力した文字がもちろん表示されていますので、ミスタイプに気づきやすくなります。
また、画面を見るということは、キーボード⇄画面の目線移動が無くなりますので、
疲れにくくなる上に速さに繋がります。

正確さについては、正直気をつけていただくしかないと思っています。
ミスタイプが減ると、速さにもつながりますしストレスも減ります。
そのため速く入力することも大切ですが、それでミスタイプが頻発しては元も子もないのでお気をつけくださいね。

## 2-2. ホームポジション
上記のタッチタイピングと組み合わさるものです。

皆様は普段タイピングをする時に、指を何本使用しているでしょうか？
速く入力するためには、持っている指を全て使用した方が当然良いです。
ホームポジションは指の基本となる配置のことです。
多くのキーボードのFキーとJキーには突起がついています。
タッチタイピングをされる方は、この突起を頼りにしてホームポジションを保っています。

また、一般的に、どのキーをどの指で打つかということが決まっています。
ここでは図と説明を省略しますが、練習をするためのサイトがありますのでご紹介します。

[ひよこでも出来るタイピング練習講座](https://typing.twi1.me/training)

自分なりの入力方法が身についていると、中々変えることは難しいですよね。
ただ、指を全部使用することは指にかかる負担を分散させることにもなり、そこからも速さに繋がりますので、お時間があれば練習してみても良いのかなと思います。

## 2-3. 運指の最適化
発展的・マニアックな内容です。
大変細かい話なので、高みを目指したい方だけお読みいただければと思います。

タイピングをしていると、「この単語入力ではこのキーはこの指で打った方が良いな」と感じる時があります。

例えば「安寧」という単語を入力するとします。
おそらく`annnei`と入力するかと思いますが、これを`axnnei`とします。
実は`ん`は`xn`でも入力することができるのですが、入力キー数は変わらないものの、`n`の入力回数が1つ減ったことがわかります。
これにより指の負担を分散させるだけではなく、ミスタイプの可能性を下げることができます。

また、別の例で「湯葉」（ `yuba` ）という単語を入力するとします。
`y`は左・右どちらの手でも入力できる位置にありますが、右手の人差し指で打ちます。
そして次の`u`を右手の中指で打ちます。
すると`y,u,b,a`をそれぞれ別の指で打つことができます。　（`y`右人,`u`右中,`b`左人,`a`左小）
`y`と`b`を同じ指で入力しなくなりますので、指の負担軽減およびタイプの速さに繋がります。

2つ例を挙げましたが、運指の最適化に終わりはありません。
少しでもタイプの正確さと速さを上げるためには、より良い指の使い方を意識すると良いかもしれません。

# 3. おすすめの練習サイト
・　[マイタイピング](https://typing.twi1.me/)
先ほどご紹介したサイトと同じです。
圧倒的に多くのお題があり、自分でもお題の作成ができることが特徴です。

・　[寿司打](https://sushida.net/play.html?soundless)
エンジニアの方たちで知らない方は少ないと思いますが、ゲームのような感じで親しみやすいことが特徴です。（お寿司食べたい）

・　[タイピング速度測定](https://typing.tanonews.com/)
その名の通り、入力速度を評価することに重きを置いていることが特徴です。

・　[Typing Tube](https://typing-tube.net/)
YouTubeにある曲動画を流しながら、その歌詞を入力することが特徴です。

・　[Weather Typing](https://denasu.com/software/weathertyping.html)
サイトではなくソフトですが、人間やCPUと対戦できることが特徴です。

# 4. 最後に
タイピングが上達するためには、とにかく練習するしかありません。
たくさん練習すれば速く入力できるようになります。
ただ、正確さは意識しないと改善されませんので気をつけてみてくださいね。

何か少しでも皆様の参考になれば幸いです。
練習お互いに頑張りましょう。
_vimrc on windows

色スキームは[molokai](https://github.com/tomasr/molokai)
プラグイン管理は[vim -plug](https://github.com/junegunn/vim-plug)
入れるプラグインは[lightline.vim](https://github.com/itchyny/lightline.vim)

molokai.vimは"C:\Program Files (x86)\Vim\vim90\colors\molokai.vim"へ
vim-plugは$HOME/vimfiles/autoload/plug.vimへ
まずは以下の_vimrcを$HOME直下に作成する
``` Bash:_vimrc
call plug#begin()

Plug 'itchyny/lightline.vim'

call plug#end()

set encoding=utf-8
scriptencoding utf-8

set whichwrap=b,s,h,l,<,>,[,],~ " カーソルの左右移動で行末から次の行の行頭への移動が可能になる
set number " 行番号を表示
"set cursorline " カーソルラインをハイライト

inoremap <silent> jj <ESC> 
" jjをescに割り当てる
noremap ;; :
";;でコマンドモードに移行

" 行末まで移動可能
set virtualedit=onemore
"smartindentの設定
set smartindent
" ビープ音を可視化
set visualbell
" 対応する括弧の強調表示
set showmatch
" シンタックスハイライトの有効化
syntax on
" シンタックスハイライトのテーマ設定
colorscheme  molokai
"ステータスラインの有効化
set laststatus=2
" ステータスラインのテーマ設定
let g:lightline = { 'colorscheme': 'molokai' }

" マウス操作の有効化 & ホイール操作の有効化
set mouse=a
set ttymouse=xterm2

"バックスペースキーで行頭を削除する
set backspace=indent,eol,start
"改行後に「Backspace」キーを押すと上行末尾の文字を1文字消す
set backspace=2
"use english
let $LANG = "en"
"use clipboard when yanked
set clipboard+=unnamed
```
保存後リロードしてvim内で以下のコマンドを実行する
```
:PlugInstall
```
Googleデジタルマーケティング＆Eコマース：Google広告の入札戦略

# はじめに

”Googleデジタルマーケティング＆Eコマース プロフェッショナル認定証"　の受講が完了しました(2022/3/3)。私がこのコースから得られた素晴らしい体験を、テーマごとに分割して、わかりやすくご紹介しています。興味を持たれた方は、是非下記を受講してみてください。

https://jp.coursera.org/professional-certificates/google-digital-marketing-ecommerce

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/84e33f4e-81cb-98a6-4546-f2ec06fd8b8b.png" width="800">

# 入札戦略とは？

Google広告のキャンペーンには必ず入札戦略が必要であり、正しい戦略を決定することがGoogle広告を使ったビジネスキャンペーンを成功させる鍵となります。


- 最も基本的な入札戦略は、手動CPC（Cost Per Click）です。手動CPC入札では、広告のクリック単価の上限を自分で設定します。
- 自動入札では、Google Adsが広告のクリック率やコンバージョン率に基づいて自動的に入札価格を設定し、特定の目標を達成することができます。

# 自動入札戦略のサブセット

自動入札戦略では、機械学習を使用して、各入札でコンバージョンまたはコンバージョン価値を最適化し、ユーザーのデバイス、場所、時間帯、リマーケティングリスト、言語、およびオペレーティングシステムなどの幅広いオークション時のシグナルを考慮します。

つまり、これらの要素とすべての検索の文脈に基づいて、入札戦略は自動的に入札の可否と入札額を決定するのです。

# 入札戦略の種類

| 戦略名  | 定義  | 目標 |  
| :--- | :--- | :--- |  
| Maximize conversion value | 高度な機械学習を用いて自動的に入札額を最適化し、設定するものです。また、各オークションに合わせた入札を行うオークションタイム入札機能も備えています。 | Increase business value |  
| Target ROAS | コンバージョン価値を最大化するためのオプションターゲットです。この入札戦略は、広告している製品やサービスをユーザーが検索するたびに、潜在的なコンバージョン価値を分析し、インテリジェントに予測します。そして、これらの検索に対する入札を自動的に調整し、そのリターンを最大化します。理想的には、入札戦略によってユーザーの検索が高い価値を持つコンバージョンを生み出す可能性があると判断された場合、Target ROASはその検索に対して高い入札を行うことを意味します。 | Increase business value |  
| Maximize conversions | 予算内でキャンペーンに最も多くのコンバージョンを獲得できるよう、自動的に入札を設定します。   | Increase sales or leads  |  
| Maximize clicks | 予算内でできるだけ多くのクリックを獲得できるように入札額を設定します。 | Increase website visitors  |  
| Target CPA | コンバージョンを最大化するためのオプションのターゲットです。この入札戦略では、できるだけ多くのコンバージョン（顧客の行動）を獲得できるように入札を設定します。ターゲットCPA（ターゲットコストパーアクション）入札戦略を作成する際に、各コンバージョンに対して支払いたい平均コストを設定します。  |  Increase sales or leads |  
| Target impression share | 広告を表示する場所によって3つのオプションがあります：ページの絶対上部、ページの上部、またはGoogle検索結果のページ内の任意の場所です。Google広告は、プレースメント設定に基づき、広告を表示するための入札を自動的に設定します。 | Increase awareness and visibility  |  
| Cost per 1000 impressions (CPM) | YouTubeやGoogleディスプレイネットワークでのインプレッション数（広告が表示された回数）に応じて支払いが行われます。 | Increase awareness and visibility  |  
| Cost per view (CPV) | oogle Adsの動画広告に支払う金額を設定するためのデフォルトの入札戦略です。CPV入札では、動画の視聴やインタラクションに対して支払いが行われます。 | Increase awareness and visibility  |  


# 入札戦略の選択

キャンペーンを作成している間、Google広告はキャンペーンの目標を決定するための一連の質問をすることで、入札戦略を選択するようガイドします。これは、特定の入札戦略についてよく知らない場合に便利です。

しかし、Webサイトでは、入札戦略を直接選択するオプションが用意されています。一度選択すると、ユーザーはドロップダウンメニューから特定の入札戦略を選択することができます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/e3e240a5-de21-cd5e-0d1d-9ed572f67d40.png" width="700">
SwiftでTDD写経　第三章　三角測量


注意：TDD勉強会会用の資料です。
殴り書きしてあとで清書していくので投稿段階では綺麗ではありません。


```playground.swift
var money = MoneyTest()

money.TestMultiplication()
money.TestEquality()
class MoneyTest{
    init(){}
    
    func TestMultiplication(){
        var five = Dollar(5)
        var Product:Dollar = five.times(2);
        print(Product.amount)
        Product = five.times(3);
        print(Product.amount)
    }

    func TestEquality(){
        assert(Dollar(5).equals(Dollar(5)))
        assert(Dollar(6).equals(Dollar(6)))
    }
}

class Dollar  {

    var amount:Int
    
    init(_ amount:Int){
        self.amount = amount
    }
    
    func times(_ multiplire:Int)  -> Dollar{
        return Dollar(self.amount * multiplire)
    }
    
    func equals(_ Object:Any) -> Bool{
    var dollar:Self = Object as! Self
        return dollar.amount == self.amount
    }
}
```
misskeyのオブジェクトストレージにcloudflare r2を利用する

# R2を使う

R2を使うメリットとしては、

- 無料枠が存在する
  - 10GB まで無料,通信料金がある一定まで無料
- 初期投資しなくて良い
- cloudflareに紐づけているドメインと連携がしやすい

   辺りが挙げられるかと思います。個人運用してみたいけど、初期投資にお金掛けたくない方に向いていると思います。

詳細な料金設定などは最新のドキュメントをご覧ください。
https://www.cloudflare.com/ja-jp/products/r2/


##  必要なもの
- Cloudflareのアカウント
  - クレジットカード紐づけ
- misskeyインスタンス


##  手順

### 1. バケットの作成

Cloudflareのアカウントに作成し、サイドメニューからR2を選択します。
そこからCreate Bucketを押してください。
![](https://scrapbox.io/files/63e305e1a52122001b2ffb68.png)

### バケット名の指定
Bucket名を指定します。　特に何でも構いません。

![](https://scrapbox.io/files/63e3e33191a07c001cfa5dd8.png)

#### バケットのアクセス方法

Sttingsにアクセスすると、バケットの詳細な情報が記載されています。

Public Bucket URLを有効にしておきましょう。　設定にはPublic Bucket URLとS3 APIを使用します。

![](https://scrapbox.io/files/63e3e7695fa2f7001b3031c9.png)


### 2. R2 APIのTOKEN取得

R2のダッシュボードから、Manage R2 API Tokensをクリックします。

![](https://scrapbox.io/files/63e3e969ba3ee0001be86dc8.png)

Permissionから Read -> Editに変更します。
TTLやIPフィルタリングは各自環境に合わせて設定してください。

![](https://scrapbox.io/files/63e3e9904da750001ccd9550.png)

Access Key IDとSecret Access Keyが表示されます。使用するので控えておきましょう。
閉じると再度表示できなくなるので注意してください。

![](https://scrapbox.io/files/63e3e9ecab94f7001cb17cdd.png)


### 3. misskey側の設定

R2の情報を入力してアクセス出来るようにします。

	Base URL:  SettingsにあるPublic Bucket URL
		(最後に/は入れないでください)
	Bucket: バケット名
	prefix: 何でも可
	Endpoint: SettingsにあるS3 APIのFQDN
		(https:// と /<バケット名>は削除)
	Resion: us-east-1
	Access Key: 生成したAPI TokenのAccess Key ID
	Secret Key: 上記のSecret Access Key

![](https://scrapbox.io/files/63e3eac84d781b001b27caf7.png)

:::note warn
追記：2023/7/6現在、region指定を"us-east-1"、proxyを切らないと動かないというコメントをいただきました。すぐに確認は出来ていないのですが、ご報告までに。
https://twitter.com/msg_quail/status/1676662967264497665?s=20
:::

### 4. 反映されているか確認 

ドライブから画像アップロードしてみましょう。　画像がボケて表示されなければ設定出来ています。

もし、出来ていなければ、画像を見つつ、設定を見直してみてください。
最悪、バケット作り直してみてください。

![](https://scrapbox.io/files/63e3ec27e5f155001b893539.png)
初LeetCode

こんにちは！
昨日初コーディング面接で、惨敗した者です😂
しっかりとコーディング対策は必要だなぁと痛感したので、
LeetCodeを始めることにしました！

## なぜLeetCode?
下記3点の理由でLeetCodeを選びました！
- UI/UXが好み
- 問題を選ぶときのソートが使いやすい
- 英語の勉強にもなる

## さっそく1問解いてみた
No1の「Two Sum」を選び、30分ぐらいで解けました・・・

問題↓
https://leetcode.com/problems/two-sum/

解いた後は
Submission DetailにRuntimeとMemoryUsageが書かれている
また、グラフ化されているので分かりやすいですね😊
![スクリーンショット 2023-03-12 12.41.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/587a2dc6-34c1-7fb3-6434-b5ca63409bb7.png)

他にも、RuntimeとMemoryUsageが速い人？（いいコードを書いてる人）の、
コードも見れ参考になりますし、
コードについてもdiscussionできるみたいです！

地道に頑張ります :)

では！
外部キー

# 外部キーとは
>The relationship between customers table and orders table is one-to-many. And this relationship is established by the foreign key in the orders table specified by the customerNumber column.

# 出典
https://www.mysqltutorial.org/mysql-foreign-key/#:~:text=The%20relationship%20between%20customers%20table%20and%20orders%20table%20is%20one%2Dto%2Dmany.%20And%20this%20relationship%20is%20established%20by%20the%20foreign%20key%20in%20the%20orders%20table%20specified%20by%20the%20customerNumber%20column.

# 訳
顧客テーブルと受注テーブルの関係は、一対多である。そして、この関係は、customerNumber列で指定されたordersテーブルの外部キーによって確立されている。
出典　deepL

>MySQL supports foreign keys, which permit cross-referencing related data across tables, and foreign key constraints, which help keep the related data consistent.
>A foreign key relationship involves a parent table that holds the initial column values, and a child table with column values that reference the parent column values. A foreign key constraint is defined on the child table.

# 出典
https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html#:~:text=MySQL%20supports%20foreign%20keys,on%20the%20child%20table.

# 訳
MySQL は、テーブル間で関連するデータの相互参照を可能にする外部キーと、関連するデータの一貫性を保つための外部キー制約をサポートしています。

外部キー関係には、最初のカラム値を保持する親テーブルと、親カラム値を参照するカラム値を保持する子テーブルが含まれます。子テーブルには、外部キー制約が定義されています。
出典 deepL

# 感想
関係を確立させるために外部キーを設定するのか。
何となく知っていたけど、改めて理解した気がする。
まだ自信がない。
HTTP/2、CORS、IPFS を活用して個人スケールで大容量の地理空間情報をホストする

個人スケールで大容量の地理空間情報をホストするために有望な3つの要素である HTTP/2、CORS、IPFS と、それらを用いるのに便利な nginxの概要、および個人スケールで大容量の地理空間情報をホストすることの社会的インパクトについてのまとめを、ChatGPT の支援を得て行ってみました。

# 3つの要素
## HTTP/2
Webサイトの読み込み速度を向上させるためのプロトコルです。Webサイトのデータ転送が高速で効率的に行われるため、地理空間情報を含む大量のデータをホストするためには重要な要素となります。特に、ベクトルタイル、COPC、COGなどのクラウド最適化フォーマットではデータがストリームされるので、HTTP/2による増速効果が高いように思います。

## CORS
Cross-Origin Resource Sharingの略で、異なるドメイン間でのリソース共有を制御する仕組みです。異なるドメインからのアクセスを許可するために必要な設定となります。

## IPFS
InterPlanetary File Systemの略で、P2Pネットワークを使用して分散型ファイル共有システムを実現する技術です。ここでは、地理空間情報を分散してホストするために使用します。

# nginx

nginxは、高速で軽量なWebサーバーソフトウェアであり、リバースプロキシ、負荷分散、キャッシュ、SSL/TLS暗号化などの機能を持っています。nginxは、HTTP/2とCORSの設定を簡単に行うことができます。

また、nginxは、Raspberry Pi OSで簡単にインストールできるので、UNVT Portable など Raspberry Piベースの技術と相性が良いです。

# 社会的インパクト:

個人スケールでも大量の地理空間情報をホストできるようになった場合、民間や学術的な地理情報システムの構築・運用において、大企業や研究機関に依存する必要がなくなってきます。

地理空間情報を分散してホストすることで、ネットワーク上の負荷やセキュリティ上のリスクを分散することができるため、より信頼性の高い地理情報システムの構築が可能になってきます。確かに、中央のサーバが落ちると機能しなくなるサービスというのは、現状多いです。サービスの信頼性を向上し、SNSか、さらに望ましいところでは携帯電話程度までの信頼性を持たせることができると、世の中からの期待が変わってくるように思います。

IPFSの使用により、インターネット上での情報共有において中央集権化の問題を解決することができ、より分散化された、自律的な情報共有システムの構築が可能になります。
これだけは意識して..!! 高凝集/低結合

## はじめに
たくさんの原則を覚えるのは大変だけど、これは常に意識して欲しい！
と先輩から助言をいただきました。メモになります。

### 凝集度と結合度とは
- ソフトウェアの品質を示す指標（メトリクス）

### 高凝集／低結合にするメリット
- 理解容易性：コードを読んで理解しやすくなる
- 拡張性：コードを修正、拡張しやすくなる
- 信頼性：修正時にバグを埋めにくくなる
- 再利用性：同じコードを別の場所で再利用しやすくなる
- テスト容易性：テストが実施しやすくなる

### 凝集度とは
- モジュール内の要素同士がどれだけ関連しているかを示す指標
- クラスの責務、そのクラスのメソッドとデータ関連（属性）の強さ
- 高い方が良い

保守を考えたとき、ひとつの関数の中で、様々な機能が混ざり合うことは好ましくない。機能分割されて、機能と関数が１対１になっている方が理解しやすく、修正の際に他の部分に悪い影響を与える機会が減る。

### 結合度とは
- モジュール同士の依存度の高さを示す指標
- 依存度が高い→依存先の修正の影響を受けやすくなる
- 低い方が良い

呼び出し関係にあるメソッドの結び付きの強さを表す指標。結合度が高くなると複数のクラスで依存度が上がってしまうため、保守やメンテナンス、仕様変更などの対応がしづらくなる。また、設計的な観点からしても、複雑で分かりづらくなってしまう。
SwiftでTDD写経　第六章　テスト不足に気づいたら

まず継承を検討する。
Dollarを親とし、Fracを子クラスにすると考えた。
しかし、実際はこれはコードを削減にはつながらない。
（てか個人的にはむしろこの発想がやべぇ。普通しない）

次にMoneyという親クラスを検討する。
これは少し時間がかかるが、非常にうまくいく。

なお、SwiftにはJavaのprotectedのようなものはない！！！
（aaaaa!罪を贖えぬ！！！！！

本書には共通メソッド、共通プロパティ親クラスに移す手順が書かれている。
コピペしているわけだから、共通プロパティはamount、メソッドはequalメソッドとすぐわかる。
ちょっとjavaと書き方変わるけど,swiftだとこんな感じですかね。


```playground.swift

var moneytest = MoneyTest()

moneytest.TestMultiplication()
moneytest.TestEquality()
moneytest.TestFrancMultiplication()

class MoneyTest{
    init(){}

    func TestMultiplication(){
        var five = Dollar(5)
        assert(Dollar(10) == five.times(2))
        assert(Dollar(15) == five.times(3))
    }

    func TestEquality(){
        assert(Dollar(5) == Dollar(5))
        assert(Dollar(6) == Dollar(6))
        assert(Franc(5) == Franc(5))
        assert(Franc(6) == Franc(6))
    }
    
    func TestFrancMultiplication(){
        var five = Franc(5)
        assert(Franc(10) == five.times(2))
        assert(Franc(15) == five.times(3))
    }
}
///親クラス
class Money :Equatable{
    var amount:Int
    init(_ amount:Int){
        self.amount = amount
    }
    static func == (lhs: Money, rhs: Money) -> Bool {
        return lhs.amount == rhs.amount
    }
}

///Dollar子クラス
class Dollar:Money {
    override init(_ amount:Int){
        super.init(_ :amount)
        self.amount = amount
    }
    
    func times(_ multiplire:Int)  -> Dollar{
        return Dollar(amount * multiplire)
    }
}

///Franc子クラス
class Franc:Money {
    override init(_ amount:Int){
        super.init(_ :amount)
        self.amount = amount
    }
    
    func times(_ multiplire:Int)  -> Franc{
        return Franc(amount * multiplire)
    }
}


```