OmniAICreator/Qiita-1.07M huggingface dataset:
SOLID原則とは

SOLID原則について学習しましたのでアプトプットもかねて載せます。

# SOLID原則とは
オブジェクト指向プログラミングにおいて、柔軟性、保守性の高いソフトウェアを設計するための５つの原則の頭文字をとったマクロニム（略語）です。

5つの原則
1 単一責任の原則
2 オープンクローズドの原則
3 リスコフの置換原則
4 インターフェース分離の原則
5 依存性逆転の原則

↑の５つの原則を具体的にコードを交えて説明します。
今回は1 単一責任の原則について記述します。

## 1 単一責任の原則(SPR)
単一責任の原則はクラスやモジュールが一つの責任を持つべき、という原則です。これにより、クラスが特定の機能や役割に集中し、変更や修正が必要となったときに、その責任範囲のみが修正できるようになります。これにより、コードの理解やメンテナンスが楽になります。

悪い例
```
class Animal
{
    public function createAnimal($name, $species, $age)
    {
        // 動物をデータベースに保存する処理
    }

    public function displayAnimalInformation($animalId)
    {
        // 動物の情報を取得して表示する処理
    }

    public function feedAnimal($animalId)
    {
        // 動物にエサを与える処理
    }

    public function updateAnimal($animalId, $name, $species, $age)
    {
        // 動物の情報を更新する処理
    }

    public function deleteAnimal($animalId)
    {
        // 動物の情報を削除する処理
    }
}
```
SPR化したコード↓
```
class Animal
{
    public function createAnimal($name, $species, $age)
    {
        // 動物をデータベースに保存する処理
    }

    public function updateAnimal($animalId, $name, $species, $age)
    {
        // 動物の情報を更新する処理
    }

    public function deleteAnimal($animalId)
    {
        // 動物の情報を削除する処理
    }
}

class AnimalInformation
{
    public function displayAnimalInformation($animalId)
    {
        // 動物の情報を取得して表示する処理
    }
}

class AnimalFeeding
{
    public function feedAnimal($animalId)
    {
        // 動物にエサを与える処理
    }
}
```
改善後の例では、Animalクラスが動物の作成、更新、削除といった動物に関連する情報を処理する責任を持ちます。AnimalInformationクラスは動物の情報を取得して表示する責任を持ち、AnimalFeedingクラスは動物にエサを与える責任を持っています。これにより、各クラスはそれぞれ特定の責任に集中し、クラスの理解と変更が容易になります。

#### 簡単に単一責任の原則をまとめるとクラスの中でコードが増えた場合に他のクラスに分散させるイメージです。
↓

しかし、ここである不安が私はありました。
↓

#### しかし、ファイルが（クラス）が増えることによって処理が重くなったり、サーバー側の負担が増えるんじゃないですか？
#### 結論:リソースの消費やサーバー側の負担はそれほどありません

1 メモリの消費 
クラス数が増えることによってメモリの読み込まれるファイルが増えます。しかし、現代のコンピューターのメモリ容量が大きいため、ほとんど変わらない。またファイルがインスタンス化された時点でのみメモリに読み込まれるため、アプリのメモリ使用量はそれほど変わらない。

2 ディスクの使用量
クラスが増えるとアプリのディスク上のファイル数も増えます。しかし、一般的にソースファイルは非常に小さいファイルなのでアプリ全体のディスク使用量に与える影響はほとんどない。

3 ビルド時間
クラスが増えるとビルド時間がわずかに増加します。ただし、ビルドツールやキャッシュの効率化によってこの増加は最小限に抑えられる。

ですのでクラス数が増えることによって処理が重くなったりすることはほとんどありません。
ですので私は積極的に使っていきたいと思います。

以上になります。ありがとうございました。
【ChatGPT無】の不可解現象。報告（のちに2023/08/17、出なくなった）

:::note info
本記事は、ChatGPT（無料版）で
行なっております。GPT4での確認
はできておりません。あしからず。
:::

　どうも、カーブミラーです。
　　連日、とても暑いですね。
　　　私もへばっています。
　　　　みなさんも、
　　　　　熱中症にご注意を。

　下記も参照して
　　気を付けましょう。

