OmniAICreator/Qiita-1.07M huggingface dataset:
既存のログイン認証基盤からCognitoに移行するために調べてわかったこと

既存のID&パスワード認証のシステムに加え、新たにシステムを作り、SSO(シングルサインオン)を実装するために、Cognitoを使う。

その際に、既存のユーザー情報を移行しないといけないので、調べてみました。

マサカリ待ってます。

# 前提
AWS CLIは使わず、マネジメントコンソールから操作します。
## 既存の認証基盤仕様
### ログインするためにユーザーが入力するもの
- ユーザーID(またはメールアドレス)
- パスワード

# 移行について
## [懸念点]ユーザーにパスワードの変更をしてもらう必要がある
[[モバイルアーキテクチャ ] Cognitoにどこまで任せるべきか？研究してみた - Qiita](https://qiita.com/vankobe/items/b6bf3a581765e8c3eb37)

> 既存のメール認証システムから移行する場合、name, email, phone numberなどはcsvでimportできるが、passwordだけはimportできないので、ユーザーにpasswordの再設定を依頼する必要がある。そのため、移行コストは高い

## CSVでユーザーをインポートする
既存のユーザー情報を定められた形式のCSVファイルからインポートできる。

既存システムから、CSVを作る仕組みは別途用意しなければなりません。

[ユーザーインポート .csv ファイルの作成 - Amazon Cognito](https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-user-pools-using-import-tool-csv-header.html)

フォーマットはユーザープールで設定した属性に依るので、「CSVヘッダーのダウンロード」からヘッダーファイルをダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256853/5eceac82-5005-eea2-5f76-9ac3c54bae5a.png)

```ダウンロードされるヘッダー例.csv
name,given_name,family_name,middle_name,nickname,preferred_username,profile,picture,website,email,email_verified,gender,birthdate,zoneinfo,locale,phone_number,phone_number_verified,address,updated_at,cognito:mfa_enabled,cognito:username
```

インポートするには上記ヘッダーに合わせて必要な情報を作っていく必要がある

```インポートのソース.csv
name,given_name,family_name,middle_name,nickname,preferred_username,profile,picture,website,email,email_verified,gender,birthdate,zoneinfo,locale,phone_number,phone_number_verified,address,updated_at,cognito:mfa_enabled,cognito:username
tanaka,,,,,,,,,tanaka@example.com,TRUE,,,,,,FALSE,,,FALSE,tanaka
suzuki,,,,,,,,,suzuki@example.com,TRUE,,,,,,FALSE,,,FALSE,suzuki
yamamoto,,,,,,,,,yamamoto@example.com,TRUE,,,,,,FALSE,,,FALSE,yamamoto
```

このCSVファイルを、「インポートジョブの作成」から選択してジョブを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256853/e903039c-47b1-02f2-68af-cbab2340ac70.png)

(試行錯誤の跡がありますが)、ステータスが`Created`の状態で、`開始`を押します。
成功すると`Successed`の状態になります。

> Too many users have failed or been skipped during the import.
というエラーは、CSVの内容を見直してください。具体的なエラー内容は、CloudWatchLogsに吐き出されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256853/9aa80a0b-d880-fbd7-ea4b-75155120f6fc.png)

インポートが成功すると、下記の通りインポートされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256853/0a9f05e8-2857-af70-176f-e545fc71b7ff.png)

あとはアプリクライアントからパスワードのリセットを促すように対応すれば移行できるかと思います。
【Golang】構造体③埋め込み

#【Golang】構造体③埋め込み

Golangの基礎学習〜Webアプリケーション作成までの学習を終えたので、復習を兼ねてまとめていく。 基礎〜応用まで。

```
//Embedded
//クラスの継承のイメージ
//埋め込み



//Pythonの場合
/*
class Vertex(object):

    def __init__(self, x, y):
        self._x = x
        self._y = y

    def area(self):
        return self._x * self._y

    def scale(self, i):
        self._x = self._x * i
        self._y = self._y * i


class Vertex3D(Vertex):

    def __init__(self, x, y, z):
        super().__init__(x, y)
        self._z = z

    def area_3d(self):
        return self._x * self._y * self._z

    def scale_3d(self, i):
        self._x = self._x * i
        self._y = self._y * i
        self._z = self._z * i


v = Vertex3D(3, 4, 5)
v.scale(10)
print(v.area())
print(v.area_3d())
*/


package main


import (
	"fmt"
)

type Vertex struct {
	x, y int
}

func (v *Vertex) Scale(i int) {
	v.x = v.x * i
	v.y = v.y * i
}

//3D
type Vertex3D struct {
	//埋め込み
	//上記で作成した、Vertexを渡すと中身をそのまま渡せる
	Vertex
	z int
}


func NewV3D(x, y, z int) *Vertex3D {
	//埋め込みなので、このように書く。
	//return &Vertex3D{3, 4, 5}ではできない
	return &Vertex3D{Vertex{x, y}, z}
}

func main() {
    v3d := NewV3D(3, 4, 5)

    //どちらでもアクセスできる
    fmt.Println(v3d.x)
    fmt.Println(v3d.Vertex.x)

	
	fmt.Println(v3d)

	v3d.Scale(5)

	fmt.Println(v3d)
}
```
JavaScript＋AzureFunctionsで簡易アクセス解析をやってみた

# 背景
静的なWEBサイト(HTML/CSS/JavaScript)で、ちょっとしたアクセス解析っぽいものを実現したくて試してみました。サーバーサイドで処理できる環境を準備したり、アクセス解析ツールを使ったりするのが、正攻法なのかもしれないですが、ローカルネットワーク内で運用されているWEBサイトで、尚且つ、環境まで触れない（いまは触らない）というのもあり、ちょっと何か出来ないかと思ってやってみたものです。

# 構成
* HTML+CSS
* JavaScritp(Fetch API)
* Azure Functions
* Azure Cosmos DB

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/47c65292-b830-1cbf-0e59-83efd3319333.png)



# 流れ
1. WEBページの操作（ボタンクリックなど）
2. JavaScript(Fetch API)でHTTPリクエスト
3. Azure FunctionsのHTTPトリガーで処理が起動
4. HTTP通信で受信したデータをAzure Cosmos DBに格納



# ソースコード
### HTML
```HTML
<a href="xxxx.html" onclick="javascript:logClick('xxxx')">ああああ</a></li>
```

### JavaScript
```JavaScript
function logClick(xxxx) {

  // Create param
  const yyyy= "hogehoge";

  // Create the query param for Azure Functions
  const params = {
    xxxx: xxxx,
    yyyy: yyyy
  };
  const qs = new URLSearchParams(params);

  // POST to Azure Functions
  fetch(`https://xxxx.azurewebsites.net/api/HttpTriggerXXXX?${qs}`, { method: "POST", })
    .then(response => response.text())
    .then(text => { console.log(text); })
    .catch(console.error);
}
```


### Azure Functions
```C#
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

public static IActionResult Run(HttpRequest req, out object outputDocument, ILogger log)
{
    string XXXX= req.Query["xxxx"];
    string YYYY= req.Query["yyyy"];

    if (!string.IsNullOrEmpty(XXXX) && !string.IsNullOrEmpty(YYYY))
    {
        outputDocument = new
        {
            XXXX,
            YYYY
        };

        return (ActionResult)new OkResult();
    }
    else
    {
        outputDocument = null;
        return (ActionResult)new BadRequestResult();
    }
}
```

# まとめ
データベース上にデータが格納されるまで確認できました。
可視化まわりは今後ちまちまやっていこうと思います。
websocket 入門

## 基本的な構文

```js
var connection = new WebSocket('ws://localhost:8080');
```



## 4つのイベント処理と2つのメソッド

```javascript
var connection = new WebSocket('ws://localhost:8080');
//通信が接続されたとき
connection.onopen = function(e){};
//エラーが発生したとき
connection.onerror = function(e){};
//メッセージを受け取ったとき
connection.onmessage = function(e){};
//通信が切断されたとき
connection.onclose = function(e){};
```

```javascript
//データを送信するメソッド
connection.send();
//通信を切断するメソッド
connection.clse();
```



## ボタンクリックでデータを送信する

```javascript
btn.addEventListener('click',function(e){
    var text = document.getElementById('text');
    connection.send(text.value);
})
```



## テキストデータを受信する

```javascript
connection.onmessage = function(e){
    console.log(e.data);
    connection.close();
}
```
[JavaScript ]条件分岐(if、switch)

# if文
`if (条件式)　{
   処理
}`

```javascript
const number = 10;

