OmniAICreator/Qiita-1.07M huggingface dataset:
Marpで目指す脱パワポ職人

# 背景
TwitterのTLで少し話題になっているのを見かけたので、Marpに入門してみました。
特に新バージョンリリースされたとかではないですが、便利さゆえか定期的に話題に上がる様子。
VScodeのプラグインもあり、私もなんちゃってエンジニアとしてVScodeを使っているので触ってみました。
Marpはおろかマークダウンも使い慣れていない人なので生暖かい目でご覧ください。


# About Marp
- マークダウンの文書をいい感じにスライド形式に落としこんでくれるツール
- オープンソース
- 作成したスライドはHTML, PDF, ppt形式で出力可能
- クロスプラットフォーム対応(Linux, Windows, Mac)


VScodeのプラグインとCLIの2種類あり
今回はVScode版を触りました~~(CLIもあるので宗教上の理由でVScode触れない人も安心)~~。
![marp_tool.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647699/67ffd3af-6b68-d17b-4ae4-6ef96b2a144b.png)


# How to Install
インストールはVScodeのエクステンションなのでボタン一発
![vscode_extention.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647699/06b3c903-b308-647d-8451-3c9b5dc2beea.png)


# How to Use
- マークダウン形式なのでマークダウンファイル(.md)を作成
- ファイルの冒頭でFront Matter(水平線3つ)で区切られたセクションにYAML記法でMarpの設定を記載、今回は以下の設定で記載しました。

```
---
marp: true 　　　　            　　　　　　　　　　--> Marpを利用することを明記
theme: gaia                   --> スライドテーマ
paginate: true                --> 通し番号
headingDivider: 1             --> スライドの区切り指定(1なら#、2ならば##、3ならば###で区切られる)
class: lead                   --> 中央揃え
header: Marpで目指す脱パワポ職人 　　--> ヘッダー指定(フッターも同様に指定可能)
---
```

スライドテーマはデフォルトで3種類あり、テーマはCSSで記述されているので自作や公開されているものをインポートも可能です。今回はチュートリアルなのでデフォルトのgaiaを利用しました。

- 表紙などページごとの設定を入れたい場合は、HTMLのコメント文である「<!–-  -–>」を用いることで、スライド毎にMarpの設定が可能です。以下は表紙のみページの通し番号とヘッダーを消したものになります。

```
<!--
_class: lead
_paginate: false
_header: ""
-->
# Marpで目指す脱パワポ職人
```

- あとはMarkdown形式で記載することでスライドが作成されます。以下のように文字装飾や図/表もMarkdown形式で挿入可能です。
![create_slide.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647699/12523ebf-1a07-ad6d-3d54-b4144f582a93.png)


