OmniAICreator/Qiita-1.07M huggingface dataset:
[CAIレシピ] CAIプロセス呼び出し元IPアドレスの取得

## はじめに
この記事では、CAIプロセス呼び出し元のIPアドレスを取得する方法を確認します。

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

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

## CAIプロセス呼び出し元IPアドレスの取得

### CAIプロセスの作成

次の手順では、割り当てステップを利用して、CAIプロセス呼び出し元のIPアドレスを出力フィールドに設定するCAIプロセスを作成しています。

1. CAIプロセスを次の設定で作成します。
    - 名称を __recipe-pca-functionIPAddress__ とする
    - __匿名アクセス__ を許可する
    - __クラウドサーバー__ にデプロイする

1. 出力フィールド __output__ を __タイプ=テキスト__ として定義します。

1. 割り当てステップを追加して、出力フィールド __output__ に __計算式__ として `request:getHeader('x-forwarded-for')` を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074553/61c394d9-7c55-a153-3cc8-51ebd6d736d2.png)

### CAIプロセスの実行
実行すると、次のようにIPアドレスを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074553/8cb8e3c2-c2ca-4701-cb30-1e3d82f6780a.png)

HTTPヘッダー __x-forwarded-for__ は事実上の標準ヘッダーであり、アクセス元のIPアドレス(赤線部分)、およびProxyサーバーのIPアドレス(青線部分)が記載されています。

## 参照

