OmniAICreator/Qiita-1.07M huggingface dataset:
[VScode]OpenCV Cppで環境構築しようとして詰まった点と解決策

# 導入
この記事に書いてあることは題名の通りです。
他qiitaやzennで調べながらopencv cppで環境構築しようとして詰まったところ書いておきます。
8割方備忘録のようなモノです。
構築するときに使わせていただいたサイトは一番下に載せておきます。
是非活用してください。
# 本題
まず一つ目です。
まずopencvソースコードのビルドについてです。
事前にmkdirで生成ファイルを吐き出すフォルダを作成しておきます。
その後ビルドするには、
```terminal:terminal
cmake -S . -B (mkdirで作成したフォルダ名)
```
と実行するとエラーを吐く方が居ると思います。俺はそれでした。

```terminal:エラー内容
-- Building for: Visual Studio 17 2022
-- Selecting Windows SDK version 10.0.22621.0 to target Windows 10.0.22631.
-- The C compiler identification is MSVC 19.42.34436.0
-- The CXX compiler identification is MSVC 19.42.34436.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/14.42.34433/bin/Hostx64/x64/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/14.42.34433/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Error at CMakeLists.txt:4 (find_package):
  By not providing "FindOpenCV.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "OpenCV", but
  CMake did not find one.

  Could not find a package configuration file provided by "OpenCV" with any
  of the following names:

    OpenCVConfig.cmake
    opencv-config.cmake

  Add the installation prefix of "OpenCV" to CMAKE_PREFIX_PATH or set
  "OpenCV_DIR" to a directory containing one of the above files.  If "OpenCV"
  provides a separate development package or SDK, be sure it has been
  installed.


-- Configuring incomplete, errors occurred!
```
エラー内容はOpenCVConfig.cmakeとopencv-config.cmakeが見つからないとのことです。
原因はCMakeLists.txtはopencv/sourcesにあるのですが、OpenCVconfig, opencv-config.cmakeはopencv/buildにあります。
それを解決するために、**-S** オプションの後にCMakeLists.txtの位置を指定してあげます。
``` terminal:terminal
cmake -S opencv/sources -B
```
生成ファイルを吐き出すフォルダがopencvにあるなら上記のコードで正常にビルドできるはずです。
場所が違うなら、**-B** オプションの後に同じように位置を指定してあげてください。


# 環境構築の際使わせていただいたサイト
https://zenn.dev/nadegata_memo/articles/8143303ae19968
0.5^n 表

循環小数(2進)にならない浮動小数点用数値、固定小数点の精度(ビット幅)決定の参考値、などに。

