OmniAICreator/Qiita-1.07M huggingface dataset:
【oracle備忘録】UNION ALL句にキーを持たせて、UNION ALL句を並び替え

※この備忘録は初学者の私が学習、もしくは業務で体験した内容を忘れないために書き起こしたものとなります。

#目的
画面1、画面2、画面3内の未完了明細の件数を画面4を見て把握できるようにするため、
「画面名称」「未完了件数」をまとめて抽出する用のSQL文を作成したい。
　※各画面の表示内容については、各画面下にデータ参照元を記載

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520051/e99e2f89-3ae1-5fe6-9e01-b78e82bb58cc.png)
※全てGAMEN1テーブルから参照
・[物件No.]…GAMEN1.BUKKEN_NO
・[案件名]…GAMEN1.ANKEN_NAME
・[予算]…GAMEN1.YOSAN
・[完了]…GAMEN1.KANRYO ※未完了の場合…"0", 完了の場合…"1"
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520051/ec0aade3-d3cc-f94b-971d-f15173046e17.png)
※全てGAMEN2テーブルから参照
・[物件No.]…GAMEN2.BUKKEN_NO
・[案件名]…GAMEN2.ANKEN_NAME
・[経費予算]…GAMEN2.KEIHI_YOSAN
・[完了]…GAMEN2.KANRYO ※未完了の場合…"0", 完了の場合…"1"
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520051/4c2c2d2f-c956-3ba2-4665-78b73054642a.png)
※全てGAMEN3テーブルから参照
・[物件No.]…GAMEN3.BUKKEN_NO
・[案件名]…GAMEN3.ANKEN_NAME
・[輸送費予算]…GAMEN3.YUSOUHI_YOSAN
・[完了]…GAMEN3.KANRYO ※未完了の場合…"0", 完了の場合…"1"
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520051/389ac1ec-2695-1509-80f8-bf04290e5be1.png)


##誤答
下記のソースで抽出したデータをそのままC#を用いて(例えばforeach等で)画面に表示させた場合、画面4に表示される画面名称の順番が、上から
「物件製作原価見積画面」⇒「経費見積画面」⇒「輸送費見積画面」
の順番にならない場合があった。(私の環境では、正しい順で表示されたが、別の方の環境では誤った順で表示されてしまった)

~~~C#
-- ■各画面の未完了件数,名称取得

WITH

-- 画面1(物件製作原価見積画面)の未完了件数
GAMEN1_MIKAN AS
(SELECT COUNT(KANRYO) AS MIKANRYO
  FROM GAMEN1
 WHERE GAMEN1.KANRYO = '0'),

-- 画面2(経費見積画面)の未完了件数
GAMEN2_MIKAN AS
(SELECT COUNT(KANRYO) AS MIKANRYO
   FROM GAMEN2
  WHERE GAMEN2.KANRYO = '0'),

-- 画面3(輸送費見積画面)の未完了件数
GAMEN3_MIKAN AS
(SELECT COUNT(KANRYO) AS MIKANRYO
   FROM GAMEN3
  WHERE GAMEN3.KANRYO = '0')

SELECT '物件製作原価見積画面'  AS GAMEN_NAME    --画面名称
      ,MIKANRYO              AS MIKANRYO_NUM  --未完了件数
  FROM GAMEN1_MIKAN

UNION ALL

SELECT '経費見積画面'
      ,MIKANRYO
  FROM GAMEN2_MIKAN

UNION ALL

SELECT '輸送費見積画面'
      ,MIKANRYO
  FROM GAMEN3_MIKAN
~~~

##原因
上記コード内で、WITH句以降のSELECT文で、ORDER BYで表示順を指定しなかったため。

##正しく表示されたコード
~~~C#
-- ■各画面の未完了件数,名称取得

WITH

-- 画面1(物件製作原価見積画面)の未完了件数
GAMEN1_MIKAN AS
(SELECT COUNT(KANRYO) AS MIKANRYO
  FROM GAMEN1
 WHERE GAMEN1.KANRYO = '0'),

-- 画面2(経費見積画面)の未完了件数
GAMEN2_MIKAN AS
(SELECT COUNT(KANRYO) AS MIKANRYO
   FROM GAMEN2
  WHERE GAMEN2.KANRYO = '0'),

-- 画面3(輸送費見積画面)の未完了件数
GAMEN3_MIKAN AS
(SELECT COUNT(KANRYO) AS MIKANRYO
   FROM GAMEN3
  WHERE GAMEN3.KANRYO = '0')

SELECT '物件製作原価見積画面'  AS GAMEN_NAME    --画面名称
      ,MIKANRYO              AS MIKANRYO_NUM  --未完了件数
      ,1                     AS KEY           --表示順を決める為のキーナンバー
  FROM GAMEN1_MIKAN

UNION ALL

SELECT '経費見積画面'
      ,MIKANRYO
      ,2                     AS KEY
  FROM GAMEN2_MIKAN

UNION ALL

SELECT '輸送費見積画面'
      ,MIKANRYO
      ,3                     AS KEY
  FROM GAMEN3_MIKAN

 OREDR BY KEY
~~~

##感想
今回、自分の環境ではORDER BYを用いなくても、たまたま上手く正しい表示順で出力できたため問題なかったが、UNION ALL句は必ずしも上の句から順に表示される訳ではないことが分かった。
表示順を指定したい場合は、必ずORDER BYを用いて、誰の環境で実装した場合でも正しい表示順で出力されるようにSQL文を作成したい。
VSCode + Docker + PHP の開発環境を、XDebugでデバッグする。

## はじめに

扱っていたプロジェクトは Laravel を使ったPHPアプリケーションで、VSCodeによって製作されていました。
Java や Swift を使った作業には慣れていたのですが、PHPのデバッグが久しぶりで大いにはまったので備忘録です。

## やったこと