[【ChatGPT無】に尋ねた、熱中症。](https://qiita.com/kabumira/items/3f9a274ecd97764484a0)

[夜間熱中症という言葉を知っていますか？](https://qiita.com/kabumira/items/53882dc9ba37f6502432)

[スマホ熱中症にご注意を。Bingも含む。](https://qiita.com/kabumira/items/8df2074dbe5280612236)
***
　今回は、
　　ChatGPTさんの
　　　ちょっと不可解な現象に
　　　　出会いました。

　状況は、
　　Androidアプリでの
　　　ChatGPTさんとの
　　　　チャットで発生しました。

　以下に
　　NewChatのはじめからを
　　　載せます。

　最初は、
　　ロジカルシンキングについて
　　　尋ねています。
```Text:不可解
（セッション開始）
User
ロジカルシンキングって何？

ChatGPT
ロジカルシンキングは、論理的思考とも呼ばれ、合理的かつ論理的に問題を分析し、解決する能力です。情報を整理し、因果関係を理解し、論理的な結論を導くことが重要です。それにより、効果的な意思決定や問題解決が可能になります。



（ここから）
User
今日は何日？

ChatGPT
今日は2023年7月30日です。




User
あれ、なんでわかるの？

ChatGPT
私はOpenAIが提供するChatGPTという人工知能のモデルです。しかし、私はインターネットにアクセスすることはできず、私が訓練された範囲内の情報しか持ちません。私の知識は2021年9月までで更新されていない可能性がありますので、最新の情報は持っていないことをご理解ください。今日の日付については、ユーザーからの前回の入力を参照しています。
```
　セッション開始から
　　日付の入力は、
　　　行なっていません。

　ならば、
　　何を参考にしている？

　その後、
　　いろいろと
　　　尋ねてみますが、
>セッションの開始時刻や履歴については知識として持っていません。

　　　　という答え。

　今日のことを尋ねたのも
　　たんなる気まぐれです。

　わからんです。フニャ。
***
　NewChatして、
　　そこでも、尋ねてみました。

```Text:答え？
User
今日は、何日？

ChatGPT
今日は2023年7月30日です。




User
その答えは、どこから得ましたか？　教えてください。

ChatGPT
私は2021年9月までの情報で訓練されたAIです。そのため、知識は2021年9月までのものに限られています。今の日付はシステムが提供する情報ではなく、最初にプロンプトに表示された日付を基準にしています。申し訳ありませんが、私自身で現在の日付を取得する機能は持っていません。
```
　ムムム、
　　「最初にプロンプトに
　　　表示された日付を
　　　　基準にしています」
　　　　　ですと。

　ということは、
　　アプリ側で、
　　　隠しプロンプト的な
　　　　情報のやり取りがある？

　Web版でも
　　やってみました。

　こちらでも、
　　正しい日付が
　　　表示されます。
　　　　アプリ側ではなく、
　　　　　システム側での
　　　　　　改良かしら？

　悪くない改良、
　　と思うことにしましょうか。
***
　本日（2023/08/17）、
　　こういうのを知っていますか？
　　　と、やってもらったら、
　　　　出なくなっていました。

　残念です。
【写経】Pythonでカウントダウンタイマー

# サマリ
ネットの記事を参考にPythonで超シンプルなカウントダウンタイマーを書きました。
（本当に基本的な内容なのでご容赦ください）

# 背景
Pythonの学習を始めたので、慣れるために超シンプルなプログラムを書いてみようということでやってみました。
（＋月一投稿を何とか維持するため。。（おい））

# ゴール
- Pythonプログラムで10→0までカウントダウンするプログラムを書き、実行する。
- コマンドライン上に秒数がカウントダウンされていることを確認する。

# 対象読者
- Python勉強したての方
- 自分（備忘のため）

# 前提
必須：PC、エディタ、Python
推奨：Pythonの基本的な知識
# 環境
- ホストOS：Window10 Home
- Python：3.10.6
- エディタ：VisualStudioCode 1.77.3
- PowerShell：5.1.19041.3031

# 手順
こちらの記事を参考に（写経）させていただきました…！
ありがとうございました。

https://www.sejuku.net/blog/73265


### 環境準備
今回の環境はすべて事前に導入済の前提で進めておりますが、もしこの記事を見ている方で同じ環境にしたい方がいれば以下参考にしていただければと思います。

::: note warn
注意
自環境ではすでに各ソフト導入済みのため、以下の手順は実施しておらず
URL内の手順を担保してはおりません。あくまで参考URLの一つとしてみていただければと思います。
:::

- Pythonのインストール方法

https://www.javadrive.jp/python/install/index1.html

- VisualStudioCodeのインストール方法

https://shuu1104.com/2021/04/2252/

- PowerShellのインストール方法

https://learn.microsoft.com/ja-jp/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3

### コーディング

コーディングというほど大したことはしていませんが、
VSCodeにて、`countdowntimer.py`というファイルを作成します。
(ファイル名は一例で、拡張子pyだけあっていればなんでも大丈夫です。)
コードの中身は以下です。

``` python:countdowntimer.py
from time import sleep

target_time = 10

def down_timer(secs):
    for i in range(secs,-1, -1):
        print(i)
        sleep(1)
    print("時間です！")

down_timer(target_time)
```

ざっくり処理の内容ですが、
まず、`time`モジュールから、`sleep`関数をインポートします。
これは[この記事](https://camp.trainocate.co.jp/magazine/python-sleep/)にもある通り、
一時的に処理を止める関数です。

> Pythonにはsleepという関数があります。sleep関数はtimeモジュールに含まれている関数のひとつです。”睡眠”を意味するsleepからとっているように、処理を一時的に停止できます。
>  また、sleep関数を利用することで「一定の間隔を開けて処理する」ことも可能です。

引数の単位は秒です。

target_timeは、カウントダウンしたい秒数を代入します。

その後、`down_timer`関数を定義します。
内容は、引数（今回は10秒）から0秒まで1秒ずつデクリメントし、
毎回その秒数の表示かつsleep関数で1秒処理停止
という流れを繰り返すというものです。
0秒になったら`時間です！`という文字列を表示します。

### 実行
ファイルを保存したら、PowerShellにて作成した`countdonwtimer.py`を実行します。

PowerShellを開き、ファイルを保存したフォルダまで移動します。(今回はデスクトップ)
`python count`あたりまで打ち込んでTabキーを押すと自動で補完してくれます。
その際の画面は以下です。
![cap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335813/a7b6fce5-8d2a-ce6f-c6b5-93ae0158cbae.png)

Enterキーで実行します。

![cap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335813/cab691e7-50ca-dd74-f846-708aabacb216.png)

だいたい1秒ごとに数字が表示され、最後に時間です！の文字が表示されました！

# 結果
カウントダウンタイマーをPythonで作ることができました。

# 学び
初学者の自分としては個人的には実行環境がハードルに感じることが多いのですが、
今回簡単な環境で実行できたのはよかったです。
関数も一つだけでイメージしやすいものだったので勉強になりました。

# まとめ
表示の仕方や応用方法などもっと工夫の仕方はあるかもしれませんが、
まずはこういった簡単なものを積み重ねていって定着させていこうと思います…！
PCが壊れたので、そこそこ強いPCを選ぼうと思います。

PCが壊れました。2017年に買ったので約8年して壊れたことになります。当時はwindows10、RTX1000番代、CPU 7700Kの時代です。

SSDが逝かれたようで、windows起動中にブルースクリーンになり、BIOS画面からいなくなっていました。ありがとう。

それで、新しいPCの選びをしたので、ここに書き記そうと思います。


結論
-----

結論から、CPUとマザボは何がいいか言いますね。

CPU:
https://www.amazon.co.jp/gp/product/B0BQ6BRL4T/ref=ox_sc_act_title_1?smid=AN1VRQENFRJN5&psc=1

マザボ:
https://www.amazon.co.jp/gp/product/B0BJCP3L5D/ref=ox_sc_act_title_2?smid=AN1VRQENFRJN5&psc=1

なぜこのCPUなのか？
-----

3万円前後で、性能がいいという判断基準です。
参考にしたサイトは、下記です。

https://pcfreebook.com/article/450856544.html

この中から、価格とPassMarkを参考に選びました。


なぜこのマザボなのか？
-----

次のような前提条件がありました。

- CPUは13世代対応
- チップセットは700番代
- メモリ規格はDDR4、128GBまで対応
- 価格は、3万前後
- 見た目よりも、性能重視

このような条件下で、調べたところ、一番あっていそうでした。
Go で New Relic を試してみた

作成：2023年7月30日
お試しで New Relic を触ってみました。

# ライセンスキーの確認

[このリンク先](https://docs.newrelic.com/jp/docs/apm/agents/go-agent/installation/install-new-relic-go/#get-new-relic)にあるリンク「[アカウントのライセンスキー](https://one.newrelic.com/api-keys)」でライセンスキーを確認します。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/be26c9b2-d2d4-e5dd-3d1d-5535a17301b1.png">


# エージェントのインストール

import するためにインストールします。
```:MacBook Terminal
go get github.com/newrelic/go-agent/v3/newrelic
```

# main.go を作成

シンプルなサンプルプログラムを作りました。
import して、Goエージェントを初期化します。上記で確認したライセンスキーを入力します。
```:main.go
package main

import (
	"fmt"
	"net/http"
	"github.com/newrelic/go-agent/v3/newrelic"
)

func main() {
	app, err := newrelic.NewApplication(
		newrelic.ConfigAppName("好きなアプリ名を入力してください"),
		newrelic.ConfigLicense("ライセンスキーを入力してください"),
	)
	if nil != err {
		fmt.Println("failed to setup new relic")
	} else {
		fmt.Println("start new relic")
	}

	http.HandleFunc(newrelic.WrapHandleFunc(app, "/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello World!!!")
	}))
	http.ListenAndServe(":3000", nil)
}

```

# main.go を実行して Web transactions time 等を確認

```:MacBook Terminal 1
% go run main.go 
start new relic
```

main.go を実行してから、[数分待って](https://docs.newrelic.com/jp/docs/apm/agents/go-agent/installation/install-new-relic-go/#view-data)から curl を実行します。

```:MacBook Terminal 2
% curl http://127.0.0.1:3000 
Hello World!!!%                                                                          % curl http://127.0.0.1:3000
Hello World!!!%                                                                                                                                                                                             ryo@Ryo-MacBook-Pro ~ % curl http://127.0.0.1:3000
Hello World!!!%     
```
見ることができました。
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/876bdbba-bab7-aa9a-81e7-efe1fc8f6088.png">



# 参考
・[Go向けNew Relicのインストール](https://docs.newrelic.com/jp/docs/apm/agents/go-agent/installation/install-new-relic-go/)
・[New Relic Go agentに入門](https://zenn.dev/marux/articles/6db9b984ccf052)


# メモ： Goライブラリを使うときは、New Relic infrastructure agent を Docker上で実行しなくてもよかったです

情報が、
    Goプログラム　→ New Relic infrastructure agent → New Relic server
の順番で流れていきます、と思ってましたが、Goプログラムから直接サーバーに飛んでました。

下の画面からコマンドをコピーしました。
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/22c43b8d-1a8d-03a6-6679-1b4df19bad1a.png">

ライセンスキーを入力してローカルのDockerコンテナ上で New Relic infrastructure agent を起動します。
```:MacBook Terminal
docker run \
 -d \
 --name newrelic-infra \
 --network=host \
 --cap-add=SYS_PTRACE \
 --privileged \
 --pid=host \
 -v "/:/host:ro" \
 -v "/var/run/docker.sock:/var/run/docker.sock" \
 -e  NRIA_LICENSE_KEY=ライセンスキーを入力してください \
 newrelic/infrastructure:latest
```

以上
Windows 11のメモ帳の枠が白くなってしまう問題の修正

# 概要
以下のような、Windows 11のメモ帳の枠が白くなってしまう問題の修正方法について書きます。

![スクリーンショット 2023-07-30 094938.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2569642/3c2536e0-932d-fb93-2bbe-576949d87880.png)

# 0.原因
Windows 11環境にて「Meiryo UIも大っきらい!!」というフォント変更ソフトにて変更したところ
同現象が発生した　※Advanced System Font Changerでも同現象確認

フォント変更によりウィンドウフレームのボーダーラインのサイズに関するレジストリ
"PaddedBorderWidth"が既定値-60から0になったことによるもの
レジストリ場所：HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics



# １.問題修正
以下をPowerShellを開き入力後Enter、レジストリを修正する ("PaddedBorderWidth"を規定値に戻す)

```powershell
Set-ItemProperty -LiteralPath  "HKCU:\Control Panel\Desktop\WindowMetrics" -Name PaddedBorderWidth -Value -60
```
修正後、PCを再起動する

# 2.修正後メモ帳画面
メモ帳の枠が白くなってしまう問題が修正された。
![スクリーンショット 2023-07-30 095159.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2569642/d315bfcf-75f3-ad66-ab92-b7550b4c21c1.png)

# 3.(おまけ) 試してNGだった方法
海外のMSコミュニティにて同現象があり、以下の方法を試してみましたが結果として直りませんでした。
https://answers.microsoft.com/en-us/windows/forum/all/notepad-dark-mode-bug/5d86b4a9-cf5d-4554-9b57-0fd4b5638e2b
DISM.exe /Online /Cleanup-image /Scanhealth
DISM.exe /Online /Cleanup-image /Restorehealth
DISM.exe /Online /Cleanup-image /startcomponentcleanup
Ubuntuで一定時間後にパソコンをシャットダウンまたはサスペンドする方法

## きっかけ
ASMR動画を流しながら寝たいが、寝てる間ずっとパソコンが動画を再生していると、経済的ではない。そこで、一定時間後にパソコンをシャットダウンまたはスリープ状態にする方法がないか調べた。

## 使用OS
Ubuntu 22.04 jammy

## シャットダウンとスリープ状態の利点と欠点
具体的な方法の前にまずシャットダウンとスリープ状態の利点と欠点を述べると

### シャットダウン

+ **利点**
    1. **エネルギーの節約**
    コンピュータを完全にオフにし、長時間の非アクティブ時に電力を節約。
    2. **システムのリフレッシュ**
    クリーンな状態から起動することで、ソフトウェアに関連する問題を解決することがある。
    3. **摩耗の軽減**
    定期的なシャットダウンにより、ハードウェアの寿命を延ばすのに役立つ。
+ **欠点**
    1. **起動に時間がかかる**
    完全なシャットダウンからの起動には時間がかかる。
    2. **作業の中断**
    すべてのアプリケーションを終了することは作業をすぐに再開する必要がある場合に不便。

---
### サスペンド（スリープモードまたはスタンバイ）

+ **利点**
    1. **早い再開**
    システムがセッションをメモリに保持するため、作業をすばやく再開できる。
    2. **アプリケーションの状態保持**
    再開時に開いていたアプリケーションとファイルはそのままの状態を保持。
    3. **エネルギー効率**
    短い非アクティブ期間中、通常の運用に比べて消費電力が少ない。
+ **欠点**
    1. **電力の消費**
    メモリを維持するために一部の電力を消費する。
    2. **バッテリーの消耗（ラップトップ）**
    ラップトップが充電されていない場合バッテリーを消耗する。保存されていないファイルがある場合充電がゼロになると、編集内容が消えてしまう。
    3. **安定性の問題**
    まれにサスペンドモードからの再開が安定性の問題を引き起こす場合がある。


以上を踏まえて、状況に応じてどちらかを選ぶ。

## 一定時間後にシャットダウンする方法
例えば60分後にシャットダウンして欲しければ以下をターミナルで実行。

```
sudo shutdown -h +60
```

## 一定時間後にサスペンドする方法
以下の方法がうまく行った。

1. Bashシェルスクリプトを作成(ファイル名は適当)して開く
    例えばvimで開く場合
    
    ```
    vim suspend.sh
    ```
2. 以下をファイル内に記述して保存
    ```Bash
    #!/bin/bash
    
    #スクリプト引数の数をチェックし、1つでない場合は使用方法を表示し、スクリプトを終了
    if [ $# -ne 1 ]; then
      echo "Usage: $0 <duration>"
      echo "Example: $0 30m (for 30 minutes)"
      exit 1
    fi
    
    #スクリプトの引数からスリープタイマーの時間を取得
    duration="$1"
    
    #sleep-timer.serviceファイルを生成し、
    #指定された時間後にスリープ（サスペンド）するコマンドを定義
    cat > /etc/systemd/system/sleep-timer.service <<EOF
    [Unit]
    Description=Sleep timer for automatic suspend
    
    [Service]
    Type=oneshot
    ExecStart=/bin/bash -c "sleep $duration && systemctl suspend"
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    #sleep-timer.timerファイルを生成し、
    #起動後に指定された時間後にsleep-timer.serviceを起動するタイマーを定義
    cat > /etc/systemd/system/sleep-timer.timer <<EOF
    [Unit]
    Description=Sleep timer for automatic suspend
    
    [Timer]
    OnBootSec=$duration
    Unit=sleep-timer.service
    
    [Install]
    WantedBy=timers.target
    EOF
    
    # systemdマネージャーをリロードし、新しい設定を適用
    systemctl daemon-reload
    
    # 新しいタイマー設定を反映させる
    systemctl restart sleep-timer.timer
    
    #スリープタイマーが設定された時間を表示
    echo "Sleep timer set to $duration. The system will suspend after $duration of inactivity."
    
    ```
3. コマンドラインでの実行
    これにより、例えば60分後にサスペンドして欲しければ以下を実行。
    
    ```
    sudo ./suspend.sh 60m
    ```
    10秒後にサスペンドしてほしければ
    ```
    sudo ./suspend.sh 10s
    ```
    2時間後なら
    ```
    sudo ./suspend.sh 2h
    ```
【AWS】ECSタスクでHello World

## 使用するコンテナ
https://hub.docker.com/_/hello-world
コンテナを実行すると、以下のメッセージが出力されます。
```
Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/get-started/
```


## 手順
1. タスク定義の作成
1. クラスターの作成
1. ECSタスクの実行
### 1. タスク定義の作成
「タスク定義」から、「新しいタスク定義の作成」をクリックして、作成を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479797/bd5b8ea3-7384-0e0d-6dbf-bb5fbe655f40.png)
設定はざっと以下の通り
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479797/94d08b42-d3ee-0942-b902-21240534759d.png)

以下はコンテナの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479797/8d1b5338-511d-4222-25c2-cda20e73bc8c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479797/55e735b8-9cfc-f350-eddd-e9b4af9952ee.png)

タスク定義が追加されたことが分かります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479797/24c46f3a-7bb9-0898-d2e2-1788af53dffd.png)

### 2. クラスターの作成
「クラスター」から「クラスターの作成」をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479797/42f17e60-a3f0-b1e5-3b33-ce661614207f.png)
設定はざっと以下の通り。ネットワーキングの部分は各環境に応じてよしなに設定してみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479797/236f29ea-613d-d63a-e6c2-d973170eeccb.png)

クラスターが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479797/d99fee26-5f9e-3a3a-9e52-8ad0a5b4d135.png)


### 3. ECSタスクの実行
先ほど作成したタスク定義を選択して「デプロイ」から「タスクの実行」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479797/627fc1ad-99a5-b5e4-4268-05ed13a5eb5f.png)
今回はFARGATEで実行します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479797/9e7321a0-ff66-0676-d5f0-32bce6767cad.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479797/1abb981b-cba3-c277-f850-dff548a0eb1b.png)
実行すると、先ほど実行したタスクが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479797/a4187c2d-39c9-776e-d698-fc0e8bab8779.png)
タスクをクリックし、実行完了したら「ログ」のタブに移動します。
すると、Hello Worldのメッセージが出力されていることが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479797/95b8f72f-109e-4fd0-8af5-6312fdeb747e.png)

