OmniAICreator/Qiita-1.07M huggingface dataset:
echo -eオプション

はじめて学ぶバイナリ解析を読んでいて
echoコマンドで-eを指定すると
数字で渡したASCIIコードを文字に変換する事が出来ると知った

そもそも、echo コマンドのオプションeは
エスケープシーケンスを解釈するという意味

</br>
##echoコマンド
```
echo -e "\x21"
!
```

#    エスケープシーケンス
###     \a
アラート文字(ベル,beep音)を表示します。

```bash
echo -e "ALERT\a"
ALERT
```





### \b
バックスペース文字を表示します

```bash
echo -e "BACK\b　"
BAC

echo -e "BACK\bH"
BACH
```

### \c
\cの後ろに指定した文字は出力されない

```bash
echo -e "TEST\cTEST"
TEST
```

### \f
フォームフィード文字（改ページ）
>フォームフィードはプリンターで改ページすること
>紙送りをして、次の用紙の先頭から印刷すること。 また、そのための制御文字（FF）のこと。

```bash
echo -e "TEST\fTEST"
TEST
    TEST
```

### \n
改行文字

```bash
echo -e "TEST1\nTEST2"
TEST1
TEST2

echo -e "TEST1\n\nTEST2"
TEST1

TEST2
```

### \r
復帰文字 同じ行の先頭に戻る

```bash
echo -e "TEST1\rTEST2"
TEST2
```

### \t
タブ文字

```bash
echo -e "TEST1\tTEST2"
TEST1   TEST2
```

### \v
垂直タブ文字
垂直タブ文字を使うと垂直方向的なカーソル移動(タブ挿入)が行われる。

```bash
echo -e "TEST1\vTEST2"
TEST1
     TEST2

echo -e "TEST1\v\vTEST2"
TEST1

     TEST2
```


### \0nnn
ASCIIコードがnnn(8進数)の文字。
nnnは0から3個の8進数字
1〜3桁の8進数で表されたASCIIコードの文字（0〜7）

```bash
echo -e "\0101"
A
```

#### ASCII ⇔ 8進数変換表

