OmniAICreator/Qiita-1.07M huggingface dataset:
【読書感想】デザイン思考２．０　人生と仕事を変える「発想術」

ランニングしながらAudibleで聴いた本の感想です。
本のまとめというより、自分が心に残ったことを3つだけ書いてます。
とりあえず思ったことをメモするのが大切と思い、なるべく30分以内で書き上げています。

# 聴いた本

デザイン思考２．０　人生と仕事を変える「発想術」 (小学館新書 440)
松本 勝 (著)

個人的には勉強になる点が多かったので、とても良い本だと思いました。（個人的満足度２．５／３、一般的なおすすめ度２．５／３）
ただし、「名著」と分類するにはカッチリしてはいないかなとも思いました。これは本書の良い点でもありますが・・

# 心に残ったこと

## デザイン思考という学問

まず、デザイン思考というものについて、「名前は聞いたことがあったけど・・・」状態だったので、学ぶことができてよかったです。

「デザイン」というと、アートと混同されがちですが、「問題解決のための手法」のことです。
例えば、「ロゴデザインをしてほしい」というと「芸術性が求められるのではないか？」と思う人が多いと思います。しかし実際は、「その集団をよく表す、ひと目で伝わるようなロゴを作りたい」という**課題に対して、解決策を提案するステップが「デザイン」なのです**。芸術のような自己実現の要素は本来不要なのです。

本書では**デザイン思考の5ステップ**も説明されていました。DX系業務で似た部分があると思ったので、参考になりました。

1. **共感**：顧客の悩みに共感するところがスタートです
1. **問題定義**：当事者を客観的に見て、取り巻く環境も考慮しながら問題を定義します
1. **創造**：解決策を創造します
1. **プロトタイプ**：創造した解決策は、**顧客には言葉では伝わらない**ため、実際の試作品を作る必要があります。
たとえば、スマートフォンの無い時代に、スマートフォンを口で説明しても人々には伝わらないでしょう。
1. **テスト**：プロトタイプを試してもらい、フィードバックをもらいます。

実際は、これら5ステップをぐるぐる何度も繰り返し、質を上げていきます。


## 人間の根源的欲求は有限

デザイン思考の使い方の説明の際に出てきた言葉です。

現代は価値観が多様化し、人によって欲しい製品がバラバラ、「無限にニーズがある」という状態かな思います。
ただ、「**製品をなぜ欲しいのか**」「**製品によって叶えたい価値**」という部分は、人によっては違うものの、ある程度パターン化されており有限とのことです。
新製品を開発するときは、**利用者の欲しいものを聞いてそれを実現するのでなく、この「人間の根源的欲求」からスタート**することで、成功する製品が生まれるとのことでした。
ただ、根源的欲求は中々教えてもらえないので、「共感」が重要なのだと思いました。

根源的欲求は、「マズローの欲求5段階」や、「マレーの欲求リスト」などがあります。
（少なすぎたり、多すぎたりして使いにくいので、ChatGPTに聞くと良いかも・・）

## DMN、CEN

脳の状態はDMN（ボーっとしている時、デフォルト・モード・ネットワーク）とCEN（集中しているとき、セントラル・エグゼクティブ・ネットワーク）の2つがあります。
アイデアはDMN、つまりボーっとしている時に生まれる事が多いらしいです。そのため、アイデアを出す立場の人は、仕事詰めというわけでなく、オンオフがある、とのことでした。
これは、よく「アイデアが出やすい3B」などがあるので、経験的に正しいかなと思います。

また、**DMNの脳のパフォーマンスはCENの質次第**、とのことでした。
つまり、集中するときにちゃんと集中していれば、ボーっとしている脳の活動も質が高く、良いアイデアが出やすい、ということです。

例えば、車の運転では、（常に集中しているわけではないですが、、）集中して運転する際の「集中」の質が高いほど、ボーッとしているときの運転が他の人より上手い、という事象が起きるのかなと思いました。
また、仕事などでも「最初は全力で取り組む」を心がければ、その後、「最初は全力で出せていたレベル」（＝後から振り返ると高くはないのですが・・・）が無意識でできて、結果的に能力が向上する、という事象が起きるのかなのかなと思いました。

## その他

### イノベーションは「想像もできないこと」と「人々が諦めていたこと」の2種類

イノベーションというと、すごい革新的で自分からは程遠い印象があります。
しかし、本書でイノベーションは2種類あるということを知って、「後者なら自分でもできるかも？」と少し思えました。

おそらく、「想像もできない」タイプのイノベーションは、一般に受け入れられず日の目を見ないケースも多いと思います。
ただ、「人々が諦めていた」タイプのイノベーションであれば、効果が出やすい・自分たちでも思いつきやすい・技術の掛け合わせなどで乗り越えていける、という良い点が多そうだと思いました。

### 「イノベーションは会社内でカニバる」

会社などで、なにか新しいことをしようとすると、よく「他の部署で同じことをしていないかを調べてほしい」となることがあると思います。
ただ、本書では「イノベーションはカニバるのが普通」ということが述べられていました。
同じような新規開発の動きが同時に起きるのは、ある程度は普通とのことです。
もちろん車輪の再開発は不毛なのですが、**「車輪の再開発が不毛」という価値観に囚われすぎなくても良い**のかなと思いました。

これは、ここ2ヶ月くらいずっと「MacBook Airと、iPad Pro+Magic Keyboard、どちらが良いのだろう」と悩んでいたので、「あっ、これがイノベーションなのか」と非常に納得できました。

### 1人のアイデアより、みんなのアイデア

「多くの人から意見をもらったほうが、良いアイデアになりやすい」と思うことが多いので心に残りました。
実際、アイデアコンペなどは、1人で出るより複数人で出たほうが圧倒的に通りやすいなと経験的に感じています。

複数人のアイデアをまとめるのは、技術的な職種からするとメンタルを結構使いますが、「3人よれば文殊の知恵」を**信じてやり続けることが重要**なのかなと思いました
VBAでWordの差し込み印刷を行う方法

ExcelのVBAでWordの差し込み印刷を行う、自分なりに納得のいく正解を見つけた気がするので記事にします。

Wordのドキュメントにセルの値を代入しようとするときに、いつもの方法で

        wdDoc.Paragraphs(2).Range.Text = Range("A1").value

という方法で代入しようと思います。
実はこの.Range.textは上書きモードであり、既存の行を消去してしまい、下の行が繰り上がったり、段落が崩れたりします。
なので上記のコードで差し込み印刷を行う場合は

      '.Paragraphs(2).Range.InsertBefore Text:= で段落の先頭に文字列を挿入
     wdDoc.Paragraphs(2).Range.InsertBefore Text:=　Range("A1").value

が正しい方法だと思われます。

段落の先頭に挿入するので改行コードを消しませんし、ダミーの文字列がある場合はその文字列の前に挿入されてしまいます。

次に私なりに納得のいく答えです

オチ　Replace関数で置換するだけ

    Sub 差し込み印刷()
    Dim wdApp As Object, wdDoc As Object

    ' Wordアプリケーションをセット
    Set wdApp = CreateObject("Word.Application")

    ' Word文書を開く（パスを指定）
    Set wdDoc = wdApp.Documents.Open("ファイルの場所")
    
    Dim target As String, change As String
    '置換したい文字列
    target = "○○○○年○○月○○日"
    'wdDoc.Paragraphs(段落番号)で段落を指定　例として2番目                              '例として今日の日付
    wdDoc.Paragraphs(2).Range.Text = Replace(wdDoc.Paragraphs(2).Range.Text, target, Format(Date, "Long Date"))
    
    '置換したい文字列
    target = "[○○○○株式会社]"
    
    '例として実際の株式会社　セルの値　可
    change = "実際の株式会社"
    
    'wdDoc.Paragraphs(段落番号)で段落を指定　例として5番目
    wdDoc.Paragraphs(5).Range.Text = Replace(wdDoc.Paragraphs(5).Range.Text, target, change)
    
    '左揃え指定（5番目以外が右揃えのせいか、なぜか右揃えになるので、左揃えに指定）
    wdDoc.Paragraphs(5).Alignment = 0

    ' Word文書を保存して閉じる
    wdDoc.SaveAs ThisWorkbook.Path & "\保存したいファイル名"
    wdDoc.Close

    ' Wordアプリケーションを終了
    wdApp.Quit

    ' 参照を解放
    Set wdDoc = Nothing
    Set wdApp = Nothing

End Sub

    target = "[宛先]"
    target = "[名前]"
    target = "[日付]"
    target = "[注文番号]"
    target = "[住所]"
    ほか何でもいいです
    ひな形に置換対象として成立する文字列を記入してください
    それを元にReplace関数で置換するだけです
Go言語の単体テストにおける[][]stringデータをマルチパートファイルに変換する実装例

# Go言語でデータをCSVファイルとしてマルチパート形式に変換する方法

## 概要
Go言語でCSVデータの情報を元にDBに更新をかけるAPIを実装をしており、その単体テストの中で`multipart.File` 型のテストデータを準備するのにすごく苦労したので記事にしました。
この関数は、`[][]string` 型のデータを受け取ってマルチパートのCSVファイルに変換し、単体テストなどで利用可能です。

## 関数の実装
以下の関数 `createMultipartDataFromSlice` は、`[][]string` 型のデータを受け取り、それをマルチパート形式のCSVファイルに変換して返します。

