OmniAICreator/Qiita-1.07M huggingface dataset:
Shopify App CLI（Node.js）を使用したアプリ開発で、ngrokを使わずにshopify serveを動かす

この記事は [Shopify開発を盛り上げる（Liquid, React, Node.js, Graph QL） Advent Calendar 2020](https://qiita.com/advent-calendar/2020/shopify-liquid) の18日目の記事です。

# 記事の内容

Shopify App CLI（Node.js）を使用したアプリ開発では、shopify serveを動かすとローカル（ http://localhost:8081 ）でWebサーバーが動き、自動的にngrokという外部サービスが使われてインターネットから http://localhost:8081 にトンネリングされます。
環境により、ngrokを動かせないケースがあることを知りましたので、本記事ではngrokを使わずに同等の処理を行います。
ngrokでお困りの方の解決策になればいいな。

# 手順

環境構築はこの記事と同様となります（本記事との違いは後ほど）。

[ローカルに立てたWebサーバーを、VPSのSSHサーバーを経由して外部公開する（リバースSSHポートフォワーディング）](https://qiita.com/kanedaq/items/4c3d37d278e674df6e14)

## 上の記事と本記事の違い(1)：ポート番号

上の記事では、外部からhttpsアクセスすると、ポートは以下のように変遷します。

443（VPSのhttps）
→ 13001（VPSのhttp）
→ 3001（ローカルのhttp）

Shopify App CLIでは、ローカルWebサーバーのポートは8081ですので、3001を8081に置き換える必要があります。

## 上の記事と本記事の違い(2)：ローカルWebサーバー

上の記事では、動作確認用に「python3 -m http.server 3001」を起動してローカルWebサーバーを立てていますが、本記事では不要です。
代わりにshopify serveを起動することになります。

## shopify serveの動かし方

オプションを付けずにshopify serveを起動すると、ngrokが使用されます。

--hostオプションを使えば、ngrokを使わずに、起動させるWebサーバーのURLを指定することができます。
この時、プロトコルはhttpsである必要があります。httpでは動きません。

上の記事と同様の環境構築をし、VPSのドメインも記事と同じ「 example.com 」だと仮定しますと、以下のようにオプションをつけて動かせば、リバースSSHポートフォワーディングによりローカルWebサーバー（ http://localhost:8081 ）にトンネリングされます。

```

shopify serve --host=https://example.com
```

動作確認したところ、以下のように ngrok を使わずにアプリを動かすことができました。

![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327312/e7212a77-7148-9cf5-b0f7-d2008ddc14ca.png)

以上です。
新規プロジェクトでのScriptableObject活用事例

本記事は、[サムザップ #1 AdventCalendar 2020](https://qiita.com/advent-calendar/2020/sumzap1)の12/17の記事です。

#はじめに
株式会社サムザップでUnityエンジニアをしている佐藤です。
主に新規開発をしています！
↑
とここまでは去年のアドベントカレンダーと同じ出だしでスタートしました。
実は私、去年から今までずっと同じプロジェクトで新規開発をしていました。リリースはまだもうちょい先なので、大々的にこれやった！みたいなことは言い出しづらいんですが、実績もないし、ただまあ去年から引き続きゲーム開発と環境の整備をしています。

というわけで今回は今のプロジェクトでやっているScriptableObject活用実例を紹介してみようと思います。
去年よりは、もうちょっと具体的なことが書けるな、やったね！

#ScriptableObjectとは
詳細は割愛しますが、

> ScriptableObject は、クラスインスタンスとは無関係に、大量のデータを保存するために使用できるデータコンテナです。

という[公式リファレンス](https://docs.unity3d.com/ja/2018.4/Manual/class-ScriptableObject.html)の文言がすべてを言い表していると感じます。

* メモリ内にデータのコピーが一回ですみ、すべてのプレハブから参照を使ってアクセスできる。
* エディター上では編集中、実行中にデータの保存をすることができる。
* ビルドされたアプリのセーブデータ保存には向かない。

この辺りが特徴といえるかもしれません。

[Unity Pro Tips](https://forpro.unity3d.jp/unity_pro_tips/)でもScriptableObject活用方法を紹介しています。

[ゲーム構築を劇的にスマートにするScriptable Objectの3つの活用方法例](https://forpro.unity3d.jp/unity_pro_tips/2019/07/27/57/)

というわけでここから先は私がScriptableObjectをどのように活用しているのかの実例になります。

#デバッグデータでの利用
実際の開発で配信されるマスターデータとの結合までにタイムラグがあることはよくあります。
なので先にアプリ側で使用するデータ構造を定義し、ScriptableObject側にデータを設定して利用しています。

こういう場合、jsonファイルを読み込むという方法もあると思います。
私は以下の理由によりScriptableObjectにしました。

* Unity Editor上で編集、即時反映をさせたい
* データ編集作業もなるべくUnity Editor上で完結させたい

「即時反映」はScriptableObjectを利用する上で、特にアドバンテージのある部分だと思います。

#ゲームで利用する設定データとしての利用
私のプロジェクトではなるべくエンジニア以外の人たちにもUnityを触ってもらっています。

背景やキャラクター、エフェクト、技の演出...
これらはクリエイターさん手動でゲームへの組み込みを行ってもらっています。

そういった時に、例えばですが

* カメラに対する背景の位置
* エフェクトの発生場所

というデータをどこに設定するかという問題が出てきます。

プランナーさんは割とスプレッドシートからのマスターデータで解決したいという要望があるのですが、
クリエイターさんにとっては馴染みの薄いものだと思います。

なのでクリエイターさんがメインで設定するものは、ScriptableObjectを利用することにしました。

* 背景の設定データ
* キャラクターの設定データ
* エフェクトの設定データ

このようなデータはクリエイターさんがUnityに組み込む際に、
一緒にデータを設定してもらうことで、クリエイターさんのみで作業が完結するようにしています。

#Editor拡張を用いた設定データの編集
とはいえ、ScriptableObjectってそのままだと、あまり見やすくありません。
特にデータが大量になったときの編集効率や一覧性は、そのままだと段々辛くなってきます。

クリエイターさんのみで作業が完結することを目指すと設定項目は多岐にわたってきます。
一例としてエフェクトを挙げます。
種別、タイプ、用途、描画位置、発動位置、発生位置、発生サイズ・・・・。
エフェクトは種類も多いです。
これらを踏まえてエフェクトはEditor拡張を用いた編集をしてもらっています。
![スクリーンショット 2020-12-11 10.31.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210467/fe9d4a99-8d9a-e55d-73c3-b6a188e57604.png)

まずエフェクトごとに用途を定めて、設定項目を決めました。
実際のゲームではこの設定項目に合わせて処理を行うようにしました。
エディター拡張によるデータ設定を行うことで、以下のようなメリットもありました。

* 設定項目を日本語で表示することができる
* エンジニアだけがいじりたい設定を隠蔽できる(Editor拡張に表示させない)。
* データが大量になった時に備えて、ソート機能や絞り込み機能も準備できる。

というわけで煩雑で、大量のデータを扱う際はEditor拡張を用いた方が効率がよくなると思います。

#デバッグ機能としての利用
先ほどScriptableObjectは即時反映できるのがアドバンテージと言いました。
それは特にデバッグ機能として利用することで、非常に使いやすくなると思います。

ゲーム内容に関わるので、具体的に言いづらいですが
例えば各キャラクターにそれぞれデバッグ用のScriptableObjectを参照させます。
すると、ScriptableObjectの値を変更することで、各キャラクターの状態を即時変更することが可能です。

Editorであれば、インスペクターからデータをそのまま変更すればよいですし、
実機であっても、ScriptableObjectをコントロールするデバッグコントローラーを1つ用意するだけで、
あら不思議。複雑な依存関係をすっ飛ばしてキャラクターを制御できたりします。
今のプロジェクトではこの仕組みを意識することで、かなり細かい制御をワンタッチで行っています。


#おわりに
ScriptableObjectを使用することで、開発の効率化を行うことができました。
最初に今のプロジェクトに関わることになった時に、

* スクリプトで解決する部分を少なくする
* 色々な職種の人にUnityを触ってもらう

ということを意識して設計を行いました。
その設計を実現するにあたり、ScriptableObjectは非常に有用でした。

明日は@mmm_hiroさんの記事です。
@extendの使い方

＠extendの使い方


```
.hoge1 {
margin:10px 0;
padding:5px;
}
.hoge2{
@extend .hoge1;
padding:0;
}
```
とすることによって、hoge2はhoge1の

```
margin:10px 0;
padding:5px;
```
が適応されつつ、そのあとに

```

padding:0;
```
が適応されるということになる。

まさに継承、、


mixinと似ているが、mixinは
・グルーピングをしない
・引数を使うことができる
という違いがある
sassでこう記述すると

```sass

@mixin hoge($value : 5px) {
margin:20px 0;
padding:$value;
}
.hoge1{
@include hoge;
}
.hoge2{
@include hoge(0);
}
```

これがcssでは

```css

.hoge1 {
margin: 20px 0;
padding: 5px;
}
.hoge2 {
margin: 20px 0;
padding: 0;
}
```

こうなる。

引数を指定してあげればスタイル描くの楽そうですね。
【メモ】Docker使用時に使うコマンド（コンテナ停止、削除、イメージ削除）

* 製造業出身のデータサイエンティストがお送りする記事
* 今回は自分のメモとして記事に残しておきます。

##はじめに
自分でDockerを使用する際にコンテナの停止や削除、イメージの削除を行うコマンドを備忘録として残しておきます。

###起動中のコンテナ確認
下記のコマンドを使って起動中のコンテナIDを取得します。

```
$ docker ps -q
```

下記のようにコンテナIDを取得できます。

```
d75e0580aa81
d886772499bd
```

###起動中のコンテナ停止
下記のコマンドを使って起動中のコンテナを停止します。今回はコンテナID`d886772499bd`を停止しようと思います。

```
$ docker stop d886772499bd
```

###コンテナの削除
下記のコマンドを使ってコンテナを削除します。今回はコンテナID`d886772499bd`を停止しようと思います。

```
$ docker rm d886772499bd
```

###コンテナの一括削除
下記のコマンドを使うとコンテナが多い場合も全てのコンテナを一気に削除することができます。

```
$ docker ps -aq | xargs docker rm
```

注意点としては、上記コマンドは起動中のコンテナがあると失敗しますので、必ず起動中のコンテナは停止させてから実施してください。

###イメージ確認
下記のコマンドを使ってイメージIDを取得します。

```
$ docker images -q
```

下記のようにイメージIDを取得できます。

```
30557a29d5ab
746b819f315e
```

###イメージの削除
下記のコマンドを使ってイメージを削除します。今回はイメージID`746b819f315e`を停止しようと思います。

```
$ docker rmi 746b819f315e
```

###イメージの一括削除
下記のコマンドを使うとイメージを一気に削除することができます。

```
$ docker images -aq | xargs docker rmi
```
秘密鍵をCircleCIに登録できない原因はパスフレーズだった

# やりたいこと
CircleCIに秘密鍵を登録したい。
CircleCIで`$ git push`したら自動デプロイも走るようにしたく、そのためにSSH鍵を登録する必要があった。

# 結局どうやって解決したのか？
秘密鍵のパスフレーズ（暗号化するための記述）があるのが原因だった。
秘密鍵のパスフレーズをなしに変更したら解決した。

[CircleCIの公式ドキュメント](https://circleci.com/docs/ja/2.0/add-ssh-key/)を読んで、

- パスフレーズありの秘密鍵はCircleCIに登録できない。
- パスフレーズなしの秘密鍵はCircleCIに登録できる。

ということがわかったので、パスフレーズなしの秘密鍵を作成した。

# 秘密鍵のパスフレーズとは？何のためにあるの？
秘密鍵を暗号化するもの。らしい。
しかし、なぜ暗号化する必要があるんだ？何のために暗号化するんだ？

teratailに全く同じ質問をした人がいて、回答が載っていた。
https://teratail.com/questions/76995

パスフレーズを設定していると、自分のパソコン（ローカル）がウイルスに感染したときに被害を防止できる場合があるという。
あなたのパソコンがウィルスに感染したときに秘密鍵にパスフレーズを設定していると被害を防止できる場合があります。

この投稿を見て知ったのだが、秘密鍵を知られてしまうと、パソコンのデータ全部とられたり、GitHub上のデータが全部ウイルスに感染してしまう可能性があるらしい。

そんな恐ろしいことになるんですね。
少しでもそのリスクを下げられるなら、やっておいた方がいいということですね。

# パスフレーズなんていつ作ったっけ？

```
$ cd .ssh
$ ssh-keygen

Generating public/private rsa key pair.
Enter file in which to save the key (/Users/xxxx/.ssh/id_rsa): (リターン)

Enter passphrase (empty for no passphrase): (パスフレーズを入力してリターン)
Enter same passphrase again: (パスフレーズを入力してリターン)
↑　↑　↑　↑　↑　↑　↑　↑
　　　　ここで生成してたわ！
　　　　何も押さずENTERで自動生成してたわ！

Your identification has been saved in /Users/xxxx/.ssh/id_rsa.
Your public key has been saved in /Users/xxxx/.ssh/id_rsa.pub.
The key fingerprint is:
93:b3:41:fe:3a:cb:ba:f3:6b:99:fe:6f:d4:21:dd:fb xxxx@local
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|        .    . . |
|       o .  . o .|
|        S    o ..|
|         *  . .. |
|        .o..    .|
|      ..=.  .   E|
|      oBB=.o.    |
+-----------------+
```

# パスフレーズを解除するやり方

調べてみたら、「なくす」というより「解除する」という方が正しいようだ。
「openssl」＝「sslのパスフレーズを解除させる」という感じか？

```
openssl rsa -in パスあり秘密鍵 -out パスなし秘密鍵

例えば自分の場合だと
openssl rsa -in  pfcmaster7118_key_rsa -out pfcmaster7118_second_key_rsa
```
pfcmaster7118_key_rsaだとCircleCIに登録できなかったけど、pfcmaster7118_second_key_rsaは登録できた。

ここが秘密鍵の文字列だけだったら、パスフレーズがなしになっているということです。

```:pfcmaster7118_second_key_rsa
-----BEGIN RSA PRIVATE KEY-----
（秘密鍵の文字列）
-----END RSA PRIVATE KEY-----
```
ちょっとわかりにくいかもしれませんが、パスフレーズがありの場合は、秘密鍵の文字列の上に、2行記述があります。それがパスフレーズです。

```:pfcmaster7118_second_key_rsa
-----BEGIN RSA PRIVATE KEY-----
（パスフレーズがある場合は、ここに2行書いてあります）

（秘密鍵の文字列）
-----END RSA PRIVATE KEY-----
```

# 参考記事
[SSLの秘密鍵ってどんなデータですか？またパスフレーズを解除するにはどうすればいいのでしょうか？](https://teratail.com/questions/36677)
【GitHub】ブランチ作成からマージ、プッシュまでの流れ

#目的
基本的には、チーム開発する上で、マスターブランチで作業することは推奨されない。必ず、トピックブランチを作成し、そこで開発を行い、完了後マスターにマージ（合流）する。

#作業前

```
$ git status
```
`On branch master`と表示されれば、現在マスターが選択されている。




```
$ git checkout -b ブランチ名
```
この操作で、ブランチの新規作成と、ブランチの切り替えが同時に行われる。


```
$ git status
```
`On branch ブランチ名`と変化していれば、切り替わっている。


#作業後

```
$ git add -A
$ git commit -m 
```
変更箇所をインデックスして、コミットします。

```
$ git checkout master
```
マスターブランチに切り替えます。

```
$ git merge ブランチ名
```
編集したブランチをマスターにマージ（合流）させます。

```
$ git push 
```

プッシュして完了です。
Ubuntu20.4でelectron-react-boilerplateを使うための準備

Ubuntu 20.4にまるっきり1からelectron-react-boilerplate(ERB)の環境構築をしたので、せっかくなのでメモしておきます  

# やることリスト  

* Node.jsのインストール
* curlのインストール
* yarnのインストール
* gitのインストール
* ERBのクローン
* 動くか確認  

# Node.jsのインストール  
### ローカルパッケージインデックスの更新  
`sudo apt update`  
### Node.jsのインストール  
`sudo apt install nodejs`  
### インストールできたか確認する  
`nodejs -v`  
### ついでにnpmもインストールしておく  
`sudo apt install npm`  

Node.jsのインストールは以上。  
  
<参考>
[Ubuntu 20.04にNode.jsをインストールする方法](https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-20-04-ja)

# curlのインストール  
yarnのインストールに必要なので、curlのインストールをする。
以下コマンドでインストール。  
`sudo apt install curl`  

curlのインストール終わり。  

# yarnのインストール  
### Debianパッケージリポジトリの設定  
`curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -`
`echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list`  
### yarnのインストール  
`sudo apt-get update && sudo apt-get install yarn`  

yarnのインストール終わり。  

<参考>
[インストール | Yarn](https://classic.yarnpkg.com/ja/docs/install/#debian-stable)

# gitのインストール  
### 以下コマンドでインストール  
`sudo apt-get install git`  
### インストールされたか確認する  
`dpkg -l git`  

# ERBのクローン  
### 以下コマンドでインストール  
`git clone --depth 1 --single-branch https://github.com/electron-react-boilerplate/electron-react-boilerplate.git your-project-name`  
your-project-nameに自分の好きな名前を入れる。  
### ディレクトリを変更してyarnする  
`cd your-project-name`  
`yarn`  

<参考>  
[GitHub - electron-react-boilerplate/electron-react-boilerplate: A Foundation for Scalable Cross-Platform Apps](https://github.com/electron-react-boilerplate/electron-react-boilerplate)


# 動くか確認する  
### 以下コマンドで実行  
`yarn start`  

画像のように表示されればOK。  
(12/11にERBがv2.0.0になり、以前までのCounterページがなくなりました。詳しくは別で書こうと思います。)

![Screenshot from 2020-12-12 17-11-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/948895/08f3b745-6bf7-846f-8d22-763c3aa52dbf.png)

([自分の](https://ishikidakehataikei.hatenablog.com/)転載です。)
CDKでAWS 環境の作成 SNS編

## 概要

CDKを使ってAWS環境を作成するときの方法についてまとめていこうと思います。
今回は[前回](https://qiita.com/dmikita/items/f13771b816c6aa019f1e)作成したCDKの定義にSNSの定義を追加してみました。


## 準備

* 準備部分は[前回](https://qiita.com/dmikita/items/f13771b816c6aa019f1e)等を参照してください。

* `メールアドレス`を変更する場合はパラメータストアから値を取得しなおすため`cdk.context.json`を一度削除してください。

## コンパイルの準備
* ライブラリインストール後にプロジェクトを作成したディレクトリに移動して以下のコマンドを実行します。windowsの場合はライブラリのインストール時には停止する必要があるので注意を
    * `npm run watch`


## 各モジュールの説明

* モジュールは[github](https://github.com/dmikita-sss/cdk-sample)で公開しています。今回追加した部分のみ追記します。
* /rds-s3
    * SNSの設定を追加しています。
    * `./bin/rds-s3.ts` の方で以下のように設定することで複数のソースの定義を使えるようにしています。今回追加部分のみ抜粋しています。

        ```typescript
            import { CdkSnsStack } from '../lib/cdk-sns-stack';

            new CdkSnsStack(app,'CdkSnsStack',{
                env: {
                    region: 'ap-northeast-1',
                    account: env.AWS_ACCOUNT,
            }});

        ```
    * デプロイするときはStack名を指定して実施します。ワイルドカードの指定も可能です。
        * `cdk deploy * ` または `cdk deploy CdkSnsStack` の用に指定します。

### CDKの定義

* SNS
    * サブスクリプション用のメールアドレスをパラメータストアから取得するようにしています。
    * 必要に応じて外部のファイルからメールアドレスを複数取得する方法にするといいかもしれません。
    * サブスクリプションは他にも選択できるので必要に応じて変えてみるのもよさそうです。

        ```typescript

            const topic = new sns.Topic(this, 'Topic', {
                displayName: 'Customer subscription topic',
                topicName:'cdk-sns-topic'
            });  

            const subscriptionMail=ssm.StringParameter.valueFromLookup(this,'/sns/subscriptionMail');

            topic.addSubscription(new subscriptions.EmailSubscription(subscriptionMail));
            }

        ```
    * デプロイ後に登録したメールアドレスに確認用のメールが届くのでサブスクリプションを有効にするのを忘れずに。
    * 以下のようなメールが来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657697/2d91322c-8ee0-4004-9118-c28f7d8d11ae.png)

    * 有効にすると以下のような画面が出ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657697/1c0fa9fd-7303-1b9f-9742-296215665436.png)


## SNSの送信
### 作成したSNSの使用コード例です
* pythonで実装しています。
* プログラム内で例えば処理件数などを通知したいときに手軽に実装できます。


```python

import boto3
TOPIC_ARN = u'arn:aws:sns:ap-northeast-1:238836858026:cdk-sns-topic'
msg = 'テストメッセージ'
subject = u'テストタイトル'
client = boto3.client('sns')
request = {
'TopicArn': TOPIC_ARN,
'Message': msg,
'Subject': subject
}
response = client.publish(**request)

response['ResponseMetadata']['HTTPStatusCode']

```

* メールは以下のような形で届きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657697/24d8d014-0531-7610-7be0-26e0b1002f8d.png)
KVM バックアップとリスト

Linux KVM仮想マシンのバックアップとリストア手順
作業ユーザーは、KVMの管理コマンド**virsh**の実行権限を持っている事を前提として説明します。

今回は以下の環境として説明します。

実行環境は**Ubuntu20.04TLS**になります。

|項目|値|
|---|---|
|VMイメージファイル格納先|/var/lib/libvirt|
|VMイメージファイル名|mail.img|
|VM設定ファイル格納先|/etc/libvirt/qemu|
|VM設定ファイル名|mail.xml|


## バックアップ

KVM仮想マシンのバックアップを行います。
作業としては、VMのイメージファイルをコピーと、VMの設定ファイルをDUMP出力してそれをファイルに保存します。

### 1. バックアップ対象の確認

- バックアップ対象のVMの状態を確認
    VMが停止してることを確認する。サーバーを稼働させたままでは、バックアップ出来ない（というよりしてはダメ）なのでKVMの管理コマンドで確認する。
    > 下記のコマンドで出力されるのは、現在稼働中のサーバーのみになります。

    ```bash
    virsh list
    ```

    出力結果の見本

    ```bash
    Id   Name       State
    --------------------------
    1    filesrv    running
    2    mail       running
    3    labo6      running
    ```

### 2. バックアップを取得

事前確認が終了したらバックアップを取得していきます。
今回は、上記の確認結果のid3の**mail**仮想マシンのバックアップを取得します。

- バックアップ格納ディレクトリを作成
    バックアップデータを格納しておくディレクトリを作成しておきます。

    ```bash
    mkdir -pv ~/kvm-backup
    ```

- KVM設定ファイルバックアップ
    KVMの管理コマンド**virsh**を使ってVMの設定ファイルのバックアップを取得します。

    ```bash
    virsh dumpxml mail > ~/kvm-backup/mail.xml
    ```

- VM本体のデータのバックアップを取得します。
    こちらは、専用コマンドはなく純粋に対象のVMのイメージファイルのコピーを取得します。
    KVMの仮想マシンのイメージファイルのデフォルト格納先は、**/var/lib/libvirt**になります。

    ```bash
    cp -ivp /var/lib/libvirt/mail.img ~/kvm-backup/mail.img
    ```

以上でKVM仮想マシンのバックアップが完了となります。
このままバックアップデータとして保管しておくことも、別のKVMホストサーバーへ送り
そちらでこのデータをリストアして、別のKVMホストサーバーのVMとして稼働させることも可能です。

---

## リストア

バックアップを取得しておいた仮想マシンのリストア作業を説明します。
> その際ホストのOSとハードウェア（私の経験的にCPUが多い）の相違によりVM設定ファイルの一部を修正する必要があります。
> 今回は、割愛します。

### 1. リストア環境の確認

- リストア環境のVMの状態を確認
    リストアを行うKVMホストサーバー上にリストアするVMと同じ名前の仮想マシンがないことを確認します。

    ```bash
    virsh list --all
    ```

    出力結果の見本

    ```bash
    Id   Name       State
    --------------------------
    1    filesrv    running
    2    ad1        running
    -    web        running
    -    labo6      running
    ```

### 2. リストアデータの配置

リストア環境に同じ名前のVMがないことを確認したらバックアップしておいたデータを各々配置していきます。
配置先は、バックアップを取得した環境と同一のディレクトリに格納してください。
> 別の場所に格納する場合は、バックアップしておいたVMの設定ファイルのイメージファイルの格納先設定を書き換えなくてはなりません。

- VM設定ファイルの配置
    バックアップ時とは、異なり設定ファイルも純粋にファイルをディレクトリへコピー（または、移動）するだけになります。

    ```bash
    cp -p ~/kvm-backup/mail.xml /etc/libvirt/qemu/mail.xml
    ```

- 仮想マシンイメージファイルの配置
    こちらも同様にバックアップしておいたイメージファイルを所定のディレクトリへコピー（または、移動）するだけです。

    ```bash
    cp -p ~/backup/kvm-backup/mail.img /var/lib/libvirt/images/mail.img
    ```

### 3. VMのリストア

設定ファイルとVMイメージファイルの配置が完了したら**virsh**コマンドを使ってKVMホストサーバーに設定を適用します。

- リストア

    ```bash
    virsh define /etc/libvirt/qemu/mail.xml
    ```

    仮想マシン一覧を確認してリストアできているかを確認する。

    ```bash
    virsh list --all
    ```

    出力結果の見本

    ```bash
    Id   Name       State
    --------------------------
    1    filesrv    running
    2    ad1        running
    -    web        running
    -    labo6      running
    -    mail       running
    ```


VM一覧に新しく**mail**という仮想マシンが出てきました。
リストア自体は、以上で完了となります。
仮想マシンを実際に起動してみてエラーが出る場合は、設定ファイルを見直してください。

以上、ありがとうございました。

- 参考サイト  
 [MSeeeeN](https://mseeeen.msen.jp/backup-and-restore-virtual-image-for-kvm/)
【SQL】基本コマンド一覧

# 概要
- フレームワークが裏で何をやっているのか理解するために最低限必要なコマンド群をリストにしました。


DML
- SELECT
- INSERT・UPDATE・DELETE
DDL
- CREATE
- ALTER
- DROP
トランザクション制御文
- COMMIT
- ROLLBACK

# Data manipulation language(DML)
##SELECT
- データの検索
- 重複の削除
- 条件指定

```sql
SELECT something FROM table_name
SELECT DISTINCT column_name FROM table_name
SELECT something FROM table_name WHERE condition
-- conditionの例
something IS value AND value --value両方にヒットするものを抽出
something IS value OR value --いずれかのvalueにヒットするものを抽出
something IS BETWEEN value OR value --value間にヒットするものを抽出
something IS IN (value, value, ...)  --いずれかのvalueを含むものを抽出
something IS LIKE "somethign%"  --文字列を含むものを抽出
something IS NULL --空ものを抽出
something IS NOT NULL --空でないものを抽出
ORDER BY something  --昇順でソート
ORDER BY something  DESC --降順でソート
```

##INSERT
- データの挿入
- データの変更
- データの削除

```sql
INSERT INTO table_name VALUES(value, value, ...) --最後尾に値を挿入
INSERT INTO table_name (column, column, ...) VALUES(value, value, ...) --カラムを指定して最後尾に値を挿入
UPDATE table_name SET Column = value WHERE condition --条件に一致するものを更新
DELETE FROM table WHERE condition --条件に一致した行を削除
```

# Data definition language(DDL)
- テーブル作成
- テーブル変更
- テーブル削除

```sql
CREATE TABLE table_name (column type, ...);
ALTER TABLE table_name change action;
-- change actionの例
ADD (column_type) --列を追加
MODIFY column_type --データ型やバリデーションを変更
DROP COLUMN column --列の削除
ADD validation --バリデーションを追加
DROP validation --バリデーションを削除
```

#その他
## fk_keyの有効・無効化
```sql
SET FOREIGN_KEY_CHECKS = 0; --無効化
SET FOREIGN_KEY_CHECKS = 1; --有効化
```


# トランザクション制御文
- DMLを実行した結果
- ターミナルでよく見るかも？

```sql
COMMIT; --確定
ROLLBACK; --取り消し（何らかのエラーが出た場合に表示される）
SAVEPOINT savepoint_name; --現在のトランザクション内に新しいセーブポイントを確立
ROLLBACK TO SAVEPOINT savepoint_name; --savepoint_nameの確立後に実行されたコマンドの結果を取消
```
【CSS】transitionプロパティについて【まとめ】

transitionプロパティについて学習したことをまとめました。

#transitionとは

ある要素の状態が変化する時、その変化が終わるまでの時間や緩急を指定できる。

#とりあえず四角を用意する

```html:index.html
  <div class="box"></div>
```
```css:style.css
.box {
  height: 100px;
  width: 100px;
  background-color: red;
}
```

![スクリーンショット 2020-12-13 17.26.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635852/9fa28cbe-c1a6-7e5e-0eaa-04e70118764f.png)
***

`:hover`した時に色を青色に変化させる

```css:style.css
.box {
  height: 100px;
  width: 100px;
  background-color: red;
}

.box:hover {
  background: blue;
}
```

![demo](https://gyazo.com/336c6a9e793f58c136b85faff3258c0c/raw)

***
現状では変化に間が無くて目がチカチカしてしまう

ここで`transition`の出番です

```css:style.css
.box {
  height: 100px;
  width: 100px;
  background-color: red;

  transition: background-color 3s;

}

.box:hover {
  background-color: blue;
}
```

![demo](https://gyazo.com/28783f85664adfe3da728527c4981912/raw)
第2引数に指定した`3秒`かけて徐々に変化している
***

伸ばしたり丸めたりもできます
`transition: width 3s;`
`transition: border-radius 3s;`
と毎回指定するのが面倒なときは`transition: all 3s;`でOK

```css:style.css
.box {
  height: 100px;
  width: 100px;
  background-color: red;
  transition: all 3s;
}

.box:hover {
  background-color: blue;
  width: 500px;
  border-radius: 50%;
}
```

![demo](https://gyazo.com/bcf1d807b32dec77b882cf87f7bf9b09/raw)


#緩急をつける


`transition`の第3引数に`ease`を取ることで緩急をつけられる

デベロッパーツールで色々イジれるのが楽しそうでした。

```css:style.css
.box {
  height: 100px;
  width: 100px;
  background-color: red;

  transition: all 3s ease;

}

.box:hover {
  background-color: blue;
  width: 500px;
  border-radius: 50%;
}
```

![demo](https://gyazo.com/8f203c63f46d3d8e64bffe73bcfc4e4a/raw)

![demo](https://gyazo.com/1775b8aa1869e468ecbf5f2cd3bdce69/raw)


#遅延時間の設定

第4引数に変化までの遅延時間を設定できる

```css:style.css
.box {
  height: 100px;
  width: 100px;
  background-color: red;

  transition: all 3s ease 2s;

}

.box:hover {
  background-color: blue;
  width: 500px;
  border-radius: 50%;
}
```

![demo](https://gyazo.com/e4efff0fcf0c32561cace7f13470ef3b/raw)

`2秒`待ったあとに変化が始まる
Big Sur で R が Terminal から起動できない & 解決策

# R が Terminal から起動できない
## 環境と文脈
+ macOS Big Sur
+ R 4.0.3 (CRAN から.pkgをダウンロードしてインストール)

Big Sur にアップデートするのを機に、OSのクリーンインストールを行ないました。
R などの環境を1から構築する上で、問題が発生しました。
## 問題
本来であれば、Rを公式のパッケージからインストールすれば Terminal上から R と入力するだけで、
Terminal内で R が利用できるはずです。
しかし、Rと入力しても

```zsh
% R
zsh: command not found: R
```

という結果に。
R.app 自体の起動や、Rstudio からの R の利用には問題がありません。

## 表面的な原因
本来であれば、パッケージからインストールした場合、/usr/bin 内にRやRscript が設置される[^cran] [^2]ので、Terminal からそれを呼び出せるはずなんですが。。。
ためにしに、/usr/local/bin/R や　/usr/bin/Rを入力しても呼び出せません。
(Homebrew でRをインストールしている場合は/usr/local/bin[^3])

直接的な原因は、設置されるべき場所 (/usr/bin) に R が設置されていないことのようです。

## 解決
/usr/bin/R は、/Library/Frameworks/R.framework/内にある該当ファイルのエイリアスです。
ここから適切なリンクを引っ張ってきて設置すればよさそう。
今回は手作業でリンクを貼るので、/usr/binではなく、/usr/local/bin 内に設置をします。
R だけでなくついでに Rscript も作業しましょう。

```zsh
% ln -s /Library/Frameworks/R.framework/Versions/Current/Resources/bin/R /usr/local/bin
% ln -s /Library/Frameworks/R.framework/Versions/Current/Resources/bin/Rscript /usr/local/bin
```

Terminal を再起動すれば無事に R を起動することができました[^ess]。

```zsh
% R

R version 4.0.3 (2020-10-10) -- "Bunny-Wunnies Freak Out"
...
```

# 気がかり
今後のアップデートで競合などが起きないかが気になります。

何故Rのエイリアスが貼られていなかったのかという根本的な原因についても不明なままなのもモヤモヤするところです(先に Homebrew を導入したせいでしょうか)。


[^cran]: [Uninstalling under macOS](https://cran.r-project.org/doc/manuals/r-release/R-admin.html#Uninstalling-under-macOS)
[^2]: [Rstudio Support: Changing R versions for RStudio desktop](https://support.rstudio.com/hc/en-us/articles/200486138-Changing-R-versions-for-RStudio-desktop)

[^3]: そもそも homebrew を使えばこの問題を解決できる気もしますが、R は公式パッケージで管理をしたいので、今回は homebrew は使わない方針です。

[^ess]: これでようやくESSに篭れます。
cssを使って投稿した画像をアイコン風にする方法

＜この記事について＞

投稿した画像をTwitterやInstagramのアイコン風にする方法を備忘録として投稿!

[環境]
・Ruby 2.6.5,
・Rails 6.0.0
・macOS

style.cssファイルで、以下の記述を追加するだけで簡単に実装できます。
※幅と高さを同一数字にすることで縦横比を維持

```
.クラス名 {
  width: ○px;
  height: ○px;
  border-radius: 50%;
}
```
さらに、アイコンに枠線を付けて縁取りしたい場合は以下を追加します。

```
border: △px solid カラーコード（#00ffff等）;
```

他にもアイコン風にする方法は色々ありますが、初心者が手っ取り早く実装するには
この方法がオススメです！
Vue3 + TypeScriptで、作成したコンポーネントを表示するまで

# はじめに

これは個人的なメモです。
Vue3 + TypeScriptのプロジェクトを作ったときのメモは[こちら](https://qiita.com/aikouchino/items/f0651487ffc7f3598027)。

# 環境

```
$ vue -V
@vue/cli 4.5.9
$ my-project aiko$ node -v
v14.13.1
$ my-project aiko$ npm -v
6.14.8
```

# やりたいこと

`Header.vue`というコンポーネントを、`App.vue`でimportして使いたい。

# やったこと

## Headerコンポーネントをつくる

```vue
<template>
  <h1>Header</h1>
</template>

<script lang="ts">
import { Options, Vue } from "vue-class-component";

@Options({
  props: {
    msg: String,
  },
})
export default class Header extends Vue {
  msg!: string;
}
</script>

<style scoped></style>>
```

とりあえずの表示ができれば良いので適当に。

## App.vueにHeaderコンポーネントをimportする

```vue
<script lang="ts">
import { Options, Vue } from "vue-class-component";
import Header from "@/components/Header.vue";

@Options({
  components: {
    Header,
  },
})
export default class App extends Vue {}
</script>
```

scriptタグの中を書く。


## Headerコンポーネントを使う

```vue
<template>
  <div id="header">
    <Header />
  </div>
  <div id="nav">
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link>
  </div>
  <router-view />
</template>
```

これはjavascriptのときと同じだ。

# おわり

できた。(Headerと表示された)

![スクリーンショット 2020-12-13 20.08.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951040/5140dcea-97e1-e42f-9b12-d171b160ca7d.png)
Pythonの仮想環境(venv)の作り方

Pythonを学習しはじめていざアプリを作成をしてみようと思い色々調べていたら、仮想環境を作ることが一般的なようなのでその操作方法をまとめておく。


## なぜ仮想環境が必要か
そもそもなぜ仮想環境が必要かといえば、ライブラリやPythonをアプリごとに適切なバージョンを使用できるようにするためだ。

Pythonの学習をはじめたばかりで文法などの基礎を学習している間は特に必要ではなかったが、これからどんどんアプリを作成していこうとなった段階では仮想環境を使うようにした方がよさそうだ。

## 仮想環境の基礎知識

* Conda
* virtualenv
* venv

データサイエンス向けのAnacondaを使用するためのCondaが有名で、venvのベースになっているvirtualenvなど他にもたくさんあるようだが、ここではPython標準の**venv**について解説していく。

## 仮想環境の作り方
venvはPython標準なので任意のディレクトリで以下のコマンドを実行するだけ。入力した仮想環境名でフォルダが作成される。

```python -m venv [仮想環境名]```

pythonコマンドに**-m**オプションをつけることでモジュールを指定することができる。モジュールを指定する場合はモジュール名のみを指定し拡張子(.py)は不要。

## 仮想環境を実行
仮想環境を作成したら、作成したフォルダへ移動して以下のコマンドを実行する。

Windowsの場合
```Scripts\activate```

Macの場合
```source bin/activate```

Windowsで**PSSecurityException**が発生する場合は以下のコマンドを実行。
```Set-ExecutionPolicy RemoteSigned -Scope Process```

## 仮想環境を終了
activateで実行した仮想環境を終了しないとプロセスが残ってしまうことがあるようなので注意。作業が終わったらdeactivateコマンドで仮想環境を無効化して終了する。
```deactivate```

## 仮想環境を初期化
何らかの理由で初期状態に戻したくなった場合は、仮想環境を作成した親ディレクトリへ移動して以下のコマンドを実行。
```python -m venv --clear [仮想環境名]```

## 仮想環境を削除
deactivateで無効化した状態にしてから、作成したフォルダを削除。
```rm -rf [仮想環境名]```
【Swift】Table Viewをつくる際のテンプレ（のようなもの）

# これはなに

Table Viewを作るときにほぼ毎回書いてるコードをテンプレのようにまとめた。

## オブジェクトの配置

1. ストーリーボードで `Table View` を配置
2. 配置した `Table View` の上に `Table View Cell` を配置

## ViewControllerの編集

1. `Table View` をControlキー押しながらViewControllerにドラッグドロップ
2. プロトコル（DataSourceとDelegate）を追記して使えるようにする

```swift:ViewController.swift
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

  // Table Viewをドラッグドロップしてきた部分
  @IBOutlet weak var tableView: UITableView!
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    tableView.delegate = self
    tableView.dataSource = self
  }
```

プロトコルの追加をしたところで

`Type 'ViewController' does not conform to protocol 'UITableViewDataSource'`

 というエラーが出る。
「必要なメソッドがない」といったところで、 `fix` を押すと『セルの数』と『セルの構築』に関するメソッドが自動で作られる。

### セルの数と構築

- セルの数。数値で返す
- ストーリーボードでTable View Cellを選択して `Identifier` に任意の名前を書く。ここでは "Cell" と書いた
- セル再利用のためのメソッド `dequeueReusableCell` を追記

```swift:ViewController.swift
  // セルの数
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1
  }
  
  // セルの構築
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    
    // その他やりたいこと

    return cell
  }
```

### セルの高さ

`heightForRowAt` というデリゲートメソッドを使う。
これは上記のように `fix` を押しても自動追加されないので自分で書く。

```swift:ViewController.swift
  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 200
  }
```

---

まだ足りないものがあったら教えてください。
UnityのVFX Graphでパーティクルを格子上に整列させる

UnityのVFX Graphで`particleId`というattributeにパーティクルのIDが0から順に振られるので、それを基に格子上になるように位置を計算すればパーティクルを格子上に整列させることができます。

2次元の場合はこんな感じです 最初に必要な数だけパーティクルを生成して、`Initialize`コンテキスト内の最初の`Set Position`ブロックで`particleId`を基にXYの位置を決定しています。その後で、色を調整してパーティクル全体が真ん中になるように移動させています。
![VfxGrid2d.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/f3371d9e-8ad1-ee8c-aa64-4dca2211e594.png)
![VfxGrid2d_Render.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/60a797cd-80a5-3e77-aa32-f0cb92d2d6c1.png)

3次元格子の場合は以下のようになります。最初の位置の計算が少し複雑に見えますが、やっていることは2次元の場合とほとんど同じです。
![VfxGrid3d.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/db33a84a-c068-3943-5bdc-d800ea7cdc2f.png)
![VfxGrid3d_Render.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/6d6136d1-4ff2-5605-dc9a-3e36a4d51e7e.png)

---

今回の検証に使用したバージョンです。

- Unity: 2020.1.4f1
- Visual Effect Graph: 8.2.0
【FileMaker】バックアップのつもりでテーブル丸ごとコピーしたら主キーが変わっちゃった

FileMakerのバックアップネタです。

# FileMaker バージョン
今回のお話は、バージョン17で追加された、デフォルトフィールドの追加に関することになります。
それ以下のバージョンをお使いの場合は、この記事はバージョンアップした際の注意点としてお読みください。

# 話の概要
FileMakerが自動で作る主キーを、まさにレコードの主キーとしてリレーションシップを張っていますか？
それ自体は別に問題ない（あるという人もいるとかいないとか、、、）のですが、、、

テーブルデータをバックアップする場合、自分が追加したフィールドはルックアップしたりスクリプトでループしながらデータの移行をしていると、思わぬ落とし穴があるよ、というお話です。

# 自動で追加される主キーって？
↓この部分です。
![スクリーンショット 2020-12-13 19.02.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/72a05ec3-f45b-50f4-3670-cdf35e7d77b5.png)
これらのフィールドは、新規レコードを作成した際に、自動で値が設定されます。[^1]
ありがたいっちゃありがたいのですが。

# どういう時に間違いが起こるか
↓こういう時に起きがちです。
![スクリーンショット 2020-12-13 19.21.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/7972dfaf-baf3-2cad-25af-faceb1670ced.png)
業務データとしてはこの枠の２つしかないから、２つだけループで回してコピーすればいいよね、として独自にスクリプトを組んでしまうと、デフォルトフィールドがバックアップ先のテーブルで違う値が設定されてしまい、そもそものバックアップとしてデータが違うことになってしまします。

# どうすればいいのか？
## FileMaker Serverでバックアップ計画を作って実行する
一番妥当で間違いがないです。

## 素直にファイル自体をバックアップする
これが一番簡単ですが、ディスクの容量的に無理がある現場もあるでしょう。

## デフォルトフィールドも含めてコピーする
特定のテーブルのバックアップをしたいケースが考えられます。
例えば、トランザクション系のテーブルだけバックアップしておきたい、などです。
あと、FileMaker Serverを使っていなくて、バックアップ計画が立てられない場合もあるでしょう。

### やり方
(1)バックアップ元（画像ではコピー元）とバックアップ先（画像ではコピー先）の主キーをリレーションして、その他の値はスクリプトでルックアップでコピーさせます。
![スクリーンショット 2020-12-13 19.20.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/c425d252-bd19-2016-5fd3-61b2e9985f8a.png)
(2)バックアップ先は、リレーションシップを張った主キー以外をルックアップします。
![スクリーンショット 2020-12-13 19.28.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/6ace7b20-4672-46e3-f129-4cb526e0ff28.png)
(3)スクリプトでグルグル回します。
![スクリーンショット 2020-12-13 19.38.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/f20f1715-e23d-b799-e489-3930b9c1bb95.png)

FileMaker ProやFileMaker Go単体で使っている場合は、バックアップスケジュールとして毎日ファイルを閉じるor開いたタイミングで実行するようにスクリプトを組むのも一つの方法です。
バックアップはリレーションシップが崩れないように気を配りましょうね。

[^1]: もし、これらのデフォルトフィールドを自動で追加されたくない、使用しない、という場合は、[ヘルプ](https://help.claris.com/ja/pro-help/content/database-tables.html)にあるように、作成されないようにすることもできますので、参考までにリンクを貼っておきます。
[無料] AWS EC2 + RDS + Flask でWebアプリを作り HTTPS 化する [その4: IPアドレスの固定]

[その3](https://qiita.com/nozomiyamada/items/0be5844568eeceeca51d) からの続きです。Webアプリとして使うための設定をしていきます。

## IPアドレスの固定

EC2インスタンスのIPアドレスは、一度シャットダウンすると変わることがあります (再起動だけでは変わらないかも)。まあシャットダウンしなければいいのですが、万一IPアドレスが変わってアプリにアクセスできないなんてことがあったら困るので、念のために固定しておきます。

EC2 のメイン画面から **Elastic IPs** を選択します。
 ![Screen Shot 2563-12-13 at 17.23.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727634/a1a7bf31-5d0f-5f64-b0ce-4c9287f954f3.png)
何もない画面が出てきます。**Allocate Elastic IP address** をクリックします。
![Screen Shot 2563-12-13 at 17.24.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727634/a7895a56-3a50-4fdf-20c2-e91e1e0470bb.png)
そのまま **Allocate** します。
![Screen Shot 2563-12-13 at 17.25.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727634/04afaf7b-0fc3-738a-10b2-aa724bcfc8bd.png)
固定IPアドレスが作成できました。ついでに名前を `ElasticIP for testapp` とでもつけておきます
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3732373633342f38653066386432632d623034662d373839362d306137642d3964333161633132313330332e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727634/f8127b7c-f983-625b-7940-0f542eeb0296.png)
**Actions** から、**Associate Elastic IP address** を選択します。
![Screen Shot 2563-12-13 at 17.33.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727634/79635512-aeb8-3864-4fad-774083bde761.png)
真ん中の **Insrance** から、インスタンスを選択し、**Allocate** します。
![Screen Shot 2563-12-13 at 17.29.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727634/acc018bf-0599-575d-9df8-3cce98ef1e68.png)

これでインスタンスの作成と設定は終わりです。[その5](https://qiita.com/nozomiyamada/items/8d75ff32dad5b0976738) では具体的なFlaskアプリの作成を行います。
【SIGANTE】画像ラベリング（１０種類）①データの下準備

# 全体の構成

###①データの下準備
https://qiita.com/hara_tatsu/items/a90173d33cb381648f72
###②画像データの拡張（水増し）
https://qiita.com/hara_tatsu/items/86ddf3c00a374e9ae796
###③転移学習
https://qiita.com/hara_tatsu/items/bc93fb61b7ccbc639eed


# 環境情報

Python 3.6.5
tensorflow 2.3.1

# 【SIGANTE】画像ラベリング（１０種類）について

画像データに対して、10種類のラベルの1つを割り当てるモデルを作成します。

学習データサンプル数：5000

以下リンク
https://signate.jp/competitions/133

# データの下準備

# ライブラリーの準備

```python.py
import numpy as np
import pandas as pd
# 画像処理
from PIL import Image
# 画像を読み込む用
import glob

# データの分割
from sklearn.model_selection import train_test_split
# カテゴリー変数へ変換
from tensorflow.keras.utils import to_categorical
```

## ラベルデータの読み込み

```python.py
# データの読み込み
train_Y = pd.read_csv('train_master.tsv', delimiter='\t')
# ラベル名の削除
train_Y = train_Y.drop('file_name', axis=1)
# カテゴリー変数へ変換
Y = to_categorical(train_Y)
print(Y.shape)
```

```
データ数:5000, 種類:10
(5000, 10)
```



## 画像データの読み込み

```python.py
# train_imagesディレクトリ内のデータをリストに格納
train_file = glob.glob('train_images/t*')
len(train_file)
```

```
データ数：5000
5000
```



ここで一つ問題が発生。
globを使ってtrain_imagesディレクトリ内のデータを取得したのですが、順番がバラバラになっているため、番号順に並べ替える必要があります。。。

```python.py
# 番号順に並び替える関数
import re
from collections import OrderedDict

def sortedStringList(array=[]):
    sortDict=OrderedDict()
    for splitList in array:
        sortDict.update({splitList:[int(x) for x in re.split("(\d+)",splitList)if bool(re.match("\d*",x).group())]})
    return [sortObjKey for sortObjKey,sortObjValue in sorted(sortDict.items(), key=lambda x:x[1])]

sort_file = sortedStringList(train_file)
sort_file[:5]
```

```
並び替え後のリスト内
['train_images/train_0.jpg',
 'train_images/train_1.jpg',
 'train_images/train_2.jpg',
 'train_images/train_3.jpg',
 'train_images/train_4.jpg',]
```

## 画像の前処理

```python.py
X = []
for image in sort_file:
    # 画像ファイルの読み込み
    image = load_img(image) 
    # 画像ファイルのnumpy化 + 正規化
    image = img_to_array(image) /255.0
    # リストへ格納
    X.append(image)

# リストデータをnumpy化
X_np = np.array(X)
print(X_np.shape)
print(X_np.dtype)
```

```
データ数:5000, 96*96のカラー画像
(5000, 96, 96, 3)
float32
```

## データの分割

```
# データの分割
X_train, X_test, Y_train, Y_test = train_test_split(X_np, Y, test_size=0.3, random_state=0)
X_train, X_valid, Y_train, Y_valid = train_test_split(X_train, Y_train, test_size=0.3, random_state=0)

# 形状を確認
print("Y_train=", Y_train.shape, ", X_train=", X_train.shape)
print("Y_valid=", Y_valid.shape, ", X_valid=", X_valid.shape)
print("Y_test=", Y_test.shape, ", X_test=", X_test.shape)
```

```
Y_train= (2450, 10) , X_train= (2450, 96, 96, 3)
Y_valid= (1050, 10) , X_valid= (1050, 96, 96, 3)
Y_test= (1500, 10) , X_test= (1500, 96, 96, 3)
```


# おわり

### 次回は、データの水増し！！
Figmaのプラグイン開発事始め

#はじめに
この記事はユニークビジョン株式会社 [Advent Calendar 2020](https://qiita.com/advent-calendar/2020/uniquevision) 14日目の記事です。
弊社ではここ一年くらい、画面のレイアウトの設計にはFigmaが利用されるケースが増えてきました。
画面数が増えてくるとFigmaの規模も大きくなり人力で何かをするのがだんだんつらくなてきます。
Figmaは無料プランでもプラグインの開発ができますので、実際どんな感じか手を動かしてみました。

## One-shotのプラグインを作る
### 環境のセットアップ
公式の[セットアップガイド](https://www.figma.com/plugin-docs/setup/)がとても分かりやすいのでこれに沿って以下のものを用意します。

- Figma デスクトップ版アプリとアカウント
- VS code
- Typescript


### プラグインを作成する
上記のセットアップガイドでは`With UI`のプラグインを作成していますが、今回は1度だけ実行するタイプの`Run once`を選択して、`save as`に進みます。
完了ダイアログにある`Open Folder`というリンクをクリックすると作成されたリソースのフォルダがファイルブラウザで開きます。

### ビルドする
すこし寄り道して`Open Folder`で開いたディレクトリのファイルをいくつか見てみます。

```bash

MyOneShotPlagin/
　├ code.js
　├ code.ts
　├ manifest.json
　├ package.json
　├ tsconfig.json
　└ README.md
```

```manifest.json
{
  "name": "MyOneShotPlagin",
  "id": "{ plugin id }",
  "api": "1.0.0",
  "main": "code.js"
}
```
`manifest.json`を見るとプラグインを呼び出したときに実行されるコードの相対パスが`main`で指定されています。初期状態では`code.js`が以下のようになっていますのでプラグインを実行してもエラーメッセージが表示されるだけです。

```javascript:code.js
throw new Error("This plugin template uses Typescript. Follow the instructions in `README.md` to generate `code.js`.")
```

引き続きセットアップガイドの[Install the typings](https://www.figma.com/plugin-docs/setup/#install-the-typings)から先を進めます。

`tsc: watch - tsconfig.json`まで実行すると、`code.js`に変更があったときに`tsconfig.json` に記載した内容に則って `code.ts` から `code.js`にトランスパイルされるようになります。
ためしに`code.js`を確認すると、`code.ts`から生成されたコードで初期のコードが上書きされていますね。

### プラグインを実行する
適当なDraftsを作成するか、既存のDraftを開きます。レイアウト画面を右クリック > `Pulgins` > `Development` と進むと作成したプラグインが実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/220881/599d87df-1cb4-81b3-02c6-8822f99d8f56.png)

Rectangleが5つできました。

### メニューを追加する
[ドキュメント](https://www.figma.com/plugin-docs/manifest/)を参考に、`manifest.json`に`menu`を追記します。menuのアイテムは以下のいずれかを指定できますので、サブメニューを作ってみます。

```typescript

type ManifestMenuItem =
  // Clickable menu item.
  { name: string, command: string } |
  // Separator
  { separator: true } |
  // Submenu
  { name: string, menu: ManifestMenuItem[] }
```

```diff:manifest.json
{
  ...略
- "main": "code.js"
+ "main": "code.js",
+ "menu": [
+   {"name": "Create Shape",
+    "menu": [
+      {"name": "Create Circle", "command": "circle"},
+      {"name": "Create Rectangle", "command": "rectangle"}
+    ]
+   }
+ ]
}
```
`command`で定義した文字列は、プラグインが実行された際にプラグインのコードから`figma.command`で参照できます。この値を参照して処理を分岐するように`code.ts`を書き換えてみます。

```typescript:code.ts
// ...
const nodes: SceneNode[] = [];
for (let i = 0; i < numberOfRectangles; i++) {
  // const rect = figma.createRectangle();
  const node = figma.command === 'rectangle' ? figma.createRectangle() : figma.createEllipse()

// ...
}
```

コードをコンパイルしたらもう一度Draftのメニューから実行してみます。
`Pulgins` > `Development` と掘っていくと先ほど追加した`Create Circle`、`Create Rectangle`が追加されています。それぞれ実行すると異なる図形が描画されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/220881/270a1e06-a3f1-d0cf-48dc-8ac40aaaa644.png)

## おわりに
入力がいらないプラグインであれば結構簡単に作れそうです。
今回は選択しなかった　`With UI`なプラグインについても[公式のサンプル](https://github.com/figma/plugin-samples)がいくつかあります。プラグインのUI構築にvueを使用するサンプルもあるので、次はこれを使って実際に何か機能を持ったプラグインを作成してみたいと思います。
DeFi 金利計算のメモ


## DeFi における金利

Compound, AAVE などの lending pool を想定します.
金利は, 主に基本は供給(貸し手)と需要(借り手)の pool 残高の割合できまります.

利用率が低い(貸し手が多いが, 借り手が少ない)と, 金利は低いです.
利用率が高いと金利は高くなります.

Compound, AAVE では, 金利のカーブを kined(共起?) model(２つの線形の金利モデルで, 利用率が高くなると金利上昇が高くなる)にすることで, 
利用率が高い場合は借り手は金利が高くなるので返そうとするインセンティブが働き, 貸し手は金利が高いのでより供給を行おうというインセンティブが働くことで, 最適な利用率(optimal utilization. たとえば USDC だと 90% くらい)に収れんするのを期待しています.

また, 各ユーザー単位では, 借入率(利用率)が高くなりすぎると担保割れになり清算(liquidation)が発生します. 担保割れになるとペナルティ(借り手が貸し手に借入の 5% 支払いなど)が発生するので, 利用率が高い状態では借り手はより早めに返済したくなります.
このルールも利用することで, プール全体としては最適な利用率に収斂するのを狙っているようです.

### risk-free rate

ステーブルコインの場合は, そのペッグしている通貨の risk-free rate(国債で運用などからのほぼリスクゼロで得られる金利)も考慮しています.

https://docs.aave.com/risk/liquidity-risk/atoken-valuation

### その他詳細

Towards Understanding Flash Loan and Its Applications in DeFi Ecosystem
https://arxiv.org/abs/2010.12252

に金利モデルの解説があります.

### 実装

実装としては, 金利は debt token(負債トークン)を発行(mint)することで実現しているようです.

## Compound

1 block(ethereum だと平均 15 秒)で供給の割合を計算して金利を計算します.

https://compound.finance/docs#protocol-math


```
Rate = cToken.supplyRatePerBlock(); // Integer
Rate = 37893566
ETH Mantissa = 1 * 10 ^ 18 (ETH has 18 decimal places)
Blocks Per Day = 4 * 60 * 24 (based on 4 blocks occurring every minute)
Days Per Year = 365

APY = ((((Rate / ETH Mantissa * Blocks Per Day + 1) ^ Days Per Year - 1)) - 1) * 100
```


金利などの履歴は API で取得できます.

https://compound.finance/docs/api#MarketHistoryService

## AAVE

AAVE も, 基本は Compound と同じようにブロック単位で金利を計算します(variable rate)

AAVE では, この変動金利(variable rate)に加えて, stable 金利(stable rate)があります.

stable 金利はスキャンしている platform(compound とか他の lending pool?)の金利から重み平均で求めています.

stable 金利は借入期間中ずっと固定ではなく, 状況によって変更になります. 

stable 金利が変更になる条件

https://docs.aave.com/risk/liquidity-risk/borrow-interest-rate#stable-interest-rate-model-parameters


Utilization が 95% を超え, かつ時系列での重み付き APY が 25%(レートは config で設定) 以下の場合
(利用率は高いが, stable rate での借り手がおらず貸し手が十分な金利を得ていない場合)

詳細はコードをみるのがよいでしょう.
オブジェクトを返すとわかっている関数がOptionalと定義されていて扱いにくい場合の回避法

Optionalを返す関数に対して、Pyright(Pylance)、mypyではNone出ないことが評価されないと、返されたオブジェクトのプロパティにアクセスしてもエラーとなってしまいます。
これに対して、`assert val is not None`でチェックすればOKというのがシンプルに良さそうと思いました。

```python
# Optional[Way] を返す関数
way1 = repo.get_way(100)

# way1 が None である可能性があるため、mypy、pyrightでエラーになる
print(f"way: {way1.way_id}")


# None で分岐を作るのが正攻法
way2 = repo.get_way(100)
if way2 is not None:
    print(f"way: {way1.way_id}")


# typing.cast や # type: ignore を使うと回避できるが
# 代入したもとの値がWay型であるかの評価がされなくなってしまう 
way3: Way = repo.get_way(100)  # type: ignore
print(f"way: {way3.way_id}")
way4 = typing.cast(Way, repo.get_way(100)) 
print(f"way: {way4.way_id}")


# assert 使えば分岐なしにNoneでないことが評価でき、Pyrightでもエラーにならない
way5 = repo.get_way(100)
assert way5 is not None
print(f"way: {way5.way_id}")
```
AWS GlueでRAC構成のOracle DBに接続する

Glueでは以下のようなロードバランスをONにした接続設定を作成できません。

```
jdbc:oracle:thin:@(DESCRIPTION = (LOAD_BALANCE=ON)(FAILOVER=ON)(ADDRESS = (PROTOCOL = TCP)(HOST = xxx.xxx.xxx.xxx)(PORT = 1521))(ADDRESS = (PROTOCOL = TCP)(HOST = xxx.xxx.xxx.yyy)(PORT = 1521))(CONNECT_DATA = (SERVICE_NAME = my_ora_service)))
```

公式のドキュメントにあるOracleDBに接続するJDBC URLの書式は以下の通りです。
https://docs.aws.amazon.com/ja_jp/glue/latest/dg/connection-defining.html

>employee サービス名を使用して Amazon RDS for Oracle データストアに接続する。
>jdbc:oracle:thin://@xxx-cluster.cluster-xxx.us-east-1.rds.amazonaws.com:1521/employee

>Amazon RDS for Oracle の構文は次のパターンに従います。これらのパターンでは、host, port, service_name, および SID 独自の情報を使用することもできます。
>・jdbc:oracle:thin://@host:port/service_name
>・jdbc:oracle:thin://@host:port:SID

そのためジョブ内でspark dataframeを用いてJDBC接続し、データ取得を行う必要があります。

```python:sample.py
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.dynamicframe import DynamicFrame

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)

url = "jdbc:oracle:thin:@(DESCRIPTION = (LOAD_BALANCE=ON)(FAILOVER=ON)(ADDRESS = (PROTOCOL = TCP)(HOST = xxx.xxx.xxx.xxx)(PORT = 1521))(ADDRESS = (PROTOCOL = TCP)(HOST = xxx.xxx.xxx.yyy)(PORT = 1521))(CONNECT_DATA = (SERVICE_NAME = my_ora_service)))"

dataframe = spark \
  .read \
  .format("jdbc") \
  .option("driver", "oracle.jdbc.driver.OracleDriver") \
  .option("url", url) \
  .option("user", "xxx") \
  .option("password", "xxx") \
  .option("dbtable", "DUAL") \
  .load()
```
Vue CLIでVue3のプロジェクトを作るメモ

# はじめに

これは個人的なメモです。

# 環境

```bash
$ vue -V
@vue/cli 4.5.9
$ node -v
v14.13.1
$ npm -v
6.14.8
```

# メモ

## プロジェクト作成

```bash
vue create my-project
```

`my-project`は、プロジェクト名



## プリセットの選択

```bash
? Please pick a preset:
  Default ([Vue 2] babel, eslint)
  Default (Vue 3 Preview) ([Vue 3] babel, eslint)
❯ Manually select features
```

TypeScriptを使いたいので、`Manually select features`を選択。

## 使いたいパッケージを選択

```bash
? Check the features needed for your project:
❯◉ Choose Vue version
 ◉ Babel
 ◉ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◉ Router
 ◉ Vuex
 ◯ CSS Pre-processors
 ◉ Linter / Formatter
 ◉ Unit Testing
 ◯ E2E Testing
```

カーソルで移動して、スペースで選択する。エンターで次の質問へ。
デフォルトで選択されているのは、以下の3つ。
- `Choose Vue version`
- `Babel`
- `Linter / Formatter`

使うかわからないけど、`Vuex`と`Router`も入れておく。
TDDを実践したいので、`Unit Testing`も入れておく。（フレームワークは後で選べる）

## Vueのバージョンを選択する

```bash
? Choose a version of Vue.js that you want to start the project with (Use arrow
keys)
  2.x
❯ 3.x (Preview)
```

## class-style component

```bash
? Use class-style component syntax? (y/N)
```

~~yes~~ -> no

（2020/12/14 追記）
vue-class-componentはvue3のRFCから外され、Composition APIがRFCになっているらしい。
だからデフォルトは`N`だったのか...
https://qiita.com/ryo2132/items/4d43209ea89ad1297426

## Babel

```bash
Use Babel alongside TypeScript (required for modern mode, auto-detected polyfi
lls, transpiling JSX)? (Y/n)
```

yes

## History modeを使うかどうか

```bash
? Use history mode for router? (Requires proper server setup for index fallback
in production) (Y/n)
```

yes

## LinterとFormatterを選ぶ

```bash
? Pick a linter / formatter config:
  ESLint with error prevention only
  ESLint + Airbnb config
  ESLint + Standard config
❯ ESLint + Prettier
  TSLint (deprecated)
```

この前`ESLint + Pretter`を勉強したので選択。

## Linterをいつ動かすか

```bash
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i
> to invert selection)
❯◉ Lint on save
 ◯ Lint and fix on commit
```

保存したとき

## UTのフレームワーク

```bash
? Pick a unit testing solution:
  Mocha + Chai
❯ Jest
```

どっちでも良かったが、勉強中のJestで。

## BabelとESLintの設定ファイルをどこに置くか（どこに書くか）

```bash
? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
❯ In dedicated config files
  In package.json
```

独立させたい

## 今までの設定を保存するか

```bash
? Save this as a preset for future projects? (y/N)
```

やり直したくなるかもしれないのでNO

## おわり

実行してみる。

```bash
npm run serve
```

`localhost:8080`にアクセス。

![スクリーンショット 2020-12-13 19.14.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951040/f128ab08-f7ef-84ca-3917-ca1c9c300c72.png)
VS Codeのsetting.jsonで"yaml.customTags"がうまく適用されない時の対処

**ほぼ自分用のメモ**

# 対象の読者
VS Codeでyamlファイルを編集する人
CloudFormationとかAnsibleとかのyamlファイルを取り扱う人
VS Codeのsetting.jsonの"yaml.customTags"がうまく適用されてなくて悩んでいる人

# 何が起きたか

VS CodeでCloudformationのyamlファイルをセコセコと記述していたら

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435280/2640ea6d-b110-1215-a866-b7b70778fab1.png)

!Refなんてタグがないよと言われている。

ググったら
[setting.jsonのyaml.customTagsを追加してあげれば回避できるとのこと](https://qiita.com/yoskeoka/items/6528571a45cd69f93deb)

上記リンクの手順通りやっていてもエラーが解消されず。。。

# 原因

VS Codeの拡張機能でAnsible Extensionを有効にしている場合に発生するっぽい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435280/d6854b5a-ced3-82c3-8fa4-86c9bc09a13d.png)

この拡張機能を無効にしたら解決できました。
【ミライトデザイン社内勉強会#9】フロントの環境構築（webpackとBabel）の基本を知りたい


## webpack
### [webpackとBabelの基本を理解する\(1\) ―webpack編― \- Qiita](https://qiita.com/koedamon/items/3e64612d22f3473f36a4)
- 機能
    - ファイルを1つにまとめる
- メリット
    - モジュール化
        - jsファイルは他のファイルを参照できないが、開発する時はモジュールに分割して開発したい
    - ブラウザによってES6のimportやexportが搭載されていないものがあるが、webpackを使用することで共通でデプロイができる

- [Webpackの入門書](https://zenn.dev/yuri/books/4391b9280f823061932c)


## Babel
### [webpackとBabelの基本を理解する(2) ―Babel編― - Qiita](https://qiita.com/koedamon/items/92c986456e4b9e845acd)

- jsの構文を変換してくれるコンパイラ。
    - es2018→es2015に変換したり
    - react や ts で書いたものをjsのソースに直してくれたり
    - constをvarに変更したりとか
- 構文を変更することによって古いブラウザにも対応できる
    - あんまり古いブラウザに対応しすぎると、変換後のコード量が増えて重くなったりするかも
- 変換後の構文はおそらくes2015だけど、設定によって変換できる

- Presets
    - https://qiita.com/koedamon/items/92c986456e4b9e845acd#presets
    - 変換のルール集みたいなもの
    - これを設定していないと変換してくれない
        - TSを使用するなら（@babel/preset-typescript）が必要。みたいな。
- 設定ファイルは`.babelrc`以外に`package.json`に書くことも可能
    - どっちにもある場合はどっちが優先されるんだろう？
        - おそらく`.babelrc`
    - あんまり`package.json`まとめるメリットはないかも？

- 設定方法はいろいろあるけど、基本は構文を変換してくれるってだけ。

### [webpackとBabelの基本を理解する\(3\) ―webpackとBabel編― \- Qiita](https://qiita.com/koedamon/items/6cf2201be78c3d79516d)

- webpackのLoader
    - webpackでjs以外のアセットをバンドルする場合はLoaderを使用する
        - cssや画像ファイルをimportできるようになる
- babel-loader
    - webpackとbabelでは噛み合わないため、その間にloaderを挟んでいる

### [webpackとBabelの基本を理解する(4) ―React編― - Qiita](https://qiita.com/koedamon/items/8fb75a7c001da40c7bea)

- Reactはコンポーネント分割をするため、WebpackやBabelが必須となっている
- ESモジュールって何？
    - [ECMAScriptモジュール · JavaScript Primer #jsprimer](https://jsprimer.net/basic/module/#es-module-syntax)
    - import exportでモジュール化するための仕組み
- create-react-app
    - 自前でwebpackとBabelの設定をすることってある？
        - まれにカスタマイズすることはある
        
### [webpackとBabelの基本を理解する\(5\) ―Sass編― \- Qiita](https://qiita.com/koedamon/items/a5be9456e0591db4d1f4)

- Sass（Syntactically Awesome StyleSheet）
    - CSSをいい感じに描けるようにしたもの
    - CSSにコンパイルする必要がある
    - SASSとSCSSという2つの記法がある
        - SASS: インデントを使う
        - SCSS: `{ }`を使う
- WebpackでSassやCSSをバンドルできる
Google Classroomの導入はとても良かった話

## はじめに
今年の4月、コロナ事情により岩手県立大学ではGoogle Meet, Google Classroomの導入を行い、オンライン授業を開始しました。目標として**「講義でのやりとりのすべてをGoogle Classroomで完結できるようにする」**ことを掲げ、PCさえ持っていれば資料を閲覧でき、講義を受けられ、課題を提出できます。以前は一部の講義で講義資料などが学内のネットワークからしか受け取れないということがあったので、それを避けて誰も大学に来る必要が無い環境を整えました。

それから1か月後、コロナも多少落ち着いたため対面授業を再開しました。そのため、Google Meetはお役御免です。しかし、**Google Classroomだけは依然として残っています。**「依然として残っている」という表現をすると悪い感じに聞こえますが、学生目線(=私)からするととても有難い！

というわけで、なぜ有難いかを述べていきます.


## Google Classroomの良さ
### 講義資料の閲覧が楽
今までは先生ごとに講義資料の受け取り方が違いました。ある先生の講義では事務管理公開システム(学生が履修登録をしたりシラバスの確認をしたりする)から受け取ったり、別の先生の講義では先生が管理しているサーバから受け取ったりという感じです。この中で**先生が管理してるサーバからの資料受け取りがとても面倒**でした。たとえば、サーバへのアクセスにはURLが必要です。そのURLはたいていの場合初回の講義で伝えられます。伝えられたURLをPCに入力して資料を受け取るという行為を今までは行っていました。中には**学内ネットワークからしかアクセスできないサーバもありました。**しかし、Google Classroomではクラスに参加するだけで手軽に講義資料を閲覧できます。統一したUIかつ一つのWebページから資料を受け取れるため、「この講義で開くべきサーバのURLってなんだっけ？」や「このサイトってどこに資料が置いてあるんだ？」という苦悩を抱かずに済みます。とてもストレスが減りました。また、これによりスマホから講義資料の閲覧も楽になった気がします。

### 課題の提出が楽
Google Classroomでは課題の提出もできます。しかもこれが**Google Docsなどとの相性が良い**のでいちいちファイルをダウンロードして提出する必要がなくなり、また提出した課題の確認も簡単になりました。レポートをメールボックスに提出することや、メールで提出する機会も減ったような気がします。自分が持ってるPCだけで課題の作成から提出まで完結できるのはとても良いです。

## 最後に
先生目線からGoogle Classroomの導入の評価は分かりませんが、すべての講義で使うツールが統一されたというのは学生目線からするととても有難いと感じています。もしも我儘が通るのならば**コロナが収束してもGoogle Classroomは使い続けたいなと考えています。**