OmniAICreator/Qiita-1.07M huggingface dataset:
NVIDIA×CrewAI ドキュメントジェネレーター：リバースエンジニアリングドキュメントの簡素化

![Screenshot 2025-02-11 at 23.00.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3892767/2b092522-226f-efde-6f37-e3aacf23eb1c.png)

:::note info
※この記事は機械翻訳により日本語に翻訳されています。
:::
## はじめに
人工知能（AI）がさまざまな業界を革新し続ける中、最も一般的な活用の一つがリバースエンジニアリングを通じたドキュメント生成です。NVIDIAはCrewAIとのパートナーシップを通じて、エージェントアーキテクチャを活用したドキュメントジェネレーターを導入するためのマルチエージェントシステムフレームワークを提供しました。このツールは、特にリバースエンジニアリング向けのドキュメント作成プロセスを自動化し、効率化することを目的としています。本記事では、[NVIDIA×CrewAI ドキュメントジェネレーターの機能](https://github.com/crewAIInc/nvidia-demo)、利点、および潜在的な活用方法について詳しく解説します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3892767/5847a363-96a5-0418-c8e7-9525be3c5eac.png)

## **CrewAIとそのドキュメントジェネレーターの理解**  

CrewAIは、**複数のAIエージェントをオーケストレーションし、複雑なタスクを効率的に実行する** マルチエージェントフレームワークです。CrewAI内のドキュメントジェネレーターは、**生成AIモデル、自然言語処理（NLP）、およびエージェント自動化技術** を活用し、**最小限の人間の介入で詳細なドキュメントを生成** します。  

## **NVIDIA CrewAI ドキュメントジェネレーターの主な特徴**  

### **1. AI駆動のコンテンツ生成**  
- **大規模言語モデル（LLM）** を活用し、構造化され一貫性のあるドキュメントを生成。  
- **Llama 3.3-70B LLM NIM** および **NeMo Retriever E5 embedding NIM** を活用。  
- **PDF、Word、Markdown** など、複数のドキュメント形式をサポート。  

### **2. マルチエージェントによる協調作業**  
- **複数のAIエージェント** が連携し、**内容の正確性、フォーマットの統一性、文脈の適合性** を確保。  
- **調査、編集、要約、フォーマット調整** などの異なる領域に特化したエージェントが、それぞれ適切なツールを使用。  

### **3. NVIDIA AIエコシステムとのシームレスな統合**  
- **NVIDIAのAIサービスおよびソフトウェアソリューション** に最適化され、高効率な処理とスケーラビリティを実現。  
- **NVIDIA NIM** との統合により、**事前構築されたエージェントの設計図（Blueprint）** を活用可能。  

### **4. データの自動抽出と構造化**  
- カスタマイズにより、**構造化・非構造化データ** からインサイトを抽出可能。  
- **自動的に情報を整理し、事前定義されたテンプレートに統合** することで、一貫性のあるドキュメントを作成。  

### **5. リアルタイムコラボレーションと編集**  
- **CrewAIの最新バージョン** では、**人間とAIの協調作業** をサポートし、**ユーザーがAI生成コンテンツを調整・改善** 可能。  
- **APIと統合し、ワークフローの自動化** を実現。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3892767/514fdd53-ae71-05e9-3c80-6859b1d25c26.png)

## **NVIDIA CrewAI ドキュメントジェネレーターの利点**  

### **1. 効率の向上**  
- 繰り返しの多い**ドキュメント作成作業を自動化**し、手作業での記述時間を削減。  
- **チームの生産性を向上**させ、より戦略的な業務に集中できる環境を提供。  

### **2. コンテンツの精度向上**  
- **AI駆動のファクトチェック** や **文脈認識によるライティング** により、誤りを最小化。  
- **一貫性のあるドキュメントを維持**し、不整合のリスクを低減。  
- **CI/CDパイプラインと統合** することで、ドキュメントの**最新状態を自動的に維持**可能。  

### **3. シームレスなAIと人間のコラボレーション**  
- **リアルタイムでユーザーがAI生成ドラフトを調整可能**。  
- **レビューとフィードバックメカニズムを活用** し、コンテンツの正確性と品質を向上。  

## **ユースケースと適用例**  

✅ **システムアーキテクチャ、依存関係、技術的詳細の自動抽出**  
✅ **リバースエンジニアリングによる詳細なソフトウェアドキュメントの生成** → レガシーシステムの理解をサポート  
✅ **コードからドキュメントへの変換を支援** → エンジニアがソフトウェアのモダナイズやリファクタリングを効率的に実施  
✅ **ソースコードリポジトリを分析し、APIリファレンス、フローダイアグラム、システム概要を自動生成**  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3892767/c88b1fdc-c992-0e0b-3777-df782f93d6b9.png)

## **結論**  

NVIDIA CrewAI ドキュメントジェネレーターは、**NVIDIAのAIハードウェアおよびソフトウェアエコシステムを活用し、リバースエンジニアリングのドキュメント作成を強化** します。エージェントアーキテクチャ（Agentic Architecture）、生成AI（GenAI）、および自動化（Automation）を統合することで、**複雑なシステムを効率的に分析し、構造化されたドキュメントを生成** できます。  

CrewAIとのコラボレーションにより、**自動化と人間の監視のバランスを確保**し、ドキュメント作成の迅速化、精度向上、および変化するシステム要件への適応を可能にします。
SSMSで生成したINSERT文の項目名と値の対応をExcelで確認できるようにするVBA

# SSMSで生成したINSERT文の項目名と値の対応をExcelで確認できるようにするVBA
ChatGPTに作ってもらいました。個人的な備忘録なので使用の際は各自の判断でお願いします。

## 使い方
- アクティブシートのA列に複数のINSERT文を貼り付ける
- マクロを実行
- SQL_Results シートに解析結果が出力される

## 注意点
- INSERT先は同一のテーブルしか対応できてません

## コード
```
Sub ParseSQLInsert_Multiple()
    Dim wsSource As Worksheet, wsTarget As Worksheet
    Dim sql As String
    Dim lastRow As Long, rowIndex As Long, colStart As Integer
    Dim fieldsPart As String, valuesPart As String
    Dim fieldsArray As Variant, valuesArray As Variant
    Dim i As Integer
    Dim regex As Object
    Dim matches As Object
    Dim outputRow As Long, firstSQL As Boolean

    ' ソースシートとターゲットシートを取得（なければ作成）
    Set wsSource = ActiveSheet
    On Error Resume Next
    Set wsTarget = ThisWorkbook.Sheets("SQL_Results")
    If wsTarget Is Nothing Then
        Set wsTarget = ThisWorkbook.Sheets.Add
        wsTarget.Name = "SQL_Results"
    End If
    On Error GoTo 0

    ' A列の最終行を取得
    lastRow = wsSource.Cells(wsSource.Rows.Count, 1).End(xlUp).Row
    outputRow = 2  ' 出力先の開始行（1行目はヘッダー）

    ' 正規表現オブジェクトの作成
    Set regex = CreateObject("VBScript.RegExp")
    regex.Global = True
    regex.IgnoreCase = True
    regex.Pattern = "CAST\((.*?) AS .*?\)|NULL|N?'(.*?)'|(\d+(\.\d+)?)"

    ' 1つ目のSQLの処理でヘッダーを記録
    firstSQL = True

    ' A列の各行をループ
    For rowIndex = 1 To lastRow
        sql = wsSource.Cells(rowIndex, 1).Value
        If sql = "" Then GoTo NextSQL ' 空白ならスキップ

        ' INSERT文のカラム部分を抽出
        Dim startPos As Integer, endPos As Integer
        startPos = InStr(sql, "(") + 1
        endPos = InStr(sql, ") VALUES")
        If startPos = 1 Or endPos = 0 Then GoTo NextSQL ' エラーならスキップ
        fieldsPart = Mid(sql, startPos, endPos - startPos)

        ' VALUES部分を抽出
        startPos = InStr(sql, "VALUES (") + 8
        endPos = InStrRev(sql, ")")
        valuesPart = Mid(sql, startPos, endPos - startPos)

        ' カラム名を配列に変換
        fieldsArray = Split(fieldsPart, ", ")

        ' 正規表現で値の配列を取得
        Set matches = regex.Execute(valuesPart)
        ReDim valuesArray(UBound(fieldsArray))

        ' マッチした値を配列に格納
        For i = 0 To matches.Count - 1
            If matches(i).SubMatches(0) <> "" Then
                valuesArray(i) = matches(i).SubMatches(0) ' CAST(...) の場合
            ElseIf matches(i).SubMatches(1) <> "" Then
                valuesArray(i) = matches(i).SubMatches(1) ' N'...' の場合
            ElseIf matches(i).SubMatches(2) <> "" Then
                valuesArray(i) = matches(i).SubMatches(2) ' 数値
            Else
                valuesArray(i) = "NULL" ' NULL の場合
            End If
        Next i

        ' ヘッダー行を出力（最初のSQLのみ）
        If firstSQL Then
            wsTarget.Cells(1, 2).Resize(1, UBound(fieldsArray) + 1).Value = fieldsArray
            firstSQL = False
        End If

        ' 解析結果を出力
        wsTarget.Cells(outputRow, 1).Value = rowIndex ' 元の行番号
        wsTarget.Cells(outputRow, 2).Resize(1, UBound(valuesArray) + 1).Value = valuesArray
        outputRow = outputRow + 1

NextSQL:
    Next rowIndex

    MsgBox "すべてのSQLを解析しました！", vbInformation
End Sub
```
【Next.js】Hydration failedの対処方法

