OmniAICreator/Qiita-1.07M huggingface dataset:
AndroidでEditText以外のタップでキーボードを閉じる

## EditText以外のタップでキーボードを閉じたい

プラットフォームに関係なく、よくある要件ですね！
色々調べたのですが下記のようにしたら大体のレイアウトでカバーできそうだなって思ったので共有します


### dispatchTouchEvent()　を使う

`onTouchEvent()` を使う記事などが多くありますが、List系のレイアウトがあったりScrollViewが入ってると反応しないので `dispatchTouchEvent()` を使っておけばいいと思います。

あとは、スクロールのタッチアクションにも反応してしまうので、そこも対応が必要です。

タッチした箇所がEditTextだった場合は処理をしたくないので、タッチ領域がEditTextの表示領域かを判定する必要があります

```kotlin
private var lastEventAction: Int? = null

override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
    // スクロール時のタップを無視させる
    if (lastEventAction != MotionEvent.ACTION_MOVE && event?.action == MotionEvent.ACTION_UP) {
        // タップ位置がEditText以外だったらフォーカス外す
        if (!isEditTextTouch(event.rawX.toInt(), event.rawY.toInt(), editText1, editText2, editText3)) {
            // 画面内のルート要素とかをフォーカスさせる
        }
    }
    lastEventAction = event?.action
    return super.dispatchTouchEvent(event)
}

private fun isEditTextTouch(touchRawX: Int, touchRawY: Int, vararg editText: EditText): Boolean {
    return editText.any {
        val areaOutsideFocusedView = Rect()
        it.getGlobalVisibleRect(areaOutsideFocusedView)
        // 対象のEditTextの表示領域内のタップであるか判定
        return@any areaOutsideFocusedView.contains(touchRawX, touchRawY)
    }
}
```

おそらくこれで大体の画面レイアウトで対応が可能かと思います。

#### おまけ

*キーボード閉じる処理*

```kotlin
fun Context.hideKeyboard(view: View) {
    getSystemService<InputMethodManager>()?.let {
        it.hideSoftInputFromWindow(view.windowToken, 0)
        view.clearFocus()
    }
}
```

こちらは自作ライブラリでも同様の処理を用意しております

https://qiita.com/sasa-nori/items/aa63e380ff646bab7823
計算経済学　日本評論社　釜国男先生　

```{r}

#ロトカボルテラ方程式 p.34

#x は被食者の個体数、 y は捕食者の個体数、t は時間

#オイラー法　連立微分方程式

a=1
b=2
c=3
d=2

#dx/dt=(a-b*y)*x
#被食者の個体数変化速度 dx/dt 
#a*x:被食者の個体数 x は順調に自然増していくと考えられる。
#-b*y*x:被食者増殖速度は被食者個体数にも比例して減少すると仮定できる

f=function(tt,xx,yy){

return((a-b*yy)*xx)  

}

#dy/dt=(-c+d*x)*y
#捕食者の個体数変化速度 dy/dt
#c*x*y:捕食による捕食者増殖速度も同じ理屈から被食者数 x と捕食者数 y に比例するといえる。
#-d*y:被食者が存在しないことは食糧が尽きたことと同じであり、捕食者の死亡率は出産率を上回り、捕食者の個体数 y は減少の一途を辿る


g=function(tt,xx,yy){

return((-c+d*xx)*yy)  

}

t=0
x=4.5
y=6.5

x_vec=c()
y_vec=c()
t_vec=c()

ite=20000
h=0.001

for(l in 1:ite){

x_vec=c(x_vec,x)
y_vec=c(y_vec,y)
t_vec=c(t_vec,t)  
x=x+h*f(t,x,y)
y=y+h*g(t,x,y)
t=t+h

}

plot(t_vec,x_vec,xlab="t",ylab="x",xlim=c(min(t_vec),max(t_vec)),ylim=c(min(x_vec),max(x_vec)),col=2)

plot(t_vec,y_vec,xlab="t",ylab="y",xlim=c(min(t_vec),max(t_vec)),ylim=c(min(y_vec),max(y_vec)),col=3)



```


```{r}

#積分方程式　p.39

f=function(x){
  
return(23*x/6)  

}

f_vec=c()

ite=10

for(l in 1:ite){
  
fs=integrate(f,0,1)$value

f_vec=c(f_vec,fs)  

f=function(x){
  
return(23*x/6+x*fs/8)  
  
}

}


```

````{r}

#p.42 Lucas（1978）の資産モデル

#モンテカルロ法

#仮のデータで配当を最尤推定する:AR(1)
data("AirPassengers")
y=c(t(AirPassengers))
x=y[1:(length(y)-1)]
y=y[2:length(y)]
t=c(1:length(y))
n=length(y)

beta=0.5
p=0.01
mu=1

ite=10^2
eta=10^(-4)

for(l in 1:ite){
sig=sum((y-((1-p)*mu+p*x))^2)/n  
dp=-sum((mu-x)*(y-((1-p)*mu+p*x)))/sig  
dmu=sum((1-p)*(y-((1-p)*mu+p*x)))/sig
p=p+eta*dp  
mu=mu+eta*dmu  
loglik=-n*log(2*pi*sig)/2-sum((y-((1-p)*mu+p*x))^2/(2*sig))
print(loglik)
}

#予測値をモデルから作成
val=x[1]
values=c()
times=c()
itet=1000

for(l in 1:itet){
predict=((1-p)*mu+p*val)
values=c(values,predict)
times=c(times,l)
val=predict  
}

#モンテカルロ法で計算
r=-0.9
ite=10000
ts=2
py=c()

for(l in 1:ite){
val=-1
while(val<0)({val=values[ts]+rnorm(1,0,sqrt(sig))})
val2=values[ts:length(values)]+rnorm(length(c(ts:max(times))),0,sqrt(sig))
while(sum(val2<0)>0)({
val2=values[ts:length(values)]+rnorm(length(c(ts:max(times))),0,sqrt(sig))  
})
py=c(py,sum((beta^c(ts:max(times)))*(val2)^(r+1)/((val)^r)))
}
mean(py)


```
MATLABでPythonの仮想環境を使用する方法（Ubuntu20.04）

# 目次
[1. 実行環境](#1-実行環境)
[2. 試したこと](#2-試したこと)
[3. 対策手順](#3-対策手順)

#はじめに
　本記事は，自分がUbuntu20.04でMATLABからPythonを呼び出すとき，仮想環境で処理させるために少々時間を費やしたので，備忘録として作成しました。
　この記事のメインは3項目の対策手順ですが，2項目の試したことを行った場合に成功する可能性もあります。

#1. 実行環境
・Ubuntu20.04
・MATLAB R2021b
・Python3.8

#2. 試したこと
　まず，MATLAB R2021aで導入された`pyenv`というPythonインタープリターの既定環境の詳細を取り出す関数を実行します。この関数の構文は以下の通りです。
```pyenv('Version','executable')```
　そのため，具体的なコードは以下のようになります。
```pyenv('Version','~/anaconda3/envs/仮想環境名/bin/python')```
　このコードを実行すると，Pythonのバージョンや，ライブラリなどのパスがanacondaの仮想環境に指定されると思います。
　ここで呼び出すPythonプログラムに以下のようなプログラムを用いてPythonのバージョンを表示します。

```python:python.py
import sys
print(sys.version)
```

また，MATLAB側で上記のプログラムを呼び出し，pythonの出力を取り出したい場合は以下のように実行します。

```MATLAB:matlab.m
command = "python ~/matlab.m"
status = dos(command)
```
この二つのプログラムによって呼び出したpythonプログラムがどのバージョンで実行されているのか確認できると思います。しかし，root環境と仮想環境のバージョンが同じである場合は，バージョンで確認しても判断が難しいので，root環境にはインストールされていないパッケージを`import 'パッケージ名'`とするだけでも確認ができると思います。
　この方法で出来る方もいらっしゃると思いますが，自分の場合では成功しなかったので下に続きます。

#3. 対策手順
　先ほどの方法で成功しなかった場合は，Ubuntuのターミナルの方で仮想環境をアクティベートし，MATLABを起動します。root環境(base)にいる際は3行を，特にどこにも入っていない場合は下の2行のみを実行します。

```terminal:terminal
(base)$ conda deactivate
$ conda activate "環境名"
("環境名")$ MATLAB
```

　呼び出されたMATLABを使用して，2項目で述べた方法を実行すれば指定した仮想環境でのpython呼び出しが可能になると思います。
（ちなみにですが，2項目でパス指定を行うと，MATLABを閉じた後も残り続けると思いますので，再びパス指定などを行う必要はないかもしれません。）

　本記事は以上です。最後までお読みいただきありがとうございました。
PowerAutomateDesktopを用いてexcelの表まとめの自動化までのメモ　その7

なんか新規でバンバン書いて申し訳ございません。

今現在”月”の文字列の
前までと後ろ
までの文字列を取得したいと思っております。

””テキストの分析””
で出来そうなのですがそのめもを表記失礼いたします。
【Java】PaizaのJava入門編(6)まで終えて重要だと感じた内容まとめ。

##乱数の生成 Math.random();
```java
public class Lesson036{
    public static void main(String args[]){
        //randomメソッドは実数を生成するのでdouble型の変数を宣言
        double d;
        //randomメソッドで生成した実数を変数dに代入
        d = Math.random();
        //出力
        System.out.println(d);
    }
}
```
##整数を生成する場合 (int)(Math.random()*10)
```java
public class Lesson037{
    public static void main(String args[]){
        //int型変数iを宣言
        int i;
        //randomメソッドで0以上10未満の整数を生成
        i = (int)(Math.random()*10);
        //出力
        System.out.println(i);
    }
}
```
#代入演算子
```java
class JSample10_1{
  public static void main(String[] args){
    int num;

    num = 10;
    System.out.println(num);
    num += 5;
    System.out.println(num);//15

    num = 8;
    System.out.println(num);
    num *= 4;
    System.out.println(num);//32
  }

```
#配列 データ型[] 配列変数名 = new データ型[要素数]
```java
int [] num = {1,2,3,4,5,};
```
```java
int[] num = new int[5];
```
```java
class JSample2_1{
  public static void main(String[] args){
    int[] result = new int[3];

    result[0] = 75;
    result[1] = 88;
    result[2] = 82;

    for (int i = 0 ; i < 3 ; i++){
      System.out.println(result[i]);
    }
  }
}
```
#拡張for文 for (データ型 変数名: コレクション)
```java
String name[] = {"Suzuki", "Katou", "Yamada"};

for (String str: name){
  System.out.println(str);
}
```
#標準入力　Scanner scan = new Scanner(System.in);
```java
import java.util.Scanner;
 
public class InputSample {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String str1 = scan.nextLine();//行入力を取得
        String str2 = scan.next();//空白文字までを取得
        int num = scan.nextInt();//数値を取得
        System.out.println(str1);
        System.out.println(str2);
        System.out.println(num);
        scan.close();
    }
}
```
#戻り値
```java
class JSample5_1{
  public static void main(String args[]){
    int kekka;

    kekka = bai(9);
    System.out.println(kekka);

    kekka = bai(5);
    System.out.println(kekka);
  }