- [Qiita - IICS CAIの実装レシピ - マスターページ](https://qiita.com/shunsuzu/private/3d1971ef6e3b993516aa)
NW基礎知識 NAT,NAPT,PAT,IPマスカレード

今回はネットワークエンジニアとしての基礎知識
NATについて記載しようと思います。

IPアドレスには範囲があります。

192.168.0.1/24

このIPアドレスから172.16.0.1/24のアドレスへ通信したい場合、
192.168.0.1/24の範囲で通信できるため、172.16.0.1には通信ができません。

192.168.0.1～192.168.0254までのIPアドレスで通信が可能です。

ネットワークとしては同じセグメント/24の範囲で通信されては困る機器があります。
例えば様々なサーバーがあるが同じネットワークに存在すると同じIPアドレス範囲の
パソコンからは誰もがサーバにアクセス出来てしまいます。

そこでサーバーへのアクセスを制限するため、
別のネットワークを用意することで誰もがアクセスすることを制御しています。

PCのIPアドレス 192.168.0.1/24 のパソコンが
サーバー 172.16.0.1 /24 へアクセスするには
NAT機能が必要です。

ここからはNATについて解説していきます。
NATにはいくつか種類があります。

SNAT (Source NAT)
※送信元NATという機能です。

送信元NATを使う理由は、PC側がローカルIPしか持っていない場合、
外部インターネットや外部ネットワークへ通信する際
自分達のネットワーク/24の範囲を超えて通信するために利用します。

192.168.0.1 から インターネットへアクセスする際、
192.168.0.1 を 69.249.XXX.XXXのグローバルIPへ変換し
透過的に送信元が69.249.XXX.XXXから通信が来ているように見せることが可能です。

相手には192.168.0.1がアクセスしていることはわかりません。
変換した機械が知っています。この変換をSNATといいます。

次に

DNAT (Destination NAT)
※宛先NATといいます。

SNATと同じような用途で使われることが多いですが、
こちらは宛先に対して1対1という透過通信を可能とします。

192.168.0.1 から インターネットへアクセスする際、
www.google.com
にアクセスする際は必ず69.248.XXX.XXXでアクセスする。
という変換を行います。これDNATといいます。

ここまでがNATとなります。

応用

最近ではこれらを組み合わせた機能が用いられ
NAPTという機能が使われます。

NAPTを利用することで
送信元IPと宛先IPで通信することが可能です。

こちらは

送信元IP

192.168.0.1 を 69.294.1.1 に変換し

送信元NAT
69.294.1.1:8888 → 
宛先NAT
69.294.1.1:9999 →

宛先
www.google.com

という同じIP内でポート番号を付与することで、
グローバルIPとして一つで約6万4千ポートの利用が可能になります。
(ウェルノンポートを省きます)

ユーザー数でいうと1つのグローバルIPアドレスで1300ユーザーの接続可能です。
この同じIPアドレスで、ポート番号を付与することで送信元と宛先をNATする機能を
NAPT,PAT,IPマスカレードといいます。
これらは違う呼び方で機能が同じとなります。

IP枯渇を防ぐためにも必要な知識となり、NAPTを利用することでNWチーム側は誰がサーバーにアクセスしたかを調べることが出来ます。IPアドレスの利用範囲を最小限に抑えるて障害発生時に調査することが出来ます。
そのため、大きな会社ではNAPTがよく使われます。

簡単ではございますが、今回はNAT,NAPTをご紹介しました。
ここまで読んでいただきありがとうございました。
Architecture Decision Record (ADR)ってなに

一年を振り返る Advent Calendar 2024の10日目です。

全然やったことないですが、Architecture Decision Record (ADR) なる単語を聞いて今の設計手法ってそうなんだというのを感じたのでざっくりまとめ。

## ADR とは

https://engineering.nifty.co.jp/blog/23151

https://qiita.com/fuubit/items/dbb22435202acbe48849

今のプロダクションコードが作られている設計変更の背景をログに残してくやり方みたいです。
自分が初めてこの単語を聞いたときは初期に記載した設計書には手を加えず、そのままADRを記載してプロダクトがどうやって変わってきたかを残していく、みたいなのを見ましたが、現場の運用でやったことが無いので実際どうやってやってるのか気になる所存です。
Networkデバイスの名前慣習メモ

### はじめに
Networkのデバイスについて、名前に慣習があるようなのでメモ
検証環境: Ubuntu(24.04.1)
ip link show 出力(ifconfigは、非推奨)で確認できる

### en始まり: 有線ネットワークデバイス
en = Ethernet

### enp始まり:
p=predictable
Predictableということで、PCIeで接続されているはず。デバイス名がenp0s31f6の場合、Bus=0, Slot=32, Function=6（PCIeにおいてデバイスは、Bus,Slot,Functionで一意に定まる。バス番号:デバイス番号.ファンクション番号のような形）のはず。

### enx始まり: USB接続のEthernet
xの後にMACアドレスが続く

```sh
ip link show enx6c1ff71a06b5
enx6c1ff71a06b5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 6c:1f:f7:1a:06:b5 brd ff:ff:ff:ff:ff:ff
```
link/etherの右に、Macアドレスが見える

### wl始まり: Wifi
wl = Wireless LAN(wlanとかぶっている気がする...)

### wlan始まり: Wifi
レガシーな命名規則に基づくWi-Fiデバイスの名前。

### ww始まり: WWAN
ww = Wireless Wide Area Network

おまけ
### veth始まり: 仮想Ethernet
veth = Virtual Ethernet
ちょうどDockerコンテナを立てていたから、存在した。
仮想Ethernetデバイス。2つのvethデバイスがペアになっており、片方で受信したパケットがもう片方に送られる。
veth425f609@if8 の場合、if8がペア。
if8とif9がペアなどになっている模様（Hostではveth@if8, Containerではif9が見える）。実際、Host側で `sudo ip link delete vethxxx` を実行したら、コンテナ内部から見えていたveth9も消えた。
【Android Studio】IntelliJ 2024.2プラットフォーム統合で強化された新機能まとめ

# はじめに
AndroidStudioに関して今年のアップデートを振り返ってみると、かなり意欲的に開発が行われていることが受けて取れますね。
AndroidStudioはIntelliJ IDEAプラットフォームを基盤に開発されているため、アップデートの内容には左記のIntelliJ IDEAベースの差分も多く含まれているわけですが、この差分がAndroid開発においてどう影響するのか少々分かりづらいですよね。
そこで今回の記事では、Android Studio 2024.2.1 Ladybugで導入された IntelliJ 2024.2プラットフォーム統合にフォーカスし、Android開発にどのような影響をもたらすかを簡単にまとめたいと思います。

# 1. 起動効率の向上でスムーズな作業開始
これまではプロジェクトを開いた後、インデックス作成が終わるまで待つ必要がありましたが、今回の統合によりインデックス作成中でも以下の操作が可能になり、作業開始までの待ち時間が大幅に削減されます。

- コード補完の利用
- プロジェクトの構成確認
- 基本的なデバッグ作業

これに関してはプロジェクト間を行ったり来たりする方にはかなり嬉しい内容なのではないでしょうか？
プロジェクト規模によってですが、地味にインデックス作成に時間がかかったりするのでこの時間を無駄にせずに済むのは嬉しいですね。

# 2. Kotlin K2モードの統合
Android Studio 2024.2.1 LadybugよりKotlinの新しい解析モード「K2」が正式サポートされ、以下の恩恵を受けることが可能です。

- コード補完がより高速かつ正確
- 最新のKotlin機能への対応
- IDEの安定性向上

k2モードに関しては以前より話題に上がることも多かったのでご存知の方も多いかと思います。
この新しいコンパイラは、従来のものと比較してコンパイル速度が約2倍にも向上しているともいわれていますし、今後の開発パフォーマンスも向上していくことが期待できますね。

# 3. cron式サポートの改善
Android開発においてはバックグラウンドタスクやリピートタスクの設定にcron式を利用することがありますが、今回の統合により、cron式を記述する際に次のサポートが追加されました。

- 自動補完
- インラインでの解説表示（例：次回の実行タイミングのプレビュー）

これについてはWorkManagerを使うことになればその恩恵は受けられそうですが、そこまで大きく影響することはなさそうですね。
ただ実際に実装するとなった場合にWorkManager系は動作確認が大変だったりするので、自動補完でミスが減るのは嬉しいポイントですね。

# 参考資料

https://www.jetbrains.com/idea/whatsnew/2024-2/

https://developer.android.com/studio/releases?hl=ja

# さいごに
最近時間なさすぎてまとめ的記事ばっかりなので、そろそろ深めの記事を書きたいところ・・・
設計書はマークダウンで書く

一年を振り返る Advent Calendar 2024の9日目です。

SIer時代はすごいしっかりまとめられた開発フレームワークがあり、そのドキュメントを使って詳細設計を記述していたのでゴリゴリのエクセルやワード、パワーポイントでした。

製造業に転職してからは設計書をマークダウンで記載するようになりました。
そこで使っているのがHugoなるツールです。

https://gohugo.io/

https://qiita.com/peaceiris/items/ef38cc2a4b5565d0dd7c

もうエクセルとかワードとか使わないんだなぁというのを学んだ一年でした。
Hugo何となくで使っているのでもうちょっと理解深めていこう。

終わり。
TOMLの復習（基礎知識）

業務でtomlを使ったので復習。

### TOMLとは

TOML (Tom's Obvious, Minimal Language) 

設定ファイルなどに適したシンプルなフォーマット。
人間が読み書きしやすく、かつ簡単にパースできます。

TOMLの公式サイトは[こちら](https://toml.io/)

toml関連のライブラリはいくつかありますが、今回は[こちら](https://pypi.org/project/toml/)を使いました。

### インストール

```bash
pip install toml
```


### TOMLファイルの読み込み (load)

`toml.load()` 関数でTOMLファイルを読み込めます。
引数にはファイルパスまたはファイルオブジェクトを指定。
読み込んだデータはPythonの辞書型に変換されます。

```python
import toml

# tomlファイルの場所
toml_path = "toml_data/config.toml"

# ファイルパスを指定
toml_data = toml.load(toml_path)

# # ファイルオブジェクトを指定することも可能
# with open(toml_path, "r") as f:
#     toml_data = toml.load(f)

print(toml_data)
```

**config.toml**

```toml
[servers]

[servers.alpha]
ip = "10.0.0.1"
role = "frontend"

[servers.beta]
ip = "10.0.0.2"
role = "backend"
```

**出力例**

```
{'servers': {'alpha': {'ip': '10.0.0.1', 'role': 'frontend'}, 'beta': {'ip': '10.0.0.2', 'role': 'backend'}}}
```

上記の`config.toml`をJSONで表現すると、以下のようになります。

```json
{
	"servers": {
		"alpha": {
			"ip": "10.0.0.1",
			"role": "frontend"
		},
		"beta": {
			"ip": "10.0.0.2",
			"role": "backend"
		}
	}
}
```

### TOMLファイルへの書き込み (dump)

`toml.dump()` 関数を使って、Pythonの辞書型データをTOMLファイルに書き込めます。
第一引数に書き込むデータ、第二引数にファイルパスまたはファイルオブジェクトを指定します。

```python
import toml

toml_path = "./toml_data/toml_dump.toml"

toml_string = """
# This is a TOML document.
name = "Example"
version = "1.0"
port = 3000
"""

# ファイルパスを指定

parsed_toml = toml.loads(toml_string)

# ファイルオブジェクトを指定
with open(toml_path, "w") as f:
    toml.dump(parsed_toml, f)
```

出力結果
```toml:toml_dump.toml
name = "Example"
version = "1.0"
```

### 値の取得 (get)

`toml.load()` で読み込んだ辞書データから値を取得するには、以下の方法があります。
- キーを使う方法
- get()を使う方法
 
存在しないキーを指定した場合、`KeyError` が発生します。これを防ぐには、`get()` メソッドを使用します。`get()` メソッドは、キーが存在しない場合にデフォルト値を返すことができます。

```python
import toml

# tomlファイルの場所
toml_path = "toml_data/toml_dump.toml"

# ファイルパスを指定
toml_data = toml.load(toml_path)

# ----- get() を使う場合 -----
# tomlからportの値を取得
port = toml_data.get("port", 8080)

print(port)  # 出力結果：3000

# tomlからportの値を取得（存在しない要素名）
port = toml_data.get("port_num", 8080)

print(port)  # 出力結果：8080

# ----- キーを使う場合 -----
# tomlからキーでportの値を取得
port_by_key = toml_data["port"]

print(port_by_key)  # 出力結果：3000

# tomlからキーでportの値を取得（存在しないキー）
port_by_key = toml_data["port_num"]

print(port_by_key)  # KeyError: 'port_num'
```

### まとめ

今回は、Pythonで簡単にTOMLファイルを扱う方法を紹介しました。
文法については、改めてご紹介します。
Flutter再勉強

# 内容
この記事は３回目の挫折をして，udemyで改めてFlutterの勉強をしている著者の完全備忘録です．
今週はいろいろあって時間がないので，普段obsidianにメモしている内容のコピペです. 

### 学んだこと
私はdartの言語を学んでいなかったために初歩的な事で躓いていた.　今までは躓いていたことにすら気づくことが出来なかった. 
特定のif条件をつかる時（sscafold()にbakcoler）
```dart
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: _counter % 4 == 0 ? Colors.blue : Colors.yellow,
```
上記のようにまずifの条件が前に着てそのあと「?」でifの替わりを行い，「：」の後にelse条件を持ってくる.

宣言したstlessWidgetはそのまま上位のクラスに呼び出せば，特にtextなどで宣言する必要なく，使用することが出来る.

return 文の前に関数記述することで変数処理を行える.

## Align
paddigは存在するWidgetの周囲をpaddingする
AlignはWidgetの配置を決める
```dart
aligment : Aligment.[y軸,x軸]
```


### 使えそうなこと
~~ : ~~~ ? ifの真結果　：　ifの偽結果
【tailwindcss】スタイルのメモ


## レスポンシブ

| ブレークポイント | 意味 |
|:-:|:-:|
|sm|640px以上に適用|
|md|768px以上に適用|
|lg|1024px以上に適用|
|xl|1280px以上に適用|
|2xl|1536px以上に適用|

```scss
// sm: の実態（640px以上に適用）
@media (min-width: 640px) {
    background-color: red;
}
```

### モバイルファーストを推奨している
:::note info
ブレークポイントのプレフィックスをつけない = モバイルスタイル
:::
```tsx
<div className="w-screen h-full 2xl:bg-black xl:bg-orange-400 lg:bg-green-400 md:bg-blue-400 sm:bg-red-400 bg-white"></div>
```

### smからlgの間だけスタイルを適用したい場合
```tsx
// sm～lgの間だけスタイルを適用（640～1023pxの間だけスタイルを適用）
// max-lgは"1024px未満"という意味
<div className="w-screen h-full sm:max-lg:bg-red-400"></div>
```


## Tailwind Variants
### TailwindはPropsで渡されたtwクラス名ではスタイル変更できない

```tsx:指定したtwクラス名でスタイルが適用されないパターン
const Component = ({customClass}:{customClass:string}) => {
    return <div className={`w-40 h-40 ${customClass}`}>コンテンツ</div>
}

// bg-red-500が適用されない
<Component customClass="bg-red-500"/>
```

### Tailwind Variantsを使う
https://www.tailwind-variants.org/

```terminal
npm install tailwind-variants
```

```tsx
import { memo } from "react";
import { Link, InertiaLinkProps } from "@inertiajs/react";
import { tv } from "tailwind-variants";

type Props = InertiaLinkProps & { active?: boolean };

const spanTv = tv({
    base: "border-b-2 text-base font-medium leading-5 transition duration-150 ease-in-out focus:outline-none",
    variants: {
        active: {
            true: "border-indigo-400 text-gray-900 focus:border-indigo-700",
            false: "border-transparent text-slate-400 hover:text-gray-700 hover:border-gray-300 focus:text-gray-700 focus:border-gray-300",
        },
    },
    defaultVariants: {
        active: false,
    },
});

const NavLink = ({ active = false, children, ...props }: Props) => {
    return (
        <Link
            {...props}
            className="flex justify-start items-center w-20 min-w-20 min-h-10 bg-red-200"
        >
            <span className={spanTv({ active })}>{children}</span>
        </Link>
    );
};

```
【Playwright】テスト実行時の動画を取得する

# はじめに
この記事では、Playwright でテスト実行時の動画を取得する方法を記載します。
フロントエンドのテストでは、手動でのUI確認が大変だと感じることは、あるあるだと思いますが、Playwight を使えば自動テストで動画の取得して、UI確認ができます。

https://playwright.dev/docs/videos

# 開発環境
開発環境は以下の通りです。

- Windows 11
- VSCode
- Next.js 14.2.4
- React 18.3.1
- TypeScript 5.5.2
- Playwright 1.49.0

# 事前準備
事前準備として、Playwright の利用設定とテスト対象コード・自動テストの実装を行います。

## Playwirght の利用設定
以下の手順で利用設定を行います。

https://qiita.com/Yasushi-Mo/items/a886118e8c166933f066

## テスト対象コードの実装
テスト対象コードとして、画面遷移のコードを実装します。

```app/page.tsx
import Link from "next/link";

export default function Home() {
  return (
    <div>
      <h1>Home</h1>
      <Link href="/about">About</Link>
    </div>
  );
}

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/e121f260-9090-18e9-e754-1cef8998097b.png)

```app/about/page.tsx
import Link from "next/link";

export default function About() {
  return (
    <div>
      <h1>About</h1>
      <Link href="/">Home</Link>
    </div>
  );
}

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/7aa13f32-4436-5edd-2c81-f7464c261d7a.png)

## 自動テストの実装
画面要素の確認と画面遷移のリンククリックの自動テストを実装します。

```__tests__/e2e/page/spec.ts
import test, { expect } from "@playwright/test";

test("Home page should work as expected", async ({ page }) => {
  // Start from Home page
  await page.goto("http://localhost:3000/");
  // Find page heading
  await expect(page.getByRole("heading", { name: "Home" })).toBeVisible();
  // Find link  with the text 'About' and click on it
  const linkToAbout = page.getByRole("link", { name: "About" });
  await expect(linkToAbout).toBeVisible();
  await linkToAbout.click();

  // The new URL should be "/about"
  await expect(page).toHaveURL("http://localhost:3000/about");
  // Find page heading
  await expect(page.getByRole("heading", { name: "About" })).toBeVisible();
});
```

これで準備は完了です。

# テスト実行時の動画取得を有効にする
`playwright.config.ts` でテスト実行時の動画取得を有効にできます。

```playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
  ...,
  use: {
    ...,
    video: 'on',
  },
});
```

:::note
以下のように動画サイズを指定することもできます。

```playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
  ...,
  use: {
    ...,
    video: {
      mode: "on",
      size: { width: 600, height: 400 },
    },
  },
});
```
:::

# テストを実行する
VSCode でテストを実行します。

![page.spec.ts-next-app-router-Visual-Studio-Code-2024-12-08-14-54-54.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/e8bb5faf-4eb4-1d25-c875-536e5cd7d463.gif)


# テスト実行時の動画を確認する
テスト実行を以下のコマンドを実行すると、テストレポートがブラウザ上に表示されます。

```powershell
npx playwright show-report
```

テストレポート内で取得した動画を確認できます。

![Playwright-Test-Report-Google-Chrome-2024-12-08-14-56-58.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/a7e80153-6b61-b797-3117-10512c863a10.gif)

:::note
`test-results` ディレクトリでも動画を確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/547c0e89-2eac-1880-4e23-f0192c5bb217.png)



:::

# 参照
- [Videos](https://playwright.dev/docs/videos)
IoT周りでこの一年学んだ単語をざっくりまとめてみる2

一年を振り返る Advent Calendar 2024の8日目です。早速記事をこすりにかかりました。

ということでIoT周りで学んだ単語その２です。

## Modbus
前回のBACNetに続き、今のIoTプロジェクトでよく使うので多分世間一般的なものかと思っています。

https://www.mgco.jp/magazine/plan/mame/b_network/9911/

- 通信プロトコルとしてModbus Protocolを実装したネットワークを、Modbusと呼んでいます。Modbus Protocolは、Modicon Inc.（AEG Schneider Automation International S.A.S.）がPLC用に開発した通信プロトコルであり、その仕様は公開されています。

スマートファクトリ系で良く使われるのかな。そんな理解です。

## Wago機器
これは単純に Wago 社の提供している機器です。

https://www.wago.co.jp/products/download/automation.html

スマートビルディングの構築で照明を遠隔操作したりするときにWago社の機器を使って操作したりすることがあるので覚えておいてよいかなと思いました。

## IIoT
IoTとくればIIoTです。

https://www.techs-s.com/media/show/178

- IIoT（インダストリアルIoT）とは、製造業を中心とした産業分野でのIoT活動のことです。

ビジネスで IoT やるってなったらもうほとんど IIoT をさしているのではないかと思ってしまっています。製造業で働いているせいか、IoTの使い方が製造業の使い方に寄っている気がしています。

## まとめ
IoTといってもほんとにいろんな分野でいろんな技術が使われているのでもっと知見を広めていきたいところです。特にエンベデッド周り。
Web初心者向け　基本的な概念

# Webアプリの初心者向け
HTML,CSS,JavaScriptの関係が伝わる記事を作成してみました。
HTMLは「構造」を作り、ページの中身を記述します。
CSSは「デザイン」を追加して、ページを見やすく、おしゃれにします。
JavaScriptは「動作」を加えて、ウェブページを変化させる仕組みです。
クリックやスクロールといったアクションで、ページの見た目や内容を動的に変えることができます」
例:ショッピングサイト
「商品をカートに追加するボタンを押すと、JavaScriptが動作して、画面に『商品が追加されました』というメッセージを表示したり、カートのアイコンが更新される仕組みです。」

下記リンクより参照
https://github.com/HiHiroyoshi/SampleWebPage
初投稿

# はじめに
初投稿です。勉強の記録としてアウトプットしたく、Qiitaを始めました。


### 現在勉強していること
・Python
・データ分析
・AI
上の3つをメインに勉強していて、気分転換にhtml,css,javascriptのフロントも勉強しています。

### やりたいこと
・Kaggleに参加してメダル取ることを目標にしています！
・自分でwebアプリケーションを作ること

## 最後に

本当にわからないことだらけですが、根気強く続けていきたいです！
自分の勉強としてはもちろん、私みたいな初心者の方が参考にできるような投稿をしていきたいと思っています。
もし内容に不備がありましたら、ご指摘いただけると泣いて喜びます！よろしくお願い致します！
【個人開発】7個の有料生成AIサービスをフル活用し1ヶ月でサービスをリリースしました🎉

## はじめに
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3955753/b0948ab6-6a46-6f05-ed79-e4548830a39f.png)

この度、クラウドソーシングサイトで活動するエンジニア向けの案件検索・提案作成サービス「DevSpot」をリリースしました🎉

https://www.devspot.jp

学習と実践を兼ねて開発したサービスですので、皆様からのフィードbackをいただけますと幸いです！

## アプリの概要
「DevSpot」は、クラウドソーシングで活動するエンジニアの案件探しと提案文作成を効率化するAIプラットフォームです。主な機能として以下を提供します：

1. 複数プラットフォームからの一括案件検索

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3955753/6b732474-f22b-6332-d2ef-968d5080e798.png)

毎日最新の情報を連携するため、いろんなクラウドソーシングサイトを監視する必要がなくなります！

2. AIによる最適な提案文の自動生成

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3955753/5ebdb116-13f5-a15f-2a47-ace1b31dd3e4.png)

