OmniAICreator/Qiita-1.07M huggingface dataset:
useState更新タイミング/useEffect初回レンダリング、非同期処理


たぶん Vue から React に来た人ははまるんじゃないかポイント

<h2>useState</h2>
初めて見ると変わった書き方だが、ただ状態管理してくれるもの

```react
const Qiita = () => {
    const [data, setData] = useState(0)
    const up = () => {
        setData((data) => data + 1)
    }
    return <div onClick={up}>{data}</div>;
};

```

クリックしたら１づつ上がる関数である

<h4>更新タイミング</h4>
ここで私は躓いた
例えば、クリックされプラス1されたとき、この数字をバックエンドに送りたい時なんかを考える

```react
const Qiita = () => {
    const [data, setData] = useState(0)
    const up = () => {
        setData((data) => data + 1)
        console.log(data)
    }
    return <div onClick={up}>{data}</div>;
};

```

1 回クリックしたときのコンソールは０
2 回目は１

おかしいぞ、１ずつずれている

どうやら、useState の data が更新されるのは up 関数が終了後らしい

それを踏まえて、更新時に何か処理したいときには、こう書けばいいらしい

```react
const Qiita = () => {
    const [data, setData] = useState(0)
    const up = () => {
        setData((data) => data + 1)
    }

    useEffect(() => {
        console.log(data)
　　　　//data更新時の処理
    }, [data])

    return <div onClick={up}>{data}</div>;
};
```

<h2>useEffect</h2>

<h4>非同期処理</h4>
useEffect内で非同期処理をする場合はこうかく

```react
const Qiita = () => {
    const [data, setData] = useState(0)
    const up = () => {
        setData((data) => data + 1)
    }

    useEffect(() => {
        const fetch = async () => {
          　//非同期処理
            await axios.get("API")
        }
        fetch()
    }, [data])

    return <div onClick={up}>{data}</div>;
};
```

これでデータが更新されたときに非同期処理ができる

```react
    useEffect(async() => {
        await axios.get("API");
    },[data])
```

こう書くとエラーが出てしまう
理由はコールバックの中に async 関数や Promise はいれられないから

<h4>初回レンダリング</h4>

useEffect の第二引数に[]を指定するとマウント時にのみレンダリングされる

先ほどのプログラムを例に見てみよう

```react
const Qiita = () => {
    const [data, setData] = useState(0)
    const up = () => {
        setData((data) => data + 1)
    }

    useEffect(() => {
        const fetch = async () => {
            console.log("初回レンダリング")
            await axios.get("API")
        }
        fetch()
    }, [data])

    return <div onClick={up}>{data}</div>;
};
```

こちら側の意図としてはクリックされて up 関数実行され、data が更新した時に API を取得してほしい

だが実際は、data はマウント時にも更新されるので、クリックする前に get の処理は一度実行されてしまう

初回レンダリング時の useEffect の実行を防ぐにはこうかく

```react
const Qiita = () => {
    const renderFlgRef = useRef(false);
    const [data, setData] = useState(0)
    const up = () => {
        setData((data) => data + 1)
        console.log(data)
    }

    useEffect(() => {
        if (renderFlgRef.current) {
          const fetch = async () => {
            console.log("クリック時に実行");
            //await axios.get("API")
          };
          fetch();
        } else {
          renderFlgRef.current = true;
        }
    }, [data])

    return <div onClick={up}>{data}</div>;
};
```

初回レンダリングでフラグをたたせて、二回目以降は条件分岐してやればいい
AWS Lambda(Python)でmultiprocessing【Python,Lambda】

# はじめに

Lambda高速化のためのmultiprocessingを使った並列処理です。パッと使いたいときの自分用テンプレです。

# 実装
LambdaのPython3.6です。

```python
import json
import boto3
from multiprocessing import Process, Pipe
import time

def worker(conn, num):
    # ここに処理を記述
    # boto3を使う場合
    # session = boto3.Session()
    # s3 = session.client('s3')
    print(num)
    response = f'process: {num}'
    time.sleep(1)
    conn.send(response) # 処理結果
    conn.close()

def lambda_handler(event, context):
    
    results = []
    processes = []
    parent_connections = []
    for i in range(10):
        parent_conn, child_conn = Pipe()
        parent_connections.append(parent_conn)
        process = Process(target=worker,args=(child_conn,i))
        processes.append(process)
    for process in processes:
        process.start()
    for process in processes:
        process.join()
    for parent_connection in parent_connections:
        results.append(parent_connection.recv())

    body = json.dumps({'results': results})
    return {
        'statsCode': 200,
        'body': body
    }
```