```go
package interactor_test

// import は省略

func TestInteractor_Invoke(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()
	mockHogeRepo := mocks.NewMockHogeRepository(ctrl)

	interactor := interactor.NewInteractor(
            mockHogeRepo,
        )

	data := [][]string{
        {"header1", "header2", "header3"},
        {"row1_col1", "row1_col2", "row1_col3"},
        {"row2_col1", "row2_col2", "row2_col3"},
    }
    
    // 今回紹介するmultipart.Fileを生成する関数
    file, err := createMultipartDataFromSlice(data)
    if err != nil {
        fmt.Printf("Failed to create multipart file: %v\n", err)
        return
    }
    defer file.Close()

    content, err := io.ReadAll(file)
    if err != nil {
        fmt.Printf("Failed to read CSV: %v\n", err)
        return
    }
    fmt.Println(string(content))

    ctx := context.Background()
    testCases := []struct {
        // Field
        setupMocks    func()
        expectedError error
    }{
        {
            // test cases
        },
    }
	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			tc.setupMocks()
			err := interactor.Invoke(ctx, file)
			if tc.expectedError != nil {
				assert.Error(t, err)
				assert.Equal(t, tc.expectedError, err)
			} else {
				assert.NoError(t, err)
			}
		})
	}
}

// 指定された`[][]string`型のデータをマルチパートデータに変換
func createMultipartDataFromSlice(data [][]string) (multipart.File, error) {
	var buf bytes.Buffer
	writer := multipart.NewWriter(&buf)

	// フォームファイルとしてデータを追加する
	part, err := writer.CreateFormFile("file", "test.csv")
	if err != nil {
		return nil, fmt.Errorf("error creating form file: %w", err)
	}

	// CSVライターを作成してデータを書き込む
	csvWriter := csv.NewWriter(part)
	err = csvWriter.WriteAll(data)
	if err != nil {
		return nil, fmt.Errorf("error writing data to CSV: %w", err)
	}

	// ライターを閉じてマルチパートデータを完成させる
	csvWriter.Flush()
	writer.Close()

	// バッファを *os.File に変換する一時ファイルを作成する
	tmpFile, err := os.CreateTemp("", "test-*.csv")
	if err != nil {
		return nil, fmt.Errorf("error creating temp file: %w", err)
	}
	_, err = tmpFile.Write(buf.Bytes())
	if err != nil {
		return nil, fmt.Errorf("error writing to temp file: %w", err)
	}

	// tmpFileを再度読み取れるようにカーソルを先頭に戻す
	if _, err := tmpFile.Seek(0, io.SeekStart); err != nil {
		return nil, fmt.Errorf("error seeking temp file: %w", err)
	}

	return tmpFile, nil
}

```

```
=== RUN   testInteractor_Invoke
--56d604397513fcbd3154df6a39aa9da7bfe68612e54db46788fd4faf5ceb
Content-Disposition: form-data; name="file"; filename="test.csv"
Content-Type: application/octet-stream

header1,header2,header3
row1_col1,row1_col2,row1_col3
row2_col1,row2_col2,row2_col3
```


まとめ
この関数を使用することで、Goプログラム内でテストしたいcsvデータを[][]stringで準備してあげつ事でマルチパート形式のファイルに変換し、単体テストや他の用途（実装でも使えたりする？）で利用できます。
【Simple PAY.JP Payment】カード名義バリデーション変更の対応あり？

ないとも言えん結果に

2025年4月1日より、PAY.JPのカード決済において、カード名義欄にクレジットカード番号やセキュリティコードのような機密情報とみなされる数字が入力された場合、従来のアスタリスク変換処理からエラーを返すように変更されるとのことですね。

ご提示のWordPressプラグイン「Simple PAY.JP Payment」のコードを拝見した限りでは、**この変更による直接的な影響は少ない**と考えられます。

理由としては、以下の点が挙げられます。

*   **カード名義欄（`card[name]`）をプラグイン側で明示的に扱っていない:**  コードを確認したところ、`simplepayjppayment_create_payment` や `simplepayjppayment_create_customer` などのPAY.JP APIを呼び出す関数で、`card[name]` パラメータを明示的に設定している箇所は見当たりません。
*   **PAY.JP Checkoutを利用している:** プラグインは `checkout.pay.jp` を利用しており、決済フォームのカード情報入力部分はPAY.JP側でホストされています。カード名義のバリデーションチェックは、このPAY.JP Checkoutの処理の中で行われると想定されます。

**考えられる影響と対応:**

*   **プラグインのフォーム自体は影響を受けにくい:**  プラグインが生成するフォームには、メールアドレスと名前の入力欄はありますが、カード名義を直接入力する欄はありません。そのため、プラグインの基本的な機能は今回の変更で直接的に動作しなくなる可能性は低いでしょう。
*   **ユーザーへの注意喚起は必要:**  ただし、ユーザーが誤ってカード名義欄に機密情報を入力してしまう可能性はゼロではありません。プラグインのフォームの説明文などで、カード名義欄には**カードに記載されている名義人の名前**を入力するように明確に指示することを推奨します。
*   **念のためテストは実施:** 2025年4月1日以降、実際にプラグインを利用してカード決済をテストし、問題がないか確認することを推奨します。もしエラーが発生するようであれば、PAY.JPのお知らせ ([https://pay.jp/info/2025/02/10/110000](https://pay.jp/info/2025/02/10/110000)) を再度確認し、必要に応じてプラグインの修正を検討してください。
*   **開発会社や製品提供元への確認:**  メールにも記載があるように、開発を外部に委託されている場合や、PAY.JP決済がパッケージ化されている製品を利用している場合は、念のため開発会社や製品提供元にも今回の変更について確認しておくとより安心です。

**まとめ:**

「Simple PAY.JP Payment」プラグインは、今回のカード名義バリデーション変更による直接的な影響は少ないと考えられますが、ユーザーへの注意喚起やテスト実施による確認を行うことを推奨します。

ご不明な点や、さらに詳細なご質問がありましたら、お気軽にお尋ねください。
【Linux】よく使うコマンドと使用タイミングをまとめてみた

### はじめに

この記事ではLinuxでよく使うコマンドとその使用例を簡単に載せています。
利用法を忘れた際にご覧いただければと思います

---

### **📝 Linuxコマンド解説**  

#### **📂 移動・ディレクトリ操作**  

- **`cd` (Change Directory)**  
  - **ディレクトリを移動**するためのコマンド。  
  - 例: `cd /home/user/Documents` → `/home/user/Documents` に移動  
  <br>

- **`pwd` (Print Working Directory)**  
  - **現在のディレクトリのパスを表示**する。（カレントディレクトリともいう）  
  - 例: `pwd` → `/home/user`  
  <br>

- **`ls` (List)**  
  - **ディレクトリの中のファイルやフォルダを一覧表示**する。  
  - 例: `ls -l` → 詳細な情報付きで表示  
  <br>

- **`mkdir` (Make Directory)**  
  - **新しいディレクトリを作成**する。  
  - 例: `mkdir new_folder` → `new_folder` を作成  
  <br>

- **`rmdir` (Remove Directory)**  
  - **空のディレクトリを削除**する。  
  - 例: `rmdir old_folder` → `old_folder` を削除  
  <br>

#### **📄 ファイル操作**  

- **`cat` (Concatenate)**  
  - **ファイルの内容を表示**する。(本来の文字の意味的には複数のファイルを連結するコマンドだが、ファイル1つ指定でその内容を表示するコマンドとして使用されることが多い)  
  - 例: `cat file.txt` → `file.txt` の内容を表示  
  <br>

- **`less`**  
  - **ファイルの内容をスクロールしながら表示**する。  
  - 例: `less file.txt` → `file.txt` の表示を制御できる。（`cat`で表示しようとすると、行数が多い場合は表示が流れて行ってしまうため）  
  <br>

- **`tail`**  
  - **ファイルの末尾を表示**する。  
  - 例: `tail -n 10 file.txt` → `file.txt` の最後の10行を表示  
  <br>

- **`touch`**  
  - **空のファイルを作成**する、または**既存のファイルの更新日時を変更**する。  
  - 例: `touch newfile.txt` → `newfile.txt` を作成  
  <br>

- **`rm` (Remove)**  
  - **ファイルを削除**する。  
  - 例: `rm file.txt` → `file.txt` を削除  
  <br>

- **`mv` (Move)**  
  - **ファイルやディレクトリを移動・名前変更**する。  
  - 例(移動): `mv sample.txt  dir` → `sample.txt` を `dirディレクトリ` に移動
  - 例(名前変更): `mv oldname.txt newname.txt` → `oldname.txt` を `newname.txt` に変更  
  <br>

- **`cp` (Copy)**  
  - **ファイルやディレクトリをコピー**する。  
  - 例: `cp file.txt copy.txt` → `file.txt` を `copy.txt` にコピー  
  <br>

- **`ln` (Link)**  
  - **ファイルのハードリンクやシンボリックリンクを作成**する。  
  - 例: `ln -s target_file link_name` → `target_file` のシンボリックリンクを `link_name` で作成  
  - ▼より詳細を知りたい方は以下記事を参考にしてみてください

  
https://qiita.com/mitsumizo/items/3c266699d9ca7a712108

  <br>

#### **🔎 検索・アクセス権限操作**  

- **`find`**  
  - **ファイルやディレクトリを検索**する。  
  - 例: `find /home -name "*.txt"` → `/home` 内の `.txt` ファイルを検索  
  - ▼より詳細を知りたい方は以下の記事を参考にしてみてください

https://qiita.com/ko1nksm/items/7fec71f78a394a80ed2b

  <br>

- **`chmod` (Change Mode)**  
  - **ファイルやディレクトリのアクセス権を変更**する。  
  - 例: `chmod 755 script.sh` → `script.sh` に実行権限を付与  
  <br>

- **`chown` (Change Owner)**  
  - **ファイルやディレクトリの所有者を変更**する。  
  - 例: `chown user:user file.txt` → `file.txt` の所有者を `user` に変更  
  <br>

#### **🖥 プロセス管理**  

- **`ps` (Process Status)**  
  - **現在動作しているプロセスを表示**する。  
  - 例: `ps aux` → 実行中のプロセス一覧を詳細表示  
  <br>

- **`kill`**  
  - **プロセスを終了させる**。  
  - 例: `kill 1234` → プロセスID 1234 を終了  
  <br>
VB.Net（ASP.Net） ユーザーコントロールの作成

## VB.Netでのデザイン作成

### 前提
VB.Netのデザイン部分の記法です。
フレームワークは、VB.Net 4.7.2を利用しています。
BootStrap 5.3.3を利用。

### 1.ユーザーコントロールの作成
ASP.Net（VB.Net）を利用してのWebアプリの開発をしています。
デザインの開発の際、個々の画面とほかの画面が、
共有の部分を利用していて、共通化ができるかもといった際に、
利用してみてください。

こんなコントロールを想定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537494/eb5c72e3-809f-4538-82f6-e70fa29f9702.png)


### 2.デザインのコード例
例えば、以下のコントロールを別の画面でも利用する場合、
```
        
        <table class="cp0">
            <tr>
                <td>
                    <asp:TextBox ID="txtMsg" runat="server"></asp:TextBox>
                </td>
            </tr>
            <tr>
                <td style="width:100px">
                    <asp:TextBox ID="txtHours" Width="20px" runat="server"></asp:TextBox>
                    :
                    <asp:TextBox ID="txtMinutes" Width="20px" runat="server"></asp:TextBox>
                    <asp:Button ID="btnOk" Text="OK!" Width="50px" CssClass="btn btn-primary btn-sm" runat="server" />
                </td>
            </tr>
        </table>
        <asp:RegularExpressionValidator ID="revtxtMinutes" runat="server"
            ControlToValidate="txtMinutes"
            ValidationExpression="^\[0-6][0-9]$"
            ErrorMessage="0-60の数値のみ入力してください。"
            ForeColor="Red"
            Display="Dynamic">
        </asp:RegularExpressionValidator>
    </form>

```

ユーザーコントロールを作成します。
ソリューションエクスプローラー
ソリューション右クリック
追加クリック
新しい項目クリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537494/a2c617b3-a980-4a34-b573-56da2256cc3f.png)

Webフォームのユーザーコントロールをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537494/b6744137-156c-42e0-a29b-00fd87c6cd15.png)

名称をつけて、追加をクリック

デザイン側に先ほどの画面のコードを貼り付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537494/03549b25-7bc8-4185-8ae9-a63cac25ad90.png)
こういった形で、共通の画面コントロールが作成できます。

では、SampleWebPage1に上記のコントロールを置いてみます。

### ポイント1
```
<%@ Register Src="~/WebUserControl.ascx" TagName="uc" TagPrefix="UserControl1" %>
```
ユーザーコントロールの定義を行うこと

ポイント2
```
<UserControl1:uc ID="Control1" runat="server" />
```
ユーザーコントロールの実装を行うこと

見た目上、上と下で違いが分かりづらいですが、上がユーザコントロールです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537494/bb2fc017-43cd-4679-8cb4-f2a894e1ce3f.png)

### まとめ
ユーザコントロールを作成する方法を記載しました。
同じデザインを流用する際は、デザインをユーザコントロールとして作成。
そのユーザーコントロールをページ側で実装が可能です。
【競技プログラミング】AtCoder Beginner Contest 369_D問題

# 問題
https://atcoder.jp/contests/abc369/tasks/abc369_d

# 既存投稿一覧ページへのリンク
[一覧ページ](https://qiita.com/o_chan_t/items/fc759695acfaef8df2cc)


# 解法手順1

`dp[i][j]` を以下のように定義する
- `i`: i番目のモンスターまで考慮した場合
- `j`: 0なら偶数回、1なら奇数回モンスターを倒した場合
- 値: その状態での最大経験値

## 初期化

1. `dp`テーブルを十分大きな負の値（ここでは $-10^{18}$）で初期化する。
2. `dp = 0` とする。これは、まだモンスターを倒していない初期状態を表す。

## DPの遷移

各モンスター `i` （1からNまで）に対して、以下の2つの選択肢を考慮する

1. モンスターを逃がす場合：
   - `dp[i+1][0] = max(dp[i+1][0], dp[i])`
   - `dp[i+1][1] = max(dp[i+1][1], dp[i][1])`

2. モンスターを倒す場合：
   - 偶数回目の場合（追加経験値あり）：
     `dp[i+1][0] = max(dp[i+1][0], dp[i][1] + a[i] * 2)`
   - 奇数回目の場合：
     `dp[i+1][1] = max(dp[i+1][1], dp[i] + a[i])`

これらの遷移を全てのモンスターに対して行う。

## 最終結果の出力

全てのモンスターを考慮した後、`dp[N]` と `dp[N][1]` の大きい方が答えとなる。


# ACコード1
```python:ac.py
import logging

def setup_logger(debug_mode):
    logger = logging.getLogger(__name__)
    if not logger.handlers:
        logger.setLevel(logging.DEBUG if debug_mode else logging.INFO)
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        
        file_handler = logging.FileHandler('program_trace.log', encoding="utf8")
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)
    
    logger.debug("ロガーのセットアップが完了しました。デバッグモード: %s", debug_mode)
    return logger

def io_func():
    n = int(input())
    monster_strengths = list(map(int, input().split()))
    return n, monster_strengths

def solve(n, monster_strengths):
    logger = setup_logger(True)
    
    inf = 10**18
    dp = [[-inf, -inf] for _ in range(n + 1)]
    dp[0][0] = 0
    
    logger.debug(f"初期化: n = {n}, monster_strengths = {monster_strengths}")
    logger.debug(f"DPテーブルの初期状態: dp = {dp}")

    for i in range(n):
        dp[i+1][0] = max(dp[i][0], dp[i][1] + monster_strengths[i] * 2)
        dp[i+1][1] = max(dp[i][1], dp[i][0] + monster_strengths[i])
        logger.debug(f"ステップ {i+1}: dp[{i+1}] = {dp[i+1]}")

    max_experience = max(dp[-1])
    logger.debug(f"最終結果: max_experience = {max_experience}")
    return max_experience

def main():
    n, monster_strengths = io_func()
    result = solve(n, monster_strengths)
    print(result)

if __name__ == "__main__":
    main()

```
Bluetoothの通信プロトコル/プロファイルなど(ホスト)

本記事では、個人のCore資料の理解と忘備録を兼ねて、Core資料に沿ってBluetoothの各役割や通信の流れについて整理していきたいと思います。
(解釈が誤っている部分があれば指摘いただけると嬉しいです！)

本日はホストの通信プロトコル/プロファイルなどアーキテキチャブロックについてまとめていきたいと思います。
前回と同じ図がわかりやすいので、図を載せて説明していきたいと思います。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4024363/987b81af-6a16-48a9-92ac-d2bfe29c7a02.png)

## 通信プロトコルとその役割
ざっくりとホストにおけるそれぞれの通信プロトコルと役割です。

| プロトコル | 役割 |
|------------|--------------------------------------|
| L2CAP  | 基本的なデータフレームの転送を管理 |
| ATT    | 属性データのやり取り（GATTの基盤となる） |
| SDP    | BR/EDR用のサービスディスカバリ |
| SMP    | 暗号鍵の交換やペアリングの管理 |


| プロファイル| 	役割| 
|------------|--------------------------------------|
| GATT	| サービスとキャラクタリスティックの管理| 
| GAP	| デバイスの検出や接続管理、セキュリティ設定| 

それぞれ詳細を説明していきます。

## ロジカルリンクコントロールアンドアダプーテーションプロトコル(L2CAP)
L2CAPは、データ転送を管理するプロトコルです。アプリケーションや上位プロトコルのデータを受け取り、パケットの分割・再構成を行います。また、QoS（Quality of Service）を制御します。BR/EDRとLEの両方で使用され、論理チャネルの管理も担当します。


## セキュリティマネージャープロトコル（SMP）

SMPは、BLEにてセキュリティ機能を担うプロトコルです。L2CAPチャネル上で動作します。
主に下記の3つの機能があります。
・暗号化キー：ペアリング時に、デバイス同士で共有する暗号鍵を交換します。
・識別キーの管理：デバイスの識別情報（例：IRK）を管理し、ランダムアドレスを解決します。
・ペアリングとセキュリティの確立：デバイス間で認証を行い、安全な通信を保証します。

また、SMPはホスト側で実装され、HCIコマンドを介してコントローラと連携します。
一部の機能はコントローラ側に任せるホストもあれば、ホスト側で生成することもあります。(DHKEYなど)

一方、Classic(BR/EDR)では、同様の機能がリンクマネージャ（Link Manager）によってコントローラ側で処理されます。

## アトリビュートプロトコル（ATT）

ATTは、ATTサーバとATTクライアント間の1対1通信を実装するプロトコルです。
ATTクライアントは、リモートデバイスのATTサーバと、L2CAPチャネルを介して通信します。

ATTクライアントは、コマンド、リクエスト、確認メッセージをATTサーバに送信し、ATTサーバはレスポンス、通知、インディケーションをクライアントに送信します。
これにより、ATTクライアントはピアデバイス（ATTサーバ）上の属性（Attribute）の値を読み書きできるようになります。

## ジェネリックアトリビュートプロファイル（GATT）

GATTは、ATTサーバの機能、および必要に応じてATTクライアントの機能を定義します。
このプロファイルでは、ATTサーバ内のサービス、キャラクタリスティック（特性）、および属性の階層構造を規定しています。

GATTは、サービスやキャラクタリスティックの探索（ディスカバリ）、読み取り、書き込み、通知（Indication）を行うためのインターフェースを提供します。


## ジェネリックアクセスプロファイル（GAP）

GAPは、すべてのBluetoothデバイスに共通する基本的な機能を提供するプロファイルです。
GAPは、以下のような機能を定義します。

- デバイスの検出
- 接続モードの管理
- セキュリティと認証
- デバイスペアリングの仕組み
- サービスディスカバリ

GAPは、Bluetoothの通信プロトコルやアプリケーションプロファイルの基盤となる重要なプロファイルになっています。

## サービスディスカバリプロトコル（SDP）

サービスディスカバリプロトコル（SDP）は、クライアントが必要なサービスを検索できる仕組みを提供するプロトコルです。
検索は、特定のサービス属性に基づいて行われるほか、サービスの種類（クラス）による検索や、データベース全体のブラウジングも可能です。

SDPはBR/EDRデバイスで使用され、BR/EDRプロファイルのサービスディスカバリに利用されます。
SDPは、Bluetoothデバイス上で提供されるサービスの検出に特化しており、一度サービスを発見した後のアクセス方法（通信方法）は、サービスごとに異なる仕様となります。

---
Classicはあまり触ったことがなく、SDPの説明はCoreの資料そのまま持ってきています。間違えてしまっていたら、教えていただけると嬉しいです。

次回は、コントローラの通信プロトコルにします。
ExcelVBA 自动批量写入随机数的方法

这个函数能够将Date表里面存储的数据，用随机抽取的方式，转写到新的表里面
如果稍加修改，将ThisWorkbook.Worksheets("DATE").Cells(ret, "H")部分换掉改成ret，
则可以变成获取iMax到iMin范围内的随机数
```
Sub AUTO_INPUT()
    Dim iMax As Double
    Dim iMin As Double
    Dim arrcols As Variant
    iMax = 5
    iMin = 2
    arrcols = Array("B", "C")
    For i = 4 To 10005
        'ret = Format(Fix((iMax - iMin + 1) * Rnd + iMin), "0")
        For Each j In arrcols
            ret = Format(Fix((iMax - iMin + 1) * Rnd + iMin), "0")
            Cells(i, j) = ThisWorkbook.Worksheets("DATE").Cells(ret, "H")
        Next j
    Next i
End Sub
```
iMax 是取得的最大值（包含）  
iMin 是取得的最小值（包含）  
arrcols 是写入的列名称，这里写的内容西会在后面的 For Each里面被转换出来  
这里用数组的好处是，可以随意指定列，并且会通过一次执行全部执行到  
上面例子里，B，C列将被追加数据
for i 为需要写入数据的行号
Format 用于控制最后的输出格式，这里是使用的是“0”，也可以是“0.00”，“00.00”或者任意的位数的格式
ThisWorkbook.Worksheets("DATE") 里面的DATE是放存储需要的数据表的表名称，可以随意修改
Cells(ret, "H")里面的ret，是前面获得的随机数，H是Date表里存放随机获取数据的所在列
Excel VBA 批量写入设定范围内的随机日期

