OmniAICreator/Qiita-1.07M huggingface dataset:
STL：vectorの要素アクセス方法　at と operator[]

STL の`vector`を使っていて頭に入れておくべきことがあったので、ここにメモしておきます。
`std::vector`の n 番目の要素の参照を返す（要素へアクセスする）方法は大きく2つあります。
さあ、あなたはどっち？
※`iterator`を使ったアクセスについてはまた改めて！

#vector::at
境界チェックをする（`vector`の管理範囲外にアクセスしていないか）
　　範囲外アクセスをした時、`std::out_of_range`の例外を送出する。
　　範囲外アクセスチェックのため、若干の OH（オーバーヘッド）が生じる。

```例.
// vectorにある要素の値を変数に代入したり
variable = vector.at(index);

// ある値をvectorにある要素に代入したり
vector.at(index) = value;
```

#vector::operator[]
境界チェックをしない
　　範囲外アクセスをした時、 未定義動作を行う。
　　範囲外アクセスチェックをしないため、OH が生じない。

```例.
// vectorにある要素の値を変数に代入したり
variable = vector[index];

// ある値をvectorにある要素に代入したり
vector[index] = value;
```

#サンプルコード
「え？どゆこと？」
そう思ったあなた、是非ご自身の環境で以下のコードを試してみて下さい。
あ、for 文のindexに注意して下さいね。

```sample.cpp
#include <iostream>
#include <vector>
#include <stdexcept>

int main()
{
    std::vector<int> sampleVector;

    // sampleVectorのindex0～9に要素を詰める. 
    for (int i = 0; i < 10; i++)
    {
        sampleVector.push_back(i);
    }

    std::cout << "###std::vector::at" << std::endl;

    // at
    try
    {
        // sampleVectorの管理範囲外であるindex10の要素にアクセスする. 
        for (int i = 1; i <= 10; i++)
        {
            std::cout << sampleVector.at(i) << std::endl;
        }

        // atの境界チェックで例外を投げるため、この処理は実行されない. 
        std::cout << "Complete..." << std::endl;
    }
    catch (std::out_of_range& sampleException)
    {
        std::cout << "out of range!" << std::endl;
        std::cout << "Error : " << sampleException.what() << std::endl;
    }

    std::cout << std::endl << "###std::vector::operator[]" << std::endl;

    // operator[]
    try
    {
        // sampleVectorの管理範囲外であるindex10の要素にアクセスする. 
        for (int i = 1; i <= 10; i++)
        {
            std::cout << sampleVector[i] << std::endl;
        }

        // 境界チェック無しのため、そのまま不定値が出力され、実行完了となる. 
        std::cout << "Complete..." << std::endl;
    }
    // 境界チェック無しのため、例外は投げない. 
    catch (std::out_of_range& sampleException)
    {
        std::cout << "out of range!" << std::endl;
        std::cout << "Error : " << sampleException.what() << std::endl;
    }

    std::cout << "End..." << std::endl;

    return 0;
}
```

```出力.
###std::vector::at
1
2
3
4
5
6
7
8
9
out of range!
Error : invalid vector subscript

###std::vector::operator[]
1
2
3
4
5
6
7
8
9
2011707104
Complete...
End...
```

おやおや、全然違う結果になっていますねぇ
へっへっへ・・・
`std::vector::operator[]`の方は、なんだかとんでもない値を出力していますねぇ
へっへっへ・・・

#まとめ
上記2つの違いは「範囲外アクセスをした時に、未定義動作を行うか例外を投げるか」です。
防御的プログラミングということであれば、未定義動作を行わないことが保証されている方をできるだけ使うべきだと思います。

`at`は範囲外アクセスに対して`std::out_of_range`例外を投げるため、適切に処理されなかった場合、`std::terminate`が呼ばれてプログラムが異常終了します。
例外処理を用意していなかったとしても、プログラムが終了するだけです。
デバッグも比較的容易でしょう。

未定義動作を原因とするバグは、実際に未定義動作を行った箇所と異なる箇所で致命的なエラーを発生させることも多くあります。
エラー発生箇所と原因箇所が異なる場合、デバッグは困難になるでしょう。

個人的にはまず`at`を使うことをオススメしたいかなぁ。

`at`派 vs `operator[]`派の議論を見たいので、よかったらコメント下さい！
vue.js google analytics

vue.js で googleAnalyticsを使いたい。


# インストール

```

npm install vue-analytics

```



```app.js

//app.js の最下部に追加
import VueAnalytics from 'vue-analytics'
Vue.use(VueAnalytics, {
    id: 'UA-xxxxx-xx',//your
    router
});

```

たったこれだけ。
入室管理システムの設計（DB）ー午後

応用情報技術者平成30年秋期 午後問6

ファイル：2018h30a_ap_pm_qs.pdf

**１、図１に適切なエンティティ間の関連を記入し、E-R図を完成させよ。図１の凡例に倣うこと。**
・①入室管理用社員　から　②入室許可　に、１対多ですね。複数室に入室許可は可能だから。
・①入室管理用社員　から　④入退室ログに、１対多ですね。複数回に入室するから。
・③室から　②入室許可　に、１対多ですね。表３に記載されている「入室許可登録する時に、同じ社員ID、室ID、入室開始年月日の場合、更新」しますが、入室開始年月日が異なる場合、登録しますから。
・③室から　④入退室ログに、１対多ですね。１つの室に対して、複数回に入室するから。
・②入室許可と入退室ログは、関係は曖昧ですね。入室許可だけど、入退室ログがないのは可能ので、凡例には使えるのエンティティ関連はないですね。

私の答え：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/6b970baa-3b86-d709-21f4-7dc310674389.png)

参考答え：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/1e532985-2f89-e5bd-7e44-51c5c2e389d8.png)


＜＜図１＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/de377b42-c9e8-417e-98c6-2c6553be1990.png)

＜＜表２＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/de54e995-edd1-c2be-250c-491921b7e4b4.png)

＜＜表３＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/d3154d98-3978-e793-dc7c-e530e1d38dbb.png)



**２、表２に示した実表”入室許可”における、主キーを答えよ。**
表３に記載されている「入室許可登録する時に、同じ社員ID、室ID、入室開始年月日の場合、更新；その三つが異なる場合は、登録」ので、多分、社員ID、室ID、入室開始年月日ですね。
あとは、もし社員ID、室IDだけがキーとすると、社員ID、室IDが同じ、入室開始年月日が異なるでも登録できないから、入室開始年月日が主キーとしなければならないですね。


**３、図２中のaに入れる適切な字句を答えよ。**
aは、入室チェックです。入室可の場合、１以上を返す；入室否の場合、0を返すとのSQLです。
図２のSQLから見ると、入室許可の件数を求めるとのことですね。入室許可テーブルに条件満たせるデータがあれば、その件数を戻すこと。なので、COUNT(＊)です。もちろん、COUNT(0)などは正しいと思っております。参考答えは、COUNT(＊)ですから、それをしよう。

＜＜図２＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/7b509480-a845-1151-ba9c-37144693311d.png)
alpine-linuxでcode-serverを立ち上げる

# Alpine-Linux上でcode-serverを立ち上げる

Pythonの開発環境を構築する必要があり調査を実施。
以下のDockerfileで起動し、それとなく使える事が判明した。
ベースイメージはpythonオフィシャルの3.7-alpineを使用したが、通常のalpine-linuxでも起動できると思う。

```Dockerfile
FROM python:3.7-alpine

RUN apk --no-cache --update add alpine-sdk bash libstdc++ libc6-compat npm libx11-dev libxkbfile-dev libsecret-dev && \
    npm config set unsafe-perm true && \
    npm install -g code-server

ENTRYPOINT ["code-server", "--auth", "none", "--bind-addr", "0.0.0.0:8080"]
CMD [""]
```

## 注意事項

* ポート番号は8080なので、docker起動時にポートのマッピングが必要
* 鍵情報を作らないとブラウザ等からクリップボード等のアクセスに問題がある模様？insecureだと警告がでる。
* スリム化は行っていない。現状、docker images上で944MBと表示される。
* 認証も外しているので、インターネット等外部からアクセスするようなところでの起動は自己責任で。
* その他、使い込んでいないので、他にどのような問題があるかは不明。
信頼関係のあるAD配下でのADFS認証フロー

# 概要

信頼関係を設定している2つのActive Directoryの一方にADFSを構築して認証させる際のネットワークフローです。
パケットキャプチャした内容等をもとに記載していますが、推測で記載しているところも多々ありますので、あくまで参考程度としてください。

# 想定シナリオ

Active Directory ドメインAとドメインBが存在し、AとBにおいて2-wayの信頼関係を設定。
ADFSはドメインA配下のサーバーに構築。
この環境において、ドメインB配下のWindows10 PCからADFS経由でSAML連携で外部サービスにアクセスする。認証はWindows統合認証とする。

# ネットワークフロー

1. PCから外部サービスにアクセスすると、ADFSへリダイレクトするようレスポンスが返る
   
    ```
    https://adfs.main.hishi/adfs/ls?SAMLRequest=XXXXXXXXXXXXXXXXX
    ```
   
