OmniAICreator/Qiita-1.07M huggingface dataset:
エンジニアたるもの 一次情報にあたれを紐解く

# エンジニアたるもの「一次情報にあたれ」
エンジニア界隈では「一次情報にあたれ」という言葉がよく使われる。原書や原典を直接読むべきだという考え方だ。聞いたことがない人はいないと思うが、なぜ一次情報にあたるべきなのか？その理由には、もちろん正当な背景がある

# 一次情報以外は伝言ゲーム
一次情報とは、その仕組みを作った本人、もしくは最も近い人物が記述した情報だ。基本的には、もっとも正確でかつ網羅的な内容が含まれる。それに対して、二次情報は一次情報をベースにまとめられたもので、解釈や装飾が加わることが多くなる。あえて言うなら、一次情報以外の情報はすべて劣化コピー。それを見ただけで理解した気になることは危険で、発信者の意図が歪んでしまうこともある

# 一次情報は「最小かつ完全」である
一次情報は、基本的に抜け漏れがないように完全を目指して書かれている。そのため、余計な例えや説明を極力避け、正確性を重視した「最小かつ完全」な形で提供されることが多い。これがもっとも効率的で、一次情報が持つ最大の特徴と言える

# しかし「最小かつ完全な文章」は読みにくい
「最小かつ完全な文章」は無駄がなく、効率的。一方で、このような文章は読みにくいと感じる人が多いかもしれない。特に、頭の良い人にはこのような情報が最も読みやすく感じられるが、凡人にはそれが一つの障壁になることがある。なぜなら、こうした文章は読むのに慣れが必要で、初心者には難解だからだ

# 「分かりやすさ」よりも「正確さ」が優先される
この読みにくさの理由は、余計な情報が削ぎ落とされているからだ。例えば、QiitaやZennなどの技術ブログでは「分かりやすさ」を重視しているが、一次情報では「正確さ」が重視される。分かりやすい文章には冗長な説明や例えが多く含まれることもあり、それが理解を助ける一方、一次情報はそうした冗長さを排除する

# 日本人は「分かりやすさ」を求めがち
個人的な見解だが、日本人は特に「分かりやすさ」を求める傾向が強いと思う。マンガ文化が発展した背景にも、文章より視覚的な情報の方が理解しやすいという文化的側面があるのかもしれない。最小かつ完全な文章を理解することが難しく、日本人は文章だけでは伝わらないと感じることが多いかもしれない

# つまり…
結局、「一次情報にあたれ」というのは間違いなく正しいことだ。しかし、一次情報だけで全てを理解するには、かなりの知識と経験が必要になる。理解が難しい人は、一次情報に目を通しつつ、二次情報などで補完していくのが現実的な方法となる。賢い人ほど「なぜこれだけ言っても一次情報にあたらないのか？」と不思議に思うかもしれないが、そうした人々にとっては、そもそも読めない難解な文章である可能性もある。実際僕も一次情報で理解するのは苦手だ。。
Three.jsでディスプレイによってオブジェクトのスピード感が違うのをなんとかしたい

## 概要
Three.jsでディスプレイによって動きのスピードが早かったり遅かったりといったことが起こると思います。
その対応策を調べました。

## 問題のコード
```javascript:公式サイトのコード
  import * as THREE from "three";

  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setAnimationLoop(animate); //⭐️
  document.body.appendChild(renderer.domElement);

  const geometry = new THREE.BoxGeometry(1, 1, 1);
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  const cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  camera.position.z = 5;

  function animate() {
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;

    renderer.render(scene, camera);
  }
```
上記は[公式のコード](https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene)です。
このままの状態だと cubeの動きがディスプレイによって早かったり遅かったりします。

仕組みとしては、⭐️をつけた行の `setAnimationLoop`関数で `animate`関数を呼び出しています。
その呼び出し方がディスプレイのリフレッシュレートに基づいているため、ディスプレイごとに早かったり遅かったりします。

## 対応策
```diff_javascript:追加編集したコード
  import * as THREE from "three";

  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setAnimationLoop(animate);
  document.body.appendChild(renderer.domElement);

  const geometry = new THREE.BoxGeometry(1, 1, 1);
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  const cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  camera.position.z = 5;

+ const clock = new THREE.Clock(); //①

  function animate() {
+   const elapsedTime = clock.getElapsedTime(); //②

-   cube.rotation.x += 0.01;
+   cube.rotation.x = elapsedTime; //③
-   cube.rotation.y += 0.01;
+   cube.rotation.y = elapsedTime; //③

    renderer.render(scene, camera);
  }
```
Clockのインスタンスを作成（①の箇所）し、
そこから `getElapsedTime` メソッドの値を `elapsedTime` に代入（②の箇所）、
その値を cubeの`rotation` に代入（③の箇所）しました。

これで、cubeの動きは時間で制御されるようになったので、
リフレッシュレートに関わらず一定の速さで動くようになりました。

## おわりに
すごい細かいこだわりかもしれませんが、何も疑問に思わず `requastAnimationFrame` で動かしたりしていたので、勉強になりました :baby:
~未経験・知識なしからセキュリティエンジニアになる！～『｛Level3｝振り返りと目標決定と理想のためには？』

こんばんは！Itoshinです。朝サクッと投稿するつもりが諸々バタバタで結局夜。
昨夜の続きです。Markdown記法というものがあると知ったので、活用してみようと思いました。慣れてないとかなり時間掛かりますねこれ...。
# 15日の講座で学んだこと
<dl>
<dt>暗号資産</dt>
<dd>・ネットワーク上でやり取りされる財産的価値<dd>
<dd>・不特定の者に対し、代金支払いに使用可能で、法定通貨(日本円や米国ドルなど)と相互に交換できる<dd>
<dd>・電子的に記録され、移転できる<dd>
<dd>・法定通貨または法定通貨立ての資産(プリペイドカードなど)に当たらない<dd>
※令和2年法改正以前は「仮想通貨」といわれていたが、法定通貨による価値の裏付けがないものを「通貨」とはみなせないとの意見から法改正後に「暗号資産」と呼ばれるようになった。
「暗号通貨」に当たるものは各国の中央銀行が発行する法定デジタル通貨や民間企業の発行するステーブルコインが定義されている。
<dt>ブロックチェーン</dt>
<dd>・取引情報をまとめ塊にした「ブロック」、これを「チェーン」のように繋ぐ事で偽造防止する仕組み<dd>
<dd>・ブロックにはブロックヘッダというデータを扱う為のデータと、このブロックのハッシュ値[これが次のブロックの偽造防止になります]<dd>
<dd>・いくつものトランザクション[送金情報]が格納されています(1つのブロックのサイズが1MB以下になる数)<dd>
<dt>ブロックヘッダの構造と偽造防止の仕組み</dt>
<dd>・前述した前のブロックのハッシュ値、難易度、Nonceが組み込まれている<dd>
<dd>・ハッシュ化されたデータは元に戻せない<dd>
<dd>・前のブロックを1bitでも改ざんすると、同じハッシュ値は出ない<dd>
<dd>・難易度はヘッダを含めた全体データに対して計算したハッシュ値が、先頭から難易度に指定された長さだけ"0"になっているかを調べ、一致させる必要がある<dd>
<dd>・Nonceは使い捨ての32bitのランダムな値が用いられる<dd>
<dd>・よって、計算で一致させるのにかなりの時間が掛かる<dd>
<dd>・その上、成功報酬目当てのマイニング業者達によって取り掛かれるブロックはどんどん切り替わっていく<dd>
事実上、改ざんは不可能と言われるわけです。

<dt>CDN(Contents Delivery Network)</dt>
<dd>・CDNとはWebコンテンツを迅速に効率よくユーザーに配信するためのネットワーク（仕組）<dd>
<dd>・仕組みとしてはオリジンサーバー（大元のコンテンツを保持している）とキャッシュサーバーがある<dd>
<dd>・この仕組みがない場合、クライアントはオリジンサーバーへのコンテンツ要求と応答をしないといけない→オリジンサーバーとの距離やトラフィック負荷増が影響し、表示速度が落ちる<dd>
<dd>・キャッシュサーバーがクライアントとオリジンサーバーとの間に置き、活用するとその都度オリジンサーバーにアクセスする頻度が減る<dd>
<dd>・オリジンサーバーコンテンツをキャッシュしたキャッシュサーバーからクライアントはコンテンツを要求、応答してもらえるため、遅延減少<dd>
<dd>・キャッシュサーバーが複数あれば信頼性の向上ができる<dd>
<dd>・デメリットとしては、キャッシュの保持時間が長いと古い情報が表示されること。誤って個人情報がキャッシュに残ってしまう可能性がある。

