OmniAICreator/Qiita-1.07M huggingface dataset:
[C言語] pthread/mutexを使った並列処理

pthreadとmutexを使い、データの競合を起こさずに並列処理をする方法について調べてみました。

まずはptreadを用いた並列処理のサンプルです。
2つのスレッドでそれぞれ1万回ずつインクリメントすることで最終的にcntの値を20000にします。

```c:
#include <stdio.h>
#include <pthread.h>

int	cnt = 0;

void *routine(void *p)
{
	for (int i = 0; i < 10000; i++)
		cnt++;
	return (NULL);
}

int main(void)
{
	pthread_t p1, p2;

	// 2つのスレッドで並列処理する
	pthread_create(&p1, NULL, &routine, NULL);
	pthread_create(&p2, NULL, &routine, NULL);

	// 終了するまで待つ
	pthread_join(p1, NULL);
	pthread_join(p2, NULL);

	printf("cnt -> %d\n", cnt);
}
```

実行結果

```bash:
$ gcc test.c
$ ./a.out 
cnt -> 19677
$ ./a.out 
cnt -> 15331
$ ./a.out 
cnt -> 12060
```
おかしいですね。
結果が実行するたびに変わってしまいます。

実はこのままだとデータの競合が起きてしまい、正しい結果が得られません。
そのため、mutexを使うことで同時アクセスを防ぎます。

```c:
#include <stdio.h>
#include <pthread.h>

int cnt = 0;
pthread_mutex_t	mutex;

void *routine(void *p)
{
	for (int i = 0; i < 10000; i++)
	{
		pthread_mutex_lock(&mutex);	//lockして同時アクセスを防ぐ
		cnt++;
		pthread_mutex_unlock(&mutex);
	}
	return (NULL);
}

int main(void)
{
	pthread_t p1, p2;
	pthread_mutex_init(&mutex, NULL);

	// 2つのスレッドで並列処理する
	pthread_create(&p1, NULL, &routine, NULL);
	pthread_create(&p2, NULL, &routine, NULL);

	// 終了するまで待つ
	pthread_join(p1, NULL);
	pthread_join(p2, NULL);

	pthread_mutex_destroy(&mutex);
	printf("cnt -> %d\n", cnt);
}
```

実行結果

```bash:
$ gcc test.c
$ ./a.out 
cnt -> 20000
$ ./a.out 
cnt -> 20000
$ ./a.out 
cnt -> 20000
```


無事に正しい結果が得られました。
mutex_lockをすることで同時に別のスレッドがアクセスするのを防いでくれるみたいですね。
ちなみに値の変更だけではなく、参照する際もロックが必要です。

そのため次のような条件文でアクセスする際も必要となります。


```c:
#include <stdio.h>
#include <pthread.h>

int cnt = 0;
pthread_mutex_t	mutex;

void *routine(void *p)
{
	for (int i = 0; i < 10000; i++)
	{
		pthread_mutex_lock(&mutex);		// lockして同時アクセスを防ぐ
		if (cnt == 10000)			 	// 参照する際もlockが必要
		{
			pthread_mutex_unlock(&mutex);
			break ;
		}
		cnt++;
		pthread_mutex_unlock(&mutex);
	}
	return (NULL);
}

int main(void)
{
	pthread_t p1, p2;
	pthread_mutex_init(&mutex, NULL);

	// 2つのスレッドで並列処理する
	pthread_create(&p1, NULL, &routine, NULL);
	pthread_create(&p2, NULL, &routine, NULL);

	// 終了するまで待つ
	pthread_join(p1, NULL);
	pthread_join(p2, NULL);

	pthread_mutex_destroy(&mutex);
	printf("cnt -> %d\n", cnt);
}
```

実行結果

```bash:
$ gcc test.c
$ ./a.out 
cnt -> 10000
$ ./a.out 
cnt -> 10000
$ ./a.out 
cnt -> 10000
```
正しく10000で処理を終了できましたね。

## まとめ
無事安全に並列処理を実行することができました。
gcc -fsanitize=threadでコンパイルしてあげると、データ競合のリスクがある際にエラーを出してくれるので便利です。
共用の変数にアクセスする際はロックを忘れないようにしたいですね。
Github Actionsでdiffチェックをしてみよう

#初めに
CircleCIからGitHub Actionsへの移行で気づいたことの共有です。
目的：pr際にgithub actionsが動作するように作る。

###環境
actions/checkout@v2

**レポジトリ**
origin/main
origin/new4

