OmniAICreator/Qiita-1.07M huggingface dataset:
Vueのpropsの使い方

# はじめに
Vueで親コンポーネントから子コンポーネントに値を渡すpropについて、簡単にまとめました。

# 子コンポーネントの書き方
子コンポーネントでは、以下のように記述します。

```vue
<script>
export default {
  props: ['hoge1', 'hoge2']
}
</script>
```
上記は、propsの名前のみを指定できます。
以下のように書くことで、他の項目も定義できます。

```vue
<script>
export default {
  props: {
    hoge1: {
      type: String,
      default: 'abc',
      required: true
    },
    hoge2: {
      type: String,
      default: '',
      required: false
    }
  }
}
</script>
```
`type`でデータの型、`default`でデフォルト値、`required`で必須を指定できます。


# 親コンポーネントの書き方
親コンポーネントから子コンポーネントにデータを渡す場合は、以下のように記述します。

```vue
<template>
  <!-- (prop名)="(データの値)" -->
  <Child hoge1="ABC" hoge2="DEF"> 
</template>

<script>
import Child from 'child'

export default {
  components: {
    Child
  }
}
</script>
```

また、固定値ではなく変数の値を渡したい場合は以下のようにv-bindを使用して記述します。

```vue
<template>
  <!-- :(prop名)="(データ名)" -->
  <!-- :hoge1 ⇨ v-bind:hoge1の省略形 -->
  <Child :hoge1="dat1" :hoge2="dat2">
</template>

<script>
import Child from 'child'

export default {
  components: {
    Child
  },
  data () {
    return {
      dat1: 'ABC',
      dat2: 'DEF'
    }
  }
}
</script>
```


# 命名について
親コンポーネントでプロパティを使用する場合はプロパティ名が小文字に変換されるため、小文字しか使えないのですが、子コンポーネントのプロパティをキャメルケースで記述した場合は自動でケバブケース（「-」で単語を繋ぐ書き方）に変換してくれます。

```vue:子コンポーネント
  props: ['hogeData']
```

```vue:親コンポーネント
  <!-- hogeData ⇨ hoge-data -->
  <Child hoge-data="dat1">
```
ターミナルで使える自作コマンドを作る

# この記事について
この記事では、ターミナルで使える自作コマンドを一から作って、使えるようにするための手順を紹介します。

## 使用する環境・バージョン
- OS : MacOS Mojave ver 10.14.5
- bash : Copyright (C) 2007 Free Software Foundation, Inc.

## 前提条件
- 自作コマンドはディレクトリ`~/command`に作成します。

## 読者に要求する前提知識
- 「パスを通す」の意味がわかり、実際にできること。
- shellスクリプトが書けること。

# 自作コマンドの作り方
## 1.コマンドファイルを作る
今回は、`aaa`という名前のコマンドを作ることにします。
そのため、ディレクトリ`~/command`中に`aaa`という名前のファイルを作ります。
注：拡張子はなしで作ります。

```bash
$ cd ~/commmand
$ touch aaa
```
作った`aaa`ファイルの一行目に、以下のように記述します。

```shell:/command/aaa
#!/bin/sh
```

## 2.シェルスクリプトを書く
これで準備はできたので、あとは二行目以下に望み通りの機能を実現するシェルスクリプトを書くだけです。
ここでは、コマンドを作るという観点で便利なコーディングを紹介したいと思います。

### コマンドの引数を処理する
コマンドには、引数という形でシェルスクリプトに値を渡すことができます。

```bash
$ command aaa 引数1 引数2 ... 引数n
```
この引数はシェルスクリプトの中で`$1`,`$2`…`$n`という風に設定されています。
実際に、スクリプトに以下のように記述します。

```shell:/command/aaa
echo "$1"
echo "$2"
echo "$3"
```
この状態でコマンドに引数をつけて実行すると、以下のように出力されます。

```bash
$ aaa one two three
one
two
three
```
このように、第一引数one、第二引数two、第三引数threeが認識されています。