# メリット
- **書くのが楽**<br>
文字の配置や整形を勝手にやってくれるのでパワポで作成するよりも文書を書くのが楽でした。
- **変にこだわらなくなる**<br>
上記の通りで自動整形してくれるのですが、逆に細かい調整はし辛いのでスライドの無駄な拘りが減って作成時間が短くなりました。
- **Git連携ができる**<br>
今回は使ってないですがGit管理してチームで資料作成も可能です。マークダウンファイルなのでgit diffで差分も取れたりするのが便利そうですね。
- **既存ドキュメントを再利用できる**<br>
今回は使って(ry<br>
マークダウン形式で書かれた文章であれば冒頭の設定追記するだけでスライド化できるので、それこそQiitaの記事をLTにしたいときなどにも使えると思います。
- **コーディングチックでパワポ職人よりは楽しい**<br>
普段コーディングあまりしない故の憧れ・・・

# デメリット
- **画像系の扱いが難しい**<br>
画像の埋め込みが難しかったです。イメージどおりにできず、寄せるだけで四苦八苦しました。やはり画像はGUI操作できる方が楽ですね。
- **細かい調整が難しい**<br>
たぶん慣れていないだけでできないことはないと思いますが、細かい文書や配置の整形は難しい気がしました。
- ~~**たまにプレビューの反映がされない**~~<br>
~~画像を差し替えた際などにプレビューに反映されないことがありました。~~その後右上の三点リーダーを押すと"Refresh Preview"ボタンがありました。。。

# まとめ
なかなか個人的には使いがってのいいツールでした。ただ細かい調整が難しいので体裁を気にするようなものには向かないかもしれません。一時的にアイデアを共有したい場合やLT等のスライド作成には向いていると思います。
また普段からVScode使っている人であればVScodeにさらに機能集約ができるので使ってみて損はないかと。
あとQiita→LTやLT→Qiitaで変換しやすいのは良いですね。

# 参考資料
- "Marp(公式サイト), https://marp.app/
- "Markdownでスライドを作る、Marpのすゝめ", 
https://eng-blog.iij.ad.jp/archives/11432
- "Markdownから簡単にスライドを作成する「Marp(Marpit)」", https://tracpath.com/works/development/marp/
エスケープシーケンス   \newline	バックスラッシュと改行文字の無視ってなに？

下記のサイトをみて、自分の中でも、あれ？と、こんがらかってしまったので、図解してメモを残します。

# [Pythonでの\ newlineエスケープシーケンスとはどういう意味ですか？](https://stackoverflow.com/questions/48693600/what-does-the-newline-escape-sequence-mean-in-python)

> \newlinePythonドキュメントのエスケープシーケンスのリストでシーケンスを見つけました。それはどのように、そして何のために使われるのだろうか。少なくとも私の通訳では、これは次のように解釈されているようです'\n' + 'ewline'。

```python
>>> print('\newline')

ewline
```

---

# [字句解析](https://docs.python.org/ja/3/reference/lexical_analysis.html)

| エスケープシーケンス | 意味 | 注釈 |
|:-----------:|:------------:|:------------:|
| \newline    | バックスラッシュと改行文字が無視されます     |      |










![kaigyo_01-100.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/7c6351ab-6ee0-d3b2-208c-c20ae72ed342.jpeg)
![kaigyo_02-100.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/3deb4568-f772-3c14-6e78-4da997e544b2.jpeg)
next_permutation

入力した配列より後のパターンを辞書順にすべて試す

next_permutation(a, a + n)
(aは配列、nは要素数)

計算量
 O(N) * N!
(1順列あたり)　*　(全てのパターン)

```c++
do {
  
} while(next_permutation(a, a + n));
```
n = 3, a = {2, 3, 1} の実行結果
```c++
2,3,1
3,1,2
3,2,1
```

```c++
do {
        for(int i = 0; i < N - 1; i++) sum += dist(v[i], v[i+1]); //v[i]は配列の要素
    } while(next_permutation(v.begin(), v.end())); //vは配列
```
【React】useReducerの使い方

## はじめに
　本記事は、プログラミング初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
　そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
　間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。

## useReducerの使用例

``` counter.jsx
//useReducerをimport
import React, {useReducer} from 'react'
import Button from '@material-ui/core/Button';
import ButtonGroup from '@material-ui/core/ButtonGroup';

//counterの初期値を0に設定
const initialState = 0
//reducer関数を作成
//countStateとactionを渡して、新しいcountStateを返すように実装する
const reducerFunc = (countState, action)=> {
//reducer関数にincrement、increment、reset処理を書く
//どの処理を渡すかはactionを渡すことによって判断する
  switch (action){
    case 'increment':
      return countState + 1
    case 'decrement':
      return countState - 1
    case 'reset':
      return initialState
    default:
      return countState
  }
}
const Counter = () => {
//作成したreducerFunc関数とcountStateをuseReducerに渡す
//useReducerはcountStateとdispatchをペアで返すので、それぞれを分割代入
  const [count, dispatch] = useReducer(reducerFunc, initialState)
//カウント数とそれぞれのactionを実行する<Button/>を設置する
  return (
    <>
      <h2>カウント：{count}</h2>
      <ButtonGroup color="primary" aria-label="outlined primary button group">
        <Button onClick={()=>dispatch('increment')}>increment</Button>
        <Button onClick={()=>dispatch('decrement')}>decrement</Button>
        <Button onClick={()=>dispatch('reset')}>reset</Button>
      </ButtonGroup>
    </>
  )
}

export default Counter

```
find

 x が含まれる場所を判定

find(a + l,　a + r,　x) (配列)
find(a.begin(),　a.end(),　x) (vector)

(xが含まれる: a[i]の itr)　( 複数ある場合は最初の値 )
(xが含まれない: a+r または a.endの itr)


<初めて現れる位置>
find(a + l,　a + r,　x) - a

```c++
int f = find(a + l, a + r + 1, x) - a;
```
Railsで使用しているDBの情報を取得する

# はじめに
`rails console` とかで今使っているDBの情報をパパッと表示したいと思って調べたら出てきたのでメモ代わりに書き出します。

# 結論
`connection_db_config` メソッドを使う（`connection_config` メソッドもあるが、こちらはRails 6.2で Deprecated となっている）

# 確認方法
ここではirbで確認してみる。

このようにDBの接続状況が `DatabaseConfigurations::HashConfig` オブジェクトで返ってくる。ちなみに `connection_config` メソッドでは `Hash` オブジェクトで返ってきていた。

```ruby
irb(main):001:0> ActiveRecord::Base.connection_db_config
=> 
#<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fffe98d16c0
 @configuration_hash={:adapter=>"sqlite3", :pool=>5, :timeout=>5000, :database=>"db/development.sqlite3"},
 @env_name="development",
 @name="primary">
```

# 参考リンク
- [connection_db_config (ActiveRecord::ConnectionHandling)](https://apidock.com/rails/v6.1.3.1/ActiveRecord/ConnectionHandling/connection_db_config)
tuple

要素数は任意

get<要素数>(配列)

```c++
tuple<int, int, int> A;
cin >> get<0>(A) >> get<1>(A) >> get<2>(A);
```

```c++
vector<tuple<double, int, int>> B;

cin >> p1 >> p2 >> p3;
B.push_back(make_tuple(p1, p2, p3));

sort(B.begin(), B.end());
```
EC2にS3アドミン権限をアタッチしているのにS3バケットにcurlできない？

# はじめに
30代未経験からwebエンジニア目指して勉強中の者です。
S3のアドミン権限を持ったEC2にログインしてS3バケットにhttpリクエストを送ってもアクセスできず、なぜ？となったので備忘録として書きます。

# 結論
EC2にロールをアタッチしても、SDK/AWS-CLI経由のリクエストでなければ意味がない。（直にS3にcurlしてもアクセスできない。）
SDK/AWS-CLIを使わないのであれば、S3のバケットポリシーを使ってEC2のIPからのアクセスを許可する必要がある。

![gecipe-Page-2.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572098/ff0fa530-5e1d-7e16-9429-b6d27550b37d.png)


# 最後に
この辺の話は、FargateやLambdaにも通用しますね！
![Qiita.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572098/9660939f-55fb-cebe-8fc4-290863158935.png)
ラズパイでOpenCVが重い? 最適化したビルドをすればいい！

RaspberryPi4でOpenCVがやたら重かった。
調べてみると、公式のドキュメントは見つけられないが、個人のブログなどでちらほらNEONへの最適化などの話が見つかった。
下記の手順でビルドすれば、ラズパイに最適化されたOpenCVになる。

おそらく`apt install`で入れたOpenCVはこれら（少なくとも`ENABLE_NEON`）が最適化されたものだと思う。
これは自分でビルドしたいときの手順。

重要なのはcmake時の環境変数

* WITH_OPENMP
* WITH_TBB
* ENABLE_NEON
* ENABLE_FAST_MATH
* ENABLE_NEON
* ENABLE_VFPV3

## OpenCVソース取得

ほしいバージョンのソース (zip) を次から取得
https://opencv.org/releases/

あるいは
`wget https://github.com/opencv/opencv/archive/<バージョン>.zip`

## 依存するライブラリ

```bash
sudo apt install -y build-essential cmake git unzip pkg-config
sudo apt install -y libjpeg-dev libtiff-dev libpng-dev
sudo apt install -y libavcodec-dev libavformat-dev libswscale-dev
sudo apt install -y libgtk2.0-dev libcanberra-gtk* libgtk-3-dev
sudo apt install -y libgstreamer1.0-dev gstreamer1.0-gtk3
sudo apt install -y libgstreamer-plugins-base1.0-dev gstreamer1.0-gl
sudo apt install -y libxvidcore-dev libx264-dev
sudo apt install -y python3-dev python3-numpy python3-pip
sudo apt install -y libv4l-dev v4l-utils
sudo apt install -y libopenblas-dev libatlas-base-dev libblas-dev
sudo apt install -y liblapack-dev gfortran libhdf5-dev
sudo apt install -y libprotobuf-dev libgoogle-glog-dev libgflags-dev
sudo apt install -y protobuf-compiler
sudo apt install -y libtbb2 libtbb-dev libdc1394-22-dev
```

## ビルドとインストール

ここでは`3.4.16`を`~/`にダウンロードしてきたとします。

```bash
# cd ~/
# wget https://github.com/opencv/opencv/archive/3.4.16.zip
cd ~/
unzip 3.4.16.zip 
rm 3.4.16.zip

cd opencv-3.4.16
mkdir build
cd build
pwd
# ~/opencv-3.4.16/build

# cmake webカメラ使うラズパイに最適化
cmake -DCMAKE_BUILD_TYPE=RELEASE \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DPYTHON3_PACKAGES_PATH=/usr/lib/python3/dist-packages \
-DENABLE_FAST_MATH=ON \
-DENABLE_NEON=ON \
-DENABLE_VFPV3=ON \
-DWITH_OPENMP=ON \
-DWITH_OPENCL=OFF \
-DWITH_TBB=ON \
-DBUILD_TBB=ON \
-DBUILD_TIFF=ON \
-DWITH_FFMPEG=ON \
-DWITH_V4L=ON \
-DWITH_LIBV4L=ON \
-DWITH_VTK=OFF \
-DWITH_QT=OFF \
-DOPENCV_ENABLE_NONFREE=ON \
-DINSTALL_C_EXAMPLES=OFF \
-DINSTALL_PYTHON_EXAMPLES=OFF \
-DOPENCV_GENERATE_PKGCONFIG=ON \
-DBUILD_EXAMPLES=OFF \
..

# make と install すごい2119
make -j4
sudo make install
make clean

# ldconfig
sudo ldconfig
sudo apt update
```
ＡグループとＢグループにあるものとないものを可視化


# 動機


ＡにあってＢにないもの、ＢにあってＡにないものを可視化したい

| Ａグループ   | Ｂグループ   |
----|----
| いちご       | いちご       |
| みかん       | みかん       |
| りんご       | なし         |
| めろん       | りんご       |
| もも         | めろん       |
| すいか       | とうもろこし |
| とうもろこし | なす         |


# よくするのは


各列をソート

| Ａグループ   | Ｂグループ   |
----|----
| いちご       | いちご       |
| すいか       | とうもろこし |
| とうもろこし | なし         |
| なす         | なす         |
| みかん       | みかん       |
| めろん       | めろん       |
| もも         | りんご       |


おなじものが、同じ行になるように、セルを挿入する

| Ａグループ   | Ｂグループ   |
----|----
| いちご       | いちご       |
| すいか       |              |
| とうもろこし | とうもろこし |
|              | なし         |
| なす         | なす         |
| みかん       | みかん       |
| めろん       | めろん       |
| もも         |              |


うーん

# マクロつくってみた


Ａ列を選択して、マクロ実行
Ｂ列を選択
出力先を選択

重複を避けて項目を並び替えて、ＡとＢそれぞれにあり（１）なし（０）を示してくれる

| くだもの     | A | B |
----|----|----
| いちご       | 1 | 1 |
| すいか       | 1 | 0 |
| とうもろこし | 1 | 1 |
| なし         | 0 | 1 |
| なす         | 1 | 1 |
| みかん       | 1 | 1 |
| めろん       | 1 | 1 |
| もも         | 1 | 0 |


タイトル行は出力されません

```vb

Sub Diff2Lines()
    Dim range1 As Range, range2 As Range, rangeDiff As Range

    Set range1 = Selection
    If range1.columns.Count > 1 Then
        MsgBox "2列以上は選択できません"
        Exit Sub
    End If

    Set range2 = Application.InputBox(prompt:="", title:="2列目を指定する", Type:=8)
    If range2.columns.Count > 1 Then
        MsgBox "2列以上は選択できません"
        Exit Sub
    End If

    Set rangeDiff = Application.InputBox(prompt:="", title:="出力先を指定する", Type:=8)

    If WorksheetFunction.CountA(rangeDiff.Resize(range1.Rows.Count + range2.Rows.Count, 3)) <> 0 Then
        MsgBox "比較結果出力先が空欄でありません"
        Exit Sub
    End If

    Dim r(1 To 2) As Variant
    r(1) = range1
    r(2) = range2

    Dim dic(1 To 2) As Object, dicDiff As Object
    Set dic(1) = CreateObject("Scripting.Dictionary")
    Set dic(2) = CreateObject("Scripting.Dictionary")
    Set dicDiff = CreateObject("Scripting.Dictionary")

    Dim i As Long
    Dim c As Long
    Dim v As String
    For c = 1 To 2
      For i = 1 To UBound(r(c))
          v = r(c)(i, 1)
          If Not dicDiff.Exists(v) Then
              dicDiff.Add v, v
          End If
          If Not dic(c).Exists(v) Then
            dic(c).Add v, v
          End If
      Next
    Next

    Dim allKeys As Variant  '
    allKeys = dicDiff.Keys

    Dim diffArrayList As Object
    Set diffArrayList = CreateObject("System.Collections.ArrayList")

    For i = 0 To UBound(allKeys)
        diffArrayList.Add (allKeys(i))
    Next
    diffArrayList.Sort

    Dim outValue As Variant
    outValue = rangeDiff.Resize(UBound(allKeys) + 1, 3)
    For i = 0 To UBound(allKeys)
        outValue(i + 1, 1) = diffArrayList(i)
        outValue(i + 1, 2) = IIf(dic(1).Exists(diffArrayList(i)), 1, 0)
        outValue(i + 1, 3) = IIf(dic(2).Exists(diffArrayList(i)), 1, 0)
    Next
    rangeDiff.Resize(UBound(allKeys) + 1, 3) = outValue
End Sub

```
tmuxの超基本操作

n予備校プログラミングコースの復習です。


tmux tmuxの起動
ctrl + b → d デタッチtmuxから離れる
tmux a tmuxに接続する
ctrl + b → c ウィンドウ作成
ctrl + b → x ウィンドウ削除
ctrl + b → n 次のウィンドウに移動
ctrl + b → p 前のウィンドウに移動
ctrl + b → 数字　指定した数字のウィンドウに移動
Amazon Elastic File System（EFS）の暗号化方式に関して

## 概要
Amazon Elastic File System（EFS）におけるデータの暗号化方式についてまとめる
基本的にEFSの暗号化の利用にあたりアプリケーションの変更は必要ない

## 方式
やり方は以下の2パターンの方式がある
- 転送時の暗号化
- 保管時のデータの暗号化

https://docs.aws.amazon.com/ja_jp/efs/latest/ug/encryption.html

## 転送時の暗号化
以下2パターンのどちらかの方式をEFSをマウントするOS側で実施する
- マウントヘルパーを利用する方式（AWS推奨）
- stunnel（スタンネル）を利用する方式


https://docs.aws.amazon.com/ja_jp/efs/latest/ug/encryption-in-transit.html


## 保管時のデータ暗号化
AWS Management Console、AWS CLI、Amazon EFS API またはAWS SDK から、暗号化されたファイルシステムを作成することがでる
保管されるデータの暗号化および復号化はEFS側で実施されるため、アプリケーションの変更の必要はない
- **※注意点**
  - AWS Management Consoleから新しくEFSを作成する場合はデフォルトで保管時の暗号化が**有効になる**
  - AWS CLI、API、および SDK を使用して新しいファイルシステムを作成すると、保管時の暗号化がデフォルトで**有効にならない**為、暗号化を有効化する場合、明示的に指定する必要がある


### 暗号化の対象

保管時の暗号化の対象となるのは**メタデータ**および**ファイルデータ**の2種類存在する

#### メタデータの暗号化
- AWS管理CMK（aws/elasticfilesystem）を利用して暗号化/複合化が実施される

#### ファイルデータの暗号化
以下の2つのタイプの鍵が利用可能
- AWS管理CMK（aws/elasticfilesystem）
  - KMSの利用にあたり別途費用がかかる
- カスタマー管理CMK

https://docs.aws.amazon.com/ja_jp/efs/latest/ug/encryption-at-rest.html
コンタクトフォーム７をテーマの中に組み込む

今回WordPressで作られたウェブサイトの復旧作業を行う中で、備忘録として私自身経験を記録した方が良いことがありました。

今回の復旧作業は、テーマを応用してウェブサイトが作られていました。
最初依頼主から受け取ったファイル一式が、不思議な構成でした
phpの拡張子のファイルでしたし、header.phpなどがあったので、WordPressで作られたウェブサイトの一部かなと直感しました。

色々調べる中で、テーマの中に入れてみようと思い、テーマのフォルダの中に配置してみました。
予想が当たって、ウェブサイトを表示できました。
でもSVG画像だけが表示されていないように見えたので、ドツボにハマってしまいました。
それで、前回の記事を書いたのです。

https://qiita.com/masaru21/items/647c2748d8f80812bdf0

結局は、画像のパスを修正したら、直りました。

次にメールフォームの関連で、不思議なファイルがありました。
contact.phpなのですが、ファイルの中は、コンタクトフォーム７でフォームを作るときに入力する内容でcssも使われていました。
そして同じ内容で、<label>タグが並んでいました。

結局contact.phpを気にせず、このファイルの中のタグの部分を、コンタクトフォームのタグの欄に、コピペしました。
そして、<label>の部分は、無視しました。

```php
 <?php echo do_shortcode( '[contact-form-7 id="9" title="contact"]' ); ?>
```
この部分のcontact-form-7 id="9" title="contact"を今回作ったフォームのIDに変更して対応しました。
この方法でも、ちゃんとCSSが反映されて意図した通りに復旧できました。

今回は、下記のブログなどの記事を参考にしました。

https://kagesai.net/contactform7perfectguide/

https://wp-technique.com/wp-contactform7-html/

https://blog.chinsukoustudy.com/2020/04/02/contact-2463/
【Rails】ローカルサーバーを起動したときに、"A server is already running."とエラーが出た時の解決方法

# 環境
- Ruby 2.6.6
- Rails 6.0.3

# エラー内容
Railsアプリのディレクトリ上でローカルサーバーを起動したところ、以下のようなエラーが発生し、アプリにアクセスできない状況になってしまった。
このエラーの内容は、サーバーはすでに実行されているというもの。

```:ターミナル
$ rails s
=> Booting Puma
=> Rails 6.0.3 application starting in development 
=> Run `rails server --help` for more startup options
A server is already running. Check /your_project_path/tmp/pids/server.pid.
Exiting
```

# 原因、仮説
エラーが発生した原因は、ローカルサーバーを停止する前に誤ってターミナルを閉じてしまったことにありそう。
ターミナルを閉じた後もローカルサーバーが動いている状態になっているため、ローカルサーバーが動いているプロセスを終了させれば解決しそう。

# 解決方法
まず、ローカルサーバーが動くプロセスのIDを調べるために、ターミナルで以下のコマンドを実行する。

```:ターミナル
$ lsof -i:3000
COMMAND     PID     USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
Google    15466 username   22u  IPv6 0xda4848d42daa87b7      0t0  TCP localhost:55152->localhost:hbci (ESTABLISHED)
ruby      33412 username   14u  IPv4 0xda4848cf62d8e48f      0t0  TCP localhost:hbci (LISTEN)
ruby      33412 username   15u  IPv6 0xda4848d42dab0577      0t0  TCP localhost:hbci (LISTEN)
ruby      33412 username   31u  IPv6 0xda4848d42daaaa17      0t0  TCP localhost:hbci->localhost:54993 (CLOSED)
ruby      33412 username   36u  IPv6 0xda4848d42daab7d7      0t0  TCP localhost:hbci->localhost:55102 (CLOSED)
ruby      33412 username   37u  IPv6 0xda4848d42daabeb7      0t0  TCP localhost:hbci->localhost:55147 (CLOSED)
ruby      33412 username   38u  IPv6 0xda4848d42daada37      0t0  TCP localhost:hbci->localhost:55152 (ESTABLISHED)
```

ローカルサーバーが動いているプロセスのID（PID）は、COMMANDの値がrubyの`33412`です。
なお、`tmp/pids/server.pid.`のファイルを開くことでも確認することができます。

```:tmp/pids/server.pid.
33412
```
そして、ローカルサーバーのプロセスを終了させるために、ターミナルで以下のコマンドを実行する。

```:ターミナル
$ kill -9 33412
```

これで再度ローカルサーバーを起動することができるようになります。

# 参考
- https://pikawaka.com/rails/rails-s
pandasのread_csvでフォルダ内のcsvを読み込む方法

# 解決したい事象
pandasのread_csvメソッドで、フォルダ内のcsvを選択したい

# 方法
絶対パスを書いても、エラーが発生するため、pyファイルがある階層以降のパスを記載する。

```python
#間違い
train = pd.read_csv("/Hoge/hogehouse-prices-advanced-regression-techniques/train.csv")

#正解
train = pd.read_csv("house-prices-advanced-regression-techniques/train.csv")

```

はじめにスラッシュ（/）を使わない点もポイント。
Twilio StudioのMake Outgoing Callを使った複数番号架電を試してみた。

# これは何？
Make Outgoing Callを使って複数番号への架電を実装したかったのですが、上手くいかなかったのでメモです。

## やりたかったこと
下記、図のようにMake Outgoing Callを複数繋げて、電話に出なかったら次の人(番号)へ架電するというのを実装しようと思いました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435702/0fbd9df0-bc55-7322-1aa9-823177bf3015.png)

## 問題
設定値のNUMBER TO CALLとNUMBER TO MAKE CALL FROMが変更できない。。

確かにドキュメントを確認するとRESTAPIで渡される値が使われ、ウィジェット内で変更はできないと書いてある。
>The required fields for this Widget are To and From. These are determined at runtime by the values provided >in the REST API request to create the Execution and cannot be changed in the widget configuration.
https://jp.twilio.com/docs/studio/widget-library/make-outgoing-call

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435702/e9235ba9-1d83-1db9-ddca-026740a0b1ac.png)

