OmniAICreator/Qiita-1.07M huggingface dataset:
Xibファイルの高さを自動調整する


XibファイルをViewに埋め込んだ時に、高さを文字数などによって自動調整したい場合の方法。

非自動調整時：
緑のViewが途中で切れてしまっている。
![Simulator Screen Shot - iPhone 11 Pro Max - 2020-10-24 at 11.52.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332381/19d184ba-2c40-b130-5d0c-170a9f36592a.png)

自動調整後：
緑のViewが最後まで表示されている。
![Simulator Screen Shot - iPhone 11 Pro Max - 2020-10-24 at 11.52.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332381/3616bc3f-dbf1-cbe9-1b7e-66d125bc2988.png)

【解決方法】
StoryBoard上で埋め込んでいるXibファイルを表示するViewの設定を下記のように変更。
Layout→Autoresizing Mask
![スクリーンショット 2020-10-24 11.49.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332381/49dd18b6-6608-c08f-be5b-1753edf07473.png)
Autoresizingで自動調整して欲しい拘束を設定。
![スクリーンショット 2020-10-24 11.50.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332381/454f1efb-f1c6-ca56-a817-e1b85c7fc594.png)
【Firebase】Firebaseでデプロイ（公開）する方法

## まずはnpmでFirebase関連のモジュールをインストール
### firebase-tools はglobalオプションでインストールされることが多い
```sh
npm i firebase-tools -g

npm i firebase --save
```

## コマンドライン上でfirebaseにログインする
### 既にログインをしている場合、このコマンドは不要

```sh
firebase login
```

## 設定する。コマンドライン上で色々と選択が必要
### 機能の選択例。スペースキーで選択しEnter, Returnキーを押す
・hosting, functions, firestore

```sh
firebase init
```

## 実際にデプロイ、公開する
### ここでエラーが出る場合、google platformで請求先住所を登録しておく必要がある様子（2020/10/24時点）

```sh
firebase deploy
```
匿名型とタプル

長い間、匿名型とタプルを同じものだと思い込んでいたため、反省と備忘録をこめて記事を作成しました。

## 匿名型


```C#
List<string> strList = new List<string>() { "AAA", "BBB", "CCC", "DDD", "EEE"};

//anoはタプルではない！匿名型
var ano = strList.Select((str, index) => new { str, index });
```

上記のような記載をした場合、anoはタプルのリストではなく匿名型のリストとなります。
そのため、以下のような代入はできません。

```C#
//↓NG : '<anonymous type: string str, int index>'を'(string str, int index)'に暗黙的に変換できません
//(string str, int index) val = ano.FirstOrDefault();
```

## タプル
```C#
List<string> strList = new List<string>() { "AAA", "BBB", "CCC", "DDD", "EEE"};

//tupはタプル！
var tup = strList.Select((str, index) => (str, index));
```

一方こちらは、タプルのリストとなります。
以下のような代入が可能です。

```C#
//↓OK
(string str, int index) val = tup.FirstOrDefault();
```

## 補足
本記事ではC#8.0から標準で導入されているValueTupleのことをタプルと呼んでいます。
Visual Studio 2017を使用されている場合、NuGetからValueTupleパッケージをインストールすることで利用可能です。
【UFT】Windowsの「ファイル名を指定して実行」を自動操作してみる

キャプチャリプレイ機能でうまく操作を記録することができなかったWindowsの「ファイル名を指定して実行」を制御する方法を調べたので備忘録として記事に残します。

# はじめに
UFTを使いIEのインターネットオプションを制御しようとキャプチャリプレイを試してみる。
→　キャプチャリプレイでオブジェクトを認識してくれない（アドイン追加済み）
　→　ならコードで対処するか
　　→　なんか思っていたよりも複雑だぞ...

インターネットオプションだけでなく、「ファイル名を指定して実行」は今後自動化することがあるかも知れない。
その時が来たときにスムーズに実装できるよう記事に残します。

## 環境
・Windows 10 64bit Ver.2004
・UFT15.01
・IE11 最新版（2020/10/24時点）

# コード
【**前提**】<br>「ファイル名を指定して実行」から「インターネットオプション」と入力し検索しても失敗します。
そのため、インターネットオプションを実行するために専用のコマンドを用います。
下記に一部コマンドを抜粋します。

|コマンド|対応プログラム|
|---|---|
|inetcpl.cpl|インターネットオプション<br>（インターネットのプロパティ）|
|notepad|メモ帳|
|control|コントロールパネル|
|mstsc|リモートデスクトップ|
|regedit|レジストリエディタ|
|winver|Windowsのバージョン情報|
|cmd|コマンドプロンプト|
|explorer|エクスプローラ|