# 初めに
Next.jsでプロジェクトを初回起動した後、開発を進めていく中で、次のようなエラーが発生することがあった。
私なりの対処方法で表示されなくなったので、備忘録がてらここに残そうと思う。

    Hydration failed because the server rendered HTML didn't match the client.
    As a result, this tree will be regenerated on the client.
    This can happen if a SSR-ed Client Component is used.
訳：Hydration に失敗しました。サーバーでレンダリングされた HTML がクライアントのものと一致しません。そのため、このツリーはクライアント側で再生成されます。これは、SSR されたクライアントコンポーネントが使用された場合に発生する可能性があります。

# 問題

ある時、```npm run dev```したのち、開発を進めると画像のようになった。

![スクリーンショット 2025-02-11 22.52.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688801/d1a18c8a-cf0f-3421-4b61-50301d6fdd34.png)

エラーをクリックすると

![スクリーンショット 2025-02-11 22.40.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688801/91b7bc6d-68a9-d060-6281-f69e8f0b320a.png)

のように表示された。

今回のHydrationのエラーは、「'use client' をファイルの最初に書いたかどうかに関するエラー」で生じているようだ。（※すごく雑な説明）
（私はやっていないが「htmlの`<p>`タグの中に`<p>`タグを書いた」みたいな時にも発生する）

いちいち確認するのは面倒ですよね。特に、外部ライブラリなどを使用していたり、複数人で急いで開発している場合には、どこで use client を追加すべきかを管理するのが難しくなります。
（`<p>`タグの問題方はChakraなどのUIコンポーネントライブラリで特定のコンポーネントで使用されているのを気が付かずにネストして発生している印象。まあuse clientの件も含めて適切に修正しろって話なんですが）

一般的に、src/app/layout.tsxにuseEffectを使ったり、`<html lang='en' suppressHydrationWarning>`を追加しても、自分の環境では解決しませんでした。

# 解決方法
私が試した解決方法は以下の通り。

```
<html lang='en' suppressHydrationWarning>
    <body suppressHydrationWarning>
        <!-- ここにコンテンツ -->
    </body>
</html>
```
`<body>`タグにもsuppressHydrationWarningを追加したところ、エラーが解消された。

# 理由
ReactのHydrationのエラーは、仕様上指定した要素にのみ適用され、その子要素には適用されない。

例えば、`<html>`タグにsuppressHydrationWarningを付けても、Reactはその内部にある`<body>`タグやその他の要素を個別にチェックするため、依然としてエラーが発生する。

# 補足
私の場合は`<body>`にも追加したことで一旦問題が解決したが、もしそれでもエラーが解消されない場合、suppressHydrationWarningを多用するのは避けたほうが賢明。
コードを見直し、'use client'を適切に追加することで、根本的な解決を目指しましょう〜。

# 参考文献
https://dev.to/ramunarasinga/suppresshydrationwarning-what-is-it-2edd
【Rails】特定の範囲内で一意のバリデーション

## 実装方法

以下のように記述すると`scope`に指定した範囲内で一意であることを検証できます。

```ruby:project.rb
class Project < ApplicationRecord
  belongs_to :account

  has_many :tasks

  validates :name, presence: true, uniqueness: { scope: :account_id }
end
```

上記の場合には`name`は同一の`account_id`で一意でなければなりません。つまり、`name`と`account_id`の組み合わせは一意でなければなりません。
【PostgreSQL】年月でパーティショニングするテーブルに単独主キー（UUID）を設定したい

## はじめに

PostgreSQLではテーブルのパーティショニングがサポートされています。
パーティショニングを行うテーブルに一意制約や主キー制約を設定することは可能ですが、このとき、主キーにはパーティショニングキーを含める必要があります。
今回、パーティショニングしつつ全体で一意なことを保証されたUUIDを用意したかったので主キー・パーティショニングキーにUUIDv7を使う方法を検討しました。
備忘録として残します

## 解決方法

UUIDv7の値を主キーとし、パーティショニングキーとしても使用することで対処しました。
UUIDv7は先頭48bitがタイムスタンプでソート可能のため、パーティショニングキーとして使用することが可能でした。

```sql
create table logs(
  id uuid primary key,
  created_at timestamp with time zone default now(),
  message text not null
) partition by range(id);
create table logs_202501 partition of logs
   for values from('01941f297c00-0000-0000-0000-000000000000') to ('0194becea000-0000-0000-0000-000000000000');
create table logs_202502 partition of logs
   for values from('0194becea000-0000-0000-0000-000000000000') to ('01954f00b000-0000-0000-0000-000000000000');
```

## 課題

- UUIDv7をPostgreSQLで発番する関数はまだPostgreSQLに入っていないので自分で用意する必要がある
- パーティションテーブルの範囲指定が直感的でない
HTTP、ブラウザ、レンダリングエンジンについて簡潔にまとめてみる

## HTTPメッセージの基本構造
HTTPはクライアント（ブラウザなど）とサーバーが通信する際に使われるプロトコルです。リクエストとレスポンスのメッセージ形式を理解することで、Webの仕組みが見えてきます。

### **1. HTTPリクエストメッセージの構造**
```
<リクエストライン>
<ヘッダー部>
（空行）
<ボディ（任意）>
```
- **リクエストライン**: メソッド、リクエストターゲット、HTTPバージョンを含む。
  - 例: `GET /index.html HTTP/1.1`
- **ヘッダー部**: リクエストに関する情報を含む。
  - 例: `Host: www.example.com`
- **空行**: ヘッダーとボディを分ける。
- **ボディ**: POSTなどで送信するデータ（任意）。

### **2. HTTPレスポンスメッセージの構造**
```
<ステータスライン>
<ヘッダー部>
（空行）
<ボディ>
```
- **ステータスライン**: HTTPバージョン、ステータスコード、ステータスメッセージ。
  - 例: `HTTP/1.1 200 OK`
- **ヘッダー部**: サーバーからのレスポンス情報。
  - 例: `Content-Type: text/html`
- **空行**: ヘッダーとボディを分ける。
- **ボディ**: HTMLなど実際に表示されるデータ。

---

## User-Agentとレンダリングエンジンの基礎知識

### **1. User-Agentとは？**
User-Agentは、ブラウザやクライアントがサーバーに送る情報の一部で、**どんな環境（ブラウザ、OS）でアクセスしているかを伝えるヘッダー**です。

- 例:
```
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.77 Safari/537.36
```
- **Mozilla/5.0**: 互換性のための歴史的表記（深い意味はなし）。
- **Windows NT 10.0; Win64; x64**: OSがWindows 10の64ビット版であること。
- **AppleWebKit/537.36**: WebKitエンジンを使用している。
- **Chrome/110.0.5481.77**: 実際に使用しているブラウザ（Chromeのバージョン）。

💡 **ポイント**: サーバーはUser-Agentを見て、スマホ向けページやPC向けページを出し分けることが可能。

---

### **2. レンダリングエンジンとは？**
- **レンダリングエンジン**とは、**HTML、CSS、JavaScriptを解析し、画面にWebページを描画するプログラム**です。

#### **主なレンダリングエンジン**
| エンジン名     | 採用ブラウザ                | 特徴                                    |
|----------------|-----------------------------|-----------------------------------------|
| **Gecko**      | Firefox                     | 柔軟性が高く、Web標準への対応が早い。  |
| **WebKit**     | Safari、旧Chrome            | 高速で軽量。Apple製品に最適化。        |
| **Blink**      | Chrome、Edge（現行）        | GoogleがWebKitから派生させたエンジン。 |

💡 **レンダリングエンジンの役割**:
1. HTMLやCSSを解析して**DOMツリー**と**CSSOMツリー**を構築。
2. レイアウトを計算し、画面にどのように配置するか決定。
3. ページを画面に描画。

#### **エンジンが違うと何が起こる？**
- 各エンジンが微妙に違うため、**同じWebサイトでもブラウザごとにレイアウトが異なる**ことがあります。
- 開発者は異なるブラウザで動作確認をする必要がある。

---

### **3. レンダリングエンジン vs JavaScriptエンジン**
- **レンダリングエンジン**: HTMLやCSSを解析し、ページを描画する。
- **JavaScriptエンジン**: JavaScriptを実行し、動的なページを処理する。

| エンジン名         | 主な採用ブラウザ         | 開発元       |
|-------------------|--------------------------|--------------|
| **V8**            | Google Chrome, Edge      | Google       |
| **SpiderMonkey**  | Firefox                  | Mozilla      |
| **JavaScriptCore**| Safari                   | Apple        |

---

## **まとめ**
- **HTTPメッセージ**は、リクエストとレスポンスに分かれており、各要素を理解することでWeb通信が見えてくる。
- **User-Agent** はサーバーがクライアント環境を判断するための重要な情報。
- **レンダリングエンジン** はWebページの見た目を決めるプログラムで、ブラウザによって違いがある。
Windows Serverの認証局で証明書の有効期限を変更する

Windowsサーバーの証明機関機能では、証明書テンプレートで有効期限を設定しても、強制的に期限が2年になってしまいます。これは、レジストリー上の設定が反映されていることが原因です。
この記事では、有効期限の変更に必要なレジストリの場所をご紹介します。

## レジストリの場所

```
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\CertSvc\Configuration\<CA名>
```

### 変更場所

