OmniAICreator/Qiita-1.07M huggingface dataset:
Terraformモジュールの相対パス指定方法について

Terraform でモジュールを参照する際の相対パスの指定方法について、よくあるケースと注意点を説明します。

## 同じディレクトリ階層のモジュールを参照する場合

以下のような構成で`modules/random_str` に `random_string` リソースを含むモジュールがあるとします：

```hcl:modules/random_str/main.tf
resource "random_string" "random" {
  length           = 16
  special          = true
  override_special = "/@£$"
}
```

このモジュールをルートディレクトリの `main.tf` から参照する場合は、以下のように記述します：

```hcl:main.tf
module "test" {
  source = "./modules/random_str"
}
```

### 重要な注意点

パスの指定には必ず `./`から始める必要があります。
`source = "modules/random_str"` のように `./` を省略すると、以下のようなエラーが発生します：

```
╷
│ Error: Invalid module source address
│
│   on main.tf line 2, in module "test":
│    2:   source = "modules/random_str"
│
│ Terraform failed to determine your intended installation method for remote module package "modules/random_str".
│
│ If you intended this as a path relative to the current module, use "./modules/random_str" instead. The "./" prefix indicates that the address is a relative filesystem path.
╵
```

## 異なるディレクトリ階層からモジュールを参照する場合

例えば `environments/development` ディレクトリから、上記の `modules/random_str` を参照する場合は、共通の親ディレクトリまで `../` で遡って指定します：

```hcl:environments/development/main.tf
module "test" {
  source = "../../modules/random_str"
}
```

### ディレクトリ構成例

参考までに、上記の例で想定しているディレクトリ構成は以下のようになります：

```
├── modules
│   └── random_str
│       └── main.tf
└── environments
    └── development
        └── main.tf
```

このように構造化することで、環境ごとの設定とモジュールの再利用が容易になります。
RaspberryPiで画像生成AIにチャレンジ（FastSDCPU編）

手軽に画像生成AIを試す方法がないか探していたらCPUだけでも動作する[FastSDCPU](https://github.com/rupeshs/fastsdcpu)という環境を見つけました。

特徴は

・GPUがない環境でも動作する。
・様々なプラットフォームに対応（Windows,Mac,Linux,Android等）
・GUIアプリ、WebUI、APIサーバに対応。
・インストールが簡単。（筆者の主観です。）

RaspberryPi4での動作実績もあるのでRaspberryPi5,RaspberryPi4,RaspberryPi Zero2にインストールしてみました。
インストールの手順はすべて同じです。

## 動作環境
・16GB以上MicroSDカード
・Raspberry Pi OS with desktop bookworm 2024/07/04
・Python 3.11.2

## インストール手順
Pythonの仮想環境を準備します。
```
$ python -m venv fastsdcpu
$ cd fastsdcpu
$ source ./bin/activate
```
続いてGithubからFastSD CPUをクローンします。
```
$ git clone https://github.com/rupeshs/fastsdcpu.git
```
ディレクトリを移動して一部のスクリプトに実行権限を設定します。
```
$ cd fastsdcpu
$ chmod +x install.sh start-webui.sh
```
インストールスクリプトを実行します。RPiではQT5のインストールに失敗するので、GUIアプリは使用しないようにします。
```
$ ./install.sh --disable-gui
```
![fastsdcpu01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/76a6b9bb-e1fd-313e-2c4a-29a755a7d237.png)


これでインストールは完了です。

## 実行
GUIアプリは動作しないので、WebUI用のスクリプトを実行します。
```
$ ./start-webui.sh
```
次のようになれば起動が完了しています。
![fastsdcpu02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/0e3ac66b-9635-d17c-9d16-81cf990c7e56.png)

RPiのブラウザを起動して http://127.0.0.1:7860/ にアクセスします。
![fastsdcpu03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/07f8d041-ecce-89c3-cfce-986b54a11546.png)

Genarateボタンの左側テキストボックスにプロンプトを入力して、Genarateボタンをクリックすると画像の生成が始まります。
初回はモデルのダウンロードをあるため時間がかかります。2回目以降はRPi4で約10分ほどで生成されました。
![fastsdcpu04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/92e6e2e4-6666-cf2b-8ecb-f871d8b5a060.png)

RaspberryPiZero2でもインストールは出来ました。ただブラウザが動作しないため使えるのはAPIサーバだけとなります。まぁ動作しても生成に5時間以上かかるので使い道はほとんどないのですが・・・

レポジトリ内にはWindows用インストールバッチファイル、Mac用インストールスクリプトがありますのでPythonのバージョンを3.10か3.11にしておけば簡単にインストールできます。Intel CPUだとOpenVINOも使えるのでより速く画像を生成できるようです。
Reactで子コンポーネントにPropsを渡すときに｛｝を使う理由

## はじめに
Reactを使っているときによく関数コンポーネントの引数をブロック（{}）にせずエラーが出がちでした。
そもそもなんでここでブロックを使用しているかを理解したらエラーも減るのでは？と思い調べてみました。

## ブロックの理由

### 前提：分割代入
```js
const obj = { name: 'John', age: 30 };

// オブジェクトの分割代入
const { name, age } = obj;

console.log(name); // 'John'
console.log(age);  // 30
```
上記のような代入方法を分割代入というそうです。

`const { name, age } = obj;`
の箇所についてはオブジェクトのキーを指定します。

ちなみに、キー以外を指定するとundefinedになります。

```js
const obj = { name: 'John', age: 30 };

// 正しいプロパティ名を使った場合
const { name, age } = obj;

console.log(name); // 'John'
console.log(age);  // 30

// 存在しないプロパティ名を使った場合
const { a, b } = obj;

console.log(a); // undefined
console.log(b); // undefined
```

### ブロックを使わないpropsの受け渡し
propsを受け渡す際に、ブロックを使わない方法も有るようです。
こちらをベースに考えたほうがわかりやすそうなので記載します。

```tsx
// props の型定義
type UserProfileProps = {
  name: string;
  age: number;
};

const userProfile: React.FC<UserProfileProps> = (props) => {
  return (
    <div>
      <h1>{props.name}</h1>
      <p>年齢: {props.age}</p>
    </div>
  );
};

// 使用例
const App = () => {
  return <userProfile name="John" age={30} />;
};
```
上記のようにこれだと{props.name}のように、
コードが冗長になりやすいのであまり使われていないようです。

### ブロックを使ったPropsの受け渡し
最後によくみるブロックを使ったPropsの受け渡し例です。

```tsx
// props の型定義
type UserProfileProps = {
  name: string;
  age: number;
};

const userProfile: React.FC<UserProfileProps> = ({ name, age }) => {
  return (
    <div>
      <h1>{name}</h1>
      <p>年齢: {age}</p>
    </div>
  );
};

// 使用例
const App = () => {
  return <userProfile name="John" age={30} />;
};
```
ここまで来たらなんとなくわかるかと思うのですが、
Propsオブジェクトの中身を分割代入の仕組みを使って取り出しています。
この場合Propsオブジェクトは以下のようになっています。
```js
UserProps = {
  name: "John",
  age: 30,
}
```

上記のオブジェクトからnameキーに該当するvalueであるところの"John"と
ageキーに該当するvalueであるところの30を、name,ageに代入している
という感じです。

### 補足
`UserProps`はいつ作られるねんとおもったのですが、
`return <userProfile name="John" age={30} />;`
↑の記述をもとに、コンポーネントがレンダリングされるタイミングでReactによって自動的に作成される仕様になっているようです。

## おわりに
React使う上でもJavaScriptの基礎はちゃんと抑えておく必要が有ることを再確認しました。
これでエラーが減ることを願って…
超初心者向けSQLノート(SELECT編)

僕のように0からSQLを使う人向けに記載していく。
実際は自分用の辞書として用いる予定だが、初心者が読んで有用であるよう心がけて作成するよう心がけている。

# はじめに：超役に立つサイト
https://sqlab.net/

経験則から、おそらくガンガン実践しながらわからない部分を検索 or youtubeの動画で補充していくのが最も効率が良いので、上記のサイトが有用。問題数が少ないのが難点だが、初心者がやるには十分そう。
これで問題解きながら色々実験していく。問題外のことも試してみると◎

# ベーシック
SELECT variable
FROM table_name

#### 条件の指定
SELECT variable
FROM table_name
**WHERE** variable = value

#### 空欄の指定方法
SELECT variable
FROM table_name
WHERE variable **IS NULL**

#### 昇順並び替え
SELECT variable
FROM table_name
**ORDER BY** <column>;

#### 降順並び替え
...(同上)
ORDER BY <column> **DESC**

#### 複数指定も可能
....
**ORDER BY mogumogu ASC, hamuhamu DESC**　みたいな。


# JOIN 系　
https://wa3.i-3-i.info/word1262.html

↑とても参考になるサイト。JOINについて解説している 

#### INNER JOIN
*条件をもとに、テーブルとテーブルを合体する*
>2つのテーブルの合体可能なデータのみを抜き出して合体させるやり方が「内部結合」です。

テーブル1:名前、性別　テーブル2:名前、年齢が入っているとする。
どちらにもデータが入っている人について、名前、性別、年齢を表示させる２は以下のようにINNER JOINする。

SELECT
  table1.【名前】,
  table1.【性別】,
  table2.【年齢】
FROM
　table1
INNER JOIN
　table2
ON
　table1.【名前】 = table2.【名前】


 ONにて名前が一致するという条件を指定した上でtable1にtable2をINNER JOINしている。

# COUNT系
文字通りカウントする。括弧の中に*を入れたり数字(1,2など)を入れる用法があるらしい。後々追記。

https://techmania.jp/blog/sql-count/

#### 基本的な用法
SELECT COUNT ()
FROM table

COUNT()ですべてのrowをカウントする。これを引数として扱うこともできる。

例)
SELECT  category_id,
COUNT ()
FROM book_categories
GROUP BY category_id 
**ORDER BY COUNT() DESC**

