OmniAICreator/Qiita-1.07M huggingface dataset:
Google Cloud SDK のエミュレータをDockerで使う時に死ぬほどハマった

すげーアホなことで2時間ほどハマりました。忘れそうなので備忘録として残しておきます。

gcloud を使って firestore のエミュレータを以下のような docker-compose 設定で Docker コンテナ内から起動するとうまく接続できません。

```
version: "3.9"
services:
  firestore:
    platform: linux/amd64
    image: gcr.io/google.com/cloudsdktool/cloud-sdk:352.0.0-emulators
    ports:
        - 6641:6641
    command:
      - gcloud
      - beta
      - emulators
      - firestore
      - start
      - --host-port=localhost:6641
  backend:
    platform: linux/amd64
    build: ./backend
    depends_on:
      - firestore
    environment:
      - FIRESTORE_EMULATOR_HOST=firestore:6641
    ports:
      - 6640:6640
```

原因は --host-port で指定しているホストが localhost だと docker-compose のデフォルトネットワークにバインドしてくれないからで、ここをサービス名である firestore にすると通るようになります。

```
version: "3.9"
services:
  firestore:
    platform: linux/amd64
    image: gcr.io/google.com/cloudsdktool/cloud-sdk:352.0.0-emulators
    ports:
        - 6641:6641
    command:
      - gcloud
      - beta
      - emulators
      - firestore
      - start
      - --host-port=firestore:6641
  backend:
    platform: linux/amd64
    build: ./backend
    depends_on:
      - firestore
    environment:
      - FIRESTORE_EMULATOR_HOST=firestore:6641
    ports:
      - 6640:6640
```

HTTPサーバとかだと普通に localhost:5000 とかにバインドするから全然気にしてなかった......
WordPress化までの流れ

1年ぶりにホームページの制作を請け負い,楽しくマークアップとJSを用いたコーディングが終了し、先方も見た目には大満足。

順調に進んでいるかと思いきや、WordPress化しようとしたら想像以上に忘れていることが多く手間取ってしまいました。
そこで次のホームページ制作を請け負うのは何年後になるかわかりませんが、1連の流れをドキュメントとして残しておこうと思います。
※こんなことをやるな〜という程度の記事です。初学者には説明が足りなさすぎるし、基礎を網羅している人には浅すぎる話なので完全に忘れかけてる人が対象ですね笑

## MAPMの起動
こいつを使ってまずはローカルでワードプレス環境を作ります。
### データベースの作成
WorPressをインストールする際にデータベースのユーザー名などを問われるのでphpMyAdminにアクセスしDBを作成。そしてユーザーアカウントのも自分は作ります。
### WordPressのインストール
インストールする場所はここ！

``` shell
Applicaion/MAMP/htdocs
```

## ワードプレス化
### index.htmlを3つのファイルに分ける
index.html
↓
index.php
header.php
footer.php

### style.cssの追加
index.phpと同じ階層にテーマの詳細を記入したcssファイルの追加

```css
/*
Theme Name: テーマの名前
Theme URL: URL
Description: ディスクリプション
Version: 1.0
Author: 著者
Author URI: 著者のプロフURL
*/
```

### 固定ページの作成
page-スラッグ.phpにファイル名&拡張性変更
管理画面からテンプレートを選択できるように名前の設定をファイルの先頭に入れる

``` php 
<?php
/*
Template Name: page-company
*/
?>
```

##　インストールしたプラグイン
### 投稿複製
「Yoast Duplicate Post」
ワンクリックで投稿を複製できるのは最高です！！

https://wordpress.org/plugins/duplicate-post/
### お問い合わせ
「contact form 7」
問い合わせ作成と言ったらこれです！お馴染みのやつですね！
もろもろ設定が終わったらエディタにこのように貼り付けでソースの実装は完了！
楽すぎますね！！

``` php
<?php
  echo do_shortcode('[WordPressが生成した任意の値が入ります]');
?>
```

https://ja.wordpress.org/plugins/contact-form-7/

### SEO対策用
「All In One SEO Pack」
久しぶりに見るとかなり変わっていてどれか見つけられませんでした笑

https://ja.wordpress.org/plugins/all-in-one-seo-pack/

## その他ちょっとした設定
### OGP設定
OGP設定はざっくり3つの設定方法があります。

1. HTML（herder.php）の<head>タグないに直書き
1. function.phpに記述
1. プラグインで設定

自分は応用が効く（投稿に画像があるかやサムネイルがあるか等の条件分岐ができる）のでfunction.phpのテンプレをコピペで設定してます。
--追記
AllInSEOの設定の幅が広がっていたのでfunctions.phpの設定はせずにプラグインで対応

## その他
ここからはワードプレスとか全く関係ないかもしれませんがサイト向上につながりそうなこと載せておきます。
### 動画の圧縮
今回はファーストビューに動画を載せるのですがまさかの36MB笑笑
音声なしのリピート映像は3MB前後に収めたいところですね！！
オンラインの動画圧縮ツールを使っても20MBまでにしか圧縮できなかったので専用の「HandBrake」というアプリインストールして圧縮しました。

https://liginc.co.jp/342227


## SEO対策
### h1タグについて
TOPページではlogoにh1タグを使用しています。
→TOPのみimgタグのalt属性を読み取ってもらえるため。
しかし、`下層ページではlogoにh1タグを使うのはNGとされている`のでheaderの使い分けが必要ですね！
haderをtop用とそれ以外で分けるのは修正するときの工数が増えるので1つのheaderファイル内で条件によって表示分けをします。

```php
<?php if ( is_home() || is_front_page() ) : ?>
  ここにトップページにだけ表示したいHTMLを記載
<?php else : ?>
  ここにトップページ意外に表示したいHTMLを記載
<?php endif; ?>
```

### OGP設定
上記に記載したとおり

### 全画像の圧縮
これは必須ですね！

### タグの設定
* sectionタグ h2タグの設置
* altの設定

### グーグルサーチコンソールの設定
https://search.google.com/search-console/

こちらより設定

### サイトマップ送信
［JavaScript］fetch メソッド

#### コード
```sample.html
<html>
<body>
	<input id="station">
	<button id="button" onclick="fetchAPI()">検索</button>

	<div id="stationList">
	</div>

	<script>
		function fetchAPI(){
			console.log("処理を開始します");
			const name = document.getElementById('station').value
			console.log(`入力された駅名: ${name}`);

			// fetch メソッドは Promise を返す
			fetch(`https://api.ekispert.jp/v1/json/station?key=YOUR_ACCESS_KEY&name=${name}`) 
			.then(function(result){
				return result.json();
			}).then(function(result){
				return result.ResultSet.Point;
			}).then(function(result){
				var count = 0;
				var station = "";
				for (element of result){
					console.log(element.Station.Name);
					count += 1;
					station += `${element.Station.Name}\n`;
				}
				document.getElementById('stationList').innerText = `${station}駅候補計${count}件\n`;
			}).catch(function(){
				alert("エラーが発生しました");
				console.log("エラーが発生しました");
			}).finally(function(){
				console.log("処理を終了します"); // エラー発生有無関わらず、最後に必ずこの処理を実行する
			})

		}
	</script>
</body>
</html>
```

#### 実行結果
テキストフィールドに「大阪」を入力し、「検索」ボタンをクリック
![スクリーンショット 2021-08-13 1.24.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199441/6736ec8f-5541-7616-5689-bcb0bef0f9e9.png)

#### 参考資料
[非同期処理:コールバック/Promise/Async Function - JavaScript Primer](https://jsprimer.net/basic/async/)
[駅すぱあとWebサービス](https://docs.ekispert.com/v1/)
【4章】Javaを学ぼう

#真偽値・比較演算子

##真偽値について
真偽値には「true」と「false」という2つの値しか存在しません。
trueは真、falseは偽を意味するもので、真偽値のデータ型はboolean型です。

```java:boolean型の変数定義
boolean bool = true;
```

##比較演算子について
比較演算子とは、値を比較するための記号であり、比較した結果は真偽値（trueもしくはfalse）になります。

```java:
a == b
// aとbが等しい場合はtrue
// aとbが等しくない場合はfalse

a != b
// aとbが等しくない場合はtrue
// aとbが等しい場合はfalse
```

「a == b」はaとbが同じかどうかを比較し、同じであればtrue、違っていればfalseとなります。また「a != b」はその逆になります。
実際の数値を入れた場合の例を見ていきたいと思います。

```java:Main.java
7 + 2 == 6 ・・・・・ false

7 + 2 != 6 ・・・・・ true

6 / 2 == 3 ・・・・・ true

6 / 2 != 3 ・・・・・ false
```

##真偽値を出力
真偽値も出力することができますが、trueやfalseはダブルクォーテーションで囲んではいけません。囲んでしまうと出力されませんので注意しましょう。

```java:Main.java
System.out.println(true);   // ダブルクォーテーションは不要
System.out.println(false);  // ダブルクォーテーションは不要
System.out.println(7 + 1 == 6);
System.out.println(7 + 1 != 6);
```

出力結果↓

```java:コンソール
true
false
false
true
```

##大小比較について
<, >という記号は数学でも用いる大小比較の記号です。x < yはxがyより小さければtrue, 大きければfalseを返します。x > yはその逆になります。また数学で同様に用いる≦, ≧という記号は、<=, >=と記述します。

```java:
x < y       // yの方が大きい場合はtrue
x <= y      // yの方が大きいまたは等しい場合はtrue