###diffチェックを実行する
```
on: 
  pull_request:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: js diff check
        run:  git --no-pager diff --name-only --diff-filter=AMCR origin/${GITHUB_BASE_REF}..origin/${GITHUB_HEAD_REF} -- "*.js" \
              > js-files.txt || echo 'js not exists'


```
githubの環境変数については、[こちら](https://docs.github.com/ja/actions/reference/environment-variables)

###結果
```
fatal: bad revision 'origin/main..origin/new4'
js not exists
```
CircleCiでは実行できたコードなのにbad revisionが出た。

###エラーの原因
1. CircleCiでは全てのlogを持ってくる
2. gihub actionsのcheckout@V2のdefaultはlogを１つ持ってくる

>default 
>＠V2: logを**一つ**持ってくる (depth-fetchが1だ)
>＠V1: logを**全部**持ってくる


###解決
```
- uses: actions/checkout@v2
  with:
    fetch-depth: 0 
```
depthを設定する必要があった。

###追加で
circlecでの**always**
>-run:
　name: test
　when: always

はgithub actionsでは**if**
>-name: test
　if: ${{ always() }}

で使えます

##終わり
割と簡単な問題だったが、公式docにはなかったものなので、
自分は原因探しに時間がかかってしまいました。
私みたいな人が出ないようにと思って投稿しました。
役に立てたら幸いです。

## PR
不動産売却の時は LIFULL HOME'S へ！

https://lifullhomes-satei.jp/
axiosをクラス化してメソッドを再利用しやすくする

## 概要

現在udemyでReact.jsとNode.jsでECサイトを作成する講座を学んでいるのですが、その際axiosで使うメソッドを再利用するための方法が少し面倒で、こっちの方が良いんじゃないかと思ったのでここにメモを残しておきます。

## udemy講座のやり方

```
// src/fucntions/auth.js
import axios from "axios";
export const createOrUpdateUser = async (authtoken) => {
  return await axios.post(
    `${process.env.REACT_APP_API}/create-or-update-user`,
    {},
    {
      headers: {
        authtoken,
      },
    }
  );
};

export const currentAdmin = async (authtoken) => {
  return await axios.post(
    `${process.env.REACT_APP_API}/current-admin`,
    {},
    {
      headers: {
        authtoken,
      },
    }
  );
};

```

```

// src/fucntions/category.js
export const updateCategory = async (slug, category, authtoken) =>
  await axios.put(`${process.env.REACT_APP_API}/category/${slug}`, category, {
    headers: {
      authtoken,
    },
  });

```


なんかごちゃごちゃして見づらいです。
メソッドを取り出して使う時もいちいちimportする際にメソッドを指定する必要があります。

```
import { createorUpdateUser, currentAdmin } from '../../functions/auth';
import { updateCategory } from '../../functions/auth';

const handleSubmit = (e) => {
    e.preventDefault();
    createCategory({ name }, user.token)
      .then((res) => {
        ...
}
```




## クラス化

再利用しやすくするためaxiosのメソッドをクラスに入れます。

```
// src/utils/API.js
import axios from 'axios';


// 共通処理
const instance = axios.create({
  baseURL: process.env.REACT_APP_API_URL,
  timeout: 30000,
  cors: true,
})

// クラス化
class API {

 createOrUpdateUser(authToken) {
    return instance.request({
      method: 'POST',
      headers: {
        authToken,
      },
      url: '/create-or-update-user'
    });
  }

  currentUser(authToken) {
    return instance.request({
      method: 'POST',
      headers: {
        authToken,
      },
      url: '/current-user'
    });
  }
  
  updateCategory (slug, category, authToken) {
    return instance.request({
      method: 'PUT',
      headers: {
        authToken
      },
      url: `/category/${slug}`,
      data: {
        name: category,
      }
    })
  }
}

export default new API();

```

これで大分見やすくなりました。こちらの方が何のためのメソッドかがぱっと見でわかるので良い気がします。

使う時はAPI.メソッド名とするだけで呼び出すことができます。
axiosは非同期処理ですので呼び出す時はasync/awaitを追加するのを忘れないでください。

```
import API from '../../utils/API';


const handleSubmit = async (e) => {
  e.preventDefault();
   await API.createCategory(name, user.token)
    .then((res) => {
      ...
}
```

## まとめ

クラス化した方がコードがスッキリして再利用しすくなりました。

話が変わりますが`.env`ファイルに入れた環境変数が呼ばれないのなんでだろうと思ってたのですが`create-react-app` を使うと `REACT_APP_` を環境変数の前に入れないといけないみたいです。

https://create-react-app.dev/docs/adding-custom-environment-variables/

## 参照
https://github.com/axios/axios#axioscreateconfig
システムトラブルの問題解決に物理学のプロセスを導入する

エンジニアとは全く関係ないと思われる物理学ですが、実は物理学の研究プロセスは、システムトラブルの調査やプログラムのデバッグの際に重宝すると筆者は考えています。

今回は文系出身のエンジニアや「物理学とか蕁麻疹出るわ！」と思っている方に向けて、物理学を学んでいるとこんなにメリットあるんだぜ！ってのを紹介していきたいと思っています。

※ちなみに筆者は自社開発企業でWebアプリケーションエンジニアをしています。大学では物理学科で物性物理を専攻していました。


# そもそも物理学の研究ってどんな感じなの？

まず物理学に明るくない方向けに、物理学の研究がどのように進められているのかを説明していきます。

一般に物理学とは「自然界で起きている現象を数学を使って記述する」学問です。
数学を使って記述するためには「現象」が「数式」で示せることを実証していく必要があります。※数式でない場合もある。

現象の例

- リンゴが地面に落ちる
- 地球が太陽の周りを公転する
- 風が吹く

これは超簡単な例で誰でも知っている現象だと思います。
しかしこれを数式でどう表すか知っている人は物理学をやったことある人でないとわからないかと思います。
現在ではこの現象がいずれも数式で表すことが可能です。
ではどのように「数式」で表せることが実証されたのでしょうか。。。

いずれにも共通して言えることは

- 影響範囲のものを計測する
- 複数回同じことを試行する
- 対照実験（1つのパラメータだけを変えて実験する手法）

これらによって、「普遍的な法則」を現象から導き出します。

## 仮説を立てて、それを検証する

例えば、1つ目であれば **「自由落下運動」** といいますが、

- 重いモノのほうが先に落ちるだろう
- 高いところから落とすと高さに比例して落ちる時間がかかるだろう

と **「仮説」** をたてることができます。
仮説とは上記のように「きっとこうなっているだろう」と「予想」を立てておくことです。
すると、

- リンゴの質量を量っておく
- 落とす高さを測っておく
- 地面に到達するまでの時間を計測する

というように影響するだろうものの計測（記録）をすべきものが明らかになります。
そして

- リンゴを鉄球に変えて実験してみる
- 高さを2倍のところにして実験してみる
- 数十回、数百回と試行し、毎回時間を計測する

というように、「仮説」に対する「実証実験」をしていきます。
すると、

- リンゴでも、鉄球でも同じ高さから落としたら、同じ時間で地面に到達すること
- 高さを2倍にしてもかかる時間は2倍ではなく、√２倍であること

などが実験からわかります。
これにより「仮説」を「検証」することで、現象の特徴が理解でき、これにより、

- 自由落下運動に質量には関係ない（すべてのものに同じ大きさの重力加速度がかかっていること）
- 自由落下運動の落下時間は高さの√に比例している（力学的エネルギー保存則）

が導かれます。（歴史上こういう順番だったかはわかりませんが）

## ここで言いたいこと

物理学の簡単な研究の例を用いましたが、ここから言いたいことは

- 問題や解き明かしたい事象に対して **「仮説」** を立てる
- 仮説を立てたらそれに対して必要な要素を **「計測（ベンチマーク）」** し、実際に **「実験」** する

このプロセスを何度も実行してきた結果が今の物理学を作り上げています。

※重要なことを忘れてましたが、サイエンスの考え方は同様に「仮説→検証→普遍的法則の実証」と言うプロセスは変わらないと思います。
ただ、私が物理学専攻だったこともあり、物理学が伝えやすいただそれだけです。

# エンジニアの仕事に置き換える

システムトラブル調査やプログラムの不具合修正においてこの物理学の考え方が非常に重要です。

- 「ボタンを押しても画面遷移しません。何でですか？」
- 「100と表示されるべきなのに10と表示されます」

のような問い合わせや質問がまぁまぁあります。
これは上の物理学の考え方がなっていない問い合わせです。
こういう問い合わせを受けるとエンジニアは2通りに分かれます。

- 隅から隅まで原因を総当たりで調べる(私は **「ホワイトボックス調査」** と勝手に呼んでいます)
- 現象に対し影響する設定やオペレーションをヒアリングし、ひとつづつ可能性をつぶしていく（仮説→検証→実証のサイクル）

前者は、言うまでもなくえげつない工数がかかります（IT人材不足のこのご時世にこんなエンジニアは存在してはならない）。
後者は、発生条件を絞り込んでいき、「設定の組み合わせが原因か？」、「このオペレーションでしか発生しないようだ」のように、影響範囲を小さくしてから、根本的な原因を1つずつ検証していきます。

今回の1つ目の例であれば

- XXXの設定とYYYの設定はどうなっていますか？
- ボタンのある画面の前の画面はどの画面ですか？
- ほかのボタンは問題なく動きますか？

のようにあらかじめその動作に及ぼす影響範囲から必要なものをヒアリング（計測、ベンチマーク）しておき、

- XXXの設定をx1からx2に変えたらどうだろうか
- ほかのボタンは意図通りに動いているみたいだからこのボタンのバグかもしれない

のように仮説を立てることができ、あとは順に検証して聞くという作業になります。

不具合修正の場合も、
まず「設定やオペレーションから再現する状態を明らかにする」→「設定やオペレーションを1つずつずらしたら再現するか？」のように絶対発生する状態をベンチマークしておき、そこから仮説に基づき検証をしながら影響範囲を絞って、最終的な修正方針を固めるというプロセスを踏むと思います。



# 終わりに

新人エンジニアや、一部の論理的思考に欠ける人材が、優秀な人材の工数を奪わないためにも、IT業界で「エンジニア」を名乗る人にはぜひこの物理学のプロセスである「仮説を立て→検証し→実証していく」のサイクルを実行できるようになってほしいです。
日々のトレーニングは必要ですし、前提知識も必要だと思いますが、多くのエンジニアは「技術などに対する知的好奇心」は高いはずなので、合わせて今回紹介した物理学のプロセス、ロジカルシンキング、クリティカルシンキングのような思考方法なども学んで、優秀なエンジニアを目指していきましょう。


※クリティカルシンキングについては私の個人ブログにざっくりまとめていますので参考まで↓↓↓


https://soepysoechang-af.hatenablog.jp/entry/2021/05/30/233308
シンギュラリティ

AIを調べていて興味を持ったので共有する。

[動機]
始めにみなさんはシンギュラリティという言葉を知っていますか？
自分は、企業研究で会社を調べている際にその言葉に出会い、気になったので調べました。
まず始めに言葉の定義から話していきます！

[定義]
シンギュラリティ：アメリカの発明家で人工知能研究の世界的権威であるレイ・カーツワイル博士らが示した未来予測の概念で、一つの仮説として想定され得る、人工知能（以下AI）が人間の能力を超える時点 や、それにより人間の生活に大きな変化が起こるという概念のこと

[追加で！]
詳しく説明すると、テクノロジーの加速度的な進化の結果、いずれコンピュータは人間の知能を超える「超知能」を獲得するようになり、社会や人々の生活に決定的な変化が起こると考えられているとのことです。

[時期]
ちなみに大体いつ頃からかも分かっており、レイ・カーツワイル博士は、「2029年にAIが人間並みの知能を備え、2045年に技術的特異点が来る」と提唱しています。

[内容]
AIが人類の脳を超えることで、AI自身がより優れたAIを生み出せるようになります。その結果、2045年以降人類は何かを新たに発明する必要がなくなったり、AIが出す答えや生み出す物を予測することができなくなったりします。これがAIが人類最後の発明となるともいわれるゆえんらしいです。

[感想]
またいつものAIに仕事奪われる話かぁと思って記事を読んでいると、妙にリアルな内容で少しビビりました。一応補足になるかもですが、奪われる仕事は基本的に料理人やレストランの従業員、一般的な事務員みたいです。これらの共通点は、比較的単純作業を行う業種で、反対に奪われにくいのは芸術家や教師、警察などのクリエイティブな職種みたいです。今の勉強(AIの勉強)は、おそらく後者に関連していると思われるので、もっと真剣に取り組まねばと感化された気がします(笑)
ぜひコメントお待ちしています！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/fd44cf13-2808-be4f-ac10-d42f41764d60.png)
Next.js

# Next.jsの導入
## パッケージのインストール

```bash
yarn add next react react-dom
```

## package.jsonにスクリプトコマンドを追記します
```package.json
"scripts": {
  "dev": "next dev",
  "build": "next build",
  "start": "next start",
  "lint": "next lint"
}
```

# 静的生成とサーバーサイドレンダリング
Next.jsではページという概念を中心に構成されています。ページとはpagesディレクトリ配下のjsファイルからエクスポートされているreact component です。pagesディレクトリ配下にindex.jsを作成しyarn dev を実行しlocalhost:3000にブラウザでアクセスするとindex.jsの内容が表示されるいるのが確認できます。


```bash
mkdir pages && cd pages && touch index.js
```

```/pages/index.js
function HomePage(){
    return(
        <div>
            <h1>Welcome to Next.js</h1>
        </div>
    )
}
export default HomePage
```