#### ValidityPeriod (REG_SZ) / 日付単位
Days/Weeks/Months/Yearsから選択

#### ValidityPeriodUnits(REG_DWORD) / 期間
上記で設定した単位に対する有効期限

:::note info
設定例
ValidityPeriod = Years
ValidityPeriodUnits = 5
→5年が有効期限
:::

### 設定反映
以下を管理者権限で実行

```
net stop certsvc
net start certsvc
```

参考
[Change the expiration date of certificates that are issued by Certificate Authority](https://learn.microsoft.com/en-us/troubleshoot/windows-server/certificates-and-public-key-infrastructure-pki/change-certificates-expiration-date)
【Ruby実装あり】トポロジカルソートって何？

# 1. はじめに
トポロジカルソートというアルゴリズムを学習したため、アウトプットしようと思います。
また、今回の記事では、トポロジカルソートの基本概念からアルゴリズム、実装例（Ruby）までの解説を試みます。


# 2. トポロジカルソートの概要
トポロジカルソートは、有向非巡回グラフ（DAG：Directed Acyclic Graph）の頂点を線形に並べる手法です。

「有向非巡回グラフ」がすでに難しいと思うので、「有向」と「非巡回」に分けて説明します。

まず、「有向グラフ」とは、「頂点」と「向きのついた辺」からなるグラフのことです。
イメージ的には、丸い図形を頂点とすると頂点が複数あり（仮にA〜Cまでがあるとします）、その頂点同士を結ぶ辺が頂点Aから頂点Bと頂点C,頂点Bからは頂点Cに向かって矢印で描かれている様子などを思い浮かべていただくと良いかと思います。

そして「有向非巡回グラフ」とは、「有向グラフ」が巡回しないということです。
先ほどの例を用いると、頂点Cから頂点Aに向かって矢印が描かれていないということです。

この並べ替えにより、すべての有向辺が前から後ろへ向かう順序になります。
例として、プロジェクトのタスク管理やビルドの依存関係が挙げられます。
グラフ内にサイクルが存在するとソートできないため、DAGが前提となります。

各頂点は、あるタスクや要素に対応し、依存関係が辺として表されます。
正しい順序を求めることで、処理の前後関係が明確になります。
アルゴリズムの出発点は、入次数が「0」の頂点から順次処理する方法です。

またこの「入次数」が難しいと思うのですが、「その頂点に向けられている辺の数」のことです。
先ほどの頂点A〜Cの例だと、頂点Aの入次数は0、頂点Bの入次数は1、頂点Cの入次数は2　となります。

このDAGは、グラフ理論における順序決定の基礎として広く用いられているそうです。

# 3. アルゴリズムの詳細
トポロジカルソートを行うための代表的なアルゴリズムには①Kahnのアルゴリズム（Kahnさんが考案）と ②深さ優先探索ベースの方法があります。
今回は、Kahnのアルゴリズムを中心に説明します。

まず、各頂点の入次数を計算し、入次数が「0」の頂点をキューに入れます。
その後、キューから頂点を取り出し、結果リストに追加します。
取り出した頂点に隣接する頂点の入次数を減らし、新たに「0」になった頂点をキューに追加します。
この手順をすべての頂点が処理されるまで繰り返します。
途中で複数の頂点が同時に入次数「0」になれば、一意な順序ではなくなる可能性があります。
また、全頂点が処理できなければサイクルが存在することになります。
各ステップの処理と一意性の確認がポイントです。

# 4. 実装例（Ruby）
Ruby を使ったトポロジカルソート（Kahnのアルゴリズム）の実装例を解説します。
状況としては、1,2,3,4の4種類の紐があり、伝えられた比較結果から紐の長さ順を1通りに定めることができるか判定したいとします。

◎ 比較結果
1の紐 > 2の紐
1の紐 > 3の紐
2の紐 > 3の紐
3の紐 > 4の紐

そして、上記比較結果は以下の形で入力されると仮定します。
```
1 2
1 3
2 3
3 4
```

最終的には、1通りに定められる場合には下記のような長い紐から順に並べた出力をし、1通りに定められない場合は-1を出力するようにします。
```
1 2 3 4
```

上記を踏まえた場合の実装が下記です。

```
# n : 紐の種類
n = 4

# m : 比較結果の数
m = 4

# 「より長い」から「より短い」への関係を格納するための配列
graph = Array.new(n + 1) { [] }
# 各鉱物の入次数を記録する配列（初期値は 0）
indegree = Array.new(n + 1, 0)

# グラフと入次数を構築する
m.times do
  h, s = gets.split.map(&:to_i)
  graph[h] << s     # 「h > s」なので、hからsへの有向辺を追加
  indegree[s] += 1  # sの入次数を1増やす
end

# この時点では以下のようになっている
# graph[[][2,3][3][4]]
# indegree[0, 0, 1, 2, 1]

# トポロジカルソート
queue = []  # 入次数0の頂点を格納する配列(上記indegreeだと、初回はqueueに1が入る)
(1..n).each do |i|
  queue << i if indegree[i] == 0
end

order = []  # 順番に並べた結果を保存する配列

while !queue.empty?
  # もし頂点が複数ある場合、一意な順番とならないので -1 を出力して終了
  if queue.size > 1
    puts -1
    exit
  end

  # queue から一つ取り出す（入次数が0の唯一の紐）
  current = queue.shift
  order << current

  # current（最も長い紐）から出る各辺について、隣接する頂点の入次数を１ずつ減らす
  graph[current].each do |next_node|
    indegree[next_node] -= 1
    # 入次数が 0 になったら、queue に追加する
    queue << next_node if indegree[next_node] == 0
  end
end

# もし全ての頂点を処理できなかった場合（=サイクルが存在する場合）は -1 を出力
if order.size != n
  puts -1
else
  # 結果を半角スペースで区切って出力
  puts order.join(" ")
end
```

# 5. 最後に
ソートアルゴリズムとしては、バブルソートやクイックソートなどは知っていたものの、トポロジカルソートは知らなかったため勉強になりました。
情報系を出ていない自分にとって、初耳のアルゴリズムはちょっと身構えてしまうのですが、実装して理解してみると思ったほど複雑ではないような気もしました（実際のケースで使うとなると難しいのかもですが、、笑）
Webサーバーのボット対策入門

## はじめに

Webサーバーを運用していると、いわゆる「ボット」からの大量のアクセスに悩まされることがあります。この記事では、効果的なボット対策の基本的な方法を、実践的な例を交えて説明します。

## ボットによる問題とは？

ボットによるアクセスには以下のような問題があります：

- サーバーリソースの消費
- レスポンス時間の低下
- 不正アクセスの試行
- コンテンツのスクレイピング

## 基本的な対策方法

### 1. Nginxでのレート制限

最も基本的な対策は、一定時間内のアクセス数を制限することです。

```nginx
# IPアドレスごとのレート制限
limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=10r/s;

server {
    location / {
        # バースト的なアクセスを20リクエストまで許可
        limit_req zone=ip_limit burst=20 nodelay;
    }
}
```

この設定により：
- 1秒あたり10リクエストまでを許可
- 一時的な超過は20リクエストまで許容
- それ以上は429エラーを返す

### 2. 不要なアクセスのブロック

明らかに不要なアクセスは、初期段階でブロックします。

```nginx
# WordPressを使用していない場合のwp-adminブロック
location ~* wp-admin {
    return 403;
}

# 特定のUser-Agentをブロック
if ($http_user_agent ~* (crawler|scraper|bot)) {
    return 403;
}
```

### 3. fail2banによる動的ブロック

異常なアクセスを検出して、一定時間IPをブロックします。

1. インストール
```bash
sudo apt-get install fail2ban
```

2. 基本設定（/etc/fail2ban/jail.local）
```ini
[nginx-botsearch]
enabled  = true
port     = http,https
filter   = nginx-botsearch
logpath  = /var/log/nginx/access.log
maxretry = 5
findtime = 60
bantime  = 3600  # 1時間ブロック
```

### 4. 簡単なボット検出（Node.js/Express）

```javascript
const rateLimit = require('express-rate-limit');

// レート制限の設定
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15分
  max: 100 // IPあたりの最大リクエスト数
});

app.use(limiter);

// 簡単なボット検出
function isBot(req) {
  const userAgent = req.headers['user-agent'] || '';
  
  // 明らかなボットパターン
  if (/bot|crawler|spider/i.test(userAgent)) {
    return true;
  }
  
  // 異常な速度でのアクセス
  // （実装例：直近5秒間のアクセス回数をチェック）
  const recentAccesses = getRecentAccesses(req.ip);
  if (recentAccesses > 10) {
    return true;
  }
  
  return false;
}

app.use((req, res, next) => {
  if (isBot(req)) {
    return res.status(429).send('Too Many Requests');
  }
  next();
});
```

## 対策のポイント

1. **段階的な実装**
   - まずは基本的なレート制限から始める
   - 効果を見ながら徐々に調整する

2. **正常なアクセスを妨げない**
   - 制限値は控えめに設定
   - 正常なユーザーの利用パターンを把握

3. **ログの監視**
   - アクセスログを定期的にチェック
   - 異常なパターンを見つけたら対応

## トラブルシューティング

よくある問題と解決方法：

1. **正常なユーザーがブロックされる**
   - レート制限の値を緩める
   - ホワイトリストの設定を検討

2. **制限が効かない**
   - プロキシ設定の確認
   - X-Forwarded-Forの設定確認

3. **サーバー負荷が高い**
   - キャッシュの活用
   - 静的コンテンツのCDN利用

## まとめ

ボット対策は完璧な解決策はありませんが、基本的な対策を組み合わせることで、多くの問題に対処できます。サーバーの状況に応じて、適切な設定値を見つけることが重要です。

## 参考資料

- [Nginxでのレート制限の設定](https://www.nginx.com/blog/rate-limiting-nginx/)
- [fail2ban公式ドキュメント](https://www.fail2ban.org/wiki/index.php/Main_Page)
- [Express Rate Limitの使い方](https://www.npmjs.com/package/express-rate-limit)
reactのiconとui

## heroicons
アイコン一覧

https://heroicons.com/

使い方等

https://github.com/tailwindlabs/heroicons

名前一覧

https://unpkg.com/browse/@heroicons/react@2.2.0/24/outline/

### インストール方法
```
npm install @heroicons/react
```
### 使い方
公式サイトのボタンからはダウンロードしないで名前だけ見てくる
```
import { BeakerIcon } from '@heroicons/react/24/solid' <- インポートする(24,20,16がある。outlineとsolidがある。)
<BeakerIcon className="size-6 text-blue-500" /> <- 使う
```

## headlessui

https://headlessui.com/

https://github.com/tailwindlabs/headlessui?tab=readme-ov-file

### インストール
```
npm install @headlessui/react@latest
```
### 使い方
```
import { Button } from '@headlessui/react'

function Example() {
  return (
    <Button className="rounded bg-sky-600 py-2 px-4 text-sm text-white data-[hover]:bg-sky-500 data-[active]:bg-sky-700">
      Save changes
    </Button>
  )
}
```

### CSS
cssファイルに記載しインポートすると全体に適用されるっぽい？
インラインはこんな感じ
```
function About() {
  const header1 = {
    color: "blue",
    fontSize: "24px",
    fontWeight: "bold",
  };

    return (
      <div>
        <h1 style={header1}>header</h1>
```
[自分用メモ]docker-compose.ymlを使用したコンテナ構築

1. rootユーザに移行

2. docker-composeのインストール

   ```
   sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
   ```

3. 実行権限を付与

   ```
   sudo chmod +x /usr/local/bin/docker-compose
   ```

4. docker-compose.ymlファイルを作成

   ```vim
   vim docker-compose.yml
   ```

   以下は、`docker-compose.yml` の例

   ```docker-compose.yml
    services:
      ansible-container:
        image: ansible-container-image
        container_name: ansible-container
        network_mode: host   # ホストのネットワークを使う
        tty: true            # コンテナ内でインタラクティブに作業できるようにする
        build: ./Dockerfile
        command: sleep infinity
   ```

5. MakeFileの作成

   ```
   vim Makefile
   ```

   内容は以下

   ```
   # Rocky Linux 9のベースイメージを取得
   pull-image:
           docker pull rockylinux:9
   
   # docker-compose.ymlを実行
   up: pull-image
           docker-compose up
   ```

6. makeを実行

   ```
   make up
   ```
Unity上で推しを【操作】した

## はじめに
前回からだいぶ日にちが開いてしまいましたが、推しの誕生日が刻一刻と近づいております、、！
やらなければやらなければと思いつつ、他のことをやっていたら手が回らず、ようやく0.1歩動こうと思い立ち、作業を行いました。

## 今回の進捗
今回の成果物は、下のようにキーボード操作に合わせて向きを変えて、推しが歩くようになるというものです。
次で実際にやったことを説明していきます。
<iframe width="560" height="315" src="https://www.youtube.com/embed/rX5nKX-f6E8?si=T7PVo7KjU_-ZUGpW" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>



## 何をしたか
⇩ 以下のお二つの神記事を参考につくっていきました

https://tanisugames.com/simple-anim-unity-2d/

https://cgbox.jp/2024/02/08/unity-pixel-art/

手順を追って、説明していきます

### ドット素材の読み込み
まず、素材を読み込みます。
Imagesディレクトリを作成して、そこに素材を放り込みました～～

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3952100/01bd5254-a56f-6bdd-24ea-425b4f293357.png)

### アニメーションの作成
次に、アニメーションの作成です。
左を向いて歩いているアニメーションから作成しました。
左向きのもの（2つ）を選択し、ヒエラルキーにドロップ。
するとアニメーションが作成されましたね、すごい、！

同じような手順で、右向きで歩くアニメーションも作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3952100/95544230-29fc-db38-98ae-687220322e6f.png)

この段階で、すでに実行すると歩いていてはいますが、ずっと左or右向きに歩いており操作することができません。

### アニメーションコントローラとの出会い
アニメーションを遷移するために、アニメーションコントローラを使います。なんか難しそう、、
実際に、参考にさせていただいた記事をみて繋げてみたものがこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3952100/28d6061c-9687-b965-c78d-1e5350dc8bb7.png)

よさそう、、？？

※ ちなみに遷移の条件としてパラメーターを設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3952100/2d259118-26e6-5767-1d4e-420cbef0dc2a.png)
trueの場合➔右向きのアニメーション、falseの場合➔左向きのアニメーション