並列処理でboto3をたたく場合はスレッド(プロセス)の中でboto3.Session()からclientやresourceを呼びます([参考](https://dev.classmethod.jp/articles/python-boto3-session-thread-unsafe/))。

# 参考

- [Pythonのthreadingとmultiprocessingを完全理解](https://qiita.com/kaitolucifer/items/e4ace07bd8e112388c75)
- [Parallel Processing in Python with AWS Lambda](https://aws.amazon.com/jp/blogs/compute/parallel-processing-in-python-with-aws-lambda/)
CloudFront Functionsで画像のリクエストをWebPに書き換える

# CloudFront Functions


同じS3ディレクトリに  `.jpg.webp`や`.png.webp`などの拡張子のWebPがある前提で

Viewer Requestに対して以下の関数を設定

```javascript
function handler(event) {
    var request = event.request;    
    var uri = request.uri;
    var ua = request.headers["user-agent"].value
    if ( ua.match(/Version\/13\./) || ua.match(/Version\/12\./) || ua.match(/Version\/11\./) || ua.match(/Version\/10\./)){
        return request
    }
    else if (uri.match(/\/images\//) && (uri.match(/\.(jpe?g|png)$/)) ) {
        
        request.uri += ".webp";
    }
    return request;
}
```

古いブラウザなのでUserAgentを使用しても良いので
`ua.match(/Version\/13\./)　|| ...`の部分でWebP未対応のSafariを分岐させる。


# 終わりに

ちょっとしたことはLambda@Edge使わなくても実装可能
GASのSpreadsheetでRangeオブジェクトに2次元配列をsetValuesするとき（備忘録）

# 困ったこと

ぼく「うーん、実行してみるまでspreadsheetに設定する値の数わからないんだよなー。」
ぼく「でもなんか、行ごとにインデックスをインクリメントして設定していくのもなー。」
ぼく「適当に2次元配列をRangeのsetValues()に渡したらよしなにしてくるだろー。」

```js
let arr = [
  ['a', 'b', 'c'],
  ['d', 'e', 'f'],
  ['g', 'h', 'i'],
];
sheet.getRange(1, 1).setValues(arr);
```

もちろん怒られました。

値を設定したい2次元配列に対して、Rangeオブジェクトの行列が一致していないといけないみたい。

# なんとかする

sheet.getRangeにシグネチャ違いがあって、列数と行数を設定できるようです。

```js
sheet.getRange(1, 1, arr.length, arr[0].length).setValues(arr);
```
エラー500って何？

オンラインの教材にて「PHP+MySQL(MariaDB)」を学習しているときに遭遇した正体不明の「error 500」。

このページは動作していません
localhostでは現在このリクエストを処理できません。
HTTP ERROR 500

という表示が出てしまいました。それを解決するために活躍するのが、

<?php
ini_set("display_errors", 1);
error_reporting(E_ALL);
?>

というエラーチェック用のコード。こちらをおそらくエラーを起こしているであろうページに入力（コピペ）してブラウザで実行するとエラーの原因となっている箇所を教えてくれます。
アップデートで使われなくなった記法であったり、記述ミスであったりするのですが、初見では「どこが悪さしているのか分からない」という状況になるため、すぐにでも上記のコードで原因箇所の特定をしたいですね！

ではまた！
SQLアンチパターン：リーダブルパスワードを防ぐ実装

# はじめに
SQLアンチパターンを勉強したときのメモ。
リーダブルパスワードを防ぐ実装方法です。

# 実装
① HTTPS通信をしていれば、フロントエンドではパスワードを平文のままバックエンドに送るのも可能
② 平文で送られてきたパスワードはそのまま処理せず、まずはソルトだけをDBから取り出して（もしくはユーザに固有のソルトを作り出して）パスワードをハッシュ化する
③ ハッシュ化したパスワードをDBで扱う。

![Untitled Diagram.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572098/c5c064d3-fd63-e8d1-56dd-0c6fd68808da.png)
CCNA基礎学習　個人メモ

#OSI TCP/IPの基本

##プロトコル・通信基礎

###プロトコルとは
『ルール、規定、規約、方法』のこと

通信プロトコルは通信についての共通ルール、方法のことで、その代表的なものがOSIモデル、TCP/IPモデルの２つがある。


###OSIモデル(OSI参照モデル)
Open Systems Interconnection
通信の機能を７つのレイヤーに分類した通信ルールのこと。

###アプセトネデブ
OSIモデルの７つのレイヤーの頭文字。語呂合わせ

アプリケーション層
プレゼンテーション層
セッション層
トランスポート層
ネットワーク層
データリンク層
物理層


###上位層
OSIモデル７つのレイヤーのうち７、６、５層

アプリケーション層：文字をデータにする　
プレゼンテーション層：データを送信しやすい形に変換
↓主なプロトコル
HTTP
SMTP
FTP
DNS

セッション層：送信元と送信先の確立
↓
SSL

の３つを上位層とまとめている。

データを送る前段階

###下位層
データを実際に送り届ける際のプロトコルと機器

###トランスポート層
・通信の信頼性を確保
データを壊さないようにがんばるところ;
TCP
UDP

・ポート番号
アプリケーション層で使用されるプロトコルを識別するための番号

PCがマンションでそれぞれのアプリケーションが各部屋に収まっているその部屋番号がポート番号


###ネットワーク層
エンドツーエンド:端から端まで
通信元から通信先の機器までの通信を担う層

IPアドレス
コンピュータの住所

ルーティング
適切な通信ルートの決定
PC１　→　ルーター１　→　ルーター２　→　PC2

ルーターによるルーティングで最適な通信経路を決定する。

###データリンク層
同一ネットワーク内の機器通信

MACアドレス
IPアドレスはネットワーク層で使う
MACアドレスはデータリンク層で使うアドレス（パークアクシスA棟　B棟みたいな感じ？）

フィルタリング
MACアドレスをもとにポート（インタフェース）を確定し指定の機器のみに送る



###物理層
電気信号
これまでのレイヤーからのデータを０と１に置き換えて電気信号、光信号にして送信する（受信の場合その反対）

ケーブルの種類と規格
LANケーブルなど接続するケーブルにもいろいろな規格がある


###OSIモデルのメリット
・世界共通の通信ルールだから通信機器はほぼこの規格で作られているので異なるメーカーでも通信が可能
・階層ごとに独立しているため他レイヤでの影響が少ない
・障害発生時に特定しやすい

###カプセル化
データを送信可能な形に変換する事
物をラッピングして〜段ボールに入れて〜伝票貼って〜って感じ

###カプセル化の動作
上位層から元データに必要な情報を加えて（ヘッダ）いく、順次直下の下位層でまたヘッダを加えてそのまた下位層へ
データリンク層ではヘッダとトレーラーもつけて物理層へ
物理層では７〜２までに加えたヘッダを含めたデータを01にしていく

マトリョーシカ


###非カプセル化
送られてきたヘッダ付きのデータから元データを取り出す作業
開梱しているイメージ

非カプセル化の動作
01のデータを物理そうで読み込む。→直上位層へ送ってトレーラーとヘッダを外して上位層へ...を繰り返す

###ペイロード
上位層からのデータのこと（上位層のヘッダ＋元データ）

PDU
ヘッダ＋上位層からのデータ

メッセージ
７、６、５層のPDUの総称

セグメント、データグラム
４層でのPDUの名称

パケット
３層でのPDUの名称

フレーム
２層でのPDUの名称

ビット
01になったデータの名称


###TCP/IP
ISOでは７層だったものを４層に分類した通信の基本ルール

4層(5層)
アプリケーション層
トランスポート層
インターネット層
ネットワークインターフェイス層（物理）

OSIとの違い(成り立ち)
OSIは通信のモデルを作ろうとして作ったが浸透しなかった
TCP/IPはインターネットを前提にした通信モデル

###キャスト

<dl>
<dt>マニキャスト</dt>
<dd>１対１の通信</dd>

<dt>ブロードキャスト</dt>
<dd>同じネットワーク内全体に送る
ブロードキャストアドレスを指定すると同一のネットワークとルーターまで通信するがルーターで通信が堰き止められる。</dd>


<dt>マルチキャスト</dt>
<dd>１対指定のグループ宛に送る
マルチキャストアドレスを指定するとマルチキャストグループ全体に送信できる。</dd>
</dl>
VMware vSAN ストレージポリシーについての紹介

この記事では VMware vSAN のストレージポリシーについてご紹介していきます。

#vSANのストレージポリシーとは

vSANはポリシーベースのストレージ管理(SPBM)機能により、仮想マシンが使用するストレージのキャパシティ、パフォーマンス、可用性に関する要件を定義できます。

vSANを使用せず、外部ストレージを使用する場合は、ストレージ側であらかじめLUNの切り出しやRAIDレベルを指定してデータストアを作成するため、仮想マシン単位で可用性に関する設定ができないなどの制限があります。

vSANはvCenter Sreverから仮想マシン個々に対して、柔軟に複数のポリシーを設定することができます。
仮想マシン単位で様々な要件にもとづいた柔軟な運用が可能です。

#ストレージポリシー一覧
vSANのストレージポリシーは具体的にどのような種類、機能があるのかを、ご紹介していきます。

**■許容される障害数**
仮想マシンの可用性を高める重要なポリシーです。
Failure to Torelateの略称で「FTT」と表記されることも多いです。

ミラーリング(RAID1)または、イレージャーコーディング(RAID5,6)の方式で仮想マシンのデータをvSANクラスタ内の複数のESXiホストに格納することで耐障害性を高めることができます。
仮想マシンのデータが格納されているESXiホスト、ディスクで指定した許容する障害数に相当する障害が発生しても、継続して仮想マシンを稼働させることができます。

仮想マシンを作成する際、ストレージポリシーを選択しないと、このポリシーがデフォルトのストレージポリシーとして割り当てられます。許容できる障害数のデフォルト値は1です。上限値は3です。

なお、下記のように許容する障害数によって、ESXiホスト最小台数、対象の仮想マシン一台あたりの必要容量の要件が異なります。
 
イレージャーコーディングはミラーリングと比較してキャパシティを大幅に節約できますが、IOPSやネットワーク帯域幅のオーバーヘッドが増大します。なお、イレージャーコーディングは、オールフラッシュ構成でのみサポートされています。

**■オブジェクトあたりのディスクストライプの数**
仮想マシンのデータを分割して複数のキャパシティディスクに格納します(ストライピング)。ストライプ数を増やすと、読み取り処理の観点でパフォーマンスを向上させることができます。
ストライプ数のデフォルト値は1です。上限値は12です。
なお、許容される障害数の値が1の場合は多重化されたデータ毎にストライピングされます。

**■オブジェクト容量の予約**
仮想マシンを作成する際にシンプロビジョニング、シックプロビジョニング方式を指定する必要がありますが、このポリシーでは初期化時に予約される割合を指定できます。予約されたストレージ容量は、シックプロビジョニングされ、残りのストレージ容量はシンプロビジョニングされます。

**■フラッシュの読み取りキャッシュの予約**
特定の仮想マシンに対して、キャッシュデバイスの一部を予約して割り当てることができます。
なお、ハイブリッド構成にのみ使用できます。
読み取りキャッシュを予約することでキャッシュ領域を占有することができます。
デフォルト値は0%です。最大値は100%です。

**■強制プロビジョニング**
vSANクラスタ内に十分なリソースがなくても、仮想マシンを作成できます。
例えば、許容される障害数のポリシーの値を2として仮想マシンを作成する場合、5台以上のESXiホストが必要になります。強制プロビジョニングを使用した場合、vSANクラスタ内のESXiホストが3台でも、許容される障害数が0の状態で作成されます。必要要件であるESXiホスト5台以上のリソースを確保した際に、許容される障害数＝２のポリシー対して、仮想マシンが準拠した状態になります。

**■オブジェクトのIOPS制限**
仮想マシンが使用できるIOPSを制限するための機能です。
ワークロードが高い仮想マシンが、IOPSを消費しすぎることで、他の仮想マシンのワークロードに影響を及ぼすおそれがある場合に有効です。

**■オブジェクトチェックサムの無効化**
チェックサムは仮想マシンのデータが破損していないかや、整合性がとれていないか等を、定期的にチェックする機能です。
データの破損を検知した場合は、他のミラーリングされたデータやパリティストライプから自動的に再構築されます。 


以上、vSANのストレージポリシー一覧についてご紹介しました。
次回は、vSANのストレージポリシーの中で最も使用する許容される障害数の設定方法、動作についてご紹介します。
データベースdumpをinsert時に、日付Columnが増えた場合の対処

MySQLのデータ移行時の話です。
古いテーブルのdumpを取得して、新しいデータベースでクエリを流せば、いい感じに移行できるわけです。

## 問題点
しかし、一つだけ問題がありました。
古いテーブル設計がイマイチで、新しいテーブルでは日付Columnを増やしていました。
例えば以下のような場合です。

#### 古いテーブル
```sql
select * from old;
-----------------------------------------
| id   | value   | stamp                |
-----------------------------------------
| 1    | tokyo   | 2022/01/28 21:34:56  |
-----------------------------------------
```

#### 古いdumpファイル
```sql:dump.sql
insert into old values (1, "tokyo", "2022/01/28 21:34:56")
```

#### 新しいテーブル
```sql
select * from new;
----------------------------------------------------------------
| id   | value   | created_at           | created_at           |
----------------------------------------------------------------
| 1    | tokyo   | 2022/01/28 21:34:56  | 2022/01/28 21:34:56  |
----------------------------------------------------------------
```

#### ほしいdumpファイル
```sql:new_dump.sql
insert into old values (1, "tokyo", "2022/01/28 21:34:56", "2022/01/28 21:34:56")
```

同じ値のColumnが一つ増えているので、dumpしたSQLをそのまま使うことができません。
サンプルではデータが一行だけですが、実際はデータが何千・何万とあるわけです。
とはいっても、dumpファイルってただのテキストファイルなので、うまく置換すればいけそうですが・・・

## 置換方法
今回は、テキストエディタでの置換方法になります。
代表的なvscodeです。
違うのエディタであっても、同じことができると思うので、一度調べてみてください。

１．まず、⌥⌘Fで置換ボックスを開きます。
そして、正規表現検索をONにしましょう。
![スクリーンショット 2022-01-28 17.14.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272102/9fba6484-cab9-d52d-d1ce-48af6e776225.png)

２．検索欄と置換欄にはそれぞれ
検索：`('\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}')`
置換：`$1,$1`

３．後はすべて置換するだけです。

## 説明
正規表現で検索できることまでは簡単ですよね。
ここで鍵となるのは、正規表現を`()`で囲っているところです。
`()`で囲むと、囲まれたところのマッチしたデータを、一時的に保存してくれるんです。
`()`を複数つけると、つけた分保存してくれます。
そして、それらのデータにアクセスできる変数が、`$1`、`$2`・・・になるわけです。

上記の例では、`$1,$1`に置換しているので、同じ日付のデータを`,`区切りでつなげることで、目的を達成しています。
この方法を活用すれば、もっと複雑な置換作業も可能でしょう。
V字モデル✌️

　開発手法について調べていたらV字モデルについて出てきたので調べました。上流工程とか下流工程とかのやつですね。それぞれがどんなことをするのかについてまとめました。

# 目次
- V字モデル概要
- 要求分析
- 要件定義
- 基本設計
- 詳細設計
- コードレビュー
- 単体テスト
- 結合テスト
- システムテスト
- 受け入れテスト

## V字モデル概要
　V字モデルは、システム開発プロジェクトの一連の流れにおける開発工程とテスト工程の対応関係を表した１つのモデル。
　　(左):開発工程を上流工程から順に右下がりに並べる
　　(右):左の開発工程に対応したテスト工程を右上がりに並べる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091770/cc7d0443-bb2a-0c70-6f0b-4cadff01c5b9.png)

>
https://webrage.jp/techblog/v_shaped_mode/

## 要求分析
　クライアントがシステムに求める仕様を明確にしていく工程。「こういうシステムを作って欲しい」というオーダーを要求定義書として書き起こす。要求定義書には、システムにおける細かな仕様や機能、費用面や開発スケジュールなどが含まれる。

## 要件定義
　システム開発を行う上で実施すべき業務内容を想定して要件定義書として文書化する工程。要件定義は以下のステップで行われる。
1. 解決したい課題と目標の明確化
2. システムの全体的な構成の明確化
3. 機能要件の定義 (システムの機能)
4. 非機能要件の定義 (可用性や運用性、セキュリティなど)
5. 予算やスケジュール、プロジェクトメンバー等の定義
6. 要件定義書の作成

要件定義書の詳しい内容は下記のサイトが参考になると思います

https://pm-rasinban.com/rd-write

## 基本設計
　基本設計は開発すべきシステムを機能単位で分割して設計する工程。要件定義ではどんな機能や画面が必要か(What)を決めたが、基本設計ではどのように機能や画面を実装するか(How)を決める。基本設計は機能の説明書みたいなイメージ。

基本設計書の詳しい内容は下記のサイト参照

https://pm-rasinban.com/bd-write

## 詳細設計
　基本設計で大まかに決めた内容をプログラマー向けに詳細化する工程。「この条件の時APIを叩いてDBにデータを追加する」のような感じで詳細にしていく。

## コードレビュー
　ソースコードを記述者以外がチェックしてレビューを行う工程。コードレビューのポイントは
1. 自社のコードルールに則っているか
2. コメントがわかりやすく書かれているか
3. 仕様変更の際に修正箇所が多くならないか
4. 例外処理は入っているか
といったところを意識すると良き。

## 単体テスト
　プログラムを構成する比較的小さな単位（ユニット）が個々の機能を正しく果たしているかどうかを検証するテスト。関数やメソッドのテスト。フロントエンドではJestやMochaなどのツールが使用される。

## 結合テスト
　複数の要素が問題なく連動するかを確かめるためのテスト。単体テストで品質担保したモジュールを結合して動作するかチェックする。フロントエンドではJestやTesting Libraryなどのツールが使用される。

## システムテスト
　システムの要件を満たしているかを確認するテスト。非機能要件や外部システムとの連携が正しく行われるかもチェックする。

# まとめ
　要件定義って何するんだろう？とか基本設計と詳細設計の違いって何？といった部分について理解でき、世に出ているアプリやサービスはいくつもの工程を経てリリースされているのだなと感心しました。

# 参考
https://webrage.jp/techblog/v_shaped_mode/

https://www.gpol.co.jp/blog/135

https://smbiz.asahi.com/article/14495721

https://www.pasonatech.co.jp/workstyle/column/detail.html?p=2833

https://it-biz.online/it-skills/design-documents/

https://and-engineer.com/articles/YDCJfhAAACEAIa3y

https://qiita.com/gevanni/items/ff9a27936a1a6df28b9a

https://postd.cc/frontend-testing-is-for-everyone/
Accessクエリ 関数【日付操作編】②

備忘録として投稿します。
全13項目【日付操作編】④まであります。
今回は【日付操作編】②です。
#ACCESSの日付操作でよく使用する関数　その２
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517880/e0c7abd4-c58a-aac7-4d36-3dd0d0cc4584.png)
#まとめ
今回は
④〇日前のデータを求めたい。
⑤勤続年数を求めたい
⑥勤続年数を「〇年〇ヶ月」と表示したい。
⑦日付から「月」のデータを抽出したい。
以上４つの項目についてまとめてみました。
残り2つの記事も参考にしてみてください。
auroraでエンドポイント関連で３つのことを実験


###実験①
#####データベースに設定したものとは別VPCでかつデータベースが配置されていないAZのEC2でauroraにアクセス可能か

データベース情報：
VPC：VPC1
データベースのインスタンスがあるAZ：AZ-1a、AZ-1c
パブリックアクセス：あり

EC2情報：
VPC：VPC2
EC2を配置したサブネット：AZ-1dのパブリックサブネット
クライアント：mysql-community-client.x86_64 　8.0.27-1.el7

```txt:成功
$ mysql -h (データベースのエンドポイント) -P 3306 -u admin -p --enable-local-infile
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 40
Server version: 5.7.12 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
```
###実験②

#####インスタンスや読み取り専用のエンドポイントを利用してmysqlにログイン可能か

```txt:成功
$ mysql -h (読み取りエンドポイント(roがついているやつ)) -P 3306 -u admin -p --enable-local-infile
$ mysql -h (データベースのエンドポイント) -P 3306 -u admin -p --enable-local-infile
$ mysql -h (インスタンスのエンドポイント) -P 3306 -u admin -p --enable-local-infile
```

なぜ接続できるかというとエンドポイントがこういう風になっているからです

![Untitled-21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/1fdb3b0b-9423-930f-ffae-a19fc4f9f6ec.png)

https://dev.classmethod.jp/articles/amazon-aurora-custom-endpoints/

###実験③
####インスタンスや読み取り専用のエンドポイントでログインした場合書き込み操作はできるか
#####(i).リードレプリカがクラスターにない場合

```txt:読み取りエンドポイントでログイン（インスタンスエンドポイントでも同じ挙動）
$ mysql -h （読み取りエンドポイント(roがついているやつ)） -P 3306 -u admin -p --enable-local-infile

mysql> use sampledb
Reading table information for completion of table and colu
You can turn off this feature to get a quicker startup wit

Database changed
mysql> create table user (id int, name varchar(10), addres

Query OK, 0 rows affected (0.03 sec)

mysql>
mysql> insert into user values (1, 'Yamada', 'Tokyo');
Query OK, 1 row affected (0.00 sec)

mysql>
mysql> select * from user;
+------+--------+---------+
| id   | name   | address |
+------+--------+---------+
|    1 | Yamada | Tokyo   |
+------+--------+---------+
1 row in set (0.00 sec)

```

これは読み取りエンドポイントでログインしたときにリードレプリカがなかったら書き込み可能なDBにログインする仕様なのかもしれません

実際にDBの変数'innodb_read_only'を確認したところOFFになってる

```

mysql> show variables like 'innodb_read_only';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_read_only | OFF   |
+------------------+-------+
1 row in set (0.00 sec)

```
https://dev.classmethod.jp/articles/amazon-aurora-reader-endpoint/

#####(ii).リードレプリカがある場合
読み取り用エンドポイントでもリードレプリカのエンドポイントを指定してログインしても以下の挙動でした

```
mysql> CREATE DATABASE sampledb_by_readonly;
ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement

mysql> show variables like 'innodb_read_only';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_read_only | ON    |
+------------------+-------+
1 row in set (0.00 sec)

```
Chrome拡張機能でスクレイピング結果をダウンロードする

#Chrome拡張機能のプロジェクトを作成する
## ファイルを設置
任意のディレクトリに以下のファイルを設置する。
manifest.json
script.js

## ディレクトリをChromeから読み込む
![chrome___extensions_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28556/a19924f5-8e45-32a7-be34-5d787b287871.png)

１．拡張機能管理ページを開く。　(URLは→　chrome://extensions/)
２．「デベロッパーモード」をONにする。
３．「パッケージ化されていない拡張機能を読み込む」ボタンを押してディレクトリを選択する。

参考：[Chrome拡張機能の作り方。誰でもかんたんに開発できる！](https://original-game.com/how-to-make-chrome-extensions/)

# manifest.json
```manifest.json
{
  "name": "Scrape Sample",
  "action": {},
  "manifest_version": 3,
  "version": "0.1",
  "description": "Scrape the web page",
  "permissions": [
    "activeTab",
    "scripting"
  ],
  "content_scripts": [
    {
      "run_at":"document_end",
      "matches": ["<all_urls>"],
      "js": ["jquery-3.6.0.min.js"
      ,"script.js"
      ]
    }
  ]
}

```
概要：
activeTab: 現在のタブで実行する。
document_end: ページ読み込み後に実行する。
all_urls: 全てのURLが対象。
js: マイ拡張機能ディレクトリのjquery-3.6.0.min.js、script.jsを実行する。
jQueryを利用する場合はダウンロードして設置する。
[jQuery Download](https://jquery.com/download/)

# スクリプト script.js
```script.js
$(function(){
    // タイトルをファイルタイトルとして取得する
    var title = $('title').text();
    var str = "";
    // (全体取得だと順番が崩れたためeachにする)
    $('article p').each(function(idx,ele){
        // 空文字列の場合は飛ばす
        if ( $(this).text() == "" ) return true;
        if ( idx > 0 ) str += "\n";
        curtext = $(this).html();
        // brタグを改行に変更する
        curtext = curtext.replace(/<br>/g, "\n");
        // 文字列に追加する
        str += curtext;
    });

    // 取得した文字列でテキストファイルを作成
    const blob = new Blob([str],{type:"text/plain"});
    const link = document.createElement('a');
    link.href = URL.createObjectURL(blob);
    link.download = title + '.txt';
    // aタグをクリックさせて自動ダウンロードする
    link.click();
    
});
```
拡張機能を読み込み（変更した場合はリロード）後に、対象ページを読み込むと、機能が実行される。

参考：[JavaScript：ブラウザからローカルのテキストファイルの入出力](https://cyzennt.co.jp/blog/2021/02/04/javascript%EF%BC%9A%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%8B%E3%82%89%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%AE%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE/)
javaScriptで濁音・半濁音を清音にしたい。

## はじめに
業務で濁音・半濁音の文字を清音に変換する処理が必要となりました。
normalize()メソッドを使用すると簡単に清音を取得できることが分かりました。

```javaScript:例1
var str = 'ペンギン';
    console.log(str + ' = ' + str.length + '文字');
    // 正規化する
    str = str.normalize('NFD');
    console.log(str + ' = ' + str.length + '文字');

    // expected output: ペンギン = 4文字
    //                  ペンギン = 6文字

```

６文字？？

```javaScript:
// ペンギン = 6文字 の内訳。
for (var i = 0; i < str.length; i++) {
   console.log(str[i]);
}

// expected output: ヘ
//                   ゚
//                  ン
//                  キ
//                   ゙
//                  ン

```

簡単に濁点・半濁点を外した文字を取得することができました。

## 簡単な説明
normalize() メソッドは、文字列の Unicode 正規化形式を返します。
今回は、NFDを引数に渡し、「ぺ」から「へ」などを抽出しています。

※NFD・・・正準等価な文字については、結合文字に分解した形で正規化する。

詳しく知りたい方は参照にある記事を読み理解を深めてみてください。

## 注意
String.prototype.normalize()はES6で加わったメソッドなので、IE11では使用できません。

## 参照
 - https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
 - https://qiita.com/jkr_2255/items/e0c039c438d3ebfd1a6a
WindowsとLinuxでファイル共有してみた。

#はじめに
こんにちは、山田です。
今回は、CIFSでWindowsとLinuxでファイル共有するについて記載していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/e2b71774-624e-bd4b-af73-50ff1b9be6de.png)

#Windows共有フォルダの作成
①：今回はCドライブに、`cifsフォルダ`を作成してそれを共有フォルダにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/25922515-43ea-1e1d-8720-3629ce05f779.png)
②：cifsフォルダ作成後、プロパティを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/76f7115e-cd32-7017-ce6c-8555d5d0a8a3.png)
③：共有をクリックして、共有するユーザーを選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/b597495b-3b63-9fb3-d4b5-a820ee49d4ea.png)
④：テスト用にcifsフォルダ直下に`test.txt`を作成しておく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/24f1b85d-ca16-6962-78ea-897689d04537.png)

#LinuxでCIFSマウント
①：`cifs-util`をインストールする。

```
yum -y install cifs-utils
```
②：マウントポイントを作成する。
今回は`/cifs`をマウントポイントとする。

```
mkdir /cifs
```

③：Windows共有フォルダをマウントする。

```
mount.cifs  -o user=test-user,password=P@ssw0rd //10.1.0.110/cifs /cifs
```
④：`test.txt`をコピーする。

```
cd /cifs
cp test.txt /tmp  #test.txtを/tmpにコピーする。
cd /tmp           #コピーできているかlsコマンドを打ち確認する。
ls 　　         　#以下のようにtest.txtがコピーされていればOK。
test.txt
```
Excelを使わずに表をプリンタ出力してみる

職場の看護師からの依頼。毎日利用者の血圧や体温などのバイタル測定をして熱型表用紙に記入しているのを省力化したいとのことでした。そして、ゆくゆくは電子カルテのような機能も希望しているようです。熱型表とはこういうのです（右側のグラフのような様式）。
https://www-ui.is.s.u-tokyo.ac.jp/~takeo/research/karte/karte-j.htm
弊社のような医療型でもない中小の事業所は電子カルテなど望むべくもないので自作します。

病院受診の際に熱型表のプリントアウトを持参したいとのことなので、要件としては一番のネックになりそうです。バイタル値のプロットはプロデルからExcel連携する方向で実装しようかとも思ったのですが、ちょっと試行錯誤が必要となりそうなのでこれは無しで行くことにしました。

A4サイズの用紙だと300dpiの場合は約2,480×3,508ピクセルになるそうなので、このサイズのキャンバスに描画してこれを直接印刷することにします。沢山の罫線があるので描画をなるべくすっきり記述出来て、後々の微調整の要望にも迅速に対応できるようにしたい。また、今後別案件でも罫線一杯の紙への対応を求められそうですので、ライブラリとして使い回しがきくようにしたい。そんなことを考えながら、ひとまず罫線の描画を作ってみました。

``` 罫線描画.rdr
表用紙というキャンバスを作る
その大きさは、{3508,2480}
表用紙へ四角形を描く
その位置と大きさは、{0,0,3508,2480}
その背景色を、白に変える
その線色を白に変える

ーー10x10の方眼を描画してみます
10回繰り返す
	表設定へ200という幅で行を追加する
	表設定へ200という幅で列を追加する
繰り返し終わり
11回値にカウントしながら繰り返す
	設定辞書は、{線種=「標準」,色=「黒」,太さ=1}
	表設定に、{値,1}から{値,11}まで設定辞書という罫線を設定する	ーー縦の罫線
	表設定に、{1,値}から{11,値}まで設定辞書という罫線を設定する	ーー横の罫線
繰り返し終わり
表用紙へ表設定で描画する

表用紙を更新する
表用紙を「result.bmp」へ保存する
「result.bmp」を開く


表設定とは
	単一種類
	-列数
	-行数
	+罫線定義:配列
	+横座標配列:配列
	+縦座標配列:配列

	はじめの手順
		横座標配列(1)=0
		縦座標配列(1)=0
		罫線定義は、{}
	終わり

	自分へ【設定値:整数】という幅で行を追加する手順
		縦座標配列に、(縦座標配列の末尾+設定値)を加える
	終わり

	自分へ【設定値:整数】という幅で列を追加する手順
		横座標配列に、(横座標配列の末尾+設定値)を加える
	終わり

	自分に【始点:配列】から【終点:配列】まで【設定値:辞書】という罫線を、設定する手順
		罫線定義(罫線定義の個数+1)という罫線情報を作る
		罫線定義の末尾の始点は、始点
		罫線定義の末尾の終点は、終点
		罫線定義の末尾の線種は、設定値(「線種」)
		罫線定義の末尾の色は、設定値(「色」)
		罫線定義の末尾の太さは、設定値(「太さ」)
	終わり
	
	【用紙:キャンバス】へ自分で描画する手順
		罫線定義を要素にそれぞれ繰り返す
			始点配列は、{横座標配列(要素の始点(1)),縦座標配列(要素の始点(2))}
			終点配列は、{横座標配列(要素の終点(1)),縦座標配列(要素の終点(2))}
			用紙に線を描く
				その始点は、始点配列
				その終点は、終点配列
				その線色を要素の色に変える
				その線種を要素の線種に変える
				その太さを要素の太さに変える
		繰り返し終わり
	終わり
	
終わり

罫線情報とは
	+始点:配列
	+終点:配列
	+線種:文字列
	+色:文字列
	+太さ:整数
終わり
```

キャンバスに描画したものをbmp形式で保存して表示させていますが、本番では「表用紙を印刷する」でプリンタ出力します。ちなみにこのままでプリンタ出力すると2倍くらいに拡大されて印刷されてしまいますので、プリンタ側の設定を詰めるか、キャンバスのピクセル数を変更する必要がありそうです(追記参照)。

(追記)
今のところキャンバスはどうも96dpiくらいでの印刷にしか対応していない感じです(2022/03/03現在)。当面は保存したbmp画像を何らかの外部アプリを使用して印刷するしかないようです。
SalesforceのレコードタイプによりTodoページレイアウトを分ける方法

SalesforceのレコードタイプによりTodoページレイアウトを分ける方法を解説します。


今回はリードオブジェクトにAとBのレコードタイプを作成しました。

リードのレコードタイプがAの時にTodoレイアウトはaを。
リードのレコードタイプがBの時にTodoレイアウトはbを表示させる方法をお教えします。


まずはTodoオブジェクトにページレイアウトa,b
およびレコードタイプa,bを作成します

![レコードタイプ１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/6e94cb71-acde-a82a-de46-774fa2e47398.png)


次にリードにオブジェクトにアクションを作成します
![レコードタイプ２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/d80acfe0-95e2-2279-10f3-2ce32e5609bb.png)


アクションその１はaのレコードタイプを選択します
![レコードタイプ３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/478ce458-2026-3cc6-e828-a7e2b1b807a5.png)

次にもう一度アクションを作成します。アクションその２はレコードタイプｂを選択します
![レコードタイプ４.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/d6358d54-5eb4-2d77-0582-53988b84809b.png)


リードレコードタイプAに設定されているページレイアウトAを編集。Todoレコードタイプaが作成できるアクションを配置します。
![レコードタイプ５.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/9b1d3a1b-91b1-8731-b8d6-0026e75f13e0.png)

リードレコードタイプBに設定されているページレイアウトBを編集。Todoレコードタイプbが作成できるアクションを配置します。

![reko-dotaipu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/e7ebc842-d517-16c7-4f1e-f0c0bd8742a2.png)

これで完成です。実際にレコードタイプAのリードをみると、画像のようにaレコードタイプのTodoが作成できるアクションがございますね。
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/fe18f7c6-509a-e25d-70cc-f9296e94ef11.png)