Next.jsではページはreact component でありそれぞれのページはファイル名によってルーティングされます。
例えばpages/about.jsを以下の内容で作成した場合、localhost:3000/aboutでabout.jsの内容が表示されます。

```/pages/about.js
function About(){
    return(
        <div>
            <h1>About</h1>
        </div>
    )
}
export default About
```

# ナビゲーションバーの作成
ここまで作成したふたつのページ間を遷移できるようにナビゲーションを作成します。componentsディレクトリ配下にNavbar.jsを作成しreact component を記述します。
その際、クライアントサイドでの遷移はnext/linkからエクスポートされているLinkコンポーネントを使用します。

```/components/Navbar.js
import Link from "next/link";

const Navbar = () => {
  return (
    <ul>
      <li>
        <Link href="/">
          <a>Home</a>
        </Link>
      </li>
      <li>
        <Link href="/about">
          <a>About</a>
        </Link>
      </li>
    </ul>
  )
}

export default Navbar;
```

ナビゲーションバーを各ページに表示させるには、pagesディレクトリ配下の各ファイルでNavbarコンポーネントを読み込み描画します。
※記述例はHomePageのみを記載しています。

```/pages/index.js
import Navbar from '../components/Navbar'

function HomePage() {
  return (
    <>
      <Navbar />
      <div>
        <h1>Welcome to Next.js</h1>
      </div>
    </>
  )
}
export default HomePage
```

ここまででNextjsによるふたつのページを遷移するアプリケーションが完成しました。

Homeページ(http://localhost:3000/)
![homepage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35213/fd0409cd-d522-8590-9dd2-4892138d9c4e.png)

Aboutページ(http://localhost:3000/about)
![about.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35213/b44e4754-b753-5609-5004-8609272e7d2e.png)
自己署名証明書の作成

## 概要
自己署名証明書の作成方法のメモ。
細かいところを省略すると、フローは以下の通り。

1. 秘密鍵作成
1. csr作成
1. csrに署名

RHEL7まではmakeを使っていたが
使えなくなったので、メモ。

## 事前準備事項
事前に以下パラメータは整理しておいた方がいい。

1. 秘密鍵パスワード
1. Country Name
1. Locality Name
1. Organization Name
1. Organization UnitName
1. Common Name
1. E-mail

特に「Common Name」は真正性にも影響が出るのである程度はちゃんと考えた方がいい。
※自己署名なんでどうでもいい感はあるが、、、

## 手順
### 変数整理
```cmd
# KEY=server.key
# CSR=server.csr
# CRT=server.crt
# PFX=server.pfx
# DER=server.der
```

### 秘密鍵作成
```cmd
# cd /etc/pki/tls/certs
# /usr/bin/openssl genrsa -aes128 2048 > ${KEY}
Generating RSA private key, 2048 bit long modulus (2 primes)
.............................................................+++++
............................................................................................................+++++
e is 65537 (0x010001)
Enter pass phrase:
aborted!
140003687208768:error:0906906F:PEM routines:PEM_ASN1_write_bio:read key:crypto/pem/pem_lib.c:357:
[root@rhel8 19:46:34 certs]# /usr/bin/openssl genrsa -aes128 2048 > ${KEY}
Generating RSA private key, 2048 bit long modulus (2 primes)
...........+++++
.............................................................................+++++
e is 65537 (0x010001)
Enter pass phrase:
Verifying - Enter pass phrase:
```

### 秘密鍵のパスワード削除
```cmd
# openssl rsa -in ${KEY} -out ${KEY}
Enter pass phrase for server.key:
writing RSA key
```

### csr作成
```cmd
# /usr/bin/openssl req -utf8 -new -key ${KEY} -out ${CSR}
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
```

### csrに署名
```
# openssl x509 -in ${CSR} -out ${CRT} -req -signkey ${KEY} -days 10950
Signature ok
subject=C = XX, L = Default City, O = Default Company Ltd
Getting Private key
```

## 形式変換おまけ
### pkcs12
```cmd
# openssl pkcs12 -export -name apiicert -in ${CRT} -inkey ${KEY} -out ${PFX}
Enter Export Password:
Verifying - Enter Export Password:
```

### DER
```cmd
# openssl x509 -outform der -in ${CRT} -out ${DER}
```
L2SWのVLAN機能を使って家の無線LANの置き場所を自由にする

#やりたいこと
家の無線LANルーターを好きな場所に置きたい。
我が家のインターネット回線はマンションのLAN経由なのでつなげば動くので便利なのですが外部、各部屋へのケーブルが玄関のシューズボックスにあるため熱もこもるし、無線LANの電波上も不利なので好きな場所に置きたいためいろいろ考えた結果がこの記事になります。
PPPoEとか使っている方も同じようにしてできると思います。

#必要なもの
HUB(VLAN(802.11Q)対応のもの)が2台

#以前の構成
以下の通り玄関横のシューズボックス上部にケーブルと無線LANルーター、HUBを押し込んでいたので　夏場の熱が不安になったのと肝心のリビングで無線LANが弱くなるという欠点があり何とかしたいと思っていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361560/2ed62215-578a-4199-e7f3-54661ef78e82.png)

#完成図
詳細、具体的な設定はこの後説明しますがVLANを活用して以下の構成を行うことで無線LANルーターを自由な場所に設置することができるようになりました。
詳細をかいつまんで言うとVLANという機能を活用することで１つのHUBの中で別々のHUBとして扱う機能になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361560/bbd3d5b9-39ed-2fe1-118b-6c60b1ea41e3.png)

上の図をVLANごとに整理したのが以下の図になります。よくあるWAN側はInternet接続、LAN側はHUBにつないでいる形式になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361560/267b9ed8-b29c-956e-a5d7-4963da767dad.png)

#具体的設定方法
ここでは家で利用している [NETGEAR GS308T](https://store.netgear.jp/products/detail/66)を利用して説明しますが
TP-LINKでもNETGEARのほかの機種でもVLAN（802.11Q）対応と書いているやつなら基本出来るかと思います。

L2SW管理メニューに入ってVLANを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361560/18a691e1-7166-21c5-f01a-b456ce262118.png)

###VLAN IDの定義画面があるのでそちらから必要なVLAN IDを追加

VLANに必要なIDを設定します。
今回 LAN側はデフォルトの1を利用するため　WAN側として100のみ追加します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361560/28fd8591-2369-0caa-63b7-19c360446865.png)

###VLANメンバーシップ設定から VLAN定義を行います。

上図のHUB#1の場合

VLAN 1(LAN側） として以下を設定

+ Port 1 は T（Trunk)を設定　（簡略化して言うとVLAN1通信を行うHUB間の設定）
+ Port 2/3は U(Untag)を設定 （簡略化して言うと　PC、無線LANルーター等VLANを意識しない機器を接続する場合の設定）
+ Port 4 は設定なし

VLAN 100(WAN側)として以下を設定

+ Port 1 は T（Trunk)を設定
+ Port 2/3は設定なし
+ Port 4は U(Untag)を設定

HUB #2の場合
VLAN 1(LAN側） として以下を設定

+ Port 1 は T（Trunk)を設定
+ Port 2は設定なし
+ Port 3/4はU(Untag)を設定


VLAN 100(WAN側)として以下を設定

+ Port 1 は T（Trunk)を設定
+ Port 2は U(Untag)を設定
+ Port 3/4は設定なし

###NWを接続
無線LANルーター等NW接続をすればいけるようになるはずです。
Jupyter Lab3でPythonのコーディング

# Jupyter Lab3でPythonのコーディング
## Jupyter lab3の起動
Anaconda promptを起動して、jupyter labと打つとJupyter Labがデフォルトのブラウザで立ち上がります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1769855/6af51220-12d7-1d3c-966c-081ce9b25c4d.png)

## 新規のNotebookを作る
上記の画面のpython3のアイコンか、File>New>Notebookで新規ノートブックが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1769855/0437ff39-5b49-6a83-2a3a-9b25ca4a217d.png)

## Pythonのコーディングをして実行
a = 2020, b = 2021, c = 2022　として a+b+cを実行。RunボタンまたはCtrl+Enterを押せば実行できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1769855/58de4802-2470-1e59-87c8-e99077ea1fa1.png)

## packageのimport
numpyとpandasとmatplotlibをインポートしてみます。
import *PACKAGE* as *USENAME*
という形式で記述します。asは英語の「～として」インポートするよ、という意味なので、同一Notebook内で、「import numpy as np」はnumpyをnpという名前で使うよ、という意味になります。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1769855/b4ec11bb-c7ee-bdc9-4c47-1b4d088dccd9.png)
Linuxで7zipを使うときのメモ


## 概要

当初は Linux にデフォルトで 7zip コマンドが存在しないことが多いので嫌っていた.
しかし、使い始めると高速なので重宝している.

ただし、コマンドオプションを暗記できず、そのたびに Web を探し回ることが多々あったので書き残す.


## インストール

Ubuntu だと以下でインストールした.
コマンド名は「7z」である. なお、CentOS だと「7za」になっていて、やや困惑した.

