OmniAICreator/Qiita-1.07M huggingface dataset:
ファームウェア／ソフトウェアエンジニアが知っておきたい電気設計の基礎知識【電源IC編】

この記事では、電池で駆動するデバイスにおける**電源ICと消費電流との関係性**について記載します。

電気設計者向けというよりは、「電気設計者の考え方を知りたい」、「電気設計者と今より深い議論がしたい」という方向けです。
そのため、**技術的な厳密さ**よりも、「そもそも電源ICのとは何なのか？」の様な**基本的な考え方や概念**の説明に重点を置いていますので、そのあたりご了承下さい。

# 自己紹介
初投稿のため、簡単に自己紹介を書いておきます。

元々は大手カメラメーカーにて電気設計者として働いており、現在はファームウェアの設計を担当しています。

経歴は以下の通りです。
- 大手カメラメーカーで一眼レフカメラの**電気設計**　　　　　　　　　7年
- Bitkeyでスマートロックやその他IoTデバイスの**電気設計**　　　　　　1年
- Bitkeyでスマートロックやその他IoTデバイスの**ファームウェア設計**　1年

カメラメーカーにいたときは、主に電気回路設計や基板・アートワーク仕様設計を担当しつつ、ディスプレイやセンシングデバイス（GPS、加速度センサなど）についてのファームウェア制御仕様の検討やコマンド仕様の策定を担当していました。

その経験を元にBitkeyで働いている中で、「ファームウェア設計者に向けて、電気設計者の自分だからこそ共有できる知見がある」ということに気付いたので、それを記載していこうと思います。

# 背景
スマートロックやIoTデバイスは電池駆動のモノも多く、お客様が頻繁に電池を交換することがない様に設計する必要があります。
具体的には、デバイスの待受状態では数十uAオーダーに抑え込んだりします。

そんな中で、あるデバイスの電気回路を見つつ、消費電力の削減を検討しているときに、
「電源ICを変えたら、電池寿命が大幅に上がりそうだね」と気付いた場面があったわけです。
それを聞いていたファームウェアチームメンバーにウケが良く、この投稿をすることにしました。

# 前知識
「そもそも電源ICってなんだ？」という方は以下を読んでみてください。

[Rohm エレクトロニクス豆知識](https://www.rohm.co.jp/electronics-basics/dc-dc-converters/dcdc_what1)

ちなみにこの記事では直流(Direct Current：**DC**)電源に絞ります（我々が扱っている多くのデバイスが電池駆動のため）。

要点は以下の通りです。
- 電源ICは、**ある電圧を入力として別の電圧を生成するIC**である
    - 他の電子部品は、電源ICによって生成された、その部品に合った電圧を用いて駆動することができる
- 電源ICの中で、電池駆動デバイスにおいてよく使われるのはDC/DCコンバータである
- DC/DCコンバータとは、あるDC電圧を入力として、別のDC電圧を生成する電源ICのことである
- 代表的なDC/DCコンバータには、**リニアレギュレータ**と**スイッチングレギュレータ**の2つがある
- リニアレギュレータは、**入力された電圧よりも低い電圧にしか**変換できない
- スイッチングレギュレータは、回路によって**入力された電圧より低い電圧にも高い電圧にも**変換できる

# 電源ICと消費電流
ここからが本題です。
[このサイト][link-2]の"リニアレギュレータ"のページで軽く書いてある以下の部分の話について詳細に見ていきます。

> (リニアレギュレータは)制御素子で降圧するため、入力と出力の電圧差（降圧度合）が大きいと損失が大きくなり効率も悪くなります。

私がよくリニアレギュレータとスイッチングレギュレータについて、他の人に伝えるときに使うのが以下の考え方です。

- リニアレギュレータは、入力に対して出力の**電流が保持される**ICである
- スイッチングレギュレータは、入力に対して出力の**電力が保持される**ICである

冒頭でも書いた通り、これはあくまで電源ICでの損失等もろもろを無視した**考え方**です。

どういうことか、を図にすると以下の様になります。
例として、入力電圧 Vin=6V から出力電圧 Vout=3V に電圧変換し、負荷で消費する電流 Iout=1mA とした場合を考えます。
そのときの各部での電圧・電流は以下の様になります。

![スクリーンショット 2022-03-09 21.40.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219768/0da259a5-e0f2-7543-87ed-03a234d939eb.png)

ここで、我々製品開発者が下げるべき電流は、電池の放電電流（上の図でいうと <font color="Blue">**Iin**</font>）です
この例では、スイッチングレギュレータを使ったときの <font color="Blue">**Iin**</font> は、リニアレギュレータのときの**半分**になります。
この**半分**というのは、スイッチングレギュレータの**電力が保持される**という特性を元に Vin と Vout の比から算出できます。
具体的には、**入力電力 Pin = 出力電力 Pout** を、 P = V × I の公式を使って変換すると、 **Iin = Vout / Vin × Iout**　となり、 Iin は Iout にVin と Vout の比である Vout / Vin を掛けたものであることがわかります。
そのため、<font color="Red">**入出力電圧の降圧度合が大きい( Vout / Vin が小さい)電圧変換のときはスイッチングレギュレータを使った方が消費電流を節約できる**</font>わけです。

実際に部品を選定する際は、消費電流に応じた電源ICの損失含めた変換効率や出力電圧の変動、電源ICから出るノイズの影響、周辺部品のコスト、更に、最近では部品調達性などまで考えなければなりませんが、上記の考え方を知ることで、皆さんの**電気領域の知識を広げる**ことに少しでも役に立てばと思います。

[link-1]: https://www.wantedly.com/companies/bitkey/post_articles/378678
[link-2]: https://www.rohm.co.jp/electronics-basics/dc-dc-converters/dcdc_what1
TypeScript tips① objectのvalueの型を抽出する方法

### まずobjectを用意する
constアサーションを忘れないでください

```
const object = {
　　BREAKFAST: 'breakfast',
 LUNCH: 'lunch',
 DINNER: 'dinner'
} as const

```

下記のようにこのobjectのvalueを抽出したいと思います。

```
type ObjectType = 'breakfast' | 'lunch' | 'dinner'
```

これでもいいですが、長いですね...
```
type FormObjectInputType = typeof FormObjectInputType[keyof typeof FormObjectInputType]
```

### Genericsを使って汎用的な型を定義する

```
type ValueOf<T> = T[keyof T]
```
Tの部分に、typeof + 対象のobjectを入れれば、valueを抽出できます。

```
type FormObjectInputType = ValueOf<typeof FormObjectInputType>
```
ちょっとシンプルになりましたね。
Rspecのallow_any_instance_ofを書き換える

# はじめに
インスタンスメソッドのスタブを `allow_any_instance_of` で書いていたのですが、どうやらこれが非推奨らしいので、これを書き換える方法をメモがてら記事にしました。

# allow_any_instance_of を使ったテスト

テスト対象のファイルはこちら

```ruby:test.rb
class Test
  def test_method
    hoge = Hoge.new
    hoge.hello
  end
end

class Hoge
  def hello
    "hello!"
  end
end
```

そして `allow_any_instance_of` を使ったスペックファイルがこちら

```ruby:test_spec.rb
require_relative 'test'

describe 'Test' do
  context 'test_method' do
    before do
      allow_any_instance_of(Hoge).to receive(:hello).and_return('hello!(stub)')
    end

    it 'returns hello!(stub)' do
      expect(Test.new.test_method).to eq('hello!(stub)')
    end
  end
end
```

これでも一応動くのですが、はじめにも書いたように `allow_any_instance_of` は非推奨なので、今回はこれを `instance_double` を使った形に書き換えます。

# instance_double を使ったテスト
先ほどのスペックファイルを `instance_double` を使って書き換える

```ruby:test_spec.rb
require_relative 'test'

describe 'Test' do
  context 'test_method' do
    it 'returns hello!(stub)' do
      hoge_moc = instance_double(Hoge)

      allow(Hoge).to receive(:new).and_return(hoge_moc)
      allow(hoge_moc).to receive(:hello).and_return('hello!(stub)')

      expect(Test.new.test_method).to eq('hello!(stub)')
    end
  end
end
```

`Hoge` で `new` メソッドを呼ばれた際に、`instance_double` で作ったモックを呼ぶようにしています。
このテストも書き換え前のテスト同様ちゃんと通ります。

# おわりに
今回は書き換え前後をただメモ感覚で書き殴っているだけですが、ちゃんと理解したらまた追記するなり別の場所で書くなりしたいと思います。
書き換えの方法もこればっかりではないと思うので、このあたりについてはまた記事にしたいですね。
Laravelのeloquentでjoinしたときに同じカラム名でバグる可能性

aテーブルのid=1
と
bテーブルのid=2でa_id=1だとして、
これをjoinすると

```php
$a = A::join('b', 'a.id', '=', 'b.a_id')->first();
```

とする。

このとき

```php
$a->id; // 2
```

となる現象が起きました。
同じidというカラム名だからっぽいです。
このままだとidをキーにするのでリレーションで辿るデータなどがうまくとれないなど発生します。
知らないと結構やらかしそうな内容です。

回避は

```php
$a = A::select('*', 'a.id as id')->join('b', 'a.id', '=', 'b.a_id')->first();
```

とかですね。
あとはこれを起こさないためのグローバルスコープなんかもissueに書かれてました。

```php
trait OnlyMyColumnsTrait
{
    public static function bootOnlyMyColumnsTrait()
    {
        static::addGlobalScope('only_my_columns', function (Builder $builder) {
            $builder->select($builder->getModel()->getTable().'.*');
        });
    }
}

```

https://github.com/laravel/ideas/issues/347
javascript_const、letの変数宣言とテンプレート文字列、アロー関数

React講座を受講しているため、自分のメモとしてまとめます。

JSは動的型付け言語です。変数の中身を自動的に判定してくれます。
```
const name = 123;
const name1 = "田中さん";
// 変数の型を知りたい時はconsole.log(typeof 変数);
// Javaは静的型付け言語で、型を宣言する必要がある。
// 例：integer int string
```
var変数は簡単に上書きされることと再宣言されることで、大規模な開発ではミスの原因となります。
let変数：　上書き可能、再宣言は不可能
const変数：　上書きも再宣言も不可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067004/7228a8c5-1d25-7879-0fa2-6da40f8c23a5.png)