<dt>ダークウェブ</dt>
<dd>・一般的な検索エンジンではインデックスされず、特殊なブラウザを使用してのみアクセス可能なインターネットの一部。私達が普段見ているウェブはサーフェスウェブであり、見ることができない領域（ディープ＆ダークウェブ）は400倍以上になると言われている<dd>
<dd>・TorやI2Pなどの特殊なブラウザによって、ユーザーの匿名性が保護されるが完全に追跡不可能ではない。<dd>
<dd>・本来の利用目的としては1.閲覧の厳しい国々において、自由な情報交換の場として利用される　2.サイバーセキュリティ研究者が分析し、匿名技術の分析と対策を開発するためプラットフォームとして扱われる　<dd>
<dd>・ツールさえあればアクセス可能ではあるが、セキュリティリスク、法的リスク、倫理的懸念、プライバシーリスクがあるため、安易に接続することは勧められていない<dd>
<dt>無線LAN</dt>
<dd>・接続するケーブルがないため、自由なレイアウトで接続できるLAN形態。伝送路は電波を使用。WLANとも表現される<dd>
<dd>・無線LANアクセスポイントルーター（無線親機）と無線LANネットワークカードが必要(無線子機。現在はPCに内臓されているものがほとんどで、故障した場合は外付けで購入することがある)<dd>
<dd>・「SSID」と「パスワード」をアクセスポイント（AP）に設定し、無線子機であるPCにて使用可能なAPが表示されるため、選択してパスワードを入力する<dd>
<dd>・ハブやスイッチのような役割を果たすので、同じAPに接続したPCとプリンター同同士を接続することもできる<dd>
<dd>・接続形態はインフラストラクチャーモードとアドホックモードがある</dd>
<dd>・無線LAN規格はIEEE802.2委員会が策定。それに伴ってメーカーの開発が促される<dd>
<dd>・規格が新たなものになるにつれ、通信速度は速くなっていくが、影響範囲は狭くなる（周波数が上がる＝遠くまで届きにくくなる）<dd>
<dt>無線LANのセキュリティ</dt>
<dd>・脆弱性のある機能も散見され、安全でないネットワークを使用してしまう可能性がある（SSIDステルス、MACアドレスフィルタリング、WEPキーの暗号化など）<dd>
<dd>・無線LAN通信をする上での脅威とその対策を知っておくべき<dd>
<dd>・正規のユーザーになりすまして無線LANを利用する脅威に対しては、認証技術を利用しましょう。<dd>
<dd>・電波通信である以上、盗聴の危険性は高い。通信の暗号化をするため、TKIP、AESなどのセキュリティプロトコルを活用しましょう。<dd>
<dd>・データの改ざんが行われていないか確認するため、ハッシュ化技術を用いて整合性チェックしましょう。TKIP,AESで実現できます。<dd>
</dl>

15日の講座は大体ここまででした。ここまで書くのにスマホで1時間、PCで2時間。
Qiitaに書き込むまではマインドマップで講座内容を復習していたので、直感的にまとめられないのとmarkdown記法に手間取ってしまうのが大きなタイムロスになっているような気がします。
~~いっそのことならマインドマップをそのまま貼るか・・・？~~
明日は講座がないため、午前中にどうするか決めようと思います。
それではおやすみなさい＾＾
【お手軽エラー監視】AWS CloudWatchからSNSでメール通知する

## はじめに
アラート監視体制は、小規模なサービスや開発初期でも信頼性向上や障害発生時の迅速な対応のために無くてはならないものです。
ただ、人数やスケジュールが限られているとどうしても後回しにしがちな部分でもあります。
そこで、今回はAWSで普段使用するであろうCloudWatchに対して、特別な設定なくLambdaとSNSを組み合わせることで簡単にアラートのメール送信を実現できたので、その際使用した方法を載せます。

まずは簡単なとこらからでも、少しずつ少しずつ積み重ねることでプロダクトの信頼性は着実に向上していきます！

## アラートを送信するLambda関数の作成
今回はPythonを使って関数を作成します。
AWSコンソールで`Lambda > 関数 > 関数の作成`を選択し、関数を作ります。
ランタイムはPythonで任意のバージョンを選択すればOKです。

**コード例**
```python
import base64
import json
import zlib
import os
import boto3

def lambda_handler(event, context):
  errorLog = zlib.decompress(base64.b64decode(event['awslogs']['data']), 16+zlib.MAX_WBITS)

  try:
    sns = boto3.client('sns')
    
    #SNS Publish
    publishResponse = sns.publish(
      TopicArn = os.environ['SNS_TOPIC_ARN'],
      Message=errorLog,
      Subject='hogehoge',
    )
    
  except Exception as e:
    print(e)
```

`SNS_TOPIC_ARN` には後ほど設定するSNSトピックの環境変数を設定します。

Lambda関数にアタッチされたIAMロールには、アラート関数自体のログ出力のため`logs:CreateLogGroup`, `logs:CreateLogStream`と、SNSからのメール送信のため`sns:Publish`あたりの許可が必要になります。

## CloudWatchのサブスクリプションフィルターを設定する
先ほど作った関数を起動するキッカケを設定します。
関数のコンソールで、`トリガーを追加`を選択します。
![CleanShot 2024-10-16 at 18.29.28@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3128448/10107a2a-1b0b-2d18-c430-5642e428d308.png)

ロググループにはアラートを監視したいロググループを選択します。もし複数ある場合は、ロググループごとにトリガーを追加します。
フィルターパターンで、正規表現を使って監視したい文字列を指定しましょう。(例:アプリケーションから吐かれるエラーにERRORという文字が必ず含まれているなら `?ERROR`を設定)

:::note info
フィルターパターンの参考
[メトリクスフィルター、サブスクリプションフィルター、フィルターログイベント、およびライブテールのフィルターパターン構文 - Amazon CloudWatch Logs](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html)
:::



ここまで完了すれば、CloudWatchにエラーログが吐かれたタイミングで、Lambda側でログを受取っていることを確認することができます。

## SNSトピックを設定する
メール送信のため、`SNS > トピック > トピックを作成`からトピックを作成します。
タイプはスタンダードを選択し、その他設定はデフォルトでOKです。
作成したトピックで、`サブスクリプションの作成`を選択しプロトコルは`Eメール`で送信先のメールアドレス全て追加します。

最後に、作成したLambda関数の詳細画面で、`設定 > 環境変数 > 編集`から`SNS_TOPIC_ARN`を追加し、値にはSNSトピックのarnを設定します。

これで、お手軽アラートのメール監視実装完了です！

:::note warn
**補足**
ただし、このやり方ですと、Lambdaで受け取れるログは、CloudWatchのサブスクリプションフィルタに該当した1ブロック分に限られるので、例えば同じリクエストの別ログも参照したい場合は、下記の例のようにCloudWatchに検索をかける必要があります。

```python
logs_client = boto3.client('logs')
anotherLogs = logs_client.filter_log_events(
    logGroupName=log_group,
    logStreamNames=[log_stream],
    filterPattern=f'"{request_id}"',
    limit=5
  )
```
:::
ID-POSデータを活用したデータ分析入門　その５

## 今回のテーマ
前回（第4回目）は、商品視点の分析として「バスケット分析」を解説しました。
今回は、「バスケット分析」の実践編として、R言語のarulesパッケージ内に格納されている「Groceries」データを使ったバスケット分析をご紹介します。
（本来は、最近分析に関わった、とある生鮮食料品スーパーのPOSデータを用いてバスケット分析をした結果をご紹介する予定でしたが、商品名などデータを加工する必要があるので、次回以降に回します）

## 使用するデータ
今回使用する「Groceries」データはR言語のarulesパッケージの中に格納されているデータです。
データの中身は、食品や日用品、生活雑貨を取り扱う一般的なスーパーマーケットの1か月間のトランザクションデータです。
商品は「liquor」や「dish cleaner」「white wine」など、169のカテゴリーにまとめられています。
トランザクション数は、9835トランザクション（行）です。

データの中身を見るため、先頭10行を抜粋します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3834217/ca24d15f-be34-d917-1af6-c7531e7fafd6.png)

同時購入された商品が1行ごとに格納されています。

## ビジネスへの活用
「Groceries」データを元にバスケット分析を行い、「どの商品とどの商品がセット購入されているのか」や「ある特定の商品とセット購入されやすいのはどの商品か」などを明らかにすることで、購入点数や客単価アップに繋がることが期待できます。
尚、ビジネスへの活用については、第4回目の記事を参照ください。

## Rによる実装
````R:code
#tidyverseの読み込み
library(tidyverse)

#arulesの読み込み
library(arules)
``````
次に、Groceriesのデータをロードします。
````R:code
data("Groceries")
Groceries
``````
apriori関数でアソシエーションルールを抽出します。

````R:code
Gr_ap <- apriori(Groceries)
``````
出力結果を以下に示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3834217/c8c134b6-4a3e-1805-9a8d-c8b6eed20200.png)

>writing ... [0 rule(s)] done [0.00s].

ルールが抽出されませんでしたので、パラメータ（支持度、信頼度）を調整していきます。

````R:code
Gr_ap <- apriori(Groceries, p = list(support = 0.005, confidence = 0.01))
``````
支持度（Support）を0.005、信頼度（Confidence）を0.01に調整しました。
出力結果を以下に示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3834217/f6721d43-40ec-3c06-b33b-fec318f4625e.png)

>writing ... [2138 rule(s)] done [0.00s].

2138個のルールが抽出されました。

抽出された2138個のルールをlift値でソートし、上位20個のルールを抽出してみます。
````R:code
Gr_ap %>% sort(, by = "lift") %>% 
  head(n = 20) %>% 
  inspect()
  ``````
出力結果を以下に示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3834217/2a873993-9634-447a-1bdb-810735523290.png)

最もlift値が高い組み合わせは、「ham」と「white bread」の組み合わせであることが分かりました。
「ハム」と「パン」の組み合わせですので、サンドイッチでも作るのでしょう。

上位20個の組み合わせを見ると、