```
$ sudo apt install -y p7zip-full
```

## 圧縮

`-mx` を使う

### 無圧縮

```
$ 7z a -mx=0 output.7z dir/
```

### 強圧縮

```
$ 7z a -mx=9 output.7z dir/
```


## パスワードあり

`-p` を使う

### 圧縮

```
$ 7z a -ppass output.7z dir/
```

### 展開

```
$ 7z x -ppass output.7z
```

## 備考

7zip コマンドのバージョン新旧によってエラー有無が生じることもあるので、やや注意が必要.

　

## 参考サイト

|URL|
|:--|
|https://www.howtoforge.com/tutorial/understanding-7z-command-switches/|
アンカラソコンサルティング

アンカラソサービス
私たちは、アンカラ地域専用のマホールアンカラにあるオフィスでseoコンサルティングサービスを提供しています。私たちはプロのseoチーム、グラフィックチーム、ソフトウェアチームと協力しています。

SEOは何をしますか？
ソ、特にグーグル検索エンジン。これは、検索ボリュームを拡大し、ブランド認知度を高め、BingやYandexなどの多くの検索エンジンでの認知度を高めるために必要な実用的な戦略です。

Seoのメリットは何ですか？
私たちがSEOに取り組み始めると、ソーシャルメディアアカウントでウェブサイトのコンテンツを記事の調査、バックリンク、ブックマークの調査と定期的に共有する機会があります。したがって、あなたの人気はグーグルや他の検索エンジンを含めて増加し始めています。

アンカラソ料金はいくらですか？
アンカラでは、seoの料金は、リクエスト、単語の量、競合他社の密度に応じて、平均で2500〜5000 TLの間で変動し、難易度に応じて計画されます。

https://www.nanomedya.com.tr
並列処理〜応用情報技術者試験に向けて〜

#並列処理

CPUの性能向上には様々なアプローチがあるが、単独のCPU内で果たすことのできる性能向上には限界がある。
複数のCPUを強調させて動作を行う**並列処理**が重要である。
このようにコンピューターシステム上に複数のCPUを搭載するのを**マルチプロセッサシステム**という

* 対称型マルチプロセッサ（SMP：Symmertrical MUltiple Processor）
全てのプロセッサを同等に扱って処理を並列化する方法
* 非対称型マルチプロセッサ（AMP：Asymmertical Multiple Processor）
それぞれのプロセッサに対して処理を分散させる方式

##マルチコアプロセッサ
ひとつのCPUパッケージ内に複数のコア（CPUの中核で実際に処理を実行するところ）を持たせたもの
近年では広く用いられている

##フリンの分類

|名前|正式名称|説明|
|:--:|:--:|:--:|
|SSID|Single Instruction stream/Single Date stream|１つの命令で１つのデータを処理する|
|SIMD|Single Instruction stream/Multiple Date stream|１つの命令で複数のデータを処理する。グラフィック処理用のプロセッシングユニットであるGPUの多くはこの方式|
|MISD|Multiple Instruction stream/Single Date stream|複数の命令で１つのデータを処理する|
|MIMD|Multiple Instruction stream/Multiple Date stream|複数の命令で複数のデータを処理する。マルチプロセッサを採用する一般的なコンピューターはこの方式である|

##マルチプロセッサと主記憶装置の関係
複数のCPUが協同動作を行うにあたり、主記憶装置との関係は重要な問題。

###密結合マルチプロセッサ
複数のプロセッサが主記憶装置を共有し、それを単一のOSが制御する方式である。
共有した主記憶装置へのアクセスが競合した結果、処理効率が低下する。

###疎結合マルチプロセッサ
複数のプロセッサに対して独立した主記憶装置を割り当てる方式である。
各プロセッサ毎にOSが必要となる。

##アムダールの法則
プロセッサの数を増やしても単純にシステムは高速化しない
複数のプロセッサを用いてどれほど高速化できるのか理論上の限界値を求める公式がアムダールの方式という
AWS CLI 「You can also configure your 〇〇 by running "aws configure".」エラー対処方法

#エラー発生
AWS CLI上で下記のエラーが発生。

```
aws kms create-key
You must specify a region. You can also configure your region by running "aws configure".
(リージョンを指定しなければいけません。"aws configure"を実行することで、リージョンを設定することができます。)
```

