OmniAICreator/Qiita-1.07M huggingface dataset:
OKEでコントロールプレーンの各コンポーネントのログを取得

OCI Kubernetes Engine (OKE)では、OCI Logging のサービス・ログを設定することで、以下コントロールプレーンの各コンポーネントのログを取得できます。

| ログ・カテゴリ | 概要 |
| :--- | :--- |
| All log sources | すべてのログソースを含むログカテゴリ |
| kube-apiserver | Kubernetes API サーバのログ |
| cloud-controller-manager | Kubernetes のクラウドコントローラーマネージャーのログ |
| kube-controller-manager | Kubernetes のコントローラーマネージャーのログ |
| kube-scheduler | Kubernetes のスケジューラーのログ|

表-01 ログ・カテゴリ

「All log sources」を取得する設定方法を見て行きましょう。

メニューから、「監視および管理」-「ログ」を選択します。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/a1927cad-51f2-0652-800e-2d7ee170e79b.png)

「サービス・ログの有効化」ボタンをクリックします。

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/031c4cce-07ce-8263-df53-d82e0660a431.png)

以下の設定を行います。表-01で示した各コントロールプレーンのコンポーネントまたは全てのログをログ・カテゴリで選択できます。

| 設定項目 | 設定値 |
| :--- | :--- |
| サービス | Container Engine for Kubernetes |
| リソース | 対象となるOKEクラスタ、ここでは cluster 1 を設定 |
| ログ・カテゴリ | コントロールプレーンのコンポーネント、ここでは All log sources を設定 |

表-02 設定内容

最後に、「ログの有効化」ボタンをクリックします。

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/daa80877-7a9b-9ef7-c03a-6a9f343d2cbf.png)

しばらくすると、アクティブになり利用可能となります。

![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/b8120169-44c5-447c-d58a-968d2bfb7b29.png)

試しに、cloud-controller-manager のログを出力させるために、「type: LoadBalancer」の Service object を削除して再作成してみます。

Service object を削除
```sh
kubectl get services
NAME             TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)             AGE
backend-app      ClusterIP      10.96.77.1     <none>           8081/TCP            11d
datasource-app   ClusterIP      10.96.190.41   <none>           8080/TCP            11d
frontend-app     LoadBalancer   10.96.210.77   xxx.xxx.xx.xxx   80:31423/TCP        11d
kubernetes       ClusterIP      10.96.0.1      <none>           443/TCP,12250/TCP   11d
```
```sh
kubectl delete service/frontend-app
service "frontend-app" deleted
```
Service object を再作成
```sh
kubectl apply -f . 
・
・
・
service/frontend-app created
```

ログが出力されると一覧表示されます。

![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/c88baa58-f3ef-b989-54bf-f836c0c49d6e.png)

Service object が削除された場合のログ

![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/31b6490f-515f-509e-55ab-c2518011e434.png)

Service object が作成された場合のログ

![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/ff9b68d6-f0dc-0eea-35d4-be0dcacf959e.png)

「type: LoadBalancer」の Service object、つまり、ロードバランサを OKE クラスタ上で削除および作成する場合、cloud-controller-manager と連携が必要となりますが、その動き含めてログで可視化できることが分かります。

OKE クラスタ作成後、サービス・ログの設定をするだけでコントロールプレーンの各コンポーネントログを取得できるのはとても便利です。
Multilingual E5 Embedding を HTTP Server化して利用する (Multilingual E5 Embedding Server : REST API)


### Multilingual E5 Embeddingとは？

Multilingual E5 Embeddingは、Hugging Faceで提供されている94言語対応の大規模言語モデルです。このモデルは、以下の特徴を持っています：

- **基盤モデル**: XLM-RoBERTaを基に構築。
- **トレーニングデータ**: 多様な多言語データセットを使用。
- **適用分野**: テキスト検索や意味的類似性の評価など。
- **互換性**: PyTorchで実装され、Sentence Transformersと互換性があります。

高い精度と柔軟性を兼ね備えたこのモデルは、テキスト検索や文書間の類似性計算など、幅広いタスクでその性能を発揮します。詳細は[Hugging Faceの公式ページ](https://huggingface.co/intfloat/multilingual-e5-large)をご覧ください。

---

## nlp4j-llm-embeddings-e5 のメリット

- Embedding 処理を別コンポーネントに切り出して分散化することができます
- システムの中で複数のコンポーネントでEmbeddingを利用したいときに、リソースを集中することができます (例: 複数のコンポーネントから呼び出し、GPUを用いて高速に Embedding処理を行う)
- REST APIを利用できるようになることで、プログラムランタイムに依存しなくなります (Java, VBなどからも利用可能)


## nlp4j-llm-embeddings-e5 – 実践的な活用法

`nlp4j-llm-embeddings-e5`リポジトリでは、この埋め込みモデルを活用した簡単なサーバーの構築方法を提供しています。以下にインストール方法と使い方を説明します。

### インストール手順

1. リポジトリをクローン:
   ```sh
   git clone https://github.com/oyahiroki/nlp4j-llm-embeddings-e5.git
   ```
2. ディレクトリを移動:
   ```sh
   cd nlp4j-llm-embeddings-e5
   ```
3. 必要な依存ライブラリをインストール:
   ```sh
   pip install -r requirements.txt
   ```

ソースコードは以下のレポジトリで公開しています。

https://github.com/oyahiroki/nlp4j-llm-embeddings-e5



### サーバーの起動

以下のコマンドでサーバーを起動します：
```sh
python3 nlp4j-embedding-server-e5.py
```

サーバーが起動すると、HTTPリクエストを介して埋め込み生成が可能になります。

### Webブラウザで簡単に試す (2025-2-28更新)

単純に localhost:8888 を開くとテスト用画面になるようにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110265/416c080b-5921-4e43-a3ed-1a5c004659f5.png)

Embedding, Semantic Search, Cosine Similarity を試せます。

### REST APIの利用方法

#### GETリクエスト (URLエンコードなし)
```bash
curl http://127.0.0.1:8888/?text=これはテストです。
```

#### GETリクエスト (URLエンコードあり)
```bash
curl http://127.0.0.1:8888/?text=%E3%81%93%E3%82%8C%E3%81%AF%E3%83%86%E3%82%B9%E3%83%88%E3%81%A7%E3%81%99%E3%80%82
```

#### POSTリクエスト (JSON形式のリクエストボディ)
```bash
curl -X POST -H "Content-Type: application/json" -d '{"text":"これはテストです。"}' http://127.0.0.1:8888/
```

### サンプルレスポンス

リクエストを送信すると、以下のようなJSONレスポンスが返されます：
```json
{
  "message": "ok",
  "time": "2024-05-26T23:21:38",
  "text": "これはテストです。",
  "embeddings": [0.04231283441185951, -0.0035561583936214447, ... 0.022928446531295776]
}
```

このレスポンスには、入力テキスト、生成された埋め込み、リクエスト処理時間などが含まれます。

---

## パフォーマンスとスケーラビリティ

### サーバーのリソース使用状況
以下のコマンドでプロセスやGPUメモリ使用量を確認できます：
```bash
$ ps aux | grep python
$ nvidia-smi
```

---

## 結論

Multilingual E5 Embeddingは、簡単なAPIインターフェースを介して高度な多言語テキスト処理を実現する強力なツールです。その高い柔軟性とスケーラビリティにより、研究から実用的なアプリケーションまで幅広く活用できます。

ぜひ、このモデルを活用して多言語対応の自然言語処理プロジェクトを強化してください！

---

以上、ChatGPT も利用して作成しました。
Vue3 - ref / reactive / watch

# REF
* 可綁定 object
* 可綁定基本型別
* 取值需要 .value

# REACTIVE
* 可綁定 object
* 不可綁定基本型別
* 取值不需要 .value

# REF
https://stackoverflow.com/questions/61452458/

https://medium.com/i-am-mike/vue-3-ref-%E8%B7%9F-reactive-%E6%88%91%E8%A9%B2%E6%80%8E%E9%BA%BC%E9%81%B8-2fb6b6735a3c

https://hackmd.io/@SkT7-27LSWWQi5G2DJBLkw/rJAc7cm1j
ファイル名取得(昇順).vbs

```vba:ファイル名取得(昇順)

' エクスプローラーで選択したファイル（複数可）をこのアイコンにDrag&Dropすると、
' ファイル名（またはパス）をソートしてクリップボードにコピーする。
' SendToフォルダにこのファイルを置くと、選択したファイルの右クリックメニューの
' ［送る］でパスを取得できる。
' エクスプローラーのアドレスバーにshell:sendtoを入力すると飛べる。
' ※ 一度に選択できるファイル数の上限：パスの総文字数が32,699未満（Windows7、10の場合）

Option Explicit

Dim args              '// 選択したファイルパスの配列
Dim folderPath        '// フォルダのパス
Dim i                 '// 配列のループカウンタ
Dim fileNames         '// ソート前のフルパスリスト
Dim fileNamesArray    '// ソートされたフルパスの配列
Dim sortFileNames     '// ソートされたフルパスリスト
Dim msg               '// パスかファイル名かの選択メッセージ

Set args = WScript.Arguments

'// D&Dした複数ファイルのフルパスを改行で繋いだリスト（文字列）にする
folderPath = CreateObject("Scripting.FileSystemObject").GetParentFolderName(args(0)) & "\"

For i = 0 to args.Count - 2
    fileNames = fileNames & args(i) & vbcrlf
next

fileNames = fileNames & args(i) '// 末尾に改行を入れないようにするため、最後はループから外す

Set args = Nothing

'// フルパスを配列にしてソートする（フルパスは2次元目に格納されている）
fileNamesArray = SortRecordset(Split(fileNames, vbcrlf))

'// ソートされた配列を改行で繋いだリスト（文字列）にする
For i = 0 to UBound(fileNamesArray, 2)
    sortFileNames = sortFileNames & fileNamesArray(0, i) & vbcrlf
next

'msg = "フォルダのパスも含めますか？" & vbcrlf & vbcrlf
'msg = msg & "［はい］フルパス" & vbcrlf & "［いいえ］ファイル名のみ"

'If Msgbox(msg, vbYesNo) = vbNo Then
    sortFileNames = Replace(sortFileNames, folderPath, "")
'End If

CreateObject("WScript.Shell").Exec("clip").StdIn.Write(sortFileNames)   '// クリップボードにコピー
WScript.Echo "以下のファイル名リストをコピーしました。" & vbcrlf & vbcrlf & sortFileNames


'// ソート関数
Function SortRecordset(arry)
    Dim i
    With CreateObject("ADODB.Recordset")
        .Fields.Append "Field1", 200, 2047      '// 引数は、順にカラム名、型、文字バイト数
        .Open

        '// データをレコードセットに追加していく
        For i = 0 To UBound(arry)
            .AddNew
            .Fields("Field1").Value = arry(i)
        Next

        .Sort = "Field1 ASC"        '// ASC(昇順)／DESC(降順) ※省略した場合は昇順
        SortRecordset = .GetRows    '// GetRowsは2次元配列を返すので要注意
        .Close
    End With
End Function

```
OMC237B(1367)

