OmniAICreator/Qiita-1.07M huggingface dataset:
DifyでGitHubからコード検索できるようにする

## はじめに

chatGPTやBingを使ってコード生成することはできますが、いまひとつ物足りなさを感じていることがあります。それは、参考にしている元情報がブログ記事であって、GitHubの生コードではないといったことろです。そこでGitHubを対象に検索してくれる生成AIアプリを作ってみました。

作るといっても、Difyを使うことでノーコードで作れます。GitHubツールがビルトインされているため、それを組み込んだらいいだけです。非エンジニアはこれでも開発と言っているようですが、エンジニアであればこれで開発というのは少しいかがなものだろうかといった心境です。

モデルは有料にはなりますが、OpenAIの最新モデルを使うことができます。Dify自体は無償で使えます。GitHubのビルトインツールの使用も無料です。

## 作り方

「最初から作成」より「エージェント」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/ec2f9397-0ef7-4239-70fe-5ece2b9d1c2d.png)

「ツールの追加」で「Github Search Repositories」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/ecd337eb-5450-1607-a632-a66651d7b248.png)

「lang変数」を作成して、プロダウン項目に自分がよく使う言語をいくつか追加します。自分はRubyとJava Scriptをよく使うのでこの２つを追加しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/91443b84-4221-9ef4-91f3-dc21dc43afa1.png)

「手順」にはこのように記述しました。「変数lang」には画面のプルダウンから選択した言語が入力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/394585b8-99c0-f5fc-ac26-b57d7eca841a.png)

入力画面のイメージはこのようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/a7452961-94fb-7291-a342-b65caeea21c0.png)

モデルは色々と選択できるようになっています。自分は格安なgpt-4o-miniを選択しました。gpt-4にすると少し割高になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/a87500bc-8f48-0aea-9a04-34c5ddfa57bc.png)

## 実行結果

Difyの実行結果です。このようにRubyでコードを生成してくれました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/60a68718-2cdb-31ed-18d1-1c90141944c6.png)

この程度の質問であればchatGPTで聞いても同じ回答をしてくれました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/0214162d-84a3-9ef6-4f96-629d7fdedd57.png)

異なる質問をしてみました。Difyの結果です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/4fee3bbe-f0a9-5924-c142-e897ab44e555.png)

chatGPTの結果です。随分と差が出てきました。Difyの方がスマートな回答をしてくれました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/ede42397-bf4f-d5dd-4734-fa424587476c.png)
SpringBootプロジェクトでimport文が全てエラーになった時の対処法

# エラー内容

全てのimport文に赤い線がかかり、以下のエラーが出力

```
Cannot resolve the modulepaths/classpaths automatically, please specify the value in the launch.json.
```


# 解決方法

1.Spring Boot Extension Packをアンインストール

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1243082/8ea058e4-52ec-fabe-6595-ff910a93a577.png)

2.VSCを再起動

3.Spring Boot Extension Packを再インストール

4.[Ctrl] + [Shift] + [p]で cleanと検索し「Clean Java Language Server Workspace」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1243082/db00dab0-a162-d978-5453-977a6db5540f.png)

以上です。

## 参考サイト

https://www.geecul.com/entry/2020/10/11/184750
LangChain × NVIDIA NIM で実現：調査レポート自動生成エージェント

最近、LangChainがNVIDIA AIで調査レポートを自動生成するAgentをリリースし、NVIDIA NIM上で公開したというブログをLangchainのホームページで見ました。
NVIDIA AI/NIM は以前から名前だけは聞いたことがあったのですが、実際に触ったことはなかったので、今回このAgentをきっかけに少し試してみました。

https://build.nvidia.com/explore/discover

NVIDIA NIM は、NVIDIA 独自のAgent Storeのようなもので、Low Code や No Code でもAgentを作成できます。しかも、多くのオープンソースモデルが揃っており、UI もシンプルで直感的に使えるため、かなり便利だと感じました。

# 1. 調査レポート作成Agentのワークフロー

このAgentのワークフローは下記図の通りですが、ざっくり説明すると、まず最初にはPlanning Agent（LangGraph を使って実装）が全体のプランを組み立て、次に調査Agent（NVIDIA NIM 上で定義）を呼び出して必要な情報を収集します。調査には Tavily API を利用して検索を行い、その結果をもとにレポート生成Agent（こちらも NIM 上で定義）を用いて最終的なレポートを作成し、ユーザに返すという仕組みです。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/52019136-520b-eae9-6160-d066f2238e70.png)


# 2. Sakana AI の AI Scientist との比較
このレポート生成機能はビジネス向けの調査レポートだけでなく、学術的なレポートにも対応できるとされています。ここで「学術レポート」と聞いて思い浮かんだのが、sakanai AIのAI Scientistです。ワークフローとしてはかなり似ており、「AI Scientist の簡易版」といった印象を受けました。（⇩はAI Scientistのワークフロー）




![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/c2cfbac1-e5b9-01a4-f96d-aec70e031388.png)

一方、Sakanai AI の AI Scientist については、こちらの論文（https://arxiv.org/pdf/2408.06292）
で詳しく説明されています。AI Scientist はプランニング用のAgentに加え、LLM を使って実験用コードを生成し、そのコードを実行して得られた実験結果をまとめ、LaTeX 形式の論文として執筆するなど、より高度なプロセスを実現しています。それに比べると、今回のAgentはあくまで「調査」に特化しており、実行までは踏み込まない分、汎用的なレポート作成を手軽に行える印象です。

ちなみに、NVIDIA NIM 上で作成したAgentは、ワンクリックでデプロイも可能です。また、料金も「1 時間いくら」という形で可視化されているので、コスト感覚をつかみやすく使い勝手が良さそうです。

![123123123123123123213.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/16cf1dde-b141-6fe3-628f-c04aae2f8d36.png)


興味ある方:

https://blog.langchain.dev/structured-report-generation-blueprint/
Gaussian Installation note on linux

Version: Gaussian G16 C.01 linux x86_64 with AVX2 support

Package name: ***.tbJ

Installation step
```bash:g16_install.sh
export g16root=/opt/gaussian
mkdir ${g16root}
cd ${g16root}
tar xvfJ ${g16_bin}.tbJ
sudo usermod -aG users ${myname}
chgrp -R users g16
csh ${g16root}/g16/bsd/install
source ${g16root}/g16/bsd/g16.profile
```
If ${g16root} is not properly set, error of not found g16 will occurs.

Add export g16root=/opt/gaussian to .bashrc can

Known problems:
version C.01 will generate fort.7 in work directory, this is no damage to the running result.
However, to prevent the extra file confusing users, we can add IOp(99/10=0) to prevent generate the extra fort.7 file.

Rerence
https://www.hpc.co.jp/tech-blog/2023/05/29/steps-to-install-best-gaussian16-for-your-computer/
http://bbs.keinsci.com/forum.php?mod=viewthread&tid=34648
【ChatGPT】成人の日。日記をはじめよう。日記の作成を手伝ってくれるPromptです。


　どうも、カーブミラーです。

　成人の日ですね。
　日記をはじめましょう。
　今回は、日記の作成を手伝ってくれるPromptです。