上記エラー内容をググると、下記の記事発見。
[AWSクライアントでリージョン(region)を指定する](https://salumarine.com/specifying-region-using-aws-client/)
リージョンを指定してみるが、下記のエラーが発生。。

```
aws kms create-key --region us-east-1
Unable to locate credentials. You can configure credentials by running "aws configure".
(認証情報が見つかりません。"aws configure"を実行することで、認証情報を設定することができます。)
```

#解決方法
`aws configure`の設定をすることで解決できます。

[AWS-CLIの初期設定のメモ](https://qiita.com/reflet/items/e4225435fe692663b705)の記事のaws-cliの設定を参考にしました。

```
$ aws configure --profile user1
AWS Access Key ID [None]: {アクセスキー(各自)}
AWS Secret Access Key [None]: {シークレットアクセスキー(各自)}
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

AWS Access Key IDとAWS Secret Access KeyはIAMの該当ユーザー>認証情報>アクセスキーから確認可能です。

参照:https://github.com/aws/aws-cli/issues/915
OpenFOAM 9 チュートリアルケースの動作確認 : 非圧縮性流体、icoFoam、ミキシングエルボー

# ケース
$FOAM_TUTORIALS/incompressible/icoFoam/elbow
# 概要
底部左側 (velocity-inlet-5) より Ux = 1 m/s、底部右側 (velocity-inlet-6) より Uy = 3 m/s で流入し、上部右側 (pressure-outlet-7) より流出します。流れは（乱流モデルを使用しないことから）層流と仮定され、層流、等温、非圧縮性流れ用の _icoFoam_ ソルバを使用して、メッシュ上で解かれます。
# 解析モデル
解析モデルを下図に示します。
![figModel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/194bf78c-008f-87d8-45e4-8e37fb3d7258.png)
# 解析条件
解析条件を下表に示します。

|項目1|項目2|項目3|単位|設定内容|
|---|---|---|:-:|:-:|
|_system_|_controlDict_|開始時刻|sec|0|
|   |   |終了時刻|sec|10|
|   |   |$\Delta$ _t_|sec|0.05|
|_constant_|_transportProperties_|動粘性係数 $\nu$|m2/s|0.01|
# 解析結果
計算終了時 (10 sec) の圧力分布を下図に示します。
![figPressure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/44b0fa95-75bb-d3c5-c3ad-055abae140c5.png)
計算終了時 (10 sec) の流速分布を下図に示します。
![figVelocity.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/8812e237-c958-b38d-60fc-1006e91d444e.png)
# 実行コマンド
前処理 (Pre-processing)
`run`
`cp -r $FOAM_TUTORIALS/incompressible/icoFoam/elbow .`
`cd elbow`
メッシュ作成・アプリケーションの実行
`./Allrun`
後処理 (Post-processing)
`paraFoam`
# 計算時間
0.46 (sec), シングル, AMD Ryzen 7 3750H with Radeon Vega Mobile Gfx
# 参照
- [XSim](https://www.xsim.info/articles/OpenFOAM/tutorials/incompressible-icoFoam-elbow.html)
GolangでFirebaseのFirestore Databaseを使う

# はじめに

FirebaseのFirestore Databaseに、GolangのSDKを用いて接続したい。

[公式Doc](https://firebase.google.com/docs/firestore/quickstart?hl=ja)を参考にFirestoreへの接続を試みたところ、以下のように「ファイルが見つからない」と怒られたので、その解決策を備忘録として残す。

```
Init Firestore failed. err=cannot read credentials file: open ./firebase-adminsdk-key.json: no such file or directory"
```

ちなみに、解決方法をググると、GOPATHまわりを良い感じに変更する方法がたくさん出てくるが、よくわからなかったので、本記事では別の方法を採用している。
（一応、記事後半に採用理由も記載済み）

# 失敗パターン

プログラム自体は概ねこれで問題ない

```golang
// このpackageはあくまで筆者の環境
package infrastructure

import (
    "context"

    "github.com/labstack/gommon/log"

    firebase "firebase.google.com/go"
    "google.golang.org/api/option"
)

func NewFirestoreHandler() error {
    ctx := context.Background()

    // 今回の問題点はここ
    sa := option.WithCredentialsFile("./firebase-adminsdk-key.json")

    // ProjectIDには自分のFirebaseプロジェクトIDを入れる
    conf := &firebase.Config{
        ProjectID: "hogehoge",
    }

    app, err := firebase.NewApp(ctx, conf, sa)
    if err != nil {
        log.Errorf("Firebase NewApp failed. err=%+v", err)
        return err
    }

    client, err := app.Firestore(ctx)
    if err != nil {
        log.Errorf("Init Firestore failed. err=%+v", err)
        return err
    }

    defer client.Close()

    // ここから動作確認用のレコードINSERT処理なので、必須ではない
    _, _, err = client.Collection("users").Add(ctx, map[string]interface{}{
        "first": "Ada",
        "last": "Lovelace",
        "born": 1815,
    })
    if err != nil {
        log.Errorf("Add failed. err=%+v", err)
        return err
    }
    // ここまで

    return nil
}
```

これで実行すると、下記の通り「ファイルが見つからない」と怒られる

```
Init Firestore failed. err=cannot read credentials file: open ./firebase-adminsdk-key.json: no such file or directory"
```

# 成功パターン

ファイルが読み込めないならば読み込まなければ良いのでは？
ということで、JSONをベタ書きする案でいけた

```golang
// JSONファイル読み込み案を不採用
// sa := option.WithCredentialsFile("./firebase-adminsdk-key.json")

// JSONをベタ書きする案を採用
tmpJson := []byte(`{"type": "hogehoge", "project_id": ...}`)
sa := option.WithCredentialsJSON(tmpJson)
```

念のため、JSONベタ書き案を採用する場合は、しっかりと中身を環境変数で管理するなどしてGit管理下に含めないようお気をつけを…

# おわりに

JSONベタ書きする案ならば、SDKの秘密鍵を環境変数などで管理することができるので、JSONファイルを読み込む方法よりも何かと便利かと。

例：JSONファイル使う方法の場合だと、認証情報の入ったJSONファイルはGit管理できないのでHerokuにデプロイするときに少し手を加える必要が出てくるが、今回の方法ならば環境変数に設定すれば終わり

# 参考
- [Cloud Firestore を使ってみる  |  Firebase](https://firebase.google.com/docs/firestore/quickstart?hl=ja)
    - 公式Doc
- [go - Build golang including firebase credential file .json - Stack Overflow](https://stackoverflow.com/questions/51444273/build-golang-including-firebase-credential-file-json)
    - 解決方法を知るにあたり、この記事が大いに参考になった
- [【第3回】Go言語（Golang）入門～Firestoreデータ操作編～ – 株式会社ライトコード](https://rightcode.co.jp/blog/information-technology/golang-introduction-firestore-data-manipulator)
    - 画像も載っていて、Firestoreへの接続方法の基本的なやり方はここも参考になった（ファイル読み込む方法を採用している記事）
Z3Py　例題　コイン問題２

# 問題
以下のユーロ硬貨を持っているとする(総和は148セントになる)。
20セント硬貨 4枚
10セント硬貨 4枚
5セント硬貨 4枚
2セント硬貨 4枚
合計がちょうど93セントになる組合せはあるだろうか?
各3枚の場合はどうか？

# 回答
```example_coin2.py
from z3 import *

coin__2cent = Int("coin__2cent")
coin__5cent = Int("coin__5cent")
coin_10cent = Int("coin_10cent")
coin_20cent = Int("coin_20cent")

s = Solver()
s.add(And(0 <= coin__2cent, coin__2cent <= 4))
s.add(And(0 <= coin__5cent, coin__5cent <= 4))
s.add(And(0 <= coin_10cent, coin_10cent <= 4))
s.add(And(0 <= coin_20cent, coin_20cent <= 4))
s.add(2*coin__2cent + 5*coin__5cent + 10*coin_10cent + 20*coin_20cent == 93)

print(s.check())
if s.check() == sat:
    print(s.model())

s = Solver()
s.add(And(0 <= coin__2cent, coin__2cent <= 3))
s.add(And(0 <= coin__5cent, coin__5cent <= 3))
s.add(And(0 <= coin_10cent, coin_10cent <= 3))
s.add(And(0 <= coin_20cent, coin_20cent <= 3))
s.add(2*coin__2cent + 5*coin__5cent + 10*coin_10cent + 20*coin_20cent == 93)

print(s.check())
if s.check() == sat:
    print(s.model())

```
出力

```terminal
sat
[coin__2cent = 4,
 coin__5cent = 1,
 coin_10cent = 0,
 coin_20cent = 4]
unsat
```
4枚の場合は解があるが、3枚の場合は解がないことが分かる。

## 解説
`And()`は、And条件を生成します。
そもそも、条件の追加（`.add()`）はAnd条件として追加されているので、
`s.add(0 <= coin_20cent, coin_20cent <= 4)`も同じ。（今回の例では、必要なかったということ）
[And()の詳細](http://z3prover.github.io/api/html/namespacez3py.html#a0d14fcc08b1daf608f3213b22c86a43d)
`or()`もある。
[Or()の詳細](http://z3prover.github.io/api/html/namespacez3py.html#a23922fcd80aa933a6f2aa176168e6d37)

# 他の例題
[Z3Py個人的ポータル](https://qiita.com/Ganesha/items/7a606ffc8a7c2504c143) へ
Rails5.2から6.1に更新する際に躓いたところ（zeitwerk)

# Rails5.2から6.1に更新する
* bulk insertを使いたかった。
* gem単体でも入れられるらしいけど、まあついでに。

## 6.xからはオートロード（requireしなくてもクラス参照できるアレ)の仕組みが刷新されている = zeitwerk

### さっとさらった概要
以前は下記参照ルールだったらしい。
`使われている定数の名前 -> 定義しているファイル名の特定`

新しいオートロードでは以下参照ルール。
`定義しているファイル名の特定 -> 使われている定数の名前`

### 今まで参照できていた、Concernsに入れてるクラスが参照できなくなった？？？(本題)

```ruby:controller/concerns/gas_api_callable.rb
# GAS APIコールする共通モジュール
module GasAPICallable
  extend ActiveSupport::Concern
  ### code ####
  end
end
```

```ruby:controller/concerns/gas_controller.rb
# GasAPICallableを使って色々するコントローラー
class GasController < ApplicationController
  include GasAPICallable
  ### code ###
end
```

------> uninitialized constants "GasAPICallable" エラー発生。

### ファイル名のCapitalize(大文字化)から定数名を探すことで、「API」というアクロニム(略称)がひろえなくなっているみたい。（根本原因）

`gas_api_callable.rb -> GasApiCallable       ----> GasAPICallableはあるけど、GasApiCallableはないよ？？？？ -> const未定義エラー`

### 対処1 アクロニムをやめる(大文字略称をやめる)

```ruby:controller/concerns/gas_api_callable.rb
# GAS APIコールする共通モジュール
- module GasAPICallable
+ module GasApiCallable
  extend ActiveSupport::Concern
  ### code ####
  end
end
```

```ruby:controller/concerns/gas_controller.rb
# GasAPICallableを使って色々するコントローラー
class GasController < ApplicationController
  - include GasAPICallable
  + include GasApiCallable
  ### code ###
end
```

参照できた。

### 対処2 アクロニムをzeitwerkに伝える。
```ruby:config/initializeers/zeitwerk.rb
ActiveSupport::Inflector.inflections(:en) do |inflect|
   inflect.acronym "API"
end
```

※ただしこの場合すべての`API`という単語を`API`として定義しなければならない(`Api`は探索できない)

https://railsguides.jp/autoloading_and_reloading_constants.html

https://github.com/fxn/zeitwerk#file-structure

### 参考

https://qiita.com/fursich/items/717a720d9f4465e4cbbb#b%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%90%8D%E3%81%A8%E7%95%B0%E3%81%AA%E3%82%8B%E5%AE%9A%E6%95%B0%E5%90%8D%E3%82%92%E4%BD%BF%E3%81%84%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88
Rails6 Bootstrap 導入 (docker)

#Rails6 Bootstrap 導入 (docker)

いくつかの記事を渡り歩かなきゃいけなくて時間かかったのでまとめておく
(Rails6からはjavascriptsフォルダが作られず、webpackが標準になったことでディレクトリ構造がRails6以前と違い、混乱した)

```
Rails 6.1.4
ruby 2.6.8p205 (2021-07-07 revision 67951) [x86_64-linux]
Docker version 20.10.5, build 55c4c88
```

##①
`app/javascript/src/application.scss` 作成

```app/javascript/src/application.scss
@import '~bootstrap/scss/bootstrap'; //追加
```

##②
```app/javascript/packs/application.js
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
//追加（ここから）---------------------
import "jquery"
import "bootstrap"
import "../src/application"
//追加(ここまで)---------------------
Rails.start()
Turbolinks.start()
ActiveStorage.start()

```

##③
```config/webpack/environment.js
const { environment } = require('@rails/webpacker')
//追加（ここから）---------------------
const webpack = require('webpack')
environment.plugins.prepend('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery/src/jquery',
    jQuery: 'jquery/src/jquery'
  })
)
//追加(ここまで)---------------------
module.exports = environment