PHPのデバッグには XDebug を使うということなので、[XDebug解説記事](https://qiita.com/castaneai/items/d5fdf577a348012ed8af) をふむふむと読み（大変わかりやすい記事です）作業に当たりました。

たくさんの記事が丁寧に説明しているので詳細は端折りますが

```php.ini
;...省略

[XDebug]
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20190902/xdebug.so
xdebug.default_enable=1
xdebug.remote_port=9000
xdebug.remote_autostart=1
xdebug.remote_handler=dbgp
xdebug.remote_connect_back=0
xdebug.remote_host=host.docker.internal
xdebug.remote_log=/tmp/xdebug.log
xdebug.idekey=VSCODE
```

```Dockerfile:Dockerfile
FROM php:7.4-apache

# XDebug
RUN pecl install xdebug \
  && docker-php-ext-enable xdebug

#...省略
```

```launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Listen for XDebug",
      "type": "php",
      "request": "launch",
      "port": 9000,
      "log": true,
      "pathMappings": {
        "/var/www/html": "${workspaceFolder}/src"
      },
      "ignore": [
          "**/vendor/**/*.php"
      ]
    }
  ]
}
```

こんな感じで、PHP初期化、Docker初期化、XCodeのデバッグ設定を終えました。

__これが全然びくとも動かない。__

## 解決策

いろんなパラメータをいじり倒しましたが全然動かず諦めかけましたが、最終的には xdebug のバージョンの問題ということに気づきました。

```bash
$ php -v | grep -i "xdebug"
    with Xdebug v3.0.2, Copyright (c) 2002-2021, by Derick Rethans
```

Xdebug 2.x から 3.x で、__設定値が様変わりしています。__
https://xdebug.org/docs/upgrade_guide
このドキュメントに詳しくわかりやすく書いてあります。

たとえば、`xdebug.remote_log` は `xdebug.log` に Rename されています。どうりで、ログもさっぱり出ないわけです。

細かい意味はそちらを見ていただくとして、上記の `php.ini` は正しくはこうなりました。

```php.ini
;...省略

[XDebug]
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20190902/xdebug.so
xdebug.mode=debug
xdebug.client_port=9000
xdebug.start_with_request=yes
xdebug.discover_client_host=0
xdebug.client_host=host.docker.internal
xdebug.log=/tmp/xdebug.log
```

現場からは以上です。
[基礎] サーバーとは

 

#サーバー
サーバーとは、クライアントに対してサービスを提供するコンピューターです。

webサーバーやDBサーバーなど、種類がたくさんありますが、
実態はどれも「ただのコンピューター」で、役割によって呼び方が違うだけです。

ここでいうクライアントとは、ユーザーのみを指しているのではなく、
「リクエストを送った側」をクライアントと呼んでいます。
例えばAPサーバーから見たクライアントは、
「動的コンテンツ送って！」と言っているwebサーバーです。

#Webサーバー
「Webサーバー」とは、静的コンテンツのみをリクエストとしてブラウザに返すサーバーです。
動的コンテンツはAPサーバーにリクエストを送ります。

「静的コンテンツ」とは、リクエストのたびに内容が変更されないファイルのことです。
例として、表示するものが定まっているCSSや、画像ファイルなどがあります。


最初に、クライアントからのリクエストすべてがWebサーバに送られます。

# APサーバー（アプリケーションサーバー）
「APサーバー」は、動的コンテンツを生成し、処理結果をWebサーバーに返すという役割のサーバーです。
具体的には、APサーバーが、APサーバ内に設置されているアプリケーション本体にリクエスト処理の指令を出します。
アプリケーション本体が処理を完了すると、APサーバーはその処理結果をレスポンスとしてWebサーバーに返します。


「動的コンテンツ」とは、リクエストのたびに内容が変更されるファイルのことです。
送られてくるリクエスト毎にデータベースから検索条件に該当するデータ取得し、
表示する役割を果たしています。


#DBサーバー（データベースサーバー）
DBサーバーとはアプリケーション上のデータを保存したり、
取り出してきてブラウザに表示したりするためのサーバーです。

APサーバーから送られてくるリクエストに従い、
その処理の結果をAPサーバーに返します。

APサーバーから送られてくるリクエストは、いわゆるCRUDの操作内容です。
sympyとDecimalは仲悪いみたい

`Decimal`オブジェクトを

```python
from sympy import *
from decimal import *

getcontext().prec = 100 # Decimalの精度100桁
弟子丸 = Decimal(1)/ Decimal(3) 
x = Symbol("x")

print("decimal:", 弟子丸)
print("sympy.nsolve:", nsolve(x-弟子丸,          x,         1, prec=100))
#                             =0       について解く  初期予測値  精度

```
これを`Python 3.8.3 (default, Jul  2 2020, 17:30:36) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32`な環境で実行した結果が次の通り

```:結果
decimal: 0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
sympy.nsolve: 0.3333333333333333148296162562473909929394721984863281250000000000000000000000000000000000000000000000
```

`decimal`オブジェクトを`sympy`に渡すと、精度が落とされてしまうようだ。
ちなみにこれは`nsolve`だけの問題ではなく、`evalf`を使っても同様。

```python
expr = x
print("sympy.evalf:", expr.evalf(100, subs={x:d}))
```

```:結果
sympy.evalf: 0.3333333333333333148296162562473909929394721984863281250000000000000000000000000000000000000000000000
```

次のように、未計算のオブジェクトを渡し、`sympy`に解かせれば、確かに`sympy`でもちゃんとした精度を得られる。

```
y = Symbol("y")

expr = x/y
print("sympy.evalf:", expr.evalf(100, subs={x:Decimal(1), y:Decimal(3)}))

```

```:結果
sympy.evalf: 0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
```
pycaretに任意の評価指標を追加するadd_metricメソッドの調査

# はじめに

pycaretで評価指標のloglossを使おうと思ったのですが、デフォルトではloglossが無かったので、追加する方法を調査しました。
以前まで、評価指標を追加することができなかったのですが、2020年10月のアップデート(version 2.2.0)で評価指標を任意に追加できるようになったようです。

# 環境とバージョン

- PyCaret 2.2.0
- Google Colaboratory

# pycaretとは

pycaretとは、機械学習の前処理からモデリングまで自動でしてくれる機械学習ライブラリです。

# デフォルトで使える評価指標

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993875/c99f0bc1-b500-e25d-0fdf-3b7ba56d7ce6.png)

# add_metricメソッドについて

add_metricメソッドを使用することで、scikit_learnで利用可能な任意の評価指標や、make_scorer関数を使用した独自の評価指標を扱うことができるようになります。

```python
from pycaret.classification import add_metric
from sklearn.metrics import log_loss

add_metric('logloss', 'Log Loss', log_loss, greater_is_better = False)
```

add_metric()の引数の説明です。

- id: 1つ目の引数
    - str型
    - 評価指標のID
- name: 2つ目の引数
    - str型
    - 評価指標を表示する際の名称
- score_func: 3つ目の引数
    - type型
    - 追加したい評価指標
        - 今回の場合は、sklearnから引っ張ってきたlog_lossを入れています
- greater_is_better: 4つ目の引数
    - bool型
    - デフォルト=True
    - score_funcが数値が高いほうが良い指標なのか、低いほうが良い指標なのかを表します。
        - Trueでは高いほうが、Falseでは低いほうが良いということになります。

では、再度評価指標を確認してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993875/dfe6713d-c312-e46a-addc-937c87f8beb9.png)


無事にloglossを追加することできました。

# 参考サイト
https://pycaret.readthedocs.io/en/latest/api/clustering.html
新型コロナウイルス感染症に関する相模原市発表資料（発生状況等）のPDFをCSVに変換

```python
import datetime
import pathlib
import re
from urllib.parse import urljoin

import pandas as pd
import pdfplumber
import requests
from bs4 import BeautifulSoup


def fetch_file(url, dir="."):

    r = requests.get(url)
    r.raise_for_status()

    p = pathlib.Path(dir, pathlib.PurePath(url).name)
    p.parent.mkdir(parents=True, exist_ok=True)

    with p.open(mode="wb") as fw:
        fw.write(r.content)
    return p


url = "https://www.city.sagamihara.kanagawa.jp/shisei/koho/1019191.html"

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
}

r = requests.get(url, headers=headers)
r.raise_for_status()

soup = BeautifulSoup(r.content, "html.parser")

tag = soup.find(
    "a", href=re.compile(".pdf$"), onclick=re.compile("新型コロナウイルス感染症による新たな患者の確認")
)

link = urljoin(url, tag.get("href"))

path_pdf = fetch_file(link)

with pdfplumber.open(path_pdf) as pdf:

    dfs = []

    for page in pdf.pages:

        if page.page_number == 1:

            # cropでテキスト取得
            crop = page.within_bbox((400, 44, page.width, 60))
            update = crop.extract_text()

        for table in page.extract_tables():

            df_tmp = pd.DataFrame(table)

            row, col = df_tmp.shape

            # 列が11

            if col == 11:

                # 表の一番先頭に未満が含まれない

                if "未満" not in table[0][0]:

                    dfs.append(df_tmp)

df = (
    pd.concat(dfs)
    .iloc[1:]
    .set_axis(
        ["症例No.", "年代", "性別", "職業等", "場所", "居住地", "症状", "発症日", "陽性判明日", "感染経路等", "備考"],
        axis=1,
    )
)

df

# 前後の空白文字、正規化
for col in df.select_dtypes(include=object).columns:
    df[col] = df[col].str.replace("\s", "").str.normalize("NFKC")

dt_now = datetime.datetime.now()


def str2date(s: pd.Series) -> pd.Series:

    df = (
        s.str.extract("(\d{1,2})月(\d{1,2})日")
        .rename(columns={0: "month", 1: "day"})
        .fillna(0)
        .astype(int)
    )

    df["year"] = dt_now.year

    tmp = pd.to_datetime(df, errors="coerce")

    df["year"] = df["year"].mask(tmp > dt_now, df["year"] - 1)

    return pd.to_datetime(df, errors="coerce")


df["発症日YMD"] = str2date(df["発症日"])

df["陽性判明日YMD"] = str2date(df["陽性判明日"])

y, m, d = map(int, re.findall("\d+", update))

dt_update = datetime.datetime(2018 + y, m, d)


df.to_csv(f'sagamihara{dt_update.strftime("%Y%m%d")}.csv', encoding="utf_8_sig")
```
備忘録：Anaconda起動してPythonの仮想環境入ってMongoDBにローカル接続


※備忘録

#開発中アプリに移動

``terminal``にて``cd``とかでディレクトリ内に入る。


#``Anaconda``を起動

↓``base``（現在の場所）から、仮想環境（私の場合は作成した名前が``py3_aaaa``）へ移動する為、下記を入力

```terminal:
$ (base) lancai@oja % source activate py3_aaaa #py3_aaa：作成した仮想環境名
```

↓今回の開発環境が``API``なので
``uvicorn prog:app --reload --host 0.0.0.0 --port 8100``の
``prog``を``api``に置き換えたもの(下記)を入力

```terminal:
$ (base) lancai@oja %　uvicorn api:app --reload --host 0.0.0.0 --port 8000
```

これで接続完了となる！



#MongoDBにローカル接続できない時に確認すること