# GROUP BY

https://www.youtube.com/watch?v=x2_mOJ3skSc

データを分類して表示。（グループ化）
例えば「スーパーの商品」テーブルに全商品の品名とそのジャンルがあったとする。
ジャンルごとに表示したければGROUP BYだし、そのジャンルの商品の個数を出すのもGROUP BYらしい。



# 細々としたメモ

#### stringを引数として扱う方法
引数としてstringを扱う際は、''で挟む。例は以下の通り。

SELECT  *
FROM books
WHERE name = 'ココア'

#### 処理の順序について

GROUP BYは最後になされなければならず、GROUP BYの後にJOINすることはできない。

#### コメントアウトの方法
-- または/*によってコメントアウトできる。
AWS EC2とLambda利用シナリオ「知識整理」 

### AWS EC2とLambdaの比較について、どのシナリオでそれぞれを利用するかを以下に示します。

## AWS EC2の利用シナリオ
■長時間のプロセス:
継続的に稼働するアプリケーションや長時間実行されるバッチ処理。

・具体例: オンラインゲームのサーバー、データ分析ジョブ、長時間実行されるバックグラウンド処理など。
・理由: EC2は常時稼働できるため、長期的なタスクに適しています。サーバーの起動やシャットダウンの時間を考慮する必要がありません。


■カスタム環境が必要な場合:
特定のOSやソフトウェアスタックが必要な場合。例: 特定のライブラリやフレームワークが必要な場合。

・具体例: 特定のデータベースサーバーやアプリケーションサーバー（例: Oracle DBや特定のアプリケーションフレームワーク）。
・理由: EC2インスタンスでは、好きなOSやソフトウェアを自由にインストール・設定できるため、特定の要件に応じた環境を構築できます。

■状態管理:
セッション情報やユーザーデータを保持する必要がある場合。EC2インスタンス上でのデータベースやキャッシュの管理。

・具体例: ユーザーセッションやリアルタイムデータ処理が必要なアプリケーション（例: ECサイトのカート機能）。
・理由: EC2はステートフルなアプリケーションに適しており、セッション情報をインスタンス内に保存できます。

■高いカスタマイズ性:
ハードウェアのリソースを自由に選びたい場合や、特定の設定を行いたい場合。
・具体例: 特定のネットワーク設定やセキュリティ要件（例: カスタムVPC、セキュリティグループ）。
・理由: EC2はインフラを細かく設定できるため、特定のビジネスニーズに合わせた構成が可能です。

## AWS Lambdaの利用シナリオ
■短期間の処理:
短時間で完了するタスクやイベント駆動型の処理（例: HTTPリクエストの処理やデータの変換）。

・具体例: イメージの処理、データの変換、APIリクエストの処理。
・理由: Lambdaは短時間で完了するタスクに最適で、実行後すぐに自動でリソースが解放されます。

■スケーラビリティ:
自動的にスケールアップ・スケールダウンが必要な場合。特に突発的なトラフィックに対応したいとき。

・具体例: 突発的なトラフィックに対応するWebアプリケーションのバックエンド。
・理由: Lambdaはリクエストに応じて自動でスケールし、数千のリクエストを同時に処理できます。

■コスト効率:
利用した分だけ料金が発生するため、トラフィックが不定期な場合や低頻度での実行が求められる場合。

・具体例: 定期的に実行されるバッチ処理やトリガーに基づくタスク。
・理由: Lambdaは実行時間に応じた料金体系で、使用していない時間は料金が発生しません。

■サーバーレスアーキテクチャ:
サーバー管理の手間を省きたい場合。インフラの管理をAWSに任せたいとき。

・具体例: マイクロサービスアーキテクチャの一部として利用されるサービス。
・理由: Lambdaを利用することで、インフラ管理から解放され、コードに集中できるため、開発効率が向上します。

■イベントドリブンな処理:
S3のオブジェクトアップロード、SNS通知、DynamoDBの変更など、イベントに基づいて処理を実行する必要がある場合。

・具体例: S3バケットへのファイルアップロード時に自動で画像をリサイズする処理。
・理由: Lambdaは各種AWSサービスとの連携が容易で、イベントに基づいた処理を簡単に設定できます。
S/4 HANAコンバージョンSUM実行でのあれこれ【SAP BASIS向け】

# 実行前準備

■ソース
SUM解凍(最新版使用を推奨)

SPAMアップグレード(最新化を推奨)

hostagentアップデート

crlbag.p7sアップデート(https://tcs.mysap.com/crl/crlbag.p7s)

不要クライアント削除(T-code:SCC5、001,066等)
    クライアントロールが変更できない場合の変更SQL
>UPDATE sid.T000
SET CCCATEGORY ='T'
WHERE MANDAT = '066'

無効化オブジェクト削除(T-code:SE80)

更新キューの削除(T-code:SM13)

移送依頼のリリース(T-code:SE01)
　基本DMY。移送先(ターゲット)をDMYにしてからリリース。
  SE03からオブジェクトロック解除(expertツール)から強制リリースも可。

ページング設定(メモリサイズx1.2-5程度)

SQLサーバのログモード変更(overwrite)

<パフォーマンス関連>
インスタンスタイプ変更

SAPインスタンスパラメータ変更

SQLサーバパラメータ変更

パフォーマンスモニタリング有効化(windows) or cloudwatch詳細モニタリング有効化等
→メモリ、CPU、IOPSモニタリング

stack.xml修正(※下記以外にもあり)
<caption>SID</caption>
<sid>SID</sid>
<host>hostname</host>

マイグレーションキー取得(OSS)
SAPライセンスインストール(マイグレーションキーと同じインストレーション番号)

■ターゲット
HANA DB移行用パラメータ設定

HANAのログモード変更(overwrite)

インスタンスタイプ変更

SAPインスタンスパラメータ変更

# 実行中
実行中のプロセス数に関して
1616401 - Parallelism in the Upgrades, EhPs and Support Packages implementations

●インスタンスの起動停止
※SPDD作業中でもターゲットDBの起動が必要
ASCS→SHD→PASの起動順
PAS→SHD→ASCSの停止順

SPDD対応
SE06(下記はrestricted modifibablitityのまま)
 SAP_ABA
 SAP_BASIS
 (SAP_HR, SAP_AAPL etc...)

tmpフォルダで処理確認
MAIN_SHDRUN/ACT_UPGなどログの動きが少ないフェーズの処理確認に有効
 
# 実行後
SGEN
C言語でprintf魔改造

こんにちは。kazuです。
今回は授業でprintfを使ったので、魔改造しました。
後でレポートを書くときに忘れないように記事にしてみました。

# ことの発端
授業「複雑なプログラム書いてね！出力は要件を満たしてね！」
ぼく「デバッグ用の出力...」
ぼく「printfの関数名だけ変えてデバッグ出力管理したろ！」
マクロ「君のマクロはあぶないよ！」

...ということでマクロを使わずprintfと同じ使い方ができるデバッグ出力用の関数を作りました。


# コード
```c
#include <stdarg.h>

void debug_printf(const char *format, ...) {
    if(debug_mode){
        // 可変引数を処理するための準備
        va_list args;
        va_start(args, format);

        // デバッグメッセージの前に追加する文字列
        printf("\033[2m[DEBUG] ");

        // vprintfを使用して可変引数に対応する形でフォーマットされた出力を行う
        vprintf(format, args);

        // デバッグメッセージの終わりに追加する文字列
        printf("\033[0m");

        // 可変引数の処理を終了
        va_end(args);
    }
}
```

printfが内部で呼び出しているvprintf関数にformatとargsを渡すことで魔改造に成功しました。
\033[はエスケープシーケンスという最近ハマっているやつで、頑張ればBIOSやraspi-config的なのが作れちゃいます。
今回は\033[2mで文字の色を灰色に設定、最後に\033[0mで白に戻すという使い方をしました。
Paiza D310:タイトルの略称 Rubyで

apple
book
cake

という入力を受け取り、

abc

という出力を行う際のコード

```
# 標準入力から単語を読み込み、最初の文字を連結する
result = []

while line = gets
  result << line[0]  # 各行の最初の文字を取得
end

puts result.join  # 結果を出力
```
配列を宣言、ループ処理で入力を受け取り変数lineに代入、
result<<line[0]にて、配列に受け取ったlineの初めの1文字を取得し、
joinメソッドを使って各配列を連結。
[Node.js]Satoriを用いて動的にOGPを生成する際のtips

## TL;DR

- SatoriによるSVG生成にはフォントファイルの読み込みが必要
- フォントファイルの読み込みはモジュールバンドラーとの相性が良くない
- `vite-plugin-arraybuffer`を利用してインラインでフォントファイルを読み込むことですっきりビルド


## 動的OGP生成の手法

筆者所属のMIERUNEにて最近[QGIS LAB](https://qgis.mierune.co.jp/)というWebサイトをリリースしました。

https://qgis.mierune.co.jp/

このサイトの記事ページでは、記事タイトルから動的にOGP画像を生成しています。

https://qgis.mierune.co.jp/posts/howto_1_download_ksj-data

動的OGPの生成は下記の手順がポピュラーのようです。

1. [vercel/satori](https://github.com/vercel/satori)で、SVGを生成する（JSXによる記述が可能）
2. SVGを画像化（Node.jsなら[lovell/sharp](https://github.com/lovell/sharp)、それ以外だと[yisibi/resvg-js](https://github.com/yisibl/resvg-js)も利用できそうです）

これらの利用方法は以下のWebサイトが詳しいです。

https://azukiazusa.dev/blog/satori-sveltekit-ogp-image/

## satoriにはフォントファイルが必要

satoriはSVG生成時の第二引数でオプションを設定するのですが、そのオプションにはフォントの指定が必須です。フォントデータは`Buffer`型である必要があります。サンプルコードによれば、`fs`や`fetch`で読んできてねと書いてあります。

```tsx
import satori from 'satori'

const svg = await satori(
  <div style={{ color: 'black' }}>hello, world</div>,
  {
    width: 600,
    height: 400,
    fonts: [
      {
        name: 'Roboto',
        // Use `fs` (Node.js only) or `fetch` to read the font as Buffer/ArrayBuffer and provide `data` here.
        data: robotoArrayBuffer,
        weight: 400,
        style: 'normal',
      },
    ],
  },
)
```

動的に作るので、外部からフォントファイルをダウンロードする時間も節約したいので、`fetch`を利用する線はなくなります。

## モジュールバンドラーが介在する場合の問題

`fs`で静的なファイルを読み込むと、以下のようなコードになります。

```javascript
const font = fs.readFileSync('./fonts/NotoSansJP-Regular.otf')
```

このときファイルパスを指定するのですが、このパスはスクリプト実行時点のカレントディレクトリから見た相対パス（あるいは絶対パス）となります。

今回のWebサイトはSvelteKitで構築されているため、ソースコードとビルドアーティファクトのディレクトリ構成は全く異なります（なので相対パスで書きづらい）。また、実行環境に依存したコードもあまり書きたくないので、絶対パスもなるべく利用したくありません。

## 解決策：ビルド時にファイルをインラインに読み込んでしまう

https://github.com/tachibana-shin/vite-plugin-arraybuffer

SvelteKitではビルドにViteを利用するので、Viteのプラグインを利用してフォントファイルを`import`することで、バイナリデータをインラインで持ってしまうという策です。これによりシンプルに解決できて、以下がサンプルコードです。

```tsx
import NotoSansJpBold from './NotoSansJP-Bold.ttf?arraybuffer&base64';
// "?arraybuffer"というsuffixで、vite-plugin-arraybufferがファイルをバンドルしてくれる
// "&base64"により、base64文字列として読まれる（今回の実装では必要だった）

const svg = await satori(
    <div>...</div>,
    {
        width: 1200,
        height: 630,
        fonts: [
            {
                name: 'Noto Sans JP Bold',
                data: NotoSansJpBold
            }
        ]
    }
);

// svg to webp
const buffer = await sharp(Buffer.from(svg)).webp().toBuffer();
return buffer;
```

これをビルドすると以下のようなコードになります。base64文字列がインラインに埋め込まれていることがわかりますね。

```javascript
const NotoSansJpBold = decode64("AAEAAAATAQAABAAw...")
```

## まとめ

- この手を試す前は[sapphi-red/vite-plugin-static-copy](https://github.com/sapphi-red/vite-plugin-static-copy)を用いてビルドアーティファクトにフォントファイルをコピーするような手も試しました。この手でも頑張れば解決は出来ると思いますが、実行環境に依存したコードが増えてポータビリティが低下すると思います（例：今回で言うと、AWS AmplifyとAWS Lambdaで動く必要があった）
- バンドラーにViteを利用しているなら、今回紹介したプラグインが有効なケースは結構あるかもしれません
アジャイル開発手法とは？そのメリットと導入方法

<br>

## ■ はじめに
<br>

**アジャイル開発手法** をご存じでしょうか。
これはソフトウェア開発において柔軟性を高め、チームの効率性を向上させるために生まれた開発手法です。
従来のウォーターフォール開発との違いを理解し、なぜ多くの開発でこのアジャイルを採用しているのか、その理由を紐解いていきましょう。

また、ウォーターフォール開発については以下の記事で解説しておりますので合わせてご覧ください。

https://qiita.com/e-tak/private/9a939f544b1c391dfa6b

## ■ 目次
<br>

1. [アジャイル開発とは？](#1-アジャイル開発とは)
2. [アジャイルを用いるメリット](#2-アジャイルを用いるメリット)
3. [アジャイルを用いた際のデメリット](#3-アジャイルを用いた際のデメリット)
4. [ウォーターフォールとの比較](#4-ウォーターフォールとの比較)
5. [スクラムの概要](#5-スクラムの概要)
6. [まとめ](#6-まとめ)

## 1. アジャイル開発とは？
<br>

アジャイル開発[^1]は、チームが迅速に変化に対応できるよう設計された反復型の開発手法です。
アジャイルマニフェスト[^2]に基づいており、以下の4つの価値観に重点を置いています。

- **対話の重視**
    - プロセスやツールよりも、チームメンバー同士のコミュニケーションを重視

- **動くものを優先**
    - ドキュメントよりも、実際に動作するソフトウェアを優先

- **顧客との協力**
    - 契約交渉よりも、顧客と協力しながらプロジェクトを進行

- **変化への対応**
    - 計画に固執せず、変更に柔軟に対応を行う

上記の価値観を元にしているアジャイル開発は、要件が変わりやすいプロジェクトに適しています。

## 2. アジャイルを用いるメリット
<br>

アジャイル開発手法には、多くのメリットがあります。

一つ目は「早期かつ継続的な価値提供を可能にすること」です。
これは短期間で動作するプロダクトをリリースするため、顧客側は短いスパンで成果を確認することができます。


二つ目は「顧客満足度の向上」です。
要件変更に柔軟に対応できるため、顧客の要望を反映しやすく、従来のウォーターフォールに比べて戻りも最小限に抑えられます。

三つめは「リスクの軽減」です。 
これは短いスプリント[^3]で進行するため、大きな問題が発生する前に対処が可能になります。


最後に「チームの協力の向上」です。
チーム内で頻繁にコミュニケーションを取り合うことになるため、課題解決に向けて迅速に対応できます。

## 3. アジャイルを用いた際のデメリット
<br>

勿論このアジャイル開発にも様々なデメリットは存在します。

一つ目は「スコープの不確実性」です。
アジャイル開発は柔軟性を重視しているので、ウォーターフォールと異なり要件やスコープがプロジェクトの進行中に変わることも多いです。
そのため最終的な成果物の内容が当初の予定と異なるといったことも少なくはなく、スコープが膨らみすぎてしまう可能性があります。

二つ目には上記に伴う「スケジュール管理の困難さ」も挙げられます。
スプリントごとに新しい要件に変更要望が発生した場合、全体的なスケジュールを正確に予測することが困難になります。
その結果、プロジェクトが期限内に完了しないといったリスクにも繋がってしまいます。

また、三つめとして「継続的な顧客の関与が必要」ということも挙げられます。
アジャイル開発ではクライアント（顧客やエンドユーザ）からのフィードバックは欠かせません。
これが欠けてしまうとクライアントとの開発の方向性がずれてしまい、最終的にクライアントが期待するものと異なる結果になってしまう可能性が挙げられます。

## 4. ウォーターフォールとの比較
<br>

従来のウォーターフォール開発は各フェーズを順番に進め、全ての計画（設計）を最初に行い、
その後開発～テストと進行する開発手法であり、一度決定した要件を変更するは手戻りが発生し、非常に困難です。

一方でアジャイル開発は短いサイクルで開発を行い、毎回フィードバックを受けながら次のステップへ進むことができる開発手法となるので、仕様の変更があった際にも柔軟に対応することができます。


## 5. スクラムの概要
<br>

アジャイルの実践にはいくつかのフレームワークが存在しますが、その中でもスクラム[^4]は最もよく使われています。

スクラムは以下の要素で構成されます。
|用語|意味 / 役割|
|:---:|:---:|
|スプリント|通常1〜4週間|
|プロダクトオーナー|顧客要件を反映させる役割|
|スクラムマスター|チームがスムーズに開発を進めるための調整役|
|デイリースクラム|毎日短時間の進捗報告会|

スクラムの導入は、まずこれらの役割を明確にし、チーム全体で協力して進行することが重要となります。

## 6. まとめ
<br>

- アジャイル開発は開発手法の一つ
    - 柔軟で顧客の要求に応じた開発手法で、変化の多いプロジェクトに向き
- メリット
    - 「早期の価値提供」、「リスク軽減」、「チーム協力」など
- デメリット
    - 要件やスコープが変わりやすく、最終的な成果物が当初の計画と異なることがある
    - スコープが膨らみ、プロジェクトが拡大するリスク
    - スプリントごとに新しい要件が加わることがあるため、スケジュールを正確に予測するのが困難
    
[^1]:アジャイル（Agile）は「俊敏性の高いソフトウェア開発」の概念を意味しており、単語自体は「俊敏な」や「素早い」という意味で使用されるが、ここでは短い期間でのサイクルを実現する開発概念の総称。

[^2]:2001年に当時ソフトウェア開発手法分野で活躍していた17名の専門家によってまとめられた文書で、アジャイルの定義にあたる。

[^3]:「スクラム」における工程の反復単位のこと。1～4週間で区切られることが多い。

[^4]:メンバーごとに「プロダクトオーナー」、「開発者」、「スクラムマスター」の役割を割り振り、「チームワークを重視する」手法。
アルファSSL/KingSSL更新後の接続エラー対応

安いSSL大好きな身の回りで数件起きたのでメモしておきます。

## 症状

- アルファSSL/KingSSLなどGlobalSignがルートに入っている証明書を更新したら一部デバイスからSSLでアクセスできなくなった

※多分、GMOグローバルサイン/グローバルサインの名称で販売しているもの（お高い系）でも同様です。

## 原因

- アルファSSL/KingSSLで利用しているGlobalSignのルート証明書が変更された（2024/1/29以降発行分）
- クライアント側のOSに新しいルート証明書が含まれていない（OS更新やCA更新がされていない）

## 解決方法

以下の４パターンになるかと思います。

### 1.SSLの証明書のチェックを無効化

本当はよく無いですよねー。手元でコード直せるような環境の場合の暫定対応です。

- curlコマンドに`-k`オプションを付加する
- phpの場合は以下のようにする
    ```php
    $curl=curl_init();
    curl_setopt($curl,CURLOPT_URL,$url);
    curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,false);
    curl_exec($curl);
    ```
    
### 2.クライアントにルート証明書の追加

基本的にCAが更新されていないので、これ以外の場合にも影響する可能性がありますのでパッケージ更新や新しいOSへのアップグレードなどが最善です。が、アクセス元がIoTデバイスや他社サーバーの場合には、なかなか難しいですよね。

- パッケージ更新（ubuntu)
    ```sudo apt install ca-certificates```

- 手動追加
    ルート証明書/中間証明書を取得しインストールする
    
    ```sh:Ubuntuの場合
    cp （証明書ファイル名） /usr/local/share/ca-certificates
    sudo update-ca-certificates
    ```

https://www.toritonssl.com/repository/

### 3.クロスルート証明書を付加

クロスルート証明書を付加する事で、証明書を有効にします。対応方法としては、サーバー側だけで済むので一番簡単です。が、将来的にはCA更新が必要ですよね。あと、翌年の設定漏れに注意が必要です。

https://www.toritonssl.com/repository/xcert.html

中間証明書のcrtを以下のように連結してクロスルート証明書にして設置します。基本的にはR3-R6だけで問題無いはずです（相当古くない限り

```
-----BEGIN CERTIFICATE----- 
 中間CA証明書
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
 R3-R6クロスルート証明書
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
 R1-R3クロスルート証明書
-----END CERTIFICATE-----
```

参考

https://jp.globalsign.com/support/ssl/environment-r3.html

https://jp.globalsign.com/support/ssl/environment-r6.html

### 4.他のSSLを使う

GlobalSignの問題なので、サクッと他のRoot証明書に紐づいているSSL証明を使います。お金で解決する方法です。ただし、ブランドが異なってもルートがGlobalSignだと解決しないので注意しましょう。

- COMODO Positive SSL(Sectigo->USERTrust)
- FUJI SSL(SECOM Trust)

などがお手頃かと。

## ぶつぶつ

同様の現象はLet's Encryptでも2021年に`DST Root CA X3`から`ISRG Root X1`に切り替わった際、古いデバイスからのアクセスができなくなりました。

https://letsencrypt.org/ja/docs/dst-root-ca-x3-expiration-september-2021/

インターネットにアクセスするデバイスは定期的に更新されることが望ましい（証明書やセキュリティアップデート）という事ですし、固定用途であれば独自の証明書をインストールするなどの方が良いという事ですね。
WordPressのバージョンアップで壊れにくいサイトを作る

X等で、「WordPressのバージョンアップでサイトが壊れた(表示が崩れた)」というのを見かけることがあります。
もちろん、事前にベータ版やRC(リリース候補)版で動作確認する、が確実ですが、この記事では、そもそもWordPressがバージョンアップしても壊れにくい(コード変更が生じにくい)方法の1つを紹介します。

# コアのブロックを活用する
WordPressでは独自ブロックを追加することができます。独自ブロックだと入力欄を自分の好きなように構築できるので、たしかに開発時は楽しいでしょう。しかし、問題があります。

* WordPressのブロック機能は開発が日々行われており、バージョンアップで新しくなる ([詳細は=>ブロック API リファレンス / API バージョン](https://ja.wordpress.org/team/handbook/block-editor/reference-guides/block-api/block-api-versions/))

このため、独自ブロックを作っている場合、WordPressのバージョンアップ時にコード変更を必要とするケースが結構あります。

私の場合も、昔(WordPress5.0ぐらいのころ)は独自ブロックで吹き出しブロックを作成していました。しかし現在では、コアブロックの『メディアとテキスト』に、スタイルシートをあてることで、吹き出しブロックを実現しています。

![スクリーンショット 2024-10-23 125907.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31643/c387c29e-e01b-7b4b-4a8c-69617a4d3bf2.png)

↑ブロック編集画面で、**追加CSSクラス** が指定できるので、*speech-balloon* と記載しています。(CSSの詳細は、本記事では省略) ↓実際の画面はこのようになります。

![スクリーンショット 2024-10-23 125825.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31643/4b461af1-75de-2cf0-8a75-69f6ca6fdf79.png)

スクリーンショットの元記事は=> [ファクトフルネス(ハンス・ロスリング他)の次に読む本は「存在しない女たち](https://book-recommend.com/2020/04/10/factfulness/)

## 追加CSSクラスは初期設定可能

さて、**追加CSSクラス** ですが、ここに都度*speech-balloon*と書くのは手間がかかりますね。これを解決する方法の1つとして、[新規投稿時にブロックを初期配置する ](https://php4wordpress.calculator.jp/gutenberg/new-post/) があります。

新しく記事を書くときにブロックをあらかじめ配置しておく機能ですが、ブロックの詳細設定も同時に可能です。このため、**追加CSSクラス**に値を指定できます。

```PHP
$post_type_object->template = array(
    array( 'core/media-text', array(
		'mediaType' => 'image',
		'mediaUrl' => '',
		'className' => 'speech-balloon'
	)),
);
```
といったように、*className' => 'speech-balloon'* という指定が可能です。

このように、コアブロックを活用して作ることで、バージョンアップ時にコード変更が必要になる事態を減らすことが可能です。
【画像】特定のLabelの文字の色を変える

### ① UILabelの紐付け
```
@IBOutlet weak var label: UILabel!
```
### ② 色を変える単語を指定
```
// ストーリーボードで設定されたテキストを取得
let fullText = label.text ?? ""
        
// Attributed Stringの作成
let attributedString = NSMutableAttributedString(string: fullText)
        
 // 変更したい部分の範囲を指定
let range = (fullText as NSString).range(of: "ここに色を変える単語")
        
// 属性を設定
attributedString.addAttribute(.foregroundColor, value: UIColor.red, range: range)
        
// UILabelに設定
label.attributedText = attributedString
```
↓ここで好きな色に指定
```
// 属性を設定
attributedString.addAttribute(.foregroundColor, value: UIColor.red, range: range)
```
## 例
### 変更前
![スクリーンショット 2024-10-23 12.36.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760972/0b62fd8b-f832-684d-fe2e-199152f11a6a.png)
### 変更後
![スクリーンショット 2024-10-23 12.40.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760972/9155c833-82d0-8889-84da-bfc961f62242.png)
```

// ストーリーボードで設定されたテキストを取得
let fullText = label.text ?? ""
                
// Attributed Stringの作成
let attributedString = NSMutableAttributedString(string: fullText)
                
// 変更したい部分の範囲を指定
let range = (fullText as NSString).range(of: "カレー")
                
// 属性を設定
attributedString.addAttribute(.foregroundColor, value: UIColor.brown, range: range)
                
// UILabelに設定
label.attributedText = attributedString
```
GITでのブランチ差分確認方法

Gitでは、ブランチ間の差分を確認することがよくあります。コードのレビューや変更の把握に便利なこの操作は、git diff コマンドを使ってシンプルに行えます。

### 基本的なgit diffの使い方

- コマンドの基本構文

```bash
git diff <branch1> <branch2>
```

```bash
git diff <branch1>..<branch2>
```

このコマンドは、`branch1` と `branch2` の間の **差分（変更内容）** を表示します。


### コミット単位での差分確認（--statオプション）
`--stat` オプションを使うと、ファイルごとの変更数を簡潔に表示します。

```bash
git diff --stat main feature-branch
```

```diff
 src/main.go   | 12 ++++++++----
 README.md     |  2 +-
 2 files changed, 10 insertions(+), 4 deletions(-)
```


 ファイルごとの変更行数や追加・削除の数が表示され、概要を把握するのに役立ちます。

### 特定のファイルだけを比較
もし特定のファイルの差分だけを見たい場合、以下のようにファイル名を指定します：

```bash
git diff main feature-branch -- src/main.go
```

### 前回のコミットとの差分
あるブランチの最新コミットと1つ前のコミットの差分を確認するには、以下のコマンドを使います

```bash
git diff HEAD~1 HEAD
```

### 差分確認時の便利なオプション


|オプション|	説明|
|--|--|
|--color	|差分の出力に色をつけて視認性を高めます|
|--name-only	|変更されたファイル名だけを表示します|
|--name-status	|変更の種類（追加、削除、変更）も表示します|
|--cached	|ステージ済みの変更だけを確認します|


Gitでブランチ間の差分を確認するには、`git diff` を使うのが基本です。さらに、`--stat` や `--name-only` などのオプションを活用することで、より見やすく情報を整理することができます。


https://git-scm.com/docs/git-diff
Railsでキャッシュの削除をpub/subで行う（ActiveSupport::Notifications）

# はじめに
Railsのプロジェクトでキャッシュを使う際のパターンをちょっと考えました。
一般的なActive Recordのキャッシュというよりは、複数のモデルに紐づく返り値のキャッシュをどうするかという観点で、もしもっと良い方法とか一般的なアーキテクチャパターンあれば教えてください。

# 前提条件
- 複数モデルに紐づくAPIの返り値をキャッシュしたい
- 複数モデルに紐づくが、その中の一つでもupdateされたらキャッシュを削除したい

# アンチパターン
アンチパターンという言葉はちょっと強いですが、パッと思いつく方法は以下のように紐づくモデルに`after_commit`でキャッシュを削除するコードを追加する方法です。

例えば、以下のような場合です。

```ruby
class Api::MyApiController < ApplicationController
  def index
    cache_key = "my_api_cache_key"
    result = Rails.cache.fetch(cache_key, expires_in: 12.hours) do
      # 複数のモデルからデータを取得する処理
      model1_data = Model1.all
      model2_data = Model2.all
      # 必要なデータのマージ処理
      { model1: model1_data, model2: model2_data }
    end

    render json: result
  end
end

class CacheClearService
  def self.clear_my_api_cache
    Rails.cache.delete("my_api_cache_key")
  end
end

# 各モデルのコールバックでサービスクラスを利用
class Model1 < ApplicationRecord
  after_commit :clear_cache, on: [:update]

  private

  def clear_cache
    CacheClearService.clear_my_api_cache
  end
end

class Model2 < ApplicationRecord
  after_commit :clear_cache, on: [:update]

  private

  def clear_cache
    CacheClearService.clear_my_api_cache
  end
end
```

これでももちろん良いのですが、この場合の問題点としてはキャッシュを使ってる側では、どのタイミングでキャッシュが削除されているか分からないところです。

使われているモデルを全て見に行かないと、いつキャッシュが削除されているかわかりません。

# 解決策
キャッシュの呼び出し側で紐づくモデルが分かれば、少なくともキャッシュ削除に関連するモデルは分かります。
そこで、`ActiveSupport::Notifications`を使います。

```ruby
class CacheClearService
  CACHE_KEY = 'my_api_cache_key'
  MODEL1_EVENT_KEY = 'clear_my_api_cache_model1_event'
  MODEL2_EVENT_KEY = 'clear_my_api_cache_model2_event'
  
  def self.setup_cache_cleanup_listener
    ActiveSupport::Notifications.subscribe(MODEL1_EVENT_KEY) do
      self.clear_cache
    end

    ActiveSupport::Notifications.subscribe(MODEL2_EVENT_KEY) do
      self.clear_cache
    end
  end

  def self.clear_cache
    Rails.cache.delete(CACHE_KEY)
  end
end

class Model1 < ApplicationRecord
  after_commit :clear_cache, on: [:update]

  private

  def clear_cache
    ActiveSupport::Notifications.instrument(CacheClearService.MODEL1_EVENT_KEY, self)
  end
end

class Model2 < ApplicationRecord
  after_commit :clear_cache, on: [:update]

  private

  def clear_cache
    ActiveSupport::Notifications.instrument(CacheClearService.MODEL2_EVENT_KEY, self)
  end
end

# initilizerでリスナーを初期化
Rails.application.config.to_prepare do
  CacheClearService.setup_cache_cleanup_listener
end
```

このように`ActiveSupport::Notifications`を使ってイベントをsubscribeする形にすることで、少なくともCacheClearServiceを見れば、どのモデルが関係ありそうとか、イベントを一覧で確認することができますので便利かなと思います。

# まとめ
お互いに疎結合のためこれを導入してもテストが落ちることがないというのはある意味で利点ですが、モデル側のキャッシュをクリアするイベントが削除されても、CacheClearService側からは分からないところは欠点かと思いますので、メリットデメリット把握した上で導入されるのが良いと思います。
grepコマンドで複数条件を指定して検索する（AND検索、OR検索）

（自身の備忘録用です）

任意の対象に対して、AND検索
```
grep <grepしたい文字列> <対象（ファイル名）> | grep <grepしたい文字列>
ex: grep test test.txt | grep hoge
```

任意の対象に対して、OR検索
```
①
grep -e <grepしたい文字列> -e <grepしたい文字列> <対象（ファイル名）>
ex: grep -e test -e hoge test.txt

②
egrep "<文字列|文字列>" <対象（ファイル名）>
ex: egrep "test|hoge" test.txt
```
Node.js/Nest.jsのサーバーのメモリ使用量が知りたい時のコマンド

# 目的
表題の通りです。
開発を行っているとローカルでは問題なく動いていましたが、デプロイなど環境が変わると動かなくなることがよくあります。
環境と発生したエラーは以下です。
- Heroku
    - Basicプラン
- Nest.js
```
Memory quota exceeded
Error R14 Heroku
```

容量が大きいデータを処理する際に発生し、エラーメッセージの内容からメモリの使用量について調査しました。
記事で紹介するコマンドはそのメモ書です。


# コマンド
以下のコマンドで取得できます。
```
node -e "
const os = require('os');
const fs = require('fs');
const v8 = require('v8');

console.log('=== システム全体のメモリ情報 ===');
console.log(\`全体メモリ: \${(os.totalmem() / 1024 / 1024).toFixed(2)} MB\`);
console.log(\`使用メモリ: \${((os.totalmem() - os.freemem()) / 1024 / 1024).toFixed(2)} MB\`);
console.log(\`空きメモリ: \${(os.freemem() / 1024 / 1024).toFixed(2)} MB\`);
console.log(\`使用率: \${((1 - os.freemem() / os.totalmem()) * 100).toFixed(2)}%\`);

console.log('\n=== コンテナのメモリ制限情報 ===');
try {
  const cgroupPaths = ['/sys/fs/cgroup/memory/memory.limit_in_bytes', '/sys/fs/cgroup/memory.max', '/proc/self/cgroup'];
  let containerMemoryLimit;
  for (const path of cgroupPaths) {
    try {
      const content = fs.readFileSync(path, 'utf8');
      const limit = parseInt(content);
      if (!isNaN(limit) && limit > 0) {
        containerMemoryLimit = limit;
        break;
      }
    } catch (err) {
      continue;
    }
  }
  if (containerMemoryLimit) {
    console.log(\`コンテナメモリ制限: \${(containerMemoryLimit / 1024 / 1024).toFixed(2)} MB\`);
  } else {
    console.log('コンテナメモリ制限が設定されていません');
  }
} catch (error) {
  console.log('コンテナのメモリ制限情報を取得できませんでした:', error.message);
}

console.log('\n=== Node.jsのメモリ情報 ===');
const heapStats = v8.getHeapStatistics();
const used = process.memoryUsage();
console.log(\`全体メモリ制限: \${(heapStats.heap_size_limit / 1024 / 1024).toFixed(2)} MB\`);
console.log(\`メモリ使用量: \${(used.heapUsed / 1024 / 1024).toFixed(2)} MB\`);
console.log(\`メモリ割り当て量: \${(used.heapTotal / 1024 / 1024).toFixed(2)} MB\`);
console.log(\`空きメモリ: \${((heapStats.heap_size_limit - used.heapUsed) / 1024 / 1024).toFixed(2)} MB\`);
console.log(\`使用率: \${((used.heapUsed / heapStats.heap_size_limit) * 100).toFixed(2)}%\`);
"
```

# 結果割り当て
Node.jsのメモリがコンテナに割り当てられたメモリよりも大きいことがわかります。
Node.jsで使用するメモリ量を変更すれば解決しそうです。

```
=== システム全体のメモリ情報 ===
全体メモリ: 63276.48 MB
使用メモリ: 27747.42 MB
空きメモリ: 35529.06 MB
使用率: 43.85%

=== コンテナのメモリ制限情報 ===
コンテナメモリ制限: 512.00 MB

=== Node.jsのメモリ情報 ===
全体メモリ制限: 4144.00 MB
メモリ使用量: 3.86 MB
メモリ割り当て量: 4.45 MB
空きメモリ: 4140.14 MB
使用率: 0.09%
```

ローカル環境では以下となっています。
コンテナのメモリ上限を1024MBに指定
Node.jsには524MBが割り当てられています。

```
=== システム全体のメモリ情報 ===
全体メモリ: 7938.84 MB
使用メモリ: 2215.38 MB
空きメモリ: 5723.46 MB
使用率: 27.91%

=== コンテナのメモリ制限情報 ===
コンテナメモリ制限: 1024.00 MB

=== Node.jsのメモリ情報 ===
全体メモリ制限: 524.00 MB
メモリ使用量: 3.68 MB
メモリ割り当て量: 4.27 MB
空きメモリ: 520.32 MB
使用率: 0.70%
```






# おわり
現象の解決などはコマンドとは別件なので割愛します。

エラー内容がメモリに関係するものであれば本記事のコマンドを使ってみると原因がわかるかもしれません。
どこに行ってもリソースに悩んでいる気がします。
Hyperforceについて

### Salesforce Hyperforceとは何ですか？
[Hyperforce について - 一般情報と FAQ](https://help.salesforce.com/s/articleView?id=000388902&type=1)
>Hyperforce は、パブリッククラウド用に構築された次世代の Salesforce インフラストラクチャアーキテクチャです。 Salesforce アプリケーションにコンプライアンス、セキュリティ、プライバシー、俊敏性、スケーラビリティを提供し、顧客にデータレジデンシーに関するより多くの選択肢を提供します。

### Hyperforce に移行したかを確認するにはどうすればよいですか?
設定の[会社の設定]-[組織情報]で確認できるインスタンス名のプレフィックスが、「[Salesforce インスタンスの場所](https://help.salesforce.com/s/articleView?id=000396845&type=1)」に記載されているHyperforceインフラストラクチャと同様か確認します。また、「[Find My Instance](https://availability.salesforce.com/find-my-instance/)」マップにインスタンス名を入力すると、「Non-Hyperforce」または「Hyperforce」を示す記号と情報が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/d4f6cc9c-f716-5b6a-0cdf-5373b4b93ade.png)
Google Chromeの開発ツールの「ネットワーク」タブから取得したURLから、エディタの正規表現による置換で特定のFQDN配下のURLを抽出する

## 概要
あるWebページでネットワーク越しに読み込んでいるファイルを調べる際、開発者ツールのネットワークタブを利用することが多いと思います。
その際、ネットワークタブにはアクセス解析や広告など調査のノイズになるファイルが大量に記録されます。
特定のFQDN配下のURLのみを抽出すると便利な場面もありますが、クエリにURLが含まれるなど、ネットワークタブのフィルタでは機能が足りない場合があります。
ここで紹介するのはその場合の抽出方法です。

## 説明の前提
- Windows 11を使用している。Windows10、Macでも可能だと思うがこの記事ではWindows 11で説明します。
- Google Chromeを使用できる。
- サクラエディタ・Visual Studio Codeなど正規表現での置換が可能なエディタを使用できる。JSが分かる人なら開発者ツールのコンソールでも可能だと思います。

## やり方
1. Google Chromeを開く。
1. 開発ツールを起動する。
1. 調査したいページを開く。
1. ページのロード完了後、開発者ツールで下記のキャプチャを参考に「fetchとして**すべて**コピーを」選択をクリックする。
![Chromeネットワークタブで右クリック.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1226959/ff31f9be-364a-c9c1-d870-a6c3e6c8817f.png)

1. コピーしたfetch文をエディタの新しいファイルにペーストする。
1. URLを含む行以外は要らないため、エディタで以下の正規表現の「example\.com」の箇所を当該のFQDNに差し替えて検索し、空白に置換する（つまり、一致した箇所を削除する）。
```
^(?!fetch\("https?://example\.com).+$\r?\n
```
:::note warn
「.」は正規表現では任意を一文字を表すので「\\.」と記載してエスケープを忘れずに。漏れても支障のないケースが多いので罠になるかもしれません。
:::
:::note info
テスト系のURLも含めて抽出するケースも場合によっては可能。例えば「test.example.com」も抽出したい場合は
example\\.com を (test\\.)?example\\.com と書く
:::

7\. 最後にfetch文からURLを抽出する。以下の正規表現で一致した行をキャプチャグループの1番目「$1」で置換する。そうすればエディタには改行区切りのURLのみが残る。
```
^fetch\("(https?://example\.com[^"]+).*$
```
:::note info
URL中のダブルクォーテーションはエンコードされるのでこれで問題ないはず。私は困ったことないです。
:::

:::note info
クエリやハッシュは残るので、必要に応じて ```[?#].+$``` で検索して削除するといいです。
:::

## 余談
否定先読みのようにやや難しめの表現を使わずに済ませたかったが、```[^(...)]```とかのやり方では思いつけなかった。
画面タッチで左右に移動をさせたかった話

## はじめに
2D横スクロールで
画面右側に触れていたら右へ移動
画面左側に触れていたら左へ移動
というのがやりたかった

## つまずいた点
タッチ操作をするとキャラクターが左右に動き続けてしまう

### 初心者の私が考える原因
アクションにPointerのPositionを設定すると
canceledが発火しない

## 解決法
InputSystemのアクションやらバインドやらをぽちぽちすることで解決したかったが
TouchStateなるものを使うことで何とかなった
もっと簡単な方法とは思う…ぜひ教えて欲しい…

### とりあえず必要なコード全文
```c++
    using UnityEngine.InputSystem.LowLevel;
    
    private TouchState _touchState;
    
    public void _onMove(InputAction.CallbackContext context)
    {
        _touchState = context.ReadValue<TouchState>();
        var touchPosition = _touchState.position;

        float screenWidth = Screen.width;

        // タッチ位置が画面のどちら側か判定
        if (touchPosition.x < screenWidth / 2)
        {
            _inputDirection = Vector2.left;
        }
        else
        {
            _inputDirection = Vector2.right;
        }

        if (!_touchState.isInProgress)
        {
            _inputDirection = Vector2.zero;
        }
    }
}
```

ポイントはこれ↓
```C++
if (!_touchState.isInProgress)
{
    _inputDirection = Vector2.zero;
}
```

touchStateのisInProgressを取得することで触れているかどうかを取得できた

## おわりに
もっといい方法があると思いつつも他の方法で解決できないので
一旦このようになりました

もっといいやり方があればぜひコメントなどで教えていただけると助かります…
Events

[Previous << Transactions](https://qiita.com/flowcadence/items/0d73ce09c9da04d8b697)
[Next >> Core Events](https://qiita.com/flowcadence/items/5e0aea26c0ce24fab7e9)

https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a#cadenceの言語仕様を学ぶ

イベントは、プログラムの実行中に発行できる特別な値です。

イベントの種類は、`event`キーワードで宣言できます。
```ruby
event FooEvent(x: Int, y: Int)
```
イベント宣言の構文は、[関数(function)宣言](https://qiita.com/flowcadence/items/6518644e68d32b032530#function-declarations)の構文と類似しています。イベントには名前付きパラメータが含まれ、それぞれにオプションの引数ラベルがあります。

イベントパラメータは、有効なイベントパラメータ型のみを持つことができます。有効な型は、boolean、string、integer、これらの型の配列およびディクショナリ、およびすべてのフィールドが有効なイベントパラメータ型である構造体です。リソース型は許可されていません。リソースが引数として使用されると移動されてしまうからです。

イベントは、[スマートコントラクト](https://qiita.com/flowcadence/items/91a5ecb5812af1f98bef)本体の中でしか宣言できません。イベントはグローバルに、またはリソース型や構造体の中で宣言することはできません。
```ruby
/* Invalid: An event cannot be declared globally */
event GlobalEvent(field: Int)