2. PCからADFSにアクセスすると、Windows統合認証ページにリダイレクトされる。ADFSは401 Unauthorizedを返す。
   
    ```
    https://adfs.main.hishi/adfs/ls/wia?SAMLRequest=XXXXXXXXXXXXXXXXX
    ```
   
3. ADFSは401を返す。

    ```
    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: Negotiate
    WWW-Authenticate: NTLM
    ```

3. PCからドメインBに対してKRB-AS-REQ を送信。PCへはKRB-AS-REPでTGTを返却。
3. PCからドメインBにTGTを添えてadfs-serverのPrincipalのSTを要求。ドメインBはPRINCIPAL-UNKNOWNを返す。
5. PCから `https://adfs-server/adfs/ls/wia?SAMLRequest=XXXXXXXXXXXXXXXXX` にアクセスする。この時HTTPヘッダで`Authorization: Negotiate AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`を送る。 (この時InitializeSecurityContextでNTLMのコンテキストを送っている模様)
5. ADFSは再度401を返す。

    ```
    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: Negotiate BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
    ```

5. PCから `https://adfs-server/adfs/ls/wia?SAMLRequest=XXXXXXXXXXXXXXXXX` に再度アクセスする。この時HTTPヘッダで`Authorization: Negotiate CCCCCCCCCCCCCCCCCCCCCCCCC`を送る。
6. ADFSからドメインAにポートマッピングリクエストの後、NetrLogonSamLogonEx をリクエスト (詳細不明)
7. ADFSがDNSに接続し、_ldap._tcp.Default-First-Site-Name._sites.dc._msdcs.DOMAIN.NAME のSRVレコードを検索し、ドメインBのAレコード(IPアドレス)を取得
7. ADFSからドメインBにLDAP Ping (UDP Port 389)。この時、ADFS自身を検索している模様。((&(&(&(DnsDomain=DOMAIN-B)(Host=ADFSのホスト名))(NtVer=0x20000016))(DnsHostName=ADFSのFQDN)))
7. ADFSからドメインBにKerberos接続 (TCP Port 88)。ユーザーを検索しようするが、ドメインBはeRR-PREAUTH-REQUIREDを返す。
7. ADFSからドメインBにKerberos接続 (TCP Port 88)。krb-tgs-reqでADFSのプリンシパルを送信してticketを取得
7. ADFSからドメインBにLDAP Ping (UDP Port 389)。先ほどのLDAP pingと同じ内容。（かつ2回、合計3回）
8. ADFSからドメインBにLDAP 接続 (TCP Port 389) searchRequest (objectClass=*)で検索しているようだが詳細不明
8. ADFSからドメインBにKerberos接続 (TCP Port 88)。STを取得
8. ADFSからドメインBにLDAP 接続 (TCP Port 389) STをつけてbindRequest後、LDAP検索
9. ADFSからPCにSAMLレスポンスを返す
10. PCから外部サービスに接続しログイン

ここでKerberos通信はキャッシュするらしく、2度目のリクエストからはLDAPの通信のみ発生する模様。

# Revision History

Rev 1 2020年08月30日 初版
Rev 2 2021年06月22日 Kerberosの記載を追加
【React】ミュータブルな操作とイミュータブルな操作

# はじめに
業務で本格的にReactを触り始めて10ヶ月程経過しました。  
実装を進める中でドキュメントを読んだり、ググったりする中で必ず目にするのが

- 「Reactはイミュータブルな操作を要請する」
- 「Reactでは破壊的な変更を伴う操作を行ってはいけない]  

といった内容のものです。

なんとなくの理解で通り過ぎてしまっていたのですが、
そのせいでコンポーネントが期待どおり再レンダリングされず、画面が変化しないという現象に何度かぶち当たりました。
10ヶ月も基本的なことをスルーしていたので、調べて理解したことをまとめてみました。

# ミュータブル/イミュータブルとは
まずは言葉の意味から

- mutable (ミュータブル): 可変
- immutable (イミュータブル): 不変

**ミュータブルな操作とは**
元の状態の変更を伴う(可変)操作

**イミュータブルな操作とは**
元の状態の変更を伴わない(不変)操作

言葉だけだとつまりどう言うこと？？となるので実際の配列操作をしてみます。

## ミュータブルな操作/ミュータブルな操作
配列への要素の追加をしてみます。

```javascript

const arr = ['1', '2', '3'];
// ミュータブルな操作(イミュータブルではない操作)
arr.push('4');
console.log(arr);
// [ '1', '2', '3', '4' ];

// イミュータブルな操作(ミュータブルではない操作)
const immutableArr = [...arr, '5'];
console.log(immutableArr);
// [ '1', '2', '3', '4', '5' ]
```

実行結果だけを見てもパッと見違いがありません。
配列の操作で4と5という要素を加えた新しい配列が返ってきてるように見えます。

ここで注目するのが**元の配列と新しい配列のデータの参照先**です。
```arr.push('4');```
とした時にはコピー元の```const arr = ['1', '2', '3'];```も
```arr.push('4');```をした新しい配列も
```arr = [ '1', '2', '3', '4' ];```という情報を参照します。
``arr = ['1', '2', '3'];```
の一つの情報(メモリ)に直接変更が加わり参照されるようになります。

乱暴な言い方ですが、元の```arr = ['1', '2', '3'];```の情報はなくなります。

```const immutableArr = [...arr, '5'];```
とした場合には
```コピー元の配列([ '1', '2', '3', '4' ])```と
```新しい配列(immutableArr)```の参照先の情報をそれぞれ別々に持ちます。
arrは[ '1', '2', '3', '4' ]という情報を参照。
immutableArrは[ '1', '2', '3', '4', '5' ]という情報を参照。

※言語は異なりますが、下記サイトの図解がわかりやすかったです。
https://kurochan-note.hatenablog.jp/entry/20110316/1300267023

下記のようなオブジェクトの操作でも同様のことが行われます。

```javascript
const obj = {name: 'a', type: 'old'};
// ミュータブルな操作(イミュータブルではない操作)
obj.type = 'new';
console.log(obj);
// { name: 'a', type: 'new' }

// イミュータブルな操作(ミュータブルではない操作)
const immutableObj =  { ...obj, type: 'new' };
console.log(immutableObj);
// { name: 'a', type: 'new' }
```

## なぜReactではイミュータブルな操作が必要なのか
上記を踏まえて、Reactでイミュータブルな操作が必要とされる理由は、
**React がコンポーネントの変化をオブジェクトの 同一性(差分) チェックで検知しているためです。**

ミュータブルな操作をしてしまうとコピー元の情報も変更されてしまうため、
変更前と変更後の差分をReactが検知できなくなってしまいます。

一方、イミュータブルな操作では変更前と変更後の情報をそれぞれ参照しているので、
Reactは差分を検知することができます。

先ほどのオブジェクトの操作を例に取ると、

```javascript
const obj = {name: 'a', type: 'old'};
// イミュータブルな操作(ミュータブルではない操作)
const immutableObj =  { ...obj, type: 'new' };
console.log(immutableObj);
// { name: 'a', type: 'new' }
```

```obj !== immutableObj```とした時にReactはコンポーネントに変化があったと検知することができます。



しかしミュータブル(イミュータブルではない)な操作をした下記の場合、

```javascript

const obj = {name: 'a', type: 'old'};
// ミュータブルな操作(イミュータブルではない操作)
obj.type = 'new';
console.log(obj);
// { name: 'a', type: 'new' }

```
```obj.type = 'new';```
とした後の```obj```は初めとは異なったtypeの値を持ちますが、
```obj !== obj```では変更を検知できないため、Reactは差分に気付けないのです。

この変更の検知の仕組みを持つため、Reactではイミュータブルな操作が必要とされるのです。

なのでReactで配列操作やオブジェクト操作をする際には,
```concat()```、```Object.assign()```や```スプレッド演算子```を用いたイミュータブルな操作をする必要があります。

たどたどしい説明になってしましましたが、最後まで読んで頂きありがとうございました。
RestSharpを使ってDigest認証を試してみた

# 背景

Windowsアプリ開発の中でHTTPクライアント周りを調べていたのですが、標準では`HttpClient`クラスが用意されています。
[HttpClient クラス (System.Net.Http) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.net.http.httpclient?view=netcore-3.1)

が、このクラスが結構曲者らしいのです。（実際使ったことがないのでわかりませんが）
Qiitaで調べてみても結構出てきて、これは使いたくないな、、と正直思いました。

[HttpClientをusingで囲わないでください - Qiita](https://qiita.com/superriver/items/91781bca04a76aec7dc0)
[.NET(Framework)のHttpClientの取り扱いには要注意という話 - Qiita](https://qiita.com/nskhara/items/b7c31d60531ffbe29537)

さらに調べたところ、[RestSharp](https://restsharp.dev/)というREST APIクライアントライブラリがあることを知り、割と良さそうだと思ったので、Digest認証で試してみることにしました。

# 導入方法

NuGetパッケージの管理から以下のパッケージをインストールします。

- RestSharp
- RestSharp.Authenticators.Digest
- RestSharp.Serializers.Utf8Json

```
Install-Package RestSharp
Install-Package RestSharp.Authenticators.Digest
Install-Package RestSharp.Serializers.Utf8Json
```

# 使い方

例えばAPIがGETメソッドで、レスポンスとして以下のJSONデータを返してくるものとします。

```json
{"foo": "bar", "baz": {"foo": "bar", "baz": "qux"}}
```

まず、JSONデータを受け取るためのデータクラスを作成します。

```cs:Foo.cs
public class Foo
{
    public string foo { get; set; }

