OmniAICreator/Qiita-1.07M huggingface dataset:
【正規表現】条件が複雑な場合の正規表現一覧

## はじめに
クロスワード検索のようなものを実装する際に、条件が複雑な場合の正規表現を調べるのに苦労したのでまとめておく。


## 正規表現一覧
+ `Lx` : X の文字数とする
+ `Ly` : Y の文字数とする
+ `.{n}` : 代わりにピリオド n 個でもよい（ `.{3}` と `...` は同じ）

|条件|正規表現|文字数: N|文字数: N以上M以下|
|:-:|:-:|:-:|:-:|
|Xで始まる|`^X.*$`|`^X.{N-Lx}$`|`^X.{N-Lx,M-Lx}$`|
|Xで終わる|`^.*X$`|`^.{N-Lx}X$`|`^.{N-Lx,M-Lx}X$`|
|Xで始まりYで終わる|`^X.*Y$`|`^X.{N-Lx-Ly}Y$`|`^x.{N-Lx-Ly,M-Lx-Ly}Y$`|
|Xを含む|`^.*X.*$`|`^(?=.*X).{N}$`|`^(?=.*X).{N,M}$`|
|Xを含まない|`^(?!.*X).*$`|`^(?!.*X).{N}$`|`^(?!.*X).{N,M}$`|
|XとYを含む|`^(?=.*X)(?=.*Y).*$`|`^(?=.*X)(?=.*Y).{N}$`|`^(?=.*X)(?=.*Y).{N,M}$`|
|XまたはYを含む|`^.*(X\|Y).*$`|`^(?=.*(X\|Y).*).{N}$`|`^(?=.*(X\|Y).*).{N,M}$`|
|Xを含むがYを含まない|`^(?=.*X)(?!.*Y).*$`|`^(?=.*X)(?!.*Y).{N}$`|`^(?=.*X)(?!.*Y).{N,M}$`|
|XYZで構成される|`^[XYZ]+$`|`^[XYZ]{N}$`|`^[XYZ]{N,M}$`|
|XYZ以外で構成される|`^[^XYZ]+$`|`^[^XYZ]{N}$`|`^[^XYZ]{N,M}$`|
|1文字目と3文字目、2文字目と4文字目が同じ|`^(.)(.)\\1\\2.*$`|`^(.)(.)\\1\\2.{N-4}$`|`^[^XYZ]{N-4,M-4}$`|
listen (LoadError)

# はじめに
AWSのリモート上でpumaを起動させた所、エラーが出た時ので備忘録として書かせて頂きます。

# 環境
ruby 3.0.2
rails 6.1.4
puma 5.4

# エラー
![スクリーンショット 2022-04-07 19.41.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2594478/32c6c251-4644-d3dc-8d3e-a1f76ad32ede.png)
LoadErrorだったので、listenのファイルを確認したところ、ファイルがあったので、listenのgemがないのかと思いGemfileを確認した所あるのに何故エラーが出るのだろう？

# gem listenとは
ファイルの変更、追加、削除を検出するものみたいです。

# 原因
Gemfileをよく見てみると...:bulb:
![スクリーンショット 2022-04-08 11.38.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2594478/691aed58-19c1-e65b-3e63-acda6deebd14.png)
group :developmentの中に入っていました。
だから、本番環境でlistenが反映されずにLoadErrorが出ていたみたいです。
# 対処法
listenをgroup :developmentから外してbundle installします。
そして、pumaを起動してみたところ...
起動しました！

# 反省
gem listenについてあまり分かっていないので、詳しく教えてくれる方は、コメントください。
GASで特定のTwitterアカウントの監視ツールを作る・Part 2 (Googleドライブのファイルを自動削除)

## はじめに
### 概要

[前回：GASで特定のTwitterアカウントの監視ツールを作る](https://qiita.com/hightail/items/c4274f5e0122457e0bac)

自動でツイートのスクショを撮るスクリプトを作ったのはいいけど、画像データがGoogleドライブの容量を圧迫してしまう。
最新の100件以降は自動的に削除しよう。

### 使うもの
* Google App Script

## つくりかた

```javascript:コード:gs
function deleteOldFiles() {
  let folder = DriveApp.getFolderById('GoogleドライブのフォルダID');
  let files = folder.getFiles();
  let filesArray = [];

  while(files.hasNext()) {
    let file = files.next();
    filesArray.push(file);
  }

  filesArray.sort(function(a,b){
    if(a.getName() > b.getName()) return -1;
    if(a.getName() < b.getName()) return 1;
    return 0;
  });

  let number = 0;
  for(let image of filesArray) {
    if(number > 100) {
      image.setTrashed(true);
    }
    number++;
  }
}
```

この関数を[前回](https://qiita.com/hightail/items/c4274f5e0122457e0bac)作ったtakeScreenShots関数のif文の中で呼び出せば、新しいスクショを撮ったときに古いスクショを削除してくれるよ。
C# ListViewで条件別に色分け

~~~C#
switch (条件)
  {
  case "条件A":
    ListColor = Color.Blue;
    break;
  case "条件B":
    ListColor = Color.Green;
    break;
  case "条件C":
    ListColor = Color.Red;
    break;
}
string[] item = {"ABCD", "EFGH","IJKL" };
listView.Items.Add(new ListViewItem(item));
listView.Items[listView.Items.Count-1].ForeColor = ListColor;
~~~
PHPの基礎について

現在、プログラミングスクールの講師の人からの宿題でいろいろ調べていますが、頭を悩ませています。
# 内容が混同している。
以前、投稿した内容でクラスなどを調べているとお話しましたが、最近、与えられたキーワードで混乱していることがあります。
## クラス変数とプロパティ
サイトによると、同一のものと書いてあるものもあり、どう違うのかが分からないです。
キーワードが分かれていることを考えると、明確な違いがあるのだろう。
## メソッド
主に、クラスメソッドとインスタンスメソッドの二つある。
独学でそこまで勉強していないので、調べても違いがよくわからない。

# キーワードが難しすぎて、全部調べ切れていない。
他にも、インスタンス化やコンストラクタ、継承、メソッドチェーンなどのキーワードがありましたが、
難しくて調べきれていません。
進捗があれば、また投稿します。
Raspberry Pi OS 2022-04-04 Release-note 翻訳

(追記: 2022/9/7にRaspbian OS 2022-09-06がリリースされています)
https://qiita.com/utaani/items/9203c5c5270d55040b55

https://downloads.raspberrypi.org/raspios_full_armhf/release_notes.txt

2022-04-04:
 - デフォルトの "pi" ユーザーは削除されました。初回起動ウィザードは、新しいユーザーアカウントの作成を強制します
 - rename-user スクリプトが追加され、一時的に再起動して初回起動ウィザードを削減することで既存のユーザーの名前を変更できるようになりました
 - オーバースキャンはKMSの下でxrandrによって管理されるようになり、個々のモニターに対して個別に設定でき、再起動を必要とせずにオンザフライで有効にできるようになりました
 - Bluetooth ペアリング画面のラジオボタンの代わりにGTK3スイッチコントロールが使用されるようになりました
 - piwiz: 初回起動ウィザードは、異なるグラフィックスを持つ別のユーザーとして別のセッションで実行されるようになりました
 - piwiz: 初回起動ウィザードに、検出可能なBluetoothマウスとキーボードの自動ペアリングが追加されました
 - lxinput: キーボードの遅延と繰り返しの設定が、mutter使用時再起動後も持続するようになりました
 - raspi-config / rc_gui: KMSドライバー使用時のピクセル倍増オプションを削除
 - raspi-config: レガシードライバーを使用しているときにコンポジションマネージャーオプションを削除しました
 - arandr: インターレースディスプレイのサポートを復元
 - mutter: より直感的なウィンドウとアプリケーションのサイクリング動作を実装
 - pi-greeter: GTK3用に再構築
 - バグ修正: システムトレイアイコンのグラフィックの破損
 - バグ修正: ドラッグするとデスクトップアイテムが消える
 - バグ修正: 起動時にターミナルウィンドウが正しくフォーカスされない
 - バグ修正: アップデータプラグインで複数の更新チェックを行った後にクラッシュする
 - バグ修正: 以前のリリースでは、ウィザードによるRaspberryPiキーボードの自動検出が壊れていました
 - バグ修正: 起動時にBluetoothLEデバイスに再接続すると表示される偽の窶彡onnected窶�ダイアログボックス
 - 実験的なWaylandバックエンドのサポートが追加 - raspi-config の高度なオプションとして有効にできます
 - さまざまな小さなバグ修正とグラフィックの調整
 - Chromiumがバージョン98.0.4758.106にアップグレードされました
 - FFmpeg HWアクセラレーションが改善されました
 - OpenJDK 17 は、ARMv6との互換性のためにデフォルトで「クライアント」JVMになりました
 - RaspberryPiファームウェア 69277bc713133a54a1d20554d79544da1ae2b6ca
 - Linuxカーネル 5.15.30
cscの作法 その104

# 概要
cscの作法、調べてみた。
resourceを埋め込んでみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/2f36d1b5-52ee-fc19-f3a4-e5cfc97f5819.png)

# コンパイル手順

```
>csc run2.cs /resource:sprite-animation4.png

```

# サンプルコード

```
using System;
using System.Windows.Forms;
using System.Drawing;

class Form1: Form {
	PictureBox pb0;
	Bitmap bmp;
	int ind;
	Form1() {
		Text = "Run";
		ClientSize = new Size(320, 240);
		pb0 = new PictureBox();
		pb0.Width = 85;
		pb0.Height = 102;
		System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly();
		bmp = new Bitmap(myAssembly.GetManifestResourceStream("sprite-animation4.png"));
		pb0.Image = bmp;
		ind = 0;
		Controls.AddRange(new Control[] {
			pb0
		});
		Timer timer = new Timer();
		timer.Interval = 100; 
		timer.Tick += new EventHandler(timerTick);
		timer.Start();
	}
	void timerTick(object sender, EventArgs e) {
		int x;
		int y;
		Text = DateTime.Now.ToString("HH:mm:ss");
		ind = ind + 1;
		if (ind > 29)
			ind = 0;
		x = (ind % 6) * 85;
		y = (ind / 6) * 102;
		Bitmap canvas = new Bitmap(pb0.Width, pb0.Height);
		Graphics g = Graphics.FromImage(canvas);
		Rectangle srcRect = new Rectangle(x, y, 85, 102);
		Rectangle desRect = new Rectangle(0, 0, srcRect.Width, srcRect.Height);
		g.DrawImage(bmp, desRect, srcRect, GraphicsUnit.Pixel);
		g.Dispose();
		pb0.Image = canvas;
		this.Invalidate();
	}
	[STAThread]
	public static void Main() {
		Application.Run(new Form1());
	}
}





```
以上。
最短でVRChatのMMDワールドで踊らせた際に表情を連動させる[備忘録]


# 踊らせている際に表情を連動させる条件
- ハンドサインを切る
- BlendShapeをMMDと同じ名前に統一する
- BlendShapeが存在するオブジェクトの名前をBodyに変える

## ハンドサインを切る
`VRC Avatar Descriptor`→`Playable Layers`→`Base`→`FX`のｘを押して`Default Non-Transform`の状態にする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/69935e66-8bab-380c-c6bb-c7d9093deda5.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/349797af-36a1-349e-d3bc-599c84dce046.png)