access(all)
contract Events {
    /* Event with explicit argument labels */
    event BarEvent(labelA fieldA: Int, labelB fieldB: Int)

    /* Invalid: A resource type is not allowed to be used
     * because it would be moved and lost
     */
    event ResourceEvent(resourceField: @Vault)
}
```

<h1 id="Emitting-events">Emitting events</h1>

プログラムからイベントを発信するには、`emit` ステートメントを使用します：
```ruby
access(all)
contract Events {
    event FooEvent(x: Int, y: Int)

    /* Event with argument labels */
    event BarEvent(labelA fieldA: Int, labelB fieldB: Int)

    fun events() {
        emit FooEvent(x: 1, y: 2)

        /* Emit event with explicit argument labels
         * Note that the emitted event will only contain the field names,
         * not the argument labels used at the invocation site. */
        emit BarEvent(labelA: 1, labelB: 2)
    }
}
```
イベントの発信には、以下の制限があります。

  * イベントは`emit`ステートメントの中でのみ呼び出すことができます。つまり、イベントを変数に割り当てたり、関数のパラメータとして使用することはできません。
  * イベントは、宣言された場所(スマートコントラクト)からしか発信できません。

翻訳元

https://cadence-lang.org/docs/language/events

***
<b>[Previous << Transactions](https://qiita.com/flowcadence/items/0d73ce09c9da04d8b697)
</b>

[Flow blockchain / Cadence version1.0ドキュメント](https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a) (Events)

<b>[Next >> Core Events](https://qiita.com/flowcadence/items/5e0aea26c0ce24fab7e9)</b>
kubernetesの便利機能

## Node selector
特定のNodeにのみスケジュールしたい時に使う。例えば**SSDを使っているNodeにスケジュールしたい**ってとき、マニフェストに
```
Nodeselector:
    disktype:ssd