    public Baz baz { get; set; }
}
```

```cs:Baz.cs
public class Baz
{
    public string foo { get; set; }

    public string baz { get; set; }
}
```

そして、以下のようにリクエスト＆レスポンスからJSONデータをデシリアライズします。

```cs
// クライアントの生成（BaseURLを設定しておく）
var client = new RestClient("https://hogehoge.api/1.1)
{
    // Digest認証の設定
    Authenticator = new DigestAuthenticator("username", "password");
};

// JSONシリアライザーの設定（今回はUtf8Jsonを使用）
client.UseUtf8Json();

// リクエストの生成（Resourceとレスポンスのデータフォーマットを設定）
var request = new RestRequest("foobaz", DataFormat.Json);

// 同期呼び出し
var response = client.Get(request);

// JSONデータをデシリアライズ
var result = new Utf8JsonSerializer().Deserialize<Foo>(response);
```

大まかには`RestClient`クラスのインスタンスを生成し、認証方式やJSONシリアライザーの設定をして、`RestRequest`クラスのインスタンスを`client.Get`メソッドの引数に渡すことでできます。
そして、変数`response`に結果が入っているので、あとはJSONデータをデシリアライズします。

また、以下のように非同期呼び出しにして、デシリアライズをまとめることもできます。

```cs
// 非同期呼び出し（resultがFoo型として返ってくる）
var result = await client.GetAsync<Foo>(request);
```

# 参考URL
- [RestSharpの基本的な使い方 - Qiita](https://qiita.com/kawaidainfinity/items/032d831187c08702fce9)
Sign In With Appleを実装

# 概要
* Sign In With Appleをアプリに組み込む際に調べたことをまとめました。  
* 今回の内容はサーバーサイドのみの内容となります。  

# 開発環境  
* 使用言語：PHP(v7.3.11)
* フレームワーク：Laravel(v7.20.0)
* DB：Sqlite

# 事前準備
* Apple Developerに登録してSign In With Appleの設定をしておく
以下の値、ファイルを取得
 * アプリのバンドルID
 * KeyID
 * 秘密鍵の.p8ファイル(1度しかダウンロードできないので注意)
 * TeamID

# 認証の流れ  
以下の手順で認証を行いました  

* クライアント側でSign In With Appleの認証をする
* 認証結果のcode値をサーバに送る
* サーバ側でcodeの検証
* 検証結果がJWT形式で返ってくるのでJWTデコードする

### codeの検証
検証はAppleが提供している検証APIに以下のパラメータをPOSTして行います。
API：POST https://appleid.apple.com/auth/token  

パラメータ  

* client_id：アプリのバンドルIDのこと
* client_secret
* code：クライアント側から取得する
* grant_type：検証なので'authorization_code'を設定
* redirect_uri：あらかじめDevelopperサイトで登録しておく

### client_secretの作成
* client_secretとは検証に必要なJWTでエンコードされた値  
* JWTとは3種類の文字列をドットで繋げた文字列
* JWTの作成にはfirebaseが提供しているライブラリを使用(他にもありましたが今回は以下を使用しました)  


#### client_secret作成に必要な値
* alg：ES256
* kid：KeyID
* iss：TeamID
* iat：現在時刻
* exp：有効期限
* aud：'https://appleid.apple.com'(固定)
* sub：ClientID(アプリのバンドルID)

今回は以下のように実装しました  

```
$key = openssl_pkey_get_private('file://'.PRIVATE_KEY_PASS); // 秘密鍵ファイルのパス
$now = time();
$expire = time() + 86400 * 180; // 有効期限を半年に設定
$payload = array(
    'iss' => TEAM_ID,
    'iat' => $now,
    'exp' => $expire,
    'aud' => 'https://appleid.apple.com',
    'sub' =>  CLIENT_ID
);
return JWT::encode($payload, $key, 'ES256', KEY_ID); // ES256は署名アルゴリズム
```

#### 検証結果からユーザーを一意に特定するIDを取得
* ユーザーを特定する文字列はid_tokenの中に含まれているのですが、JWT形式のためそのまま取り出すことはできません。
* id_tokenは「ヘッダー.ペイロード.署名」のように情報をドット区切りで持っています
* ユーザーを特定するIDはペイロードの中に含まれる「sub」値がそれに該当します  

以下のようにしてsub値を取得しました  

```
$jwt_token = expload('.', 'id_token');
$payload = base64_decode($jwt_token[1]);
$decode_payload = json_decode($payload, true);
$sub = $decode_payload['sub'];
```

### 参考資料
* https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens
* https://jwt.io/
* https://github.com/firebase/php-jwt
JavaFX + IntelliJ + Scene BuilderでGUIアプリケーションを作るサンプル

# はじめに
GUIアプリケーションを作りたいと思いました。GUIアプリを作るためのライブラリやフレームワークは色々ありますが、個人的には一番得意なJavaで作れたらいいなと思い、JavaFXを使って開発するための環境構築をしてみました。
~~サンプルを作っただけで満足しちゃったけど！~~

肝心なところは他の記事に丸投げするクソ記事ですのでご注意ください。
でも、他の記事に書かれているのと同じことをそのまま書くのは色々とアレだと思うので仕方ないのではないかと（言い訳）

ソースはこちらです。
https://github.com/dhirabayashi/javafx_sample

# 超適当な用語説明
## JavaFX
* Javaでいい感じのGUIアプリを作れるライブラリ
* もともとはRIAのライブラリだったが、~~RIAがオワコンになったため~~今は普通のGUIライブラリになっている
* 今はJDKに同梱されなくなったので、OpenJFXを別途導入する必要がある（Gradleがいい感じにやってくれるけど）

## IntelliJ（IntelliJ IDEA）
* Javaに対応したIDE
* 今はEclipseよりも人気が高い気がする
* 有料のUltimateと無料のCommunity版がある
* 今回のサンプルではCommunity版を使用する

## SceneBuilder
* JavaFXでの開発を楽にしてくれるツール
* ドラッグ&ドロップでコンポーネントを配置するなど、GUIベースで開発ができる

# 環境
* macOS Catalina 10.15.6
* AdoptOpenJDK 14.0.1

# 環境構築手順
JDKとIntelliJはインストール済みとします。

## IntelliJでJavaFXプロジェクトを作成する
下記の記事を参考になさるといいでしょう。プロジェクトの作成からサンプルコードの作成、実行まで一通り網羅されていてわかりやすいです。
[IntelliJ IDEAとGradleでのJavaFXアプリケーション開発 〜環境構築からサンプルコードまで〜](https://qiita.com/maru2213/items/c81905304c4c3ca09aa2)

しかし、私の環境ではなぜかうまく動かなかったため、少しソースを変更しました。
Class#getResource() → ClassLoader#getResource()

```MainApp.java
package com.github.dhirabayashi.javafx;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.util.Objects;

public class MainApp extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        var cl = getClass().getClassLoader();
        Parent root = FXMLLoader.load(Objects.requireNonNull(cl.getResource("scene.fxml")));

        Scene scene = new Scene(root);
        scene.getStylesheets().add(Objects.requireNonNull(cl.getResource("styles.css")).toExternalForm());

        stage.setTitle("JavaFXサンプル");
        stage.setScene(scene);
        stage.show();
    }
}
```

## Scene BuilderとIntelliJの連携
上記の手順だけでも開発は可能になりますが、全部コードベースで開発するよりも、Scene Builderを導入してGUIベースで開発したほうが楽だと思いますので、その手順を示します。（やはり丸投げですが）

これについてはIntelliJの公式ヘルプがありますので、それをご覧になるといいです。
[JavaFX Scene Builderを構成する](https://pleiades.io/help/idea/opening-fxml-files-in-javafx-scene-builder.html)

やっていることとしては、Scene Builderを別途インストールして、そのパスをIntelliJで設定するだけです。
日本語化していない場合はメニュー名が違っていると思いますが、Preferencesを開いて「JavaFX」で検索すれば出てきます。

JavaFXではfxmlファイルを編集することでGUIの開発を行いますが、Scene Builderを使うとそのfxmlの内容をいい感じに書き換えてくれるというイメージです。
Scene Builderを開くには、fxmlファイルを選択して右クリックメニューから「Open in SceneBuilder」を選択します。[^scenebuilder]
[^scenebuilder]: ダブルクリックでfxmlファイルを開き、左下のタブで「Scene Builder」を選択するという方法もありますが、その手順だと後述のプレビューやコントローラのスケルトンコード生成機能が使えないっぽいので、右クリックからの起動がおすすめです。

![スクリーンショット 2020-08-30 11.28.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321705/c3674d57-baad-90c4-1929-ece763e1d048.png)

Scene Builderの使い方はこちらの記事がわかりやすかったです。Eclipseの例となっていますが、Scene Builderを開いた後の操作は変わりません。
[Scene Biulder の基本的な使い方](https://java.keicode.com/lib/javafx-scene-builder.php)

# おわりに
予告通りのクソ記事でしたが、とりあえずJavaFXの開発環境ができてよかったです。
dired-modeにおけるQuick Lookの利用について (MacOS)

MacOSのFinder上でSPCを押すとQuick Lookが起動し、ファイルの中身をチラ見できるということは、MacOSユーザであれば周知のことだろう。

Emacsの`dired-mode`でそれを利用可能にした、という記事はいくつか見つかる。

- [What are the advantages of Emacs for Mac OS X users?](https://www.quora.com/Emacs/What-are-the-advantages-of-Emacs-for-Mac-OS-X-users)

- [Emacsのdiredからクイックルックを開く](http://y0m0r.hateblo.jp/entry/20120211/1328967193)

これらの記事では以下の関数が紹介されている：

```elisp
(defun do-ql-dwim ()
  (interactive)
  (let* ((proc (get-buffer-process "*Async Shell Command*")))
    (if proc
        (kill-process proc)
      (dired-do-async-shell-command
       "qlmanage -p 2>/dev/null" ""
       (dired-get-marked-files)))))