JavaScriptのオブジェクトや配列については値を変えることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067004/5b164d43-6e62-1782-5069-e625d4ae5b6f.png)

constで定義したオブジェクトはプロパティの変更が可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067004/68e49a7e-fd05-8eec-d9fb-fcc4c76ba4aa.png)

constで定義した配列は中身の変更が可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067004/a6740f3e-a10d-af5f-5d13-de98c2fff729.png)

JSの中に基本constを使います。上書きが必要な変数についてはletを使います。

テンプレート文字列：JSの文字列にコードを埋め込んだ感じです。
構文は＄{}になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067004/dfbaed85-431a-2680-64ea-4c96bfcbe604.png)

アロー関数
・引数は（）を省略することができる
・returnを省略することができる {}は書かない
**アロー関数の書き方**
const 関数名 = (引数)　=> {処理　戻り値};
引数が1個なら（）は不要
- const test = test => test;
処理が1行なら{}不要、returnも省略
- const tax = (price,tax) => price*tax;

```ruby
// アロー関数　関数の名前あり
const getItem = () => console.log("アロー");
getItem();

fruits = ["りんご","バナナ","みかん"];
fruits.forEach(function(input){
    console.log(input);
});
// アロー関数　関数の名前なし
fruits.forEach(input => console.log(input));
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067004/68ac0a4b-89eb-0f72-8c14-fc30dc500a82.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067004/7711a936-18d0-f59b-5809-20efb6b2fbc4.png)

分割代入
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067004/0aa81701-8174-fe58-5547-fc6481a1a61e.png)

**アロー関数filter**
MDNの中に、filter()関数についてこのように説明しています。
- filter() は、与えられた callback 関数を配列の各要素に対して一度ずつ呼び出し、callback が true と評価される値を返したすべての要素からなる新しい配列を生成します。
```ruby
// array.filter()
const scores = [30,40,50,60,70];

const newScores = scores.filter((value)=> value>=40);
console.log(newScores);
```

**アロー関数find()**
MDNの中に、find()関数について下記のように説明します。
-find メソッドは、配列のそれぞれの添字に対して一度ずつ、callback 関数を実行し、callback 関数が truthy な値を返すまで繰り返します。
```ruby
const members = ["本田","田中","中田"];

const member = members.find((value)=> value === "田中");
console.log(member);
```

**array.map()メソッド**
MDN内にmap()メソッドについて下記のように解釈しています。
- 与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列を生成します。
```ruby
const userList = [10,20,30,40];
// 文字列とくっ付けるには'${}' バッククォート
const userIdList = userList.map(value => `user_${value}`);

console.log(userIdList);
// logの代わりtableを書くこともできる tableは表形式に表示する
console.table(userIdList);
```
[Golang] [GCP] grpc-gatewayがbackend serverにX-Cloud-Trace-Contextヘッダーを渡す方法

## やりたいこと

`grpc-gateway`がHTTP/1.1で受け取ったリクエストヘッダー`X-Cloud-Trace-Context`の情報を
BackendへgRPCで通信するときにも伝搬してBakend側で使用したい。

## 想定しているアーキテクチャ

![grpc-gateway_grpc.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335866/7a600ef0-fd84-84be-a782-072fd3b592a8.jpeg)



## grpc-gateway側の設定

muxを作成する際に、http headerを伝播するオプションをセット。
`runtime.WithIncomingHeaderMatcher()`を設定しない場合、header情報は伝搬されない。

```go
mux := runtime.NewServeMux(runtime.WithIncomingHeaderMatcher(matcher))
```

`matcher`で伝搬したいheaderのみ指定することもできる。
> This matcher will be called with each header in http.Request. If matcher returns true, that header will be passed to gRPC context. To transform the header before passing to gRPC context, matcher should return modified header.
https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime#WithIncomingHeaderMatcher
```go
func matcher(key string) (string, bool) {
	if key == "X-Cloud-Trace-Context" {
		return key, true
	}
	return "", false
}
```

## Backend側の設定

Backend側で`X-Cloud-Trace-Context`を取得するためには
Controller層などのgrpcのpb serverに登録している関数が`context`を受け取ったあとに、
`metadata`を取り出すことでHttp Headerを取り出せる。

```go
import (
    "context"

	"github.com/example/controller"
	"github.com/exmaple/pb"
	"google.golang.org/grpc/metadata"
)

// Backend側のController実装の例
func (ec *ExampleController) HelloExample(ctx context.Context, req *pb.ExampleRequest) (res *pb.ExampleRequest, err error) {
    // grpc-gatewayからheader情報はmetadataとして伝搬される
	md, isExist := metadata.FromIncomingContext(ctx)
    // metadataが存在する場合はisExist=true
    // metadata.Get(key string) []string　を使用してheader情報を取得する
	traceContext := ""
	if isExist && len(md.Get("X-Cloud-Trace-Context")) > 0 {
        // []stringなのでindex=0を指定して取得
		traceContext = md.Get("X-Cloud-Trace-Context")[0]
	}
	

	..

	return res, err

}
```
## Sample

TODO: そのうちにつくってgithubのurlを貼ります。。


## 参考した記事
https://note.com/dd_techblog/n/nd902b7ef8088#Gnoko
【Flutter】api通信がAndroidでのみうまくいかない件

# 何があったのか？
GitHubApiを使用した通信処理がAndroidでのみ失敗して詰まったので、備忘録を残しておく。

# 解決法
#### AndroidManifest.xmlにネットワーク権限を追加
以下のようにandroid / src / main /AndroidManifest.xmlに\<uses-permission\>の記述を加えるとネットワーク権限が加えられ、api通信もできるようになります。

```
<manifest xmlns:android...>
 ...
 <uses-permission android:name="android.permission.INTERNET" />
 <application ...
</manifest>
```

# 参考
https://stackoverflow.com/questions/64120563/flutter-android-http-get-never-returns-in-release-mode
[Flutter] テスト実行時にMissingPluginExceptionが発生する

# Overview

Flutterのテスト実行時に以下のようなエラーが出現するようになった。
```
> flutter test
...
00:10 +0 -9: /path/to/test.dart: hogehoge scenario [E]
  MissingPluginException(No implementation found for method getApplicationDocumentsDirectory on channel plugins.flutter.io/path_provider_macos)
  package:flutter/src/services/platform_channel.dart 175:7  MethodChannel._invokeMethod
...
```

### 環境
```
❯ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.10.2, on macOS 11.5.2 20G95 darwin-arm, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1)
[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.1)
[✓] IntelliJ IDEA Community Edition (version 2021.2.1)
[✓] VS Code (version 1.63.2)
[✓] Connected device (1 available)
[✓] HTTP Host Availability

• No issues found!
```


# 原因
Dartのunit test実行時はpluginをそのまま使うことはできないらしい。

https://github.com/flutter/flutter/issues/96460

（参考）
https://github.com/flutter/flutter/issues/95970


# 解決法
使おうとしているpluginのMockを定義すれば解決する模様。

今回はテスト実行時に`getApplicationDocumentsDirectory`でパスを取得しようとして失敗しているっぽいので、以下のように`setUpAll()`でMockを定義するように変更したところ、エラーが発生しなくなった。

```dart
  setUpAll(() {
    TestWidgetsFlutterBinding.ensureInitialized();
    const MethodChannel channel = MethodChannel('plugins.flutter.io/path_provider_macos');
    channel.setMockMethodCallHandler((methodCall) async {
      return ".";
    });
  });