if (number > 8) {
   console.log(`${number}は8より大きいです`);
}
```
##else
elseとifの間は半角空ける。
**else if(条件式)**

```javascript
const number = 10;

if (number > 8) {
   console.log(`${number}は8より大きいです`);
} else if (number > 5) {
   console.log(`${number}は5より大きいです`);
} else {
   console.log(`${number}は5以下です`);
}
```

##複数条件式
どちらの条件も満たす時true
**条件式1 && 条件式2**

```javascript
const number = 20;
if (number > 10 && number < 100) {
   console.log(`${number}は10より大きく100より小さいです。`)
}
```

どちらかの条件を満たす時true

**条件式1 || 条件式2**

```javascript
const number = 8;
if (number < 10 || number > 100) {
   console.log(`${number}は10より小さいか100より大きいです。`)
}
```

#switch
値によって処理の分岐をする
必ず**break;**で処理を終了するようにする

`switch (条件の値) {
  case 値1;
    処理
  case 値2;
    処理
  default;
    処理
}`

```javascript
const color = "赤";

switch (color) {
   case "赤";
     console.log("ストップ！");
     break;

   case "黄";
     console.log("要注意");
     break;

   case "青";
     console.log("進んでよし");
     break;

   default;
     console.log("値が正しくありません。");
     break;
}
```

#比較演算子
aとbが等しい
**a === b**
aとbが異なる
**a !== b**
【EC2】seleniumのwebdriverを実行する方法

#【EC2】seleniumのwebdriverを実行する方法

ec2上でseleniumのwebdriverを実行する方法についてわかりやすくまとめています。


<br>
<br>
**＞この記事は[こちらに移転しました。](https://prograshi.com/platform/aws/selenium-webdriver-on-ec2-headless-browser/)**


<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
java Scannerクラス

# Scannerクラスについて

## 導入

Scannerクラスはjava.utilパッケージに含まれるクラスです。

主にコンソール画面の入力、csvファイルの読み込みに使います。


説明読むのめんどくさいんで例題行きます。
<img width="400" alt="スクリーンショット 2020-05-26 15.37.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253875/114a6e94-3f33-191f-f830-3d4039ac218f.png">


## 例題

まずよく使う型指定の入力について見てみましょう。
コード画面
<img width="553" alt="スクリーンショット 2020-05-26 14.32.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253875/0478db46-8bf2-960a-94f2-78363c40693a.png">

コンソール画面
<img width="476" alt="スクリーンショット 2020-05-26 14.32.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253875/88346f2a-5656-f379-72a6-f1adddeaaa7e.png">

はい、こんな感じになります。
ちなみにこれでは不完全なのですが見やすいので一旦解説します。

順番としては
①
まず、Scannerクラスをimportします。importの決まりは```import パッケージ名.クラス名```です。
②
次にインポートしたScannerクラスを[インスタンス化](https://techacademy.jp/magazine/17543)します。
System.inがコンソールでの入力（標準入力）です。

③
指定の型の変数を作成。
そこにScannerクラスのnextInt()メソッドで値を取得し初期化します。

`他にも型指定だとnextByte, nextShort, nextLong, nextFloat, nextDouble, nextBoolean があります。char 型のメソッドだけがないですね。文字列にはnext と　nextLine があります。`

④
最後にcloseメソッドでScannerを閉じる必要があります。
closeがないと予期せぬエラーを引き起こすため気をつけましょう。

##例外処理

不完全と言ったのは、実は上記のコンソール入力の画面でint型以外の入力をしてしまうとエラーが起きてしまいます。
コンソール画面
<img width="472" alt="スクリーンショット 2020-05-26 15.17.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253875/6127bcf7-1ee4-88a2-090e-de2eb2debd27.png">


このように予期せぬ処理を行おうとするとエラーが起きるので、この場合の処理を予期しときます。（日本語わからん）

例外が起きる可能性の処理はtry-catch構文で覆います。if文と同じ要領です。
```try{
例外の起こる可能性のある処理;
}catch(<例外クラス> <変数名>){
例外が起きた時に行う処理;
}```
です。今回ですと

コード
<img width="704" alt="スクリーンショット 2020-05-26 15.24.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253875/3d2e96d6-1b6e-e20e-c542-17ac611c6e2d.png">

コンソール画面
<img width="469" alt="スクリーンショット 2020-05-26 15.24.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253875/babbcf5c-907a-a78f-3fa4-f1358352f71f.png">


注意点としては　
①
例外処理のクラスをimportする必要があります。
よく見ると一番上に```import java.util.InputMismatchException; // 例外処理用のもの```が追加されているのがわかります。

