OmniAICreator/Qiita-1.07M huggingface dataset:
PowerShellで空行とコメントアウトを除外する


```Get-Content ＜対象のファイル＞ | select-string "^\s*$" -notmatch | select-string "^\s*#.*$" -notmatch```

```
> Get-Content .\test.txt          
#ビッテンフェルトは失敗した

人を褒めるときは大きな声で、悪口を言うときにはより大きな声で

われらが参謀長どのは、人間には嫌われても犬には好かれるわけか。犬どうし気が合うのだろう

#ビッテンフェルトの言や良し

ビッテンフェルト家には、代々の家訓がある、他人をほめるときは大きな声で、悪口をいうときはより大きな声で、というのだ
```

```
> Get-Content .\test.txt | select-string "^\s*$" -notmatch | select-string "^\s*#.*$" -notmatch

人を褒めるときは大きな声で、悪口を言うときにはより大きな声で
われらが参謀長どのは、人間には嫌われても犬には好かれるわけか。犬どうし気が合うのだろう
ビッテンフェルト家には、代々の家訓がある、他人をほめるときは大きな声で、悪口をいうときはより大きな声で、というのだ

```
Git fetchとpullの違い

どちらも「リモートからローカルリポジトリの内容を更新する」という操作なのですが、少し違いがあるので、そこを解説します。

#### ざっくりとまとめ
**fetch**・・・リモートと通信を行い、更新された内容をローカルリポジトリに取り込む。(ローカルのソースファイル自体はまだ更新されない)
**pull**・・・上記のfetchとmergeというコマンドを連続して実行し、リモートの更新内容をローカルのソースファイルに反映させる。

ざっくりしすぎたかも。。ここから少し詳しく書いていきます。

## fetchって何？
まずはfetchの解説、の前に、簡単に「3種類のブランチ」の説明をしておきます。
Gitの仕組みの根幹の部分に関するものであり、複数人(複数環境)でリポジトリを共有するチーム開発においては、必ずかかわっていかなければならないものです。
fetchコマンドもこの概念と密にかかわっています。この概念を簡単にでも理解しておくと、fetchコマンドの理解が早くなると思います。

### Gitの3種類のブランチ
①*リモートブランチ*
②*ローカルブランチ*
③*リモート追跡ブランチ(リモートトラッキングブランチ)*

①のリモートブランチは、その名の通りリモート環境上に存在するブランチです。
リモートで全員がアクセスできる共有のブランチであり、最終的な成果物となりうるブランチです。協力してキレイに保ちましょう。

②のローカルブランチは、その名の通りローカル環境上に存在するブランチです。
ソースを新規作成したり修正したりして、その内容をコミットしているのは、ローカルブランチ上での作業になります。

①と②はそのままの意味なので、あまり理解に苦しむことはないと思います。ですが、③は少し特殊な役割になるので、丁寧に解説します。

③のリモート追跡ブランチは、「ローカルリポジトリ上で①のリモートブランチの内容のコピーをし続けるブランチ」です。
コピーをし続ける、変更内容を追いかける、から「追跡」ブランチと名付けられています。
Git系の記事とかでたまに見かける**origin/master**という形式で記載されたブランチ名は、リモート追跡ブランチ名を指しています。
役割としては、①リモートブランチの情報をローカルのリポジトリに引き込む際の受け皿、①と②の橋渡し役みたいなものです。
また、この③追跡ブランチのソースの内容を直接編集してコミット、なんてことはできません。

では、この③追跡ブランチが更新されるシチュエーションはというと、「**fetch**」と「**push**」のどちらかのコマンドが実行されたときのみとなります。(ブランチの作成、削除は更新には含めていません)
リモート側から情報を更新するのが**fetch**、ローカル側から情報を更新するのが**push**です。

はぁ、、、やっとfetch出てきた。。。

### つまりfetchとは
⇒**①リモートブランチからローカルリポジトリの③リモート追跡ブランチに情報を送って更新をかけること**
となります。

ここで大事なのは、更新されるのは**③追跡ブランチ**であって、②ローカルブランチではない、ということです。
PC上のソースファイルたちは、②のローカルブランチに紐づいているものなので、fetchだけではソースファイル自体は更新されない、ということになります。
ソースファイルに更新を反映させるためには、②のローカルブランチに③のリモート追跡ブランチを「**merge**」する必要があります。

※fetchとpull、二つのコマンドの概念を説明する上で、「merge」というコマンドからは逃げられないのですが、この記事ではmergeに関する詳細な解説は省きます。
(mergeだけで3時間語れるくらい深い深い。。。)
この記事を読むうえでは、「2つのブランチの内容を統合するコマンド」くらいのイメージで十分です。

これで、リモートの更新を、PC上のソースファイルにまで反映することができました。
コマンドで表すとこの2行分。

```
git fetch origin master
git merge origin/master
```

masterブランチ上にいる想定で、リモート名：originからmasterブランチの最新の情報をローカルブランチに引き込むコマンドです。
origin/masterがリモート追跡ブランチ名ですね。

## pullって何？
fetchを使用してローカルリポジトリの更新を行う場合、fetchだけでなくmergeを行う必要があります。
よく実行する作業なのに毎回2コマンド打つのめんどくね？という時のためのpullなのです。

### つまりpullとは
⇒**「fetch ＋ merge」を1コマンドで実行してくれる便利なヤツ**
となります。

試しに、fetchを使ってローカルリポジトリを更新するコマンドと同様の動作を、pullを使用して実行しようとすると、、

```
git pull origin master
```

となります。ちゃんと1行にまとまりました！

## まとめ
普段使用するのはpullでいいと思うけど、pull=fetch+mergeを理解しておかないと、いざ謎のエラーが出てきたときに詰むから気を付けてください。


理解したとてエラー内容によっては詰むときは詰むけどね！！！！！
Ruby on Rails 変数、定数まとめ

# Ruby on Rails 変数、定数まとめ
Railsにおいてよく使う変数、定数についてまとめました。

## 前提条件
- 変数
  - 変更可能
- 定数
  - 定数不可

## 変数
### ローカル変数

- メソッドやブロック内でのみ有効
- 変数名
  - 小文字のスネークケース  
    `user_name = 'jon'`

#### Railsでの活用
- View
  - View でローカル変数を扱いたい場合は、Viewファイル内で定義する。
[users/show.html.erb]

```erb
<% hoge = 'huga' %>
<div><%= hoge %><div>
```
- Controller
  - Viewに変数の値をわたす必要がなかったり、Contrller内で変数の値を共有する必要がない場合は、ローカル変数に定義する

```ruby
def create
  article = Article.find( params[:id])
  return render_404 if article.blank?
end
```

### インスタンス変数

- 同じコントローラー内で使える変数
- 変数名
  - 先頭に`@`を付ける

#### Rails での活用

- Controller Action内で定義したインスタンス変数を View へわたす。

```ruby
def show
  @user = User.find(params[:id])
end
```

[users/show.html.erb]

```erb
<div>ユーザーID：<%= @user.id %><div>
```

※ローカル変数をわたすことはできない

```ruby
def show
  user = User.find(params[:id])
end
```

[users/show.html.erb]

```erb
<div>ユーザーID：<%= user.id %><div>
```
-> 参照不可
`undefined local variable or method 'user' `



### グローバル変数

- 全てのContrller使える
- プログラムのどこからでも、変更、参照が可能
- 変数名
  - 先頭に`@`を付ける

## 定数

- クラス内で定義する

- 定数名
  - 大文字、スネークケース

#### Rails での活用

- [config/initializers/constants.rb]に共通の定数を定義する
  - 全ての Controller, View で参照することができる
    [config/initializers/constants.rb]

```ruby
MAX_SIZE = 10
```

- 各 Model で使用する定数を定義するには、model ファイルのクラス内に定義する。
  [user.rb]

```ruby
class User
  OFFICIAL_ID = 100
end
```

Controller や View で参照する場合は、`User::OFFICIAL_ID`と書く
Lambda & Serverless Frameworkで、multipart/form-data形式のデータを受け取る

## 前書き
最近業務でAWSのLambdaとServerless Frameworkを使うことが多いです。
業務の流れが早く、次から次へと新しいツールを触ってすべて忘れていきそうなので、個人的なまとめとして、記事を作成します。
言語はnode.js, TypeScriptを使用しています。

## multipart/form-dataとは？

>multipart/form-dataは、前述の通り複数の種類のデータを一度に扱える形式で、主な利用シーンはHTMLフォームです。特にファイルアップロードでよく利用されます。
引用元:
[フロントエンド] multipart/form-dataを理解してみよう
https://www.yoheim.net/blog.php?q=20171201

ボディはBoundaryという区切り文字で、ファイル送信時に指定したnameごとに区切られます。

```
------WebKitFormBoundaryO5quBRiT4G7Vm3R7
Content-Disposition: form-data; name="message"

Hello
------WebKitFormBoundaryO5quBRiT4G7Vm3R7
Content-Disposition: form-data; name="file"; filename="a.txt"
Content-Type: text/plain

aaa
------WebKitFormBoundaryO5quBRiT4G7Vm3R7--

curl
curl -X POST -F file=@./sample.csv https~(Lambda関数のエンドポイント(URL)) --output output.csv
```
(引用元同じ)

## serverless.tsでの設定