実際にレコードタイプBのリードをみると、画像のようにbレコードタイプのTodoが作成できるアクションがございますね。
![b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/912d5b8c-9647-ef5e-2ddc-5e5cb0ff84d5.png)
【React】useStateに関数を渡す

react初心者です🙏

reactよくわからないのですが、`useState`と`setInterval`を使うテクニックで`useState`の引数に関数を渡せるということを知りました

## setIntervalでの実装例

[公式](https://ja.reactjs.org/docs/hooks-reference.html#usestate)に書いておけよって思うのですが、僕が見つけられないだけ？？？

```js
const [now, setNow] = useState(Math.floor(new Date().getTime() / 1000))

useEffect(() => {
  const timeId = setInterval(() => {
    // setNow(now+1) だと動かない、値の参照が違うから
    setNow((v) => v + 1)
  }, 1000)

  return () => clearInterval(timeId)
}, [])
```

## react-domのソースを読んでみる

`useState`は最終的に`react-dom`側に実装されていました. 
`setNow`は以下の`dispatchAction()`のラップになっていて、`fiber`と`queue`の引数は`.bind()`で予約されていて、僕らが引数で渡してる値は、`action`になります

```js
function dispatchAction(fiber, queue, action) {
 // ...色々
 // currentStateが変更前の値
 // eagerStateが変更後の値
 var eagerState = lastRenderedReducer(currentState, action)
 // ...色々
}
```

`lastRenderedReducer()`が何かというと`basicStateReducer()`になります. 
`useState()`の引数で、関数が渡されてたら関数を実行してて、関数じゃない場合はそのまま値を返却しています

```js
function basicStateReducer(state, action) {
  return typeof action === 'function' ? action(state) : action;
}
```

公式ページに書いておけ？？？とは思いました。
流石に気づいてるはずなので、書かない意図があるんだと思う。使い方として推奨してないとか

知らんけど😵
TypeScript + clasp で Google Apps Script の開発環境を整える

静的型付け言語に慣れすぎてしまっているため、Google Apps Script（以下、gas）をJavaScriptで書くのがとても辛い。
Google謹製のgasプロジェクト管理ツール [clasp](https://developers.google.com/apps-script/guides/clasp) を使えばTypescriptでも書くことができる、とのことだったので試してみる。

参考） 
- [Command Line Interface using clasp](https://developers.google.com/apps-script/guides/clasp)
- [clasp/README.md at master · google/clasp](https://github.com/google/clasp/blob/master/README.md)
- [clasp/typescript.md at master · google/clasp](https://github.com/google/clasp/blob/master/docs/typescript.md)


## インストール

以下のコマンドで`clasp`をinstallします:

```sh
npm install -g @google/clasp
```

ユーザ設定からGoogle Apps Script API を有効にします。: https://script.google.com/home/usersettings

![Enable Apps Script API](https://user-images.githubusercontent.com/744973/54870967-a9135780-4d6a-11e9-991c-9f57a508bdf0.gif)

:::note alert
この設定が漏れていると以降のclaspの認証がうまくいきません。
:::

## ログイン

`clasp`からgasにログインします。

```sh
clasp login
```

上記のコマンドを実行するとGoogleアカウントへの認証が求められるので、案内に従いログインします。
以後、全ての`clasp`の操作はここでログインしたアカウントのgasに対して行われます。

アカウントを切り替えたい場合は一度ログアウトと行う必要があります。

```sh
clasp logout
```

現在の接続先のアカウントの状態を確認したい場合は以下のコマンドから行えます。

```sh
clasp login --status
```

## プロジェクト作成

プロジェクトをフォルダに移動します。

```sh
cd /path/to/project/dir
```

TypeScriptの型定義モジュールをinstallします。

```sh
npm i -S @types/google-apps-script
```

`mode_modules`ディレクトリと`package-lock.json`が作成さることを確認します。

```shell_session
$ gas-sample tree -L 1
.
├── node_modules
└── package-lock.json

1 directory, 1 file
```
 

gasプロジェクトを作成します。

```sh
clasp create --type standalone
```

作成されたプロジェクトの構成を確認します。

```shell_session
$ gas-sample tree -a -L 1
.
├── .clasp.json
├── appsscript.json
├── node_modules
└── package-lock.json

1 directory, 3 files
```

`clasp`でログインしている先のgasにアクセスし、プロジェクトが作成されていることを確認します。

![スクリーンショット 2022-01-28 15.36.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1265758/a12500a2-eaa5-b985-da81-238b427f10be.png)


## ファイルの作成およびアップロード

プロジェクトにアップロードするファイルを作成します。

```shell
touch hello.ts
```

ファイルの中身を記載します。今回はベタなやつで。

```ts:hello.ts
function hello() {
  console.log("Hello World.");
}
```

`clasp push`でアップロードされます。

```shell_session
$ clasp push
└─ /workspaces/gas-sample/hello.ts
Pushed 1 files.
```

無事アップロードされました。

![スクリーンショット 2022-01-28 17.02.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1265758/4332209e-7096-fa93-e570-4024c9a9d071.png)

問題なく実行もできます。

![スクリーンショット 2022-01-28 17.04.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1265758/eba5a3e0-3c2e-aab9-6679-3338d7cdf214.png)

次回からは実際にGoogle Calender APIを絡めた実装に着手します。
Jenkinsでビルドした成果物をArtifactoryにPushする

### JenkinsにArtifactoryサーバーを設定
Jenkins上で「Jenkinsの管理」⇒「システム設定」からArtifactoryサーバーを設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/5e78fab2-112f-7014-a584-c65251063a9a.png)

ここで設定されたServer IDをJenkinsfileで使用します。

### Jenkinsfileを作成
各種ビルドをした次のstageでArtifactoryへのPushを記述します。

```
stage('publish') {
      steps {
        rtUpload (
            serverId: 'artifactory',
            spec: '''{
                "files": [
                    {
                        "pattern": "target/***.jar",
                        "target": "Your repository"
                    }
                ]
            }'''
        )
        cleanWs()
      }
    }
  }
```

Server IDは先程Jenkinsに登録したIDを指定します。
patternにはビルドによって生成されたPushすべきモジュールのパスを指定します。
targetはArtifactoryのリポジトリのパスを指定します。ビルド時に受け取った変数などを指定することでPush先を切り替えることも可能です。
コマンド実行時に"Ignoring 〜 because its extensions are not built."が出力

## 環境
- Ruby 2.7.4
- Rails 6.1.4.4

## エラー内容
コマンドを叩く度に以下のようなメッセージが表示されるようになった。

```
・・・
Ignoring nokogiri-1.12.4 because its extensions are not built. Try: gem pristine nokogiri --version 1.12.4
Ignoring racc-1.5.2 because its extensions are not built. Try: gem pristine racc --version 1.5.2
Ignoring racc-1.5.2 because its extensions are not built. Try: gem pristine racc --version 1.5.2
・・・
```

## 解決方法
コマンドプロンプトで以下のコマンドを叩く。

```
gem pristine --all
```

処理に少し時間がかかるが解消された。

## 参考
https://stackoverflow.com/questions/39991410/bundle-error-on-macos-10-12-sierra
Windowsをbridgeまたはrouterに


#### Windows10をブリッジまたはルータに
bridge: ２つのネットワークデバイスを選択して「ブリッジ接続」
router:サービス「Routing and Remote Access」
https://m-suta.com/bibouroku-windows-bridge-router/

#### WinsowsServerをルータに設定
レジストリ変更、または、サービス「Routing and Remote Access」
https://turningp.jp/server-client/windows/windows-server-router

#### 複数の有線LANを持つWindowsをルーターに設定
サービス「Routing and Remote Access」
複雑なルート設定「route add」
https://blog.putise.com/windows%E3%82%92%E3%83%AB%E3%83%BC%E3%82%BF%E3%83%BC%E5%8C%96%E3%81%95%E3%81%9B%E3%82%8B%E6%96%B9%E6%B3%95%E3%80%82windows%E3%83%AB%E3%83%BC%E3%82%BF%E6%A7%8B%E7%AF%89/#Windows

#### 有線LANを持つWindowsを有線LANのアクセスポイントに設定
「ネットワークのほかのユーザーに、このコンピュータのインターネット接続をとおしての接続を許可する」
https://pentan.info/server/windows/router.html

#### 有線LANを持つWindowsをWLANのアクセスポイントに設定
「モバイルホットスポット」
https://yourclip.life/post/20200414kowaza/

#### 有線LANを持つWindowsをWLANのアクセスポイントに設定
「netshコマンド」
https://www.teradas.net/archives/17764/

https://faq.nec-lavie.jp/qasearch/1007/app/servlet/relatedqa?QID=018483
Backlogで議事録を書いてみた

# 軽く自己紹介
+ 新人エンジニア
+ 業務でBacklogを使い初めて議事録を書く
+ メインはモバイルアプリケーション開発
+ 今回が初投稿
+ 言語化能力向上、アウトプットするために投稿する

## なぜ、議事録を書くことになったのか
+ プロジェクトのスケジュールがタイトなため、雑用や補助周りの仕事をする人が必要だった

シンプルにこれだけです。会社入って分かったんですが、打ち合わせとか多いと議事録書く時間が取れないことがあるので打ち合わせの予定がない私が担当することになりました。(初めて投稿するので拙い記事ですが何卒ご容赦ください....)

## 議事録作成する環境&記述形式
+ Backlog
+ Backlog形式

## どんな内容を議事録にするのか
基本的には会議で決まったこと、今後の課題、プロジェクトの予定などを議事録として書いています。
また、上記以外にもエクセルなどの資料をwikiにするなどもやったりします。
この辺りは、会社によってやり方違うと思うので作成を依頼した人からヒアリングして作成した方がいいかと思います。

## 会議の内容をどう保存するか
基本的には会議を聞きながら、テキストに保存するのですがどうしてもタイピングが追いつかない場合があるので以下の方法を取りました。

+ レコーダーで会議の音声を録音
+ ホワイトボードに書いてある内容を画像として保存
+ 会議で使用された資料を利用する
+ 内容が不明な場合は自ら質問をする

あくまで一例ですので、自分がやりやすい方法をとっていただければと思います。

## Backlogの記述方法
Backlogですが、記述方法はおそらくデフォルトだとBacklog形式になっているかと思います。
というのも、テーブルを使い表を作成した際にセルの結合をMarkdown形式で記述を行おうとしたのですが、設定がBacklog形式なのでできませんでした。
Backlog形式だとセルの結合ができないっぽいです。....
Backlog形式とMarkdown形式は別物という認識になります。(ここはまりポイントだと思います。)
Markdown形式で議事録などを作成したい場合は、プロジェクトの設定からMarkdown形式に変える必要があります。
もし管理者権限がない場合は管理者権限がある人に依頼する必要があります。

## 最後に
ざっと私が経験したことを書いてみました。これから最低でも1ヶ月に1本は記事を書いていきたいと思います。
[py2rb] callable

# はじめに
移植やってます。
( from python 3.7 to ruby 2.7 )
# callable (Python)
```python
if callable(func):
```
https://qiita.com/keishi04hrikzira/items/3864d6c74da76ad3ffde

こちらの記事が分かりやすい。~~独習Pythonには載っていない~~
# defined? (Ruby)
```ruby
def a; end
b = lambda { |x| p x }
c = 1
class D; end
e = D.new

p defined?(a)
p defined?(b)
p defined?(c)
p defined?(D)
p defined?(e)
p defined?(f)
p '----------'
p [a, b, c, D, e]
p [a.class, b.class, c.class, D.class, e.class]

# output
"method"
"local-variable"
"local-variable"
"constant"
"local-variable"
nil
"----------"
[nil, #<Proc:0x000002a58a4228e0 main.rb:2 (lambda)>, 1, D, #<D:0x000002a58a422840>]
[NilClass, Proc, Integer, Class, D]
```

||Python|Ruby|
|:--|:--:|:--:|
|組み込み関数|True|method|
|未定義の関数|False|nil|
|定義済みの関数|True|method|
|定義済みのクラス|True|constant|
|lambda|-|local-variable|

行けそうです。
# 追記
```python
list = [0, 1, 2, 3]
iter_list = iter(list)
print(callable(iter_list))

# false
```
`iter()`の場合、`false`になります。

```ruby
list = [0, 1, 2, 3].to_enum

p defined?(list)
p list.class

# "local-variable"
# Enumerator
```
よって、`Enumetator`の場合、クラスを見る必要があります。
# メモ
+ Python の callable を学習した
+ 百里を行く者は九十里を半ばとす
Nuxt.jsでv-iconのFont Awesomeが表示されない

Nuxt.js+vuetifyでポートフォリオを作っていたら、v-iconのfa(Font Awesome)が表示されない事件が起きた。
小一時間詰まってしまったので、解決方法と行ったことをメモしておく。

#faをインストール
```:terminal
yarn add @fortawesome/fontawesome-free -D
// OR 
npm install @fortawesome/fontawesome-free -D
```
#nuxt.config.jsを編集

```:nuxt.config.js
vuetify: { 
  defaultAssets: {icons: 'fa'}//ここを追加
}, 

//---------省略-----------//

plugins: ['plugins/vuetify'],
　　　　
```
#plugins/vuetify.jsを追加

```:src/plugins/vuetify.js
import '@fortawesome/fontawesome-free/css/all.css' // Ensure you are using css-loader
import Vue from 'vue'
import Vuetify from 'vuetify/lib'

Vue.use(Vuetify)

export default new Vuetify({
  icons: {
    iconfont: 'fa',
  },
})
```
これでOK
#おまけ(v-iconのfaの書き方)
```
<v-icon>fas fa-lock</v-icon>
```
こんな感じ適宜```fas fa-○○```の○○を変更すればいける
PowerShellでファイル内容を連結して出力する

Windowsで複数のファイルを統合したいことがあり、せっかくなのでPowerShellを使った。普通にPowerShellを使うと、基本ShiftJISだったので、PowerShell7を使った。

# 書いたスクリプト

```test.ps1
# 文字列をファイルに出力
function WriteToFile($str) {
    # ファイル先頭の改行を削除
    $str = $str -replace "^\r\n", ""
    # 改行の繰り返しを削除
    $str = $str.Replace("`r`n`r`n", "`r`n")
    $str = $str.Replace("`r`n`r`n", "`r`n")
    # ファイルに出力
    $str | Out-File -FilePath hoge.txt -Append
}

# ファイルの内容を取得して関数に渡す
$content = (Get-Content "C:\tmp\archive1.txt" -ReadCount 0) -join "`r`n"
WriteToFile($content)
$content = (Get-Content "C:\tmp\archive2.txt" -ReadCount 0) -join "`r`n"
WriteToFile($content)
$content = (Get-Content "C:\tmp\archive3.txt" -ReadCount 0) -join "`r`n"
WriteToFile($content)
```
概要：C:\tmp\archive1.txt～C:\tmp\archive3.txtの内容を読み込んで、現在のディレクトリのhoge.txtに書き込む。


```
    # ファイル先頭の改行を削除
    $str = $str -replace "^\r\n", ""
    # 改行の繰り返しを削除
    $str = $str.Replace("`r`n`r`n", "`r`n")
```
ファイル先頭に改行があったり、空白行が多かったりしたので調整している。


```
(Get-Content "C:\tmp\archive1.txt" -ReadCount 0) -join "`r`n"
```
取得したファイル内容の改行コードをCRLFにする。（１行ずつ配列にして\r\nでJOINしている）

# スクリプトの実行
スクリプトを「**.ps1」というファイル名で保存し、PowerShellプロンプトからファイルを実行する。
[PowerShell上からスクリプトを実行する](https://www.dospara.co.jp/5info/cts_str_pcuse_powershelluse#:~:text=PowerShell%E4%B8%8A%E3%81%8B%E3%82%89%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%82%92,%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%8C%E4%BD%9C%E6%88%90%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82&text=%E4%BD%9C%E6%88%90%E3%81%97%E3%81%9F%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%AF%E3%80%8C%E3%83%91%E3%82%B9,%E5%90%8D%E3%80%8D%E3%81%A7%E5%AE%9F%E8%A1%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82)

# PowerShell7のインストール
以下より環境にあったものをインストールする。
[Windows への PowerShell のインストール](https://docs.microsoft.com/ja-jp/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.1)
QUERY OPTIMIZATIONを変更してSQLプッシュバックを実行する

SPSS ModelerでSQLプッシュバックをする場合に、Db2のQUERY OPTIMIZATIONのレベルを変えたいことがあるかもしれません。

SET CURRENT QUERY OPTIMIZATION ステートメント - IBM Documentation 

https://www.ibm.com/docs/ja/db2/11.5?topic=statements-set-current-query-optimization

データベース入力ノードのSQLクエリーのモードを使えば、Db2のQUERY OPTIMIZATIONのレベルを変えることが可能です。

#1. current query optimizationの設定と実行
まず初期状態を確認しておきます。
データベース入力ノードのSQLクエリーのモードで
values current query optimization
を入力し、プレビューしてみます。結果としてLevel 5が返っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/5980ffdf-f980-e202-2cae-ea1b92201f26.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/1e16a425-4274-49f1-6719-c3ed71db86ac.png)


set current query optimization 0を設定してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/3a591fac-4f96-2143-ce40-9abb27a4c2f2.png)

テーブルノードを接続して実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/729eb9b5-11aa-5a06-028d-0a998dd6a2f1.png)

次の結果は特に意味がないので無視します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/1d2c518e-28b1-005f-3766-0fda226aaacf.png)

再度values current query optimizationを実行するとLevel 0に設定できたことがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/e77f5850-34ec-7097-2239-3854613b1f6b.png)

この後に実際にやりたい処理を選んで実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/24141e77-dd6f-9a0c-084a-b2007c74b067.png)


#2. バッチ実行
Query Optimization設定と本処理でそれぞれ実行するのは、特に自動実行するときには困ります。

そういう場合はスクリプト実行ができます。
オプションの実行タブからデフォルトスクリプト追加のボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/65598706-1ee3-0cc6-58fb-afa89ad233a2.png)