## 試してみたこと
画像の順でNUMBER TO CALLに相当する部分のJsonを直接書き換えることで確かに画面上では番号は変更できた。
パワー技だけど、書き変わったからいけるだろうと思いました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435702/1f27fb3a-f622-985e-7d24-38d1c1b65455.png)
### 結果
結論としては実現できなかったです。
実際にリクエストしてみると、1人目に架電され拒否すると問題無く2人目へ架電されるのですが、
SAY/PLAYの内容が読み上げられずApplicationエラーの様な文言を伝えられます。

StudioのErro Logを確認すると下記、11200エラーが出力されており、
架電自体は行えるのですがそれ以外が上手くいかなかったです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435702/e723028b-03ee-5409-53d9-669d6858f3dc.png)


# まとめ
複数番号への架電をする際には下記、記事の様に複数回Studioを呼び出す方法などを使用する必要がありそうです。

https://qiita.com/mobilebiz/items/8757eec854f37ce0cb2d
UNTimeIntervalNotificationTrigger.nextTriggerDate が正しい値を返さない話

## やりたいこと
UNTimeIntervalNotificationTriggerをNotificationCenterに登録したのち、あとからgetPendingNotificationRequestsを使って通知が発火する日時を知りたい。

## 何が変なのか
UNTimeIntervalNotificationTrigger.nextTriggerDateは、一見「次にイベントが発火する日」を返しそうだし、ドキュメントにもそう書いてあるのに、「現在時刻 + timeInterval」を常に返す。