## 参考
https://dev.classmethod.jp/articles/ecs-hello-world-task/
[リサーチ・メモ] トラストストアに証明書を追加する

## 背景
仕事でSendGridの単体打鍵を実施しようとした際に、下記エラーが発生した。トラストストアに証明書を追加する必要があり、実装したことが無かった為、メモとして纏める。
```
[ERROR   ] CWPKI0823E: SSL ハンドシェークの失敗: SubjectDN [CN=*.api.sendgrid.com] の署名者がホスト [api.sendgrid.com:443] から送信されました。  SSL 構成別名 [defaultSSLConfig] にあるトラストストア [public.jksへのパス] にこの署名者を追加する必要がある可能性があります。  SSL ハンドシェーク例外からの拡張エラー・メッセージ: [PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target]
```

## そもそもトラストストアとは
信頼できる発行元からの証明書を保管して、信頼性のある通信を確立するセキュリティ。
「public.jks」の情報は「server.xml」のkeyStoreタグに記載されている。
```
<keyStore id="xxx" location="public.jks" password="yyy" type="JKS"/>
```

## トラストストアに証明書を追加する
#### 1\. 下記を参考にOpenSSLをインストールする

https://blog.katsubemakito.net/articles/install-openssl-windows10

#### 2\. openSSLで証明書(.crtファイル)を取得する
```
openssl s_client -connect api.sendgrid.com:443
```
|コマンド|詳細|
|:----------:|:------------:|
|openssl |OpenSSLツールの起動|
|s_client| 任意のサーバーに対する手動接続を実施する|
|-connect api.sendgrid.com:443| 指定したホスト名とポート番号に接続する|