```
[初心者向け][エンジニア的思考]  情報とは何か？ 情報は武器である？

## 「情報」ってなんだよ！？

当たり前のように日本語で出てくる「情報」って言葉。

IT : Information Technology（情報テクノロジー）で代表されるようにソフトウェアは「情報」を扱うことがほとんどです。「情報」ってのははとっても大事なんです。

**情報とは「知らせ」のことです。**

相手に何かを伝える、その時のその「何か」が「情報」です。
文章かもしれないし、絵かもしれないし、音かもしれないし、刺激かもしれない、それです。

では情報の価値や情報の量というのはどうやって考えればいいのでしょう？

### 情報の量とは「意外性」のこと

例えば、

「黒いカラスがいた」

これはあまり価値ある情報ではなありません。
ほとんどのカラスが黒いからです。

「白いカラスがいた」

これは驚きます。
白いカラスがいる確率はほとんどないからです。
これは価値ある情報です。

どれだけ相手が知らない・相手が驚く情報かによって情報の量が決まります。
どれだけ置きづらいことかによって情報の量（価値）が決まってきます。
ちょっと大げさに言い換えると「出現確率が低い」≒「みんながあっと驚く」情報が価値が高いということです。

### 情報は武器である……なんて言いますが

ここで言う「情報」って何でしょう。
情報は情報ですが、じゃあ、どんな情報でもいいのでしょうか？

北海道の○○市のカラスは黒い、その隣町のカラスも黒い、○○県のカラスも黒い……

これは武器にならないです。情報の量が少なすぎます（価値が低すぎます）。

武器になる情報はあくまで情報量のある価値の高い情報です。
それは「相手があっと驚くような」ものである必要があります。

武器になるのは**単なる空っぽの情報じゃなくて相手が何を知りたいのかそして何を知らないのかを元にした「情報」です** という話でした。


## [中級者向け] シャノンの情報エントロピー

勘のいい方はお気づきと思いますが👆は情報エントロピーの話です。

別にシャノンを知らなくても仕事はできますが「情報」という言葉への感度があがるとエンジニアとしては少しだけものの見方がかわってきますのでもし興味ある方いましたらシャノンなどもご一読ください。
Flask+nginx+uwsgiでの環境でchdirはつけろよな

# 概要
dockerにてFlaskを動作する環境を作りたくて色々試行錯誤
そのときに他の記事を書いている方の内容を参考に作っていたのだがどうしても動作せず…。
なぜ…。
そのときに気づいた内容を自分の備忘録がてら記載しておく

## ローカルでは動くけどdocker環境じゃうごかないのはなぜ？
flaskをつかってWebアプリを作っていたけどどうしてもDBを触る機会が出てきそうなので早いうちにdockerに移行してローカルを圧迫しないようにしたかった。
だけど実際動かすには、uwsgiが必要とのこと…。
今回は、詳しくは話さないのでuwsgiを詳しく知りたい人はこちらのサイトを見てください。
[uWSGI入門](https://www.python.ambitious-engineer.com/archives/1959)

その中でどうしても動かない理由がわからなかったのでnginxやuwsgiの設定を確認していく中で必要項目があった。

それは…****uwsgiの設定にアプリのプロジェクトルートを指定しろ****っということ
これdockerの開発環境を作っているだけじゃわからない事象でした…。

結局作ったコードは以下に記載する

### uwsgi.ini
```ini
[uwsgi]
wsgi-file = main.py
callable = app
master = true
processes = 1
socket = :3031
chmod-socket = 666
vacuum = true
die-on-term = true
py-autoreload = 1

chdir = /var/www/ #<-これが大事
wsgi-file = /var/www/app.py

# log関係
logto = /var/log/uwsgi/%n.log
touch-logreopen = %(base)/.logreopen_trigger
```
このchdirがなければアプリのプロジェクトルートがわからなくてそもそも起動しないっぽい
正直どの記事も乗ってなくてuwsgiを確認していく中で見つかった…。
ハマっちまったよ…。

### nginx.ini
```ini
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    upstream uwsgi {
        server uwsgi:3031;
    }

    server {
        listen 80;
        charset utf-8;

        location / {
            include uwsgi_params;
            uwsgi_pass uwsgi;
        }

    }
}

```

### docker-compose.yml

```yaml
version: "3"
services:
  uwsgi:
    build: ./python
    volumes:
      - ./app:/var/www
    ports:
      - 3031:3031
    tty: true
    command: uwsgi --ini /var/www/uwsgi.ini
    environment:
      TZ: "Asia/Tokyo"
  web:
    build: ./nginx
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - /tmp/nginx_log:/var/log/nginx
    links:
      - uwsgi
    ports:
      - 4231:80
    environment:
      TZ: "Asia/Tokyo"