一応ハンドサインを切らないで実装する方法も存在するが難易度が高そうなので今回はこっちで実装した

## BlendShapeをMMDと同じ名前に統一する
自作モデルの場合は既存のBlendShapeコピーし、名前をMMD用のモーフに合わせて作れば実装すば大丈夫
https://mmd15gyuunyuu.blog.jp/archives/11193436.html
購入したモデルで.Blendファイルが存在する場合も上と同じ

![実装例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/e9a80634-2fa4-5e35-9334-c342c5a7772b.png)

`ウィンク` `ウィンク２` `ウィンク右` `ｳｨﾝｸ２右`はワールドごとに対応しているものが違うので面倒ではあるがすべて実装した方がいい

購入したモデルで.Blendファイルが存在しない場合は既存のBlendShapeの名前を変更することで対応可能(らしい)(未確認)


## BlendShapeが存在するオブジェクトの名前をBodyに変える
今回は顔のオブジェクト名がFaceだったのでBodyにリネームした
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/9601302a-d368-7865-7b9c-66f088afc6db.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374827/69fcde81-0b7c-a60b-23e4-adb0ed21a57b.png)
この際、すでにBodyが存在している場合はその名前を他の名前に変更しておく必要がある
Hyperledger Iroha 環境構築

# 前提条件
- Docker、node.js、npmはインストール済み
- 使用PC：M1 Mac
- Docker Desktopは起動済み
- 作業ディレクトリは~/User/development/

### Docker環境のイメージ
Hyperledger Irohaの1ノード（ここでは1台のPCだと思ってください）にはHyperledger Iroha APIとデータベースが必要になります。以下ではiroha入門者が各所でPostgresを利用していることに鑑みて、データベース ＝ PostgresSQLとします。

# 環境構築
## コンテナ作成＆起動
APIとDBの各コンテナが通信を行うためのネットワークを作成
```
docker network create iroha_network
```
コンテナ外部にブロックチェーンを格納するための領域を確保
```
docker volume create blockstore
```
DBコンテナをsome-postgresという名前で作成＆起動
```
sudo docker run -it -d --name some-postgres \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=mysecretpassword \
-p 5432:5432 \
--network=iroha-network \
postgres:9.5
```
Iroha API起動に必要な環境をクローン
```
sudo git clone https://github.com/hyperledger/iroha --depth=1
```
APIコンテナをirohaという名前で作成＆起動
```
sudo docker run --platform linux/amd64 \
-it -d --name iroha \
-p 50051:50051 \
-v $(pwd)/iroha/example:/opt/iroha_data \
-v blockstore:/tmp/block_store \
--network=iroha-network \
--entrypoint=/bin/bash \
-e KEY='node0' \
hyperledger/iroha:latest
```
APIサーバ起動
```
irohad --config config.docker --genesis_block genesis.block --keypair_name node0
```

### 最終状態
![スクリーンショット 2022-04-08 11.18.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1953297/c9cf9b6d-8e2b-e691-ab93-42dd1f2c76f7.png)

## Tips
コンテナの起動＆停止
```
sudo docker start some-postgres iroha
sudo docker stop iroha some-postgres
``` 
各コンテナへの接続
```
sudo docker exec -it iroha /bin/bash
sudo docker exec -it some-postgres /bin/bash
```

# まとめ
iroha環境構築は情報がとても少ないので、Irohaは勿論ですがDockerオプションの学習もかなりしました。次回は「iroha-cliでAPIにアクセス」を投稿する予定です。
cscの作法 その103

# 概要
cscの作法、調べてみた。
練習問題やってみた。

# 練習問題

真理値表を作れ。

# 方針

- listviewを使う
- ビット演算子使う
- or,and,xor,nor,nandを表示



# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/b414ee92-7068-905e-0249-f19c0d2b0cdf.png)


# サンプルコード

```
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

public class Form1 : Form {
	Button button0,
		button1,
		button2,
		button3,
		button4;
	ListView lsv;
	public Form1() {
		this.ClientSize = new Size(400, 400);
		this.Text = "panel";
		button0 = new Button();
		button0.Location = new Point(10, 10);
		button0.Size = new Size(80, 30);
		button0.Text = "OR";
		button1 = new Button();
		button1.Location = new Point(110, 10);
		button1.Size = new Size(80, 30);
		button1.Text = "AND";
		button2 = new Button();
		button2.Location = new Point(210, 10);
		button2.Size = new Size(80, 30);
		button2.Text = "XOR";
		button3 = new Button();
		button3.Location = new Point(10, 60);
		button3.Size = new Size(80, 30);
		button3.Text = "NOR";
		button4 = new Button();
		button4.Location = new Point(110, 60);
		button4.Size = new Size(80, 30);
		button4.Text = "NAND";
		Controls.Add(button0);
		Controls.Add(button1);
		Controls.Add(button2);
		Controls.Add(button3);
		Controls.Add(button4);
		button0.Click += Button0_Click;
		button1.Click += Button1_Click;
		button2.Click += Button2_Click;
		button3.Click += Button3_Click;
		button4.Click += Button4_Click;
		lsv = new ListView();
		lsv.Location = new Point(10, 110);
		lsv.Size = new Size(300, 200);
		lsv.View = View.Details;
		lsv.FullRowSelect = true;
		lsv.HideSelection = false;
		lsv.MultiSelect = false;
		lsv.GridLines = true;
		Controls.Add(lsv);
		lsv.Columns.Add("A", 70, HorizontalAlignment.Left);
		lsv.Columns.Add("B", 70, HorizontalAlignment.Left);
		lsv.Columns.Add("X", 70, HorizontalAlignment.Left);
	}
	private void make(int n) {
		int x;
		lsv.Items.Clear();
		lsv.BeginUpdate();
		for (int a = 0; a < 2; a++)
		{
			for (int b = 0; b < 2; b++)
			{
				switch (n)
				{
				case 0:
					x = a | b;
				break;
				case 1:
					x = a & b;
				break;
				case 2:
					x = a ^ b;
				break;
				case 3:
					x = a | b;
					if (x == 0)
						x = 1;
					else
						x = 0;
				break;
				case 4:
					x = a & b;
					if (x == 0)
						x = 1;
					else
						x = 0;
				break;
				default:
					x = 0;
				break;
				}
				lsv.Items.Add(new ListViewItem(new string[] {
					a.ToString(),
					b.ToString(),
					x.ToString()
				}));
			}
		}
		lsv.EndUpdate();
	}
	private void Button0_Click(object sender, EventArgs e) {
		make(0);
	}
	private void Button1_Click(object sender, EventArgs e) {
		make(1);
	}
	private void Button2_Click(object sender, EventArgs e) {
		make(2);
	}
	private void Button3_Click(object sender, EventArgs e) {
		make(3);
	}
	private void Button4_Click(object sender, EventArgs e) {
		make(4);
	}
	[STAThread]
	public static void Main() {
		Application.Run(new Form1());
	}
}





```

以上。
goenvとさよならしつつも、複数バージョンのgoを運用する

![macOS-12.3.1](https://img.shields.io/badge/macOS-12.3.1-brightgreen) ![go-1.18](https://img.shields.io/badge/go-1.18-brightgreen)

公式からGoの複数バージョンの取り扱い方が発表されていたので、goenvとさよならして公式の方法で運用することにしました。
goenvのアンインストールと複数バージョンのGoの扱い方について公式を引用しつつ記載します。

## goenvのアンインストール方法

アンインストール方法は、goenvのgithubに記載があります。
https://github.com/syndbg/goenv/blob/master/INSTALL.md#uninstalling-goenv

まずは、自分のローカルマシンに設定している環境変数の設定を削除します。
私の場合は.zshrcに記載している以下の3行（コメント入れて4行)を削除しました。