アニメーションコントローラの方はできてそうなので、次にアニメーションにアタッチするスクリプトを書きます。スクリプトによって、キー入力で動きを制御できるようになるのですね～～

### スクリプトを書いた

右矢印入力したら右向き、左矢印入力したら左向きになるようにスクリプトを書きました。
とりあえず動きはしそう、、

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Control_move : MonoBehaviour
{
    Animator animator;
    // Start is called before the first frame update
    void Start()
    {
        animator = GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.RightArrow)){
            animator.SetBool("IsWalkRight", true);
        } else if(Input.GetKeyDown(KeyCode.LeftArrow)){
            animator.SetBool("IsWalkRight", false);
        }
    }
}

```

ってなわけで、これをアニメーションがくっついてるオブジェクトにアタッチしてみました。
そして、完成したものが最初に見せたものです。

## さいごに
と、とりあえずUnity上で動いた、、
まだまだ、ステージ設定したり、背景おいたり、位置変えられるようにしたりとやること盛りだくさんですが、ゆーっくりとやっていきたいと思います。←推しの誕生日すぎちゃうよッ！！！

見ていただきありがとうございました。
Amazon MSKを試したい(構成検討)

## MSKとは
Amazon Managed Streaming for Apache Kafkaのこと。
Apache Kafkaのインフラ管理をAWSがマネージドでやってくれるよというPaaS。
データストリームやメッセージキューイングに利用される。
Amazon Kinesis Data Streams(KDS)やAmazon Simple Queue Service(SQS)、Amazon MQ、Amazon Simple Notification Service(SNS)が比較対象となるサービスである。

MSKは標準的なAPI/ライブラリの利用が可能なため既存のアプリケーションの改修を最小限に利用が可能であり、スケーリングも可能で高可用性なシステムの構築が可能という特徴を持つ。
一方でKDS、SQS、SNSはAWS専用のAPI/ライブラリがインターフェースとなっているためクライアントの再設計が必要である。
またAmazon MQはスケーリングができずActive/Passiveな構成であることから大量のデータを扱う、ミッションクリティカルな大規模システムには向いていない。

クライアントの改修を心配しなくて良い場合はKDS、MSK、SQSが主な選択肢となる。
下記の記事で詳しい比較をしてくださっているので参考になりそうだ。
https://qiita.com/sigmalist/items/73d3feeb6e0f5905ed64

## MSK アーキテクチャ比較
MSKの初心者向けに比較を行う。
MSKではAWS上にApache Kafkaのブローカーを構築する。
アーキテクチャにはMSK ProvisionedとMSK Serverlessの2種類が存在する。
ProvisionedはブローカーインスタンスをMSKで明示的に管理し、Serverlessはブローカーインスタンスを意識することなく利用することができる。
Provisionedには更にStandardとExpressの2種類のブローカータイプに分かれる。
それぞれの概要は下記のとおりだ。(2025年2月現在)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561522/0a9fb03f-5f4d-7ec3-f22a-fb214b6f1a7c.png)

※1 プロビジョンドストレージスループットを利用した場合。(オプション)
※2 KRaftメタデータモードとExpress BrokerではPrometheusによるモニタリングとパブリックアクセスを同時に有効にすることはできない。
### MSK Provisioned Standard
最も一般的なブローカーでありStandard Brokerを基準として構成を考えていく必要がある。
利用可能なインスタンス数も多く設定可能な範囲の柔軟性も高い一方で、管理しなければいけない範囲も広い。
スケーリングにも対応しておりブローカーのスケールイン/スケールアウト、ブローカーのスケールアップ/スケールダウン、ストレージの拡張に対応している。
※ストレージの縮小には対応していない。
利用可能なリージョンが多く、大阪リージョンでの利用を考える必要がある場合には、Standard Broker一択となる。(2025年2月現在)

### MSK Provisioned Express
2024年11月にGAされたサービス。
1ブローカーあたりのスループットが(標準の)Provisioned Standard比で約3倍、スケールアップが最大20倍高速、復旧時間が 90% 短縮と謳われている。
また、公式ブログではスケールアウト時のパーティション再割り当てが100倍以上高速と実験されている。

一方でインスタンスサイズあたりのお値段はProvisioned Standard比で約2倍になっている。
Standard Brokerオプションであるプロビジョンドスループット(オプション)は1ブローカーあたり1MBpsが0.0966$/月で購入可能であり、スループット約3倍は美味しいとは言えない。
コスパに関しては悪いと言える。
また大阪リージョン未対応なため国内サービスのDR利用ができず、可用性に関しても一概に優れているとは言えない。

【利用想定】
- 高速なスケーリングが求められる
- ストレージのスケーリングが必要でかつ永続的でない
- 国内DRは不要だが大規模災害以外は高速で復旧したい
- ワールドワイドなActive/Active構成
- Active/Standby構成でStandby側はインスタンスサイズを小さくしてコスト削減 ※3

※3 DRリージョンでProvisioned Expressが利用可能な必要あり。

### MSK Serverless
キャパシティプランニングが不要なサーバレスなサービス。
構築にあたってはキャパシティプランニングが不要なためインフラエンジニアの工数を削ることができる。
一方で設定の柔軟性は低く、Kafkaのバージョンが指定できないことや認証がIAMのみなど非常に制限事項が多い。
またこちらも大阪リージョンでの利用はできない。
利用に応じて料金のかかるサーバレスな料金プランとなっているが、コンピューティング観点ではクラスターとパーティションについては有効化されている時間分請求される。
データ観点ではのイン/アウトのそれぞれとストレージの利用に応じて料金が請求される。

【利用想定】
- キャパシティプランニングが難しい
- インフラ管理者を十分確保できない
- 高いスループットは求められないが、時間によってスループットが大きく変化する

## 構成検討
今回は金融系システムで下記のような一般的な要件があると仮定する。
- 大阪リージョンにDRが必要
- Apache Kafkaのクライアントがオンプレ拠点に存在する
- 専用線にてオンプレと接続を行う
- 99.99％の可用性を求める
- メンテナンスはオンラインで行う
- スモールスタートでシステム構築
- 年度ごとに予算の確保が必要

上記の簡易なシステム構成として下記のような構成を考えた。
(オンプレ拠点からMSKに書き込み、AWS上のコンシューマーが読み取る。その後MSKにAWSからプロデューサーとして書き込んでオンプレがコンシューマーとして読み取るだけ。)
![AWS.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561522/59058b2b-3b7c-8cd0-7065-e317c310f39f.png)

このうちMSKの利用箇所のみ検討していく。
次回へ続く。。。
【LeetCode】125. Valid Palindrome 解いてみた【Easy】


<!--

## 技術記事のタイトル

【LeetCode】125. Valid Palindrome 解いてみた【Easy】

### 【 】(墨付き括弧)

タグ

LeetCode 競技プログラミング Python 

-->

## 問題の概要

回文
アルファベットと数字以外を削除して残った文章が前から読んでも後ろから読んでも同じ文章ならTrue

Input: s = "A man, a plan, a canal: Panama"
Output: true
Explanation: "amanaplanacanalpanama" is a palindrome.



## 最初に考えた解き方
・どうやってアルファベットと数字以外を削除するか
＞Unicodeに直してaからzもしくは0から9なら配列に格納？
・回文チェックは後ろから格納していくリストを上でつくったリスとから作成してリスト＝リストならTrue?
できるのか？
＞いや''.join(list)にしてから評価だな
もしくは配列は一つだけ作り、list[0] == list[-1]で評価していく？
(len(list) + 2　- 1) // 2 切り上げ回数評価

### ちょっとEasyでUnicodeはないだろとカンニングしてきた
.isalnum()
という便利なのがあるようだ

## 何がよくなかったか？

実はUnicodeで解く方法もあった
やってみれば楽しかったのに...


## 解き方

### 絶対思いつくであろう、文を反対にする

```
class Solution:
    def isPalindrome(self, s: str) -> bool:
        newStr = ''
        for c in s:
            if c.isalnum():
                newStr += c.lower()
        return newStr == newStr[::-1]
