OmniAICreator/Qiita-1.07M huggingface dataset:
【Python×API】ポケモンを検索するアプリ

# 初めに
どうやらポケモンのデータを取得することができるAPIが存在するらしい。。
得られるデータは「名前」「図鑑ID」「タイプ」「ポケモンの画像」など！

使い方は簡単で、以下のURLにIDを入れるだけです。
※名前で検索することも可能らしい。。

丁度PythonでWebAPIの呼び方を備忘録としてまとめようと
考えていたので、どうせなら面白そうな内容と考えこの記事を作成しました！

早速使ってみましょう！！！
### PokéAPI
https://pokeapi.co/

# 例
例えばイーブイ(No.133)を表示する際は、以下の通り指定する必要があります。

名前指定：https://pokeapi.co/api/v2/pokemon/eevee/
図鑑№指定：https://pokeapi.co/api/v2/pokemon/133/

「eecee」はポケモンの名前、「133」は図鑑IDになります。
上記のように指定すると、ポケモンの情報が取得できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/945342/910433a1-804f-6764-91b5-6d9bd21c9fab.png)
# ソースコード
```pokemon.py
import requests

url = "https://pokeapi.co/api/v2/pokemon/"

print('ポケモン図鑑番号を入れてください')
# 入力文字を取得
poke_id = input('>> ')

# バリデーションチェック
while True:
    # 範囲は1〜905 (2022/10現在)
    judge = 0 <= int(poke_id) < 906

    if not judge:
        # 存在しないIDを記述したら、再入力を求める
        print('存在しないポケモンIDを入力しています！再度入力してください。')
        poke_id = input('>> ')

    else:
        # 正しければループを抜ける
        break

# urlに図鑑IDを付与
url = url + poke_id

response = requests.get(url)
response = response.json()

# 名前
name = response['name']
# ID
id = response['id']
# ポケモン画像
image = response['sprites']['front_default']
# タイプ
types = response['types'][0]['type']['name']

print(id)
print(name)
print(image)
print(types)
```
:::note warn
警告
2022/10現在では、ポケモンの種類は905匹だそうです。
:::
# 出力結果
```
# 図鑑ID
133　
# 名前
eevee
# ポケモンのタイプ
normal
```
#### 画像も取得できます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/945342/8b664dd9-3e2a-3c00-c82f-e6fa7fea4c81.png)
# 最後に
実装自体は大した内容ではありませんが、APIにも面白いものがあるんだなー
と率直に感じました！

後日フロントの言語を使用して、ポケモン図鑑なるものを作成したいと
思います。。

取得できる情報は英語なので、少々違和感がありますが
皆様もポケモン図鑑の作成にチャレンジしてみてはいかがでしょうか？
フォールトアボイダンス とは

## 勉強前イメージ

アボイダンス・・・聞いたことある気もする。
アボイダンスって回避って意味らしい。

フォールトトレランスのお友達？

## 調査

### フォールトアボイダンス とは

英語でfault avoidanceと書く。
fault(=欠陥) avoidance(=回避) ということで欠陥を回避することを目的にしています。
問題の発生に対する考え方で、なるべく障害や故障を発生させないようにする考え方になります。

個々の部品や障害など発生自体がしないように品質や信頼性を高めようとする発想で
機械であれば信頼性の高いものを採用、
グループ全体であれば人員の教育や訓練などもフォールトアボイダンスに入ります。

### フォールトトレランスは関係ある？

