OmniAICreator/Qiita-1.07M huggingface dataset:
Kotlinよく使いそうな短いスクリプトまとめ

# 画面遷移
* ```MainActivity::class.java```は次の画面のファイルを指定すればOK


```kotlin
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
```

# フォーカスを当てる
```kotlin
//要素の取得
input =  findViewById(R.id.targetCd)

// Input項目へフォーカスを当てる
input.requestFocus()
```
Hello World!をコンソールに一文字づつ出力してみます。

## 環境
Visual Studio 2022
.NET 8.0
Consoleアプリケーション

## コード
```
// See https://aka.ms/new-console-template for more information
//Console.WriteLine("Hello, World!");

string str = "Hello, World!\r";
foreach (char s in str)
{
    Console.Write(s);
    Thread.Sleep(100);
}

```

## 出力![helloworld.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3859154/882bcc35-d6c0-8180-5843-d9f3cb21758c.gif)

## 感想
これでノベルゲームが作れるかも…
Google Earth Engineで夜間光の変化を見る

# 1. はじめに
前回の記事でQGISで夜間光の変化を算出したのですが、結局Google Earth Engine一つに絞った方が効率的と考えています。。

https://qiita.com/ishimotojuri/items/9881343925602a2fda63

今日はGoogle Earth Engineで夜間光データのインポート、変化の算出、可視化、ダウンロードまでやってみたので紹介します。

とはいっても、お客さんに出す最終的なアウトプットはQGISで加工することが多いのですが、できればGoogle Earth Engine一つで完結させたいなと思っています。。


# 2. コード