>[3]  {citrus fruit, other vegetables, whole milk}   => {root vegetables} 
>[5]  {root vegetables}                              => {herbs}
>[7]  {root vegetables, other vegetables}            => {onions}
>[8]  {citrus fruit, pip fruit}                      => {tropical fruit}

など、野菜同士の組み合わせや、果物同士の組み合わせなどが多いことが分かりました。
組み合わせ自体は「発見」といえるほどの組み合わせではありませんが、多くのお客さんが、野菜や果物を単品ではなく、色々とセット購入するという結果からは、「フルーツバスケット」などの商品を作ると売れるかもという示唆が得られると言えます。

また、少し面白いルールとして
>[17] {beef, other vegetables}                       => {root vegetables} 

「牛肉とその他野菜を購入したお客さんは、根菜類を一緒に買う傾向がある」というルールは面白い組み合わせだと感じました。

根菜類ですので、ステーキに付け合せるにんじんなどでしょうか？

ちなみに、ステーキの付け合せににんじんが選ばれる理由には、にんじんに含まれるカロテンが油と一緒に摂取すると吸収が良くなるからという説があるようです。
カロテン（ビタミンＡ）は、のどや鼻の粘膜を丈夫にし、細菌に対して免疫力を高める効果があるようなので、これからの時期、風邪予防にもなりますね。
こういったトピックを売り場で展開するのも、インストアマーケティングとしては面白いと思いました。

話は少しそれましたが、バスケット分析は、たとえ「発見」といえるような結果が得られなくても、抽出されたルールを見ていくと、販促のヒントが得られることが分かります。

本記事ではここまでとしますが、バスケット分析は前件部などの条件を変えれば、いろいろなルールが抽出できますので、引き続き試してみようと思います。
ReactHookFormでプルダウンの一覧にない項目を追加できるようにする。

## はじめに
表題通り、プルダウンの一覧にない項目を追加できるようにしていきます。
プルダウンの一覧にある場合は一覧から選択し、ない場合は新規で作れるようにするのが本実装の目的です。

## 成果物
![react_hook_form_free_solo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/8f5ce290-d474-d763-e606-c09009307f64.gif)

```tsx:src/FreeSolo.tsx
import React, { useState } from "react";
import { useForm, Controller } from "react-hook-form";
import { Autocomplete, TextField } from "@mui/material";

type FormValues = {
	country: string;
};

const defaultOptions = [
	"アメリカ",
	"イギリス",
	"カナダ",
	"日本",
	"アメリカ合衆国",
];

export default function MyAutoCompleteForm() {
	const { control, handleSubmit } = useForm<FormValues>();
	const [options, setOptions] = useState(defaultOptions); // 初期の選択肢
	const [inputValue, setInputValue] = useState("");

	const onSubmit = (data: FormValues) => {
		alert(`選択した国: ${data.country}`);
	};

	return (
		<form onSubmit={handleSubmit(onSubmit)}>
			<Controller
				name="country"
				control={control}
				defaultValue=""
				render={({ field }) => (
					<Autocomplete
						sx={{ width: 300 }}
						{...field}
						freeSolo // 自由入力を許可
						options={options}
						inputValue={inputValue}
						onInputChange={(_, newInputValue) => {
							setInputValue(newInputValue); // 検索バーの入力値を更新
							if (!options.includes(newInputValue) && newInputValue !== "") {
								// 新しいラベルを追加して表示
								setOptions([...defaultOptions, `"${newInputValue}" を追加`]);
							} else {
								setOptions(defaultOptions); // 既存の選択肢にリセット
							}
						}}
						onChange={(_, newValue) => {
							// 新しい値が選択されたときの処理
							if (typeof newValue === "string" && newValue.startsWith('"')) {
								// "新しいラベル" を選択した場合、新しい値を設定
								const addedValue = newValue.replace(/"| を追加/g, ""); // エスケープを削除
								field.onChange(addedValue);
							} else {
								field.onChange(newValue);
							}
						}}
						renderInput={(params) => <TextField {...params} label="国" />}
					/>
				)}
			/>
			<button type="submit">送信</button>
		</form>
	);
}

```
:::note info
freeSoloを入れるだけで良いんですね😊
意外と簡単！！ReactHookFormは扱いやすくて良いですね！！！
:::


## 終わりに
思ったより簡単な実装ですね。
AWS EC2インスタンスのUbuntu初期セットアップガイド



AWS EC2インスタンスでUbuntuをセットアップした際に最初に行うべき基本的なステップについて解説します。これらの手順は、セキュリティと安定性を確保するための基本設定となります。

## 1. SSHでEC2インスタンスに接続

まず、SSHキーを使用してインスタンスに接続します。

```bash
ssh -i /path/to/aws-tikeda-access-key.pem ubuntu@your-ec2-public-ip
```

## 2. パッケージの更新

最初に、すべてのパッケージを最新の状態に更新します。これにより、セキュリティパッチやバグ修正が適用されます。

```bash
sudo apt update && sudo apt upgrade -y
```

## 3. ファイアウォールの設定 (UFW)

UFW (Uncomplicated Firewall) を有効化してセキュリティを強化します。基本的には、SSH（ポート22）、HTTP（ポート80）、HTTPS（ポート443）を許可します。

```bash
sudo ufw allow OpenSSH
sudo ufw allow 'Apache Full'
# 必要に応じて他のサービスも許可
sudo ufw enable
```

## 4. ユーザー管理とSSH設定の強化

セキュリティを強化するため、`ubuntu`ユーザー以外の新しい管理ユーザーを作成し、sudo権限を与え、公開鍵認証のみでSSHログインを許可する設定に変更します。

```bash
sudo adduser newuser
sudo usermod -aG sudo newuser
```

その後、`/etc/ssh/sshd_config`ファイルを編集し、パスワード認証を無効にし、ルートログインも禁止します。

```bash
sudo nano /etc/ssh/sshd_config
```

以下のように設定します：

```plaintext
PermitRootLogin no
PasswordAuthentication no
```

変更を保存したら、SSHを再起動します。

```bash
sudo systemctl restart ssh
```

## 5. タイムゾーンの設定

サーバーのタイムゾーンを設定します。

```bash
sudo timedatectl set-timezone Asia/Tokyo # 例: 東京時間に設定
```

## 6. 自動アップデートの設定 (オプション)

セキュリティアップデートを自動でインストールする設定を行います。

```bash
sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
```

## 7. スワップファイルの設定 (必要に応じて)

メモリが少ない場合、スワップファイルを設定して仮想メモリを利用できるようにします。

```bash
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo bash -c 'echo "/swapfile none swap sw 0 0" >> /etc/fstab'
```

これで基本的なセットアップが完了です。セキュリティと安定性が向上し、AWS EC2インスタンス上のUbuntuを安全に運用する準備が整いました。
非スーパーユーザでも Docker コマンドを実行する方法

# 非スーパーユーザでも Docker コマンドを実行する方法

https://www.docker.com

## はじめに

はじめまして。私は大学院生です。

この記事では、非スーパーユーザでも Docker コマンドを実行する方法について紹介します。

この記事が、「Docker を使って、開発する手助けになった」と思ってもらえるように書かせていただきます。

## 現在の置かれている状況

現在、私がスーパーユーザで、後輩が一般ユーザです。弊研究室の方針に従い、この状況を変えることなく、Docker コマンドを使えるようにしたいです。

## 手順

### `docker` グループにユーザを追加する

Docker には `docker` グループがあり、このグループにユーザーを追加することで、そのユーザが `sudo` なしで Docker コマンドを実行できるようになります。

以下の `qiita` を追加したい人のユーザに変更することで、`docker` グループにユーザを追加することができます。

```bash
sudo usermod -aG docker qiita
```

`usermod` コマンドの `-aG` オプションは、`-a` と `-G` の二つから構成されています。

`-a`：既存のグループに対して新しいグループを追加します。これを付けないと、ユーザが指定したグループ以外の他のグループから削除されてしまいます。つまり、ユーザを新たなグループに追加する際に必ず必要となるオプションです。

`-G`：指定されたグループのリストにユーザを追加します。このオプションは、グループ名（または複数のグループ名）を指定します。

### ユーザセッションの再起動

ユーザを `docker` グループに追加した後、セッションを再起動するか、ログアウトして再ログインすることで変更が有効になります。

あるいは、`newgrp docker` コマンドを実行することで、変更を反映できます。

## 追加した一般ユーザのできること

### Docker コマンドの実行

`docker` グループにユーザーを追加すると、`sudo` なしで Docker コンテナの起動や停止、イメージのビルドなど、一般的な Docker コマンドは実行できるようになります。例えば、`docker run` や `docker ps` などの基本的な Docker 操作が実行できます。

### ネットワーク設定

Docker の独自ネットワークを作成したり管理する操作は、`docker` グループに追加されていれば `sudo` なしで実行可能です。ただし、システム全体のネットワーク設定（Docker 外の設定）は依然として `sudo` 権限が必要です。

## おわりに

この記事では、`docker` グループにユーザを追加することで、非スーパーユーザでも Docker コマンドを実行できるようになりました。

この記事が、「Docker を使って、開発する手助けになった」と思ってもらえたら幸いです。
引数指定時に条件判定

こんにちは、新人エンジニアの三上です。

今回は、Kotlin の実装時に便利だと感じた機能を共有させていただきます。

## 引数
以下のような関数があるとする。
引数を渡すことで、それを「resultDto」に詰めて返す関数である。