这个函数用于获取fstDate到lstDate之间的随机日期
```
Sub AUTO_CALENDAR()
    Dim fstDate As Date
    Dim lstDate As Date
    fstDate = #1/1/2023#
    lstDate = #12/31/2025#
    col = "K"
    For i = 2 To 10001
        Cells(i, col) = CStr(Format(Int(lstDate - fstDate + 1) * Rnd + fstDate, "yyyyMMdd"))
    Next i
End Sub
```

fstDate　是随机写入日期范围的初始日期值（包含）
lstDate 是随机写入日期范围的截至日期（包含）
for i 为需要写入数据的行号
col 是写入位置的列名
AWS ANSに合格したので、直前で理解漏れていたポイントをまとめてみた

# AWS 合格しました
![スクリーンショット 2025-03-04 200705.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4016542/592de01c-87ed-4a53-8b57-bda9b14ffd53.png)

巷では最難関ともいわれていますが、個人的には難易度はDOP＞SAPro＞SCS＞ANSという感じでした。
勉強時間は平日30分～1時間　休日2~3時間を1.5か月程度しました。


# AWS ANS試験で躓きやすいポイント
注：あくまで試験用です。実際のサービスはアップデートあって今はできるよ！とかは普通にあります。

## VPC

- VPCピアリングはCIDR重複には使用できない。
- CIDRが重複している場合は、AWS PrivateLinkを設定し、インターフェースエンドポイントで作成されたDNS名を使用して通信する。
- BGPセッションの確立には、TCPポート179の通信が必要。
- パブリックNATゲートウェイにはインターネットゲートウェイが必要。IGWがない場合は、プライベートNATゲートウェイを使用する。
- S3ゲートウェイエンドポイントはVPC内のリソース向けに用意されており、オンプレミス環境からS3にアクセスする際はインターフェースエンドポイントを使用する。
- VPC内のリソース間の到達性は、VPC Reachable Analyzerを使用して確認する。CloudTrailでNetwork ACL、ルートテーブル、セキュリティグループの変更を検知できる。

## グローバルアクセラレータ

- グローバルアクセラレータには2種類あり、複数のALBなどの宛先にルーティングしたい場合は、標準ではなくカスタムルーティングアクセラレータを使用する。
- カスタムルーティングアクセラレータを使用する場合、Route53はレイテンシベースのルーティングを設定する必要がある。
- Global AcceleratorのAnycast IPを利用することで、グローバルなユーザーが最小限のレイテンシでアクセスできるようになる。

## PrivateLink

- PrivateLinkはVPC間の通信をAWSの内部ネットワークを利用する仕組み。VPC間のきめ細やかなルーティングは、Transit GatewayよりもPrivateLinkを使用した方が良い。
- PrivateLinkを利用する際はNLBが必要で、ALBを使用している場合は前段にNLBを挿入する。

## Transit Gateway

- Transit Gatewayはリージョナルサービスで、各トランジットゲートウェイをピアリングさせることができる。
- 同じ仮想プライベートゲートウェイで終端する複数のVPN接続を作成でき、すべてのVPN接続を同時に使用するために等コストのマルチパス（ECMP）ルーティングを設定する。
- マルチリージョン、マルチBUの場合は、Transit GatewayとVPCルートテーブルよりもAWS Cloud WANのセグメント機能を利用することで、BUごとにネットワークの論理区画を柔軟に作成できる。
- トランジットゲートウェイとSD-WAN仮想ハブをネイティブに統合することで、複数のVPCを一元的に管理しやすくなる。

## Route53

- プライベートホストゾーンにはゾーン転送の概念はない。
- DNSSECでは2種類のキーがあり、ZSKはゾーンを署名し、KSKはZSKを認証する。Route 53ではAWSがZSKを自動でローテーションし、KSKは手動で管理する必要がある。

## Direct Connect

- OSPFはサポートされておらず、BGPがサポートされている。
- SiteLink機能を有効にすることで、Direct ConnectゲートウェイとトランジットVIFの既存の構成を利用しつつ、オンプレミス間のトラフィックをAWSバックボーン経由に切り替えられる。
- Direct Connectそのものには暗号化の機能はないが、パブリックVIFを利用したSite to Site VPNで暗号化できる。

## ネットワークファイアウォール

- ステートフルルールグループのプレフィックスリストを参照することで、オートスケーリング時も常に最新の状態を保てる。

## ELB

- NLBでクロスゾーンロードバランシングをオフにすることで、同じアベイラビリティゾーン内に健康なターゲットが存在する限り、トラフィックをローカルに留めることができる。
- GWLBを使用した構成では、ゲートウェイルートテーブルを適切に設定する必要がある。
- ゲートウェイロードバランサー（GWLB）はレイヤー4のロードバランサーであり、ALBのようにヘッダーを見て処理することはできない。
- Gateway Load BalancerはGeneveトンネル（ポート6081）を使用してトラフィックを転送し、ファイアウォールアプライアンスとの間でパケットをやり取りする。
- ALBはIPアドレスを固定化できないため、固定化したい場合はプライベートNATゲートウェイを使用する。
- ALB、CLB、CloudFrontはUDP処理ができない。
- ALBにはCNAMEではなくエイリアスレコードを使用する。

## その他

- GuardDutyを使用して、過度に許可的なルールをモニタリングできる。
- クライアントIPアドレスを伝えるヘッダーは「X-Forwarded-For」。

## すごく参考になったサイト

- 非対称通信のアプライアンスモードの話
https://blog.serverworks.co.jp/aws-transit-gateway-appliance-mode
- グローバルアクセラレータの話
https://qiita.com/zumax/items/527fe685a322e44f956e
IAM Identity Centerにユーザーを一括で作成する

簡単なスクリプトを作りました。
せっかくなのでOSSにして公開しておきます。
- 既にusernameが存在している場合は無視されます。

https://github.com/nidcode/aws-idc-import



# aws-idc-import

## 概要

このプロジェクトは、AWS IAM Identity Center（旧AWS SSO）を使用して、CSVファイルからユーザーとグループを作成し、ユーザーをグループに追加するスクリプトです。

## ファイル構成

- `settings.yml`: IAM Identity CenterのIdentity Store IDおよびSSOプロファイル名を設定するための設定ファイル。
- `main.py`: メインのスクリプトファイル。ユーザーとグループの作成、ユーザーのグループへの追加を行います。
- `users.csv`: ユーザー情報を含むCSVファイル。ユーザー名、氏名、メールアドレス、グループ情報が含まれます。

## 事前準備 AWS SSO 設定手順

1. AWS CLIをインストールしていない場合は、インストールします：

    ```bash
    pip install awscli
    ```

2. AWS SSOを設定します：

    ```bash
    aws configure sso
    ```

3. プロンプトに従って、SSOの設定を完了します。 

## 使い方

1. `settings.yml`ファイルを作成し、以下の内容を設定します：

    ```yaml
    IDENTITY_STORE_ID: 'your-identity-store-id'
    SSO_PROFILE: 'your-sso-profile'
    ```

2. `users.csv`ファイルを作成し、以下の形式でユーザー情報を入力します：

    ```csv
    username,first_name,last_name,email,groups
    johndoe,John,Doe,johndoe@example.com,group1;group2
    ```

3. `requirements.txt`ファイルに記載されたパッケージをインストールします：

    ```bash
    pip install -r requirements.txt
    ```

4. スクリプトを実行します：

    ```bash
    python main.py
    ```

## 注意事項

- `settings.yml`ファイルには、適切なIdentity Store IDおよびSSOプロファイル名を設定してください。
- `users.csv`ファイルには、ユーザー情報を正確に入力してください。
- AWS CLIが設定されている必要があります。

## ライセンス

このプロジェクトはMITライセンスの下で提供されます。

## バージョン情報

- Python: 3.x
- boto3: 最新バージョン
作業メモ 押せるボタンのCSS

この組み合わせで押したら動くぼたんｎ
<button class="button">Click Me</button>

.button {
  background-color: #3498db;
  color: #fff;
  font-size: 16px;
  font-weight: bold;
  padding: 12px 24px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease-in-out;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.15);
  display: inline-block;
}

.button:hover {
  background-color: #2980b9;
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2);
  transform: translateY(-2px);
}

.button:active {
  background-color: #2471a3;
  box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
  transform: translateY(1px);
}
PassitCertifyの学習資料でGoogle Professional-Cloud-Architect認定試験に合格しよう


プロフェッショナル認定の取得は、キャリアを前進させるための重要なステップです。Google Professional-Cloud-Architect試験は、あなたの専門知識を証明し、プロフェッショナルとしての信頼性を高め、新たな就職機会を開くものです。しかし、この試験に合格するには、徹底した準備、適切な学習資料、そして戦略的な練習が必要です。ここでPassitCertifyが役立ちます。PassitCertifyは、一発合格を目指す受験者のために、Google Professional-Cloud-Architect試験対策に最適な学習資料を提供しています。

Google Professional-Cloud-Architect認定が重要な理由

Google Professional-Cloud-Architect認定は業界内で高く評価されており、以下のような多くのメリットをもたらします。

キャリアアップ: 認定を取得した専門家は、より良い職位と高い給与を得る可能性が高くなります。
業界での評価: 企業は認定を持つ候補者を高く評価し、未認定の応募者に対して優位性を与えます。
スキル向上: 最新の知識と実践的なスキルを身につけることができます。
競争力の強化: 急速に変化する市場の中で、認定は差別化要因になります。
キャリアを真剣に考えているなら、Google Professional-Cloud-Architect認定の取得は将来への賢明な投資です。

Google Professional-Cloud-Architect試験準備の一般的な課題
多くの受験者がGoogle Professional-Cloud-Architect試験の準備に苦労する理由として、以下のようなものがあります。

