OmniAICreator/Qiita-1.07M huggingface dataset:
VIMでよく使うコマンド

Visual Studio Codeを使って、普段のPythonやHTMLなどを書いています。プログラマーではないですが、やっぱりVIMを使った方がストレスフリーですので、以前使い慣れたVIMを再度使い始めました。5年ぶりですね、結構忘れたので、使う際にこちらを参照できるように、メモしておきます。

使うのはVisual　Studio　Codeのいかのプラグインです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/b3b334ed-b3ec-a745-f375-f4019df6a5ba.png)


# :white_sun_cloud: 三つのモード
VIMには、三つのモード：**編集モード**、**コマンドモード**、**ビューアモード**があります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/87713e97-b643-f1c9-a043-0c6440f60b26.png" width=480>

| コマンド | 意味 |
|:-:|:-:|
| `i`  | カーソルの前に挿入  |
| `a`  | カーソルの後ろに挿入  |
| `I`  | 該当行の最初の文字へジャンプして、挿入モードに  |
| `A`  | 該当行の最後の文字へジャンプして、挿入モードに  |
| `v`  | 文字を選択対象として、VisualModeに  |
| `V`  | 行を選択対象として、VisulModeに  |

# :white_sun_small_cloud: よく使うコマンド

|コマンド           |意味          |例     |
|:--            |:--            |:--:   |
|`:q`           |終了           |       |
|`:wq`          |保存して終了       |       |
|`i`            |カーソルの`前`に挿入         |       |
|`a`            |カーソルの`後`ろに挿入         |       |
|`:10`          |10行目         |       |
|`gg`           |１行目         |       |
|`G`            |最終行         |       |
|`x`            |1文字を削除   |       |
|`dd`           |一行を削除       |       |
|`yy`           |一行を複製        |       |
|`n yy`         |n行を複製        |       |
|`p`            |後ろに貼り付け     |       |
|`P`            |前の方に貼り付け |       |
|`u`            |操作の取り消す           |       |
|`/検索文字列`  |検索           |       |
|`n`            |次を探す      |       |
|`N`            |前を探す  |       |
|`:ns/old/new`  |n 行目の最初の old を new に置換して終了       |       |
|`:ns/old/new/g`|n 行目の全ての old を new に置換して終了       |       |
|`:%s/old/new/g`|ファイル全体の検索語句を置換する               |       |
|`:%s/old/new/gc`|置換の度に確認を求める                        |       |

# :one: 移動

`H←（左）`　`J↓（下）`　　`K↑（上）` `L→（右）`すべてのコマンドはCommandModeでしか使えません。
| コマンド  | 意味 |
|:-:|:-:|
| `H / M / L `  | 現在のスクリーンの左上/左中央/左右へ移動	  |
| `０（数字）`  | 該当行の最初へ移動  |
| `^`  |  該当行の最初の文字へ移動 |
| `gg`  |  第一行 |
| `G`  |  最後の行 |
| `w`  | 次の単語の頭へ移動  |
| `e`  | 次の単語の最後へ移動  |
| `b`  | 一つ前の単語の頭へ移動  |
| `ge`  |一つ前の単語の最後へ移動   |
| `$`  |　該当行の最後の文字へ移動 |
| `W`  | 次の単語の頭へ移動、（）＜＞などをignoreする  |
| `E`  | 次の単語の最後へ移動、（）＜＞などをignoreする  |
| `gE`  | 一つ前の単語の最後へ移動、（）＜＞などをignoreする  |

**TIPS:**

| コマンド  | 意味 |
|:-:|:-:|
| 　`ggVG / y`  | 全部選択して複製	  |
| `:%s/^/a`  | すべての行の最初の文字の前に”a”を挿入  |
| `:%s/$/a`  |  すべての行の最後の文字の後ろに”a”を挿入 |

# :two: 編集

| コマンド  | 意味 |
|:-:|:-:|
| 　`d`  | 現在のカーソルから次のコマンドの内容を削除	  |
| 　`dw`  | 	単語削除  |
| 　`dd`  | 	一行削除  |
| 　`dk`  | 	削除して、上へ； `dj`が削除して、下へ  |
| 　`d$`  | 現在のカーソルから行の最後まで消す	  |
| 　`d0`  | 現在のカーソルから行の最初まで消す	  |
| 　`c`  | 上記の`d`と同じ削除ですが、同時に挿入モードへ	  |
| 　`x`  |カーソル文字消す 	  |
| 　`y`  | 現在のカーソルから次のコマンドの内容を複製	  |
| 　`p P`  |貼り付け、前後が違う 	  |
| 　`r`  | 置き換え	  |
| 　`.`  | 繰返し同じ操作	  |
| 　`:registers`  | 查看寄存器的内容	  |
dotnet の使い方