```kotlin:関数
    fun createResult(
        code: String, 
        result: String? = null
    ): resultDto {
        return resultDto(
            resultCode = code,
            resultMessage = result
        )
    }
```

上記の関数に引数を渡す際に、条件分岐を設けることが可能である。
以下に具体的な実装を示す。

```kotlin:関数
    fun funcReturn(
        code: String, 
        result: String? = null, 
        resultSuccess: Boolean? = false
    ): resultDto {
        return createResult(
            code,
            if (resultSuccess == true) resultSuccess else null
        )
    }
```

上記のように関数の外側ではなく、引数部分に条件分岐のif ~~文~~ 式を記載することができる。
分岐の中で関数を呼ぶ必要が無いため、コード量が削減できる。


## まとめ
分岐の中で同じ関数を引数を変えて呼び出すような場合には、今回紹介した機能を使ってみて欲しい。

以上、三上でした。

（2024/10/21）ご指摘を受けて、if 文を if 式と修正しました。
Microsoft Certified: Azure AI Engineer Associate(AI-102) 合格記

## はじめに
AI102に合格したので，勉強法と当日の環境について記載します．スコアは8割と少しでした．

- 筆者について
    - 普段はpythonを書いているデータエンジニア
    - 直近はアプリケーションエンジニア
    - AWSはなんとなく理解している
    - AI-900, AZ-900, DP-900, SC-900取得済み

## 試験日程について
2024年9月に受験しました．
テストセンターもしくは自宅で受験か，どちらかを選択可能です．
筆者はテストセンターで受験しました．受験申込時に会場と時間の候補から都合の良い場所と時間を選択できます．
予約上，試験時間が2時間もあるため，社会人の方は土曜or日曜に受験することになります．

## 学習方法
### 1.Microsoft Learn
概要の学習のために，Microsoft learnのAI-102のDesiginig and Implementing a Microsft Azure AI Solutionを読みました．
概要をさらうだけでよいので，Microsoftの推奨学習時間の半分ぐらいで進めました．

***読む際は日本語版のパス(ja-jp)ではなく英語版(en-us)を開いて，google翻訳で英日に翻訳したり，戻したりして読みました．***

正直な所，Azure全体として，日本語化のセンスがイマイチなので，サービス名やステータス名は日本語で頭に入れていくよりも，英語の方が勘所を押さえやすい気がします．

### 2.Microsoft 認定資格のプラクティス評価
Microsoft Learnを一通り抑えた後には，Microsoft公式の問題を解きました．こちらは難易度としては，優しめのモノが多いので，8割程度解けるようになっていることが理想的だと思います．

### 3.Udemyの模擬試験
他の記事では推奨されている問題集が2,3種類あると思いますが，私はこちらを使用しました．

[AI-102 Azure AI Engineer 100% Original Practice Exam FEB'24](https://nttls.udemy.com/course/ai102-azure-practice/)

上記の問題集を2周やりました．1周目が6割程度のスコア，2周目が8割程度でした．


### 4.模擬試験などの学習の補助
Microsoft Learnのdocsを適宜参照しました．英文の方が情報量が多いため，基本的に英語で参照していました．試験当日も本サイトは参照することができます．***ただし，試験当日は試験予約時に選択した言語でしかdocsを閲覧できないので注意です．*** （できたよ！って方はコメントお願いします）

## 試験について
- 最初にプログラミング問題の穴埋めのための言語を選択する
    - python or C# が選択可能
- 試験は基本的に4択問題
- 選択肢をドラッグアンドドロップして穴埋めする問題あり
- 最後の3～4問はケース問題
    - 難易度としては通常の問題と変わらない
    - この問題だけは一度回答すると再回答できない
    - この問題以外の見直し/回答変更はできる
- Microsoft Learnは試験中いつでも開ける
    - ブラウザで見られる画面と同じ
    - Learn外へのアクセスはできない
    - Learn内でも言語設定などにはアクセスできない

プログラミング言語は，型宣言の関係で問題文の記述量が多いC#の方が解きやすいのではないかと推測しています．（私はpythonで受験しましたが，回答を意図的に分かりにくくする意地悪な変数名や分かりにくい記載方法は無かったので変わらないのかも？）

また，learnは試験時間中いつでも開くことができますが，それぞれの問題に対して，learnを開いて検索しても時間が足りないので，事前の傾向分析や対策は必須だと思います．
### 最後に
AOAIの名目で利用が拡大しているAzureですが，当然，本試験では，OpenAI以外の機械学習系のコンテンツも含まれています．

特にRAGの構築方法については，知っていなければ合格は難しいと思うので，重点的に学習した方がよさそうです．

取得価値については，まだなんとも言えませんが，MLで解決する案件に対して，Azure上で簡単に解決できるか？程度は判断できそうです．
GraphRAGパッケージ: ナレッジグラフを活用したGenAIの加速

注意: この記事は、Neo4jのブログ記事「[GraphRAG Python Package: Accelerating GenAI With Knowledge Graphs](https://neo4j.com/blog/graphrag-python-package/?utm_source=Twitter&utm_medium=OrganicSocial&utm_campaign=GenAI-KG--&utm_ID=&utm_term=&utm_content=-Blog--&utm_creative_format=&utm_marketing_tactic=&utm_parent_camp=&utm_partner=&utm_persona=)」を元に、機械翻訳を利用して作成した備忘録的な内容です。正確性を確保するため、原文と照らし合わせてチェックすることをお勧めします。とくに**コードのところは原文のほう**を見てください。**概要、構成、雰囲気を掴む**ために読んでください。

https://neo4j.com/blog/graphrag-python-package/?utm_source=Twitter&utm_medium=OrganicSocial&utm_campaign=GenAI-KG--&utm_ID=&utm_term=&utm_content=-Blog--&utm_creative_format=&utm_marketing_tactic=&utm_parent_camp=&utm_partner=&utm_persona=

## はじめに

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/2b66e181-d4b4-971c-cf44-82dc19e857a9.png)

Neo4jのGraphRAGパッケージは、非構造化データからナレッジグラフの作成、ナレッジグラフの検索、そして完全なGraphRAGパイプラインまでをワンストップで提供するPythonパッケージです。このツールは、知識ベースのアシスタント、検索API、チャットボット、レポートジェネレーターなどの開発に役立ちます。

## GraphRAGの概要

GraphRAGは、ナレッジグラフとRetrieval-Augmented Generation (RAG)を組み合わせることで、大規模言語モデル（LLM）の幻覚などの問題を解決し、ドメイン固有のコンテキストを追加することで、従来のRAGアプローチよりも質と効果を向上させます。

## GraphRAGパッケージの主な機能

1. ナレッジグラフの構築
2. データ検索
3. GraphRAGパイプラインの実行

### 1. ナレッジグラフの構築

SimpleKGPipelineクラスを使用して、以下の要素を指定するだけで自動的にナレッジグラフを構築できます：

- Neo4jへの接続ドライバー
- エンティティ抽出用のLLM
- テキストチャンクのベクトル化用の埋め込みモデル

オプションで、グラフスキーマやプロンプトテンプレートも指定可能です。

```python
from neo4j_graphrag.experimental.pipeline.kg_builder import SimpleKGPipeline

kg_builder = SimpleKGPipeline(
   llm=ex_llm,
   driver=neo4j_driver,
   embedder=embedder,
   from_pdf=True
)
await kg_builder.run_async(file_path='example.pdf')
```

### 2. データ検索

GraphRAGパッケージは、以下を含む複数の検索クラスを提供しています：

- Vector Retriever: ベクトル埋め込みを使用した類似性検索
- Vector Cypher Retriever: ベクトル検索とCypherクエリを組み合わせたグラフ走査
- Hybrid Retriever: ベクトル検索とフルテキスト検索の組み合わせ
- Text2Cypher: 自然言語クエリをCypherクエリに変換

例えば、Vector Retrieverは以下のように使用できます：

```python
from neo4j_graphrag.retrievers import VectorRetriever

vector_retriever = VectorRetriever(
   neo4j_driver,
   index_name="text_embeddings",
   embedder=embedder
)

results = vector_retriever.get_search_results(query_text="How is precision medicine applied to Lupus?", top_k=3)
```

### 3. GraphRAGパイプラインの実行

GraphRAGクラスを使用して、簡単にGraphRAGパイプラインをインスタンス化し実行できます。最小限の設定では、LLMと検索機能を指定するだけで済みます。

```python
from neo4j_graphrag.generation.graphrag import GraphRAG

rag = GraphRAG(llm=llm, retriever=vector_retriever)
response = rag.search("How is precision medicine applied to Lupus?")
print(response.answer)
```

## まとめ


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/0af2f878-c91d-23c3-0633-acfb285be713.png)

GraphRAGパッケージは、ナレッジグラフを活用したGenAIアプリケーションの開発を大幅に簡素化します。非構造化データからナレッジグラフの作成、高度な検索機能、そして完全なGraphRAGパイプラインまでを提供し、Neo4jの専門知識がなくても利用可能です。

詳細なドキュメントやチュートリアルも提供されているので、GraphRAGを使った開発に興味がある方は、引用元の記事を参照ください。
Markdown Preview Enhanced で Tikz が動かなかった

