OmniAICreator/Qiita-1.07M huggingface dataset:
Angular9から13へ移行してESLintの構築がうまくいかなかった

Angular９から１３まで移行したことによってリンターもTSLintからESLintへ移行したが、
`ng lint`を叩くとエラーを吐いて辛い思いをした…

# 問題があった場所と対処

まずエラーが出たのは下のエラーメッセージ
```
An unhandled exception occurred: Failed to load parser '@angular-eslint/template-parser' declared in
```
これは`eslintrc.json`にparserの記載がないと解釈して`.eslintrc.json`に以下を追加
```.eslintrc.json
{
  "files": ["*.component.html"],
  "parser": "@angular-eslint/template-parser",
  "parserOptions": {
    "project": "./tsconfig.app.json",
    "ecmaVersion": 2020,
    "sourceType": "module"
  },
  "rules": {},
  "plugins": ["@angular-eslint/template"]
}
```
細かい設定は後回しにしてとりあえず`ng lint`試すも同じエラー…
もしかして、コンバイルかどこかがだめ？とおもい、一旦`package.json`を確認。
```package.json
"@angular-devkit/build-angular": "^13.3.9",
"@angular-eslint/builder": "1.2.0",
"@angular-eslint/eslint-plugin": "1.2.0",
"@angular-eslint/eslint-plugin-template": "1.2.0",
"@angular-eslint/schematics": "^14.0.2",
"@angular-eslint/template-parser": "1.2.0",
"@angular/cli": "~13.3.9",
```
`@angular-eslint/builder`を始め`1.2.0`のバージョンに問題がありそう
と思てアップデートしようとすると
```
ERR! stack Error: Can't find Python executable "python",(詳細はコピペミスりました）
```
と出てPythonが必要なの？と疑問にも思いながらも、`Dockerfile`に下記を追加
```
RUN apk add py3-pip make g++
```
ここまでやってやっとアップデートも正常に稼働
```
CC(target) Release/obj.target/nothing/../../node-addon-api/nothing.o
  AR(target) Release/obj.target/../../node-addon-api/nothing.a
  COPY Release/nothing.a
  CXX(target) Release/obj.target/watcher/src/binding.o
  CXX(target) Release/obj.target/watcher/src/Watcher.o
  CXX(target) Release/obj.target/watcher/src/Backend.o
  CXX(target) Release/obj.target/watcher/src/DirTree.o
  CXX(target) Release/obj.target/watcher/src/watchman/BSER.o
  CXX(target) Release/obj.target/watcher/src/watchman/WatchmanBackend.o
  CXX(target) Release/obj.target/watcher/src/shared/BruteForceBackend.o
  CXX(target) Release/obj.target/watcher/src/linux/InotifyBackend.o
  CXX(target) Release/obj.target/watcher/src/unix/legacy.o
  SOLINK_MODULE(target) Release/obj.target/watcher.node
  COPY Release/watcher.node
```
packege.jsonもいい感じに
```packege.json
 "devDependencies": {
    "@angular-devkit/build-angular": "^13.3.9",
    "@angular-eslint/builder": "13.5.0",
    "@angular-eslint/eslint-plugin": "13.5.0",
    "@angular-eslint/eslint-plugin-template": "13.5.0",
    "@angular-eslint/schematics": "^14.0.2",
    "@angular-eslint/template-parser": "13.5.0",
    "@angular/cli": "~13.3.9",
```
`@angular-eslint/schematics`だけ14なのが気になるけど一旦はよしとします。
Angular自体14にアップする予定があるので…

# さいごに
とりあえず、自分が忘れないように色々書き殴りましたが、読みづらかったらごめんなさい。
あと、残そうと思ったのは問題解決してからなので色々書けてる部分もあり…
今後体験していくことは残す前提で色々残そうと反省しております。

:::note warn
間違い等ございましたら、ぜひご指摘ください。
:::
AlmaLinuxにDockerとdocker-composeを導入する

# Dockerインストール
```
# dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# dnf -y install docker-ce docker-ce-cli containerd.io
```

## Docker起動＆起動設定
```
# systemctl start docker
# systemctl enable docker
```

## 確認
バージョン確認できればOK！
```
# docker --version
Docker version 20.10.17, build 100c701
```

# Docker Composeインストール
```
# curl -L "https://github.com/docker/compose/releases/download/v2.4.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
```

## 実行権限付与
```
# chmod +x /usr/local/bin/docker-compose
```
## 確認
バージョン確認できればOK！
```
# docker-compose --version
Docker Compose version v2.4.1
```
AWS AmazonLinux 日本語化（locale設定）

# 概要
- Amazon Linuxの初期設定、日本語化についてまとめた

# 日本語化
- localectlコマンドにて変更等を実施する

- ロケールの確認
```
# localectl status
▼コマンド実行結果
------------------------------------
   System Locale: LANG=en_US.UTF-8
       VC Keymap: n/a
      X11 Layout: n/a
------------------------------------
```

- 日本語化
```
// 変更可能なロケールの確認
localectl list-locales | grep -i jp

// 日本語に設定変更
localectl set-locale LANG=ja_JP.utf8

// 変更確認
localectl status
▼コマンド実行結果
------------------------------------
   System Locale: LANG=ja_JP.utf8
       VC Keymap: n/a
      X11 Layout: n/a
------------------------------------

//　設定の反映
source /etc/locale.conf
```