```


### 左と右にポインターを作る

```
class Solution:
    def isPalindrome(self, s: str) -> bool:
        l, r = 0, len(s) - 1

        while l < r:
            while l < r and not self.alphaNum(s[l]):
                l += 1
            while r > l and not self.alphaNum(s[r]):
                r -= 1
            if s[l].lower() != s[r].lower():
                return False
            l, r = l + 1, r - 1
        return True
    
    def alphaNum(self, c):
        return (ord('A') <= ord(c) <= ord('Z') or 
                ord('a') <= ord(c) <= ord('z') or 
                ord('0') <= ord(c) <= ord('9'))
```


#### 実は左と右にというのは初期の構想と似ていた。

もしくは配列は一つだけ作り、list[0] == list[-1]で評価していく？
これである。
なんとなくstrってインデックスで参照できないのかと思って考えるのをやめてしまった
f
## 参考資料

https://neetcode.io/solutions/valid-palindrome

## おわりに

楽なほうに流れずに自分でやってみると面白くなることもある
URLの書き方と短縮設定について調べてみた

# URLの書き方と短縮設定について調べてみた

Web開発をやっていると、URLの書き方が気になってきますよね。特に「https://」とか「www」の部分って省略されてることが多いけど、何がどこで決まってるのか知りたくなりました。

## 正式なURLってなにも省かないことだよね？
そもそもURLって、下みたいなフルの書き方が正しいですよね。

```
https://www.example.com/
```

けど、実際はこれを省いたり、短くしたりする場面が多い。その時に何が関与しているかを見ていきましょう。

## 主な省略の例とその設定場所

### 1. プロトコル (https://)の省略
**問題**: たまに「https://」が見えないことがありますよね？

**理由**: ブラウザが自動で表示を省いてくれることが多いです。でも実際は全てのURLにはあるもので、省かないと問題が起こる場面もあります。

**設定方法**: 特殊な設定はいりませんが、フロントエンドのコードを書くときは「https://」を残しておいたほうがセキュリティ的には上。

---

### 2. www の省略
**問題**: 「wwwあり」と「なし」の両方があるのはなぜ？

**理由**: これは、DNS設定によります。多くのサイトでは、wwwがなくてもリダイレクトされるように設定されています。

**設定方法**:
- DNS設定でwwwのありなしを突き合わせる
- Webサーバー側でリダイレクト設定
  
Apacheの例：
```apache
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
```

---

### 3. デフォルトファイルの省略 (/index.html)
**問題**: どうして「/index.html」が省かれるの？

**理由**: Webサーバーは「デフォルトファイル」を自動で読み込むので、ブラウザには表示されません。

**設定方法**:
- Apacheでは「DirectoryIndex」を設定
```apache
DirectoryIndex index.html index.php
```
- NGINXでは「index」ディレクティブで設定
```nginx
location / {
    index index.html index.htm;
}
```

---

### 4. 短縮URLの使用
**問題**: SNSでたまにめちゃくちゃ短いURLを見るけどあれって？

**理由**: 短縮URLサービスが自動で不要な情報を省き、新しいURLを生成しています。

**設定方法**:
- **bit.ly**や**t.co**などの外部サービスを利用
- 自分のサーバーで短縮したければ [YOURLS](https://yourls.org/) を使って設定できます

---

## まとめ

| 省略方法            | 設定場所                     | メモ                                                                 |
|--------------------|----------------------------------|----------------------------------------------------------------------|
| プロトコル省略      | ブラウザ自動                  | セキュリティ重視の場面では残したほうがよい。                           |
| wwwの省略           | DNS設定、Webサーバー側設定      | wwwの有無を突き合わせるのが重要。                         |
| デフォルトファイル省略 | Webサーバーのデフォルト設定      | index.html などはサーバー側の設定で省略される。 |
| 短縮URLの使用       | 外部サービスや自分の短縮システム | SNSで便利だが、安全に使うには利用先に注意。                       |
【論文読み】灯油配送計画問題の近似最適化における車両別配送地域の決定戦略の検証

## はじめに
こんにちは。読んだ論文の紹介記事です。
今回紹介するのは、「灯油配送計画問題の近似最適化における車両別配送地域の決定戦略の検証」という論文です。  

- タイトル： 灯油配送計画問題の近似最適化における車両別配送地域の決定戦略の検証
- 出典： 人工知能学会 第127回知識ベースシステム研究会(2022)
- URL： https://www.jstage.jst.go.jp/article/jsaikbs/127/0/127_11/_pdf/-char/ja


## 概要
本研究では、配達エリアを決定するアルゴリズムと灯油配達計画問題に対する手法を提案する。灯油消費データに基づく実験では、実際の配達時間よりも総作業時間を36%短縮した計画の実現可能性が示された。
本論文では、現状の配送地域よりも良い配送地域を作成し、配送業務に関わる内容の均等化や全体の配送計画の効率化を目標に、配送地域の決定戦略を提案する。
タンクローリーを1台に制限した設定での灯油配送計画問題についてそれぞれの配送地域で解を求め、1配送業者が扱う地域全体での配送計画を評価する。


## 特徴
- 配送地域の決定戦略
    - 配送地域の決定戦略において考慮すべき内容としては、合計給油量や総配送件数、総移動距離といった作業時間に影響を及ぼす数値であり、これらを均等化することを考える。
    - デポ距離、クラスタ中心距離の2つを考える。まずはこれらの数値を使って求まる評価関数について、重みパラメータを掛けた和として定義する。

- 灯油配送計画問題
    - ローリングホライズン方式とは、在庫配送計画問題(IRP) をはじめとするスケジューリングを行う最適化問題において、最適化する期間を区切り、区切った区間において問題を新たに作成、最適化し、得られた解を適用しながら次の区間へスライドさせていく手法である。以下の２つのパラメータがある。本論文ではW=Sとする。
        - 次の計画開始日を決めるために何日間スライドするかを決定するステップサイズW
        - 下位問題の計画期間を決める値としてウィンドウサイズS
　　- タブサーチメタヒューリスティクスの1種であり、近傍探索による解の改善（移動操作）をメモリに記憶し、記憶された移動操作を禁止することによって、局所解への停滞を回避する手法である。

- 実験結果
    - 提案手法によって得られた配送計画は、配送履歴から得られた配送計画よりもより少ない作業時間となっていることが分かる。
    - 残量しきい値を現状に合わせたインスタンスでは、最も良い作業時間が 5.62時間であり、配送履歴から作成した配送計画と比べて17%の作業時間を削減可能であることが分かる。
    - また、残量しきい値を低く0.3に設定した結果については、最も良い作業時間が 4.34 時間となっており、配送履歴から作成した配送計画と比べて、36%程度作業時間を減らせていることが分かる。


## 想定される適用例
- 様々な配送の最適化


## 参考
- [灯油配送計画問題の近似最適化における車両別配送地域の決定戦略の検証](https://www.jstage.jst.go.jp/article/jsaikbs/127/0/127_11/_pdf/-char/ja)
【合格体験記】AWS Certified Security - Specialty (SCS-C02) 

いつも記事を読んでいただきありがとうございます！
モブエンジニア（[@mob-engineer](https://qiita.com/mob_engineer))です！

2025.02.11（火）に**AWS Certified Security - Specialty**を受験し無事合格したので、アウトプットして合格体験記を執筆したいと思います。

初学者でもサクッと読めるように平易な表現で執筆しておりますので、お気軽に読んでいただければ幸いです。

#### 試験結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846878/4213da22-da9e-0e95-d759-a2cdd344fa91.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846878/267031d6-9240-1beb-a61d-635178d09aae.png)

スコア自体は800点台でしたので問題ありませんでしたが、
「第2分野：セキュリティロギングとモニタリング」と「第3分野：インフラストラクチャのセキュリティ」に関して改善が必要と言った結果でしたので、キャッチアップ不足感は否めない印象でした。

# 目次
- 対象読者
- AWS Certified Security - Specialty（SCS-C02）とは
- 試験対策
    - 試験時
- よりよい学習ポイント
- まとめ

## 対象読者

次のような課題を抱えている読者のお役に立てていただければ幸いです。

- SCS-C02の試験勉強をチャレンジしている方
- AWSのセキュリティ関連サービスについて知りたい方
- SCS-C02合格後のキャッチアップ方法を模索している方

## AWS Certified Security - Specialty（SCS-C02）とは

公式サイトを見てみると以下の通り示されています。

#### 公式サイト

https://aws.amazon.com/jp/certification/certified-security-specialty/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846878/54a3ac75-2704-56a0-c1ac-c7bad0a34050.png)

>AWS クラウドにおけるセキュリティソリューションの作成と実装に関する知識を検証します。この認定では、専門的なデータ分類と AWS のデータ保護メカニズム、データ暗号化方法とそれらを実装するための AWS メカニズム、および安全なインターネットプロトコルとそれらを実装するための AWS メカニズムについての理解も検証されます。

ざっくり言えば、**AWSを用いたソリューションのセキュリティ対策を計画⇒実装⇒運用できる人材向けの資格**と思っていただければわかりやすいかと思います。

出題範囲に関しては、以下試験ガイドに示されています。

:::note alert
**AWSがソリューションアーキテクトに対してどのようなセキュリティ知識を求めているのか**を認定ガイドは示しています。SCS-C02を受験する・しないに限らず、セキュリティ担当者なのであれば、目を通しておいてください。
:::

#### 試験ガイド

https://d1.awsstatic.com/ja_JP/training-and-certification/docs-security-spec/AWS-Certified-Security-Specialty_Exam-Guide.pdf

## 試験対策

試験勉強に関しては**約2週間**の期間行っておりました。勉強時間として、**約20時間**位だったと記憶しております。

学習方法として以下を行っておりました。

- ①：出題傾向の理解
    - AWS Skill Builder：SCS-C02
- ②：出題範囲の演習
    - Cloud License
    - 解説を読んで**正しい選択肢の根拠を示す**ことを行っておりました
    - 本番試験モードでコンスタントに80％以上のスコアを得点できたら合格圏内かと思います
- ③：サービス理解
    - 各サービスのFAQ
        - ユーザリファレンスより端的にまとめられており、最初に読んでおくことを推奨します
    - ユーザリファレンス
        - 主要サービス（Amazon Detective、Amazon GuardDutyなど）は目を通しておくことを推奨します

### 試験時

試験内容に関しても、想定していた内容が取り上げられていたためそこまで苦戦する印象はありませんでした。ただし、以前受けたMLSよりかは**根拠を持った選択肢選び**は行えなかったと思います。

## よりよい学習ポイント

個人的に学習を行うなかで、より良い学習ポイントとして以下があるとと思いました。

- ポリシー周りは可能な限り手を動かしておく
    - IAMに関しては基本的に無料で利用可能なため、ポリシー周りは手を動かしてキャッチアップすることをおすすめします
- ANSと並行して学習を行ってみる
    - 現時点でANSの学習も行っていますが、ネットワーク分離などSCSで求められる知識が流用可能です
    - セキュリティロギングやインフラストラクチャのセキュリティは特にその傾向が強いのではと学習しながら思っています
- **試験学習のための勉強で終わらせない**
    - 本試験に限らないですが**認定試験を通じて得た知識をどのようにアウトプットしていくか**が最も重要だと思っています
    - 特に、セキュリティ戦略に関しては実務でも求められるシーンが多数あるため、**認定資格合格してからがスタートライン**と思って学習することを心がけるとよい良い結果になると思います

## まとめ

SCS-C02の合格体験記についてまとめてみましたが、AWSのセキュリティサービスに関しては、深掘りすることで**面白い景色**が見えるかと思います。

また、今回の試験範囲では出題外でしたが、宣言型ポリシーなどの考えについても今後試験で取り上げられていく可能性が高いと思います。そのため、**試験で求められている以外のサービス知識**も必要だと個人的に思いました。

## 参考ブログ

https://sal-blog.com/aws-scs/

https://note.com/fallen_pear/n/nf55bb121d975

最後まで読んでいただきありがとうございました！！
本記事が、読者の皆さんのお役に立てていただければ幸いです！！
CAN通信をラスパイのWiresharkでモニタする

CAN通信をラズパイのWiresharkでモニタする方法です

:v:アピールポイント:v:
- DockerのWiresharkコンテナを利用
- Wiresharkコンテナを日本語表示で起動
- CANのデータをISO-TP、UDSで解析

## 使用機器
- Raspberry PI 4
- [RS485 CAN HAT](https://www.waveshare.com/rs485-can-hat.htm)

## 手順
### 1. ラズパイにCANインタフェースボードを追加してCAN通信できるようにする
以下のページを参考にラズパイでCAN通信できるようにする

https://www.nomishinblog.online/raspberrypi-can-sendreceive/

以下を実行し、can0インタフェースが有効な状態にしておく
```
$ sudo ip link set can0 up type can bitrate 500000
```

### 2. ラズパイにDockerをインストール
Docker公式の [Install using the convenience script](https://docs.docker.com/engine/install/debian/#install-using-the-convenience-script)のぺージで紹介されている以下コマンドでDockerをインストール
```
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
```
また、sudoなしでDockerコマンド実行できるようにするため、以下ページを参考にしてDockerグループにユーザを追加

https://qiita.com/sakagucchi/items/92dc2ddc4f286405077e

### 3. Wiresharkコンテナ起動
Docker Hubから [linuxserver/wireshark](https://hub.docker.com/r/linuxserver/wireshark) のコンテナイメージをpull
```
docker pull lscr.io/linuxserver/wireshark
```


Wiresharkコンテナを日本語表示で起動
- 日本語表示のために```LC_ALL```,```DOCKER_MODS```,```INSTALL_PACKAGES```を設定
```
docker run -d \
  --name=wireshark \
  --net=host \
  --cap-add=NET_ADMIN \
  --security-opt seccomp=unconfined \
  -e PUID=1000 \
  -e PGID=1000 \
  -e TZ=Asia/Tokyo \
  -p 3000:3000 \
  -p 3001:3001 \
  -v /path/to/wireshark/config:/config \
  --restart unless-stopped \
  -e LC_ALL=ja_JP.UTF-8 \
  -e DOCKER_MODS=linuxserver/mods:universal-package-install \
  -e INSTALL_PACKAGES=font-noto-cjk \
  lscr.io/linuxserver/wireshark:latest