参考：[UNIX & Linux コマンド・シェルスクリプト リファレンス 引数を処理する](https://shellscript.sunone.me/parameter.html)

### コマンド名を認識する
今実行しているコマンド名`aaa`をスクリプト中で取得するためにはどうしたらいいでしょうか。
実は、実行コマンドのパスが「0番目の引数」にあたります。
実際に0番目の引数を表示するようなコマンドを作ってみます。

```shell:/command/aaa
echo "$0"
```
これを実行すると、以下のような出力が得られます。

```bash
$ aaa
/Users/username/command/aaa
```
確かに0番目の引数がパスを指しているのがわかります。
コマンド名`aaa`だけを取得するためには、以下のようにします。

```shell:/command/aaa
echo "$(basename ${0})"
```

```bash
$ aaa
aaa
```

### コマンドのオプションを処理する
コマンドには、引数以外にも、`-a`のように、「ハイフン+アルファベット一文字」の形でも値を渡すことができます。(オプション)

```bash
$ command aaa -a -b test
```
上のコマンドだと、オプション`-a`と、testの値付きのオプション`-b`が指定されています。
オプションの処理をするためには、`getopts`コマンドを使用します。

```shell:/command/aaa
while getopts ab: OPT; do
    case $OPT in
        a ) FLG_A="TRUE" ;;
        b ) FLG_B="TRUE" ; VALUE_B="$OPTARG" ;;
    esac
done
```
1行目のwhile文に`getopts`が使われています。
第一引数には取りうるオプションを並べます。オプション`-a`には値がないのでそのまま`a`と記載、オプション`-b`には値がつくので`b:`と記載します。
第二引数OPT`にはコマンド実行時に使われたオプションアルファベットが格納されます。

上記のスクリプトにすることで、以下の形でそれぞれのオプションの有無・その値が取得できます。
- オプション-aが存在　→ 変数`FLG_A`に`"TRUE"`が格納される
- オプション-bが存在　→ 変数`FLG_B`に`"TRUE"`が格納される + 変数`VALUE_B`に-bについた値が格納される

参考：[シェルスクリプトでオプション付きのコマンドを作成する](https://qiita.com/Esfahan/items/e88bb806c7ca1dc8b758#実行例)
参考：[Bash の getopts でロングオプションを処理する](https://chitoku.jp/programming/bash-getopts-long-options)

## 3.実行する準備をする
せっかく作った自作コマンドですが、そのままでは使うことができません。
そのため、作ったスクリプトをきちんとコマンドとして認識させましょう。
参考：[シェルスクリプトで自作コマンドを作成する](http://tsujitaku50.hatenablog.com/entry/2017/12/30/120046)

### 3.1-1 パスを通す
作ったコマンドがあるディレクトリ`~/command`にパスを通します。

```bash
$ vi .bash_profile
```

```~/.bash_profile
export PATH=$HOME/command:$PATH
```

### 3.1-2 シンボリックリンクを貼る
`~/command`にパスを通す代わりに、`~/command/aaa`にシンボリックリンクを貼ってもよいです。

```bash
$ ln -si ~/command/aaa /usr/local/bin
```

### 3.2 自作コマンドのスクリプトに権限を付与
これでコマンド自体は認識されるようになりますが、このままだと権限エラーが出てしまいます。

```bash
$ aaa
bash: /Users/username/command/aaa: Permission denied
```
そのため、作ったスクリプト`~/command/aaa`に権限を付与します。

```bash
$ chmod 777 ~/command/aaa
```
これで自作コマンド`aaa`が使えるようになりました！

```bash
$ aaa
(指定の動作)
```
Spring Boot：Hello Worldを表示する&jarファイルを使って実行する

# Spring Boot触ってみた。
スキル向上のため、Spring Boot触ってみました。業務ではPHPなんですけど、Javaに興味があり、シコシコと(^^)
学んだことを忘れないために、Qiita投稿させてもらいます！
※環境はMacBookProを使って作業しています。

## 目的
- Spring Bootを使って、「Hello World」を表示する。
- Hello Worldを表示するプログラムをjarファイルにして、実行してみる。

## 手順

### プロジェクト雛形を生成
[start.spring.io](https://start.spring.io/)にアクセスして、プロジェクト雛形を生成します。
<img width="1437" alt="スクリーンショット 2019-12-28 21.48.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558604/7a0e3c88-5d87-3439-7f8b-1a6755073736.png">

- 画面遷移すると、上記の感じなります。

<img width="1424" alt="スクリーンショット 2019-12-28 21.53.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558604/ea173945-039a-55b5-42e0-189853f04879.png">

- スクロールすると、`Dependencies`欄があると思います。`Search dependencies to add`ボックスに`Web`を入力し検索すると候補が出てきます。今回、`Spring Web`を追加します。

<img width="1352" alt="スクリーンショット 2019-12-28 21.57.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558604/8490a744-5d42-90ee-11c9-ae8fcb7d9c64.png">

- 追加すると上記のような感じになります。あとは`Generate`ボタンを押して、プロジェクトをダウンロードしてください。

### 「Hello World」を表示する。

```
$ cd demo
```

- 手順「プロジェクト雛形を生成」より、zip形式のファイルをダウンロードしたあと解凍。解凍したファイルに移動します。

```
$ vim src/main/java/com/example/demo/DemoApplication.java
```

- 上記のコマンドで`src/main/java/com/example/demo/DemoApplication.java`を修正します。

```
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class DemoApplication {


    @GetMapping
    String home(){
	    return "Hello World!";
    }


    public static void main(String[] args) {
	    SpringApplication.run(DemoApplication.class, args);
    }

}
```
- ソース内容は上記のイメージ。

```
$ ./mvnw spring-boot:run
```

- 上記のコマンドを実行し、Tomcat（Nginxみたいなもの？）を起動します。

<img width="1428" alt="スクリーンショット 2019-12-28 22.36.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558604/335e5c75-7c09-8ee5-07c2-421821ffa6f4.png">

- 起動後、`http://localhost:8080`にアクセスするとHello Worldが表示されると思います！

### jarファイル作成

`./mvnw spring-boot:run`を実行してるコンソールに対して、`Ctrl+C`を実行して、アプリケーション終了させて下記を実行します。

```
$ ./mvnw package
```

- 実行後、targetディレクトリに「demo-0.0.1-SNAPSHOT.jar」が作成されます。このjarファイルを実行してもう一度Hello Worldを表示します。

### jarファイルを使って実行

```
$ java -jar target/demo-0.0.1-SNAPSHOT.jar
```

- 上記のコマンドを実行し、`http://localhost:8080`にアクセスするとHello Worldが表示されると思います。

```
$ java -jar target/demo-0.0.1-SNAPSHOT.jar --server.port=ポート番号
```

- ポート番号を変えて確認したい場合は、上記で実行し、`http://localhost:ポート番号`アクセスすればOKです。

## 感想

- 思った以上に簡単でした！！PHPでは触れないアノテーションっていうのがプログラムを簡単にしてくれてるんだなと感じました！
- 開発環境が簡単に作れるので便利だと！
Youtubeの動画をDVDで再生したい

#発端

私、社内SEをしておりますが、「DVDが再生できないぞ！どうなっているんだ！」という問い合わせ(怒り)がありました。
内容を確認すると「Youtubeの動画をDVDにしたものが再生できない」という話だったので、「ダウンロードは違法」であることを回答する為に裏付け調査。

##DVDの内容

動画自体は、非常に為になる動画。

志高く、今を生きろ
https://www.youtube.com/watch?v=n_0iPFzkNaQ

INSIDE TOYOTA #1 豊田章男からのメッセージ　～”自分”のためにプロになれ！～
https://www.youtube.com/watch?v=vJ8DsIiSb-U


##問題点
####当然ながら、ダウンロードは規約違反でした。

![2019-10-21_14h06_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/16982e8c-3d34-ccbe-65fa-f0f34c871050.png)


##例外もある
YouTube公式チャンネルの動画はダウンロードOKなものがあるとのこと。
見抜き方が2つある模様。

####見抜き方1
動画にマウスオーバーして「確認済み動画」と表示されればダウンロードOK
![2019-10-21_14h52_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/a2823155-ac18-226d-d5f5-cd5b7f68220b.png)


####見抜き方2
ライセンスに「クリエイティブ・コモンズ」と表示されればダウンロードOK

![2019-10-21_14h52_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/d3fe8b62-086c-d4ae-2ee0-5d2dbcdb7ed4.png)


##結果
今回の対象となった動画のダウンロードは、やはり違法となるようなので本人に連絡してYoutubeで再生してもらうようにお願いしました。そもそもなぜDVDにする必要があるのかと聞くと、取引先の方がITに疎くてDVDなら再生できるとのこと。Youtubeの再生も同じぐらい簡単なので、新しい方法をご紹介頂くことで解決しました。

#参考サイト

YouTube公式チャンネルをチェック！ダウンロードや再利用ＯＫの安全な動画を見抜く方法
https://www.crav-ing.com/column/youtube/63.html
一定時間外部割り込みを停止する方法

#はじめに
外部割り込みを入力された時に、しばらく、その外部割り込みを無効にしたい場合があります。手順としては以下のようにしてみます。
1. 外部割り込みを受けます
2. 受けたところで、外部割り込みを無効にして、タイマを設定します。このタイマに設定する時間がしばらく無効にする時間です
3. タイマ割り込みを受けます。ここで外部割り込みのペンディングをクリアして、外部割り込みを有効にします

#サンプルコード
STM32CubeIDEとNucleo-F446ZEを使ってコードを作成します。このコードでは、一度USERボタンを押すと10秒間USERボタンを受け付けなくなります

```
/* USER CODE BEGIN 0 */
__IO uint8_t Pushed;
/* USER CODE END 0 */
```
```
  /* USER CODE BEGIN 2 */
  TIM2->EGR |= TIM_EGR_UG;
  __HAL_TIM_CLEAR_IT(&htim2, TIM_IT_UPDATE);
  /* USER CODE END 2 */
```
```
    /* USER CODE BEGIN 3 */
	  Pushed = 0;
	  while (Pushed == 0)
		  ;
	  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14);
  }
  /* USER CODE END 3 */
```
```
/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	Pushed = 1;
	HAL_NVIC_DisableIRQ(EXTI15_10_IRQn);
	HAL_TIM_Base_Start_IT(&htim2);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	HAL_TIM_Base_Stop_IT(&htim2);
	// Clear Pending IRQ
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_13);
	HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}
/* USER CODE END 4 */
```
プロジェクトはGitHubにおいておきます。
https://github.com/kotetsuy/STM32forWindowsDemos/tree/master/DisableIRQSampleF446ZE
動画はこちらです
https://twitter.com/kotetsu_yama/status/1210930004558630912?s=20

#注意点
例のEXTI13は、IRQTypeの定義ファイル内でEXTI[15:10]となっています。
DisableIRQSampleF446ZE/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f446xx.h

```
  EXTI15_10_IRQn  = 40,     /*!< External Line[15:10] Interrupts */
```
これはEXIT15からEXIT10の6ラインを一つの割り込みにまとめて入力しているという意味で、この割り込みを無効にすると、EXIT13だけではなく、EXTI10やEXTI15も無効になります。STM32では回避する手段が無いので、外部回路を工夫して無効にしたい割り込みをEXTI0からEXTI4などの単独で無効にできるピンに割り当てる必要があります。
Roboto Monoは通常体とイタリック体の幅が等しくない

「ほう、Roboto Monoですか、たいしたものですね。Roboto Monoは可読性がきわめて高いらしく、OSのクリーンインストール直後にインストールするプログラマーもいるくらいです」

といいたいところだが、実はRoboto Monoは通常体と筆記体（以下イタリック体）の幅が等しくない。なので並べると以下の様になってしまう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78355/24e61c99-3cd3-39e6-bdca-583d9af2e0f1.png)

ウェブ上で通常体とイタリック体が同じ幅で表示されるようにするためには、以下のように`@font-face`を設定してやればよい。

```css
@font-face { font-family: 'Roboto Mono'; font-weight: 100; src: local('RobotoMono-Thin');    }
@font-face { font-family: 'Roboto Mono'; font-weight: 300; src: local('RobotoMono-Light');   }
@font-face { font-family: 'Roboto Mono'; font-weight: 400; src: local('RobotoMono-Regular'); }
@font-face { font-family: 'Roboto Mono'; font-weight: 500; src: local('RobotoMono-Medium');  }
@font-face { font-family: 'Roboto Mono'; font-weight: 700; src: local('RobotoMono-Bold');    }
```

こうすればイタリック体の表示に使われるリソースが通常体でオーバーライドされる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78355/a6f11d19-74b8-b17d-bafc-a59f9e31f4ce.png)

ちなみにこの問題はすでにIssueとして具申されている。

- [Several metrics issues in Roboto Mono worth fixing together · Issue #1832 · google/fonts](https://github.com/google/fonts/issues/1832)
【Laravel】DBの値をもとにViewに画像を表示させる

Laravelで、DBの値をもとにViewに画像を表示させる方法です。

## やりたいこと
DBの値（=流動的）をもとにViewに画像を表示させる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356958/25f8dbe3-0058-a9d3-6689-9073ca7f7f72.png)


## 環境
* PHP：バージョン7.3.7
* Laravel：バージョン5.8
* OS：Windows10

## 画像表示のキホン
画像ファイルは外部ファイルにあたり、{laravelプロジェクト}/publicに置く必要があります。
他、CSSやJavascriptも同様。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356958/565a6795-0abe-0cd0-48c8-f4493d300a88.png)