<p class="codepen" data-height="800" data-default-tab="result" data-slug-hash="vEBwmoM" data-pen-title="0.5^n 表" data-user="ikiuo" style="height: 800px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ikiuo/pen/vEBwmoM">
  0.5^n 表</a> by Ikiuo (<a href="https://codepen.io/ikiuo">@ikiuo</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

https://qiita.com/ikiuo/items/6c02524a35f676ec753b

https://qiita.com/ikiuo/items/ac99a130f49ac2371d86

https://qiita.com/ikiuo/items/fae0011e061c711d42d8

```JavaScript
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>2^-n表</title>
    <style>
     table {
         border: solid 1px #e2e2e2;
         border-collaspe: collaspe;
         border-spacing: 0;
     }
     th, td {
         border: solid 1px #e2e2e2;
     }
     th { background: white; }
     td { padding: 2px 2px 2px 4px; }
     .eline { background: #edefef; }
     .oline { background: #f5f6f6; }
    </style>
  </head>
  <body>

    <script>

     function toClipboard(text) {
         navigator.clipboard.writeText(text).then(() => {
             // success
         }, () => {
             // failed
         });
     }

     function pow5n(n) {
         var a = 1n;
         var b = 5n;
         while (n) {
             if (n & 1)
                 a *= b;
             b *= b;
             n >>= 1;
         }
         return a;
     }

     function expstr(n) {
         const v = '' + pow5n(n);
         const s = v.length >= 9 ? v.slice(0, 3) + '⋅⋅⋅' + v.slice(-3) : v;
         return `10<sup>-${n - v.length}</sup> × 0.${s}`;
     }

     function fullstr(n) {
         const v = '' + pow5n(n);
         return '0'.repeat(n - v.length) + v;
     }

     window.onload = (() => {
         document.body.innerHTML = [
             '<table>',
             // '<tr><th colspan="3" style="font-size: xx-large;">0.5<sup>n</sup> 表</th></tr>',
             '<tr><th>n</th><th>指数形式(途中省略)</th><th>2<sup>-n</sup> 全桁</th></tr>',
             [...Array(64)].map((_, i) => {
                 const s = '0.' + fullstr(i+1);
                 return [
                     `<tr class="${i & 1 ? 'oline' : 'eline'}">`,
                     `<td style="text-align: right;">${i+1}<sup>&nbsp;</sup></td>`,
                     `<td onclick="toClipboard('${s}')">${expstr(i+1)}</td>`,
                     `<td onclick="toClipboard('${s}')">${s}</td>`,
                     '</tr>',
                 ].join('');
             }).join(''),
             '</table>',
         ].join('');
     });

    </script>
  </body>
</html>
```
wslでIPv6

# 概要
wslでIPv6やってみた。
wslにapache2をインストールして、chromeから開いてみた。

# 環境
windows11
wsl(wsl2じゃない)
ubuntu 18.04

# 手順
## apache2をインストール
```
$ sudo apt install apache2
```

## sudo nano  /etc/apache2/ports.conf

```
Listen [2404:7a83:*:a730:45e4:45c5:*:93fb]:80
```
## apache2 起動

```
$ sudo service apache2 start
```

# chromeから開く。

```
http://[2404:7a83:*:a730:45e4:45c5:*:93fb]:80/
```

# 写真


![スクリーンショット 2025-02-04 055223.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/eb1e45f8-5ce4-e80d-e414-d17e919d1977.png)

# 以上。
「良い」コミットと「悪い」コミット

こんにちは。

自称コミットオプティマイズドアドバイザーの古里です。
今日は、「良い」コミットと「悪い」コミットについて話していこうと思います。

PR（プルリクエスト）のレビューを幾度となく経験した上で、良いコミットと悪いコミットを言語化してみました。良いコミットを知る前に、まずは悪いコミットの例を見て、理解を深めましょう。

## 「悪い」コミットの例
悪いコミットの典型例です。

### ① 適当なコミットメッセージ
例: `fix`、`update`、`変更した`
- 何を修正したのか、どの部分を更新したのかが分かりません
- 何のためのコミットなのかもわかりません
- レビュワーからするとブチギレ案件です

### ② 変更点が多すぎるコミット
例:1000行以上の変更を1コミットに詰め込む
- 1つのコミットに異なる機能の変更やリファクタリングが混在しているとカオスです
- 差分を適切に管理できないため、デバッグ時に影響範囲を特定しにくくなるなります
- 変更点多すぎなんじゃぼけ案件です
- レビュワーも人間ですので、往々にして後回しにされます

:::note warn
大規模な修正で本当に1000行以上の変更が必要な際は例外です。
:::

### ③複数のコンテキストが含まれているコミット
コンテキストという抽象的な単語を使いましたが、ここでのコンテキストは、「目的・背景・意図」の意味で利用しています。

例えば、1つのコミットに「新規機能」と「リファクタリング」が含まれていると、2つのコンテキストがあると解釈します。②の話とも被るのですが、同じような修正なのだが、意図が異なる場合、別のコミットに分けて欲しいと思うのです。


## 「良い」コミットとは

では、良いコミットとは何か？ それを実現するためのポイントを紹介します。



### ① 「1コミット＝1コンテキスト」の原則
これが一番伝えたいことです。
- 1つのコミットに1つのコンテキスト（目的・背景・意図）を持たせる
- 修正とリファクタリングを混ぜない（バグ修正とコード整理を同時にしない）
- 小さな変更単位でコミットすることで、レビューの負担を減らし、問題が発生した際の原因特定を容易にする

### ② コミットメッセージにはPrefixを
- **例:** `[fix] バグの修正`, `[feat] ログイン機能の追加`, `[refactor] コード整理`
- コミットの意図を明確にし、履歴を追いやすくする
- チームで統一したルールを決めることで、誰が見ても分かりやすい履歴を作れる

### ③ コミットメッセージは簡潔かつ具体的に
- **例:** `fix: APIエンドポイントの認証処理を修正`
- 「何を、なぜ変更したか」を含めると、あとから見返したときに役立つ

## なぜ悪いコミットが生まれてしまうのか？
ここまで、「良い・悪い」コミットの話をしてきましたが、PRを出す側も意図的に分かりにくくしている訳ではないでしょう。

気づいたら、わかりにくいコミットが生まれている状況なのです。この理由については、コミット単体ではなく、タスクの切り分け方にも問題があると考えます。

つまり、PRを出す側ではなく、そもそもタスク依頼者側にも問題があるのではないか？という話です。

### タスクの適切な粒度
- アジャイル開発におけるPBI（プロダクトバックログアイテム）の設定の見直し
- 1つのPBIが適切な粒度で設計されていれば、それに対応するコミットも自然と適切なサイズになる
- 「1コミット＝1コンテキスト」を実践するためには、タスク自体の設計を適切に行うことが重要

### 変更の論理的なまとまり
- ある機能の追加・修正・削除を、それぞれ適切に分割する
- 変更を積み重ねたときに、履歴が分かりやすくなるように意識する

## まとめ

良いコミットは、単に「きれいな履歴を作る」だけではなく、チーム開発においてコミュニケーションコストを下げ、変更を管理しやすくするために重要です。

- 適切なコミットメッセージを書く
- 1コミット1コンテキストを意識する
- コードの変更を論理的に整理する

これらを意識することで、よりスムーズな開発が可能になると考えます！
試してみてね♡

## 宣伝
Organizationやってます。

https://qiita.com/organizations/raretech
1万時間学習記録：Laravel9

# github
https://github.com/HondaAkihito/ten-thousand-hours-record

# サイト
https://akkun1114.xsrv.jp/trackers

# 新しくやったこと
・CRUD処理
・ファットコントローラー防止
・バリデーション
・oldヘルパ関数
・ダミーデータ(シーダー、　Factory&Facer)
・ページネーション
・リレーション
・ログイン
・エラーメッセージの日本語化
・githubにアップロード
・サーバーへ上げる
dependabot さんと僕　〜　その１ package.json について

昨日投稿した expressjs の小さなアプリですが、githubに入れてみました。プライベートなものでそもそも大した機能はないのですが、汎用性（分析とレポート出力、設定管理やDBマイグレーションのサブシステムを加えれば有用性、可搬性が出ると思われます）をもたせることと顧客に由来する情報は全部削除して習作的に並べてみようという試みです。

## githubからメールがいっぱい来ました。

* dependabot さんいわく：要約：「色々セキュリティ脆弱性あるコードがあるよ」

10年分の脆弱性検査分だから結構な数あります。 <a href="https://github.com/vitaly-t/pg-promise">pg-promise</a> みたいに核を成しているもの以外の node_module がいっぱい... ｳｹﾞｴ

''それが要るのか要らないのか!?''　ということはさておいて、本日から純粋に保守だけするという観点で作業をします。　足したり引いたりは別な人がやることを前提にするので、コツコツ package.json をいじって都度を掛けてみました。

## lodash とはなんだ？
* 軟弱なのでお助けを求める：<a href="https://qiita.com/sosomuse/items/a08e28def541c28458a0">【JavaScript】lodashの使い方</a>
* 初見、dependabot が出してくる表記に惑わされます。何故か？　”Iodash"　と見間違えて、散々探しました。そりゃ見つからんよ。 l/I の区別が！
* l(エル）odash の バージョン縛りを外したんですが、何故か上がりませんなぜですか？
* packge-lock.json に残ってしまってます。消しても良いのか？　結論：意味ないです。
→ 感謝：<a href="https://qiita.com/sugurutakahashi12345/items/1f6bb7a372b8263500e5">package-lock.json ってなに？</a>
---
* 深掘ってみますと 二つ入っているみたいです...
```json

   "node_modules/inquirer/node_modules/lodash": {
      "version": "3.10.1",
      "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
      "integrity": "sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ==",
      "dev": true,
      "license": "MIT"

```
```json
    "node_modules/lodash": {
      "version": "4.17.21",
      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
      "license": "MIT"
    },
 
```
* node_modules の 依存関係の tree とか無いのか？　探しましょう。
* 発見したもの１：まず理解を深めるに良さそう記事がありました。
<a href="https://zenn.dev/estra/articles/npm-lockfile-dependencies" >npmの依存関係とv7のロックファイルについて調べてみた</a>
<a href="https://zenn.dev/estra/articles/npm-about-dependencsies">npmの依存関係について勘違いしていたこと</a>
* 可視化ツールらしいものがありました。　→ https://www.npmjs.com/package/dependency-tree
* さてどこから手を付けるか。　時間切れです。
*
C# でのバックグラウンド処理と `async/await` の正しい使い方を学ぶ

`async/await`を久しぶりに書いていたら少し忘れてしまっていたので学び直しです。・・・

## 1. `Task.Run(async () => await ...).Wait();` の問題点

C# でバックグラウンドスレッドを利用する際、以下のように `Task.Run` を `Wait()` で待機することがあります。

```csharp
Task.Run(async () => await DoSomethingAsync()).Wait();
```

しかし、これは以下の問題を引き起こします。

### ❌ `Wait()` の問題点
1. **メインスレッドがブロックされる** → 非同期のメリットが失われる
2. **UIスレッド（WPF/WinForms）でフリーズの原因になる**
3. **デッドロックが発生する可能性がある**
4. **例外が `AggregateException` にラップされるため扱いにくい**

✅ **解決策**
```csharp
await Task.Run(async () => await DoSomethingAsync());
```
これにより、メインスレッドをブロックせずに非同期処理を実行できます。

---

## 2. バックグラウンドで処理を並行実行する方法
### **方法1: `Task.Run` で非同期実行**
```csharp
Task.Run(async () => await DoBackgroundWorkAsync());
```
✅ **ポイント**
- `await` しないので **メインスレッドをブロックしない**
- `Task.Run` の戻り値を無視することで **完全に独立した処理** になる

### **方法2: `Task` を保存してあとで `await`**
```csharp
Task backgroundTask = Task.Run(async () => await DoBackgroundWorkAsync());

// 他の処理を並行して実行
Console.WriteLine("メインスレッドで別処理");

// あとで結果を待つ
await backgroundTask;
```
✅ **ポイント**
- `Task` を保存することで、好きなタイミングで `await` できる

### **方法3: Fire and Forget（例外処理付き）**
```csharp
Task.Run(async () =>
{
    try
    {
        await DoBackgroundWorkAsync();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"エラー発生: {ex.Message}");
    }
});
```
✅ **ポイント**
- `await` しないので **メインスレッドはブロックされない**
- `try-catch` で **例外処理を適切に行う**

---

## 3. `.Wait()` と `.Result` の違い
| メソッド | 動作 | 例外の扱い | デッドロックの危険性 |
|----------|------|----------|----------------|
| `.Wait()` | タスクが完了するまで **同期的に待つ** | `AggregateException` にラップ | あり |
| `.Result` | タスクが完了するまで **同期的に待ち、結果を取得** | `AggregateException` にラップ | あり |

### ❌ **デッドロックの危険性**
特に **UIスレッド** で `Result` や `Wait()` を使うと、デッドロックが発生しやすくなります。

```csharp
string result = Task.Run(async () => await GetDataAsync()).Result; // デッドロックの危険
```
✅ **解決策** → `async/await` を使う
```csharp
private async void button_Click(object sender, EventArgs e)
{
    string result = await GetDataAsync();
    MessageBox.Show(result);
}
```

---

## 4. まとめ
### ❌ 避けるべきコード
```csharp
Task.Run(async () => await DoSomethingAsync()).Wait();
```
**理由:**
- メインスレッドをブロックする
- デッドロックの可能性
- 例外が `AggregateException` にラップされる

### ✅ **推奨される実装**
#### **バックグラウンドで非同期処理を開始**
```csharp
Task.Run(async () => await DoBackgroundWorkAsync());
```
#### **`Task` を保存してあとで `await`**
```csharp
Task backgroundTask = Task.Run(async () => await DoBackgroundWorkAsync());
// 他の処理を実行
await backgroundTask;
```
#### **UIアプリでデッドロックを避ける**
```csharp
private async void button_Click(object sender, EventArgs e)
{
    string result = await GetDataAsync();
    MessageBox.Show(result);
}
```

**結論:**
`Wait()` や `Result` を避け、可能な限り `async/await` を使うのが最適！
e-Taxで確定申告(2025)

# e-Taxで確定申告（2025年版）
e-Taxでの確定申告に手間取ったので記事にしました。
## 前提
会計ソフト（FreeeやMoney Forwardなど）を使っておられるフリーランス・自営業者さんがe-Taxで電子申告する場合、参考になればと思います。
- 会計ソフトを使っていない場合、提出用データ(.xtx）を用意出来ませんので参考になりません。
- PCを使った操作です。
## 1. 事前準備
(1) 会計ソフトで __e-Tax用ファイル(.xtx)__ をダウンロードしておきます。
例：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440640/93f2a4be-71dd-6383-724b-f208f090ac1c.png)
  <BR>

(2) [e-Taxソフト(WEB版)のご利用にあたって](https://www.e-tax.nta.go.jp/e-taxsoftweb/e-taxsoftweb1.htm)の __(4)事前準備セットアップ__ でブラウザ拡張機能や電子証明のセットアップを行います。
説明は難解ですが、よく読んで手順通りに操作してください。

## 2. 初手
(1) [e-Tax](https://www.e-tax.nta.go.jp)のトップページから __個人の方__ を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440640/3075cb20-e025-33ae-b54f-063c62f515df.png) 
  <BR>

(2) 右上の __ログイン__ を選択します。左の __確定申告書等の作成はこちら__ を選択すると、イチから申告データを入力（または前年度の修正で作成）することになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440640/541d4df9-6b98-7843-f826-2d4e36a618ea.png)

## 3.手順
(1) マイナポータルまたはマイナンバーの電子証明を利用してログインします。
私はマイナンバーカードとスマホを使ってログインしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440640/30db54ba-e132-583d-9fd0-558915b4367a.png)
  <BR>

(2) 初めて電子申告される場合、氏名、住所などの個人情報を入力する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440640/e41a081f-badf-42b5-6154-12f4f161f9ff.png)
  <BR>

(3) 過去、電子申告を行った事がある／または(2)で個人情報入力後にe-Taxのメニュー画面が表示されます。ここで __確定申告を行う__ を選択したいところですが、 __申請・納付手続を行う__ が正しい道です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440640/89ed1fa7-149a-cfa7-9ce3-8775a2029ca9.png)
  <BR>