```

## 締め
今回改めて公式の必要性を感じた
こういうちょっとしたことでかなり詰まってしまうことなんて多々ある
公式や使うならちょっとドキュメントをさらっと読んでおくとちょっとした内容につまらなくて良くなる
ちゃんとしよう…。
Twitch Emotesの画像URLリンク一覧の取得 【windows, twitch API】




# Twitch Emotesとは

動画配信サイトであるtwitchで利用できる絵文字たちのことです。

https://twitchemotes.com/

ずいぶん昔にはこの絵文字たちの画像URL一覧がJSONで提供されていたようなのですが、
現在アクセス先が見当たらず、自分でJSONを作ってしまおうという記事です。

類似記事として

https://qiita.com/pasta04/items/750d71d41e5edd12932b

https://qiita.com/pasta04/items/2ff86692d20891b65905

があります。

登録方法は上記リンクで網羅されているので、私は箇条書き程度での紹介にさせていただきます。


# 登録からAPIを触るまで

1. Twitchデベロッパーに登録 https://dev.twitch.tv/console
2. 二段階認証を有効化
3. アプリケーションを登録、とりあえず名前適当に決めてローカルホストを指定
4. 管理タブからidをメモして、シークレットキーを生成
5. ツイッチcliをダウンロード　https://github.com/twitchdev/twitch-cli/releases
6. twitch.exeをコマンドプロンプト上にドラック＆ドロップ
7. 続けて「token」と入力して、id、シークレットキーで認証を通す
8. 「api get /chat/emotes/global」の入力でグローバルエモートの一覧が得られる


あとはコマンドプロンプトの出力をjsonに保存するだけなので


```
twitch.exe api get /chat/emotes/global >C:\Users\user\Desktop\json\emote.json
```


# おわり

**twitchemotes.com より**

twitch emotesやbadgeの権利はクリエイター・オーナーに帰属するようです。
クリエイター・オーナーの許可のもとで利用を行ってください。
Quantum-secured blockchain ②

前回の記事の続きになります．

[Quantum-secured blockchain ①](https://qiita.com/0917laplace/items/5c2f499251a67ca2777a)

[参照論文](https://arxiv.org/pdf/1705.09258.pdf)

既存のブロックチェーン技術に量子アルゴリズムを組み込むことを始めて提案した論文です．
前回は論文の大雑把な内容を解説しただけなので，今回は具体的なプロトコルやどこにQKDの技術を使うのかについて解説します．

# 通信プロトコル
それぞれのノードは２層に分かれていて，大雑把には，

- 上層がQKDネットワークで，秘密鍵を伝送する
- 下層がタグ付きのメッセージを伝送する

のように分かれています．

また，これらはブロードキャストプロトコルとします．つまり，$n$ 人の個々のノードを全員で管理する方式です．

まず，上層のQKDネットワークですが，特にプロトコルに指定はなく，BB84プロトコルでもE91プロトコルでもその辺は関係なさそうです．とにかくQKDであればなんでもいいっぽい．

下層では，上層での秘密鍵を使った Toeplitz hash を用いて，タグ生成をします．

また，この論文で提案されているプロトコルは，broadcast プロトコルになっています．


# 古典との違い
大きくは2つあって，マイナーの廃止とフォークが起こらない，ということです．

マイナーの廃止
理由としては，これも２つあって，まず，メッセージに署名がつかないためです．これがOKになると，任意のトランザクションがブロックに含まれてしまいます．
そして，量子と古典的なノードが混在した状況において，量子的なノードの方が古典ノードより新しいブロックを作り出すのが早いためです．さすがにこれはだめで，51%攻撃のようなものが起こりうる状況となってしまいます．

フォークが起こらない
これは，今回提案されているプロトコルがブロードキャストプロトコルのためです．全員で新しいブロックを合意するので，フォークが起こる可能性がないのです（マイナーもいませんし）．

# 今後やること
具体的にどういうプロトコルなのかはイマイチ掴めなかったのですが，次のステップに進もうと思います（何かわかったことがあれば，この記事のリメイク版を出します）．
この論文自体まだ2018年のものなので，まだまだ新しいと分かります．最新内容をキャッチアップするのもそこまで時間がかからないかなと思うので，一旦量子ブロックチェーンに関する論文を洗い出そうかなと思います．
ひとまず，今回のQKDネットワークでどのようなプロトコル（BB84, B92, E91とか）を使うのかで違いも出てくると思うので，次に読むのはそれらを使うと，古典とどのように違うのかなど調べていきたいです．
OSINT Tips: How to view surveillance camera footage in Bings Map

# 紹介

基本的にOSINTでジオロケーションを行う場合、大抵はGoogleで解決することが多い。

しかし、Google Street ViewやGoogle Earthでは過去を見ることはできるが、現在進行形で現状を把握することはできない。

もしあなたが抗議デモの群衆の様子を把握したかったり、旅行にいけない代わりに景色を見たかったりする場合はBings Mapをおすすめする。

Bings Mapはリアルタイムで現在の様子を見ることができる便利なマップです。

しかし、都市により数に差がありすぎるため、もしあったら使う程度である。

筆者はモスクワ、キエフ、ベルリン、ロンドン、新宿と見てみたが、ロンドンでしか見当たらなかった。

# 使い方

1: まずログイン(https://www.bing.com/maps)

2: 検索ワードで行きたい場所入力
　試しに「London」と入力

3: ZOOMのアイコンに似たのが出るためマウスを当ててみると映像が勝手に流れる。

![スクリーンショット 2022-02-24 21.14.31.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/848369/804963f6-729a-84dc-4e28-2c9601063678.jpeg)

# 参考

https://twitter.com/SEINT_pl/status/1494001956389412867?s=20&t=dfsDCFsgyRX66M1i8fuevg
Route53にサブドメインを登録する手順

# はじめに
ドメイン周りの設定、期間が空くと忘れがちですよね。 (~~自分だけかもしれないですが~~)
なので今回は`Google Domain`にて取得済みのドメインの`サブドメイン`を`Route53`にて管理し、証明書の取得までの流れを記録しておきます。

:::note warn
当記事にて記載されているスクリーンショットは2022年2月24日現在時点でのものになります。閲覧時期によってはレイアウト等が変更されている可能性がありますのでご注意を。
:::

## 前提条件
- AWSのアカウントを所持している
- Google Domain等のドメインサービスにて独自ドメインを所持している

### サブドメインを登録する
[こちら(Route53)](https://console.aws.amazon.com/route53/v2/hostedzones#)にアクセスし

![hostzorn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2175468/23ee3a0d-5729-eb3b-60b4-baad1ce30f46.png)

右上のホストゾーンの作成をクリック

ドメイン名は
`{登録したいサブドメイン名}.{取得しているドメイン名}`を入力してください
他の部分は変更せずにホストゾーンの作成をクリック

![record.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2175468/d68268b6-1293-b9b1-6e7c-4dfd4e3326d4.png)

ホストゾーンの詳細画面に移動したら、
- NS
- SOA
の二つのレコードが存在していると思います(今回は既存の物をスクショしているので他のレコードもありますが・・・)

今回は`NS`と書かれた部分の一番右側にある４つの文を自身が所持しているドメインに適応させる形になります。
今回はGoogle Domainを利用するのでサイトへ行きます

![googledomain.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2175468/c366b214-6f92-653a-48d1-5af9c55d2fe7.png)

上記画像のように左のメニューから`DNS`を選択、`カスタムレコード`欄の`カスタムレコードを管理`ボタンから先ほどの4つのNSを登録していきます。例として
```
Route53に登録したサブドメイン名 | NS | 3600 | 先ほどの文から文末のピリオドを削除したもの
```
行の追加は`このレコードにさらに追加`ボタンを押すことで可能ですので4つ分登録します。
登録が完了しましたら当手順は終了です、次項に続きます。

### 証明書の取得

[こちら(ACM)](https://ap-northeast-1.console.aws.amazon.com/acm/home?region=ap-northeast-1#/welcome)に移動します

![acm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2175468/aef2ec8b-4a00-7c81-7624-c80caf8d91e7.png)

証明書をリクエストの画面まで来ましたら、`完全修飾ドメイン名`の部分に先ほどRoute53に登録したドメイン名を入力します。

:::note info
青く記載の情報部分をクリックすると解説が表示されます。ワイルドカード等の情報が記載されているので必要に応じて確認してください。今回は触れません。
:::

他部分は変更せずにリクエストボタンをクリックします

![acmd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2175468/331849a6-d6ec-1fde-e6e1-ac05e447b7b8.png)

すると上記画像のようなページに遷移します。
本来であればステータスは`保留中の検証`といった文字列になっていると思いますので、もうひと手順を踏みます。

`証明書ID`の文字列をクリックすると、ページ中部に
`Route53でレコードを作成`
というボタンがありますのでそちらをクリックします。すると保留中のドメインが表示されますのでそのまま右下の`レコードを作成`ボタンをクリックすることで当手順の完了です。実際の反映には5分～30分ほどかかるとされています。

## さいごに
今回はサブドメインをRoute53に登録し、証明書をリクエストする手順を紹介しました。
ここまで実行できた場合はALBにつなげるなり、私の場合はkusanagiにてwordpressを建てる際のホスト名に利用しています。SSL設定も簡単ですしね。
何方かのお役に立てることを祈っております。

### 余談
記事を書くのに全く慣れておらず、見辛い部分等多くあったかもしれません。また誤字脱字や認識・手順違いありましたらお気軽にコメントにて教えて頂けると幸いです。ではまた。
ReactでGoogleログイン

## 前提
以前作成した下記記事の環境からスタート

https://qiita.com/sh19982580/items/5f71856c7949c494d769


## react-google-login
`yarn add react-google-login`

## react-router-dom
`yarn add react-router-dom`
`yarn add -D @types/react-router-dom`

※ログインページからサイトトップページに移動したいため、`react-router-dom`を導入

## ログインページの作成

src > componentフォルダ > login.tsx

    import React from "react";
    import { Link } from "react-router-dom";

    export const Login = () => {
    return (
        <>
        <h1>ログイン画面</h1>
        <Link to="/site">サイトへ</Link>
        </>
    );
    };


## サイトトップページの作成
src > componentフォルダ > siteTop.tsx

    import React from "react";
    import { Link } from "react-router-dom";

    export const SiteTop = () => {
    return (
        <>
        <h1>Hello World</h1>
        <Link to="/">ログインへ</Link>
        </>
    );
    };


## app.tsxの編集

app.tsx

    import React, { FC } from "react";
    import { BrowserRouter, Routes, Route } from "react-router-dom";

    import { Login } from "./component/login";
    import { SiteTop } from "./component/siteTop";

    const App: FC = () => {
    return (
        <>
        <BrowserRouter>
            <Routes>
            <Route path="/" element={<Login />} />
            <Route path="/site" element={<SiteTop />} />
            </Routes>
        </BrowserRouter>
        </>
    );
    };

    export default App;

- `react-router-dom`を使ってページを分けれるようにしておく
- `/`でログインページへ
- `/site`でサイトトップページへ

## ここまでで確認
`yarn start`を実行し、ブラウザで`localhost:8111`を入力
`ログイン画面`と`サイトへ`が表示されて、`サイトへ`を押すと`Hello World`が表示されればOK！
 
## Googleログインの導入

    import React from "react";
    import GoogleLogin from "react-google-login";
    import { useNavigate } from "react-router-dom";

    const CLIENT_ID = "作成したクライアントID";

    export const Login = () => {
    const navigate = useNavigate();
    const success = () => {
        navigate("/site");
    };
    const error = () => {
        navigate("/");
    };
    return (
        <div>
        <h1>ログイン画面</h1>
        <GoogleLogin
            clientId={CLIENT_ID}
            buttonText="Googleでログイン"
            onSuccess={success}
            onFailure={error}
            cookiePolicy={"single_host_origin"}
        />
        </div>
    );
    };

- 確認のために作成した`login.tsx`の`<Link>`は削除する

[※クライアントIDが必要なため、作る必要があります。](https://developers.google.com/identity/sign-in/web/sign-in)
`Google Cloud Platform` => `APIとサービス` => `認証情報` => `認証情報を作成` => `OAuthクライアントID` => `ウェブアプリケーション` => `作成` 

## 最後に

1. 実際に作成した`クライアントID`を入れる
1. `yarn start`を実行し、ブラウザで`localhost:8111`を入力

`Googleでログイン`というボタンを押し、ログインが成功、`Hello World`が表示されたらOK！

 ## 参考文献

https://coders-shelf.com/react-router-v6-intro/

https://github.com/anthonyjgrove/react-google-login


https://github.com/remix-run/react-router/blob/main/docs/getting-started/tutorial.md
Automation test

### Something need to be considered before Automation test
#### know what can automation test can do
> because the time cost, labor cost and maintain cost and technology cost . Actually, automation test is much more expensive than you thought.
  
#### 2. Some Test types
 ##### 1. what is Functional test
     >just like a blackbox test, we don't consider the inside. According to the product features etc. to check if the functions meet our needs.
 ##### 2. what is performance test
     > 1. performance tools : timeit， profile, cProfile, line_profiler, objgraph,jmeter etc.
       2. standards： RT， TPS， stability etc.
 ##### 3. what is Stress Test
     > 1. difference between performance test and stress test
 ##### 4. what is Regression Test
 ##### 5. what is unit test
 ##### 6. what is interface test
     > Postman
###### some question below
> 1. how to do the test above
> 2. what tools can we use
> 3. what's the test standards 
  
#### 3. Test Flow
##### 1.prepare test data
  - base data
  - use case data
  - use data delete
##### 2.focus on writing use cases, not the automation tool
  - the important business
  - where has lots of bugs
  - some functions must need to be satisfied 
###### some question below
> 1. how to write effective test cases
> 2. how to deal with bugs? if there's no bug? a lot of bug?
> 3. how to manage use cases
> 4. automation test tools standards: run time, finished alert, covering 
> percent, failed cases rerun etc.
> 5. if your system is based on a cloud platform, how to do tests. Maybe there's some limitations, just like Multi-Factor Authentication (MFA） SF， etc.
##### 3. Get the test result
 > please reference allure
【rspec】画像のテスト

## rspecでの画像の投稿とその表示
``rspec``での画像の投稿をする場合、``Active Storage``を使用する。

>**Active Storageとは**
Amazon S3、Google Cloud Storage、Microsoft Azure Storageなどのクラウドストレージサービスへのファイルのアップロードや、ファイルをActive Recordオブジェクトにアタッチする機能を提供します。 development環境とtest環境向けのローカルディスクベースのサービスを利用できるようになっており、ファイルを下位のサービスにミラーリングしてバックアップや移行に用いることも可能です。
<br>Active Storageは、アプリケーションにアップロードした画像の変形や、PDFや動画などの画像以外のアップロードファイルの内容を代表する画像の生成、任意のファイルからのメタデータ抽出にも利用できます。

## Active Storageセットアップ
``Active Storage``のセットアップをしていく。

```config/storage.yml
test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>
```
## 画像のセット、画像選択

``spec/fixtures``ファイルを作成し、配下に画像をセットしておく。

```rb
require 'rails_helper'