public配下のimageディレクトリ内の画像を表示させたい場合、Bladeでの記述は以下のようになります。

```php
<img src="{{ asset('image/hoge.png') }}" alt="hoge.png"> 
```
Laravelのヘルパ関数のひとつ、asset関数を用いるのがポイント！

## DBの値をもとに表示させるには
barsテーブルから取得したデータ$barのPICTUREの値をもとに画像を表示させたい場合はBladeには以下のように記述します。
※画像は上記同様、public配下のimageディレクトリ内に配置。

```php
<img src="{{ asset('image/' . $bar->PICTURE) }}" alt="{{ $bar->PRODUCT }}"> 
```

固定値（=imageディレクトリ）はクオーテーションで囲い、「.」で変数（=DBから取り出した画像名）と連結させます。
記述の仕方を間違えるとうまく表示されないので、注意しましょう！

## 参考
* [画像やCSS/JSの設置とパスの書き方について | Laravel学習帳](https://laraweb.net/environment/2884/)
* [Laravelで画像を保存し、そのパスをDBに格納する方法 | 昼寝王子のエンジニアブログ](http://masyumaroking.com/26)
* [Laravel5.5 ヘルパ | Readouble](https://readouble.com/laravel/5.5/ja/helpers.html)
セッションについて

#最初に
コードを書いていてセッションについての知識が曖昧な部分があると感じた。なので、セッションについて理解を深めるためにこの記事を書きたいと思う。

#セッションとは
接続（ログイン）から切断（ログアウト）までの一連の流れをいう。
http通信時、ブラウザからサーバーをリクエストを行い、サーバー側がレスポンス時にセッションIDを格納する。
セッションIDは個々のユーザーを識別することができる。

#セッションとクッキーの違い
クッキーはブラウザで保存され、セッションはサーバー側で保存される。
クッキーもセッションもキーと値を持ったデータ（ファイル）である。

クッキーでは、リクエスト時に毎回ブラウザ側からサーバー側へ値を送信するのに対し、
セッションはサーバー側に値を保存しておき、ブラウザ側から送信されたクッキー情報を元に
対応するセッション情報があるか確認する。

なので、セッション情報は毎回ブラウザ側からサーバー側へ送信しないので、セキュリティ上良いのである。

#セッションの使い方
```
session_start()
```
これでセッションが開始される。

#セッション変数について
セッションIDに紐付けされた変数のこと。
セッション変数は配列であり、そこで格納したものは他のページへリダイレクトした際にも持っていくことができる。
Noodlとmicro:bitをつないで、メッセージのやり取りをする

※この記事はNoodl2.0を使用

#Noodlとmicro:bitをつなぐ！！
下記に挑戦！
- Noodlからメッセージを送る
- micro:bitのボタンを押したらNoodlになにか送る

# micro:bitのサンプルコード
[こちらからコピー](https://makecode.microbit.org/_A2gfAXLvgVAt)
※micro:bitの設定で、「No Pairing Required: Anyone can connect via Bluetooth.」にチェックを入れておく。

# Noodlのサンプルコード
[こちらからクローン](https://github.com/mizuki-kisa/microbit_noodl)

## 使い方
1. NoodlのプロジェクトをNoodl2.0で読み込む。
2. 右上のボタンから「UART」をクリックし、Google Chromeでプロジェクトを表示する
<img width="1552" alt="スクリーンショット 2019-12-28 22.07.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480279/8f9558d7-c637-aca8-da63-8ea67b2fd853.png">

3. URLの「192.168.XXX.XXX」を「localhost」に変更 ※ブラウザのセキュリティの問題で、httpsまたはlocalhostでないとBluetoothが使えないため
4. 「接続」ボタンをクリックし、デバイスを選択→「ペア設定」を押す
<img width="629" alt="スクリーンショット 2019-12-28 22.02.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480279/0aaa9ff4-718f-ee7f-a039-42c249cdfa78.png">

5. これでOK！！
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">今日の成果！！ありがとうございました！！<a href="https://twitter.com/hashtag/%E5%B9%B4%E5%BF%98%E3%82%8C%E3%82%82%E3%81%8F%E3%82%82%E3%81%8F%E4%BC%9A?src=hash&amp;ref_src=twsrc%5Etfw">#年忘れもくもく会</a><a href="https://twitter.com/hashtag/Noodl?src=hash&amp;ref_src=twsrc%5Etfw">#Noodl</a><a href="https://twitter.com/hashtag/microbit?src=hash&amp;ref_src=twsrc%5Etfw">#microbit</a> <a href="https://t.co/scj31Uk6ym">pic.twitter.com/scj31Uk6ym</a></p>&mdash; はりねずみ麺 (@hedgehog_noodl) <a href="https://twitter.com/hedgehog_noodl/status/1210918714285015040?ref_src=twsrc%5Etfw">December 28, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
**micro:bitからNoodlに送信：**
  micro:bitのAボタンを押す→「Aだよ」と表示
  micro:bitのBボタンを押す→「Bだよ」と表示

**Noodlからmicro:bitに送信:** 
  Noodlの「テキストを入力」に「noodl」と入れて送信ボタンを押す→micro:bitのLEDにハートのアイコンが出る
  Noodlの「テキストを入力」に「noodle」と入れて送信ボタンを押す→micro:bitのLEDに顔が出る

## オマケ（加速度センサーの値取得）
このNoodlプロジェクトには、micro:bitの加速度取得のコンポーネントも含まれています。
右上のブラウザ表示アイコンから、「Acc」を選ぶと確認できます。
<img width="433" alt="スクリーンショット 2019-12-28 22.32.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480279/28c6298a-8794-2349-6d6f-43145b24a931.png">

[micro:bitのサンプルはコチラ](https://makecode.microbit.org/_VY7AV6AJp1Xs)
IntelliJ + TypeScript + Docker で Remote Debug (Break Point)

# TL;DR
1. Dockerコンテナ上で、 `ts-node-dev --inspect=0.0.0.0:9229 ./dist/index.js` を実行
<img width="1395" alt="スクリーンショット 2019-12-28 22.10.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143813/0a9047b3-d803-be98-cf88-3de5d1ac9150.png">

1. IntelliJ上で、`Attach to Node.js/Chrome` を実行
   `Run > Edit Configuration ... > +ボタン > Attach to Node.js/Chrome`
<img width="1068" alt="スクリーンショット 2019-12-28 21.56.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143813/3d2d1df6-be89-482d-798e-cb1c71e83980.png">
1. IntelliJ上でBreakPointを貼り、ブラウザにアクセス
<img width="1438" alt="スクリーンショット 2019-12-28 22.13.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143813/c5774937-4e1c-8435-141c-7cca9a44f4ea.png">

※ Dockerコンテナでは、アプリ用ポート(8080)と、inspect用ポート(9229)を開放する必要あり
<img width="1396" alt="スクリーンショット 2019-12-28 22.11.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143813/d663482a-6d9e-0e3a-695d-11e6fc1fb1c3.png">
STM32マイコンの書き込み方法の種類

(初学者です)
　STM32マイコンのチップ単体の書き込みに関することです。どんな種類があるのか簡単に説明します。各書き込み方法の詳細は、説明しません。
#はじめに
　STM32　32bitマイコンを利用する際、最小のピン数で書き込みたい。
　そのため、書き込みに必要なピン数を調べるため、各書き込み方法を比較してみました。
　一応この記事ではSTM32L432KCU6に書き込む際に困り、調べたことを書いているので、STM32のもっと高性能なF7とか、MP1に関してはどうなってるかわかりません。

#STM32マイコンの書き込み方法の種類
　STM32マイコンの書き込み方式ではJTAGやSWD(Serial Wire Debug)、シリアル通信(UART)、DFU(Device Firmware Upgrade)などが存在します。

|方式名|必要ピン数|説明|
|:----|:-----|:------|
|SWD|2+電源|デバッガにより書き込む|
|JTAG|4+電源|デバッガにより書き込む|
|UART|2+電源|汎用シリアル変換により書き込む+ブートローダの起動が必要なため、BOOT0ピンを切り替える必要あり|
|DFU|2+電源|USBで直接接続して書き込む+ブートローダの起動が必要なため、BOOT0ピンを切り替える必要あり|
　※ここではプログラムの書き込みに必要なピンの本数です。トレースをする場合は、SWDは3線＋電源が必要です。
追記2020/03/10　SWDによる変数の値の確認などのデバッグは2線+電源で動作できそうです(STM32CubeIDEでOpenOCDにて確認)。シリアルワイヤビューワや文字出力を利用する場合(トレース)は3線+電源が必要っぽいです。
　※BOOT0ピンを切り替えるということは、ピンが1本増えるか、スイッチが必要になります。(ここではBOOT1は省略)
　※DFUは対応していない製品もあるかも（調べてないです）。
　STM32CubeIDEでは、デバッグ構成で、SWDかJTAGを選択することができます。

#結論
　書き込みピンの本数的に、おすすめはSWDです。DFUもデバッガが必要なく、USBで書きこめることは面白いが、デバッガをもってたら、いらん子かも?
　STM32CubeIDEでの書き込みも、初期設定ならSWDで書き込まれます。
　SWDでは、SWDIOとSWCLKの2線で書き込むことができ、トレースをするには、SWOを接続する必要がある(多分)。
 **注:　これらは書き込みに限った話であり、デバッグの性能を比べると、SWD以外の書き込み方法にも利点があるかも。**

#####参考サイト↓

- [マイコン徹底入門:導入編:オープンソースでCortex-M3/STM32の開発環境を無償構築: 6. ビルドと書き込み:](http://miqn.net/introduction/118.html)
- [JTAG総合情報サイト  SWDって何？](http://www.tokudenkairo.co.jp/jtag/adv2018/08.php)
- [STM32CubeIDEでprintf【SWO編】](https://yukblog.net/stm32cubeide-printf-swo/)
SASでデータセットをまとめて取得

ライブラリTEST内にSMPL_yyyymmddの形式で保存されているデータセットをまとめて取得する。
TEST.SMPL_20191031
TEST.SMPL_20191130
TEST.SMPL_20191231

```
* マクロ変数dsnに空白区切りでデータセット名を格納 ;
proc sql ;
    select kcompress(libname || "." || memname)
    into :dsn separated by " "
    from  dictionary.tables
    where libname eq "TEST"
    and   prxmatch("m/^SMPL_(\d{8})$/", kcompress(memname)) > 0
    ;
quit ;

* %put &dsn. ;

data aggr_smpl ;
    set &dsn. ;
run ;
```
”Soracom”で始める、IoT入門　　　　　　　「もう遅刻なんてしない」編

#はじめに
この記事は、
***ものづくり未経験者が、Soracomに出会い、初めてものづくりをする。***
までを綴った奇妙な冒険譚です。
Qiita初投稿なので、”こたつの中で、長時間温まった後の足先”のような生暖かさで見ていただけると嬉しいです。

#お品書き

- 物語は突然に
- Soracomとの出会い
- 便利屋、「ショートカット」くん
- 感想

#物語は突然に
ある日僕が仕事をしていると、同期がとても落ち込んだ顔をしていました。
彼は遅刻をしてしまい、面談で上司に酷く怒られたそうです。
![Image1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557096/7db97c87-f9b2-f732-f64e-dd7f33258f60.jpeg)
※画像はイメージです

「せめて連絡さえできていれば...」
そのとき、ふと閃きました！
![Image2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557096/55919875-ecd3-d5af-f938-8291a5a3db1a.jpeg)

#Soracomとの出会い
どうやって遅刻を判定しようかな〜と悩んでいると、上司がこんなものをくれました。
![products_glove_iot_starter_kit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557096/49e2e019-3632-5bc3-4f54-77a852112728.png)
Grove IoT スターターキット for SORACOM(Wio LTE JP Version)
https://soracom.jp/products/kit/grovestarter_kit_lte/

***僕：「これは！誰でも簡単にIoTを始められるスターターキットじゃないですか！」***
***上司：「これあげるから、それ使って面白いもの作って。」***
***僕：「わかりました！(遅刻メールに使うことは内緒にしておこう...）」***

ということで、以下のような構成を考えました。
「〇時なのに、GPSの情報が自宅だったら遅刻」と判定することにしました。

***無事、起きれたとき***
![Wakeup.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557096/a96148ae-66d9-c30f-745c-11c282bf6c09.jpeg)

***遅刻しちゃったとき***
![BeLated.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557096/421ccf2a-685c-413d-4ba2-15b955b45125.jpeg)

遅刻時は「〇時のGPS情報が自宅だったら、API叩いてメールを送る」、それだけです。
無事、起床時は「ショートカット(後述)を押すことでAPI gateway経由でLambdaを動かし、メール送信をOFFにする」
ようになってます。

#便利屋、「ショートカット」くん
今回の押しポイントである、iOSのショートカットについて少しだけ。
iOS13から標準アプリの仲間入りをしたショートカットくん。
複数の手順を組み合わせることで、オリジナルのショートカットを作ることができます。
今回はアラームのON/OFFとRaspiのON/OFFを組み合わせました。
![Shortcut.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557096/5f625b71-11bd-bdea-2bbe-c6831ba68ad1.jpeg)
API GatewayとLambdaはこんな感じ。
![APIGateway.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557096/d0db3df7-eee1-e060-0306-7f5843f6e656.png)
![Lambda.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557096/ae7e7b1f-4f2c-e352-377b-1b8c59a68bdd.png)
URLを叩く→Lambda呼び出し→AWS IoTでpublish
って流れです。
ONにするときはlat(latitude)=-2を送信、OFFにするときはlat=-1を送信することでRaspiのON/OFFを行いました。
目覚ましのONとRaspiのONを同時にワンクリックで出来るので便利です！
これで、もし遅刻しても事前に上司に連絡がいくので、叱られずに済みます。ﾔｯﾀﾈ!!

#感想
初めてのものづくりでしたが、自分で何かを作るって良いですね。
SoracomやらAWSやらは先駆者様がたくさんいらっしゃるので、ググれば何とかなるのがベネ(笑)
僕は以下のサイトを参考にしました。
https://iot.kyoto/integration_case/2019/04/13/3739/

反省点は、SoracomのSIMであるメリットを活かしきれなかったことですね...
センサーもいっぱい付属してるので、そいつらも活かしたいところ...(Soracomのスターターキット、めちゃお得なのでオススメです！)
次はもっとIoTっぽいものに挑戦したいと思います(^。^)
Railsのプロセスを強制killする、ワンライナーのLinuxコマンド

Railsはよくフリーズするので、`Ctrl-C`でkillできないことがあります。
そういうときは以下のコマンドを使えば強制killできます。

```zsh
lsof -i tcp:3000 | grep ruby | awk '{print $2}' | xargs kill -9
```

自分は以下のaliasで.zshrcに登録しています。
`$2`の前の`\`に注意！

```zsh
alias rk="lsof -i tcp:3000 | grep ruby | awk '{print \$2}' | xargs kill -9"
```

## 参考
[Rails sのプロセスが切れない時](https://qiita.com/motty93/items/d22c1eb8f5128f8cd7f8)
[Getting a zsh alias including a pipe to execute](https://stackoverflow.com/questions/21626583/getting-a-zsh-alias-including-a-pipe-to-execute)
selenium小技 (プロキシ/ヘッドレス)

![selenium-logo-150x150.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258841/99ae6c09-45ea-2cde-5bfe-10fd7cc33432.png)

## 背景

seleniumで色々作業した時に得た知見のメモ

↓導入方法
■ [Selenium WebDriverのインストール～動かしてみる](https://www.htmlhifive.com/conts/web/view/library/webdriver-howtouse)

ちなみにpythonならこんな感じで爆速で始めることも可能

``` bash
$ pip install selenium

# または
$ conda install selenium
```

#### ベース

``` python
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
```

#### 起動オプション 

--headlessを付与することでヘッドレスモードで起動可能

``` python
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
```

--no-sandboxを付与することでサンドボックス外で動作

``` python
options.add_argument('--no-sandbox')
driver = webdriver.Chrome(options=options)
```

プロキシ設定

``` python
option.add_argument('--proxy-server=http://%s' % PROXY)
option.add_argument('--proxy-auth=%s' % PROXY_AUTH)
driver = webdriver.Chrome(options=options)
```

既存のウィンドウの新しいタブで開くのではなく新しいウィンドウで開くように設定

``` python
options.add_argument('--new-window')
driver = webdriver.Chrome(options=options)
```

#### onclick属性で発火されるjsを実行する

seleniumでボタン系の自動化してるときのあるあるらしい。
jsを実行させたい場合はボタンクリックとかせずとも下記のように直接実行が可能

``` python
browser.execute_script('javascript:hogehoge();')
```

#### iframeをスイッチ

``` python
iframe = driver.find_element_by_id('wpnt-notes-iframe2')
# 取得したインラインフレームにスイッチ
driver.switch_to.frame(iframe)
```

#### quitとexitの違い

「driver.close()」
アクティブになっているタブのみ終了。

「driver.quit()」
すべてのタブを閉じてブラウザを終了。

#### docker-selenium

seleniumはまっさらな状態から入れるとなるとちょっと面倒な手順が必要です。
dockerみたいな感じでさくっと使えるかなと思って調べたら存在しました。

[docker-selenium 使って見た](https://qiita.com/yutachaos/items/4a1da5d55a3bf0df889e)

VNCを使ってその内部でchromeを動かしそこで動作させてるようです。
ファイルの共有なんかもdockerの知識さえあれば簡単に行えてとても便利そうです。

VNC用のコンテナとブラウザテスト用のコンテナを用意することで開発環境とは分離されたテスト環境もこんな感じでさくっと用意できますね。

``` yaml
version: '3.7'

services:
  chrome-server:
    build:
      context: ./chrome
      dockerfile: Dockerfile
    container_name: 'chrome-server'
    hostname: 'chrome-server'
    ports:
      - 9000:5900
      - 4444:4444
    environment:
      - 'TZ=Asia/Tokyo'
      - 'HUB_PORT_4444_TCP_ADDR=hub'
      - 'HUB_PORT_4444_TCP_PORT=4444'
    volumes:
      - ./chrome/downloads:/root/Downloads
  py-server:
    build:
      context: ./py-server
      dockerfile: Dockerfile
     container_name: 'py-server'
     hostname: 'py-server'
     environment:
       - 'TZ=Asia/Tokyo'
     tty: true
     depends_on:
       - chrome-server
     volumes:
       - ./py-server/src:/app/src
       - ./py-server/images:/app/images
     env_file:
       - app.env
```

ブラウザテスト環境がdockerで完結してしまうのはとても便利です。

## 参考

■ [chrome 起動オプション](http://chrome.half-moon.org/43.html#c776272a)
■ [【Python】Seleniumでiframeの内容を操作する](https://kazusa-pg.com/python-selenium-iframe/)
■ [Chrome DevToolsを使いこなそう！ Web開発に必須なブラウザ開発ツールによるデバッグの基本](https://employment.en-japan.com/engineerhub/entry/2017/05/30/110000)
Djangoがアプリケーション下のtemplatesを検索してくれない

ほんとうにどうでもいいことなんだけどよく忘れるのでメモ。

Python 3.5.2
Django 2.2.9
Ubuntu 16.04.6 LTS (Xenial Xerus)



Djangoにアプリケーション下のtemplatesを探してもらうにはsettings.pyの```TEMPLATES```で```APP_DIRS```がTrueだけではだめなんです。
```INSTALLED_APPS``` に自分自身を追加する必要があります。


settings.py

```python

INSTALLED_APPS = [
    'testapp',  #自分自身
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]


TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },

```
Djangoでbitflyerの収支管理アプリを作ってみる（設計編）

今年はあまりbotを稼働させられず、収支は微プラスで終了となりました。
来年からは、稼働とロットを上げて収益を伸ばして行きたいと考えているのですが、勝率や取引回数あたりの期待収支、積み重なった手数料などを一目できる画面を作りたいなぁ…と思い至りました。

そこで、実務でも使ってるしDjangoで作ってみれば勉強にもなってちょうどいいんじゃね？という~~浅はかな~~考えで、年末年始を使って取り組んでみることにします。

必要な画面は6個。

```1.ログイン画面。(login.html)

ID入力フィールド
メールアドレス前提だと、英数と記号は-_@ぐらいっすかね。

パスワード入力フィールド
大文字小文字、数字、記号から「3種類以上組み合わせて8文字」とかそんな感じで。

「ログイン」ボタンも必要っすね。
ログインボタンが押されたら、入力されたIDをキーにデータベースを検索。
ヒットしたら、パスワードをIDに紐づくパスワードと入力されたパスワードを比較。

フィールドが空白の場合、文字数長を満たさない場合などは
ログインボタンが押されてもデータベースを見に行かず
バリデーションチェックで弾きましょう。

入力されたIDがデータベースから見つからない場合はログイン失敗。
パスワードが相違している場合もログイン失敗。

ログイン成功時はダッシュボード画面に遷移。
ログイン失敗時は「フィールドの入力内容を保持したまま」で、「IDかパスワードが間違っています」ぐらい表示しましょう。

また、ユーザー情報新規登録画面へのリンクも貼ります。
```

データベースについては次の「ユーザー情報新規登録画面」で考えます。

```2.ユーザー情報新規登録画面。(registration.html)
ログインユーザーの情報とAPIキーを登録する画面です。
（今回は変更、削除の画面は作りません）

登録情報を格納するデータベースが必要ですね。
ユーザーID、パスワード、APIキーとAPI Secretはすべてユーザーと紐づくので
[users]という名前のテーブルを作ってやれば良いでしょう。
id
user_name
password
api_key
api_secret

こんなもんでしょうか。
```

Djangoでは、データベースにテーブルを作るのではなく
プロジェクトにデータベースにかかわるコードを書いておくことで
データベースにテーブルを自動生成してくれる…という仕組み。
このあたりの操作を通して、「モデル」の概念に対する理解を深めておきたいところ。

```3.ダッシュボード画面。(dashboard.html)
ログインしたら飛んでくる画面。

左上に「現在の累計収支」を表示。
左下に「現在の資産情報」を表示。
どちらもLightningと現物、日本円それぞれの情報を一目できるように。

右側は縦ぶち抜きで「取引履歴」を表示。
bitflyerは両建てできないので、在庫ゼロになったところを「決済完了」として表示しましょうか。

それぞれの表示領域をクリックすると「収支確認画面」「資産情報確認画面」「取引履歴確認画面」に遷移。
ログアウト用のボタンも付けましょう。
```
これらに必要な情報はbitflyerのAPIを叩けば取得できるので、さくさく実装できる予定。
bot作るときにAPIは全部叩いたし、ドキュメントもわりとまじめに読んだし。

```4.収支確認画面。(balance.html)
現在の収支を数字で表示。
過去の収支変動を「グラフで」表示。
グラフに表示する期間とか選択できるとかっこいいですね。
わぁ大変そう。
```

```5.資産情報画面。(funds.html)
現在の資産を数字で表示。
過去の資産変動を「グラフで」表示。
グラフに表示する期間とか選択できるとかっこいいですね。
わぁ大変そう。
```

```6.取引履歴確認画面。(result.html)
過去の取引履歴を表示。
日時、注文金額、約定金額、手数料、レバレッジetc
期間指定して絞り込みする機能を付ける。
絞り込み前、絞り込み後どちらもCSV出力をできるようにする。
もちろん確定申告用。
```

※確定申告するほど勝ってないです。

タスクを順に並べて行くと、こんな感じでしょうか。

01.URLマッピングを作成する。
02.ログイン画面を作る。
03.ユーザー情報新規登録画面を作る。
04.ダッシュボード画面を作成する。
05.ログイン画面からユーザー情報新規登録画面に遷移できることを確認する。
06.モデルを作成する。
07.ユーザー情報新規登録画面からデータが登録できることを確認する。
08.項番07で作成した情報を用いて、ログイン画面からログインできることを確認する。
09.ログイン後にダッシュボード画面に遷移することを確認する。
10.収支確認画面を作成する。
11.ダッシュボード画面から収支確認画面に遷移できることを確認する。
12.資産情報画面を作成する。
13.ダッシュボード画面から資産情報画面に遷移できることを確認する。
14.取引履歴画面を作成する。
15.ダッシュボード画面から取引履歴画面に遷移できることを確認する。
16.取引履歴画面の期間絞り込み機能を実装する。
17.取引履歴画面のCSV出力機能を実装する。
18.動作確認を行う。

グラフは余力があったらやる。

続きは明日から！
Google Cloud Functionsを使ったおうむ返しLINE botの作成

goでLINE Botを作成しようと思い、まず初めにLINE APIのサンプルでも紹介されているおうむ返しをするLINE Botを作成する。
BotということでLINEの[messagingAPI](https://developers.line.biz/ja/reference/messaging-api/)を利用。

今回作成したBotのGitHubは[こちら](https://github.com/Hiroya3/LINE_Bot_parrot_return)

# 作成方法

## 1, チャネルの作成
LINE messagingAPIを利用するためにチャネルを作成したければならない。
チャネルとは、[LINE Developers](https://developers.line.biz/ja/docs/messaging-api/getting-started/)によると

>チャネルは、LINEプラットフォームが提供する機能を、プロバイダーが開発するサービスで利用するための通信路です。LINEプラットフォームを利用するには、チャネルを作成し、サービスをチャネルに関連付けます。チャネルを作成するには、名前、説明文、およびアイコン画像が必要です。チャネルを作成すると、固有のチャネルIDが識別用に発行されます。

となっており、プロバイダー（開発組織）とAPIとかの機能を紐付けるもので
チャネルによって紐付けられた機能が利用できるようになる。

チャネルの作成方法はLINE Developersで出ているので[そちら](https://developers.line.biz/ja/docs/messaging-api/getting-started/)を参考にした方がいいです。

今回はBotを作成するので **channel Typeはmessaging API** を選択してください。

## 2,CHANNEL_SECRET＆CHANNEL_TOKENの入力
[対象のgitHub](https://github.com/Hiroya3/LINE_Bot_parrot_return)を下記のコマンドでcloneしてください。

```
$ cd {cloneするディレクトリ}
$ git clone https://github.com/Hiroya3/LINE_Bot_parrot_return.git
```

その後、server.goの

```
bot, err := linebot.New(
  "CHANNEL_SECRET",
  "CHANNEL_TOKEN",
)
```

の `CHANNEL_SECRET` , `CHANNEL_TOKEN` の部分にそれぞれ
CHANNEL_SECRET : チェネル基本設定>チャネルシークレット 
CHANNEL_TOKEN  : Messaging API設定>チャネルアクセストークン（ロングターム）
を入力。

## 3,Cloud Functionsの作成
Cloud Functionsの[Console を使用したクイックスタート](https://cloud.google.com/functions/docs/quickstart-console?hl=ja)の **始める前に** を参照し、Cloud Functionsを作成する。

## 4,Cloud Functionsへデプロイ
### デプロイ時の注意点
#### ①go.modが必要
Goではcloud Functionsへのdeployには対象のソースコード以外にも `go.mod` （と `go.sum` ）ファイルも必要となっている。
参考：[Go での依存関係の指定](https://cloud.google.com/functions/docs/writing/specifying-dependencies-go?hl=ja)

今回のGitHubには既に入っているため、 **作成する必要はない** が作成する場合は[こちらを参照](https://cloud.google.com/functions/docs/writing/specifying-dependencies-go?hl=ja)

#### ②goの関数名は大文字始まり
私が躓いたところでもありますが、 **関数名は大文字始まり** にし他パッケージからの参照を可能とします。

#### ③基本的にfunction名は関数名と同じ
[ローカルマシンからのデプロイ](https://cloud.google.com/functions/docs/deploying/filesystem?hl=ja)に記載があるように `-entry-point フラグを指定しない限り、コードに同じ名前の関数を含める必要があります。` 

### デプロイ
以下のコマンドでデプロイし、cloud console上に `Omubot` というfunctionが作成されたことを確認する。
また、コンソール上に表示される `httpsTrigger: url:` はメモしておく。
（5,Webhookの設定で使います）
※gcloudコマンドがセットアップされていない場合は[こちら](https://cloud.google.com/sdk/docs/?hl=ja)を参照

```
gcloud functions deploy Omubot --runtime go111 --trigger-http
```

--runtime : goの実行バージョン
--trigger : トリガーの種類

## 5,Webhookの設定
最後にcloud functionsに登録された関数をLINE Developer内の１で作成したチャネルに設定する。
設定は[こちら](https://developers.line.biz/ja/docs/messaging-api/building-bot/)を参照。

設定するURLはデプロイ時に表示される httpsTrigger: url:
fish-shellのワイルドカード

# fishのワイルドカード
"*"によるワイルドカードに対応している.



```shell
> ls -la *-*.txt
-rw-r--r--  1 e155755  staff    969  4 19  2017 2017-04-19.txt
-rw-r--r--  1 e155755  staff   1569  4 20  2017 2017-04-20.txt
-rw-r--r--  1 e155755  staff   4225  4 27  2017 2017-04-26.txt
-rw-r--r--  1 e155755  staff  11943  4 27  2017 2017-04-27.txt
-rw-r--r--@ 1 e155755  staff    238  5  2  2017 2017-05-02.txt
-rw-r--r--  1 e155755  staff      0  5  4  2017 2017-05-04.txt
-rw-r--r--@ 1 e155755  staff      1  5 18  2017 2017-05-17.txt
-rw-r--r--  1 e155755  staff   4337  6  6  2017 2017-06-06.txt
中略
-rw-r--r--  1 e155755  staff   4414  6 18  2019 2019-06-15.txt
-rw-r--r--  1 e155755  staff   7578  6 18  2019 2019-06-18.txt
-rw-r--r--  1 e155755  staff   2193  7 17 13:57 2019-07-17.txt
-rw-r--r--  1 e155755  staff      0  8 21 00:43 2019-08-21.txt
-rw-r--r--  1 e155755  staff    271 10  1 17:58 2019-10-01.txt
-rw-r--r--  1 e155755  staff   5043  7  9 09:39 LT用の草案-2019-07-09.txt
 
```


## "**"という技
"*"では一文字しかワイルドカードとして扱えない.
しかし,"**"を使えば,二文字以上のワイルドカードになる.

```shell
 ~/D/blog  ls -la  **.ipynb                                                                                                                                                        土 12/28 21:35:30 2019
-rw-r--r--  1 e155755  staff    39126  7 31  2017 Keras/CNN.ipynb
-rw-r--r--  1 e155755  staff     5667  7 31  2017 Keras/Inception v3.ipynb
-rw-r--r--  1 e155755  staff   201896  8 14  2017 Keras/Keras-MNIST/affine.ipynb
-rw-r--r--  1 e155755  staff   202679  7 31  2017 Keras/affine.ipynb
-rw-r--r--  1 e155755  staff   156336  7 31  2017 Keras/cifar10.ipynb
-rw-r--r--  1 e155755  staff    50772  7 31  2017 Keras/cifar10_cnn.ipynb
-rw-r--r--  1 e155755  staff     8687  7 30  2017 Keras/cifar10_original.ipynb
-rw-r--r--  1 e155755  staff  5796887  8 19  2017 Keras/facets/facets_dive/Dive_demo.ipynb
-rw-r--r--  1 e155755  staff    34039  8 19  2017 Keras/facets/facets_overview/Overview_demo.ipynb
-rw-r--r--  1 e155755  staff     9986 12 18  2018 リスト.ipynb
-rw-r--r--  1 e155755  staff     4436 12 14  2018 タプル.ipynb
-rw-r--r--  1 e155755  staff     5381 12 15  2018 イテレータ.ipynb

```

それ以外にも機能盛りだくさん

# 参考
fishチュートリアル
https://fishshell.com/docs/current/tutorial.html#tut_why_fish
ELP-USB100W05MT-DL36-J

ELP 720p HD 1.0megapixel 防犯カメラ 監視カメラ HDのUSBドームカメラ 防水 
CMOS センサ ミニドームウェブカメラ 赤... 
https://www.amazon.co.jp/dp/B017SP4TB0/
6000円弱でraspberryでmoitoonやmotioneye対応です(専用ドライバーなし)
![ダウンロード.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532249/de6a9581-b80c-2f6d-8994-a8e84c77b06e.jpeg)
GCP・AWS・Azureクラウドの帯域を計ってみた

#はじめに

- 計測したクラウド/リージョン
    - GCP　東京リージョン / オレゴンリージョン
    - AWS　東京リージョン / オレゴンリージョン
    - Azure　東京リージョン / カリフォルニア州

- 計測方法
    - iperf3を使ってクライアントPCから各クラウド間の帯域幅パフォーマンスを計測


## iperf3の利用方法

### 1.Windowsにiperf3インストール、クライアントモードで起動

- iperf公式サイトからWindows用zipファイル（iperf-3.1.3-win64.zip）をダウンロード。<br>
公式：https://iperf.fr/
- 解凍して適当なディレクトリに配置
- コマンドプロンプトを開き、クライアントモードで起動してサーバに接続します。

```
C:\iperf-3.1.3-win64>iperf3 -c
```


### 2.各クラウドインスタンスにiperf3インストール、サーバモードで起動

- 今回はCentOSでインスタンスを立てたのでyumでインストール

```
$ yum install iperf3
$ firewall-cmd --zone=public --add-port=5201/tcp --permanent
$ firewall-cmd --reload
```

- iperf3をサーバモードで起動<br>
デフォルトでは、ポート5201で待ち受け状態となります

```
$ iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
```

### 3.iperf3サーバに接続
- Windows側のコマンドプロンプトから各サーバーに接続コマンドを発行

```
#iperf3 -c [インスタンスのIPアドレス]

[ ID] Interval           Transfer     Bandwidth
[  4]   0.00-1.00   sec  26.2 MBytes   220 Mbits/sec
[  4]   1.00-2.00   sec  29.6 MBytes   249 Mbits/sec
[  4]   2.00-3.00   sec  28.0 MBytes   235 Mbits/sec
[  4]   3.00-4.00   sec  23.4 MBytes   196 Mbits/sec
[  4]   4.00-5.00   sec  23.6 MBytes   198 Mbits/sec
[  4]   5.00-6.00   sec  22.6 MBytes   190 Mbits/sec
[  4]   6.00-7.00   sec  30.5 MBytes   256 Mbits/sec
[  4]   7.00-8.00   sec  28.2 MBytes   237 Mbits/sec
[  4]   8.00-9.00   sec  28.5 MBytes   239 Mbits/sec
[  4]   9.00-10.00  sec  22.6 MBytes   190 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth
[  4]   0.00-10.00  sec   263 MBytes   221 Mbits/sec                  sender
[  4]   0.00-10.00  sec   263 MBytes   221 Mbits/sec                  receiver
```

### 5.計測結果


|リージョン  |GCP  |AWS  |Azure  |
|---|---|---|---|
|東京リージョン  |221  |94.4  |156  |
|西海岸リージョン  |12.6  |18.2  |6.29  |
単位：Mbits/sec

結果としては、GCPの東京リージョンが速く、AWSが最も遅いとういう結果になった
西海岸リージョンでは逆にAWSが速い


### 6.参考：iprefのその他コマンド

- コマンドのオプションは公式にも記載がありますので参考に<br>
https://iperf.fr/iperf-doc.php


### 7.参考：AWS,Azureのインスタンスにiprefインストール時エラーになった件

AWS（AWSLinux2）、Azure(Centos base7)にiperfをインストールしようとした際下記のようなエラーが出た

```
$ yum install iperf
読み込んだプラグイン:fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.jaist.ac.jp
 * extras: ftp.jaist.ac.jp
 * updates: ftp.jaist.ac.jp
```
EPELのリポジトリをyumに追加しないといけないとのことで

```
$ sudo rpm --import https://fedoraproject.org/static/0608B895.txt

$ sudo rpm -Uvh http://ftp.iij.ad.jp/pub/linux/fedora/epel/6/i386/epel-release-6-8.noarch.rpm
Retrieving http://ftp.iij.ad.jp/pub/linux/fedora/epel/6/i386/epel-release-6-8.noarch.rpm
Preparing...                ########################################### [100%]
   1:epel-release           ########################################### [100%]
```
これでiperfがインストール可能になりました。。
ReactでDOMにカスタムデータ属性を設定したい。

HTML5ではカスタムデータ属性が導入され`data-`という接頭辞をつければDOMに自由に属性値を入れる事が可能。

**Reactでも同じ事が可能です。**

ですが、今回`WOVN`という翻訳サービスを導入するにあたり指定のタグを一部の決められたDOMだけに埋め込む必要がありました。同社から`wovn-enable`とタグを入れる様に指示があり、DOMにそのまま埋め込んだのですが、それではレンダリングされた時にタグそのものが入らず、`wovn-enable=“true”`でもだめでした。そこで`data-`接頭辞をつけてみたらタグ自体は入るものの翻訳がされない、と全然うまくいかずに困っていたのですが、コールバックRefを使って見事に解決できたので記事にまとめました。

Reactで同じような問題でお悩みの方の助けになればと思います。

[WOVN.io](https://wovn.io/ja/)は、ウェブサイト・アプリを様々な言語に多言語化できるサービス。

まず、コールバックRefに関して。[React公式ドキュメント](https://ja.reactjs.org/docs/refs-and-the-dom.html#callback-refs)から抜粋。

> createRef() によって作成された ref 属性を渡す代わりに、関数を渡します。この関数は、引数として React コンポーネントのインスタンスまたは HTML DOM 要素を受け取ります。これを保持することで、他の場所からアクセスできます。

要は、`refコールバック`を使えば、 DOMに外からアクセスして制御ができるという事です。


公式ドキュメントに習い、こんな感じで実装しました。

DOMにコールバックRefを埋め込みます。

```
<p ref={this.setWovn}>
	hogehoge
</p>
```

constructorでコールバック関数を実行します。

```
constructor(props: Props) {
	this.setWovn = element => {
		if(element) element.setAttribute(‘wovn-enable’, ‘true’);
	}
}
```

これでばっちりタグに`wovn-enable=“true”`とカスタム属性値が入り、翻訳もきちんとされるようになりました。

最初は禁じ手のdocument.getElementBy…でやってしまおうかと思ってしまいましたが、公式ドキュメントに載ってるやり方なのでこれが間違い無いと思います。ただRefは使いすぎないとも書かれています。

Refを使う前にコンポーネントの階層のどこで状態を保持すべきかについて、よりしっかりと考えてみてください、との事です。
Pythonの文字列フォーマット

##format

### 辞書
```python
hoge = {'a': 'aa', 'b': 'bb'}
print('a is {a}\nb is {b}'.format(**hoge))
```
>```
a is aa
b is bb
```

### 左寄せ、中央寄せ、右寄せ

```python
hoge = {'a': 'left', 'b': 'center', 'c': 'right'}
print('left  : {a:<10}'.format(**hoge))
print('center: {b:^10}'.format(**hoge))
print('right : {c:>10}'.format(**hoge))
```
>```
left  : left
center:   center
right :      right
```

### 左寄せ、中央寄せ、右寄せ（0埋め）
```python
hoge = {'a': 'left', 'b': 'center', 'c': 'right'}
print('left  : {a:<010}'.format(**hoge))
print('center: {b:^010}'.format(**hoge))
print('right : {c:>010}'.format(**hoge))
```
>```
left  : left000000
center: 00center00
right : 00000right
```

### 左寄せ、中央寄せ、右寄せ（文字埋め）
```python
hoge = {'a': 'left', 'b': 'center', 'c': 'right'}
print('left  : {a:_<10}'.format(**hoge))
print('center: {b:_^10}'.format(**hoge))
print('right : {c:_>10}'.format(**hoge))
```
>```
left  : left______
center: __center__
right : _____right
```

### 桁区切り、小数点
```python
print('{:,}'.format(1234.5678))
print('{:,.1f}'.format(1234.5678))
print('{:,.2f}'.format(1234.5678))
print('{:,.3f}'.format(1234.5678))
print('{:,.4f}'.format(1234.5678))
print('{:,.5f}'.format(1234.5678))
```
>```
1,234.5678
1,234.6
1,234.57
1,234.568
1,234.5678
1,234.56780
```

## ｆ文字列

```python
a = 'aa'
b = 'bb'
print(f'a is {a}\nb is {b}')
```
>```
a is aa
b is bb
```
【Rails】Timecopはもういらない話


`travel_to`、`travel_back`を使えばいい。
時間を止める場合は、`freeze_time`。

```ruby
it do
  travel_to Time.zone.local(2019, 12, 1)
  expect(something).to ...
  travel_back
end
```

```ruby
before { travel_to(Time.current) }
after { travel_back }
```

# ドキュメント

https://api.rubyonrails.org/v5.2.4.3/classes/ActiveSupport/Testing/TimeHelpers.html
初心者によるプログラミング学習ログ 197日目

#100日チャレンジの197日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

197日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>197日目<br><br>udemyでjquery<br>メンターさんに提出した課題修正<a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a><a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1210656015487623168?ref_src=twsrc%5Etfw">December 27, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Raspberry Pi で .Net の MVC を作成

次のバージョンで確認しました。

```text
$ dotnet --version
6.0.302
```

プロジェクトの作成

```bash
mkdir Mvc01
cd Mvc01
dotnet new mvc
```

```text
$ dotnet new mvc
The template "ASP.NET Core Web App (Model-View-Controller)" was created successfully.
This template contains technologies from parties other than Microsoft, see https://aka.ms/aspnetcore/3.0-third-party-notices for details.

Processing post-creation actions...
Running 'dotnet restore' on /home/uchida/tmp/Mvc01/Mvc01.csproj...
  /home/uchida/tmp/Mvc01/Mvc01.csproj の復元が 504.67 ms で完了しました。

Restore succeeded.
```

次の２つのファイルを修正します。

１）　localhost 以外からもアクセスできるようにします。

```json:appsettings.Development.json
{
        "urls": "http://*:5000",
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}
```

2) 表示に日本語を入れてみます。

```html:Views/Home/Index.cshtml
{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
        <p> Hello Everybody!</p>
        <p> こんにちは</p>
</div>
```

コンパイルと実行

```bash
dotnet run
```

ブラウザーで　 http://host:5000/ にアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/0e3b8f30-58d8-fc1e-6073-98e0517a5cd4.png)
【Rails】正しいmany-to-manyテーブルの作り方

# 環境

- Rails 5.2.2

# やりたいこと

- `FistName`クラス（first_namesテーブル）と`LastName`クラス（last_namesテーブル）を`many-to-many`で繋ぐ`FullName`クラス（`full_names`テーブル）を作りたい。

# 手順

## rails g model の実行

```
rails generate model FullName first_name:references last_name:references
```

生成されるマイグレーションファイル

```ruby
class CreateFullNames < ActiveRecord::Migration[5.2]
  def change
    create_table :full_names do |t|
      t.references :first_name, foreign_key: true
      t.references :last_name, foreign_key: true

      t.timestamps
    end
  end
end
```

## マイグレーションファイルを編集

- `t.references`（`belongs_to`は`references`のalias）はindexも作成してくれます。
  - `foreign_key: true`があれば、外部キー制約もつけてくれます。
- `t.references`を使いつつ、中間テーブルでは、以下の通り変更します。
  - 複合キーでunique制約を張ります。(※1）
  - 上記のunique制約で`first_name_id`に対するindexも張られるため、`index: false`を指定します。(※2)
  - `last_name_id`に対するindexも不要であれば、`index: false`を指定します。

```ruby
class CreateFullNames < ActiveRecord::Migration[5.2]
  def change
    create_table :full_names do |t|
      t.references :first_name, foreign_key: true, null: false, index: false # (※2)
      t.references :last_name, foreign_key: true, null: false

      t.timestamps
    end

    add_index :full_names, [:first_name_id, :last_name_id], unique: true # （※1）
  end
end
```

## モデル

### マイグレーションを実行して生成される中間テーブルのモデル

```ruby:app/models/full_name.rb
class FullName < ApplicationRecord
  belongs_to :first_name
  belongs_to :last_name

  # DB レベルでは外部キー制約、複合ユニークインデックスが付いているため、以下の validates が無くても
  # 意図しないデータが保存されることはありません（なので、無くても大丈夫です）。
  # 但し、その場合 DB のエラーが返されます。
  # Rails のエラーを返したい時は、validates をつけましょう。
  # 但し、Rails の処理のほうが遅いはずなので、メッセージへのこだわりが無く、スピード重視の場合はここの validates は外してください。
  #
  # ※上記については、belongs_to のデフォルトで required: true となっているため、presence: true の validates については、
  #  Rails レベルで担保されそうです（エラー内容は validates ~ presence: true と belongs_to で異なるかもしれませんが）。
  validates :first_name_id, presence: true
  validates :last_name_id, presence: true
  validates :first_name_id, uniqueness: { scope: :last_name_id }
end
```

### その他のモデル
```ruby:app/models/first_name.rb
class FirstName < ApplicationRecord
  has_many :full_names, dependent: :destroy
  has_many :last_names, through: :full_names
end
```

```ruby:app/models/last_name.rb
class LastName < ApplicationRecord
  has_many :full_names, dependent: :destroy
  has_many :first_names, through: :full_names
end
```
ローカル開発環境の構築備忘録

# はじめに
こんにちは。zer0です。
Qiitaに投稿するのは久しぶりなのですがよろしくお願いします。
現在大学2年で情報系に通いながら12月からはインターンで開発やってます。

記事を書いた経緯としては、前述したとおり12月からインターンをしていてローカル開発環境を構築するという下準備がありました。ついでに自分で以前構築したローカル開発環境もブラッシュアップしようと思ってここ数日で色々学べたので備忘録としてまとめておきます。

（ちなみにインターン先でローカル開発環境構築したんですが、諸事情で来月から別企業にて助っ人的な立ち位置でWEBサイト作るのでせっかく環境作ったのがほぼパーになったというのもあります笑）
備忘録的な側面が強いので端折ってる部分も結構あります。ご了承ください。

## この記事の対象
・ 初めて環境を作るけど、コピペしたくない人
・ ドットインストールでローカル環境構築したけどさらに自分でも環境構築したい人
私自身も最初はドットインストールでローカル開発環境作った身ですが、レッスンの環境がだいぶ古いので少しなれたらググりながらやるといいと思います。

初めて作る人はドットインストールのローカル開発環境の構築のレッスンの最初のローカル開発環境とは何かという部分を視聴してからをオススメします。

##　環境
前置きが長くなりましたが、自分で以前構築した環境のブラッシュアップが主目的ですので環境は以下です。
・ Mac OS Mojave 10.14.6（Catalinaは未確認です）
・ VirtualBox 6.0.14
・ Vagrant 2.2.6

## 注意
※　VirtualBoxのバージョンが6.1.xだとVirtualBoxとVagrantのバージョンが対応してないとかでエラー出るので注意したほうがいいです。
（実際インターン先でWindows10、Vagrant2.2.6、VirtualBoxをトップページのやつを入れたらそうなりました）

VirtualBox　インストールのトップページは[これ](https://www.virtualbox.org/)ですが、これだともしかするとパーミッションエラーになるので、[こっち](https://www.virtualbox.org/wiki/Download_Old_Builds)で入れたほうがいいですね。

トップページから飛ぶ場合はDownload→下の方にVirtualBox older buildsというところがあるので6.0.xを入れましょう

Vagrantは普通にググって入れるだけでいいです。
ここまででVirtualBoxとVagrantが入りましたね。

##　いよいよ構築する
1. まずどこでもいいのでターミナルから環境を入れるディレクトリを作りましょう

```
mkdir ディレクトリ名
cd ディレクトリ名　で作ったディレクトリに移動
```

2 複数環境を入れる可能性がある人はもう1個ディレクトリをつくる
1をもう1回行い、そのディレクトリに移動

3 Boxをつくる
[ここ](http://www.vagrantbox.es/)からBoxをURLをコピーする
今回はCentOS7.0を使用しました。

```
vagrant box add [box_name] [URL]
```
box_nameは好きに決めてください

ここで**SSL certificate problem: self signed certificate in certificate chain**というエラーが出た人がいるかもしれません。

その場合は
[こちら](https://qiita.com/h-isota/items/9c45a5a3b3eefba7a24d)を参考にさせていただきました。

```
vagrant box add [box_name] [URL] -insecure
```
これでできると思います。

原因を調べてみるとセキュリティ関係らしいですが、私もよくわかりませんでした。

時間かかりますが**successfully added box [box_name]**と出れば成功です

4 Boxができているか確認する

```
vagrant box list
```
これで自分がURLで指定したものが入っていれば成功です

5 Vagrantfileを作る

vagrantfileは構成情報などが書かれています

```
vagrant init [box_name]
```

これで**A `Vagrantfile` has been placed in this directory.**と出たら成功です

ちなみにVagrantfileはRubyで書かれていますがそこまで難しくないのでRubyやってなくても多分大丈夫です。ipアドレスの重複がある場合はここで編集しておくことを勧めます。

6 仮想マシンの起動

```
vagrant up
```
いよいよ仮想マシンの起動です。時間がかかりますがこれで起動できると思います。
起動後に**vagrant status**とコマンドを叩いて**running**と出れば起動しています。

7 最後にssh接続すればローカル開発環境構築終了です。

```
vagrant ssh
```

お疲れ様でした。駆け足でしたが最初の構築部分さえできてしまえばあとはPHPなりRubyなりをインストールして使うことができます。

Vagrantの便利なコマンドは[こちら](https://qiita.com/oreo3@github/items/4054a4120ccc249676d9
)がわかりやすいかと思います。


##　参考
・　[vagrant box add centos/7 → SSL エラー](https://qiita.com/h-isota/items/9c45a5a3b3eefba7a24d)
・　[【まとめ】Vagrant コマンド一覧](https://qiita.com/oreo3@github/items/4054a4120ccc249676d9)

ありがとうございます。
「リファクタリング 第2版」Swiftでコーディング その3

# 9頁 第1章 amountFor関数
## Swift版 main.swift
データ生成、結果表示付き。

```swift
import Foundation

makeData()

func statement(invoice:Invoice, plays:Dictionary<String, Play>) -> String {
    var volumeCredits = 0
    var totalAmount = 0
    var result = "Statement for \(invoice.customer)\n"
    let format = NumberFormatter()
    format.numberStyle = .currency
    format.locale = Locale(identifier: "en_US")

    for perf in invoice.performances {
        let play = plays[perf.playID]!
        let thisAcmount = amountFor(perf: perf, play: play)

        volumeCredits += max(perf.audience - 30, 0)
        if "comedy" == play.type {
            volumeCredits += Int(perf.audience / 5)
        }
        result += "  \(play.name): " + format.string(from: NSNumber(value: thisAcmount / 100))! + " (\(perf.audience) seats)\n"
        totalAmount += thisAcmount
    }
    result += "Amount owed is " + format.string(from: NSNumber(value: totalAmount / 100))! + "\n"
    result += "You earned \(volumeCredits) credits\n"
    return result
}

func amountFor(perf:Performance, play:Play) -> Int {
    var result = 0

    switch play.type {
    case "tragedy":
        result = 40000
        if perf.audience > 30 {
            result += 1000 * (perf.audience - 30)
        }
    case "comedy":
        result = 30000
        if perf.audience > 20 {
            result += 10000 + 500 * (perf.audience - 20)
        }
        result += 300 * perf.audience
    default:
        print("error")
    }
    return result
}

let result = statement(invoice: invoices[0], plays: plays)
print(result)
```