追加されたスクリプトでQuery Optimizationを設定する文が先に実行されるようにします。
そして「このスクリプトを実行」のオプションを選びOKで閉じます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/d48f7521-951c-9a01-8042-3d8c4bf80b7a.png)

この「現在のストリームを実行」のボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/dabdbca9-d3a1-28ee-b62b-7eeaa5b46dc6.png)

するとQuery Optimization設定、本処理の順で実行されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/50f80564-db2e-de69-b644-7e60fe369cf9.png)

#3. サンプルストリーム

https://github.com/hkwd/spsssample/raw/master/220128Optimization%E3%83%AC%E3%83%99%E3%83%AB%E5%A4%89%E6%9B%B4/Optimization%E3%83%AC%E3%83%99%E3%83%AB%E5%A4%89%E6%9B%B4.str

■テスト環境
Modeler 18.3
Windows 10 64bit
Db2 Warehoue on Cloud
Docker × Phpstorm環境でXdebugを動作させる手順

やっと動いてくれたので、備忘録用に記事を書きます。

## 環境
今回はこのような環境で検証を行いました、

```
windows 10
DockerDesktop 4.3.0
PhpStorm 2020.3.3
Xdebug v3.1.2
Laravel
- php7.4
- Apache/2.4.52 (Debian)
```