https://onlinemathcontest.com/contests/omc237/tasks/11468

剰余の定理の解き方を練習したので、類似の問題を続けて投稿します。

https://qiita.com/msykkb/items/3e383ab63d0968aa4b78

まず、$(1,3),(2,5),(3,7)$の関係性から、
　$y=2x+1$ $…①$
が思い浮かびます。
OMCB012D問題では$f(x)=g(x)(x-1)(x-2)(x-3)(x-4)+C$と定数でしたが、この$C$の部分を変数(つまり$①$)にします。すると、
　$f(x)=g(x)(x-1)(x-2)(x-3)+(2x+1)$ $…②$
になります。
また、$x=4$を$②$に代入すると、
　$f(4)=6g(4)+9$
になり、$f(4)=567$であるので、
　$6g(4)+9=567$
　$g(4)=93$ $…③$
$③$より、$g(x)$を剰余の定理を使って表すと、
　$g(x)=h(x)(x-4)+93$ $…④$
になります。
$④$を$②$に代入すると、
　$f(x)=\lbrace h(x)(x-4)+93\rbrace(x-1)(x-2)(x-3)+(2x+1)$
　$=h(x)(x-1)(x-2)(x-3)(x-4)+93(x-1)(x-2)(x-3)+2x+1$ $…⑤$
になります。
$⑤$に$x=10$を代入すると、
　$f(10)=h(10)×3024+46893$ $…⑥$
になります。

$h(10)$が負の整数でも問題の制約は満たすので、$⑥$が負と正の境界になる$h(10)$を探してそこから$5$番目に小さい$f(10)$を求めます。
まず、$46893÷3024≒15.5$なので、
以下のように、$h(10)$が$-16$と$-15$の間で負から正になります。
　$f(10)=-16×3024+46893=-1491$
　$f(10)=-15×3024+46893=1533$
したがって、正整数の最小の$f(10)$は$h(10)=-15$の場合です。
$5$番目は、$h(10)=-11$のときなので、
　$f(10)=-11×3024+46893=13629$
が解になります。
IDMC:Boxコネクタでファイルをダウンロードします

<h1> 初めに

Informaticaはデータマネジメントクラウドを提供しています。その中で、重要な要素の1つとして、データ連携（Cloud Data Integration、略してCDI）があらゆるデータにアクセスし、連携することが可能です。
本日ご紹介したのはBOXコネクタを使ってファイル連携する方法です。

<h1>シナリオ

BOXコネクタは下記のファイル操作が可能です。
・ファイルをアップロード
・ファイルをダウンロード
・ファイルを削除

BOXコネクタでファイル連携したい場合、CDIでそのままファイルデータの中身を読めるのはCSVファイルのみです。他のファイルを連携したい場合、先ずファイルをダウンロードして、その後ファイルコネクタでダウンロードされたファイルを転送します。２段階処理となりますが、ファイルリスナーを活用して、ファイルのダウンロードフォルダーを監視することで、ファイルの自動転送を実現できます。

<h1>ファイルをダウンロード

<h4>事前準備：

・BOX接続を作成します。ファイルのダウンロード元のBOXに繋ぐ必要があります。ファイルのダウンロード場所を指定する場合、Target File PathにSecureAgentサーバのディレクトリを設定してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986164/1d98cb8f-5b1a-a9c7-839b-19a093b9842a.png)

・CSVファイルを新規作成します。その中にBOXのファイルIDやフォルダーIDを指定します。ファイルIDを指定する場合、特定のファイルをダウンロードすることになって、フォルダーIDを指定する場合、全フォルダーをダウンロードすることになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986164/e9edd55e-a5de-b534-f25c-db78c799ec26.png)
・フラットファイルの接続を作成し、先作成したCSVファイルを接続先のフォルダーに入れておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986164/83ab606a-8669-364b-fa58-641ec15b2afd.png)

<h4>マッピングを作る

BOXのファイルをダウンロードするため、マッピングを作成します。
ソースの設定に、事前に作成したcsvファイルを繋ぎます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986164/87bf8dc9-252e-64ff-e5fa-e441b77e0c74.png)

ターゲットの設定に、事前作成したBOX接続を選んで、Objectの設定は３種類があり、Upload/Download/Delete、今回はDownloadを選択します。そのご、成功ファイルとエラーの保存パスをそれぞれ指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986164/e9e3cd14-82b6-cb7b-9f06-f21971779c63.png)

上記の設定で、ソースから取得したファイルやフォルダーIDを持って、ターゲットにBOX API経由で該当ファイルやフォルダーをダウンロードする動作を実現できます。

<h4>後続アクション

ファイルのダウンロード場所に対して、ファイルリスナーを立てれば、ファイルの到着を自動検知でき、CDIジョブをトリガーしてファイルの自動転送を実現可能です。

ファイルリスナーの使い方はこちらのドキュメントをご参照ください。英語になりますが、今後日本語版の運用編を作りたいと思います。楽しみしましょう。
<https://docs.informatica.com/integration-cloud/data-integration/current-version/components/file-listeners.html>

<h1>まとめ

BOXコネクタでファイルをアップロード、ダウンロード、削除することができます。CDIは半構造化または構造化データしか処理できないですが、動画ファイル、画像ファイルなどの非構造化ファイルを連携したい場合、先ずSecureAgentサーバにダウンロードして、その後CDIR（Cloud Data Ingestion and Replication）サービスを使って転送します。CDIRもファイルリスナーをサポートしますので、便利でご利用いただけます。

BOX連携を早速やってみましょうか！
新卒インフラエンジニアが半年働いた結果を振り返る

# はじめに
今回の1人アドベントカレンダーではインフラをテーマに書いてきました。
新卒でインフラエンジニアとして働き始めて約半年、この期間にインプットしてきた知識や経験をアウトプットする良い機会となりました。
最後の締めくくりとして半年ほどインフラエンジニアとして勤務した現時点で、自分の仕事について思うことを書きたいと思います。

# インフラエンジニアとは
## そもそもインフラとは
「インフラ」とはインフラストラクチャー（Infrastructure）の略で、私たちの生活やビジネスを支える基盤技術を指します。
IT分野では、システムやインターネットの利用に必要不可欠なサーバーやネットワークがこれに当たります。

## インフラエンジニアとは
インフラエンジニアは、これらの技術基盤の設計・構築・運用・保守を担う技術者です。
サーバー、ネットワーク、セキュリティなど、担当する技術領域によって専門性が分かれることもあります。

# インフラエンジニアをやってみて
まずはじめに自分の現在の主な業務内容をここに提示してから、インフラエンジニアをやってみて思ったことを書いてきたいと思います。
自分は普段以下のような業務を主に担当しています。

- 現状プロダクトの運用保守のサポート
- 社内環境の標準化推進
- 開発者の生産性向上のためのツール開発

## インフラエンジニアのここが難しいな
### ググるがあまり通用しない
自分は入社前Webアプリ等の開発経験がありました。この時は実装方法に困ったときはググったりして調べたりすれば、その内容から必要な情報をピックアップして比較的困らずに実装できたものです。
これがインフラだと現存プロダクトの仕様、社内の環境、セキュリティ問題等で自社に当てはまる最適解は自分自身で見つけなければなりません。直接的な実装方法もアプリのコードよりは情報が少なく手探りで行うことも多い気がしています。

### 知っていなければいけない範囲が広い
インフラ領域だけでなくアプリケーション、ドメイン知識、セキュリティと割と幅広い知識が求められてキャッチアップし切れるのはもう年単位なんじゃないかと思うくらい知らないことが多いです。それなりに能動的に勉強していかないとおいてかれるんだろうなという意識は常に付き纏っています。

### 目立ちはしない
これはインフラの仕事がしょぼいとかの話ではなく、表向き見えるものを作るわけではないことが起因していると思います。
例えば、「リリースしました！」といったように、対外的にすぐやったことが知られて目立つような仕事は少ないと思っています。そういうものにモチベがある人はあんまり向かない仕事かなと思いました。

## インフラエンジニアのここ意外と楽しい点
### 意外と単純作業だけではない
インフラエンジニアのイメージとして自分は運用・保守のイメージが強くありました。
運用・保守と聞くと、デバッグだったり日々同じトイル作業をひたすらに繰り返しそうな気がしていたのですが、どちらかというとそれをいかになくすかとかより良い環境を作るためにと頭を使う仕事が多かったです。
コードをガンガン書くという感じではないですが、暇になることはありません。
変にリリースが決まっているとかで締め切りに追われて妥協するみたいなことはないので、その点満足がいくものを突き詰められるところが個人的には好きでした。(環境によるかもしれません)

### 視野が広くなる
今まで自分はアプリの開発だけしかしておらず、インフラ面でどのようなことが行われているかをあまり気にしませんでした。
これは個人単位では問題ないですが、実際の会社だと複数のプロダクトを運用する場合、プロダクト間の疎通、ログの配送等の時にきっと苦労していたと思います。
アプリケーション、ネットワーク、サーバー、セキュリティ、クラウド技術等全体を見るという癖ができたのは良かったなと思っています。

### 強い人が多い
一概には言えないですが、比較的社内でもベテランだったり、色々な会社で経験を積んだ強い人が多いです。最初の段階で上を見上げられる環境で成長できるのは恵まれているなと思いました。

### 顔が広くなる
社内での連絡で色々なプロダクトの人と関わるので、単純に知っている人が増えます。
するとその後のコミュニケーションが取りやすくなったり、伝手で情報を得られたりと会社での生きやすさを感じることが多かったです。

# 終わりに
個人的には新卒という未経験の免罪符を引っ提げてインフラをやって良かったと思います。

アプリケーション開発が特定分野で深い専門性を得られるとすれば、インフラエンジニアとしての経験は技術全般に渡る幅広い知見が得られる点が特徴的だと思います。アプリケーション系の仕事だと特定の開発に特化した経験値が + 50くらい増えるとするならばインフラ系の仕事は全ての経験値に + 10追加されるイメージで日々成長できます。