```ts:serverless.ts
const serverlessConfiguration: Serverless = {
  service: {
    name: 'sls-test',
  },
  frameworkVersion: '1',
  custom: {
    webpack: {
      webpackConfig: './webpack.config.js',
      includeModules: true
    },
    // ここ
    apiGateway: {
      binaryMediaTypes: ['multipart/form-data']
    }
  },
```
これで、APIGatewayの設定→バイナリメディアタイプという欄に、multipart/form-dataが設定されるようになります。

## Lambda関数内での処理
node.jsで、aws-lambda-multipart-parserというnpmモジュールを使って、multipart/form-data形式のデータを解析しています。
他の言語でも、「言語名　multipart/form-data」と調べれば、同じようなライブラリを検索できると思います。

```ts:handler.ts
// 受け取ったevent.bodyがbase64エンコードされているのでデコード
event.body = Buffer.from(event.body, 'base64').toString('binary');

// multipart/form-dataをパースする
const multipartBuffer = Multipart.parse(event, true);

// 再度base64エンコードされているのでデコード
let data: string = Buffer.from(multipartBuffer.file.content, 'base64').toString('binary');
```

## 後書き
他にも、serverless-jest-pluginというnpmモジュールを使ってテストを構築する方法や、そもそもBufferについても勉強してまとめたいのですが、一旦止めておきます。

##参考
serverlessを使ってLambdaにmultipart/form-dataでバイナリデータをアップロードする
https://qiita.com/YoukyMurakami/items/a1da42b394970979ad1e

base64ってなんぞ？？理解のために実装してみた
https://qiita.com/PlanetMeron/items/2905e2d0aa7fe46a36d4

Node.jsのバッファについて
http://info-i.net/buffer#i-2
Pythonで線形探索

線形探索のコードは以下です。

```python 
def linear_search(src, target_value):
    result = False
    for i in range(len(src)):
        if src[i] == target_value:
            result = True
    return result


def main():
    src = [1, 2, 3, 4, 5]
    target_value = 5

    if linear_search(src, target_value):
        print('Found!')
    else:
        print('Not Found')


if __name__ == '__main__':
    main()
```

実行結果は以下になります。

```console
Found!
```


最後まで読んでいただきありがとうございました。
またお会いしましょう。
`% terraform init` で `* hashicorp/aws: version = "~> 3.10.0"` とエラーが表示される場合

IaCに憧れてTerraformを勉強中の新米エンジニアよしこです。

AWS EC2にVPCを構築するのにTerraformを使用しているときに以下のログに遭遇しました

```bash

> terraform init

Initializing the backend...

Initializing provider plugins...
- Using previously-installed hashicorp/aws v3.10.0

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, we recommend adding version constraints in a required_providers block
in your configuration, with the constraint strings suggested below.

* hashicorp/aws: version = "~> 3.10.0"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
```

日本語のケースワークが少なかったので解消方法を共有します

# 環境

```bash
> terraform -v
Terraform v0.13.4
+ provider registry.terraform.io/hashicorp/aws v3.10.0
```

# 解決策

ログにもしっかり書かれていますが、`hashicorp/aws: version = "~> 3.10.0"` のようにバージョンの記述を `main.tf` へ追加することでエラーが解消します。

Terraformのドキュメントを参考に以下のように記述しました。
https://registry.terraform.io/providers/hashicorp/aws/latest/docs



```main.tf
variable "access_key" {}
variable "secret_key" {}
variable "region" {}

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "~> 3.10"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  access_key = var.access_key
  secret_key = var.sevret_key
  region = var.region
}

# Create a VPC
resource "aws_vpc" "vpc-1" {
  cidr_block = "10.0.0.0/16"
  tags = {
    Name = "vpc-1"
  }
}
```

こちらはterraformのバージョン0.13 以降の記述になります。

バージョン0.12 以前の場合は以下のように記述します。

```main.tf
# Configure the AWS Provider
provider "aws" {
  version = "~> 3.0"
  region  = "us-east-1"
}

# Create a VPC
resource "aws_vpc" "example" {
  cidr_block = "10.0.0.0/16"
}
```

### 変更前

参考程度に、変更前はこのように記述していました

```main.tf
variable "access_key" {}
variable "secret_key" {}
variable "region" {}

provider "aws" {
  access_key = var.access_key
  secret_key = var.secret_key
  region     = var.region
}

resource "aws_vpc" "vpc-1" {
  cidr_block = "10.0.0.0/16"
  tags = {
    Name = "vpc-1"
  }
}
```
macOSでmermaid.jsを使えるようにする

# インストール

ターミナルで次を実行してインストールします。

```bash
$ brew install yarn
$ yarn global add mermaid
$ yarn global add mermaid.cli
```

これでインストール完了。以下のようなヘルプを確認してみましょう。

```bash
$ mmdc --help
Usage: mmdc [options]

Options:
  -V, --version                                   output the version number
  -t, --theme [theme]                             Theme of the chart, could be default, forest, dark or neutral. Optional. Default: default (default: "default")
  -w, --width [width]                             Width of the page. Optional. Default: 800 (default: "800")
  -H, --height [height]                           Height of the page. Optional. Default: 600 (default: "600")
  -i, --input <input>                             Input mermaid file. Required.
  -o, --output [output]                           Output file. It should be either svg, png or pdf. Optional. Default: input + ".svg"
  -b, --backgroundColor [backgroundColor]         Background color. Example: transparent, red, '#F0F0F0'. Optional. Default: white
  -c, --configFile [configFile]                   JSON configuration file for mermaid. Optional
  -C, --cssFile [cssFile]                         CSS file for the page. Optional
  -p --puppeteerConfigFile [puppeteerConfigFile]  JSON configuration file for puppeteer. Optional
  -h, --help                                      output usage information
```

# VSCodeで図を書いてみる

エディターとしてVSCodeを使っているのでVSCodeでどうやって図を作成するのか簡単にメモしておきます。（mac, VSCode使っていない人すみません:disappointed_relieved:）

**Mermaid Preview**という拡張機能をインストールしておきます。これで図を横に表示させながらファイルを作成することができます。（**Mermaid Markdown Syntax Highlighting**という拡張機能も入れてシンタックスハイライトさせたかったのですが、**Mermaid Preview**が有効になっていると機能しないみたいです？）

例として次のファイル`test.mmd`を作成して保存します。拡張子は`.mermaid`でもOKらしい。

```mermaid:test.mmd
sequenceDiagram
    participant Alice
    participant Bob
    Alice->>John: Hello John, how are you?
    loop Healthcheck
        John->>John: Fight against hypochondria
    end
    Note right of John: Rational thoughts <br/>prevail!
    John-->>Alice: Great!
    John->>Bob: How about you?
    Bob-->>John: Jolly good!
```

VSCodeで`command + shift + P`でコマンドパレットを開き、`mermaid`などと検索して`> Preview Mermaid`を選択すると、画面右にプレビューが表示されます。

![ 2020-10-10 20.10.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686583/2101186d-b8cc-635d-bd60-58f95423e3cc.png)

## エクスポート
保存した`test.mmd`をPNGにエクスポートしてみます。ターミナルに戻って

```bash
$ mmdc --input test.mmd --output test.png --backgroundColor transparent
```

などと実行すれば、背景が透過された`test.png`を出力できます。コマンドのオプションなどは`$ mmdc --help`で参照してみてください。テーマなども変更できるらしいです。出力できたPNGがこちら。

![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686583/29fa07d3-f2b6-2dac-9ea1-4da6e0032cf2.png)
grafanaとpostgresを連携してみた【docker-compose】

# 起動方法
```bash 
git clone https://github.com/guedim/grafana-postgres.git
docker-compose up -d
```

# grafanaへログイン
ブラウザから http://localhost:3000/ へアクセス
**user** : admin
**password**: foobar
でログインする。
(grafana-postgres/grafana/dashboard/post.sh にて設定してある)

# grafanaのGUIでの設定方法
Add data sourceを押して、postgresを設定する
一番難しいところが以下の設定場所。Host名がlocalhost:5432ではなくて、**postgres:5432**に設定する

![grafana_postres_setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610591/3106ffd3-4501-7436-0c8e-1847fa79e564.png)
入力後、**Save & Test**を押してDatabase Connection OKが出れば連携完了。

# テーブルを可視化
dashboard > table > edit でsql文を書ける画面が出てくる。
https://github.com/guedim/grafana-postgres.git には元々データが入っているので、そのデータを表示した。
![tableのeditを選んでsql文を書いた.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610591/c05ad7d1-2a9e-0931-6219-8ecd616f2edb.png)

# postgres のデータをみる
```bash
docker-compose exec postgres bash
su postgres
psql
\d #テーブル一覧表示
\l #database一覧を表示
\d account_metrics #カラム一覧を表示 カラムなのでデータベースを指定してから 
\q #exit
```
M5ATOM(ESP32)で簡易プレゼンリモコンを作ってみる

前回のマウスに引き続き、ArduinoIDE環境用の **ESP32をBLEキーボードにするライブラリ** を使ってパワポやpdfでのプレゼンでページ送りをする「簡易プレゼンリモコン」を作成してみました。