## Xdebugインストール
Dockerfileに以下を記載して、Dockerコンテナを作る際にXdebugインストールします。

```dockerfile
RUN pecl install xdebug \
   && docker-php-ext-enable xdebug
```

## Xdebugを有効にする
php.iniに以下を追加します。

```ini
[xdebug]
xdebug.mode = develop,coverage,debug,gcstats,profile,trace
xdebug.start_with_request  = yes
xdebug.log="/tmp/xdebug.log"
xdebug.client_port=9001
xdebug.client_host=host.docker.internal
xdebug.idekey=phpstorm
```

## Dockerコンテナを起動
上記の設定が終わったら、Dockerコンテナを起動します。

```bash
$ docker-compose up -d 
```

## PhpStorm側の設定

### ポート設定
File > Settings > Langueages&Frameworks > PHP > Debugを開き、
XdebugのDebug portを`php.ini`で設定した値を入れます。（今回例だと9001）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308656/5a8e551c-288f-cfd7-598f-91d199d308a4.png)

### servers設定

`Name`は任意の名前を入力します。
`Host`は任意の名前を入力します。
`Port`は`php.ini`で設定した値を入れます。（今回例だと9001）
`Debugger`は`Xdebug`を選択します。
`Use path mappings`にチェックを入れます。

`Absolute path on the server`には、Docker内にソースを配置しているPathを入力します。
私の場合だとホスト側のsrcディレクトリ内をDocker側の/var/www/htmlに同期させているので、`/var/www/html`になります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308656/7ed5af98-a044-0e22-5626-0e413f51d16a.png)