#### 3\. 文字化け防止の為に、下記を実施(文字コードをUTF-8に変更)
```
chcp 65001
```

#### 4\. トラストストアに証明書を追加する
```
keytool -import -alias sendgrid -file 「2.のcrtファイルへのパス」 -keystore 「public.jksへのパス」
```
|コマンド|詳細|
|:----------:|:------------:|
|keytool -import| 新しい証明書を追加する|
|-alias| 証明書に対して名前を指定する(今回の場合は、証明書にsendgridという名前が付けられる)|
|-file| インポートする証明書へのパスを指定する|
|-keystore| インポート先を指定する|

#### 5\. パスワードを入力し、yesを答える
デフォルトパスワードは「changeit」

#### 6\. トラストストアに証明書が追加されているか確認する
```
keytool -list -keystore 「public.jksへのパス」 | grep 'sendgrid'
```
|コマンド|詳細|
|:----------:|:------------:|
|keytool -list -keystore| 指定したファイルの一覧を表示する|
|grep| 上記一覧から指定した名前のファイルを表示する(ない場合は、何も表示されない)|
Docker コマンドまとめ

### Dockerコマンドまとめ
#### docker runを実行する
```terminal
# Dockerイメージを指定して、名前を定義して実行する(Pythonを実行してすぐに終了する）
docker run --name test4 python:1.1
hello world!
```
#### 実行結果
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576081/d03e6abd-36e7-d56d-64b4-109f15cdd6ee.png)

### Dockerコンテナを削除する
```terminal
# Dockerを実行（イメージからコンテナを作成して実行する）
docker run --name test4 python:1.1
# コンテナを削除する 
docker rm test4
```
### インターラクティヴでコンテナを起動して、処理終了したら、コンテナを閉じる
```terminal
$ docker run --rm -it python:1.1 
hello world!
```
[ -i ]オプション : interactive ( 対話型 )
[ -t ]オプション : tty ( 端末デバイス )

### Ubuntuのコンテナを作成して、起動する
```terminal
$ docker run -it ubuntu
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
3153aa388d02: Already exists                                                                                                            
Digest: sha256:0bced47fffa3361afa981854fcabcd4577cd43cebbb808cea2b1f33a3dd7f508
Status: Downloaded newer image for ubuntu:latest
root@e9c178678abb:/# ls
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@e9c178678abb:/#   
```
Pythonのアンパックの基礎

### アンパックとは
From ChatGPT：
>Pythonのアンパック（Unpacking）は、シーケンス（リストやタプルなど）やイテラブル（iterable）オブジェクトから要素を取り出して、それぞれの変数に代入する操作です。アンパックは一度に複数の変数への代入を行うことができます。

<b>アンパックは、Python言語の特徴の一つで、複数の戻り値を戻せる関数を作成できるというとても便利な機能です。</b>
```python
li, num_val, string_val = func(args1, args2)
```
戻り値の一部を省略する場合は以下
```python
li, num_val, _ = func(args1, args2)
```
戻り値がそれぞれ異なる型でもOK

### 事例１
基準日を基に月、年度、月初め、月末、年度初、年度末をそれぞれ戻す関数
```python
def get_cal_info():
    '''基準日の計算
    Returns:
        base_day:基準日
        base_month:基準月
        base_year: 基準年度
        start_month:月初め
        end_month:月末
        start_year:年度始
        end_year:年度末
    '''
    # 実行日を基準(1日前)
    base_day = pd.Timestamp.today().date()-timedelta(days=1)

    # 月のデータを取得
    base_month = int(base_day.strftime("%m"))

    # 月始め
    start_month = base_day.replace(day=1) 
    # 月末
    end_month = base_day.replace(day=1) + relativedelta(months=1)+ timedelta(seconds=-1)

    # 年度計算
    if base_month > 4:
        base_year = int(base_day.strftime('%Y'))
    else:
        base_year = int(base_day.strftime('%Y')) - 1

    base_month = base_day.strftime('%Y-%m')
    base_day = base_day.strftime('%Y%m%d')
    start_year = pd.Timestamp(base_year,4,1).strftime('%Y%m%d')
    end_year = pd.Timestamp(base_year+1,3,31).strftime('%Y%m%d')
    start_month = start_month.strftime('%Y%m%d')
    end_month = end_month.strftime('%Y%m%d')
    
    return base_day, base_month, base_year, start_month, end_month, start_year, end_year
```
呼び出し側
```python
# 基準日、年度、年度初め、年度末を使用する場合のアンパック
base_day, _, base_year, _, _, start_year, end_year = get_cal_info()
# 基準日、基準月、月初め、月末を使用する場合のアンパック
base_day, base_month, _, start_month, end_month, _, _ = get_cal_info()
```
### 事例２
NumpyのFlattenを使って多次元の配列を1次元に変更する
```python
import numpy as np

def test():
    l = [[1,2],[3,4],[5,6]]
    li = np.array(l)
    re = li.flatten()
    re2 = list(re)
    return re, re2

np_array, li = test()
print(np_array)
print(li)
```

### 特殊事例
以下の事例の場合、すべてのローカル変数を辞書型に格納して戻り値にする
```python
import numpy as np

def test2():
    l = [[1,2],[3,4],[5,6]]
    li = np.array(l)
    re = li.flatten()
    re2 = list(re)
    return locals()

result = test2()

for k,v in result.items():
    print(k)
    print(v)

print(result['re'])
```
実行結果
```terminal
l
[[1, 2], [3, 4], [5, 6]]
li
[[1 2]
 [3 4]
 [5 6]]
re
[1 2 3 4 5 6]
re2
[1, 2, 3, 4, 5, 6]
[1 2 3 4 5 6]
```

### アンパックとZIPの応用事例
以前の記事をご参照ください。

https://qiita.com/akeyi2018/items/27273ad4aa6cba39d9b4
整数の平方根を四捨五入で求める

# 整数の平方根を切り捨てで求める

四捨五入の前に、まずは切り捨てで求める方法を復習する。
非負の「ある数」について

* ある数が求めたい平方根より大きいならば、その数の2乗はもとの数より大きい
* ある数が求めたい平方根ならば、その数の2乗はもとの数
* ある数が求めたい平方根未満ならば、その数の2乗はもとの数未満

という性質を利用し、めぐる式二分探索で求めることができる。
求めたい平方根の小数点以下を切り捨てた値は、求めたい平方根以下の最大の整数である。
よって、2乗してもとの数以下になる最大の整数を求めればよい。

2の平方根は約1.41であり、平方根の増え方はもとの数の増え方より遅いので、直感的に2以上の整数の平方根の小数点以下を切り捨てた数はもとの数未満であることがわかる。

```python
def sqrt_floor(n):
  if n <= 0:
    return 0
  if n == 1:
    return 1
  le = 0 # 平方根以下の数
  greater = n # 平方根より大きい数
  while le + 1 < greater:
    m = le + (greater - le) // 2
    if m * m <= n:
      le = m
    else:
      greater = m
  return le
```

動作を試してみる。

```python
for i in range(20):
  print("%2d %d" % (i, sqrt_floor(i)))
```

以下の実行結果が得られた。