```
上記の関数を定義したあとで、dired-modeが有効になっているバッファで`do-ql-dwim`を実行すればQuick Lookを呼び出すことができる（カーソル下のファイルを対象に）。これでも悪くはないのだが、"**\*Async Shell Command\***"というバッファが別ウィンドウにポップアップし、そのまま残り続けるのが不満であった。

そこで以下の設定を書き、見た目の上では件のバッファがポップアップしないようにしたわけである。

```emacs-lisp
(with-eval-after-load "dired"
  (define-key dired-mode-map (kbd "SPC") #'dired-quick-look)
  (defun dired-quick-look ()
    (interactive)
    (let ((proc (get-buffer-process "*Async Shell Command*")))
      (if proc
          (kill-process proc)
        (dired-do-async-shell-command
         "qlmanage -p 2>/dev/null" ""
         (dired-get-marked-files))))
    (delete-window
     (get-buffer-window "*Async Shell Command*"))))
```

この設定では、`dired-mode`時に`SPC`とするとQuick Lookによるプレビューが利用可能になる。キーバインドは各自の好みで変更可能である。
ros2-rust動かしてみた

ros2-rustを動かしてみた報告と理解ができていない部分のまとめです。

(自分でもコミットできるかと思ったのですが、理解してない部分が多くて先に進めぬ。。。)

# 環境

- OS Ubuntu 20.04
- ROS **FoxyFitzroy** (Dashingでは何個かヘッダが見つからずビルドエラー)
- rustc 1.46.0
- cargo 1.46.0

# 準備

## Rustのインストール 

下記コマンドでインストールできます。

```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

インストール時に以下の画面出ますが1を選んでください。

```
1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
>
```

スクリプトがPATHを勝手に通してくれるのですが、一旦ログアウトしないと適用されないので、ログアウト&ログインしてください。

## 使用ツールのインストール

vcstool他必要なツールをインストールします。

```bash
sudo apt install python3-vcstool libclang-dev clang git
```

## ソースコードのインポート

(2020/10/29修正 wgetだけじゃインポートできなくなってた)

```bash
mkdir -p ~/ros2_rust_ws/src/ros2-rust
cd ~/ros2_rust_ws/src/ros2-rust
git clone https://github.com/ros2-rust/ros2_rust.git
cd ../../
vcs import src < src/ros2-rust/ros2_rust/ros2_rust.repos
```


# ビルド

あとは、いつものようにros2のビルドをすれば良いだけ。

```bash
source /opt/ros/foxy/setup.sh
colcon build
```

# 実行

Publisher端末

```bash
source ./install/setup.sh
ros2 run rclrs_examples rclrs_publisher
```

Subscriber端末

```
source ./install/setup.sh
ros2 run rclrs_examples rclrs_subscriber
```

実行結果はこんな感じ。

![コメント 2020-08-30 113634.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6898/c6d6180d-8b1c-59c8-c581-3ad4164355ac.png)


# この辺分からん

サンプル動かしてみただけなので、まだちゃんと読んでませんが、以下の部分理解してなかったり、知識不足です。。

知ってる方いたら教えてください。。。。

- ros2/common_interfaces, ros2/rcl_interfaces, ros2/rosidl_defaultsの3つのリポジトリの役割
    - おそらくidlの生成とかrclを自前で作るのに必要なリポジトリっぽい。あとで調べる
    - この辺の資料知ってる人居たら、コメント貰えると嬉しいです
- rcls_examplesのCargo.tomlにrclrsについての記述が無い(なぜ？)
    - おそらくammentやcolconの都合でこうなってるんだろうけど。。ぱっと見不自然。。

# 参考
ros2-rustのリポジトリ　https://github.com/ros2-rust/ros2_rust
【Kubernetes】マルチクラスタの最適なヘルスチェックとFailOverについての考察

## 概要
ここ最近関わっているプロジェクトで、
クラスタを安全にBlue/Greenで更新するためにマルチクラスタ構成にして冗長化する案件を推進していました。
クラスタの安全な更新とクラスタのHealth Check、Fail Overは切っても切れない関係にあります。
そこで得られた、どのような目的で、どのような構成でヘルスチェックするべきか、という1意見を記述してみます。

## 想定の構成

- GCPでGCLBの下にメインでルーティングするためのGKEクラスタと、レプリカクラスタを配備

- Istioが入っており、LBはまずIstio Ingress Gatewayにルーティングし、Ingress Gatewayでクラスタ内の各サービスにルーティング
 - (これによってGCLBからのトラフィックに対してもIstioのproxyルールを適用させる)

![base_architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45875/0ed4d4fc-4ac2-42eb-77c1-dac437d8d8c4.png)

## なぜクラスタを冗長化するのか？
クラスタのアップデート、Istioのバージョンアップデート時にダウンタイム無しで安全に更新するために冗長化しています。
InPlaceでUpdateするのではなく、
一度レプリカクラスタをLBから切り離して更新し、もう一度LBに紐づけ、
しばらく様子を見て問題なさそうならメインのクラスタも更新する、という方針をとっています。
またシステムのユーザへの影響を最小にするためにも、クラスタに問題があったときにまだ更新していないクラスタにちゃんとFail Overさせたいので、
ヘルスチェックの定義がとても重要になってきます。

## ヘルスチェックを定義する上での課題
本来クラスタ自体の更新といえども、どのサービスにどんな影響を与えるかは各サービス依存です。
例えば、クラスタの中にはバージョン依存のリソースを使っているサービスもあり、アップデートすると一部壊れてしまうかもしれません。

よって、

1. 各サービスごとに、問題があれば別クラスタにFail Overする
2. すべてのサービスが正常に稼働していなければ別クラスタにFail Overする

といったような方針で安全を担保することが考えられます。

しかし1は現状構成が複雑になりがちであり、
2に関していえば特定のサービスだけの障害がクラスタ全体に波及してしまうため論外です。

(たとえばあるサービスに障害が出たときに、クラスタ全体でFail Overされてしまい、仮にFail Over先もヘルスチェックに通っていなかったときにLBからみてルーティング先がなくなる)

とはいえ、クラスタ更新起因でサービスに障害が発生したときに検知してFail　Overする必要あります...

ではどうすればいいでしょうか？

## 採用した方針
ニーズに応じてヘルスチェックの内容を変えることにしました。

本来サービスの可用性は、CanaryやBlue/Greeなどを駆使してサービスのレイヤーで担保するべきであり、サービスすべての状態を検知する必要があるのはクラスタの更新中の間だけです。

よって、

- ヘルスチェック用のサービスを実装
  1. 全サービスのヘルスチェックを行い、すべて健康ならOK、そうじゃないならNGを返すエンドポイントを提供 ※1
  2. 何もせず200を返すエンドポイントを提供

- クラスタ更新中はGCLBのヘルスチェックは、Istio IngressGatewayを通して1のエンドポイントを見に行く
- 更新が落ち着いたらFeature Toggleなどで、GCLBが見るヘルスチェックエンドポイントを2に切り替える ※2

という方針を採用しました。

![new_health_architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45875/18ae1f99-65e4-9b26-c915-e9c339076b29.png)

これにより、クラスタ更新中はかなりシビアに全サービスをチェックし、
それ以外のときは、Istioの疎通だけ死んでいないことだけ担保して、サービスの可用性担保はサービスのレイヤに任せる、
といった方針を実現しています。

### 補足
- ※1 実施自体は裏で非同期で行い、エンドポイントに問い合わせが来たら最新のスナップショットから結果を返す
- ※2 Istio IngressGatewayを通すことでクラスタ全体でIstio起因で疎通が死んでいないことを担保する

## まとめ
今回、普段はクラスタはIstioの疎通まで担保できてたら健康とし、サービスごとの可用性はサービスに任せるという思想で、
見るべきヘルスチェックエンドポイントを切り替えるという方針を取りました。
アーキテクチャの良し悪しは運用してはじめて明らかになるので、しばらく運用して所感を別の機会に振り返りたいと思います。
AtCoder Beginner Contest 177 C問題「Sum of product of pairs」解説(Python3,C++,Java)

注意)解答例は<b>Python3</b>のみ出来ております。C++,Javaの方は「全ての提出」からコードを見て実装することをおすすめします。

