OmniAICreator/Qiita-1.07M huggingface dataset:
vector では v[i] より v.at(i)と書こう

当たり前なのかもしれないが、知らなかったので備忘録として。
初投稿だが、こういう時のためにQuitaを使うのかというお気持ち。

さっそく本題だが、競プロで合ってるはずなのになぜかWAになることが多く、その原因の多くはインデックス周りが原因だった。
自分の環境ではvectorの配列外参照はコンパイルが通ってしまうから余計にたちが悪い。

vectorを使ってランダムアクセスをする時は .at(i) を使うと配列外参照するとちゃんとエラーが出てきてくれて嬉しかった。

```c++
vector<int> v{0,1,2,3,4};
cout<<v[5]<<endl; // 0
cout<<v.at(5)<<endl; // Abort trap: 6
```



『江添亮のC++入門』より引用
>さあ皆さんご一緒に、
>・コンパイルエラーは普通
>・コンパイルエラーが出たらありがとう
>・コンパイルエラーが出たら大喜び
Laravel(5.5)のビルトインサーバーでCSRFの問題を解決しても419が出続ける際の解決策

# 結論

```config/session.php
    'secure' => env('SESSION_SECURE_COOKIE', false),
```

にしておく。

## 事象

```console
$ php artisan serve
```

でサーバーを立ち上げ、[http://127.0.0.1:8000](http://127.0.0.1:8000)にアクセスしたら、延々と419が・・・。調べてもCSRFの問題が大半を占める。

ログイン実行時の時だけ発生するので、セッション関連かと思って延々ググってたら、以下の記事に・・・

[Post request in Laravel - Error - 419 Sorry, your session/ 419 your page has expired](https://stackoverflow.com/questions/52583886/post-request-in-laravel-error-419-sorry-your-session-419-your-page-has-exp)

```config/session.php
    'secure' => env('SESSION_SECURE_COOKIE', false),
```

をやれば解決した。ビルトインサーバーだとそもそもSSLとかないので、そりゃそうだった・・・。
【AWS SOA】AWS Shield Standardとアドバンスドの違い 

#はじめに
AWS SAAに合格し、現在SOAの勉強をしています。SOAの問題集に出てきたAWS Shieldについて深掘りしたいと思います。

#解説
##そもそもAWS Shieldとは
AWS ShieldはDDoS攻撃に対する保護を行うマネージドサービス。DDoSとは標的となるコンピュータに対して複数のマシンから大量の処理負荷を与えることでサービスを機能停止状態へ追い込む、ネットワークを通じた攻撃手法の１つである。保護レベルとしてAWS Shield StandardとAWS Shieldアドバンスドの2つがある。

##Shield Standard
・全てのユーザーが自動的に無料で使用することができる。
・SYN/UDPフラッド攻撃やリフレクション攻撃といった最も頻繁に発生する一般的なインフラストラクチャ(ネットワーク層およびトランスポート層)攻撃に対して防御する。 

##Shield アドバンスド
・有料
・Standardの防御機能に加えて、以下のリソースの保護が可能。
　　・ELBロードバランサー
　　・EC2 Elastic IPアドレス
　　・Amazon CloudFront ディストリビューション
　　・Amazon Route53 ホストゾーン
　　・AWS Global Accelerator アクセラレーター
・保護されているリソースがDDoD攻撃を受けたことによりコストが上昇した場合に備えるDDoSコスト保護が含まれる。

ちなみにShieldのコンソールを開くと英語で書かれており、アドバンストだと月$3000かかるようだ。
![スクリーンショット 2020-09-02 16.11.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/30291607-d0d5-ea17-d2e6-6984c1279173.png)


参考
https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/ddos-overview.html#ddos-advanced

https://www.weblio.jp/content/DDoS#:~:text=DDoS%E3%81%A8%E3%81%AF%E3%80%81%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%92,%E3%81%95%E3%81%9B%E3%81%9F%E3%82%82%E3%81%AE%E3%81%A7%E3%81%82%E3%82%8B%E3%80%82

https://www.amazon.co.jp/dp/B07VFFX6V1/ref=cm_sw_r_tw_dp_x_hq0tFbSM291QE
[android] Error:No such property: GradleVersion for class: JetGradlePlugin


## Solution
```
help->check Updata
```
から最新のAndroid Studioのバージョンに変更する

## Referred Link

[Referred article  (【android】エラー：Error:No such property: GradleVersion for class: JetGradlePluginについて)](https://cpoint-lab.co.jp/article/201908/11313/)
1分でできるVSCodeでBladeファイルを綺麗に整形する設定方法【Laravel】

## 前置き
VSCodeは標準でファイル整形機能があるが、HTML, CSS, Javascriptにしか対応していません。
他の形式の場合は自分でフォーマッターを用意する必要があります。
とっても簡単なので、設定していない方はぜひこの機会に設定してみてください。


## 設定手順
### VSCodeの拡張機能の「Laravel Blade Snippets」をインストールする

※すでに「Laravel Blade Snippets」をインストール済みの方は飛ばしてください

#### まずVSCodeを起動して、VSCodeの左バーのメニューから「拡張機能」を選択してください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206138/ed6868af-b2ba-1851-210a-30f4df3916b1.png)

#### 次に画面上部の「Marketplaceで拡張機能を検索する」と表示されている検索バーに「blade」と入力すれば、「Laravel Blade Snippets」が上位に表示されるので、緑のインストールボタンを押下してください。
※筆者はすでにインストールされているため表示されていませんが、未インストールの拡張機能にはインストールボタンが表示されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206138/b27ff109-6b2e-4b9d-6cf8-47b10ff141d5.png)

これでインストールは完了です。


### 設定から「Enable format blade file」を有効化する

#### VSCodeの左バーのメニュー最下部に、下記の歯車のマークがあるのでそれを押下します。さらにメニューウインドウが開くので、「設定」を選択してください。

※Windowsの方は「Ctrl」+「,」、Macの方は「⌘」＋「,」でも設定画面が開けます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206138/0b00a427-9644-a7ec-e6dd-5cf15dcbd13f.png)

#### 設定画面が表示されるはずなので、その検索バーに「blade config」と入力してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206138/20aacb12-aa00-eb9f-cf6f-e4890e5fa397.png)

#### Bladeの設定として、「Enable format blade file」のチェックボックスが表示されるので、チェックを入れてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206138/bc81b459-0e90-c64b-d1e1-3c84912fc5e7.png)

これで設定は完了です！

### 動作の確認

テキトーにbladeファイルを開いて、「Shift」+「Alt」+「F」（Macは「⇧」＋「⌥」＋「F」）を押下すれば綺麗に整形してくれます。

```php:整形前
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>整形サンプル</title>
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<link rel="stylesheet" href="{{ asset('css/style.css') }}">
</head>
<body>
<div>hoge</div>
<div>fuga</div>
<div>
<p><a href="{{ route('toppage') }}"></a></p>
</div>
</body>
</html>
```

```php:整形後
<!doctype html>
<html>

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>整形サンプル</title>
  <meta http-equiv="Content-Style-Type" content="text/css">
  <meta http-equiv="Content-Script-Type" content="text/javascript">
  <link rel="stylesheet" href="{{ asset('css/style.css') }}">
</head>

<body>
  <div>hoge</div>
  <div>fuga</div>
  <div>
    <p><a href="{{ route('toppage') }}"></a></p>
  </div>
</body>

</html>
```
Dockerなんて聞いたことしかないよ...

未経験から自社開発企業に転職し、現在実務2日目です。
先ほどローカルでの環境構築が完了したのでアウトプットがてら書かせていただきます。
間違った記載があればご指摘いただけるとありがたいです。

参考にしたサイト
https://qiita.com/tsuboyataiki/items/90dbe94553d3dea39b19
https://knowledge.sakura.ad.jp/13265/
https://qiita.com/wasanx25/items/d47caf37b79e855af95f

#Dockerとは？
Dockerは、インフラ、DevOps界隈（開発チームと運用チームを掛け合わせた語句）で注目されている技術で、Docker社が開発している、コンテナ型の仮想環境を作成、配布、実行するためのプラットフォームです。

Linuxのコンテナ技術を使ったものであり、ホストマシンのカーネルを利用しプロセスやユーザーを隔離することで、あたかも別のマシンが動いてるかのように見せることができます。

#使用することのメリットは？？
・軽量で高速に起動、停止などができる。
・コード化されたファイルを共有することで、どこでも誰でも同じ環境が作れる。
・作成したDockerイメージを他の人にも渡しすことで、各自の環境のバージョンずれ防止や、開発環境準備の短縮化にもつながる

##現在のコンテナを確認

Dockerのプロジェクトのディレクトリで

```terminal:ターミナル
$ docker-compose ps
```
上記を実行します。
これでコンテナの名前、状態が表示されます。

##コンテナを起動

コンテナがあることが確認できましたら、いよいよ起動します。

```terminal:ターミナル
$ docker-compose up -d
```
サービスコンテナーのビルド、（再）生成、起動、アタッチを行います。
「-d」オプションをつけることによりコンテナーはバックグラウンドで起動しそのまま実行し続けます。

人によってはここでかなり時間がかかることもありますので気長に待ちましょう。
起動が成功するとコマンドラインに

```terminal:ターミナル
Use Ctrl-C to stop
```
と表示されます。



##その他コマンド

###ログを表示
サービスのログを表示します。
(また引数でサービス名も指定できるそう。)

```terminal:ターミナル
$ docker-compose logs
```

###コンテナの停止

docker-compose.ymlに書かれているサービスを参考にコンテナを停止し、そのコンテナとネットワークを削除します

```terminal:ターミナル
$ docker-compose down
```

###再起動

```terminal:ターミナル
$ docker-compose restart
```

#最後に

本日触り始めたばかりでまだ全然理解が追いつかないので順次理解を深めていきます。
この記事もどんどん学んだことに応じて更新していきます。
ASP.NET Core webアプケーションを公開する

# 目的

ASP.NET Coreで作成したwebアプケーションをRaspberry pi上で実行し、PCからアクセスする

# 対象物

以下記事で作成したチャットアプリを公開する
https://qiita.com/takmot/items/7fc13b50a3c8d0f6d2aa

# `dotnet run`で実行する場合

Properties/launchSettings.jsonを以下のように変更

```json

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:49801",
      "sslPort": 44357
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "SignalRChat": {
      "commandName": "Project",
      "launchBrowser": true,
-     "applicationUrl": "https://localhost:5001;http://localhost:5000", // 変更前
+     "applicationUrl": "https://0.0.0.0:5001;http://0.0.0.0:5000",     // 変更後
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}
```

実行結果
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695430/4bcce7f3-f2f7-9362-a403-ee07163032c1.png)

