OmniAICreator/Qiita-1.07M huggingface dataset:
DevOpsにおけるサービスシナリオ(初期リリース編)

私の文章ではDevOpsに関する専門用語はなるべく書かないようにしています。
理由はツールと同じで専門用語を使った事で出来ている気分になってしまうからです。
これからもなるべく平易な文章で書いていきますので、Qiitaの読者層には合わないかもしれませんがご理解ください。

##サービスシナリオって何？
サービスの提供は、企画・設計、開発、テスト、リリース、運用、トラブル対応、と言った各フェースが繰り返し行われて成り立っています。
これらを全部一つのチームで行えれば理想的ですが、現実は縦割りの業務に阻まれてしまいます。

>古い話ですが2000年ぐらいのころは、「自分で作ったシステムは自分で責任を持つ」と言うのが基本であったため、上記全てを1つのプロジェクトチームが行っていて、かつメンバー全員がそのシステムにプライドを持っていたため、DevOpsなんて言う概念がなくても成り立っていました。
>しかし、現在と比べると非常に小さなシステムであって、背後に大型計算機と言った大量の人員と金が使われている大規模システムが存在する上での話でした。

主に各チームが協力し合わなければならないのは、
- テスト
- リリース
- トラブル対応
です。
先日の記事でもトラブル対応のシナリオの話が出ましたが、他チームとの連携が必要な場合は、自分たちの行う作業を周知しなければならないので、作業シナリオを書くと言う作業が必要です。

これらの作業シナリオをここではサービスシナリオと言っています。

##初期リリース前に準備しておくもの
企画・設計、開発(単体テストや結合テストを含む)が終わった後、いよいよ運用を前提とした業務テストとリリースが行われます。
この業務テストではインフラから上位アプリケーションまで、関わった人、これから関わる人全てに影響するため、入念に準備をしなければいけません。
具体的には
- 事前確認内容
- 初期データ投入内容確認
- リリース作業
- 初期データ投入
- リリース後状態確認
- サービス正常系確認テスト
- サービス異常系確認テスト
- 負荷テスト
- 業務テスト
- 初期トラブル対応
- 切り戻し(作業中止)確認
- 初期データ再投入
- 稼働確認

と言った作業が行われるため、これら全ての作業をシナリオとして作成しておく必要があります。

とんでもなく面倒な作業ですが、ここで手を抜くとサービスリリース直後からトラブル対応で手が回らなくなり、やっつけ仕事での対応が増え、その後のフェーズに悪影響を残してしまう事になります。
また、ここでシナリオを作っておくと、障害発生時や次回のリリースが格段に楽になりますので、一番やりたくない作業ですが、時間と人員を割いて実行しましょう。

##厄介な切り戻し(作業中止)
上記の作業の中で事前準備が難しく、作業当日の判断も難しいのが切り戻し(作業中止)でしょう。
当然、予定していたリリースは遅れてしまいますし、各メンバーの再スケジュールも必要になります。
プロジェクトマネージャーの評価にも影響してきますし、判断を誤る可能性が高い内容です。

しかし、あらかじめ決めた条件やシナリオ通りに作業中止ができる、問題発生の可能性も含めてスケジュールを決められるのが優秀なマネージャーです。
上から言われた日に何とかリリースしないとと頑張って、無理矢理進めてしまう人は上司の評価は良いでしょうけど、その後全てのフェーズの担当者から恨まれることになります。
これが更に業務の分断とコミュニケーション不足を加速させることになります。

こう言う時はマネージャーだけに責任を押し付けないように、各チームもシナリオ通りに進まなかった場合ははっきりと中止を伝えて負担を減らしてあげることが、今後のDevOpsの各フェーズを上手く進めていける
要因となります。

##まとめ
簡単に初期リリースの話をまとめました。
初期リリースは作業量が多く大変ですが、サービス開始前ですのでまだまだ楽な方です。
今後はサービス中のシステム変更などが控えています。
いかにサービスを止めずに各チームが連携して作業を進められるのか、初期リリース時よりさらに難しい切り戻し判断ができるのか等、問題は山積みです。
Linux版VSCodeのbackground-coverが動作しないときの解決策