:::note info
本記事は、ChatGPT（Plus版）
で行なっております。
画像はありません。あしからず。
:::
　ChatGPT等の動作状況を知らせる
　　OpenAIのステータスページ。
　　　[OpenAIステータス](https://status.openai.com/)
***
　ではさっそく、【本題】です。

　今回は、
　　日記の作成を
　　　手伝ってくれるPromptです。

　今日は、成人の日。

　成人したんだから
　　日記を書こう、
　　　と誓った方も
　　　　いらっしゃるかと
　　　　　思います。

　でも、
　　イザ、日記帳を開いて
　　　書き出そうと思っても
　　　　筆が進みませんよね。
　　　　　何を書いたらいいのか
　　　　　　わからないんですね。

　　それで、
　　　三日と続かずに
　　　　三日坊主になるのがオチです。

　　せっかく買った日記帳は
　　　最初の数行に
　　　　何かを書いただけに終わる。

　私は、三日坊主でもいいから
　　一行でもいいから
　　　できる限り、続けよう、
　　　　継続することが大切だ、と
　　　　　知人には言っています。

　　しかし、
　　　普段、文章を書かない人には
　　　　それが厳しく、続かないもの。

　そこで今回は、
　　それをアシストしてくれる
　　　Promptを用意しました。

　　アシストとは言っても
　　　一問一答すれば、OK。

　わざわざ日記帳を
　　購入する必要もありません。
　　　（“書く”という行為は有用ですが）

　LINEとかDiscordとかに
　　自分だけの場所を用意して
　　　そこにコピペするだけです。
　　　　エディタでも構いません。
　　　　　好きな場所を選んでください｡
***
　では、Promptです。　
　　入力して、送信すれば、
　　　やり取りが開始されます。
　　　　充分に聞き取れたと判断したら
　　　　　日記を書き出してくれます。
　　　　　　特になければ“ない”でOK。
```Text:日記作成Prompt
ユーザーの日記を作成します。
下記の手順に従ってください。

1. 今日の日付と天気をWebで調べてください。

2. 今日どんなことがあったか聞いてください。1つずつでも大丈夫です。すべてユーザーの思いつくままに会話をしてください。（必要な回数繰り返します）

3. 入力が終わったら、まとめて日記の文面を作成します。日記の文面は、コードブロックに出力してください。

4. 1へと戻る。
```

　ライフログを記録している方は、
　　それを入力すると、
　　　会話せずにふくらませてくれます｡

　　私は一日のライフログを
　　　手入力で記録しています。
　　　　そこには、天気や服装や
　　　　　購入記録や立ち寄ったお店
　　　　　　などなどを。

　　これをそのままコピペすると
　　　一日の行動を日記化してくれます｡
　　　　長くなるので、
　　　　　編集が必要かも😅
***
　日記を手書きすることは、
　　以下のような
　　　メリットがあるそうです。

　　　・思考の整理
　　　・自己分析
　　　・ストレス軽減
　　　・文章力向上
　　　・記憶力向上
　　　・ポジティブ効果

　できれば、
　　日記帳を購入して、
　　　最初のうちは、
　　　　今回のPromptを使って
　　　　　出てきた文言を
　　　　　　書き綴ってみてください。

　　それを
　　　まず一ヶ月継続してください。
　　　　次第に変化を
　　　　　感じることと思います。

　　おそらく、
　　　“書き写すこと”から
　　　　自分なりの書き方で
　　　　　書くようになるでしょう。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
***
　日記と言えば、
　　こんなニュースも。
>スマホに内蔵されたセンサーとAIだけで「自動日記生成」を実現――写真も音声も不要の新技術「AutoLife」で従来のライフログが大幅に進化
[Ledge.aiさんページ](https://ledge.ai/articles/auto_life_journaling_smartphones_ai)

　まぁ、まだまだ開発中らしく
　　サービスとしては
　　　実現されていませんね。
GoogleのOSS Licenses Gradle PluginをKotlin DSL環境に導入する

サードパーティーライセンスを表示するためにGoogleのOSS Licenses Gradle Pluginを導入しようとしたのですが、公式の情報が古くなっていて少し手間取ったので最新（2025/01/13 現在）の環境向けに導入する方法を書いておきます。
　

下記の内容を追加することで
`app/build/generated/third_party_licenses/[debug|release]/res/raw/third_party_licenses`
と
`app/build/generated/third_party_licenses/[debug|release]/res/raw/third_party_license_metadata`
が生成されるようになりました。

```diff_kotlin:‎build.gradle.kts
plugins {
    ...
}

+ buildscript {
+     repositories {
+         google()
+     }
+     dependencies {
+         classpath(libs.oss.licenses.plugin)
+     }
+ }
```

```diff_kotlin:app/build.gradle.kts
plugins {
    ...
+   id("com.google.android.gms.oss-licenses-plugin")
}
...
dependencies {
    ...
+   implementation(libs.play.services.oss.licenses)
}
```

```diff_toml:gradle/libs.versions.toml
[versions]
...
+ ossLicensesPlugin = "0.10.6"
+ playServicesOssLicenses = "17.1.0"

[libraries]
+ oss-licenses-plugin = { module = "com.google.android.gms:oss-licenses-plugin", version.ref = "ossLicensesPlugin" }
+ play-services-oss-licenses = { module = "com.google.android.gms:play-services-oss-licenses", version.ref = "playServicesOssLicenses" }
```
DocumentAIによるOCRの始め方

# はじめに
Google Cloud の AI 系プロダクトに Document AI があります。

この Document AI は、構造化・非構造化されたドキュメントから要素の抽出や分類、分割することができます。

つまり、Google 製の OCR です。

この Document AI を使って、画像からテキストを抽出してみたいと思います。


# プロセッサの作成
Document AI において OCR を行う AI は、プロセッサという単位で管理されます。

我々は、抽出したい画像をプロセッサに向かってアップロードするわけですね。

では、そのプロセッサを作ってみましょう。

## 1. プロセッサギャラリーを表示
Document AI ページを開いて、左メニューから「マイプロセッサ」を選び、上部の「プロセッサギャラリー」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869191/98b9cf60-75f9-39e1-bf4e-ec6887aba71f.png)


## 2. Document OCR を作成する
一般の中から、「Document OCR」の「プロセッサを作成」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869191/1acf57c9-9020-41af-c666-848dbd63e693.png)


## 3. プロセッサを作成
プロセッサ名を入力して、作成ボタンを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869191/93854cce-d15d-64d0-cff0-7a10e1a85cb7.png)


## 4. プロセッサ作成完了
作成完了しましたね。

ここで、後々コードから呼び出すときになるプロセッサの「ID」「リージョン」を控えておいてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869191/5af530e8-4a86-e6ec-decc-2668fd1fff01.png)


# サンプル画像の実行
## 1. サンプル画像の用意
今回は、Google 検索の結果のスクリーンショットで試してみます。

以下画像を適当なローカルに保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869191/e5447f53-88be-b4db-687b-c1e8ad900567.png)


## 2. サンプル実行
先ほどのプロセッサの詳細画面から「テスト ドキュメントのアップロード」からサンプル画像を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869191/92f9c039-10b5-ee43-f816-2c64fed03ce5.png)

## 3. 結果表示
以下のように、各テキストのまとまりと、読み取った文字列が表示されれば成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869191/00dd5023-0a5e-e656-bcc3-d732b2dac8bd.png)


# プログラムから呼ぶ
以下同じ事を、python で再現します。

ADC を使うので、あらかじめ gcloud コマンドでプロジェクトを切り替えておいてください。

```python
import google.auth
from google.api_core.client_options import ClientOptions
from google.cloud import documentai

# 設定
location = "us"
processerId = (ここで上記で控えていたプロジェクトIDを設定)
file_path = (サンプルで設定した画像のファイルパスを設定)
mime = (ファイルのMIMEを設定)
  
# クレデンシャル作成
credential, pid = google.auth.default()
auth_req = google.auth.transport.requests.Request()
credential.refresh(auth_req)

# クライアント作成
opts = ClientOptions(api_endpoint=f"{location}-documentai.googleapis.com", quota_project_id=pid)
client = documentai.DocumentProcessorServiceClient(client_options=opts, credentials=credential)

# OCR リクエスト
with open(file_path, "rb") as image:
  buff = image.read()

raw_document = documentai.RawDocument(content=buff, mime_type=mime)
name = f"projects/{pid}/locations/{location}/processors/{processerId}"
request = documentai.ProcessRequest(name=name, raw_document=raw_document)
response = client.process_document(request)

# OCR レスポンス
text = response.document.text
print(text)
```

抽出されたテキストが、`response.document.text` に格納されています。

サンプルのようにブロックごとの情報も得たいと思います。

レスポンスの後にコードを追加します。
```python
document = response.document
for page in document.pages:
  for block in page.blocks:
    print("---")
    for segment in block.layout.text_anchor.text_segments:
      print(text[segment.start_index:segment.end_index])
```

このように、レスポンス文字列のどの位置がブロックの範囲か？という情報を取得できるので、自前で文字列分解します。

また、ブロック以外にも行やパラグラフ単位等、`page` には各構造単位の情報が格納されているので、分析に必要な単位で取得するのが良いでしょう。
【AWS】エラー「does not exist or is not attachable」や「...Role is not valid.」の原因

# 概要
IAM Roleにポリシーを付与した状態でcloudformationのスタックに適用すると、エラー「`does not exist or is not attachable`」や「`...Role is not valid.`」が発生しました。原因がわかったので紹介します。

# 原因と解決方法

まずは以下でインポートした場合。

```yaml
Resources:
  LambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - sns.amazonaws.com
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: "/"
      RoleName: LambdaRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSNSFullAccess
        - arn:aws:iam::aws:policy/AWSLambdaExecute
        - arn:aws:iam::aws:policy/AWSLambdaVPCAccessExecutionRole
```

上記だと以下のエラーになります。

> Resource handler returned message: "Policy arn:aws:iam::aws:policy/AWSLambdaVPCAccessExecutionRole does not exist or is not attachable.

問題はAWSLambdaVPCAccessExecutionRoleらしい。

ポリシーではなく`service-role`にすると良いのか？

```yaml
Resources:
  LambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - sns.amazonaws.com
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: "/"
      RoleName: LambdaRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSNSFullAccess
        - arn:aws:iam::aws:policy/AWSLambdaExecute
        - arn:aws:iam::aws:service-role/AWSLambdaVPCAccessExecutionRole
```

すると今度は以下のエラー。

> Resource handler returned message: "ARN arn:aws:iam::aws:service-role/AWSLambdaVPCAccessExecutionRole is not valid. 