```zsh
# for goenv
export GOENV_ROOT="$HOME/.goenv"
export PATH="$GOENV_ROOT/bin:$PATH"
eval "$(goenv init -)"
```

次にgoenvのインストールディレクトリを削除します。

`goenv root`を実行したときに出力されるディレクトリを削除します。

```zsh
rm -rf `goenv root`
```

私は臆病なので、```ls -Rl `goenv root` ``` と中身を確認してから、実行しました。

Homebrewを使ってインストールした方は、brew uninstallしてください。

```zsh
brew uninstall goenv
```

以上です

## goのインストール方法

公式から環境に合わせてインストールします。

https://go.dev/doc/install

もちろんソースからビルドしても良いと思います。

私はmacなので、macのインストーラーからインストールしました。

## goのバージョンアップ

過去のバージョンをアンインストール

```zsh
sudo rm -rf /usr/local/go
```

公式から環境に合わせて最新版をインストールします。

https://go.dev/doc/install


## 過去バージョンのgoをインストールする方法

公式の方法にならってインストール、実行します。

https://go.dev/doc/manage-install#installing-multiple

goの1.17.7をインストールする場合を例示します。
インストールした古いバージョンのgoを実行するときにはgoの後ろにスペースを開けずにバージョン番号をつけます。

```zsh
go install golang.org/dl/go1.17.7@latest
go1.17.7 download
```

GOROOTを確認します。

```zsh
MacBook-Pro:~ vermee81$ go1.17.7 env GOROOT
/Users/vermee81/sdk/go1.17.7
MacBook-Pro:~ vermee81$ go env GOROOT
/usr/local/go
```

ちゃんとバージョンごとに分かれてて安心です。
Databricks CLIを複数のワークスペースで利用するための手動設定と使用例

## はじめに

Databricks CLIを複数のワークスペースで利用するための手動設定方法と利用例をまとめます
`databricks configure --token` コマンドでうまく設定できないときにも読んでください

## 事前準備

### ➀`databricks-cli` をインストールする

```bash
$ pip install databricks-cli
```

### ➁トークンを用意する

Databricks CLIを利用したいワークスペースで
「設定」→「ユーザー設定」→「Access tokens」タブからトークンを生成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1022607/10d8c4cb-baca-5be0-a4fb-5c06356477a2.png)

## 公式ドキュメントの解説