```
って書く。

## Node Affinity
### Affinity ＝類似性、　近づくようにする
Selectorとやることは近いけど、こっちは「可能ならスケジュールする」選択肢が取れる。Selectorだと対応するNodeが存在しない場合、PodがNodeにスケジュールされないが、**Affinityなら適当なNodeにスケジュールするように設定できるので柔軟性が高い。**
**絶対に特定のNodeにスケジュールしたい**って時以外はAffinityを使うのが無難。
設定が二つある。
**requiredDuringSchedulingIgnoredDuringExecution**：対応するノードが見つからなければスケジュールされない。Selectorと比べてPodの指定を細かくできる
**preferredDuringSchedulingIgnoredDuringExecution**：できれば対応するNodeにスケジューリングするけど、なかったら適当にスケジュールする。

**Preferredを指定した場合、Weightのしていが必要になる**
複数Preferredを指定した時、各条件に重みをつけることで、各Weightの合計が高いNodeにスケジュールされる。

## Pod Affinity(Anti-affinity)
NodeSelectorやNodeaffinityと違い、**すでにNodeにスケジュールされたPodを基準に考える**
例えば
すでにNodeAにPodAがスケジュールされている。
ここでPodBはPodAと同じNodeがいいと言っている。これがPodAffinity
しかしPodCはPodAと同じNodeは無理と言っている。これがPodAntiaffinity
よく使うケースとして、Node障害に備えて**同じアプリケーションを動かしているPodを同じNodeに載せない**という使い方がある。なぜか。いくらdeploymentでアプリケーションを冗長化させてもNodeがイカれたらアプリケーションが停止してしまうから

## Pod Topology Spread Constraints(PTSC)
TopologyKeyを使うことでどうPodを分散させるかを表現できる。
例：Kubernetes.io/hostnameラベルを指定すると、ホスト間でPodを分散してスケジュールできる。
PodAntiaffinityではPreferrを指定しても、Podの数がNodeの数を超えると制御できなかった。
逆に完全に分散させようとRequireを使うとPodの数がNodeの数を超えられなくなる。
そこで**PTSC**
ポイントは**maxSkew:数字**という指定。
これはNode間の差分が１以下になるようにスケジュールするという設定。
例えば三つNodeがあったとする時、全てのNode間のPodの個数の差分をみて、全体の差分が１以下になるようにスケジュールする

## TaintとToleration
TaintはNodeに、TolerationはPodにつけるもの。
Taintは汚れ、Tolerationは寛容という意味。
**NodeについているTaint（汚れ）をPodが許容できるかという考え方**
Node Affinityでは **「あるPodをどういうNodeにスケジュールしたいか** という考えだったが、Taint/Tolerationは **「あるNodeが特定のPodしかスケジュールしたくない（特に指定のないPodはスケジュールしたくない）」** という考え方になる
**NodeにTaintをつける方法**
```
kubectl taint nodes <対象ノード名><Label名>=<Labelの値>:<Taintの効果>
```

## Pod priorityとPreemption
Podがスケジュールされる優先順位を決めることができる。
やりかた
1.Priorityclassを作成
2.設定したPriorityclassをPodのマニフェストに設定
①value:10000みたいに重みをつける。多いほど重要
②PriorityclassName:に①のMetadataの名前を書く

## 水平スケールと垂直スケール
アクセスが増えると一つのPodでは厳しくなる。スケールさせてアプリケーションを安定させよう。
水平スケール：同時に使えるアプリケーションを増やすこと
垂直スケール：使用できるリソースを増やすこと
### Horizontal Pod Autoscale
HPAが自動でPodの個数を調整できる。
HPAのマニフェスト
**minReplicas**と**maxReplicas**を指定。Podの増減の幅を決める。
増減を決めるメトリクスはMetrics以下に書く
**targetaverageUtilization**には望ましいCPU使用率を書く
### VPA
resource requests/limitsの値を自動で調整してくれる

## アプリケーションの可用性を保証しよう
### PodDisruptionBudget
DeploymentでカバーできるのはPodの更新のみ。Nodeのメンテナンスの時などにPodがどっか言ってしまったりする。それを安全に行う方法。
ポイント
**minAvailable**　**「最低幾つのPodが利用可能な状態か」** を指定
**maxUnavailable** **「最大幾つのPodが利用不可な状態か」** を指定
例：deploymentのReplicas:3の時、必ず二つ以上のPodが利用可能な状態で存在してほしいという要件があったとする。
このときPDBはminAvailable:2と書く
例えば何らかの理由でPodが一つPendingになった時、同時にapp:hello-serverのPodが載っているPodからPodをどかせられなくなる。これによってNodeのメンテはPendingが解消されるまでできなくなるので、自動的にNodeが保たれる。
MVVM モーテル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3694878/d5a65439-f63b-3539-0cce-e31805acd54a.png)

ViewModelに関する理解：
ViewModelは、視覚の状態と行動の2つの部分を含んでいます。モデル層のデータモデルは、状態のみを含んでいます。
例えば、ページのこの部分に何を表示するか、あの部分に何を表示するかは視覚の状態（表示）に属します。一方、ページが読み込まれたときに何が起こるか、ここをクリックしたときに何が起こるか、ここをスクロールしたときに何が起こるかは視覚の行動（インタラクション）に属します。視覚の状態と行動はすべてViewModelにカプセル化されています。このようなカプセル化により、ViewModelはView層を完全に記述することができます。これはフロントエンドとバックエンドの分離において重要な要素です。

コード理解：
//擬似コードの説明：
View層:
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3694878/4139ae0a-63b0-b3c1-e419-b8d03addd315.png)

ViewModel層:
var app = new Vue({
    el: '#app',
    data: {     // ビューの状態を記述するために使用（モデル層データに基づくものと、純粋なフロントエンド定義の両方がある）
        message: 'こんにちは Vue！',  // 純粋なフロントエンド定義
        server: {}, // モデル層データに基づく二次封装データを格納
    },
    methods: {  // ビューの行動を記述するために使用（完全にフロントエンド定義）
        showMessage(){
            let vm = this;
            alert(vm.message);
        }
    },
    created()
        let vm = this;

        // Ajaxでモデル層のデータを取得
        ajax({
            url: '/your/server/data/api',
            success(res){
                // TODO 取得したモデルデータの変換処理を行い、二次封装を実施
                vm.server = res;
            }
        });
    }
})

Model層：
{
    "url": "/your/server/data/api",
    "res": {
        "success": true,
        "name": "IoveC",
        "domain": "www.cnblogs.com"
    } 
}
Angular バインディング

```hoge.ts
// プロパティバインディング [ ]
// 動的な値をバインド
<mat-select [aria-label]="labelText">
// TypeScriptコンポーネント
labelText = '国選択';