```

---
###ファイルの作成と修正は　これで完了
---

`docker-compose run --rm web bash`　実行

`yarn add jquery bootstrap popper.js @popperjs/core` 実行

これでdockerコンテナ再起動すればいける
AWS上にサーバーを作る（その03：VPCウィザードによるAmazon VPCの設定）

前回の投稿
[AWS上にサーバーを作る（その02）](https://qiita.com/aa_ha1uhik0/items/c92d4f7d3b31a361a3b2 "AWS上にサーバーを作る（その02）")

# Amazon VPCの設定

さて、だいぶ期間が開いてしまいましたが、前回はネットワーク周りの名称と内容の確認までは終わっていたと思います。
ここからは、ようやく初めてAWSのネットワークの設定に入ります。

まずは「ルートユーザー」または「IAMユーザー」でログインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520646/be40585e-5f1b-9823-fdb5-ef306cfd03d9.png)


## Amazon VPCの作成

前回調べた通り、「VPCの作成」自体は無料のようですので、早速作成を開始しちゃいます。

### 1.VPCウィザードを起動
今回、VPCの作成には、初心者でも簡単に作成できそうな「VPCウィザード」を使ってみる。
サービス一覧からVPCへ進むと、「VPCウィザードを起動」ボタンが設置されています。
サービス > VPC > [VPCダッシュボード](https://ap-northeast-1.console.aws.amazon.com/vpc/home?region=ap-northeast-1)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520646/e19791dc-59c7-c85b-b47a-9ed4a5501aae.png)

#### ステップ 1: VPC 設定の選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520646/83908438-9b59-f726-f8ff-ea7d35630422.png)
今回は外部へサーバーを公開しない想定ですが、
「プライベートのサブネットのみで、ハードウェア VPN アクセスを持つ VPC」
を選択してセキュアなネットワークを構築する、または
「1 個のパブリックサブネットを持つ VPC」
を選択してセキュリティグループで接続元IPアドレスを限定する方法、どちらでもよいと思います。
前者はそもそも外部に通信をさらされないため安全ですが、拠点間VPN接続は別途金額がかかってしまうようですので、今回はケチって後者を採用しました。

#### ステップ 2: 1 個のパブリックサブネットを持つ VPC
IPアドレスなどを指定していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520646/0bb03d6f-e451-2a6a-61ad-4afc85a1193b.png)
「アベイラビリティーゾーン」の項目ですが、簡単に説明するとどこのデータセンターに仮想マシンを設置するかということのようです。
現在、AWSのアジアパシフィック東京リージョンは、

+ ap-northeast-1a
+ ap-northeast-1c
+ ap-northeast-1d

の３か所が公開されていて、このうちのどこに仮想マシンを設置するかを指定します。
今後、冗長化を考える際はアベイラビリティーゾーンの1aと1dのような感じで別の場所にプライマリー、セカンダリーサーバーの設置場所を指定すると良さそうです。
それ以外は、デフォルトで進めてしまいましょう。

## 完成
たったこれだけの操作で、サブネット、ルートテーブル、インターネットゲートウェイなどと一緒に、VPCが作成されます。

# 次回の内容
そろそろ仮想マシン作成できる？？
（まだ引っ張る）

To be continued...
OpenFOAM 9 チュートリアルケースの動作確認 : 非圧縮性流体、icoFoam、天井駆動のキャビティ流れ（ケース形状の変更）

# ケース
$FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavityClipped
# 概要
天井駆動のキャビティ流れ (cavity) を、底部右側、長さ 0.04 m の正方形を除いたメッシュで計算します。元となる cavity で movingWall であった天井壁は、lid という名前に変更されていますが、データマッピングを行うことができます。 
# 解析モデル
解析モデルを下図に示します。
![figModel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/4f0d68f8-1571-8413-bb83-556bec166133.png)
# 解析条件
解析条件を下表に示します。

|項目1|項目2|項目3|単位|設定内容|
|---|---|---|:-:|:-:|
|_system_|_blockMeshDict_|解析モデルサイズ _x_|m|0.1|
|   |   |解析モデルサイズ _y_|m|0.1|
|   |   |解析モデル分割数 _nx_|-|20|
|   |   |解析モデル分割数 _ny_|-|20|
|   |_controlDict_|開始時刻|sec|0.5|
|   |   |終了時刻|sec|0.6|
|   |   |$\Delta$ _t_|sec|0.0025|
|_constant_|_transportProperties_|動粘性係数 $\nu$|m2/s|0.01|

# 解析結果
計算開始時 (0.5 sec, データマッピング時) の速度ベクトルプロットを下図に示します。
![figGlyphMapped.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/096ba18c-53c0-6883-e54b-6a29f0d58353.png)
計算終了時 (0.6 sec) の速度ベクトルプロットを下図に示します。
![figGlyphEnd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/8c574d66-064b-6b4b-8c95-683c38972595.png)
# 実行コマンド
前処理 (Pre-processing)
`run`
`cp -r $FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavityClipped .`
`cd cavityClipped`
メッシュ作成
`blockMesh`
データマッピング
`cp -r 0 0.5`
`mapFields ../cavity`
アプリケーションの実行
`icoFoam`
後処理 (Post-processing)
`paraFoam`
# 計算時間
0.02 (sec), シングル, AMD Ryzen 7 3750H with Radeon Vega Mobile Gfx
# 参照
- [OpenFOAM v9 User Guide: 2.1 Lid-driven cavity flow](https://cfd.direct/openfoam/user-guide/v9-cavity/)
- [XSim](https://www.xsim.info/articles/OpenFOAM/tutorials/incompressible-icoFoam-cavity-cavityClipped.html)
SES開発エンジニア業務とVBAデバックで学んだ点

###SES開発エンジニアの案件の現状
基本的に一人で常駐してプログラムの全てを解決します。現場では、先方も仕様について深く理解していないことがほとんどです。分からない箇所は、自分で検索して調べていきます。

###仕様を理解していない人へのアウトプット
開発SESでは、コードが分からない人に如何に分かりやすく伝えるか、ということも考えてアウトプットする能力も必要です。私は、今まで仕様を理解している人にしかアウトプットをしていなかったので、初めての現場で「コードがこうなっていて・・」と伝えても先方は理解できないということを知りました。

###VBAデバック業務
エラー事象を確認した後、エラーが起きているコードをステップインで実行して特定します。その後、修正内容を自分で考えてそれを記述します。

###苦戦したエラー
実行時エラー424 オブジェクトが必要です。
実行時エラー91 オブジェクト変数またはwithブロック変数が設定されていません。

###苦戦したエラーの解決方法
上記のエラーでRowが選択された状態になっていたので、自分で追記したSearchDirection:=xlPreviousとRowを同じ行で扱えないということに気づきました。

###デバックについて
開発言語どれか一つでもデバックができるようになると他言語でもデバックできるようになります。
OpenFOAM 9 チュートリアルケースの動作確認 : 非圧縮性流体、icoFoam、天井駆動のキャビティ流れ（勾配メッシュ）

# ケース
$FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavityGrade
# 概要
天井駆動のキャビティ流れを、壁に向かって勾配を付けた 20×20 セルのメッシュで計算します。詳細メッシュ (cavityFine) での計算結果を初期条件として、勾配付けされたメッシュに適用します。
# 解析モデル
解析モデルを下図に示します。
![figModel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/fcc5ea85-c885-5393-296b-4f7ad3a5ec0c.png)
# 解析条件
解析条件を下表に示します。

|項目1|項目2|項目3|単位|設定内容|
|---|---|---|:-:|:-:|
|_system_|_blockMeshDict_|解析モデルサイズ _x_|m|0.1|
|   |   |解析モデルサイズ _y_|m|0.1|
|   |   |解析モデル分割数 _nx_|-|20|
|   |   |解析モデル分割数 _ny_|-|20|
|   |_controlDict_|開始時刻|sec|0.7|
|   |   |終了時刻|sec|0.8|
|   |   |$\Delta$ _t_|sec|0.005|
|_constant_|_transportProperties_|動粘性係数 $\nu$|m2/s|0.01|

# 解析結果
計算終了時 (0.8 sec) の圧力分布を下図に示します。
![figPressure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/a1ae0c8e-f38f-e590-aa37-d5ab0cfbef05.png)
計算終了時 (0.8 sec) の速度ベクトルプロットを下図に示します。
![figGlyph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/956037d6-149f-7067-9ac5-c95621ff07bb.png)
計算終了時 (0.8 sec) の流線を下図に示します。
![figStreamLine.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/eac8e4b7-20cb-a75c-6ab3-dae9825cab49.png)
# 実行コマンド
前処理 (Pre-processing)
`run`
`cp -r $FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavityGrade .`
`cd cavityGrade`
メッシュ作成
`blockMesh`
データマッピング
`mapFields ../cavityFine -consistent`
アプリケーションの実行
`icoFoam`
後処理 (Post-processing)
`paraFoam`
# 計算時間
0.03 (sec), シングル, AMD Ryzen 7 3750H with Radeon Vega Mobile Gfx
# 参照
- [OpenFOAM v9 User Guide: 2.1 Lid-driven cavity flow](https://cfd.direct/openfoam/user-guide/v9-cavity/)
- [XSim](https://www.xsim.info/articles/OpenFOAM/tutorials/incompressible-icoFoam-cavity-cavityGrade.html)
Python>pandas>DataFrame:指定行の抽出

# <a id ="1">1.概要</a>
初心者の自分はDataFrameでの行の抽出を練習するときにちょくちょく混乱。。。
今後の混乱予防対策のために少し操作方法を整理。

# <a id="2">2.DataFrameの準備</a>
以下のDataFramewoを操作して行の抽出操作を確認する。

```python
import pandas as pd
import numpy as np