# 参考リンク
- [サーバー構築の基本 CentOS Linux 8のインストール後に設定する12の項目](https://www.rem-system.com/centos8-first-settings/#11)
date-fnsについて

## はじめに
最近は date-fns を使うことが多いので、メモとして書いておきます。

## format
Dateオブジェクトを指定した文字列にして生成できる。
https://date-fns.org/v2.14.0/docs/format

``` javascript
const date = new Date()  // Fri May 13 2022 17:09:15 GMT+0900 (日本標準時) 
format(date, 'yyyy-MM-dd') // 2022-05-13
format(date, 'yyyy/MM/dd HH:mm:ss') // 2022/05/13 17:09:15
format(date, 'yyyy年M月d日(E)', {locale: ja}) // 2022年5月13日(金)
```

## parse
文字列をDateオブジェクトに変換する。
https://date-fns.org/v2.14.0/docs/parse

``` javascript
parse('2022-05-13', 'yyyy-MM-dd', new Date()) // Fri May 13 2022 00:00:00 GMT+0900 (日本標準時)
parse('2022-05-13 09:15:10', 'yyyy-MM-dd HH:mm:ss', new Date()) // Fri May 13 2022 09:15:10 GMT+0900 (日本標準時)

```

## addDays,  subDays
特定の日付に日付を加算、減算できる。

``` javascript
addDays(new Date(2022, 4, 13), 1) // Sat May 14 2022 00:00:00 GMT+0900 (日本標準時)
subDays(new Date(2022, 4, 13), 1)  // Thu May 12 2022 00:00:00 GMT+0900 (日本標準時)
```
週、月、年を加算するときは、addWeeks、addMonths、addYears を使う。
逆に週、月、年を減算するときは、subWeeks、subMonths、subYears を使う。

## differenceInCalendarDays
指定した日付の差を求めることができる。

``` javascript
differenceInCalendarDays(new Date(2022, 4, 13, 0, 0), new Date(2021, 4, 13, 0, 0)) // 365
differenceInCalendarDays(new Date(2022, 4, 13, 0, 0), new Date(2022, 4, 12, 23, 59)) // 1
differenceInCalendarDays(new Date(2021, 4, 13, 0, 0), new Date(2022, 4, 13, 0, 0)) // -365
```

## eachDayOfInterval
指定期間内の各日付を配列にしてくれる。

``` javascript
eachDayOfInterval({ start: new Date(2022, 4, 13), end: new Date(2022, 4, 16)})
// [Fri May 13 2022 00:00:00 GMT+0900 (日本標準時), Sat May 14 2022 00:00:00 GMT+0900 (日本標準時), Sun May 15 2022 00:00:00 GMT+0900 (日本標準時), Mon May 16 2022 00:00:00 GMT+0900 (日本標準時)]
```

## eachWeekendOfInterval
指定期間内の土日のみを配列にしてくれる。

``` javascript
eachWeekendOfInterval({ start: new Date(2022, 4, 1), end: new Date(2022, 4, 31)})
// [Sun May 01 2022 00:00:00 GMT+0900 (日本標準時), Sat May 07 2022 00:00:00 GMT+0900 (日本標準時), Sun May 08 2022 00:00:00 GMT+0900 (日本標準時), Sat May 14 2022 00:00:00 GMT+0900 (日本標準時), Sun May 15 2022 00:00:00 GMT+0900 (日本標準時), Sat May 21 2022 00:00:00 GMT+0900 (日本標準時), Sun May 22 2022 00:00:00 GMT+0900 (日本標準時), Sat May 28 2022 00:00:00 GMT+0900 (日本標準時), Sun May 29 2022 00:00:00 GMT+0900 (日本標準時)]
```

## 参考
https://date-fns.org/
https://tech.mof-mof.co.jp/blog/date-fns/
エクセルでなぜか消えない列や行やセルの削除方法

# 概要

右クリックメニューの『削除』で **物理削除** までしているのにも関わらず、それでも消えない。
（セルに数式が残っていた、とかそういうオチではない）

新しいシートを作ってデータを移管すれば解決するけど、レイアウトの面からそれはなるべく避けたい。

そんな時に試す一つの手。

# やり方

消したい列やセルなどを削除後、**すぐ保存** して、さらに **すぐにエクセルを閉じる** ことで解決する場合がある。

なぜか消えない列や行やセルは『不要な編集履歴が残ってしまう』ことが原因で発生する場合がある。
削除後に余計な処理をせずに、すぐに保存してファイルを閉じることがポイント。


# 参考サイトさん

https://thesweetspecialist.com/cell-not-del/

# バージョン
Windows 10 Pro 21H2 OSビルド 19044.1889
Microsoft Excel for Microsoft 365 MSO (バージョン 2207 ビルド 16.0.15427.20166) 32 ビット
古いGoogle App Engine のバージョンをGitHub Actionsで定期的に削除する

## エラー

```
ERROR: (gcloud.app.deploy) INVALID_ARGUMENT: Your app may not have more than 210 versions. Please delete one of the existing versions before trying to create a new version.
```

- GAEは最大210個までバージョンを保有することができる。
  - それ以上はエラーとなってデプロイできない
  - (古いバージョンは自動的に削除してくれたらいいのに...)
- バージョンはデプロイの度に増えるので、定期的に削除する必要がある。

## やってみる

GitHub Actionsのワークフローを書いていきます。

```.github/workflows/remove-old-versions-of-gae.yml
name: Remove old versions of Google App Engine

on:
  workflow_dispatch:
  schedule:
    # 毎週月曜のJST 9:00に実施する。(30分前後の実行遅延がある)
    - cron: '0 0 * * 1'

jobs:
  remove-old-versions:
    runs-on: ubuntu-latest

    permissions:
      contents: read
      id-token: write

    steps:
      - id: auth
        uses: google-github-actions/auth@v0
        with:
          workload_identity_provider: projects/1234567890/locations/global/workloadIdentityPools/github-actions-pool/providers/github-actions-provider
          service_account: github-actions@your-project-id.iam.gserviceaccount.com

      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v0

      - name: Remove old versions of Google App Engine
        env:
          CI: true
          PROJECT_ID: your-project-id
        run: gcloud app versions list --project ${PROJECT_ID} --format 'value(version.id)' --sort-by '~version' | tail -n +100 | xargs --no-run-if-empty gcloud app versions delete --project ${PROJECT_ID} --quiet
```

### 補足

やってることは

- 毎週月曜に定期的に実行する
  - workflow_dispatch を設定してるのでActionsタブから手動実行もできる
- バージョンは100件目以降は削除する

重要な部分は `Remove old versions of Google App Engine` のステップです。

```
$ gcloud app versions list --project ${PROJECT_ID} --format 'value(version.id)' --sort-by '~version' | tail -n +100 | xargs --no-run-if-empty gcloud app versions delete --project ${PROJECT_ID} --quiet
```

小分けに解説します。

```
$ gcloud app versions list --project ${PROJECT_ID} --format 'value(version.id)' --sort-by '~version'
```

- `--project ${PROJECT_ID}` プロジェクトIDを設定
- `--format 'value(version.id)'` バージョンIDのみ出力
- `--sort-by '~version'` バージョンIDで降順に並び替え(`~` を付けないと昇順)

```
| tail -n +100
```

- 100行目以降の行のみ取得する
- バージョンIDの降順なので100個目以降の古いバージョンIDのみ抽出

```
| xargs --no-run-if-empty gcloud app versions delete --project ${PROJECT_ID} --quiet
```

- `--no-run-if-empty` 古いバージョンがない時はコマンドを実行しないオプション
- `--project ${PROJECT_ID}` プロジェクトIDを設定
- `--quiet` 質問しない

認証周りについては下記の記事にまとめてます。

https://qiita.com/ucan-lab/items/80dbf7d31cacf8a624d1
TypeScript の as は未定義プロパティをスルーする

## ことの発端

例えばこんな定義があったとします。

```ts:Parameter型
type Parameter = {
  command: "start" | "stop";
  duration: number;
};
```

こいつを初期化する際、色々と面倒な問題が出てきます。

## 何か問題でも？

返却値とオブジェクトの初期化 `Parameter型` を生成する場合、下記のように `<Parameter>` とか `as Parameter` とか書くことが多いと思います。

```ts:よく見かけるコード
function generateParameter() {
  return <Parameter>{
    command: "start",
    duration: 100
  };
}
function generateParameter2() {
  return {
    command: "start",
    duration: 100
  } as Parameter;
}
```

これはこれで、間違いではないです。
`command` に `"start"` か `"stop"` を入れないとエラーになりますし、`duration` も `number型` を入れないとエラーになります。

間違いではないのですが、<b>「間違いが見つかりにくい」</b>という問題が生じます。


## 見つかりにくい問題

TypeScript での `<Parameter>` や `as Parameter` の取り扱いは
<b>「型変換ではなく型チェックと型の上書き」</b>
です。[^1]
これがどういうことかというのは、下記のコードを見ると明らかです。

[^1]: [型アサーションとキャストの違い](https://typescriptbook.jp/reference/values-types-variables/type-assertion-as#%E5%9E%8B%E3%82%A2%E3%82%B5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%82%AD%E3%83%A3%E3%82%B9%E3%83%88%E3%81%AE%E9%81%95%E3%81%84) を参照

```ts:このコードはエラーになりません
function generateParameter() {
  return <Parameter>{
    command: "start",
    duration: 100,
    debug: true
  };
}
function generateParameter2() {
  return {
    command: "start",
    duration: 100,
    debug: true
  } as Parameter;
}
```

`Parameter型` の初期化に `debug` という `Parameter型` に定義されていないプロパティが登場していますが、これは型チェック的にはエラーになりません。つまり、`command` と `duration` が既定の型で初期化されていれば `Parameter型` としては成立しているからです。（`interface`の考え方と同じ）

今回の `Parameter型` のように単純な型ならまだしも、メタプログラミングで交差型や合併型が複雑になってくると、間違いを見つけるのはかなり困難になります。

上記の例だと、デバッグモードなんて存在していないのに「あれれ？デバッグモードがある筈だから設定してみたけど動いてないな～」的な思い込み系のバグです。
または、`Parameter型` がインターネット網を経由して対向サーバへデータを送信した際に、対向サーバでパラメータチェックを厳格にやっていてエラーレスポンスが返却され、「何がエラーなんだ！」と対向サーバ作っている人に文句を言ったらフルボッコされるケースなんかもあります。


## ちゃんと書くと

で、ちゃんと書こうとするとこうなります。

```ts:ちゃんと＃１
function generateParameter() : Parameter {
  return {
    command: "start",
    duration: 100
  };
}
```

```ts:ちゃんと＃２
function generateParameter() {
  const p: Parameter = {
    command: "start",
    duration: 100
  };
  return p;
}
```

上記の例では `debug` みたいな `Parameter型` に含まれないプロパティを指定するとエラーになります。
で、まぁ、TypeScriptの良さは高度な型推論にあると思うので、`ちゃんと＃１` のように関数定義で返却型を指定することは稀だったりします。（意図的に書く場合もありますが）
そうなると、 `ちゃんと＃２` みたいなパターンなると思うのですが、ちょっと手間だし、返却値を生成するためだけにローカル変数を定義するのもイマイチだったりします。


## 解決案

```ts:今回作ったもの
function as_<T>(o: T): T { return o; };
```

```ts:使用例
function foo() {
  return as_<Parameter>({
    command: "start",
    duration: 100
  });
}
```

TypeScriptは C++ のようにジェネリクス（template）の特殊化は行われないため、似たような関数がバカスカ生成されることはありません。
しかし、下記のような問題が考えられます。

* オブジェクトのコピーが発生
* 関数呼び出しのコストが発生

まず「オブジェクトのコピー」ですが、オブジェクトの実体がコピーされる訳ではなく、単なるポインタのコピー[^2]なので問題ないでしょう。
次に「関数呼び出しのコスト」はオブジェクト初期化の定石であるコンストラクタ呼び出しと比較すると問題にならないんじゃないかと思います。

[^2]: Javascriptではポインタという定義は無いのですが、概念として考慮しないと説明できないことが多くあります。（ディープコピーやシャローコピーなんかもそうですし、仮引数で受け取ったオブジェクトの操作と代入行為などもポインタを概念として取り入れないと説明が難しいです）

## まとめ

単なる型チェックのために何もしない関数を作らなければならないので、TypeScriptの型チェックの機能として何かあれば良いのだが。。。
Github ActionsのキャッシュをGET/DELETEする



[actions/cache](https://github.com/actions/cache)でGithub Actions内にキャッシュされたデータを消したい場合、
現状ではUIから消すことはできず、Github APIを使って消す必要がある。




# tl;dr
1. Personal Access Token(PAT)を取得する
1. Github CLIをインストールする
1. 下のコマンドを実行して、Cacheを削除
```bash
$ gh api -X GET repos/{ORG}/{REPO}/actions/caches | jq '.actions_caches[] | select(.key == "${CACHE_ID}") | .id' | xargs -L1 -I{} gh api -X DELETE repos/{ORG}/{REPO}/actions/caches/{}
```

# Requirements
- GitHub CLI
    - Personal Access Tokenを発行し、 `gh api` が実行できるようにしておく。
- jq

# cacheリストの取得(GET)
```bash
$ gh api -X GET repos/{org}/{repo}/actions/caches/{CACHE_ID}
```
# cacheの削除(DELETE)
`key` と `id`は異なるので注意。
`key`はキャッシュの同一性判定に使われるもので、Actionsの画面に表示されている。

ここで指定するのは`id`なので、 GETエンドポイントでkeyからidを引く。
```bash
# 例:
# gh api -X DELETE repos/{ORG}/{REPO}/actions/caches/162
$ gh api -X DELETE repos/{ORG}/{REPO}/actions/caches/{CACHE_ID}
```
XSSとCSRFの違い

# はじめに

みなさんこんにちは。Web開発勉強中の大学3年生です。
まだまだ未熟なエンジニアですので記事の中に間違いなどがある可能性がございます。
もし何か間違いがあったらコメントで教えていただけると幸いです。

## このテーマにした理由

個人開発中のwebアプリで認証機能を実装しようとしており、何も考えずJWTをlocalStorageに格納していたところ「セキュリティ的に良くない」と言うことを知り、認証機能部分に関係するセキュリティの知識を勉強したため、その内容を記事にまとめることにしました。

## XSSとは

XSS(クロスサイトスクリプティング)とは、Webアプリケーションに対する代表的な攻撃の一つです。ざっくり言うと「外部から入力された不正なスクリプトがアプリ内で勝手に実行されてしまう脆弱性・攻撃手法のこと」です。



## 具体的な流れ

1. 普通はクライアント側の「田中　太郎」などと文字列を入力するフォームに、

```
"><script>alert("こちらをクリックで１００万円プレゼント")</script><!--"
```
のような、不正なスクリプトが入力されデータベースに保存されてしまう

2. データベースから不正なスクリプトがクライアント側に送られる

3. 利用者の画面上で不正なスクリプトが勝手に動き出してしまう

## XSS対策

XSS対策としてサニタイジング（エスケープ）が挙げられます。サニタイジングとは入力された文字列に含まれる特殊文字を変換することでスクリプトとして機能しない形にすることです

| 特殊文字の変更前 | 特殊文字の変更後 | 
| :---: | :---: | 
| & | &amp;amp; | 
| < | &amp;lt; | 
| > | &amp;lt; | 
| < | &amp;gt; | 
| " | &amp;quaot; | 
| ' | &amp;#39; | 

このようにすることで

```
"><script>alert("こちらをクリックで１００万円プレゼント")</script><!--"
```
のようなスクリプトが
```
"&lt;&gt;scriptlt;alert(&quaot;こちらをクリックで１００万円プレゼント&quaot;)&lt;/script&lt;lt;!--"
```
という文字列になってデータベースに保存されるため、利用者の画面上でスクリプトが勝手に動き出してしまうことが回避できます。

## CSRFとは

CSRF(クロスサイトリクエストフォージェリ)とは、XSSと同様にWebアプリケーションに対する代表的な攻撃の一つです。ざっくり言うと「利用者がログインした状態で意図しない処理が実行されてしまう脆弱性・攻撃手法のこと」です。



## 具体的な流れ

1.　利用者がログインに成功しサーバ側から送られてきたセッションIDをCookieなどに保持する
2.　「１」の状態のまま、罠サイトにアクセスしボタンやリンクをクリックしてしまう
3.　ログイン状態のままであるためサーバ側では不正なアクセスではないと判断してしまう
4.機密性の高いデータが盗まれたり、勝手に商品を購入されたりなど意図しない操作が行われる

## XSS対策

CSRF対策としてセッションIDと一緒にユーザーから見えない状態の機密情報をCookieなどに保持することが挙げられます。セッションIDだけでなく、サーバーであらかじめ保持されている機密情報とCookie内の機密情報を照らし合わせることで不正なリクエストかを判断します。
また、画面遷移をする際に意図している画面に遷移しているかのチェックをすることも有効です。
MacでAltTabを使い、ウインドウを切り替える

## はじめに

https://twitter.com/kkfactory0705/status/1555048513037148160?s=20&t=xtD51dCqkqsrwM9WAKrBHA

WindowsユーザがMacに切り替える際に色々と障壁があります。その中でも一番は、「Alt＋Tab」です。Windowsでは同一のアプリケーションを2つ開きながら、「Alt＋Tab」で切り替えていきました。それがMacだとできない。異なるアプリケーションの切り替えはできても、Chrome→Chrome、Excel→Excelの切り替えはできないです。作業効率が落ちて嫌だなぁと思っていた時に、「HyperSwitch」に出会いました。HyperSwitchを利用することで、ウインドウの切り替えがスムーズにできるのですが、ログイン時に毎回アップデート確認のポップアップが出てきて嫌。。。ここらへんを解消できるのが、「AltTab」というソフトウェアでした。今回の記事では、「AltTab」について紹介します。

### AltTab
AltTabはSwiftで作成されたウインドウ切り替えアプリです。
![スクリーンショット 2022-08-04 13.20.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/3d5ff94c-e74a-2862-754f-86f490a39741.png)


### AltTab
https://alt-tab-macos.netlify.app/
【Alteryx】正規表現ノードでの正規表現の書き方

# はじめに
Alteryxの正規表現がなかなか使いこなせないので備忘も込めてご紹介します。

# 正規表現とは
内容が異なる文字列を1つの形式で表現する表現方法です。
「ある文字列の中にある5桁の数字」や「アルファベットとスペースが含まれる文字列」等、
一定の規則を持った複数の文字列パターンを、1つの文字列で表現できます。

# 基本的な正規表現の一覧
Alteryxで意図通り動いたもののみ、下記サイトを参考に記載しています。
https://www-creators.com/tool/regex-checker

上記URLでは、
正規表現で表したい文字列を、作成した正規表現で表現できているかのチェックができるので
うまく正規表現に置き換えられないときにおすすめです。

|正規表現|正規表現が指す文字列の内容|正規表現|正規表現が指す文字列の内容|
|:---|:---|:---|:---|
|.|改行を除くすべての文字|-|-|
|*|直前で指定した正規表現の0回以上連続|+|直前で指定した正規表現の1回以上連続|
|(R)|正規表現のグルーピング|[abc]|カッコ内文字のうちいずれかの1文字|
|[a-c]|カッコ内文字のいずれか|[^abc]|カッコ内文字以外の1文字|
|{N}|直前の正規表現パターンのN回の連続|{N,}|直前の正規表現パターンのN回以上の連続|
|{,M}|直前の正規表現パターンのM回以下の連続|{N,M}|直前の正規表現パターンのN回以上M回未満の連続|
|^|テキストの開始位置|$|テキストの終了位置|
|\t|タブ|\0|Null文字|
|\s|空白文字すべての文字 (\t, \n, \r, \fと同義)|\S|空白文字以外のすべての文字|
|\d|任意の数字1文字|\D|数字以外の任意の1文字|
|\w|アルファベット, "_"のうち任意の1文字|\W|アルファベット, "_"以外の任意の1文字|
|\l|半角英小文字のうち任意の1文字|\L|半角英小文字以外の任意の1文字|
|\u|半角英大文字のうち任意の1文字|\U|半角英大文字以外の任意の1文字|

# Alteryxでの正規表現の使い方
Alteryxで正規表現が使用できるノードは[正規表現](https://help.alteryx.com/ja/20221/designer/regex-tool)・[フィルタ](https://help.alteryx.com/ja/20221/designer/filter-tool)・[フォーミュラ系](https://help.alteryx.com/ja/20221/designer/formula-tool)・[動的リネーム](https://help.alteryx.com/ja/20221/designer/dynamic-rename-tool)等です。
※リンク先は公式

正規表現自体はどのノードでも同じものを使用できますが、
正規表現ツールは正規表現を直接入力、
フィルタ・フォーミュラ・動的リネームについては正規表現用の関数を使用する違いがあります。

今回は、下記データを使用した正規表現ノードでの処理をご紹介します。
![input.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752246/246c8f66-0f22-95e8-ecfa-4170629d8d09.png)
3行目・5行目の数値に対して正規表現でいろいろな処理を行ってみるとします。
正規表現で指定したいものは数値なので数値を表す ```\d```と、
桁数が異なる値に両方対応させたいので、1回以上繰り返す表現の```+```を使用します。
組み合わせて、「98」「7」両方に対応する正規表現は```\d+```となります。

# 正規表現ノードでの処理
正規表現ノードでは ①置換②トークン化③解析④一致 の4つの処理を行えます。

①置換
　正規表現に該当する文字列を指定文字列に置換します。
　今回は数値を空白へ置換しています。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752246/5f24643f-0951-bece-5f0d-55025e0c7d26.png)
　正規表現はグループ化でき、グループ化した正規表現は前から連番が振られます。
　```$番号```で指定することが可能で、
　「一致する正規表現の1つ目の文字列の前に0を追加する」のような処理も可能です。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752246/dead025a-c36e-de88-d9f4-93bbc8400b9b.png)
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752246/f031c4a9-21ba-14c5-2560-e27b6b2c0a1a.png)

②トークン化
　正規表現に一致する文字列を列もしくは行へ分割します。
　今回は数値部分を列へ分割しています。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752246/af914966-65ea-b036-6f8d-8f06d13d34d7.png)

