OmniAICreator/Qiita-1.07M huggingface dataset:
JSで特定の要素だけを選択した状態にする

## やりたいこと
こんな感じで要素をクリックしたときにクリックした要素のみ選択された状態にしたい。
![recommended-books-5-3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/c5c0c3c6-993f-4996-75c7-df53c8a7c17f.gif)

## 実装方針

- clickイベント発火時にクラスを付与
- 付与したクラスに対してcssをあてる
- クリックされていない要素からクラスを外すことで1つだけにクラスが付与されている状態にする

## 実装結果

```jsx
  resultItem.addEventListener('click', (e) => {
          const selectedItems = document.getElementsByClassName('selected')
          if (selectedItems) { //初回は選択状態の要素がないので条件分岐しないとエラーが発生しそう
            Array.prototype.slice.call(selectedItems).forEach(item => {
              item.removeAttribute('class') //一度クラスが付与されたdiv要素を全て外し1つだけ選択されている状態にする
            })
          }
          resultItem.setAttribute('class', 'selected') //選択状態にする
        })
      })
    })
```

まず最初にgetElementsByClassNameでselectedクラスが付与された要素をまとめて取得。
次に取得した要素に対してremoveAttributeを実行する。getElementsByClassNameではHTMLCollectiomが返されるので
forEachを使うためにはArray.prototype.slice.callを用いて一度Array型に変換する必要がある。

ループ処理の中でクラスを除外することで、既に選択された要素からクラスを外し、非選択状態にする。
最後に選択した要素にクラスを付与することで選択された状態にする。

### 参考

- https://bit.ly/3fmtaYw

- https://hacknote.jp/archives/21892/
Laravel heroku S3 500エラーでつまづいた話

## S3のバケットを作成し、herokuでの環境変数も設定したのにherokuで画像アップロードが動かない

画像アップロードをしようとするとserver errorになってしまっていた。
初めはS3への接続の問題かと思ったがローカルでできているし、環境変数の設定も間違っていない。

##解決方法

まず500エラーのみ表示される状態からエラーの内容を表示されるようにする。
herokuでは.envファイルを読み込まないのでAWSのキー設定の他にAPP_DEBUGも設定されていない、つまりはAPP_DEBUG=falseの状態になっている。（本番環境ではfalseにするべき）
そのために以下のコマンドでエラーメッセージを出力されるように設定する
`heroku config:set APP_DEBUG=true`

そして画像アップロードの際のエラーを読むとGD extensionが入っていないとのこと。

なのでcomposer require ext-gdでGDのライブラリをインストールする。

すると画像アップロードに成功した。

つまづいた時はエラーメッセージを表示できるようにして、しっかりと読むこと。


### 追記
S3を使う際にflysystemをcomposerでインストールしたが、バージョン2.0以降だとLaravel8では動作しないので1.0をインストールすること。
画面キャプチャ

<pre>
// Console.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
#include "stdafx.h"
#include <windows.h>


struct  cell{
	HWND hWnd;
	TCHAR WindowName[256];
};

BOOL  CALLBACK  EnumWndProc( HWND hWnd, LPARAM lParam )
{
	TCHAR buff[256];
	GetWindowText( hWnd, buff, sizeof(buff));//ウインドウの文字を取得して、
	if(_tcscmp(buff,((cell*)lParam)->WindowName)==0){//名前が一致したら、
		((cell*)lParam)->hWnd = hWnd;//ウィンドウハンドルを渡す
	}
	return true;
}



int _tmain(int argc, _TCHAR* argv[])
{

	cell c;
	c.hWnd =NULL;
	_tcscpy_s(c.WindowName, TEXT("電卓"));//検索するウィンドウの名前

	EnumWindows( EnumWndProc, (LPARAM)&c);

	if(c.hWnd != NULL){
		//目的のウインドウハンドルが取得できました
		//SetWindowPos(c.hWnd,HWND_TOP,0 ,0 ,100,100,SWP_SHOWWINDOW);//ウインドウのサイズを変更
	}
	else {
		return 0;
	}

	#if 0	// 横
		#define X	28
		#define Y	101
		#define W	(78 - 1)
		#define H	(60 - 1)
	#else
		#define X	37
		#define Y	92
		#define W	(60 - 1)
		#define H	(78 - 1)
	#endif

	

	OpenClipboard(NULL);

	HBITMAP  hBitmap;
	HDC hDC;
    HWND hWnd = c.hWnd;	//GetForegroundWindow();
	hDC = GetDC(hWnd);

	HDC destDC;



	destDC = CreateCompatibleDC(hDC);
	hBitmap = CreateCompatibleBitmap(hDC, W, H);

	SelectObject(destDC, hBitmap);
	BitBlt(destDC, 0, 0, W, H, hDC, X, Y, SRCCOPY);

	if (0) {
		HPEN hPen;
		hPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
		SelectObject(destDC, hPen);
		MoveToEx(destDC, 0, H-1, NULL);
		LineTo(destDC, 2, H-1);
		MoveToEx(destDC, W-1, 0, NULL);
		LineTo(destDC, W-1, 2);
	}


	EmptyClipboard();
    SetClipboardData(CF_BITMAP, hBitmap);
    CloseClipboard();


	return 0;
}

</pre>
PHP strcmp() とstrcasecmp()、関連して宇宙演算子での比較も

#strcmpとstrcasecmpについての検証結果
双方ともに第一引数と第二引数を比較して第一引数より第二引数が大きければ負の値。小さければ正の値、同じなら０を返す。


例）

```php
<?php
//strcmpは大文字小文字を区別する。strcasecmpは大文字小文字を区別しない
echo strcmp('a','A')."\n";//32
echo strcasecmp('a','A')."\n";//0
echo strcmp('a','b')."\n";//-1
echo strcasecmp('a','b');//-1
```
- **strcmpは大文字小文字を区別する。strcasecmpは大文字小文字を区別しない**
- **小文字の「a」の方が大文字の「A」よりも大きい（比較すると32が出る為）**
- **aとbではbの方が大きい（比較すると-1が出る為）**

#strcmpについての検証結果


例）

```php
<?php 

$a = strcmp('a','b');
var_dump($a);//-1

$a = strcmp('a','f');
var_dump($a);//-5

$a = strcmp('a','eab');
var_dump($a);//-4

$a = strcmp('c','b');
var_dump($a);//1

$a = strcmp('b','b');
var_dump($a);//0

$a = strcmp('あ','い');
var_dump($a);//-2

$a = strcmp('あ','う');
var_dump($a);//-4

$a = strcmp('あ','あ');
var_dump($a);//0
```

#strcmpで文字列の数字の比較をする場合

例）

```php

//  -5200の方が小さいと出力の例2点-
//例）１
if(strcmp('5200',"621")> 0){
    echo '5200方が大きい'."\n";
}elseif(strcmp('5200',"621")===0){
    echo'等しい'."\n";
}else{
    echo'5200の方が小さい'."\n";
}

//例）２
if(strcmp('5200',"521")> 0){
    echo '5200方が大きい'."\n";
}elseif(strcmp('5200',"621")===0){
    echo'等しい'."\n";
}else{
    echo'5200の方が小さい'."\n";
}
```
上記例のように文字列の数字を比較するときは先頭文字から順番に数字を比較する。
####例）1
"5200"と"621"の比較の為
5と6が比較される。
**その結果621の方が大きく、5200の方が小さくなる**

####例）2
"5200"と"521"の比較の為
①5と5が比較される。
②1桁目で判断できない為2桁目を比較
2と2が比較される
③3桁目で0と1を比較し521の方が大きいと分かる

**その結果521の方が大きく、5200の方が小さくなる**

#宇宙演算子でも同様にやってみた
strcmp()で比較していた内容を宇宙演算子で
例）

```php
//上記例を宇宙演算子で書き換えた場合5200の方が大きくなる
//$nと$mには１の値が格納される。
//宇宙演算子は文字列比較時に文字列を値に変換している様子（ドキュメントからは読み取れなかった為推測）
$n = "5200"<=>"621";//1
return;
if($n > 0){
    echo '5200の方が大きい'."\n";
}elseif($n===0){
    echo'等しい'."\n";
}else{
    echo'5200の方が小さい'."\n";
}

$m = "5200"<=>"521";//1
if($m> 0){
    echo '5200の方が大きい'."\n";
}elseif($m ===0){
    echo'等しい'."\n";
}else{
    echo'5200の方が小さい'."\n";
}
```

どうやら宇宙演算子では比較の際に文字列の数値を数値へ変換して比較している様子。
その為5200が大きいが表示される。
【GCP】3/24 Google Cloud INSIDE Mediaまとめ

https://www.youtube.com/watch?v=QKBHMbm9BOg&t=673s


