OmniAICreator/Qiita-1.07M huggingface dataset:
Angular + Electron事始め

# Angular + Electron事始め

# 概要
Electronが気になっていた今日このごろ。
Angularを久しぶりに触りたいこともあり、Angular + Electronでアプリを作ってみようと思う。
とりあえずAngular-CLIで作ったテンプレートをElectron使って起動できるところまですすめていく。

# TL;DR.
[ソースコード](https://github.com/Tetsuya-Minase/program-samples/tree/master/angular-electron)

# 手順
## Angularプロジェクト作成
``` bash
# いつも通りCLIからスタート
$ng new angular-electron
```

## Electronインストール
``` bash
$ npm install electron --save-dev
```

# 起動できるように各種修正
[公式ドキュメント]([https://www.electronjs.org/docs/tutorial/first-app](https://www.electronjs.org/docs/tutorial/first-app))と[angular-electron]([https://github.com/maximegris/angular-electron](https://github.com/maximegris/angular-electron))を参考に作っていく。

## Angular.jsonを修正
`projects > architect > build > oprions > outputPath`を`/dist/プロジェクト名(今回はangular-electron)`を`dist`のみに修正。

```json
{
  ...
  "projects": {
    ...
      "architect": {
        "build": {
          ...
          "options": {
            "outputPath": "dist",
            ...
```

## main.jsを作成
アプリを起動するためのjsを作成する。
tsで書きたかったりホットリロードとかも試したいところだけど、
一旦jsでちゃんと動くところまで確認する。

```js
const { app, BrowserWindow, screen } = require('electron');
const url = require('url');
const path = require('path');

let win = null;

function createWindow() {
  const electronScreen = screen;
  const size = electronScreen.getPrimaryDisplay().workAreaSize;

  // ブラウザウインドウを作成
  win = new BrowserWindow({
    x: 0,
    y: 0,
    width: size.width,
    height: size.height,
    webPreferences: {
      nodeIntegration: true
    }
  })

  win.loadURL(url.format({
    pathname: path.join(__dirname, 'dist/index.html'),
    protocol: 'file:',
    slashes: true
  }));

  // dev toolを開く
  win.webContents.openDevTools();

  win.on('closed', () => win = null);

  return win;
};

app.allowRendererProcessReuse = true;

app.on('ready', () => setTimeout(createWindow, 400));
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});
app.on('activate', () => {
  if (win === null) {
    createWindow();
  }
});
```

## package.jsonを修正
`electron`コマンドで起動できるように`package.json`の`main`に上記ファイルを指定する。

```json
{
	"name": "angular-electron",
	"main": "main.js",
	...
}
```

# 起動できることを確認する
アプリを起動できることを確認する。
その前にAngularのビルドが必要なので実行しておく。

```bash
# Angularのファイルをビルド(最初から入っているコマンドそのまま)
$ npm run build
> dist配下にファイルが出力されていることを確認

# アプリを起動してみる
$ npx electron .
```

画像のようにAngular-CLIのテンプレートが表示されることを確認できればOK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176571/97681cf0-24b3-2427-e20d-fecae79aef4a.png)

# まとめ
Electron ＋ Angularでアプリを作ってみようと思ったので、とりあえず起動できるまでやった。
起動だけならさっくりできたので、次は`main.js`をts化したり、アプリを作っていきたいところ。

# 参考サイト
- [ドキュメント | Electron](https://www.electronjs.org/docs)
- [はじめての Electron アプリ | Electron](https://www.electronjs.org/docs/tutorial/first-app)
- [maximegris/angular-electron: Ultra-fast bootstrapping with Angular and Electron (Typescript + SASS + Hot Reload)](https://github.com/maximegris/angular-electron)
java エスケープ解析とは

## 前書き

Graalを触っていて、部分的エスケープ解析が何のこっちゃ分からなかったから、調べたメモ。

↓Graal・GraalVMに関して書いた記事
https://qiita.com/kinshotomoya/items/39a821dd6a6a52202c0a


サンプルコードは、scalaで書いています。

## エスケープとは
オブジェクトの参照がメソッドの外や、違うスレッドに存在すること。
エスケープすると、不特定多数の場所からオブジェクトへ参照できる。

## エスケープの条件
実際にのコードでは、どのような場合にオブジェクトがエスケープされていると言えるのか？
主に、以下の３つの条件がある。

1. メソッドの引数に指定
2. returnで返す（戻り値に指定する）

### 1. メソッドの引数に指定

Objectのインスタンスであるaへの参照は、hogeメソッドを超えて参照できる。
fooメソッドからも参照できる

```scala
case class Object()

object Test {
  def hoge: Object = {
    val a = Object()
    foo(a)
  }
  
  def foo(obj: Object) = ???
}

```

### 2. returnで返す（戻り値に指定する）

Objectのインスタンスbへの参照は、hogeメソッドを超えて参照できる。
b2変数が、オブジェクトaへの参照を持ってる。

```scala
case class Object()

object Test {
  def hoge: Object = {
    val b = Object()
    b
  }
  
  val b2 = hoge()
}

```

つまり、メソッドを超えて上記の例のインスタンス、a・bへの参照が可能であるということ。

## エスケープ解析とは

インスタンスの参照がメソッド外・別のスレッドにエスケープするかどうかを解析する。
様々なアルゴリズムがある。

## エスケープされていないと解析されると？
エスケープ解析の結果、参照がメソッド内に閉じられているとわかると、

### 1. インスタンスをヒープではなく、スタックを格納する。
メソッド内のみでインスタンスが使用されるなら、メソッド終了後に解放されるスタック領域に格納すると効果的。

### 2. メソッド実行の際に、不要な同期を無視する
単一スレッドからのみの参照ならば、スレッド間の同期は不要になる。


## 最適化例

エスケープ解析の結果、コンパイラはコードを最適化する。
その例を示す。

### インライン化
以下のようなコードがある。

```scala

class Person {
  def get(name: String) = {
    val person: Person = Person(name)
    if (person.name === "hoge") {
    }
    ...
  }
}

case class Person(name: String)

```

Personオブジェクトのインスタンスである、personはエスケープされていない。
このような場合、コンパイラはインライン化して最適化する。


```scala
class Person {
  def get(name: String) = {
    // val person: Person = Person(name)
    if (name === "hoge") { // インライン化

    }
    ...
  }
}

case class Person(name: String)


```

### 部分的エスケープ解析
新しいJITコンパイラ Graalの特徴の１つである。
部分的に最適化をすることができる。

以下のようなコードがあった場合。

```scala
class Person {
  def get(name: String) = {
    val person: Person = Person(name)
    val cachePerson = Cache.get(name)
    if (cachePerson.isDefined) {
      cachePerson
    } else {
     addToCache(person)
     person
    }
  }
}

case class Person(name: String)

```
cachePersonが存在している場合、オブジェクトpersonはエスケープされない。
そのことをコンパイラは解析して、以下のようなコードに直す。

```scala

class Person {
  def get(name: String) = {
    val cachePerson = Cache.get(name)
    if (cachePerson.isDefined) {
      cachePerson
    } else {
    　val person: Person = Person(name)
    　addToCache(person)
      person
    }
  }
}

case class Person(name: String)

```

`val person: Person = Person(name)`を`else`配下に移動し、`cachePerson`が存在する場合には、ヒープ領域へのメモリ割り当てををなくすことができる。代わりにスタック領域に格納され、処理効率よくなる。

`cachePerson`が存在しなかった場合には、personはエスケープされるので、ヒープ領域に格納される。

## 参考
- https://www.slideshare.net/jyukutyo/graal-in-graalvm-a-new-jit-compiler
- https://docs.oracle.com/javase/jp/11/vm/java-hotspot-virtual-machine-performance-enhancements.html#GUID-6BD8FCB5-995B-4AE9-BFAA-B2C7DE2BA5CD
- https://www.weblio.jp/wkpja/content/%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%E8%A7%A3%E6%9E%90_%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%E8%A7%A3%E6%9E%90%E3%81%AE%E6%A6%82%E8%A6%81
- https://gist.github.com/kawasima/32b8097163029d452553e4ae5b8e070b
玄関2ロックのセサミをAWS IoTボタン1回押しで解錠できるようにしてみた

# 背景など
## 本記事の位置づけ
以前にここで[玄関2ロックのセサミを1ボタンで解錠するIFTTTボタンを作ってみた（AWS Lambda経由）](https://qiita.com/nt_namazu/items/0986a2b6bad8d26a34ed)という記事を書いたのですが、そのときに作ったLambda関数を応用して、こんなこともできるようにした、という感じの記事です。

## 先行事例
セサミの発売元であるCandyhosueさんが2018年に[記事](https://ameblo.jp/candyhouse-inc/entry-12416231560.html)を出しており、筆者もこれを一度ハンズオンしてみました（AWS IoTボタンはその際に買ったもの）。しかしこの記事の手法だとセサミを1台しか解錠できないというものだったので、ボタン1発で2つのセサミを解錠したいなあ、と思ってこの記事の手法を作りました。

## AWS IoTボタンってなに
[こんなやつ](https://www.amazon.co.jp/dp/B075FPHHGG/ref=cm_sw_em_r_mt_dp_U_Y743EbZK85CGR
)です。ボタン一つ押してやればAWS上にあるIoT 1-ClickとLambdaを刺激できるというボタンですね。

# やったこと
## 1. AWS IoTボタンの登録とネットワーク接続
[公式記事](https://ameblo.jp/candyhouse-inc/entry-12416231560.html)の

- 2. AWS lot 1 clickのアプリを設定する

の手順を踏むだけでOK。

## 2. APIキーと2台ぶんのセサミIDの取得
以下の記事の `1.` の記述の要領で、APIキーとセサミIDを得ておく。

- [玄関2ロックのセサミを1ボタンで解錠するIFTTTボタンを作ってみた（AWS Lambda経由）](https://qiita.com/nt_namazu/items/0986a2b6bad8d26a34ed)

## 3. Lambda関数の準備
### 3-1. 関数の立ち上げと `pysesame2` のアップロード
以下の記事の `2-1.` と `2-2.` 記述の要領で、AWS Lambdaから関数を立ち上げて外部モジュール `pysesame2` を上げておく。

- [玄関2ロックのセサミを1ボタンで解錠するIFTTTボタンを作ってみた（AWS Lambda経由）](https://qiita.com/nt_namazu/items/0986a2b6bad8d26a34ed)

### 3-2. Pythonコードの記述
次のようなコードを記述。なおPythonのバージョンですが3.8でよいかと。

```lambda_function.py
from uuid import UUID
from pysesame2 import Sesame
import os

device_id_1 = UUID(os.environ['DEVICE_ID_1'])
device_id_2 = UUID(os.environ['DEVICE_ID_2'])
APIKey = os.environ['APIKEY']
sesame_1 = Sesame(device_id_1, APIKey)
sesame_2 = Sesame(device_id_2, APIKey)

def lambda_handler(event, context):
    sesame_1.async_unlock()
    sesame_2.async_unlock()
```

コードが書けたらその下の「環境変数」に、手順 `1.` で得たAPIキーと2台のセサミIDを1つずつ書いて保存する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512661/90fa0775-728f-92ea-e465-ae7cc0f734b7.png)

### 3-3. テスト
以上までできたら画面右上の「テスト」から、関数のテストを実行する。流し込むJSONはhello worldでもなんでもOK。セサミ2台が解錠すれば成功。

## 4. IoT 1-Clickプロジェクトの作成と、ボタンとLambda関数の関連付け
[公式記事](https://ameblo.jp/candyhouse-inc/entry-12416231560.html)の

- 4. AWSでプロジェクトを作成する
- 5. AWS IoT ボタンをリンクさせる

の手順を踏んで、IoTボタンとLambda関数の関連付けを行う。ボタンを押してセサミ2台が解錠すれば成功！！！:grin:
Keycloak+Apache+mod_auth_openidcでheader sizeのエラーが発生した件

# 発端
Apacheのリバースプロキシにmod_auth_openidcを入れて、Keycloakで認証を連携を構築している。
一通りの設定を終えて、アクセス確認をしていると、

```
Bad Request
Size of a request header field exceeds server limit
```
が出て、アクセスできないことが多々起きた。

# 対処その１：Apacheのヘッダーサイズ
そのまま、`Size of a request header field exceeds server limit`をググると、
`LimitRequestFieldSize `を設定する情報にたどり着いたので、設定する。
デフォルトは８１９０なので、とりあえず４倍の３２７６０に設定。
※値を大きくするリスクは社内限定利用なので、無視。

でも、これでも改善しない。
Chromeのデベロッパーツールで見ている限り、上限は上がっているけど、簡単に引っかかってしまう。
際限なく上げるのもよくないし、
どうしようかと、ググると、どうやらmod_auth_openidcの方に原因があることがわかった。

# 原因：mod_auth_openidcのstateのcookie
mod_auth_openidcは、セッションのstate情報をcookieにしており、
大量にタブを開いてアクセスすると、その分のstateのcookieができ、それにより、headerが肥大化する。
https://github.com/zmartzone/mod_auth_openidc/wiki/Cookies

いろいろと詳細に書いてあるが、対処としては、次の２点を試した。
※最終的には、先の対処その１と対処その２を採用し、対処その３はむしろ無効化するが。

## 対処その２：バージョン
>alternatively use a version of mod_auth_openidc >= 2.0.0 so it supports chunked cookies

バージョンを上げると効果がありそうな記述を見つける。

利用していたのが、epelのリポジトリからyumでinstallした、
Version 1.8.8だったので、対処その３の実施の準備も含めて、Versionを２.３.１１にした。
※最新は、２．４．２．１だったが、自分の環境起因で、2.3.11にした（[次回の記事](https://qiita.com/henatyokotraveler/items/1906d2e3b18ab1ddfe99)へ）
※インストールにはcjoseが依存性の関係で必要。

最新のmod_auth_openidcもcjoseも、rpmがGithubのリリースにアップされているのでそこからダウンロードしました。
https://github.com/zmartzone/mod_auth_openidc/releases


バージョンアップし、chromeのデベロッパーツールで見ていたところ、
一つのstate cookieのサイズが10分の１程度になりました。

## 対処その３：古いstate cookieの削除
古いstate cookieを削除する機能が、
2.3.8、2.3.10.1で実装されている。

>Since version 2.3.8 mod_auth_openidc limits the number of state cookies - i.e. the number of outstanding authentication request - to 7 by default, controlled by the OIDCStateMaxNumberOfCookies setting.

>Since version 2.3.10.1 mod_auth_openidc can also be configured to delete the oldest state cookie when overrunning the OIDCStateMaxNumberOfCookies limit by adding true after the size value e.g. OIDCStateMaxNumberOfCookies 5 true


```
OIDCStateMaxNumberOfCookies 7 false #デフォルト。stateのcookie ７つを上限にし、削除しない。上限に達すると、エラーを出す
OIDCStateMaxNumberOfCookies 5 true　#stateのcookie ５つを上限にし、削除する。
OIDCStateMaxNumberOfCookies 0 #stateのcookieを制限しない。
```

最初は`OIDCStateMaxNumberOfCookies 10 true`を試したが、
アクセス先のサイトに、keycloakのトークンリフレッシュのタイミングで、複数のstate cookieを同時に発生させるものがあり、そのタイミングでエラーになってしまう。

# 対処のまとめ
最終的には以下で対処を終えた。

- mod_auth_openidcのバージョンアップによるcookieサイズの抑制
- 下記の設定

```
LimitRequestFieldSize 32760
OIDCStateMaxNumberOfCookies 0 #デフォルトの７の制限でエラーになることを避ける
```
PHP ファイル操作

様々なファイル操作についての備忘録

```
ファイル構造について

-mainte
|-file.php
|_.contact.dat
　　//拡張子はtextまたはdat。
　　datはセキュリティ的にカモフラージュになる
```

#外部ファイルの内容をまるごと呼び出す方法
```php

<?php

//呼び出したいファイルを変数に入れる
$contactFile = '.contact.dat';

$fileContents = file_get_contents($contactFile);
```

#外部ファイルを上書きする方法
```php
file_put_contents($contactFile, '上書きします');

//.contact.datの内容が「上書きします」に変わる
```
#外部ファイルに追記する方法
##file_put_contents()

```php

//追記したいテキストを変数に入れる

$addText = '追記します' . "\n";

file_put_contents($contactFile, $addText, FILE_APPEND);
//.contact.datの内容に「追記します」が追加される
```

#外部ファイルの内容を取得して、','で区切って表示する方法
```.contact.dat
こんにちは,こんばんは,さようなら
hello,hi,bye
ヨッ,やあ,んじゃ
```
```php:file.php
$allData = file($contactFile);
//.contact.datの文字を配列に入れる
//配列に入れる関数file()

foreach ($allData as $lineData) {
  $explodedLineData = explode(',',$lineData);
  //コンマごとに区切って配列に入れる
  //区切る関数explode()

  echo $explodedLineData[0]. '<br>';
  echo $explodedLineData[1]. '<br>';
  echo $explodedLineData[2]. '<br>';
}

//結果
こんにちは
こんばんは
さようなら
hello
hi
bye
ヨッ
やあ
んじゃ

```
##fwrite

```php
//ファイルを開く関数
$contents = fopen($contactFile,'a+');
//ファイルを開く
//a+は追記モード

$addText = '一行追記' . "\n";
//追記したいテキストを変数に入れる

fwrite($contents, $addText);

fclose($contents);
//ファイルを閉じる

```



参考
https://qiita.com/tadsan/items/0955b3de7dc58490ddaf
空白を含むファイルパスで、二重引用符を4つ続けてエラーがでなかった。

おかしいですね？
(参考)空白を含むファイルパスを変数として扱う方法 
https://tanisukestr.hatenablog.com/entry/2018/12/30/164838
(参考)VBScript でパスに空白を含むアプリケーションを起動するときには、二重引用符を 2 つ続ける 
https://jutememo.blogspot.com/2014/03/vbscript-2.html
ただリンクにしたいときにhref="url"の代わりにonClick="location.href = 'url'"的なことをすると体験を損ねます

ただのページ遷移をしたいだけなのに、（主に手抜きという）実装の都合で JS の `location.href` になってることはありませんか？
実はそれ、体験を損ねているかもしれませんよ。

# 起こる出来事

マウスのホイールクリック（ミドルクリック）で別のタブで開けません。
Mac にはマウスホイールなんてついてないだろ？
実は Cmd+クリックも同様に別のタブで開けないんですよ。
スマホだったら長押しに相当すると思います。

したがって、意図して別タブで開かせたくない場合を除いて、location.href での遷移は避けるべきです。

厳密には JS の処理内での遷移させるのを避けよう、というべきですね。
なので Router の API を直接コールしての遷移も同様です。

できるだけ `<a href="url">` になるようなコードが望ましいです。
SPA（React, Vue, Angular）も同様のコードになるよう意識しましょう。
[#補足spa各種フロントエンドフレームワークについて](#補足spa各種フロントエンドフレームワークについて) ページの末尾にフロントエンドフレームワークでどう書けばよいか記載しています



# location.href になってる理由を考える

## 遷移先が動的に代わる

`<a href=>` を動的に書き換えましょう。

## 同じコンポーネントを使いまわしてるから history.back になってる

可能であれば親コンポーネントからパスを決定したほうがよいです。

## 親ページじゃなくて遷移元に「戻る」history.back ボタンやりたいじゃん

そういう要望がくるのはわかる。
「でもそれ別のタブで開けないんですよねえ。スマホだったら長押しができないんですよ」というのを説得材料にできないでしょうか。

history.back はブラウザの戻るボタンで同様のことができますし、遷移元によってボタンの遷移先が変わるのは、私はイマイチだと思うんです。
「 **どこからきても前のページに** 戻る」より「 **どこからきても親のページに** 戻る」と設計するほうが良いと思うのですが、最終的には様々な事情によってそうなることもありますね。

## ボタンやリンクじゃない

ならいいんじゃないでしょうか。

## 他の処理をやった後に遷移したい

処理と遷移を別に分けるべきかどうか悩むところですが、１つにまとまっていてもよいケースもあるでしょう。

## 強い意思を持って location.href を使う

そういうこともあります。存分にやれ。

# どういう人がやりがちか

根っからのMacユーザーやラップトップユーザーなど、マウスを使ってない人には馴染みがないのかもしれません。
発見でした。

# まとめ

手抜きにはささやかな代償が伴うこともある。


# 補足SPA(各種フロントエンドフレームワーク）について

## React（@rithmetyさん感謝 [該当コメント](#comment-b9db158495ef799305ff) )

```.jsx
<Link to="/path">
```

> 有名な React 系のライブラリにはいい感じにしてくれるコンポーネントなどがあります。
それらの内部の実装をまとめた記事を前に書きましたので宣伝します。
> [SPA で右クリックや shift \+ クリックなどによる別窓表示に対応させる \- Qiita](https://qiita.com/rithmety/items/fce93dec436b681a58e3)

## Vue

```.vue
<template>
  <!-- vue router -->
  <router-link to="/path">
  <!-- nuxt -->
  <nuxt-link to="path">
</template>
```

## Angular （@seapolisさん感謝 [該当コメント](#comment-3e69b46fc1cfaa7ecb03)）

```.html
<a [routerLink]="'/hoge'">
```

> ただこの[routerLink]はaタグじゃなくても付けられます。Angular Materialのテーブルの行に対してリンクを付けたいという需要があり、この記事と同様の問題が発生したので、最終的にはJS的に新しいタブで開くよう制御するディレクティブを書きました。
> [ngx\-nat\-link \- npm](https://www.npmjs.com/package/ngx-nat-link)
[AWS] Storage Gatewayの基本

####前置き
毎日AWSのサービスで学習したことをアウトプットして定着させるためにやってます。
間違いがあったらご指摘よろしくお願いします。

# Storage Gatewayってなに？
AWSのドキュメントを見てみると、
> AWS Storage Gateway は、オンプレミスのソフトウェアアプライアンスをクラウドベースのストレージと接続し、お客様のオンプレミスの IT 環境と AWS のストレージインフラストラクチャとの間にデータセキュリティ機能を備えたシームレスな統合を実現するサービスです。

と書かれてあります。これを一回読むと意味がわかる人は尊敬します。

さて、この文章を紐解くと、「オンプレ環境とクラウド上にあるAWSのストレージ(S3など)を簡単に統合できるサービス」と書かれてあります。

# 3つのゲートウェイ
ゲートウェイとは通信プロトコルが違うネットワーク同士がデータをやりとりする際、中間的存在となる機器のことです。
StorageGatewayには3つのゲートウェイがあります。

**ファイルゲートウェイ**
S3とオンプレミス環境が統合されます。そのため、IAMでの一般的なアクセス管理やCloudWatchを用いたモニタリングなどをオンプレミスから直接行うことができるようになります。

**ボリュームゲートウェイ**
オンプレミスのアプリケーションサーバーから接続できるストレージボリュームを提供します。
ボリュームには2種類あって特徴が違います。
・キャッシュボリューム
主要なデータはS3に保存されますが、頻繁にアクセスされるデータはローカルにコピーされます。そのため低レイテンシー(=低遅延)なアクセスが可能です。また、オンプレミスのストレージを拡張する必要が最小限になるのも利点です。

・保護型ボリューム
主要なデータは全てローカルに保存され、このデータを非同期でS3にスナップショットとしてバックアップを取ります。主要データ全てに対して低レイテンシーなアクセスが可能です。

**テープゲートウェイ**
長期間にわたってデータをアーカイブしたい時にコスト効率と耐久性が両方必要な時に使われる。
詳細は自分の知識では理解しきれなかったので公式ドキュメントをご覧ください。[こちらの最下部](https://docs.aws.amazon.com/ja_jp/storagegateway/latest/userguide/StorageGatewayConcepts.html)

# 最後に
わからない単語がまだまだ多すぎてググりまくりです。

参考
公式ドキュメント
https://docs.aws.amazon.com/ja_jp/storagegateway/latest/userguide/WhatIsStorageGateway.html

先人の記事
https://qiita.com/MayForBlue/items/ce0d915ffdda11ffffe2
Oracle PL/SQL ファイル操作の例

#PL/SQL ファイル操作
PL/SQLにて、UTL_FILEパッケージを用いることによりファイルの入出力を行うことができます。
例としてログを残すなどの使い方ができます。

※1. 実行前に初期化パラメータUTL_FILE_DIRを設定する必要があります。
※2. UTL_FILE_DIRパラメータの設定後は、データベースの再起動が必要になります。

##ファイル書き込み
```Write_File.sql
CREATE PROCEDURE Write_File
IS
    FILE_HD_W UTL_FILE.FILE_TYPE;
BEGIN

    FILE_HD_W := UTL_FILE.FOPEN('D:¥PLSQL','Write_File.txt','w');

    UTL_FILE.PUT(FILE_HD_W,'書き込みました');
    UTL_FILE.FCLOSE(FILE_HD_W);

END;
/
```

##ファイルに追記
```Write_File_Add.sql
CREATE PROCEDURE Write_File_Add
IS
    FILE_HD_A UTL_FILE.FILE_TYPE;
BEGIN

    FILE_HD_A := UTL_FILE.FOPEN('D:¥PLSQL','Write_File.txt','a');

    UTL_FILE.NEW_LINE(FILE_HD_A,3);
    UTL_FILE.PUT(FILE_HD_A,'追記しました');
    UTL_FILE.FCLOSE(FILE_HD_A);

END;
/
```

##ファイル読み込み
```Read_File.sql
CREATE PROCEDURE Read_File
IS
    FILE_HD_R UTL_FILE.FILE_TYPE;
    READ_DATA VARCHAR2(250);
BEGIN

    FILE_HD_R := UTL_FILE.FOPEN('D:¥PLSQL','Read_File.txt','r');

    UTL_FILE.GET_LINE(FILE_HD_R,READ_DATA);
    DBMS_OUTPUT.PUT_LINE(READ_DATA);
    UTL_FILE.FCLOSE(FILE_HD_R);

END;
/
```
laravel を利用した、ローカル環境での開発サーバ立ち上げ

#立ち上げ方について
composer を実行できる環境を想定して、記載します。
自分はmacを利用して、サーバーの立ち上げを行っています。

初めに以下コマンドを実行すると、ServerTestフォルダが作成されます。
`composer create-project --prefer-dist laravel/laravel ServerTest`

フォルダが作成されたことを確認後、フォルダの直下へ移動。
`cd ServerTest`

以下コマンドを実行すると **http://localhost:8000/** にてサーバーが起動します。
`php artisan serve`

#参考URL
https://readouble.com/laravel/6.x/ja/installation.html

#補足
起動したいポートを変更したしい際には、以下のように実行すれば可能。
`php artisan serve --port=8080`
以下クイックリファレンスにも、その旨の記載があります。
https://readouble.com/laravel/4.2/ja/quick.html

laravelのレポジトリをgit clone して、サーバーを起動しようとしても以下のエラーが発生して、起動しないので、その点はご注意を。
`$ php artisan serve`

> Warning: require(/Users/test/git/php/laravel/vendor/autoload.php): failed to open stream: No such file or directory in /Users/test/git/php/laravel/artisan on line 18

>Fatal error: require(): Failed opening required '/Users/test/git/php/laravel/vendor/autoload.php' (include_path='.:') in /Users/test/git/php/laravel/artisan on line 18
元初心者VimmerはVSCodeで今

# この記事 is なに？

エディタ遍歴が

- 4年 : gedit(色付きメモ帳) & VisualStudio & Unity を遊んでフラフラ
- 2年 : **vim**
- 1年 : **vscode**

な感じの、やる気のない学生プログラマが、**vimかぶれから抜けられない、現状の中途半端なvscode環境**を解説します。

ちなみに、言語は、割といろいろ使います。

もともとC++をよく触っていましたが、最近数か月はReactとSpring Bootが主です。その前もPythonとかいろいろです。ラズパイもよく触ります。

# vim時代の筆者の性能ざっくり

- 超簡単な**入力・移動ショートカット**は習得
- **map**は登録しまくって魔改造
- pluginも有名どころ(NERDTreeなど)は一通り入れた
- neovimに手を出したり、deopleteとか補完に手を出したり
- したあたりで、**vscodeの補完が強いらしい、しかもvimのキーバインドが使えるらしい**、ということでvscodeに転向

# vscodeに移行直後の感想

### よかったところ

- 本当にvimのキーバインドが使えそう
- **補完強い！**(各言語extensionの補完を使用)
- 初めからNERDTreeが生えている(フォルダ・ファイル一覧のことです)
- extensionにロマンを感じる
- **見た目がカッコいい**
- 思ったより起動が速い(他のIDEは化け物重いイメージだった)

### 辛かったこと

- mapのやり方がわからず、settings.jsonでちまちま直書き
- **たまにvimとvscodeのキーバインドが衝突する**
- Ctrl + Shift + P でメニューを出すのに慣れない
- Ctrl + Shift + @ でターミナルを起動するのが、すごく手間
- アップデートが多すぎて、機能を追えない
- 謎の機能・依存が多く感じた (F5は便利だけど、中で何をしているんだ...)
- そこそこ重い

# vscodeで今

以降直後から環境はあまり進化はしていませんが、ざっくりスタイルは定着してきました。

### 必須のextension

- Vim
    - vimのキーバインドが使えます
- TabNine
    - 入力補完がめっちゃかかります。なんかDeepでLearningしてるらしい。
    - ただし、言語サポートの補完と違って、Javaのimportみたいな依存関係の解決は自動化しないので注意。
- Git系(GitLens/Git Graphなど)
    - これは便利なのを適当に。
- Bracket Pair Colorizer
    - 括弧に色が付きます。
- 各種言語サポート
    - 補完、デバッガ、実行、デモ、Linterなどなど、適当に。
    - syntax highlightはextensionを入れなくてもデフォルトで入っています。
- 各種Remote
    - WSLとSSHを主に使ってます。

### 頻繁に使っているキーバインドや操作

- ファイル保存 (**Ctrl + s**)
    - vim時代は使えなかった記憶がありますが、今は便利なので使ってます。
    - 入力モードのまま、いったんファイルを保存して別の作業をしたりできます。
- カーソル移動 (vim系)
    - **gg**(最上)、**G**(最下)
    - **0**(行頭)、**$**(行末)
    - **f**(検索)
    - **hjkl**(上下左右)
- 新しい行の追加 (vim系)
    - **o**(下)
    - **O**(上)
- コピー&ペースト(vim系)
    - **y**(保存)
    - **p**(下に貼り付け)、**P**(上に貼り付け)
    - yの行数指定は、settings.json内に以下を追加することで、現在の行からの相対的な行数が表示され、便利になる。

```json
"editor.lineNumbers": "relative"
```
- 入力切替
    - **i**(入力モード)と**Esc**(標準モード)の使い分け。
    - Escの代わりに、たまに**jj**を癖で叩いてしまうので、以下のキーバインドをsettings.jsonに追加している。このキーバインドは、同時に保存もする。

```json
  "vim.insertModeKeyBindings": [
    {
      "before": ["j", "j"],
      "after": ["<Esc>"],
      "commands": [
        {
          "command": "workbench.action.files.save",
          "args": []
        }
      ]
    }
  ],
```

- 検索、置換
    - 手早さが求められる場合は、vimの**:%s/before/after/g**
    - 慎重に作業したい場合は、vscodeのメニューから編集や置換を行う。
    - vscodeは複数ファイル横断の置換が便利。
    - リファクタリングはよくわかっていない。確認のひと手間が面倒。
- プログラムの実行
    - **F5**でなぜか動くものはF5。
    - 動かないものは、ターミナルからコマンドを叩く。
- git
    - ほぼGUIでOK。

# 最後に

- キーバインドがたまに衝突するなー、と思いながら、衝突するキーバインドは一切使っていないので、どれが衝突するかはもはや忘れた。
- dockerでどうこう、、みたいなのをやってみたい。dockerわからないけど。
- 実はvimキーバインドから完全に足洗ったほうが作業効率いいよ、とかあったら教えてほしい...。
TODOリスト作成

#このページについて
・swiftの練習のために作ったものの覚え書き程度のものです。
・今回はTableViewの使い方がメインです。

##step1
・Xcodeを起動
・Create a new Xcode projectを選択
・SingleViewAppを選択し立ち上げます

##step2
・StoryBoardのViewContorollerにTableviewをドラッグ
・Tableviewのサイズを任意のサイズに変更
・その上にTableviewCellをドラッグ
<img width="1280" alt="スクリーンショット 2020-06-09 21.10.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648887/547317e3-67eb-3870-3eb5-f7fe33d6f0dc.png">

##step3
・左のViewContorollerSceneの中のTableViewを選択します
・control+ドラッグしViewControllerの(■)の部分にドロップ
・Outletsの欄が出てくるのでDataSourceとDelegateを選択
<img width="1280" alt="スクリーンショット 2020-06-09 21.14.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648887/06239b2c-7b1d-ae00-13a8-8ac6cc485d7b.png">

##step4
・左のViewContorollerSceneの中のTableViewCellを選択
・ユーティリティーエリア(右側)の右から3番目を選択
・Identifierにcellと入力
　※ここを忘れるとシュミレーターを起動した時にエラーが出ます
<img width="1280" alt="スクリーンショット 2020-06-09 21.21.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648887/a841a7bd-d609-f18a-457a-e6c7948e2520.png">

##step5
・コードを編集していきます
・ViewController.swiftを選択しクラスにUITableViewDataSource, UITableViewDelegateを追加
・すると赤い警告が出ると思います
<img width="1280" alt="スクリーンショット 2020-06-09 22.15.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648887/fa30bdb5-e54f-ece4-1fdb-d4d0949aa82b.png">
・Fixを押すとコードが追加されます。
<img width="1280" alt="スクリーンショット 2020-06-09 22.17.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648887/35c0a43c-0feb-4197-d503-d2da59aa0da8.png">
・ひとまず無視してTODOの表示したいものを書き込みます。
<img width="1280" alt="スクリーンショット 2020-06-09 22.20.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648887/a2db55bb-22c9-4bb1-6bf9-d5dddc3d20d0.png">
・先ほど無視したcodeの部分を編集していきます

    //セルの個数を指定するためのデリゲートメソッド
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return TODO.count
    }
    //セルに値を設定するためのデリゲートメソッド
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        //セルを取得
        let cell:UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        //セルに値を設定
        cell.textLabel!.text = TODO[indexPath.row]
        return cell
    }

・この様に追加して完成です

##参考にさせていただいたページ
SwiftでTableViewを使ってみよう
https://qiita.com/pe-ta/items/cafa8e20029047993025

##終わりに
完全初学者のため間違っているところなどあると思いますので
ご指摘等ありましたら是非お願いします
【Raspberry Pi】【エアコン操作】赤外線の受信・送信

ラズパイでのエアコン操作に関する備忘録。

こちらを参考にしました。
[赤外線LEDを積んだRaspberry Piでスマートルームをつくる(テスト編)](https://paltee.net/archives/180)

作業ディレクトリは
`~/work/AirControl`

#もろもろインストール
##pigpio
よく使われる`lirc`は色々面倒なので、pigpioをインストール

```
sudo apt-get install pigpio
```
インストールしたら起動しておきます。

```
sudo systemctl enable pigpiod.service
sudo systemctl start pigpiod
```

##irrp.py
pigpio作者による赤外線リモコン解析スクリプトのダウンロード

```
$ curl http://abyz.me.uk/rpi/pigpio/code/irrp_py.zip | zcat > irrp.py
```

#赤外線受信
ラズパイのGPIO23を読み取りとして使用するため、以下コマンドを入力して受信。

```
$ python3 irrp.py -r -g23 -f codes aircon:on --post 130
```

|オプション|意味|
|---|---|
|-g|読み取るGPIOピン番号|
|-f|出力先jsonファイルとキー配列の指定|
|--post|信号終端後の空白時間の目安|

>GOIOのピン番号はたとえば「GPIO23」の「23」のこと
![image-1553073694352.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136271/0b08a530-be75-a8ba-6954-be408c50d24e.png)
出典:[StackExchange](https://raspberrypi.stackexchange.com/questions/83610/gpio-pinout-orientation-raspberypi-zero-w)

#赤外線送信
GPIO25から信号送信

```
$ python3 irrp.py -p -g25 -f codes aircon:on
```
マージソート｜大きい順のソーティング

#マージソートをPythonで
###分割してまた結合（マージ）して
マージソートは、ソートする値が入ったリストを２つに分割することを繰り返し、バラバラにした後、今度は結合（マージ）するときに大きい順（小さい順もOK）に並べ替えていくソーティングアルゴリズムです。
<img width="528" alt="merge.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409451/14b61ccf-02de-f18e-d7e3-72864cfaa373.jpeg">

・ソースコードは以下の通りです

```python:mergeSort.py
data = [6,13,12,65,76,22,43,87,14,9]

def merge_Sort(data):
    if len(data) <= 1:
        return data

    mid = len(data) // 2 # ど真ん中のインデックス取得
    # 再帰的に分類
    left = merge_Sort(data[:mid]) # 左側を分割
    right = merge_Sort(data[mid:]) # 右側を分割
    # 結合（マージ）
    return merge(left, right)

def merge(left, right):
    result = []
    ii, jj = 0, 0

    while ( ii < len(left)) and (jj < len(right)):
        if left[ii] >= right[jj]:
            result.append(left[ii])
            ii += 1
        else:
            result.append(right[jj])
            jj += 1

    # 残りを一気に追加する
    if ii < len(left):
        result.extend(left[ii:]) # 左側残りを追加
    if jj< len(right):
        result.extend(right[:jj]) # 右側残りを追加
    return result

print(merge_Sort(data))

# 結果
# [87, 76, 65, 43, 22, 13, 12, 6]
```
特徴として、メモリに入りきらないような大容量のデータがあったとして、分割した別の箇所でそれぞれソーティングしておいて、それから結合しながらデータを作成することも可能となります。
ssh接続中にスリープしたMacBookが復帰するときにKarabiner-Elementsが固まる問題への対処

#問題概要
ssh接続でMacBookからサーバにアクセスして作業しているとき、たまに接続したままMacBookをスリープさせてしまうことがあります。その状態からMacbook(英字配列キーボード搭載、アプリでキーマップを変更している)を復帰させようとすると、OSがキーボードを認識できずに一切操作できなくなることがありました。原因は英語キーボードで英数かな変換キーを実現するために入れているKarabiner-Elementsでした。試しに、英かな(ei-kana)アプリやBetterToolTouchも試しましたが同じ結果に終わりました。Auto-Update checkをオフにしたりもしてみましたが無駄でした。

#対処療法
根本解決には至らなかったので、対処療法として"ssh接続中はシステムをスリープさせない"ことで対処しました。caffeinateという一定条件下でスリープを回避できるコマンドを使い、その後ろのコマンド(sshコマンド)が終了するまではシステムをスリープさせないようにします。

例えば.bashrcか.zshrcなどに以下を記述し、caffeinateを通したsshコマンドを作成します。
```
alias ssh2="caffeinate -i ssh XXXアドレスなどXXX"
```

-i はcaffeinateのオプションで、"次に記述されるコマンドが終了するまでシステムをスリープさせない"という意味があります。(なので一定時間経つとMacBookの画面は消えます)
ターミナルでssh2と打つと実行されます。

#追記
VPN接続中にMacBookがスリープしても固まることがわかりました。スリープに入る直前にVPNを切断することでしのぎます。
sleepwatcherというライブラリはスリープに入る直前にコマンドを実行してくれます。
```
networksetup -disconnectpppoeservice "VPNの名前"
```
このコマンドでVPNを切断できるので、以下のサイトを参考にして設定すれば完了です。
http://blog.serverworks.co.jp/tech/2019/08/17/sleepwatcher/

#参考にしたサイト
https://www.softantenna.com/wp/review/caffeinate/


リモートせざるを得ない状況なので、すこしでも快適に....
読書会「プログラマが知るべき97のこと」 #3

# 1．今回の読んだ記事
No.63　[ユーザの操作ミスを防止する](https://xn--97-273ae6a4irb6e2hsoiozc2g4b8082p.com/%E3%82%A8%E3%83%83%E3%82%BB%E3%82%A4/%E3%83%A6%E3%83%BC%E3%82%B6%E3%81%AE%E6%93%8D%E4%BD%9C%E3%83%9F%E3%82%B9%E3%82%92%E9%98%B2%E6%AD%A2%E3%81%99%E3%82%8B/)　
著者: Giles Colborne

# 2．記事の概要
**正しく動くだけで満足せず、利用するユーザーを考えたプログラミングを行う**

+ ユーザのミスを想定したうえでプログラムを作成する
+ 日付などのフォーマットが多岐にわたる場合、ユーザの補助を行う
+ 使い方の指示を充実させてもエラーの抑制として機能しない
+ ユーザは過去の経験則や既存のUIをもとに操作することを心得る
+ 可能であればUNDOの機能をつける



# 3．この記事を選んだ理由・感想
**理由**
自分が作ったプログラムをユーザに使用してもらう際に、どのようにすればうまく扱ってもらえるかが気になったから。
皆さんが、プログラムを作る際に記事の内容をどこまで考慮しているかディスカッションしたかったため。
（ユーザの誤入力による事故の防止や、ユーザ補助の機能などを取り入れているか等）

**感想**
この記事を読んで、システムやプログラムの「なんとなく使いにくい」という部分に対する原因と対策方法についえ理解を深めることができた。
より良いものを作るためにはどうしていけばよいかを「作る側」と「使う側」の視点で考えるよいきっかけになったと感じた。

# 4．議論

**各自のさまざまな体験談**
	
- **担当システムで誕生日を入力するフォームがある**
    - ドロップリストがあると入力が便利。和暦も入力できるように追加された。
        - 和暦の追加は要望があったのでしょうか？
            - ユーザ分析や要望で和暦が追加されたのかどうはは不明
	
- **名前にタブを入れられてDBに登録してしまった**

    - ユーザの入力なので勝手に修正してよいのか
    - この例とは違うかもしれないが、ユーザによる入力なのであえて除去してしまうと、「おせっかい」になる場合あると思う
    - ログインIDを入れてたとき、スペースが自動で消えるフォームもあった。この時のテストが大変だった

- **パスワードを勝手に変更されて登録されてしまったことがある**
    - パスワードの長さ制限に引っかかって、勝手に文字数を切られて登録されてしまった
        - それは大変！パスワードがわからなくなってしまう！ 


- **数字の入力の変換が面倒な場合がある**
    - 全角の場合、半角の場合など、サイトによっていろいろあるためそれに合わせるのが面倒だった
    - 郵便番号での住所の補完は便利

		
**他ののシステムの画面を参考にするのは重要**
他のシステムはどうしているのだろう、など参考にするためいろいろ見た方がいいと思う


**ユーザに、サイトをどのように使ってほしいのか考える**
入力が自由すぎると、ユーザは想定外の信じられない操作をするかもしれないので、使いやすくかつソフトウェアにも優しいUI設計をしておきたい

# まとめ
3回目なので、初回よりも皆が意見を言いやすい感じになってきた気がする。
次回に続く。
【Windows】EC2でPermission denied (publickey,gssapi-keyex,gssapi-with-mic). 



まずEC2インスタンスに接続するために

```
ssh -i hogehoge.pem ec2-user@IPアドレス
```

を実行すると

```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions for 'hogehoge.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "hogehoge.pem": bad permissions
ec2-user@IPアドレス: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
```

エラー発生！
権限が開きすぎてるって言われてます。
EC2のサイトに記載されてるコマンドを実行。

```
$ chmod 400 hogehoge.pem
```
そして再度SSHで接続。

```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions for 'hogehoge.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "hogehoge.pem": bad permissions
ec2-user@IPアドレス: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
```
**????????**
エラーメッセージ再び。。。
取り合えず`ls -l`で権限を確認してみると

```
-r--------+ 1 user          user     1696 Jun 8 11:21 hogehoge.pem
```
権限は変わってるっぽい

Windows環境でchmod使ったのがおかしかったのかなーと思い
Windowsのプロパティで権限を確認。

chmod実行前
![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/54b04adc-c42f-e303-27fa-18cbf8129bea.png)
chmod実行後
![hoge3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/0802260d-80a7-5f44-15d4-8fc33d00c288.png)

なんか増えてる

よく分からないけどhogehoge.pemに対して色々試した感じ、
chmodする前まではアクセス許可を与えられてるユーザーグループを削除できないけど、
chmodした後だとユーザーグループ消せるようになってた。
Windowsの権限管理に関して壊滅的なことやってる雰囲気を感じた。。。((((；ﾟДﾟ))))

まあ権限広すぎるらしいから自分以外の権限を消し飛ばすと
**EC2インスタンスに接続できました。**
与えた権限は以下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/3dd10d64-aab5-8054-c748-ee4c8181919c.png)

～追記～
ふとした時に自分の記事を見直して作業をしようとすると、chmodをしても権限が削除できる状態でないなど、再現性が無かったので権限削除する方法について正規の手段を載せます。

まず、何もしていない状態でファイルに付いた権限を削除しようとすると以下のエラー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/450b8e80-e1f7-2662-136b-ac58e577031f.png)

プロパティの画面に戻る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/a8b731a9-9bf5-78dd-3589-d52b1c44b7a5.png)

「詳細設定(V)」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/ca663ef7-ddcb-2a5e-2480-851d8a832fb2.png)

「継承の無効化(I)」を押して
「継承されたアクセス許可をこのオブジェクトの明示的なアクセス許可に変換します。」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/ffa1f2df-82c0-86ca-f158-10f6305bee62.png)

すると以下のような感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/187aa87e-6d5d-d8a7-8054-7e60c5c3531f.png)

この状態になったら「適用(A)」を選択。すると元のプロパティ画面で削除可能になっているはずです。

それが完了したら自分以外の権限を消し飛ばします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/a7b60baa-4cb6-1785-f364-98ee28e8e78a.png)

以上。
Puppeteerで繰り返し処理

# はじめに
[【初心者】Puppeteerでよく使うコードベスト3](https://qiita.com/Shin/items/aa5b82d1f0505ca9608f)
に処理追加。
繰り返し処理を追加しました。


# 繰り返し処理するコード
以下のようにdo whileで処理を記載する。

```javascript
do {
  // 処理
} while(true);
```

# 最終的なコード

```javascript
const puppeteer = require('puppeteer');
// ID・アカウント認証する時はここでID・アカウント情報を読み込む
const {USER, PWD} = require('./config.json'); // 認証が必要であれば別ファイルのconfigファイルから読み込む

(async () => {
    const browser = await puppeteer.launch({
        headless: false,  // ブラウザの動きを表示
        slowMo: 50  // puppeteerの操作を遅らせる
    })
    const page = await browser.newPage()

    // ページを開く
    await page.goto('https://www.google.com/')

    // do {処理} while(true);
    do {
      // 指定した時間待つ
      await page.waitFor(10000); // ミリ秒
      // 入力
      await page.type("#IdUser", USER); // 変数の場合
      // クリック
      await page.click("#loginButton"); // セレクタ
      // テキスト取得
      const text = await page.$eval('td.timeHour', text => text.textContent) // セレクタ
    } while(true);
    // ブラウザを閉じる
    await browser.close()
})()
```
ドメインサービスの仕組み

# ActiveDirectoryについて
マイクロソフトが提供するユーザー管理を行う仕組み
簡単に言うとあなたは誰?を確認する役割がある
[https://www.atmarkit.co.jp/ait/articles/1404/11/news028.html](https://www.atmarkit.co.jp/ait/articles/1404/11/news028.html)

#ドメインについて
ActiveDirectoryとは厳密に使いわけると異なる
ドメイン・・・1回のログオン操作でアクセスできる範囲
ActiveDirectory・・・マイクロソフトが提供するユーザー管理に関わるさまざまな役割でその一つにドメインサービスがある
ドメインサービス・・・ActiveDirectoryのうちの一つのサービス。1回のログオン操作でアクセスできる範囲を決める

# ドメインサービスのメリット
ドメインサービスを利用しない場合、ネットワーク上のPCにアクセスしたい場合はアクセス先のPC毎に設定したユーザー**(ローカルユーザー)**でアクセスしないといけない。

例えば、同一のユーザーでネットワーク上の3台のサーバーにアクセスしたい場合はそれぞれのサーバーにそのユーザーのアクセス権を登録しないといけない。

また、ユーザー情報が変更されると再度、3台のサーバーに登録しなおす必要がある。この管理方法だと、ユーザー数やPC台数が多くなると煩雑になってしまう。

しかし、ドメインサービスを利用する場合、一元管理されたユーザー情報**(ドメインユーザー)**をドメインに参加しているPCやサーバーが参照して、ユーザー認証を行うので、各PCにユーザー登録しなくてもよく、ユーザー情報を変更する必要がでても、ユーザー情報を一元管理しているドメインコントローラーのユーザー情報を変更するだけでよい。

次回認証方法について(詳しく)

参考資料1[https://www.atmarkit.co.jp/ait/articles/1405/26/news024.html]
参考資料2[https://www.slideshare.net/SuguruKunii/active-directory-25767080]

ドメインの管理者とローカルの管理者の関係[https://milestone-of-se.nesuke.com/sv-advanced/activedirectory/domain-and-local-users/]
【C++】初級者からみた三方比較演算子

# 三方比較演算子について
C++20で追加予定の比較演算子`<=>`。
比較演算子だがbool値を取らない。

# 主な用途
三方比較演算子をオーバーロードすることで他6種の比較演算子が自動生成される……わけではないらしく、
実際は`==`と`!=`が生成されないため、`==`のオーバーロードも必要。
三方比較演算子をオーバーロードする際の戻り値の型は以下の三種。

* `std::strong_ordering`
`==`が代入可能性を満たしている。
`==`が真なら値は全く同じという解釈で大体あっていると思う。

* `std::weak_ordering`
`==`が代入可能性を満たしているとは限らない場合に使うっぽい。
例えば文字列比較で大文字小文字を区別したくないときの三方比較演算子はこの型を返すべき。

* `std::partial_ordering`
唯一比較結果なし(unordered)の場合がある型
unorderedのときはすべての比較演算が偽になる模様。

また三方比較演算子は符号なし整数型と符号付整数型の比較ができないらしいので制約でも使えそう。

以下コード例

```c++:
#include <iostream>
// オーバーロードの例
struct A{
    int a = 0;
    auto operator<=>(const A& value) const -> std::strong_ordering{
        return this->a <=> value.a;
    }
};
// 制約に三方比較演算子を使用する
template <class T, class U>
requires requires (const T& x, const U& y) { x <=> y; }
bool myless(const T& t, const U& u){
    // return t < u; // t<u がdeleteされるとエラーになるので念の為こちらは使用しない
    return (t<=>u) < 0;
}
// 通常の比較演算子の場合
template <class T, class U>
requires requires (const T& x, const U& y) { x < y; }
bool myless2(const T& t, const U& u){
    return t<u;
}

int main()
{
    A a1{.a=-1},a2{.a=1};
    std::cout << std::boolalpha;
    std::cout << (a1 < a2) << std::endl;                // true
    std::cout << myless(a1,a2) << std::endl;            // true
    std::cout << (-1 < 1u) << std::endl;                // false
    //std::cout << myless(-1,1u) << std::endl;          // コンパイルエラー
    std::cout << myless2(-1,1u) << std::endl;           // false
}
```
踏み台サーバ越しのファイル転送

##はじめに
Zscalerなんかを入れている状態だとセキュリティ的に直接EC2に接続できない問題が起きる。
そうなると一度踏み台を経由して繋ぐことになるが、ファイル転送を行うと踏み台にしか送れない問題がある。



##踏み台サーバへ接続
接続後、Teraterm>設定>SSH転送まで入る

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208003/b3ef2372-24b6-5482-14f9-55d376b267de.png)

追加>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208003/9f96d780-e5d6-1d88-9e3b-6570eecbadf5.png)


- ローカルのポート
    - 任意（8080とか）
- リモート側のホスト
    - 本来接続したいIP
- ポート
    - SSHなら22でいいはず



##仕上げ
踏み台に接続しているウィンドウを閉じずに、新しくウィンドウを開く
そこで、

- ホスト
    - localhost or 127.0.0.1
- ポート
    - 先ほど設定した任意のポート番号(8080)

これで本来接続したい先に繋がる

あとは、普通にドラッグアンドドロップで転送が行える。

##最後に
多少面倒ではあるけれど、これくらいでテレワークが継続できるならいいもんである。
AWSネットワークの基礎①「VPC」「サブネット」「リージョン」「アベイラビリティゾーン」


##VPCとは

アカウントに紐付く仮想ネットワーク空間
他のVPCと論理的に区別されている
※AWSではアカウントに1つ以上結びついています。

<注意点>
VPCはAZを跨げるが、リージョンは跨げない
リージョン=国
AZ=データセンター
※厳密には違うそうですが、初心者の認識は一旦これでイメージを！
※AZはアベイラビリティゾーンのことです

##サブネットとは
大きなネットワークを小さなネットワークに分割すること

<注意点>
サブネットはAZを跨って作成することはできない


▼参考動画
https://www.youtube.com/watch?v=mHi2yFWLz9M
選択ソート｜備忘録

# 大きい順にソーティングしてみた
 よく使われる手法で、先頭から順に調べながら、
それまでの要素よりも大きい値が登場したらそのインデックスを記録する方法

```Python:select_sort1.py
data = [6,13,12,65,76,22,43,87,14,9]

for ii in range(len(data)):
    max = ii
    for jj in range( ii + 1, len(data)):
        if data[max] < data[jj]:
            max = jj

    # ここでSWAP
    data[ii], data[max] = data[max], data[ii]

print(data)

# 結果
# [87, 76, 65, 43, 22, 14, 13, 12, 9, 6]
```
この手法は容易に導入しやすい分、for二重ループとなるので、１０件、２０件程度なら大した差は出ないでしょうが、１０万件、２０万件といったソーティングでは負荷がかかりやすい。
routes.rbのcollectionとmemberについて詳しく学習

##そもそもcollectionやmemberってどんなときに使うか？
**[結論]**
「resourcesでroutingを設定しているとき、resourcesメソッドでは`自動で生成されない`actionへの
ルーティングを設定するとき」に使用する。

通常RailsのWebアプリケーションの中でルーティングを設定する際には7つのアクションを
自動生成してくれる`resources`メソッドを使用することが多いが、例えば投稿検索機能などを新たに追加で実装する際にはresourcesで設定できる７つのアクション以外にルーティングを生成しなければならない。そこでこういった場合に`collection`や`member`を使用する。

##それではcollectionとmemberにはどんな違いがあるか？
**[結論]**
ルーティングを設定する際に**「:id」を含ませるかどうか**の違い。

|||
|:---------|:---------------------|
|collection|ルーティングに「:id」がつかない|
|member    |ルーティングに「:id」がつかない|

**【例】`collection`で定義した場合**

```ruby:route.rb
Rails.application.routes.draw do
  resources :tweets do
    collection do
      get 'search'
    end
  end
end
```
**【例】collectionのルーティング**

```
Prefix           Verb    URI                                 Pattern
search_tweets    GET    /tweets/search(.:format)              tweets#search
```
**※上記をみると「:id」がついていないのが確認できる。**
つまり投稿一覧ページのように`データを特定する必要がない`場合はcollectionでOK!!


**【例】`member`で定義した場合**

```ruby:routes.rb
Rails.application.routes.draw do
  resources :tweets do
    member do
      get 'search'
    end
  end
end
```

**【例】memberのルーティング**

```
Prefix           Verb    URI                                 Pattern
search_tweet      GET    /tweets/:id/search(.:format)       tweets#search
```
**※上記をみると「:id」がついているが確認できる。**
つまり詳細ページのように`データを特定する必要がある`場合はmemberを使用！！

##まとめ
collectionやmemberはルーティングの設定で`resourcesメソッド`を使用した際に
**新たにアクションを追加したい**場合に使用する。
またそのアクションを動かすときにparamsで**「:id」**を受け取りたい場合は`member`を使用し、
特に**id**を指定して特定のページにいく必要がない場合は、`collection`を使用してアクションを追加する。

自分自身検索機能を入れた時に使用したこの部分の概念がとても難しいと感じ、
よく理解できていなかったが、再度調べてなおして学習してみると意外と悩まず理解することができました。

＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊

**参考記事**
[railsのroutes.rbのmemberとcollectionの違いをわかりやすく解説してみた。〜rails初心者から中級者へ〜](https://qiita.com/hirokihello/items/fa82863ab10a3052d2ff)
ノイズに強いテレワーク用マイクを自作する。

テレワークをしていると、どうしても相手のマイクの音質が気になってしまい、転じて自分のマイクの音質が気になってしまいます。
PC用のマイクは、USBからバスパワーで電源をとり、それをコンデンサマイクに内蔵されているJFETに供給する構成上、USB電源の質で音質が左右されてしまいます。

なので、自作してみました。
CM108は比較的メジャーなUSB-DAI+ADC。このICにマイクの電源は内蔵されていますが、こちらは使用せず、POL電源で別途レギュレートしてあげます。マイクはPSRRの良いシリコンマイク。電源部はUSBのフレームレートに起因するノイズを巻き込まないように、細心の注意でデカップリングコンデンサを配置。特にC11,C12は近接配置です。

![CM108AH_USBDAI.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599011/3b45ff70-5569-4212-237a-5e90175ddc6e.png)

![CM108_DAI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599011/3ed045b9-218c-93ba-45ef-113d202c98d9.jpeg)
ゼロから始めるLeetCode Day51 「647. Palindromic Substrings」

#概要
海外ではエンジニアの面接においてコーディングテストというものが行われるらしく、多くの場合、特定の関数やクラスをお題に沿って実装するという物がメインである。

その対策としてLeetCodeなるサイトで対策を行うようだ。

早い話が本場でも行われているようなコーディングテストに耐えうるようなアルゴリズム力を鍛えるサイト。

せっかくだし人並みのアルゴリズム力くらいは持っておいた方がいいだろうということで不定期に問題を解いてその時に考えたやり方をメモ的に書いていこうかと思います。

[Leetcode](https://leetcode.com/)

[ゼロから始めるLeetCode 目次](https://qiita.com/KueharX/items/6ee2502c3b620c795b70)

前回
[ゼロから始めるLeetCode Day50「739. Daily Temperatures」](https://qiita.com/KueharX/items/eccc225ccab38969e23d)

今はTop 100 Liked QuestionsのMediumを優先的に解いています。
Easyは全て解いたので気になる方は目次の方へどうぞ。

[Twitter](https://twitter.com/kueharx)やってます。

# 問題
[647. Palindromic Substrings](https://leetcode.com/problems/palindromic-substrings/)
難易度はMedium。
Top 100 Liked Questionsからの抜粋です。

問題としては、文字列`s`が与えられます。
この文字列内の回文の数を数え、その数を返すアルゴリズムを実装してください、というものです。

なお、開始インデックスまたは終了インデックスが異なる部分文字列は、同じ文字で構成されていても、異なる部分文字列としてカウントされます。

>Input: "abc"
Output: 3
Explanation: Three palindromic strings: "a", "b", "c".

>Input: "aaa"
Output: 6
Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".

# 解法

よくある回文のチェック方法としては最初から文字列を舐めたものと反対から舐めていったものが一致すれば回文であるということになります。

Bruteforce(総当たり)でよければfor文を二重に回せば良いことになりますが、for文を2重に回すと計算量がO(N^2)になってしまい、とても遅くなってしまいます。

```Python
class Solution:
    def countSubstrings(self, s: str) -> int:
        ans = 0
        if not s:
            return ans
        for i in range(len(s)):
            ans += 1 
            for j in range(1, i+1):
                if self.is_palindrom(s[i-j:i+1]):
                    ans += 1
        return ans

    def is_palindrom(self, s):
        return s == s[::-1]
# Runtime: 604 ms, faster than 13.54% of Python3 online submissions for Palindromic Substrings.
# Memory Usage: 13.8 MB, less than 81.86% of Python3 online submissions for Palindromic Substrings.
```

他にどんな解き方があるかdiscussを見てみましょう。
例えば、[この解答法](https://leetcode.com/problems/palindromic-substrings/discuss/392119/Solution-in-Python-3-(beats-~94)-(six-lines)-(With-Detaiiled-Explanation))です。

```Python
class Solution:
    def countSubstrings(self, s: str) -> int:
	    L, r = len(s), 0
	    for i in range(L):
	    	for a,b in [(i,i),(i,i+1)]:
	    		while a >= 0 and b < L and s[a] == s[b]: a -= 1; b += 1
	    		r += (b-a)//2
	    return r
# Runtime: 132 ms, faster than 71.16% of Python3 online submissions for Palindromic Substrings.
# Memory Usage: 13.8 MB, less than 71.36% of Python3 online submissions for Palindromic Substrings.		
```

while文の条件付けの部分が肝ですね。
こういった風に漏れなくダブりなくしっかりとフローを考えられるのはとてもすごいと思いました。

パッと見でもある程度分かりやすいですし、英語ではありますが、詳しく解説してくださっているので気になる方はリンク先で確認してみると良いかもしれません。


今日はここまで。お疲れ様でした。
TechAcademyが無料公開している「HTML・CSS入門講座」を受講する～HTML第4回～

# アジェンダ
* パス
    * 絶対パス
    * 相対パス
* HTMLのタグ
    * a
* HTMLの属性
    * href
    * id
* 実践

# パス
パスとは、ファイルの存在する場所のことである。

## 絶対パス
絶対パスとは、どのディレクトリからでも、対象のファイルの存在する場所がわかるように表す記法である。

## 相対パス
相対パスとは、今いるディレクトリを基準として、対象のファイルの存在する場所を表す記法である。

# HTMLのタグ
## a
アンカータグを示すタグ。他のファイルや指定したidへのリンクを示す。
anchorのa。

# HTMLの属性
## href
リンク先を指定する属性。値にはリンク先ファイルのパスを記載する。
リンク先をidに設定する場合、id名の先頭に # を付ける。
hypertext referenceのhref。

## id
文書(またはHTMLファイル)の位置に名前をつける属性。名前をつけることによって、リンク先に指定することができる。
値にはid名を記載する。
identifierのid。

# 実践
上記のタグ・属性を使用し、以下のindex.htmlとmenu.htmlを作成した。

```html:index.html
<!DOCTYPE html>

<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>トップページ</title>
  </head>
  <body>
    <h1 id="top">トップページ</h1>
    <p>ようこそ！何をしますか？</p>
    <ul>
      <li><a href="./menu.html#lunch">ランチメニューを見る。</a></li>
      <li><a href="./menu.html#dinner">ディナーメニューを見る。</a></li>
    </ul>
  </body>
</html>
```

```html:menu.html
<!DOCTYPE html>

<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>メニュー</title>
  </head>
  <body>
    <h1 id="lunch">ランチメニュー</h1>
    <ol>
      <li>おにぎり</li>
      <li>らーめん</li>
      <li>かれー</li>
      <li>ぱん</li>
    </ol>
    <h1 id="dinner">ディナーメニュー</h1>
    <ol>
      <li>すぱげてぃ</li>
      <li>うなぎ</li>
      <li>おむらいす</li>
      <li>ぴざ</li>
    </ol>
    <a href="./index.html">トップへ戻る</a>
  </body>
</html>
```

index.htmlをWebブラウザに表示させるとこんな感じ。
ランチメニュー、ディナーメニューにそれぞれリンクができている。
![index.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648214/6fb4aa45-417f-d0a9-40be-d22e10f2d9a3.png)

「ランチメニューを見る。」をクリックすると、menu.htmlのランチメニューの箇所が表示される。
![lunch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648214/8799cc68-02d1-6e2e-05e9-cf82c0141c66.png)

「ディナーメニューを見る。」をクリックすると、menu.htmlのディナーメニューの箇所が表示される。
![dinner.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648214/e9d95185-a341-a8b0-963e-6bbc82f49166.png)

そして、menu.htmlの「トップへ戻る」をクリックすると、index.htmlが再び表示される。

# おわりに
今回はリンクの記述の仕方について学んだ。
idを使用することで、同ページの特定の箇所にリンクを作成できる。とても便利だと感動した。

次回 >> [ここ](https://qiita.com/MakoMakoMakotsu/items/84d96259860fa5050f21)

## 参考
[4-1 アンカータグ（HTMLのリンク）](https://www.youtube.com/watch?v=Eo-_dQRstGU&list=PLjw-30bsJNVU87F5iCPAW9kB4QDUGQxUG&index=12)
[4-2 相対パスと絶対パス（HTMLのリンク）](https://www.youtube.com/watch?v=2QuEQS8GYa0&list=PLjw-30bsJNVU87F5iCPAW9kB4QDUGQxUG&index=13)
ESLint 上で dprint を使う

[dprint] は [Deno] に `deno fmt`コマンドとして内蔵されている JavaScript/TypeScript のためのフォーマッターです。Rust で記述されており、高速に動作します。
[eslint-plugin-prettier] のような感じで ESLint 上で動作させられそうだったので作ってみました。

# [eslint-plugin-dprint]

## 💿 インストール方法

[npm] かその互換ツールを利用します。

```console
$ npm install -D eslint eslint-plugin-dprint
```

## 📖 使い方

`.eslintrc.*` ファイルを記述します。

```jsonc:.eslintrc.json&nbsp;(例)
{
    "extends": ["eslint:recommended", "plugin:dprint/recommended"],
    "rules": {
        "dprint/dprint": ["error", {
            "config": {
                // ここに dprint の JavaScript/TypeScript 向け設定を書く
            }
        }]
    }
}
```

- [dprint] の JavaScript/TypeScript 向け設定は [こちら](https://dprint.dev/plugins/typescript/config/)。
- `plugin:dprint/recommended` 設定には、競合する ESLint のルールをオフにする設定が含まれています。
- このプラグインは、`dprint.config.js`ファイルを読みに行きません。このプラグインは設定ファイルを解釈する CLI パッケージに依存できない[^1]ためです。

そして、普段通りに ESLint を利用してください。

## 実装

[dprint]は、各言語向けのフォーマッターがプラグインとして独立して存在しています。[dprint] のコアはファイルの種別に対応するプラグインを呼び出す感じです。

[eslint-plugin-dprint] は、[dprint] の TypeScript プラグイン (`typescript.wasm`) を読み込んで ESLint から叩いています。その後、フォーマット前後のテキスト差分を自動修正可能な ESLint エラーとして報告しています。

[lib/dprint/typescript.ts](https://github.com/mysticatea/eslint-plugin-dprint/blob/53072f88567951630f52b900e39348a6dda0ffa5/lib/dprint/typescript.ts) が `typescript.wasm` を読み込んで叩いているところです。WebAssembly は文字列を直接やりとりできないので意外と面倒でした。オブジェクトを JSON 文字列でやりとりするのも非効率そうです。

[^1]: [npm] パッケージとして公開されていないこと、オープンソース ライセンスではないこと等が理由です。

[Deno]: https://deno.land/
[dprint]: https://dprint.dev/
[npm]: https://www.npmjs.com/
[eslint-plugin-prettier]: https://www.npmjs.com/package/eslint-plugin-prettier
[eslint-plugin-dprint]: https://www.npmjs.com/package/eslint-plugin-dprint
GPUってなんだ？

#GPUってなんだ

graphic praphics processing unitの略である。

# これからの並列計算のためのGPGPU連載講座

##第１回
https://www.cc.u-tokyo.ac.jp/public/VOL12/No1/201001gpgpu.pdf

- GPGPU
    - GPUを用いた計算
- CUDA
    - GPGPUの開発環境
- GPU
    - GPUはグラフィックス処理の並列性が高いため、ハードウェアレベルでの高い並列性を備えている。
    - グラフィックのsリにはxyzw及びARGB（色計算)のベクトル演算が多様されるためベクトル計算に強い。
- グラフィックプログラミング
    - グラフィックAPI
        - 画像処理を記述するAPI
    - シェダー言語
        - GPUの動作を記述する
    - グラフィックを処理するために作られた仕組みであるためGPGPUには適していない。そのためGPGPU専用の言語のcudaが開発された。
    - 

第２回
https://www.cc.u-tokyo.ac.jp/public/VOL12/No2/201003gpgpu.pdf

- cuda
    - nvidia製のGPU向けのプログラミング環境

第３回
https://www.cc.u-tokyo.ac.jp/public/VOL12/No3/201005_gpgpu2.pdf

第４回
https://www.cc.u-tokyo.ac.jp/public/VOL12/No5/201009_gpgpu.pdf
Reduxの概念を理解する

**このページの目的**
・Reduxを利用して開発を行う上でReduxの流れを理解する
・メリットやデメリットを理解する


#Redux基本情報

**Reduxとは**
・state（状態）を管理を簡単にするためのフレームワーク
・Reducer/State/Action/ActionCreatorの要素からなる
・ReduxはjQueryやAngular、VueなどReact以外のフレームワークとも併用できる(Reactと相性がいい)

**Reduxのメリット**
・State変更までの流れがルール化されているためコードが読みやすくなる
・ルール化によりメンテナンスやテストがしやすくなる
・親子関係以外のコンポーネント同士でのやりとりが簡単に出来るようになる
（詳細は下図）

 ![reduxflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594379/16894a71-f6cc-1dc0-21e7-f25d72b565ee.png)
→今まで親子関係が深いと値の受け渡しなどが複雑になっていたState管理も、Reduxを使うことでどのコンポーネントからでもStateを変更させることができるようになり、状態管理が楽になる。
→複数人開発や、遠隔地で開発を進めている場合でも、Reduxを使うことで開発を進めやすくなる。
 
**Reduxのデメリット**
・ルール化のための下準備に手間がかかる（→小規模開発には向かない）

##Reduxの流れ
<img width="887" alt="スクリーンショット 2020-03-18 9.13.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594379/b9a5cfee-96d9-c029-4023-524870687af4.png">

Reduxは上図のような流れで処理を進めていきます

今回は、「パン屋さんの商品リストの編集」を例にとって書きたいと思います

店員さんが編集画面から[編集完了]ボタンを押したところからスタートしたいと思います
([編集完了]ボタンが押される)
1.ボタンを押されたことからコンポーネントが動き出し、コンポーネント内でActionの引き金(ActionCreater)が引かれ、Actionを呼び出す
2.ActionCreaterをもとに対応するActionが発行され、Reducerを呼び出す
3.ReducerのなかでState変更処理を実施する
4.新しいStateができる
5.ページが新しいStateをみて再読込され、変更が反映されている
<img width="1008" alt="スクリーンショット 2020-06-09 20.59.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594379/a70f5cda-c5f1-49f5-8dce-5766622b8d85.png">
<img width="992" alt="スクリーンショット 2020-06-09 20.55.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594379/b1a27bc8-d3cf-4af7-32df-1b03ffd03a51.png">

このような流れでReduxではState変更をしていきます

##まとめ

**Reduxの流れは**
①あるコンポーネントで状態変更が必要になるファンクションが呼び出される
②そのファンクションはActionCreaterと呼ばれ、その名の通り、ActionをCreate、つまりActionを呼び出します
③そのActionが呼び出されると、そのActionに合ったReducerが呼び出されて(Ajax通信などを経て)Stateが新しく作り変わる

**Reduxのメリット**
・State変更までの流れがルール化されているためコードが読みやすくなる
・ルール化によりメンテナンスやテストがしやすくなる
・親子関係以外のコンポーネント同士でのやりとりが簡単に出来るようになる

**Reduxのデメリット**
・ルール化(ActionやReducerなど)のための下準備に手間がかかる（→小規模開発には向かない）


---
間違っているところなどあればお気軽に教えていただきたいです
最後までお読みいただきありがとうございました☺︎
Thymeleaf関連エラーの解決方法

# ThymeleafでリストがNullであるかどうかのチェック方法
How to check if list is empty using thymeleaf?

```html

<div th:if="${not #lists.isEmpty(xxxxxx)}">
 --content--
</div>
```
org.springframework.expression.spel.SpelEvaluationException: EL1007E:(pos 0): Property or field 'xxxxxx' cannot be found on nullってメッセージが出たときに、リストの場合、上記のように修正すれば、直ります。けっこうはまりました。