③解析
　正規表現に一致する文字列で新しい列を作成します。新しい列のデータ型は指定できます。
　今回は数値部分をstring型で作成しています。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752246/eb886841-454c-e85a-c8c6-7c8a2c9f1c65.png)

④一致
　正規表現に一致した文字列かどうかをBoolean型で判定します。
　今回は数値が含まれる文字列 (```.*(\d+)```) か否かを判定しています。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752246/ed05620b-7eb0-af2b-dda2-793f67bc95ad.png)

# おわりに
正規表現ノード以外での書き方はまたまとめます。
e.force:createRecordで日付型を使う時の注意


元の質問 : [Custom Lightning Component broken](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000HEYetSAH)

単純に日付型を設定できないようです。

I'm not exactly sure why, but if you try to just set the currentYear variable in the Default Field:Close Date, Salesforce will not accept it. But if you create a date attribute in the component, store the exact same value in this attribute, then call the attribute in the Close Date field, Salesforce accepts it.

正確な理由はわかりませんが、CurrentYear 変数を Default Field: Close Date に設定しようとすると、Salesforce はそれを受け入れません。ただし、コンポーネントで日付属性を作成し、この属性にまったく同じ値を保存してから、[完了予定日] 項目で属性を呼び出すと、Salesforce はそれを受け入れます。 