// イベントバインディング ( )
// イベントのバインド
<mat-select (selectionChange)="onSelectionChange($event)">
// コンポーネント
onSelectionChange(event: MatSelectChange) {
  console.log('選択された値:', event.value);
}

// 双方向バインディング [( )]（バナナインザボックス構文）
// 値の読み書き両方
<mat-select [(value)]="selectedCountry">
// コンポーネント
selectedCountry = 'jp';

// テンプレート参照変数 #
// テンプレート内で要素を参照
<mat-select #countrySelect>
<button (click)="countrySelect.open()">開く</button>

// 文字列の属性バインド（バインドなし）
// 静的な文字列を直接設定
<mat-select aria-label="国選択">

// 実践的な使用例：
<mat-select
  [aria-label]="'国選択'" // プロパティバインディング
  [(ngModel)]="selectedCountry" // 双方向バインディング
  (selectionChange)="onCountryChange($event)" // イベントバインディング
  [disabled]="isDisabled" // 条件に基づくプロパティバインディング
>
  <mat-option *ngFor="let country of countries" [value]="country.code">
    {{country.name}}
  </mat-option>
</mat-select>

// コンポーネント
export class CountrySelectComponent {
  selectedCountry: string;
  isDisabled = false;
  countries = [
    { code: 'jp', name: '日本' },
    { code: 'us', name: 'アメリカ' }
  ];