皆さんこんにちは(コンテスト後の方はこんばんは！)Ruteです！

AtCoder Beginner Contest 177 C問題の解説をこれから始めます！
A問題,C問題の解説は以下のリンクより見ることが出来ますのでご確認下さい！！

##各問題の解説
|A問題|B問題|C問題|
|---|---|---|
|準備中|準備中|この記事です|

#問題概要
$N$個の整数$A_1,...A_N$で構成された数列が与えられる。
$1 \leq i < j \leq N$を満たす全ての組$(i,j)$についての$A_i×A_j$の和を$mod(10^9+7)$で求めよ。

問題URL :https://atcoder.jp/contests/abc177/tasks/abc177_c

##制約
・$2 \leq N \leq 2×10^5$
・$0 \leq A_i \leq 10^9$
・入力は全て整数

#解説
$A_1,...A_N$のうち、$(i,j)$の組は$(N-1)+(N-2)+....1$組あり、$\frac{N(N-1)}{2}$組あることが分かります。これらを$1$個ずつ考え計算していくと$O(N^2)$の計算量が必要になります。
一般的に、コンピューターで1秒間に処理できる計算回数はおよそ$10^8$回(1億回)なので制約上、この計算量では<b>実行時間制限</b>を超過してしまいます。

ここで、問題を別の視点で考えてみましょう。

入力例1・出力例1では、答えは$11$ですが、

答えについて、

```math
\sum_{i = 1}^{N-1} \sum_{j = i+1}^{N} A_i A_j
```

になることが分かっています。

そこで、まずは $\sum_{j = i+1}^{N} A_j$について求めることを考えます。

ここで用いるテクニックは<font color = "red"> <b>累積和</b></font>と呼ばれるものです。

累積和とは、あらかじめ初項からある項までの和を求め、それについての数列を作るというものです。

累積和で作成する数列の例としては、
数列$B$ : ($B_1,B_2, ... B_N$)が与えられた時、
$[0 , \sum_{i = 1}^{1} B_i , \sum_{i = 1}^{2} B_i , ... \sum_{i = 1}^{N} B_i ]$
というものがあります。

詳しくは、[けんちょんさんの累積和の記事](https://qiita.com/drken/items/56a6b68edef8fc605821)をご覧下さい。

今回、考える累積和としては、長さ$N-1$の数列
$[\sum_{j = 2}^{N} A_j , \sum_{j = 3}^{N} A_j , ... \sum_{j = N}^{N} A_j]$
です。
これは、数列Aの総和から$A_{j-1}$を引き続けて、その都度数列に値を挿入し続ければ作成することが出来ます。

これで、$\sum_{j = i+1}^{N} A_j$ の数列が出来ました。この数列を$C$とおくことにします。

次に、

```math
\sum_{i = 1}^{N-1} \sum_{j = i+1}^{N} A_i A_j
```

を求めるために、各$i(1 \leq i \leq N-1)$について$A_i × C_i$を計算します。
その値を、求める答えの値に加算していきます。

最後に、答えの値を$(10^9+7)$で割ったあまりを出力すれば良いです。

ここで、Pythonの場合は多倍長整数に対応しているのでその都度答えを$(10^9+7)$で割らなくても良いですが、C++やJavaの場合は、計算の途中で<b>64bit整数型の範囲よりも答えが大きくなる可能性があります。</b>(`long`や`long long int`など)(いわゆる<b>オーバーフロー</b>と呼ばれるものです)

なぜなら、 $2^{63}-1 \simeq 9.22×10^{18}$となりますが、$A_i$の制約より、$10^{18}$を$10$回以上足すケースがあることも考えられるからです。

結局、求める値は足したあとその都度$10^9+7$で割った余りにし続けても最終的には同じになるので、$10^9+7$で割った余りにし続ければ<b>オーバーフロー</b>を気にしなくてもよくなります。

計算量は累積和の処理で$O(N)$, 各$i(1 \leq i \leq N-1)$について$A_i × C_i$を計算するときに$O(1)$かかるので、$O(N)$となります。

以下、Pyhton3,C++,Javaでの解答例を示します.
(8/30 11:29時点　Python3の解答例のみ示しています。C++,Javaは準備ができ次第作成しますので、更新をお待ち頂きたいと思います)
<details><summary>Python3での解答例</summary><div>

```{ABC177C.py}
N = int(input()) #入力する整数
A = list(map(int,input().split())) #入力する数列A
SUMA = sum(A) #数列の和
MOD = 10**9 + 7 # mod
C = [0] * (N-1) #累積和数列
for i in range(N-1): #\sum_{j = i+1}^{N}を求めて数列に代入する
  SUMA -= A[i]
  C[i] = SUMA
ans = 0 #求める答え
for i in range(N-1):
  ans += A[i]*C[i]
  ans %= MOD #その都度modで割った余りにする
print(ans) #答えを出力する

#計算量はO(N)です。

```

</div></details>

<details><summary>C++での解答例</summary><div>

準備中です


</div></details>

<details><summary>Javaでの解答例</summary><div>

準備中です


</div></details>
PythonでAtCoder Beginner Contest 177 E - Coprime

# AtCoder Beginner Contest 177に参加しました
D完。E問題で詰まったので復習としてまとめをします。

# [E - Coprime](https://atcoder.jp/contests/abc177/tasks/abc177_e)
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667032/a167b076-1e53-422b-1049-f17f9ac6ab93.png)

## 本番中に考えたこと
実質「pairwise coprimeをどう判定するか？」という問題。
愚直にpairwiseで判定すると当然時間がかかるので素数ベースで考えるしかない。
要するに「すべての$A_i$について素因数が全くかぶらない」ということなので、$A_i$を素因数分解して出てきたものをカウント（p_cnt[$A_i$] に+1）していけばよさそう。
例：12→2・3、16→2、35→5・7なので、2が2回以上ありpairwiseではない
p_cntの最大値が1ならpairwise coprime、最大値がNならnot coprime、それ以外ならsetwise coprime。

ただし1を含む場合がコーナーケースなので、まず全部1ならpairwise coprime。
1, 1, 3, 6みたいに1以外がcoprimeでないならsetwise coprime、
1, 1, 3, 4みたいなケースならpairwise coprime。
したがって各$A_i$について考えるときに、それが1ならば個数をカウントしないようにする。

```python
# Nの素因数分解を辞書で返す
def prime_fact(n):
    if n == 1:
        return {1: 1}
 
    root = int(math.sqrt(n))
    prime_dict = {}
    for i in range(2, root+1):
        cnt = 0
        while n % i == 0:
            cnt += 1
            n = n // i
        if cnt:
            prime_dict[i] = cnt
        if n == 1:
            break
    if n != 1:
        prime_dict[n] = 1
    return prime_dict
 
 
def main():
    N = int(input())
    A = list(map(int, input().split()))
 
    if max(A) == 1:
        print("pairwise coprime")
        exit()
 
    p_cnt = defaultdict(int) # 素因数pが出てきた回数を記録
    for a in A:
        if a == 1: continue # 1の個数は数えてもしょうがないので無視
        AP = prime_fact(a)
        for apk in AP.keys():
            p_cnt[apk] += 1
 
    max_p = max(p_cnt.values())
    if max_p == 1:
        print("pairwise coprime")
    elif max_p == N:
        print("not coprime")
    else:
        print("setwise coprime")
```

1個（max_02.txt）だけTLEが取れない！！となりタイムアップ。

## 本番後に考えたこと
Cならともかく、Python(PyPy)では$N$が$10^6$もあると厳しい。
ここで、1,000,000以下の素数は78,498しかないことを利用することを思いつく。
すなわち$A_i$の種類($len(set(A))$)がだいたい8万以上の場合、鳩の巣原理からどこかの素因数に必ずカブリが発生してpairwise coprimeを満たさなくなる！！
なのでまず適当にgcdを取ってnot coprimeのケースを除外しておき、そのうえで8万種類以上あるケースをsetwise coprimeに突っ込むことで、Nを実質$10^6$から$10^5$くらいまで落とすことができる。

この枝刈りにより無事AC。


```python
def main():
    N = int(input())
    A = list(map(int, input().split()))
 
    if max(A) == 1:
        print("pairwise coprime")
        exit()
 
    # 全Aiの最大公約数が1より大きければnot coprime
    g = A[0]
    for a in A:
        g = math.gcd(g, a)
    if g > 1:
        print("not coprime")
        exit()
    
    # not coprimeでなく、Aが80000種類以上ならsetwise coprime
    SA = set(A)
    if len(SA) >= 80000:
        print("setwise coprime")
        exit()
 
    # 上記でないケースのみ頑張る
    p_cnt = defaultdict(int)
    cnt = 0
    for a in A:
        if a == 1: continue
        AP = prime_fact(a)
        for apk in AP.keys():
            p_cnt[apk] += 1
 
    max_p = max(p_cnt.values())
    if max_p == 1:
        print("pairwise coprime")
    else:
        print("setwise coprime")
```