### Edit Configurationsの設定
PhpStormの右上にあるリストボックスから「Edit Configurations」を開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308656/2a37e30b-6d01-37c7-5926-5283b2425486.png)

左上にある「＋」ボタンを押して、`PHP Remote Debug`を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308656/5cc8b5ec-41e8-18f5-28ae-9d52f367cbc3.png)


右側の設定値を入力します。

`Name`は任意の名前を入力します。
`Server`は上記の`servers設定`で作ったものを指定します。（今回の場合だと`docker-debug`）
`IDE key`は`php.ini`で設定した値を入力します。（今回の場合だと`phpstorm`）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308656/64cb0dc3-cf9b-2c21-b4ef-2dc86a73c166.png)

## デバッグ準備

PhpStormの右上にある虫のアイコンをクリックします。（アイコンの右下に黄色のポッチがあるとONの状態です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308656/2eefe824-2d25-fa5f-5bf7-904bade7aeb8.png)

## ブレイクポイント設定
あとは止めたい処理のところで、行番号の横の空白をクリックして●をつけてブレイクポイントを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308656/e3488cd2-2e03-cbd3-c67f-10508d5ca50c.png)

## サイトにアクセス
処理がある部分にアクセスしてデバッガーが動いていればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308656/27173e3b-9c1c-bd16-a746-9b7641320157.png)

