OmniAICreator/Qiita-1.07M huggingface dataset:
AzureでBot開発ってどうやる？参考記事でお勉強（高専キャリア×Microsoft クラウドAI開発講座#2）

ハム川です

今週のクラウドAI開発の進捗をまとめます

#1. 概略
de:code2020やQiitaでひたすらお勉強した。気になる、参考にしたい技術をピックアップした。
ソース: de:code2020[(1)](https://www.microsoft.com/ja-jp/events/decode/2020session/detail.aspx?sid=Z01) [(2)](https://www.microsoft.com/ja-jp/events/decode/2020session/detail.aspx?sid=A02)や[ちょまどさん](https://qiita.com/chomado/items/6bda10abde0551f25723)と[おーちょさん](https://qiita.com/miokawa/items/6f1a3e480580e1e29abc)のQiita


#2. 学習内容
##de:code Z01
###要旨
学生向けにクラウドやAzureの魅力とその導入と魅力を紹介している。
特にPaasのAzure Cognitive Services（機械学習による認識技術） と、 Azure Machine Learning（機械学習）に焦点を当てている。
例として顔認識APIを利用したゲームのデモンストレーションを紹介している。
（スライドはドラクエのような雰囲気で面白く、読みやすかった）
###Azure Cognitive Services
####どんなもの？
各種認知、認識のうち特に需要の高いものをまとめたサービス。AI開発経験がない人でもAPIを叩くだけで目的のデータを得られる。
####サービス例
音声->テキスト変換、物体検出、認識、文章分析
####特徴
学習モデルの作成の上で面倒なデータセットの作成、楽手モデルの作成、調整の作業をやらなくてよい
###Azure Machine Learning
####どんなもの？
開発者のレベル別にオリジナルAI作成のための開発手法を提供している。
####サービス例
- デザイナー
　コードを書かずとも開発可能（GUI）
- ノートブック
　PythonやR言語で各種フレームワークやAPIを利用してコードを書いて開発
- 自動ML
　デザイナーとノートブックの間くらい。

####特徴
Azure Cognitive Servicesではできないオリジナルのデータセットに対する学習をするならこのサービスを使うのがよいだろう。
###参考にしたい技術
botを開発する上でAzure Cognitive ServicesのText Analyticsは必須だろう。

##おーちょさんのQiita
AzureのBot FrameworkとCognitive Serviceを利用してLINEでのやさしいBot開発の備忘録。
非常に細かく手順を説明しているため、このまま踏襲することで勉強になる。

##de:code A02
###要旨
ちょまどさんによるAzure Bot ServicesでTeams bot開発
Azureでのbot開発の入門編。サービスの紹介から具体的な開発の過程まで入門編として非常にわかりやすいスライド
###bot開発に使えるMicrosoftサービスの例
*Azure Bot Services*: bot開発の統合開発環境
*Bot Framework*: bot開発のフレームワーク
###簡単なbot開発の詳細過程（図は[(2)](https://www.microsoft.com/ja-jp/events/decode/2020session/detail.aspx?sid=A02)から引用）
####1. エミュレータから接続（ローカル）
ローカル環境でTeamsやLineのような*エミュレータ*と*ローカルサーバ*(Visual Studioから実行)でやりとりする。
![Azure Bot Services を使って Teams bot を開発する - Google Chrome 2020_07_12 22_05_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469182/cab9ccd1-9a97-2683-f685-42f12188278c.png)

####2. Teamsから接続（ローカル）
エンドポイントの設定などをAzure上で行い、入力である対話もTeams上で行う。
![Azure Bot Services を使って Teams bot を開発する - Google Chrome 2020_07_12 22_05_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469182/884e8d91-655c-5b39-c6c2-893e77aa1350.png)
####3. Teamsから接続（クラウド）
ローカルで開発したbotをデプロイしてAzure上で全部完結させる。
![Azure Bot Services を使って Teams bot を開発する - Google Chrome 2020_07_12 22_05_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469182/e13ee1e4-3188-812f-7fd8-cce209fc1e7d.png)

###参考にしたい技術
詳細な開発は一度踏襲しやってみると感触を確かめることができそう。

##ちょまどさんのQiita
実際に自分で動かしてみるべき非常に細やかな説明がされている記事。後日やってみる。

#次週に向けて
来週は実際にAzureに触れる。ちょまどさん、もしくはおーちょさんのQiitaを参考に実際に触っていじって、感触を確かめてそれをまとめる。
vagrant + VirtualBox でCentOS7の環境を作成

個人マシンの開発でもお手軽に検証環境の構築を可能としますが
チームで作業する場合に、同じ構成の検証環境を個人マシンで簡単に構築する事ができます

インストール方法は下記の２パターンのどちらかを選択して下さい

#インストール(Homebrewを使わない場合)
VirtualBoxを下記からダウンロードしてインストールする
https://www.virtualbox.org/wiki/Downloads
vagrantを下記からダウンロードしてインストールする
https://www.vagrantup.com/docs/installation
GUIでvagrantを操作したい場合はvagrant-managerをインストールする
https://www.vagrantmanager.com/

#インストール(HomebrewとHomebrew caskインストール済みの場合)
VagrantとVirtualBoxのインストール

```
$ brew cask install vagrant
$ brew cask install virtualbox
```


GUIでvagrantを操作したい場合はvagrant-managerをインストールする

```
$ brew cask install vagrant-manager
```

#CentOS7環境の作成

###boxの追加
boxとは仮想マシンのテンプレート(ひな形、ベース)となるファイルです。
これを利用する事で手軽に環境の構築を行う事ができます。

下記サイトで作成した環境のboxを探します
https://app.vagrantup.com/boxes/search

CentOS7のboxを追加します
途中で選択肢が出てきますが、Virtual Boxで環境構築しますので、「３」を選択します

```
$ vagrant box add centos/7
==> box: Loading metadata for box 'centos/7'
    box: URL: https://vagrantcloud.com/centos/7
This box can work with multiple providers! The providers that it
can work with are listed below. Please review the list and choose
the provider you will be working with.

1) hyperv
2) libvirt
3) virtualbox
4) vmware_desktop
```

ローカルのboxに追加されたことを確認します

```
$ vagrant box list
centos/7 (virtualbox, 2004.01)
```

###初期化
任意のディレクトリを作成＆移動して、初期化を行います

```
mkdir -p 任意のディレクトリ
cd 任意のディレクトリ
vagrant init centos/7
```

vagrant initのコマンドを発行した際のカレントディレクトリにVagrantfileが作成されます。
Vagrantfileは仮想マシンを作る際の設定ファイルになります。
ネットワークの設定やその他の各種設定を行う事ができます。

仮想マシンの状態を確認します
「not created (virtualbox)」とあり、まだ仮想マシンは作成されていません

```
$ vagrant status
Current machine states:

default                   not created (virtualbox)

The environment has not yet been created. Run `vagrant up` to
create the environment. If a machine is not created, only the
default provider will be shown. So if a provider is not listed,
then the machine is not created for that environment.
```

###起動
仮想マシンの起動します
先ほど作成したVagrantfileを格納しているディレクトリに移動してコマンドを実行します

```
$ vagrant up
```

仮想マシンの状態を確認します
「running (virtualbox)」となっています
VirtualBoxを起動して表示して見ると、仮想マシンが新しく作られて実行中になっています

```
$ vagrant status
Current machine states:

default                   running (virtualbox)

The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.
```

###ログイン
仮想マシンにログインします
vagrantユーザーでログインすることになります

```
$ vagrant ssh
```

vagrantユーザーでログイン後にrootユーザーで作業する場合のパスワードは「vagrant」です。

###シャットダウン
仮想マシンをシャットダウンします

```
$ vagrant halt
```

シャットダウンすると「poweroff (virtualbox)」となります

```
vagrant status
Current machine states:

default                   poweroff (virtualbox)

The VM is powered off. To restart the VM, simply run `vagrant up`
```

###ディレクトリ構成
仮想マシンの実態はデフォルトでは下記にあります
```
ホームディレクトリ/VirtualBox VMs/centos7_default_1594559457009_7794
下記のようなディレクトリ構成になります

```
$ cd ホームディレクトリ/VirtualBox VMs/centos7_default_1594559457009_7794
$ ls
Logs
centos-7-1-1.x86_64.vmdk
centos7_default_1594559457009_7794.vbox
centos7_default_1594559457009_7794.vbox-prev
```
AWS Hands-on for Beginners Network編#1 実施時の所感

## 概要

[AWS Hands-on for Beginners Network編#1](https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-Network1-2020-reg-event-LP.html?trk=aws_introduction_page)を先日実施したのでその所感などをまとめてみます。
以下の人におすすめです。

* AWSの勉強をしようとしている人
* 資格を取るために勉強中の人
* あまり実務経験がない人

## 学べる内容
このハンズオンで学べる内容としては
* public subnet と private subnet について
* VPC内から外部のインターネットに接続する方法
* VPC内から外部からの接続は禁止にして内部からの接続のみ可能にする方法
* VPCエンドポイントの使い方

とVPCの基本を学ぶことができます。
Udemyのハンズオンなどでもこのあたりは学べますが、エンドポイントについての説明など細かくしていただけるので理解を深めるのによいかと思います。

## 引っかかったポイント
私が実施した際に引っかかったポイントです。

* privateLinkを使ってSSMとの接続を行うところでエンドポイントの設定の反映が時間がかかったようで最初エラーになりました。
    * インスタンス起動の時など時間がかかるポイントではコンソールで反映されてもちょっと待った方がよさそうです。
de:code 2020 個人メモ

# はじめに
* 日本マイクロソフト社のカンファレンス「de:code 2020」について、（内容が偏っていますが）個人的に気になった点について簡単に記載します。

# まとめ
## [K01 基調講演の抜粋版] Cyber Security
### Azure Active Directory External identities
* ディレクトリ外のユーザについて、Face book IDといった Consumer ID によりディレクトリで管理するアプリケーション等にアクセスできるようにする。
  * Azure AD B2Cの拡張版に近いとの理解。
  * 今までは以下のように使い分けられていたが、External identities で事前に定義したユーザフローに従い、外部ユーザは Consumer ID で一本化してアクセスできるようになる。 

``` 
    1. ディレクトリ外のユーザ（パートナー企業ユーザといった別ディレクトリ等のユーザ）
       →Azure AD B2B によりゲストユーザとして招待する
    2. Consumer
       →Azure AD B2C で事前に定義したユーザフロー（サインアップ・サインイン、プロファイル編集、パスワードリセットの各フロー）に従い、アクセスさせる
```

## Build 2020 最新情報 ～ Azure & Visual Studio & .NET ～
### Win UI
* これまで、MFCの流れを継承する Win32 アプリケーション、UWPアプリケーションの2つの系譜があったが、これらを一つに統合しようという UI プラットフォーム
* Native C/C++, .NET5等に対応

## Apps on Azure AD アプリケーション連携の WHY と HOW
### Azure ADの役割
1. Single Sign On
  * SAML、Open ID Connectといったフェデレーションプロトコルを用いて、Azure ADがidpとして認証基盤の役割を担う。
2. Outbound Provisioning
  * SCIMプロトコルを用いて、Azure AD から外部サービスに対してユーザ等のアカウント情報をプロビジョニングする。
3. Inbound Provisioning
  * クラウドHCM(Human Capital Management) から、Azure ADにユーザ等のアカウント情報をプロビジョニングする。
4. Application Proxy
  * Azure AD Application Proxy Serviceにより、オンプレミス Web アプリケーションのアクセス制御を Azure AD が担う。
5. Secure Hybryd Access
  * Azure AD Application Proxy Serviceにより、オンプレミスアプリケーションのアクセス制御を Azure AD と 3rd Party ネットワーク製品が担う。

### 新機能
1. Admin consent workflow
  * ユーザがアプリケーションにアクセスする際、管理者の同意を求めるようにする機能
2. Publisher verification
  * Azure AD に登録されたアプリケーションの発行者自体の信ぴょう性を検証する仕組み
3. Consent Policy
  * ユーザのアプリケーションに対するアクセス許可の同意について「ユーザーは、確認済み発行者からのアプリに対し、選択されたアクセス許可にのみ同意できる」が選択肢として追加された
4. Risk based consent
  * Microsoft 社がリスクがあると判断したアプリケーションは、ユーザーがアクセス許可を同意していたかに関わらず、アプリケーションのアクセスはブロックされる

## セキュアなソフトウェアを実現する GitHub のコード解析のご紹介
### GitHub Advanced Security
* Public Previewで以下の3点を提供するサービス
  1. コードのセキュリティ: 開発の早い段階で脆弱性を検知
  2. 依存関係のセキュリティ : 依存関係の脆弱性の検知
  3. 安全なデプロイ : シークレット情報の漏洩やコードリークへの対策

#### コード関連
* Code Scanning
  * Code QL（コード上のゼロデイ脆弱性や既存の脆弱性の探索エンジン）を利用し、コードのマージ前に脆弱性を検知する

### 依存関係
* セキュリティアラート
  * リポジトリ内の依存関係で脆弱性が見つかったら検知する
* 自動セキュリティフィックス
  * 「セキュリティアラート」で検知した脆弱性の改修バージョンまでアップするプルリクエストを自動で生成する
* dependency insight
  * 各リポジトリの依存関係を集約し可視化。依存関係に含まれる脆弱性情報、ライセンス情報が分かる。

### デプロイ関連
* シークレットスキャニング
  * pushした時点でシークレットが含まれていないか検知する。
  * 全 git ヒストリに対応

# おわりに
* Azure ADについては、以下に注力している印象を受けました。
  * External identities を例にディレクトリ外ユーザの管理
  * Publisher verification を例にディレクトリで管理するアプリケーション自体の信頼性の強化
* また、External identities について、クラウドの流行もあり、従来の AD と Azure AD とでユーザ管理の考え方が変わってきた印象をあらためて受けました。AD はドメインツリー内でのユーザ管理にフォーカスしていたことに対し、Azure AD はドメインといったボーダにこだわらずユーザを管理するといった違いです。

* GitHub Advanced Security については、DevSecOpsで開発の初期段階からセキュリティチェックを組み込むといった潮流がありますが、それにマッチした機能が用意されている印象を受けました。
kubernetes the hard way on PC（４．Clone 作成）

#初めに

「[kubernetes the hard way](https://github.com/kelseyhightower/kubernetes-the-hard-way) を PC でやってみる」の４回目、「Clone 作成」についてです。（ [目次](https://qiita.com/shimauma_Zzzzz/items/84ecf5c748ceafd05380#%E8%AA%AC%E6%98%8E%E8%A8%98%E4%BA%8B%E7%9B%AE%E6%AC%A1) ）
今回は、 kubernetes the hard way でいうと、３つ目の Provisioning Compute Resources に該当します。

なぜいきなり３番目から行くのか、というと
１番目： Prerequisites
　　Google Cloud Platform の準備の話しで、今回は直接該当しないため
　　（というか、内容としては１～３回目が該当します）
２番目： Installing Client Tools
　　これは、当一連の記事の中では、次回実施します。

Google Cloud のことを知らないからだと思いますが、
kubernetes the hard way の Installing Client tools は　いったいどこのサーバーに対してやっているんだ、、、というのが
わかりませんでした。。。
そのためこの一連の記事では順番を入れ替えています。


この記事は、以下の作業を行うという内容です。
- VM のクローン
- クローン後のVMのホスト名、IP 設定


図で言うと赤枠部分の作成になります。

![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310495/1cc30247-13e5-a82f-c49f-ee79f1a7f128.png)


#VMのクローン

共通で使うものや設定を入れたのち、テンプレート用の VM をシャットダウンします。
停止状態で、 virt-manager からクローンを作成します。
テンプレートVMを右クリックし、 Clone を選択します。

![35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310495/9af9191f-8c2d-febf-c764-9a8c153882b8.png)

VM 名を指定し、Storage については Clone this disk が選択されていることをかくにんし、Clone ボタンを押します。
![36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310495/ee947329-ae90-8800-3dd2-4067ea09812e.png)

VM が作成されます。
![37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310495/23f00d24-3c39-6d16-523c-1081c344e127.png)

作成完了後、右クリックし、Run を選択して起動します。
![38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310495/9fc6cacc-2d21-eb1d-229b-53b46b87b9a1.png)

# クローン後の VM のホスト名、IP の設定

起動後の VM はテンプレートと同じホスト名、IP アドレスを持っていますので、
その修正が必要です。　ユーザーも同じですので、テンプレート作成時のユーザーでログインします。

hostnamectl コマンドで ホスト名を変更します。

```shell-session
root@ubuntu20:~# hostnamectl set-hostname k8smaster0
root@ubuntu20:~# hostname
k8smaster0
```

次に IP アドレスを変更します。 ubuntu では netplan というのを使うんですかね。。。（RedHat派）

/etc/netplan 配下に 00-installer-config.yaml ファイルがあることを確認します。

```shell-session
root@ubuntu20:/etc# cd /etc/netplan/
root@ubuntu20:/etc/netplan# ls
00-installer-config.yaml
```

それを修正します。 基本的には IP アドレス部分を修正するだけです。

```shell-session
# This is the network config written by 'subiquity'
network:
  ethernets:
    enp1s0:
      addresses:
      - 192.168.199.200/24
      gateway4: 192.168.199.254
      nameservers:
        addresses:
        - 192.168.199.254
  version: 2

```

修正後、 本来は `netplan apply` で反映させますが、 ssh で入っていると切断されるため、
再起動し、新しいIP でログインしなおします。

同様に、 k8smaster1, 2,   k8sworker0,1,2 　の計6台クローンします。

![39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310495/7b9b3413-b44f-a4d3-e7c1-13a773711969.png)



----
今回はここまでとして、次回はようやく kubernetes the hard way の内容に入ります。


← [３．VM 作成](https://qiita.com/shimauma_Zzzzz/items/4c436a6030f7ed120d5d)
↑ [目次](https://qiita.com/shimauma_Zzzzz/items/84ecf5c748ceafd05380#%E8%AA%AC%E6%98%8E%E8%A8%98%E4%BA%8B%E7%9B%AE%E6%AC%A1)
→ [５．Client Tools](https://qiita.com/shimauma_Zzzzz/items/6a756f12d73d92949a69)

----
rails d controller コマンド

#指定したコントローラーを削除するコマンドです。
##削除したいコントローラー名を後ろにつけて以下のように使用します。

```
$ rails d controller コントローラー名

###rails d controllerのdとは「destroy」を省略したもの

###例えば　messagescontrollerだと

$ rails d controller messages

```

このコマンドで削除を実行すると、コントローラーを作成した際に自動的に作られた関連ファイルも同時に削除されるので非常に便利ですね。
vue.js/クラスバインドまとめ

```js
new Vue({
  el: "#app",
  data: {
  	isActive: true,
    isGreenBackActive: true
  },
  methods: {
  	changeGreen: function() {
    	this.isGreenBackActive = !this.isGreenBackActive
    }
  }
  
})
```

```html
<div id="app">
<p :class="{ red: isActive, blue: !isActive, 'green-back': isGreenBackActive }">テキスト</p>
<button @click="isActive = !isActive">押す</button>
<button @click="changeGreen">背景を緑にする</button>
</div>
```

```css
.red{
  color: red;
}
.blue{
  color: blue;
}
.green-back{
  background: green;
}
```

オブジェクトにまとめることもできる

```js
  computed: {
  	classObject: function(){
    	return {
      red: this.isActive,
      blue: !this.isActive,
      'green-back': this.isGreenBackActive
      }
    }
  },
```

```html
<p :class="classObject">テキスト</p>
```
[Error] Module not found: Can't resolve 'fs' (Next.js バージョン9.3と9.4での対処法)

### はじめに
この記事では、Next.jsで`Module not found: Can't resolve 'fs'`のようなエラーを、バージョンがそれぞれ9.3以前と9.4以降の時の対処法を書きます。

### バージョン9.4の場合

以下の条件によって、設定ファイルの有無が決まります。

|    `fs`を使う場所    |    設定ファイル    |
|:-----------------:|:------------------:|
|`getStaticProps` と `getServerSideProps`| false|
|それ以外(例えば、通常の関数内)|true|

つまり、`getStaticProps` と `getServerSideProps`関数以外でも`fs`を使う場合は
次のような設定ファイルが必要になります。
空のオブジェクト渡すことで、npmパッケージが`fs`モジュールに依存しないようにします。

```next.config.js
module.exports = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.node = {
        fs: 'empty'
      };
    }

    return config;
  }
};
```

### バージョン9.3以前

以下の条件によって、設定ファイルの有無が決まります。

|    `fs`を使う場所    |    設定ファイル    |
|:-----------------:|:------------------:|
|`getInitialProps`| false |
|それ以外(例えば、通常の関数内)|true|


**注意**

`getInitialProps`内で使用する場合は、上述した設定ファイルは不要ですが
client bundleをビルドをする場合は、設定ファイルが必要だそうです。

### なぜ、こんなややこしい？
そもそも、`fs`の処理はクライアント側でなく、サーバー側のコードでのみ動くものだからだそうです。

#### 参考
https://github.com/vercel/next.js/issues/7755#issuecomment-508633125
AtCoder 生活　89日目

[前回](https://qiita.com/flandrescarlet237/items/0c575b2cf03bff84513c)

#89日目
今回は茶色diffの問題を2問解きました。

|問題|難易度|自力で解けた|かかった時間|
|:-:|:-:|:-:|---|---|
|ABC169|D|✕|122分49秒|
|CODE FESTIVAL 2015 予選A|C|◯|19分32秒|

##[ABC169_D](https://atcoder.jp/contests/abc169/tasks/abc169_d)

```c++

#include <bits/stdc++.h>
using namespace std;
 
vector<pair<long long, long long> > prime_factorize(long long n) {
    vector<pair<long long, long long> > res;
    for (long long p = 2; p * p <= n; ++p) {
        if (n % p != 0) continue;
        int num = 0;
        while (n % p == 0) { ++num; n /= p; }
        res.push_back(make_pair(p, num));
    }
    if (n != 1) res.push_back(make_pair(n, 1));
    return res;
}
 
int main() {
    long long N;
    cin >> N;
    auto pf = prime_factorize(N);
    long long res = 0;
    for (auto p : pf) {
        long long e = p.second;
        long long tmp = 0, cur = 1;
        while (e >= cur) e -= cur++, ++tmp;
        res += tmp;
    }
    cout << res << endl;
}

```

解くのにかかった時間：122分49秒
感想：素因数分解の関わる問題が苦手と感じる


##[CODE FESTIVAL 2015 予選A_C](https://atcoder.jp/contests/code-festival-2015-quala/tasks/codefestival_2015_qualA_c)

```c++

#include <bits/stdc++.h>
#define rep(i,n) for(int i = 0;i < (n);i++)
using namespace std;
using ll = long long;
using pii = pair<int,int>;

const int INF = 2e9;

int main(){
    ll n,t;
    cin >> n >> t;
    vector<ll> x(n);
    rep(i,n){
        int a,b;
        cin >> a >> b;
        t -= a;
        x[i] = a - b;
    }
    int ans = 0;
    sort(x.rbegin(),x.rend());
    while(t < 0){
        if(ans == n){
            cout << -1 << endl;
            return 0;
        }
        t += x[ans];
        ans++;
    }
    cout << ans << endl;
}

```

解くのにかかった時間：19分32秒


###最後に
素因数分解に慣れたい。

難易度|かかった平均時間|解けた問題数|
|:-:|---|---|
|C|19分32秒|1問中1問|
C++ builder 10.2 Tokyo > TStringGridにおいて複数セル選択 > 選択したセルの数値を合計する実装例 > Selection.TopLeftとSelection.BottomRightの使用

```txt:動作環境
Windows 10 Pro v1909
RAD Studio 10.2 Tokyo Update 3
```

### 概要

- TStringGridで複数セル選択を使う
- 選択したセル内の数値の合計を取る

### 参考

- [Delphi TStringGrid multi select, determining selected rows](https://stackoverflow.com/questions/5950918/delphi-tstringgrid-multi-select-determining-selected-rows)

上記においてどのようにセルの値を読み取るのかが紹介されている。

### デザイン

オブジェクトインスペクタで「Options」の下記を選択しておく。

- goRangeSelect : true
- goEditing : true

![コメント 2020-07-12 220254.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/d64b1249-543b-c730-fb0c-fae506a0a398.png)

フォームは以下のようなデザインとした。

![form.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/6ed8320d-a6b4-f9ec-e210-0f4daf108fd2.png)


### ソース

以下の情報を使う。

- StringGrid1->Selection.TopLeft
    - X: 左上のセルの列
    - Y: 左上のセルの行
- StringGrid1->Selection.BottomRight
    - X: 右下のセルの列
    - Y: 右下のセルの行

セル文字から数値への変換は`StrToIntDef()`を使う。
下記の実装とした。

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------

// セルの値が数値でない時のエラー値として使う。数値として読めないものは`kError_NotAValue`として除外処理を行う。
static const int kError_NotAValue = -9999; 

void __fastcall TForm1::Button1Click(TObject *Sender)
{
	// 選択したセルの数値を合計する

	int topleft_col = StringGrid1->Selection.TopLeft.X;
	int topleft_row = StringGrid1->Selection.TopLeft.Y;
	int bottomright_col = StringGrid1->Selection.BottomRight.X;
	int bottomright_row = StringGrid1->Selection.BottomRight.Y;

	int sum = 0;
	for(int acol=topleft_col; acol <= bottomright_col; acol++) {
		for(int arow=topleft_row; arow <= bottomright_row; arow++) {
			int aval = StrToIntDef(StringGrid1->Cells[acol][arow], kError_NotAValue);
			if (aval == kError_NotAValue) {
				continue; // 数値でない
			}
			sum += aval;
		}
	}

    Edit1->Text = IntToStr(sum);
}
//---------------------------------------------------------------------------
```


### 実行例

Button1押下時に選択したセル内の数値の合計がTEditに表示された。
1+2+3+5+6+7 = 24 ([pythonでの検算](https://ideone.com/ZhllJn)).

![runExample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/84e2b2aa-45a7-55c7-ba7f-6b944536a418.png)


### 関連

- [System.SysUtils.StrToIntDef](http://docwiki.embarcadero.com/Libraries/Tokyo/ja/System.SysUtils.StrToIntDef) (10.2 Tokyoのヘルプ)
CentOSでパッケージの依存関係をTree表示したい

# CentOSでパッケージの依存関係をTree表示したい

AというパッケージがBというパッケージに依存していて、そのBというパッケージはCとDのパッケージに依存していて・・・という関係をTree構造で一気に見るコマンドがあります。

`repoquery`です。`yum-utils`というパッケージに入っています。

CentOS7とCentOS8のそれぞれで、postfixパッケージの依存関係を見てみましょう。

```console:CentOS7の場合
# yum install -y yum-utils

# repoquery --tree-requires postfix
postfix-2:2.10.1-9.el7.x86_64 [cmd line]
 \_  bash-0:4.2.46-34.el7.x86_64 [2: /bin/bash, /bin/sh]
 |   \_  glibc-0:2.17-307.el7.1.i686 [1: rtld(GNU_HASH)]
 |   \_  glibc-0:2.17-307.el7.1.x86_64 [4: libc.so.6(GLIBC_2.15)(64bit), libdl.so.2()(64bit), libdl.so.2(GLIBC_2.2.5)(64bit), rtld(GNU_HASH)]
 |   \_  ncurses-libs-0:5.9-14.20130511.el7_4.x86_64 [1: libtinfo.so.5()(64bit)]
 |   |   \_  glibc-0:2.17-307.el7.1.i686 [2: /sbin/ldconfig, rtld(GNU_HASH)]
・・・・
以下大量に
```

```console:CentOS8の場合
# dnf install -y yum-utils

# repoquery --tree --requires postfix
postfix-2:3.3.1-12.el8.x86_64
 \_ bash-0:4.4.19-10.el8.x86_64 [6: rtld(GNU_HASH), libdl.so.2()(64bit), libdl.so.2(GLIBC_2.2.5)(64bit), libc.so.6(GLIBC_2.15)(64bit), libtinfo.so.6()(64bit), filesystem >= 3]
 |   \_ filesystem-0:3.8-2.el8.x86_64 [2: /bin/sh, setup]
 |   |   \_ bash-0:4.4.19-10.el8.x86_64 [6: rtld(GNU_HASH), libdl.so.2()(64bit), libdl.so.2(GLIBC_2.2.5)(64bit), libc.so.6(GLIBC_2.15)(64bit), libtinfo.so.6()(64bit), filesystem >= 3]
 |   |   \_ setup-0:2.12.2-5.el8.noarch [1: system-release]
・・・・
以下大量に
```

CentOS7とCentOS8で少しだけオプションが違うようです。
製薬企業研究者がSeabornについてまとめてみた

# はじめに

ここではSeabornの基本的な利用方法について解説します。
Python3系の使用を想定しています。


# インポート

慣例として、`sns`としてインポートすることが多いです。

```python:Seaborn_1.py
import seaborn as sns
```


# Seabornの適用

matplotlibで作成した図に対して、`seaborn.set()`メソッドを用いることで、見た目を変えることができます。

```python:Seaborn_2.py
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns

sns.set()

x = [1, 2, 3]
y = [3, 1, 2]
plt.title('Line-chart') # グラフタイトル
plt.xlabel('X-axis') # x軸ラベル
plt.ylabel('Y-axis') # y軸ラベル

plt.plot(x, y) # グラフを作成
plt.savefig('seaborn_2.png') # グラフを画像ファイルとして保存
```

![seaborn_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517951/4b111a36-c0b9-e2bb-a05e-26b27b8fde03.png)


# まとめ

ここでは、Seabornの基本的な利用方法について解説しました。
Matplotlibで作成した図の見た目を変更したい場合は使ってみると良いでしょう。


# 参考資料・リンク

[プログラミング言語Pythonとは？AIや機械学習に使える？](https://pharma-engineer.com/basic-programming/python-summary/)
製薬企業研究者がSciPyについてまとめてみた

# はじめに

SciPyは、科学技術計算を行うためのライブラリです。
ここでは、SciPyでよく使うメソッドなどについて解説します。
Python3系の使用を想定しています。

# インポート

以下のいずれかの方法でライブラリをインポートします。

```python:SciPy_1.py
import Scipy as sp

from SciPy import モジュール名
```

# 積分

積分には、`scipy.integrate.quad`が使えます。

```python:SciPy_2.py
from scipy.integrate import quad


def my_func(x):
    return x**2 + 2*X + 3

result, error = integrate.quad(my_func, 0, 10)
```

# まとめ

ここでは、SciPyでよく使われるメソッドなどについて紹介してきました。
基本的な計算はNumPyでできることが多いですが、少し応用的なことになると、SciPyが必要になります。


# 参考資料・リンク

[プログラミング言語Pythonとは？AIや機械学習に使える？](https://pharma-engineer.com/basic-programming/python-summary/)
[インフラエンジニア向け]運用・保守性の考え方

#運用の検討事項
一般的な検討事項は以下の通り
・サービス提供時間はいつにするのか？
・バックアップの頻度と保存期間
・システム監視は何をどのように行うのか？
・運用をどこまで自動化するか？
・運用体制はどのようにするか？
・保守作業でのシステム停止時間はどのような時間帯で実施するのか？

これらについて掘り下げて見てみましょう。

#サービス提供時間
システムによって定義するサービス提供時間は異なります。
例えばWEBサイトなど２４時間ずっと動き続けなければいけないシステムは２４時間３６５日(24H365D)がサービス提供時間になりますし
業務で日中の営業時間しか使わないようなシステムであれば定時に前後プラス２時間くらいが提供時間で良いものもあります。

ここを定義することで、運用体制やコストが大きく変わってくるので、まずはサービス提供時間を定義しましょう。

#バックアップ
バックアップはシステムを運用する中で、とても重要になります。
障害が発生した際に、いつの時点まで戻せるのか、はシステムによりますのできっちり定義しておく必要があります。

バックアップには主に以下の３種類があります。
・システムバックアップ
・ログのバックアップ
・データのバックアップ

システムに障害が発生した場合、システムをバックアップから復旧させる際にシステムバックアップは必要となります。
このシステムバックアップの取得頻度によって、いつの時点に戻すことができるのか、が変わってきます。
リアルタイムでバックアップを取得することも可能ですが、システム負荷も上がりますし、バックアップデータも膨大になってしまいます。

バックアップ設計はユーザーと「障害発生時はいつのポイントに復旧する必要があるのか」の要件をしっかりと合意しておく必要があります。
また、障害解析の観点からも保存期間は最低1ヶ月、可能であれば3ヶ月分は欲しいところです。

データバックアップの観点では、例えば何らかのデータを誤って消してしまった場合、数日前の状態に戻したい！ということを言われることがあります。
このような事態を避けるために、あらかじめユーザーとは「何日前のデータまで戻せるようにするか」を合意しておく必要があります。
データバックアップは基本容量を食ってしまうので、ディスク容量にも気をつけながら設計する必要があります。

ログのバックアップについては、主に障害解析と監査目的で使われることがほとんどです。
障害解析の観点では1ヶ月〜３ヶ月、理想は半年ほどあれば良いと思います。
監査の観点では法律や制度で定められているものはそれに従うとして、基本的には3〜5年ほどは保存が必要になります。
大抵ログはアーカイブとして圧縮した状態で長期保存をするのでI/O処理性能が求められるディスクは必要ないです。

#システム監視
システムは障害が発生するものです。
その前提に立って、何をどのように監視するのかを設計していきます。
主な監視の種類としては以下が挙げられます。
・リソース監視
・プロセス監視
・メッセージ監視
・ハードウェア監視
・ジョブ監視

これらを監視する際は、多くの企業では監視ソフトウェアを利用して監視を行います。

##プロセス監視
アプリケーションが動作するには、裏でプロセスが動いています。
プロセスに異常が起きると、システムが使えなくなるので、プロセス監視は必須です。

##リソース監視
CPUやメモリの使用率、ディスクのI/Oなどが基準値を超えていないか監視します。
ただ、単純にCPU使用率が90％を超えたらアラームが鳴る、としている場合
たまたま瞬間的に負荷が上がっただけなのか、それとも恒常的に高い状態が続いていて90％を超えてきたのか、アラームに至るまでの状態も加味した対応が必要となります。
ですので、あらかじめ「○％以上でかつ○％以上が５分間続いた状態であれば、対応Aを実施する」など障害対応の定義を決めておいた方が、障害対応が俗人化しなくて済みます。

##メッセージ監視
ログに含まれるメッセージでアラートを上げる監視方法です。
例えばerrやattentionなども文字列で引っ掛けるなど。
ただ、この方法は場合によって検知しすぎてしまうことがよくあります。
検知した中でも実際には対応不要のものが含まれていたりします。
この辺りの匙加減は実際に運用していく中で微調整が必要な部分です。

##ハードウェア監視
いわゆる死活監視です。
ハードウェアに異常がないか継続的に確認します。

##ジョブ監視
バッチ処理など定期的にスケジュール実行されている処理が、
正常に始まって、正常に終了しているかを監視します。
また、動いてはいるが通常よりも時間がかかっている場合も検知する必要があります。
例えばAバッチが終わった後にBバッチを実行する、という連続性がある処理の場合、
前段の処理が遅延してしまうと、後続の処理が実行されない、あるいは実行してしまってエラーとなってしまうケースがあります。

#運用・保守はどこまで求められるのか
運用保守で何をどこまで実施するのかは、あらかじめ定義しておく必要があります。
これをしっかりやっておかないと、障害が発生したときや何かトラブルが起きた際に、
「それは運用保守でやってくれる範囲だろう？」
「いえ、それは範囲外となるので別途費用がかかります」
などという不毛なやりとりが発生してしまいます。。。。

特に費用が発生する/しない、という点は結構揉めるところでもあるので、可能な限り運用設計のなかで定義するようにしましょう。
【初心者向け】Pythonでパス設定するときに「\」が含まれていると予期せぬ動作になる

#はじめに
本記事は、Windows環境でパスの設定をする場合など「\」バックスラッシュを含んだ文字列を扱う際の、注意と対処法をまとめています。
(Macはパスの区切り文字が「/」スラッシュになっていますので、パスの設定の際はとくに気にしなくても大丈夫かと思います。)

#文字列に「\」バックスラッシュが含まれていると予期せぬ動作になる
例えば、下記のようにWindowsの環境でフォルダパスの指定をした際に、想定した文字列と異なる扱いになるときがあります。

```python:
dir_name = 'C:\testDir'
print(dir_name)
# 想定した文字列        > C:\testDir
# 実際に表示される文字列 > C:      estDir
```

なぜこのようなことが起こるかというと、windowsのパスの区切り文字である**「\」バックスラッシュは、Pythonで「エスケープシーケンス」という処理に使われる**からです。

「エスケープシーケンス」がどういう処理かというと、例えば文字列の中で改行をしたいとき

```python:
txt = 'ここで改行→←改行'
# print(txt)で 以下のように表示させたい
# ここで改行→
# ←改行
```

改行を入れたいからといってエンターを押しても、コード上で改行されてしまいエラーになってしまいます。

```python:
txt = 'ここで改行→
←改行'
# SyntaxError: EOL while scanning string literal
```

そこで「改行」などの**特殊な文字を表すための方法が「エスケープシーケンス」**です。
改行を意味する文字は、バックスラッシュ'`\`'と'`n`'を組み合わせた'`\n`'で表します。

```python:
txt = 'ここで改行→\n←改行'
print(txt)
# ↓表示される文字列
# ここで改行→
# ←改行
```

最初のパスの設定の例だと　`dir_name = 'C:\testDir'`　の`\t` 部分が「`TAB`」という文字に扱われ
Pythonで`'C:[TAB]estDir'`と認識され、不自然にスペースの空いた文字列になっていたのです。


#対処法
そこで「\」をエスケープシーケンス用の「\」ではなく、そのまま「\」バックスラッシュという文字列として扱う方法があります。
##方法１：raw文字列

文字列の最初に「そのまま」という意味の「raw」の頭文字「r」をつけます。
raw文字列と言われ、エスケープシーケンスが行われず、そのままの文字列として扱われるようになります。

```python:
# rを付けると そのままの文字列として扱われ、エスケープされない
r'C:\testDir'

# ただし最後に「\」が含まれているものは対応できない
r'C:\testDir\'
# SyntaxError: EOL while scanning string literal
```

##方法２：「\」バックスラッシュをエスケープする
「\」も特殊な文字なので「これはバックスラッシュです」とエスケープシーケンスで表現することができます。
バックスラッシュを２つ「`\\`」書くとバックスラッシュとして扱われます。

```python:
# バックスラッシュを2つ「\\」書いてバックスラッシュ自体をエスケープさせる
'C:\\testDir'
```

##方法3：「\」バックスラッシュを「/」スラッシュに書き換える
パスに対してならこの方法が一番いいと考えています。
Linux、Macのパスの区切り文字文字は「/」スラッシュになっているため、「/」に統一するよう意識すると、環境を変更したときの不具合を防止することができます。


Windowsも区切り文字「/」スラッシュで対応出来るため
「\」バックスラッシュを「/」スラッシュに書き換えて対処します。


```python:
# 「\」バックスラッシュを「/」スラッシュに書き換える
'C:/testDir'
```

###注意点
バックスラッシュをスラッシュに書き換える際の注意として
パスを取得する関数を利用した場合、パスの区切り文字は「\」バックスラッシュになります。

以下は、'C:\testDir'で実行しているとします。

```python:
import os
# カレントディレクトリの取得(作業中のフォルダ)
current_dir = os.getcwd()
print(current_dir)
# C:\testDir　「\」バックスラッシュで取得される
```

この取得したパスを利用して、以降のパスを自身で設定する場合、「/」「\」が混在しないように注意が必要です。

```python:
import os
# カレントディレクトリの取得
current_dir = os.getcwd()
# 画像用フォルダを設定 「/」で続きのパスを書く
image_dir = f'{current_dir}/image'
print(image_dir)
# C:\testDir/image 「\」「/」混在
```

pythonの関数では、混在していても動きはしますが、別のシステムにパスを渡すときや、パスを文字列操作するときにエラーになったりします。
例)SeleniumでChromeのダウンロードフォルダを設定するとき

そこで対処法として、パスを取得する際に「\」を「/」に置き換えてから、取得するようにします。

```python:
import os
# カレントディレクトリの取得のときに区切り文字を「/」に置き換え
current_dir = os.getcwd().replace(os.sep,'/')
print(current_dir)
# C:/testDir
```

#おわりに
ご覧いただきありがとうございました。
「\」バックスラッシュの対応方法はいろんな方法がありますが、現場や自分自身でルールを設けて統一して、不具合のない開発が出来るようにしていきましょう。


#参考
[エスケープシーケンスを使用する](https://www.javadrive.jp/python/string/index2.html)
[Pythonでエスケープシーケンスを無視（無効化）するraw文字列](https://note.nkmk.me/python-raw-string-escape/)
[セパレータの取得](https://www.python-izm.com/advanced/separator/)
個人アプリ作成＃２

# 一覧の作成
<img width="1327" alt="スクリーンショット 2020-07-12 21.47.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663122/6e6d5533-49bc-6007-71d4-b606c48df1a8.png">
freeCodeCampでPythonの勉強 part1

# freeCodeCampのカリキュラムが追加された！
freeCodeCampにおいて、以下のカリキュラムが追加されました。([こちらの記事](https://www.freecodecamp.org/news/python-curriculum-is-live/)参照)

1. Scientific Computing with Python(Pythonでの科学的計算)
2. Data Analysis with Python(Pythonでのデータ分析)
3. Information Security(情報セキュリティ)
4. Machine Learning with Python(Pythonでの機械学習)

せっかくなのでこれを機に勉強しようと思い立った次第。
今回の記事では*Scientific Computing with Python(Pythonでの科学的計算)*で行ったことを紹介します。

# Scientific Computing with Pythonをやってみた

大きくこの分野は以下の二つに分かれていました。

- Python for Everybody
- Scientific Computing with Python Projects

*Python for Everbody*ではPythonとはという部分から、基本構文や、ネットワーク、データベースなどを動画+選択式の問題で学ぶことができました。動画は全て英語なので、字幕や翻訳を使いながらどうにか解読しました。

*Scientific Computing with Python Projects*では実際に問題が出され、コードを書いて提出すると言った形式で学ぶことができます。ローカルに実行環境がなくても`repel.it`というブラウザ上で動く環境が提供されているので安心です。(私はローカルにソースをコピーして書きました)
また、テストコードも用意されており、全てのテストが通れば提出可能になります。

これから数回の記事では、*Scientific Computing with Python Projects*で出された問題と、個人的なポイントを紹介していきます。

## 1問目:[Arithmetic Formatter](https://www.freecodecamp.org/learn/scientific-computing-with-python/scientific-computing-with-python-projects/arithmetic-formatter)
最終的に欲しいものは`arithmetic_arranger`メソッドで、動きは以下の通り

```python
arithmeric_arranger(["32 + 698", "3801 - 2", "45 + 43", "123 + 49"])
```

Output:

```
   32      3801      45      123
+ 698    -    2    + 43    +  49
-----    ------    ----    -----
```

また、第2引数にbool型の値を指定することができ、`True`の時は計算結果も出力させないといけないです。

### 実装方針
上パーツ(`   32      3801      45      123`)、
中パーツ(`+ 698    -    2    + 43    +  49`)、
下パーツ(`-----    ------    ----    -----`)に分けて、最後に`\n`でつなげる。

皆さんにもトライしていただきたいので、私の実装は載せません…

### 個人的ポイント: 文字列の右寄せ、中央寄せ、左寄せ
この問題では以下のように、上、中、下パーツが右に揃っている必要があります。

```
○○○32
+○698
-----

○:空白
```

そこで文字列メソッド`rjust()`が使いました。(中央寄せ:`center()`、左寄せ:`ljust()`)
また、数値を右寄せにしたいときには一度`str()`で文字列に変換したのちに使います。

私は以下のように右寄せを行いました。

```python
"""
    top_num=32, mid_num=698 
    top_num_len=2, mid_num_len=3
    op='+' or '-'
"""

row_len = max(top_num_len, mid_num_len) + 2 # +と空白1つ分
top = top_num.rjust(row_len)
mid = op + mid_num.rjust(row_len - 1)
```

# 最後に
このように、問題を解くと普段あまり使わない物の発見(今回で言えば文字寄せのメソッド)が多いのでとても楽しいです。

次の問題は[*Time Calculator*](https://www.freecodecamp.org/learn/scientific-computing-with-python/scientific-computing-with-python-projects/time-calculator)です。
【試験合格記】認定Kubernetesアプリケーション開発者（CKAD-JP）

お疲れさまです。
表題の試験に合格したため記録として残したいと思います。

# 結果
合格

# スコア
74% / 66%

# 出題範囲

|分野|名称|割合|
|:-----------------|:-------------------|:-------------------|
|1|主な概念|13%|
|2|構成|18%|
|3|マルチコンテナポッド|10%|
|4|可観測性|18%|
|5|ポッド設計|20%|
|6|サービスとネットワーク|13%|
|7|状態の永続性|8%|

# 事前知識
GCP上でGKE(Google Kubernetes Engine)の構築、保守、CI/CD、HPA、監視、トラブルシューティングをしていました。
また、ローカルマシン上でMinikubeを用いたハンズオンをいくつかクリアしています。
前回CKAを受験した際の知識貯金があったため、今回の試験学習にかけた時間はおおよそ1週間ほどです。

# 所感
前回同様、「完全に理解した」と言えない程度のスコアでなんとか合格したという感じです。
解けなかった問題は一問だけだったので間違えた箇所の理解というより文章の理解が不足していたのかなと感じています。

CKADはCKAと比較してPodやDeploymentの作成に関する指示が複雑で設問をよく読んで何をすべきか理解する時間が多く、おたおたと設問を読んでいると時間が無くなるジレンマから焦りが生まれました。
実際、間違えてセッションからログアウトしてしまい数分無駄にしたときはリトライが頭をよぎったことを覚えています。

試験対策としてはUdemyの「[Kubernetes Certified Application Developer (CKAD) with Tests](https://www.udemy.com/course/certified-kubernetes-application-developer/)」を一周した後は「[CKAD-Exercises](https://github.com/dgkanatsios/CKAD-exercises)」を読んで不足していた知識の穴埋めをしました。

繰り返しになりますが、CKAを合格または合格できる経験を保有している場合、設問内容自体に戸惑うことはなく
文章理解力と要求内容を制限時間内に構築するスピードがあれば合格できるはずです。

# 受験者に向けたアドバイス
- まずはUdemyを完走してみる(HintやAnswerがあるので知識がなくてもなんとかなる)
- わけがわからない問題やコマンドは本やウェブサイトで理解できるまで調べる
- Udemyを周回する前に、各トピックに関連する「[kubernetes.io](https://kubernetes.io/docs/home/)」のページをブックマークし、整理する
- 問題の内容とブックマークしたページやコマンドを頼りに問題解決できるようにする
- PodやDeploymentをコマンドだけで迷わず作成することができれば時間にはだいぶ余裕が生まれるはず
- 身分証明書にパスポートを用意する必要はなく、免許証だけでも問題なかった
- 試験開始までのやり取りは英語だが、直前まではGoogle翻訳などを開いてやり取りしても何も言われない

# まとめ
これでCKAとCKADに合格できたので、3年間はKubernetesに関わる人権を得られたのかなと勝手に思っています。
この試験で得られる知識は各コンポーネントの理解に大いに役立ちますし、開発時のYAMLの書き方にも漏れが少なくなるような内容ですので、Kubernetesやっていきな方は忙しい合間を縫ってでも挑戦されると良いかなと感じました。
ちなみにCKADの難易度は上述したようにCKAと比べてPod作成に複雑さが増すので、合格ラインだけを見て「CKAの下位資格」だと思い込むと普通に落ちると思うので慢心せず学習に励むことをオススメします。

今年中に取りたい資格はAWSコンプリートのための2資格となったので、引き続き学習していき、落ち着いたらアウトプットしていければという感じでがんばります。
純粋関数

純粋関数について説明する。

純粋関数の特徴は以下である。

- 引数が同じ場合、常に同じ返り値となる。（参照透過性）
- 副作用が発生しない

例えば、下記のような`add`関数は純粋関数である。

```javascript
function add(a, b) {
  return a + b
}
```

`a=1`かつ`b=2`の場合、必ず`3`が返る保証があるためである。（参照透過性）

参照透過性を持たない例として、ランダムな値や現在時刻を返す関数は、実行するたびに結果が変わるので純粋関数ではなくなる。（ただし、ランダム値を返す関数を返す高階関数は純粋関数にできる）

では下記の関数はどうか。

```javascript
function increment(obj) {
    obj.num = obj.num + 1

    return obj
}
```

`obj={ num: 1 }`の場合、必ず`{ num: 2 }`が返る保証がある。

しかし、この関数は副作用を持つ。

JavaScriptの仕様として、[プリミティブ](https://developer.mozilla.org/ja/docs/Glossary/Primitive)な値以外は値ではなく参照が渡される。その為、引数の`obj`のメンバへの変更は呼び出し元が渡したオブジェクトのメンバも書き換えてしまう。

```javascript
function increment(obj) {
    obj.num = obj.num + 1

    return obj
}

var origin = { num: 1 }

var result = increment(origin)

console.log(origin) // { num: 2 } 呼び出し元のオブジェクトのメンバに変更が入ってしまっている
console.log(result) // { num: 2 }
```

この関数は、**関数の外への影響 ＝ 副作用**を持っている。

よって純粋関数ではない。

これ以外の副作用の例として、外部デバイス・ネットワーク・ファイルシステムとの**IO**や、グローバル変数・スコープ外変数などがある。

**テスト性やコードのトレーサビリティの利点**もある。

関数が関数外への影響（副作用）を持つということは、関数外の値やデータベースの状態を考慮してテストし、なおかつコードをトレースしなければいけなくなることが多い。

関数の中に影響を留める（＝**ローカリティ**を高める）ことは、純粋関数の使用や[結合度](https://qiita.com/oedkty/items/9bc2c93f388cd12d3923)の低さと関連している。

また、多くの有用なライブラリは、ユーザーが純粋関数のみを実装することで目的を達成できるように調整されていることが多い。

IOによる副作用を除去する方法として、**依存性注入**のテクニックを利用することもできる。

純粋関数ではIOが発生しないことからパフォーマンスが良くなる傾向があるが、たまに計算量の多い処理がある。

その場合、「引数が同じ場合、常に同じ返り値となる」特徴を利用して、**メモ化**をすることがでパフォーマンスが改善されることがある。

メモ化を行うと、引数と結果のセットがキャッシュできるため、２回目以降の呼び出しはキャッシュの参照のみを行えばよくなるからだ。

こうしたことから、純粋関数は非常に有用な概念である。
ブランチに最新のマスターの情報を取り込む方法

初投稿！

非常に感動した内容だった為、備忘録！


ブランチを切って作業をしていると、マージするまでの間にmasterに追加された更新で表示が変わってしまったり、コンフリクトするようになってしまいますよね。
それを防止するためには定期的にブランチにマスターの内容を反映させる必要があります。
その方法をメモ。


1. 反映したいブランチに切り替える

```
作業してるディレクトリ%　git checkout ブランチ名
```

２. マスターの内容をブランチに反映させる

```
作業してるディレクトリ%　git merge master
```
以上

参考にさせていただいたサイトhttps://hacknote.jp/archives/11191/
Guzzleでリクエスト、レスポンスを取得する方法

公式のドキュメントより一部抜粋。完全に自分のメモ。
ログを残すときとかに便利。

以下のようなありがちなリクエストを想定。

```php
$response = $client->request('PUT', '/put', ['json' => ['foo' => 'bar']]);
```


#リクエスト・レスポンスボディを取得する方法
`getbody() `を使う。ボディがStringでキャストされる。
このとき、リクエストを取得するには`#request->getbody()`してあげる。

```php
use GuzzleHttp\Middleware;

// Create a middleware that echoes parts of the request.
$tapMiddleware = Middleware::tap(function ($request) {
    echo $request->getHeaderLine('Content-Type');
    // application/json
    echo $request->getBody();
    // {"foo":"bar"}
});
```
レスポンスを取得するには`$response->getbody()`してあげる。ミドルウェアを使わないといけないっぽい。
Guzzleのミドルウェアについては、[この記事](https://qiita.com/Hiraku/items/bb67cf3113fe3c43f24d)が詳しいです。

```php
$body = $response->getBody();
// Implicitly cast the body to a string and echo it
echo $body;
// Explicitly cast the body to a string
$stringBody = (string) $body;
// Read 10 bytes from the body
$tenBytes = $body->read(10);
// Read the remaining contents of the body as a string
$remainingBytes = $body->getContents();
```
ちなみに`read()`を使うと指定したbyteだけ取得してくれるらしいです。重いデータとか用いるときには指定したい。

# ステータスコード・フレーズを取得する方法
`200 OK`とかそういうのをそれぞれ取得してくれます。

```php
$code = $response->getStatusCode(); // 200
$reason = $response->getReasonPhrase(); // OK
```

# 公式ドキュメント
http://docs.guzzlephp.org/en/stable/index.html
C++ Builder 10.2 Tokyo > Form in Formの試用 > TEditに入力ができなくなる > TFrameを使う

```txt:動作環境
Windows 10 Pro v1909
RAD Studio 10.2 Tokyo Update 3
```

### Form in Form

TFormの中にTFormを入れる方法が下記に紹介されている。

- [Delphi - form within form](https://stackoverflow.com/questions/2475540/delphi-form-within-form)

Delphi実装をC++ Builder実装にしてみた。

### Unit1 > 親フォーム

親となるフォームは下記のデザインとソースとしている。

![Form1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/3193d147-4e07-aa70-444f-309de1a6b765.png)


```Unit1.hpp
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
#include "Unit2.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TPanel *Panel1;
	void __fastcall FormCreate(TObject *Sender);
private:	// ユーザー宣言
	TForm2 *m_form2;
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

```

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	m_form2 = new TForm2(this);
	m_form2->Parent = Panel1;
	m_form2->Align = alClient;
	m_form2->Visible = true;
}
//---------------------------------------------------------------------------
```

### 子フォーム

子フォームは下記のデザインとしている。
ソースはデフォルトから変更せず。

![Form2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/cdd675f6-d564-227c-5f50-1001ed466769.png)


### 実行結果

実行すると下記のようになる。

![RunExample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/0a7d1923-bb01-b3c3-993a-095494778d7c.png)


### 問題点

Form in Formで実行したところ、「TEditマウスクリック選択時に入力ができない」問題が発生するようだ。
一方で、タブキー移動でTEditにフォーカスを移した時はTEditに入力はできる。

### 代わり

[上記のStackOverflowのリンク](https://stackoverflow.com/questions/2475540/delphi-form-within-form)にもあるように、TForm in TFormにせずにTFrame in TFormにする方が良さそう。
TFrameをTPanelに割り当てした場合は、TEditの入力不可問題は発生しない。
【Laravel】ファビコン(WEBブラウザタブのアイコン)を簡単に作成・設定する方法


### 使用するサイト

#### Favicon & App Icon Generator
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420171/2e98cf20-1394-65cb-d541-71cceea262af.png)

使用するのはこちらのサイト。
どんなサイズでもいいので画像を用意しておけば、それをファビコン用に加工・生成してくれます。

[Favicon & App Icon Generator](https://www.favicon-generator.org/)

### ファビコンの作り方
ファビコンにしたい画像を用意して、Favicon & App Icon Generatorにアクセス
ファイルをアップロードする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420171/68015e35-90b1-c51e-0e8a-e3088769b7bd.png)

切り替わった後の画面で、ファビコン化した画像をDLする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420171/b687172e-1c2d-2de7-3be5-1ddf9acc652b.png)

この画面のHTMLタグは後で使います。

### ファビコンを設定する

#### アプリ内にファビコンを配置
・`welcome.blade.php`がレイアウト構成を担うbladeファイル
という設定で配置します。

①resourcesディレクトリに画像を保存する`image`ディレクトリを作成
②さらに`image`の中に`favicon`ディレクトリを作成
③`favicon`の中に先ほどDLしたファビコン画像を移動

#### レイアウト構成を担うbladeファイルで参照する

`welcome.blade.php`の<head>タグに、先ほどのファビコンDLページのHTMLタグをコピペします。

```html
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png">
        <link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png">
        <link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png">
        <link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png">
        <link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png">
        <link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png">
        <link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png">
        <link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png">
        <link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png">
        <link rel="icon" type="image/png" sizes="192x192"  href="/android-icon-192x192.png">
        <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
        <link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png">
        <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
        <link rel="manifest" href="/manifest.json">
        <meta name="msapplication-TileColor" content="#ffffff">
        <meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
        <meta name="theme-color" content="#ffffff">
```

#### href(参照パス)を修正する
hrefのhref(パス)は`welcome.blade.php`からの相対パスになります。
よって、コピペしたhrefを全て下記のように修正しましょう。

```
href="../images/favicon/apple-icon-57x57.png"
```

これで設定は完了!
レイアウトで使っているbladeページを表示すればファビコンが設定されているのが分かります。
［原因不明］一つのUSB to LANを複数のパソコンで共有してネットワークが不安定になった話

# 概要
家で作業するようになって、表題のような事が発生したので備忘録
というかよく考えると原因不明だ…
完全に個人的なメモ…解決したら更新します。

# 背景
そもそも、共有するつもりはなかったが、自分が新しいMACBOOKを購入した時にUSB-CハブでHDMIとRJ45に変換するアダプタを買ったので、「これを共有すればそんなに抜かなくても色々共有できて便利やん！」とか思って、失敗しました。

## 現象

1. [パソコンA]-[USB2LAN]-[ハブ]-[家庭内ネットワーク]
2. [パソコンB]-[USB2LAN]-[ハブ]-[家庭内ネットワーク]
   [パソコンA]-[無線ラン]-[家庭内ネットワーク]

1を行ったあと、2の状態になると**パソコンA**がネットワークに繋がらなくなる。

# 解決
ハブを再起動すればネットワークが復旧する。

## 原因(予想)
USB2LANはMAC Addressが変わらないため、これとIPアドレスの紐付けが更新されない。
（個人的には一旦パソコンから外しているので、更新されているような…）
（ネットワークハブはMAC Addressを記憶する機能があるのでそこにキャッシュされている？）
AWS VPC設計、サブネット設計メモ

# VPC設計のポイント

## VPCで割り当てるIPはプライベートIPアドレスの範囲の使用が推奨される
VPCでは仮想のプライベートネットワーク空間を作成するのでプライベートIPアドレスの使用が推奨される。

具体的には以下（IPv4の場合）
IPv4プライベートアドレス範囲（RFC1918）：

 - 10.0.0.0〜10.255.255.255（24ビットブロック）
 - 172.16.0.0〜172.31.255.255（20ビットブロック）
 - 192.168.0.0〜192.168.255.255（16ビットブロック）


## VPCのIPアドレスの範囲を決めるときは大きめ（できれば/16）に設定する
後から変更できないため、IPの枯渇を防ぐために範囲を大きめにとる。
CIDRの範囲は/24〜/16と決まっている。できれば/16に設定しする。

## 他のVPCやオンプレミスとIPアドレスが重複しないようにする。

## VPCを分けるか、アカウントを分けるか

 - 違うシステムの場合はアカウントを分ける
  - 違うシステムを同一アカウントに入れると管理が煩雑になる
 - 同一システムで環境（本番環境、ステージング環境など）が違う場合は

# サブネット設計のポイント
### IPアドレスの範囲はできれば/２４推奨に設定する
　一つのサブネット内に256個設定できればほとんどの場合足りるのではないか

### サブネットに割り当てられるルーティングテーブルは１つ

###高可用性のために、２つ以上のアベイラビリティゾーンを使う。
C++ Builder 10.2 Tokyo > IDE > コンポーネントの追加方法 > ツールパレット(失敗: 配置先の間違い), 右クリックからのコンテキストメニュー(成功)

```txt:動作環境
Windows 10 Pro v1909
RAD Studio 10.2 Tokyo Update 3
```

### コンポーネントの追加

コンポーネントの追加には少なくとも二つの方法があるようだ。

1. ツールパレットからの追加
2. コンテキストメニュー

### 1. ツールパレットからの追加

ツールパレットからTButtonの選択
![ツールパレット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/9ecc373e-f94a-5482-ec18-699f73f3aa7c.png)

ツールパレットにて選択したコンポーネントをTFormやTPanel上にドロップする。


### 2. コンテキストメニュー

コンテキストメニュー (TButtonの選択)
![コンテキストメニュー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/a02bcc28-a058-6e95-82ff-ae6ab6ca014c.png)

配置をしたいコンポーネント(例: TForm, TPanel, TGroupBoxなど)で右クリックしてコンテキストメニューから選択する。

以下が選択できる。

- ラベル: TLabel
- ボタン: TButton
- 編集: TEdit
- パネル: TPanel
- ツールバー : TToolBar
- ステータスバー: TStatusBar


### ツールパレットの問題と代わりとしてのコンテキストメニュー

10.2 Tokyoを使っていて何度か失敗したのは、TPanel上にツールパレットからドロップしたつもりがTFormに行く、というようなことだった。
これが何回か発生して、TForm上から張りなおすというような作業の手間が発生していた。

もともとC++ Builder 6のころからツールパレットを使用していたので、失敗する症状については仕方なく使っていた。
ふと見たなかでコンテキストメニューに気づき使ってみたところ、ツールパレットのような配置先のミスがなくなった。

コンテキストメニューは選択肢が少ないが、よく使うコンポーネントについてはツールパレットでなくコンテキストメニューを使うことで、デザイン作業時の失敗がなくなった。
AWS SAA対策メモ（コンテナ、コスト管理＆その他）

~~SAA対策の自分用のメモ。~~
7/13にSAA合格

SOA対策の自分用のメモ。
どんどん更新して加筆修正していく予定。

## コンテナ
より少ないコンピュータリソースで、OS上に独立した実行環境を構築する仮想化技術

3つの構成要素
**データプレーン**　コンテナ稼働の実行環境
**コントロールプレーン**　コンテナの管理
**レジストリ**　コンテナの起動元のイメージ格納場所


**Elastic Container Service (ECS)**
Dockerコンテナを管理するオーケストレーションサービス。これにより、コンテナ化されたアプリケーションを AWS で簡単に実行およびスケールで可能。コンテナ上のタスクの増減をService Auto Scalingが行う。

**Fargate**
サーバーやクラスターの管理の必要なしにコンテナを実行するための、Amazon ECS および EKS に対応したコンピューティングエンジン

**Elastic Container Service for Kubernetes (EKS)**
コンテナ化されたアプリケーションのデプロイ、管理、スケールを Kubernetes を使って AWS で簡単に実行

**Elastic Container Registry (ECR)**
完全マネージド型の Docker コンテナレジストリです。Dockerコンテナイメージを簡単に保存、管理、デプロイ


## コスト管理系
**AWS Cost and Usage Report**
コスト状況の詳細分析
CSV形式でS3やRedshiftに保存したり、QuickSightで分析・可視化できる。

**Cost Explorer**
コストの可視化と傾向分析
部門ごとなどで**タグ**をつけておくと、集計時にフィルタリングなどをして部門ごとの使用状況を可視化しやすくできる。

**AWS Budget**
予算額を設定し、超過した場合にはCloudWatchアラームやSNS通知が来る。

**Trusted Advisor（ビシネス／エンタープライズサポートのみ）**
５つの観点をベストプラクティスに基づいて利用状況をチェック
コスト最適化、セキュリティ、耐障害性、パフォーマンス、サービス制限

## DR
**RPO(Recovery Point Objective)**
過去のどの地点までデータ復元を許容できるか

**RTO(Recovery Time Objective)**
復旧するまでの目標時間

**パイロットライト**
常に利用可能であるアプリケーションの最小バージョン
DRシナリオでよく使われる

## その他
**AWS Artifact**
コンプライアンス関連情報を一元管理

**Server Migration Service (SMS)**
多数のオンプレミスワークロードをAWSに移行可能
自動化した移行プロセスによって素早く展開することが可能

**Database Migration Service (DMS)**
商用およびオープンソースのデータベースとの間でデータを移行するために使用

**Application Discovery Service (ADS)**
オンプレミスサーバーのインベントリと動作を検出するために使用されます。AWSへの移行計画を作成するときに利用するものです。

**AWS Globel Accelerator**
世界中の顧客に提供するアプリケーションの可用性とパフォーマンスを改善するネットワークサービス

**Lightsail**
仮想サーバー、ストレージ、データベース、およびネットワーキングを予測可能な低価格で提供するサービス

**Amazon Rekognition**
画像分析と動画分析をアプリケーションに簡単に追加できます。Rekognition API に画像または動画を与えるだけで、このサービスが対象物、人、テキスト、シーン、アクティビティ、それに不適切なコンテンツまで検出します。

**Amazon Polly**
文章をリアルな音声に変換するサービス

**Amazon Lex**
音声やテキストを使用して、任意のアプリケーションに対話型インターフェイスを構築するサービス

**AWS DataSync**
オンプレミスストレージと Amazon EFS の間でデータを迅速かつ簡単に移動することができるマネージド型のデータ転送サービス

**Amazon Elastic Transcoder**
はクラウドのメディア変換サービス

**AWS Batch**
バッチ管理機能
優先度高なジョブはオンデマンドインスタンスで、優先度低なジョブはスポットインスタンスで行う。ビッグデータ分析に利用。

**CloudSearch**
簡易検索機能を追加できる

**Systems Manager**
リソースの運用情報の可視化、制御

**AWS KMS**
鍵管理サービス。暗号化鍵の自動ローテーション、キーの権限管理、暗号化鍵の使用状況の可視化、証跡管理ができる
SDKやCLIのクライアントアプリケーションやS3、EBS、RDS、Redshiftなどのストレージサービスで利用可能

**CloudHSM（Hardware Security Module）**
HSMはデータセンター内にあるユーザー占有ハードウェアアプライアンス。HSMと連携可能なのは、RedshiftとRDS for Oracle。

### 自動セットアップのアプローチ
**ブートストラップ**
CloudFormation, OpsWorks

**ゴールデンイメージ**
AMI, VM Import/Export

**コンテナ**
Elastic Beanstalk, ECS, Fargate, EKS
様々な言語のHello Worldについてまとめてみた

# はじめに
言語によって画面に```Hello World```と表示するのに長いコードが必要なものやすごく短いものがあります。そこが面白いなぁと思い、知ってる言語の```Hello World```についてまとめてみました。この一覧に取っていない```Hello World```や言語がありましたら、コメント欄でお願いします。

---
# Java
```java
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}
```
知ってる中で一番長いと思います。また、環境構築も大変で、JDKのインストールやPATHを通したり、コンパイルも必要です。しかし大規模開発に向いていておすすめの言語です。くわしくは[これ](https://qiita.com/javaboy/items/c284059d994020260518)で。

---
# Kotlin
```kotlin
fun main(args: Array<String>){
    println("Hello World")
}
```
Javaの進化版です。初めて見たときc言語ににてるなと思いました。

---
# C言語
```c
#include <studio.h>

int main()
{
    printf("Hello World\n");
    return 0;
}
```

独特な波括弧の改行位置だと思いました。ちなみに```Hello World```という文字は[Wikipedia](https://ja.wikipedia.org/wiki/Hello_world)によるとC言語のK&Rという入門書籍から発祥したみたいです。

---
# JavaScript
```javascript
alert("Hello World")
```

Javaと名前が似ていますが**マスクとマスクメロン**のように用途も使い方もだいぶ違っています。javascriptはwebページを動的に動かすために存在している感じです。ですから```Hello World```と出すにもさまざまな方法があります。今回は短いものを例にだしました。

---
# Python
```python
print("Hello World")
```
最近はやりのPython。Rubyと似てる気がします。

---
# Ruby
```ruby
print "hello world"
```
短いコードですが括弧がなくて読みにくい気がします。

---
# おわりに
RubyとPythonは用途を知らないので説明が極端に短くなってしまいました。もしこの記事に追加してほしい言語があればコメント欄にお願いします。
GitHubリポジトリの動向をSlackに通知する方法


![alt](https://slack.github.com/static/img/githubplusslack.svg)

# SlackにGitHubアプリをインストール
1. https://slack.github.com/ にアクセスし、`Add to Slack`。
2. `All Public Channels`を選択して`Install`。（実際のチャンネル紐付けは後で行う。）

# GitHubアカウントとの接続
1. Slackで、追加されたGitHubに`/github signin`と話しかける。
2. GitHubリポジトリの通知を流したいチャンネルで`/github subscribe owner/repo`。

# 通知のカスタマイズ
参考: https://github.com/integrations/slack#configuration
LINEからngrokに接続できない時はリージョンをアジアにする

ngrokを使ったローカルでのLINE Bot動作確認がうまくいかない時の対処法です。

ngrokのサーバーのデフォルトのリージョンは`us`(アメリカ)ですが、この`us`だとLINEスマホアプリからメッセージを送っても、そのリクエストがngrokに届かなくなりました（2020年7月ごろの現象）。

```:ngrokを起動中のターミナル
# 略
Region                        United States (us)
# 略

Connections                   ttl     opn     rt1     rt5     p50     p90                                                             
                              0       0       0.00    0.00    0.00    0.00 

# このあたりに出るはずのログが出ない。。。
```

そんな時は、ngrokを一度停止し、以下のように`--region ap`を指定して起動してください。

```sh
$ ngrok http 80 --region ap
```

サーバーのリージョンが`ap`(アジアパシフィック)になったことで、リクエストが届くようになる可能性があります。

```:ngrokを起動中のターミナル
# 略
Region                        Asia Pacific (ap) 
# 略

Connections                   ttl     opn     rt1     rt5     p50     p90                                                             
                              0       0       0.00    0.00    0.00    0.00 

POST /callback                200 OK # ログが出た！
```