[Populating date on e.force:createRecord](https://salesforce.stackexchange.com/questions/360179/populating-date-on-e-forcecreaterecord)

一旦変数にセットしてから使えばいいみたい。

コンポーネント
```
<aura:attribute name="todaysDate" type="Date"/>
```

コントローラ

```
newRecord : function(component, event, helper) 
    { 
        var currentYear = $A.localizationService.formatDate(new Date(), "YYYY-12-31");
        component.set("v.todaysDate", currentYear);
        var createRecordEvent = $A.get("e.force:createRecord");
        //change this when deploying
        var RecTypeID  = '0126C0000005BT9QAM';
        createRecordEvent.setParams({
            "entityApiName": 'Opportunity',
            "recordTypeId": RecTypeID,
            'defaultFieldValues': {
                'Type' : 'Land',
                'Budget_Status__c' : 'Pending',
                'StageName' : 'Pursuit Identified',
                'CloseDate' : component.get('v.todaysDate')
            }   
            
            
        });
        createRecordEvent.fire();
    }
```
AWS AmazonLinux 時刻同期設定

# 背景
- 2022/08/04時点の情報
- AWSの時刻同期についてのまとめ

# 目次
1. タイムゾーンの設定
2. 時刻同期設定

# 環境
```
# uname -a
Linux CMS_ALLIN_01 5.10.130-118.517.amzn2.x86_64 #1 SMP Wed Jul 13 16:51:52 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

# cat /proc/version
Linux version 5.10.130-118.517.amzn2.x86_64 (mockbuild@ip-10-0-43-203) (gcc10-gcc (GCC) 10.3.1 20210422 (Red Hat 10.3.1-1), GNU ld version 2.35-21.amzn2.0.1) #1 SMP Wed Jul 13 16:51:52 UTC 2022

# cat /etc/system-release
Amazon Linux release 2 (Karoo)
```

# タイムゾーンの設定
- タイムゾーンの確認
```
timedatectl status
▼以下の結果であればOK
-----------------------------------------------
      Local time: Thu 2022-08-04 12:48:37 JST
  Universal time: Thu 2022-08-04 03:48:37 UTC
        RTC time: Thu 2022-08-04 03:48:38
       Time zone: Asia/Tokyo (JST, +0900)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
-----------------------------------------------
```

- 日本への変更方法
```
timedatectl set-timezone Asia/Tokyo
```


# AWSでの時刻同期
- [Amazon Time Sync Service で時間を維持する](https://aws.amazon.com/jp/blogs/news/keeping-time-with-amazon-time-sync-service/)
    - AWSでサービスを持っているので利用することが可能
    - 外部にアクセスする必要がなく、プライベート通信
    - chronyサービスにより実装

# chronyについて
- [Amazon Linux 2はNTPにChronyとAmazon Time Sync Serviceを使う](https://dev.classmethod.jp/articles/amazon-linux2-use-chrony-and-time-sync-service-by-default/)
- サービス確認
```
# systemctl status chronyd
```

- 設定ファイル

```
# cat /etc/chrony.conf
```
- 接続先確認
```
chronyc sources -v
```
Athenaを使ってAWSリソースの削除ログをみつける

### Athenaを使ってAWSリソースの削除ログをみつける

- KMSが削除されてしまったので、その犯人探し

```
SELECT * 
FROM "$DBNAME"."$TABLENAME"
CROSS JOIN UNNEST(resources) AS t (resource)
WHERE eventSource = 'kms.amazonaws.com' 
AND resource.arn = 'arn:aws:kms:ap-northeast-1:XXXXXXXXXXXX:key/YYYYYYYYYYYY'
AND NOT eventName = 'Decrypt'
limit 100;
```
DOIなどのリダイレクト先を取得する

# はじめに
学術雑誌のDOI（doi.or）やhandle.net などのURLをPANDASのSeriesから、リダイレクト先（提供元）を取得し、戻します。
DOIなどでなくても、何らかの理由でリダイレクトされていれば構いません。
取得処理自体は、以下をそっくりそのまま利用させていただきました。ありがとうございます。
[Python で HTTP リダイレクト先の URL を取得する](https://qiita.com/niwasawa/items/d3f5ceb5f2f9d8784571)

# 変換元データ
```python
import pandas as pd
df = pd.Series(['https://doi.org/10.20730/100240356', 'http://hdl.handle.net/2324/4245',
               'https://repository.dl.itc.u-tokyo.ac.jp/search?search_type=2&q=6092'], index=['1', '2', '3'])
```

# 変換
```python
import urllib.request
from time import sleep

# リダイレクトしないハンドラークラス
class NoRedirectHandler(urllib.request.HTTPRedirectHandler):
  # HTTPRedirectHandler.redirect_request をオーバーライド
  def redirect_request(self, req, fp, code, msg, hdrs, newurl):
    self.newurl = newurl  # リダイレクト先URLを保持
    return req

# リダイレクト先 URL を取得する関数
def get_redirect_url(src_url):
  # リダイレクトしないハンドラーをセット
  no_redirect_handler = NoRedirectHandler()
  opener = urllib.request.build_opener(no_redirect_handler)
  try:
    sleep(0.1)
    with opener.open(src_url) as res:
      return src_url
  except urllib.error.HTTPError as e:
    if hasattr(no_redirect_handler, "newurl"):
      return no_redirect_handler.newurl  # リダイレクト先 URL を返す
    else:
      print('else:', src_url)
      return src_url
  except Exception as e:
    print('except Exception:', src_url)
    return src_url
    
df_redirect = df.map(get_redirect_url)
```
# 結果
```python
pd.set_option("display.max_colwidth", 200)
print(df_redirect)
```

```
1                           http://kotenseki.nijl.ac.jp/biblio/100240356
2               https://www.lib.kyushu-u.ac.jp/publications_kyushu/jagri
3    https://repository.dl.itc.u-tokyo.ac.jp/search?search_type=2&q=6092
dtype: object
```
[ServiceNow] Flow Designerでイベントをトリガーする

## やりたいこと
Flow Designerでイベントをトリガーしてメール通知を送りたい

## 確認したバージョン
San Diego

## やり方
Create Recordでsyseventにレコードを作成
|Field|Value|
|:--|:--|
|Name|イベント名|
|Table|テーブル名|
|Instance|SysID|
|State|ready|
|Param1|オプション|
|Param2|オプション|

![TriggerEvent_FD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676866/88b8906b-f002-f1c6-9c60-3bdd32baa4f5.png)
Firestoreのセキュリティルールで1づつ加算することだけを許可する

# どういうことか
以下のようなドキュメントの時
```json-doc
{
  aaa: 0,
  xxx: 12,
  nnn: 42,
}
```
それぞれのフィールドを1づつ加算することのみを許可したい。
# どうやるか
ルールに、どのフィールドをアップデートするかを伝えるために、`update`フィールドを追加する。
上の`xxx`に1加算するのであれば、
```js
{
  aaa: increment(1),
  update: "aaa",
}
```
というデータを送信することにすることで、どのフィールドが更新されるかをルールに伝える。
# 失敗した例
私は、`request.resource`には、**update関数に渡したものが入ってくるのだと勘違いしていた。**
公式ドキュメントにも書いてある通り、`request.resource`には、
**オペレーション後の保留中のドキュメントの状態が含まれます**、とのことである。

https://firebase.google.com/docs/firestore/security/rules-conditions#data_validation

これを知らずに、私はこのように書いた。
```js
allow update: if request.resource.data.size() == 2 &&
    request.resource.data[request.resource.data.update] 
      == (resource!=null 
      && resource.data.keys().hasAny([request.resource.data.update])
      ? resource.data[request.resource.data.update] : 0) + 1;
```
1行目で、`update`と`incrementするフィールド`以外を更新しようとするリクエストを弾いたつもりだった。

ドキュメントに何も状態が保存されていないときなら、`request.resource.data`のサイズは2だが、
ドキュメントにすでに何らかのデータが保存されている状態だと、サイズは「保存されているデータ数」または「それ+1」となる。
なので、このルールでは、2つ目以降のデータを保存しようとすると、すべてリジェクトされる。

# どうするか
そこで、何かいい方法がないかと探していると、こんなものを見つけた。

https://firebase.google.com/docs/reference/rules/rules.Map#diff

どうやら、マップの差分を返してくれるらしい。これを使うしかなさそうだ。

長くなってきたので、関数にしてしまった。
```js
    function allowUpdate(request,resource){
      let safeResource = resource != null ? resource : {"data":{"update":""}};
      let diff = request.resource.data.diff(safeResource.data);
      let affected = diff.affectedKeys();
      let allowedCount = diff.removedKeys().size() == 0 && 
                           (request.resource.data.update == safeResource.data.update
                           ? affected.size() == 1 : affected.size() == 2);
      let allowedDocument = request.resource.data[request.resource.data.update] 
            == (safeResource!=null 
            && safeResource.data.keys().hasAny([request.resource.data.update])
            ? safeResource.data[request.resource.data.update] : 0) + 1;
      return allowedCount && allowedDocument;
    }
```

`update`フィールドは、前回と同じものになる場合と、ならない場合があると思われたので、
同じになる場合はaffectedの大きさが１、そうでない場合はaffectedの大きさが２であればよい。
よって、こうなった。

# 最後に
こんな複雑なことするなら最初からFunctions使えよって話はあると思うのですが、私クレカ持ってないので使えない。
セキュリティルール師みたいになってしまったと反省しております。
shopifyでslick.js使いたい！

### 解決
`index.liquid`の最後尾にslick.min.jsおよびslick用の自作JSを設置することで解決した

### 使用しているテーマはデフォルトではなく購入テーマ

shopify slick で検索してみれば、先駆者様方が情報を出してくれている。
しかし、今回は同じようにやっても出来なかった。

原因について究明はしていないが恐らく購入したテーマに入っている何かと競合していると思われる。
※本当は究明したほうがいいのだろうけど、そこが難しい...言い訳だがタスクに追われているので今回は見逃し
※こういうの究明方法どうしたらいいんだろうか。そこも学ばなくてはいけない。

今回slickを使いたいページはTOPページのみであるため、
`index.liquid` だけ適用されれば良いので、`layout/theme.liquid`に固執する必要はない。

というわけで、色々と試行錯誤。

Shopify Slickの場合に言われている内容は基本的に`<head>`内に書く事だが、
競合してうまく動かない場合は結局のところ、`</body>`直前に書く方が安全であるということ。
つまり、普通にHTMLで使う時と同様にJquery自体の読み込みは`<head>`でやるが、
slick.min.jsやslickを動かすために設定した自作のjsファイルは`</body>`直前におく事で解決した。

具体的にいうと今回の対象（slickを使って動かしたいの）は`index.liquid`のみなので、
`index.liquid`の最後尾にslick.min.jsおよびslick用の自作JSを設置することで解決した。


### 最終構成

実際は、sectionに作るがとりあえず動いたところまで。

```templates/index.liquid
{% comment %}
例なのでコメントアウト
<ul class="slider">
    <li><img src=".png" alt=""></li>
    <li><img src=".png" alt=""></li>
    <li><img src=".png" alt=""></li>
    <li><img src=".png" alt=""></li>
    <li><img src=".png" alt=""></li>
</ul>
{% endcomment %}

{{ 'slick.min.js' | asset_url | script_tag }}
{{ '自作slick.js' | asset_url | script_tag }}
```

```layout/teheme.liquid
{% comment %} 色々あるけど下記以外は省略 {% endcomment %}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
{{ 'slick.css'| asset_url | stylesheet_tag }}
{{ '自作slick.css'| asset_url | stylesheet_tag }}
```


ここに時間をかける、相も変わらず無能である
SwiftUI チュートリアルをやっていく その2

# SwiftUI チュートリアル
SwiftUI Essentialsの二つ目をやっていきます。
https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation

リストビューの作成、UIナビゲーションを学んでいくコンテンツのようです。

# Listを利用する
Listを使用することでUITableViewのようなリストビューが表示できます。
Listのデータ部分は構造体の配列を利用していました。
構造体は下記のように定義され、ランドマーク情報を表現しています。

```swift
struct Landmark: Hashable, Codable, Identifiable {...}
```

`Identifiable`プロトコルについて気になったので調べました。
UITableViewでは自分でどの行にどの情報を表示するかを定義していたが、Listではそれを宣言的に行うため、Identifiableを使用して一意にデータを扱えるようにしているようです。
Identifiableのidプロパティで一意な値を自分で設定することができます。
下記リンクの実装例を見るとUUID構造体を使用することで、実現していました。どの範囲で一意か（アプリの全期間、アプリ起動中、ビュー表示中、etc.）は都度検討する必要があります。

https://software.small-desk.com/development/2021/09/06/swift-whatis-protocol-identifiable/

# jsonファイルからデータを読み込む
landmarkData.jsonがプロジェクトに配置されているので、それを下記のように読み込んでいます。

```swift
guard let file = Bundle.main.url(forResource: filename, withExtension: nil) else {
    fatalError("Couldn't find \(filename) in main bundle.")
}

let data: Data
do {
    data = try Data(contentsOf: file)
} catch {
    fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
```
そしてデコードを行なっています。
```swift
do {
    let decoder = JSONDecoder()
    return try decoder.decode(T.self, from: data)
} catch {
    fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
```
この処理をグローバルメソッドとして定義していました。
こういったファイル読み込みやパース処理などは頻出するので、切り出しておくのは良いなと思いました。
デコードのエラーハンドリングをいつもtry?で握りつぶしてしまい、パース失敗時にどこで失敗しているのか追いづらくなることが多いので、しっかりエラーログを吐かせているのもいいなと思いました。

# Group, ForEach, List
それぞれViewプロトコルに準拠していて、複数のViewを表示する際に利用できます。
Groupは複数のビューをまとめてひとかたまりに扱えるようにできます。一度に同じ修飾子をつけたりできます。また、ViewBuilderのViewが10個までの制約を回避することもできるようです。SwiftUIの独特の記述方法はSwiftのFunctionBuilderによって実現されていて、SwiftUI用にViewBuilderという型が用意されています。このViewBuilderの実装では10個のViewまでしか受け入れられません。11個以上のViewがある場合には、Groupを利用してまとめることで対応が可能のようです。

参考

https://llcc.hatenablog.com/entry/2020/03/22/151751

ForEachとListの違いが気になりました。もう少し勉強を進める必要があります。

# Navigation
NavigationViewにListを追加することで、タップ後の遷移を実装することが出来ます。UINavigationViewよりもわかりやすい気がしました。NavigationLinkにて遷移先のViewを渡すことで、指定することが出来ました。

# Previewのデバイス指定
Xcode14beta4を使用しているためか、iPhoneSEでのプレビューもiPhoneXSMaxでの表示になってしまいました。iPhoneSE2ndの指定となっていたので、3rdに変更してもうまくいきませんでした。一度Previewが失敗するとエラーで動かなくなってしまいました。。

# 所感
ナビゲーション処理を繋ぎこむときに、宣言的UIで実装すると抜け漏れが少なく実装できそうだと感じました。それぞれのカスタムビューに必要な情報をinit時に渡していくようになり、必要な情報の渡し忘れなどが減りそうです。リストビューを作る際のUITableViewから脱して記述量が減るのも魅力的です。特に初心者はどこに何が書いてあるかわからないということが多いので、パッと分かるのは大切だと思いました。
M1 Macでターミナルを閉じてもコマンドを実行させたい！

# コマンドをバックグラウンドで走らせたい！
実行に長時間を有するコマンドの場合、ターミナルからログアウトしても、バックグラウンドで動かしたいですよね。

そんな時、`nohup`が便利です。
今回を本コマンドについて紹介します。

## nohupを使ってみよう
ターミナルがzshの場合、コマンドは基本的にこのようになります。
```
nohup COMMAND_PROGRAM &!
```
`nohup`と`&!`で実行したいものを挟み込むって感じです。これでOKです。

## nohupがうまくいっていたか確認したい。
`nohup`で実行されたプログラムのログは、同ディレクトレリで`nohup.out`というファイルに書き込まれます。`nohup.out`のテキストを見れば、実行がうまくいったかわかりますよ。

## ちょっと補足
筆者がnohupを調べるにあたって、注意したほうが良いと思った点を紹介します。

### &!じゃなくて&じゃないっけ？
bashの場合、`&!`ではなく`&`ですね。
お使いのターミナルが、どのシェル（bash, zshなどなど）か確認しておくことも大事ですね。
　
### 画面を閉じたらプロセスがとまっちゃうんだけど
スリープしてしまっていると考えられます。
[過去記事](https://qiita.com/bacbac/items/c59029ed2c25e7a237df)に、画面を閉じてもスリープしない方法を紹介しているのでご参照ください。
ファイルにアクセス権を付与しよう

# エラーの原因がわからない！！
ターミナル上でプログラムを走らせようとしても動かないことがありますよね。
エラーメッセージの通りに修正しても、いまいちうまくいかなかったり、そもそもメッセージの意味がわかんないこが多くあります。

そんな時、原因の候補としてアクセス権（パーミッション）が考えられます。
今回はそれについて説明します。

#　そもそもアクセス権って？
知っている人は飛ばしてください。
アクセス権によって、ユーザーごとにファイルへのアクセスの許可または禁止を設定できます。
ユーザーは「所有者」「グループ」「その他」で分類され、それぞれにパーミッションの設定ができます。

ファイルへのアクセス権は三つで分類されます。権限の情報は`ls　-l`で確認でき、それぞれアルファベットで表記されます。
| アクセス権 | 表記 | 説明 |
|:-:|:-:|:-|
| 読み取り | r | 『read』　ファイルの読み取りが可能（内容表示） |
| 書き込み | w | 『write』　ファイルの書き込みが可能（編集や上書きコピーなど） |
| 実行 | x | 『execute』　ファイルの実行が可能（プログラムやシェルスクリプトの実行） |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519906/e3eeb5ee-00f1-70eb-e8ff-9def1b72077f.png)

## chmodでアクセス権を付与しよう
`chmod`は権限を付与するコマンドです。
```
#使用例
chmod u+x FILE #ユーザー(u)に実行(x)権限を与える
```
`ls -l`で権限を確認して、プログラムを実行してみましょう！

# これで解決しない場合・・・
はよくありますよね。
エラー対処によってスキルは向上していくと思うので、めげずにトライしていきましょう！！
文書をしまう場所がディレクトリ

# ファイルとディレクトリの関係性
ファイルが文書を表す。
ディレクトリはそれを束ねるためのフォルダの役割を果たす。
ディレクトリのことをフォルダとも言われる。

ハードディスクの中は乱雑に散らかっている。のでディレクトリを使うことによって用途別の仕切りができてどこにあるかを把握することができる。

## 気づき
```ディクレクトリ⇨ファイルの集まり```という関係性なのか。

# ルートディレクトリとサブディレクトリ
ディレクトリには、ファイルだけじゃなくて、他のディレクトリも入れることができる。
　補助記憶装置全体に階層構造（ツリー構造)を持たせて管理する。
他のディレクトリに含まれるディレクトリを```サブディレクトリ```という。
階層構造の一番上位に位置するディレクトリは```ルートディクトり```
仮想構造の一番上位に位置するディエレクトリは```ルートディクトリ```という。
```/```や```¥```がルートディレクトリを表す。

## 気づき
p２７３の図のようにカテゴリに分けてディレクトリに分けている。

# カレントディレクトリ
ディレクトリの縦の関係性を確認した。
まだ縦の関係がある
```今開いて作業している```ディレクトリをのことを```カレントディレクトリ```いう。
あるディレクトリを開いたらサブディレクトリとファイルがあるとする。
つまりこのディレクトリの範囲はサブディレクトリとファイルまでとなる。
p２７４ページの図を参照

カレントディレクトリを含む一階層上のディレクトリを```親ディレクトリ```と呼ぶ。

# 問題を解いた時の気づき
## ホームディレクトリとは？
* ユーザがログインした際、最初に移動するディレクトリ（フォルダ）のことです。
出典 https://26gram.com/directory-meaning

* ホームディレクトリとは、コンピュータのストレージ（外部記憶装置）内に用意された、個々の```利用者が自由に使えるディレクトリ。```一般的にはUNIX系OSでアカウントごとに割り当てられるファイルシステム上の領域を指す。
 利用者は自分に割り当てられたホームディレクトリ内には自由にファイルやサブディレクトリを作成することができる。```ログインするとカレントディレクトリ（ファイルシステム内での現在地）が自分のホームディレクトリに設定される```ことが多い。多くのシェルでは```「~」（チルダ）```という記号が自分のホームディレクトリを表している。
各ホームディレクトリが実際にはどこにあるかはシステムによって異なるが、```Linuxなど多くのUNIX系OSでは通常「/home/ユーザー名」```という場所に作成されることになっている。```macOS（Mac OS X）では「/Usesrs/ユーザー名」```になる。
出典 https://e-words.jp/w/%E3%83%9B%E3%83%BC%E3%83%A0%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA.html#:~:text=%E3%83%9B%E3%83%BC%E3%83%A0%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%A8%E3%81%AF%E3%80%81%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF,%E4%B8%8A%E3%81%AE%E9%A0%98%E5%9F%9F%E3%82%92%E6%8C%87%E3%81%99%E3%80%82

```ルートディレクトリ > ホームディレクトリ > カレントディレクトリ(ホームディレクトリと同じの時もある）　> カレントディレクトリ（全体を移動する場合ある）```
こんなイメージかな。

出典 キタミ式イラストIT塾　基本情報技術者　令和03年
DialogFragmentのUITestの書き方

# 何をしたいか
DialogFragmentのUITestを記述する際にtestRuleにActivityを渡してダイアログ表示までの遷移部分を記述するのがどうにも面倒でダイアログだけを最初から開いて確認する方法がないか探していたところ解決したのでその共有記事です。

公式記事はこちら
https://developer.android.com/training/basics/fragments/testing?hl=ja

今回は最小の実装でDialogFragmentを対象として記述していきますので詳しいところは上記記事参照です。
testにはEspressoを使用しています。

# 方法
まずapp配下のbuild.gradleに下記を追加します。

```gradle
dependencies{
    debugImplementation 'androidx.fragment:fragment-testing:${version}'
}
```

次にテストメソッドで
```kotlin
@Test
fun test(){
    val scenario = launchFragment<DialogFragment>()
    scenario.recreate()
    assertDisplayed(R.id.viewId, "text")
}

```

これで無事に通りました。超簡単
可愛い無線タブレットスイッチ と小型モジュール「XBee」

## <　ブライダル用　Wifi　リモートスイッチ　＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/0b185f28-4816-76f6-0cfc-3e12cdcadfff.png)
### 2010　初めてのAndroidアプリ当時タブレットが安価になりデモ用に試作しました。
![AndroidシュミレーターWelcameBaloon.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/47b1a743-8364-f9a4-21b4-f6c813ce35ef.jpeg)

## IoTプロトタイプの無線化におすすめ！ 無線通信規格ZigBeeに対応した小型モジュール「XBee」を使ってみよう
https://codezine.jp/article/detail/9773

https://bokunimo.net/bokunimowakaru/std-zigbee.html

## 2010当時の価格です
![XBeee.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/7b8c56d9-f6c2-dc85-c5b2-86cfc43bcc03.jpeg)
無線2.4ギガ帯リモコン可搬型4CHソレノイド制御

## 2.4ギガ帯リモコン4CH　遠距離制御（赤外線リモコンの届かない10m以上の距離）2010年試作記事です
![2.4ギガ帯リモコン4CH.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/c057bb79-1798-9b5f-a8cd-de4ecc27a410.jpeg)
![2.4ギガ帯リモコン4CH出荷説明.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/ee48e66d-319c-4083-3596-8c092c118d5c.jpeg)
## バッテリーで可搬型試作
![実負荷・試験101024.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/a801cbe5-9518-41be-4837-9d90087a7526.jpeg)

![ダイセン2.4Gリモコン.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/ac90dbba-7a89-ad05-b3cf-9e215f08a60b.jpeg)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/5810373d-7e0b-f59f-f058-9b049842a9fd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/05ae307d-2313-c47a-cd2d-6a98bb46432e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/a4a65871-a811-c1da-8354-2116bc3420f2.png)
filter_inputの早見表

## 環境
PHP 7.4

## filter_inputとは
[filter_input](https://www.php.net/manual/ja/function.filter-input.php)をご確認して下さい。
※ typeを `INPUT_GET` のみで検証しておりますので、POSTで利用する場合には下記の早見表は参考までのご確認に留めていただくようにお願いします。

## filter_input早見表
| $value | FILTER_DEFAULT | FILTER_VALIDATE_INT | FILTER_VALIDATE_FLOAT | FILTER_VALIDATE_BOOLEAN |
|:-:|:-:|:-:|:-:|:-:|
| 1 | string(1) "1" | int(1) | float(1) | bool(true) |
| 0 | string(1) "0" | int(0) | float(0) | bool(false) |
| '１' | string(3) "１" | NULL (false) | NULL (false) | bool(false) |
| 'a' | string(1) "a" | NULL (false) | NULL (false) | bool(false) |
| '0.1' | string(3) "0.1" | NULL (false) | float(0.1) | bool(false) |
| '1a1' | string(3) "1a1" | NULL (false) | NULL (false) | bool(false) |
| '001' | string(3) "001" | NULL (false) | **float(1)** | bool(false) |
| 'on' | - | - | - | bool(true) |
| 'yes' | - | - | - | bool(true) |
| 'true' | - | - | - | bool(true) |
| 'false' | - | - | - | bool(false) |

## 検証内容
下記の `int`, `float`, `string`, `checkbox` にそれぞれの値を送り確認しました。

```
filter_input(INPUT_GET, 'int', FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
filter_input(INPUT_GET, 'float', FILTER_VALIDATE_FLOAT, FILTER_NULL_ON_FAILURE);
filter_input(INPUT_GET, 'string');
filter_input(INPUT_GET, 'checkbox', FILTER_VALIDATE_BOOLEAN);
```

### 第４引数の `FILTER_NULL_ON_FAILURE` について
第４引数を指定しない場合の失敗した時の返り値がdefaultでは `bool(false)` となっている。
`FILTER_NULL_ON_FAILURE` を使用することで `bool`から `NULL` を返してくれるようになる。
[Python] jsonファイルが開けない…(JSONDecodeError: Extra data: line * column * (char *))

## 事の発端

jsonファイルをjson.loadで開こうとしたら以下のエラーが出た。
```python
import json
with open("sample.json") as f:
    df = json.load(f)

>>> JSONDecodeError: Extra data: line 2 column 1 (char 23)
```
対象のjsonファイルは以下のようになっていた。
```json
{"id": 0, "data": 100}
{"id": 1, "data": 200}
{"id": 2, "data": 300}
```

## json.loadで読み込むための修正
以下のようにjsonファイルを修正すると開ける。
```json
[
  {"id": 0, "data": 100},
  {"id": 1, "data": 200},
  {"id": 2, "data": 300}
]
```
リストの形式にしてあげればよいということである。(最後のデータの後ろにカンマは入れてはいけない)

```python
with open("sample.json") as f:
    df = json.load(f)

print(df)
>>> [{'id': 0, 'data': 100}, {'id': 1, 'data': 200}, {'id': 2, 'data': 300}]
```

## jsonファイルの中身を変更しないで読み込む方法
ファイルの内容を変更すれば読み込めるとはいえ修正は面倒…という場合は以下のようにすれば読み込むことができる。

```python
df = [json.loads(line)
        for line in open("sample.json", 'r', encoding='utf-8')]

print(df)
>>> [{'id': 0, 'data': 100}, {'id': 1, 'data': 200}, {'id': 2, 'data': 300}]
```
一行ずつ読み込みリストを作成するパターンですね。読み込んだ結果もファイルを修正したパターンと同じになります。
Linux プロセス・シグナル・psコマンドについて（自分用メモ

プロセスとは、システム上で動作しているプログラムの最小単位。PID（プロセスID）およびプロセス名(コマンド名)はpsコマンドで調べることができます。

ps ［オプション］

psオプション一覧
・a　他のユーザのプロセスも表示（xオプションとの併用で全てのプロセスを表示）
・u　プロセスの実行ユーザ名も表示
・x　制御端末のないデーモン等のプロセスも表示
・f　プロセスの親子関係をツリー上で表示（pstreeと同様）
・-e　全てのプロセスを表示
・-f　完全なフォーマットでプロセスを表示
・-p | p PID　指定したPIDのプロセスを表示
・-l | l　親プロセスのPIDや実行優先度を決定するnice値(NI)なども併せて表示


また、pgrepコマンドで実行中のプロセスから特定の名前を持つプロセスIDを検索することができます。

pgrep [ オプション ] 検索パターン

検索パターンには拡張正規表現が指定できます。-lオプションを使うと、検索パターンにマッチしたプロセス名も表示されます。

-uオプションを使うと、特定のユーザーが実行したプロセスのみを検索対象とすることができます。
例）


シグナル
・HUP(SIGHUP)　１　ハングアップ（端末の切断による終了）
・INT(SIGINT)　２　割り込みによる終了（Ctrl+Cとおなじ）
・KILL(SIGKILL)　９　クリーンアップせずに終了（強制終了）
・TERM(SIGTERM)　１５　クリーンアップして終了（デフォルト）
・CONT（SIGCONT)　１８（環境依存）　一時停止のプロセスを再開
・STOP(SIGSTOP）　１９（環境依存）　一時停止
・TSTP(SIGTSTP)　２０（環境依存）　端末から入力された一時停止（Ctrl+Zと同じ)

kill、killall、pkillコマンドで、プロセスに終了や再起動などのシグナル(命令)を送ることができます。
kill [-シグナル名または-シグナル番号] プロセスID
または
kill -s [シグナル名またはシグナル番号] プロセスID

killall [-シグナル名または-シグナル番号] プロセス名(コマンド名)
または
killall -s [シグナル名またはシグナル番号] プロセス名(コマンド名)

pkill [-シグナル名または-シグナル番号] プロセス名(コマンド名)
または
pkill --signal [-シグナル名または-シグナル番号] プロセス名(コマンド名)


killコマンドはプロセスID(PID)を使用して単一のプロセスにシグナルを送りますが、killallコマンドはプロセス名(コマンド名)を使用して、同じプロセス名の全てのプロセスに対してシグナルを送ります。

例）　kill -SIGHUP 1133
例）　killall -SIGHUP mycommand

また、pkillコマンド、もしくはkillallの-rオプションを使うことで、プロセス名を拡張正規表現で指定してシグナルを送ることができます。

また、killコマンドはジョブ番号を指定し、ジョブにシグナルを送る事もできます。ジョブ番号は「%ジョブ番号」と指定します。

例）　kill %2

ジョブ番号はjobsコマンドで確認することができます。
Java で圧縮ファイル gzip (.gz) ，bzip2 (.bz2) を読み込む

以下サンプルでは，単純なテキストファイルを gzip，bzip2 で圧縮されたファイルを読み込むものとします．


gzip はJVM標準のライブラリだけで読み込み可能です．
java.util.zip.GZIPInputStream を利用します．

```java
package hello.compress;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPInputStream;

public class HelloGZipMain {

	public static void main(String[] args) throws Exception {
		File gzFile = new File("hello-compress.txt.gz");
		try (InputStream is = new FileInputStream(gzFile);
				// java.util.zip.GZIPInputStream
				GZIPInputStream gzis = new GZIPInputStream(is);
				InputStreamReader isr = new InputStreamReader(gzis, StandardCharsets.UTF_8);
				BufferedReader br = new BufferedReader(isr);) {
			String s;
			while ((s = br.readLine()) != null) {
				System.err.println(s);
			}
		}
	}
}
```

bzip2 ファイルは Apache Commons Compress を利用するのがベストかと思います．

https://mvnrepository.com/artifact/org.apache.commons/commons-compress

```java
package hello.compress;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.commons.compress.compressors.CompressorException;
import org.apache.commons.compress.compressors.CompressorInputStream;
import org.apache.commons.compress.compressors.CompressorStreamFactory;

public class HelloBZ2Main {
	public static void main(String[] args) throws Exception {
		File bz2File = new File("hello-compress.txt.bz2");
		// try-with-resources
		try (FileInputStream fis = new FileInputStream(bz2File);
				BufferedInputStream bis = new BufferedInputStream(fis);
				// see https://mvnrepository.com/artifact/org.apache.commons/commons-compress
				// org.apache.commons.compress.compressors.CompressorStreamFactory
				CompressorInputStream cis = new CompressorStreamFactory() //
						.createCompressorInputStream(bis);
				BufferedReader br = new BufferedReader(new InputStreamReader(cis, "UTF-8"));) {
			String line;
			while ((line = br.readLine()) != null) {
				System.err.println(line);
			}
		} catch (CompressorException e) {
			throw new IOException(e);
		}
	}
}
```


以上．
Lihgtsail上のWordpressで急に負荷が上がった時の対応

AWSサービスの一つLightsailは、EC2以上に簡単に仮想サーバを作って利用できるので便利です。

# 起こった現象
早速、今あるWordPressベースのWebサイトをどんどんこちらに移行を進めています。
WordPressサイトを7,8個Lightsail上に移行させて稼働させたところ、急にCPU使用率が上がってレスポンスが全く返ってこなくなってしまいました。

topやpsコマンド、Apacheのerror_logなどを確認しながら原因を調べていたのですが今までにない現象だったのでなかなか原因救命に手こずりました。

結果的に原因はphp-fpmでした。今まで全く触ったことがなかったので設定変更もちょっと怖い分野。。。
以下の記事も参考にさせていただきながら、試しに静的構成にして同時稼働数も抑えたところ無事に安定しました。

https://qiita.com/YasumiJP/items/fd36b4a7df08f92d2da4

# 具体的な対応内容
LightsailはBitnamiベースなので参考にした記事とは設定ファイルのある場所が異なります。
具体的には、~/stack/php/etc/php-fpm.d/www.conf内で以下のように修正。

```:www.conf
# pm=dynamicの記載を以下に変更
pm=static
```

次に~/stack/php/etc/memory.confを以下のように修正
```:memory.conf
pm.max_children=1 # CPU数に合わせる
pm.max.request=1500 # GoogleAnalyticsなどでPV数を確認しながら設定するといいかも
```

その後php-fpmを再起動
```
sudo /opt/bitnami/ctlscript.sh stop apache
sudo /opt/bitnami/ctlscript.sh restart php-fpm
sudo /opt/bitnami/ctlscript.sh start apache
```

その後AWSのLightsail管理画面でメトリクスを表示し、CPU使用率が安定しているかを確認してください。
![スクリーンショット 2022-08-04 10.27.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1926542/1e864cc9-ee9b-e5bf-4e7f-9709040d5091.png)

上のグラフを見ると、夜10:00くらいに設定変更作業していたのですが無事にその後安定するようにな他のがわかります。
ひとまず安心。とはいえ、CPU数を増やすなどの対策も今後考えておいた方がよさそうです。

ついでにCPU使用率が一定量を超えるとアラートが飛ぶようにも設定しておきました。
CO2センサーSCD41ボード【FSNS-SCD41-X00】を使ってみた

新型コロナは相変わらずすごい勢いで感染者が増えていますが、
3密や換気に関しての意識は以前より薄れてきたように思えます。
ただ、換気に関してはコロナが収まったとしても必要な事だと思っています。

今回換気の目安になるCO2計測用のセンサー使ってみました。
使ったのはSensirion社のSCD41を搭載したボードで、
マルツで販売されている、SCD41搭載CO2温湿度センサーモジュール【FSNS-SCD41-X00】
です。

これはSensirionが販売している SCD30 というセンサーの基板サイズとピン配置を互換にして
SCD41をのせたモジュールになります。

SCD30の販売価格が税込￥8,677円で
こちらのボードが税込￥7,040円となっていますので1600円位安くなっています。
(共にマルツでの販売価格)
多分SCD30を使うように設計された基板で安価なSCD41を使うために開発された基板だと思います。

【FSNS-SCD41-X00】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/969ed6c4-ad6d-4f92-82bf-2c206a293d5d.png)

【SCD30】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/c6551c23-cf2b-d465-acf9-f9b50fea845d.png)