生成AIを利用して、案件情報と事前に登録したあなたの情報から提案文を作成します。
気になった案件を複数保存しておけば、提案文を次々生成でき、効率的に応募できます。
生成AIの精度は日々改善中で、今後もノウハウを発信していこうと思います。

3. PlantUMLを使用した図解の自動生成

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3955753/e3d254fd-ed9f-8c8f-4e40-fab6bb17fbdc.png)

提案文の生成機能には、他の提案者と差をつける、図解の差し込み機能があります。
この図解も生成AIが作成するため、作成者は書き方をしらなくても自然言語でAIを話しながら作成できます。

## なぜ開発した？
クラウドソーシングサイトで活動するエンジニアの多くが、以下のような課題を抱えていることに気づきました：

- 複数のプラットフォームを横断して案件を探す時間が取られる
- お決まりのテンプレートを使って作成している場合が多い提案文の作成に時間を取られている
- 他の提案者との差別化が難しい

これらの課題を解決し、エンジニアの方々が本来の開発作業により多くの時間を使えるよう、AIを活用した効率化ツールの開発に至りました。

## 技術スタック

プロトタイプの作成やLPの作成、リリースした本製品の開発までAIをフル活用して作成しました。
全ての作業が一人で完結でき、プロトタイプ作成開始からちょうど1ヶ月ほどでのリリースとなりました。

### デザイン
- Canva
- gamma
- Reprit Agent

### リサーチ ・ LP内容作成
- perplexity
- ChatGPT
- claude

### LP
- gamma
- Reprit Agent

### フロントエンド
- Reprit Agent
- Next.js
- TailwindCSS

### バックエンド
- Python
- Dify

### インフラ
- AWS
- Vercel
- Reprit Agent

### 開発ツール
- Cursor

## 今後の展開
現在はベータ版として全機能を無料で提供していますが、今後は以下のような機能追加を予定しています：

- AIによる独自の案件カテゴライズとマッチング

現在、生成AIを一般的なAPIを利用して作成しており、今のままではコスト的に不可能な機能です。
そこで、Mac Miniを手配して、Mac Mini上でLama3を動かしローカル環境でLLMを動作させることで従量課金から解放され、可能になってくるのではないかと考えています。