```js
// 最新更新日: 2024/08/28

//1．ネパールの境界データをインポートして、地図に表示させる
var dataset = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017');//境界データを取得する
var nepal = dataset.filter(ee.Filter.eq('country_na', 'Nepal'));//ネパールのデータを取得する
// ('シェープファイル上の変数名', 'データ名')

// マップに表示させる
Map.addLayer(nepal, {
  fillColor: 'b5ffb4',
  color: '00909F',
  width: 1.0,
},
'青:ネパール');
// {}：地図に表示される方法（色など）。デフォルトは黒


// 2. 夜間光データのインポート
var pre_data = ee.ImageCollection("NOAA/VIIRS/DNB/MONTHLY_V1/VCMSLCFG") 
             .filterDate('2014-01-01', '2014-12-31')
             .select('avg_rad')
             .filterBounds(nepal)
             .mean();

var post_data = ee.ImageCollection("NOAA/VIIRS/DNB/MONTHLY_V1/VCMSLCFG") 
             .filterDate('2023-01-01', '2023-12-31')
             .select('avg_rad')
             .filterBounds(nepal)
             .mean();


// 3. 夜間光量の差を計算する
var diff = post_data.subtract(pre_data);


// 4. 解析結果の可視化
// 変化をマップに表示させる
Map.addLayer(diff.clip(nepal), {
  min: -2,
  max: 2,
  palette: ['blue', 'yellow']
},

'夜間光量の変化');

// 5. 事業対象地域のインポート
var bphighway = ee.FeatureCollection('users/ishimotojuri/SindhuliRoad');
var town = ee.FeatureCollection('users/ishimotojuri/town');

// マップに表示させる
Map.addLayer(bphighway, {'color': 'black'}, '黒:シンズリ道路');
Map.addLayer(town, {'color': 'red'}, '赤:町');

Map.centerObject(bphighway,8);

// 6. 分析結果のエクスポート
Export.image.toDrive({
  image: diff,
  description: 'diff_ntl_nepal',
  folder: 'Nepal',
  region: nepal,
  scale: 500, //衛星データの解像度
  crs: 'EPSG:4326'
});

```
# 3. 参照リンク
上記コードは[こちら](https://code.earthengine.google.com/be560eba1a3405b3d286bbd7ee820de0)からGoogle Earth Engineで直接みれます。

ただし、上記のコードを実行するためには、以下のデータをご自身のGoogle Earth EngineのAssetにアップロードしていただく必要があります。

・SindhuliRoad.shp
・Town.shp

こちらの[フォルダ](https://drive.google.com/drive/folders/16bV7XI8e52p04TdBPdT94yIT2oH3tJCG?usp=sharing)からダウンロードできます。

データをAssetにアップロードしたら、以下のコードの（）内を変更してください。
var bphighway = ee.FeatureCollection('users/ishimotojuri/SindhuliRoad');
var town = ee.FeatureCollection('users/ishimotojuri/town');
超初心者向け解説：Amazon RDS for SQL Server のリードレプリカとは？

## はじめに

あなたは、データベースのパフォーマンス向上やコスト削減に頭を悩ませている経営者でしょうか？ それとも、AWSをこれから使い始めようとしている超初心者でしょうか？ 

もしそうなら、このブログ記事はあなたにピッタリです！ 今回は、AWSのデータベースサービスであるAmazon RDS for SQL Serverの「リードレプリカ」について、超初心者でも理解できるよう、わかりやすく解説していきます。

### リードレプリカとは？

リードレプリカとは、データベースの読み取り処理を別のサーバーに分散することで、パフォーマンスを向上させる機能です。まるで、お店のレジを複数台設置して、お客様の待ち時間を減らすようなイメージです。

### リードレプリカのメリット

リードレプリカには、様々なメリットがあります。

* **パフォーマンス向上**: プライマリデータベースへの負荷を軽減し、データベースの処理速度を速めます。
* **分析処理の高速化**: データ分析は大量のデータを読み込むため、リードレプリカを使用することで処理速度を大幅に向上させることができます。
* **コスト削減**: リードレプリカは、プライマリデータベースよりも安価なサーバーを使用できます。
* **災害対策**: 異なる地域にリードレプリカを作成することで、災害発生時にもデータにアクセスできるようになり、事業の継続性を高めます。

### リードレプリカの種類

リードレプリカには、以下の2種類があります。

* **リージョン内リードレプリカ**: プライマリデータベースと同じ地域にリードレプリカを作成します。
* **クロスリージョンリードレプリカ**: プライマリデータベースとは異なる地域にリードレプリカを作成します。

### リードレプリカを使用する際の注意点

リードレプリカは非常に便利な機能ですが、いくつか注意すべき点があります。

* **書き込みはプライマリのみ**: リードレプリカは読み取り専用のため、データの書き込みはプライマリデータベースで行う必要があります。
* **自動フェイルオーバーなし**: リードレプリカは、プライマリデータベースが停止した場合でも自動的にプライマリに昇格することはありません。手動で昇格させる必要があります。
* **同期遅延**: データの同期には時間がかかる場合があり、プライマリデータベースとリードレプリカ間のデータにずれが発生する可能性があります。

### まとめ

リードレプリカは、データベースのパフォーマンス向上、コスト削減、災害対策に役立つ便利な機能です。AWSのサービスを活用することで、より安全で効率的なデータベース運用を実現できます。
データの受け渡し練習のためECサイト作ってみた

## 記事の概要
エンジニア未経験からの挑戦ということで企業様へアピールするためのポートフォリオを作成してみました。
作成手順と機能、工夫したところ、課題点を書き出してみようと思います。

### プロフィール
20代後半　男性
ITは全くの未経験(前職は営業)
就労移行支援にて０からプログラミングを学ぶ。
**作成期間は1ヶ月くらい**

## 目的
* JavascriptとPHPを使いつつDBとの連携も行えるよう経験を積む
* 今の自分のレベル感を企業に見ていただく
* 素のJs、PHPでどこまで書けるかチャレンジ

# スペック
**言語**
    Javascript (Vanilla Js)
    PHP 8.0.19
    
**DBMS**
    MySQL  Ver 8.0.29

**開発環境**
    Windows 11 Pro
    IIS　(Version 10.0.22621.2860)


## 完成画面
(圧縮上手くできませんでした。。。)
![ECサイト.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683991/6d12ec89-0328-6380-5d25-036f834c7bf4.gif)

******************************


### こだわったところ
**カートアイコンのカウント**
![スクリーンショット 2024-08-28 111013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683991/b0afb303-eb6d-8656-44fa-33e73c7a3104.png)

ECサイトと言えばカートアイコンのカウントが増えていく某有名サイトの仕様が凄く頭の中にあったのでやってみましたが、かなり難しかったです。
自分の場合はJavascriptでローカルストレージに保存してカートカウントを取得・更新しましたが、あんまり実戦的じゃないので素のJavascriptの限界を感じております。
jQueryは使えるけど、もっと新しいフレームワーク勉強しなきゃ…


<br>

**商品の数量をまとめる・一つずつ削除する**
![ニット.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683991/33233838-ace0-7439-f24c-38342574186d.gif)

カートに追加してカートページを更新するのは比較的容易にできたのですが、一個ずつしか追加されず、ニットx4と表示したいところが「ニットx1ニットx1ニットx1ニットx1」みたいになってしまいかなり苦戦しました。
また、ニットx4の表示に成功しても、削除ボタンを押すと4つ全て削除されてしまう問題も起き、コードの書き直し、設計し直しで序盤の躓くポイントでした。難関！

<br>

**注文履歴の作成**
![スクリーンショット 2024-08-28 112802.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683991/63aee2b2-6383-3cd1-466a-c422625ff2ed.png)

**一番やりたかったのはこれ。**

前回予約サイトを作ってみて **「自分がいつ予約したか履歴見られるようにしないとな～」** と思って作り始めたのが今回のサイトです。
なので、データベースと絡めて、そのIDでいつどんな注文を送ったか分かるような仕様を作ってみたいと思って作り始めました。
<br>

結果的にそこまで難しくはなかったのでホッとしています。
ただここでも右端の数量の箇所で躓きました。カウント増やしていくだけなのに今回はやたらそこに沼りましたね…。
異なる言語間、DBへの接続では **データの受け渡しが命** ということは前回で痛いほど分かったので今回はそこまで痛手じゃなく済みました。（苦労はした。）


## 振り返ってみて
前回は設計段階から曖昧な設計をしており、プログラミングを書きながら **思いついた仕様を追加していくという愚策** を行ってしまったのでかなり非効率なコーディングをしていきましたが、今回は **素直に設計通りにやりたいことをやっていく** ようにしたら割と目標期間内で作れました。

あとはいつものデータベースへの**データの受け渡し**でとか**ページをまたいだ際のデータ処理**がまだまだ慣れないという感じですので、設計全体を俯瞰してどうコードを書いていくかが重要だと感じました。

他人に見られても大丈夫な見やすいコードを心がけます…。

## Github
Githubにも公開したのでよろしければ…

https://github.com/amedamasan/ECsite
Pythonでスクレイピングをしてみよう

## はじめに
こんにちは、らっじです

今回は、Pythonでスクレイピングする方法を解説します

## 環境
以下の環境で実行してます

- Ubuntu 24.04 LTS x86_64 (Proxmox)
- Python 3.12.3 venv
- beautifulsoup4 4.12.3
- requests 2.32.3

beautifulsoup4とrequestsはpipでインストールしています

## スクレイピングとは
WebページはHTMLで書かれていて、それを解析して必要な情報を抜き出すことをスクレイピングといいます

:::note warn
スクレイピングをしまくるとサーバーに負荷がかかったりするので、スクレイピングを禁止しているサイトもあります
:::

スクレイピングの手法は大きく分けて、

1. HTTPリクエストを送り、返ってきたレスポンスのHTMLを解析する
2. ブラウザをスクリプトで操作して情報を取り出す

という2種類がありますが、今回は1のほうをやります

(2のほうはSeleniumというライブラリでできるので興味があったら調べてみてください)

## 手順
今回は試しに、[Yahoo天気](https://weather.yahoo.co.jp/weather/jp/13/4410.html)から今日明日の東京の天気を取得してみます

![Screenshot 2024-08-28 at 12.23.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637875/d7d0ece7-00b8-5a44-6362-db2a62d84af2.png)


### HTTPリクエスト
まずは、解析したいサイトにHTTPリクエストを送り、HTMLを取得します

```python
import requests

url = "https://weather.yahoo.co.jp/weather/jp/13/4410.html"  # Yahoo天気のURL

response = requests.get(url)

print(response.text)
```

これでHTMLが標準出力に表示されるはずです

### BeautifulSoup4で解析
次に、取得したHTMLをパーサーに読みこませます

```python
from bs4 import BeautifulSoup4

soup = BeautifulSoup4(response.text, "html.parser")

print(soup.title)
```

このようにすると、titleタグのみを抜きだせているはずです

では実際に天気の情報を取得してみましょう

まずは、欲しい情報がHTML内のどこにあるかを探します

![Screenshot 2024-08-28 at 12.37.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637875/1af9c173-c237-b560-6c9b-a8f97d11e210.png)

Chromeを使っている場合は、欲しい要素上で右クリックして「検証」というメニューを押すと、ページのソースが表示されて分かりやすいです

見ていくと、`forecastCity`というclassのdivの中にtableがあって、その中をたどっていくと、2つのtdにそれぞれ今日と明日の情報が入っていて~という感じにわかってきます

これをコードに書いていくと最終的に以下のようになります

```python
td = soup.find(class_="forecastCity").find("tr").find_all("td", recursive=False)  # td[0]が今日でtd[1]が明日

print(td[0].find(class_="date").text.strip())  # 8月28日(水)
print(td[0].find(class_="pict").text.strip())  # 曇時々晴
print("最高気温: " + td[0].find(class_="high").text.strip())  # 最高気温: 33℃[+1]
print("最低気温: " + td[0].find(class_="low").text.strip())  # 最低気温: 27℃[+1]

print(td[1].find(class_="date").text.strip())  # 8月28日(水)
print(td[1].find(class_="pict").text.strip())  # 曇時々晴
print("最高気温: " + td[1].find(class_="high").text.strip())  # 最高気温: 33℃[+1]
print("最低気温: " + td[1].find(class_="low").text.strip())  # 最低気温: 27℃[+1]
```

findメソッドやfind_allメソッドで辿っていくことができます

findメソッドは、子要素の中から検索して合致するもののうち1つめを返します

find_allメソッドは、検索結果を全てリスト形式で返します

あとは、.textで中身のテキストを抜き出して、.strip()でいらない空白や改行を削除しています

検索方法はドキュメントを読むのが間違いないと思います

https://kondou.com/BS4/

また、CSSを理解している人は、[CSSセレクタで探す](https://kondou.com/BS4/#id37)ほうが分かりやすいかもしれません
AWSのAIサービスのオプトアウト（Opt-Out)設定について

## はじめに
AWSは、サービス改善や品質向上のために、ユーザーのリソース使用状況やメタデータを収集することがあります。
AWSではデータが利用されないようにするため、オプトアウト(Opt-out)を設定することが可能です。
今回はAIサービスのオプトアウト設定をしてみたいと思います。
## 前提
・AWSアカウントがあること(Organaizationを操作出来る権限があること)
## やること
本記事は**AIサービスのオプトアウトのポリシーを特定のアカウントにアタッチ**する手順になります。
手順は以下になります。
1.AWS OrganizationsでAI サービスのオプトアウトポリシーを有効化する
2.オプトアウトポリシーを作成し、アカウントにアタッチする
## 1.AWS OrganizationsでAI サービスのオプトアウトポリシーを有効化する
AWSコンソールの検索窓で「Organizations」を検索します。
「Organizations」の画面で「ポリシー」を選択します。
「AIサービスのオプトアウトポリシー」を選択します。
![スクリーンショット 2024-08-25 155757.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677761/e686df1f-9e1f-4c00-45a5-8f4325be1a78.png)

「AIサービスのオプトアウトポリシーを有効にする」を押下します。
![スクリーンショット 2024-08-25 155806.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677761/ffa99b2d-45f6-eebe-9489-524b5b948d72.png)
ポリシーの画面に戻ると「AIサービスのオプトアウトポリシー」が有効になったことが確認できます。
![sute-tasu .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677761/611cfa26-7daf-21ff-c611-4e98eb2ac17c.png)

次にメニューから「AWSコンソールアカウント」を押下します。
対象のアカウントを押下します。
![対象のアカウント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677761/41571a3b-c834-bc47-cd21-811f62abc655.png)

アカウントの画面で「ポリシー」タグを押下し「アタッチ」を押下します。
![アタッチ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677761/f81c9c5f-4e65-908f-ffb3-9943d7f55c5a.png)
ポリシー作成に進みます。



## 2.オプトアウトポリシーを作成し、アカウントにアタッチする
「ポリシーを作成」を押下します。
![ポリシーを作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677761/1bdeb89f-284e-03d8-70a3-b2c9dd7e1ed3.png)
「新しいAIサービスのオプトアウトポリシーを作成」画面でポリシーを作成します。
ポリシー名を入力します。
![新しいAIサービスのオプトアウトポリシーを作成画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677761/6bf6a6d5-e87b-220c-30c7-eaa80ff11129.png)
それ以外はデフォルトのままです。
JSONに適用したいポリシーを入力します。
今回は「**デフォルトで全ての機能やデータ収集からオプトアウト（利用しない、または拒否）する設定**」を行います。
以下のコードを貼り付け「ポリシーの作成」を押下します。
```
{
    "services": {
        "default": {
            "opt_out_policy": {
                "@@assign": "optOut"
            }
        }
   }
}
```
作成したポリシーにチェックを入れ「ポリシーのアタッチ」を押下します。
![スクリーンショット 2024-08-25 162347.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677761/cc12d2a1-94a5-a728-11e0-44cf6d9d7b93.png)

対象のアカウントの「ポリシー」タグの「適用されたポリシー」に先程作成したポリシーがアタッチされていることを確認します。
![porisi- .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677761/d035fc39-0edb-f8dc-45e0-43fb28346dfa.png)

設定はこれで完了です。
なお「デタッチ」の際はこの画面で対象のポリシーを選択し「デタッチ」を押下すればデタッチされます。
## 確認
AIポリシーが適用できているか確認します。
オプトアウトを設定したアカウントの「ポリシー」タブで「このAWSアカウントの有効なAIポリシーを表示する」を押下します。
![有効なAIポリシー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677761/68464175-6bbe-2bfc-9d7f-f653d00e212c.png)
ポリシーが有効になっていることが確認ができます。
![AIポリシー有効確認画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677761/76d73445-c919-69b3-071c-af8bb697e246.png)

## まとめ
普段はあまり意識することが無い設定かもしれませんが、設定が必要な際は参考にしていただければ幸いです。

## 参考資料
https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_ai-opt-out.html
関数が呼び出された箇所のディレクトリを取得する方法

- next.jsといったwebページのパスとディレクトリが対応しているフレームワークで、ディレクトリ名を変えると他の箇所も記述を変える必要があるといったことに対応したい

# コード
以下を貼り付けて実行すると、この関数が実行されたファイルのディレクトリパスが表示される
```typescript
// denoならこれ↓を記述
// import * as path from "node:path";
// import * as fs from "node:fs";
import * as path from "path";
import * as fs from "fs";
/*
 * find Directory when you call this function
 */
export const findCurrentDirectory = (): string | undefined => {
  const err = new Error();
  const stack = err.stack?.split("\n") || [];

  // 呼び出し元のスタックトレースを解析して、呼び出し元ファイルのパスを取得
  const callerLine = stack[2]; // スタックの3行目に呼び出し元の情報がある
  const match = callerLine.match(/\((.*):\d+:\d+\)$/);

  if (match) {
    const fullPath = match[1]; // ファイルのフルパス
    const callerDir = path.dirname(fullPath); // ディレクトリ名を取得
    const lastPathSegment = callerDir.split("/").pop(); // 最後のパス部分だけを取得
    return lastPathSegment;
  } else {
    console.log("Could not determine the calling directory.");
  }
};

console.log(findCurrentDirectory());
```
IPv4 アドレスからその所属国のカントリーコードを検索するためのGo言語用モジュールを作ってみました

![作ったモジュールのデモ用CLI](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3872080/b1b67141-5220-d26b-8808-f16390db0551.png)

勉強がてら、IPv4 アドレスからその所属国のカントリーコードを検索するためのGo言語用モジュールを作ってみました（上の画像は、そのモジュールのデモ用CLIのスクリーンショット）。
せっかく作ったので、需要は無視して無謀にも公開。

[github.com/suka-test/ccipv4](https://github.com/suka-test/ccipv4)

## 作った動機とか

IPアドレスの国判定なんていうのは、いろんな手段が提供されていまして、今さら作る必要もない気もしますが。
実際、わたしもアクセスログのチェックなどに、アメリカのMaxMind社が提供している無償利用可のジオロケーションデータベース GeoLite2 Free をずっと使っていました。

[MaxMind](https://www.maxmind.com/en/home)

だいぶ前にダウンロードした（多分、５，６年以上前）のを、そのまま使っていました。IPアドレスの所属国って、そうそう変わるものじゃないだろうと高をくくっていたからですが、どうもそうじゃないらしい。
最近、なんか、おかしいなと思って、他のサービスを使って確認してみたら、手元のデータベースでは **ドイツ** と出るのに、よそでは **ロシア** だったり・・・。ダメじゃん。
じゃあ、新しいのをダウンロードすっかぁ、とMaxMind社のサイトを見てみたら、今でもフリーで使えるらしいのですが、なんだか手続きがめんどくさくなってる・・・。たりぃ。
なら、いっそ、自分で作ってしまえ、と（短絡）。

## 使い方・機能

使い方はグダグダと [ccipv4: README](https://github.com/suka-test/ccipv4?tab=readme-ov-file#readme) に書きましたので、ご参照ください。
機能としては、基本的に **IPv4 アドレスからカントリーコードを検索するだけ** です（他にオマケ的なことも、ほんのちょっと、できますが）。
取り柄があるとしたら、使いながら新しいデータをダウンロードして古いのと切り替えられるようにしてある（つもり）ことかな。
必要なデータを全部メモリに読み込んだ状態で検索をかけているので、応答はさほど悪くないと思います。
ただ、その分、メモリを余計に食ってしまうという難点もあるのですが・・・。

などという、ふつつかモノですが、なにかの折にでもお試しいただければ幸いでございます。
【Swift】Realmを使ったCRUD（追加・読み取り・更新・削除）処理

# はじめに
タイトルの通り、Realmを用いてデータを扱っていこうという記事です。
文字列の保存をRealmを用いて最も一般的な追加〜削除までを取り扱います。読み取る際のフィルタリングとかは別途記事を書く予定です。
# 0.0. データベースとかRealmの簡単な説明
簡単に言うと、データベースはデータを一箇所に集約してデータ（情報）を保管・管理できる場所のことです。
以下のようなものをデータベースと言います。
| 商品名 | 値段 |
|:-:|:-:|
| じゃがいも  | ¥100  |
| キャベツ  |  ¥360 |
|  人参 | ¥90  |

で、Realmはモバイル向けのデータベースのライブラリです。
Realmという超優れ物のライブラリを使うことで簡単にデータベースを作ることができます。
ちなみに、Userdefaultsもありますが、こちらは大きい容量のものを保存するとどんどん重くなってしまうなど、デメリットが多々あるので個人的には断然Realm派です。

# 1. モデル
色々処理を始める前に、まずはデータを扱うための場所を作ってあげます。
今回は以下のようなモデル（VegetableModel）を作成しました。
idはアップデートの際に使用します。
| 変数名 | 型 |
|:-:|:-:|
| name  | String  |
| price  | Int  |
| id  | String  |

``` Swift
import Foundation
import RealmSwift

class VegetableModel: Object {
    @objc dynamic var name: String =  ""
    @objc dynamic var price: Int = 0
    @objc dynamic var id: String = UUID().uuidString //updateの際に必要
    override static func primaryKey() -> String? {
        return "id"
    }
}

```

# 2. 追加
場所を作ったらまずは追加をします。
`realm.write`の中で処理を行うようにしましょう。例えば、`realm.add(mode)`の部分をその外に書いてしまうと、`追加・更新・アップデートなどの処理はwrite{}の中で行われなきゃいけないよ`とエラーが出て怒られます。

``` Swift
let realm = try! Realm()
@IBAction func tappedSaveButton(_ sender: UIButton) {
    let model = VegetableModel()
    try! realm.write({
        model.name = nameTextField.text!
        model.price = Int(priceTextField.text!)!
        model.id = UUID().uuidString
        realm.add(model)
    })
    
    print(model)
}
```
# 3. 読み取り
追加ができたら、追加した内容を読み取りましょう。簡単ですね。
``` Swift
var vegetableList: Results<VegetableModel>!
self.vegetableList = realm.objects(VegetableModel.self)
```
例えば0番目のnameを取得したい場合は
```Swift
self.vegetableList[0].name
```
とすれば取得できます。

# 4. 更新
vegetableListの0番目のnameをcabbage、priceを360にアップデートするコードです。
更新したい対象の項目をidで検索して一致したら更新します。
```Swift
@IBAction func tappedUpdateButton(_ sender: UIButton) {
    try! realm.write({
        if let model = realm.object(ofType: VegetableModel.self, forPrimaryKey: vegetableList[0].id) {
            model.name = "cabbage"
            model.price = 360
        }
    })
    self.vegetableList = realm.objects(VegetableModel.self)
}
```
# 5. 削除
vegetableListの0番目を削除するコードです。
削除も更新と同じく、対象の項目をidで検索して一致したら削除します。

```Swift
@IBAction func tappedDeleteButton(_ sender: UIButton) {
    try! realm.write({
        if let model = realm.object(ofType: VegetableModel.self, forPrimaryKey: vegetableList[0].id) {
            realm.delete(model)
        }
    })
}
```

# その他
Modelの中身を書き換えると実行した時にエラーが出るので、その際はとりあえずシミュレーターからアプリを削除するのが手っ取り早いです。
実際はマイグレーション処理を行うとこの問題は解決しますが、この記事では一旦置いておきます。

書き加えることが出てきたら随時更新します。
Node.jsとはなにか？なぜみんな使っているのか？

[Node.jsとはなにか？なぜみんな使っているのか？](https://qiita.com/non_cal/items/a8fee0b7ad96e67713eb)
という記事をAIで動画にしてみました。
<iframe width="560" height="315" src="https://www.youtube.com/embed/Ke0ZNtnLUxQ" frameborder="0" allowfullscreen></iframe>
ESP32: Light Sleep の使い方

こちらのプログラムを参考にしました。
[How to use Light Sleep mode on ESP32](https://www.luisllamas.es/en/esp32-light-sleep/)

## プログラム

```text:light_sleep.ino
// ---------------------------------------------------------------------
//	light_sleep.ino
//
//						Aug/28/2024
// ---------------------------------------------------------------------
#define	PROGRAM	"light_sleep.ino"
#define	VERSION	"2024-8-28 PM 12:03"

// ---------------------------------------------------------------------
void setup() 
{
	Serial.begin(115200);
	delay(3000);
	Serial.println(PROGRAM);
	Serial.println(VERSION);
	Serial.println("*** setup end ***");
}

// ---------------------------------------------------------------------
int counter = 0;

void loop() {

	Serial.println(PROGRAM);
	Serial.println(VERSION);
	Serial.println(counter);
	counter ++;

	delay(10);
	esp_sleep_enable_timer_wakeup(3 * 1000000); //light sleep for 2 seconds
	esp_light_sleep_start();  
}
```

## Arduino IDE
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/11714abc-e766-44c5-f14e-11132726d9ac.png)
ngrokでHTTPSサーバーを公開する方法

ぷちハマりしたのでメモ

# ngrok
ngrokとはローカルで開発したサーバーをインターネットに公開するサービスです。
リバースプロキシしてる感じに近い。

# いつもの方法
httpのサーバーを公開する方法
```bash
# ポート番号3000の場合
ngrok http 3000
```

# httpsの場合
mkcertなどでサーバー証明書を作成してHTTPS化した場合、URLはフルで指定する。
```bash
ngrok http https://localhost:3000
```

# おまけ、visit siteを表示しない方法
ngrokで公開したサーバーに接続するとき"visit site"ボタンが現れる。
これはプログラムからAPIを呼び出したとき邪魔になる。

リクエストヘッダーに"ngrok-skip-browser-warning"を指定すればスキップできる。
(valueはなんでもいい。)
Open API Specでコード生成する際の個人的チェックリスト

## 前提

- フロントエンドではopenapi-typescriptを利用している
- バックエンドではOepnAPI Generator(Spring)を利用している
- OpenAPI Specの記述にはredocly-cliを利用している

## pathファイルのポイント

- tagsに記載した内容がコントローラー名になる
    - 複数名で開発している時にはコンフリクトに気をつける必要がある
- [ ] descriptionにはクライアントがどう利用するか、どういう結果が返ってくるかを記載している
- operationIdに記載した内容がメソッド名になる
    - なので冗長な名前はつけなくて良い
        - 例： UserController#getUserByIdとかはgetByIdとかにできる
    - ただしoperationIdは全体でユニークである必要がある
- [ ] parametersにはそのパラメータにどういう値をしているするとどういう結果が返ってくるか記載している

## schemaファイルのポイント

- [ ] schemaに記載した内容がdtoのファイル名になるので、単独でみた時にわかるようにしている
- $refを使わずにschemaを指定した場合、titleの内容がDTOのクラス名になる
    - [ ] titleにはDTOのクラス名になってもいいよう英語で記載し、descriptionに日本語で記載する
- $refを使わずに別々のファイルで同じ内容のobjectを定義した場合、一方のファイルはもう一方のファイルで定義されたDTOを参照することがある
    - 例： user.yamlとsupport.yamlで同じ構造を持つpropertyとしてcommonを持っていた場合、生成されるDTOはUserCommonDto.javaになり、UserDto.javaとSupportDto.javaの両方からUserCommonDto.javaを参照する
- APIのレスポンスがNULLで返される場合にはnullableをつける（OpenAPI 3.0系の場合）が、nullableをつけたプロパティはOpenAPI Generator(Spring)でJsonNullable<>でラップされて扱いづらくなる
  - [ ] JsonNullableをつけないようにはOpenAPI GeneratorのopenApiNullableプロパティをfalseにする（デフォルトはtrue）
- requiredをつけないとopenapi-typescriptで生成される型定義ではundefinedを含むUNION型になる
  - springで生成されるDtoのコンストラクタでrequiredをつけたプロパティが含まれ、かつgetterにBean  Validationの`@NotNull`がつくので実行時に落ちる
  - [ ] nullableとrequiredのどちらかだけつける

## その他

- undefinedなプロパティもバックエンド側にはnullが入った状態で送ってくれる
  - openapi-typescriptがやってくれているのかSpringのjacksonがやってくれているのかまでは追っていない
【合格体験記】Java Silver 17を受験してみて

## はじめに

  先日、Java Silver 17に合格したので、感想や気を付けたことを残します。
  Java Silver 17の受験に際して、ネット上など情報が少なく、こういった合格体験記が少なく苦労したので、少しでも参考になれば幸いです。
  
  ※誤りありましたら、ご指摘いただけますと幸いです。

## Java Silver 11との違い
  簡単には以下のような違いです。
  |  | Java Silver 11 | Java Silver 17 |
|----------|----------|----------|
| 制限時間 | 180分 | 90分 |
| 問題数 | 80問 | 60問 |
| 合格正答率 | 63％ | 65％ |

  Java Silver 17では1問あたりに避ける時間が減った他、合格正答率もやや上がっています。

### 試験範囲
  大半は同じですが、Java Silver 11で出題範囲となっていた **「ラムダ式」「モジュールシステム」** 等は、Java Silver 17では試験範囲外となっています。  

  逆にJava Silver 17では **「Switch文・Switch式」「レコードクラス」「シールクラス」「パターンマッチング（instanceof）」** 等が新たに試験範囲に追加されています。


## 受験までの勉強  
  受験までの勉強時間は約1か月ほどでした。  

  Java Silverを勉強するに際して、黒本と呼ばれる参考書が人気のようですが、Java Silver 11までしか発売されておらず（2024年8月28日現在）、今回はJava Silver 17の紫本をメインに学習を進め、試験1週間前にJava Silver 11黒本にも手を付けた形でした。

  紫本は流しで1周、じっくり1周、最後にそれらの復習で1周の計3周しました。
  その後、巻末に模擬試験が2つ（うち1つは公式サイトからダウンロード）あるので、それらを受験。  
  1つ目に関しては全く時間が間に合わず **90分で45問程度** しか終わりませんでした。  

  軽く復習して2つめの模擬試験を受験するも **90分で57問解答、正答率は50％** でした。  
  この時点で試験1週間前でしたので、危機感を感じ、理解が曖昧な部分を洗い出して猛復習、黒本（Java Silver 11）も3日で1周しました。  

  黒本の模試については、Java Silver 11なので180分80問解答が本来のところ、早く解答することを意識して90分で80問解答しました。こちらも模試は2つあり、試験範囲外の問題は除いて正答率は **85％～90％** 程度でした。
  

## 受験本番
  近くのテストセンターで受験しました。
  受付では顔写真の撮影や試験の説明等を受け、受験が始まります。  

  受験会場では1枚のメモ用紙が配られるので、メモしながら回答することも可能です。私は使用しませんでした。  
  会場によるかもしれませんが、その他希望すれば耳栓なんかももらえるみたいです。  

  ITパスポートや基本情報技術者試験同様、合格結果は受験後すぐにPCに表示されます。  
  試験終了後はスコアレポートを受付で受け取り、受験サインをして終了となります。
  

## 気を付けること
  受験した上で感じた気を付けた方がいいことを下記にまとめます。
  あくまで個人の感想にはなるので、その上で参考にしていただければ幸いです。

### 細かい部分まで確実に理解すること
  正直、普段からJavaを触っているので、ある程度理解しているつもりになっていましたが、試験では細かい部分の理解を問われます。

  **インタフェースのメンバ** についてや **継承時のルール** 、 **コンストラクタ** 、その他新たに触れた **シールクラス** や **レコードクラス** 等々、覚えることがかなり多いです。  

  試験本番でも、「そこ聞くか～」って思わず呟いてしまうような部分を問われます。  
  
  普段実装する中で、そういった部分は随時調べて進めればいいわけですが、本番はそうは行きませんので、 **参考書の内容は確実に理解していいるレベル** まで落とし込んでおいた方がいいです。  
  
  なんとなくの理解だと確実に落ちると痛感しました。

### 試験時間・試験問題に慣れておくこと
  模試でかなり苦労した部分は、何より時間の少なさでした。コードを読み、選択肢を読み、解答を選ぶという作業を約1分半で行う必要があります。  
  本番ではダミー問題という、正答選択肢のない問題もあるようです。  
  難しく悩む問題は適当にマークして次の問題に進む等、時間を意識しながら進めることが大切になります。

  そのためにもまずは、コードを読むスピードを上げる事を前提として、試験問題の意図を読み取ることができるか否かが非常に重要だと感じました。  

  例えば、 **「この問題は継承先のルールが問われている」** **「この問題は変数の初期化ルールを問われている」** というように、各問題で何を問われているかを察知し、その知識を選択肢と照らし合わせるという作業を、60問行うことになります。  

  上記に慣れるためにも、模試を多く解くことが重要になります。

### 模試の結果で一喜一憂しない
  最初に解く模試は難しく感じるかもしれないです。私自身、紫本の模試はどちらも散々な結果でした。  
  ですが、細かい部分を理解できるようになり、時間配分を覚えてくれば、確実に点数は上がっていきます。  

  あくまで主観にはなりますが、難易度について、 **紫本の模試（Java Silver 17）は難しく、黒本の模試（Java Silver 11）は易しく** 感じました。  

  また、Java Silver 11では、黒本で学んだ問題が実際の本番でもほぼ同じ形で出た、というようなことがあったと聞いたことがありました。
  しかし、今回受けたJava Silver 17の本番ではそのようなことはなく、紫本レベルの難易度高めの問題がゴロゴロ出てきたように私個人的には感じました。（問題は全員一緒ではないと思うので、人それぞれかとは思います）  

  ですが、上記で記述した、 **「細かい部分まで確実に理解すること」** **「試験時間・試験問題に慣れておくこと」** これらができていれば、ちゃんと合格できるはずです。  

  模試の結果で一喜一憂せず、この範囲は何も見ずに自分で説明できるまで理解できているかを突き詰めていくことが重要になると感じました。

## まとめ
  Java Silverの受験は、資格を取得すること自体というよりも、Javaの構造であったり細かいルールを理解するという意味で非常に有意義な勉強をできたと感じました。  

  実際に勉強をした後と前では、コードに対する理解力は上がっていると思います。 

  ただ合格を目指して過去問を解きまくるのではなく、自分が理解できているかどうかを照らし合わせながら学習を進めていくことが、実は合格の近道で、そして今後にも繋がる勉強法なのではないかと思うので、この記事が少しでも皆様の学習のお役に立てれば幸いです。
Jetpack Compose の Modifier.testTag() で指定した内容がテストで見つからない場合

:::note info
androidx.compose.ui.test 1.6.8 にて確認
:::

.onNodeWithTag(useUnmergedTree = true) を指定すると、testTag() で指定した内容を取得できる。

```kotlin
// 実装
Image(
    painter = painterResource(id = R.drawable.icon_name),
    contentDescription = "アイコンの説明",
    modifier = Modifier.testTag("テストタグ")
)

// テスト
composeTestRule.onNodeWithTag("テストタグ", useUnmergedTree = true).assertIsDisplayed()
```

参考

https://qiita.com/takahirom/items/3de0fe66dace14b41e23
【ChatGPT＋Code Interpreter】で日本語の描画をします。


　どうも、カーブミラーです。

　今回は、日本語の描画をします。PDFでも使えるようになります。

:::note info
本記事は、ChatGPT（有料版）
で行なっております。画像は
ありません。　あしからず。
:::

　まずは、ニュース。

　本日（2024/08/28）、
　　Anthropicからポストが
　　　ありました。
　　　　[Anthropic公式ポスト](https://x.com/AnthropicAI/status/1828462522468372600?t=WOGlL73oqDII47tV1f877Q&s=19)

　すべてのClaudeユーザーが
　　Artifactsを利用できるように
　　　なりました。 

　Claudeの
　　iOSとAndroidアプリでも
　　　Artifactsの作成と閲覧が
　　　　可能になりました。

***
***user***
ClaudeのArtifactsとはなんですか？

***Perplexity***
ClaudeのArtifacts（アーティファクト）は、AnthropicのAIモデルClaude 3.5 Sonnetに追加された新機能です。この機能は、AIとの対話を通じて生成された成果物を管理・表示するためのもので、画面を左右に分割してAIとの対話と生成物を同時に確認できます。Artifactsは、プロジェクトごとに資料やプロンプトを集約することができ、無料プランでも利用可能ですが、使用回数には制限があります。
***

　詳しい説明と使い方は
　　こちらを参照してください。
　　[チャエンさんポスト](https://x.com/masahirochaen/status/1828581836706177118?t=TFLRzJ1Va9HEHfZ78vyOTA&s=19)
***
　さて、本題です。

　今回は、
　　Code Interpreterで
　　　日本語の描画をします。

　昨日（2024/08/27）の
　　PDF作成もこれで
　　　日本語化できました。

　前々から
　　方法は知っていたのですが、
　　　スマホ使いの私は
　　　　躊躇していました。

　なにせ、
　　パソコンがなければ
　　　できない、と
　　　　思っていたからです。

　試しにやってみたら、できた、と
　　言う訳で、今回の記事に
　　　することにしました。
***
　日本語を使うには
　　何をどうすればいいのか。

　日本語を扱えるフォントを
　　用意して、それを使うように
　　　指示するだけです。

　毎回、
　　指示しなければならないのか？

　いいえ。
　　一度、アップロードすれば
　　　そのセッション内での
　　　　テキスト描画に使えます。

　　ただし、
　　　Code Interpreterは
　　　　一定時間が経過すると
　　　　　環境を保持できなくなり
　　　　　　処理ができなくなります。

　　また、
　　　新たなセッションには
　　　　引き継がれませんので
　　　　　そうした注意は必要です。
***
　日本語を扱えるフォントは
　　Code Interpreterにはありません。

　だから
　　外部から
　　　ダウンロードする
　　　　必要があります。

　有名なものは
　　NotoSansJPですね。
　　　今回、使ったのもこちらです。

　GoogleとAdobeが開発したとか。

　ダウンロードは
　　こちらからどうぞ。
　　　[ITnabiさんnote“Advanced Data Analysis（旧Code Interpreter）で暗号解読とか色々試してみた”](https://note.com/it_navi/n/n6cf8dd967fb2)

　こちらの記事の
　　“２．グラフの日本語表示の改善”で
　　　ダウンロードリンクが
　　　　示されています。
***
　ダウンロードしたら
　　その使い方です。

　❶フォントをアップロード
　❷以下を入力・送信
```Text:
以降、CodeInterpreterで使うフォントはこのNotoSansJP.ttfを使用してください。
```
　❸あとはふつうにPromptを入力

　これだけです。

　注意点は
　　テキストを日本語にするくらい
　　　でしょうか？

　ほかにもありました。

　以前の記事に
　　単語単位で出す
　　　アニメGIF作成が
　　　　ありました。
[【ChatGPT＋Code Interpreter】で文章をワード単位で出すアニメGIFです。](https://qiita.com/kabumira/items/4722a681d07061ce2115)

　これのテキストを
　　単純に日本語文章を
　　　書き入れて、実行しても
　　　　動きません。

　これは
　　英語と違い、
　　　単語を区切るコードが
　　　　違うためです。
　　　　　Code Interpreterは
　　　　　　英語圏のものですからね😅

　同様の処理をさせるには
　　区切る処理を入れねばなりません。
　　　結構大変です。

　代わりに
　　日本語文章に
　　　スペース（半角全角）を入れて
　　　　分かち書きします。

　これで
　　同様の処理が
　　　行なえます。


　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
「いいね」を押すと世界が救われる（かもしれない）

## :beginner:はじめに
Qiitaには日夜専門的で高レベルな記事が次々と投稿されています。
その中で新参者や初心者が記事を投稿してもすぐに埋もれてしまい
「いいね :heartbeat:」が0件のまま世間から忘れ去られる…これが現実です。

:boy_tone1:『専門的な投稿は出来ないけど「いいね:heartbeat:」欲しい』
:boy_tone1:『すごい人から「いいね:heartbeat:」で応援してほしい』

と思う方は少なくないと思います。
この記事を見て「いいね」の敷居がちょっとだけでも下がれば幸いです:pray:

## そもそも「いいね」の定義は？
https://help.qiita.com/ja/articles/qiita-like

>記事やコメントを読んで「いい！」「技術的に役立った」と思った時や、書いた人を「応援したい」という気持ちを表現できる機能で、Contribution の算出にも用いられています。

みなさんはどんな時に「いいね:heartbeat:」をポチッと押しますか？
おそらくこういった時に押すのではないでしょうか？
- 最先端の記事だ:bangbang:
- 勉強になった:bangbang:
- 業務で使えそう:bangbang:

公式にも記載の通り なんとな～く **いい** と思ったり 
**応援したい** と思った時でも「いいね:heartbeat:」してよいのです！

## 自分用（...でもホントは「いいね」欲しい）

> ・備忘録として投稿します
> ・理解度向上のためにoutputします
> ・自分用

こういった記事をよく見かけますが、これは**嘘**です:skull:
本当は他の人に見てもらって「いいね:heartbeat:」が欲しいのです。
「いいね:heartbeat:」が欲しいからパブリックな場所に投稿をしているのです。
人はみな、承認欲求の塊なのです。

## :mega: 「いいね」をもっと気軽に
私は、もっと気軽に「いいね」してもよいと思います。
マッチングアプリの「いいね」は一定以上有料ですがQiitaは何個つけても無料です。

えー大事なことなのでもう一度言いますね

**マッチングアプリ:couple:の「いいね」は一定以上<font color="red">有料</font>ですが
Qiitaは何個つけても<font color="blue">無料</font>です:bangbang:**


## 私の 推し「いいね」:one: 初回クーポン押し
qiitaの世界に飛び込んで右も左も投稿の仕方さえもわからない状態で
自分なりにつたない表現でもなんとか情報を発信した「初回投稿:beginner:」

みなさんも初めての投稿した後、「いいね:heartbeat:」待ちしませんでしたか？
来る日も来る日も「いいね」が付かず枕を涙で濡らしましたよね:sob:？

『qiitaへようこそ:thumbsup:これから頑張っていきましょう』という意味を込めて私は初回投稿の方には「いいね」を押しております。


## 私の 推し「いいね」:two: おぉ！心の友よ！押し
- 自分と同じ問題や悩みに関する投稿
- 自分と同じ目標や試験勉強についての投稿
- 「いいね:heartbeat:」が付かずともコンスタントに続けている投稿

「応援いいね」というよりかは「共感いいね」になっておりますが、同じ志、
同じ境遇の方とは『お互い頑張りましょう:muscle:』という意味を込めて「いいね:heartbeat:」します

## 私の 推し「いいね」:three: チェーンいいね！押し
みなさん昔流行った「呪いのチェーンメール:ghost:」ってご存じですか？

:::note warn
このメールを見た人は呪われています。
呪いを解くためにはこのメールを5人に送信してください。
:::
これが来て焦ってどんどん拡散されていくというやつですね。
この原理で自分に「いいね:heartbeat:」が付いたら誰かの記事に5つ
「いいね:heartbeat:」をつけようと心がけています。もちろん適当につけるのではなく、
素晴らしい記事はもちろん応援したい投稿等を探してつけるようにしております。


## :bell:「いいね」するにはログインが必要
基本的に投稿はせず「見る専用」でしか使ってない方もいらっしゃると思われます。
ログインすると「いいね」だけでなくストック（あとで読む）も使えますので便利ですよ:point_up:
X(旧twitter)でもgoogleでも簡単にログインできますので、是非ログインして「いいね」してみましょう:point_up_2:


## :ramen: 締め
「いいね」がただのクリックではなく、日常のスパイスとなることで、
あなたも投稿者も人生にちょっとした楽しさが生まれるかもしれません:yum:
いや、**実際には巡り巡って世界が救われるかもしれません**:tada:
Font Awesome アイコンが表示されなくなったら真っ先に確認すること

数年前に初版を納品させていただいた業界向けWebアプリがリスティング広告に載ったことで、アクセスが急激に増えて月間PVが１万を超えました。
それは喜ばしい出来事ですが、Font Awesome 無料プランの上限に引っ掛かってしまいアイコンが表示されなくなりました。

状況を確認するため、Font Awesome にサインインします。

https://fontawesome.com/sessions/sign-in

「今月はページビューの許容量を超えています」と警告が出ていますね。
無料プランは月間10,000ページビューまでであり、翌月1日にリセットされるとも書かれています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236222/a3381b31-9dd8-85e5-6509-49a55f1296a1.png)

Font Awesome は３通りの使い方があります。

1. アカウントを登録し、kit を作成する
2. 公開されているCDN（コンテンツデリバリーネットワーク）を参照する
3. ダウンロードし、サーバ内にファイルを配置する

お客様とも相談し、今回は kit に課金せず、ダウンロードして使うことにしました。
Amazon Bedrockの新機能「Prompt Flows」Lambdaノードを使ってみた

# はじめに
今回はAmazon Bedrockの新機能「Prompt Flows」のLambdaノードを使って、ユーザーから入力を受け取り、それをLambda関数で処理し、結果を返すシンプルなアプリケーションを作成してみました。
作成してみて分かったことも共有します。

「Prompt Flows」は、ノードを配置して生成AIのワークフローを開発・管理できるサービスです。

https://aws.amazon.com/jp/bedrock/prompt-flows/

# 導入
アプリケーションの全体像は以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/b2b1ae34-3da9-a237-c134-3d8933937439.png)

**①文字列の入力**
**②Lambda関数での処理**
**③処理結果の出力**
という流れになっています。

**①文字列の入力**
Flow inputでは、文字列を入力してもらいます。
後ほど記述しますが、今回はどのような文字列を入力しても同じ応答を返すようになっています。


**②Lambda関数での処理**
・Lambda側の処理
今回Lambdaを使うにあたって、以下のサイトを参考にしました。

https://zenn-dev.translate.goog/nakam_aws/articles/46fcc003855aef?_x_tr_sl=ja&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=sc&_x_tr_hist=true

「関数の作成」では、以下のような設定で関数を作成しました。

![Lambda1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/7c2f8b5c-5b94-e7d6-ca49-dfd9cd710415.png)

今回Prompt Flows側でLambda関数を呼び出す際に、アクセスが拒否されたエラーに苦戦しましたが、以下のサイト通りにやれば実行できました。

手順としては、
関数
↓
設定
↓
リソースベースのポリシーステートメント
↓
アクセス権限を追加
↓
AWSのサービス
↓
Otherを選択
↓
ステートメントIDを入力
↓
bedrock.amazonaws.comをプリンシパルに入力
↓
ARNを入力
↓
アクションでlambda:InvokeFunctionを選択
↓
保存
となっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/7af9b8da-454d-c82c-1468-6304c2ca3d37.png)


https://repost.aws/questions/QUXk7QWdzGTh-c5MIWch9NNQ/error-when-bedrock-agent-invoke-lambda


コードは以下のようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/56295b43-c6fb-1b46-2409-1d7b6abcbfd4.png)

```
import json

def lambda_handler(event, context):
    # TODO implement
    return json.dumps({
        'statusCode': 200,
        'body': 'Hello from Lambda!'
    })
```

今回の関数では、event(入力)パラメータは関数内で使用されていないため、どのような入力が与えられても常に以下のJSON文字列が返されます。
{"statusCode": 200, "body": "Hello from Lambda!"}


・Prompt Flows側の処理
Lambda関数を呼び出します。
Lambda functionでは、自分が呼び出したい関数を選びます。
Versionでは、$LATESTを選択します。

![Lambda2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/5b1b18ed-f565-a055-3b4f-dc209ad26d45.png)

Inputでは、Lambda関数でのevent(入力部分)で送信する入力を定義します。
Outputでは、処理結果を指定されたデータ型で返します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/b7e78503-42d1-a75e-e8d3-8a8e4d28d710.png)

**③処理結果の出力**
**②Lambda関数での処理**でおこなった処理の結果を出力します。


# 実行結果
どんな文字を入力しても、常に以下のJSON文字列が返されることを確認できます。
{"statusCode": 200, "body": "Hello from Lambda!"}
これによって、Lambda関数が正常に呼び出されることを確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/0aba49ed-9bbd-8e08-f6f2-e4088b4b1bdf.png)


# まとめ
今回は「Prompt Flows」のLambdaノードを使って、ユーザーから入力を受け取り、それをLambda関数で処理し、結果を返すシンプルなアプリケーションを作成してみました。
今後はもっと発展した内容の例を作成したいと考えています。
Djangoでtransタグで囲った部分がTemplateSyntaxErrorになる

# Djangoでtransタグで囲ったのにTemplateSyntaxErrorになる原因

こんなエラーが出た
```
'trans'. Did you forget to register or load this tag?
```

それは以下のコードをテンプレートに書き込んでいないのが原因だったから

```
{% load i18n %}
```

参考になれたら嬉しいです。
宅配ボックスに荷物がはいったかどうかを、LINEに通知するセンサーを実運用してみた

## はじめに

最近、ネットショッピングの利用が増え、自宅の宅配ボックスを活用する機会が多くなりました。しかし、いつ荷物が届いたのかをリアルタイムで知るために、何か工夫ができないかと考えました。そこで、宅配ボックスに荷物が入ったかどうかを検知し、LINEに通知するセンサーを自作して実運用してみました。本記事では、その作成過程や実運用での工夫について紹介します。

## 使用した部品

* Atom S3 Lite
Wi-Fi搭載のマイコンで、小型かつ低消費電力。
* HC-ST04 超音波センサー
安価で距離を測定するために使用。これを使って、宅配ボックス内に物があるかどうかを検知します。
* [ケーブルグランド](https://www.amazon.co.jp/gp/product/B07H261SQY/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1)
* [タカチの防水ボックス](https://www.amazon.co.jp/dp/B07BD6BH26?ref=ppx_yo2ov_dt_b_fed_asin_title)

## 回路
以下に、センサーの接続方法を示す概略の回路図を載せます。
HC-SR04を接続してレベル変換しただけです。

![circuit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215525/e0309c61-c6bc-b7e0-f76e-9f41a299eeb9.png)

![IMG_1590.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215525/1afb7506-c339-b941-5061-b0fe5a7cb027.jpeg)

電源は偶然にも門扉に設置していた電灯から１２Vが取得出来たため、それを利用しています。

## ソフトウェア
ソースコードはGitHubで公開しています。詳しいコードについては、こちらを参照してください。

https://github.com/imoted/deliveryBoxMonitor

## 実際の設置
設置の際には、防水対策や見た目をすっきりさせるためのケーブルの引き回しが特に大変でした。以下の写真は、実際の設置時の様子です。

### 宅配ボックス内部

超音波センサーを宅配ボックスの天井に設置しています。荷物が入ると距離が変化し、それを検知します。

![IMG_1649.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215525/6fefa12f-1d63-1e11-9ece-48b76a814efa.jpeg)

### 防水対策とケーブル処理

屋外で使用するため、防水ボックスにマイコンや電源を収納しました。ケーブルの配線も外部から見えにくくなるように工夫しています。

## まとめ

このプロジェクトでは、宅配ボックスに荷物が入ったことをリアルタイムでLINEに通知するシステムを作成し、実際に運用しています。設置時には防水や見た目を重視した配線処理に苦労しましたが、便利なシステムが完成しました。興味がある方は、ぜひ試してみてください。
Sourcetrail


# 参考にした記事 (これ以上のことはしていません！)

https://tracpath.com/works/development/sourcetrail/

# 実施したこと

1. sourcetrailをPCにインストール
2. VSCodeにプラグインを追加
3. VSCodeでsourcetrail プラグインの設定
3.1 settings.jsonを開く (Ctrl + ,)
3.2 Extensions -> Sourcetrail Configurations
3.3 enable "Start Server At Startup"
4. VSCode上でサンプル用ファイル "main.cpp" "Sample.h"を作成

```
#include "sample.h"
#include 

using namespace std;
using namespace sample;

int main()
{
    Member m;
    
    m.registration( 20 );
}

void Member::registration(int Age)
{
    age = Age;
    std::cout << "registered Age:" << age;
}
```

```
namespace sample
{
    class Member
    {
    private:
        int age;
    public:
        void registration( int Age );
    };
}
```

5. VSCode上でサンプル用ファイル "main.cpp" "Sample.h"がおかれたフォルダを開く
6. プロジェクトの作成
6.1 (VSCodeではなく) スタートメニューからsourcetrailを起動
6.2 プロジェクトの作成 (プロジェクト名、プロジェクトの保存フォルダ、言語、解析するコードのフォルダ)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600486/f872c8dd-fdf1-6842-0ee1-be9029e8b364.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600486/71152580-586f-b6f8-b450-62902628cb33.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600486/e170a159-a362-35f0-237c-d3d378846526.png)


7. VSCodeとの連携
7.1 VSCodeからmain.cppを開き、registrationメソッドを選択し右クリック。Sourcetrail Send Locationをクリック
本来はsourcetrail上でregistrationに関する解析結果が出るはずだが、自分の環境では"Sourcetrail - Cant send message: is sourcetrail running?" のエラーが出る

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600486/2c778c53-652f-2725-77d8-18f18674775a.png)

7.2 sourcetrail上からコードを見つけて"registration"メソッドの解析結果を見ることはできた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600486/b8bc08e6-c3be-fe5f-1c55-1aabaa677d0b.png)


## pythonの場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600486/4e7ccae5-caed-4e84-5df9-2d5df7a4a438.png)
SSMパラメータの一覧と値を取得する方法


### Nameの一覧を取得する
describe-parametesで一覧を取得してjqでNameを出力
```shell
REGION=ap-northeast-1
aws ssm describe-parameters --region $REGION | jq -r '.Parameters.[].Name'
```
結果
```
/parameter/name1
/parameter/name2
/parameter/name3
```


### Nameと値を取得する
```shell
REGION=ap-northeast-1
for parameter in $(aws ssm describe-parameters --region $REGION | jq -r '.Parameters.[].Name'); do 
aws ssm get-parameter --name $parameter --region $REGION | jq -r '.Parameter | [.Name,.Type,.Value] | @csv'
done;
```

結果
```
"/parameter/name1","String","value1"
"/parameter/name2","String","value2"
"/parameter/name3","String","value3"
```
Amazon ECSについて勉強してみた

## 前提
- SAA-C03合格済み！
- 合格までの道のりは[こちら](https://qiita.com/ryotabaske13/items/e81e61e98235aa284933)を参照してみてください
- 普段の業務ではLambdaを使ってサーバーレスアプリケーションを開発
- SAA合格はしたけど、知識定着のために定期的に記事を書くことにしました
- ECSについて勉強したのでまとめてみる

## ECSとは
- AWSが提供するコンテナオーケストレーションサービス
- コンテナを管理する
- コンテナ化されたアプリケーションを簡単にデプロイ、管理、スケールするのに役立つ

## そもそもコンテナとは？
- 業務ではサーバーレスアプリケーションを開発しているので、コンテナに馴染みがない...
- まずはそこから調べてみる

### コンテナとは
- アプリケーションを実行するための環境をパッケージにしたものです
  - アプリケーションを実行するための設定ファイル
  - ライブラリ
  - ランタイム
- などをパッケージとしてひとまとめにしているもの
### コンテナの特徴・メリット
#### ①環境の一貫性
- 「どの環境でも同じように動く」
- アプリケーションに必要なものがパッケージにまとまっているので、「開発環境で実現できた→同じパッケージを使って本番環境も動かせる！」ということが可能

#### ②負荷分散
- 複数のコンテナを追加することで、アプリケーションを拡張できる
- アクセスが増加して負荷がかかった時、コンテナを追加するとその分パフォーマンスを担保できる

#### ③開発効率が上がる
- コンテナ化することで、特定の環境へのデプロイを素早く行うことができる

**再確認すると、ECSとはAWSが提供しているコンテナを構築・管理するためのサービス**
**複数のコンテナがあるということはその分、管理対象のコンテナが増えるということ。それを管理してくれるのが「ECS」**

## ECSの関連機能

![スクリーンショット 2024-08-28 10.29.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730913/c98defb5-045c-c418-e97e-7dd2fd4c85f4.png)

### クラスター
- サービスとタスクを実行する基盤
- 利用するインフラを決める(EC2,Fargate,オンプレミスサーバー)

### サービス
- クラスター内で実行されているタスクを管理する
- タスクの実行数や起動タイプ(EC2,Fargate)を決める

### タスク
- 起動するコンテナの集まり
- アプリケーションを実行する単位
- タスク定義に基づいて起動する

### タスク定義
- タスクを構成するコンテナの定義・テンプレート
- アプリケーションを実行する1つ以上のコンテナを定義している
- JSON形式で定義される

| 設定項目 | 内容 |
| -- | -- |
| ファミリー名 | タスク定義の名前 |
| コンテナ定義 | 起動するコンテナに関する定義 |
| 起動タイプ | Fargate、EC2、オンプレミスなどの外部 |
| タスクサイズ | タスクが使用するCPU、メモリサイズを指定 |
| ネットワークモード | default、bridge、Host、awsvpc、None |
| タスク実行ロール | タスクを起動する際に必要となる権限を設定したロール |
| タスクロール | アプリケーション**から**実行するのに必要な権限を設定したロール |

- 詳細なタスク定義項目は[こちら](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_definitions.html)を確認してください

## FargateとECS on EC2
- ECS起動タイプでは、タスクを実行できる容量を定義します
- FargateとEC2、外部サービスを指定できます

### Fargate
- サーバーレス
- サーバーの管理をする必要がなく、アプリケーションの構築に集中できる
- 容量のスケールアウトもやってくれるため、トラフィックの急増を心配する必要がない
- 運用が楽で大規模なワークロード、時折バーストが発生する小さなワークロード、バッチワークロードなどに向いている

### EC2
- EC2インスタンスを使用してコンテナを実行する
- インスタンスを管理する必要がある
- アプリケーションのニーズに合わせて、CPUやメモリ設定を自由に設定できる
- 高度なカスタマイズが必要なワークロード、長期間の利用が前提で料金を最適化する必要がある大規模なワークロードに向いている

### 外部
- ECSでコンテナ化したアプリケーションを、オンプレミスサーバー、仮想マシンで実行するために使用される
## 参考にした記事
- https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/Welcome.html
- https://envader.plus/article/180
- https://qiita.com/K5K/items/0d8dbdb39fbb0375e2bd
- https://zenn.dev/issy/articles/zenn-ecs-overview
- https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/launch_types.html
CTE: ファイルへの不正アクセスの検出（監査ログの確認）をためす

# 概要

これまでのCTEのご紹介記事でファイルシステムレベル暗号のご紹介と、実際の利用手順を解説させていただきました。

- [ファイルシステムレベル暗号化とは？\(CTE機能紹介\)](https://qiita.com/shinyaarai/items/ef4ddaef397a05335cac)
- [CipherTrust Transparent Encryption (CTE)をためす](https://qiita.com/shinyaarai/items/72f3df86d6a5c4a92143)

CTEには、監査ログの機能があり、ファイルシステム上のGuardPointに対してのアクセスを記録することができ、ランサムウェアや、内部不正等による不正なアクセスを検知することが可能です。

# 目的

監査ログの確認方法の概要を理解し、基本的な監査ログの確認方法を試してみます。

# 参照ドキュメント

- [CipherTrust Transparent Encryption Agent](https://thalesdocs.com/ctp/cte-con/cte/latest/)
    - User Guides > CTE Agent for Linux Advanced Configration
        - [Logging](https://thalesdocs.com/ctp/cte-con/cte/latest/user-manuals/lin-adv/lin-adv-logs/index.html)
    - [Additional Resources](https://thalesdocs.com/ctp/cte-con/cte/latest/add-resources/index.html)
        - "Event Log and Messages Guide"参照
- CipherTrust Manager > Administration
    - CipherTrust Manager
        - System Monitoring > [Records](https://thalesdocs.com/ctp/cm/latest/admin/cm_admin/monitoring/records/index.html)
    - CTE Administration
        - [Managing Profiles](https://thalesdocs.com/ctp/cm/latest/admin/cte_ag/profiles/index.html)


# 監査ログ確認の手順

## CTE Agentをインストールしたサーバ側での確認方法
### Windowsの場合

1\. CTE Agent をインストールした Windows Server のタスクトレイ中の “CTE Agent”のアイコンを右クリック
2\. Log > View > File System > Log を選択で、下記のようなCTE Agent 側のログをご確認いただけます。
(C:\ProgramData\Vormetric\DataSecurityExpert\agent\log\vorvmd.log)

![CTE_Audit_log_1_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613085/77e3dd08-3ae8-f26a-70e6-68433f05cfac.png)


### Linuxの場合
/var/log/vormetric/vmd.log 参照

## CM管理画面での確認方法

### Profileの設定

CTE Agent のログを CMへ転送設定や、ログのレベル等、ログの詳細を Profile として管理することができます。

1\. CM管理画面 > "Transparent Encryption" > Settings > Profiles > "DefaultClientProfile"（又は、任意のProfile） > "CLIENT LOGGING CONFIGRATION"　を選択
2.\ "Log Upload to Key Manager" を選択し、"Update"をクリック

![CTE_Audit_log_2_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613085/ebb80273-710b-cd88-efe1-9b61a097c9ca.png)


### ログの確認
CM管理画面 > Records > "Loki Audit Records" > "Client Records" 選択

![CTE_Audit_log_2_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613085/2603e977-b50b-2735-71da-00ebf895bb37.png)


## 補足

CipherTrust Managerのストレージは有限ですので、過去にわたって長期間大量のログを保存することができません。
Syslogサーバや、SEIM製品を用い、ログを転送、保存いただくことをお勧めします。


- CipherTrust Manager > Administration > CipherTrust Manager Administration
    - [Log Forwarding](
https://thalesdocs.com/ctp/cm/latest/admin/cm_admin/monitoring/log-forwarding/index.html)
    - [Integrating Logging with Splunk App](
https://thalesdocs.com/ctp/cm/latest/admin/cm_admin/config-splunk/index.html)
文系人間のCookie学習メモ（一）

こんにちは、法律の単位を少しだけ取得した文系の人間です。 これは1時間cookieを勉強した小さな感想です。

①LocalStorageとSessionStorageの標準は、2009年にW3Cによって発表され、Cookieの一部の用途を置き換えるために作られました。

②各標準の背後には複雑な組織が存在します。これらの標準は法律とは異なり、国家の公権力によって支持されていないにもかかわらず、実際には守られているのがとても興味深いです。

③法律も標準の制定に影響を与えます。例えば、EUのGDPRはコンセント管理（Consent Management）を規定しています。

④逆に、標準が先行し、後に法律に適合する場合もあります。例えば、RFC 6265におけるHttpOnlyとSecureは、GDPRの法的リスクを回避することができます。

⑤技術的な観点に戻ると、初心者はまずCookie、LocalStorage、SessionStorageの基本操作に慣れるべきです。IndexedDBやCache APIはより高度な技術です。

まあとにかく、早く基本的な技術を押さえないとね。この1時間、ほとんどCookieの技術に手をつけられなかった…組織とかお金の流れとか、無駄なことばっかり調べてた自分を反省しないと(｡-_-｡)
M5StackCore2: ホルムアルデヒドセンサー SFA30 を使う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/c09fe958-ae5c-8ad5-6149-d98a9a9d631d.png)

## プログラム

```text:i2c_read.ino
// ---------------------------------------------------------------------
//	i2c_read.ino for M5StackCore2
//
//						Aug/28/2024
// ---------------------------------------------------------------------
#include <SensirionI2CSfa3x.h>
#include <Wire.h>
#define	PROGRAM	"i2c_read.ino"
#define	VERSION	"2024-8-28 AM 10:06"

SensirionI2CSfa3x sfa3x;

// ---------------------------------------------------------------------
void setup() {

	Serial.begin(115200);
	while (!Serial) {
		delay(100);
	}

	Wire.begin();

	uint16_t error;
	char errorMessage[256];

	sfa3x.begin(Wire);

	// Start Measurement
	error = sfa3x.startContinuousMeasurement();
	if (error) {
		Serial.print("Error trying to execute startContinuousMeasurement(): ");
		errorToString(error, errorMessage, 256);
		Serial.println(errorMessage);
	}
}

// ---------------------------------------------------------------------
void loop() {
	uint16_t error;
	char errorMessage[256];

	delay(1000);
	int16_t hcho;
	int16_t humidity;
	int16_t temperature;
	error = sfa3x.readMeasuredValues(hcho, humidity, temperature);
	if (error) {
		Serial.print("Error trying to execute readMeasuredValues(): ");
		errorToString(error, errorMessage, 256);
		Serial.println(errorMessage);
	} else {
		Serial.print("Hcho:");
		Serial.print(hcho / 5.0);
		Serial.print("\t");
		Serial.print("Humidity:");
		Serial.print(humidity / 100.0);
		Serial.print("\t");
		Serial.print("Temperature:");
		Serial.println(temperature / 200.0);
	}
}

// ---------------------------------------------------------------------
```

## Arduino IDE
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/4451fc18-3363-8e06-43dd-b4de478aae7b.png)
モジュールリリースまでに試行錯誤した話

### カタカタカッターン
　今日もクソデカいエンターの打鍵音がオフィスに響く。
ようやくコーディングが終わった。あとはビルドしてテストするだけだ。余計なものがついてこないよう公開ビルドをして……完成だ。

しかし、そのアプリが正常に起動することはなかった――

:::note info
今回の環境：.NET Core8
使用言語：C#
:::

# ビルドエラーは出てないし、どうしたものか

試験者さん「アプリを開いたら落ちます」

　付いては落ちるの繰り返し。
何故だろうと調べてみると、自分の環境が **.NET Core8**だったのに対し、調べた方法が **.NET Framework4.8**だったのだ！ 恐らくアプリケーションを動かすのに必要ななんやらが足りないっぽい。断定はできないが、限りなく怪しい……なんてうっかりさんなんだ。
さて、Core8で調べてはみたが中々上手く行かない。迫る期限。ここは他の策に切り替えた方が良さそうだ……
そこで出てきたのがショートカットを使う方法。なるほど、実行ファイルのショートカットを置いて、実際の実行ファイルはsrcフォルダにまとめてしまえば疑似的な最小ビルドとすることができる。
```
Apps ┬ exeショートカット
     └ src
        ├ hoge.exe
        └ dll等
```
みたいな感じ
よし、さっそくショートカットを作ってzipに圧縮して試験者に送るぞ！

試験者さん「開けません」

そうだ……ショートカットって絶対パスだからそのままコピーしても参照できないんだ……。


# 絶対パスがダメなら相対パスにすればいいじゃない

こちらはちょっと調べてみるとすぐに出てきた。
相対パスとは絶対パスと違って「このショートカットから見たパス」なのでどんな環境でも対応できるはず。

 `` %windir%\explorer.exe "src\hoge.exe" `` こんな感じで

これで参照できるはず！

試験者さん「開けたけどエラー吐きました」

え……なんで……？


# コード内のパスも……

　これもちょっと調べてみればすぐにわかる原因だった。
ショートカットを作ったことによる不具合、つまり参照先が見つからないとかが原因だろう。そういえばディレクトリ参照のコードを書いた気が……

```
Apps - exeショートカット
     ├ setting
     └ src
        ├ hoge.exe
        └ dll等
```

　そう、設定ファイルの存在を忘れていたのだ。設定ファイルのパスは **自分から見た**相対位置になっているので、このショートカットを使うとexplorer.exeからの位置になってしまうのだ。つまりこれを **実行ファイルから見た**相対位置に直さなければならない。
なにそれどうやるの……？
そうだ、カレントディレクトリを取得すれば……いや、今ここはexplorer.exeになっているので結局同じことだ。

途方に暮れてる中教えてもらった関数は
``AppContext.BaseDirectory``
これを現在位置として代入して
`string path = $"{current}..\\setting.json"`

こうしてようやくまともに動くようになったのである――

# 結論
　絶対パスと相対パスはさすがに知っていたが、それがこんな不具合を招くとは想像していなかった。相対パスは場合によって始点が変わってしまうので、こちらから指示してあげる必要があったのだ。
~~最初からFramework4.8の方が良かったのでは……？~~
あきらめなければ方法は見つかるものである。頑張ろう。
Xserver StaticでCORSを有効化【Header set Access-Control-Allow-Origin】

外部サイトからエラーなく画像などが読み込めます

```apache:.htaccess
Header set Access-Control-Allow-Origin "*"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/2509a810-7287-f14f-aedd-c27255d7f884.png)
[Swift]RxSwift　TextFildで入力した文字をリアルタイムで表示させる

# RxSwiftのbindメソッドを利用した実装
今回は簡単なRxSwiftの実装を行います。
初歩中の初歩ですがbindメソッドを利用して、TextFildで入力した文字をリアルタイムで表示させる実装を行います。


今回の完成イメージです。 
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1789173/22901f56-04cb-d08e-e76d-ce1afba7b5fe.png" width="300" />

## 実装コード

使用したのは
Label ✕ 1
TextFild ✕ 1
文字を入力したら、その入力した文字データが反映されるシンプルなコードです。

```Swift:

import UIKit
import RxSwift
import RxCocoa

final class ViewController: UIViewController {
    
    @IBOutlet private weak var nameTextFild: UITextField!
    @IBOutlet private weak var nameLabel: UILabel!
    private let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        bind()
    }
}

extension ViewController {
    func bind() {
        nameTextFild.rx.text
            .bind(to: nameLabel.rx.text)
            .disposed(by: disposeBag)
    }
}
```

bindは双方向のデータバインディングを想像するが、RxSwiftの場合は単方向のデータバインディングです。
振る舞いはsubscribeとほぼ同様で値をセットすることと同じです。
```Swift:
// 上の実装のbind部分はこれでも対応可能です。
nameTextFild.rx.text
    .subscribe(onNext: { [weak self] text in
        self?.nameLabel.text = text
    })
    .disposed(by: disposeBag)
```

しかしbindにすると少しスッキリ実装できシンプルでいいと感じました。

## まとめ
RxSwiftは難しいです。少しずつRxSwiftの知識を増やして行きます。
M5Stack Core2: i2c のスキャン

## プログラム

```text:i2c_scanner.ino
// ---------------------------------------------------------------------
//	i2c_scanner.ino for M5StackCore2
//
//						Aug/28/2024
// ---------------------------------------------------------------------
#include <Wire.h>
#define	PROGRAM	"i2c_scanner.ino"
#define	VERSION	"2024-8-28 AM 09:59"

// ---------------------------------------------------------------------
void setup()
{
	Wire.begin();
	Serial.begin(115200);
	delay(1000);
	Serial.println(PROGRAM);
	Serial.println(VERSION);
	Serial.println();
	delay(1000);
	Serial.println(PROGRAM);
	Serial.println(VERSION);
	delay(1000);
	Serial.println("*** setup end ***");
}

// ---------------------------------------------------------------------
void loop()
{
	byte error, address;
	int nDevices;

	Serial.println("Scanning...");

	nDevices = 0;
	for(address = 1; address < 127; address++ ) 
	{
		// The i2c_scanner uses the return value of
		// the Write.endTransmisstion to see if
		// a device did acknowledge to the address.
		Wire.beginTransmission(address);
		error = Wire.endTransmission();

		if (error == 0)
		{
			Serial.print("I2C device found at address 0x");
			if (address<16) 
				Serial.print("0");
			Serial.print(address,HEX);
			Serial.println("	!");

			nDevices++;
		}
		else if (error==4) 
		{
			Serial.print("Unknown error at address 0x");
			if (address<16) 
				Serial.print("0");
			Serial.println(address,HEX);
		}		
	}
	if (nDevices == 0)
		Serial.println("No I2C devices found\n");
	else
		{
		Serial.print("done   ");
		Serial.print("nDevices = ");
		Serial.println(nDevices);
		}

	delay(10000);
}

// ---------------------------------------------------------------------
```

## Arduino IDE
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/f635181c-50f4-261a-c9da-c5bd3babb0eb.png)