(4) 1. の (2) の事前準備が終わっていれば __スキップする__ をクリックすると、申告メニューが表示されます。
事前準備を行っていない場合 __事前セットアップへ__ へ進み、説明に従って操作してください。終わったら当ページに戻り __スキップする__ をクリックすると、申告メニューが表示されます。
事前セットアップ終了後、PCの再起動が要求された場合は __初手__ に戻ってログインからやり直してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440640/3921c197-6af8-7d01-50f3-9dd8cc7064bd.png)
  <BR>

(5) __作成済みデータの利用__ の __操作に進む__ をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440640/b8707182-dc16-4e90-7b40-c5adfe775278.png)
   <BR>

(6) 1.準備で作成したデータを選択し、 __次へ__ をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440640/326bcb21-964e-d775-d9c0-d183fe6e505e.png)
   <BR>

(7) 正常にアップロードできれば、確認画面が表示されますので、右側のチェックボックスを（通常であれば）全て選択します。念のため __帳票表示__ で申告データを確認して、問題無ければ __次へ__ をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440640/2345148b-b9d3-96fb-65ea-06b66709b226.png)
   <BR>

(8) 右下の __送信__ をクリックすると申告完了です。 __送信__ ボタンクリック時に確認画面は出ませんので、焦ってクリックしないように！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440640/5654d8aa-f222-3d9b-b691-f736b9522b30.png)
## おわりに
私は __初手__ で __確定申告書等の作成はこちら__ を選んでしまってハマりました。
その後も __申請・納付手続を行う__ を選択するまでにずいぶん時間がかかりました。
解ってしまえば申告操作は10分程度で終わると思います。
消費税申告も会計ソフトでe-Tax用ファイルを出力しておけば、同じ手順で申告出来ます。
MacでのRails + MySQL環境構築でハマった1日：試行錯誤と解決策

## **はじめに**

昨日、**MacでRails + MySQLの開発環境をセットアップ**していたら、思わぬトラブルに見舞われました。\
「Railsが動かない」「rbenvの設定がうまくいかない」など、エラーの連続…。\
いろいろ試したけど解決せず、競合やバージョン違いを疑いましたが、**実はプロジェクトをiCloud Driveの同期フォルダに入れていたことが原因**でした。\
これは過去にも、iCloud Driveの同期が影響して音楽系のソフトが正常に動作しなかったことがあったので、それと同じ問題だったようです。

この経験を共有し、同じ問題に悩む開発者の参考になればと思います。

---

## **試したことと解決しなかったこと**

### **1. `rails db:create` でエラー発生 (`NameError: uninitialized constant Logger`)**

#### **問題発生**

```sh
% rails db:create
/Users/robot/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/activesupport-7.0.8.7/... (略)
NameError: uninitialized constant ActiveSupport::LoggerThreadSafeLevel::Logger
```

#### **試したこと**

- `bundle update activesupport` でバージョンを更新
- `gem pristine --all` でGemを再インストール
- `rbenv rehash` を実行
- `.zshrc` の設定を見直し、環境変数を修正
- `brew reinstall rbenv` で再インストール
- `bundle install` で依存関係を再インストール

→ それでも Logger のエラーは解決しませんでした。

---

### **2. `rails` コマンドがそもそも効かなくなる**

#### **問題発生**

```sh
% rails -v
Could not find activesupport-7.0.8.7
```

#### **試したこと**

- `gem list rails` で確認し、`bundle install` で修正
- `bundle exec rails -v` を試すも同じエラー
- `rbenv global 3.2.0` でバージョンの明示的指定
- `.rbenv/versions` に異常がないか確認

→ それでも `rails` コマンドは動作せず。

---

## **最終的な原因：iCloud Drive の影響**

ここまで色々試したが、**Logger のエラーは解決しないままだった**。しかし、ふと「プロジェクトを iCloud Drive のフォルダに保存していること」に気づいた。\
**プロジェクトを iCloud Drive の外 (`~/dropbox/projects/` など) に移動したところ、全ての問題が解決！**

iCloud Drive は同期処理が入るため、一部のファイルが正しく認識されなかったり、Rails の動作に影響を与えることがあるようだ。\
**過去にも、iCloud Drive の同期が原因で音楽系ソフトがうまく動かなかった経験があるので、同じような問題だったのかもしれない。**

---

## **学びとまとめ**

今回のトラブルシューティングで得た教訓:

1. **エラーメッセージをしっかり読む** → ログ (`tail -n 50` など) を確認する
2. **バージョンの競合を疑う** → `bundle update`、`gem pristine --all` で修正
3. **環境変数 (`PATH`) の整理を意識する** → `.zshrc` ではなく `.zshenv` を活用
4. **プロジェクトは iCloud Drive に保存しない** → Rails や MySQL が適切に動作しなくなる可能性がある

この経験を活かして、今後はスムーズに環境構築できるはず！

同じ問題に悩んでいる方の参考になれば幸いです🙏

---

**参考リンク**