- 提案文生成の精度向上, UX改善

こちらがこのサービスのコア機能となってくるため、提案文の雛形を自分好みにカスタマイズできたり、提案文の口調を変更したりといった機能改善をしていきたいと思っています。

## 最後に
最後までお読みいただき、ありがとうございます。現在ベータ版として全機能を無料でご利用いただけます。ぜひお試しいただき、フィードbackをいただけますと幸いです！

https://www.devspot.jp
GraphQL - Facebookのモバイルデータ通信戦略における技術的革新 -

## Facebookの試練
2012年、Facebookは急成長を遂げ、世界中で数十億人がこのソーシャルメディアを日々利用していた。しかし、その裏では、技術的な困難が迫っていた。特に、急速に進化するモバイルアプリにおいて、パフォーマンスの低下が深刻な問題となっていた。

## 問題の本質
### 非効率なAPIコール
Facebookのモバイルアプリには、あらゆる面で非効率が蔓延していた。特に問題となったのは、複数回にわたるAPIコールである。
- ニュースフィードを表示するために4～5回ものAPIコールが必要
- 毎回必要以上のデータを転送
- モバイルネットワークは限られており、データ通信は高コスト
その結果、ユーザーの待機時間は長くなり、モバイルデバイスのバッテリーは急速に消耗していた。Facebookは、その速度と効率の問題に対応する必要があった。

**具体的な問題点**
- ユーザー情報取得
1回のAPI呼び出し
- 投稿データ取得
別のAPI呼び出し
- コメント情報取得
さらに別のAPI呼び出し

## 解決への道のり
### 新しい設計思想の誕生
リー・バイロンを中心に、従来のRESTful APIの限界を徹底的に分析し始めた。従来のアーキテクチャでは、リソース間の相互関係やデータの柔軟な取得が難しく、無駄なデータ転送が続いていた。

そこで、まったく新しいアプローチを考案した。これが、後に「GraphQL」として知られることになる。

- 単一のエンドポイント
- クライアントが必要な情報を正確に指定
- 型安全性を持たせた設計

この新しい設計により、クライアントとサーバー間のデータのやり取りが劇的に効率化されることが期待された。

#### GraphQLクエリの革新
```graphql
query {
  user(id: "123") {
    name
    profileImage
    newsFeed {
      posts {
        content
        likes
        comments
      }
    }
  }
}
```
開発者はこのシンプルで直感的なクエリによって自由なデータ転送を実現できるようになった。

## GraphQLが解決した課題
1. **データ転送の最適化**
   - 必要な情報のみを取得し、無駄なデータ転送を排除
   - ネットワークリソースを劇的に削減
2. **クライアント-サーバー間の柔軟性**
   - 動的なデータ構造により、複雑な要求にも柔軟に対応
   - 型安全性を確保し、信頼性を向上
3. **開発者体験の向上**
   - 直感的なデータ取得が可能になり、開発者の生産性が向上
   - 自己文書化されたAPIにより、APIの利用方法が自然と明示される
Einstein for Service 



https://trailhead.salesforce.com/content/learn/modules/einstein-for-service-rollout-strategies

|機能	|何をするのか|
|:--------------------------|:------------------------------------|
|Einstein Bots|チャットやメッセージング チャネルでの会話における一般的な問題を自動的に解決します。 |
|Einstein Case Classification|顧客がケースから提示するテキスト (ケースの件名と説明) に基づいて、受信したケースを分類するためのフィールド値 (理由、タイプ、優先度など) を予測します。 |
|Einstein Case Routing |Einstein ケース分類と連携して、ケースをトリアージし、適切なエージェントまたはキューにルーティングします。|
|Einstein Case Wrap-Up|エージェントがケースを迅速に完了できるように、顧客チャットの最後にケース フィールドを推奨します。|
|Einstein Reply Recommendations|チャットおよびメッセージング セッション中に関連する返信を推奨するためにチャット トランスクリプトを分析します。|
|Einstein Article Recommendations|オープンケースに関連するナレッジ記事をエージェントに推奨します。|
|Einstein Next Best Action|データ インサイトとビジネス ルールを使用して、エージェントが実行すべきオファーとアクションを推奨します。たとえば、離脱リスクの高い顧客にオファーを推奨したり、顧客が要件を満たした場合に製品をアップセルしたり、サブスクリプションのリマインダーを送信したりできます。 |


+ 各 Einstein ツールには、異なる量のデータと権限が必要です。Sita は準備を整えたいので、各 Einstein ツールのデータ要件を確認します。

|機能	|利用可能|データ要件|	Einstein for Service アドオン ライセンスが必要ですか?|
|:--------------------------|:------------------------------------|:-----------|:----------|
|Einstein Bots|Enterprise, Performance, and Unlimited|過去6か月間で少なくとも400件の解決済みのケース、ただし400件以上が理想的、予測したい各フィールドに値を持つ 400 件のクローズド ケース|はい、フル機能を利用できます。Try Einstein バージョンにはアドオン ライセンスは必要ありません。|
|Einstein Case Classification|Enterprise, Performance, and Unlimited|1,000件、予測したい各フィールドと値を使用した 100 件のクローズされたケース|はい |
|Einstein Case Routing |Enterprise, Performance, and Unlimited. In Enterprise edition, the Digital Engagement license is required for Chat.|Einstein ケース分類と同じです。Einstein ケース ラップアップには組織内のチャットも必要です。|はい、フル機能を利用できます。Try Einstein バージョンにはアドオン ライセンスは必要ありません。|
|Einstein Case Wrap-Up|Enterprise, Performance, Unlimited, and Developer|2 つのインテント（顧客の目標）、インテントごとに少なくとも 20 の発話（インテントごとに 100 ～ 150 の発話を推奨）|Einstein ケース分類と同じです。Einstein ケース ラップアップには組織内のチャットも必要です。|いいえ。チャネルを増やすには、Digital Engagement アドオン ライセンスが必要です。 |
|Einstein Reply Recommendations|Enterprise, Performance, and Unlimited|（必須）ナレッジ記事3件、（推奨）過去2年間の1,000件、（推奨）過去2年間の500件の事例記事の添付|いいえ|
|Einstein Article Recommendations|Enterprise, Performance, Unlimited, and Developer|1,000件の英語チャット記録|はい|
|Einstein Next Best Action|Enterprise, Performance, Unlimited, and Developer|なし|はい、フル機能をご利用いただけます。限定バージョンではアドオン ライセンスは必要ありません。 |

# エラー