```

### 4. CAN通信をWiresharkでモニタ
ブラウザで ```http://{ラズパイのアドレス}:3000``` にアクセスすると、Wiresharkの画面が表示される
- Wireshark画面が表示可能となるまでに、コンテナ起動後 数分かかる場合がある

![2025-02-11_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269407/bd0baf35-92a4-c682-533c-f3055f2f64b6.png)

### 5. CANデータをISO-TP、UDSで解析
- ISO-TP： OSI参照モデルのネットワーク層、トランスポート層のプロトコルで、フレーム分割の制御などを行う。ISO 15765-2で定められている。
- UDS： OSI参照モデルではアプリケーション層のプロトコル。診断通信プロトコル。ISO 14229-1で定められている。

Wiresharkの「分析」－「･･･としてデコード」で、以下の画面のように設定する
![2025-02-11_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269407/92833597-0b52-4f5a-1ef2-085800d1c831.png)

UDSで解析するようにしておけば、OBD-Ⅱデータも自動解析される
- 以下の画面例ではサポートPIDが表示されている

![2025-02-11_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269407/82dd452a-ecc9-c9ed-ca06-5e20bcf92c08.png)

複数フレームに分割されているデータも一つにまとめて、UDSデータとして表示される
- 以下の画面例では3フレームのデータをまとめて、UDSのSecurity AccessのSeedが表示されている