より強いテストケースには負ける気がするのでおとなしく解説の高速化を使いましょう。
画像に合わせて点を打つ

# 概要
ログに記録されたタッチ座標をそれに対応する画面イメージにひたすらプロットする
・・・という苦行が発生したのでそれを自動化する。

なお、x軸、y軸が描画され、画像のサイズも変わります。
[Python - Python3 座標を画像の上にプロット｜teratail][5]
> plt.imshowにより、プロットされた画像を確認できたのですが、それを
> ...
> にてセーブすると、ピクセル数が変わってさらに余計な軸までついて、その周りに余白が現れます。

逆にそのほうが都合がいいという稀？なケース。
あとでわかったことですが、どうやらPillow(PIL)がなくてもできるようです。[リンク][4]

## コード

```py
import matplotlib.pyplot as plt
from PIL import Image

# Figureとaxの準備 ... matplotlibの定型的な処理
fig = plt.figure(figsize=(8, 6))
fig.patch.set_facecolor('white') #<--これはなくてもよさそう。図全体の背景色を設定するが、imageで塗られる形になるため。
ax = fig.add_subplot(1, 1, 1)

# 画像だと(0,0)が左上に来て, y軸の正の方向が下を向くのでinvert_yaxis()
# ax.invert_yaxis()と思ったけど、いらないようす。

# xとyはログから入手したタッチ座標。ここでは、暫定的に左上、中央、右下を指定している
x = [0, 400, 200]
y = [0, 300, 150]

# タッチ座標をプロットする
ax.scatter(x, y, c='red', s=20)


# 背景に画面イメージを出す
im = Image.open("aaaa.png")
ax.imshow(im)

# プロット画像を保存する
plt.savefig("aaaa_plot.png")
```

元の画像(aaaa.png)・・・ペイントで適当に作った400x300の画像
![aaaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34777/5406d69a-3850-3a3a-dd75-adcbcc20d0ff.png)

プロット後(aaaa_plot.png)
![aaaa_plot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34777/3052b8a8-d758-b6e0-6511-c8ff96009a7b.png)


## コード2 -- Pillowなし

```py
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import pathlib

# 画像を読み込んでおく
f = cbook.get_sample_data(pathlib.Path("aaaa.png").absolute())
im = plt.imread(f)

# Figureとaxの準備 ... matplotlibの定型的な処理
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(1, 1, 1)

# 理由はわからないが、ax.invert_yaxis()を呼ばなくてもy軸は下を向く

# xとyはログから入手したタッチ座標。ここでは、暫定的に左上、中央、右下を指定している
x = [0, 400, 200]
y = [0, 300, 150]

# タッチ座標をプロットする
ax.scatter(x, y, c='red', s=20)

# 背景に画面イメージを出す
ax.imshow(im)

# プロット画像を保存する
plt.savefig("aaaa_plot2.png")
```


## 備考
この苦行、既視感があるな・・・と思ったら↓も近いやつだった。
[正規表現にマッチした部分をExcelに書き出す + プロットする - Qiita][2]
このときは画像に合わせる必要がなかった＋他の人が生データを見る都合上、Excelにしてた。

## 参考
[matplotlib - imshow で画像や配列を表示する方法 - Pynote][1]
[matplotlibのめっちゃまとめ - Qiita][3]
[python - matplotlib：画像imshowの座標をプロットと互換性がない - stackoverrun][4]
[AxesDivider — Matplotlib 2.0.2 documentation][6]
[1]:https://www.pynote.info/entry/matplotlib-imshow
[2]:https://qiita.com/int_main_void/items/f59d9e9f2a8d8f9c6b51
[3]:https://qiita.com/nkay/items/d1eb91e33b9d6469ef51
[4]:https://stackoverrun.com/ja/q/10393572
[5]:https://teratail.com/questions/139505
[6]:https://matplotlib.org/mpl_toolkits/axes_grid/users/axes_divider.html
Ruby で解く AtCoder ABC177 D UnionFind

# はじめに
*[AtCoder Problems](https://kenkoooo.com/atcoder/#/)* の Recommendation を利用して、過去の問題を解いています。
AtCoder さん、AtCoder Problems さん、ありがとうございます。

# 今回のお題
*[AtCoder Beginner Contest D - Friends](https://atcoder.jp/contests/abc177/tasks/abc177_d)*
<font color="brown">Difficulty: 676</font>

今回のテーマ、UnionFind

典型問題の *[B - Union Find - AtCoder](https://atcoder.jp/contests/atc001/tasks/unionfind_a)* の応用です。
# Ruby
```ruby.rb
class UnionFind
  def initialize(n)
    @parents = Array.new(n, -1)
  end
  def find(x)
    @parents[x] < 0 ? x : @parents[x] = find(@parents[x])
  end
  def parents
    @parents
  end
  def union(x, y)
    x = find(x)
    y = find(y)
    return if x == y
    if @parents[x] > @parents[y]
      x, y = y, x
    end
    @parents[x] += @parents[y]
    @parents[y] = x
  end  
end

n, m = gets.split.map(&:to_i)
u = UnionFind.new(n)
m.times do
  a, b = gets.split.map(&:to_i)
  u.union(a - 1, b - 1)
end
puts -u.parents.min
```
```sub.rb
    @parents = Array.new(n, -1)

    @parents[x] += @parents[y]
```
配列`@parents`に初期値`-1`を代入します。
次に、ペアとなった配列の初期値`-1`を加算します。
これを繰り返すことで、ペアの集合の要素数を取得することができます。

```sub.rb
@parents = [-3, 0, -2, 2, 0]
```
`入力例 1`の場合、マイナスの数値を見ますと、`3`と`2`のグループに分かれることが分かります。
よって出力は、グループの要素が大きい方の`3`になります。

||Ruby|
|:--:|:--:|
|コード長 (Byte)|548|
|実行時間 (ms)|260|
|メモリ (KB)|15824|
# まとめ
+ ABC 177 D を解いた
+ Ruby に詳しくなった

参照したサイト
*[AtCoder Beginner Contest 177 参戦記](https://qiita.com/c-yan/items/0414c435ed8259ea15db)*
GroupByのメモ

#DataFrameの作成
```ruby:qiita.rb
df = pd.DataFrame({'Animal': ['Falcon', 'Falcon',
                              'Parrot', 'Parrot','Parrot'],
                   'Max Speed': [380., 370., 24., 26.,27.],'Annimal_ID': [1, 1,2,2,2]})

df
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/9866e4ee-6cfc-9f34-f0e5-8afca78b63d0.png)

#Groupby
同じグループに対して処理をしたいときに使用する。

###平均
```ruby:qiita.rb
#FalconやParrotのグループに対して同じ処理をしたいときに使用する
df.groupby(['Animal']).mean()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/01366e3c-607a-19c6-1ac9-2ffe4e3ba052.png)

###サイズを調べる・取得する
```ruby:qiita.rb
#サイズを調べる
df.groupby(['Animal']).size()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/24577770-f829-5081-4c05-4f98bdaa2774.png)

```ruby:qiita.rb
#サイズの取得
Falcon_num=df.groupby(['Animal']).size()['Falcon']
print(Falcon_num)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/9062b987-1147-99ec-b7b9-1a58972bb539.png)

###特定のグループのデータ取得
```ruby:qiita.rb
#サイズの取得
#特定のグループのデータの取得
df.groupby(['Animal']).get_group('Falcon')
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/c0a7208f-77aa-de18-da17-9a9d554ebb5a.png)


#参考
[GropuBy](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.groupby.html)
Flutter/DartでBitfinexのレンディングアプリを作る(Part2 stateful/データの永続化)

---
# :book: Flutterの記事を整理し本にしました :book:
https://zenn.dev/kazutxt/books/flutter_practice_introduction

* <font color="red"><b>本稿の記事を含む様々な記事を体系的に整理し本にまとめました</b></font>
* 今後はこちらを最新化するため、<font color="red"><b>最新情報はこちらをご確認くださ</b>い</font>
* 10万文字を超える超大作になっています(笑)

---

# はじめに
* この記事は、初めてのスマホアプリを作るまでの軌跡を残したものです。
* この記事では、stateless/statefulとshared_preferencesを用いたデータの保存を紹介します

## 関連記事

https://qiita.com/kazutxt/items/e4f3bbb4d8b301f4141c

# 画面の再描画
* Dartでは、画面の再描画を行うか行わないかで、使うクラスが異なります。
    * StatelessWidgetを継承するとbuildが一度しか呼ばれず、静的な(イミュータブルな?)ページになります
    * StatefulWidgetとStateクラスを用いると、buildが繰り返し呼ばれ画面が再描画される動的な(ミュータブルな画面)になります。
* 公式ドキュメントを読むと、statelessもstatefulもどちらも不変オブジェクトと書かれています
    * statelessは完全な不変オブジェクト
    * statefulはStateクラスのジェネリクスにStatefulのクラスを指定することで利用します
        * Stateクラスを継承したクラスのbuildが繰り返し呼ばれ、状態を保てます

``` stateless.dart
class Info extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("info"),
      ),
      body: Center(child: Text("使い方、更新情報など")),
    );
  }
}