# publishによって発行したファイルを実行する場合

Properties/launchSettings.jsonの変更では、publishで発行した場合に設定が反映されなかった
そのため、Program.csを以下のように変更

```c#

namespace SignalRChat
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>()
                    .UseUrls("http://0.0.0.0:5001"); // 追加
                });
    }
}
```

# Raspberry pi準備

### Raspberry piに.NET Coreをインストール
公式ドキュメント通りでうまくいかなかったため、以下記事を参照
https://qiita.com/logikuma/items/de8c987dc2308a96256d

以下抜粋
下記コマンドを実行し、必要な事前取得パッケージをインストールする

```
sudo apt-get install curl libunwind8 gettext
```
下記コマンドを実行し、.NET Core ランタイムをCurlでダウンロードする

```
curl -sSL -o dotnet.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Runtime/release/2.0.0/dotnet-runtime-latest-linux-arm.tar.gz
```
下記コマンドを実行し、.NET Coreランタイムをインストールする

```
sudo mkdir -p /opt/dotnet && sudo tar zxf dotnet.tar.gz -C /opt/dotnet
```
下記コマンドを実行し、「dotnet」コマンドを実行可能にする

```
sudo ln -s /opt/dotnet/dotnet /usr/local/bin
```
下記コマンドを実行し、結果を確認する

```
dotnet --help.
```

# Raspberry pi上での実行

1. `dotnet publish -r linux-arm`でRaspberry pi用に実行ファイルを生成
1. bin\Debug\netcoreapp3.1\linux-armに生成されたpublishフォルダをzip圧縮して、
Raspberry piにFTP等で転送
1. 転送したファイルを`unzip publish`
1. publishフォルダの権限を変更`chmod 755 -R publish`
1. アプリを実行`./SignalRChat`

実行結果

```
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: http://0.0.0.0:5001
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /home/pi/work/DGC/publish
```

`http://localhost:5001`ではなく`http://0.0.0.0:5001`になっていれば成功
robots.txt でクローラーのアクセスを制限する

Apache2.4 のアクセスログが次のような状況でした。

```text
$ grep SemrushBot access*.log | wc
   6552   98280 3790927

$ grep MJ12bot access*.log | wc
   6185   92775 2139285

$ grep AhrefsBot access*.log | wc
  16802  252030 6534579

$ grep BLEXBot access*.log | wc
   3798   56970 1035560
```

そこで、robots.txt に次を加えました。

```text:robots.txt
User-agent: SemrushBot
Disallow: /

User-agent: MJ12bot
Disallow: /

User-agent: AhrefsBot
Disallow: /

User-agent: BLEXBot
Disallow: /
```
「 Failed to install the following Android SDK packages as some licences have not been accepted. 」[Android][MacOS]

## Solution
~~~
cd ~/Library/Android/sdk/tools/bin
~~~
~~~
export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jre/jdk/Contents/Home
yes | ~/Library/Android/sdk/tools/bin/sdkmanager --licenses
~~~
## Referred Link