以上となります。
昨日、つまずいたphoton

#photonPunチャット、初心者つまずき事例
プロの方、お控えください。
ググっても情報古いし、頭の良いひとの記事は今一つわからない。
書き方がちょっと違っていたりして困った。
teratailで聞く前に、なんとなく実装出来たことを備忘録として記録。

参考にした動画は、こちら
やりたかったことは、吹き出しおしゃべりを、実装したかった。
https://www.youtube.com/watch?v=7cOtVzjy-6o


###■PhotonTargets.AllBufferedってのが、使えないらしい

```
photonView.RPC("SendMessage", PhotonTargets.AllBuffered, ChatInputField.text);
```
今はこうらしい。

```
photonView.RPC("SendMessage", RpcTarget.All, ChatInputField.text);
```

###■コードのRPC文字のみが、赤字になってエラーが出る。
プロジェクトをコピーして、当該スクリプトをコピペしたら治った。


###■インプットフィールドのテキストメッシュプロ版はいつもと記載が違う
常識なのかもしれないが、確実につまづいた。

```
using TMPro;
-----
-----
private TMP_InputField ChatInputField;
```

###■PhotonViewに吹き出しコンポーネントが登録出来ない
ゲームを実行すると、相手画面で吹き出し（チャット）が反映されない。1人チャット状態

#####原因はPhotonViewコンポーネントのObservedComponentsに共有するものは登録する必要がある。
ですが現在の状況は、PhotonViewにスクリプトコンポーネントをドラッグしても、共有オブジェクトが登録出来ない状態になっている。

↓ここが死んでいる

```
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
```
その場合、、、これにすると復活した。

```
public class ChatManager : MonoBehaviourPunCallbacks, IPunObservable
```

'MonoBehaviourPunCallbacks'
（公式）このクラスは、.photonViewと、PUNが呼び出すことができるすべてのコールバック/イベントを提供します。使用したいイベント/メソッドをオーバーライドします
（解釈）punが折り返し連絡してくれる。電話のコールバックと似たもの。

'IPunObservable'
（公式）監視可能なスクリプトを正しく実装することを容易にするため、OnPhotonSerializeViewメソッドを定義。
（解釈）登録しないと仲間はずれにされる、複数の関数を登録しているもの。