フォールトトレランスの詳細は [こちら](https://qiita.com/miyuki_samitani/items/ee86e0b15b5a9cb238f4) にも詳細記載させていただいていますが
システムや機器の一部が故障・停止しても予備系統に切り替える等で正常に稼働させ続ける仕組みのことです。
要するに、 壊れても大丈夫なようにするという考え方 になります。

### フォールトアボイダンス と フォールトトレランスの違い

以下の違いがあります。

- フォールトアボイダンス : 壊れないように品質を高める考え方
- フォールトトレランス : 壊れても大丈夫なように冗長構成などをする考え方

どっちのほうがいいというわけではなく
どっちも採用することでより品質の高いサービスを提供できます。

## 勉強後イメージ

やっぱりお友達だった。
個人的にはフォールトトレランスの方がスキ

## 参考

- [フォールトアボイダンス 【fault avoidance】](https://e-words.jp/w/%E3%83%95%E3%82%A9%E3%83%BC%E3%83%AB%E3%83%88%E3%82%A2%E3%83%9C%E3%82%A4%E3%83%80%E3%83%B3%E3%82%B9.html)
- [フォールトトレラント、フォールトアボイダンス等の違いとは？(備忘録)](https://zenn.dev/supersatton/articles/3d56d1dfa10ddf)
PythonによるJWTの実装入門

# そもそもJWTとは？
・[【JWT】 入門](https://qiita.com/knaot0/items/8427918564400968bd2b)
この記事がわかりやすかったので参考までに

・API認証やアクセス制御などで用いられる規格の一つ。
・公開鍵暗号に基づくメッセージ認証コードにより改ざんやなりすましを防ぐ。
・JWT(JSON Web Token)でジョットと読む。

# JWTのストラクチャ
ヘッダー、ペイロード、署名(シグネチャ)の3つの要素からなる。
それぞれが`.`で区切られている。

```c:ざっくりしたイメージ 
xxxx.yyyy.zzzz
```

```c:実際のJWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
t42p4AHef69Tyyi88U6+p0utZYYrg7mmCGhoAd7Zffs
```


### ヘッダー
ヘッダーは通常、トークンの種類（JWT）と、使用する署名アルゴリズム（HMAC SHA256やRSAなど）の2つの部分から構成されている。Base64でエンコード。

### ペイロード
ユーザー情報や認証対象となるエンティティに関する情報からなる。
Base64でエンコード。

### 署名
エンコードされたヘッダーとペイロードをにヘッダーで指定したアルゴリズムと秘密鍵を用いて作成する。


`.`で繋ぎ合わせれば完成。

## JWTの注意点・リスク
良さげな記事を見つけたので貼っておきます。
[セキュリティ視点からの JWT 入門](https://scgajge12.hatenablog.com/entry/jwt_security#3-JWT-%E3%81%AE%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%83%AA%E3%82%B9%E3%82%AF)

飛ぶのがめんどくさい人のために簡単に説明すると、
・検証を行うサーバー側であらかじめアルゴリズムをしっかり選定しよう。
＞1.ヘッダーに`alg:none`を設定させるとセキュリティホールになる
＞2.RS256 の公開鍵を HS256 の共通鍵として使用する攻撃 を回避する

・HMACはできれば避けよう
＞使用される共通鍵が脆弱な(短い)文字列の場合に、その文字列をブルートフォースによって特定されるから


# [python]API認証におけるJWT実装の流れ

## 前提
1. API認証を想定している。
1. 秘密鍵はダウンロード済み。
1. `secrets`は秘密鍵

## 実装

### 1.事前準備
```python:Bash
$ pip install pyjwt
```
### 2.JWTの作成 
```python:JWT
import jwt  

#相手サーバーのAPIドキュメントによって内容は変わります。
payload = {           
  "iat": 1653199095,
  "jti": "da5dd8a6-15c5-4197-9f6b-cc0f6051dcf2",
  "type": "access",
  "sub": "U0000000120",
  "nbf": 1653199095,
  "exp": 1653199995
}

jwt_assertion = jwt.encode(
  payload,
  secrets,
  algorithm='RS512'
  headers={
    'kid':keyId   #JWTへの署名に使用する公開キーのID
  }
}
```
### 3.アクセストークンのリクエスト

```python:access_tokenのリクエスト
import json
import requests

#適宜パラメータを付け加えてください。
params = {
    'grant_type': urn:ietf:params:oauth:grant-type:*,
    'assertion': assertion,
    'client_id': clientid,
    'client_secret': clientSecret
}
response = requests.post(authentication_url, params)
access_token = response.json()['access_token']


```


大体のAPI認証の流れはこんな感じになると思います。
ありがとうございました。



## 参考記事
[【JWT】 入門](https://qiita.com/knaot0/items/8427918564400968bd2b)
[JWT公式](https://jwt.io/introduction)
[わくわくバンク JWTの仕組みと注意点](https://www.wakuwakubank.com/posts/523-it-jwt/)
QGISに HERE Vector Tile APIを接続する手順

# はじめに
以前、[HERE Raster Tile API](https://developer.here.com/documentation/raster-tile-api/dev_guide/index.html) を利用し、QGIS上で背景図として日本を含む世界中のマップ タイル イメージをリクエスト利用する手順をまとめました。

https://qiita.com/kekomat/items/18a94ba9d9c36d8caf23

今回は、[HERE Vector Tile API](https://www.here.com/docs/ja-JP/bundle/vector-tile-api-developer-guide/page/README.html) をQGISで利用するメモになります。
Rasterの時と同様に、HEREのAPIキーをお持ちであれば、事前準備と確認をスキップし、コピペとクリック操作のみ3分程度で設定できる手順になります。

# 事前準備と確認　
- APIキーの入手
HEREのAPIキーをお持ちでない場合は、下記リンクの手順を参照ください。

https://qiita.com/kekomat/items/d2e29bac84a27c1ec521

# QGIS上での接続設定
QGIS versionは、3.26.2-Buenos Airesを利用しています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725955/1118e89b-bec0-01f6-eef3-1a16a7db6a3f.png" width=50%> 

QGISを立ち上げていただき、ブラウザパネルの中の`Vecter Tiles` を右クリックし`New Generic Connection(新しい接続）`を選択します。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725955/ede70aba-d313-9469-207b-b496ecfeac19.png" width=50%>


`Name(名前)`は、任意の名前を入力いただき、URLに
https://vector.hereapi.com/v2/vectortiles/core/mc/{z}/{x}/{y}/omv?apikey={API_KEY}

最小ズーム レベル `0`,最大ズームレベル `17`を入力
`OK`をクリックします。

# レイヤーの表示と調整

Vector Tiles の配下に追加された接続名が表示されますので、それをダブルクリックすると、マップ上に追加のレイヤーが表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725955/996bb228-7446-c7a2-0e81-cace5b6824ad.png" width=50%>

世界地図を拡大すると、地図上にいくつかの点や線が表示されます。
下記は、日本の関西、中京エリアになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725955/f5d0f615-002a-7b64-e13d-2bdf2f988163.png" width=50%>
これは、デコードされた HERE Vector Tile で、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725955/aca439f5-1795-a0bd-acdf-573f3854e6c0.png)
ツールバーのIdentify Featuresからクリックいただくと含まれている属性情報の確認もできます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725955/da1b5cfe-c7d0-53f4-7ee2-2fe5476a1e80.png" width=50%>

- レイヤーの概要については、開発者ガイド[タイルレイヤー](https://jp.developer.here.com/documentation/vector-tiles-api/dev_guide/topics/layers.html#tile-layers) をご参考にしてください。

道路属性などが含まれるLineだけ表示させる場合は、
レイヤーのプロパティで、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725955/917d1405-28d1-78f9-acae-2165c8ec26ac.png" width=50%>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725955/a0137318-c454-6a46-a423-8addb3a844af.png" width=80%>
`Lines`だけチェックします。

そうすると、道路ネットワークなどのLineがズームレベルに応じて浮かび上がり、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725955/ae01e556-6897-0e8a-88c6-2c96ed9ed410.png" width=80%>

QGIS上でお持ちのHERE以外のレイヤーを背景図にすることもできます。（今回は、Open Street Mapを重ねてみました。）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725955/881f749e-3c0b-8a43-e0db-c225c8cf7844.png" width=80%>

# 参考情報

APIの引数については、
- HERE Vector Tile API リファレンス
https://developer.here.com/documentation/vector-tiles-api/api-reference-vectordata.html

また、HERE Maps API for JavaScript との組み合わせ例なども参考にいただければ幸いです。
- Vector Tile Examples
https://developer.here.com/documentation/examples/vector-tiles
ブレードサーバ とはどんなサーバ？

## 勉強前イメージ

普通の1Uのサーバのことをブレードっていうんじゃないの？

## 調査

### ブレードサーバ とは

ブレード(刃)のような細長い基盤にCPUやメモリなど主要部品を取り付けたサーバのことを指します。
専用の筐体を ブレードシャーシ や ブレードエンクロージャー など呼ばれ
内部にコネクタが並んで給電などのユニットが用意されています。
各ブレードには湯用美品が配置されて単体で一つのコンピュータとして機能します。

ブレードサーバは3Uで20枚程度詰め込めるため、1ラックに大量のサーバを詰めることが出来ます。

### ブレードサーバの用語と種類

- フルハイトブレード

ブレードに装着する基盤の幅が36cm程度のもの
1台あたりの性能を重視したい場合に使用される。

- ハーフハイトブレード

ブレードに装着する基盤の幅が18cm程度のもので、フルハイトブレードの半分になります。
台数を多く詰め込みたいときに使用されます。

- サーバブレード

サーバの機能を一枚の基板に集約した小型のコンピュータを指します。
ブレードシャーシと呼ばれる専用の筐体に差し込んで使用します。

- ストレージブレード

ブレードサーバのスロットに装着できるストレージ部品になります。
NAS製品やSASやSATAなどで別に接続して利用する場合などがあります。

## 勉強後イメージ

よく1Uで使われているのはラックマウントサーバと言うらしい。。。

## 参考

- [ブレードサーバ 【blade server】](https://e-words.jp/w/%E3%83%96%E3%83%AC%E3%83%BC%E3%83%89%E3%82%B5%E3%83%BC%E3%83%90.html)
- [【2022年版】サーバーブレード メーカー5社一覧](https://metoree.com/categories/2487/)
【React】eventオブジェクトと他の値を複数取得する(渡す)方法

## はじめに
- Reactを触っていたときにイベントハンドラ関数の引数に、propsで渡ってきた引数に加えてeventオブジェクトも渡したい時にどうするか迷ったため、共有します。
    - 想定読者はJSやReactなどのフロント技術を触っている方とします。

:::note warn
追記
この記事で紹介する`todos`という値はイベントハンドラ側から引数として渡さなくても、propsから受けとった変数でそのまま使用できたため、誤りな点がありますのでご容赦ください。
:::

## 実現したいこと
- イベントハンドラの関数の引数として、eventオブジェクトともう一つ任意の引数の値を渡したい。

## 前提(準備)
- 今回はReactでサンプルを動かします。

## 参考

### 修正前
- 修正前では、propsから受け取ったtodosの値が取得できず、
```Javascript
const Form = ({ todos, addedTodo }) => {
//...(略)

	// ここでtodosを取得したい
  const addTodo = (e) => {
    e.preventDefault();

	const newTodo = {
      id: todos.length + 1,
      content: enteredTodo,
    };

    addedTodo(newTodo);
  };

//...(略)
<form onSubmit={addTodo}> 	// eオブジェクトしか(todosは)渡せない
	<button>追加</button>
</form>
```

### 修正後
- アロー関数を定義して、eオブジェクトを引数で渡してから、引数を２つ定義した関数をreturnする。

```Javascript
import { useState } from 'react';

const Form = ({ todos, addedTodo }) => {
  const [enteredTodo, setEnteredTodo] = useState('');

  // eオブジェクトとtodosも取得可能に
  const addTodo = (todos, e) => {
    e.preventDefault();

    const newTodo = {
      id: todos.length + 1,
      content: enteredTodo,
    };

    addedTodo(newTodo);

    setEnteredTodo('');
  };

  return (
      <form
    	// ここでeオブジェクトをアロー関数で渡して、関数の引数で２つの引数を渡す
        onSubmit={(e) => {
          addTodo(todos, e);
        }}
      >
		<button>追加</button>
      </form>
  );
};

export default Form;
```


## 終わりに
意外にあまり情報が出てこなかったので、少しハマりました・・・。
参考になれれば幸いです！
【サンプルコード】aws sdk phpでec2 instance profileを使ってapi gatewayへリクエストする

```php
<?php

require './vendor/autoload.php';

use Aws\Signature\SignatureV4;
use Aws\Credentials\CredentialProvider;
use GuzzleHttp\Psr7\Request;

$method = 'GET';
$region = 'ap-northeast-1';
$stage = 'prod';
$apiName = '/testApi';
$resource = '/test';
$queryAgrs = '?test=1';
$headers = [];
$body = null;
$protocol = '1.1';
$url = 'https://xxxxxx.execute-api.' . $region . '.amazonaws.com/' . $stage . $apiName . $resource . $queryAgr;

$request = new Request($method, $url, $headers, null, $body, $protocol);
$provider = CredentialProvider::instanceProfile();
$credentials = $provider()->wait();
$sigv4 = new SignatureV4('execute-api', $region);
$ret = $sigv4->signRequest($request, $credentials);

```
rsort関数について

# 概要
競プロの練習課題でrsortを使うことがあったのですが、挙動について把握できておらず少しハマったので備忘録で残します

## rsort
降順に並び替える関数

## メモ
ソートしたデータは以下のように変数に格納する必要があると思っていました。
```php
$array = [2,10,30,1,3,50];
$rsort = rsort($array);
foreach($rsort as $v){
    echo $v;
}
```
しかし、rsort関数は元の変数に変更を加えます。
なので、以下が正しいです。上記の書き方だとエラーになります。

```
$array = [2,10,30,1,3,50];
rsort($array);
foreach($array as $v){
    echo $v;
}
```

以上
Neovim (vim-plug + coc.nvim) で Rust を快適に書ける環境を作る


## はじめに

タイトルの通り、 Neovim で Rust を快適にかけるような環境を整えたので、まとめました

## 環境

私が利用する環境は以下の通りです。 vim でも同様に設定できるはずですが未確認です :pray:

- OS
  - macOS (Ventura)
- Editor
  - Neovim
- Plugin manager
  - vim-plug
- Plugin
  - coc.nvim

既に "vim-plug" や "coc.nvim" の設定が終わっていることを前提で記載します

https://neovim.io/

https://github.com/junegunn/vim-plug

https://github.com/neoclide/coc.nvim

## Plugin "rust.vim" を install する

`.vimrc` 等に "rust.vim" を install するための記述をします

```vim
Plug 'rust-lang/rust.vim'
```

`vim-plug` 以外の Plugin manager を利用している場合は、以下 `README.md` を確認してください

https://github.com/rust-lang/rust.vim

## Language server を設定する

macOS で Homebrew を利用している場合は以下コマンドを実行するだけで `rust-analyzer` を install 出来ます

```sh
brew install rust-analyzer
```

https://formulae.brew.sh/formula/rust-analyzer

https://github.com/rust-lang/rust-analyzer

https://rust-analyzer.github.io

## coc-rust-analyzer を install する

nvim を起動し、 coc-rust-analyzer を install します

```vim
:CocInstall coc-rust-analyzer
```

私は、 coc.nvim の extension を `.vimrc` 内で管理していたため以下のように記述しています

```vim
let g:coc_global_extensions = ['coc-rust-analyzer']
```

設定を追記したら `:CocInstall` を実行しましょう

https://github.com/fannheyward/coc-rust-analyzer

適当な `.rs` ファイルを開き意図した設定が動いているか確認しましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55950/41ad6fac-85ea-4a9d-e38d-28017cd17791.png)

## 最後に

Neovim (vim-plug + coc.nvim) で Rust の開発環境を作りました
まだ、 Rust を書き始めたばかりなのでより良い設定があれば変更するかもしれません

## References

https://github.com/mziyut/dotfiles/pull/27
Python　スクレイピング　参考サイト

https://kino-code.com/python_finance-01/

https://www.youtube.com/watch?v=6R6-BCFd7zM&t=1806s

https://www.youtube.com/watch?v=-2mV7W2xO_4&t=130s

https://pasopet.com/kindle_web_scraping

https://telecom-engineer.blog/blog/2022/02/25/scraping-kindle/

https://nanjamonja.net/archives/1257

https://shikaku-mafia.com/python-scraping/

https://tiero.jp/magazine/python-scraping-sample-code/

https://ai-inter1.com/python-webscraping/#st-toc-h-3

https://udemy.benesse.co.jp/development/python-work/web-scraping.html

https://boardtechlog.com/2020/08/programming/seleniumchrome%E3%81%A7%E3%82%88%E3%81%8F%E4%BD%BF%E3%81%86chromeoptions%E3%81%BE%E3%81%A8%E3%82%81/

https://qiita.com/kawagoe6884/items/889f8f2cf816439c026b
Apache　参考サイト

https://toriaezu-engineer.hatenablog.com/entry/2017/01/14/111157

https://www.ritolab.com/posts/128

https://qiita.com/Kazunori-Kimura/items/ac0ec57df751f25b2c06


https://www.jacepark.com/how-to-redirect-301-to-https-with-apache-on-centos-7/
Pythonの仮想環境の比較

この記事では、Pythonの仮想環境である
- pyenv + vertualenv
- pyenv + conda
- venv

の3つを比較します。

<details><summary>わたしの手元の環境</summary>

- MacBookAir(M1, 2020)
- macOS Monterey 12.5
</details>

# pyenv + vertualenv

### メリット
- 自分が必要なパッケージを1つずつ入れたい時に最適。
- Python自体のバージョン管理も可能。

### デメリット
- pyenvとvertualenvをインストールする必要がある(pyenv重い😢)。

### 手順

1. pyenvをインストールする
    ```bash
    brew install pyenv
    ```
    パスを通すように指示されるので、書かれている通りにパスを通す
2. virtualenvをインストールする
    ```bash
    brew install pyenv-virtualenv
    ```
3. python3.x.xをインストールする
    ```bash
    pyenv install 3.x.x
    ```
    ※M1　Macでは特定のバージョンのPythonしか入れられないようです([参考](https://stackoverflow.com/questions/71577626/issues-installing-python-3-8-10-on-macos-12-3-monterey))
4. virtualenvを作成する
    ```bash
    pyenv virtualenv 3.x.x 環境名
    ```
5. 仮想環境を起動する
    ```bash
    pyenv global 3.x.x/envs/環境名
    ```
6. 仮想環境を終了する
    ```bash
    pyenv global system
    ```

# pyenv + conda

### メリット
- Python自体のバージョン管理も可能
- 稀にcondaでしか入らないライブラリがある(今はほとんどない)ので、condaなら最強
- 分析系・科学計算系に強い

### デメリット
- pyenvとcondaをインストールする必要がある(pyenv重い😢)。
- M1 Macでは、pyenv経由でanacondaを入れることができないので、注意([公式HP](https://www.anaconda.com/)から入れよう😢)。
- condaは全体的に重い気がする。

### 手順
1. [公式HP](https://www.anaconda.com/)からanacondaをインストールする
2. インストールできるanacondaのバージョンを確認する
    ```bash
    pyenv install --list | grep anaconda
    ```
3. anacondaをインストールする
    ```bash
    pyenv install anaconda3-x.x.x
    ```
    `3-x.x.x`は任意のバージョンを
4. 環境を切り替える
    ```bash
    pyenv global anaconda3-x.x.x
    ```
5. 仮想環境を作成する
    ```bash
    conda create -n 仮想環境名 python=3.x.x インストールしたいパッケージ名
    ```
6. 仮想環境を起動する
    ```bash
    pyenv global anaconda3-x.x.x/envs/仮想環境名
    ```
7. 仮想環境を修了する
    ```bash
    pyenv global system
    ```

# venv

### メリット
- Python3系の標準機能なので、わざわざインストールする必要がない。
- とてもシンプル。

### デメリット
- Python自体のバージョン管理は不可

### 手順
1. 仮想環境を作成する
    ```bash
    python -m venv 適当な仮想環境の名前
    ```
2. 仮想環境を起動する
    仮想環境を作成したディレクトリで以下のコマンド
    ```bash
    .仮想環境名/bin/activate
    ```
3. ライブラリをインストールする
    ```bash
    pip install ライブラリ名
    ```
    もしくは
    ```bash
    pip install -r requirements.txt
    ```
4. 仮想環境を終了する
    ```bash
    deactivate
    ```

# まとめ

| 評価項目                   | pyenv + vertualenv | pyenv + conda | venv   | 
| -------------------------- | ------------------ | ------------- | ------ | 
| Python自体のバージョン管理 | 可能               | 可能          | 不可能 | 
| インストール               | 必要               | 必要          | 不要   | 
| 軽さ                       | △                 | ×             | ○     | 

# 参考
以下の記事を参考にさせていただきました🙏
- [pyenvでのPython仮想環境の作り方まとめ](https://qiita.com/ysdyt/items/5008e607343b940b3480)
- [venv: Python 仮想環境管理](https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e)

普段はvenv以外使わないので、間違っているところなどありましたら教えていただけると幸いです🙇‍♀️
amplify push と戦う２

# 症状の確認方法
amplify pushで出てくるメッセージではあんまり役に立たないので以下の方法で確認する

amplify＞アプリ＞Backend environments>環境のアクション＞詳細を表示＞最新のデプロイアクティビティ＞CloudFormation 
イベントタグを選択する
（状況の理由に「User Initiated」があるのでそれが、push開始っぽい）

# 症状1

```　
Resource handler returned message: "1 validation error detected: Value '[xxxxxxxArn]' at 'layers' failed to satisfy constraint: Member must satisfy constraint: [Member must have length less than or equal to 140, Member must have length greater than or equal to 1, Member must satisfy regular expression pattern: (arn:[a-zA-Z0-9-]+:lambda:[a-zA-Z0-9-]+:\d{12}:layer:[a-zA-Z0-9-_]+:[0-9]+)|(arn:[a-zA-Z0-9-]+:lambda:::awslayer:[a-zA-Z0-9-_]+), Member must not be null] (Service: Lambda, Status Code: 400, Request ID: xxxxxxx)" (RequestToken: xxxxxxxxxx, HandlerErrorCode: InvalidRequest)
```

## 対処

レイヤーのarnが変更されて存在が無くなったっぽいので、amplify update functionでlayerの更新をする


# 症状2

```　
Embedded stack arn:aws:cloudformation:ap-northeast-1:なんかID:stack/なんかID/なんかID was not successfully created: No export named 〜〜〜〜GraphQLAPIIdOutput:GetAtt:テーブル名Table:Name found
```

## 対処
templateがおかしくなった？？

amplifi update function
関数選択＞権限が出るので
```
Resource access permission
- xxxxxxxx (create, read, update, delete)
- xxxxxxxx:@model(appsync) (create, read, update, delete)
- xxxxxxxx:@model(appsync) (create, read, update, delete)
- xxxxxxxx:@model(appsync) (create, read, update, delete)
- xxxxxxxx (create, read, update, delete)
```
権限をメモしておく。

Resource access permissionsを選んでエンター
xxxxxxTableを外してpush

amplifi update function
関数選んで
メモした権限を復活


# 症状3

```
Parameters: [storagexxxxxxxxBucketName] do not exist in the template
```

## 対処
templateがおかしくなった？？

amplifi update function
Resource access permissionsを選んでエンター連打で終わらせる
これだけで、更新されるらしい



# 症状4



```
Parameters: [unauthRoleName, authRoleName] must have values
```
＋
```
The following resource(s) failed to create: [functiondecodingBarcode]. The following resource(s) failed to update: [apixxxxxxx, authuserPoolGroups].
```

## 対処

追加したばかりの関数を`amplify push function xxxxxx`で発生する
amplify push したら出なかった。
追加したばかりの場合はamplify pushしないとダメらしい
Deploy application in Kubernetes

1. set alias in powershell
`set-alias -name k -value kubectl`
1. Create pod manifest template
`k run tellhost --image=toka9988/tellhost --dry-run=client -o yaml >mypod.yaml`
1. Apply pod manifest file to create a pop
`k apply -f mypod.yaml`
1. Set up port-forward
`k port-forward tellhost 8080` tellhost is the pod name, the porxy will wait connect. Use another powershell terminal to test.
1. show pod log
`k logs tellhost`
stream the application log in real-time to see each request as it comes in
`k logs tellhost -f`  --follow 
`k logs tellhost --timestamps=true` show log time of each line
1. copy file between local PC and pods
`k cp tellhost:\etc\hosts hosts.txt`
1. Run command in Pod
`k exec tellhost -- ps aux`
`k exec tellhost -it  -- bash`
1. delete pod by name
`k delete pod tellhost3`
`k delete pod tellhost2 --wait=false`
1. Creating an HTTP GET liveness probe
```yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: tellhost
  name: tellhost
spec:
  containers:
  - image: toka9988/tellhost
    name: tellhost
    ports:
    - containerPort: 8080
    livenessProbe:
      httpGet:
        path: /
        port: 8080
      initialDelaySeconds: 10
      periodSeconds: 5
      timeoutSeconds: 2
      failureThreshold: 3
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
```
1. Using a startup probe 
```yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: tellhost
  name: tellhost
spec:
  containers:
  - image: toka9988/tellhost
    name: tellhost
    ports:
    - containerPort: 8080
    startupProbe:
      httpGet:
        path: /
        port: http
      periodSeconds: 10
      failureThreshold: 12
    livenessProbe:
      httpGet:
        path: /
        port: 8080
      periodSeconds: 5
      timeoutSeconds: 2
      failureThreshold: 3
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
```
【VSCode】スペースの可視化とタブ入力時にスペースにする設定

お疲れ様です。今日もゴリゴリ職場でコードを書いていこう、、と思った矢先、自分がレビューを出していたコードに修正が入りました。
修正理由はスペースがタブになっているとのこと。おや？コード修正中にタブキーを押した覚えはないぞ。。？と思いながらVSコードの設定を見てみると、なんとまあ、そうゆう設定になっておりました。

てな訳で今日はこれ知っておくといいよってのを備忘録的につらつらと書いていこうと思います。

# タブキーを押すとスペースが挿入される

設定をポチッとな
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2647183/35a47d35-d303-d8c4-25cd-b9f0f8250034.png)

検索バーに「insert spaces」と検索一番上の赤いカッコの中をチェック
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2647183/857aa4e4-d398-53d3-1a81-29c796d7c0ea.png)

# 空白スペースの可視化

検索バーに「Render White space」と検索
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2647183/d98de284-c6c7-08c9-9c16-7ef4369c9c80.png)

てな感じで設定周りをいじって、LGTM（Looks Goot To Me）してもらいました。
プリズン・ブレイク　シーズン5　第9話（最終話）『瞳の奥』のあのシーンを再現するべくWebアプリ『Open the gate with Michael!』を制作した。

# 前書き
**「プリズン・ブレイク」**

皆さんの中にも作品を愛し、**マイケル・スコフィールド**を愛した方もいるだろう。
例に漏れず私もその一人だ。
プリズン・ブレイクは、ウォーキングデッドほどではないが、5シーズン90エピソードで構成されており、一通り見るには**一度深呼吸をし、覚悟を決めなければ最後まで見切ることができない**ような長編ドラマである。

私はそれを、**5周**した。
5回、1からプリズン・ブレイクを見たのだ。
周りからは、「他の作品も色々見ろ」と言われたが、**5回も見ることができるほど価値のある作品**なのである。

今回制作したシーンだが、90エピソードある90話目の一部にあたる。
プリズン・ブレイクについて詳しく知りたい方や気になる方は、もちろんご自身の目で一度見ていただくことを推奨するが、[Wikipedeia](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AA%E3%82%BA%E3%83%B3%E3%83%BB%E3%83%96%E3%83%AC%E3%82%A4%E3%82%AF)も参考いただけたらと思う。

主人公のマイケルが、とある悪の組織に我が息子を奪われてしまう。
息子がいる部屋は顔認証でゲートが開く仕組みになっており、その組織の幹部であるポセイドンと名乗る者ののみが入室することができる場所であった。

マイケルの手の甲には既に、息子を救うべくポセイドンの顔をモチーフとしたタトゥーが描かれており、それを顔の前にかざすことによって顔認証のスキャニングに成功し、扉が開くのだ。

私は初めてそのシーンを見たとき、鳥肌が立つなんて簡単な言葉では片づけることができないほど、なんて素晴らしく、圧倒的なのだろうと感嘆した。

手の甲にタトゥーを掘る予定はまだないが、手の甲を顔の前にかざしたときに扉を開くといったシーンを再現することはできるため、今回制作にあたった。

# 制作に至った背景
現在Webアプリケーションの制作を学んでおり、その中でブラウザ上で機械学習を利用できるml5というものを知った。
そこで、ml5に関わるものについて現状Qiita上にどんな記事があるのだろうと調べてみたところ、こんな記事を見かけた。

https://qiita.com/twtjudy1128/items/4c29a98a035a6e8cbcb4

素晴らしい。
自分が好きなものを全力で作られている。

私も何か似たようなものを作りたい、そう考えたときに思いついたものが、今回のプリズン・ブレイクのシーンである。

# 制作したアプリケーション
まずはご覧いただきたい。

手の甲を顔の前にかざすと、扉が開く音が鳴る、という仕様だ。
（はじめはスキャニング成功、のような音源を流したかったのだが、ちょうど良いものが見つからず断念した。）

https://helpful-duckanoo-81aad9.netlify.app

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885795/568b6c20-5001-490e-64b7-aec47416fe98.png)

動作は下記を参考いただきたい。

* Succeeded：両手の甲を顔の前にかざした場合
* Failed：何もしていない、また片手のみをかざした場合

![スクリーンショット_20221120_211350.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885795/d9ed1c6e-0a1c-8a69-9efc-aca7e7efefa9.png)

# 使用したもの
* ml5.js
* CodePen
* Teachable Machine
* netlify

# 使用してみた感想
上手く作動したときはとても嬉しく男心をくすぐった。
私はこれから息子を救うのだ、そのためにこのタトゥーを事前に用意していたのだ、、。
実に素晴らしい。
前述したが、今のところタトゥーを掘る予定はないため、体験することができただけでも楽しかった。

# 後書き
今回は機械学習を活用したWebアプリケーションを制作したが、実に容易に実装することができた。
機械学習に係る部分で躓くことはなく、スムーズに進めることができた（それ以外の部分はてんでダメだったが）。
また、Teachable Machineの使用するモデル作成も作業自体は非常に簡単だったため、プログラミング初心者には有難い内容であった。

夢の一つを叶えることができたため、それではこれから第6周目に突入でもしようかと思う。
AWS S3に保存してあるファイルをPYTHONで直接読みこむ方法


s3からファイルに書き込まない、ダウンロードしないで直接読み込んで何かする

# CSVの場合
- utf-8
- csv.readerを使う



```py
import csv
import io

import boto3

s3_client = boto3.client("s3")
csv_s3_object = s3_client.get_object(Bucket="bucket name", Key="key～csvのパス～")
with io.TextIOWrapper(
    io.BytesIO(csv_s3_object["Body"].read()), encoding="utf-8"
) as csv_file_io:
    reader = csv.reader(csv_file_io, delimiter=",")
    for record in reader:
        print(record[0], record[1])
```



# jpgの場合
- Image.openする




```py
import os
from io import BytesIO

import boto3
from PIL import Image

s3_client = boto3.client("s3")
storage_bucketname = os.environ["xxxxx"]


def handler(event, context):
    print(event)
    arguments = event["arguments"]
    s3_object = s3_client.get_object(
        Bucket=storage_bucketname,
        Key=arguments["key"],
    )
    with BytesIO(s3_object["Body"].read()) as img_io:
        pillow_object = Image.open(img_io)


```
Docker環境でVUE CLIのホットリロードが効かない


## 問題

Docker上でvue.jsプロジェクトを作成するとホットリロードが動作しない。

## 解決策
プロジェクトルートのvue.config.jsに以下のように記述。
vue.config.jsがなければ作成

```vue:vue.config.js
module.exports = {
  devServer: {
    client: {
      webSocketURL: 'ws://0.0.0.0:8080/ws'
    }
  }
}
```

## 詳細

### 環境
・macOS Big Sur 11.5.2
・@vue/cli 5.0.0
・Docker version 4.13.1 (90346)
・docker-compose version 2.12.1

最初は、以下の記事を参考にし、vue.config.jsにこんな感じで書いた。
[Docker Compose 上で Vue CLI の Hot Reload を動くようにする](https://qiita.com/myabu/items/cfd7359a498c55c5dc4f)
```vue:vue.config.js
module.exports = {
  devServer: {
    client: {
      host: '0.0.0.0',
      webSocketURL: 'ws://0.0.0.0:8080/ws'
    }
  }
}
```
しかし、`npm run serve`するとこんなエラーを吐かれた

```
 INFO  Starting development server...
 ERROR  ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
         - options.client has an unknown property 'host'. These properties are valid:
           object { logging?, overlay?, progress?, reconnect?, webSocketTransport?, webSocketURL? }
```

どうやらwebpack-dev-serverのv4ではhostオプションが消えているらしい。

https://webpack.js.org/configuration/dev-server/#devserverclient

devServer-> client内のhostオプションを削除するとうまく動作した。

```vue:vue.config.js
vue:vue.config.js
module.exports = {
  devServer: {
    client: {
      // host: '0.0.0.0',
      webSocketURL: 'ws://0.0.0.0:8080/ws'
    }
  }
}
```


### 参考文献

[Docker Compose 上で Vue CLI の Hot Reload を動くようにする](https://qiita.com/myabu/items/cfd7359a498c55c5dc4f)

https://webpack.js.org/configuration/dev-server/#devserverclient
【Laravel】リレーション先のさらに先で条件をつけて取得


## やりたいこと

リレーションの先で条件検索はありましたが、先の先が中々見当たらなかったのでメモ代わりに記載しました。

Laravel Eloquentで取得していきます。
例えば usersテーブルとproductsテーブルが1対多の関係にあり、さらにproductsテーブルとblogsテーブルが1対多の関係にある場合にblogsテーブル→productsテーブル→usersテーブルのusersの名前で条件をつけたい場合の記法です。

※あくまでも例なのでテーブルの内容やDBの構造は気にしないでください。
## 動作環境
Laravel9.0

## 記述方法

結論、以下の記述でやりたいことが実現できる。

```php
$userId = 1; //usersテーブルのid = 1が条件
$items = Blog::wereHas(['product', function($query) use($userId) {
	$query->wereHas('user', function($query) use($userId) {
        $query->where('id', $userId);
    });
}])->get();
```

実行しているSQLを出力して確認してみる。
use($xxxx)で変数を持っていかないとエラーになる。
blogsテーブル→productsテーブル→usersのつまり
usersの条件を元に検索をかける。

## 主なデータ
主なデータは以下に記載の通りです。

### Userテーブル
| id | name |
| --- | --- |
| 1 | 田中 |
| 2 | 鈴木 |
| 3 | 佐藤 |

### Productテーブル
| id | name | user_id |
| --- | --- | --- |
| 1 | スポーツ | 1 |
| 2 | 読書 | 2 |
| 3 | 仕事 | 3 |

### Blogテーブル
| id | name | product_id |
| --- | --- | --- |
| 1 | title1 | 1 |
| 2 | title2 | 2 |
| 3 | title3 | 3 |

```User.php
...省略

public function users()
{
    $this->hasMany('App\Models\Product');
}
```

```Product.php
...省略

public function user()
{
    $this->belongsTo('App\Models\User');
}

public function blogs()
{
    $this->hasMany('App\Models\Blog');
}
```

```Blog.php
...省略

public function product()
{
    $this->belongsTo('App\Models\Product');
}

```


上記の通り、ユーザー情報は全て取得し、ブログについてはcategoryがPHPのもののみ取得できていることが分かる。

## 失敗例　&　成功例

以下の書き方だと、whereHasの条件に合うユーザー情報を取得する。
今回のように、blogs情報は全て取得したうえで、リレーション先のその先のデータを指定した条件に合うものだけ取得したい、、という場合は以下の書き方ではいけないので注意。

`use($userId)がないとエラーになる`
```php

//失敗例
$userId = 1; //usersテーブルのid = 1が条件
$items = Blog::wereHas(['product', function($query) {
	$query->wereHas('user', function($query) {
        $query->where('id', $userId);
    });
}])->get();

//成功例
$userId = 1; //usersテーブルのid = 1が条件
$items = Blog::wereHas(['product', function($query) use($userId) {
	$query->wereHas('user', function($query) use($userId) {
        $query->where('id', $userId);
    });
}])->get();
```



上記の通り、`use($userId)がないとエラーになる`ので注意

## さいごに
この記法でさらに先までも検索は可能だと思います。
HTMLタグ早見表

# 基本構造

```html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="文字コード">
        <title>Title</title>
    </head>
    <body>

    </body>
</html>
```

|タグ|説明|
|:---:|---|
|\<!DOCTYPE html\>|DOCTYPE宣言: HTML5に準拠した内容という宣言|
|\<html\>\</html\>|ルート要素: \<head\>と\<body\>の2つのタグがこの順番で含まれる|
|\<head\>\</head\>|メタデータ(ウィンドウには表示されないHTMLドキュメント自身の情報)を記述|
|\<meta charset="文字コード"\>|文字コードを指定(\<head\>タグの直下に記述)|
|\<title\>\</title\>|HTMLドキュメントのタイトル(テキストのみ)|
|\<body\>\</body\>|本文|

## 複数の要素をまとめるタグ

```html
<body>
    <header>
        ヘッダーの内容
    </header>
    <nav>
        複数の要素を記載
    </nav>
    <main>
        複数の要素を記載
    </main>
    <div>
        複数の要素を記載
    </div>
    <footer>
        フッターの内容
    </footer>
</body>
```

|タグ|説明|
|:---:|---|
|\<header\>\</header\>|ヘッダー部分|
|\<nav\>\</nav\>|サイトの主要なページを往来できる様にナビゲーション(リンク)を記述|
|\<main\>\</main>|本文中の重要な要素をまとめるタグ<br>1つのHTMLファイル内で1回しか使用出来ない|
|\<div\>\</div\>|汎用ブロック<br>本文中の複数の要素をまとめる|
|\<footer\>\</footer\>|フッター部分|

## 見出し

```html
<body>
    <h1>最も重要度の高い見出し</h1>
        <h2>見出し2</h2>
            <h3>見出し3</h3>
                <h4>見出し4</h4>
                    <h5>見出し5</h5>
                        <h6>最も重要度が低い見出し</h6>
</body>
```

|タグ|説明|
|:---:|---|
|\<h1\>\</h1\>|最も重要度が高い見出し|
|\<h6\>\</h6\>|最も重要度が低い見出し|

## 段落

```html
<body>
    <p>段落1の内容</p>
    <p>段落2の内容</p>
</body>
``` 

|タグ|説明|
|:---:|---|
|\<p\>\</p\>|段落(paragraph)の内容を記述<br>(テキスト，テキストを修飾するタグ，リンクタグ，画像タグのみ記述可)|

## 箇条書き

### 非序列(番号なし)リスト

```html
<body>
    <ul>
        <li>箇条書き項目</li>
        <li>箇条書き項目</li>
    </ul>
</body>
```

|タグ|説明|
|:---:|---|
|\<ul\>\</ul\>|非序列(番号なし)リスト|
|\<li\>\</li\>|リスト項目|

### 序列(番号付き)リスト

```html
<body>
    <ol>
        <li>項目1</li>
        <li>項目2</li>
    </ol>
</body>
````

|タグ|説明|
|:---:|---|
|\<ol\>\</ol\>|序列(番号付き)リスト|
|\<li\>\</li\>|リスト項目|

## テーブル

```html
<body>
    <table>
        <tr><th>ヘッダー1</th><th>ヘッダー2</th></tr>
        <tr><td>項目1</td><td>項目2</td></tr>
    </table>
</body>
```

|タグ|説明|
|:---:|---|
|\<table\>\</table\>|テーブル本体|
|\<tr\>\</tr\>|テーブルⅠ行|
|\<th\>\</th\>|ヘッダー|
|\<td\>\</td\>|項目|


## リンク

```html
<body>
    <a href="Path or URL">リンク</a>
    <a href="Path or URL" target="_blank">別タブで開きたいリンク</a>
</body>
```

|タグ|説明|
|:---:|---|
|\<a\>\</a\>|リンクを設定<br>targetに`_blank`を設定すると新しいタブでリンク先を表示|

## 画像

```html
<body>
    <img src="画像のファイルパス" alt="代替テキスト">
</body>
```

|タグ|説明|
|:---:|---|
|\<img\>|画像を挿入|

## テキスト修飾

|タグ|意味|例|結果|
|:---:|---|---|---|
|\<br\>|強制改行|サンプル\<br\>サンプル|サンプル<br>サンプル|
|\<strong\>\</strong\>|重要|\<strong\>サンプル\</strong\>|<strong>サンプル</strong>|
|\<b\>\</b\>|太字|\<b\>サンプル\</b\>|<b>サンプル</b>|
|\<sub\>\</sub\>|下付き文字|H\<sub\>2\</sub\>O|H<sub>2</sub>O|
|\<sup\>\</sup\>|上付き文字|y = x\<sup\>2\</sup\>|y = x<sup>2</sup>|

## 特殊文字

|特殊文字|文字実態参照|
|:---:|---|
|&copy;|\&copy\;|
|&lt;|\&lt\;|
|&gt;|\&gt\;|
|&amp;|\&amp\;|
|&quot;|\&quot\;|
|&yen;|\&yen\;|
|&nbsp;|\&nbsp\;|



# Reference
* スラスラわかるHTML＆CSSのきほん(狩野祐東著;SBクリエイティブ;2018年)
deviseのサインアップ時に名前を登録できるようにする

deviseにてログイン機能を実装すると、
サインアップ時に登録できる情報はデフォルトとして　「メールアドレス」「パスワード」が用意される。

今回は「メールアドレス」「パスワード」に加えて「名前」を登録できるようにする。

# テーブルにカラムを追加

現状、カラムは「メールアドレス」と「パスワード」のみであるが、ここに「名前」を追加する。

:::note warn
データベースは表形式のテーブルで管理される。
この表形式の行をレコード、列をカラムという。
:::

ターミナルにて下記を実行することで、「追加先テーブル」に「追加するカラム」を追加することができる。

```ruby:ターミナル
% rails g migration Add カラム名 To 追加先テーブル名 追加するカラム名:カラムの型
```

名前を登録できるようにしたいため、「カラム名」を`Nickname`とする。
*「追加先テーブル名」は`User`、カラムの型は`string`とする。

```ruby:ターミナル
% rails g migration AddNicknameToUsers nickname:string
```

:::note warn
カラムの型 一覧
- string : 文字列
- text : 長い文字列
- integer : 整数
- float : 浮動小数
- decimal : 精度の高い小数
- datetime : 日時
- timestamp : タイムスタンプ
- time : 時間
- date : 日付
- binary : バイナリデータ
- boolean : Boolean
:::


# 作成したマイグレーションを実行

```ruby:ターミナル
% rails db:migrate
```
# サーバーを再起動

```ruby:ターミナル
% rails s
```
Javaで何か作ってみる(2022/11/20 Day31)

## 今日やった事
- 何もしなかった。
## 参考にしたもの
- 特になし。
## 所感
- 今日は本当何も勉強しなかった、ただただ反省。。。しかも2日連続
## 明日の予定
- 引き続き、Javaの勉強を進めていく。明日こそは。。。
Javaで何か作ってみる(2022/11/19 Day30)

## 今日やった事
- 何もしなかった。
## 参考にしたもの
- 特になし。
## 所感
- 今日は本当何も勉強しなかった、ただただ反省。。。
## 明日の予定
- 引き続き、Javaの勉強を進めていく。
【SwiftUI】長押しでメニューを表示する

# はじめに
ContextMenuは長押しした時に出るメニューです。
意外と知られてなさそうなので紹介します。

# 動画
![Simulator Screen Recording - iPhone 14 - 2022-11-20 at 21.50.34.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/0aef788c-d1f4-ea34-f032-aca52b1219cd.gif)

# データ
```swift
struct Weather: Identifiable {
    let id = UUID()
    let iconName: String
    let iconColor: Color
    let title: String
}

let weathers: [Weather] = [
    .init(iconName: "sun.max.fill", iconColor: .orange, title: "晴れ"),
    .init(iconName: "cloud.fill", iconColor: .gray, title: "曇り"),
    .init(iconName: "cloud.rain.fill", iconColor: .blue, title: "雨")
]
```

# 実装
```diff_swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        List(weathers) { weather in
            Label {
                Text(weather.title)
            } icon: {
                Image(systemName: weather.iconName)
                    .foregroundColor(weather.iconColor)
            }
+           .contextMenu {
+               Button {
+                   print()
+               } label: {
+                   Text("テスト")
+               }
+           }
        }
        .listStyle(.grouped)
    }
}
```

# おわり
かなりかっこいいので積極的に使っていきたいです
FlaskとPostgreSQLの連携

[前回の記事](https://qiita.com/outsider-kithy/items/40accddcb7f3fab6d749)に引き続き、
HerokuにデプロイしていたFlask,PostgreSQLを使ったアプリケーションを、さくらのVPSに移した際の備忘録です。

今回はCentOSにインストールしたPostgreSQLをFlaskアプリケーションと連携させる手順です。

## PostgreSQLを操作する「postgres」ユーザーと「postgres」グループを作成
    adduser -U postgres
    Enter new password://postgresユーザー用のパスワードを入力
    Retype new password://もう一度同じパスワードを入力

## /usr/local/に「pgsql」ディレクトリを作成して所有権を「postgres」ユーザーに変更
    mkdir /usr/local/pgsql
    chown postgres:postgres /usr/local/pgsql

## postgresユーザーに切り替えて、/usr/local/pgsqlに移動
    su - postgres
    cd /usr/local/pgsql

## /usr/local/pgsqlにPostgreSQL14.5をダウンロードして解凍
    wget https://ftp.postgresql.org/pub/source/v14.5/postgresql-14.5.tar.gz --no-certificate
    tar xvfz postgresql-14.5.tar.gz

各バージョンのソース一覧はこちら
https://www.postgresql.org/ftp/source/

## コンパイルとインストール
    cd postgresql-14.5
    ./configure --prefix=/usr/local/pgsql
    gmake
    cd contrib
    gmake
    cd ..
    gmake install
    cd contrib
    gmake install

## psqlのインストール
※ルートユーザーで作業
````
yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
yum install -y postgresql14-server
````

## PostgreSQLの初期化
※postgresユーザーで作業
````
su -
````
/usr/local/pgsql/dataにデータベースクラスタを作成
````
cd /usr/pgsql-14/bin/
postgresql-14-setup initdb
````

## PostgreSQLの起動
    systemctl start postgresql-14.service

## PythonアプリケーションからPostgreSQLに接続するためにpostgresql.confを編集
    vi /var/lib/pgsql/14/data/postgresql.conf
    
    //60行目あたり
    listen_addresses = '*' 
    #listen_addresses = 'localhost'

## PostgreSQLを再起動
    systemctl restart postgresql-14.service

## PostgreSQLが使うポート番号5432を解放
※ルートユーザーで作業
````
su -
firewall-cmd --permanent --add-port=5432/tcp
````

## firewallを再起動
    firewall-cmd --reload

## データベースが正しく稼働しているか確認
※postgresユーザーで作業
````
su - postgres
psql -l
````

データベース一覧が表示されたら、正しく稼働しています。
ローカルの不要なブランチをまとめて削除するshell

gitのブランチが気づいたら大量にできてしまったときに、特定のキーワードを入力すれば候補を確認のために表示して問題なければまとめて削除できるshellを作ってみました。

例えば以下のように`fix/`以下のhogeXXブランチは残したいけどfugaXXブランチは削除したいときに使うと便利かもです。
![スクリーンショット 2022-11-20 21.25.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287537/44d83ea5-d1b3-3839-6197-e45e02ae89fa.png)

# shellの中身
```.shell
#!/bin/bash

echo "削除したいブランチ名の一部を入力してください。"

read KEYWORD

LIST=($(git branch | grep -E --color=always $KEYWORD))

printf "%s\n" "${LIST[@]}"

if [ ${#LIST[@]} = 0 ]; then
    echo "該当するブランチがありません。"
else
    echo "${#LIST[@]}個のブランチを削除しますか？ y or n"

    read INPUT

    if [ $INPUT = "y" ]; then
        git branch | grep $KEYWORD | xargs git branch -D
    else
        echo "ブランチの削除をキャンセルしました。"
    fi
fi
```

# 上記shellを任意の場所に配置
私はデスクトップに配置していますが、お好きなディレクトリに配置しましょう。

# terminal上で削除したいブランチがあるディレクトリに移動して用意したshellを叩く
![スクリーンショット 2022-11-20 21.29.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287537/5ea233db-3599-34a3-0c71-f08e77f16bf3.png)

削除したいブランチ名の一部を入力（ここではfuga）を入力すると`fix/fugaXX`のブランチの該当箇所が色付きで一覧で表示されますので削除前に確認しましょう。

問題なければ`y`を入力するとまとめて削除できます。
![スクリーンショット 2022-11-20 21.32.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287537/8cfc9d44-8f32-e159-7aeb-93b94222e00a.png)
ブランチを確認すると`fix/fugaXX`のブランチが削除できていますね。
![スクリーンショット 2022-11-20 21.33.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287537/c8f79b99-d28f-c805-a38c-aad4571bc84c.png)
また、`fix`をキーワードとして入力すると`fix/`配下のブランチをまとめて削除することができます。
Digital Marketing with Drupalを読んだレビュー

# 始めに
昨年、Next.js関係でQiita Advent Calendar 2021の投稿宣言していましたが、多忙＆新年早々コロナ陽性などにより投稿出来ていませんでした。私的にもやりきりたい性格なので、2022年に発売されたDrupal本からポエム的にレビューを投稿をします。

春頃に洋書のDrupal本 「[Digital Marketing with Drupal](https://www.drupal.org/node/3266781)」 が発売されているのを把握をしていましたが、[packt](https://www.packtpub.com/) でebook版が購入出来ず躊躇していました。既にKindle版は購入可能でしたが、英語がアレで私的にGoogle翻訳経由でないと内容が把握するのに時間を要します。[packt](https://www.packtpub.com/) で購入できればブラウザで表示する部分はページごと和訳表示にすれば違和感も少なく内容を把握するのも容易です。9月頃にebook版も購入できるようになったので、即購入しました。

[amazon.co.jp](https://www.amazon.co.jp/Digital-Marketing-Drupal-ultimate-marketing-ebook/dp/B09F3TH5XP/ref=sr_1_13?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=2QMLX13ZYZ12R&keywords=Drupal&qid=1668938128&qu=eyJxc2MiOiIzLjU3IiwicXNhIjoiMy41MSIsInFzcCI6IjMuMzIifQ%3D%3D&sprefix=drupal%2Caps%2C170&sr=8-13)
[packt](https://www.packtpub.com/product/digital-marketing-with-drupal/9781801071895?_ga=2.160871613.1298488938.1668938319-36145804.1668938319)

お題の書籍はどちらかと言うとマーケティングに関わる人を対象にしたものです。もちろん、マーケティングに関わる方以外にも有益であり、Drupalを通じて自分のターゲットにどう伝えてDX出来るかを指南してもらえる書籍。プログラミングスキルは必要ないので、Drupalを通じて他のサービスも組み合わせて各自やクライアントのビジネスモデルをどのように展開できるか考察したくなるものです。

私がDrupalを使い始めた時はサイトだけ作れば良く、いわゆるものを作れば終わっていた。PCやスマートフォンの普及により物事が多様化した。全ての領域を扱うものから一部分の機能がほしいマイクロサービスの組み合わせでサービス展開するのが普通になりつつある。今や時代はサブスクリプションサービスが主流になりつつある。マーケティング戦略も作れば売れる時代から進化し、デジタルマーケティングやコンテンツマーケティングの戦術・戦略の成果を上げることで事業のサステナブルにつながるのである。

 「[Digital Marketing with Drupal](https://www.drupal.org/node/3266781)」 は10章の構成となっており、デジタルマーケティングの基礎から始まる。

1.Fundamentals of Digital Marketing
2.Building Your Own Digital Marketing Plan
3.Setting up Your Drupal Playground
4.Content Is King
5.Generating Website Traffic
6.Communicating with Your Customers
7.Measuring Success Through Web Analytics
8.Marketing Your Drupal Commerce Store
9.Tools to Help You Be More Efficient and Productive
10.Taking Drupal's Digital Marketing to the Next Level

## 1.Fundamentals of Digital Marketing
デジタルマーケティングの基礎を説明。
ブランド価値・カスタマージャーニー・コンテンツマーケティング・ソーシャルマーケティング・SEM（サーチエンジンマーケティング）・SEO（検索エンジン最適化）・ディスプレイ広告・メールマーケティング・アフィリエイトマーケティング・デジタルPR・インフルエンサーマーケティング・CRMマーケティングについて言及し、次の章でのデジタルマーケティング戦略について解説しています。

## 2.Building Your Own Digital Marketing Plan
デジタルマーケティングプランの構築に向けて、デジタルマーケティングプランの作成方法やサンプルで解説されています。
この1・2章ともマーケティングの話でWebサイトごとにマーケティングプランを定義すること、ブランドの現在位置から見出すことを学ぶことができます。
## 3.Setting up Your Drupal Playground
この章からDrupal が出てきます。Drupal Commerceをlando環境でセットアップし、digital_marketing_checklistモジュールをインストールするまでを解説しています。
検索で調べると以下のGithubにSampleがヒットしますので掲載。
https://github.com/PacktPublishing/Digital-Marketing-with-Drupal

## 4.Content Is King
Drupalがコンテンツ管理に優れていること、コンテンツ管理に紐づくMedia・タクソノミーなどが解説されています。

5章以降も書いていたのですが内容のネタバレになってしまうので割愛します・・・。

## おわりに
https://www.drupal.org/node/3266781
書籍のページにもあるように対象者にはマーケティングの基礎知識があることを前提に書いてある。1・2章は進んでいくにも止まってしまう人もいるだろう。3章からはDrupalと組み合わせてデジタルマーケティングを進めていきます。章が進むにつれてDrupalを中心としたデジタルマーケティングの戦略手法が明らかになっていきます。書籍の内容を把握できれば、もうDrupalから抜けられない人になっているはずです。
【読書感想】ザ・ダークパターン ユーザーの心や行動をあざむくデザイン

（最近、更新頻度が落ちているので・・・）
読書感想シリーズを定期的に投稿していこうと思います。

# 「ザ・ダークパターン ユーザーの心や行動をあざむくデザイン」 出版社：翔泳社
翔泳社さんではコンスタントにポイントバックキャンペーンを打っていて、電子書籍ではなく、紙派の私は`書籍50％ポイント還元キャンペーン`などを狙っては積本させて頂いております。今回はその時に購入した1冊です。

https://bookmeter.com/books/19948015

「ダークパターン」とはWebサイトやアプリケーションにおいて、ユーザーを騙して購入させたり、登録させたり、意図しない行動を取らせるユーザーインターフェース（UI）のことです。

こちらの本ではこの「ダークパターン」が及ぼす影響についての研究や事例の解説を中心に、ビジネスパーソンに向けて「ダークパターン」問題とどのように向き合っていくかを考えさせられる内容となっています。

# 以下、ざっくり感想です。
具体的な内容は是非、本書を購入して読んで頂ければと思いますが、まず全体として200ページ弱と非常にコンパクトにまとまった良書と感じました。

ビジネスにおいて数字ばかり追いかけた定量的な目標設定や評価では、いつしか目的と手段が逆になってしまって、ユーザー目線でなくなり、ダークパターンに走りますよ、気をつけましょうね。と言う話なのですが、例えば「退会の仕方が分かり辛いUI」とか、「メルマガ登録チェックがデフォルトで入ってるUI」とか、フロントエンド開発に携わっている身として、耳の痛い話でありました。

そうなんですよね。本来、ユーザーにとって使い易いデザインを考えるのが仕事なわけじゃないですか。目先の売上や登録数、クリック数に囚われて、それが会社の評価指標となってユーザー体験に繋がらないなんて終わってるよなーと思いますが、実際は大手サイトでも日常的にダークパターンが使われていますよね。

実例を見てもダークパターンは中長期的にユーザーの信用を失う要因となるのは間違いないので、誠実にユーザーと向き合った開発をしていきたいなと思いました。
FlaskをCentOSで動かす

Herokuの無料枠廃止に伴い、自分で作ったFlask,PostgreSQLを使ったアプリをさくらのVPSに移しました。
備忘録として、その際の手順をメモ。

### バージョン
CentOS 7
Python 3.7.9
mod_wsgi 4.5.6


## apacheのインストール
    yum install httpd

## apacheを起動
    systemctl start httpd

## サーバーの起動とともにapacheが自動で起動するように設定
    systemctl enable httpd

## http通信とhttps通信を許可するようにファイアーウォールを設定
    firewall-cmd --zone=public --add-service=http --permanent
    firewall-cmd --zone=public --add-service=https --permanent

## ファイアーウォールを再起動
    firewall-cmd --reload

## Pythonのために必要なパッケージをインストール
    yum groupinstall "Development Tools"
    yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel
    yum install httpd-devel python-devel wget

## Python3系のインストール
CentOSにはデフォルトでPython2系がインストールされていますが、
mod_wsgiを利用するにはPython3系が必要なのでインストールします。

    cd /usr/local/src
    wget https://www.python.org/ftp/python/3.7.9/Python-3.7.9.tgz
    tar zxvf Python-3.7.9.tgz
    cd Python-3.7.9
    ./configure --enable-shared
    make && make altinstall
    ln -s /usr/local/bin/python3.7 /usr/bin/python3
    ln -s /usr/local/lib/libpython3.7m.so.1.0 /lib64/
    python3.7 --version　//Pythonのバージョンが3.7.9になればOK
    ln -s /usr/local/bin/pip3.5 /usr/bin/pip3.7
    pip3.7 --version //pipのバージョンを確認

## mod_wsgiのインストール
    cd /usr/local/src
    wget https://github.com/GrahamDumpleton/mod_wsgi/archive/4.5.6.tar.gz
    tar zxvf 4.5.6.tar.gz
    cd mod_wsgi-4.5.6
    ./configure --with-apxs=/bin/apxs --with-python=/usr/local/bin/python3.7
    make && make install
    chmod 755 /etc/httpd/modules/mod_wsgi.so 

## Flaskのインストール
    pip3.7 install flask

## アプリケーションの設定
ディレクトリ構成はこんな感じ
- /var/www/html/
        - app.py
        - application.wsgi

## app.pyファイルの設定
```Python:app.py
import sys

from flask import Flask,request

app = Flask(__name__)

@app.route("/")
def index():
    return "Hello, World"

if __name__=="__main__":
    app.run()
```


## application.wsgiファイルの設定
```Python:application.wsgi
import sys
sys.path.insert(0,"/var/www/html")
from app import app as application
```

## （追記）Blueprintでアプリケーションを分割している場合のapplication.wsgiファイル

```Python:application.wsgi
import sys
sys.path.insert(0,"/var/www/html")
from app import create_app
application = create_app()
```

## flask.confの追加
etc/httpd/conf.d/flask.confを作成して以下を記述

```flask.conf
LoadModule wsgi_module ./modules/mod_wsgi.so
<VirtualHost *:80>
    WSGIScriptAlias / /var/www/html/application.wsgi
    <Directory /var/www/html/>
        Order deny,allow
        Allow from all
    </Directory>
</VirtualHost>
```

## apacheを再起動
    service httpd restart

## postgreSQLをインストール
    yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
    yum install -y postgresql-devel

## Pythonのライブラリをインストール
    pip3.7 install sqlalchemy
    pip3.7 install flask_login
    pip3.7 install openpyxl
    pip3.7 install psycopg2


PostgreSQLとアプリケーションの連携は、[こちらの記事](https://qiita.com/outsider-kithy/items/807bac1f8191892f90c7)で。
EMアルゴリズムおよび変分ベイズを理解するための備忘録

VAE（変分オートエンコーダ）を理解するには、変分ベイズを理解せねばならず、そのためにはさらに遡って（以前少しかじった）EMアルゴリズムまで再度理解を深める必要があることがわかった。学習の備忘録として記載（よって、正しさは保証できない）。

## EMアルゴリズム
最尤推定（i.e. p(X|Θ)を最大化するΘの推定）のための手法の一つ。
混合正規モデルの推定を行う文脈においては、Θはパラメータμ（混合される各正規分布の平均）、Σ（混合される各正規分布の標準偏差）、π（各正規分布に対する重み）を含み、これらの値を推定する。
この問題は、クラスタリングの問題とのアナロジーで捉えることができる。
K-means法においては、各データ点のクラスタへの割り当て、クラスタのcentroidの更新の２ステージによって、クラスタ内分散の和を最小化する問題を解いている。
一方、EMアルゴリズムにおいては、とりあえず与えたパラメータから尤度を計算（Eステップ）、尤度を最大化するパラメータを求める（Mステップ）→さらにそのパラメータを用いてEステップを行う→ ... というプロセスを繰り返す。
使用した資料：　https://qiita.com/kenmatsu4/items/59ea3e5dfa3d4c161efb

以前勉強した時は、3-6-1〜3-6-3の箇所において、なぜ準備として尤度関数を微分をする必要があるのだ？というのがわからなかったが、これは「Mステップにおいて、尤度を最大化するパラメータ（最尤推定値）を求めるための準備」

### 学習中に湧いた疑問
・ MCMCとの関係は？
> EM アルゴリズムは山登り法の一種であり、局所最適解（local minimum）に陥る可能性があるのが問題ですが、MCMC は局所最適解にとどまらないという利点を持っています。
引用元：https://soonraah.hatenablog.com/entry/2014/10/06/081020

・　今回は、混合正規分布モデルの話だったので、クラスタリングの問題とのアナロジーで理解できたが、EMアルゴリズムを最尤推定に普遍的に使える理由は何か？
→ パラメータから尤度を求め、求めた尤度からそれを最大化するパラメータを求めてあとそれを繰り返す、というプロセスは普遍的に使えそう
→ 新たな疑問としては、なぜこのプロセスを繰り返すと、山を登れるのか？というところ（ただ、直感的にはMプロセスで最大化しているわけなので、落ちることはなさそう）。ここで下界とかの話になるのだろうか？　収束する保証はあるのか？とかそういった観点も疑問
→ 4章に解説あり。
クラスタリングにおいて、クラスタの割り当ての箇所が、q(Z)（Zは潜在変数、q(Z)はZに関する確率変数...**この箇所がイマイチわかっていない**）を最大化していく過程（すなわちEステップ）に対応しているという理解。

・　なぜK-meansと違って、単純に解けないのか？
→ log-sumが出てくるから？

## 変分ベイズ
モチベーションはEMアルゴリズムと同じでパラメータ推定。
EMアルゴリズムでは、パラメータを点推定するが、変分ベイズでは、ベイズ推定のコンセプトに基づき、「パラメータの分布」を仮定する。
→ これによって、単峰性ではない問題にも対応可能であり、かつ過学習にもなりにくい（点推定が有効ではないバイオインフォマティクスの問題に使われるらしい）
最大化するのは尤度ではなく、対数周辺尤度。
この資料がわかりやすかった。
https://tips-memo.com/python-vb-gmm#i-6

> EMアルゴリズムでは，真の事後分布を計算できるという立場を取るため，KLダイバージェンスをにする近似事後分布を求めることができました。一方で，変分ベイズでは真の事後分布を計算することができないという立場を取るため，近似分布が真の事後分布と厳密に等しくなることはないと仮定します。
引用元：　https://academ-aid.com/ml/vb

> 最尤推定 (EM) と違い, 過学習を自動的に防ぐ
https://www.ism.ac.jp/~daichi/paper/vb-nlp-tutorial.pdf

### 学習中に湧いた疑問
・ 何がベイズ？
→ パラメータの点推定ではなく、確率変数として推定しているところ。

・　変分ってどの箇所のことを指してる？
→  まだ理解に至っていない
はじプロでのゲーム制作

はじプロに限った事ではないのですが、自分はゲームを作るとき、操作性や効果性を念頭に入れて制作しております。

１１月からリスペクト制作しているF-ZEROも、見た目はF-ZEROらしく速さを重視していますが、効果性による見た目の速さであり、一定の操作性を維持する為に実速度はそれほど速くありません。

前回リスペクトした”F-ZEROハイパーデトネーター”は、オマージュとしてアレンジしてあるのですが、速さに関しては、実は再現性よりも実速度の速さの研究対象として制作していました。

結果として、作品としては操作性に難ありとして出来上がってしまいましたが、操作可能な最高速度や、それをより速く見せる為の自機のスケールダウンの施行…いわゆるスケールスピード法を採用したりなど、速く見せる為の手法のデータ群としてはいいところに落ち着いたのではないかと自負しております。


今回のF-ZEROですが、実機(SFC版)のマスタークラスの特別エンディングでもわかる通り、実はSFC版オリジナルはそれほど実速度が早い訳ではなく、あの速く見える映像は、拡縮機能による映像的恩恵であるようなところが伺えます。

その辺りを踏まえ、今回のF-ZEROは、視覚効果による速度感とコーナーの視認性の向上による遊びやすさを目指して作成しました。

今回は、前回のスケールスピード法を活用し、テクスチャを使って最小の0.1サイズで自機を作成、カメラをアップさせて速度感を出しています。
(これはコースを広く取る為の手法でもあります)

画角は変更せず、初期値の６０前後辺り(推定)、自機0.1mに対して道幅を2.4mに設定(幅割合24倍)、コースの幅を相対的に広くして感覚的な速度感を落としつつ(操作しやすくする為)、演出としての速度感は、ワールドのテクスチャを細かく書くことにより発生する視覚効果を用いています。

これらは、背景(ワールドのテクスチャのスクロール)によるスピード感をプレイヤーに与えつつ、コースの速度感を遅くさせて視覚情報であるコーナーの視認性を向上、遊びやすくさせるという狙いがあります。

ただし、操作性を深めるため、コーナーリング時の横滑り効果も導入させてるので、プレイヤーが操作技術を獲得する(つまり操作に慣れる)のに一定の期間が要されます。

その辺りは、ノービスクラスや操作練習用のステージを導入し、それらにも一定のゲーム性を追加して遊びながら習得できるようにして解決できるよう検討しています。


ちなみに、前回のハイパーデトネーターの操作性の悪さの原因は、実速度が速い為に高い動体視力が必要な事でした。
また、実速度が速いがゆえに、コーナーのRに対して、自機のコーナーリング性能が合わないRがある、というのも原因の一つでした。

さらに、コースアウトをリスタートに設定していた為、操作に慣れる前にコースアウト→リスタートとなり、playerの操作学習をする機会を少なくしていたのも関連した要因として考えられます。

以上の点を踏まえて今回のF-ZEROは制作しており、前回のハイパーデトネーターが、多少なりとも手法データ群として役に立っているのかな〜と感じている次第であります。

また、その他の視覚効果、聴覚効果についても色々とやっているのですが、長くなるのでとりあえず今回はこの辺までにしておきます。
(次回があるかはわかりませんが…)

こういった書物に書き慣れておらず、拙い文章となってしまいましたが、最後までご覧いただき誠にありがとうございました。
m(_ _)m
TypeScript : ユニオン型

## ユニオン型
ユニオン型とは、A型またはB型として表現できる型。 
複数の型に使用することができる。 

## 基本的な使い方
```TypeScript
// ユニオン型で定義
type StringNumber = string | number;

// StringNumber型は、文字列と数値の両方を含むことができる
const StrObj: StringNumber = "abcdefghi";
const NumObj: StringNumber = 123456789;

// どちらの型も出力出来る
console.log("StrObj type is " + typeof StrObj + " : " + StrObj);
console.log("NumObj type is "+typeof NumObj + " : " + NumObj);
```

## 複数で使う場合
```TypeScript
// 複数の型を定義
type Tiger = {
    tigerSound: string;
};
type Gorilla = {
    gorillaSound: string;
};
type Crow = {
    crowSound: string;
};
type Pig = {
    pigSound: string;
};

// 複数の型をUnion型にまとめて、Animal型とする
type Animal = Tiger | Gorilla | Crow | Pig;

// Animal型に複数の型を定義することができる
const tigerObj: Animal = {
    tigerSound: "Roar !"
};
const gorillaObj: Animal = {
    gorillaSound: "Ooh ooh !"
};
const crowObj: Animal = {
    crowSound: "Caw caw"
};
const pigObj: Animal = {
    pigSound: "Oink oink"
};

// Animal型の各値は、それぞれの値を含んでいる
console.log("Tiger sound is " + tigerObj.tigerSound);
console.log("Gorilla sound is " + gorillaObj.gorillaSound);
console.log("Crow sound is " + crowObj.crowSound);
console.log("Pig sound is " + pigObj.pigSound);
```

## 出力サンプル
$ npx tsc  
$ node dist/index.js  
StrObj type is string : abcdefghi  
NumObj type is number : 123456789  

Tiger sound is Roar !  
Gorilla sound is Ooh ooh !  
Crow sound is Caw caw  
Pig sound is Oink oink  

## Node.js
TypeScript をコンパイルして実行するために Node.js をインストール。  

https://nodejs.org/en/  
 note : 安定板である偶数番がオススメ

バージョンチェック
$ node -v  

## GitHub
https://github.com/GL-Kageyama/TypeScript_UnionType