```


``` stateful.dart
class Info extends StatefulWidget {
  @override
  _InfoState createState() => _InfoState();

  Widget build(BuildContext context) {
    return Info();
  }
}

class _InfoState extends State<Info> {
  String _value = "";
    return Scaffold(
      appBar: AppBar(
        title: Text("info"),
      ),
      body: Center(child: Text("使い方、更新情報など")),
    );
}
```
## 初期状態と状態の変え方
### 初期状態
* initStateメソッドが最初に呼び出されるので、ここを書き換えます

``` initState.dart
@Override 
void initState(){
  super.initState();
  //ここに独自の処理を入れる
}
```

### 状態の変更
* setStateメソッドで明示的に再描画させることができます

``` setState.dart
if (mounted) {
  setState(() {
    value = "変えたい値";
  });
}
```
* mountedをチェックしているのは、再描画のときに画面の構築が不完全な?な時がありエラーがでるので、ドキュメントにはmountedを調べてから書き換えるのを推奨としているためです。

# データの保存
* 画面から入力された値を永続化するニーズはたくさんあると思います。
    * DBに入れるなども解決策がありますが、手軽なshared_preferencesを使う例を紹介

``` sharedpref.dart
SharedPreferences prefs = await SharedPreferences.getInstance();

prefs.setString("key",value); // 登録
prefs.getString("key") // 取得
prefs.remove("key") // 削除
```

* pubspec.yamlのdependenciesにshared_preferencesを記述するのをお忘れなく
    * アプリ内で共有されるので、別の画面からももちろん呼び出せます
Rails Tutorial　第12章 完了

##2020/8/22 1.5時間
12.1.2まで進めました。
##2020/8/23 2.0時間
12.3.2まで進めました。
##2020/8/24 0.5時間
リスト12.18の途中まで進めました。
##2020/8/25 0.5時間
##2020/8/26 0.5時間
リストの入力間違いでエラーになっていたのをデバッグしてやっと動きました。テキストから手打ちしていると、入力ミスで結構バグが出ることが分かります。
##2020/8/27 0.5時間
##2020/8/28 1.0時間
##2020/8/29 4.0時間
うち1.5時間はSendGridのエラー調査です。
##2020/8/30 0.5時間
Sendgridはあいからずエラーですが、先に進めることにしました。

12章を完了です。
所要時間は11.0時間です。

##digestは作るたびに違う値になる
tokenが同じ値ならdigestは何度作っても同じなのかと思ったのですが、2回実行してみたところ違う値になっていました。

```bash
>> a.password_digest
=> "$2a$10$92Y.9S6JdU9HutSoZu6TdOSDFHsodZ5PJKZfzBxmflqIYNwuUA6Su"

>> a.password_digest
=> "$2a$10$yZ9mPXl/uWJF1czSLso9yejl7A4ALE9HvRWJOuozwLldjb98vT1yO"
```

##SendGridのAddonの追加でエラーになった件は解消
8/19にSendGridのAddonの追加でエラーになった件は、8/29になぜか解消していました。
前回リンクを貼ったネットの他の方と同じです。

>理由は以下のどちらかだと推測します。 
>1.時間が立ったことによりバグ？のようなエラーが修正された
>2.第12章まで進めることでエラーを回避できる 

```bash
ubuntu:~/environment/sample_app (master) $ heroku addons:create sendgrid:starter
Creating sendgrid:starter on ⬢ fathomless-mesa-1xxxx... free
Created sendgrid-crystalline-46xxx as SENDGRID_PASSWORD, SENDGRID_USERNAME
Use heroku addons:docs sendgrid to view documentation

ubuntu:~/environment/sample_app (master) $ heroku config:get SENDGRID_USERNAME
app173xxxx@heroku.com
ubuntu:~/environment/sample_app (master) $ heroku config:get SENDGRID_PASSWORD
uxxxxxxx78xxx

```

##SendGridで違うエラー　Authentication failed: 
メールを送るところで、違うエラーになりました。

```bash
.. Completed 500 Internal Server Error in 606ms (ActiveRecord: 42.2ms)
..ArgumentError (SMTP-AUTH requested but missing secret phrase):
..app/models/user.rb:59:in send_activation_email'
..app/controllers/users_controller.rb:23:in `create'
```

入力間違いに気が付き修正しました。
誤：user_password
正：password


```ruby:config/environments/production.rb(誤)
 ActionMailer::Base.smtp_settings = {
    :address          => 'smtp.sendgrid.net',
    :port             => '587',
    :authentication   => :plain,
    :user_name        => ENV['SENDGRID_USERNAME'],
    :user_password    => ENV['SENDGRID_PASSWORD'],
    :domain           => 'heroku.com',
    :enable_starttls_auto => true
```

再実行したところ、違うエラーになりました。

```bash
..Net::SMTPAuthenticationError (535 Authentication failed: account disabled
```

ネットで他の方を調べたところ、SendGridでアカウントを一時凍結された方がいたので、時間をおいて試してみることにしました。
Apache2: Let's Encrypt で SAN 証明書を使う

SAN（Subject Alternative Name）証明書の使い方です。
Ubuntu 20.04 で確認しました。

コマンドのインストール

```bash
sudo apt install certbot
```

次の４つのドメインが同じIPに割り当てられているとします。
>test.example.com
test2.example.com
test3.example.com
test4.example.com


証明書の取得

```bash
folder="/var/www/html/public_test"
mail="admin@example.com"

certbot certonly \
        --webroot -w $folder -d test.example.com \
        --webroot -w $folder -d test2.example.com \
        --webroot -w $folder -d test3.example.com \
        --webroot -w $folder -d test4.example.com \
        --email $mail
```

このコマンドを実行すると、
/etc/letsencrypt/live/test.example.com
に証明書が作成されます。

Apache2 の設定ファイル

```text:/etc/apache2/sites-available/test.example.com-le-ssl.conf
<IfModule mod_ssl.c>

<VirtualHost *:443>
        ServerName test.example.com
        ServerAlias test2.example.com
        ServerAlias test3.example.com
        ServerAlias test4.example.com
        DocumentRoot /var/www/html/public_test

        ErrorLog ${APACHE_LOG_DIR}/error_ssl.log
        CustomLog ${APACHE_LOG_DIR}/access_ssl.log combined

        <Directory /var/www/html/public_test>
        AllowOverride none
        Require all granted
        </Directory>

SSLCertificateFile /etc/letsencrypt/live/test.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/test.example.com/privkey.pem

Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>

</IfModule>
```

シンボリックリンクの作成

```bash
cd /etc/apache2/sites-enabled
sudo ln -s ../test.example.com-le-ssl.conf .
```

設定の確認

>```bash
sudo apache2ctl configtest
```

Apache2 の再起動

>```bash
sudo systemctl restart apache2
```

証明書の取得は次のようにすることもできます。

```bash
folder="/var/www/html/public_test"
mail="admin@example.com"

certbot certonly \
        --apache -d test.example.com \
        --apache -d test2.example.com \
        --apache -d test3.example.com \
        --apache -d test4.example.com \
        --email $mail
```

次のライブラリーをインストールする必要があります。

```bash
sudo apt install python3-certbot-apache
```
Automation Anywhere Version 11で意外に知られていない機能

# はじめに
Automation Anywhere Ver11で途中から追加された、紹介資料が少ない、などの理由で、意外に知られていないのでは？という機能を紹介します。
「知られていない」ってのは私の主観なので、ご存じでしたら笑い飛ばしてください。

# 辞書型の変数
変数の型として途中から辞書型がサポートされています。タスク(bot)の途中で簡単にキーを追加できない等扱いにくい部分もありますが、ちょっとした情報保持には便利です。

# Excelのセッションを親・子のタスクで共有する
親タスクでOpenしたExcelのセッションを、子タスクで共有することができます。Open SpreadsheetでShare Sessionにチェック

#メールサーバのEWS
これ追加されていろいろと助かりました。
でもこれは基本の設定なので「知られていない」にはならないか...

# ウィンドタイトルの一括置換
以下にすばらしい記事があります。
https://qiita.com/zamaezaaa/items/f2a71c6fcb60c2d5eb78

# Object CloningのSelect Technology
これも次の記事を。
https://qiita.com/RPAbot/items/477c783ef5c2f8e91d9b

いや、あまり使い分けを意識した事ないんですけれどね。

# さいごに
「おっ！」と思った機能がもっとあったかなと思いましたが、書き出してみると少なかったですね。おもしろいもの気づいたら追加します。
尊厳死に対する事前指示書（リビングウィル）に電子署名をしてみた


# はじめに

日本には尊厳死に関する法律がありませんが、事前に本人が意思表明をしておくことで一定の効力が期待できるそうです。しかし、生死に関わることですので意思表明における信頼性が担保されていることが、本人や家族、医師にとって非常に重要です。