広範な試験範囲: 試験は複数の分野をカバーしており、包括的な学習が必要です。
複雑な問題形式: 多くの問題はシナリオベースで、単なる暗記ではなく深い理解が求められます。
時間管理の難しさ: 仕事や私生活と勉強のバランスを取るのが難しいことがあります。
信頼できる学習資料の不足: すべての教材が最新の試験範囲に適しているわけではありません。
これらの課題を克服するためには、PassitCertifyのプレミアム学習資料を活用した戦略的な学習計画が成功の鍵となります。

PassitCertifyがProfessional-Cloud-Architect試験合格をサポート

PassitCertifyは、Google Professional-Cloud-Architect試験を簡単にクリアするために、専門的に作成された試験対策教材を提供しています。以下の点で優れています。

1. 本番試験に基づいた実践問題
PassitCertifyは、最新の試験傾向を反映した本番試験に近い問題を提供しています。試験範囲を網羅した問題を解くことで、試験形式に慣れることができます。

2. 多様な学習フォーマットで柔軟な学習
学習スタイルは人それぞれ異なります。そのため、PassitCertifyは3つの柔軟なフォーマットで学習資料を提供しています。

PDFフォーマット: ダウンロード・印刷可能でオフライン学習に最適。
デスクトップ版模擬試験ソフト: 実際の試験環境をシミュレーションし、時間制限付きで練習が可能。
Webベース模擬試験: インストール不要で、どのデバイスからでもアクセス可能。
3. 専門家による監修と定期的な更新
すべての学習資料は、業界の専門家によってレビューされ、最新の試験シラバスに準拠しています。定期的な更新により、常に最新の試験内容に対応できます。

4. カスタマイズ可能な模擬試験で自己評価
受験準備の効果を測る最善の方法は、カスタマイズ可能な模擬試験です。PassitCertifyでは、トピック別や難易度別にテストをカスタマイズし、弱点を特定して克服することができます。

5. 24時間365日対応のカスタマーサポート
試験勉強はストレスが伴うものですが、PassitCertifyの24時間365日対応のカスタマーサポートがあれば、いつでもサポートを受けられます。学習の妨げを最小限に抑え、スムーズに準備を進めることができます。

🎉 限定オファー！PassitCertifyの学習資料が35%オフ！ 🎉
この特別割引を活用し、Google Professional-Cloud-Architect試験対策をお得に始めましょう！期間限定で、PassitCertifyの全学習資料が35%オフになります。高品質な学習リソースをお得な価格で手に入れるチャンスをお見逃しなく！今すぐ割引を適用して、合格への道を加速しましょう！

Download Professional-Cloud-Architect Exam Questions 2025: https://www.passitcertify.com/google/professional-cloud-architect-questions.html

Google Professional-Cloud-Architect合格のための効果的な学習法
PassitCertifyの学習資料を活用するだけでなく、以下の学習戦略を取り入れることで、試験合格率をさらに高めることができます。

✅ 学習計画を立てる: 試験範囲を確認し、各トピックに十分な時間を割り当てる。
✅ 定期的に模擬試験を受ける: 試験形式に慣れ、自信をつけるために模擬試験を活用する。
✅ 苦手分野を重点的に対策: 自分の弱点を特定し、集中的に学習する。
✅ 継続的に学習する: 毎日の学習と復習を習慣化し、知識を定着させる。

まとめ
Google Professional-Cloud-Architect認定を取得することで、キャリアの可能性を大きく広げることができます。しかし、試験に合格するには適切な準備と学習戦略が不可欠です。

PassitCertifyの業界最高水準の学習資料を活用すれば、本番試験と同様の環境で練習でき、効率的に試験対策を進めることが可能です。

 確実に合格したいなら、今すぐPassitCertifyの学習資料を手に入れましょう！
あなたの成功を全力でサポートします。
MySQLのパフォーマンス改善（同期タイミング調整）

# MySQLのパフォーマンス改善（同期タイミング調整）
以前パフォーマンス改善でパーティショニングについて記載しました。今回は、書き込み時のパフォーマンスについて観点を当てて記載します。
過去構築したシステムをAWSのMySQLに移行する際、データ登録の処理が遅延し、パンクする事象があったため、調べた内容になります。

今回記載するsync_binlogの設定や、関連するパラメータ（innodb_flush_log_at_trx_commit など）を適切に調整することで、トランザクションの安全性とパフォーマンスのバランスを取ることができます。

# sync_binlogの役割と設定
`sync_binlog` は、バイナリログ（Binlog）の同期タイミングを制御するパラメータです。ディスク書き込みの頻度が高いほどパフォーマンスは低下します。デフォルトは`1`になっています。他のパラメータは以下

| 値        | 説明                      | パフォーマンス | データ耐久性               |
| -------- | ----------------------- | ------- | -------------------- |
| `0`      | OSのキャッシュに任せ、明示的な同期を行わない | 高速      | クラッシュ時にデータ損失のリスクあり   |
| `1`      | トランザクションごとにバイナリログを同期    | 低速      | クラッシュ耐性が最も高い         |
| `N (>1)` | N回のトランザクションごとにバイナリログを同期 | 中程度     | データ損失は最大N回のトランザクション分 |

設定のイメージは以下:

- 高パフォーマンスを求める場合: `sync_binlog = 1000` ※最大1000回のトランザクションデータ紛失可能性あり、ここが大きいほど耐久性は低下
- クラッシュ耐性を重視する場合: `sync_binlog = 1`
- レプリケーションを使用しない場合: `sync_binlog = 0` も検討可能

データが損失することを完全に許容しないのであれば`1`のまま運用することが望ましいですが、最新データの紛失がある程度は許容できるシステムであることと性質上大量のデータが書き込まれる仕組みのため、今回はパフォーマンスを優先し設定を変更しました。

# 関連する他のパラメータ

## `innodb_flush_log_at_trx_commit`

このパラメータは、トランザクションコミット時のログのフラッシュ方法を制御するパラメータです

| 値   | 説明                            | パフォーマンス | データ耐久性                |
| --- | ----------------------------- | ------- | --------------------- |
| `0` | OSのキャッシュに任せる（1秒ごとにフラッシュ）      | 高速      | クラッシュ時にデータ損失のリスクあり    |
| `1` | トランザクションごとにログをフラッシュ           | 低速      | クラッシュ耐性が最も高い          |
| `2` | コミット時にログを書き込むが、ディスクフラッシュは1秒ごと | 中程度     | クラッシュ時に1秒分のデータ損失リスクあり |

設定のイメージは以下:

- `innodb_flush_log_at_trx_commit = 1`（データ耐久性重視）
- `innodb_flush_log_at_trx_commit = 2`（パフォーマンスとデータ耐久性のバランス）
- `innodb_flush_log_at_trx_commit = 0`（性能重視、データ損失許容）

# 検証時の速度調査
1万件のトランザクションで1万件インサートした場合以下の動作となった。　※当時RDSのスペックはだいぶ落としていたはずだが詳細は失念。。。
| `sync_binlog` | `innodb_flush_log_at_trx_commit` | 所要時間 |
|--------------|--------------------------------|--------|
| `1`          | `0`                            | 70秒   |
| `10000`      | `0`                            | 35秒   |
| `1000`       | `0`                            | 38秒   |
| `1000`       | `1`                            | 10秒   |
| `1000`       | `2`                            | 18秒   |


当時の事象では上記を1分以内に処理できないと問題が起きるというのが問題だったので、以下の設定にして対応した。
`sync_binlog = 1000`、`innodb_flush_log_at_trx_commit = 2`

データの保守性は弱くなるので、安易にsync_binlogをいじることを推奨することではないが、登録系のパフォーマンス改善という部分では考慮が必要な部分かと思い記載しました。
競プロを始めてからずっと嘘のDFSを使っていた

# はじめに
競プロ典型90問 021 - Come Back in One Piece（★5）を考えていたのですが、解説を見てもACが取れず、DFSとして使っていたコードが実はDFSになっていなかったことに気が付きました。

https://atcoder.jp/contests/typical90/tasks/typical90_u

# どういうこと？

結論としては、各頂点の確認済みのフラグを立てるタイミングを間違えていたみたいです。

以下、$N$ を頂点数、$d$ を隣接リストとして、グラフの各頂点の番号を順に出力することを考えます。

## 正しいコード

```python
# N: 頂点数, d[v]: vに隣接している頂点の配列
start = 0
todo = [start]
seen = [False] * N
while todo:
    v = todo.pop()
    if seen[v]:
        continue
    seen[v] = True  # フラグを立てる
    print(v)  # 各頂点での処理
    for w in d[v]:  # 辺を調べる
        if seen[w]:
            continue
        todo.append(w)  # 次の頂点をtodoに追加
```

各辺に対しては、次の頂点 `w` をスタック `todo` に追加するだけです。

## 間違えていたコード
```python
# N: 頂点数, d[v]: vに隣接している頂点の配列
start = 0
todo = [start]
seen = [False] * N
seen[start] = True
while todo:
    v = todo.pop()
    print(v)  # 各頂点での処理
    for w in d[v]:  # 辺を調べる
        if seen[w]:
            continue
        todo.append(w)  # 次の頂点をtodoに追加
        seen[w] = True  # フラグを立てる
```

各辺に対して、次の頂点 `w` をスタック `todo` に追加して、**フラグ `seen[w]` を立てています**。辺を見てすぐにフラグを立てることで、今いる頂点 `v` から隣接する全ての頂点 `w` への経路を確定することになり、「深さ優先」でなくなっています。


# 具体例

簡単な例を紹介します。
次のグラフにおける $0$ を根としたDFSを考えます。


![グラフ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929378/6ab40095-995a-452c-bc7e-6ccf8a4b2582.jpeg)


「深さ優先」という性質に注意すると、このDFSでは、以下のどちらかが成り立つはずです。

- 頂点 $1$ の直後に頂点 $3$ を見る
- 頂点 $3$ の直後に頂点 $1$ を見る


入力は以下のようにとります。

```python
N = 4
d = [[3, 2, 1], [3, 0], [0], [1, 0]]
```

先ほど紹介した「正しいコード」「間違えていたコード」の実行結果は次のようになります。

## 正しいコード

```python
N = 4
d = [[3, 2, 1], [3, 0], [0], [1, 0]]

start = 0
todo = [start]
seen = [False] * N
while todo:
    v = todo.pop()
    if seen[v]:
        continue
    seen[v] = True  # フラグを立てる
    print(v)  # 各頂点での処理
    for w in d[v]:  # 辺を調べる
        if seen[w]:
            continue
        todo.append(w)  # 次の頂点をtodoに追加
```

