OmniAICreator/Qiita-1.07M huggingface dataset:
IBMCloud 今から無料で始めるVPC①-初期導入編-

##目的
これからIBMCloudを始める人向けに、VPC環境の導入方法について記事を書いてみる。
オンプレ同様にサーバを構築してサービスを提供する場合、ClassicもしくはVPCが可能。
今後は、VPCを利用した環境が標準となると思われるので、VPC上で構築するのがオススメ。
また、GCPやAWSに似た考えで導入できるので、割と簡単に導入できる。
<font color="red">**VPC環境は無料で試せるので是非やってみよう**</font>

あらかじめクレジットカードの登録による、アカウントのアップグレードが必要。
登録後は、下記の金額分無料で試すことができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/866a8106-21e6-be76-582f-3bcff0955d8f.png)

##初期導入編について
今回はVPCをオーダするまでをスコープとする。

* 初期導入編:（**本ページ**)
* サーバ導入編:[IBMCloud 今から無料で始めるVPC②-サーバ導入編-](https://qiita.com/khoshina/items/db8c49fcce7a7fc4ab1b)
* セキュリティ設定編:[IBMCloud 今から無料で始めるVPC③ -セキュリティ設定編 -](https://qiita.com/khoshina/items/d0ed3922f74a5a36a222)
* ストレージ追加編:[IBMCloud 今から無料で始めるVPC④-ストレージ編-](https://qiita.com/khoshina/items/dad5406ce806e6ae78bf)

[その他VPC関連]

* VPN:[IBM Cloud(VPC) x GCP IPsecVPN接続](https://qiita.com/khoshina/items/39d8e5671e3d59a968c9)
* AutoScale + LB：[AutoScale用VPCロードバランサ](https://qiita.com/khoshina/items/4094175ff8d58d6a3dbd)、[CPU負荷によるAutoScale VPC](https://qiita.com/khoshina/items/d10adf46cf2b787ed37e)



###VPCの作成

**VPCインフラストラクチャ-** -> **VPC**を選択
![貼り付けた画像_2020_10_30_23_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/8f86e5cd-fd50-0379-0192-cb30b76635fc.png)

なにをやるにしても、まずは**VPC**を作成する必要があるので、右上の**作成**を選択
VPCについての詳細はこちら：[Virtual Private Cloud について](https://cloud.ibm.com/docs/vpc-on-classic?topic=vpc-on-classic-about&locale=ja)
![IBM_Cloud_Infrastructure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/b98a314c-7b2d-c321-cd4f-d1b3be97a9ad.png)

名前:**任意名**
リソースグループ:**Default**
本格的に運用する場合は、リソースグループ毎にアクセス制御を実施するのがベスト
こちらを参照:[リソースを編成してアクセス権限を割り当てるためのベスト・プラクティス](https://cloud.ibm.com/docs/account?topic=account-account_setup)

タグ:**必要に応じてリソースの識別タグを記入**
SSHを許可:**必要に応じてチェック**
pingを許可:**必要に応じてチェック**
デフォルトのアドレス接頭部:リージョン毎にアドレスが自動採番される。問題なければチェックをいれたままにする。

本格的に運用する場合は、アドレス設計を検討しましょう：[VPC のアドレス指定計画の設計](https://cloud.ibm.com/docs/vpc-on-classic-network?topic=vpc-on-classic-network-vpc-addressing-plan-design)
利用されるアドレスの範囲はこちら：[IP アドレス範囲、アドレス接頭部、リージョン、およびサブネットの理解](https://cloud.ibm.com/docs/vpc-on-classic-vsi?topic=vpc-on-classic-network-working-with-ip-address-ranges-address-prefixes-regions-and-subnets&locale=ja)

![IBM_Cloud_Infrastructure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/1d2b8244-3635-b81a-a483-1f362f706dbc.png)

名前:**任意名**
リソースグループ:**Default**
ロケーション:**作成したいロケーションを選択**
IP範囲選択:**必要に応じてアドレスの数**を変更

各項目を選択肢、**仮想プライベート・クラウドの作成**を選択
![IBM_Cloud_Infrastructure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/5a3b0ebc-5284-d906-2f86-1a9d52b3b138.png)
Google Play Storeでリジェクトされた App Rating : App is incorrectly rated as AO - Adults Only. 

#初めてGoogle Playでリジェクトされた！！
![スクリーンショット 2020-10-29 18.05.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/a8d0c99f-dbbf-a071-179b-9db9f2e1e3f2.png)

アプリをアップデートするとまさかの**reject**でした。。。

#理由は？
**「コンテンツレーティングのガイドラインに違反している」**ということでした。。。

うーん。よくわからんが、意図してレーティングを「18歳以上」にしたのがよくなかったのかも。

レーティングは`アプリのコンテンツ＞コンテンツのレーティング`で質問に回答することで変更できる。
![スクリーンショット 2020-10-29 18.11.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/014c5d87-2707-6db3-3f92-41e87cafffb3.png)

というのも、アプリ内で使っているAdmob広告から以下のような警告？が来たからので、レーティングを上げれば「ユーザーに不快な思いをさせないで！」と言われなくなるかな？と思い、、、:sweat:
![スクリーンショット 2020-10-29 18.24.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/6288eff6-a0fb-22cd-991f-11c811644d7c.png)

それでレーティングを上げまくった結果、**「アプリの内容とレーティングがあってないよ！」**
と言われた訳だ。。。

再度レーティングを設定した後、admob側で「デリケートな広告」を一部ブロックした事で丸く治りましたとさ:relieved:
【Auth0】ソーシャルログインしたときの外部IDプロバイダーのアクセストークンを取得する

# はじめに
Auth0で外部のIDプロバイダーを利用してソーシャルログインをすると、利用したIDプロバイダーから取得できた情報でユーザーが作成されます。
この作成されたユーザーには、IDプロバイダーから取得できたアクセストークンもデータの一つとして保存されます。

今回はManagementAPIを使って、ソーシャルログインで作成されたユーザーのデータからIDプロバイダーのアクセストークンを取得してみました。

# 利用するユーザーデータ
本記事では例として以下のようにソーシャルログインで作成されたユーザーを利用します。

![スクリーンショット 2020-10-31 14.36.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653972/1b717b8b-7275-dbef-699e-8275c6ae2b6e.png)

`PRIMARY IDENTITY PROVIDER`をみてもらえればわかるように、Goolgeでログインをして作成したユーザーです。

Auth0の管理画面からuser情報の`Raw JSON`等をみても特にアクセストークンは表示されません。
ManagementAPIを使ってユーザー情報を取得したときだけアクセストークンを取得できるみたいです。

# IDプロバイダーのアクセストークンを取得

以下のAPIを使ってユーザー情報を取得します。

**Get a user**
https://auth0.com/docs/api/management/v2#!/Users/get_users_by_id

```http
GET https://{Auth0テナントのドメイン}/api/v2/users/{ユーザーID} HTTP/1.1
```

リクエストが成功するとユーザー情報が取得できます

```json
{
  "created_at": "2020-10-31T05:34:57.252Z",
  "email": "XXXXXXXX@gmail.com",
  "email_verified": true,
  "family_name": "XX",
  "given_name": "XX",
  "identities": [
    {
      "provider": "google-oauth2",
      "access_token": "ya29.A6fHA0S.......................................",
      "expires_in": 3599,
      "user_id": "..........",
      "connection": "google-oauth2",
      "isSocial": true
    }
  ],
  "locale": "ja",
  "name": "XXXX",
  "nickname": "XXXXXXXX",
  "picture": "https://lh3.googleusercontent.com/a-/.................",
  "updated_at": "2020-10-31T05:34:57.252Z",
  "user_id": "google-oauth2|..........",
  "last_ip": "XXX.XXX.XX.XX",
  "last_login": "2020-10-31T05:34:57.250Z",
  "logins_count": 1
}

```

取得できたJSONに`identities`という配列があり、ここにユーザーに紐づくIDプロバイダーの情報が載ってきます。
このIDプロバイダーの情報の中の`access_token`プロパティを参照すると、そのIDプラバイダーから取得できたアクセストークンを取得できます。

# おわりに
ユーザー情報からアクセストークンを取得した後はソーシャルログイン時にユーザーから同意を得たスコープの範囲内で、このアクセストークンを使ってIDプラバイダー側が提供するログインユーザーのリソースにアクセスすることができます。
必要があれば試してみてください。
C# .NetCoreで、ボートレース結果の解析　読み込みその2


# やらなきゃいけないこと
前回
C# .NetCoreで、ボートレース結果の解析　構造検討
https://qiita.com/TamanegiTarao/items/04f43d96e50cb3eeaa03
で内容が取り出せるようになった。
しかしながら、細かいバグさらいが必要だった。
その話。

## レース結果がない場合

レース結果がない場合は以下のような場合がある。

```
例：K191014.TXT
02KBGN


ボートレース戸　田
データは、この場の全レース終了後に登録されます。


02KEND　←本来はここで開催日情報が来る行数
```

開催日情報が来る行は、文字列のパターンで拾うことがむつかしいところであるため、
現状``XXKBGN`` 検知からの行数で把握していた。
また``XXKEND``の検知をしていなかった。

この２点を対応するようにコードを修正し解決。

7行目(開催日情報が記載されているか)

```
private static bool IsStringInDate(string str){ return Regex.IsMatch(str, "..../../.."); }

private static bool IsStringInInDay(string str){ return Regex.IsMatch(str, "第..日"); }

private bool IsStringLine7(string str){ return IsStringInDate(str) && IsStringInInDay(str); }
```

``Regex.IsMatch(string target, string pattern)``でパータン検知することで、
適切な行であるか検知できるようにした。
``.``で１文字ワイルドカードである。こういう場合は便利。
https://www.atmarkit.co.jp/ait/articles/1701/25/news025.html

XXKENDの検知、XXKBGNで開始、XXKBGNで終了を徹底。

```
if (line.Contains("KBGN"))
{   // １.開催場コードの取得
    place = Lib.IntParse(line.Replace("KBGN", ""));
    inLineInfo = 0;
    start = true;
}
else if(line.Contains("KEND"))
{
    inLineInfo = 0;
    start = false;
}
else if(start)
{
    if (inLineInfo == 5) // 文字列を含むかどうかで拾うのがむつかしい
    {  
    	/*　略 */
    }
    else if (inLineInfo == 7)// 文字列を含むかどうかで拾うのがむつかしい
    {   // ３.節間日、開催年月日の取得
        if (IsStringLine7(line))
        {
            raceBase.Place = place;
            raceBase.InDay = Lib.IntParse(_StringExtraction(line, 5, 2));

            DateTime dateTime = new DateTime(Lib.IntParse(_StringExtraction(line, 19, 4)),
                                                Lib.IntParse(_StringExtraction(line, 24, 2)),
                                                Lib.IntParse(_StringExtraction(line, 27, 2)));
            raceBase.Date = dateTime;
            if (entryfirst)
                internodeTitle.Start = dateTime;
            internodeTitle.End = dateTime;
        }
        else
        {
            Console.WriteLine("Error:" + line + " " + raceBase.Date.ToString("yyyyMMdd"));
        }

    }
    /* 略 */
}
```

## ２周時の配慮不足

通常ボートレースはコースを３周するが、荒天により２周になる場合がある。

```
   1R       予　選　　　                 H1800m  晴　  風  北　　 2m  波　  3cm
```

```
  10R       予選特賞　　                 H1200m  雨　  風  北　　 2m  波　  3cm
```
従来は``H1800m``で拾っていたがこれでは、2周時に拾うことができないので、

```
private bool IsStringInRoundInfo(string str) { return Regex.IsMatch(str, "H1.00m"); }
```
で拾うように変更した。
単純なバグですね。。。

## まとめ
これにより、１年分のデータを取得してみたが取れている様子である。
必要だったら修正しなければならないが、いったんは読み取りはできるようになったと判断。

今後は、展示情報のスクレイピングしていきたい。

次回
C# .NetCoreで、ボートレース結果の解析　スタ展スクレイピング
https://qiita.com/TamanegiTarao/items/0d7d4a1e0452c866c2fd
テストとは・テストの重要性について

#テストとは

**テストとは**プログラムが想定どおりの動きをするか確認するためのプログラム

##テストの重要性
①バグを減らしてユーザーに安心して使ってもらえる
②プログラムを変更しやすくなる
③プログラムを書くのが早くなる

①サービスを使用してもらってるユーザーに、バグが出ないことを保証するためにテストを書き安心して使ってもらえる
②テストを書くことで、どこまで動いてるか確認でき、原因を見つけやすくなる。機能の削除や追加、編集がしやすくなる
③開発側が、コードを書いた際にバグが出てもテストのおかげで原因を見つけて修正しやすくなるので、安心してコードをかける。

テストの重要性は、プロジェクトや会社によって変わるためどこまでテストを書くかは一概には言えない
医療系では、患者のデータの流出や情報が閲覧できなくなるなどのエラーはかなり防ぎたいものだと思うので、テストの重要性は高いと考える。
機能の追加や編集が少ないようなサービス。お金が発生しないような簡単なアプリケーションなら少なくても良い場合がある。

##railsのテスト
**railsのテストには主に３つ**
・requst spec(Controllerテスト)
・model spec(Modelテスト) 
・system spec(見た目のテスト)

テストの流れは(Controllerテストの場合)
①タイトルが未入力時に保存されないという設定を確認したい
②タイトルが未入力のダミーデータを作成し、実行
③ダミーデータが保存されていないかの確認

##まとめ
今回は、テストについて軽く説明しました。テストは書けば書くほど保守性が上がると思っていますが、１００個以上書くとなると大変なので、今度なるべく簡単にテストをかけるような記載方法を紹介していきたいと思います。
Laravelでnpm installをした時に、No Xcode or CLT version detected!と表示される問題

##No Xcode or CLT version detected!
laravelでアプリ開発中に、npm installコマンドで下記画像のエラーが発生。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605741/04a798a6-d27b-bf4d-adb5-fe8d73c4e360.png)
どうやらXcodeがインストールされていなくてエラーを吐いている様子...。
Xcodeをインストールする為に下記のコマンドを実行。

```
$ xcode-select --install
```
ポップアップが表示され、順調にインストールされていると思いきや...。
下記画像の様にインストールが中断された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605741/349eecd6-1b0e-be00-e3df-b2e47df01808.png)
##手動でのダウンロードへ切り替え！
色々ネットで調べてみると、どうやら手動でXcodeをインストールすると解決するとの事。
以下のリンクから、More Downloads for Apple Developersへ移動する。

[Xcodeのインストールページ](https://developer.apple.com/download/more/) (下記実際の画面)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605741/d9cec10e-1d11-055e-b3df-3100206227f1.png)
2020年10月30日時点で、最新のXcodeバージョンは12.1となってたので、上から2つ目の「Xcode12.1」をインストール。

インストールが始まるとこの様なポップアップが表示される (体感的に1時間程度)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605741/e1adab86-c475-9b86-744a-14e3c1496125.png)
##改めてnpm installコマンドを実行する
インストール終了後、npm installコマンドを実行！

```
$ npm install
```

同じ様な現象で悩んでいる方がいましたら、是非参考にして頂けると幸いです！
nuxt/pwaのiconが変わらない！

# nuxt/pwaを使用する場合の注意点


あるプロジェクトでnxut/pwaを使うことがあり、ハマったとろこがあったので書かせてもらいます。


nxut/pwaでiconを設定したい場合は、staticディレクトリに、icon.pngというファイル名で保存しないといけません。

![スクリーンショット 2020-10-31 14.31.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417546/abd18a71-bb18-b1a3-a4bd-881fb7fb9223.png)


別の画像にしたいと思い、新しい画像に変更しても前に設定されたiconが表示されました。

## 解決方法
nuxt/pwaのIconは、{rootDir}/node_modules/.cache/pwa/icon にキャッシュされるという特徴で、新しく画像を置き換えても、前回のキャッシュが残っており画像が反映されていなかったのです。

```bash
$ rm -rf node_modules

$ yarn or npm install
```

を実行してキャッシュをクリアして依存関係を再構築しましょう。

そしたら、新しいiconになってるはずです！
Google Play Consoleから前のバージョンのappファイル（もしくはapk）を削除するには？

#はじめに
Google Play Consoleの画面の見方と操作方法が分からずにめっちゃ困ったお話。
新しいGoogle Play Consoleになってから、どこにどのボタンがあるか？などわからず、かなり時間を費やしてしまったのでここに記録する！

#目的
![スクリーンショット 2020-10-29 22.32.00.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/dc229871-4f79-61c6-7c6c-0a1fbd797785.jpeg)
上記の一覧から「バージョンコード31と32」を削除したいのです。

**新しいGoogle Play Consoleからだと、どの画面のどこのボタンを押せば削除か？
それがなかなかわからなかった**:joy: 

#背景
そもそも、「なんでアップローダしたappファイルを削除したいのか？」ということから書きていく。

###環境
ストアで公開されているアプリのバージョンは下記の通り。
・バージョンコード29 
・バージョン(1.3.8) 

###アップデートがリジェクトされた
**バージョンコード30、バージョン(1.3.9)のバージョンが審査の結果リジェクトになり、アプリのアップデートは承認されませんでした。。**
![スクリーンショット 2020-10-29 22.17.49.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/dbdf41fe-30de-7460-f0eb-a4a91c9c18ff.jpeg)

（しかし、バージョンコード30、バージョン(1.3.9)のバージョンはずっと審査中。。なんで？？w）
![スクリーンショット 2020-10-29 22.17.44.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/0db54002-0061-f28b-078f-811ed8db2db2.jpeg)

###リジェクトされたバージョンと同じバージョンコードでappファイルをアップロードすると、appファイルがアップロードできなかった
「新しいリリースを作成」から「バージョンコード30」のappファイルをアップロードすると、「すでに存在するバージョンコード」という事でエラーになりました。
![スクリーンショット 2020-10-29 22.08.33.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/51e4d244-b7a4-88db-b85b-03feceaeb696.jpeg)
:middle_finger:上記はバージョンコード31の場合だが、こんな感じで「ダブったバージョンはアップロードできない」と言われた。。

###不備のあるバージョンをアップロードしてしまった
バージョンコード30はすでに存在するからダメだという事で、バージョンコードを１つ上げた「バージョンコード31」を「新しいリリースを作成」からアップロード。

しかし、そのバージョンには不備があることに気付き、製品版としての公開はせずに「リリースの破棄」をクリックました。
![スクリーンショット 2020-10-29 22.32.34.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/a84d7bbc-8b7f-16dc-b519-51b2c9532210.jpeg)

###「不備のあるバージョン」から１つ上げたバージョンをアップロード
「バージョンコード31」を再びアップローダすると、やはりすでに存在するためアップロードできませんでした。なので、「バージョンコード32」をアップロード。
**すると、「バージョンコードが +2になるからダメ」と言われました。。**
こちら:point_down:と同じエラーです。。
[完全にブロックされた APK](https://www.hirohomme.com/2019/06/03/完全にブロックされたapk/)

「えーーー、どうすればいいの〜？？」って事で、今回の問題に繋がるのです。。。

#解決策
**App Bundle エクスプローラー＞右上のArtifact: 31.abb**（ここの数値は現在アップされている最新バージョン）**＞下からスライドアップで表示された画面で、各バージョン横の→をクリック＞もしアップロードされただけのバージョンなら、「Android App Bundleを削除」のボタンがある？**（詳しくは未確認）

![スクリーンショット 2020-10-29 23.13.09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/2383874c-5811-8e4b-efd9-a1f55f56c0c0.jpeg)

![スクリーンショット 2020-10-29 23.13.28.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/4f219008-6e0b-0d85-6c96-8a2532aa8386.jpeg)


![スクリーンショット 2020-10-29 22.41.44.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/8d7aafd6-0945-978d-3465-d23aef6b4290.jpeg)

これで「バージョンが被ってるからappファイルアップロードできません！！！」みたいな問題は解決！！
間違ったバージョンをアップロードしてしまった方がいたら、参考になるかと:sweat_smile:
【Docker】MySQLワークベンチに繋がらない…DBコンテナのポートフォワーディングの設定

Dockerを個人的にいじっていて遭遇した問題。
ポートを変更したいけど、うまく行かなかったときの解決策メモ。
いいやり方があれば教えて下さい。

# MySQLコンテナのポートフォワーディングを変更したい
```yml
# docker-compose.yml
version: "3"
services:
  db:
    build:
      context: ./docker/mysql
    container_name: db
    volumes:
      - db-store:/var/lib/mysql
      - db-logs-store:/var/log/mysql
      - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    environment:
      - MYSQL_DATABASE=${DB_NAME:-JETmysql}
      - MYSQL_USER=${DB_USERNAME}
      - MYSQL_PASSWORD=${DB_PASS}
      - MYSQL_ROOT_PASSWORD=${DB_PASS}
      - TZ=${TZ:-Asia/Tokyo}
    ports:
      - ${DB_PORT}:3307 #アクセスするポート：コンテナ内のポート
volumes:
  db-logs-store:
  db-store:
  redis-store:

```

```env
# .env
DB_CONNECTION=mysql
DB_HOST=db #0.0.0.0
DB_PORT=3307
```

ポートフォワードというのは特定のポートにやってきた通信リクエストを、
転送してあげることです。
通常、MySQLの場合3306番が使われますが、競合を避けたい事情で3307を
あてがおうと考えました。

上記YMLの、ports部分にポートを定義します。
${DB_PORT}部分は、envファイルから引っ張るようになっています。
左側がポートフォワーディング先、右側がDockerコンテナ内部で使用されるポート番号です。
「ローカルのポート3307にリクエストが来たら、コンテナ内の3307につないでね」という意味です。
コンテナはローカル端末とは隔離されたネットワークという位置づけのため、
コンテナ内部でもポート番号があるという認識です。

ここだけ定義すれば、よしなにやってくれるのかと思っていたのですが、
3306以外ではなぜか繋がらないという事象に見舞われました。
今回はMySQLワークベンチというGUIを接続しようとしていました。

![Screen Shot 2020-10-31 at 13.55.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429030/c39002ae-b60d-90a3-8b61-c5724d9cbfdf.png)

### docker-compose ps 

```sh
           Name                           Command               State                Ports
-------------------------------------------------------------------------------------------------------
db                              docker-entrypoint.sh --por ...   Up       3306/tcp, 33060/tcp,
                                                                          0.0.0.0:3307->3307/tcp
```

定義されているように見える。。


# docker runする場合のポート指定

```sh
docker run -p 3307:3307 db
```
これだとうまくいきます。
だとすれば、コマンドでポート指定すればうまくいく？

# ymlにコマンドを追記

```yml

    ports:
      - ${DB_PORT}:3307 #アクセスするポート：コンテナ内のポート
    command: --port 3307
```
![Screen Shot 2020-10-31 at 13.56.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429030/1a709502-83da-a13f-aa95-cd7702953435.png)

うまく接続できたようです。
なぜポート指定のコマンドが必要なのかわかりませんが、
一応これで動くようです。
STM32L010F4P6のUSARTシリアル書き込み(UART)

STM32L010F4P6のUSARTシリアル書き込み成功まで約1か月試行錯誤した。

2020/10/31現在　STM32L010のシリアル書き込みは、STM32CubeProgrammerのみ
2021/06/10現在  05:41:09 : STM32CubeProgrammer API v2.7.0でも同じ
2021/08/08現在  05:09:03 : STM32CubeProgrammer API v2.8.0でも同じ


[使用したUSBシリアル変換器]
ＦＴ２３４Ｘ　超小型ＵＳＢシリアル変換モジュール
通販コード　M-08461
[接続ピン]
BOOT0 3.3V
VDD,VDDA 3.3V
GND ->GND
PA9(TX) -> USBシリアルRX
PA10(RX) -> USBシリアルTX

構成(5V->3.3V)

低損失ＣＭＯＳ三端子レギュレータ　３．３Ｖ５０ｍＡ　Ｓ－８１２Ｃ３３ＡＹ－Ｂ－Ｇ　（８個入）
[S-812C33AY-B-G]
通販コード　I-03289
発売日　2009/12/16
メーカーカテゴリ　エイブリック株式会社(ABLIC/ｴｽｱｲｱｲｾﾐｺﾝﾀﾞｸﾀ/ｾｲｺｰｲﾝｽﾂﾙ/SII)


セラミックコンデンサー　０．１μＦ２５Ｖ　Ｆ特性　（２００個入）
[DSXC75TJYF104Z]
通販コード　P-07935
発売日　2014/06/13
メーカーカテゴリ　三菱マテリアル株式会社



x書き終わったらbootを開放

1.書き込み装置を「ST-LINK」から「UART」に変更
2.USARTシリアル通信をUSBに接続
3.Portを再読み込み
4.この場合COM7を選択　各自違う
5.Erasing & programmingのアイコンを選択
6.File pathでファイル選択　この場合mded_blinky_011.NUCLEOL011K4(2).bin　各自違う
7.Skip flash..はアンチェック
8.Verify..はチェック
9.Run..は、アンチェック
10. Connectボタンを押す。接続が切れても気にしない。
11.Start Programmingボタンを押して書き込む
12.書き込み成功したらおわり。いったん抜いてbootを外す、挿す

忙しい人よう
https://github.com/caa45040/mbed_binky_010
mbed_blinky_010.NUCLEO_L011K4.bin を書き込むとブリンクします。(PA4)

書き込み画面への行き方

![kakikomi.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/5b8692cd-d4c1-69b6-306c-749318bbe815.jpeg)



![l010書き込み.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/e9032913-5690-7f46-23a9-e191f6b14851.jpeg)

![中華link_5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/e32571a9-485c-4911-3029-dc9a0c7047e1.jpeg)

![sel_L010_b_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/94e86e57-4fee-18c6-6a87-1b6920322dd8.jpeg)

![sel_L010_b_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/7c99caa3-deae-fd35-5d5e-7051bed996f4.jpeg)
ソケット通信とWebSocket

HTTP通信とソケット通信の違いってなんだ？となっていたらWebSocketと理解が混同していたとわかったのでまとめ。

# ソケットとは
プロセスのもつ出入り口。プロセス間で通信を行う場合や、プロセスからインターネットに繋ぐ場合の口となる。

# ソケット通信
インターネットを利用してWebサーバと通信する時には、TCPで通信を行うためのソケットを用意し、そこに相手のIPとポート番号を指定する。そしてコネクションを確立するとデータのやりとりを自由にできる仕組み。

プロセスがソケットを介して外と通信する時にはカーネルが介在する。
ネットワークからパケットが到達すると、カーネルはネットワークインターフェースで受信しIPヘッダとTCPヘッダを見て各プロセス(アプリケーション)が用意しているソケットに適切に選別してソケットバッファにデータを格納する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406130/81e94f13-6771-c702-b5e0-890f1cc911c4.png)

### ソケット通信の準備〜開始〜終了まで

```
サーバ側                                 クライアント側
1) socket() ソケット作成                  1) socker()
2) IPアドレス＋ポート番号の設定               2) IPアドレス＋ポート番号の設定  
3) bind() ソケットに名前つける
4) listen() 待機
5) accept()                          <-3) connect() 接続要求    # 3way handshakeが行われるのはここ
6) 通信 read()/write()                  4) 通信 read()/write()
7) close() 閉じる                        5) close() 閉じる
```

クライアント側ではbindが明示的にされないと、connectする際に任意のポート番号がカーネルから割り振られるので明示的にbindしなくても通信できる。
(なお、サーバ側も明示的にbindしなくてもいいが結局どのポートから送っているのかわからないのは困るのであとから調べる事になる。)

## TCP/IP

送る側

* 送信するデータをパケット単位に分けて送る。
* それにより複数の通信で一つの回線を使える。

ルータ

* ルータはパケットの宛先を見て正しく送ることだけが責任範囲。
* 目的地に届いたかは保証しない。
→ これを保証させるのがTCP(Transmission Control Protocol)の仕組み。
送る方と受け取る方でどのパケットがロストしたかを把握し、ルータは知らなくていいという仕組み。

* 経路に障害があったら別の経路を見つけるのもルーティングの仕事。

受け取る側

* 足りてないパケットを再要求する。

### TCP/IP通信開始

TCPで通信を開始する(セッションを構築する)には始めに3way handshakesと呼ばれる通信が行われる。。

1. SYNパケット(synchronize) : 通信していいですか？
2. SYN + ACK(acknowledgement) : いいですよ、こちらも通信しますね
3. ACK : いいですよ

TCPのセッションは、5タプル(プロトコル番号6、送信元IP、送信元ポート番号、宛先IP、宛先ポート番号)で区別している。

### 余談 (UDP)
UDPは後から開発されたもの。プロトコル番号が17番なのもその理由。
TCP/IPという呼び方ももとはTCPが当たり前だったから(パケットロスしない仕組みは必須)。ところが、音声等は多少ロスしてもリアルタイムである事の方が大事じゃない？となり、TCPからIPを切り離すことになった。

___

HTTP通信とソケット通信の違いってなんだ？
→ ソケット通信はTCP/IPレベルの通信である。アプリケーション層の通信であるHTTP通信も当然ソケットを使用している。ここで言うソケット通信と、HTTP通信と比較される`WebSocket`は別物。

# WebSocket
通信規格の1つ。
クライアント側からしか通信を開始できないというHTTP通信の問題に対応することができる(双方向通信)。

## HTTPでの様々な解決方法
従来のHTTPを用いて双方向通信を実現する様々な手段が検討されてきた。

* ポーリング
… 定期的にサーバ側に変更がないかを問い合わせる。→サーバ負荷やばい。サーバ側の変更反映のラグ。

* Comet : ポーリングを少し改善
… サーバ側に変化があるまでぎりぎりまでレスポンスを保留 →やはり上記の問題あり。

* Server Sent Events(SSE)
… チャンクデータとして分割して結果を返しているように見せる。コネクションをcloseしていないのでサーバ側からその後もデータを送りつづけらる。 → コネクションの占有時間が長く他のアプリケーションに影響。

## 新しい解決方法:WebSocket
WebSocketはこの問題に対応した新しい通信。

* 双方から任意のタイミングで通信を開始できる。
* ヘッダめっちゃ少ない(HTTP通信はヘッダ情報がでかい)。

## WebSocket通信の開始
### WebSocket opening ハンドシェイク

HTTPのUpgradeヘッダを用いてWebSocketの通信をリクエストし、サーバ側から101を返すことでプロトコルを変える。
このハンドシェイクを通してWebSocketによる通信が開始される。

なお、WebSocketは新しい通信規格であるため未対応の通信機器も多い。もちろんルータなどを対応させる訳にはいかない。
→ TLS/SSLで暗号化してあたかも`https://`のようにしまえばルータなどの通信経路上からはわからないため破棄されにくいということで`wss://`も利用される。



# 参考

* 書籍SoftwareDesign 2014/5
* https://qiita.com/chihiro/items/9d280704c6eff8603389
* https://www.slideshare.net/mawarimichi/websocketwebrtc
Javascriptのみで作るトップに戻るボタン(rails,haml)

## ■ はじめに

Javascriptのみで作るトップに戻るボタンについて記事にしました。
この記事で得る内容は以下の通りです。

・Javascriptの基礎知識が増える
・jQueryに依存せず、Javascriptを使ったトップに戻るボタンの作り方が理解できる様になる

・参考にさせて頂いたサイト・動画
→ [JSでscrollしたら◯◯する！スクロールに紐づかせて処理をしましょう！](https://www.youtube.com/watch?v=_agZ_AP6W44&ab_channel=%E3%83%95%E3%83%AD%E3%83%B3%E3%83%88%E3%82%A8%E3%83%B3%E3%83%89%E3%83%81%E3%83%A3%E3%83%B3%E3%83%8D%E3%83%AB-%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E5%BF%9C%E7%94%A8%E3%81%BE%E3%81%A7-%E6%AD%A6%E7%94%B0%E4%B8%80%E7%9C%9F)
→[【脱jQuery】Javascriptのみでトップへ戻るボタンを実装](https://flex-box.net/js-scrolltop/)

## ■ コード

```haml:index.html.haml
.scroll#scrollValue
  %i.fas.fa-angle-up

= javascript_pack_tag 'main' -# app/javascript/packs/home/main.jsを読み込む
```

```scss:index.scss
.scroll {
  position: fixed;
  right: 0;
  bottom: 0;
  font-size: 2rem;
  color: #fff;
  transform: translate(-50%, -50%);
  background-color: #333;
  padding: 0 14px;
  border-radius: 50%;
  visibility: hidden;
  opacity: 0;
  transition: 0.5s;
}
.scroll.top {
  visibility: visible;
  opacity: 1;
  transition: 0.5s;
}
```

```javascript:main.js
window.addEventListener("scroll", function () {
  const scroll = document.documentElement.scrollTop; // documentのルート要素で一番上からのスクロール値を取得する処理を変数で定義
  const PageTopBtn = document.getElementById("scrollValue");

  if (scroll > 300) {
    document.querySelector(".scroll").classList.add("top");
  } else {
    document.querySelector(".scroll").classList.remove("top");
  }

  PageTopBtn.addEventListener("click", () => {
    window.scrollTo({ // 文書内の特定の組み合わせまでスクロールする
      top: 0,
      behavior: "smooth", // スムーススクロール
    });
  });
});
Unity Ads でAndroidの広告を実装

今更ですが、UnityのAds でAndroid の広告を実装しました。
設定も簡単で実機の確認もすぐできました
最新の環境によって動かない可能性があるので、動かない方はこちらもご覧ください
https://qiita.com/aimkbiz/items/196b66b291622a70f7d6

# 【Switch Platformを行う】
android ios での機能なので、Switch Platform をします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771936/a9ea72e8-4c41-b015-1f13-213fd76c157b.png)


#【Unity Ads を有効にする】
Window > General > Services を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771936/a7c52ec4-f81b-320a-4fc0-c0e19129d663.png)

Project ID で自分のアカウントを選択しcreateボタンクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771936/89d69238-0cff-b6e2-f2a4-ac178237903b.png)

13歳未満も対象ですか？と聞かれるので、対象の場合はチェック。
今回の場合は、対象外にするので、チェックを外しています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771936/2257da4f-fdeb-2ea5-beb4-f15c7ae5a8cb.png)


#Ads を有効にする


Test Mode にチェック
実機にビルドする場合はTest Modeのチェックを外します
(android ios の番号は後で使います)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771936/172e76e2-b534-ec00-0b2f-b047b48fdf13.png)



#【広告を表示する場所に処理を書く】

c#側で表示したい位置に下記のように処理を書きます
先ほどのandroidとiosの番号を該当の「Advertisement.Initialize」に記載します
下記の場合はボタンクリック時に広告表示

```
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Advertisements;

public class MainController : MonoBehaviour {
    [SerializeField]
    protected Button _button;

    /// <summary>
    /// 初期設定
    /// </summary>
    protected virtual void Awake() {
        //初期化
#if UNITY_ANDROID
        Advertisement.Initialize("");
#elif UNITY_IOS
            Advertisement.Initialize("");
#endif

        _button.onClick.AddListener(() => {
            if (Advertisement.IsReady()) {
                Advertisement.Show();
            }
        });

    }
}

```


これだけ

Unity Editer上で実行すると下記のように表示されればおっけです


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771936/2c74a2f3-681d-58e4-471a-276cd85aee6d.png)




#【実機でビルドする(今回はandorid)】
・シーンを追加しBuildしてください(player Settingsの設定は割愛)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771936/e29cc7c6-3ad2-0196-6674-79e480dce842.png)



ビルドして実機で再生すると正規の広告が表示されます

#【Adsのアナリティクスを確認する】
下記にアクセスし、ログイン後該当のプロジェクトのアナリティクスを確認する
https://unity.com/ja/products/unity-ads
Amazon Echo (Alexa) でPCの電源を付ける

## 動機

帰宅時のもろもろ家電操作をアレクサの定型アクションにまとめたいな、と思ったのですが、PCの起動だけ方法が見つからなかったので作成しました。

Wake on LANのマジックパケットはラズパイとか使って飛ばしている記事を見かけたのですが、去年ぐらいからAmazon Echoでも飛ばせるようになってるらしく、Skill作ればAlexaだけで完結してスッキリするよね、ということで自作に。

## 実装方法

ソースコードと一緒に[github](https://github.com/algi-nao/alexa_wake_on_lan)に上げたのでそちらを参照してください。

対象PCはS5のWake on LANが出来る必要があります。
最近のPCのデフォルトだと、Windows10側で完全シャットダウン（クラシックシャットダウン）の設定とBIOS/UEFIでWake on LANの有効化をする必要があると思います。
やってみるつもりなら、[スマホアプリ](https://play.google.com/store/apps/details?id=co.uk.mrwebb.wakeonlan&hl=ja)とかで対応しているか確認してからがおすすめ。


## 感想

帰宅時に「アレクサ、ただいま」以外の家電操作が必要なくなったので快適です。
PC起動時に誤爆しても問題ないので安心。
MySQL ターミナルからのログインするときにデータベース名を指定する

# 目的

- ターミナルからMySQLにログインするときデータベース名を指定する方法をまとめる

# 実施条件

- MySQLにログインするユーザのパスワードがわかっていること（パスワードを忘れてしまった方はこちら→[Mac ローカル環境の MySQL 8.x のrootパスワードを忘れた時のリセット方法](https://qiita.com/miriwo/items/1880e9d2ebcfd3c0e60d)）

# 方法

- 下記下記コマンドを実行する。

    ```terminal
    $ mysql -u MySQLのユーザ名 -p データベース名
    ```
- MySQLのrootユーザでtestデータベースを指定してログインしたいときは下記を実行する。

    ```terminal
    $ mysql -u root -p test
    ```
- 上記のログインコマンドは下記を実行しているのと同じである。
    1. ログインコマンド

        ```terminal
        $ mysql -u root -p
        ```
    1. useでデータベースの指定
    
        ```sql
        use test;
        ```
- ログイン前からデータベース名がわかっているならちょっとの短縮ではあるが1回のコマンドでログインとデータベース指定をする事ができて楽である。
OwlgardenRPA - 遊んでみる2

# 遊んでみる その2

1. Yahoo!ファイナンスの株式ランキングページを表示
2. JASDAQ市場のランキング情報をすべて取得
3. CSVに出力

## 共通変数定義
| 変数名 | データ型 |
|:-:|:-:|
| ranking | 明細部ジェクト型 |

## シナリオの流れ

### 1. Yahoo!ファイナンスの株式ランキングページを表示

- COM名：アプリケーション実行

| プロパティ名 | 設定値 |
|:-:|:-:|
| 実行パス | （chromeの実行パスを設定） |
| 実行引数 | "--new-window https://finance.yahoo.co.jp/" |

- COM名：クリック
    - サイト上部の"株式"リンクを押下

- COM名：クリック
    - サイト上部の"株式ランキング"リンクを押下

- COM名：クリック
    - 市場を選ぶメニューリンクの中から"JASDAQ全体"リンクを押下

### 2. JASDAQ市場のランキング情報をすべて取得

- COM名：表形式一括列取得
    - 不可能!!

![pic_05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340394/58d711f4-3f84-5907-4db5-ff480688ec69.jpeg)


## 表形式を操作するCOM

### できること
- Windowsアプリケーション内の表形式（？）

### できないこと
- HTML内のtableタグで作られた表形式データ
- ブラウザ上で動くスプレッドシート
- Excel
- ページング対応

### 雑感
- 紹介ムービーでは表形式のデータも取得可能と謳われていたので期待したが、ブラウザ上の表形式データを操作できるものではないようだ。そもそも、Owlピッカーが反応しないので設定でどうにかできるようなものでもない。サポートサイトでは、社内システムでよくあるWindowsアプリケーションの操作を例に紹介されており、こういったものに特化したCOMなのかもしれない。そもそも、OwlgardenRPAはUIオブジェクトの認識はわりと優秀な印象を受ける一方で、ブラウザに特化したCOMはなくアプリケーション操作という括りでまとめられている。もしかすると、ブラウザやWebアプリケーションの操作はそれほど強くは意識されていないのかもしれない。
pytorchとtensoflowのバージョンをコマンドラインから調べる


※追記をまとめると以下
（pytorch,tensoflow,opencv,sklearn,pandas...）

python3の場合

```
python3 -c 'import torch; print(torch.__version__) '
python3 -c 'import tensorflow as tf; print(tf.__version__)'
python3 -c "import sklearn;print(sklearn.__version__);"
python3 -c "import cv2 ;print(cv2.__version__);"
python3 -c "import pandas as pd ;print(pd.__version__);"
python3 -c "import torchvision;print(torchvision.__version__);"
python3 -c "import pygame; print(pygame.version.vernum);"
```

pythonの場合

```
python -c 'import torch; print(torch.__version__) '
python -c 'import tensorflow as tf; print(tf.__version__)'
python -c "import sklearn;print(sklearn.__version__);"
python -c "import cv2 ;print(cv2.__version__);"
python -c "import pandas as pd ;print(pd.__version__);"
python -c "import torchvision;print(torchvision.__version__);"
python -c "import pygame; print(pygame.version.vernum);"
```

pytorchでcudaが使えるかコマンドラインから確認する

```shell
python -c "import torch; print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0));"
python3 -c "import torch; print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0));"
```

# pytorchとtensoflowのバージョンをコマンドラインから調べる

以下をコマンドラインから実行すればよい

```
python3 -c 'import torch; print(torch.__version__) '
python3 -c 'import tensorflow as tf; print(tf.__version__)'
```

以下のような結果がでる

```
$ python3 -c 'import torch; print(torch.__version__) '
1.3.0
$ python3 -c 'import tensorflow as tf; print(tf.__version__)'
1.14.0
```

# 追記

sklearnのバージョンは以下で調べる

```
python3 -c "import sklearn;print(sklearn.__version__);"
```

opencvのバージョンは以下で調べる

```
python3 -c "import cv2 ;print(cv2.__version__);"
```

pandasのバージョンは以下で調べる

```
python3 -c "import pandas as pd ;print(pd.__version__);"
```

# 参考
[【Python/PyTorch】バージョン確認](https://algorithm.joho.info/programming/python/pytorch-version/)
[TensorFlowのバージョンのチェック方法](https://qiita.com/JeJeNeNo/items/9dd1343eb7d01e9577ca)
エンジニアでも知っておきたい!マーケティング用語~サイト指標編~

# はじめに

自分も含めてwebエンジニアの方は日々技術のキャッチアップ、研鑽に励んでいると思います。

しかし最近ではwebサービスを技術側として創り上げていくにおいても、
開発の技術的な知識経験だけでなくマーケティングの知識を求められることも多いです。
特に自社でBtoCのサービスを運営している企業だと顕著な傾向です。

単に何か機能を追加する、改修する際にもそれがどれほどの効果があるのか?
という数値的な根拠を提示できることが大切になってきます。
(インフラ側の改修などはまた別の観点)

技術一辺倒ではなく、
サービスのグロースへの影響も考えながら開発ができるエンジニア
というのを私は強く意識して仕事に挑んでいます。

自分の開発がサービスの数値にどのような影響を与えるのかを少し考えるだけでも、
ビジネスサイド側との会話がスムーズにできるようになりますし、
視点が変わり、幅が広がると思います！

私もマーケティングの深い知識があるわけではないですが、
(新卒で広告代理店でweb販促の営業を1年やった程度)
その足掛かりとして本当に基本的なものですがウェブサイトのマーケティング指標をざっくり簡単にメモ程度にまとめました。
※一部webサイトに閉じておらずweb広告についての指標もあります。

# 閲覧数/ユーザー数 編
### PV（Page View）
・webサイト内の特定のページが閲覧された回数

### AU (Active User)
・特定の期間のうちにに1回以上利用があったユーザーのこと
・会員登録をしていても利用していないユーザーを除いた、実際に利用しているユーザーを表す

※AU(Active User)の数はサービス毎に定義が異なる。
ex) ECだと「購入したユーザ」をActive Userとする...etc

### CV (Conversion)
・サービスにおける最終的な成果
※CVもサービス毎に定義が異なる。
ex) ECだとユーザーが「購入した」ことを1CVとする...etc

### UU（Unique User）
・サイトを訪問したユーザの人数
・Aという人が1日にQiitaを何回訪れても1人でカウント
・ユーザーごとのcookieでカウントされる

### DAU (Daily Active User)
・1日あたりのUnique Userの数

### WAU (Weekly Active User)
・1週間あたりのUnique Userの数

### MAU (Monthly Active User)
・1ヶ月あたりのUnique Userの数

### SS (Session)
・ユーザーの訪問回数
・サイトに訪れてからサイトを去る(離脱)するまで

# 費用の単価と割合
### CPA (Cost Per Action / 顧客獲得単価)
・1人のユーザを獲得するのにかかった費用
・サイトや施策よって「新規会員登録のためのCAP」など定義が変わる
・CPAは低い方がいい
新規獲得のために広告を無闇に増やそうとすると、会員獲得数が増えるかもしれないが、CPAは上昇する可能性がある。

### CPC (Cost Per Click / クリック単価)
・1クリックされた時にかかった単価
・広告にかけた総費用 ÷ その広告のクリック数 = クリック単価(CPC)
・CPCは低い方がよい

### CTR (Click Through Rate)
・表示された広告がクリックされた頻度を示す割合
・クリック数 ÷ 表示回数 = クリック率（CTR)
・CTRは高い方がよい

### CVR (Conversion Rate / 顧客転換率)
・CVした人の数 ÷ サイト全体の訪問者数 = 顧客転換率(CVR)
・CVRは高い方がよい

### LTV (Life Time Value / 顧客生涯価値)
・ユーザーが取引を開始してから終了するまでの期間に、サービスに対してどれだけ利益をもたらしたか。
・新規顧客の獲得には大きなコストがかかります。せっかく獲得した顧客とも、取引が1回限りで終われば、得られる利益は少ない。
・顧客と信頼関係を築くことができて取引が続けば、獲得費用を回収することも、継続的な利益を生むことができるという考えに基づいた指標。
・1回の取引で得られる利益だけではなく、2回目以降の取引で得られる利益も含めて考える。
・最近サブスクリプションサービスなどが台頭してきて注目されるようになった。
・平均顧客単価×収益率×購買頻度×継続期間 － (新規顧客獲得コスト＋既存顧客維持コスト) = 顧客生涯価値

# まとめ
とてもざっくりと簡単にですがざっと自社でよくマーケ担当者とのやりとりで使われる用語を羅列しました。
なんとなく知っているだけでもだいぶ違うと思います。
こういった技術以外の知識も頭に入れつつ、事業数値に影響を与えられるエンジニアを目指したいです。

まだまだ色々な指標や、ユーザーの意思決定プロセスなどの考え方も存在するので、
また別でまとめて行こうと思います。
【徹底解説】React環境構築 〜 create-react-app


Reactで初めてアプリを作る方向けの、環境構築 〜 アプリ立ち上げまでのフローを紹介します。

#0.create-react-appに必要なもの

・node 8.10 以上
・npm 5.6 以上

#1.Homebrewインストール
Homebrew とは macOS 用のパッケージマネージャーです。
Homebrew のサイト↓↓↓
https://brew.sh/index_ja

Homebrew をインストールします

```
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

Homebrew がインストールされていることを確認します

```
$ brew -v
```

#2.nodebrewインストール

Homebrew を使って nodebrew をインストールします

```
$ brew install nodebrew
```

nodebrew がインストールされていることを確認します

```
$ nodebrew -v
```

#3.nodeインストール

nodebrew を使って node をインストールします

node の安定バージョンをインストール（create-react-appに必要なバージョンをインストール）

```
$ nodebrew install stable
```

node の最新バージョンをインストールしたい方はこちら

```
$ nodebrew install latest
```

インストール可能な node のバージョンを一覧で確認することもできます（バージョンを指定したいときに）

```
$ nodebrew ls-remote

バージョン一覧が表示されるので、任意のバージョン番号を以下の要領で指示する。（セットする）

$ nodebrew use vX.X.X
```

特に要求がない場合は安定バージョンをインストールしましょう

#4.パスを通す

まだ node が使える状態になっていないので使えるようにする

zshの場合

```
$ echo export PATH=$HOME/.nodebrew/current/bin:$PATH >> ~/.zprofile
```

bashの場合

```
echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bash_profile
```
ターミナルを一度再起動しましょう

node がインストールされているか確認しましょう

```
$ node -v
```

node がインストールされていれば npm も自動的にインストールされています

```
$ npm -v
```

これで create-react-app を実行する準備が整いました

#5.create-react-app

自分の開発ディレクトリで create-react-app を実行

```
$ npx create-react-app 作りたいフォルダ名
```

エラーが出ずに実行されればOK

お疲れ様でした。

#参考サイト
https://qiita.com/sugasaki/items/ad4d5d88965057840a04
Darkmode.jsの利用方法

 皆さんこんにちは！本日は「Darkmode.js」についてご紹介していきたいと思います。

公式のドキュメントに沿って紹介を進めていきますので、下記のリンクを参照しながらご覧ください！
Darkmode.jsのURL: https://darkmodejs.learn.uno/

###下記の順で解説していきます
- Darkmode.jsとは何か？
- 実装方法
- オプションの解説

それでは早速いってみましょう！！

#Darkmode.jsとは？
Darkmode.jsは簡単に「ダークモード」の実装ができるJavaScriptのライブラリです。近年TwitterやInstagramに限らず、モダンなアプリケーションにはほぼ確実に実装されているダークモード。
目に強い光が送り込まれないので、深夜帯にスマホ画面を見ていても睡眠に支障が出難くていいですよね。

「アプリケーションを作ったはいいけど、ダークモード入れたい。でも難しそう...」
そう言った方でも簡単に実装できる内容になっていますので、ご安心ください！

#実装方法
それでは早速実装していきましょう。
まずは簡単なhtmlファイルを作りましょう。

```html:index.html
<!doctype html>
<html class="no-js" lang="jp">
<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="style.css">
  <script src="darkmode.js"></script>
</head>
<body>
  <h1>Hello world!</h2>
    <button>BUTTUN</button>
  <script src="https://cdn.jsdelivr.net/npm/darkmode-js@1.5.7/lib/darkmode-js.min.js"></script>
</body>
</html>
```
cssとjsファイルを読み込んだシンプルな作りにしています。

```html
<script src="https://cdn.jsdelivr.net/npm/darkmode-js@1.5.7/lib/darkmode-js.min.js"></script>
```
こちらのコードをbodyタグの終わりに記述する事でDarkmode.jsを呼び出しています。

続いてJavaScriptファイルを見てみましょう。

```javascript:darkmode.js
function addDarkmodeWidget() {
    new Darkmode().showWidget();
  }
  window.addEventListener('load', addDarkmodeWidget);
```

これだけでダークモードの実装は完了です。（cssファイルは省略します。）
下記のような画面になるはずです。

![右下に黒い丸印](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810467/5a2f945c-b837-d2e3-a3bc-d306c60007b8.png)
右下に黒い丸印が現れましたね。試しにクリックしてみましょう。
すると...
![クリックするとダークモードになる](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810467/a943c57e-d54f-5467-f8bb-10ed6bc3ffe1.png)

画面が暗くなり、黒いフォントだった「Hello world!」が白になっています！
ボタンの色を見ていただくとわかりますが、仕組みとしては色を反転しているだけでかなりシンプルですね。
これがダークモードです！ライトモードに戻したいときは右下の白い丸印をクリックすれば戻ります！！
とまあ、こんな感じで簡単に実装できちゃいました。

#オプション解説
Darkmode.jsにはオプションも用意されています。
それらを紹介します。

```javascript:darkmode.js
const options = {
  /*①*/ bottom: '64px', // default: '32px'
  /*②*/ right: 'unset', // default: '32px'
  /*③*/ left: '32px', // default: 'unset'
  /*④*/ time: '1s', // default: '0.3s'
  /*⑤*/ mixColor: '#fff', // default: '#fff'
  /*⑥*/ backgroundColor: '#fff',  // default: '#fff'
  /*⑦*/ buttonColorDark: '#100f2c',  // default: '#100f2c'
  /*⑧*/ buttonColorLight: '#fff', // default: '#fff'
  saveInCookies: false, // default: true,
  label: '🌓', // default: ''
  autoMatchOsTheme: true // default: true
}

const darkmode = new Darkmode(options);
darkmode.showWidget();
```
順番に解説していきます。

①下から何px離れるかを指定しています。px数をあげればあげるほど、上の位置に固定されます。
②右から何px離れているか指定できます。今回のコードであれば「unset」になっているので特に機能はして居ません。
③左から何px離れているか指定できます。今回の場合であれば左下にダークモードの丸印が表示されることになりますね。
④モードの切り替え時間を指定できます。
⑤ダークモードの色に配合する色を選べます。
⑥ライトモードの色を指定できます。
⑦⑧モード切り替えの丸印の色を変えられます。

#終わりに
いかがでしたでしょうか。皆さんもぜひダークモードを実施してよりリッチなアプリケーションを作ってみましょう！！
ちなみにダークモードは単純に色の反転を利用して実装されているので、中には反転して欲しくない要素もでてくると思います。その際の解決方法もこちらに記述しておきます。
今回の場合はボタン要素に反転して欲しくないのでそれを例に対応していきます。

```html
<button class="darkmode-ignore">BUTTUN</button>
```
このように対象の要素にクラスで「darkmode-ignore」と設定してあげるだけでOKです！！
![ダークモードを除外したボタン要素](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810467/f6306ff0-8241-d49b-3ec4-3d99bf7369cd.png)
複数要素に対して、平均μと分散σ^2を逐次更新する方法【統計の断捨離】

#まだ、平均μや分散σ^2を計算するために、すべての要素を保持していますか？
すべての要素を保持しておく必要はありません。
そう、要素数と、直前のμとσを保持しておけば。


## まずは結論
n番目までの平均、分散

```math
\mu_{n}と\sigma_{n}^2
```
が既知であれば、そこに、下記の複数の要素を追加したい場合、

```math
x_{n+1}, x_{n+2}, .. x_{n+k}
```

#### 平均
```math
\mu_{n+k} = \frac{1}{n+k}(n\mu_{n} + \Sigma_{n+1}^{n+k}x_{i})
```
#### 分散
```math
\sigma_{n+k}^2 = \frac{n(\sigma_{n}^2+\mu_{n}^2)+\Sigma_{n+1}^{n+k}x_{i}^2}{n+k} - \mu_{n+k}^2
```

で計算できる。

基本的には、[3] にあるように、
> 分散は「自乗の和」から「和の自乗」を引いたもの

であり、「自乗の和」の部分を式変形することで導出できる。

# 解説 (作成中。近日補完)

## 定義

n番目までの平均は

```math
\mu_{n} := \frac{1}{n}\Sigma_{1}^{n}x_{i}　　・・・(1)
\\
```

分散は

```math
\sigma_{n}^2 := \frac{1}{n}\Sigma_{1}^{n}x_{i}^2 - \left (\frac{1}{n}\sum_{1}^{n}x_{i}  \right )^{2}　　・・・(2)
\\
= \frac{1}{n}\Sigma_{1}^{n}x_{i}^2 - \mu_{n}^2　　・・・(2)'
```

と定義されます。
この時点では、計算するためにすべての要素が必要です。

## 逐次計算！
n+1番目の要素を加えるにはどうするか
[1][2]にも記載があるように、

```math
\mu_{n+1} := \frac{1}{n+1}(n\mu_+x_{n+1})　　・・・(3)
\\
\sigma_{n+1}^2 := \frac{n(\sigma_{n}^2 + \mu_{n}^{2})+x_{n+1}^2}{n+1} - \mu_{n+1}^{2}　　・・・(4)
```
と計算できます。逐次計算してる感満載。

##### つまり…下記だけ保持しておけばよい！

```math
n, \mu_{n}, \sigma_{n}^2
```
断捨離である。

### 軽く解説

(3)は、意外と単純で：
> 1. n番目までの総和を“復元”
2. (n+1)番目を足し込む
3. 改めて(n+1)で除算

としているだけ。
(4)は

```math
Var[X] = E[X^2] - \mu_{n}^2
```
をもとに、式変形することで導出できます。

### これ以降、近日追記予定



---
[1] [平均と分散を逐次的に計算するアルゴリズム](https://mathwords.net/tikujiheikin)
[2] [分散の逐次更新](https://qpp.bitbucket.io/post/variance/)
[3] [分散の意味と二通りの計算方法](https://mathtrain.jp/variance)
新gTLDってどんなもの？

## 勉強前のイメージ

ドメインの種類？

## 調査

### まずトップレベルドメインの種類

- ccTLD

country code Top Level Domain の略。
国コードトップレベルドメインという意味
国コードというだけあり、特定の国や地域に割り当てるために作られたトップレベルドメイン。
日本の場合は `.jp` が割り当てられています。
日本の他、中国の `cn` やドイツの `.de` が割り当てられている。
登録はその国の人しかできないか、世界中の人が登録できないかは各ccTLDの管理によって様々です。
日本以外を見ることは少ないですが、250を超えるccTLDが存在します。

- gTLD

generic Top Level Domain の略。
分野別トップレベルドメイン の意味
特定の国や地域によらない、領域・分野ごとに割り当てられたトップレベルドメインのことです。
`.com` や `.net` などがそれに当たります。
基本的には、世界中の人が登録できるようになっています。

### gTLD とは

上記で書いたように、特定の国や地域によらない、領域・分野ごとに割り当てられたトップレベルドメインのことです。
gTLDの中には、 `スポンサー付き` と `スポンサーなし` の2種類に区別されます。

- スポンサー付き : ドメイン名の登録は特定の業界や分野の関係者に制限
	- 博物館用 : `.museum`
	- 旅行関連用 : `.travel`
- スポンサーなし : 登録制限がない
	- `.com`
	- `.net`

### 新gTLDとは

初めて2000年に新gTLDが募集されて以降、2003年・
・2012年1月から5月末にかけて実施され、受理されたものが `新gTLD` です。
2012年に実施された応募では、1500件程度導入されることが特徴です。

## 勉強後のイメージ

ドメインの種類じゃなくて、
新しくgTLDを募集して、受理されたのが `gTLD` ってことがわかった。
そもそもトップレベルドメインに種類があるって知らなかったからよかった。

## 参考

- [いまさら聞けないドメイン名の基本（前編） | 第1回](https://webtan.impress.co.jp/e/2011/09/29/11107)
- [新gTLD](https://www.nic.ad.jp/ja/dom/new-gtld.html)
- [新gTLDとは](https://www.gmoregistry.com/about/)
正規表現を使ってgitLFS管理から複数ファイルを除外する

## gitLFSとは
画像ファイルなどのgitで管理されるべきでないとされるバイナリファイルなどを、まとめてgit上で管理するため機能のこと


## gitLFS管理されているファイルの一覧を見る

```
git lfs ls-files
```
で、LFS管理されている全ファイルを見ることができる。

## 一つのファイルを管理下から外したい場合

ある一つのファイルを管理下から外したい場合には

```
git rm --cached <ファイル名>
```
で除外できる
もしこの`--cached`をつけ忘れてしまうと、ファイル自体が削除されてしまうので注意


## 全てのtxtファイルを管理下から外したい場合
#### 正規表現を使いこなす

```
$ git rm --cached <フォルダ名>/**/*.txt
```

`<フォルダ名>/**/*.txt`で、そのフォルダの配下にあるあらゆるテキストファイルを指定することができる。


## まとめ
正規表現をもっと使いこなせるようになりたい

## 参考サイト
[Git LFSについて調べてみた](https://medium.com/nttlabs/enabling-git-lfs-c907ca393ccb)
Mac OS XをMBRで動かす

# はじめに
この記事はニッチな需要でレガシーOSを弄るお話です。
もしこの記事があなた様のお役に立ちましたらLGTMとコメントをください。質問も答えられる範囲で受け付けます。
最近のMacでは再現できませんので大人しくあきらめてください。

## 自己 ~~(事故)~~ 紹介
N高等学校に在学してい~~る~~た三年生です。
普段はPythonとRustをやっています。
2021年4月付で金沢工業大学に進学させていただきました．


## ちょっとした説明
MacはEFIを採用しながらも2006~2009[^1]までのMacはUEFIとの互換性はマトモにないです。[^2] [^3]

## MBRで動かすことになったきっかけ
手元に余ったMacBook Air 2011 Mid 11インチがありWindows8[^4]とOS X 10.7をデュアルブートするBootCampを使用するとハイブリッドMBRを使用することになりますが[^5]ハイブリッドMBRはパーテーションを操作した暁[^6]にはWindowsが起動不可になります。そのためMacをMBRのみで動作させたいと考えました。

## 参考文献を読み漁る
まずは前提知識が何もないため```UEFI Mac```とか雑に関連ワードを入れて検索しましょう。[^7] 
[Arch LinuxのWiki](https://wiki.archlinux.jp/index.php/Mac)はArch以外LinuxやWindowsの情報を載せてることがよくあります。デュアルブート関連の情報はここも参考にするといいでしょう。

## 見つけたサイト
[UEFI Advent Calendar 2014](https://qiita.com/advent-calendar/2014/uefi)の9日目から有能な記事を見つけました。[MBPのApple EFIが自動的に認識するブートEFIファイルについて](https://ichelm.hatenadiary.org/entries/2014/12/09)です。

## 得た知識
[上にあげたサイト](https://ichelm.hatenadiary.org/entries/2014/12/09)を引用させていただきます。
#### Startup Managerに表示される条件

###### Startup Managerにエントリが表示される条件は、内蔵SSD・USBメモリ・SDカードを問わず、以下の条件を満たすファイルが存在することです。

- HFS+またはvfatでフォーマットされたパーティション上に存在する。これらはApple EFIが読み込めるファイルシステムです。
        パーティションIDは問いません。vfatでフォーマットされたEFI System PartitionやHFS+でフォーマットされたApple Bootはもとより、HFS+でフォーマットされたMicrosoft Basic DataやvfatでフォーマットされたLinux Swapでも大丈夫です。

- パーティションテーブルはGPT、MBRパーティションテーブルのいずれでも可です。

##### 上記ファイルシステム上の、以下のパスにEFI実行ファイルが置かれている。

- a. 対象がファイルシステムがHFS+の場合のみ、"blessed"ファイル。HFS+のメタデータ上で起動用とマークされたファイルのことです。OS Xのbless(8)コマンドのFolder Mode、Linuxのmactel-bootのhfs-blessコマンドで指定できます。
- b. OS Xブートファイルのデフォルトパス、/System/Library/CoreServices/boot.efi。ファイルシステムはvfat、HFS+のどちらでも可。
- c. EFIブートファイルのデフォルトパス、/efi/boot/bootx64.efi。ファイルシステムはvfat、HFS+のどちらでも可。

## ここからどうするか
- Mac OS Xでは新規にインストールする際GPTが必要なのでそれでインストールを行う。
- Time machineでバックアップを行う。[^8]
- そして復元パーテーションを使用して起動する(ただしこの際内蔵から起動するとMBRにできないので注意)
- そしてディスクを完全に削除し、MBRでフォーマットした後Time machineでリストアしたら画像のようになる。[^9]
![download_20201031_115023.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328076/f5600fbc-dc0a-cc0a-758d-6a7e53bb22d6.jpeg)

## その後
パーテーションを分けるなりしてBIOS方式で起動しWindowsを入れるなりしましょう。Mac単体で使うならこんな事しなくていい。
ここまで読んでいただきありがとうございました。

[^1]: そりゃEFI32/EFI64やぞ、UEFIと互換性があるわけがない。
[^2]: 2010~2011に製造されたMacはUEFIと互換性が無いわけでは無いのですが事故が起きる。[これ](https://seecom-s.com/?p=3136)[とか](https://qiita.com/74th/items/63f9bde5b747b03f0794)を参照。
[^3]: Windowsがマトモに動くUEFIとの互換性持たせたのは2013(Late)~からのMacだったと記憶。具体的にはHaswellから。
[^4]: Windows Embedded 8.1 Industry Pro(ニッチすぎる)がMicrosoft Azure for Studentの偉大なる力によってライセンスキーとISOが手元に生えてきた。学生の身分に感謝しながら使い倒していこう。もう使えなくなったけど．
[^5]: 知人のMacBook Pro 2015 Retina 13インチを代理で構成する際macOS10.12のBootCampを使用したのですがその際ハイブリッドMBRを使用してインストールしたので思わず台パンしかけました。勘弁してくれ。ちなみに10.13~だとUEFIを使用してインストールします。
[^6]: パーテーション弄るなよオイ
[^7]: Googleしか勝たん:fist::triumph:
[^8]: Mac Proとかあるならddコマンドぶっ放しても問題ない気がするが私はチキンなので...
[^9]: time machineは緩すぎて普通にMBRにリストアできちゃうので大問題．ただし10.10あたりで対策されていると思う．
Gitコマンド早見表（初めてのコミットからブランチの管理まで）

railsを勉強し始めて４ヶ月目です。
自分用の備忘録としてですが何かのお役に立てればと思い、なるべく丁寧にまとめてみました。
初めてのqiita投稿ですので、見辛かったらすみません...

GitHubに、作成した内容、または変更内容をあげる手順をまとめました。

ローカルリポジトリ？
リモートリポジトリ？？(°▽°)
な方は、Gitに関して学ぶところからスタートされたらよいかと思います。

***

###初回のpush
ローカルリポジトリの作成し、リモートリポジトリに内容を保存するまでの手順

```terminal:ターミナル
① GitHubで管理したいディレクトリに移動
　cd desktop/sample_app

② リポジトリの新規作成（バージョン管理できるようにするための設定）
　git init

③ 変更履歴を残すための準備
　#特定のファイルだけ保存したいとき
　　git add <ファイル名>

　#変更したファイル全て保存したいとき（削除したファイルは除く）
　　git add .

　#削除したファイルも含んで全て保存したいとき
　　git add -A

④ 変更履歴の保存
　git commit -m "変更内容に関する説明コメント"
　#コメントに何を書けば..？という方は下記のメモ内容を参照してください

⑤ リモートリポジトリへ接続
　git remote add origin <GitHubのリポジトリURL>
　#GitHubのURLに関しては下記のスクショを参照してください
　
⑥ ローカルリポジトリで保存した変更内容をリモートリポジトリに反映
　git push origin master


```

###初回pushに関するメモ
- **コメントに何を書けばいいか分からない！**<br>
git commit で入力するコメントを**コミットメッセージ**と呼びます。<br>
コミットメッセージの内容のポイントは<br>
「何をしたのか」が分かるように書くことです。<br>
よく使う単語を紹介します。<br>

| コミットメッセージ | 意味 |
|:-:|:-:|
| first commit  |  初めてのコミット |
| add ~  |  ~を追加しました |
| update ~ | ~を更新しました  |
| remove ~ | ~を削除しました  |
| fix ~ | ~の不具合を修正しました  |

変更内容をため込んでからコミットメッセージを書こうとすると、簡潔にまとめられなくなります。
一言でまとめられるくらいの変更でこまめにコミットすることが大切なようです。

- **GitHubのリポジトリURLって？**
![スクリーンショット 2020-10-29 13.04.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688517/99e203a6-9627-590d-1177-b0423bbe21d8.png)

***

###２回目以降のpush

```terminal:ターミナル
① 変更履歴を残すための準備
　#特定のファイルだけ保存したいとき
　　git add <ファイル名>

　#変更したファイル全て保存したいとき（削除したファイルは除く）
　　git add .

　#削除したファイルも含んで全て保存したいとき
　　git add -A

② 変更履歴の保存
　git commit -m "変更内容に関する説明コメント"

③ ローカルリポジトリで保存した変更内容をリモートリポジトリに反映
　git push origin master

```

***

###ブランチの作成・確認

```terminal:ターミナル
#ブランチの作成
git branch <新規ブランチ名>

#ブランチの一覧表示
git branch

#指定のブランチに切り替え
git checkout <ブランチ名>

#ブランチを新規作成してそのブランチに切り替える
git checkout -b <新規ブランチ名>

#新規作成したブランチを空コミット
git commit --allow-empty -m "コミットメッセージ"
　#空コミットの説明は下記メモ
```

###ブランチに関するメモ
- **ブランチを切るって？**
実装する機能ごとにブランチを切る方が多いみたいです。
自分の変更した箇所が原因で他に悪影響を与えないようにできる点がブランチを切ることのよいところ。


- **空コミットって？**
新規作成したファイルや、変更したファイルがなくてもコミットをできるようにします。
ブランチを切ったときに実行するとGitHubにブランチを反映することができます。

- **切ったブランチはどうするの？**
メインのブランチと合体させる方法があります。
合体させることを「マージする」と言います。
また別の記事でまとめられたらと思います。

***

###ブランチでの作業

作業したいブランチ上にいるか確認してから作業します。

```terminal:ターミナル
① git branch
　#作業したいブランチにいる？

② git checkout <ブランチ名>
　#ブランチを移動した時はこのコマンド

③ 作業する

④ add と push する
　git add
　git commit
　git push origin <ブランチ名>
```

***

以上、まとめでした。

正直、まだまだGitHubに慣れないです...
間違った内容を書いてしまっていた場合は、ぜひ先輩エンジニアのみなさまの意見を参考にさせていただきたいです！

よろしくおねがいします☺︎
Laradockのdocker-compose upがコケる

##  環境
- macOS Catalina 10.15.7
- Docker for mac 2.4.0.0

## 現象
```
$ git clone https://github.com/Laradock/laradock.git
$ cd laradock
$ docker-compose up -d php-fpm nginx mysql phpmyadmin workspace

略

Step 123/291 : RUN if [ ${INSTALL_AST} = true ]; then     if [ $(php -r "echo PHP_MAJOR_VERSION;") != "5" ]; then         printf "\n" | pecl -q install ast-${AST_VERSION} &&         echo "extension=ast.so" >> /etc/php/${LARADOCK_PHP_VERSION}/mods-available/ast.ini &&         phpenmod -v ${LARADOCK_PHP_VERSION} -s cli ast     ;fi ;fi
 ---> Running in f765b424fea4
ERROR: `phpize' failed
ERROR: Service 'workspace' failed to build : The command '/bin/sh -c if [ ${INSTALL_AST} = true ]; then     if [ $(php -r "echo PHP_MAJOR_VERSION;") != "5" ]; then         printf "\n" | pecl -q install ast-${AST_VERSION} &&         echo "extension=ast.so" >> /etc/php/${LARADOCK_PHP_VERSION}/mods-available/ast.ini &&         phpenmod -v ${LARADOCK_PHP_VERSION} -s cli ast     ;fi ;fi' returned a non-zero code: 1
```

## 解決方法
https://github.com/laradock/laradock/issues/2738#issuecomment-706938037

`https://github.com/Laradock/laradock.git`からクローンした`env-example`内に記載のphpのバージョンは7.3。
これをそのままコピーして`.env`を作成したのでphpのバージョンが7.3になってしまっていた。

```
### PHP Version ###########################################

# Select a PHP version of the Workspace and PHP-FPM containers (Does not apply to HHVM).
# Accepted values: 7.4 - 7.3 - 7.2 - 7.1 - 7.0 - 5.6
PHP_VERSION=7.3
```
phpのバージョンを7.4にするとうまくいくよ！とのことなので`.env`ファイルを書き換える。

```.env
# Select a PHP version of the Workspace and PHP-FPM containers (Does not apply to HHVM).
# Accepted values: 7.4 - 7.3 - 7.2 - 7.1 - 7.0 - 5.6
PHP_VERSION=7.4
```

7.4に変更後、再度`docker-compose up`を実行

```
$ docker-compose up -d php-fpm nginx mysql phpmyadmin workspace

略

Successfully built 8d1580fef486
Successfully tagged laradock_nginx:latest
WARNING: Image for service nginx was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating laradock_docker-in-docker_1 ... done
Creating laradock_mysql_1            ... done
Creating laradock_workspace_1        ... done
Creating laradock_phpmyadmin_1       ... done
Creating laradock_php-fpm_1          ... done
Creating laradock_nginx_1            ... done
```

うまくいったようです。

### *Mission Complete*