OmniAICreator/Qiita-1.07M huggingface dataset:
【jQuery】const, let, varの違い

# constとは
`const`は定数を宣言するために使用されます。一度値が代入されると、その値は変更できません。また、再代入ができないため、定数としての値が変更されないことを保証します。
# letとは
`let`は変数を宣言するために使用されます。再代入が可能です。変数のスコープが宣言されたブロック内に制限されます。これにより、グローバルスコープでの変数の汚染を防ぎます。
# varとは
`var`は古いバージョンのJavaScriptで変数を宣言するために使用されますが、ES6以降では let と const が推奨されています。ブロックスコープを持たず、関数スコープであるため、ブロック内で宣言されても関数の先頭に巻き上げられます。
# それぞれの違い
| 　          | const       | let          |  var         |
|:-----------|:------------:|:------------:|:------------:|
| 再宣言      | 不可能        | 不可能         | 可能
| 再代入      | 不可能      | 可能       | 可能
| スコープ     | ブロックスコープ        | ブロックスコープ         | 関数スコープ
| 繰り返し構文  | 不可能          | 可能           | 可能
### 再宣言、再代入
再宣言は一度宣言した変数名で再度宣言すること。再代入は値が入っている変数に上書きで代入することです。

varは再宣言と再代入のどちらも可能で、constはどちらも不可能。letは再代入できるものの、再宣言できないという違いがあります。
### スコープ
スコープとは、宣言した変数を利用できる範囲のことです。letとconstはブロックスコープという、ブロックごとに作られるスコープ内で利用できます。
```js
var hoge = 1

if (hoge === 1) {
  var num1 = 'varの値は1です';
  let num2 = 'letの値は2です';
  console.log(num1);
  console.log(num2);
}
console.log(num1);
console.log(num2); // ここでエラーが発生
```
letに代入した値をif関数のブロック内で出力した内容は反映されますが、ブロックで出力した内容はエラーになります。varはブロックスコープではないので、if文の外で出力しても反映されます。

varは関数のブロック内でのみ利用できる関数スコープや、全てのスコープからアクセスできるグローバルスコープに該当します。
### 繰り返し処理
繰り返し処理は指定した条件と回数に該当する間、決められた処理を繰り返すことです。JavaScriptではfor文やwhile文が該当します。

繰り返し処理は宣言した変数に数字の再代入を繰り返すことで反復処理するため、letとvarでは利用できます。反対に、再代入できないconstは利用できません。
```js
for (let i = 0; i < 5; i++) {
  console.log(i);
}
console.log("--end--");

for (const j = 0; j < 5; j++) { // ここでエラーが発生
  console.log(j);
}
```
letを指定したfor文は正常に動作しますが、constでは変数への代入に関するエラー文が表示されます。constは再代入できないため、最初に代入した0のみ正常に表示されるのです。

例外として、for…inやfor…ofのように配列の内容をループするたびにブロックスコープが作られる場合、constを利用できます。
# 使い分け方
### 基本はconstで定義する
JavaScriptの変数宣言は、letやvarに比べてconstがおすすめです。constは再宣言と再代入ができないため、意図せず値を書き換えることによるエラーを未然に防ぐことができます。

### 繰り返し構文のみletを定義する
繰り返し構文では、ブロックスコープなので管理がしやすいletの利用が適しています。letは再代入ができて再宣言できないため、varに比べて変数宣言でエラーする可能性を減らせるのが特徴です。

### varは使わない方がよい
varはJavaScriptで使える変数の中で最も影響範囲が広いのが特徴です。さまざまな場面で利用できる反面、意図しない再宣言や再代入によってエラーにつながる可能性があります。

また、varを使うと変数名や再代入をチェックする範囲が広くなります。ブロックスコープであるletやconstであれば、ブロック内のみチェックすれば良いので見る範囲を短縮できます。
文字列の重複を取り除く

文字列の重複を取り除くプログラムを***Python3***で実装しました。

```python
input_line = input()
array1 = []
for i in input_line:
# 文字列iが配列に含まれているか確認する
    if i not in array1:
        array1.append(i)
        print(i,end="")
```
[CAIレシピ] 待機ステップによるスリープ処理

## はじめに

待機ステップを利用することで、実行中の処理を一時的に停止できます(`プログラミングにおけるSleep処理`)。この記事では次のポイントを確認します。

- 待機ステップとは
- 待機ステップの利用と動作確認
- 待機ステップの留意事項

なお、この記事は次の記事の内容を理解していることを前提としています。

- [はじめてCAIを使う際に](https://qiita.com/shunsuzu/private/12b8dbd08a30efa0003a)
- [プロセスの作成と実行(匿名認証と基本認証)](https://qiita.com/shunsuzu/private/01d91caedb92bd7781ea)
- [割り当てステップと、各種変数フィールドの利用](https://qiita.com/shunsuzu/private/fae696539cd245828848)

## 待機ステップとは

待機ステップを利用すると、CAIプロセスの実行を任意のステップ位置で待機(Sleep)できます。待機方法には次の2つのタイプがあります。

- 特定の時間 ... 指定 __時刻__ まで待機する
- 待機期間後 ... 指定 __時間__ (例えば30秒)が経過するまで待機する

## 待機ステップの利用と動作確認

### CAIプロセスの作成

次の手順では、プロセス起動時の時刻を取得、待機ステップにより10秒待機後の時刻取得して、2つの時刻を呼び出し元に返すCAIプロセスを作成しています。

1. CAIプロセスを次の設定で作成します。
    - 名前を __recipe-pca-stepWaitSleep__ とする
    - __匿名アクセス__ を許可する
    - __クラウドサーバー__ にデプロイする
1. 出力フィールドとして __output1__ と __output2__ を __タイプ=テキスト__ で定義します。
1. CAIプロセスが次の順に実行されるように各種ステップを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074553/52d68ba4-819b-05dc-5ee8-1998fc3ca48e.png)

1. 各割り当てステップで、それぞれの出力フィールド __output1__ と __output2__ に __計算式__ として `fn:current-dateTime()` を指定します。この指定により、それぞれの出力フィールドに現在時刻が設定されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074553/902cc693-f776-cd45-c546-f8c022076031.png)

1. 待機ステップの各プロパティを次のように設定します。
●続行 = 待機期間後
●待機期間 = 10 秒
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074553/44acc6d0-1547-dbd6-59f4-12d447335345.png)

### CAIプロセスの実行

以下、curlコマンドを例とした動作確認結果です。output1とoutput2に10秒の差異が確認できます。

```:curlコマンドと実行結果
// curl コマンド
curl https://<IICS・CAIサーバー>/active-bpel/public/rt/<Org ID>/recipe-pca-stepWaitSleep

// 実行結果(見やすいように整形しています)
{
"output1":"2024-02-04T21:59:16.045Z",
"output2":"2024-02-04T21:59:26.048Z"
}
```

## 待機ステップの留意点

CAIプロセスのデプロイ先を __クラウドサーバー__ としている場合、設定変更できない __95秒のタイムアウト動作__ に留意します。通常、CAIプロセスの実行は処理完了後に実行結果を返す同期モードですが、このタイムアウトが発生するとCAIプロセスは非同期モードに切り替わりHTTP 500をレスポンスとして返します(この例で `938917518365007872` はCAIのプロセスID)。

```:タイムアウト時の動作
$ curl https://<IICS・CAIサーバー>/active-bpel/public/rt/<Org ID>/recipe-pca-stepWaitSleep | jq

{
  "error": {
    "code": 500,
    "message": "Timeout waiting for reply from process ID 938917518365007872 (recipe-pca-stepWaitSleep)."
  }
}
```

次のKBはタイムアウト動作に関する技術情報です。