  private static int bai(int n){
    return n * 2;
  }
}
```
Intellij IDEA 使用箇所の検索の仕様


## 概要
IntelliJ IDEA をメインで使っていますが、「使用箇所の検索(Ctrl+B)」を多用しています。
Typescript を書いていて、ファンクションやメソッドの検索の仕様がわからなくなったので整理しました。
特に継承したクラスや型変換して実行するときの取り扱いについてまとめます。
ついでに、Visual Studio Codeと比較しています。  
なお、本記事の正確性や完全性について保証しませんので、ご注意ください。

## まとめ
- superクラス側で「使用箇所の検索」すると、継承クラス側の使用箇所まで検索される。
- 継承クラス側の「使用箇所の検索」では、superクラスや、他の継承クラスの使用箇所は検索されない（対象の継承クラスの検索対象だけ検索される）。
- any型にしてしまうと「使用箇所の検索」では、一切で検索できない（any型はやめよう）
- Visual Studio Code は、superクラス, 継承クラスともに関係なく検索される。(継承クラス側の使用箇所のみの検索はできない ＊メインで使ってないのでできたら教えてください)
- Visual Studio Code の「すべての出現個所を検索」はIntelliJ IDEA ではできない。 -> 一応複数ファイル内検索(Ctrl+Shift+F)で代替可能。
 
## 検証

検証コードをもとに色々な実装パターンで検索を試して、どのパターンが検索対象となるかを確認します。

### 検証コード

```typescript:TestCode.ts
export class SuperA {
  public testA(): string {
    return "HOGE";
  }
}

export class A extends SuperA {
  testA(): string {
    return "HOGEHOGE";
  }
}

export class B extends SuperA {
  testA(): string {
    return "HOGEHOGEHOGE";
  }
}

export class Main {

  main(): void {
    // パターン1. 継承クラスAのtestAを実行
    new A().testA();
    // パターン2. 親クラスSuperAのtestAを実行
    new SuperA().testA()
    // パターン3. Aをany型に入れ、testAを実行
    let ta: any = new A();
    ta.testA();
    // パターン4. SuperAをA型に入れ、testAを実行
    let tb: A = new SuperA();
    tb.testA()
    // パターン5. AをSuperAにキャストしてtestAを実行
    let tc:A = new A();
    (tc as SuperA).testA();
    // パターン6. Aを型定義なしで作成後、testAを実行
    let td = new A();
    td.testA();
    // パターン7. 型定義なしで変数を作成後、Aを代入してtestAを実行
    let te;
    te = new A();
    te.testA()
    // 8. Main(継承関係がない)のtestAを実行
    this.testA();
  }

  testA(): string {
    return "HUGA";
  }
}

new Main().main();
```

### 検索の実行
- superAクラスのtestAメソッドの使用箇所を検索(Ctrl+B)  
  - 検索結果 パターン1,2,4,5,6
  - superAのtestAメソッドの使用箇所に加えて、継承クラス(A,B)のtestAメソッドの使用箇所も検索される。
  - any型として認識されているパターン3,7、関係がないtestAメソッドの使用(パターン8)は検索されない。
- 継承クラスAのtestAメソッドの使用箇所を検索(Ctrl+B)  
  - 検索結果 パターン1,4
  - 継承クラス(A)のtestAメソッドの使用箇所のみが検索される。
  - superクラスのtestAメソッドの使用箇所(2,5,6)、any型として認識されている使用箇所(パターン3,7)、関係がないtestAメソッドの使用箇所(パターン8)は検索されない。

## 結果
- superクラス側で検索すると継承クラス側の使用箇所まで検索される。
- 継承クラス側での検索では、superクラスやほかの継承クラスの使用箇所は検索されない。
- any型にしてしまうと使用箇所の検索では一切で検索できなくなる。-> 当たり前だがany型を使うのはやめよう。
- 基本的にはtypescriptの型認識に従う（asによる型アサーション等に対応)。

## Visual Studio Code との比較
- Visual Studio Code は、superクラス, 継承クラスともに関係なく検索される。(継承クラス側の使用箇所のみ検索できない)
- Visual Studio Code の「すべての出現個所を検索(パターン1~8のすべてを検索)」はできない -> 複数ファイル内検索(Ctrl+Shift+F)で対応可能 。

## 商標
- IntelliJ IDEAは、JetBrains社またはその関連会社の商標です。
- Visual Studio Code およびMicrosoft社の各種サービスは、Microsoft Corporationまたはその関連会社の商標です。
- 記載の会社名、製品名、サービス名等はそれぞれの会社の商標または登録商標です。
「こんな変数宣言は、嫌だ。どんなの？」: JS

## ある日のパイセン、「こんな変数宣言は、嫌だ。どんなの？」

> なんだ？
> パイセンは最近、大喜利にハマっているのか？
> 
> もしや、新たなレビュー方法…？
> 評価に関わるかもしれないな
> よし、受けて立とうじゃないか！


## シンプルに`var`

```js
var notCoke = 'Pepsi'
```

`var`は嫌だろう！
どれくらい嫌かって？

炭酸が抜けたコークや
BBQで、もはやあたたかさを帯びたビールくらい嫌だね！

`var`が何で嫌か？まあ、こんなところかな！
1. 巻き上げられて、エラーがでない
2. 再宣言ができてしまう

```js
console.log(notCoke) // undefined　（巻き上げられて、エラーがでない）

var notCoke = 'Pepsi'

var notCoke = 'Dr.Pepper' // 再宣言ができてしまう
```

まあこんなことを抜きにしても、`var`を見たら
「え、古っ！」って思うようにはなってしまっているな…

なんか、`var`からは、おじいちゃんおばあちゃんの家と同じようなニオイがするんだよ

話は逸れるが、あのニオイの正体は一体何なんだい？


## 再代入しないのに`let`

```js
function getKingOfPizza() {
  let kingOfPizza = 'Cuatro Formage' // 4種のチーズピザ、あれ最高だよな！
  return kingOfPizza
}
```

宣言した`kingOfPizza`をそのまま`return`しているな！

別に動きはするからいいのかもしれないが
もちろん再代入しないなら`const`にしてほしいさ！

そうしたら、コードを最後まで見なくても
`kingOfPizza`は再代入されないことがわかるからな！


## 積み上がった`const`

テトリスって知ってるかい？
そうだ、ブロックが積まれて、横一列になったら消せる、あのゲームだ

JSを書いていて、こんな感じで`const`が積まれた状況に遭遇したことはないかい？

```js
const hamberger = 'Cheese Berger'
const sideMenu  = 'French Fries'
const drink = 'Coke'
```

もちろん変数宣言は必要だ
処理によっては、たくさん宣言することになるだろう
（人類も平和を守るためにあらゆる宣言を出してきたからな！）

でも、たくさん宣言されると何がなんだかわからなくなるのは、ボクだけじゃないはずだ

そんなとき、ボクはテトリスを思い出すよ

分割代入をうまく使えば、積み上がった`const`は消すことができる、ってね！

```js
const [hamberger, sideMenu, drink] = ['Cheese Berger', 'French Fries', 'Coke']