<table>
	<tr>
		<th>VisionAPIの検出方法について</th>
		<th>猫だけでなく、どんなネコかまで抽出できる。Googleシステム内でラベル付けされていて、その結果が返される詳細については、非公開のよう。</th>
	</tr>
	<tr>
		<th>Speech to text の句読点はどのタイミングで入力されるか</th>
		<td>ブレスのタイミングやしゃべり方に間があるときに入れる。文法的に正しいところにも入れるようにしてくれてはいるが、精度は正確ではない。</td>
	</tr>
	<tr>
		<th>字幕に対応できるか</th>
		<td>リアルタイムの字幕には対応できない。他のシステムを組み合わせれば対応可能。</td>
	</tr>
	<tr>
		<th>TBSの事例。文字起こし</th>
		<td>もじこ、という文字起こしエディタ。</td>
	</tr>
	<tr>
		<th>もじこ開発の目的</th>
		<td>TV局では、文字起こしの作業がかなりの量。且つ急ぎのものが多い。１時間の番組であれば、１日かける。これが毎日ある。大切な作業だが、クリエイティブではなく、ずっとやらされると離職してしまう。</td>
	</tr>
	<tr>
		<th>実証実験</th>
		<td>２０１７年１月から開始。音声認識は１００％ではない。変換確定するまで編集でいない。正しい文章であるかを何度も聞きなおす。</td>
	</tr>
	<tr>
		<th>もじこを実現したSaas</th>
		<td>Chrome</td>
		<td>GoolgeCloud、Speech to textAPI</td>
		<td>Workspace</td>
	</tr>
	<tr>
		<th>Speech to textAPIのメリット</th>
		<td>125か国に対応している。コンテナのスケーリングも利用している。</td>
	</tr>
	<tr>
		<th>どのくらい工数削減できたか？</th>
		<td>１時間かかっていたものが１０分になった。2184時間分の作業時間を削減できた。</td>
	</tr>
	<tr>
		<th>開発工数</th>
		<td>メンバーは１５人。５年かかった。予算はそれなりにかかった。。</td>
	</tr>
	<tr>
		<th>開発で苦労したところ</th>
		<td>プログラミングに詳しくない人間もいたため、技術者とユーザーのコミュニケーションがとりずらかった。</td>
	</tr>
</table>
リーダブルコードの概要をまとめてみた【前編】

#はじめに
本記事ではプログラミングの本として有名な「リーダブルコード」を読んだので、簡単に概要を紹介する。
前編では1章〜7章までを紹介。

#1章　理解しやすいコード
###鍵となる考え
コードは理解しやすくなければならない。
コードは他の人が最短時間で理解できるように書かなければならない。

- 優れたコードとは他人が最短時間で理解できるコードである。理解できるとは変更を加えたり、バグを見つけたりできるという意味だ。
- コードは短い方が良い。だが理解するまでの時間を短くする方が大切だ。
- 理解しやすいコードは設計やテストのしやすさにつながることが多い。

#2章　名前に情報を埋め込む
###鍵となる考え
名前に情報を詰め込む。
気取った言い回しよりも明確で正確な方が良い。
- 明確な単語を選ぶ。

```
def Getpage(url):
```
このメソッドはデータベースやインターネットなどどこから取ってくるかわからない。インターネットであれば、DownloadPage()の方が適切。

また、使用する単語の代替案を調べれば、適切な単語を選択できる。

- tmpやretvalなど汎用的な名前を避ける。（それ相当の理由があれば良い。例えばtmpは情報の一時的な保管など）
- 具体的な名前を使って、物事を詳細に説明する。
- 変数名に大切な情報を追加する。（値に単位あれば書くべき。また、危険や注意が必要な部分には喚起する情報を書く）
- 長い名前はなるべく避ける（スコープの大きな変数には長い名前をつける。）
- プロジェクト固有の省略系は使用しない。（新しくチームに入った人が混乱する）
- 不要な単語は捨てる（DoServerLoop()はServerLoop()で良い）
- 名前のフォーマットで情報を伝える（HTMLならclassの区切り文字にはハイフン、idの区切りにはアンダースコアを使用する）

#3章　誤解されない名前
###鍵となる考え
名前が「他の意味と間違えられることはないか」と考える。

```
filter("year <= 2011")
```
このコードはyearが2011以下のものを指すのか、2011以下を除外したものを指すのかわからない。2011以下ならselect()、除外するならexclude()が良い。

- 限界値を含めるときは、minとmaxを使う。
- 範囲を指定するときはfirstとlastを使う。
- 包括/排他的範囲には、beginとendを使う。

#4章　美しさ
###鍵となる考え
一貫性のあるスタイルは「正しい」スタイルよりも大切だ。

- 複数のコードブロックで同じようなことをしていたら、シルエットも同じようにする。（メソッドをうまく使う）
- コードの「列」を整理すれば、概要が把握しやすくなる。（縦の線をまっすぐにする）
- ある場所でA・B・Cのように並んでいたら他の場所でB・C・Aのように並べてはいけない。順番に意味を持たせ、常にその順番を守る。（後で見たときに、要素があるかどうかわかりやすくなる）
- 空行を使って大きなブロックを論理的な「段落」に分ける。（グループごとに考えを分けられる。後から見たときに、自分の考えている場所が分かりやすくなる）

#5章 コメントすべきことを知る

###鍵となる考え
コメントの目的は、書き手の意図を読み手に知らせることである。