## TL;DR
- `Markdown Preview Enhanced`でコードチャンクを使うと、`tikz`などの図を表示することができる。
- Windowsなら`pdf2svg+texlive`をインストールし、PATHを通す(再起動も必要だった)。[^1]
- 日本語を含まないパスにする。
- `latex {cmd=true}`に`latex_zoom=xx`や`latex_width=xx`、`latex_height=xx`を追加する。

## 概要

Markdown Preview Enhanced は、VSCode で Markdown ファイルをプレビューするすごい拡張機能です。

マークダウンの文中で
```latex
$$
\begin{equation}
\frac{d}{dt}\left(\frac{\partial L}{\partial \dot{q}_i}\right) - \frac{\partial L}{\partial q_i} = 0
\end{equation}
$$
```
のように書くと、以下のように表示できます。
$$
\begin{equation}
\frac{d}{dt}\left(\frac{\partial L}{\partial \dot{q}_i}\right) - \frac{\partial L}{\partial q_i} = 0
\end{equation}
$$

しかし、この状態では`mathjax`のみが動くため、`tikz`などの図を表示することができません。

そこで、`Markdown Preview Enhanced`の設定から、`markdown-preview-enhanced.enableScriptExecution": true`として次のコードチャンクを追加します。

```javascript
> ```latex {cmd=true}
> \documentclass{standalone}
> \begin{document}
>   Hello world!
> \end{document}
> ```
```
(ただし、左端の`>`は不要です。)

するとプレビュー画面でコードにマウスを持っていくと実行ボタンが現れ、しばらく待つとTexのコードが画像に変換されて表示されるはずです。

しかし、うまくいきませんでした。

## エラーの解決

まず、次のようなエラーが出ました。
```bash
'pdf2svg' �́A�����R�}���h�܂��͊O���R�}���h�A
����\�ȃv���O�����܂��̓o�b�` �t�@�C���Ƃ��ĔF������Ă��܂���B
```

これはおそらく`pdf2svg`が存在しないことを表しています。
[ここ](https://shd101wyy.github.io/markdown-preview-enhanced/#/ja-jp/code-chunk?id=latex)を参考にして、`pdf2svg`をインストールしPATHを通してください。(PATHを通したあとパソコンの再起動をしないと反映されませんでした。（なぜ？）)

次に、このようなエラーが出ました。
```bash
Unable to open file
```

この場合、マークダウンファイルのパスに日本語が含まれている可能性があります。日本語を含まないパスに変更してください。

次に、このようなエラーが出ました。
```bash
EntryNotFound (FileSystemError): Error: ENOENT: no such file or directory, open <filepath>
```

この場合、`latex {cmd=true}`に`latex_zoom=xx`や`latex_width=xx`、`latex_height=xx`を追加してください。[^1]

[^1]: https://github.com/shd101wyy/vscode-markdown-preview-enhanced/issues/1180

これで晴れて、図を表示することができます。
```javascript
>  ```latex {cmd=true, latex_zoom=300%, hide=true}
>  \documentclass{standalone}
>  \usepackage{tikz}
>  \begin{document}
>    \begin{tikzpicture}[samples=100]
>      \draw[->,>=stealth,semithick] (-0.3,0)--(2,0) node[right]{$x$};
>      \draw[->,>=stealth,semithick] (0,-0.3)--(0,3) node[above]{$y$};
>      \draw (0,0) node[below left]{O};
>
>      % 過剰和を赤色、不足和を青色で示す
>      \foreach \x in {0.0, 0.2, ..., 1.6}
>        \filldraw[fill=red!20] (\x,0) rectangle (\x+0.2,{max(\x*\x,(\x+0.2)*(\x+0.2))});
>        
>      \foreach \x in {0.0, 0.2, ..., 1.6}
>        \filldraw[fill=blue!20] (\x,0) rectangle (\x+0.2,{min(\x*\x,(\x+0.2)*(\x+0.2))});
>
>      \draw[domain=-0.3:1.85] plot(\x,{\x*\x});
>    \end{tikzpicture}
>  \end{document}
>  ```
```
のように書くと、次のように表示されます。

![3e5fb921af0fde5e584c517699df029f_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840768/abce2bd1-432f-4eec-5e68-200fbc4be7fc.png)
【初心者向け】何行くらいになったら関数化するの

## はじめに

何行くらいになったら関数化するの？という質問をされたので少し考えてみました

調べてみると難しい用語も出てきますが、私の言葉で一言で言うならこういうことです

行数が短く済むなら良いことだけどそこは本質ではない。「関数名で関数内の処理を説明しきれているか？」そうでないなら抽出したほうがいいかも

## 具体例

以下の関数は行数的にはそんなに長くないですけど

```javascript
const checkXXX = (xxx) => {
    const errors = [];
    if (チェック処理1) {
         errors.push("チェック処理1に失敗しました");
    }
    if (チェック処理2) {
         errors.push("チェック処理2に失敗しました");
    }

    let errmsg = "";
    for (const err of errors) {
        errmsg += "<li>" + err + "</li>";
    }
    
    if (errmsg) {
        return "<ul>" + errmsg + "</ul>";
    }
    return "";
};
```

「チェックする関数だよね～どんなチェックをしてるのかな？」と思ってこれを見に来た人は「チェック以外のこともやってるんかい！」って思ってしまうかもしれません＞＜
でもこういうソースよく見かけます
せっかくに見に来てくれた人をがっかりさせたら良くないよ、1つのことに絞ろう

## こんなのはどうでしょうか

```javascript
const checkXXX = (xxx) => {
    const errors = [];
    if (チェック処理1) {
         errors.push("チェック処理1に失敗しました");
    }
    if (チェック処理2) {
         errors.push("チェック処理2に失敗しました");
    }

    return errors;
};

const createListHTML = (textList) => {
    // 略
}

const 呼び出し元 = () => {
    const errors = checkXXX(xxx);
    const errHTML = createListHTML(errors);
}
```

どうですか？チェック処理を見に来た人は、「チェック処理だなぁ～」って思うんじゃないでしょうか
しかも読みやすくなったどころか、なんと抽出した関数の汎用化にも成功していまして（本題ではないのでカット）

## おわり

人間が読むんですから、読みやすいかどうかは人によって違いますよね
皆さんならどう書きますか？
どうやったら読みやすくなるかなって考えながらプログラミングするのはとても楽しいですよ（　＾ω＾）・・・
いいリファクタのやり方を閃いたらぜひ共有してみてください
AWS S3にSQSを全部出力するLambda書いてみた

### AWS SQS

Python で記載
```
import boto3
import json
import os

# クライアントを作成
sqs_client = boto3.client('sqs')
s3_client = boto3.client('s3')

def process_sqs_queue_to_s3(queue_url, bucket_name):
    """指定されたSQSキューの全メッセージをS3に保存する関数"""
    processed_count = 0
    while True:
        response = sqs_client.receive_message(
            QueueUrl=queue_url,
            MaxNumberOfMessages=10,
            WaitTimeSeconds=10
        )

        if 'Messages' not in response:
            break

        for message in response['Messages']:
            message_body = message['Body']
            s3_key = f"messages/{message['MessageId']}.json"
            s3_client.put_object(
                Bucket=bucket_name,
                Key=s3_key,
                Body=json.dumps({"message_body": message_body})
            )
            sqs_client.delete_message(
                QueueUrl=queue_url,
                ReceiptHandle=message['ReceiptHandle']
            )
            processed_count += 1

    return processed_count

def lambda_handler(event, context):
    # キューリストとS3バケット名を環境変数から取得
    queue_urls = os.environ['SQS_QUEUE_URLS'].split(',')
    s3_bucket_name = os.environ['S3_BUCKET_NAME']

    total_processed = 0

    for queue_url in queue_urls:
        processed_count = process_sqs_queue_to_s3(queue_url.strip(), s3_bucket_name)
        total_processed += processed_count
        print(f"Queue {queue_url} processed {processed_count} messages.")

    return {'statusCode': 200, 'body': f"Total {total_processed} messages processed from all queues."}


```
環境変数 SQS_QUEUE_URLS にすべてのキューURLをカンマ区切りで入力（例: https://sqs.region.amazonaws.com/123456789012/Queue1,https://sqs.region.amazonaws.com/123456789012/Queue2
【UE5/C++】取り込んだサウンドをキー入力でオブジェクトから再生する

# はじめに
UE5 に取り込んだ音源を C++ で再生する。
特定のキーを押したとき再生できるようにする。
座標をオブジェクトと同じ位置にし、指向性を持たせる。

# C++ クラスを作る
Unreal Editor で右クリック > New C++ Class > Actor > Create Class

```PlaySound.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Sound/SoundBase.h"
#include "PlaySound.generated.h"

UCLASS()
class GAME_API APlaySound : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	APlaySound();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

private:
	UPROPERTY(EditAnywhere, Category = "Sound")
	USoundBase* SoundToPlay;
};
```
```PlaySound.cpp
#include "PlaySound.h"
#include "Kismet/GameplayStatics.h"

// Sets default values
APlaySound::APlaySound()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	
}

// Called when the game starts or when spawned
void APlaySound::BeginPlay()
{
	Super::BeginPlay();
}

