OmniAICreator/Qiita-1.07M huggingface dataset:
MCD(Mel-cepstrum distortion)を求める

# DTW版作成しました．
- 2021/8/16 dtwで音声の長さが異なっても対応を取るプログラムを作りました．
- [**MCD(Mel-cepstrum distortion)を求める(音の長さが異なる版)**](https://qiita.com/fleming_tone/items/0c3f1b46c9eb5346eda7)

# MCD（Mel-cepstrum distortion）とは

- 声質変換系の評価軸としてよく使われるやつ
- [cyclegan-vc2](https://arxiv.org/pdf/1904.04631.pdf)では変換後の評価に使われている
- MSD(modulation spectra distance)もあるが，簡単に求めるツールを知らんので誰か教えて！！
- 式は以下の通り[参考リンク](https://dsp.stackexchange.com/questions/56391/mel-cepstral-distortion)

```math
\frac{10\sqrt{2}}{\ln10}\frac{1}{T}\sum_t\sqrt{\sum^{25}_i 2||mc(t,i)-mc_{synth}(t,i)||^2}
```
- mel-cepstrumに変換その後，差分の二乗を行いルート取るって感じ

# どんなツール使うの
- [nnmnkwii](https://r9y9.github.io/nnmnkwii/latest/)です！
- 声質変換を触った人は一回は見たことあるツール
- [**nnmnkwii.metrics.melcd**](https://r9y9.github.io/nnmnkwii/v0.0.16/references/generated/nnmnkwii.metrics.melcd.html)で求められる！！（神！！）
- 入力としてmel-cepstrumを求めるので**pyworld**で変換！！
- 以下コード

```python
# -*- coding: utf-8 -*-
import os
import subprocess
import sys
import glob
import librosa
import numpy as np
from nnmnkwii.metrics import melcd
import pyworld

args=sys.argv
if len(args) != 3:
    print("python3 mcd.py [input wavfile1] [input wavfile2]")
    sys.exit()

else:
    sr = 16000
    wav1, _ = librosa.load(sys.argv[1], sr=sr, mono=True)
    wav2, _ = librosa.load(sys.argv[2], sr=sr, mono=True)
    
    wav1 = wav1.astype(np.float64)
    f0_1, timeaxis_1 = pyworld.harvest(wav1, sr, frame_period=5.0, f0_floor=71.0, f0_ceil=800.0)
    sp1 = pyworld.cheaptrick(wav1, f0_1, timeaxis_1, sr)    
    wav2 = wav2.astype(np.float64)
    f0_2, timeaxis_2 = pyworld.harvest(wav2, sr, frame_period=5.0, f0_floor=71.0, f0_ceil=800.0)
    sp2 = pyworld.cheaptrick(wav2, f0_2, timeaxis_2, sr)
    # mel-cepstrum
    coded_sp_1 = pyworld.code_spectral_envelope(sp1, sr, 24)
    coded_sp_2 = pyworld.code_spectral_envelope(sp2, sr, 24)

    result = melcd(coded_sp_1,coded_sp_2 , lengths=None)

    print(result)
```
- 以上！！（厚切りジェンソン風（古っる））
GitHub リモートリポジトリ【基礎】

#【GitHub リモートリポジトリ】

山浦清透さん いつもありがとうございます。
[Git：もう怖くないGit！チーム開発で必要なGitを完全マスター](https://www.udemy.com/course/unscared_git/)

##リモートリポジトリ

リモートリポジトリとは、オンライン上にあるリポジトリ（GitHub）
これからの知識は、実際の開発現場でも必須。

##リモートリポジトリを新規追加

リモートリポジトリを新規追加する。
　→　git remote add origin < GitHubのURL >　

　※originというショートカットにGitHubのURLのリポジトリを登録している。

##リモートリポジトリへ送信

ローカルリポジトリからリモートリポジトリにアップする。
　→　git push < リモートリポジトリ名> < ブランチ名 >　

　※リモートリポジトリ名を毎回入力するのは面倒だから、originを使う。

##リモートリポジトリを表示

設定しているリモートリポジトリの情報を表示する。
　→　git remote -v （-vを付けると対応URLを表示）

##リモートリポジトリを新規追加

リモートリポジトリは複数登録可能

tutorialというショートカットでURLのリモートリポジトリを登録する。
　→　git remote add < リモート名> < リモートURL >　

##リモートリポジトリから情報取得

リモートリポジトリからローカルリポジトリに情報を取得する。
（ワークツリーに反映されないで、リモートブランチに保存される。）
　→　git fetch < リモート名 >

リモートリポジトリからローカルリポジトリに情報を取得し、マージする。
　→　git pull < リモート名 > < ブランチ名 >　（git pullのみでも可）

　※プルは、いま自分がいるブランチにプルしてきたブランチの内容がマージされる。
　仮に別のブランチにいた場合、誤ったマージをしてしまうことになる。

##リモートリポジトリの詳細情報を表示

fetch、pushのURLやリモートブランチ、pullやpushの挙動を表示する。
　→　git remote show < リモート名 >

##リモートリポジトリの変更と削除

リモート名を変更する。
　→　git remote rename < 旧リモート名 > < 新リモート名 >

リモート名を削除する。
　→　git remote rm < リモート名 >
"foo" <> x = "foobar" (Elixir)

# はじめに
- [Elixir](https://elixir-lang.org/)楽しんでいますか:bangbang::bangbang::bangbang:
- [<>/2](https://hexdocs.pm/elixir/Kernel.html#%3C%3E/2)のおもしろい使い方をご紹介します
    - いつかそのうち使う機会があるだろうと個人的におもっています
- 2021/02/15(月)に開催した[autoracex #10](https://autoracex.connpass.com/event/203963/)という[Elixir](https://elixir-lang.org/)の純粋なもくもく会での成果です

# "foo" <> x = "foobar"

```elixir
iex> "foo" <> x = "foobar"
"foobar"

iex> x
"bar"
```

- [<>/2](https://hexdocs.pm/elixir/Kernel.html#%3C%3E/2)は上のような使い方ができます
    - 上の例は公式の[Examples](https://hexdocs.pm/elixir/Kernel.html#%3C%3E/2-examples)を拝借しました
- 私は[Elixir実践ガイド](https://book.impress.co.jp/books/1120101021)という本:book:で知りました

```elixir
iex> "foo" <> "bar" = "foobar"
"foobar"

iex> "f" <> "o" <> "o" <> "bar" = "foobar"
"foobar
```
- あまり意味は無いかもしれませんが:point_up::point_up_tone1::point_up_tone2::point_up_tone3::point_up_tone4::point_up_tone5:こういう使いかたもできます
- ちなみに[<>/2](https://hexdocs.pm/elixir/Kernel.html#%3C%3E/2)の左側は、_literal binary_である必要があります
- 要は次のように左側に変数をもってきてマッチさせようとしても動かなくて、[CompileError](https://hexdocs.pm/elixir/CompileError.html)となってしまいます

```elixir
iex> x <> "bar" = "foobar"
** (ArgumentError) the left argument of <> operator inside a match should always be a literal binary because its size can't be verified. Got: x
    (elixir 1.11.3) lib/kernel.ex:1857: Kernel.invalid_concat_left_argument_error/1
    (elixir 1.11.3) lib/kernel.ex:1829: Kernel.wrap_concatenation/3
    (elixir 1.11.3) lib/kernel.ex:1808: Kernel.extract_concatenations/2
    (elixir 1.11.3) expanding macro: Kernel.<>/2
    iex:10: (file)
```

# Wrapping Up :lgtm::lgtm::lgtm::lgtm::lgtm:
- [Pattern matching](https://elixir-lang.org/getting-started/pattern-matching.html)、奥が深いですね
- Enjoy [Elixir](https://elixir-lang.org/) :rocket::rocket::rocket:
JavaScriptでストップウォッチを実装する

#やりたいこと
久しくJavaScriptを触っていないため思い出すために、
簡単なJavaScriptで以下の様な、**STARTボタンを押下後にストップウォッチを起動させ、ストップボタンで止めることをする。**
![screencast 2021-02-15 23-01-28.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203874/b63c3b57-0fdf-1c9a-7f24-61886692f2f3.gif)

**コードは以下の通り**
複雑ではないのでHTMLに直接記載

````
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
    <link rel="stylesheet" href="./style.css">

    <title>TIMER</title>
</head>
<body>
    <div class="container">
        <p id="timer">00:00:00</p>

        <div>
            <button id="start_stop" class="btn btn-lg btn-primary">START</button>
        </div>
    </div>

    <script>
        var start;
        var timer_id;
        document.getElementById('start_stop').addEventListener('click', function(){
            if (this.innerHTML === 'START') {
                start = new Date();
    
　　　　　　　　　 // 一定時間ごとに特定の処理を繰り返す(10ミリ秒)
                timer_id = setInterval(goTimer, 10);
    
                // STOPボタンにする
                this.innerHTML = 'STOP'
                this.classList.remove('btn-primary');
                this.classList.add('btn-danger');
            } else {
                clearInterval(timer_id);

                this.innerHTML = 'START'
                this.classList.remove('btn-danger');
                this.classList.add('btn-primary');
            }
        })

        var addZero = function(value) {
            if (value < 10) {
                value = '0' + value;
            }
            return value;
        }

        var goTimer = function() {
            var now = new Date();

　　　　　　　// 現在の時間をSTARTした時間から引いて経過時間を計算
            var milli = now.getTime() - start.getTime();
            var seconds = Math.floor(milli / 1000);
            var minutes = Math.floor(seconds / 60);
            var hours = Math.floor(minutes / 60);

            seconds = seconds - minutes * 60;
            minutes = minutes - hours * 60;

　　　　　　　// innerHTMLの要素を書き換える
            document.getElementById('timer').innerHTML = addZero(hours) + ':' + addZero(minutes) + ':' + addZero(seconds);
        }
    </script>
</body>
</html>
````
【初心者でもわかる】選択中の入力フォームに装飾を入れる

# どうも7noteです。選択中の入力フォームにCSSを当てる方法

現在選択されているフォームに装飾をいれます。

使うのはこちら↓

**`:focus`**

擬似クラス`:focus`を使えばCSSで装飾を入れることができます。

![sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/e0b76f92-cdeb-732a-0e54-dd70a3227e87.gif)

**↓↓ちょっとゲームチックにすることも可能！！↓↓**
![game.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/c6715007-5bcb-799d-d156-682c4aa14a38.png)


## 使い方

```index.html
<form>
  <input type="text"><br>
  <input type="text"><br>
  <input type="text">
</form>
```

```style.css
input:focus {
  background: #fcc;
}
```

## まとめ

装飾をがんばればゲーム画面のような装飾も可能！
オリジナルの入力フォームを作ってみてください。

```style.css
form {
  background: radial-gradient(circle farthest-side, #1F6C85, #0A3C5A, #07334F); /* 
円形グラデーション */
  padding: 20px;
}
	
input {
  width: 100%;
  color: #fff;
  background: none;
  border: none;
  caret-color: transparent;   /* デフォルトの点滅カーソルを非表示 */
}
	
input:focus {
  outline: none;
  background: linear-gradient(to top, #1D81C4, transparent);
}
```

![sample2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/28b97350-5b10-667c-e59d-732a8915d262.gif)

（カーソル、指にしておけばよかった・・・）

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
AWS EC2 T4g インスタンスのLAMP向け調査

# AWS EC2 T4g インスタンス
最近（といっても去年ですが）追加になった、armアーキテクチャのEC2ファミリーです。
価格が安いらしいので、実験 or 自分用サーバに利用できないか調査してみます。

# 調査の目的
armアーキテクチャと聞いているので、使いたいパッケージが対応しているのか把握しておきたい。

# 主な利用用途
LAMP(Linux/Apache/MySQL/PHP)環境＋postfix・dovcotあたりを入れたい。

# 環境
取り合えず、EC2 T4g.nanoをAmazonLinuxで起動。(いつもの通り、SpotInstanceで起動)

# 調査状況
## OS周り
### uname
aarch64 の表記があります。

```
$ uname -a
Linux ip-172-30-3-195.ap-northeast-1.compute.internal 4.14.214-160.339.amzn2.aarch64 #1 SMP Sun Jan 10 05:53:19 UTC 2021 aarch64 aarch64 aarch64 GNU/Linux
```

### python

```
$ python -V
Python 2.7.18
```

## パッケージ

### デフォルト

apacheは yum install httpd にて最新のものが入りました。

```
 httpd                            aarch64              2.4.46-1.amzn2                     amzn2-core              1.3 M
```

### amazon-linux-extras

lampパッケージとして、MariaDB 10.2 + PHP7.2 があったのでこれを使う。
(他にもPHP7.3 , PHP8も利用可能な模様)

Pythonはこちらに3.8がありました。

```
$ sudo amazon-linux-extras list
 13  lamp-mariadb10.2-php7.2  available    \
        [ =10.2.10_7.2.11  =10.2.10_7.2.14  =10.2.10_7.2.16
          =10.2.10_7.2.17  =10.2.10_7.2.19  =10.2.10_7.2.22
          =10.2.10_7.2.23  =10.2.10_7.2.24  =stable ]
 36  python3.8                available    [ =stable ]
```

### その他

ffmpegを入れたかったのですが、yum ではarm用のパッケージの所在が良く分からず、
以下からダウンロードしてきました。
https://www.johnvansickle.com/ffmpeg/
( https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-arm64-static.tar.xz をダウンロード・展開 )

簡単なテストをした範囲では利用できそうでした。

ひとまず、ここまで。
Document領域のファイルを名前変更、削除するメソッドを作る

#名前変更
```swift
public func renameFile(oldPath:String,newPath:String) {
    let dir = FileManager.SearchPathDirectory.documentDirectory
    let mask = FileManager.SearchPathDomainMask.userDomainMask
    let docPath = NSSearchPathForDirectoriesInDomains(dir,mask,true)[0]
    let atPath = "\(docPath)/\(oldPath)"
    let toPath = "\(docPath)/\(newPath)"
    do {
        try FileManager.default.moveItem(atPath:atPath,toPath:toPath)
    }
    catch {
        print("Error")
    }
}
```
#削除
```swift
public func deleteFile(path:String){
    let dir = FileManager.SearchPathDirectory.documentDirectory
    let mask = FileManager.SearchPathDomainMask.userDomainMask
    let docPath = NSSearchPathForDirectoriesInDomains(dir,mask,true)[0]
    let atPath = "\(docPath)/\(path)"
    do {
        try FileManager.default.removeItem(atPath:atPath)
    }
    catch {
        print("Error")
    }
}
```
初学者の私が、より理解が深まって頭がスッキリしたDB知識



DBの種類はたくさんあり、主にRDBが使われています。

ー有名なDBー
リレーショナルデータベース（RDB）
グラフ型データベース
キー・バリューストア型データベース
ドキュメント指向データベース


DBMS（データベースマネジメントシステム）
・利用者とDBとのやりとりを整理してくれるシステムです。

RDBMS（リレーショナルデータベースマネジメントシステム）
・MySQL
・PostgreSQL
・Oracle
などがあります。


普段MySQLを使っているのであれば、それはDB本体ではなく、私たちユーザーとRDBの間に入って、「データを整理してくれているRDBMS」ということです。

　ーーーーー　　　　　　　　　ーーーー　　　　　　　　　　　　　　ーーーーーーー
｜   ユーザー　｜　　→　SQL　｜  RDBMS　 |　＜ー＞   操作・取得　　　｜RDB（テーブル）｜
　ーーーーー　　ビュー　←　　ーーーー　　　　　　　　　　　　　　ーーーーーーー

#３層スキーマ
DBは３層スキーマから成り立ちます。
３層スキーマとは、下記３つのスキーマのことです。
・外部スキーマ（ビュー、ユーザーから見たDB）
・概念スキーマ（テーブル、開発者から見たDB）
・内部スキーマ（データファイル、DBMSから見たDB）
　
それぞれの関係性は以下のようになっています。
　ーーーーーー　　　　　ーーーーーー　　　　　ーーーーーー
｜外部スキーマ｜　ー　｜概念スキーマ｜　ー　｜内部スキーマ｜
　（ビュー）　　　　　　（テーブル）　　　　　　（DB）
　ーーーーーー　　　　　ーーーーーー　　　　　ーーーーーー

・外部スキーマと概念スキーマの関係性　→　テーブルをSQLでビューに持ってくる
・概念スキーマと内部スキーマの関係性　→　データファイルを、見やすいようテーブルにする
・外部スキーマと内部スキーマは直接的な関連を持たない

つまりテーブルは、「ビューとDBの直接的な関係を持たせないための仲介役」とも言えます。
それではなぜ概念スキーマ（テーブル）を用意するかというと
概念スキーマ（テーブル）は、データ独立性を確保するために、「絶対必要」だからです。

---
論理的データ独立性
・外部スキーマを変更しても、内部スキーマに影響がない状態を指します。

物理的データ独立性
・内部スキーマを変更しても、外部スキーマに影響がない状態を指します。

反対に考えると、概念スキーマ（テーブル）を変更すると、全てのスキーマに影響が出てしまいます。   
なので論理設計は非常に重要です。

#論理設計
論理設計（概念スキーマの設計）
・テーブル設計
・データを管理するためのデータモデルの設計

物理設計（内部スキーマの設計）
・DDLによる実装やストレージの構成などの設計


論理設計の４STEP
１,　エンティティの抽出　　　
・どんなデータを管理するエンティティ（テーブル）が必要かを明確化する

２,　エンティティの定義　　　
・エンティティ（テーブル）ごとにどんな属性（カラム）が必要かを明確化する

３,　正規化　　　　　　　　　
・データの冗長性（ムダ・重複）をなくすために、テーブルを分割する

４,　ER図作成　　　　　　　　
・エンティティ（テーブル）間の関係性を可視化して図にする

---
#エンティティとは？
システムにおいて「管理する必要があるデータ」のことです。
RDBにおいてはテーブル名とイコールになります。

エンティティ（Entity）は日本語で「実体」という意味です。
顧客・店舗などの物理的実体と、予約・注文などの概念的実体があります。

---
エンティティの抽出とは？
実現したいシステムで、どんなエンティティを管理する必要があるか？を洗い出すプロセスです。

例：商品購入システム
必要なエンティティ
・商品
・販売者
・購入者
・発送日　など


どんなどんなシステムを実現したいのか？に依存しているので、要件定義と似たようなプロセスです。

---
エンティティの定義とは？
各エンティティがどのような属性（データ）を保持するかを決めるプロセスのことです。
RDBではどんな列（カラム）を持つのかを定義するプロセスです。
必要だと思われるカラムを列挙します。

---
#テーブルとは？
共通点を持ったレコードの集合体
共通点を持っているため、テーブル名は全て複数形で書けています。

構成要素は３つです。
１,　レコード/カラム
２,　キー　　　　　　　　　　
３,　制約

---
#キーとは？
あるデータを引き出すための鍵となるレコードです。
重要なものは「主キー」と「外部キー」があります。

---
#主キーとは？
主キー（プライマリーキー[Primary key]）
・その値を指定すれば、必ず一行のレコードを特定できるカラムの組み合わせのことです。
・テーブルに１つ存在する必要があり、かつ１つしか存在してはいけないという決まりがあります。

例：商品テーブル
商品ID　｜
ーーーー｜
　１　　｜
　２　　｜
　３　　｜

---
#外部キーとは？
外部キー（フォーリンキー[Foreign key]）
２つのテーブル間のカラム同士の関連性を設定するものです。


存在しない販売者ユーザーのデータを商品テーブルに登録してしまうことを防止することができます。
これは、反対に商品テーブルに対して、「制約」を課しているとも言えます。（参照整合性制約）

例：商品テーブル
商品ID　｜　　価格　　　　　　　ユーザーID　　　　←外部キー（ユーザーテーブルに存在
ーーーー｜ーーーーーーーー｜ーーーーーーーーー　　　　　　　　　しない4~を防止できる）
　１　　｜　　100　　　　 ｜　　　 3
　２　　｜　　 500　　　　｜　　　 ２
　３　　｜　　1000　　　　｜　　　１
ーーーーーーーーーーーーーーーーーーーーーーー

例：ユーザーテーブル
ユーザーID　｜　名前
ーーーーーー｜ーーーーーー
　１　　　　｜　田中
　２　　　　｜　加藤
　３　　　　｜　右京


---

#制約とは？
特定の条件を禁止したり、特定の条件のみを許可することができる決まりのことです。

以下のような制約があります。

NOT NULL制約
・NULL値を禁止

CHECK制約
・条件を指定し、条件を満たさないデータを禁止

一意性制約（UNIQUE KEY)
・重複したデータを禁止
・NULLを禁止するわけではない

主キー制約 (PRIMARY KEY)
・一意を保証
・重複とNULLを禁止
・1つのテーブルに1つ

外部キー制約 (FOREIGN KEY) ｜｜ 参照整合性制約
・他のテーブルの列を参照し、その列にないデータを禁止
Amazon EMR とは？

## 勉強前イメージ

DB的なもののイメージではある

## 調査

### Amazon EMR とは

Elastic MapReduce の略で大量のデータを迅速に効率よく処理するためのサービスです。
ビッグデータフレームワーク(Hadoop、Spark)の構築や運用、また分散アプリケーションの実行を行ってくれます

- そもそもHadoopとは？

巨大なデータを処理するため、アプリケーションの実行をハードウェアのクラスター上で行う
オープンソースのソフトウェアフレームワークです。

### EMRの特徴

- 伸縮自在

オンプレのクラスタのような伸縮性の低いインフラとはおこなり、
EMRのコンピューティングとストレージは分離されているため、
スケーリングができます。

- 安全性

EMRではインスタンスへのアクセスは自動的に制御されており、またKMSを使用して暗号化を行うことが可能です
伝送中の暗号化や保管時の暗号化、強力な認証など暗号化オプションも簡単に利用できます

- 信頼性

EMRはクラウド向けに調整されており、パフォーマンスの低いインスタンスは自動的に置き換わります。
それによりクラスター内の可用性が高まり、安定してリリースできるため環境の維持に力を使うことが少なくなります

### 用語の確認

- クラスター

EC2インスタンスの塊のことを指し、クラスター内の各インスタンスはノードと呼ばれます。
ノードはEMR用のデフォルトAMIとカスタムAMIを選べます。

- マスターノード

クラスター内のまとめ役で、ノード間のデータや分散したタスクを管理するノード。
最小構成では、マスターノードだけでも可能

- コアノード

タスクを実行するHDFSにデータを保存するノード

- タスクノード

タスクを実行するだけでデータの保存する機能はないノード

## 勉強後イメージ

hadoopをAWSで動かせるのか・・・
なんとなくイメージはわかったけど、Dynamoとかと何が違うんだろう
次まとめてみよう

## 参考

- [Amazon EMRのチュートリアルをやってみました](https://blog.serverworks.co.jp/amazonemr-tutorial)
- [AWSチーム社内勉強会「EMRおじさんに聞いてみよう」レポート](https://dev.classmethod.jp/articles/cmstudy-amazon-emr/)
- [[初心者] EMRとは何ですか/とりあえずざっとまとめてチュートリアルしてみる](https://dev.classmethod.jp/articles/beginner-what-is-emr-overview/)
- [Amazon EMR](https://aws.amazon.com/jp/emr/?whats-new-cards.sort-by=item.additionalFields.postDateTime&whats-new-cards.sort-order=desc)
そうだ、SQLの勉強をしようⅪ

#はじめに
だんだんSQLの文が長くなってきて、読み解くのに正しく句や文の理解しておくことが大切だと感じる日々です。読み解けると書けるはまた別次元なので、もっと勉強をしないと…

##SQL文をネストする
###ネスト構造
一つのSQL文の中に、別のSQL文を含めている状態をネスト構造といいます。
また、含まれているSQL文を
「副問い合わせ」
「副照会」
「サブクエリ」
と呼びます。

###記述方法
`()`丸括弧でくくって記述します。

```sql
SELECT 〇〇
FROM 〇〇
WHERE (SELECT △△ FROM …)
```

###ポイント
- 記述するときは、一つひとつのSQL文を作ってから組み合わせると考えやすいです。
- 命令文を読むときは、()の中がどんな値になるかを先に読んだ方が、読みやすい。実際に命令が処理される順番も()の中が先です。

###いくつかのパターン
- 単一行副問い合わせ
- 複数行副問い合わせ
- 表副問い合わせ

###単一行副問い合わせとは

検索の結果が1行1列の値となる副問い合わせです。
一つの値を指す場所であれば、どこでも記述可能です。

例えば次のような場面が考えられます。

クラスのテストの結果を分析するような場面で、
数学のテストの点数がクラス全員分入力されているテーブルがあったとして…

|名前|点数|
|---|---|
|青木|92|
|石井|56|
|石田|13|
|：|：|

だれが、何点で最高点を取ったのか調べるとき、

```sql
SELECT 名前, 点数
FROM 数学テスト
WHERE 点数 = (SELECT MAX(点数) FROM 数学テスト)
```
検索結果は、

|名前|点数|
|---|---|
|青木|92|

読み解くと…

1. `(SELECT MAX(点数) FROM 数学テスト)`この部分で、最高点が何点か調べています。
2. 「92」が最高値であることがわかると、そこに代入されます。（正確な処理はわかりませんが、読み解く上で代入と使っています）
3. つまり、3行目は`WHERE 点数 = 92`となります。
4. 全体的なSELECT文を読むと、「数学テストのテーブルから、点数が92と等しい行の名前と点数を検索して」といった感じです。

---

- 複数行副問い合わせ
- 表副問い合わせ

については、次の機会にします。

##最後に
難しくて、理解に時間がかかるようになってきた…
その記述によって、何が呼び出されているか、どんな処理が行われるかを言葉ではもちろん、表や図でイメージできると、理解できているなぁと感じるので、そのレベルまで深めていきたいです。
Google Apps Script の JDBC で timeout が頻発する際の対策

　Google Apps Script(GAS) を Web フロント、データベースに Azure SQL Server を使う案件でのトラブル対策とその経過、対処（仮）を備忘録としてアップします。

# Google Apps Script から Azure SQL Server への接続

　GAS 使うなら、GCP SQL 使えばいいのにと思いつつ、Azure SQL Server を準備。Google からドキュメントが公開されていますので、これを参考に、Azure SQL Server のファイアウォールの設定や、接続テストなどを行いました。

https://developers.google.com/apps-script/guides/jdbc

　この際の設定は、下の画面の通りです。

<img alt="azure SQL Server Firewall" width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177616/a8bcd4e3-3923-06fa-f149-1e899abc0391.png">

　最小TLSバージョンの設定ですが、「>1.2」にしてみたところ繋がらず、「>1.0」にしたところ繋がりました。もしかすると GAS の JDBC の TLS は 1.0 なのかもしれません。

　接続ポリシーですが、VPN 経由で接続しようと思うとプロキシに指定する必要があるようです。速度的にはリダイレクトの方が高速らしいのですが、VPN でDBの操作が必要だったため、プロキシにしています。

# Azure SQL Server のセキュリティ設定

Azure SQL Server に、下の IP アドレスに接続許可の設定を行ます。
IP の範囲が広すぎてびっくりますが、GAS で使うそうです。


```bash:許可するポート
64.18.0.0/20
64.233.160.0/19
66.102.0.0/20
66.249.80.0/20
72.14.192.0/18
74.125.0.0/16
173.194.0.0/16
207.126.144.0/20
209.85.128.0/17
216.239.32.0/19
```

これで設定が完了しました。データベース接続文字列、ユーザ名、パスワードを用いて接続します。

```js:サンプルコード

function test() {
  var r = [];
  try {
    var connectionString = "";//接続文字列
    var dbuser = "";//データベースのユーザ名
    var dbuserPwd = "";//パスワード
    // JDBCでデータベースへのコネクション確立
    var conn = Jdbc.getConnection(connectionString, dbuser, dbuserPwd);
    var stmt = conn.prepareStatement("SELECT * FROM SAMPLETABLE");
    stmt.setString(1, arg.uuid);
    var result = stmt.executeQuery();
    while (result.next()) {
      var s = {};
      s['ID'] = result.getString('ID');
      s['NAME'] = result.getString('NAME');
      r.push(s);
   }
   catch{
   }
   finally{
   }
   return JSON.stringify(r);
}
```

無事、接続できれば成功です。
Gem 'omniauth-google-oauth2'を使って、認証機能を実装する時にエラー！！「The action 'google_oauth2' could not be found for Devise::OmniauthCallbacksController」

こちらの記事に参考にGoogleアカウントでの認証を実装していました。
https://qiita.com/yuki_0920/items/003d8b1c73352378188d


実際の画面でも、RSpecのテストでも下記のエラーに結構苦戦したので、残しておく。

#前提条件
<h3>環境</h3>
Docker
Rails 6.0.3
MySQL
devise
omniauth
omniauth-google-oauth2



#The action 'google_oauth2' could not be found for Devise::OmniauthCallbacksController

![スクリーンショット 2021-02-15 20.56.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/764924/9c2a4a26-1dbc-6ebd-18aa-1ae1948272e9.png)

コントローラーやモデル、ルーティングの設定が終わり、View上に「Sign in with GoogleOauth2」の自動リンクが作成され、いざ認証をテストすると、

このエラー・・・
 Devise::OmniauthCallbacksControllerには「google_oauth2」というアクションは見つからないよ

と返ってきます。

#結論

<h3>routes.rbを確認しよう！！</h3>
今回の実装方法ではDevise::OmniauthCallbacksControllerを継承したUsers::OmniauthCallbacksControllerに「google_oauth2」を定義しているので、

コントローラーへのルーティングがミスっているということは検討はついていた。

どこにも間違いはないのに・・・
はい。間違っていました。

```rb
#間違い
devise_for :users, controller: {
    :registrations => 'users/registrations',
    :sessions => 'users/sessions',
    :omniauth_callbacks => 'users/omniauth_callbacks'
  }

#正解
devise_for :users, controllers: {
    :registrations => 'users/registrations',
    :sessions => 'users/sessions',
    :omniauth_callbacks => 'users/omniauth_callbacks'
  }
```

controllerが単数形になっていたことが原因でした。

#おまけ

エラー解決にあたり、グーグルのクライアントIDやシークレットキーや環境変数の入力間違いでこうなっているのでは？とかも考えました。
実際は違ったわけですが、その場合のエラーも一応残しておきます。


「Sign in with GoogleOauth2」のリンクをクリックした時点で「承認エラー」がでます。

![スクリーンショット 2021-02-15 21.06.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/764924/2e8ff851-b135-3e00-6bec-8e0d51a5d924.png)

もしこの部分が間違っていて、```.envファイル```を修正した場合はdocker-compose up しなおさないとダメです。
Composer1系から2系にアップグレードしたらエラーが起きた

# 何が起きたか
修正依頼が来たLaravelアプリケーションのために環境構築を行っていたところ、見慣れぬエラーが発生しました。

# エラー発生時

dockerでコンテナを立てて、コンテナ内でいざ`composer install`をしたところ良きせぬエラーが。

```bash
$ composer install

Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem x
    - Root composer.json requires xxx/xxx x.x, found xxx/xxx in lock file but not in remote repositories, make sure you avoid updating this package to keep the one from lock file.
```

# 調査
いろいろな記事を参考にさせていただいたところ、まだ各種プラグインが`composer2系`に対応していないとのこと。

### 参考記事
[Composer2.x で変わったこと](https://qiita.com/ucan-lab/items/289009ffe5bb417c808e)
[composer2.xでLaravelが動かなくなったら](https://qiita.com/fagai/items/15232a3f1a5a640d84a7)


# 原因と対処
私のエラー原因は以下のプラグインによるものでした。

* packagist.jp
* hirak/prestissimo

これらは`composer2系`に対応していないためにインストールしようとするとエラーが発生します。
以下のコマンドなどで対処を行うor`composer.json`から削除orそもそもインストールしない等の対処を行いましょう。

```bash:各公式に記載されているコマンド
$ composer config -g --unset repos.packagist
$ composer global remove hirak/prestissimo
```

私の場合はDockerfileにて以下の記述があったため、それを削除して問題解決しました。

```:Dockerfile
...略

RUN composer global require hirak/prestissimo && ¥   <-- 削除
    composer config -g repos.packagist composer https://packagist.jp  <-- 削除
```

# おわり
終わりです。
既出の記事に書いてある内容と殆ど内容が一緒ですが、備忘録として。
T-SQLにおけるOPENJSON-WITH句でException取り扱い

## はじめに
OPENJSON-WITH句でちょっとハマったのでメモ。
jsonファイルを読み取ってその内容をDatabaseに**一行ずつ**INSERTしたい。
異常なデータがあった場合、そのデータのみ失敗させてその他のデータは正常にINSERTする。

## 具体的に
こんな感じのjsonファイルがある。
これをOPENJSON句を使ってT-SQLで扱いたい。

**テーブルの定義はすべてintで定義されてる**ので、2つ目のlengthのデータはINSERT時にoverflowする。
そのため、1つ目と3つ目のデータのみをINSERTするようにする。

```sample.json
{"Size" : [
        {"Number": 1, "Width" : 1000, "Length" : 2000 } ,
        {"Number": 2, "Width" : 2000, "Length" : 3147483647} ,
        {"Number": 3, "Width" : 3000, "Length" : 2000 } 
    ]
}
```

処理のイメージとしては、jsonの中身をループさせて、overflowのExceptionが発生したらCONTINUEして次のJSONを実行してく。
例えばこんな感じ。
(動作確認していないので細かい部分が間違ってたらすいません)

```sql:sample.sql
DECLARE @i int = 1
WHILE @i <= 3
BIGIN
  BEGIN TRY
    INSERT INTO sampletable
    SELECT Number, Width, Length FROM OPENJSON(@json,'$.Size')
    WITH(Number int '$.Number', Width int '$.Width', Length int '$.Length')
    WHERE Number = @i
  END TRY
  BEGIN CATCH
    @i += 1;
    CONTINUE;
  END CATCH
    @i += 1;
END;

```

想像していた処理的には
2番目のデータの時にのみoverflowのExceptionが発生して、TRY-CATCHが行われCONTINUEされて次の文を処理する。

ただ実際の動作としては、すべてのループにおいてExceptionが発生してしまっていた。
どうやら、jsonのの中に一つでもoverflowする値が入っている場合、OPENJSON-WITH句でExceptionが発生してしまうようだ。

##対策
Exception発生させたいのはOPENJSON-WITH句の部分ではなく、INSERTの部分なので
とりあえずjsonの変換はException発生しないよう応急処置

```sql:sample.sql
DECLARE @i int = 1
WHILE @i <= 3
BIGIN
  BEGIN TRY
    INSERT INTO sampletable
    SELECT Number, Width, Length FROM OPENJSON(@json,'$.Size')
    WITH(Number int 'Number', Width bigint '$.Width', Length bigint 'Length') --bigintにする
    WHERE Number = @i
  END TRY
  BEGIN CATCH
    @i += 1;
    CONTINUE;
  END CATCH
    @i += 1;
END;

```

これで想定した動作が行われた。

OPENJSON-WITH句ではWHEREは効かず、いったんjsonファイルをすべて変換している模様(?)
なのでWITH句の中の変換をとりあえず乗り切るためにintじゃなくてbigintに変換するというその場対応。
bigintで変換したとしてもINSERTするときは、結局テーブルの定義がintとしてあるのでException発生する。

##まとめ
とりあえずいったんbigint型を経由することで想定した処理が実現できた。
ただあまり褒められた実装でないし、スマートでないし、納得もいっていない。

素直に、Jsonを一旦ListにDeserializeし、そのListをForeachで回して一行ずつINSERTしていく方が無難なんでしょうか。
WHILEループのたびにOPENJSON-WITHをでjson全体を展開していることも考えると、SQLの外で分解してあげた方が処理としても早いかもしれないですね。
(AzureFunctions内の処理でHTTPRequestbodyでjsonを受け取り、それをDatabaseにINSERTする流れを想定しています)


それともSQLでもっと簡単にできたりするんでしょうか。
もっと効率のいいやり方ご存じの方いましたらコメントお願いします。

## 追記
Json.Netを使ってjsonをListに変換してからforeachで回してINSERTした方が処理が早かったです。
ただJson.NetでDeserializeするときにも大きめの型を用意しないとExceptionが発生するので注意
AWS EC2の利用(公開鍵・秘密鍵の作成、セキュリティグループ作成)

# AWS公開鍵・秘密鍵の作成
EC2は**公開鍵暗号方式**でログイン情報を暗号化する。
EC2では、この公開鍵・秘密鍵を簡単に作成することが可能。

公開鍵暗号方式とは？

**1.　公開鍵を作成する。
2.　送信者は受信者の公開鍵を取得する。
3.　暗号化したい文を送信者が公開鍵を使い暗号化し送信する。
4.　受信者が暗号文を受け取る。
5.　受信者は暗号文を秘密鍵で復号化する。**

![スクリーンショット 2021-02-15 21.23.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/3b8156a8-e255-41fc-d79c-873315106464.png)

###キーペアの作成

**1.　トップ画面からEC2選択
2.　キーペアを作成クリック
3.　名前入力
4.　ファイル形式選択
5.　キーペアを作成
6.　ファイルダウンロード**

![スクリーンショット 2021-02-15 21.33.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/8c8bf20c-a6e6-fb09-b8fa-1a027bcd737c.png)




![スクリーンショット 2021-02-15 21.34.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/be0e88c5-ada5-4e3c-9ba8-3a8b87c43aae.png)

![スクリーンショット 2021-02-15 21.34.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/9ee38e05-e367-298d-8ae0-84cf9cbed837.png)

# セキュリティグループを作成する
*「セキュリティグループにより、IPアドレスやインスタンスごとのアクセス制御を実現できる。」*
**ホワイトリスト方式**のため、**許可のみを設定**できる。

### セキュリティグループの作成
**1.　セキュリティグループ選択
2.　セキュリティグループの作成クリック
3.　項目入力
4.　インバウンドルール入力
5.　アウトバウンドルール入力
6.　作成クリック**
![スクリーンショット 2021-02-15 21.52.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/840d9f5d-5049-e02a-d02d-99544dd73e08.png)

![スクリーンショット 2021-02-15 21.59.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/23818da0-e9ff-c6f7-a93b-3d7d131de7e5.png)
![スクリーンショット 2021-02-15 21.56.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/6484c679-77b3-8a76-cf4c-994b6c5470ed.png)

■**タイプ**
通信の種類選択。SSH、HTTP等を選択できポート番号は自動的に入力される。
特殊な通信の許可はカスタムを選択。

■**プロトコル**
プロトコルとは、コンピューター同士の通信をする際の手順や規格。
TCP、UDP等を設定する。

■**ポート番号**
ポート番号は、TCP/IP通信で、コンピュータが通信に使用するプログラムを識別するための番号。 ポート番号は「0～65535」まである。
ポート番号指定、範囲を指定することもできる。
カスタムを選択した場合、任意の値を指定できる。

■**ソース**
許可する接続元。

■**送信先**
許可する送信先。
【初学者】deviseの論理削除の実装方法

deviseの削除機能を実装しようとしたところ理論削除と物理削除があるとのことでした。

#### 論理削除とは
簡単に言うと「データ自体は残っているけど、扱いとしては削除済みにすること」です。
実際にデータを削除せずに、削除されたと見なすフラッグと呼ばれるカラムを設定することでユーザーには削除されてるかのように振る舞うことができることをさします。
データを復元できるメリットもあります。
これにより登録されたデータは残るので、その後の分析などにも役立ちそうです。

#### 物理削除とは
完全にデータベースから削除することです。
データを復元したり、参照することもできません。

## 実装してみる
1. datetime型のdeleted_atカラムを追加
2. routingのusers/registrations#destroyをオーバーライド
3. registrations controllerのusers/registrations#destroyをオーバーライド
4. 論理削除でユーザーモデルを更新し。認証でユーザーがアクティブかどうかを確認する
5. delete時のカスタムメッセージを追加

###1. datetime型のdeleted_atカラムを追加
以下をターミナルで実行

```ruby
rails g migration AddDeletedAtColumnToUsers deleted_at:datetime
rake db:migrate
```

###2. routingのusers/registrations#destroyをオーバーライド
```ruby
# devise_for :usersの部分を下記のように修正
devise_for :users, controllers: { registrations: 'users/registrations' }
```

###3. registrations controllerのusers/registrations#destroyをオーバーライド
`app/controllers/users/registrations_controller.rb`を作成する。
ここでDevise registrations controllerを継承し、destroyをオーバーライドする。

```ruby
# app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  # DELETE /resource
  def destroy
    resource.soft_delete
    Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
    set_flash_message :notice, :destroyed
    yield resource if block_given?
    redirect_to root_path
  end
end
```

###4. 論理削除でユーザーモデルを更新し。認証でユーザーがアクティブかどうかを確認する
```ruby
# app/models/user.rb  

  # 物理削除の代わりにユーザーの`deleted_at`をタイムスタンプで更新
  def soft_delete  
    update_attribute(:deleted_at, Time.current)  
  end

  # ユーザーのアカウントが有効であることを確認 
  def active_for_authentication?  
    super && !deleted_at  
  end  

  # 削除したユーザーにカスタムメッセージを追加します  
  def inactive_message   
    !deleted_at ? super : :deleted_account  
  end 
```

###5. delete時のカスタムメッセージを追加
```ruby
# config/locales/ja.yml

ja:
  devise:  
    failure:  
      deleted_account: "このアカウントは既に削除されています。" 
```



参考：
[How to: Soft delete a user when user deletes account](https://github.com/heartcombo/devise/wiki/How-to:-Soft-delete-a-user-when-user-deletes-account)
[【翻訳】deviseで論理削除を実装する方法](https://qiita.com/t1gert1ger/items/0b90040085005f0860bf)
[論理削除 (logical delete)](https://wa3.i-3-i.info/word18493.html)
バリデーションの正規表現

#WHY
今日は正規表現で漢字、ひらがな、カタカナでのみ入力するというバリデーションの記述方法などを学んだのでアウトプットしていきます。

-----
結果から言うと

```ruby
VALID_NAME_REGEX =/\A[ぁ-んァ-ン一-龥々]+\z/

with_options presence: true do
validates :last_name, format: { with: VALID_NAME_REGEX, message: 'Full-width characters.' }
validates :first_name, format: { with: VALID_NAME_REGEX, message: 'Full-width characters.' }
end
```
でLGTMもらったのですが、

<br>
最初に提出した時は...

```ruby
with_options presence: true do
validates :last_name, format: { with: /\A[ぁ-んァ-ン一-龥]/, message: 'Full-width characters.' }
validates :first_name, format: { with: /\A[ぁ-んァ-ン一-龥]/, message: 'Full-width characters.' }
end
```
こう書いてしまっていました、、、。
変数の定義は知らなかったということでさておき、正規表現においてはいま改めて見るとめちゃめちゃ恥ずかしい限りです、、、

##正規表現の内容について
自分の書いた正規表現を前にも紹介したサイトで見てみます。
https://regexper.com/
![せいき２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/f3a2d51b-a15e-b9f0-ee46-83aebb53e012.png)

Aは文字列の先頭と言う意味ですね。
そして末尾が指定されてません、これだと末尾に数字をいれても通ってしまいます...
なのでアンカーの「<b>\z</b>」を付け足します。
![せいき３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/4e94c8d7-fe1d-b9ea-852c-e05c19f2594b.png)
これで末尾をつけることができましたが、まだこのままだと中の箱の中は一回しか役割を果たしません、これを繰り返すのに「<b>＋</b>」をつけます。
![せいき１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/bfa5ffb8-4098-81fb-6abd-6f975caa0365.png)
これで文頭から末尾まで適応されます。
ですがこのままだと全国の佐々木さんに謝らなければいけなくなるので「<b>々</b>」という字も足します。
![せいき４.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/1a087bc7-62ea-1e46-acff-d3f1a295cc82.png)
これで佐々木さんが入力できます！

--------
##バリデーションの記述について
これで無事に漢字、ひらがな、カタカナで入力させることができましたが、
バリデーションでは<b>同じ正規表現を複数回記述する場合、変数化してまとめることが推奨される</b>らしいです。
上のwithオプションの表現は全く同じものを２回繰り返しているので変数化します。

```ruby
VALID_NAME_REGEX =/\A[ぁ-んァ-ン一-龥々]+\z/
```
あとはwithオプションにこの変数を使っていけば問題なくバリデーションできます。

-----
正規表現の感覚がまだつかめていないですけど少しずつ学んでいけたらなとおもいます。
syncroomのユーザー数をモデリング

apiから、googleシートに1h毎のデータを取得。

１日の中の変動が特徴的で、感染症のSIRモデルっぽく
season[t]=season[t-1]*ss+s_ys*y[t-1]
とかできないかと思ったけど、ちょっと試してうまく行かなかったのでパス。

普通に
log(y)~normal(trend+season,sigma)
trendは１回微分の確率トレンド
とした。


２月
![スクリーンショット 2021-02-15 22.03.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38159/6c092f14-7f91-abb6-4a3f-b1384524162b.png)


![スクリーンショット 2021-02-15 22.04.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38159/8718ce44-8292-1604-716b-0c6cfbd0e891.png)

やはり、seasonだけでは日内の変化を捉えきれてなく、trendが24h周期をかなり追従してしまうが、⊿trendの分散を小さくする事前分布を使うと季節項がファビョって精度が大幅に悪化してしまう。

また、休日のユーザー数は明らかに多いけど、効果を入れていないのでおかしい部分がある。



目的が大きく見てユーザーが増えてるかや、緊急事態宣言でどう変わったかをみるのであれば、無理にマクロとミクロを同時にやるのではなく、日内の最大値や中央値、傾きなどの代表値を普通の状態空間でモデリングするのが良いのかもしれない。
何を一日の代表値とするのか、SIRのSっぽいのをトレンドにするのかベストなのか、など難しいが・・・・。
[個人開発]エンジニア向けSNSを作ってみた

今回はエンジニア向けSNS「RoZi」というものを作ってみました。
まだβ版ですが公開したのでとりあえず投稿しました。
作った理由や開発環境、つらかったことなどを紹介していきたいと思います。

RoZiのURL↓
https://rozi1.herokuapp.com/

僕のRoZiアカウント（適当につぶやいてます）
https://rozi1.herokuapp.com/yamada

![Rozi-top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480294/2c67417f-7e85-f313-7714-7f7be9f586d6.png)

↑トップページ

##なぜつくったか
qiitaだとあくまで「記事」なのでツイッターのように気軽に気づいたことを投稿しずらいし、逆にツイッターだと140文字という制限があるのでソースコードをツイートしずらいなぁと思ったからです。
RoZiはあくまでSNSなので技術に関する投稿以外もOKです。

## 特別な機能
今まで作ったの作品・サービス投稿機能
技術タグ登録
マークダウン方式（ソースコード色分け機能付き）
GithubアカウントURL設定

## 開発環境
rails6.0.3.4
ruby2.7
postgresql
windows10

```:gemfile
gem 'ridgepole'
gem 'slim-rails'
gem 'html2slim'
gem 'pry-rails'
gem 'redcarpet'
gem 'rouge'
gem 'devise'
gem 'carrierwave'
gem 'rmagick'
gem 'kaminari'
gem 'activeadmin'
gem 'rack-attack'
gem 'rails-i18n'
gem 'devise-i18n'
gem 'devise-i18n-views'

```

こんな感じです。
なぜrails6.1にしなかったかは後で書きます。


## つらかったこと ランキング

###一位　モチベーション低下
これはあるあるだと思いますが僕自身ここまでやるきがなくなったのは初めてです。ひどいときは一日に十分程度しかやらなかった時もありました。本当に開発が楽しいと思えなくなったんですよね。いままではやめられないくらい好きだったのに...。
今現在も正直、完治はしてません。

###二位　rails6.1
rails6.1がリリースされたのでそっちを使おうとしたのですが、ridgepoleとの相性が悪いのかrails db:createが全くできませんでした。
結構頑張ったのですが解決できず初めて古いバージョンのrails6.0で開発しました。早くridgepole治るといいなー

###三位　デザイン
開発中に何度かレイアウトが崩れて同じところのデザインを何度も変更しました。

## まとめ
内容が薄い記事になってしまいした( ;∀;)

これはβ版なので使われる見込みがあるなら改良していこうと思います。
ぜひ使ってください！

RoZiのURL↓
https://rozi1.herokuapp.com/

僕のRoZiアカウント（適当につぶやいてます）
https://rozi1.herokuapp.com/yamada
Unity パーティクルシステムでスピード感を表現するエフェクトを実装する

マリオカートでキノコを使った時に出てくるようなエフェクトを作ります。

完成形はこちら
[![Image from Gyazo](https://i.gyazo.com/e7f1567e80b54e7d76acce7622858d5b.gif)](https://gyazo.com/e7f1567e80b54e7d76acce7622858d5b)
#手順

##パーティクルを作成
GameObject >> Effects >> ParticleSystemを選択
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774410/0a5bdf37-a52b-f9a8-a946-37953fe1a21b.png">
[![Image from Gyazo](https://i.gyazo.com/bc99bdb97ec07e0ae36ee87725057f79.gif)](https://gyazo.com/bc99bdb97ec07e0ae36ee87725057f79)
↑初期状態はこんな感じ。このパーティクルを編集していきます。
##パーティクルの編集
まずは、パーティクルをカメラに向けます。
PositionZとRotationXを変更して調整しましょう。
<img width="400" src="https://i.gyazo.com/86b65cab0d45733a0a193e2b21adddda.png">
パーティクルがカメラを向きました。
[![Image from Gyazo](https://i.gyazo.com/1d5bd685d7312abc82f9834d321ffe50.gif)](https://gyazo.com/1d5bd685d7312abc82f9834d321ffe50)
次にParticleSystemのパラメータを以下のように変更します。

ParticleSystem >> Start Size ==> <b>0.2</b>
Emission >> Rate over Time ==> <b>80</b>
Shape >> Radius ==> <b>5</b>

|パラメーター |内容 |
|---|---|
|Start Size  | 開始時のパーティクルの大きさ |
|Rate over Time|ユニットタイム毎に放出されるパーティクルの数|
|Shape| パーティクル射出円の半径|

<img width="400" src="https://i.gyazo.com/8a7e35ee80db73e24d2a182b019aa493.png">
パーティクルの大きさは小さくなり、数が増え広範囲に広がるようになりました。
[![Image from Gyazo](https://i.gyazo.com/5527898e9fb739ca4d0992400a4c14de.gif)](https://gyazo.com/5527898e9fb739ca4d0992400a4c14de)
次にパラメータを以下のように変更します

ParticleSystem >> StartSpeed ==> <b>50</b>
Shape >> Angle ==> <b>5</b>
Renderer >> RenderMode ==> <b>Streched Billboard</b>
Renderer >> LengthScale ==> <b>15</b>

|パラメーター |内容 |
|---|---|
|StartSpeed  | 各パーティクルの初速 |
|Angle|射出されたパーティクルの広がり幅|
|RenderMode(Streched Billboard)| パーティクルの大きさをカメラに向けたまま変更可能にする|
|Length Scale|パーティクルを速度の方向に引き伸ばす |
<img width="400" src="https://i.gyazo.com/db29a252dedfa28b990358ef9dc1e528.png">
こんな感じで完成です。
[![Image from Gyazo](https://i.gyazo.com/e7f1567e80b54e7d76acce7622858d5b.gif)](https://gyazo.com/e7f1567e80b54e7d76acce7622858d5b)
過ぎ去ったパーティクルを残していても意味がないので、ParticleSystem >> Start Lifetimeは1に設定しても良いと思います。
Start Colorを変更する事で色を付けたりもできます。
複製してそれぞれ色をつけるとこんなエフェクトも作れます。
[![Image from Gyazo](https://i.gyazo.com/928dc297339b0c153eb4af1ad1e78c56.gif)](https://gyazo.com/928dc297339b0c153eb4af1ad1e78c56)

##おまけ
ユニティちゃんのダッシュに合わせてパーティクルを発動
[![Image from Gyazo](https://i.gyazo.com/02a8159b11458c1c93f8bceb646fa930.gif)](https://gyazo.com/02a8159b11458c1c93f8bceb646fa930)
スピード感がありますね！！

なお、スクリプトで操作する場合は以下の通りです。
ゲーム開始時にパーティクルシステムをオフにしたい場合はインスペクター上で
ParticleSystem >> PlayOnAwake　のチェックを外してください。

```C#:Player.cs
[SerializeField] ParticleSystem particleSystem; // パーティクルシステムを取得

particleSystem.Play(); //パーティクルシステムをスタート
particleSystem.Stop(); //ストップ
```
Laravelで指定の言語で翻訳があるかどうかの判定をしたい

# はじめに
こんにちは。ひそかに保持しているビットコインがついに800%を超えました、筆者です :smile: 

Laravelで多言語サイトの構築をしているのですが、指定の言語で翻訳があるかどうかの判定をしたいケースがありました。

先入観にとらわれ地味にうまくいかなかったので記事にしました。
参考にしてくださいませ。

# 前提
## 翻訳ファイル
```php:resources/lang/ja/messages.php
return [
];
```

```php:resources/lang/en/messages.php
return [
    'title' => 'Hello',
];
```

## 設定ファイル
```php:config/app.php
return [
    'fallback_locale' => 'en',
];
```

# 悪い例:sob:
```php
App::setLocale('ja');
$has = \Illuminate\Support\Facades\Lang::has('messages.title');
dump($has); // true

App::setLocale('en');
$has = \Illuminate\Support\Facades\Lang::has('messages.title');
dump($has); // true
```


# 良い例:+1:
```php
App::setLocale('ja');
$has = \Illuminate\Support\Facades\Lang::hasForLocale('messages.title');
dump($has); // false

App::setLocale('en');
$has = \Illuminate\Support\Facades\Lang::hasForLocale('messages.title');
dump($has); // true
```


# 結論
`\Illuminate\Support\Facades\Lang::has`では、設定ファイルに`fallback_locale`を設定している場合、指定の言語で翻訳が無い場合にそちらの値が採用されてしまいます。
そのため、`ja`に翻訳が無くても、enを見に行ってあるので、<font color="red"><b>true</b></font>が返ってしまいます。


`fallback_locale`を無視して翻訳のあるかどうかの判定をする場合は、`\Illuminate\Support\Facades\Lang::hasForLocale`を使ってください！

# おわりに
`has`でも第3引数に`false`渡せば同じですが、引数3つ渡さないといけないので、`hasForLocale`が便利です:+1:
nuxtjs/composition-api の意外な利点と使い方

## はじめに

composition-apiがリリースされて時間が経ちました｡

Nuxt.jsで使う場合はpluginsで
`Vue.use(VueCompositionApi)`
を読み込むやり方が主流だったのではと思います｡

そんな中､ [@nuxtjs/composition-api](https://composition-api.nuxtjs.org/) がリリースされていました｡
@vue/composition-apiと比べてNuxt特有の機能(UseAsync)などをサポートしているのが特色で､@vue/composition-apiをラップしているのでcomposition-apiの機能はもちろんNuxt特有の機能が揃っている｡というものです｡
なのですが個人的には以下の1点のみが気に入ってます｡

```
- Easy access to router, app, store within setup()
```

@vue/composition-apiのPlugin版と比べて何が良いのか見ていきます｡

## なにが違うのか

### route.params.id の取得方法


@vue/composition-apiの場合

```typescript
// index.vue
export default defineComponent({
  setup(_, context) {
    console.log(context.root.$route.params.id)
    return {}
  }
})
```

@nuxtjs/composition-apiの場合

```typescript
// index.vue
import { useContext } from '@nuxtjs/composition-api'

export default defineComponent({
  setup() {
    const { route } = useContext()
    console.log(route.params.id)
    return {}
  }
})
```

ここまでだとちょっと書き方が変わったレベルですね｡

### route.params.id を外部に切り出した関数で使いたい場合

composition-apiの特徴はデータ､処理を分けられることにあります｡
composables, use, などのディレクトリを切ってロジック処理を外に書くのはよくあると思います｡
その切り出した処理の中でroute.params.idを使いたい場合を見てみましょう｡

@vue/composition-apiの場合

```typescript
// useHoge.ts
const useHoge = (context) => {
  console.log(context.root.$route.params.id)
}
export default useHoge

// index.vue
export default defineComponent({
  setup(_, context) {
    useHoge(context)
    return {}
  }
})
```

@nuxtjs/composition-apiの場合

```typescript
// useHoge.ts
import { useContext } from '@nuxtjs/composition-api'
const useHoge = () => {
  const { route } = useContext()
  console.log(route.params.id)
}
export default useHoge

// index.vue
export default defineComponent({
  setup(_, context) {
    useHoge()
    return {}
  }
})
```

はい､利点が見えてきました｡
@vue/composition-api では呼び出し時にcontextを引数として渡す
@nuxtjs/composition-api では呼び出された場所のcontextをuseContextで取得できる

contextをリレーする必要がなくなります｡

## テストしたい

pureJSのテストをしたい場合､useContextで値を取得する処理だとそのままではundefindになります｡

まず､ [jestの設定](https://composition-api.nuxtjs.org/getting-started/setup#testing-with-jest) を行います｡

jest実行時にcontextの値を注入します｡


```typescript

import { shallowMount } from '@vue/test-utils'
import XXX from '../XXX.vue'

test('xxx', () => {
  const wrapper = shallowMount(XXX, {
    mocks: { // 注入
      $route: {
        params: {
          id: 1,
        },
      },
    },
  })
  // ...
})
```

これでjest実行時に

```typescript

const { route } = useContext()
console.log(route.params.id) // 1
```
という処理では注入した `1` が取得､表示できます

## さいごに

@nuxtjs/composition-apiは
@vue/composition-api と同じ機能が使えてNuxt特有の機能も実装されている｡

それに加えて､なにかと使いがちなcontextまわりの取得がスッキリするという利点があるのでこれからは `@nuxtjs/composition-api` を使っていこうと思います｡
むだなプロダクトに時間を費やさないために -デザインスプリントについて


#本記事を書いた理由
私は、デザイナーをやっています。エンジニアの皆さんにもビジネス要件あたりから入ってこれる人になってほしいと感じたのでかきました。しっかりと実りあるサービスを実現させることができれば、自分のポートフォーリオにもなりますし、それこそ会社に対して大きく貢献できることでしょう。

誰かが始めなくてはならない。
一切見返りがなくても、誰も認めてくれなくても。
あなたから始めるのだ。
by Alfred Adler
#誰向けか
・デザイン思考を身につけたい方
・プロダクト開発速度を爆上げさせたい方
・CTO
・プロダクトマネージャー
・CEO
#デザインスプリントとは
プロダクトデザインのための柔軟なフレームワーク。
人々が望んでいるものを作り出す確率を高める効果があり、小さなチームで集中的に作業を行い、その成果からプロダクトやサービスの方針を定めることができます。
デザインスプリントはアジャイルの世界からうまれた手法で、デザイン思考を短期間で回すことが可能です。
ちなみに、この手法を世に広めたのがGVのJake Knappさんです。
#デザインスプリントを行うメリット
大きく言えば、失敗のリスクを減らすことができます。
具体的にいうと
・スピードと効率高める
・集中を高める
・多様性のあるチームでの意思統一を可能にする。
#デザインスプリントが向いている企業の規模
もともとは、極めて動きが早く市場にプロダクトをリリースするまでの時間が何よりも重視されるスタートアップのために開発されたフレームワークですが、大企業でも活用が可能です。加速されたデザインスプリントでの作業は大企業に優位性を与えるとともに、プロダクト開発に関する人や予算よ時間の消費を減らす効果が見込まれます。
#導入は様々な段階で可能
独創的なコンセプトを実世界で検証する目標で可能性を探るプロジェクトの初期段階や既存コンセプトの拡張やプロダクトの新しい利用法を探求する中盤〜にも導入が可能とされています。
#デザインスプリントのフェーズ
![Group 1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369367/083db63d-81b7-518b-01a9-56f479593b21.jpeg)
上記５ステップを五日間で実施するのが理想的とされています。
###理解フェーズ
理解フェーズでは、背景やユーザーインサイトを確認する
###発散フェーズ
何が可能なのか、みんなでアイデアを出し合う
###決定フェーズ
解決策を評価して１つ選ぶ
###プロトタイプフェーズ
最小限の機能で実行可能なコンセプトモックを作る
###テストフェーズ
ユーザーにとって何が効果的なのか観察する
#デザインスプリントの成功の定義
一般的なのが、何がどの程度無くなったのかを測定することです。
例えば、できの悪いプロダクトに費やさなくて済んだ時間やお金がそうです。
ほかには、いままでになかった方向性が思い浮かんだことを成功と言ってもいいかもしれません。Faze1でCEOを務めるMarc Guyさんもデザインスプリントを行い、プロダクトの作成をやめて顧客と対話すべきと言う結論に達し、そのおかげで売上が前年比の約8倍になったという事例があります。
成功の定義は、プロジェクトごとに変わってくるため、それにあった成功を定義してあげてください。
#デザインスプリントに興味が湧いたら
![51BzRq7y+kL._SY498_BO1,204,203,200_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369367/df98c3b2-8e8e-1b9e-b9ac-ac9ae6fe4e8d.jpeg)
[この本](https://www.amazon.co.jp/%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%97%E3%83%AA%E3%83%B3%E3%83%88-%E2%80%95%E3%83%97%E3%83%AD%E3%83%80%E3%82%AF%E3%83%88%E3%82%92%E6%88%90%E5%8A%9F%E3%81%AB%E5%B0%8E%E3%81%8F%E7%9F%AD%E6%9C%9F%E9%9B%86%E4%B8%AD%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-Richard-Banfield/dp/4873117801)まじおすすめなので読んでみてください。
僕も最近デザインスプリントを始めたので多くは語れませんが、デザイン思考万歳です。以上です。
需要あれば、デザインスプリントのフェーズごとにやることを記事にしていきたいと思っています。
macOSのバージョンのニックネームを表示（シェルスクリプト）

こんにちは。
[macOS](https://en.wikipedia.org/wiki/MacOS) のバージョンのニックネームを表示させました[^1]。

[^1]: ```sw_vers```コマンド（print Mac OS X operating system version information）だけではニックネームは表示しません。

```console
$ ./macos_ver.sh 
10.14.6 macOS Mojave
$ ./macos_ver.sh 10.15
10.15 macOS Catalina
```

```macos_ver.sh
#!/bin/sh
ver="$1"
[ -z "$ver" ] && ver=$(sw_vers -productVersion)
printf "%s " "$ver"
case "$ver" in
  14*)    echo "macOS Sonoma";;
  13*)    echo "macOS Ventura";;
  12*)    echo "macOS Monterey";;
  11*)    echo "macOS Big Sur";;
  10.15*) echo "macOS Catalina";;
  10.14*) echo "macOS Mojave";;
  10.13*) echo "macOS High Sierra";;
  10.12*) echo "macOS Sierra";;
  10.11*) echo "OS X El Capitan";;
  10.10*) echo "OS X Yosemite";;
  10.9*)  echo "OS X Mavericks";;
  10.8*)  echo "OS X Mountain Lion";;
  10.7*)  echo "Mac OS X Lion";;
  10.6*)  echo "Mac OS X Snow Leopard";;
  10.5*)  echo "Mac OS X Leopard";;
  10.4*)  echo "Mac OS X Tiger";;
  10.3*)  echo "Mac OS X Panther";;
  10.2*)  echo "Mac OS X Jaguar";;
  10.1*)  echo "Mac OS X Puma";;
  10.0*)  echo "Mac OS X Cheetah";;
  *) echo ;;
esac; 
exit
```
RedHat8でdisplaylinkのUSBアダプタを使用してディスプレイを利用する

環境:
Red Hat Enterprise Linux release 8.3
kernel:5.10.16-1.el8.elrepo.x86_64

以下のサイトより、centos-8-displaylink-1.7.2-1.x86_64.rpm ダウンロードする。
https://github.com/displaylink-rpm/displaylink-rpm/releases

cd <ダウンロードしたディレクトリ>

dnf install ./centos-8-displaylink-1.7.2-1.x86_64.rpm
これにより、依存関係があるパッケージもインストールする。
Amplifyでセキュリティヘッダ（Strict-Transport-Security, X-Frame-Options, X-XSS-Protection, X-Content-Type-Options, Content-Security-Policy）を追加する

Amplifyでセキュリティ対策（カスタムヘッダを追加）した際のメモです。
CloudFrontよりお手軽に設定できます。

## 方法

以下2点のいずれかの方法で設定しましょう。

1. 設定ファイル追加（customHttp.yml）
2. `Amplify Console`

### 1. 設定ファイル追加（customHttp.yml）

レポジトリのルートディレクトリに`customHttp.yml`ファイルを追加し、commit & push します。
`Amplify Console`でのデプロイアクションの後、指定したヘッダが追加されているのが確認できるでしょう。

```yaml:./customHttp.yml
customHeaders:
  - pattern: '**/*'
    headers:
      - key: 'Strict-Transport-Security'
        value: 'max-age=31536000; includeSubDomains'
      - key: 'X-Frame-Options'
        value: 'SAMEORIGIN'
      - key: 'X-XSS-Protection'
        value: '1; mode=block'
      - key: 'X-Content-Type-Options'
        value: 'nosniff'
      - key: 'Content-Security-Policy'
        value: 'default-src self'
```

### 2. `Amplify Console`

`Amplify Console` -> `Custom headers`に移動します。

![スクリーンショット 2021-02-15 13.46.35.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73176/09ae9b24-6b91-b1f0-908a-5317421ce895.jpeg)

上記、yamlと同等の内容を追加して、保存します。

![スクリーンショット 2021-02-15 13.47.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73176/966e18fb-efdb-807a-70ab-dbee611dd071.png)

![スクリーンショット 2021-02-15 13.53.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73176/2ced2bcc-8c73-984d-95bc-63694f400dec.png)

## （参考） CloudFrontの場合

Lambda@Edgeで対応できますが、Amplifyより手間がかかります。

[[CloudFront] Lambda@EdgeでHTTPセキュリティヘッダーを追加する方法](https://dev.classmethod.jp/articles/cloudfront-lambd-edge-http-security-header/)

## 参考サイト
* [（公式ドキュメント） AWS Amplify - Custom headers](https://docs.aws.amazon.com/amplify/latest/userguide/custom-headers.html#migrate-custom-headers)
kali linuxのFirefoxでネットに接続できない

#問題
前回の続き(のようなもの)。いつも通りGoogleでHackTheBoxにアクセスしようとしたらこの有様。
![VirtualBox_Kali_15_02_2021_20_49_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/848369/1b2adb28-971b-7369-d5d6-83f61df4f338.png)

#対策
まず、上のURL入力欄で`about:config`と打つ。
![VirtualBox_Kali_15_02_2021_20_48_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/848369/a69a8f48-2784-4987-e670-02e48e74fdfa.png)

すると次のような画面が出るから、迷いなく`危険性を承知の上で使用する`をクリック。別に全く危険性はないので
怖がる必要はありません。
![VirtualBox_Kali_15_02_2021_20_48_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/848369/de35f46f-dbad-9eb7-160a-8c3fc1993784.png)

進むと、上に検索欄が出てくる。
![VirtualBox_Kali_15_02_2021_20_48_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/848369/625e3787-645a-46fe-aa56-f349a915ff1a.png)

ここに`http2`と入力する。
そうすると、一番下に`network.http.spdy.enabled.http2`が`true`になっているので`false`にする。
これで完了なので、変えた時点ですでに保存されているらしいので閉じて大丈夫です。
![VirtualBox_Kali_15_02_2021_20_49_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/848369/0e58d642-5b9a-5eea-450f-990052d11917.png)

#結果
Googleに繋がりました！！
![VirtualBox_Kali_15_02_2021_21_00_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/848369/565eee0b-62f1-f55a-574c-fef64a897791.png)
研究成果を一瞬で吹き飛ばす魔法のコマンド

こんにちは、美味しいしです。
結論だけ読みたい、という方は[こちら](#まとめ)

## 本当にあった怖い話
最近は卒論発表の時期ですね。

研究成果を一瞬で吹き飛ばす素敵なコマンドとして悪名高いのは

```sh
rm -rf hoge
```

ですよね。
ディレクトリごと全てを抹消できます。
あまりに有名すぎるこのコマンドを誤って使うことは、そんなにないでしょう。(たまに[本番環境でやらかしちゃった人 advent calender](https://qiita.com/advent-calendar/2020/yarakashi-production)などで目にしますが)

では、以下のpythonのコードはどうでしょう？

```python3
import json

nanika = json.load(open("hoge.json","w"))
print(nanika)
```

一見なんの害もない、ただのデータの確認のように思えますよね。
このコードを実行してみましょう。
すると、なぜかエラーがでる。

```
io.UnsupportedOperation: not readable
```

何かtypoでしょうか。
フォルダを確認してみるとと、データがぎっしり詰まっていたはずの`hoge.json`が空になっています。
おかしい.......

なぜこのようなことが起きたのでしょう...?

そう全てこいつが悪いんです。


![SCR 2021-02-12 at 19.23.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545134/5e0531d1-6c2a-0c7c-ccf1-8f0aec4d2370.png)


はい、ということで今回のまとめです。


## まとめ
python3において、

```python3
open(path,"w")
```
は、ファイルの新規作成を意味します。
すでにファイルが存在しても関係ありません。全てまっさら白無垢な状態で上書きです。

データを無に帰さないためにも、file ioを行う際にはくれぐれも注意しましょう。

## 対策

```python3
def json_load(path):
    json.load(open(path,"r"))
def json_dump(obj,path):
    json.dump(open(path,"w"))

def pickle_load(path):
    return pickle.load(open(path,"rb"))
def pickle_dump(obj,path):
    return pickle.dump(obj,open(path,"wb"))
```
あたりを作っておいて、直接ファイルioをしないようにするのも良さそうです。
みなさんも何か対策なさっていたらコメント等で教えてください。
【RealSense】ARマーカーの位置の取得

RealSenseのRGB画像からARマーカーを認識し,対応する深度情報からその位置の3次元情報を取得します。

- install

```
pip3 install pyrealsense2
```

- program

```Python:rsAruco.py

# coding: utf-8
import pyrealsense2 as rs
import numpy as np
import cv2

aruco = cv2.aruco
dictionary = aruco.getPredefinedDictionary(aruco.DICT_4X4_50)

pipeline = rs.pipeline()
config = rs.config()
config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)

print("Start streaming")
pipeline.start(config)

cv2.namedWindow('RealsenseImage', cv2.WINDOW_AUTOSIZE)

while True:

    frames = pipeline.wait_for_frames()
    depth_frame = frames.get_depth_frame()
    color_frame = frames.get_color_frame()

    color_intrinsics = color_frame.profile.as_video_stream_profile().intrinsics

    depth_image = np.asanyarray(depth_frame.get_data())
    color_image = np.asanyarray(color_frame.get_data())

    gray_image = cv2.cvtColor(color_image, cv2.COLOR_RGB2BGR)
    corners, ids, rejectedImgPoints = aruco.detectMarkers(gray_image, dictionary)

    if len(corners)!=0:
        point = np.average(corners[0][0], axis=0)
        depth = depth_frame.get_distance(point[0], point[1])
        point = np.append(point,depth)
        if depth!=0:
            x=point[0]
            y=point[1]
            z=point[2]
            x,y,z=rs.rs2_deproject_pixel_to_point(color_intrinsics, [x, y], z)
            print("point:",x,y,z)
            
    aruco.drawDetectedMarkers(color_image, corners, ids, (0,255,0))

    depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.03), cv2.COLORMAP_JET)
    images = np.hstack((color_image, depth_colormap))

    cv2.imshow("RealsenseImage",images)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

```

下の写真のようにARマーカーの3次元情報が出力されます。
![Screenshot from 2021-02-15 20-52-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/9ac235f3-338d-17d2-6fa8-22c1c4c9f501.png)

###プログラムの解説
ArCuoのライブラリを用いた,Arマーカーの認識は以下の流れで行います。
まず以下のようにarucoのインスタンスを生成します。

```
aruco = cv2.aruco
```

次に```getPredefinedDictionary```関数を用いて```dictionnary```変数に保存します。```aruco.DICT_4x4_50```で50種類のマーカーが生成されます。

```
dictionary = aruco.getPredefinedDictionary(aruco.DICT_4X4_50)
```

あとは```dictionnary```とグレーイメージを入れれば検出してくれます。

```
corners, ids, rejectedImgPoints = aruco.detectMarkers(gray_image, dictionary)
```