参考：
[windows ファイル名を指定して実行覚書 - Qiita](https://qiita.com/suvene@github/items/454e4f9fb9e426a5c40f)
[「ファイル名を指定して実行」で、よく使うやつ - Qiita]((https://qiita.com/suvene@github/items/454e4f9fb9e426a5c40f)
)


## サンプルコード
```VB:ファイル名を指定して実行を起動し、インターネットオプションを開く
Option Explicit    'お約束
On Error Resume Next    ' エラーが発生すると、エラーが発生した次の行から処理を続行します。

Dim objShell        ' Shell オブジェクト

Set objShell = CreateObject("Shell.Application")    'shellオブジェクトの作成（Windowsのシェル(エクスプローラ)の機能）
If Err.Number = 0 Then
    objShell.FileRun    '「ファイル名を指定して実行」の実行
    Dialog("text:=ファイル名を指定して実行").WaitProperty "enabled","True"    'waitPropertyを使い表示されるまで待機
    Dialog("text:=ファイル名を指定して実行").WinEdit("Class Name:=WinEdit").Set "control inetcpl.cpl"    'setに実行するファイル名を入力する
    Dialog("text:=ファイル名を指定して実行").WinEdit("Class Name:=WinEdit").Type micReturn    'Enter keyを実行
Else
    Msgbox("処理失敗")
End If

Set objShell = Nothing

```


# おわりに
> Dialog("text:=ファイル名を指定して実行").WinEdit("Class Name:=WinEdit").Set

このSetにコマンドを指定することで対応したプログラムが実行されます。
サンプルコードはオブジェクト登録がなくても動くようにしています。
実際に自動テストを作る場合は遷移先のオブジェクトを取得してコードを実装してみてください。

以上
[AWS認定SAP]アプリケーション移行戦略（6R）

#6Rとは
2011年に調査会社であるGartner社が定義したクラウド移行の5つのアプローチに基づいて定義された以下の6つの移行戦略。

1. Rehost ("lift and shift"):ホスト変更
2. Replatform ("lift, tinker and shift"):プラットフォーム変更
3. Repurchase ("drop and shop"):再購入
4. Refactor / Re-architect:再設計
5. Retire:リタイア
6. Retain:保持

##1. Rehost ("lift and shift")
現在の環境をそのままクラウド移行し、随時最適化する。

##2. Replatform ("lift, tinker and shift")
コアの部分を変えず部分的に最適化した上で移行する。

##3. Repurchase ("drop and shop")
現在のシステムやアプリケーションの使用を廃止し、新しいシステムやアプリケーションに移行す。

##4. Refactor / Re-architect
現在のシステムやアプリケーションを見直し再設計した上で移行する。

##5. Retire
不要なシステム・アプリケーションの使用を停止する。

##6. Retain
移行しない。

###参考
・https://aws.amazon.com/jp/cloud-migration/

それぞれのメリット・デメリットの説明有り
↓
・https://blog.mmmcorp.co.jp/blog/2020/07/07/Six_Strategies_Migrating_to_AWS_ProsandCons/
Asp .Net Core AzureWebServerのログをBlobストレージに送る

#loggerの設定

```C#:Program.cs
  public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureLogging(logging =>
                {
                    // デフォルトを上書き
                    logging.ClearProviders();
                    logging.AddAzureWebAppDiagnostics();
                    logging.AddFilter((provider, category, logLevel) =>
                    {
                        // フィルタ条件が書ける
                        return true;
                    });
                })
                .ConfigureServices(serviceCollection => serviceCollection
                    //Blobを使うよ
                    .Configure<AzureBlobLoggerOptions>(options =>
                    {
                        //出力ファイル名 (prefixにGuidが付く)
                        options.BlobName = "log.txt";
                    }))
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
```

# App Service側の設定
![スクリーンショット_102220_065012_PM.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/c2cabec3-53cc-d231-5b92-d6548c6e4f09.jpeg)

# 使用箇所
DIに登録されているので、コンストラクタにILogger<クラス名>でインスタンスが取得できる

```C#
public TestController(ILogger<TestController> logger)
{
    logger.LogError("エラーメッセージ");
}
```

Startup.csのConfigureServicesで使いたい場合は以下で取得可能

```
public void ConfigureServices(IServiceCollection services)
{
    var logger = services.BuildServiceProvider().GetRequiredService<ILogger<Startup>>();
}
```

# 確認
指定したBlobストレージにログが出力されるかと思います。

![スクリーンショット_102420_114558_AM.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/2aa20f69-1e57-7eba-b966-42b83b718f10.jpeg)
【Windows】通常の通信はVPNを経由したくないけどAWS向けはVPNを経由したい

#はじめに

リモートワークでVPNを使っているんですけれども、Windowsで普通にVPNを設定するとすべての通信がVPNを経由してしまいます。
そこで、VPN先のネットワークへの通信だけVPNを経由し、普通にググったりツイッターで~~脱線~~情報収集したりするのは直接インターネットに出ていきたい。
しかしながら、特定のIPだけはVPNを経由したい。
そんな環境があって、特定の数個のIPアドレスだけ手動で登録して使ってました。

しかし、AWSのEC2スポットインスタンスをポコポコ立ち上げてアクセスする必要が出てきました。セキュリティ上、拠点以外からのアクセスは遮断しています。
スポットインスタンスを立ち上げるたびにいちいちパブリックIPを調べて手動でルーティング設定するのは面倒です。
そこで、AWS向けは全部VPN経由にする方法を考えました。
たまたまAWSが使われているサービスへの通信（例の52.68.96.58とか）もVPN経由になってしまいますが、まあ、許容範囲内でしょう。

#前提条件

・AWS Tools for Windows PowerShell がインストールされている
　　参考　[AWS Tools for PowerShell ことはじめ](https://qiita.com/NakaD/items/ec03843a6428713ac5fb)
　　（今回の使い方では、Credential情報の設定は不要です。）

・通常の通信はVPNを経由しない指定は設定済み
　　参考　[【Windows】指定した宛先の通信のみVPN経由にする](https://qiita.com/mindwood/items/5c56769a7fc40cafe7e3)

#AWSのIP範囲取得

AWSのIP範囲って変わっていくんじゃないかと思ったのですが、プログラマブルに取得する方法が用意されていました。
公式ドキュメントの [AWS IP アドレスの範囲](https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws-ip-ranges.html) をご覧ください。

だけだと不親切なので、とりあえず取得するコマンドを

```awsipv4.ps1
Get-AWSPublicIpAddressRange -Region ap-northeast-1 -ServiceKey EC2 | Where-Object {$_.IpAddressFormat -eq "Ipv4"} | Select-Object IpPrefix

```

これを応用して、ルーティング設定コマンドに流し込みます。

#出来上がり

VPN接続をトリガにスクリプトを走らせられないかと調べたのですが、見つからなかったので、スクリプトを走らせると設定したうえでVPN接続をする方法にしました。

```connectVpn.ps1
$vpnName = "MyVPN"
$vpnUser = "username"
$vpnPass = "password"

# 現状のルーティング設定を全部削除
(Get-VpnConnection $vpnName).Routes |
ForEach-Object {
    Remove-VpnConnectionRoute $vpnName -DestinationPrefix $_.DestinationPrefix
}

# AWSのIP範囲を取得(東京リージョンのEC2だけ)
Get-AWSPublicIpAddressRange -Region ap-northeast-1 -ServiceKey EC2 |
#IPv4に絞る
Where-Object {$_.IpAddressFormat -eq "Ipv4"} |
#おのおのルーティング設定
ForEach-Object {
    Add-VpnConnectionRoute $vpnName -DestinationPrefix $_.IpPrefix
}

#AWS以外でルーティングが必要ならここに記述
#Add-VpnConnectionRoute $vpnName -DestinationPrefix xxx.xxx.xxx.xxx

#VPN接続
C:\windows\system32\rasdial.exe $vpnName $vpnUser $vpnPass
```

実際に使うときは ```$vpnName``` ```$vpnUser``` ```$vpnPass``` をご自身の環境に合わせて変更してください。
（WindowsのUIから接続するときはVPN名だけで接続できるので、スクリプトからもVPN名だけでいけないか調べたのですが、どうも出来ないようで、ユーザー名・パスワードもスクリプト内に記述しております）

また、自分の利用範囲ということでAWSの東京リージョン・EC2・IPv4に絞ってますが、ここもご自身が利用するAWSのサービスに合わせて書き換えましょう。

PowerShellのお作法として、BOM付UTF-8で保存しましょう。（←それがベストプラクティスなのかはよくわかってない）

ルーティングテーブルが大量にあると速度低下の懸念がありますが、上記設定（40件ぐらい）では目立った速度低下は無いようです。（NURO光で変わらず800Mbpsぐらいでてます。）
Electron-Builderでnode.jsのパッケージを含めてビルドする際の注意点

![screen0010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76058/68c411cd-df3a-00a3-d574-d9a96df81e0d.png)

ElectronとExpressを使ったアプリを開発していたのだが、Electron-builderを使ってパッケージ化した際に、設置したはずの`express`が見つからないというエラーが表示された。

調べてみると、どうやらプロジェクト毎のnode_modules`npm install --save-dev express`ではなく、環境毎のnode_modules`npm install --save express`である必要があるそうだ。

ちなみに、`npm install --save express`でインストールした後にパッケージ化したものは、ちゃんとパッケージ内にexpressが内包されているらしく、別端末からも起動できた。

```json
...
  "devDependencies": {
    "electron": "^10.1.4",
    "electron-builder": "^22.9.1"
  },
  "dependencies": {
    "express": "^4.17.1"
  },
...
```
Pythonで解く【初中級者が解くべき過去問精選 100 問】(053 - 055 動的計画法：その他)

# 1. 目的
[初中級者が解くべき過去問精選 100 問](https://qiita.com/e869120/items/eb50fdaece12be418faa)をPythonで解きます。
すべて解き終わるころに水色になっていることが目標です。

本記事は「053 - 055 動的計画法：その他」です。

# 2. 総括
「その他」とあるようにこの3問は今までの```dp```とは少し志向（嗜好？）が違い、```dp```らしくない```dp```であると感じました。


# 3. 本編


## 053 - 055 動的計画法：その他

### 053. [DPL_1_D - 最長増加部分列](http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_1_D&lang=ja)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668985/d6e6c9b3-8e13-e11f-114e-96413ff38b4c.png)

#### 回答
```python

import bisect

n = int(input())
A = [int(input()) for _ in range(n)]
dp = [A[0]]

for i in range(1, n):
    if A[i] > dp[-1]:
        dp.append(A[i])
    else:
        ind = bisect.bisect_left(dp, A[i])
        dp[ind] = A[i]

print(len(dp))

```

二分探索とDPで解きます。

```dp``` に昇順に```A```の要素を順に追加していきます。
具体的には、

1. すべての```A```の要素```A[i]```について
2. ```dp```の最後の要素より大きいものは```dp```に追加し
3. 大きくない場合は```dp```の中に```A[i]```以上の数字が存在するので、```A[i]```で置き換える
4. できあがった```dp```の長さが答え
です。


---

### 054. [AtCoder Beginner Contest 006 D - トランプ挿入ソート](https://atcoder.jp/contests/abc006/tasks/abc006_4)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668985/96e4870e-6c1d-5195-2459-9ea59384ef7c.png)

#### 回答
```python

import bisect

N = int(input())
C = [int(input()) for _ in range(N)]

dp = [C[0]] # 初期値

for i in range(1, N):
    if C[i] > dp[-1]:
        dp.append(C[i])
    else:
        ind = bisect.bisect_left(dp, C[i])
        dp[ind] = C[i]

print(N - len(dp))


```

053. [DPL_1_D - 最長増加部分列](http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_1_D&lang=ja)とほぼ同じです。
違いは最後の```print(N - len(dp))```。
トランプを挿入する必要回数は、トランプの数から最長増加部分列の長さを引いた数になります。

---

### 055. [AtCoder Beginner Contest 134 E - Sequence Decomposing](https://atcoder.jp/contests/abc134/tasks/abc134_e)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668985/29024de6-43ab-8ba3-dba5-840ea021cfe8.png)

#### 回答
```python

import bisect
from collections import deque

N = int(input())
A = [int(input()) for _ in range(N)]

dp = deque()
dp.append(A[0])

for i in range(1, N):
    ind = bisect.bisect_left(dp, A[i])

    if ind == 0:
        dp.appendleft(A[i])
    else:
        dp[ind-1] = A[i]

print(len(dp))


```

上記２つの問題から少しだけ考え方をかえます。
上記２つの問題では、```dp```の最大値以上の要素を```append```していましたが、
今回は最小値以下の要素を```appendleft```していきます。


---
Xcodeでプロジェクト作成時に.gitignoreを追加する

# 概要

Xcodeでプロジェクトを作成した際に、.gitignoreが作成されないままinitialコミットされるので、.gitignoreを追加して再コミットする。

# 手順
### .gitignoreの生成
以下のサイトでXcode用の.gitignoreを生成し、プロジェクトに追加する。
https://www.toptal.com/developers/gitignore

### initial commitの取消
initial commitはgit resetではなく、以下のコマンドで取り消し可能。
取り消し後、再度コミットし直す。

```bash
git update-ref -d HEAD
```
オブジェクト指向という考え方について2

2.1.2 メソッドとカプセル化

次に先ほどのオブジェクトの説明に出てきた「振る舞い」という言葉について考えてみます。この「振る舞い」はメソッドと呼ばれ、オブジェクト固有の動作仕様（固有の動作ロジック）をしみします。つまりオブジェクトは、自身の中にメソッドという形で自分の行動に放るようなロジックを保持しています。

メソッドは、目的の動作に合わせてオブジェクトの中に複数保持することができます。オブジェクトの自身のメソッドをオブジェクト内に閉じ込めて（隠蔽）保持することを特にカプセル化といいます。

メソッドを利用する人は通常、メソッドがどんなロジックで作られているかを知る必要はなく、どんな名前で、どのような目的を果たしてくれるかを知っていれば十分でしょう。オブジェクトが持つ固有のロジックをカプセル化することによって外部からはメソッドの名前と役割だけを認識できるようになります。そのことによって、オブジェクト間の関係をよりシンプルにわかりやすく組み上げていくことができます。

犬の飼い主の立場でkの意味を考えてみます。犬の行動をメソッドと考えると飼い主には犬が「餌を食べる」「走る」「吠える」などのメソッドは見えますが、犬がどのような仕組み（ロジック）で餌を食べたり走ったりするかを知っている必要はありません。


今回は以上です！引き続き頑張ります🔥読んでいただきありがとうございました！
C言語+MPIのtips（MPI_Allreduce）

MPI_Allreduce は「各プロセスの持つ同じ長さのデータを何らかの演算をして，その結果をすべてのプロセスに渡す関数」。
※ MPI_Reduce は結果をある一つのプロセスに渡していたことに注意。

【目的】
 一次元配列 my の和を求めることで MPI_Allreduce の機能を知る。

【使用するもの】 
open-mpi

【環境】
 $ mpicc --version 
Apple clang version 11.0.3 (clang-1103.0.32.29) 
Target: x86_64-apple-darwin19.6.0
 Thread model: posix 
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

【方法】

```c:Allreduce.c 
#include<stdio.h>
#include"mpi.h"

int main(int argc, char *argv[]){

  int my_rank, num_proc;
  int i, my[3], sum[3];
  int j;

  MPI_Init(&argc, &argv);
  MPI_Comm_size(MPI_COMM_WORLD, &num_proc);
  MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

        for(i=0;i<3;i++) my[i] = i*4 + my_rank;
        printf("my_rank=%d, my[0]= %d, my[1]= %d, my[2]= %d\n",my_rank,my[0], my[1],my[2]);
        MPI_Allreduce(my, sum, 3, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
        printf("my_rank:%d, sum[0]= %d, sum[1]= %d, sum[2]= %d\n",my_rank, sum[0], sum[1],sum[2]);

  MPI_Finalize();

  return 0;
}

```
【結果】
mpicc コマンドでコンパイル、mpirun コマンドでプロセス数を２にして実行。

```
$ mpicc Allreduce.c
$ mpirun -np 2 ./a.out
my_rank=1, my[0]= 1, my[1]= 5, my[2]= 9
my_rank=0, my[0]= 0, my[1]= 4, my[2]= 8
my_rank:1, sum[0]= 1, sum[1]= 9, sum[2]= 17
my_rank:0, sum[0]= 1, sum[1]= 9, sum[2]= 17
```

【考察（何が起きたのか）】
 まずプロセス０と１でそれぞれ my[0]、my[1]、my[2]が生成される。 それぞれのプロセスでのfor文で値が格納される。
 at プロセス０　my[0]=0*4+0=0、my[1]=1*4+0=4、my[2]=2*4+0=8 
at プロセス１　my[0]=0*4+1=1、my[1]=1*4+1=5、my[2]=2*4+1=9

MPI_Allreduceによって「my」が送信され「sum」が受信される。要素の数は「3」、データの型は整数（int）「MPI_INT」、操作は和を求めること「MPI_SUM」。 
sum[0]=（プロセス０でのmy[0]）＋（プロセス１でのmy[0]）
 sum[1]=（プロセス０でのmy[1]）＋（プロセス１でのmy[1]） 
sum[2]=（プロセス０でのmy[2]）＋（プロセス１でのmy[2]） 
結果は全てのプロセスへ送信される。

それぞれのプロセスでsumが表示されて終了。

【参考】
「mpi 並列プログラミング」と検索すると、より正確でより情報量の多い資料が見つかります。
Xcode12.0.1でXVim2を利用する

# 概要

Xcodeをvimのキーバインドで利用するため、XVim2をインストールする。
https://github.com/XVimProject/XVim2

# 手順

### 1. 証明書の作成

READMEのINSTALL.1にあるリンク「 You can read the instructions for how to do this and...」の通り実行する。
https://github.com/XVimProject/XVim2/blob/master/SIGNING_Xcode.md

キーチェーンアクセスを開き、メニューバーから「証明書アシスタント > 証明書を作成」を選択する。
![スクリーンショット 2020-10-24 10.07.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/802246/a3a73cd6-b807-0c4f-5476-5026ec21f87a.png)
以下の通り入力する。
![スクリーンショット 2020-10-24 10.09.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/802246/d3b29deb-26c9-5bd4-6b6a-7f1ceb616199.png)
コマンドラインから署名を実行する。(時間がかかるので放置。その後、ログインパスワードの入力を何度か求められる。)

```bash
sudo codesign -f -s XcodeSigner /Applications/Xcode.app
```

### 2. Xvim2リポジトリのclone

```bash
git clone https://github.com/XVimProject/XVim2.git
```

### 3. ブランチ切り替え

Xcodeのバージョンに合わせたブランチに切り替える。
ブランチのリストは以下の通り。
https://github.com/XVimProject/XVim2#branches-and-releases
※ 2020.10.24時点ではmasterブランチがXcode12に対応しているので、Xcode12を利用しているのであれば切り替える必要は無い。

ここで、以下の結果が空の場合はREADMEの手順通り設定を行う。「/Applications/Xcode.app/Contents/Developer」というようにパスが表示されれば問題無い。

```bash
xcode-select -p
```

### 4. make実行

cloneしてきたXVim2のディレクトリ内でmakeを実行する。

```bash
cd XVim2
make
```

### 5. Xcode起動

Xcodeを起動すると、以下のダイアログが表示されるので、「Load Bundle」を選択する。
![スクリーンショット 2020-10-24 10.42.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/802246/1307106d-cbdc-032f-df86-7bd05baa6b97.png)

※ 間違えて「Skip Bundle」を選択した場合は、Xcodeを閉じた上で以下のコマンドを実行する。(Xcode 12.0.1の場合のコマンド。最後のバージョンの指定はXcodeに合わせる。)

```bash
defaults delete com.apple.dt.Xcode DVTPlugInManagerNonApplePlugIns-Xcode-12.0.1
```

### 6. Xcode再起動

Xcodeを一度閉じて、再起動する。
成功すると、以下のようにカーソルがブロック型となり、Vimのキーバインドで操作が可能となる。
![スクリーンショット 2020-10-24 10.50.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/802246/aa8274df-b215-fabb-8a82-3cbc63134502.png)
Rails6でサーバーを立ち上げるまで（環境構築）

#Rails6で$ rails s をしてもエラーが出る

ProgateのRuby on Rails環境構築をやってみました。
[Ruby on Railsの環境構築をしてみよう！(macOS)](https://prog-8.com/docs/rails-env)

Progateで扱っているバージョンは5.2.4.1で、自分はバージョン6を使用したかったため、バージョンのところだけ6.0.3.4としました。
(Rubyのバージョンは2.6.6を使用しました)

そして無事最後まで行き、**$ rails s のコマンドを実行すると...エラーが出ました。**
=> Booting Puma
=> Rails 6.0.3.4 application starting in development 
（省略）
Webpacker configuration file not found /Users/name/Desktop/ruby_lesson/sample_app/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /Users/name/Desktop/ruby_lesson/sample_app/config/webpacker.yml (RuntimeError)

**どうやらWebpackerというものが必要だとのこと。**
**実際に調べてみると、Rails6ではwebpackerが標準になったそうです。**

参考にした記事
[Rails6サーバー起動時webpackerエラー(Node.jsアップデート, yarnインストール)](https://qiita.com/KZ-taran/items/d4c6eb1a41e0abd5b448)
[Rails6 開発時につまづきそうな webpacker, yarn 関係のエラーと解決方法](https://qiita.com/NaokiIshimura/items/8203f74f8dfd5f6b87a0)

上記の記事を読み、**$ rails webpacker:install を実行しました。しかしこれもエラー...**
node: command not found
nodejs: command not found
Node.js not installed. Please download and install Node.js https://nodejs.org/en/download/

**Node.jsがダウンロードされていないようだったので、ダウンロードしました。**
[Node.jsのHP](https://nodejs.org/en/)

インストールまでの流れは下記を参照。
[Node.jsをインストールする](https://qiita.com/sefoo0104/items/0653c935ea4a4db9dc2b)

nodeとnpmのバージョン確認をコマンドで行い、
再び、$ rails webpacker:installを実行すると...

Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/

**今度はyarnをインストールしろとのこと。**
**$ brew install yarn を実行。**
（なぜ上記のコマンドになるのかは分かりません...いろんなコマンドを試しましたが、上記でやっとインストール成功しました）

$ yarn -v でバージョン確認しインストールできていることが分かりました。

**そしてやっと、$ rails webpacker:install を実行。**
**Webpacker successfully installed 🎉 🍰が表示されました！！**

#$ rails sでエラーは出ていないのにサーバーが起動しない
**やっと最初の目的だった $ rails s を実行。**
エラー文出てない！！！
あとはProgateの記事どおりブラウザでlocalhost:3000をURLに入れるだけ...

入れてみるとブラウザにはあの画面が表示されません...
なぜか分からず、調べてみると、こちらの記事にたどり着きました。
[Rails 6 で rails s をすると起こる Webpacker エラーを解決](https://k-koh.hatenablog.com/entry/2020/01/15/115500#rails-s)

**$ rails s -b 0.0.0.0 をして、**
**localhost:3000ではなく、上記コマンド実行後に出てくるIPを入力しました。**

そうするとあの画面が出てきました！
成功のようです！

※その後コマンドを閉じて、$ rails sをしてlocalhost:3000にアクセスすると、立ち上げ成功しました。

yarnインストールまでの流れはしっくりきましたが、その後の流れについてはよく理解できませんでした。
とりあえず環境構築はできたということで、学習を進めていこうと思います。

Rails6の環境構築に苦戦されているプログラミング初学者の方が一人でも救われましたら幸いです。
PRML　演習問題  8.8（基本）　解答

## はじめに
本記事は, 機械学習の教科書の決定版ともいえる, **Christopher Bishop先生**による[**『Pattern Recognition and Machine Learning （パターン認識と機械学習）』**]  (https://www.microsoft.com/en-us/research/people/cmbishop/prml-book/) , 通称**PRML**の演習問題のうち, 私が解いた問題の解答を記したものです. これは, 私の所属する[生物測定学研究室] (https://www.ut-biomet.org/) の輪読会で**PRML**を取り扱っており, その勉強の一環として演習問題を解いたときのものです. なお, 他の演習問題の解答例に関する記事については, [PRML　演習問題　解答集　まとめ]  (https://qiita.com/Lab_of_Biomet/items/15e38ca34fafa8176d89) をご覧ください.
$$\newcommand{\indep}{\mathop{\perp\\!\\!\\!\\!\perp}}$$
 
## 問題
$a \indep b, c \mid d$ ならば $a \indep b \mid d$ であることを示せ. 


## 解答
まず, $a \indep b, c \mid d$ は, $d$が与えられた下で, $a$ の分布と $b, c$ の同時分布が条件付き独立であることを表すので, 

```math
\begin {align*}
p \left ( a, b, c \mid d \right )  = p \left ( a \mid d \right )  p \left ( b, c \mid d \right ) 
\tag{8.8.1}
\end {align*}
```
と書き表わせる. この $ \left ( 8.8.1 \right ) $ 式の両辺を $c$ に関して周辺化すると, 

```math
\begin {align*}
p \left ( a, b \mid d \right )  = p \left ( a \mid d \right )  p \left ( b \mid d \right ) 
\tag{8.8.2}
\end {align*}
```
が得られる. 
これを例の記法で書き直すと、$a \indep b \mid d$となる. 
したがって, $a \indep b, c \mid d$ ならば $a \indep b \mid d$ であることが示せた.  (証明終)
AndroidにおけるJSR-310実装

ちょっとツイッターに流れてきた情報を見て気になったので改めて調べてみました。

[https://twitter.com/red_fat_daruma/status/1268177028915716102:embed]


## TL;DL
- ThreeTenABPでJSR-310を利用する場合は環境によらず同じtz databaseを参照する（はず
- desugaringでJSR-310を利用する場合は実行環境により異なるtz databaseを参照する（はず

## java.util.Date と JSR-310 
java.util.Dateが使い勝手が悪いことは良く知られており、Java SE 8ではjava.util.Dateを置き換える`Date and Time API`が追加された。このAPIはJSR-310として標準化されており、インターフェースがデベロッパーフレンドリーであるだけでなくインスタンスがイミュータブル、スレッドセーフといった機能的な優位性を持つ。[1]

## AndroidでのJSR-310実装方法の変遷
前述の通りJSR-310はJava SE 8からの機能である。Android Gradle plugin4.0.0以降でJSR-310のdesugaring対応がされたが[2]、それまではThreeTenBPやThreeTenABP[3]のようなJava6,7向けにJSR-310をバックポートしたライブラリを利用する必要があった。またThreeTenBPはJSR-310と完全に同じ振る舞いをするわけではないという点にも注意が必要でタイムゾーン(tz database)は独自に実装されておりJREではなくThreeTenBP自体にパッケージされたtz databaseを参照するため、tz databaseの更新にはThreeTenBPの更新が必要であった。[4][5]

## tz databaseについて
世界各地域の標準時（time zone、タイムゾーン）情報をまとめたデータ群のことである、以下のように標準時からの差をタイムゾーンとオフセットにより定義する。厄介なのが世界各国でこの定義の更新は割と頻繁に行われているようで、年に数回はtz databaseの更新が行われていることだ。[6]


```
# Zone  NAME            GMTOFF  RULES   FORMAT  [UNTIL]
Zone    Asia/Tokyo      9:18:59 -       LMT     1887 Dec 31 15:00u
                        9:00    -       JST     1896
                        9:00    -       CJT     1938
                        9:00    Japan   J%sT
```
ZonedDateTime:  2020-08-01 00:00:00 (Asia/Tokyo)
OffsetDateTime: 2020-08-01T00:00:00+09:00


## Androidにおけるtz database
Android Gradle plugin4.0.0以降でJSR-310のdesugaring対応がされたと述べたが、これまでThreeTenABPで利用していたJSR-310に見えるものとdesugaringで利用可能となるJSR-310はtz databaseの取り扱いなど細かい部分で実は挙動が異なる。ThreeTenABPが参照するtz databaseはパッケージングされたものであるのに対してdesugaringしたJSR-310が参照するのはJava実行環境のtz databaseとなる。Android10以降の端末でいうと`/system/apex/com.google.android.tzdata.apex` に含まれているtz databaseを参照する。

またAndroid10以降でAPEXベースのモジュール更新メカニズム[7]が採用されたようでtz databaseの更新方法が変わっているようだが、Android9以前のOEMがAPKベースのメカニズムでtz databaseを端末にプッシュしていた方法と比べて今回の件について本質的な差異はないように思う。

## まとめ
JSR-310で実装するといってもThreeTenABPを使うかdesugaringを使うかで参照するtz databaseは異なる。今後はdesguaringでJSR-310を利用するほうに流れていくと思うが、その場合実行環境によって異なるバージョンのtz databaseを参照することは避けられないのではないだろうか。


## 参考
[1] [https://builder.japan.zdnet.com/sp_oracle/35067620/:title]

[2] [https://developer.android.com/studio/write/java8-support#library-desugaring:title]

[3] [https://github.com/JakeWharton/ThreeTenABP:title]

[4] [https://www.coppermine.jp/docs/notepad/2016/12/threeten-extra-and-threeten-backport.html:title]

[5] [https://www.threeten.org/threetenbp/apidocs/org/threeten/bp/zone/TzdbZoneRulesProvider.html:title]

[6] [https://www.oracle.com/java/technologies/tzdata-versions.html:title]

[7] [https://source.android.com/devices/architecture/modular-system/timezone?hl=ja:title]
AM送信所マップを作ってみた

AM放送局の送信所を地理院タイルにマーカーで表示してみます。

送信所のjsonを作ります。とりあえず東北の各県にある民放の一番出力の大きい主幹送信所のみをデータにしてみました。

送信所の住所は[でんぱでーたどっと混む](http://www.denpa-data.com/)さんで調べて[Geocoding.jp](https://www.geocoding.jp/)さんの航空写真で確認して調整してあります。座標はアンテナの位置に合わせています。

https://gist.githubusercontent.com/yamori813/16065bbff4473e8ec3430570fcf7da7f/raw/4e1b1673465d247ae137aeb9fecec63015fc8128/radio.json

gistのrawデータはヘッダーに"Access-Control-Allow-Origin: *"を付けてくれるので、ローカルのファイルから読み込んでもエラーになりません。

これを地理院タイルにマーカーを置きます。

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>AM DX MAP</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script>
        function init() {
            $.getJSON("https://gist.githubusercontent.com/yamori813/16065bbff4473e8ec3430570fcf7da7f/raw/4e1b1673465d247ae137aeb9fecec63015fc8128/radio.json", null, function(data,status){
    //取得成功したら実行する処理
 
                var map = L.map('mapcontainer', { zoomControl: false });
                var mpoint = [35.8627, 139.6072];
                map.setView(mpoint, 6);
                L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/blank/{z}/{x}/{y}.png', {
                    attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>"
                }).addTo(map);
                for (var i = 0; i < data.radio.length; i++) {
                    //ポップアップする文字（HTML可、ここでは画像を表示）
                    var popup = L.popup().setContent(data.radio[i].name + " " + data.radio[i].frequency + "kHz");
                    //マーカーにポップアップを紐付けする。同時にbindTooltipでツールチップも追加
                    L.marker([data.radio[i].latitude,data.radio[i].longitude]).bindPopup(popup).bindTooltip(data.radio[i].corporation).addTo(map);
                }
            });
        }
    </script>
</head>
<body onload="init()">
    <div id="mapcontainer" style="position:absolute;top:0;left:0;right:0;bottom:0;"></div>
</body>
</html>
```

こんな感じになります。

![Screenshot_2020-10-24 AM DX MAP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/d5f715f9-d51d-0057-a2d1-f4159d741738.png)

あとは全国版のjsonを作るだけ。

追記

全国版のjsonできました。当初対象を主幹局で作っていましたが、1kw以上の局にしてみました。[広域大阪無線保全課](http://www.kouiki.com/index.html)さんの情報も大変参考になりました。いくつかは住所で出てこなく、いろいろ検索してみました。すべて航空写真で確認しました。

https://gist.githubusercontent.com/yamori813/16065bbff4473e8ec3430570fcf7da7f/raw/radio.json

手書きのjsonなのでところどこミスがあり、jsonチェッカーで確認しました。^ ^;

gistのURLはレビジョンのハッシュを取ると最新のデータになるようです。

地理院タイルを標準地図にして拡大すると電波塔の記号が確認できます。

![Screenshot_2020-10-25 AM DX MAP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/c4350ca3-e3f8-dda2-d144-3c222934c29d.png)

アンテナは海の中にあるものや、島にあるもの、ゴルフ場の中にあるものなどあり、形もいろいろでした。航空写真で全国アンテナめぐりできて楽しかったです。

HTMLもgistに置いてブラウザで直接見れるようにしました。

https://gist.githack.com/yamori813/16065bbff4473e8ec3430570fcf7da7f/raw/map.html
【Ruby on Rails】Formオブジェクト(ActiveModel)のエラーメッセージを日本語化する方法

## 本記事の概要

・Formオブジェクトのバリデーションエラーが日本語にならない問題に悩んだので、備忘録として残しておきます。
・＋α余談としてActiveRecoｒｄとActiveModelの違いについて少し触れました。

### 開発環境
Mac OS Catalina 10.15.4
ruby 2.6系
rails 6.0系

### 前提条件
gem 'rails-i18n'を導入してデフォルトの言語設定はすでに日本語にしています。
また、configのlocalsディレクトリにja.ymlファイルを作成済みです。

## エラーメッセージを日本語化できなかった原因とその対策

結論から言うと、今回作成したFormオブジェクトは```include ActiveModel:Model```によってactivemodelを継承したモデルであったにも関わらず
activerecordを継承したモデルとして日本語化を行おうとしたのが問題だったよう。


<誤っていたコードの記述>

```ruby:ja.yml
ja:
  activerecord:
    models:
      detail: 詳細情報
      posts_tag: 投稿 
    attributes:
      user:
        name: 名前
      detail:
        age: 年齢
        pr: PR文
        area_id: 居住地
        occupation_id: 職業
        interest_id: 興味
      posts_tag: 
        title: タイトル
        content: 概要
        name: タグ
```

<正しいコードの記述>

```ruby:ja.yml

ja:
  activerecord:
    models:
      detail: 詳細情報
    attributes:
      user:
        name: 名前
      detail:
        age: 年齢
        pr: PR文
        area_id: 居住地
        occupation_id: 職業
        interest_id: 興味
  
  activemodel:
    models:
      posts_tag: 投稿 
    attributes:
      posts_tag: 
        title: タイトル
        content: 概要
        name: タグ
```

### 余談

ちなみに、```rails g model```で生成するデフォルトモデルが継承しているActiveRecordとActiveModelの違いは、DBとのやり取りが可能か否かにあります。

前者は、可能なのでモデル名.findなどですでに保存してあるデータを引っ張ってこられますが、後者のActiveModelは通常findメソッドは使えません。

他にも、バリデーションにおける```validates uniqueness: true``等も、DBに保存されているデータを参照して一意性かどうか判断するので、ActiveModelで記述することはできません。

そんな感じで便利な一方、割とActiveModelはややこしいですね...
なにはともあれ、最後までお読み頂きありがとうございました!
【Laravel】Array to string conversion〜の解決方法


##はじめに
今回はLaravelでRequestを受け取ってfillしてsaveしようとした時に`Array to string conversion〜`のエラー出てきたのでその解決方法の一つをまとめたいと思います。

##Array to string conversion〜の解決方法
```php
<?php

namespace App\Http\Controllers;

use Request;
use DB;

//-----（省略）-----
public function postEdit(Request $request)
    {
        $inputs = $request->validatedValues();
        $user = User::findOrFail($inputs['id']);
        $user = fill($inputs->toArray())->save();

        return redirect("/users/{$user->id}/edit");
    }
```

fillしてsaveしようと思った時にredirectの直前の実装で`Array to string conversion〜`とエラーが出てきてしまいました。

あくまで1つの可能性ですが$requestの中身を確認した時にあるひとつの項目に対して複数選択が可能なjson型の項目があるとこのようなエラーになります。
そんな時はキャストを定義する必要があります。

```php:
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ネイティブなタイプへキャストする属性
     *
     * @var array
     */
    protected $casts = [
        'options' => 'array',
    ];
}
```

引用：[Eloquent：ミューテタ 8.x Laravel](https://readouble.com/laravel/8.x/ja/eloquent-mutators.html)

キャストを実装するとfillしてsaveできるようになるので参考にしてみてください。

##最後に
いかがでしたでしょうか。
またエラーが出てきて詰まった際にはこのようにまとめていきたいと思います。
初心者のためのGitとGitHub用語集

#GitとGitHub用語集(初心者用)

##Gitとは
Gitとは、プログラムソースなどの変更履歴を管理する分散型の`バージョン管理システムのこと。`プログラムの編集などができ、変更履歴も管理することが出来る。Gitがあることにより、昔の状態をみたり、復元したりが簡単になる。

##GitHubとは
GitHubとはGitを利用した、開発者を支援するWebサービス。　GitとGitHubの違いに私も最初は混乱しましたが、Gitはツールの名前で、`GitHubはGitを使ったWebサービスの名前。`

##リポジトリ(repository)
いわゆる`貯蔵庫`のこと。システムの開発プロジェクトに関連するデータの一元的な貯蔵庫を意味する。一種のデータベースで、各工程の様々な情報を管理することが可能。

##ローカルリポジトリ(local repository)
Gitのリポジトリはローカルリポジトリとリモートリポジトリに分けられる。ローカルリポジトリは自分のマシン内に作られ、`ワーキングツリー`が所属するリポジトリのこと。※ワーキングツリーに関しては後ほど説明あり

##リモートリポジトリ(remote repository)
自身の手元側にあるローカルリポジトリに対して、外部にあるリポジトリのことを指す。サーバなどネットワーク上にあるリポジトリもそれに当たる。公開、共有がスムーズなので複数人での開発に使われたり、個人開発でもネットワーク状にデータを保存したい時、共有したい時に使う。

##フォーク(fork)
forkはGitHubが提供する機能の一つ。fork は他の開発者のリポジトリを github上でclone(クローン）する。また、forkは、`fork元への貢献を前提とする。`開発を援助する前提の上で使う必要がある。

##クローン(clone)
クローンとはリモートリポジトリを手元のマシンの指定した場所に複製する。

##イニット(init)
一言でいうとリポジトリを新規作成、空のレポジトリが作成される。また、すでに存在するリポジトリの初期化をしたい場合にも使われる。

##ワーキングツリー(working tree)
Gitの管理下に置かれた、自分が実際に作業をしているディレクトリのこと。作業ディレクトリ、ワークツリー、様々な呼ばれ方をする。

##インデックス(index)
インデックスとは、`コミットする前に更新内容の一時的な保存をする場所のこと`で、ステージとも呼ぶ。

##アド(add)
ワーキングツリーにあるファイルの更新内容を、インデックスに反映するためのコマンド。コミットする対象を登録する作業。

##コミット(commit)
`追加・変更したファイルをリポジトリに記録。`ゲームのセーブみたいな感じ。

##コミットメッセージ(commit message)

コミットした内容を記述する。変更内容の要約、変更した理由（内容、詳細）などを記述する。

##ヘッド(HEAD)
今いるブランチの最新のコミットの代名詞を指す。デフォルトではmasterの先頭を表し、HEADが移動することで、使用するブランチが変更される。

##プル(pull)
リモートリポジトリのコミットをローカルリポジトリに送り込む。データのダウンロードのようなもの。

##ブランチ(branch)
プロジェクトを分岐させることにより、プロジェクト本体に影響を与えずに開発を行える機能。ブランチにより、不具合が発生した場合も対応しやすく、１つのプロジェクトを同時進行で作業が可能。また、ブランチには下の画像のように複数種類がある。
![ブランチ命名規則.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605741/b27ab566-9dfb-1dab-cf21-b921578ed682.png)

##マスターブランチ(master branch)
`プロジェクトの本流のブランチ`で、リポジトリに最初のコミットを行うと、masterという名前のブランチを作成される。その後のコミットはブランチを切り替えるまでmasterブランチに追加されていく。

##マージ(merge)
`加えた修正を統合する作業をする。`変更を加えたブランチを元のブランチにマージして修正する。

##リセット(reset)
`最新のコミットを取り消す`また、ステージされたファイルを取り消す。

##リバート(revart)
取り消したいコミットに対して、それを`打ち消すようなコミットを新しく作成する。`ただ、既存コミットの履歴が消えるわけではなく、コミットログには残っている。

##リベース(rebase)
指定したコミットをブランチを変えて作り直すことが可能。また、コミットをひとまとめにしたりして、ログを綺麗にするコマンド。

##スタッシュ(stash)
コミットせずに変更を退避したいときに使用。あるブランチで作業中だけど、いますぐやりたいことができた時、作業するブランチを間違えてしまった時にコミットしていない変更を一時退避することが出来る。

##コンフリクト(conflict)
Gitの場合同じファイルの`同じ場所への変更が同時にある時に生じるエラーのこと`を指す。

##フェッチ(fetch)
リモートリポジトリの最新の履歴の取得を行う。取得を行うのみなので、マージが自動で行われないのがpullとの違い。

##チェックアウト(checkout)
今作業しているブランチから出て、`他の作業ブランチで作業をしたい場合`に使用するコマンド。

##プッシュ(push)
ローカルリポジトリの内容をリモートリポジトリに反映させる。

##プルリクエスト(pull request)
開発者のローカルリポジトリでの変更を他の開発者に通知するGitHubの機能。会社やチームでコードレビューする時に使用。
2重のモーダル画面を作成する

備忘録として記載しておきます。

If you have both modal boxes in the same component then in the first modal box class you can write a condition as follows:
class="{!v.secondModal? 'slds-fade-in-open' : 'slds-modal slds-fade-in-open'}"

同じコンポーネントに２つのモーダルボックスがある場合、最初のモーダルボックスクラスで次のように条件を記述できます。

class="{!v.secondModal? 'slds-fade-in-open' : 'slds-modal slds-fade-in-open'}"


質問と回答
https://trailblazers.salesforce.com/answers?id=9064S000000DFRT
DockerでPlantUML Serverの環境構築をやってみた

先日業務でクラス図を描くことが有りました。クラス図を描くのは応用情報受験以来。。。しかも応用情報は穴埋め問題でパターン暗記。。。その業務は無事終わりましたが、モデリングについて勉強してみることにしました。そこでプログラミング感覚でUMLを描くことが出来るPlantUMLの実行環境(PlantUML Server)の環境構築をDockerを使ってやってみました。

# コンテナイメージのPull
[Docker Hub](https://hub.docker.com/r/plantuml/plantuml-server)より公式のイメージをダウンロードします。以下のコマンドで実行出来ます。

```bash
docker pull plantuml/plantuml-server
```

Docker Ver1.13.x以降で採用されているコマンド形式を採用すると以下のコマンドで実行できます。

```bash
docker image pull plantuml/plantuml-server
```

# コンテナの起動
コンテナを起動します。`--restart=always`オプションを渡すことで、ホストが再起動された場合に自動でコンテナも再起動されます。Jetty版かTomcat版を選べる様ですが、筆者は特に指定しませんでした。logを確認した所、Jetty版が標準では起動される様です。どちらにしてもJavaで実装されていることに変わりは有りません。

```bash
docker run -d -p 8080:8080 --name plantuml-server --restart=always plantuml/plantuml-server
```

以下のコマンドでも実行可能です。

```bash
docker container run -d -p 8080:8080 --name plantuml-server --restart=always plantuml/plantuml-server
```

# 起動確認
ホスト上で確認する場合、ブラウザを起動して`localhost:8080`にアクセスします。以下の画面に遷移すれば成功です。描画したUML図はSVGかASCII Artとしいて表示可能な様です。

![plantumlsv](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/001e2e83-2ef5-598e-c265-71dcaa0d54be.png)

* クラス図の例

<img width="200" alt="plantuml" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/c939d92e-5c0a-c9df-b468-6dfbc4d0a6c6.jpeg">

# まとめ
PlantUML Serverの環境構築が出来たので、以下の書籍でモデリングの勉強をしたいと思います。

* [技術評論社電子書籍購入ページ](https://gihyo.jp/book/2017/978-4-7741-9039-6)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/46cff989-1c19-3a42-7e47-1d0069b4dd9f.png)
remの使い方

#remとは
rem（レム）は「root em」の略で、名前のとおり「最上位階層の『em（エム）』」を意味します。
###pxとの違い
#####メリット
pxによるサイズ指定は、主要なグラフィックソフトでWebサイト用デザインを制作する際サイズの単位としてｐｘが用いられていることもあり、デザインデータとの整合性を取りやすいです。

#####デメリット
文字サイズを指定すると、ブラウザによってはユーザー操作による文字サイズの拡大／縮小に対応できなかったり、タブレットやスマートフォンなど、高解像度のディスプレイを備える端末で表示をした場合に、端末ごとに見た目の文字サイズが大きく異なって表示（下図）されたりする場合があります。

###％との違い
#####メリット
様々な閲覧環境に対応するため、「％（パーセント）」という単位が用いられるようにより、「80％＝親要素の文字サイズの0.8倍」という形で文字サイズを指定することが可能になりました。

#####デメリット
グラフィックソフトでは文字サイズを％で指定することは少ないため、デザインとの整合性が取りづらく、親要素の文字サイズを基準とした指定になるため、HTMLタグが入れ子構造になっているような箇所では個々の要素の最終的な文字サイズが把握しづらい、という面があります。

###コード
```css
html{
  font-size: 62.5%;/* 10px相当 */
}

/* body
----------------------------- */
body{
  font-size: 1.6rem;/* 16相当px */
}
```

##参考
[remを使ってCSSの文字サイズ指定](https://www.pc-koubou.jp/magazine/23912)
「最新取得」の使い方 - DBUpdateTool

Excelアドイン
DBUpdateTool(https://www.lasis.com/products/dbupdatetool)

全行について、セルとDBのデータを比較し、差分がある場合は、セルの背景色を変更して差分を表現します。 その後、DBのデータとExcelシート内の既存のデータを比較し、Excelシート内に存在しないレコードを取得します。

1. 「Microsoft SQL Server Management Studio」にて、現在のテーブルのデータを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/805113/70ae5c56-5b34-5f31-f59c-d807f4d904a7.png)

2. Excel上に、テーブルのデータが存在しないのを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/805113/e12fe4b8-a48f-a1c0-99d5-ff7a01cc9534.png)

3. Excelの「アドイン」タブにある「DBUpdateTool」の「最新取得」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/805113/382331b4-297a-6294-adb3-0932ee36e495.png)

4. 処理が完了しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/805113/b24e103f-f592-cb31-ec24-488f2a4f45b7.png)

5. 「Microsoft SQL Management Studio」で事前に確認したテーブルのデータが、Excel上に表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/805113/e3d2388b-0f00-bcdb-abc6-eac5c10bcf1e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/805113/5e22838b-47e0-39a2-3e22-b694df3d41ab.png)
派生したブランチを最新の状態にする

#Gitでブランチの派生元を最新版に変更する

`rebaseコマンド`
Gitでブランチの派生元を最新版に変更するにはrebaseコマンドを使用する。rebaseコマンドは、Gitでブランチを作成した後に派生元に変更があった際に、派生元を最新版のものに変更することができる。rebaseコマンドの使用方法は以下の通り。

`使用例 `
リモートのdevelopブランチより作成したfeatureブランチがある想定。
developブランチに変更があったためrebaseコマンドで派生元を最新版に変更してみる事に。

```
git rebase origin/develop
```

以上で派生元が変更される。ちなみに競合などがあった場合は手作業で修正を行う。修正が完了したら以下のコマンドを入力する。

```
git add <file>
```
```
git rebase --continue
```

これで派生元を最新版に変更することが可能。
Python 3 エンジニア認定データ分析試験受験前学習について

Python 3 エンジニア認定基礎試験に合格したので次はデータ分析を受けようと学習している途中経過を残しておこうと思います。

## エンジニア認定データ分析試験とエンジニア認定基礎試験の違い

まずエンジニア認定基礎試験とエンジニア認定データ分析試験の違いは何かというとエンジニア認定基礎試験はPythonのみの試験。試験範囲は狭く、python以外の言語を経験した人であれば1週間程度勉強すればいいくらいの範囲の狭い試験です。

エンジニア認定データ分析試験は主にライブラリと数学の試験です。
他の言語をやっていたとしても、ほぼ1から勉強から勉強することが多く時間がかかりそうです。

## 試験範囲

試験範囲のライブラリは以下の4つ
・NumPy
・pandas
・Matplotlib
・scikit-learn

[エンジニア認定データ分析試験の4つのライブラリを勉強してみた](https://qiita.com/Hidenori-Yamaguchi/items/0c0baaf1d2f5c9ddb977)

この4つのライブラリが試験問題の**67.5％**も占めています。
次に多い問題が数学の基礎問題が**15％**となっています。
**合格ラインは70%**ですので、数学の基礎問題をある程度やりつつ、ライブラリに時間を費やせば受かると思っています。
[指定教材](https://www.amazon.co.jp/Python%E3%81%AB%E3%82%88%E3%82%8B%E3%81%82%E3%81%9F%E3%82%89%E3%81%97%E3%81%84%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-AI-TECHNOLOGY-%E5%AF%BA%E7%94%B0-%E5%AD%A6/dp/4798158348/ref=as_li_ss_tl?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8&qid=1599359168&sr=8-5&linkCode=sl1&tag=isekihakken-22&linkId=1e0444405f510c550fb0e103ab7cc8fc&language=ja_JP)からは以下の割合で問題が出題されます。
(参考:https://www.pythonic-exam.com/exam/analyist)

|章|節|章立て|問題数|出題率|
|:--|--:|:--:|:--:|:--:|
|1||データエンジニアの役割|2|5.00%|
|2||Pythonと環境|||
||1|実行環境構築|1|2.50%|
||2|Pythonの基礎|3|7.5%|
||3|Jupyter Notebook|2|2.5%|
|3||数学の基礎|||
||1|数式を読むための基礎知識|1|2.50%|
||2|線形代数|2|5.00%|
||3|基礎解析|1|2.50%|
||4|確率と統計|2|5.00%|
|4||ライブラリによる分析実践|||
||1|NumPy|6|15.00%|
||2|pandas|7|17.5%|
||3|Matplotlib|6|15.00%|
||4|scikit-learn|8|20.00%|
|5||応用: データ収集と加工|0|0.00%|






◆受験方法
受験日：通年
試験センター：全国のオデッセイコミュニケーションズCBTテストセンター
申込URL：http://cbt.odyssey-com.co.jp/pythonic-exam.html
受験料金：1万円（税別）　学割5千円（税別）
※申込み方法や受験方法に疑問がある場合は、オデッセイコミュニケーションズへ直接お問い合わせください。
※試験内容については公平を期すためにご質問へは一切回答致しません。

◆「Python 3 エンジニア認定データ分析試験」概要
試験名称：Python 3 エンジニア認定データ分析試験
（英名：Python 3 Certified Data Analyst Examination）
資格名：Python3 エンジニア認定データ分析試験合格者
（英名：Python 3 Data Analyst Certification）
概要：Pythonを使ったデータ分析の基礎や方法を問う試験
受験料金：1万円（外税）　学割5千円（外税）
問題数：40問（すべて選択問題）
合格ライン：正答率70％
試験センター：全国のオデッセイコミュニケーションズCBTテストセンター
主教材：
2018年9月19日発売（税込2,678円）
「Pythonによるあたらしいデータ分析の教科書」（翔泳社）
著者：寺田 学、辻 真吾、鈴木 たかのり、福島 真太朗（敬称略）


## 模擬試験

こちらのサイトには模擬試験と解説動画があります。
模擬試験は3回分あり、かなりお勧めです。
まだ始めたばかりなのか解説動画は私が見たときの再生回数は12回で、長さは2分くらいと短く説明速度が速いため事前知識はある程度必要だと思います。
個人的にはちょっとわかりにくい動画だと思いました。


[PRIME STUDY](https://study.prime-strategy.co.jp/)

私自身まだ本試験は受けていないが、模擬試験を受けた感想としては、もしも普段pythonやデータ解析に関わっていないのであれば必ず模擬試験をやったほうがいいと思います。
良い面として問題の傾向がわかるのはもちろんですが、時間配分が分かることが重要かと思います。
とはいえ、この試験で時間がギリギリだったという記事は見たことがないので問題はないかもしれません。


## 勉強法

私の勉強法は、ただJupyter notebookで指定教材をポチポチ打ってライブラリを使用しているだけです。
「このように」教材を読むだけではなく実際に使用しないと、記憶するのが難しいかもしれません。
数学基礎が苦手な方は、少し時間をとってUdemyなどで探すと分かりやすい動画があります。
私は以前、機械学習の動画を購入して基礎数学をやったことがあるので（学生の時の記憶はなし）あとは指定教材で十分な気がします。


## 勉強をはじめたときの感想

今まで業務でpythonを使用したことがほとんどないため、エンジニア認定基礎試験に合格後しばらくするとpythonの基礎さえ忘れてしまっていました。
もしもエンジニア認定基礎試験に合格したばかりの人がいるならば、感覚をあけずにエンジニア認定データ分析試験を受けることをお勧めします。



## まとめ

エンジニア認定基礎試験を合格できるレベルの人であれば、おそらく1カ月あれば受かると思います（もう一度言いますが私はまだ受けていない）。
お金のかかる教材は指定教材のみで受かる試験だと思っているので、迷ってる人であれば受けるべし。
zsh: command not found: jupyterの対応

##背景
新しいmacが支給されて、```pip3 install jupyter```でjupyterをインストールし、ターミナルで```jupyter notebook```と入力すると、``zsh: command not found: jupyter``とエラーが返ってきました。

macOS Catalinaになってデフォルトのシェルがzshになり、pathを通さなければいけないとのこと。

##やったこと
```find ~/.zshrc```などでファイルがあるか確認、
なければ```touch ~/.zshrc```でファイルを新規作成

```Vim .zshrc```を開き、以下の1行を追記する

export PATH=$PATH:[追加したいディレクトリの絶対パス名] 
```export PATH=$PATH:$HOME/Library/Python/3.8/bin```

esc、```:wq```で .zshrcを閉じ、以下のコマンドでzshを再起動
```source ~/.zshrc```

##参考
[zshにPATHを通す方法](https://tkhs0604.hatenablog.com/entry/zsh-path-setting)
firebaseのStorageのフォルダをローカルにバックアップする

Android,iOS向けにOCRアプリを作っているのですが、firebaseのStorageデータ容量が増えてきたので削除することにしました。その前にローカルにバックアップ取ったのでその時のメモ。

## 値段の目安

現在の容量これです。

![スクリーンショット 2020-10-24 8.42.01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550742/5edb2386-db56-c892-214a-78688611102d.jpeg)

費用は、

![スクリーンショット 2020-10-24 8.45.40.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550742/2f83a4d8-6500-7930-37b1-08c16aa67336.jpeg)

ということなので、まぁ１GBで３円、、？　なんか安すぎるかもしれないが少ないに越したことはないので削除します。
https://firebase.google.com/pricing?hl=ja


## 方法

結論から言うと、

```
gsutil cp -r gs://backup-bucket ./backup
```
で行けます。
https://medium.com/scalp/how-to-back-up-firebase-firestore-and-firebase-storage-bucket-b6d8dbc0cd7c

https://medium.com/@BrodaNoel/how-to-backup-firebase-firestore-8be94a66138c

## 補足

まず、gcloudでログインします

```
gcloud beta auth login
```

もしここで詰まったら、
```
gcloud components update
```

でベータ版をインストール。それもいかないならgcloud SDKがインストールする。
https://cloud.google.com/sdk/docs/install?hl=ja


自分のプロジェクトの一覧を取得します

```
gcloud projects list
```

プロジェクトを切り替えます

```
gcloud config set project <your-project-id>
```

firebaseにログインしてbackupを取りたいフォルダのパスをコピーします。

あとは、

```
gsutil cp -r gs://backup-bucket ./backup
```

で行けます。

ソフトはこちらです。

アップル
https://apps.apple.com/app/id1497498494
Google
https://play.google.com/store/apps/details?id=com.rainbowsv2.ocr
CSS：サイズ指定は比率・相対指定

# フォントサイズ、余白、幅などの指定は相対的に

　レスポンシブデザインのポイントになるのは「サイズ」。
　「サイズ」は、画面の幅によって動的に変動させる。
　また、ブレークポイントによって異なるサイズを指定しないといけない。

　このとき、いろいろなパーツに個別のサイズを指定していたのでは管理が大変。
　なので、その画面の起点となるサイズを定めたら、それの比率で他のサイズを決めていく。
　ブレークポイントごとに、その起点のサイズを変える。
　以下は、サンプル。

```sass:sample.sass

/* mixin：タイトルの集合 */
+titles($baseFontSize)
  .title
    font-size: $baseFontSize
  .sub-title
    font-size: $baseFontSize * 0.8  

/** デスクトップ以外 **/

//デスクトップの基準サイズ
$pcBaseSize: 1vw 
.container
  =titles($pcBaseSize)

/** デスクトップ以外 **/
@media screen and (max-width: $desktop)

//デスクトップの基準サイズ
$spBaseSize: 3vw
.container
  =titles($spBaseSize)

```
　
コード量を減らせるだけでなく、文字間のバランスを統一的にできるので、個別指定よりは相対的な指定をする方がよいと思います。

「多行は悪」がコーディングの指針ですね。
【自動化】PythonでOutlookの予定を抜き出す

## Outlookで予定と実績を管理しているけれど…

私の会社はメール文化なので、Outlookでメールをやり取りし、仕事や会議の予定もOutlookで管理しています。
また、日報や週報での実績報告のために、いつ何をどこまでやったかもOutlookの予定に記録しています。

結果として、**Outlookの予定表は予定と実績記録だらけで、目視で管理するのが面倒な状態**になります。

週報にその日の業務実績を書く場合も、Outlookの予定表を書き写さないといけません。
私の業務はかなりマルチタスクで1日の予定の数がすごいことになっているので、手作業で確認して書き写すのがとても面倒です。

Pythonを使うとOutlookから予定表をまとめて抜き出すことができるので、あとはテキストファイルなりExcelなりに整形して、日報などにそのまま貼り付けることができます。

本記事では**Microsoft Outlookのクライアントソフトから、Pythonで予定を抜き出す方法**をご紹介します。

##PythonでOutlookの予定表を抜き出す

outlookを操作するためにはwin32com.clientをimportする必要があります。
私はAnacondaを使っていますが、特に追加でインストールしなくてもimportできました。

```python:python
import win32com.client
```

次にOutlookのオブジェクトを作成し、予定表と取り出します。

```python:python
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
calender = outlook.GetDefaultFolder(9) # 「9」というのがOutlookの予定表のこと
```

このcalenderというのが予定表です。
では早速、期間を指定して予定を抜き出してみましょう。
ここでは【2020-10-19～2020-10-23】の予定を抜き出してみます。
※例として、この期間には2つだけ予定を登録しています。

```python:python
import datetime

items = calender.Items # このitemsが一つ一つの「予定」

select_items = [] # 指定した期間内の予定を入れるリスト

# 予定を抜き出したい期間を指定
start_date = datetime.date(2020, 10, 19) # 2020-10-19
end_date = datetime.date(2020, 10, 23) # 2020-10-23

for item in items:
    if start_date <= item.start.date() <= end_date:
        select_items.append(item)

# 抜き出した予定の詳細を表示
for select_item in select_items:
    print("件名：", select_item.subject)
    print("場所：", select_item.location)
    print("開始時刻：", select_item.start)
    print("終了時刻：", select_item.end)
    print("本文：", select_item.body)
    print("----")
```

```:実行結果
件名： 不具合調査
場所： 実験室1
開始時刻： 2020-10-20 10:00:00+00:00
終了時刻： 2020-10-20 11:30:00+00:00
本文： ハングする不具合の調査をAさんと行う。
----
件名： コードレビュー
場所： 会議室3
開始時刻： 2020-10-22 14:00:00+00:00
終了時刻： 2020-10-22 15:00:00+00:00
本文： Bさん、Cさんとと案件1234のコードレビューを行う。
----
​
```

予定を抜き出せていますね！
日報などの形式に合わせてprint文を工夫すれば、出力結果をそのままコピペできるはずです。

## コードまとめ

最後にコードをまとめて載せておきます。

```python:python
import win32com.client
import datetime

outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")

calender = outlook.GetDefaultFolder(9)

items = calender.Items # このitemsが一つ一つの「予定」

select_items = [] # 指定した期間内の予定を入れるリスト

# 予定を抜き出したい期間を指定
start_date = datetime.date(2020, 10, 19) # 2020-10-19
end_date = datetime.date(2020, 10, 23) # 2020-10-23

for item in items:
    if start_date <= item.start.date() <= end_date:
        select_items.append(item)

# 抜き出した予定の詳細を表示
for select_item in select_items:
    print("件名：", select_item.subject)
    print("場所：", select_item.location)
    print("開始時刻：", select_item.start)
    print("終了時刻：", select_item.end)
    print("本文：", select_item.body)
    print("----")

```




## Microsoft Office関連の自動化

Microsoft Officeに関連する他の自動化シリーズはこちらです。ご興味があればどうぞ！

【自動化】PythonでOutlookメールを送信する
https://qiita.com/konitech913/items/51867dbe24a2a4272bb6

【自動化】PythonでOutlookのメールを読み込む
https://qiita.com/konitech913/items/8a285522b0c118d5f905

【自動化】Pythonでメール(msgファイル)を読み込む
https://qiita.com/konitech913/items/fa0cf66aad27d16258c0

【自動化】PythonでWordの文書を読み取る
https://qiita.com/konitech913/items/c30236bdf47775535e2f
Laravelのenvメソッドがスレッドセーフ版のPHPでは正常に機能しない

#環境
Windows 10 Pro
Apache 2.4
PHP 7.3 スレッドセーフ版
Laravel 6.18

#現象について
Laravelでの開発中に
envメソッドで時々値が読み込めない場合や
Apacheの公開ディレクトリに配置している他プロジェクトの環境変数を取得してしまう？現象が発生した。
（他プロジェクトの環境変数を取得しているかは確証はないがそれっぽい値を取得してしまう）

調査した結果
PHPのgetenvがスレッドセーフ版のPHPでは正常に機能しないことを発見した。

#対応策について
設定ファイルをキャッシュすればいいらしい。

```
php artisan config:cache
```
設定ファイルをキャッシュすると
envメソッドが実行されなくなるので注意が必要である。

環境変数を変更した場合はその都度上記コマンドを実行し
キャッシュを更新する必要がある。

#まとめ
Windows+Apache環境でLaravelの開発をする場合、
この現象に遭遇する確率が高いので注意が必要。

ちなみにLaravelの公式ドキュメントには
この問題への注意喚起はないと思われる。
（あったらすみません）

ノンスレッドセーフ版なら上記の問題は発生しないので
dockerでノンスレッドセーフ版の環境を作って開発したほうがいい気がしてきた...


#参考URL
laravelやphpdotenvのissueで既に議論されていたのでご参考に
https://github.com/laravel/framework/issues/8191
https://github.com/vlucas/phpdotenv/issues/76
FreeRTOS理解その６（ボタン押下をキューに入れて通知）

# ボタン押下すべてを別タスクに通知
ESP32搭載のM5Stackには3つのボタンがある。ボタン押下すべてを別タスクに通知することを目的とする。

## 環境
ESP32搭載のM5Stack、FreeRTOS、Arduino IDE利用。

## 方針
ボタンをハンドリングするタスクにて、押下されたことをキューに入れて、別タスク（ここではloop()）に通知する。これには複数タスクの排他制御の簡略化も意図している。また、長押しと短押しとの区別も通知する。

## ソースコード
### インクルードファイル
```c++:misc.h
#ifndef Misc_h
#define Misc_h

#define STACK_SIZE 512

// Button in M5Stack
#define NUM_BTN 3
#define L_BTN   39  // GPIO
#define M_BTN   38
#define R_BTN   37

enum {L_SHORT, L_LONG, M_SHORT, M_LONG, R_SHORT, R_LONG};
#define IDX_SHORT  0
#define IDX_LONG   1
#define CHATTERING 20    //ms
#define LONG_PUSH  1000

#endif
```
このファイルでは、M5Stackボタンの[GPIOの定義](https://github.com/m5stack/m5-docs/blob/master/docs/en/api/gpio.md)、長押しの定義（1秒以上押下）、それぞれのボタンの長押しと短押しなどを定義する。

### ボタンハンドリングタスク
```c++
#include "misc.h"
extern QueueHandle_t qBtn;

xTaskHandle xBtnH;

void BtnTask(void *arg) {
  uint8_t btn[] = {L_BTN, M_BTN, R_BTN};
  uint8_t msg[][2] = {{L_SHORT, L_LONG}, {M_SHORT, M_LONG}, {R_SHORT, R_LONG}};
  uint32_t t[NUM_BTN], p;
  
  for (int i=0; i<NUM_BTN; i++) {
    t[i]= 0;  // initialize timers
  }
  while (1) {
    for (int i=0; i<NUM_BTN; i++) {
      if (!digitalRead(btn[i])) {
        if (!t[i]) {
          t[i] = millis();     // timers start when button is pushed.
        }
      } else if (t[i]) {       // button is released after timers start.
        p = millis()-t[i];
        if (p > CHATTERING) {  // prevent button chattering
          uint8_t val = ((p < LONG_PUSH)? msg[i][IDX_SHORT]: msg[i][IDX_LONG]);
          xQueueSend(qBtn, &val, portMAX_DELAY);  // Send value to loop()
        }
        t[i] = 0;              // timer is reinitialized.
      }
    }
    vTaskDelay(1);
  }  
}

void createBtnTask() {
  xTaskCreate(BtnTask, "BtnTask", STACK_SIZE, NULL, 1, &xBtnH);
}
```
ボタンごとにタイマーを設け、仮想チャタリング時間(20ms)を超えた場合にはボタン押下とみなし、長押しか短押しかのメッセージを[xQueueSend()](https://www.freertos.org/a00117.html)によりキューに入れる。

## メイン
```c++
#include "misc.h"

QueueHandle_t qBtn;  // Information (value) from button task

void setup() {
  Serial.begin(9600);
  pinMode(L_BTN, INPUT);
  pinMode(M_BTN, INPUT);
  pinMode(R_BTN, INPUT);
  qBtn = xQueueCreate(4,                // Queue length
                      sizeof(uint8_t)); // Queue item size
  createBtnTask();
}

void loop() {
  uint8_t btn;
  char *pushed_btn[] = {"Left short", "Left long", "Middle short", "Middle long", "Right short", "Right long"};
  
  if (xQueueReceive(qBtn, &btn, portMAX_DELAY) == pdPASS) { // Wait forever
    Serial.printf("%s pushed\n", pushed_btn[btn]);
  }
  vTaskDelay(1);
}
```
ボタン初期化、[xQueueCreate()](https://www.freertos.org/a00116.html)によるキューの作成、[xQueueReceive()](https://www.freertos.org/a00118.html)によるキューからのメッセージ取得。

## 実験
例えば、こんな感じ。

```
Middle short pushed
Right long pushed
Right short pushed
....

```
確実にボタン押下を捕捉。

## 最後に
1. 複数ボタン同時押し処理
xQueueReceive()があるタスクにて、複数キューのハンドリングを行えば、複数ボタンの同時押し処理も可能である。

1. キューの数と処理時間
今回は４としたが、

```c++
  qBtn = xQueueCreate(4,                // Queue length
                      sizeof(uint8_t)); // Queue item size
```
キューからメッセージを取り出した後の処理時間がかかるようであれば、数値を大きくする必要があるだろう。


実は続きがあります。