OmniAICreator/Qiita-1.07M huggingface dataset:
Jupyter環境でimportができなかった件について (no module...)

Kaggleを初めて、Jupyterで開発しようと思い環境を用意したのですが何故か他ファイルの関数をimportできなかった

# 環境
Vagrantで環境構築

# 問題について
Jupyterでimportをすると

```
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-1-34fd8e2ed2a5> in <module>
----> 1 from test_1 import call

ModuleNotFoundError: No module named 'hello'
```
`hello.ipynb`がないといわれる

# 解決策
`.ipynb`はimportできなかった。対応していないっぽい(?)
`.py`でファイルを作り直したらimportができた

`.py`の作り方はこんな感じで作れます
ここでは`hello.ipynb`を`hello.py`として保存します 
(実行するとhello.pyが同じディレクトリに保存されます)

```
%%writefile hello.py
def test():
    printe("Hello World")
```

# 追記
https://python.atelierkobato.com/py/#outline__1
https://noa-ai.hatenablog.jp/entry/2019/05/15/152141
この方法でも可能でした

# 最後に
新しい環境はわからないことばかりです
MySQLを起動できない。ERROR! The server quit without updating PID file (/usr/local/var/mysql/mbc.local.pid).

MySQLを起動しようとしたら、
エラーになりました。

なかなか、抜け出せずに苦労しました。
ERROR! The server quit without updating PID file (/usr/local/var/mysql/mbc.local.pid).

色々と調べてみましたが、
他のMySQLが干渉しているようでした。

ps ax | grep mysql

こちらで起動中のMySQLを確認し、
 sudo kill -9 #######
邪魔しているプロセスを解放してみました。

すると、起動すると、
Starting MySQL
.... SUCCESS! 

いえーーい！！という感じで無事に終わりました。
受講生のときと卒業後のプログラミングへの考えを振り返ってみて

##はじめに
Qiita初投稿です。あまり文章を書くのは得意ではないですが、どうか温かい目でみて頂けるとありがたいです。この記事では、僕がプログラミングスクール受講生だったときと、卒業して学習を続けている中でのプログラミングに対しての考え方や意識の変化についてざっと振り返りも含め書いていきたいと思います。

##プログラミングを学ぶ上で意識していたこと・していること
**受講生時**
スクール受講生のときは、とにかくコードが書けるようになるということばかりを意識していたなと今振り返ると思います。ここでいうコードが書けるというのは、コーディングだけできて、他のインターネットやwebの仕組みを勉強しないということです。というのも、僕自身コードが書ければ動くものが作れる、動くものが作れれば自分が考えるサービスが作れるといった短調な考えで勉強していたなと少し反省しています。（振り返りって大事ですね。）
**卒業後**
プログラミング自体webやインターネットなどの色々な知識を必要とすることが多いことを知り、雑学ではありますがそれらの勉強もするようになりました。すると、思ったよりプログラミング言語の理解にも役に立ち、現在は言語だけの勉強に特化するのではなくプログラミングの周辺知識にも目を向けるように意識しています。

##学習方法
**受講生時**
僕が人見知りっていうこともあり、基本的に1人でもくもく勉強し、講師やサポータの方に躊躇してあまり質問せずにもったいない時間の過ごし方をしていました。
**卒業後**
講師の方から15分考えてわからなかったら質問するというアドバイスをもらって、質問をするようにしています。その変えようと思ったきっかけとしては、僕よりもできる人達がこんなに周りにいるのだから、その人達から答えだけを聞くのではなく、その考えに至った経緯なども聞いて盗めるのなら聞いた方が絶対得だなと考えたからです。（いや、受講生の時もその考えでしろよって話ですよね。笑）
もちろん、質問する時は相手の時間を奪ってしまうので、なるべく手間を取らせないような質問を心がけるようにしています。

##作りたいもの
**受講生時**
LINEやインスタみたいなものを作ったらすごいんだろうなと、自分の作りたいものというよりは、作ったらすごいと思われそうっていうものを作りたいとあの頃は考えていました。（普通に撃沈。笑）
**卒業後**
自分の周りの物やコトを便利にできるようなシステムを作りたいという考えに変わりました。その理由としては、単純に作っていて楽しそうなのと、僕をラクにしてくれるからです。（これ超大事！）

##おわりに
今回は僕がスクール受講生の時と卒業後のプログラミング学習への意識の変化についてざっと振り返ってみました。まだまだ足りないことだらけのプログラミング初心者ですが、これからもプログラミング学習を頑張っていきたいと思います。
今後の目標としては、より実践的な環境で知識や経験を積んでいきたいので、そうできるように行動していきたいと考えています。
最後まで温かい目で見てくださり本当にありがとうございました。
DataPortal: 新機能さかのぼり（ピボット テーブルのカラースケールの条件付き書式）

DataPortalのまだ知らない使えそうな機能を求めて、新機能の一覧を遡ってみました。

