OmniAICreator/Qiita-1.07M huggingface dataset:
AWS EC2にSplunkを立ててみた。

https://aws.amazon.com/marketplace/pp/B00PUXWXNE

AWSにはちゃんとあるんだけど、Free枠でできるかどうかよくわからなかったので、立ててみた。

#EC2の準備

```console:aws起動.sh
aws ec2 run-instances --block-device-mappings '{"DeviceName": "/dev/xvda", "Ebs": {"VolumeSize": 30}}' --image-id ami-0be2609ba883822ec --count 1 --instance-type t2.micro \
--key-name XXX --subnet-id  subnet-XXXXX  --security-group-ids sg-XXXXXXXXXX \
--user-data file://open.txt --output text
```

立ち上げ用スクリプト。ポイントはディスク容量をfree枠いっぱいの３０GBにしているところ。
セキュリティグループでは２２と8000番のポートを開けている。

```text:open.txt
yum update -y
yum install man-pages-ja -y

localectl set-locale LANG=ja_JP.UTF-8
timedatectl set-timezone Asia/Tokyo

source /etc/locale.conf

echo 'LANG=ja_JP.UTF-8' >> /etc/profile
```
以前作るのに苦労した記憶のあるec2-userのローカル時刻と日本語環境に直す起動ファイル。


#Splunkのインストール

`wget --content-disposition 'https://www.splunk.com/bin/splunk/DownloadActivityServlet?architecture=x86_64&platform=linux&version=latest&product=splunk&filename=.tgz&wget=true'`

https://community.splunk.com/t5/Installation/Use-WGET-to-download-Splunk/m-p/48090

これで、いつでも最新版がダウンロードできる。

https://qiita.com/nntsugu/items/c3c8e80259a02e117754

を見つつインストール。でも、ec2だとこのやり方そのままだとうまくいかないので、

```bash:install.sh
sudo su
groupadd -g 503 splunker
useradd -u 501 -g 503 splunker
passwd splunker
su - splunker
# ここでsplunker
export SPLUNK_HOME=/usr/local/splunk
wget --content-disposition 'https://www.splunk.com/bin/splunk/DownloadActivityServlet?architecture=x86_64&platform=linux&version=latest&product=splunk&filename=.tgz&wget=true'
tar xvfs splunk*
exit
# ここでrootに戻る。
mv /home/splunker/splunk /usr/local/
exit
#　ここでec2-userに戻る。
su - splunker
cd $SPLUNK_HOME/etc
cp splunk-launch.conf.default splunk-launch.conf
vi splunk-launch.conf
# SPLUNK_HOMEを定義
# 今回はSPLUNK_HOME=/usr/local/splunk
cd $SPLUNK_HOME/bin
./splunk start --accept-license
```
で起動する（はず。）

administratorのユーザ名とパスワードを聞かれるので、適当に打ち込む

#アクセス

![スクリーンショット 2021-05-04 15.07.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130729/8e7924e9-4792-0794-784e-5c65c172f7ce.png)

セキュリティグループがしっかり設定できていると、ログインが可能となる。
:sweat_smile: なんか恥ずかしいのが右上にでている。

#まとめ

とりあえず、EC2を起動して、splunkをインストール及び起動ができた。

`$SPLUNK_HOME/bin/splunk start`の前にappsとか入れたりすると、データも含めて起動できそう。

あとは、ちょこちょこと自動化していきます。
新しくなった、GitHubネイティブのDependabotの設定

先日、2021/8/3に以前のDependabotが終了することが発表されました。今後は、GitHubの機能の一部となった、「GitHubネイティブのDependabot」に一本化されるとのことです。
しかし、公式のドキュメントがあまり充実しておらず、困っている方も多いのではないでしょうか。
そこで、この記事ではGitHubネイティブのDependabotの設定をわかりやすく説明していきます。
#Dependabotとは
パッケージ[^1]のアップデートを自動で確認し、Pull Requestを出してくれる、便利な機能です。GitHubに搭載されています。
[^1]: 開発をする際に利用する、サードパーティ製のソフトウェアを指します。`package.json`などのようなファイルには、インストールされたパッケージの名称・バージョンなどが記載されています。
# Dependabotの設定
**ブラウザ版のGitHubでの操作になります。**
1. Dependabotを適用させたいリポジトリのInsightsを開く
2. 左側のメニューからDependency graphを選択
3. Dependabotタブを開く![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1172197/b23d7b4a-1d38-3716-2e40-46a4b98c2e2d.png)
このような画面になったでしょうか。（画面が黒いのは筆者がダークモードを適用しているからですので、気にしなくて大丈夫です。）
4. 「Enable Dependabot」をクリック
5. Create config file」をクリック

すると、以下の文が入力された`dependabot.yml`の編集画面が現れます。

```yaml:dependabot.yml
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
  - package-ecosystem: "" # See documentation for possible values
    directory: "/" # Location of package manifests
    schedule:
      interval: "daily"

```

このファイルは未完成なので、手を加えていきます。
## package-ecosystem
使用するパッケージマネージャーを入力します。
例）`npm`、`docker`
## directory
`package.json`や`Gemfile`などのファイルがあるディレクトリ（フォルダ）を、リポジトリのルートに対する相対パスで指定します。
例）`package.json`がリポジトリのルートにある場合→`directory: "/"`（初期設定のまま）
`Gemfile`が`/manifest`内にある場合→`directory: "/manifest"`
## schedule
パッケージ[^1]のアップデートを確認する頻度や時刻を設定します。
### interval
パッケージ[^1]のアップデートを確認する頻度を設定します。

| タグ | 意味 | 実行される時刻(初期値) |
|:-:|:-:|:--|
|  `daily` |  毎日 |  AM5:00(UTC[^2]) |
| `weekly`  | 毎週  |  毎週月曜日のAM5:00(UTC[^2]) |
|  `monthly` |  毎月 | 毎月1日のAM5:00(UTC[^2])  |
[^3]: 協定世界時。日本時間より9時間遅い。


<font color="red">**ここまでが必須の内容となります。**</font>
編集が終わったら`dependabot.yml`をコミットすれば完了です。お疲れさまでした。
## 筆者がその他に設定していること

```yaml:dependabot.yml
#これより上は省略
schedule:
      #ここも省略させていただきます
      timezone: "Asia/Tokyo"
```
デフォルトではUTC[^2]になってしまうので、`timezone: "Asia/Tokyo"`でタイムゾーンを日本標準時にしています。
[^2]: 協定世界時のこと。日本時間より9時間遅い。
## 全体
全体ではこのようになります。（**あくまでも一例です。**中身は開発環境によって異なるので、あくまでも参考程度でお願いします。）

```yaml:dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm" # See documentation for possible values
    directory: "/" # Location of package manifests
    schedule:
      interval: "daily"
      # Use Japan Standard Time (UTC +09:00)
      timezone: "Asia/Tokyo"
```

#参考
Dependabotの設定について（この記事では紹介していないオプションも多数あります）

https://docs.github.com/ja/code-security/supply-chain-security/configuration-options-for-dependency-updates
デザインに関する業務をする人のためのBrewfile

## これは何

- デザイナーはもちろん、デザイナーと関わりの多いエンジニアや、デザインエンジニアと呼ばれるような人向けに、いくつかFormulaeを紹介した記事です
- 無料でも十分に使えるものだけを紹介しています

## Formulae一覧

- FFmpeg
- ImageMagick
- Blender
- Figma
- FontBase
- ImageOptim

これらについて、筆者がよく使う用途とともに簡単に紹介します。

### FFmpeg

https://www.ffmpeg.org/

```shell:インストール
brew install ffmpeg
```

以下のようなシーンで使うことが多いです。

- フォーマットの変換
- 容量を軽くするためにサイズやビットレートを変更する
- 連番で書き出した画像を繋げて動画にする

（仕組みを分かっていれば「それはそう」な話ですが）動画ファイルをPremiereやAfter Effects経由で出力すると、矩形を小さくしたにも関わらず容量が増える場合すらあり、地味に大変です。
FFmpeg経由で実行した方が色々と楽だと感じています。

参考記事：

https://qiita.com/cha84rakanal/items/e84fe4eb6fbe2ae13fd8

### ImageMagick

https://imagemagick.org/index.php

```shell:インストール
brew install imagemagick
```

- フォーマットの変換
- 2枚の画像の差分を出す
- gifのループ回数変更

Photoshopのバッチを作っても良いのですが、設定が意外と面倒なので、ImageMagickから実行した方が楽だと思います。
あとはgifのループ回数変更は細かい話ながらかなり重宝しています。

参考記事：

https://qiita.com/yuji38kwmt/items/57c77f4526ca47193c1d

https://qiita.com/gunn/items/e7116d4863d6894e22d1

https://qiita.com/yoya/items/6bacfe84cd49237aea27

### Blender

https://www.blender.org/

```shell:インストール
brew install --cask blender
```

- 立体のアタリをとるための下書き
- ちょっとしたグラフィックを作る際、画面の情報量を増やす手段