df = pd.DataFrame(np.arange(12).reshape(4,3),
                  index=['R1','R2', 'R3', 'R4'],
                  columns=['C1','C2', 'C3'])
```
|  |C1|C2|C3|
|--:|--:|--:|--:|
|R1|0|1|2|
|R2|3|4|5|
|R3|6|7|8|
|R4|9|10|11|

# <a id="3">3.ひとつの行を抽出
「R2」行のみの以下を抽出する操作を確認。

|  |C1|C2|C3|
|--:|--:|--:|--:|
|R2|3|4|5|

* `[ ]`で囲う操作

```python
df['R2':'R2']
```

* `.loc`・`.iloc`を使う操作

```python
df.loc[['R2']]
```

```python
df.iloc[[1]]
```

```python
pd.DataFrame(df.loc['R2']).T
```
 < memo >

`df.loc['R2']`だけだと出力はSeries型。

C1 &nbsp; &nbsp;  3
C2 &nbsp; &nbsp;  4
C3 &nbsp; &nbsp;  5
Name: R2, dtype: int32

→`pd.DataFrame()`で変換すると縦横逆。

|  |R2|
|--:|--:|
|C1|3|
|C2|4|
|C3|5|

→`.T`で転置すれば同じ形になった。


* `.drop`を使う操作

```python
df.drop(labels =['R1','R3','R4'],axis = 0)
```
```python
df.drop(labels =[R for R in df.index if R!='R2'],axis = 0)
```

* `True`/`False`を使う操作

```python
df[[False, True, False, False]]
```

1. 例えば以下で`[False,True,False,False]`をつくることが可能。

[input]`list(df['C1']==3)`
↓
[output]`[False,True,False,False]`
なので以下でも「R2」行のみのDataFrameを抽出できる

```python
df[list(df['C1']==3)]
```

2. `list()`でくくらない場合は出力はSeries型。これを使っても「R2」行のみのDataFrameを抽出できる

[input]`list(df['C1']==3)`
↓
[output]
`R1    False
R2     True
R3    False
R4    False
Name: C1, dtype: bool `

```python
df[list(df['C1']==3)]
```



* df (再掲) 

|  |C1|C2|C3|
|--:|--:|--:|--:|
|R1|0|1|2|
|R2|3|4|5|
|R3|6|7|8|
|R4|9|10|11|








# <a id="4">4.ふたつの行を抽出
「R2」「R3」行を抽出して４以下を得る操作を確認。

|  |C1|C2|C3|
|--:|--:|--:|--:|
|R2|3|4|5|
|R3|6|7|8|

* `[ ]`で囲う操作

```python
df['R2':'R3']
```

* `.loc`・`.iloc`を使う操作

```python
df.loc[['R2','R3']]
```

```python
df.loc[1:2]
```
```python
df.iloc[[1,2]]
```

```python
df.iloc['R2':'R3']
```



* `.drop`を使う操作

```python
df.drop(labels =['R1','R4'],axis = 0)
```

```python
df.drop(labels =[R for R in df.index 
                 if  R!='R2' and R!='R3'],axis = 0)
```


* `True`/`False`を使う操作

```python
df[[False, True, True, False]]
```
`[ ]`の中が以下になるSeriesをつくればよい。

`R1    False
R2     True
R3     True
R4    False
Name: C1, dtype: bool`

例えば以下で上記Seriesが作れるので
* `(df['C1']==3) | (df['C1']==6)`
* `(df['C1']<9) & (df['C3']!=2)`

```python
df[(df['C1']==3) | (df['C1']==6)]
```

```python
df[(df['C1']<9) & (df['C3']!=2)]
```




* df (再掲) 

|  |C1|C2|C3|
|--:|--:|--:|--:|
|R1|0|1|2|
|R2|3|4|5|
|R3|6|7|8|
|R4|9|10|11|

以上
Z3Py　例題　コイン問題（制約充足問題）

# 問題
1円硬貨，5円硬貨，10円硬貨を合計で15枚，それぞれを1枚以上持っている． 
金額の合計は90円である． それぞれの硬貨を何枚持っているか?

# 回答
```example01_coin.py
from z3 import *

coin__1yen = Int("coin__1yen")
coin__5yen = Int("coin__5yen")
coin_10yen = Int("coin_10yen")

s = Solver()
s.add(coin__1yen >= 1)
s.add(coin__5yen >= 1)
s.add(coin_10yen >= 1)
s.add((coin__1yen + coin__5yen + coin_10yen) == 15)
s.add((coin__1yen + 5 * coin__5yen + 10 * coin_10yen) == 90)

print(s.check())
if s.check() == sat:
    print(s.model())
```
出力

```terminal
sat
[coin__5yen = 3, coin_10yen = 7, coin__1yen = 5]
```

## 解説
【基本的な順序】
`Int()`等で変数を定義し、`s=Solver()`に`s.add()`で条件・制約を定義する。
`s.check()`で解があるかを確認する。（たぶん、ここで演算をしている）
解がある場合、「sat」が返ってき、解がない場合は「unsat」が返ってくる。
「sat」が返ってきた場合、`s.model()`で条件を満たす解の1つが取得できる。
（一つしか出てこないため、条件を満たす解が見つかった時点で探索を終了すると思われる）

# 他の例題
[Z3Py個人的ポータル](https://qiita.com/Ganesha/items/7a606ffc8a7c2504c143) へ
【1行野郎】できる限り速くファイルに列挙したデータをアーカイブにする


**何か良いアイデアがあれば、連絡いただけると有り難いです**

## 概要

次の調査をしたときの記録.　正確には一行野郎では無いですが..

次のようにアーカイブしたい対象を列挙した **input.txt** があり、
input.txt に列挙したデータ群を無圧縮でも良いので、できる限り速くアーカイブにしたい.

```
$ cat input.txt
./.bashrc
./.emacs.d/bookmarks
以下略
```

その他、条件は以下であった.
・input.txt に列挙したデータの個数は 20万個 ほどであった.
・input.txt に列挙したデータの総サイズは 20GB ほどであった.
・input.txt に記したデータ構造(ツリー)でアーカイブにする.
・スクリプトを作って並列化はさせたくは無い (∵ バグ混入を避けるため).


## 実行

以下、生成されるアーカイブ(約20GB) を `output.*` という形式にしている.
結果は以下であった.

```
## 下記だと 12分
$ cat input.txt | zip -0 -ry -@ output.zip &>/dev/null

## 下記だと 36分
$ tar cv -I pigz -f output.gz -T input.txt &>/dev/null
  
## 下記だと 40分経過しても終了せず
$ tar cv -f output.tar -T input.txt &>/dev/null
```

## 結論

・平凡そうに見える zip -0 -r が最も速くて意外だった
・データ数や総サイズなどの条件次第で結果は異なる気がする.


## 参考にしたサイト

|URL|
|:--|
|https://mickey-happygolucky.hatenablog.com/entry/2018/04/21/011811|
Preact はじめの一歩

## 参考

https://preactjs.com/guide/v10/getting-started#no-build-tools-route

https://www.codegrid.net/articles/2020-preact-1/

ビルドツールなしで利用できるっぽいが、公式のサンプルがJSX中心。

## サンプル

```html:index.html
<meta charset="UTF-8" />

<script type="module">
  import { h, render } from "https://unpkg.com/preact?module";

  const app = h(
    "div",
    null,
    ...[
        h("h2", null, "ハローワールド")
        , h("p", null, "テスト")
        ]
  );

  render(app, document.body);
</script>
```

* `h`は`createElement()`のエイリアス

## htm を使ってhtmlっぽく書く

* https://github.com/developit/htm

### サンプル1

```
<meta charset="UTF-8" />

<script type="module">
  import {
    html,
    render,
  } from "https://unpkg.com/htm/preact/standalone.module.js";

  const app = html`
    <div>
      <h2>タイトル</h2>
      <p>htmlを利用したサンプル</p>
    </div>
  `;
  render(app, document.body);
</script>
```


### サンプル2

```html:index.html
<meta charset="UTF-8" />
<script type="module">
    import { h, render } from "https://unpkg.com/preact?module";
    import htm from "https://unpkg.com/htm?module";
    const html = htm.bind(h);

  const app = html`
    <div>
      <h2>タイトル</h2>
      <p>htmを利用したサンプル</p>
    </div>
  `;

  render(app, document.body);
