OmniAICreator/Qiita-1.07M huggingface dataset:
【MySQL】NULLを含む比較演算でハマった

アドベントカレンダー10日目です！

MySQLに特化した内容ではありませんが、最近NULLの比較でハマったので知識の整理も兼ねて書き残します。

# NULLと比較演算
## NULLと比較したらどうなるか？
NULLとの比較結果は常に``NULL``です。

SQLの比較演算の結果は``1(true)``・`` 0(false)``・``NULL``の3種類です。
NULLと比較した場合、人間の目で見た真偽とは関係なく結果はNULLになります。

```sql
SELECT 'a' = 'a';
-- 1(true)
SELECT 'b' = 'a';
-- 0(false)
SELECT '' = 'a';
-- 0(false)
SELECT NULL = 'a';
-- NULL, 偽に見えるが0(false)ではない
SELECT NULL = NULL;
-- NULL, 真に見えるが1(true)ではない
```

## 結果をtrue/falseで受け取るには？
演算の結果を``1(true)``・``0(false)``で受け取るためには``IS NULL``や``IS NOT NULL``などを使用します。

```sql
SELECT NULL IS NULL; 
-- 1(true)
SELECT NULL IS NOT NULL;
-- 0(false)
```

また、``<=>(NULL安全等価演算子)``を使用する方法もあります。

NULL以外の値の比較では``=(等価演算子)``と同じ挙動ですが、NULL同士の比較であれば``1(true)``が、片方のみNULLであれば``0(false)``の結果が返ります。

```sql
SELECT 'a' <=> 'a', 'b' <=> 'a', '' <=> 'a';
-- 1(true), 0(false), 0(false)
SELECT NULL <=> NULL;
-- 1(true)
SELECT NULL <=> 'a';
-- 0(false)
```

# ハマったこと
``<>(不等価演算子)``や``NOT演算``を利用した場合、比較対象のカラムにNULLが含まれると意図しない挙動が発生します。

実際にテーブルを用意して検証します。

## テーブル・レコードの生成
```sql
mysql> CREATE TABLE users(id int, name varchar(10));
mysql> INSERT INTO users VALUES(1, 'taro'), (2, 'hanako'), (3, ''), (4, NULL);
mysql> SELECT * FROM users;
+------+--------+
| id   | name   |
+------+--------+
|    1 | taro   |
|    2 | hanako |
|    3 |        |
|    4 | NULL   |
+------+--------+	
```

## SELECT文を実行
``<>(不等価演算子)``もしくは``NOT演算``を利用して``name = 'taro'``以外のレコードを取得します。

``id = 2, 3, 4``のレコードが取得できればOKです。

### NG
``id = 4``のレコードが取得できません。

抽出対象は``name <> 'taro'``の結果が``1(true)``のレコードのみです。
``id = 4``のレコードはnameの値がNULLなので``name <> 'taro'``の結果が``NULL``になり、抽出から除外されます。

```sql
mysql> SELECT * FROM users WHERE name <> 'taro';
-- SELECT * FROM users WHERE NOT(name = 'taro')も同様
+------+--------+
| id   | name   |
+------+--------+
|    2 | hanako |
|    3 |        |
+------+--------+	
```

### OK
``id = 4``のレコードも含めて取得できました。

``IS NULL``の条件追加によりnameの値がNULLの場合も``1(ture)``が得られ、抽出対象となります。

```sql
mysql> SELECT * FROM users WHERE name <> 'taro' OR name IS NULL;
+------+--------+
| id   | name   |
+------+--------+
|    2 | hanako |
|    3 |        |
|    4 | NULL   |
+------+--------+
```

# ハマらないためにできること
SQLを実行する度にNULLを想定するのではなく、カラムの定義で解決できれば楽ですね。

- カラムにNOT NULL制約を追加する
- カラムにデフォルト値を設定する
- 常にNULLを想定したSQLを作成する