+ [Einstein Data Libraryでアップロードできない](https://qiita.com/Keiji_otsubo/items/c5df7042897212630b8e)
「T-DASH」を使ってみて

## T-DASHの良い点：効率化の実感とその魅力
#### 自動化の力を実感する優越感
「T-DASH」を使っていると、自動化の効果を直に感じる瞬間が何度もありました。手動で行うと時間がかかる作業が、ボタン一つで処理されるのを見ると、自分が何か特別なことを成し遂げたような感覚になります。特に、普段は手間がかかると感じる作業を効率化できると、自分がプロジェクト全体に大きく貢献しているように感じられ、自然とやる気も湧いてきます。

## まとめ
可能性と使いやすさがあったので今後も利用しようと思いました
ウォルラス演算子の使い方

# ウォルラス演算子とは
2019 年に Python 3.8 で追加された機能で、**セイウチ演算子**という愛称で親しまれている？らしいです。
```変数名 := 式```の記法で、値の代入と条件の判定を 1 行でできます。
かなり昔に追加された機能のようですが、ついさっき知ったので記事を書いてみようと思います。

# コピーして動くサンプルコード
このクラスは数値の配列と閾値を渡して、各数値を 2 倍したとき、閾値を超えている数値の配列を返すものです。
ウォルラス演算子を使った場合と使わなかった場合で見比べられるようにしました。
```python:test.py
class AboveThresholdDoubledNumbersExtractor:
    def __init__(self, numbers: list[int], threshold: int) -> None:
        self._numbers = numbers
        self._threshold = threshold

    def without_walrus_operator(self) -> list[int]:
        above_threshold = []

        for num in self._numbers:
            doubled_num = num * 2
            if doubled_num > self._threshold:
                above_threshold.append(doubled_num)
        return above_threshold

    def with_walrus_operator(self) -> list[int]:
        above_threshold = []

        for num in self._numbers:
            if (doubled_num := num * 2) > self._threshold:
                above_threshold.append(doubled_num)
        return above_threshold

    def without_walrus_operator_in_list_comprehension(self) -> list[int]:
        return [num * 2 for num in self._numbers if num * 2 > self._threshold]

    def with_walrus_operator_in_list_comprehension(
        self,
    ) -> list[int]:
        return [
            doubled_num
            for num in self._numbers
            if (doubled_num := num * 2) > self._threshold
        ]


if __name__ == "__main__":
    nums = [10, 20, 30, 40, 50]
    threshold = 50
    extractor = AboveThresholdDoubledNumbersExtractor(nums, threshold)

    a = extractor.without_walrus_operator()
    b = extractor.with_walrus_operator()
    c = extractor.without_walrus_operator_in_list_comprehension()
    d = extractor.with_walrus_operator_in_list_comprehension()

    print(a)
    print(b)
    print(c)
    print(d)
```

# 感想
num * 2 程度であればその恩恵は感じられないのかもしれませんが、処理の結果に意味を持たせながら条件の判定もできるのは嬉しいです。
趣味の開発では可読性を損なわない範囲で積極的に使っていきたいですね。
セイウチ演算子を使うべきではないと思しき場面に直面したらこの記事を更新しようと思います。
CommonUIとImGuiを使用する場合に決定ボタンが効かなくなる

# はじめに
この記事は[Unreal Engine (UE) Advent Calendar 2024](https://qiita.com/advent-calendar/2024/ue)の11日目です。

# 概要

ImGuiとても便利ですね。デバッグメニューを作るならこれ一択といった感じでデファクトスタンダードとなっています。
いろいろな講演で目にするデバッグメニューはほとんどImGuiです。
そんなImGuiをUnrealEngineでも使用できます。導入方法は無数の記事があるので検索してください。

ここではCommonUIプラグインとImGuiを同時に使用する場合に決定ボタン(XboxGamePadならAボタン)が効かなくなる問題と対策方法を書きます。

# 問題
ImGuiを導入してデバッグメニューを作っていき、ゲームパッドで操作もしていたとき、そろそろインゲームUIを作成していこうとCommonUIプラグインを使うことにしました。
UMGとCommonUIで順調にインゲームUIを作っていきます。
EnhancedInputも使い、InputActionやInputMappingContextでゲームプレイとUIで入力の切り替えも順調です。

一通りできてきたころ、デバッグメニューを使用するユーザーからこんな報告がきます。
「デバッグメニューでAボタンが効いてません。」

関連しそうな変更は加えていないのに、一体何が原因でしょうか

# 原因
バグ発生前までバージョンを戻したり、新規プロジェクトで検証していくと、CommonUIを有効化しCommonGameViewportClientへ変更した場合に発生することが判明します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157391/9656535a-6921-1d7a-4222-0001aca584e7.png)

この変更によって
CommonInputSubsystemからFSlateApplication::RegisterInputPreProcessorが追加で呼ばれCommonInputPreProcessorが追加されます。
このPreProcessorがあるとAボタン操作が効かなくなります。

# 対策
## Yボタンを使う
ImGuiをXboxGamePadで操作する場合、実はYボタンも決定ボタンとして扱っています。
Aボタンの代わりにYボタン使ってもらえれば問題は回避できます。

## エンジン改造する
CommonInputSubsystemが持つCommonInputPreProcessorから、決定ボタンの動作がImGuiに伝わらなくなります。
デバッグメニューを開くときにこのPreProcessorをUnregister,閉じるときにRegisterしおなおすことで無効にできます。
```cpp
protected:
	TSharedPtr<FCommonInputPreprocessor> CommonInputPreprocessor;
```
を以下のようにPublicにします。
```cpp
public:
	TSharedPtr<FCommonInputPreprocessor> CommonInputPreprocessor;
```
とすれば取得できるようになるので、デバッグメニュー開閉時にUnregister/Registerを行います。
```cpp

void UMyCheatManager::Hoge()
{
	auto PlayerController = GetPlayerController();
	auto LocalPlayerController = PlayerController->GetLocalPlayer();
	auto&& CommonInput = UCommonInputSubsystem::Get(LocalPlayerController);
	auto&& Slate = FSlateApplication::Get();
	Slate.UnregisterInputPreProcessor(CommonInput->CommonInputPreprocessor);
}

void UMyCheatManager::Hoge2()
{
	auto PlayerController = GetPlayerController();
	auto LocalPlayerController = PlayerController->GetLocalPlayer();
	auto&& CommonInput = UCommonInputSubsystem::Get(LocalPlayerController);
	auto&& Slate = FSlateApplication::Get();
	Slate.RegisterInputPreProcessor(CommonInput->CommonInputPreprocessor);
}

```
この方法だとデバッグメニューを常時表示しながらゲーム操作するときどうなるんだという問題があります。

# 終わり
エンジン改造はできればしたくないので、Yボタンを使ってもらうようにしましょう。
CommonInputPreProcessorをUnregister/Registerするのも、デバッグメニューを常時表示しながらテストしているときにどうするんだという問題もあります。
デバッグメニューはキーボード・マウスの操作のみをサポートする。と割り切ってしまうのもありです。
理解の違いが生む課題

理解のずれによるあるあるが多かったので書いてみました。
## 理解のズレが生む困惑
### 知識のスタート地点が違う
プロジェクトに関わる人たちの中には、自動化そのものに詳しい人もいれば、初めて触る人もいます。そのため、同じ説明をしても、何が重要かや何に注意するべきかの捉え方がバラバラでした。特に初心者の自分にとって、専門用語が飛び交う会話の中で、自分だけが遅れているような感覚を持つことがありました。

### 話がかみ合わない瞬間
一方で、逆に基本的な内容を説明したときに、相手がすでに知っていると感じる瞬間もありました。相手が「そんなの当たり前だよ」と思っているような空気に気づくと、少し焦る自分がいました。その場の雰囲気や相手の反応を読みながら進めるのは難しいと実感しました。
Symfony5のエンティティクラスの記述メモ

# Symfony5のエンティティクラスの書き方について

## カラムの属性を記述する方法はどうすればいい？

結論、こんな感じで書きます。

https://symfony.com/doc/current/doctrine.html

```Person.php
<?php

namespace App\Entity;

use App\Repository\PersonRepository;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: PersonRepository::class)]
class Person
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Name]
    #[ORM\Column(length:255,nullable:true)]
    private ?string $name = null;

    #[ORM\Mail]
    #[ORM\Column(length:255,nullable:true)]
    private ?string $mail = null;
    
    #[ORM\Age]
    #[ORM\Column(nullable:true)]
    private ?int $age = null;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName():?string
    {
        return $this->name;
    }

    public function getMail():?string
    {
        return $this->mail;
    }

    public function getAge():?int
    {
        return $this->age;
    }

    public function setName(string $name):self
    {
        $this->name = $name;
        return $this;
    }

    public function setMail(string $mail):self
    {
        $this->mail = $mail;
        return $this;
    }

    public function setAge(int $age):self
    {
        $this->age = $age;
        return $this;
    }
}

```

たとえば。nameカラムの属性情報は、下記の通り記載します。

```Person.php
    #[ORM\Name]
    #[ORM\Column(length:255,nullable:true)]
    private ?string $name = null;
```

symfonyのバージョンによって記載は少し違うので、バージョンごとに公式サイトで確認してみましょう。
【Python】ランダムな日付のファイルを生成するプログラムを作る

## はじめに

今回はランダムな日付のファイルを生成するプログラムを作りました。

## 実行環境

- Python 3.11
- Windows 10

## 使用ライブラリ

- os
- random
- datetime

このプログラムでは外部ライブラリは使用していないのでpipでのインストールは必要ありません。

## 実装の準備

randam.pyみたいな適当な名前の.pyファイルを作成して、ファイルを生成させたいフォルダに移動してください。

## 実装

以下のコードを先程作成した.pyファイルにコピペしてください。
実行すると「sample_[連番]_[ファイルの日付].pdf」という名前のファイルが100個生成されます。

```python:
import os
import random
from datetime import datetime, timedelta

# PDFファイルを生成するフォルダを指定
output_folder = '.'

# フォルダが存在しない場合は作成
os.makedirs(output_folder, exist_ok=True)

# ランダムな日付を生成するための関数
def random_date(start, end):
    return start + timedelta(days=random.randint(0, (end - start).days))

# 日付の範囲を設定（例: 2020年1月1日から2023年12月31日）
start_date = datetime(2020, 1, 1)
end_date = datetime(2023, 12, 31)

# 100個のランダムなPDFファイルを生成
for i in range(100):
    # ランダムな日付を生成
    random_modification_date = random_date(start_date, end_date)

    # ファイル名を日付に基づいて作成
    file_name = f"sample_{i+1:03d}_{random_modification_date.strftime('%Y%m%d')}.pdf"
    
    # フルパスを作成
    file_path = os.path.join(output_folder, file_name)
    
    # PDFファイルを作成（空のファイル）
    with open(file_path, 'wb') as f:
        pass  # 空のPDFファイルを作成

    # ファイルの更新日を設定
    os.utime(file_path, (random_modification_date.timestamp(), random_modification_date.timestamp()))

print("ランダムなPDFファイルが生成されました！")

```

## 応用

以下の部分の.pdfを作成したいファイルの拡張子に変えることでファイルの種類を変えることができます。

```python:
# ファイル名を日付に基づいて作成
file_name = f"sample_{i+1:03d}_{random_modification_date.strftime('%Y%m%d')}.pdf"
```

## おわりに

今回はランダムの日付のファイルを生成するプログラムを作りました。以下の記事のプログラムでのテスト用に作成したプログラムなので気が向いたらそちらの記事も読んでいただけると嬉しいです。

https://qiita.com/mikannohako/items/8b1f9e832be82d45fa9b
テスト自動化導入の試み

## こうして自動化をした
テスト自動化を初めて導入したとき、手元にあるのはわずかな情報と、わずかに頼りになる自分の直感だけでした。直感だけでなく基礎を学ぶことも大切だと感じつつ、このような挑戦の中で得た経験が、自分の成長につながると実感しています。
ログファイルの出力先を見つけるコマンド

# 背景

ログファイルの出力先を知りたいが場所がわからない。

# 方法

あるディレクトリ配下すべてについて、更新履歴が新しい順の１０個のファイルを表示するコマンドを実行して見つける。
以下のコマンドならfindとxargs,ls を使った時に発生する、「xargs が標準入力から受け取ったファイルリストを ls -lt に渡す時に、ls がそのファイルリストをまとめて一度に処理できず、ls の実行がシグナル（signal 13）で終了してしまう可能性」を排除できる。

### コマンド
```bash
find /path/to/directory -type f -exec stat --format='%Y %n' {} + | sort -n -r | head -n 10 | while read timestamp file; do
  echo "$(date -d @$timestamp '+%Y-%m-%d %H:%M:%S') $file"
done
```
PrismaでSupabase接続する際の沼

# ハマった点
Next.jsにおいて、PrismaでSupabaseと接続するために新しくマイグレーションを行おうとしました。
```
npx prisma migrate dev --name add_createdAt
```
しかし、以下のエラーが発生してうまくいきませんでした。
```
Error: P1001: Can't reach database server at `aws-0-ap-northeast-1.pooler.supabase.com:5432` 
```

# 解決策
接続する際のURL内のパスワードに含まれる$が原因でした。特殊文字を含む場合はそれをパーセントエンコーディングする必要があるとのことです。（例：`p@$$word`→`p%40%24%24w0rd`）
`DATABASE_URL`と`DIRECT_URL`の両方について上記の方法で解決できました。

なおパーセントエンコーディングを用いず試行錯誤した結果、`DATABASE_URL`についてはバックスラッシュによるエスケープ（例：`$`→`\$`）で、`DIRECT_URL`については全くエスケープしないことでうまくいくことがわかりました。使う機会はないと思いますが、沼にはまらないための備忘録として…
## 参考文献
https://supabase.com/partners/integrations/prisma

https://www.prisma.io/docs/orm/reference/connection-urls

https://developer.mozilla.org/ja/docs/Glossary/Percent-encoding
VSCodeでlolipopに接続したい（SSH FS）

この記事はIPFactory Advent Calender 2024 6日目の記事です。

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

初投稿です。

# 概要
Remote - SSHで接続できるかと思ったらそうでもなかった。

# 使用した拡張機能
- SSH FS

https://marketplace.visualstudio.com/items?itemName=Kelvin.vscode-sshfs

# 手順
1. lolipopのSSHを有効にする
![スクリーンショット 2024-12-07 192535.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3903819/d5b56f07-9710-57ed-83fb-b733398037f7.png)

2. 拡張機能からSSH FSのインストール
![スクリーンショット 2024-12-07 193517.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3903819/c8a235b2-b8c3-7cec-7c78-89d0e7ac088a.png)

3. アクティビティバーのSSH FSからCreate a SSH FS configuration
（Ctrl + Shift + Pからでも可能）
![スクリーンショット 2024-12-07 191731.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3903819/4d4c51c9-8a8d-c6fc-0cad-c59fbf1cd2c5.png)

4. 適当な名前を付けて保存
![スクリーンショット 2024-12-07 193258.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3903819/410022a4-8f05-3002-5738-fb30cd27d99f.png)

5. Edit configに進むので少し下にスクロールしてlolipopのSSHから貼り付けて保存
    - Host -> サーバー
    - Port -> 接続ポート
    - Root -> ~/（ホームディレクトリ）
    - Username -> アカウント
    - Password -> SSHパスワード

    ![スクリーンショット 2024-12-07 192535.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3903819/6530ac90-5bd1-9cce-f7f5-e7d7c1af469a.png)
（Rootを設定し忘れて詰まったので注意）

6. Add as Workspace folderを選択
![スクリーンショット 2024-12-07 200352.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3903819/0d8976bb-16a4-ea05-86c0-55cf957ef1d2.png)

7. 接続確認
![スクリーンショット 2024-12-07 200902.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3903819/2e55aacc-0baf-4a53-9f40-97d7fe5a4dbe.png)

文字化けしてますが日本語入力できたので問題ないと思います。
あとは好きなようにしましょう。

### 参考
https://tat-fujii.net/2023/11/10/%E3%83%96%E3%83%AD%E3%82%B0visualstudiocode%E3%81%A7%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%81%AE%E3%83%AD%E3%83%AA%E3%83%9D%E3%83%83%E3%83%97%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AE%E3%83%95%E3%82%A1/
研究室のパソコンに研究室外から操作したい！

# 経緯
ノートPCしか持っていないため、時間のかかるプログラムはGPUを搭載している研究室のデスクトップPCで実行したい。ただ、そのためにわざわざ大学まで行くのもメンドクサイ。そこで、「リモートデスクトップ」というものを活用しようと思った。

# リモートデスクトップとは？
リモートデスクトップとは、インターネットを介して他のコンピュータに接続し、そのコンピュータを別のコンピュータから操作できるというもの。これにより、たとえば外出先のノートPCから自宅のデスクトップPCを操作して作業できたりする。

# Windowsリモートデスクトップ使えない!?
リモートデスクトップと検索して、まずお目にかかるのが、Windowsの設定からリモートデスクトップをオンにする方法。たったこれでOKと思いきや、実は同ネットワークでないと接続できず、これでは自宅から研究室PCにアクセスすることができない。もちろん、ここからさらに色々設定とかすればできるようになるが、ネットワーク管理者の権限などが必要そう…

# chromeリモートデスクトップ！
Windowsリモートデスクトップで数時間費やして、諦めて、他の方法を模索。Googleアカウントがあるならば、chromeリモートデスクトップが簡単にセットアップできた。このとき、Windows設定のリモートデスクトップがオフでも動作する。

# 接続先（研究室PC）の設定
1. 予めGoogleにログイン
1. chromeリモートデスクトップのサイトにアクセス
https://remotedesktop.google.com/access/
1. ダウンロードボタンを押し、拡張機能のChrome Remote DesktopをChromeに追加
1. PC名とPINコードを設定、PINコードは忘れないように！
1. 登録したデバイスがオンラインと表示されていればOK

# 接続元（我のノートPC）
1. 接続元と同じGoogleアカウントでログイン
1. chromeリモートデスクトップのサイトにアクセス
https://remotedesktop.google.com/access/
1. オンラインになっている登録デバイスをクリック
1. PINコードを入力
1. 接続先のPC画面が映っていれば、晴れて接続(^^)/

# 注意点
* 接続先のPCの電源は入れっぱなしにすること。落ちるとオフラインになりアクセスできない。
* 再起動はしても大丈夫だった。一度リモート接続が切れるが、再度PC電源が入ればオンラインになる。
ただし、スタートアップに設定する必要があるかも。
* PCの設定「電源」から「スリープまでの時間」は「なし」にすること。スリープになるとオフラインになってしまう。
一応書いておくと、PC電源のスリープとモニター画面のスリープは違う。
:::note warn
* モニターの電源は切っておいたほうがいい。
何も操作せず数分経ってPCモニターの画面が消えても、リモートデスクトップ接続して接続元からマウスカーソル動かすなどで接続先へ操作があると、PCモニターはつく。
つまり、目の前で誰もPCを触ってないのに、マウスカーソルが動き、勝手にウィンドウが開かれ、そして閉じられる...というような、はたから見ると超常現象に映る。
:::
ECS構築して自動復旧を試す

## はじめに
Hands-on for Beginnersを使用してECSの構築と自動復旧を試してみたので備忘録です。

## やること
- Cloudshell環境でコンテナイメージの作成
- Cloudshell環境からECRにドッカーイメージプッシュ
- ECS Fargateの作成
- ECS Fargateにアクセスして確認
- 自動復旧

#### 各環境構築のログは記事が長くなるので割愛します
ECS Fargateの作成は公式ハンズオンを推奨
[Amazon Elastic Container Service 入門](https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-ECS-2022-confirmation_012.html)
## ECSへのアクセスを確認
![スクリーンショット 2024-12-05 191815.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/1ca4b3a4-62ed-5ca3-f1c3-589e695eca0e.png)

### コンテナイメージをECRにプッシュ
![スクリーンショット 2024-12-03 173330.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/22bbf265-721b-0bc3-45c1-0614a4ab751c.png)

### タスク定義したECSサービス
![スクリーンショット 2024-12-05 185104.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/4510f73f-8a68-f897-dddb-be17f3e51f69.png)


## コンテナの自動復旧
- タスク定義を2つで設定していることを確認して、1つのタスクを停止する
![スクリーンショット 2024-12-06 123955.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/472e57f0-70a4-9432-1ae9-c7fad4711377.png)

- タスクが復旧してhello-worldに問題がないことを確認
![スクリーンショット 2024-12-06 124238.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/4807f72b-2dfe-4ce5-d0d2-63b3efa77c25.png)
-----
![スクリーンショット 2024-12-05 191815.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/36707138-d5c3-054c-6737-feab4ffaee5d.png)

## 最後に
次回は応用としてCodeサービス群を使用してECSへの自動デプロイやIaCを使用してECS環境を構築してみたいと思います。
2次元配列を全探索する際にネストを浅くする

2次元配列を全探索する際にネストを浅くする方法を解説します。この記事では、Pythonを使います。

AtCoder Beginner Contest 383のB問題を使って解説します。まずはリンクから問題を読んでください。

https://atcoder.jp/contests/abc383/tasks/abc383_b

次に解説を読んでください。

https://atcoder.jp/contests/abc383/editorial/11540

この解説にある解答例では、forループが6階の入れ子になっています。1つ目の加湿器の場所について高さと幅でforループ2回、2つ目の加湿器で2回、その場所が加湿されているかどうかで2回の計6回のforループです。forループのネストを浅くするにはどうすればいいでしょうか。

ここで、次の点に着目します。$S$の全ての行を一列に並べた長さ$H \times W$の文字列$S'$を考えると、ある$i(0\le i < H \times W)$番目の文字$S_i'$と元の2次元配列$S$の$h$\($i$を$W$で割った商\)行目、$w$\($i$を$W$で割った余り\)列目の文字$S_{hw}$は一致します。

forループを$S'$の要素について行うことでネストの深さを半分にできます。

サンプルコードは以下のとおりです。Pythonでは`divmod`を使うことで商と余りを同時に取得できます。

```Python3:abc383_b.py
H, W, D = map(int, input().split())
S = [input() for i in range(H)]

answer = 0

for i in range(H * W):
    for j in range(i + 1, H * W):
        ih, iw = divmod(i, W)
        jh, jw = divmod(j, W)
        if S[ih][iw] == "#": continue
        if S[jh][jw] == "#": continue

        count = 0
        for k in range(H * W):
            kh, kw = divmod(k, W)
            if S[kh][kw] == "." and (abs(kh-ih)+abs(kw-iw)<=D or abs(kh-jh)+abs(kw-jw)<=D):
                count += 1
        answer = max(count, answer)
print(answer)

```
国連開発計画のWebGIS - GeoHubについて

## はじめに

国連開発計画（UNDP）では新しいWebGISプラットフォームであるGeoHubをインハウスかつオープンソースで開発しています。
ArcGISなどの有償のプラットフォームを使ったプロジェクトなどはありましたが、UNDPは他の国連機関と比べて、これまでGISデータの利活用はあまりされてきませんでした。UNDPで働くスタッフの大半はPolicy makarでGISを活用できるスキルを持った人は非常に限られています。またそれぞれのカウントリーオフィスが持っているであろう膨大はGISデータを組織を横断して共有し、利活用できるようにしたいという思惑もあります。

そういったこともあって、GeoHubはGIS経験のない人でもできるだけ容易にデータをアップロードし、ビジュアライズして、地図を保存し、共有できるようにすることを意識して開発しています。

## アクセスの仕方

以下のURLからGeoHubにアクセスできます。

https://geohub.data.undp.org/


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858331/9d4930ec-6f7a-436f-8a8b-d22e9c51286c.png)