- [rbenv の公式ドキュメント](https://github.com/rbenv/rbenv)
- [Rails ガイド](https://railsguides.jp/)

もし「こういうエラーもあったよ！」という方がいたら、ぜひコメントで教えてください！
rpm、yum、dpkg、apt...の検索オプションが「search」の理由

1ヶ月前くらいからLinuCの勉強をはじめました。
わかったことを雑にメモしていこうと思う。
あくまで自己解釈なので悪しからず。

Linuxの多くのコマンドではオプションに使われるアルファベットにある程度の法則がある
から推測しやすいけど、パッケージ管理ツールはオプションが特殊だぞ...？

そう思ってる人が見たら、頭が整理できるかもしれません。


## yumとaptはインターネット上のリポジトリから検索する

yum（rpm形式）とapt(deb形式)は、インターネット上にあるリポジトリ（パッケージが管理されている倉庫みたいな場所）を検索して、いろいろやってくれる。

インターネット上で検索を行うことを海外圏では「search」で表現する

検索系のオプションには「find」とか「-f」が使われていることが多い気がするけど、
yumとaptで"search"が使われるのはインターネット経由で調べるのが関係してそう。

## おまけ：なぜinstalled listではなく「list installed」なのか

パッケージ管理ツールのオプション関連で発見があったのでプチ共有。

たぶんプログラミング関係の世界では、**重要なものから左に配置**していく。

今回の場合なら、インストール済みのファイルを「一覧で」確認すること。

つまり、listを見たいというのが最も重要な要素だ。

installed list　だと、

・installed か、何かのパッケージ名が来るんだろうな
・あれ？　listじゃないの！もっと早く言いなさいよ！

と、せっかちさんに叱られるのかもしれない。

これがlist installed だと、

・list ってことは何かを一覧表示するんだろな
・installed あー、インストール済みのを調べたいのね

という感じですんなり理解できる。

こまかい違いだけど、こういうルールで統一されてるからこそ、
働く人が少しずつラクチンになっていくのかもしれない。
We couldn't retrieve the action output. Try again or contact Salesforce Customer Support for assistance


+ [Agentforce Actions エラーの考察(Idが正しくない？)](https://qiita.com/Keiji_otsubo/items/5aff7a81c231cba493e1)

---------------
具体的なエラーを探すのが困難なエラーメッセージです。

+ [Agent is unable to 'retrieve action output'](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000P7Jf0AK)

:::note
I was able to figure it out last night, turns out that there was an issue with my input variable, which prevented the flow from even launching (hence why my fault emails weren't even firing).
:::

+ [Apex @InvocableMethod が使用されている場合、結果のテーブルを Agentforce で返してテーブルとしてフォーマットできますか?](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000J8zd80AB)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8f91df44-a1f4-d328-f409-499968f6ce6f.png)

+ [【消されています】custom agent action failing to retrieve the action output](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000KCuR30AL)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/46131f0e-5d8a-3a00-a873-a8d9ebf09aee.png)

+ [Error when create a lead in agentforce](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000PWNQr0AP)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/ff203432-0211-4fd8-b7ea-675c611001d7.png)
VOICEVOX（zip版）を使って読み上げwavを作る際のメモ

# はじめに

会社でずんだもんに何かを読み上げさせたい時、VOICEVOXを使いたくなる時がありますね。
ただ、会社PCだとレジストリをいじるようなexeを禁止されている場合もあります。
そこで、zip版でできるかどうかを確かめてみます。

# 手順

## 0. VOICEVOXのインストール

公式サイトに移動。

https://voicevox.hiroshiba.jp/

ここで、ダウンロード時に「Zip」を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308248/327bade5-4fd3-40bc-1074-aea55bb6dae3.png)

「Zip」を選ぶと、インストーラがないので、任意のフォルダに置いてしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308248/145d74a0-88f6-d511-7e8d-0f295f76609b.png)

なお、実際のwav作成はWeb APIを使って作成するので、環境変数でPATHを設定するなどの作業も不要です。

当たり前ですが、インストールは初回のみでOK。

## 1. VOICEVOXを起動

上記フォルダのVOICEVOX.exeを起動。

ブラウザで http://127.0.0.1:50021 を叩き、サーバが立ち上がっていることを確認。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308248/1aa66b1a-cd99-35ca-43ad-b2a65f0d6dac.png)

## 2. Web APIを叩いて、wav作成

この状態で、PythonなどでWeb APIを叩けばwavは作成できます。サンプルコードはQiitaにたくさんありますので、適宜参考にしてください。たとえば、以下をご参照。

https://qiita.com/hatt_takumi/items/d65c243294f250724c19

# メモ

- 基本的に、http://127.0.0.1:50021/audio_query で作りたい音声合成用のクエリを作って、帰ってきたレスポンス(json)を使って http://127.0.0.1:50021/synthesis に送り付けるとwavのバイナリが返ってくるので、それをファイルにして保存するという流れ。
- 読み上げ速度を変更したい場合などは、最初のレスポンスjsonを直接書き換えるようだ。

上記のサイトを参考にアレンジすると

~~~ vvt.py
import json
import requests
import wave

# パラメータ
params_dict = {
    'text' : "これはテストなのだ。",
    'speaker': 1
}
# 追加のパラメータ
data_dict = {
    'speedScale': 1.3
}

def generate_wav(filepath='./audio.wav'):
    host = 'localhost'
    port = 50021
    response1 = requests.post(
        f'http://{host}:{port}/audio_query',
        params=params_dict
    )
    headers = {'Content-Type': 'application/json',}

    # 追加のパラメータ
    my_audio_query = response1.json()
    for key, value in data_dict.items():
        my_audio_query[key] = value

    response2 = requests.post(
        f'http://{host}:{port}/synthesis',
        headers=headers,
        params=params_dict,
        data=json.dumps(my_audio_query)
    )

    wf = wave.open(filepath, 'wb')
    wf.setnchannels(1)
    wf.setsampwidth(2)
    wf.setframerate(24000)
    wf.writeframes(response2.content)
    wf.close()

if __name__ == '__main__':
    generate_wav()
~~~

あとは、params_dict.textを外部ファイル化などすれば、より便利になるだろうと感じた。

# 2025/02/20追記

「より便利になるだろう」という点を改造しました。

https://qiita.com/hideh_hash_845/items/bc98e5068d83dbd5cbf1

（つづく）
アロー関数とは？


# 🌟 アロー関数とは？  
アロー関数 (`=>`) は、**短くてスッキリ書ける関数** のこと！  
JavaScriptの普通の関数 (`function`) よりも、**見た目がシンプルでスマート** になるよ！  

---

## 🆚 普通の関数 vs アロー関数  
まずは、普通の関数 (`function`) から！  

```js
function sayHello(name) {
    return "こんにちは、" + name + "さん！";
}
console.log(sayHello("さくら")); // こんにちは、さくらさん！
```

👉 これをアロー関数にすると…  

```js
const sayHello = (name) => "こんにちは、" + name + "さん！";
console.log(sayHello("さくら")); // こんにちは、さくらさん！
```

🌟 **たった1行になってスッキリ！**  
`function` がなくなって、`(引数) => 処理` って形になったね！  

---

## 🎯 アロー関数のポイント  

### ✅ 1. 引数が1つならカッコ `()` 省略OK！  
```js
const double = num => num * 2;
console.log(double(5)); // 10
```

### ✅ 2. `{}` がないと `return` も省略OK！  
```js
const add = (a, b) => a + b;
console.log(add(3, 7)); // 10
```

### ✅ 3. 処理が複数あるなら `{}` を使う！  
```js
const greet = (name) => {
    console.log("ようこそ！");
    return "こんにちは、" + name + "さん！";
};
console.log(greet("たけし"));
```

---

## 🚨 注意点（ここだけは気をつけて！）  

### ❌ `this` の扱いが違う！  
アロー関数では `this` が **外側のスコープ（親のthis）を引き継ぐ**！  
普通の `function` とは動きが違うから注意！  

```js
const obj = {
    name: "さくら",
    hello: function() {
        console.log(this.name); // さくら
    },
    arrowHello: () => {
        console.log(this.name); // undefined（外側の `this` を引き継ぐ）
    }
};

obj.hello();      // さくら
obj.arrowHello(); // undefined
```

---

## 🎉 まとめ  
✅ **アロー関数 (`=>`) でスッキリ書ける！**  
✅ **1行（すみません💦 単一の式が正しいです）なら `{}` や `return` も省略OK！**  
✅ **`this` の扱いは普通の関数と違うので注意！**  

アロー関数、めっちゃ便利だからバンバン使っていこう！🔥✨
OACのホームから任意のWebページへのリンクを作成する

# はじめに
OAC（**Oracle Analytics Cloud**）にログインすると最初に表示されるのが、「ホーム」です。
ホームには、ワークブックをはじめ様々なものを表示することができますが、そのひとつにカスタムグループがあります。
カスタムグループには、任意のアイテムが追加できます。
この記事では、カスタムグループに特定のWebページへのリンク（URLアイテム）を追加する方法を紹介します。

# カスタムグループを追加
OACにログインします。
ホームで任意のワークブックのメニューを開き、「カスタム・グループに追加」「新規カスタム・グループ」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/891268d2-9d69-3045-4dbc-a0a9a38c5b7f.png)

どのワークブックを使っても構わないのですが、もしも目的のワークブックがホームに表示されていない場合は、検索バーを使用して検索します（またはカタログメニューから探します）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/04f30845-3074-594d-680a-41f85825c2e3.png)

## 新しいカスタム・グループに名前をつけて保存

「カスタムグループ」という名前にしました（後から考えると、もっと的確な名前にした方が良かったです）。
「追加」をクリックすると、新しいカスタム・グループにワークブックが追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/0113dfd3-3022-ea9a-b2bd-8d89356fd307.png)

カスタムグループがホームに表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/6ef0634f-f7f0-1059-1b85-32fa3253b791.png)

## カスタムグループにURLアイテムを追加
カスタムグループのメニューを開き、「URLアイテムの追加」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/0276f369-450b-b7d2-6be1-d9ab8fd7e59f.png)

任意のURLを入力して、「OK」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/37d6af53-042f-cd30-0122-65aad101aec4.png)

URLアイテムが追加されました。
カスタムグループに追加したURLアイテムをクリックしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/8374a885-e4fa-b16b-9deb-ea852f6fce96.png)