### 返して欲しいもの
次にプッシュ通知が発火する日付

### 実際に返ってくるもの
現在時刻+timeInterval（なんの意味もない日付）

## 公式ドキュメント
次に発火する日が知りたかったらこのプロパティ使ってね、としっかり書いてある(2022/2/22現在)

```
Use this property to find out when a notification associated with this trigger will next be delivered.
```

## ワークアラウンド
- UNCalendarNotificationTriggerで代用できるならそうする
- UNtimeIntervalNotificationTriggerを生成する際、UserDefaultsに起点となる日付を保存しておく（！？）

## 同じハマりをしてた人達
https://stackoverflow.com/questions/40411812/does-untimeintervalnotificationtrigger-nexttriggerdate-give-the-wrong-date

※Appleに問い合わせた結果、メンゴメンゴ、ドキュメント書いた時は楽観的だった！って返ってきた話などが書いてある。

## 環境
iOS 15.1.1
Xcode 13.0
Windows COMポートを調べるWSHスクリプト

USBシリアルを利用したときに、デバイスマネージャからCOMポートを調べていますが、面倒になってきたので、WSHスクリプトを書いてみました。

Windows 10 Home 21H1 を使って動かしています。

```vb:Ports.vbs
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_PnPEntity WHERE PNPClass = 'Ports'")
Set ports = CreateObject("System.Collections.ArrayList")
For Each objItem in colItems
    ports.Add(objItem.Name)
Next
If ports.Count = 0 Then
    msg = "The port was not found."
Else
    msg = Join(ports.ToArray(), vbCrLf)
End If
Wscript.Echo msg
```

よい方法があれば、コメントください
[AndroidStudio]エディターのタブを複数行表示にする

#前置き
たくさんのファイルを開くとタブが画面に入りきらなくなり、タブの部分をスクロールする必要が出てきます
![スクリーンショット 2022-02-22 11.54.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/927e5985-84df-6ef0-40e9-6d69aace42de.png)

#本文
(macの場合)
AndroidStudio > Preferences > Editor > General > EditorTabs

(windowsの場合)
File > Settings > Editor > General > EditorTabs

![スクリーンショット 2022-02-22 11.46.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/be6f7cf1-8b1c-d45d-c540-631f7a81409d.png)

この中のShow tabs in one rowのチェックを外すと
タブが複数行で表示されるようになります。
![スクリーンショット 2022-02-22 11.54.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/de7cad19-5f17-2de4-4583-562511f2869c.png)
#補足
Show pinned tabs in a separate rowのチェックを入れると、ピン留めされたタブが上段に固定されて区別しやすくなります。
![スクリーンショット 2022-02-22 11.48.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/e17a9ea6-6790-7350-9851-45b4eae5a6f4.png)
[AndroidStudio]作業画面を手軽に分割する


#本文
画面を2分割したい時は、タブをドラッグするだけで
![スクリーンショット 2022-02-22 11.29.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/aed1ee8e-156f-2384-0577-806dd8705694.png)
2分割になります（画面の右寄りにドロップ）
![スクリーンショット 2022-02-22 11.31.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/daa3f7e3-363c-41af-372e-4beefa8d1597.png)
下方向の分割も
![スクリーンショット 2022-02-22 11.29.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/8dc08004-575c-9dda-fc7f-b8cd3f030c03.png)
簡単です！（画面の下寄りにドロップ）
![スクリーンショット 2022-02-22 11.31.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/196ac24b-9105-8a3e-920f-0b4787c9094f.png)
#補足
追加した画面はタブを閉じるだけで一画面に戻ります
Everything (It's you)をFirehoseでparquet形式にしてみた

# Kinesis３兄弟

言わずも知れた3兄弟のうち、`Firehose`を触ってみました。(自分用のメモです）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/fc5d2f3a-515a-9ff5-3ce0-725343934a43.png)

## Firehoseって？

https://aws.amazon.com/jp/kinesis/data-firehose/

>ストリーミングデータを確実にキャプチャおよび変換し、データレイク、データストア、および分析サービスに配信する、抽出、変換、ロード (ETL) サービス

とありますが、とりあえずEverything (It's you)=>parquet変換を試してみました。
（JSON=>parquet変換ですね）

```
data = {
    "id": 1,
    "name": "Everything(It's you)"
}  
```

# Firehose配信ストリーム作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/28d959f7-b67e-381a-8001-982ba3e61ce1.png)

#### Source

Kinesis Data Streamsから取り込むか、直接Firehoseへ書き込むか。
今回はDirectPUTを試行。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/1ca847a4-4424-59f6-35ab-6d1022a2048e.png)

#### Destination

出力先を色々選べますが、今回はS3を選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/e275025f-ad40-faa9-5439-42a536cdc16c.png)

#### ストリーム名を設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/847db429-92d8-e09d-b822-d9d4dc8327a9.png)

#### データ変換の指定

`Record format converion`を`Enabled`に。
`Output format`の設定が表示されるので下図のように`Apache Parquet`を指定。
データ変換プロキシの役割するAWS Glue databaseを指定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/393c043f-3491-4906-72c3-250b28d30d3b.png)

#### 出力先S3バケットを指定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/f4a11f07-c227-4e18-a941-1397f5244ac4.png)

#### 作成Done

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/596556c1-40b4-b6d4-2894-8852fb30d42f.png)


# Firehoseへデータを送信

`put_record`にて`Everything(It's you)`を送信。


```sample.py
import boto3
import json

client = boto3.client('firehose')

data = {
    "id": 1,
    "name": "Everything(It's you)"
}    

response = client.put_record(
    DeliveryStreamName='PUT-S3-from-kinoko',
    Record={
        'Data': f'{json.dumps(data)}\n'
    }
)

print(response)
```

# S3を見てみると

`.parquet`の形式で格納されてた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/de8bca33-a340-9f53-cc0d-1a98f254d23c.png)


- デフォルトで5分間隔の配信頻度

PUTしてからしばらく経ってからS3に格納されましたが、以下の通りデフォルトの`Buffer interval`が`5分`となってますので、この値を良きに変更すれば良さそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/25a6322d-fad1-1f51-47f3-36f0a3dab238.png)

>Amazon S3 へのデータ配信の頻度は、配信ストリームで設定した Amazon S3 の [Buffer size (バッファサイズ)] および [Buffer interval (バッファ間隔)] の値によって決まります。

# まとめ

parquet形式に簡単に変換できたけど、この先どう扱っていくかはまだピンと来ていないので試してみたい。
Twilio StudioのMake Outgoing Callについて遷移調査メモ

#これは何？
Twilio Studioを使って開発をしている中で、
Widgetの中の1つである**[Make Outgoing Call]**の挙動について分かりにくい部分があったので、検証したメモです。

https://jp.twilio.com/docs/studio/widget-library/make-outgoing-call

## 何が分かりにくいか
Answered以外が具体的にどういうときに遷移するのか分からない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435702/2f023dad-9020-08c7-b4d1-f5b40d69b4d6.png)

## 検証結果
自分の携帯に通話してみて思いつく範囲でいくつか試してみたので結果を記載しておきます。

|アクション |遷移先  |
|---|---|
|通話に応答する  |Answered  |
|通話を拒否する  |BUSY  |
|通常の通話中の場合  |BUSY  |
|通話中に切る  |No Answer  |
|通話に出ない(タイムアウト)  |No Answer  |
|通話をかけた端末の電源切れてる  |No Answer  |
|おやすみモードになっている(iphone)  |No Answer  |

また、パターンが思いついたら追記します。
AWS Lightsail×VSCodeでftp

AWS Lightsail環境に対してローカルからftp接続で直接編集したい人向けです
すべてrootで