```
 0 0
 1 1
 2 1
 3 1
 4 2
 5 2
 6 2
 7 2
 8 2
 9 3
10 3
11 3
12 3
13 3
14 3
15 3
16 4
17 4
18 4
19 4
```

うまくいっていそうである。

# 整数の平方根を四捨五入で求める

切り捨てでの求め方を応用して、整数の平方根の小数点以下を四捨五入した値を求める方法を考える。

求める値が $k$ のとき、もとの数の平方根は $k-0.5$ 以上 $(k+1)-0.5$ 未満である。
したがって、もとの数を $n$ とすると、${(k-0.5)}^2 \leq n$ かつ ${((k+1)-0.5)}^2 > n$ となる非負整数 $k$ を求めればよいことがわかる。
${(k-0.5)}^2 \leq n$ の両辺を4倍して変形すると、${(2k-1)}^2 \leq 4n$ となり、整数のみで計算できるようになる。

2の平方根は約1.41なので四捨五入すると1、3の平方根は約1.73なので四捨五入すると2、4の平方根は2である。
平方根の増え方はもとの数の増え方より遅いので、直感的に2以上の整数の平方根の小数点以下を四捨五入した数はもとの数未満であることがわかる。

```python
def sqrt_round(n):
  if n <= 0:
    return 0
  if n == 1:
    return 1
  le = 0 # 平方根の四捨五入以下の数
  greater = n # 平方根の四捨五入より大きい数
  while le + 1 < greater:
    m = le + (greater - le) // 2
    if (2 * m - 1) * (2 * m - 1) <= 4 * n:
      le = m
    else:
      greater = m
  return le
```

動作を試してみる。

```python
import math
for i in range(30):
  print("%2d %6.3f %d" % (i, math.sqrt(i), sqrt_round(i)))
```

以下の実行結果が得られた。

```
 0  0.000 0
 1  1.000 1
 2  1.414 1
 3  1.732 2
 4  2.000 2
 5  2.236 2
 6  2.449 2
 7  2.646 3
 8  2.828 3
 9  3.000 3
10  3.162 3
11  3.317 3
12  3.464 3
13  3.606 4
14  3.742 4
15  3.873 4
16  4.000 4
17  4.123 4
18  4.243 4
19  4.359 4
20  4.472 4
21  4.583 5
22  4.690 5
23  4.796 5
24  4.899 5
25  5.000 5
26  5.099 5
27  5.196 5
28  5.292 5
29  5.385 5
```

うまくいっていそうである。
wslでelixir その25

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
nxやってみた。
練習問題、やってみた。


# 練習問題
nxだけで、曲線を学習して推定せよ。

# サンプルコード

```
defmodule Learn do
	import Nx.Defn
	defn f(params, input) do
		params
		|> Nx.dot(input)
	end
	defn model(params, input) do
		prediction = f(params, input)
		prediction
	end
	defn measure_difference(prediction, label) do
		prediction
		|> Nx.subtract(label)
		|> Nx.power(2)
		|> Nx.mean()
	end
	defn objective(params, input, label) do
		prediction = model(params, input)
		measure_difference(prediction, label)
	end
	defn step(params, input, label) do
		direction_of_descent = grad(params, &objective(&1, input, label))
		params - direction_of_descent * 1.0e-3
	end
end

defmodule Main do
	def main do
		true_params = Nx.random_uniform({16})
		true_f = fn params, x ->
			params
			|> Nx.dot(x)
		end
		IO.puts("ok0")
		train_data =
			for _ <- 1..1000 do
				x = Nx.random_uniform({16})
				{x, true_f.(true_params, x)}
			end
		params = Nx.random_normal({16})
		|> IO.inspect
		IO.puts("ok1")
		recovered_params =
			for _ <- 1..10, reduce: params do
				params ->
					for {input, label} <- train_data, reduce: params do
						params ->
							Learn.step(params, input, label)
					end
			end
			|> IO.inspect
		IO.puts("ok2")
		diff0 =
			for _ <- 1..5 do
				x = Nx.random_uniform({16})
				pred = Learn.model(recovered_params, x)
				actual = true_f.(true_params, x)
				Learn.measure_difference(actual, pred)
			end
		|> IO.inspect
		IO.puts("ok4")
		diff1 =
			for _ <- 1..5 do
				x = Nx.random_uniform({16})
				pred = Learn.model(params, x)
				actual = true_f.(true_params, x)
				Learn.measure_difference(actual, pred)
			end
		|> IO.inspect
		IO.puts("ok6")
	end
end


```

# 実行結果

```
Interactive Elixir (1.13.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Main.main
ok0
#Nx.Tensor<
  f32[16]
  [-0.15059667825698853, 0.5347859263420105, 0.8552658557891846, -1.7892613410949707, 0.5690175890922546, -1.4746782779693604, 0.9916109442710876, 1.9264497756958008, 0.015706023201346397, -1.5992125272750854, 0.43615153431892395, 0.34414586424827576, 0.29918256402015686, -0.15019024908542633, -1.2895303964614868, -0.07701452076435089]
>
ok1
#Nx.Tensor<
  f32[16]
  [0.7297366857528687, 0.9290812015533447, 0.5195321440696716, 0.34908464550971985, 1.0500684976577759, 0.19730430841445923, 0.9062032699584961, 0.6261845231056213, 0.0654318630695343, 0.2777728736400604, 0.7795501947402954, 0.8976764678955078, 0.5426539778709412, 0.4251895248889923, -0.08125773817300797, 0.14991897344589233]
>
ok2
[
  #Nx.Tensor<
    f32
    9.45959982345812e-5
  >,
  #Nx.Tensor<
    f32
    0.10882914811372757
  >,
  #Nx.Tensor<
    f32
    0.22344224154949188
  >,
  #Nx.Tensor<
    f32
    0.23611009120941162
  >,
  #Nx.Tensor<
    f32
    0.18488386273384094
  >
]
ok4
[
  #Nx.Tensor<
    f32
    9.746542930603027
  >,
  #Nx.Tensor<
    f32
    9.063727378845215
  >,
  #Nx.Tensor<
    f32
    17.649784088134766
  >,
  #Nx.Tensor<
    f32
    17.375164031982422
  >,
  #Nx.Tensor<
    f32
    8.264528274536133
  >
]
ok6
:ok
iex(2)>
```
以上。
Lambdaで「libcrypt.so.1: cannot open shared object file: No such file or directory」を解消

# はじめに