[Referred Qiita article 1 (“Failed to install the following Android SDK packages as some licences have not been accepted” error)](https://stackoverflow.com/questions/54273412/failed-to-install-the-following-android-sdk-packages-as-some-licences-have-not)
[Referred Qiita article 2 (Androidのlicencesのエラーを解決)](https://qiita.com/joji/items/931d5f4e4ee853d7458c)
Excelに自動で変換された日付の文字列をjava.time.LocalDateで取り込む

CSVファイルなどで日付を文字列で扱うとき、日付のフォーマットは `YYYY-MM-DD` を使うことが多いかと思います。
ところが、CSVファイルをExcelで開くと勝手にExcelの日付フォーマットに変更されて `2020-09-02` が `2020/9/2` といったように上書きされてしまうことがあります。

# java.time.LocalDate で取り込む

このようにExcelで自動変換された日付フォーマットの文字列を `java.time.LocalDate` で取り込むときは `java.time.format.DateTimeFormatter` でフォーマットを指定する必要があります。

```scala

scala> import java.time.LocalDate
import java.time.LocalDate

scala> import java.time.format.DateTimeFormatter
import java.time.format.DateTimeFormatter

scala> val localDate = LocalDate.parse("2020/9/2", DateTimeFormatter.ofPattern("yyyy/M/d"));
localDate: java.time.LocalDate = 2020-09-02
```
Win10でUnity ML-Agents release_6 Install から 環境テストまで。

#はじめに

前回Unity ML-Agentsを使ってから新たにメジャーバージョンが出たのでとりあえず実行環境を整えていきます。

参考: [Unity Ml-Agents Installation](https://github.com/Unity-Technologies/ml-agents/blob/release_6/docs/Installation.md)

困ったことがあったら公式を見ること。英語は読むこと。

実行環境
---
||バージョン|
|:---:|:---:|
|Windows 10|1909|
|Unity|2018.4.26f1|
|Python|3.6.6|
|ML-Agents|Release 6|

ML-Agentsは現時点でUnstableでない最新のRelease 6を使用します。

またRelease 6は、Unityの2018.4もしくはそれ以降、Pythonは3.6.1もしくはそれ以降を使用しなければならない点に注意してください。

#まずは仮想環境作成

Anacondaで仮想環境を作成して元の環境と分けられるようにしておく。

```
conda create -n ml-agents
```

pythonのバージョンを指定したい場合は(バージョン3.6とすると)、

```
conda create -n ml-agents pyhton=3.6
```

仮想環境を作成後はactivateします。

```
conda activate ml-agents
```

これで仮想環境作成は終了。


#ML-Agents Release 6のセットアップ


UnityとPythonのインストールは済んでいるものとします。

まずはGithubからToolkit Repositoryをcloneします。

```
git clone --branch release_6 https://github.com/Unity-Technologies/ml-agents.git
```

`--branch release_6`はrelease 6を指定するタグで、これを除くとmasterブランチのリポジトリをcloneすることになります。masterブランチは最新ですが、unstableなバージョンです。

##`com.unity.ml-agents`パッケージをUnityにインストール


先ほどクローンしてきたレポジトリ内にcom.unity.ml-agentsがフォルダがあるのでそれをUnityにインストールする。

1. Unityを開き、`Window -> Package Manager`を開く
2. Package Managerウィンドウの `+`ボタンをクリックする
3. `Add package from disk...`を選ぶ
4. `com.unity.ml-agents`フォルダを開く
5. `package.json`ファイルを選択する

##Pythonの`mlagents`パッケージをインストールする


```
pip3 install mlagents
```

#Getting Started ガイドを試す


参考: [Getting Started Guide](https://github.com/Unity-Technologies/ml-agents/blob/release_6/docs/Getting-Started.md)

このガイドにEnvironmentを理解する項目があるのですが、自分で環境作成をするならしっかりと読んだ方がいいです。

今回はお試しなのでまずは3DBallのpre-trained modelを使います。他にもいろんなサンプルがあるのでいろいろ試してみましょう。


##pre-trained modelを試す

1. `Project/Assets/ML-Agents/Examples/3DBall/Scenes` から `3DBall`を開く
2. Projectウィンドウから`Assets/ML-Agents/Examples/3DBall/Prefabs`を開き、3DBallを展開してAgent prefabをクリックする

    Note: 3DBallのプラットフォームは3DBall prefabを使用し作られている。よって12個のプラットフォームを全てアップデートする代わりに、3DBall prefabをアップデートすることによって変更できる。

3. Projectウィンドウから、`Assets/ML-Agents/Examples/3DBall/TFModels`の3DBallをInspectorウィンドウのAgentのBehavior ParametersのModelにドラッグする。(既に設定されているが、それぞれの学習結果をNNModelとして保存しModelに設定することで学習結果を確認できる。)
4. Sceneの各3DBallのAgentのBehavior ParameterのModelが3DBall(NNModel)になっていることを確認する。
5. このModelで使用するInference DeviceをCPUにセットする(GPUを使用する場合はGPU)
6. Unity EditorのPlayボタンを押して3DBallが実行されていることを確認する

##強化学習で新しいモデルを学習させる


1. terminal windowを開く
2. Cloneした`ml-agents`レポジトリに移動する
3. 以下のコマンドを実行する

    ```
mlagents-learn config/ppo/3DBall.yaml --run-id=first3DBallRun
    ```

4. "Start training by pressing the Play button in the Unity Editor"というメッセージが出たら、UnityのPlayボタンを押して学習を始める
5. 学習結果が`ml-agents/results`に格納されるので、first3DBallRunをProjectウィンドウにドラッグしコピーする
6. Projectウィンドウから`first3DBallRun/run_logs`の3DBallを3DBall prefabのBehavior ParameterのModelにドラッグする
7. UnityのPlayボタンを押して学習結果を確認する

##トレーニングの進行を確認する

先ほど学習した結果をtensorboardで確認する

```
tensorboard --logdir results
```

上のコマンドを実行すると、自身のブラウザの`http://localhost:6006`で確認できる

#まとめ
以上でインストールからテストまでは終了です。
間違いや不足点などございましたらおしらせ下さい。

また、自身で何をしたか確認する等の目的で書いたものなのでわかりづらい点などがあるかと思います。基本的には自身で公式のドキュメントを読んで実行するのがいいと思います。
緯度経度のリストを作って一括でUTM座標変換→ファイル出力

#EQAリストから一括変換してUTMリスト作成まで
以前pythonを用いてEQA (緯度経度) からUTM (ユニバーサルトランスバースメルカトル) 座標へ変換するpythonコードを書きました．
↓Pythonで緯度経度座標↔UTM座標変換
https://qiita.com/spicy_HotChicken/items/4cdf303493d73e24dc14

ひとつひとつ座標変換するときにはpythonスクリプトに座標値を入力してしました．
しかし，だんだん変換する数も増えてきて面倒になってきたので，緯度経度のリストを作って一括変換してテキストファイルで出力できれば楽なのではないかと思いました．
緯度経度リストは左から緯度，経度の順でスペース区切りにしたときの座標変換スクリプトになっています．

```
$ cat input.dat
139.2341321 35.534243
132.3214315 32.542664
138.4312145 36.534261
```

変換スクリプトは以下の通りになります．
冒頭で入力・出力ファイル名を指定しています．

```python:eqa2utm_list.py
import numpy as np
import os 
from pyproj import Proj

inpf='input.dat' #Define input file name.
outf='output.dat' #Define output file name.
#Check existence of output file.
#If output file exists, remove it.
if os.path.isfile(outf):
    os.remove(outf)

tmpdata=open(inpf, "r")
data=tmpdata.read().split('\n')
for a in range(len(data)-1):
    ardata=np.array(data[a].split(), float)
    #datastr=data[a]
    lon=ardata[0]
    lat=ardata[1]
    #print lon, lat
    
    #eqa2utm.py
    e2u_zone=int(divmod(lon, 6)[0])+31
    e2u_conv=Proj(proj='utm', zone=e2u_zone, ellps='WGS84')
    utmx, utmy=e2u_conv(lon, lat)
    if lat<0:
        utmy=utmy+10000000
    
    with open(outf, 'a') as f:
        outp=str(utmx)+str(' ')+str(utmy)+str(' ')+str(e2u_zone)
        f.write("%s\n" % outp)
        
print '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n',\
 ' EQA2UTM transformation Completed. \n',\
 '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n'

#Show output file on a screen
f=open(outf, 'r')
data=f.read()
print(data)
```
私の環境だとpythonでテキストデータを読み込むとstring型のlistになるので，`*.read.split('\n')`で改行ごとに分割してlistにします．
今回は1行ずつ読んでいく方法しかわからなかったので，ループで1行ずつ読んで変換→ファイル出力を繰り返しています．
`ardata`は緯度経度座標をfloat型のnparrayにしています．
あとは緯度と経度をそれぞれ定義して，EQA2UTMの座標変換をしています．

##適用例
試しに動かしてみます．

```
$python eqa2utm_list.py
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 EQA2UTM transformation Completed. 
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

339907.669515 3933725.28372 54
248457.470634 3603752.79472 53
270030.490036 4046278.55358 54
```

inputファイルは左から緯度，経度の順に，outputは左からUTM Easting, UTM Northing, UTM Zoneの順にリストになっています．



## (おまけ) 対話的にEQA2UTM変換をする
先ほど紹介したEQA2UTMの変換はスクリプトに座標したい緯度経度座標を直接入力していました．これは面倒．
今回は緯度経度リストをつくって一括変換しました．座標変換したい緯度経度リストさえ作ってしまえばいいのです．
しかし1点だけ変換したいけどリストを作るほどでなければ，対話的に座標を入力してターミナル画面上にUTM座標値を出力するようにしてしまおうという算段です．そんな人いないか．．．

```python:eqa2utm_int.py
from pyproj import Proj

#変えたのは下の2行だけです↓
lon=float(input('>> Longitude [deg.] >>')) 
lat=float(input('>> Latitude [deg.] >>'))  

e2u_zone=int(divmod(lon, 6)[0])+31
e2u_conv=Proj(proj='utm', zone=e2u_zone, ellps='WGS84')
utmx, utmy=e2u_conv(lon, lat)

if lat<0:
    utmy=utmy+10000000

print "UTM zone is ", e2u_zone, " \n", \
      "UTM Easting is", utmx, "[m]\n",\
      "UTM Northing is ", utmy, "[m]"

#EOF
```


```
$ python eqa2utm_int.py
>> Longitude [deg.] >>132.55
>> Latitude [deg.] >>38.222
UTM zone is  53  
UTM Easting is 285531.137964 [m]
UTM Northing is  4233284.85815 [m]
```
pythonスクリプトを動かすと緯度と経度を聞かれるので，入力してEnter押下でUTM座標値をターミナル画面上に表示します．楽ちんです．

-
Rubyのクラス内でインスタンス変数が定義済みかを確認する方法




```rb:dog.rb
class Dog
  def initialize(name)
    @name = name
  end

  def set_nickname(nickname)   # rubyでset_hogeは使わないけど今回は簡略化のために大目に見て!
    @nickname = nickname
  end

  def print_nickname
    if !defined?(@nickname)
      puts('Not Set')
      return
    end
    puts(@nickname)
  end
end
```


if @ageを参照した時に、それがnilだった場合、以下のどちらのケースか分からない。

- 一度も定義されていないからnilなのか
- 一度@nickname=nilを代入した結果のnilなのか

そんな時には`defind?(@age)`を使用すべし。
VBAでMatch関数を使用し列番号を取得する

##列挿入や列削除で列番号が変わる可能性がある
Excelのシートでは列を追加したり削除したりすることがあり
以下のようなコードだとその度書き直すことになるので

```vb
ThisWorkbook.Worksheets("Sheet1").Cells(LastRow + 1, 1).Value = 10
```

その度書き直さなくてもいいように
項目行から項目名をMatch関数で検索し、変数に格納します。

```vb
Sub MasterDataAdd1()'最終行のひとつ下にデータを追加するコード
    Dim NoCol As Long 'Noの列番号を格納する変数
    Dim IDCol As Long 'IDの列番号を格納する変数
    Dim LastRow As Long '最終行を格納する変数
    
'列番号を変数に格納する
'Masterはシートオブジェクト名です
    NoCol = WorksheetFunction.Match("No", Master.Rows(1), 0) 'Match関数で列数格納
    IDCol = WorksheetFunction.Match("ID", Master.Rows(1), 0) 'Match関数で列数格納
    LastRow = Master.Cells(Rows.Count, NoCol).End(xlUp).Row '最終行格納
    Master.Cells(LastRow + 1, NoCol).Value = 10 '最終行のひとつ下にNo追加
    Master.Cells(LastRow + 1, IDCol).Value = "jjj" '最終行のひとつ下にID追加
End Sub
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700414/98ac074e-3644-ba1c-3adf-56cf874e34e1.png)
##ワタシ流こだわり:point_up:
列番号を格納する変数は「__～Col__」
行番号を格納する変数は「__～Row__」
##ちなみに
このままだと項目行の上に行を追加されたり項目名を変更されたらアウトです。
その可能性がある場合はその対策もとる:wink:
でもとりあえずむやみな変更をしないように伝えておくのは大事。
【AndroidStudio】ボタンのキャプション設定方法その2

:arrow_right: [設定方法その1](https://qiita.com/Yuko809/items/8c3bf42daf6cdd37922f)

activity_main.xmlにボタン（id：myButton）を配置した上で、
MainActivity.javaに以下の通り記述する。

```java:MainActivity.java
package hoge.fuga.sandbox;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.View;

import android.widget.Button; //★1

public class MainActivity extends AppCompatActivity {
    
    private Button myButton; //★2
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        myButton = findViewById(R.id.myButton); //★3
        
        myButton.setText("あいうえお"); //★4
    }
}
```

| ★ | 説明 |
|:-:|:--|
| 1 | ★2を記述したところ、「この `Button` はAndroidWidgetか？」との確認が出て自動生成されたもの。 |
| 2 | activity_main.xmlに配置した `myButton` をMainActivity.java内で取り扱うための変数を宣言している。 | 
| 3 | activity_main.xmlのコントロールが列挙されたRクラスから、 `myButton` を取得して★2で用意した変数に格納している。 | 
| 4 | `setText()` を用いてボタンのキャプションをセットしている。strings.xmlの設定よりこちらが後勝ちになる。 | 

以上
AHDLでCPUを加算器から作成してみる

今回が初投稿になりますがよろしくお願いします.
もし間違いや誤字等ございましたらお知らせいただけると幸いです.

計算機の基礎として学習する半加算器,全加算器等を用いて16bitのCPUを設計してみようと思います.
今回は序論ということで

* 半加算器の作成
* 全加算器の作成

について書いていこうと思います．

# 半加算器の作成
まず,半加算器について学んでいきましょう.
半加算器とは1bitの値A,Bを入力として,Sum(1bitの演算結果),CarryOut(桁溢れ)を出力する回路です.
実際には

* $0+0=0$
* $0+1=1$
* $1+0=1$
* $1+1=0$(桁溢れ)
 
のようになります.

## 真理値表の作成
これを真理値表にすると

| A | B | Cout | S |
|:-:|:-:|:----:|:-:|
| 0 | 0 |   0  | 0 |
| 0 | 1 |   0  | 1 |
| 1 | 0 |   0  | 1 |
| 1 | 1 |   1  | 0 |

のようになります.それでは順番に見ていきましょう.

まず,A=0,B=0の場合は0+0ということでCout,Sumともに0になります.
なのでCoutもSoutも0となります.ここは特別な説明は不要だと思います.

次に,A=0,B=1およびA=1,B=0の場合は0+1ということでSumは1となります.
この時点では桁溢れを起こしていないためCoutは0+0同様に0のままです.

## CoutとSの論理回路について
先ほど作成した真理値表の動きを実現する論理回路を作成していきます.
CoutについてはA,Bともに1の場合に1を出力,つまりANDゲートを用いて実現できます.
SについてはAとBのどちらかが1の場合に1を出力,つまりXORゲートを用いて実現できます.

よって

* Cout = A・B
* S    = A⊕B

となります.


# 全加算器の作成
全加算器は半加算器を拡張したものであり,入力がA,Bの他に下の桁からの繰り上がりCinを持ちます.

| A | B | Cin |Cout | S |
|:---:|:---:|:-----:|:-----:|:---:|
|  0  |  0  |  0  | 0 | 0 |
|  0  |  0  |  1  | 0 | 1 |
|  0  |  1  |  0  | 0 | 1 |
|  0  |  1  |  1  | 1 | 0 |
|  1  |  0  |  0  | 0 | 1 |
|  1  |  0  |  1  | 1 | 0 |
|  1  |  1  |  0  | 1 | 0 |
|  1  |  1  |  1  | 1 | 1 |

この真理値表から**A,B,Cinの2つ以上が1のとき**に**Coutは1**となることがわかります.
また,**A,B,Cinのどれか1が1,もしくはA,B,Cinの全てが1のとき**に**Sは1**となることがわかります.
これを半加算器同様に論理式で表すと

* Cout=(A・B)+(B・Cin)+(Cin・A)
* S=A⊕B⊕Cin

となります.
ではここで全加算器をAHDL言語で書いてみましょう.

```
SUBDESIGN fa_d
(
    a,b,c_in :  INPUT;
    s,c_out  : OUTPUT;
)
BEGIN
    c_out = (a & b) # (b & c_in) # (c_in & a);
    s = a $ b $ c_in;
END;
```
上記のコードに関して1つずつ見ていきましょう.
まずSUBDESIGN()で囲まれた部分はサブデザイン部分と呼ばれサブデザイン名(のちに参照される際の名称)と信号で構成されます.今回は**入力信号としてa,b,c_in**を,**出力信号としてc_out,s**を持つのでこのように記述します.

また,BEGINとEND;で囲まれた部分は論理部分であり,回路の動作を記述します.
今回設計する全加算器のc_outとsは先ほど述べた論理式で導出されます.AHDL言語では**論理積は&,論理和は#,排他的論理和は$**を用いることに気をつけてください.

これで全加算器の設計は終了です.
【Rails】updateアクションが通らない理由を間違って検証し続けた話(update)


# 1.やりたかったこと

gem deviseを利用してユーザー登録（名称はownerとしている)機能を実装済。
パスワードの入力なしに、登録されたデータを編集しようとするもエラーが起き、その解決に無駄にだいぶ悩んでしまった話。

# 2.実行環境

Ruby 2.6.5
Rails 6.0.3

# 3.前提としてできていた準備

devise側の仕様に沿って以下の二つの準備が必要でした。
①account_update時にデフォルトカラム以外のカラムの値を許容する（sanitizer)
②passwordなしでのアップデートを許容する。

公式の[こちら](https://github.com/heartcombo/devise)とか[こちら](https://github.com/heartcombo/devise/wiki/How-To:-Allow-users-to-edit-their-account-without-providing-a-password)の記事を見ればできるかと思います。Qiitaも調べればいっぱいあるはずです。

これらは出来ていたのに以下の様になぜかうまくアップデート保存ができず、deviseの仕様のせいか・・・？と悶々と悩むはめに。

![スクリーンショット 2020-09-02 12.00.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619380/25c367e6-c03b-af69-58f9-7945cc7be61a.png)

上のエラー検証をしていて僕は以下の様に悩んでいたのでした。

1.ArgumentError given 0〜となっているので、そもそもうまいこと引数が渡されていないのでは？(でもparamsはちゃんと通っている・・・)
2.エラーメッセージがパスワードということは、やはりdeviseのパスワードなし更新がうまくいっていないのでは？

# 4.結論

パスワードのバリデーションがひっかかってる故のエラーでした。

```ruby:owner.rb
class Owner < ApplicationRecord

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  validates :name, presence: true
  validates :email, presence: true, uniqueness: true, format: { with: VALID_EMAIL_REGEX}
  validates :password, presence: true, confirmation: true, length: { minimum: 7 }

  has_many :shops
end

```

上記モデルのバリデーションがupdate時にもかかっており、それでエラーがでていた形です。
よく考えればバリデーションに設定したエラーメッセージが出力されてるんだから当たり前ですよね、そもそも。

なので

```ruby:owner.rb
class Owner < ApplicationRecord

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  validates :name, presence: true
  validates :email, presence: true, uniqueness: true, format: { with: VALID_EMAIL_REGEX}
  validates :password, presence: true, confirmation: true, length: { minimum: 7 },on: :create

  has_many :shops
end

```

こんな感じでパスワードのバリデーションをcreate時のみの設定にしてあげれば解決しました。


# 5.泥沼にはまったミス

![スクリーンショット 2020-09-02 14.49.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619380/3f79dd89-2ed8-d574-499d-9f7c36bc49d7.png)

先ほどのbinding.pry時のエラーメッセージについて、僕はここで引数がうまくわたっていないと思いこんでいたのですが、その認識がそもそも誤っておりまして。

controllerのupdateアクションでちゃんと引数が渡った後に、デバッグ画面でもう一回updateを実行しているんですよね、これだと。
なので僕がこの画面上でうったupdateには引数が指定されていないので、そりゃ引数ないよというエラーが起きているだけなのです。

この流れをちゃんと理解できていいないからこそはまったミスでした・・・反省。
[GAS]隔週に一回、何週目などを判定したい[Momentjs]

ソースコードで解説します。
Momentに詳しくない私のために、考え方をコメントに添えています。

```
var today = moment();

// 隔週の場合、今日が一年で何週目か分かれば、2で割れば隔週が求められる
var week = today.week() % 2;

// 月の１週目などの指定がある場合、月初めが何曜日で今日が何日目か分かれば何周目か求められる
var first_day = moment(today.format("YYYY/MM/DD")).date(1);  // 今月1日
var today_week = Math.ceil((first_day.day() + today.date())/7);    // 日曜日の1日は1、土曜日の1日は7になる
if(today_week == 1 && today.day() == 0) // 一周目の日曜日の場合

// 一回目の日曜日を検出したい場合、1日が何曜日か求めて、1週目と2週目の可能性を追求すれば分かる
var target_week = (first_day.day() == 0) ? 1 : 2;
if(today_week == target_week) // 一回目の日曜日の場合  
```

# 解説
この記事を読んでいる方は面倒くさがりな方[^1]だと思いますが、コメントを読んでフローチャートを書けば難しい話ではない事がわかります。
本稿では考え方について触れたいので`moment`を使用していますが、`moment`である必要はないです。

[^1]: 【面倒くさがり】プログラマーとしては良いことだと思います。

# 実践例
[GASで毎日ゴミの日を通知する](https://github.com/shimajima-eiji/Hosting/blob/GAS-timetrigger/%E3%82%B4%E3%83%9F%E3%81%AE%E6%97%A5.gs)
IQ Bot：可変の明細がとれるしくみ

#可変の明細が取得できるIQ Bot

IQ Botは以下のように、行数が可変の明細でも取得することができます。

![可変の明細がとれる.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/0b30d42a-883f-7cdb-d9f5-481f9eb1b13a.jpeg)

ただし、「どんなに複雑な明細でも空気を読んでうまいこととってくれる！」というわけではなく、可変の明細を取得するためには一定の条件があります。


#IQ Botが可変の明細を取得する仕組み

ズバリ！　ポイントは、テーブル項目の一覧のいちばん上の行にある「Table/section settings」の中の、「テーブル/繰り返しセクションに最適なフィールド」という部分です。

![繰り返しのキー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/9221443c-7aea-68d4-6493-2493721186b0.jpeg)

上記の例では「商品番号」が設定されていますが、これは「商品番号が切り替わるごとに、抽出する行を切り替えてください」という意味です。
以下、この「テーブル/繰り返しセクションに最適なフィールド」をキーと呼びます（繰り返しのキーになるので）。

![行の切替.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/2da4c4e2-bbb2-9efb-694f-3dee3add0ee0.jpeg)

商品番号をキーにすると、ここのように、商品番号の単位で行が抽出されていきますが・・・
![商品番号がキー.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/c460640c-bb62-256a-65d3-8cc0ba3d8c1d.jpeg)

例えば同じ帳票でも摘要欄をキーにした場合、摘要欄が切り替わるごとにIQ Botも抽出の行を切り替えるので、こんなかんじの抽出ぶりになります。

![摘要欄をキー.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/0bb5aae7-5e4a-e190-ecb3-f108e386d73f.jpeg)

どの項目をキーにするべきかは、帳票や業務要件によって様々です。
例えば以下のような帳票であれば、「品名」や「金額」あたりをキーにするのが良いでしょう。

![どこでも商事（明朝、グレー、紺文字）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/33ed9cb1-44eb-040f-6644-ae50dcdf26c5.jpeg)

上記の帳票で、仮に「日付」などをキーにしてしまうと、IQ Botは日付が切り替わるまでを同じ明細行として認識しようとします。

![仮に日付をキーにするとこうなる.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/c578bc82-f1c6-e690-3382-95dc9b7a5f8a.jpeg)

すると抽出結果はこのようになり、明らかに意図と違いますね。
![明らかに意図と違う抽出結果.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/cf31fa56-3cee-a5c0-6d1b-9aa59b60e7f2.jpeg)


#可変行の明細・とれる/とれないの見分け方

IQ Botが可変行の明細を取得する仕組みは上記のとおりなので、原則として、以下の条件を満たす必要があります。

- キーになる項目が決められること
- キーになる項目が「上揃え」の状態になっていること

可変の明細で、かつ「上下中央揃え」のような書式になっているものをたまに見かけますが、そうなると一筋縄ではいきません。

![上揃え.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/1186936a-2fa9-4bff-10fe-d3705fa8f787.jpeg)

キーが決まらない場合でも、[テーブルに対するカスタムロジック](https://qiita.com/IQ_Bocchi/items/b24fad1aa6b19aa17267)など使って抽出できる場合もありますが、キーで切り替えられる帳票に比べると難易度が上がります。
【React + TypeScript】event.preventDefault()をTypeScriptで使う。

# event.preventDefault()のeventをTypeScriptの型対応

Reactでなかなかの頻度で使用するevent.preventDefault()をTypeScript対応させるとこんな感じ。

```tsx
 const functionName = (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
    e.preventDefault()
    ...
 }
```

みんなも使ってね。
Oracle 11g Express Editionのダウンロード方法

対象
-------------
- Oracle 11g Express Edition を公式サイトからダウンロードしたい人
- ダウンロードできない人 (2020/09/02時点の内容なので変わる可能性があります)


結論
------------
[Oracle Database XE Downloads](https://www.oracle.com/database/technologies/xe-downloads.html) → [Prior Release Archive](https://www.oracle.com/database/technologies/xe-prior-releases.html)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12275/96cb4b8e-61de-8271-6cde-38eb944bddb1.png)

※ダウンロードするにはログインとライセンスへの同意が必要です


解決に至るまでの経緯
=======================

ハマった点: 永遠に同じページが表示される
-------------

[Oracle Database Express Edition 11g Release 2 | Oracle 日本](https://www.oracle.com/jp/database/technologies/xe-prior-releases.html)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12275/06d2a2f7-bb39-ccb0-ac06-1815cb2bc118.png)

こんなページが表示されて、永遠に同じページが表示され続ける
→見るページが違う


ハマった点：18cしかない
-------------------
[Oracle Database XE Downloads](https://www.oracle.com/database/technologies/xe-downloads.html)
Basic認証下でServiceWorkerがエラー吐くのを解決する

Basic認証やDigest認証掛かってる非公開環境でありがちな問題を.htaccessで解決する

### こういう人向け。

・cssやjsの読み込みの度に認証ダイアログが出て困ってる
・動いてんだけどmanifestファイルが引っかかってコンソールでエラー吐いてる

```apache:.htaccess
<FilesMatch "\.(js|css|json)">
    Satisfy Any
    Order allow,deny
    Allow from all
    Deny from none
</FilesMatch>
```

もちろんURL直打ちでファイルの内容は見えてしまうので
minifyなり見られていいレベルのもの限定。
DockerでPuphpeteerを使う

# この記事について
すでにあるプロジェクトに[Puphpeteer](https://github.com/nesk/puphpeteer)を導入する

自分用メモです

## 作業

```:in-container-terminal
$ composer require nesk/puphpeteer
$ npm install @nesk/puphpeteer puppeteer
```

メモリでコケたら`php.ini`を修正

```ini:php.ini
memory_limit=1G
```


```Dockerfile:Dockerfile
FROM php:7.4.1-fpm

# 省略

# puppeteerのインストール
RUN apt-get install -y nodejs gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils libgbm-dev wget
RUN npm install --global --unsafe-perm puppeteer

# 日本語フォントのインストール(これ入れないと日本語のサイトで文字化けする)
RUN apt-get install fonts-ipafont-gothic fonts-ipafont-mincho

# 省略

```


## 以下の処理を実行して`example.png`ができていれば成功

```php:puppeteer
<?php

use Illuminate\Console\Command;
use Nesk\Puphpeteer\Puppeteer;

class Scraping
{

    public function main()
    {
        $puppeteer = new Puppeteer;
        $browser = $puppeteer->launch([
            'args' => ['--no-sandbox', '--disable-setuid-sandbox']
    	]);
        $page = $browser->newPage();
        $page->goto('https://example.com');
        $page->screenshot(['path' => 'example.png']);

        $browser->close();
    }
}
```




## 参考
https://qiita.com/HeRo/items/9be64b559692e12cc109
OSSにIssueを書いたら他の人がPRを作ってくれた話

## なんか感動した

人生で初めて OSS に Issue を書いてみました
修正方法はわかっていたのでプルリクを出してみようかと思ったけどやり方が分からずにモヤモヤしてました
すると他の人がコメントで PR 出しますよ〜と、やってくれて感動したので共有したいと思いました

※　 Issue を書いた以外は私は何もしていません・・・ぴえん

## 経緯

### バグ発見

いつも使ってる Buefy でバグを見つけました

↓ 記事
[【Buefy】b-table の background スタイルのバグを見つけたので修正してみた](https://qiita.com/azuharu07/items/4f8fcd92e049e34c2797)

折角の機会なので OSS である Buefy のリポジトリに Issue を書いてみようと思いました

### 人生初 OSS に Issue 投稿

規約を読み、先生（google）の翻訳機能を駆使しながら拙い英語で書いてみました
[the margin part of the b-table record is displayed in white on the smartphone #2824](https://github.com/buefy/buefy/issues/2824)

※　アカウントがazuharu07ではないのは会社で使ってるアカウントを使用したから

一応ローカルで修正していたので、人生初 PR をしてみようと思いました

しかし当然他者のリポジトリなので修正することができませんでした

### 人生初 Issue のコメントで会話

OSS コントリビュートの仕方を調べていると、通知が来ました・・・

感動のあまり英語を読むのを諦めて速攻翻訳にかけました

> 神：プロジェクトで直したことあるよ！行けそうなら僕が PR 出すよ！（意訳）

その直後、その方から dev ブランチに PR が・・・!!!

私は感動のあまりまた速攻翻訳で英文を作りました

> 僕：Thank you for your quick response!!!

これ翻訳にかけるまでになかった・・・

### その後の会話

> 神：どういたしまして！でも僕初コントリビュートなんで承認されるかは分からん w
> 　　でもまあ必要ならこのコードローカルに持って行ったら使えると思うよ！（意訳）

強者の余裕を感じました

> 僕：thank you for the advice! I hope your PR is approved

アドバイスありがとう！あなたの PR が承認されることを祈っています で google 翻訳すると出る文章まんまです

ちゃんと英語を勉強しようと思いました

こうして僕は何もしないまま問題は解決しました

## どうやって PR 作ったか

github には fork という機能があります

これは自分のアカウントにそのアカウントのクローンを作り、あたかも自分のリポジトリであるかのようにする機能です

どうやら OSS は

1. オリジナルのリポジトリを fork して自分のアカウントに持ってくる
1. 自分のリポジトリをローカルに clone してきて修正し push する
1. 自分のリポジトリからオリジナルのリポジトリの develop(に相当するブランチ)に PR を作る

という流れでやるのが一般的みたいです（間違ってたら指摘していただけるとありがたいです・・・）

fork,PR を作る際はオリジナルのリポジトリの規約をちゃんと読んで出してね〜　と書いてあります

## 参考

### fork の仕方

-   オリジナルのリポジトリの右上の fork をクリック

![fork_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461616/849951b0-c79c-330b-f84f-d8c1ddd410aa.png)

-   自分のアカウントに同じ名前のリポジトリが作成される

![fork_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461616/0b3ed766-7144-1adf-b660-6f800359f2c0.png)

このリポジトリはあくまで自分のリポジトリなので、煮るなり焼くなり好きにして OK

### PR を出すとき

-   自分のリポジトリで Pull requests で[New pull request]をクリック

![fork_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461616/6338c9e4-e2b4-bee2-786b-33c6012fb5b3.png)

-   fork 元のブランチに行くので base repository と head repository が正しいことを確認して[Create pull request]

![fork_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461616/62a58cdb-fd1d-64bc-35f5-52121f43bf22.png)

これで自分のリポジトリからオリジナルのリポジトリへアカウントの垣根を飛び越えて PR が作るみたいです

※この PR はもちろんキャンセルしました

## いつか・・・

今回初めて OSS コントリビュートの流れを体感しました（自分は Issue 作っただけですが・・・）

Issue を書く前はドキドキしていたけど、作ったあとはトントン拍子で PR 作成まで進むのをみて意外とハードルが低いんだな？と思いました

いつかは自分で修正し、PR を作成し、OSS コントリビュートをしたいなと思ってます

今回出してくれた PR はまだマージされていないみたいなので、無事に承認されることを祈っています
web製作でスライドショー設置するならslickがおすすめの理由

![uploading...0]()


スライドショーでどのプラグインを使えばいいか迷った経験はありませんか？僕はどれを使えば良いか分からず、いろいろ試してみました。プラグインなし、swiper、slick...
今回は、その中でもslickが一番おすすめできる理由を紹介します。

1.オプションが充実していて自分なりにカスタマイズできる
　slickの一番の魅力は、そのオプション数の多さです。参考サイトは下記。

slickの使い方からカスタマイズまで【スライダープラグイン決定版】
https://b-risk.jp/blog/2020/01/slick-customize/

余程凝ったスライドショーを設置したいと思わない限り、自分好みのスライドショーを設置することができます。

2.一番有名だから、サンプルのコードが出回っている
　slickはその使いやすさから、スライドショーのプラグインの中でも、もっとも有名なプラグインの１つです。そのため、「スライドショー slick」などとググれば、サンプルコードが大量に転がっています。自分の理想のスライドショーに近いサンプルコードを探して、コピペして、少しオプションをいじるだけで完成です。jQueryの知識がない人でも簡単にスライドショーを設置することができます。

slickは汎用性の高いプラグインです。基本的には、スライドショーの設置に困ることはないと思いますが、状況によっては他のプラグインが適している場合があります。自分なりにある程度調べてから、どのプラグインを使うか検討してみてください！
ActiveStorageとFakerを利用した際に、画像を含めたテストをする方法



【概要】
----------------------------------------
<b>1.結論</b>

<b>2.なぜFakerでimageを作らずに、fixture_file_uploadを使うのか</b>

<b>3.どのように使うのか</b>

<b>4.ここから学んだこと</b>



1.結論
----------------------------------------
<b>fixture_file_upload</b>メソッドを使用する。

<br>
2.なぜFakerでimageを作らずに、fixture_file_uploadを使用なのか
----------------------------------------
理由は1つです。

ActiveStorageを利用しているのでimageカラムを作っていません。なので、Fakerで作ることができない（仮に具体的な画像を入れるにしてもspec/factoriesにはimageカラムがないので設定できない)からです。

たとえimageカラムを作っていたとすると、Fakerで画像をランダムで生成（適当に拾ってくる）方法がわかりませんでした。（Fakerにそのような機能はGithubに見当たりませんでした。）

<br>
3.どのように使うのか
----------------------------------------
答えは簡単で、spec/modelsの該当ファイルに、
fixture_file_upload（該当ディレクトリの画像ファイル）をインスタンス変数に代入するだけです。
（Fakerを利用せずに、具体例をspec/factoriesにプログラムしている場合はローカル変数になると思います)

```ruby:spec/models
require 'rails_helper'

RSpec.describe BuyItem, type: :model do
  describe '#create' do
    before do

      @buy_item = FactoryBot.build(:buy_item)
      @buy_item.image = fixture_file_upload('app/assets/images/aiueo.png')

    end
  end
end
```
このような記述になります！
spec/factoriesで具体例をプログラムしていない（Fakerを使用しているかつ、imageカラムがない）ので適当な具体的な画像を直接的にインスタンス変数に入れました。そうすることで、”@buy_item”に直接的に画像を入れているので"Image can't be blank"というエラーがなくなります。
<br>
5.ここから学んだこと
----------------------------------------
ActiveStorageのgemを利用しているのにもかかわらず、カラム名に"image"を作っていました。またFakerでimageを作ろうにもやり方がわからず、カラム名を削除しました。その後、imageをFakerに頼らず（ランダム生成ではなく適当な画像を）インスタンス変数に代入しようかといろいろ検索した結果、fixture_file_uploadに行きつき救われました！

参考URL：<a href="https://www.it-swarm.dev/ja/ruby-on-rails/rspec%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89%E3%82%92%E3%83%86%E3%82%B9%E3%83%88%E3%81%99%E3%82%8Brails/940452994/">rspecを使用してファイルのアップロードをテストする-rails</a>
<br>
Vue.js commputedが動いてくれないがリロードすると治る問題


## 事象
シークレットモードで動作確認するとcommputedが動いてくれなかった。
リロードしてから再度確認すると動くようになった。

## 原因
vuex初期化の際、stateに、key, valueを渡していなかった
別のアクションによりkey, valueがstateにセットされた

## 対応
初期化の際、stateに、key, valueをセットする

```
const initialState  = () => ({
 hoge: fuga
})

export default new Vuex.Store({
  state: initialState(),
  
```
httpdサービスの構成とアプリケーション

#1. httpdサービスの設定ファイル
通常、httpdサービスのメイン構成ファイルは、httpdルートディレクトリにあるconf / httpd.confファイルです。yumを介してインストールされたhttpdサービスのメイン構成パスは、通常、次のとおりです。

httpd-2.2：/etc/httpd/conf/httpd.conf
httpd-2.4：/etc/httpd/conf/httpd.conf

メイン構成ファイルのフォーマットは、大きく3つの部分に分かれています。

セクション1：グローバル環境
セクション2：「メイン」サーバー構成
セクション3：仮想ホスト

ただし、対応する説明はhttpd-2.4バージョンで削除されましたが、httpd-2.2とほぼ同じです。

メイン構成ファイルに加えて、他の構成ディレクトリパスがあります。通常Include conf.d/*.conf、Include conf.modules.d/*.conf（httpd-2.4）同様のステートメントがメイン構成ファイルで使用され、対応するディレクトリ内の構成ファイルを呼び出します。パスの形式は相対パスです。 、ルートディレクトリは、メイン構成ファイルのServerrootによって決定されます。

この記事のケースはCentos 7.4 httpd-2.4に基づいています。

#2. httpdサービスの基本設定
1.監視対象のIPアドレスとインターフェースを変更する
メイン構成ファイルでは、httpdサービス監視IPアドレスとインターフェースの文形式は次のとおりです。

リッスン[IPアドレス：]ポート番号[プロトコル]

このステートメントの使用には、次の注意点があります。

IPアドレスは省略できます。つまり、0.0.0.0はすべてのIPに一致します。
このコマンドListenを複数回繰り返して、複数のIPアドレスとポートを監視できます。
監視対象のソケットを変更した後、サービスプロセスを再起動して有効にする必要があります。
SSL経由での通信に制限されている場合、プロトコルはhttpsとして定義する必要があります。

ユースケース：
`[root@localhost ~]# vim /etc/httpd/conf/httpd.conf 
Listen 80
Listen 192.168.0.109:8080  
[root@localhost ~]# systemctl restart httpd
[root@localhost ~]# ss -tnl
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128    192.168.0.109:8080                          *:*                  
LISTEN     0      128               *:22                            *:*                  
LISTEN     0      100       127.0.0.1:25                            *:*                  
LISTEN     0      128              :::80                           :::*                  
LISTEN     0      128              :::22                           :::*                  
LISTEN     0      100             ::1:25                           :::*      `

2.長い接続を使用する
長い接続とは、tcpリンクが確立された後、各リソースは取得の完了後に完全には切断されないが、他のリソース要求を待ち続けることを意味します。ただし、同時アクセス数が多いサーバーでは、長い接続を使用すると、後続の要求の一部が不可能になります。通常の応答を取得します。この状況では、長い接続タイムアウト期間を短くし、長い接続要求の数を少なく設定することで、状況を緩和できます。
構成コマンドは次のとおりです。

`keepalive On|off 
keepAliveTimeout 15  
MaxKeepAliveRequests 100  

ユースケース：
`[root@localhost ~]# vim /etc/httpd/conf.d/keepalive.conf
KeepAlive on
KeepAliveTimeout 30
MaxKeepAliveRequests 100
[root@localhost ~]# systemctl restart httpd  #重启服务

[c:\~]$ telnet 192.168.0.109 80  #在电脑终端用telnet测试连接性
Connecting to 192.168.0.109:80...
Connection established.
To escape to local shell, press 'Ctrl+Alt+]'.
GET /index.html HTTP/1.1
Host:192.168.0.109

HTTP/1.1 200 OK
Date: Tue, 01 May 2018 10:06:06 GMT
Server: Apache/2.4.6 (CentOS)
Last-Modified: Tue, 01 May 2018 10:03:41 GMT
ETag: "d-56b2215c57e7e"
Accept-Ranges: bytes
Content-Length: 13
Content-Type: text/html; charset=UTF-8

hello,world/

GET /index2.html HTTP/1.1  
Host:192.168.0.109

HTTP/1.1 200 OK
Date: Tue, 01 May 2018 10:06:39 GMT
Server: Apache/2.4.6 (CentOS)
Last-Modified: Tue, 01 May 2018 10:05:43 GMT
ETag: "15-56b221cfe406e"
Accept-Ranges: bytes
Content-Length: 21
Content-Type: text/html; charset=UTF-8

welcome to my office`
JavaScriptでAPIを叩いたらCORSエラーになった話

# JSでCORSエラー発生...
以下のコード(```fetch()```を使って)で外部APIを叩いてデータを取得しようとした。

```javascript

    const url = 'https://api.bitflyer.com/v1?product_code=BTC_JPY';

    fetch(url)
      .then(reseponse => {
        reseponse.json();
      })
      .then(data =>{
        console.log(data);
      });
```

しかし、以下のようなエラーが発生した。

```
Access to fetch at 'https://api.bitflyer.com/v1?product_code=BTC_JPY' from origin 'null'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on 
the requested resource. If an opaque response serves your needs, set the request's mode 
to 'no-cors' to fetch the resource with CORS disabled.
```

これらの文言を解釈すると、要するに....


- ```api.bitflyer.com```とは異なるホストからアクセスしようとしていますよ。
- CORSのポリシーにより、ブロックされましたよ。
- サーバーからのレスポンスに```Access-Control-Allow-Origin```のヘッダーがありませんよ。
- ```no-cors```のmodeを付けてリクエスト送ればCORSがdisableになるよ。

CORSとは[こちら](https://qiita.com/Kohei-Sato-1221/items/50faf3a8d118193f84a2)でも書いた通り、異なるホストからでもアクセスを許可する仕組みである。

つまり上記の場合
**bitflyer側がAccess-Control-Allow-Originを設定していないため、
ブラウザによってブロックされてしまった**
ということである。


# 新しいヘッダーを追加して再度トライ
modeの```no-cor```でやればいいじゃん？、的なことがエラーメッセージに書いてあったので、以下の通りソースコードを修正して再度トライしてみた。

```javascript
    const url = 'https://api.bitflyer.com/v1?product_code=BTC_JPY';

    fetch(url, {
      mode: 'no-cors'
    }).then(reseponse => {
      reseponse.json();
    }).then(data =>{
      console.log(data);
    });
```

しかし、上手く行かず、、、、、
以下のエラーが発生した。

```
Uncaught (in promise) SyntaxError: Unexpected end of input
```

最初のエラーメッセージに書いてある```opaque response```が問題なのでは？？
と思い。これを調べてみることにした。


# opaue responseとは？？？
opaque response 直訳すると**不透明なレスポンス**という意味である。
デバッグしてレスポンスの中身を見てみると以下の通りである。

```json-doc
//Response(一部省略)
{
    body: null,
    bodyUsed: false,
    ok: false,
    redirected: false,
    status: 0,
    statusText: "",
    type: "opaque"
}
```

**bodyがnull**である！！！
言葉通り不透明なレスポンスである。。。。


# 結論
色々ネットでも調べましたが、
**JavascriptでCORSエラーを回避してレスポンスを得るのは不可能**
という結論になりました。

素直にバックエンドと連携せよということでしょうか....

# 参考
[What is an opaque response, and what purpose does it serve?
](https://stackoverflow.com/questions/36292537/what-is-an-opaque-response-and-what-purpose-does-it-serve)
位相鋭敏マスク（PSM）で音声強調 with Python

所望信号が既知の場合に観測信号から所望信号を取り出すフィルタ（マスク）を作る位相鋭敏マスク（PSM）をPythonで実装してみる。音声強調の超基本のSTFT領域の音声マスクの設計というやつです。

# 音源強調の定式化
$x = s + n$<br>
$x$ 観測信号
$s$ 所望信号
$n$ その他信号

なんとかして$s$が欲しい。

音声強調の基本的な考え方としては、
$\hat{S} = G \odot X$

$X$ : $x$をSTFTしたもの
$S$ : $s$をSTFTしたもの
$\hat{S}$ : 推測された所望信号$s$

$G$ : 時間周波数マスク(行列の要素は $0\leq x \leq 1$の実数値)

観測信号$X$に何らかの手段で作った時間周波数マスク$G$を行列の要素ごとに掛け算（アダマール積）することで所望信号$\hat{S}$を推定する。時間周波数マスク$G$の作り方には、所望信号に含まれる周波数を増幅し、その他の信号を減衰させることで所望信号を取り出すウィナーフィルタなど様々に存在する。

音源強調は$x$から$s$を推定する問題となる。

# 位相鋭敏マスク(PSM)

$G = T[(|S| \oslash |X|) \odot cos(\angle S - \angle X)] ^1 _0$
$T[x]^1_0=min(max(x,0),1)$

# コード
```PSM.py
# 計算
import numpy as np
# 音声処理
import librosa
import librosa.display
# データ表示
from IPython.display import display, Audio


# Original Data
# オリジナルの音声ファイル
voice, rate = librosa.load("voice.wav", sr=rate)
# オリジナルの音声ファイルにノイズを付加したもの
noise, _ = librosa.load("noise.wav", sr=rate)


# STFT

# STFTパラメーター
n_fft = 1024*4     #フレーム長 (サンプル数)
win_length = n_fft     #窓関数長 (サンプル数)
hop_length = win_length // 4     #ホップ長 (サンプル数)
sr = rate     #サンプリングレート [Hz]

f_voice = librosa.stft(voice, n_fft=n_fft, win_length=win_length, hop_length=hop_length)
f_noise = librosa.stft(noise, n_fft=n_fft, win_length=win_length, hop_length=hop_length)

#PSM
X, S = f_noise, f_voice #観測信号、所望信号

A = (np.abs(S) / np.abs(X)) * np.cos((np.angle(S)-np.angle(X)))
B = np.where(A < 0, 0, A)
G = np.where(B > 1, 1, B)

# スペクトログラムの表示
# librosa.display.specshow(G, y_axis='log', x_axis='time', sr=sr, hop_length=hop_length)

# マスクの適応
_data = f_cafe * G # アダマール積
data = librosa.istft(_test,win_length=win_length, hop_length=hop_length)

# 完成音声の表示
# display(Audio(test, rate=rate))
```

# まとめ
Qiitaには音声ファイルを掲載できないので各自でやってみてください。
そのうちコラボラトリーかなんかでまとめて公開します。

# おまけ
## ウィナーフィルタを用いたノイズリダクション

$\hat{X} = E[X|Y] = \frac{\sigma_x ^2}{\sigma_x ^2  + \sigma_d ^2} Y$

ここで$\sigma_x ^2$や$\sigma_d ^2$は所望信号と雑音信号のそれぞれのスペクトルの分散を表す。(多分周波数領域ごとのスペクトル分散)<br>
つまり、誰も会話してない部分をノイズとして選択して、Dとして使ってやれば良い。この分散の分数部分がウィナーフィルタとなる。

```win.py
s=voice #所望信号
d=noise #観測信号
axis = 1

#観測信号
_, _, X = stft(d,fs = rate,nperseg=nperseg,noverlap = noverlap)

# 所望信号の分散
_, _, S = stft(s,fs = rate,nperseg=nperseg,noverlap = noverlap)
sigma_s=np.square(np.var(S,axis = axis))

#noiseの分散
noise_start = time2tap(8,rate)
noise_end = time2tap(9,rate)

_noise = d[noise_start:noise_end]
_, _, D = stft(_noise,fs = rate,nperseg=nperseg,noverlap = noverlap)
sigma_d=np.square(np.var(D,axis = axis))

#フィルタの生成
W = sigma_s / (sigma_s + sigma_d) #これだけあれば、リアルタイムな処理もできます
G = np.tile(W,(63,1)).T

#フィルタの適応
ret = G * X
ret = ret / np.amax(ret)
_,test = istft(ret,fs=rate)

display(Audio(test,rate=rate))
display(Audio(d, rate=rate3))
```


# 参考文献
[深層学習に基づく音源強調と位相制御](https://www.jstage.jst.go.jp/article/jasj/75/3/75_156/_article/-char/ja/)
MFCの開発環境移行時の画面レイアウト崩れ　備忘録

# 起こったこと
### 発端
わたしはいまだに仕事の一部でVisual Studio 2010の環境でMFCアプリケーションの（保守ではなく）開発をしています
※2010続行は客先要望です

メンバが増えたので新たなPCに開発環境を準備することになりました
ただ、Visual Studio 2010はライセンスの関係でそのPCで使用できず、Visual Studio 2017で開発環境を作成することに…
### 実行
無事環境をととのえ、Visual Studio 2017でビルドができるようになりました
さっそくビルドしたアプリケーションを実行したところ、なんと、レイアウトが崩れている！！！
### よくある話でしょと思ったが…
自分の環境でもあったのですが、Windows10に移行した際にレイアウトが崩れたりしたので
その時はDPIの設定などで解決したのですが、何をしてもうまくいかない…！！！
当然、Visual Studio 2010環境下でビルドしたアプリケーションをPCに持ってきて起動するとレイアウト崩れは起きない
…なぜ？
### 解決方法
レイアウト崩れがどこで起きているのか、よく見るとヘッダ部分の文字の位置やサイズが微妙にずれている
こんな感じの崩れはIEのバージョン違いであったなーと思い、
ためしに、 `[アプリケーション右クリック] > [プロパティ] > [互換モード] > [互換モードでこのプログラムを実行する] > [Windows Vista(Service Pack 1)] `
を選択してみると、レイアウト崩れが解決できた
恐らくはService Pack 1で開発されているからこれで解決するのでしょう（ちゃんと調べてない）

# これから
全体の開発環境が更新される時には、実装やビルドの設定などを見直さなければなりませんが、 
現状1人の環境でのみ起こる事象であるので、ソリューションなどの設定は極力変えたくありません
目先の解決方法としてはこれでよいかと思います
そもそもでいえば未だに2010環境で開発しているのがどうかしてる気がしますし、
一般的には2010 ⇒ 2017以降にすっ飛ばして移行することもないでしょうから

この記事はあくまで備忘録としてインターネット上に浮かべておきます
Amplify+Cloud9で詰まったところメモ

# この記事について

>【初心者向けワークショップ】Cloud9+React+Amplify+Cypressでアプリの公開からCI/CD+E2Eテスト自動化までやってみよう！
>https://qiita.com/oh_rusty_nail/items/90f19b14fe12b65f0ed8

上記のAmplify + Cloud9環境でreactアプリをつくってみるチュートリアルをやってみたので、詰まった点を共有します

# ボリュームの容量が足らない！

今回の作業メモリ容量が10Gほどだったため、途中で「容量が足りません」と怒られることがありました。

```
df -h
```
上記のコマンドで容量を確認してみると99%使用済みとなっており、やばそうです。


下記の記事を参照に、プロジェクトのEC2インスタンスに紐づけられたボリュームの容量を増やしてあげると改善されました。

>AWS Cloud9 で利用している EBS ボリューム領域を拡張する
>https://qiita.com/ktrkmk/items/8cf1e100da2e717f3be2


# Amplifyプロジェクト上限数を超えてしまった！

複数人で同じAWS環境でチュートリアルを実施したため、Amplifyのアプリ数が上限である25個を超えてしまいました。そのため、ホスティング時にエラーが発生する事態に・・・

**対策**

- アプリ名は個人が特定できるものを設定する
- 「amplify init」に失敗した際はコンソールのプロジェクトも削除しておく
- 個人AWSアカウントでチュートリアルを実施する

# Cypressのテストがうまくいかない
「チュートリアル通りに行っているのにCypressのテストが失敗してしまう」という状況にはまったのですが、テスト用jsファイルのアカウント名とパスワードの設定に原因がありました。

チュートリアルにおいてCypressは画面操作を再現するのみです。
そのため、テストを行う前に「npm start」のプレビュー画面からテスト用アカウントをあらかじめ作成しておく必要があります。

アカウントを作成したら、アカウント名とパスワードを下記のコードへ適宜挿入するとテストが成功するかと思います。

```js:cypress/integration/authenticator_spec.js

describe('Authenticator:', function() {
  beforeEach(function() {
    cy.visit('/');
  });

  describe('Sign In:', () => {
    it('allows a user to signin', () => {
      cy.get(selectors.usernameInput).type(
        'テスト用に作成したアカウント名'
      );
      cy.get(selectors.signInPasswordInput).type(
        'テスト用に作成したアカウントのパスワード'
      );
      cy.get(selectors.signInSignInButton)
        .contains('Sign In')
        .click();
      cy.get(selectors.root).contains('Global');
    });
  });
});
export const selectors = {
  usernameInput: '[data-test="username-input"]',
  signInPasswordInput: '[data-test="sign-in-password-input"]',
  signInSignInButton: '[data-test="sign-in-sign-in-button"]',
  root: '#root'
};
```

# 勉強用リンク集

フロント実装やAPI部分を詳しく知る際に使えそうなリンク一覧

**公式チュートリアル**
https://ja.reactjs.org/tutorial/tutorial.html

**Reactのチュートリアルをhooks + TypeScriptでモダンな仕様にリファクタしてみた**
https://dragon-taro.com/technology/modern-react-tutorial

**Material-UI**
https://material-ui.com/

**Web API初心者と学ぶGraphQL**
https://qiita.com/SiragumoHuin/items/cc58f456bc43a1be41b4

**Cypress**
https://qiita.com/sinpaout/items/4313ed75e603508696b1
Ubuntu20.04にPHP7.2をインストールしたい。

標準のリポジトリにあるのが7.4


1: APTの調査先を追加
`sudo add-apt-repository ppa:ondrej/php`

2: リポジトリ更新
`sudo apt update`

3: install PHP7.2
`sudo apt install php7.2`


以下を参考にしました。
https://askubuntu.com/questions/1230869/cant-install-php-7-2-on-ubuntu-20-04