開発中のアプリディレクトリ``..>src>db>connect.py``内に、
設定した``username``と``password``が記述されているか確認。なければ追記する。

```python:python
from pymongo import MongoClient

# DB接続
def get_connect():
    # mongoDBローカル接続
    client = MongoClient("mongodb://（※ここにusername）:（ここにpassword）@localhost:27017/")
    # 使用DB （DBを指定）
    db = client.（※ここにDB名が入る）
    return db
```



##terminalにて下記コマンド入力

```:terminal:terminal:
$ uvicorn api:app --reload --host 0.0.0.0 --port 8000
```

#【補足】MongoDBに設定したusernameなどの情報を確認する方法


①terminalにて開発中アプリの``docker-composer.yml``ファイルが置いてある場所へ移動



②↓terminalにてcat”で参照する。

```:terminal
$ cat docker-compose.yml
```

③↓``environment:``部分に記載してある^^

```:terminal
    environment:
      MONGODB_USERNAME: ＊＊＊＊＊
      MONGODB_PASSWORD: ＊＊＊＊＊
      MONGODB_HOSTNAME: ＊＊＊＊＊db
      # VIRTUAL_HOST: ""
      # LETSENCRYPT_HOST: ""
      # LETSENCRYPT_EMAIL: "＊＊＊＊＊＊＊＊＊@gmail.com"

```
A - Large Digits AtCoder　考察



■問題
◉ ABC187 A - Large Digits
https://atcoder.jp/contests/abc187/tasks/abc187_a

■方針
この問題の一番のポイントは、入力数値の桁取得が実装できるかどうか。
考え方はビットシフトとほとんど同じで、取得桁への移動方法を考える。

■手法
1.取得する桁の位置決めは、切り捨て除算で行う。
2.位置決めされた値を取り出すのは、剰余算で行う。

--------------------------------------------------------

以下の流れが思いつけば、とりあえずOK。

input 123

1の位の取得
123　%　10　=　3
123　/　10　=　12　・・・　次のループに渡す値:12

10の位の取得
12　%　10　=　2
12　/　10　=　1　　・・・　次のループに渡す値：1

100の位の取得
1　%　10　=　1 
1　/　10　=　0　　・・・　次のループに渡す値：0　ループ終了
PC Maticにブロックされるソフトを【1分で】ホワイトリストに追加して起動できるようにする。

# リスク
[PC Matic公式](https://pcmatic.jp/faq/supershield/06/)は今回しようとしている事にリスクがある事を**警告**しています。
この記事を参考にホワイトリストに追加した事による責任は負いませんのでご自身で判断してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635641/796fefc2-c3b9-d3df-4bd8-3345d74e3d95.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635641/fd2d8f8f-5d57-1f30-6fc9-71a48e657c6a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635641/bcd1924e-be4b-3f17-1a2a-f0b6b516227d.png)

# やり方
###タスクバーのPC Maticアイコンを右クリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635641/15f59250-c82a-59eb-1427-db8393688ced.png)

### 保護レベルをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635641/99cec543-71ac-1f0c-ef48-3259d2f69f28.png)

### 保護警告表示をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635641/911e8385-7027-5fc2-5f19-3d904498508e.png)

### 防御・許可表示 をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635641/38d88d6e-4de2-efc4-3448-71392c703564.png)

### PC Maticにブロックされるソフトを起動

### 理解した上で **常時許可** をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635641/eebb29de-ff05-6531-adfb-5c29d988e87e.png)

### 最後に保護警告表示に戻しておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635641/1c7a9091-8093-5d0e-4fff-853a629a0c70.png)

これで完了です。
GitLabにSSH接続するための手順

GitLabにSSH接続するための備忘録です。
ターミナルからSSHキー(公開鍵・秘密鍵)を発行しGitLabへ公開鍵を登録します。

# 動作環境
macOS 10.14.6
Terminal

#GitLabへのアカウント登録
[GitLabの公式](https://gitlab.com/users/sign_up)からアカウント登録を行ってください。

オンプレ環境でGitLabを立ち上げたい場合は、こちらの記事が参考になります。
[オンプレ版 GitLab で GitLab Pages する](https://qiita.com/hykisk/items/ebff2f7cd2e8100a6bbe)

#手順
ターミナルを起動し以下のコマンドからSSHキー(公開鍵・秘密鍵)を発行します。
途中のパスフレーズは必要なければ、そのままEnterしても良いと思います。（毎度入力するのが面倒なので）

```
mypc:~ mypc$ ssh-keygen

Generating public/private rsa key pair.
Enter file in which to save the key (/Users/mypc/.ssh/id_rsa):
Created directory '/Users/mypc/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/mypc/.ssh/id_rsa.
Your public key has been saved in /Users/mypc/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:Tyome4559090HogeMogegegegehg;ahgajh;nfjefej
The key's randomart image is:
+---[RSA 2048]----+
|    tyome        |
|                 |
+----[SHA256]-----+

```

発行した公開鍵(id_rsa.pub)と秘密鍵(id_rsa)を確認

```
mypc:~ mypc$ ls ~/.ssh

id_rsa		id_rsa.pub
```

公開鍵の内容をクリップボードにコピーする

```
mypc:~ mypc$ pbcopy > ~/.ssh/id_rsa.pub
```

GitLabにコピーした公開鍵を貼り付けし、そのままAdd Keyをクリック
![スクリーンショット 2021-01-11 22.18.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165793/1c7f4ae1-bbb5-b1de-36cc-a463fb0c5ced.png)


完了です。

# 最後に
ここからSSH経由でGitの操作ができると思います。
[My SQL] macOSでログイン、ログアウトする方法

#環境
MySQLがインストールされたPC
MySQLのバージョンは `5.7`

#MySQLにログインする方法
##MySQLを起動する
ターミナルで以下を実行します。

```
$ brew services start mysql@5.7
```

起動に成功すると以下のようになります。
すでに起動していた場合は再起動（restart）されます。

```
Successfully started `mysql@5.7` (label: homebrew.mxcl.mysql@5.7)
```

##ログインする
ターミナルで以下を実行し、rootユーザーとしてログインします。

```
$ mysql --user=root --password
```

コマンド実行後 `Enter password:` と表示されるので設定したパスワードを入力します。
ログインに成功すると `mysql> ` と表示されます。

#ログアウトとMySQLの停止をする
ターミナルで以下を実行し、ログアウトします。

```
$ exit;
```

`Bye` と表示されたらログアウト成功です。
次にターミナルで以下を実行し、MySQLを停止します。

```
$ brew services stop mysql@5.7
```

 `Successfully stopped msyql@5.7` と表示されたらMySQLの停止は成功です。
レポート[応用数学]

#応用数学
##線形代数
ここでは，以下の概要を理解する．
1) 固有値・固有ベクトルの求め方 
2) 固有値分解の方法
3) 特異値・特異ベクトルの求め方
4) 特異値分解の方法

正方行列$A$について
$$A\boldsymbol{x}=\lambda\boldsymbol{x}$$
を満たす$\lambda$を固有値そのときのベクトル$\boldsymbol{x}$を固有ベクトルという．
　正方行列$A$は以下のように固有値$\lambda$および固有ベクトル$\boldsymbol{x}$を用いて表現することができる．
$$A=V\Lambda V^{-1}$$
このとき，

```math
\Lambda=
\begin{pmatrix}
\lambda_1 &  &\\
 &  \lambda_2 &\\
& & ...
\end{pmatrix}
```

```math
V=
\begin{pmatrix}
\boldsymbol{v_1} & \boldsymbol{v_2} & ... \\
\end{pmatrix}
```
また，正方行列以外の行列についても固有値分解の代わりとして特異値分解をすることができる．これらの分解手法は例えば画像データの行列から成分の小さい部分を取り除くことでデータ縮小化ができる．

##確率・統計
ここでは，以下の概要を理解する．
1) 条件付き確率
2) ベイズ則
3) 期待値・分散の求め方
4) 様々な確率分布

ある事象を前提として別の事象が起こる確率を条件付き確率と呼ぶ．事象Bを前提として事象Aが起こるときの条件付き確率は次式で表される．
$$P(A|B)=\frac{P(A\cap B)}{P(B)}=\frac{n(A\cap B)}{n(B)} $$
また，上式より，条件付きのほうが条件なしに比べて確率が高くなることが分かる．
また，事象Aの条件で事象Bが起こる条件付き確率も同様の考えで表せられるので次式が得られる．
$$P(A\cap B)=P(B)P(A|B)=P(A)P(B|A)$$
したがって次式が成立する．次式はベイズ則と呼ばれる．
$$P(A)P(B|A)=P(B)P(A|B)$$
ある事象$X$による確率変数$f(X)$を得る確率を$P(X)$とするとその期待値は次式で表される．
$$\mathrm E[X]=\sum_{k=1}^{n}=P(X=x_k)f(X=x_k)$$
期待値に対する各確率変数のばらつきの総和を分散と呼び次式で表される．
$$V[X]=E[X^2]-E[X]^2$$