で、スクリプトをPhotonViewの監視対象コンポーネントにできた。

###■【Unity】using Photon.Pun　が、参照しなくなった
この記事で解決できました。
https://teratail.com/questions/316915
ありがとうございます。
色々あったけど、結局EC2でTableauServer構築したメモ

### 概要

TableauServer構築時に苦戦したメモ

### Quick Startを使用して環境構築に挑戦するも挫折

> このクイックスタートを使用すれば、AWS と Tableau Software のベストプラクティスに従いながら、AWS クラウドで完全に機能する Tableau Server 環境を アマゾン ウェブ サービス (AWS) のクラウドにデプロイ

https://aws.amazon.com/jp/quickstart/architecture/tableau-server/

ということで構築してみるも、Cloudformationが落ちまくり断念。
テンプレート名に記号入れてたら途中で落ちたりした

### 手動で実施するしかない

何回も起動スクリプト叩きました。

##### 前準備

1. アップデート＆タイムゾーン設定

```sh
#!/bin/bash
yum -y update

# Change Time Zone
timedatectl set-timezone Asia/Tokyo
cat /etc/locale.conf
localectl
localectl set-locale LANG=ja_JP.UTF-8
yum update systemd -y
```

2. インストーラーダウンロード

こちらのインストーラーにあるバージョンを指定する

https://www.tableau.com/ja-jp/support/releases/server

```sh
# Install Tableau
wget https://downloads.tableau.com/esdalt/XXXXX/tableau-server-XXXXX.x86_64.rpm -P /tmp
yum install /tmp/tableau-server-YYYY-MM-DD.x86_64.rpm -y
```

あとは手順のとっとり作業！
以下のサイトが参考になった。

### 備忘録

- 各DBのドライバーもインストールする必要があるが、ドライバーのバージョンはTableauから指定のバージョンでないと動作しない

- Tableauのサポートに問い合わせるときにログコマンド入力して問い合わせる

https://help.tableau.com/current/server/ja-jp/logs_archive.htm


### 参考サイト

https://boxcode.jp/linux%E3%81%A7tableau-server%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E7%B7%A8
ゲーム開発におけるSubversion/Git/Perforcerの比較

ゲーム開発においてバージョン管理システムは開発の中核を担う重要なものです。
Subversion、Git、Perforceをそれぞれ3年以上使った経験から、各バージョン管理システムのメリットとデメリットをまとめていきたいと思います。

# Subversion

○　導入コストが安い
○　仕組みがシンプルで分かりやすい
○　TortoiseSVNが使いやすく、とっつきやすい
○　ファイルの排他ロックがある
×　コードレビューの仕組みがない
×　巨大なファイルを扱うと重くなりやすい
×　ブランチを作ると丸ごとコピーになるため、プロジェクトが肥大化するとブランチコストが高くなる

古さゆえにシンプルで、色々な職域の人が作業するゲーム開発において「分かりやすさ」の一点において優れています。
ただしプロジェクトが肥大化すると巨大ファイルを扱うと重い・ブランチ作成のコストが高いといった理由で運用コストが跳ね上がります。またコードレビューの仕組みがないため、コードの品質担保が難しい側面があります。

# Git

○　導入コストが安い
○　GitHubを使うことでコードレビューが容易
○　ブランチがローコストで作成できる
×　競合の解決方法が分かりづらく、事故が起きやすい
×　100MBを超えるファイルをコミットするにはGitLFSなどのサポートが必要
×　ファイルの排他ロックがない（拡張すれば使えるようになるらしい）

GitHubの存在のおかげで導入コストが安く、またPullRequestによる仕組みがあるのでコードの品質担保が容易です。
ブランチ間を移動するのも早く、プロジェクトが肥大化してもブランチ運用のコストが上がりにくいです。
しかし元々ソースコードのためのバージョン管理システムだったこともあり、リソースを扱うことが苦手です。
GitLFSがないと100MBを超えるファイルはコミットできませんし、バイナリファイルを扱う際に便利な排他ロック機能もありません。
またコミット・プッシュ・プルの仕組みを理解していないと競合の解決で事故が起きやすく、色々な職域の人が作業するゲーム開発においてはデメリットです。特にチームの人数が増えるとトラブル解決のコストも大きくなります。

# Perforce

○　コードレビューの仕組みがある（ただしGitHubほど洗練されていない）
○　巨大なファイルを扱っても重くなりにくい
○　ファイルの排他ロックがある
×　導入コストが高い
×　ブランチを作ると丸ごとコピーになるため、プロジェクトが肥大化するとブランチコストが高くなる
×　日本語の資料がほとんどない

基本的な使い方はSubversionに似ていますが、巨大なファイルを扱うのに長けています。
ゲーム開発は巨大なファイルを扱うことが多いので、この一点だけでも非常にメリットがあります。
Gitのようなコミット・プッシュ・プルの仕組みがなく、分かりやすさも強みです。
コードレビューの仕組みはHelix Swarmというものがあり、GitHubほどではないですが可能です。
ですが商用なので個人が扱うには敷居が高く、日本語の資料もほとんどないため非常に玄人向けです。
GitHubのように気軽にブランチを行き来する機能がないのも残念な点です。

# 所感

大規模なコンソールゲームならPerforce一択、個人開発や小～中規模のカジュアルゲームならGitHubというところでしょうか。
Subversionは分かりやすくはあるのですが、さすがに昨今の開発事情を考えると選ぶケースはあまりないのではと思います。
将来的にPerforce導入予定で、その繋ぎとしてならありかもしれません。

ちなみに筆者はCVS→VSS→SVN→Git→Perforceと使ってきました。
Pythonでエシェロン解析

昨年発売のコチラの書籍を読んでいたところ実装して試したくなったので、[echelon-py](https://github.com/takeshi-teshima/echelon-py)という汎用パッケージを作って公開しました。


栗原考次・石岡文生 （2021） 『エシェロン解析―階層化して視る時空間データ―』 共立出版

https://www.kyoritsu-pub.co.jp/bookdetail/9784320112704

----

パッケージに実装されている全機能をカバーするように、論文等で扱われている例を実装したノートブックも作成・同時に公開しています。データセットのダウンロードもノートブック内で行なっているので、他の実装をちょっと試すのにも地味に便利。
https://takeshi-teshima.github.io/echelon-py-examples/


## 使用例：東京23区の肺炎データ
上述の書籍でも使われているデータです。

入力①：観測値のDataFrame
![スクリーンショット 2022-01-28 15.28.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81016/1f4b1eb6-92c1-94ea-5b85-dd5b781fba11.png)

入力②：GeoPandasで読み込んだ東京都のShapefile(`.shp`)
![スクリーンショット 2022-01-28 15.29.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81016/ed72bae8-072e-63c8-926d-879d29f010b2.png)


この2つの入力からEchelonを作成して、Dendrogramで図示（このときAdjacencyの情報をShapefileから抽出している）：

```python
from echelon.contrib.geo import GISEchelonAnalysis
api = GISEchelonAnalysis()

result = api(table43, Tokyo_gdf, 'ID', 'Name', 'SMR')

print(api.dendrogram(result))
```

結果
![スクリーンショット 2022-01-28 15.31.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81016/5d33b254-b4b0-15da-c25e-d2bfd57c5da7.png)

同じデータと、作成済みのEchelon集合から、ホットスポット候補の列挙

```python
hotspots = api.hotspots(result, (table43, 'ID', 'n', 'o'), score='binomial')
hotspots
```

![スクリーンショット 2022-01-28 15.33.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81016/191ced14-ca0c-27ea-97d6-cc0852f03c6b.png)

列挙したホットスポット候補のトップ1を地図にプロット

```python
%matplotlib inline
import matplotlib.pyplot as plt
api.plot_hotspot(hotspots)
plt.show()
```

![スクリーンショット 2022-01-28 15.34.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81016/711eea42-b787-80f9-bbb2-0ab125956181.png)

こちらの例は以下のノートブックで確認できます：

https://takeshi-teshima.github.io/echelon-py-examples/src/notebooks/application-neumonia-Tokyo.html

### 未実装の機能
モンテカルロ検定と時系列ホットスポット表示以外は概ね実装しました。
Matplotlibでデンドログラムを楽していい感じに描く方法がなさそうだったので、デンドログラムは図ではなく文字列で出ます。本当は図で出力する機能を付けたいところ。
デンドログラムをいい感じに描けるよという方がいたらぜひIssueでお知らせください。

## 参考
- R実装（本家）
  https://cran.r-project.org/web/packages/echelon/echelon.pdf
- JS実装 https://zenn.dev/yonda/articles/4493fc696b2180
- [栗原考次・石岡文生 （2021） 『エシェロン解析―階層化して視る時空間データ―』 共立出版](https://www.kyoritsu-pub.co.jp/bookdetail/9784320112704)

書籍に書かれているアルゴリズムはそのままだと動かなかった（ちょっとしたバグとかではなく）ので、R実装を参考にしつつ、多分こうだろうというアルゴリズムを実装しています。