`1` の直後に `3` が出力されます。

```sh
0
1
3
2
```

## 間違えていたコード

```python
N = 4
d = [[3, 2, 1], [3, 0], [0], [1, 0]]

start = 0
todo = [start]
seen = [False] * N
seen[start] = True
while todo:
    v = todo.pop()
    print(v)  # 各頂点での処理
    for w in d[v]:  # 辺を調べる
        if seen[w]:
            continue
        todo.append(w)  # 次の頂点を追加
        seen[w] = True  # フラグを立てる
```

`1` の直後に `3` が出力されず、間に `2` が入ってしまいます。

```sh
0
1
2
3
```
# さいごに

約一年ほど競プロをしていますが、ずっと嘘のDFSを使っていたと思うとぞっとします...。
ただ「正しいコード」に比べると「間違えていたコード」はスタックに入れる情報が少なく、計算量的には若干程度は優秀なのかなと思います。到達可能判定や、ただの連結成分への分解ではバグにはならないはずなので、TLEに悩まされたら使ってみる価値もあるかも。

一応、冒頭で触れた 競プロ典型90問 021 - Come Back in One Piece（★5） の提出も貼っておきます。

- AC : https://atcoder.jp/contests/typical90/submissions/62637460
- WA : https://atcoder.jp/contests/typical90/submissions/62636711
padStart() でゼロ埋めをスマートに！

 paiza のゼロ埋め問題に挑戦したら、最初は if 文ゴリ押しでダサいコードに…。`padStart()` を知ったら、一発で解決した ので、その学びをメモ。


<br>整数 n（0~999）が1つ入力されるので3桁にそろえて出力する処理 を考える。
入力例　→　9　45　123
出力例　→　009　045　123

<br>❌ NGコード：if 文でゴリ押し
```js
rl.on('line', (line) => {
    if (line.length === 3) {
        console.log(line);
    } else if (line.length === 2) {
        console.log("0" + line);
    } else {
        console.log("00" + line);
    }
    rl.close();
});
```
🚨 問題点
if の分岐が増えてコードが読みにくい
バグの原因になりやすい

<br>✅ OKコード：padStart() で一発解決！
```js
rl.question('', (line) => {
    console.log(line.padStart(3, '0'));
    rl.close();
});
```
✨ 改善ポイント
✅ padStart(3, '0') で たった1行で解決！
✅ rl.question() で 一回の入力を確実に処理！
✅ 可読性アップ＆ミス減少！

<br>📌 padStart() のポイント

不足分を指定の文字で埋める
```js
console.log('9'.padStart(3, '0'));  // "009"
console.log('42'.padStart(3, '0')); // "042"
```
デフォルトは半角スペース
```js
console.log('42'.padStart(5)); // "   42"
```
ターゲットの長さ以下なら何もしない
```js
console.log('1234'.padStart(3, '0')); // "1234"
```

<br>🔍 まとめ

最初は if 文ゴリ押しで書いてたけど、padStart() で一発解決！
「ゼロ埋め？ → padStart() でOK！」って流れを覚えよう！🔥

※ちなみに、on('line',～)は複数行入力向けと聞いたので、.questionを使ったのですが、
　paizaの問題で.question()を使うと上手く処理されず正解になりません(´;ω;｀)
　通過するためにon('line',～)の方を使いました。
 
[僕の失敗談と解決話！](https://paizabeginner.wordpress.com/2025/03/04/paiza%e3%81%a7%e5%9f%ba%e6%9c%ac%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bc-padstart%e3%81%a7%e3%80%810%e5%9f%8b%e3%82%81%e5%87%a6%e7%90%86%e3%82%92%e3%82%b9%e3%83%9e%e3%83%bc%e3%83%88%e3%81%ab%ef%bc%81/)
LeetCode. 2.Add Two Numberの回答方法

## 初めに
転職に向けて、LeetCodeを初めてみました。
思っていたより難しかったので、備忘録も兼ねて間違えた問題について、回答方法とその理由を記録していこうと思います（笑）

## 2.Add Two Numberの回答方法
結論、いかが回答になります。

```python
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
        tempsum = 0
        root = cur = ListNode(0)
        while l1 or l2 or tempsum:
            if l1:
                tempsum += l1.val
                l1 = l1.next
            if l2:
                tempsum += l2.val
                l2 = l2.next
            cur.next = cur = ListNode(tempsum % 10)
            tempsum //= 10
        return root.next

```

順を追って解説します。

### 1.初期化
```python
tempsum = 0
root = cur = ListNode(0)

```
tempsum は各桁の合計値や繰り上がりを一時的に保存する変数
root は新しく作るリンクリストの ダミーヘッド
cur は現在のノードを指すポインタ（root からスタート）

### 2.ループ処理
```python
while l1 or l2 or tempsum:
```
l1 や l2 にまだノードがある、または tempsum に繰り上がりの値が残っている限り続ける。

#### (1)各ノードをtempsumに加算
```python
if l1:
    tempsum += l1.val
    l1 = l1.next
if l2:
    tempsum += l2.val
    l2 = l2.next
```
l1 があるなら、その値を tempsum に加算し l1 を次のノードへ
l2 も同様に処理

#### (2)計算結果の新ノードを作成
```python
cur.next = cur = ListNode(tempsum % 10)
tempsum //= 10
```

### 3. 計算が完了したら、新しいリストの先頭を返す
```python
return root.next
```

## 最後に
ListNode型のデータを業務で使わないので、何それ美味しいの状態でした（笑）
この問題定期的に見直したい、、
簡易勤怠表エクセル作成。平日のみ表示/週毎に色変更

# 成果物

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821335/c8b50f60-d724-49eb-9dcb-f5964497a94e.png)

＃作成方法
黄色の付箋は名前入力
日付はユーザ定義：m/d(aaa)
C3セルは直接日付入力：2025/3/3
D3以降：=WORKDAY(C3,1)入力後、右にドラッグ
色付け：日付のみ選択、条件付き書式設定→数式入力=MOD(WEEKNUM(C3),2)=0、書式の色変更
海外旅行中の開発者が知っておくべき金融取引のコツ

開発者として海外を旅する際、現地の金融システムにアクセスするのが難しい場面に遭遇することがあります。特に、例えばイランみたいな国では、国際的な銀行サービスや取引所が制限されているため、普通の方法では取引がほぼ不可能です。私が最近経験したケースでは、現地の規制を回避しつつ、安全に取引を進める必要がありました。

そこで役立ったのが、オンラインのブローカープラットフォームです。これを使うと、規制の厳しい環境でも比較的簡単に金融取引ができます。例えば、私が試した中では、あるプラットフォームが使いやすく、サポートも充実していて助かりました。具体的には、アカウントの設定や入金方法（暗号通貨を使うケースが多いです）を工夫することで、スムーズに取引を始められます。