console.log(hamberger) // 'Cheese Berger'
```

だいぶ見通しがよくなった気がしないかい？

とはいえ分割代入を、変数宣言を少ない行で書くために使うときは
意味のあるまとまりごとに変数宣言したほうがよさそうだ

どんなふうに分割代入を使うか、は
テトリスのこんな形┗┓のブロックをどう使うか、と同じように
センスが問われるところかもしれないな！


## さあ、キミも参戦してくれ！

ここまで読んでくれたキミ、ありがとう！

ボクは全然優れたプログラマーではないから
たった3つしか思い浮かばなかった…！
（ウケをとれたかもわからないしね！）

パイセンからの大喜利はまだ終わりじゃない。

ぜひ、キミたちも参戦して、パイセンに
スタンディングオベーションさせる回答をしてくれよ！



**こんな変数宣言は、嫌だ。どんなの？**


**Follow ME !!!**
**I'm sure to follow you back!**
twitter: [@marty_ojiya](https://twitter.com/marty_ojiya)
ソースコードがネイティブコード（機械語）になるまで

#概要
記述したプログラム（ソースコード）がコンピュータで実行可能なネイティブコード（機械語）になるまでのイメージをまとめました。

詳細なことを細かく、というよりは図を用いながらイメージを掴めることに主眼をおいています！
（コンパイル言語を想定して書いています）

[「プログラムはなぜ動くのか」](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AF%E3%81%AA%E3%81%9C%E5%8B%95%E3%81%8F%E3%81%AE%E3%81%8B-%E7%AC%AC3%E7%89%88-%E7%9F%A5%E3%81%A3%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AE%E5%9F%BA%E7%A4%8E%E7%9F%A5%E8%AD%98-%E7%9F%A2%E6%B2%A2-%E4%B9%85%E9%9B%84/dp/4296000195/ref=pd_lpo_1?pd_rd_i=4296000195&psc=1)を要約した内容になります。
#目次
- 前提：コンピュータはネイティブコードしか実行できない
- ソースコードが実行可能なネイティブコードになるまで
- 余談


##前提：コンピュータはネイティブコードしか実行できない
ネイティブコードとは？
・0,1ですべての命令、データが表現されている
・CPUが実行できる単純な命令レベル（加算、データ読込等）まで分解されている
・windowsなら.exeの拡張子のファイルの中身
[参考サイト](https://e-words.jp/w/%E3%83%8D%E3%82%A4%E3%83%86%E3%82%A3%E3%83%96%E3%82%B3%E3%83%BC%E3%83%89.html)

ネイティブコードのイメージ↓
![スクリーンショット 2021-10-16 9.12.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495868/82f4c0d7-6905-b961-1b53-e2806a304cdb.png)

どんな言語でも最終的にはネイティブコードに変換されてCPUに実行される。
![スクリーンショット 2021-10-16 9.28.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495868/b7ba70a6-24da-9342-3273-91e59293941a.png)


##ソースコードが実行可能なネイティブコードになるまで
![スクリーンショット 2021-10-16 10.09.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495868/072c99cb-8675-08f3-d67c-1444b15ab06f.png)

①C言語を例にすると、まずsample.cというソースコードを書いたとします。
ネイティブコードにしないとCPUが理解できないのでソースコードをネイティブコードに変換する必要があります。

②そこでコンパイラというソフトウェアを使ってネイティブコードに変換（コンパイル）します。

③すると、sample.objというファイルができます。
ただ、sample.objはネイティブコードになってはいますが、このままではCPUで実行できません:sweat_smile:

なぜなら、外部で定義されている情報が入っていないからです。

たとえば、sample.cではライブラリAからlibraryA_functionという関数をインポートして使っていたとします。
そしてlibraryA_functionはライブラリの中のlibrary2.objというファイルに定義されているとします。

sample.objにはlibraryA_functionに関するネイティブコードが入っていないのでCPUはこのファイルを実行できません。

④そこで、リンカ(linker)というソフトウェアを使って、実行のために必要なファイル、今回の例でいうとlibrary2.objをsample.objに連結させます。

⑤実行可能なファイルであるsample.exeができます:raised_hands:


##余談
**余談1**
CPUの種類が違えば、ネイティブコードの種類も違います。
例えば、同じソースコードをコンパイルしてもx84とarmではそれぞれ違うネイティブコードになります。

**余談2**
ネイティブコード（機械語）は0,1で表現されていて人間には理解できませんが、機械語の命令に1対1で文字や記号を割り当てて人間に理解できるようにしているアセンブリ言語というものがあります。

[compiler-explorer](https://gcc.godbolt.org/)というサイトでは高水準言語（C言語など）をアセンブリ言語に変換して表示してくれます。
VS Code 1.61 の新機能 - ペア括弧ガイドの色付け機能

https://code.visualstudio.com/updates/v1_61#_bracket-pair-guides

前回リリース時の[ペア括弧色付け機能](https://qiita.com/12345/items/7a7bc1200d9068674fe4)に続き、ペア括弧のガイドを色付けする機能が追加された。

設定 `editor.guides.bracketPairs` をオンにすると有効になる。

javascriptの例

![bracket_pair_guide.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181011/017c2950-fde5-0709-879a-444c4417d8a3.gif)
IBM Cloud Code Engineを使って旅行ジェネレータを作ろうと考えた

#概要
[IBM Cloud Code Engine](https://www.ibm.com/jp-ja/cloud/code-engine)を利用して、プログラム作成にチャレンジしてみるという企画が会社で立ち上がり、参加すべく手を上げました。
できれば旅行に関わるもの、ですが、Code Engineが利用できれば内容は問わないという企画です。

#作りたかったもの
複数の選択肢を選ぶと、最適な旅行先を提案するというプログラムを作成しようと考えました。AかBか選択すると答えにたどり着く形でおすすめの旅行先を提案します。
- ゆっくりしたい or アクティブに動きたい
- きれいな景色をみたい or 美味しいものを食べたい
- 遠くに行きたい or 近くに行きたい　…等

答えはSNSに投稿できる形式で、結果が「行きたい」のか「いまいち」なのかをフィードバックとしてより多くの人が「行きたい」と思う答えにたどり着くよう人工知能のフィードバックとして与えて回答を成長させるものを考えました。

#どのような技術を活用しようとしたのか
IBM Cloud Code Engineでは様々な[AI・機械学習のコンテンツ](https://cloud.ibm.com/catalog?category=ai)が無償・有償で提供されているのでこれを利用しようと考えました。
が、AIの勉強からどのサービスを利用すれば良いのか選定できるところまで理解が進みませんでした。
また、今回の学習ではChromebookの利用として全てサーバサイドでCodingしようと考えましたが、こちらも作業が進められませんでした。

#利用者のメリットはなにか
一般ユーザには、旅行がしにくいご時世に、どこに行きたいか想像の中だけでも旅行気分が味わえるようにと考えました。
旅行を提供する側としては、世の中のニーズの収集や、SNSによる拡散、いざ旅行ができるようになった際の誘導入り口になりえないかということを考えました。

#今回の自己学習で取得できたものはなにか
- 全く技術力が足りてないことを痛感しました。最近手をつけているプログラム作成はGoogle Apps ScriptやExcelVBA、Google Colaboratoryなど環境構築を必要としないものが多かったため、CodeEngineのプラットフォーム構築ができませんでした。
- CodeEngineはプラットフォームの提供だけでなく、様々な外部サービスとの連携ができることがわかりました。たくさんありすぎて、どれを利用するか選定する知識が必要だと感じました。
- 最終的な成果物を提示するまでできませんでしたが、自身の足りない部分が可視化できたのでプログラミングの学習は続けたいと思います。
【JavaScript】関数とオブジェクト③　thisについて


#はじめに

Udemyの[【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)の講座の振り返りです。

前回の記事

https://qiita.com/nao0725/items/8339820949532dbd6bae

#目的

* 関数とオブジェクトについての理解を深める

#本題
###1.this

* 呼び出し元のオブジェクトへの参照を保持するキーワード
* thisの参照先は実行コンテキストによって変わる

####使い方

`````javascript
// personというオブジェクトを設定
const person = {
    // nameとhelloをそれぞれ設定
    name: 'Tom',
    hello: function() {
        // この場合,thisがpersonを参照しているpersonオブジェクトの中のnameを呼び出す
        console.log("Hello" + this.name);
    }
}
// helloを実行「Hello Tom」と出力
person.hello();

// helloで定義した関数内からみて外部の関数スコープ
// 　＝レキシカルスコープがpersonにあたるので値を取得できる
``````


###2.参照のコピーとthis

呼び出し時のコンテキストのthisの内容によってhello関数の挙動が変わる

####例1

```javascript
const person = {
    name: 'Tom',
    hello: function() {
        console.log('Hello ' + this.name);
    }
}
// ここで他の変数に代入
const ref = person.hello;
// 「Hello 」だけが出力される(thisが機能していない)
ref();

// refにfunctionがコピーされている
// refはhelloやnameではなくコピーされた参照から値を拾ってくるので"Tom"を取得できない

`````

ここで１行目に下記を追加する

`````javascript
// 下記の一行を入れると「Hello John」と出力される
window.name = "John";
const person = {
    name: 'Tom',
    hello: function() {
        console.log('Hello ' + this.name);
    }
}
const ref = person.hello;
ref();
``````

なぜ、windowオブジェクトから値をとってくるのか

基本的に以下のように考える

○**オブジェクト**のメソッドとして実行される場合
→ this => 呼び出し元のオブジェクト

○**関数**として実行される場合
→ this => グローバルオブジェクト、undefined


####例2

````javascript
window.name = "John";
const person = {
    name: 'Tom',
    hello: function() {
        console.log('Hello ' + this.name);
        // ここでaを実行すると,下記のa関数の参照先はグローバルオブジェクトになるので、「Hello John」となる
        a();
    }
}
// aという関数を用意
function a(){
    console.log('Hello ' + this.name);
}
// もしここでhelloを呼ぶと「Hello Tom」と出力される
person.hello();
```````