# 参考
- [MySQL 5.6 リファレンスマニュアル 12.3.2 比較関数と演算子](https://dev.mysql.com/doc/refman/5.6/ja/comparison-operators.html)

# 採用PR
弊社で一緒に働く仲間を募集しています。
全てのオタクを幸せにしたい方、是非ご覧ください！

https://hrmos.co/pages/vivion/jobs/0000191

アドベントカレンダーも中盤に差し掛かりました。
クリスマスまで楽しんでくださいね！
PRML　演習問題 2.2（標準）　解答

## はじめに
　本記事は, 機械学習の教科書の決定版ともいえる, **Christopher Bishop先生**による[**『Pattern Recognition and Machine Learning （パターン認識と機械学習）』**]  (https://www.microsoft.com/en-us/research/people/cmbishop/prml-book/) , 通称**PRML**の演習問題のうち, 私が解いた問題の解答を記したものです. これは, 私の所属する[生物測定学研究室] (https://www.ut-biomet.org/) の輪読会で**PRML**を取り扱っており, その勉強の一環として演習問題を解いたときのものです. なお, 他の演習問題の解答例に関する記事については, [PRML　演習問題　解答集　まとめ]  (https://qiita.com/Lab_of_Biomet/items/15e38ca34fafa8176d89) をご覧ください.
 

## 問題
>　ベルヌーイ分布 $\mathrm{Bern} (x \, | \,  \mu) = \mu ^ x (1- \mu )^{1-x} $ の表現では， $x$ の $2$ つの値 $0$ と $1$ に関して対称ではない．場合によっては， $x \in \{ -1, \, 1\}$ を用いた等価な表現の方が便利である．このとき分布は
>
```math
p(x \, | \, \mu) = \left(  \frac{1-\mu}{2}   \right) ^{(1-x)/2} \left(  \frac{1+\mu}{2}   \right) ^{(1+x)/2}
```

>と書くことができる．ただし，$\mu \in [-1, \, 1]$ である．この分布が正規化されていることを示し，その平均，分散，エントロピーを計算せよ．



##解答
### 正規化の証明
　ベルヌーイの式で規定しているのは離散的な2回の結果なので，$\Sigma \, p $ の合計が $1$ になっていれば正規化されているとすることができる．

```math
p(x \, | \, \mu) = \left(  \frac{1-\mu}{2}   \right) ^{(1-x)/2} \left(  \frac{1+\mu}{2}   \right) ^{(1+x)/2}
```

より，

```math
\begin{aligned}
\sum_{x = 1, \, -1} p(x \, | \, \mu) \, &=  p(x = 1 \, | \,  \mu) + p(x = -1 \, | \,  \mu) 
\\
& = \frac{1 + \mu}{2} + \frac{1 - \mu}{2}
\\ 
\\
& = 1
\end{aligned}
```

したがって，この分布は正規化されている．

<br>


### 平均の導出
　平均はいわゆる期待値であり， $\Sigma \,  x \, p(x)$  で計算できる．したがって，平均は

```math
\begin{align}
\mathrm E[x] \,  & =  1 \times \frac{1 + \mu}{2} + (-1) \times \frac{1 - \mu}{2}
\\
& = \mu
\end{align}
```

となる．

<br>

### 分散の導出
　分散の式より，

```math
\begin{aligned}
\mathrm {var}[x]  \, &=  \mathrm {E}[x^2] - \mathrm {E}[x]^2
\\
\\
& = \left\{ 1^2 \times \frac{1 + \mu}{2} + (-1)^2 \times \frac{1 - \mu}{2} \right\} -  \mu^2
\\
\\
& = 1-\mu^2
\end{aligned}
```

<br>


### エントロピーの導出
　ある送信者が確率変数の値を受信者に送りたいとする時，その操作で送られる情報の平均量のことを確率変数 $x$ のエントロピーと呼ぶ．これは分布 $p(x)$ に関する期待値なので，今回のような離散的な形をとる場合は以下のようにして求まる．

```math
\begin{aligned}
\mathrm H[x] \, & = - \sum_{x = -1, 1} \, p(x \, | \, \mu) \ln \, p(x \, | \, \mu)
\\
\\
& = - \left\{  \, p(x=-1 \, | \, \mu) \ln \, p(x=-1 \, | \, \mu)  +  \, p(x =1\, | \, \mu) \ln \, p(x=1 \, | \, \mu) \right\}
\\
\\
& = -\left\{ \frac{1-\mu}{2} \, \ln \, \frac{1-\mu}{2} + \frac{1+\mu}{2} \, \ln \, \frac{1+\mu}{2} \right\} 
\end{aligned}
```

<br>
<br>
PythonでXML形式のAPIレスポンスをいい感じに辞書にする

# 概要
Redmineのクライアントアプリ的なものを作っており、Redmineの各APIを叩いてチケット起票に必要な情報を取ってくる必要があった。RedmineのAPIレスポンスはXMLだが、パッと調べた感じjsonと違っていい感じに辞書にしてくれる機能がないっぽいので自分でやった。忘れそうなので備忘録として書いとく。もし調べ方が下手なだけでいい感じにしてくれるやつが存在するなら僕はただのバカです。

**12/12追記**
APIのパス末尾の`.xml`を`.json`にしたらふつーにjsonで返ってきました。**僕はただのバカです。**

# まずAPIを叩く
RedmineのAPIドキュメントは[こちら](https://www.redmine.org/projects/redmine/wiki/Rest_api)。この中で、とりあえず[ユーザ取得API](https://www.redmine.org/projects/redmine/wiki/Rest_Users)を叩きます
返ってくるデータはこんな感じ

```xml
<?xml version="1.0" encoding="UTF-8"?>
<users total_count="10" offset="0" limit="100" type="array">
    <user>
        <id>1</id>
        <login>tanakatarou</login>
        <admin>false</admin>
        <firstname>太郎</firstname>
        <lastname>田中</lastname>
        <mail>tanakatarou@mail.com</mail>
        <created_on>2021-10-10T10:00:00Z</created_on>
        <last_login_on>2021-10-10T10:00:0Z</last_login_on>
    </user>
    <user>
        <id>2</id>
        <login>yamadahanako</login>
        <admin>false</admin>
        <firstname>花子</firstname>
        <lastname>山田</lastname>
        <mail>yamadahanako@mail.com</mail>
        <created_on>2021-10-10T10:00:00Z</created_on>
        <last_login_on>2021-10-10T10:00:0Z</last_login_on>
    </user>
<users>
```

jsonで返ってくるなら`json.loads()`で一発だが、XMLとなると使いやすい形にするのに一工夫いる。

# XMLを辞書にする
今回は、ユーザIDと名前が欲しいので、以下のような形にすることを目標にする。

```python
[
 {"id":"1","name":"田中太郎"},
 {"id":"2","name":"山田花子"}
]

```

書いた処理はこんな感じ。

```python
import xml.etree.ElementTree as XmlET

# 1 APIを叩いて取得したXML形式の文字列をElementオブジェクトに変換（execute_api()は自作の関数)
redmine_user_xml = XmlET.fromstring(execute_api(url=redmine_user_api_url, headers=redmine_headers, method="GET"))
# 2 全てのuserタグをElementとして取得
all_user_element = redmine_user_xml.findall("user")users
# 3 userのElementからid、nameを取得しテキストにして辞書に格納
users = []
for user_element in all_user_element:
  users.append({
    "id": user_element.find("id").text,
    "name": f"{user_element.find('lastname').text}{user_element.find('firstname').text}"
  })

return users
```

以下、解説 ([ドキュメント](https://docs.python.org/ja/3/library/xml.etree.elementtree.html#element-objects))

1. 文字列であるXML形式のレスポンスを、pythonでパースするためにElementというオブジェクトに変換する。この変換のためにxml.etree.ElementTreeモジュールをimportする必要がある。
1. 1で使ったfromstring()により、XMLのタグひとつひとつがElementオブジェクトとなり、その属性としてタグの属性や子のElementを持つような形になる。そこで、まずuserタグのElementを全て取得する。findall()を使うとタグ名で検索&取得できる。
1. 「まずAPIを叩く」で取得したXMLの形式を見ると、userタグの中にidタグやfirstnameタグ、lastnameタグなどが存在しており各タグに囲まれた部分にデータ文字列が入っていることがわかる。なので、2で取得したuserのElementひとつづつに対して"id"や"firstname"、"lastname"でfindしてタグのElementを取得する。そのタグの文字列はtext属性で持っているので`.text`で取得できる。firstnameとlastnameが別れている必要はないので結合してる。

結果がこちら。

```python
[
 {"id":"1","name":"田中太郎"},
 {"id":"2","name":"山田花子"}
]
```
いい感じ！！！

# まとめ
jsonで返せ。
【fish】【ShellScript】fish環境で初めてShellScript(シェルスクリプト)を触る私が困ったこと

# はじめに
初めまして！
Life is Tech ! メンターで、某大学院の2年生で情報工学の研究に勤しんでいるきゃみです！
今日はShellScriptについてまとめてみました！

## ShellScriptはfishとbash(zsh)でコードが違う
仕事でfish環境にしなきゃいけないことがあり、その中で作業効率化のために初めてShellScriptを触ったら仕様がちょくちょく違う部分があったので、備忘録的にfishとbash(zsh)の仕様の違いをまとめてみました。
自分の認識なので間違ってる部分があれば是非コメントいただきたいです！

# 変数宣言が違う
### bashの場合
```shell:bash.sh
hoge="fuga"
```
### fishの場合
```shell:fish.sh
set hoge "fuga"
```
_=くらい使わせてくれよなあ、、、_

# 変数の使い方が違う
### bashの場合
```shell:bash.sh
$hoge
${hoge}
# どっちでもいい
```
### fishの場合
```shell:fish.sh
$hoge
# こっちだけ許されてる
```
_シンプルになんで？連結する時にとても不便_

# 引数の使い方が違う
### bashの場合
```shell:bash.sh
$1 #一つ目の引数
$2 #二つ目の引数
```
### fishの場合
```shell:fish.sh
$argv[1] #一つ目の引数
$argv[2] #二つ目の引数
```
_これはfishの方がわかりやすいかもしれないけど気づけない_

# 四則演算の仕方が違う
### bashの場合
```shell:bash.sh
$(( $hoge + 1 ))
```
### fishの場合
```shell:fish.sh
expr $hoge + 1
```
_四則演算までコマンド操作にするんじゃねええええ_

# if文、ループ文の文法が違う
### bashの場合
```shell:bash.sh
if [$hoge -ge 123] then;
    # なんか処理
fi

for f in hoge fuga
do
  # なんか処理
done
```

### fishの場合
```shell:bash.sh
if [$hoge -ge 123]
    # なんか処理
end

for f in hoge fuga
  # なんか処理
end
```
_これもなんとなくfish文法のが馴染みあるけど、エディターがシンタックスハイライトしてくれないのがうざすぎる_

# コマンドの使い方が違う
### bashの場合
```shell:fish.sh
for f in 'ls direcectory'
do
  # なんか処理
done

# 上下のどちらか

for f in $(ls direcectory)
do
  # なんか処理
done
```


### fishの場合
```shell:fish.sh
for f in (ls direcectory)
  # なんか処理
end
```
_これもシンタックスハイライトしてくれないのでうざい_

# なんかわからないけどif文の条件分に使えないコマンドがある
これは自分の環境だからかもしれないけど、**testコマンド**が使えなかった

### fishの場合
```shell:fish.sh
if (test $hoge -ge 123)
    # 実行すると上の行でエラーを吐く
end
```

### 実際に吐くエラー
``` text:iTerm
create_matlab_code.sh (line 16): Command substitutions not allowed
  if (test $i -ge 2) && [ $i -le 11 ]
     ^
from sourcing file create_matlab_code.sh
source: Error while reading file 'create_matlab_code.sh'
```

# 最後に
こんなに仕様変えなくてもいいじゃないか...
今更ながらかもしれないUnityの導入方法について第1回目

#はじめに
VCIワカラン！
Luaワカラン！！
そもそもUnityワカラン！！！

ということで今更かもしれませんがUnityの導入を3回くらいに分けて記事にしたいと思います。
初めて記事を書くので不手際が有るかもしれませんが、生暖かく見ていただければと思います。

#そもそもUnityとは？
Unityとはゲームを作るために環境を提供してくれるプラットフォームと考えてもらえれば良いかと思います。
ゲームサイズ規模にもよりますが、WindowsどころかMACやLinux、Android、もちろんiOSでも動作するゲームを作成できます。
バーチャルキャストはUnityベースで作成されているため、Unityで作成したアイテムやアバターを（システム的に）簡単に導入できると言うことです。
今回は説明のために適当に用意したWin7仮想環境にて説明していきましょう。

#インストール・アカウント作成の開始
・ここ（*https://unity3d.com/jp/get-unity/download*）にアクセスして
　UnityHubをダウンロードしましょう。
![1_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/9af16dbc-4c11-5a92-3894-d1372a51c2f4.jpeg)

・ダウンロードしたUnityHubをインストールしましょう。
　下の画像が出れば完了です。
![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/305d1a11-33bc-2316-d063-88dd84552f70.jpeg)

・UnityHub起動後、新しいバージョンや、ベータ版のHubを使用するか聞いてくる
　ことがありますが、ここはお好みで選択してください。
![5_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/2b2faddc-2231-cd46-07c5-b9b3deba4757.jpeg)

・アカウント作成のため、右上の人マークからサインインを選びましょう。
![6_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/e6844e5c-3ec7-40c1-a646-c4da4fb35327.jpeg)

・IDを作成をクリックして新規IDを作成するかアカウント連携で登録する方法がありますが、
　今回はID作成から行きましょう。
![7_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/0586789a-7651-cf1d-b454-4522c6c17c0c.jpeg)

・必要な情報を入力＆チェックを入れて「UnityID作成」をクリックしましょう。
![8_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/2a5f20f8-4fa4-1d2c-9785-cc6d07f2a72e.jpeg)

・登録したメールアドレスにUnityからメールが届いているので、
　そこから「Link to confirm email」をクリックしましょう。
　届かないときは迷惑メールとして処理されたか登録したメールアドレスが間違っています。
![unityメール_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/de04afb9-9377-d5e5-7fa0-e629dc37d1a9.jpeg)

・URLをクリックすると、ロボットかの確認やサインインを求められるので
　サインインを行いましょう。
　正常にサインインできればアカウントの作成は完了です。
![unityメール3_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/84e5212d-9929-6065-e31b-8a93d58876a1.jpeg)

・ここでUnityHubに戻り、「続行」をクリック。
　コレでUnityHubでもアカウント設定が終わりましたがまだ続くんじゃ！
![9_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/f69da739-e28a-ac4a-7c4d-4c23f4f84ab1.jpeg)

・今度は作成したアカウントにライセンス登録する必要があるので
　「ライセンス管理」→「新規ライセンスの認証」をクリックしましょう。
![10_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/69136b5a-c443-564d-3173-49c4e7cfe670.jpeg)

・ライセンスの条件が聞かれます。「UnityPersonal」を選択しましょう。
　次のチェックボックスはどちらでも良いのですが、将来的にアバターや
　アイテムを販売する予定があるのであれば
　「前年度の～～」を選択すれば良いでしょう。
![11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/6c2922ce-bbe6-cb7a-cbcb-da2f9b83a969.jpeg)

・これでUnityをインストールするためのランチャーソフトUnityHubのインストール及び
　アカウント連携が終わりました。
![12_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/13a9e60f-566b-c8dc-e816-ec9a09769f78.jpeg)

#次回に続く
次はUnity本体のインストールの準備等の説明をしていきたいと思います。
GASでメールを管理する！

#GASでメールを管理する！
Gmailを開くとそこには、就活関係や大学からの様々なメールが、、、
本当に大事なメールが漏れる恐れがある。
これは、自炊するしかない！！

##材料
Gmail　・・・　お好みで
Spreadsheet　・・・ 1シート
GAS　・・・　適量

##完成イメージ
![スクリーンショット 2021-12-05 15.50.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1450663/4879da08-d936-1fb2-2ac7-3b200b0259ba.png)

##お好みのメールアドレスをとってくる
ここはなんでもOKです。
お気に入りのものが見つかったら、Spreadsheetの今回使うシートの中に置いといてください。
今回は、[コンテナバインド](https://auto-worker.com/blog/?p=344 "GASの書き方")で作っていきます。
そのほうが、スプレッドシートの操作が楽という利点があります。

```JavaScript:スプレッドシートのA2のセルからメールアドレスの値をとる
const sheet = SpreadsheetApp.getActiveSheet();
const mailAdress = sheet.getRange(2, 1).getValue();
```

##メールを検索
まずは検索条件の日付を取得していく。
今回は、直近の7日間で検索を行う予定なので、7日前の日付を取得する。

```JavaScript:7日前の日付を取得
const getSevenDaysBeforeDate = () => {
  const today = new Date();
  const sevenDaysBefore = new Date(today.setDate(today.getDate() - 7));

  const year = sevenDaysBefore.getFullYear();
  let month = sevenDaysBefore.getMonth() + 1;
  month = month < 10 ? '0' + month : month;
  let date = sevenDaysBefore.getDate();
  date = date < 10 ? '0' + date : date;
  
  // フォーマットは（uuuu/MM/dd）
  return year + '/' + month + '/' + date;
}
```
7日前の日付がわかったらそれを「after」で指定していく。

```JavaScript:スプレッドシートのA2のセルからメールアドレスの値をとる
const sheet = SpreadsheetApp.getActiveSheet();
const mailAdress = sheet.getRange(2, 1).getValue();

const threads = GmailApp.search('from:' + mailAdress + ' AND after:' + getSevenDaysBeforeDate());
```

##スプレッドシートに出力
出力する方法は、シート内のセルの範囲を指定して値をセットする。

```JavaScript:セルに値をセット
sheet.getRange(row, 1).setValue(message.getDate());
sheet.getRange(row, 2).setValue(message.getSubject());
```

##実行のトリガーを設定する
GASでは時間をトリガーにして、処理を走らせることもできますが、
今回は、使いたいときにちゃんとなっていればいいので、
トリガーをスプレッドシートの起動時と変更時にしておきます。
![スクリーンショット 2021-12-05 16.07.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1450663/670ffdd4-5598-f113-a172-e5fca7848c09.png)

##完成したものがこちら

```JavaScript:メール管理
/**
 * メールを取得してスプレッドシートに出力する
 */
const printMail = () => {
  const sheet = SpreadsheetApp.getActiveSheet();
  const mailAdress = sheet.getRange(2, 1).getValue();

  // 直近一週間のメールを検索
  const threads = GmailApp.search('from:' + mailAdress + ' AND after:' + getSevenDaysBeforeDate());

  let i = 0;
  let row = 5; // 5行目から出力する
  for (const thread of threads) {
    if (i >= 10) {
      // 10件分のスレッドを出力していく
      return;
    }

    for (const message of thread.getMessages()) {
      // スプレッドシートに出力
      sheet.getRange(row, 1).setValue(message.getDate());
      sheet.getRange(row, 2).setValue(message.getSubject());

      row++;
    }

    i++;
  }
}

/**
 * 現在日から7日前の日付を取得する
 * フォーマット（uuuu/MM/dd）
 */
const getSevenDaysBeforeDate = () => {
  const today = new Date();
  const sevenDaysBefore = new Date(today.setDate(today.getDate() - 7));
  
  const year = sevenDaysBefore.getFullYear();
  let month = sevenDaysBefore.getMonth() + 1;
  month = month < 10 ? '0' + month : month;
  let date = sevenDaysBefore.getDate();
  date = date < 10 ? '0' + date : date;

  return year + '/' + month + '/' + date;
}
```

##感想
自分のように、用心深い人はダブルチェック用に活用してもらえるといいなと思う。
また、これに関しては、どの方向に改良していこうか迷うところ。
時間をトリガーにして、何か通知が来るようにしてもいいしな〜。
カレンダーと連携して、何かできるようにしてもいいな〜。
なんて思いました。
Discordでの災害情報提供


この記事は[地震情報アプリ界隈 Advent Calendar 2021](https://adventar.org/calendars/6729) 6日目の記事です
#本題に入る前に。。
まず。お前は誰だって始まりますね。
今年もカレンダーにはBSC24関係者がいるし。地震ソフトの作成者など有名人しかいない中で、、
##自己紹介

孤独のコーヒーです
現在、学生で受験生です。
コロナの中、休校になり暇になったのでPythonに出会いいろいろ書いています、
2018年の胆振東部地震で停電などを経験し防災に興味を持つ
そして、2021年現在、気象庁xml を解析・提供しています、
（詳細は一週間後に、、、）
##Discord とは。。
ゲーム中で
ボイスチャットをするときに、使うのが本来の用途ですが。。
BOTを作れるなど（LINEでも作れますが。。）ゲーマー以外の人も使用している場合もあります、
https://discord.com/
#本題・・・
さてやっと本題に、入りますが
まず情報は、ぶっちゃけ言っちゃうと送信は簡単ではありますが、視認性が皆無です
なぜなら。。
![2021-11-28_10h24_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613330/1b564848-0a1b-e1aa-bc36-8dd0726bb34e.png)

このように、文字だけなんです。。。
（まぁ。、BOT用じゃなく人間が使用するために作られたんで、、）
ちなみに写真も上げることも可能ですが。。。
正味めんどいです、
けどいいところもある
タイトルを目立たせることもできる
そして、斜め文字や打ち消し線なども使用可です、
けど。。やはり。。表など使いたいです。
現在、気象庁xmlからはいろいろな情報が出ており、
文字のほうが見やすい！！！もあれば
表また写真のほうがわかりやすい！！
もあります、、、
そのため警報級などはプログラムでは対応しているものの、Discord には対応してないのが現状です
![2021-11-28_10h38_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613330/2f6d2b11-651e-ef22-feb7-1259338bfa98.png)

Discord 様お願いします、
デフォで表など作れるようにしてください！！
#本題2
Discord での災害提供の中での問題点です。
現在、discord にPython で送信する方法は、
webhook でのURLを使った送信、と直で送信する、二種類です

| |webhook  |直送信 |
|---|---|---|
|送信レスポンス |0.45s  |0.27ms  |

webhook で送信するにはURLが必要です
そのURLはその鯖の中のチャンネルで一つとなっているので
URLが増えるとその分、送信するのに時間がかかり、
うしろに登録しているURLに送信するまで時間がかかります
利点としては、URLさえされば、いつでも送信できることです
（URLは流出すると、大変なことになるので（荒らしなど）その点は気をつけています）

直で送信するにはBOTを鯖に入れる必要になるので
鯖主が導入する必要があります
利点は、いつでもコマンドを実行すれば、最新の情報をすぐ見れます
webhook だと。情報がどんどんチャンネルの後ろに行ってしまうため、
自分に関係ある情報を確認するまでに時間がかかりますが
コマンドを実行すると、自分に関係ある地域や今知りたい情報を、
見ることができます
（一時的にBOTを動かしてるPCに保存していますが詳細は次回）

##最後に
掲載される前日に、いろいろ追加したため、誤字脱字あると思います、、
もしあったら（あってほしくないけど）指摘お願いします。

まだまだ地震界隈では無名ですが、へぇ～こんなやつがいるんだー程度に認知していただければ、幸いです
windowsでpsqlのコマンドが認識されない人へ向けた記事

# windowsでpsqlのコマンドが認識されない人へ向けた記事

## 背景
PostgreSQLをインストール後、コマンドプロンプトにて
` psql -V `
を確認するも、
``` 'psql' は、内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチ ファイルとして認識されていません。```
と、エラーが吐かれてしまう。

## 原因
WindowsにPathがうまく通っていない

## 解決方法
Windowsのシステム環境変数にパスを通しましょう
＜手順＞
1. 設定→システム→詳細情報→システムの詳細設定→環境変数の変更
2. __システム環境変数(S)__よりPathを選択→編集
3. [新規]よりパスを登録→OK
### システム環境変数にPathがない場合
システム環境変数の欄の[新規]をクリックし、新規作成しよう。

## パスがわからない場合
デフォルトでインストーラーを進めていればCドライブよりPrograming Files/PostgreSQL/[version]/bin/psql (.exe)を参照するとよい。
パスの書き方がわからない場合はpsql.exeを右クリックし、一番下のプロパティ(R)より**場所:**という欄を参照するとよい（コピペ可）

## 私が詰まった要因
システム環境変数ではなくユーザー環境変数(U)にパスを渡しても作動しない。
これで２時間ほど詰まっていたのでどうしてもわからない方は一度チェックしてみましょう。
Flutter環境構築手順(M1 Mac)

## 0. はじめに
先日PCを新調したので改めてFlutterの環境構築手順を記載します。

- PC: MacBook Pro（14インチ、2021）
- チップ: Apple M1 Pro

※途中でXcodeのインストールが必要になりますが、かなり時間がかかります。Xcodeのインストールだけ先にやっておくことをおすすめします。

## 1. Flutterインストール
[公式サイト](https://flutter.dev/docs/get-started/install)からインストールしパスを通す

```
$ echo 'export PATH="$PATH:{pwd}/flutter/bin"' >> ~/.zprofile
$ source ~/.zprofile
```
※{pwd}はFlutterをインストールした場所によって変更する

## 2. セットアップ

```
# 以下コマンドを実行し必要な設定事項を確認できる
$ flutter doctor
```
### Android
- Android Studio  
    [こちらのサイト](https://developer.android.com/studio/install?hl=ja)などからインストール
- Androidエミュレータ   
    メニューバーから`Tools >> AVD Manager >> Create Virtual Device`の順に選択してエミュレータを設定する
![スクリーンショット 2021-12-05 15.16.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264889/dcfe42b4-cc5a-9207-d4be-3f358a9ae741.png)
- Android SDK Command-line Tools
    メニューバーから`Tools >> SDK Manager >> Appearance & Behavior >> System Settings >> Android SDK >> SDK Tools`の順に選択し、`Android SDK Command-line Tools`にチェックを入れてApplyする
![スクリーンショット 2021-12-05 15.22.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264889/8bf19989-67af-6395-cba3-479abb47ec7b.png)

- Android Licenses

```
# 色々聞かれるが全部y(yes)で答える
$ flutter doctor -android-licenses
```

### iOS
- Xcode  
AppStoreからインストール  
※時間がかかります！注意！！！  
インストールが完了したら下記コマンドを実行します

```
$ sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
$ sudo xcodebuild -runFirstLaunch
```

- cocoapods

```
$ brew install cocoapods
```
[React Native]TextInputのサイズを自動調整する方法

#はじめに

こんにちは。今週もReact Native開発のノウハウを投稿させていただきます。
Webページに入力欄を作るとき、`TextInput`がよく使われています。入力された文字に応じて、`TextInput`のサイズを調整したい、という仕様もよくあるのですが、React Nativeでそれを実現するのは思ったより難しい、と私が気づいています。
ちなみに、React Native Paperにも`TextInput`がありますが、スタイルをつけているため、カスタマイズが必要な場合、React Nativeの`TextInput`のほうが使いやすいと考えております。
調べたところ、`TextInput`のpropsに`onContentSizeChange`を設定したら、高さの自動調整ができるけれど、デメリットが二つあります。

1. `onContentSizeChange`では、改行する時発火されるが、行を削除する時発火されない、というバグがある
2. 高さが改行に応じて変更されるが、広さの変更ができない

となると、`onContentSizeChange`では希望に応えられないときが多いではないかと思っております。ほかに良い方法を考えなければならないですね。

#結論は最初に出す
`TextInput`の後ろに`Text`を重ねていれば、自動調整ができるようになります。
もちろん、`Text`コンテンツの末尾にZero-width-spaceを忘れないように。

#解決策
「Talk is cheap」、とにかくソースコードを見てみましょう。

```tsx
// ...
<View>
  <Text style={{fontSize: 18}}>
    {message}&#8203;
  </Text>
  <TextInput
    style={styles.msgInput}
    placeholder={''}
    onChangeText={text => setMessage(text)}
    value={message}
    multiline={true}
    numberOfLines={1}
  />
</View>
// ...
const styles = StyleSheet.create({
  msgInput: {
    position: 'absolute',
    top: 0,
    left: 0,
    fontSize: 18,
    width: '100%',
    height: '100%',
    overflow: 'hidden'
  }
});
```

ご覧の通り、`TextInput`に文字を入力したら、その後ろの`Text`にも表示されます。こうして、`TextInput`のサイズも`Text`と同じようになります。そして、`Text`のサイズは中に入れている文字次第のため、したがって`TextInput`のサイズも入力した文字に応じて自動調整ができるようになります。

###Zero-width-spaceについて
`Text`コンテンツの末尾に、`&#8203`をつけているのですが、これはいったい何でしょうか、と疑問を持っている方もいらっしゃると思いますね。
これはzero-width-spaceというものです。つまり、広さが0の文字のことです。
では、zero-width-spaceは何のためにここに入れているのでしょうか？
Zero-width-spaceをつけるのは、改行を対応するためです。
この文字をつけない場合、どうなるか見てみましょう。
![nospace.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252959/1f8b3b7e-6821-e582-bf70-fc9001b1d436.gif)
ご覧の通り、改行しても、何らかの文字を入力しない限り、高さが変更されなかったです。
Zero-width-spaceをつけましょう。
![withspace.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252959/9f25fe39-56c3-d0aa-712e-49b8a4ce8a74.gif)
Zero-width-spaceの広さがゼロですが、一つの文字として高さがあります。そのため、改行したら`Text`の高さも変更されます。
こうして、入力文字に応じて`TextInput`のサイズを調整することができます。

#最後に
この記事はあくまでも私個人（初心者として）の経験です。間違っているところ、もっと良い方法がございましたら、ぜひ教えてください。

#参考資料
https://github.com/necolas/react-native-web/issues/2160
https://www.yuzutalk.net/ ←このサイトは資料ではないけれど、同じく`Text`と`TextInput`を重ねていて、私にヒントを与えました
【OutSystems】入力フォームで未来の日付を入れた場合にエラーを表示させる

## もし、未来の日付を入れた場合、そのまま登録されてしまわないようにするには。

以下は、新規登録から名前と誕生日を入力すると、一覧画面に表示がされる画面です。
誕生日に未来の日付を入力した際、登録ができないようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2197080/51ce47bb-fdd0-f018-7a8e-44aa703ab234.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2197080/a08586ce-4b20-68bb-d984-f82ab1cba69a.png)

エンティティ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2197080/1bbe3abc-7674-84ee-6ce6-e093ca6a4aba.png)

Saveロジック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2197080/1891e136-f80b-e862-55c4-25ecbb2631f9.png)

#**①** If文
`ProfileForm.Record.Profile.DateOfBirth > CurrDate() `
ProfileFormのDate Of Birthが現在の日付よりも先であれば
と設定。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2197080/7d195ada-bc2a-48f6-7ca4-4b0243d0e1ec.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2197080/e79bac63-095c-ad81-9caa-e0daac9c1b74.png)

#**②** True(現在の日付よりも先)の場合
`Profile_DateOfBirth.Valid = False`
ProfileFormのDate Of Birthは違いますよ
と設定。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2197080/337c3163-3050-758b-ec5c-9e41e80eb81c.png)

#**③** データを検証
`not ProfileForm.Valid?`
ProfileFormにユーザーが正しい日付を入力していない？
という設定。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2197080/969acdeb-f3a3-c37f-b2bb-2b08c51ea2dd.png)

FormウィジェットのValidプロパティにアクセスすることにより、クライアントアクションでデータを検証している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2197080/103360b4-fec1-cb4f-1309-5ac6dc67949d.png)

ProfileFormにユーザーが正しい日付を入力していない？
->はい、正しい日付を入力していない(未来の日付を入力)場合は、
右に進み(True)、フィードバックメッセージ(「日付が正しくありません」など)を表示させEnd。

->いいえ、正しい日付を入力している場合は、
下に進み(False)、Profileをアップデートして、フィードバックメッセージ(「登録しました。」など)を表示させEnd。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2197080/df4c5f1b-4d41-179f-9556-da2499cdb4a0.png)
Sublime Text 初期設定

## ① `Sublime Text 3`をインストールする
下記URLからダウンロード・インストールする。
http://www.sublimetext.com/3

## 【前提】 コマンドパレットの開き方
`Cmd`+`Shift`+`P`で開く。

## ② パッケージコントロールをインストールする
1. https://packagecontrol.io/installation から`Package Control.sublime-package`をダウンロードする。
2. コマンドパレットから`Preference: Browse Packages`を開く。
3. `2`で開いたディレクトリに`1`でダウンロードしたファイルを移動する。（`Packages`ディレクトリの配下でOK）
4. コマンドパレットから`Install Package Control`を実行する。
5. `Sublime Text`を再起動する。

## ③ メニューを日本語化する
1. コマンドパレットから`Package Control: Install Package`を実行する。
2. `Japanize`をインストールする。
3. メニューバーは日本語化されるが、トップメニューがまだ英語表記のため、追加で下記手順を行う。
4. コマンドパレットから`Preference: Browse Packages`を開く。
5. `./Packages/Japanize`にインストールされている`*.jp`ファイルを`./Packages/Default`にコピーする。（`Default`フォルダがない場合は作成する）
6. `5`でコピーしたファイルの拡張子を`.sublime-menu`に変更する。（ファイル末尾の`.ja`を削除すればOK）
7. `./Packages/Japanize/Main.sublime-menu`（元々の拡張子が`.jp`でない方）を`./Packages/User`にコピーする。

## ④ Shift-JISファイルを表示できるようにする
1. コマンドパレットから`Package Control: Install Package`を実行する。
2. `ConvertToUTF8`をインストールする。

## ⑤ 全角スペースを可視化する
1. コマンドパレットから`Package Control: Install Package`を実行する。
2. `TralingSpaces`をインストールする。
3. コマンドパレットから`Preference: Trailing Spaces Settings`を開く。
4. 下記を設定する。

```json
{
    "trailing_spaces_regexp": "　|[ \t]+"
}
```

## ⑥ 日付・時刻を自動入力できるようにする
1. コマンドパレットから`Package Control: Install Package`を実行する。
2. `InsertDate`をインストールする。
3. コマンドパレットから`Preferences: Key Bindings`を開く。
4. 下記を設定する。（`Cmd`+`;`で現在日付、`Cmd`+`:`で現在時刻を自動入力できるようになる）

```json
[
    {
        "keys": ["super+;"],
        "command": "insert_date",
        "args": {"format": "%Y/%m/%d "}
    },
    {
        "keys": ["super+:"],
        "command": "insert_date",
        "args": {"format": "%H:%M:%S"}
    },
]
```

## ⑦ その他基本設定
1. コマンドパレットから`Preferences: Settings`を開く。
2. 下記を設定する。

```json
{
    "draw_white_space": "all", // タブ・半角スペースを表示する
    "font_size": 13, // フォントサイズを13ptにする
    "highlight_line": true, // 選択行をハイライトする
    "show_encoding": true, // 文字コードをフッターに表示する
    "show_line_endings": true, // 改行コードをフッターに表示する
    "translate_tabs_to_spaces": true, // タブで半角スペースを入力する
}
```

## 参考文献
- [SublimeText使い方メモ](https://qiita.com/opengl-8080/items/0c3a35d6dc2e1ab82cb1)
- [SublimeText3のPackage Controlインストール方法やプラグイン設定のメモ](https://photo-tea.com/p/17/sublimetext3-settings/)
- [WindowsでSublimeText3日本語化は意外と分かりづらい（mac版追記）](https://qiita.com/I-201/items/0869a288eb6e4ed5a274)
- [Sublime Text 3でスペース（半角・全角）やタブを可視化する方法](https://nj-clucker.com/highlight-whitespace-characters-on-sublime-text/)
- [Sublime Text 2で日付をショートカット入力する](http://ytkyk.info/blog/2013/08/28/sublime-text-2%E3%81%A7%E6%97%A5%E4%BB%98%E3%82%92%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88%E5%85%A5%E5%8A%9B%E3%81%99%E3%82%8B/)
ハンズラボで過ごした1年間を振り返る

## ご挨拶

この記事は ハンズラボ [AdventCalendar2021](https://qiita.com/advent-calendar/2021/handslab) 5日目の記事です。

今月で入社1年経った中川です！
昨年もAdventCalendarに参加させてもらいましたが、あれから早1年
今回の記事ではハンズラボでの1年間を振り返りたいと思います。

## 振り返り

そもそも1年前の面接でAWS認定色々取りたいです！勉強会したいです！！
と言って面接をパスした手前、AWS認定取得と外部の勉強会参加を念頭に頑張ってきました。

結果としては
* 入社1年でAWS認定を5つ取得 → ハンズラボ内部でのAWS認定最多資格保持者になった
* 外部勉強会で登壇 → ２回登壇
* 自身で主催の社内勉強会開催

でしたので、個人的には割と頑張ったかなと思っております。
因みに9月〜12月まで資格を取れてないのは

* ハンズメッセ
* チーム移動
* 引っ越し

の３つが重なり中々落ち着けなかったのが原因です...

業務的な話はあんまり書けないのでアレですが、
東急ハンズファンとしてハンズネットのアーキテクチャ関連に携われたのですごく楽しかったです！

## AWS認定を色々取ってみて

AWS認定を取ってた上での業務上のメリットかなと思った点は

* AWSの知識の引き出しが増えた
* 色々なアーキテクチャパターンを覚えられた
* 多少なりとも自信がついた(AWSナニモワカナラナイ)

辺りかなと思います。
特にサービスとサービスの組み合わせやセキュリティを重視したアーキテクチャ、
AWSの使い方・考え方は仕事でめっちゃ役に立ってます！

ただ、同時に資格は持ってるけど経験値が浅い分野も数多くあるので、
知識として知ってはいるけど構築できるか怪しいと思う所もあるので、
これからも天狗にならずに精進が必要とつくづく感じました...

**AWS認定は取ったらゴールじゃない！取ってからがスタート！！**

※一応年内にもう後1~2資格位取りたいとはおもってます

## 来年の目標

* AWS認定11冠を目指す
* 内部,外部での勉強会の登壇
* ラボブログの記事を書きたい

ひとまずはAWS認定を制覇した上でLPICやCCNA・CCNPなどメジャーな物は取りたいとも考えております。
継続的なアウトプットが大事なので1ヶ月に1記事位は最低でも書きたいんですがネタが中々...
検証してみた系の記事とかも色々書きたいなとは考えております！

## 最後に

本当にあっという間の１年間でしたが１年で色々と成長を実感できたので凄く濃くて良い１年間だったと思います！
それもこれも社内の皆様や、勉強会で知り合った方々など多くの人の影響があってこそでした！！
今年も残り少ないですが、来年含めて引き続きよろしくお願い致します！！

## 取得したAWS認定まとめ

2021/01/29　AWS Certified Security Specialty

https://www.credly.com/badges/814a5a9a-8d6d-4357-8971-4cf9a74ca635/public_url

2021/03/05 AWS Certified SysOps Administrator Associate

https://www.credly.com/badges/16c52974-5d31-4da4-8a14-4b040c347898/public_url

2021/04/16 AWS Certified Developer Associate

https://www.credly.com/badges/d42d75be-e03d-44c0-8431-d59f2d0d2837/public_url

2021/07/24 AWS Certified DevOps Engineer Professional

https://www.credly.com/badges/f5fa8fa0-efff-4d04-abf5-b19b7bb6d7f8/public_url

2021/08/21 AWS Certified Solutions Architect Professional

https://www.credly.com/badges/ef865ee7-64ac-41ba-9a0c-da09012e19fd/public_url
azure batchってなんなん？

# azure batchとは
[Azure Batch とは](https://docs.microsoft.com/ja-jp/azure/batch/batch-technical-overview)


![azure_batch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/0fe3243e-68dc-972a-f233-3e2afb5f0167.png)

MSのドキュメントの通りですが、

## 利用用途
1.一時的に
2.大量の計算を
3.並列で実行したい
処理が利用用途に合います。

## 利点
大量のリソースをAzureマネージドサービスで簡単に準備、処理の実行ができます。

# プール、ノード、ジョブ、タスク
[Azure Batch のノードとプール](https://docs.microsoft.com/ja-jp/azure/batch/nodes-and-pools)

[Azure Batch でのジョブとタスク](https://docs.microsoft.com/ja-jp/azure/batch/jobs-and-tasks)

azure batchを利用する上で、
- プール
- ノード
- ジョブ
- タスク

これらを理解する必要があり、ドキュメントを読めばわかるのですが、
はじめうまく理解できなかったため、以下のように図にしました。

![node.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263851/e7d680b5-da2a-3c70-9fa8-90f9e84d86cc.png)

## プール
VMのテンプレート定義と理解しています。

一つのプールには同じスペックのVM（仮想マシン）を複数作成できます。

つまりスペックが異なるVMが必要な場合は別プールを用意する必要があるということです。

## ノード
VMという理解で問題ないと思います。


## ジョブ
タスクの集合体であり、一つのプールにひも付きます。
ここがポイントだと思っていて、ジョブが紐づくのはプールであり、
ノードではありません。

ジョブに属するタスクがどのノードで実行されるかはAzureBatchによって振り分けられ
利用者視点ではタスクがどのノードで実行されるかを意識する必要はありません。

## タスク
大量に実行したいなんらかの処理の最小単位

# Azure Batch と　Azure Kubernetes Service
Azure BatchとAKS(Azure Kubernetes Service）は似ています。

AKS(Azure Kubernetes Service）をご利用の方は、Azure BatchでできることってAKSでできるのでは？
と思われることでしょう。

用途に応じて使い分けるとよいでしょう。

（個人的には）設定の難易度 Azure Batch < AKS　という理解なので、
まずはAzure Batchを検討して、ハマらないようであればAKSを検討する。といった形がよいかと考えます

# まとめ
さくっと大量に処理できるリソースを準備したいバッチ処理がある場合にはAzure Batchの利用を
検討されてみてはいかがでしょうか。

実際読んだだけだとよくわからないと思うので実際手を動かしてみるとよいと思います
具体的な設定手順は@nakazaxさんの以下記事がわかりやすいです。
https://qiita.com/nakazax/items/47daae65708bc3188cbf
【React】Reactにおけるメモ化に関して(useCallback / useMemo / React.memo)

どうも、[@ちーず](https://qiita.com/cheez921)です。
アドベントカレンダー5日目、本日のテーマはReactにおけるメモ化に関してです！！

## :question: そもそもメモ化とは？

> プログラムの高速化のための最適化技法の一種であり、サブルーチン呼び出しの結果を後で再利用するために保持し、そのサブルーチン（関数）の呼び出し毎の再計算を防ぐ手法である。
> 
> メモ化された関数は、以前の呼び出しの際の結果をそのときの引数と共に記憶しておき、後で同じ引数で呼び出されたとき、計算せずにその格納されている結果を返す。
>
> 参考: [メモ化 - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%A2%E5%8C%96)

つまり、**計算結果をキャッシュし、それを再利用すること**をメモ化と言います。


## :question: なぜメモ化が必要？
Reactでは下記のようなタイミングでComponentが再レンダリングされます。

* **state / props が更新**された時
* **親コンポーネントが再レンダリング**された時

Componentが再レンダリングすると、
そのComponent内で定義している関数や変数も新しく生成されてしまい、
**値が変わっていなかったとしても再計算**されてしまいます。

Reactでは油断しているとそのような**予期していない再計算**が増えてしまい、
サイトのパフォーマンスが影響する可能性があるため、メモ化の重要度が高いです。


## :warning: メモ化する時の注意点

軽い処理に対してメモ化すると、キャッシュを参照するオーバーヘッドが発生します。
また、メモ化の必要性はアプリケーションによっても異なります。

そのため、何でもかんでもメモ化するのではなく、**実行してみてパフォーマンスがちゃんと改善したか確認しながら**メモ化するとよりパフォーマンスの向上に繋がると思います。

(ちなみに自分はなんでもかんでもメモ化しちゃっていました...反省)

## :pencil: Componentをメモ化 - `React.memo`
`React.memo`は、Componentをメモ化する[HOC（higher-order component）](https://ja.reactjs.org/docs/higher-order-components.html) です。
Propsの値に変更がなかった際の再レンダリングを抑制することができます。

:::note info
HOCとは、あるコンポーネントを受け取って新規のコンポーネントを返すような関数のことです。
:::


### 書き方

```jsx
// 第一引数: 関数Component

export const heavyComponent = React.memo(() => (
  // とても思い処理
  <p>子Componentです</p>
));

```

### どんな時に使う？

#### レンダリングコストが高いコンポーネント
(そもそも、値のメモ化でどうにかなるケースの方が多そうですが...)
Component自体が重い処理をもっている場合は、メモ化することでレンダリングを避けることができます。

#### 頻繁に再レンダリングされてしまう可能性があるコンポーネント
親Componentの変更が頻繁に発生する場合、子コンポーネントがその度に不要な再レンダリングをしてしまうため
`React.memo`でメモ化することおすすめします。

:::note warn
親Componentの処理に依存してComponentがのレンダリングが頻繁に起きてしまう場合、
そもそものComponent設計が正しくない可能性もあります。

そのような場合は、脳死メモ化するのではなく一度設計を見直した上でメモ化することをおすすめします。
:::


## :pencil: 値をメモ化 - `useMemo`
`useMemo`は、実行結果や値をメモ化することができるフックです。

### 書き方

```jsx
// 第一引数: コールバック関数
// 第二引数: 依存配列 - この値が変更された時のみ再計算

useMemo(() => function(), [deps])
```

### どんな時に使う？
#### 非常にコストのかかる計算を行う場合

非常にコストのかかるの定義は難しいですが、
下記記事をよんでみると、100回くらいの配列のループで`useMemo`を使うのは意味がないかなぁ。。。と思いました。

▼ 参考: メモ化していない時と

https://off.tokyo/blog/react-usememo-when-to-use/

* 500回以上のループ処理並の複雑さの処理
* 何度も再レンダーされる可能性がある

時に使えるかなと思いました！


## :pencil: 関数をメモ化 - `useCallback`
`useCallback`はメモ化されたコールバック関数を返すhooksです。

### 書き方
```jsx
// 第一引数: コールバック関数
// 第二引数: 依存配列

const func = useCallback(() => {
  // callback関数
}, [deps]);
```

### どんな時に使う？

#### 関数を返すカスタムhooks
カスタムフックは、再利用性を高いhooksを定義するためのものであり、
Component側で呼ばれる際にその関数が再生成されることを利用者側が考えなくても良いように設計すべきです。
そのため、カスタムフックが関数を返すなら、基本的にメモ化することをお勧めします。

筆者は下記記事にものすごく感銘を受けたので、より詳しく知りたい人はぜひ読んでください！！

▼ 参考

https://blog.uhy.ooo/entry/2021-02-23/usecallback-custom-hooks/


#### メモ化されたComponentに関数を渡す場合
`React.memo`の復習になりますが、propsの値が同一である場合は再レンダリングは走りません。

しかし、そのまま関数をメモ化された子Componentに渡してしまうと
親が再レンダリングされたタイミングで関数が再生成されてしまうため、同一の値と判定されないため再レンダリングが走ります。

そのため、関数の同一性を保つために`useCallback`で囲いましょう！


---

以上 「Reactにおけるメモ化に関して」 でした！！
いつか、メモ化パフォーマンス改善実験をやってみたいな〜と思います！！
Retrofit+OkHttpでファイルダウンロードするAPIを呼び出す

### はじめに

今日はRetrofit+OkHttpでファイルダウンロードするAPI呼び出しについて書いていきたいと思います。  
検索すると古いバージョンの話やAndroidに特化した内容の記事が多くヒットしたのですが、今回紹介するのはWebサイトで同期的にAPIを呼び出す前提のやり方です。

### バージョン

- retrofit:2.9.0
- okhttp:3.14.9

### 実装方法

#### Retrofitのインスタンス生成

レスポンスをバイト列で受け取りたいので今回はコンバーターを設定しません。

```java
Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://localhost:8080")
            // コンバーターを指定しない
            //.addConverterFactory(JacksonConverterFactory.create())
            .build();
```

#### インターフェイスの実装

サービスから戻り値を変換せずに`okhttp3.ResponseBody`で受け取るように宣言します。また`@Streaming`をつけておかないとダウンロードしたファイルが一気にメモリに展開されてOutOfMemoryErrorが起きる可能性があるので注意してください。

```java
public interface DownloadService {
    @Streaming
    @GET("/download")
    Call<ResponseBody> download();
}
```

### 呼び出し方

あとはAPIを呼び出して取得したレスポンスに対して`response.body().byteStream()`するとダウンロードしたファイルがInputStreamで取得できるのでファイルに保存するなり好きにしてください。

```java
// API呼び出し
DownloadService service = retrofit.create(DownloadService.class);
Response<ResponseBody> response = service.download().execute();

InputStream is = new BufferedInputStream(response.body().byteStream());
OutputStream os = new BufferedOutputStream(
        new FileOutputStream(new File("/tmp/test.gif")));
try (is; os) {
    int read = 0;
    byte[] bytes = new byte[1024];
    while ((read = is.read(bytes)) != -1) {
        os.write(bytes, 0, read);
    }
}
```

### おしまい

以上、最近仕事で実装しているRetrofitについての3日間連続投稿でした。
駆け出したあと、EMとして走り続けている理由

# 冒頭

望む望まざるに関わらずと言いますか、社内のEM（エンジニアリングマネージャー）としては割と経験年次を重ねている部類になってきました。

ただただ任されたプロダクトの改善に没頭し、メンバーは部下というよりは同じ第一線に立つ仲間として、「お願いします！」「ちゃんとやってくれよ！」と日々叱咤、それを「マネジメント」だと思い込みながらとにかく全力疾走していた、そんな頃から比べるとやや一皮剥けた感触があります。

# なんでEM（エンジニアリングマネージャー）やってんだっけ

そんな折、メンバーから「なんでEMやってるんですか？」とか「開発だけしてた方が楽しくないですか？」みたいな、いわゆる世の中でよく言われるエンジニアのお悩み、みたいなやつをよくぶつけられるようになりました。

一昔前だったら
「エンジニアのキャリアとしてはやっぱりさ、マネジメント経験やっといて絶対損はないでしょ」
みたいな、マネージャーあるあるのただの正論をかましていたかもしれません。

でも確かに、別に毎日毎日「きゃーたのしー」みたいにやってるわけでもないので、「そういえばなんでだっけ、言語化できるんだろうか」と疑問に思い、今回筆をとった次第です。丁度EMのアドベントカレンダーの投稿枠も（半ば強引に）お預かりしたのでそれにも乗っからせていただきたく。

# 自分だけエンジニアとして面白い仕事をしてるのもずるいなーと思ったから

書いてるうちにグダグダになりそうだったので、先に結論を。あれこれと考えていて、一番大きな理由はこれかもしれないです。

何個かポイントはあると思ってますが、自分は多分プログラミング未経験からのエンジニアキャリアとしては非常に恵まれた環境に合ったと自負していて、それに伴って自分のこれまで歩んできた道のりについてはとても素敵なものだなと思えています。

## プロダクトを任せてもらえた

プログラミング未経験の新卒に、入社2ヶ月後にリリース間近のβ版新商品を預けるなど、今から考えるとある種の狂気です。大事故をやらかすかも知れませんし、未成熟故に心が折れて虚しく道半ば退場してしまうかも知れません。
そもそも、未経験なので短期間でのハイパフォーマンスもなかなか見込めません。

にも関わらず、商品を任せ、徐々に人を任せ、チームを任せ、という英断、狂気。

まあ実際心は何度も折れたと思うのですが、一方で「自分の責任によってプロダクトを作る手応え」「チームとを引っ張る」というのは、自分のエンジニアのキャリアとしてすごく自信を与えてくれる経験となりました。

## ある程度結果が出た

加えて、非常に幸運にも市場でのニーズ拡大タイミングに乗ることができたおかげで、プロダクトは業界内では一定程度認知していただけるだけのシェアを獲得することができました（満足はしてないです、もっといきたいと毎日思ってます）。

そうするとやっぱり、「こんにちは、私こういうものです」という名前とともに語る名乗りにも力が増してくるのか、相手様の反応も変わってきます。
そうした反応を目にするたび、一つ自分の次のステップを勝ち取るのを後押ししてくれる資産とも言える積み上げになっているのだなと感じます。

## 実績→チャレンジのサイクルに乗れた

そして実際、「じゃあこれもやってみたら？」と次のチャレンジをいただくことができ、結局また四苦八苦七転八倒五里霧中暗中模索するものの、どうにかこうにか着地するところまでは辿り着ける経験させてもらうことができました。

そしてそうしたことが繰返され、気づくと「大変ではあるけれどもやってよかった」みたいな仕事をやり続けるサイクルに乗っかっているのだなと気づきました。

人間というのは不思議なもので、「やってよかった、２度とやりたくないけど」という仕事ほど、語りながら飲む酒がうまいのです。

# で、下の子たちは？

「こいつ遺言状書いてんのか」みたいな自叙で誠に恐縮です。ようやくここから本題の回答に移ります。

マネージャーやって2年くらい経った時に、「泣きながら仕事頑張ってるメンバー」に出くわしたんですよね。

すげー頑張ってる。飲み込みも悪くない。「私商品をなんとかよくしたいんです」って。
でもなんか、やってるのはよく見たら「先人が作った負債の回収」。

## モヤッとしました。

自分は好き放題に開発をやらせてもらえて、メンバーを預けてもらえた、ある程度結果が出て、でも下の子たちはその道をつづいてくることができているのだろうか。

もしかして、自分が歩いてきた道は、自分が荒らして閉ざしてしまっていないだろうか。
「自分は必死に頑張ったから」、ただそれだけでその道を歩むことができていたんだっけ。
たくさんの人に後押しをもらったり、環境をお膳立てしてもらえたからではなかっただろうか。

（ちなみに技術負債について運用で向き合うことは、正義だと思っています。フェーズが違うだけで力もつくし、必ず全ての人がどこかで向き合わないといけない壁です）

## そっか、それが今の俺の役割だった

至極当たり前なことを自覚するのに一周してしまった感覚です。

そして「自分だけいい思いをしてたら、多分自分の仕事も楽しくなくなる」そう思いました。
後に続くメンバーたちも、「大変だけど、エンジニアとして仕事をしていてよかった」そう思わせてこそ、自分の仕事に満足できて美味しく酒が飲める。

そのための環境や後押しをするのが今の自分の仕事だった、というわけです。

# 勉強することが死ぬほどたくさんある

という感じで、もう結論までいってしまったのであれなんですが、もうちょっとだけ続きます。
「これが自分のやることなんや！」って自覚を持ってから、あれこれとインプットを始めました。

* エンジニアのキャリア
* 組織論
* 開発環境の改善事例
* もっと現場を良くするためのプロダクト改善技術・ツール

知れば知るほど知らないことが多く、溺れていくかのようです。

一方で、メンバー一人一人、それぞれに対してのポテンシャルを死ぬほど強く感じられるようにもなりました。
選択肢は死ぬほどあるし、それぞれが価値を出せる未来が見える。

多分諸先輩方から見れば小鳥の囀り程度のことかも知れませんが、自分がジタバタするには十分な気づきであり、目一杯やっていこうと思える内容です。これからも日々日々精進を重ねていきたいと思います。
【環境構築】macOS Big Sur 11.6.1 + Dockerでpython

会社貸与のMacBook Proに飲み物をこぼしてしまい動かなくなったので交換してもらった。:bow_tone1:
前のマシンにはPythonやらPandasやら使いたいライブラリーを直接インストールしていたので、環境のトラブルがあった場合に色々と面倒だった。今回は素直にDockerで環境構築して、いざとなればimage捨てて作り直せばいいやと思い、環境構築の手順をロギング。

今回はPythonのコンテナを起動するところまで進めたい。

前回記事
[環境構築]macOS Big Sur 11.6.1 にDockerをInstall
https://qiita.com/cocoapuff/items/e3eee747b1aeafa32037

# pythonのimageをpull

dockerhubで良さげなimageを探す

https://hub.docker.com

pythonで検索してみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2351871/dcd85e2e-5f64-0a21-a5f4-0ba3b1133914.png)
[dockerhubより]

素直に"python"を選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2351871/d1fa284e-0cd0-7697-0956-79d90cd3fde0.png)

[dockerhubより]

"Official image"ということで、まずはこのimageを使ってライブラリーはお好みで追加することにする。

ここから先はCLIで作業が必要になってきた。
仕方が無いので、とりあえずTerminalを起動して、pythonのimageをpullする
この時、Dockerが起動していること
pythonのバージョンを指定しなければ最新のものを引っ張ってくる

```
$ docker pull python
```

実行結果

```
Using default tag: latest
latest: Pulling from library/python
5e0b432e8ba9: Pull complete 
a84cfd68b5ce: Pull complete 
e8b8f2315954: Pull complete 
0598fa43a7e7: Pull complete 
83098237b6d3: Pull complete 
b92c73d4de9a: Pull complete 
57f48b8baa06: Pull complete 
702d43ac0fd7: Pull complete 
5e2753218c06: Pull complete 
Digest: sha256:a1fba384d3aa879533a271ab5d73965fbd3385648f38835dacd07e519f1c7c3f
Status: Downloaded newer image for python:latest
docker.io/library/python:latest
```

# pythonのコンテナを起動

とりあえずpullしたimageを起動してみる
プロンプトが変わる

```
$ docker run -it --name test python /bin/bash
＃
```

pythonのバージョンがいくつか確認してみる

```
# python --version
Python 3.10.0
```

Docker DesktopのDashboardを見てみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2351871/e0b75347-5549-7dd5-f7af-50e8f295d328.png)

動いてます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2351871/337330bc-df54-5b51-cb66-649b4b378d9f.png)

"test"コンテナにマウスを当てると"CLI"を起動できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2351871/b571f5a5-f268-e87f-2612-4feecf249d76.png)

# pythonコードを動かす

ちゃんとpythonコードを実行できるか試してみようと思ったら、viが動かない

```
# which vi
#
```

無いと何かと不便なのでviをインストールする

```
# apt-get update && apt-get -y install vim
```

実行結果の表示は長いので割愛
vi入った

```
# which vi
# /usr/bin/vi
```

"Hello World"を書いて動かす

```
# vi test.py
```

```python:test.py
print("Hello World")
```

```
# python ./test.py
Hello world
```

動いた。今日はここまで。
Mac OS を Big Sur にして npm が command not found になった時の対処方法

結論から言うと

```Terminal
echo "export PATH=$HOME/.nodebrew/current/bin:$PATH" >> ~/.zprofile
```

ではなく

```Terminal
echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.zshrc
```

で解決した。

## やったこと

最初にこれを読んだが見ている node -v の場所が違うようだった。
https://tanarizm.com/command-not-found-npm

なので、こちらをさらに参考に。
https://khom-loi.com/on/56

一旦、解決したと思ったのにまた npm のパスが通らなくなったので、下記を試したら直った。
https://chaika.hatenablog.com/entry/2021/03/26/083000
ミルククラウン解析（その３，OpenFOAM での Smoothed CSF モデルの実装）

# 概要
オープンCAEシンポジウム2021のオープンCAEコンテスト2021に応募したミルククラウン解析の解析結果をコンテストが終了したので、順次公開します。

# Smoothed CSF (Continuum Surface Force) モデルの説明
OpenFOAMに実装されているのは、Brackbillらによって提案されたCSFモデルです。
CSFモデルでは、曲率の計算にセルの水の割合$\alpha$の勾配を用います。
一方、Smoothed CSF モデルでは、曲率の算出にスムーズ化した水の割合$\alpha$の勾配を用いることで、Spurious Currents の低減を図ります。
$$ \vec{F_\sigma}=\sigma\tilde{k}\nabla\alpha $$
$$ \tilde{k}=-\nabla\cdot\vec{\tilde{n}} $$
$$ \vec{\tilde{n}}=\frac{\nabla\tilde{\alpha}}{|\nabla\tilde{\alpha|}+\delta} $$
$$ \delta=\frac{10^{-8}}{(\frac{\sum_{N} V_i}{N})^{1/3}} $$
$$ \nabla\tilde{\alpha}=\frac{\sum_{f=1}^{N} \alpha_{c\rightarrow f}}{\sum_{f=1}^{N} S_f} $$

|変数|単位|説明|出典|
|:-:|:-:|:-:|:-:|
|$\vec{F_\sigma}$|N/m|表面張力|O. Ubbink, Ph.D Thesis of Imperial College London (1997).|
|$\sigma$|N/m|表面張力係数|同上|
|$\tilde{k}$|-|曲率|同上|
|$\vec{\tilde{n}}$|-|法線ベクトル|同上|
|$\delta$|-|ゼロ割防止変数|同上|
|$\nabla\tilde{\alpha}$|-|スムーズ化した水の割合$\alpha$の勾配|B. Lafaurie et al., J. Comput. Phys. 113, 134–147 (1994).|
|$\alpha_{c\rightarrow f}$|-|セル中心からフェイス中心への水の割合$\alpha$の補間値|同上|

# Smoothed CSF モデルの実装
ESI版OpenFOAM-v2106にSmoothed CSF モデルを実装したコードは、githubからダウンロードできます。
(a) githubのページに移動
https://github.com/yanagim/smoothedCSF/tree/release
(b) ページ内の"Code"ボタンを押下
(c) "Download ZIP"を選択

次回は、Smoothed CSF モデルを使用することで、どれくらい Spurious Currents が低減するのか確認します。
何故Modifierは最初のデフォルト引数でないといけないのか

Jetpack Composeでコード書いていると、次のような警告を見かけることがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53293/4f117c7f-e050-b9b3-84fc-ee4c3173d6ab.png)
Modifier parameter should be the first optional parameter

Modifierは最初のデフォルト引数であるべき、という話ですね。
例えば次のようなコードを書いた場合に上記の警告が出ます。

```kotlin
@Composable
fun SampleComposable(
  param: Boolean,
  optionalParam: String = "First optional param",
  modifier: Modifier = Modifier,
)
```

そしてこの方針はModifierのドキュメントにも書かれています。

https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier
> It should appear as the first optional parameter in the parameter list; after all required parameters (except for trailing lambda parameters) but before any other parameters with default values.


しかし何故Modifierは最初のデフォルト引数でないといけないのでしょうか？

# 先に結論

- ガイドライン上、そう定められているため
- APIの一貫性を保つため

# 詳細

警告を出しているLintの実装は以下です。

https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/ui/ui-lint/src/main/java/androidx/compose/ui/lint/ModifierParameterDetector.kt

このコミットログを追うと "for consistency with Compose guidelines" という記述が確認できます。
https://android-review.googlesource.com/c/platform/frameworks/support/+/1502816

そしてComposeのAPIガイドラインには次のような記述があります。

https://github.com/androidx/androidx/blob/androidx-main/compose/docs/compose-api-guidelines.md#elements-accept-and-respect-a-modifier-parameter

> Modifiers occupy the first optional parameter slot to set a consistent expectation for developers that they can always provide a modifier as the final positional parameter to an element call for any given element's common case.

Modifierを常に最初のデフォルト引数にしていくおくと、開発者は最後にmodifierを書けばいいと期待してコードを書けるらしいです。どういうことでしょう？

例えば、`Text`や`Button`が次のように実装されていたとします。

```kotlin
fun Text(
    text: String,
    modifier: Modifier = Modifier, // 1st optional parameter
    color: Color = Color.Unspecified
)

@Composable
fun Button(
    onClick: () -> Unit,
    enabled: Boolean = true,
    modifier: Modifier = Modifier, // 2nd optional parameter
)
```

これらをModifierを指定して呼び出すと次のようになります。

```kotlin
Text("sample text", Modifier.padding(8.dp))
Button({ /* onClick */ }, modifier = Modifier.padding(8.dp))
```

`Text`がシンプルに書けた一方、`Button`のModifierは2番目のデフォルト引数であるため、`modifier=`の名前付き引数にする必要が出てしまいました。

このようにModifier引数の順番が不規則であると、Composable毎に引数の順番を意識して書く必要が出てしまいます。Modifierが各所で使われる仕組みであることを考えると、これは良くないでしょう。

従って、一貫性を保つためにModifierは最初のデフォルト引数であるべき、としているわけです。
これを守ることでComposableを書くときには必須のパラメータを記述して、最後にModifierを書けばいい、という共通認識でコードが書くことができます。
.NET Framework 4.XではCheckedListBoxからVB6.Support.GetItemStringで値が取得できない

# 概要

- .NET Framework 4.XではCheckedListBoxから[Microsoft.VisualBasic.Compatibility.VB6.Support.GetItemString](https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.visualbasic.compatibility.vb6.support.getitemstring?view=netframework-4.8)メソッドで値が取得できない

## 検証結果

x86（32bitアプリケーション）、NetFx 3.5 および 4.7.2 でのみ確認しています。

|プラットフォーム|コントロール|フレームワーク|値取得|
|--|--|--|--|
|x86|ListBox|NetFx 3.5|OK|
|x86|CheckedListBox|NetFx 3.5|OK|
|x86|ListBox|NetFx 4.7.2|OK|
|x86|CheckedListBox|NetFx 4.7.2|NG|

:::note info
Microsoft.VisualBasic.Compatibility.VB6 は、4.7.2では、32bitアプリケーションしかサポートされていません。言い換えると、32bitアプリケーションはサポート対象ですが、32bitアプリケーションでも動作が変更となっていました。
:::

# 詳細（再現）

```vb
Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ListBox1.Items.Add("a")
        ListBox1.Items.Add("bb")
        ListBox1.Items.Add("ccc")
        CheckedListBox1.Items.Add("a")
        CheckedListBox1.Items.Add("bb")
        CheckedListBox1.Items.Add("ccc")
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        MsgBox(Microsoft.VisualBasic.Compatibility.VB6.GetItemString(ListBox1, 0))
        MsgBox(Microsoft.VisualBasic.Compatibility.VB6.GetItemString(CheckedListBox1, 0))
    End Sub
End Class
```

# 対処

次のように変更する

**変更前**

```vb
VB6.GetItemString(ListBox1, 0)
```

**変更後**

```vb
ListBox1.Items(0).ToString
```

# IDEでの正規表現例

:::note warn
変更前後で十分にご確認ください。
:::

検索： `(VB6.GetItemString\()([^,]+)(, )([^\)]+)(\))`
置換： `$2.Items($4).ToString`
STM32G031とVSCoed、計3ポート(PA11,PA12,PB7)でナイトライダー




x 過去ログを見よ->

x cubemxではstm32g0316-discoを選択
x VSCでnecleo-g031を選択(visual studio code)
x 動けば正義、細かい事を気にするな
x STM32G031J6M6との違い、ピン数


stm32g031_11_12_b7_1内をいろいろ適当にコピー


https://os.mbed.com/users/caa45040/code/f303_h_p1/


![o_con130.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/1dfd6833-0674-04ee-7488-dd2d1a0114be.jpeg)


![B8B04B3A-BCC7-4C46-8531-0A97761355EF.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/1a3262ce-d28d-dacb-0a96-b0539e65565b.jpeg)



```c++


    //b7    
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
    HAL_Delay(500);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
    HAL_Delay(500);

    //11
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_RESET);
    HAL_Delay(500);

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_SET);
    HAL_Delay(500);

    //12
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
    HAL_Delay(500);

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET);
    HAL_Delay(500);




```
【随時更新】はじめてレジリエンスを勉強している

##はじめに
個人的な備忘録及びQiita初心者です。
上記をご了承いただけると幸いです。
※現在絶賛勉強中のため随時更新【予定】です。


##レジリエンスとは
「**マイナスのメンタルからプラスに回復させる**」スキル

:::note warn
※注意※
ずっとポジティブなメンタルを
キープする考え方とは違います
:::

##どんな人におすすめ？
・ポジティブ思考は難しい人
・感情に振り回される人
・楽しく働きたい人

##メリット
１．「自分ならできる」自信を持てて、逆境でも強いメンタルを発揮できる
２．変化への対応ができる（立ち直ることができる）
３．失敗してもプラスにできることを理解できる
　　→チャレンジを繰り返すことができる

:::note info
レジリエンスが高い人が多い「組織」は
新しいチャレンジを多くできる。
→おのずと業績も上がりやすい
と、言われいている。
:::

##ストレス耐性のよくある勘違い
×ストレスを受けないようにする。
〇ストレスを受けても**”逃がせる”**ことを知ってる。
→ストレスに「勝とう」と考えるとより大きな負荷に「負ける」。
負けてもOKその後「立ち直れると知っている」ことが大事。
**※執筆者は過去、見事に大きな負荷に負けました！**

:::note alert
メンタルがマイナスに落ちて戻せないと
→失敗を恐れてチャレンジできなくなる
→成長が止まる
→体調に影響が出てしまう
:::

#まずなにする？
####メンタルが沈んだら
どんなに小さいことでもいいから__「できる」__ことをみつけて
実践し、積み重ねることで自信をつける。

##レジリエンスの磨き方
・底打ち（下降を止める）
・立ち直り
・教訓化
※逆境に強い（メンタルが強い）
　→先天的ではなく上記3つで鍛えられるもの。
※「あいつはメンタル強いから大丈夫」とか言われる人も
　　大体何等か過去の経験から鍛えられてる背景があるはず。

##具体的な磨き方
__底打ち__
→負の感情と向き合うこと。

__底打ちの方法例__
１．「事実」を書き出していく
２．書き出したものを眺めて「客観視」する
※第3者目線で見ると案外「そんなもんか・・」と思えることもあったりする。
３．「客観視」した「事実」をもとに「深堀り」をスタートする
→「なぜそう思った？」を書き出していく。

:::note info
「あくまで事実に基づく」こと。
:::
:::note warn
主観的な考え方はいけない
例：自分は実力がないから・・→×
:::

__立ち直り__

１．負の感情が生まれた__理由__を探る
２．今できる行動を起こす（どんなに小さくてもOK）
３．__「できる」__を実感する
１～３を繰り返す。

後日

__教訓化__

立ち直りで積み重ねた自信から
「この先自分はどうなりたい」ということを考えていく。

１．理想を描く
→_「じゃあどうしたい？」_を想像する。
２．次に備える
３．備えたことを発揮しやすい環境を作る
→サポーター（話を聞いてくれる人・共感してくれる人）を作る
※自分がサポーターになることも重要


:::note info
「マイナス」から何を学び「どういう風にしていきたいか」を考える。
:::

###どうしてもイライラするときは・・・

趣味に没頭する時間を作る
→切り替えのできる趣味を作っておくことは大事。

それでもだめなら・・・
※趣味をする元気すらないとき。（ありますよねぇ・・・）

:::note info
何も考えず寝る！
睡眠をとることでリフレッシュする！

心身を壊してまでやらないといけない仕事なんて
この世にはないはず。
:::

###極力使いたくない言葉
「どうせ」「でも」「だって」
→この言葉が自然と出てくるときは心理的に負荷が高いとき
or
掲げている目標が大きすぎる可能性が高い。

大きすぎる行動目標は心理的な負担になりえる
はじめは「達成できそう」な小さな行動から始めていく。
→どんなに小さいことでも__「できることをやる」__ことに意味がある。

大きな目標を掲げて気分が下がると、
「内的動機づけ」が働かず、行動がとれなくなる。
→目標があるのに行動できない→落ち込む（悪循環！）

「行動のハードルを下げる」ことは決していけないことではない。
→自分に適したハードルを設定する（できる）ことも重要なスキル。