![2025-02-11_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269407/3238b38f-54cd-8258-43b8-87f9bb13f450.png)

### 6. DockerのWiresharkコンテナを停止する

```
docker stop wireshark
docker rm wireshark
```

以上です。
【ABC】バケット問題 AtCorder 081 C - Not so Diverse

# 目的
[AtCoder 081 C - Not so Diverse](https://atcoder.jp/contests/abc081/tasks/arc086_a)にあるバケット問題について考え方などを備忘録として残す。

# はじめに
## バケットとは
配列の値の度数分布を新たな配列を用いて表したものである。
例えば、配列A=[3, 1, 3, 6, 4, 0]のバケットA_bucketは以下のようになる。
A_bucket=[1, 1, 0, 2, 1, 0, 1]
| | 説明 |
| --- | :-: |
| A_bucket[0] | 配列Aに出てきた0の個数 |
| A_bucket[1] | 配列Aに出てきた1の個数 |
| A_bucket[2] | 配列Aに出てきた2の個数 |
| A_bucket[3] | 配列Aに出てきた3の個数 |
| A_bucket[4] | 配列Aに出てきた4の個数 |
| A_bucket[5] | 配列Aに出てきた5の個数 |
| A_bucket[6] | 配列Aに出てきた6の個数 |

# ソースコード
```c++
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

using namespace std;
#define rep(i, n) for (int i = 0; i < (int)n; ++i)

int main()
{
    int n, k;
    cin >> n >> k;
    vector<int> a_bucket(n+1);
    rep(i, n) {
        int a;
        cin >> a;
        a_bucket[a] += 1;
    }

    // 0を抜いた配列を作成
    vector<int> vec;
    rep(i, n+1) {
        if (a_bucket[i] != 0) vec.push_back(a_bucket[i]);
    }

    int kind = vec.size();
    // 昇順にソート
    sort(vec.begin(), vec.end());
    if (kind <= k) cout << 0 << endl;
    else {
        int query = 0;
        rep(i, n+1) {
            // 0でない箇所を探す
            if (vec[i] != 0) {
                // 種類を減らすには該当箇所の個数を0にする必要がある
                query += vec[i];
                vec[i] = 0;
                --kind;
            }
            if (kind <= k) break;
        }
        cout << query << endl;
    }
    return 0;
}
```
Tableau CloudとSnowflake間のOAuthを構成してみる

ドキュメント
https://docs.snowflake.com/ja/user-guide/oauth-partner.html

## SnowflakeでのTableau CloudへのOAuth統合
Tableau CloudとDesktopは別のSECURITY INTEGRATIONの設定が必要
トークンの有効期限は最大90日（デフォルトも90日）で超過すると再度ログインプロセスが必要
トークンの最大値を上げる必要がある場合は、Snowflakeサポートにリクエストする

Snowflake上でACCOUNTADMIN権限で実行する

```SQL:Tableau Cloudセキュリティ統合設定
CREATE OR REPLACE SECURITY INTEGRATION TABLEAU_ONLINE_OAUTH
  TYPE = OAUTH
  ENABLED = TRUE
  OAUTH_CLIENT = TABLEAU_SERVER
;
```
トークンの有効期限は最大90日（デフォルトも90日）で超過すると再度ログインプロセスが必要

Tableau Cloudの画面右上よりマイアカウントの設定を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304373/fc17038e-fe03-9b77-7500-49886207d96b.png)

セキュリティのSnowflakeよりOAuth認証情報を追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304373/b22600db-fbf8-cbdf-53b1-6d6bcae354f8.png)

URLを入力（画像は期限切れSnowflakeトライアル）
Snowflakeのユーザーのロールはデフォルトロールを利用する場合では空欄のままでOK
※ACCOUNTADMINがデフォルトロールの場合なぜかログインが出来なかったので今回はSYSADMINを指定した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304373/115e026e-abe4-561e-9226-ff837bac6acb.png)

Snowflakeへログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304373/ee77964c-5fc7-b61b-7ce5-9504d5b18c12.png)

許可の画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304373/b2c00002-997d-9e85-9b0e-b1c7ea54f19f.png)

テストを押下し接続が無事できていることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304373/742bf654-f7ac-3bf1-01fa-424982e4cdba.png)

## Tableau Cloud上から直接データソースをパブリッシュしてみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304373/1127030b-43a2-d64e-adbc-8ce1381957ad.png)

Snowflakeを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304373/0531fad6-48dc-1d24-500c-96e6f996b6da.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304373/815e9994-2020-aa93-ec47-34263e36744e.png)

このあとは先ほどと同様に認証する

適当なデータソースを作成し、右上のパブリッシュボタンを押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304373/c40d7635-bc39-fb5d-fb98-dea0377bc76a.png)

認証情報の埋め込みのオプションがある。これを有効化すると今現在パブリッシュしようとしているユーザの認証情報が埋め込まれる。
逆に言えば埋め込まない場合このデータソースは利用するユーザごとに認証を要求する。デフォルトロールを用いている場合ユーザーによってそのロールも異なる可能性もある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304373/3ac5ec50-7d75-bd82-8599-8d71458d31de.png)

パブリッシュを押下すると無事完了

## SnowflakeでのTableau DesktopへのOAuth統合
Tableau CloudとDesktopは別のSECURITY INTEGRATIONの設定が必要

```SQL:Tableau Desktopセキュリティ統合設定
CREATE OR REPLACE SECURITY INTEGRATION TABLEAU_DESKTOP_OAUTH
  TYPE = OAUTH
  ENABLED = TRUE
  OAUTH_CLIENT = TABLEAU_DESKTOP
;
```
トークンの有効期限は最大10時間（デフォルトも10時間）で超過すると再度ログインプロセスが必要
トークンの最大値を上げる必要がある場合は、Snowflakeサポートにリクエストする

あとはTableau Desktopからtableau Cloudと同じようなイメージで接続する
社内のネットワークポリシーによって接続できない可能性も留意
【JavaScript】importで外部ファイル読み込み


JavaScript[ES6]では、**import** と **export** を使えるようになりました。

今回はES6に導入された **import** についてわかりやすく説明していきます。

## import とは

ES6では、JavaScriptオブジェクトをモジュール化して管理することができます。
モジュール化を行うと、**機能の再利用** 、**保守性** 、**変数名を被る問題を防ぐ** ことに関してうまく利用することが可能です。

このように記述をします

```JavaScript
import {モジュール名} from "インポート元"
```
## 基本的なimportの使い方

モジュールには **defaultモジュール** と **namedモジュール** があります。


### namedモジュールのインポート

modulesというファイルから、ModuleAとModuleBの2つのモジュールをインポートする方法をnamedモジュールのインポートする方法です。

```JavaScript
import {ModuleA,ModuleB}1 from "modules";
```


### defaltモジュールのインポート

moduleというファイルから、derfaultモジュールをインポートする方法です。

```JavaScript
import Default from "module";
```
【SwiftUI】モディファイアについて

## 概要
SwiftUIのモディファイアについて、簡単にまとめます

## モディファイアとは
そもそもModifireの意味から見ていきましょう
**Modifire**
- 変更[修正]する人[物]
- 修飾子

そんで、SwiftUIのモディファイアとは。
Text()やButton()、VStackなどのView構造体に対して、**外観や動作を変化・変更させる修飾子**です。
英単語の意味する通りですね。

具体的には以下のようにViewに対してチェーン形式（.で繋げること）で適用している`.padding`や`.background`を指します。
```swift
Text("Hello, SwiftUI!")
    .padding()
    .background(Color.blue)
```

## 代表的なモディファイア
- `padding`: 内側の余白を追加する
- `background`: 背景色を設定する
- `cornerRadius`: 角を丸くする
- `font`: フォントサイズやスタイルを設定
- `foregroundColor`: テキストの色を設定
- `frame`: ビューの幅・高さを設定
- `onTapGesture`: タップジェスチャーを検知

もちろんもっと沢山ありますので、沢山使って慣れていきたいです。

## モディファイアを使ううえでの注意点
モディファイアは適用順に処理されます。
以下をご覧ください。
```swift
var body: some View {
    VStack{
       Text("Text1")
       .background(.gray)
       .frame(width: 200, height: 200)

       Text("Text２")
       .frame(width: 200, height: 200)
       .background(.gray)
    }
}
```

コードだけを見るとbackground(.gray)の順番が変わっただけで同じ結果になるようにも感じますよね。
実行結果を見てみましょう。
![Simulator Screen Shot - iPhone 14 Pro - 2025-02-11 at 21.39.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577392/ebdfc15b-324e-bf07-ba91-63e13ccc1e41.png)

ご覧の通り、背景色のついている範囲が異なります。
Text1はTextに`.background`で背景色をつけた後に、200x200の`.frame`を指定していますので、あくまで背景色が付けられたのは元のTextのサイズに対してになります。
Text2は200x200にサイズ指定された`.frame`に対して`.background`を指定していますから、200x200のサイズに背景色がつきます。