RSpec.describe 'AddState', type: :system do
    let(:admin) { create :user, :admin }
    let!(:article) { create :article}

    before do
        login(admin)
        visit admin_articles_path
        click_on '編集'
        attach_file 'article[eye_catch]', "#{Rails.root}/spec/fixtures/sample.jpg"
        click_on '更新する'
    end

    describe 'アイキャッチの横幅を変更' do
     context '横幅を100~700pxに指定した場合' do
       it '記事の更新に成功し、プレビューでアイキャッチが確認できる' do
        eyecatch_width = rand(100..700)
        fill_in 'article[eyecatch_width]', with: eyecatch_width
        click_on '更新する'
        click_on 'プレビュー'
        switch_to_window(windows.last)
        expect(page).to have_css('.eye_catch')
        expect(page).to have_selector("img[src$='sample.jpg']")
       end
     end
   end

　　　　　　describe 'アイキャッチの位置' do
      it '左寄りにした場合、正常に左寄せに表示される' do
        choose '左寄せ'
        click_on '更新する'
        click_on 'プレビュー'
        switch_to_window(windows.last)
        expect(page).to have_selector('section.eye_catch.text-left')
      end
   end
end
```

**``attach_file 'article[eye_catch]', "#{Rails.root}/spec/fixtures/sample.jpg"``**
``attach_file``にてファイルアップロードしているため、ここで画像を指定している。

**``eyecatch_width = rand(100..700)``**
100~700の間の数値をランダムで``eyecatch_width``に代入している。

**``expect(page).to have_selector("img[src$='sample.jpg']")``**
画像の位置と画像が表示されているか判定している。

**``expect(page).to have_selector('section.eye_catch.text-left')``**
画像が中央位置にあるか判定している。

## 参考記事
[Active Storageについて](https://railsguides.jp/active_storage_overview.html#active-storage%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
[【RSpec】画像の登録と表示についてテストする](https://study-diary.hatenadiary.jp/entry/2020/10/16/133144)
【Laravel】laravel-adminの導入から初期設定まで

# 概要
laravel-adminを利用して、インストールから初期設定までを行います。
実務でLaravelを使う機会があればlaravel-adminを使用する場面があるかもしれないのでこの機会にまずは設定をしていきます。

※Laravelプロジェクトがインストール済みの前提で進めます。

# laravel-adminとは
Laravelで簡単に管理画面が構築できるライブラリです。

ドキュメントやデモサイトなど使用するために必要な資料が充実しており、難しいカスタムを行う必要がなければものすごく簡単に管理画面が構築できます。

[公式ドキュメント](https://www.ritolab.com/entry/208#:~:text=%E7%84%A1%E5%90%8D%E3%82%AF%E3%83%A9%E3%82%B9-,%E6%A6%82%E8%A6%81,%E6%91%A9%E6%93%A6%E3%82%92%E6%B8%9B%E3%82%89%E3%81%99%E3%81%93%E3%81%A8%E3%81%A7%E3%81%99%E3%80%82)

[demoサイト](https://demo.laravel-admin.org/)

# 実際にインストール

#### 1. インストール

```
$ composer require encore/laravel-admin
```

#### 2. laravel-adminのファイルをプロジェクトに追加

```
$ php artisan vendor:publish --provider="Encore\Admin\AdminServiceProvider"
```

#### 3. laravel-Adminの標準テーブルを生成

```
$ php artisan admin:install
```

#### 4. もし管理者ログインデータが消えてしまった場合
こちらは管理者ログインデータが消えた場合に備えて、シーダーファイルを作成します。

laravel adminを実行した後に`php artisan migrate:fresh`などをやると、管理者用ログインデータが消えてしまいます。

万が一に備えて、以下の記事に沿ってシーダーファイルを作成します。

https://qiita.com/ntm718/items/5ea29ee70b50320352c4


# 管理者画面用のコントローラーを作成する
#### 1. コントローラーの作成
[公式ドキュメント](https://www.ritolab.com/entry/208#:~:text=%E7%84%A1%E5%90%8D%E3%82%AF%E3%83%A9%E3%82%B9-,%E6%A6%82%E8%A6%81,%E6%91%A9%E6%93%A6%E3%82%92%E6%B8%9B%E3%82%89%E3%81%99%E3%81%93%E3%81%A8%E3%81%A7%E3%81%99%E3%80%82)には

```
php artisan admin:make UserController --model=App\\User
```

と記載がありますが、Laravel8系からはモデルのディレクトリがapp/Modelsになっていますので、以下コマンドを実行してコントローラーを作成します。

```
php artisan admin:make UserController --model=App\\Models\\User
```

####2. ルーティングを追記

```/app/Admin/routes.php
<?php

use Illuminate\Routing\Router;

Admin::routes();

Route::group([
    'prefix'        => config('admin.route.prefix'),
    'namespace'     => config('admin.route.namespace'),
    'middleware'    => config('admin.route.middleware'),
    'as'            => config('admin.route.prefix') . '.',
], function (Router $router) {

    $router->get('/', 'HomeController@index')->name('home');
    $router->resource('/users', UserController::class); //追記内容
});