// Called every frame
void APlaySound::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	// Play sound if v key is pressed
	if (GetWorld()->GetFirstPlayerController()->WasInputKeyJustPressed(EKeys::V))
	{
		if (SoundToPlay)
		{
			UGameplayStatics::PlaySoundAtLocation(this, SoundToPlay, GetActorLocation());
		}
	}
}
```
# 再生する音源を入れる
Unreal Editor 上にドラッグアンドドロップするだけで、UE 内で使えるように変換される。なので複雑な手順は不要。

# 再生するデータをセットする
PlaySound クラスを Level にドラッグアンドドロップし、Outliner 内にある PlaySound の Details を編集する。
コード内 `UPROPERTY(EditAnywhere, Category = "Sound")` で設定した変数、この画像の Sound to Play に再生するファイルをセットする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348896/2890048f-5b2c-b27d-d706-9ec8bcefa9d7.png)

# 実行して再生してみる
`if (GetWorld()->GetFirstPlayerController()->WasInputKeyJustPressed(EKeys::V))` このコードで V キーを押したとき、音がセットされていれば再生できるようになっている。
なので、実行後に V キーを押すとセットした音が流れる。(音量注意)

# BP クラス化して座標を変える
今作ったクラスを右クリック > Create Blueprint class based on PlaySound を選択し、格納するパスを指定して Create Play Sound Class を押す。
Level に Cube を配置し、先ほど作った BP クラスを Cube 配下に設置、すると Cube の位置から音源が流れる。

※ 音源は BP クラス内でセットしておくこと。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348896/cfefa5e6-e070-4e33-d802-01d5de271605.png)


## 指向性と距離減衰がない場合
もし、指向性や距離減衰がない場合は、取り込んだ音源ファイル をダブルクリック後 `Attenuation Setting` を変更する。もし設定が何も存在しない場合は、新規アセットを自分で生成し、割り当ててあげるといい感じになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348896/d6b3b1c7-09a2-c765-95eb-a274b969ff0e.png)
【Mac】コマンドで動画をGIFに変換する方法

動画をGIFに変換するには `ffmpeg` コマンドを使用します。

https://ffmpeg.org

## インストール

以下のコマンドを実行してインストールします。

```terminal
brew install ffmpeg
```

https://formulae.brew.sh/formula/ffmpeg

## 使用方法

以下のようにコマンドを実行するとMP4をGIFに変換できます。

```terminal
ffmpeg -i input.mp4 output.gif
```

### フレームレートを指定する

フレームレートを指定するには `-r` を使用します。

```terminal
ffmpeg -i input.mp4 -r 10 output.gif
```

上記の場合、フレームレートは 10 fps になります。

### 開始時間・終了時間を指定する

開始時間や終了時間を指定するには `-ss` および `-t` を使用します。

```terminal
ffmpeg -ss 00:00:00.000 -i input.mp4 -t 00:00:15.000 output.gif
```

上記の場合、開始時間は 0 秒、終了時間は 15 秒となります。
Herokuについて

Herokuとは？概要と使い方に関する記事
Herokuは、Salesforceが提供するクラウドプラットフォームで、Herokuを使うことで、インフラの管理に煩わされることなく、WebアプリケーションやAPIのデプロイ、運用、スケーリングが簡単に行えます。


# 1. Herokuの特徴と主な機能
**1 Herokuの特徴**
シンプルなデプロイ：Gitコマンドで簡単にアプリケーションをHerokuにデプロイ可能。
多言語対応：Node.js、Python、Ruby、Java、Go、PHPなど、さまざまなプログラミング言語をサポート。
スケーラビリティ：負荷に応じてアプリケーションをスケールアップ・ダウンできます。
アドオンの利用：データベース（PostgreSQLやRedis）、モニタリングツール、認証機能など、様々なアドオンを追加可能。
無料プランあり：学習用やプロトタイプの構築に使える無料プランを提供。

**Heroku1.2 主な機能**
Gitによるデプロイ：git pushを使ったシンプルなデプロイ方法。
CI/CDのサポート：継続的インテグレーション（CI）とデプロイの自動化が可能。
Heroku CLI：コマンドラインからHerokuの操作を行うツール。
アドオンマーケットプレイス：Redis、PostgreSQL、Papertrailなど、便利なアドオンを簡単に追加可能。
# 2. Herokuの導入とアプリケーションのデプロイ
Herokuを使ったアプリケーションのデプロイは非常に簡単です。以下の手順に沿って進めてみましょう。

**2.1 Herokuアカウントの作成**
Heroku公式サイト にアクセスし、無料のアカウントを作成します。
メール認証を完了し、アカウントの設定を行います。

**2.2 Heroku CLIのインストール**
Heroku CLIは、コマンドラインからHerokuを操作するためのツールです。以下のコマンドでインストールします。

Windows/Mac: Heroku CLI公式ページからインストーラをダウンロードし、インストール。
Ubuntu/Debian:
```bash
curl https://cli-assets.heroku.com/install.sh | sh
```

**2.3 Herokuへのログイン**
インストール後、以下のコマンドを実行し、Herokuにログインします。

```bash
heroku login
```
ブラウザが開き、ログインを求められます。ログインが成功すると、CLIでHerokuを操作できるようになります。

**2.4 Herokuアプリの作成とデプロイ**
1. Gitリポジトリの初期化
プロジェクトフォルダに移動し、Gitリポジトリを初期化します。

```bash
git init
```

**2. Herokuアプリの作成**
Heroku上に新しいアプリを作成します。

```bash
heroku create アプリ名
```
これで、Heroku上にアプリケーションの環境が準備されます。URLが発行され、ブラウザでアクセスできるようになります。

**3. アプリのデプロイ**
アプリケーションをHerokuにデプロイするためには、git add と git push を使います。

```bash
git add .
git commit -m "Initial commit"
git push heroku main
```

**4. アプリケーションの起動確認**
デプロイが成功したら、以下のコマンドでアプリのURLを表示します。

```bash
heroku open
```
これで、Herokuにデプロイされたアプリケーションがブラウザで確認できます。

# 3. Herokuでのデータベース利用
Herokuでは、PostgreSQLが標準でサポートされており、アドオンとして簡単に追加できます。

**3.1 PostgreSQLの追加**
以下のコマンドで、PostgreSQLアドオンをアプリケーションに追加します。

```bash
heroku addons:create heroku-postgresql:hobby-dev
```

**3.2 データベースの接続情報取得**
以下のコマンドで、データベースの接続情報を取得します。

```bash
heroku config:get DATABASE_URL
```

**3.3 マイグレーションの実行**
アプリケーションのモデルをデータベースに反映するため、マイグレーションを実行します。
```bash
heroku run python manage.py migrate
```

# 4. Herokuのアドオンと拡張機能
Herokuは、多くのアドオンをサポートしており、アプリの機能を簡単に拡張できます。

**4.1 代表的なアドオン**
Heroku Redis：Redisキャッシュの導入
Papertrail：ログのモニタリング
SendGrid：メール送信サービス
New Relic：パフォーマンスモニタリング

**4.2 アドオンの管理**
アドオンを確認するには、以下のコマンドを使用します。

```bash
heroku addons
```

アドオンの削除には、以下のコマンドを使います。
```bash
heroku addons:destroy アドオン名
```

# 5. Herokuのスケーリングと運用
**5.1 アプリのスケーリング**
Herokuでは、アプリのプロセス（Dyno）をスケールアップ・ダウンすることができます。

スケールアップの例:
```bash
heroku ps:scale web=2
```
このコマンドは、Web Dynoを2つにスケールアップします。

**5.2 ログの確認**
アプリの実行状況やエラーを確認するには、以下のコマンドでログを取得します。
```bash
heroku logs --tail
```

# 6. HerokuのCI/CDパイプラインの設定
Herokuでは、GitHubと連携してCI/CDパイプラインを構築することができます。

**6.1 GitHubとの連携**
HerokuアプリとGitHubリポジトリを連携するには、以下の手順を実行します。

Herokuダッシュボードにアクセス。
アプリの「Deploy」タブを開き、GitHubとの連携を設定。
自動デプロイの設定を有効にする。

**6.2 自動デプロイの設定**
GitHubのブランチに変更が加わるたびに、Herokuが自動的に最新のバージョンをデプロイするように設定できます。

# 7. まとめ
Herokuは、アプリケーションのデプロイや運用を簡単にする強力なPaaSプラットフォームです。特に、開発者がインフラ管理に時間を割くことなく、アプリケーションの開発に集中できる点が大きな魅力です。

Herokuの主な特徴として、簡単なデプロイ、スケーラビリティ、豊富なアドオンの利用が挙げられます。また、無料プランも提供されているため、プロトタイプ開発や学習目的にも適しています。

これからアプリケーションをクラウドに展開したいと考えている方は、Herokuをぜひ活用してみてください。
毎日更新していますので、@y-t0910をフォローしていただけると嬉しいです。
【AWS】Lambda(python3.11)でSlack通知を行うCloudformationテンプレート

# 概要
AWS Lambdaを使ってSlackチャンネルへ通知を行うCloudFormationテンプレートを作成しましたので、紹介いたします。

# CFnテンプレート

```yaml
  BatchLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.lambda_handler
      Role: !GetAtt LambdaExecutionRole.Arn
      FunctionName: sample-function
      Runtime: python3.11
      Environment:
        Variables:
          SLACK_WEBHOOK_URL: !Sub ${SlackWebhookURL}
      Code:
        ZipFile: |
          #!/usr/bin/python3.11
          import json
          import os
          import urllib3

          def lambda_handler(event, context):
              slack_webhook_url = os.environ.get("SLACK_WEBHOOK_URL")

              message = {
                  "text": "HERE IS YOUR MESSAGE!!"
              }

              http = urllib3.PoolManager()
              response = http.request(
                  "POST",
                  slack_webhook_url,
                  body=json.dumps(message).encode('utf-8'),
                  headers={"Content-Type": "application/json"}
              )

              return {
                  "statusCode": response.status,
                  "body": response.data.decode('utf-8')
              }