```shell
apt install vsftpd -y
adduser --home /home/ftp_user ftp_user
パスワード聞かれるから適当にパスワード
あとパーソナル情報も聞かれるので全部空でOK(?)

chown ftp_user:ftp_user -R /home/ftp_user/
echo "ftp_user" | sudo tee -a /etc/vsftpd.userlist

vi /etc/vsftpd.conf
--------------
listen=YES
listen_ipv6=NO
pasv_min_port=60001
pasv_max_port=60010
pasv_address={サーバの固定IPアドレス}
--------------
↑ 管理画面側で上記のポート(60001-60010) ＋ 20、21ポートを開けるのを忘れずに
※ 固定IP(EIP)が必要になります
※ listenとlisten_ipv6は既に記載されている場合もあるので追記じゃなくてデフォルト値変更で

その後再起動
service vsftpd restart
```

これでパッシブモードでftp可能に　
　
ローカル側はなんでもいいけどVSCodeで繫ぐならSFTPというプラグインを入れるのオススメ

```conf
VSCode上でCtrl＋Shift＋P → SFTP: config と入力 → プロジェクトを選択

FTPの設定をそれっぽく

{
    "name": "test",
    "host": "test.wing.com",
    "protocol": "ftp",
    "port": 21,
    "username": "ftp_user",
    "remotePath": "/home/ftp_user",
    "uploadOnSave": true
}

```
入社日がスーパー猫の日

みなさん入社日と、退職日について考えたことがあるでしょうか。
多くのITエンジニアが考えたことがあるではないかと思います。
こんなの毎日考える訳行かないので、そこのあなた今1回だけ私と一緒に考えませんか。
入社日がスーパー猫の日2022年2月22日の場合は2022年2月22日（0時）になった時点従業員になり従業員としての権限を持ち始めます。
退社日がスーパー猫の日2022年2月22日の場合は2022年2月23日（0時）になった時点従業員ではなくなり従業員としての権限を持たなくなります。
スーパー猫の日入社の場合は2022年2月22日の一番早い0時に従業員としての権限を持たせましょう。
スーパー猫の日退社の場合は2022年2月23日の一番早い0時に従業員としての権限を持たせなくしましょう。
知ってるでしょうけど0時なんて人でやるには早すぎだから、マシーンに頼みましょう。
以上です。お付き合いいただきありがとうございました！
Property 'hoge' does not exist on type 'CombinedVueInstance<Vue, unknown, unknown, unknown, Readonly<{ hoge }>>'.と怒られる

## 概要
 - 仕事中nuxtでコードを書いてたら謎のエラーに遭遇して２時間くらい苦戦したので、備忘録のため残しておく

## 環境
- nuxt -> 2.15.8
- @nuxt/typescript-build -> 2.1.0

## 事象
`computed`配下の変数に下記のエラー文が出る

````
Property 'hoge' does not exist on type 'CombinedVueInstance<Vue, unknown, unknown, unknown, Readonly<{ hoge }>>'.
````

## 解決方法
- `computed`の関数の返り値に型をつける

````typescript
computed {
  hogeHoge(): string { return hoge}
}
````

- 後から知ったのですが結構有名な問題なのですね、、色んな解決法がありました
    - https://qiita.com/shunjikonishi/items/3774486d37af80d1ae47
    - https://github.com/vuejs/vue/issues/8721
pipenvでdotenvをinstallできなかった問題【解決済み】

おや？　dotenvをpipenvでインストールしようとしたらエラーが出た。

[pipenv.exceptions.ResolutionFailure]: Warning: Your dependencies could not be resolved. You likely have a mismatch in your sub-dependencies.
  You can use pipenv install --skip-lock to bypass this mechanism, then run $ pipenv graph to inspect the situation.
  Hint: try pipenv lock --pre if it is a pre-release dependency.
ERROR: No matching distribution found for dotenv

Pipfileを見てみる。

修正前

```:Pipfile
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
dotenv = "*"
```

修正後

```:Pipfile
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
python-dotenv = "*"
```
dotenvがpython-dotenvになってなかったね。これでOK。
【必見】未経験から社会人経験3年のうちに取得！AWS(SAA,SAP,DVA),情報処理安全確保支援士の合格体験記

私の実体験を基に、各種IT資格（AWS(SAA,SAP,DVA),情報処理安全確保支援士）に係る合格ガイドを記載しています。

いずれも非情報系学部から新卒で大手IT企業に入社した初心者状態から、3年目までに取得しましたので、いずれの方にとっても参考になると思います。

サラリーマンをしながらの資格試験は、時間も有限であり、実際に受かった人の経験が少しでも役に立てば幸いです。

●情報処理安全確保支援士
https://yukikuuiki.com/ipa-sc-preparation/

●AWS　ソリューションアーキテクトアソシエイト(SAA)
https://yukikuuiki.com/aws-saa-exam-preparation/
●AWS　ソリューションアーキテクトプロフェッショナル(SAP)
https://yukikuuiki.com/aws-sap-preparation/
●AWS　デベロッパーアソシエイト(DVA)
https://yukikuuiki.com/aws-dva-preparation/

また、要望があれば、基本情報・応用情報技術者試験の体験記も記載しようと思いますので、是非コメント頂ければ幸いです。

AWSは試験対策のもう少し踏み込んだ内容も記載していければと思っていますので、合わせて要望があれば連絡をお待ちしております。
【eslint】importで出るエラーの解決

初書：2022/02/22
eslint： 8.9.0

# 前書き

typescriptで、eslintを使っていると、謎にエラーが出る時があるので、修正メモ。

# 現状

```ts:main.ts
import { test } from './lib/test';
// Missing file extension for "./lib/test" eslint(import/extensions)
// Unable to resolve path to module './lib/test'.eslint(import/no-unresolved)
```

```json:.eslintrc.json
{
    "env": {
        "es2021": true,
        "node": true
    },
    "extends": [
        "airbnb-base"
    ],
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "plugins": [
        "@typescript-eslint"
    ],
    "rules": {
        "no-console": "off"
    },
    "overrides": [
        {
            "files": ["*.ts"],
            "rules": {
                "no-undef": "off"
            }
        }
    ]
}
```

インストール済みeslint関係のライブラリ

```json:package.json
    "@typescript-eslint/eslint-plugin": "^5.12.0",
    "@typescript-eslint/parser": "^5.12.0",
    "eslint": "^8.9.0",
    "eslint-config-airbnb-base": "^15.0.0",
    "eslint-plugin-import": "^2.25.4",
```

ちなみに、`tsc`でコンパイルするとエラーなくコンパイルできるので、ファイルは存在し、
また実行もできるので、ただ単にeslint側の問題だと推測できる。

# 対処

Airbnbを使っている時の対処法で、以下の方法が有効だったので、それを使用した。

以下をインストール

```zsh
% npm install -D eslint-config-airbnb-typescript
```

以下の一行を追加。

```diff_json:.eslintrc.json
extends: [
  'airbnb-base',
+ 'airbnb-typescript/base'
]
```

※reactを使用する場合は`/base`なし

以上で終わりです

# 参考サイト