②
```System.out.println("入力された数値は " + num + " です。");```をtry-catch文のそとに出すと例外の場合も処理を行ってしまいます。(今回は num のスコープが try ブロックの中なのでエラーが起きますが）
<img width="466" alt="スクリーンショット 2020-05-26 15.35.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253875/419191e5-73f8-e426-c392-93da1708284e.png">
これは気持ち悪いですね〜。

## まとめ

超基本的なScannerの使い方をまとめてみました。
次は正常処理を行うまで入力をループさせるコードの記事をまとめました。

[次へ](https://qiita.com/hiroki2525/private/00398e3b6921952faa8c)
Node.jsで簡易サーバをつくる

# install

```bash
$ sudo apt install nodejs npm
```

```bash
# 実行
$ node demo.js
```


# webserver using http module

- Node.jsはモジュールをrequire()で呼び出す

- createServer() メソッドを使ってWebサーバーを構築する

- 最後にlisten()でポート番号を指定すれば「localhost:8080」にブラウザからアクセスする

- createServer()の中身は、最低限の記述としてヘッダー情報とコンテンツを次のように記述する
- writeHead()は、responseオブジェクトのメソッドで、ヘッダー情報をレスポンスに書き出す。第１引数には**ステータスコード**を指定し、第２引数に**ヘッダー情報**を連想配列でまとめたものを指定する。

```javascript
var http = require('http');
var server = http.createServer(function(request, response){
    response.writeHead(200,{'Content-Type': 'text/html; charset=utf-8'});
    response.end('<h1><span id="hello">Hello World</span></h1>');
})
server.listen(8080);
```


# htmlを表示するサーバ構築

-  Node.jsでファイルを扱うためのfsモジュールを使って「index.html」を読み込む
- これを変数htmlに格納し、end()の引数に設定することでブラウザに表示できる

```javascript
var http = require('http');
var html = require('fs').readFileSync('views/index.html');

var server = http.createServer(function(request,response){
    response.writeHead(200,{'Content-Type':'text/html'});
    response.end(html);
})
server.listen(8080);
```

# Expressによるサーバ構築


```javascript
var express = require('express');
var app = express();
```

createServer()の引数に先ほど作成したExpressの**サーバーオブジェクト**を設定する。

```javascript
var server = require('http').createServer(app);
app.get("/", function (request, response) {
  response.sendFile(__dirname + '/views/index.html');
});
 
server.listen(8000);
```


# GETを受信する

**ブラウザからWebサイトにアクセスする時はGET通信でサーバーへリクエストを自動的に送信する。**

**フォームなどのデータを送信する場合はPOST通信で送る。**

サーバーに来るリクエストがGET通信であるかどうかを判断するには次のように記述する。

```javascript
http.createServer(function(request,response){
    response.writeHead(200,{'Content-Type':'text/html; charset=utf-8'});
    
    if(request.method == 'GET'){
        //処理
    }
})
```

「request.method」には、サーバーへ送られた**リクエストの種類**が格納される。



# POSTを受信する

**ブラウザからWebサイトにアクセスする時はGET通信でサーバーへリクエストを自動的に送信する。**

**フォームなどのデータを送信する場合はPOST通信で送る。**


```javascript
http.createServer(function(request, response) {
    response.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'});
    
    if(request.method == 'POST'){
    var postData = '';
    
    request.on('data', function(chunk){
        postData += chunk;
    }).on('end',function(){
          response.end('あなたが送信したのは'+postData);
          })
	}
    
})
```

POSTの場合は何らかのデータが送信されているのが普通なので、このデータを受けとる処理が必要である。

request.on() の中で関数を記述し、その引数である「chunk」に送信されたデータが格納される。



続けて、on('end')イベント処理内で取得したデータを画面に表示させる。

on というメソッドは、指定のイベント処理を組み込むためのもので、第一引数にイベント名を、第２引数に組み込む処理（関数）をそれぞれ指定する。


```javascript
var http = require('http');
 
var server = http.createServer();
server.on('request', doRequest);
server.listen(process.env.PORT, process.env.IP);

function doRequest(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.write('Hello World\n');
    res.end();
}
```

requestというイベントにdoRequestという関数を割り当てる。
requestというのは、Serverオブジェクトがクライアントからのリクエストを受け取ったときに発生するイベントで「ブラウザからサーバーにアクセスした時のサーバー側の処理」を組み込む。
筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (6)

前回
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (5)](https://qiita.com/legacyworld/items/2d2db10024d7dfb5f89b)
https://github.com/legacyworld/sklearn-basic

# 課題 4.2 リッジ回帰とラッソの正則化パス
Youtubeでの解説：第5回(1) 15分50秒あたり
課題 4.1とほぼ同じだが、今度は正則化パラメータをより大きく振って($10^{-3} ～ 10^{6}$)、各係数への影響を見ていく問題となっている。
リッジとラッソの違いがはっきりと判るので良い課題だと思う。
ソースコードはこれ。

```python:Homework_4.2.py
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model
from sklearn import preprocessing

#scikit-leanよりワインのデータをインポートする
df= pd.read_csv('winequality-red.csv',sep=';')
# 目標値であるqualityが入っているので落としたdataframeを作る
df1 = df.drop(columns='quality')
y = df['quality'].values.reshape(-1,1)
scaler = preprocessing.StandardScaler()
# 正則化パラメータ
alpha = 10 ** (-4)
X = df1.values
X_fit = scaler.fit_transform(X)
# 結果格納用のDataFrame
df_ridge = pd.DataFrame(columns=np.append(df1.columns,'alpha'))
df_lasso = pd.DataFrame(columns=np.append(df1.columns,'alpha'))
while alpha <= 10 ** 6 + 1:
    # リッジ回帰
    model_ridge = linear_model.Ridge(alpha=alpha)
    model_ridge.fit(X_fit,y)
    tmp_se = pd.Series(np.append(model_ridge.coef_[0],alpha),index=df_ridge.columns)
    df_ridge = df_ridge.append(tmp_se,ignore_index=True)
    # ラッソ回帰
    model_lasso = linear_model.Lasso(alpha=alpha)
    model_lasso.fit(X_fit,y)
    tmp_se = pd.Series(np.append(model_lasso.coef_,alpha),index=df_lasso.columns)
    df_lasso = df_lasso.append(tmp_se,ignore_index=True)
    alpha = alpha * 10 ** (0.1)

for column in df_ridge.drop(columns = 'alpha'):
    plt.plot(df_ridge['alpha'],df_ridge[column])
plt.xscale('log')
plt.gca().invert_xaxis()
plt.savefig("ridge.png")
plt.clf()
for column in df_lasso.drop(columns = 'alpha'):
    plt.plot(df_lasso['alpha'],df_lasso[column])
plt.xscale('log')
plt.gca().invert_xaxis()
plt.savefig("lasso.png")
```

因みに`while alpha <= 10 ** 6 + 1:`の`+1`は、これがないと最後の$10^{6}$が実行されないからである。
`alpha = alpha * 10 ** (0.1)`と刻んでいるのが原因だろうと思う。

今回は描画にあたって２つ変更している。
X軸のみを対数にする(方対数)にする`plt.xscale('log')`とX軸を逆にする(右側が小さい)`plt.gca().invert_xaxis()`

リッジ回帰（左）　ラッソ回帰（右）
![ridge.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629456/18d3c9f0-d5ed-59a1-3fba-51c08ed3401b.jpeg)

全体的に徐々に正則化が効いてくるリッジと係数の小さいものから0に収束するラッソの違いが鮮明に出ている。
（問題は$10^{-3}$からだったが解説のリッジ回帰が$10^{-2}$から描画されていたので変更している）

リッジとラッソ共に、正則化パラメータが大きくなっている途中で係数の絶対値が大きくなるパターンが見える。
以下のグラフはその動きをする特徴量だけを抜き出して描画したものである。
リッジの方が大きく動いて見えるが、Y軸のスケールが10倍違うだけである。
![ridge_increase.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629456/7c0375b3-24fb-08fe-6334-e7429eae960d.jpeg)
とある特徴量の係数が小さくなるとそれまで目立たなかったものが表面化してくる、という動きなんだろうけどよくわからない。
このような動きがあるとは思わなかったので機械学習は一筋縄ではいかないと思わせる良い課題でした。

# 過去の投稿
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (1)](https://qiita.com/legacyworld/items/a3763760e65774dc0e33)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (2)](https://qiita.com/legacyworld/items/5a72c83860c1d0b1d352)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (3)](https://qiita.com/legacyworld/items/c9cd7865efb343c42e5e)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (4)](https://qiita.com/legacyworld/items/9231c44206c8f0823ff5)
sqlite3.OperationalErrorが出た

#エラー内容
sqlite3.OperationalError: no such table: (テーブル名)themes
![sqlite3error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638366/7c23fbd3-c745-994b-9233-a6c17a1cab44.png)


File "/Users/<ユーザー名>/<フォルダ名>/app.py", line 92, in remind
Open an interactive python shell in this frame

```
c.execute("select theme from themes where id = ?", (theme_id,))
```

#誤字確認せよ！
最初にいうと、私のエラーは誤字が原因でした。

テーブル名`from themes`
だけでなく
データベース接続のdb名`conn = sqlite3.connect("service.db")`
も確認しましょう。

#テーブルはあるのに
service.dbのなかにちゃんとthemesテーブルは既に作ってある。

#データベースが無い？
[Help!! sqlite3.OperationalError: no such table: users](https://www.pythonanywhere.com/forums/topic/14348/) (英語)
「作業ディレクトリが何であるかを気にせずに、データベースファイルへの相対パスを使用している可能性があります。」
「同じフォルダにあるかどうかは関係ありません。相対パスは、作業ディレクトリからの相対パスであり、参照先のファイルではありません。データベースファイルが存在しない場合でも、sqliteは文句を言わず、空のデータベースを提供します。」
という回答を見つけた。

**空のデータベース!?**
接続するデータベースが見つからない場合、その名前のデータベースを自動で作るらしい。
文句を言わず（エラーを吐かず）。
見つからないのがおかしいんだけど、
確かにFinderで見ても、VScodeで見ても、空のデータベースがあるorz

#接続先データベースの指定ミス！

```
conn = sqlite3.connect("service.db")
```

が間違っているのかも。ここで嫌な予感。

```
conn = sqlite3.connect("servise.db")
```

servi **s** e

#結論：ただの誤字
ごめんなさい綴りミスでした。

エラー解決のメモ残したかったのに！！！
よくあるから気をつけろ自分！！！！
サーバー運用について

定義：　webの資産の管理や機能を果たすデバイスの事。

例：自分のiPadからAppleのサイトにアクセス
１．ipad端末からAppleに公式サイト見してよのリクエストを送る。
２．サーバーがそのリクエストを承諾してレスポンスを送る
３．ipadにサイトが表示される。

サーバーはWeb上のサイトやアプリのアクセスする人との取引を行っているPCやらストレージですと理解していると十分条件。

大きな視点で見ると、インターネット上で存在する膨大なデータを各担当のサーバーが蓄積している。

現実に使われているサーバーには3種類ある。
１：レンタルサーバー
２：クラウドサーバー
３：PaaS BaaS

1.レンタルサーバーはレンタル代のみで安く面倒なサーバーの構築がないが、既製品であるため機能制限が多く拡張性が少ない
　例　Rails、Django 

2.クラウドサーバーは自由に構築でき専用サーバーより安く済む場合ありで管理者権限で自由度が高い。しかし使用する際の前提知識が多く
学習コストが存在し、Linuxコマンドやデータ保護は自分で行う必要がある。

　例　Google Cloud Platform, Amazon EC2　

３．PaaS(Platform as a Service) BaaS(Backend-as-a-Service)
サーバー構築が不要で学習コストが引くくソフト開発に集中できるが、既製品なので制限がありLinuxコマンドは必要な知識である。

 例　 Heroku(PaaS) Firebase(BaaS) データベースとアプリケーション

気になったサーバーがあるならば実際に料金や学習コストを比較して利用するとよい。
コンテナ設計方針をまとめてみた

## Docker化にあたって

**全てDocker化できるわけではない**

- ステートレスなものは向いている
    - コンテナはステートレス
- 極力手作業なしの形で実装する

### 環境変数を活用する

アプリケーションの挙動を環境変数で制御する

手法
- 実引数
- 設定ファイル
- 設定ファイルに環境変数を埋め込む

### 永続化データの扱い

- Data Volumeとしてホストと共有する
- Data Volumeコンテナとして独立させる

## セキュリティ

- OFFICIALイメージを使う
- Docker Bench for Securityでチェックを行う
- 脆弱性が混入する恐れがあるのでdokerfileにはADDは使わない
    - COPY推奨
    - ADDを使うならチェックサムを併用する

- 適切なアクセス制御を設定する
    - rootログイン禁止
    - ACLを設定する
    - VPNを併用する

- Dockerデーモンにアクセスできることになるので、/var/run/docker.sockを共有しない
- アプリケーション実行ユーザを用意し、rootユーザのままで実行しない

### 機密情報の扱い

- 環境変数(要暗号化)
- 外部から(暗号化S3バケット等)

## ポータビリティ(≒冪等性)

**絶対ではない**

### 冪等性を損ねる要素

- Kernelの違い
- アーキテクテャの違い  
    [ARMアーキテクチャ向けのDockerコンテナイメージをWindows/Macでビルドする](https://dev.classmethod.jp/articles/build-dokcer-image-for-arm-architecture/)
- ダイナミックリンクライブラリ
    - 極力スタティックリンクを使う

## コンテナの粒度

**1コンテナ = 1関心事**

- 1コンテナ=1プロセスではうまくいかないことも
    - プロセスを過剰に意識しないこと

        参考: [dockerfile_best-practices](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)

- 1つのロール or 1つのドメインに収まる粒度で

## より軽いコンテナを

### コンテナが重いことの弊害

- **オートスケールでのサービスインまで時間がかかる**

- ビルドに時間がかかる
- プッシュに時間がかかる
- ホストへにデプロイするのに時間がかかる
- ディスク容量を無駄に消費する
- CIに要する時間が増加する

→ 塵も積もれば、生産性が低下する

### 軽量ベースイメージ

- scratch
    - 機能が限定的すぎる

- BusyBox
    - 標準Cライブラリ別にイメージが作られている
    - パッケージマネージャなし

- Alpine Linux
    - デファクトスタンダード

- dlstroless

### コンテナサイズの削減手法

- アプリケーションのサイズを削減する
    - 不要ファイルの削除
    - 不要プログラムの削除
    - 依存ライブラリの削減
    - web asset(主に画像)のサイズ削減

- .dockerignoreを定義する

- Doker build時のレイヤ構造を削減する
    - RUNで個別に実行する → "&&"で結合して実行する

        ```
        FROM alpine:xx.yy
        RUN apk add --no-cache wget 
        RUN wget https:// hoge.com/fuga.tgz
        RUN tar -xvzf fuga.tgz
        RUN rm fuga.tgz
        RUN mv fuga /bin/fuga
        RUN chmod +x /bin/fuga
        RUN fuga --symlink
        ```

        ↓

        ```
        FROM alpine:xx.yy
        RUN apk add --no-cache wget &&\
          wget https:// hoge.com/fuga.tgz &&\
          tar -xvzf fuga.tgz &&\
          rm fuga.tgz &&\
          mv fuga /bin/fuga &&\
          chmod +x /bin/fuga &&\
          fuga --symlink
        ```

        可読性とトレードオフになる

    - multi-stage builds
        - ビルド用コンテナと実行コンテナを分離する
        - ビルド用コンテナで制作したファイルは実行コンテナにコピーし、ビルド用コンテナは破棄される  
        = ビルド用にのみ必要なツールをインストールするレイヤは、実行コンテナに存在しなくてよい

        ```
        FROM golang:xx AS build
        WORKDIR /
        COPY ./go/src/hoge.com/fuga/piyo
        RUN go get github.com/go-sql-driver/mysql
        RUN go get hoge.in/gorp.v1
        RUN cd /go/src/hoge.com/fuga/piyo && go build -o bin/piyo cmd/main.go

        FROM alpine:yy
        COPY --from = build /go/src/hoge.com/fuga/fuga/bin/piyo /usr/local/bin/
        CMD ["piyo"]
        ```

## 本番環境適用以外のコンテナ活用法

- 開発環境の統一・共有
- CLIの利用
    - Win・MacでLinuxでしか動かないツールを使う手段
- シェルスクリプト
- 負荷テスト


## 参考
[Docker/Kubernetes 実践コンテナ開発入門](https://www.amazon.co.jp/dp/B07GP1Q3VT)
ElasticbeanstalkでAmazon Linux 2のプラットフォームブランチを選択するとebextensionsが動かない

AWS BeanstalkでPHPプラットフォームを選択するとき、最新のプラットフォームブランチだとAmazon Linux2を使うようになっている。
Amazon Linuxのときに使っていた、ebextensionsがそのままだと動かなかったのを書き換えたのでメモ。
`/var/app/ondeck`で動いていた部分を変更。

一応ログを見る限り、composer installは自動で走っているみたいなので、00-composerはいらないかもしれないと思う。
ここのコマンドのエラーログは、`/var/log/cfn-init-cmd.log`に出力される

変更前

```yaml:.ebextensions/*.config
commands:
  01-updateComposer:
    command: export COMPOSER_HOME=/root && /usr/bin/composer.phar self-update

option_settings:
  - namespace: aws:elasticbeanstalk:application:environment
    option_name: COMPOSER_HOME
    value: /root

  - namespace: aws:elasticbeanstalk:container:php:phpini
    option_name: document_root
    value: /public

container_commands:
  00-composer:
    command: "php /opt/elasticbeanstalk/support/composer.phar install"
    cwd: "/var/app/ondeck"
  01-environment:
    command: "mv /var/app/ondeck/$ENV_FILE /var/app/ondeck/.env"
  02-migrate:
    command: "php artisan migrate"
    cwd: "/var/app/ondeck"
```

変更後

```yaml:.ebextensions/*.config
commands:
  01-updateComposer:
    command: export COMPOSER_HOME=/root && /usr/bin/composer.phar self-update

option_settings:
  - namespace: aws:elasticbeanstalk:application:environment
    option_name: COMPOSER_HOME
    value: /root

  - namespace: aws:elasticbeanstalk:container:php:phpini
    option_name: document_root
    value: /public

container_commands:
  00-composer:
    command: "php /usr/bin/composer.phar install"
    cwd: "/var/app/staging"
  01-environment:
    command: "mv /var/app/staging/$ENV_FILE /var/app/staging/.env"
  02-migrate:
    command: "php artisan migrate"
    cwd: "/var/app/staging"
```
負荷テストを始めるにあたり読んだ記事まとめ

# とは
[負荷テストの基本的な考え方と進め方(前編)](https://qiita.com/s_yokoi/items/4e21aed46e561badce94)
[負荷テストの基本的な考え方と進め方(後編)](https://qiita.com/s_yokoi/items/d6d8e2fef567fe7aaacf)

# 観点
> テストの主な目的は，バグを見つけることによって品質を確保すること

https://gihyo.jp/dev/serial/01/tech_station/0001

# 種類
|種類|目的|
|---|---|
|パフォーマンステスト、性能テスト|速度、スケーラビリティ、安定性を決定・検証するための技術的調査|
|負荷テスト、ロードテスト|実運用での、通常時／ピーク時の負荷に対して耐えうるかの検証|
|ストレステスト|実運用での想定利用モデル下で、負荷量と負荷サイズの増大させ、過負荷な状態で発生するバグ(同期の問題、競合条件、メモリーリークなど)を検出するため|
|キャパシティテスト|パフォーマンス要件を満たしつつ、どの程度のユーザやトランザクションをさばけるか検証するため|

http://somat.hatenablog.com/entry/20080119/1200778168
https://qiita.com/shase428q/items/058e0a482ca618e1655d

# 性能要件
シナリオを作成するにあたって、性能要件を定める必要があります。
性能要件が定まらないと、計測の際に何の数字を取るべきか曖昧になってしまいます。
サイトの種類によってスピードがどの程度求められるかは変わってくるので、必要以上の値を求める必要がないということですかね。
性能要件とSLOって近いような気がする。

### 一般的な性能要件
> 　- スループット
　- レスポンス・タイム
　- トランザクション量
　- ピーク時間帯とその集中率

[[方式設計編]性能要件はユーザーが決めると思ってはいけない](https://xtech.nikkei.com/it/article/COLUMN/20071220/289917/)

### 例
> ・ある時間内にサイトに訪れるユーザーの最大数（例：1時間で1万アクセスを処理できるか）
・最大同時アクセスユーザー数（例：同時に1,000アクセスを処理できるか）
・主要なページの平均応答時間（例：3秒以内にページを表示できるか）

[性能テスト、性能改善に関するお話し](http://blog.catalyst-system.jp/useful-003/)

## ツール
https://qiita.com/jun2014/items/121f2dcb2de4c4e77421

### Gatling
https://medium.com/eureka-engineering/gatring-stress-test-14ac5efdfcbc
https://qiita.com/yasuaki0206/items/c84361faef08d6788fd0
https://dev.classmethod.jp/articles/gatling/

### locust
https://cloud.google.com/solutions/distributed-load-testing-using-gke?hl=ja#scaling_up_the_number_of_users_optional

### Vegeta
https://qiita.com/chidakiyo/items/f8cdfac7683216a29c56
AWSで ssh -i 〇〇.pem ec2-user@☓☓☓が通らない理由

AWSで 

```
ssh -i 〇〇.pem ec2-user@☓☓☓
```

が通らない理由についてです。

僕がハマった2つの原因についてお伝えします。

原因１：〇〇.pemのパス指定が間違っている。

解決策：〇〇.pemが存在するディレクトリに移動する。あるいは、現在いるパスから〇〇.pemが存在するディレクトリまでのパスを指定しましょう。（例えば△△/□□/〇〇.pemのように）

原因2:セキュリティグループでSSH接続に自分のIPアドレスを登録していない。

解決策：シンプルに自分のセキュリティグループで登録しましょう。

AWS→EC2→インスタンス→セキュリティグループ（右の方にあります。）
→インバウンドルール（下側）→インバウンドルールを編集のところでタイプをSSHにする。そして自分のIPアドレスを入力する。

で、実は、はまる理由はこの登録を忘れているからではなく、自分のIPアドレスが変わっていることに気づかないことなんです。

IPアドレスはインターネット環境によっては接続のたびに変わります。
詳しくは以下をご覧ください。
https://quoinexjp.zendesk.com/hc/ja/articles/360016319111-IP%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%8C%E6%AF%8E%E5%9B%9E%E5%A4%89%E3%82%8F%E3%82%8B


自分のIPアドレスはこちらで確認できます。もしやと思ったらこちらで確認して再度セキュリティグループに登録しましょう！
https://www.cman.jp/network/support/go_access.cgi


以上です！
ストリーミング配信の仕組みについて基礎知識を解説

#はじめに
ストリーミング配信の仕組みについて基礎知識を解説
https://www.fujiya-avic.jp/contents/video-streaming-system/754.html

##ストリーミング配信とは
> インターネットで動画を見る場合、従来は膨大なファイルデータをパソコンのハードディスクへ、すべてダウンロードしてからでないと視聴できませんでした。すべてのファイルデータをダウンロードするには時間がかかり、現在のように動画を気軽に楽しむことは難しかったのです。

> そこで登場したのがストリーミング配信。サイズの大きいファイルをパケット化して、ダウンロードしながら同時に再生するという仕組みで、パケットはパソコンのメモリに蓄積されます。ユーザーはダウンロードの待ち時間を気にすることなく、見たいときにすぐに動画を視聴することができるようになりました。

視聴が終わるとパケットデータはメモリから消去され、パソコン内に残ることはありません。

###ストリーミング配信のメリット
> ストリーミング配信には、以下のようにたくさんのメリットがあります。

* 有料サービスなどテレビではできない情報の提供
* アクセス履歴による効果の分析が可能
* インタラクティブによりユーザーのリアルタイムな動向の把握が可能
* ファイルがハードディスクなどに保存されない仕組みのため、違法コピーを防ぐことが可能

##ストリーミング配信の2つの配信方法

* オンデマンド配信とは
* ライブ配信とは

###オンデマンド配信とは
> オンデマンド配信は、あらかじめサーバにアップロードされた動画ファイルを、ユーザーが見たいものを見たいときにアクセスして再生する仕組みの配信方法。ビデオデッキでビデオを見るように、早送りや巻き戻しなどが自由に行えるるので、手軽な視聴が可能です。

> WindowsMediaやQuickTimeなど、4種類のフォーマットが主流を占めています。映画などのプロモーションビデオやセミナーなど、あらゆるコンテンツで広く利用されています。

ストリーミング配信に際しては、動画撮影用のデジタルビデオカメラや動画編集ソフト、撮影した素材をストリーミングフォーマットへ変換するためのエンコーダーソフトが必要です。また、動画ファイルの公開には、ストリーミングサーバと高域帯専用回線が必要になります。


###ライブ配信とは

> ライブ配信は、文字通りテレビの生中継のようなものです。撮影している映像を、ストリーミング配信用にエンコードしてリアルタイムで配信する仕組みで、早送りなどの操作はできません。パーソナル放送局や監視システム、eラーニング、会議や研修などで使用されています。

ライブ配信には、オンデマンド配信同様、デジタルビデオカメラ、エンコード用パソコン、エンコードソフト、ストリーミングサーバ、回線が必要です。


#ストリーミングの基礎技術
https://www.nic.ad.jp/ja/materials/iw/2004/proceedings/T9.pdf

##ストリーミングとは？
* 映像配信
    * ダウンロード型
        * 一度ハードディスクに保存し、ハードディスク内のコンテンツを再生
    * ストリーミング型
        * プログレッシブ（逐次）再生、ダウンロードしながら再生
        * データをローカルディスクにファイルとして残さない

<img width="466" alt="スクリーンショット 2020-05-26 13.36.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321923/d3d5bd3c-1605-75da-b9a8-b72617b80610.png">

##TV会議との違い
* リアルタイム性
    * TV会議は、双方向通信で、（ほぼ）リアルタイムにやりとりができる
    * ストリーミングについては、バッファリングなどの影響で、リアルタイムとは言いがたく、片方向通信をメインとしたメディア特性

* 同報性
    * 両者とも1対1や1対特定多数は実現できるが、1対不特定多数になると、ストリーミングのほうが分がある

##本日のデモ構成 本日のデモ構成
<img width="460" alt="スクリーンショット 2020-05-26 13.46.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321923/e85e16a4-a0f9-e2d5-51b8-fec2ed0ccef2.png">
Win10 + Zscaler + Android Studio(Flutter)

##はじめに
テレワークをするために、「Zscaler」なるクラウドセキュリティを導入することになった。
この「Zscaler」の証明書問題が原因でAndroid Studioでの環境構築が止まってしまった。
調査にかなり時間がかかったので、実行手順をまとめていきます。



##実行手順

###Zscalerの証明書をDLする
[Chrome（ブラウザ）からZscalerの証明書をエクスポートしてくる(.cer形式)](https://jp.globalsign.com/support/faq/562.html)
（↑がリンクになっているので、やり方が分からなければ見てください。）

コマンドプロンプト上でコマンドをたたく

```
openssl x509 -inform der -in certificate.cer -out certificate.pem
```
権限が足りなければ、管理者で実行後にたたく

###環境変数に生成したpemファイルを以下に追加する
>変数名：DART_VM_OPTIONS
>変数値：--root-certs-file=[path_to_pem_file]


###Android Studioに証明書を追加する
>Android Studio>Setting>Tools>Server Certification
ここに***.cer***の証明書を追加する

再起動後、Android Studioの設定とAndroid Studioが見ているjavaに証明書を追加する
以下のコマンドを<font color="Red">***Windows Power Shell***</font>を<font color="Red">***管理者権限で実行***</font>して、たたく
*keytoolはAndroidStudioのjavaの中にあるので、その中まで入る必要があります。

```
PS C:\Program Files\Android\Android Studio\jre\bin> .\keytool.exe -import -alias Zscaler  -file 'C:\Users\*******\Downloads\zscaler.cer'  -keystore "C:\Program Files\Android\Android Studio\jre\jre\lib\security\cacerts"
```

PassWord: changeit

これができたら、最後に以下を実行
>Setting>Invalidate Caches/Restart

ダメだった場合は、再起動して完成。


####ちなみに
git cloneをしようとして、SSLエラーが出た場合は以下のコマンドを実行すると解決するかも

```
git config --global http.sslVerify false
```

##おわりに
今回参考にしたリンクを張っていくので、この対処が使えなくなったときは以下のリンクまで行って探してほしい。

- https://github.com/dart-lang/sdk/issues/32131#issuecomment-565059106
- https://serverfault.com/questions/254627/how-do-i-convert-a-cer-certificate-to-pem
- https://qiita.com/tetsu0831/items/a7b3f7abed589d2f0c8a
- https://qiita.com/TKR/items/5f23fe5a341e228cf9b5
マイライブラリ：positionプロパティ

親要素内で、子要素の位置をCSSでデザインする

親要素に```position:relative```で基準位置を作る
子要素に```position:absolute```で基準位置からの絶対値で位置を指定する
そして`top``bottom``left``right`で具体的な位置を指定する。

↓は黄色い親要素のボックスの右上に文字を配置

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="abetack" data-slug-hash="YzyoObL" 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="YzyoObL">
  <span>See the Pen <a href="https://codepen.io/abetack/pen/YzyoObL">
  YzyoObL</a> by abetack (<a href="https://codepen.io/abetack">@abetack</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
Electronアプリの起動を高速にするGoogleFontの読み込み改善テク

## モチベーション

Electronアプリの起動が遅いときの処方箋です。Electronアプリの起動時間が遅く、次のような挙動でした。

- Electronアプリを起動すると、ウィンドウは直ぐに表示される。
- しかし、ウィンドウ内部のHTMLの表示が遅い。
- Electronのイベントでいえば`webContents.once('did-finish-load, ...')`の発火が遅い。

HTMLのロードが遅い原因として、Google fontを使っていたことが原因でした。しかし、あくまで体感ですが、Google fontはElectronであってもキャッシュされているような挙動をします。

[ElectronでのWebフォントのキャッシュについて](https://qiita.com/pochman/items/22343e771528119dc7f6)

で結局ボトルネックはどこで、どう解決するかという話です。

## Google Fontの読み込み

Googleフォントを利用する場合、私の場合はCSS上で読み込みを行っていたので、次のように書いていました。


```CSS
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+JP:wght@400;700&display=swap');

body{
font-family: "Noto Serif JP",serif;
}
```

その他にはlinkタグでHTMLのヘッダーに記述する方法もありますね。

しかしどちらにせよ、**最初に読み込むのはfontではなく、 https://fonts.googleapis.com/css2 というファイル (以下css2ファイル)**ということです。

css2ファイルの中身は、次のようになっています。


```css
/* [0] */
@font-face {
  font-family: 'Noto Serif JP';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: local('Noto Serif JP'), local('NotoSerifJP-Regular'), url(https://fonts.gstatic.com/s/notoserifjp/v7/xn7mYHs72GKoTvER4Gn3b5eMXNvMckQlPa61uNKcCqOfbtLXoH3502Rk.0.woff2) format('woff2');
  unicode-range: U+25e56, U+25e62, U+25e65, U+25ec2, U+25ed8, U+25ee8, U+25f23, U+25f5c, U+25fd4,
 ...(略)...,
 U+2f9d0, U+2f9de-2f9df, U+2f9f4;
}
/* [1] */
@font-face {
  font-family: 'Noto Serif JP';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: local('Noto Serif JP'), local('NotoSerifJP-Regular'), url(https://fonts.gstatic.com/s/notoserifjp/v7/xn7mYHs72GKoTvER4Gn3b5eMXNvMckQlPa61uNKcCqOfbtLXoH3502Rk.1.woff2) format('woff2');
  unicode-range: U+1f230-1f23a, U+1f240-1f248, U+1f250-1f251, U+2000b, U+20089-2008a, U+200a2, U+200a4, U+200b0, U+200f5, U+20158, U+201a2, U+20213, U+2032b, U+20371, U+20381,
 ...(略)...,
 U+25c4b, U+25c64, U+25da1, U+25e2e;
}
/* [2] */
@font-face {
...(略)...
```

このようにcss2ファイルの中身は、`@font-face`の束になっています。

つまり、Google fontの読み込みは

1. css2ファイルの読み込み
1. フォントデータの読み込み

の順で二段階のファイル読み込みが発生します。そして、後者はキャッシュされますが、前者はキャッシュされていないようです（あくまで体感です）。

つまり、**ボトルネックはcss2ファイルの読み込み速度**でした。

## 処方箋

さて、あらためて、フォントデータの方はキャッシュされるとして、css2の読み込みを改善させる必要があります。どうするかといえば、css2ファイルをローカルに持つということです。

まず、googleフォントの`@import`や`link`に記述するURLを適当なブラウザのURL欄に入力してアクセスします。
![css2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557342/ad6dea87-a3e2-827b-9b2a-5e9323a8cbb7.png)
するとcss2の中身がテキストで表示されます。この内容を全て選択してコピーし、適当なテキストエディタで張り付けしてローカルに保存しましょう。ここでは仮に保存名は`imp_NotoSerifJP.css2`としておきます。

次に、HTML上で読み込むCSSの中身を、最初の例から次のように変更します


```CSS
/*
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+JP:wght@400;700&display=swap');
*/

@import url('./imp_NotoSerifJP.css2');

body{
font-family: "Noto Serif JP",serif;
}
```

こうすることで、ローカルからcss2ファイルが読み込まれるようになり、読み込み速度が改善します。

## まとめ

Google fontの読み込みではcss2ファイルとfontデータの二段階になっており、後者はキャッシュが効きますが、前者が速度的なボトルネックになることがあります。前者のcss2ファイルをローカルに持たせることで、Electronアプリの起動速度を改善できました。

私の作っているアプリでは、1秒以上かかっていた起動時間がかなり改善されました。
storyshotsでのスナップショットテスト

## スナップショットテスト

現在の画面のスナップショット（キャプチャみたいなもの）を保存しておいて、テストの時にそのスナップショットと今の画面と比較して変更点を出力してくれる。
変更内容を確認して意図せぬ変更に気づくことができる。
正しい変更かそうでないかは自分で確認にすること。


## 流れ

スナップショットは導入した後の初回のテスト時に自動で生成される。
なので初回は比較対象がないので、必ずパスする。
スナップショットが生成した次回以降のテストは比較結果が出る。
変更点が問題なく、新しくスナップショットを取りたいと思ったら、スナップショットのファイルを削除して、再度テストを実施して生成させる。


## 導入


### storybookの導入

スナップショットのテストの方法はいくつかあると思うが、今回はstorybookを利用したテストの方法を記載する。
storybookの初期化を実行する。
下を実行することで、storybookのパッケージの追加とstorybookの設定ファイルを生成してくれる。

```
npx -p @storybook/cli sb init
```


`./src/stories`がサンプルファイルとして生成されるので、不必要なら削除する。
また、typescriptを使っているなら、`./storybook/main.js`の設定ファイルを変更する。


```js
module.exports = {
  stories: ['../src/**/*.stories.tsx],
  addons: [
    '@storybook/preset-create-react-app',
    '@storybook/addon-actions',
    '@storybook/addon-links',
  ],
};
```

Hello world!!と表示するだけのHelloコンポーネントがあるとする。
Hello.stories.tsxを作成してstorybookに登録する。


```tsx
// src/Hello.tsx

import React from 'react';

const Hello = () => <div>Hello world!!</div>;

export default Hello;
```



```tsx
// src/Hello.stories.tsx

import React from 'react';

import Hello from './Hello';

export default {
  component: Hello,
  title: 'Hello',
  excludeStories: /.*Data$/,
};

export const Default = () => <Hello />;
```


`yarn storybook`を実行するとstorybookの画面で確認することができる。


### storyshotsの導入

スナップショットの実行するパッケージを追加する。


```
yarn add -D @storybook/addon-storyshots react-test-renderer
```


スナップショットを生成するためのファイルを作成する。


```js
// src/storyshots.test.js

import initStoryshots from '@storybook/addon-storyshots';
initStoryshots();
```


`yarn test`を実行したら、`./src/__snapshots__/storyshots.test.js.snap`というファイルが生成されたはず。
中身は以下ようにHelloコンポーネントで表示する内容が記載されている。


```
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Storyshots Hello Default 1`] = `
<div>
  Hello world!!
</div>
`;
```


testはこのスナップショットのファイルがない場合はスナップショットの生成、ある場合は比較する。
生成の場合はテストはパスになる。
このあとHelloコンポーネントを変更して、`yarn test`を実行したらスナップショットのファイルと比較するのでテストは通らない。

コンポーネントを変更して、再度スナップショットを取りたい場合は`__snapshots__`のディレクトリごと削除する。
色んなコントローラーでラジコン動かしたい_01

UnityとRaspberryPi使ってラジコンをハンコンで動かしてみたいメモ

#検討中の方法
1. 既製品を用いる方法（Web io Pi）
2. webに事例が多い方法（Web io Pi）
3. Unityと相性が良さそうな方法（WebSocket）

###1.既製品を用いる方法（Web io Pi）
>専用ソフトウエアをどこまでカスタマイズできるか？

世界最強のラズパイ・ラジコン基板 RC Berry
https://eleshop.jp/shop/g/gH7C411/
たのしい電子工作クラブ
http://elec-nuts.cocolog-nifty.com/blog/cat64607689/index.html
http://elec-nuts.cocolog-nifty.com/blog/rcb01-.html
![SnapCrab_NoName_2020-5-26_14-54-31_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227439/00a14561-26f4-acb4-b05e-8fdcc7fa36f5.png)


###2.webに事例が多い方法（Web io Pi）
>WebioPiがちょっと古そうで不安（ver.が1未満だったり）
>ブラウザGUI以外で操作したい。Unityから直接指示出せる？

WebIOPiを使ってRaspberryPiのGPIOを外出先から操作する
https://westgate-lab.hatenablog.com/entry/2020/01/09/231539
Raspberry PiでWebから操作できるラジコンクローラーを作る
http://kazuki-room.com/create_a_radio_control_that_can_be_operated_from_the_web_with_raspberry_pi/
![SnapCrab_NoName_2020-5-26_14-55-34_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227439/da7282fa-95f0-90e8-d67a-92138545b948.png)

###3.Unityと相性が良さそうな方法（WebSocket）
>Node.js入れたり環境構築から始める必要あり、先ずは手短に完成させたい。

UnityとRaspberry Pi間でWebSocket通信
https://tomosoft.jp/design/?p=4466
UnityでWebSocketを使用する
https://qiita.com/oishihiroaki/items/bb2977c72052f5dd5bd9

![SnapCrab_NoName_2020-5-26_14-59-27_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227439/6114b589-d1a3-4e16-240d-449fbe612b5c.png)
flutter doctor で VS Code Flutter extension not installed

# 現象

```
[!] VS Code, 64-bit edition (version 1.33.1)
    X Flutter extension not installed; install from
      https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75451/b3373a0a-2214-9770-b626-02150a2602bc.png)

# 対策

* VS Code を起動する。

* EXTENSIONS を選ぶ（左メニューの、テトリスのブロックみたいなやつ）

* flutter を検索してインストールする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75451/5df39fbb-742c-bfbf-2ebd-65a775963ee7.png)


再度、flutter doctor を実行して下記のようになればＯＫ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75451/461414d8-bfb8-5ece-7303-8d44ca499d98.png)
Laravel リクエストログの場所

# 目的

- ログの場所を知ったため忘れない様にメモする。

# 実施環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.3) |
| ハードウェア | MacBook Pro (16-inch ,2019) |
| プロセッサ | 2.6 GHz 6コアIntel Core i7 |
| メモリ | 16 GB 2667 MHz DDR4 |
| グラフィックス | AMD Radeon Pro 5300M 4 GB Intel UHD Graphics 630 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.3 | Homwbrewを用いて導入 |
| Laravel バージョン | 7.0.8 | commposerを用いて導入 |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いて導入 |

# ログの場所

- ログは下記に存在する。
    - `アプリ名ディレクトリ/storage/logs/laravel.log`

# 出力

- アプリ名ディレクトリで下記コマンドを実行してログを出力する。

    ```terminal
    $ tail -f storage/logs/laravel.log
    ```
Windows10でVScodeを用いてPytorchを動かす ～新品からのセットアップ

#はじめに
Windows10の環境に、VScodeを用いてPytorchを動かすところまでのセットアップ方法をまとめました。ちなみにエディタとしてVScodeを使うのは、GitHubとの連携が容易であるためです。今回は敢えてAnacondaを導入しませんでした。その理由は、Anacondaを使っても結局面倒なことが多いためです（参考サイト1を参照）。

#PCのスペック
ThinkPad P53
GPU NVDIA Quadro 5000

#ダウンロードしたもの、手順
**NVIDIA toolkit v10.2**
https://developer.nvidia.com/cuda-toolkit
どのバージョンを入れるかについては、参考サイト2を参照。
Ver10.1をインストールしようとしたところエラーが出てうまくいきませんでしたが、Ver10.2はうまくインストールできました。このような場合にNVDIAのツールを全て削除することを勧めているサイトが多数ありますが、今回は削除する必要はありませんでした。ちなみに、本ツールの動作にvisual studio 2017が必要ですが、toolkitのインストール時に勝手についてきたので別個に入れる必要はありませんでした。

**Cudnn v7.6.5**
https://developer.nvidia.com/cudnn
NVDIA toolkitのバージョンと対応したものをダウンロードします。メンバーサイトに登録す必要があります。
ダウンロードしたらNVIDIA toolkitにコピーしてパスを通しておきます。手順は下の参考サイト3を参照。

**Python v3.7**
https://www.python.org/downloads/
ダウンロード後、コマンドプロンプトにpythonと打ち込み、起動を確認する。
起動できなければ、環境変数からパスを通す（参考サイト4を参照）。

**Pytorch**
https://pytorch.org
CUDA toolkitのバージョンなどを入力して、出てきたコードをコマンドプロンプトで実行すればOK!
pipのバージョンが古いとエラーが出たので、`python -m pip install --upgrade pip `
でバージョンアップしてからインストールしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620139/e7b0ffb9-66b1-0e7f-8629-56154f717515.png)

ここで、コマンドプロンプトに`python`と打ち込んでpythonを立ち上げ、`import torch`と入力。
これでエラーが出なければ、pytorchのインストールは無事に完了。さらに`print(torch.cuda.is_available())`と入力しtrueと出力されました。CUDAがめでたく認識されていることがわかりました。

**Git**
https://git-scm.com/downloads
GitHubとの連携のために、ダウンロードしておく必要があります。

**VScode (Visual Studio Code)** 
https://azure.microsoft.com/ja-jp/products/visual-studio-code/

そのままでも動きますが、拡張機能の`python`を入れておくと、スクリプト中で「shift+enter」を押すことにより部分的に実行できるという究極に便利な機能を使えるようになります。
![rqkod-7ff3z.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620139/5ad3cd5d-4566-6458-638d-a4366d3521c1.gif)
GitHubとの連携：（参考サイト5を参照）
①GitHubにリポジトリを作る、リポジトリのアドレスをコピーしておく
②VSCODEでCTRL+SHIFT+P → Git clone：ﾘﾎﾟｼﾞﾄﾘURLを貼り付け
③Git cloneするフォルダを選択
④スクリプトを書いたら、CTRL+Sでセーブ→✔マーク（コミット）→右の…マークから「同期」をクリック
![furjz-dzubx.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620139/72e04d34-aa44-c15e-4ae4-cd28b4f90993.gif)

#最後に
ドライバを削除すると必要なものまで消えたりして、環境構築にまる3日かかりました。
この通りに行えば、2時間程度でセットアップできそうです。
環境構築にはまっておられる方の助けになれば幸いです。



#参考にしたサイト
1. Windows10でPyTorchをインストールしてVSCodeで使う
https://blog.negativemind.com/2019/03/06/python-pytorch-on-windows-10-with-visual-studio-code/

2. CUDA+cuDNNのインストールまとめ
https://qiita.com/8128/items/2e884998cd1193f73e2f

3. PyTorchインストール時のCUDAバージョンの選び方
https://katsuwosashimi.com/archives/742/how-to-choose-cuda-version-pytorch/

4. 【windows10】Python3.7をインストールしてpathを通して、pipでパッケージを入れる
https://karupoimou.hatenablog.com/entry/2019/04/29/064646

5.　鍋綿ブログ【初心者向け】GitHubにリポジトリを作成してVisual Studio Codeと連携するまで
https://www.micknabewata.com/entry/github/vscode-sync
完全に理解した人達の「Web技術」Talk #2 勉強会レポート

# 完全に理解した人達の「Web技術」Talk #2
2020年2月27日にオンライン開催した「Web技術」勉強会のスライド資料と概要をまとめです。

> みんなが知っている「筈」のWebの技術に関することのLT大会です！
> 
> - HTTP
> - REST
> - URI
> - HTML
> - サーバー
> - 設計
> - API 
>
> などなど、「Webに関連する技術」ことならなんでもOKです！
> あなたの知ってるWebの技術についての話を存分に語りましょう！
>
> [完全に理解した人達の「Web技術」Talk　#2 - connpass](https://easy2.connpass.com/event/167520/)


# LT1:HTTPステータスコード完全に理解した（@unsoluble_sugar）
[![thumbnail](https://speakerd.s3.amazonaws.com/presentations/807eea3bb49d479a9b52c80c159085bf/slide_0.jpg)](https://speakerdeck.com/unsoluble_sugar/http-status-code-perfectly-understood-dawn)
[HTTPステータスコード 完全に理解した - Speaker Deck](https://speakerdeck.com/unsoluble_sugar/http-status-code-perfectly-understood-dawn)

- HTTPステータスコードとは、そもそもなんぞや？
- ステータスコードは100番台～500番台の5つのクラスに分類される
- 代表的なステータスコードの紹介
- ステータスコードを意識した設計を行うことで、 サーバとクライアント間の開発がスムーズに進む
- ステータスコードを理解することで 、問題の切り分けや判断がしやすくなる

以下記事にスライド内容を書き起こしています。
[HTTPステータスコード 完全に理解した - Qiita](https://qiita.com/unsoluble_sugar/items/b080a16701946fcfce70)

# LT2:モダンブラウザストレージ（@mainyaa）

[![thumbnail](https://image.slidesharecdn.com/modernbrowserstorage-200227122802/95/-1-638.jpg?cb=1582806567)](https://www.slideshare.net/mainya/ss-229318451)
[モダンブラウザストレージ - SlideShare](https://www.slideshare.net/mainya/ss-229318451)

- HTML5で使われるストレージの良いところと悪いところ
- Web Storage、Web SQL Database、IndexedDB、Cookie
- 使い分け方の紹介
- どれを使ったら良いのか
- エラーハンドリングについて

# CORS再入門（@i-dach）

[![thumbnail](https://speakerd.s3.amazonaws.com/presentations/4686a88c2ed0412790c502b5817760ae/slide_0.jpg?15000398)](https://speakerdeck.com/dach/cors-zai-ru-men-8b1db383-cd93-4530-b4dd-8badfa6a370d)

[CORS_再入門 - Speaker Deck](https://speakerdeck.com/dach/cors-zai-ru-men-8b1db383-cd93-4530-b4dd-8badfa6a370d)

- CORSとはCross-Origin Resource Sharing（オリジン間リソース共有）の略
- CORS制約で怒られるケースの紹介
- オリジンには「ドメイン」「プロトコル」「ポート番号」が含まれる
- 異なるオリジンにあるリソースをリクエストするときにはレスポンス側に設定が必要
- フロントだけではなくAPIサーバー側の修正も必要
[Javascript]テンプレートリテラレル

#説明
コンソールに表示する時に　**${変数}** で文字をつなげる。

＃注意点
この書き方をする時はバックコーテーション**「`」**でくくる。

#例

```javascript
const name = "田中";

console.log(`こんにちは、${name}さん`);
```

出力結果
こんにちは、田中さん
【Swift】 TextFieldのあるAlertを表示させる方法

SwiftでTextFieldのあるAlertを表示させる方法。


#### 実装イメージ
このようなタイトル、サブタイトル、入力欄、キャンセル、追加で構成されたAlertを作成して行きます。
<img width="378" alt="スクリーンショット 2020-05-26 14.57.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592713/a6a022df-76a5-ce23-3fce-609f1755c641.png">




#### Storyboard
buttonを押すとAlertが表示されるようにするため、好きな場所にbuttonを1つ追加しましょう。
<img width="1880" alt="スクリーンショット 2020-05-26 14.19.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592713/5f973213-588f-7687-a0f1-a106cd252969.png">

#### ソースコード

```Swift:ViewController.Swift
import UIKit

//UITextFieldDelegateを追加する
class ViewController: UIViewController,UITextFieldDelegate {

    //StoryboardのbuttonをAction接続する
    @IBAction func aleat(_ sender: Any) {

        let alert = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
        alert.title = "ここにタイトル"
        alert.message = "メッセージ"
        
        alert.addTextField(configurationHandler: {(textField) -> Void in
            textField.delegate = self
            
        })
        
        //追加ボタン
        alert.addAction(
            UIAlertAction(
                title: "追加",
                style: .default,
                handler: {(action) -> Void in
            self.hello(action.title!)
        })
        )
        
        //キャンセルボタン
        alert.addAction(
        UIAlertAction(
            title: "キャンセル",
            style: .cancel,
            handler: {(action) -> Void in
                self.hello(action.title!)
        })
        )
        
        //アラートが表示されるごとにprint
        self.present(
        alert,
        animated: true,
        completion: {
            print("アラートが表示された")
        })
    }

    func hello(_ msg:String){
        print(msg)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

}
```

#### ビルドして確認してみましょう
実装イメージのようなAlertを表示させることができたでしょうか？
title部分は好きな文に変えることでお好みのAlertを表示させることができます。

できたー！という方はLGTM押してくださると僕がめっちゃ喜びます!
[Python]学習メモ1

###ハノイの塔

```python:py
def hanoinoto(hanoi, n):
    """ハノイの塔の表示"""
    print('------', n)
    for stack in hanoi:
        print('#', ''.join(stack))

N = 3  # 円盤の数

# 3つの位置の円盤の状態
hanoi = [list('4321')[-N:], [], []]
hanoinoto(hanoi, 0)  # 初期状態の表示

# 全ての円盤を移動
for n in range(1, 2**N):
    i = (n & (n - 1)) % 3  # 移動元（ビット演算）
    j = ((n | (n - 1)) + 1) % 3  # 移動先（ビット演算）
    c = hanoi[i].pop()  # 位置iからpop
    hanoi[j].append(c)  # 位置jにappend(push)
    hanoinoto(hanoi, n)
```
***実行結果***

------ 0
\# 321
\# 
\# 
\------ 1
\# 32
\# 
\# 1
\------ 2
\# 3
\# 2
\# 1
\------ 3
\# 3
\# 21
\# 
\------ 4
\# 
\# 21
\# 3
\------ 5
\# 1
\# 2
\# 3
\------ 6
\# 1
\# 
\# 32
\------ 7
\# 
\# 
\# 321
flutter doctor で Android license status unknown.

### 原因

ライセンスに同意していないと出る。同意すればＯＫ。

### 対策

```
flutter doctor --android-licenses
```

を実行して、すべて y と答えればよい。

最後に

```
All SDK package licenses accepted
```
と表示されたらＯＫ。




# SDKが入っていない場合はインストールする。

```
flutter doctor --android-licenses
```


の実行で

```
Android sdkmanager tool not found (C:\Users\yamato\AppData\Local\Android\sdk\tools\bin\sdkmanager).
Try re-installing or updating your Android SDK,
visit https://flutter.dev/docs/get-started/install/windows#android-setup for detailed instructions.
PS C:\Users\yamato\develop>
```

のように出る場合は、下記を実行する。

* Android Studio を起動する。

* ファイル＞設定＞システム設定＞Android SDK に進む。

* 「SDKツール」タブをクリックする。

* Android SDK Build-Tools にチェックを入れる。

* Android SDK Platform-Tools にチェックを入れる。

* Android SDK Command-line Tools にチェックを入れる。

* 「適用」を押す。

* 「要求されたコンポーネントのインストール中」になる。

* 「完了」を押す。

* Android Studio を終了する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75451/9f05aa8a-4488-b7f5-efda-e4512fb86d8b.png)



この状態で

```
flutter doctor --android-licenses
```

を実行する。
Rails チュートリアルを分解してみる

# やったこと
- Railsチュートリアルを最初から読んで、最終的に作るものを把握する
- 最終成果物を作成する過程をissues として自分で切り出した

# なぜやったか
- 実践では何を作るかが最初に提示されるから
- 作成する対象を分解する必要があるから
- 最初に全体を分割して把握することで進捗を見えるようにしたいから
- issue 毎にタスクをさらに細分化する練習が必要だから

まずは最小限の機能が作りたいので、途中のch9-ch12 までは飛ばした。余裕があればアサインしたissue にToDoを整理し追加した上で、テストを書いてから実装するほうが良い。

# 次にやること
-  ローカルに開発環境を作る

issue 切り出すだけですごい時間がかかった。
[rails]共同開発で苦労した点:github編


苦労した点のメモ書き。

#mergeができない
プルリクエストも作成できており、削除もできるのに
mergeボタンだけなかった。

【原因】
共有するための「collaborators」が、うまくできていなかった。

参考：
[Githubのプロジェクト(オリジナル・リポジトリ)を複数人で共有する(Collaborators権限)](https://git-manual.net/github-collaborators-right/)

#コンフリクトに戸惑う
一番初めは何をどうすればいいのかわからない。
開発が進むと、コンフリクトは起きているのにボタンが押せない、、、

対応策は下記に記載(ローカルでマスターを取り込む事で解決)
→https://qiita.com/ki-ku/items/1416795cdaac7b7545ae