事前指示書の作成には公正証書として記録する方法が一般的なようですが、今回は少し手軽に電子署名を使った方法で試してみました。

# 環境

- macOS 10.15.6
- Adobe Acrobat Pro DC 2019.21.20058.359605

# 手順

## 事前指示書をPDFとして作成する

こちらのページの例文を参考にしました。

[終末期の医療・ケアについての事前指示書の例文 - リビング・ウィルと事前指示書 -書き方と例文-](http://square.umin.ac.jp/~liv-will/new1017.html)

Google Docsにコピペして体裁を整え、自分の意思に合わせて一部内容を修正します。

![FireShot Capture 043 - 終末期の医療・ケアについての事前指示書 - Google ドキュメント - docs.google.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55365/5e523029-50ad-c8e0-fde7-5cca8f02b94b.png)
https://docs.google.com/document/d/14HxZFImTgo-tRsQJ98-kdcl-TNB2qCO6mduE6zJVmDY/edit?usp=sharing

完成したらPDFとして出力しておきます。

## Adobe Acrobat DCで電子署名をする

下記のページを参考に、署名と証明書発行を行いました。

[[基本操作]　PDF ファイルに電子署名を追加する](https://helpx.adobe.com/jp/acrobat/kb/235107.html)

「署名後に文書をロックする」というチェックボックスが表示されますが、これはPDFを読み取り専用にするということです。これにより他の署名を追加できなくなるため、最後に署名する人はチェックを入れておくと良いでしょう。（今回は家族の署名を省略しているので自分でチェックを入れました）

![スクリーンショット 2020-08-30 9.21.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55365/bd3a419b-f526-9a4e-c946-c186a9c1bd52.png)

署名後は再度PDFとして出力します。

## 署名済みの事前指示書を配布する

電子署名の仕組みには公開鍵暗号方式が用いられています。そのため、署名（暗号化）の際に使った鍵ペアから公開鍵を証明書として書き出すことで、信頼性を証明することができます。こちらも、先ほどの記事の手順にそって証明書ファイル(`.fdf`)を出力しておきました。

今回はGoogle Driveを使って配布を行います。ライフサイクルに応じて文章を更新する場合があると思うので、必ずフォルダ単位で共有するようにしたいと思います。

![スクリーンショット 2020-08-30 9.44.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55365/817fd369-7316-804f-6918-4aca2d5fde3f.png)
https://drive.google.com/drive/folders/1pnCqFogXOdPdjUjxZE_dQGZ73lCh6puS?usp=sharing

情報を辿りやすいよう、[Notion上の自分の公開Wiki](https://www.notion.so/nkjzm/f7c58881a3a34a94a0f3e64b8034226d)にもまとめておきます。
![スクリーンショット 2020-08-30 10.14.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55365/be51eaf4-8e5a-96a7-e88a-89375d2c942c.png)
https://www.notion.so/nkjzm/3253c053e2a14bcfb9ed48d4e45e23d3

最後にこのページを家族に共有して終わりです。

## 考えられる脆弱性

電子証明書自体は公開鍵によって証明できますが、署名に使っている鍵ペアは自身のPC上で作成したものであるため公開鍵自体の信頼性は自分で担保する必要があります。そのため、公開鍵毎差し替えらた場合はなりすましや改竄等のリスクがあるといえるでしょう。公開鍵を配布しているGoogle DriveやNotionの扱いには十分に注意する必要がありそうです。

# 最後に

理解が誤っている部分などあれば、ぜひご指摘いただけると嬉しいです。

最後に自己紹介です。普段から自分の人生をインターネットで公開しています。よかったら是非フォローしてください！ 
Twitter: [@nkjzm](https://twitter.com/nkjzm)
ros2 でgeometry msgsがないよと言われたときの備忘録

#確認事項
cpp
[x] include <geometry_msgs/msg/pose.hpp>
CmakeLists.txt
[x] find_package(geometry_msgs REQUIRED)
[x] ament_target_dependencies(hoge rclcpp geometry_msgs)
Package.xml
[x] package.xml <depend>geometry_msgs</depend>



```main.cpp
//どっちでも良い
#include "geometry_msgs/msg/pose.hpp"
#include <geometry_msgs/msg/pose.hpp>
//これはros1
x #include <geometry_msgs/pose.h>
```


```CmakeLists.txt
//find packageしてる？
find_package(geometry_msgs REQUIRED)
//dependencyに追加してる？
ament_target_dependencies(hoge rclcpp geometry_msgs)
```

```package.xml
  <!--dependに追加してる？-->
  <depend>geometry_msgs</depend>
```

```
colcon build --symlink-install --packages-select hoge
>
Starting >>> hoge
Finished <<< hoge [5.23s]
Summary: 1 package finished [6.09s]

```

ハマると時間食うのでどなたかのお役に立てれば。。。
これいらないよとかこれ便利だよとかあれば教えてください。
ActiveRecord::NotNullViolation in Deviseエラー

【概要】
----------------------------------------
<b>1.結論</b>

<b>2.ActiveRecord::NotNullViolationtとは何か</b>

<b>3.なぜActiveRecord::NotNullViolation in Deviseになるのか</b>

<b>4.どのように解決するか</b>

<b>5.補足</b>



1.結論
----------------------------------------
db/migrate/""""_devise_create_""""".rbに
記載してある<b>"t.string password(またはpassword_confirmation)"</b>の記載を削除する！

<br>
2.ActiveRecord::NotNullViolationtとは何か
----------------------------------------
![スクリーンショット 2020-08-29 20.47.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686400/bca5d65d-6e68-38dd-9c23-ea48913dca06.png)

この意味は、<b>「DBの規則上、空欄（NULL）にしてはいけない項目がデータで保存されかけましたよ！そんなことしちゃいけませんよ！」</b>という機械からのご指摘です！

<br>
3.なぜActiveRecord::NotNullViolation in Deviseになるのか
----------------------------------------
2.と掛け合わせると、「デバイスでDBの規則上、空欄（NULL）にしてはいけない項目がデータで保存されかけましたよ！コントローラーで指示されてDBで保存して登録されかけたときだよ!」と行っています。

なぜこのようなことになるかというと、gem'devise'がわざわざpasswordを作ってくれたのに、
被せて作ろうとしているのでどっちのpasswordがいいかわからずNULLになったと思われます！

gem'devise'というものはpasswordとそれに対するpassword_confirmationを作ってくれるgemです！


なので

```ruby:db/migrate/""""_devise_create_""""".rb
t.string :password null:false"(password_confirmation)
```
をプログラムしてカラムを作成する必要はないんです！

<br>
4.どのように解決するか
----------------------------------------


```ruby:db/migrate/""""_devise_create_""""".rb
t.string password,  null:false"
(またはpassword_confirmation)
```
と記載されていると思うので削除しましょう！
<br>

5.補足
----------------------------------------
ちなみにgem'devise'にはpasswordに対してもう一つ付け加えれれている機能があります！

それは<b>バリデーション</b>です！

6文字以上にしなければ、入力ができないように制限が既に機能として備わっているので、

```ruby:model/user
validates :password, length { minimum: 5 }
```
を記載する必要がなくなります！
<br>
【Rails】NoMethodError: undefined method `new' for BigDecimal:Classの対処法

#はじめに
`NoMethodError: undefined method 'new' for BigDecimal:Class`の詳しい対処法が日本語であまり載ってなさそうなので、備忘録として残しておきます。

#対処法
結論として
`Gemfile`の`bigdecimal`を下記内容に修正したら、うまく行きました。

```
gem 'bigdecimal', '1.3.5'
```

gemの内容を書き換えたのでその内容を反映させるために、`bundle install`を行なってください。

```
$ bundle install
```

#意味

|バージョン  |特徴  |サポートされているRubyのバージョン範囲  |
|---|---|---|
|2.0.0  |BigDecimal.newとサブクラス化の使用ができない  |2.4 ..  |
|1.4.x  |BigDecimal.newとサブクラス化を使用の際、警告がいつも表示される  |2.3 .. 2.6  |
|1.3.5  |警告なしでBigDecimal.newとサブクラス化を使用できる  |.. 2.5  |
		

参考
https://stackoverflow.com/questions/60226893/rails-nomethoderror-undefined-method-new-for-bigdecimalclass
https://github.com/ruby/bigdecimal#which-version-should-you-select
監視をメールからslackに変えてみた

#監視をメールからslackに変えてみた

初めての投稿なのでtestも兼ねて記載
# 目的

サービスの監視として、いつもメールでエラーを送っていたのですが、メールを見ることが減ってきたのと、テストサーバーからのメールが届かない（迷惑メールとして処理）されてしまうことがあるため、slackのapiを使って日々の運用業務の簡易化と自動化を考えてみる。
ここではslackapiの方法を記載する。

## 前提条件
slackの登録。○○.slack.com　が存在すること

- webhookの登録
- apiのテストリクエスト
    - apiの便利な機能
        - チャンネル指定
        - ユーザー指定
        - メンション方法
- スクリプトの作成