[node.js - Typescript eslint - Missing file extension "ts" import/extensions - Stack Overflow](https://stackoverflow.com/questions/59265981/typescript-eslint-missing-file-extension-ts-import-extensions)
40 代おっさん GASの配列を使ったデータ処理を行ってみる

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## 配列を使ったデータの追加、削除

シート上のデータは配列としてまとめて収得、入力するとアクセス回数、実行時間を削減できます。
理想的な手順
・シート上のデータを配列として取得
・配列の状態で処理を施す
・処理を施した配列のデータをまとめてシートに入力

シート上のデータを追加、挿入、削除をする場合

pushメソッド：配列の末尾に新しい要素を追加
popメソッド：配列の最期の要素を取り出す
spliceメソッド：配列内の指定した位置にある古い要素を取り除きつつ、新しい要素を追加することが可能
shiftメソッド：配列の最初の要素を取り出す
unshiftメソッド：配列の先頭の新しい要素を追加する

お試し
データを入れて行ってみてください

```javascript
function toshiki4() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const values = sheet.getDataRange(). getValues();

  values.push(['アッキー', 9, 'りんご', 'ドラえもん', '本']);
  console.log(values);

  values.splice(1, 1, ['パパ', 41, '肉', 'ガンダム', 'ゲーム']);
  console.log(values);

  values.shift();
  console.log(values);

  sheet.clearContents();
  sheet.getRange(1, 1, values.length, values[0].length).setValues(values);
}
```

## 配列を使ったデータの検索

ここで使うが
indexOfメソッド：文字列や配列において、検索したい要素が配列内の先頭から何番目にあるかを教えてくれるメソッド
flatメソッド：flatメソッドは2次元配列を1次元配列に変換する事ができるメソッド

お試し
データを入れて行ってみてください

```javascript
function toshiki4() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const values = sheet.getDataRange(). getValues();

  const keys = sheet.getRange(1, 3, sheet.getLastRow()).getValues().flat();
  console.log(keys);

  const favorite = 'みかん';
  console.log(keys.includes(favorite));

  const row = keys.indexOf(favorite);
  console.log(row);

  const [ name, age] =　values[row];
  console.log(`${favorite}が好きなのは、${age}際の${name}です。`); 
}
```

## 配列を使ったデータの抽出

シートから特定の条件だけを抽出したいときには、filterメソッドを使用

filterメソッド：配列の要素のうち関数fncを満たす要素のみで新しい配列を生成して返す。（ファルター）

```javascript
function toshiki4() {

  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const values = ss.getActiveSheet().getDataRange().getValues();
  const header = values.shift();

  const targetValues = values.filter(record => {
    const [name, age] = record;
    return age < 30;
  });

  targetValues.unshift(header);
  const targetSheet = ss.getSheetByName('出力シート');
  targetSheet
    .getRange(1, 1, targetValues.length, targetValues[0].length)
    .setValues(targetValues);
}
```

## 参考資料

<https://www.amazon.co.jp/s?k=google+apps+script+%E5%AE%8C%E5%85%A8%E5%85%A5%E9%96%80&adgrpid=110264232688&gclid=CjwKCAiA9aKQBhBREiwAyGP5lSl7AJJLCvOEHb4wQgMlyqW1fll5X8GDTT_Rkd1_soUAyIPMXQr26hoClHEQAvD_BwE&hvadid=553833563682&hvdev=c&hvlocphy=1009076&hvnetw=g&hvqmt=b&hvrand=4378489642044417389&hvtargid=kwd-594191211348&hydadcr=4106_13159878&jp-ad-ap=0&tag=googhydr-22&ref=pd_sl_2x1owglv0s_b_p52>
【Mac】ターミナルでシャットダウン、再起動などをするコマンド

# はじめに
Macのターミナルでシャットダウン、再起動、スリープ、ロック、ログアウトするコマンドを紹介します。

macOS Big Surで動作を確認済みです。
古いMacでは動作しないかもしれません。

# シャットダウン

```sh
sudo shutdown -h now
```

パスワードを入力する必要があります。

# 再起動

```sh
sudo reboot
```

パスワードを入力する必要があります。

# スリープ

```sh
pmset sleepnow
```

MacのスリープはWindowsのスリープと休止状態の中間のような感じです。
だから、休止状態のコマンドは必要ないと思います。

# ロック

```sh
pmset displaysleepnow
```

# ログアウト

```sh
launchctl bootout user/$(id -u)
```

# 参考
[Mac｜スリープ・再起動・シャットダウンする方法 | PC設定のカルマ](https://pc-karuma.net/mac-sleep-reboot-shutdown/)
[Macでコマンドラインからsleep](https://qiita.com/cakipy/items/f4d1188dfa4b0982ef4d)
[Macのコマンドでスクリーンセーバー・画面ロック・画面オフ - それマグで！](https://takuya-1st.hatenablog.jp/entry/2018/06/06/104223)
[ターミナルを使用してMacからログアウトする方法– WebSetNet](https://www.websetnet.net/ja/%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6Mac%E3%81%8B%E3%82%89%E3%83%AD%E3%82%B0%E3%82%A2%E3%82%A6%E3%83%88%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/)
100日でSQLの達人になる@LeetCode! Day22 <MS SQL Serverでの小数点問題>

## 1294. Weather Type in Each Country （問題レベル: Easy）要課金
今日の問題はこれ。
国毎の2019年11月の平均気温から、国を"Cold", "Warm", "Hot"に分類するという問題。
`LeetCode Curated SQL 70`の`Easy`問題（全32問）も残すところ後3問まで来ました。
おかげさまで、基本的な問題はほぼ悩まずに回答できるようになってきました。

今日の課題も基本的なところは大丈夫でしたが、なかなかAcceptされない。
原因は小数点問題でした。

小数点問題はDay18でも悩んだので少し進歩したのかもです。

そこで今日のポイントは、
`MS SQL Server`では`AVG句`などは注意。整数値にまるめられるため`CAST`句を使用するなどの対応が必要
とした。

`CONVERT`も同様に使用できるようだ。
`CAST`を使用せずに勘弁に記載する方法は`AVG(変数 * 1.00)`のように小数点以下の桁数を指摘した掛け算をしてあげること。

`CAST`は日付や、文字列にも使用できる。また`data_type`も色々あるが、わかりやすくまとめられた記載が見つからなかったため、
また学習しようと思う。

* [LeetCode](https://leetcode.com/)の問題は、`MS SQL Server`で解いています。
ナレッジとデータカテゴリーとトピック

# ナレッジをExperienceCloudに出したい
簡単にExperienceCloudに出したいのでトピックとデータカテゴリーつなげて、標準のコンポーネントでずらずら出せばよいのでわ！
って安易に考えてがんばってやってみました。

## ナレッジの設定
ナレッジを設定せねばなりません。
[設定]>[ナレッジ]から有効可してあげましょう。
すると、[設定]>[ナレッジ設定]ができるようになるので「Lightning Knowledge を有効化」にチェックして保存だ！
あと今回はExperienceCloudにだすので、「URL 設定で記事を共有」もチェックだ！（これホントにいるのかな。。。）

## データカテゴリの設定
[設定]>[データカテゴリ]>[データカテゴリ設定]からデータカテゴリを作ろう！
一からつくったらとても面倒です。つらいです。
UIがなんかいうこと聞かなくて色々泣きます。。。
なので、メタをデプロイしたほうが色々幸せになれます。
そう、データカテゴリーはメタなのです。
[DataCategoryGroup](https://developer.salesforce.com/docs/atlas.ja-jp.api_meta.meta/api_meta/meta_datacategorygroup.htm)ってメタなのです。
注意にあるようにSalesforce様は手で入れることを推奨されてますので、新規に作るとか今あるデータカテゴリーを綺麗にして1からつくるって時だけデプロイしたほうがいいと思います。

## トピックを作る
ExperienceCloudにトピックを作ります。
これもサイトビルダーなりからいけるコンテンツ管理から作るのですが、今回はメタでやりした。
そう、これもメタなのです。
[ManagedTopics](https://developer.salesforce.com/docs/atlas.ja-jp.216.0.api_meta.meta/api_meta/meta_managedtopics.htm)です。
ExperienceCloud自体もメタでデプロイしたので其の時に一緒にいってるかと思ったのですがいってなく。。。
変更セットからメタ一式引っ張ったのでそこで漏れたのだと思います。そもそも変更セットにこのメタないですね。

なのでこれだけ自力でデプロイしましたがこのメタは難しかったです。
ポイントは、
- 主要トピックとナビゲーショントピックをちゃんと定義しませう。主要トピックの下に主要トピック置けないとか
- parentNameも間違えないで。間違えるととんでもないとこにくっつくます。

これも新規でつくるときのみ使うのがいいと思います。
更新もできると思いますが、その場合はメタを直接いじってやればなんとかですが関係性を把握してメタ作るのでこっちは手でやる方が早いと思われます。
デプロイ自体はメタのエラーさえなければすんなりいきます。

## 記事をインポートだ
記事自体はDataloderでインポートできますが注意が・・・
[データローダでのナレッジの Insert](https://help.salesforce.com/s/articleView?id=000337861&type=1)ってメタなのです。
このヘルプにもある通り、
- 記事の公開やアーカイブをデータローダで行うことはできません。 
- 記事の作成とデータカテゴリ設定をデータローダの 1 回の実行で行うことはできません。 
- リッチテキストエリア型カスタム項目に画像を挿入することはできません。 
- データローダバージョン 20.0 以降が必要です。 
という制約があり、何がつらいって公開はUIからやらないといけないので1つ1つポチポチする必要があります。
リストビューからやれるかと思いましたが勿論対応してないようです。。。
あとExperienceCloudで出すためには「知識ベースに公開」をチェックしないといけないですがこれもダメっぽいです。
Dataloderで値をTrueにできますが公開したとこでExperienceCloudからは見えないのでTrue⇒False⇒Trueと二回保存してやることに・・・私はやってしまいました。

## 記事とトピックに割り当てだ
トピックとデータカテゴリーは同じような名前にしておき自動割り当てを行うように設定しました。
ビルダーのコンテンツ管理いってトピックタブから設定できます。
記事にはデータカテゴリーを割り当てるのですがデータカテゴリはAPI名を指定しないといけません。
UIからやるととても押しにくい編集リンクを押してやるのですが、メタで処理しておけばAPI名も把握できると思います。
割り当てはDataloderで更新できます。
xxx_DataCategorySelectionというオブジェクトです。”データカテゴリーの選択：XXX”って名前になってたりしてちょっと探しにくいです。
かつ、Show all Salesforce objectsにチェックしないと出てこないので注意です。

## 他もろもろ
プロファイルにはナレッジへの参照権限を与えましょう。
データカテゴリーにも権限を与えてください。
データカテゴリー自体も有効にしてください。「カテゴリグループ表示設定」ってのがプロファイルの下のほうにあります。
Google Cloud Storage + Google Cloud CDNの環境を作ってみる

### 前説
- Google Cloud Storage には[組み込みキャッシュがある](https://cloud.google.com/storage/docs/caching#built-in_caching_for)。癖はあるが、通常は組み込みキャシュに任せている。
- ただし、キャッシュ可能な最大ファイルサイズが10MBなので、それ以上のファイルはキャッシュしてくれない
- 10MB以上のファイルを配信したい場合は、Google Cloud CDNを使うのが良いようだ

### 前提条件
- Google Cloud Platform の環境がある
- 参考: https://cloud.google.com/cdn/docs/setting-up-cdn-with-serverless

### Google Cloud Storage
- Cloud Storage > バケットを作成
  - バケット名 : 任意
  - ロケーション タイプ : Region
  - ロケーション : 任意 （東京にした）
  - ストレージ クラス : Standard
  - オブジェクトへのアクセスを制御する方法 : きめ細かい管理
  - 以上で作成
- 作成したバケットの > 権限 > 権限追加
 - `allUser` で ロールに `storage レガシー バケット読み取り` を追加
 - 一般公開バケットになる
- テスト用のファイル(test.png)をアップロード

### Google Cloud CDN
- ネットワークサービス > Cloud Load balancing > ロードバランサを作成
- `HTTP(S) 負荷分散` を選択
- `インターネットから VM またはサーバレスサービスへ` を選択し続行
  - バックエンドバケット名 : 任意
  - Cloud Storageバケット : 先ほど作成したバケットを選択
  - `Cloud CDNを有効にする` を選択
  - `静的コンテンツをキャッシュする` を選択
  - 高度な構成を表示して、カスタム レスポンス ヘッダー追加
     - ヘッダー名 : Cache-Status
     - ヘッダーの値 : {cdn_cache_status}
  - 以上で作成
- 作成した ロードバランサを選択し、IPを確認

### 動作確認
- curlで確認

```
$ curl -v -o/dev/null http://<ロードバランサのIP>/test.png
HTTP/1.1 200 OK
...
< Cache-Control: public,max-age=3600
< Cache-Status: miss

$ curl -v -o/dev/null http://<ロードバランサのIP>/test.png
HTTP/1.1 200 OK
...
< Cache-Control: public,max-age=3600
< Cache-Status: hit
```

キャッシュされている

### 以降の手順
Cloud CDNだけではhttps配信できないので
外部 IP アドレスの予約、SSL 証明書リソース作成等必要だが、今回はここまで。
jsで指定した割合で・確率・重み付けしたうえで抽選する

# コード
```
const array = [];
// 合計が100になるように値を設定してください。
const patterns = {
  "1st": 10,
  "2nd": 30,
  "3rd": 60,
};
for (var i = 0; i < 10000; i++) {
  // 0〜99までの整数
  const rand = Math.floor(Math.random() * 100);
  let result = "";
  let rate = 0;
  for (const name in patterns) {
    rate += patterns[name];
    if (rand < rate) {
      result = name;
      break;
    }
  }
  array.push(result);
}
for (const name in patterns) {
  console.log(name, array.filter((n) => n === name).length);
}
```

※ @332f　さんのコメントから、 `if (rand <= rate) {` を `if (rand < rate) {` に変更しました。


#　console.log 例
```
> 1st 1095
> 2nd 3060
> 3rd 5845

> 1st 1121
> 2nd 2968
> 3rd 5911
```

# 参考

https://iwb.jp/javascript-random-lottery-program-probability-settings/


# 合計値が10の場合の例
```
const array = [];
// 合計が10になるように値を設定してください。
const patterns = {
  "1st": 1,
  "2nd": 3,
  "3rd": 6,
};
for (var i = 0; i < 10000; i++) {
  // 0〜9までの整数
  const rand = Math.floor(Math.random() * 10);
  let result = "";
  let rate = 0;
  for (const name in patterns) {
    rate += patterns[name];
    if (rand < rate) {
      result = name;
      break;
    }
  }
  array.push(result);
}
for (const name in patterns) {
  console.log(name, array.filter((n) => n === name).length);
}
```
光一剛判定ゲーム作った #obniz

#KANZAI BOYAでミスるヲタク
https://twitter.com/kk_puruzera/status/1489524128931581954?s=20&t=fK7UbKP67SvlclsauXd-lw

#何これ
KinKiKidsの曲を聞きながら、
「今歌っているのは光一か、剛か」
を判断してLEDを光らせるゲームです。
図書委員（KinKiKidsファンのこと）ならば、歌割を完璧に聞き分けたいですよね。（諸説あり）
心の中で「今のは光一、今のは剛、今のは光一上ハモ剛メロディー」
と判定してニチャニチャしてもいいですが、せっかくならと思い光らせてゲームっぽくしてみました。
楽しいです。

#作り方
複数用意して図書委員同士で遊ぶとなお楽しいと思うので作り方を載せておきます。
簡単ですのでぜひ。

##(1)必要なものをそろえる
以下のリンク先はすべて秋月電子通商の商品ページになっています。
・[obniz](https://akizukidenshi.com/catalog/g/gM-14930/)
・[LED赤](https://akizukidenshi.com/catalog/g/gI-06245/)（10本入りでなくてもいいですし、5mmでなくてもいいです。赤ければなんでも）
・[LED青](https://akizukidenshi.com/catalog/g/gI-06247/)（青ければなんでも）
・[ジャンパワイヤー（オス-オス）](https://akizukidenshi.com/catalog/g/gC-05371/)（使用したコードの色はもちろん赤と青）
・[ミニブレッドボード](https://akizukidenshi.com/catalog/g/gP-05155/)（なくてもいけますがあったほうが工作しやすいですしキーホルダーなどの推しグッズをつけやすいです。）

動画にあるマスコットはその昔十六茶のCMをやっていたときに、期間限定で十六茶についていた光一氏と剛氏です。
当時は毎日十六茶を飲んでいました。（思い出しゲップ）
色違いもありましたね。懐かしい。

![20220204_130158.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122198/5cf84c87-cdc5-46c9-df9f-081557eb72f5.jpeg)


##(2)どう動くか決める
obnizのスイッチを押したときに、それぞれどう動作するか決めます。
今回は以下の内容にしました。

|  | obnizスイッチ | obnizのディプレイ | LED赤 | LED青 |
|:-:|:-:|:-:|:-:|:-:|
| KinKiKids | 押す | KinKiKids | ON | ON |
| 光一 | 右に倒す | Koichi | ON | OFF |
| 剛 | 左に倒す | Tsuyoshi | OFF | ON |
| 無音 | 押さない | clear | OFF | OFF |

##(3)プログラムを作る
どう動くか決めたらプログラムに反映します。

```JavaScript
const Obniz = require('obniz');
const obniz = new Obniz('Obniz_ID'); // Obniz_IDに自分のIDを入れます

obniz.onconnect = async function () {
    // LEDを利用
    const blue = obniz.wired('LED', { anode: 0, cathode: 1 }); // 青
    const red = obniz.wired('LED', { anode: 10, cathode: 11 }); // 赤

    // ディスプレイ表示（初期画面）LED OFF
    obniz.display.clear();
    obniz.display.print('start');
    red.off();
    blue.off();

   
    // スイッチの反応を常時監視
    obniz.switch.onchange = function (state) {
        if (state === 'left') {
            // スイッチが左に倒された時
            // ディスプレイ表示
            obniz.display.clear();
            obniz.display.print('Tsuyoshi');
            // 青点灯
            blue.on();
        } else if (state === 'right') {
            // ディスプレイ表示
            obniz.display.clear();
            obniz.display.print('Koichi');
            // 赤点灯
            red.on();
        } else if (state === 'push') {
            // スイッチが押されたとき
            obniz.display.clear();
            obniz.display.print('KinKiKids');
            // 両方点灯
            red.on();
            blue.on();
        } else {
            // 押されていない
            obniz.display.clear();
            red.off();
            blue.off();
        }        
    }
}

```

#完成！
あとはお好きなKinKiKidsの曲を流して遊んでください。
テンポの速い曲だと難しいです。
KANZAIBOYAは難しかったです……。

出来ればボタン式にしたいし、音声認識させて自動で光るとかもおもしろそうです。
結果をどこかに出力して答え合わせできるようにしても面白いかも。
気が向いたらやります。（やらない）
高速ゼータ変換について

こんにちは。株式会社オプティマインドの伊豆原と申します。

今回は自社の競プロ部の活動の一環として、アルゴリズム紹介記事として高速ゼータ変換について話させて頂きます。なお、当社の競プロ部に関しては以下のような紹介記事がございます。

https://note.com/t_fuki889/n/nc4ecec3265e2

## 高速ゼータ変換について

有限集合$S$とその部分集合を引数にとる関数$f : \mathcal{P}(S) \to \mathbb{R}$が与えられた時、そのゼータ変換$g : \mathcal{P}(S) \to \mathbb{R}$が以下のように定義されます。

$$g(T) := \sum_{U \subset T} f(U)$$

競技プログラミングでは小さい集合(要素数64個以下など)の管理をビットで行うことが多く、要素数$N$の集合$S$の部分集合は$0$から$2^N-1$までの整数(のビット表現)で表されます。その表現を使って関数$f : [0,2^N-1] \to \mathbb{R}$のゼータ変換$g$を求めるPythonコードを書きますと、"愚直"に計算して$\mathcal{O}(4^N)$、"部分集合の部分集合"でうまくループを廻して$\mathcal{O}(3^N)$となります。

```python
# 配列F : F[i] = f(i), i \in [0,2^N-1]
# O(4^N) 
G = [0]*(2**N) # G[i]=g(i)
for i in range(2**N):
    for j in range(2**N):
        if i&j == j: # (jのビット) ⊆ (iのビット)
            G[i] += F[j]

# O(3^N)
G = [0]*(2**N)
for i in range(2**N):
    j = i
    while True: # (iのビット)の部分集合のみでループ
        G[i] += F[j]
        if j == 0:
            break
        j = (j-1) & i # & i で部分集合以外を飛ばす
```

この計算を**高速ゼータ変換**と呼ばれる方法で行いますと、計算量を$\mathcal{O}(N2^N)$に抑えることができます。

```python
G = F.copy() # copy
for j in range(N):
    b = 1<<j
    for i in range(2**N):
        if i&b:
            G[i] += G[i^b] # i^bはiの(右から)jビット目が少ない状態
```

言葉で説明しますと、任意の要素$x \in S$ごとにその要素を含んでる任意の部分集合$x \in T$に対して$g(T) += g(T\setminus \lbrace x \rbrace)$と足し上げる計算になります。たとえば$|S|=3$として、集合のビット表現において左から1ビット目に着目しますと、行われる足し算は$g(100)+=g(000),g(110)+=g(010),g(101)+=g(001),g(111)+=g(011)$となります。

## 図を用いた説明

この計算をもう少し視覚的にしてみます。

一般に有限集合の部分集合全体は束構造を成します。たとえば要素数3の集合の部分集合は[ハッセ図](https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%83%E3%82%BB%E5%9B%B3) の形で直方体の各頂点に割り当てて表現することができます。この表現を基に考えると、先の高速ゼータ変換は下記の図の水色の矢印において、始点から終点の方向に順に足し上げていることが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334028/f77e1d6f-d643-3877-d782-59be17e21f0a.png)

あたかも縦・奥・横の各"次元"ごとに足し上げているようですが、これは有限集合$S$の部分集合全体の成す束$L=\mathcal{P}(S)$がBoolean束$\mathbb{B}=\\{0,1\\}$の直積として書けることに由来します(つまり$\mathcal{P}(S) \cong \mathbb{B}^{|S|}$)。つまり高速ゼータ変換とは、"ゼータ変換を行う束が直積に分解できるときに各次元でゼータ変換する"という下の逐次積分のような計算と考えることができます。

$$g = \int_\mathbb{B}\cdots\int_\mathbb{B}f(x_1 x_2 \cdots x_n)dx_1 \cdots dx_n$$

特に分解先の束が$\mathbb{B}=\\{0,1\\}$や有限区間$[0,N]$みたいな時は、inplaceな累積和がゼータ変換になるのでとりわけ高速に計算することができる、という感じです。

## 計算量について

この考えに基づいて計算量を考えてみます。

有限集合$S$の部分集合の成す束$\mathcal{P}(S)$について$\mathcal{P}(S) \cong \mathbb{B}^{|S|}$でした。$\mathbb{B}=\\{0,1\\}$でのゼータ変換はinplaceな累積和(というか足し算1回)で済み、それを各次元ごとに$2^{|S|-1}$回行う必要があります。次元は$|S|$次元なので、計算量は定数倍を除いて$\mathcal{O}(|S|2^{|S|})$となります。

他の例ですと、(inplaceな)二次元累積和なども高速ゼータ変換と見做せます。束として下記のような格子を考えますと、これは$[0,H]\times [0,W]$という部分束の直積になります。そのため各次元でのゼータ変換はinplaceな累積和で計算できるので、全部で$H(W+1)+(H+1)W$回の計算でゼータ変換を求めることができます。よって計算量は$\mathcal{O}(HW)$です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334028/8bf15ede-90cb-6e24-3e98-1bcae7809876.png)

## 結び

以上、高速ゼータ変換を紹介させて頂きました。分解する部分束がもうちょっと複雑な構造を持つ高速ゼータ変換で面白そうな例を見つけてみたいですね。
読んで頂きありがとうございました。
AWS Certificate ManagerをDNS検証で使用する

社内向けサービスを新しいドメインに変更することとなり、
SSLを使うために「AWS Certificate Manager」を使ってみた。

## 「AWS Certificate Manager」とは
通常は、SSLを使用するために認証局などにに申請して証明書を発行してもらわないといけないが、
そこを無料で簡単に証明書を発行してくれるAWSのサービス。

## ２つの検証方法
- Eメール検証
    - ドメインを管理しているEメールアドレスに検証メールが届き、文中のリンクをクリックすることで検証
    - 証明書更新のたびにメールが飛んでくるので、気づかないと証明書が切れてしまう
- DNS検証（今回はこちら）
    - AWS側がドメインの所有者かどうかを確認するために、管理しているドメインにDNS設定を追加して決まっている値を返すことで検証
    - ドメインごとにCNAME名と値が設定されるので、それをRoute53内の管理しているドメインに登録する
    - 証明書の更新は自動で行われる

## さっそく設定してみる
1. まずは「AWS Certificate Manager」にアクセスして「証明書をリクエスト」をクリック
![スクリーンショット 2022-02-22 12.15.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/815054/5494ab9c-7fdb-9b88-194c-fc6b19494138.png)
1. 「パブリック証明書をリクエスト」のままで「次へ」
![スクリーンショット 2022-02-22 12.18.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/815054/9d7a8e05-4af2-5a93-94d2-9765e970ceed.png)
1. 申請したいドメイン名を入力、検証方法は「DNS検証」を選択、「リクエスト」
![スクリーンショット 2022-02-22 12.20.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/815054/7d2ca171-d44b-35eb-a188-745e96a5d6f4.png)
1. ドメインが追加されていることを確認して「Route53でレコードを作成」をクリック
![スクリーンショット 2022-02-22 12.57.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/815054/f94c588c-f06b-e4a4-8952-aa94896b263e.png)
1. 表示内容を確認して「レコードを作成」
![スクリーンショット 2022-02-22 12.57.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/815054/1c16e39c-3856-5d30-3ec7-4fdce3cd1de8.png)
1. 設定後しばらくして検証が完了し、ステータスが成功になれば、証明書を使用できる
![スクリーンショット 2022-02-22 18.02.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/815054/ce9b9c51-8f52-375e-b6b2-93d430129194.png)


## 参考
- [AWS Certificate ManagerでSSLをお手軽に！](https://blog.serverworks.co.jp/tech/2016/04/07/acm_beginner/)
CEH 合格証を電子データでなく紙でもらう方法

CEH (Certified Ethical Hacker) の合格証は通常は電子データで送付されますが、有料で紙で郵送もできるようなので紹介させていただきます。

この記事は 2022/1/17 時点の内容です。

# 依頼フォームの入力と支払い

「https://cert.eccouncil.org/physical-certificate-printing.html」 より必要項目を入力します。

![ec_council_printing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44348/f4a4367b-917d-02de-d38d-0941479a92b9.png)

EC-Counsil Store にて $75.00 を支払います。以下は、支払い完了後のメール内容です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44348/13b50ab4-443f-fa95-ee06-8c32cd452f54.png" width="50%">

# メールでの送付先住所確認

支払い完了後の当日に、配達先の住所等の確認メールが送られるため返信し、やることは以上です。

```
Hi Kojiopn,

Greetings for the day.

This is to inform you that we have received your payment for a printed copy of the certificate.

Please let us know the following details, so we can process your certification accordingly.

1>        Certification number
2>        Aspen registered Email ID

Also, help us by providing your current mailing address with a registered mobile number in the following format, so that we can send you the welcome kit to the correct address.

Address:
City:
State:
Country:
Postal Code:
Mobile Number:


Have a nice day!

Best Regards,
```

# 実物はどのようなものか？

2022/1/17　の申し込みから、約１ヶ月ほどの 2022/2/17 に到着しました。

以下のような簡易的なビニールの封筒で届きます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44348/8fcd2d2b-edf1-74fd-949c-ca760ae7f7d9.png" width="50%">

ビニールの封筒の中には、更に紙の封筒があります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44348/868ce680-a431-f9aa-5b72-06bc84f41e62.png" width="50%">

紙の封筒の裏には厳重に注意書きがあり閉じられています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44348/63887aec-305c-265b-b9f4-5bbcc50432ea.jpeg" width="50%">

証書がでてきました。紙質はそこそこです。

![omote.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44348/cf1a7ca8-555c-01ee-01b9-8a90594cb8ec.jpeg)

証書の裏には EC-Council と書かれた裏紙です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44348/ff4d7730-dd61-c82b-347c-366925ec6028.jpeg" width="50%">