> [Databricks CLI \| Databricks on AWS](https://docs.databricks.com/dev-tools/cli/index.html)

ここで紹介されている `databricks configure --token` コマンドを使って、指示通りに設定すればよいです
、、、が、私が実行したときは、何度やっても登録できませんでした。

 `databricks configure --token` コマンドが行っていることは
ホームディレクトリの `.databrickscfg` ファイルの設定のみのようなので、
手動で `.databrickscfg` ファイルの設定を行います。

## `.databrickscfg` ファイルの手動設定

`vim` コマンドかテキストエディタで下記の通り、値を設定し、ホームディレクトリに保存します
ここでは2つのワークスペースを設定します

```text
[DEFAULT]
host = https://adb-0000000000000000.00.azuredatabricks.net/
jobs-api-version = 2.0
token = 0000000000000aaaaaaaaaaaaaaa1111111111bbbbbb

[dbw-second]
host = https://adb-1111111111111111.11.azuredatabricks.net/
jobs-api-version = 2.0
token = 0000000000000aaaaaaaaaaaaaaa22222222222cccccc
```

### 補足

* 1つめのワークスペースは `[DEFAULT]` にします
    *  `--profile` オプションを付けずにコマンドを実行した時、そのワークスペースが優先されます
* `[dbw-second]` に指定した値を使って異なるワークスペースに対してCLIを実行できるようになります
    * 短めの名前にしておくとよいです
* `host` は `Azure Databricks` のアドレスなので、環境が異なる場合は適宜変更してください
* `token` はワークスペースで発行したものを貼り付け

## Databricks CLIを使ってみる

### `--profile` オプションを付けないときはデフォルトワークスペースに対して実行される

```bash
$ databricks secrets list-scopes

Scope                  Backend         KeyVault URL
---------------------  --------------  ----------------------------------------
dwh-first                 DATABRICKS      N/A
```

### `--profile` オプションを付けたときはそのワークスペースに対して実行される

```bash
$ databricks secrets list-scopes --profile dbw-second

Scope                  Backend         KeyVault URL
---------------------  --------------  ----------------------------------------
dwh-second                 DATABRICKS      N/A
```

## 作成済みの `profile` を知りたいときは👇コマンド

```bash
$ grep -E "\[.+\]" ~/.databrickscfg
```
Zennシェア:Flutter Animationパターン

FlutterのアニメーションWidget数多くて、
バラバラになって、どんな時、どんなアニメーションパーツを使うのはわからない時来たら。

こちらに来てください。

[Flutter Animationパターン](https://zenn.dev/reinf0rce/articles/5bb8fa26588a94)
webの仕組みについて（備忘録）

`・IPアドレス`
PC,スマホ,プリンターなどネットワーク上の機器に割り当てられているインターネット上の住所。
32ビットの二進数で構成。表記は人間が理解できるように、3桁区切りの12桁で構成。
イメージ：発送から到着地まで変化なし。
MACアドレスと同様、世界で唯一の番号。
プライベートIPアドレス　家庭内や施設内のネットワーク機器で使用。
通常、ルーターの機器等でプライベートIPアドレス→グローバルIPアドレスへ変換が行われインターネットの使用が可能。

グローバルIPアドレス　インターネットなど公共回線でアクセスを行う際に使用。世界中で重複することはない。

IPアドレス（IPv4）の枯渇が問題となっていおり、順次IPv6への移行が行われている。

`・MACアドレス`
ネットワークにつながるすべての機器に割り当てられている識別番号。インターネット上の住所
経由地で書き換えられる。
IPアドレスと同様、世界で唯一の番号。

`・ホスト`


`・ドメイン`


`・ポート番号`


`・SSH`


`・DNS`


`・公開鍵/秘密鍵`


`・Cookie（クッキー）`


`・Session（セッション）`


`・HTTPメソッド（GET/POST）`
【Django】DjangoでLine Profilerを使う

## Line Profilerとは
プログラムを行単位でプロファイリングできるモジュールです。今回はDjangoアプリ内で行ごとの処理時間を計測し、コンソールに表示させてみます。

## Line Profilerの使い方
### １. Line Profilerをインストール
```terminal
$ pip install line_profiler
```
インストール後は $ pip freeze > requirements.txt しておくと良いでしょう。

### ２. 処理時間を計測したいファイル(views.pyなど)に下記を追加
```python:views.py
# Line Profiler
import line_profiler
import atexit

profile = line_profiler.LineProfiler()
atexit.register(profile.print_stats)

# 測定したい関数にアノテーションを付ける
@profile
def foo():
    ...
```

### ３. runserverする
```terminal
$ python manage.py runserver
```

### ４. ブラウザを更新するなりして関数を実行する

### ５. Ctrl+c でrunserverを終了する。
計測結果がコンソールに表示されます↓
```terminal
Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     3                                           @profile
     4                                           def foo():
     5         1    1557939.0      0.3     50.9      print('Hello World')
     6         1   10541423.0      2.1     49.1      print('foo')
```
【DICOM】DICOM画像を.jpg/.pngファイルとして書き出し、保存する

## １. Pillowをインストールする
```terminal
$ pip install Pillow
```
## ２.  ファイルに書き出し、保存する
png形式で保存したい場合は、拡張子を .png にしてください。
```python: sample.py
import pydicom
from PIL import Image

# dicomファイルを読み込む
file = pydicom.dcmread('ファイルパス')
# 画像処理
img = file.pixel_array
pil_img = Image.fromarray(img)
# 保存したい場所、ファイル名を引数に設定
pil_img.save('ファイルパス/original_dcm.jpg')
```

## ３. 補足
### ■ TypeError: Cannot handle this data type
ndarrayのデータ型がdtypeやfloatの場合はエラーになることがあります。この場合、unit8に変換すると解決します。
```python:sample.py
import numpy as np 

pil_img = Image.fromarray(img[0].astype(np.uint8))
pil_img.save('ファイルパス/original_dcm.jpg')
```

### ■ DICOMファイルにRGBが欠けている場合
```python:sample.py
pil_img = Image.fromarray(img)
new_pil_img = pil_img.convert('RGB')
new_pil_img.save('ファイルパス/original_dcm.jpg')
```

### ■ DICOMファイルにNumberOfFramesタグが欠けている場合
pixel_arrayを取り出す前に以下を実行します。
```python:sample.py
file = pydicom.dcmread('filepath')
file.NumberOfFrames = '31'
file.PixelData = file.PixelData * 31
img = file.pixel_array

pil_img = Image.fromarray(img)
pil_img.save('ファイルパス/original_dcm.jpg')
```
Go言語 構造体

## 構造体
構造体とは、複数の任意の型を、１つの要素にまとめたもの。
さまざまなデータ構造を、１つの「型」として扱うことが可能。

## Code
```Go
// 監督名のための共通化用構造体
type Directer struct {
	Name    string
	Country string
}

// 映画タイトルのための構造体
type Movie struct {
	Directer
	Title    string
	Year     int
}

// 受賞タイトルのための構造体
type Prise struct {
	Directer
	Title    string
	Year     int
}

// メイン関数
func main() {

	// スティーブン・スピルバーグ
	movie1 := Movie{
		Directer: Directer{"Steven Spielberg", "USA"},
		Title: "Saving Private Ryan",
		Year: 1998,
	}
	prise1 := Prise{
		Directer: Directer{"Steven Spielberg", "USA"},
		Title: "Academy Award for Directing",
		Year: 1998,
	}

	// 構造体の出力
	fmt.Println(movie1, prise1)
}
```

## Output Sample
$ go build main.go  
$ ./main  
{{Steven Spielberg USA} Saving Private Ryan 1998} {{Steven Spielberg USA} Academy Award for Directing 1998}  

## GitHub
https://github.com/GL-Kageyama/Go_Struct
【Android Studio】Gitの連携が上手くいかないときの対処法

Android Studio上でpullしようとしたら、"Update canceled"というエラーが発生。
![スクリーンショット 2022-04-08 103842.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/3f1d1b3f-a7b3-293b-49c2-5b3612c0c302.png)
```
error: unable to read askpass response from 'C:\Users\xxxx'
bash: /dev/tty: No such device or address
error: failed to execute prompt script (exit code 1)
fatal: could not read Username for 'https://xxxx': No such file or directory
```

その時行った対処法を記述。


# 最初に行った方法
File→Settings…→Version Control→Git→Use Credenciral helperにチェックを入れる

# それでも上手くいかない時

1. File→Settings…→Appearance & Behavior→System Settings→Passwords→Do not save, forget passwords after restartを選択

2. 再起動


参考：https://stackoverflow.com/questions/28142361/change-remote-repository-credentials-authentication-on-intellij-idea-14
phpMyAdminのSQLインジェクション/インポート/エクスポートで403Forbidden

### 事象・問題の発生 (´ε｀；)　
PhpMyAdminのSQLインジェクション/インポート/エクスポートしようとして、403Forbiddenに。
SQLインジェクション、インポート、エクスポートができない状態

### 原因
AWSで環境を構築していたため、WAF（Web Application Firewall）によるブロックが原因でした。

### 対応・解決
AWSのWAFでURIに特定の文字列が含まれるリクエストを許可する設定を追加
追加方法については、下記サイトを参考にしました。

- AWS WAFで特定IPのリクエストからアクセス許可しよう https://www.sunnycloud.jp/column/20210601-01/
- AWS WAFでURIに特定の文字列が含まれるリクエストをブロックする https://www.wafcharm.com/blog/block-specific-string-in-uri-jp/
- AWS WAFの運用方法 https://www.cloudsolution.tokai-com.co.jp/white-paper/2021/1014-262.html


### 注意点
WAFルールの設定時に、Priority(処理する優先度)を設定します。
その際、「特定URIを含むリクエストを許可するルール」が、「AWS-AWSManagedRulesSQLiRuleSet」より優先度を高く（先に処理されるよう）にしておかないと、403Forbiddenは解消されませんでした。
[VHDL]numeric_stdライブラリを使った時のinteger⇔std_logic_vectorの変換方法


ライブラリのソースを見に行くのが面倒臭いので備忘録として残しておく

### 使用ライブラリ
```vhdl
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
```

### 変換コード
```vhdl
signal s_stdlogicvector : std_logic_vector(9 downto 0) := (others => '0');
signal s_integer : integer range 0 to 1023 := 0;

-- std_logic_vector ⇒ integer
s_integer <= to_integer(unsigned(s_stdlogicvector)); -- unsignedとして扱いたい時
s_integer <= to_integer(signed(s_stdlogicvector)); -- signedとして扱いたい時

-- integer ⇒ std_logic_vector
s_stdlogicvector <= std_logic_vector(to_unsigned(s_integer, s_stdlogicvector'length));
s_stdlogicvector <= std_logic_vector(to_signed(s_integer, s_stdlogicvector'length));
```
[Django] Pythonanywhere  Could not find your API token エラー解決方法


解決方法
API Token を発行する。
・手順
1 Pythonanywhere  ログイン
2 Dashboard > Account > API Token に進み API Token を作成する。
![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560347/1486aab4-f50c-6f44-0106-22f7e0bc925a.png)

3 exit コマンドでコンソールを終了しログアウトする。
4 再度ログインしコンソールにてコマンドを実行する。

エラーメッセージ
pythonanywhere.exceptions.SanityException: Could not find your API token. You may need to create it on the Accounts page? You will also need to close this console and open a new one once you've done that.

参考サイト
https://www.pythonanywhere.com/forums/topic/21224/
100日でSQLの達人になる@LeetCode! Day63 <MS SQL Serverでべき乗、POWER>

## 612. Shortest Distance in a Plane （問題レベル: Medium）要課金
今日の問題はこれ。
複数の点座標間の最も近い距離を求めよという問題。

２点間の距離を総当りで求めることはすぐに分かったのだが、なかなかアクセプトされない。

```:SQL Server　間違い
SELECT TOP 1 ROUND(SQRT((a.x-b.x)^2 + (a.y-b.y)^2),2) AS shortest
FROM point2d a
INNER JOIN point2d b
ON a.x <> b.x OR a.y <> b.y
ORDER BY ROUND(SQRT((a.x-b.x)^2 + (a.y-b.y)^2),2) ASC
```
`Runtime Error, An invalid floating point operation occurred.`というエラーが出てしまいます。

ポイントは`MS　SQL Server`で、べき乗する場合には、`^`は使えない、`POWER`を使うだった。
最終的に提出したコードは下記。
```:SQL Server
SELECT TOP 1 ROUND(SQRT(POWER((a.x-b.x),2) + POWER((a.y-b.y),2)),2) AS shortest
  FROM point2d a
 INNER JOIN point2d b
    ON a.x <> b.x OR a.y <> b.y
 ORDER BY ROUND(SQRT(POWER((a.x-b.x),2) + POWER((a.y-b.y),2)),2) ASC
```
* [LeetCode](https://leetcode.com/)の問題は、`MS SQL Server`で解いています。
HTTPリクエストとは

HTTPリクエストとは何かというと、
WebクライアントとWebサーバーとのやりとりを示す方法の一つで、
WebサーバーとWebクライアントの送受信における取り決めがHTTPというプロトコルである。

ユーザーが使うクライアント側がサーバーに対して要求を上げて、それにサーバーが応答する形で成り立っている。
例えばツイッターであれば、

投稿するというものそれをポストというメソッドで

そのメソッドを投げることで、
サーバーはHTTPリクエストを受けてポストということで、
実際にリソースを作ってその結果をまたクライアント側に返してあげる。

自分が理解していなかったのは、
クライアントとサーバーという二つの
役割があって、それがごっちゃになっていたことが原因で混乱していた。

サーバとクライアントの役割を同じものとして考えていた。

そこを明確に分けて、
WebブラウザがHTTPリクエストを投げて、そしてそのサーバー側でリクエストを解析処理
して、それをレスポンスを返す。

この流れを、理解することが必要。

クライアントがサーバーにどういうふうに投げるのか、その実装方法については
fetchとかaxiosとかがあって
今自分が所属している会社では、axiosを使ってそれを実現している。
パーミッション（権限）　確認また変更　Linux

## 用途
- ファイルのパーミッション（権限）を確認する、または変更する時に使用する。

## パーミッションの確認方法
```:確認方法
$ ls -l
```
## パーミッション確認コマンドの結果の例
```:例
-rw-r--r--    1 hoge  staff   478  7 19  2021 hoge.html
drwxr-xr-x    4 hoge  staff   128  7 24  2021 hoge.text
```
## 解説
**1番目の値は、パーミッション情報**
ファイル所有者、グループ、その他のユーザのアクセス権限が示されている。
例の場合、 「-rw-r--r--」 と 「drwxr-xr-x」

**2番目の値は、リンクされている数・サブディレクトリの数**
例の場合、 「1」 と 「4」
サブディレクトリ数と連動するが、そのものではない。
ご指摘いただいたコメントを引用させていただきました。
https://qiita.com/marukome/items/735516a8435312526082#comment-7b113f83f5b5a08dd9b4


**3番目の値は、所有者やグループ情報**
所有者やグループ情報が表示される。
例の場合、 「hoge  staff」 と 「hoge  staff」
（所有者が「hoge」、グループが「staff」）

**4番目の値は、ファイルサイズ**
例の場合、 「478」 と 「128」

**5番目の値は、日時**
更新日時が、月・日にち・年の順で表示される。
例の場合、 「7 19  2021」 と 「7 24  2021」

**6番目の値は、ファイル名**
例の場合、 「hoge.html」 と 「hoge.text」


### `-rw-r--r--` や `drwxr-xr-x` について
１文字目はファイルのタイプを表している。
2文字目から4文字目はファイル所有者に対する権限を表している。
※今回の場合は左から3つ目の値の `hoge` というのがファイル所有者。
5文字目から7文字目はファイル所有グループに対する権限を表している。
※今回の場合は左から4つ目の値の `staff` というのがファイル所有グループ。
8文字目から10文字目はその他に対する権限を表している。

**1文字目の意味**
```
「-」 が 通常ファイル
「d」 が ディレクトリ
「l」 が リンクファイル
```
**2文字目から10文字目までのアルファベットの意味**
```
「r」 が 読み取り
「w」 が 書き込み
「x」 が 実行
```
**-rw-r--r--の意味**
```
「ファイルのタイプ」 が 「通常ファイル」 であり、
「所有者であるhoge」 に 「読み取り」 と 「書き込み」 の権限があり、
「所有グループであるstaff」 に 「読み取り」 の権限があり、
「その他」 に 「読み取り」 の権限があることを示している。
```

**drwxr-xr-xの意味**
```
「ファイルのタイプ」 が 「ディレクトリ」 であり、
「所有者であるhoge」 に 「読み取り」 と 「書き込み」 と 「実行」 の権限があり、
「所有グループであるstaff」 に 「読み取り」 と 「実行」 の権限があり、
「その他」 に 「読み取り」 と 「実行」 の権限があることを示しています。
```

## アクセス権限の設定方法
```:書き方
$ chmod 設定したい値 ファイル名
```
```:例
$ chmod 755 hoge.html
```
**設定したい値について**
```
「r」 が 「4」
「w」 が 「2」
「x」 が 「1」
```
3文字ずつの合計を指定する。
例の755の場合は 「rwxr-xr-x」 を設定している。
内訳 「（rwx）4+2+1, （r-x）4+1, （r-x）4+1」
　
　
　
下記の記事を参考にしました。
- https://wa3.i-3-i.info/word1151.html
- https://www.tohoho-web.com/wwwxx012.htm
ホスト型、ハイパーバイザー型、 コンテナ型の仕組みについて


```

仮想化の方式や仕組みについて
仮想化の方式は大きく分けて3つあり、それぞれに基本的な特徴や、メリット・デメリットがあります。

■ホスト型
ホスト型はハードウェア（サーバ）の中にOS上に土台となる仮想化ソフトウェアをインストールし、仮想化ソフトウェアで仮想マシンを稼働させる方法です。

■ホスト型の特徴
すでに動作しているコンピュータの中に仮想マシンが作れるためホストOSと仮想化ソフトウェアを動作させるので
ハードウェアにかかるリソースは余計に消費をしてしまう。
本番環境には適しているとは言えないものの、仮想化環境の構築がしやすい点が特徴で検証環境にはよく使われている。

代表的な技術
「VMware Workstation Player」「VMware Fusion」「Oracle VM Virtualbox」など。

■ハイパーバイザー型
仮想環境は、ゲストと呼ぶことができ、1ゲスト専用のCPU・メモリ・ネットワーク・HDD利用域が割り当てられると共に、 そのリソースを自由に扱ってWebアプリケーションやデータベースシステム等のプログラムを自由に起動することができます。 ゲスト間は完全に独立している故に隣のゲストとのデータ共有は、一般的にIPレベルでの通信を必要とする。

■ハイパーバイザー型の特長
ハイパーバイザーの上に複数の仮想マシンを立てることができる
それぞれ別のOSでサーバーを立てることができる

代表的な技術
「Vmware ESXi」「Linux KVM」「Microsoft Hyper-V」「Citrix Xen Server」
「Red Hat Enterprise Virtualization（RHEV）」など。

■コンテナ型
1つのOSの中にアプリケーションを格納する箱を複数用意するという考え方の仮想化技術になります。

■コンテナ型の特徴
とにかく処理が軽量
一つのOS内でアプリケーションを動作させることができる
コンテナ設定の再利用が可能


コンテナは「アプリケーションを実行するための領域（ユーザ空間）を複数に分割して利用する」もので、
ホスト、ハイパーバイザーとは全く異なる概念なので、要注意。

代表的な技術
「Docker」、「Kubernetes」
今週の学び  第1回

今週の学び

### Githubへの繋ぎ方

初回のみ最初に git init の入力が必須

2回目以降は下記手順↓

```
$ git add .
```

```
$ git commit -m 'message'
```

```
$ git push origin main
```
上記の順でファイルをGithubへ上げれる

### cssの読み込み方の確認
ブラウザから検証でソースの所を見て読み込めてるか確認、"./css/style.css"でちゃんと階層が読み込めてなかった

### githubへのあげ方、再確認
git pullとはリモートリポジトリからダウンロードしてローカルリポジトリに更新する
git pushとは逆にリモートリポジトリの情報を更新する

### flexboxの使い方
flex-direction,flex-wrap,justify-content,align-itemsなど目的によって使い分ける
flexは直後の子要素にしか効かないので、その親要素に入れる

### max-width
header.main.footerの幅を統一すれば大きい画像もそのページの範囲に収まる

### id
同じページ内のリンクは#とidで繋げる
idは同じページ内で1つしか使えない

### テンプレートリテラル
文字列の中に定数（変数）を埋め込むことができる
例、console.log(`ぼくの名前は${name}です`);

### if文
if文を用いると「もし○○ならば●●を行う」という条件分岐が可能
    例、const level = 12;
    if (level > 10){
  console.log("レベルが10より大きいです");
}

### 比較演算子
「a == b」はaとbが等しければtrue、等しくなければfalse、「a != b」はその逆
 厳密に比較できる厳密等価演算子は「=」がもう1つ増える

### ブロック要素にborder-bottomでアンダーラインを引く場合
displayでインライン要素にしてからborder-bottomを付与
しかしインライン要素はmarginが使えないので、周りを整えたりセンター寄せする時はtext-alignを使うなどブロック、インライン、インラインブロック要素で出来る事、出来ない事をしっかり把握する

### ブロック要素、インライン要素、インラインブロック要素の特性
ブロック要素→要素の前後に改行が入り、ブロック要素同士縦に並ぶ横幅や高さを指定でき、 余白(margin,padding)が指定できる
インライン要素→要素の前後に改行が入らず、インライン要素同士横に並ぶ
横幅や高さを指定できない
ブロック要素のように上下の余白設定(margin,padding)が効かない
インラインブロック要素→横幅と高さが指定できる
ブロック要素と同じ余白のつき方をする
横幅の初期値が内容で決まる
前後の要素と横に並ぶ

### ブロック要素の整え方
いきなりmargin、text-alignなどを付与すると思い通りに動作しないので、
width80%などでブロック要素の幅を小さくしてからmargin.0 auto等を使う

### text-align
直前の親要素に付与する、divなど

### idのルール
タグを作成時、""内は基本小文字にする


## ■　今週の振り返り
- 調べる時間で数時間かかってしまった（無駄な時間を過ごしてしまった）
    - まずは英語で出てきた部分をコピーしてGoogleで調べることとする
- 自分で調べながらの作業で時間がかかる割に問題解決出来ていない
    - 今後の家庭教師でやり方を見てもらい自分の作業の問題点をピックアップしてもらう
GASで特定のTwitterアカウントの監視ツールを作る　その１

## はじめに

### 概要
気になるあの人がツイートしたらそれを自動でスプレッドシートに記録しよう。
何かあったときのために自動でスクリーンショットも撮って保存しちゃおう。

### 使うもの
* Google Spreadsheet
* Google Apps Script
* [Zapier](URL "https://zapier.com")
* [API FLASH](URL "https://apiflash.com/")

### 全体の仕組み
1. ZapierがTwitterアカウントを監視する（たぶん15分おきに見に行ってる）
1. Zapierが最新ツイートを取得したらスプレッドシートに記録する
1. スプレッドシートに変更があったら（2で記録されたら）GASのトリガー発火
1. GASでAPI FLASHにリクエストを投げてTwitterスクショ生成
1. 生成したスクショをGoogleドライブに保存する

### 完成イメージ
![sheetsample.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273081/26610b09-6ad6-ba10-f445-72202b2743d6.jpeg)

## つくりかた

#### 1. Googleスプレッドシートで下準備
新しいスプレッドシートを用意して1行目にヘッダーだけ作っておく。

ここでの例：
* created at ... ツイート日時
* user name ... Twitterアカウント名
* text ... ツイート内容
* url ... ツイートURL
* screenshot ... スクショURL

#### 2. ZapierでZapを作成する

 Trigger (User Tweet in Twitter)
* Choose app & event ... Twitter / User Tweet
* Choose Account ... 自分のTwitterアカウント
* Setup Trigger ... 監視したいTwitterアカウント

Action (Create Spreadsheet Row in Google Sheets)
* Choose app & event ... Google Sheets / Create Spreadsheet Row
* Choose account ... 自分のGoogleアカウント
* Set up action ... 
    * Drive ... My Google Drive
    * Spreadsheet ... 1で用意したスプレッドシート
    * Worksheet ... 任意
    * 以下、スプレッドシートで作成したヘッダーの項目と取り込む項目を一致させる

#### 3. GASでコード記述&トリガー作成

コード記述
```javascript:コード.gs
function takeScreenshots() {
  let sheet = SpreadsheetApp.openById('スプレッドシートID').getSheetByName('シート名');
  let sheetLastRow = sheet.getLastRow();
  let ssLastRow = sheet.getRange(sheet.getMaxRows(), 5).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
  let tweetUrl = null;

  if(sheetLastRow !== ssLastRow) {
    for(i = ssLastRow + 1; i <= sheetLastRow; i++) {
      url = sheet.getRange(i, 4).getValue();
      let fileUrl = takeAScreenshot(tweetUrl);
      sheet.getRange(i, 5).setValue(fileUrl);
    }
  }
}

function takeAScreenshot(tweetUrl) {
  let folderId = 'GoogleドライブのフォルダID';
  let now = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'YYYYMMdd-HHmmss');
  let access_key = 'API FLASHのアクセスキー';
  let requestUrl = 'https://api.apiflash.com/v1/urltoimage?access_key=' + access_key + '&url=' + tweetUrl;

  try {
    UrlFetchApp.fetch(requestUrl);
    Utilities.sleep(1000 * 10);
    let image = UrlFetchApp.fetch(requestUrl).getBlob();
    fileUrl = folder.createFile(image).setName('任意の名前' + now).getUrl();
  } catch(error) { //API FLASH月上限の100Screenshotsを超えてしまった場合など
    fileUrl = 'none';
  }
  return fileUrl;
}
```

トリガー作成
* 実行する関数 ... takeScreenshots
* 実行するデプロイを選択 ... Head
* イベントのソースを選択 ... スプレッドシートから
* イベントの種類を選択 ... 変更時
* エラー通知設定 ... お好みで

## 結果

自動でツイートが記録されて、Googleドライブにスクショが保存されるようになったよ。

![sheetsample.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273081/5367aa15-5f7c-fd12-6b26-97a03c6a0340.jpeg)

![drivesample.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273081/2c889641-c450-c49c-4af5-c73fb19be460.png)

#### 追記（2022/5/2）

API FLASHの無料プランは月100枚までしかスクショが撮れないので、リクエストのエラーが返ってきたときの例外処理をコードに追加。
Azure Functions の Python + VSCode 環境不具合への対応

解消にすごく苦しめられたので個人のメモとして置いておきます。
他にもこうやれば解消したよ、という情報があれば是非共有したいです。

# デバッグ実行時にECONNREFUESED:127.0.0.1:9091

Python実行環境へアタッチできない、というエラーなのはぱっと見で想像できますが、その原因が多種多様すぎて解決が大変なエラーです。（以前に比べてこのエラーが出ることは減ったようです）

## 1. Python のバージョンを対象のものにする

2022/4現在では、ver.3.7, 3.8, 3.9 なら動きます。3.10は対象外です。気を付けましょう。64bit マシンでの開発の場合は（大抵はもう64bitだと思いますが）、64bit 版を選ばないとデバッグ実行ができないそうです。（32bit 版を使ったことがないので本当にデバッグ実行できないのかは不明です）

## 2. Azure Function Core Tools を ver.3.x にする

ver.3.x と ver.4.x の2種類がありますが、ver.4.x でうまくいかないときは ver.3.x にしましょう。いずれは ver.4.x できれいに動く日が来ると思います。公式ページのよるとデバッグ実行をするなら ver.3.x を使用せよ、という記載がありますが、ver.4 でも大抵は動きます。

Azure Function Core Tools の version switch は、 https://github.com/anthonychu/funcvm を使うのがすごく便利です。（Node.js必須）

（追記）@horihiro さんよりコメント（ありがとうございます！）
>azure functions core tools のバージョンは更新漏れのようなので v4 でも問題なさそうです。

## 3. Azure Logic Apps (Standard) をアンインストール

これは完全に不具合です。このプラグインがあると、Port:9091を奪われてしまってデバッグ実行時にエラーがでます。早く直してほしいわ・・・

（追記）@horihiro さんよりコメント（ありがとうございます！）
>Logic App (Standard) に "type": "func" のタスクの制御を奪われて、9091 ポートでのデバッグ用の待ち受けをサボる、というのが正確な動きになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222127/105e87b5-7fe8-d9ec-6f1d-c4d05ab473a8.png)

# 実行時に タスク 'func: host start' を見つけられない

仮想環境を再作成すれば大抵直るようです。プロジェクト直下の.venv フォルダを削除します。次にAzureのプラグインを開きます。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222127/5aecc643-6247-6ca2-51c5-2e5006ad5df0.png)

ダイアログが上がってくるので、 Create virtual environment を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222127/67eb1f3b-d924-1073-4ba4-47536ffc3be5.png)

もしくは、.venv フォルダを削除した後にプロジェクトフォルダで Terminal などを開き、次のコマンドで仮想環境を作ります。

```powershell:powershell
py -m venv .venv
```

```bash:bash
python -m venv .venv
```

コマンドについての公式はこちらです。
https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-python?tabs=azure-cli%2Cpowershell%2Cbrowser#create-venv
Dockerコマンド

## 背景
Dockerコマンドをまとめた備忘録です。

## コマンド

- Dockerのバージョンを確認するコマンド
```
docker version
```

- Dockerの実行環境を確認するコマンド
```
docker info
```

- Dockerイメージの一覧を表示するコマンド
```
docker images
```

- Dockerイメージを作成するコマンド
```
docker build -t [作成するイメージ名]　[Dockerfileの場所]
```

- Dockerコンテナを作成するコマンド　
※起動はしない
```
docker create -it [イメージID]
```

- Dockerコンテナを作成＆起動
```
docker run [オプション] [イメージ名:タグ名] [引数]
```

- 起動しているコンテナの一覧を表示するコマンド
```
docker ps
```

- 存在するコンテナの一覧を表示するコマンド
```
docker ps -a
```

- コンテナを起動するコマンド
```
docker start [コンテナID]
```

- コンテナを停止するコマンド
```
docker stop [コンテナID]
```

- 起動中のコンテナにログインするコマンド
```
docker exec -it [コンテナID] [引数]
```
仮想化とクラウドとコンテナ


```
❏仮想化(ホスト型)

■仮想化のメリット
既存マシンが利用できる点
仮想化に必要なソフトウェアが扱いやすい点
テスト環境などを作成したいときに便利

■仮想化のデメリット
一般的にハイパーバイザー型の仮想化ソフトに比べて、
仮想マシンの動作速度が遅い
ホストOSを動作させるための物理リソースが必要
ゲストOSを運用する場合にホストOSでの処理速度が限定的になる


❏仮想化(ハイパーバイザー型)

■仮想化のメリット
ホストOSが不要でハードウェアを直接制御が可能
システム全体の観点から見てリソースの使用効率がよい
管理するサーバの台数削減が可能になるのでリソースの無駄を排除できる
安価なサーバで対応できるのでコスト削減が可能になる
複数の異なるオペレーティングシステムを同時に稼働させ、同じ仮想化ハードウェアリソースをハイパーバイザーと共有できる。


■仮想化のデメリット
仮想化環境の高度な管理を実現するツールが標準装備されていない場合がある
ハードウェアのスペックが低かった場合は処理能力不足となる可能性がある
頻繁にアップデートすを要するものもあるため専門的な知識や技術が必須

❏コンテナ
■コンテナのメリット
処理が軽量
アプリの起動が速くリソース効率が良いので、コスト低減＆パフォーマンス向上が可能
必要最小限のCPUやメモリしか使用しないので負荷が小さく高速な動作が実現可能
比較的容易でコピーも簡単なので作業時間の大幅な短縮が可能（構築時間等）
開発と運用の相性がよくリリースサイクルの高速化が期待できる
本番環境と開発環境を同一の状態で構築できることによる本番運用における環境要因でのトラブルが減少できる
障害時における代替環境への切り替え時間の短縮


■コンテナのデメリット
複数のホストでのコンテナ運用が煩雑になる
カーネルを他のコンテナと共有するため、個別に変更できない
コンテナ環境でベースとなるOSと異なるOSのシステムを動かすことはできない
⇨いわゆるwindowsとLinuxで異なる場合は使用できません。
新しい技術であり学習コストが比較的高いため、学習が必要

❏クラウド
■クラウド化のメリット
コストが抑えられる
担当者がいない、または育っていない場合は外部に委託せざるを得ず、ランニングコストがかかるが、クラウドサービスなら、費用負担は基本的に定額料金のみとなる

サービス利用の場所を選ばなくて済む
リモートワークが増えている現状を考えると、場所を選ばずに利用できるのは大きなメリットと言えるでしょう。従業員は無理に出社する必要がなくなるため、経費削減の効果も期待できる。

運用負荷を削減できる
クラウドサービスなら運用を任せきりにできるのがメリットです。従来は自社で行っていた細かなメンテナンスは、サービスの提供元が済ませてくれるので必要ありません。システムの維持に担当者を配置する必要すらなくなるため、人件費の削減にもなる

すぐにサービスを利用できる
速やかに社内システムを見直す必要があるときは、クラウド化が有効といえるケースもある。

データ共有が楽になる
端末の環境が異なる場合でも、クラウドサービスにさえ対応していれば互換性を気にせず快適に仕事ができるようになるのはメリット。

■クラウド化のデメリット
ユーザー側でカスタマイズできる範囲に限度がある。
オンライン環境が必須となる。
回線速度が遅い場合や、接続が不安定になっている状況では満足に使えないことがあります。
システムの運用を任せきりにできるが使い勝手の良し悪しも他社に任せることになる。
仕様変更で使いにくくなったり、月額料金が上がったりしても使用者側では対応ができません。
（いつサービス自体が終了するかも懸念度としては十分把握しておいたほうがいい）
ユーザー新規登録機能に画像登録も追加する方法【Ruby on Rails】

まずは完成イメージから。
こんな感じで、新規ユーザー登録画面でユーザーアイコン用の画像も設定出来る仕様を実装してみます。　ちなみに、画像の登録は面倒だし、取りあえす画像は設定しないといった場合にはデフォルトで画像が自動で設定される仕様になっています。

![スクリーンショット 2022-04-08 9.54.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2316171/ffb3997b-dfca-e89e-b108-abd87b01cb7b.png)


## コントローラーで、createアクションの設定

```rb:app/controllers/users_controller.rb
  def create
    @user = User.new(user_params)
    image = params[:user][:user_image]  ←　この行を追加
    hash = SecureRandom.hex(10)  ←　この行を追加
    @user.user_image = "#{@user.name}_#{hash}.jpg" if image  ←　この行を追加
    if @user.save
      write_image(@user.user_image, image) if image  ←　この行を追加
      session[:user_id] = @user.id
      flash[:notice] = "ユーザー登録が完了しました"
      redirect_to user_path(@user.id)
    else
      @user.user_image = image if image  ←　この行を追加
      render :new
    end
  end
```

まずは下記の一文でuser_imageカラムにファイル名を入れています。
```rb
hash = SecureRandom.hex(10)
@user.user_image = "#{@user.name}_#{hash}.jpg" if image
```

ファイル名を"ユーザー名_ランダムな文字列"としています。
これは、なぜかと言うと、ユーザーの新規作成処理なので@user.saveとするまではユーザーidがありません。　そこで、ユーザー名とランダムな文字列（他の画像のファイル名と被らないように）をつけることでユニークな名前としています。
※ それに伴いupdateでも同じようにユーザー名＋ランダムな文字列としました。

そして下記によってupdateと同様、ファイルに画像を書き込みしています。

```rb
# write_imageメソッドが呼ばれます。
write_image(@user.user_image, image) if image
```

## コントローラーで、updateアクションの設定
```rb
def update
    redirect_to user_path(@user.id) and return if @user.guest?
    
    @user.name = params[:name]
    @user.email = params[:email]

    image = params[:image]  ←　この行を追加
    hash = SecureRandom.hex(10)  ←　この行を追加
    @user.user_image = "#{@user.name}_#{hash}.jpg" if image  ←　この行を修正
    if @user.save
      write_image(@user.user_image, image) if image  ←　この行を修正
      flash[:notice] = "ユーザー情報を編集しました"
      redirect_to user_path(@user.id)
    else
      @user.user_image = image  ←　この行を追加
      render :edit  ←　この行を修正
    end
  end
```

ちなみに、ストロングパラメーターでは画像のカラムは設定していません。
```rb
    def user_params
      params.require(:user).permit(:name, :email, :password)
    end
```

## ビューで画像投稿フォームの追加

```erb:app/views/users
# app/views/new.html.erb
        <%= form_with model: @user, url: "/users/create", multipart: true do |f| %>
          <%= f.label "ユーザー名" %>
          <%= f.text_field :name %>

          <%= f.label "画像" %>  ←　この行を追加
          <%= f.file_field :user_image %>  ←　この行を追加

          <%= f.label "メールアドレス" %>
          <%= f.email_field :email %>

          <%= f.label "パスワード" %>
          <%= f.password_field :password %>

          <%= f.submit "新規登録" %>
```

ではサーバーを立ち上げてみましょう。
ユーザーの画像を登録して新規作成することができれば成功です！
EPUB とは

## 勉強前イメージ

なんかのサービス？

## 調査

### EPUB とは

Electronic PUBlication の略で、
電子書籍のファイル形式の標準規格の一つになります。
電子書籍の業界団体のIDPFが策定した企画でISO/IECによって国際標準規格にもなっています。

epubファイルはコンテンツ群をディレクトリ構造で配置して全体を一つのzipにしたような構造になっています。
拡張子は `.epub` です。

元々はepubのリリースは2007年でその後バージョアップされています。

### 種類

epubは大きく2種類があります。

- 固定型

レイアウトが固定されているepubデータで
紙のレイアウトと同じ状態でepub化することが出来ます。
ただし、固定型にすると文字検索や文字ハイライトという特徴が失われるため
紙のまま電子化したいなど以外ではあまり採用されないことがある

- リフロー型

再レイアウトが行われるepubデータで
使用するリーダーに合わせて文字サイズ・行間を変更することが可能である。
こちらは文字検索・ハイライトなどが使用できるため
電子書籍の特徴を活かせる形式になります。

## 勉強後イメージ

## 参考

- [EPUB](https://www.jepa.or.jp/ebookpedia/201507_2529/)
- [EPUB](https://e-words.jp/w/EPUB.html)
vbaでWinSCP経由でs3.amazonaws.comにアクセスしアップロード等するには

諸々割愛


１、vba のshellでバッチファイルを実行する。

２、そのバッチファイルは
s3.amazonaws.comのシークレットキーをパイプで前に置いておき
winscp.comを起動してWinSCPでのコマンドが入ったテキストファイルを読みに行く動作。

３、WinSCPでのコマンド群はtxtファイルで用意しておく。
アクセスキーとs3.amazonaws.comを開くコマンドなどを入れておく。

で操作が可能でした。


WinSCPは全ユーザ用としてProgram Files (x86)\WinSCPに
インストール済みとしてソースを見ながら再度説明していきます
```vba:control_winscp.vb
sub control_winscp()
    Shell ("C:\Program Files (x86)\WinSCP\execute_upload.bat")
end sub
```
これで execute_uoload.bat というバッチを実行。多分場所はどこでも大丈夫なはず


```bat:execute_upload.bat
@REM
@echo off
cls
echo {シークレットキー}|"C:\Program Files (x86)\WinSCP\WinSCP.com" /console /script="C:\Program Files (x86)\WinSCP\winscp_upload_commands.txt"
```
英語の解釈の様に後ろから読解すると
winscpで実行したいコマンド群のテキストを収めた winscp_upload_commands.txt を
/script=　として実行したい
WinSCP.comで
アクセス後はシークレットキーを入力して。

といった感じでしょうか。
シークレットキーをパイプで繋いで前に置いておくのがトリッキーでした。
コマンドプロンプトのお作法で 実行しますか？　Y　を入力。的な状況の時は
このようにするようです。

```txt:winscp_upload_commands.txt
open s3://{アクセスキー}@s3.amazonaws.com:{ポート}/{バケット名}
cd {上げたいディレクトリ}
put "\\{上げたいファイルのパス}\file1.htm"
put "\\{上げたいファイルのパス}\file2.png"
put "\\{上げたいファイルのパス}\{フォルダ名}"
```
ここからはWinSCPコマンドライン上のコマンド群ですね
openでアクセスして
cd で階層を移動
putでファイルやフォルダのアップロード

です。
バッチファイルに記述すると文字化けしてしまい通りませんでした。
base64とかじゃないとダメなのかもしれません。


これでvba上で操作が可能になりますが自動実行などaws側が認めていない可能性もあるので
利用の際はご注意を。
Dockerに対する２つの考え方

最近業務でDockerをさわる機会が多いので、何回かに分けて基本的な考え方をまとめておこうと思います。  

初回として、Dockerに対する考え方には２種類あるぞ、という話をまとめます。  
実際のDockerの使い方は出てきません。  

第２回は、<a href="https://www.northtorch.co.jp/archives/1155">こちら</a>です。

※ 本記事は、2022/02/22に[弊社スタッフブログ](https://www.northtorch.co.jp/archives/1125)に投稿した記事をQiitaに転載しています。

## TL;DR

- Dockerでの処理には2通りの考え方がある
    - 仮想マシンおよび仮想ネットワークとしてのDocker
    - 特定の処理を動作させるための安定環境としてのDocker

## 承前

Dockerの使用方法はググるとたくさんでてきます。  
ネット上の記事を見れば、Dockerを使用して何かを動かすことはできるようになります。  
しかし、実際に業務で使用するとなると
- どの部分をDockerで仮想化すべきか
- DockerとDocker Composeの使い分けはどのようにすべきか
等で迷うことが多いと思います。  
もちろん、唯一の正解があるわけでなく、それぞれの状況に応じた設計をする必要があるのですが、とっかかりとしてDockerに対して、下記２つの考え方を持っていると切り分けがしやすいと感じます。  

- 仮想マシンおよび仮想ネットワークとしてのDocker
- 特定の処理を動作させるための安定環境としてのDocker

## 仮想マシンおよび仮想ネットワークとしてのDocker

一般にDockerでググると出てくるのは、こちらの考え方に沿った情報だと思います。  
Docker Composeを使用すると複数のコンテナを仮想ネットワーク上で協働させることができるため、例えばひとつのWebサービスを
- Webサーバ
- アプリケーションサーバ
- データベースサーバ
の3つのコンテナを使用して実現したりします。  

考え方は従来のシステム設計と同一で、各コンテナを仮想的な一台のサーバとみなし、必要なOSやパッケージをインストールして起動します。  
nginxやMySql等標準的なアプリケーションの場合、立ち上げるだけで動作するコンテナが公式に公開されていますので、Docker Composeに組み込むだけで仮想システムを構築することができます。  

## 特定の処理を動作させるための安定環境としてのDocker

もうひとつの考え方は、特定の処理を安定動作させるための環境としてDockerを使用する、というものです。  
Docker単体で動作させる場合、こちらの考え方が根底にあるように思います。  

古来から、ある処理を安定して動作させるのは大きな課題でした。  
- OSのバージョンが合わない
- 必要なパッケージがインストールされていない
等の理由で、ある環境で動作した処理が別の環境では動作しない、という事はよくあります。
DockerはOSごと仮想化しますので、上記のような環境齟齬が発生しなくなります。  

例えば、定期的な処理についてcronからDockerコンテナ上でコマンドを実行するような使い方の場合、こちらの考え方になると思います。  
AWS Lambdaとかを使用していると、違和感のない考え方かと思います。

## 設計する時に考えること

最終的に欲しいものが  
- アプリケーションとしての動作
- コマンドの実行結果
のどちらなのかを意識する、という、すごく当たり前の話でした。
kintone User API を cURLコマンドで実行する方法

kintoneのユーザーをcURLで登録する方法のメモです。

# User API

## ユーザーインポート API（JSON）

### 登録

```
curl -X POST -H "X-Cybozu-Authorization:BASE64_ENCODED_STRING" -H 'Content-Type: application/json' -d '{"users":[{"code": "demoUser1", "valid": false, "password": PASSWORD, "name": "デモユーザー1"}]}' 'https://sub-domain.cybozu.com/v1/users.json'
```

# 参考

https://developer.cybozu.io/hc/ja/articles/360023068751-curl-%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A7-kintone-REST-API-%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%97%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86#curl
JavaScript　型を調べる

## 用途
- JavaScriptのコードで型を調べたい時に使用する。
:::note warn
注意
`typeof` は「null」や「object」を正しく判別できない。
その場合は `Object.prototype.toString.call()` を使用する。
:::

## 使用方法
## typeof
```js:書き方
typeof(型を調べたい値);
```

```js:例
console.log(typeof("hogehoge"));
console.log(typeof(1));
console.log(typeof(null));
console.log(typeof([hoge1, hoge2, hoge3]));

// 結果
// string
// number
// object
// object
```
「null」と「配列」が `object` で返ってくる。

## Object.prototype.toString.call()
```js:書き方
var hoge = Object.prototype.toString;
console.log(hoge.call(型を調べたい値));
```
```js:例
var hoge = Object.prototype.toString;
console.log(hoge.call("hogehoge"));
console.log(hoge.call(1));
console.log(hoge.call(null));
console.log(hoge.call([hoge1, hoge2, hoge3]));

// 結果
// string
// number
// null
// array
```
「null」と「配列」が `null` と `array` で返ってくる。
Window端末でvimtutorをコンソール上で実行する

Windowsに`vim 8.2.4647`をインストールした環境で、コマンド`vimtutor`を実行すると`gvim`で`vimtutor`が起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/1b5985d9-9f1e-9a85-4367-a5431c86d65c.png)

これは`vimtutor.bat`が実行されて`vimtutor`が起動されているわけですが。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/3465a41f-92d0-e552-d07d-af36b0176152.png)

たまに`vimtutor`をやろうと思った際に、`gvim`ではなくコンソール上で`vimtutor`をやりたいと思い、そもそも`vimtutor.bat`はどうなってるの？　と眺めてみたら、そのものズバリなオプションが冒頭に書いてありましたので忘備録。

>:: Usage: vimtutor [-console] [xx]
::
:: -console means gvim will not be used
:: xx is a language code like "es" or "nl".
:: When an xx argument is given, it tries loading that tutor.
:: When this fails or no xx argument was given, it tries using 'v:lang'
:: When that also fails, it uses the English version.

上記のように記載あり、gvimを使わないで起動するには`-console`オプションを付ければよいようです。

```powershell
vimtutor -console
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/229c20ba-7650-1ed5-0628-77abd2f8a561.png)

## Windows Terminalのプロファイルに追加してみる

せっかく？　なので`Windows Terminal`のプロファイルに追加して、`Windows Terminal`のタブで`vimtutor`が開くように設定してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/82d19b72-f889-026c-0ffe-d9a791283d79.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/889c5268-61e5-4f31-3702-dc012359b119.png)

## 総評

batファイル読みたくないなと思いつつ開いたら、欲していたものが冒頭に書いてありました。
IEEE829から学ぶテストドキュメント～⑧テストサマリーレポート編～

# 1．概要
IEEE829から学ぶテストドキュメントの最終第8回目として、テストサマリーレポートについて記載いたします。テストサマリーレポートを作成する目的は、

**①テストが終了しても問題ないことを関係者に伝える**
**②次の案件をよりよくするための教訓にする**

となります。

テスト完了後の終了結果をすべてまとめると膨大な量となることが多いので、テストサマリーレポートでは**重要な部分を要約**して記載します。また、テストが完了すると別のプロジェクトに移動する人が多いので、できる限りプロジェクトの期間中に作成することが求められます。（テストが完了してから作成していては遅い！）

# 2．IEEE829のテストサマリーレポートについて

- テストサマリーレポート識別番号
- テストの要約　⇒②
- 計画との差異　⇒②
- 総合評価　⇒①
- 結果の要約　⇒①
- 個別評価　⇒①
- 活動の要約　⇒②
- 承認

上記がIEEE829のテストサマリーレポートに記載する項目になります。また、テストサマリーレポートは「①テストが終了しても問題ないことを関係者に伝える」ために、以下の項目を記載します。

### 現状のテストの品質状況

- リリースしても問題ないか？（終了基準を満たしているか）
- 不具合は残っていないか？また、対応策はあるか？

### 報告資料としての項目

- テストの評価が数値で記載されているか？
- テストの結果が要約されているか？
- テストの分析結果（不具合分析など）が記載されているか？

「②次の案件をよりよくするための教訓にする」のために記載する項目は以下となります。（振り返るために、「**何を行ったか**」を明確にする）

### 対象システムの情報

- ソフトウェア名
- バージョン名
- 動作環境…など

### テストの活動

- 行ったタスク（テスト計画、テスト設計、テスト実施など）
- テストタイプ（機能テスト、ユーザビリティテストまど）
- テストレベル（単体テスト、結合テスト、システムテスト）
- 使用したテストの技法

### 学んだ教訓

- ベストプラクティス
- 計画との差異（初期の考えとどこがずれたのか）

# 3．サマリーレポートの項目の詳細

- テストの要約

②に該当。どんなソフトウェアをどんな環境でテストしたのか、を記載する。

- 計画との差異

②に該当。問題が起きた点はどこか、計画とのずれはどうして起きたのか（テストの終了基準と比較する）、などを記載する。

- 総合評価

①に該当。テスト中に収集したメトリクス等も記載する。リリースしても問題ないか一言で記載（不具合が残っているのか、直っているのか記載する）。

- 結果の要約

①に該当。テストの消化数や不具合の発見数などを時系列で記載する。未解決な不具合もすべて列挙し、その対応方法を記載。また、不具合全体の分析結果があれば記載する。（できれば図にするとわかりやすい）

- 個別評価

①に該当。各テストタイプやテストレベルごとの評価を記載する。（ここにベストプラクティスや教訓があってもいい）

- 活動の要約

②に該当。どんなテスト活動（テスト計画、テスト設計、テスト実施、テスト管理…など）を行ったのか記載する。また、テスト活動中に作成した成果物も記載する。

# 4．サマリーレポート作成前に実施すること

サマリーレポートを作成する前に案件中に起きた出来事をまとめるため、振り返りを実施しておいた方がいいと言えます。KPIやYWTなどの手法を用いて実施することで、レポートに記載すべきベストプラクティスや教訓などを集めます。

レポートの記載内容を充実させるために、外部の専門家を招くのも1つの方法です。その時、TPI等の改善技法でプロセス診断を実施するのもいいと思います。

また、案件終了前に収集すべきメトリクスを集めて、最終的な結果を算出します。（収集するメトリクスは、テスト計画書作成時にまとめるべきです。）

この際に行ってはいけないことは、**サマリーレポートを充実させるためにこの時点でメトリクスを決めることです**。メトリクスを後出しで決めてしまった場合、個人個人の過去の記憶から数値を算出しなければならないため、**数値の精度が非常に下がります**。

また、算出した値が悪いためテストのやり直しをすることもあるので、メトリクスを収集する目的を早くから決めて実施すべきと思います。


# 5．まとめ

テストサマリーレポートは、**①テストが終了しても問題ないことを関係者に伝える**、**②次の案件をよりよくするための教訓にする**ためのドキュメントです。そのため、関係者にわかりやすく伝えることを心がけ、次に活かせる教訓があれば問題ありません。

ただ、サマリーレポートを充実させるために、テスト完了間際にあれこれメトリクス等を追加すると、収集するのに時間がかかり、結果としてまとめることができなくなるので注意が必要です。
【備忘録】PythonでMySQLに接続しよう

# 経緯
Pythonを使用してMySQLからデータを取得したい。
DBの列構成が変わっても結果に変化がないよう、辞書型を採用した。

# ライブラリインストール
~~~cmd:cmd
python -m pip install pymysql
~~~

# ソース
~~~python:python
import pymysql

SQL="SELECT * FROM userlist;"

mysql_kwargs = {
    "host":     "127.0.0.1",
    "port":     3306,
    "user":     "testuser",
    "password": "test",
    "database": "testdb",
}

conn = pymysql.connect(**mysql_kwargs)

# カーソルを取得する（辞書型）
cur = conn.cursor(pymysql.cursors.DictCursor)

# SQL実行
cur.execute(SQL)

# 実行結果を取得する
rows = cur.fetchall()

for row in rows:
    print(row["username"])

cur.close
conn.close
~~~

# もし列名が不要の場合
下記を
~~~python:python
cur = conn.cursor(pymysql.cursors.DictCursor)
~~~
このように変える。
~~~python:python
cur = conn.cursor()
~~~
但し、列名では取得できなくなるので、値取得も下記のように変更する。
~~~python:python
for row in rows:
    print(row[0]) #1列目の値を取得
~~~