新しいタブで、設定したWebページが表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/6b07a301-b270-2b91-1707-3ed4b62d4e05.png)

## 不要になったアイテムをカスタムグループから削除
不要なアイテムのメニューを開き、「カスタム・グループから削除」をクリックします。
間違えて「削除」をクリックしないようにしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/ff3063bc-cf2f-6387-8815-1babf4a065d9.png)

# おわりに
カスタム・グループは他のユーザーと共有することができます。
検査メニューの「アクセス」タブで、ユーザーやロールを指定してください。
[GAS] 動的ページをスクレイピングする

## きっかけ
GASは静的ページなら簡単にスクレイピングできるが、動的ページはそれができないので`PhantomJSCloud`という外部サービスを使う。

## PhantomJSCloud
https://phantomjscloud.com/

APIキーの取得方法はまた後日
無料：1日に500回

## 完成コード
~~~Javascript
function phantomJSCloudScraping(URL) {
  //スクリプトプロパティからPhantomJsCloudのAPIキーを取得する
  let key = PropertiesService.getScriptProperties().getProperty('PHANTOMJSCLOUD_ID');

  //HTTPSレスポンスに設定するペイロードのオプション項目を設定する
  let option ={
    url: URL,
    renderType: "HTML",
    outputAsJson: true
  };
  
  //オプション項目をJSONにしてペイロードとして定義し、エンコードする
  let payload = JSON.stringify(option);
  payload = encodeURIComponent(payload);
  
  //PhantomJsCloudのAPIリクエストを行うためのURLを設定
  let apiUrl = "https://phantomjscloud.com/api/browser/v2/" + key + "/?request=" + payload;
  
  //設定したAPIリクエスト用URLにフェッチして、情報を取得する。
  let response = UrlFetchApp.fetch(apiUrl);
  
  //取得したjsonデータを配列データとして格納
  let json = JSON.parse(response.getContentText());
  
  //APIから取得したデータからJSから生成されたソースコードを取得
  let source = json["content"]["data"];

  return source;
}
~~~

## 概説
引数：動的WebページのURL
戻り値：HTMLのソースコード

`PHANTOMJSCLOUD_ID`：PhantomJSCloudのAPIキー（スクリプトプロパティで設定）

## 躓いた事
というか複数ページのテストを１日に何度もやってると割とすぐに５００回制限に引っかかったので、その日の動的ページを取得してGoogleDriveに保存してそれでテストしてました。
~~~Javascript
function createFile(fileName, content) {  
  var folder = DriveApp.getFolderById('フォルダID');
  var contentType = 'text/plain';
  var charset = 'utf-8';

  // Blob を作成する
  var blob = Utilities.newBlob('', contentType, fileName)
                      .setDataFromString(content, charset);

  // ファイルに保存
  folder.createFile(blob);
}

function todayPhantom() {
  let url = "対象URL";
  createFile("PhantomJsCloud_Raw.html",phantomJSCloudScraping(url));
}
~~~
フォルダIDのGoogleDriveのフォルダに`PhantomJsCloud_Raw.html`ができるので、それでテストする。

## まとめ
PhantomJSCloudを間に挟むだけなので、後は静的ページのスクレイピングと同じなので比較的簡単！
nvm node バージョン固定

# nodeのバージョン固定
nvmでnodeのバージョンを切り替えているのですが、WSLを再起動するたび元に戻ってしまうのでdefault設定をしたいと思います。

## 現状
バージョンを確認すると、v16が使われています。
```bash
node -v

# v16.20.1
```

今の開発環境では、v20.x.x.が必要なので以下の様にしています。
```bash
nvm use v20

# v20.0.0
```

ただし、WSLを再起動すると、v16に戻ってしまいます。

## 解決法
[こちら](https://qiita.com/yuzooho/items/a5072ade3a0787640ef9)を参考にdefault設定をします。

```bash
nvm alias default v*.*.*
```

v20に設定したいので以下を設定します。

```bash
nvm alias default v20.0.0

# default -> v20.0.0
```

`default -> v20.0.0`となりました。再起動し、`node -v`とすると、設定した`v20.0.0`になっていることを確認できました。
@lazarv/react-serverの環境構築方法について (You can remove the following packages from your project:   react@19.0.0 expected: react)

# はじめに

https://react-server.dev/

の環境構築をするときに環境構築の方法を間違えていたのでまとめます

# 問題

ViteでReactの環境構築をしてから@lazarv/react-serverをインストールすると以下のエラーが出ます

```
> react-server

You don't need to install react, react-dom or react-server-dom-webpack in your project.
@lazarv/react-server already includes a specific version of react, react-dom and react-server-dom-webpack that is compatible with the current version of @lazarv/react-server.
You can remove the following packages from your project:
  react@19.0.0 expected: react@0.0.0-experimental-de1eaa26-20250124 
```

以前別の方法で回避していたのですが、うまくいかないケースがありました

https://qiita.com/Sicut_study/items/56825e1afdf7001c9ad7

# 環境構築方法

@lazarv/react-serverは他のフレームワークとはすこし変わった方法で環境構築ができます。

まずはViteでTypeScriptの環境構築をします

```
$ npm create vite
✔ Project name: … react-server-handson
✔ Select a framework: › Vanilla
? Select a variant: › - Use arrow-keys. Return to submit.
❯   TypeScript

$ cd react-server-handson
$ npm i @lazarv/react-server
```

こうすることで@lazarv/react-serverにはReactも同梱されているためサーバーが立ち上げられます。

```
$ touch react-server.config.mjs
```

```mjs:react-server.config.mjs
export default {
  root: "src/app",
};
```

```
$ mkdir src/app
$ touch src/app/page.tsx
```

```tsx:src/app/page.tsx
export default function Home() {
  return <div>Home</div>;
}
```

またVSCodeでjsxについて怒られるので`tsconfig.json`を直します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/a3ca3a5c-2074-68f7-6684-26e6ca889e67.png)


```json:tsconfig.json
{
  "compilerOptions": {
    "jsx": "react-jsx", // 追加
    "target": "ES2020",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": true,

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedSideEffectImports": true
  },
  "include": ["src"]
}
```

```
$ npm run dev
```

[http://localhost:3000](http://localhost:3000)を開くと無事ページが表示されました


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/2c5878ba-efd0-7db6-2ddb-fc76666c1023.png)

# おわりに

今後もreact-serverをたんきゅうしてきます
[Next.js] server-onlyとuse server(server action)の違いと使い分け

## server-onlyとは？
処理がサーバーでのみ実行される保証をしたい。Server Componentでのみ利用可能にしたい時に有効。
client側では呼び出すことができず、build時にerrorとなります

例えば以下のコードはClient ComponentでもServer Componentでも含めることが可能ですが、process.env.API_KEYがprivateな環境変数であるため、Client Componentでは動作しません。

動作しないにも関わらずimportができてしまい、build時にerrorも発生しません。

`import 'server-only'`を追加することにより、開発者にServer Componentでのみ利用可能である意図を伝えるとともに、build時にerrorを出すことが可能です。
```ts
// 追加する
import 'server-only'

export async function getData() {
  const res = await fetch('https://external-service.com/data', {
    headers: {
      authorization: process.env.API_KEY,
    },
  })
 
  return res.json()
}
```

使用には追加のinstallが必要です
```
$ npm install server-only
```

https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns

## server action
サーバー上で実行される非同期関数のこと
reactの"use server"ディレクトリを使って定義できる
- 非同期(async)関数の先頭におくことで、関数をserver actionとしてマーク
- 別のファイルの先頭に配置してそのファイルの全てのエクスポートをマーク
インライン(関数の中の非同期関数をserver actionとするには1つ目の方法)
`クライアントコンポーネント`で呼び出して利用するには、2を使う
```ts
export default function Page() {
  // Server Action
  async function create() {
    'use server'
    // Mutate data
  }
 
  return '...'
}
```