VSCodeに背景画像を設定できる拡張機能[background-cover](https://marketplace.visualstudio.com/items?itemName=manasxx.background-cover)が、Linuxで動作しないときの解決策です。

workbench.desktop.main.cssのアクセス権を変えるだけ。

```console
$ cd /usr/share/code/resources/app/out/vs/workbench
$ sudo chmod 666 workbench.desktop.main.css
```
上記はLinux Mintでの設定例ですが、
ディストリビューションによってディレクトリが異なるかもしれないので
適切なディレクトリを指定してください。

アップデートとかしたら再設定が必要だと思います。
herokuで環境変数を設定する方法２パターン

#herokuの環境変数を設定する方法は大きく分けて２つあります。
①ターミナルで登録
②heroku上で登録
<br>

##①ターミナルで登録
ターミナル上でherokuにログイン（ログイン済ならスルーでOKです）

```
heroku login --interactive
```

まず環境変数を確認

```
heroku config
```

追加したい環境変数を設定

```
heroku config:set ＜設定したいキーとバリューを入力＞

下記のようになります

heroku config:set RAILS_TEST_KEY='1111'
```

ちなみに２個以上も一気に登録可。

```
heroku config:set RAILS_TEST_KEY='1111' TEST_KEY='2222'
```

再度下記を入力して、設定されているか確認。

```
heroku config
```

もし間違えて消したい場合は下記を入力。

```
heroku config:unset RAILS_TEST_KEY='1111'
```


##②heroku上で確認



Herokuにログインする
https://dashboard.heroku.com/

対象アプリを選択し、Settingsタブをクリック
<img width="1435" alt="スクリーンショット 2020-08-08 13.20.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540447/3e2c2306-6a14-4407-e0e5-aa2f94142c40.png">
<img width="1440" alt="スクリーンショット 2020-08-08 13.22.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540447/d8850317-ec83-1a6d-dcc2-d27dfd95d639.png">
Config Var欄の「Reveal Config Vars」をクリック
<img width="1440" alt="スクリーンショット 2020-08-08 13.23.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540447/e0684621-6b21-f4b0-ad04-afac5866fc4b.png">

「KEY」と「VALUE」を入力して「Add」で保存
<img width="1439" alt="スクリーンショット 2020-08-08 13.24.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540447/250068e0-547f-e61e-d5cc-1bdda4f11d92.png">

以上です。
すぐ反映されるので、ターミナルでも「heroku config」で確認してみましょう。
正社員エンジニアからフリーランスエンジニアになるために行ったこと

2020年7月、正社員エンジニアからフリーランスエンジニアになりました。
それにあたり行ったことなどをまとめておきます。
お役に立てば幸いです。

# プロフィール
- 年齢：30代後半
- 主な言語経験：Java 10年、PHP 1年強、JavaScript 1年強、Perl 半年

# きっかけ
- 成長が鈍ってきたように感じていた
- 収入を上げたかった

# 独立前
##### 情報収集(1〜2月)
主な情報源はYouTube。
勝又健太さんの[「雑食系エンジニアTV」の再生リスト「フリーランスエンジニア」](https://www.youtube.com/playlist?list=PLbX4sZSRPk6x1mNSpxF7zvJnozMcqdGVf)など。
フリーランスは比較的単価が高いことや、新しい技術を身に付けるために職場を変えていきやすいことなどを知る。

##### エージェント登録(3〜4月)、案件探し
まず一社登録してカウンセリングを受けたものの、コロナの影響で案件の数が減っていて、
参画のハードルが上がっているとのこと。
現時点でのスキルセットでは難しいと言われ、あきらめかける。

2週間後、別のエージェントに登録。
やはり参画のハードルは高くなっているとのことだったが、いくつか案件を紹介していただけた。
自分でも、一覧表にまとめながら案件を探す。

##### ポートフォリオ作成(5月)
現在、PHPではLaravelが使われている案件が多い。
しかし自分はLaravelを使った経験がないため、ポートフォリオを作ることにする。
どんなものを作ればいいのか参考にするため、勝又健太さんの[「雑食系エンジニアサロン」](https://kentakatsumata.net/archives/10)に入会。

##### 面談(5〜6月)
2社目で、Laravel、Vue.js、AWSなどのモダンな技術が使われている案件に参画決定。

##### 退職手続き
健康保険について、任意継続するか、脱退して国民健康保険に加入するか聞かれる。
国民健康保険の場合、扶養制度がないことなどから、任意継続を選択。

##### 事業用銀行口座用意
新しく口座を作ることも検討したが、既存の口座の一つを事業用として使うことにした。

##### 事業用クレジットカード作成
フリーランスになると正社員時代よりも借金をしづらくなるため
クレジットカードを作りにくくなるらしいので、事業用のクレジットカードを作成。

##### 名刺作成
[「アイボス名刺」](https://www.ibos.jp/)で作成。
名刺に記載するため、仕事用メールアドレスをGmailで取得。

# 独立後
##### 開業届提出
「[開業freee](https://www.freee.co.jp/kaigyou/)」で書類を作成し、税務署へ提出。
青色申告のための書類も同時に作成できる。

##### 年金切り替え手続き
区役所にて、厚生年金から国民年金への切り替え手続き。

##### 会計ソフト導入
「[会計freee](https://www.freee.co.jp/)」を使うことにする。
事業用のクレジットカード、銀行口座を登録しておくと、自動的に記帳してもらえる。

##### iDeCo変更手続き
証券会社から書類を取り寄せ、手続き。
【VBA】VBEでコードスニペットを扱う仕組み

# 概要

VisualBasicEditor(VBE) にはコードスニペットを扱う機能が搭載されていない。
インテリジェンスは効くが、よく使うまとまった構文を蓄えておいて
使いたいときにすぐ呼び出せるにはどうするか考えた結果、この方法に落ち着いた。

# スニペット呼び出し

イミディエイトウィンドウから対象のスニペット関数を実行し、
表示されたコードをエディターに貼り付けて使用する。

![9c5we-mvej8.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/fd4be5cf-13db-a78a-a191-073a28534165.gif)

# 仕組み

### スニペット用のモジュールにスニペット関数を作成する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/89f61113-b168-8344-e435-e55405efb045.png)

関数自体はシンプルで、`Debug.Print` でコードをイミディエイトに表示するだけ。
スニペット用の標準モジュールを作成してその中にまとめておく。
これを個人用マクロブックの **xlsb** にでも挿しておくと良い。

ポイントは関数の命名規則。

まず先頭はわかりやすく**SNI_**で統一している。
これによって、sni と入力後にCtrl+Spaceで一覧を表示できる。

<img width="323" alt="1_list表示.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/f9d44ef8-b1a7-afaf-a8ba-38bce3f046b8.png">

ここに表示されるのは関数名そのものなので、
関数名は内容がわかりやすいようにしておく。

次に、 **SNI_** に続く部分はカテゴリーを表記している。
対象とするオブジェクト名 **ListObject_** や、
プロシージャテンプレのようなものを入れておく **Proc_** など。

これによって多少の絞り込みができるようにしている。
特に使用頻度の高いものは **00_** などつけてリストの上位に出すようにしても良い。

<img width="316" alt="2_絞り込み.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/87b49ad6-b734-c16c-a87d-33a22343a23f.png">

### スニペット関数の作成と管理

スニペット関数を直接書いていくのは非常に大変である。

* すべての行を `Debug.Print ""` で囲む必要がある
* コード内のダブルクォーテーションをエスケープする必要がある
* モジュールの中に内包してしまうと管理ができなくなってしまう。

そのため、スニペットの管理と作成は専用のブック上で行っている。
カテゴリーと名称も分けておくことで個別の管理も問題ない。

<img width="1722" alt="3_管理票.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/81968654-c49c-4a0c-1fa7-81ba55c30c74.png">

素のコードからスニペット関数化を作成する部分と、
スニペットモジュールに反映する処理は自動化している。
kotlinでJSONObjectを簡単作成

kotlinで、変数から `JSONObject` を作成したかったのですが、 まずはオブジェクト作って〜とかputして〜とか面倒だったのでパーサーを作りました。
自分用ですが、忘れないように残しておきます。

# パーサー作成

```kotlin:JsonObjectBuilder.kt
internal fun json(build: JsonObjectBuilder.() -> Unit): JSONObject {
    return JsonObjectBuilder().json(build)
}

internal class JsonObjectBuilder {
    private val deque: Deque<JSONObject> = ArrayDeque()

    fun json(build: JsonObjectBuilder.() -> Unit): JSONObject {
        deque.push(JSONObject())
        this.build()
        return deque.pop()
    }

    @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
    infix fun <T> String.to(value: T) {
        deque.peek().put(this, value ?: JSONObject.NULL)
    }
}
```

# 使用例

```kotlin

fun parseSample() {
    
    // こんな感じでJSONObjectを作成できます
    val jsonObject = json {
        "str" to "hoge"
        "int" to 123
        "null" to null
    }

    // 文字列にしたい場合は、普通にtoString()
    val jsonString = jsonObject.toString();

    // ネストしたJSONObjectはこんな感じ
    val nestedJsonObject = json {
        "hoge" to "hoge"
        "nestObj" to json {
            "fuga" to "fuga"
        }
    }

    // JSONArrayが作りたい場合はputしていってください
    val jsonArray = JSONArray()
    val list = listOf(1, 2, 3)
    list.forEach {
        val jsonObject = json {
             "num" to it
        }
        jsonArray.put(jsonObject)
    }
}

```
slack投稿時のメッセージの書式設定まとめメモ


slackbotでの書式設定変更投稿のメモ。


## テキストを**太字**にする

→アスタリスク(*)で囲む

```
*こんにちわ*
```

**こんにちわ**


## テキストを*斜体*に変える

→アンダースコア(_)で囲む

```
_こんにちわ_
```

*こんにちわ*

## 取り消し線をつける

→チルダ(~)で囲む

```
~こんにちわ~
```

~~こんにちわ~~

## インラインコード（赤文字）

→バッククォート１つ(`)で囲む

```
`こんにちわ`
```

<img width="120" alt="&#x60;こんにちわ&#x60;.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242038/daa06c6f-7767-6984-a770-a64983526917.png">

## インラインコード

→バッククォート３つ(```)で囲む

```
```こんにちわ```
```

<img width="130" alt="&#x60;&#x60;&#x60;こんにちわ&#x60;&#x60;&#x60;.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242038/7eeb65c7-7e83-dcab-a1f1-11adc4bae475.png">



## 引用タグ

文字列の先頭に大なり(>)をつける

```
>こんにちわ
```

>こんにちわ

## リスト

→文字列の文頭に「1」とピリオドを入力 (1.) し、スペースを入れる

```
1. こんにちわ
2. こんばんわ
3. おやすみなさい
```

1. こんにちわ
2. こんばんわ
3. おやすみなさい


## リンクを貼る

→< URL | 文字列 >のようにする

```
<https://qiita.com/|ここをクリック>
```

[ここをクリック](https://qiita.com/)

気づいたのは最近なのですが、文字などにリンクを張れるようになったおかげで、slack投稿時のメッセージをスマートに表記できるようになったのは非常にありがたいです。
Node.js + JavaScript で HTTP リダイレクト先の URL を取得する

## 概要

- Node.js + JavaScript で HTTP リダイレクト先の URL を取得する
- 動作確認環境: Node.js 14.7.0 + macOS Catalina

## ソースコード

get_redirect.js というファイル名で以下の内容を保存する。

```get_redirect.js
'use strict'

const https = require('https')
const http  = require('http')

// リダイレクト先 URL を取得する関数
function get_redirect_url(src_url) {
  return new Promise((resolve, reject) => {
    try {
      // https と http で使うモジュールを変える
      const client = src_url.startsWith('https') ? https : http
      // 4xx や 5xx ではエラーが発生しないので注意
      client.get(src_url, (res) => {
        // HTTP レスポンスから Location ヘッダを取得 (ヘッダ名は小文字)
        resolve(res.headers['location'])
      }).on('error', (err) => {
        reject(err)
      })
    } catch(err) {
      reject(err)
    }
  })
}

(async () => {

  // コマンドライン引数を取得
  const src_url = process.argv[2]

  // リダイレクト先URLを取得
  const redirect_url = await get_redirect_url(src_url)
    .catch(err => {
      console.log(err)
    })

  // リダイレクト先URLを出力
  if (redirect_url) {
    console.log(redirect_url)
  }
})()
```

実行例。

```
$ node get_redirect.js https://bit.ly/3kmTOkc
https://t.co/yITSBp4ino
```

```
$ node get_redirect.js https://t.co/yITSBp4ino
https://qiita.com/niwasawa
```

```
$ node get_redirect.js https://qiita.com/niwasawa
```

## 参考資料

- [HTTPS \| Node\.js v14\.7\.0 Documentation](https://nodejs.org/dist/v14.7.0/docs/api/https.html)
- [HTTP \| Node\.js v14\.7\.0 Documentation](https://nodejs.org/dist/v14.7.0/docs/api/http.html)
- [HTTP のリダイレクト \- HTTP \| MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Redirections)
- [Location \- HTTP \| MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Location)
WireGuardでRaspberryPiにVPNを実装する方法

#目標
RaspberryPiを使って外出先から自宅のLANに接続できるようにVPNのサーバーを作る。nuro光を使っており、めったにグローバルIPアドレスが変更されないのでグローバルIPアドレスの固定化は行わない。クライアントはWindowsとiOSを想定しますが、macOSでもubuntuでも設定ファイルの読み込み以外は特に違いはないと思います。ルーター側でポートマッピング（ポート開放）をする必要があります。その方法についてはルーターによって異なるためサポートできません。方法がわかっている方のみ以下の手順でwireguardをセットアップしてください。
#手順
##インストール
```
$ sudo apt update
$ sudo apt upgrade
# RaspberryPiの場合
$ curl -L https://install.pivpn.io | bash
# debian系の場合
$ sudo apt install wireguard
```
##設定に必要なパラメータの値を取得する
###認証鍵を作る
####サーバー用のカギを作る
```
# 秘密鍵を作る
$ wg genkey | sudo tee /etc/wireguard/server.key
$ sudo chmod 600 /etc/wireguard/server.key

# 秘密鍵から公開鍵を生成して保存する。
$ sudo cat /etc/wireguard/server.key | wg pubkey | sudo tee /etc/wireguard/server.pub
$ sudo chmod 600 /etc/wireguard/server.pub
```

####クライアント用のカギを作る
```
# 秘密鍵を作る
$ wg genkey | sudo tee /etc/wireguard/client.key
$ sudo chmod 600 /etc/wireguard/client.key

# 秘密鍵から公開鍵を生成して保存する。
$ sudo cat /etc/wireguard/server.key | wg pubkey | sudo tee /etc/wireguard/client.pub
$ sudo chmod 600 /etc/wireguard/client.pub
```

###サーバー側のグローバルipアドレスを確認する
```
$ curl inet-ip.info
```

###サーバー側のローカルipアドレスを確認する
```
$ ip addr show
```

- Lanケーブルが繋がっている場合はeth0のinetの行のipアドレスがサーバーのプライベートipアドレスです。例( inet 192.168.1.16←これ  netmask 255.255.255.0  broadcast 192.168.1.255)
- Wi-Fiを使っている場合はwlanのipアドレスがサーバーのプライベートアドレスです。

##設定ファイルを編集する。
###サーバー側の設定ファイル

```
$ vim /etc/wireguard/wg0.conf

[Interface]
PrivateKey = サーバー側の秘密鍵
Address = 10.0.0.1/24
ListenPort = 50002
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = クライアント側の公開鍵
AllowedIPs = 10.0.0.2/32

```

###ユーザー側の設定ファイル

```
クライアント側メモ帳

[Interface]
PrivateKey = ユーザー側の秘密鍵
Address = 10.0.0.2/32
DNS = サーバー側のLANのDNSのipアドレス(デフォルトゲートウェイのipアドレスであることが多いです。)

[Peer]
PublicKey = サーバー側の公開鍵
AllowedIPs = 0.0.0.0/0
Endpoint = サーバー側のグローバルipアドレス:50002
```

##サーバー側のwireguardの起動
```
$ sudo systemctl enable wg-quick@wg0
$ sudo systemctl start wg-quick@wg0

# 起動の確認 wg0が追加されているかを確認する。
$ ip addr show
$ sudo wg
```
###ポートマッピング(ポート開放)をする
サーバー側プライベートipアドレスの50002番に設定をする。

##クライアント側(windows)のwireguardの起動
[WireGuardインストーラーダウンロードサイト](https://www.wireguard.com/install/)の自分のOSを選択してダウンロードし、実行してインストールする。先ほど作った設定ファイルをインポートして実行する。

サーバーとは異なるネットワークから[グローバルipアドレス確認サイト](http://inet-ip.info/)にアクセスして、サーバー側のグローバルipアドレスが表示されていれば繋がっている。

#参考資料
[wireguard公式サイト](https://www.wireguard.com)
[技術評論社　Ubuntu Weekly Recipe 第614回　WireGuardでVPNサーバーを構築する](https://gihyo.jp/admin/serial/01/ubuntu-recipe/0614?page=1)
[WireGuard VPN の利用](https://ma-tech.centurysys.jp/doku.php?id=mae3xx_ope:use_wireguard_vpn:start)
【JavaScript】数値範囲による分岐

#前置き

ふと、数値の範囲で分岐させるのって面倒だったなぁと思い返したはいいけど、どう書いていたがすぐ思い出せなかったので自分用に記載。

コードはよくありそうな年代別の分岐。

#コード

```javascript:
const getGeneration = age => {
	if (!Number.isFinite(age)) return console.error('数値以外が入力');
	if (age<0) return console.error('0歳未満？');
	if (age<12) return console.log('12歳未満');
	if (age<20) return console.log('12歳～19歳');
	if (age<30) return console.log('20歳代');
	if (age<40) return console.log('30歳代');
	if (age<50) return console.log('40歳代');
	if (age<60) return console.log('50歳代');
	if (age<70) return console.log('60歳代');
	if (age<80) return console.log('70歳代');
	if (age<100) return console.log('80歳以上');
	if (age<120) return console.log('100歳以上');
	return console.log('120歳以上');
};

getGeneration(-1);		// => 0歳未満？
getGeneration('14');	// => 数値以外が入力
getGeneration(14);		// => 12歳～19歳
getGeneration(200);		// => 120歳以上
```

Number.isFinite()の行は、数値以外の入力が絶対にない状態なら削除OK。

#最後に

もっとスマートな書き方はないものか…
【学習メモ】Docker（Docker運用の流れ、Linux操作、コマンド操作の基本）

#なぜDockerを採用するのか？
**コンテナ1つ作れば、テスト環境・本番環境もコンテナ起動でOKになるから**

Dockerなしの場合
**1回1回、テスト・開発・本番環境ごとにインストーラをダウンロード、起動、エラー修正しなきゃいけない**

しかもチーム開発だと、**全く同じバージョンの同じアプリで同じ挙動をしないといけないため大変**

#Linuxについて
・Linuxのコンテナ技術を利用するので、Linuxの知識が必要
・Linux：Unixをベースに1から作ったオープンソースのOS
**・ターミナルでは、Shellを仲介してKernelに命令を出している**
・Shell：bazh,zsh,shなど
・Shellを起動するために必要なアプリがターミナルであって、**Shell＝ターミナルではない**

#Dockerを使ってみる
**運用の流れ**
・Docker imageを管理するDockerHubから自分のhostに、Docker imageを持ってくる
・Docker imageをbashでコンテナ起動
・コンテナでの作業が終わったらexitかdetach
・Hostに戻ったときに、現在のコンテナの状況をps-a、imagesで確認
・exit状態にあるコンテナを再起動
・コンテナをcommitして新しいimageを作成する（＝更新内容をDocker imageにする）
・DockerHubにアップする際、**リポジトリ名と一致する必要があるので**、古いimageを新しいimage名に変更する
・その後保存したDocker imageをDockerHubにpushする
※タグ＝バージョン管理

#コマンド操作の例
```
$ docker login                    　#Dockerにログイン
$ docker pull <image>             　#DockerHubからDocker imageを出力
$ docker run -it <image> bash     　#bashはshell。そのDocker imageでコンテナ起動
$ exit                            　#コンテナでの作業を終了
$ docker ps-a　                　　　#Dockerコンテナ一覧を確認
$ docker images       　　　　  　　　#Docker images一覧を確認
$ docker restart             　　　　#Dockerを再起動
$ docker exec -it <container> bash　#特定のコンテナで作業開始
$ docker commit <container><image>  #特定のコンテナの変更をDocker imageに反映
$ docker tag <source> <target>    　#Docker imageの名前を変更
$ docker push <image>             　#Docker imageをリポジトリにpush
$ docker rmi <image>              　#Docker imageを削除
```

#参考
[米国AI開発者がゼロから教えるDocker講座](https://www.udemy.com/course/aidocker/learn/lecture/20294807#content)
PCが重いとき、起動中のVagrantを一括確認してhaltする


複数のvagrantを立ち上げてると重くなりがちなMy貧弱PC。

ディレクトリを移動しながら、起動中かどうか確認して回るのは面倒だと思っていましたが、最近一発で確認できると知りました。

```
vagrant global-status
```

power off

```
vagrant halt {id}
```

もう使わないならdestroy

```
vagrnat destroy {id}
```
Django3チュートリアル準備

#Django3の環境構築をdockerで行う

##環境構築
[Django3.0の開発環境をDocker,Docker-compose,Poetryで作ってみた](https://qiita.com/k4ssyi/items/b8d1355fed43b526aee1)
上記の記事がシンプルで分かりやすかったので、参考にしました。
私の環境では下記のディレクトリー 構造となりました。
Makefileは私が作成したものです。
記事の最後に載せてあります。

```
.
├── Dockerfile
├── docker-compose.yml
├── Makefile
└── src
    ├── manage.py
    ├── project
    ├── pyproject.toml
    └── poetry.lock
```

##git管理する




```
//git config でユーザー名と設定
git config --global user.email "xxx.yyy@example"
git config --global user.name "password"

//git hubでリポジトリの作成後リモートリポジトリの追加をします。
git remote add origin [remote repository PATH]

//git pullを実行し設定終了
git pull
```

##.gitignore 作成
Djangoについて全くと言っていいほど理解しておらず【gitignore】に追加すべきファイルがわからなったので、gitignore.ioで作成
https://www.toptal.com/developers/gitignore


##Makefile作成
dockerコマンドは長いので打つのが面倒なので、Makefileに記述しています。


```makefile
up:
	docker-compose up -d

build:
	docker-compose build --no-cache --force-rm

stop:
	docker-compose stop
down:
	docker-compose down

restart:
	@make down
	@make up
	
destroy:
	docker-compose down --rmi all --volumes

django:
	docker exec -it django3_django_1 bash
```



###参考にさせていただいた記事
[Django3.0の開発環境をDocker,Docker-compose,Poetryで作ってみた](https://qiita.com/k4ssyi/items/b8d1355fed43b526aee1)
[#django 用の .gitignore を一瞬で自動生成する](hhttps://qiita.com/YumaInaura/items/3907bb632f5f8564a871)
AWSとAzureの比較（リージョン・AZ）

※個人の調査によるものです。誤りがあればご指摘ください
※2020/8/8現在の情報をもとにまとめました。

AWSとAzureのリージョンなどの考え方を比較しました。

## AWS

| 分類レベル | 名称 | 定義 |
| --- | --- | --- |
| レベル小 | データセンター | 1つの物理的なデータセンター |
| レベル中 | アベイラビリティゾーン (AZ)  | 1 つの AWS リージョン内でそれぞれ切り離され、冗長的な電力源、ネットワーク、そして接続機能を備えている **1 つ以上のデータセンター**のことです。各 AZ はそれぞれ他の AZ から物理的に意味のある距離、つまり数キロメートル離れていますが、すべて 100 km 以内 (互いに 60 マイル) に配置されています。 |
| レベル大 | リージョン | 1 つの地理的エリアにある、**複数の、それぞれが隔離され物理的にも分離された AZ** によって構成されています。1 つのデータセンターを 1 つのリージョンとして定義することが多い他のクラウドプロバイダーとは違い、全 AWS リージョンが採用するこのマルチ AZ デザインは、お客様にいくつかのメリットをご提供するものです。 |

大阪ローカルリージョンは特殊で、

* 分離された耐障害性の高いインフラストラクチャデザインが 1 つのデータセンター内で構成されます。
* アジアパシフィック (大阪) ローカルリージョンは 1 つのアベイラビリティーゾーンで構成されており、アジアパシフィック (東京) リージョンと組み合わせて使用することが意図されています。
* このリージョンには、お客様のセールス担当者からのリクエストが必要です。

とのこと。

他にはLocal Zonesというものがあるようです。現在はロサンゼルスのみで提供されています。

https://aws.amazon.com/jp/about-aws/global-infrastructure/
https://aws.amazon.com/jp/about-aws/global-infrastructure/regional-product-services/
https://aws.amazon.com/jp/about-aws/global-infrastructure/regional-product-services/


## Azure

| 分類レベル | 名称 | 定義 |
| --- | --- | --- |
| 小 | Azure データセンター | ネットワークに接続されたコンピューター サーバーのグループを収容する、世界中に存在する**一意の物理的な建物**です。 |
| 中 | Azure Availability Zones | **Azure リージョン内の一意の物理的な場所**であり、データセンターの障害からアプリケーションとデータを保護する高可用性を提供しています。それぞれのゾーンは、独立した電源、冷却手段、ネットワークを備えた **1 つまたは複数のデータセンターで構成**されています。 |
| 大 | Azure リージョン | Azure リージョンは、待機時間で定義された境界内でデプロイされ、低遅延の専用リージョン ネットワークを使用して接続された一連のデータセンターです。 |
| 特大 | Azure 地域 | 通常、**1 つ以上のリージョンを含み**、データ所在地とコンプライアンスの境界を保持します。 |

AWSにはない、「地域」というものが出てきました。リージョンも地域のような気もしますが、英語名はAzure リージョンが**Azure region**で、Azure 地域が**Azure geography**です。
東日本リージョンと西日本リージョンはペアに指定されているようで、このAzure 地域に該当するようです。

ペアになっているリージョンのメリットとしては、以下が上げらててました
* 物理的な分離
* プラットフォームに備わっているレプリケーション
* リージョン復旧順序
* 順次更新
* データ所在地


https://azure.microsoft.com/ja-jp/global-infrastructure/
https://azure.microsoft.com/ja-jp/global-infrastructure/geographies/#geographies
https://docs.microsoft.com/ja-jp/azure/best-practices-availability-paired-regions

## 日本国内リージョンの比較

| 比較項目 | AWS東京リージョン | AWS大阪ローカルリージョン | Azure東日本リージョン | Azure西日本リージョン |
| --- | --- | --- | --- | --- |
| 開設時期 | 2011年 | 2018年 | 2014年 | 2014年 |
| AZ数 | 4 | 1 | 3 | 1 |

調べていると、AWS東京リージョンに4つ目のリージョンが開設されたのが、2018年、Azure東日本リージョンがAZに対応したのが2019年のようです。この間はAWS東京リージョンが4AZ、Azure東日本リージョンが1AZとかなりの差があったような形ですね。
また、AWS大阪ローカルリージョンは2021年初頭までに3つのAZをもつフルリージョンになるようです。

https://aws.amazon.com/jp/blogs/news/the-fourth-new-availability-zone-tokyo-region/
https://azure.microsoft.com/ja-jp/updates/general-availability-azure-availability-zones-in-japan-east/
https://aws.amazon.com/jp/blogs/news/in-the-works-aws-osaka-local-region-expansion-to-full-region/

## まとめ

AWS側のほうが知識があるので、AWS押しのような内容となりましたが、Azure側の押しポイントがあれば教えて下さい。
github-readme-statsがバグってる場合の治し方

# 前提
[github-readme-stats](https://github.com/anuraghazra/github-readme-stats)とは、プロフィールREADMEの中で自分のgithubのスタッツを表示してくれるものです。

[これ](https://github.com/s3pt3mb3r)は実際の僕の画面なんですが、この`S3pt3mb3r's GitHub Stats`および `Most Used Languages`という二つのカードをgithub-readme-statsで表示させています。
![image](https://user-images.githubusercontent.com/33578715/95545182-ba48b580-0a2f-11eb-94cd-80fb8bfd5089.png)


これ自体の導入方法は[この記事](https://qiita.com/zizi4n5/items/f8076cb25bbf64a9bc1c)で説明されているので知りたい方はご覧ください。

また、かなり雑に説明したので万が一躓いた方はコメントで教えてください。

# 本題
さて、github-readme-statsなんですが、この大元自体はVercelというサービス上で動いています。ですが、ここ最近このアプリが人気すぎてダウンしてしまったようです。そのため普通にurlを使って配置している方は現在は画像のような表記になっていると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143170/052275d5-8649-9b4d-ed1a-23f8e91a3547.png)

これの原因と対処法について[このissue](https://github.com/anuraghazra/github-readme-stats/issues/325)で製作者様が触れているのですが、英語がわからない人のために翻訳して書いておきますね。

ちなみにこれは今後も起こる可能性が高いと製作者様がおっしゃってるので、今後も使いたい方は以下の対処法を実行した方がいいです。

# 方法

**ざっくりいうと、「このプロジェクトを各自でforkしてVercel上にデプロイしてくれ」ってことです。**
簡単にできるので以下を参考に試してみてください。

## デプロイの方法

まず[このページ](https://vercel.com/signup)で、githubと連携してVercelのアカウントを作ってログインしてください。

![68747470733a2f2f66696c65732e636174626f782e6d6f652f62746437386a2e6a706567.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143170/13163922-550e-898a-9c29-f331cb55f70d.jpeg)


そのあと[本家のGitHubリポジトリ](https://github.com/anuraghazra/github-readme-stats)をforkしてください。

#### 追記(2022/2/21)
forkした後プロジェクトの`vercel.json`を編集し、maxDurationの値を10に変更してください。でないとビルドに失敗します。

そしたら[プロジェクトのインポート](https://vercel.com/import/git)へ飛んでもらって、ここにフォークしたプロジェクトのURLを入れてください。

```
https://github.com/あなたのgithubID/github-readme-stats
```

って感じです。

その後この画面で下のPERSONAL ACCOUNTを選択してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143170/efef251a-7325-8dab-ef88-2d2bbc057b88.png)

その後以下の画像のページが出るまでは適当にOKを押していただいて問題ないです。
この画面ではgithubのアクセストークンを環境変数に登録する作業が必要です。

![68747470733a2f2f66696c65732e636174626f782e6d6f652f30657a3467372e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143170/575250c6-99cf-8aae-1680-097474ada26f.png)

上の画像のように、NAMEに`PAT_1`と入力してください。VALUEですが、[ここ](https://github.com/settings/tokens/new)でトークンを作る必要があります。権限などはそのままでいいので、トークンの名前だけ適当に入力して作ってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143170/0369a764-a2de-983c-4c9d-1be07d950fd7.png)

作ったら、Vercelに戻ってVALUEに生成されたトークンを入力し、`Add`ボタンを押してください。

その後右下のDeployボタンを押して、完了するまで待てばデプロイ完了です。

デプロイが完了しただけでは解決しません。エンドポイントが違うので、あなたのREADMEを書き換える必要があります。

## エンドポイントの確認

以下のYOURIDの部分をあなたのgithubIDに変えて、リンク先へ飛んでください。

```
https://vercel.com/YOURID/github-readme-stats/settings/domains
```

赤く線を引いた部分のURLをコピーして、あなたのREADMEにもとからあるURLの代わりに使いましょう。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143170/f0e78e6c-fc92-4ecb-d8cf-3ab99b5321a4.png)


以上で終わりです。うまくいっていればあなたのプロフィールは元通りになっているはずです :)
Ruby モジュールとは？

# モジュールとは？
モジュールとは、処理を1つにまとめたものである。  

```ruby
# 例：足し算、引き算の処理をまとめたCaluculateモジュール
module Calculate
  def add(a, b)
    a + b
  end

  def sub(a, b)
    a - b
  end
end
```

# モジュールとクラスの違い
モジュールとクラスは似ているが、以下のような違いがある。

* モジュールはインスタンスを作れない
* モジュールは継承できない
* クラスは処理とデータを持つが、モジュールは処理だけを持つ

# モジュールの用途
モジュールは以下のような用途で使用される。
## 名前空間の提供
同じクラスでも別の名前のモジュールの中に入れることで別のクラスとして使用することができる。

```ruby
# 例：同じImageクラスを別のモジュールに含めて違うクラス（User::ImageとPost::Image）として扱う
module User
  class Image
    def self.hoge
      puts 'user image'
    end
  end
end

module Post
  class Image
    def self.hoge
      puts 'post image'
    end
  end
end

User::Image.hoge #=> "user image"
Post::Image.hoge #=> "post image"
```
## クラスにインスタンスメソッドとして取り込む
includeメソッドを使用してモジュールの処理を対象のクラスのインスタンスメソッドとして取り込む事ができる。

```ruby
# 例：UserモジュールをImageクラスのインスタンスメソッドとして取り込む

module User
  def hoge
    puts 'user image'
  end
end

class Image
  include User
end

image = Image.new
image.hoge #=> "user image"
```

## クラスにクラスメソッドとして取り込む
extendメソッドを使用してモジュールの処理を対象のクラスのクラスメソッドとして取り込む事ができる。

```ruby
# 例：UserモジュールをImageクラスのクラスメソッドとして取り込む

module User
  def hoge
    puts 'user image'
  end
end

class Image
  extend User
end

Image.hoge #=> "user image"
```

# まとめ
* モジュールは処理をまとめたもの
* モジュールはクラスと違い、インスタンスの作成や継承はできない
* 名前空間の提供や、インスタンスメソッド・クラスメソッドとしてクラスに取り込むことができる
【ラズパイ】ディレクトリを継続的に監視して変更をフックで任意のシェルを走らせる方法

Raspberry Pi 3B(以下:ラズパイ)で、**指定ディレクトリ内を監視**して更新されたら任意の処理を走らせるという事をしたいと思います。

- フック : Aディレクトリに画像が保存される
- する事 : AディレクトリとBディレクトリの状態を同期

具体的には上記のような事をするために**inotify-tools**を使用しします。

## inotify-toolsのインストール

apt-getでインストールします。

```shell
$ sudo apt-get install inotify-tools
```


## inotyfywaitコマンドで監視

`inotyfywait -e 【イベント】 【監視するディレクトリ】`

inotfywaitコマンドで特定イベントと監視するディレクトリを指定します。
今回は`moved_to(対象ディレクトリ内へ移動された)`イベントの監視をして処理をさせます。

```inotify_single.sh
#!/bin/sh

inotifywait -m -e moved_to A | \
    rsync -rv A B
```

ryncコマンドを使ってAとBを同期させています。

### -mオプションについて

`-m`オプションをつけないとが初回のイベント発行でinotifywaitが終了してしまうので付けています。


## 継続的に監視する

このままだと一連のイベントが通知されると監視が終了してしまいますので処理を修正します。

```inotify_continuous.sh
#!/bin/sh

inotifywait -m -e moved_to A | \
    while read _; do
        rsync -rv A B
    done
```

このようにwhile文を使って継続的に監視するようにしています。

## 環境

- Raspberry Pi 3B
- Raspbian GNU/Linux 9.8 (stretch)
- inotifywait 3.14[^1]


[^1]: inotifywaitのバージョンは `inotifywait -hl`で確認できます



## 参考

- [inotify-toolsでファイルやディレクトリを監視する](https://qiita.com/stc1988/items/464410382f8425681c20)
D言語の配列コピーでの注意点

# はじめに
D言語には、静的配列と動的配列があります。
意識せずにコピー処理を行うと、想定外の結果となるため、注意が必要です。

# C言語の場合
C言語で配列をコピーする場合の実装例は、以下の通りかと思います。
コピー後、配列`t`の値を書き換えています。
結果として、配列`s`と配列`t`の値は異なっています。

```c:copysample.c
#include <stdio.h>
int main(void){
  int s[3] = { 1, 2, 3 };
  int t[3];
  
  // t = s とはできない
  memcpy(t,s,sizeof(s));
  printf("s = %d %d %d\n",s[0],s[1],s[2]);
  printf("t = %d %d %d\n",t[0],t[1],t[2]);
  
  t[1] = 4;
  printf("s = %d %d %d\n",s[0],s[1],s[2]);
  printf("t = %d %d %d\n",t[0],t[1],t[2]);
}
```
```txt:実行結果
s = 1 2 3
t = 1 2 3
s = 1 2 3
t = 1 4 3
```

# D言語の場合
D言語では、`t = s`を使ったコピーが可能ですが、静的配列と動的配列で実行結果が異なります。
int[3]は、静的配列です。先ほどのC言語の場合と同じ実行結果になります。

```d:copysample1.d
import std.stdio;
void main(){
  int[3] s = [ 1, 2, 3 ];
  int[3] t;
  
  t = s;
  writefln("s = %s",s);
  writefln("t = %s",t);
  
  t[1] = 4;
  writefln("s = %s",s);
  writefln("t = %s",t);
}
```
```txt:実行結果
s = [1, 2, 3]
t = [1, 2, 3]
s = [1, 2, 3]
t = [1, 4, 3]
```
`int[]`は、動的配列です。
先ほどとは実行結果が異なり、配列`s`と配列`t`の値が同じになっています。

```d:copysample2.d
import std.stdio;
void main(){
  int[] s = [ 1, 2, 3 ];
  int[] t;
  
  t = s;
  writefln("s = %s",s);
  writefln("t = %s",t);
  
  t[1] = 4;
  writefln("s = %s",s);
  writefln("t = %s",t);
}
```
```txt:実行結果
s = [1, 2, 3]
t = [1, 2, 3]
s = [1, 4, 3]
t = [1, 4, 3]
```

copysample1.dの静的配列では、**ディープコピー**、
copysample2.dの動的配列では、**シャローコピー**が行われています。[用語補足](https://hacknote.jp/archives/28270/)

では、動的配列をディープコピーしたい場合はどうすればいいのか。
D言語では、`.dup`というプロパティが用意されています。

```d:copysample3.d
import std.stdio;
void main(){
  int[] s = [ 1, 2, 3 ];
  int[] t;
  
  t = s.dup;
  writefln("s = %s",s);
  writefln("t = %s",t);
  
  t[1] = 4;
  writefln("s = %s",s);
  writefln("t = %s",t);
}
```
```txt:実行結果
s = [1, 2, 3]
t = [1, 2, 3]
s = [1, 2, 3]
t = [1, 4, 3]
```
# おまけの注意点

D言語には、もう1つ連想配列というものがあります。
連想配列のコピーは基本的に動的配列と同じですが、連想配列の要素がない空の状態でのコピーは`null`がセットされるだけで、シャローコピーにはならない点に注意です。
[D言語のサイト(英語)](https://dlang.org/spec/hash-map.html#construction_and_ref_semantic)

# 参考情報
他のプログラミング言語についてのリンク情報です。

https://eng-entrance.com/java-array-copy

https://futabooo.hatenablog.com/entry/20110811/1313073921

https://qiita.com/riotam/items/06850524450d882e2bd5

https://qiita.com/mojihige/items/7b0a36b595273e70812d

https://qiita.com/kokorinosoba/items/e9ab9398af5b44d2ac9a

https://qiita.com/niwasawa/items/55f662a5dd4cd72e5398
シーケンスコード、デシマルコード、ニモニックコード、ブロックコード

平成31年春期 午前問題24

コードの値からデータの対象物が連想できるものはどれか。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/c6c6e4a7-d320-16be-76ae-1fba195aa5f2.png)


１、ニモニックコード(Mnemonic Code)は、
表意コードとも言い、値から対象のデータが容易に連想できる英数字・記号の組合せをコードとして割り当てる方法です。他のコードよりも桁数が多くなりますが、利用者が記憶しやすい利点があり、商品番号や製品の型番としてよく使用されています。

例)
国名：日本→JP，アメリカ→US
色名：黒→BK，白→WH
プロジェクトマネージャ→PM　など

２、シーケンスコードは、
順番コードともいい、0001→0002→0003→…→9999 というように連続した値をデータに1つずつ割り当てていく方法です。

３、デシマルコードは、
10進コードとも言い、全てのデータを0～9の10グループに分割し、さらにグループごとに10個のサブグループに分割することを繰り返していく方法です。図書コード内の分類コードで使用されています。

デシマルコードとは人が認識できる英数字をHTMLコード化したものです。
例えばHTMLソース内で「&#64;」と記入するとブラウザ上では文字列「@」と表示されます。

４、ブロックコードは、
区分コードとも言い、営業部は1000～1999、企画部は2000～2999 というようにグループごとに定められた範囲内でコードを割り当てる方法です。上位けたを見ればどのグループに属しているのかがわかる特徴があります。

参考：
https://www.ap-siken.com/kakomon/27_aki/q24.html

デシマルコードとは
https://www.webolve.com/make/decimal/#:~:text=%E3%83%87%E3%82%B7%E3%83%9E%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89%E3%81%A8%E3%81%AF%E4%BA%BA,%40%E3%80%8D%E3%81%A8%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82
[SwiftUI]Buttonのカスタマイズ

SwiftUIでButtonのカスタマイズ方法を調べました。
カスタマイズ方法はUIKitのUIButtonとだいぶ違ったので、試行錯誤に時間がかかりました。

## どのようなボタンを作るか

- 背景が塗りつぶしで角丸
- シャドーがある
- ボタンを押した時のエフェクトをつける

## 作成したもの

|Playground|
|---|
|<img width="373" alt="スクリーンショット 2020-08-08 11.52.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297014/4cbed683-455d-20de-feb0-5eb6b0d73ba8.png">|

- １つ目：角丸の通常ボタン
- ２つ目：角丸の無効状態のボタン
- ３つ目：角丸が完全な丸のボタン

## 実装方法

SwiftUIの[ButtonStyle](https://developer.apple.com/documentation/swiftui/buttonstyle)を使います。
文字の内容・画像とそのpaddingについてはButtonStyleで共通化できませんでした。（paddingが共通化できないのはなんでだろう）

```CustomButtonStyle.swift
struct CustomButtonStyle: ButtonStyle {
    
    @State var isEnabled: Bool  //ボタン有効・無効
    var cornerRadius: CGFloat   //角丸半径
    var color: Color            //通常Color
    var disabledColor: Color    //無効Color
    var textColor: Color        //テキストcolor
    
    func makeBody(configuration: Configuration) -> some View {
        let isPressed = configuration.isPressed
        let foregroundColor = isEnabled ? color : disabledColor
        return configuration.label
            .background(RoundedRectangleFill.init(cornerRadius: cornerRadius, fillColor: foregroundColor))
            .foregroundColor(textColor)
            .shadow(color: foregroundColor, radius: 5, x: 0, y: 0)
            .scaleEffect(x: isPressed ? 0.95 : 1, y: isPressed ? 0.95 : 1, anchor: .center)
            .animation(.spring(response: 0.2, dampingFraction: 0.9, blendDuration: 0))
    }
    
}
```

細かい実装はソースを見てください。

- cornerRadiusに`.infinity`を設定すると、角丸が完全な丸になります。（スクショ３つ目のボタン）
- backgroundにRoundRectangleベースの角丸塗りつぶしを設定しています
- foregroundColorでテキスト・画像の色を設定しています
- shadowで影を描画しています
- scaleEffectとanimationでボタンを押した時のアニメーションを設定しています


## ソース

[こちら](https://gist.github.com/usk2000/bf5bcb172ca072e223dc191006da8cb2)に置いてあります。

## 参考
https://developer.apple.com/documentation/swiftui/buttonstyle
https://developer.apple.com/documentation/swiftui/primitivebuttonstyle
https://medium.com/better-programming/how-to-build-and-customize-buttons-in-swiftui-448f5994022d
https://qiita.com/muukii/items/46125dced6be51ddb736
https://stackoverflow.com/questions/59169436/swiftui-buttonstyle-how-to-check-if-button-is-disabled-or-enabled
https://will.townsend.io/2019/an-intro-to-swiftui-button-styles
【Rust】loopとwhile trueの違い

# `loop != while true`
意味的な違いはないと思われる`loop {...}`と`while true {...}`だが、変数制約チェックなどのパス解析では扱いが異なる。

```rust
// loopだとコンパイルできる
fn main() {
    let mut a = 1;
    let mut b = 2;
    let mut x = &mut a;
    println!("{}", x);

    loop {
        x = &mut b;
        break;
    }
    let y = &mut a;
    println!("{} {}", x, y);
}
```

```rust
// while trueだとコンパイルできない
fn main() {
    let mut a = 1;
    let mut b = 2;
    let mut x = &mut a;
    println!("{}", x);

    while true {
        x = &mut b;
        break;
    }
    let y = &mut a; // ERROR: second mutable borrow occurs here
    println!("{} {}", x, y);
}
```

`x`による`a`の可変参照はループブロック内の`x = &mut b;`によって解放されるが、`while`ではブロックが実行されない可能性も考慮されるため、ループ後の`y`に割り当てることができない。一方`loop`では確実に解放されるとみなされるため、`a`の可変参照は`y`に割り当て可能と判定される。

上のような`while true`は単純に`loop`に置き換えるだけで解決するが、他言語でみられる以下のようなパターンも`while`のかわりに`loop`（+`break`）を使うべき事例があるかもしれない。

```rust
// 必ず1度は実行されるループ（do-whileなんてなかった）
let mut found = false;
while !found { // 見つかるまでループ
    // 前処理
    ...
    // 検索
    found = ...
    // 後処理
    ...
}
```

## おまけ
```rust
// loopでも途中で抜ける素振りを見せるとコンパイルできない
fn main() {
    let mut a = 1;
    let mut b = 2;
    let mut x = &mut a;
    println!("{}", x);

    loop {
        if false { break; } // ここでbreakするかも（しない）
        x = &mut b;
        break;
    }
    let y = &mut a; // ERROR: second mutable borrow occurs here
    println!("{} {}", x, y);
}
```
たとえ0％でも可能性は見逃さない。
パトランプを回してみる - verson 0 電源付けてみる


### はじめに
秋葉原を散策していたら、秋月電子の前でパトランプが展示されていました。大きさが小さめで可愛かったので、ちょっと回してみようと思いました。何につなぐかは考えながら。
超簡単な工作入門です。彼女や奥さんに「パトランプ回してほしいわ！」って言われたらすぐにできるように、メモしておきます。（「ここ見て自分でやったら楽しいよ！」って紹介してもらってもいいね）

### 用意した部品
####1. パトランプ

![IMG_20200808_111406.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231182/c0050597-a635-e991-35ad-c63552041266.jpeg)

http://akizukidenshi.com/catalog/g/gM-13666/
・電源電圧：DC10.8~13.2V
・消費電力：5W
・突入電流：4A

####2. ACアダプタ

ACアダプタで、上のパトランプの仕様に対応しているもの。DCプラグのものが扱いやすい。

例：
http://akizukidenshi.com/catalog/g/gM-08431/

####3. DCジャック
DC プラグから電極を接続しやすくするもの。ACアダプタの先に刺します。
![C-00076.jpg](http://akizukidenshi.com/img/goods/L/C-00076.jpg)

例：
http://akizukidenshi.com/catalog/g/gC-00076/

####4. ワニ口クリップ
一時的に接続テストをするのに使います。一家に一台あるくらい有名なもの。
例：
http://akizukidenshi.com/catalog/g/gC-04353/


### 手順
1.パトランプの電源接続用の金属部分を切り落として、コードをむき出しにします。

![IMG_20200808_111433.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231182/78511265-9a3e-b02f-b4f1-433b1a02a11f.jpeg)

白がプラス、黒がマイナスね。

2.ワニ口クリップで接続します。


![IMG_20200808_114314.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231182/c3f80c78-0298-3d83-8d49-38d7ed819588.jpeg)

パクッ。赤がプラスです、白とつながってまっす。

3.プラスを真ん中部分に接続、マイナスを外側につなぎます。

![IMG_20200808_110149.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231182/34ceaba2-9aa9-df68-fcc4-57fcc3b58ad5.jpeg)

赤がプラスね。

4. 電源を入れると....おーパトランプが回ったー。


![IMG_20200808_110155.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231182/2d9f472b-c1a3-c025-4feb-e7ff29d5d685.jpeg)

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">パトランプまわしたり。 <a href="https://t.co/phL7h15WwW">pic.twitter.com/phL7h15WwW</a></p>&mdash;<a href="https://twitter.com/maohmi/status/1291929495620870145?ref_src=twsrc%5Etfw">August 8, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

回るとか光るとか、テンションあがるよねー！
さて、これを何につなごうかなー。


[パトランプを回してみる - verson 1 ラズパイとつなげてみる]
(https://qiita.com/maco-san/items/75a26d56b804809bf1dd)
へつづく
音声を標本化する周波数の音声データ量

平成31年春期 午前問題22

音声を標本化周波数10kHz，量子化ビット数16ビットで4秒間サンプリングして音声データを取得した。この音声データを，圧縮率1／4のADPCMを用いて圧縮した場合のデータ量は何kバイトか。ここで，1kバイトは1,000バイトとする。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/bcf02e57-6416-e14b-89af-ce7d59d8e0a2.png)


計算としては、難しいくないですね。
・1Hzが16bit
・10kHz * 16bit/Hz * 4s ->640kbit  
  -> 640k/8 Byte ->80KB 
  -> 80/4 KB = 20KB(圧縮後)


１、標本化（サンプリング）」とは
アナログ信号から、一定の時間間隔で区切ってデータを採取することです。この時間間隔を「標本化周波数（サンプリング周波数）」と呼び、 Hz（ヘルツ）という単位で示します。 
**1 秒間に 1 回が 1 Hz** です。
音声 のサンプリング周波数は、10 kHz（キロ・ヘルツ）であり、1 秒間に 10k ＝ 10,000 回のデータの採取を行います。

２、量子化とは
符号化で採取されたデータを、数値にすることです。この数値の大きさを「量子化ビット数」と呼びます。
音声 の量子化ビット数は、16 ビット（ 2 進数で 16 桁）です。

３、符号化とは
量子化で得られた数値を、特定の形式にすることです。「 PCM（ Pulse Code Modulation ）」という形式では、量子化された 16 ビットのデータを、そのままの形式で符号化します。


参考：
音声サンプリングの計算方法がわかる
https://www.seplus.jp/dokushuzemi/fe/fenavi/easy_calc/sampling_voices/
BitBoardを利用してリバーシの合法手を求める

リバーシ（オセロと呼んではいけない時代は終わったのでしたでしょうか…。）を BitBoard で実装します。アイデア自体については、[オセロをビットボードで実装する](https://qiita.com/sensuikan1973/items/459b3e11d91f3cb37e43) などの記事を参考にしてください。

```
xxxx
xWBx
xBWx
xxxx
```
（簡単のために 4x4 の例で説明しますが、実装は 8x8 です。W: 白石、B: 黒石、x: 石がない、をそれぞれ表します。）
この盤面を BitBoard では黒石の配置

```
0000
0010
0100
0000
```
と白石の配置

```
0000
0100
0010
0000
```
の二つの bit列で表現します。

今回は、合法手をすべて求める方法を考えます。
黒番の合法手は必ず、盤面のある黒石の上下左右斜め8方向のいずれかにあります。そのうち、まず左方向（つまり、盤面の黒石の左方向から白石を挟める手）の探索から考えます。

左方向の探索では、この盤面における黒番の合法手のひとつ

```
0000
1000
0000
0000
```
が求められるはずです。

まず、盤面の黒石の左隣に隣接する白石を求めます。これは、黒石の配置を 1 bit 左にシフトして、白石の配置との積を求めることと同じです。

```
0000   0000   0000
0100 & 0100 = 0100
1000   0010   0000
0000   0000   0000
```
さらに 1 bit 左にシフトすると、黒番の合法手を見つけることができますが、白石が連続する場合が考慮できていません。少し盤面を変えます。

````
xWWB
xWBB
xWBW
xBWB
```
まず、黒石の配置を 1 bit 左にシフトして、白石の配置との積をとります。ここまでは同じです。

```
0010   0110   0010
0110 & 0100 = 0100
0100   0101   0100
1010   0010   0010
```
黒石の左隣にある白石の、さらに左隣にある白石を求めます。つまり、これは、黒石の左隣にある白石の配置を 1 bit 左にシフトして、白石の配置との積を求めることと同じです。

```
0100   0110   0100
1000 & 0100 = 0000
1000   0101   0000
0100   0010   0000
```
結果として、黒石の左隣に連続している白石の配置

```
0010   0100   0110
0100 | 0000 = 0100
0100   0000   0100
0010   0000   0010
```
を求めることができます。4x4 では黒石の左隣に白石は二つしか隣接しないので、これ以上の演算は不要ですが、8x8 では 計6回繰り返すことで、黒石の左隣に隣接する連続した白石をすべて求められます。

黒番の合法手はさらに 1 bit 左にシフトすることで見つけれます。ただし、その位置に石があり着手できない場合を取り除くため、石のない位置との積をとります。

```
1100   1000   1000
1000 & 1000 = 1000
1000   1000   1000
0100   1000   0000
```
黒番の合法手をすべて見つけることができました。

最後に、これまで無視していた左端の石の取り扱いを考えます。左端の石はひとつ上の段の右端の石と隣接していることになります。次の盤面を例に考えます。

```
WBxW
BWBx
WWBx
WBxx
```
左端の白石は左方向の探索ではひっくり返せない白石なので、あらかじめ`opponent_board` から取り除きます。
また、左端の黒石が一つ上の段の右端の白石と隣接していると判定しないように、右端の白石も`opponent_board` から取り除きます。

```
1001   0110   0000
0100 & 0110 = 0100
1100   0110   0100
1000   0110   0000
```

上記を python で実装したものが以下です。

```python:board.py
class Board:
    BLACK, WHITE = True, False

    def __init__(self, black=0x000010080000, white=0x000008100000):
        self.board = {Board.BLACK: black, Board.WHITE: white}

    def legal_moves(self, player):
        self_board = self.board[player]
        opponent_board = self.board[not player]
        blank_board = ~(self_board | opponent_board)
        opponent_board = opponent_board & 0x7e7e7e7e7e7e7e7e

        temp = self_board << 1 & opponent_board
        temp |= temp << 1 & opponent_board
        temp |= temp << 1 & opponent_board
        temp |= temp << 1 & opponent_board
        temp |= temp << 1 & opponent_board
        temp |= temp << 1 & opponent_board

        temp = temp << 1 & blank_board

        return temp
```
コメントを書くことについて


# 前提のはなし

---
# コードは読み物である
作成に費やされる時間より、他の人が理解するのに費やされる時間の方がはるかに長い

---
# コードは改修される
理解しづらいソースの改修は極めて危険

---
# 「理解しやすさ」は品質
製品の不具合を減らし、ライフサイクルを延長できる

---
# 優れたコード > ひどいコード + 優れたコメント
本当はコメントなしでわかりやすいのがベスト

---
# しかし、コメントでしかできないこともある

---
# コメントの原則
ソースに書かれていないこと、理解するのに時間がかかることを書く
(「すぐに」わかることはいらない！)

---
# コードの意図を書く
```java
// マルチスレッドで使用するためStringBuilderは使用不可
StringBuffer sharedBuffer;
```

---
# 全体像や要約を書く
```java
// 様々なお菓子を作るクラス
class patissier {
  public Cake makeCake(){
    // 計量する
    ...
    // 混ぜる
    ...
    // オーブンで焼く
    ...
  }
}
```

---
# 読み手の立場で書く
独特の処理、わかりにくい処理、etc
「プロジェクトに初めて入った人」が疑問に感じる点を想像する

---
# 推敲する
初めから良いものは書けない
思いついたら書く、書いてから簡潔にする

---
# とにかく書いてみる
書かないと上達しない
コードも理解しにくくなる一方

---
# 参考
リーダブルコード
―より良いコードを書くためのシンプルで実践的なテクニック―
https://www.oreilly.co.jp/books/9784873115658/

---
# おしまい
アクチュエータの機能

平成31年春期 午前問題21

アクチュエータの機能として、適切なものはどれか。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/cd12417c-59cc-ac89-daf5-ad5984b41f4f.png)


１、アクチュエータは
入力されたエネルギーを物理的運動に変換するものである。

アクチュエータ(Actuator)は、入力された電気エネルギーを物理運動量に変換するものであり、機械・電気回路を構成する機械要素です。

ロボットなどの制御システムを構成する。

２、A/Dコンバータ(アナログ・ディジタル変換器)
アナログ電気信号を，コンピュータが処理可能なディジタル信号に変える

３、静電センサー
キーボード，タッチパネルなどに使用され，コンピュータに情報を入力する。
アクチュエータは入力デバイスではありません。

４、センサ
物理量を検出して，電気信号に変える

参考：
https://www.fe-siken.com/kakomon/29_aki/q22.html
VERA当番日報で役に立ちそうなツール

#日報メールをより楽に
当番に入った観測兵は日報メールを出すことが義務である。しかし、日報メールの天候の欄がどうもめんどくさい。特に風向。これをなんとかしたい。
pythonの方が良いかなあと思いつつ、pythonを使うほどでもないか(スナネコ)ということでC原語で書いた。力技で書いているので適宜修正していくつもりである。
mac OSで動作確認済み。

追記：
大変ありがたいコメントによって曜日、風向がすっきりしました。
ありがとうございます。20/8/9
日付けを取得する部分で不備が見つかりました。修正してます。20/8/10

プログラムの構成は、日付け取得→データ入力→条件分岐(風向、曜日)→出力となっている。
入力のフォーマットは以下の通り。一番上の行(UT00:00)を丸々コピーすれば良い。

```ruby:input_format
2020221000000      7.91      3.76      9.45      4.41    229.60     26.99     26.48     78.91     78.95    951.07      0.13     10.65     10.35
```

天候も自分で入力していただきたい。

以下ソースコード。

```ruby:VERA_weather.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<time.h>

int main(){
	
	int DAYS;
	double SPDNOW, SPDAVE, SPDMAX1, SPDMAX2, DIRECT;
	double TEMP1, TEMP2;
	double HUMID1, HUMID2;
	double PRESS;
	double RAIN, DHUMID1, DHUMID2;
	
	char in[256];
	char weather[16];
	char windDirection[3] = "";
	
	time_t timer;
    struct tm *date;
    char week[16];

/*入力データ*/
	printf("input data.\n");
	fgets(in, 256, stdin);
	printf("today's weather?\n");
	fgets(weather, 16, stdin);
	printf("\ncopy under text\n");

/*今日の日付けを取得*/
    timer = time(NULL);
    date = localtime(&timer);
    
    printf("%d/%d", date->tm_mon+1, date->tm_mday);
    
    strftime(week, 15, "%a", date);

    const char DayOfWeekTable[] = "MonTueWedThuFriSatSun";
    const char* dayOfWeek = strstr(DayOfWeekTable, week);
    if (dayOfWeek) {
        printf("(%s)", (const char*[]){"月", "火", "水", "木", "金", "土", "日"}[(dayOfWeek - DayOfWeekTable) / 3]);
    }
        	
    printf("UT00:00 ");

/*入力データの処理*/
	sscanf(in, "%d      %lf      %lf      %lf      %lf      %lf      %lf      %lf      %lf      %lf      %lf      %lf      %lf      %lf",&DAYS,&SPDNOW, &SPDAVE, &SPDMAX1, &SPDMAX2, &DIRECT, &TEMP1, &TEMP2, &HUMID1, &HUMID2, &PRESS, &RAIN, &DHUMID1, &DHUMID2);
	printf("気温 %.2lf °C 湿度 %.2lf ％ 気圧 %.2lf hPa 風速 %.2lf m/s 風向 ",TEMP2, HUMID2, PRESS, SPDAVE);
		
	strcpy(windDirection, (const char*[]){"N", "NE", "E", "SE", "S", "SW", "W", "NW"}[(int)(fmod(DIRECT + 22.5, 360) / 45.0)]);
    printf("%s %s\n",windDirection, weather);
	
	return 0;
}
```

出力はこのようになるはず。

```ruby:output
8/8(土)UT00:00 気温 26.48 °C 湿度 78.95 ％ 気圧 951.07 hPa 風速 3.76 m/s 風向 SW [ここに入力した天候が入る]
```
[React] propsの基本

前回は関数コンポーネントの基本的な書き方について記事を書いた。
https://qiita.com/QiitaD/items/5ba8adbde6ff01c914a7

今回はpropsについて記事にしようと思う。

##propsとは
データの入ったプロパティという意味。個人的には引数みたいなものと認識している。
例えば関数コンポーネントにpropsとしてデータを渡すことで、そのデータを関数コンポーネント内で使うことができるし、データに応じた要素を返却できる。

##コード
前回のButton.tsxファイルにpropsを設定してみる。propsとしてボタンに表示するテキストを指定できるようにしようと思う。

Button.tsx

~~~typescript
import React from "react";

export default Button;

// propsを指定するときはinterfaceを使う。このブロック内にボタン表示テキストを定義しておく
interface ButtonProps {
  text: string;
}

//関数コンポーネントの引数としてButtonPropsを指定することで、呼び出し側でtext: stringを指定しなければならなくなる。（もちろん複数定義されていればその分渡す必要がある）
function Button(props: ButtonProps) {
  return <button>{props.text}</button>;
}

~~~

呼び出し側は、関数呼び出し時にButtonPropsに定義されている変数を渡すだけである。

~~~typescript
import React from "react";
import { RecoilRoot } from "recoil";
import Button from "./Button";

function App() {
  return (
    <RecoilRoot>
      <div>
        //ここでtextにデータを渡す。
        <Button text="テストボタン"></Button>
      </div>
    </RecoilRoot>
  );
}

export default App;
~~~

##表示結果
前回と同じ結果になる
![スクリーンショット (110).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506451/6f4c142f-e458-42df-e9bb-495025334f55.png)
FXをAIで攻略する難題をどう乗り越えるかのメモ

# 為替予想についての考察

FXで失ったお金を取り戻すため半AIトレーディング計画を始動しました。


## FX相場予測問題

- 為替市場は線形問題ではない。定義できるパラメータが簡単なものしかない
   - 説明変数が少なければ汎用性の高いモデルは絶対に作れない
- 市場の性質上、市場環境全体が異なるので、同じ入力が異なる結果をもたらす可能性がある
   - これはコンピュータが特に苦手とすること
- コンピュータは「行動」や「市場」のような抽象的な概念を理解することができない
   - 世界クラスのチェスをするコンピュータでさえ、実際のチェスがなんであるかさえ知らない
      - ようするにコンピュータは、勝つ方法を理解しているだけ
- 時間に依存し、非決定論的な性質を持つ為替相場は機械学習システムにとって難易度が高い
- 市場の状況を本質的に理解する必要がある
 - 学習と検証にかかる時間を考慮すると、ライブトレードはなかなか難しい
- 単純に正確な予測(上か下か予測)を行う能力に基づいてモデルを作成するのは意味がない
   - 99の小さな決定が、1つの大きな決定により一掃されてしまうことがある
   - この問題を回避するためには、機械学習アルゴリズムを再トレーニングする方法を利用する


## FX相場予想問題の回避方法

① 柔軟なウィンドウを使用することで、サンプル内/サンプル外のセットに関連付けられている選択バイアスが減少する。
② トレーニングは一連の検証演習となり、データセットが大きく異なる場合でも、機械学習アルゴリズムが常に適切に機能するようにする。アルゴリズムの真の価値とメソッドを確立するプロセスでは、バックテストのパフォーマンスを測定することも重要であると考える必要がある。

- このようなアプローチはフェールセーフ（常に安全に制御できること）ではない
- カーブフィッティング(過学習)とデータマイニング(知識を取り出す技術)のバイアスがかかる
  -  これを軽減するために膨大なデータセットを使用し、大量のデータマイニングバイアス評価テストを実施し、
       偶然に有望な結果が発生する可能性を排除することが重要になる (半ば完璧な相場状況判別アルゴリズムをつくる)
 
③ 以上のことを踏まえると、リアルタイムで現在の市場を把握して、カスタマイズ可能なアルゴリズムにより成功の可能性を高められる？かもしれない


# 結論

現在考察中、結論は近日中に出す予定
lazy_high_chartsを1.6.1にアップデートしたらCIが落ちるようになった

Railsで[lazy high charts](https://github.com/michelson/lazy_high_charts)を使っていて、最近アップデートしようとしたら、エラーが出るようになって更新できなかったので、そのときに調べたことをまとめています。

## 気の早いお方へ
7/29以前から[lazy_high_charts](https://github.com/michelson/lazy_high_charts)を使っていて、アップデートしたら `couldn't find file 'highcharts/highcharts' ...`というエラーが出てあれー？ってなっている方は`rake highcharts:update`をしてみてください。` vendor/assets/javascripts/highcharts`以下に最新の[highcharts](https://www.highcharts.com/)がダウンロードされて使えるようになります。


## 詳細
### CIでエラー

dependabotが更新のプルリクを作ってくれていたんですが、CIでエラーが出ていました。
`couldn't find file 'highcharts/highcharts'`と、highcharts

```console
Failure/Error: //= require highcharts/highcharts

ActionView::Template::Error:
  couldn't find file 'highcharts/highcharts' with type 'application/javascript'
  Checked in these paths: 
    /home/circleci/repo/app/assets/config
    /home/circleci/repo/app/assets/images
    /home/circleci/repo/app/assets/javascripts
    /home/circleci/repo/app/assets/stylesheets
      :
      :
```

### 調査
地道に前回インストールしたバージョンのコミットからの差分を見ました。
大変そうですが、実は5個しかみてません。
普段から最新のgemを使うようにしていて、ホントよかったです！

それで見つけたのが[このコミット](https://github.com/michelson/lazy_high_charts/pull/257)です。

内容は「gemにjsのソースをバンドルすると、本家がアップデートするたびにgemのバージョンもあげなきゃいけなくて大変だと思うので、別途利用者が個別にインストールする形をとったらどうでしょう？」というもので、最新のhighchartsを取得するrakeタスクの追加と、gem内部のjsの削除がされていました。

その後、よくよく見るとREADME.mdのインストール手順にrakeタスクの実行が追加されていました。

### highchartsのインストールで解決

追加されたインストール手順の`rake highcharts:update`を実行すると、無事にhighchartsをインストールできました。場所は`vendor/assets/javascripts/highcharts`です。

利用しているページでグラフが表示されていることを確認して、問題ないことがわかりました。

リポジトリに登録して、解決しました。

### 懸念事項
今まで[lazy_high_charts](https://github.com/michelson/lazy_high_charts)のアップデートで[highcharts](https://www.highcharts.com/)の更新が行われていたわけですが…これが自分たちでやらなくてはならなくなってしまいました…。

どうやって忘れないようにしよう…。

## おわりに
sprocketsからwebpackerに移行したいです…！
そしたらアップデート作業をdependabotに頼めるので。

あとは…README.mdのblame見ればよかった。
ちゃんとREADME.mdも更新されていたので、コミットログでなくて、こちらを見たらもっと楽だったと思いました…。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14380/c3b8501a-77dd-ffa0-1915-9f0e4f99618e.png)
[React] 関数コンポーネント

##関数コンポーネントとは
UIの一部を部品としてコンポーネント化することで、再利用できるようになる。
例えば、テキストを引数によって変更できるボタンをコンポーネント化する、のような感じである。

##コード
今回はボタンコンポーネントを作成してみる。
まずはファイルを作成する。名前は適当に「Button.tsx」とする。

Button.tsx

~~~typescript
import React from "react";

//他のファイルでこのファイルをimportすることで、ここの関数を使えるようになる
export default Button; 

//この関数を呼ぶことでボタンが返却される
function Button() {
  return <button>テストボタン</button>;
}
~~~

上記の関数を他のファイルで呼び出すときは以下のように書く。

App.tsx

~~~typescript
import React from "react";
import { RecoilRoot } from "recoil";

//「Button」という名前でButton.tsxをimportする。名前は好きに付けることができる。
//fromの後はButton.tsxへのパスを書く。今回はApp.tsxと同じ階層にあるので以下のようにしている。
import Button from "./Button";

// import文で付けた名前のタグで関数コンポーネントを呼び出せる
function App() {
  return (
    <RecoilRoot>
      <div>
        <Button></Button>　
      </div>
    </RecoilRoot>
  );
}

export default App;
~~~

##表示結果
ボタンが表示される
![スクリーンショット (110).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506451/10c67751-19c9-0789-a954-cef24c07939e.png)
Flutterの導入(2) ~for Windows10~ Visual Studio Code をインストールしよう

今回は Visual Studio Code で Flutter を使うための準備をする。

#Visual Studio Code をインストールする
コレは説明不要、だよね？
一応書いておくと、[公式](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)からダウンロードしてきて、インストールするだけ。
Azure を試すのは、また今度。今回はローカル環境作成だから。

#Flutter 用の Extensions(Plugin) をインストールする
Visual Studio Code を起動すると出る、このテトリスみたいなマーク。
↓ここをクリックすると、Extensionsをインストールする事ができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194966/e7db1510-2813-cfa6-cc14-bef17890289c.png)
今回は Flutter 用の環境になるので、
↓赤枠の中のものをInstallすれば、最低限は足りる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194966/473867c5-c26e-432d-cf79-98c7c4ff7cf8.png)
ここまでインストールが出来たら、 Visual Studio Code での設定は終わり。

#参考

- Visual Studio Code 公式
   - https://azure.microsoft.com/ja-jp/products/visual-studio-code/