フォトリアルな3DCGを作ろうと思うと一朝一夕には扱えませんが、レイアウトを考えるとかで幾何図形だけ使って下書きをするような場面では結構有効だと思います。
（あまりそういう使い方をしている人はみませんが……）
例えば、立体的に見えるロゴを作ろうと思った際にBlenderで下書きをしてからIllustratorでの作業に移る、といったフローは実際に行ったことがあります。

また、幾何図形のみの組み合わせでも平面のパスだけで作るより表情豊かに見えます。
以前私が作ったものを載せますが、PhotoshopやIllustratorで同等の情報量を出すのは結構大変だと思います。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/065c5c98-ac26-3af3-f0bf-fe92f334774e.png)

### Figma

https://www.figma.com/

```shell:インストール
brew install --cask figma
```

- UIデザイン・プロトタイピング
- ブレインストーミング
- スライド作成
- CATAN

SketchもHomebrewからインストールできますが、基本的には有料なソフトなのでFigmaを紹介します。
一番の目的であるUIデザインやプロトタイピングはもちろん、ブレインストーミングのような用途にも使えますし、発表用スライドをFigmaだけで完結させることも可能なんですね。
また、PluginやWebhookなども魅力の1つです。

参考記事：（3つ目は自分の記事ですが……）

https://qiita.com/hikaru_tayama/items/49373412ec1a515ff05d

https://qiita.com/seya/items/cb1a1a5350311549d41f

https://qiita.com/xrxoxcxox/items/9f7ce7131cd1778850e0

ちなみにCATANと書いたのはネタで、Figma上で遊べるCATANが公開されています。

https://www.figma.com/community/file/834302905869835373

### FontBase

https://fontba.se/

```shell:インストール
brew install --cask fontbase
```

- フォントのベンダーやライセンスごとにグループ分けをする
- 使わないフォントはオフにしておく
- Googleフォントをダウンロードせずに使う

最近はフリーフォントでも質の良いものが増えているので、気軽に色々なものを試せる世の中になっていると思います。
ですが、フリーの中でも商用利用の可否や、改変してロゴにして良いかどうかなど、ライセンスの違いは結構あります。

Macなら標準でもFont Bookというフォント管理アプリが入っていますが、これだけで様々な管理の仕方をするのは無理がありますよね。
というわけでフォント管理のためにソフトを入れておこう、というお話です。

### ImageOptim

https://imageoptim.com/mac

```shell:インストール
brew install --cask imageoptim
```

- 画像を圧縮する

使いどころが若干ImageMagickと被っていますが、ImageOptimはドラッグ＆ドロップするだけで複数ファイルを一気に処理してくれるのと、（非可逆圧縮含めて）圧縮の度合いを選べるのでシーンに合わせて使い分けています。

ちなみにCLI版のImageOptimもあります。
自分はGUIの方が気軽に使えたのでこちらを選んでいますが、もしCLIが良い場合は以下のコマンドでインストールできます。

```shell:インストール
brew install imageoptim-cli
```

## まとめ

主に画像や動画に関わるものを紹介しました。
Photoshopでやるまでもないなあ……みたいな場面で活躍するものが多いかと思います。
WSL2のsshdに他のPCからssh接続

```sh:start-sshd.bat
# sshdの起動
wsl -u root -- service ssh start

# ポートフォワーディング設定
wsl -u root -- sh /opt/bin/port_forwarding.sh
```

```sh:/opt/bin/port_forwarding.sh
#!/bin/bash

set -eux

IP=$(hostname -I)

#netsh.exe interface portproxy delete v4tov4 listenport=22
netsh.exe interface portproxy add    v4tov4 listenport=22 connectaddress=$IP

sc.exe config iphlpsvc start=auto
sc.exe start  iphlpsvc
```

## 管理者権限で実行させるショートカット登録

管理者権限で実行させる必要がある。
`start-sshd.bat`のショートカットを作成し、`管理者として実行`にチェックを入れる。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/9575501f-d166-95a2-5088-40e73dd65367.png)

## 起動方法

スタートアップに入れても管理者権限で実行してくれなかったので
手動でダブルクリック。

タスクスケジューラに登録という方法がおすすめみたいなので必要に応じて登録。
ショートカットキーで登録したコマンドをターミナルで実行するVSCodeの拡張機能

# 環境

Windows 10
Version: 1.55.2

Windowsを想定して説明します。他のOSでは適宜読み替えてください。

# 目的

現在開いているプログラムファイルをターミナルで実行するような拡張機能はたくさんあると思いますが、自分で任意のコマンドを登録して実行させたかったので作りました。

# インストール

VSCodeには~~面倒だったので~~登録していないので、GitHubからgit cloneしてください。
WindowsのVSCode拡張機能は`C:\Users\xxx\.vscode\extensions`に格納されています。

```powershell
cd C:\Users\xxx\.vscode\extensions
git clone https://github.com/raster0x2a/vscode-my-shortcut.git
```

# ショートカットキーとコマンドの登録

１. VSCodeのキーバインドのファイルは`C:\Users\xxx\AppData\Roaming\Code\User\keybings.json`にあるので、そこで以下のように記述してください。
  
```json
{
    "key": "[[ 登録したいショートカットキー 例: ctrl+shift+z ]]",
    "command": "my-shortcut.execInTerminal"
}
```
  
２.  VSCodeの設定ファイルは`C:\Users\xxx\AppData\Roaming\Code\User\settings.json`にあるので、そこで以下のように記述してください。もし現在開いているファイルのパスを利用したい場合は、コマンドに`{{filepath}}`を含めて記述してください。
  
```json
"my-shortcut": "[[ 実行したいコマンド 例: python {{filepath}} ]]"
```
  
３. 必要に応じてCtrl+Pで表示されるコマンドパレットでReloadと入力し、Enterで再読み込みをしてください。
コンフリクトが起こったGemの修正とActiveRecord::PendingMigrationErrorの対応

##はじめに
コンフリクトが起こった際に、下記の内容を修正したので、備忘録としてまとめました。
・Gemファイルのインストール＆アンイストールの手順（コンフリクトの原因）
・ActiveRecord::PendingMigrationErrorの対応手順
※コンフリクトの状況を確認する方法は、この記事には記載しておりません。

##状況
作業ブランチで編集したのち、プルリクを出したらコンフリクト
（しかもGemファイル！Gemファイル修正したら次のエラー！）

##環境
Rails 6.1.2.1

##手順
####①コンフリクトの状況を確認する