```


これで`/admin/users`にアクセスするとユーザーの一覧画面が閲覧できるようになります。

他にも`/config/admin.php`で設定の変更、`Admin / bootstrap.php`でコンポーネントを拡張または削除したり、フロントエンドリソースを導入したりできますが、ここでは特に設定の変更はせず、またの機会に記事にしようと思います。

# 最後に
今回は初期設定からほぼコードをいじらずにインストールから初期設定するという内容でした。
まだまだ勉強中ですが、色々使い方を知って記事にしていきます。
PostgreSQLの識別子は小文字で書こう

PostgreSQLでの識別子に大文字を使うと、Testというデータベースを探したいのにtestと認識され、
```sql
postgres=# drop database Test;
ERROR:  データベース"test"は存在しません
```
と大文字小文字の区別ができず困った！

# 結論
そもそもデータ定義に大文字は使わない方がいい。
そして、もし作ってしまった場合はデータベース名などを""（ダブルクォーテーション）で囲むと良さそうです！
reduce()について

# reduce()とは
typescriptでreduceというものに初めて出会った。
そもそも純粋なjavascriptですら齧った程度だったのでtypescriptには大分へし折られた。
map()やfilter()などであれば何となく知ってはいたが、reduceは知らなかったので備忘録として残す。
聞くところによると初見殺しらしい。

      interface Example {
        id: number;
        name: string;
        beer: string;
      }

    const data: Example[] = [
      { id: 1, name: 'aaa', beer: 'heineken' },
      { id: 2, name: 'bbb', beer: 'badwiser' },
      { id: 3, name: 'ccc', beer: 'kirin' },
      { id: 4, name: 'ddd', beer: 'sapporo' },
      { id: 5, name: 'eee', beer: 'corona' },
    ];

例えばこういったinterfaceと配列が定義されているとする。

    const total = data.reduce((acc: number, val) => {
      return acc + val.id;
    }, 0);

reduceでこんな感じにできる。
accはアキュムレーターと呼ぶらしい。返却する型を設定する。
最後の引数は初期値。
idを全員分足して返却した。
totalは15となる。

    const beers = ['heineken', 'sapporo', 'kirin', 'asahi', 'corona', 'ebisu'];

またこういった配列がやってきたとして、

    interface Beer {
      name: string;
      beer: string;
    }

こういったinterfaceを作成し、

    const beer = beers.reduce((acc: Beer[], val) => {
      const result = data.find((item) => item.beer === val);
      if (result) {
        acc.push({ name: result.name, beer: result.beer });
      }
      return acc;
    }, []);

アキュムレーターことaccを```Beer[]```に設定し、reduceの中でfindを使い、一致するものを```Beer[]```の方にして返却することができる。
beerの中は下記のようになる。

    [
      {
          "name": "aaa",
          "beer": "heineken"
      },
      {
          "name": "ddd",
          "beer": "sapporo"
      },
      {
          "name": "ccc",
          "beer": "kirin"
      },
      {
          "name": "eee",
          "beer": "corona"
      }
    ]

ちなみに、

    interface MadeIn {
      madein: {
        country: string;
        taste: string;
      };
    }

こういった型で、

    const data_2: MadeIn[] = [
      {
        madein: {
          country: 'germany',
          taste: 'good',
        },
      },
      {
        madein: {
          country: 'usa',
          taste: 'good',
        },
      },
      {
        madein: {
          country: 'japan',
          taste: 'good',
        },
      },
      {
        madein: {
          country: 'japan',
          taste: 'good',
        },
      },
      {
        madein: {
          country: 'mexico',
          taste: 'good',
        },
      },
    ];

配列でなくオブジェクトだった場合、

    interface Country {
      country: string;
    }

    const country = Object.values(data_2).reduce((acc: Country[], m) => {
      if (m.madein.country === 'japan') {
        acc.push({ country: m.madein.country });
      }
      return acc;
    }, []);


    [
      {
          "country": "japan"
      },
      {
          "country": "japan"
      }
    ]




```Object.values``` または```Object.keys```などで繋げてやれば使用することができる。
超初歩的かもしれないが初めて知った時驚愕した。

確かに初見殺しであり半殺しくらいにはされたが仕組みが理解できればとても便利だ。
ビールはサッポロ派だ。
テストでタイムアウトしてしまった話

N予備校の4-17「【サービス開発2】プロジェクトの作成と認証の実装
」にて、Routerオブジェクトをテストしていたとき、、、

```javascript:エラーログ
FAIL  test/test.js (49.46s)
  /login
    ✕ ログインのためのリンクが含まれる (14759ms)

  ● /login › ログインのためのリンクが含まれる

    : Timeout - Async callback was not invoked within the 10000ms timeout specified by jest.setTimeout.Timeout - Asyn