今年は比較的初心者向けに自分の勉強したことをまとめる記事が多かったですが、来年にはもっと高度な知識の記事を書けるようになれたらいいなと願いを込めて、カレンダーを締めさせていただきます。今年もお疲れ様でした。
聞いて・しゃべって・納得！理由を大事にする勉強会

## はじめに
こんにちは、GxPのあさかです。
この記事は[グロースエクスパートナーズAdvent Calendar 2024](https://qiita.com/advent-calendar/2024/gxp)の23日目の記事です。

GxP社内では様々な有志による勉強会が開催されており、[2日目の記事](https://qiita.com/asaka271/items/a017cba88b84c3b1cd3e)でも紹介した通り、僕は約5年くらい競技プログラミングをやっているので、その経験を活かして今現在社内でアルゴリズム・数学勉強会を開催しています。

その勉強会でやってることや心がけていることを少しだけ紹介したいと思います。

## やってること
週に1回、米田 優峻 (著)[問題解決のための「アルゴリズム×数学」が基礎からしっかり身につく本](https://www.amazon.co.jp/%E5%95%8F%E9%A1%8C%E8%A7%A3%E6%B1%BA%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E3%80%8C%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%C3%97%E6%95%B0%E5%AD%A6%E3%80%8D%E3%81%8C%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%81%97%E3%81%A3%E3%81%8B%E3%82%8A%E8%BA%AB%E3%81%AB%E3%81%A4%E3%81%8F%E6%9C%AC-%E7%B1%B3%E7%94%B0-%E5%84%AA%E5%B3%BB/dp/4297125218)をベースに、僕自身が内容を説明し、参加者がそれを聞くという学校の授業スタイルで進めています。
数学・アルゴリズムを座学で理解するパートと、学習した内容を演習問題として実装するパートがあり、プログラミングの問題はPythonを使って解いています。

僕は義務教育～高校卒業レベルのベーシックな数学は一通り理解していて、大学でも理論的なことについては学んだので、毎回特に予習をすることなく勉強会に臨んでいますが、時々鋭い質問が飛んできて驚かされることもしばしばあります。
詰まりそう・理解が難しそうなところは「ここでわからなくてつまづいた」「こうやって考えたら理解できた」という自分の経験もフルに活かして丁寧に説明することを意識しています。

## 心がけていること

### 全員に参加してもらう
こういう「ひとりがしゃべって他の参加者は聞くだけ」スタイルの勉強会・授業にありがちだと思うんですが、しゃべってる人以外は注意散漫になってしまうことです。せっかく時間を割いて参加してもらっているのに、内職していたらお互いの時間がもったいないと思うんですよね。

そこで、全員に発言するチャンスが回ってくるように、参加者に発言を求めるようにしています。
例えば、最初の式変形は僕が説明して「じゃあ同じように式変形するとどうなる？〇〇くん教えて」みたいな感じで、簡単な内容でもすべて僕が答えを埋めずに発言を促すようにしています。
リアルタイムで参加者の理解度を聞くことで、今の内容をもう少し丁寧に説明したほうがいいのか、しっかり理解できているのかも把握することができます。

### 「なぜ？」を大切にする/理由を言語化してもらう
数学というのは、理由無くして突然答えが降ってくるということは絶対にないです。
上で紹介したように、参加者には勉強会内で発言をしてもらうようにしていますが、「答えを言うだけで終わらせない」ということを意識しています。例えば以下のような感じです。
> あさか：「10種類のアイスの中から3つのフレーバーを選ぶ組み合わせ」を計算をしてください
> 参加者：10C3？
> あさか：なんでそう思った？

この場合、答えは10C3(120通り)で正解です。ただ、正解だったとしても(もちろん不正解のときも)「なんでそれが答えだと思いましたか？」ということを、簡単な問いかけ以外は必ず聞くようにしています。直近で扱ってた式を勘で言って当たるパターンもあれば、正しく理由を説明できるパターンもありますが、誘導しつつ必ず参加者の口で正しい答えとその理由を説明してもらうようにしています。

これは数学ガールの著者として知られている結城浩先生の考えからきています。よければこちらも併せてお読みください。

https://mm.hyuki.net/n/nae6e0041a746

また、昨今AIが進化して、結構ハイレベルなコーディングも提案してくれるようになりました。その一方で、エンジニアが担保すべきなのはプロダクトの質です。「なんかAIが提案してくれたの書いたら動いたけど、どういう内容なのかよくわかりません」ということでは困ります。「わからなければ自分で裏取りをして、正しく動く理由を説明できるようにする」という習慣をつけてもらえればな、という思いも少しだけあります。

### メモを取るのに一生懸命にならないようにしてもらう
こういう授業みたいなものに限らず、LTとかもそうですが、大事なことって資料には書いてないんですよね。
本質は頭に刻んで、あとから本や資料を見れば「そういやあのときこんなこと言ってたなー」となるような状態がベストだと考えています。「これは大事だから何回も言うからね」とか「あとで本見ればいいよ」というようなことを何度か言った覚えがあります。

### 硬い雰囲気にならないようにする
有志の勉強会なので成績を付けるわけでもなく、当然人事評価や昇進なんかも関係ありません。静かにやるよりワイワイやってた方が楽しいし、つまらないよりも楽しい方が参加していて嬉しいと思います。数学の授業ってどちらかというと難しいな、つまらないな、というイメージを持ってる人が多いんじゃないかと勝手に思っていますが、できればそういうイメージを払拭してもらえるようにやっています。

また、勉強会での交流を通して、勉強会以外の場面でもコミュニケーションを取れたらそれはとても嬉しいことです。

## おわりに
僕が参加している勉強会の話をしていきました。
勉強会に参加している方・主催している方が少しでも参考になれば嬉しいです。

話の終着点がよくわからなくなってしまったのでこの辺で...

> 「存在すれば一意」という表現ができているのは偉いです。じゃあ「存在しないときはどうするんですか」と思う人もいると思いますが、存在しないときはどうでもいいんです。
EC2のコストを20％削減するためにやったこと

株式会社GxPのInternal Development Platforms室(IDP室)所属の大中です。IDP室は本年12月から新設された組織で、自分はその中で生成AIを基盤とした生産性向上を推進する…ということになっています。ですが自分のGxPで今まで行ってきたことがインフラ運用や移行作業主体だったため、RAGのようなキラキラ✨したことを推進する基盤を作る上での種々面倒くさいことを馬力で片付ける、というのが自分のロールです。

さて、今日はEC2で運用しているWebアプリケーションについて、AWSのコスト削減に取り組み、おおよそ20％程度の削減を実現した取り組みを紹介します。

まず、運用しているアプリケーションの概要は以下の通りです。

- JVMで稼働している業務アプリケーションが7つ。それぞれEC2インスタンス
- ミドルウェアのサポート条件の制約のためEC2を使用
- また、これもミドルウェアの制約で添付ファイル等のストレージはEBSを使用。ストレージ総容量はおよそ10TB
- RDBMSはRDS(PostgreSQL)。一番大きいインスタンスでデータベースのサイズは100GB程度
- アクティブユーザー4000名前後、ピーク時(平日業務開始時)に50万リクエスト/時
- AWSのインフラはTerraform+Ansibleでコード化。AMIイメージの作成にはPackerを使用
- 監視ははてな社の提供するMackerelで実施

なお、AWSアカウントの運用ポリシーの関係で、リザーブドインスタンス(RI)等のコスト削減策は使用していないため、今回これらの手法については触れません。

## 毎日コストチェック

この種の事例の定番ですが、Cost Explorerのレポートは毎日チェックするようにします。

このエントリーで付け加えることとしては、

- AWSのコストの集計タイミングの関係で、AWSの設定を変更したときに、それがAWSの日次コストに反映されるには2～3日かかる
- また業務システムの場合休日は課金額が落ち込むため、週の後半に設定変更の作業を行った場合は、効果が確定するまで1週間近くかかる場合がある
- 月次コストを考える時に、月の日数が30日の場合と31日の場合で3％強違い、祝日等で営業日がかわるとそちらも影響する

ということです。

## 未使用のリソースの削除

日常から使用していないリソースはチェックしていたはずなのですが、いざ棚卸ししてみるとNATゲートウェイ・EIP・EBSなど未使用リソースがステージング環境を中心に出てきたため、こちらは整理しました。

NATゲートウェイなどVPC関係のリソースの削除は机上での検証は十分進めた上で行いましたが、削除時にネットワーク障害を引き起こす可能性を否定できないため、運用開始後にVPC関係のリソースを作成する際は検証用であっても慎重に行う筆王があると思いました。

## スナップショット・AMIの削除の定期化

リソースを整理する中で未使用のEBSを削除しましたが、EBS内のデータが削除必要と判明した場合に備えて、EBSはスナップショットを取得してから削除しました。

また、アプリケーションのアップデート時にAMIイメージごとEC2インスタンスは作り直しているため、用済みになったAMIの削除も定期作業として行うようにしました。

それからアプリケーションのアップデート時にバックアップとしてEBSはスナップショットを取得しているため、スナップショットの削除も定期作業に組みこみました。

このようなプロセスの中で出てくる課題が、スナップショットを誤って削除した時にどのようにリカバリーするのかということです。EC2では、EBSスナップショット/AMIに対して「ごみ箱」機能を有効にすることができます。ごみ箱機能を有効化すると、スナップショット/AMIを削除した際に、一定期間ごみ箱内でリソースを保持することができます。

https://aws.amazon.com/jp/blogs/news/new-recycle-bin-for-ebs-snapshots/

実際運用の中でごみ箱からリソースを復旧したことがありました。スナップショットの課金はEBSを用いた運用を行っている案件では、無視できない要素です。この場合セーフガードとしてのごみ箱機能は非常に有用だと思います。

## RDSのGravitonインスタンスへの切り替え

RDSのインスタンスタイプをGravitonインスタンスに変更しました。RDSをGravitonインスタンスに切り替えること自体は低コストかつ低リスクで実施できます。

ただし、当時使用していたRDSのPostgreSQLバージョンに対するサポート切れが迫っていたため、そちらを先に対応しました。当時メンテナンスウィンドウを設定しての運用をしていなかったため、インスタンスタイプの切り替えよりもバージョンアップにともなうサービス停止の調整や実際の作業に苦労したという記憶が残っています。

## EC2/RDSのインスタンスタイプの変更

サービスイン後時間が経過し、使用状況が落ち着いているサービスは、EC2/RDSのインスタンスタイプを見直しました。また、最も頻繁に使用されるサービスのEC2インスタンスは、一番消費するリソースがJVMのヒープであるため、m5.4xlargeからメモリ最適化インスタンスのr7g.2xlargeに切り替えました。

## EC2のGravitonインスタンスへの切り替え

EC2のインスタンスタイプをGravitonインスタンスに変更しました。CPUアーキテクチャーがaarch64に切り替わりますのでこのことへの考慮が必要です。こちらはJVMアプリケーションということがあって、それほど苦労しなかったです。

それよりもサーバーOSをこのタイミングでCentOS 7からUbuntu22.04に切り替えているのがこの作業の山場なのですが、これは別の話なので、稿を改めて話させていただきたいと思います。

## RDS/EBSのストレージのGP3への切り替え

仕上げにRDS/EBSのストレージタイプをGP2からGP3に切り替えました。このことによりAWSの総コストで5％程度の削減効果をあげるこができました。

ストレージタイプの切り替えはダウンタイムなしで実施できますが、切り替え中のパフォーマンスの影響は予測しきれないところがあります。このため切り替え作業は業務時間後に実施しました。


上記のような取り組みを通じて、AWSのコストを20%程度(月で1000ドル単位)削減することができました。

コンテナベースでなくEC2ベースでのシステム運用を行っている方はそれなりの数いらっしゃると思いますので、何かの参考になればと思います。
Burp Suite の decorder がうまく動かなかった場合の代替手段

## はじめに

おぼえがきです。
Burp Suite で脆弱性診断中のリクエストを確認していたときに1つのパラメータだけものすごい長い値が入っていました。( URLエンコード済み & サイズが200KB超え ）
ひとまず中身を確認したかったのですが decorder に値をつっこむと完全に沈黙したため、 VSCode で実施しました。

## 環境

Windows 11 Pro 10.0.22631 ビルド 22631
openJDK 21.0.5
burpsuite_pro_v2024.9.3.jar
VSCode 1.96.2
[Encode Decode](https://marketplace.visualstudio.com/items?itemName=mitchdenny.ecdc)

## 手順

新しいテキストファイルを開いて、対象の文字列を貼り付け、右クリック
`Convert Selection > Encoded Url to String`
でできました。
シンプル！

改ざんした後は逆にエンコードしてあげれば良さそうですね。

## 問題の値(sample)

こういう感じの値でした。
```
%5B%7B%22aaaa%22%3A%221111%22%2C%22bbbb%22%3A%222222%22%2C%22cccc%22%3A%223333%22%2C%22dddd%22%3A%224444%22%7D%2C....
```

## 変換後の値(sample)

こういう感じの値になりました。実際は日本語の値も混じっており、サイズが肥大化しやすかった。
```
[{"aaaa":"1111","bbbb":"2222","cccc":"3333","dddd":"4444"},....
```

## おわりに

改ざんの対象にはなるのですが、どうみても固定値だったのでサーバーで保持してほしいなと思いました。
AWS認定ソリューションアーキテクトアソシエイト（AWS SAA）合格記

# AWS Solutions Architect Associate (SAA) 合格記

業務でAWSを扱う機会が多くなり、スキルを高めるためにAWS Solutions Architect Associate（SAA）の資格取得を目指しました。本記事では、勉強方法や試験の傾向、当日の流れを共有し、これからSAA取得を目指す方に役立つ情報を提供できればと思います。

---

## はじめに

業務でAWSのサービスを扱うことが多く、より深く理解して効率的に活用するために、AWS Solutions Architect Associate（SAA）の資格取得を目指しました。AWS認定資格を持っていることで、どのようなAWSのサービスをどの程度扱えるかを相手に示すことができ、信頼度も上がります。また、業務でのスキルアップにもつながり、日々のタスクをより効率よく進めるための知識を身に着けられるのも大きなメリットです。

---

## 勉強期間＆結果
2024/9月～10月中旬の約1か月半です。
#### 結果
 **882/1000**　 一発合格！！！
 
 （合格点は720/1000）
 
---
## 使った教材と勉強の流れ
使用した教材は3種類です。
上から順番に取り組みました。

- 書籍　
  - **AWS認定資格試験テキスト AWS認定ソリューションアーキテクト - アソシエイト 改訂第3版**  
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3912257/0ee28029-ae1d-a1c6-5b98-41caf5cd5ec2.png)

    - SAAの勉強を始めるにあたってすぐこの本を一通り読み、AWSの基本的なサービスを学習しました。
    - AWSの基礎から試験の出題範囲まで幅広くカバーしており、体系的に学べる構成が魅力です。個々のサービスに関する理解を深めるためにとても役立ちました。

- 問題集
  - **Ping-t**  
    - 試験1か月前から利用しました。
    - 各分野ごとに問題を解き、ミスがなくなるまで繰り返し取り組むことで、分野別の知識を確実に固めました。
  - **Cloud License**  
    - 試験2週間前から一通り解き、模擬試験を3回実施しました。
    - 模擬試験を解いた後にすぐに間違えた問題を見直し、その問題を再度解くという方法を繰り返し、サービスの理解を深めました。

最初から分厚い参考書を読むのが嫌だぁ！！という方は、AWSが提供しているAWS Skill Builderの「AWS Cloud Quest: Solutions Architect (Japanese)」を利用することをおすすめします。
ゲーム感覚でSAAの勉強ができるので、手を付けやすく知識が定着しやすいと思います。(29USD(約4600円)/月かかるので、費用を抑えるために私はやりませんでした)←





---
## SAA試験の出題傾向と難易度

AWS Solutions Architect Associate試験は、130分の試験時間で65問が出題されました。
問題はAWSのさまざまなサービスや機能から満遍なく出題されていましたが、特にセキュリティ系や、オンプレミスからAWSへのサービス移行に関する問題が多かった印象です。これらのトピックは、実務にも直結するため重要視されているように感じました。

試験全体としては、AWSの幅広い知識が問われるため、どの分野もバランスよく学習しておくことが求められる試験です。

---

## 模擬試験の活用法

模擬試験を解くのであれば、断然Cloud Licenseに課金して解くことをおすすめします。私は、模擬試験を解いた後にすぐに間違えた問題を見直し、その問題を再度解くという方法を繰り返し、理解を深めました。この復習方法は、本番での安定したスコアアップに非常に効果的でした。

また、Cloud Licenseの模擬試験は本番よりも約100点高くなる傾向があるため、少なくとも820点を目指して取り組むと良いでしょう。このスコアを基準にすることで、自信を持って本番に臨むことができると思います。

---

## 試験当日の流れと注意点

### 持ち物
試験当日は、身分証明書が2種類必要です。
※私はマイナンバーカードと運転免許証を持参しましたが、あらかじめ持ち物を確認しておくと安心です。

### 試験会場での流れ
試験会場に着いて受付を済ませると、すぐに試験室へ案内されるため、会場で問題の見直しをする時間はありませんでした。また、会場内は基本的に持ち込み不可で、入る前に所持品チェックが行われました。
※私はメガネをかけていたため、メガネもチェックされました。

### 時間配分と試験中のポイント
試験は130分ですが、私は見直しを含めて40分余裕を残して終了しました。試験中は焦らず、ゆっくりと進めることが大切です。問題数が多い分、時間も十分に与えられているため、時間配分を意識しすぎずに落ち着いて最後まで取り組めば大丈夫です。

### アンケート
試験後には5分ほどの制限時間でアンケートを書きました。残り時間に関係なく限られた時間内で記入する必要があるので、注意して対応すると良いでしょう。

---

## 合格後に感じたことと今後の展望

### 合格発表
試験後、その場で結果は分からず、19時頃にCredlyからメールで試験結果が届きました。私はCloud Licenseの模擬試験で一度も820点を取れなかったため、本番ではかなり不安がありましたが、結果は882点と予想以上のスコアを取得でき、本当に嬉しかったです。

### 今後の展望
次は順当にAWS Solutions Architect Professional（SAP）か、AI分野の資格としてAWS Certified AI Practitionerを受験しようと考えています。今回の合格を糧に、さらなるスキルアップを目指していきたいです。

---
「ハッカーと画家」読んでみた

ジョブカン事業部のアドベントカレンダー２４日目です。

https://qiita.com/advent-calendar/2024/jobcan

今年度からジョブカン事業部でエンジニアをしている@mochi33です！

クリスマス・イブですね！
ということで、今から誰かのプレゼントに使えるかもしれない、あるエッセイ本について書きていきたいと思います。
よろしくお願いします！

### はじめに
本記事では、入社してすぐの時期に先輩エンジニアの方におすすめしていただいた本、ポール・グレアム著「ハッカーと画家」ついて紹介いたします。
ただ、本の全体について触れると長くなってしまうので、第二章に絞って書いていきます。
拙い文章となってしまっていますが、お付き合いいただけると幸いです🙇

### 「ハッカーと画家」はどんな本？
この本は、最初のASPと言われるViawebを創り上げたポール・グレアム氏が書いたエッセイ集です。
載っているエッセイはそれぞれでかなり異なった内容となっているのですが、どれもグレアム氏のコンピュータの世界に対する思想が濃く書かれていて、エンジニアであれば強烈に惹かれるような内容となっていると思います。

### 第二章の内容
「ハッカーと画家」の第二章は本のタイトルと同じ、「ハッカーと画家」となっています。
そして章内では、ハッカーと画家の関係について『私が知っているあらゆる種類の人々の内でハッカーと画家が一番よく似ている。』と述べられています。
そこまで似ているかな？
私自身が想像するハッカーはどちらかといえば画家とは逆の存在のようなイメージがあったので驚きました。
ただ、この章では、その2つの共通点や用いる手法の類似点がいくつも書かれていており、読んでいくうちに深く納得することができました。

### ハッカーとは

グレアム氏の言うハッカーとは一体なんなのでしょうか？

#### ハッカー≠科学者
ハッカーは数学者ではないらしいです。まず、計算機科学=ハッカーでないことが説明されていました。
『計算機科学とはほとんど関連のない分野が歴史的な偶然からいっしょくたに放り込まれたもので、いってみればユーゴスラビアみたいなものだ。』と、計算機科学とハッキングの混同を憂いていて、少なくともハッカーの仕事は論文を書くためにあるものではないことがわかります。
確かに、優れたソフトウェア設計者が高度な計算機科学の知識を持っているかと考えればあまり関連性はない気がします...

#### ハッカー≠エンジニア
『優れたソフトウェア設計者は、建築家がエンジニアではないのと同じように、エンジニアではない。』

！？
私が読んでいる時には勝手にハッカー＝エンジニアと置き換えて読んでいたが、どうやらそういうわけではなさそうですね...。
建築家の立ち位置をソフトウェア開発に置き換えて考えてみると、何かの要望から仕様をつくるのはハッカーの仕事ということでしょうか。

ただ、

『「何を」と「どうやって」を分けすぎるのもよくない。』
『ハッキングをするのに最良の形態は仕様を創ることだ。ただ、仕様を創る一番の方法は、それを実装することだ。』

ともありました。
つまり、ハッカーは要望から実装までの流れを分業した一部分を担当するということではなく、ソフトウェアのデザインをし、そのデザインのためにコードも書くというようなループのような工程を行うということらしいです。

まるでスーパーマン。ハッカーかっこいい…

#### つまりハッカーは
まとめるとハッカーは論文を書く科学者や、仕様をコードに翻訳する技師ではなく、エンジニアリングをしながらソフトウェアのデザインをする人間ということです。

ん？デザインをしながら技術を用いて対象物を作り上げていく…？

まるで「画家」みたいだ！

### 画家から学べること

グレアム氏の言うハッカーと画家はかなり近しい存在であるということがわかりました。
そんなハッカーは画家の手法から多く学べることがあるみたいです。

以下にそれらを簡単にまとめました。

- 作りながら学ぶ

画家は作品を何枚も描きあげながら学ぶ。

ハッカーはいくつものプロジェクトを通してハックしながら学ぶ。

科学者は座学や先人の完璧な仕事(実験)を再現して学ぶ。
つまり、まずは上手になることから初めて、次第にオリジナルになっていく。ハッカーとは逆の順序となっている。

- 詳細化しながらも、元の計画を動かしながら作る

絵画は大まかな描写から始まり、次第に細部を埋めていくという手法がとられる。

しかし、時には最初の計画(構図や顔の表情など)を変更していくこともある。

ハッキングもそうあるべきで、元の仕様が変わってもそれに耐えられるような書き方をすべき。

つまり早すぎる最適化は危険。

- 共感能力が必要

絵画は人に見られるものであるため、共感能力が必要。

ハッカーもユーザ視点、コードを読む人の視点を得るためにそれが必要。

### ハッキングはクールか？

第二章の終わりはハッキングに対する世間の評価やその展望について書かれていました。

『ハッキングは画家や小説家と同じだとして、それは同じくらいクールだろうか。』

「ハッカー」ではないにしてもやはりエンジニアとしても気になる問いですね！

グレアムは『名声が遅れてくるのが常だ。』

『画家たちの名声が遅れてついてきたように、いつかハッキングにも栄光の時代が来るであろう。』
おお…(* ’ω` *)

この本が出版されたのは2004年ですが、確かにその時点からも良いソフトウェアが次々に生まれ、それらを創り上げるハッキングというものへの評価も向上しているのではないでしょうか？

### 終わりに
この記事で触れた第2章以外の部分で、『ハッカーは優れたプログラマのことである』とありました。エンジニアの進化系はハッカーなのかもしれないですね。

### 最後の最後に
DONUTSでは、新卒中途を問わず積極的に採用活動を行っています!!

ジョブカン事業部も、一緒に働くエンジニアを募集しています!!

気になる方はお気軽に応募してみてください。

https://www.donuts.ne.jp/recruit

https://recruit.jobcan.jp/donuts/show/B001/1396297
Kind公開設定で意味ある組み合わせは３つだけ

# 背景
練習用kubernetesであるkindは、以下3つのマニュフェスト(yaml)の組み合わせで公開設定しますが、意味がある組み合わせは主に3種類だと思うので共有しておきます
- cluster
- deployment
- service

# 環境
- Windows 11 Pro for Workstations 23H2
- WSL 2.3.26.0
- ubuntu 24.04.1 LTS (Windowsストア版）
- Docker version 27.3.1, build ce12230

# 意味ある組み合わせ
## 1.通信ポートでのサービス一切しない
|  | cluster | deployment | service |
| ---- | ---- | ---- | ---- |
| 設定 | なし | **なし** | なし |
- deployment-spec-template-spec-containers-port(またはpod のport)で公開設定しなければ、clusterやserviceに何書こうとも、podから何も公開されないので何書いても無意味です

## 2.cluster内のみ通信する
|  | cluster | deployment | service |
| ---- | ---- | ---- | ---- |
| 設定 | なし | **あり** | **あり** |
- deployment-spec-template-spec-containers-port(またはpod のport)だけ公開設定しても、IPが分からないと通信できないので、名前解決できるようにserviceもセットで設定しないと無意味です
- PODにWebサーバ立てても、クラスタ外に公開してないので、ホストOS上のchomeブラウザや、ubuntu上で動作してるgoogle-chrome等からも何も通じません

## 3.cluster外に公開する
|  | cluster | deployment | service |
| ---- | ---- | ---- | ---- |
| 設定 | **extraPortMapping** | **あり** | **あり** |
- docker上で動作するkindにおいて、node-port設定しても外に出せないので無意味です
- なので、clusterにextraPortMappingが必須

- httpサービス動かしたpodへのアクセス状況は以下の通り
### ホストOS(Win11)上のクロムブラウザから
|  | localhost | 172.17.0.1(kind動作dockerの外IP) | 172.17.212.197など(HyperVネットワーク上のUbutnuIP eth0) |
| ---- | ---- | ---- | ---- |
|　応答 | 〇 (WSLのlocalhost forwarding経由) | × | 〇 |

### WSL上のgoogle-chromeから
|  | localhost | 172.17.0.1(kind動作dockerの外IP) | 172.17.212.197など(HyperVネットワーク上のUbutnuIP eth0) |
| ---- | ---- | ---- | ---- |
| 応答 | 〇 | 〇 | 〇 |

- なお、隣のPCからもアクセスさせたいときは、ホストOS(Win11)にFierwallとPortfowardeingかければいけます（あくまで練習用という前提で）
- なるべくシンプルに書きたかったので割り切ってます。が、間違いのご指摘はウエルカムです m(_ _)m
OMCB012D(923)

https://onlinemathcontest.com/contests/omcb012/tasks/6768

公式解説では、偶関数について触れられており、こちらの方が簡単に解が求まりますが、
偶関数の特徴がわからなくても、剰余の定理(因数定理)の解き方がわかれば、解が導けます。

$f(x)$は$f(1)=f(2)=f(3)=f(4)=5$なので、剰余の定理を使って以下のように書くことができます。
　$f(x)=g(x)(x-1)(x-2)(x-3)(x-4)+5$ $…①$

$①$の$(x-1)(x-2)(x-3)(x-4)$を展開すると、
　$(x-1)(x-2)(x-3)(x-4)=x^4-10x^3+35x^2-50x+24$ $…②$
となり、$②$の$x^4$の係数が$1$、また、$f(x)$が$8$次式、かつ$x^8$の係数が$1$なので、
$①$の$g(x)$は以下のように書くことができます。
　$g(x)=x^4+px^3+qx^2+rx+s$ $…③$

$②,③$を展開すると、
　$f(x)=x^8+(p-10)x^7+(q-10p+35)x^6+(r-10q+35p-50)x^5+(s-10r+35q-50p+24)x^4+(24p-50q+35r-10s)x^3+(24q-50r+35s)x^2+(24r-50s)x+24s+5$ $…④$
となります。
$④$の奇数次の係数は$0$であることに着目すると、
　$p-10=0$ $…⑤$
　$r-10q+35p-50=0$ $…⑥$
　$24p-50q+35r-10s=0$ $…⑦$
　$24r-50s=0$ $…⑧$
になり、方程式が立てられます。

～～～以下、方程式を解きます。～～～

$⑤$より、$p=10$になります。
$p=10$を$⑥,⑦$に代入すると、
　$r-10q+300=0$ $…⑥'$
　$240-50q+35r-10s=0$ $…⑦'$
　$24r-50s=0$ $…⑧$ (変更なし)
になります。
$⑥'$を変形して、$⑦'$に代入すると、
　$10q=r+300$
　$240-5(r+300)+35r-10s=0$
　$30r=10s+1260$
　$3r=s+126$ $…⑦''$
になります。
さらに、$⑦''$を$⑧$に代入すると、
　$8(s+126)-50s=0$
　$42s=8×126$
　$s=24$
になります。
$s=24$を$⑦''$に代入すると、$r=50$が求まります。
$r=50$を$⑥'$に代入すると、$q=35$が求まります。

～～～ここまで、方程式を解いています。～～～

したがって、
　$g(x)=x^4+10x^3+35x^2+50x+24$ $…⑨$
であることがわかりました。
$⑨$より、
　$g(5)=5^4+10×5^3+35×5^2+50×5+24$
　$=625+1250+875+250+24$
　$=3024$
になります。$g(5)=3024$を$①$に代入すると、
　$f(5)=3024×(5-1)×(5-2)×(5-3)×(5-4)+5$
　$=3024×24+5$
　$=72581$
となり、解を求めることができました。
データサイエンスと機械学習の違いを分かりやすく解説！

近年、AIやデータ活用の話題が増える中、「データサイエンス」と「機械学習」という言葉を耳にする機会が増えました。しかし、この2つの違いについてしっかり理解している人は意外と少ないかもしれません。この記事では、中学生でも分かるように、データサイエンスと機械学習の違いをわかりやすく解説していきます！
※この記事は、ChatGPTの出力を基に作成しています。

---

## 機械学習とは？

まず、機械学習とは何かを簡単に説明します。機械学習は、**コンピュータがデータから学んで賢くなる方法**のことです。

通常、コンピュータに何かをさせたいときには、細かいルールをプログラムとして教える必要があります。しかし、機械学習では大量のデータをコンピュータに与えて、自分でルールを見つけさせるのです。

### 例：猫と犬の区別
たとえば、猫と犬の写真を区別する方法を考えてみましょう。

- **従来のやり方**  
  「猫の耳は三角形で、犬の耳はたれ耳が多い」というルールをプログラムで教えます。しかし、すべての猫や犬に当てはまるルールを作るのはとても大変です。

- **機械学習のやり方**  
  猫と犬の写真をたくさんコンピュータに見せて、「これは猫」「これは犬」と正解を教えます。すると、コンピュータは自分で「耳の形や目の特徴」を学び、猫と犬を区別できるようになります。

---

## データサイエンスとは？

一方で、データサイエンスはもっと広い範囲をカバーしています。データサイエンスは、**データを使って問題を解決する全体的なプロセス**のことです。問題を見つけることから始まり、データを集め、分析して結果を使うまでの流れ全体が含まれます。

### データサイエンスの役割
データサイエンスでは以下のようなステップが重要です。

1. **問題を特定する**  
   例：スポーツチームの成績を予測したい。
2. **データを集める**  
   例：試合結果、選手の記録、練習状況などのデータを収集。
3. **データを分析する**  
   例：どの要素が勝敗に影響しているかを調べる。
4. **解決策を提示する**  
   例：次の試合での勝利に向けた戦略を提案。

---

## データサイエンスと機械学習の違いを比較

では、この2つをもう少し具体的に比較してみましょう。

| **項目**             | **データサイエンス**                          | **機械学習**                        |
|----------------------|---------------------------------------------|-------------------------------------|
| **範囲**            | データの分析、可視化、問題解決まで幅広い。          | データを元に予測や判断を自動化する技術に特化。 |
| **役割**            | 問題を見つけて解決方法を考える。                 | データから学び、モデルを作る。         |
| **使用技術**         | 統計、プログラミング、可視化ツールなど幅広い。       | 主にアルゴリズムや数学。              |
| **例えるなら**        | 科学者や探偵のように、全体を調べて解決策を見つける。 | 学習するロボットを作る技術者のような役割。 |

---

## 具体例で考える

### スポーツの成績予測
1. **データサイエンス**  
   スポーツチームの成績を予測するために、選手の成績や試合結果などを集めて分析します。

2. **機械学習**  
   集めたデータを使って、「次の試合で勝つ確率」を自動で予測するモデルを作ります。

### オンラインショップのおすすめ機能
1. **データサイエンス**  
   「どんな商品をおすすめするべきか」という問題を考え、購買履歴や人気商品などを分析します。

2. **機械学習**  
   似たような趣味を持つユーザーのデータを使って、「この商品を買う可能性が高い」と予測します。

---

## まとめ

- **データサイエンス**は、データを使って問題を解決するための全体的なプロセス。
- **機械学習**は、データを使ってコンピュータが自動で学ぶ技術のこと。

データサイエンスの中には、機械学習だけでなく統計分析やデータ可視化などさまざまな技術が含まれます。一方、機械学習は「データから学んで予測や判断をする」ことに特化しています。

どちらもデータを活用する上で欠かせない分野なので、これからの社会でますます重要になるでしょう。興味を持ったらぜひ深く調べてみてください！
Javaで整数⇔2進数の変換

AtCoderの問題などを解いていると整数と2進数の相互変換する機会があるので方法をメモ。  

## 参考

https://amzn.asia/d/bATAE4P

## 全体のコード

整数を2進数に変換し、その後再び整数に戻すプロセスを実行しているコードが以下。  
この例では、整数17を2進数に変換し、その2進数を再度整数に変換している。  

```java
import java.util.*;

public class ConvertNumberAndBinary {
    static final int BIN_LENGTH = 10; // ビット数の設定
    static final int NUMBER = 17;

    public static void main(String[] args) {
        // 整数 -> 2進数
        int[] bin = number2binary(NUMBER);
        // 2進数 -> 整数
        int num = binary2number(bin);
        System.out.println("17 -> " + Arrays.toString(bin) + " -> " + num);
    }

    private static int[] number2binary(int number) {
        int[] bin = new int[BIN_LENGTH];
        for (int i = 0; i < BIN_LENGTH; i++) {
            int index = BIN_LENGTH - (i + 1);
            int v = 1 << i;
            int rightShifted = number / v;
            bin[index] = rightShifted % 2;
        }
        return bin;
    }

    private static int binary2number(int[] bin) {
        int number = 0;
        for (int i = 0; i < BIN_LENGTH; i++) {
            int index = BIN_LENGTH - (i + 1);
            if (bin[index] == 1) {
                number += (1 << i);
            }
        }
        return number;
    }
}
```

### プログラムの実行結果

実行すると以下の出力が得られる。  

```
17 -> [0, 0, 0, 0, 0, 0, 1, 0, 0, 1] -> 17
```

この結果は、整数17が2進数 `[0, 0, 0, 0, 0, 0, 1, 0, 0, 1]` に変換され、再び17に戻されていることを示している。  

### BIN_LENGTH について補足

このプログラムでは、`BIN_LENGTH`を10に設定している。  
これは、2進数表現で使用するビット数を意味し、この場合は10ビットで表現される。  
10ビットで表現できる最大の整数は  [tex: 2^{10} - 1 = 1023] となる。  

## `number2binary`

`number2binary`メソッドは、整数を2進数の配列に変換している。  
このメソッドでは、与えられた数値を右シフトしながら、各ビットを計算して配列に格納している。  

```java
private static int[] number2binary(int number) {
    int[] bin = new int[BIN_LENGTH];
    for (int i = 0; i < BIN_LENGTH; i++) {
        int index = BIN_LENGTH - (i + 1);
        int v = 1 << i;
        int rightShifted = number / v;
        bin[index] = rightShifted % 2;
    }
    return bin;
}
```

## `binary2number`

`binary2number`メソッドは、2進数を表す整数の配列を受け取り、それを整数に変換する。  
配列の各要素を左から右へと走査し、各ビットが1の場合に対応する2の累乗を合計していく。  


```java
private static int binary2number(int[] bin) {
    int number = 0;
    for (int i = 0; i < BIN_LENGTH; i++) {
        int index = BIN_LENGTH - (i + 1);
        if (bin[index] == 1) {
            number += (1 << i);
        }
    }
    return number;
}
```
Luacheckの設定ファイルの書き方

## `.luacheckrc`ファイル

vim(ALE)から呼ぶ場合はHomeディレクトリに、ターミナルから使うときはソースのあるディレクトリに`.luacheckrc`が必要(シンボリックリンクを使う)

```luacheckrc.lua
color = false
cache = true
std = 'max+love+busted'
globals = {'PROJECTNAME', 'VERSION', 'idiv', 'gr' ,'inspect', 'pp'}
-- self = false
max_line_length = false
max_code_line_length  = false
-- max_cyclomatic_complexity = 10
ignore = {'122', '142', '143', '211/_', '212/self', '213/_[ij]', '214/_u[%x_u]', '232/dt', '311/_continue_.*', '431/self', '432/self'}
```

## ignore(警告を出さなくする)の設定

パターン(正規表現)を後ろにつけて当てはまるものだけ警告を出さないようにできる

- 122: mathやloveなどに対して追加で識別子を定める
- 142: ioなどに対して追加で識別子を定める
- 143: 142で定めたものを使う

- 212: 使っていない引数(ただしselfという名前のみ)を警告しない
- 214: 『アンダースコアで始まる変数名を使っている』という警告をださない(ただしyueがUnicode識別子を変換したもののみ)
- 311: 『セットした値が使われない』という警告を出さない(ただしyueが生成する`_continue_0`などのみ)
- 431: 『同じ名前の変数名でより外側のスコープの変数を覆い隠す』という警告を出さない(ただしyueが生成するselfのみ)
DNSサフィックスメモ

**DNSサフィックス**とは、完全修飾ドメイン名（FQDN: Fully Qualified Domain Name）の最後に付加される名前の一部を指します。主にネットワーク内で名前解決を簡略化し、利便性を高めるために使用されます。

### 主なポイント
1. **役割**  
   - ドメイン名の補完: 短いホスト名（例: `server1`）を指定すると、DNSサフィックスが自動的に付加されて完全な名前（例: `server1.example.com`）になります。
   - 名前解決の効率化: ユーザーが完全なFQDNを入力する手間を省きます。

2. **構成例**  
   - ホスト名: `server1`  
   - DNSサフィックス: `example.com`  
   - 完全修飾ドメイン名（FQDN）: `server1.example.com`

3. **適用場所**  
   - クライアントのネットワーク設定: OSのネットワーク設定でDNSサフィックスを設定できます。
   - ドメイン参加: WindowsのActive Directoryに参加したクライアントでは、自動的にドメイン名がDNSサフィックスとして設定されます。

4. **検索順序**  
   ネットワーク環境によっては、複数のDNSサフィックスを設定し、名前解決時にこれらを順番に試す仕組みもあります（DNSサフィックス検索リスト）。

### 使用例
例えば、`ping server1`と入力した際に、DNSサフィックスが`example.com`であれば、実際には`server1.example.com`に対して通信が行われます。

これにより、特定のドメイン内での名前解決がスムーズに行えるようになります。
pipenvでpythonの仮想環境

### 仮想環境作成
```cmd.py

py -m pipenv install

```
### pipfileに必要ライブラリのインストール
```cmd.py

py -m pipenv intsall ライブラリ

```
### 簡潔に実行できるように
pipfileに以下のコードを追加する
```
[scripts]
dev = "python exe.py"
````
:::note info
py -m pipenv run dev　で実行可
:::
Raspberry Pi 5でサイネージ　画面をSSH経由で制御（Wayland/Labwc対応）


これは [RaspberryPI Advent Calendar 2024](https://qiita.com/advent-calendar/2024/raspberrypi) の23日目の記事です。

Raspberry Piで社内向けサイネージを作っています。当初は専用OS(Anthias)で作っていましたが、映像出力でのトラブルが多く困ったため、シンプルな構成のChromium『キオスクモード』による構成としました。

https://qiita.com/shinya_nakashima/items/203f628846c62e0f8458

# 概要
Chromium『キオスクモード』で、起動時にAPIをコールして設定や任意のURLのリストを取得しています。
- 来訪されたお客さんなどに見せるときがたまにあるのですが、画面数が多い場合に「あの画面を見せたい！」という要望が上がってきます
- そのため画面を切り替えるためのデバイスなどを開発するのですが、支社などのサイネージに対してSSH経由でも『画面送り／戻し』をしたいケースがあります

そこで今回は、SSH経由でサイネージの各画面を制御（画面送り / 画面戻し / リロード等）を行えるようにします。

# やること
`ydotool`をインストールしましょう。`Wayland` & `Labwc`の環境でもバッチリ動きます。

https://github.com/ReimuNotMoe/ydotool

`ydotool`と`ydotoold`を導入したら、`.bashrc`に下記のように記載します。
- `63:1 63:0`は、F5キーを押して離す動作を再現
- `29:1 15:1 15:0 29:0`は、Chromiumのタブ移動（次のタブ）を再現
- `42:1 29:1 15:1 15:0 29:0 42:0`は、Chromiumのタブ移動（前のタブ）を再現

```bash:.bashrc
alias sinage_reload='/usr/local/bin/ydotool key 63:1 63:0'
alias sinage_next='/usr/local/bin/ydotool key 29:1 15:1 15:0 29:0'
alias sinage_prev='/usr/local/bin/ydotool key 42:1 29:1 15:1 15:0 29:0 42:0'
```

# 独自のキーを設定したい
Linux kernelの`input-event-codes.h`を参照して、オレオレのキー入力を見つけましょう！

- 直接ファイルを参照したい場合
`/usr/include/linux/input-event-codes.h`を参照

- オンラインで確認したい場合
Linux kernelのヘッダーファイルを参照しよう。

https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h

# おまけ
こんな感じのサイネージを表示しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30994/24a64d34-1298-66cf-f933-01363788de86.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30994/6f0a5a22-9b40-faf2-3d59-356f6ffa6cb4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30994/efcf7fb4-a404-52d3-6220-8843f2ca127e.png)
AWSを用いたwebアプリケーションの作成　〜はじめに〜

# はじめに
活動しているゼミでMBTI診断のようなものを作りたく、AWSを用いて外部公開することになりました。この記事は備忘録的なメモ書きになっているので悪しからず。

なお、筆者のスキルとしては、

- 2024年4月からプログラミングを始めた（自分でコードは書けない…）
- 基本情報技術者試験はギリギリ合格したが、実務経験はない
- AWSを初めて使う

と、ほぼゼロに等しいので本当に初心者です。なんなら文系ですし。
トンチンカンなことを書くかもしれないですが、温かい目で見守っていただけると幸いです🙇‍♂️


# 今回使用するもの
### ツール
- VS code
- GitHub
- AWS
- Excel

### 言語
- Python
- HTML
- CSS
- JavaScript

### その他
- Pythonのライブラリ系（今後詳しく記述予定）

<br>
<br>
大前提としてとにかくコストを抑えてやるのがミッションでもあるので、
そこも意識できたらなと考えています。



# システムの概要
1. Excelにデータを保存
1. Pythonのpandasを用いてExcelデータを読み取る
1. 回答者側と、用意したデータを比較し、診断結果をHTML形式で表示
<br>
簡単にまとめるとこんな感じです。<br>
これをAWS上にデプロイして、外部公開することを想定中です。



# AWSのアーキテクチャ図
👷今後編集予定👷


# 次回に向けて
次回からはEC2を用いてインスタンス起動をまとめたいと思います。
オリジナルのPukiWikiスキンをつくってみよう #0 (準備)

# はじめに
今回はオリジナルのPukiWikiスキンを開発のための準備をします。
1から作るのもいいですが、このシリーズではデフォルトのスキンを改造していく形となります。

ただ、改造して作るとライセンスは元ソースの `GPLv2 or any later version` が適用されます。
別のライセンスを使いたいのであれば1から書くことをオススメします。
(私的利用の範囲内で配布しないのであればライセンスに関しては考えなくてもヨシ！)

### 過去につくったCleaskin
過去にCleaskinというスキンを作ったことがあります

https://github.com/PTOM76/pukiwiki-cleaskin

デスクトップ
![image](https://github.com/PTOM76/pukiwiki-cleaskin/assets/58260965/478f1142-f08e-4ded-be69-2fdbf9dc0f3a)

モバイル
<img src="https://github.com/PTOM76/pukiwiki-cleaskin/assets/58260965/53dd17f5-cae1-40f1-8378-042c313792ae" /> <img src="https://github.com/PTOM76/pukiwiki-cleaskin/assets/58260965/4058ad1a-9f2c-4880-a08a-2a9e70d5c767" />

## 前提
- PHPを導入していること
- PukiWikiを既に導入していること

上記については省きます。

# スキンの仕組みについて

## pukiwiki.ini.php
```pukiwiki.ini.php
/////////////////////////////////////////////////
// Directory settings II (ended with '/')

// Skins / Stylesheets
define('SKIN_DIR', 'skin/');
// Skin files (SKIN_DIR/*.skin.php) are needed at
// ./DATAHOME/SKIN_DIR from index.php, but
// CSSs(*.css) and JavaScripts(*.js) are needed at
// ./SKIN_DIR from index.php.

// Static image files
define('IMAGE_DIR', 'image/');
// Keep this directory shown via web browsers like
// ./IMAGE_DIR from index.php.
```

デフォルトではSKIN_DIRは `skin/` となっています。
`skin/` にはデフォルトのスキンが入っており、スキンを変えるには
1. SKIN_DIRの定数を変更する
2. `skin/*` の中身を使いたいスキンで上書きする

という方法があります。
私は`1. SKIN_DIRの定数を変更する`方法でいいと思います。
例えば、Cleaskinならば`skin/cleaskin/`にCleaskinスキンを設置し、それをSKIN_DIRで`skin/cleaskin/`として設定して読み込ませます。

## スキンの読み込み
pukiwiki.ini.phpで設定されたSKIN_DIRのディレクトリ内にある`pukiwiki.skin.php` を読み込む仕様となってます。
つまり、pukiwiki.skin.phpさえあればスキンを作ることができます。
その他、CSSやJSなどをpukiwiki.skin.phpから読み込むことによって適用できるわけです。

## スキンで使われる定数やら
必ず必須というわけでもないと思いますが、PukiWikiの標準スキンで利用されている定数なので基準みたいな感じだと思ってください。

| 定数名 | 説明 |
| ----- | ---- |
| SKIN_DEFAULT_DISABLE_TOPICPATH | 0でパンくずリスト(topicpath)、1でURL |
| PKWK_SKIN_SHOW_NAVBAR | ナビバーの表示 (標準スキンでいうところの左上の文字のバー) |
| PKWK_SKIN_SHOW_TOOLBAR | ツールバーの表示 (標準スキンでいうところの右下のアイコンのバー) |
| LANG | 表示言語、pukiwiki.ini.phpで定義されている |
| UI_LANG | UI上の表示言語、pukiwiki.ini.phpで定義されているが、初期設定ではLANGと同様の値 |
| PKWK_READONLY | 閲覧専用、pukiwiki.ini.phpで定義されている |
| CONTENT_CHARSET | 文字のエンコード形式 |
| SKIN_DIR | スキンのディレクトリ |
| IMAGE_DIR | 画像のディレクトリ |
| PLUGIN_DIR | プラグインのディレクトリ |
| S_COPYRIGHT | PukiWikiのコピーライト、バージョンや開発チームなどの情報 |
| PHP_VERSION | PHP標準定数でPHPのバージョン情報 |

# スキン開発のための準備

1. `skin/スキン名/` のディレクトリを作成
    私は `skin/nature/` にしました
2. `skin/`にある `pukiwiki.skin.php` と `pukiwiki.css` を`skin/スキン名/`へコピーする
3. 私は `pukiwiki.css` をリネームしてnature.cssにしました。
    これも `スキン名.css` でもいいですし、別に名前は任意です
4. cssの名前を変えた場合は、`skin/スキン名/pukiwiki.skin.php` の 75行目あたりの以下のコードにあるpukiwiki.cssの部分を変更後のファイル名にしてください
```php
<!-- 変更前 -->
 <link rel="stylesheet" type="text/css" href="<?php echo SKIN_DIR ?>pukiwiki.css" />
 
<!-- 変更後 (例) -->
 <link rel="stylesheet" type="text/css" href="<?php echo SKIN_DIR ?>nature.css" />
```
5.&nbsp;`pukiwiki.ini.php` の SKIN_DIRの定数を`skin/` から `skin/スキン名/` に変更 (85行目)
```php
/* 変更前 */
// Skins / Stylesheets
define('SKIN_DIR', 'skin/');


/* 変更後 (例) */
// Skins / Stylesheets
define('SKIN_DIR', 'skin/nature/');
```

正常にCSSやJSが読み込まれていれば準備は完了です。

次回は実際に変更していきます。
旅行思い出マップのユニーク保存体験と苦難と激闘の末にできた北海道179市町村マップの現実

## はじめに

こんにちは。私は個人開発者として、旅行好きな人々にとって新しい体験を提供するために「[旅行思い出マップ](https://apps.apple.com/jp/app/%E6%97%85%E8%A1%8C%E6%80%9D%E3%81%84%E5%87%BA%E3%83%9E%E3%83%83%E3%83%97-%E6%97%A5%E6%9C%AC%E3%82%84%E4%B8%96%E7%95%8C%E3%81%AE%E5%9C%B0%E5%9B%B3%E3%82%92%E5%86%99%E7%9C%9F%E3%81%A7%E5%9F%8B%E3%82%81%E3%82%88%E3%81%86/id6478291625?platform=iphone)」というアプリを開発しています。このアプリは、旅行先の思い出の写真を地図上に配置し、都道府県や市町村の地形に切り取ることで視覚的に楽しめるというユニークな機能を持っています。

![appliv.010.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171702/15c24dd3-ccda-14cb-562a-2ab28c142fc0.jpeg)



今回のQiitaアドベントカレンダーでは、このアプリ開発において挑戦したこと、成功したこと、そして失敗したことを中心にお話しします。特に、成功の背景にある工夫や、失敗から得た教訓について共有することで、同じようにチャレンジしている方々のお役に立てれば幸いです。

## チャレンジしたこと

**1. 写真を地図の地形に切り取る体験の実現**

アプリのコアアイデアは、ユーザーが撮影した写真を旅行先の地形に合わせて切り取ることで、旅行の思い出を視覚的かつ楽しく保存することです。このアイデアを実現するために、次のような課題に取り組みました：

- **地形データの収集と加工**
  全国47都道府県と北海道179市町村の地形データを収集し、それらを写真切り取り用のテンプレートとして最適化しました

- **ユーザーが直感的に操作できるUI/UX設計**
  地形を選び、写真を簡単に配置・切り取るまでのフローをスムーズにするため、繰り返しプロトタイプを作成しました

![appliv.005.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171702/64076f64-6266-a2f5-e38d-27ed0d8e25b7.jpeg)

**2. 北海道179市町村マップの実装**

初期バージョンでは都道府県単位の地形デザインが中心でしたが、ユーザーから“もっと詳細な地図が欲しい”というリクエストを受け、北海道内の179市町村を追加するという大きなチャレンジに挑みました。

![appliv.008.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171702/bdfe6b0e-9203-56da-9d46-3e219196e164.jpeg)

## 成功したこと

### ユニークなデザイン体験を作り上げたこと

アプリの中核機能である「写真を地形に切り取る体験」は、開発当初から多くのユーザーに支持されています。この成功の背景には、次のような要因がありました：

- **地形データの最適化**
  シンプルかつ美しいデザインを目指し、地形データを正確に加工。過剰に詳細なデータは省き、写真を引き立てるような形状に仕上げました

- **プロトタイプによる反復的な改善**
  アプリの初期テスターからのフィードバックを重視し、ユーザーが簡単に地形を選び、写真を調整できる操作性を追求しました

- **直感的なUI**
  地図の形を選ぶだけで写真が切り取られるシンプルなフローにより、アプリ初心者でも楽しめる設計になっています

これらの取り組みの結果、ユーザーからは「旅の思い出をこんな風に残せるのは新鮮」「家族と一緒に楽しめる」といった高評価をいただいています。

## 失敗したこと

### 北海道179市町村マップが使われていない現実

ユーザーのリクエストを受けて北海道の179市町村データを追加したものの、データ利用率が極めて低いという結果に直面しました。具体的には、アクセスログを分析したところ、ほとんどのユーザーが都道府県単位の地形を選択し、市町村単位の地図はほとんど使用されていませんでした。

この失敗の原因として、次の点が考えられます：

- **ニーズの過剰解釈**
  ユーザーの一部から詳細な地図データを求める声があったものの、実際にはそれが全体のニーズを代表していなかった可能性。

- **操作の煩雑さ**
  179市町村の中から適切な地形を探すのがユーザーにとって手間だったこと。

- **プロモーション不足**
  新機能の価値をユーザーに十分に伝えきれていなかったこと。

## 学びと改善の取り組み

### 学んだこと

- **ユーザーの声を多角的に分析する重要性**
  ユーザーの意見を聞くことは重要ですが、全体のニーズを過剰に解釈するとリソースの無駄につながることを実感しました😭

- **データに基づく意思決定の必要性**
  開発前にユーザー調査やプロトタイプテストを実施し、需要を測定するべきだったと反省しています

### 改善への取り組み

現在、次のような改善を進めています：

- **北海道地図の利用促進**
  北海道の179市町村データをより使いやすくするため、地図検索やおすすめ表示機能を追加。

- **ユーザーインタビューの拡充**
  機能開発前に複数のユーザーグループから意見を集め、全体のニーズを把握するプロセスを強化。

- **プロモーション戦略の見直し**
  新機能の価値を伝えるための動画やブログを作成し、ユーザーへの告知を強化。

## これからの展望

「旅行思い出マップ」は、旅行好きな人々の思い出作りを支えるアプリとして進化を続けていきます。次のステップとして：

- **より広い地域への対応**
  現在は日本国内を中心とした機能ですが、海外旅行にも対応できるよう多国籍地図データの導入を計画中です。

- **コミュニティ機能の強化**
  ユーザー同士で旅行のアイデアや思い出を共有できる機能を追加する予定です。

- **データドリブンな開発**
  ユーザー行動データをもとに、より実用的かつ魅力的な機能を提供します。

## おわりに

個人開発は挑戦の連続であり、成功も失敗も貴重な学びの機会です。「旅行思い出マップ」を通じて得た経験をもとに、これからも新しい価値を生み出していきたいと思います。この記事が、同じようにチャレンジしている方々の参考になれば幸いです。

最後までお読みいただきありがとうございました！
【PostgreSQL】PrometheusからNewRelic PostgreSQLオンホスト統合へ移行している話

この記事はディップ[New Relic Advent Calendar 2024](https://qiita.com/advent-calendar/2024/newrelic)のシリーズ3 23日目の記事です。是非とも他の記事も読んでみてください！

## 自己紹介
息子大好きDBエンジニアのだいちです。
現行の監視環境にてPrometheusを利用しているのですが
NewRelic PostgreSQLオンホスト統合へ移行した(している最中)件について
まとめてますので是非とも最後まで読んでください。

## 誰に向けた記事なのか
今回は次のような環境・状況下の人に向けて纏めていきます。

- NewRelicを使っている
- PostgreSQLを使っている
- とにかくコストを下げたいと思っている

## 移行前の状況について
移行を検討する前は図にすると以下のようなアーキテクチャで監視をしていました。
※ Python コードでアーキテクチャ図を生成できる「diagrams」を利用したのですがうまく表現できなかったのでちょいと誤解を生む図になっているかもです。
![streaming_replication_with_monitoring.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572072/bc5adbf3-2b93-f61d-10d4-2f4f482e929c.png)

オンホスト統合への移行をして以下のようなアーキテクチャになるように進めていきました。
![ec2_instances_with_newrelic_monitoring.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572072/2ded4e8e-7cea-44d8-29bb-f0e65e2f8184.png)

## なぜNewRelic PostgreSQLオンホスト統合を利用するのか
大きく2つの課題がありました。

### 管理の属人化
Fargateを利用してそこでPrometheusを使っています。
Fargateの構築にはTerraformを利用しているのですが理解してる人は一人だけ。
別の人が何かをしようとしてもキャッチアップに時間がかかってしまうという状況です。

### リソースの維持費
DB一つに対してFargateを一つ立ち上げていたため
マスター・スレーブのストリーミング構成を利用しているためにDBの数は多いので
リソースのコストも膨大になっている状況でした。


これらの課題がたまたま利用していたNewRelicにオンホスト統合があったので調べたところ課題が解決されるので導入を進めた次第です。

## 移行までにやったこと
移行の中で一番大事にしたことは「現状と同じことができるか」でした。
### 現状と同じことができるかどうか
今現在はPrometheusを利用してPostgreSQLのメトリクスをNewRelicに送りダッシュボードにてチャートで表示させています。
オンホスト統合をしても同じようにみていたメトリクスを取得できてダッシュボードで表示できるのかを調べていきました。
Prometheus（正確にはPostgreExporter）で取得しているメトリクスが
オンホストではデフォルトで取得していないのもいくつかありました。そんなメトリクスに対してはカスタムクエリを使って取得することで解決してます。

NewRelic PostgreSQLオンホスト統合の導入については
[公式ドキュメント](https://docs.newrelic.com/jp/install/postgresql/)に書いてある手順を行うことで簡単に導入できます。

## 移行してみての気づき
カスタムクエリがクエリごとにプロセスが立つことに気づいたのですが想定と違ったので知っておくといいかもです。
当初の想定ではカスタムクエリは一つのプロセスでyamlに書いた順に実行していくのかと思ったのですが、カスタムクエリごとにプロセスが立って実行されていました。
何が影響するかというと、コネクション数のカウントがカスタムクエリのプロセスもカウントするのでメトリクスの取得タイミングでは常にカスタムクエリ分のプロセスがコネクション数としてチャートで表示されます。
まぁそういう状況だと把握しておけば何も問題はないですね。


## まとめ
今回移行をしたことで以下のようなメリットが得られるはずです。

### 料金コストダウン
年間で約7000ドルほどかかっているリソース(ECS)をオンホストで
1つのサーバから複数のDBに対してメトリクスを取得できるようにしたので
不要なリソースを削除できて年間で1000ドルほどになります。

### 属人化の解消
今現在としては移行に関わったメンバーしか把握していないですが、Prometheusを利用しているときのようなIaCを使ってECSを立ててみたいなことがないのでしっかりと共有すれば誰でも管理ができるようになる見込みです。

今回は上記の2点を現状の課題として解決まで対応を進められたのでとても勉強になりました。
dockerとdocker composeでwebアプリをdocker化する方法

# 環境構築方法

このプロジェクトは、Docker を使用して Ruby on Rails アプリケーションを構築しています。以下の手順を実行して、開発環境をセットアップしてください。

---

## **前提条件**

Ruby,Rails,Postgresql のバージョンは以下とする：

- Ruby 3.2.2
- Rails 7.0.6
- Postgresql 12

---

## **環境構築手順**

### **1. プロジェクトテンプレートをクローン**

以下のコマンドを実行し、プロジェクトのテンプレートをクローンします：

```bash
git clone 任意のgithub上にあるリポジトリURL
```

---

### **2. 必要なファイルを作成**

クローンしたプロジェクトのディレクトリで、`Dockerfile` と `docker-compose.yml` を作成します：

```bash
cd rails7_docker_template
touch Dockerfile docker-compose.yml
```

---

### **3. `Dockerfile` の記述**

以下の内容を `Dockerfile` に記述します：

```dockerfile
FROM ruby:3.2.2

# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y     build-essential     libpq-dev     nodejs     postgresql-client     yarn

# 作業ディレクトリを指定
WORKDIR /app

# アプリケーションコードをコンテナにコピー
COPY . .

# Bundler をインストール
RUN bundle install

# サーバーを起動
CMD ["rails", "server", "-b", "0.0.0.0"]
```

---

### **4. `docker-compose.yml` の記述**

以下の内容を `docker-compose.yml` に記述します：

```yaml
version: "3"

volumes:
  db-data:

services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - ".:/app" # ローカルディレクトリをコンテナの /app にマウント
    environment:
      - "DATABASE_PASSWORD=postgres"
    depends_on:
      - db

  db:
    image: postgres
    volumes:
      - "db-data:/var/lib/postgresql/data"
    environment:
      - "POSTGRES_USER=postgres"
      - "POSTGRES_PASSWORD=postgres"
```

---

### **5. データベースの作成**

#### **(1) コンテナを起動**

以下のコマンドを実行して Docker イメージをビルドし、バックグラウンドでコンテナを起動します：

```bash
docker-compose up -d
```

#### **(2) コンテナに入る**

以下のコマンドを実行して、`web` コンテナ内に入ります：

```bash
docker-compose exec web bash
```

#### **(3) データベースとテーブルを作成**

コンテナ内で以下のコマンドを実行してデータベースを作成します：

```bash
rails db:create
```

次に、マイグレーションを実行してテーブルを作成します：

```bash
rails db:migrate
```

---

### **6. コンテナの再起動とサーバーの確認**

#### **(1) コンテナから退出**

以下のコマンドでコンテナから退出します：

```bash
exit
```

#### **(2) コンテナとイメージを停止・削除**

以下のコマンドを実行してコンテナを停止し、削除します：

```bash
docker-compose down
```

#### **(3) コンテナを再ビルドして起動**

以下のコマンドを実行してコンテナを再度ビルドし、起動します：

```bash
docker-compose up --build
```

---

### **7. アプリケーションにアクセス**

ブラウザで以下の URL にアクセスし、Rails アプリケーションが起動していることを確認します：

```
http://localhost:3000
```

---

## **補足情報**

### **コンテナの操作**

- **コンテナの停止**

  ```bash
  docker-compose down
  ```

- **Rails コマンドの実行**
  コンテナ内で以下のようにコマンドを実行できます：
  ```bash
  docker-compose exec web rails <コマンド>
  ```

---