x > y       // yの方が小さい場合はtrue
x >= y      // yの方が小さいまたは等しい場合はtrue
```
それでは実際の数値を入れた場合の例を見ていきたいと思います。

```java:Main.java
3 + 4 > 7 ・・・・・ false

3 + 4 >= 7 ・・・・・ true

6 / 2 < 3 ・・・・・ false

6 / 2 <= 3 ・・・・・ true
```

今回の記事では真偽値、比較演算子について説明させていただきました。次章では論理演算子について記事を書いていきたいと思います！
最後までご覧いただきまして、ありがとうございました！
LinuxディストリビューションとOSの構造についてまとめました

今回、今更ですがLinuxってなんかいっぱいあるなという浅い認識止まりだったので、
Linuxディストリビューションと言われているものについてと、
また調べていく中でそもそもOSの構造わかってないと改めて認識したので、
OS構造についてとまとめてみました。

Linuxディストリビューションの役割を本当の意味で理解するにはOSの構造が重要ぽかったので、深くみてみました！（カーネルだけではOSは機能しないのでディストリビューションを利用する）

参考URL
https://www.linuxacademy.ne.jp/lablog/infrastructure/266/
https://qiita.com/tatsuya4150/items/f830c9b2ae33275aef42
https://www.geekly.co.jp/column/cat-technology/1910_023/
http://ss.sguc.ac.jp/~rider/unix/unixos.html


#Linuxについて

そもそもLinuxという言葉はLinuxカーネルを指して言われており、
OSはカーネルだけでは機能しないので、後述する他構造のデーモンやシェルなどを含んで初めて機能する。

この足りないOSの箇所を補ったLinuxのいわばパッケージがディストリビューションと呼ばれるものである。

有名どころでは、
RedHat centOS Ubuntuなどがある。

#OS構造

OSの構造はいくつかに分けられていてる。
よく例えられるのが「車」である。

車をOSとした時、それを構成するタイヤ、エンジンなどがカーネル・シェルなどになる。

上のLinuxの話をここの話を交えてもう一度まとめると、
「OSとして機能を持たせた（車として機能持たせた）ものがディストリビューションにあたる」ということになる！

会話の中で「OS何？」という問いに対して「Linux」という答えだけでは不十分で、
「CentOS」まで答えないとダメみたいなイメージ！（分かりにくいかな笑）

少し話が逸れてしまいましたが、そのパーツにあたる構成の中身を見ていくと、

ブートローダー：OSを起動させる役目
カーネル：OSの中核。ソフトウェアとハードウェアとの間を取り持ってくれている
デーモン：メモリ上で常駐しているプログラム
シェル：コマンドプロントなどの人間からコンピュータへ指示するプログラム
デスクトップ環境：操作しやすいデスクトップを提供
アプリケーション：必要最低限なものしかない（ファイル管理、ブラウザ、各種設定、メール）

ざっくりとこんな感じ。

#最後に

今回のまとめでそもそもOSとはとその中身とLinuxについての概要のイメージを掴むことができました。今年中にLPIC３まで取りたいので、引き続きLinuxの勉強頑張ります！
Rubyの環境構築

*Vscodeを使う前提

#Rubyのバージョン

macOsには、はじめからRubyが導入されている。

```
$ ruby -v
```

*PCには基本的に1つのバージョンしか入らない
プロジェクトによってRubyのバージョンを切り替える。
これを簡単に行いたい

#バージョン管理ツール　rbenv
⚫︎rbenv
Rubyのバージョン管理ツール
使用するRubyのバージョンを簡単にきりかえられるもの

#公式ドキュメントを確認し導入する
rbenvはGithubで公開されている。公式ドキュメントをもとに
導入を進めていく。

*公式ドキュメントは基本英語なので英語に慣れていくのがいい。

https://github.com/rbenv/rbenv

⚫︎インストール 2021年8月12日現在
 macOsでHomebrewを使ったインストール
上の記事を参考にrbenvを導入してください。


#readlineのインストール(日本語化)

```
$ irb 
irb(main):001:0> "うううう"

=>文字化けする　　　　　　　　　#irbと入力するだけで、Rubyのコードを実行できる
#デフォルトだと日本語を入力すると文字化けする

```
⚫︎readlineのインストール

```
$ brew install readline
```

# ~/.zshrcの設定

```
$ echo `eval "$(rbenv init -)"` >> ~/.zshrc

```
zsh(ターミナル)が立ち上がった時に自動的にrbenvが使用されるようになる
*すでに上で作業はやっているのでこの作業は必要なし

#Rubyのインストール
*ここでは2.7.1のバージョンを入れる。

```
#利用できるバージョンの確認
 $ rbenv install -l 
 
#Rubyのバージョンのインストール
$ rbenv install 2.7.1
*少し時間かかる

#新しいバージョンのRubyをインストールした後、実行
$ rbenv rehash

#バージョンの確認
$ rbenv versions

#全体で使うrubyのバージョンを使うもの
$ rbenv global 2.7.1

*バージョンの確認
$ rbenv versionsでバージョンが変わる

#rubyのバージョン確認
$ ruby -v

#プロジェクトで使われるrubyのバージョンを固定
 $ rbenv local <version>  .ruby-versionが作成される