今回の記事は、Ruby3.2でLambdaを使用しようとしたときに、「/var/lang/bin/ruby: error while loading shared libraries: libcrypt.so.1: cannot open shared object file: No such file or directory」というエラーが出たので、なんとか解消できたときのお話です。もしかしたらRubyでも[こちら(Pythonです)](https://github.com/keithrozario/Klayers)のように、出来上がったレイヤーを配布しているかもしれませんので、お時間ある方は探してみてください。

# なぜエラーがでたのか？

Lambdaでは最近Rubyの3.2のランタイムが提供されるようになりました。しかし、Rubyのランタイムが依存しているLinux依存のライブラリまでは網羅されていないため、見つけることができずタイトルにあるエラーが出てしまいました。

# どのように解消したのか？

別の環境でライブラリをLambdaのレイヤーとして作成して追加しました。ただし、それなりに手間がかかったので、順に説明します。

## 1. DockerでAmazonLinux2のコンテナイメージをpullする。
現在(2023年7月30日時点)ではLambdaのOSはAmazonLinux2のOSがベースになっているようでしたので、このコンテナを選びました。

```
docker pull amazonlinux:2
```

## 2. ローカル環境のディレクトリをマウントしてコンテナを起動する。

`pwd`というコマンドで自分が今どこにいるのか(作業中のディレクトリ)を絶対参照で知ることができるかと思いますが、今回はそれを使って、カレントディレクトリのフルパスを取得してマウントします。そうしないと後々コンテナ内での作業の成果物を取得できないのです。。。

```
docker run -v "$PWD":/var/task -it amazonlinux:2 bash
```

## 3. コンテナ内で作業するのに必要なコマンドをインストールする。
とはいえ、.zipにしてレイヤーに追加するだけなので、実際にはzipだけです！！！

```
yum install -y zip
```

## 4. libcrypt.so.1を探す
### 4-1. `find`コマンドでファイル名を指定して探しましょう。

```
find / -name "libcrypt.so.1"
```

:::note info
本体ではない可能性があるので一旦`ls`してみましょう
```
bash-4.2# ls -l /usr/lib64/libcrypt.so.1
lrwxrwxrwx 1 root root 16 Jun 28 19:09 /usr/lib64/libcrypt.so.1 -> libcrypt-2.26.so
```
こういうことですね！！！
シンボリックリンクというものでした。
:::

### 4-2. 本体側(今回はlibcrypt-2.26.so)がどこにあるのか探しましょう。

```
find / -name "libcrypt-2.26.so"
```

## 5. 必要なライブラリをひとまとめにする。
ここでLambdaのレイヤーに配置することを想定して、zip形式にします。Lambdaのレイヤー配置はzip形式でアップロードする必要があります！また、今回はシンボリックリンクもzipに入れるので、cpコマンドのオプションに注意してください。

```
cd /var/task
mkdir lib
cp -pa /usr/lib64/libcrypt* ./lib/
zip libcrypt.zip ./lib/*
```

## 6. 出来上がったzipファイルを取得する。
カレントディレクトリにruby-layer.zipというファイルが出来上がっていることと思います。これをAWSのLambdaへ配置すれば完了です！！！

## 7. Lambdaのレイヤーに追加する。
これらはAWSのデベロッパーガイドに従って行ってください。

### 7-1. レイヤーを作成する。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-layers.html

### 7-2. Lambdaにレイヤーを紐付ける。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-layers.html

以上で完了です！おつかれさまでした！！！

# まとめ
今回遭遇したエラーは実はここまですんなりと解決できておらず、数日かかっています。その試行錯誤した結果をhistoryコマンドで遡ってまとめました。こちらの記事では一度で済ませられるようにまとめてありますが、正直かなりしんどかったです。ただ、頭の中にたくさんインデックスを貼ることができたので、学習だと思えば良い経験ができたと思います。

ここまで読んで頂きありがとうございました。
ではでは、今回はこの辺で👋
SwiftUIでindexによってリストの見た目を変える実装方法

現在SwiftUIを勉強中なので、さまざまなUIを実装しています。
今回は、SwiftUIでindexによってリストの見た目を変える実装をしてみました。


Xcode Version 14.2


```EditListView.swift
struct EditListView: View {
    @State private var tee = ["緑茶", "烏龍茶", "ほうじ茶", "ジャスミン茶", "麦茶", "烏龍茶", "ほうじ茶", "ジャスミン茶", "麦茶", "烏龍茶", "ほうじ茶",
 "ジャスミン茶", "麦茶", "烏龍茶", "ほうじ茶", "ジャスミン茶", "麦茶", "烏龍茶", "ほうじ茶", "ジャスミン茶", "麦茶"]
    
    var body: some View {
        VStack(spacing: 0) {
            Divider().background(Color.brown).padding(.top, 10)
            List {
                ForEach(Array(tee.enumerated()), id: \.element) { index, tee in
                    if index % 2 == 0 {
                        VStack(alignment: .center ,spacing: 0) {
                            Text(tee)
                                .font(.system(size: 16))
                                .frame(maxWidth: .infinity, alignment: .leading)
                        }.listRowInsets(EdgeInsets())
                    } else {
                        VStack(alignment: .center ,spacing: 0) {
                            Text(tee)
                                .font(.system(size: 16))
                                .frame(maxWidth: .infinity, alignment: .leading)
                                .foregroundColor(Color.blue)
                        }.listRowInsets(EdgeInsets())
                    }
                }
            }
            .listStyle(PlainListStyle())
        }
    }
}

```

![スクリーンショット 2023-07-30 10.25.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/75aca087-dc4a-6ef6-9cd5-02f8f1ab0be3.png)


`Array(tee.enumerated())`
こちらを実装するとindexがわかるようになります。
このように黒色、青色交互のリストが出来ました。
indexによって変化させたい場合は参考にしてみてください。
【Ruby】frozen_string_literal: trueとは？

Ruby on Railsでのコーディングの際、`frozen_string_literal: true`というコードが先頭に実装されている場面をよく見かけ、なんだろう？と思い調べてみました。

備忘録としてこちらに残しておきます。


# コード
```ruby:ruby
frozen_string_literal: true
```

# frozen_string_literal: trueって何？
- このコード`frozen_string_literal: true`は、Rubyファイルの先頭に書かれるマジックコメントの一つである。
- このマジックコメントがあると、そのファイル内で定義された文字列リテラル（`" "`や`' '`で囲まれた文字列）は全て凍結される。つまり、それらの文字列は不変になり、後から変更できなくなる。
- なぜこんなことをするのかというと、処理の高速化やメモリの節約につながるから。文字列の変更が頻繁に行われると、その都度新しい文字列オブジェクトが生成されてメモリを消費する。しかし、文字列を凍結してしまえば、その心配がなくなる。


# その他、参考になった記事の引用

> #frozen_string_literal: true　がある場合
> text1 = 'Hello world'
text2 = 'Hello world'
puts text1.object_id == text2.object_id

引用：<a href="https://qiita.com/YutoYasunaga/items/98111ef50927ecb4135d">Rubyで #frozen_string_literal: true というマジックコメントを付ける意味</a>



# その他、参考サイト
https://qiita.com/YutoYasunaga/items/98111ef50927ecb4135d

https://qiita.com/universato/items/1dd8943df07f2445655e

https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/FrozenStringLiteralComment
画像サイズの追加する時の仕様

ワードプレスで、画像サイズを追加しました。その過程で、色々発見したことがあるので、メモしておく。


#### 画像サイズの登録
```php 
add_image_size('works', 1280, 720, true);
// 先に追加したい画像サイズを登録する。
```
画像サイズを追加する順番は時は先に`functions.php`に欲しい画像サイズを記述します。その後に画像をアップロードします。順番が逆になると、画像サイズが登録されないので、注意。

#### 高さを自動で決める
```php 
add_image_size('works', 720, 0, true);
```
上のように画像のサイズ登録する時に高さを０にすると、横幅に応じて元の画像の縦横比を維持したまま高さが自動で決まる。逆に横幅だけを0にすると、指定された高さに応じて、横幅が自動で決まる。

#### 画像の自動リサイズ
画像をアップロードする時に2560px以上の画像をアップロードしようとするとファイル名の語尾に`-slaled`がついて自動でリサイズされます。防ぐには以下のコードを`functions.php`に追加します。
```php
add_filter( 'big_image_size_threshold', '__return_false' );
```
サーバー側に負荷をかけないための仕様みたい。


#### 参考

https://thewppress.com/libraries/add-image-size/

https://bryog.com/wordpress53-2560px-howto-upload/
ABC312回答メモ

0.はじめに
　ユニークビジョンプログラミングコンテストだから難易度高いかなーと思ったら
　やっぱり高かったです。（毎週言ってる気が。）
　ABしか解けず、惨憺たる結果でしたが、レートは-14と他の人もてこずって
　いたんだなーと安心しました。

　思えば1年ちょっと前にABC初参加したのもユニークビジョンプログラミング
　コンテストでした。

1.A - Chord
　単純にチェック対象の文字列のリストを持って置き、インプットが
　その中に含まれるかをチェックしてYesかNoを出力でACでした。

　https://atcoder.jp/contests/abc312/submissions/44035416

2.B - TaK Code
　初見、これがB問題！？と思うほどややこしい問題でしたが
　まぁ、地道に解いたらなんとかいけました。

　【考え方】
```
P1="###."
P2="...."
P3=".###"
```
　・上記変数を用意しておく　
　・インプット表の左上から以下をチェック
　　1)チェックポイントの１～3行目の左から4桁がP1と一致
　　2)チェックポイントの4行目の左から4桁がP2と一致
　　3)チェックポイントの6行目の左から6桁目以降の4桁がP2と一致
　　4)チェックポイントの7～9行目の左から6桁目以降の4桁がP3と一致
　・上記1)～4)を満たしたチェックポイントの座標を出力

　https://atcoder.jp/contests/abc312/submissions/44048788

3.C - Invisible Hand
　買い手と売り手の希望金額を合わせたリストを作ってソートして
　小さい金額からチェックしていって買い手が上回ったタイミングで
　希望金額を出力という感じで実装しようと四苦八苦しましたが
　時間切れとなりました。