  onCountryChange(event: MatSelectChange) {
    console.log('選択された国:', event.value);
  }
}

```


## バインディングの使い分け

[ ] :

動的な値を設定する場合
TypeScriptの値をHTMLに反映させたい場合


( ) :

ユーザーのアクションを検知したい場合
コンポーネントの変更を監視したい場合


[( )] :

フォーム入力など、双方向のデータの流れが必要な場合
ビューとモデルを同期させたい場合


バインドなし（直接記述）:

静的な文字列を設定する場合
値が変更されない場合



### 注意点：
プロパティバインディングを使用する場合、式の評価結果が代入されます
イベントバインディングは$eventオブジェクトでイベントデータにアクセスできます
双方向バインディングは内部的にプロパティバインディングとイベントバインディングの組み合わせです
sshpass + 1passwordを使用してパスワード入力を楽にする

SSHを使用してサーバーに接続する際、パスワード入力を行うのがいちいちめんどくさかったので。

sshpassと1password CLIを使用するとパスワードをshの履歴に残さずに楽に接続ができます。

まずはsshpassをインストールしていきましょう。macOSではbrewからインストールできます。

```sh
brew install sshpass
```

インストール後は以下のような感じでワンライナーで接続できます。

```sh
sshpass -p "$(op read [1passwordの秘密参照])" ssh [ホスト]
```

簡単にできました。
macアドレスの相手先アドレスの表示


結果

![o_coq546.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/6f9e279c-8e52-b71c-ccdb-e343c3b350d8.jpeg)


プログラム

```c++