- [HOW TO: Avoid timeouts while triggering any process built using process developer or Cloud Application Integration (CAI)?](https://knowledge.informatica.com/s/article/552590?language=en_US)

非同期モードとして実行されたCAIプロセスのステータスを確認するには、次の記事で紹介しているREST APIを利用します。

- [実行済みCAIプロセスのステータス取得](https://qiita.com/shunsuzu/private/08d434246a4767ce6de7)

## 参照

- [Qiita - IICS CAIの実装レシピ - マスターページ](https://qiita.com/shunsuzu/private/3d1971ef6e3b993516aa)
データレプリケーションにMirrorMaker 2.0を使うべき5つの理由

<font color="Grey">*[5 reasons why you should be using MirrorMaker 2.0 for data replication](https://aiven.io/blog/5-reasons-why-you-should-be-using-mirrormaker-2)の翻訳です。*</font>

2021年10月6日

# データレプリケーションに MirrorMaker 2.0 を使うべき 5 つの理由

Apache Kafka®でデータをレプリケートする？いい考えですね！MirrorMaker 2.0を使うべき5つの理由をお読みください。

[MirrorMaker](https://aiven.io/kafka) 2.0 は、[Apache Kafka®](https://aiven.io/blog/what-is-apache-kafka) 用の堅牢なデータレプリケーションユーティリティです。このユーティリティは、複数のKafkaクラスタのコンシューマおよびプロデューサとして機能するため、ユーザはクラスタ間で簡単かつ確実にデータをコピーすることができる。これにより、Kafka中心のアーキテクチャの耐障害性が向上します。


## Apache Kafkaクラスタのデータを複製する理由


Apache Kafkaは一時的にデータを保存するだけで、その意味では[本当のデータベースではない](https://aiven.io/blog/apache-kafka-and-the-great-database-debate)。では、なぜその一時的なデータのレプリケーションを気にする必要があるのでしょうか？


なぜなら、Apache Kafkaクラスタ間のデータレプリケーションは、コアデータインフラに柔軟性、パフォーマンス、信頼性を追加することができるからです。特に膨大なデータ量を持つ大企業は、この恩恵を受けることができます。


### 1.ディザスタリカバリ


Apache Kafkaクラスタ間でデータをレプリケートしたい場合、最も理解され、最も重要なシナリオは[ディザスタリカバリ](https://aiven.io/blog/data-and-disaster-recovery)です。多くの企業がデータインフラの要としてApache Kafkaに依存している。Apache Kafkaは成熟しており、信頼性が高く、信頼できるプロバイダーによって提供されていますが、それでも災害は起こりうるものであり、データが一時的に利用できなくなったり、完全に失われたりすることがあります。


リスクを軽減する最善の方法は、データのコピーを別のデータセンターの別のKafkaクラスタに置くことです。そうすることで、比較的シームレスにクライアントを切り替えることができ、サービスの中断を最小限に抑えながら、その場で代替のデプロイメントに移行することができる。


MirrorMaker2は、コンシューマのオフセットマッピングを保持し、クラスタ間でコンシューマをほぼ透過的に移行するためのツールを提供します。これは、ディザスタリカバリを成功させる鍵となります。


### 2.クラウドへの移行


Apache Kafkaクラスタをオンプレミスからクラウドに移行する企業が増えている。あるクラウド地域やプロバイダーから別のクラウドへ移行する段階にある企業もある。


データサービスのクラウド移行をサポートするツールは、データをよりコントロールしやすくします。Kafkaクラスター間のデータ複製は、ダウンタイムの少ないKafkaクラウド移行に最適な選択です。


### 3.より身近に


多くのグローバル・ビジネスでは、地理的に分散した場所でデータを作成・利用することが珍しくありません。レプリケーションを利用することで、ユーザがいる場所にデータを持ち込むことができます。これにより、レイテンシとネットワークコストを削減し、最適なスループットを提供します。


### 4.データの分離


データセットによっては、法的、コンプライアンス、パフォーマンス上の理由から、別の Kafka クラスターに隔離する必要があります。


たとえば、法的な配慮が必要な場合、あるクラスタに書き込んでいるトピックの保持期間を制限し、読み取りがコンプライアンス上問題ないリージョンで保持期間を長くして別のクラスタにミラーリングすることができます。


パフォーマンスを向上させるには、1つのクラスターで受信データを一時的に保存し、それを集約して、集約されたデータのみを別のクラスターにミラーリングする。こうすることで、受信パイプラインをクリーンに保ちつつ、重要なビットを保持することができ、おまけにストレージスペースの節約にもなる。


### 5.データ分析


アグリゲーションはデータパイプラインの要素でもあり、分散したKafkaクラスタのデータを1つに統合する必要があるかもしれない。集約されたクラスターは、そのデータを他のクラスターやデータシステムにブロードキャストし、分析や視覚化を行う。


## Apache Kafka MirrorMaker は人生をより簡単にする


Kafka Connect を使用して Apache Kafka クラスタをレプリケートする場合、MirrorMaker2 はソースクラスタとターゲットクラスタのトピック構成 (パーティショニングを含む) と ACL を同期します。これを実現するための外部ツールはもう必要ありません。


レコードがセマンティックにパーティショニングされている状況では、レプリケーション中にパーティショニングが保持されることは良いことだ。


アクティブ・アクティブ・レプリケーションやチェーン・レプリケーションのような複雑なレプリケーション・トポロジーを設定するのは簡単だ。1つのMM2クラスタで複数のレプリケーションフローを実行でき、レプリケーションサイクルを防止するメカニズムも備えている。


## まとめ


Apache Kafka MirrorMaker2を使えば、様々な用途に使える堅牢なレプリケーションアーキテクチャが構築できる。[Aiven for Apache Kafka](https://aiven.io/kafka)のアドオンとして入手でき、Aivenに作業を任せることができます。


まだAivenのサービスをお使いではありませんか？<https://console.aiven.io/signup>から無料トライアルにお申し込みください！


また、[changelog](https://aiven.io/changelog)と[blog](https://aiven.io/blog)のRSSフィード、または[LinkedIn](https://www.linkedin.com/company/aiven/)と[Twitter](https://twitter.com/aiven_io)のアカウントをフォローし、製品や機能関連の最新情報をご確認ください。
【備忘録】マクロと同じフォルダにあるExcelファイルを開いて、データ数を取得し、マクロのシートに転記する。

マクロと同じフォルダにあるExcelファイルを開いて、データ数を取得し、マクロのシートに転記する。
・B列に連番、C列にデータが入力され、最終行に合計が記載されている
・合計行は転記しない

```
Sub 集計()
    
    Dim Path As String
    'このマクロのあるフォルダ
    Path = ThisWorkbook.Path
    
    Dim buf As String
    Dim ext As String
    
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    Dim fileName As String
    Dim wb As Workbook
    Dim ab As Workbook '開いたファイル
    Dim ws As Worksheet '開いたファイルの対象シート
    Dim lRow As Long '対象シートの最終行
    Dim ms As Worksheet '作業シート
    
    Dim msLCnt As Long '作業シート行数
    msLCnt = 1
    
    '作業シートを指定
    Set ms = ThisWorkbook.Worksheets("集計結果")
    
    'フォルダにある全てのファイルを取得
    buf = Dir(Path & "\*.*")
    Do While buf <> ""
        'フルパス
        fileName = Path & "\" & buf
        
        '拡張子取得
        ext = fso.GetExtensionName(fileName)
        
        '対象がExcelファイルだったら処理
        If ext = "xlsx" Or ext = "xls" Or ext = "XLSX" Or ext = "XLS" Then
        For Each wb In Workbooks
            If wb.Name = buf Then
                MsgBox buf & vbCrLf & "はすでに開いています", vbExclamation
                Exit Sub
            End If
        Next wb
        '対象ファイルを開く
        Set ab = Workbooks.Open(fileName)
        '対象シートの指定
        Set ws = ab.Worksheets(1)
        
        'B列最終行取得
        lRow = ws.Cells(Rows.Count, 2).End(xlUp).Row
        
        'メインシートに書き込み
        ms.Cells(msLCnt, 1).Value = buf 'ファイル名
        ms.Cells(msLCnt, 2).Value = ws.Cells(lRow-1, 2).Value '最終行-1の値を設定
        
        '対象ファイル閉じる
        ab.Close
        
        '作業シート行数カウントアップ
        msLCnt = msLCnt + 1
        
        End If
        buf = Dir()
        
    Loop
    
    MsgBox "完了しました"
      
End Sub

```
AtCoderで入青しました

## はじめに
こんにちは、Yoyoyo8128です！
昨日のARC171で初の黄色perfを出し、青コーダーになりました。

![スクリーンショット 2024-02-04 231700.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2972704/18d885fc-be99-d405-d6dc-a3a41198e3ed.png)

## 自己紹介
開成中学校の2年生です。
KCLCに入ってから中1の夏くらいからC++を勉強して競プロを始めました。
OMC : [Yoyoyo](https://onlinemathcontest.com/users/Yoyoyo)
X(Twitter) : [Yoyoyo8128](https://twitter.com/Yoyoyo8128)です。

## これまで
### 黒色時代
まず、コンテストに出る前、[APG4b](https://atcoder.jp/contests/APG4b)でC++を勉強しました。
JOI本選以降ではC++しか使えない、C++はPythonなどの他の言語よりも実行速度が短い、などの理由からC++で競技プログラミングをすることをおすすめしておきます。

### 灰色時代
仲のいいKCLCの人と勝負感覚でAtCoderに出てました。最初は仲間と一緒に切磋琢磨していくことでモチベーションになるとおもいます。
虚無埋めという過去の簡単な灰色問題(ABC-A,B)を埋めたりすることでここは簡単に乗り越えられると思います。

### 茶色時代
このあたりでTwitterをはじめ、同学年の他校の人と交流するようになりました。
開成には運動会という~~ゴミ~~行事があり、4,5月は放課後を練習のせいで潰されてしまうので、6月から部活が始まります。普通の学校は4月から部活が始まったりするので、競技プログラミングを本格的に始めるのが2,3か月遅くなります、~~本当にゴミだと思います。~~
なので、僕が茶色になるころには他校の強い人は緑とかでした。他校の人に追いつきたくてこのころは頑張っていた記憶があります。格上の人を目標にして精進するのはおすすめです。
入緑するまでにこれくらい精進をしました。

![スクリーンショット 2024-02-05 045510.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2972704/2bba7bc9-66b5-3df5-685c-6015628fe771.png)
この時はstreakを繋げるために頑張る、解けるまで寝ないなどの手段をとったりもしていました。あと、E869120さんの「アルゴリズム×数学」の本を使って精進したりもしていました。

### 緑色時代
緑色時代は、精進をほぼせず、茶色時代の精進が効いてレートが一瞬で伸びていきました。ほぼ印象に残っていないです。

![スクリーンショット 2024-02-05 050101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2972704/f6c79691-c46e-06c8-9be2-4ff3a6d83506.png)

### 水色時代
ここで、10か月近く停滞しました...
3月から5月はレートが伸びていって1400まで上がりました。ここからABCの重実装の精進から逃げていたら、ABCで緑perfや水下位perfを出してレートが下がり、ARC,AGCなどのコンテストで青perfを出してレートをちょっと上げてを繰り返していました。
12月くらいからABCをUnRatedで出てARCでちょっとずつ上げていくという戦法を取っていったらいつの間にかレートが200くらい上がって青色になっていました。こうならないようにしましょう。

### 履修したアルゴリズム(蟻本に載ってるアルゴリズム)
5段階評価でつけます。
|アルゴリズム名|理解度|
|:---:|:---:|
|全探索|4|
|ナップザックdp|5|
|桁dp|4|
|bitDP|4|
|UnionFind|5|
|BFS|5|
|DFS|5|
|素数判定|5|
|繰り返し二乗法|5|
|逆元|5|
|dijkstra|5|
|ワーシャルフロイド|5|
|最小全域木|5|
|二分探索|5|
|セグメント木|2|
|BIT|1|
|平方分割|3|
|行列累乗|5|
|フロー|1|
|平面走査|1|

です...

## 黄色に向けて
ABCの精進やセグメント木などのデータ構造を学んでABCで強くなって黄色になりたいです。あと、重実装がとても苦手なのでコードを書く練習をしたいと思います。

## 精進
精進を載せておきます。

![スクリーンショット 2024-02-05 053453.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2972704/ff766cfd-b863-fc82-5f76-0e81832b06c0.png)
2024/2/5主にITとかセキュリティの記事

生成AIのセキュリティリスクとは？具体的な問題や対策、過去に起きた事例を解説(2/3)
https://weel.co.jp/media/security-risk

「分散型エネルギーシステム」におけるサイバーレジリエンスの構築(2/2)
https://www.trendmicro.com/ja_jp/research/24/b/build-cyber-resilience-with-distributed-energy-systems.html

SNSと生成AIのあり方が問われた１週間　テイラー・スウィフトのAI偽画像が拡散→Xが検索不可→ホワイトハウスがコメント→Xも声明「同意なきヌードは許さない」(2/3)
https://ledge.ai/articles/deep-fake_images_of_taylorswift_spread

Bing AIとChatGPTはどちらを使うべき？違いからわかる活用方法(2/3)
https://www.sejuku.net/blog/236073

ランサムウェア「Black Basta」と提携する「Water Curupira」がマルウェア「Pikabot」によるスパム攻撃を展開(2/5)
https://www.trendmicro.com/ja_jp/research/24/b/a-look-into-pikabot-spam-wave-campaign.html

ウクライナ司令官が方針転換示唆　ドローンやサイバー攻撃重視へ(2/3)
https://mainichi.jp/articles/20240203/k00/00m/030/003000c
仮想通貨取引所に預けてる資産データを一括で全取得する

# 趣旨
botを作っていると取引所に預けてある自分の資産のデータが必要になることが多いので、全データを一括で取得するためのコードを準備しました。

先物と現物の資産額を取得するためのコードです。先物の部分はまだ用意している段階です。

# コード
fetchSpotBalance関数とfetchFuturesBalance関数に分けてコードを書いて、それらの関数を両方ともcheckAllBalances関数に入れています。
こうすることで1つの取引所のリストを代入して引数とするだけですべての現物資産と先物口座の資産が一挙に表示されるようになります。

```javascript checkBalances.js
const ccxt = require('ccxt');
const { apiKeys } = require('./configLoader');

async function fetchSpotBalance(exchangeId) {
    const exchangeClass = ccxt[exchangeId];
    const credentials = apiKeys[exchangeId];
    const exchange = new exchangeClass({
        apiKey: credentials.apiKey,
        secret: credentials.secret,
        password: credentials.password,
        enableRateLimit: true
    });

    try {
        const balance = await exchange.fetchBalance();
        console.log(`${exchangeId} Spot Balance:`, balance.total);
        return balance.total;
    } catch (error) {
        console.error(`Failed to fetch spot balance for ${exchangeId}: ${error.message}`);
    }
}

async function fetchFuturesBalance(exchangeId) {
    console.log(`Fetching futures balance is not implemented for ${exchangeId}.`);
}

async function checkAllBalances(exchanges) {
    for (const exchangeId of exchanges) {
        console.log(`Checking balances for ${exchangeId}...`);
        await fetchSpotBalance(exchangeId);
        await fetchFuturesBalance(exchangeId);
    }
}

const exchanges = ['binance', 'bitget', 'bybit'];
checkAllBalances(exchanges);
```

# config設定
config.jsonファイルを読み込むためのプログラムを別ファイルに保存してモジュール化しました。

```javascript configLoader.js
const fs = require('fs');

function loadConfig() {
    const configPath = './config.json';
    if (fs.existsSync(configPath)) {
        const configFile = fs.readFileSync(configPath, 'utf8');
        return JSON.parse(configFile);
    } else {
        console.error('Config file not found.');
        return null;
    }
}

const config = loadConfig();
if (!config) {
    console.error('Failed to load config, exiting...');
    process.exit(1);
}

const apiKeys = config.apiKeys.reduce((acc, item) => {
    acc[item.exchange] = item;
    return acc;
}, {});

module.exports = {
    apiKeys: apiKeys,
    loadConfig: loadConfig,
};
```
実際のconfig.jsonの中身は以下のように記述する必要があります。
```config.json
{
  "apiKeys": [
    {
      "exchange": "binance",
      "apiKey": "",
      "secret": ""
    },
    {
      "exchange": "okx",
      "apiKey": "",
      "secret": "",
      "password": ""
    },
    {
      "exchange": "bybit",
      "apiKey": "",
      "secret": ""
    },
    {
      "exchange": "bitget",
      "apiKey": "",
      "secret": "",
      "password": ""
    },
    {
      "exchange": "gate",
      "apiKey": "",
      "secret": ""
    }
  ]
}
```
個人でゲーム制作すること

ゲームエンジンなしでアクションゲーム開発をして考えたことのまとめです
# よほどの精神がないときつい
私はゲームを作るためにプログラミングをし始めました。
さて、プログラミング3か月で何が作れたでしょう?
1.絵が動き、音もなるそれっぽい物
2.音はならないが絵が動く物
3.アニメーションのない絵が左右に動かせるもの
4.四角が動かせる物

ゲーム制作経験とプログラミング経験がなかった私は、3か月かけて作ったのはたったの
4.四角が動かせる物
です。
嘘だろとなる人もいるでしょうが割とマジです。
知り合いに見せてもあまりいい反応は帰ってこないレベルです。
おそらく私が本気でゲームを作りたいとならなければ諦めていたでしょう。

# ソースコードは読みやすく
一人で開発するとはいえ、読みづらいソースコードは本当に精神によくないです。

私はインデントの意味が最初はわからず、すべて消してしまいました。プログラミングしたことがある人ならわかるでしょうが、ソースコードは地獄と化しました。「連続する中括弧閉じ、1つだけ足りなくてエラー」なんて起こったら精神に影響を及ぼします。

これは非常に極端な例ですが、おそらくほかのプログラマーも似たような経験はあるでしょう。

# ChatGPTは皆が思っているほど銀の弾丸ではない
おそらくChatGPTは聞いたことがあるでしょう。プログラムを書かせることもできますが、ChatGPTが多くのプログラマーの代わりになるという状況にはならないでしょう。

「銀の弾丸」というのは、「何が問題でもこれをすればいい」というような方法のことです。ChatGPTに聞くというのは一見「銀の弾丸」に似通ったものだと思う人もいるでしょうが、そんなにChatGPTには任せないほうがいいです。

例えば、空気抵抗ありの斜方投射を前記事にしましたが、あれはChatGPTには書けませんでした。ランバートの$W$関数を使って数式を書くことも指定しましたが、できませんでした。
# ググることはほぼ銀の弾丸
では、ChatGPTが頼りにならないなら、なにをするべきかといえば、ググるのです。とにかくググってください。人々はまだAIより賢いのでググってください。
New Relic APM を使ってアプリケーションのパフォーマンスを迅速に分析してボトルネックを解消！

# はじめに
　New Relic APM の Transactions を活用するとアプリケーションの中でどの処理の実行回数が多くて時間がかかっているのかをランキング形式で確認することができます。ランキングの中から対象の処理を特定したら、さらに詳細を深掘りして処理のボトルネックがどこにあるのかを分析していきましょう。今回はその分析をよりスムーズに実現するアップデート紹介します。

:::note info
最新のアップデートの詳細はこちら
[New Relic アップデート(2023年12月)](https://newrelic.com/jp/blog/nerdlog/new-relic-update-202312 "New Relic アップデート(2023年12月)")
[New Relic アップデート一覧](https://newrelic.com/jp/blog/nerdlog/new-relic-update  "New Relic アップデート一覧")
:::

:::note info
[New Relic株式会社のQiita Organization](https://qiita.com/organizations/newrelic)では、新機能を含む活用方法を公開していますので、ぜひフォローをお願いします。
:::

# トランザクショントレースのUIが新しくなった！
　New Relic APM では、トランザクショントレースでアプリケーションにおける単一のトランザクションのスナップショットを提供していて、トランザクショントレースは、関数、データベース、外部API等の呼び出しを記録しています。
　トランザクショントレースで収集されるデータは多岐に渡り、量も多いため、その分析には時間がかかっていました。しかし、今回のアップデートでトランザクショントレースのUIが刷新されたことで収集されたすべてのデータを理解し、根本原因をより迅速に分析するために必要な情報や洞察を提供できるようになりました。
 
## 円グラフでセグメント毎の処理時間や割合がわかる
　トランザクションのセグメント毎の割合が円グラフで表示されるようになり、セグメント毎の所要時間や実行回数といった集計値を表示するようになりました。単一トランザクションのボトルネックを見つける場合には Timeline の中から時間のかかっているセグメントを探す必要がありましたが、このUIを活用することで簡単にどのセグメントがボトルネックの候補なのかを選別できます。

![pie_chart.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/48d34c77-37c2-d828-9c65-bf2c032d751b.png)

## クリックすると対象のセグメントを表示
　一覧で表示されているセグメントをクリックすると対象のセグメント以外がグレーアウトされて表示されます。セグメントを選択するとそのセグメントのパフォーマンス情報や属性情報（ Request URL や SQL ）が表示され、セグメント単位での詳細な分析が可能です。このように一覧からセグメントを選択するだけでその詳細情報のシームレスな分析が実現できるように UI がアップデートされています。
 ![セグメント詳細.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/87402ac5-da56-1631-8c1f-583295b9e70b.png)

## 実行されたクエリの一覧をCSV出力
　トランザクションないで実行されたクエリの一覧も **Database queries** のタブで確認できます。クエリの情報だけではなく、処理時間や実行回数も確認できるようになっています。さらに今回のアップデートでこの画面に表示されている内容を CSV ファイルでダウンロードできるようになりました。障害の原因調査をしている場合には調査資料として添付したり、トランザクションないで実行されているクエリの種類が多い場合には、一覧性の高いExcel等で確認するのもよさそうです。
 ![SQL_Export.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/017fcd71-25f2-f33a-424f-d88e69392c9a.png)

# まとめ
　今回のアップデートには情報量の多いトランザクショントレースの中からボトルネックの根本原因を迅速に分析できる UI　の改善が多く含まれています。アプリケーションのパフォーマンス改善に新しくなったトランザクショントレースを活用してみてください。

:::note info
最新のアップデートの詳細はこちら
[New Relic アップデート(2023年12月)](https://newrelic.com/jp/blog/nerdlog/new-relic-update-202312 "New Relic アップデート(2023年12月)")
[New Relic アップデート一覧](https://newrelic.com/jp/blog/nerdlog/new-relic-update  "New Relic アップデート一覧")
:::
:::note info
[New Relic株式会社のQiita Organization](https://qiita.com/organizations/newrelic)では、新機能を含む活用方法を公開していますので、ぜひフォローをお願いします。
:::
WordPressでACFの値がプレビュー画面に表示されない問題の解決方法

## 原因
WordPressでは、投稿やページの編集履歴をリビジョンとして保存します。ACFを使用してフィールドの値を取得しようとすると、プレビュー時にACFが参照する投稿IDが編集中の投稿ではなく、リビジョン（または自動保存されたバージョン）になっている為、値の代わりにfalseが返されることがあります。

## 解決策
この不具合の対策として、プレビュー時に正しい投稿IDをACFに渡すためのカスタムコードをfunctions.phpに追加します。
```ruby:index.html
function fix_post_id_on_preview($null, $post_id) {
    if (is_preview()) {
        // プレビュー時は現在のポストIDを返す
        return get_the_ID();
    } else {
        // プレビューでない場合は、渡された$post_idを検証して返す
        $acf_post_id = isset($post_id->ID) ? $post_id->ID : $post_id;
        if (!empty($acf_post_id)) {
            return $acf_post_id;
        } else {
            return $null;
        }
    }
}
add_filter('acf/pre_load_post_id', 'fix_post_id_on_preview', 10, 2);
HHKBで気軽に尊師スタイルをする方法

# はじめに
簡単にいうと、Karabiner を使って、HHKBなどの外部キーボードをボードなしに尊師スタイルしようって話です。

これによって、外部キーボードを接続しただけで、自動的に内部キーボードを無効化することができます。

毎回、毎回新しいPCにするたび、忘れてしますのでメモとして残そうと思いました。参考になれば幸いです。

環境はMacOSです。

# Karabiner とは

Karabiner とは、 MacOS　Sierra 以降でキーボードカスタマイズができるOSS ツールです。
ダウンロードは公式ホームページを参照ください。↓

https://karabiner-elements.pqrs.org/

また、Karabiner の GitHub リポジトリは以下の通りです。↓

https://github.com/pqrs-org/Karabiner-Elements

# 設定方法
まず、公式ホームページでツールをインストールします。

初期設定をしたら、Karabiner の Devices から 自分が設定したい外部キーボードを選択します。

その中にある "Disable the built-in keyboard when external keyboard is connected" のスイッチを ON にします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/707293/8574dd55-8f0c-2d4f-f453-d299b4ce656b.png" width=100%>

これで、外部キーボードに接続している状態だと、内部キーボードは接続ができていないと思います。

## 参考文献
https://www.l08084.com/entry/2019/12/22/194228
【Excel関数】if関数で指定期間(日時)との比較

指定した期間との比較するための、関数記述
※判定結果を〇、×で表記する

=IF(AND(判定対象>=比較期間①,判定対象<=比較期間②),"〇","×")

参考:
https://nyanto.jimdofree.com/%EF%BD%B4%EF%BD%B8%EF%BD%BE%EF%BE%99%E9%96%A2%E6%95%B0-%E8%AA%AC%E6%98%8E/if%E9%96%A2%E6%95%B0%E3%81%A7%E6%9D%A1%E4%BB%B6%E3%81%AE%E7%9C%9F%E5%81%BD%E3%81%AB%E3%82%88%E3%81%A3%E3%81%A6%E8%BF%94%E3%81%99%E7%B5%90%E6%9E%9C%E3%82%92%E5%A4%89%E3%81%88%E3%82%8B%E8%89%B2%E3%80%85%E3%81%AA%E6%9D%A1%E4%BB%B6%E5%BC%8F%E3%81%AE%E6%8C%87%E5%AE%9A%E6%96%B9%E6%B3%95/%E6%97%A5%E4%BB%98%E7%AF%84%E5%9B%B2%E3%82%84%E6%9C%9F%E9%96%93%E3%82%92if%E9%96%A2%E6%95%B0%E3%81%AE%E6%9D%A1%E4%BB%B6%E5%BC%8F%E3%81%A7%E7%B0%A1%E5%8D%98%E3%81%AB%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B%EF%BC%92%E3%81%A4%E3%81%AE%E6%96%B9%E6%B3%95/
【Rust】MacでVSCodeでのLLDBのdebugが動かない

## 概要
少し久しぶりにRustを触ってみようかなと思ったら、なぜかVSCodeでのデバッグが動かなかったので対応をメモ書きします。

## 前提
* LLDBのバージョンは`1.10.0`です。
* MacのOSはSonoma14です。
* 使用したMacのPCはx86（Intel Mac）です。

## 対応
[Rust Analyzer Not Working in VSCode for Mac x86 with MacOS Sonoma 14.0](https://github.com/rust-lang/rust-analyzer/issues/15699)の記事の回答にある通り、LLDBのVSCode拡張の`debugserver`が悪さしているようです。`~/.vscode/extensions/vadimcn.vscode-lldb-1.10.0/lldb/bin/debugserver`のファイルを削除すれば動きました。
なお、この事象はIntel Mac限定で起きるものかもしれません。
【OCI】APEXで作成した表をDatabase Actionsで確認する方法

## はじめに
Oracle Cloud Infrastructure（OCI）のAutonomous Database (ADB)のAPEXで表を作成した際に、Database Actionsでユーザー名を選択して作成した表を確認しようとしても出てこない場合があります。
今回は、Database Actionsを用いてAPEXで作成した表を確認するときの注意点をご紹介します。

■前提条件
* ADBを作成してあること
まだ作成していない場合は、以下のチュートリアルをご覧ください。

https://oracle-japan.github.io/ocitutorials/adb/adb101-provisioning/

* APEXでワークスペースを作成し、表を作成してあること
今回は以下のチュートリアルを元に、ユーザー名を「TestADB」、表名を「Orders」としてAPEXで作成してあります。

https://oracle-japan.github.io/ocitutorials/adb/adb105-create-apex-app/#4-%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7%E3%83%BC%E3%83%88%E3%81%8B%E3%82%89%E7%B0%A1%E6%98%93%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E6%88%90

## APEXで使用されるユーザーについて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072173/3cc5b8d3-ab64-e2d2-ecde-a372c569772e.png)
APEXでは、最初にワークスペースを作成する際に、ワークスペース・ユーザー名を入力します。

ここで重要なのが、ここで入力したユーザー名を元に、<font color="red">**ワークスペースの管理者ユーザー**</font>と、<font color=#1e90ff>**データベースオブジェクトなどを保持するユーザー**</font>の2種類が作成されるという点です。

管理者ユーザー名はワークスペース作成時に入力したユーザー名になりますが、DBオブジェクトなどを保持するユーザー名は管理者ユーザー名の接頭辞に「**WKSP_**」を付けたものになります (WKSPはワークスペースの略)。

なので今回の場合だと、

ワークスペースの管理者ユーザー：TestADB
DBオブジェクトなどを保持するユーザー：WKSP_TestADB

という2つのユーザーが作成されます。

## APEXで作成した表をDatabase Actionで確認する
ここまでの説明でお気づきの方も多いと思いますが、APEXで作成した表はDBオブジェクトを保持するユーザーが所有しているので、Database Actionで参照すべきユーザーは「**WKSP_〇〇**」になります。

したがって、DataBase ActionsのSQLで、ユーザー名「WKSP_TestADB」を選択すると、APEXで作成した表の「Orders」がしっかりと表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072173/7f626cb2-6a68-68aa-5551-daef8d41f010.png)

逆に、ユーザー名「TestADB」を選択しても、作成した表は表示されません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072173/e9abfc8a-025d-c787-fb43-a756033556c1.png)

## おわりに
APEXを始める際に、APEXのユーザーとして、「**ワークスペースの管理者ユーザー**」と「**DBオブジェクトなどを保持するユーザー (WKSP_〇〇)**」の2種類が作成されることについて紹介いたしました。
初めてのチーム開発で学んだこと

こんにちは！未経験からWEBエンジニアを目指している初学者です。

# 1.はじめに
現在参加させていただいているアプレンティスシップというサービスで、初めてチーム開発を経験しました。タスク管理、チームでのコミュニケーションの取り方など、初心者なりに学んだことがあったので記録を残します！

# 2.チーム開発の概要
## 2-1.開発期間
2023/12/11～2024/1/28 の約6週間

## 2-2.チームメンバー
私含む3名のチームで、全員未経験でWEBエンジニアを目指しているメンバーでした。

## 2-3.テーマ
「自分たちの役に立つWEBアプリ」というテーマで自由にアイデアを出し、開発を行いました。

## 2-4.技術アーキテクチャ
フロントエンドとしてHTML/CSS/JavaScriptを使い、ローカル環境（手元のPC）で動くWEBサイトを製作しました。（PHP、Ruby等バックエンドの言語については、後述する理由で使っていません）
なお会議のメモ作成やタスク管理はNotionで行い、ソースコードの管理はGitHubでやっていました。

# 3.チーム開発をどのように進めたか
## 3-1.アイデア出し
健康管理アプリ、学習の進捗管理アプリなどアイデアを出して相談した結果、「自分たちでも作れそう」、「単純に面白そう！」といった理由で、プログラミングの学習をするタイピングゲームのWEBサイトを開発することになりました。

## 3-2.デモ用スライド作成・要件定義
チーム開発の成果発表会に使うスライドを作成したり、要件定義をしたりしました。この部分ではメディア関連の仕事をされているメンバーの方が活躍され、大変ありがたかったです。
私は第3者の目線で「もっとこうした方が伝わりやすいかも」と提案した程度でしたが、「**メンバーの得意な部分は、その人に頼る**」ことも大事だと感じました。

## 3-3.設計、タスク出し
・業務フロー図の作成
・画面遷移図の作成
・ワイヤーフレームの作成
・テーブル定義書の作成
・技術アーキテクチャの設定
・タスク出しと作業の割り振り
を行いました。メンバー全員が未経験だったので、予定を前倒しで実装を始めようかと相談していたのですが、このときは「大丈夫そうだ」ということで予定通りに進めました。
今思えば、私は用事が入って時間があまり取れないことは分かっていたので、**多少でも手を付けてどれくらい時間がかかりそうかもっと正確な見積をする**べきだったと反省しています…

# 3-4.実装～完成まで
## 3-4-1.うまくいったこと
### ➀「こうしたほうがいい」という内容はマイルドに伝える
今回、初対面でバックグラウンドも違ううえ、全員初心者のメンバーで6週間チーム開発を行っていたので、コミュニケーションにはかなり注意しました。
他のメンバーに対して「もっとこうしたほうがいい」と思っても、その人なりに事情やこだわりがあってやっているのかもしれないですし、言い方次第では悪口のようになってしまいます。**チームの信頼関係を壊さないために、相手を尊重する伝え方が大事**だと感じました。

### ⓶.言われた側も、相手の考えをくみ取ってアイデアを昇華する
自分が良いと思ったアイデアに対して、「もっとこうしたほうがいい」と言われると、多少モヤっとしてしまうこともあるかと思います。（今回は全員初心者だったので、単に知識不足から来る未熟な点・それに対する指摘がよくありました）
そこでㇺっとしてしまうのではなく、**相手の言っていることに一理あるということを認識して、直すところは直す、より良い折衷案を考える**ようにするとスムーズにチーム開発が進められると思いました。

# 3-4-2.反省したこと
### ➀.タスク管理の甘さ
今回、とにかくタスク管理が甘かったことを反省しました。
当初はタイピングゲームの問題や正答をデータベース（MySQL）で管理して、PHPでアクセスする予定でしたが、
たまたま用事が重なってしまい時間が取れなかったことがきっかけで、この実装を諦め、問題についてはJavaScriptにベタ打ちで管理することになりました。今回はデモ用のサイト作成だったので問題はなかったですが、**厳しい事が分かった時点で他のメンバーに助けを求める**べきでした…

### ⓶.自分の技術力の無さ
上記の原因の1つですが、本来簡単（であるはずの）機能を実装するのにも毎回調べてやっていたので、想定の倍どころか3倍くらい時間がかかっていました。これは恐らく**アウトプットの反復が足りていないからで、学習を継続することの必要性を痛感**しました。

# 6.おわりに
本記事では、初めてのチーム開発で初心者が経験したこと、感じたことを書きました。
まだまだ未熟であることを痛感しましたが、この経験を活かして今後も頑張っていきます！
繰り返し処理

繰り返し処理を2通りで実装しました。

>課題:iを0から9まで10回ループするプログラムを作成しなさい。

while文
```ruby 
# while

i = 0

while i < 10 do
  puts "Hello"
  i += 1
end
```

times文
```ruby
10.times do |i|
  puts "#{i}: hello"
end
```
LocalAIにおけるモデルの推論速度調査

# はじめに
LangChainのバックエンドとしてローカルでLLMを動かしたいと思っています. OpenAIのREST APIと互換で動作してくれると嬉しいです.
[LocalAI](https://github.com/mudler/LocalAI)は, OpenAIのREST APIサーバをローカルで再現しようとするプロジェクトです. あらゆるLLMをOpenAIのAPIで使いたいというプロジェクトです.

環境は次のコンピュータで, WSL2上でLocalAIを動かしています.
|||
|:---|:---|
|CPU|Ryzen 7 7700|
|Memory|DDR5-5200MHz 64GB|
|GPU|Geforce RTX 4070|

## モデル選択
LocalAIでは, 例えば次のような`gpt-3.5-turbo.yaml`ファイルを, デフォルトでは`models`ディレクトリに作成しておくと, `luna-ai-llama2-uncensored.ggmlv3.q5_K_M.bin`を`gpt-3.5-turbo`モデルとして処理します. OpenAI APIの`model`パラメータに対応します.

<details><summary>gpt-3.5-turbo.yaml</summary><div>

```yaml:gpt-3.5-turbo.yaml
name: gpt-3.5-turbo
# Default model parameters
parameters:
  # Relative to the models path
  model: luna-ai-llama2-uncensored.ggmlv3.q5_K_M.bin
  # temperature
  temperature: 0.3
  # all the OpenAI request options here..

# Default context size
context_size: 512
threads: 10
# Define a backend (optional). By default it will try to guess the backend the first time the model is interacted with.
backend: llama-stable # available: llama, stablelm, gpt2, gptj rwkv
```
</div></details>

# テスト方法
Windowsのcurlを使って簡単なテストをしてみます.
```bash
curl -X "POST" -H "Content-Type: application/json" http://localhost:9090/v1/chat/completions -d "{\"model\": \"mixtral-8x7b-instruct\", \"messages\": [{\"role\": \"user\", \"content\": \"Could you introduce yourself?\"}]}"
```
# 結果
モデル名のあとに量子化ビット数をVRAMにロードする層数を記載します. あくまで設定値ですので, llama2系だと全層VRAMにロードします.

||promt eval (ms/token)|eval time (ms/token) |total time (ms)|VRAM use|
|:---|:---|:---|:---|:---|
|mixtral-8x7b-instruct 2bit GPU 16 layers|503.55|108.30|15930.48|8Gb|
|mixtral-8x7b-instruct 4bit GPU 8 layers|856.37|251.04|27553.77|7Gb|
|codellama-7b-instruct 4bit GPU 32 layers|4.23|21.94|2070.06|5Gb|
|elyza-code-7b-instruct 4bit GPU 32 layers|2.52|20.80|2257.07|4.5Gb|
|mistral-7b-instruct 4bit GPU 32 layers|6.41|21.84|475.33|4.1Gb|

# まとめ
LangChainを駆動できるほどのLLMをローカルPCで動かしたいと思っています. なかなか難しそうです.
【CSS】positionのプロパティまとめ

# relative
```
<div style="position: relative; left: 20px; top: 10px;">
  相対位置で移動
</div>

```
左に20px、上に10px移動します。

# absolute
```
<div style="position: relative;">
  <div style="position: absolute; top: 0; right: 0;">
    絶対位置で配置
  </div>
</div>

```
この内側のdivは、親要素の右上角に配置されます。

# fixed
```
<div style="position: fixed; bottom: 0; left: 0;">
  画面の左下に固定
</div>

```

の要素は、ビューポートの左下に固定され、スクロールしても位置が変わりません。


# sticky
```
<div style="position: sticky; top: 0;">
  スクロールに応じて固定
</div>

```

この要素は、ページをスクロールするとトップに"固定"されます。
Pythonを用いて製品IDと複数の画像IDを対応させる方法（枝番を有するテーブルで紐づける）

# 0. はじめに
タイトルだけでは何をしたいか伝わりきらないと思いますが、
以下のような状況での対応方法について私なりの考えを投稿させていただきます。
- 製品の性能を画像から予測したい
- 一つの製品に対して複数個所の画像を取得している
- 上記の複数の画像データと製品を紐づけるための管理テーブルを準備する
- 上記テーブルは記入の負担を下げるために、横持ちのデータにしたい
- 横持ち⇒縦持ちの変換を毎回全データに対して行うと負荷が高くなるため、変換した結果を保存し、次回の変換時には未対応のIDのみを処理する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/753878/c891764e-ed04-7b72-0e94-1a5a1f6eff4f.png)

# 1. 流れ
処理の流れは以下の通りです
1. 横持ちのID対応表を読み込み(htable)
1. 縦持ちに変換済みのID対応表を読み込み(vtable)
1. 縦持ちに変換されていない行のみを選択
1. 上記で選択した行をループ処理で一行ずつ縦持ちに変換

# 2. 関数の準備
処理4の関数を準備します
``` python:get_idx_corr_df.py
def get_idx_corr_df(sr,
                    idx_col_name,
                    root_col_name,
                    start_col_name, end_col_name,
                    sep=''):
    """
    製品IDと複数の画像IDを対応させる

    Parameters
    ----------
    sr : Series.
    idx_col_name : str, 製品IDのカラム名.
    root_col_name : str, 枝番を除いた画像IDの情報を含むカラム名.
    start_col_name : str, 数字で指定された枝番群の最小値を格納したカラム名.
    end_col_name : str, 数字で指定された枝番群の最大値を格納したカラム名.
    sep : str, idxと枝番のセパレータ.

    Return
    ------
    idx_col_df : DataFrame, idxの対応表(縦持ち)
    """
    idx_list = []
    for i in range(sr[start_col_name], sr[end_col_name]+1):
        idx_list.append(sr[root_col_name] + f'{sep}{i}')
    idx_corr_df = pd.DataFrame(idx_list)
    idx_corr_df.index = [sr[idx_col_name]]*len(idx_corr_df)
    return idx_corr_df
```

# 3. 実行
① 以下のような二つのテーブルを読み込みます

htable：画像を取得した際に対応表を記入
|Product-ID| Image-ID_root | Image-ID_branch-start | Image-ID_branch-end |
|:-:|-:|:-:|:-:|
|p1        |i1             |1|3|
|p2        |i2             |1|2|
|p3        |i3             |1|4|

vtable：htableを縦持ちに変換した結果を格納
|Product-ID|Image-ID|
|:-:|:-:|
|p1|i1_1|
|p1|i1_2|
|p1|i1_3|

```Python:読み込み
htable = pd.read_excel('./htable.xlsx')
vtable = pd.read_excel('./vtable.xlsx')
```

② htableからvtableに変換されていない行を抽出する
```Python:行の選択
already_idx_list = vtable['Product-ID'].unique()
htable_select = htable[~htable['Product-ID'].isin(already_idx_list)]
```

③ htable_selectを一行ずつ読み込んでget_idx_corr_dfを実行する
```Python:変換
## 格納用に準備
all_corr_df = pd.DataFrame()
for i in range(len(htable_select)):
    ## 行を抽出
    sr = htable_select.iloc[i, :]
    
    ## 関数を実行
    corr_df = get_idx_corr_df(sr, 
                              'Product-ID',
                              'Image-ID_root',
                              'Image-ID_branch-start', 'Image-ID_branch-end',
                              '_')
    
    ## 格納
    all_corr_df = pd.concat([all_corr_df, corr_df], axis=0)
```

④ vtableを上書き
```Python:上書き
## 形を整える
all_corr_df.columns = ['Image-ID']
all_corr_df.insert(0, 'Product-ID', all_corr_df.index)
all_corr_df = all_corr_df.reset_index(drop=True)

## 元のデータと結合
vtable_update = pd.concat([vtable, all_corr_df], axis=0)

## 上書き
vtable_update.to_excel('./vtable.xlsx', index=None)
```

# 4. 最後に
もっと効率的な処理があると思います。
アイディアのある方がいらっしゃればコメントをお願いいたします。
firewall-cmdでルールが削除できない時の対応

アウトバウンドの通信を不許可にするためfirewalldのdirectルールを設定したところポート設定を間違えてどうにもならなくなってしまった時の解決法。
基本は設定項目をコピペするのがオペレーションとして正しいと思いますが、雑に手でやったら困ったことになったので備忘録として結果を残します。


iptablesにもかかる内容かと思います。


## 削除できなくなったオペレーション

ポート設定を間違えて登録した際に、--reloadで失敗する。
``` sh
$ firewall-cmd --reload                                                    
Error: COMMAND_FAILED: Direct: '/usr/sbin/iptables-restore -w -n' failed: iptables-restore v1.8.5 (nf_tables): invalid port/service `0-65535' specified
Error occurred at line: 2
Try `iptables-restore -h' or 'iptables-restore --help' for more information.

```

## 確認したこと
ルール設定を確認しても、表示されない
``` sh
$firewall-cmd --direct --get-all-rules
何も表示されない
$firewall-cmd --state
failed ←失敗したことは既にわかっている
```

ルール設定に表示されていないのでdirectルールの削除ができない
``` sh
$firewall-cmd --direct --remove-rule ipv4 filter OUTPUT 1 -m state
Warning: NOT_ENABLED: rule '('-m', 'state')' is not in 'ipv4:filter:OUTPUT'
success
```

iptablesの設定を見ても更新されていない
``` sh
$iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
```

## 解決策
設定ファイルを削除後、reload
```sh
$rm /etc/firewalld/direct.xml
$rm /etc/firewalld/direct.xml.old
$firewall-cmd --reload
```

設定できるようになった

``` sh
$firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 1 -m state --state ESTABLISHED,RELATED -j ACCEPT
$firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 1 -m state --state NEW -j DROP 
$firewall-cmd --reload
success
```

directルールを使用する時は便利だが、気をつける設定があるなと思いました。
firewall-cmdはまだまだ勉強中なので、ご意見ありましたらぜひコメントください。
今すぐ使える！DNSの伝播時間の測定について

# 概要
代表的なDNSサーバに向けて定期的に問い合わせを実施し、どのタイミングで名前解決の結果が切り替わるか確認するためのシェルをchatGPTで作成する。

## 1.前提
今回はPowershellで実行。
Powershellでスクリプト実行できるように以下コマンドを管理者権限で実行しておく。
```
Set-ExecutionPolicy RemoteSigned
```

## 2.スクリプト作成
cursorのGPT機能でコードを作成。
質問：nslookupを定期的に代表的なDNSを指定して打ち、伝播時間を測定するスクリプトを書いてほしいといった趣旨でお願してみた結果が以下。(これでスクリプトが書けてしまうとは・・！
※cursorのインストール方法は別途記事作成予定。

**シェル例**
nslookupを指定した回数だけ繰り返し、結果をログに記録する。
$dns_serverには実際のDNSサーバのIPアドレスを設定し、$target_domainには対象のドメインを指定する。
$intervalは実行間隔（秒）で、必要に応じて調整。ログはdns_propagation.logに保存される。
```
# 定期的に実行する回数
$iterations = 10

# DNSサーバのIPアドレス
$dns_server = "x.x.x.x"  # 例: Public DNS

# 対象のドメイン
$target_domain = "example.com"

# 実行間隔（秒）
$interval = 60  # 60秒ごとに実行

# ログファイル
$log_file = "dns_propagation.log"

# スクリプト開始時のメッセージ
Write-Host "Start DNS test"

# 定期的にnslookupを実行
for ($i = 1; $i -le $iterations; $i++) {
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    
    # nslookupの実行
    $result = nslookup $target_domain $dns_server
    
    # 結果をログに追加
    Add-Content -Path $log_file -Value ("[${timestamp}] Iteration $i " + $result)
    
    # インターバルを待つ
    Start-Sleep -Seconds $interval
}

# スクリプト終了時のメッセージ
Write-Host "DNS test finished"
```

**ご参考**
以下はシェルのスクリプト。
このスクリプトでは、指定されたドメインとDNSサーバーに対してnslookupコマンドを発行し、応答時間を測定する。結果はログにも保管される。sleep $interval_secondsにより、指定した秒数だけ待機してから次のループを実行するため、パラメータは必要に応じて修正が必要。
```
#!/bin/bash

domain="example.com"
dns_server="x.x.x.x"  # 対象のDNSサーバーを指定
interval_seconds=60  # 定期的な実行間隔（秒）
log_file="dns_propagation_log.txt"  # ログファイルの指定

echo "DNS Propagation Measurement for $domain"

while true; do
    start_time=$(date +%s.%N)
    response=$(nslookup $domain $dns_server)
    end_time=$(date +%s.%N)
    duration=$(echo "$end_time - $start_time" | bc)

    if [ $? -eq 0 ]; then
        echo "$(date): Response received in ${duration} seconds" >> $log_file
        echo "$response" >> $log_file
    else
        echo "$(date): No response received." >> $log_file
    fi

    sleep $interval_seconds
done
```

### 注意点

このスクリプトは単純な周期的な実行を行うが、実際のDNS伝播を正確に測定するには、異なる地域やネットワークからのクエリを発行するなどの追加の工夫が必要。あくまで参考ツールとしてご参照いただきたい。
[技育CAMPキャラバン]GitHubの統計情報を用いたユーザーのランク付け

# 概要
2024年2月3日に東京で行われた技育CAMPキャラバンハッカソンに参加しました。

本ハッカソンにてGitHub統計情報からユーザーをランク付けして画像を生成するGitHub Personaを作成したのでその概要や感想を書こうと思います。

サービスURL: https://read-me-psi.vercel.app/
GitHubレポジトリ: https://github.com/tomoish/github-persona


# サービス概要
GitHub Personaは、GitHubの統計情報を取得し、ユーザーに異世界系の世界観で役職とランクを割り当てるサービスです。

以下はその一例です。

![result_tomoish.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3507134/44d6bc32-d0b8-7f5e-6951-90ee413540d8.png)

# システム
今回は以下のような設計としました。

![github-persona-system-design.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3507134/a372fd53-1fb3-46b9-f8f0-87e6720ed4b8.jpeg)


## バックエンド
* 使用言語: Golang

### GitHub API
GitHubの統計情報を得るためにGitHub GraphQL APIを使用しました。

[このページ](https://docs.github.com/en/graphql/overview/explorer)でクエリを試すことができたので、自分が取得したい情報を簡単に取ってこれました。

### 役職のイラスト
全てChatGPTに作成してもらいました。

メンバーがこれ用のGPTsを作成してくれたのでスムーズに多くのイラストを作ることができました。



### グラフを作成する
GitHubでの日別のコントリビューション数を折線グラフにして表示しています。

実際に使用したライブラリは[Gonum Plot](https://github.com/gonum/plot)です。
しかし、画質が悪かったりフォントの変更がうまく行かなかったりしため、Golangでグラフを書いて出力したい場合はこれとは違うライブラリの方がいいかもしれません。

### 画像を作成する
ユーザーが使用している言語の割合を表示しています。

僕は担当しませんでしたが、[Go Graphics](https://github.com/fogleman/gg?tab=readme-ov-file)というライブラリを使用していました。

### 画像を合成する
最終的に全ての情報が詰まった画像を作成しました。

これも同じく担当しませんでしたが、標準ライブラリの[image](https://pkg.go.dev/image)と[resize](https://github.com/nfnt/resize)というライブラリを使用して作成されていました。

## インフラ
* 使用クラウド: Google Cloud

バックエンドのデプロイ先はGoogle App Engineのフレキシブル環境を利用しました。

画像を作成する関係上、読み取り専用のGAEスタンダード環境が使用できなかったため、この選択となりました。



他のサーバーレスサービスと同様、デプロイは非常に簡単でした。

参考記事:
    [Building a Go App on App Engine](https://cloud.google.com/appengine/docs/standard/go/building-app)
   [Go on Google App Engine - Flexible environment](https://cloud.google.com/appengine/docs/flexible/go/runtime)

## フロントエンド
* 使用言語・フレームワーク: TypeScript, Next.js

最初はバックエンドのみを作成し、リンクを貼るとREADME.mdで見られるというものにする予定でしたが、それでもハッカソン参加者に試してもらえるかというと微妙そうだと思ったため簡単なページを作ることにしました。

この効果は非常に大きく、当日も多くの方に試してもらえました。

急造のものでしたが、背景が単色だと少し寂しかったので[tsParticles](https://github.com/tsparticles/tsparticles)というライブラリを用いて動きを付けてみました。

本ライブラリの[テストページ](https://particles.js.org/)や[particles.jsのテストページ](https://vincentgarreau.com/particles.js/)で動きを確認した後に設定ファイルをダウンロードできたため、手間はかかりませんでした。


# 終わりに
本ハッカソンは即席チームで参加しましたが、企業賞を頂けて嬉しかったです。

サポーターズ主催のハッカソンは今後増やしていくとのことでしたので、オンサイトのハッカソンがあればまた参加してみたいと思います。(どなたか誘ってくれると嬉しいです。)
AWS RHELの価格改定後の課金について(2024 年 4 月 1 日以降)

AWSより、Red Hat Enterprise Linux (RHEL) ベースの EC2 インスタンスの価格を2024 年 4 月 1 日以降に変更するとの通知がありました。


## 価格改定の経緯
Red Hat側ではもともと「小規模」と「大規模」という2 段階の価格モデルで提示していました。
ただ、この2種類で区別するには市場規模が大きくなりすぎたとのことで、今回からは、vCPU 数に応じた価格とする形になります。
10年以上前から同じ区分であったとのことですし、改定の経緯には納得。

RHEL公式アナウンス

https://www.redhat.com/ja/blog/red-hat-enterprise-linux-scalable-pricing-cloud-partners-announcement

## AWS上の価格改定の対象
**オンデマンド**と **スポットインスタンス**のすべての使用に適用されます。

また、2024 年 4 月 1 日以降に購入した**Compute Savings Plans**、**Savings Plans**、**リザーブドインスタンス**も対象となります。2024 年 4 月 1 日より前に購入したものは古い価格で請求されるとのことなので、価格改定後に課金額が上がる場合は早めに**Savings Plans**へ入るといったことも検討してもよいかもしれません。

## AWS上の価格例
改定後の価格一覧はまだ内容ですが、既存からの比較表はこちらのFAQに記載されています。
https://aws.amazon.com/jp/partners/redhat/rhel-pricing/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969669/9e4f2374-5b7d-8e8a-099a-4ce03377ad6d.png)

通常のRHELのOSを利用している場合、vCPU数が12以下か、16以上かで影響度が大きく変わってきます。

### **12 vCPU**以下のインスタンスを利用している場合
微弱ですが、値下げとなります。

例：c5.xlarge (4 vCPU 8 GiB)
1時間あたり&#36;0.0024の値下げ
→730時間稼働している場合は 0.0024 * 730h = &#36;1.752 の減額

### **16 vCPU**以上のインスタンスを利用している場合
サイズに応じた値上げとなります。
 
例：c5.4xlarge (16 vCPU 32 GiB)
1時間あたり&#36;0.0428の値下げ
→730時間稼働している場合は 0.0428 * 730h = &#36;31.244 の増額
これはかなりの値上げとなりますね。

※HA等の場合は異なりますので、ご自身の利用のインスタンスと表を確認してみてください。

## 請求単位の変更
また、EC2 RHEL ベースのインスタンスは、時間単位から秒単位の請求に移行するとのこと。

## ポイント
今回の価格改定のポイントは、**インスタンスサイズが大きければ大きいほど課金額の影響が大きい**ということでしょう。
具体的には**16 vCPU**(**4xlarge**)以上のインスタンスから、影響が出てきます。


小さいインスタンスを利用している場合にはあまり影響ないですが、**16 vCPU**以上のインスタンスをお持ちの方にはかなり大きな変更となりそうです。

合わせて秒単位の課金になることもありますし、不要な時間帯の停止やSavings Plans等の利用といったコスト減に向けた工夫が必要となりそうですね。
[CSS]同一要素に複数クラスが適用されるのか、親要素から子要素にクラス階層が出来ているのか[セレクター]

# 同一の要素に複数クラスがある場合

```
<!-- HTML -->
<button class="container__btn btn--filled">ボタン</button>

```

```
/* CSS */
.container__btn.btn--filled:hover {
  color: white;
  background-color: black;
}

```

CSSは`container__btn`と`btn--filled`の2つのクラスが適用されている、
かつ`ホバー状態`のときに適用される



# 親要素に対して子要素に特定のクラスがある場合

```
<!-- HTML -->
<div class="container__btn">
  <button class="btn--filled">ボタン</button>
</div>

```

```
/* CSS */
.container__btn .btn--filled:hover {
  color: white;
  background-color: black;
}
```

CSSは親要素に`container__btn`のクラスがあるかつ、
対象の要素に`btn--filled`クラスがあるかつ、
`ホバー状態`のときに適用される
【VBA】Outlookのメールデータを抽出

Sub Mailデータ抽出()

Dim oApp As New Outlook.Application

Dim oNs  As Outlook.Namespace
Set oNs = oApp.GetNamespace("MAPI")

'抽出するプロファイルとフォルダを定義する
Dim oF As Folder
Set oF = oNs.Folders("任意のプロファイル").Folders("任意のフォルダ")

'アイテムのセット
Dim mailLists As Items
Set mailLists = oF.Items

'ソートを受信時間で、昇順(true:降順　false:昇順)
mailLists.Sort "[ReceivedTime]", true

'取得するデータの種類、入力箇所、取得数(例:3件)
Dim i As Long
For i = 1 To 3
   On Error Resume Next
   Cells(i + 1, "A").Value = mailLists.Item(i).ReceivedTime
   Cells(i + 1, "D").Value = mailLists.Item(i).SenderEmailAddress
   Cells(i + 1, "E").Value = mailLists.Item(i).Subject
   Cells(i + 1, "F").Value = mailLists.Item(i).Body
Next i

End Sub

***********************************************************************************************
特定のサブフォルダを指定する場合は、フォルダの定義を以下のように変更する。
Set oF = oNs.Folders("任意のプロファイル").Folders("任意のフォルダ").Folders("任意のサブフォルダ")
***********************************************************************************************

※連続して別のフォルダの情報を取得する場合は、「Next i」と「End Sub」の間に、下記を追記。

Set oF = oNs.Folders("任意のプロファイル").Folders("任意のフォルダ")

Set mailLists = oF.Items

mailLists.Sort "[ReceivedTime]", True


For i = 1 To 3
   On Error Resume Next
   Cells(i + 5, "A").Value = mailLists.Item(i).ReceivedTime
   Cells(i + 5, "D").Value = mailLists.Item(i).SenderEmailAddress
   Cells(i + 5, "E").Value = mailLists.Item(i).Subject
   Cells(i + 5, "F").Value = mailLists.Item(i).Body
Next i

End Sub
Javascriptの短絡評価

## Javascriptの短絡評価とは
論理演算において、結果が確定した時点で評価を中断し、その値を返ものを短絡評価と言います。
本来、if文や三項演算子を使って記述できる処理ではあるものの、短絡評価で記述することによりシンプルに記述することができます。
## 基本的な書き方
```javascript
// && を使った短絡評価
const condition = true;
condition && myFunction(); // conditionがtrueの場合にmyFunction関数を実行する
let variable = condition && "check OK!!"; // conditionがtrueの場合にvariableに値を格納する

// ||を使った短絡評価
let isValid = false;
isValid || myFunction();  // idValidがfalseの場合、myFunctionを実行する
```
## 具体的な使い方
```javascript
// 1冊1600円の本を複数購入した時の金額を計算する
const book = 1600;
const tax = 1.10;
const numberOfBooksPurchased = 2;// 購入数

// 短絡評価
let cost = 1 <= numberOfBooksPurchased && book * numberOfBooksPurchased * tax;

console.log(cost);
// 出力結果：3520.0000000000005
```
上記の例は、本を1冊以上購入する際の金額を計算しています。

※サンプルなので0冊の場合の考慮は入れていません

## まとめ
以上、簡単にJavascriptの短絡評価についてまとめました。

参考になれば幸いです。
@dataclassをちょっと理解する

## 環境
python: 3.12

### dataclassを使わない場合の書き方
```py
class Point:
    def __init__(self, x, y):
        self.x: str = x
        self.y: str = y

    def __repr__(self):
        return f"Point({self.x}, {self.y})"

    def __eq__(self, other):
        if isinstance(other, Point):
            return self.x == other.x and self.y == other.y
        return False

    def __hash__(self):
        return hash((self.x, self.y))

    # ...etc
    

print("__init__")
point1 = Point(1, 2)
point2 = Point(1, 2)

print("__repr__")
print(point1)  # Point(1, 2)
print(point2)  # Point(1, 2)

print("__eq__")
print(point1 == point2)  # True

print("__hash__")
point_set = {point1}
print(point_set)  # {Point(1, 2)}
print(point2 in point_set)  # True
```

### dataclassを使う場合の書き方（frozen=False）
```py
from dataclasses import dataclass


@dataclass
class Point:
    x: int
    y: int

# クラスの使い方
print("__init__")
point1 = Point(1, 2)
point2 = Point(1, 2)

print("__repr__")
print(point1)  # Point(1, 2)
print(point2)  # Point(1, 2)

print("__eq__")
print(point1 == point2)  # True

# print("__hash__")
# point_set = {point1}  # エラー
# print(point_set)  # {Point(1, 2)}
# print(point2 in point_set)  # True

print(point1.x)  # 1
point1.x = 3
print(point1.x)  # 3
```

### dataclassを使う場合の書き方（frozen=True）
```py
from dataclasses import dataclass


@dataclass(frozen=True)
class Point:
    x: int
    y: int


# クラスの使い方
print("__init__")
point1 = Point(1, 2)
point2 = Point(1, 2)

print("__repr__")
print(point1)  # Point(1, 2)
print(point2)  # Point(1, 2)

print("__eq__")
print(point1 == point2)  # True

print("__hash__")
point_set = {point1}
print(point_set)  # {Point(1, 2)}
print(point2 in point_set)  # True

print(point1.x)  # 1
point1.x = 3  # エラー
```
ESP32-S3-DevKitCでSDカードを操作してみた

今回はESP32-S3からSDカードを操作したので記事にしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/bdffc421-b0cf-98d9-d431-e70a285a6c0a.png)

## ハードウェア
1、ESP32-S3-DevKitC
https://akizukidenshi.com/catalog/g/g117073/
2、マイクロSDカードスロットDIP化キット
https://akizukidenshi.com/catalog/g/g105488/

## 配線図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/5688e27b-550f-4437-5760-13d4fe4de5ac.png)

## ソフトウェア
今回はmgo-tec電子工作様の記事を参考にさせていただきました。
https://www.mgo-tec.com/blog-entry-esp32-wroom-micro-sdhc-01.html

```c
#include <SD.h>
 
const uint8_t cs_SD = 10; 
const char* fname1 ="/test1.txt";

File f1;
 
void setup() {
  Serial.begin(115200);
  SD.begin(cs_SD, SPI, 24000000, "/sd");
 
  Serial.println("\r\n File Write");
  f1 = SD.open(fname1, FILE_WRITE);
  serial_print_Fwrite(f1, 1, "このファイルはテスト1\r\n");
  f1.close();
  delay(1);
   
  Serial.println("File Read");
  f1 = SD.open(fname1, FILE_READ);

  serial_print_Fread(f1, 1);
 
  f1.close();
   
/*  
  Serial.println("\r\n------------ファイル削除");
  Delete_File(fname1);
*/
}
 
void serial_print_Fwrite(File ff, byte num, const char *message){
  if(ff.print(message)){
    Serial.printf("f%d Message wrote. Good!\r\n", num);
  }else{
    Serial.printf("f%d write failed\r\n", num);
  }
}
 
void serial_print_Fread(File ff, byte num){
  size_t len = ff.size();
  uint8_t buf[256];
   
  if (ff.read(buf, len)) {
    Serial.printf("f%d File found OK!!\r\n", num);
    for(int i=0; i<len; i++){
      Serial.write(buf[i]);
    }
  }else{
    Serial.printf("f%d File not found\r\n", num);
  }
}
 
void Delete_File(const char *fname){
  if(SD.remove(fname)){
      Serial.printf("%s File deleted\r\n", fname);
  } else {
      Serial.printf("%s Delete failed\r\n", fname);
  }
}
 
void loop() {
}
```

プログラムの内容としては、
serial_print_Fwrite(f1, 1, "このファイルはテスト1\r\n");
の部分でファイルに書き込みを行い、
serial_print_Fread(f1, 1);
の部分でファイルの内容を読み込んでいます。

## 最後に
ESP32-S3では少しピンアサインがわかりにくい部分があったので
多少配線に時間がかかりました。
みなさんもこの記事を参考にSDカードを操作してみてください。

ESP32やLPWA（プライベートLoRa）などの開発を行っております。
IoT製品の開発も行っていますのでなにかありましたら
お気軽にご相談ください。
GazeboでLiDAR反射強度のある物体の作成方法

# はじめに
* Gazebo (classic)で、LiDAR反射強度のある物体の作成方法
  * ROS2 2D LiDARの場合は、[sensor_msgs/msg/LaserScan](https://docs.ros2.org/latest/api/sensor_msgs/msg/LaserScan.html)のintensitesに入る値

# 動作確認環境
* ROS2 Foxy 
* Gazebo 11 (Gazebo classic)
* 2D LiDAR Plugin
  * libgazebo_ros_ray_sensor.so
    * ```<output_type>sensor_msgs/LaserScan</output_type>```

# 方法

ポイントは、```<laser_retro>```タグを```<visual>タグ```に入れて、物体をSDFで作成する。

例 (50cm x 50cm x 5mm の反射板)

mode.sdf
```xml
<?xml version="1.0"?>
<sdf version="1.6">
  <model name="reflection_panel">
    <static>true</static>
    <pose>0 0 0.25 0 0 0</pose>
    <link name="left_reflection_panel_link">
      <pose>0 0 0 0 0 0</pose>
      <collision name="collision">
        <laser_retro>1000.0</laser_retro>
        <geometry>
          <box>
            <size>0.005 0.5 0.5</size>
          </box>
        </geometry>
      </collision>
      <visual name="visual">
        <laser_retro>1000.0</laser_retro>
        <material>
          <script>
            <uri>file://media/materials/scripts/gazebo.material</uri>
            <name>Gazebo/White</name>
          </script>
        </material>
        <geometry>
          <box>
            <size>0.005 0.05 0.5</size>
          </box>
        </geometry>
      </visual>
    </link>
  </model>
</sdf>
```

上記の場合は、2D LiDARデータ[sensor_msgs/msg/LaserScan](https://docs.ros2.org/latest/api/sensor_msgs/msg/LaserScan.html)のintensitiesに1000.0が入る。
* ```<laser_retro>```タグは、```<collision>```タグには入れなくても大丈夫だったが入れても問題ない。

Gazeboモデルのパッケージ化は以下の記事を参考にすると良い。

https://qiita.com/srs/items/ac242e46177c2b797a7b

# 参考

http://sdformat.org/spec?ver=1.6&elem=visual

https://community.gazebosim.org/t/laser-reflection-intensity-of-the-gazebo-model/1119