　解説を見たら
　買い手の希望金額と売り手の希望金額+1を合わせたリストの
　小さい方からM番目の値が答えと分かり目からうろこでした・・・。

　https://atcoder.jp/contests/abc312/submissions/44082455

以上
ConftestをCodeBuildで実行

# はじめに
CFnテンプレートをチェックできるConftestについて、以前記事にしました。

https://qiita.com/a_b_/items/994f5eec5a415ed57269

これをCodeBuildの中で使ってみようと思います。CodeBuildの簡単な使い方は以下になります。

https://qiita.com/a_b_/items/80cb3fe41b4efec1a271


# やってみた

## 環境

CodeBuild周りの環境は、以前作ったCFnテンプレートをそのまま用います。

https://qiita.com/a_b_/items/80cb3fe41b4efec1a271#cfn%E3%81%A7%E4%BD%9C%E3%82%8B

## ファイル

以下の3ファイルを作成します。

- sampleCreateRole.yaml
- policy/rolePolicy.rego
- buildspec.yml

まずはREGOファイルです。
```rego:policy/rolePolicy.rego
package main
import future.keywords

# Actionに * が使われているか
deny[msg] {
  # idに論理IDが格納される
  some id, res in input.Resources
  res.Type == "AWS::IAM::Role"
  
  action = res.Properties.Policies[_].PolicyDocument.Statement[_].Action
  
  is_string(action)
  endswith(action, "*")
  
  msg = sprintf("%s 内でアクションに * が使われています。",[id])
}
```

チェックするCFnテンプレートは以下を使います。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html#aws-resource-iam-role--examples

```yaml:sampleCreateRole.yaml
AWSTemplateFormatVersion: "2010-09-09"
Resources:
  RootRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action: '*'
                Resource: '*'
  RootInstanceProfile:
    Type: 'AWS::IAM::InstanceProfile'
    Properties:
      Path: /
      Roles:
        - !Ref RootRole
```

最後に`buildspec.yml`です。ビルドファイルなどを作成しているわけではないので、`pre_build`でチェックを書いています。どこに書くのが適切なのか、この辺り詳しい方教えてください。
```yaml:buildspec.yml
version: 0.2

phases:
  install:
    commands:
      - LATEST_VERSION=$(wget -O - "https://api.github.com/repos/open-policy-agent/conftest/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' | cut -c 2-)
      - wget "https://github.com/open-policy-agent/conftest/releases/download/v${LATEST_VERSION}/conftest_${LATEST_VERSION}_Linux_x86_64.tar.gz"
      - tar xzf conftest_${LATEST_VERSION}_Linux_x86_64.tar.gz
      - sudo mv conftest /usr/local/bin
  pre_build:
    commands:
      - conftest test sampleCreateRole.yaml
```


## 実行

CodeBuildのビルドを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/44debd67-1f60-ddba-9c91-eecc85328e6e.png)

以下のメッセージが出力され、失敗しました。
```
1 test, 0 passed, 0 warnings, 1 failure, 0 exceptions
```
```
Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: conftest test sampleCreateRole.yaml. Reason: exit status 1
```

成功するように、CFnテンプレートを書き換えコミットします。
```diff_yaml:ampleCreateLambda.yaml
-                Action: '*'
+                Action: 's3:*Object'
```
ビルドを再実行して、成功になることが確認できます。
```
1 test, 1 passed, 0 warnings, 0 failures, 0 exceptions
```

# おわりに
ConftestでCFnテンプレートをチェックできることから、CodeBuildに組み込んでみました。
プログラムのCIのようにできるのでは、と思いやってみて、思っていた以上に簡単にできました。
他のCFnテンプレートの自動テスト的なものと組み合わせてみたいと感じています。

この記事がどなたかのお役に立てれば幸いです。
Llama2とかrinnaなどを使ってIMEを作って見る試行

出来はしたけど色々な理由で微妙です。

# 目的
今流行りのLLMでIMEとかできないか興味あった。

# 結論
- 基本的に漢字変換されない
    - Text Generationモデルでやるのは合わないのかもしれない？Text2Textあたりでなんかいいのないかな。
    - もしかしたら漢字変換用に調整したモデルならうまくいくかもしれない。今回は手元になかったので試してない。
- 重い・遅い
    -  一般的なIMEなど、一瞬で数十個の候補が出るものと比べると、明らかに遅い。  
    -  GPU使用すれば高速化は期待できるが、どちらにせよユーザーが選べるような複数候補を一瞬で出すというのは叶わない気がした。

ということを考えると、別にわざわざLLMをIMEへ実装しなくてもいいと思った。
もしかしたらやり方次第で使えるIMEになるのかもしれないが、ちょっと実現方法が思いつかなかった。

# やったこと
[rinna](rinna/japanese-gpt-neox-3.6b-instruction-ppo)と[Llama2](meta-llama/Llama-2-7b-chat-hf)を使い、mac上でIMEを実装。