あれ、`service-role`の前に`policy`つけるのか。

```yaml
Resources:
  LambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - sns.amazonaws.com
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: "/"
      RoleName: LambdaRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSNSFullAccess
        - arn:aws:iam::aws:policy/AWSLambdaExecute
        - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
```

ということで、上記であれば正常に適用することができました。
Vite + ReactプロジェクトをTypeScriptに移行する手順と発生しがちなエラーの解決方法

## はじめに
Viteで作成したReactプロジェクト（JavaScript）をTypeScriptに移行する際、様々なエラーに遭遇することがあります。この記事では、移行手順と実際に遭遇したエラーの解決方法を紹介します。

## 環境
- Node.js
- npm create vite@latestで作成したReactプロジェクト（JavaScript）

## 1. 必要なパッケージのインストール
まず、TypeScriptと型定義ファイルをインストールします：

```bash
npm install -D typescript @types/react @types/react-dom
```

インストール後、正しくインストールされたか確認：
```bash
npm list typescript
npm list @types/react
npm list @types/react-dom
```

## 2. TypeScript設定ファイルの作成

### tsconfig.jsonの作成
```bash
npx tsc --init
```

生成された`tsconfig.json`を以下の内容で上書き：

```json
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}
```

### tsconfig.node.jsonの作成
```json
{
  "compilerOptions": {
    "composite": true,
    "skipLibCheck": true,
    "module": "ESNext",
    "moduleResolution": "bundler",
    "allowSyntheticDefaultImports": true
  },
  "include": ["vite.config.ts"]
}
```

## 3. vite.config.jsの変更
`vite.config.js`を`vite.config.ts`にリネームし、内容を更新：

```typescript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()]
})
```

## 4. main.jsxの修正
`src/main.jsx`を`src/main.tsx`にリネームし、以下のように修正：

```typescript
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'  // 拡張子を.tsxに変更

// rootの存在チェックを追加
const rootElement = document.getElementById('root')

if (!rootElement) {
  throw new Error('Failed to find the root element')
}

const root = createRoot(rootElement)

root.render(
  <StrictMode>
    <App />
  </StrictMode>
)
```

## 遭遇したエラーと解決方法

### エラー1: tsconfig.node.jsonが見つからない
```
ファイル '/path/to/project/tsconfig.node.json' が見つかりません。ts
```
**解決策**: `tsconfig.node.json`ファイルを作成し、上記の設定を追加します。

### エラー2: vite.config.tsが見つからない
```
構成ファイル 'tsconfig.node.json' で入力が見つかりませんでした。指定された 'include' パスは '["vite.config.ts"]' でした。
```
**解決策**: `vite.config.js`を`vite.config.ts`にリネームし、内容を更新します。

### エラー3: rootElementのnullチェックエラー
```
型 'HTMLElement | null' の引数を型 'Container' のパラメーターに割り当てることはできません。
型 'null' を型 'Container' に割り当てることはできません。
```
**解決策**: `document.getElementById('root')`の戻り値に対してnullチェックを追加します。

## 動作確認
すべての設定が完了したら、以下のコマンドで動作確認：

```bash
npx tsc --noEmit
npm run dev
```

## まとめ
TypeScriptへの移行に時間がかかってしまい、記事にしようと思いました。その中で、いくつかのエラーに遭遇することがあります。本記事で紹介した解決方法を参考に、エラーに遭遇しても一つずつ解決していって欲しいです。
jPostalで郵便番号7桁入力時に住所自動入力を反映させる

## この記事の趣旨
jPostalで郵便番号を「7桁」入力した際に住所自動入力を反映させる方法について記載します。

## jPostalの通常の自動入力動作について
通常は、郵便番号先頭3桁以上入力時に該当の住所が存在した場合は、都度判定され補完されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867400/36f504f6-7239-4ae5-542c-cb676b3b0ea5.png)