personオブジェクトの中身を更にコピーして定義したらどうなるのか

```````javascript
window.name = "John";
const person = {
    name: 'Tom',
    hello: function() {
        console.log('Hello ' + this.name);
        a();

        // さらにpersonを定義する
        const person = {
            // nameの値を「太郎」に変更
            name: '太郎',
            hello: function() {
                console.log('Hello ' + this.name);
                // ここでは上記同様に、Johnが呼ばれる
                // **関数**として実行される場合(26行目)
                a();
            }
        }
        // 再定義したpersonを実行すると"太郎"が呼ばれる
        // **オブジェクト**のメソッドとして実行される場合
        person.hello();
    }
}

function a(){
    console.log('Hello ' + this.name);
}

person.hello();
``````

thisを確認するにはデベロッパーツールのSouresで確認できる



今日はここまで！

#参考にさせて頂いた記事

* [【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)
開発系のまとめ

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)


# Apex

```
myMap.keySet()
myMap.values()

for(Target__c target : mapTargets.values()) {

for (OpportunityContactRole oppCR : opp.OpportunityContactRoles){
   if (oppCR.IsPrimary){
      IsPrimary = true;
      bewak;                        
   }//end of if
}//end of for
```

+ [Lightningコンポーネントは、コミュニティまたは標準のLightning Salesforceページにあるかどうかを認識していますか？](https://salesforce.stackexchange.com/questions/142710/does-a-lightning-component-know-if-it-is-in-a-community-or-a-standard-lightning)
+ [Pattern と Matcher の例](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_pattern_and_matcher_example.htm)

```
// Listの場合

List＜Account＞ accList = [Select Id From Account];


// Setの場合

// これはコンパイルエラー
Set＜Account＞ accSet = [Select Id From Account];

// コンストラクタにSOQL結果のListを渡すとうまくいく
Set＜Account＞ accSet 
  = new Set＜Account＞([Select Id From Account]);


// Mapの場合

// これはコンパイルエラー
Map＜Id, Account＞ accMap = [Select Id From Account];

// コンストラクタにSOQL結果のListを渡すとうまくいく
Map＜Id, Account＞ accMap 
  = new Map＜Id, Account＞([Select Id From Account]);
```

[SOQLでのコレクションとバインド変数の使用方法](http://blog.flect.co.jp/salesforce/2011/11/soql-a233.html)


# JavaScript 

+ [Use Third-Party JavaScript Libraries](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.js_third_party_library)
+ [JavaScriptで配列の重複チェックを超簡単＆スマートにやる方法](https://pisuke-code.com/js-check-duplicated-array-values/)


# 全般

+ [Salesforce の開発メモ](https://qiita.com/shohei_ot/items/1b418c082d6eedd632dc) @shohei_ot さま、ありがとうございます。
+ [lightning:navigation](https://qiita.com/Keiji_otsubo/items/9bf2423c1a3b9015934b)
+ [Apexでオブジェクトの定義情報を参照する ~Salesforce Schema.系 まとめ~](https://qiita.com/s_hayashida/items/517da55c05c6099805dc )
+ [コレクション型](https://developer.salesforce.com/docs/atlas.ja-jp.lightning.meta/lightning/ref_attr_types_collection.htm)
+ [スケールを意識した Lightning ページの設計](https://developer.salesforce.com/jpblogs/2020/03/designing-lightning-pages-for-scale/)
+ [ lightning:inputRichText の高さをもっと大きくする方法](https://salesforce.stackexchange.com/questions/187051/make-lightninginputrichtext-length-longer)
+ [失敗したApexジョブの電子メールが間違った電子メールに送られる](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000HDBwT)
+ [Apex ガバナ制限](https://developer.salesforce.com/docs/atlas.ja-jp.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/salesforce_app_limits_platform_apexgov.htm)
+ [Styling lightning:combobox drop down to not hide inside modal and extend modal length?](https://salesforce.stackexchange.com/questions/231397/styling-lightningcombobox-drop-down-to-not-hide-inside-modal-and-extend-modal-l)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/ad0c5b84-5e98-56d9-1e4c-3f5fef5b2be6.png)
トポロジカルソートに関して

## 参考文献   

- 秋葉拓哉,岩田陽一,北川宜稔,『プログラミングコンテストチャレンジブック』,株式会社 マイナビ出版(2012) 
- [AtCoder Beginner Contest 223 Problem D](https://atcoder.jp/contests/abc223/tasks/abc223_d) 
- [Nyann様の 提出 #26618152](https://atcoder.jp/contests/abc223/submissions/26618152)


# 1. 初めに
[AtCoder ABC 223 D問題](https://atcoder.jp/contests/abc223/tasks/abc223_d) にてトポロジカルソートに関する問題が出たそうです。

解説を読む以前に,
『トポロジカルソートってなんだっけ...?』と思った私はそれに関してまとめてみることにします。

# 2. トポロジカル順序とは

有向非巡回グラフ(Directed Acyclic Graph)において,  
$i,j\in\[N],v_i,v_j\in V$に対して$v_i\rightarrow v_j$ならば $i<j$である時,トポロジカル順序といいます


つまり, 以下のようなグラフのことをいいます。
![スクリーンショット 2021-10-17 23.16.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417525/9bd71c2b-e1cd-51fd-6c41-31d208bff43d.png)

そして,このような順序となるようなグラフを求めることをトポロジカルソートと呼びます。

また,上記において自分に入ってくるノードの数を入次数と定義すると,入次数はそれぞれ {0,1,1,1,1,2}となります.

# 3. 今回の問題への対応付け
[今回のD問題](https://atcoder.jp/contests/abc223/tasks/abc223_d) はこのトポロジカルの応用例であると考えられます。

実際の問題文(一部改変)は以下の通りです。

### 問題

ある数列

```math
T=\{ A_i,B_i\}^{M}_{i=1} 
```
が与えられた時に,$(1,2,...,N)$を並び替えて得られる数列 $P$ であって以下の条件を満たすもののうち、辞書順で最小のものを求めよ。

```math
\begin{align}
\forall  i &\in [M]{\rm において,} A_i,B_i\in T \cap P {\rm ならば}　\\
\exists k,l &\in [|P|](k<l)\ {\rm s.t.}\ P_k=A_i, P_l=B_i
\end{align}
```
ただし,そのような$P$が存在しない場合は-1を返せ.

## 考察

$A_i,B_i\in T$であれば$A_i \rightarrow^{+} B_i$であるようなものを調べていくため,トポロジカル順序にいて

- $v_i\rightarrow v_j$を$A_i,B_i\in T$

- $i<j$を$A_i \rightarrow^{+} B_i$

とすることで,トポロジカルソートと似たように考えることができそうだと考えます(通常のトポロジカルソートと対応関係が逆であることに注意する必要があります)。

それではここからは実際にどのように解けば良いかを考えましょう。

# 4. 実装とそのアルゴリズム

今回は,最も提出が早かった(というか開催前に提出済みであった)  
[Nyann](https://atcoder.jp/users/Nyaan)様の解答を参考にさせていただきました。

方針としては,

- 1に $A_i \rightarrow^{+} B_i$は確定なのでそれを埋めていきます.
- 2に 巡回グラフでないかどうかを確認します. means 入次数が0のものがあるかを確認します.
- 3に 入次数が0の集合のうち,最も小さいものから順に追加していきます. mean use heqpq.
- 4に 今追加したところの入次数を減らしていきます.
- 5に 追加される配列の長さが$N$になるまで繰り返します.

だと思います.

Nyann様の解答は以下の通りです(一部改変, [Nyann様の 提出 #26618152](https://atcoder.jp/contests/abc223/submissions/26618152)  )。

```python
# 問題設定
N, M = map(int, input().split())
# グラフを表すmatrix g : 
#   任意の頂点aに対してg[a]はaから矢印が向いている頂点を指す
g = [list()for _ in range(N)]
d = [0] * N
for _ in range(M):
  a, b = map(int, input().split())
  a -= 1
  b -= 1
  g[a].append(b)
  d[b] += 1

import heapq

Q = []
# 入次数が0のものを候補として入れる
for i in range(N):
  if d[i] == 0:
    heapq.heappush(Q, i)

ans = []
while len(ans) < N:
  # 非巡回グラフであることを確認する
  if len(Q) == 0:
    print(-1)
    exit()
  # 最も小さい値を取ってくる
  x = heapq.heappop(Q)
  ans.append(x + 1)
  # 現在追加したもので x=A_i ->　+ B_i の関係を見る
  for y in g[x]:
    d[y] -= 1
    if d[y] == 0:
      heapq.heappush(Q, y)

print(*ans)
```

# 5 あとがき

いかがでしたでしょうか。

このように,$\rightarrow^{+}$ヒープ構造を使ったり,うまく行列を定義したりすることで,今回の問題が解けることを確認できました。

また,グラフのアルゴリズムの勉強が自分は少し苦手であることがわかったので練習問題を解いて復習したいと思いました。
Progate Ruby on Rails5 IV ~ V 個人的ざっくりまとめ

# 投稿の編集

流れは、以下の通り。
①**編集したい投稿を取得**
②**その投稿のcontentの値を上書き**
③**データベースに保存**

```terminal:ターミナル
$ rails console

> post = Post.find_by(id: 1)  #①
> post.content = "Rails"  #②
> post.save  #③
```


# フォームに初期値を設定

textareaタグで囲んだ部分を初期値として設定できる。

```erb
<textarea>初期値です。</textarea>  <!-- テキストエリアに「初期値です。」が入る -->
```

特定のアクションで、URLのidと同じidの投稿データをデータベースから取得し、そのcontentの値を初期値に設定したりできる。

```rb:posts_controller.rb
def edit
  @post = Post.find_by(id: params[:id])
end
```
```erb:posts/edit.html.erb
<textarea><%= @post.content %></textarea>
```


# 投稿内容の更新

流れは、以下の通り。
①**URLに含まれたidを用いて、データベースから投稿データを取得**
②**フォームから編集内容を受け取り、投稿データを更新**

```erb:posts/edit.html.erb
<%= form_tag("/posts/#{@post.id}/update") do %>
  :
  <textarea name="content"><%= @post.content %></textarea>  <!-- name属性を指定する -->
  :
<% end %>
```

フォームの入力内容が変数paramsに代入され、updateアクションに送信される

```rb:posts.controller.rb
def update
  @post = Post.find_by(id: params[:id])
  #params[:content]はフォームから送信された値を受け取る
  @post.content = params[:content]
  @post.save
  :
end
```


# 投稿の削除

流れは、以下の通り。
①**データベースから削除したい投稿を取得する**
②**destroyメソッドを用いて、投稿を削除する**

```rb
@post = Post.find_by(id: params[:id])  #①
@post.destroy  #②
```

# getとpostの使い分け

「get」はデータベースを**変更しない**アクション

「post」はデータベースを**変更する**アクション


# post用のリンク

link_toメソッドの第三引数に**{method: "post"}**と指定する

```erb:posts/show.html.erb
<%= link_to("削除", "/posts/#{@post.id}/destroy", {method: "post"}) %>
```


# バリデーション

バリデーションとは、不正なデータがデータベースに保存されないように、データをチェックする仕組みのこと。

バリデーションはモデルで設定する。

```rb:models/post.rb
class Post < ApplicationRecord
  #validates :検証するカラム名, {検証する内容}
  validates :content, {presence: true}  #{presence: true}は空の投稿を防ぐバリデーション

  validates :content, {length: {maximum: 140}}  #{length: {maximum: 140}}は最大文字数140文字に設定

  #検証する内容を複数指定するやり方
  validates :content, {presence: true, length: {maximum: 140}}  #コンマで区切る
end
```


# renderメソッド

renderメソッドは、別のアクションを経由せずに、直接ビューを表示することができる。

**render("フォルダ名/ファイル名")**のように表示したいビューを指定する。

redirect_toメソッドと違い、そのアクション内で定義した＠変数をビューでそのまま使うことができる。

```rb:posts_controller.rb
def update
  @post = Post.find_by(id: params[:id])
  @post.content = params[:content]
  #render("フォルダ名/ファイル名")
  render("posts/edit")
end
```


# エラーメッセージの表示

```erb:posts/edit.html.erb
<!-- @post.errors.full_messagesにエラーメッセージの配列が入っているため、each文を用いることで全て表示することができる -->
<% @post.errors.full_messages.each do |message| %>
  <%= message %>
<% end %>
```


# フラッシュ

フラッシュとは、ページ上に一度だけ表示されるメッセージのこと。表示された後はページを更新したり、別のページに移動するとフラッシュは表示されなくなる。

アクションで変数flash[:notice]に文字列を代入すると、flash[:notice]をビューで使うことができる。

```rb:posts_controller.rb
def update
  if @post.save
    flash[:notice] = "表示したい文字列"
    :
  end
end
```
```erb:layouts/application.html.erb
<!-- フラッシュメッセージが存在する場合のみ、表示する -->
<% if flash[:notice] %>
  <div class="flash">
    <%= flash[:notice] %>
  </div>
<% end %>
```
angular.jsonを書き換えてassetsフォルダのようなビルドと関係ないフォルダを作りたい

自分なりに調べたので備忘として残しておきます。
# angular.jsonとは
一言でいうとAngularアプリの設定を行うファイルとのこと。
ビルドの設定やフォルダ構成、sourceMap等の有効化など色々な設定を行っている。

# ビルドのオプションをいじって任意のフォルダを作成する
[参考サイト](https://angular.jp/guide/workspace-config#asset-config)

デフォルトではAngular.jsonのassetsプロパティに定義されている通り、**assetsフォルダ**の中身がdist/appフォルダ下に展開される。

```angular.json
"assets": [
  "src/assets",
  "src/favicon.ico"
]
```
これを詳しく書くと以下のようになる

```angular.json
"assets": [
  {
    "glob": "**/*",
    "input": "src/assets/",
    "output": "/assets/"
  },
  {
    "glob": "favicon.ico",
    "input": "src/",
    "output": "/"
  }
]
```
ここで、ビルド時にphpフォルダを作成して、ビルド前にsrc/phpファルダに入っているファイルをすべてphpフォルダにコピーするには以下の設定を加える。
inputにビルド前どこにファイルが入っているか、outputにはビルド後ファイルがどのフォルダに格納されるかを記述する。
globにはinputフォルダ内のどのファイルをoutputフォルダ内に格納するか、対象ファイルを記述する。ファイルはUnix形式のパスで指定することができる。(globライブラリによってパスを指定可能にしているとのこと)

[参考](https://docs.python.org/ja/3/library/glob.html)


```angular.json
"assets": [
  {
    "glob": "**/*",
    "input": "src/assets",
    "output": "/assets/"
  },
  {
    "glob": "favicon.ico",
    "input": "src/",
    "output": "/"
  },
  {
    "glob": "**/*",
    "input": "src/php/",  //　src/php配下のファイルを
    "output": "/php/"     //  dist/SampleApp/php/にコピー
  }
],
```
NURO光で自前ルーターによるVPN構築

備忘録

## まとめ
* NURO光回線で自前ルーターのVPNサーバー機能を利用してVPNネットワークを構築した
* 自前ルーターにVPNサーバー機能がついていればすんなりいく

## NURO光の問題

### NURO光はONUとルーター一体型の機器を強制的に利用させられる
私の場合はHG8045Qだった。
これに自前のASUSのRT-AX92UをつないでDMZ設定し、パケットを横流しにすることで自前ルーターを機能させる。
RT-AX92UにはVPNサーバ機能が備わっているため、VPNサーバをONにするだけですぐに利用が可能。
今回は外出時にiPhoneから接続することを想定しているためIPSecVPNをONにした。

### NURO光の個人向け回線は固定IPサービスがないため、DNSの設定をしたほうが良い
今回はとりあえず別で使っている個人ドメインのサブドメインとしてRoute53にDNSレコードを追加した。
自動更新するところまでやりたいが一旦置いておく。

RT-AX92UにはDDNSサービスを利用する機能が搭載されているが、HG8045Qを挟んだ構成だとうまくいかなかった。
ipv4の場合はWAN側のIPアドレスがプライベートIPとなってしまうためそもそもDDNSの登録自体できない。
ipv6を設定することでipv6での登録は可能だが、VPNサーバへの接続不可。

## やったこと
### HG8045Q
1. 光コンセントにNURO光の光ケーブルを挿す
1. LAN1にLANケーブル挿してRT-AX92のWANポートに繋ぐ
1. HG8045Qの管理画面へアクセス
1. メニューのLAN>DHCPスタティックIP設定を選択
1. RT-AX92のMACアドレスを指定し、IPアドレスを適当なものに固定化
1. メニューの転送ルール>DMZ設定を選択
1. 固定化したIPアドレスを指定してDMZを有効にする
1. ネットワークアプリ>ALG設定でIPsecALGが有効か確認

### RT-AX92
1. RT-AX92の管理画面へアクセス
1. メニューからWANを選択
1. WAN接続タイプを自動IPにして適用
1. メニューからVPN>VPNサーバー>IPSec VPNを選択
1. `IPSec VPN サーバーを有効にする`をONにする
1. 事前共通鍵に適当なものを設定
1. ユーザー名とパスワードに適当なものを設定し、IKEバージョンをV1にして追加、適用
AtCoder Beginner Contest 223 参戦記

# AtCoder Beginner Contest 223 参戦記

## [ABC223A - Exact Price](https://atcoder.jp/contests/abc223/tasks/abc223_a)

2分半で突破. 0円だけ特別であることを意識して書くだけ.

```python
X = int(input())

if X == 0:
    print('No')
elif X % 100 == 0:
    print('Yes')
else:
    print('No')
```

## [ABC223B - String Shifting](https://atcoder.jp/contests/abc223/tasks/abc223_b)

6分で突破. 全部実際に生成すればいいですね.

```python
S = input()

a = {S}
for i in range(1, len(S)):
    a.add(S[i:] + S[:i])
    a.add(S[:-i] + S[-i:])
a = sorted(a)
print(a[0])
print(a[-1])
```

## [ABC223C - Doukasen](https://atcoder.jp/contests/abc223/tasks/abc223_c)

26分半で突破、TLE1. 片側からだけ燃やしてかかる時間の半分の時間が、両側から燃やすのにかかる時間. 後は左からその時間でどこまで進むかシミュレーションすればOK! 所要時間をにぶたんして、左右からシミュレートしてちょうど燃え尽きるところを探したりして TLE してはいけません(笑).

```python
from sys import stdin

readline = stdin.readline

N = int(readline())
AB = [tuple(map(int, readline().split())) for _ in range(N)]

s = sum(a / b for a, b in AB) / 2
result = 0
for a, b in AB:
    if s - a / b <= 0:
        result += s * b
        break
    s -= a / b
    result += a
print(result)
```

## [ABC223D - Restricted Permutation](https://atcoder.jp/contests/abc223/tasks/abc223_d)

48分半で突破. 考察が手強かったけど、思いついてしまえばそんなに実装は難しくはなくて面白かった. 既に自分より前に出ないといけない数が全て出終わっている数を管理し、これを「利用可能」と呼ぶ. 求めたい数列は辞書順最小なので、「利用可能」は性能の観点から heap で管理し、最小順に取り出して出力数列に加える. その値が出力数列に入ったことによって新たに「利用可能」が発生するかもしれないのでそれを処理する. もし循環などで矛盾があり数列Pが存在しない場合には、すべての数字を使い終わる前に「利用可能」が空になるので、出力数列の長さを確認すれば分かる.

```python
from sys import stdin
from heapq import heappop, heappush, heapify

readline = stdin.readline

N, M = map(int, readline().split())
AB = [tuple(map(int, readline().split())) for _ in range(M)]

fronts = [set() for _ in range(N + 1)]
rears = [set() for _ in range(N + 1)]

availables = set(range(1, N + 1))
for a, b in AB:
    if b in availables:
        availables.remove(b)
    fronts[b].add(a)
    rears[a].add(b)
availables = list(availables)
heapify(availables)

result = []
while availables:
    x = heappop(availables)
    result.append(x)
    for y in rears[x]:
        fronts[y].remove(x)
        if len(fronts[y]) == 0:
            heappush(availables, y)
if len(result) != N:
    print(-1)
else:
    print(*result)
```
JavaScriptの画面描画後の実行タイミングについて

# 画面描画後の実行タイミングは3パターンある！

### ①HTMLが全て表示された後のタイミング(DOMが出揃ったとき)
HTMLが揃っただけなので、画像などHTMLと並行して読み込まれるものの制御はこのタイミングではできない

書き方の例

```
$(function() {
   console.log('hoge');
});
```

### ②全要素が読み込まれた後のタイミング
画像やレイヤの大きさの制御を行うのはこのタイミング！

書き方の例

```
$(window).load(function(){
    console.log('hoge');
});
```

### ③処理が読み込まれた後のタイミング
HTMLのソースにベタがきすれば良い
この場合、特定のDOMに対する処理は実行できない
【書籍レビュー】基礎&応用力をしっかり育成! Androidアプリ開発の教科書 第2版 Java対応 なんちゃって開発者にならないための実践ハンズオン

#はじめに
今回はAndroidアプリ開発の参考書
『基礎&応用力をしっかり育成! Androidアプリ開発の教科書 第2版 Java対応 なんちゃって開発者にならないための実践ハンズオン』
をレビューしたいと思います。

https://www.amazon.co.jp/dp/4798169803?tag=shoeishacom-22

![51kvMrmhNTL._SX394_BO1,204,203,200_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925070/2f7791a4-c6b8-4ae8-b67d-190d0c7afa2f.jpeg)
開発環境は「Android Studio」で「Java版」と「Kotlin版」があります。(僕はJava版を使いました)
なぜこの参考書のレビューをしたのかというと、シンプルに**「めちゃくちゃ分かりやすかった」**からです。実は一度、別の参考書でAndroidアプリ開発の勉強をしたのですが、難しくて挫折しました。それから半年ほど経った頃、ふと書店に立ち寄りこの本をパラパラ見たとき**「めっちゃ丁寧！これならいける！」**と速攻買いました。私の予感は正しく、スイスイ勉強が進み簡単なアプリならすぐ作れるようになりました。
#なぜ分かりやすいのか？
**・コーディングから逃げていない**
Android Studioの良いところはボタン、メニューなどの部品がドラッグ&ドロップで配置出来るところです。
しかしそれに頼るがあまり「どうやったらボタンを押して画面が遷移するのか」、「表示方法を変えるにはどうするのか」などが曖昧になりがちです。
この参考書では**「ドラッグ&ドロップ」より先に「コード」でボタンを配置する**方法を紹介しています。ややこしく見えるかもしれませんがちょっとずつ教えてくれるので躓きにくいです。また、参考書の後半になり「画面遷移」や「フラグメント」の章に入っても、「あ、これは序盤でコード書いたところの知識を使うんだな」と難易度が下がります。(もし、ドラッグ&ドロップに頼り、この辺りで初めてコードを書き始めるとついて行けないと思います。)

**・基礎に徹底**
ほかの参考書だと、とにかくサンプルアプリを作らせようとしてコードの説明が簡略化されていることがあります。この参考書では、確かにサンプルアプリは作りますが、あくまで「機能を確認するため」の物です。**「その機能を搭載するには、どう実装すれば良いのか」**を丁寧に説明しています。
参考書にある**サンプルコードにはたくさんコメント**が書かれています。(私が見た中では、一番コメントが書かれている参考書)

**・新しい**
初版が2021年04月12日とかなり新しく、**最新バージョン**に対応しています。
ほかの参考書だと最終版が2016年の本があり、サンプルコードを実行してもエラーが出ます(汗)
#注意点
**・先にxmlファイルの勉強をするべし**
Androidアプリは「Javaファイル」と「xmlファイル」で構成されます。**そもそも「xmlファイルはどんなものか」という説明は無い**ので注意です。(もちろん、機能を搭載するのにはxmlファイルにどう書けばいいのかの説明はあります)
ただ**「xmlファイル」の勉強はめちゃくちゃ簡単です！**ネットで調べたら15分ぐらい読むだけで理解出来ると思います。

**・サンプルアプリの数が少ない**
先に述べた通り、「機能を確認するため」のアプリを作るので、本格的なアプリはあまり作れません。とはいえ、アプリは基礎的な機能の組み合わせなので自力で作れます。もしもう少しサンプルアプリが欲しいなら以下の参考書を勧めます。

https://www.amazon.co.jp/-/en/%E9%87%91%E5%AE%8F-%E5%92%8C%E5%AF%A6/dp/4798145807/ref=sr_1_3?dchild=1&keywords=%E4%BD%9C%E3%82%8C%E3%81%B0%E3%82%8F%E3%81%8B%E3%82%8B%21+android+%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1634499006&s=books&sr=1-3

![152.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1925070/961e22ff-2114-aba8-0ec2-2bdd870dbf0a.jpeg)


**・アプリのリリース方法が書かれていない**
アプリを作ったらGoogle Playにリリースしないといけないですが、その方法が書かれていません。ただAndroid デベロッパーの公式サイトに載っているので、そちらをご覧ください。

https://developer.android.com/studio/publish/preparing?hl=ja

#終わりに
非常にお世話になった参考書なのでレビューしました！皆さんも、まずは書店で手に取ってください！
初心者JavaScriptのセミコロン『 ; 』

##『 ; 』いつ使う？
JavaScriptを勉強していると、文末の;をどうしても忘れてしまう・・・。
というより、いつ使えばいいのかと思うときがあります。
今回は、そんなときにパッとわかるようにまとめます。
記事を調べると、「;いらない説」なども見受けますので、そこまで重要ではないかと思います。
(例えば文と文が改行されているときは省略できるなど）

##『 ; 』が必要なとき
:::note info
let
:::
:::note info
const
:::
:::note info
console.log( );
:::
:::note info
break;
:::
(注)break;とは、switch文の終了命令です。case ○○: とセットで使います



##『 ; 』が不必要なとき
:::note info
if ( ) { }      else if ( ) { }      else ( ) { }
:::
:::note info
while ( ) { }
:::
:::note info
for (変数定義; 条件式; 変数更新) { }
:::
:::note info
switch ( ) { }
:::

###おわりに
今後まとめながら追記していきます！
RSpec sequenceについて

# RSpecとは
RailsでWebアプリを開発する時に想定通りの挙動になるかを
検証するためのテストフレームワークです。

# sequenceとは
sequenceとは順序という意味の単語です。
FactoryBotを使う時にバリデーションに引っかからないように
```データが重複しないことを防ぐためのもの```です。
FactoryBot.createやFactoryBot.buildを使い、
複数個データが作成した時にデータ番号をそれぞれ作成できます。

# sequenceの使い方
sequenceの使い方を見ていきましょう。
下が構文です。

```~.spec.rb
FactoryBot.define do
  factory :モデルクラス名 do
    sequence(:カラム名) { |n| "ここに#{n}連番を挿入" }
  end
end

```
※下の資料から引用


staffモデルとして説明します。

```staffs_spec.rb

FactoryBot.define do
  factory :staff do
    name {Faker::Name.name}
    sequence(:job) {|n|　　"#{n}_#{Faker::Job.field}"}
    sequence(:idnumber) 　{|n|　"#{n}_#{Faker::IDNumber.valid}"}
end
end
```
これで***nを1ずつ増やして行ってもデータは重複しなくなります。***
コンソールを立ち上げて見て
FactoryBot.create(:staff)かFactoryBot.build(:staff)
あたりで調べていくとidが１ずつ増えていくのがわかるかと思います。



# 参考資料
https://qiita.com/9-michi-9/items/fa009d725dfeba56b22a
http://www.code-magagine.com/?p=9687
https://nowdeveloping.blogspot.com/2016/10/factorygirlsequence.html
スプレッドシートでマークダウンの表をコピーする【マクロ】


![スクリーンショット 2021-10-18 2.27.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112929/9bd4ce0a-77c4-3faf-ca03-b8d9c3c2888a.png)

スクリプトエディタで以下の関数を追加

```javascript

/**
 * アクティブな範囲をMDの表に変換する
 */
function createMdTableText() {
  const range = SpreadsheetApp.getActiveRange();

  const data = range.getValues();
  console.log(data);

  // 行列
  const rowNum = range.getNumRows();
  const columnNum = range.getNumColumns();
  console.log(`行数: ${rowNum}, 列数: ${columnNum}`);
  if (rowNum < 1 || columnNum < 1) {
    Browser.msgBox("選択して〜");
  }

  const  convertedData = [];
  convertedData.push(data.shift())
  convertedData.push(Array(columnNum).fill("---"))
  convertedData.push(...data);
  console.log( convertedData);
  const resText = convertedData.map(v => v.join(" | ")).join("\\n")
  console.log(resText);
  Browser.msgBox(resText);
}
```

![スクリーンショット 2021-10-18 2.28.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112929/562b84fb-acf4-813b-bebf-333865c4bf33.png)

インポート `createMdTableText`

表を選択してマクロの `createMdTableText` ボタンを押す

![スクリーンショット 2021-10-18 2.29.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112929/3e175a8e-20c6-982e-7970-e48d992e44aa.png)


許可するウインドウがでる、Googleの認証

![スクリーンショット 2021-10-18 2.33.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112929/6755cf98-fbe2-c465-4cfc-6fcb01ab7775.png)


```
タイトル | URL
--- | ---
google | https://www.google.com/
yahoo | https://www.yahoo.co.jp/
```

↑作られたMDファイル↑
↓実際の表↓

タイトル | URL
--- | ---
google | https://www.google.com/
yahoo | https://www.yahoo.co.jp/
「煽り」文化は善なのか悪なのか… - ロボコンをやってみて

こんにちは。すずともです。

すずともは某高専のロボット部のOBで、現役時代には一応部長もやっていました。

ロボコンを4年間(弊高専は1~4年までロボコンに参加することになっている)やってきた上で色々あったので、個人的な考え等をまとめていけたらなと思っています。

# 「煽り」文化とは…

皆さん。**「煽り」**って聞いて何を思い浮かべますか？
最近だと「煽り運転」とかですかねぇ。

弊部には**「煽り文化」**っていうのがあります。まぁ簡単に言うと後輩が先輩（逆でもいいけど）を煽って焦らせるというものです。

一般的に煽りという言葉にはあまりいい印象がありませんが、僕の中でこの「煽り文化」は**ロボコンにとって良いもの**ではないかと思っていました。

簡単にメリットをリスト化するとこんな感じ。

- 後輩が先輩に言いやすい環境を作ることで、先輩が**気づかないミス**や、**新しい発想**に気づける。
- 煽ることで相手を焦らせ、納期内に作らせる（又は遅れている物を進ませる）
- **煽られたくない！**という思いから煽られないようなものを作るようになる（**より良いもの**を作るようになる）
- ~~煽っている側はストレス解sa...~~

とまぁこんな感じでしょうか。現役のころはもうちょっとあった気がしますがいろいろ忘れていますね。

# なぜ煽り文化ができた？

僕が高専1年でロボット部に入部したころ、やべー先輩たちとかやべー先輩たちとかがいたんですよね。んで、その人たちは僕から見たら煽りあっていたんですよねww。でも、その人たちはみんなすごい人たちだから煽られてまたいいものを作るんですよねぇ。

そして、僕もロボットとか見てここおかしくない？とか、この機構にこれ使ってるの？？？とか結構言ってたんで、先輩とかといろんな意味で仲良くなれましたね。（まぁそんなことやってるうちに同学年の人たちは半分ぐらい辞めちゃいましたけどwww）

そんなこんなで、僕自身が**煽り文化ってなんかいいのかもしれない**と思っていて、自分が先輩・部長の立場になっても後輩の煽り行為をあまり注意しなかったり、自分も後輩煽ってたりしたので、「煽り文化」が定着したのかなと考えてみます。

記事を書きながら思いましたが、自分は怒るのが苦手なので、**怒る代わりに煽った**っていう面が一番大きいのかもしれません。

# 現状の煽り文化

最近、部室に顔を出す機会があって、いろいろ雰囲気とか見ていたのですが、現状の煽り文化の実態はこんな感じ

- 後輩は先輩に**普通にタメ口**を使う（煽る煽らない関係なしに）
- 煽られても**特に何も思わない**（笑って過ごす！？）
- 煽り相手のことを尊敬していない

まぁ、ごく一般的な「煽り」行為ですねww。
一年前に部長をしていた身でありながら「これはやばいな」と痛感しました。

# 「煽り文化」って善なの？悪なの？

本題である善悪の問題。
一週間前の僕であれば**「善！」**って言ってましたが、今の僕なら**「悪」**といいますね。
というのも、僕が今までしてきた煽りっていうのは、**自分の中での解決策を持ったうえで相手に問題のみを伝える**という行為なんじゃないかと思ったからです。

「最近の若い子は…」って言われるように、今の子(自分もそうですけどw)はあまり考えない癖がついているんじゃないかなと思います。これは今まで後輩を教育してきた経験からも言えます。（ここに関しては長くなりそうなので気が向いたら別の記事にしてみようかな…。読みたかったらコメントください）

なので、煽ったとしても、**煽られたことに気づかない・問題点を問題と思わない・問題点の解決法が分からない**といった感じで結局は放置されるんですよね。だから「煽り」の悪い部分のみが今の部活に残ったと。

# 煽り文化に変わる新しい文化

今まで煽り文化を肯定してきた身であり、今後否定していくには煽り文化に変わる新しい文化(体制)が必要ですね。

さっき出した煽りの解釈「**自分の中での解決策を持ったうえで相手に問題のみを伝える**」自体の問題点は「**相手に問題のみを伝える**」という部分にあると思います。今の子は問題のみを伝えたって何もしてくれません。なので**ここは〇〇じゃなくて××にしてみたらどう？**とか、もっと厳しめに**ここは〇〇じゃダメだから××にしなさい**という感じにしてもいいかもしれません。とにかく**自分が持っている解決策をぶつけてみる**っていう体制・意識が大切なんじゃないかなと思います。

# 昔の煽り文化が通用しなくなった理由

ちょっと本題からずれますが、これについても自分の考えを少し書いてみましょう。もし後輩くんが見ててくれたら、自分の思いを見直してみてね。
※ちょっとオーバーに書いてますのでお手柔らかに…

人は内面と外面に分かれています。それぞれ真面目だったり遊んでいたり、アホっぽかったりする面があります。

僕の先輩の各面の割合はこんな感じ

- 外面：エロ系の変態w 50%、技術系の変態 30%、アホ 20%
- 内面：エロ系の変態 20%、真面目 80%

内面にある「真面目」は外面には出ていないのですね。一見するとダメな奴っぽいですが、真面目かどうかは制作物で分かります。先輩が作るロボット・プログラムは皆綺麗だった。美しかった。かっこよかった…

僕はこの真面目な部分を感じていたのですが、今の後輩たちは「外面」しか見ていないので、先輩たちは遊んでばっかじゃないかと感じていると思います。でも本当は真面目なんだよね…

そんな外面しか見ていない後輩たちが、今や先輩の立場。大先輩を見習って今の先輩たちは「外面・内面共に：エロ系の変態 50%、技術系の変態 30%、アホ 20%」。そんな先輩をみて後輩たちはどうなるでしょうか？想像つきますねwww

まぁこんな感じで先輩たちの「内面」があまり見れていないのかなと思います。
だから、先輩に対する尊敬の意が無くて、単に悪の「煽り」になっているんですね。

# さいごに

全然まとまってないのですが、深夜テンションで書いていてそろそろ寝たいので締めます。

そもそも僕は色々と深く考えてしまう癖があって僕は本当に部長でよかったのだろうか…と常々思っています。僕が部活にしたことはざっとこんなかんじ

- 自分が怒れないせいで煽り文化を作ってしまった。
- 自分が色々改善できるのではと思って変えちゃったからぐちゃぐちゃになっちゃって部活がまとまらなくなった。
- そもそも自分が入ったときはちゃんとしていたので、今ちゃんとなってないのは自分たちのせいなのでは…

まぁこんな感じでネガティブな考察しかしてないのですが、その中でも特に理由がしっかり組み立てられたものを綴っていこうかと思っています。
この記事もその一つ。

ちなみに僕の外面は「いい人のまねをする 100%」で生きています。（内面はお察し…）

もう少しで弊部のロボコン地区大会。頑張れぇ～～

ではおやすみなさい。
pythonで連続同一値を数え上げる

# pythonで連続する１を数える方法
コーディングテストの中で、連続する1を数える関数を作成する必要がありました。「python 連続する1を数える」と検索し、出てきたものを安易にコピペしてもうまくいかなかったので、自分で考えて解決しました。安易にコピペした反省と備忘録を兼ねて、この記事を執筆します。

## 連続する1を数えたいシチュエーション
A君は三日坊主です。
そこで、aというリストを用意し、ちゃんと勉強ができた日は'1'を、できなかった日は'0'を追加しました。
A君が連続で勉強できた日数の最大を求めよう！

```md:input
a = [1,1,1,1,0,0,0,1,0,1,0,1,1,1,1]
```

## 1. 実際にコードを書いてみる
リストに連続する1を数える関数を作ります。この関数では、直前が1であれば、その数を足していき、最終的にその最大値を出力しています。
```python
a = [1,1,1,1,0,0,0,1,0,1,0,1,1,1,1] #連続する１を数えたいリスト

def mikkabozu(x):
    for i in range(len(x) - 1):
        if x[i+1] == 1:
            x[i+1] += x[i]
    print(str(max(x)) + '日続きました')

mikkabozu(a)
#output
#4日続きました
```
この方法で、連続する1を数えることができました。
しかしながら、この方法ではもとのリストに上書きしていて、少々お行儀がよくないです。

## 2. 書いたコードをリファクタリングする

current_countで現在の連続する1の数をカウントし、max_countでその最大値を求めるようにします。

```python
def max_consecutive_ones(a):
    max_count = 0  # 最大の連続1の数を格納する変数
    current_count = 0  # 現在の連続1の数をカウントする変数
    
    for num in a:
        if num == 1:
            current_count += 1  # 1ならカウントを増加
            max_count = max(max_count, current_count)  # 最大カウントを更新
        else:
            current_count = 0  # 0が出たらカウントをリセット
    
    return max_count  # 最大連続1の数を返す

print(f"{max_consecutive_ones(a)}日続きました")
```
このコードでは、もとのリストを上書きすることなく連続する1の数を求めることができるようになりました。

## 3. 正規表現を使った方法
正規表現のメタ文字 `+` は、直前の文字が「1回以上」連続するパターンにマッチします。そのことを用いて、連続する1の数を求めることができると考えました。
調べると、reモジュールには、`findall`という関数があり、これを用いると、指定したパターンに一致するすべての部分をリストとして返してくれることがわかりました。

```python
import re

def max_consecutive_ones_regex(a):
    # リストを文字列に変換
    binary_str = ''.join(map(str, a))
    
    # 連続する1のパターン "1+" を検索し、各マッチの長さを取得
    ones_sequences = re.findall(r'1+', binary_str)
    
    # 各マッチの長さの最大値を取得
    max_count = max(len(seq) for seq in ones_sequences) if ones_sequences else 0
    return max_count
```

- **参考文献**
[ゼロから覚えるPython正規表現の基本とTips](https://qiita.com/FukuharaYohei/items/459f27f0d7bbba551af7)

## 作成したアルゴリズムの比較
2つ関数を作成したので、どちらが優れているか比較したいと思います。

この2つの関数は、リスト内での連続する1の最大数を計算する目的は同じですが、考え方や効率性、コードの簡潔さにおいては違いがあります。

### 比較表

| 特徴            | `2. リファクタリング後` | `3. 正規表現を使った方法` |
|-----------------|-------------------------|-----------------------------|
| **メモリ効率**   | 〇                    | △                    |
| **実行速度**    | 〇                    | △                    |
| **コードの簡潔さ** | △                    | 〇                       |

### 使い分け
`2. リファクタリング後`は直感的なアルゴリズムで、計算量は`O(n)`と効率的です。一方、`3. 正規表現を使った方法`は正規表現と文字列変換が必要なため、平均実行時間がやや長くなります。ただし、他のパターン検索にも応用でき、コードが簡潔である点は優れていそうです。

- **参考文献**
[オーダー記法O(n)について](https://itmanabi.com/order_notation/)

## 教訓
<strong>ラクしようとして、検索をかけたものを理解しないままコピペしない！</strong>
ラクをしようと検索したものをそのままコピペした結果、うまくいかず無駄な時間を過ごしました。今後は気を付けます。
37003枚の画像で徹底比較 画像超圧縮 mozjpeg vs guetzli vs webp

37003もあれば、十分なほどに徹底比較になるでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149448/117e089a-8c5a-4a55-d0f9-57e918e5297f.png)

#使用コマンドライン
・/opt/mozjpeg/bin/cjpeg -quality 84 -optimize
・/usr/local/bin/guetzli –quality 84
・/usr/local/bin/cwebp -quiet -q 80
　もしくは /usr/local/bin/cwebp -quiet -q 75

###使用サイト
https://coldcurry.org/

#使用している画像
１枚のおおむね4K画像の画像から Image::Magick を使用して、多少の画像自動加工をしてから

横1600pxのJPEG（クォリティー84）
横800pxのJPEG（クォリティー84）
横600pxのJPEG（クォリティー84）
縦✕横80pxのJPEG（クォリティー84またはクォリティー75）

に変換をしています。

#使用バージョン
・mozjpeg (cjpeg) v4.0.3
・guetzli v1.0.1
・webp (cwebp) v1.2.1

#平均圧縮率
・オリジナル 1ファイル平均 351273 bytes
・mozjpeg 1ファイル平均 131087bytes
・guetzli 1ファイル平均 114851bytes
・採用JPEG 1ファイル平均 121969bytes (圧縮率34.72%）
・webp 1ファイル平均 78685bytes（圧縮率22.40%）

###37003枚分のデータすべて
巨大なスプレッドシートですので、特にスマホではご注意下さい。

https://docs.google.com/spreadsheets/d/1SFXM2GhwIs0dTnLwkkkdxOS3gKbO6T6OlbFYxgDh53U/edit
PythonでFFTとそのピーク検出をする方法

#概要
Pythonを用いて時系列データのFFTを行い，そのピーク検出をする方法をまとめておく。

#データ準備
解析例とする時系列データを作成する。3つの正弦波とノイズを組み合わせたデータを次のように作成した。

```python
import numpy as np
import matplotlib.pyplot as plt

# parameters
dt=6 #data duration
fsamp=10000 #sampling rate
f=[28, 60, 213, 355] # sin frequency
y=[0.6, 1.3, 0.3, 0.5] # sin amplitude
pi=np.pi

# data creation
# gauusian noise sigma=1
n=dt*fsamp+1 #data size![time_series.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2184372/45ed0137-bbff-fa65-3130-89ffecf07771.png)

t=np.linspace(0,dt,n) #sampling time
y=np.random.randn(n)\
+y[0]*np.sin(2*np.pi*f[0]*t)\
+y[1]*np.sin(2*np.pi*f[1]*t)\
+y[2]*np.sin(2*np.pi*f[2]*t)\
+y[3]*np.sin(2*np.pi*f[3]*t)

# plot
plt.plot(t,y)
plt.xlabel("Time [s]")
plt.ylabel("Amplitude [a.u.]")
plt.show()
```

結果は下図のようになる。
![time_series.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2184372/0772abfb-077b-05e0-f8e1-415a4183ce88.png)

#FFT
生成した時系列データをFFTする。FFTの効率のためにはデータ数が2の累乗となるようにするのがよいが，今回はデータ数が少ないため気にしないことにする。
FFTの係数`y_fft`は複素数のため，プロットしやすくするために振幅スペクトル`amp_fft`に変換してプロットする。振幅スペクトルが元の信号の振幅を再現するように，AC成分には 2/(データ長) を，DC成分には 1/(データ長) を掛けて規格化しておくと，プロットした際に解釈しやすくなる。

```python
# t: sampling time
# y: data
# fsamp: sampling rate

#FFT
y_fft=np.fft.fft(y)
y_fft=y_fft[:int(len(y_fft)/2)+1]
f_fft=fsamp/2*np.linspace(0,1,len(y)/2+1)
amp_fft=np.abs(y_fft)/len(y)*2
amp_fft[0]=amp_fft[0]/2

# plot
plt.plot(f_fft, amp_fft)
plt.xlim(1,500)
plt.xlabel("Frequency [Hz]")
plt.ylabel("Amplitude [a.u.]")
plt.grid()
plt.show()
```

結果は下図のようになり，設定した4つの正弦波が検出されている事がわかる。
![amp_spectrum.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2184372/349018fd-fadd-11a5-da71-71cc71cdfba8.png)

#ピーク検出
前項では振幅スペクトルをプロットしてピークを確認したが，さらにそのピークを自動で検出できるようにする。ピーク検出ができるライブラリには [scipy.signal.argrelmax](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.argrelmax.html) や [scipy.signal.find_peaks](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks.html) がある。今回はピーク検出条件を細かく設定できる後者の find_peaks を使用する。
find_peaks はデータ `x` とピークの検出条件 (`height` など) を入力し，`scipy.signal.find_peaks(x, height, threshold, distance, prominence, width, wlen, rel_height, plateau_size)` のように使用する。以下のコードではピーク値が周囲からどれだけ突出しているかを表す prominence を設定して，雑音をピーク認定しないよう調節している。結果を前項のグラフに重ねると，確かにピークが検出されていることがわかる。

```python
# peak detection
peaks,_ = signal.find_peaks(amp_fft,prominence=0.1)

#amplitude spectrum plot
plt.plot(f_fft, amp_fft)
plt.scatter(f_fft[peaks], amp_fft[peaks], color='red')
plt.xlim(1,500)
plt.xlabel("Frequency [Hz]")
plt.ylabel("Amplitude [a.u.]")
plt.grid()
plt.show()
```
![amp_spectrum.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2184372/d0131150-120a-1b5d-fa3b-c3ce2a8d63b6.png)

このとき prominence の値が不適切だと，例えば prominence = 1, 0.05 の場合，ピーク検出が不十分となったり，雑音まで拾って過剰にピーク検出してしまう。prominenceに限らず，このようなハイパーパラメータの設定には注意が必要である。

![amp_spectrum_prominence-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2184372/20faecb7-f974-7cac-3164-f25553265134.png)
![amp_spectrum_prominence-0.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2184372/2dea1a29-b8d2-32ee-c59c-257aee242e56.png)