```

### コードの補足

SlackチャンネルのIncoming webhookは事前に作成し、パラメータ`SlackWebhookURL`として設定しておいてください。Roleも適切な権限のものを記載してください。

ランタイムのpythonのバージョンは`3.11`にしています。
※2024年10月現在、管理コンソールから確認すると`3.7`（2023年6月EOL）は当然ですが既にサポート対象外になっていました（`3.8`は2024年10月EOLなのでこれももうすぐ）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/24b0a24c-0e27-5afe-d2ea-e8d2cbebce5f.png)

`urllib3.PoolManager()`では、HTTPリクエストを管理するためのプールマネージャを作成しています（`urllib3`はHTTP通信を扱うためのPythonライブラリ）。 そして、`PoolManager`オブジェクトの`request`メソッドを呼び出して、HTTPリクエストを送信（＝SlackのWebhook URLに対してPOSTリクエストを送信）、という流れです。

今回は`POST`を利用していますが、`('GET', url)`といった形で指定すればGETリクエストを送信できます。

最後の`return`文は、Lambda関数の戻り値です。
上記では特にログ出力していないですが、ログに残したい場合は`print`文を使用すればOKです。

### 通知の流れ

EventBridgeルールで「xxのステータスがxxになったら」などと条件指定し、ターゲットを上記にすれば特定の条件下のみ動くルールにすることができます。

また、SNSトピックを利用したりアラームで閾値を設定することも可能です。

以前似た記事としてこちらも作成したのでご参考までに。

https://qiita.com/Ryo-0131/items/50a6e9e094f9efa6b512
CodeWars オススメ問題 #7

# はじめに

個人的に好きなアルゴリズム学習サイト「CodeWars」の問題をシェア。

週1くらいのペースで、全10回を目指す予定。

:::note
CodeWarsはいいぞ！の紹介は[こちら](https://qiita.com/kohki_takatama/items/2ae2808b931e943262b8)

CodeWarsの始め方は[こちら](https://qiita.com/javacommons/items/7c473cda7825ab99e08c
)
:::

今回もTypeScriptに挑戦してみようと思います。

簡単な問題を解きながら、TSに慣れていきたい。
# オススメ問題

https://www.codewars.com/kata/5502c9e7b3216ec63c0001aa/typescript

### 問題
Number「年齢」と「ハンディキャップレベル」が与えられる。
両方とも基準より大きい場合`"Senior"`、そうでない場合は`"Open"`を返す。

```ts
input =  [[18, 20], [45, 2], [61, 12], [37, 6], [21, 21], [78, 9]]
output = ["Open", "Open", "Senior", "Open", "Open", "Senior"]
```
### 難易度
分類は 7kyu です。
前回の 8kyu から少しステップアップしながら、TSのお作法を学ぼうと思います。

# オススメの回答
「評価が高い回答」の中から、学びの多い回答をピックアップしてご紹介。

:::note
<details><summary>模範解答</summary>

```ts
export function openOrSenior(data:number[][]):string[]{
  return data.map(x => x[0] >= 55 && x[1] > 7? 'Senior': 'Open')
}
```

使われているのは、主に `map` と 三項演算子 ですね。

`map`は、与えられた配列の中の要素ひとつひとつに対して処理をするためのメソッドです。
今回は、引数`[[age1, handicap1], [age2, handicap2], ...]`の、それぞれの`[age, handicap]`を操作するために使われています。

三項演算子は、ざっくり言えば`if else`の短縮形です。
`true or false ? trueの場合 : falseの場合`という形で書かれています。
今回は、`x[0]`つまり`age`が55以上の時、かつ（`&&`）、`x[1]`（`handicap`）が7より大きい時に、`"Senior"`と返し、それ以外では`"Open"`と返しています。

---

アルゴリズムとは関係ありませんが、Number型のネストされた配列は、`number[][]`と表すのですね。

</details>
:::





:::note
<details><summary>1行の解答</summary>

```ts
export const openOrSenior=d=>d.map(x=>x[0]>54&&x[1]>7?'Senior':'Open')
```

いかに短くするかだけを求めた答えです。
- アロー関数を使い1行で書いている（`function` / `return` といった記述が不要）
- 引数`data`を`d`として少しでも短くしようとしている
- 「55以上」（`x[0] >= 55`）を、少しでも短くするため`x[0]>54`と書いている
（真似しないほうがいい書き方）
- とにかく余白を削り、可読性を犠牲にして短さを求めている

個人的には、美しさのない短さだと思いますが、ここまでつきぬけているのは好ましくも思います。
</details>
:::

# おわりに
以上、CodeWarsオススメ問題でした。


オススメ問題・解法など、ぜひコメントお待ちしております！
XAMPPのPHPを8.0→8.2にバージョンアップ

## バージョンアップを行う理由
Larave10を使うにはphp8.1以上が必要なため、XAMPPのPHPをバージョンアップ（8.0→8.2）することに。

[こちらの記事](https://zenn.dev/ritton/articles/66e01b8567f75a)を参考に、php8.2をダウンロードしてきてXAMPPのPHPを入れ替えることにした。

## 手順通りやったがうまくいかない
PHP公式サイトのダウンロードページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1830892/03bdf6d9-1cb4-bbf6-212e-947a8ddcea8f.png)

ダウンロードするPHPについて、参考記事には「『Non Thread Safe』でよいっぽい。」とあったが、「Non Thread Safe」をダウンロードし以降の手順を進めたところ、私の環境ではXAMPPのApatcheが起動しなかった。

### 問題1: httpd-xampp.confの指定と実際のPHPモジュールの不一致
Chat GPTに質問し以下の回答を得る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1830892/5b916943-7844-900b-ca52-b0c570d00b01.png)


httpd-xampp.confの該当箇所を確認すると以下のようになっていた。
しかし実際にはxampp/php内にphp8ts.dllはなく、**php8.dll**が入っていた。
```
LoadFile "C:/xampp/php/php8ts.dll"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1830892/9f811b81-12ce-321f-94f1-7c0b04eafd99.png)

そのため、httpd-xampp.confに合わせる形で、「Thread Safe」版をダウンロードし直すことにした。

### 問題2: browscap.ini
Apacheのerror.logに「C:\xampp\php\extras\browscap.iniが存在しないか、PHPが参照できていない。」ことが示されていた。
確認すると該当ファイルが存在しなかったので、元のphpフォルダからbrowscap.iniをコピーして配置した。

## 無事、バージョンアップ完了
最終的になんとかPHPをバージョンアップし正常にApatcheを起動できるようになった！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1830892/0b03546d-3a3c-ef1b-9863-ebee47e13d31.png)



## 参考リンク一覧
- [PHPのバージョンを更新したい！with.XAMPP](https://zenn.dev/ritton/articles/66e01b8567f75a)
SourceTreeのファイルステータスでファイル一覧が何故だか出なくなった時

# ある日突然、SourceTreeのファイルステータスでファイル一覧が出なくなった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21645/2db17676-5b0f-3d52-b5de-f33a0b985247.png)

ファイルを選択できないので、複数ファイルの差分があっても表示されるのは1ファイルのおそらく先頭の差分のみで、めちゃめちゃ不便・・・。

PC再起動しても変わらず。
色んな設定をいじってみても変わらず。
SourceTreeのバージョンが最新だったので、古いのに変えても変わらず。

# 突然の解決

色いじり回して、ふと `ファイルステータス → 右クリック → リセット...` を選択したら、その瞬間出るようになった。
それで開いた画面では何もしていない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21645/c0520db5-4960-6b7f-f1d2-f403aa2a2834.png)

# わいだけ？

いくらググってもChatGPTに聞いてもそんな事例は見つからず。
もしかしたらレアな不具合だったのかもしれないが、そんなレアモノに遭遇したら是非試してみてほしい。
GAS で開発をしてみての留意点など雑多なまとめ

GAS (Google Apps Script) について何も知らなかった私が簡単な開発を通してポイントだな、詰まったなという点を雑多に上げさせていただきます

# 1. 実行に際して制限がある (2024/10/16 確認時点)
https://developers.google.com/apps-script/guides/services/quotas?hl=ja

以下のあたりが GAS に関して主な制限事項かと思いますので列挙
（漏れがあったら申し訳ございません）

|  | 機能 | 無料版 | 有料版 | 補足など |
|:-----------|:-----------|:------------|:-------------|:-------------|
|  | スプレッドシートの作成 | 250ファイル/日 | 3200ファイル/日 | GAS に関係なくそもそもスプレッドシートの作成個数に制限有り |
| ★ | トリガーの合計実行時間 | 90分/日 | 6時間/日 | 時間指定、ファイルを開いた時点などをトリガーに設定できる<br>利便性が高いからこそ乱用しないように項目は注意が必要に思う |
| ★ | トリガー | 20 / スクリプト | 20 / スクリプト | 同上。<br>トリガーを手動で管理している場合には気づけるかもしれないが、自動でトリガー設定している場合には実行済みのトリガーの削除をしないとこの制限事項に引っかかる恐れがある |
| ★ | Apps Script プロジェクト | 50件/日 | 50件/日 | GAS 自体もプロジェクト数に制限がある |
| ★ | スクリプトランタイム | 6分/実行 | 6分/実行 | 有料無料に違いなし<br>大規模であれば注意 |
| ★ | カスタム関数ランタイム | 30秒/実行 | 30秒/実行 | 同上 |
| | 1 日あたりのメール受信者 | 100人/日 | 1500人/日 | GAS の実装でメール送信可能なため |
| | メール本文のサイズ | 200KB/メッセージ | 400KB/メッセージ | 同上 | 