client componentからもserver actionが利用できるのは嬉しいですね
そして何より嬉しい点は、formのaction要素からも実行できる点です。 これによりformのstate管理が不要になります
[server actionをformで使う例](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#forms)



https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
簡単AWS  SQS（Simple Queue Service）

# AWS SQS（Simple Queue Service）とは？

AWS SQS（Simple Queue Service）は、**メッセージキューサービス** です。システム間でデータ（メッセージ）をやり取りする際に、メッセージを一時的に保存して**非同期処理**を実現するために使用されます。

## 🎯 SQSの特徴

### ✅ 非同期処理が可能
- 送信側（プロデューサー）と受信側（コンシューマー）が直接やり取りせずに、SQSを介してメッセージを受け渡せる。
- これにより、処理の負荷を分散し、システムの柔軟性を向上させる。

### ✅ フルマネージドサービス
- AWSがスケーリングや可用性を管理してくれるので、運用負担が少ない。

### ✅ 異なるコンポーネント間の疎結合化
- メッセージをキューに蓄積し、コンシューマーが必要に応じて処理するため、システムの依存関係を減らせる。

### ✅ 2つのキュータイプ

| キュータイプ | 特徴 |
|-------------|------|
| **Standard Queue**（標準キュー） | 無制限のスループット、**メッセージの順序は保証されない**（Best-Effort Ordering）、**メッセージの重複が発生する可能性がある**（At-Least-Once Delivery） |
| **FIFO Queue**（FIFOキュー） | **メッセージの順序を保証**（First-In-First-Out）、**重複メッセージなし**（Exactly-Once Processing）、スループットに制限あり（最大300TPS） |

## 🏗 基本的な動作の流れ
1. **プロデューサー（送信側）** がSQSキューにメッセージを送信
2. **SQSがメッセージを保存**（一定時間キューに保持可能）
3. **コンシューマー（受信側）** がメッセージを取得し処理
4. **メッセージを削除**（処理完了後、コンシューマーがSQSから削除）

## 📌 具体的なユースケース
- **注文処理システム**  
  → 注文データをSQSに入れて、バックエンドで順次処理する
- **動画処理・画像変換**  
  → 動画アップロード後、SQSを通じて非同期にエンコード処理
- **ログ処理・イベント駆動アーキテクチャ**  
  → マイクロサービス間でのメッセージ連携に利用

## 🚀 関連AWSサービス

| サービス | 説明 |
|----------|------|
| **SNS（Simple Notification Service）** | メッセージのプッシュ配信（サブスクライブ） |
| **Lambda** | SQSのメッセージをトリガーにして処理を実行 |
| **Amazon EventBridge** | システム間のイベント連携 |

## 💡 まとめ
AWS SQSは、システムのスケーラビリティを向上させ、非同期処理を簡単に実装できるメッセージキューサービスです。特にマイクロサービスや分散システムでの活用が多く、**負荷分散**や**スケーラビリティの向上**に役立ちます。
GitHub Pagesで独自ドメイン設定した byムームードメイン

## 前置き
とにかく手を動かそう！ということで、swiftでのiOSアプリは一旦中断して、javascriptやpythonで簡単なwebアプリを思いついただけ作っていくことにした。

そして、GitHubにも慣れなきゃと思い...
エディタ：Visual Studio Code
管理:GitHub
で管理していきます。

まず戸惑ったのが、GitHub Pagesで独自ドメインを設定すること
その過程を備忘として残しておく

## 独自ドメインを設定しよう

### 1.ムームドメインの設定

DNSサーバに以下の内容を入力

ネームサーバ:ムームーDNS

設定２
内容
185.199.108.153
185.199.109.153
185.199.110.153
185.199.111.153

種別：A(全部）

![スクリーンショット 2025-02-04 9.14.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3786034/1444f2aa-23ca-dc83-bfd5-accf1c5e238a.png)

### 2.GitHub Pages設定

GitHub Pages＞Setting＞Custom Domainに取得したドメインを入力(www不要）

Saveを押して、問題なくSaveできたら、Enforce HTTPSにチェックボックスがアクティブになる

ここでサイトをhttpsにする場合は、Enforce HTTPSのチェックボックスをON

![スクリーンショット 2025-02-04 9.15.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3786034/61335447-4f55-8fe6-a3db-1102c56aaf0b.png)

これで無事、取得したドメインでサイト閲覧できた。

色々ネットを調べたんだけど検索能力や読解力が足りなくて理解できず、結果chatGPTで確認したところ方法を教えてくれてその通りにやっただけ。
ってことはやっぱり色々なサイトに載ってたんだよなぁ:frowning2:

まだまだ知見が足りない

## 学習したこと

:::note alert
ポートフォリオ作成のため、レンタルサーバーをロリポップ、ドメインをムームードメインで取得していたので、webアプリ用もムームードメインで取得した。

合わせてロリポップに独自ドメインを設定しちゃったことが躓いた理由。
他サーバでドメイン設定してたら、それはダメだよね:no_good_tone1:
:::
Google Sheets新機能「Gemini」で実現するデータ分析の効率化

# はじめに
2025年1月にリリースされたGoogle Sheetsの新機能「Gemini」について、具体的な活用例を交えて解説します。売上データのサンプルを例に、どのようなインサイトが得られるのか、実際に試してみましょう。

# サンプルデータ
以下のサンプルデータをGoogle Sheetsに貼り付けてください。
```csvs
顧客企業名,業界,地域,セグメント,月間収益,最終購入日,製品カテゴリ,顧客満足度
朝日メディカルセンター,ヘルスケア,関東,中小企業,1700000,2024-01-15,医療機器,4.8
光星産業,ヘルスケア,近畿,中小企業,50000,2024-01-20,消耗品,4.2
千代田ヘルスケア,ヘルスケア,関東,中小企業,230000,2024-01-18,ソフトウェア,4.5
大和メディカル,ヘルスケア,中部,大企業,1850000,2024-01-10,医療機器,4.9
栄和産業,ヘルスケア,九州,中堅企業,150000,2024-01-22,ソフトウェア,4.3
藤医療,ヘルスケア,四国,中小企業,40000,2024-01-25,消耗品,3.9
銀河ソリューションズ,ヘルスケア,中部,中小企業,1500000,2024-01-12,医療機器,4.7
飯田メディカル,ヘルスケア,北海道,中小企業,65000,2024-01-28,消耗品,4.1
勝田グループ,ヘルスケア,関東,中堅企業,270000,2024-01-05,ソフトウェア,4.4
望月メディカル,ヘルスケア,近畿,大企業,1950000,2024-01-08,医療機器,4.8
武蔵野グループ,ヘルスケア,中部,大企業,1400000,2024-01-17,医療機器,4.6
新井医療,ヘルスケア,九州,中小企業,38000,2024-01-30,消耗品,3.8
奥村病院,ヘルスケア,四国,大企業,1650000,2024-01-03,医療機器,4.7
平和ヘルスケア,ヘルスケア,関東,中堅企業,380000,2024-01-14,ソフトウェア,4.5
富士見ウェルネス,ヘルスケア,北海道,中小企業,43000,2024-01-27,消耗品,4.0
涼風クリニック,ヘルスケア,近畿,中小企業,280000,2024-01-19,ソフトウェア,4.3
清水診断システム,ヘルスケア,九州,中堅企業,360000,2024-01-07,ソフトウェア,4.6
月島メディカル,ヘルスケア,中部,大企業,1780000,2024-01-11,医療機器,4.8
東海ソリューションズ,ヘルスケア,関東,中堅企業,320000,2024-01-21,ソフトウェア,4.4
宇治川研究所,ヘルスケア,近畿,中小企業,210000,2024-01-16,ソフトウェア,4.2
瑞穂ヘルスケア,ヘルスケア,中部,中堅企業,410000,2024-01-09,ソフトウェア,4.5
```
使用方法:
1. 新しいGoogle Spreadsheetを開く
2. A1セルにカーソルを置く
3. このCSVデータをコピー&ペースト
4. データ → 「テキストを列に分割」を選択
![spredsheet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/edf75e4d-1e9e-73df-882c-6ffa80feeb83.png)

# Geminiの新機能
1. Pythonコードの自動生成による高度な分析
例えば、「地域別の売上分布を分析して」と指示するだけで、以下のようなPythonコードが自動生成され、実行されます。
```python
import pandas as pd
import matplotlib.pyplot as plt

def analyze_regional_sales(data):
    regional_sales = data.groupby('地域')['月間収益'].sum()
    return regional_sales.sort_values(ascending=False)
```

2. インタラクティブな分析機能
例えば以下のような分析が自然言語で可能です。
+ 「関東地域の医療機器カテゴリの平均売上を教えて」
+ 「顧客満足度が4.5以上の企業の特徴を分析して」
+ 「製品カテゴリごとの売上推移をグラフ化して」

# 活用のポイント
a. データの前処理
+ ヘッダーの統一
+ 数値データの正規化
+ 欠損値の適切な処理
 
b. 効果的な指示の出し方
+ 具体的な分析目的を明確に
+ 必要な集計単位を指定
+ 可視化の形式を指定
 
c. 結果の検証
+ 自動生成されたコードの確認
+ 異常値のチェック
+ クロスバリデーション

# まとめ
Geminiの導入により、以下のような効果が期待できます。
+ データ分析の民主化
+ 分析作業の効率化
+ インサイト発見の迅速化

特に、Pythonコードの自動生成機能は、データサイエンティストではない実務担当者でも、高度な分析が可能になる点で画期的です。

# 参考文献
https://9to5google.com/2025/01/29/google-sheets-gemini-insights/

https://support.google.com/docs/answer/14218565?hl=ja
【css】横に少しだけズレが生じる時の直し方

# 問題
全体コンテンツの高さが
・ファーストビューに収まらなかった時
・収まった時
↓
横へ少しだけズレが生じる

# 原因
全体コンテンツの高さによって横ズレが生じる問題は、スクロールバーの有無
・スクロールバーが表示される時 → 右側にスペースが生まれ、ページの幅が縮む。
・スクロールバーが表示されない時 → 幅が変わらない。

# 解決策：overflow-y-scroll
「Tailwind」の「overflow-y-scroll」を「html or body」に適用すると、常にスクロールバーを表示するのでズレがなくなる。
```
<body class="overflow-y-scroll">
  <div class="container mx-auto">
    <!-- コンテンツ -->
  </div>
</body>
```
テンプレートリテラル`${}`でコードの可読性が上がる

多くの場合、`console.log`でコメントを出す際には、変数が含まれていると思います。
その際に
```java:log
const name = Tom;
console.log("Hello, " + name);
```
などと書いていないでしょうか？
初歩的なことですが、
```java:log
const name = Tom;
console.log(`Hello, ${name}`);
```
と書くと、可読性が上がります！変数を{}で括って、$を付けるだけです。
文字列を括るのは"や'ではなく、\`(SHIFT＋@で出ます)であることに気を付けてください。
たった二行のコードだと、その便利さは分かりませんが、長いコードを書くと、いちいち"+"でつなぐ記法だと読みづらくて仕方ありません。
積極的に\`${}`を使っていきましょう。
FreeBSDでfirmware解析

ルーターなどのオリジナルのファームウエアのファイルシステムをFreeBSD上で解析してみます。

binwalkとsquashfs-toolsのpkgをインストールしておきます。

```
% binwalk -Me hoge.bin
% unsquashfs 1234.squashfs
```

squashfs-rootというディレクトリが出来てファイルが展開されます。

あとはこつこつ中身を調べてください。
Account Engagement リストメールとメールテンプレートの比較



+ [Account Engagement リストメールとメールテンプレートの比較](https://help.salesforce.com/s/articleView?id=000382710&type=1)

リストメールとメールテンプレートのどちらを作成するかの選択で混乱する場合があります。ただし、この 2 つの違いを理解すると、どちらの種別のメールが適切であるかを容易に判断することができます。

+ **メールテンプレート**は、すべての自動送信で使用することができます。これには、自動応答メールや Engagement Studio メールが含まれます。テンプレートを使用してリストメールを送信することもできますが、これが混乱の原因となる場合があります。リストメールを作成する際には、事前に作成されたテンプレートを選択することができ、すでに確立されたスタイルやブランド設定を含めるだけでなく、テンプレートのコンテンツを再利用することもできます。メールテンプレートのレポートは、Account Engagement 内でのみ利用可能で、Salesforce のレポートでは利用できません。メールテンプレートでは、完了アクションは利用できません。

Account Engagement テンプレートは、印刷されたはがきに似ています。一度設定し、繰り返して何度も使用します。
テンプレートは次のような場合に使用します。​
+ 自動応答メール
+ Engagement Studio
+ リストメール

------------------

+ **リストメール**は、1 回の送信を目的として作成されます。1 回の送信の例として、ニュースレターやオペレーショナルメール (将来再設定する必要がないコンテンツ) があります。1 度送信されたリストメールは、コピーや編集が可能ですが、テンプレートのように再利用することはできません。リストメールのレポートは、Salesforce の Engagement History を用いることによって確認することができます。送信前のリストメールに完了アクションを適用することができます。

Account Engagement リストメールは手書きのはがきに似ています。つまり、1 回のみ使用します。
リストメールは次のような 1 回の送信で使用します。
+ ニュースレター
+ 運用上の更新

+ [リストメール用の Lightning メール テンプレート](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000LIU65SAH)

Lightning テンプレートリストメールは、「Pardot メール」(レガシー) タブでは送信できません。リスト メールは、「メール コンテンツ」というタブ/オブジェクトで Lightning ページ ビルダーを使用して作成し、送信する必要があります。そのオブジェクトで作成/スケジュールすると、レガシー Pardot メール タブのスケジュール済み/送信済みセクションに表示されます (図のように「ビルダー メール」のオプションを使用します)。スケジュールすると、スケジュール済み送信を実際にキャンセルできるのは、この方法だけです。ツールが移行されるにつれて、少し混乱します... 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8735cd2a-a07e-e506-6a66-606497d30745.png)

移行を容易にするために、メールコンテンツタブとメールテンプレートタブを Pardot Lighting アプリに追加して、前面中央に配置することをお勧めします。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/09383623-5de1-7e44-519e-aca104b03c48.png)
SQLでカレンダーとかインデックスの付番

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417736/6c51e529-ef99-61ed-ad99-75457f2be8fc.png" alt="mysql" width="156">

一定期間のカレンダーを生成したり、結果に論理番号を付番するメモ

## カレンダー

起算日(2025-01-01) + オフセット(0..*)でカレンダーを作成する
### オフセットの準備

指定レンジでインクリメンタルなオフセット値を持つテーブルを作成する

- オフセット値は変数に持ち歩かせる
- information_schema.COLUMNSのクエリ結果でレンジ行を確保しつつ、オフセット値を格納
- LIMITでレンジを切る

```sql:sql
-- 1行目でレンジ変数初期化
SELECT @_index := 0 AS _index -- 0
-- 2行目以降をUNIONで結合
UNION
-- 行確保のため、information_schema.COLUMNSをクエリして、レンジ変数をインクリメント
SELECT @_index := @_index + 1 AS _index FROM information_schema.COLUMNS -- 1..*
-- レンジの上限=7行
LIMIT 7;
```

```
+--------+
| _index |
+--------+
|      0 |
|      1 |
|      2 |
|      3 |
|      4 |
|      5 |
|      6 |
+--------+
```

### カレンダーにする

* 起算日(2025-01-01)にオフセット値を加算する

```sql:sql
SELECT '2025-01-01' + INTERVAL _range._index DAY AS DATE FROM (
  -- 1行目でレンジ変数初期化
  SELECT @_index := 0 AS _index
  -- 2行目以降をUNIONで結合
  UNION
  -- 行確保のため、information_schema.COLUMNSをクエリして、レンジ変数をインクリメント
  SELECT @_index := @_index + 1 AS _index FROM information_schema.COLUMNS
  -- レンジの上限=10個
  LIMIT 7
) _range;
```

```
+------------+
| DATE       |
+------------+
| 2025-01-01 |
| 2025-01-02 |
| 2025-01-03 |
| 2025-01-04 |
| 2025-01-05 |
| 2025-01-06 |
| 2025-01-07 |
+------------+
```

## 論理番号を付番する

クエリ結果に対して、論理番号を付番して意味付けする

こんな科目-点数テーブルがあったとして

```
+-----------+-------+
| category  | score |
+-----------+-------+
| 国語       |    84 |
| 国語       |    91 |
| 国語       |    77 |
| 数学       |    88 |
| 数学       |    98 |
| 数学       |    81 |
| 理科       |    50 |
| 理科       |    80 |
| 理科       |    68 |
+-----------+-------+
```

### 結果に行番号を付番する

- 行番号を変数に持ち歩かせる
- FROM句で変数を初期化する

 全教科の点数ランキング

```sql:sql
SELECT
  -- 結果順に変数を加算
  @_rank := @_rank + 1 AS rank,
  score.category,
  score.score
FROM
  score,
  -- 変数を初期化。テーブルに用はない
  (SELECT @_rank:= 0) AS row_num
-- score降順
ORDER BY score.score DESC;
```

```
+------+----------+-------+
| rank | category | score |
+------+----------+-------+
|    1 | 数学      |    98 |
|    2 | 国語      |    91 |
|    3 | 数学      |    88 |
|    4 | 国語      |    84 |
|    5 | 数学      |    81 |
|    6 | 理科      |    80 |
|    7 | 国語      |    77 |
|    8 | 理科      |    68 |
|    9 | 理科      |    50 |
+------+----------+-------+
```

教科ごの点数ランキング

- 付番する軸=教科の変わり目で行番号を初期化する

```sql:sql
SELECT
  -- 付番する軸=教科の変わり目で行番号を初期化する
  @_rank := IF(@prev_category = score.category, @_rank + 1, 1) AS rank,
  @prev_category := score.category AS category,
  score.score
FROM score
-- カテゴリ×score降順
ORDER BY score.category ASC, score.score DESC
```

```
+------+----------+-------+
| rank | category | score |
+------+----------+-------+
|    1 | 国語      |    91 |
|    2 | 国語      |    84 |
|    3 | 国語      |    77 |
|    1 | 数学      |    98 |
|    2 | 数学      |    88 |
|    3 | 数学      |    81 |
|    1 | 理科      |    80 |
|    2 | 理科      |    68 |
|    3 | 理科      |    50 |
+------+----------+-------+
```
Sys IDがリストビューに表示されない理由［ServiceNow］

※この記事はServiceNow初心者が学習用のために記載した記事です。内容について誤っている場合がございます。不足点などございましたらコメントいただけますと幸いです。

# Sys IDとは
Sys ID（シスアイディー） は、ServiceNow の すべてのレコードを一意に識別する 32 文字の文字列（UUID）である

# リストビューでSys IDが表示されない理由
Sys IDがフィールドにない！たまにしか見かけない！その理由

- sys_id は UI で直接表示するためのカラムではない
    - sys_id は ServiceNow の内部識別子であり、通常のフィールドではなく「システムフィールド」 に分類されるため、リストビューのカラム管理に表示されないことがある
- UI 設定で sys_id が非表示になっている
    - ServiceNow の UI ポリシーやシステム設定で sys_id をリストビューに表示しないように制限されている場合がある

### 表示される場合
- sys_id がカスタムカラムとしてテーブル定義に追加されている
- 高度な権限を持つユーザー（admin 権限など）でログインしている
- システム設定が sys_id の表示を許可している

### 表示されない場合
- sys_id は UI 用のカラムではなく、内部識別子として扱われる
    - sys_id は データベースの主キー（UUID） として機能するため、デフォルトでは ユーザーが直接操作するフィールドではないため、カラム管理の候補に表示されないことが多い
- フィールドが sys_dictionary に登録されていない
    - sys_id は sys_dictionary テーブル（フィールド定義を管理するテーブル）に明示的に登録されていないため、カラム管理の対象として表示されない ことがある
- UI 設定（View Configurations）で非表示になっている
    - インスタンスごとに UI の表示設定が異なり、管理者が sys_id をカラム管理に表示しないように設定 している場合がある
- 一般ユーザー（admin 以外）の権限では表示されない
    - 一部のインスタンスでは、sys_id の表示は admin のみ許可されていることがある
Sys IDを取得する方法［ServiceNow］

※この記事はServiceNow初心者が学習用のために記載した記事です。内容について誤っている場合がございます。不足点などございましたらコメントいただけますと幸いです。

# Sys IDとは
Sys ID（シスアイディー） は、ServiceNow の すべてのレコードを一意に識別する 32 文字の文字列（UUID）である

- 特徴
    - 各レコードに一意の値が割り当てられる（重複しない）
    - テーブル間で一意（incident テーブルのレコードと user テーブルのレコードは異なる Sys ID を持つ）
    - 削除されない限り変わらない
    - 手動で変更不可
- Sys ID の用途
    - レコードの特定
        - 例: incident レコードの sys_id を使って特定のインシデントを取得
    - レコード間のリレーション
        - 例: assigned_to フィールドには sys_user テーブルの sys_id が格納され、ユーザーを参照
    - API / GlideRecord でのデータ操作
    - sys_id を使えば、特定のレコードを素早く取得できる

# Sys IDの取得方法
### ① レコードの URL から確認
レコードのフォームを開くと、URL に sys_id が含まれる
```
https://your-instance.service-now.com/incident.do?sys_id=1234567890abcdef1234567890abcdef
```
### ② リストビューで表示
リストビューの「カラムの管理」から sys_id を追加

### ③ リスト画面で右クリック
右クリックするとsys_idを確認する項目がある


### ④ GlideRecord で取得
```
var gr = new GlideRecord('incident');
gr.addQuery('number', 'INC0010023'); // インシデント番号で検索
gr.query();
if (gr.next()) {
    gs.info("Sys ID: " + gr.sys_id);
}
```
［ServiceNow］Customer Updates（sys_update_xml）のpayloadフィールドについて

※この記事はServiceNow初心者が学習用のために記載した記事です。内容について誤っている場合がございます。不足点などございましたらコメントいただけますと幸いです。

# 前提知識
- Customer Updates（sys_update_xml）テーブルとは
    - sys_update_xmlテーブルは、ServiceNow 内の更新セット (Update Set) に関連する変更を管理するテーブル
    - フォームやスクリプト、ビジネスルールなどのカスタマイズが加えられると、その変更がこのテーブルに記録される

# payloadフィールドとは
- 更新内容の XML データが格納される
- payload は、変更されたレコード（スクリプト、UI ポリシー、カスタムアクションなど）の XML 形式のデータ を保存するフィールド
    - XML データには、変更前後の情報や関連するメタデータが含まれる

# payload フィールドの内容
- ServiceNow で Incident レコード (incident テーブル) が更新された場合
- 更新内容
    - number: INC0010023
    - short_description: "ユーザーがVPN接続できない"
    - state: New (1) → In Progress (2)
    - assigned_to: John Doe (sys_id: abc123def456)
- この場合、payload は以下のような XML になる
```
<record_update>
  <update>
    <table>sys_script</table>
    <sys_id>1234567890abcdef</sys_id>
    <action>UPDATE</action>
    <record>
      <sys_name>MyCustomScript</sys_name>
      <script>
        var myVar = "Hello, ServiceNow!";
        gs.info(myVar);
      </script>
    </record>
  </update>
</record_update>
```
# payload の構造
| XML タグ            | 説明 |
|---------------------|------|
| `<table>`          | 更新対象のテーブル名 (`incident`) |
| `<sys_id>`         | 変更された `incident` レコードの `sys_id` |
| `<action>`         | `UPDATE` (更新) |
| `<record>`         | レコードのフィールド値 |
| `<number>`         | インシデント番号 |
| `<short_description>` | 短い説明 |
| `<state>`          | インシデントのステータス (`1: New`, `2: In Progress`, `3: Resolved` など) |
| `<assigned_to>`    | `sys_id` 形式の担当者 |
| `<sys_updated_by>` | 更新を実行したユーザー |
| `<sys_updated_on>` | 更新日時 |
M5NanoC6、SNTPで時間を取得して遊ぶ。(ESP32-C6)((簡素(S))NTP)






x 過去ログを見よ!!
x 3.1.1
x なぜか、なんかいか「ツール」-「シリアルモニター」を開くと成功する(Windows系)
x なぜか、り、こんぱいる、すると「内蔵USBシリアル」が上手く(linux系)

いろいろ
m5stamps3とほぼ、おなじ(なんのこと)


目的
時間を取得する

各自、書き換える

```c++

const char *ssid = "ご自宅のSSID";
const char *password = "ご自宅のパスワード";

```

結果
----


![Screenshot from 2025-02-04 08-01-23.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/d957f27b-c0ce-c16e-f4a6-369927cf7845.jpeg)


プログラム
----


```c++



//ser_time_h_1_esp32_c6_1
//
//https://www.autumn-color.com/archives/839
//


//インクルド
#include <WiFi.h>
#include <time.h>

//定義
#define JST 3600 * 9

const char *ssid = "ご自宅のSSID";
const char *password = "ご自宅のパスワード";


void setup() {

  //WiFiの初期化
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  //シリアルの初期化 esp32-s3 usb-serial
  Serial.begin(9600);
  Serial.println();
  //シリアルの待ちが0.5*9
  //delay(3000);//決め打ちなので、おかしかったら調整してね! wifiの待ち0.5*6
  for (int i = 0; i < (9 + 6); i++) {
    delay(500);  //接続待ち
    Serial.print('.');
  }  //for
  Serial.println();

  Serial.println("\nSTART\n");

  Serial.println();
  Serial.printf("Connected, IP address: ");
  Serial.println(WiFi.localIP());

  configTime(JST, 0, "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");

}  //setup


void loop() {

  time_t t;
  struct tm *tm;
  static const char *wd[7] = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };

  t = time(NULL);
  tm = localtime(&t);
  Serial.printf(" %04d/%02d/%02d(%s) %02d:%02d:%02d\n",
                tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
                wd[tm->tm_wday],
                tm->tm_hour, tm->tm_min, tm->tm_sec);
  delay(1000);

}  //loop




```