```

#Gemのインストール
⚫︎Gemとは
RubyGemsが公開しているライブラリ(使いやすい形でまとめたコードの集まり)
Gemが公開されていることで同じツールを使いたい方が各々で作る必要がなくなる。

⚫︎以下のGemをインストール
・bundler gemのバージョンや依存関係を管理してくれるgem
・pry-byebug デバックをする時に使う
・pry　　Rubyのirbのようにrailsのコンソールでメソッドなどを使えることができるようになる機能
・pry-doc Cで書かれたRubyのソースコードを表示できshow-sourceコマンドを利用出来る

```
$ gem install bundler pry pry-byebug pry-doc
```
because it has an invalid code signature, inadequate entitlements or its profile has not been explicitly trusted by the user.と出た時の解決法

#はじめに
Apple Developerで証明書を作成しただけでは実機でRunできずド忘れして詰まったので、その解決法。

#起きた現象

![Screen Shot 2021-08-12 at 11.52.41 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300780/6d73a028-3004-1636-5210-8fc017654be1.png)

このようなエラーが起きてRunできない

#解決法

実機の設定Appから
一般 → プロファイルとデバイス管理で「Trust "Apple Development: XXXXX"」を押す。
そうすることでRunできるようになる
入力された日付が存在するか判定させる。

#今回の内容
 * TextFieldに`例 -> 2021/08/12` で入力された日付が存在するか判定します
 
 * 今回は、月は12月まで、日付は31日までと仮定して進めます。(28日,29日,30日までしか無い月もありますが今回は無視します)
 
# コードと簡単解説

* `.addTarget()`で判定させるために処理を追加します。

```Swift:
  deadlineDayTextField.addTarget(self, action: #selector(judgeText), for: .allEditingEvents)
```
 
* まずは、入力された文字が指定の文字数になったら"/"を追加する様にします

* 今回は、日付が10文字入力された時に`Int((sender.text?.components(separatedBy: "/")[1])!)`と`Int((sender.text?.components(separatedBy: "/")[2])!)`でTextField.textから年と月と日付を分解します。

* `Int((sender.text?.components(separatedBy: "/")[1])!)`が12より大きいなら、TextField.textを空にします。

* `Int((sender.text?.components(separatedBy: "/")[2])!)`が31より大きいなら、TextField.textを空にします。

```Swift:judgeText
    @objc func judgeText(_ sender:UITextField){
        
        if sender.text?.count == 4{           
                        
            sender.text = sender.text! + "/"                                    
            
        }else if sender.text?.count == 7{            
            
            sender.text = sender.text! + "/"            
            
        }else if sender.text?.count == 10{
            
            if Int((sender.text?.components(separatedBy: "/")[1])!)! > 12 {
                
                alert.warningAlert(messageContents: "月", alertTargetView: self)
                sender.text = ""
                
            }else if Int((sender.text?.components(separatedBy: "/")[2])!)! > 31{
                
                alert.warningAlert(messageContents: "日付", alertTargetView: self)
                sender.text = ""
                
            }
        }       
    }
```

* `.components(separatedBy: "/")`は分解後、配列に値が入ります。

```Swift:
print(sender.text?.components(separatedBy: "/") as Any)
```
```:デバッグエリア
(["2021", "08", "12"])
```

#終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
[Nim] enum にエイリアスを付ける。または class method を実現する。

# まとめ
`typedesc[SomeObject]`を第一引数にとろう。型に対して関数が定義できる。

# enumにエイリアス

```nim:enumDef.nim
type SomeEnum {.pure.} = enum
  ValA
  ValB
  ValC
type OtherEnum {.pure.} = enum
  ValA
  ValB
  ValC

template AliasA(someEnum: typedesc[SomeEnum]): SomeEnum =
  SomeEnum.ValA

assert SomeEnum.ValA == SomeEnum.AliasA
# error!
# assert SomeEnum.ValA == AliasA
# assert SomeEnum.ValA == OtherEnum.AliasA
# echo OtherEnum.AliasA
# echo AliasA

template defineAlias*(TEnum: typedesc; value, alias: untyped): untyped =
  template alias*(tEnum: typedesc[TEnum]): TEnum =
    TEnum.value

SomeEnum.defineAlias(ValB, AliasB)

assert SomeEnum.ValB == SomeEnum.AliasB
```

# class method

```nim
type Object = object
  value: int
var `Object.staticmember`: int = 10

proc init(TObject: typedesc[Object]; value: int): Object =
  Object(value: value)
template staticmember(_: typedesc[Object]): int = `Object.staticmember`

echo repr Object.init(10)
# stdout: 10

echo Object.staticmember
# stdout: 10
```
VSCodeでTomcat for Javaが起動できない

#vscodeでTomcat for javaが起動できない

Tomcat for Java で下記のようなエラーが出て解決策を見つけたので書きます。

![スクリーンショット (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893794/d1c0c54e-9c96-4927-6141-924ffb092ad5.png)

これは、java.home(vscodeの設定)のjavaファイルが**OS(C:)**の下に置いていないのが、原因です。


windowsのファイルパスがTomcatサーバーでうまく読み込まれないのが主な原因みたいです。
>上記の文は、https://teratail.com/questions/291816より引用

なので、

**<修正前>**
![スクリーンショット (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893794/9d2f5236-d5b1-c324-f20d-4017e2a633e3.png)
から

**<修正後>**
![スクリーンショット (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893794/b3ebfa20-0ae0-3851-3e6a-2ada497a45c0.png)

のように直したら、tomcatが動くと思います。
かいけつ

<補足>
・java.configuration.runtimesのPathは、C直下でなくても起動します。

<参考>
>teratail(VSCodeでTomcatが突然起動できなくなりました)
>https://teratail.com/questions/277744
teratail(VScodeでTomcatに接続できない)
>https://teratail.com/questions/291816
ヘルパーメソッドのパスを知る！

# はじめに
本記事では、`form_with`についてまとめました。
本日、深掘りした内容になりますので、アウトプットいたします。

# ヘルパーメソッド
Railsにおける、主にビューでHTMLタグを出現させたり、
テキストを加工するために使用されるメソッドの総称です。
以下のようなものがあります。

|ヘルパーメソッド|使用用途|
|------|------|
|form_with|投稿ページなど、情報を送るためのフォームの実装|
|link_to|リンクの実装|

他にもたくさんのヘルパーメソッドがありますが、初めに学習するものは上の２つです。

## パスについて
パスの指定方法は、大きく分けて２種類あります。
①URL(URIやPrefixを記述する方法)
②modelオプション

### URL(URIやPrefixを記述する方法)
例えば、

```erb
<%= link_to "編集する", edit_prototype_path(@prototype), class: :prototype__btn %>
```

`edit_prototype_path(@prototype)`
ここの部分です。

`データベースに保存しないパスの方法`としてよく用いられております。
レコードに生成した情報を保存・追加しないということです。

これまで学習したアプリケーションを確認していると
`index→show`に画面遷移する際など、直接的にデータを保存せず、
ただ`ページを遷移`する際に多く使われている印象です。

#### 「url:」の有無
付けることによる弊害は特に無いです。
付けるか付けないかは、保存先のコントローラーでない場合には付けます。
↑後述のFormオブジェクトの話です。

不安であれば、付けておけば問題ありません。

### modelオプション
例えば、

```erb
<%= form_with model: prototype, local: true do |f|%>
```

`model: prototype`
ここの部分です。

`データベースに保存するパスの方法`としてよく用いられております。
URLの逆で、レコードへ生成したものを保存・追加するということです。
ですので、`new`や、`edit`のファイルで使用されている印象があります。

#### 削除するためのパス

```erb
<%= link_to "削除する", prototype_path(@prototype), method: :delete, class: :prototype__btn %>
```

`prototype_path(@prototype)`
ここの部分です。

こちらについては、両方用いられております。
URLの方が見やすく、使用しやすいため、URLを利用されることが多いです。

## URLとmodelオプションの両方を使う場合
例えば、

```erb
<%= form_with id: 'charge-form',url: item_purchases_path(@order_form) ,model: @order_form ,class: 'transaction-form-wrap',local: true do |f| %>
```

`url: item_purchases_path(@order_form) ,model: @order_form`
ここの部分です。
前述での、`url:`を付けるかどうかの話はここです。

### ２つ使う理由
`Formオブジェクト`を使う際に、両方使用します。

例えば、商品を購入する際、
`発送する住所のテーブル`と`購入記録のテーブル`に対して、
Formオブジェクト（上のコードでは`order_form`をFormオブジェクトにしています）を使っているとします。

当時の私はこう考えました。

購入ページへ遷移後、
その購入ページから購入ボタンを押し、
`発送する住所`と`購入記録`の情報を保存するものだと考えていたため、
まずここでは、`modelオプション`を使うのだと思いました。

ただ、ここでは、`Formオブジェクト`を使用しているため、
order_formへ保存をしたいわけではなく、
その後から、`発送する住所と購入記録に仕分け`し、
それらへ保存したいため、やはりmodelオプションは使わず、
`URLパスを使用する`、と判断しました。


しかし、発送住所と購入情報のデータに保存をするためには、
`order_formを通って`一時的にorder_formへ送らないといけない(保存みたいな？)ことから、
`２つ（URLとPrefix）を使用する`のだと思いました。

```
要するに、
情報をテーブルに保存するために、
中間にいるFormオブジェクトへワンクッション置いて（URL）、
正式なテーブルへ保存(Prefix)する、そんなニュアンスです。
```

```
フォーム送信
↓
Formオブジェクト（ここでワンクッション）
↓
いろんなテーブル（今回だと発送する住所と購入記録のテーブル）
```

### 他に使用するケース
ほとんどないと思います。
例えば、
`modelオプションを使用しても、画面が遷移されない時`
とかだと思います。

# 終わりに
この辺は私にとってかなりの鬼門でした。
なかなか理解できず、
うまくパスが記述できずに、エラーが出続けておりました。

毎日のように深掘りしなければ理解できないことばかりですが、
理解できて、それをコードで上手く表現できた時が一番嬉しいですし、
報われたみたいで、幸せになれます🤗

明日も頑張ります！！
VScodeでUbuntuのターミナルを使い仮想環境(venv)を作る方法

いろいろ調べていくうちにUbuntuを使える方がいいと考えました。
なのでまず、Ubuntuでの仮想環境の作り方をメモ代わりに記事を投稿させていただきます。
##作り方
pipを一応アップグレードしておきます。

```console:Ubuntu
pip3 install --upgrade pip

```
次に、Ubuntuではvenvが標準搭載されていないのでインストールしていきます。

```console:Ubuntu
sudo apt install python3-venv
```

インストールが完了したら以下のコードでターゲットディレクトリが制作できます。
ちなみに、ターゲットディレクトリの名前はmyenvとしています。

```console:Ubuntu
python3 -m venv myenv
```

最後に、以下のコードで仮想環境を有効化します。

```console:Ubuntu
source myenv/bin/activate
```

以上のことでUbuntuで仮想環境を制作することができました。

##インタープリターの選択
①まず、左下の緑のところがUbuntuのリモートが開けていることを確認してください。開けてない人はUbuntuの方で

```:Ubuntu
code .
```

とすることで開けると思います。
<br>
インタープリターの選択をするために左上の表示からコマンドパレットを開き「インタープリターを選択」を選びます。
②そこで、すでに仮想環境のPythonインタプリタ表示されていればそれを選びます。
③表示されていなければ手動でenter interpreter pathを選び、/myenv/bin/python3を選択もしくは入力していきます。
これにより④に示すようになれば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1752668/d92812b9-490e-3841-3439-c214b3c78cf9.png)

##参考文献
https://docs.python.org/ja/3.6/library/venv.html
GitHubActionsでブランチ名の参照

**GITHUB_REF_NAMEが使えるようになったのでそちらを使おう！**

https://docs.github.com/en/actions/learn-github-actions/environment-variables



**以下、太古の昔の手法です。
IT考古学的に、将来なんらかの文化的価値が出るかもしれないので保存しておきます。**

----


GitHubActionsでブランチ名を取りたいけど毎回忘れるのでメモ。

下記の環境変数と、gitコマンドによる取得を試しています。

https://docs.github.com/en/actions/reference/environment-variables#default-environment-variables

# 確認に使ったyamlファイル

```
name: Build

on:
  workflow_dispatch: # 手動で任意のブランチをビルドしたい
  pull_request:
    branches:
      - main         # mainあてのPRをビルドしたい
  push:
    branches:
      - main         # mainにPRがマージされてpushされたらビルドしたい
      - develop      # developにPRがマージされてpushされたらビルドしたい
    tags:
      - v*           # タグが打たれたらビルドしたい

jobs:
  prepare:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Set tag names
        id: tag_names
        run: |
          echo "GITHUB_EVENT_NAME                         =" "${GITHUB_EVENT_NAME}"
          # git コマンドでの習得テスト (sedは、いろいろ試しているときの消し忘れなので気にしないでください)
          echo "git branch --show-current | sed 's|/|-|g' =" $(git branch --show-current | sed 's|/|-|g')
          echo "git rev-parse --short HEAD                =" $(git rev-parse --short HEAD)
          echo "git describe --tags --always              =" $(git describe --tags --always)
          # 環境変数での習得テスト
          echo "GITHUB_REF#refs/heads/                    =" "${GITHUB_REF#refs/heads/}"
          echo "GITHUB_HEAD_REF#refs/heads/               =" "${GITHUB_HEAD_REF#refs/heads/}"
          echo "GITHUB_BASE_REF#refs/heads/               =" "${GITHUB_BASE_REF#refs/heads/}"
```

# トリガーごとの動作

## 1. push branch

mainブランチをpushする。
(mainあてのPRがマージされたときも同じ)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53551/6a626a18-64d6-7456-f5ae-fbe747b792ce.png)

gitコマンドでも環境変数でも取れる。
`git describe --tags --always` はalwaysオプションつけているので、タグが無いときはコミットハッシュがとれています。


## 2. pull_request

`feature/test01` -> `main` のPRを作成。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53551/2d1de111-6f8e-8c50-da1f-aedc3fae6b32.png)

PRをマージした場合のcommit hashについて、ビルドしてdockerイメージを作りたい。
イメージのタグはPRもとのブランチ名にしたい。
そんなときは `GITHUB_HEAD_REF` から取る。


## 3. push tag

github web-ui から `v0.0.1` というリリースを作成。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53551/fd790ba5-19b5-2cab-a37e-386c91cbf5d8.png)

ブランチ名など存在しませんよ。


## 4. workflow_dispatch

github web-ui から `feature/test01` というブランチを選んで `Run workflow`。

<img width="400px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53551/c51a8277-a72a-496e-0556-0f23521f336e.png" />

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53551/13477506-01d3-3dd0-a852-ed6e22469e2e.png)

push branchとおんなじですね。


# まとめ

この記事を書いたことを覚えていますように :pray:
標本分散・不偏分散について可視化してみた

# はじめに
統計学の教科書の割と最初の方で出てくる「分散」ですが、「標本分散」と「不偏分散」というものが教科書に載っているはずです（最初に見たときはどう使い分けるのか悩んだものです）。

標本分散や不偏分散を母分散の推定量と見たとき、標本分散には不偏性がなく「標本分散の期待値」は母分散よりも小さくなってしまうという性質がある一方で（これはサンプルサイズが小さい場合に顕著です）、不偏分散には「不偏分散の期待値」が母分散に一致するという性質があります。
ですから、何らかの実験でデータを得たときにその結果から背後にある母集団の分散を推定したいような場合には不偏分散を用いることになります。一方、標本分散は得られたデータがどのように散らばっているのかを記述するために使うことになります。

今回は、母集団から適当なサンプルサイズで抽出したサンプルに対して標本分散・不偏分散を計算してサンプルサイズに対する標本分散・不偏分散の動きを可視化してみたいと思います。

※詳しい話は書籍やネットで「一致性」や「不偏性」で調べてください。今回問題になるのは不偏性の方です。

# 実験と結果
標準正規分布に従うサイズ1000000の母集団を用意します。

```Python
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns


np.random.seed(seed=42)
population = np.random.normal(0, 1, 1000000)  # 母集団：平均0, 分散1, サイズ1000000
sns.histplot(population)

plt.title('Population Distribution')
plt.show()
```
![Population.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213259/ca862365-d270-cdcc-4bfc-94e2eec7c4e1.png)



## 実験1
母集団からサンプルサイズ50で標本抽出を行い不偏分散と標本分散を求める操作を（とりあえず）1000回行いそれぞれの平均を求めます。

```Python
unbiased_variances = []
sample_variances = []


for _ in range(1000):
    # 母集団から50件の抽出を行い不偏分散と標本分散を求めるのを1000回
    sample = np.random.choice(population, 50)
    unbiased_variance = np.var(sample, ddof=1)  # 不偏分散
    sample_variance = np.var(sample, ddof=0)  # 標本分散
    unbiased_variances.append(unbiased_variance)
    sample_variances.append(sample_variance)
```

```Python
np.mean(unbiased_variances)
```
1.0042536587305344

```Python
np.mean(sample_variances)
```
0.9841685855559237

不偏分散の方がいい感じに母分散=1を推定できています。標本分散は少し小さめになっていることがわかります。

## 実験2
母集団からサンプルサイズ5～1000で変えながら標本抽出を行い、不偏分散と標本分散を求める操作を（とりあえず）1000回行いそれぞれの平均を求めます。最後にサンプルサイズに対して、標本分散・不偏分散の平均をプロットします。

```Python
sample_size_list = []
uv_mean_list = []
sv_mean_list = []

for sample_size in range(5, 1001, 5):
    # サンプルサイズを5～1000まで5刻みで変化させる。
    unbiased_variances = []
    sample_variances = []
    
    for _ in range(1000):
        # 母集団から指定サンプルサイズの抽出を行い不偏分散と標本分散を求めるのを1000回
        sample = np.random.choice(population, sample_size)
        unbiased_variance = np.var(sample, ddof=1)  # 不偏分散
        sample_variance = np.var(sample, ddof=0)  # 標本分散
        unbiased_variances.append(unbiased_variance)
        sample_variances.append(sample_variance)
    
    # サンプルサイズ、そのサンプルサイズでの不偏分散の平均・標本分散の平均を追加
    sample_size_list.append(sample_size)
    uv_mean_list.append(np.mean(unbiased_variances))
    sv_mean_list.append(np.mean(sample_variances))

df1 = pd.DataFrame({'sample_size': sample_size_list, 'mean_of_variance': uv_mean_list})
df1['variance_type'] = 'unbiased_variance'

df2 = pd.DataFrame({'sample_size': sample_size_list, 'mean_of_variance': sv_mean_list})
df2['variance_type'] = 'sample_variance'

df = pd.concat([df1, df2])

sns.lineplot(data=df, x='sample_size', y='mean_of_variance', hue='variance_type')
plt.show()
```
![ss_vs_mean_of_var.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213259/a635ada3-836b-fb46-f2d2-5390065ac1f9.png)

サンプルサイズの小さいところでは標本分散が母分散よりかなり小さくなっていますが、サンプルサイズを大きくするにつれて母分散=1とのズレが小さくなっていく様子を確認できます。

# 最後に
最初に見たとき標本分散と不偏分散の違いが直感的にすぐに頭に入ってこなかったのですが可視化するとそんなに難しくなかったなという感想です。
SwiftUIはweb開発に近いところを感じた

記事の期間が空いてしまいました。また最近アプリを作ってます。今度は仕事でSwiftUIを使う環境になったので一人で勉強した僅かなアドバンテージと一緒に仕事に励んでいます。Storyboardと比べるとやっぱりSwiftUIの方が簡単かなと思います。

私にとってSwiftUIはHTMLCSSに近い言語感覚を持っているので、どのくらい記事を書けるかわかりませんが感じたことをまとめていきたいと思います。

## HStack, VStack, ZStackについて
前回の記事でHStackとかで囲わないと2行以上、2列以上テキストなどを置けないということに気がついたのですが、囲わないといけない理由は探し出せていません。理由を知りたい気持ちはありますがそういうもんだと思って開発しています()

このHStack, VStack, ZStackは、web開発のイメージと近いところがありました。


### VStackのCSSイメージ
VStackはwebでいうブロック要素を縦に並べる挙動に見えました。SwiftUIでは自動的にcenteringされているのでcssで表記するとこんなイメージかな。

```html
<div class="vstack">
    <p>A</p>
    <p>B</p>
    <p>C</p>
</div>
```

```css
.vstack {
    text-align: center;
}
```

#### SwiftUI
<img width="320" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229502/60a62c49-b4c1-ba67-bee8-4e9079ed1836.png">

#### HTML,CSS
![vstack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229502/bfb68ebd-ef43-9d4c-ada6-bb5c8148b813.png)


### HStackのCSSイメージ
HStackは要素を横並びにするので私が好きなflexの挙動に見えました。あと並んだ要素は真ん中に寄るのでjustify-contentのcenterが自動的についてるイメージです。

```html
<div class="hstack">
    <p>A</p>
    <p>B</p>
    <p>C</p>
</div>
```

```css
.hstack {
    display: flex;
    justify-content: center;
}
```

#### SwiftUI
<img width="320" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229502/5edf6eb9-44bc-9169-6336-96d988637b31.png">

#### HTML,CSS
![hstack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229502/bc5b40ae-9588-2673-e186-bfa6db805d4a.png)


### ZStackのCSSイメージ
ZStackはPhotoshopとかで言うレイヤーをイメージしています。cssだとpositionのrelativeとabsoluteをセットしてz-indexで調整という感じですが、ZStackの要素は下に書いてある要素が上のレイヤーに来るのでhtmlで表現すると複雑になりました。

```html
<div class="zstack">
    <p>A</p>
    <p>B</p>
    <p>C</p>
</div>
```

```css
.zstack {
    position: relative;
    z-index: 0;
}

.zstack p {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

.zstack p:nth-child(1) {
    z-index: 1;
}

.zstack p:nth-child(2) {
    z-index: 2;
}

.zstack p:nth-child(3) {
    z-index: 3;
}

```

#### SwiftUI
<img width="320" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229502/481c4bf9-2249-8b74-e915-8d43aca3c857.png">

#### HTML,CSS
![zstack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229502/8b5ba8ac-ca12-427b-34ba-8e3feffbb251.png)


元々HTMLやCSSで並べていくのが楽しいのでSwiftUIの3つも近しいものを感じたので開発イメージが付きやすいです。

## 参考
https://developer.apple.com/documentation/swiftui/vstack
https://developer.apple.com/documentation/swiftui/hstack
https://developer.apple.com/documentation/swiftui/zstack
Influxdb-client-kotlinを使ってみた

InfluxDBを使ってみたかったので、AndroidからKotlin SDKでwrite/readを試してみた。

## 準備 Clientライブラリの追加

ライブラリを追加する

```gradle:app/build.gradle
    implementation "com.influxdb:influxdb-client-kotlin:3.1.0"
```

ライブラリバージョンは以下で確認できる。
2021/08/12時点では 3.1.0 が最新
https://github.com/influxdata/influxdb-client-java/tree/master/client-kotlin

## 実装

Androidで実装しているので、
View → Repository → ApiClientWrapper の順になるよう実装していく。
（ViewModelは ~~面倒~~ サンプルなのでスキップした）

### View
```kotlin:MainActivity.kt
        // 本来はDIすべき
        val repository = ApiRepository(InfluxDBClientKotlinWrapper())

        lifecycleScope.launch {
            withContext(Dispatchers.IO) {
                // サンプル用書き込み値
                val writeValue = Random.nextDouble(62.0, 65.0)

                // InfluxDBに書き込み
                repository.add(writeValue)
                // InfuxDBから読み取り
                repository.fetch().collect { record ->
                    Log.d("FLUXRECORD", record.value.toString())
                }
            }
        }
```

### Repository

```kotlin:ApiRepository.kt
class ApiRepository(private val influxDBClientWrapper: InfluxDBClientKotlinWrapper) {

    // これ必要？
    private val bucket = "k_ikemura's Bucket"

    /**
     * データ取得
     */
    fun fetch(): Flow<FluxRecord> {
        val query = """
from(bucket: "$bucket") 
|> range(start: 0) 
            """
        val results = influxDBClientWrapper.query(query)
        return results.consumeAsFlow()
    }

    /**
     * データ登録
     */
    suspend fun add(writeValue: Double) {
        influxDBClientWrapper.add(writeValue)
    }
```

### ApiClientWrapper

```kotlin:InfluxDBClientKotlinWrapper.kt
class InfluxDBClientKotlinWrapper {
    private val token = "dummy_token" // influxdb-cloudや自分の環境で用意する
    private val org = "dummy_org"
    private val bucket = "sample Bucket"
    private val url = "dummy_url"

    // 公式ライブラリのClientクラス TODO:DIで渡したい
    private val client: InfluxDBClientKotlin = InfluxDBClientKotlinFactory.create(
        url = url,
        token = token.toCharArray(),
        org = org,
        bucket = bucket
    )

    // 読み込み実行
    fun query(query: String): Channel<FluxRecord> = client.getQueryKotlinApi().query(query)

    // 使用が終わったらクローズする必要あり？（公式サンプルではクローズしてた）
    fun cloese() {
        client.close()
    }

    // 書き込み実行
    suspend fun add(value: Double) {
        val writeApi = client.getWriteKotlinApi()
        // 書き込み用データ、公式サンプルのコピペなので正式な値に修正すべき
        val temperature = Temperature("south", value, Instant.now())
        writeApi.writeMeasurement(temperature, WritePrecision.NS)
    }
```

上記を実行して、InfluxDB-Cloudで書き込み値の確認できたので、正常に動いてるっぽい。

## 参考にした情報
ライブラリのGitHub
https://github.com/influxdata/influxdb-client-java/tree/master/client-kotlin

公式ライブラリのドキュメント
https://docs.influxdata.com/influxdb/cloud/query-data/get-started/

ライブラリバージョン
https://mvnrepository.com/artifact/com.influxdb/influxdb-client-kotlin
【Rails】多数のテーブルが存在する場合においてアソシエーションの一覧を取得する

## 概要

本記事は数百個のテーブルが存在するアプリケーションの開発をしている中で、あるモデルがどのモデルに対してアソシエーションの関係があるかを一覧で把握したいことがあった際に、アソシエーションの情報を一覧で取得できるコマンドを考えた際のメモになります。

## コマンド

Railsコンソールで実行

### has_many

```ruby
hash = {}
tables = ActiveRecord::Base.connection.tables
tables.each do |table|
 value = table.classify.constantize.reflect_on_all_associations(:has_many).map(&:name) rescue false
 hash.store(table, value)
end
```

### has_one

```ruby
hash = {}
tables = ActiveRecord::Base.connection.tables
tables.each do |table|
 value = table.classify.constantize.reflect_on_all_associations(:has_one).map(&:name) rescue false
 hash.store(table, value)
end
```

### belongs_to

```ruby
hash = {}
tables = ActiveRecord::Base.connection.tables
tables.each do |table|
 value = table.classify.constantize.reflect_on_all_associations(:belongs_to).map(&:name) rescue false
 hash.store(table, value)
end
```

###　出力イメージ

```
"hoge"=>[],
"fuga"=>false,
"piyo"=>[],
"hogehoge"=>[],
"fugafuga"=>[],
"piyopiyo"=>[],
"hogefuga"=>[],
"fugapiyo"=>[:fugafuga, :hoge],
```
プログラミング言語ー動的・静的と型の強さ、弱さについてー

##プログラミング言語とは
データの**処理や計算**を行なってくれる言語のこと
→そこの観点から**HTML（マークアップ言語）やCSS（スタイルシート言語）**はプログラミング言語ではないです。

プログラミング言語は大きく分けて**動的型付け言語**と**静的型付け言語**の２つに分かれます。
また、静的/動的型付けでのプログラム要素の型を解釈（interpret）する際の性質として
**型の強さ・弱さ**という型の扱いの厳格さ、データ型の変換の際の欠けや、ゆるさがないかでさらに分けることができます。

##動的型付け言語・静的型付け言語について
ここでは動的型付け言語・静的型付け言語について説明していきたいと思います。
動的型付け言語と静的型付け言語の違いは
**変数に対して型を自ら宣言するか自動的に判定されるか**にあります。

動的型付け言語の場合、プログラム実行時（動いた時）に型の判定が自動的に行われます。
それに対し、静的型付け言語の場合はプログラムの実行前（実行していない時→静の時）に
型の判定が行われ、型がつくプログラムのみをコンパイル・実行します。


###型とは何か？
そもそも型というのはコンピュータなどのハードウェアで扱うことのできるデータの種類を意味しています。そしてここでいう型とは**データ型**のことを示します。
データ型とはあるデータがどのような性質を持っていて、どのように取り扱うべきかを定めたものです。典型的なものとしては整数型や文字列型などがある。それぞれの変数や値のデータ型に応じて、それを適切に扱うためのプログラムコードを記述する必要があります。

###なぜ型というものが必要なのか？
コンピューターは実際に処理を行う際、ソースコードを元に処理を行うのではなく、ソースコードがソフトウェアによって変換された機械語の情報をもとに処理を行います。
その機械語や物理メモリ上における抽象的な数字（０と１）の羅列に意味を持たせることが型の目的です

###動的型付け言語
・プログラムを実行時に型の変換が行われ型が決定されます。
・インタプリタ言語（直訳：翻訳者型言語）とも言われています。

・型の宣言（この型はこういうものですよという記述）を行う必要がないので、コードが静的よりも**シンプルで簡単**になりやすいという特徴がありますが、実際に実行した際、型に不整合が生じたらエラーとして表示されます。（ランタイム時）
つまりプログラムの字面に型の情報が登場せず、実行するまで型の判断はされないため、それまではエラーに気づけないというデメリットもあります。

・また、型の判定は実行時に一行ずつ行われるので静的型付け言語に比べ処理速度が遅くなってしまうというデメリットもあります。
しかし、型の判定を自動的に行うという面から静的な言語では記述できないような、柔軟なプログラミングができる可能性があります。

・動的型付け言語の例
→JavaScript,PHP,Ruby,Pythonなど

###静的型付け言語
・型付けが実行前に行われる言語のことでコンパイラと呼ばれるソフトウェアを使用して
ソースコードを機械語に変換することから、コンパイラ言語とも言われています。

※正式には静的型付けの高水準言語（人間の言葉に近い言語）のことを指します。
低水準言語（機械語に近い言語）にはC言語の元になったアセンプリ言語があります。
ややこしいですがC言語はコンパイラ言語に分類されます。

・プログラムの実行前に（コンパイル時、インタプリタ開始前）に型検査（演算とデータの型が適合しているかを確かめるために行われる型の検査）を行い、
型がつくプログラムのみコンパイルされ、実行されます。

・またgo言語では、:=を使用して型推論を行うことで、動的型付け言語のような書き心地で変数をや関数を宣言できます。

### 具体例
実際にGo言語とJavaScriptを比較して考えてみましょう。
####Go言語の場合

```go
package main

import (
	"fmt"
)

func main() {
	// string型の変数aを定義
	// 変数aにはstring型がはいることを明示的に書く
	// この時点でメモリ内にstring型分の領域が確保される
	var a string

	// aに文字列Hogeを代入
	a = "Hoge"
	fmt.Println(a)

	// aに文字列Fugaを代入し上書き
	// string型であれば上書きすることができる
	a = "Fuga"
	fmt.Println(a)

//実行結果
Hoge
Fuga
```

####Javascriptの場合

```javascript
const HogeFuga = () => {
 console.log("Hoge");
 console.log("Fuga");
};

HogeFuga();

// 実行結果
Hoge
Fuga
```
となります。



### 型推論とは？
静的型付け言語は関数や変数の型について明示的（はっきりと記述すること）に宣言しなくてはいけません。
しかし型推論という仕組みによってそれらの型を自動的に（暗黙的）に示すことができます。

実際にGo言語を例えに見て行きたいと思います。

```golang
package main

import (
	"fmt"
)

func main() {
        //:=を使用することで型推論が行われるのでデータ型をしていする必要がなくなる
        //動的型付け言語のように扱うことができる
        a := "Hogehoge"
	    fmt.Println(a)

	    // aに文字列Fugafugaを代入し上書き
	    // string型であれば上書きできる
	    a = "Fugafuga"
	    fmt.Println(a)

         //実行結果
        Hogehoge
        Fugafuga
```


##型の強さ、弱さについて
次にプログラム言語の型の強さ・弱さについて説明していきたいと思います。
型が強いというのは動的型付けであれば実行時に、静的型付けであればコンパイル時に
型の不整合が検出できるものを指します。

反対に型が弱いというのは型システムに抜け穴があり，すべての型エラーを検出できなかったり、
型の不整合があっても暗黙的な変換（自動的な変換）により型エラーが検出されなかったり
することを言います。

実際のコードを例にして考えると　

```
var x = 1
var y = “2”
x + y
```
の場合


強い型付け→ 型の不整合によるエラー
弱い型付け→ どんな結果になるか言語ごとに異なる

という形になります。

ちなみにJavascriptの場合

```Javascript
var x = 1
var y = "2"
x + y
//実行結果
'12'
```

となりました。

###分類
最後に型の強さ・弱さで動的と静的な型付けの言語を分けていきたいと思います。

####強い動的型付け言語
Ruby・Pythonなど
####弱い動的型付け言語
PHP・Javascriptなど

####強い静的型付け言語
Go・Javaなど

####弱い静的型付け言語
C・C++など
Heroku 「 ▸ Couldn't find that app.」というエラーが出てきた時の解決方法

今日は人に読ませるレベルではないかもです。
メモメモ。

VSChordにてherokuのデプロイを行っていたら、、、

```perl:
        $ Couldn't find that app.
```

というエラーがでてきた。
再度チャレンジしていると、どうも格闘しているアプリ名が違い。。。

は！と気づいた
先ほどheroku createで一度違う、アプリを作成してしまっていた。
そして、herokuのwebサイトから削除した間違えたアプリ名だ！

色々調べていくと

```perl:
         $ heroku git:remote -a [app name]
```

でherokuの対象を変更して解決。

以上
AtCoderログ：0070 - ABC 213 C

# 問題

https://atcoder.jp/contests/abc213/tasks/abc213_c

## 問題文
> $H$ 行 $W$ 列の格子状に $HW$ 枚のカードが並べられています。$i=1,\cdots,N$
 について、上から $A_i$ 行目、左から $B_i$ 列目にあるカードには数 $i$ が書かれており、それ以外の $HW−N$ 枚のカードには何も書かれていません。
> これらのカードに対し、以下の $2$ 種類の操作を可能な限り繰り返します。
> ・数の書かれたカードを含まない行が存在するとき、その行のカードを全て取り除き、残りのカードを上へ詰める
> 数の書かれたカードを含まない列が存在するとき、その列のカードを全て取り除き、残りのカードを左へ詰める
> 操作が終了したとき、数が書かれたカードがそれぞれどこにあるか求めてください。なお、答えは操作の仕方に依らず一意に定まることが証明されます。

## 制約
> ・$1 \le H,W \le 10^9$
> ・$1 \le N \le {\rm min}(10^5,HW)$
> ・$1 \le A_i \le H$
> ・$1 \le B_i \le W$
> ・$(A_i,B_i)$ は相異なる
> ・入力に含まれる値は全て整数である

# 回答
## 回答1 (AC)
$HW$ 枚の全てのカードについて何が書かれているかを管理すると、$HW \le 10^9$ よりTLEになってしまいます。また $H$ や $W$ だけでも $10^9$ に近い値となる可能性があるため、$H$ や $W$ に関するループも TLE になってしまいます。このため、数字を書き込むカード情報の個数 $N$ に関するループだけで処理する必要があります。

設問では、数字が書かれたカードのない行と列を削除していきますが、行と列は独立しているので、ばらばらに処理することが可能です。まず行だけで考えましょう。数字の書かれたカードが存在する行の並びをソートすると、何行目を削除すれば良いかがわかります。数字の書かれたカードが存在する行に対しその行が何行ずれるか(その行までに何行が削除されたか)を記録していけば良いでしょう。列も同様です。コードは以下のようになりました。

```C++:abc213c-1.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int64_t h, w, n;
  cin >> h>> w >> n;

  vector<int64_t> a(n), b(n), c, d;
  for ( int i=0; i<n; i++ ) {
    cin >> a.at(i) >> b.at(i);
  }
  copy( a.begin(), a.end(), back_inserter(c) );
  sort( c.begin(), c.end() );
  copy( b.begin(), b.end(), back_inserter(d) );
  sort( d.begin(), d.end() );

  map<int64_t,int64_t> da;
  int64_t acounter = 1;
  for ( auto i=c.begin(); i!=c.end(); i++ ) {
    if ( *i==0 ) {
      da[0] = 0;
      acounter += 1;
    } else {
      if ( da.count(*i)!=1 ) {
        da[*i] = *i-acounter;
        acounter += 1;
      }
    }
  }

  map<int64_t,int64_t> db;
  int64_t bcounter = 1;
  for ( auto i=d.begin(); i!=d.end(); i++ ) {
    if ( *i==0 ) {
      db[0] = 0;
      bcounter += 1;
    } else {
      if ( db.count(*i)!=1 ) {
        db[*i] = *i-bcounter;
        bcounter += 1;
      }
    }
  }

  for ( int i=0; i<n; i++ ) {
    cout << a.at(i)-da[a.at(i)] << " " << b.at(i)-db[b.at(i)] << endl;
  }
}
```

## [AtCoder の解説](https://atcoder.jp/contests/abc213/tasks/abc213_c/editorial) → [ユーザ解説](https://blog.hamayanhamayan.com/entry/2018/01/07/224838)
「座標圧縮」というテーマの問題とのことでした。

## [AtCoder の解説](https://atcoder.jp/contests/abc213/tasks/abc213_c/editorial) → [ユーザ解説](https://blog.hamayanhamayan.com/entry/2021/08/09/010106)
lower_bound という関数を使うと、上記のコードがもっと精錬されるようでした。が、理解が追いついていません...
kintoneで録音してMP3ファイルを保存する

前回、kintoneで録音してWAVファイルを保存するという記事を書きましたが、

https://qiita.com/juri_don/private/ad301dff2d746f1f193f

WAVだとファイルサイズが大きいからMP3で保存したいなぁと思って色々と試行錯誤していたら成功したので紹介します。（変更点のみ書きます。）

# JavaScript

こちらから

https://github.com/zhuker/lamejs

`lame.all.js`

をダウンロードしてアプリの設定の`JavaScript / CSSでカスタマイズ`にアップロードしておきます。

## WAVをMP3にエンコードする
github内の`README.md`や`example.html`をほぼコピーいや、参考にしてESLintに怒られたところを直していきました。

```js
// wav to mp3 エンコード
const encodeMono = (channels, sampleRate, samples) => {
  const buf = [];
  const mp3enc = new lamejs.Mp3Encoder(channels, sampleRate, 128);
  let remaining = samples.length;
  const maxSamples = 1152;
  for (let i = 0; remaining >= maxSamples; i += maxSamples) {
    const mono = samples.subarray(i, i + maxSamples);
    const mp3buf = mp3enc.encodeBuffer(mono);
    if (mp3buf.length > 0) {
      buf.push(new Int8Array(mp3buf));
    }
    remaining -= maxSamples;
  }
  const d = mp3enc.flush();
  if (d.length > 0) {
    buf.push(new Int8Array(d));
  }
  return new Blob(buf, { type: "audio/mp3" });
};
```

## WAVデータをmp3化したものをkintoneにアップする

`FILE`の`name`の拡張子を`.mp3`にするのもお忘れなく。

```js
// PCM 16bit なので、1要素あたり 16bit = 2byte つまり要素数*2でwavのチャンクサイズを計算する
const wavsize = samples.length * 2;
～略～
view.setUint32(40, wavsize, true); // サブチャンクサイズ 波形データのバイト数 4byte
floatTo16BitPCM(view, 44, samples); // 波形データ

// wavファイルデータを作ってmp3にエンコードする
const wav = lamejs.WavHeader.readHeader(new DataView(buffer));
const samples_mp3 = new Int16Array(
  buffer,
  wav.dataOffset,
  wav.dataLen / 2
);
const blob = encodeMono(wav.channels, wav.sampleRate, samples_mp3);

// kintoneの添付ファイルフィールドに添付する
const client = new KintoneRestAPIClient();
const date = luxon.DateTime.local();
const FILE = {
  name: fname.value
    ? fname.value + "_" + date.toFormat("yyyyMMddHHmmss") + ".mp3"
    : "音声_" + date.toFormat("yyyyMMddHHmmss") + ".mp3",
  data: blob,
};
```

## 全体的なコードはコチラ

https://gist.github.com/juridon/cf9560936f4d263482edba7d8809fcc4

これでファイルサイズの大きさも気にしなくて良くなりました✨✨

# mp3で保存したときの動画

mp3で保存できますっ！うれしい！

https://twitter.com/juri_don/status/1425796121348087817?s=20
[OutSystems]Reactive/MobileのEmail機能（Technical Preview）

最近追加された、Reactive Web App/Mobileアプリケーションでのメール送信機能を試してみました。
（2021/8/12時点ではまだTechnical Preview。リリース当初のバージョンではPersonal Environmentでの動作に問題があったが、最近のアップデートで解決した）

# 前提条件
- Platform Serverのバージョンが11.12以上（ただし、当初のバージョンではバグが有り、Personal Environmentではメールを送信できないことがあったので、より新しいバージョンを利用する）
- Service Studioが最新

# 確認環境
Personal Environment(Version 11.13.0 (Build 31107))
Service Studio (Version 11.11.12)

# Technical Previewを有効にする
1. LifeTimeを開く
1. Environmentsリンクをクリック
1. 右上の「Options」ドロップダウンリストからTechnical Previewをクリック
1. 「Built-in emails for Mobile and Reactive Web apps」のスイッチをオンにする
1. Saveボタンをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/3e92fc5c-500a-4285-6d3c-0095d17811d4.png)


# SMTPサーバーを設定
事前に利用するSMTPサーバーと、その接続情報を準備しておく。
私は、Office365についてくるSMTPサーバー（smtp.office365.com）を利用しました。

1. Service Centerを開く
1. Administration > Emailページを開く
1. SMTPの接続情報を設定してSaveボタンをクリック

# 送信ロジック
Service Studioで作業。

アップデートにより、Reactive Web Appでも、EmailをGUIで作成する機能が使えるようになっています。
UI Flowを右クリックし、Add Emailで追加される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/c8329981-90e6-20d6-25b2-88cef1825e31.png)

追加されたEmailを以下のようにGUIで編集可能（基本的にはScreen/Blockと同じ方法）。
以下は、追加したEmailにMessageというInput Parameterをもたせ、その値を、「Message: 」というテキストのあとに出力するだけのもの。
Emailの設計方法がScreen/Blockと同じことがわかりますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/18402abd-0467-2ea2-b10d-79e3f8927119.png)

実際にメールを送信するには、Server Action内で、Send Emailという要素を配置し、Emailプロパティに上で作成したEmail要素を指定。
Emailに追加しておいたInput Parameterはここで指定可能。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/da57c921-c621-77b3-cfb8-45c4c89ea966.png)

送信したメールは以下のような形（枠は境界を示すためあとづけて加工）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/e9e4b74d-2ef3-102b-82c2-8d3623f53018.png)

# 注意点
EMailでは、Aggregate・Data Action・Client Variablesは使えないようです。

# ドキュメント

[Technical Preview - Emails in Mobile and Reactive Web Apps](https://success.outsystems.com/Documentation/11/Developing_an_Application/Implement_Application_Logic/Technical_Preview_-_Emails_in_Mobile_and_Reactive_Web_Apps)
React.memoでメモ化する技術

# React.memoとは
React.memoとは、コンポーネント(renderの結果)をメモ化するReactのAPIのことです。
(「メモ化」とは、計算結果を保持して再利用する手法のこと)
イメージ的にはキャッシュと似たようなものです。これを使うことでコンポーネントの再renderをスキップする事ができます。

## メモ化対象のコンポーネント例
- renderするコストが高いコンポーネント

- 頻繁にrenderされるコンポーネントの子コンポーネント


## 使い方
`React.memo(関数コンポーネント)`のように書きます。

```react
// 渡した関数がメモ化される
const Hello = React.memo(({name}) => {
  return <h1>Hello! {name}!</h1>;
}
```

## 仕組み
新しく渡されたPropsと前回のPropsを比較して、等価であれば再renderせずにメモ化したコンポーネントを再利用しています。
GCPのリージョンってわかりづらいって話

# なぜこれを書いたか
初めてGCPでVPCを構築した時ですね。
サブネットを作る時にリージョンを「東京」にしようと思い、
プルダウンから選択していたら。下のような画面でめちゃわかりづらかった。
どれが東京リージョンなんだよってなりましたね。

![スクリーンショット 2021-08-05 22.52.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478546/41bd66b7-731d-9897-b9df-4288262edb14.png)

なのでGCPを初めて触る人に向けて記事を書いてみました。

# AWSとAzureだとちょっと親切かも
他のクラウドプロバイダーのVPCを確認してみました。

### AWS
AWSはデフォルトリージョンを指定しているので特に気にすることもありませんし
AZも対象リージョン内から選択できるのでわかりやすい。
![スクリーンショット 2021-08-05 23.11.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478546/a95f7d9c-261b-beb4-f99b-9d6dd9b4c649.png)

### Azure
Azureはデフォルトリージョンを指定できないですが、
表記がわかりやすいですね。
![スクリーンショット 2021-08-05 23.13.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478546/0c6a63b3-85f7-5890-236d-7001c9a80627.png)

# なぜわかりづらいのか
GCPのネットワークアーキテクチャの概念は、VPCの中にリージョンが存在して、
リージョンの中にAZが存在しているのでAWSとAzureのネットワークアーキテクチャでは逆になっていますね。

![gcp-aws-azure-security-measures-image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478546/c4623727-4b5f-e64e-25fa-99ddc5e8f9fa.png)

なので、サブネットはAZをまたいで作成ができるということですね。
また、複数のリージョンを使用したいときは、1つのVPC内で対応することが可能になるという訳のようですね。

# リージョンを調べる場合はどうすればいいか
[Cloudのロケーション](https://cloud.google.com/about/locations?hl=ja)にアクセスすれば確認ができます。

# まとめ
アーキテクチャの概念を知らないと腑に落ちないことも多々あることを知りました。。
普段から使っていれば気にすることではないので、参考程度にみていただれば嬉しいです。
Amazon workspace とは

## 勉強前イメージ

仮想のデスクトップなんだけど、
特徴とか知りたい

## 調査

### Amazon workspace とは

フルマネージドなデスクトップの仮想化サービスになります。
在宅勤務が広がり、リモート環境の選択肢の一つになります。

### 概要

- フルマネージドサービス
- LinuxとWindowsが使用可能
- ライセンスの持ち込みが可能
- ADとの連携やCloudwatchでの監視などAWSサービスとの連携が可能

### 特徴

- 俊敏性

世界中のリージョンとAZを使用できるので、
時間と場所を問わず業務を行うことが出来ます。

- セキュリティ

VPC内にデプロイされて暗号化されたストレージにアクセスされます
KMSとも統合されます。

- コスト

従量課金オプションで、
最低料金や長期契約などがないため気軽に使用することが出来ます。

- 信頼性

自動スケーリングの負荷分散が組み込まれたEC2インスタンスの上で実行され、
稼働率のSLAは99.9%になります。

### 料金体系

料金体系は以下の2種類あります。

- 時間課金 : 短時間使用のユーザ向け
- 月額課金 : 長期間使用のユーザ向け

また、メモリやストレージの容量によっても料金が異なります。

## 勉強後イメージ

Linuxもあるのか・・・

## 参考

- [Amazon WorkSpaces](https://aws.amazon.com/jp/workspaces/?workspaces-blogs.sort-by=item.additionalFields.createdDate&workspaces-blogs.sort-order=desc)
- [リモートワークの増加で需要が高まるAmazon WorkSpacesをゼロからざっくり理解する](https://dev.classmethod.jp/articles/amazon-workspaces-for-beginner/)
[css]inline-blockとは

# はじめに

以下のリンクに画像例を使ってめちゃくちゃわかりやすく書いてある。これをみよう。

[ブロックレベル要素とインライン要素の違い](https://www.itra.co.jp/webmedia/block-inline-difference.html)
[インラインブロック要素の性質と使い方](https://www.itra.co.jp/webmedia/what-is-inline-block.html)

# 概要
HTMLコンテンツの振る舞いの一種のこと。
HTMLコンテンツ(divタグやaタグなど)の振る舞い（改行したり、横幅が調整できたり）は主に二つある。

## ブロックレベル要素

divタグなど。
入れると必ず前の要素から改行して入るブロックのように振る舞うやつ

## インライン要素

spanタグなど。
ブロックのように振る舞わず、前の要素から改行せずに入る。
インライン要素を色付けしても、マーカーのように文字に被せるようになり、width,heightを指定できない。

## インラインブロック要素
これら2つの要素の特徴をいい感じに取り入れたのがインラインブロック要素。以下の性質を持つ

* 横幅と高さが指定できる。
* ブロック要素と同じ余白のつき方をする。
* 横幅の初期値が内容で決まる
* 前後の要素とよこに並ぶ（改行が入らない）
scikit-learnの学習結果をpickleしない

機械学習を簡単に行うための有用なライブラリの一つは[scikit-learn](https://scikit-learn.org/stable/)である。
この文書では、scikit-learnの学習結果を[pickle](https://docs.python.org/ja/3/library/pickle.html)しないで済ます方法について述べる。

## scikit-learnの特徴
- 各種識別器の学習・予測・評価方法のためのインターフェースがそろえてある設計。
- 各種アルゴリズムを試して、比較しやすい。
- ドキュメントが充実している。

## 前提

- python
- scikit-learn
- pickle

## scikit-learn に欠けているもの
- scikit-learnで学習した結果を保持するための枠組みが不足している。
- そのため、sckit-learnで作った学習済みの識別器をpickleして、それをpickl.loads(pickle済みのファイル)して使ってしまうということをしてしまいやすい。

## 問題点
scikit-learn のサイトでも、pickleしたものを使うことの問題点が述べられている。

https://scikit-learn.org/stable/modules/model_persistence.html#security-maintainability-limitations

## 解決策
sklean-onnx のライブラリを用いて、学習済みの識別器をonnxファイルに変換する。そのonnxファイルを元にonnxruntimeを使って推論する。

http://onnx.ai/sklearn-onnx/

このページの中で、以下の手づきの例があるので、それをたどればよい。

- Train a model.
- Convert into ONNX format
- Compute the prediction with ONNX Runtime

### 一連の動作の実施例
- sckit-learn で学習する。
- sklean-onnx を使ってonnxファイルに変換する。
- onnxファイルを元に推論を実行する。

-----
```sample.py
# Train a model.
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y)
clr = RandomForestClassifier()
clr.fit(X_train, y_train)

print(clr.predict(X_test))

# Convert into ONNX format
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType
initial_type = [('float_input', FloatTensorType([None, 4]))]
onx = convert_sklearn(clr, initial_types=initial_type)
with open("rf_iris.onnx", "wb") as f:
    f.write(onx.SerializeToString())

# Compute the prediction with ONNX Runtime
import onnxruntime as rt
import numpy
sess = rt.InferenceSession("rf_iris.onnx")
input_name = sess.get_inputs()[0].name
label_name = sess.get_outputs()[0].name
pred_onx = sess.run([label_name], {input_name: X_test.astype(numpy.float32)})[0]

print(pred_onx)
```
【画像処理解説】二値化（Javaソース付き）

#はじめに
画像処理を簡単に解説していきます。
下部にはJavaでのソースコードも載せているのでぜひご参照ください。
不定期にはなりますが、随時更新していく予定です。

#二値化とは？
名前の通り、画像を0(黒)と1(白)の二値に変換する処理です。
なお、処理によっては1ではなく255を設定することもあります。

二値化された画像は白と黒の二色だけで構成されます。
下部の例を見て頂いた方が理解しやすいかと思います。

この変換は領域分割や境界線抽出などの前処理としてよく用いられます。
白黒はっきりつけることで、画像の解析がしやすくなると理解しておけば十分です。

#どうやって二値にするの？
画像を二値化するにはしきい値というものを用います。
処理としては単純で、画素値がしきい値より大きければ白、小さければ黒とするのが一般的です。
カラー画像のままでは処理ができないため、前処理としてグレースケール変換が用いられます。

余談ですが、二値化には2つ以上のしきい値を用いるものも存在します。
応用として実装してみても面白いかもしれませんね。

#しきい値の決め方は？
しきい値の決め方については、手動で決め打ちする方法と自動で決定する方法があります。
自動で決める方法としては判別分析法（大津の二値化法）が有名です。
これは次回説明する予定です。

今回は手動で決める方法を選択します。
手動のメリットとしては、好きなように微調整ができるという点があります。
一方、その調整が手間であることがデメリットになります。

#アルゴリズム
1. カラー画像はグレースケール変換する。
2. グレースケール画像をラスタスキャンし、各画素に対して3と4の処理を行う。
3. 画素のグレー値を取得する。
4. グレー値がしきい値以上ならば255を、そうでなければ0をバイナリ画像にセットする。

#二値化の例
元画像（グレースケール画像）
![out002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655420/e3c60b67-a52a-46f6-e1d9-a9aa843ee523.png)

結果画像（しきい値120の二値化画像）
![out003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655420/c61451e3-7685-6f2c-f7a9-69d1c2e07d3c.png)

#ソースコード
以下のプログラムでは白領域を255としています。
1でも処理上は問題ないのですが、表示した際に結果が確認しにくいためです。

```Color.java
public static SImage binarize(SImage grayImg, int threshold) {
    // グレースケール画像でない場合、まずグレースケール変換する
    if (grayImg.channel != 1)
        return binarize(toGray(grayImg), threshold);

    // 二値画像の生成
    var binaryImg = new SImage(grayImg.width(), grayImg.height(), 1);

    // 画像をラスタスキャン
    for (int x = 0; x < grayImg.width(); x++)
        for (int y = 0; y < grayImg.height(); y++) {
            // グレー値を取得
            int gray = grayImg.getGray(x, y);

            // グレー値がしきい値以上ならば255を、そうでなければ0をバイナリ値にセット
            int binary = gray >= threshold ? 255 : 0;

            // バイナリ値を画像にセット
            binaryImg.setGray(x, y, binary);
        }
    return binaryImg;
}
```
AWS KMSについて（その２）

##はじめに
　こんにちは！本日はKMSについての記事[（その１）](https://qiita.com/pankata79/items/7b5643f23f5710e4db8b)の続きになります。
　
　よろしくお願いします(｡･ω･)ﾉﾞ
##許可（Grant）
　KMSではキーポリシーのほかに許可という設定機能があります。

　◆**許可の作成**
　許可を作成する場合は以下のような**CreateGrant**を実行して設定します。

```
$aws kms create-grant\
 --key-id ~~~~~
 --grante-principal arn:aws:iam::~~~~
 --operations Decrypt
 --retiring-principal arn:aws:iam::~~~
```

　key-idで対称のCMK、grantee-principalで利用を許可するIAMユーザー、operationsで許可するAPIを指定する。retiring-principalを指定することで設定した許可を無効にできるIAMロールを設定しています。

##クライアントサイド暗号化（Client-Side Encryption：CSE）
　ユーザーがアプリケーションで暗号化を行いたいときに使用する。SDKでKMSのAPIを取りだし、取り出したキーを使用してデータを暗号化する。カスタマー管理CMKを使用し暗号化した後、そのデータは通信経路上も暗号化された状態となるためセキュアにデータを扱うことができる。エンベロープ暗号化の暗号化の流れはこちらになる。

クライアント側の暗号化では、Amazon S3に送信する前にデータを暗号化する。クライアントサイド暗号化を有効にするには以下のオプションがある。

　・KMSに保存されているCMKの使用
　・アプリケーションに保存したマスターキーの使用
　
##サーバーサイド暗号化（Server-Side Encryption）
　AWSの各サービスが提供する暗号化を使用する機能。AWSサービスがデータを受信した後に自動的に暗号化を行い途中の通信経路上のデータは暗号化されないためセキュリティ的には強度は落ちるが簡単に実装することができる。
　Amazon S3はデータセンターのディスクに書き込まれるときにデータをオブジェクトレベルで暗号化し、お客様がデータにアクセスするときに複合する。
　
##KMSでの制限
**◆CMKで直接暗号・複合できるデータは４KBまで**
　　CMKを直接暗号や複合に使用する場合は、４KBまでのデータしか処理できない。

**◆APIリクエストのレート制限がある**
　暗号化処理に使用するAPIは同時実行できる1秒当たりのリクエスト最大数が決まっている。このレートを超えてKMSのAPIをリクエストした場合に**ThrottingException**というエラーが返される。
　
**◆リージョン間でのキーの共有はできない**
　CMKは生成したリージョン内でのみ使用可能。ほかのリージョンで使用する場合は新しく生成する必要がある。

**◆CMKを削除したらデータ複合できない**
　CMKを削除した場合はそのCMKを使用して暗号化しているデータの復旧はできなくなる。AWS側に問い合わせしても復旧自体できないため削除は慎重に行う必要がある。
　ただ、データを破棄する際は暗号化に使用しているCMKを削除することで復旧をできなくさせるため安全にデータを破棄することができる。
　
**リソースの制限**
 KMSで作成するリソースについて上限があり、超える場合は制限の引き上げリクエストが必要

| リソース | 上限値 |
|:-:|:-:|
| CMKあたりの許可数 | 10,000  |
| エイリアス数  |  10,000 |
| カスタマー管理のポリシー|  10,000 |
| CMKあたりの特定のプリンシパル数  | 500  |
| キーポリシーのサイズ  | 32KB  |

## 対称キー（共通鍵暗号方式）
　暗号化のアルゴリズムの一つで、暗号化と複合に同じ暗号鍵を使うアルゴリズムのこと。
対称鍵暗号方式では暗号化に使用される暗号化のかぎと複合に使用される複合鍵が同一で、対象鍵の暗号方式で暗号化した情報を誰かに送るとき暗号鍵も一緒に送らなければならない。

##非対称キー（公開鍵暗号方式）
　2つの対となる鍵を用いてデータの暗号化や復号化を行う暗号方式。
公開鍵暗号のうち一方は広く他人に公開するため公開鍵と呼ばれもう一方は本人だけに分かるよう厳重に管理されるので秘密鍵と呼ばれる。秘密鍵で暗号化したデータは対応する公開鍵でしか復号できない。
　AWS KMSでは**RSA CMK**と**ECC CMK**がサポートされている。

　**◆RSA CMK：**暗号と復号または署名と検証に使用
　**◆楕円曲線（ECC） CMK：**署名と検証に使用

##　おわりに
　SCSの学習でKMSについてまとめました。仕事でも使うことがありとても勉強になりました。

(｡･ω･)ﾉﾞバイバイ