SCD30とSCD41のデータの比較をこちらに公開していますので参考にしてください。
[CO2センサーデータ比較](https://qiita.com/kaz19610303/items/4bddf6ed0f40efc03f3b)

マルツの販売ページには解説や解説へのリンクが有りませんが
[[VOL-23]SCD4X, SCD30 Exchangeボード(クレイン電子)](https://crane-elec.co.jp/products/oem/vol-23/?fbclid=IwAR1D_-cHg1lNis6M-YiOkOWmLxwMTFI2sgr8DAZbtyyHEpZN0cwoGkstwZA)
こちらに回路図やRaspberry piでのサンプルプログラムが公開されていますので参考にしてください。

マイコンボードとの接続は
VCC
GND
SCL
SDA
の4本を接続するだけです。
VCCはSCD41の動作電源が **2.4 V to 5.5 V** となっていますのでその範囲にしてください。

なお1点注意しないといけない点が有ります。
回路図を見てもらうと、I2C信号 のプルアップがジャンパーとなっていて標準ではプルアップされていません。
このボードを単体で使う場合や、他のボードでI2Cがプルアップされていない場合は、
必ず **ジャンパーを半田でショートしてプルアップ**してください。
(I2Cはプルアップされていないと動きません)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/c3a40453-9f16-2fc1-38b7-06c37b255fc6.png)

Raspberry piで使う場合の参考ページへのリンクは先ほどのクレイン電子のページに有りますので
ここではArduino UNOで使う場合を例にします。

[Github Sensirion/arduino-i2c-scd4x](https://github.com/Sensirion/arduino-i2c-scd4x)
こちらからライブラリをダウンロードして Arduino IDE にセットアップしてください。
(ライブラリの追加方法に関しては色々と紹介されているのでここでは割愛します)
ライブラリの追加が終わると
ファイル->スケッチ例に
Sensirion I2C SCD4x -> exampleUsage
が表示されるので、これを選択して実行してください。
![スクリーンショット 2022-08-04 094719.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/61237e16-1fbb-ac70-72a1-c4c2dad6df6b.png)

実行してしばらくは校正が出来ていない為、データがばらついたり、おかしかったりしますのでしばらく動かしたままにして下さい。
CO2の濃度の目安としては外で**400ppm**位です。

なおこのサンプルは他のマイコン(ESP系、Spresenses等)でも動きます。
(SpresenseはIO電源が**1.8V**なのでその点ご注意ください。)

※補足
このSCD41ボードはGROVEコネクターを実装できるようになっていて、
それを付ければGROVE用のケーブルでも使えるようになります。
マルツで販売されているGROVE用のSCD41センサーの中では低価格となっています。

このボードを使うと高性能なCO2計測器を作ることが出来ますので、皆さんぜひ挑戦してみて下さい。
なおこの記事に関して質問等がある場合は マルツ様やクレイン電子様にはしないようにお願いします。
pythonクロージャとnonlocal

# この記事
`nonlocal` ってどこに使うだろうって思ってたけど、ここだったのね、って話。

# クロージャ作成例
```python
# クロージャを用いた関数生成関数
def MakeFunc(a):
	""" a : 作成する関数に指定するパラメーター
	"""
	def Func(b):
		""" b : 作成された関数実行時の引数
		"""
		nonlocal a # バグ回避のためのおまじない
		return a*b

	return Func

# クロージャ使用
F2 = MakeFunc(2)
print(F2(3))
```

## pythonでクロージャを使う場合の注意点
- 関数内で代入が行われた変数は、global文またはnonlocal文で宣言が無い限り、その関数内のローカル変数となる
- よって、上位関数のスコープにあり、クロージャに用いる変数は、上記の例のように`nonlocal`文で宣言しておくことで、意図せずにバグを生じることが防げる。
- `nonlocal`文で宣言することで、クロージャであることが明確になるので、不要な場合にもそうした方が良い。
※上記例ではnonlocal文が無くても問題無い


## 確認例
以下は、この辺の動作をJupyter上で確認したものです。

### 例1：バグで実行時エラーとなる書き方
```python:In [1]:
def MakeClosure(a):
    def Func(b):
        print(a)
        a = a + b
        print(a,b)
    return Func
```
```python:In [2]:
F1 = MakeClosure(1)
F1(2)
```
```python:
--------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
Input In [2], in <cell line: 2>()---> 1 F1(2)
Input In [1], in MakeClosure.<locals>.Func(b) 2 def Func(b):
---> 3 print(a) 4 a = a+ b 5 print(a,b)
UnboundLocalError: local variable 'a' referenced before assignment
```

### 例2：別の変数を用いて例1を修正
```python:In [4]:
def MakeClosure2(a):
    def Func(b):
        print(a)
        c = a+ b
        print(c,b)
    return Func
```
```python:In [5]:
G1 = MakeClosure2(1)
```
```python:In [6]:
G1(2)
```
```python:
1
3 2
```
```python:In [7]:
G9 = MakeClosure2(9)
```
```python:In [8]:
G9(2)
c
9
11 2
```

### 例3：`global`を用いて例1を修正し、実行時エラー
```python:In [9]:
def MakeClosure3(a):
    def Func(b):
        global a
        print(a)
        a = a+ b
        print(a,b)
    return Func
```
```python:In [10]:
H1 = MakeClosure3(1)
```
```python:In [11]:
H1(2)
```
```
Traceback (most recent call last)
Input In [11], in <cell line: 1>()---> 1 H1(2)
Input In [9], in MakeClosure3.<locals>.Func(b) 2 def Func(b): 3 global a
---> 4 print(a) 5 a = a+ b 6 print(a,b)
NameError: name 'a' is not defined
```

### 例4：`nonlocal`を用いて例1を修正し
```python:In [12]:
def MakeClosure4(a):
    def Func(b):
        nonlocal a
        print(a)
        a = a+ b
        print(a,b)
    return Func
```
```python:In [13]:
I1 = MakeClosure4(1)
```
```python:In [14]:
I1(2)
```
```python:
1
3 2
```