確率分布は例えば下記のようなものがある．
・ベルヌーイ分布
「成功か失敗か」「表か裏か」「勝ちか負けか」のように２種類のみの結果しか得られないような実験、試行（ベルヌーイ試行）の結果を0と1で表す．
・マルチヌーイ分布
それぞれ独立した確率 を持つ事象 が存在し、1回の独立した試行でそのいずれか一つが観測される．
・二項分布
結果が成功か失敗のいずれかである試行（ベルヌーイ試行と呼ばれる）を独立に n 回行う．
・正規分布
データが平均値の付近に集積する．

##情報理論
ここでは，以下の概要を理解する．
1) 自己情報量・シャノンエントロピーの定義
ある情報$W$の変化$\Delta T$の感度は比率に依存すると仮定すると，情報変化は$\Delta W/W$と表現できる，全体の情報変化はこれを積分する．これを自己情報量と呼び，以下となる．
$$I(x)=\int \frac{1}{W}dW=\log W(x)$$
2) KLダイバージェンス・交差エントロピー
KLダイバージェンスは同じ確率事象・確率変数における異なる確率分布の違いを表す．$Q$を予定の確率分布，$P$を実績の確率分布とすると，KLダイバージェンスは次式で表される．
$$D_{KL}(P||Q)=\mathrm E_{x\sim P} \Big[\log \frac{P(x)}{Q(x)}\Big]=\sum_{x} \Big\\{P(x)\log \frac{P(x)}{Q(x)}\Big\\}$$
交差エントロピーはQについての自己情報量をPの分布で平均したものである．KLダイバージェンスの上式から，
$$D_{KL}(P||Q)=\sum_{x} \Big\\{P(x)(-\log Q-(-\log P))\Big\\}$$
である．ここで，交差エントロピーは
$$H(P,Q)=-\mathrm E_{x\sim P}\log Q(x)$$
である．これより，交差エントロピーは次式で表される．
$$H(P,Q)=H(P)+D_{KL}(P||Q)$$
Visual Studio Code のターミナルでGit Bashで使っているコマンドを使う方法

WindowsのVSCodeでターミナルを開いたときに、Git Bashのコマンドを使えるように設定した時のメモ。

#事前準備
この設定はGitBASHを使用する前提なので、下記サイトよりインストールしておく。
https://gitforwindows.org/