:::note info
インフォメーション
現在ランディングページをもっとみやすいように再デザインをしていますので、近日中にアップデート予定です。
:::

ヘッダーの右側にあるSign inボタンからGitHubアカウントを持っているユーザー、もしくはUNDPを含む全ての国連機関職員なら誰でもサインインすることができます。

プラットフォーム自体はサインインしなくても利用可能ですが、新しいデータのアップロードや地図の保存などは利用できません。

## 主な機能

### データ管理機能

データポータルは[こちら](https://geohub.data.undp.org/data)からアクセスできます。Data uploadボタンから主なGISデータフォーマットは大体アップロード可能です。

ラスタデータはパイプラインで自動的にCOG（Cloud optiomised GeoTiff）に変換され、ベクタデータはPMTilesとFlatGeoBufに変換されて、UNDPのAzureにアップロードされます。

また、すでにあるデータを検索することも可能です。

ユーザーがデータをアップロードしてオープンデータとして公開する以外に、一部のSTACデータから衛生画像を追加できるようにもしています。

- Microsoft Planetary Computer (Sentinel 2, ESAなど）
- STAC Catalog (Maxar Open data, JAXA, HREAなど）
- UNDP STAC Catalog（Night time light mosaic）

以下は衛星データのみを検索した例です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858331/8f2bdf40-9334-cc1e-eb82-6d09d7f5ed1b.png)


### 地図編集機能

地図編集ページは[こちら](https://geohub.data.undp.org/maps)からアクセスできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858331/2a935467-ddda-20af-714a-be44916bd58a.png)

各レイヤごとにデザインの編集が可能です。サインインしていれば、地図を保存し、URLを共有することもできます。

また、ベクタデータのみですが、属性テーブルも表示可能です。

### ストーリーマップ作成機能

一番新しい機能として、Maplibreを利用したスクロールベースのストーリーマップを簡単に作成できるストーリーマップビルダーがあります。[こちら](https://geohub.data.undp.org/storymaps)からアクセスできます。

例えば、以下はサンプルのストーリーマップになります。

https://geohub.data.undp.org/storymaps/3c50cf49-0212-4014-9a7e-fafc27ad088a

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858331/893439ad-4477-1e1e-bc60-bf69efe985e9.png)

Viewボタンを押すと、ストーリーマップ本体が表示されます。

Editボタンを押すとストーリーマップエディタが表示されます（地図作成者または許可されたユーザーのみ可能）。

以下はサンプルのスクリーンショットになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858331/ac2519a7-eaa7-6b78-df6f-cfa3e002c4c5.png)

パワーポイントのような見た目のUIでできるだけ簡単に、GeoHub Mapsで保存した地図からストーリーを作成できるようにしています。

## ソースコード

GeoHubはBSD 3 Licenseで開発するオープンソースです。全てのソースコードは以下のリポジトリからアクセス可能です。

https://github.com/UNDP-Data/geohub
Snowflakeを作ったのは誰？設立者と当時の課題

# いつ作られた？

---

- 2012年 
  設立
- 2015年6月
  クラウドデータウェアハウスプラットフォーム発表

---

# 誰が作った？

---
Oracleのデータベースシステムに携わっていたエンジニア
- Benoît Dageville
- Thierry Cruanes

Vectorwise co-founcder 
- Marcin Zukowski

---

# 歴史的背景 2000年代

---

特別な用途をもった、リレーショナルOLAP(Online Analytical Processing) のシステムが出てきた。
- Vertica
- Greenplum
- MonetDB
- Vectorwise
- ParAccel

---

| DB   | 主な用途                        | アーキテクチャ           | 特徴                               |
|----------------|--------------------------------|-------------------------|------------------------------------|
| Vertica        | 分析、リアルタイム分析           | 列指向 + 分散型         | 高速クエリ、多クラウド対応         |
| Greenplum      | ビッグデータ、データウェアハウス | 分散（MPP）             | PostgreSQLベース、スケーラブル     |
| MonetDB        | 分析、科学計算                 | 列指向                 | オープンソース、OLAP特化           |
| Vectorwise     | データウェアハウス              | 列指向                 | CPUキャッシュ最適化、小規模データ向き |
| ParAccel       | 高速分析、AWS Redshiftの基盤     | 列指向 + 分散型         | Redshiftの基盤技術、クラウド向き   |

---

# 歴史的背景  2010年代初期

---
多くの組織が Hadoop/HDFS（Hadoop Distributed File System） でSQL を使用しようとしていた。
- Hive
- Presto
- Impala


#### Hadoopとは
データを複数のサーバに分散し、並列して処理するミドルウェア。
テラバイト、ペタバイト級大容量データの分析などを高速処理できる。

---

# Snowflakeはなぜ、Hadoopスタイルのシステムを使用しなかったのか？

---


- 大規模な特定のユースケースで使われる
- 分析のパフォーマンスが大幅に低下するため
- セキュリティ、管理の容易性にはあまりフォーカスされていなかった

---

# 当時の課題

---
- 複雑な管理
- スケーラビリティ
- あらゆる規模の企業の分析しやすいサービスがなかった
- 企業が生成するデータの増加を効果的に処理できない

---
# 参考文献
[21 - Snowflake Data Warehouse Internals (CMU Advanced Databases / Spring 2023)](https://15721.courses.cs.cmu.edu/spring2023/slides/21-snowflake.pdf)
[CMU Advanced Database Systems - 25 Ashish Motivala](https://15721.courses.cs.cmu.edu/spring2018/slides/25-snowflake.pdf)
[A brief history of Snowflake](https://www.bigeye.com/blog/a-brief-history-of-snowflake)
『ビッグエンディアン』と『リトルエンディアン』とその由来について浅く理解する

## そもそもエンディアンって何？？
2バイト以上のデータをメモリ上に展開したり、どこかに送ったり、保存するときの「バイト単位で見たときのデータの並び順」のこと

つまり下のようにどうやって塊(バイト)を並べるかってこと(バイトは0x07みたいな8bitの塊)

```python
hoge
0x68 0x6f 0x67 0x65
egoh
0x65 0x67 0x6f 0x68
```

**由来**
ガリバー旅行記に出てくるゆで卵の割り方が由来らしい
>Endianという呼び方は、もともとはガリバー旅行記に出てくる、ゆで卵をどちらの端の方から最初に割るかという議論に由来している。 
物語中では、大きな方の端から割る人々はBig End-ian、尖った方の端から割る人々はLittle End-ianと呼ばれていた（-ianは「～な人々」を表す接尾辞）。[1]

具体的なエピソードは以下のサイトに載ってます
http://fujimura2.fiw-web.net/java/mutter/endian/index.html



## ビッグエンディアン
**先頭から順にデータを保存していく方式。**
つまり、日本語のように左から右へデータを保存するのがビッグエンディアン。
hogeをバイトで表すと以下のようになる。
```python
hoge
0x68 0x6f 0x67 0x65
```

## リトルエンディアン
**逆順でデータを保存していく方式。**
下から順にバイトを読むような方式になるのがリトルエンディアン。
hogeをバイトで表すと以下のようになる。
```python
egoh(hogeを逆側から)
0x65 0x67 0x6f 0x68
```

## 何でこんなことが発生するん？？
普通に考えてビッグエンディアンだけでええやんって思ってしまう。

リトルエンディアン方式が採用されている理由として、計算速度が少しだけ早いパターンがあるということが挙げられる。

計算するときのことを考えるとわかりやすくて、

42+39をする時、

1. 下の位である2と9を足す。
2. 繰り上がった1と4と3を足す

こんな流れで計算することになると思う。

これが、下の位から保存していくリトルエンディアンの考え方と一致するため、リトルエンディアンの保存形式の方が少し計算が速くなる。

一方で、ビッグエンディアンの場合は一旦全部の数字を読みだしてから計算する必要があるため、リトルエンディアンに比べて少し遅くなるというわけ

ただ、ビッグエンディアンの方が当然人間にとっては直感的なわけで、プログラムを書く人間からするとビッグエンディアンの方が分かりやすい

## どっちの形式か判定するためのBOM
二つの方式があると当然、どんな順番でデータを読めばよいか分からなくなるという問題が発生する

UTF-16だとデータの先頭に `FE FF` が付くとビッグエンディアンが続くと表され、`FF FE` でリトルエンディアンが続くと表される。

UTF-32だと`00 00 FE FF` がビッグエンディアンで、`FF FE 00 00` がリトルエンディアンである。

これによって、読み込む方式が違うことによる文字化けを防ぐことができるというわけ

## 引用
[1] ZDNET JAPAN エンディアン
https://japan.zdnet.com/glossary/exp/エンディアン/?s=1
Spinnerの使い方

Androidのスピナーの使用方法をメモします。
``` xml 
<Spinner
    android:id="@+id/spinnerDate"
    android:layout_width="120dp"
    android:layout_height="50dp"
    app:autoSizeTextType="uniform" />
```
xmlにスピナーを設置する。動作に必要なコードのみ書いてます。

```kotlin
val array = arrayOf("果物", "リンゴ", "ブドウ", "ナシ", "ナシ", "オレンジ", "マスカット")
val arrayAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, array)
    spinner.adapter = arrayAdapter
```
`ArrayAdapter`にリストを並べるリストを詰めてスピナーのアダプターにセットします。

```kotlin
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
    override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
        // 選択された時の処理
        println(spinner.selectedItem)
        println("番号$position")
    }

    override fun onNothingSelected(parent: AdapterView<*>?) {
        // 選択しなかった時の処理
    }
}
```
アイテムを選択したタイミングで別の処理も同時に行いたい場合は`onItemSelected`を使用します。引数の`position`は選択したアイテムのインデックス番号と同じです。
```kotlin
spinner.setSelection(4)
// オレンジ
```
アイテムを変更したい場合は`setSelection()`を使用します。引数には指定したいアイテムと同じインデックス番号を設定します。
下記のように指定の果物をセットすることも可能。
```kotlin
for ((i, fruit) in array.withIndex()) {
    if (fruit == "リンゴ") {
        binding.spinner.setSelection(i)
    }
}
```

#### 参考
https://it-kyujin.jp/article/detail/1703/
**/*と検索した人に届け

この記事は[ソニックガーデン 若手プログラマ Advent Calendar 2024](https://qiita.com/advent-calendar/2024/sonicgarden-junior)の9日目の記事です。
## はじめに
Advent Calendarの流れでこの記事を読んでくれている方もいるかもしれませんが、おそらくこの記事に辿り着いた方は **「\**/\*」** という記法は何だと思った方だと思います。

結論を言うと **「linux glob」** と検索すればきっと欲しい情報が得られると思います。もちろんこの記事でも解説します

 **「\**/\*」** という記法は何と思った人向けて作成した記事です。

## 解説
早速この **「\**/\*」** 記法について詳しく見ていきましょう。これは、主にLinuxやUnix系システムで使用されるファイルパターンマッチングの一種である[「glob」](https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%AD%E3%83%96)の一部です。
> wikipediaからの引用
グロブ（英: glob）とは主にUnix系環境において、ワイルドカードでファイル名のセットを指定するパターンのことである。

globは、ファイルやディレクトリを指定する際に便利な方法を提供します。基本的に[ワイルドカード](https://ja.wikipedia.org/wiki/%E3%83%AF%E3%82%A4%E3%83%AB%E3%83%89%E3%82%AB%E3%83%BC%E3%83%89_(%E6%83%85%E5%A0%B1%E5%87%A6%E7%90%86))を用いて、特定のパターンに一致するファイル名やディレクトリ名を簡潔に指定することができます。

例えば、**「\**/\*」** というパターンは、次のように解釈されます
- **\*\*** これは、現在のディレクトリから再帰的にすべてのサブディレクトリを含むすべてのファイルやフォルダを対象にします。
- **/** ディレクトリを区切るためのスラッシュです。
- **\*** 任意の文字列にマッチします。この場合、特定のディレクトリ内のすべてのファイルを指します。

## 実際に試してみよう
ごちゃごちゃ書きましたが、具体例を見た方が分かりやすいと思うので実際に試してみましょう。

任意のディレクトリに移動してターミナルで以下を実行してください
```
mkdir test-dir

mkdir test-dir/dir1
mkdir test-dir/dir2
mkdir test-dir/dir1/subdir1
mkdir test-dir/dir1/subdir2
mkdir test-dir/dir2/subdir1

touch test-dir/file1.rb
touch test-dir/file2.rb
touch test-dir/file1.txt
touch test-dir/file2.txt
touch test-dir/dir1/file3.txt
touch test-dir/dir1/subdir1/file4.txt
touch test-dir/dir1/subdir2/file5.txt
touch test-dir/dir2/file6.txt
touch test-dir/dir2/subdir1/file7.txt
```
そうすると以下のディレクトリ構成になります。

```
test-dir/
├── dir1
│   ├── file3.txt
│   ├── subdir1
│   │   └── file4.txt
│   └── subdir2
│       └── file5.txt
├── dir2
│   ├── file6.txt
│   └── subdir1
│       └── file7.txt
├── file1.rb
├── file2.rb
├── file1.txt
└── file2.txt
```

**「\**/\*」** のパターンを使って、上記のディレクトリ構造でどのようにファイルを検索できるかを確認しましょう。以下のコマンドを試してみてください。
```
cd test-dir
ls **/*
```
このコマンドを実行すると、**test-dir**ディレクトリ内のすべてのディレクトリとファイルがリストされます。**「\**/\*」** パターンは、すべてのサブディレクトリを再帰的に探索し、その中のすべてのファイルを見つけることができます。

また、ちょっと応用して以下を実行してみます。
```
cd test-dir
ls **/*.rb
```
この場合、**「\**/\*.rb」** パターンを使用して、すべてのサブディレクトリ内の **.rb** 拡張子を持つファイルを見つけることができます。

## おわりに
この記事では、LinuxやUnix系環境で使用される「glob」パターンの一部である **「\**/\*」** 記法について解説しました。初めて、**「\**/\*」** この記法を見た人の疑問を解消できたら嬉しいです。

私自身実際に、**「\**/\*」** この記法はなんだと思った経験からこの記事を書きました。具体的に遭遇した場面はテストフレームワークであるrspecについて学んでいる時に出会いました。この記事を読んだ方なら以下のコードが`spec/support`配下の`.rb`で終わるファイルを対象に`require`していっているということが何となくわかると思います。

```ruby:spec/rails_heper.rb
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
```


以上です。次回、ソニックガーデン 若手プログラマ [Advent Calendar 2024](https://qiita.com/advent-calendar/2024/sonicgarden-junior)の10日目は[@yatsuhashi168](https://qiita.com/yatsuhashi168)さんです。お楽しみに！
AWS Certified AI Practitioner (AIF-C01) 勉強アウトプット②　～AWS用語編～

# 概要
インフラ屋さんがAI Practitionerを勉強してみたアウトプット

# わからなかったワード　-AWS用語-

- SageMaker Model Dashboard
- SageMaker Model Cards
- SageMaker Feature Store
- SageMaker Experiments
- SageMaker JumpStart
- SageMaker Model Registry
- SageMaker Clarify
- SageMaker Canvas
- Amazon Augmented AI(A2I)
- Amazon Forecast
- Amazon Lex
- Amazon Kendra
- トップP
- トップK
- 温度
- トークン

内容はそのうち書きます・・・