[ピボット テーブルのカラースケールの条件付き書式](https://support.google.com/datastudio/answer/9528890?color-scale-conditional-formatting#color-scale-conditional-formatting)
> ピボット テーブルにカラースケールの条件付き書式を適用できるようになりました。

早速試してみます。

ピボットテーブルを配置し、スタイルから条件付き書式を追加します。
ルールの設定画面が表示されるので、カラースケールを選択します。
![スクリーンショット 2020-12-11 19.07.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/14371c50-3f8f-aa5d-a4f3-b00f5e2b5465.png)

任意の色を選択し、保存します。
値のばらつき具合やヤバさがよりわかりやすくなりそうです。

![スクリーンショット 2020-12-11 19.13.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/fb1e6965-5cc0-1024-1895-cebf1c77bb9a.png)
PSoC5LP＋ESCONでモータを回してみた！

#はじめに
ガチガチの機械系が初めての電子工作に挑戦しました．
多少，言葉のミスがあるかと思いますが，大目に見てください:eyes:
#やること
1.ESCONのチューニング
2.PSoCからduty比をESCONに入力してモータを回転させる
3.モータの回転数をTeraTermに出力する
#使用するもの
＊PSoC5LP PrototypingKit
＊ESCON 50/5
＊モータ(maxon RE40)※エンコーダ付き
＊USB A-MicroB ケーブル
＊USB A(オス)-A(メス)ケーブル
＊配線等
#環境
＊PSoC Creater 4.3
＊ESCON Studio 2.2

#準備
ESCONを使うにあたって，事前準備が必要です．
まず，「ESCON Studio」というコントローラの初期設定ソフトを自分のPCにインストールします．
下記リンクからESCON Studioをインストールします．(2020/12 確認済み)
[https://www.maxongroup.co.jp/maxon/view/content/ESCON-Detailsite](https://www.maxongroup.co.jp/maxon/view/content/ESCON-Detailsite)

また，ESCON Studioの進め方は[ゲッティングスタート](https://maxonjapan.com/wp-content/uploads/manual/escon/ESCON_gettingstart.pdf)を見ながらやるのをお勧めします！！

###～1.ESCONのチューニング～
インストールできたらESCON Studioを開いて，指示に従ってUSBケーブルをPCとESCONを接続します．
その後，ゲッティングスタートを見ながら進めます．
モータのパラメータ，制御方法，入出力端子などの選択をします．
全行程の設定が完了したら，最後に「自動チューニング」を選択し，下記のように接続し，「開始」ボタンを押します．

#接続～チューニング時～
![配線図01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486633/78dbfdb7-aa00-2580-9dbe-2b895f49d695.png)

#接続
![配線図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486633/5ec9c4e1-7292-a99a-1b30-068ad32d02e7.png)


#TopDesign
![スクリーンショット (97).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486633/083b3c76-e3eb-004f-3912-31f260035ab5.png)
#Pins
![スクリーンショット (98).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486633/2868a9c9-6822-ad2e-d76f-b9cb85dfc7ea.png)


#コード
###～2.PSoCからduty比をESCONに入力してモータを回転させる～
for文でPSoCのPWMコンポーネントのduty比を変化させて，加減速させています．

```c
#include "project.h"
#include <stdio.h>

int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
    
    PWM_Start();
    UART_Start();
    ADC_SAR_Start();
    int i;
    int16 count=0;
    char String_count[64]={'\0'};
    
    LED_Write(1);
    Rotation_Write(1);
    Enable_Write(1);
        
    for(;;)
    {
        /* Place your application code here. */
        
        ADC_SAR_StartConvert();
        
        for(i=0;i<200;i++)
        {
            PWM_WriteCompare(i);
            CyDelay(10);
            count=ADC_SAR_GetResult16();
            sprintf(String_count,"%d\r\n",count);
            UART_PutString(String_count);
            if(SW_Read()==0)    
            {
                Stop_Write(1);  /*Switchが押されたら動作停止*/
            }
        }
        for(i=199;i>0;i--)
        {
            PWM_WriteCompare(i);
            CyDelay(10);
            count=ADC_SAR_GetResult16();
            sprintf(String_count,"%d\r\n",count);
            UART_PutString(String_count);
            if(SW_Read()==0)
            {
                Stop_Write(1);  /*Switchが押されたら動作停止*/
            }
        }
    }
}

```
###～3.モータの回転数をTeraTermに出力する～
<img width="400" alt="スクリーンショット (99).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486633/ba38ac59-15dc-357f-44b1-42c29ccd1ebe.png">
` sprintf(String_count,"%d\r\n",count);
 UART_PutString(String_count);`で，TeraTermに出力します．

#最後に
PSoC5LPとESCONを使ってモータを回しました．
AD変換(ADC_SAR)コンポーネントを用いてESCONからのアナログ信号(回転数)をAD変換してUART通信でTeraTermで表示させました．この時にbit数について改めて勉強し直しました(;^_^A
Railsアプリに「いいね機能」を実装

# 背景
オリジナルアプリに実装する機能としてよくあるもの１つが「いいね機能」です。
自分自身で調べて実装したもの復習用になります。初学者のため間違っている部分もあるかと思います。
そのような時は優しく指摘していただけると幸いです。

# 準備
基本的な写真投稿サイトのアプリを「user」と「post」モデルを使用し作成してあります。

# 手順
######　「いいね」を記録するためにlikeモデルを作成
`rails g model like`を実行し、できたマイグレーションファイルにuserとpostを参照するための外部キーreferences型を用いて記述します。

```ruby:app/db/migrate/YYYYMMDDHHMMSS_create_likes.rb
class CreateLikes < ActiveRecord::Migration[6.0]
  def change
    create_table :likes do |t|
      t.references :post, foreign_key: true
      t.references :user, foreign_key: true
      t.timestamps
    end
  end
end
```

データベースに反映させるため`rails db:migrate`を実行します。
likeモデルにバリデーションと各モデルとの紐付けを行います。

```ruby:app/models/like.rb
class Like < ApplicationRecord
  with_options presence: true do
    validates :user
    validates :post
  end
  belongs_to :user
  belongs_to :post
end
```

###### ルーティングの設定

```ruby:config/routes.rb
Rails.application.routes.draw do
＜省略＞
  resources :posts do
    resources :likes, only: [:create, :destroy]
  end
＜省略＞
end
```

###### likesコントローラーを作成
今回は手動でコントローラーを作成し、createとdestroyの２つのアクションを定義します。

```ruby:app/controllerss/likes_controller.rb
class LikesController < ApplicationController
  def create
    @like = Like.new(user_id: current_user.id, post_id: params[:post_id])
    @like.save
    redirect_to("/posts/#{params[:post_id]}")
  end
  def destroy
    @like = Like.find_by(user_id: current_user.id, post_id: params[:post_id])
    @like.destroy
    redirect_to("/posts/#{params[:post_id]}")
  end
end
```

###### ビューファイルに表示
いいねボタンを作成し、既にいいねしたユーザーかどうかによって切り替える記述にします。

```ruby:app/views/posts/show.html.erb
＜省略＞
<% if Like.find_by(user_id: current_user.id, post_id: @post.id) %>
  <%= link_to "いいね済み", post_like_path(@post), method: :delete %>
<% else %>
  <%= link_to "いいね！", post_likes_path(@post), method: :post %>
<% end %>
＜省略＞
```

###### いいね数をカウントする
whereメソッドとcountメソッドを使用し、いいねの数をカウントします。
` @like_count = Like.where(post_id: @post.id).count`
今回はpostsコントローラーのshowアクション内に定義しました。

表示する際にはビューファイルに`<%= @like_count %>`を配置すれば完了です。
【React】"" is assigned a value but never used  no-unused-vars ワーニングが出た時

## "" is assigned a value but never used  no-unused-varsが出た

ワーニングで出てきてこれは一体なんぞ？と言う話でありまして。

翻訳をかけてみた

![スクリーンショット 2020-12-11 19.15.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629679/d919e79a-f7e0-9a45-5157-b65126017873.png)

つまりどう言うことだ...

## 定数を定義するだけしておいてコードの中で使っていなかった

```javascript
const loading = this.state;
```
みたいに定義しておいて、実際使う時に

```javascript
{this.state.loading}
```

みたいに直接stateを見ていました

loadingを使ってワーニングは解消しました。

これからも頻発しそうだから覚えておこう...
Swift Package Manager にパッケージを追加する際に The repository could not be found. Make sure a valid repository exists at the specified location and try again. と表示される時の対応


# 概要

Swift Package Manager にパッケージを追加する際に 
`The repository could not be found. Make sure a valid repository exists at the specified location and try again. ` となる時の対応


# 症状
Swift Package Manager に既に何らかのパッケージが存在するときに、さらにパッケージを追加しようとするとエラーとなる事がある。リポジトリはまごうことなく存在するので、Swift Package Managerのバグかな?

![スクリーンショット 2020-12-11 15.17.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136288/41bd7422-892f-a660-8334-d73707f1c703.png)

# 解決策
次の方法で解決できました

1. SPMキャッシュの削除 
`File -> Swift Packages -> Reset Package Caches`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136288/54481592-64de-8cb4-2440-98d7cb0fa5e7.png)


2. SPMの再構築が始まりますが、ここで構築を止めます (この操作が肝)
`STOPボタン`で止める
![スクリーンショット 2020-12-11 19.16.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136288/860bf938-a982-7c67-b3b5-f13cea980dd2.png)


3. 通常通りパッケージを追加する
PycharmでDocker環境を構築する手順（Django、PostgreSQL）

Docker初心者ですが、今後のため手順をまとめました。お気づきの点ありましたら、ご教示頂けると幸いです。

# プロジェクトディレクトリ直下にdockerディレクトリを作る
![dockerdirectory.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107197/21fb2e3c-d191-4d39-f9f1-7b94aa86f990.png)

# Dockerfileの作成
- Dockerfileをdockerディレクトリに置く

```
FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
```

# docker-compose.ymlの作成
- docker-compose.ymlをdockerディレクトリに置く。

```
version: '3'
services:
  app:
    build: .
    ports:
      - "8000:8000"
    volumes:
      - './:/app/sampleApp'
    working_dir: '/app/sampleApp'
    container_name: sampleApp
    privileged: true
    tty: true
```

# requirements.txtの作成
- requirements.txtをdockerディレクトリに置く
- インストールしたいライブラリ名を記載する

```
Django==3.1.4
psycopg2-binary
```

# PyCharmでの手順
- File>Settings>Add Python InterpreterでAddを押し、Docker Composeを選択
![docker_composeを選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107197/cd3d043a-4e68-b9a6-9194-00a205b59b1e.png)
- Configuration file(s)からプロジェクト内のdocker-compose.ymlを選択
- Serviceが選択できるようになるのでappを選択し、OKボタンをクリック
![Serviceを選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107197/1c9943ff-b41e-3f25-d78d-4a986092d9db.png)
- ライブラリが追加された
![installed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107197/e5cdc42b-b885-b595-489e-47ac76ba270b.png)

【参考】
- [【Django】PyCharmでDjangoのコンテナ(Docker)開発環境をサクっと構築する](https://qiita.com/mth1209/items/82678e1cd59c925846b4)
使ってますか? SSH Config

# 使ってますか? SSH Config
## はじめに
本稿は[「株式会社オープンストリーム "小ネタ" Advent Calendar 2020」](https://qiita.com/advent-calendar/2020/opst-mini)の14日目です。
過去2年ほど14日目を担当してたのでこの日を選んだのですが、特に思い入れはありません。
## 概要
サーバにSSHログインする時にテキストファイルに書いたものをコピペとかしてませんか? テキストファイルではなくそれ用の設定ファイルに特定の書式で記載しておけばsshコマンドがお手軽に利用できるようになります。
最初に基本的な使い方を説明し、その後に私が良く使う小技をご紹介していきます。
## 基本的な使い方
**~/.ssh/config** に必要な情報を記述するだけでsshコマンドが楽になります。
まずは例を見てみましょう。

```:~/.ssh/config
Host serverA
  Hostname 12.34.56.78
  User server-user
  IdentityFile ~/.ssh/id_rsa.pem
```

このファイルがある状態でコマンドラインで

```
$ ssh serverA
```

と打つだけで下記のコマンドと同じことができます。

```
$ ssh -i ~/.ssh/id_rsa.pem server-user@12.34.56.78
```

簡単に解説すると、**Host**でコマンドラインで指定するためのホスト名(エイリアス的なもの)を、**Hostname**にサーバのIPアドレス、Userにユーザ名、**IdentityFile**に秘密鍵ファイルを指定します。
設定可能な項目の完全なリストはmanページ([本家](https://linux.die.net/man/5/ssh_config) / ([日本語版](https://nxmnpg.lemoda.net/ja/5/ssh_config))を参照してください。

### 落とし穴
上記の例のままファイルを作成しても正しく動かないと思います。それはファイルのパーミッションに問題があります。
パーミッションを600にしておきましょう。

```
chmod 600 ~/.ssh/config
```

### オートコンプリート
正しく設定ファイルが配置されるとsshコマンドでアクセス先のオートコンプリートが効くようになります。
Hostを適切に命名することで便利に利用することができます。

## 小技
ここからは私が使っている便利だと思っている小技をご紹介します。
### 踏み台をプロキシする
サーバ環境に直接ログインするのではなく、踏み台を経由することはしばしばあります。踏み台サーバに秘密鍵置いたりしてませんよね?

```:~/.ssh/config
Host bastion-server
  Hostname 11.22.33.44
  User bastion-user
  IdentityFile ~/.ssh/bastion.pem
Host server
  Hostname 10.0.0.1
  User server-user
  IdentityFile ~/.ssh/server.pem
  ProxyCommand ssh -W %h:%p bastion-server
```

踏み台サーバに関しては普通にログインするための記述をします。
その先にあるサーバのHostnameは踏み台サーバから見たローカルIPアドレスを指定し、**ProxyCommand**で踏み台サーバにログインするためのコマンドを記述します。
秘密鍵はどちらもクライアント側に配置します。

### Includeでファイルを分割する
**Include**を使うと設定ファイルを分割することが可能です。

```:~/.ssh/config
Include conf.d/hosts/*
Host serviceA-server1
Host serviceA-server2
Host serviceB-server1
Host serviceB-server2
```

```:~/.ssh/conf.d/hosts/serviceA
Host serviceA-server1
  Hostname 12.34.56.78
  User server-user
  IdentityFile ~/.ssh/serviceA-server.pem
Host serviceA-server2
  Hostname 12.34.56.79
  User server-user
  IdentityFile ~/.ssh/serviceA-server.pem
```

```:~/.ssh/conf.d/hosts/serviceB
Host serviceB-server1
  Hostname 23.45.67.89
  User server-user
  IdentityFile ~/.ssh/serviceB-server.pem
Host serviceB-server2
  Hostname 23.45.67.90
  User server-user
  IdentityFile ~/.ssh/serviceB-server.pem
```

~/.ssh/configにHostのみ記述しているのはオートコンプリートを効かせるようにするためです。
ディレクトリ構成は手元にあっただけなのでこの構成である必要はありません。

### ワイルドカードを活用する
先ほどの例を見ると、UserやIdentityFileの設定値が繰り返されているのが気になります。
ユーザ名や秘密鍵ファイル名が変わることはそうそう無いとは思いますが、サーバが増設される場合を考えると省けるものは省きたいですね。
このような場合はワイルドカードを用いてまとめて記述することができます。

ワイルドカードはHostで使用可能で、アスタリスク(*)は任意の文字列、クエスチョンマーク(?)は任意の1文字を表します。
先ほどのファイルをワイルドカードを用いたものに書き換えてみます。

```:~/.ssh/conf.d/hosts/serviceA
Host serviceA-*
  User server-user
  IdentityFile ~/.ssh/serviceA-server.pem
Host serviceA-server1
  Hostname 12.34.56.78
Host serviceA-server2
  Hostname 12.34.56.79
```

2つのサーバで異なるのはHostnameのみなのでそこは個別に書き、共通のUserとIdentityFileはワイルドカードで記述しています。
例では記載していませんが、ProxyCommandもワイルドカードを用いた設定に記述することもできます。

## まとめ
以上です。皆さんもSSH Configを活用して快適なSSHライフを満喫してください。
Swiftの詳細設計をドキュメントツール「Jazzy」で作成するメモ

２度目でも大概てこずったのでメモ。

まずはJazzyをgemでインストール

```
sudo gem install jazzy
```

バージョン確認↓　入ったバージョンは0.13.5

```
jazzy -v
```

発行した対象のプロジェクトファイルのルートディレクトにて、
最終的には下記コマンドで発行成功（ちなみにこれはxcworkspaceの場合）。

```
jazzy --min-acl private -c  -o docs --author Digital Standard  --author_url https://digital-standard.com/--module testProject --xcodebuild-arguments -workspace,testProject.xcworkspace,-scheme,testProject
```

このコマンドに行き着くまでが時間かかった。
自分にとって最も参考になったのがこちらのページ
[[iOS][Swift] 「Jazzy」を使ってSwiftのソースファイルからドキュメントを生成する](https://dev.classmethod.jp/articles/generate-documentation-using-jazzy/)


だが、このコマンドに行き着くまでもいろいろあって、
書き込み権限が無いと怒られたこともあった。
→　rbenvでrubyを管理するとうまくいった。
詳細は[gem installでpermissionエラーになった時の対応方法](https://qiita.com/nishina555/items/63ebd4a508a09c481150)

大体は上記ページのコマンドをコピペで行けるか、自分の環境の場合、シェルはbashだったのでパスを通す時は.bash_profileをviで開いて
末尾に下記コードを追記する形になった。

```
[[ -d ~/.rbenv  ]] && \
  export PATH=${HOME}/.rbenv/bin:${PATH} && \
  eval "$(rbenv init -)"
```

これでパーミッションエラーは回避した。

で、次がSwiftのバージョン指定も間違えて怒られた。
Xcodeのビルドのバージョン調べてやってたのだが、そうではなく
これは普通にターミナルでSwiftのバージョンを調べて打ち込めばそれで良い。


大体こんなとこか。
もー、この作業ではつまづきたく無いな。
以上、どどん。
Ruby(assert_equal)



# assert\_equal

assert equalとはequalかどうかを確かめる(assert)関数です．assert\_equal(引数，引数)が同じ値かを判定するコードを示します．

```ruby
def assert_equal(expected, result)
  return expected == result
end

p assert_equal(1, 1)
```

expectedとresultが同じ値のためtrueと帰ってきます．


# colorize-出色の継承-

次に出力に色を付けます．trueのときは緑，falseのときは赤で表示させます．

```ruby
require 'colorize'

def assert_equal(expected, result)
  if expected == result
    puts 'true'.green
  else
    puts 'false'.red
  end
end

assert_equal(1, 1)
```

trueのため緑で表示されます．

colorizeというgem libraryがないと怒られた場合は

    > gem install colorize

でinstallしてください．gemというのはrubyのlibraryを管理するシステムです．



------
 - **source** ~/grad_members_20f/members/Kazufumi0823/c4_assert_equal.org
配信・中継で「音質」にこだわりたいとき

Applibot Advent Calender 12日目の記事になります。
前日は @nodarby さんの「勉強会で扱ったGoのエラーハンドリングについての話」という記事でした!

# 1.はじめに
4月よりアプリボットでデザイナーとして業務に携わっています。
大学時代はメディアアートを学んでおり、インスタレーション・空間演出をする中で趣味で音響を学んでいました。
本記事では、直近需要が増えているZoom等のインターネット配信・中継において「音質」にこだわりたい場合に使えるTipsを執筆します。

# 2.なぜ「音」なのか？
「配信って絵の方が重要なんじゃないの？」「音なんか聞こえてればいい」と思われがちですが、
配信を閲覧する側にとって音に不備のある配信はストレスフルであることが多いです。

例えば、何らかの説明会で以下のようなシチュエーションを考えてみます。

○映像は綺麗だけど、音が途切れまくり何を言っているか分からない
○映像はガビガビ(またはそもそも映像がない)だが、音は明瞭に聞こえる

大前提、配信の目的によって絵と音の優先度の比率は大きく左右されますが、同時にどんな状況においても「情報伝達に問題ないレベル」の音質は担保されるべきです。

ライブ配信の需要の高まりからか、映像会社からビデオミキサーやスイッチャーが販売されるようになりましたが、
いずれも「絵」優先で「音」のクオリティはまだまだ底上げできると考えています。

# 3.具体的な手法
音質改善のキーは『音の明瞭度』にあると考えています。
原音を途切れさせずに、芯をもったまま相手に伝達させる具体的な手段として、ここでは松竹梅に分けて説明します。

## 梅コース：今日から手軽に音質改善

梅コースはいずれも特別な機器は不要で、話者の意識一つで改善するので是非お試しください。

- マイクと口元の距離を近づける
- 反響の少ない部屋を選ぶ
- ゆっくりハキハキと話す


## 竹コース：内蔵マイクからレベルアップしたい
竹コースは、内蔵マイク音質を脱却して、さらなる音質向上を目指したい状況にピッタリです。

- ヘッドセットやイヤホンマイクを用いる
- USB接続型の外部マイクを用いる(おすすめ)
- オーディオインターフェースとマイクを用いる

上から下に向かっていくほどコストがかかる分、得られる音質は向上します。
いずれの場合も、「高い機材を使えば音質は勝手に良くなる」という訳ではなく、
梅コースの基本的な意識がベースになります。

使い方を間違うと、「内蔵マイクの方が音質良かったかも...」という状況にもなり得るため
機材の選定は慎重に行うことをおすすすめします。

## 松コース：とにかく音にこだわりたい、複雑なことをした
松コースは、「複数人の話者の声をバランスよく配信に乗せたい」「エコーをかけたい」「ワイヤレスマイクを使いたい」など
ソースが1人の声以外にも存在する場合に向いています。

- 話者にバウンダリーマイクやショットガンマイク等を仕込む
- 話者分の(ピン)マイクを仕込み、オーディオミキサーでミックス、2mixを用いる

話者が複数人いる場合、1つのマイクではどうしても拾いきれない（声が「遠くなる」）結果、
特定の人の声は大きすぎて、別の人の声は小さすぎるという問題が起こります。
これを解消するには、それぞれの話者にマイクを用意する必要があります。
また複数のマイクを配信に乗せるためには、パソコンに入力する前段階で1つの音源としてまとめる必要があります。

オーディオミキサーは複数の音声入力とその音量調整をする機材で、エコー等のエフェクトがついている機種もあります。

# 最後に

Applibot Advent Calendar 2020 12日目の記事でした！
明日は @16cho  さんです！
エラーでspecが通らない「ArgumentError:  '0' is not a valid カラム名」

状況

:カラム名1→str型
:カラム名2→str型
:カラム名3→int型
:カラム名4→int型

newアクションやupdateアクションのspecで
ArgumentError:  '0' is not a valid カラム名の
エラーが起きる


結論

0は有効ではありません、と言われています。
整数(int型)として渡すべき内容が、文字列(str型)として渡されているため
起こっているいるエラーになります。

そのため、渡す値を整数に変換してあげれば解決します。

解決方法

```ruby:controller
def ●●●_create_params
  params.require(:staff).permit(
    :カラム名1, :カラム名2, :カラム名3, :カラム名4
  ).tap do |v|
    v[:カラム名3] = v[:カラム名3].to_i
    v[:カラム名4] = v[:カラム名4].to_i
  end
end

```

updateも同様になります。
slimのlink_toに条件付きでclassを付与したい

個人的にlink_toの書き方で詰まったところがあったので忘れないようメモ

# やりたかったこと
link_to に条件付きでクラスを付与したかった。

```slim:example.slim
.btn
  = link_to example(a),
  class: 'class1 class2 #{'class3' unless user.status?}'do
```

user.statusの値がfalseの場合のみclass3を追加したい。
ただこれだとエラーが出る。散々調べた結果

```slim:example.slim
.btn
  = link_to example(a),
  class: "class1 class2 #{'class3' unless user.status?}" do
```

正しくはこっち。ダブルクオートで囲むべきだったんですね・・・。
何でプログラミング学習しても現場で実践できないんだろう？(序章)

プログラミングには必要な要素が有ると長年大学の時の友達、後輩、会社の後輩を指導して思った、それは「疑似コード」による「コーディング」の練習、そもそもロジック組み立てられないと無理ケーと思う今日この頃、あなたは判りますか！

最初の部分だけ・・・

#１．必要な素養

プログラミングとは「魔法の杖」だが魔法の素養が必要。
・ロジカルシンキング
・ものつくりが好き
・新しい技術的を学ぶ事が好き
・常に自動化出来ないか考える思考

#２．ロジカルシンキング

何故ロジカルシンキングが重要か
プログラマー又はエンジニアは課題を分析し要素(顧客名、住所など)、機能(検索、追加、削除など)に分解し実際のプログラムに落とし込む必要が有ります。
この時にロジカルシンキングが必要に成ります。
次に実例を見てみましょう。

#３．じゃんけんゲームを作る(ロジック構築前調査)

例として「じゃんけんゲーム」考えてみます。
じゃんけん自体は判る思いますのでその他の要素を考えてみます。
①プレーヤーは「グウ」、「チョキ」、「パー」の何れかを選ぶ。
②コンピューターも「グウ」、「チョキ」、「パー」の何れかを選ぶ。
③プレーヤーとコンピューターの選んだ結果で勝敗を判定し夫々の選んだ手と結果を表示する。
④再度①から繰り返し。
⑤終了させると対戦成績と総合結果を表示する。
⑥画面はブラウザに表示する。

以上挙げられた内容(要件と言います、システムエンジニアの担当範囲です。)足りない事項を推測します。
(A)ブラウザに表示する方法
(B)「グウ」、「チョキ」、「パー」をプレーヤーにどうやって選ばせるのか。
(C)「グウ」、「チョキ」、「パー」をコンピューターにどうやって選ばせるのか。
(D)勝敗はどうやって判定させるのか
(E)対戦結果をどうやって記録するのか

それでは上記内容を解決していきます。
(A)ブラウザに表示するための方法を「ブラウザ 表示」でググって調べてみます。
※ググって・・・google検索サイトで検索する事
結果の中に(https://tone.ne.jp/column/howtouse/whatsbrowser-beginner-smartphone/)と言うページが有り「SNSやWebサイトの閲覧」と表記されています。
どうやらブラウザ表示するにはSNSやWebサイトが必要な様です。
「SNS 表示」でググって見ても内容が難しくて良く判りません。
「Webサイト 表示」でググると最初に( https://www.homepage-maker.jp/ 以下参考ページ)と言うページが有り何かの作成の記事のようです、判らない「何」(ホームページ)を「ホームページとは」でググると最初に表示する内容の事の様です。
この参考ページを見ると表示するにはHTMLとCSSと言う知識が必要なのが判ります。

(B)「グウ」、「チョキ」、「パー」を選ぶのに他のWebサイトを見るとボタンが良さそうと思えます。

(C)コンピューターに「グウ」、「チョキ」、「パー」をランダムに選ばせたい(本当はAIで判定するとか考えられますが複雑に成るので辞めます)

「Webサイト ランダム」でググって数サイト目で( https://allabout.co.jp/gm/gc/23805/ )でJavaScriptを使う事が書いてありました。

(D) 勝敗は
	プレーヤーが「グウ」でコンピューター「パー」ならばコンピューター勝利
プレーヤーが「パー」でコンピューター「チョキ」ならばコンピューター勝利
プレーヤーが「チョキ」でコンピューター「グウ」ならばコンピューター勝利
同じなら引き分け
それ以外はプレーヤー勝利

(E)「javascript データ記録」でググって「クライアント側ストレージ」(https://developer.mozilla.org/ja/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage)でWeb Storage APIで記録可能の様です。

(次章に次く)
【Ansible】templateモジュールを使わずに、jinja2のloop.indexが使いたい



### はじめに
<バージョン>
ansible 2.9.1
jinja2 2.11

jinja2ではfor文でループする際に、「現在何ループ目か」を表す変数loop.indexが存在します。
Ansibleではtemplateモジュールによりこの変数を使えるのですが、
このモジュールを使わずにloop.indexを使う方法はあるのかというお話をします。

```jinja:jinja_sample.j2
{% set list_sample = ['a', 'b', 'c'] %}
{% for tmp in list_sample %}
{{ loop.index }}: {{ tmp }}
{% endfor %}
```

```text:出力
1: a
2: b
3: c
```

### Playbookの紹介

[Ansible Documentation](https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html)を見ると、どうやらAnsible2.8からloopの拡張機能としてloop.indexが
使えるようになったようです。その代わり、ansibleとjinja2で変数名が異なります。
　jinja2： loop.index
　Ansible： ansible_loop.index
また、loop_controlの拡張機能を使うことを宣言しないとエラーになるので注意しましょう。

```yaml:loop_test.yml
---
- name: "loop test"
  hosts: localhost
  gather_facts: no
  vars:
    list_sample:
      - a
      - b
      - c
  tasks:
    - name: "debug loop"
      debug:
        msg: >-
          {{ ansible_loop.index }}: {{ item }}
      loop: "{{ list_sample }}"
      loop_control:    # ポイント
        extended: yes
```

### 実行結果
想定通り、ansible_loop.indexに1～3の値が代入されていることが確認できます。

```text:出力
[ec2-user@ip-<ip addr> ansible]$ ansible-playbook loop_test.yml

PLAY [loop test] *******************************************************************************************************

TASK [debug loop] ******************************************************************************************************
ok: [localhost] => (item=a) =>
  msg: '1: a'
ok: [localhost] => (item=b) =>
  msg: '2: b'
ok: [localhost] => (item=c) =>
  msg: '3: c'

PLAY RECAP *************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```




### 参考記事
[Jinja - Jinja Documentation](https://jinja.palletsprojects.com/en/2.11.x/templates/)
[Loops - Ansible Documentation](https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html)
Notionでインラインデータベースの表示件数を設定する

アルプ株式会社でエンジニアをしています、集約のエンティティ@pictinyです。
これは[Notion Advent Calendar 2020](https://qiita.com/advent-calendar/2020/notion) 11日目のエントリです。
10日目は[NotionでデータベースをCSVでエクスポートする](https://qiita.com/pictiny/items/73eb52871eeac22dada4)でした。

# データベース
Notionでは[データベース](https://qiita.com/pictiny/items/dba21dd5d226ac5b6849)を作ることができます。

## インラインデータベース
Notionはデータベースだけでページを作ることもできますし、ページ内にデータベースを作ることもできます。
ページ内にデータベースを作った場合、データベースのページがサブページとして作られます。

サブページに作られたデータベースのことを [インラインデータベース](https://www.notion.so/Intro-to-databases-fd8cd2d212f74c50954c11086d85997e#d042946e53a3455d98424fc347494d2d) といいます。

## インラインデータベースの表示件数を設定する
データベースのデータ数が膨大になってくると、一度に表示されすぎて不便なことがあります。
件数が多いデータベースを[テーブルビューやリストビュー](https://qiita.com/pictiny/items/dba21dd5d226ac5b6849#view)で表示していると、データベースの下部に表示件数の設定が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/ad1d18a3-de7d-ec5a-8b21-598e502c29ec.png)

ページの初回読み込み時にデータベースに表示する件数を設定することができます。
また、 `Load` ボタンを押すと非表示になっていたインラインデータベースのデータを一時的に表示することができます。

# まとめ
公式ドキュメントは[Full page vs. inline databases](https://www.notion.so/guides/full-page-vs-inline-databases)にありますので、そちらもご覧ください。
Salesforce Mobile SDK を使う

## はじめに
[Phone Appli Advent Calendar 2020](https://qiita.com/advent-calendar/2020/pa_engineers) 12日目です。

### 書くこと
- Salesforce Mobile SDKについて
- Salesforce Mobile SDK の導入からログインまで

### 書かないこと
- コードそのものについて

プロジェクトの作り方などはすっ飛ばしてるので、モバイル開発をやったことがある人向けとなります。

## Salesforce Mobile SDK について

Salesforce Mobile SDK（以下、Mobile SDK）とはSalesforceが提供しているモバイル開発向けライブラリです。
[開発者ガイド](https://developer.salesforce.com/docs/atlas.ja-jp.mobile_sdk.meta/mobile_sdk/preface_intro.htm)

>Mobile SDK は、クラウドでのプッシュ通知、地理位置情報、分析、コラボレーションツール、ビジネスロジックなど、幅広いプラットフォームモバイルサービスをサポートしています。これらのサービスにより、モバイルアプリケーションが大幅に強化されるとともに、開発時間が短縮されます。

とあるように、Mobile SDKを使うことによってログイン画面の構築だったり、アクセストークンの管理を全て任せることができるので、開発がめっちゃ楽になります:santa:

## やってみよう

### 環境
- Swift 5
- Xcode 12.2
- iOS 14.0 ~
- CocoaPods 1.9.3

### Mobile SDK のインストール
今回はCocoaPodsを使ってインストールしていきます。

```shell:Podfile

target 'SalesforceMobileSDKSample' do
  use_frameworks!
#　①
source 'https://github.com/forcedotcom/SalesforceMobileSDK-iOS-Specs.git'
source 'https://cdn.cocoapods.org/'
source 'https://github.com/CocoaPods/Specs.git'

#　②
pod 'SalesforceSDKCore'

end
```
① SalesforceMobileSDK-iOS-Specs リポジトリをソースとして追加します。必ず最初にこのエントリをCocoaPods ソースパスより前に配置します。
② 今回はログインが目的なので`SalesforceSDKCore `のみインストールします。

### 設定ファイルを作る
Mobile SDK は`bootconfig`という名前のファイルを設定ファイルとして参照します。

```xml:bootconfig.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>remoteAccessConsumerKey</key>
    <string>①</string>
    <key>oauthRedirectURI</key>
    <string>②</string>
    <key>oauthScopes</key>
    <array>
        <string>web</string>
        <string>api</string>
    </array>
    <key>shouldAuthenticate</key>
    <true/>
</dict>
</plist>

```

① Salesforceアクセスコンシューマキー
② 設定済みのリダイレクトURL 

### ログイン処理
今回はSwiftUIを使用しています。

```swift:SalesforceMobileSDKSampleApp.swift
import SwiftUI
import SalesforceSDKCore
import Combine

@main
struct SalesforceMobileSDKSampleApp: App {
    // ①
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    @StateObject private var loginViewModel = LoginViewModel()
    
    var body: some Scene {
        WindowGroup {
            if loginViewModel.isUser {
                Text("ログインしている")
            } else {
                Text("ログインしていない")
            }
        }
    }
}

class LoginViewModel: ObservableObject {
    
    @Published var isUser: Bool = false
    
    init() {
        // 実際のログイン処理
        AuthHelper.loginIfRequired {
            self.isUser = (UserAccountManager.shared.currentUserAccount != nil)
        }
    }
}

```

① Mobile SDK がAppDelegateを必要としているため使用しています。

### 結果
ここまで実装してアプリを起動すると

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138921/7046d52d-ceca-ed18-0d9d-9fbb6705bc08.png" width="200px"/>

Salesforceが推奨するログイン画面が表示されます。

## 終わりに
ログイン画面の開発をしたことがあるひとであれば、コードの少なさに驚いたのでは無いでしょうか。
２、３行のコードでログイン処理を行えるのはありがたいことです。
他にもMobile SDKには`Mobile Sync`、`Smart Store`などの便利な機能があるので、Salesforce＋モバイル開発で行えることが増えそうな予感がします。

[サンプルコード](https://github.com/forcedotcom/SalesforceMobileSDK-Templates)も公開されているので、興味ある人は実際に触ってみましょう:runner:
PythonからMIDIメッセージを送ってDAWを操作


- MIDI Machine Control (MMC)を使って、Nuendoを外部から操作できる。
- PythonのモジュールでMIDIメッセージを送ることができる

これらを利用して、PythonからNuendoを動かす。
もちろん、Nuendoでなくとも、一般的なDAWであれば、同じことができると思います。

# 0. 環境

- MacOS 10.15.6 Catalina
- Nuendo 10.3


# 1. MIDI Port を開く

### Audio MIDI設定

- **Audio Midi Setup** を開く
- ⌘2 で MIDI Studio を開く

![Screen_Shot_2020-11-09_at_17.39.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548796/3121f8f0-53ae-feb3-6ad3-62d6b27ccf72.png)

- 新規作成

![Screen_Shot_2020-11-09_at_17.41.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548796/fd21c177-cb07-5636-8f5b-9c90a24d1c98.png)

- IAC Driverをダブルクリック
- プロパティタブ
- 機能の、MIDIマシンコントロールをチェック

![_2020-11-09_18.56.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548796/67576cfe-3760-7c27-7abc-597b7c4589fa.png)

- ポートタブ
- デバイスをオンラインにする。
- ポートの名前を決める。
- 適用

![Screen_Shot_2020-11-09_at_17.47.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548796/e6a84be5-2146-8eef-621d-897320ff0ec4.png)


- Audio MIDI設定は立ち上げたまま

# 2. PythonでMIDIを送信する

### Install Modules

```bash
$ pip install mido python-rtmidi
```

Document

[Mido - MIDI Objects for Python - Mido 1.2.9 documentation](https://mido.readthedocs.io/en/latest/)

### Python でMIDI Portを開く

```python
import mido

print(mido.get_output_names())
# ['IAC Driver MMC Port']

port = mido.open_output('IAC Driver MMC Port')
```

### MIDI Messageを送る

- sysex(system exclusive) messageを 16進数のコマンドで送る。

[MIDI Machine Control](https://en.wikipedia.org/wiki/MIDI_Machine_Control)

```python
# Control Play and Stop
# F0 7F <Device-ID> 06 [<Sub-ID#2> [<parameters>]] F7

# Device-ID -> 7F (ALL Devices)
# Sub-ID#2 -> 01 (Stop)

msg_start = mido.Message.from_hex("F0 7F 7F 06 02 F7")
msg_stop = mido.Message.from_hex("F0 7F 7F 06 01 F7")

# Control Locator
# F0 7F <Device-ID> 06 44 06 01 <hr> <mn> <sc> <fr> <ff> F7

# <hr> -> hour
# <mn> -> minute
# <sc> -> second
# <fr> -> frames
# <ff> -> sub-frames (0 basically)

# move Locater to 00:05:00:00
msg_locate = mido.Message.from_hex("F0 7F 7F 06 44 06 01 00 05 00 00 00 F7")

# send messages

port.send(msg_locate)
port.send(msg_start)
port.send(msg_stop)

# close port

port.close()
```

### 関数化してみよう

```python
import mido
import time

def test():
    with mido.open_output('IAC Driver MMC Port') as port:
        port.send(msg_locate)
        port.send(msg_start)
        time.sleep(3)
        port.send(msg_stop)
```

# 3. Nuendoで受け取る

- トランスポート > プロジェクト同期設定... を開く

![_2020-11-09_18.29.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548796/a9efadd5-2e34-53c7-8115-ab36e7a7d765.png)


- ソースのタブ

![_2020-11-09_18.39.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548796/5ef0da1c-f021-58ce-2dcc-cc11bb7033c0.png)

- マシンコントロールのタブ
- マシンコントロール入力をMIDI マシンコントロールに設定
- MMC入力を、さっき作ったポートに設定

![_2020-11-09_18.33.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548796/db25614e-e3b6-599a-63f9-2bda3c12c93c.png)


## 完成!!!!!!!!!!!!!

# 未解決問題

- 稀に、Nuendoの警告で、"24フレームに変更されました、無視しますか？"と聞いてくる。
- とりあえず無視しています。
【Java】replaceAllメソッド(文字列を置換する)

# JavaのreplaceAllメソッド

についてまとめました。

## replaceAllメソッドとは

一言でいうと

「置換した結果の文字列を持った新しいStringインタンスを作り、そのインスタンスへの参照を戻す」ものです。

## 【説明】

replaceAllは、Stringクラスに実装済みのメソッドとして使うことができます。このメソッドは置換した結果の文字列を持った新しいStringインタンスを作り、そのインスタンスへの参照を戻します。

## 【実際に書いてみる】

書き方は以下です。

```
String 変数名 = “文字列”
String 置換後の変数名 = 変数名.replaceAll(“置換したい文字”, ”置換後の文字列”）
```

## サンプルプログラム

おなじみ「Hello World」の「Hello」の部分を置換して出力してみます。

```java
public class Main {

    public static void main(String[] args) {
        String str = "Hello world";
        String afterStr = str.replaceAll("Hello", "こんにちわ");
        System.out.println(afterStr);
    }

}
```

```java
こんにちわ world
```

文字が置換されて出力されました。

## 【まとめ】

replaceAllメソッドは、新しいStringインスタンスをつくり、そのインスタンスへ参照へ戻します。

つまり**引数で渡した参照先のStringインタンスの値が変わることがありません**。

JavaSilver試験でそのの部分を試される可能性があるので、正確に理解しておく。

## 参考文献・記事

- [徹底攻略Java SE 11 Silver問題集[1Z0-815]対応](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5Java-SE-11-Silver%E5%95%8F%E9%A1%8C%E9%9B%86-1Z0-815/dp/4295007625/ref=pd_lpo_14_img_0/356-5238196-1895250?_encoding=UTF8&pd_rd_i=4295007625&pd_rd_r=1c21865b-a9fe-43e8-ac01-46170e44abca&pd_rd_w=9El0Q&pd_rd_wg=hh5Hc&pf_rd_p=4b55d259-ebf0-4306-905a-7762d1b93740&pf_rd_r=72AVH18EM90CKG00CH5W&psc=1&refRID=72AVH18EM90CKG00CH5W)
- [JavaのreplaceAllメソッドと正規表現を使って文字列の一括置換をする方法を現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/28631)
[Rails]特定のviewだけ共有レイアウトを指定する方法

# 特定のビューだけレイアウトを変えたい！！

ポートフォリオを開発してる中で、ログイン画面と新規登録画面には
「ヘッダーやサイドバーを表示したくないな、、」
という場面が出てきたので備忘録的に記事に残して置こうかと思います。
<br/>

###　環境

僕の開発環境はこんな感じです。
<br/>
MacBookPro 13インチ
Ruby on Rails 6.0.3.4
Ruby 2.7.2

##前提

この記事はRailsに於ける共通レイアウト(パーシャル)についての理解が前提で書いていきます。
共通レイアウトのやり方がわからない方は[Railsチュートリアルの第３章](https://railstutorial.jp/chapters/static_pages?version=6.0#cha-static_pages)の内容が該当しますので
のぞいてみるといいかもしれません。





## レイアウトの違いの例



まず普通のレイアウトだとこんな感じ。

![スクリーンショット 2020-12-11 17.55.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769439/b16f086e-7773-9f49-be8f-d03012ac138b.png)


ヘッダーやサイドバーが表示されています。
<br/><br/>
次に特定のレイアウトを変更したい画面はこんな感じ。

![スクリーンショット 2020-12-11 17.58.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769439/d79e8316-53ac-dde2-40d3-b4172866b004.png)


ヘッダーはロゴだけが表示されていて、サイドバーは表示されていません。




## 共通レイアウトを２つ作る


特定のページだけ共通レイアウトを変更したい場合、app/views/layoutsディレクトリ内に
<br/>
・通常の表示の共通レイアウト
・特定のページ用の共通レイアウト
<br/>
この二つを用意する必要があります。
<br/>
今回はこの２つを

・application.html.erb
・login_layout.html.erb
<br/>としたいと思います。
以下にコードを示しておきます。
<br/><br/>

```erb:application.html.erb

<body>
  <%= render 'layouts/header' %>
  <%= render 'shared/flash_message' %>
  <div class="wrapper">
    <div class="left-wrapper">
      <%= render 'layouts/sidebar' %>
    </div>
    <div class="right-wrapper">
      <%= yield %>
    </div>
  </div>
  <%= render 'layouts/hooter' %>
</body>

```
<br/>
通常、なんの指定もしなければビューたちはこのapplecation.html.erbの
yieldのところに含まれて表示されます。
<br/>

```erb:sign_layout.html.erb
<body>
  <div class="header-top">
    <%= link_to((image_tag 'logo.png', class: "logo"), root_path) %>
  </div>
  <%= yield %>
  <footer>
    <p class="footer-label">Created by Sato Yusuke 2020</p>
  </footer>
 </body>
```
<br/>
こちらのsign_layout.html.erbのyieldには通常なんの指定もしなければ
なにも含まれることはなく、この共通レイアウトがブラウザ上に表示されることはありません。

##表示を切り替える

それでは特定のビューだけ表示を切り替えていきます。

表示を変えたいビューのアクションにこう書き込んで読み込む共通レイアウトを指定します。

```ruby:session_controller.rb
class SessionsController < ApplicationController
  def new
    render :layout => 'sign_layout'
  end
end

```
これでデフォルトのapplication.html.erbではなくsign_layout.html.erbを
通してビューを表示することができます。

##renderした場合にも特定のレイアウトを表示するには？

これでsign_layout.html.erbを表示することはできました。
しかし、ログインに失敗して再びログイン画面をrenderして読み込んだ場合、
今度はapplication.html.erbを通して表示されてしまうためこういった
表示になってしまいます。

![スクリーンショット 2020-12-11 18.43.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769439/d9ec32cd-5d29-e52a-46ea-e7b9496d22bb.png)

（開発途中のため未ログインなのにログアウトボタンが表示されていますが、お気になさらず。）

これの状況を解消するにはアクションにこう記述します。

```ruby:session_controller.rb
class SessionsController < ApplicationController
  def new

    render :layout => 'sign_layout'
  end

  def create
    render 'new', :layout => 'sign_layout'
  end

end
```

renderしたいテンプレートの後に読み込むレイアウトを指定してあげることで
狙ったレイアウトに読み込ませることができます。
【小ネタ】Chrome DevToolsで、クリック時のみNodeが描画される要素の確認方法

タイトル通り、Chrome DevToolsで、クリック時のみNodeが描画される要素の確認方法ほか、DevToolsの小ネタを投稿します。

# クリック時のみの描画される例
以下のようなものがそれにあたります。
この場合、Elementsを調べようとしても、inputタグ以外をクリックすると削除されてしまい簡単には確認できません。
https://material-ui.com/components/autocomplete/#combo-box

![スクリーンショット 2020-12-11 17.54.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258256/d6405de4-cbb6-1136-a209-06934a31aa4f.png)

## ブレークポイントの指定
よって、このDOM要素にブレークポイントを指定する必要があります。
ブレークしたい要素をDevToolsにて右クリック後、下記画像の<font color="Red">赤上矢印</font>の**node removal**をクリックしてください。
これは、指定した要素が削除された際にブレークする仕組みを提供してくれます。

![スクリーンショット 2020-12-11 17.56.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258256/391e0369-a00b-a661-ab8a-987531ec7b55.png)


こうすると、この例で出したmaterial-uiの例だと最下部に移動してしまうのですが、きちんと要素の確認ができます！
![スクリーンショット 2020-12-11 17.59.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258256/db6c6975-d826-bead-4e33-e1b48da68d84.png)

# FYI:ホバー時のみの描画される例
これは同僚から教えていただいたのですが、ホバー時のみに描画が変わる場合は、
下記の画像にあるように、**:hov**をクリックした後に<font color="Red">赤下矢印</font>のチェックボックスをチェックしてください。
（ここではリンクテキストのホバー時のものが確認できます）

![スクリーンショット 2020-12-11 18.02.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258256/624e5830-f3a0-bfa4-ffa3-897557583a58.png)
[Oracle Cloud]予約済パブリックIPをコンピュートインスタンスに付与(2020/12/11)

OCIにある「予約済パブリックIPアドレス」を作成し、コンピュートインスタンスに割り当ててみた。

# 予約済パプリックIPの新規作成
1.  OCI Webコンソールから ネットワーキング→IP管理 を選択![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/65187bfa-b2ef-37bd-6960-9b14260adf93.png)

2. 「パプリックIPアドレスの予約」ボタンをクリック![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/503b605d-a0dd-f0c9-91af-8a7a4a1604d7.png)

3. 「予約済パプリックIPアドレス名」を入力し「パプリックIPアドレスの予約」をクリック![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/e4ab9c9d-1bee-1f0b-6aea-e08c007e4c80.png)

4.  予約済パプリックIPアドレスが作成されていることを確認![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/11f4b65f-c922-698a-3720-b25e71ba3170.png)


# コンピュートインスタンスの作成・確認
パプリック・サブネットにインスタンスを作成
インスタンス作成時には予約済パプリックIPアドレスは指定できないため、パブリックIPアドレスを割り当てないでインスタンスを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/efca72b0-81e6-5422-fa27-e696c521371e.png)

# 予約済パプリックIPアドレスを付与
作成したインスタンスの「アタッチされたVNIC」からプライマリ VNIC名をクリックし、アタッチされたVNICの詳細を表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/f21143d7-6e5c-d322-d843-ddac7aa8755e.png)


### VNICに割り当てられたIPアドレスの編集
VNICの詳細から「IPアドレス」を選択し、割り当てられているIPアドレスの「編集」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/b98aedcf-d285-6a43-97b9-58816a59eea6.png)

### 予約済パプリックIPアドレスを付与
「プライベートIPアドレスの編集」ダイアログで
パブリックIPタイプに「予約済パブリックIP」を選択し
利用する「予約済パブリックIP」をプルダウンから選択し「更新」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/f2da21ca-13d6-568d-cf4d-e6ac9538ed66.png)

VNICのIPアドレスには「（予約済）」の表示がつき、予約済パブリックIPが付与されていることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/63418d65-cd8c-471a-1558-0d5970139076.png)

# 予約済パブリックIPアドレスの削除
予約済パブリックIPのリスト（ネットワーキング→IP管理）から削除するパブリックIPのメニューの「終了」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/45ff9b17-8c65-44a3-baf4-e021052965ec.png)

インスタンスに割り当てている予約済パブリックIPを削除するとインスタンスのパブリックIPが「使用不可」(割り当てが解除)となる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/4b587bda-579d-efbf-c0bb-65bb7ce97370.png)

# 予約済パプリックIPアドレスを使用したロード・バランサの作成
ロード・バランサ作成時に「予約済パブリックIPアドレス」の選択が可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/ce502408-f302-972c-d375-7529b561abdb.png)
【初心者向け🔰】ド素人がプログラミングを始める時にやるべきこと、まとめ・流れ

## 概要
本当に初心者の状態で、これからプログラミングを始める人向けのポイントについてまとめておきます。
技術的に何から始めたらいいのか、どういう事をイメージして取り組めばいいのかのまとめです。

## そもそも、プログラミングとは
使われる意味としては、２つある。

1. コンピュータ言語を記述すること。言語記述（コーディング）
2. 言語記述（コーディング）を含めた、プロダクトやサービスを生み出す一連の作業

#### IT サービスを分けると大きく３ジャンル

- Web アプリ（Webブラウザを通して利用するサービス）
- ネイティブアプリ（スマホアプリ、PCにインストールするツールなど）
- 組み込み系（ロボット、IoT、ドローンなど）

## 初心者が短期間で成長できる学習方法

- 学んだ知識を絵で説明する
    - 紙/ホワイトボードを使用して、文字と図形で説明する
    - 小学生が聞いてもわかる説明をゴールにする（小学校５〜６年生）
- 実践形式で学習する
    - 実際に何かを作りながら成長するイメージ（何かすでにあるもののマネでも良い）
    - 言語やフレームワークの公式のチュートリアルとかでもOK
    - [Progate（プロゲート）](https://prog-8.com/)
    - [ドットインストール](https://dotinstall.com/)
    - [Udemy（ユーデミー）](https://www.udemy.com/ja/)（お金を多少かけてもいい人なら）
- 有識者に質問できる環境を確保する
    - 現役のエンジニアと個別に対面で話せる環境を目指す
    - 知恵袋的なサービスでは「質問力」が必要になるが、初心者にはハードル高い

### プログラミング学習のコツ

プログラミングの勉強をする上で意外と重要なポイントは...
**『全てを覚えようとしないこと』**
その理由は👇

- **現役エンジニアでも ネット検索頼り**
  - 医者や弁護士の様に、多くの知識を暗記して仕事しているわけではない
  - 現場では、ネット検索でほとんど解決している
  - 逆に、ネットが使えないと仕事がほとんどできないエンジニアもごまんといる
  - 「検索能力」がエンジニアには重要
- **現役エンジニアにも 不得意領域がある**
  - みんな何でも知ってるわけではない（特に日本は）
  - 役割分担して作業することが多いので、知らない分野もたくさんある
  - 例：「Web画面できるけど、バックエンド書けない」「バックエンドわかるけど画面書けない」「アプリ作れるけどインフラやネットワークあまりわからない」「プロジェクト管理や資料作成はよくやるけどプログラム書けない」
- **後回しで良い知識も たくさんある**
  - 別に知らなくても何も実務で困らない知識もたくさんある
  - 優先度の低い知識は、後回しで良い
  - 例：「HTMLとはハイパーテキスト・マークアップ・ランゲージの略である」「HTMLはプログラミング言語ではない」
- **経験を積んでいく内に 自然と身に付く**
  - 暗記より実践を優先する
  - ネット検索で解決してる内に、自然と覚えていく
  - エラーにぶつかった時が一番の成長チャンス
  - 経験ベースの方が「なぜ？」が身に付く

### 人はなぜ成長できるのか
【成長のメカニズム👇】
**小さな成功体験 ＋ それを支援する環境 ＝「努力感」のない努力**
　➡︎ 結果、成長をもたらす（※ 個人的意見です）

- 小さな成功体験：「学んだ知識を絵で説明する」「実践形式で学習する」が該当する
- それを支援する環境：「有識者に質問できる環境を確保する」が該当する
- 「努力感」のない努力が、ガンガン能力を伸ばし、自然と実績と自信を生み出す
- 数字や行動量だけをあげれば、他人から見たら「努力」。しかし本人は「夢中なだけ」

## おススメのIT学習フロー
まず、パソコン（PC）を購入し、必要なソフトをインストールして「開発環境」を整える。
その後のオススメの流れ。

- ❶ 最初に学習すべきは Web フロントの言語
    - HTML：画面のレイアウトや構造を決める
    - CSS：画面を装飾する、細かいレイアウト調整を行う
    - JavaScript (JS)：画面に動きをつける、通信等の処理を行う
- ❷ 次に、Web フロントでよく使われるライブラリやフレームワーク、エコシステムに触れる
    - jQuery：昔から使われているライブラリ
    - Bootstrap：デザインでよく使われるフレームワーク
    - Angular（もしくは Vue, React）
- ❸ Web バックエンドの言語・フレームワーク、DBに触れる
    - node.js、Nginxの導入
    - TypeScript（もしくは JavaScript）で簡単に書いてみる
    - MySQL を導入してみる
- ❹ クラウドサービスに触ってみる
    - クラウドサービスを契約して、無料枠で Web サービスを公開・運用してみる
- ❺ モバイルアプリの学習へ...

なんだかんだで基礎からやると、未来で差がつきます。

## まとめ
とりあえず、手を動かす。ガンガンいこうぜ！

## 参考

- [プログラミング初心者向け｜初心者にオススメのPCスペック・学習方法（YouTube）](https://www.youtube.com/watch?v=TL7oA_4NkQw)
- [プログラミング初心者向け｜初心者が最初に学習すべき内容（YouTube）](https://www.youtube.com/watch?v=AL9wxNMidCU)
Docker For Macを3.0.0にアップデートしたらec-cube（コンテナ）起動しなくなった


Docker For Mac (Docker Desktop)の最新版3.0.0が20/12/10にリリースされました。
https://docs.docker.com/docker-for-mac/release-notes/

ポップアップのままに最新版インストールしたら、
先程まで元気に稼働していたコンテナが`docker-compose`で起動できなくなりました...涙
現在絶賛開発進行中の状態で、肝を冷やしたので、共有しておきますー！

## 追記（20/12/14）

こちらの記事を投稿してほどなく3.0.1リリースされたとのことで、
アップデート＆インストールしたところ、
`Use gRPC Fuse for file sharing` がONの状態でも
無事コンテナが起動することを確認しました🙌

> https://qiita.com/TeppeiMimachi/items/14c4a411ab56cd5892c7

## エラー内容

```
Cannot start service ec-cube: Mounts denied
ERROR: Encountered errors while bringing up the project.
```

ふぁ？！起動できない....だと。

アップデートしたときに、ファイルアクセスに関する設定変更求められたので、
このへんか？と思ったのですが、チェックついてるしー！何ー！
![スクリーンショット 2020-12-11 17.48.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454968/e900ab58-02eb-d54a-db5e-ceb9528727fc.png)


## 解決方法（先に）

これです！！

⇒その①3.0.0を使う場合

`Docker Preference`（設定） > `Experimental Features` > `Use gRPC Fuse for file sharing` をオフる（デフォルトではONになっています）
![スクリーンショット 2020-12-11 17.58.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454968/bd4bc3e1-6b8a-6dbd-6ee2-04b37f63c87a.png)



=> その②2.5.系にダウングレードする

わたしは①で解決しましたが、無理なかたはダウングレードを...


> 参考ISSUE
> https://github.com/docker/for-mac/issues/5115

Special Thanks...!! 🎉


## 〆

Imageも全部クリーンしました、まあいいんだ、今日中に作業再開できたから、、😇
今回も世界の知見にすくわれました、ありがとう🌏


<small>

- 作業優先でろくにメジャーバージョンアップデートであることを確認しなかったのは私のミスです..
- インストールするタイミングでコンテナSTOPしていなかったのが原因かもしれないです..

</small>

気をつけよう。
Nuxt.jsでIE11対応したときに「strict モードでは、プロパティの複数定義は許可されません。」と怒られる

NuxtのSSGでWebページを作る仕事をしており、
その際IE11対応をする必要がありました。

既にChromeやEdgeなど他のブラウザではちゃんと動いている状態だったのですが
IEでだけ表示が崩れていました。
（まぁよくあることですね）

IEのコンソールを見てみると以下のような状態でした。

![コンソール.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239351/49c4474b-65e1-9629-db4e-b9c6f06bc2ac.png)


**strict モードでは、プロパティの複数定義は許可されません。**とのこと。。。

今回は私のケースではこう解決しましたよという話をします。
**すべてのケースでこれが正しいってわけではないと思います。**

# 結論
- エラーメッセージの通り、同じプロパティを二回設定している可能性があるので、スタックトレースに出力されているコンポーネントをよく見直しましょう。
- strictモードを解除するは最終手段にしよう。
- なぜ他のブラウザでは怒られないのか・・・

# 解決するまでにしたこと

## まずエラーメッセージをググってみる 

とりあえずstrictモードをやめると解決したよ！みたいな情報が多かったので
その方向で色々と検証しました。

- tsconfig.jsonに「"alwaysStrict": false」を設定する
- [babel-plugin-transform-remove-strict-mode](https://github.com/genify/babel-plugin-transform-remove-strict-mode) を使ってみる

私の試したプロジェクトではいずれも上手くいかず、strict modeが解除されなかったです。
（babelやTSへの理解が浅いことも原因かもしれません）

まぁそもそもあまり根本的な解決法ではなさそうなので断念することに。

## スタックトレースを読んでみる

スタックトレースを見てみると概ね以下のような状態でした。
※一部ファイル名等変更してます。

```
stack: "SyntaxError: strict モードでは、プロパティの複数定義は許可されません。
   at ./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/@nuxt/components/dist/loader.js?!./node_modules/vue-loader/lib/index.js?!./components/organisms/layouts/Modal.vue?vue&type=template&id=da284a90&scoped=true& (http://localhost:3000/_nuxt/pages/index.js:1016:1)
   at __webpack_require__ (http://localhost:3000/_nuxt/runtime.js:854:12)
   at fn (http://localhost:3000/_nuxt/runtime.js:151:13)
   at eval code (eval code:2:22)
   at ./components/organisms/layouts/Modal.vue?vue&type=template&id=da284a90&scoped=true& (http://localhost:3000/_nuxt/pages/index.js:536:1)
   at __webpack_require__ (http://localhost:3000/_nuxt/runtime.js:854:12)
   at fn (http://localhost:3000/_nuxt/runtime.js:151:13)
   at eval code (eval code:2:22)
   at ./components/organisms/layouts/Modal.vue (http://localhost:3000/_nuxt/pages/index.js:500:1)
   at __webpack_require__ (http://localhost:3000",
      Symbol()_e.kk24c8l2mhc: undefined
```

下から3行目辺りにこちらで用意したVueコンポーネントがでていたので
そちらを探ることになりました。

色々調べていると以下のページにたどり着きました。
英語のエラーメッセージで検索（Multiple definitions of a property not allowed in strict mode）
https://github.com/BabylonJS/Babylon.js/issues/4257

同じpropsを二回設定している。。。

もう一回見直してみると私のところでは以下のようにやらかしてました。
widthを二回設定しています。

```vue:components/organisms/layouts/Modal.vue
<div class="container" :style="{ width, width, maxWidth, maxHeight }">
  <slot></slot>
</div>
```

結局凡ミスでした。


## 参考
https://alliance7.blogspot.com/2019/07/ie11strict.html
https://github.com/BabylonJS/Babylon.js/issues/4257
低遅延動画配信 Apple Low Latency HLS を試す

去年の WWDC２０１９ で発表された Apple 謹製 LL-HLS ですが、諸々仕様変更などもあり今年の WWDC2020で情報のアップデートがありました。

今年中にはベータが外れるとのことでしたが、未だ GA になったとは聞いていない中、Wowza が Apple LL-HLS に対応したとのことで、早速試してみました。

# Wowza Streaming Engine

Wowza の基本的な設定などは割愛します。
試したのは AWS EC2 で稼働する Wowza ですが、プラットフォームは関係なく動作すると思います。

## 設定

下記のように設定ファイルを変更するだけ。

https://www.wowza.com/docs/deliver-apple-low-latency-hls-live-streams-using-wowza-streaming-engine

あとご丁寧に動画でも設定変更方法を説明してくれています。

https://www.wowza.com/blog/announcing-new-support-for-low-latency-hls

今回、Wowza で SSL を利用する為の手順は面倒なので省き、代わりに CloudFront を噛ますことで HTTPS を利用できるようにしてます。

# Encoder

何でもよいかと。
試しに OBS で RTMP で送りつけます。

分かりやすいようにブラウザで時計サイトを開いてキャプチャします。

![obs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172426/7e7c183a-ee26-b0d9-2230-34b545f1a24f.png)

# 視聴

## iOS
iOS14 デバイスならなんもせずにそのまま Safari で視聴できます。
なんと遅延2秒で安定します。

![IMG_0186.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172426/1a60f0e5-610c-6ce0-0447-7838638667d1.jpeg)

## Mac
THEOPlayer のテストページで再生します。

Mac Chrome で3秒

https://www.theoplayer.com/ll-hls-test-page

![Image from iOS (29).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172426/c48df1c1-2528-6173-f14c-aecba8287a84.jpeg)

## Android
こちらも THEOPlayer で再生します。
約2秒

![IMG_0191.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172426/f89ffb13-a861-b70c-695f-354a7c9855f3.jpeg)


# まとめ

どこに行っても「低遅延、低遅延」と言われる昨今、本家である Apple の LL-HLS が実際に使えるようになったのは嬉しい限り。
遅延2秒とか、もう殆ど地デジと変わりません！

反面、仕様がとても複雑になり、特に Player 側の実装は大変なんじゃないかと思われます。
自分が調べた限りにおいてですが、現状まともに動作するが前述の iOS14 と THEOPlayer のみで、他の HTML5 Player で対応しそうなもの（いわゆるベータ）などは、Wowza デフォルト設定では安定せず、chunkDuration を伸ばせば安定、けど遅延7秒くらいに増えちゃう、といった状況でした。
残響曲線から残響フィルタを算出する

# はじめに
音声認識において、学習用データを水増し(Augumentation)する際に
任意の残響時間のリバーブを付加したくなったので、
任意の残響時間から残響曲線を求めてリバーブフィルタを作成しました。


# インパルス応答から残響曲線を求める方法
インパルス応答から残響曲線を求めるとき、
通常の場合、インパルス応答2乗積分法[[1]](https://www.jstage.jst.go.jp/article/jasj/69/6/69_KJ00008722046/_pdf)を用います。
>
インパルス応答2乗積分法(Integrated impulse response method)は、インパルス応答から下式を用いて残響エネルギーの減衰曲線を求める方法です。この積分は開発者の名前からシュレーダ積分法(Schroeder integration method)ともいいます。

```math
E(t) = \int^\infty_t p^2 (\tau)dt　\tag{1}
```

(1)式の$p(t)$にインパルス応答を代入すると、残響曲線$E(t)$が求められます。
(インパルス応答は音圧の次元、残響曲線はパワーの次元です。)

# シュレーダ積分を解く
(1)式を$p(t)$について解くと、任意の残響時間を模擬したインパルス応答が求められ（る気がし）ます。

```math
E(t) = \frac{1}{3} \bigr[p^3\bigr]^\infty _t \\
E(t) = \frac{1}{3} p^3(\infty) - \frac{1}{3} p^3(t)\\
\frac{1}{3}p^3(t) = p^3(\infty) - E(t)
```
$p(\infty) = 0$とすると、

```math
p^3(t) = -E(t) \\
p(t) = -E^{\frac{1}{3}}(t)
```
# 残響曲線を作る
任意の残響時間を模擬した残響曲線を作りましょう。
残響時間とは、以下で定義されます[[2]](https://ja.wikipedia.org/wiki/%E6%AE%8B%E9%9F%BF%E6%99%82%E9%96%93)。
>
残響時間は、音源が発音を止めてから、残響音が60デシベル減衰するまでの時間をいう。

すなわち、t=0のとき0dB、t=[残響時間]のとき-60dBとなるような減衰を擬似的に作れば良さそうです。
簡単のため、残響曲線が直線を描くとすると、
残響時間がRTのとき、擬似残響曲線$E'(t)$は、

```math
E'(t) = -\frac{60}{RT} t
```
で表せます。

# Pythonで実装
必要な材料が整ったので、Pythonで実装してみます。

```Python
# import modules
import numpy as np

# define const.
rt = 0.1
fs = 48000

t = np.linspace(0, ir_len, int(ir_len*fs))
E = np.power(10, -3 * t / rt)
    
reverb = np.power(E, 2/3)
rand = np.random.randint(0, 2, reverb.size)
rand = np.where(rand==1, 1, -1)
reverb *= rand
```
例えば、RT=0.3sのとき、以下のようなインパルス応答が得られました。

![スクリーンショット 2020-12-11 17.30.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548796/2dda0d13-8698-50c9-4bc6-919088e686b2.png)

# まとめ
簡易的に残響曲線から残響付加インパルス応答を算出する方法について紹介しました。
あくまで簡易的なので、初期反射音・後期反射音の反射音密度の違いや、
残響時間の周波数による違いまでは再現できていませんが、
簡単な再現でも良い場合は、使えるかもしれません。


## 参考文献
[1] インパルス応答から求める室内音響指標、羽入敏樹、日本音響学会誌69巻6号(2013)
[2] 残響時間 - Wikipedia