c callback was not invoked within the 10000ms timeout specified by jest.setTimeout.Error:

      4 |
      5 | describe('/login', () => {
    > 6 |   test('ログインのためのリンクが含まれる', () => {
        |   ^
      7 |     return request(app)
      8 |       .get('/login')
      9 |       .expect('Content-Type', 'text/html; charset=utf-8')

      at new Spec (node_modules/jest-jasmine2/build/jasmine/Spec.js:116:22)
      at Suite.<anonymous> (test/test.js:6:3)
      at Object.<anonymous> (test/test.js:5:1)

GET /login 200 14665.183 ms - 170
Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        73.928s
Ran all test suites.
Force exiting Jest: Have you considered using `--detectOpenHandles` to detect async operations that kept running afte
r all tests finished?
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
```

こんなエラーが！

## 原因
```Timeout - Async callback was not invoked within the 10000ms timeout specified by jest.setTimeout.Timeout```というところからPCに負荷がかかったり、メモリの影響で時間がかかってしまうみたい。

## 結論
```json:package.json
"scripts": {
    "start": "node ./bin/www",
    "test": "jest --testTimeout=10000 --forceExit"
  },
```
の```--testTimeout=10000```を自分の環境(メモリなど)に合うように```15000```とかに調節してあげる
だから、package.jsonは
```json:package.json
"scripts": {
    "start": "node ./bin/www",
    "test": "jest --testTimeout=15000 --forceExit"
  },
```
などにしてあげるとOKです！
【C#】ValueObject作成時のGetHashCode()のオーバーライドの実装方法

# 前提知識(知っている方はスキップ推奨)
### そもそもValueObjectって何？
ざっくりいうと、システム固有のオブジェクト(独自型)です。
値が持つビジネスルールを表現することができます。
詳しくはググってみてください。

### そもそもハッシュ関数って何？
入力されたデータを"何らかの値"にして返却する関数です。
"何らかの値"を生成するときは、ある一定のルールに従って行われます。
したがって、同じ値をハッシュ関数に与えると、同じ値が返却されます。
尚、ハッシュ関数が返却する値を**ハッシュ値**と言います。

# ValueObjectが単一の値しか持たない場合
プロパティに対して`GetHashCode()`をするだけでOKです。

```c#
public class Id
{
	public int Value { get; set;}
	// ...略
	public override int GetHashCode()
	{
		return Value.GetHashCode();
	}
	// ...略
}
```

## ValueObjectが複数の値を持つ場合
### C#7以降の場合tupleを使用する

```c#
public class Name
{
	public string First { get; set;}
	public string Last { get; set;}
	// ...略
	public override int GetHashCode()
	{
		return (First, Last).GetHashCode();
	}
	// ...略
}
```

### .NET Standard2.1以降の場合`HashCode.Combine`を使用する

```c#
class Name
{
	public Name(string first, string last)
	{
		First = first;
		Last = last;
	}

	public string First { get; set; }
	public string Last { get; set; }
	// ...略
	public override int GetHashCode()
	{
		return HashCode.Combine(First, Last);
	}
	// ...略
}
```

### その他、自力でやる場合は素数をかけて排他論理和をとる

```c#
class Name
{
	public Name(string first, string last)
	{
		First = first;
		Last = last;
	}

	public string First { get; set; }
	public string Last { get; set; }
	// ...略
	public override int GetHashCode()
	{
		return (First.GetHashCode() * 397) ^ Last.GetHashCode();
	}
	// ...略
}
```

### 適当にやるとどうなる？
例えば、`return First.GetHashCode() ^ Last.GetHashCode();`のようにしてしまうと、
値がひっくり返っている場合に同一のハッシュ値となってしまいます。
上述のNameクラスで例えると、
「吉野 葵(よしの あおい)さん」と「葵 吉野(あおい よしの)さん」は別人です。
しかし、`return First.GetHashCode() ^ Last.GetHashCode();`という実装だと
ただの排他論理和のため、
「吉野 葵(よしの あおい)さん」と「葵 吉野(あおい よしの)さん」のハッシュ値が同一となってしまいます。
説明した上記3つの例では、違うハッシュ値が返ります。

## まとめ
- ValueObjectが単一の値しか持たない場合
  - `return Value.GetHashCode();`でOK
- ValueObjectが複数の値を持つ場合
  - tuppleを使う:`return (First, Last).GetHashCode();`
  - `HashCode.Combine`を使う:`return HashCode.Combine(First, Last);`
  - 素数+排他論理和を使う:`return (First.GetHashCode() * 397) ^ Last.GetHashCode();`

## 参考文献
- [ハッシュ値を組み合わせる](https://hassakulab.com/knowledges/csharp-combine-hashes/)
- [【C#】ValueObjectの実装例](https://takap-tech.com/entry/2021/02/03/232823)
- [ハッシュ関数 (hash function)とは](https://wa3.i-3-i.info/word11948.html)
SSL通信で中間CA証明書の検証はどうやってるのか

# はじめに

SSL/TLS について調べていたところ、中間 CA 証明書の検証で「OCSP」という単語が出てきたので、現時点でわかったことをまとめる。

# SSL/TLS 通信の仕組み

そもそもの SSL/TLS 通信の仕組みは以下。（https://ssl.sakura.ad.jp/column/ssl/ より引用）

> 1. ブラウザ：SSL 通信をリクエストする
> 2. サーバー：SSL 証明書を送付する
> 3. ブラウザ：電子署名の検証により「SSL 証明書に記載されたドメイン」と「通信先のドメイン」が同じであることを確認する
> 4. ブラウザ/サーバー：SSL 通信を行うために共通鍵を交換する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352836/34de279e-34a9-4610-7aac-f959fd068d5c.png)
（https://ssl.sakura.ad.jp/column/ssl/ より引用）

2, 3 の部分で使われるサーバーの証明書は通常、ルート CA が発行するのではなく、中間 CA が発行する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352836/2e8cbd81-2710-bca2-4d69-4748d6e5141b.png)
（https://www.cybertrust.co.jp/sureserver/support/faq/442g976c4sgy.html より引用）

サーバーの証明書は中間 CA の秘密鍵によって署名され、中間 CA 証明書によって署名の検証ができる。
また、中間 CA 証明書はルート CA の秘密鍵によって署名され、ルート CA 証明書によって署名の検証ができる。

ブラウザでは、SSL 通信を始める際にサーバーからの受け取った証明書を検証し、正当であるかを判断する。
上記にある通り、サーバーの証明書を検証するためには中間 CA 証明書を使う必要がある。そこで、中間 CA 証明書が正当なものなのかを確かめる必要がある。検証するにはルート CA 証明書が必要である。
PC などのデバイスにはルート CA 証明書が出荷時から入っており、ブラウザはそのルート CA 証明書を使い検証をすることができる。

このようにルート CA 証明書で中間 CA 証明書を検証し、検証された中間 CA 証明書でサーバーの証明書を検証する仕組みとなっている。

# 証明書が失効した場合はどうするのか？

では、もしルート CA 証明書や中間 CA 証明書がなんらかの原因（秘密鍵が流出したなど）で失効した場合はどうするのか？

ルート証明書の場合は、PC に出荷時から入っているため、新しい証明書に切り替えるのは簡単ではない。調べたところ、Windows Update のような更新で証明書の更新が行われるらしい。

では、中間 CA 証明書の場合はどうするのか？

証明書が失効したからといって、ルート CA 証明書での検証が失敗するわけではない。
そこで、出てくるのが**OCSP サーバー**である。

# OCSP とは

> OCSP（Online Certificate Status Protocol）とは、単一の証明書のステータスについて確認するための http プロトコルです。

（https://www.digicert.co.jp/welcome/pdf/wp_ssl_handshake.pdf より引用）

中間 CA 証明書の公開鍵ハッシュ値などを OCSP サーバーに送り、証明書のステータス（good, revoked, unknown）を返してくれるサーバーのこと。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352836/902a0136-b360-385a-f42e-720440fa3ed7.png)
（https://www.digicert.co.jp/welcome/pdf/wp_ssl_handshake.pdf より引用）

SSL 通信を開始する際に OCSP サーバーに問い合わせ、有効であることを確認してから SSL 通信を開始することができる。

また、OCSP サーバーのレスポンスが改ざんされていないことを保証するために、OCSP サーバーからのレスポンスは署名されている。（この署名はどうやって検証しているのだろう？）

# さいごに

中間 CA 証明書の検証についてどうやっているのかは大方イメージがついた。
OCSP サーバーからのレスポンスの署名検証がどのようにやっているのかは気になる。

また、CRL や OCSP ステープリングについてももう少し調査をしてみようと思う。

# Ref

- [SSL って何？意味や仕組みをわかりやすく解説！ | さくらの SSL](https://ssl.sakura.ad.jp/column/ssl/)
- [クロスルート方式とは？｜ SSL/TLS サーバー証明書 SureServer ｜サイバートラスト](https://www.cybertrust.co.jp/sureserver/support/faq/442g976c4sgy.html)
- [wp_ssl_handshake.pdf](https://www.digicert.co.jp/welcome/pdf/wp_ssl_handshake.pdf)
- [サーバー証明書／中間 CA 証明書／ルート証明書の違いとは？ | さくらの SSL](https://ssl.sakura.ad.jp/column/difference-in-ssl/)
- [何度も短縮し過ぎ？！SSL 証明書の有効期間がどんどん短くなる理由とは？ | さくらの SSL](https://ssl.sakura.ad.jp/column/shortened-ssl/)
- [2020 年 7 月に中間 CA 証明書の大量失効が発生！概要や対処方法とは？ | さくらの SSL](https://ssl.sakura.ad.jp/column/mass-revocation-202007/)
- [SSL 証明書の失効・無効化とは？ | さくらの SSL](https://ssl.sakura.ad.jp/column/revocation/)
- [サイト制作/管理者必見！SSL 化がサイトの障害原因だった！？SSL 証明書の思わぬ落とし穴とは？ | さくらの SSL](https://ssl.sakura.ad.jp/column/ssl-failure/)
【現役エンジニアが語る】ネットワークエンジニア（設計・構築・運用）の仕事内容


## はじめに
こんにちは、日本リック エンジニア採用チームです。

今回は当社ベテランエンジニアのHさんにお話を伺いました。
Hさんは日本リックに中途入社して15年目のベテラン社員。入社当初は某官公庁向け保守障害対応をベンダー側サポート業務に従事。その後、CCNAの資格を取得して、ネットワークエンジニアとして設計・構築・運用の仕事をしています。

Hさんの仕事内容や、ネットワークエンジニアに必要なスキル・能力、資格、向いている人などを教えてもらいましたので、ネットワークエンジニアを目指している方の参考になれば嬉しいです。


## 私のプロフィール（40代前半・男子）

### 現在の職種
某通信キャリアにて社内ネットワーク構築及び運用業務に携わってます。

### 前職
前職は某セキュリティソフト会社にて、サポート業務に携わっていました。
電話、E-mail・FAXでのユーザーサポートからリーダー業務に至るまで行っていましたが、先の展望が考えにくかったため、転職しました。

## ネットワークエンジニアで働く私の仕事内容
主な仕事内容としては、それぞれ以下のようなことを行っています。

### 【設計・構築】
・社内ネットワークの中で制限をかけている箇所の穴あけや規制
・機器のIF等設定変更
・各拠点への機器増設や新規拠点の構築
・各システムとの接続(ルーティング等)

### 【運用】
・IPの管理(払出・返却等)
・NW機器の管理(在庫機器の入庫・出庫等)
・社内及び関連会社ユーザーからの問い合わせ回答
・動作している機器の停止調整
・接続システムの管理
・監視ソフトへのOAサーバの監視登録や変更・削除


## ネットワークエンジニアに必要なスキル・能力
機器の知識やNW機器のコマンドなどは勿論知っていた方がいいですが、ユーザーとの調整やヒアリング、関連部署とのやり取りなどメールでのやり取りや電話やTeams会議等必要に応じて対話は必要になります。

どういう風な言葉で伝えれば必要な情報が引き出せるかなど、そういった能力が高い方がスムーズに業務に当たれると思いますし、トラブル発生時には状況の説明が簡潔にまとめられると、伝わりやすいので必要な能力です。

## ネットワークエンジニアに役立つ資格
基本的には、ネットワーク系の資格である、

**CCNA**や、
**ネットワークスペシャリスト**など
を持っていると、内容の理解が早まると思いますが、持っていなくても自主的に勉強して”用語”や”仕組み”をある程度理解しているとよいと思います。

## ネットワークエンジニアに向いている人
これは、ネットワークエンジニアに限ったことではないですが、エンジニア＝知識や技術さえあれば良いというわけではないので、相手の言っていることが１０の内２ぐらいであっても、そこからどういうことを言いたいのかを理解出来たりする人は、色んな現場で対応できるような素養を持っていると思います。


## これからネットワークエンジニアを目指そうと思っている方へ
あまり難しく考えずにやりたいと思ったら、気軽にネットワークに触れてみるという位の考え方でいいかなと思います。

技術は後からついてきますので、興味さえ持てれば、あとはその興味を膨らませていって、色々と勉強しても良いですし実機に触れてみたりして、少しずつ理解していきそれを楽しいと感じられれば、もうエンジニアの一歩を踏み出しています。
まずは、その一歩を踏み出してみましょう!!
Cloudwatch logs insight のクエリ結果でアラーム設定する

Cloudwatch logs insightは、クエリ的にログ検索ができるが、検索結果をそのままメトリクス化して監視やアラーム設定することができない。同じくCloudwatchのロググループにメトリクスフィルタを設定することでメトリクス化できるが、Cloudwatch logs insightほど複雑なフィルタ条件は設定できない。

# 前提条件
Cloudwatchを使ったログ収集をしていること
AWS CLIが実行できる環境があること
jqが実行できる環境があること

# Cloudwatch logs insightの結果をメトリクス化する
一定時間毎にCloudwatch logs insightにクエリした結果を、メトリクス化する。
shell scriptで、AWS CLIを使ってCloudwatch logs insightの情報を取得し、さらにCloudwatchのメトリクス として設定します。

## AWS CLIを使ったscriptの準備
AWS CLIを使ってCloudwatch logs insightの情報を取得し、ヒット件数をCloudwatchのメトリクス として設定します。AWS CLIが実行できる環境にshell scriptを配置します

```sh:insight_to_metrics.sh
#CLI environment 各自の環境に合わせて設定してください
PROFILE=XXXXXXXX #AWS PROFILE名を設定
AWS_CLI=/usr/bin/XXXXXXXXX #AWS CLIのパスを設定
JQ=/XXX/XXX/jq # jqのパスを設定
C_PASS=/home/XXXXXX #本スクリプトファイルのディレクトリを設定

#Cloudwatch insight
#query time
STARTTIME=`date --date '-30 minute' +%s`
ENDTIME=`date +%s`
#query log name
LOG_GROUP_NAME="XXXXXXXXXX" #クエリ対象のロググループを指定

#Cloudwatch metrics
NAME_SPACE="CWinsight" #メトリクスのNAME SPACEを指定
METRIC_NAME="recordsMatched_COUNT" #メトリクス名を指定

#tmp files
QUERY_FILE=$C_PASS/query.txt
TMP_FILE=$C_PASS/tmp_query_id.txt

#start query
while read line
do
   QUERY=$line
   echo $LOG_GROUP_NAME $QUERY
   QUERY_ID=`$AWS_CLI logs start-query \
   --log-group-name $LOG_GROUP_NAME \
   --start-time $STARTTIME \
   --end-time $ENDTIME \
   --output text \
   --query-string "$QUERY"
   `
   echo $QUERY_ID >> $TMP_FILE
   DIMENSHON=`echo $QUERY | awk '{print substr($0, index($0, "#")+1)}'`
   echo $DIMENSHON >> $TMP_FILE
done < $QUERY_FILE

#wait for query finish
sleep 20s #クエリ時間によって調整すること

#output result
while read line
do
   QUERY_ID=$line
   RESULT=`$AWS_CLI logs get-query-results --query-id $QUERY_ID --output json`
   STATUS=`echo $RESULT | $JQ '.status'`
   # check query status
   if [ $STATUS != \"Complete\" ] ; then
      echo "[ERROR] exit Script" $QUERY_ID $STATUS
      rm -f $TMP_FILE
      exit 1
   fi
   COUNT=`echo $RESULT | $JQ '.statistics.recordsMatched'`
   read line
   echo $line " / query status = "$STATUS " matched count = "$COUNT
   # put Metric data of CloudWatch
   aws  cloudwatch put-metric-data --metric-name $METRIC_NAME --namespace $NAME_SPACE --unit Count --value $COUNT --dimensions insight_script=$line
done < $TMP_FILE

#END script
rm -f $TMP_FILE
```

## query条件の設定
query条件は、変更しやすいように別ファイルで記載、クエリの表記方法はCloudwatch logs insightをGUIで使う時と同じ
shell scriptと同じディレクトリに配置しておく

```sh:query.txt
stats count(@message) | filter @message like "hoge" | filter @message not like "fuga" #hogefuga_count
stats count(@message) | filter @message like "peke" | filter @message not like "poko" #pekepoko_count
```

# 実行
cronで定期実行するようにします
上記の例だと、過去30分のログを対象にqueryしているため、cronも30分毎に設定します
間隔は要件に合わせて設定してください

```txt
15,45 * * * * /home/XXXXXX/insight_to_metrics.sh
```

# 注意点
クエリ対象のログ量が大きい場合、コスト（と実行時間）が増えるので、コストに見合うか判断して利用しましょう
[参考 AWS料金](https://aws.amazon.com/jp/cloudwatch/pricing/)

# 結果
CloudwatchのCustom namespacesにメトリクスとして値が入っていればOK
あとはお好みでアラート設定したり出来ます
![スクリーンショット 2022-02-24 15.47.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989777/af685e16-4c88-7879-0dd7-b33bfb01b936.png)
ポイントサイトの比較サービスでの機能について

ポイント比較サービスを運営しているが、どうも時代の流れが違うのか、顧客の付きが悪い。

ポイントサイトはブロガーの無理な勧誘やSNSでのスパム的な友達紹介があってか、市場の飽和感が否めない感じがする。

ポイントサイトのマイナスイメージもあるが、個人的にはポイントサイトは好きだし、多くの人のお小遣い稼ぎや副業の一環として役立つと思っているので、ぜひサービスの機能向上をして広めて行きたい。

ただ、今のところ多くの方に利用してもらえていない現状があるので、アドバイスや機能追加などの提案があれば、ぜひお願いしたい。

[ポイント比較ガイド](https://pointlife.jp/)

このような「複数のポイントサイトを比較するサービス」だが、他社と比べても機能は勝ってきている。

これにさらに機能追加アドバイスや改善したら良い点、技術的な提案があれば、ご提案頂ければと思う。
【Dr.Sum DataFunnel】ミリ秒単位の時刻の丸めをやってみる


# はじめに

今回は、Dr.Sum DataFunnelでミリ秒単位のデータを丸める処理について書いていきます。
設備から直接送られてくるデータは、ミリ秒単位のデータになっていることが多いですが、
可視化する際には、そこまで細かいデータは必要ないと思います。
その場合に、予めDataFunnelでデータを丸めることができます。
![funnel1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656849/b0ccf48e-3a62-5d76-6f1a-4d8128316cb3.png)

# 2.パイプライン定義を作ってみる

今回は、以下のようなシンプルなデータを使っていきます。
※一部抜粋※
```sample.csv
jikan,value
2022/02/22 15:11:19.968537,0.900973862
2022/02/22 15:11:19.968537,0.916207125
2022/02/22 15:11:19.968537,0.959604765
2022/02/22 15:11:19.968537,0.928447962
2022/02/22 15:11:19.968537,0.904356185
2022/02/22 15:11:19.968537,0.905493181
2022/02/22 15:11:19.968537,0.832456135
2022/02/22 15:11:19.968537,0.867242689
2022/02/22 15:11:19.968537,0.903938056
2022/02/22 15:11:19.968537,0.818963725
2022/02/22 15:11:19.968537,0.849112969
```
では、パイプライン定義を作っていきます。

## 1.取り込むデータの設定
![funnel2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656849/69dacf36-6d06-cf11-52a8-0a7c5e959549.png)
テーブル化の設定等は、一番下の参考サイト等を見てください。

## 2.時刻の丸め設定
左側のメニューから「時刻関連項目の設定」を選び丸め処理を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656849/6a305039-3617-18c5-1751-4cfcf06a91ea.png)

設定はこれだけです！
ではサンプルデータで結果をプレビューで確認していきましょう。

## 3.プレビューで確認
1の取り込むデータの設定で指定したデータを使っていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656849/47b5a98b-baa5-55be-bcf5-ba0b6eb7c209.png)
設定をしながらプレビューで結果を確認できるので、便利ですよね！

左側のメニューで「データ処理」を選択し、プレビューを見ていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656849/8794cb82-c9c4-9631-bed4-d10a08abc644.png)

新たに「TIME_5COUNT」という項目が追加され、時刻が丸められていますね！
これだけでも十分かと思いますが、せっかく時刻を丸めていくなら、他の値もサマリして全体のレコード数を省略していきたいと思います。
ミリ秒オーダーのデータを細かく見ないのに、そのままデータとして残すのは、容量だったりパフォーマンスに影響しそうですよね。

## 4.SQLでグループ化
SQLで簡単にグループ化をしていきます。
入力データ項目をドラッグ＆ドロップで左側のクエリービルダーにもっていき、グループ化の設定を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656849/cd7d1a5b-0870-3128-6313-9547d781960d.png)

もう一度プレビューすると、データがサマリされているのが分かりますね！！
![2022-02-24_19h04_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656849/deabd55d-5b79-0c02-ea8a-0a4c7560bc92.png)

# まとめ
ここまで出来たら、あとはDr.Sumに格納するだけでおしまいです。
最後に元のデータとDataFunnelで加工して投入したデータを比較してみようと思います。

![final.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656849/7b1e1528-c014-0808-c861-a2c00385f117.jpeg)

加工され、データの総レコード数も少なくなっていますね。
時刻の丸めだけでなく、グループ化でデータをサマリしながら蓄積する方法を紹介しました。
ぜひお試しください！

### 参考サイト
[Dr.Sum Data FunnelでCSVファイルを連携してみた](https://qiita.com/LuiLui/items/ae0ce6b36a68ee134fed)