もし似たような状況に興味があるなら、こちらのガイドが参考になるかもしれません: [Feedbeenのガイド](https://feedbeen.com/training/best-forex-brokers-for-iranians)。海外での取引環境は国によって大きく異なるので、事前に調べておくのがおすすめです。
OSS支援と日本の寄付税制における課題と提案


オープンソースソフトウェア（OSS）は現代の産業基盤を支える重要な要素となっています。しかし、日本ではOSS開発の環境整備が十分であると言い難く、特に税制の課題が原因で企業や個人からのOSS支援が十分に進んでいない現状があります。本記事では、日本の寄付税制の仕組みと課題を整理し、それを踏まえたOSS・公益活動支援のための具体的な解決策を提案します。

## OSS開発を促進できない現状

OSS開発者が持続可能な形で取り組むためには、経済的な安定が必要です。しかし、日本では次のような状況が障壁となっています。

- **企業文化**: 欧米では「OSSへの貢献＝競争力強化」が一般的な考え方である一方、日本企業ではOSSへの関与がマイナスと捉えられる場合があります。
- **開発資金**: OSS開発には資金が必要ですが、労働者の安定収入を伴わない活動が多く、長期的な開発が困難です。
- **税制面でのインセンティブ不足**: 日本では企業や個人がOSS開発支援団体に寄付しても税優遇を十分に享受できない仕組みになっています。

## 米国の寄付税制から学ぶこと

アメリカでは寄付税制が充実しており、企業や個人が非営利団体を支援する大きなインセンティブとなっています。

### 米国税制の具体例
- **501(c)(3)**: 公益団体への寄付に対して、寄付額の50%までが課税所得から控除されます。
- **501(c)(6)**: 商工会議所や業界団体が該当し、企業は会費や協賛金を業務経費として全額損金算入することができます。
- **資産寄付の非課税措置**: 株式や不動産を寄付する場合、売却益に課税されることなく、寄付の全価値が控除対象になります。

これらの制度により、OSS推進団体（例：Linux Foundation）が企業から容易に資金を調達できる環境が整っています。

## 日本の寄付税制の現状と課題

日本にも寄付金に対する税優遇制度がありますが、以下の点で米国とは大きな違いがあります。

1. **控除限度額が低い**  
   - 一般寄付金: 所得金額の「2.5% + 資本金等の0.25%」の1/4が限度。
   - 特定公益寄付金: 所得金額の「6.25% + 資本金等の0.375%」の1/2までしか控除されない。
   - 例: 資本金2億円、所得6000万円の企業では控除可能額は約275万円で、米国企業の10%枠と比較すると大きな差がある。

2. **個人寄付における繰越控除の非対応**  
   - 日本では寄付額が年間の控除枠を超えた場合、翌年以降に控除を繰り越すことができません。

3. **認定NPO法人制度の取得ハードルの高さ**  
   - 認定NPO法人でなければ寄付控除を受けられませんが、認定要件を満たすのは非常に厳しい状態です。

## 日本でOSS開発を支える仕組み作りへの提案

以下に、特に税制面でOSS開発を支援するための具体策を挙げます。

### 1. OSS開発を公益目的に位置付けた認定制度の新設
- **「ソフトウェア公益法人」などの特別法人格を創設**  
  OSS開発を公益活動として公式に認定し、そこへの寄付を「特定公益増進法人寄付金」と同様に扱う。
- **OSS専用の税優遇スキーム**  
  魅力的な寄付先のリスト作成やOSS推進企業としての公式認定マーク付与。

### 2. 寄付金控除枠の拡大と繰越制度の導入
- **控除枠の大幅緩和**  
  米国ほどでなくとも「課税所得の10%まで控除可」など、合理的な範囲での引き上げ。
- **繰越控除**  
  複数年度にわたり控除を認める仕組みを整備し、大口寄付をしやすくする。

### 3. 企業版ふるさと納税をモデルとした「OSS版納税」
- **企業版OSS納税の導入**  
  地域創生応援税制にならった形でOSSを対象とした高率な控除メリットを適用。
  - 例: OSS寄付額のうち90%を法人税・事業税・住民税から控除。

## OSS支援における経済効果
- **資金の流動性向上**  
  企業の内部留保から放出された資金がOSSプロジェクト運営団体の人件費や事業費として消費・投資に回る。
- **イノベーションの種まき**  
  OSSへの投資は新しい技術や市場を生む可能性を秘めています。
- **長期的なリターン**  
  技術開発や人材育成を通じ、支援企業にも市場拡大や競争力向上という形でメリットが還元。

## まとめ: 
日本でOSSが今ひとつ活発になりきれない背景には、税制を中心とした支援環境の課題があるのではないかと思いました。

OSS開発には継続的な資金が不可欠ですが、日本の現状では、企業や個人がOSSに寄付を行っても十分な税制メリットを得られないため、積極的な資金の流れが生まれにくくなっています。アメリカでは、企業や個人が非営利団体に寄付することで大きな税制上のメリットを得られる仕組みが整っていますが、日本ではこれに相当する制度が整備されているとは言えないようです。

また、アメリカなどではOSSへの参加が企業の競争力強化に繋がるとポジティブに捉えられる傾向がありますが、日本では勤務先企業から必ずしも良いイメージを持たれないこともあるようです。このような認識の違いも、OSSがなかなか活性化しない一因かもしれません。

日本には企業が利益を内部留保として抱えてしまい、社会全体への資金循環が不足している課題があります。そこで、ふるさと納税が地域経済の活性化に貢献したように、「OSS版ふるさと納税」のような制度を導入し、企業や個人が気軽に社会貢献としてOSS支援を行える仕組みを整備することは効果的かもしれません。

優れたエンジニアが経済的な不安を抱えずにOSS開発に取り組めるような制度づくりが重要であると思います。

OSS活動を公益的な活動として認定し、寄付控除枠を広げたり、寄付の繰越控除を認めたりするなど、税制改革を通じて支援の輪を広げていければ、よりよい未来が見えてくるような気がします。

--- 

**参考文献**  
- [日米の寄付税制比較 - 私学高等教育研究所](https://www.shidaikyo.or.jp/riihe/research/639.html)  
- [公益活動寄付税制と制度改革提案 - 日本公認会計士協会](https://jicpa.or.jp/specialized_field/publication/files/00236-000482.pdf)  
- [企業向け寄付税制解説 - 国税庁](https://www.japan-sports.or.jp/Portals/0/data/zaimukaikei/doc/about_donation.pdf)
弱小プログラマー、個人開発1年勝負：40DL達成と膨らむ不安

どうも、個人開発で生計を立てるという無謀な挑戦を始めて1年目のchantoです。

正直、簡単じゃないです。いや、めちゃくちゃ難しい。けど、なんだかんだ小さな前進はあるので、ここに記録として残していこうと思います。これを読んでるあなたも、開発者なら"まあ、うまくいかないだろうな"って思ってるかもしれません。でも、そんなあなたにこそ見届けてもらいたい。成功するかどうかはわからないけど、もがきながら進んでいくので、よろしくお願いします！

# 現状報告

## 1つ目のアプリが40DL突破！

まず嬉しいニュースから！

初めてリリースしたアプリが、なんだかんだで40ダウンロードされました！！しかも、ダウンロードが増えるにつれて、アプリストアでの表示順もじわじわ上がってきてる…！

40DLって世間的にはしょぼい数字かもしれない。でも、自分がゼロから作ったアプリを40人もダウンロードしてくれたって、控えめに言ってもめちゃくちゃ嬉しい。リリース当初は"これ、誰も見つけてくれないんじゃ…"って不安だったけど、やっぱり行動してみるもんですね。

## すでに2つのアプリをリリース済み

なんだかんだで、2つアプリをリリースしています。ただ、これが思った以上に大変だった。

### 失敗したこと

- 機能を盛ろうとしすぎた
    - あれもこれも入れたい病を発症。気づいたら開発が遅れまくる
- みんなに使ってほしくて迷走
    - いろんな人に刺さるようにしたい欲が暴走して、機能が増え、焦りも増加。
- Codemagicの無料ビルド枠を使い切る
    - CI/CD（要はアプリの自動ビルド環境）で使ってるCodemagic、無料枠500分をあっさり使い切って詰んだ。
- 次のアプリを考える時間が不安を生む
    - いざ次のアプリを考え始めると"これ、うまくいくのか…？"という漠然とした不安に襲われる。

### 成功したこと

- アプリ概要の資料を先に作ってから開発した
    - いきなりコーディングせず、資料を作ってから進めたことで、機能が少しは暴走しなくなった。

# 今後の開発方針

今回のリリースで痛感したのは、"欲張ると失敗する"ってこと。だから、今後は以下の方針で行きます。

### ニッチに振り切る

とにかく"一部の人にぶっ刺さる"アプリを作る。万人受けは目指さない。

### スピード重視

完璧を求めず、まずは形にしてリリースする。

### タイトルとスクショに命をかける

結局、アプリをダウンロードするかどうかは、"タイトル"と"スクリーンショット"がすべて。ここは全力で。

# うまくいってないこと

SNSでの発信、怖すぎます。

ぶっちゃけ、X（旧Twitter）を使えてません…！

実は学生時代からSNSへの苦手意識がずっとありまして…。人目を気にしちゃう性格もあって、どうしても踏み出せない。てか、このブログを書いてること自体、正直めちゃくちゃ恥ずかしい（泣）。

でも、せっかく個人開発に挑戦してるし、何かしら形にしたいから、少しずつでも発信を増やしていきたい。もしこの記事を読んで"応援してやるか"って思ったら、見守ってもらえると嬉しいです。

# 宣伝
最近リリースした２つのアプリの宣伝をさせてください。。
もし需要がありそうなら使ってやってください！

1. 賞味期限や消耗予測日を管理するアプリです！備蓄品やなにか維持したい消耗品があればどうぞ！
 ![ビラ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987263/b4df2a73-b224-4c45-8cc9-ed33444d3c00.png)

https://apps.apple.com/jp/app/%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B9%E3%83%88%E3%83%83%E3%82%AF-%E8%B3%9E%E5%91%B3%E6%9C%9F%E9%99%90-%E5%9C%A8%E5%BA%AB%E7%AE%A1%E7%90%86/id6741692393?ign-itscg=30200&ign-itsct=apps_box_link&mttnsubad=6741692393&platform=iphone

2. 定期的な貯金をサポートするアプリです！封筒貯金などでコツコツ現金で貯金していればどうぞ！
![ビラ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987263/91ae028f-3f71-48ef-90d0-7f73e78c9390.png)

https://apps.apple.com/jp/app/%E3%82%82%E3%81%97%E3%82%82%E8%B2%AF%E9%87%91%E7%AE%B1-%E3%82%A2%E3%83%97%E3%83%AA%E3%81%A7%E5%B0%81%E7%AD%92%E8%B2%AF%E9%87%91/id6742336702?ign-itscg=30200&ign-itsct=apps_box_link&mttnsubad=6742336702&platform=iphone
【個人メモ】こんなQAチームを作ってみたい

アジャイル開発においてQAが上流から効率的に関わるための体制案を書いてみる。

【課題】
- 現状のQAチームでは上流（企画・デザインなど）に対するアクションはあるものの
下流（テスト）も含めて全員がカバーしているため、マンパワーを要する。
- また上記に伴い、いわば「浅く広く」な状態になっており
各工程におけるQAアプローチの改善や最適化がしづらい。

【解消のためのアプローチ】
- 企画〜デザイン〜実装〜テスト〜リリースまでの各工程ごとにQAを配置する
- 各工程ごとのQAの役割＆責任範囲を定義する
    - やらないことを明確にし、その余剰をQAアプローチの改善や最適化に充てる

【体制＆役割（案）】

- QA for Planning
    - 要件及び仕様レビュー
        - 仕様の抜け漏れがないか
        - Testabilityが確保されているか
- QA for Design
    - デザインレビュー
        - 要件や仕様を満たしているか
        - Testabilityが確保されているか
- QA for Coding
    - コードレビュー
    - UTの実装もしくはサポート（仮）
- QA for Testing
    - 手動テスト
    - 回帰テスト
    - テスト自動化

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984275/0544f0c3-0168-4041-a063-be8b90074c89.png)


【2025/03/12追記】
何名かの方からフィードバックをいただき、以下考慮する必要がある

・責任の押し付け合いにならないように
例）「このバグはこの工程で見つけるべきだよね」「いやいや...」
日頃からのコミュニケーションや関係性の維持・構築が必要

・メンバーのキャリア形成もセットで考える
例）一定のテストスキルがある。もしくはその職種（企画やデザイナーなど）への転向を前提としたアサイン。
ともすれば「レビューしかできないQAエンジニア」が生まれかねない。
スマホでnode.jsプログラミング - acepad (1) - 概要

# 前置きが要らない人は：
[acepad](https://hoge1e3.github.io/acepad/)に行って，Setup/Restoreを押してenjoy!
# いつでもどこでもプログラミングしたい
私は昔から，タイトルの通り「いつでもどこでもプログラミングしたい」ので，携帯端末でのプログラミングってのをずっとやってきました．久しぶりに昔の作品を掘り返してみたらこんなのが出来たので置いておきます．
- [silop.js](https://www.tonyu.jp/u6Ca)
- [説明スライド](https://www.tonyu.jp/u6Ca/silop.pdf)

この時作ったもの（や，スライドに出てくるsoyBasicも）は，内部で独自言語でインタプリタを走らせるものだったので，実用的な速度で動かせるものはできていませんでした．
# acepadが目指しているもの
「携帯端末のブラウザでJavaScriptを書いて，書いたものをそのまま実行する」ことを目指して作成したのが，先ほど冒頭に示した[acepad](https://hoge1e3.github.io/acepad/)です．

携帯端末だろうがPCだろうが，ブラウザでJavaScriptを書いて実行できるのはある意味当たり前ですが，携帯端末でなるべく快適にプログラミングとなってくると，デフォルトで導入されているスクリーンキーボードではどうしても，記号などが打ちにくい場所にあったりして，快適とはいえません．

ちなみに，[Codeboard](https://play.google.com/store/apps/details?id=com.gazlaws.codeboard&hl=ja&pli=1)という，携帯端末でもプログラミングで使う記号などを打ちやすくしたキーボードもあって，インストールして使っているのですが，どうしても不便なのは「Shiftキーで複数行選択をするときに，Shiftキーを長押しないといけない（矢印キーを2回押すと選択が解除される），さらに，ctrl+cなどを押すためにまたShiftの長押しで解除をしなければならない（でないと，Ctrl+大文字Cとみなされる）」という点でした．これが気に食わないという点だけで，「よし，新しいキーボードを作ろう」となって始めたのが[acepad](https://hoge1e3.github.io/acepad/)です．

acepadを起動するとわかるように，キーボード部分もすべてオリジナルのものになっています．なお，acepadでは，shift＋矢印を押した瞬間に「編集モード」に切り替わり，コピーや貼り付けや，生成AIへの問い合わせ（！）などのキーが登場します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127248/acad3cca-d663-4319-8191-6267d453f402.png)

# で，何に使うのこれ？
携帯端末でプログラミングをしたい，という目的のために開発されているので，別に何かを作りたくて作っていません．あえて言うならacepadは「acepadを開発するために」開発されたものです．いわゆるdogfoodingです（ちょっと違う？）．最初に出て来た「実用的な速度」が必要なのは，acepadを開発・動作させるのに十分なスペックが必要，と言い換えてもよいです．
　基本的に、ブラウザのJavaScriptでできることはなんでもできるはずです。加えて、後述するようにnode.jsの一部の機能をブラウザだけで実現できます。

# ブラウザでnode.jsを実現？
　せっかくだから、ちゃんとプログラムはモジュールごとに分割して書きたいし、いっそのことnodeのモジュールぽくしたいな、よし、作ろう! と思い立ち、現状では、node.jsの次の機能をブラウザで再現しています。
- localStorageをファイルシステムに見立てた仮想ファイルシステム
- 仮想ファイルシステムに配置したjsファイル、およびnpmパッケージ(node_modules配下においてあるパッケージ）の読み込み

さらに、次の機能はおそらくnode.jsでサポートしていませんが、acepadではサポートします。
- ブラウザで動作するプログラム自身が変更したjsファイルについて、ブラウザを再読み込みをすることなく変更を反映させる

これらの機能を実現しているのは、それぞれ次のライブラリです。
- [petit-fs](https://www.npmjs.com/package/petit-fs)
  - localStorageを用いた仮想ファイルシステム。localStorageなので保存容量は（ブラウザにもよりますがだいたい）おおよそ5MB程度ですが、メモリ容量限界まで格納可能なRAMディスク（もちろん再読み込みすると消えます）もサポートします
- [petit-node](https://www.npmjs.com/package/petit-node)
  - petit-fsで構築したファイルシステム上に置かれたjsファイルを実行します。importを用いて他のファイルをインポート可能です。node_modulesフォルダに置いたパッケージ名でのimportもサポートします。

次回はこのへんのライブラリについて詳しく見ていきます。あるいは、[acepadのおおまかな使い方](https://qiita.com/hoge1e3/items/b057dd9590948ce46b4d/)を見ていくかもしれません。
Virtuozzoは消えた？ いいえ、むしろ進化しています！ 

Virtuozzo Japanのソリューションエンジニアです。
最近、BroadcomによるVMwareの買収で業界が大きく揺れ動いており、弊社にも多くの問い合わせが寄せられています。その中で、驚くほど多くの方が「Virtuozzoってまだあるの？」と言われることがあります。  

実は、Virtuozzoは消えていません。それどころか、進化を続け、新たな技術を取り入れながらクラウド、仮想化、コンテナ技術を推進しています。本記事では、Virtuozzoの歴史と現在の進化について紹介し、「今のVirtuozzoが何を提供しているのか？」をお伝えします。

---

## 💡 Virtuozzoの起源と歴史

Virtuozzoの歴史は1997年に遡ります。当時は **SWsoft** という名前で、仮想化技術を開発する企業としてスタートしました。その後、2000年に **世界初の商用コンテナ型仮想化技術** を開発し、2005年には **OpenVZ** としてオープンソース化。コンテナ技術の先駆者としての地位を確立しました。2015年、SWsoft（後のParallels）から独立し、Virtuozzoは単独の企業として再出発しました。

おそらく、「Virtuozzo」と聞くと、多くの方がOpenVZやParallelsを思い浮かべるでしょう。実は、それ以来、クラウドやコンテナ、仮想化の分野で技術革新を続けています。

---

## 🚀 2010年代に消えた？ 実は進化していました！

2010年代後半、多くの人がVirtuozzoの存在を忘れてしまったのは事実かもしれません。しかし、その間も着実に進化を遂げていました。特に **2021年にはJelasticとOnAppを統合** し、クラウド基盤の提供範囲を拡大しました。

- **OnApp**: IaaS、プライベートクラウド、CDNを提供するクラウドプラットフォーム  
- **Jelastic**: コンテナ技術をベースにしたPaaS（Platform as a Service）を提供するクラウドプラットフォーム  

この2つの技術を取り込み、Virtuozzoは **クラウドネイティブな仮想化＆コンテナプラットフォーム** へと進化しました。

また、バックアップやセキュリティのプロAcronis社とも姉妹会社の関係にあります。Acronis社に対して、数年前からOpenStackを最適化した仮想化基盤と独自の仮想ストレージを提供し続けています。これは、現在の[Acronis Cyber Infrastructure](https://www.acronis.com/ja-jp/products/cyber-infrastructure/features/)というソリューションになっています。実は中身が、Virtuozzoが開発したVirtuozzo Hybrid InfrastructureというHCI構成のIaaS基盤です。

---

## 🔥 Virtuozzoの現在：進化した仮想化 & クラウド

現在のVirtuozzoは、単なる仮想化ソフトウェアの提供にとどまらず、Linux OSかた、IaaS、PaaS、クラウドネイティブな環境構築に適した製品を提供しています。

✅ **Virtuozzo Hybrid Infrastructure (VHI)**  
OpenStackを最適化にしたハイパーコンバージドインフラ（HCI）と仮想化を統合したオールインワンプラットフォーム。VMwareの代替としても注目されています。弊社の最も戦略的な製品になっています。VHIについて詳しく知りたい方はこちらの[記事](https://qiita.com/BY-san/items/7b0641b0c8d19945203b)をご参考にしてください。

✅ **Virtuozzo Hybrid Server (VHS)**  
OpenVZ仮想化技術を採用し、クラウドサービスプロバイダー向けの強力なコンテナ仮想化環境を提供しています。また、KVMのハイパーバイザーもついていますので、VMの作成も可能になっています。技術スタックがすこし古いですが、その抜群の安定性と効率性で日本でも支持層多く得られている状況です。

✅ **Virtuozzo Application Platform (旧Jelastic)**  
VMware Tanzu, Redhat Openshiftと同じカテゴリに入るPaaS製品です。コンテナ技術を活用しています。Docker、Kubernetes、Java、PHP、Node.js などの開発・本番環境を簡単に構築可能です。マルチクラウドとBilling機能もサポートしていますので、様々なビジネス形態に対応しています。

✅ **Virtuozzo Storage**  
分散ストレージ技術を活用し、高可用性とスケーラビリティを備えたストレージソリューション。S3オブジェクトストレージは高いパフォーマンスを持ち、ビッグデータやストレージサービスの基盤として注目されています。

✅ **vzLinux**  
CentOSと互換性のあるLinuxとして注目されていますが、積極的な研究開発が行われていません。

---

## 💭 まとめ：Virtuozzoは未来へ

Virtuozzoは **コンテナ仮想化の先駆者** として生まれ、現在では **クラウドインフラ全体をカバーする技術** へと進化しました。  
「2010年代に消えた」と思われがちですが、実際にはVHI、VAPが **VMware代替の選択肢** としても注目されるほど成長しています。

今後も、Virtuozzoはクラウド＆仮想化業界の新たな選択肢として進化を続けます。ぜひ、この機会にVirtuozzoの最新技術に触れてみてください！ 💡✨

https://www.virtuozzo.com/jp/
PHPで「論理値」の動作を確認してみた。

# 概要

PHPで「論理値」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/php/if/index2.html

# 実装

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

```sample.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PHPテスト</title>
</head>
<body>

<p>PHPのテストです。</p>

<p>
<?php
if (TRUE){
  print '条件式にTRUEが記述されているので常に実行されます';
}
?>
</p>

</body>
</html>
```

以下のコマンドを実行しました。

```
$ php sample.php 
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PHPテスト</title>
</head>
<body>

<p>PHPのテストです。</p>

<p>
条件式にTRUEが記述されているので常に実行されます</p>

</body>
</html>
```

# まとめ

何かの役に立てばと。
言語設定と台湾


とあるゲームのレビューを見ているときに興味深いレビューを見つけた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649673/075546f6-cfd2-45b2-a5db-d25da00e1d74.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649673/72c6918e-e925-4c34-819a-d8ecadd6f7a6.png)

[出典1](https://steamcommunity.com/profiles/76561198028853410/recommended/2214210/) [出典2](https://steamcommunity.com/profiles/76561198219688104/recommended/2214210/)

これを翻訳するとどうやら、言語設定で「台湾」を「中華台北」と表記されていることが許せないそうだ。

調べると、「中華台北」は「台湾が中国のものであると思っている中国」と「台湾は中国とは別だと思っている台湾」との折衷案で生み出された「台湾」の名称らしい。[^1][^2]

そのため「中華台北」表記で不愉快に感じる台湾のプレイヤーがいるようだ。

逆に、「台湾」と表記されていたら、今度は中国のプレイヤーが反発する可能性もあり、開発者にとってはどちらを選んでも賛否が分かれる難しい問題と言える。

出来るかは知らないが、パソコンのシステムの言語設定を取得して動的に変えられるかもしれない。

以上。

[^1]:[なぜ台湾は五輪で「チャイニーズ・タイペイ」なのか](https://news.yahoo.co.jp/expert/articles/bc3aa0b3c7308833938430b2a4a5486c04504224)
[^2]:[チャイニーズタイペイ](https://ja.wikipedia.org/wiki/%E3%83%81%E3%83%A3%E3%82%A4%E3%83%8B%E3%83%BC%E3%82%BA%E3%82%BF%E3%82%A4%E3%83%9A%E3%82%A4)