# 作ったもの
今回もデバイスは **[M5Stack](https://m5stack.com/ "M5Stack") の小型モジュールである [M5ATOM Lite](https://m5stack.com/collections/m5-atom/products/atom-lite-esp32-development-kit?variant=32259605200986 "M5ATOM Lite")** を使用しました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">M5ATOM LiteとESP32-BLE-Keyboardで簡易プレゼンリモコン作成。短押しでページ送り、長押しでページ戻り。長押し判定を敢えてM5.btn関数でやろうとしてちょったハマった位でサクッとできて楽しい<a href="https://twitter.com/hashtag/M5Stack?src=hash&amp;ref_src=twsrc%5Etfw">#M5Stack</a> <a href="https://t.co/VfKg0v83br">pic.twitter.com/VfKg0v83br</a></p>&mdash; tomorrow56 (@tomorrow56) <a href="https://twitter.com/tomorrow56/status/1314824118479409152?ref_src=twsrc%5Etfw">October 10, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

前回も書きましたが、M5ATOM LiteはESP32・フルカラーLED・ボタンが2.5x2.5cmのケースにコンパクトに納められており、オフィシャルストアで$5.95、 [スイッチサイエンスで買っても968円](https://www.switch-science.com/catalog/6262/)とコストパフォーマンスが非常に良いのでお勧めです。

# 作り方
## ESP32 BLE Keyboard libraryの導入
T-vk氏がgithubで公開しているので、ダウンロードしてArduino IDEのLibraryフォルダに解凍します。
[ESP32 BLE Keyboard library](https://github.com/T-vK/ESP32-BLE-Keyboard "ESP32 BLE Keyboard library")
examplesに **SendKeyStrokes** というスケッチがあるので、これを参考に作成しました。

## ざっくりした仕様
Amazonでプレゼンリモコンを検索すると大体2500円位しますが、まあページ送りができれば自分としては十分なので、Windows PCでのプレゼンのページ送りと戻しに特化しました。

- M5ATOMのボタンを**短押し**すると**次ページへ送る**(右矢印キーを送信)
- M5ATOMのボタンを**長押し**すると**前ページへ戻る**(左矢印キーを送信)
- 長押しの時間は変数で持たせる(デバッグしやすいので)
- PCとの接続状態やボタンの操作はM5ATOM Lite上のLEDの色を変えて知らせる

## 作成したスケッチ
コードは非常にシンプルです。長押し判定はせっかくなのでM5.btn関数を使いました。
ボタンのONを検出したら一定時間待って再度ボタンの状態を確認して判定しています。
**M5.Btn.wasPressed()**関数はキーの状態がOFF->ONに変化した時に1度だけ発生しますので、この関数内で処理することにより押しっぱなしで連続動作することを避けています。

```M5Atom_KB_presen.ino
#include "M5Atom.h"
#include <BleKeyboard.h>  // https://github.com/T-vK/ESP32-BLE-Keyboard

BleKeyboard bleKeyboard("M5ATOM KB");  //デバイス名

const int longPress_ms = 300;  // 長押し判定時間(単位 msec)

void setup() {
  // M5.begin(SerialEnable, I2CEnable, DisplayEnable);
  M5.begin(true, false, true);
  M5.dis.drawpix(0, 0x000000);  // LED OFF

  //Serial.begin(115200);
  Serial.println("Starting BLE work!");
  bleKeyboard.begin();
}

void loop() {
  M5.update();
  if(bleKeyboard.isConnected()){
    if(M5.Btn.wasPressed()){
      // M5ATOMのボタンが押されたら一定時間待つ
      delay(longPress_ms);
      if(M5.Btn.read() == true){      // キーが押されたままだったら長押しと判定
        M5.dis.drawpix(0, 0x00f0f0);  // LED MAGENTA
        Serial.println("<-Page Back");
        bleKeyboard.write(KEY_LEFT_ARROW);
        delay(100);
      }else{                          // キーがリリースされていたら短押しと判定
        M5.dis.drawpix(0, 0xf00000);  // LED GREEN
        Serial.println("Page Forward->");
        bleKeyboard.write(KEY_RIGHT_ARROW);
        delay(100);
      }
    }
    M5.dis.drawpix(0, 0x0000f0);  // LED BLUE
  }else{
    M5.dis.drawpix(0, 0x00f000);  // LED RED
  }
  delay(10);
}
```

# まとめ
送信するキーコードを変更すれば、パスワード入力やウインドウ操作等にも使えます。
ESP32 BLE Keyboard libraryのヘッダファイル(**BleKeyboard.h**)にはキー定義一覧があるので、これを参考にしてください。
「LGTM」や「ストック」、SNSでのシェアをしていただくと筆者の励みになるのでよろしくお願いします。
【Vue.js + (laravel)】画像データをPOSTしたい


Vue.jsで画像データをPOSTしたかったのでformDataを使って実現しました

【画面側】
type="file" の入力欄と送信ボタンを用意
画像の選択(input)が行われたとき、送信ボタンが押されたときにそれぞれ処理を行う

```html
 <template>
     <input @change="fileSelect" type="file" name="file">
     <button @click="upload" type="submit">送信</button>
 </template>
```


【js側】
この場合はTestViewという名前でコンポーネントを作っています。

```js
<script>
    export default {
        name: "TestView",
        data: function () {
            return {
                selected_file: null
            }
        },
        methods: {
            //ファイル選択時の処理
            fileSelect: function(e) {
                //選択したファイルの情報を取得しプロパティにいれる
                this.selected_file = e.target.files[0];
            },
            //送信処理
            upload: function() {
                //formDataをnewする
                let formData = new FormData();
                //appendでデータを追加(第一引数は任意のキー)
                //他に送信したいデータがある場合にはその分appendする
                formData.append('file', this.selected_file);

                let config = {
                    headers: {
                        'content-type': 'multipart/form-data'
                    }
                };

                axios.post('/product', formData, config)
                    .then(function(response) {
                        console.log('成功')
                    })
                    .catch(function(error) {
                        console.log('失敗')
                    })
            }
        }
    }
</script>
```


【Laravel コントローラ側】
サーバ側でのデータの受け取り方

```php
 public function test(Request $request)
    {
        //js側で設定したキーを指定
        $file = $request->file('file');
    }
```
pythonでPDFをfoxit readerを利用してプリンタ指定サイレント爆速印刷しよう！

## 開発環境
os:windows10
言語:python3.7
使うソフト:foxit reader

## foxit readerのインストールについて
窓の社さんから無償版をダウンロードすると楽です。
https://forest.watch.impress.co.jp/library/software/foxitreader/
公式サイトからダウンロードしようとすると無償版（閲覧・印刷のみ)のものでもメールアドレスなどの登録が必要みたいです。

## 自分の中で必要だった印刷要件
・少し複雑な形式の書類も大丈夫。
・印刷スピードが早い（１秒)
・単純な手順であること。

## pythonの印刷方法
<dl>
<dt>win32</dt><dd>直接テキストデータを送って印刷するものしかなかった。</dd>
<dt>adobe PDF Reader</dt><dd>adobe PDF Readerのコマンドを使って印刷するもの。
下記の記事を参考に作成。
https://qiita.com/hrs_sano645/items/e0fcf5d896b70822e998
当初はこれを採用する予定だったが実装段階で
印刷からでてくるまでに３秒ほどかかることが発覚。
一瞬CPU占有率が１００％いくときがある。
adobe PDF ReaderのGUI画面が表示されるし。
これにより違うやり方を模索する。</dd>
<dt>ghost scripter</dt><dd>ghost scripterというのを見つけた。
しかし日本語フォントに対応させるのに大変なので却下。</dd>
<dt>foxit reader</dt><dd>「これからPDFは『赤からオレンジの時代』」
　思いっきり煽った宣伝文句が飛び込んでくる
  adobe PDF readerの対抗ソフト
　その文句に負けない機能の優位性が沢山！
　テキストベースで作ったPDFの印刷速度がすごい速い
　(スキャンしたPDFはほぼ同じスピードです。)
　コマンドから印刷するとGUI画面が表示されずサイレント印刷が可能。
　CPUの使用率が50％以下である
　コマンドがadobeのコマンド形式と似ているのですぐ習得できる。</dd>
</dl>　
## 実装は以下の手順。
foxit readerの標準インストールしてください。
このままだったらただのfoxit readerをインストールしただけです。
ここからがマグマ流プログラミングです。
・下のfoxit.pyのソースコードをコピペする
・コントロールパネル >「デバイスとプリンタ」>使用したいプリンタ名を右クリック > プリンタのプロパティ > プリンタ名を一字一句間違えずにコピペ >プリンタ名をソースコードの"プリンタ名"にコピぺ
・印刷したいPDFファイルのパスをソースコードの'pdf_name'にコピペ
実行！やーーーーー！
これで爆速印刷が可能になります！
　

コマンドラインは以下を参考に作っています。
https://www.lifedesignedit.com/use_foxit_pdf_command_line_options

```foxit.py
#foxit_reader経由で印刷する
import subprocess

#プリンタを指定した場合のものです。
#デフォルトプリンタでのやり方も可能。
#詳しくはFoxit Readerを起動して、ヘルプ>コマンドラインオプションで
def print_PDF_file_via_foxitReader(pdf_name,printer_name):
    # foxitのパスは標準インストールした場合です。環境よってちがうかも。
    foxit_exe = r"C:\Program Files (x86)\Foxit Software\FoxitReader\FoxitReader.exe"　
    print_cmd = '"{}" /t "{}" "{}"'.format(foxit_exe,pdf_name,printer_name)
    subprocess.Popen(print_cmd)


if __name__ == '__main__':
    pdf_name = 'pdf_name'
    print_name = 'プリンタ名'
    print_PDF_file_via_foxitReader(pdf_name,printer_name)
```

なにか間違いがあったら言ってください。
[初心者向け]Vue.js 重要単語集

# Vue.js
- 簡単に言うと、ユーザーインターフェイスを構築するためのフレームワークのこと
- JavaScriptでDOMを操作するWebアプリケーションを構築するときに向いている
- DOMよりも先にデータが存在していて、それに合わせてDOMが構築される
- HTMLベースのテンプレート構文を使っているので、Vueインスタンスのデータと描画をDOMを宣言的に対応させることができる

## Vueインスタンス
```javascript
var app = new Vue({
  //下記などのオプションを記述する
})
```
### el
アプリケーションを紐付ける要素のセレクタ

### data
アプリケーションで使用するデータ、オブジェクトや配列も登録できる

### computed
dataと似たように扱うことのできる、関数によって算出されたデータ、算出プロパティ

### mothods
このアプリケーションで使用するメソッド、コードを管理しやすくするために処理を分けたり、イベントハンドラなど細かな実装を担当する

## DOM
- JavascriptからHTMLやCSSのデータを取得、操作するための仕組み

## データバインディング
- データと描画を同期させる仕組みのこと
- JavaScriptとのデータとそれを使用する場所を紐付け、データに変化があれば自動的にDOMを更新する

## ディレクティブ
- 接頭辞「 v- 」が付いたVue.jsの特別な属性のことで、テンプレートとロジックを関連付ける
(下記が代表的なもの)

### v-for
配列やオブジェクトから要素を繰り返し描画する

### v-on
DOMイベントのハンドリングに使う

### v-model
データとフォームの入力項目のバインド(関連付け)をする

### v-if
テンプレートベースで条件分岐をする

## コンポーネント
- 再使用可能なVueインスタンスを作ること
- 機能ごとにJavaScriptとテンプレートを1つのセットにして、他の機能とは分離して開発できるようにする仕組み
新人エンジニアが AWS Black Belt オンラインセミナー の魅力を語ってみた

# はじめに
約３ヶ月間、それなりにボリュームのある新規開発で AWS周りをガッツリやらせてもらいました。

AWS や新規開発について学ぶことが多かったので何回かに分けてまとめてみたいと思います。
これから AWS をガッツリ使っていこうと思っている方の参考になれば幸いです。

バックナンバーはこちらからどうぞ！

- [新人エンジニアがインフラのコード化（IaC）に３ヶ月取り組んで見えた知見をまとめてみた](https://qiita.com/tasurom/items/32162ae85cb9100b1850)

今回はその第２回、 **AWS Black Belt オンラインセミナー** 編です🎉

## AWS Black Belt オンラインセミナー とは？
>AWS Black Belt Online Seminar シリーズは、製品・サービス別、ソリューション別、業種別のそれぞれのテーマに分かれて、アマゾン ウェブ サービス ジャパン株式会社が主催するオンラインセミナーシリーズです。

https://aws.amazon.com/jp/about-aws/events/webinars/

![bbimage.d6eb739a7f4118fefd5e38f44b3ad7065247c527.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574222/6b53a98f-4406-2700-b7bc-7972d401eb2b.jpeg)

## 何が良いのか？
- YouTube でいつでも好きなように見られる(https://www.youtube.com/playlist?list=PLzWGOASvSx6FIwIC2X1nObr1KcMCBBlqY)
- 公式情報であることの信頼性
- 体系的な情報
- 分かりやすい説明
- 頭の中にインデックスを作るのに最適

### YouTube でいつでも好きなように見られる
これはオンラインセミナーならでは。当然ですが、非常に助かります。

動画だからこそ難しいところは巻き戻してじっくり聞いても良し、必要なパートだけをサクッと確認するも良し。

### 公式情報であることの信頼性
オンライン記事も参考になることが非常に多いのですが、情報が古くなっていたり間違っていたりすることがあるのはご存知の通りです。

もちろん公式でも情報は古くなりますし、動画という特性上、ドキュメントと違ってアップデートがしにくいかと思います。
しかし信頼性に関してはかなり高いレベルで担保できるので、考慮するのが情報の新鮮度だけになります。

それに、動画の冒頭では必ず免責事項として 20xx年〇〇月〇〇日 時点の情報です、とアナウンスがありますのでそこだけ見ればOKです。

余談ですが、多少小難しい言い回しをされたとしても出来る限り最初から公式リソースを使って学習するのが結局効率良いと思っている派です🤔

### 体系的な情報
AWS もビジネスです。自分たちの製品を使ってもらおうというマーケティングの一部としてこのようなコンテンツを公開しています。
なのでそもそもの前提知識が抜けたまま進まないように配慮されていて、非常に体系的です。

大体基礎から始まり、最後の方はコストなど管理者向けの話になっていくことが多いように思います。

新しいサービスを学ぶ時にはまず王道を体系的に学んでみてからそれぞれのユースケースに応用してみてはいかがでしょうか？

### 分かりやすい説明
ブラックベルトとはすなわち黒帯なので、結構難しいんじゃないかという印象を持たれる方も多いと思います。
確かに後半は少し難しい話が出てくる場合も多いのですが、それも含めて非常に分かりやすく説明してくれています。

おそらく資料も発表の仕方も含めて分かりやすくなるようなノウハウが AWS 社内で共有されており、それに従って担当者の方が発表してくださっているんだと思います。
どの発表も分かりやすく、説明する人によっての質のバラつきが少ないのが印象的です。

「そもそもどうしてこのサービスが必要なのか？」というところから分かりやすく説明してくれますよ😊

### 頭の中にインデックスを作るのに最適
このように素晴らしいオンラインセミナーですが、デメリットもあります。  
それは動画コンテンツなのでリファレンスとしては使えないということです。

なので役割分担としては必然的に、

- オンラインんセミナーで頭の中にインデックスを作る
- 開発を進める中での細かいことなどはドキュメントを見る

ということになると思います。

**まずは頭の中にざっくりしたインデックスを作ってあとはとにかく実際に手を動かす** というのは学習で非常に大切ですよね！！

先ほども述べたように体系的かつ割と網羅的なのでインデックスを作るのに適しているコンテンツだと思います

## 自分流 AWS 学習ステップをまとめてみた
学習方法は人それぞれに合ったものが１番ですが、参考になればということで偉そうに書いておきたいと思います😂

1. AWS Black Belt オンラインセミナー をメモを取りながら１回見る（頭の中にインデックスを作るのが目的）
2. そのサービスはどんな場合に有効なのか、よく使われるのか、ネット上の記事を見ながらざっくり把握
3. **AWS マネージドコンソールから** そのサービスを使ってみて設定する必要のあるプロパティなどを見てみる（コード化しない）
4. 実際に使う(ここからは基本公式ドキュメントを参照する)

という感じで大体いけるはずです。公式のチュートリアルが用意されているサービスも多いのでそちらもやってみても良いかもしれません😎

## おわりに
AWS Black Belt オンラインセミナー のおかげで AWS の右も左も分からない状態から幅広いサービスを習得して実務で使えるまでになりました。
本当に良いコンテンツだと思いますので、新しい AWS サービスを学習する際には是非活用してみて下さいね！！
PyPIへのモジュール公開手法がいろいろ変わっていたのでメモ

PyPIへのモジュール公開手法がしばらく見ない間にだいぶ変わっていたので備忘録としてメモしておきます。

# 何を公開したの？

こちらです。

* [tksugar · PyPI](https://pypi.org/project/tksugar/)

いまのところドキュメントと言えるドキュメントはGitHubだけです

* [TakamiChie/TkSugar: A module that generates a structured Tk window frame from a text file\.](https://github.com/TakamiChie/TkSugar)

# setup.cfg

わたしが昔PyPIを触っていたときは、`setup.py`にいろんな設定を書き込むことで、モジュールの設定を記載していたのですが、今は`setup.cfg`というファイルにモジュールの情報を書き込むようになったようです。

```config:setup.cfg
[metadata]
name = tksugar
version = attr: tksugar.__version__
author = TakamiChie
author_email = [mail]
license = MIT
description = A module that generates a structured Tk window frame from a text file.
keywords =
url = https://github.com/TakamiChie/TkSugar
long_description = file: README.md
long_description_content_type = text/markdown
classifiers =
    Programming Language :: Python :: 3.7
    Programming Language :: Python :: 3.8

[options]
packages = find:
install_requires =
  pyyaml
```

とりあえず今回の件で気になるところ。

## version
あらかじめ、アップロードするモジュールの`__init__.py`に、次のような定数を追加しておきます。

```py:__init__.py
__version__ = "0.1.0"
```

わたしの場合`__init__.py`は`root\tksugar\__init__.py`に置いていたので、このような既述でよかったのですが、たとえば`__VERSION__.py`というファイルを作ってそこに定義したいとか、`root/src/project/__init__.py`にしたいときとかは既述が変わってきますので注意。

## long_description
読んで字のごとく長い説明文です。README.mdを読み込んでそのまま表示しています。
この文章がPyPI.orgのサイトの右側に表示されます。

Markdown形式の場合は、必ず`long_description_content_type`とセットで記載しましょう。エラーで止まります。

## classifiers
PyPIのサイトにある分類です。iniファイルっぽいですが一行に1つずつ書き込めます。分類の内容はPyPIのサイトを確認してください。

## install_requires

書き方はclassifiersと同じです。上記の既述は`Pipfile`の`pyyaml = "*"`と等価です。

# アップロード

1. 参考記事に6従い`.pypirc`を作る。Windows 10の場合`C:\Users\[UserName]`のフォルダに保存する
2. `pip install twine wheel`する(いろいろ苦戦していたので他のこともやっていたかもしれない)
3. `python setup.py sdist bdist_wheel`する
4. `twine upload --repository testpypi dist/*`する
5. 問題なければ`twine upload --repository pypi dist/*`する

以下のようなコードを`Pipfile`に作っておくとあとが簡単です(参考文献6の内容はWindowsではないので適宜修正/`pipenv run`はPowerShellでなくコマンドプロンプトで動作してしまうようなので適宜調整)

```ini:Pipfile
[scripts]
clear = "pwsh -c Remove-Item -Recurse -Force *.egg-info, build, dist"
build = "python setup.py sdist bdist_wheel"
deploytest = "twine upload --repository testpypi dist/*"
deploy = "twine upload --repository pypi dist/*"
```

# 注意点

この手の操作方法は割と頻繁に変わるので、ググるときは期間指定を「1ヶ月以内」にするなどして対策しましょう。半年以上前の記事だとどこかしら内容が変わっている可能性があります(記述の内容についてはそれ以前の記事も参考になりますが)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14499/bd98513e-f39d-f46a-b259-c1e8a7e41ead.png)


# 参考文献

1. [pythonのsetup\.pyについてまとめる \- Qiita](https://qiita.com/Tadahiro_Yamamura/items/2cbcd272a96bb3761cc8)
2. [【Techの道も一歩から】第21回「setup\.pyを書いてpipでインストール可能にしよう」 \- Sansan Builders Blog](https://buildersbox.corp-sansan.com/entry/2019/07/11/110000)
3. [Python の setup\.py の内容を setup\.cfg で管理する \- astropenguin](https://astropengu.in/posts/23/)
4. [PyPIデビューしたい人の為のPyPI登録の手順 \- Qiita](https://qiita.com/kinpira/items/0a4e7c78fc5dd28bd695)
5. [\_\_version\_\_の罠とベストプラクティス \- Qiita](https://qiita.com/utkamioka/items/b62d0e03f1bc1aed5df7)
6. [Python パッケージをローカルから PyPI にアップロードするときの設定 \- Qiita](https://qiita.com/y_shinoda/items/36697034b1ec10af3948)
複数のQAチームのテスト設計技法をまとめて統一化してほしくないという心の叫び

## この記事について
新卒で配属されたQA部門に2年8ヶ月いてみて感じた心の叫びを
垂れ流す記事になっています

自分はあまり文章が得意ではないので稚拙な文章になりますが
どうぞよろしくお願いします

## はじめに
どこにでもいる若造の戯言と思って読んでいただけるうれしいです

###自分について
・高卒で某電気メーカに入社し、一年間集団研修を受ける
・とある事業部のQA部門に配属されそのままソフトウェアテストにドはまり

###QA部門について
・総勢90名以上の大人数
・製品の機能ごとにチーム割されていて十数チームほど存在（チームごとの人員はばらつきが多くある）

自分は2チームを渡り歩いてきたので最初にいたチームをAチーム
今在籍しているチームをBチームとしています

###Aチーム
・人が多くいる(10人以上)
・担当機能は3つ存在
・担当機能は最近市場でよく使われることから新規要件の追加や市場からのクレームが多く来る

###Bチーム
・Aチームに比べると人は少ない(7人、最近人が良く減る)
・担当機能は4機能+QA以外の認証取得業務等が多数存在
・担当機能はほとんど成熟されているが使い手も多く思いがけないバグを孕んでいることが多い


このような状態でとあるお触れが出ます
**テスト技法を統一化し、チェックリスト生成までのプロセスを固定化します**

ん？？？？？

自分は思いました
**こんなたった2チームだけでも性質の違うのにほかの十数チームのテスト設計を統一できるのか？**と…

## 各チームについて詳しく書いてみます
###Aチームの場合
人員としては多いもののその機能についての知識が少ない人が多かったです
40代～50代が大多数でソフト系の知識を持つ人は1~2人程度しかいませんでした
担当機能の特性としてRFCやIEEEの規格を頭に入れておかないといけないので
毎週のように勉強会が開かれていましたが、なかなか身につかない状態でした
しかし業務はプロダクトが一度に5~8個常に走っている状態で怒涛のテストが続きます

人員の技術レベルに対して、業務量が見合っていない地獄でした

テストの毛色としては複数の設定値を組み合わせる評価が多く
網羅度が重要視されチェックリストが無限に生産されていました

**故に毎回にテスト対象が非常に広く過剰評価では？と思うことも多々ありました**

###Bチームの場合
人員7名としましたが認証業務などのQA以外の業務に人員が割かれているため
担当機能を評価していたのは4名でした
うち自分を除く3人が担当機能の管理業務をしており、リーダ兼評価者という体制でした
ですがソフトウェアの知識や担当機能に対する知識は非常に豊富でまさに少数精鋭という状態です
前述のとおりプロダクトは一度に5~8個常に走っている状態なので常に人手不足状態

それを解消するために**テスト対象を大幅に減らして必要最低限の評価を行っていました**

テストの毛色はAPIテストが多く他チームの機能やアプリとのマッチングが主でした

また、追加要件に対し、探索テストを実施したりとテスト項目の選定にも多くの知識を必要としました


###まとめると

| 　| テストの主な種類 | 実施するとき|
|:--|:--|:--|
|Aチーム| 網羅的な組み合わせテスト | チェックリストにあるものをひたすら |
|Bチーム   | 組み合わせテスト、状態遷移テスト、探索的テスト | チェックリストから項目を選定して評価 |

これだけ違うのに
>**テスト技法を統一化し、チェックリスト生成までのプロセスを固定化します**

**こんなことできるか！！！と思いました**

##これから起こる弊害
テスト対象の性質に合わないテストはもちろん
**チェックリストの質の低下(カバレッジの低下)**
↓
**テスト対象のバグが取り除けなくなる**
↓
**製品の品質の低下**
↓
**事業の衰退**

容易に想像できますね
テスト設計が適切に行われなくなるのでチェックリストの質が大きく落ちるわけです

##これから

もちろん自分を含むBチームは猛反対しています

もともと
>**テスト技法を統一化し、チェックリスト生成までのプロセスを固定化します**

その目的は、**チェックリストの品質の統一**と**テスト設計の標準化**にあるのですが…

もっと別の方式がいいかなと思いますね
例えば
単純にテスト設計の技術力を高めたいのであれば
・テスト設計の勉強会をする

テスト設計の標準を作りたいのであれば
・ガイダンスや虎の巻程度の目安にするものを作成する

などなど


以上、最近感じた
複数のQAチームのテスト設計技法をまとめて統一化しないでほしいという心の叫びでした
Dockerを使ってサクッとGoアプリケーション構築

# はじめに
Dockerを使ってGo言語の開発環境を構築し、アプリケーションを動作するまでの手順をまとめました。

# ファイル作成

```shell
mkdir go_project
cd go_project
touch main.go
touch Dockerfile
```

# ファイル修正

```main.go
// サーバーアプケーションとして動作し、以下の挙動をします。
// ●どんなHTTPリクエストに対しても「Hello Docker!!」とレスポンスする
// ●8080ポートでサーバアプリケーションとして動作する
// ●クライアントからリクエストを受けた際は、received requestのログを標準出力に表示する
package main

import (
	"fmt"
	"log"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter,r *http.Request) {
		log.Println("received request")
		fmt.Fprintf(w, "Hello Docker!!")
	})

	log.Println("start server")
	server := &http.Server{Addr: ":8080"}
	if err := server.ListenAndServe(); err != nil {
		log.Println(err)
	}
}
```

```Dockerfile
FROM golang:1.9

RUN mkdir /echo
COPY main.go /echo
CMD ["go", "run", "/echo/main.go"]
```

# イメージのビルド

```
docker image build -t go_project .
```

# イメージの確認

```
docker image ls
```

# コンテナの起動

```
docker run -d -p 9000:8080 go_project
```

# GETリクエストの確認
Hello Docker!! が返って来ることを確認します。

```
curl http://localhost:9000
```
[Azure] デプロイセンターのブランチを変更する方法

# はじめに

Azure App ServiceにGit（GitHub含む）を使用してデプロイしている場合についてです。

Azureポータルのデプロイセンターでは構成時に設定したブランチからデプロイされるようになっていますが、Azureポータルからはこのブランチを変更する機能がありません。

つまり一度デプロイを切断して再構成することになってしまうのですが、切断せずに変更する方法を説明します。

![before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595926/ae26a218-6a2a-4ec2-93ee-d7fd68e75450.png)

# ブランチを変更する方法

ブランチはKuduサービスでREST APIを呼び出すことで変更できます。

具体的な方法はここで説明されています。
[Deployment branch](https://github.com/projectkudu/kudu/wiki/Deployment-branch)

```bash
# Switch branch (/settings endpoint)
$ curl https://<user>:<pass>@<site>.scm.azurewebsites.net/settings \
       --data "{key: 'branch', value: '<branch>' }" \
       -H "Content-Type: application/json; charset=UTF-8"
```

`<user>`と`<pass>`はデプロイユーザの情報です。「発行プロファイルの取得」などから確認してください。
`<site>`はApp Service名です。
`<branch>`は変更したいブランチ名です。

実行するとブランチが変更されます。デプロイセンターの画面を更新して変更されたことを確認してください。
※ 2020/10/10現在、「最新の情報に更新」をしてもブランチなどの基本情報は更新されません。一度別のページに移動するか、ブラウザから更新してください。

ブランチが切り替わったらデプロイしましょう。
デプロイセンターの同期から新しいブランチでデプロイを開始します。
APIを利用してデプロイしたい場合は、その例も先程のwikiに記載されています。

# バッチの紹介

先程のコマンドを使用してバッチファイルを作成しました。

[blue32a/azure-change-deploy-branch](https://github.com/blue32a/azure-change-deploy-branch)

例えばKuduサービスから適当なディレクトリにバッチファイルを置いて実行できます。
RRNで数独を解く！！


[Relational Network](https://qiita.com/SoseSose/items/d8087978d64432083205)の続きです。RRN（Reccurent Relational Network)です。めっちゃ時間かかりました。とりあえず論文のリンクを<https://arxiv.org/abs/1711.08028>。Tensorflow2での実装がなかったので自分で実装したら、迷路に迷い込みました。コードはここ→<https://github.com/rasmusbergpalm/recurrent-relational-networks>を参考にしました。

## RRNの形式

RNでは
$RN(O)=f_ϕ(\sum_{i,j}g_θ(o_i,o_j))$
としていたものをRRNでは
$m_{ij}^t = f_{\phi}(h_i^t,h_j^t)$
$m_j^t=\sum_im_{ij}^t$
$h_j^t=g_{\theta}(h_j^t,h_j^0,m_j^t)$
のようにします。ここで$i,j$は各ノードの添え字、$t$は時刻の添え字、$h_i^t,h_j^t$はノードi,jの状態ベクトル、$m_{ij}^t$はノードjからノードiへのメッセージベクトル、
この式を見てやっとわかりました。RNもRRNもGraph neural networkの一種だったんですね。$\sum$の理由が分からなかったんですが、エッジのあるノード間が窓になっているようなCNNと思えば、なんとなく納得できました。上記の式以外の形式のGraph neural networkもいくつもあるみたいです。→<https://qiita.com/shionhonda/items/d27b8f13f7e9232a4ae5>

## RNNの実装

まあ、ひどい実装です。直したいところはいくらでもありますが、とりあえずは動いたので載せるといった感じです。
実装したリポジトリ→
参考にしたリポジトリ→https://github.com/rasmusbergpalm/recurrent-relational-networks

## RNNの結果

テストデータの正解率だけで言えば、残念ながら20%を少し下回る結果です。ただし、学習している傾向は見て取れるます。下のgifの画像は訓練後のネットワークの各時刻における出力です。数独のルールに基づいて回答を様子が分かります。
![ezgif.com-gif-maker (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595608/6b8fafb4-2747-d280-ae84-bb010075f53c.gif)
正解率が低い理由としては最後の詰めが甘いようです。特に最初に空きマスが多いとなかなか各ノードの状態ベクトルが収束せず、ステップ数不足で間違える用です。

## 問題点

1.損失をどのように与えたら良いのかが難しい。
数独ではそのタイミングでは明らかに埋められないマスと埋められるマスがあります。あそこのマスが埋まったからこちらのマスも埋められるという思考のステップが必要になります。しかし、今回のプログラムはすべてのステップで全てのマスに対して損失を与えています。絶対に埋められないマスがあるにも関わらず損失を与えるのは理不尽に思えます。もちろんそれでも学習はするのでしょうが、むしろノイズとなってしまって学習の妨げになっている可能性もあると思います。解決策としては強化学習で損失にマスクをかけるとかでしょうか。
2.ルールをハードコーディングしている部分がある
作成したモデルではノードの接続は数独のルール（縦、横、同じ3x3のマスとは違う数字となる)に従った接続になっています。これはドメイン知識を活用しているという見方もできますが、汎化性能を下げる要因になります。実際に解きたいARCでは問題によって、ノードの接続は変化するべきです。一番簡単な実装は全接続ですが、これもノイズを増やす原因になりえると思っています。Attenntionの枠組みを使って接続するノードを制限するといったことも考えています。
3.学習の不安定さ
モデルが完成してから、起きた問題として学習の不安定さがあります。optimizerの学習率を上げすぎるとlossの減少速度は上がるが、学習が進んだあるタイミングでlossがまた上がり始めるという現象が起きるということが何度も試しているうちにわかりました。原因はよく分かりませんが、重みの値が発散している可能性を考えています。そのために重みに制限を持たせて、少しはましになった様子もありますが、それでも学習率を下げないとその現象が起きます。この問題に長い時間、悩まされました。リカレントな構造を持っていることも原因かもしれません。ARCを解くための問題にならなければいいのですが。
4.実行速度
学習にかなり時間がかかります。今回の正解率を達成するためだけでも2日ほど学習時間がかかったはずです。（正確に測定はしていません）多層のMLPを使うのでそれなりの計算量がかかります。計算量の削減も課題でしょう。時間は惜しいです。ハード面で解決するという手もありますが。

## 終わりに

本当にこんな時間がかかるとは。元論文のコピーをするだけと思ってたのに。まあ、Tensorflow2.x系の勉強にはなりました。それにネットワークが数独を解く動画は本当に思考の様子を見ているようで面白いです。またこれもひどい記事ですね。とりあえず、論理みたいなものを扱う、neural networkはできました。（改善点は驚くほどありますが）次はfewshot leaningやります。それ以外に強化学習とかattentionも必要なきがしてきたし。大変だなあ。
備忘録：VSCode でGCPインスタンスにSSH接続する際の注意

## 何の備忘録？
- WindowsローカルマシンのVSCodeからGCPに接続する方法を**一応**書いている（準備）
- VSCode上でSSH設定する場合に注意すべき点（__これ__を残しておきたいだけ）

### 準備
WSL（Windows Subsystem for Linux：Windows上でLinuxディストリビューション（UbuntuやDebianなどがMicrosoft Storeで配布されている）のターミナルを使用できるシステム）で鍵を生成する方法を載せておく（`<>`で囲まれた部分はそれぞれ自身の環境に依存するため読み替えるように）．

```bash
$ ssh-keygen -t rsa -b 4096 -C "<GCP user email address>"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/<username>/.ssh/id_rsa): <Enter> or <Enter Path You want to save the key>
Enter passphrase (empty for nopassphrase): <Enter> or <password>
Enter same passphrase again: <Enter> or <Enter the same password above>
Your identification has been saved in <savepath>
Your public key has been saved in <savepath>
The key fingerprint is:
SHA256:<sha256 fingerprint>
The key's randomart image is:
+---[RSA 4096]----+
| <some char art> |
+----[SHA256]-----+
$
```

ほかのインスタンスですでに`id_rsa`が作成されていたら，別のrsaファイル名に変えておく（例えば，`id_rsa2`）．

Windowsでも作成できるものの，著者の経験としてシステム開発ではLinuxを標準としていることが多いため，Windowsのコマンドに関しては言葉を知らない赤ちゃんレベルに何もわからない．

さて，無事作成された鍵であるが，デフォルトで指定したパスで保存した場合，WSLからしかアクセスできない場所にあることに注意が必要である．

これが以下のConfigを設定するときにパスが煩雑になってしまうため，備忘録として残しておく．

## 本論的内容

VSCode 上で GCP 上に作成したインスタンスにssh接続したい場合，標準的にはconfigファイルが作成される．以下の形式のように．

```config
Host <Arbitrary Host name>
    HostName <External IP address>
    User <UserName> (_付きのデフォルトユーザーはNG）
    Port 22 (default)
    IdentityFile <~/.ssh/id_rsa by default>
    IdentitiesOnly yes
```

### いいたいこと
ここで，`IdentityFile ~/.ssh/id_rsa`の部分！WSLユーザーなら`~`はWSL上のホームディレクトリーを指していると思うかもしれない（自分はそう思い込んでいた！）．しかし，これはWindowsのホームディレクトリである．つまり，`~`＝`C:\Users\ユーザ名`なのである！

だから，**WSLで作成した鍵の保存パスを参照しない！**
よって，WSLで作成した場合，WSLターミナルで`C:\Users\ユーザ名\.ssh\`に`id_rsa`と`id_rsa.pub`を移動（コピー）する必要がある．

※ `IdentityFile`のところで直接WSLで作成した鍵のパスを書けばいいと思うかもしれないが，筆者は勧めない．まず，WSLのパスとWindowsのパスは共有されていないため，直接パスを見つけることは容易でないうえ，WSLも設計上，Windowsアプリからの直接のパス参照は非推奨としているはずである．そもそも，WindowsのパスでWSLのホームディレクトリはどこにあるのかも不明である（探せばあるかもしれないが，そんなことはしないほうがいいのは当たり前）．

### 追記
dockerをsudoなしで一般ユーザーで使用するためには，
`$ sudo gpasswd -a <username> docker`
を実行するようにね．
[Python]loggingモジュールざっくり理解


## 登場人物

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406130/9b097021-72ca-bfd0-9b0e-ab2911a15090.png)

__Loggerクラス__ : loggingの主体のはこいつ。ログの生成から目的の場所まで送るまでを管理する。Loggerクラスから生成されるオブジェクト毎にHandlerやFilterを設定できる。Loggerは階層構造(後述)をとり、継承により親の設定を引き継ぐ。

__root (rootLoggerオブジェクト)__ : デフォルトのLoggerクラスのオブジェクトであり全てのロガーの親。必ず1つ。`logging.info()`等で書かれるログは全てここに流れる。

__独自のLoggerオブジェクト__ : `getLogger("ロガー名")`により生成する独自のLoggerクラスのオブジェクト。ファイル毎に作成することでどのファイルのログかが明示的にわかり、それぞれにログレベルの設定やハンドラを設定できる。階層構造を作ることが可能(後述)。

__LogRecord__ : ログ本文。Loggerにより生成される。

__Handler__ : LogRecordをどこに届けるか(標準出力やファイル書込み、HTTPリクエストなど)を管理する。Loggerに指定する。
→ 種々のハンドラ:https://docs.python.org/ja/3/howto/logging.html#useful-handlers

__Formatter__ : ログのフォーマットを指定。Handlerに指定する。

__Filter__ : どのログを出力するかの管理。LoggerもしくはHandlerに指定。

## Loggerの階層構造

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406130/89ec46b7-5efb-0f9c-039c-c9fad27fa6e0.png)

## Loggingのフロー

上の階層構造の`mod2`と`mod2.fuga`を用いてロギングのフローを確認する。
https://docs.python.org/ja/3/howto/logging.html#logging-flow

```py:loggingtest.py
import logging
import loggingtest2

logger = logging.getLogger("mod2")
logger.setLevel(logging.DEBUG)

# フォーマット生成
formatter = logging.Formatter('parent: %(name)s [%(levelname)s] %(message)s')

# 標準エラー出力のハンドラ生成
handler = logging.StreamHandler()

# ハンドラへの各種設定
handler.setLevel(logging.ERROR)
handler.setFormatter(formatter)

# ロガーにハンドラをアタッチ
logger.addHandler(handler)

if __name__ == "__main__":
    loggingtest2.test()
```

```py:loggingtest2.py
import logging

def test():
    logger = logging.getLogger("mod2.fuga")
    logger.setLevel(logging.DEBUG)

    # フォーマット生成
    formatter = logging.Formatter('child: %(name)s [%(levelname)s] %(message)s')

    # ハンドラ生成・設定
    handler = logging.StreamHandler()
    handler.setLevel(logging.WARNING)
    handler.setFormatter(formatter)

    logger.addHandler(handler)
    #logger.propagate = False  #後述

    logger.error("bbb")
```

この状態で実行すると、親のハンドラからも子のハンドラからも出力される。

```
$ python loggingtest.py
child: mod2.fuga [ERROR] bbb
parent: mod2.fuga [ERROR] bbb
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406130/a8243210-d394-7e84-5059-e69532a52873.png)

他も試すとわかるが、loggingtest2.pyのハンドラの条件を"CRITICAL"以上に設定すれば`child:~~`は出力されなくなり、`getLogger()`のドットを外し、階層構造をフラットにすると親だったmod2のハンドラは呼ばれなくなるため`child:~~`だけが出力される。

## propagate属性
propagateの直訳は「伝播する」であり、この属性はLogRecordを親へ伝播させるかを指定する。
上のコードで`logger.propagate = False`をアンコメントすることで親が呼ばれないことが確認できる。

## ロギングの設定の外だし
loggingに対する設定は`logging.conf`という別ファイルに記述し、`fileConfig()`で読み出すことが可能。これによりロギングの設定部分を処理本体から切り離すことができる。詳細は公式ドキュメント参照。
さくらVPSで用意したCentOS8にやたらと「最後の正しいログインの後に 999 回の失敗ログインの試行があります」と出るので対応する

# 概要

さくらVPSでCentOS8のサーバーを構築した後、何度かsshでログインすると、以下のようなメッセージが出てきていた。

```shell-session
最終ログイン: 2020/10/10 (土) 14:05:49 JST日時 pts/1
最後の失敗ログイン: 2020/10/10 (土) 18:37:59 JST 222.186.31.166から開始日時 ssh:notty
最後の正しいログインの後に 833 回の失敗ログインの試行があります
```

最初の頃はなんか気になるものの、使うとき以外はサーバーをシャットダウンしておけばいいか。ぐらいのつもりだったんですが、数百というレベルで失敗ログインの試行と出ることが頻発するようになっていたので、ちゃんと対処しようと思います。

# 対処

この対処方法について、非常に参考となるサイトがありました。
https://www.systemexpress.co.jp/centos/firewalld.html

`システムエクスプレス株式会社`様、有益な情報ありがとうございます。

まずはどういったところからアクセスされているのか確認してみます。

```shell-session
# lastb -i

root     ssh:notty    112.85.42.238    Sat Oct 10 18:38 - 18:38  (00:00)
root     ssh:notty    112.85.42.238    Sat Oct 10 18:38 - 18:38  (00:00)
root     ssh:notty    222.186.31.166   Sat Oct 10 18:38 - 18:38  (00:00)
root     ssh:notty    222.186.31.166   Sat Oct 10 18:38 - 18:38  (00:00)
root     ssh:notty    112.85.42.238    Sat Oct 10 18:38 - 18:38  (00:00)
root     ssh:notty    222.186.31.166   Sat Oct 10 18:38 - 18:38  (00:00)
root     ssh:notty    222.186.31.166   Sat Oct 10 18:38 - 18:38  (00:00)
.......
support  ssh:notty    141.98.9.162     Wed Oct  7 06:48 - 06:48  (00:00)
root     ssh:notty    218.92.0.212     Wed Oct  7 06:48 - 06:48  (00:00)
.......
ubnt     ssh:notty    141.98.9.166     Wed Oct  7 06:48 - 06:48  (00:00)
root     ssh:notty    218.92.0.212     Wed Oct  7 06:48 - 06:48  (00:00)
guest    ssh:notty    141.98.9.165     Wed Oct  7 06:48 - 06:48  (00:00)
.......
test     ssh:notty    141.98.9.163     Wed Oct  7 06:47 - 06:47  (00:00)
Admin    ssh:notty    141.98.10.211    Wed Oct  7 05:23 - 05:23  (00:00)
guest    ssh:notty    141.98.10.210    Wed Oct  7 05:22 - 05:22  (00:00)
1234     ssh:notty    141.98.10.209    Wed Oct  7 05:22 - 05:22  (00:00)
Administ ssh:notty    141.98.10.212    Wed Oct  7 05:22 - 05:22  (00:00)
.......
```

などのように、いろんなアカウントを試そうとしています。
ちなみに、rootでssh接続させるわけないので、とりあえずrootでのログイン試行については回避できているようでよかったです。

上記IPアドレスが、どういった地域のものなのか調査するため、
https://rakko.tools/tools/11/
で調べてみたところ、ダントツで中国からのアクセスが多く、ポロっとリトアニアからのアクセスもありました。

日本国内からの不正なアクセスの試行は見当たりませんでしたので、とりあえず、日本国内以外からのアクセスをfirewalldで拒否するように設定します。

ここから先の手順はほとんど[システムエクスプレス株式会社様のfirewalldで国内IPのみ許可](https://www.systemexpress.co.jp/centos/firewalld.html)の対応をしています。

追加でやった作業としてsshもfirewalldで制限をかける対象にしたくらいです。

```shell-session
# firewall-cmd --permanent --zone=public --remove-service=ssh
# firewall-cmd --permanent --zone=domestic --add-service=ssh
```

この対応でしばらく様子をみて、他に変なアクセスが出ないか注視したいと思います。
（正直さくらVPSに標準でこの辺を制御する機能を搭載してくれてもいいのではないかと思いますが。。。）

**追記**
この設定を行ってから丸一日さくらVPSのサーバーを起動しっぱなしにしてみましたが、１件も失敗ログインの試行が発生しませんでした。
やはり海外からのアクセスが集中していただけだったんですね。
DockerでPostgreSQLの環境構築（セットアップから開発直前まで）

# 進め方について
- 一通りコマンドを叩いて開発直前の工程まで進め、細かい設定は参考サイトを見て調整するスタイル
- 動かせる環境を作ることを目的としてガンガン進める感じです
- djangoを動かすための環境構築の一部としてやっているため、postgreSQLのをパスワード未設定で動かすための記述やpostgreSQL以外も若干あります

# 前提
- Dockerのインストールが完了していること
    - 苦労した記憶がないので、公式ページなり参考ページなりを見てサクッと入れたと思います
    - 参考までに[公式ページ](https://matsuand.github.io/docs.docker.jp.onthefly/docker-for-mac/install/)へのリンクです
- mac環境（10.14.6）で実行しています

# 手順
## dockerファイルの準備
特になし。

## docker-composeファイルの準備
```yml:docker-compose.yml
version: '3'

services:
  db:
    image: postgres
    environment:
        POSTGRES_HOST_AUTH_METHOD: 'trust'
    volumes:
      - ./database:/var/lib/postgresql/data
```

## postgresqlの各種設定
docker上での動作確認のため、事前にDocker上のPostgreSQLを起動してbashを起動した状態にしておく。
ターミナルで以下のコマンドを実行。

```bash
# コンテナを起動させる（「-d」をつけてバックグラウンドで実行させる）
docker-compose up -d
# コンテナ名を確認
docker ps
# コンテナへ接続
docker exec -it {postgreSQLのコンテナ名} bash
# postgreSQLへログイン
psql -U postgres
```

- ユーザー作成

```sql
-- ユーザを作成
create role {role name} with login password '{password}';
-- 作成結果の確認
\du
```
ロールの付与は別途行う想定ですが、この記事では触れません。
こちらのページを参考に、必要に応じて作成してください。
https://www.dbonline.jp/postgresql/role/index2.html#section1
https://www.dbonline.jp/postgresql/role/index3.html

- データベース作成

```sql
-- データベースの作成
create database {database name};
-- データベース一覧の表示
\l
```

- スキーマ作成

```sql
-- スキーマの作成
CREATE SCHEMA {schema name};
create schema anpi;

-- スキーマ一覧
\dn
```

- テーブルの作成

```sql
-- テーブルの作成
create table {schema name}.{table name};

-- テーブル一覧
\dt {schema name}.*;
```

# 参考サイト
- [postgreSQL](https://hub.docker.com/_/postgres)
モンティホール問題をRubyで検証したら、よく理解できてよく解らなくなった話

## モンティホール問題って何？
モンティホール問題とは、**直感的に納得できない確率の問題**です。
ネットで調べてもなんだかスッキリしなかったので自分で検証してみることにしました。

[こちらのサイト](https://mathtrain.jp/monty)でも概要は分かりますが、少しこのページでも解説します

#### モンティホール問題の概要
箱を選んだ段階で、はずれの箱を１つ開けてくれます。
その後選んだ箱を変えることができるとき、選択肢を変える・変えないのどうするのがお得かという問題です。

|箱１|箱２|箱３|
|---|---|---|
|当たり|はずれ|はずれ|

例えば、上のように３つある箱の中から箱２を選んだ状態で（まだ開けてはない）、ゲームの主催者がはずれの箱を開けたとします。
状況的には下のような感じ

|箱１|箱２|箱３|
|---|---|---|
|当たり|はずれ|はずれ|
||選択中|OPEN|

箱３がはずれと分かった時点で選択を変更できる場合に、変更すべきかどうか？という問題です。

直感的には` 当たり or はずれ `の２択なのでどちらを選んでも変わらなそうですが、数学的には次のようになります

||そのまま|選択肢を変更|
|---|:---:|:---:|
|当たりの確率| 33% |  67% |

これを最初見たとき「そんなバカな…」って思いました。
解説を見てもいまいち納得できなかったので、プログラミングを使って検証したらとても腑に落ちたので解説していきます。
（でも結局新たな謎が増えました）

## さっそくコーディングして検証
Rubyを使って検証していきます。
（もう少しリファクタはできますが、やってることが分かりやすいようにあえて冗長に書いてる部分もあります。それでも少し分かりにくいかも…笑）

#### コード

```ruby:ruby
# 試行回数（100万回くらいやれば十分でしょ）
number = 1_000_000

# 当たりとはずれを用意
win = 1
lose = 0

# 箱を用意
boxes = [win, lose, lose]

# ケース１（選択肢を変更しない場合）
count = 0
number.times do
  # ランダムでどの箱を選ぶか決定
  random_number = [0, 1, 2].sample
  selected_box = boxes[random_number]
  # はずれの箱を開ける（次に選択肢を変更しないのでこの処理は特に意味がない）
  random_number != 2 ? boxes.delete_at(2) : boxes.delete_at(1)
  # 選んだ箱のままで当たりかどうか判定
  count += 1 if selected_box == win
end
# 確率の計算
prob_1 = (count.to_f / number.to_f).round(5) * 100

puts "選択肢を変更しない場合の確率: #{prob_1}%"

# ケース２（選択肢を変更する場合）
count = 0
number.times do
  # 箱を選択
  random_number = [0, 1, 2].sample
  selected_box = boxes[random_number]
  # はずれの箱を開けて選んだ箱を変更
  if random_number == 0
    boxes.delete_at(2)
    selected_box = boxes[1]
  elsif random_number == 1
    boxes.delete_at(2)
    selected_box = boxes[0]
  else
    boxes.delete_at(1)
    selected_box = boxes[0]
  end
  # 判定
  count += 1 if selected_box == win
end
# 確率の計算
prob_2 = (count.to_f / number.to_f).round(5) * 100

puts "選択肢を変更した場合の確率: #{prob_2}%"


```
#### 結果
ファイルを実行した結果です。
確かに直感が間違っていることがわかります
![6222a43d3cc8b2ba6e6aba05f660e0b6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605568/0c9c26a6-4968-1c88-83d4-77754302ac15.png)


## 少し解説
この問題をRubyで解いてみて、そゆことかーと思ったことを解説していきます。
ポイントは**最初に選んだ選択肢による場合分け**です

箱を選んだ時点ではずれの箱を一つ教えてくれるわけですから、この問題は次の２パターンに場合分けできます。

* **最初に当たりの箱を選んでいた場合**
* **最初にはずれの箱を選んでいた場合**

それぞれの確率は当然次のようになります

|最初に当たりの箱を選ぶ確率|最初にはずれの箱を選ぶ確率|
|:---:|:---:|
| 33% |  67% |

では次にここから選択肢を変える・変えないの話をみていきます

### 選択肢を変えない場合
選択肢を変えない場合、最初に当たりの箱を選ばないといけません。
もともと当たりを引く確率が33%なので、この場合の当たりを引く確率は33%になります

### 選択肢を変える場合
選択肢を変える場合、最初に当たりの箱を選んでいたらはずれ、はずれを選んでいたら当たりになります。
つまり、最終的に当たりを引くためには最初にはずれの箱を選択する必要があります。
最初にはずれを選ぶ確率は67%ですので、この場合の当たりを引く確率は67%になります


## 少し疑問
ここまで解説してきましたが、書いてる途中で疑問も出てきました。
はずれの箱が開かれた段階で、別の参加者がやってきたとしましょう。

`このとき、別の参加者から見たらどちらの箱が当たりかどうかは五分五分では？`

この疑問を思いついたはいいが上手い説明ができないので、数学に詳しい方がいれば是非コメントしてください。

知識によって確率が変わるという謎の現象なんですよね
半分納得できて半分納得できてない。。。

## 最後に
すこしモヤっとして終わってしまいましたが、面白い問題でした！
モンティホール問題は単純なのに奥が深いですね〜
SQL備忘録

# 概要
覚えておきたいことをメモ
適宜更新

# タスク一覧
1. ヒストグラム算出
2. 1の結果をCSV出力
3. idごとにヒストグラム算出

# 解決方法
扱うデータ (38行3列)

|id|data1|data2|
|:-:|:-:|:-:|
|1|1|100|
|1|1|100|
|1|1|100|
|1|1|100|
|1|2|101|
|1|2|101|
|1|2|101|
|1|2|101|
|1|3|102|
|1|3|102|
|1|3|102|
|1|3|102|
|1|4|103|
|1|4|103|
|1|4|104|
|1|5|104|
|1|5|104|
|1|5|104|
|1|5|105|
|2|1|90|
|2|1|90|
|2|1|90|
|2|1|90|
|2|2|91|
|2|2|91|
|2|2|91|
|2|2|91|
|2|3|92|
|2|3|92|
|2|3|92|
|2|3|92|
|2|4|93|
|2|4|93|
|2|4|94|
|2|5|94|
|2|5|94|
|2|5|94|
|2|5|95|



## 1. ヒストグラム算出



```sql
select wb as range, count(wb) FROM (SELECT width_bucket(data1, 1, 10, 10) as wb from テーブル名) as t group by wb;
```

結果

```sh

 range | count 
-------+-------
     3 |     8
     5 |     8
     4 |     6
     2 |     8
     1 |     8
(5 rows)
```

## 2. 1の結果をCSV出力

```sql
copy (select wb as range, count(wb) FROM (SELECT width_bucket(data1, 1, 10, 10) as wb from テーブル名) as t group by wb) to 'ファイルパス＆ファイル名' with csv delimiter ',';
```

指定したパスにcsvが出力される

## 3. idごとにヒストグラム算出

```sql
select id, wb as range, count(wb) FROM (SELECT id, width_bucket(gender, 1, 10, 10) as wb from テーブル名) as t group by id, wb;
```

この場合、結果はこうなる

```sh
 id | range | count 
----+-------+-------
  1 |     1 |     4
  2 |     3 |     4
  1 |     5 |     4
  1 |     3 |     4
  2 |     2 |     4
  1 |     4 |     3
  2 |     4 |     3
  1 |     2 |     4
  2 |     1 |     4
  2 |     5 |     4
(10 rows)
```

ソートしたければorder byを追加 (今回は、idをソートした後にrangeをソート)

```sql
select id, wb as range, count(wb) FROM (SELECT id, width_bucket(gender, 1, 10, 10) as wb from テーブル名) as t group by id, wb order by id, range;
```

結果

```
 id | range | count 
----+-------+-------
  1 |     1 |     4
  1 |     2 |     4
  1 |     3 |     4
  1 |     4 |     3
  1 |     5 |     4
  2 |     1 |     4
  2 |     2 |     4
  2 |     3 |     4
  2 |     4 |     3
  2 |     5 |     4
(10 rows)
```