//mac_add_broadcast_out1

#include "ESP32_NOW.h"
#include "WiFi.h"
#include <esp_mac.h>  // For the MAC2STR and MACSTR macros

#include "MacAddress.h"

#define ESPNOW_WIFI_CHANNEL 1

char *mac_add_conv(const uint8_t *a){

    //uint8_t a[8] = {0x1f,0x2f,0x3f, 0xf4,0xf5,0xf6,};
    char h[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    static char b[16+1];
    
    b[0]=h[a[0]>>4];
    b[1]=h[a[0]&0x0f];

    b[2]=h[a[1]>>4];
    b[3]=h[a[1]&0x0f];

    b[4]=h[a[2]>>4];
    b[5]=h[a[2]&0x0f];

    b[6]=h[a[3]>>4];
    b[7]=h[a[3]&0x0f];

    b[8]=h[a[4]>>4];
    b[9]=h[a[4]&0x0f];

    b[10]=h[a[5]>>4];
    b[11]=h[a[5]&0x0f];

    b[12]=0;

    //printf("%s\r\n",b);

   return( b );
   
}//mac_add_conv

void setup() {

  Serial.begin(115200);

  for(int i=0;i<16;i++){
    Serial.print(".");
    delay(1000);
  }//for
  Serial.println();

  // Initialize the Wi-Fi module
  //WiFi.mode(WIFI_STA);
  //WiFi.setChannel(ESPNOW_WIFI_CHANNEL);
  //delay(3000);

  //const MacAddress peer_mac({0x48, 0x27, 0xe2, 0xe3, 0xbd, 0x50});
  const MacAddress peer_mac({0x40, 0x4c, 0xca, 0x5a, 0xe3, 0x1c});

  Serial.print("  MAC Address: " );
  Serial.println( mac_add_conv( peer_mac  ) );


}//setup


void loop() {

  delay(1000);

}//loop


```
ACDLを提唱します。その16

# 概要
ACDLとは、アプリは、クラウド、大切なデータは、ローカルです。
アプリ作ったので、plunkerに上げてみた。

# 機能
CSVから棒グラフを生成します。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/3d8594f8-c8e2-8b50-15cf-39824163eb05.png)

# サンプルコード

```

var src = document.getElementById('src');

var spec2 = {
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "description": "A simple bar chart with embedded data.",
  "data": {
    "values": [
      {"a": "A", "b": 28}, 
      {"a": "B", "b": 55},
      {"a": "C", "b": 43},
      {"a": "D", "b": 91}, 
      {"a": "E", "b": 81}, 
      {"a": "F", "b": 53},
      {"a": "G", "b": 19}, 
      {"a": "H", "b": 87}, 
      {"a": "I", "b": 52}
    ]
  },
  "mark": "bar",
  "encoding": {
    "x": {
      "field": "a", 
      "type": "nominal", 
      "axis": {"labelAngle": 0}
    },
    "y": {
      "field": "b", 
      "type": "quantitative"
    }
  }
};

vegaEmbed('#vis', spec2).then(function(result) {
}).catch(console.error);

function run() {
  var line = src.value.split('\n');
  var items = [];
  for (var i = 0; i < line.length; i++)
  {
    var item = line[i].split(',');
    if (item[0] != "")
      items.push({"category": item[0], "value": item[1]});
  };
  var spec = {
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "description": "A simple bar chart with embedded data.",
   "width": 500,
   "data": {
    "values": items
  },
  "mark": "bar",
  "encoding": {
    "x": {
      "field": "category", 
      "type": "nominal", 
      "axis": {"labelAngle": 0}
    },
    "y": {
      "field": "value", 
      "type": "quantitative"
    }
  }
};
  vegaEmbed('#vis', spec).then(function(result) {
  }).catch(console.error);
}




```

# 成果物

https://embed.plnkr.co/plunk/DIbTwqeLKMhmjNdF


以上
Dockerfileについて

## Dockerfileとは
　Dockerfileは、コンテナの設計図です。アプリケーションやパッケージの動作環境を定義し、その環境をもとにDockerイメージを作成するために使います

## Dockerfileの作成
このDockerfileでは、Ubuntu 20.04をベースにして、curlをインストールし、ローカルのファイルをコンテナ内にコピーした後、bashシェルをデフォルトで実行する設定をしています。

 ```
 FROM ubuntu:20.04

 RUN apt update
 RUN apt install -y curl 

 COPY . /app/

 CMD ["bash"]
 ```

 ### FROM
  どのベースイメージを使用するか指定します。この場合は、Ubuntu 20.04の公式イメージが使われます。
Dockerイメージはレイヤー構造になっているため、ベースイメージの上に他の命令を積み重ねることで環境をカスタマイズします。

 ### RUN
  シェルコマンドを実行するための命令です。例えば、apt updateコマンドでパッケージリストを更新し、apt install -y curlでcurlというツールをインストールしています。
  
  apt ubuntu: パッケージリストを最新の状態に更新します。
  apt install -y curl: curlというパッケージをインストールします。
		-y: 対話なしで「Yes」を自動的に選択してインストールを進めるオプションです。

   &&:コマンドをまとめて書くことができます。例えば、以下のようにしてレイヤーを減らし、イメージサイズを小さくすることが推奨されます。
   ```
   RUN apt update && apt install -y curl
   ```

 ### COPY
  ローカル環境にあるファイルやディレクトリを、Dockerイメージ内の指定した場所にコピーします。この例では、カレントディレクトリ（.）の内容をコンテナ内の/app/ディレクトリにコピーしています。
  ```
  COPY 追加元 追加先
  ```

 ### CMD
  コンテナが起動したときに実行されるデフォルトのコマンドを指定します。ここではbash（シェル）が実行されるように設定しています。
  ```
  CMD ["実行ファイル", "パラメータ１", "パラメータ２"]
  ```

**補足: ENTRYPOINTとCMDの違い**
    • CMDは、デフォルトで実行されるコマンドを指定するだけで、コンテナ実行時に上書きが可能です。
	•	ENTRYPOINTは、強制的に実行されるコマンドで、上書きができません。

## まとめ
FROM: ベースとなるDockerイメージを指定。
RUN: シェルコマンドを実行。複数のコマンドを&&でつなげてイメージサイズを最適化。
COPY: ローカルのファイルやディレクトリをコンテナ内にコピー。
CMD: コンテナが起動したときのデフォルトのコマンド。

Dockerfileを使うことで、誰でも同じ環境を簡単に再現でき、開発・テスト・本番環境の統一が容易になります。
azure.identity.ManagedIdentityCredential()なのに、ユーザクレデンシャルを使おうとする

Azure Machine Learning ワークスペースのコンピューティング インスタンスでazure.identity.ManagedIdentityCredential()を含んだPythonコードを実行するとき、
ユーザクレデンシャルが参照されてしまうことがあった。

その原因は、コンピューティングインスタンスのシングルサインオンの設定が有効になっていたことでした。無効にしたところコンピューティングインスタンスのクレデンシャルを使ってくれました。
秀和システム「Python x API で動かして学ぶ AI活用プログラミング」3章

秀和システム「Python x API で動かして学ぶ AI活用プログラミング」
3章をやってみた。
ここでは記事の内容ではなく、自環境での動作結果だけを記録のために記載しています。

## 環境
OS：Windows 11 Home 64 ビット オペレーティング システム
CPU：11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz   3.00 GHz
RAM：32.0 GB

## ソース
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/e55ed1fb-7d82-51ff-b173-9bf609dd2433.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/9a83ea16-5f5d-bcb5-94d6-942d9ae9adac.png)

## 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/ba1ce6e0-8519-4969-cfbc-90952577f407.png)
paizaラーニング問題集「【配列 1】平面で計算」を解いてみた

https://paiza.jp/works/mondai/b_rank_new_level_up_problems/b_rank_new_level_up_problems__calculate_in_two_dimensions

▼考え方

1.縦列の和,横列の和,斜め列の和を、なるべく少ないforループで求めたいと思いました。それぞれの和は変数totalに格納し、最後にmax関数で和の最大の値を求めて出力します。

2.横列の和はスライスを使用して求めます。

3.斜め列は、左斜めと右斜めを分けて考えます。

4.縦列の和は、リストの内包表記を使用して求めます。

▼コード
```py
########## 処理0(準備) インプット,リスト定義 ###########

N = int(input())

A = [[0]*N]*N

for i in range(N):
    A[i] = list(map(int,input().split()))

# miginaname_total: 右斜め列の和を計算する変数
miginaname_total = 0

# hidarinaname_total: 左斜め列の和を計算する変数
hidarinaname_total = 0

# total: 縦列の和,横列の和,(右,左)斜め列の和を格納するリスト
total = []

# maxdata: それぞれの和(リストtotal)の最大値を格納する変数
maxdata = 0

########## 処理1 縦列の和,横列の和,斜め列の和を求め、最大の値を出力する処理 ###########

for j in range(N):
    
    # 考え方2.
    total.append(sum(A[j][0:N]))
    # 考え方3.
    hidarinaname_total += A[j][N-1-j]
    
    for i in range(N):
        
        if j == 0:
            # 考え方4.
            total.append(sum(A_r[i] for A_r in A))

        if j == i:
            # 考え方3.
            miginaname_total += A[j][i]

total.append(miginaname_total)
total.append(hidarinaname_total)
print(max(total))
```
macアドレスのブロードキャストアドレスの表示


結果

![o_coq545.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/9f37edf6-1a74-c725-c441-35eaabe7963d.jpeg)

プログラム

```c++


//mac_add_broadcast_out1

#include "ESP32_NOW.h"
#include "WiFi.h"
#include <esp_mac.h>  // For the MAC2STR and MACSTR macros


#define ESPNOW_WIFI_CHANNEL 1

char *mac_add_conv(const uint8_t *a){

    //uint8_t a[8] = {0x1f,0x2f,0x3f, 0xf4,0xf5,0xf6,};
    char h[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    static char b[16+1];
    
    b[0]=h[a[0]>>4];
    b[1]=h[a[0]&0x0f];

    b[2]=h[a[1]>>4];
    b[3]=h[a[1]&0x0f];

    b[4]=h[a[2]>>4];
    b[5]=h[a[2]&0x0f];

    b[6]=h[a[3]>>4];
    b[7]=h[a[3]&0x0f];

    b[8]=h[a[4]>>4];
    b[9]=h[a[4]&0x0f];

    b[10]=h[a[5]>>4];
    b[11]=h[a[5]&0x0f];

    b[12]=0;

    //printf("%s\r\n",b);

   return( b );
   
}//mac_add_conv

void setup() {

  Serial.begin(115200);

  for(int i=0;i<10;i++){
    Serial.print(".");
    delay(1000);
  }//for
  Serial.println();

  // Initialize the Wi-Fi module
  //WiFi.mode(WIFI_STA);
  //WiFi.setChannel(ESPNOW_WIFI_CHANNEL);
  //delay(3000);

  

  Serial.print("  MAC Address: " );
  Serial.println( mac_add_conv( ESP_NOW.BROADCAST_ADDR  ) );


}//setup


void loop() {

  delay(1000);

}//loop



```