参考ページ
[スクリプトでのインストール](https://learn.microsoft.com/ja-jp/dotnet/core/install/linux-scripted-manual#scripted-install)

## インストール方法
Ubuntu 23.04 にインストールしました。

```bash
wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh
chmod +x ./dotnet-install.sh
sudo ./dotnet-install.sh -i /usr/local/bin
```

## 確認したバージョン

```text
$ dotnet --version
6.0.408
```

## プロジェクトの作成

```bash
mkdir sample
cd sample
dotnet new console --use-program-main
```

次のファイルが作成されます。

```text
$ tree 
.
├── Program.cs
├── obj
│   ├── project.assets.json
│   ├── project.nuget.cache
│   ├── sample.csproj.nuget.dgspec.json
│   ├── sample.csproj.nuget.g.props
│   └── sample.csproj.nuget.g.targets
└── sample.csproj

2 directories, 7 files
```


Program.cs を編集

```cs:Program.cs
namespace sample;
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello, World!");
        Console.WriteLine("こんにちは!");
        Console.WriteLine("Apr/30/2023");
    }
}
```

## プログラムの実行

```text
$ dotnet run
Hello, World!
こんにちは!
Apr/30/2023
```

一度、dotnet run を実行すれば、次のようにしても実行が出来ます。

```text
$ dotnet bin/Debug/net6.0/sample.dll
Hello, World!
こんにちは!
Apr/30/2023
```

## プログラムの改造
もう少し、プログラムを複雑にしてみます。

```cs:Program.cs
namespace sample;
class Program
{
	static void Main(string[] args)
	{
	Console.WriteLine("こんにちは!");
	for (int it=0; it<5; it++)
		{
		Console.WriteLine("it = " + it);
		}
	Console.WriteLine("Apr/30/2023");
	}
}
```

実行結果

```text
$ dotnet run
こんにちは!
it = 0
it = 1
it = 2
it = 3
it = 4
Apr/30/2023
```
全ての行の長さが不定な2次元配列(Ruby)

paiza問題集で下記の問題を**Ruby**で実装しました。

自然数 N と N 個の要素の数列 M が与えられます。1 ≦ i ≦ N の各 i について、i 行目には以下の数列を出力してください。
* 1 以上 M_i 以下のすべての自然数を昇順、半角スペース区切りで出力してください。

```ruby
# 自分の得意な言語で
# Let's チャレンジ！！
num = gets.to_i 
data = gets 
array1 = data.split(' ')
count = array1.length 
for i in 0...count do
    num2 = array1[i]
    str1 = ""
    for j in 1..num2.to_i do 
        if j === num2.to_i 
            str1 = str1 + j.to_s
        else   
            str1 = str1 + j.to_s + " "
        end    
    end 
    puts str1 
end      
```
Azure Functions のローカルデバッグで 'Value cannot be null' のエラーが起こったら

備忘メモ

パッケージ`azure-functions-core-tools`をアンインストール＆インストールのが良さげ。
VSCodeから、uninstallを選ぶとbrewで入れていてもnpmで入れていても両方アンインストールできる。

アンインストールもインストールも分単位で時間がかかるので、コーヒーでも入れに行くのが吉。
超簡単Salesforceの画面フロー作成方法～入力を効率よくするための方法

こんにちは
本橋孝昭です

今回の内容は動画でも公開しています

https://youtu.be/QToa8tKTTkY

<iframe width="560" height="315" src="https://www.youtube.com/embed/QToa8tKTTkY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>


Salesforceには画面フローと呼ばれるものがあります

これはSalesforceの画面を作成してデータの入力をしやすくすることが可能です

しかしながらこの画面フロー。
ちょっと作成してみたいけどどうやって作成したらいいか分かりにくいな

と思ってる方、多いのかと思います

今回は、そんな方のために画面フローを最初から徹底解説します

今回の内容を見れば
このようにホームの画面から画面フローを表示し、
・項目を絞り込んで簡易的に項目を表示させ
・ボタンクリック１つでレコード作成させる

という画面の作成が可能です

![画面作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/07ce9062-e83a-f9a5-0623-2b4af9494b75.png)

このような画面ですね


私があった経験として
・取引先のデータとか作成するのって
（タブをクリックしたり新規ボタンをクリックしたり保存したりで）大変だよね
と言われ、Salesforceにデータを入力してくれない　というかたとても多く見てきました

そんな話は、この画面フローでおしまいですね

この画面フローを作成すれば、見てください。もうホーム画面に取引先作成画面が出てますね
そして、もう保存ボタンも出てますね
これでSalesforceユーザは簡易的に情報を入力し、なんと保存ボタンクリック１つで取引先を作成することが可能なんです

さあ、ではそんな画面フローはどのように作成すればいいのか見ていきましょう


画面フローの完成図はこのようになっています

![画面フロー1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/023e78dd-11ad-236c-3f77-0182878abc9a.png)


開始画面はこちらです

![作成画面1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/c030c456-c981-251e-573e-fee458819dcb.png)


終了画面はこちらです

![作成画面２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/fc8cc26a-352f-bd2b-02dd-b5303d0c6d48.png)


いかがでしたでしょうか

フローの応用編はこちらから確認可能です

https://qiita.com/Takaa/items/dd2d9dd4842ca6d7c602
phpenvが使えなかった話

anyenvでphpenvをインストールしてパスを通し、php-buildをpluginsフォルダにクローンしたのに

```
phpenv: no such command `install'
```

なぜなのか

ビングさんに聞いてphp-buildのパスも通したらうまくいきました。

```sh
export PATH="$HOME/.anyenv/envs/phpenv/plugins/php-build/bin:$PATH"
```

php-buildのREADMEには書いていないので公式の方法ではないのかもしれませんが、取り急ぎこれで良いです。

一応環境は

M1
macOS 13.3.1（22E261）

Homebrew 4.0.15
Homebrew/homebrew-core (git revision 8e9ff0b0804; last commit 2023-03-03)
p5.jsでつくる天体運動

# はじめに
p5.jsというライブラリを利用してchatGPTと共に作成したアートの紹介です。
「なんかいい」をモットーに作っています。

# 作品紹介
<iframe width="560" height="315" src="https://www.youtube.com/embed/PX5zpmSG7EI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

```math
『planet』
```

## 構想
作品の題名『planet』のとおり、太陽系の惑星の運動をイメージして作ろうとしました。惑星は厳密には楕円軌道を描きますが、全て円運動しているかのように見えるように仕掛ける方針にしました。

## chatGPTにした指示の流れと調整
まずは一つの円が円運動するように指示しました。これはすぐにできました。

一つの円が円運動するようになったら、移動速度・円の大きさ・色・運動の動きをランダムになるようにした上で複数に増やすように指示しました。

最後に円の表示数や円が動く様子は表示された結果を見ながら自分で数値を調整しました。

始めは軌道の配置も太陽系の惑星みたいにしようと考えていたのですが、ランダムに入り交じる様子が星雲を見ているような心地よさを感じこのようにしました。単純な動きでも数が増えることで心地のよい複雑感を生み出せることに感動します。

# 作品解説
## 下準備
必要なファイルや実行方法がわからない人は以下を参考にしてください。

https://qiita.com/keigo1110/items/543423379813b49e7415

## コード
コードはchatGPTが生成しています。
ランダムの数値範囲は調整しています。

```javascript:planet.js
let planets = [];

function setup() {
  createCanvas(2000, 1250);
  colorMode(HSB);
  for (let i = 0; i < 100; i++) {
    let p = new Planet(random(width), random(height), random(5, 30));
    p.color = color(random(255), 255, 255);
    p.speed = random(0.5, 8);
    p.acceleration = createVector(random(-0.1, 0.1), random(-0.1, 0.1));
    planets.push(p);
  }
}

function draw() {
  background(0);
  for (let i = 0; i < planets.length; i++) {
    planets[i].update();
    planets[i].display();
  }
}

class Planet {
  constructor(x, y, r) {
    this.position = createVector(x, y); //位置ベクトル
    this.velocity = createVector(); //速度ベクトル
    this.acceleration = createVector(); //加速度ベクトル
    this.radius = r; //半径
    this.color = color(255); //色
    this.speed = 1; //移動速度
    this.angle = random(TWO_PI); //回転角度
  }


// 更新処理
update() {
    // 加速度を速度に加算
    this.velocity.add(this.acceleration);
    // 速度を制限
    this.velocity.limit(this.speed);
    // 位置に速度を加算
    this.position.add(this.velocity);
    // 境界条件を適用
    if (this.position.x < -this.radius) {
      this.position.x = width + this.radius;
    }
    if (this.position.x > width + this.radius) {
      this.position.x = -this.radius;
    }
    if (this.position.y < -this.radius) {
      this.position.y = height + this.radius;
    }
    if (this.position.y > height + this.radius) {
      this.position.y = -this.radius;
    }
    // 回転角度を更新
    this.angle += 0.05;
  }

  display() {
    push();
    translate(this.position.x, this.position.y);
    rotate(this.angle);
    fill(this.color);
    noStroke();
    ellipse(0, 0, this.radius*2, this.radius*2);
    pop();
  }
}
```

## 拡張性
class Planetとして移動オブジェクトがまとめられているので、この部分をコピペして、さらにchatGPTに指示を出せば違った動作するオブジェクトを生成することができます。上記のコードはコピペで動くので、ぜひ色々試してみてください！

# おわりに
今回は惑星の動きをイメージをして作り始め、星雲の心地よさに落ち着きました。
では、また。
[Git] 動作を試す 実行例13：configでコマンドのエイリアス(別名)を作成する

Gitの動作を理解するために、Gitのコマンドを実際に試して、結果を見てみました。

1つの記事内で一連のGitコマンドが完結しているので、これら一連のコマンドを順に実行させて結果を見ることで、一連のGitの動作を実際に体感でき、一通り独習することが可能です。

※前回記事のリポジトリ状態からの続きになっています。
| [前回記事へ](https://qiita.com/dl_from_scratch/items/ace5508d8e65b90de0aa) | [目次へ：Git関連記事のまとめページ](https://qiita.com/dl_from_scratch/items/597bc28a4787a7901d21) | [次回記事へ](https://qiita.com/dl_from_scratch/items/1e36862ba67bf424a764) |
|:-:|:-:|:-:|

# 実行例

```
※コマンドのエイリアスを設定する
git config --global alias.mylog "log --oneline --graph --all"
git mylog
↓
結果: 
* 94996a0 (HEAD -> master) message4
* 20bbab7 message3
* 00cad71 message2
* 4ace194 message1

※外部コマンドを実行する
git config --global alias.mydir "!dir /b"
git mydir
↓
結果: 
      0 [main] dir (1056) D:\...\PortableGit\usr\bin\dir.exe: *** fatal error - cygheap base mismatch detected

※DOSコマンドは実行されない

-----

※コマンドのエイリアスを削除する
git config --global --unset alias.mydir
```

# 環境

Windows 10、PortableGit-2.40.0-64-bitを使用、全てローカルPC上で実施、GitHub等は不使用。
[Git] 動作を試す 実行例12：grepでファイル内容を検索する

Gitの動作を理解するために、Gitのコマンドを実際に試して、結果を見てみました。

1つの記事内で一連のGitコマンドが完結しているので、これら一連のコマンドを順に実行させて結果を見ることで、一連のGitの動作を実際に体感でき、一通り独習することが可能です。

※前回記事のリポジトリ状態からの続きになっています。
| [前回記事へ](https://qiita.com/dl_from_scratch/items/3a7f9cd778c8d2b5a151) | [目次へ：Git関連記事のまとめページ](https://qiita.com/dl_from_scratch/items/597bc28a4787a7901d21) | [次回記事へ](https://qiita.com/dl_from_scratch/items/a56a161c6654240cb0b4) |
|:-:|:-:|:-:|

# 実行例

```
※現在位置でのコミット済みのファイル内容を検索
git grep "Sample"
↓
結果: 
test1.txt:Sample-Added-11
test1.txt:Sample-Added-12
test1.txt:Sample-Added-13
test1.txt:Sample-Added-14
test2.txt:Sample-Added-**21
test4.txt:Sample-Added-41

git grep "sample"
↓
結果: 
(なし)

git grep "message"
↓
結果: 
(なし)

※-nオプションで行の番号も表示
git grep -n "Sample"
↓
結果: 
test1.txt:1:Sample-Added-11
test1.txt:2:Sample-Added-12
test1.txt:3:Sample-Added-13
test1.txt:4:Sample-Added-14
test2.txt:1:Sample-Added-**21
test4.txt:1:Sample-Added-41

※マッチ回数を表示させる
git grep --count "Sample"
↓
結果: 
test1.txt:4
test2.txt:1
test4.txt:1

※--breakと--headingオプションで、出力を分割して読みやすくする
git grep -n --break "Sample"
↓
結果: 
test1.txt:1:Sample-Added-11
test1.txt:2:Sample-Added-12
test1.txt:3:Sample-Added-13
test1.txt:4:Sample-Added-14

test2.txt:1:Sample-Added-**21

test4.txt:1:Sample-Added-41

git grep -n --break --heading "Sample"
↓
結果: 
test1.txt
1:Sample-Added-11
2:Sample-Added-12
3:Sample-Added-13
4:Sample-Added-14

test2.txt
1:Sample-Added-**21

test4.txt
1:Sample-Added-41

-----

※任意のコミットの内容を検索
git grep -n "Sample" 00cad71
↓
結果: 
00cad71:test1.txt:1:Sample-Added-11
00cad71:test1.txt:2:Sample-Added-12
00cad71:test2.txt:1:Sample-Added-21

git grep -n "Sample" HEAD~2
↓
結果: 
HEAD~2:test1.txt:1:Sample-Added-11
HEAD~2:test1.txt:2:Sample-Added-12
HEAD~2:test2.txt:1:Sample-Added-21

-----

※コミット済みのツリーや作業ディレクトリを検索(正規表現)
git grep -G "Add.*[2-3]"
↓
結果: 
test1.txt:Sample-Added-12
test1.txt:Sample-Added-13
test2.txt:Sample-Added-**21

※文字列の複雑な組み合わせを探したい場合は、--andオプション
git grep -n --break --heading -e "**" -e "Sample" --and ( -e "14" -e "41" )
↓
結果: 
test1.txt
4:Sample-Added-14

test4.txt
1:Sample-Added-41
```

# 環境

Windows 10、PortableGit-2.40.0-64-bitを使用、全てローカルPC上で実施、GitHub等は不使用。
[Git] 動作を試す 実行例11：blameでコピー元を調べる(失敗)

Gitの動作を理解するために、Gitのコマンドを実際に試して、結果を見てみました。

1つの記事内で一連のGitコマンドが完結しているので、これら一連のコマンドを順に実行させて結果を見ることで、一連のGitの動作を実際に体感でき、一通り独習することが可能です。

※前回記事のリポジトリ状態からの続きになっています。
| [前回記事へ](https://qiita.com/dl_from_scratch/items/b3a357a9435bd16752cb) | [目次へ：Git関連記事のまとめページ](https://qiita.com/dl_from_scratch/items/597bc28a4787a7901d21) | [次回記事へ](https://qiita.com/dl_from_scratch/items/ace5508d8e65b90de0aa) |
|:-:|:-:|:-:|

# 実行例

```
(※現在のコミット位置を確認)
git log --oneline -1
↓
結果: 
94996a0 (HEAD -> master) message4

-----

(※恣意的に重複を作成)
echo Sample-Added-12 > test8.txt
echo Sample-Added-1x >> test8.txt
echo Sample-Added-41 >> test8.txt
git add .
git commit -m "blame test"
↓
結果: 
[master ae2c71d] blame test
 1 file changed, 3 insertions(+)
 create mode 100644 test8.txt

git blame -- test8.txt
↓
結果: 
ae2c71d2 (person1 2023-01-01 18:20:15 +0900 1) Sample-Added-12
ae2c71d2 (person1 2023-01-01 18:20:15 +0900 2) Sample-Added-1x
ae2c71d2 (person1 2023-01-01 18:20:15 +0900 3) Sample-Added-41

※-Cオプションで、コードのどの部分をどのファイルからコピーしたのかを調べる
git blame -C -- test8.txt
↓
結果: 
ae2c71d2 (person1 2023-01-01 18:20:15 +0900 1) Sample-Added-12
ae2c71d2 (person1 2023-01-01 18:20:15 +0900 2) Sample-Added-1x
ae2c71d2 (person1 2023-01-01 18:20:15 +0900 3) Sample-Added-41

※全て今回新規のコミット(ae2c71d2)表示となり、コピー元を調べられてはいない

-----

※代わりに、1行ずつ検索してコピー元を調べる
git log -S"Sample-Added-12" --oneline
↓
結果: 
ae2c71d (HEAD -> master) blame test
00cad71 message2

git log -S"Sample-Added-1x" --oneline
↓
結果: 
ae2c71d (HEAD -> master) blame test

git log -S"Sample-Added-41" --oneline
↓
結果: 
ae2c71d (HEAD -> master) blame test
94996a0 message4

-----

(※1つ前＝始めの状態に戻す)
git reset --hard "HEAD^"
```

# 環境

Windows 10、PortableGit-2.40.0-64-bitを使用、全てローカルPC上で実施、GitHub等は不使用。
[OutSystems]Camera Pluginが動画に対応したので試してみる

Camera PluginがVersion 7.2.0で動画撮影に対応したとのことなので、動作確認してみる。
[ドキュメント - Camera plugin](https://success.outsystems.com/documentation/11/extensibility_and_integration/mobile_plugins/camera_plugin/#recording-a-video)に大体記載されている。ただし、2023/04/29時点では日本語訳が無い。

# 環境情報
Personal Environment(Version 11.18.1 (Build 37884))
Service Studio(Version 11.54.5)

動作確認にはAndroidを利用。

# 実装方法
## 動画撮影
画面にCameraPluginのRecordVideo Widgetを配置する。
OnClick、OnError Eventはそれぞれ必須なのでハンドラを指定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/37a29d5e-bd67-23d3-e9cc-25e29569e3c5.png)

なお、他にも、（RecordVideo Widgetが内部で呼んでいる）RecordVideo Actionを直接呼ぶ方法もある。

### OnClick Handler
EventはMediaResultという型のデータを渡してくる。
そこで、同じ型のLocal Variableを用意しておいて、ハンドラで保存しておく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/2be4fe9c-e991-0bcb-2637-4aa5a0dbe06b.png)

### OnError Handler
Eventは、ErrorCodeとErrorMessageを属性に持つStructureを渡してくる。
MessageでErrorMessageを表示するなり、ログに出すなりする。

### データの保存先
結果のMediaResultのURIパラメータを見ると
　```/<App Identifier>/cache/```
を含むパスなので、これは一時キャッシュと思われる。

[File Pluginでファイルを保存するパス](https://qiita.com/jyunji_watanabe/items/5e0ddf9a47b788a2c202)で以前調べた、端末内部の一時保存領域のパスに見える。後ほど、File Pluginでアクセスする実験をしてみよう。

ドキュメントにも
> Beware that video files stored in the cache are deleted when the app closes. When setting the URI parameter to a video file stored in the cache, beware that the video you're trying to play may have been already deleted.

とあるのでキャッシュであっていそう。そしてアプリを閉じるときに削除されるようだ。

## 動画再生
画面にCameraPluginのPlayVideo Widgetを配置する。撮影したばかりの動画と端末のギャラリーに保存された動画が対象。
Input ParameterのURIは必須なので撮影したい動画のURIを指定する。RecordVideoで撮影したものであれば、OnClickに渡ってくるMediaResult.URI属性を設定すればよい。
OnError Eventは必須なのでハンドラを指定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/98b35dac-45d0-3a4d-50de-bf0addb4a0d0.png)

なお、他にも、（PlayVideo Widgetが内部で呼んでいる）PlayVideo Actionを直接呼ぶ方法もある。

OnError Handlerについては、動画撮影の場合と同様に。

# Metadata
RecordVideoのInput Parameter IncludeMetadataにTrueを渡すと（デフォルトはFalse）、以下のメタデータも返してくれるようになる。Durationの単位はおそらく秒。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/b543a72b-3aa5-d672-c48d-ca598a728cbc.png)

# PWAについて
このバージョンでは未対応。
撮影を行うRecordVideo Actionで、以下の通りPWAでは撮影をせずに処理を終了するロジックが入っている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/41ea7e27-b966-b8f8-e951-e5d146f7871f.png)

PWAでも同じロジックが流れる可能性があるなら、CheckCameraPluginのIsPWA Output Parameterなどで分岐させ、動画撮影ロジックが流れないようにしたほうがいいだろう。
iOSショートカットレシピ Nature Remoの明るさセンサーの値を読む

[Nature Remo](https://nature.global/nature-remo/) は[Cloud API](https://developer.nature.global/)を使って様々な操作をプログラムすることができます。ここでは、明るさセンサーの現在値を読むショートカットを解説します
# ショートカット
Remoから明るさセンサーの現在値を読むショートカットを示します
![Remo明るさ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535482/9b27bb60-2ed2-fcf3-afb5-ac11c6875fad.jpeg "現在の明るさを読むショートカット")
# ショートカットの構成
このショートカットは
1. Remoのcloud APIに現在値リクエストを送る
1. 返ってきたJSON情報を解析して明るさの値を取り出す
1.クリップボードに値をコピーする( 呼び出した別のショートカットに渡すため)
という3つのサブタスクで構成しています
## Remoのcloud APIに現在値リクエストを送る
[「【Nature Remo】APIの利用例まとめ」][link-1]などにあるようにPC(Mac, Windows, Linux)からはcurlコマンドで情報を取得、操作します。次のコマンドで

[link-1]: https://blog-and-destroy.com/37183

```
$ curl -X GET "https://api.nature.global/1/devices" -H "accept: application/json" -H "Authorization: Bearer XXXXXXXX"
```
:::note info
XXXXXXXXはアクセストークン（トークンの取得方法は→[こちらのページなど][link-1]）
:::
自分のリモコンの現在の状態が次のJSON形式で得られるので、その中から明るさ情報を取り出します。
```
[{"name":"Remo",
  "id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  "created_at":"2021-07-29T23:58:16Z",
  "updated_at":"2023-04-30T00:06:13Z",
  "mac_address":"xx:xx:xx:xx:xx:xx",
  "bt_mac_address":"xx:xx:xx:xx:xx:xx",
  "serial_number":"XXXXXXXXXXXXXX",
  "firmware_version":"Remo/1.6.4",
  "temperature_offset":0,
  "humidity_offset":0,
  "users":[{
      "id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "nickname":"XXXXXX",
      "superuser":true}],
  "newest_events":{
      "hu":{"val":71,
	  "created_at":"2023-04-30T01:15:46Z"},
      "il":{"val":97,
	    "created_at":"2023-04-30T01:21:59Z"},
      "mo":{"val":1,
	    "created_at":"2023-04-30T00:38:07Z"},
      "te":{"val":22.8,
	    "created_at":"2023-04-30T01:21:46Z"}}}]
```
明るさ情報は"il"(illumination)タグの"val"の値なので、"newest_events"/"il"/"val" の値を取り出します。
この処理は

［URL/｛https://api.nature.global/1/devices｝］　　(1)

URLアクションでAPIのURLを設定し

 [{URL}の内容を取得/
    方法： GET
    ヘッダ：
        accept: application/json
        Authorization: Bearer XXXXXXXX"]  (2)

URLの内容を取得アクションでcurlコマンドを実行してリクエストを送信します。curlの引数やオプションの文字列はそれぞれのアクションのパラメータに記述します。curlの２つの-Hオプションは「ヘッダ」の２つのパラメータとなります。Authorizationタグの値は文字列"Bearer"にスペースを入れて、前に取得したアクセストークンの値を入れます。このアクションの{URL}に直接URL文字列（https://...）を入力する例を示す記事もありましたが、うまく動作しませんでしたので、一度URLアクションにURL文字列を入力する形にしました。
## 返ってきたJSON情報を解析して明るさの値を取り出す

［リストから項目を取得/｛URLの内容｝から{最初の項目}を取得］　　(3)

curlリクエストでAPIから返ってきた文字列全体が｛URLの内容｝で一般的には複数の項目が帰ってくる場合もあるので{最初の項目}で一つを取り出します。今回の場合は一つしか返ってこないので
、同じものです。

 [辞書の値を取得 / {リストからの項目}内の{newest_events.il.val}の{値}を取得]　　(4)

取り出したJSON文字列から順にnewest_events/il/valの値を読み出します。キーを階層的に記述することで１回のアクションで読みだせます。この値が現在の部屋の明るさを示す数値です。照明を消したりして変化することを確認してみてください。値に反映されるのに少し時間がかかります（数秒）
## クリップボードに値をコピーする
このショートカットをサブルーチンとして別のショートカットから利用するため明るさの値をクリップボードにコピーします。（別のショートカットに値を渡すスマートな方法をご存じの方、教えてください）

 [クリップボードにコピー / {辞書の値}をクリップボードにコピー]　　(5)

このスクリプトを使って、現在の部屋の明るさに応じて動作するショートカットを作ることができます
Hi-ho でメールの送信ができない問題

Hi-ho で、RFC に則ったメールアドレスにメールが送れない問題についての報告です。


## メールアドレスのルール

Wikipedia より、メールアドレスについて

```text
ローカル部に使用できる文字は以下のASCII文字である。

まず、次のASCII文字をそのまま並べた形式（RFC 5321ではDot-string、RFC 5322ではdot-atomと呼ぶ）が使用できる。

大小のラテン文字（本来は大文字・小文字は区別されるが、実際には区別されていない実装がほとんどである[5]。一般的には小文字で表記される）

数字

! # $ % & ' * + - / = ? ^ _ ` { | } ~（実際には、プロバイダ側で利用可能な記号文字を一部のみに制限している場合が多い）

.（先頭と末尾以外で使用可能。2個以上連続してはならない　※ドコモ,auの携帯メールアドレスでは利用できるケースがある。）
```

## Hi-ho からメールが送れない例

Google Groups から退会する時は、+ がアドレスに含まれます。

```text
このグループから退会するには、mygroup+unsubscribe@googlegroups.com にメールを送信してください
```

## Hi-ho とのやり取り

2023-04-14 16:33:25 に、Hi-ho へ

```text
メールアドレスに、 '+' が含まれた場合だけ、hi-ho のメールサーバーでメールが送信できません。
'+' が含まれない場合は、問題なくメールが送信できます。

画面にある通り、エラーメッセージは、

Toの形式が不正です。( ...abcde+unsubscribe@googlegroups.com)

と出てきます。

このアドレスへの送信は、yahoo , gmail などのメールサーバーでは問題なく送信ができます。

hi-ho のメールサーバーは、アドレスに '+' が含まれる場合に、
メールを送信できるのでしょうか。
```

2023-04-17 12:00:07 hi-ho インフォメーションデスクより

```text
一般的な回答となりますが、
「−」（ハイフン）、「．」 （ドット）、「＿」（アンダーバー）
以外の記号はメールアドレスとしてご使用いただけません。

そのため、今回のメール形式の場合はhi-hoアドレスからは
送信できかねる状況かと存じます。

先般ご案内差し上げた内容と重複し、恐れ入りますが
サービス提供元のGoogle Groupsへご相談いただきますよう
お願い申し上げます。
```

2023-04-17 18:50:31 Hi-ho へ

```text
Wikipedia  に、メールアドレスで使える文字についての記述があります。
それによると、　'+' はメールアドレスで使えるとなっています。

> 「−」（ハイフン）、「．」 （ドット）、「＿」（アンダーバー）
> 以外の記号はメールアドレスとしてご使用いただけません。
これは、hi-ho のメールアドレスとして登録する時の制限です。
相手先が、有効なアドレス　（今の場合は '+' を含むもの）なのに、メールを送信できないというのは問題ではありませんか。
相手先が、有効なアドレスの時は送信できるようにメールサーバーの設定を変更して頂けませんか。

今回は、Google Groups で問題が健在化しましたが、
有効なメールアドレスに送れないとなると、他の宛先でも発生することです。
対応の程をよろしくお願いします。
```

2023-04-20 11:00:06 hi-ho インフォメーションデスクより

```text
いただいたご要望に関しては、hi-hoとして上申させていただきます。

しかしながら現状、「+」が含まれるメールアドレス宛への
メール送信は仕様上できかねます。

何卒ご理解いただきますようお願いします。

上記理由により、恐れ入りますが
サービス提供元のGoogle Groupsへご相談いただきますよう
お願い申し上げます。
```

2023-04-20 20:34:24 Hi-ho へ

```text
> しかしながら現状、「+」が含まれるメールアドレス宛への
> メール送信は仕様上できかねます。
仕様でなくて、実装ということではありませんか。

もし、仕様ということでしたら、
hi-ho からは、RFC に準拠したメールアドレスに、送信できないケースがある
ということになりませんか。
もし、そういうことでしたら、ホームページ等に、送信できないケースがある
ことを明示して、注意を喚起された方が良いと思います。

> サービス提供元のGoogle Groupsへご相談いただきますよう
今回は、Google でしたが、RFC に準拠した正しいメールアドレスに
メールが送れないとなると、問題の解決になりません。

いずれにしても、私が　Google の担当者でしたら、
RFC に準拠しているから正しいメールアドレスですから、
送信元の　hi-ho が原因ですと答えます。

RFC  については、
Wikipedia の　メールアドレス#ローカル部に使用できる文字
を参照しました。
```

2023-04-24 13:00:08 hi-ho インフォメーションデスクより

```text
いただいたご要望につきましては、
担当部署に申し送りさせていただき、
今後のサービス改善に活用させていただきます。
```

私は、匙を投げました。

## 感想

```text
これは、Hi-ho だけでなく、日本のインターネットサービス全般にはびこる問題です。問題を指摘されても、
問題ではないと言い張る姿勢です。
```
【Vim】Vimの基礎を学ぼう！【vimtutor】【実践Vim】


# Introduction

`Vim`について調べると必ず出てくる[実践 Vim](https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5Vim-%E6%80%9D%E8%80%83%E3%81%AE%E3%82%B9%E3%83%94%E3%83%BC%E3%83%89%E3%81%A7%E7%B7%A8%E9%9B%86%E3%81%97%E3%82%88%E3%81%86%EF%BC%81-%E3%82%A2%E3%82%B9%E3%82%AD%E3%83%BC%E6%9B%B8%E7%B1%8D-%EF%BC%A4%EF%BD%92%EF%BD%85%EF%BD%97-%EF%BC%AE%EF%BD%85%EF%BD%89%EF%BD%8C-ebook/dp/B00HWLJI3U/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=&sr=)ですが、絶版になって久しく相場は 8000 円超！
流石に Kindle で買うかと悩んでいてふとページを見たら、`Kindle Unlimited`の対象になっていました！

これを気に`Vim`を学ぶ方が増えることを祈りつつも、ほぼゼロから学ぶ方のために今回は`vimtutor`について紹介します。
Ubuntu で紹介しますが、`Vim`は Windows や mac 版もあるので是非ご参考にしてください。

**本記事が少しでも読者様の学びに繋がれば幸いです！**
**「いいね」をしていただけると今後の励みになるので、是非お願いします！**

## 環境

Ubuntu22.04
Vim9.0

## Vim を学ぶメリット

- `Vim`の基となった`vi`が Linux であれば化石サーバにも入っているため、扱えるハード範囲が大きく広がる。
- 巨大ファイルも軽量で開ける。
  - テキストエディタだと強制終了するような巨大な json 等も、`Vim`ならサクサクです。
- (慣れれば)気軽に編集できる。
- (慣れれば)超高速で操作できる。
- (慣れれば)格好良い。
- `Windows`一辺倒から`Linux`に触れることになり、いきなり`vi`や`Vim`で設定ファイルを弄ることになっても平静を保てる。
  - (これは 1 年前の私の例ですが、`Vim`初見で泣きそうになっていました......)

## Vim 学習の流れ

1. `vimtutor`で基本コマンドを学ぶ。
1. 普段のメモ等、簡単なエディタ操作を`Vim`に置き換えてみる。
   - `VSCode`拡張でも可。
1. `実践Vim`で実技を学ぶ。
1. 業務/プライベートで使いこなす。

いきなり`実践Vim`から入るのは少し重ためな気もしたので、上記の順番をおすすめします。

## vimtutor

`vimtutor`は`Vim`チュートリアルを実行できるコマンドです。
中身は基礎的なもので、初学者が初心者(`実践Vim`を進められる程度)にランクアップできるような内容です。
`Vim`をインストールしている端末であればすぐ実行可能です。スキマ時間でもやれちゃいます。

```bash:
vimtutor
```

![Screenshot from 2023-04-30 09-11-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3292052/1098e84a-95ed-6cba-811d-a9372a0e5616.png)
`vimtutor`の主なメリットは以下の 3 点にあると思っています。

- `Vim`初めてでも気軽にできる基礎的な内容の 7 章仕立て。
- 端末上で行うため必然的にハンズオンで学べる。
- 各章末に要約がありコマンドが定着しやすい。

完全な初学者が行う場合は、以下のスクリーンショットを見ながらがおすすめです。
![Screenshot from 2023-04-30 09-24-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3292052/5cabb8a9-2647-45fb-8a6c-9e09e319cd1a.png)
こちらも`vimtutor`の画面ですが、最初はカーソル移動すらストレスに感じると思うので、随時参照しながら進めてみてください。

> チュートリアルを完了するのに必要な時間は、覚えたコマンドを試すのにどれだけ時間を使うのかにもよりますが、およそ 25 から 30 分です。

このように記載がありますが、最後まで行うと 1 時間近くかかると思います。
基本コマンドの観点であれば 1~4 章が特に重要ですが、この範囲であれば 30 分で終わります。
4 章まで進めてみて余力があれば 5 章以降、なければメモ書き等で試しながら`実践Vim`に進んでみてはいかがでしょうか。

## 最後に

閲覧頂きありがとうございました。
`実践Vim`は軽く目を通したところ、私のように仕事で使えどエディタとしては 2 番手の立ち位置の方にはピッタリの内容でした。
業務で丁寧に教えていただくような構成かつ濃厚な内容で高評価の理由が伺えたのですが、ゼロ or 最低限しか触れない状態で読むと挫折しかねません。
操作すらままなりませんからね。
`Vim`に興味を持っていただいた方は、この機に是非挑戦してみてください！
本記事がお役に立てば幸いです！
野獣先輩は抗うつ剤となりうるか。（電気羊はアンドロイドの夢を見るか）

# エピローグ

「やりますねぇ！」

初めて彼の声を聞いたのは、大学一年の夏休み。別大学に進学した、高校の親友の家だった。

小綺麗な家の中で響き渡る、「イキスギィ！！」僕にとっては、何が「行き過ぎ」ているのかさっぱりだったし、久しぶりに会った友人の代わり様に、驚くばかりだった。

そんな無垢なワイであったが、変化というものは恐ろしい。なんと現在は、**迫真クリエイター**として野獣先輩シリーズを筆頭に数々の大人気アプリ（これもうわかんねぇな）を手がけているのだ。

ほら、見ろよ見ろよ👇

🍎 AppStore

https://bit.ly/kaedapple

🍏 GooglePlay

https://bit.ly/kaedroid

クリエイターとして**賞**もいくつか獲得した（激寒人生）例えば、僕のアプリの一つ「イムイム！人生詰む詰むと化した先輩」が、App Store今週のトップゲームを受賞してしまったりなどした。（困惑）

https://apps.apple.com/jp/app/id1511783815


このように、様々なゲームを作っていくうちに次第に多くのメッセージが寄せられるようになった。そのほとんどが、**人生救われました系**のもので、あっ察し。

* 失恋から立ち直れました。ありがとうございます。
* うつ病が治りました（診断書画像も添付）
* 大学落ちたけど元気出たわ。ありがとナス。

などなど。そこでワイは決心したのである。**遊ぶ抗うつ剤**をテーマにアプリを制作していくことを（誇らしくないの？）

これからの創作も、元気のない人々に笑顔を届けられる王道アプリ、作っていきますよ〜イクイク。でもヨォ、そもそも、

# 野獣先輩は抗うつ剤となりうるか？

（デデドン！）

（この重大な問いを無視して、これからの創作活動は続けられ）ないです。

というわけで今回は科学的根拠から野獣先輩抗うつ剤説を考えてみることにしました。

ちなみに筆者は、学生時代、作文コンテストで何度も佳作を受賞した経歴がありますが、大学時代に淫夢語録しか話せないカラダにさせられた（意味深）ので（文章力はもはや）ないです。

# 結論（ハヤスギィ！）

先に結論を述べますと、

**野獣先輩は抗うつ剤に、、、なりますねぇ!（激寒）ただ、ちょっと依存性あたんよ〜。**

以下での筆者の科学的考察も踏まえ、是非みなさんも淫夢動画を見る目的を見出して、どうぞ。

# 抗うつ剤とは（定義）

まずは、抗うつ剤の定義を確認しておきましょう。うつを治すために必要なものは次の4点と言われています。

1. 休養
1. 環境調整
1. 薬物治療
1. 精神療法

これらを、淫夢動画の閲覧により克服できるか？ということを下記で詳しく述べて行きます。（語録無視）

## 休養と野獣先輩

淫夢動画を見ることは、休養につながるのでしょうか？休養とはすなわち、ストレスを減らす行動になります。休養についてこの章では、**喜怒哀楽**の四つに分類して解説します。

## 喜びの淫夢

淫夢動画は、ニコニコやYouTubeで常に最新作が配信されています。その人気は、Googleの検索回数でもジャニーズの嵐と同じくらいで、多くの人々が楽しみにしています。新しい動画が投稿されたときや野獣先輩の新章が始まるとファンは大興奮し、喜びを表現します。このようなエンターテインメントは、ストレスを解消するために非常にプラスの影響を与えるといえます。

## 怒りの淫夢

また、淫夢動画には暴言や下品な言葉が含まれていることもありますが、それでもファンたちは楽しんでいます。このような言葉があることで、怒りの感情を表現することができるという意見もあります。

## 悲しみの淫夢

一方で、淫夢動画には感動的なストーリーや切ない場面が含まれています。これによって、寂しさや悲しみを感じている人々が共感する場を提供しています。

## 楽しめる淫夢

そして、淫夢動画の独特な世界観やキャラクターたちは、人々を楽しませています。このような体験を通じて、淫夢動画を見ることは、心をリフレッシュすることができるかもしれません。ただし、個人差があるため、淫夢動画を見ることでストレスを感じる人もいることを忘れないでください。環境調整としても、自分の好きな音楽や映画を楽しむことが良い影響を与えるとされています。また、淫夢動画のコミュニティに参加することで、交流を深め、気分転換にもなります。

これらのことから、淫夢動画を見ることは休養につながると言えます。

# 環境調整と野獣先輩

次に、淫夢動画を見ることが環境調整につながるのか考えてみましょう。環境調整とは、生活環境を整えることでストレスを軽減することです。淫夢動画を見ることで、自分の居場所やコミュニティを見つけることができます。また、共感できる人たちと交流することで、ストレスを解消することができます。これらのことから、淫夢動画を見ることは環境調整につながると言えます。

# 薬物治療と野獣先輩

薬物治療について考えてみましょう。薬物治療とは、抗うつ剤や抗不安剤などの薬を使用することで、うつ病の症状を改善することです。しかし、薬物治療は副作用があるため、できれば避けたいものです。淫夢動画を見ることで、薬物治療に頼らずにうつ病の症状を改善することができる可能性があると言えます。

# 精神療法と野獣先輩

最後に、精神療法について考えてみましょう。精神療法とは、カウンセリングや認知行動療法などの心理的治療法を用いて、うつ病の症状を改善することです。野獣淫夢動画を見ることで、自己開示やコミュニケーションスキルの向上など、精神療法の効果を得ることができる可能性があると言えます。

# 最後に

以上のことから、野獣淫夢動画は、休養や環境調整、薬物治療、精神療法のいずれにも当てはまると言えます。ただし、淫夢動画に依存することで、現実から逃避してしまうことがあるため、適度に利用することが大切です。

じゃ、Twitterフォローハイヨロシクゥ！

https://twitter.com/kaedeee_you

https://twitter.com/kaedeee_you?ref_src=twsrc%5Etfw%7Ctwcamp%5Eembeddedtimeline%7Ctwterm%5Escreen-name%3Akaedeee_you%7Ctwcon%5Es2
neosでlogix その124

# 概要
neosでlogixやってみる。
読み込んだtext、使ってみた。

# 写真

![2023-04-29 23.13.33.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/c2f24d8c-3f05-1e09-2f6f-42ab5c87f24d.jpeg)

# 手順
- ファイルブラウザを開く
- haru.txtをダブルクリック
- devtoolを装着
- インスペクターを表示
- logixtoolを装着
- textのインターフェースを取り出す
- contentのvalueを取り出す

以上。
neosでlogix その123

# 概要
neosでlogixやってみる。
アウトライン、使ってみた。

# 写真
![2023-04-29 22.49.57.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/5cdfcfbe-e6eb-f922-801d-9529b63cdb3c.jpeg)


# 手順
- devtoolを装着
- 新規作成>オブジェクト>テキスト>アウトラインをスポーン
- インスペクターを表示
- logixtoolを装着
- textrendererのインターフェースを取り出す
- textのvalueを取り出す

以上。
[Javascript] flatMapの使用例 二次元配列をfilterした後、mapで一次元配列にしたい

# はじめに
[こちら](https://jsnotice.com/posts/2020-07-19/index.html) でも類似の記事があり、参考にさせて頂きました。
以下、備忘録的な扱いとなりますが、誰かの役に立てば幸いです。

## いくつかの方法
上記、参考サイトや他でも言及されていますが、filterとmapを両方使いたいケースで現状考えられる方法としては以下の４点かと思います。

+ 素直にfilterした後mapする
+ 逆にmapした後filterする
+ reduceを使用する
+ flatMapを利用する

個人的に一番スッキリ記述できるのがflatMapと思います。

# サンプルコード
GAS、とりわけスプレッドシートを使うことが多いため、以下の前提で二次元配列から一次元配列を生成することとします。

+ 「シート１」のＡ列に０～１００までの数字が入力されている
+ 値は１行目から入力されておりヘッダ行はなし
+ 奇数のみの一次元配列を取得する

``` Javascript: sample01.js
const sheetName = 'シート１';
const targetCol = 'A';

const SS = SpreadsheetApp.getActive();
const SH = SS.getSheetByName(sheetName);
const targetRange = SH.getRange(`$${targetCol}:$${targetCol}`);
const rawData = targetRange.getValues();

const resultArr = rawData.flatMap(row => row[0]%2 === 1? [row[0]]: []);
// resultArr => [1,3,5,...,99]
```

## ポイント
三項演算子の返値 `[row[0]]: []` が、個人的なポイントです。filterやmapを単独で使う場合が多いため、**`[]`で値を囲うことを忘れます**。

今回はGAS及びスプレッドシート利用前提のため、二次元配列を扱っていますが、多次元（ジャグ配列）においても、一次元配列への変換時は返値を `[]` で囲う必要があります。

なお、偽値の場合に空配列 `[]` を返すことで、filterと同様の結果を得ることができます。その詳細についてはMDNにて以下のように説明されています。

> flatMap は、map 中にアイテムの追加と削除（アイテムの数を変更）を行う方法として利用できます。つまり、常に一対一ではなく、（中略）アイテムを削除するには 0 要素の配列を返します。
> 引用元：[Array.prototype.flatMap() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap#map_%E3%81%AE%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0%E3%81%AE%E8%BF%BD%E5%8A%A0%E3%81%A8%E5%89%8A%E9%99%A4)

結果として、filterしつつmapも行う（逆も然り）、ということになるのですね。

# 最後に
サンプルでは単純な処理となっていますが、例えば、条件判定に至るまでの工程が長い場合でも、最終的に振り分けできれば問題ないと思います。filterとmapを分けて記述するより、わずかに効率的かと思いますが、好みやハウスルール、ケースによります。あとは、いかにそれまでの工程をリーダブルかつコンパクトにできるかがセンスなのでしょうね。

ただし、実行環境や処理内容によってはfilter後にmapする方が体感的にも早いと思います。

以上、誰かの役に立てば幸いです。

## [参考・引用]
+ [【JS】mapとfilterを両方同時に使いたい時の書き方4通り](https://jsnotice.com/posts/2020-07-19/index.html)
+ [Array.prototype.flatMap() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap#map_%E3%81%AE%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0%E3%81%AE%E8%BF%BD%E5%8A%A0%E3%81%A8%E5%89%8A%E9%99%A4)
Dockerでhttpdを起動してアクセスしてみた

# 概要
今日はDockerでhttpdを起動してアクセスしてみました。以下のページを参考にしました。
https://weblabo.oscasierra.net/docker-httpd-usage/

# httpdイメージをダウンロード
以下のコマンドを実行しました。
```
$ docker pull httpd
Using default tag: latest
latest: Pulling from library/httpd
26c5c85e47da: Pull complete 
2d29d3837df5: Pull complete 
2483414a5e59: Pull complete 
e78016c4ba87: Pull complete 
757908175415: Pull complete 
Digest: sha256:a182ef2350699f04b8f8e736747104eb273e255e818cd55b6d7aa50a1490ed0c
Status: Downloaded newer image for httpd:latest
docker.io/library/httpd:latest
```
# httpdを起動
以下のコマンドを実行しました。
```
$ docker run -d -p 8080:80 httpd
0187896dd2b1f95cfc003f7cce88437d9d06bd96de8fc6feba4842c45c316878
```
# プロセスを確認
以下のコマンドを実行しました。
```
$ docker ps
CONTAINER ID   IMAGE     COMMAND              CREATED              STATUS              PORTS                                   NAMES
0187896dd2b1   httpd     "httpd-foreground"   About a minute ago   Up About a minute   0.0.0.0:8080->80/tcp, :::8080->80/tcp   musing_napier
```
# localhost:8080にアクセス
Chromeでlocalhost:8080にアクセスしました。ちゃんとアクセスできました。
![Screenshot from 2023-04-30 09-54-30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/93048972-124d-b9fd-1406-a03f67652175.png)
# コンテナを停止
以下のコマンドを実行しました。
```
$ docker stop 0187896dd2b1
0187896dd2b1
```
# コンテナの停止を確認
以下のコマンドを実行しました。
```
$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
```
# localhost:8080にアクセスできないことを確認
Chromeでlocalhost:8080にアクセスを試みました。アクセスできませんでした。ちゃんと落ちています。
![Screenshot from 2023-04-30 09-56-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/bbd45cbf-0d01-8bb2-2e57-c08a6fa2d1cf.png)
# ファイルを準備
以下のコマンドを実行しました。
```
$ cd /tmp
$ mkdir mypage
$ cd mypage/
$ echo "This is test page." > index.html
```
# マウントするようにしてDockerコンテナを起動
以下のコマンドを実行しました。
```
$ docker run -d -p 8080:80 -v "/tmp/mypage/:/usr/local/apache2/htdocs/" httpd
e4c2069aaceed5f5e4ba89ad6bae1a1e6eb79c03a3308c6957fc2ba03eb52f01
```
# localhost:8080にアクセス
Chromeでlocalhost:8080にアクセスしました。マウント先が見えていることを確認しました。
![Screenshot from 2023-04-30 10-01-39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/170edbd0-e186-f3b0-6686-0d599292bd62.png)


何かの役に立てばと。
neosでlogix その122

# 概要
neosでlogixやってみる。
Numeric UpDown、使ってみた。

# 写真

![2023-04-29 22.37.19.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/115f58f0-069f-feef-c163-d1d2cb7a2e3e.jpeg)

# 手順
- devtoolを装着
- 新規作成>オブジェクト>neos ui>Numeric UpDownをスポーン
- インスペクターを表示
- logixtoolを装着
- neosNumericUpDownのインターフェースを取り出す
- valueのvalueを取り出す

以上。
コツコツPRを投げてたら、とあるOSSのコラボレータになれました。(Rust, Swift)

# コツコツPRを投げてたら、とあるOSSのコラボレータになれました。

こちらのコラボレータになれました。

https://github.com/chinedufn/swift-bridge

`swift-bridge`は、RustとSwiftを繋ぐffiを自動生成するツールです。`swift-bridge`の紹介は別の記事でまとめようと思います。

以下は`swift-bridge`を使った例です。

```rust
//Rust
#[swift_bridge::bridge]
mod ffi {
    enum SomeEnum {
      Variant1
      Variant2 {
        value: usize
      }
      Variant3(i32, u32)
    }
    extern "Rust" {
        type SomeType;  //不透明な型
        #[swift_bridge(init)]
        fn new() -> SomeType;
        fn some_function(&self) -> i32;
    }
}

pub SomeType(i32);

impl SomeType {
   fn new() -> Self {
      SomeType
   }
   fn some_function(&self) -> i32 {
      self.0
   }
}
```

```Swift
//Swift
let someType  = SomeType()
let someValue = someType.some_function()

let variant3  = SomeEnum.Variant2(value: 10)
```

上記を見るとわかる通り、簡単にSwiftとRustの連携が取れることがわかります。

## OSSのコラボレータになれた経緯

元々、`swift-bridge`には関心を持っていました。そこで、このOSSに何か自分でも貢献できることがあるのではないかと思い、good first issueから取り組むことにしました。

最初に投げたPRはこちら：

https://github.com/chinedufn/swift-bridge/pull/134

テストコードの整理とGithub Actionsに対する微修正をやりました。

次に取り組んだのはこちら：

https://github.com/chinedufn/swift-bridge/pull/139

上のPRは、`swift-bridge`が提供する不透明な型の`Equatable`のサポートを行っています。

他にも色々やり、少しずつこのOSSに慣れてきました。なので、難しい実装にもチャレンジするようになりました。

個人的に難しかったのは、RustとSwiftの間で、`Enum`型を連携する実装です。

https://github.com/chinedufn/swift-bridge/pull/172

https://github.com/chinedufn/swift-bridge/pull/175

なぜ難しいのかと言いますと、RustとSwiftで提供される`Enum`型は、リッチな仕様であり、メモリ表現が複雑なのです。その為、実現方法を調査し、リポジトリのオーナーとこちらで簡単な議論を行いました。

https://github.com/chinedufn/swift-bridge/issues/160


しばらく淡々とissueに取り組んでいると、good first issueを書く機会を与えられました。


https://github.com/chinedufn/swift-bridge/issues/197

ただし、good first issueというラベルを行うには、権限が必要です。そこでついに、オーナーの方からコラボレータの招待メールが届きました!!!

![スクリーンショット 2023-04-30 10.10.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373549/357e5ad4-e548-8219-f708-d896c92a8146.png)

これまで、何度かOSS貢献をやったことはありましたが、コラボレータの招待経験がなかったので、これはとても嬉しく思いました。

## OSS貢献をコツコツ続けるには

興味のあるOSSを見つけ、コツコツgood first issueに取り組むのが良いのかなと思います。慣れてきたら、思い切って難しそうなものにチャレンジするとそのOSSに対する理解度が深まっていく気がします。あと、どのOSSもテストコードの追加は必須になっているはずなので、テストコードは日頃から書いておきましょう。

## コードを理解するコツ

ドキュメントを読むのはもちろんのことですが、テストコードを眺め、色々と入力をいじるといいです。「こういう入力の時は、こんな出力が得られるんだな。」という知見が得られます。OSSにおいて、テストコードは仕様書としての役割を持ちます。

## 終わりに

これからも様々なOSSに貢献していきたいと考えています。
neosでlogix その121

# 概要
neosでlogixやってみる。
slider、使ってみた。

# 写真

![2023-04-29 22.30.41.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/b7afffbe-9bd7-dc4d-eed5-f3ecb6444e57.jpeg)

# 手順
- devtoolを装着
- 新規作成>オブジェクト>neos ui>sliderをスポーン
- インスペクターを表示
- logixtoolを装着
- neossliderのインターフェースを取り出す
- valueのvalueを取り出す

以上。
neosでlogix その120

# 概要
neosでlogixやってみる。
text field、使ってみた。

# 写真
![2023-04-29 22.24.23.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/8e6e68be-3763-c748-0ce6-9923d8cd7e54.jpeg)


# 手順
- devtoolを装着
- 新規作成>オブジェクト>neos ui>text fieldをスポーン
- インスペクターを表示
- logixtoolを装着
- textrendererのインターフェースを取り出す
- textのvalueを取り出す

以上。
【データ基盤構築/Snowflake/AWS】自分で１から簡単なデータ基盤・データパイプラインを作ってみる

# 今回の課題
今後、業務でAWSとSnowflakeでデータ基盤を構築・運用していくことになるので、
勉強のために、自分で１からデータ基盤・データパイプラインの作成に挑戦してみた。

後から見返しやすいように、どのように作成したのかまとめてみる。

# どのようにデータ基盤を作ったのか
以下のアーキテクチャ図のように作ってみた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/082e7fe0-0a75-d614-a8bc-d954d79f32f6.png)


## データ基盤作成手順
どのようにデータ基盤を作成したのか、手順に沿ってまとめてみた。
手順毎の詳細は、以前に別の記事で書いているので、そちらの記事も手順毎に記載した。

### 1)EC2上でRDSを動かす&RDSにデータを入れる
下記の記事を参考にしながら、以下を実装。

* VPCを構築し、その中にEC2とRDSを立てる。
* 今回は、ターミナルからAWSにSSH接続して、`create table`や`insert`などを実行してRDSにデータを入れるようにした。

※注意:Snowflakeのリージョンが`ca-central-1`なので、AWSのリージョンも`ca-central-1`に合わせる。

https://zenn.dev/ito110/scraps/81b8dd657a5c6b


### 2)LambdaとEventBridgeを使ってRDSからS3に定期的にデータをロードする仕組みを実装する
下記の記事に書いたように以下を実装。
これで、RDSのデータが毎日S3にロードされるようになる。

* RDSのスナップショットをロードするためのS3バケットを作成。
* RDSからS3にスナップショットをロードするためのLambda関数が、EventBridgeで1日一回特定の時間に実行されるように設定。

※注意:Snowflakeのリージョンが`ca-central-1`なので、AWSのリージョンも`ca-central-1`に合わせる。

https://qiita.com/Ayumu-y/items/523f700960129c57e3b3


### 3)S3にRDSのスナップショットがロードされたらSnowpipeでSnowflakeにデータがロードされるように実装する
下記の記事に書いたように以下を実装。
Snowpipeを作成することで、RDSからS3にスナップショットがロードされたのとほぼリアルタイムに、
S3からSnowflakeのテーブルにデータがロードされる。

* Snowflakeでストレージ統合を作成。
* Snowflakeで外部ステージを作成。
* SnowflakeでS3のデータをロードして格納するためのテーブルを作成。
* SnowflakeでSnowpipeを作成。



https://qiita.com/Ayumu-y/items/d6713e09b0a409d1bd25

https://qiita.com/Ayumu-y/items/7ef351524c48d853f301


### 4)dbtとGitHubを連携してクエリ履歴の管理ができるように実装する
下記の記事のように、dbtをGitHubを連携してクエリ履歴の管理を行えるように実装する。

記事では、S3からSnowflakeにデータをロードするクエリ履歴のGitHubにPushしているが、
S3からSnowflakeのデータのロードは、dbtを使わなくてもSnowpipeで実施可能なので、
Snowflake上でETLを行ったクエリの管理を行うようにする。

https://qiita.com/Ayumu-y/items/7217a5d3bb66d32d3f2d


### 5)Redashでデータを可視化する
簡単なデータ基盤ができたので、
下記の記事に書いたようにEC2でRedashを立てて、データを可視化してみた。

https://qiita.com/Ayumu-y/items/cfd5f1ffdfdfe24d31d3

# まとめ
以上の流れでデータ基盤を作成することができた。
他にも、`dbt`や`AWS Cloudformation`、`AWS DMS`で色々と試してみたので、
以下の`おまけ`の見出しでまとめてみた。



# おまけ
上記以外で、dbtやAWS Cloudformationで試してみたことのまとめ

### dbtで試してみたこと

https://qiita.com/Ayumu-y/items/1cb3a3feb8d3f5db0ae5

https://qiita.com/Ayumu-y/items/7d3bf1567ca323c85f9a

https://qiita.com/Ayumu-y/items/08111ad710a4f83b679a

https://qiita.com/Ayumu-y/items/8403bd7ae32e0419d46f

https://qiita.com/Ayumu-y/items/af48189c8168c7030707

https://qiita.com/Ayumu-y/items/4fc37c19928c462d667f

### cloudformationで試してみたこと

https://qiita.com/Ayumu-y/items/abb077643661ee756c44

https://qiita.com/Ayumu-y/items/858170a85380babfa190


### AWS DMSで試してみたこと
https://qiita.com/Ayumu-y/items/63ee4838ab9d723340cc

※Lambda + EventBridgeでなくても、RDSからS3へのデータのロードができた。
ABC300回答メモ

0.はじめに
　いろいろと対策をして頂けたおかげか、久々にストレスなく回答できました。
　Cまでしか解けませんでしたが、早めに回答できたためか
　レートが30アップしました。


1.A - N-choice question
　入力をすべて受け取った後、リストを頭から見ていって
　A+Bと一致したら、その順番を出力して終了。

　https://atcoder.jp/contests/abc300/submissions/41024841

2.B - Same Map in the RPG World
　B問題にしては難しいというかめんどくさい問題でした。
　【考え方】
　　B表の方は、縦横に付け加えて4面に。
```
B=[]
～略～
for _ in range(H):    C=input()
    B.append(C+C)
for i in range(H):
    B.append(B[i])
```
　その後B表を0,0～H,W(変数i,j)まで見るループを作り
　その中に、A表の0,0～H,W(変数k,l)とB表の(i+k,j+l)を比較するループを
　つくる。
　内側のループを差がなく終了出来たら、Yesを出力して終了
　最後まで下がaにループが無かったらNoを出力して終了
　と、しました。

　https://atcoder.jp/contests/abc300/submissions/41032004

3.C - Cross
　なかなかユニークな問題でしたが、制約が親切だったので
　考えやすかったです。

　【考え方】
　　1.C表を端からチェックしていく　0,0～H,W(変数i,j)
　　　1-1.C[i][j]＝”#”の時
　　　　1-1-1.以下ループ(変数x初期値1、リストans[0]*min(H,W))
　　　　　1-1-1-1.左上、右上、左下、右下(距離x)が、#であるかをチェック
　　　　　　1-1-1-1-1.すべて#であった場合、xに1を加算し次のループ
　　　　　　1-1-1-1-2.いずれか.であった場合、Xが1なら次のi,jへ
　　　　　　　　　　　 2以上なら、ams[x-1]に1を加算
　　2.最後にリストansを出力

　https://atcoder.jp/contests/abc300/submissions/41037884

4.D - AABCC
　最初は解法分からず諦めかけましたが、Pythonでの
　素数の求め方等調べて、意外と大きい素数まで高速で求められることが
　わかったので取り組みました。

　残り3分くらいでやっと仕上がったのですが、7/17、WAがでてしまい撃沈。
　翌日見直してたら、判定の部分で、=が抜けていることに気づき
　おしかったな・・・と思いました。

　考え方
　A>B>Cなので、Cが最大になるのは、A=2、B=3の時で
　Nが制約上最大の時でも、288675以下(10**18/12の平方根)
　エラトステネスの篩を利用した方法であれば
　これくらいの素数リストは高速に計算できるので
　以下のように実装

　実装
　　1.Nを12で割った数の平方根以下の素数をリストplistに格納
　　2.変数ansを0で初期化
　　3.変数aを1～len(plist)-1まで回す
　　　3-1.変数bをa+1～len(plist)-1まで回す
　　　　3-1-1.変数cをb+1～len(plist)まで回す
　　　　　3-1-1-1.(plist[a]**2)*plist[b]*(plist[c]**2)<=Nの時
　　　　　　　　　　ansに1を加算
　　　　　3-1-1-2.(plist[a]**2)*plist[b]*(plist[c]**2)>Nの時
　　　　　　　　　　3-1-1のループを抜ける
　　4.ansを出力する

　3-1-1-1の判断で、=が抜けていたため、コンテスト中にACを頂けませんでした。

　https://atcoder.jp/contests/abc300/submissions/41062039

以上
アプリ初回読み込み時に画像データを並列処理で読み込む

サンプルアプリを作成している中で50枚ほどの画像を動的に表示する必要があり、その都度読み込んでいては遅いのでアプリの初回読み込み時に並列処理でVuexに持たせておくことにしました。

画像の並列処理と、このサンプルアプリ作成で初めてVuexを使用したので、そのアウトプットも兼ねて書いていきます。

## 環境
Vue 3.2.47
vuex 4.0.2
vite 4.2.0
node 16.13.0

## App.vueでactionsを呼び出す
onMountedでvuexのactionsを呼び出します。
```javascript:App.vue
<script setup lang="ts">
import { onMounted } from 'vue';
import { useStore } from 'vuex';

onMounted(async () => {
  const store = useStore();
  await store.dispatch('initializeCardImageList');
});
</script>
```

## Vuexの実装
vuexはこのようになりました。
cardImageListというのが画像データを保持する変数になります。
actionsでinitializeCardImagesメソッドを呼び出し、戻り値をmutationに渡しています。

```javascript:store/index.js
import { createStore } from 'vuex';
import { initializeCardImages } from '../utils/index';

type State = {
  cardImageList: Record<number, string>; // 画像データが入る
};

const store = createStore<State>({
  state: {
    cardImageList: {},
  },
  mutations: {
    setCardImageList(state, data) {
      state.cardImageList = data; // stateに格納
    },
  },
  actions: {
    initializeCardImageList({ commit }) {
      const cardImageList = initializeCardImages(); // このメソッド内で画像を並列処理で読み込む
      commit('setCardImageList', cardImageList); // mutationを呼び出す
    },
  },
  getters: {
    getCardImageList(state) {
      return state.cardImageList;
    },
  },
});

export default store;
```

## 画像を並列処理で読み込む
本題の並列処理になります。

```javascript:utils/index.js
export const initializeCardImages = (): Record<string, HTMLImageElement> => {
  // cardImageListにはオブジェクト形式でインポートした画像データが入っている
  // { 1: image1, 2: image2, 3: image3 ... }
  const promises = Object.values(cardImageList).map((url) => {
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.onload = () => resolve(img);
      img.onerror = () => reject(new Error(`Failed to load image ${url}`));
      img.src = url;
    });
  });

  const imageCache: Record<string, HTMLImageElement> = {};
  Promise.all(promises).then((images) => {
    images.forEach((img, i) => (imageCache[i] = img as HTMLImageElement));
  });
  return imageCache;
};
```

## まとめ
今回はアプリの初回読み込み時に画像データを並列処理で読み込む方法をまとめました。

現状の実装では最初にまとめて行っているだけで、読み込み処理自体の長さはそこまで改善されていないので、画像を圧縮させたりして読み込み時間の短縮もいずれ行おうと思います。
DI：Dependency Injection

# DIとは
依存性の注入。
使いたいオブジェクトを直接はnewせず外部から渡してもらうようにする。(コンストラクタを呼び出す側でnewしてもらうなど)
* 依存とは
クラスAがクラスBに依存している＝クラスAの中でクラスBを使っている

# メリット
コードが疎結合になる
* newをしないため
* 「new」をすることは蜜結合
例）クラスAでクラスBをnewする。
→クラスB内部で使うオブジェクトについて知っていないといけない。
→クラスBの実装の詳細について知っていないといけない。

### 疎結合であることのメリット
* 拡張性がある
テストBの引数の数などの実装が変わった際などに、呼び出す側のクラスAの実装を変更しなくて良い。
* テストしやすい

# 使用法
SpringでDIを使用するには、Beanの登録とインジェクションを実施する必要がある。
* Bean登録
Bean＝DI管理対象のクラスのこと。
@Component-付与したクラスがBeanであることを示す。
代わりにユースケースを現すアノテーションを使える。（@Controller、@Service、@Repositoryなど）
@Beanというものもある。
* インジェクション
引数ありのコンストラクタを用意する。（@Autowiredは省略可能）など。
~~~ java
@Controller
@RequiredArgsConstructor
public class IssueController {

    private final IssueService issueService;
~~~
lombokの@RequiredArgsConstructorにてインジェクションを自動化できる。
→finalがついているフィールド　かつ　初期化されていないフィールドを初期化するコンストラクタを自動生成。
複数Glue Jobのトリガーをまとめて変更してみた

月次で定期実行しているGlue Jobを週次で実行するよう変更したかったため、Glue Jobのトリガーのスケジュールを変更するスクリプトを作成しました。

## 前提条件
- 1つのAWSアカウントの東京リージョン内に複数のGlue Jobがある。
- chap8-xxxという名前のGlue Jobが複数あり、トリガーによって毎月１日に実行している。
- chap8-xxxという名前のGlue Jobを「毎週月曜日10:00(UTC)」実行に変更したい。

## やったこと
- トリガーの一覧を取得する。
- トリガーが紐づくGlue Job名を取得する
- Glue Job名がchap8から始まっていたら、スケジュールを書き換える。

## スクリプト
~~~
import subprocess
import json

region = "ap-northeast-1"
profile = "default"

# AWS CLIを使用してトリガーリストを取得
result = subprocess.run(["aws", "glue", "get-triggers", "--region", region, "--profile", profile], stdout=subprocess.PIPE)
output = result.stdout.decode('utf-8')

# トリガーリストをパースして、Job名とトリガー情報を表示し、スケジュールを書き換える
json_output = json.loads(output)
for trigger in json_output["Triggers"]:
    job_name = trigger["Actions"][0]["JobName"]
    print("Job Name | Trigger Name: {}".format(job_name + " | " + trigger["Name"]))
    print("Schedule: {}".format(trigger["Schedule"]))
    if job_name.startswith('chap8'):
        # cron書式で固定の値を指定する
        new_schedule = "cron(0 10 ? * 2 *)" # 毎週月曜日10:00(UTC)実行
        print("New Schedule: {}".format(new_schedule))
        # スケジュールを書き換える
        new_trigger = {
            "Name": trigger["Name"],
            "Actions": trigger["Actions"],  # 元のトリガーのActionsをそのままコピー
            "Schedule": new_schedule,  # 書き換えたスケジュールを指定
            "Description": trigger["Description"]  # 元のトリガーのDescriptionをそのままコピー
        }
        args = [
            "aws", "glue", "update-trigger", "--region", region, "--profile", profile, 
            "--name", trigger["Name"], "--trigger-update", json.dumps(new_trigger)
        ]
        subprocess.run(args, stdout=subprocess.PIPE)
~~~
Spring アノテーションまとめ

随時更新する。
### @Controller
Controllerクラスであることを定義する。
### @ResponBody
戻り値のStringがそのままレスポンスとなる。
### @GetMapping
Controller内のメソッドに記述し、Getリクエストを紐づける。
### @PostMapping
Controller内のメソッドに記述し、Postリクエストを紐づける。
### @RequestMapping
Controllerクラスに記述し、クラス内のリクエストのそれぞれのルートパスを記述する。
### @Service
業務ロジックや業務ルール(アプリケーション特有のもの)をコーディングしたクラスであることを定義する。
### @Repository
データアクセス層のクラスであることを定義する。データの保存や取得を担う。
### @Component
付与したクラスがBeanであることを示す。
### @ModelAttribute
model.addAttributeとほぼ同等。
### @Transactional
登録・更新処理をするクラスに付与し、Springにて処理をトランザクション処理を実施する。
lombokについて

# lombokとは
コンストラクタやGetter・setterを自動生成してくれるライブラリ。
### Gradleに以下を追加
~~~
configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

dependencies {
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
}
~~~

### コンストラクタの自動生成
@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructorがある。
https://projectlombok.org/features/constructor

* アノテーションをクラスに付与して使用する。
~~~ java
@AllArgsConstructor
public class IssueEntitiy {
    private long id;
    private String summary;
    private String description;
}
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469740/8c9aef3d-5ece-8fbe-6774-c17b830b8b26.png)
構造を確認すると、コンストラクタが作成されていることがわかる。

### Getter・Setterの自動生成
@Getter・@Setterアノテーションが存在するが、
equalsやToStringなどの諸々のメソッドも自動生成してくれる@Dataを使用する。
~~~ java
@AllArgsConstructor
@Data
public class IssueEntitiy {
    private long id;
    private String summary;
    private String description;
}
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469740/c6759ba3-570f-806b-b675-c220244ce7b5.png)
構造を確認すると、Getter・Setter、その他メソッドが自動生成されていることがわかる。

### 公式サイト
https://projectlombok.org/
featuresメニューより利用可能なアノテーション確認可能
[自分用]実装の流れ

## 実装の流れ
コンポーネント分け
※細かく分けすぎると「保守性」が悪くなり、粗すぎると「再利用性」が悪くなる
↓
１ファイルの中に複数コンポーネントを記述し、名前付きインポートで対応することもできるが、チームの方針に従うべき。

①
繰り返し使うもので分ける。
ex) Header,Footer,Hero

②
componentsフォルダにそれぞれを用意。

③
さらにHeader,Footerは全ページに入っているので、Layoutにまとめるとより使い回しをしやすくなる。
※HeaderとFooterの間の要素はその時によって変わるので、propsで受け取るのが理想。

④
③のまま全ページに反映させてもいいが、Next.jsには「初期で全ページに反映させてくれる機能」があるのでそっちを使ってみる。
```
_app.js
**Component**には、レンダリングされるページの関数コンポーネントが渡ってきます。
→つまり現在のページに対応するコンポーネントが渡されます。

