OmniAICreator/Qiita-1.07M huggingface dataset:
最大実行時間9分→60分になった第二世代CloudFunctionsを使ってみた。

# tl;dr
- 2022年8月にGAとなった第二世代CloudFunctions(以下CF)。主な変更点として、最大使用可能リソースと最大実行時間が大幅に増加した。(具体的な変更点は[こちら](https://shinyorke.hatenablog.com/entry/cloud-functions-gen2))
- 最大実行時間が`9分→60分`と、AWSのFaaSであるLambda(最大15分)も屁じゃないくらいに最大実行時間が増えたように聞こえるが、実際には`HTTP関数以外の最大実行時間は今まで通り9分のまま`([参考](https://cloud.google.com/functions/docs/configuring/timeout?hl=ja))。

# やったこと
![スクリーンショット 2022-09-24 22.14.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646534/b8371ea0-b7a2-cace-e9cd-c1eb1be56422.png)
- pandasなどでbigqueryのデータをクレンジングするバッチをCloudScheduler→CloudPub/Sub→CloudFunctionsという定番構成で作っていたら、それなりに実行時間が必要な場面が出てきた。リファクタよりひとまずデプロイしたい。
- 第一世代では小分け実装の必要があり管理リソースが増えてしまうので第二世代の恩恵を受けたいところ。しかし2022年9月現在では、第二世代CFの実行時間は`HTTP関数の場合のみ、最大3,600秒=１時間`に設定できる模様。Pub/Subなどをトリガにする`イベントドリブン関数は最大実行時間540秒=9分のまま`。
- 現在の構成では最大実行時間だけ伸ばすことはできないようなので、Pub/Subの代わりに`CloudWorkflows`を挟んでHTTPトリガを叩かせるようにちょっと構成を変えてみた。

# Cloud Workflowsとは？([参考](https://cloud.google.com/workflows/docs/overview?hl=ja))
- CloudFunctionsやAPI呼び出しなどを組み合わせてワークフローを作れる、AWSでいうところのStepFunctionsのようなGCPのワークフロー管理サービス。
- A→B→C→D...のような、いくつか段階を踏む必要のあるデータ処理などの場合でも、「Aが成功したらBをトリガするPub/Subを叩く」みたいなことをする必要がないので管理リソースが減る&全体像を把握できるので複雑なワークフロー管理で重宝する。
- 今回は[クラスメソッド先輩を参考にして](https://dev.classmethod.jp/articles/google-workflows-send-email/)下記のように、HTTPトリガで作成したCFを叩くワークフローを作成し、これをCloudSchedulerで定期実行させるようにできないか試した。

```
- cleanse_batch:
    call: http.get
    args:
        url: CFのURLを書く
        timeout:1800
        auth:
            type: OIDC
    result: response
- result:
    return: ${response}
```

#### 注意
- ちょっと問題だったのは、`Workflows側のhttp.getのtimeoutが最大1,800秒=30分だった`こと。CF側で3,600秒に設定していても、30分を超えるとWorkflows側でタイムアウトになってしまう。少し悔しいが、9分→30分でも大幅増加だし、第二世代になって増えたリソース割り当てでカバーすればひとまず困らない。
- CFのHTTPエンドポイントを叩くには、`type: OIDC`が必須。
- Workflows側のサービスアカウントにCloud Run 起動元（`roles/run.invoker`）のロールを付けておく必要あり(ここは第一世代と違う。第二世代はCloud Run上に構築されているため)。[参考](https://cloud.googles.ltd/workflows/docs/calling-run-functions?hl=ja#invoke_2nd_gen)

# 感想
- CloudWorkflowsはとても簡単にワークフロー管理ができるので、本来の用途でも大活躍しそう。今回の要件を満たすだけなら、HTTPトリガを叩くだけ用のCFを別に用意する方法でも可能とは思う。
- 実行時間などの第二世代の恩恵を受けられる&依存関係の管理などの拡張性を考えれば今後、定番のPub/Sub構成よりも初めからWorkflowsで実装するのもありかもしれないと思った。
- イベントドリブン関数でも実行時間が拡張がサポートされるよう、今後のCF第二世代のリリースを期待したい。[参考](https://cloud.google.com/functions/docs/concepts/version-comparison?hl=ja#coming_soon_in_2nd_gen)

# 参考

- https://dev.classmethod.jp/articles/google-workflows-send-email/
- https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html
- https://cloud.google.com/functions/docs/configuring/timeout?hl=ja
- https://cloud.google.com/workflows/docs/overview?hl=ja
- https://shinyorke.hatenablog.com/entry/cloud-functions-gen2
- https://cloud.googles.ltd/workflows/docs/calling-run-functions?hl=ja#invoke_2nd_gen
- https://cloud.google.com/functions/docs/concepts/version-comparison?hl=ja#coming_soon_in_2nd_gen
- https://cloud.google.com/workflows/docs/reference/stdlib/http/get
Precision, Recall系の記事のまとめページ

(※もしお気付きの点がありましたら、編集リクエスト・コメントなどご指摘お願い致します。)

機械学習等の分類問題で判別性能を見るために用いられる、Precision, Recall, F値等に関する記事をまとめます。

# 【1】Precision, Recall, F値の解釈

Precision, Recall, F値とは、どういう意味/違い/ニュアンスなのかを、機械学習くんがりんごかどうかを見分けるシーンを想像して解釈する記事。

https://qiita.com/dl_from_scratch/items/4efdf647b397d794cd67


# 【2】表を用いてPrecision, Recallを具体的な数値で計算する例 (分類クラスが3種類以上ある場合も計算)

Precision, Recallを具体的な数値で計算する記事。分類クラスが3種類以上ある場合も、計算の方法を詳解。

https://qiita.com/dl_from_scratch/items/e6f615b7b50833e2fd4a


# 【3】Precisionが大きくRecallが小さい状態とは何か?

Precisionが小さくRecallが大きい状態とはどういうことなのか?、Precisionが大きくRecallが小さい状態とはどういうことなのか?、について解釈する記事。

https://qiita.com/dl_from_scratch/items/309f98c11156b4ab6b52


# 【4】PrecisionとRecallの間に生じる差とは何か?

PrecisionとRecallの間に生じた差について、マーク模試の例で解釈する記事。

https://qiita.com/dl_from_scratch/items/c8c5f8407e6c64d57884

# 【5】Precision, Recallの定義式をより分かり易い形で表記・その特性や生じる差について解釈する

Precision・Recallの定義式をより分かり易い形で表して、PrecisionとRecallの間に発生する差とは何かについてより直感的に解釈してみます。

https://qiita.com/dl_from_scratch/items/af934432965ff532b967

# 【6】分類問題で判別性能の調べ方を考える

Precisionだけを見ていれば良いのか? または、全体の正解率(Accuracy)だけを見ていれば良いのか? について考える記事。

https://qiita.com/dl_from_scratch/items/b8cc7cebe6e94acec795
関数が分母にきても平気な理由


【大学数学】微分方程式入門②(変数分離形)
12:30あたりから
https://www.youtube.com/watch?v=uPRY-KUl4fg

微分方程式で分母に関数がくるケースがある。関数g(x)は恒等的に０ではないが、０になる瞬間もある。これの説明。

結論：
g(x)がゼロになる瞬間があっても良い。
AWSのVPCウィザードが2022年から進化した

# VPCウィザード
VPCを作成する時にはVPCウィザードを使うと簡単に効率よくVPCを作成できたが、
今回はVPCを作成のボタンを押すと、下の資料のようにサブネットやルートテーブルなどが可視化できます。


![スクリーンショット 2022-10-15 12.39.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748789/e2dbaa5c-eb6e-0338-7686-23ba0ae1e1b9.png)

![スクリーンショット 2022-10-15 12.40.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748789/a666dfdc-384f-740b-cc2f-145d55dba6d6.png)

![スクリーンショット 2022-10-15 12.40.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748789/80cbd9d3-7506-dde4-6a39-015dc8905a23.png)

全体的に見やすくするとこうなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748789/7b3c8a27-ba08-e4d3-2cea-7cec911a4ce9.png)

> 引用　　https://www.yamamanx.com/new-vpc-wizard-2022/

このように目で見てわかりやすいです。

![スクリーンショット 2022-10-15 12.43.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748789/f38b2fb5-4181-528f-754a-795da8409ac6.png)

![スクリーンショット 2022-10-15 12.43.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748789/a012c76c-cb7f-bead-0632-a9f89149552d.png)


# 参考資料

https://www.yamamanx.com/new-vpc-wizard-2022/
メモ(serialize,deserialize)

# Serialize,Edit,Deserialize
イメージ
serialize -> 製品を設計図にする　(インスタンス→byte)
deserialize -> 設計図を製品にする　(byte→インスタンス)

serialize -> edit -> deserialize
製品のままではいじれないところを設計図に落とし込んで(serialize)変更(edit)、変更した設計図を基に再度製品化(deserialize)する感じ?

Spigotプラグインで使う機会があったので書きました。
エンチャ本の内容を操作するのにItemStackをシリアライズしてMap<String,Object>にしてからEnchantmentStorageMeta(以後、Meta)を取得して弄る。弄ったMetaをデシリアライズしてItemStackにして終わり、という流れ。
なお、Spigotではシリアライズ化したデータであってもSpigot APIを通さずに直接編集すると怒られてエラーが出る場合があるので注意。

# 参考
https://qiita.com/NBT/items/9f76c9fd1c7a90506658
AWSのCloudFormationのCognitoで発生した「Property validation failure: [Encountered unsupported properties in {/AdminCreateUserConfig}: [TemporaryPasswordValidityDays]]」を解消する

# はじめに

AWSのCognitoのCFnがよく理解できておらず、少し修正するとエラーが発生するのでメモ。
元々作成していたCFnをアップデートしたら壊れました。なんでや！

# エラー

```
Property validation failure: [Encountered unsupported properties in {/AdminCreateUserConfig}: [TemporaryPasswordValidityDays]]
```

```元々動いてたCFn.yaml
  CognitoUserPool:
    Type: "AWS::Cognito::UserPool"
    Properties:
      UserPoolName:　"user-pool"
      AliasAttributes:
        - email
      AutoVerifiedAttributes:
        - email
      Policies:
        PasswordPolicy:
          MinimumLength: 8
          RequireUppercase: true
          RequireLowercase: true
          RequireNumbers: true
          RequireSymbols: true
      MfaConfiguration: 'OFF'
      AdminCreateUserConfig:
        AllowAdminCreateUserOnly: false
        UnusedAccountValidityDays: 7
```

```エラーが発生したCFn.yaml
  CognitoUserPool:
    Type: "AWS::Cognito::UserPool"
    Properties:
      UserPoolName:　"user-pool"
      AliasAttributes:
        - email
      AutoVerifiedAttributes:
        - email
      Policies:
        PasswordPolicy:
          MinimumLength: 8
          RequireUppercase: true
          RequireLowercase: true
          RequireNumbers: true
          RequireSymbols: true
      MfaConfiguration: 'ON'
      AdminCreateUserConfig:
        AllowAdminCreateUserOnly: false
        UnusedAccountValidityDays: 7
```

# 解決

## UserPoolClientを作成すると、「MfaConfiguration: 'ON'」が指定できない。

「OPTIONAL」なら指定可能。

ドキュメントには書いてない。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpool.html#cfn-cognito-userpool-mfaconfiguration

以下を参照して解決.


https://qiita.com/sugo/items/07a249405477e56163dd

# UserPoolClientを作成すると「AdminCreateUserConfig」の「UnusedAccountValidityDays」は使用出来ないらしい。

ドキュメントに書いてました。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-userpool-admincreateuserconfig.html

解決したコード
```yaml
  CognitoUserPool:
    Type: "AWS::Cognito::UserPool"
    Properties:
      UserPoolName: !Sub "${ServiceName}-users-pool"
      AliasAttributes:
        - email
      AutoVerifiedAttributes:
        - email
      Policies:
        PasswordPolicy:
          MinimumLength: 8
          RequireUppercase: true
          RequireLowercase: true
          RequireNumbers: true
          RequireSymbols: true
      MfaConfiguration: 'OPTIONAL'
      EnabledMfas: 
        - SOFTWARE_TOKEN_MFA
      AccountRecoverySetting: 
        RecoveryMechanisms: 
            - Name: verified_email
              Priority: 1
      AdminCreateUserConfig:
        AllowAdminCreateUserOnly: false
```
指定した数を素因数分解した値を表示するコード

# 指定した数を素因数分解した値を表示するコード
```Python:素因数分解.py
import tkinter as tk

def dispLabel():
    number= []
    a = int(EditBox.get())
    str_a = str(a)
    lbl2.configure(text = str_a + "=")

    while a!=1:
        for waruyatsu in range(2,a+1):
            if a%waruyatsu == 0:
                number.append(waruyatsu)
                number.append("×")
                a=int(a/waruyatsu)
                break

    number.pop(-1)
    lbl3.configure(text = number)

root = tk.Tk()
root.geometry("300x200")

EditBox = tk.Entry(width=6)
EditBox.place(x = 230, y = 20)

btn = tk.Button(text = "調べる", command = dispLabel).place(x = 60, y = 50)

lbl1 = tk.Label(text = "調べたい数字は何ですか？").place(x = 20, y = 20)
lbl2 = tk.Label(text = " ")
lbl2.place(x = 20, y = 80)
lbl3 = tk.Label(text = " ")
lbl3.place(x = 40, y = 80)

tk.mainloop()
```
## 例
![素因数分解.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2739883/0f37ad57-71d8-0648-3c4b-5b06ed652c2c.png)

![素因数分解_入力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2739883/4c82f421-bf9a-d761-ef9c-7668c4904477.png)

![素因数分解_例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2739883/e0b82b92-e093-dfae-919d-f91c9c98cca5.png)

## 作りたいもの
* タブ
* 質問文
* 数字を打ち込めるボックス
* 「調べる」と書かれた、押したら下に解を表示させるボタン
* ボタンを押したら計算して、解を求める関数

## 作りたいものに対応するコード
#### タブ
```Python
import tkinter as tk

root = tk.Tk()
root.geometry("300x200")
``
``
tk.mainloop()
```

#### 質問文
```Python
lbl1 = tk.Label(text = "調べたい数字は何ですか？").place(x = 20, y = 20)
```

#### 数字を打ち込めるボックス
```Python
EditBox = tk.Entry(width=6)
``
``
EditBox.place(x = 230, y = 20)
```

#### 「調べる」と書かれた、押したら下に解を表示させるボタン
```Python
btn = tk.Button(text = "調べる", command = dispLabel).place(x = 60, y = 50)
```

#### ボタンを押したら計算して、解を求める関数
```Python
def dispLabel():
    number= []
    a = int(EditBox.get())
    str_a = str(a)
    lbl2.configure(text = str_a + "=")

    while a!=1:
        for waruyatsu in range(2,a+1):
            if a%waruyatsu == 0:
                number.append(waruyatsu)
                number.append("×")
                a=int(a/waruyatsu)
                break

    number.pop(-1)
    lbl3.configure(text = number)
```


## 感想
* 割り切れた数字の商を再び割るためにはどうすればいいか、を考えるのに時間がかかった。
* 解を表示するときに素数の間にXをいれようとすると、どうしても一番右にも表示されてしまっていたので、どうやったら一個減らせるかを考えるのに悩んだ。
【Mysql入門】rootユーザーで開発はやめよう

## rootユーザーで開発するのはヤバい
Mysql、RDB、セキュリティの知識が皆無な自分は、これまでmysqlを使う際に常にrootユーザーで作業していました。mysqlでユーザーを新規作成するのがめんどくさく、やり方もよくわからなかったからです。

しかし、rootユーザーで作業するのはエンジニアとして無知をアピールしているようなものです。

## なぜrootユーザーで開発するのはヤバいのか？
これはセキュリティ的に大きなリスクが2点あります。
### リスク①デフォルトのパスワードが空欄になる
まずはこちらをご覧ください。
>MySQL サーバーを Unix root ユーザーとして絶対に実行しないでください。 これを行うと、FILE 権限を持つすべてのユーザーが、root としてサーバーにファイルを作成させることができるため (~root/.bashrc など)、非常に危険です。 これを防ぐために、mysqld は --user=root オプションを使用して明示的に指定された場合を除き、root として実行することを拒否します。

Mysqlはデフォルト状態だとrootユーザーのパスワードが空欄になっています。

そのためもしパスワードを変更していなかった場合、誰でもデータベースにアクセスできてしまいます。

対策としては初期設定時に以下の2点を実行します。
- パスワードを設定する
- そもそも外部からrootユーザーへのアクセスを禁止する

ただし、それでもrootユーザーは使うべきではありません。

### リスク②rootユーザーは全ての権限を持っている
rootユーザーは全ての権限を持っています。

セキュリティの基本として、権限は必要最低限にするべきです。

例：
- 全てのDBにアクセスできる　✕
- アプリケーションに必要なDBのみアクセスできる ◯

セキュリティインシデントが起きた場合を考えて、被害を最小限にできるように権限設定はしっかり行いましょう。

## ユーザーを作成しよう
自分で新しくユーザーを作成して、必要最低限な権限を与えてあげましょう。

**ユーザー作成するコマンド**
`CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';`
**権限を与えるコマンド**
`GRANT ALL ON dbname.* TO 'username'@'localhost';`
※権限を与えるコマンドは他にも色々あります。必要最低限になるように設定しましょう
権限設定→　https://qiita.com/shuntaro_tamura/items/2fb114b8c5d1384648aa

もうrootユーザーで開発するのはやめましょう。root、ダメ・ゼッタイ。

## 参考
https://qiita.com/Iruk_Nuj/items/badb5bf7856ca6936613
https://www.digitalocean.com/community/tutorials/how-to-create-a-new-user-and-grant-permissions-in-mysql-ja
Baby step Giant stepを完全に理解してABC270のG問題をRustで解く

# はじめに
これは[ABC270のG問題の解説](https://atcoder.jp/contests/abc270/editorial/4847)を読んでRustで実装したものです。

# Baby step Giant step について

[Wikipedia](https://en.wikipedia.org/wiki/Baby-step_giant-step)などで調べると、Baby step Giant stepは離散対数問題を解くアルゴリズムのようです。
素数$p$と$x, y$が与えられたとき、「$x^n\equiv y\mod p$を満たす$n$が存在するかどうか」を判定し、存在する場合は最小の$n$を求めることができます。

そのアルゴリズムは以下です。
1. 自然数$m$を決める。
1. （Baby step）$S=\lbrace y, y(x^{-1}), y(x^{-1})^2,\ldots,y(x^{-1})^{m-1}\rbrace$を求める。
1. (Giant step)$i=0,\ldots,\lfloor \frac{p}{m}\rfloor$ の順に以下を行う。
    1. $x^{im}$が$S$に含まれているか判定する。
        * $x^{im}$の計算はBaby step終了後に$x^m$を求めておくことで、$x^{im}=x^{(i-1)m}\cdot x^m$とすると効率的です。
    1. 含まれている場合は$x^{im}=y(x^{-1})^j$であるような最小の$j$を求める。$n=im+j$が条件を満たすので、ループを打ち切って終了する。

これは空間計算量$O(m)$、時間計算量$O(m+\frac{p}{m})$です。$m=\lfloor\sqrt{p}\rfloor$あたりで時間計算量が最小になります。

さて、このアルゴリズムを応用すると以下の問題も解くことができます。（こちらの方がABCの解説に近いです）

状態$s, g$および次の状態を返す関数$f(x)$が与えられる。$f^n(x)=y$を満たす$n\in\[0, N\]$が存在するか判定し、存在するならそのような$n$の最小値を求めよ。
ただし、$f$は以下の制約を満たしている。
* $f^m(x)$を高速に計算できる。
  * この計算に$O(m)$かかるようであれば全探索と効率が変わりません。
* $f^{-1}(x)$を求められる。
  * $f^{-1}(x)$がわからないとBaby step で$S$を構築できません。

# 実装

```rust
/// xからyにするにはfを何回適用すればいいか求める
/// # Arguments
///
/// * `x` - 開始状態
/// * `y` - 終了状態
/// * `max` - `f`を適用する回数の上限
/// * `m`, `f_m` - `x`に`f`を`m`回適用したときの状態
/// * `f_inv` - `f`の逆関数
///
/// # Returns
/// * `Some(n)` - `f^n(x)=y`であるような最小の`n`
/// * `None` - 'max`回以下では`x`を`y`にできない
///
fn baby_step_giant_step<T, FM, FINV>(x: T, y: T, max: usize, m: usize, f_m: FM, f_inv: FINV) -> Option<usize>
where
	T: Copy + Eq + std::hash::Hash,
	FM: Fn(T) -> T,
	FINV: Fn(T) -> T
{
	let mut result = None;
	let mut candidates = std::collections::HashSet::new();
	let mut candidate = y;
	for _j in (0..m).rev() {
		candidates.insert(candidate);
		candidate = f_inv(candidate);
	}

	let mut fmx = x;
	for i in 0..=max/m {
		if candidates.contains(&fmx) {
			let mut v = f_m(fmx);
			for j in (0..m).rev() {
				v = f_inv(v);
				if v == y {
					result = Some(i * m + j);
				}
			}

            break;
		}

        fmx = f_m(fmx);
	}

	result
}
```

実際にABC270のG問題をACした解答は[こちら](https://atcoder.jp/contests/abc270/submissions/35152746)
FlutterにFirebaseの導入が超簡単便利に！FlutterFireを使用する

### はじめに
今までのFirebase導入手順とかどうでも良い！という方は「[2.FlutterFireを使用する](#2flutterfireを使用する) 」からご覧ください。

### 1.今までの手順
FlutterでのiOS/Androidアプリケーション開発でFirebaseを導入するには
次のような手順が必要になっていました。
  
まずはFirebaseで新規プロジェクトを作成します。
次にAndroid、iOSそれぞれにFiorebaseを導入していきます。
##### ■Android
1. Androidパッケージ名を入力
1.1. android/app/src/main/AndroidManifest.xmlを開く
1.2. package="xxx.xxxxx.xxxxx" 「" "」の中がパッケージ名
1. 「アプリを登録」を選択
1. google-service.jsonをダウンロード
1. ダウンロードしたjsonファイルを android/app 配下に配置
1. Firebase SDKの追加
6.1. プロジェクトレベルのbuild.gradleのdependenciesにclasspathを追加
6.2. アプリレベルのbuild.gradleにapply pluginを追加
6.3. アプリレベルのbuild.gradleのdepecdenciesにimplementationを追加
1. FirebaseのコンソールにAndroidアプリが追加されていることを確認
#### ■iOS
※前提：Macを使用していて、Xcodeの準備ができていること
1. iOSバンドルIDを入力
1.1. Finderで自信のプロジェクトのios/Runner/Runner.xcworkspaceをXcodeで立ち上げる
1.2 Runnerを選択
1.3 Bundle Identifireに記載されているパッケージ名をコピペ
1. 「アプリを登録」を選択
1. GoogleService-Info.plistをダウンロード
1. ダウンロードしたplistファイルを Runner/Runner 配下に配置

pubspec.yamlにfirebase_core: ^x.x.xを追加　xはバージョン

以下をmain.dartのmain関数に追加
```
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
```

ファイルダウンロード、配置、コードを書き換えたりと、かなり面倒でした。。。

### 2.FlutterFireを使用する

https://firebase.flutter.dev/docs/overview
↑こちらでやることを簡単にまとめて記載していきます。

1.従来と同じように、まずはFirebaseで新規プロジェクトを作成
2.自身のプロジェクトのターミナルで以下のコマンドを実行
```
flutter pub add firebase_core
```
3.pubspec.yamlファイルに「firebase_core: ^x.x.x」が追加されていることを確認　xはバージョン

4.Firebase CLIを導入 ※一度導入すればOK! 導入済みの方は次へ
　https://firebase.google.com/docs/cli
　CLIが導入できていれば、ターミナルでfirebaseコマンドが実行出来るはず

5.ターミナルでコマンドを実行してfirebaseにログイン
```
firebase login
```
　コマンドを実行すると以下のように聞かれるので「Y」を入力
```
? Allow Firebase to collect CLI and Emulator Suite usage and error reporting information?  (Y/n)
```
　googleログインページが立ち上がるので、ログインする

6.次のコマンドを実行
```
dart pub global activate flutterfire_cli
```
```
export PATH="$PATH":"$HOME/.pub-cache/bin"
```
```
flutterfire configure
```
　コマンドを実行すると、自身のプロジェクトが一覧表示されるので、方向キーで選んで選択
　色々聞かれたら「Y」でEnter

7.自身のプロジェクトの lib配下に「firebase_options.dart」が作成されていればOK
8.以下の4行のコードを「main.dart」のmain関数にコピペ
```
// main関数をasyncにするのを忘れずに
void main() async {
  // この下から4行
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(MyApp());
}
```
9.main関数の「Firebase」と「DefaultFirebaseOptions」でエラーが発生するのでインポートで解決

以上でFirebaseの導入、連携が完了です。
いちいちファイルをダウンロード、配置などの手間もなくなり
Firebase CLIさえ導入していれば、びっくりするほど簡単になりました。
【AWS】AWSのReserved Instance (RI)とは？(ElastiCacheのRI購入方法も紹介)

## はじめに
業務で AWS の ElastiCache の Reserved Node を購入する機会があったということもあり、Reserved Instance (RI) の知識定着のために記事をまとめたいと思います。

## Reserved Instance(RI)とは？
事前にインスタンスサイズと数を 1年 or 3年 で予約しておくことにより、1ヶ月毎にかかる料金を削減できるものになります。

例えば、EC2 Instance の場合、 `Linux/UNIX` の サイズ(`t3.small`) を 2つ「1年間使います！」という形で事前予約しておくことによって、`Linux/UNIX` の サイズ(`t3.small`)を2つ使用した場合の料金が自動的に割引になるという仕組みです。

### RIが購入できるマネージドサービス
RIが購入できるマネージドサービスは以下のようなものがあります。

| RIの種類  |  サービス  |
| ---- | ---- |
|  Reserved Instance  |  Amazon EC2<br>Amazon RDS<br>Amazon OpenSearch Service Service  |
|  Reserved Cache Nodes  |  Amazon ElastiCache  |
|  Reserved capacity  |  Amazon DynamoDB  |
|  Reserved Nodes  |  Amazon Redshift  |

詳細はサービス毎にことなりますが、どれも以下のようになっております。

- 1年 or 3年のプランがある
- サイズと数を選択して購入(事前予約)をする

## RIの購入方法
僕が実際に経験がある `ElastiCache` のRIを購入する際の手順についてついでにご紹介します。
(2022/09/24時点での手順になります。)

### ElastiCache のダッシュボードより `Reserved nodes` を選択し、「Purchase reserved nodes」をクリック

![スクリーンショット 2022-09-24 17.02.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/d58a8838-7e3f-9653-654f-4a6e2ce1f325.png)

### Purchage reserved nodes より項目を選択する。

![スクリーンショット 2022-09-24 17.03.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/cad3e083-3964-b56d-f040-dfa30da6f52d.png)

|  項目  |  Engine  |
| ---- | ---- |
|  Engine  |  `Redis` か `Memcached` を選択  |
|  Node type  |  購入したい Node Type を選択  |
|  Term  |  1year か 3year を選択 |
|  Offering type  | 使用頻度を選択(使用頻度によって割引率が異なる) |
|  Reserved node ID  | 任意のIDを設定(分かりやすい名前を設定) |

### Number of nodes に購入したいnode数を入力し、かかる金額を確認する。

![スクリーンショット 2022-09-24 17.03.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/c81fe48e-9f1c-935d-0521-eade178b211d.png)

### Usage charges で1時間毎にかかる料金を確認し、`Purchase` をクリックする。

Tags は任意で設定。

![スクリーンショット 2022-09-24 17.03.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/76a71250-3def-375d-442d-d7a83d1fef72.png)

`Purchase`をクリックすると購入され、選択した `Node type` に合致するインスタンスが購入した台数分あれば、自動的に割引が適用される。

## 参考
- AWS
    - [Amazon EC2 Reserved Instances](https://aws.amazon.com/ec2/pricing/reserved-instances/?nc1=h_ls)
    - [Amazon RDS Reserved Instances](https://aws.amazon.com/rds/reserved-instances/?nc1=h_ls)
    - [Reserved Instances in Amazon OpenSearch Service](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/ri.html)
    - [Amazon ElastiCache Reserved Nodes](https://aws.amazon.com/elasticache/reserved-cache-nodes/?nc1=h_ls)
    - [Read/write capacity mode](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html)
    - [Purchasing Amazon Redshift reserved nodes](https://docs.aws.amazon.com/redshift/latest/mgmt/purchase-reserved-node-instance.html)
- 他のサイト
    - [AWSリザーブドインスタンス（RI）とは？
](https://www.sunnycloud.jp/column/20201222-01/)
マイチートシート

//---------------------------------
// サクラエディタ
//---------------------------------

【右端で折り返さない】
「設定」→「タイプ別設定」→「スクリーン」タブ→「レイアウト」→折り返し方法→折り返さない

【URLリンク外し】
設定→タイプ別設定→カラー→URLのチェックを外す

【パスリンク外し】
設定→タイプ別設定→正規表現キーワード→色指定「URL」のキーワードを色指定「テキスト」に変更

【ダブルクリック起動、アプリケーション関連付け】
設定→タイプ別設定一覧→左ペインから関連付けたい拡張子選択
→「右クリックメニューに追加」をチェック済みにする。「ダブルクリックで開く」をチェック済みにする。

【マクロ、スクリプト】
１．マクロ配置
例
```format_clean.mac
ReplaceAll('[ 　\\t]+$', '', 36);	// すべて置換
ReDraw(0);	// 再描画
```

２．マクロ登録
「設定」＞「共通設定」＞「マクロ」
参照ボタン：マクロファイルのある場所を指定
名前：登録するマクロ名を決める
Fileプルダウン：マクロファイルを選択

３．マクロ使用
「ツール」＞「登録済みマクロ」

　

//---------------------------------
// PowerShell
//---------------------------------

【batで実行】
```ps実行.bat
powershell -ExecutionPolicy RemoteSigned -File "C:\script\sample.ps1"
```

　

//---------------------------------
// git-bash
//---------------------------------
【テキストファイル分割】
cd /C/mydir
split -l 100000 -d bigfile.txt bigfile.txt.

【テキストファイル末尾取得】
cd /C/mydir
tail -n 100000 bigfile.txt > bigfile.txt.tail
Gatsby.js & Wordpress カスタム投稿のタクソノミー名をGraphQL に含める方法

# はじめに
WordPressを使用してHeadlressCMSを構築する時、タクソノミー名が取得できなかったので、そのメモです。


# 問題
Wordpressで構築するとカスタム投稿を利用することが多いと思います。
そして、そのカテゴリーも一緒に実装するかと思うのですが、そのカテゴリーをGraphQLで上手く取得することができない！
ということで、いろいろ試してようやく実装できたのでメモしたいと思います。


# 現象

https://gray-code.com/wordpress/getting-custom-post-by-graphql/

こちらを参考にタクソノミーもGraphQLに含める記述をfunctions.phpに追記しましたが、私の環境ではidしか取得できませんでした。。

理想はnameとid両方の取得です！
ですが、IDしか取得できていません。。

![スクリーンショット 2022-09-25 12.04.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483702/650cb551-7d66-82a0-3c34-bf821cf5474b.png)

![スクリーンショット 2022-09-25 12.04.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483702/8e6fce99-7219-c541-0af9-e51b0f99e44a.png)

今回はinterview_categoryという名のタクソノミーです。


# 結論
REST APIのレスポンスにタクソノミー名とIDを含めて戻せば取得できました！
以下のような感じです。

``` functions.php

add_action('rest_api_init', 'add_api_fields');
function add_api_fields()
{
register_rest_field(
  // カスタム投稿名
  'interview',
  // ユニークなキー定義
  'interview_cat',
  array(
    'get_callback' => function ($data) {
      $category_terms = wp_get_post_terms(
        $data['id'],
        'interview_category'  // ここにタクソノミー名
      );
      $interview_categories = array();
      foreach ($category_terms as $term) {
        $interview_category_obj       = new StdClass();
        $interview_category_obj->ID   = $term->term_id;
        $interview_category_obj->name = $term->name;
        array_push(
          $interview_categories,
          $interview_category_obj
        );
      }
      return $interview_categories;
    },
  )
);
}

```

これでinterview_catというエンドポイントが追加され、その中に名前とIDが含まれて取得できました！！
（最初の記事で設定したIDのみ取得できるinterview_categoryも残ってます）

![スクリーンショット 2022-09-25 18.06.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483702/a156f32a-f45d-90c1-3d43-eab9944eda30.png)

![スクリーンショット 2022-09-25 18.06.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483702/0a06a278-050b-d005-33f7-aa03b1e15d0f.png)




参考は以下のサイトです。

https://wp-qa.com/gatsby-using-graphql-query-on-custom-post-type-with-custom-taxonomy

ただ、こちらのサイトは間違っていて、、サイト通りに記述するとIDが取得できませんでした。。
ですので、以下に修正する必要がありました。

``` php

$portfolio_category_obj->ID   = $term->ID;
↓
$interview_category_obj->ID   = $term->term_id;

```

これは、

``` php
 $category_terms = wp_get_post_terms
```

でwp_get_post_termsの戻り値で指定しないとダメなので、

https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/wp_get_post_terms

こちらで調べるとIDはterm_idと書いてあったので修正したところきちんと取得できました。


# 余談
WordPressのカテゴリーは取得するのが結構複雑で、投稿の種類により取得する変数名が違ったりします。。
Wordpressに詳しくないと、その辺り戸惑うかもしれません。。

WP標準の投稿：カテゴリー、タグ
　↓　　　　　　　↓　　　　　↓
カスタム投稿：タクソノミー、ターム

丁寧に説明しているサイトがいくつかあるので、良くわからない方はそちらを参考にして見て下さい。

以上です。


# 訂正
※ 一部間違えておりましたので、修正しました。（2022.9.25）
「Their offer: diffie-hellman-group1-sha1,diffie-hellman-group14-sha1」と表示され、SSH接続できないときの対策

### 解決方法　「.ssh/config」の作成
``` console:.ssh/config
HOST ipアドレス
KexAlgorithms +diffie-hellman-group1-sha1,diffie-hellman-group14-sha1
Ciphers aes128-cbc
```
エルビス演算子を使うときの注意点

## 前置き
三項演算子を省略できる書き方で、エルビス演算子「?:」というものがありますが、
自分が間違えた使い方をしていた為、共有したいと思い記事にしました。

## エルビス演算子の間違えた使い方
```php
    $a = 15;

    $b = $a === 15 ?: 17;
```

私は、この＄bの期待値としては「15」であると思っていました。
しかし、この＄bの値は「true」になっていました。

これは「＄a === 15」の結果がtureの為、三項演算子の条件式的には「＄a === 15」を返します。
言い換えると下記のようなコードに置き換えることができます。
```php
    $a = 15;

    $b = $a === 15 ? $a === 15: 17;
```
これを見ると＄bの値は「true」になるのがわかります。これと同じ現象が起きているというわけです。

## エルビス演算子の正しい使い方
```php
    $a = 15;
    $b = $a ?: 17;

    //言い換えると

    $a = 15;
    $b = $a ? $a : 17;
```

＄aがtrueと同等の場合は「15」、それ以外の場合は「17」になります。それ以外の場合というのは「false, null, 0, '', [] 」あたりです。


## まとめ
エルビス演算子について紹介しました。
正しく使うとコードが短くなる、わかりやすくなる、読みやすくなる、といったメリットがあります。
是非使ってみてはいかがでしょうか？

## 参考文献
【PHPなど】エルビス演算子 ?: 本当にエルビス・プレスリーだった【画像あり】
https://qiita.com/ito_gen/items/7650454fbb27baefc1f7
PHPの便利な演算子でコードを短くしよう！
https://learningbox.co.jp/2021/06/15/blog_php-code/
[ABC270] A,B,CをPythonで解いてみる

## はじめに

初投稿になるが、コンテスト中に今までできなかったことができたことからその記念(?)も兼ねて投稿する。


## [A - 1-2-4 Test](https://atcoder.jp/contests/abc270/tasks/abc270_a)

配点が1,2,4点とあるので2進数で考える。
少なくとも一方が解けた問題は解け、2人とも解けなかった問題は解けないとあるので論理和をとればよい


```Python:a.py
A,B = map(int,input().split())
print(A|B)
```

## [B - Hammer](https://atcoder.jp/contests/abc270/tasks/abc270_b)

XとYの位置関係から先に考えて、経路に壁がある場合にZが壁より原点寄りにあるか考える。

ゴールに到達可能なのは以下のパターンである。
- X,Yが異符号 (1)
- X,Yが同符号
    -  XがYより壁寄り (2)
    -  ZがYより壁寄り (3)

(3)に関しては、Xへの最短経路にZがない場合(X,YとZが異符号)の場合はZを経由する必要があることに注意する。

```Python:b.py
import sys

X,Y,Z = map(int,input().split())

if X*Y < 0:
    print(abs(X))
    sys.exit()

if X * Y > 0 and abs(X)<abs(Y):
    print(abs(X))
    sys.exit()

if X < 0 and Y < 0 and Y < Z:
    if Z > 0:
        print(abs(2*Z-X))
        sys.exit()
    else:
        print(abs(X))
        sys.exit()


if X > 0 and Y >0 and Y > Z:
    if Z > 0:
        print(abs(X))
        sys.exit()
    else:
        print(abs(2*Z-X))
        sys.exit()

print(-1)

```

(3)は(1),(2)のように絶対値を使ってスマートに書きたかったがいい方法が思いつかなかったので保留。
`sys.exit()`を至る所につけるのがなんとも言えぬ、、、

## [C - Simple path](https://atcoder.jp/contests/abc270/tasks/abc270_c)

公式解説では深さ優先探索で行っていたが、本番中は幅優先探索で解いた。
今回の問題で大変なことは、スタートからの最小コストを格納した変数を使って当該の目的地への最短パスを求めることである。(これが初で戸惑った)

手順は以下のとおりである。
1. `defaultdict`を使って木を管理
1. BFSでスタートからの最小コストを求める
1. `defaultdict`を使ってkeyをコスト、valueをそのコストでいけるノードとする変数を管理
1. ゴールから逆算してスタートまでの経路を記録
1. 4の配列を逆で表示


```Python:c.py
from collections import defaultdict, deque

tree = defaultdict(list)

N,X,Y = map(int,input().split())


# 1
for i in range(N-1):
    u,v = map(int,input().split())
    tree[u].append(v)
    tree[v].append(u)

history = [-1]*(N+1)
history[X] = 1

def bfs(T,i):
    Q = deque([i])
    while Q:
        q = Q.popleft()
        for c in T[q]:
            if history[c] == -1:
                history[c] = history[q] + 1
                Q.append(c)
# 2
bfs(tree,X)

# 3
root = defaultdict(list)
for i in range(1,len(history)):
    root[history[i]].append(i)

# 4
ans = [Y]
now = Y
for i in range(history[Y]-1,0,-1):
    for j in root[i]:
        if j in tree[now]:
            ans.append(j)
            now = j

# 5
print(*ans[::-1])
```
4に関して、ゴールからスタートして、辿ることのできるノードかつコストが辿る前の`-1`であるものは今回の場合一意に定まるため上記の処理で実装できる。計算量的には問題ないが、もっとスマートな書き方で行先のノードを求める方法がある気がする。


## 最後に
コンテスト中は速さ重視で使い捨てのようなコードを書いてしまうが、詰まったとき原因に気づくのが遅くなるため決めたルールに従って書くようにしたい。
一発 AC への第一歩:AB Substring 

# [問題](https://atcoder.jp/contests/diverta2019/tasks/diverta2019_c)
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/93a824e1-f7e1-cdce-82d6-29669d908679.png)
# 考察
ザックリ以下のアプローチが必要となることが分かる。
i).入力 _Si_ に _"AB"_ が何個入っているかカウント
ii).任意に文字列を連結した際に _"AB"_ が出来るケースをカウント

&emsp;カウント時の注意点
&emsp;&emsp;例えば B※※A + B※※A + B※※A の場合、AB は 2 個になる。
&emsp;&emsp;**B※※※/※※※A と B※※A を混在**させてカウントすると上記に辿り着けない

よって、以下のように B※※※, ※※※A, B※※A を分けて考えよう

&emsp;Case1&emsp;※※※A + B※※※ = ※※※AB※※※
&emsp;Case2&emsp;B※※ A + B※※※ = B ※※AB※※※
&emsp;Case3&emsp;※※※A + B※※A  = ※※※AB※※A
&emsp;Case4&emsp;B※※A + B※※A  = B※※AB※※A

Case1 ~ Case4 で、どれを優先すれば "AB" が最大になるのか。
<font color="LimeGreen">B※※A</font>,<font color="LimeGreen">B※※A</font>,<font color="Blue">B※※※</font>,<font color="Red">※※※A</font>,<font color="Red">※※※A</font> を例に考える。

&emsp;<font color="LimeGreen">B※※**AB**※※**A**</font><font color="Blue">**B**※※※</font><font color="Red">※※※A</font><font color="Red">※※※A</font>　=> 2個
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;or
&emsp;<font color="LimeGreen">B※※**AB**※※A</font><font color="Red">※※※**A**</font><font color="Blue">**B**※※※</font><font color="Red">※※※A</font>　=> 2個
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;or
&emsp;<font color="Red">※※※**A**</font><font color="LimeGreen">**B**※※**AB**※※A</font><font color="Red">※※※**A**</font><font color="Blue">**B**※※※</font>　=> **3個**
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;or
&emsp;<font color="Red">※※※**A**</font><font color="LimeGreen">**B**※※**AB**※※**A**</font><font color="Blue">**B**※※※</font><font color="Red">※※※A</font>　=> **3個**

よって、以下の式で対応できそうだ。
&emsp;&emsp;**<font color="LimeGreen">B※※A</font> の個数+ min(<font color="Red">※※※A</font>の個数 , <font color="Blue">B※※※</font>の個数)**

しかし、冒頭に少しコメントした注意点を思い出す。
それは入力が <font color="LimeGreen">B※※A</font> only の場合だ。

&emsp;<font color="LimeGreen">B※※**AB**※※A</font>　=> 1個
&emsp;<font color="LimeGreen">B※※**AB**※※**AB**※※A</font>　=> 2個
&emsp;<font color="LimeGreen">B※※**AB**※※**AB**※※**AB**※※A</font>　=> 3個

よって、以下の式で対応できそうだ。
&emsp;&emsp;**<font color="LimeGreen">B※※A</font> の個数 - 1**

# 実装

```ABsubstrings.cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main() {
	int N; cin >> N;
	vector<string>num(N, "");

	for (int i = 0; i < N; i++) {
		cin >> num[i];
	}

	int cnt=0,ABcnt = 0, Acnt = 0, Bcnt = 0;
	for (auto S : num) {
		for (int i = 0; i < S.size() - 1; i++) {
			if (S.substr(i, 2) == "AB")
				cnt++;
		}
		if (S[0] == 'B' && S[S.size() - 1] == 'A')
			ABcnt++;
		else if (S[0] == 'B')
			Bcnt++;
		else if (S[S.size() - 1] == 'A')
			Acnt++;
	}

	if (Acnt == 0 && Bcnt == 0)
		cout << cnt + max(ABcnt - 1, 0);
	else
		cout << cnt + ABcnt + min(Acnt, Bcnt);

	//while (1) {}
	return 0;

}
```
Splunk: 判定処理における NULL の扱いについて


###### 実施環境： Splunk Free 8.2.2

### 0. 概要

 Splunk では対象のフィールドに値が入っていない場合、 NULL として扱われます。
この NULL は、空文字列や 0 とは明確に別のものです。
今回は判定処理においてこの NULL を処理した場合の挙動について紹介していきます。

### 1. 使用するデータ

今回は、以下のデータをもとに確認していきます。

```Splunk:Splunk
| makeresults count=3
| streamstats count AS CNT
| eval NULL  = if( CNT == 1, null(), CNT),
       EMPTY = if( CNT == 2, "", CNT),
       ZERO  = if( CNT == 3, 0, CNT)
| fields - CNT, _time
```

![WS000157.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/42cf15d9-ff0c-6be5-0bb5-5bd227cee376.jpeg "元データ")

| EMPTY | NULL | ZERO |
|-:|-:|-:|
| 1 | (NULL) | 1 |
| (空文字列) | 2 | 2 |
| 3 | 3 | 0 |

### 2. 通常の比較

比較演算子を用いた通常の比較において、両辺のどちらか一方でも NULL 値の場合は、常にその条件式は「偽」となります。
下記の条件式も、同一の値について等しいかどうかの確認なので NULL 値も当然「真」となるように思いますが、 NULL 値の場合のみ「偽」となっています。

```Splunk:Splunk
| makeresults count=3
| streamstats count AS CNT
| eval NULL  = if( CNT == 1, null(), CNT),
       EMPTY = if( CNT == 2, "", CNT),
       ZERO  = if( CNT == 3, 0, CNT)
| fields - CNT, _time
| eval NULL_IF  = if( NULL  == NULL,  "OK", "NG"),
       EMPTY_IF = if( EMPTY == EMPTY, "OK", "NG"),
       ZERO_IF  = if( ZERO  == ZERO,  "OK", "NG")
```

![WS000223.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/3bc28fd7-ccd3-42a6-177c-23b45cdcff98.jpeg "if")

### 3. NOT を使用する比較

 NOT 演算子は条件の真偽を反転させる演算子ですが、その処理において NULL 値が関与しているかどうかは判定しません。
そのため下記のように同一の値について異なるかどうかを判定してその結果を反転させる場合、結果は NULL 値も含めて「真」となります。

```Splunk:Splunk
| makeresults count=3
| streamstats count AS CNT
| eval NULL  = if( CNT == 1, null(), CNT),
       EMPTY = if( CNT == 2, "", CNT),
       ZERO  = if( CNT == 3, 0, CNT)
| fields - CNT, _time
| eval NULL_IF  = if( NOT NULL  != NULL,  "OK", "NG"),
       EMPTY_IF = if( NOT EMPTY != EMPTY, "OK", "NG"),
       ZERO_IF  = if( NOT ZERO  != ZERO,  "OK", "NG")
```

![WS000224.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/f82f7dcb-5a93-3867-6597-e179ee43f19a.jpeg "NOT")

| A | A == A | A != A | NOT A != A |
|-:|-:|-:|-:|
| NULL | 偽 | 偽 | 真 |
| その他 | 真 | 偽 | 真 |

### 4. 評価関数 を使用する比較

 where コマンドや eval コマンドといった評価関数を使用する比較の場合、 NULL 値について判定を行える関数があります。
それが NULL 値の場合に真となる isnull 関数と、 NULL 値の場合に偽となる isnotnull 関数です。

```Splunk:Splunk
| makeresults count=3
| streamstats count AS CNT
| eval NULL  = if( CNT == 1, null(), CNT),
       EMPTY = if( CNT == 2, "", CNT),
       ZERO  = if( CNT == 3, 0, CNT)
| fields - CNT, _time
| eval NULL_IF  = if( isnull(NULL),  "OK", "NG"),
       EMPTY_IF = if( isnull(EMPTY), "OK", "NG"),
       ZERO_IF  = if( isnull(ZERO),  "OK", "NG")
```

![WS000225.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/02f08995-7e38-5dd9-2489-325a3f7f6836.jpeg "isnull")
【Salesforce】各サンドボックスの特徴


## Developer

- 本番組織の設定 (メタデータ) のコピーが入る

- 機能単位の開発に使う容量の小さいサンドボックス

- 毎日更新できる

- データストレージ: 200MB  
  ファイルストレージ: 200MB

## Developer Pro

- 本番組織の設定 (メタデータ) のコピーが入る（Developerと同じ）

- Developerより容量が大きい

- 毎日更新できる

- データストレージ: 1GB  
  ファイルストレージ: 1GB

## Partial Copy

- 以下が入る

    - 本番組織の設定 (メタデータ) のコピー

    - Sandbox テンプレートで定義されている本番組織のデータのサンプル

- UATを行うのに向いている

- 5日おきに更新できる

- データストレージ: 5GB  
  ファイルストレージ: 本番と同じ

## Full

- すべてのデータ (オブジェクトレコード、添付ファイルなど) とメタデータが入る

- 用途など

    - 本番組織の複製であり、ステージング

    - パフォーマンステスト、負荷テストを行うのに最適

    - 更新間隔が長いため、開発には向いていない

- 29日おきに更新できる

- データストレージ: 本番と同じ
  ファイルストレージ: 本番と同じ

## 参考文献

- [Sandbox の種別およびテンプレート](https://help.salesforce.com/s/articleView?id=sf.create_test_instance.htm&type=5)

- [Sandbox の更新](https://help.salesforce.com/s/articleView?id=sf.data_sandbox_refresh.htm&type=5)

- [種類別 Sandbox ライセンスおよびディスク使用制限](https://help.salesforce.com/s/articleView?id=sf.data_sandbox_environments.htm&type=5)

- [【実践＆検証】Sandboxの更新│OPT PLANNING ブログ｜広島のWebシステム開発](https://opt-p.co.jp/blog/salesforce-sfdc/post-1527/)

- [SFDC SandBOx リフレッシュ時間 - Memos About Salesforce](https://salesforce.oikeru.com/entry/sandbox_ref_time)
【Swift】フォトライブラリでの写真の複数選択を実現する（高画質化）

# はじめに
写真アプリで「フォトライブラリから写真を複数同時に取り込む機能」を実装しようとした際に、
[こちら](https://qiita.com/kozitex/items/7f71000d8dca521941f8)の記事を参考にしたのですが、ハマったことがあったので、記事にしてみようと思いました。

ハマった点は以下の３点です。
* 単純に複数画像を選択するだけなら「imageManager.requestImage」を使えばいいのですが、この場合選択した画像がかなり低画質になってしまい使い物にならなかった。
* Storyboadを使わずにコードでUIを設定していたので他の機能を追加しづらかった。
* 長押しドラッグ（？）で複数選択ができない。（未実装）

# 本題
基本的なことは[元ネタの記事](https://qiita.com/kozitex/items/7f71000d8dca521941f8)を見てください。
また、[元ネタの記事](https://qiita.com/kozitex/items/7f71000d8dca521941f8)同様コードが長く重すぎるのでコードはGitHubに公開しておきました。
https://github.com/YoshihisaTanaka-prog/PhotosMultiSelect

## 変更点

### 高画質化

まず、以下の部分を以下に書き換えました。

~~~ LibraryPhotoViewController.swift(before) (220-230行目付近)
    imageManager.requestImage(for: asset, targetSize: thumbnailSize, contentMode: .aspectFill, options: nil, resultHandler: { image, _ in
        if image == nil {
            print("managerError")
        } else {
            self.items.append(image! as UIImage)
        }
    })
~~~


~~~ LibraryPhotoViewController.swift(after) (220-230行目付近)
    imageManager.requestImageDataAndOrientation(for: asset, options: nil, resultHandler: { data, _, _, _ in
        if data == nil {
            print("managerError")
        } else {
            if let image = UIImage(data: data!){
                self.items.append(image)
                if(self.items.count == indexPaths.count){
                    self.mainView.items = self.items
                    self.mainView.photoCollectionView.reloadData()
                    self.dismiss(animated: true, completion: nil)
                }
            }
        }
    })
~~~

しかし、このまま状態では非同期処理を行うためメインの画面に全く反映されなかったので「DispatchQueue.main.async」を追加しました。

~~~ LibraryPhotoViewController.swift(add DispatchQueue) (220-230行目付近)
    imageManager.requestImageDataAndOrientation(for: asset, options: nil, resultHandler: { data, _, _, _ in
        if data == nil {
            print("managerError")
        } else {
            if let image = UIImage(data: data!){
                DispatchQueue.main.async {
                self.items.append(image)
                    if(self.items.count == indexPaths.count){
                        self.mainView.items = self.items
                        self.mainView.photoCollectionView.reloadData()
                        self.dismiss(animated: true, completion: nil)
                    }
                }
            }
        }
    })
~~~

**(追記2022-09/29)
このままでは画像の順番がバラバラになってしまうのでもう少し修正しておきました。
詳しくはGitHubのコードを見てください。一応大まかに何をしたのかを書いておきます。**

1. 同期処理部分にUIImage配列の要素を追加するようにし、非同期部分にindexを送りその部分を上書きするようにしました。
2. 全てを上書きしたかどうかを確認するためのBoolean配列を作り、上書きが全て完了した時点で最初の画面に戻るようにしました。

**(ここまで追記です)**

これでうまく動くようになりました。


### Storyboadの対応

Storyboadへの対応は特筆すべき点はありません。


### 長押しドラッグ選択の対応
未実装です。
Markdown記法主要メモ

# READMEの為のMarkdown記法  
  
## 見出し  
  
   
先頭の「＃」の数を1-6の間で選び、大きさを決める。数が増えるほど、見出しは小さくなる。  
  
  
## 改行  

スペース2つを文末に入れる。  
  
  
## 文字の装飾   
  
*「**」、もしくは「__」で囲うとイタリック体  
＜em＞になる。  
*「** **」「__ __」は太字。 
* 3つになるとイタリック体太字。  
* 「~~ ~~」は打ち消し線。
* [" と "] はメニューボタンの外観。
* [’ と ’] はキーボードのキーの外観。  
  
    
## リスト   
  
先頭に「*」で箇条書きリスト。(+、-も可)
数字 ＋ 「.」でナンバリングリスト。
半角スペース2つ以上字下げで、入れ子に出来る。
  
## チェックボックス  
  
リストの記法に[x]もしくは[ ]でタスクの表示。
[x]は完了、[ ]は未完。  
  
## 定義  
  
* 2行目先頭「:」＋ 1つ以上のスペースで、  1行目の内容を定義するリスト表示。1行目に下記を付与で、  
  * {.note}    ・・・ メモ
  * {.tip}     ・・・ ヒント
  * {.info}    ・・・ 情報
  * {.warning} ・・・ 注意
  * {.caution} ・・・ 警告
を付箋形式に。付箋が連続する場合は、  
<!---->で区切る。1行目は省略可。  
  
## リンク    
* 先頭に[テキスト]: (URL)でリンク表示。  
* 上の文末に{target="_blank"}で、  リンク先を新しいタブで開く。  
* <>か[]で囲むとリンクのみの表示。  メールは<>のみ対応。
  
## 画像  
  
リンクの記述の先頭に「!」で画像。
左右に寄せたい場合は、スペース ＋ {.left}  など。影付けはスペースなし{.dropshadow}  
  
## テーブル  
  
|-----|:-----|
「：」で文字の寄せる方を決める。
  
## 引用  
    
先頭が「＞」。入れ子可。
俯瞰的考え気づく客観が存在しない空集合と 

「俯瞰的に考えて、ふと気づく。」という書き込みをあるSNSで拝見した。　

何に気づいたかを推測して質問する前に、何に気づいて欲しいかを短歌形式で書き込ませていただいた。　

「俯瞰的考え気づく客観が存在しない空集合と」　短歌　

# 俯瞰と客観　

## 俯瞰
俯瞰は、物事を上から眺める場合に使う言葉と理解している。　

## 客観　
客観には、２つの意味と１つの構造がある。　

### 主客　
主人と客人の関係で、主人が第一者、客人が第二者で、両方とも当事者である。　
客の視点で見ることはとても大事だ。　

## 非当事者　

当事者が二人いて、その当事者以外を客観的ということがある。　
当事者の一人が第一者で、もう一人が第二者である。　
非当事者が第三者である。　

#### 舞台　
舞台芸術の場合に舞台にあがっている人が、複数人いれば、舞台上に第一者と第二者がいて、お客様は第三者という関係になる。　
この場合、舞台という枠組みでみれば、舞台上にいるのが当事者で、お客様は非当事者で第三者になる。 

## 入れ子構造　
舞台の例で、舞台のある劇場の中にいる人を当事者として捉えると、　
舞台上にいる人が第一者で、お客様は第二者で、劇場の外にいる人が第三者になる。　

舞台とか、劇場の話題を読んだり見たり、記事を書いたり、喋ったりしている人を関係者として当事者と考えると、劇場の外にいる人も当事者となる。そして、舞台、劇場の話題に全く触れていない人が第三者となる。　

地球を舞台として考えれば、地球上で生きている人は、すべて第一者で、第二者は、将来生まれてくる人たちだろう。過去に生きていた人たちは、現在に影響を残している可能性があり、第三者とはいいにくい。

このように、空間定義を一つ大きな枠で定義すれば、第三者というものは、ほとんど存在しないことがわかるかもしれない。

客観という概念を第二者として捉えれば、常にお客は想定できる。　
客観を第三者として捉えると、最後は空集合にたどり着く可能性を考慮しているとよいかもしれない。　

俯瞰的は、空間に限定して考えた。時間を含めると、さらによいことがあるかもしれない。　天文関係では、空間は時間でしか計れない。何光年とか、今、届いている光は、過去のものであり、今がどうなっているかわからない。

測定に時間がかる事象を扱う場合には、空間だけで俯瞰して、俯瞰したつもりになっているのは危険だとわかるかもしれない。　

世界同時に測定しても、それを伝えるのに、それぞれの場所から別の場所に伝えるのに遅延が分布的になる。同時に発信すれば、同時に伝わるわけではない。　

往路と復路の遅延さがある通信手段をつかっていると、さらに遅延の分布は数的処理をするとよいことがわかる。　

マルチホーミングにおける端末間経路選択のための片方向遅延差測定方式
小川 清,澤井 新,飯田 登
https://iss.ndl.go.jp/books/R000000004-I7704255-00

端末間経路選択のための片方向遅延差測定方式
小川清, 2005 静岡大学 , 博士 (工学)
何故、今、国際規格なのか。OSEK(46)

自動車関連技術での国際規格の発行が増えているかもしれない。　

いくつかの自動車に関する動きと国際規格の関係を調べてみる。　


<この項は書きかけです。順次追記します。>
This article is not completed. I will add some words in order.

# 自動車関連国際規格の歴史　

CAN(Controller Area Network)

OSEK

FlexRay

LIN

CXPI

### OBD 1989
ISO 9141:1989 Road vehicles — Diagnostic systems — Requirements for interchange of digital information

https://qiita.com/kaizen_nagoya/items/7d6300044916763a58c7

### UDS, 1998

ISO 14229-1:2020 Road vehicles — Unified diagnostic services (UDS) — Part 1: Application layer

https://qiita.com/kaizen_nagoya/items/3231d9fea536d1b9b1f7

## OffBD, 15031, 2001

ISO 15031-2:2010, Road vehicles — Communication between vehicle and external equipment for emissions-related diagnostics — Part 2: Guidance on terms, definitions, abbreviations and acronyms

https://qiita.com/kaizen_nagoya/items/e96aabf3983f33b884db

## DoCAN, 2004

ISO 15765-2:2016 Road vehicles — Diagnostic communication over Controller Area Network (DoCAN) — Part 2: Transport protocol and network layer services 

https://qiita.com/kaizen_nagoya/items/ed24d992e6313a4e7362

## WWH-OBD 2006

ISO 27145-1:2012
Road vehicles — Implementation of World-Wide Harmonized On-Board Diagnostics (WWH-OBD) communication requirements — Part 1: General information and use case definition

https://www.iso.org/standard/46273.html


## DOIP , 2011

ISO 13400-2:2019 Road vehicles — Diagnostic communication over Internet Protocol (DoIP) — Part 2: Transport protocol and network layer services

https://qiita.com/kaizen_nagoya/items/2f7798df491c0b5d9546

### 自動車関連国際規格の歴史　まとめ

ISO Road vehicles - Diagnostics 等規格調査中。百規格、百記事をめざして。

https://qiita.com/kaizen_nagoya/items/51e29d318585a4219985

# 電気自動運転車の急増　

TESRA

毎年報告書を出している。　

https://www.tesla.com/ns_videos/2021-tesla-impact-report.pdf

https://www.tesla.com/ns_videos/2020-tesla-impact-report.pdf

https://www.tesla.com/ns_videos/2019-tesla-impact-report.pdf

https://www.tesla.com/ns_videos/2018-tesla-impact-report.pdf

# 中国のWTOへの加盟

中国がWTO

China and the WTO
>This page gathers key information on China's participation in the WTO. China has been a member of WTO since 11 December 2001.

https://www.wto.org/english/thewto_e/countries_e/china_e.htm



# ヨーロッパ 
電気自動車の急増はアメリカ発のように見えるが、　
電池の標準化はイギリスが取り組んでいたり、　
オープン化もOpen Projectはヨーロッパが力を入れていたりする。　

車載Ethernetは、IEEEへ　
車載LinuxはISOへ　
標準を反映していくかもしれない。

ヨーロッパの自動車関係の標準化で中心になっているのは、BMW - BoschのOEMと世界一のSuppliyerの共同作業のことがある。

ボッシュ自動車ハンドブック

https://qiita.com/kaizen_nagoya/items/8e330ce57880f04d71d9

BMWとBoschの方と直接議論したことがあるのは、　
ISO TC22のあるWGにISO/IEC JTC1 SC7からリエゾンで参加したとき。


＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
This article is an individual impression based on the individual's experience. It has nothing to do with the organization or business to which I currently belong.

# 文書履歴(document history)
ver. 0.01 初稿 　20240427
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
OT,OTネットワーク とは

## 勉強前イメージ

そういう環境？OT？

## 調査

### OT,OTネットワーク とは

OTとはOperational Technologyの略で、
製造業、交通手段やライフラインなどの社会インフラの製品や設備(ハードウェア)・システムを制御して運用するものをOTシステムといい
OTシステムをつなぐネットワークをOTネットワークと言います。

OTとついになるのがIT(Information Technology)になり
こちらは情報通信技術の総称です。
ITは一般消費者がよく利用していますが、OTは基本的には一般消費者は使用する想定ではないです。

### ITとの違い

これが全てではないですが、大まかに違いを以下に記載しています。

- 利用時
	- OT : 製造業、社会インフラ
	- IT : 一般消費者
- 稼働
	- OT : 24時間365日が多い
	- IT : 要件によるOTより許容されることが多い
- 通信プロトコル
	- OT : 標準プロトコル or ベンダー独自プロトコル
	- IT : 標準プロトコルが多い
- ネットワーク接続
	- OT : 接続されていないことが多い
	- IT : 基本的に常に接続されていることが多い

## 勉強後イメージ

OTって初めて聞いたけど、たしかに工場とか全然違うネットワークな気もする・・・

## 参考

- [ITとOTの違い、OTのセキュリティ対策を解説](https://www.iwi.co.jp/service-products/thema-industry-search/contents/post11.html)
- [OT（Operational Technology）](https://www.nri-secure.co.jp/glossary/ot-network)
HTML内のリンク一覧をJavaScriptを使ってVimキーバインドで移動・参照できるようにする

- ブラウジングをしていてページ内にキーバインド参照が実装されていたら非常に捗る。
- 一部実装済みのサイトもあるが、割合として未実装の方が多いように感じる。
- 今回はHTML内のリンク一覧をJavaScriptを使ってVimキーバインドで移動・参照できるようにする方法を記録する。

## 結果
- 以下の簡易的なリンク一覧で移動や参照できるようにする。

![image](https://user-images.githubusercontent.com/44114228/192123717-a343af0c-a915-4167-83ca-be0a80dd7dfd.png)

- 以下のキー操作が可能。
  - j : 下に移動
  - k : 上に移動
  - Enter : リンク先へ遷移

![image](https://user-images.githubusercontent.com/44114228/192123735-1b6c5640-2d88-459c-a118-d5a166ba8195.png)

## 環境
- mac OS Monterey 12.5

## 手順

### ファイル作成
- 任意のディレクトリにHTMLとCSS、JSファイルをそれぞれ作成。

```
linkKeyBindフォルダ
|--index.css
|--index.html
|--index.js
```

### 内容記述
- 作成後、以下のCodepenのHTMLとCSSとJSの内容をそれぞれのファイルに記述。

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

- **※こちらの手順ではファイルをローカルに作成しているため、cssとjsファイルを読み込む1行をHTMLファイルのヘッダーと最後に記述。**

```html
<!-- ヘッダーに記述 -->
<link rel="stylesheet" href="index.css">

<!-- body内に記述 -->
<script defer src="index.js"></script>
```

### 結果確認
- 記述後、HTMLファイルをブラウザで開いて以下の操作で移動や参照ができるか確認。
  - j : 下に移動
  - k : 上に移動
  - Enter : リンク先へ遷移

![image](https://user-images.githubusercontent.com/44114228/192123735-1b6c5640-2d88-459c-a118-d5a166ba8195.png)

## まとめ
- 普段からキーバインドを利用している人が癖で押下した時に、サイトに実装されていると何故か嬉しさを感じる。
- こうした地味な閲覧者体験は他にもあるので、日々学びながら状況を見て検討することにする。

## 参考
- [KeyboardEvent.key](https://developer.mozilla.org/ja/docs/Web/API/KeyboardEvent/key)
Arduino IDE 2.xに変更したらunused variableエラー

# 事象

Arduino IDE 1.xでコンパイルできていたスケッチが、Arduino IDE 2.xでコンパイルできない。
普段、ワーニングになっていたような部分がエラーと判定される。

（下図では`unused variable`がエラーになっている。）
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/6d23580c-7c37-76ed-c211-27888a0b64f3.png">

# 解決方法

エラー箇所のコードを訂正する、、、のが王道。
とはいえ、ライブラリ内でエラーになっていたりすると、なかなか手が出せない。File > Preferencesにある、SettingsのCompiler warningsをNoneにすることで回避できるときもある。

# 原因

Compiler warningsの設定値が、Arduino IDE 1.xと2.xで違っていた。（デフォルトに違いがあるのか、わたしが変更していたのかは不明。）

**Arduino IDE 1.8.19:**
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/7a618869-93a2-9e5a-6ab1-eb9b1c17914b.png">

**Arduino IDE 2.0.0:**
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/fb8e4000-01a9-a168-33e1-db871f43dbb6.png">

Compiler warningsの設定値はNone, Default, More, Allの4つある。この設定値がコンパイルにどう作用するかは、使っているボードパッケージ（と選択しているボード）によって決まる。

いま選択している[Arduino core for the ESP32](https://github.com/espressif/arduino-esp32)のXIAO_ESP32C3は、それぞれの設定値でこのようにコンパイルオプションが設定されている。（[platform.txt](https://github.com/espressif/arduino-esp32/blob/f49931f902406f23b40e457e31bdb84cec974e78/platform.txt#L106-L110)）

* Compiler warnings = None
  * **-w** ... 全ての警告メッセージを抑制する
* Compiler warnings = Default
  * なし
* Compiler warnings = More
  * **-Wall** ... 一般的な警告を有効にする
  * **-Werror=all** ... 全ての警告をエラーにする
* Compiler warngings = All
  * **-Wall** ... 一般的な警告を有効にする
  * **-Werror=all** ... 全ての警告をエラーにする
  * **-Wextra** ... "-Wall"で有効にならない、いくつかの警告を有効にする

# 参考

* [Options to Request or Suppress Warnings - Using the GNU Compiler Collection (GCC)](https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options)