# 2. アクセス権限まわりはちゃんと確認する必要がある

https://qiita.com/STSHISHO/items/f2ce468ab78682c26699

* こちらの記事のような承認作業が対象の GAS の実行時に表示されます
    * デプロイした GAS の Web アプリも例外でなく他の人に使ってもらう際にはこの点を伝えておく必要がある

## スプレッドシート自体のアクセス権限にも注意
* スプレッドシート自体の共有権限も適切に変更しておかないと、スクリプトでスプレッドシートが参照できずエラーになるので注意が必要
    * 「何かシートを参照して値を書き加えたい」など定番な処理には対応が必須

# 3. `<base target="_top">`は必須
`<base target="_top">`という記述が HTML ファイルの `<head>`内に必須

* デベロッパツールで要素を確認してみると一目瞭然なのですが自分の構築した画面はあらゆるフレームの中の一つとして表示されているようでこの記述が必須となっている
    * `<base target="_top">`で画面いっぱいに表示されるようになる
    * この記述が無いと画面上に表示されない

# 4. 自動保存が無いのでこまめに保存が大事
* 自動保存機能がないため手動でのソースコードの保存が必要
    * ローカルで環境構築すれば解決する
* 自分も保存し忘れてデプロイ内容に反映されないなどで余計な手間がかかったりしてしまったので注意

---
### 参考資料など

https://developers.google.com/apps-script/guides/services/quotas?hl=ja

https://qiita.com/STSHISHO/items/f2ce468ab78682c26699
Java 学習記録 3日目

# 目的
この記事は以下の記事の続きです。

https://qiita.com/banana877_it/items/508f661746b0fd19a908

Javaを学習するC言語使い一年目エンジニアのノートです。
先日コードの色つけ方法を教えていただいたので、これからどんどん使っていきます！

# 前回の復習
前回の復習をさらっと。
前回は変数について学習を行いました！
```java
// 特別な注釈がない限りコードはJavaです。
class Main {
  public static void main(String[] args) {
      // 前回までの学習で出てきた型は3つ
      int n = 877;    // 整数型
      String s = "BaNana";    // 文字列型
      double f = 8.77;    // 浮動小数点型
      System.out.println(n);
      System.out.println(s);
      System.out.println(f);
      // 整数型と小数点型の四則演算
      System.out.println(n+23);
      System.out.println(f-0.76);
      // 文字列の連結なんかも。
      System.out.println(s+n+".it");

      // 値の変更
      n = 87;
      System.out.println(n);
      // 自己代入
      n = n + 13;
      System.out.println(n);
      // 自己代入の省略形。
      n -= 10;
      System.out.println(n);
      // インクリメントとデクリメント
      n++;
      f--;
      System.out.println(n);
      System.out.println(f);
  }
}
```
おさらいできたところで今日も頑張りましょう！

# 今日も頑張る
### 自動型変換
変数は違う型同士だと代入したり足し算したりできません。
それでも
`8 + 0.77`
とかの計算をしたいときもあるでしょう。
そんなときに型変換を使うのです（この辺もC言語と同じだ）
しかし、Javaには自動的に型変換してくれる機能がある模様……。
```java
class Main {
  public static void main(String[] args) {
    int month = 8;
    int date = 7;
    double temperature = 35.2;

    /* ここで自動型変換。
       変数はすべて数値型だが
       " + "は同じ型同士でしかできないので、
       すべて文字列型に変換されている */
    System.out.println(month + "月" + date + "日は" + temperature + "度です");

    // int型同士の計算はint型
    System.out.println(5 / 2);    // 2が出力される
    // double型同士の計算はdouble型
    System.out.println(5.0 / 2.0);    // 2.5が出力される
    // int型とdouble型だとdouble型に自動型変換される
    System.out.println(5 / 2.0);    // 2.5が出力される   
  }
}
```
1日目とかのコードでさらっと使ったのも自動的な型変換だったんですね。
Javaすごい……（C言語のこともよくわかってない）
#### ごちゃついてるのでかるくまとめ
* `System.out.println();`内で数値と文字列を連結すると自動的に文字列型に変換される
* int型で答えが少数になる計算をしても、小数点以下は切り捨てられる
* int型とdouble型で計算すると自動的にdouble型に変換される

### 強制型変換
うん、C言語とほとんど同じでした。
さっきは自動でやってくれてましたが、どうしてもint型同士の計算結果をdouble型にしたいこともあるでしょう。
そんな時は強制的に型変換をしてしまいましょう。
こちらはサラッとコードを書いて終わります。
やりかた
`(型名)変換したい値`
`(double)877`
```java
class Main {
  public static void main(String[] args) {
    int a = 5;
    int b = 2;

    System.out.println((double)5 / 2);    // 2.5が出力される
    System.out.println((double)a / b);    // 2.5が出力される
  }
}
```
そういえばキャストとかいう言い方があったな……（今思い出した）

# おわりに
今日は教材の都合でまとめはここまで！
明日も投稿できるように頑張ります！
【基本情報】独学マラソン データマイニング Day 16

「人生の嘘」を否定しよう
アドラー心理学

:::note worn
この記事は自分用の備忘録です。
:::

# マイニングといえば、ビットコイン
ビットコイン（仮想通貨）のマイニングとは、自分のパソコンを使って、仮想通貨の取引に必要となる複雑な計算処理に協力し、その成功報酬として仮想通貨を得ること

パソコンつけっぱで放っておいたらお金が増えていくという夢のような怪しい話

まぁなんか採掘してるんだなーというイメージが掴めたらOK

# データマイニングとは

### 膨大な量のデータを見てアハ体験をすること。

めっちゃわかりやすい表現だった

https://wa3.i-3-i.info/word15759.html

たくさんのデータを集めて、分析して、その中から規則性を見つける感じかな

小学校の算数や理科の授業みたいだ

# データマイニングの手法
### 決定木（Decision Tree）
木構造のモデルでデータを階層的に分岐させ、最終的な結果を導き出す手法
条件に基づいてデータを分割しながら進むため、直感的に理解しやすい

![スクリーンショット 2024-10-21 20.40.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736578/e44d0182-4144-0c92-477a-29bf7a38f0a8.png)

診断テストにありそうなやつ

### クラスタリング（Clustering）
データを類似性に基づいてグループ化する手法
ラベル付けされていないデータに適用し、パターンや傾向を見つけ出す

![スクリーンショット 2024-10-21 20.42.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736578/fad538df-1ba8-5060-ddc1-01e7e3c4e28f.png)

ブレインストーミングでグルーピングするイメージに近い気がする

### アソシエーション分析（Association Analysis）
データ間の関連性やパターンを発見する手法
支持度（Support）、信頼度（Confidence）、リフト値（Lift）の3つを割り出して分析する

![スクリーンショット 2024-10-21 20.53.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736578/b4f30b12-1157-24d5-dfad-c6c85ef2ccd6.png)

コンビニ経営のゲームで売上伸ばす時にこういうの考えてた懐かしい

# 感想
こういうのもっと学校教育で活用した方がいいと思ったが
現実は時間がなくて単発の活動になり、分析結果を次に活かせないんだろうなぁ


# 参考

https://gmo-research.ai/research-column/association-analysis

https://aismiley.co.jp/

https://wa3.i-3-i.info/word15759.html
すべての HTTP リクエストを右から左へ受け流す Web サーバ

チャラチャッチャッチャラッチャ～♪[^youtube]

[^youtube]: [ムーディ勝山 - 右から来たものを左へ受け流すの歌](https://www.youtube.com/watch?v=BgyS6I3zXfc)

届いたすべての HTTP リクエストを何も手を加えずに右から左へ受け流すだけの Web サーバを Python + aiohttp で作った。誰得？

``` python:main.py
from os import getenv

from aiohttp import ClientSession, web

UPSTREAM = getenv("UPSTREAM")
if UPSTREAM is None:
    raise Exception("UPSTREAM is required")


async def handler(request: web.Request):
    headers = {**request.headers}
    del headers["Host"]
    async with ClientSession() as session:
        async with session.request(
            request.method,
            f"{UPSTREAM}{request.path_qs}",
            headers=headers,
            data=await request.read(),
        ) as upstream_response:
            response = web.StreamResponse(
                status=upstream_response.status,
                headers=upstream_response.headers,
            )
            await response.prepare(request)
            async for chunk in upstream_response.content.iter_chunked(1024):
                await response.write(chunk)
    return response


app = web.Application()
app.add_routes([web.route("*", "/{_:.*}", handler)])

if __name__ == "__main__":
    web.run_app(app)
```

``` console
$ UPSTREAM=https://api.example.com/v1 python main.py
```

単に HTTP リクエストを流すだけであれば Nginx を使うなどしてリバースプロキシすればよいのだが、Python スクリプトとして書いておくことで通信内容を読み取ったり手を加えたりすることができて便利。