コンフリクトの解消手順は、この記事を参考にすすめました。(わかりやすかったです。)
-[Git コンフリクト解消手順](https://qiita.com/crarrry/items/c5964512e21e383b73da#%E6%89%8B%E9%A0%86)

####②Gemのインストール

・インストール済みのGemの確認（差分がないか確認）

```
$ gem list
```

・導入したいGemをインストール

```
$ gem install gemの名前
```

導入後、必ずrails sで、起動確認しよう


####③Gemのアンインストール

・削除したいGemをアンインストール

```
$ bundle exec gem uninstall gem名
```

・次にGemfileから直接削除する

```
$ bundle install
```
・Gemfile.lockを確認すると、消えています。


これで、Gemの修正は完了です:relaxed:

####④ActiveRecord::PendingMigrationErrorの対応

さて、これでプルリクだそうと起動確認すると、下記のエラーあり。

![スクリーンショット 2021-05-04 13.14.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923146/79bdb007-2cdd-c368-c00b-ad5459028016.png)


・なぜこのエラーが起こるのか？

データベースの整合性が取れていないため、起こるエラーです。
エラー文をよく読むと、解決方法も一緒に示しています。
(なんて親切なんでしょう！)

・エラー文どおり、下記を実行

```
$ bin/rails db:migrate RAILS_ENV=development
```

・実行結果

```
○○○○○@xxxxxx % bin/rails db:migrate RAILS_ENV=development
== 20210403052917 CreateReads: migrating ======================================
-- create_table(:reads)
   -> 0.0536s
-- add_index(:reads, [:user_id, :text_id], {:unique=>true})
   -> 0.0014s
== 20210403052917 CreateReads: migrated (0.0553s) =============================
```

これで無事にrails sで、サーバー起動できました。
![スクリーンショット 2021-05-04 14.50.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923146/8ffd9514-0c6e-6a3b-e380-7233f6f9eec6.png)

エラー文を焦らず、きちんと読んだので対応できました:relaxed:
for文の繰り返し処理（JavaScript）

Webページではある数値や数式、文字列を繰り返し用いるシーンは数多く見られますがその時に便利なのがJavaScriptでfor文を使ったループ（繰り返し）処理です。
用途に応じてfor文と while文 という2種類を使い分けます。
ここではfor文の繰り返し処理の基礎を説明していきます。

#for文

for文は繰り返す回数が決まっている場合に使用します。
式は以下の通りです。

```
for (初期値; 条件式; 増減式) {
　　繰り返し処理
}
```

参考例を使って実際に動かしてみましょう。


```javascript
for (var i = 0; i < 5; i++) {
  console.log(i + "←iが1ずつ上がっていきます");
}
```

こちらをコンソールで見てみると

```
0←iが1ずつ上がっていきます
test.js:2 1←iが1ずつ上がっていきます
test.js:2 2←iが1ずつ上がっていきます
test.js:2 3←iが1ずつ上がっていきます
test.js:2 4←iが1ずつ上がっていきます
```

このようになります！

初期値 var i = 0;
　「i」という変数を定義して、0を代入しています。
条件式 i < 5;
　　i < 5がtrueの場合に処理を繰り返すことを意味しています。
増減式　i++
　処理を繰り返すたびに　i に１を足していくことを意味しています。
　（i++は1ずつ足していく、i–は1ずつ減らしていく、という意味）

つまり
4←iが1ずつ上がっていくのですが出力された後は「i」の値が　5になります。
その場合条件式が　5 < 5になり、falseが返るため、繰り返し処理をしないということです。
Vue.js出力

#概要
Vue.jsでこんにちわを出力するまでについて、まとめました。

#HTML

```index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="css/styl.css">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <p>皆さん{{ message }}</p>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script src="js/main.js"></script>
</body>
</html>
```
Vue.jsは、HTMLのテンプレート構文があります。
今回の実装ではHTMLファイルを使用します。

Vue.jsの機能を適用させるためにbody要素の直下にdiv要素を作ります。id属性を使用します。名前は特に決まりはありません。
JS側で、このidをターゲットにVue.jsが提供するデータや、メソッドを使用します。
このidターゲットがない場合、Vue.jsを使用することが出来ません。

{{...}}これをマスタッシュ構文と言います。これを書くことで、dataオブジェクトのmesaggeプロパティの値を引用することが出来ます。


scriptタグには、Vue本体のCDNを組み込みます。ローカル環境にダウンロードしたVue本体のファイルを読み込み、ユーザーが作成したファイルを実行する方法です。
２つ目のscriptタグにJSファイルを読み込みます。
*注意:２つのスクリプトタグを反対に記述すると、CDNが読み込まれる前にJSファイルが読み込まれてしい、errorになります。


https://vuejs.org/v2/guide/installation.html

#JS

```index.js
const app =new Vue({
  el:'#app',
  data:{
    message:'こんにちわ'
  }
});
```

Vue.jsは、Vueクラスをインスタンス化して使用します。
new Vueは、Vueクラスからインスタンスを生成する場合の命令です。
{}の中には、オブジェクトリテラルを書きます。
el ▶Vueインスタンスを結びつけるHTML要素を指定します。
data▶Vue.jsで扱うデータを入れておく場所です。　このデータをHTMLファイルから読み込み画面に表示することが出来ます。テンプレートHTMLから参照できる値を参照できる値を格納したオブジェクトです。なお、マスタッシュ構文に格納できるのは式だけです。代入、条件分岐は使用することは出来ません。
Vue.jsでは、アプリを利用する値をデータオブジェクトで用意して、テンプレートが参照することをデータバインディングと言います。

{マスタッシュ構文}では属性の値などは指定することは出来ません。
属性の変更、条件分岐などはディレクティブを使用します。ディレクティブは[v-]から始まります。
Visual Studio 2022 に備えて大量の C# アプリを一気に作る

2021年4月19日に Visual Studio 2022 のアナウンスブログが公開されました。
[Visual Studio 2022 | Visual Studio Blog](https://devblogs.microsoft.com/visualstudio/visual-studio-2022/?WT.mc_id=DT-MVP-5002209)

**※注意：本記事執筆時点では、まだ Visual Studio 2022 はリリースされていません。**

Visual Studio 2022 の最大の特徴としては 64ビット化されるということです。
つまり、巨大なアプリケーションの開発時でも Visual Studio がメモリ不足に陥りにくいということです。

上記のブログでも 1600 のプロジェクトを含むソリューションの起動の様子が載っています。
![launch visual studio](https://devblogs.microsoft.com/visualstudio/wp-content/uploads/sites/4/2021/04/ezgif-6-fe5bba5020a8.gif)

Visual Studio 2022 がリリースされた暁には私も同じ様子を体感したいので、巨大なソリューションを一気に作れるようにします。

.NET Core なら[コマンドライン (CLI)](https://docs.microsoft.com/ja-jp/dotnet/core/tools/?WT.mc_id=DT-MVP-5002209) が提供されているため、すべてコマンドでソリューションファイルやプロジェクトファイルを作ることが可能です。
for文でひたすらに作っていきましょう！

```sh
SOLUTION_NAME=HugeDotnetSolution
dotnet new sln -o $SOLUTION_NAME
cd $SOLUTION_NAME

for i in `seq 1000`
do
  APP_NAME=ConsoleApp$i
  dotnet new console -n $APP_NAME --no-restore
  dotnet sln $SOLUTION_NAME.sln add $APP_NAME
done
```

---

（追記）上記のコマンドで C# のプロジェクトを **1000個** つくってみた動画を載せておきます。
プロジェクトのリストアは行わないようにしていますが、私の環境では30分かかりました。

<iframe width="560" height="315" src="https://www.youtube.com/embed/biJUaCNnfXA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
Laravelの多対多で中間テーブルのレコードを論理削除する

Laravelの多対多のリレーションで、中間テーブルに論理削除を実装する。

## テーブル準備
マイグレーションファイル作成

```
 php artisan make:migration create_article_tag_table
```

``deleted_at``カラムを追加する

```php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateArticleTagTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('article_tag', function (Blueprint $table) {
            $table->integer('article_id');
            $table->integer('tag_id');
            $table->timestamp('deleted_at')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('article_tag');
    }
}

```


## 中間テーブルの更新

``updateExistingPivot``を使用して中間テーブルを更新。

```php
use Carbon\Carbon;

public function delete(Request $request, Article $article)
{
    $ids = $article->tags->pluck('id');
    $article->tags()->updateExistingPivot($ids, ['deleted_at' => Carbon::now()]);

    return redirect('/articles');
}
```

## 論理削除以外のレコードを取得

``whereNull``メソッドで``deleted_at``を使用すると、論理削除以外のレコードが取得できます。

```php
use App\Models\Tag;

class Article extends Model
{
    public function tags()
    {
        return $this
                ->belongsToMany(Tag::class)
                ->whereNull('deleted_at')
                ->withTimestamps();
    }
}
```

## 中間テーブルで論理削除するべきか

中間テーブルで論理削除をするのなら、そもそもテーブル設計を見直す必要がありそうです。

>注意： ピボットモデルでは、SoftDeletesトレイトを使わないほうが良いでしょう。ピボットレコードのソフト削除が必要な場合は、ピボットモデルを実際のEloquentモデルに変換することを考えてください。

https://readouble.com/laravel/8.x/ja/eloquent-relationships.html#defining-custom-intermediate-table-models

「とりあえず削除フラグ」はSQLアンチパターンです。

https://www.slideshare.net/t_wada/ronsakucasual

参考
https://www.it-swarm-ja.com/ja/laravel/%E5%A4%9A%E5%AF%BE%E5%A4%9A%E3%81%AE%E9%96%A2%E4%BF%82%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E4%B8%AD%E9%96%93%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%AE%E3%82%BD%E3%83%95%E3%83%88%E5%89%8A%E9%99%A4/1072983220/
Denoの開発環境をDocker+VSCodeで構築

Denoを使うと、TypeScriptをコンパイルせずに実行できます。これをDockerコンテナ上で実行し、DenoもインストールすることなくTypeScriptを動かしてみましょう。

https://deno.land/

## 環境
- Debian version 10.9 (ChromeOS 89.0 Chrostini Linux)
- Docker 20.10.6
- deno 1.9.2
    - v8 9.1.269.5
    - typescript 4.2.2
- Visual Studio Code 1.55.2

## 構築
Dockerfile,docker-compose.ymlを配置してコンテナを立ち上げVSCode Remote Containerでアタッチするだけです。

```Dockerfile:Dockerfile
FROM debian:stable-slim
WORKDIR /app

RUN apt-get update && apt-get install -y \
    curl \
    zip \
    unzip \
    git \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

RUN curl -fsSL https://deno.land/x/install/install.sh | sh
ENV DENO_INSTALL="/root/.deno"
ENV PATH="$DENO_INSTALL/bin:$PATH"
```

```yml:docker-compose.yml
version: '3'
services:
  app:
    build: .
    volumes:
      - .:/app
```

`$ echo 'console.log("Hello, world")' > main.ts`のように適当なTypeScriptファイルを作って、`$ docker-compose build`して`$ docker-compose run --rm app deno run main.ts`して動作したら成功です。

### VS Codeの設定

[vscode-deno](https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno)拡張機能をインストールして下記設定で有効にする必要があります。VS CodeはデフォルトでTypeScriptに対応しているのでそれなりに動いてくれるのですが、エディタ上で`noImplictAny`が効かなかったりしました。

```json:.vscode/settings.json
{
  "deno.enable": true
}
```

## 参考文献
- [【VSCode・Deno】拡張機能：Remote \- Containers で Deno の開発環境を構築 \- 開発覚書はてな版](https://kakkoyakakko2.hatenablog.com/entry/vscode-deno)
サイドバーやヘッダーなどを追従させたい場合はstickyを使えば最強という話。


サイドバーやヘッダーの追従などをjqueryなどを使って、高さを取得して、スクロール毎にイベントを発生させて、、、としている人が結構いると思います。

しかし、そんなのは今は昔の話。

今はstickyを使えば追従は簡単に表現できます。

`sticky`は少し特殊なプロパティではありますが、慣れれば超便利アイテムです。

`position:sticky;``top:0;`などのように高さを指定してあげればそれだけで親要素の範囲内で追従します。

本当に便利なので是非使ってみてください。

これで終わりです。
swapの作成方法

# 概要
業務でswap領域を作る機会があったので自分用メモ。

# 環境
- Centos7

# swap作成

ddコマンドで指定サイズの空ファイルを作成。

```
// 1GBの場合
$ dd if=/dev/zero of=/swapfile bs=1M count=1024
// 2GBの場合
$ dd if=/dev/zero of=/swapfile bs=1M count=2048

$ chmod 600 /swapfile
```

`mkswap`：作成したファイルをスワップ領域として使用できるようにする。
`swapon`：スワップ領域を有効化。

```
$ mkswap /swapfile
$ swapon /swapfile
```

サーバ起動時に有効にする設定。再起動して有効になっている確認します。

```
$ vim /etc/fstab
↓
/swapfile               swap                   swap    defaults        0 0

$ reboot
$ free -m
```

# 参考になったサイト

https://densan-hoshigumi.com/server/gcp-free-linux

https://centos.bungu-do.jp/archives/65
Androidのワイヤレスデバッグを試す

# はじめに
* [Flutter2.0](https://flutter.dev/docs/development/tools/sdk/release-notes/release-notes-2.0.0)がリリースされていたのでちょっとさわってみようかと思い実機の準備をしていたところ、開発者向けオプションに`ワイヤレスデバッグ`という項目が追加されていたので調べてみました。
* この項目はAndroid11から追加されたみたいです。
    * 今回使用する端末はPixel3です。

## 手順
1. 開発者向けオプションの`ワイヤレス デバッグ`をタップ
![Screenshot_20210504-121912.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290533/0c58348b-201c-e6bc-726e-68a8a485b777.png)

2. `ペア設定コードによるデバイスのペア設定`をタップ
![Screenshot_20210504-121942.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290533/b426a2e4-1dc2-07b6-0d3f-441024685b08.png)
2.1. タップするとこんなダイアログが表示される
![Screenshot_20210504-122001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290533/2794ab50-9567-9dc5-90b5-fe3da6a8134a.png)

3. ダイアログに表示されているIPアドレスとポートで`adb pair [ip_address]:[port]`を叩く
3.1. 次にダイアログに表示されている6桁の`ペア設定コード`を入力する。
3.2. 一度ペアリングに成功すれば次回以降は自動的にペアリングされるようになります。

## abdコマンドが見つからないとき
* パスが通っていないと思われるのでパスを通す。
    * `export PATH=$PATH:$HOME/Library/Android/sdk/platform-tools`

## おわりに
* いちいちコードを繋がなくてもデバッグできるのはかなり快適でありがたい。:smile:
* Android11以前でもワイヤレスデバッグをする[方法](https://developer.android.com/studio/command-Zline/adb?hl=ja#wireless)はあったみたい。知らなかった。
    * IntelliJやAndroid Studio用の便利な[プラグイン](https://plugins.jetbrains.com/plugin/14969-adb-wi-fi)もあるみたいです。
JavaScriptのフレームワーク

#概要

JSのライブラリとフレームワークについて触れます。
1,フレームワークとライブラリについての違いについて
2,JSのフレームワーク
3,Vue.jsの特徴
3,コンポーネント指向とは

#1,フレームワークとは

本来、開発する上で必ずフレームワークが必要な訳ではありません。JSだけでアプリ開発を行うことはできます。
しかし、大規模な開発を大人数ですすめているとします。そして、コードの書き方が人により少しずつ変わっているとします。
このように、書き方が少しずつ違うコードを複数人で着手するのはバグに繋がります。そこで、必要になるのがフレームワークです。
フレームワークとは、再利用可能なクラスを言います。設計・開発でよく使用するコードをフレームワークが用意してくれています。
プログラマーは、フレームワークが提供してくれる枠組みにそって開発することが出来ます。
それにより、バグが少ない設計になりより堅牢なアプリケーションとして開発することが出来ます。
ただし、現段階であまり複雑な設計で無いならば無理にフレームワークを導入する必要はありません。

#ライブラリとは

ライブラリとは、コードをより簡略的に記述することが出来ます。JSで記述する長いコードをｊQueryを使用することで、より簡略的に書くことが出来ます。それにより、動作を軽くすることが出来ます。
ライブラリとはユーザーが呼び出して複数回記述するコードを効率的に記述し、開発をすすめることを目的としています。
フレームワークとはすでに用意されている骨組みを再利用して効率的に開発をすすめることを目的としています。

#2,JSのフレームワーク
Angula ▶グーグルを中心に開発されているフルスタックフレームワーク
React　▶フェイスブックが開発したビュー相当の機能を提供するフレームワーク
Vue　▶　ビューに特化したシンプルなフレームワーク


#3,Vue.jsの特徴

1,コストが低い
Vue.jsは、HTMLベースのテンプレート構文を採用しています。なので、初心者にも学習コストが低いと言われています。

2,段階的に導入することができる
例えば、規模を小さく提供したアプリケーションが拡大したため機能を追加する必要が出てきたとします。その場合に、段階にあわせてシステムを導入しやすいというメリットがあります。
アプリが大規模になり、似たようなUIが出てきたら、コンポーネントを導入することが出来ます。
また、機能が増えて明確にURLを分割することが出来ます。VueRouterを使用することが出来ます。
アプリで扱うグローバルなデータを中央管理するためのデータベースが必要になってきます。そこで使用するのが、Vuexです。

#4,コンポーネント指向
コンポーネントとはアプリを構成するUIの部分です。テンプレート、オブジェクト、スタイルの集合体です。
ある程度、規模が大きくなるとコンポーネントを組み合わせて作リます。
コンポーネントは、複数配置することも出来ます。また入れ子にすることも出来ます。
ウルトラ簡単に導入できてしまうBootstrap

こんにちは。

当記事ではBootstrap導入と簡単な使用例について記していきます。
対象はプログラミングhtmlやcssは触ったことある初学者向けです。
※検証環境:Eclipse・GoogleChrome(Java8・PostgreSQL・SpringBoot・Thymeleaf)

1．以下サイトからBootstrap本体をダウンロード
https://getbootstrap.com/docs/5.0/getting-started/download/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1439267/9da229fb-697b-64e7-b647-5839844c1f8c.png)

2．ダウンロードしたzipを解凍後cssとjsファイルを自分の環境にコピーする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1439267/82c08974-e56b-39f1-655e-f966b220da31.png)

私の開発環境のSpringbootアプリだとここにドラッグ&ドロップしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1439267/e1c9a852-ed54-d2ec-e7d1-50554e2829e2.png)

3．HTMLファイルに以下を追記する
3.1 &lt;head&gt;&lt;/head&gt;の中に以下2行をコピー

```sample.html
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">　
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
```
3.2 &lt;body&gt;&lt;/body&gt;の中に以下3行をコピー(私はbody部の最後に書きました)

```sample.html
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
```

BootStrapの導入は以上で終わりです。pomに追記するなどの別の方法もありますが、今回は割愛します。
後は実際にHTMLのタグにclassを追加して試してみると良いと思われます。
RDSとRedshiftをDatabase Migration Serviseでレプリケーションする際に気を付けることと読むべきドキュメント

#


# RDSでは

## db_parameter
`binlog_format=ROW`にする。

## バックアップ保存

バックアップ保存日を1日以上にする。
atutomated backup をenableにする。



# Redshift

VPC拡張はしない（超重要）
https://docs.aws.amazon.com/redshift/latest/mgmt/enhanced-vpc-routing.html


## RedshiftのクライアントツールはDbeaverを使うのが良かった。

https://www.youtube.com/watch?v=KVVm5uScWVM


## DMSでRedshiftをターゲットとして利用する。

https://docs.aws.amazon.com/ja_jp/dms/latest/userguide/CHAP_Target.Redshift.html#CHAP_Target.Redshift.Privileges


# DMS

## IAM
AWS CLI と AWS DMS API で使用する IAM ロールの作成

https://docs.aws.amazon.com/ja_jp/dms/latest/userguide/CHAP_Security.html#CHAP_Security.APIRole

移行前評価について
https://docs.aws.amazon.com/ja_jp/dms/latest/userguide/CHAP_Tasks.AssessmentReport.html


## ベストプラクティス
https://docs.aws.amazon.com/ja_jp/dms/latest/userguide/CHAP_BestPractices.html#CHAP_BestPractices.TaskLog

## to Redshift
https://docs.aws.amazon.com/ja_jp/dms/latest/userguide/CHAP_Target.Redshift.html


# おまけ：QuickSight
## Redshiftへの接続の確立

https://aws.amazon.com/jp/premiumsupport/knowledge-center/quicksight-redshift-private-connection/

## エンドポイント (HTTPS)

https://docs.aws.amazon.com/ja_jp/quicksight/latest/user/regions.html


```
アジアパシフィック (東京) (ap-northeast-1)

ユーザーアクセスのためのウェブサイト – https://ap-northeast-1.quicksight.amazonaws.com

IP アドレス範囲 – 13.113.244.32/27

エンドポイント (HTTPS) – quicksight.ap-northeast-1.amazonaws.com
```

## クエリについて

https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/r_concat_op.html


## Migrate and Sync RDS MySQL/MariaDB to Redshift using AWS Data Migration Service.
https://medium.com/swlh/migrate-and-sync-rds-mysql-mariadb-to-redshift-using-aws-data-migration-service-4dd352e8c411

## AWS resource

https://docs.aws.amazon.com/ja_jp/quicksight/latest/user/accessing-data-sources.html


## 権限関係

npm SDK
https://www.npmjs.com/package/amazon-quicksight-embedding-sdk

https://docs.aws.amazon.com/quicksight/latest/user/embedded-analytics-dashboards-with-anonymous-users-step-1.html


https://channaly.medium.com/quicksighthow-to-embed-amazon-quick-sight-to-your-ruby-on-rails-application-26b1de5c7baf

アプリにダッシュボードを埋め込む手順。
https://docs.aws.amazon.com/ja_jp/quicksight/latest/user/embedded-analytics-dashboards-with-anonymous-users-step-3.html
TCP/IP　超基本のキーワード

## ネットワークの基本に関して確認しました。
### プロトコルとは？IPアドレスとは？など超基本の確認です。

そもそも、コンピューターネットワークとはコンピューター同士がつながって情報がやり取りできるようになることです。

## ■LANとWAN

「LAN(Local Area Network)」とは家庭内や社内など近くにあるコンピューターを繋げたネットワークで、「WAN(Wide Area Network)」は遠くにあるコンピューターを繋げたネットワークです。

ネットワークで最も規模が大きいのが「インターネット」で様々な企業や家庭を繋いで情報のやり取りができます。

携帯電話やスマホを繋げるのは「モバイルネットワーク」で、無線技術を利用したネットワークです。（4G,5G,Wi-Fi,WiMAXなど）

## ■パケット

コンピューターネットワークでは「回線交換方式」と「パケット交換方式」があり、前者は回線を占有して一対一で通信をするアナログ電話などに使われますが、Web閲覧やメールの際は後者が使えわれます。

パケット交換方式ではメールやファイルなどのデータをパケットと呼ばれる単位に分割しネットワークにのせて届ける。その為、メールの受信とwebの閲覧などが同時にできたり、複数の相手と並行して通信ができます。

よく聞く「パケット」というのはここから来てたのですね。

## ■全体像(TCP/IP階層モデル)

コンピューターネットワークでは「アプリケーション層」「トランスポート層」「インターネット層」
「ネットワークインターフェース層」の4層に分類され、お互いに連携しながら活動しています。

### 「アプリケーション層」
Webや電子メールなどのサービスをユーザーに提供する
プロトコル：HTTP、SMTP、POP3

### 「トランスポート層」
アプリケーション層とインターネット層を仲介し正しく届けるための手配
プロトコル：TCP、UDP

### 「インターネット層」
IPアドレスを手がかりにコンピューターへデータを届けられるようにする。
プロトコル：IPv4、IPv6、ICMP

### 「ネットワークインターフェース層」
実際にデータを伝送する
プロトコル：イーサネット、PPP

※アプリケーション層以外はデータを届けるための機能を担当しています。

データを送る際はアプリケーション層から順に階層を通過しながら、情報が付加され、最終的には電気や光の信号として相手に送られます。送られた側は逆にネットワークインターフェース層から順に処理をしてデータを受け取ることができます。

## ■プロトコル

コンピューター同士の厳密な決まり事のこと。
どういう手順で何を送るかのルール、仕様書。

プロトコルは各層での役割ごとに細かく分かれているので、複数のプロトコルを組み合わせて利用します。

例えば、「webページがみたい！」場合は

- アプリケーション層ではHTTPプロトコルを使用
- トランスポート層では「TCP」を使用
- インターネット層では「IP」を使用
- ネットワークインターフェース層では「イーサネット」を使用

## ■TCP／IP
TCP／IPは一つのプロトコルを指す言葉ではなく、インターネットで標準的に利用されるプロトコル一式をまとめて呼ばれています。TCPとIPはその中の代表的なプロトコルです。


## ■IPアドレス
インターネット層では宛先のコンピューターまでデータを届けますが、世界中にある無数のコンピューターを区別する必要があります。各コンピューターには「IPアドレス」という重複しない識別番号があります。郵便番号や電話番号のイメージですが、地理的な位置とは連動しません。その代わり、ネットワーク単位で割り当てられるので、どこのネットワークに所属しているかと規模を推測することができます。

IPv4という0〜255の数値を4つ組み合わせたものを使っていますが、インターネットの急激な成長に伴い、IPv6への対応が進められています。これにより340澗の機器を識別できます。


## ■予備知識

**【無線LANで使われる周波数の特徴】**

2.4GHz帯（1秒間に約24億回の波ができる）は、障害物を浸透しやすいが電子レンジなど他の機器で使われることが多いため影響を受けることがある。

5GHz帯（1秒間に約50億回の波ができる）
障害物で跳ね返りやすいが、他との干渉が少なく通信が安定し通信速度も上がりやすい。

**【共通鍵と公開鍵】**

暗号化と復号に使うパスワードなどのことを鍵といいま。

- 共通鍵暗号
1つの鍵でデータを暗号化／復号します。
つまり同じ鍵を持っている人しかデータの中身を見れません。
高速で処理できるメリットがありますが、鍵を送る際に鍵を盗まれたり、やり取り相手ごとに共通鍵を用意するというデメリットもあります。

- 公開鍵暗号
暗号化の鍵と復号の異なる2つの鍵をセットで使用します。1つの鍵のうち1つを相手に渡し（公開鍵）、もう1つを自分で保管（暗号鍵）しておきます。

やり取りの際は、まず公開鍵を相手に渡し、貰いたいデータをこの鍵で暗号化してもらう。もらった暗号化されたデータは秘密鍵で復号ができるという仕組み。

この場合、仮に公開鍵を盗まれてもデータを復号することができないため安全性が高い。


>参考文献
[スラスラわかるネットワーク&TCP/IPのきほん 第2版](
https://www.amazon.co.jp/%E3%82%B9%E3%83%A9%E3%82%B9%E3%83%A9%E3%82%8F%E3%81%8B%E3%82%8B%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF-TCP-IP%E3%81%AE%E3%81%8D%E3%81%BB%E3%82%93-%E7%AC%AC2%E7%89%88-%E3%83%AA%E3%83%96%E3%83%AD%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9/dp/4797396075)
unityでスマホゲーム制作までのお勉強用記録記事１

今日から毎日勉強の記録を保存していくだけのメモ帳



現在unityで2Dマリオの用なゲームを練習で1本作成した。
しかし作成期間が長かったので結構忘れてることが多く、新しいゲームを作るのが困難だったため再度記録用も含めて記事を作成。
1日中家にいない日もあるので、そういう日以外で記録を付けていきます。

Void_Start()
{
Debug.Log("ゲーム制作がんばるぞ！");
}
Julia で Actor(4)

## RemoteでFutureをサポートする

Juliaの`Distributed`パッケージには、`Future`が定義されているので、これを使えばいいのだけど、基本的には`remotecall`などで使うようにできているようで、ドキュメントがない。ので、ソースを読んでみた。

## Futureの使い方
ここでは、手元で`Future`を作ってリモートノードに渡し、リモート側で値をアサインすることを考える。

まず、手元で`Future`をつくる。これには次のようにすればよい。

``` julia
using Distributed
future = Future(worker)
```
ここで`worker`は`Distributed.Worker`型。この値を、ワーカIDから得るには`Distributed.worker_from_id`関数を使えばいい。

そして、この`Future`のリファレンスID(RRID)を作ってリモートワーカに渡す。これには`Distributed.remoteref_id`を用いる。

```
rrid = remoteref_id(future)
```

こうして得られたRRIDを何らかの方法でリモートノードにわたす。RRIDはごく普通のデータ型なので、`RemoteChannel`や、通常の`remotecall`で渡すことができる。

リモート側で値をアサインするには、次のようにする。RRIDから`RemoteChannel`に変換して、そのチャンネルに値を書き込む。

``` julia
fcn = Distributed.lookup_ref(rrid)
put!(fcn, 12345)
```

裏で何がおこってるのかよくわかっていないが、取りあえず動くようだ。

## ActorでFutureをサポートする

あとはストレートフォワード。メッセージとRRIDをタプルとして送り、`handle`メソッドを呼出した結果を、RRIDからつくったチャンネルに書くようににすればいい。

``` julia
module MyActor2
export Actor, Message, start, ActorRef, callOn, @startat
import Distributed

abstract type Actor end
abstract type Message end
const MessagePair = Tuple{Message, Distributed.RRID}

function handle(a::Actor, m::Message) println("should not be called") end

##
function taskLoop(cn::AbstractChannel, target::Actor)
    while true
        msg, rrid = take!(cn)
        fcn = Distributed.lookup_ref(rrid)
        try 
            res = handle(target, msg)
            put!(fcn, res)
        catch e
            println(e)
            put!(fcn, e)
        end
    end
end

function createLoop(actorCons)
    cn = Channel()
    @async taskLoop(cn, actorCons())
    return cn
end
```

`ActorRef`という型を導入する。これは、`RemoteChannel`と`Worker`を対にしたもの。`Worker`は`Future`を作るために必要なのだが、よく考えると`RemoteChannel`に必要な情報が載っていそうな気がするので、不要かもしれない。

``` julia
function start(actorCons, node=1) 
    cn = Distributed.RemoteChannel(()->createLoop(actorCons), node)
    ActorRef(cn, node)
end

macro startat(id, expr)
    thunk = esc(:(()->($expr)))
    quote
        start($thunk, $(esc(id)))
    end
end

struct ActorRef
    cn::Distributed.RemoteChannel
    w::Distributed.Worker
end
ActorRef(cn::Distributed.RemoteChannel, id::Integer) = 
    ActorRef(cn, Distributed.worker_from_id(id))

function callOn(ref::ActorRef, mes::Message)
    rr = Distributed.Future(ref.w)
    RRID = Distributed.remoteref_id(rr)
    put!(ref.cn, (mes, RRID))
    return rr
end    

end ## module
```
`start`にクロージャを指定しなくて済むように、マクロ`@startat`を追加した。


## 使い方
使い方はこんな感じ。

``` julia
using Distributed
addprocs(1)

##
@everywhere push!(LOAD_PATH, pwd())
@everywhere using MyActor2
##

@everywhere begin
    mutable struct Accum <: Actor v::Int64 end
    struct Add <: Message v::Int64 end
    struct Sub <: Message v::Int64 end
    function MyActor2.handle(a::Accum, mes::Add) a.v += mes.v; a.v; end
    function MyActor2.handle(a::Accum, mes::Sub) a.v -= mes.v; a.v; end
end

##
ref = @startat 2 Accum(0)

##
fetch(callOn(ref, Add(10)))
##
fetch(callOn(ref, Sub(3)))
```

マクロをつかうことで

```julia
ref = start(()->Accum(0), 2)
```
を下のように書けるようになった。

```julia
ref = @startat 2 Accum(0)
```
対して変わらんか。
JavaScript 変数名と値を文字列として取得する

JavaScriptじゃない記事ですが次の記事を見ました。

デバッグ時はprintではなく、Icecreamを使うと便利 - Qiita
https://qiita.com/purun/items/c7aca300b970344214cf

JavaScript でも、変数名と値を同時出力したいと以前から思っていました。

```js
const a = 10;
console.log(`a:${a}`); // a:10
```

開発時にデバッグログとして、こんな感じに出力するコード書くときがよくあります。
この時、変数名が1文字とかなら問題ないですが、きれいなコードを書こうとするとぼちぼち変数名は長くなる時は多くあります。その時に、変数名を2回書くのがだるいわけです。

なので、どうにか解決したいかなと思って、次の関数を書いてみました。evalを使えばできます。

```js
const varNameValue = (name) => {
  return `${name}:${eval(name)}`;
}

const a = 10;
console.log(varNameValue('a')); // "a:10"
```

これは確かにできるのですが、eval は、いろいろセキュリティとか考える必要があったりなかったりしそうでやっかいそうなので使うのを避けたいところ。

MDNでも酷評されている感じですし、いろいろ怖いです。使い方に注意しておけばそれほど問題ないとも思いますけれども、念の為なるべくevalは避けたい。

eval() を使わないでください! - eval() - JavaScript | MDN
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_eval!

MDNでは、eval の回避方法として、Function 使え、とあるけれども、今回の場合には当てはめられそうにないです。


こういうときはどうしたら効果的なコード書けるかな、と思ってたところに、タイムリーに、mizdra's blog で紹介されていました。

JavaScript で print デバッグ時に変数名を出力する - mizdra's blog
https://www.mizdra.net/entry/2021/05/03/000139

簡単なのはこういうことなんですね。

```js
const a = 10;
console.log({a});
// {a: 10}
```
オブジェクト生成の省略記法でオブジェクトをconsole.logに渡せば、ブラウザやnodeの表示側で変数展開してくれるわけですね。なるほどなるほど。

この仕組みを使えば自前で変数名と値を展開して文字列として取得できるよな。そういえば。
ということで、ヒントにさせていただいて気がつけましたので、console.logにわたす前に変数名と値を展開して文字列として取得するにはこういうことすればいいなとわかりました。

```js
const varNameValues = (args) => {
  const result = [];
  for (const [key, value] of Object.entries(args)) {
    result.push(`${key}:${value}`)
  }
  return result;
}

const a = 10;
console.log(varNameValues({a})); // ["a:10"]

const b = 20;
console.log(varNameValues({a, b})); // ["a:10", "b:20"]
```

これで、変数名と値とを同時に文字列取得し出力することができました。console.logだけじゃなくてログファイルに記載するときや、localStorageに値を保持するときもわかりやすいかもしれません。

mizdra's blog にすごく感謝です。ありがとうございます。

# 追記

varNameValues なんての作らなくても、こっちの方がシンプルでいいかも。逆変換もできるし。

```js
const a = 10;
const b = 20;
console.log(JSON.stringify({a,b})) // {"a":10,"b":20}
```
Sublime Text 3のF7を無効にする(macOS)

# Sublime Text 3のF7キーバインドを無効にする(macOS)

変換時にカタカナにシタイデスがSublime Text 3のデフォルトのキーバインドとかぶっておりカタカナにできない。

デフォルトの設定を消す必要があるが、Keybindのデフォルト設定は見つからない。
そのため、デフォルトのディレクトリとファイルを作成する必要がある。

## やりかた

デフォルトキーマップをコピーして
`$HOME/Library/ApplicationSupport/Sublime Text 3/Packages/Default`ディレクトリに
`Default (OSX).sublime-keymap`として保存する。
(ディレクトリ名、ファイル名にスペースが入るので注意。)

一度デフォルトファイルを作成すると`Key Binds`設定から編集保存できるようになるので、`F7`で探してその行を削除して保存すればOK。

###  メモ

- デフォルトのキーマップ:
  - メニューから`Sublime Text` > `Preferences` > `Key Binds`でキーバインド設定を開いて左のタブに表示される内容。

---
Left side of mutating operator isn't mutable: 'self' is immutable


以下のようなクイズの問題と答え、何問目かを示すquestionNumberを関数で変化させようとしたら
Left side of mutating operator isn't mutable: 'self' is immutable
というエラーが発生した。


    import Foundation

    struct QuizBrain {
        let quiz = [
            Question(q: "1 + 2 = 3", a: "True"),
        ]
    
        var questionNumber = 0
    }

        func nextQuestion() {
            if questionNumber + 1 < quiz.count {
                questionNumber += 1
            } else {
                questionNumber = 0
            }
        }
    }

funcの前にmutatingを書くことでエラーは回避された。
どうやら構造体内の関数ではquestionNumberは不変のため変更できないようだ。
CloudFront Functions を使ってみた

CloudFront Functions が公開されました。同じ用途としては既に Lambda@Edge がありますが、Lambda を使わずに CloudFront 組み込みで超軽量な実行環境になっているようです。

![概要](https://hirose-public.s3-ap-northeast-1.amazonaws.com/qiita/2021/05/04/d057d50f-73bb-43a5-936e-e636f1d68696.png)

参考)

- [Introducing CloudFront Functions – Run Your Code at the Edge with Low Latency at Any Scale](https://aws.amazon.com/blogs/aws/introducing-cloudfront-functions-run-your-code-at-the-edge-with-low-latency-at-any-scale/)

## 特徴

既存の Lambda@Edge に比べ主に以下の特徴があります。なかなか制限がキツイので、用途としてはパスやヘッダの変換、リダイレクトといったちょっとした用途になるかと思います。

- JavaScript (ECMAScript 5.1 互換) ... Node.js の記述は使えない。
- Viewer Request/Response のみ ... Origin Request/Response は不可
- 実行時間は 1ms まで
- 使用可能メモリは 2 MB
- パッケージサイズは 10 KB まで
- ネットワークアクセス、ファイルシステムは使用不可
- リクエストボディの参照は不可

料金は 100 万リクエストあたり 0.1 USD と、Lambda@Edge の約 1/6 以下。
参考) [Amazon CloudFront Pricing](https://aws.amazon.com/cloudfront/pricing/)

ただしキャッシュの有無に関わらず実行される Viewer Request/Response より Origin Request/Response でやったほうが呼び出し回数を減らせる場合もあるので、うまく使い分けていきましょう。
参考) [CloudFront FunctionsはLambda@Edgeより安い。それ本当？！](https://dev.classmethod.jp/articles/sometimes-cf2-price-is-higher-than-lae/)

## 手順

Lambda ではないので、CloudFront の管理コンソール内で作成します。

 1. 管理コンソール > CloudFront > Functions

 1. 「Create function」で関数名を入力して作成。

 1. 「Build」タブで、コードを入力して「Save」。ECMAScript 5.1 互換のため新しい記述は使えないので注意。

    例) Vue.js でアセット以外を /index.html にルーティングする場合。

    ```js
    function handler(event) {
        var request = event.request;
        if (!request.uri.match(/\.(css|gif|html|ico|img|jpg|js|json|png|svg|txt)$/)) {
            request.uri = '/index.html';
        }
        return request;
    }
    ```

 1. 「Test」タブで、テスト。
    Stage に「Development」を選択すれば編集中のコードを、「Live」を選択すればデプロイ済みのコードを実行することができる。

 1. 「Publish」タブで、「Publish」をおこない、編集中のコードをデプロイする。(コードを更新した場合も同様)

 1. 「Associate」タブで、割り当て先の CloudFront ディストリビューション、Event type および Behavior を選択して「Add association」。(指定した Event type に既存の Lambda@Edge/CloudFront Function が割り当てられている場合は上書きされるので注意。同じ Event type に割り当てられる関数は Lambda@Edge/CloudFront Function のいずれかひとつだけ。)

これで、選択したディストリビューションの「Edge Function Associations」設定に、作成した関数が割り当てられました。

![Behavior](https://hirose-public.s3-ap-northeast-1.amazonaws.com/qiita/2021/05/04/ed515aa7-0873-49bc-bfa8-89f8406e0064.png)

更新時も Functions で「Publish」をおこなうだけで、Lambda@Edge のように時間がかかることもなく、すぐに反映されるようです。Lambda@Edge はデバッグやデプロイに辛みがありましたが、制限内で実行できるちょっとした処理であればこちらを使っていくのが良さそうです。
CloudFormationでVPCを作成する

# 概要
CloudFormationを使ってみたかったので、試しにVPCを作成してみます。

# 作成するもの
- VPC
- サブネット

### テンプレート
```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: >-
  CloudFormationでVPC, subnetを作成します
Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 172.16.1.0/24
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: VPC-name
  subnet1a:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      VpcId: 
        Ref: VPC
      CidrBlock: 172.16.1.0/26
      Tags:
        - Key: Name
          Value: subnet-1a
  subnet1c:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: "ap-northeast-1c"
      VpcId: 
        Ref: VPC
      CidrBlock: 172.16.1.64/26
      Tags:
        - Key: Name
          Value: subnet-1c
```

# 雑感
NATゲートウェイやルートテーブルも設定したいですね。
セキュリティグループは用途次第なので、作るリソースに合わせて作成ですかね。
たとえば、RDSならDBのポートを開けるとか。

# 資料
テンプレートを作る際のリファレンスはこちらです。
日本語だと情報がうまく出ないので英語を指定します。
https://docs.aws.amazon.com/en_us/AWSCloudFormation/latest/UserGuide/template-reference.html
Twitter カードの画像（OGP)を PHP で動的に変更する

## やりたいこと

自分の[ホームページ](http://safetyinternet001.ddns.net/)を [Twitter](https://twitter.com/home) で宣伝したい。
そのときに Twitter カードという形式で表示したい。
また、表示する画像を幾つか用意して、同じサイトでも違う画像で表示したい。

## どうすれば良いのか？

まず、Twitter カードの設定が必要。
下記の meta タグを`<head></head>`のなかに入れます。

```Html
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@safetyinternetz" />
<meta property="og:url" content="http://safetyinternet001.ddns.net/" />
<meta property="og:title" content="安全にインターネットを楽しもう" />
<meta property="og:description" content="美少女の画像、動画を安全に楽しむ方法をお伝えします。" />
<meta property="og:image" content="http://safetyinternet001.ddns.net/images/card_images/001.jpg" />
```

一つ目が、大きなカードで表示。
二つ目が、自分の Twitter アカウント
三つ目が、ホームページのアドレス。
四つ目が、タイトル。
五つ目が、HPの要約。
六つ目が、Twitter にアドレスを貼ったときに表示される画像。この画像部分を動的に変更したい。
ちなみに画像のパスは、相対パスではなく絶対パスで記述する必要があります。ご注意を。

この情報が入ったホームページを作成し、[Card validator](https://cards-dev.twitter.com/validator)というサイトで登録してみましょう。URL を入れて、`Preview card`を押すと、URL を貼ったときに、どのような画像が表示されるかがわかります。

で、画像が 1 つだけの場合はこれで良いんですけど、複数の画像をひとつのサイトにつけたいときに少々問題があるわけです。

もともと svelte でつくったサイトで、svelte で動的に変えてもダメでした。
仕方なく php で変更することに……。

## PHP で何をすれば良いのか？

OGP は、同じ URL ではひとつの画像しか生成されません。
よって異なる URL として認識させた上で、その URL に応じて画像を設定できればいいわけです。

つまり、`http://safetyinternet001.ddns.net/?id=001`
このときに 001 の画像を表示し、`http://safetyinternet001.ddns.net/?id=002`
このときに 002 の画像を表示すればいいわけです。
冒頭に下記のようなコードを入れてみましょう。

```PHP
<?php
if(!$_GET){
	$id = '001';
} else {
$id = $_GET['id'];
}
?>
```

PHP には詳しくないので動くだけのソースですが、GET で ID のパラメータがなければ自動的に 001 を設定、もしパラメータがあれば`$id`という変数に 002 とか 003 の数値が入るわけです。

さらに、さきほどの head 部分を少し変えてみましょう。

```PHP
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@safetyinternetz" />
<meta property="og:url" content="http://safetyinternet001.ddns.net/" />
<meta property="og:title" content="安全にインターネットを楽しもう" />
<meta property="og:description" content="美少女の画像、動画を安全に楽しむ方法をお伝えします。" />
<meta property="og:image" content="http://safetyinternet001.ddns.net/images/card_images/<?php echo "$id"?>.jpg" />

```

まあ画像のアドレスを id という変数にしただけです。
これで、さきほどの[Card validator](https://cards-dev.twitter.com/validator)で`http://safetyinternet001.ddns.net/?id=201`などを入れてみたら、201 の画像が表示されます。
あとは何かしらで`http://safetyinternet001.ddns.net/?id=001～240`とか、自分の用意した画像の分だけアドレスを作成し、BOT に突っ込めば URL を投稿したときに自動的に異なる画像が表示されるようになります。

僕が使っている BOT サービスは[Bot Bird](https://botbird.net/)です。
`id=001`とかの部分は、好きなようにつくっていいと思います。
僕は無骨に node.js で書いてみました。

```JavaScript
const R = require("ramda");
const fs = require("fs");
const rangeArray = R.range(1, 243);
console.log(rangeArray);

const zeroPaddedArray = rangeArray.map((item) => item.toString().padStart(3, "0"));
const write = (item) => {
  fs.appendFileSync(
    "./out.text",
    `http://safetyinternet001.ddns.net/?id=${item}` + "\n",
    (err) => {
      if (err) throw err;
      console.log("text追記");
    }
  );
};
zeroPaddedArray.map((item) => write(item));

```

普通に画像の個数（今回は 243 個）分の配列を作成し、`padStart`でゼロ埋めをし、テキストファイルに書き出すだけです。
ここで 243 個と画像が決まっていれば、php のほうで 243 以上の数字、あとは他の文字列だったら 001 にするとか、そういう処理を入れてもいいかも。

そんな感じで、1 時間に 1 回、違う画像で自分のホームページを Twitter で宣伝できるようになりました。
Cloud Foundry（IBM Cloud）で環境変数を使うメモ


set-envなどを使うというだけですがメモ

> [set-env - Cloud Foundry CLI Reference Guide](https://cli.cloudfoundry.org/ja-JP/v6/set-env.html)

基本的に調べて出てくる`cfコマンド`の一つ前に`ibmcloud`を追加して読み替えればOKです。

## 調べて出てくるcfをibmcloudに読み換え

たとえば

```bash
$ cf set-env APP_NAME ENV_VAR_NAME ENV_VAR_VALUE
```

で環境変数にセット出来ると[ドキュメント](https://cli.cloudfoundry.org/ja-JP/v6/set-env.html)に書いてありますが、ibmcloudだと以下のようになります。

```bash
$ ibmcloud cf set-env APP_NAME ENV_VAR_NAME ENV_VAR_VALUE
```

## 環境変数の操作

### 環境変数のセット

ということでセットは以下のような書き方です。

```bash
$ ibmcloud cf set-env MyAPP LINE_ACCESS_TOKEN xxxxxxxxxxxxxxx
```

### 環境変数の確認

```bash
$ ibmcloud cf env MyAPP
```

### 環境変数の削除

```bash
$ ibmcloud cf unset-env MyAPP LINE_ACCESS_TOKEN
```

> 参考: https://cli.cloudfoundry.org/ja-JP/v6/unset-env.html

### 編集は......?

この辺りを見ても記載がないのでedit的なものはないかもしれません。削除して新規追加することを推奨してるのかも。

> https://cli.cloudfoundry.org/en-US/v7/
【AWS】プレイスメントグループとは

#プログラミング勉強日記
2021年5月4日


#プレイスメントグループとは
　プレイスメントグループは、AZ内のインスタンスを論理的にグループしたもの。プレイスメントグループを使用することで、ネットワークパフォーマンスの向上につながる。

　プレイスメントグループのAWS公式ドキュメントでは以下のように説明されている。

> 新しい EC2 インスタンスを起動する場合、EC2 サービスは、相関性のエラーを最小限に抑えるために、すべてのインスタンスが基盤となるハードウェアに分散されるようにインスタンスを配置します。プレイスメントグループを使用することで、ワークロードのニーズに対応するために独立したインスタンスのグループのプレイスメントに影響を与えることができます。ワークロードのタイプに応じて、以下のいずれかのプレイスメント戦略によりプレイスメントグループを作成できます。
引用：https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/placement-groups.html


#プレイスメントグループ戦略

##クラスター
　単一AZでインスタンスを論理的にグループ化する。複数のAZにまたがることはできない。EC2間のインスタンス間における通信の遅延時間を短くする、処理できるデータ量を増やすために利用される。

##パーティション
　論理的なパーティションに分離されているインスタンスのグループ。複数のAZに分散させることができる。グループのAZごとに、最大7つの実行中のインスタンスを持つことができ、重要なアプリケーションといった同時障害のリスクが軽減される。

##スプレッド
　それぞれコトンるハードウェアに設置されるインスタンスのグループ。複数のAZにまたがることができる。少数のEC2が互いに分離して保持される必要があるアプリケーションに最適。


#参考文献
[プレイスメントグループ](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/placement-groups.html)
EC2でDockerを使っているとき、no space left on deviceとでたときの改善方法

自作アプリに新たなgemをインストールして、ec2で
docker-compose buildをしたとき、
no space left on deviceでた。

## 解決方法
まず、どのファイルが容量をくっているのかみました。

```
[myuser@ip-172-31-2-37 goal_tree]$ find . -xdev -type f | cut -d "/" -f 2 | sort | uniq -c | sort -n
      1 .browserslistrc
      1 .dockerignore
      1 .env
      1 .gitattributes
      1 .gitignore
      1 .ruby-version
      1 .vscode
      1 Dockerfile
      1 Gemfile
      1 Gemfile.lock
      1 README.md
      1 Rakefile
      1 babel.config.js
      1 config.ru
      1 docker-compose.yml
      1 dump.sql
      1 entrypoint.sh
      1 package-lock.json
      1 package.json
      1 postcss.config.js
      1 storage
      1 vendor
      1 yarn.lock
      1 クラス図.md
      1 ポートフォリオ コンセプトの整理.md
      1 機能設計.md
      2 containers
      2 lib
      3 log
      8 bin
     18 db
     27 test
     37 config
     59 public
     87 app
    303 .git
  10375 tmp
  16182 node_modules
```

node_modulesがダントツで多い。

現段階では、.dockerignoreにnode_modulesを入れていなかったので、
buildするときに、node_modulesもbuildするようになっていたから、容量くっているのでは?という仮説を立てました。

### .dockerignoreとは
https://docs.docker.com/engine/reference/builder/#dockerignore-file


>Before the docker CLI sends the context to the docker daemon, it looks for a file named .dockerignore in the root directory of the context. If this file exists, the CLI modifies the context to exclude files and directories that match patterns in it. This helps to avoid unnecessarily sending large or sensitive files and directories to the daemon and potentially adding them to images using ADD or COPY.


イメージをbuildするときに、.dockerignoreに書いてあるものは除外してくれる。
メリットとしては、大きなファイルや機密性の高いファイルをデーモンに送信したり、イメージを追加することがなくなる。

今回の場合、node_modulesのように大きいファイルとかをデーモンに送信しなくてよくなるので、イメージの容量が減るかなと。

ですが、書きすぎると逆にbuildに時間がかかることもあるみたいです。

参考:

https://qiita.com/munisystem/items/b0f08b28e8cc26132212


### .dockerignoreにnode_modulesをかいてみる

```ruby:.dockerignore
tmp/*
log/*
.git
containers
## ここを追記
node_modules
```

無事エラーが出ず、buildできるようになりました。
機械が言うと角が立たない2

# 背景
[前回](https://qiita.com/goichiya/items/8c09ded1bbd4e7cc80c6#%E8%83%8C%E6%99%AF)からの続きです

# 何をする？
この後色々難儀なことが出てくると思いつつ、まずは[前回](https://qiita.com/goichiya/items/8c09ded1bbd4e7cc80c6#%E4%BD%95%E3%82%92%E3%81%99%E3%82%8B)の設定を目指す

# どうやって作ろう
同じく[前回](https://qiita.com/goichiya/items/8c09ded1bbd4e7cc80c6#%E3%81%A9%E3%81%86%E3%82%84%E3%81%A3%E3%81%A6%E4%BD%9C%E3%82%8D%E3%81%86)確認した内容をもとにもう少し具体化
- マイコンボード上にカメラ、音声出力、ネットワーク機能を搭載
- Lobeで作成したモデルの実行環境を構築

大まかな処理は以下のイメージ

1. カメラで定期的に写真を撮る
1. 写真の中から顔を切り切り出す(Azure Detection)
1. マスクをしているか判定（Lobe)
    1. マスクをしている場合は称賛のコメント発声
    1. マスクをしていない場合は前回判定時の顔を同一であるか判定(Azure 顔検証)
        1. 同じ人である場合はマスク着用を強く強くお勧め
        1. 違う人であればマスク着用を強くお勧め
1. 前回保存画像を削除し、今回撮影画像を保存
1. 繰り返し

# まずは処理部分を開発する
## lobeからtensorflow liteで出力
ボタンを押すだけ。
難しいところを優しくGUIで包んでくれて、外の世界にもオープンマインド。
すごい世界になったものだ、、
![tensorflow_lite_export.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328600/28f0a675-b772-f8a3-21cf-d5a229513e05.jpeg)

## ローカルで一式開発する
サンプルはpython3.6が前提。venv環境作る前提でチュートリアルも出力されているので、この環境上で作って確認出来たら丸ごとマイコンボードに持ってゆく。持ってゆくと色々あるとは思うものの、、
![projet_folder.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328600/4125a284-0afc-bad0-ed90-8fd4065bb66f.jpeg)

windows上でreadme.mdのままではできなかったこと
- requeiremens.txtを使用してのインストールが不可だったので個別にインストール
　(TF_liteのランタイムはOS,Pythonのバージョンを確認して実行する必要があった）
3.6環境を作るのを横着して3.7で実行（Win10は3.8のTFLiteランタイムがない）

```
(tflite-venv) example> py -3.7 tflite_example.py "mask.png"
Predicted: {'predictions': [{'label': 'Mask', 'confidence': 0.9022133350372314}, {'label': 'UnMask', 'confidence': 0.09778668731451035}]} 

(tflite-venv) example> py -3.7 tflite_example.py "unmask.png"
Predicted: {'predictions': [{'label': 'UnMask', 'confidence': 0.9968219995498657}, {'label': 'Mask', 'confidence': 0.003178034909069538}]}
```

稼働を確認、これを中心に周辺の処理を構築してゆく
コードが汚いとかログがないとかエラー制御がないとか全部後回し
正常系を確認できたら早々にマイコンボードに入れて遊ぶのを優先。

## 全体の流れを制御する部分
```python:control.py
import extract_face
import takepic
import judge_mask
import speak_judge
import speak_out
import datetime

dt_now = datetime.datetime.now()
file_name = dt_now.strftime('%Y%m%d%M%S%f')

#1　写真を撮る
ret = takepic.take_pic()
#2　顔画像を切り出し
ret = extract_face.fetch_face_and_info()
#3　マスク判定（lobeで作成したものを呼び出せるようにする）
ret, ret_info = judge_mask.judge_mask_ctrl()
process_control = False
judge_m = ''
if ret is False:
    process_control = False
else:
    judge_m = ret_info['predictions'][0]['label']
    process_control = True
#4　Mask,UnMaskと前回の顔との類似度を見て判定
ret = speak_judge.speak_judge(process_control, judge_m)
#4 判定内容に合わせてファイルを再生
speak_out.speak_out_message(ret)

```

頑張ってそれぞれ作ってゆく

# 参考

[lobe](https://lobe.ai/)
[azure Detection 全般](https://azure.microsoft.com/ja-jp/services/cognitive-services/face/)
[azure Detection クイックスタート](https://docs.microsoft.com/ja-jp/azure/cognitive-services/face/quickstarts/client-libraries?tabs=visual-studio&pivots=programming-language-python)
[tensoflow lite 全般](https://www.tensorflow.org/lite?hl=ja)
[tensoflow lite ランタイム](https://www.tensorflow.org/lite/guide/python#install_just_the_tensorflow_lite_interpreter)