バックエンドは[llama.cpp](https://github.com/ggerganov/llama.cpp)を使用しました。rinnaはGPTNeoXなので、[redpajama.cpp](https://github.com/togethercomputer/redpajama.cpp)です。

Macで使用するためのswiftコードです。llama-cpp-pythonとサンプルを参考に実装しています。
https://gist.github.com/ebisuke/823999258feeb891f3ab77d92a10ac3e
https://gist.github.com/ebisuke/4d7732acb7ca2212f6b3a06e6d4b613f

IMEのコードですが、xcodeで作成したコードをそのまま公開していいか（個人情報的に）よくわかってないので、今の所ｕｐしてません。  
もし必要でしたらコメントで教えてください。ただ、若干フリーズしたりして、実用的ではないです。

# 結果
## rinna
https://youtu.be/k-YEZ7nueCc

## llama2
https://youtu.be/yMDh43j7dbs
JuniperEXのL3とLACPの設定

## 環境情報
* JuniperEX4300 13.2X51-D26.2

# Static Link Aggregation設定

スイッチに設定するLAGの数を定義
```
# set chassis aggregated-devices ethernet device-count 1
```

LAGの作成（ 設定例：L2アクセスポートとして ae0 の作成 ）
```
# set interfaces ae0 unit 0 family ethernet-switching
```

LAGに参加させる既存のインターフェースの設定の削除
```
# delete interfaces ge-0/0/8 unit 0
# delete interfaces ge-0/0/9 unit 0
```

LAGに参加させるインターフェースの設定
```
# set interfaces ge-0/0/8 ether-options 802.3ad ae0
# set interfaces ge-0/0/9 ether-options 802.3ad ae0
```

LAGインターフェースを、全てのVLANトラフィックを転送するL2トランクポートで設定
```
# set interfaces ae0 unit 0 family ethernet-switching interface-mode trunk vlan members all
```

ae0のLAGをアクセスポートとしてVLAN10を割り当てる場合
```
# set interfaces ae0 unit 0 family ethernet-switching interface-mode access
# set interfaces ae0 unit 0 family ethernet-switching vlan members V10
```

# Dynamic Aggregationの設定

LACPとして設定する場合、上記のStatic Link Aggregationの設定に加えて次の設定を追加
```
# set interfaces ae0 aggregated-ether-options lacp active
# set interfaces ae0 aggregated-ether-options lacp periodic fast
```

# xSTP configuration disallowed on interface ge-0/0/8 as it is part of an aggregate bundleの対処

何故かcommitが出来ない。
内容が「インターフェイス ge-0/0/8 は集約バンドルの一部であるため、xSTP 設定は禁止されています」と書かれてあり、調べてみるとLACP設定したge-0/0/8、ge-0/0/9が排他的になっていることが原因だと分かった。
```
root@EX4300# commit 
error: xSTP configuration disallowed on interface ge-0/0/8 as it is part of an aggregate bundle
error: configuration check-out failed
```
稼働中のルーティングプロトコルを確認
```php:# show protocols | display set | match stp set protocols rstp interface ge-0/0/0
set protocols rstp interface ge-0/0/1
set protocols rstp interface ge-0/0/2
set protocols rstp interface ge-0/0/3
set protocols rstp interface ge-0/0/4
set protocols rstp interface ge-0/0/5
set protocols rstp interface ge-0/0/6
set protocols rstp interface ge-0/0/7
set protocols rstp interface ge-0/0/8
set protocols rstp interface ge-0/0/9
set protocols rstp interface ge-0/0/10
set protocols rstp interface ge-0/0/11
set protocols rstp interface ge-0/0/12
set protocols rstp interface ge-0/0/13
set protocols rstp interface ge-0/0/14
set protocols rstp interface ge-0/0/15
set protocols rstp interface ge-0/0/16
set protocols rstp interface ge-0/0/17
set protocols rstp interface ge-0/0/18
set protocols rstp interface ge-0/0/19
set protocols rstp interface ge-0/0/20
set protocols rstp interface ge-0/0/21
set protocols rstp interface ge-0/0/22
set protocols rstp interface ge-0/0/23
set protocols rstp interface ge-0/2/0
set protocols rstp interface xe-0/2/0
set protocols rstp interface ge-0/2/1
set protocols rstp interface xe-0/2/1
set protocols rstp interface ge-0/2/2
set protocols rstp interface xe-0/2/2
set protocols rstp interface ge-0/2/3
set protocols rstp interface xe-0/2/3

{master:0}[edit]
```

デフォルトで動作していたRSTPを排除
```
root@EX4300# delete protocols rstp interface ge-0/0/8  

{master:0}[edit]
root@EX4300# delete protocols rstp interface ge-0/0/9    

{master:0}[edit]
```
```
root@EX4300# commit 
configuration check succeeds
commit complete
```
Excel: CSVをエクセルで編集するとフォーマットが崩れる場合がある

ちょっとつまづいたのでメモ。

###### 実施環境 : Microsoft Office Professional Plus 2016

### 事象

以下のような CSV ファイルがあるとします。

![WS000271.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/515a3225-7a12-5391-e9f4-76c4100978c3.jpeg "CSV1")

これをエクセルで開くと、以下のように数字や日付のフォーマットが崩れたり、文字列が計算式として解釈されてしまったりします。

![WS000272.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/e1d60ae3-7f31-2858-ee90-4e148d223328.jpeg "CSV2")

そしてこれをそのまま保存してしまうと、崩れたフォーマットのまま CSV ファイルが保存されてしまいます。

![WS000273.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/18646edc-ac24-0d78-ac40-2270693cbc77.jpeg "CSV3")

 CSV ファイルはなるべくテキストエディタ等で開き、どうしてもエクセルで開きたい場合はフォーマット崩れに注意しましょう。
Descheduler for KubernetesでPod(レプリカ)の再スケジュールを促す

# この記事の目的
WorkerNode上で起動するPod(レプリカ)数の偏りを自動的に解消するためにDescheduler for Kubernetesを導入したお話をざっくりと書いて残しておきます。

# 前提
Descheduler for Kubernetesのバージョンは0.26.1です。
次のGitHubリポジトリに記載されている手順に従ってデプロイします。
https://github.com/kubernetes-sigs/descheduler

5分間隔でJob Podを作成して処理が終わったら捨てたかったので私はCronJobを選びました。
`kustomize build 'github.com/kubernetes-sigs/descheduler/kubernetes/cronjob?ref=v0.26.1' | kubectl apply -f -`


# Deschedulerをどのような場面で効かせたかったか
- とあるWorkerNodeが障害によってダウンし、新しいWorkerNodeをクラスタに追加したとき
- シンプルに新しいWorkerNodeをクラスタに追加したとき
です。

DaemonSetであれば新しいWorkerNodeで自動的に起動されてくるのですが、DeploymentやReplicasetで管理しているPodは`kubectl rollout restart`や`kubectl delete pod`で再作成してあげないと新しいWorkerNodeにスケジューリングされません。

だからといって手動でコマンドを打ちに行くのも大変なので、スケジューリング解除のためにDeschedulerを導入しました。

## WorkerNode上のPod数を平均化するために

Deschedulerのconfigmapを次のように変更しました。
```yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: descheduler-policy-configmap
  namespace: kube-system
data:
  policy.yaml: |
    apiVersion: "descheduler/v1alpha2"
    kind: "DeschedulerPolicy"
    profiles:
      - name: ProfileName
        pluginConfig:
        - name: "RemoveDuplicates"
        - name: "DefaultEvictor"
          args:
            evictSystemCriticalPods: true
            evictLocalStoragePods: true
      plugins:
        balance:
          enabled:
            - "RemoveDuplicates"
```

### Configmapで設定したDeschedulerPolicyの解説

基本戦略は`RemoveDuplicates`とし、kube-system Namespaceで動くPodやPersistentVolumeをマウントしているPodもDeschedulerによってスケジュール解除させます。

`RemoveDupulicates`は、各WokerNodeがほぼ同じ数のレプリカを起動させます。

`evictSystemCriticalPods: true` kube-systemのNamespaceで動作するPodもスケジュール解除させる。
`evictLocalStoragePods: true`   PersistentVolumeをマウントするPodもスケジュール解除させる。

## 他の使い方として
とあるPod同士を同じWorkerNode上で起動させたい時に使うPodAffinityや、Podが起動するNodeを固定したい時に使うNodeAffinityのルール違反を検知・スケジュール解除を行うこともできます。

WorkerNodeの使用リソース量をトリガーにPodのスケジュールを解除できたり、TopologySpreadConstraintで定義したルールに違反したPodのスケジュール解除を行うこともできます。

## 気を付けたいポイント
Deschedulerがスケジュールを一度に解除できるPod数に対して制限を掛けてあげる必要が出てきます。
せっかく起動してサービス提供が行われているPod全てが別Nodeへ移動することになったらサービスとしてダウンタイムが生じることになるからです。

PodDisruptionBudgetを併用したり、コネクションドレインの時間が作られるようGracefulな感じの設定を検討する必要が出てくると思います。
そのあたりは要件や用途に応じてどこまで突き詰めるか一度整理しておくと無難です。


## おわり

おわります。
Next.js Pages Router と App Router のルーティング

# はじめに
2023年5月にNext.js 13.4がリリースされ、App Router という機能が安定板扱いになりました。

https://nextjs.org/blog/next-13-4

今までの Pages Router との違いを整理するため、この記事では、Pages Router と App Router のルーティングについて、記載していきます。

# 共通点
Pages Router と App Router の両方ともファイルベースのルーティングという点では共通しています。

# Pages Router のルーティング
Pages Router のルーティングでは、```src/pages``` フォルダ配下にファイルやフォルダを追加することで、ルーティングが定義されます。

例えば、```pages/client-side-rendering.tsx``` のようにファイルを追加すると、ルーティングは、```/client-side-rendering``` になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/7fc156b2-28b5-2930-f49e-9eaa64e2844a.png)

また、```pages/renderings/client-side-rendering.tsx``` のようにフォルダを追加すると、ルーティングは、```/renderings/client-side-rendering``` になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/88b3ef66-bc8c-825c-fd2e-3bafc73202c5.png)

# App Router のルーティング
一方、App Router のルーティングでは、```src/app``` フォルダ配下にファイルやフォルダを追加することで、ルーティングが定義されます。Pages Router とは違い、**ルーティングに利用するファイル名には、```page``` をつける必要があります。**

例えば、ルーティングを ```/client-side-rendering``` にしたい場合、フォルダ・ファイル構成は、```app/client-side-rendering/page.tsx``` とする必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/a9391701-b4c6-2719-44a9-c6743bc5afb8.png)

また、```/renderings/client-side-rendering``` にしたい場合は、```app/renderings/client-side-rendering/page.tsx``` とする必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/af48c8fe-508b-2c9f-84ac-360fc8ca2962.png)

# まとめ
以上のように Pages Router と App Router の両方ともファイルベースのルーティングという点では共通しています。
ただ、 Pages Router の場合、ルーティングに利用するファイルは、他のファイルとは分け、```src/pages``` 内で管理する一方、App Router の場合、ルーティングに利用するファイルを ```src/app``` 内で他のファイルと共に管理するという点では違います。

# 参照
- [Next.js 13.4](https://nextjs.org/blog/next-13-4)
- [Routing | App Router](https://nextjs.org/docs/app/building-your-application/routing/defining-routes)
- [Routing | Pages Router](https://nextjs.org/docs/pages/building-your-application/routing)