**pageProps**には、Conmponet に渡された関数コンポーネントが受け取る
 propsが格納されたオブジェクトが渡ってきます。
→つまり現在のページに対応するコンポーネントに渡されるべきpropsが格納されている。
```

⑤
blogなどを作成したいときはURLを「blog/〇〇」にしたいと思う。
その場合は単に`blog.js`を作成しても意味がないので、`blogフォルダー`を作成してから、随時必要なファイルを作成する

⑥
**cssの設定**
baseとなるcssは、globals.css
globalとなるcssは、utils.module.css
localとなるcssは、各コンポーネントに適したcss

※utils.module.cssを他のファイルでも使いたい時は`composes`で導入する
git diffのチートシート

一挙動ごとに確認をすることが大切
|状態|コマンド|補足|
|:-|:-|:-|
|ファイル比較|git diff -- ファイルパスA ファイルパスB|いつでも可能|
|変更内容すべて|git diff|git add前|
|特定ファイルの変更内容|git diff -- 対象のファイルパス|git add前|
|git add後、commit前|git diff --cached|参考：git add取り消し → git rm --cached [ファイル名]|
|git commit後|git diff HEAD^|本来は `git diff HEAD^..HEAD` と書くのが正しい。`..` の右側を省略すると暗示的に現在のブランチのHEADを示す|
|git push する前にリモートとの変更点を見る|git diff リモート名/ブランチ名..HEAD|`..` の右側が時系列的に最新とみなされるので、この場合は git commit した後にリモートリポジトリと、これから push したい箇所を表示したい場合の意味|

|オプション|意味|
|:-|:-|
|--output=ファイル名|stdoutではなくファイルに結果を出力|