#設定
VSCodeのsettings.jsonに下記を追加する
（settins.jsonの開き方は[こちら](https://qiita.com/y-w/items/614843b259c04bb91495)を参照）

```settings.json
  "terminal.integrated.shell.windows": "C:\\Program Files\\Git\\git-cmd.exe",
  "terminal.integrated.shellArgs.windows": [
    "--command=usr/bin/bash.exe",
    "-l",
    "-i"
  ]
```
こうすると、ターミナルはGitBashで使っているコマンドを参照するよ。となる。

#参考
https://code.visualstudio.com/docs/editor/integrated-terminal#_windows
アドベントカレンダー35日目：SREを読んでみた「効果的なトラブルシューティング」編③

前回に引き続き実践編です。

## 実践
### 検証
システムが正しく動作しているかを理解するためには、そのシステム中の各コンポーネントの動作を検証できる必要があります。
理想は、モニタリングシステムがシステムのメトリクスを記録していることです。
また、ロギングを行うことによって、任意のタイミングでのプロセスの動作を知ることができます。

Googleにおいては、その時のシステムの状況を公開することができます。
Googleサーバー群は直近に送受信されたRPCの一部を返すエンドポイントがあり、サーバーが周りと通信する様子を見ることができます。

また、コンポーネントがリクエストに何を返すのかを知るために、実験用のクライアントを用意する必要があるかもしれません。

### 診断
診断の方法には、さまざまな方法がありますが、それについてみていきます。

#### 単純化と削減
* ブラックボックステスト
既知のテストデータを与え、返ってくる結果が期待通りかを検証する。
再現性のあるテストによって、原因の特定をしっかり行うことができる。

* 分割統治法
原因の可能性があるコンポーネントを順番に調べていき、患部を特定する。

#### 「何が」「どこで」「なぜ」と尋ねる
* **何か**が動作し続けようとしているのか、**何を**しているのか。
* **なぜ**そのような動作になっているのか。
* **どこで**リソースが消費されているのか。出力は**どこへ**向かっているのか。

#### 最後の修正
動作しているコンピュータシステムには、外部からの作用が働くまでは動作し続けようとする傾向がある。そのため、システムに生じた直近の変化は、問題を特定する上で効率的な出発点になります。
プロダクションログからシステムの振る舞いの変化をみることは、モニタリングダッシュボードの構築に役立ちます。

## まとめ
* 検証の理想は、モニタリングシステムでメトリクスを読み取ること。
* 種々の検証方法を用いて、検証する。

#### 参考文献
1. Betsy Seyerほか　SRE サイトリライアビリティエンジニアリング　オライリー　143-148
[備忘録]pythonでQRコードと説明を同じ画像に書く方法

# 出来上がるもの

![qr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120339/55f70e82-b60e-85b6-fb2f-e6f600d0264c.png)

# 準備
colab上で動作させるために必要なものをインストールします。

必要なライブラリのインストール

```sh

pip install qrcode pillow
```

用意したサンプルで日本語の文字列を画像に書き込むためフォントをインストール

```sh

!apt-get -y install fonts-ipafont-gothic
```

# スクリプト実部

```python

import qrcode
import PIL.Image
import PIL.ImageDraw
import PIL.ImageFont

imgpath  = "qr.png" # 画像の保存場所とファイル名
text     = "もどる" # QRコードに組み込みたい情報
# 今回は日本語の表記を追加したいので日本語フォントを用意
fontname = "/usr/share/fonts/opentype/ipafont-gothic/ipag.ttf"
# 表記する文字のサイズ
fontsize = 36

# 表記する文字サイズを取得する関数
def getTextSize(_text="test", _fontname="", _fontsize=36):
  canvasSize    = (1, 1)
  backgroundRGB = (255, 255, 255)
  img  = PIL.Image.new("RGB", canvasSize, backgroundRGB)
  draw = PIL.ImageDraw.Draw(img)
  font = PIL.ImageFont.truetype(_fontname, _fontsize)
  textWidth, textHeight = draw.textsize(_text, font=font)
  return textWidth, textHeight

# QRコードを作成し、文字表記を下部中央に追記する
def makeQRimg(_imgpath, _text, _fontname="", _fontsize=36):
  # 誤り訂正レベルを最大に、余白は仕様上の最小幅
  qr = qrcode.QRCode(
      error_correction=qrcode.constants.ERROR_CORRECT_H,
      border=4,
  )
  qr.add_data(_text)
  qr.make()
  img = qr.make_image().convert("RGB")

  textSize    = getTextSize(_text, _fontname, _fontsize)
  textTopLeft = (img.size[0]/2 - textSize[0]/2, img.size[1] - textSize[1])
  draw = PIL.ImageDraw.Draw(img)
  font = PIL.ImageFont.truetype(_fontname, _fontsize)
  draw.text(xy=textTopLeft, text=_text, fill=(0, 0, 0), font=font)

  # QRコードを保存
  img.save(_imgpath)

# 実行
makeQRimg(imgpath, text, fontname, fontsize)
# 作成したQRコードをIPython上で表示
from IPython.display import Image, display_png
display_png(Image(imgpath))
```
RailsにてデプロイしたところPayjp::InvalidRequestErrorが発生する

#はじめに
Railsでポートフォリオ作成し、AWSにてデプロイしたところPayjpを使ったクレジット登録が完了できず
エラーとなりました。

![スクリーンショット 2021-01-11 21.41.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018660/6fd3111c-d45f-9c8c-e4d4-4139e17d7105.png)

#環境
・Rails 6.0.0
・Ruby 2.6.5
・Unicorn 5.4.1

#状況
Payjpでのクレジットカード登録で、決済ページから決済処理に入るタイミングでエラーが出ました。
tail -f log/production.logでログを確認すると

![スクリーンショット 2021-01-11 21.50.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018660/80ceec6a-4d34-d45c-5dea-fa8980e1e716.png)

Payjp::InvalidRequestError (No such token: tok_acd40b5df50c7656e3bed4444890):
というエラーがありました。


#問題解決のために行ったこと
エラー文の通り、Payjpの設定に問題があるのかと推測。
ローカルでは問題なく動いていたので
環境変数の問題かと思いevnにPAYJP_SECRET_KEYを設定し直したりしましたが
変化ありませんでした。

ローカルのコード記述を変えてみたり散々いじりましたが
そもそもローカルでは正常に動いているのでもっと根本的な問題では？と方針変更

ターミナルを再起動→変化なし
Unicon、Nginxを再起動→変化なし

#自分がやった解決手順
上記の流れでアセットコンパイルも再起動することにしました。

・rake assets:clobberでまずアセットパイプラインをクリーンにする
→このとき Please run `yarn install --check-files` to update.が出たので
　yarn install --check-files
・bundle exec rake assets:precompile RAILS_ENV=productionでアセットパイプラインのプリコンパイルを実行
・Unicon、Nginxを再起動

無事に立ち上がりました！！

# さいごに
まさかのPayjpは無関係という結果でした。
ネットで同じような事例がなく、かなり遠回りをしたので
同じような状況で苦しんでいる人の助けになればと思い投稿しました。
Reactのスタイリング(classNameやclassNamesの使い方)

こんにちは、フロントエンドエンジニアの[てりー](https://twitter.com/teriteri_code)です。
僕の詳しいプロフィールは[こちら](https://terrblog.com/about/)

また、未経験から独学でフロントエンドエンジニアになる勉強方法をまとめたので、興味があれば是非！

https://terrblog.com/how-to-get-front-end-job/



# 修正
221/1/12 12:30頃にclassnamesの記述とコードブロックの修正を加えました。それ以前は誤った記述になっていたので、現状を参考にしてください。
![スクリーンショット 2021-03-16 12.10.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397606/b1b4ffff-9d8b-5b43-289b-ada037699690.png)


# classNameとは
htmlではclassを使ってスタイリングをしますが、Reactが使っているjsxではclassNameを使ったスタイリングを行います。

#classNameの使い方
classNameの使い方は簡単で、classと全く同じです。

```react

export default function App() {
  return (
      <div className={App}>
        <h1>Hello CodeSandbox</h1>
      </div>
  );
}
```
今回はAppを入れましたが、変数などを入れることも可能です。

# classNames
動的なクラスの使い分けをする場合や複数のクラス名をつける場合はclassNamesというnpmパッケージを使うと便利です。
https://www.npmjs.com/package/classnames#usage-with-reactjs
##基本的な使い方

今回はfoobarClassNamesで定義しています。**オブジェクトの値がfalseだとそのkeyとなるclass名は付与されません**。
よって今回はfooのみがクラス名として与えられています。

```react

import React from "react";
import classNames from "classnames";

export default function App() {
  const foobarClassNames = { foo: true, bar: false };

  return (
    <div className={classNames(foobarClassNames)}>
      <h1>Hello CodeSandbox</h1>
    </div>
  )
}
```

## 複数のクラス名を使う
classNamesを使うことで複数のクラス名を手軽に使えます。

```react

import React, { useState } from "react";
import classnames from "classnames";

export default function App() {

  return (
    <>
      <div className={classnames("login", "isActive")}>
        <h1>Hello CodeSandbox</h1>
      </div>
    </>
  );
}

```
loginとisActiveが付与されています。

## 動的にクラス名を切り替える。
下記の画像ではuseStateによって定義されたstatus（progressかcreared）によってstatusClassNamesの値が切り替わる例です。
常にpazzleクラスは持っています。

```react
import React, { useState } from "react";
import classnames from "classnames";

export default function App() {
  const [status, setStatus] = useState("progress");
  const statusClassNames = {
    pazzle: true,
    progress: status === "progress",
    creared: status === "creared"
  };

  return (
    <>
      <div className={classnames(statusClassNames)}>
        <h1>Hello CodeSandbox</h1>
      </div>
    </>
  );
}


```

classNamesを使うことで、Reactにおける様々なスタイリングを行うことが出来ます。

#### もし現状の仕事に不満があるなら

転職ドラフトに登録して見てはいかがでしょうか？

実際に企業からのオファーを受ける事で、企業から見た自分の強みや市場価値などポジティブな発見がたくさんあります！！

https://terrblog.com/job-draft-merit/


# 参考
・React公式ドキュメント(CSS とスタイルの使用)
https://ja.reactjs.org/docs/faq-styling.html

・classnamesパッケージドキュメント
https://www.npmjs.com/package/classnames
Laravelでのnginxのdefault.conf

#default.confの内容
公式ページからコピーするだけ.
 [laravel公式ページ](https://readouble.com/laravel/7.x/ja/deployment.html)

```default.conf
server{
    listen 80;
    server_name example.com;
    root /srv/example.com/public;

    fastcgi_pass unix:/var/run/php/php-fpm.sock;
}
```
コピーしたら上の場所を適当に変えるだけで基本動く。

#ちなみに
dockerにおいて、nginxコンテナにapt, apt-getは実行できない。
そのため```apk update```などを使う。
[Ruby] メソッド備忘録

## はじめに
備忘録としてメソッドを書き留める

## getsメソッド
ユーザーがキーボードで入力した値を`文字列`として取得する
`末尾に必ず改行が入る`

```
標準入力
abcd

input = gets
p input

出力結果
"abcd\n"  
```

## chompメソッド
`末尾の改行文字を取り除き`、新しい文字列を返す

```
標準入力
abcd

input = gets.chomp
p input

出力結果
"abcd" 
```

## splitメソッド
文字列を分割して`文字列の配列`にする

```
標準入力
hello new world

array = gets.split(" ")
p array

出力結果
["hello", "new", "world"]
```

## readlinesメソッド
ユーザーがキーボードで入力した`複数行の値を文字列の配列`として取得する

```
標準入力
hello
new
world

array = readlines.chomp
p array

出力結果
["hello", "new", "world"]
```

##mapメソッド
配列の要素の数だけ繰り返し処理を行う

```
array = ["1", "2", "3"]
new_array = array.map{ |v| v.to_i }
p new_array

出力結果
[1, 2, 3]
```

## joinメソッド
配列の各要素を文字列に変換し、引数を区切り文字として結合する

```
array = ["hello", "new", "world"]
p array.join(" ")

出力結果
"hello new world"
```

## pushメソッド
配列の末尾に引数を要素として追加する

```
array = ["a", "b", "c"]
p array.push("d")

出力結果
["a", "b", "c", "d"]
```
HomebrewでVirtual box / Vagrantをインストールするときに困ったこと

N予備校 【2020年度】プログラミング入門 Webアプリ
[第2章2節 LinuxというOS]

仮想環境準備の手順で詰まったので解決した手順を記載。

解説にしたがって Homebrew をインストール後、
Virtual boxとVagrantをインストールするコマンド

```
brew cask install https://raw.githubusercontent.com/Homebrew/homebrew-cask/ed3d9de/Casks/virtualbox.rb
```

を実行するとエラーになります。

```
Error: Calling brew cask install is disabled! Use brew install [--cask] instead.
```

brewのバージョンが上がって cask は --caskオプションを使わないと動かないらしい。
オプションを追加してinstallコマンドで実行してみる。

```
brew install --cask https://raw.githubusercontent.com/Homebrew/homebrew-cask/ed3d9de/Casks/virtualbox.rb
```

またエラーになる。

```
'brew extract' or 'brew create' and 'brew tap-new' to create a formula file in a tap on GitHub instead.: Invalid usage: Non-checksummed download of virtualbox formula file from an arbitrary URL is unsupported!  (UsageError)
```

arbitrary URL .. URL形式は指定できない？のでこけている様子でした。
エラーメッセージでぐぐってみたところ、下記の記事の方法で、いったんwgetでファイルをローカルに落として
brew installすると上手くいきました。

参考にした記事
https://dev.to/gjrdiesel/getting-around-brew-s-error-calling-non-checksummed-download-of-17fl

wgetが必要だったのでダウンロードする。

```
brew install wget
```

直接ファイルをローカルにダウンロードする。

```
cd /home/Downloads/
wget https://raw.githubusercontent.com/Homebrew/homebrew-cask/ed3d9de/Casks/virtualbox.rb
```

ファイルがダウンロードできたら、それを使ってインストール。

```
brew install --cask virtualbox.rb
```

同じ手順で、Vagrantもインストール。

```
wget https://raw.githubusercontent.com/Homebrew/homebrew-cask/eb82c581/Casks/vagrant.rb
brew install --cask vagrant.rb
```
これでUbuntsをインストールする準備ができました。
もし２章の最初で詰まってる方がいましたらご参考まで。
Poetry での AssertionError は pyproject.toml を変更すると直る可能性がある

https://github.com/python-poetry/poetry/issues/1051 に書いてある。

`pyproject.toml` の `[tool.poetry]` にある `name` フィールドと同名のモジュールをインストールすることはできない。 Poetry がもともとモジュール開発を意識して作られたことから、納得できる。

```diff
  [tool.poetry]
+ name = "mypulp"
- name = "pulp"
  version = "0.1.0"
  description = ""
  authors = ["Your Name <you@example.com>"]
```

私の場合は `PuLP` モジュールを試すときに `pulp` というディレクトリで `poetry init` を実行した。初期値を使ったため pyproject.toml の中のモジュール名が `pulp` になっていたため `poetry` 経由で `pulp` のインストールができなかった。

ちなみに、 `pip` であれば問題なくインストールできる。
備忘録：【Docker】起動＆終了方法


備忘録φ(..)メモメモ

#【起動方法】

##アプリ起動

![スクリーンショット 2021-01-11 21.20.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584233/6ce31ca7-beb9-19c8-9b91-a1cead49ad9f.png)


##Dockerの置いてる場所で下記を入力

※私の場合”dev”というディレクトリ内に入って入力

```:terminal
lancai@oja dev % docker-compose up -d
```


↓下記のように返ってきたらOK

```:terminal
Creating network "proxy-net" with driver "bridge"
Creating rootp-db ... done
```

↓RUNNINGとなっていたらOK

![スクリーンショット 2021-01-11 21.24.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584233/af270082-de4b-53ef-4f1c-3e47009f2224.png)


#終了方法

##Dockerの置いてる場所で下記を入力

※私の場合”dev”というディレクトリ内に入って入力


```:terminal
$ lancai@oja dev % docker-compose down
```

↓下記のように返ってきたらOK

```:terminal
Stopping ※DBの名前 ... done
Removing ※DBの名前 ... done
Removing network proxy-net
```
AndroidのHiltをkotlinで実装する

Hilt は Android 用の依存関係インジェクション ライブラリです。これを使うことで、プロジェクトで依存関係の注入（DI）を手動で行うためのボイラープレートが減ります。Daggerが非常にわかりやすくなっていたので、これからHiltを使ってみましょう。

###ライブラリの導入###
####まず、hilt-android-gradle-plugin プラグインをプロジェクトのルート build.gradle ファイルに追加します。

```
buildscript {
    ...
    dependencies {
        ...
        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'
    }
}
```
####次に、Gradle プラグインを適用し、app/build.gradle ファイルに次の依存関係を追加します。

```
...
apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'

android {
    ...
}

dependencies {
    implementation "com.google.dagger:hilt-android:2.28-alpha"
    kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
}
```
####Hilt は Java 8 の機能を使用しています。プロジェクトで Java 8 を有効にするには、app/build.gradle ファイルに次の内容を追加します。
kotlinのプロジェクトの場合はkotlinOptionsの配置を追加する必要です

```
android {
  ...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    // For Kotlin projects
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

```
###Hiltの一般的なインジェクションの意味 ###
 
#### @HiltAndroidApp  
 1. Hilt を使用するアプリには、@HiltAndroidApp アノテーションが付けられた Application クラスが含まれている必要があります。
 2. @HiltAndroidApp は、Hilt のコード生成をトリガーします。これには、アプリケーション レベルの依存関係コンテナとして機能するアプリケーションの基本クラスも含まれます。
 3. ここで生成された Hilt コンポーネントは、Application オブジェクトのライフサイクルにアタッチされ、依存関係を提供します。また、アプリの親コンポーネントであることから、他のコンポーネントがこのコンポーネントの提供する依存関係にアクセスできます。
 4. Hilt はApplication、Activity、Fragment、View、Service、BroadcastReceiverの Android クラスをサポートしています  
 
 ```
@HiltAndroidApp
class App : Application() {
}
```

####@AndroidEntryPoint    
  1. Activity：FragmentActivity、AppCompatActivityなどのComponentActivity を拡張するアクティビティのみをサポートします
  2. Fragment：androidx.Fragment を拡張するフラグメントのみをサポートします。
  3. View
  4. Service
  5. BroadcastReceiver
  6. Androidクラスに@AndroidEntryPointの注釈が付けられている場合は、依存するAndroidクラスに同じ注釈を追加する必要があります  
  
```
@AndroidEntryPoint
class MainActivity:AppCompatActivity()
```
####@Inject
* クラスのコンストラクタで @Inject アノテーションを使用して、そのクラスのインスタンス提供方法を Hilt に知らせます。コンストラクター、非プライベートフィールド、メソッドでよく使用されます  

```
class AnalyticsAdapter @Inject constructor(
  private val service: AnalyticsService
) { 
     @Inject
     lateinit var user:User
 }
```
#### @Module  
@Moduleでアノテーションが付けられたクラスの場合、@ InstallInを使用してモジュールのスコープを指定する必要があります。多くの場合、依存クラスのオブジェクト（サードパーティライブラリOkHttp、Retrofitなど）を作成するために使用されます。

```
@Module
@InstallIn(ApplicationComponent::class)
// ApplicationComponentが使用されるため、NetworkModuleはApplicationのライフサイクルにバインドされます。
object NetworkModule {
}

```
#### @Provides 
クラスの内部メソッドを@Moduleアノテーションでマークし、依存関係オブジェクトを提供するためによく使用されます。

```
@Module
@InstallIn(ApplicationComponent::class)
object NetworkModule {

    /**
     * @Provides 
     * @Singleton 
     */
    @Provides
    @Singleton
    fun provideOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .build()
    }
}

```

具体的なソースを[説明ソース](https://github.com/zhanghangcode)に置きました。是非試してみてください。
ConohaのVPSからAmazon LightSailにサーバを移動③

# ConohaのVPSからAmazon LightSailにサーバを移動③

[前回](https://qiita.com/syakesaba/items/375f0b5971c5ba7ad575)までのあらすじ

> ぼく「とりあえず、SSHで乗り込めるまでやった」
> ぼく「今どきWebサーバってhttpsやし、LetsEncryptでさくっと証明書GETしよう」
> ぼく「ついでにメールもTLSや」


# 目次

1. [LetsEncryptで証明書を貰う](#LetsEncryptで証明書を貰う)
1. [HTTPSサーバでホームページ立てる](#HTTPSサーバでホームページ立てる)
1. [MX(SMTP)サーバ立てる](#MX(SMTP)サーバ立てる)
1. [POPサーバ立てる](#POPサーバ立てる)
1. [参考文献](#参考文献)

# LetsEncryptで証明書を貰う

- Let'sEncryptで有効なDN証明書をGETする: [参考](https://qiita.com/HeRo/items/f9eb8d8a08d4d5b63ee9)
    - nginxのインストール: ```amazon-linux-extras install nginx1```
    - CertBotのインストール(letsencrypt) [参考](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/SSL-on-amazon-linux-2.html): ```yum install certbot```
    - あとは```certbot certonly -a webroot --webroot-path=/var/www -d <ドメイン名> -n --agree-tos --email ...@....com``` が成功するまでもっていってcronで毎月リフレッシュさせればOK。

# HTTPSサーバでホームページ立てる
- 僕の場合は自分の*.github.ioからHTMLクローンしてnginxのlocationを指定するだけ。
    - HTTP用でletsencryptの.well-knownフォルダを作ってる場合は.gitignoreで指定する。
    - Amazon LightSailのファイアウォールでHTTPSを許可する。

# MX(SMTP)サーバ立てる
- とりあえず、MTA同士の通信をなるべく暗号化: [参考](https://qiita.com/tak-onda/items/b585841e03e4619ec367)
- 多分、もう既にpostfix入ってるので、smtpとsmtpsとsubmissionをmain.cfで有効化してちゃちゃっとTLS
    - Amazon LightSailのファイアウォールでTCP25,TCP465,TCP587を許可する。
    - ハマった点：**Conohaと違い、AWSはアウトバウント25番通信を禁止にしている。relayhostを```$mydomain:587```に変更して解決（さらばレガシー25番通信サーバ・・・）**

# POPサーバ立てる
- 普通にインストール: ```yum install dovecot```
    - Amazon LightSailのファイアウォールでTCP993,TCP995を許可する。
- これもちゃちゃっとTLS。SASLハンドラ適当に作って終わり。ハマった点特になし。


# 参考文献
- [Let's Encrypt で Nginx にSSLを設定する](https://qiita.com/HeRo/items/f9eb8d8a08d4d5b63ee9)
- [チュートリアル: Amazon Linux 2 に SSL/TLS を設定する](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/SSL-on-amazon-linux-2.html)
- [Amazon EC2 インスタンスまたは AWS Lambda 関数のポート 25 に対する制限を解除するにはどうすればよいですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-port-25-throttle/)
Chrome OS にFlutterをインストールしたときにChromeが見つからないというエラーが出たときの対処方法 

FlutterをChrome OSにインストールする場合、
[Chrome OS install](https://flutter.dev/docs/get-started/install/chromeos)
のドキュメントを参考に進めていくのですが
最後まで進めても

```shell
flutter doctor
```
を実行したときに手順通りだと

```shell
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel master, 1.26.0-2.0.pre.275, on Linux, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✗] Chrome - develop for the web (Cannot find Chrome executable at google-chrome)
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.
[✓] Android Studio
[✓] Connected device (1 available)
```
とどうしてもバツのまま残ってしまう項目があります。
調べたところGithub上のissueで追加の手順が必要なことが指摘されています。
[[web]: Document how to do flutter development on chromeos #72982](https://github.com/flutter/flutter/issues/72982)
>On a chromebook to run flutter for web development I found it best to install Chromium browser from Crostini (Linux Beta);
>$ sudo apt install chromium
>Then in bashrc make sure to add this;
>export CHROME_EXECUTABLE=/usr/bin/chromium
>
>Everything works fine thereafter including development with Android Studio

コメントにある通り
Crostini上でChromiumをインストール

```shell
sudo apt install chromium
```
した後に

`CHROME_EXECUTABLE=/usr/bin/chromium`
を`~/.bashrc`に設定すれば結果が正常になります。

```shell
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel master, 1.26.0-2.0.pre.275, on Linux, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Chrome - develop for the web
[✓] Android Studio
[✓] Connected device (2 available)

• No issues found!
```



公式ドキュメントへの追加が提案されていますのですぐに正しい手順になると思うのですが
困っている方がいたら参考にしてください。
cuiでのラズパイwifi設定と設定ようscript

## 目的
遠隔に設置したラズパイ(ak20でネットワークにつなげている)に予備のwifiネットワークに繋げるようにネットワークの設定を行う。
または、ラズパイのネットワークの設定にあらかじめお客さんのネットワーク設定を入れておく

## やり方

```:wifiの設定ファイルの編集
sudo vim /etc/wpa_supplicant/wpa_supplicant.conf
```

```/etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=JP

network={
    ssid="W03_aaaaa" #wifiの名前
    psk="aaaa"  #wifiのパスワード
    key_mgmt=WPA-PSK 
}

network={
    ssid="W03_bbbb" #wifiの名前
    psk="bbbbb"  #wifiのパスワード
    key_mgmt=WPA-PSK
    priority=3  #優先度　大きいほうに優先してつなぐ default 0
    disabled=1  #自動接続するかどうか　1だと自動接続しない default 0
}
```


## script
上記参考にwpaを書き換えるスクリプトを書くことでお客さん用のラズパイ設定が楽になります。(⚠️sudo権限じゃないと実行できない)

```add_wifi_ssid.py
import fire


def main(ssid: str, password: str):
  file = "/etc/wpa_supplicant/wpa_supplicant.conf"
  with open(file, 'a') as f:
    text = "network={\nssid=\"" + ssid + "\"\npsk=\"" + password + "\"\nkey_mgmt=WPA-PSK\n}"
    print(text, file=f)


if __name__ == '__main__':
  fire.Fire(main)

```


## その他
```:cuiでwifiを切り替えるコマンド
networksetup -setairportnetwork en0 $ssid $password
```
vuex-module-decorators(Vuex、store)のjestを書く

### 初めに
自分のメモ用として記載しています。
端折って書いている場所もある為、ご了承ください。

vuex-module-decoratorsを使ってstoreの作成をしていた際に
テスト（jest）をどう書けばわからなかった経緯があった為記載します。

*以下の記事などでも書いて下さっているのですが、自分の場合は正常に動作しなかった為
https://qiita.com/azukiazusa/items/8a158913c870bc0c8ba9


## storeの実装について

src配下に以下のように作成したとします。


```
store
├── index.ts
├── app.ts
└── utils
    ├── accessor.ts
```

```index.ts
import { Store } from 'vuex';
import { initializeStores } from '@/store/utils/accessor';

const initializer = (store: Store<any>) => initializeStores(store);

export const plugins = [initializer];
export * from '@/store/utils/accessor';

```

```accessor.ts
import { Store } from 'vuex';
import { getModule } from 'vuex-module-decorators';
import AppModule from '@/store/app';

let appModule: AppModule;

function initializeStores(store: Store<any>): void {
  appModule = getModule(AppModule, store);
}

export {
  initializeStores,
  appModule
};
```
*型などは適当に埋めています。こんなstoreを作成していると見てください

```app.ts
import { Module, Action, VuexModule, Mutation } from 'vuex-module-decorators';
import { $axios } from '@/store/utils/api.ts';

@Module({
  name: 'app',
  stateFactory: true,
  namespaced: true
})
export default class AppModule extends VuexModule {
  private app: any = [];

  @Mutation
  set〜(app: any) {
    this.app = app;
  }

  @Action({ rawError: true })
  async fetchApp(type?: string): Promise<any> {
    const params = {
      〜
    };

    await $axios
      .$get('〜', { params })
      .then((res) => {
        this.set~(res.item);
      });
  }

  get appList(): any {
    if (!this.app) {
      return [];
    }

    return this.app;
  }
}
```

## app.tsのテストを書く

`yarn build`を行うと.nuxtが作成されます。
そのstore.jsにある`createStore`を使ってstoreのAppModuleを利用できるようにしました。

```app.spec.ts
import { getModule } from 'vuex-module-decorators';
import AppModule from '@/store/app';
import { createStore } from '@/../.nuxt/store';

jest.mock('@/store/utils/api.ts', () => ({
  $axios: {
    $get: jest.fn(() =>
      Promise.resolve({
        item: [{ name: '〜' }],
        total: 10
      })
    )
  }
}));　// $axiosのmockです。

let AppModule: any;

beforeAll(() => {
  const store = createStore();
  AppModule = getModule(AppModule, store);　// こちらです。
});

describe('AppModule', () => {
  test('appList', async () => {
    await AppModule.fetch();
    expect(AppModule.appList).toStrictEqual([
      { name: '〜' }
    ]);
  });
});

```


## 最後に
かなり無理やりなテストの書き方だと思うのですが、他に良い方法があれば教えて頂きたいです。
receiptline で作った SVG の電子レシートを CodePen してみた

今回は「[Webグラフィックス Advent Calendar 2020](https://qiita.com/advent-calendar/2020/webgraphics)」に投稿した記事「[SVG + CSS + Node.js + receiptline で電子レシートを発行してみよう](https://qiita.com/dopperi46/items/2e230c322a63086ad6aa)」の補足です。

上記の記事では、作成した SVG の電子レシートを貼り付けることができず、仕方なくスクリーンショットを撮って PNG 形式で貼り付けていました。

ところが、翌日に投稿された、カレンダー作成者 [warotarock さんの記事](https://qiita.com/warotarock/items/ac7f967d9f15a9274d62)には、「動くもの」が CodePen で埋め込まれているではありませんか！

そこで、作成した SVG の電子レシート各種も CodePen でデモしてみたいと思います。

# 動くもの

<p class="codepen" data-height="960" data-theme-id="dark" data-default-tab="html,result" data-user="dopperi46" data-slug-hash="BaLVNQV" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="SVG + CSS + Node.js + receiptline = Digital Receipt">
  <span>See the Pen <a href="https://codepen.io/dopperi46/pen/BaLVNQV">
  SVG + CSS + Node.js + receiptline = Digital Receipt</a> by dopperi46 (<a href="https://codepen.io/dopperi46">@dopperi46</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

何とかできました！
ハマりどころは、CodePen 埋め込みスクリプトの URL を変更しないと表示されないところ。

```html
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
```

また何か作ったら投稿します。ではまた！
【Tips】AWSのVPC Reachability Analyzerでどんなエラーが検出できるかを調べてみた

# はじめに
[AWS の VPC Reachability Analyzer](https://aws.amazon.com/jp/blogs/news/new-vpc-insights-analyzes-reachability-and-visibility-in-vpcs/)はめちゃくちゃ便利。
構築するときに「なんでこれ通信通らないんだ……！ぐぬぬ……！」と時間が格段に減ったと思う。

しかし、これってどんなところまで調べることができるのだろう？
と思い、いくつかのパターンを確認してみた。

VPC Reachability Analyzer 自体の使い方は[クラスメソッド先生の記事](https://dev.classmethod.jp/articles/breaking-vpc-reachability-analyzer/)で詳しく図付きで解説されているので、そちらを見てもらえれば。

# AWS構成図
今回分析をかける構成は以下のような感じだ。
冗長化しているのにNLB使わないとか、こんな構成はあまり取らないだろうが、おためしで作った構成ということで。

![Figure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/ace98cc8-340d-44b9-0cf6-606598634019.png)

VPC Reachability Analyzer の分析成功時は以下のように出力される。

![キャプチャ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/2a197aa2-b470-f0f0-8080-526aa1956732.png)

さて、以下は、上記の図を各標題に記載した状態に変更した場合の分析結果だ。

# VPC Peeringのルーティングをしなかった場合
![キャプチャ4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/0e1fe4e6-2aea-42ac-5ef1-34d867974773.png)

# VPC-B側のNACLでインバウンドを制限した場合
![キャプチャ3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/6d79eee2-827c-616c-ad22-5c46e86abee5.png)

# VPC-B側のセキュリティグループでインバウンドを制限した場合
![キャプチャ1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/6b8acb97-9773-765e-a0c6-36d4dadc3d1b.png)

# VPC-B側のEC2インスタンスで対象ポートをListenしているデーモンを停止した場合
なんと、これは「到達可能」扱いになった。
わざわざポートまで指定しているのだからこれも検知してくれてもよさそうなものなのだが……。

# VPC-B側のEC2インスタンスを停止した場合
![キャプチャ5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/160dbea8-6f90-48e1-48a9-8afb22c3b8e5.png)

# まとめ
割と良い感じに色々な通信エラー部分を拾ってくれる。
ただ、デーモン停止は拾ってくれないので、あくまでも「エンドポイントまでの到達」を検査するようだ。
仮に到達可能になった時は、エンドポイントの内部に問題があると考えるのが良さそう、といったところか。
iOS Safariでも下までスクロールするモーダルの作り方

iOS Safariでモーダルを表示した際、作り方によっては画面下部のツールバーが表示されているとモーダルを下までスクロールすることができないことがあります。

おそらくheightのとり方に問題がありそうで、width: 100vw; height: 100vh;で設定しているときに発生しました。
それをtop,right,bottom,leftにすることで解決することができました。

コードとしては下記のようになります。

``` HTML
<div class="modal">
  <div class="modal_background"></div>
  <div class="modal_content_wrap">
    <div class="modal_content">モーダル</div>
  </div>
</div>
<style>
.modal {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1000;
  overflow: scroll;
}
.modal_background {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
/* モーダルをセンタリングするため */
.modal_content_wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
.modal_content {
  height: 1000px;
}
</style>
```

ちなみに元の作りは下記のようにしていました。

``` HTML
<style>
.modal {
  width: 100vw;
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1000;
  overflow: scroll;
}
</style>
```
【Azure×お名前.com】カスタムドメインを追加する

#はじめに
App Serviceドメインを購入して追加する方法についてはよく書かれているが、お名前.comなどAzure外でのドメインの追加方法についてはあまり書かれていないので、備忘録として残しておく。

#手順
ドメインの登録そのものは以下を参照。
[ドメインサービスのご契約について](https://www.onamae.com/guide/p/21)

全てのサービスからDNSゾーンを選択する。
![スクリーンショット 2021-01-11 16.59.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/fff55c6a-c565-40c7-21e8-d1a718b32cb4.png)
DNSゾーンで追加を選択する。
![スクリーンショット 2021-01-11 16.59.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/3b68b80b-1281-7b41-76f7-60d8e291e654.png)
サブスクリプションとリソースグループを選択し、名前に該当のドメインを入力する。
確認と作成を選択する。
![スクリーンショット 2021-01-11 16.59.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/bc60d334-40ac-a033-6553-8ba9a1240ece.png)
作成を選択する。
![スクリーンショット 2021-01-11 17.14.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/c54da1c8-537f-7e1a-b9f6-83ecb2ed016e.png)
DNSゾーンを作成できたら、ネームサーバーを確認し、お名前.comにAzureのネームサーバーを登録する。
![スクリーンショット 2021-01-11 17.17.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/ccb22fea-68c6-c3ff-5538-cd2c1ee76173.png)
お名前.com Naviのトップページに行き、ネームサーバーを設定するを選択する。
![スクリーンショット 2021-01-11 17.19.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/e7e63c8b-4d13-12fc-77cc-7d118da18078.png)
その他のネームサーバーを使うを選択し、Azureのネームサーバー４台を登録する。
![スクリーンショット 2021-01-11 17.20.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/7c977549-db6c-8af0-217e-a41ec950f7bb.png)

ターミナルで以下コマンドを入力し、ネームサーバーが切り替わっているかどうか確認する。

```
dig 購入したドメイン名 ns +short
```

カスタムドメインを選び、カスタムドメインの追加を押下する。
![スクリーンショット 2021-01-11 20.50.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/6e2fd5dc-5508-d348-b00c-8976cc5815ce.png)
カスタムドメインで該当のドメインを入力し、検証ボタンを押す。レコードタイプはCNAME
![スクリーンショット 2021-01-11 17.28.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/ad66ccf2-0d03-9768-a31e-2d1f31a3422b.png)
そうするとドメイン所有権で警告が出るので、CNAMEレコードの値をコピーする。
![スクリーンショット 2021-01-11 17.28.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/f91b054f-e1ec-f596-c7a6-026e73866ab4.png)
DNSゾーンに戻り、レコードセットを追加する。
![スクリーンショット 2021-01-11 17.32.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/54227627-7cd2-fbba-ecf6-2fc4769ea9f9.png)
名前にwwwを追加し、種類をCNAMEにする。OKを選択する。
![スクリーンショット 2021-01-11 17.32.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/387e3d27-589d-b387-6d4b-21750e953212.png)
カスタムドメインの追加に戻るとドメイン所有権が問題なくなるので、カスタムドメインの追加ボタンを選択する。
![スクリーンショット 2021-01-11 17.33.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/3e4b88fa-e324-e883-20b2-be6b731fe28b.png)

参考
作りながら覚えるMicrosoft Azure入門講座（PaaS編）
Git③【ファイルへの変更を取り消す】

#はじめに
これは学習用のメモになります。

#1.ファイルへの変更を取り消す方法
`ワークツリー`からステージに変更したファイルを取り消す。

```
git checkout --<ファイル名>
git checkout --<ディレクトリ名>

#全変更と取り消す
git checkout --.
```
"--"をつけるのは、ブランチ名とファイル名が被ったときに、どちらを指しているのかGitがわからなくなるのを避けるためです。

#2.ステージに追加した変更を取り消す方法
ワークツリーからの変更したファイルを`git add`で`ステージ`に変更したファイルを取り消す。

```
git reset HEAD <ファイル名>
git reset HEAD <ディレクトリ名>

#全変更と取り消す
git reset HEAD.
```
注意：指定した変更をステージから取り消すだけなので、ワークツリーのファイルには影響を与えない。

#3.直前のコミットをやり直そう
ローカルリポジトリに誤ってコミットしてしまった時にコミットし直す際に使う。

```
git commit --amend
```
注意！：リモートリポジトリに`Push`したコミットはやり直したらダメ。
【Flutter】iOS14実機で起動するとクラッシュする時の対処法

Flutterでの開発中、iOS14の実機でアプリをビルドすると、画面が真っ暗になり起動しない症状が起こりました。iOS14のシミュレーターでは問題なく起動されます。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/a7dab479-a7de-2c3b-6233-cc945305a332.png">

## 環境(バージョン)
Flutter： 1.22.5
Xcode： 12.2
iOS： 14.2

## 対処法
XcodeのEditSchemeから、Debug -> Releaseに変更する。

<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/77d4b437-627e-50ac-dba3-20ec5fc678e5.png">

試しに再度Debugに戻してビルドしてみたところ、クラッシュせず起動できたので、一回だけReleaseでビルドすればよいということなんでしょうか。そこのところはいまいちわかっていません。


Flutter公式に、今回の不具合？の記事が載っていました。
https://flutter.dev/docs/development/ios-14#launching-debug-flutter-without-a-host-computer