- コードからすぐにわかることは書かない。
- 酷いコードはコメントで補助するのではなく、コードそのものを修正する。（酷い名前の関数など）
- コードの欠陥はTODO:（後で手をつける）やXXX:(大きな問題がある）などを使って示す。
- コードを読んだ人が悩みそうなところを予想してコメントを書く。
- 読み手が細部にとらわれないように、コードブロックにコメントをつけて概要をまとめる。

#6章　コメントは正確で簡潔に

###鍵となる考え
コメントは領域に対する情報の比率が高くなければならない。

- 「それ」や「これ」といった代名詞は避ける。
- 関数の動作はできるだけ正確に説明する。
- 入出力の実例をコメントに書くには、値を慎重に選ぶ。
- 多くに意味が詰め込まれた言葉や表現を使って、コメントを簡潔に保つ。（情報密度が高くなる）

#7章　制御フローを読みやすくする

###鍵となる考え
条件やループなどの制御フローはできるだけ「自然」にする。コードの読み手が立ち止まったり読み返したりしないように書く。
行数を短くするよりも、他の人が理解するのにかかる時間を短くする。
要約するときはコードを新鮮な目で見る。

- 条件式の引数は左側が調査対象（変化する値）、右側は比較対象（安定した値）にする。
- 条件は否定系よりも肯定系を使う。（例えば　unlessや!=はなるべく使わない）
- 単純な条件を先に書く。ifとelseが同じ画面に表示されるので見やすい）
- 関心を引く条件は先に書く。（優劣が衝突する場合は自分で判断する）　　
- 三項演算子はなるべく使わない。（短くなるが、コードが読みにくくなることが多い）
- ネストは浅くする。（値を早めに返してあげると浅くできる。）

後編に続く（執筆中）
【Vue.js】グローバル変数で複数のコンポーネントをバインドする

## よく用いられるグローバル変数の定義方法とその課題
- vue.prototypeで定義する
    - [公式でも推奨](https://jp.vuejs.org/v2/cookbook/adding-instance-properties.html) されている
    - 課題
        - グローバル変数でバインドできない
            - ある子コンポーネントで行った変更を、別コンポーネントに即時反映したい

## この記事で解決できること
- vue.prototypeを使わずに、グローバル変数でコンポーネント同士を動的にバインドする

## サンプルアプリ画面
- Block1で変更したメッセージが、Block2にも同期して反映される
    - メッセージはグローバル変数でバインドしています

      <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349189/49cca482-ac47-6071-0256-8aa556dbfa6f.gif" width="400px">


### フォルダ構成
├── main.js ・・・ここでグローバル変数を定義
├── App.vue
└─┬ components
   　 ├── Block1.vue ・・・グローバル変数を参照
    　└── Block2.vue ・・・グローバル変数を参照

- サンプルアプリでは、main.jsでグローバル変数を定義し、各コンポーネントで参照しています。
    - 下記で順に説明します。


#### グローバル変数を定義する（main.js）

```js:main.js
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

// 1. グローバル変数を定義する
let GlobalData = new Vue({
  data: {
    $msg: "No comment.", // グローバル変数
  }
});

// 2. mixin でグローバル変数をラッピングする
Vue.mixin({
  methods: {
    // 2-1. 各コンポーネント内の<script>タグ内でグローバル変数を参照するための関数
    $_msg(){
      return GlobalData.$data.$msg
    },
    $_setMsg(newMsg){
      GlobalData.$data.$msg = newMsg;
    }
  },
  computed: {
    // 2-2. 各コンポーネント内の<template>タグ内でグローバル変数を参照するための処置
    $msg: {
      get: function () { return GlobalData.$data.$msg },
      set: function (newMsg) { GlobalData.$data.$msg = newMsg; }
    }
  }
})

// 3. 通常通りコンポーネントを生成する
new Vue({
  render: h => h(App),
}).$mount('#app')
```

- 補足説明
    - 1. グローバル変数を定義する
        - `new Vue()`メソッドを使ってvueインスタンスを生成します。data属性にグローバル変数を定義します。この例では、`$msg`がグローバル変数に相当します。
    - 2. mixin でグローバル変数をラッピングする
        - 2-1. 各コンポーネント内の`<script>`タグ内でグローバル変数を参照するための関数
            - methods属性で、グローバル変数のゲッター、セッターを定義します。これがないと各コンポーネントの`<script>`タグ内で、グローバル変数を参照できません。
        - 2-2. 各コンポーネント内の`<template>`タグ内でグローバル変数を参照するための処置
            - computed属性を定義し、ゲッター、セッターを定義します。これがないと各コンポーネントの`<template>`タグ内で、グローバル変数を参照できません。
    - 3. 通常通りコンポーネントを生成する


#### 各コンポーネントでグローバル変数を参照する
- components/Block1.vue を例にご説明します
    - [フォルダ構成はこちら](#フォルダ構成)

```vue:components/Block1.vue
<template>
  <div id="block1-root" @click="setMessage">
    <p>Block1</p>
    <!-- (A) <template>タグ内でグローバル変数を参照 -->
    <p>メッセージ: {{$msg}}</p>
  </div>
</template>


<script>
export default {
  components: {
  },
  data: function () {
    return {
    }
  },
  methods: {
    setMessage(){
      // (B) <script>タグでグローバル変数の参照・書き換え
      this.$_setMsg("Block1がクリックされました！");
    }
  },
  mounted: function(){
  }
}
</script>


<style scoped lang="scss">
 // 省略
</style>
```

- 補足説明
    - (A) `<template>`タグ内で変数を利用する場合は、main.js内の`computed`属性で定義した変数名を記述します。
        - この例では、{{$msg}} です。
    - (B) `<script>`タグ内で変数を利用する場合は、main.js内の`methods`属性で定義した関数を呼び出します。
        - この例では、 this.$_setMsg() です。

### その他の手法
- イベントバスを作成し、カスタムイベントをグローバルスコープに`emit`することもできます
    - 参考URL: [How To Create a Global Event Bus in Vue 2](https://www.digitalocean.com/community/tutorials/vuejs-global-event-bus)

## 参考記事
- この記事は、[こちらのStackOverflow](// https://stackoverflow.com/questions/49256765/change-vue-prototype-variable-in-all-components) の記事を参考にまとめました。
深層学習（Pytorch）を用いた、Kaggle Titanic実践 PART 10 （テストのCode）

# 予測するためのCode

```Python
import pickle
import pandas as pd
import numpy as np
import category_encoders as ce
import torch
from torch import nn
from data_preprocessing import data_preprocessing_test
from sklearn.model_selection import train_test_split
from sklearn import preprocessing

from model import Model
from earlystopping import EarlyStopping
from data_loader import *

model = Model()
model.load_state_dict(torch.load("models/model.pth"))
with open('models/ohe.pkl', 'rb') as f:
	ce_ohe = pickle.load(f)
with open('models/mm.pkl', 'rb') as f:
	mm = pickle.load(f)

model.eval()

data = pd.read_csv("titanic/test.csv")
X_test = data_preprocessing_test(data, ce_ohe)
X_test = mm.transform(X_test)

id_lst = list(data["PassengerId"].values)
pred_lst = list()
for data in X_test:
	res = model(torch.tensor(data).unsqueeze(0).float())
	pred_lst.extend(np.argmax(np.exp(res.detach().numpy()), axis=1))

sub_df = pd.DataFrame(np.array(id_lst+pred_lst).reshape(2, -1))
sub_df = sub_df.T
sub_df = sub_df.rename(columns={0: 'PassengerId', 1:"Survived"})
print(sub_df.head())
sub_df.to_csv("sub_dl.csv", index=False)
```
深層学習（Pytorch）を用いた、Kaggle Titanic実践 PART 9 （学習のCode）

# 学習のCode
```Python
import pickle
import pandas as pd
import numpy as np
import category_encoders as ce
import torch
from torch import nn
from data_preprocessing import data_preprocessing
from sklearn.model_selection import train_test_split
from sklearn import preprocessing

from model import Model
from earlystopping import EarlyStopping
from data_loader import *

# HyperParameter
LEARNING_RATE = 0.0001
TRAIN_BATCH_SIZE = 10
VALID_BATCH_SIZE = 5
EPOCHS = 1000


data = pd.read_csv("titanic/train.csv")

target, X, ce_ohe = data_preprocessing(data)

# データの正規化
mm = preprocessing.MinMaxScaler()
X = mm.fit_transform(X)

X_train, X_valid, y_train, y_valid = train_test_split(X, target, test_size=0.33, random_state=42)

model = Model()

earlystopping = EarlyStopping()

criterion = nn.NLLLoss()

optimizer = torch.optim.AdamW(model.parameters(), lr=LEARNING_RATE)

trainset = DataSet(X_train, y_train)
trainloader = torch.utils.data.DataLoader(
	trainset, batch_size=TRAIN_BATCH_SIZE, shuffle=True)
validset = DataSet(X_valid, y_valid)
validloader = torch.utils.data.DataLoader(
	validset, batch_size=VALID_BATCH_SIZE, shuffle=True)

for epoch in range(EPOCHS):

	train_loss = 0
	train_acc = 0
	total = 0
	model.train()
	
	for data in trainloader:

		optimizer.zero_grad()

		output = model(data[0].float())
		predicted = torch.argmax(output, axis=1)

		target = data[1]

		loss = criterion(output, target)

		train_loss += loss.item()
		train_acc += (predicted == target).sum().item()

		total += data[1].size(0)

		loss.backward()
		optimizer.step()

	train_loss = train_loss / total
	train_acc = train_acc / total
	
	print("train_acc:", str(train_acc))
	model.eval()
	vali_total = 0
	vali_loss = 0
	vali_acc = 0

	for data in validloader:

		with torch.no_grad():
			out = model.forward(data[0].float())
			predicted = torch.argmax(out, axis=1)

		target = data[1]

		loss = criterion(out, data[1])

		vali_loss += loss.item()
		vali_acc += (predicted == target).sum().item()
		vali_total += data[1].size(0)

	vali_loss = vali_loss / vali_total
	vali_acc = vali_acc / vali_total
	
	
	print("valid_acc:", str(vali_acc))
	
	earlystopping(vali_loss, model)
	if earlystopping.early_stop:
		print("Early stopping")
		break

with open('models/ohe.pkl', 'wb') as f:
	pickle.dump(ce_ohe, f)
with open('models/mm.pkl', 'wb') as f:
	pickle.dump(mm, f)
```
深層学習（Pytorch）を用いた、Kaggle Titanic実践 PART 8 （モデル）

# Deep Learningのモデル

```Python
import torch
from torch import nn
import torch.nn.functional as F

class Model(nn.Module):
	def __init__(self):
		super(Model, self).__init__()

		self.linear1 = nn.Linear(27, 10)
		self.linear2 = nn.Linear(10, 2)

	def forward(self, x):
		batch_size = x.shape[0]

		x = self.linear1(x)
		x = F.relu(x)
		x = self.linear2(x)
		x = F.sigmoid(x)
		out = torch.log_softmax(x, dim=1)
		return out
```
深層学習（Pytorch）を用いた、Kaggle Titanic実践 PART 7 （Early Stoppingを用いた学習）

# EarlyStoppingを用いた学習

![イラスト- data13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053943/0e7f634d-1e4c-f6c3-f325-ae31d835bf7f.jpeg)


EarlyStoppingを用いた、学習の概要は上記のようになります。

# Code

```Python
for epoch in range(EPOCHS):

	train_loss = 0
	train_acc = 0
	total = 0
	model.train()
	
	for data in trainloader:

		optimizer.zero_grad()

		output = model(data[0].float())
		predicted = torch.argmax(output, axis=1)

		target = data[1]

		loss = criterion(output, target)

		train_loss += loss.item()
		train_acc += (predicted == target).sum().item()

		total += data[1].size(0)

		loss.backward()
		optimizer.step()

	train_loss = train_loss / total
	train_acc = train_acc / total
	
	print("train_acc:", str(train_acc))
	model.eval()
	vali_total = 0
	vali_loss = 0
	vali_acc = 0

	for data in validloader:

		with torch.no_grad():
			out = model.forward(data[0].float())
			predicted = torch.argmax(out, axis=1)

		target = data[1]

		loss = criterion(out, data[1])

		vali_loss += loss.item()
		vali_acc += (predicted == target).sum().item()
		vali_total += data[1].size(0)

	vali_loss = vali_loss / vali_total
	vali_acc = vali_acc / vali_total
	
	
	print("valid_acc:", str(vali_acc))
	
	earlystopping(vali_loss, model)
	if earlystopping.early_stop:
		print("Early stopping")
		break

```
深層学習（Pytorch）を用いた、Kaggle Titanic実践 PART 6 （Early Stopping）

この章は**深層学習 (アスキードワンゴ)** と **https://github.com/Bjarten/early-stopping-pytorch** を参考に書かれています。

十分な表現要領を持つ大きなモデルを訓練して、あるタスクに対して学習するとき訓練誤差は減少するが、検証誤差が再び増加し始めることがあります。
そこで、検証誤差が改善されるたびに、モデルを保存することにします。
一定のエポック数検証誤差が改善されない場合、学習は終了します。

![](https://storage.googleapis.com/zenn-user-upload/lldiobqg2j14tyozrsixdpyics2v)


コードは以下のようになります。

以下のコードをearlystopping.pyとして保存してください。

```Python
import numpy as np
import torch

class EarlyStopping:

    def __init__(self, patience=7, verbose=False):
        
        self.patience = patience
        self.verbose = verbose
        self.counter = 0
        self.best_score = None
        self.early_stop = False
        self.val_loss_min = np.Inf
        self.force_cancel = False

    def __call__(self, val_loss, model):
        
        score = -val_loss

        if self.best_score is None:
            self.best_score = score
            self.save_checkpoint(val_loss, model)
        elif score < self.best_score:
            self.counter += 1
            print(
                f'EarlyStopping counter: {self.counter} out of {self.patience}')
            if self.counter >= self.patience:
                self.early_stop = True
        else:
            self.best_score = score
            self.save_checkpoint(val_loss, model)
            self.counter = 0

    def save_checkpoint(self, val_loss, model):
        
        if self.verbose:
            print(
                f'Validation loss decreased ({self.val_loss_min:.6f} --> {val_loss:.6f}).  Saving model ...')
        torch.save(model.state_dict(), 'models/model.pth')
        self.val_loss_min = val_loss
```
深層学習（Pytorch）を用いた、Kaggle Titanic実践 PART 5 （Titanic用のdatasetとdataloderの作成）

# どのような構造のdataloaderが欲しいか
今回のdataloaderの構造は簡単で、「data」と「label」を入れたら、「data」と「label」をそのまま返してくれる構造のdataloaderを作成したいですね。

# Code
上記の構造をcodeに落とし込むと以下のようになります。

```Python
import torch

class DataSet(torch.utils.data.Dataset):
	def __init__(self, data, label):

		self.data = data
		self.label = label
		self.length = len(data)

	def __len__(self):

		return self.length

	def __getitem__(self, index):

		data = self.data[index]
		label = self.label[index]

		return data, label
```
深層学習（Pytorch）を用いた、Kaggle Titanic実践 PART 4 （Pytorchのdataloaderとdataset）

この章では、PytorchのDatasetとDataLoaderについて解説していきます。
この章は**https://gotutiyan.hatenablog.com/entry/2020/04/21/182937** を参考に記述されています。
Pytorchでは、DatasetとDataLoaderを用いることで、簡単にミニバッチ化をすることができます。

# Datasetの実装
DataSetを実装する際には、クラスのメンバ関数として__len__()と__getitem__()を必ず作ります。

__len__()は、len()を使ったときに呼ばれる関数です。
__getitem__()は、array[i]のように[ ]を使って要素を参照するときに呼ばれる関数です。これが呼ばれる際には、必ず何かしらのindexが指定されているので、引数にindexの情報を取ります。また、入出力のペアを返すように設計します。

以上を踏まえて、Datasetを作成してみましょう。

```Python
class DataSet:
    def __init__(self):
        self.X = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # 入力
        self.t = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] # 出力

    def __len__(self):
        return len(self.X) # データ数(10)を返す

    def __getitem__(self, index):
        # index番目の入出力ペアを返す
        return self.X[index], self.t[index]
```
さて、実際にこのDataSetがどのような振る舞いをするか試してみましょう。

```Python
dataset = DataSet()
print('全データ数:',len(dataset))  # 全データ数: 10
print('3番目のデータ:',dataset[3]) # 3番目のデータ: (3, 1)
print('5~6番目のデータ:',dataset[5:7]) # 5~6番目のデータ: ([5, 6], [1, 0])
```

# DataLoaderの実装
バッチサイズを2、訓練時のデータのシャッフルをFalseとした実装は以下のようになります。

```Python
# さっき作ったDataSetクラスのインスタンスを作成
dataset = DataSet()
# datasetをDataLoaderの引数とすることでミニバッチを作成．
dataloader = torch.utils.data.DataLoader(dataset, batch_size=2, shuffle=False)
```
これでミニバッチ学習をする準備が整いました。
ミニバッチ用のデータはfor文で取り出すことができます。

```Python
for data in dataloader:
    print(data)

'''
出力:
[tensor([0, 1]), tensor([0, 1])]
[tensor([2, 3]), tensor([0, 1])]
[tensor([4, 5]), tensor([0, 1])]
[tensor([6, 7]), tensor([0, 1])]
[tensor([8, 9]), tensor([0, 1])]
'''
```

上記のdataloaderを用いて、10epoch学習をする場合には以下のように書けます。

```Python
epoch = 10
model = #何かしらのモデル
for _ in range(epoch):
    for data in dataloader:
        X = data[0]
        t = data[1]
        y = model(X)
        # lossの計算とか
```

PytorchのDatasetとDataloaderについての説明は、以上になります。



![](https://storage.googleapis.com/zenn-user-upload/c50t76z45b5rr45jlqrrbol4p1ng)
深層学習（Pytorch）を用いた、Kaggle Titanic実践 PART 3 （MinMaxScalerを使ったデータの正規化）

# MinMaxScalerによる正規化とは
0 ~ 1 の範囲への変換

# scikit-learnによる正規化
以下の式で簡単に正規化できます。
簡単ですね。

```Python
# データの正規化
mm = preprocessing.MinMaxScaler()
X = mm.fit_transform(X)
```
深層学習（Pytorch）を用いた、Kaggle Titanic実践 PART 2

# 用いる特徴量を決める
今回、『Ticket』と『Cabin』は、除外しました。
用いて見たい場合は、この本が終わった後に自分で試してみてください。

```Python
######### 用いる特徴量を決める #########
	data = data[["Survived", "Pclass", "Name", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]]
	
	data = data.dropna()
	
	
	target = data["Survived"].values
	data = data.drop("Survived", axis=1)
```

# 敬称の抜き出し
まずは、名前の構造がどうなっているかみていきましょう。

最初の乗客の名前をみると以下のようになっています。

```
Braund, Mr. Owen Harris
```
上記から、敬称（Mr）を抜き出します。

以下に、敬称を抜き出す、手順を書きます。
1. 「,」でsplit
2. 1でsplitされた、配列の１番目を「.」でsplit
3. 2でsplitされた、配列の0番目を１からスライスして取り出す

codeでは以下のようになります。

```Python
name_lst = name.split(",")
honorific_lst = name_lst[1].split(".")
honorific = honorific_lst[0][1:]
```

この敬称の抜き出しを、行う関数を以下に記します。

```Python
def extract_honorific(name):
	
	name_lst = name.split(",")
	honorific_lst = name_lst[1].split(".")
	honorific = honorific_lst[0][1:]
	
	return honorific
```

上記の関数を使い**data**に対して、**honorific**という、列を付け加えます。
また、**Name**列を削除します。

```Python
######### データの前処理(名前の整理) #########
name_lst = list(data["Name"].values)

honorific_lst = list()
for i in range(0, len(name_lst)):
	honorific_lst.append(extract_honorific(name_lst[i]))

data["Honorific"] = honorific_lst

data = data.drop("Name", axis=1)
```

# Pclassの整理
https://www.kaggle.com/c/titanic/data
上記をみると
TitanicのPclassは

```
1st = Upper（上流）
2nd = Middle（中級）
3rd = Lower（下流）
```
となっていることが分かります。

数値が低いほど、上流の階級になっていくことが分かったので
1に3を2に2を3に1を当てはめます。
以下のcodeでできます。

```Python
######### Pclassの整理 ######### 
data["Pclass"] = data["Pclass"].replace({1:3,2:2,3:1})
```

# カテゴリカル変数
カテゴリカル変数とは、性別や血液型などの、順位を付けられないものを指します。

# Pythonでの扱い方
Pythonでカテゴリカル変数を扱うには、以下のように書きます。
今回は、Titanicの性別を用いて、例を出します。

```Python
import category_encoders as ce

ce_ohe = ce.OneHotEncoder(cols=["Sex"])
data = ce_ohe.fit_transform(data)
```

簡単ですね。

# Titanicデータに当てはめる

```Python
######### データの前処理(category_encoders) #########
ce_ohe = ce.OneHotEncoder(cols=["Sex", "Embarked", "Honorific"])
data = ce_ohe.fit_transform(data)
```

# data_preprocessing.pyの作成
以下に**data_preprocessing.py**を記述します。

```Python
import category_encoders as ce

def data_preprocessing(data):
	
	######### 用いる特徴量を決める #########
	data = data[["Survived", "Pclass", "Name", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]]
	
	data = data.dropna()
	
	
	target = data["Survived"].values
	data = data.drop("Survived", axis=1)
	
	######### データの前処理(名前の整理) #########
	name_lst = list(data["Name"].values)
	
	honorific_lst = list()
	for i in range(0, len(name_lst)):
		honorific_lst.append(extract_honorific(name_lst[i]))
	
	data["Honorific"] = honorific_lst
	
	data = data.drop("Name", axis=1)
	
	######### Pclassの整理 ######### 
	data["Pclass"] = data["Pclass"].replace({1:3,2:2,3:1})
	
	######### データの前処理(category_encoders) #########
	ce_ohe = ce.OneHotEncoder(cols=["Sex", "Embarked", "Honorific"])
	data = ce_ohe.fit_transform(data)
	
	return target, data.values, ce_ohe
```
深層学習（Pytorch）を用いた、Kaggle Titanic実践 PART 1


**Pytorchを使って、KaggleのTitanicを解いていきます。**

**Pytorchの基礎**
**文字列処理**
**カテゴリカル変数の扱い方**
が学べます。

# 実行環境
OS:macOS 10.15.7
開発環境:Nova(Python対応テキストエディタならOK)
パッケージのinstall:Anaconda 4.9.2
Python:3.8.3

# 必要なパッケージ
**本書では、以下のライブラリがインストールされているとして話を進めていきます。**

```Python
category_encoders==2.2.2
numpy==1.19.2
torch==1.6.0
pandas==1.1.5
scikit_learn==0.24.1
```

# お問い合わせ
内容に関する質問は

mailto:deepblack.inc@gmail.com

までお願いします。
【React】material-ui で Toolbar の高さを低くしたいときは、minHeight を変更する

# material-ui で Toolbar の高さを変更したい

こんにちは、@ndj です。
material-ui で Toolbar の高さを低くしたかったのですが、すこしハマったので、備忘録を残しておきます。


## 結論

1. Toolbar は min-height が決められている。
2. Toolbar の高さを変更するためには、min-height を変更する必要がある。

## 高さを変更する方法

### 1. Toolbar は min-height が決められている。
material-ui の Toolbar は、min-height が決められているそうです。

>You need to change the min-height to adjust the height, as min-height is specified in material-ui.css as 64px.
[stack overflow: How do I change the Material UI Toolbar height? Shiladitya氏の回答より](https://stackoverflow.com/questions/55344569/how-do-i-change-the-material-ui-toolbar-height)

この方がおっしゃるには、Toolbar の min-height は 64px と決められているとのことなんですが、それを確認できる公式なドキュメントを見つけることができませんでした。。。material-ui のソースを確認すればいいのかな。。。

なにはともあれ、min-height が 64px ならば、いくら height をいじったところで　Toolbar の高さが 64px よりも低くならないのは納得です。

### 2. Toolbar の高さを変更するためには、min-height を変更する必要がある。

Toolbar の高さが変わらない理屈がなんとなくわかりました。
min-height を変更してやれば、Toolbar の高さを低くすることができそうです。

```sample.js
import React from 'react';
import { makeStyles, AppBar, Toolbar } from '@material-ui/core';

const useStyles = makeStyles(
    {
        toolbar: {
            minHeight: `36px`, // minHeight を再設定する
        }
    }
);

const Sample = () => {
    const classes = useStyles();
    return (
        <AppBar position="static">
            <Toolbar className={classes.toolbar}>
            </Toolbar>
        </AppBar>
    );
}

export default Sample;
```

これで、Toolbar の高さを、64px より低くすることができました。

## 参考
[stack overflow: How do I change the Material UI Toolbar height?](https://stackoverflow.com/questions/55344569/how-do-i-change-the-material-ui-toolbar-height)

## さいごに
ここまで読んでくださりありがとうございました。
誤字脱字、間違いご指摘などありましたらコメントいただけると幸いです。

[twitter: ndj](https://twitter.com/teqndj)
GitHubでメールアドレスを非公開にする

# はじめに
メモです。要点だけ書きます。

# GitHubにおけるメールアドレスの役割

- 通知メールアドレス
- バックアップメールアドレス
- コミットメールアドレス

恐らく、この3つです。

バックアップメールアドレス・コミットメールアドレスの詳しい説明や設定方法に関しては、GitHub 公式Document を参照してください。
[https://docs.github.com/ja/github-ae@latest/github/setting-up-and-managing-your-github-user-account/managing-email-preferences](https://docs.github.com/ja/github-ae@latest/github/setting-up-and-managing-your-github-user-account/managing-email-preferences)

# どうすべきか

## GitHubサイト側の設定

[https://github.com/settings/emails](https://github.com/settings/emails) にアクセスすると、自分のアカウントのメールアドレス設定ができます。

- Keep my email addresses private
- Block command line pushes that expose my email

以上の2つにチェックがついていればひとまず安心です。

Primaryとマークがついているメールアドレスは デフォルトのメールアドレスになるほか、**commit時にemail情報として含まれる可能性があります**。

メールアドレスを完全に非公開にしたい場合は、念のためローカル側で設定をする必要があります。

## ローカル側の設定

```
$ git config --global user.email [ID]+[username]@users.noreply.github.com
```

`[ID]` と `[username]` は置き換えてください。
noreply メールアドレスは [https://github.com/settings/emails](https://github.com/settings/emails) に記載されています。

### 過去のコミットをすべて変更したいとき
参考：[https://qiita.com/sea_mountain/items/d70216a5bc16a88ed932#%E9%81%8E%E5%8E%BB%E3%81%AE%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%82%92%E3%81%99%E3%81%B9%E3%81%A6%E5%A4%89%E6%9B%B4%E3%81%97%E3%81%9F%E3%81%84%E3%81%A8%E3%81%8D](https://qiita.com/sea_mountain/items/d70216a5bc16a88ed932)

参考になりました

```
$ git filter-branch -f --env-filter "GIT_AUTHOR_NAME='hoge'; GIT_AUTHOR_EMAIL='[ID]+[username]@users.noreply.github.com'; GIT_COMMITTER_NAME='hoge'; GIT_COMMITTER_EMAIL='[ID]+[username]@users.noreply.github.com';" HEAD 
```

# おわりに
めでたしめでたし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497960/0c3bf14b-a97c-0f0f-73a2-5c59511d624d.png)
【React】環境構築 create-react-app

# はじめに
Windows環境でReactを初めて使用する場合の手順
以下2点は必須
・初期導入を容易に行えるcreate-react-appを用いる

## Node.jsのインストール
#### Node.js公式サイトからNode.jsをインストール
https://nodejs.org/ja/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035014/d7a98e11-8ac5-3e22-b175-d39792fbba1c.png)

#### Chocolateyを使用してインストール
Chocolateyコマンドよりnodistをインストール
Chocolatey:Windows用パッケージ管理ソフトウェア

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035014/adeb2ba5-e9e3-edd0-2851-51b223c0e121.png)

### nodistのPathを通す
nodistはWindowsOSでNode.jsのバージョン管理を行うツールです。
上記を実行することでnodistのPathが通っているが、
nodist -v　コマンド実行時に認識されないエラーが出る場合は、pathが通っているかを確認する。
※nodistのインストール後コマンドプロンプトを再起動しないと認識されない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035014/81840215-b5b5-5b82-bf87-52e8aef73990.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035014/934f1dd9-4eb0-9aa0-4893-f46eb7cd73f9.png)

### nodistのインストール
nodist + (version)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035014/f17947a0-a008-d553-ce95-7259027ef64b.png)
次にyarnをインストールする
yarnはNode.jsのパッケージ管理を行う(他にnpmもあるが、npmよりインストールが速いなどメリットがある)
①Chocolateyでインストール
choco install yarn
②npmでインストール
npm install -g yarn
コマンドプロンプトを再起動してPathが通停ることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035014/41b8f2e8-b89b-e7f0-9697-b901113c104a.png)

### create-react-appのインストール
create-react-appをnpmでインストール
npm install -g create-react-app

### create-react-appでプロジェクト作成
作業フォルダに移動し以下コマンドを実行
create-react-app (プロジェクト名)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035014/f538cff5-06ff-e3e6-74ea-0cab1d53f101.png)

### create-react-appの実行
作成したディレクトリに移動し、以下コマンドを実行
yarn start
以下の画面がでればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035014/1c739df0-e27b-4eae-3ee4-3845d14d3fa5.png)


windowsSでのcreate-react-appを使用したプロジェクトの作成については以上です。
GASで1時間に一度、指定時刻にmyFunctionを実行する

# はじめに

**「GASで1時間に一度、指定時刻にmyFunctionを実行する」**なんて
めっちゃ簡単そうと思ったら、
下記のような事情で、工夫が必要だったので記事にしました。

- **時間主導型のトリガーは、時刻を指定すると繰り返し実行できない**
- **ユーザー/スクリプトにつき設定できるトリガーは20個まで**

# 目次

- 手順まとめ
- 解説

# 手順まとめ

- [タイムゾーンの変更](#タイムゾーンの変更)
- [GASコード](GASコード)
- [時間主導型トリガーの設定](時間主導型トリガーの設定)


## タイムゾーンの変更

プロジェクトの設定から
**「appsscript.json」マニフェスト ファイルをエディタで表示する」**
にチェックを入れる

application.jsonを編集する

```appsscript.json
{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}
```

詳しくは[こちら](https://walking-elephant.blogspot.com/2021/01/gas.timezone.html)

## GASコード

```javascript
// run in 23-24
function setTriggersAM() {
  removeTriggers();
  var time = new Date();
  time.setDate(time.getDate() + 1);
  for (var i = 0; i < 12; i++) {
    time.setHours(i);
    time.setMinutes(0);
    ScriptApp.newTrigger('myFunction').timeBased().at(time).create();
  }
}

// run in 11-12
function setTriggersPM() {
  removeTriggers();
  var time = new Date()
  for (var i = 12; i < 24; i++) {
    time.setHours(i);
    time.setMinutes(0);
    ScriptApp.newTrigger('myFunction').timeBased().at(time).create();
  }
}

function removeTriggers() {
  var triggers = ScriptApp.getProjectTriggers();
  for (var i = 0; i < triggers.length; i++) {
    if (triggers[i].getHandlerFunction() == "myFunction") {
      ScriptApp.deleteTrigger(triggers[i]);
    }
  }
}

function myFunction() {

}
```

## 時間主導型トリガーの設定

- 1日に一度、23時から24時の間に`setTriggersAM()`を実行
- 1日に一度、11時から12時の間に`setTriggersPM()`を実行


# 解説
## 設計

```javascript:GASコード
function removeTriggers() {
  // myFunction() を実行するトリガーを全て削除
}


function setTriggersAM() {
  removeTriggers()  // 実行済みのトリガーを削除するため
  // myFunction()を実行するトリガーを、翌日の0時0分から11時00分まで1時間ごとに計12個設定
}

function setTriggersPM() {
  removeTriggers()  //実行済みのトリガーを削除するため
  // myFunction()を実行するトリガーを、その日の12時0分から23時00分まで1時間ごとに計12個設定
}

function myFunction() {
  // あなたが実行したい内容
}
```

```:時間主導型トリガー
1日に一度23時から24時の間に setTriggersAM() を実行する
1日に一度11時から12時の間に setTriggersPM() を実行する
```

## 注意点

### GASの仕様

**「時間主導型のトリガーは毎日特定の日時に設定できない」**
(https://tonari-it.com/gas-trigger-set/ より引用。)

つまり、**時間主導型のトリガーは、時刻を指定すると繰り返し実行できない**ということ。
それに加えて、

**Apps script has a limited of 20 triggers per user/script.**
(https://stackoverflow.com/questions/31713735/dynamically-set-google-script-time-driven-timers-and-too-many-timers-error-in-gm より引用)

つまり、**ユーザー/スクリプトにつき設定できるトリガーは20個まで**
という事情があるので、上記のような少し複雑な実装になっている。

### setTriggersAM()とsetTriggersPM()の違い
`setTriggersAM()` は23-24時に実行されるので、
**翌日**の0時0分から11時00分まで1時間ごとに計12個設定しているのに対して、
`setTriggersPM()` は23-24時に実行されるので、
**その日**の12時00分から23時00分まで1時間ごとに計12個設定していることに注意。

### タイムゾーンを変更する理由
タイムゾーンを変更しないと、`setTriggersAM()`, `setTriggersPM()` の 

```javascript
time.setHours(i);
```

でニューヨークのタイムゾーンの時刻がセットされてしまう。

# 参考URL

https://walking-elephant.blogspot.com/2021/01/gas.timezone.html

https://stackoverflow.com/questions/31713735/dynamically-set-google-script-time-driven-timers-and-too-many-timers-error-in-gm

https://developers.google.com/apps-script/reference/script/script-app
[Arduino]短間隔におけるdeep sleepの有効性

以前、[deep sleepをつかってLチカ](https://qiita.com/ELIXIR/items/1fce2c6ff330906215bf)をしたのですが、
1秒間に2回,400[msec]程度のdeep sleepではかえって再起動時のオーバーヘッドでバッテリー消費が激しいのではないかと思い、計測してみることにしました。


まず、電圧変化を検知したらアップするカウンターを作成しました。LCDライブラリは割愛します。

```counter.cpp
#include <Arduino.h>
#include "AQM1602LCD.h"

AQM1602LCD* pLcd;
long cnt=0;
int previous=LOW;

void cntUp(){
  cnt++;
  pLcd->SetCursor(0,0);
  pLcd->WriteString(String(cnt));
  delay(10);
}

void setup() {
  Serial.begin(9600);
  Serial.println("start");
  Wire.begin();
  pLcd = new AQM1602LCD();
  // put your setup code here, to run once:
  pLcd->SetCursor(0,0);
  pLcd->WriteString("0              ");

  pinMode(2, INPUT);

}

void loop() {
  // put your main code here, to run repeatedly:
  int val = digitalRead(2);
  if(val != previous){
    Serial.println("chg");
    if(val==LOW)
      cntUp();
    previous = val;
    delay(10); // チャタリング防止用
  }
}
```

これを別のArduinoで起動しておき、
[前回](https://qiita.com/ELIXIR/items/1fce2c6ff330906215bf)のdeep sleep Lチカの
LEDの足とつないで光った回数をカウントします。
電源としては3.7[V] 300[mAh] のリポバッテリーを使用しました。

```deep_sleep_main.cpp
#include <Arduino.h>

RTC_DATA_ATTR bool bootCounter = false;

void setup() {
  pinMode(4,OUTPUT);
  pinMode(13,OUTPUT);
  Serial.begin(115200);
  Serial.println("ON");
  digitalWrite((bootCounter = !bootCounter)?13:4,HIGH);
  delay(100);
}

void loop() {
  esp_sleep_enable_timer_wakeup(400 * 1000);  // wakeup every 0.4secs
  esp_deep_sleep_start();  
}
```

光った回数は**64513回**、動作時間にして**17時間55分13秒**でした。
![IMG_9899.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/e99cbf37-c8b1-8718-375a-1f3ed967c26d.jpeg)


次にdeep sleepを使わず同じ動作を行うプログラムを用意し、同様にカウントしました。

```delay_main.cpp
#include <Arduino.h>

void setup() {
  pinMode(4,OUTPUT);
  pinMode(13,OUTPUT);
  Serial.begin(115200);
}

void loop() {
  Serial.println("ON");
  digitalWrite(13,HIGH);
  delay(100);
  digitalWrite(13,LOW);
  delay(400);
  Serial.println("ON");
  digitalWrite(4,HIGH);
  delay(100);
  digitalWrite(4,LOW);
  delay(400);
}
```

光った回数は**29666回**、動作時間にして**8時間14分26秒**でした。
![IMG_9904.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/2a56b26f-3ac8-1fde-0ea1-b5df4fd99124.jpeg)

試行回数はそれぞれ一回のみですが、倍以上の開きが出たので、短時間での頻繁なdeep sleep も効果はあるとみてよさそうです。
Flask + uWSGUでRaspberryPi上にサーバを立てる

# はじめに
RaspberryPiにFlask + uWSGIでサーバを立てたので手順を記載します。

# 様相技術
- ハード: Raspberry Pi Zero WH
- OS: Raspberry Pi OS
- アプリケーションサーバ: uWSGU
- FW: Flask

# 手順
## venv作成

venv（仮想環境）を作成します

```bash
# ディレクトリ作成 & 移動
mkdir sample
cd sample
# venv作成
python3 -m venv sample
# venvの有効化
source ore_line/bin/activate
# FlaskとuWSGIのインストール
pip install Flask
pip install uWSGI
```

## ファイル作成

```python:run.py
from flask import Flask

application = Flask(__name__)

@application.route('/')
def index():
    return 'hello!!!!'

if __name__== "__main__":
    application.run(host='0.0.0.0')
```

### 動作確認

```bash
(sample) pi@nekonisi-raspi:~/sample $ python run.py 
 * Serving Flask app "run" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
```

ブラウザで`http://{raspberryPiのIP}:5000`にアクセスするか、RaspberryPi上で`curl localhost:5000`を実行する。  
`hello!!!!`と表示されたOK

# uWSGIによる起動確認

```bash
uwsgi --http=0.0.0.0:8000 --callable=app --wsgi-file=run.py
```

ブラウザで`http://{raspberryPiのIP}:5000`にアクセスするか、RaspberryPi上で`curl localhost:5000`を実行する。  
`hello!!!!`と表示されたOK

## 補足
※ 1024番ポート以前のポート番号は開放時にroot権限が必要なので、root権限がないまま

```bash
uwsgi --http=0.0.0.0:80 --callable=app --wsgi-file=run.py
```

とかすると

```
bind(): Permission denied [core/socket.c line 769]
```

って怒られます。

# uWFGIのデーモン化

```ini:uwsgi.ini
[uwsgi]

wsgi-file=run.py
callable=app
http=0.0.0.0:8000
# ログファイルの場所
daemonize = /var/log/uwsgi.log
log-reopen = true
log-maxsize = 8000000
logfile-chown = on
logfile-chmod = 644
```

↑のiniファイルを作成した後に、

```bash
uwsgi uwsgi.ini
```

以上

# おわりに
NginxとかApacheが入るとすごく大変だけど、uWSGIだけなら簡単に設定できた。
ちょっとしたことでもQiitaにまとめるのは大事
あと、RaspberryPiあんまり関係ないワロス。

# 参考にしたサイト
[uWSGI入門](https://www.python.ambitious-engineer.com/archives/1959)
AWS リージョンとアベイラビリティーゾーンについて

知識ゼロから理解した事を纏めたものであり、認識齟齬があった場合はご連絡下さい。

##目次
[リージョンとは](#リージョンとは)
[アベイラビリティーゾーンとは](#アベイラビリティーゾーンとは)
[]()
[]()

##リージョンとは
AWSがサービスを提供している拠点のこと。
2021/03/30現在、以下の種類のリージョンが存在している。
複数のリージョンにインスタンス等を保持しておくことにより、片方のリージョンに何らかの障害が発生した場合でも、保持している別のリージョンのインスタンスで利用が出来る。(マルチリージョン構成)

リージョンを選択する際は、AWS上で稼働するシステムを利用するユーザーに出来るだけ近い場所にしないと、ネットワーク遅延が発生してしまう場合がある。


|リージョン名|Code|
|:---|:---|
|米国東部 (オハイオ)|us-east-2|
|米国東部 (バージニア北部)|us-east-1|
|米国西部 (北カリフォルニア)|us-west-1|
|米国西部 (オレゴン)|us-west-2|
|アフリカ (ケープタウン)|af-south-1|
|アジアパシフィック (香港)|ap-east-1|
|アジアパシフィック (ムンバイ)|ap-south-1|
|Asia Pacific (Osaka)|ap-northeast-3|
|アジアパシフィック (ソウル)|ap-northeast-2|
|アジアパシフィック (シンガポール)|ap-southeast-1|
|アジアパシフィック (シドニー)|ap-southeast-2|
|アジアパシフィック (東京)|ap-northeast-1|
|カナダ (中部)|ca-central-1|
|中国 (北京)|cn-north-1|
|中国 (寧夏)|cn-northwest-1|
|欧州 (フランクフルト)|eu-central-1|
|欧州 (アイルランド)|eu-west-1|
|欧州 (ロンドン)|eu-west-2|
|欧州 (ミラノ)|eu-south-1|
|欧州 (パリ)|eu-west-3|
|欧州 (ストックホルム)|eu-north-1|
|中東 (バーレーン)|me-south-1|
|南米 (サンパウロ)|sa-east-1|


##アベイラビリティーゾーンとは
アベイラビリティーゾーンとは、リージョンよりも小さな区分けであり、特定のエリア内のデータセンターの集まりのことを指している。
リージョンと同様各拠点に複数存在している為、障害が発生した場合でも、他のアベイラビリティーゾーンは利用出来る。
2021/03/30現在

|リージョン名|ゾーン数|
|:---|:---|
|米国東部 (オハイオ)|3|
|米国東部 (バージニア北部)|6|
|米国西部 (北カリフォルニア)|3|
|米国西部 (オレゴン)|4|
|アフリカ (ケープタウン)|3|
|アジアパシフィック (香港)|3|
|アジアパシフィック (ムンバイ)|3|
|Asia Pacific (Osaka)|3|
|アジアパシフィック (ソウル)|4|
|アジアパシフィック (シンガポール)|3|
|アジアパシフィック (シドニー)|3|
|アジアパシフィック (東京)|4|
|カナダ (中部)|3|
|中国 (北京)|2|
|中国 (寧夏)|3|
|欧州 (フランクフルト)|3|
|欧州 (アイルランド)|3|
|欧州 (ロンドン)|3|
|欧州 (ミラノ)|3|
|欧州 (パリ)|3|
|欧州 (ストックホルム)|3|
|中東 (バーレーン)|3|
|南米 (サンパウロ)|3|

###参考URL
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-regions-availability-zones.html
oh-my-zsh から starship に乗り換える

## 概要

zsh 移行時にとりあえず oh-my-zsh にしたけど、 .zshrc が賑やかなので、starship に移行した。


https://starship.rs/ja-jp/


## 削除手順

### oh-my-zsh アンインストール

```bash
uninstall_oh_my_zsh
```

https://github.com/ohmyzsh/ohmyzsh#uninstalling-oh-my-zsh


### .zshrc を再生成
既存の .zshrc は、同ディレクトリにアーカイブされる。
そのため、新たに生成する必要あり。

留意事項として、既存の .zshrc に `export PATH="..."` など独自設定がある場合、移行しておく。

```bash:~/.zshrc
# ...snip...
```

## starship インストール

```bash
$ brew install starship
```

https://starship.rs/ja-jp/


### .zshrc 設定


```diff:~/.zshrc
+ eval "$(starship init zsh)"
```

### フォントの文字化け修正
#### nerd-font インストール
https://github.com/ryanoasis/nerd-fonts#font-installation

#### ターミナルのフォント設定 ( iTerm2 )
DroidSansMono Nerd Font を選択した。

https://qiita.com/icchi_h/items/94b3b75012663cd33dd4


### starship の設定ファイル生成


```bash
$ mkdir -p ~/.config && touch ~/.config/starship.toml
```

https://starship.rs/ja-JP/config/

### 好みにカスタマイズ

```toml
[aws]
disabled = true

[character]
format = "❯❯ "
success_symbol = "❯❯(bold green) "
error_symbol = "❯❯(bold red) "

[directory]
format = "[$path]($style)[$read_only]($read_only_style) "
truncation_length = 4
truncate_to_repo = false
truncation_symbol = "…/"

[git_status]
disabled = true

[hostname]
disabled = true

# Disable the package module, hiding it from the prompt completely
[package]
disabled = true

[time]
disabled = false
time_format = "%Y-%m-%d %H:%M"
utc_time_offset = "+9"

[username]
disabled = true
```

## 結果
### 上記設定のプロンプト
![スクリーンショット 2021-03-30 1.28.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355926/49faed4a-aa4d-3e66-17aa-07b1854a50bf.png)

### 所感
利点として、ターミナルで新タブ開く時や、コマンド実行時の wait がゼロコンマ程度だけど早くなった。
また、プロンプトをカスタムする意欲も少し湧いてくる。

欠点として、使用不可になった機能がある。

- コマンド alias
    - `ll` etc?...
- タブによるサジェスト
    - カレントディレクトリのファイル選択
    - ssh 実行時の .ssh/config 設定
    - 大文字小文字を無視

### カスタマイズ

とりあえず、以下を参考に設定した。

リファレンス見て調整するの良いかも
[zsh: The Z Shell Manual](http://zsh.sourceforge.net/Doc/Release/index.html)
[Zsh \- ArchWiki](https://wiki.archlinux.org/index.php/zsh)

https://www.rasukarusan.com/entry/2019/07/17/201912
HerokuにデプロイしたGoアプリでpostgresに接続する時のgormの設定方法

# はじめに
最近[とうらぶ練度チェッカー]()というwebアプリを開発し、その際にサーバサイドをgoで書いてHerokuにデプロイしたのですが、postgresに接続する時のgormの設定についての情報がなかなか見つからなくて苦労したのでここに書き残しておこうと思います。

# 設定について
公式の[Heroku スターターガイド (Go)]()はすごく丁寧に書いてあります。DB接続についての説明は[ここら辺](https://devcenter.heroku.com/ja/articles/getting-started-with-go?singlepage=true#-12)にあります。しかし今回はgorm使いたいのでここに記載している方法とは別の方法で接続する必要があります。そこでgormの公式ドキュメントを観に行ってみましょう。[これ](https://gorm.io/ja_JP/docs/connecting_to_the_database.html#%E6%97%A2%E5%AD%98%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E6%8E%A5%E7%B6%9A)です。 ```heroku addons:create heroku-postgresql:hobby-dev```コマンドを打つとデータベースが作成されるので、既存のDB接続というところを参考に設定をします。公式に書いてあるのをそのまま書くと次のようになります。

```go
sqlDB, err := sql.Open("postgres", "mydb_dsn")
gormDB, err := gorm.Open(postgres.New(postgres.Config{
  Conn: sqlDB,
}), &gorm.Config{})
```
はい。
sql.Openの第二引数の```mydb_dsn```をまだ設定していないので次はそこです。
HerokuでDBのセットアップをする時、[ここ](https://devcenter.heroku.com/ja/articles/getting-started-with-go?singlepage=true#-12)にあるように、自動的に ```DATABASE_URL``` という環境変数が設定されます。これをGetenvした後parseURLして、SSLの設定も追加してさっきの```mydb_dsn```の部分に入れましょう。
書いてみます。

```go
    mydb_dsn := os.Getenv("DATABASE_URL")
    connection,err := pq.ParseURL(url)
	connection += " sslmode=require"
	sqlDB,err := sql.Open("postgres", connection)
    gormDB, err := gorm.Open(postgres.New(postgres.Config{
      Conn: sqlDB,
     }), &gorm.Config{})
```
こんな感じでherokuでgormを使ったDBの接続の設定は完了です！！

※gorm.Configの中身やエラーハンドリングは本筋に関係ないので省略しています。

# 終わりに
最後までお読みいただきありがとうございました！
何か間違いがあったらコメントでご指摘いただければと思います。
この記事が誰かの役に立てたら幸いです！


# 参考
- [Heroku スターターガイド (Go)](https://devcenter.heroku.com/ja/articles/getting-started-with-go?singlepage=true#-1)
- [Connecting to a Database - gorm](https://gorm.io/ja_JP/docs/connecting_to_the_database.html#%E6%97%A2%E5%AD%98%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E6%8E%A5%E7%B6%9A)
【Kotlin】JvmFieldアノテーションでゲッターの生成を抑制してバイナリサイズ・メソッド数を減らす

# TL;DR
- デフォルトでは、`Kotlin`のプロパティは`Java`上のフィールド + ゲッターの形にコンパイルされる
- `JvmField`アノテーションはゲッター生成を抑制するため、結果としてバイナリサイズ・メソッド数がそれぞれ減る
  - 試した限り、1フィールド当たり14.4バイト程度小さくなった
- `Android`開発等で役に立つかは不明

# 本文
## 素直に書いた場合
`Kotlin`のコードでは、以下のような`DTO`を定義することがしばしば有ります。

```kotlin
package com.wrongwrong

data class SampleDto(
    val foo: Int,
    val bar: Int,
    val baz: Int,
    val qux: Int,
    val quux: Int
)
```

上記クラスをバイトコードから`Java`にデコンパイルすると、以下のような結果が得られます。
それぞれのフィールドに対してゲッターが生成されていることが分かります。

```java:デコンパイル結果
/* 略 */
public final class SampleDto {
   private final int foo;
   private final int bar;
   private final int baz;
   private final int qux;
   private final int quux;

   public final int getFoo() {
      return this.foo;
   }

   public final int getBar() {
      return this.bar;
   }

   public final int getBaz() {
      return this.baz;
   }

   public final int getQux() {
      return this.qux;
   }

   public final int getQuux() {
      return this.quux;
   }

   public SampleDto(int foo, int bar, int baz, int qux, int quux) {
      /* 略 */
```

例示した`SampleDto`のみを定義して`./gradlew build jar`で`jar`を出力した所、その容量は2158バイトとなりました。

## JvmFieldを付与した場合
`JvmField`アノテーションをそれぞれのフィールドに付与すると以下のようになります。

```kotlin
package com.wrongwrong

data class SampleDto(
    @JvmField val foo: Int,
    @JvmField val bar: Int,
    @JvmField val baz: Int,
    @JvmField val qux: Int,
    @JvmField val quux: Int
)
```

この状態でデコンパイルすると、以下のように、ゲッターが定義される代わりにフィールドが`public`になっていることが分かります。

```java:デコンパイル結果
/* 略 */
public final class SampleDto {
   @JvmField
   public final int foo;
   @JvmField
   public final int bar;
   @JvmField
   public final int baz;
   @JvmField
   public final int qux;
   @JvmField
   public final int quux;

   public SampleDto(int foo, int bar, int baz, int qux, int quux) {
     /* 略 */
```

先程同様に`./gradlew build jar`で`jar`を出力した所、その容量は2086バイトとなりました。
先程の結果と比較すると、`(2158-2086)/5 = 14.4`ということで、1フィールド当たり大体14バイト程度減っています。

### 確認していないこと
確認は素の`Kotlin`でのみ行いました。
特に`Android`のビルドのように、難読化・最適化をかけた際にどれくらい効果が出るかや、そもそもそういったツールがゲッター生成を抑制するようなことをやっていないかは確認していません。

## 補足
以下のような`gradle`プロジェクトで検証を行いました。

```kotlin:build.gradle.kts
plugins {
    kotlin("jvm") version "1.4.31"
}

group = "com.wrongwrong"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation(kotlin("stdlib"))
}
```
Global変数はglobalsに入れろ（ESLint）

# Global変数がESLintに引っかかる
　もうこれ3回くらいハマってるので、反省の意を込めて記事書いておきます。内容はタイトルで完結しているので、補足程度の内容を追記します。
## 問題点
　Global変数は何も設定しないと、存在しないものとしてESLintのエラーが表示されます。例えば、GASの`SpreadSheetApp`とか、GoogleChromeExrtentionの`chrome`とかですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455591/abd17fc0-b0a6-5449-01bb-88fc876a93a2.png)


## 対応策
　下記の様にeslintrc.jsの`globals`へ入れます。以上！

```.eslintrc.js
module.exports = {
  extends: ['eslint:recommended', 'plugin:prettier/recommended'],
  plugins: ['@typescript-eslint', 'prettier'],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    sourceType: 'module',
  },
  rules: {
    'prettier/prettier': ['error'],
    semi: ['error', 'always'],
    'semi-spacing': ['error', { after: true, before: false }],
    'semi-style': ['error', 'last'],
    'no-extra-semi': 'error',
    'no-unexpected-multiline': 'error',
    'no-unreachable': 'error',
  },
  globals: {
    chrome: false,
  },
  env: {
    node: true,
    jest: true,
  },
};
```

単純だからこそ、引っかかりやすい…かもしれないので是非思い出してください。

## 補足
コメント欄で補足いただいたので紹介させていただきます。
> Chrome 拡張機能であれば、env.webextensions を true にされるのが良いかと。globals に chrome を含める必要がなくなります。
https://eslint.org/docs/user-guide/configuring/language-options#specifying-environments

## 宣伝
本当に大した機能じゃないですが、拡張機能リリースしたのでよかったらみてみてください。
githubもpublicにしてみました。
https://github.com/R-Az/custum_tabGroup
https://chrome.google.com/webstore/detail/tabgroupcustoms/aiidfmkcfamdjancnfkppnbhakahcndm?hl=ja
LeedCodeの問題一覧を無料問題のみに絞り込む

[LeetCodeの問題一覧ページ](https://leetcode.com/problemset/)は、難易度やタグで絞り込むことはできるのですが、プレミアム会員しか見ることのできないロックされた問題を除外するフィルター機能がありません。

そこでブックマークレットを作成しました。

```JavaScript:filter.js
javascript: (() => {
    let all = 0;
    let locked = 0;
    const tr = document.querySelectorAll('.ant-table-tbody tr.ant-table-row');
    for (let i = 0; i < tr.length; i++) {
        all++;
        if (tr[i]['cells'][1]
                && tr[i]['cells'][1].querySelectorAll('svg').length) {
            locked++;
            tr[i].hidden = true;
        }
    }
    console.log("All:", all);
    console.log("Locked:", locked);
    console.log("Free:", all - locked);
})();
```

ブックマークバーに新たなブックマークとしてURL欄に上記のコードをコピペしたものを保存[^1]し、[問題一覧ページ](https://leetcode.com/problemset/)で追加したブックマークレットをクリックすると、無料で解ける問題のみに絞り込まれます。

[^1]: 本当はドラッグ＆ドロップでブックマークバーに追加できるようにリンクで表示したかったのですが、Qiitaの仕様上、リンク先がJavaScriptだとクリックできないようなので諦めました。

コンソールには、全問題数、ロックされた問題数、無料で解ける問題数を表示しています。