</script>
```
OpenFOAM 9 チュートリアルケースの動作確認 : 非圧縮性流体、icoFoam、天井駆動のキャビティ流れ（詳細メッシュ）

# ケース
$FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavity より派生
# 概要
本ケースは、チュートリアルケースである天井駆動のキャビティ流れ（20×20 セル）を、 OpenFOAM v9 User Guide: 2.1 Lid-driven cavity flow の記載に沿って、40×40 セルの詳細メッシュで計算するケースです。
# 解析モデル
解析モデルを下図に示します。
![figModel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/b6660b4d-3ce6-ae65-67af-14a815826fdf.png)
# 解析条件
解析条件を下表に示します。

|項目1|項目2|項目3|単位|設定内容|
|---|---|---|:-:|:-:|
|_system_|_blockMeshDict_|解析モデルサイズ _x_|m|0.1|
|   |   |解析モデルサイズ _y_|m|0.1|
|   |   |解析モデル分割数 _nx_|-|40|
|   |   |解析モデル分割数 _ny_|-|40|
|   |_controlDict_|開始時刻|sec|0.5|
|   |   |終了時刻|sec|0.7|
|   |   |$\Delta$ _t_|sec|0.0025|
|_constant_|_transportProperties_|動粘性係数 $\nu$|m2/s|0.01|

# 解析結果
計算終了時 (0.7 sec) の圧力分布を下図に示します。
![figPressure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/db07dff4-6830-42ed-3642-af52105261c4.png)
計算終了時 (0.7 sec) の速度ベクトルプロットを下図に示します。
![figGlyph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/3115872a-9592-b9b5-a858-1e181d4b70b1.png)
計算終了時 (0.7 sec) の流線を下図に示します。
![figStreamLine.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/097e58f8-2969-80ac-39ac-a866997fe3f6.png)

# 実行コマンド
前処理 (Pre-processing)
`run`
`mkdir cavityFine`
`cp -r cavity/constant cavityFine`
`cp -r cavity/system cavityFine`
`cd cavityFine`
メッシュ作成
`blockMesh`
データマッピング
`mapFields ../cavity -consistent`
アプリケーションの実行
`icoFoam`
後処理 (Post-processing)
`paraFoam`
# 計算時間
0.14 (sec), シングル, AMD Ryzen 7 3750H with Radeon Vega Mobile Gfx
# 参照
- [OpenFOAM v9 User Guide: 2.1 Lid-driven cavity flow](https://cfd.direct/openfoam/user-guide/v9-cavity/)
大規模&高頻度利用なLINE BotはGASではスケールできない可能性

GASでは簡単にLINE Messaging APIとともにLINE Botを構築できます。
しかし、自分で作ったLINE Botが大規模に利用されるにつれてある問題が発生しています。
**そもそも大規模なLINEBotをGASで運用する知見がそもそもネット上には共有されていません。**
そのため、この事象にたいしての知見を投稿して、警鐘を鳴らすこととしました。

# GASで対処できないLINEBot規模とはどのくらいか
あるLINE Botがプチバズり、**現在友達総追加数は2900名ほどになり、GASによれば3万回/週ほどwebhookがコール**されます。
時間帯にもよりますが、リアルタイムログだと10秒から1秒間の感覚でコールされたり、**頻度の高い時は1秒よりも短い間隔のうちに数回コール**されます。
このLINE Botは、**与えられたメッセージを解析して、一つのメッセージを返答するものであり、必ず返信が求められます。**
しかしながら、LINE側の管理画面では受信に対してwebhookは成功していることとなっていますが、その実行量はGASのログに対して20%ほどの乖離がありました。
**すなわち、20%のwebhookはGoogle Apps Script側で返信を取りこぼしている可能性が示唆されています。**また、エラー率は一定しているため、極めてランダムな自然言語の受信メッセージに20%ほどの一定のエラーを引き起こす要素が分布しているとも考えにくいです。

その仮説を元にGASログを見ると、確かに20%ものwebhookが何らかの理由により失敗していることがわかります。

## GASの実行ログの概要
![スクリーンショット 2021-07-24 17.10.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614389/e4f9250b-4e0c-0b65-e252-7cafed46e917.png)

さらに、GAS側で問題が起きていることの原因に対して「極めて短い間隔で連続してwebhookがコールされたためにエラーが発生しているのでは？」と仮説を立て、GASの実行ログを見ると以下の知見を得ました。

# 1秒よりも短いインターバルでの連続webhookが失敗することがある
![スクリーンショット 2021-07-24 17.08.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614389/476af629-b15e-9072-3a76-bb1691101932.png)

GASログを眺めると、エラー発生には
***1秒よりも短い、または同程度のインターバルでの連続webhookコールは失敗しやすい***
という知見が得られました。

なお、具体的なエラーログの中身は通常収集できません。
**これは、GASではwebhookでトリガーした処理はLogger.log()などで出力することはできない仕様になっているためです。**
今後GASにtry,catch分でエラー内容をSpreadsheetなどにリダイレクトして確認するなどもできますが、今回のような極めて短い間隔でwebhookがコールされる状況では、正常にSpreadsheet操作ができるかは疑わしいです。この点に関しては、また調査した結果をQiitaに投稿するつもりです。


# GASのLINE Botに運用するときのAvailabilityに関して
今回のLINE Botは入力に対して返信をする必要がある場合が多いため、高いavailabilityが求められます。
幸い、20%の増加するエラー率に対して、今のところはブロック数などの増加は見られませんが、長期的に見てサービスの品質にユーザーが不満を持つ可能性が大いにあります。

GASでは同時実行回数が30回までとありますが、webhookで今回のようなユースケースでは実用に耐えない場合がある可能性が示唆されました。この点に関してはまだ検証が必要ですが、**LINE Botの利用者の増加及び、利用頻度の増加に対応するには、Google CloudやAWSなどへの切り替えが必要なのかもしれません。**

大規模なLINE BotへのGASの利用に関する情報が不足しているため、何か知っている方がいましたらぜひコメントで知見を共有いただければ幸いです。
ここまでお読みいただきありがとうございました。😊
RDBのBOOLEAN型の3値論理について

# 記事の内容

リレーショナルデータベースのBOOLEAN型の3値論理について説明します。

# 説明

RDBのBOOLEAN型は、TRUE、FALSEに加えてNULLの状態にもなり得ます。
BOOLEAN型のNULLは、意味的には「TRUEかFALSEか分からない」なので、以下Unknownという値を導入します。
すなわち、RDBのBOOLEAN型はTRUE、FALSE、Unknownの3つの値を使った3値論理です。

今、customerテーブルに以下のデータが入っているとしましょう。
「三郎」の電話番号は不明なので、NULLにしてあります。

```

(customerテーブル)
 id    name      tel
-------------------------------
  1    '一郎'    '03-1111-1111'
  2    '次郎'    '03-2222-2222'
  3    '三郎'    NULL
  4    '史郎'    '03-4444-4444'
```

customerテーブルに対して、以下の SQL文を投げてやります。
検索結果はどうなるでしょうか？

```sql

SELECT *
FROM customer
WHERE tel != '03-1111-1111'
```

「三郎」の電話番号は、'03-1111-1111'かもしれないし、そうでないかもしれません。
従って、WHERE句の評価結果（3値論理）は以下のようになります。

```

 id    name      tel               WHERE句の評価結果
----------------------------------------------------
  1    '一郎'    '03-1111-1111'    FALSE
  2    '次郎'    '03-2222-2222'    TRUE
  3    '三郎'    NULL              Unknown
  4    '史郎'    '03-4444-4444'    TRUE
```

結果表に含まれるのは、WHERE句の評価結果がTRUEの行のみです。
従って上記のSQL文で検索されるのは、「次郎」と「史郎」の2件です

では、以下の SQL文ではどうでしょうか。

```sql

SELECT *
FROM customer
WHERE tel != '03-1111-1111'
   OR tel IS NULL
```

直感では「次郎」「三郎」「史郎」の3件が検索されそうです。
そして実際にそうなります。

では、このWHERE句が「三郎」の行に適用された場合について、厳密にみていきましょう。

「tel != '03-1111-1111'」の評価結果はUnknownです。
「tel IS NULL」の評価結果はTRUEです。
従って、三郎のデータでのWHERE句は「Unknown OR TRUE」となります。
ここから最終結果を得るのはやっかいですが、「UnknownをTRUEとFALSEで置き換える」という技があります。
その結果が両方TRUEであればTRUE、両方FALSEであればFALSE、それ以外はUnknownです。

実際に置き換えてみると、「TRUE OR TRUE」も「FALSE OR TRUE」もTRUEですから、両方TRUEということで最終結果はTRUEになり、「三郎」も検索されるということになります。

```

TRUE    AND Unknown → Unknown（TRUE AND TRUE → TRUE、TRUE AND FALSE → FALSE）

FALSE   AND Unknown → FALSE  （FALSE AND TRUE → FALSE、FALSE AND FALSE → FALSE。両方FALSE）

Unknown AND Unknown → Unknown

TRUE    OR  Unknown → TRUE   （TRUE OR TRUE → TRUE、TRUE OR FALSE → TRUE。両方TRUE）

FALSE   OR  Unknown → Unknown（FALSE OR TRUE → TRUE、FALSE OR FALSE → FALSE）

Unknown OR  Unknown → Unknown

NOT Unknown         → Unknown（NOT TRUE → FALSE、NOT FALSE → TRUE）
```

これらのことから得られる教訓があります。
それは、スキーマ定義の時「列はデフォルトでNOT NULL制約を付けよ」ということです。
NULLが絡むとSQL文が複雑になり、面倒です。
NULLを可にする理由がなければ、NOT NULL制約を付けるべきです。