参考までに
Text1のframe指定後にもbackgroundカラーを指定すると、その対象範囲がわかりやすいです。
```swift
Text("Text1")
.background(.gray)
.frame(width: 100, height: 100)
.background(.red)
```
![Simulator Screen Shot - iPhone 14 Pro - 2025-02-11 at 21.48.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577392/55a9b5b8-665a-b1f4-2a15-432855aeef51.png)


## カスタムモディファイア
モディファイアは自作することも可能です。
Viewプロトコルを拡張し、Viewを返す関数を定義することで、それがカスタムモディファイアとなります。

例えば、APP内で共通のデザインとして
「上下左右10ptの余白をつけて、背景色は黄色、背景の角は10pt丸める」
というものがあるとします。

その場合以下のように自作することができます。
```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("カスタムモディファイア")
            .commonBackground() // カスタムモディファイアの適用
    }
}

// Viewプロトコルのextension内で、Viewを返す関数を定義
extension View {
    func commonBackground() -> some View {
        self
            .padding(10)
            .background(Color.yellow)
            .cornerRadius(10)
    }
}
```

こうすることで、自作のカスタムモディファイアもチェーンで繋げて使用することができます。
カスタムモディファイアの正体が関数である以上、引数も取れるわけなので、Bool型によってモディファイアのちょっとした制御なんかもできます。

モディファイアによって共通のデザインやロジックをまとめられるので、再利用性が高まり、より完結なビュー設計やコードの記述が可能になります。

## まとめ
かなり簡単に自作もできることがわかりましたので、活用していきたいですね。
APP内での統一されたデザインを提供するのにもやくだちそうです
また、SwiftUIが既に提供しているモディファイアにももっと種類があるので、沢山使って慣れていきたいです。
AWS Certified Solutions Architect - Associate (SAA) 合格体験記

## はじめに
SAAに合格したので、合格体験記として記事にする

- 学習期間
  2024年12月～2025年2月上旬

- 結果
  853/1000

## 利用した学習教材

- **Ping-t**
  - 無料の範囲のみ利用
  - 分野毎の問題で各サービスへの理解を深めた
  - 模擬試験問題は300問弱ある
- **Cloud License**
  - 主に模擬試験で利用
  - 問題数が多いので、Ping-tで物足りない場合はおすすめ

Ping-tは基礎問題も含めると結構問題数があり、問題の質も高く解説もわかりやすかったので、これが無料で利用できるのはありがたかった。Ping-tだけでも十分だと思う。
学習期間の後半はPing-tの模擬試験問題も全部解き終わってしまったので、Cloud Licenseの模擬試験をひたすら解いた。圧倒的に問題数が多いのでいろんなパターンの問題に慣れたい場合はおすすめ。

## 試験本番の出題傾向
Ping-tとCloud Licenseと全く同じ問題が10問くらい出題された。
そのほかの問題も概ね上記学習教材の問題と類似している問題が出題された。
全体的に問題文の長さは模擬試験よりも短かったので、回答の選択に集中できた。
模擬試験問題の長さに慣れておけば本番は問題なさそう。


## 感想
ある程度実務を経験してからの受験だったが、基礎的なサービスであっても業務で触れないサービスだと理解が浅かったので、一度はしっかり座学するべきだと思った。私は問題を解いて解説を読むだけだと記憶できないタイプなので、公式ドキュメントや問題の解説を自分なりに整理し、以下のようにQiita記事にまとめて理解を深めた。

[SAA 学習メモ VPC 関連](https://qiita.com/kikutch/items/e48c63696ac2bbbcf980)
[SAA 学習メモ EC2 関連](https://qiita.com/kikutch/items/b0b6fbf5a7c1fa0acfce)
[SAA 学習メモ S3 関連](https://qiita.com/kikutch/items/c18e027db7e881c31bf4)
[SAA 学習メモ Snow Family 関連](https://qiita.com/kikutch/items/921b594753d8ae6b9f74)
[SAA 学習メモ Storage Gateway 関連](https://qiita.com/kikutch/items/1b4e7f3f8289049b25ba)
[SAA 学習メモ 機械学習サービス 関連](https://qiita.com/kikutch/items/decb1c366f1c3472276b)

とりあえず合格することが目的の場合はCloud Lisenceでひたすら問題を解けば問題なさそう。
じっくりとAWSへの理解を深めながら学習しないとモチベーションが上がらない自分みたいなタイプの人はPing-tの基礎問題からやるとよさそう。
Djangoのトランザクションについて

Djangoではデフォルトで、実行されたクエリが即座にDBにコミットされる
DB処理にトランザクションを指定する方法👇

#### ※始まる前に注意事項
Djangoの**ロールバックがはしる条件は例外の発生ではなく、例外で処理をぬけること**
例えば以下のコードでは途中で登録処理に失敗してもロールバックがされない
```
def viewfunc(request):
    try:
        add_person()
        add_group()
        add_company()
    except Error:
        pass # 例外がもみけされ、結果例外で処理をぬけてない
```

### 明示的にトランザクションをコントロール

特定のView関数にトランザクションを指定
```
from django.db import transaction

@transaction.atomic
def viewfunc(request):  
    # This code executes inside a transaction.  
    do_stuff()  
```

例外で処理をぬけず、特定の条件を満たす場面でロールバックをしたいときは
組み込み関数のset_rollback関数を使える

>set_rollback ( rollback、 using = None )  ¶
>>rollback=True: 
ロールバック フラグをTrueに設定すると、最も内側のアトミック ブロックを終了するときに強制的にロールバックが実行されます。これは、例外を発生させずにロールバックをトリガーする場合に役立ちます。

>>rollback=False: 
ロールバック フラグをFalseに設定すると、このようなロールバックが防止されます。これを行う前に、トランザクションを現在のアトミック ブロック内の既知の正常なセーブポイントにロールバックしたことを確認してください。そうしないと、アトミック性が損なわれ、データが破損する可能性があります。

```
from django.db import transaction


# open a transaction
@transaction.atomic
def viewfunc(request):
    a.save()
    b.save()
    if some_condition is True:
        transaction.set_rollback(True)
        return
```

特定の領域にトランザクションを指定
```
from django.db import transaction

def viewfunc(request):
    # This code executes in autocommit mode (Django's default).
    do_stuff()

    with transaction.atomic():
        # This code executes inside a transaction.
        do_more_stuff()
```

例外処理と一緒に記載する方法
```
from django.db import IntegrityError, transaction


@transaction.atomic
def viewfunc(request):
    create_parent()

    try:
        with transaction.atomic():
            generate_relationships()
    except IntegrityError:
        handle_exception()

    add_children()
```
### 各リクエストをトランザクションでラップ
```
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        'ATOMIC_REQUESTS': True, # 各リクエストをトランザクションでラップする
    }
}
```
>ビュー関数を呼び出す前に、Django はトランザクションを開始します。問題なく応答が生成された場合、Django はトランザクションをコミットします。ビューが例外を生成した場合、Django はトランザクションをロールバックします。

### 'ATOMIC_REQUESTS': Trueを無効かする方法
```
from django.db import transaction


@transaction.non_atomic_requests
def my_view(request):
    do_stuff()
```

---------------
公式サイト　　
https://docs.djangoproject.com/en/5.1/topics/db/transactions/
電脳少女プログラミング2008【一番通りの繁華街】Cで解いてみた

paizaさんの、電脳少女プログラミング2088、楽しく解いてます。
レイミ可愛いし、検証中画面もかっこいい。
問題によってC言語で解いたりPythonで解いたりしてますが、
解いてみた投稿でC言語が少ない印象だったので、Cで書いたものを載せてみます。
リンクはこちら　[電脳少女プログラミング2088](https://ppg.paiza.jp/denno2088/areas/7 "一番通りの繁華街")

```ichiban.c
#include <stdio.h>
#include <string.h>
int main(void){
    // 自分の得意な言語で
    // Let's チャレンジ！！
    int n;
    int i,j,k;
    int count = 0; //正方形の数
    int sidelen; //辺の長さ
    char str[1000];
    fgets(str, sizeof(str), stdin);
    sscanf(str,"%d", &n);
    //マップを読み込む
    char map[n][n+1];
    memset( map, 0x00, sizeof(map));
    for( i=0; i<n; i++) {
        fgets( str, sizeof(str), stdin);
        sscanf( str, "%s", map[i]);
    }
    //正方形を探す
    for( i=0; i<n; i++) {
        for( j=0; j<n; j++) {
            if( map[i][j] == '.') { //アジトを見つけた
                for( k=j+1; k<n; k++) {
                    if( map[i][k] == '.') { //もうひとつ見つけたので、正方形になる位置にほかのアジトがあるか確認していく
                        sidelen = k-j;
                        if ( i+sidelen<n && map[i+sidelen][j] == '.' && map[i+sidelen][k] == '.') {
                            //正方形を見つけた
                            count++;
                        }
                    }
                }
            }
        }
    }
    printf("%d\n", count);
    return 0;
}
```
お姉さんなレイミからは、
ちょっとした工夫でもっと効率的になるかもしれない
例えば二重ループの構造を見直してみるのはどうか
って言われました。

島根弁のレイミからはこんな感じ。
![2025-02-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4007618/792744f9-0993-0b59-e3a1-2db710a06358.png)