|  |0 |1 |2 |3 |4 |5 |6 |7 |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|0  |NULL |SOH |STX |ETX |EOT |ENQ |ACK |BEL |
|1  |BS |HT |LF |VT |FF |CR |SO |SI |
|2  |DLE |DC1 |DC2 |DC3 |DC4 |NAK |SYN |ETB |
|3  |CAN |EM |SUB |ESC |FS |GS |RS |US |
|4  |SP |! |" |# |$ |% |& |' |
|5  |( |) |* |+ |, |- |. |/ |
|6  |0 |1 |2 |3 |4 |5 |6 |7 |
|7  |8 |9 |: |; |< |= |> |? |
|10  |@ |A |B |C |D |E |F |G |
|11  |H |I |J |K |L |M |N |O |
|12  |P |Q |R |S |T |U |V |W |
|13  |X |Y |Z |[ |\ |] |^ |_  |
|14  |` |a |b |c |d |e |f |g |
|15  |h |i |j |k |l |m |n |o |
|16  |p |q |r |s |t |u |v |w |
|17  |x |y |z |{ |&#124; |} |~ | DEL|


### \xnn
nnに16進数を表記すると16進数に対応したASCII文字が出力される

```bash
echo -e "\x21"
!
```
#### ASCII ⇔ 16進数変換表

|  |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |A |B |C |D |E |F |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|0  |NULL |SOH |STX |ETX |EOT |ENQ |ACK |BEL |BS |HT |LF |VT |FF |CR |SO |SI |
|1  |DLE |DC1 |DC2 |DC3 |DC4 |NAK |SYN |ETB |CAN |EM |SUB |ESC |FS |GS |RS |US |
|2  |SP |! |" |# |$ |% |& |' |( |) |* |+ |, |- |. |/ |
|3  |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |: |; |< |= |> |? |
|4  |@ |A |B |C |D |E |F |G |H |I |J |K |L |M |N |O |
|5  |P |Q |R |S |T |U |V |W |X |Y |Z |[ |\ |] |^ |_  |
|6  |` |a |b |c |d |e |f |g |h |i |j |k |l |m |n |o |
|7  |p |q |r |s |t |u |v |w |x |y |z |{ |&#124; |} |~ | DEL|
仕様変更に負けないでWeb版のTinderで自動スワイプする

非エンジニアの方も自動スワイプしましょう
他の記事もたくさんあると思いますが、仕様に負けないように一手間加えます

##ブラウザでスワイプする画面を開く
https://tinder.com/

##Likeボタンを右クリックして開発者ツールを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1866085/fe30e167-27fd-db18-8d30-ca41a427c04b.png)

##buttonタグを探す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1866085/29be7679-5d6c-b951-dd79-799ca862e8c8.png)

##末尾をこのように変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1866085/e0a7668b-21dd-ce37-ea99-2e92b0a0c533.png)


##consoleタブに下記をコピペ
```js
auto = setInterval(
    function () {
        document.getElementById('tinder').click();
    }, 1500)
```
なぜ Tera Term マクロには sprintf2 コマンドがあるのか

## はじめに

Tera Term のマクロ言語 TTL (Tera Term Language) には、文字列をフォーマットするコマンドが [sprintf](https://ttssh2.osdn.jp/manual/4/ja/macro/command/sprintf.html) と [sprintf2](https://ttssh2.osdn.jp/manual/4/ja/macro/command/sprintf2.html) の二種類存在します。

同じ用途のコマンドは二つも要らないように思えますが、なぜ sprintf2 コマンドがあるのか、なぜ統一されないのかを解説してみます。


## sprintf2 コマンドが生まれた経緯

TTL にはまず [sprintf コマンドが追加](https://ja.osdn.net/cvs/view/ttssh2/teraterm/source/ttmacro/ttl.c?hideattic=0&view=log#rev1.13)されました。sprintf はフォーマットされた結果の文字列を inputstr システム変数に格納します。

しかし、この仕様には次のような欠点がありました。

- [変数に関する説明](https://ttssh2.osdn.jp/manual/4/ja/macro/syntax/variables.html)を見ると、"inputstr はホストまたはユーザからの入力を受け取るシステム変数である" という設計思想になっているが、その変数を違う用途に使っている
- sprintf コマンドで文字列をフォーマットすると inputstr システム変数が上書きされてしまうので、受け取っていた文字列が暗黙のうちに削除されてしまう（inputstr 変数について上記のつもりでいると、よりハマりそう）
- 受け取った文字列 inputstr をフォーマットした場合、格納先も inputstr になるので C 言語の memcpy で領域が重複した場合のような不安がある[^1]

そこで、任意のユーザー変数に格納するように sprintf コマンドの実装を修正しようと思いましたが、この欠点に気がついたときにはすでにリリースが行われた後でした。

sprintf コマンドに互換性のない仕様変更を入れてしまうと、すでに sprintf コマンドを利用して書かれたマクロが動作しなくなってしまいます。そのため sprintf コマンドの仕様変更を断念し、[sprintf2 コマンドを追加](https://ja.osdn.net/cvs/view/ttssh2/teraterm/ttpmacro/ttl.c?view=log#rev1.14)しました。
同じ理由で、sprintf コマンドを削除して sprintf2 コマンドだけにする、ということもできませんでした。


## まとめ

sprintf2 コマンドがある理由・sprintf コマンド一つにならない理由は、一言で言えば「後方互換性」です。
行いたかった修正は、以前「[プログラマはこんなことも考えている](https://qiita.com/maya_shack/items/c34ff6ff3b9b9d2f9680)」という記事で書いた「既存の動きと両立しない」修正になるため、「壊さない」かつ「どちらも両立する仕様」にするためにこのような措置をとりました。

大げさな例を挙げると「C 言語の creat 関数が "create" に修正されなかった」「電流の向きは電子の流れる向きと逆のままになった」と似たような理由なのでした。


[^1]: 内部では直接 inputstr のメモリ領域に書き出しているのではなく、いったんバッファに入れてからコピーしているので大丈夫なはずです。
クロージャーを引数として渡す

## 渡される側の関数

```swift
func someFunction(complecation: (String, Int) -> Void) {
    complecation("Hello", 2)
    complecation("World", 3)
}
```
## 引数complecationにクロージャーを渡す

```swift
someFunction(complecation: { (text: String, number :Int) in
    for _ in 0..<number {
        print(text)
    }
})
```

## 引数ではなくクロージャーをそのまま指定

```swift
someFunction { (text: String, number :Int) in
    for _ in 0..<number {
        print(text)
    }
}
```

## 引数名を使用を省略

```swift
someFunction(complecation: {
    for _ in 0..<$1 {
        print($0)
    }
})
```
## クロージャーを先に宣言

```swift
let closer = { (text: String, number :Int) in
    for _ in 0..<number{
        print(text)
    }
}

someFunction(complecation: closer)
```

## 有用なクロージャーの使い方

Listの関数`sort()`内で比較するところを自分で実装できるようになります。

```swift
struct List<T> {
    var list: [T]
    
    init(_ list: [T]) {
        self.list = list
    }
    
    mutating func sort(compare: (T, T) -> Bool) {
        for i in 0..<list.count {
            for j in i..<list.count {
                if (compare(list[i], list[j])) {
                    let tmp = list[i]
                    list[i] = list[j]
                    list[j] = tmp
                }
            }
        }
    }
}

var intList = List([4, 7, 3, 1, 12])
intList.sort {$0 < $1}
intList.sort {$0 > $1}
```

```swift
class People {
    let age: Int
    let testScore: Int
    
    init(_ age: Int,_ testScore: Int) {
        self.age = age
        self.testScore = testScore
    }
}

var peopleList : [People] = []

for i in 0..<5 {
    let people = People(i * 5, i * 20)
    peopleList.append(people)
}

var list = List(peopleList)

list.sort {$0.age < $1.age}

list.list.forEach {
    print($0.age, terminator: ", ")
}

print("")

list.sort {$0.testScore > $1.testScore}

list.list.forEach {
    print($0.testScore, terminator: ", ")
}
```
Djangoによる非同期処理実装 in Ubuntu(Cerery,Redis)

#20220205
いくつか修正もあったので下記に移動しました。
[Djangoによる非同期処理実装(Cerery,Redis)](https://zats-firm.com/2022/02/05/django_cerery_redis%e3%81%ab%e3%82%88%e3%82%8b%e9%9d%9e%e5%90%8c%e6%9c%9f%e5%87%a6%e7%90%86%e3%81%ae%e5%ae%9f%e8%a3%85/)
Streamlit で超二次関数の 3D モデルを可視化する

# 1. はじめに
あまり聞き慣れない「超二次関数」ですが、少ないパラメータで様々な3次元形状を表現できるそうです[^1]。
パラメータが変わればどんな形状になるのか確認したくなり、Web アプリを作成したので紹介します。

[^1]: 清水 毅, 小尾 誠, 遠山 茂樹, 古屋 信幸, 超二次関数モデルによる三次元物体の認識, 2004年度精密工学会秋季大会学術講演会講演論文集, pp.1049-1050, https://doi.org/10.11522/pscjspe.2004A.0.654.0

# 2. 超二次関数
## 2.1. 定義式
複数の変形式を確認していますが、今回は、以下の定義式を用います。

$$
\left(\left|\frac{x}{a}\right|^{n_2} + \left|\frac{y}{b}\right|^{n_2}\right)^\frac{n_1}{n_2} + \left|\frac{z}{c}\right|^{n_1} = 1
$$
ここで、$n_1$ と $n_2$ は形状を変化させるパラメータ、 $a$, $b$, および $c$ は大きさをあらわすパラメータとなります。


## 2.2. 3次元形状の例

超二次関数で表現された３次元形状の例を示します。

<!-- ![fig.1](./img/fig1.png "a=1 b=1 c=1 n1=2 n2=2")
![fig.2](./img/fig2.png "a=1 b=1 c=0.5 n1=10 n2=2")
![fig.3](./img/fig3.png "a=1 b=1 c=1 n1=1 n2=1") -->
![fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409671/a312aff3-2f01-ae07-7b65-8e16c317f0e0.png "a=1 b=1 c=1 n1=2 n2=2") ![fig2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409671/3301b23d-8121-27a4-bbb2-d19ab75205f2.png "a=1 b=1 c=0.5 n1=10 n2=2") ![fig3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409671/2d790766-4d68-beab-f56a-d6b7800a41bd.png "a=1 b=1 c=1 n1=1 n2=1")


# 3. 3Dモデルによる可視化

`streamlit` で Web アプリを作成し、[share.streamlit.io](https://share.streamlit.io/ken2s/superquadrics/main/st_superquadrics.py) でデプロイしました。
具体的には下のような Web アプリで、左側のサイドバーにあるピンク色のスライダーでパラメータを調整すると、右側の3Dモデルが変化します。

https://share.streamlit.io/ken2s/superquadrics/main/st_superquadrics.py

<!-- ![streamlit.io](./img/streamlit.io.png) -->
![streamlit.io.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409671/290f3564-092e-a28a-0d88-415d976450fd.png)

# 4. python code

ここでは、コードの主要部分を抽出して紹介します。

```python
import streamlit as st
import plotly.graph_objects as go
import numpy as np

st.title('Superquadrics')

@st.cache
def superquadrics(a,b,c,n1,n2,x,y,z):
    values = np.power(np.power(np.abs(x/a),n2) \
                    + np.power(np.abs(y/b),n2),n1/n2) \
            + np.power(np.abs(z/c),n1)
    return values

st.sidebar.subheader('Parameters')
a  = 1.
b  = 1.
c  = st.sidebar.slider('c (a=b=1)', .2, 2., 1., .2)
n1 = st.sidebar.slider('n1', 1, 10, 10, 1)
n2 = st.sidebar.slider('n2', 1, 10, 2, 1)

X, Y, Z = np.mgrid[-1:1:20j, -1:1:20j, -2:2:40j]

fig = go.Figure(data=go.Isosurface(
    x = X.flatten(),
    y = Y.flatten(),
    z = Z.flatten(),
    value = superquadrics(a,b,c,n1,n2,X,Y,Z).flatten(),
    isomin = .5,
    isomax = 1,
    showscale = False,
))
st.write(fig)
```

おおまかな流れとしては、

* `def superquadrics` で超二次関数を定義
* パラメータを設定（$c$, $n_1$, $n_2$ は、`streamlit` のスライダーを使用）
* `np.mgrid` で、3次元座標を設定
* `go.Isosurface` で、`plotly` によって 3Dモデルを描画

という手順となります。

なお、`streamlit.io` にデプロイした Web アプリのソースコードについては、次の `GitHub` で確認できます。

https://github.com/ken2s/superquadrics/


# 更新履歴

* 2021/08/09 初稿


# 参照

https://en.wikipedia.org/wiki/Superquadrics

https://docs.streamlit.io/en/stable/deploy_streamlit_app.html

https://tech.ledge.co.jp/entry/2020/10/20/120000
UEFIマシンからのP2Vで気を付けること（Proxmox）

お世話になります。

前回の手順で古いノートPCをVHDX化し、P2Vしようとしたところ、"Not a bootable disk..."でフリーズする現象が起きました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/3feedb16-1842-17a5-c0d3-3f3950bc02ba.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/8267670d-08b0-1418-3cd7-5de68c7c3552.png)



Proxmoxの公式フォーラムによると、レガシーBIOSではなくUEFIマシンの場合、Proxmoxのゲスト側でもそのように設定する必要があるとのことです。
https://forum.proxmox.com/threads/migration-from-hyper-v-stuck-on-booting-from-hard-disk.56108/

そこで以下のようにSeaBIOSからUEFI仮想BIOSに変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/46ca7df9-bbbb-4135-07de-d34befa3afe5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/7a7758fe-3bbd-00b4-d831-f390b0c45ae6.png)

EFIディスクの追加が必要とのことで、追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/bda965e8-d32f-1cee-edea-5ed31cecad0b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/b8358118-c298-7d71-349f-10a3c65168d9.png)

すると起動しました。メーカーロゴのまま、Win10のローディングスプラッシュが表示されるのがUEFIマシンの特徴のようです。P2V前に再起動することで見分けることができそうですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/350c8154-5881-59b4-61d1-4cdb19fcfdc8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/aef90e04-260b-cb23-963c-2d9fffb75c92.png)

最近のPCはほぼUEFI BIOSなので、P2V時には留意します。受け皿となる仮想マシンの作成時に最初からUEFIを選んでおけばトラブルは少ないと思われます。
[テスト]FactoryBotにimageを記述する

# はじめに
本記事は、テストコードに関するもので、
FactoryBotにimageを記述する方法（factoriesディレクトリ）を記述します。

本日、何時間も悩んだものになるので、
短いですが、アウトプットしたいと思います。

単体テストコードに関する記事は、以下も参照してください。
内容的には、ターミナルにて以下を記述後のこととなっております。

```
% rails g rspec:model テーブル名
```

https://qiita.com/mkato1013/items/5236f16b03854b0cec0e

# FactoryBotにActiveStorageの記述をする
## 例
早速ですが、例文です。

```ruby
FactoryBot.define do
  factory :tweet do
    content {Faker::Lorem.sentence}
    association :user

    after(:build) do |tweet|
      tweet.image.attach(io: File.open('ディレクトリ名/画像ファイル名'), filename: 'ファイル名')
    end
  end
end
```

### afterメソッド
任意の処理の後（ここでは、（:build））の後に、
指定の処理(（:build）以降の処理)を実行することができます。

### io: File.open
ここで設定したパスのファイル（'ディレクトリ名/画像ファイル名'）をfilenameを'ファイル名'として実行しています。

### association
今回の趣旨とは、やや離れますが、
対象のテーブルとのアソシエーションも忘れずに記述しましょう。

```
association :user
```

## 実際にしてしまったミス
①テーブルのカラムに存在すると勘違いしてしまい、
今回の例文に沿って記述すると

```ruby
// （注意）謝った記述です。

FactoryBot.define do
  factory :tweet do
　　　　　　　　image {'ディレクトリ名/ファイル名'}     ←間違い！！
    content {Faker::Lorem.sentence}
    association :user
  end
end
```
と記述してしまった。

②カラムに存在しないことがわかり、アソシエーションするのかと勘違いした。

```ruby
// （注意）謝った記述です。

FactoryBot.define do
  factory :tweet do
    content {Faker::Lorem.sentence}
    association :user
　　　　　　　　association :image　　　　　　　　　　　　　　　　　←間違い！！
  end
end
```

# 終わりに
学習したことでしたが、全く初見のように思えてしまいました。
このようなことは今後も増えてきてしまうかと思いました。

しかし、忘れているのなら、
次は、理解して覚えていたら良いことです。

後ろは、フィードバックする時以外は向かず、
新しく出てきたものや、再度登場してきたものをどんどん理解していきたいと思います。

それでは、
明日も頑張りましょう！！
Vagrantで作成した環境の複製手順

# はじめに
本記事ではVagrantで作成した環境(Box)を複製する手順を記載します。
複製手順は下記です。

1. パッケージ化
1. パッケージ化したBoxを登録
1. Vagrantfile作成
1. Vgrantfile編集
1. 起動

# 1. パッケージ化

複製したいVagrantfileがあるディレクトリに移動します。
下記コマンドでboxのパッケージ化を実施します。
実行が完了すると現在ディレクトリに XXX.boxファイルが生成されます。

```:パッケージ化
$ vagrant package --output [任意のbox名].box
```

# 2. パッケージ化したBoxを登録

複製後のVagrantfileを配置するディレクトリに移動し、XXX.boxファイルを配置します。
下記コマンドでBoxを登録します。

```:Box登録
$ vagrant box add [任意のbox名] [パッケージ化したbox名].box
```
```:Box登録確認
$ vagrant box list
[パッケージ化したbox名]          (virtualbox, 0)　　# 表示されていればOK
```

# 3. Vagrantfile作成

下記コマンドで登録したBoxのVagrantfileを作成します。
現在ディレクトリにVagrantfileが作成されていることを確認してください。

```:Vagrantfile作成
$ vagrant init [登録したBox名]
```

# 4. Vgrantfile編集

複製元のVagrantfileと比較し、変更が必要であれば変更してください。
不要の場合は次へ進む。

※複製元と複製した仮想マシンを同時に起動した場合、private_networkのIPアドレスやポートフォワーディングのポートなどが同じだとエラーになり起動に失敗します。

# 5. 起動

下記コマンドでvagrantを起動します

```:起動
$ vagrant up
```
【Python】クラス変数の取り扱いを確認する

python のクラス変数とインスタンス変数で、クラス変数の内容を変更したときにインスタンスに与える影響について確認してみました。

https://docs.python.org/ja/3/tutorial/classes.html#class-and-instance-variables

**クラス変数:**

>クラス変数はそのクラスのすべてのインスタンスによって共有される属性やメソッドのためのものです

**インスタンス変数:**

>インスタンス変数はそれぞれのインスタンスについて固有のデータのためのもの

検証のために ``Dog`` クラスを用意します。

```python
class Dog:
    tricks = []
    kind = 'pug'

    def __init__(self, name):
        self.name = name
    
    def add_trick(self, trick):
        self.tricks.append(trick)

    def change_kind(self, kind):
        self.kind = kind
```

``Dog`` クラスからインスタンスを 2 つ作ります。

```python
fibo = Dog('Fibo')
buddy = Dog('Buddy')
```

ここからクラス変数の挙動を確認してみます。クラス変数はすべてのインスタンスに共有されているので、クラス変数 ``trick`` に対して ``fibo`` インスタンスでの変更が ``buddy`` インスタンスに共有されるか確認します。

```python
fibo.add_trick('roll over')

print(buddy.tricks)
# ['roll over']
```

また、``Dog`` クラスをインスタンス化させなくてもすべてのインスタンスに対して影響を与えています。

```python
Dog.tricks.append('stay')

print('fibo:', fibo.tricks)
# fibo: ['roll over', 'stay']
print('buddy:', buddy.tricks)
# buddy: ['roll over', 'stay']
```

クラス変数 ``kind`` も検証してみます。``change_kind`` メソッドを呼び出して ``kind`` の値を変更し別のインスタンスで変更が反映されるか確認します。

```python
fibo.change_kind('golden retriever')

print('fibo:', fibo.kind)
# fibo: golden retriever
print('buddy:', buddy.kind)
# buddy: pug
```

``fibo`` インスタンスでの変更は ``buddy`` インスタンスに影響を及ぼしませんでした。``change_kind`` メソッドではクラス変数の ``kind`` ではなく インスタンス変数の ``kind`` に変更を加えているのでした。クラス変数とインスタンス変数が同じ名前の場合は、インスタンス変数が優先されます。

```python
def change_kind(self, kind):
    self.kind = kind
```

クラス変数 ``kind`` を変更してみます。

```python
Dog.kind = 'bulldog'
```

各インスタンスの状態を確認します。

```python
print('fibo:', fibo.kind)
# fibo: golden retriever
print('buddy:', buddy.kind)
# buddy: bulldog
```

``fibo`` インスタンスの方は ``change_kind`` メソッドを使用してインスタンス変数を定義したのでインスタンス変数を取得しているのに対して、``buddy`` インスタンスはインスタンス変数 ``kind`` が存在しないのでクラス変数 ``kind`` を参照し、``Dog.kind`` での変更の影響を受けております。

最後に、オブジェクトの属性を確認します。

```python
print(vars(fibo))
# {'name': 'Fibo', 'kind': 'golden retriever'}
print(vars(buddy))
# {'name': 'Buddy'}
```
Ubuntu環境を構築する

Ubuntu環境を構築した際に少しつまづくポイントがあったので忘れないためにメモします。
今回僕は、WindowsとのデュアルブートでUbuntu自体は外付けSSDに保存する方法をとりました。



## Ubuntuのダウンロード
以下のURLからUbuntuをダウンロードします。
[https://jp.ubuntu.com/download](https://jp.ubuntu.com/download)

ここでは「Ubuntu Desktop 18.04.4 LTS」を選びました。
isoイメージファイルがダウンロードできます。



## ブートディスクの作成
USBを使用してブートディスクを作成します。

USBはこちらを使用しました。

https://www.amazon.co.jp/dp/B07DPVTYW7

<br>
[Rufus](https://rufus.ie)というツールを使用します。
「ブートの種類」に先程ダウンロードしたisoイメージファイルを選択します。
「スタート」をクリックし、「ISOイメージモード」で書き込みます。
<img width="300" alt="install-ubuntu-1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/35215eb5-db5f-471a-570d-bfa0f0ee2941.jpeg">

完了したら再起動します。



## UEFIの設定
起動中のロゴ画面でF2ボタンを押し続けると、以下のようなUEFI（BIOS）画面になります。
<img width="600" alt="install-ubuntu-2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/84205a88-1836-b2e0-40df-973788165a1f.jpeg">

ここでディスクの起動順位を変更し、Ubuntuが起動されるように設定します。



## ブートオプションの設定
インストールする場合は「Install Ubuntu」を選択します。
<img width="600" alt="install-ubuntu-3" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/8d5de537-f5c2-646d-f357-3e9468b0ff54.jpeg">

しかし、僕の環境ではインストール時に画面がフリーズしてしまいインストールできませんでした。
調べてみると、CPUがRyzenだと起こる現象のようです。

CPUがRyzenの場合は「Install Ubuntu」にカーソルを合わせ、eキーを押し編集画面を表示します。
linuxから始まる行の最後にnomodesetと追加し、Ctrl+xを押すと、Ubuntuのインストールが始まります。



## Ubuntuのインストール
以下手順です。

1. 「日本語」を選択
2. 「通常のインストール」、「Ubuntuのインストール中にアップデートをダウンロードする」を選択
3. 「ディスクを削除してUbuntuをインストール」を選択
4. 「ドライブの選択」で外付けSSDを選択
5. 「インストール」をクリック

これでインストールが開始されます。
<br>
SSDはこちらを使用しました。

https://www.amazon.co.jp/dp/B07B6HNFB2

<br>
インストールが完了すると以下のような画面が表示されるので、各種項目を入力すれば終わりです。
<img width="600" alt="install-ubuntu-4" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/fd3479e2-a850-3354-9737-c7caa5cda51f.jpeg">



## 起動確認
起動すると、以下のような画面が表示されるようになります。
<img width="600" alt="install-ubuntu-5" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/82579906-f271-9b14-8233-538d6acd4fbd.jpeg">

「Ubuntu」を選択するとUbuntuが起動し、「Windows Boot Manager（on /dev/sda2）」を選択するとWindowsが起動します。

これでWindowsとUbuntuのデュアルブート環境が構築できました。



## 参考サイト
[https://insilico-notebook.com/ubuntu-18-04-2-lts-install/](https://insilico-notebook.com/ubuntu-18-04-2-lts-install/)
WindowsでのUbuntu/Dockerを使った開発環境構築[2021] part2

# はじめに

この記事は[前回](https://qiita.com/tn_movie/items/9dff4a9cccc4336200f0)の続きになっております。
気が向いたらそちらもご覧ください。


# おさらい

現状、WindowsPC上にDocker DesktopとWSL2で動くUbuntuのインストールまで完了しました。
一応Ubuntu上でpythonを動かす最低限の設定もしていますが、これは念のためです（前の記事書いたときにそんな深く考えてなかった。。。）


# これからの流れ

* python3開発環境用のDockerfileの作成
* 起動する用のdocker-compose.ymlの作成
* コンテナの起動
* VSCodeでContainer内に入って開発

***ここで力尽きたので、以下あとでちゃんと書きます。。。***

## python3開発環境用のDockerfileの作成

いい感じに作りましょう。
（あとでサンプル載せます）
ポイントはrequirements.txtを使って必要なライブラリを管理しましょうというくらいですかね。


## 起動する用のdocker-compose.ymlの作成

今回の一番のポイント。
コンテナは、コードを実行せずに起動すると即終了します（たぶん）。
ymlファイルの中に`stdin_open: true`を記述することです。
これで標準入出力をopenにしてコンテナが停止するのを防げます.
（あとでサンプル載せます）


## コンテナの起動

composeファイルで楽したので、`docker-compose up` しましょう。
もしDockerfileを変更したりしたら、`--build`もお忘れなく。


## VSCodeでContainer内に入って開発
左に出ているRemote ExplorerでContainerを選択すると、入れます。


勢いでとりあえずメモ程度に走り書きしたので、随時更新していく予定でやんす。
あー夏休みーー。
Home brewの導入法

#Homebrewとは
パッケージ管理システムで色々なツールを簡単に導入するための道具。

ex)Ruby Vim Dockerなどを導入する時に使う。
``` 
$ brew install XXXXX
```

下はまずHomebrewmを導入するための作業である。

#コマンドラインツールの導入とXcodede
Xcodeとは
Apple製品向けのアプリを作るためのもので全てインストールすると6GB以上ありかなり重い。

1 ターミナルを立ち上げる。
*ターミナルがを導入していない場合は
https://qiita.com/Hashimoto-Noriaki/items/383166175572049bd689
から導入。

2　Xcode導入

```
$ xcode-select --install
```
*開発に使うコマンドを使うための道具のみをインストールする。

そのままインストール
*時間がかかる

3コマンドラインツールがすでにインストールされているとエラーが出た時
Xcodeを開き左上のXcodeを右クリックで選択し,
Open Developer Toolを選択。More Developer Toolsを選択しApple Developerにサインインする。
自分のアップルアカウントでログイン。
More Downloads for Apple Developers の画面にいき,
Command Line Tools for Xcodeの最新バージョンを選択。*beta版ではないものを選択。
これをダウンロード。*右にCommand Line Tools for Xcodeバージョンとなっているところ


#Home brewの導入
1公式サイトを見ながら導入。
https://brew.sh/index_ja

公式サイトな中のインストールの部分

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
をターミナルに貼り付けて実行。*RETURNキーで実行。

2 passwordを聞かれる。
*パスワードはMacを起動する時のもので出力されないが入力はできている。

3 RETRUNキーで実行
下のような表示が出てくるがRETRUNキーで実行。

```
press RETURN to continue or any other key to abort
```

4 インストール成功

```
Installation successful!
```
が出ていればインストール完了。

5 導入の確認

```
taro@MacBook-Pro ~ % brew --version
Homebrew 3.2.2
Homebrew/homebrew-core (git revision f7bd1179a3; last commit 2021-07-15)

```
バージョンが出ていれば導入成功。
データベースで作成したビューをLaravelに取り込む

#はじめに
MySQLで作成したビューをLaravelに取り込む方法についてメモ感覚で。

1. MySQLで作成したビューのモデルを作成する。
2. ORM（Eloquent）を用いてレコードを取得する。

#開発環境
・Laravel 7.30.4
・MySQL 5.7.32

#プロジェクト作成
テキトーにプロジェクトを作成します。

```php
composer create-project --prefer-dist "laravel/laravel=7.*.*" hoge_app
```

#.envファイルの変更
DBの設定を行います。
使用するDB名はテキトーに作ってください。

```<p>.env</p>
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=world
DB_USERNAME=##########
DB_PASSWORD=##########
```
<br>

.envファイルの設定が終わったらプロジェクトのディレクトリに移動して、下記コマンドを実行してください。

```php
php artisan config:cache
```
>これを実行しないと変更内容が反映されないので必ずするように…

#疎通確認（マイグレーションの実行）
下記のコマンドを実行して.envで指定したDB上にテーブルが作成出来ていれば、疎通確認はOKです。

```
php artisan migrate
```
>失敗したらユーザ名やパスワードが間違っている可能性があるので再度ご確認を…

#モデルの作成
私は「v_countryinformation」というビューを作成しました。
ちなみにレコードはこんな感じです。
![v_countryinformation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647483/f5b0b976-06c5-5351-f695-1ac94a4313d3.png)

ビューの作成が終わったら、モデル作成を行うコマンドを実行します。
下記のコマンド実行後、Appディレクトリに「モデル名.php」というファイル（今回はCountryInfo.php）が作成されます。

```php
php artisan make:model CountryInfo[=モデル名]
```
<br>
作成されたモデルクラスに以下のプロパティを追加し、参照するビューを指定してください。

```php:CountryInfo.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class CountryInfo extends Model
{
    /**
     * 
     * モデルと関連するビューを指定する
     */
    protected $table = 'v_countryinformation';
    
}
```
<details><summary>備考：テーブル名とモデル名の規則性</summary>
モデルに対してどのテーブルを使用するかを$tableで指定しなければ、自動的にクラス名の複数形のテーブルを参照します。
例えば、Personモデルが参照するテーブルはPersonの複数系であるPeopleテーブルとなります。
</details>

#Eloquentを使ってビューのレコードを取得
今回はtinkerで取得出来ているかの確認をするので、下記のコマンドからtinkerを起動します。

```
php artisan tinker
```
起動できたらEloquentを使用してレコードを取得します。

```
App\CountryInfo::where('Language', 'English')->first();
=> App\CountryInfo {#3351
     Code: "ABW",
     CountryName: "Aruba",
     CountryPopulation: 103000,
     Code2: "AW",
     Capital: 129,
     CityName: "Oranjestad",
     CityPopulation: 29034,
     Language: "English",
     IsOfficial: "F",
     Continent: "North America",
     Region: "Caribbean",
   }
```
上手く取得出来たようですね。
>上記の結果は次のクエリの結果と同等です。
SELECT * FROM v_countryinformation WHERE Language = 'English' LIMIT 1

また、当然ですがクエリビルダを使っても取得出来ます。

```
DB::table('v_countryinformation')->where('Language', 'English')->first();
=> {#3366
     +"Code": "ABW",
     +"CountryName": "Aruba",
     +"CountryPopulation": 103000,
     +"Code2": "AW",
     +"Capital": 129,
     +"CityName": "Oranjestad",
     +"CityPopulation": 29034,
     +"Language": "English",
     +"IsOfficial": "F",
     +"Continent": "North America",
     +"Region": "Caribbean",
   }
```

#まとめ
ダラダラと書きましたが、要するにモデルクラスの$tableプロパティにビューを指定すれば良いということです。

クエリビルダにはテーブルを結合するjoinメソッドもあるので、わざわざビューを作る必要も無い気がしますが、個人的にはプログラム内でテーブル結合させるよりはビュー内でそれを行い、そのビューに対してフィルターをかけた方が少ないコードの量でデータを取得できるので良いなと思いました。

#参考
https://readouble.com/laravel/7.x/ja/eloquent.html
ドッキングシミュレーションをやりたい人の備忘録①

# AmberTools21をインストールしたい！
環境構築って躓きどころがたくさんありますよね。
わかるわかる。
私が初めて環境構築という言葉に向き合ったのはPythonの勉強をし始めたとき。
Anacondaのインストールの方法すらおぼつかないレベルでした。

私は現在創薬化学を学ぶ修士の学生ですが、計算とは全く関係のない研究室に所属しているため、なんとか自力で化合物とタンパク質間のドッキングシミュレーションを行うことを目指しています。

でもネットに載ってる情報って<b>当たり前じゃないことが当たり前のように書いてある</b>し初心者にはハードル高すぎです。
そんな学生が私以外にもたくさんいるのではないでしょうか？？

私はそんな人々の光になりたい！という思いで<b>初心者目線のドッキングシミュレーション</b>、しかも全て無料でできる方法を模索しております。
大体完成に近づいてはいますがブラッシュアップなどを行なっております。
半年くらいかけて全て公開して、創薬化学を学ぶ全ての学生の力になれれば良いなと思います。

※用語解説などに間違いがあることが予測されます。有識者の方はそっと教えてください。

#PC環境
Mac OS Big Sur 11.2.1
プロセッサ:3.2GHz 6core intel core i7
メモリ:64GB 2667MHz DDR4
グラフィックボード:なし

#インストールしてみよう
基本的には公式サイトのoption2に則ります。

[Download Amber MD](https://ambermd.org/GetAmber.php)
option1は前のバージョンがインストールされている人向け、option3も試しましたがmakeの段階でエラーが出たのでoption2が最もスムーズにできると思います。

まずはcondaを使えるようにする。

```html
brew install conda
```

次にcondaまでのPATHを通す。

```html
export PATH="$PATH:~/bin"
```

option2に従ってインストールする。（1行ずつ入力してね）

```html
conda create --name AmberTools21
conda activate AmberTools21
conda install -c conda-forge ambertools=21 compilers
conda update -c conda-forge ambertools
```

これでambertools21のインストールは完了。このファイルはcondaが格納されているファイルのenvsに入っているので、ambertoolsまでのPATHを通しておくと楽。

```html
export PATH="$PATH:~/envs/AmberTools/bin"
```

これでどのディレクトリからでもantechamberなどが使えます。
antechamberでどんなことができるのかなどは他の方が詳しく説明をされているのでそちらをご覧になってください。
[antechamberを使ったMD用小分子化合物の電荷パラメータの作り方 - Qiita](https://qiita.com/Ag_smith/items/430e9efb32a855d4c511)
Node.jsからVOICEVOXを使ってみる。


思い出しながらソースをペーストしているので違ってる部分もあるかも
解説というより思い出す為のメモ程度だと思ってください。

# VOICEVOXとは
つよつよエンジニアが作った音声読み上げソフト、詳しくはここ見て
https://voicevox.hiroshiba.jp/

# こんなツイートがあったので試してみた
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">「 <a href="https://twitter.com/hashtag/VOICEVOX?src=hash&amp;ref_src=twsrc%5Etfw">#VOICEVOX</a> を外部のソフトウェアから使えますか？」という質問をよく貰います。すごく簡単に使えます！<br><br>VOICEVOXの音声合成エンジンはローカルにHTTPサーバーが立っているだけなので、こんな感じでPOSTを叩けばテキスト読み上げができます。<br>詳しくは localhost:50021/docs をご覧ください。 <a href="https://t.co/JFg2xMLgGK">pic.twitter.com/JFg2xMLgGK</a></p>&mdash; ヒホ（ヒロシバ）🗑️ (@hiho_karuta) <a href="https://twitter.com/hiho_karuta/status/1423038523058233344?ref_src=twsrc%5Etfw">August 4, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# とりあえずやりたいこと
Node.jsを使用してVOICEVOXで読み上げデータを作りたい。

# 準備&インストール
npm install axios
npm install fs

VOICEVOXに含まれている VOICEVOX-0.1.1-win/run.exe を起動しておく
すると http://localhost:50021 に接続することができる。
http://localhost:50021/docs にかかれているメソッドの結果を組み合わせると音声パラメータや音源を生成することができる。

# 実装
```index.js
const { default: axios } = require("axios");
const fs = require("fs");

//axios=通信するやつ
//httpを省略するとうまく接続できなかったのでしっかり書いておく。
const rpc = axios.create({ baseURL: "http://localhost:50021", proxy: false });


//text:喋ってもらいたい言葉
//filepath:保存先
//ex:genAudio("こんにちは","./greeting.wav");
async function genAudio(text, filepath) {
    
    /* まずtextを渡してsynthesis宛のパラメータを生成する、textはURLに付けるのでencodeURIで変換しておく。*/
    const audio_query = await rpc.post('audio_query?text=' + encodeURI(text) + '&speaker=1');

    //audio_queryで受け取った結果がaudio_query.dataに入っている。
    //このデータをメソッド:synthesisに渡すことで音声データを作ってもらえる
    //audio_query.dataはObjectで、synthesisに送る為にはstringで送る必要があるのでJSON.stringifyでstringに変換する
    const synthesis = await rpc.post("synthesis?speaker=1", JSON.stringify(audio_query.data), {
        responseType: 'arraybuffer',
        headers: {
            "accept": "audio/wav",
            "Content-Type": "application/json"
        }
    });

    //受け取った後、Bufferに変換して書き出す
    fs.writeFileSync(filepath, new Buffer.from(synthesis.data), 'binary');
}
genAudio("こんにちは","greeting.wav");
```

偶に読み上げに失敗するとステータス500が返ってきたりするので、うまくいかないときは特殊文字とかが含まれてたり
読ませたい文字が長すぎではないかを確認する。
再起動などするとうまくいくときもある。
# 結果
greeting.wavが生成されている、再生すると可愛い声の「こんにちは」を聞くことができる。

# そのうちやりたいこと
Chrome拡張とか作って選択箇所を読ませるのを作りたい。
追記：作ってみたけど実用的ではない速度でした。（大体1ツイート30秒くらい）←しょうがない、というか十分速いです
「一粒で四度おいしい」的なサイトの紹介

Google翻訳で読んだだけで、それだと多少不自然な訳になっちゃうところもありましたが、それ以上に「お～！」って思ったサイトがあったので、是非とも紹介したいです。

それは[TkDocs Home](https://tkdocs.com/ "TkDocs Home")というサイトです。

GUIを実現するためにTkを使用しているスクリプト言語はいくつかありますが、このサイトではTkの説明をしつつ、Tcl、Python、Ruby、Perlでの扱いを同時並行的に解説しています。すげー！

私はTclしか使えないのですが、それでも「へ～、これをPythonで書くとこうなるのか」とか、「同じことするのにだいぶコード量が違うなー」とか、妙に感心しながら興味津々で楽しく読めました。

内容的にも、各ウィジェットのオプションや外観の説明よりは、概念やバックグラウンド的ないわゆる設計思想的な内容に重きを置かれていて、Tcl/Tkを使っているうちに何となく「こういうことなのかな～」と自己流に解釈していた部分を明確に解説してくれていたりして、とても興味深いです。
Rasberry Pi ImagerでVerifying write failed.が発生する場合の対処

Rasberry Pi ImagerでSDカードに書き込むと`Verifying write failed.`が発生する場合の対処方法。

## Rasberry Pi Imagerのエラーメッセージ
:::note alert
Verifying write failed. Contents of SD card is different then what was written to it.
:::

##エラー発生環境
* Raspberry pi 4 Model B 8GB RAM
* Samsung EVO Plus マイクロSDカード 64GB microSDXC UHS-I U1
* Raspberry Pi Imger v1.6.2
* Raspberry PI OS(32-bit) Released 2021-05-07


##原因
どうやら`64GB microSDXC`に書き込むとこのエラーが発生するようだ。

`32GB microSDHC`に書き込めば解決。

##正常動作環境
* Raspberry pi 4 Model B 8GB RAM
* Samsung EVO Plus マイクロSDカード <font color="Red">32GB microSDHC</font> UHS-I U1
* Raspberry Pi Imger v1.6.2
* Raspberry PI OS(32-bit) Released 2021-05-07
eclipseでJDK Mission Control（jmcプラグインを導入）を利用してみる

#目的
Javaのパフォーマンスチューニングを目的とし、以下ツールを利用して計測したデータを元にボトルネックとなる箇所の分析を行えるようにするため、実施した手順を残しておきます。
今回はeclipseから実施できることを主目的としています。
（eclipse以外での実行、プロファイリングレポートの分析等についてはまた余力を見て記事にできたら、と思います）

- JMC（JDK Mission Control）
- JFR（JDK Flight Recorder）

#記載範囲
本記事ではeclipseで「Mission Control」の使ってみるため、プラグインとして導入してプロファイリングレポートを確認するところまでを記載します。

#前提条件
- エディション：Windows10 Pro
- eclipseバージョン：Version: 2021-06 (4.20.0)
- JDK Mission Control Plug-ins for Eclipse：バージョン8.0.1

#プロファイリングツール
JDK11より以前では、JDK Mission Control（以降JMC）は商用利用目的ではライセンスが必要でしたが、JDK11以降はJava Flight Recorder、Java Mission Controlがオープンソース化されています。
（JMCの方が使いやすく、情報量も多そうだったので今回はJMCを使ってみる事にしました）
その他には[VisualVM](https://visualvm.github.io/)等、利用できるツールはあるようです。

#eclipseプラグインにjmcを導入
  1. eclipse上で「ヘルプ」→「新規ソフトウェアのインストール」を開き、作業対象に以下URL（https://download.oracle.com/technology/products/missioncontrol/updatesites/openjdk/8.0.1/ide/）をコピペする。
  1. Mission Controlにチェックを入れ、「次へ」ボタンを押下する。
![eclipse_plugins_jmc_install.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32811/9b47b5cc-3a14-4cf8-b995-052b2d5d0f96.png)
  1. ライセンスのレビュー画面にて、「使用条件の条項に同意します」を選択し、「完了」ボタンを押下する。
![eclipse_plugins_jmc_license.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32811/082606d9-d2de-0ed8-a755-af6abf83ee99.png)

#Mission Control画面を開く
  1. eclipseから「パースペクティブを開く」を選択し、「Mission Control」を開く。
![eclipse_jmcパースペクティブを開く.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32811/1cd7c276-f35c-17ad-013a-27c9191cb8bb.png)

#eclipseからFlight Recorderを起動し、プロファイリングを開始
  1. Flight Recorderを右クリックし、「Start Flight Recording」を選択する。
![eclipse_plugins_jmc_start.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32811/17d45c59-3e67-d156-552c-ea07b17a9ed4.png)
  1. Time fixed Recordingの「Recording time：」に記録したい時間（例：60分なら、60 min）を指定して「完了」ボタンを押下する。
![eclipse_Start Flight Recording.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32811/a1c148ee-7b3c-4bc0-26b5-e6f3b21d9165.png)
  1. パフォーマンスを計測したいJavaプログラムを実行します。

#プロファイリングデータを確認
  1. eclipse上からMission Controlプロジェクト（開いているworkspace内に作成されている）を開く。
![eclipse_Mission Controlプロジェクト.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32811/0e140637-de58-1de4-6ea6-660307653526.png)
  1. 「.jfr」ファイルが作成されているので開く。
![eclipse_jfrレポート.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32811/f12095af-e455-ff21-3cef-6d9486184610.png)
  1. eclipseのアウトラインから、「環境」→「プロセス」を開いてみる。
![eclipse_jfr_sample.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32811/6d09595e-b06a-9ab2-d75c-5b5f7613e822.png)

#次回の予定
サンプルJavaを実行し、Flight Recorderで出力したレポート結果を分析できたら良いな、と思っています。
Rustの文と式

式と文の違いで戸惑ったのでメモ。
間違っているところもあるかもしれない。

#文と式の違いとは
文：値を返さない命令のこと。ただし何らかの行動はとる（変数を作成など）。
式：値を返す命令のこと。__rustにおいては最後にセミコロンがつかない。__
rustでは文 = 文 の形にすることができない。
なので

```rust:main.rs
fn main()
{
    let mut x:i32;
    let mut y:i32;
    x = y = 10;
    println!("x:{} y:{}", x, y)
    // これはコンパイルが通らない
}
```

のようにしてx, y両方に10を代入することはできない。（C言語などでは可能）。

分かりづらいかもしれないが

```rust:main.rs
fn main() 
{
    let x = (5 + 10);
    // (5 + 10)が式であり、この行全体は文となっている
    println!("{}", x);
    // 出力結果:15
}
```
の時、```let x = (5 + 10);```　そのものは文であり、その中で```(5 + 10)```のところは式である。

rustでは{}は式と扱われるので

```rust:main.rs
fn main() 
{
    let x = {
        let y = 5;
        // これは文
        y + 10
        // 式なのでここにはセミコロンがつかない
    };
    // {}自体が式であり、ここでは15を返している　let x = ... の部分全体は文である
    println!("x is {}", x);
    // 出力結果:x is 15
}
```
のようにxを宣言できる。

#まとめ
__rustではセミコロンがついているのは文、ついていないのは式である。
文 = 文 の形はできない。__

#参考
https://doc.rust-jp.rs/book-ja/ch03-03-how-functions-work.html
Outlook のメールファイル（.msg ファイル）をテキストに展開するツールを用意しました

（この記事は [地平線に行く](https://yujisoftware.hatenablog.com/entry/msg2txt) とのマルチポストです）

たまに、Outlook のメールファイル（.msg ファイル）が添付で送られてくるのですが、手元に Windows 版の Outlook がなくて[^outlook]内容を確認できなくて困ることが多々…。

そこで、.msg ファイルをテキストファイルに展開するツールを用意しました。
（添付ファイルも展開できます）

[YujiSoftware/msg2txt: Extract .msg file (Outlook mail file) to a text file. ](https://github.com/YujiSoftware/msg2txt)

インストーラ版の方には Java ランタイムが含まれていますので、どの環境でもすぐに使えます。
自分のお気に入りの Java ランタイムを使いたいという場合は、スタンドアローン版をご利用ください！ [^jdk]

[^outlook]: macOS 版の Outlook だと、.msg ファイルを開けないです。
[^jdk]: スタンドアローン版は Java 8 以上に対応しています。

# 実装について

[Apache POI-HSMF](https://poi.apache.org/components/hsmf/index.html)（Java API To Access Microsoft Outlook MSG Files）の[サンプルプログラム](http://svn.apache.org/viewvc/poi/trunk/poi-examples/src/main/java/org/apache/poi/examples/hsmf/Msg2txt.java?revision=1890117&view=markup)をビルドしただけです。

# 頑張ったところ

それだけだと面白みがないので、**Java 15 で正式リリースされた [Packaging Tool](https://openjdk.java.net/jeps/392) を使って、インストーラ版も作ってみました。**
… といっても、[適切な引数を指定して jpackage コマンドを実行するだけ](https://github.com/YujiSoftware/msg2txt/blob/703b211ae495861f64726608f78cee5e5be2399d/build.gradle#L44-L109)でいい感じのインストーラができあがるので、とても簡単でした。

なお、手元に macOS のビルド環境はないので、**インストーラの作成には GitHub Actions を使いました。**[^mac]
[`runs-on: macOS-latest` と指定するだけ](https://github.com/YujiSoftware/msg2txt/blob/703b211ae495861f64726608f78cee5e5be2399d/.github/workflows/gradle.yml#L80)でいい感じの環境でビルドしてくれるので、マニュアル通りに書いていくだけでサクッと使えました。
これ、便利ですね（いまさら感）。

[^mac]: 作れはしたけど、動作確認ができていないです…。どなたか、[サンプルファイル](http://svn.apache.org/viewvc/poi/trunk/test-data/hsmf/attachment_test_msg.msg?view=log)を展開できるかどうか確認していただけると嬉しいです。

# まとめ

というわけで、ぜひご利用ください！
web会議時のスピーカーとマイクの挙動について調べてみた

web会議時のスピーカーとマイクの挙動がよくわからないので調べてみました。
もしかしたら、使用しているイヤホンやweb会議システム、立ち上げる順番によって違うかもしれまん。

# 環境
* PC … DELL Inspiron 15 7000 Gaming（ノートPC）
* OS … Windows10 64bit
* web会議システム … Microsoft Teams（アプリ版）
* イヤホン … Anker Soundcore Life U2（Bluetoothイヤホン）

# 問題点
通常接続した状態であれば、ブラウザやメディアプレーヤーなどで再生している音がイヤホンから聴こえる。
web会議システムに接続した途端、web会議システム以外の音が聴こえなくなる。

# イヤホンについて
私が使用している Anker Soundcore Life U2 というBluetoothイヤホンには、２通りのデバイスがあるっぽいです。

**ヘッドセット** 
**Soundcore Life U2 Hands-Free AG Audio**
スピーカーとマイクの両方が使用できる。web会議などで使用するのはこっちのデバイス。
おそらく、1つのアプリケーションの音しか再生できない気がする。

**ヘッドホン**
**Soundcore Life U2 Stereo**
スピーカーのみ使用できる。通常イヤホンとして使用するのはこっちのデバイス。

# 挙動
1. PC立上げ後、Bluetoothイヤホンを接続。
    この時はヘッドホンの方のデバイスが接続されている。ブラウザやメディアプレーヤーから再生した音が鳴っている。
1. web会議システムを起動。
    スピーカーとマイクの設定でヘッドセットを選択し、会議に接続。ヘッドセットの方のデバイスに接続される。
1. web会議以外の音がならなくなる。
    ブラウザやメディアプレーヤーの音はヘッドホンのデバイスから鳴っているが（図１）、今接続しているのはヘッドセットのデバイスなので、web会議以外の音が聴こえなくなる。
    おそらくヘッドセットは複数のアプリケーションの音を再生することができないっぽい。（図２）

**図１ ヘッドホンの音量ミキサー**
アプリケーションには今起動しているアプリケーションが表示されている。
![ヘッドホンの音量ミキサー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230850/4f41ca05-d4ff-5bff-2b70-e5b48edc689d.jpeg)

**図２ ヘッドセットの音量ミキサー**
アプリケーションにはTeamsしか表示されていない。
![ヘッドセットの音量ミキサー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230850/927aea17-c52e-2e22-1dfe-3cd6fa087aeb.jpeg)

# 組み合わせを調べてみる
スピーカーがヘッドセットだとweb会議以外の音が鳴らないのだとしたら、スピーカーとマイクの組み合わせを変えれば鳴るのでは？と色々試してみた。

**スピーカーの選択肢**

* スピーカー / ヘッドホン（Realtek Audio）※ノートPCの内蔵スピーカー
* ヘッドセット（Soundcore Life U2 Hands-Free AG Audio）
* ヘッドホン（Soundcore Life U2 Stereo）
![再生デバイス](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230850/23626c8b-de60-76f3-6e92-d46f97da9b73.jpeg)

**マイクの選択肢**

* マイク（Realtek Audio）※ノートPCの内蔵マイク
* ヘッドセット（Soundcore Life U2 Hands-Free AG Audio）
![オーディオ録音デバイス](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230850/74e1ad11-15b3-566a-c181-3f51549d1a86.jpeg)

## 組み合わせ結果
| スピーカー | マイク | 挙動 |
|---|---|---|
| ヘッドセット | ヘッドセット | ヘッドセットからはweb会議の音だけが鳴る。ヘッドセットのマイクから音を拾う。 |
| ヘッドセット | 内蔵マイク | ヘッドセットからはweb会議の音だけが鳴る。ノートPCの内蔵マイクから音を拾う。 |
| ヘッドホン | ヘッドセット | ヘッドホンからは何も鳴らない。ヘッドセットのマイクから音を拾う。 |
| ヘッドホン | 内蔵マイク | ヘッドホンからはweb会議の音もそれ以外の音も再生される。ノートPCの内蔵マイクから音を拾う。 |
| 内蔵スピーカー | ヘッドセット | ノートPCの内蔵スピーカーからはweb会議の音だけが鳴る。ヘッドセットのマイクから音を拾う。 |
| 内蔵スピーカー | 内蔵マイク | ノートPCの内蔵スピーカーからはweb会議の音が鳴り、ヘッドホンからはそれ以外の音が鳴る。ノートPCの内蔵のマイクから音を拾う。 |

なんだか面白い結果になりました。

* ヘッドセットのマイクを使用している時は、ヘッドホンからは音が鳴らない
* web会議以外の音も聴きたい場合は、ヘッドセットのマイクは使用できない

# まとめ
web会議に集中する場合は、
**ヘッドセット × ヘッドセット**

web会議しつつ他の音も聴きたい場合は、
**ヘッドホン × 内蔵マイク** … ヘッドホンから全ての音が鳴る
**内蔵スピーカー × 内蔵マイク** … web会議の音は内蔵スピーカーから鳴り、それ以外の音はヘッドホンから鳴る
（ヘッドセットのマイクの存在意義よ、、、）

web会議システムを使う機会が増えてきたので、使いこなせるようになりたいですね。
ProxmoxでLVM-Thinボリュームを追加する

お世話になります。

前回のエントリで、QCOW2によるファイル単位でのシンプロビジョン・スナップショット機能を行うより、LVM-Thinで運用するほうが良さそうだとわかりました。

今回、古い256GBのNVMEディスクをLVM-ThinとLVM ext4ボリュームで半分ずつ使う設定をしてみます。

ディスクを増設した直後です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/c20164f2-f9f2-d8f4-2838-271132339a7e.png)

初期化します。

```
sgdisk -N 1 /dev/nvme0n1
```

物理ボリュームとボリュームグループを作成します。proxvgという名前にします。

```
pvcreate --metadatasize 1024M -y -ff /dev/nvme0n1
vgcreate --metadatasize 1024M proxvg /dev/nvme0n1
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/fd9d0275-4e60-c224-68e8-0b1974da4fc3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/78ce48f5-32fe-5a50-2b98-0b48fcb4d00b.png)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/22a9f6f5-7b21-1d78-5b65-f5a90b91d9c2.png)

LVM-Thinプールを作成します。256GBのうち半分がLVM-Thinとなるように設定しました。

```
lvcreate -l 100%FREE --poolmetadatasize 1024M --chunksize 256 -T -n proxthin proxvg
lvcreate -n proxvz -V 120G proxvg/proxthin
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/d5b41b24-3f67-8775-e52e-0173db8506d0.png)


ext4でファイルシステムを作成します。

```
mkfs.ext4 /dev/proxvg/proxvz
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/bf5d5d46-046c-d49a-5137-13be1afe3337.png)

新しいディレクトリ作成のために論理ボリュームを作ります。

```
mkdir /media/vz
echo '/dev/proxvg/proxvz /media/vz ext4 defaults,errors=remount-ro 0 2' >> /etc/fstab
mount -a
lvs -a
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/be0a767d-6220-f982-8ec7-93a80a9d8ea9.png)

GUIのデータセンターメニューからディレクトリを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/87ba20ab-9595-0b25-9120-e8423c42142b.png)

IDはvz、ディレクトリは/media/vzにし、コンテンツ種類としてすべてを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/58927854-0753-6253-bb9b-b0fbf38cad0f.png)

同様にLVM-Thinボリュームを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/e5e604c6-fff6-fd83-f080-c89fe6ed3f75.png)

LVMとLVM-Thinが半分ずつのボリュームで作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/7d8ac7e1-0761-6768-9aa0-93cda9d3963f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/aee9388f-01b0-9993-e6ff-c7041db3f9db.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/919a05ee-21c5-3282-0ae2-2fda80329389.png)


LVM-Thinには仮想マシンのディスクまたはコンテナイメージしか置けないため、分類がわかりやすいのと、ファイル単位ではなくボリューム単位で自動的にシンプロビジョニング・スナップショットといった機能が使えるため、効率的なボリューム運用ができそうです。

LVM-Thinについては以下のサイトを参考にさせて頂きました。
https://blog.idcf.jp/entry/cloud/lvm_thin_provisioning/
arduino:超音波センサーで距離を測定する。

#arduinoで距離を測定したいと思った。

超音波センサーとarduinoUNOです。
ちなみに、続編はこちら↓です。

https://qiita.com/tsutoban/items/6c266ebab17f3b24ec42


```c:USS
//********************************************************************
//*超音波センサを使って距離を表示するプログラム
//
//*ピンアサイン
// 基板を正面（超音波がでる裏側）から見たときの左から順に
// GND Echo Trig Vcc
//********************************************************************
#define echoPin 2 // Echo Pin
#define trigPin 3 // Trigger Pin
#define dt 10 // trigger time
#define therm 24 // therm
#define LED 13 // if <10.0cm , blink LED13
#define LIMIT 10 // LIMIT distance 10cm

double Duration = 0; //受信した間隔
double Distance = 0; //距離
void setup() {
Serial.begin( 9600 );
pinMode( echoPin, INPUT );
pinMode( trigPin, OUTPUT );
pinMode( LED, OUTPUT );
}
void is10cm(double dist)
{
  if (dist < LIMIT)
    digitalWrite( LED, HIGH);
   else
    digitalWrite( LED, LOW);
}
void loop() {
  digitalWrite(trigPin, LOW); 
  delayMicroseconds(2); 
  digitalWrite( trigPin, HIGH ); //超音波を出力0
  delayMicroseconds(dt); //
  digitalWrite( trigPin, LOW );
  Duration = pulseIn( echoPin, HIGH ); //センサからの入力
  if (Duration > 0) {
    Duration = Duration/2; //往復距離を半分にする
    Distance = Duration*(331.45+therm*0.6)*100/1000000; // 音速を340m/sに設定
    Serial.print("Distance:");
    Serial.print(Distance);
    Serial.println(" cm");
    is10cm(Distance);
  }
  delay(200);
}
```

出力は次のとおりです。

```output
22:59:26.021 -> Distance:4.89 cm
22:59:26.206 -> Distance:6.17 cm
22:59:26.394 -> Distance:3.18 cm
22:59:26.626 -> Distance:5.19 cm
22:59:26.813 -> Distance:3.79 cm
22:59:27.045 -> Distance:4.12 cm
22:59:27.232 -> Distance:4.63 cm
22:59:27.421 -> Distance:3.80 cm
```

ちなみに、10cm以内になるとLED13が光るようにしてあります。
レーザーハープ作れるかも。
AIエンジニアとは


#執筆の背景
・新卒でSＥになったものの、Web制作をしたり、バックエンドに興味を持ったりと、色々なものに手を付け、何も身についていない現状をどうにかしたい。

・今後、どういったキャリアを歩むために、どんな勉強をしたらよいか、方針がわからなくなってしまった。

・この記事は、自身の思考をクリアにするためのメモです。悪しからず。

#現時点での状況
・入社後、Javaでのwebアプリケーションづくり
・Linux、SQL、AWSは少しだけ。
・早く副収入を得られるよう、Web制作の勉強を開始。HTML/CSSをProgateで何週かした。
・模写コーディングは初心者向けのものを2回ほど行ったが、副業でできるほどのスキルはない。あまり楽しさも感じなかった。
・もともとSNSのツールを作ることに憧れがあったため、pythonを使ってtwitterのツールを作ってみたことがある。これが楽しかった。


#AIエンジニアについて

###➀データサイエンティスト
・AIで集積・分析したデータを使い、新しいアイデアや提案を行う。
・営業やコンサル寄り
・AIの知識以外にも数学、統計、DB、ビッグデータなどの知識が必要
・PＭなどのスキルも。


###②機械学習エンジニア
・AIの機会学習プログラムを開発。
・案件ごとにクライアントのニーズに合ったAIプログラムを開発
・仕事の9割が前処理。
・CSVになっていないデータを結合することからやることもよくある。
・データサイエンティストの中にAIエンジニア。
・バックエンドエンジニア＋機械学習
・バックエンドエンジニアとしての実務経験は必須。最低でも1年以上。
・論文を読める力が必要。
・エンジニアの数が足りていない中で、機械学習エンジニアはさらに少なく、需要がある。


以上が、AＩエンジニアについてざっと調べた結果です。
個人的に、得意なのは➀のデータサイエンティストだけど、興味があるのは②の機械学習エンジニアだなという印象です。

いずれにせよ、ある程度の数学や統計知識は必須であり、データサイエンティストであればプラスで経営やコンサル的な知識が、機械学習エンジニアであればバックエンドエンジニアとしての経験・知識が必要であるというイメージでした。



#AIエンジニアを目指すうえでの懸念材料
##➀周りが優秀すぎる。なんだか非常に難しそう。
統計や数学などの分野において修士や博士号をとっている方が。わんさかいらっしゃる中で、文系出身で数学もぼちぼちしかやってこなかった私が、果たしてどのように生き残れるのか。

なかなか現実的に難しい部分があるように感じます。
海外でも、データサイエンティストなどはやはり別格だと聞いたこともありますし。

##②教材が少ない
Web制作は独学でもある程度の勉強ができます。バックエンドに関しては、web制作よりは少ないものの、ググれば日本語での解説が見つかることが多いです。

それに対し、AＩ関係の主な教材は、現時点では英語がメインだそうです。



#それでも機械学習エンジニアを目指したい理由

上記の懸念点もありますが、それでもやはり、機械学習エンジニアを目指してみたいと感じます。

理由としては、仮に機械学習エンジニアを諦めたとしても、バックエンドエンジニアとして働くことも可能であり、機械学習を学ぶ＝選択肢の幅をより広げる手段に過ぎないからです。

学ぶ上でのリスクはないので、とりあえず機械学習エンジニアを目指しつつ、勉強していきます。
二重否定SQLを読み解く

Qiita投稿 #29

今回は・・・
「達人に学ぶSQL徹底指南書　第２版」で解説されている二重否定クエリがぱっと見理解できなかったので、その時の備忘録です。

###テーブルと取得内容の定義

テーブルは以下の通りです。

**テーブル名：Teams**

| member | team_id | status |
| ---- | ---- | ---- |
| ジョー | 1 | 　　待機 |
| ケン | 1 | 　　出動中 |
| ミック | 1 | 　　待機 |
| カレン | 2 | 　　出動中 |
| キース | 2 | 　　休暇 |
| ジャン | 3 | 　　待機 |
| ハート | 3 | 　　待機 |
| ディック | 3 | 　　待機 |
| ベス | 4 | 　　待機 |
| アレン | 5 | 　　出動中 |
| ロバート | 5 | 　　休暇 |
| ケーガン | 5 | 　　待機　 |

***取得内容：この中からチームの全員が待機中のメンバーを取得します。***

```sql
SELECT team_id, member
  FROM Teams T1
  WHERE NOT EXISTS (SELECT *
                      FROM Teams T2
                      WHERE T1.team_id = T2.team_id
                      AND status <> '待機');
```
***クエリ実行結果：***

| team_id | member |
| ---- | ---- |
| 3 | ジャン |
| 3 | ハート |
| 3 | ディック |
| 4 | ベス |

####解説
このクエリを言語化すると・・・
***「チームの中で待機中ではないメンバーが存在しない」*** です。
日本語でもややこしい:cry:
もう少しクエリ文寄りに言語化すると・・・
***「チームが同じ且つ、ステータスが待機という条件の返り値がないチームを取得する」***ですかね。
WHERE句の中がややこしいので、こちらにフォーカスして解読していきます。

```sql
WHERE NOT EXISTS 
(SELECT *
   FROM Teams T2
   WHERE T1.team_id = T2.team_id
   AND status <> '待機');
```
1. 1人でも待機以外だとデータが取得できるのでNOT EXISTSで弾かれます。よって全員が待機だと１行も取得できずNOT EXISTSで条件と合致します。
1. `WHERE T1.team_id = T2.team_id`はテーブルを自己結合し、チームをグループ化していますので、`GROUP BY team_id`と同じ意味です。
1. `status <> '待機'`で「待機ではない」という比較をしています。
1. チーム1とチーム2、チーム5は3.の「待機ではない」に当てはまるメンバーがいるので行が取得されます。
1. チーム3とチーム4は「待機ではない」に全て当てはまらないので行が取得できません。
1. したがって取得できなかったチームがNOT EXISTSでtrueとなり上記のチームが絞り込まれ、取得されます。

複雑なクエリでも`FROM->WHERE->GROUP BY->HAVING->ORDER BY->SELECT`の順で一つずつ処理していくと混乱せず実行できそうです。
サブクエリも混同させず、1つのクエリとして分解すれば徐々にストレスなく読み解けそうです。
S3に格納したCSVファイルをQuickSightで可視化する方法2

## 概要

AWSのQuickSightでS3に格納したCSVファイルを可視化する方法をまとめていきます。
すでに調べればいろいろと出てくるかと思いますが、とりあえず自分で実施した内容をまとめてみました。
[2021年7月のJADERのデータ](https://www.pmda.go.jp/safety/info-services/drugs/adr-info/suspected-adr/0003.html)から被疑薬、相互作用の医薬品について一般名と有害事象の関係を事前に計算したファイルを使用しています。
[前回](https://qiita.com/dmikita/items/51f57d45550c1114a01b)の結果を表示する部分になります。

## QuickSight

### 初期設定
* QuickSightへのサインアップを行います。
    * 最初の2か月は無料です。
    * また２か月後も１ユーザ、SPICE 1GB分までは無料利用枠あるので、個人でちょっと試す分にはそのまま使えます。(複数ユーザで使ったり容量を多く使って普通に課金が始まるとそれなりの金額になるので注意)
* サービス一覧からQuickSightを選択します。
    * QuickSightを開くとAWSのコンソールには戻れなくなるので別のウィンドウやタブで開くことをお勧めします。
* リージョンを使用したいリージョンに合わせます。
* エディションの設定画面が開くので好きな方を選びます。
    * 無料枠の範囲で行う場合はエンタープライズエディションがおすすめです。
* 引き続き設定を進めていきます。
    * リージョンは使用するリージョンに合わせます。
        * 無料枠がここに指定したリージョンにつくので間違えないように・・・
    * QuickSightアカウント名は任意の名前(ほかと被らないもの)を使用します。
    * メールアドレスは自分のメールアドレスを設定
    * AmazonAthenaへのアクセスを有効にするチェックボックスは外します。
        * こちらはのちの手順で設定するのでいったん外しておきます。
* メイン画面に戻ったら右上のアイコンをクリックしQuickSightの管理を選択します。(赤く塗りつぶしている部分をクリック)
![quicksight1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657697/81183058-c593-3b78-e74f-056810fba277.png)

* セキュリティとアクセス管理をクリックします。
* QuickSightのAWSのサービスへのアクセスのところにある「追加または削除する」をクリックします。
![quicksight3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657697/0af84b1a-5093-200c-92fc-8947df0d9c8c.png)

* Athenaにチェックを入れます。
![quicksight4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657697/edc13c16-43ca-adeb-bdb2-3e22ba3d0403.png)

    * `Amazon Athena permissions` という画面が出るので、「次へ」を押します。
    * QuickSightからAthenaの結果保存に使用しているS3バケットへのアクセスを許可します。
![quicksight5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657697/80b11d3c-0f53-5f0f-c757-3e1fbf1897cc.png)

### データセットの設定
* メイン画面に戻ったらデータセットをクリックします。
* 新しいデータセットをクリックします。
* データソース名は任意の名前に Athenaワークグループは前回Athenaで作成したワークグループ名を指定します。
![quicksight9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657697/80b1e495-79d7-90d9-e1cf-7934194f06b1.png)

* `接続を検証`をクリックして接続できることを確認したら `データソースを作成` をクリックします。
* テーブルの選択で以下のようにAthenaで設定したカタログ、データベース、テーブルを選択します。
    * さらにここで別途SQLを発行することも可能です。(今回は実施していません)
![quicksight6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657697/1237eb48-2979-0c47-dc5c-9e53f3f8c597.png)


### QuickSightの表示
* 取り込みが終わるとこの画面になるので視覚化を選択し使いたいグラフや表を選びます。
![quicksight10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657697/f6d8c3c4-772b-2bae-b5ce-58f438629436.png)
* 上部のフィールドウェルをクリックすればX軸になにを設定するか、Y軸に何を設定するかなどを設定することができます。(ビジュアルタイプによって変わります)
![quicksight11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657697/b36f75e5-05a7-cdd5-80e0-79f52736fdc8.png)

* QuickSightで取り込むと以下のように可視化することができます。
    * 今回は棒グラフですが表や円グラフなど用途に応じていろいろ選択できます。
    * ↓は薬品名にコロナが入っているものをフィルタリングしています。

![quicksight7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657697/89201240-be2f-d7be-d3ae-9ff58767ce70.png)

* こうやって可視化したグラフなどをページに埋め込むこともできるので、社内のポータルサイトで部ごとの売上をリアルタイムで見たり、稼働時間の偏りがないか？などを見ることも可能です。