## jPostalの clickオプションについて
公式ドキュメントには明記されていませんが、jPostal のソースコード内には「click」というキーで要素を指定し、その要素をクリックした際に main() （住所検索）を実行する実装が含まれています。
GitHubリポジトリの [jquery.jpostal.js #L802](https://github.com/ninton/jquery.jpostal.js/blob/master/jquery.jpostal.js#L802) あたりを読むと、下記のような記述があります。
```js:jquery.jpostal.js #L802
if ( typeof this.sc.click !== 'undefined' && this.sc.click !== '' ) {
    $(this.sc.click).on('click.jpostal', function(){
        _this.main();
    });
}
```

これは「this.sc.click（設定オブジェクトの click プロパティ）」が指定されていれば、その要素に対して click.jpostal イベントをバインドし、クリック時に main() を呼ぶ」という仕組みです。


これを利用して、郵便番号7桁入力時に住所自動入力を反映させるようにします。

## 郵便番号7桁入力時に住所自動入力を反映させる実装例

```js
// 郵便番号入力欄
<input type="input" id="postcode" name="postcode">

// 住所反映欄
<input type="text" id="prefecture" name="prefecture" value="">
<input type="text" id="city" name="city" value="">
<input type="text" id="street_building" name="street_building" value="">

// jpostal click動作用のinputタグ
<input type="hidden" id="postcode_search">

// jpostal設定
$('#postcode').jpostal({
    click: '#postcode_search',  // ← これが「clickオプション」
    postcode : [
        '#postcode'
    ],
    address : {
        '#prefecture' : '%3',
        '#city' : '%4',
        '#street_building' : '%5',
    }
});

// 郵便番号入力欄に対するキーイベント
$('[name="postcode"]').on('keyup blur compositionstart compositionend', function (event) {

    // 7桁入力時に、上記で指定した #postcode_search をtrigger('click') する
    if ($(this).val().length === 7) {
        $('#postcode_search').trigger('click');
    } else {
         // 7桁未満であれば住所欄をクリアする
        $('#prefecture').val('');
        $('#city').val('');
        $('#street_building').val('');
    }
});
```

### 仕組み
jPostalに click: '#postcode_search' を指定

これにより、jPostal は「#postcode_search がクリックされると main()（住所検索）を行う」という動きを内部的にセットします。
郵便番号を入力して7桁に達したら #postcode_search 要素を click する

実際にはユーザーがボタンを押すのではなく、コードで $('#postcode_search').trigger('click') しています。
すると jPostal が反応して main() を呼び、住所を補完します。
7桁未満の場合は住所欄をクリア

これにより「7桁でないときは補完しない」仕様を実現。


## まとめ
- jPostal のソースには「click オプション」を扱うコードが存在し、指定したセレクタ要素をクリックすることで main()（住所検索）をトリガーできます。
- 「click オプション」は公式ドキュメントには詳説されていません。
- 「click オプション」を利用し、7桁になったら trigger('click') することで、自動入力のタイミングを自由に制御できます。
Proof of Concept (PoC)とは？

PoC（概念実証）とは、あるアイデアや技術が実現可能であることを小規模で証明するプロセスのことです。これは完成品ではなく、動作や機能性に焦点を当てた試作品のようなものです。

### PoCの主な目的:

- 実現可能性の確認：アイデアが現実的に動作するかを検証。
- 技術的課題の特定：実装時の潜在的な問題を明らかにする。
- 価値の提示：さらなる開発に進むための説得材料を提供。
- ステークホルダーの合意形成：具体的な成果を示し、賛同や資金を確保する。


### PoCの重要性
- リスク軽減：開発前に技術的および運用上の問題を洗い出し。
- コスト効率の向上：非現実的なアイデアへの無駄な投資を防ぐ。
- ステークホルダーの信頼獲得：明確な成果物を提示して意思決定を促す。
- スピーディーな改善：試験的なプロトタイプで早期に問題点を発見・改善。


### 成功するPoCを構築するステップ
1. 目的を明確化する
    何を証明したいのかを明確にします。例えば：
    
    - サーバーが特定の負荷に耐えられるか？
    - 外部APIとの統合が期待通りの性能を発揮するか？
    
2. 範囲を定義する
    PoCは必要最低限の機能に絞ることが重要です。すべての機能を盛り込む必要はありません。

3. 適切なツールや技術を選択する
    プロジェクトの要件に合った技術スタックを選びます。PoCが本開発に進む場合にスケーラブルなツールを選ぶことが理想です。

4. 最小限のプロトタイプを構築する
    シンプルに始めます。例：

    - Webアプリの場合：基本的な1ページの機能。
    - バックエンドの場合：特定のAPIコールのテスト。

5. 成果を測定する
成功基準（KPIやメトリクス）を設定し、結果を評価します。たとえば：

    - レスポンスタイムやエラーレートの測定。
    - ステークホルダーにとって価値があるかを判断。


### PoCの実施時のベストプラクティス
- 時間とコストを管理する 
    PoCは短期間で完了させるべきです。通常、数週間から1ヶ月以内で成果を出すことが望ましいです。

- 失敗を恐れない 
    PoCの目的は技術的な課題を明らかにすることです。失敗は成功への重要なステップと捉えましょう。

- ステークホルダーとの連携 
    進捗を定期的に報告し、フィードバックを得ることでPoCの方向性を調整します。

- 成果をドキュメント化する 
    学んだことや得られたデータをしっかりと記録し、次のフェーズで活用できるようにします。

### PoCの落とし穴と注意点
- スコープの肥大化 
    本来の目的から外れた機能を追加することで、時間とコストが無駄になる可能性があります。

- 成果の曖昧さ 
    何をもって成功とするかが明確でないと、PoCの価値が薄れます。

- 技術選定のミス 
    本番環境に適さないツールや技術を選んでしまうと、再実装が必要になる場合があります。
【備忘録】Windows11でKaliLInuxを使えるようにする

## 概要
VitualBoxにKaliLinuxをインストールしてみます。
備忘録です。さらっといきます
参考
[KaliLinuxを使えるようになるのだ（基礎編）](https://qiita.com/TAKANEKOMACHI/items/428f47999c834656eb64)

## バージョン
Windows11
VirualBox 7.1.4
KaliLinux 2024.4

## VirtualBoxダウンロード

### ダウンロード

公式サイトから、ダウンロードします。↓

[VirtualBox](https://www.virtualbox.org/)

画面右のDownloadボタンを押します。

![スクリーンショット 2025-01-13 085551.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890669/b060253c-d7c4-8c6e-30f1-565f0372ba7b.png)

そして、画面左側**windows hosts**からインストーラーを取得する

![スクリーンショット 2025-01-13 085826.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890669/9651acd7-1dfc-c2ca-3fd1-e05ac50ef228.png)

インストーラを実行してみるとこれが出てきました。

![スクリーンショット 2025-01-13 090435.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890669/b2ea9ca4-45af-06e4-01fa-936a7443e821.png)

互換性の設定を使用してインストールするを選択します。

![スクリーンショット 2025-01-13 090304.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890669/01796dcf-f753-f72d-5f89-0f166edab753.png)

そして、Nextをひたすら押して続行してインストールします。
設定を変えたかったら変えてください。変えないならそのままで。

![スクリーンショット 2025-01-13 092042.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890669/5480b636-3182-b554-bd96-73744553c944.png)

この画面にたどり着けば成功です。


## KaliLinuxをインストール
ここからインストールします
[KaliLinux](https://www.kali.org/get-kali/#kali-platforms)

**Virtual Machines**を選択します。

![スクリーンショット 2025-01-13 092741.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890669/72d0abe7-e5b8-c7f7-8556-6fe1702b8e0d.png)

**VirtualBox**を押してダウンロードします。

![スクリーンショット 2025-01-13 092903.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890669/b0088f54-5a4f-b103-669e-165f74fcf761.png)

めちゃ時間かかります。

ダウンロードした7z形式のZIPファイルを解凍して、この青のアイコンのvboxファイルを実行します。

![スクリーンショット 2025-01-13 104602.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890669/b46e8908-ee14-7d16-3f31-dc8bbd30745c.png)

ここで、起動を押して起動します。

![スクリーンショット 2025-01-13 104812.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890669/a728bd79-cb50-d7d4-e5d3-e936eca0b31f.png)

ユーザー名パスワードを要求されますが、どちらとも**kali**です。
以上でインストール完了です。

## 初期設定
このままでも使えるんですが、使いやすいように変更します。

まずはタイムゾーンをJSTに変更します。
``` 
timedatectl set-timezone Asia/Tokyo
```
キーボードを日本語配列にします
以下のファイルを変更します。
```
vim /etc/default/keyboard
```
このように変更します
```
XKBMODEL="pc105"
XKBLAYOUT="jp"
XKBVARIANT=""
XKBOPTIONS=""
```
いろいろ日本語化します
以下のファイルを変更します。
```
vim /etc/default/locale
```
このように変更します。
```
LANG=ja_JP.UTF-8
```
それで再起動します
```
reboot
```
これでわりと使いやすくなったと思います。
以上です。
Raspberry でモーター制御（TA7291P）

モーターと言うと、ミニ四駆やラジコンを連想してしまいます。
ラジコンを考えますと、前輪はハンドル操作で右や左に向く、かつ、後輪は前や後ろへの推進力を生む…と。この時、前輪については、決められた角度へ向ける必要がありますので、サーボモーターの役割なのだろうと考えます。

https://qiita.com/MasahiroShouya/items/4d4b8b2e1076b4f8d806

では、後輪をどのように制御するかですが、正転逆転の制御が出来れば良いわけです。
これを簡単に実現してくれる電材「TA7291P」を扱ってみたいと思います。


**TA7291P**
後輪の正転逆転の制御に、東芝製のモータードライバを利用します。
さすが国内企業、安くて良い物を作ってますよね。
ただ、実際に配線しますと結構複雑です…。
![20250112.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3878922/b9a01c5d-507a-6996-8c77-b45331cee028.jpeg)
…どこにTA7291Pあるの…？　　状態です。（ブレッドボードに刺さってますよ）
このTA7291P（黒いプレートに足が10本）ですが、片側だけ印字されていて、
![TA7291P.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3878922/3a9b16eb-4672-f567-d121-dd079de68e22.jpeg)
印字された側が見える状態で、左側から、
　　　１．９番ピン（GND）と電池のマイナス
　　　２．モーターの片側へ
　　　３．使いません
　　　４．電池のプラス
　　　５．１３番ピン（GPIO-27）
　　　６．１５番ピン（GPIO-22）
　　　７．２番ピン（GPIO-5V電源）
　　　８．電池のプラス（安全の為1k抵抗を入れてます）
　　　９．使用しません
　　１０．モーターの反対側へ
の順に回路を構築しましょう。


**外部電源の利用**
電池３本なら、4.5ｖなので、Raspberryの5v電源でイケそう…。
この発想は、地味に危険です。理論上は、電源としては使えるはずなのですが、モーターは回転の初動時に、想定以上の電力を要する事から、過電流がraspberryに流れてしまい、Raspberry本体が壊れる可能性を高めます。
その為、外部電源（電池等）の利用が一般的です。

**稼働までの準備**
プログラムを作成しましょう
vi t7291.py

```diff_python:t7291.py
import RPi.GPIO as GPIO
import sys
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(27, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)
GPIO.output(27, GPIO.LOW)            # 初期値：停止
GPIO.output(22, GPIO.LOW)

try:
    while True:
        GPIO.output(27, GPIO.HIGH)   # 正転
        GPIO.output(22, GPIO.LOW)
        time.sleep(2)
        GPIO.output(27, GPIO.LOW)    # 逆転
        GPIO.output(22, GPIO.HIGH)
        time.sleep(2)
        GPIO.output(27, GPIO.LOW)    # 停止
        GPIO.output(22, GPIO.LOW)
        time.sleep(2)
except KeyboardInterrupt:            # CTRL＋Cで終了     
    pass
GPIO.cleanup()
```

プログラムの準備が終わったら、実行してみましょう
python t7291.py
モーターが正常に動作すれば完了です。
お疲れさまでした～


**蛇足**
ラジコンを実際に組み立てる事を想定しますと、操作画面をWEBでRaspberry内に用意して、スマホのデザリングでRaspberryを接続して、スマホからラジコン操作…が、理論上は可能と思います。
子供の工作、もしくは、大人の玩具や自己満足としては、これで十分とおもいますが、レース用に真剣な機能を構築したい場合、どうしても反応速度が遅れるので、少し難しい気がします。そのようなケースには、シングルボードコンピュータより、マイコンを選択すべきなのでしょうね…。
動画 or GIF → GIF圧縮: Google Colabで1MB以内に調整する

# GIF圧縮ガイド: Google ColabとFFmpegで1MB以内に調整する方法

GIFを最適化してファイルサイズを1MB以内に抑えるのは難しい場合があります。このガイドでは、Google ColabとFFmpegを使って効果的にGIFを圧縮する方法を紹介します。動的なスクリプトを使用して、圧縮プロセスを自動化する方法も説明します。

***

## 前提条件

以下の準備が必要です：

1.  **Googleアカウント**: Google Colabを利用するためにサインインが必要です。
2.  **基本的なPython知識**: Pythonやコマンドラインツールに関する基本的な知識があると便利です。
3.  **入力ファイル**: 圧縮したいGIFまたは動画ファイルを準備してください。

***

## ステップ1: Google Colabの設定

1.  [Google Colab](https://colab.research.google.com/)を開きます。
2.  新しいノートブックを作成します。

***

## ステップ2: FFmpegのインストール

以下のコードを実行して、GIFや動画を処理するために必要なFFmpegをインストールします：

```python
!apt-get update
!apt-get install -y ffmpeg
```

これにより、FFmpegがインストールされ、後のステップで使用可能になります。

***

## ステップ3: ファイルをアップロード

以下のコードを使用して、GIFまたは動画ファイルをColab環境にアップロードします：

```python
from google.colab import files

uploaded = files.upload()

# アップロードされたファイル名を取得
input_file = list(uploaded.keys())[0]
print(f"アップロードされたファイル: {input_file}")
```

***

## ステップ4: ファイルサイズの確認

圧縮前にファイルサイズを確認し、どの程度の圧縮が必要かを把握します：

```python
import os

file_size = os.path.getsize(input_file) / (1024 * 1024)  # バイトをMBに変換
print(f"元のファイルサイズ: {file_size:.2f} MB")
```

***

## ステップ5: GIFを動的に圧縮

以下のスクリプトは、現在のGIFサイズを確認し、1MB以内に収まるまで解像度やフレームレートを調整します。

### 動的圧縮スクリプト

```python
import os
from google.colab import files

# 出力ファイル名を定義
output_file = "compressed.gif"

# 初期設定
scale = 320  # 初期解像度幅
fps = 15      # 初期フレームレート

# 圧縮ループ
while True:
    # FFmpegで圧縮
    command = f"ffmpeg -y -i \"{input_file}\" -vf scale={scale}:-1 -r {fps} {output_file}"
    os.system(command)

    # 圧縮後のファイルサイズを確認
    compressed_size = os.path.getsize(output_file) / (1024 * 1024)  # MBに変換
    print(f"圧縮後のファイルサイズ: {compressed_size:.2f} MB")

    if compressed_size <= 1.0:
        print("圧縮成功！ファイルサイズが1MB以下になりました。")
        break

    # パラメータを調整して再試行
    scale -= 20  # 解像度を下げる
    fps -= 1     # フレームレートを下げる

    if scale < 100 or fps < 5:
        print("1MB以下に圧縮できません。品質を保つには限界値です。")
        break

# 圧縮後のファイルをダウンロード
if os.path.exists(output_file) and compressed_size <= 1.0:
    files.download(output_file)
```

### スクリプトの説明

1.  **解像度 (`scale`)**: 初期値320pxで、1MBを超える場合に20pxずつ減少します。
2.  **フレームレート (`fps`)**: 初期値15fpsで、必要に応じて1fpsずつ減少します。
3.  **ファイルサイズ確認**: 各圧縮後にサイズを再計算。
4.  **停止条件**: 解像度が100px未満、またはフレームレートが5fps未満になった場合に停止。

***

## ステップ6: 出力の確認

圧縮後のファイルをダウンロードして、以下を確認してください：

*   ファイルサイズが1MB以内になっているか。
*   視覚的な品質が許容範囲内か。

***

## 圧縮をさらに最適化する方法

*   **動画を短縮**: GIFや動画の必要な部分のみをトリミング。
*   **カラーパレットの使用**: パレットを生成して圧縮を効率化。

例:

```python
# パレットの生成
os.system(f"ffmpeg -y -i \"{input_file}\" -vf palettegen palette.png")

# パレットを使用してGIFを生成
os.system(f"ffmpeg -y -i \"{input_file}\" -i palette.png -lavfi paletteuse -vf scale=200:-1,fps=10 {output_file}")
```

***

## まとめ

このガイドでは、Google ColabとFFmpegを使ったGIFや動画の圧縮方法を紹介しました。解像度やフレームレートを動的に調整することで、品質を維持しながら1MB以内に収めることが可能です。この方法で、より効率的にファイルを圧縮しましょう。
Vite + Vue3 + VuetifyでMaterial Symbolsを使いたい

Vuetifyが公式でMaterialSymbolsに対応しておらず、少し探してみたらYoutubeに対応方法が説明されてました。

実装としてはMaterialSymbolsのアイコンをコンポーネント化し、それをIconSetとしてVuetifyにロードさせる方法でした。

参考にしたYoutube
https://www.youtube.com/watch?v=RNnzwQjDh5E

リポジトリ
https://github.com/yusukeasari/vite_vue3_vuetify_materialsymbols
【node.jsでかんたんDB操作】prismaを本番運用前提で使うなら絶対やっておいたほうが良い3つの事

最近人気のprismaに入門して実際に使ってみた。

## prismaって何？
「そもそもprismaって何」という人もいると思うので軽く説明。

[prisma](https://www.prisma.io/)というのはNode.jsのライブラリの一つで、独自の定義ファイルと汎用関数を使ってDBの定義や操作を行える(同じような機能を持つツールやライブラリをORMと呼ぶそう)
非常に軽量でnpmでインストールしてinitコマンドを叩くだけで導入でき、MySQL・SQLite・Postgreといった大抵のDBをサポートしているのもあって非常に使いやすい。
通常やるようなDBに対してSQLを発行する方法だと返ってくるデータに型定義がされていないため予期せぬエラーが発生しがちだが、prismaの関数で取得したデータはしっかりと型定義がされているため型安全なDB処理が簡単に作れる。
さらに専用のDBブラウザ(prisma studio)も同梱されているため、別途Mysql WorkbenchやpgAdminを使用しなくてもテスト環境で使用データを簡単に参照できる。

基本的な仕様と使い方は[こちら](https://qiita.com/3062_in_zamud/items/52873af4376308076310)

このprisma、本番環境へのデプロイを前提にする際に考えなければいけないことが幾つか存在する。
今回は簡単な設定で解決できる3つのポイントを紹介。

##
### 1. 主キーにインデックスを付ける※超重要！

DBを扱う際の初歩中の初歩だが主キーとなるカラムや検索時のキーに使うカラムには必ずインデックスを付けよう。
これをやらないと検索時の応答速度が大幅に低下する。

```text:schema.prisma
// model(DBに作成するテーブルの定義)
model Post {
  id Int @id @default(autoincrement()) 
  name String
  email String
  created_at DateTime @default(now())
  updated_at DateTime @default(now())
  
   @@index([id]) //インデックスを設定(絶対にやろう！)
}
```

### 2. 本番デプロイ対策としてprisma clientをルート下に作成

modelの定義をprisma client(データ操作を行う関数セット)に反映させるprisma generateはデフォルト設定だとnode_module直下のclientが更新される。
そのままではvercel等の外部ホスティングサービスにデプロイすると更新が適用されない場合があるため、本番リリース後でも正常に動作させるにはclient自体をルートフォルダ直下に作成して参照させる必要がある。

```text:schema.prisma
generator client {
  provider = "prisma-client-js"
  output   = "./src/prisma/client" //outputの設定を追加してprisma clientを外部出力する
}
```

この設定を追加した後、デプロイ時に実行するコマンドに「prisma generate」を加えることでvercel等でも正常にDB処理が動作するようになる。

```json:package.json
//ホスティングサービスへのデプロイ時にこのコマンドを実行するように設定する。
"vercel-build": "prisma generate && prisma migrate deploy && next build"

```

### 3.schema.prismaの分割
prismaにも弱点が一つだけある。migrateやgenerateでDB定義を設定する際に単一のschema.prismaしか参照できない事だ。
アプリで使用するDBのテーブルが1つか2つ程度であればいいが、これが大規模システムになってmodelの数が10個も20個も増えてしまうと単一のファイルに書き連ねていくのはどうしてもソースの可読性に支障が出てしまう。

幸いprisma用にschema用のファイルを結合させて一つのschema.prismaを作成するための「prisma import」というライブラリも提供されているので是非とも導入しよう。

[こちら](https://zenn.dev/pale_delphinium/articles/96397db45866b0)の記事に詳しく書かれている。
【初心者学習記録】CSSで背景画像が表示されない

# はじめに
私は未経験でのエンジニアへの転職を目指して学習しています。
その備忘として記録を残したいと思います。

# 事象
Railsでアプリの開発を行っていたところ、CSSで背景を設定したにも関わらず開発環境で反映されない。

# 試したこと
- CSSの記載場所（coverでないところにする）を変える⇒変わらない
- 同じクラスの文字の色やフォントを変えてみる⇒変わらない
- サーバー、ブラウザの再起動⇒変わらない
- 背景画像の保存場所のパスを直接打ち込んでみる⇒表示されるので場所はあっている
![image (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910071/0f5de123-75e0-2c54-02c1-e71be8be3973.png)
- ブラウザのキャッシュクリア⇒変わらない
- `rails assets:clobber`と`rails assets:precompile`を実行⇒表示された！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910071/cb137f40-a741-2403-815b-e1c3cb4a8d08.png)

# 最後に
このあともCSSの修正が反映されないことが多々ありましたが、最後の２コマンドを実行すれば反映されました。
AlmaLinux 9.4のセットアップ(ConoHa VPS)

ConoHaのVPSでサーバーを構築する。

以下の環境でセットアップしていく。
**〜VPS 1Gプラン〜**
メモリ：1G
CPU：仮想2Core
ストレージ：HDD 100GB
OS：AlmaLinux 9.4

# おことわり
コントロールパネルでのセットアップは省略。
また、SSH Keyをセットした状態でセットアップしてあることを前提とする。
筆者はCentOS 7からAlmaLinux 9へ移行したため、CentOS 7のコマンドで利用できる部分はそれらを用いる。

# 1．サーバーへ接続
次のコマンドを実行し、サーバーへログインする。

```
$ ssh [アカウント名]@[ドメインorアドレス] -i [pemファイルの保存場所]
```

# 2．サーバーのアップデート
次のコマンドを実行し、アップデートする。

```
[root@abc ~]# yum -y update
```

# 3．アカウントの作成とパスワードの設定
次のコマンドを実行し、アカウント作成する。

```
[root@abc ~]# adduser [ユーザー名]
```

次のコマンドを実行し、パスワードを変更する。

```
[root@abc ~]# passwd [ユーザー名]
```

設定したいパスワードを入力する。

```
New password: [パスワード]
```

設定したいパスワードを再度入力する。

```
Retype new password: [パスワード]
```

# 4．SSH Keyファイルのコピー
次のコマンドを実行し、アカウントディレクトリへ移動する。

```
[root@abc ~]# cd /home/[アカウント名]/
```

次のコマンドを実行し、ディレクトリを作成する。

```
[root@abc ~]# mkdir .ssh
```

次のコマンドを実行し、ディレクトリの所有者を変更する。

```
[root@abc ~]# chown [アカウント名]:[アカウント名] .ssh/
```

次のコマンドを実行し、ディレクトリのパーミッションを変更する。

```
[root@abc ~]# chmod 700 .ssh/
```

次のコマンドを実行し、「.ssh」ディレクトリへ移動する。

```
[root@abc ~]# cd .ssh/
```

次のコマンドを実行し、rootアカウントのSSH Keyファイルをコピーする。

```
[root@abc ~]# cp /root/.ssh/authorized_keys .
```

次のコマンドを実行し、SSH Keyファイルの所有者を変更する。

```
[root@abc ~]# chown [アカウント名]:[アカウント名] authorized_keys
```

次のコマンドを実行し、SSH Keyファイルのパーミッションを変更する。

```
[root@abc ~]# chmod 600 authorized_keys 
```

# 5．rootアカウントのログイン無効化
次のコマンドを実行し、設定ファイルを編集する。

```
[root@abc ~]# vim /etc/ssh/sshd_config.d/01-permitrootlogin.conf
```

3行目の末尾"yes"を"no"にして保存する。

``` :/etc/ssh/sshd_config.d/01-permitrootlogin.conf
PermitRootLogin yes
```

↓

``` :/etc/ssh/sshd_config.d/01-permitrootlogin.conf
PermitRootLogin no
```

次のコマンドを実行し、sshdを再起動する。

```
[root@abc ~]# systemctl restart sshd 
```


# 6．SSHの切断時間の変更
次のコマンドを実行し、設定ファイルを編集する。

```
[root@abc ~]# vim /etc/ssh/sshd_config
```

110行目のコメントアウトを解除し、末尾"0"を"60"にする。

``` :/etc/ssh/sshd_config
#ClientAliveInterval 0
```

↓

``` :/etc/ssh/sshd_config
ClientAliveInterval 60
```

111行目のコメントアウトを解除し、末尾"3"を"30"にして保存する。

``` :/etc/ssh/sshd_config
#ClientAliveCountMax 3
```

↓

``` :/etc/ssh/sshd_config
ClientAliveCountMax 30
```

次のコマンドを実行し、sshdを再起動する。

```
[root@abc ~]# systemctl restart sshd
```

# 7．ポート番号の変更とファイアウォールの設定
次のコマンドを実行し、設定ファイルを編集する。

```
[root@abc ~]# vim /etc/ssh/sshd_config
```

21行目のコメントアウトを解除し、末尾"22"を好みの数字にして保存する。

``` :/etc/ssh/sshd_config
#Port 22
```

↓

``` :/etc/ssh/sshd_config
Port [ポート番号]
```

次のコマンドを実行し、ポートを開放する。

```
[root@abc ~]# firewall-cmd --add-port=[ポート番号]/tcp --zone=public --permanent
```

次のコマンドを実行し、ファイアウォールをリロードする。

```
[root@abc ~]# firewall-cmd --reload
```

```
success
```

次のコマンドを実行し、sshdを再起動する。

```
[root@abc ~]# systemctl restart sshd
```

# 8．サーバーの再起動
次のコマンドを実行し、サーバーを再起動する。

```
[root@abc ~]# reboot
```

# 9．動作確認
次のコマンドを実行し、サーバーへログインできることを確認する。

```
[root@abc ~]# ssh [アカウント名]@[ドメインorアドレス] -p [ポート番号] -i [pemファイルの保存場所]
```
windowsでiverilog その179

# 概要　
windowsでiverilogやってみた。
verilog見つけたので、テストベンチ、書いてみた。

# 参考にしたページ

https://qiita.com/GeekMasahiro/items/45c4312c24069641f9c3

# サンプルコード

```
module test;
	reg clk;
	reg rst_n;
	wire led1,
		led2,
		led3;;
	blink u(.clk_in(clk), .n_rst(rst_n), .led1(led1), .led2(led2), .led3(led3));
	initial
	begin
		clk <= 0;
		rst_n <= 1;
	#2
		rst_n <= 0;
	#2
		rst_n <= 1;
	#10000
		$finish;
	end
	always
	#1
		clk <= ~clk;
	initial
	begin
		$dumpfile("test.vcd");
		$dumpvars(0, u);
	end
endmodule

```

# 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/07ce32d3-e3c1-96ee-b3d6-24a69c627999.png)

以上。
暇なので毎日１つリファクタしてみるのも...あり？

# Overview
「暇なときはテストでいい感じにコードをリファクタしてみる」


# Motivation/Context
最近暇なのですが、コードを書いてないとなんかむずむずします。
ということで、何かやることはないかな〜なんて思っていました。
そんな時に、いい暇つぶしを思いついたのでシェアしてみます。


# Get Started!!
今回は、なんとなーく自作しているアプリのcontrollerにあった長ったらしい処理をmodelに移動させて、modelスペックを書いて見ました。
ついでに、最近覚えたてのFactorybotを使って見ました。

### 以降前のcontroller
```ruby
@apply = Apply.new(
  user_id: current_user.id,
  location_id: @location.id,
  date: Date.today,
  time_start: Time.new(2024,1,1,12,0),
  time_end: Time.new(2024,1,1,13,0),
  message: "ああああああ"
)
```

### 以降後のcontroller
```ruby
@apply = Apply.initilize_apply(current_user.id, @location.id)
```

### 移行後に追加したテスト系のファイル
```ruby
describe "#initilize_apply" do
  it "正常に初期化される" do
    user = FactoryBot.create(:user)
    location = FactoryBot.create(:location)
    apply = Apply.initilize_apply(user.id, location.id)
    expect(apply).to be_valid
  end
end
```

```ruby
FactoryBot.define do
  factory :location do
    title { "..." }
    catch_copy { "..." }
  end
end
```

```ruby
FactoryBot.define do
  factory :user do
    sequence(:email) { |n| "test_user_#{n}@example.com" }
    password { Devise::Encryptor.digest(User, 'password') }
    admin { false }
  end
end
```


:::note info
インフォメーション
「初期化処理ならinitializeメソッドあんじゃん！」というツッコミはご遠慮くださいw
次回くらいのリファクタリングでやってみよって思います！
:::
PyWORLDのインストール

# [PyWORLD](https://github.com/JeremyCCHsu/Python-Wrapper-for-World-Vocoder "PyWORLD")

音声分析システムである[WORLD](http://www.isc.meiji.ac.jp/~mmorise/world/introductions.html "WORLD")のPythonラッパー

# インストール(uv)

```
uv add pyworld
```

clang++がない環境だと以下のようなエラーが出る
```
error: command 'clang++' failed: No such file or directory
```

clang++をインストールすれば解決するが，事情によりインストールできない場合はなんらかのC++コンパイラを指定すればOK

```
CXX=g++ uv add pyworld
```
【備忘録】リバースプロキシ配下のwordpressをssl対応させるのに時間かかった話(apache) ※テーマのカスタム真っ白な人は関係あるかもしれません。

## 結論

`/etc/apache2/apache2.conf`に

```
SetEnvIf X-Forwarded-Proto https HTTPS=on
```
を一番下に書くだけ。

## 環境確認

OS:ubuntu24.04
リバースプロキシ:[zoraxy](https://github.com/tobychui/zoraxy)
apache
wordpress

## まず最初に何があったのか
wordpressを使用してたのですが、
mixed contentsという
httpとhttpsのコンテンツが混在する状態になりました。
そのせいでcssやらjsやらがchrome等によるブラウザで危険とされ読み込まれなくなってしまい、色々崩壊することがありました。

## 原因がわかったなら対策対策!

最初はいろんな情報が錯乱しまして、

#### SSL Insecure Content Fixer 

というプラグインで解決しました。
ただそんなの入れなくても普通はどうにかなるので調べたところ、

`/etc/apache2/apache2.conf`に

```
SetEnvIf X-Forwarded-Proto https HTTPS=on
```
を一番下に書くといいという話を見つけました。

参照:https://blog.code4u.org/archives/1550

やってみたら解決した感じです。

## 最後に
この記事で一人でも解決した人が増えたら嬉しいです。

## 参照

https://blog.code4u.org/archives/1550
windowsでiverilog その178

# 概要　
windowsでiverilogやってみた。
2bitCPU、書いてみた。

# cpuの仕様
レジスタマシン
- レジスタ
アキュムレータa-2bit
プログラムカウンタ2bit
キャリー1bit
- メモリー
2bit2アドレス
- 命令2bit
h0--a = a + 1
h1--if (c > 0) pc = 0

# サンプルコード

```

module cpu2(input clk, input rst, output [1:0] outport);
	reg [1:0] a;
	reg c;
	reg [1:0] pc;
	reg [1:0] mem[1:0];
	wire [1:0] code;
	assign code = mem[pc];
	assign op = code[3:2];
	always @(posedge clk, negedge rst)
	begin
		if (!rst)
		begin
			mem[0] <= 4'h0; //a++
			mem[1] <= 4'h1; //if (c > 0) pc = 0
			a <= 2'h0;
			c <= 0;
			pc <= 2'h0;
		end
		else
		begin
			case (op)
			2'h0://a++
			begin
			end
			2'h1://if (c > 0) pc = 0
			begin
				if (c > 0)
					pc = 0;
			end
			endcase
			pc = pc + 1;
		end
	end
	initial
	begin
		$monitor("%d %d %d", a, c, pc);
	end
endmodule

module test;
	reg clk,
		rst;
	wire [1:0] outport;
	cpu2 u(.clk(clk), .rst(rst), .outport(outport));
	initial
	begin
		clk = 0;
		rst = 1;
	#2
		rst = 0;
	#2
		rst = 1;
	#20
		$finish;
	end
	always
	#1
		clk = ~clk;
	initial
	begin
		//$monitor("%d", outport);
	end
endmodule





```

# 実行結果

```
>vvp a.out
x x x
0 0 0
0 0 1
0 0 2
0 0 3
0 0 0
0 0 1
0 0 2
0 0 3
0 0 0
0 0 1
0 0 2
cpu20.v:56: $finish called at 24 (1s)

```

以上。
フォルダを分けて作業する時の備忘録【git clone】

Webアプリで使用しているフレームワークのバージョンアップ作業のため
別フォルダで作業を進める必要がでてきたので、
その際の手順を備忘録として残します。

例：
　普段作業しているフォルダ（hoge_app）とは
　別のフォルダ（hoge_app_sub）に作業環境を用意するケース。

## 結論：
フォルダを別に作成し、
git cloneコマンドを使ってリモートリポジトリをコピーするだけでOK！

## 手順
### ①新しいフォルダの作成
新たに作業用フォルダを作成し、その中に移動します。

``` bash
mkdir hoge_app_sub
cd hoge_app_sub
```

### ②リモートリポジトリをクローンする
リモートリポジトリの中身を現在のフォルダに展開します。
``` bash
git clone git@github.com:組織名/hogehoge_app.git .
```
備考：
　.（ドット）の意味 : 
　 現在のフォルダ（hoge_app_sub）にリポジトリの中身を直接展開します。

:::note info
ドット ( .) を使う理由
通常、git cloneを実行するとリポジトリ名のフォルダが新たに作成され、その中にリポジトリの中身が展開されます。

hoge_app_sub
　└── hogehoge_app/
　　　└── リポジトリの中身


しかし、ドット ( .) を指定すると、以下のように中身のみが直接展開されます。
コードをコピーする

hoge_app_sub
　└── リポジトリの中身

:::

これで、別フォルダで作業を進める準備が整いました。
筆者は今まで別フォルダに分けて作業をする機会がなく、作業環境を用意するのに
戸惑ったので今回備忘録として残しました。

以上。
Amazon Q for Eclipse を使ってみた

# はじめに
AWSの無料枠で何か使えるものが無いか？を探していて、Amazon Qを発見！
前々から興味がありEclipseで使える（プレビュー？）ので良かった点をまとめてみました。
同じように興味があれど、まだ使っていない方の参考になれば幸いです。

# 良かった点
### リファクタリングのアドバイスをくれる
趣味で書いているので、仕事とは異なりレビューアがいませんでした。
選択メソッドのリファクタリングを依頼すると、改善後のソース 及び 理由を提示してくれます。

クラス全体のリファクタリングを依頼すると無料アカウントだから？か、エラーになりましたがメソッド単位の依頼でも十分知見を得られます。

コメントを取り込まなくても、実際のレビューと類似で知見が広がります。

加えて英語で説明してくれるので英語の勉強にもなります。

# その他
### 私が理解して使えた機能
Explain（説明）、Refactor（リファクタリング）、Fix（修理？）、Optimize（解析）、Send To prompt（選択部分をプロンプトに送信）がありました。

それぞれ選択すると、適切な言葉でAmazon Qに依頼してくれます。

Refactor（リファクタリング）を主に使っていますが、Fixも徐々に使っていきたいと思います。

# 参考資料
https://github.com/aws/amazon-q-eclipse
https://aws.amazon.com/jp/q/developer/
https://marketplace.eclipse.org/content/amazon-q
paizaラーニングレベルアップ問題集の「カンマ区切りの3つのデータの入力」をやってみた。

paizaラーニングレベルアップ問題集の[カンマ区切りの3つのデータの入力](https://paiza.jp/works/mondai/stdin/stdin_comma_3)をやってみました。
- - -
###### 問題
https://paiza.jp/works/mondai/stdin/stdin_comma_3
- - -
###### 方針
1行受け取ってカンマ区切りした文字列配列要素を改行区切りで出力します。
(参考)[3つのデータの入力](https://qiita.com/anonymously115/items/3dbfe05f8a2de7e7dd20)

:::note info
本来は
- 文字列を1行受け取ります
- カンマで区切って文字列配列とします
- 文字列配列の各要素について
    - 末尾に改行を付けて出力します

とするべきですが、1文で書いてしまいました。
:::
:::note info
問題文には「$3$つ」とありますが、今回のコードには`3`を使っていません。
:::
- - -
###### C
```c
#include <stdio.h>

int main() {
	char s[101];
	while (scanf("%[^,],", s) == 1) {
		puts(s);
	}
	return 0;
}
```
- - -
###### C++
```cpp
#include <iostream>
using namespace std;

int main() {
	string s;
	getline(cin, s, ',');
	while (cin) {
		cout << s << endl;
		getline(cin, s, ',');
	}
	return 0;
}
```
- - -
###### C#
```cs
using System;

class Program
{
	public static void Main()
	{
		foreach (string s in Console.ReadLine().Split(','))
			Console.WriteLine(s);
	}
}
```
- - -
###### Go
```go
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Scan()
	S := strings.Split(scanner.Text(), ",")
	for _, s := range S {
		fmt.Println(s)
	}
}
```
- - -
###### Java
```java
import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		for (String s : sc.nextLine().split(","))
			System.out.println(s);
		sc.close();
	}
}
```
- - -
###### JavaScript
```js
require("fs").readFileSync("/dev/stdin", "utf8").trim().split(',').forEach(function (s) { console.log(s) });
```
- - -
###### Kotlin
```kotlin
fun main() {
	readLine()!!.split(",").forEach { println(it) }
}
```
- - -
###### PHP
```php
<?php
	foreach (explode(",", trim(fgets(STDIN))) as $s)
		echo "$s\n";
?>
```
- - -
###### Perl
```pl
chomp(my $S = <STDIN>);
foreach my $s (split(",", $S)) {
	print "$s\n";
}
```
- - -
###### Python3
```py
for s in input().split(','):
	print(s)
```
- - -
###### Ruby
```rb
gets.split(',').each do |s|
	puts s
end
```
- - -
###### Scala
```scala
import scala.io.StdIn._

object Main extends App{
	readLine().split(",").foreach(println)
}
```
- - -
###### Swift
```swift
for s in readLine()!.split(separator: ",") {
	print(s)
}
```
スライスでコピーしている人！注意ですよ！

## はじめに
スライス表記を使うとこんな感じでコピーができますよね？
```python
fruit = ['りんご', 'ぶどう', 'みかん']
fruit2 = fruit[:]
```
これ便利なのですが、これでコピーできるんだなーと意味も考えず使うと、よくない結果を招くので、筆者の失敗を交えて注意喚起しようと思います。

## 前提知識
前提知識として、ディープコピーとシャロ―コピーを知ってないと困るので、軽く話しておきます。
### シャローコピー（shallow copy）
シャローコピーは、元のオブジェクトの「参照」をコピーするものです。つまり、コピーされたオブジェクトと元のオブジェクトが同じ`id`を参照するということです。そのため、元のオブジェクトが変更されると、コピーされたオブジェクトにも影響します。その逆も然りです。

ここではわかりやすくするために簡単な数字やアルファベットで説明します。
```python
a = [A, B, C]
b = a[:]    #aをシャロ―コピーしたもの（[A, B, C]ということ）

id(a[0]), id(a[1]), id(a[2])    #1, 2, 3
id(a)    #4
id(b[0]), id(b[1]), id(b[2])    #1, 2, 3
id(b)    #5
```
こういうイメージで`a[0]`も`b[0]`も`A`というオブジェクトを参照しています。なので、`a[0]`から`A`の中身を書き換えると`b[0]`から`A`の中身を取ってくる時にも書き換わったものが得られる、という具合に相互に影響します。


### ディープコピー（deep copy）
ディープコピーは、元のオブジェクトの「値」を完全にコピーするものです。コピーされたオブジェクトは独立した`id`を持つため、元のオブジェクトが変更されても影響を受けませんし、その逆も然りです。

こちらも簡単な数字やアルファベットで説明します。

```python
import copy
a = [A, B, C]
b = copy.deepcopy(a)    #aをディープコピーしたもの（[D, E, F]ということ）

id(a[0]), id(a[1]), id(a[2])    #1, 2, 3
id(a)    #4
id(b[0]), id(b[1]), id(b[2])    #5, 6, 7
id(b)    #8
```
こういうイメージで、`b[0]`は`A`と同じ値を持つ`D`という別のオブジェクトを参照しています。なので、`a[0]`から`A`の中身を書き換えても、`D`の中身は書き変わらないので`b[0]`から`D`の中身を取ってくる時には影響しません。また、その逆も然りです。

## 本題
　筆者の失敗談を話します。筆者が失敗したのはお絵描きツールを作っているときです。`redo`と`undo`機能を作るため、ピクセル情報を二次元リストにして、`redo_stack`と`undo_stack`というリストにそれぞれ格納してました。しかし、格納する時点では正しい情報が、なぜか`redo`、`undo`を実行するときにおかしくなってるんです。これの原因が、**スライス表記でコピーするときは、シャロ―コピーだから**だったんですよね。
 
色を塗った時に現在のピクセル情報が書き換わる
↓ 
それをシャロ―コピーして作られたオブジェクトも全部同期して書き換わる。

こんな具合です。これのせいで`redo`しても`undo`してもなぜか絵が変わらない...保存したときのピクセルデータは正しく格納されてる...とよくわからず時間を取られてしまいました。
　ちゃんと考えれば、二次元リストの情報を格納するときに、シャロ―コピーを使っているのだから、格納した後に中身が同期して書き換わるのは当然のことです。しかし、コピーはめんどいからスライスでやっとけばいいや、という思考停止状態だと、このディープコピーとシャロ―コピーというポイントに全く思い当たらず、本当に原因不明の事態でした。

## 結論
多次元リストをコピーするときは、中身が同期してほしくないなら、ディープコピーを使っているか指さし確認する！

## 最後に
　ここまで読んで下さりありがとうございました。自分では理解しているつもりでも、理解できていないことって、やっぱりどっかでボロが出るんだなと思いました。こう言う文法が間違ってるとかじゃない、エラーが出ない間違いっていうのは、きっかけがないと気づきにくいですよね。今まさに、似たような原因で詰まっている人が、気づくきっかけになれば良いと思います。
Javaで「ラベルのサイズの設定と枠線の表示」の動作を確認してみた。

# 概要

Javaで「ラベルのサイズの設定と枠線の表示」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/tutorial/jlabel/index4.html

# 実装

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

```Sample.java
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.Dimension;

class Sample extends JFrame{
  public static void main(String args[]){
    Sample frame = new Sample("MyTitle");
    frame.setVisible(true);
  }

  Sample(String title){
    setTitle(title);
    setBounds(100, 100, 728, 400);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JLabel label1 = new JLabel("Hello!");
    label1.setOpaque(true);
    label1.setBackground(Color.YELLOW);

    JLabel label2 = new JLabel("Good!");
    label2.setOpaque(true);
    label2.setBackground(Color.GREEN);
    label2.setPreferredSize(new Dimension(100, 100));

    JLabel label3 = new JLabel("Bye!");
    label3.setOpaque(true);
    label3.setBackground(Color.RED);
    label3.setPreferredSize(new Dimension(200, 200));

    JPanel p = new JPanel();
    p.add(label1);
    p.add(label2);
    p.add(label3);

    add(p, BorderLayout.CENTER);
  }
}
```

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

```
$ javac Sample.java 
$ java Sampl
```

実行結果は以下の通りでした。

![Screenshot from 2025-01-13 07-37-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/6609460c-9af0-75a3-76eb-6e568ba6416a.png)

# まとめ

何かの役に立てばと。
RTX1200を使い自宅環境を整備してみた

## 概要
最近職場の近くに引っ越したのですが、個人回線を引けないため無料回線を使うことにしました。しかし、LAN配線方式のためプライベートIPを自由に使えないことが判明したので、RTX1200でNATを使って自由に遊べる環境を作ろうと思います。

## RTX1200とは
RTX1200について軽く紹介します。
- 中小規模向けのVPNルーター
- 事業者向けなので、市販品で行えない設定ができる

詳しくは公式をみてください。
https://network.yamaha.com/products/routers/rtx1200/index

## 現状
現状とやりたいことの図です。
RTX1200のLAN1を自分で使える環境にして、LAN2にマンションからきているケーブルを挿します。

![スクリーンショット 2025-01-11 142621.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882356/c68cfa55-d2e8-271b-61d7-e93842897614.png)

色々調べてみた結果
- マンションのルーターは、192.168.0.0/24になってるぽい
- NATを使って10.0.0.0/24で遊べる空間を作りたい

## 手順
**CUIですべて行おうとしたのですが、うまいことできなかったのでGUIと組み合わせて設定していきます。**

1.RTX1200のGUIに入る
　デフォルトだと192.168.100.1になっているかと思います。
2.管理者向けトップページに入る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882356/557b199e-ef7a-fb9d-2639-dd374e510148.png)

3.ウィザードをクリックする
下記画面になるかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882356/10170923-d798-3866-4663-ad173c07d63a.png)
- 時刻設定を行わない→設定の確定
- 管理者パスワードを設定する

4.LANの設定
![スクリーンショット 2025-01-11 145812.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882356/4d87b513-af01-9d0f-e078-cd77518afa6b.png)

デフォルトだと、192.168.100.1になっているので変更する
![スクリーンショット 2025-01-11 145902.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882356/95244579-4305-1fd5-e31b-42983cc94730.png)

5.DHCPサーバーの設定
ここは特に変更せず次へ進む
![スクリーンショット 2025-01-11 145925.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882356/5b580166-b80a-5d84-161a-510765b24275.png)

- 確認画面が表示されるので、問題なければ適用する
- 先ほど設定した10.0.0.1にGUIが変わっているので、アクセスする

6.アクセス管理でSSHの設定をする
![スクリーンショット 2025-01-11 150128.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882356/a3b791b2-692c-3960-c36d-0b3df6d552e1.png)

念のためLAN1ポートのみにしておきます。
![スクリーンショット 2025-01-11 150143.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882356/54f864e2-4871-5142-d271-8c3a799789b6.png)

7.ログインユーザーを作成する
![スクリーンショット 2025-01-11 150314.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882356/65e6c20b-cf75-a676-4f0a-95733b114723.png)

8.puttyを使ってSSH接続する
文字化けするので、リモートの文字セットをShijt_JISにする。
管理者権限に切り替える。
```
administrator
```
管理者パスワードを入力する
今回はLAN2にマンションからのLANケーブルをさしているので、DHCPでIPを受け取るようにする
```
ip lan2 address dhcp
```

NATタイプの指定をする
1:多で変換するのでmasqueradeにする
```
nat descriptor type 1 masquerade
```
変換後のIPアドレスを指定する
lan2で振られているアドレスにしたいので、下記コマンドを打つ
```
nat descriptor address outer 1 primary
```

lanへの適用をする
```
ip lan2 nat descriptor 1
```

設定を保存する
```
save
```

## まとめ
とりあえずこれで、10.0.0.0/24は好きに使えるかなと思います。
最初行った際、最後のsaveを忘れており設定飛ばしてしまいました(´ω｀)

日頃クラウドばかり触っているのですが、オンプレがここまで難儀なものだとは思いませんでした!
いつもは、AWSのコンソール上で行っているので時代の進歩というか変化を感じましたね。(GUIに慣れてしまっているので、CUIだとぱっと見で分かりにくかったです。)
オンプレとはどんなもんなんだろと興味本位で触ってみたのですが、これはこれで面白そうですね。

今度は余っているPCにproxmoxをインストールしてみます。