OmniAICreator/Qiita-1.07M huggingface dataset:
HTTPSをnginxで終端しつつFastAPIにアクセスする。

# 概要

nginxをリバースプロキシとして使ってhttpsを終端しながら、
uvicorn + FastAPIを使う場合のことを書いた記事です。

# なんでこの記事を書いたか

serverディレクティブのproxy-passでFastAPIのサーバを指定するだけじゃ
FastAPIでOpenAPIのドキュメントが見れなかったので書きました。
ちなみにドキュメントのパスにアクセスすると以下みたいな画面になります。
`Fetch error Not Found openapi.json` 的なエラーが出る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86853/af60479d-8eff-2e05-d70e-7a3cd02e373c.png)

# 単にuvicorn + FastAPIをhttpsにするなら

[uvicornの公式のhttpsの項](https://www.uvicorn.org/settings/#https) にあるように

```shell
uvicorn main:app --host 0.0.0.0 --ssl-keyfile ./cert/privkey.pem --ssl-certfile ./cert/cert.pem
```
な感じでいけます。

# 前提

- Nginxではポート8000でリクエストを待ち受けている
- uvicorn + FastAPIはポート8001で待ち受けている
- NginxとFastAPIは同じサーバで動いている
- Nginxに対する `https://FQDN名:8000/fastapi` へのアクセスを uvicorn+FastAPIの `http://FQDN名:8001/` にプロキシする
- 証明書は既にげっとん済み。
- fastAPIの主な設定はmain.pyに書いている
- 筆者はNginxのconfigをほぼ書いたことない  
「あれでしょ、serverとかlocationとかのディレクティブに設定書いたり、
includeで他のファイルから設定を読み込めたりするんでしょ？」みたいなLv。

# nginxのconfigを書く

serverディレクティブとして以下を追記する。
とりあえず、 `/etc/nginx/sites-enabled/default` をコピーして
`/etc/nginx/sites-enabled/fastapi` というファイルを作成。

その中にserverディレクティブと以下のコンテキストを作成。

```nginx
server {
    # fastapiへのリダイレクトと証明書の設定
    listen 8000;
    ssl_certificate /etc/letsencrypt/live/fastapi.tmktmk.tmk/cert.pem;
    ssl_certificate_key /etc/letsencrypt/live/fastapi.tmktmk.tmk/privkey.pem;
    location /fastapi/ {
        proxy_pass http://fastapi.tmktmk.tmk:8001/;
    }
}
```

# FastAPIにroot-pathを設定する

main.pyに以下を追記

```python
from fastapi import Request #追加する。すでにFastAPIをimportしている行があるはずなのでそこに Request だけ追加する。

# 以下のようにroot_path=にnginxのlocationで記載したパスを記載する。
app = FastAPI(root_path="/fastapi")
```

# アクセスしてみる

`https://fastapi.tmktmk.tmk:8000/fastapi/docs` にアクセスする。
以下の感じでURLバーに鍵マークがついている事が分かります。
![スクリーンショット 2021-03-26 8.32.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86853/e6ad21c0-8cd1-843f-582a-bbcf0dacbbbe.png)

# 終わり

HTTPSでアクセスしたnginxを介してFastAPIにアクセスすることが出来ました。  
ちなみに、nginxではなくHAProxyを使うとFastAPI側の設定を変えなくても、
haproxy.cfgのbackendのところに普通にFastAPIのサーバを設定するだけでこの記事と同じことが出来たりします。
新人エンジニアを育成するときの人生論

#はじめに
本誌は新人育成をしている時に上手く育ってくれず、
悩んでいる方に送ります。


以下、こんなこと言ってます。
● エンジニアの一生は人生と同じ。
● 反抗は成長のあかしだから気に病まない。
● あなたが言ったことを真に理解するのは10年後だよ。

---------
#目次
1. 人生論とはどういうこと？
1. エンジニアの成長過程


---------
# 人生論とはどういうこと？
本誌で話したい内容は、育成曲線がーとかそういうロジカルな話ではありません。
新人育成というのは、赤ん坊を育てる親と同じ気持ちで
考えてあげると、いろいろな点ですっきりするよという話です。

もちろん人間の"赤ん坊からの一生"が千差万別であるように
新人もみんな千差万別の育ち方をするのが普通です。

会社から与えられた育成で
画一的に育つなんてことは１００％ありえないです。


新人が育たないのは、あなたが悪いわけではない。
また、新人が育たないのは、その新人が悪いわけでもない。


# エンジニアの成長過程
##入園前フェーズ
社会人：１年目
人生年齢：０～２歳

右も左もわからない新人は、とにかく先輩社員の言うことを素直に聞きます。
先輩社員からやり方を１から１０まで教わってもうまくいかないことがあり
先輩社員に助けを求めることもしばしば。

積み木の積み方をまねようとしてもうまくいかない。
０歳から２歳児のフェーズです。


##入園フェーズ
社会人：２年目
人生年齢：３歳から５歳
同期の話など外界の世界を知り始めるときです。
特に周りの芝は青く見えるもので、
周りの同期のほうが恵まれてると思うこともしばしば。

先輩社員からのやり方を教わっても
自分の判断で違うやり方を実施して、結局怒られるということも。
先輩のやり方に理解ができずに衝突することもあるでしょう。

##小学生フェーズ
社会人：３年目
人生年齢：６歳～１２歳

先輩社員から少しずつ離れ、自分の力で歩み始めたころです。
案件にも慣れてきて自分の力で業務を進める自信を深めていきます。

簡単な案件を任せられて
成功経験を積み重ねることで
業務に対する自信をつけていきます。


##中学生フェーズ
社会人：４年目
人生年齢：１２歳から１５歳

社会人としての経験も積み重ねてきて自信もついてきたところ。
難しい問題にチャレンジするケースが増えてきます。

ちょっとできてきた自分に天狗になり
大きなミスをやらかすタイミングでもあります。

障害報告書などのガチ対応が必要になったりと
社会の厳しさを本当の意味で目の当たりにすることもしばしば。

中学生では、勉強が難しくなりついていけなくなったり、
補導されて警察にお世話になるケースもあったり。
親に対する反抗もあり、精神的には不安定になりやすい時期です。


##高校生フェーズ
社会人：５年目から７年目
人生年齢：１６歳から１８歳

世の中には難しい案件や技術が山ほどあることを理解し、
自己学習の大切さに気が付き始める。

自分を磨き高められるかが後々に響いてくる時期。


##大学生フェーズ
社会人：８年目から１０年目
人生年齢：１９歳から２２歳

仕事をするうえで、自身が得意とするやり方を習得し始め
専門性を高めていくフェーズ。
社内からも信頼が高まり、難しい案件をアサインされることも多い。

##成人後フェーズ
社会人：１０年目～３５年目
人生年齢：２３歳から６５歳

仕事をする上では最も長いフェーズ
この年次になると新人（赤ちゃん）を授かることも多く
今度は自分が育てる側に回ることになる。

ここでいう育てるとは新人育成の指示を受けることではなく、
自分が全責任を負わなくてはいけない案件に
新人を入れてＯＪＴしなければならないという状況を指しています。


新人を育てながら、自分が新人だった時に先輩社員から言われた
同じことを新人にもいうようになり、
その時初めて、自分の先輩の言っていた意味を深く理解します。

育成の難しさを感じて、
また自身も成長する。

##老後フェーズ
社会人：３５年目～
人生年齢：６５歳～

最新技術に必死についていこうとするが、
体力が追い付かなくなる。

でも周りからはなんでも知っている
経験豊富な人材

若手PMの下について、その豊富な経験を生かして活躍する。

##死後
社会人：定年退職
人生年齢：死亡

エンジニア人生に終止符を打った時。
死亡した後、が天国か地獄か

死後の世界がどのような世界なのかは知る由もない。



# つまり
新人がうまくできないのもしょうがない。
反抗するのも成長のあかし。

あなたが言っている内容をちゃんと理解するのは
１０年後だと思ったほうがいい。

それを自分の育成は、育成論に従ったすごい育成だから、
０歳の赤ちゃんに逆上がりを教えられると意気込んでもしょうがない。

でも、それもできちゃう赤ちゃんも稀にいるだろうけど
それはそれ。


長い目で見よう。
【Swift】カスタムセルの幅設定がうまくいかないときに思い出すこと

# どういうことか

カスタムセルを `sizeForItemAt` にて画面幅いっぱい（`view.bounds.width`）に設定しているハズなのに真ん中に**ギュッ**と縮んだ状態で表示されてしまう！！

## コレ

![0cf8227a74336d7f82ba4e1413b5c874.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413699/bba70cfb-6abd-697e-1109-b42ac57ae6df.png)

`Estimate Size` を `Automatic` から `None` にする。
ちょいちょいハマる。。
「モンテカルロで円周率」を理解する

# モンテカルロ法で円周率の近似値を求めるアレ
モンテカルロ法で円周率の近似値を求めることができます。
有名な、内部に円が描かれている正方形に点をたくさん打つアレです。
![イメージ図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558315/6098f01c-55a8-9167-fb11-bee099673b05.png)
式はこんな感じ。

```math
\pi = \frac{　円の中に入った数　}{打った点の合計} \times 4
```

なんでこれで円周率の近似値が求まるのか？
初めて理解した時はけっこう感動しました。
やってることは単純で簡単なので、解説してみます。

# 解説
### ステップ1
まず半径1の円と、その円に外接するような正方形（1辺の長さが2）を描きます。
![図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558315/e8461f39-df42-c22b-cef1-102875518a4a.png)

### ステップ2
次に「この正方形の中に無作為に点を打ったとき、点が円の中に入る確率」を考えます。
この確率は2通りの方法で求めることができます。

【単純な確率計算で求める】

```math
確率 = \frac{　円の中に入った数　}{打った点の合計}　・・・①
```

【面積の比率で求める】
　　無作為に点を打つので、正方形に対する円の面積の比率がそのまま確立と同じ値になります。
　　正方形の面積は「縦 × 横」なので 2 × 2 で 4。
　　円の面積は「半径 × 半径 × π」なので 1 × 1 × π で π。
　　つまり確率は下記で求められる。

```math
確率 = \frac{円の面積}{正方形の面積} = \frac{\pi}{4}　・・・②
```

### ステップ3
最後にステップ2で求めた2つの確率式をもとに式変形をします。
①と②はともに同じ確立を表した式なので、「=」で繋げられます。

```math
\frac{\pi}{4} = \frac{　円の中に入った数　}{打った点の合計}
```
はい、これで両辺に「4」をかければ最初に紹介した式の完成です。

```math
\pi = \frac{　円の中に入った数　}{打った点の合計} \times 4
```


# Pythonで実装
仕組みを理解したところで、実際に近似値が求まるかPythonで実装してみます。
円の中に入ったかどうかの判定には円の公式を利用します。
半径1の円の公式はこちら。

```math
x^2 + y^2 = 1
```

つまりランダムに生成したx座標、y座標が以下の条件を満たせば、円の中に入ったと言えます。

```math
x^2 + y^2 <= 1
```

では、点を100回打ってみます。
ソースコードはこちら。

```python
import random

def get_pi(iteration):
    in_square = 0
    in_circle = 0
    for i in range(iteration):
        x = random.random()
        y = random.random()
        in_square += 1
        if (x * x + y * y <= 1):
            in_circle += 1
    pi = (in_circle / in_square) * 4
    return(pi)

print(get_pi(100))
```
出力結果：3.2
おお、円周率は「3.1415926535...」なのでまあまあ良い値が出ましたね。

このように、たくさんのランダムな値（乱数）を与えて、事象を確立的に解析することを
**モンテカルロ法**といいます。

# 試行回数を増やしてみる
先ほど点を打った回数は100回でしたが、もっと試行回数を増やしてみましょう。

|試行回数|近似値|
|----|----|
|100回|3.2|
|1,000回|3.22|
|10,000回|3.1536|
|100,000回|3.13652|
|1,000,000回|3.148724|
|10,000,000回|3.1414596|
|100,000,000回|3.141593|

試行回数を増やすほど精度が向上していますね。

# せっかくなので可視化も
せっかくなので可視化もしてみました。
点を打つ回数が100回のものと10,000回のもので、それぞれ100個の近似値を求めて比較してみます。

![グラフ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558315/49fe1608-99ec-5a10-59b3-7eec5a04361c.png)


点を100回打ったときよりも、1万回打って求めた近似値の方が「3.14...」に近い値が多いことが分かります。
可視化すると説得力と安心感が増しますね。
可視化大事。

ちなみに可視化はPythonの**matplotlib**というライブラリを使用して行いました。

```python
import matplotlib.pyplot as plt

x = []
for i in range(100):
    x.append(get_pi(10000))
    
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.hist(x, bins=10, rwidth=0.8)
ax.set_xlim(2.7,3.6)
ax.set_ylim(0,30)
fig.show()
```

おわり。
Windows仮想デスクトップを簡単に切り替えるキーボードを作ってみたのでご紹介

# はじめに
キーボードにこだわりなく過ごしてきましたが、在宅ワーク環境を見直していたところ、自作キーボードが流行っていると知り、早速、作ってみることにしました。

# 出来上がり
ボタンが４つだけしかないキーボードでケースが無いのでレゴ（笑）を使ってケース風にしました。
根が関西人なもので派手好き（？）なため、こんな感じになりました。
![A2D69C6D-235D-4AD0-9F70-64841137033F.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/ae8490ba-e308-05a5-b28d-c76644c3a503.jpeg)

元は↓こちら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/81b9e568-39fc-960d-a824-424c264cc228.png)
※遊舎工房さまのHPから引用しました。
https://shop.yushakobo.jp/products/meishi2

# 操作イメージ
仮想デスクトップを４つ用意してボタン１つで仮想デスクトップを切り替えられるようにしています。
![B459838C-1B84-47E7-B14E-54D15AA11EE7.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/0aafda99-5f2e-40f7-2f90-6a40298005a9.gif)

# キーボードの作り方
こちらを購入
https://shop.yushakobo.jp/products/meishi2

作り方もこちらを参考にしました
https://biacco42.hatenablog.com/entry/2019/08/10/185624

このあたりはド素人なので割愛します m(_ _)m

# Windowsでショートカットキーを作成
Windowsでは標準で仮想デスクトップを番号入力で切り替えるショートカットがありませんでした。
ですので、Autohotkeyというソフトをインストールして作成します
https://autohotkey.com/download/

インストールしたら↓のスクリプトを任意フォルダなどに保存
https://github.com/pmb6tz/windows-desktop-switcher

↓のファイルの部分のコメントをはずす（Ctrl+Alt＋１、２、３、４の意味）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/7fd0a02f-cf51-4312-60bf-6beb11904f82.png)

desktop_switcher.ahkを起動（スタートアップフォルダにショートカットを保存して自動起動するようにしてください）

これでCtrl+Alt＋１、２、３、４で仮想デスクトップを操作イメージのように移動できるようになります。

# 自作キーボードにショートカットキーを割り当てる
QMK Toolboxのインストール
https://salicylic-acid3.hatenablog.com/entry/qmk-toolbox#QMK-Toolbox%E3%82%92%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89%E3%81%99%E3%82%8B

キー割り当てをGUIでできるQMK Configuratorを使用しました。
https://config.qmk.fm/#/handwired/boss566y/redragon_vara/LAYOUT_fullsize_ansi

↓のように配置してCOMPILEボタン→FIRMWAREボタンでhexファイルをダウンロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/a994ee03-b8bb-1416-2acd-ee9b507fa0eb.png)

QMK Toolbox起動、ダウンロードしたHEXファイルを読み込む、Auto-Flashをチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/d8c5bd5d-391c-ce9b-addf-41ef1fc2a650.png)

Meishi2をUSB接続

Meishi2のリセットボタンを５回ほど連打

一旦、Windowsから認識されなくなり、再度認識しなおしたらmeishi2にキーマップが書き込まれます
以下のように最後にThank youとでればOKだと思います。(;^ω^)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/a1a099cc-2063-b71f-2a96-571c1fb7d7e6.png)

# 最後に
秋葉原にある遊舎工房さんで見たこれが非常にカッコよく、次はこれを作りたいと考えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/5009de45-1ede-047f-27ed-ddab74778789.png)
Python/C APIを読む その2(参照カウント)

#概要
Pythonの構造を理解する助けとして、C APIのドキュメントを読み砕いていく。

#内容
##環境
Python 3.7 (CPython)に話を固定するため、
以下のコミットに話を限定したいが、必ずしもそうはならない。
[tree](https://github.com/python/cpython/tree/a144feeb7ec501aaf30072d50e70d54b200e5ef0)   ([コミット](https://github.com/python/cpython/commit/79373951b3eab585d42e0f0ab83718cbe1d0ee33); [ブランチ](https://github.com/python/cpython/tree/3.7))
(↑　githubのリンク)

##内容
###`Py_INCREF(o)`
####＜概説＞
オブジェクト`o`に対する参照カウントを一つ増やす。([出典](https://docs.python.org/ja/3/c-api/refcounting.html#c.Py_INCREF))

####＜定義＞
```c:定義　(cpython/Include/object.h)
static inline void _Py_INCREF(PyObject *op)
{
#ifdef Py_REF_DEBUG
    _Py_RefTotal++;
#endif
    op->ob_refcnt++;
}
#define Py_INCREF(op) _Py_INCREF(_PyObject_CAST(op))
```
([定義出典](https://github.com/python/cpython/blob/145bf269df3530176f6ebeab1324890ef7070bf8/Include/object.h#L437))

####＜使用例＞
```c:使用例　(cpython/Objects/classobject.c)
    Py_INCREF(func);
    im->im_func = func;
```
([使用例出典](https://github.com/python/cpython/blob/63298930fb531ba2bb4f23bc3b915dbf1e17e9e1/Objects/classobject.c#L110))



###`Py_DECREF(o)`
####＜概説＞
オブジェクト`o`に対する参照カウントを一つ減らす。参照カウントがゼロになったら、オブジェクトの型のメモリ解放関数 (`NULL`であってはならない) が呼ばれる。([出典](https://docs.python.org/ja/3/c-api/refcounting.html#c.Py_DECREF))

####＜定義＞
```c:定義　(cpython/Include/object.h)
static inline void _Py_DECREF(
    PyObject *op)
{
    if (--op->ob_refcnt != 0) {
    }
    else {
        _Py_Dealloc(op);
    }
}
(中略)
#  define Py_DECREF(op) _Py_DECREF(_PyObject_CAST(op))
```
([定義出典](https://github.com/python/cpython/blob/145bf269df3530176f6ebeab1324890ef7070bf8/Include/object.h#L462))
※大筋を変えない程度に改変した。

####＜使用例＞
```c:使用例　(cpython/Objects/classobject.c)
    Py_DECREF(im->im_func);
```
([使用例出典](https://github.com/python/cpython/blob/63298930fb531ba2bb4f23bc3b915dbf1e17e9e1/Objects/classobject.c#L240))

##蛇足
```c:Python.h
...
#include "object.h"
...
```

#参考にさせていただいた本・頁
上記参照
#感想
内部を見れているようで面白かった。
#今後
続けていきたい。
F#でクワイン書いてみた (多分これが一番短いと思います)

# クワインとは

クワイン(Quine)というのは、そのコード自身と一致する文字列を出力するプログラミングの遊びです。

# F#でクワイン

ただの思いつき。

```fsharp
(fun f -> printf f f.Value) "(fun f -> printf f f.Value) %A"
```

空白を削ったバージョン。54文字。最短かな？多分これが一番短いと思います。

```fsharp
(fun f->printf f f.Value)"(fun f->printf f f.Value)%A"
```
Java学習　基礎編　クラスとインスタンスとは？

Java学習の備忘録になります。
内容は初心者なので基礎的な部分となります。
Javaに興味がある方やJava学習初心者の参考になれば幸いです。

* * *
#### クラスとは？

『**クラスは、インスタンスを作るための設計図である。**』

インスタンスは、情報と振る舞いを持っており、
この情報と振る舞いを設計図であるクラスに定義する。

人間を例にすると、
情報にあたるのが、「名前」、「年齢」であり、
振る舞いにあたるのが、「あいさつする」、「歩く」などである。

#### クラスの定義
プログラムの一番外側に記述されているもので、クラスの中には具体的に何をさせたいのかを、メソッドの形で記述していく。

```Main.java
class クラス名{

}
```

#### インスタンスとは？

『**インスタンスは、クラスから作られた実体である。**』

インスタンスは実体という意味。
オブジェクトの別名がインスタンスなのは、設計図から実際に生み出された実体であるため。

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

インスタンスは変数に代入して使用する。

【定義方法】
**クラス名 変数名 = new クラス名(引数);**

* * *

### インスタンスの情報と振る舞い

インスタンスの情報にあたるものを、**インスタンスフィールド**と呼び、振る舞いにあたるものを、**インスタンスメソッド**と呼ぶ。

#### インスタンスフィールド

インスタンスにどのような情報を持たせたいかを考え、それをクラスに定義する。

インスタンスフィールドは、情報を格納しておく変数にすぎない。
その変数は、クラスの一番上に記述する。

インスタンスフィールドは、各インスタンスに属する。
インスタンスを生成するときに、各インスタンスにフィールドがコピーされるというイメージ。

【定義方法】
**public データ型 変数名**

```Person.java

class Person {
  public String name; // 名前を入れる変数を定義
}
```

#### インスタンスフィールドへのアクセス
インスタンスへのアクセスには、　ドット( . )を用いる。

【定義方法】
**インスタンス名.フィールド名**

また、下記のように値の取得とセット(代入)が可能となる。

```Main.java

Person.person1 = new Person(); // インスタンスの生成
person1.name = "Tanaka"; // nameに値をセット

System.out.println(person1.name); // nameの値を取得
```

#### インスタンスメソッドの定義

インスタンスの振る舞いは、プログラム上では、メソッドで表現する。
これをインスタンスメソッドと呼ぶ。

【定義方法】
**public 戻り値の型 メソッド名()**

```Person.java

class Person {
  public void hello() {
    System.out.println("こんにちは");
  }
}
```

#### インスタンスメソッドの呼び出し

インスタンスメソッドは、クラスに属しても、実際は各インスタンスに属するイメージ。
それゆえインスタンスメソッドは、インスタンス(を代入した変数)に対して呼び出す。
その際は、ドット( . )を用いる。

【定義方法】
**インスタンス名.メソッド名()**

```Main.java

Person.person1 = new Person(); // インスタンスの生成

person1.hello(); // インスタンスメソッドの呼び出し

```

* * *
#### おわりに
今回は、基本的な定義方法をメインに記載してます。長くなりそうなので実際の使用方法やコンストラクタのなどは次回へ。
なお、ご指摘などございましたら、遠慮なくお願いいたします！！
Styled-Componentを使いまわす

Rails × react SPAの作成に当たりstyled-componentを使用している。
せっかくなのでstyled-componentを使いまわす練習がしたい(0からスタイル考えるのめんどくさいってのは内緒)

## ①コンポーネントをexport

styled-componentを定義している箇所でexportしましょう

```jsx
export const FormBlock = styled.div `
  margin: 10px auto;
  width: 40%;
  display: flex;
  flex-direction: column;
```

## ②コンポーネントのimport

コンポーネントを使いまわす先でimportします。
このとき通常の名前付きexportの場合は{}で囲う必要があります。
default exportの場合は囲わなくていいみたいです。

```jsx
//コンポーネントの読み込み
import {FormBlock} from "../common/UserModal.jsx"
```

今回は通常のexportなので{}で囲います。

## ③スタイルを継承しつつアレンジ

スタイルを継承しつつアレンジすることもできます。
その場合はexport先となるコンポーネントでスタイルを定義する際に
以下のように **styled(継承したいコンポーネント名)** と記述します。

```jsx
const BooksFormBlock = styled(FormBlock)`
  width: 80%;
  & label {
    font-size: 16px;
  }
  & input {
    height: 24px;
    line-height: 24px;
  }
  
  & textarea {
    height: 100px;
    resize: none;
  }

`
```

こうするとexportしたコンポーネントのスタイルを踏まえつつ、アレンジしたいところだけ
アレンジできます。



## 実際にやってみました。

今回例としてモーダルウィンドウを使いまわしてみました。
かんたんにデザインに統一感が出せるので非常にありがたいですね。
![recommended-books-3-2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/452c53df-a34f-dbe1-500e-8b27d227e6ec.gif)
TwitterKitのUIWebView問題(TwitterKit for Unity)

Unityでアプリを開発しているが、そろそろ公開のための準備を、と思って色々やり始めてみた。

Archiveを「Distribute App」した際に、「ITMS-90809: Deprecated API Usage」となりビルドがアップされなかった。

調べてみると、TwitterKitでUIWebViewを使用しているためとのこと。

https://qiita.com/nekomimimi/items/5ed56d1c3973b9dc71f7

↑こちらを参考に、↓を導入してみたところ大丈夫だった。本当にありがたい。

https://github.com/savani24/TwitterKit5

<h1> 実際に対応したこと</h1>
ダウンロードしたTwitterKit5の『TwitterKit.framework』をプロジェクトの同名ファイルと置き換えるだけでOKでした。

2021/03/26追記
> <h1> 実際に対応したこと</h1>
> ダウンロードしたTwitterKit5の『TwitterKit.framework』をプロジェクトの同名ファイルと置き換えるだけでOKでした。

嘘です。すいません、ダメでした。。
Validatorで署名が違うと怒られる。

podを使って、『TwitterKit5』をworkspaceに含まれるようにしてやらなければダメだった。

<h1> 実際に対応したこと その２</h1>

Firebaseをunityで使用していたので、firebaseがpodを出力している部分を参考にpodに『TwitterKit5』が書き出されるように変更した。
(ExternalDependency Managerを使用していると思われる。これはGoogleAdsをimportした際に追加されていた気がする）

(1) 適当な場所にEditorフォルダを作成する。（Assets/Twitter/Editor）

(2) 以下の内容でTwitterKitDependencies.xmlを作成する。（名前は適当です）

``` TwitterKitDependencies.xml
<dependencies>
  <iosPods>
    <iosPod name="TwitterKit5">
    </iosPod>
  </iosPods>
  <androidPackages>
  </androidPackages>
</dependencies>
```
(3) 競合を避けるため、以下をAssetsから削除

「TwitterKit.framework」
「TwitterCore.framework」
「TwitterKitResources.bundle」
「TwitterShareExtensionUIResources.bundle」

(4) 『TwitterKit5』と『TwitterKit』で.hの名前が変わっているので、適宜置き換える。

以上でビルドも成功し、Validatorでも怒られずアップする事ができました。
Missing trailing comma  comma-dangle（firebase deploy）

` firebase deploy`しようとしたら
こんなエラーが出ました。

```
$ firebase deploy


/Users/name/React/chatbot-app/functions/.eslintrc.js
  13:44  error  Missing trailing comma  comma-dangle

✖ 1 problem (1 error, 0 warnings)
  1 error and 0 warnings potentially fixable with the `--fix` option.

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! functions@ lint: `eslint --ext .js,.ts .`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the functions@ lint script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/name/.npm/_logs/2021-03-25T05_53_19_710Z-debug.log

Error: functions predeploy error: Command terminated with non-zero exit code1

Having trouble? Try firebase [command] --help
```

よくエラーを読んでみるとコンマがないって言われてるので
コンマ入れてみたら直りました。
自動生成の時にうまくいっていなかったのでしょうか(泣)
こんな事に何時間も使ってしまいましたのでメモしておきます。

```
/Users/name/React/chatbot-app/functions/.eslintrc.js
  13:44  error  Missing trailing comma  comma-dangle //末尾にカンマないよ？

✖ 1 problem (1 error, 0 warnings)
```
Node.jsでLINEBOTを作ってみた②

#はじめに

パート①は[こちら](https://qiita.com/hidesan4869/items/5f0e6bad6105cf7a742c)

前回までにやったこと
・Node.jsのインストール
・npmのインストール
・npm initによるpackage.jsonファイル作成
・expressのインストール

###Herokuにアプリを作成する
https://jp.heroku.com/home

上記よりHerokuの新規登録orログイン
ターミナルでHerokuを操作するためにCLIのインストールが必要となります。

下記の記事を参考にHeroku CLIをインストールしてください。
https://note.com/makoto0419/n/n113b55afa395

Heroku上にアプリを作成してみましょう。

```ターミナル.
heroku create hogemarukun
```

herokuのアプリ名は他の誰かが使っているアプリ名を指定した場合は、アプリが作成出来ませんので、違う名前で試してみてください。

###LINE公式アカウントの作成

https://qiita.com/maKunugi/items/e6fc7f51071ab3696d5f

上記の記事を参考にアカウント作成をしてください。

1. プロバイダーを作成。プロバイダー名はなんでもOK。
1. 新規チャンネル作成→Messaging API
1. チャンネルアイコン画像登録→LINEに表示されるBOT画像です。
1. チャンネル名登録→LINEに表示されるBOTの名前です。
1. その他必須項目を適当に入力して「作成」

<アカウント作成後>

1. Webhook URLの入力→先ほど作成したHerokuアプリに紐付きますので、herokuアプリ名が「hogemarukun」ならば以下のように入力します。
https://hogemarukun.herokuapp.com/hook/
更にwebhookの利用をオンにします。
1. チャンネルアクセストークン（長期）→「発行」
1. 応答設定→応答モード：bot、あいさつメッセージ：オフ、応答メッセージ：オフ

###おわりに
パート①、②が開発をするまでの環境構築までの流れとなります。
パート③は[こちら](https://qiita.com/hidesan4869/items/9b3bc2b8fb790eb8e2d5)
【Mac版】PythonにおいてSeleniumを用いたブラウザ制御時にChromeDriverエラーが発生した場合の対処法（Selenium 4.6.0以降は不要）

## エラー発生
**Selenium**はWebブラウザ自動化テスト等の用途で使用されるポータブルフレームワークである．

Webブラウザ**Google Chrome**はバージョンが自動更新されるため，ある日突然下記のようなエラーが発生してしまうことがある．焦る気持ちを抑えつつ冷静に対処しよう．

```
selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 87
Current browser version is 89.0.4389.90 with binary path /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
```

上記の場合
**Google Chromeのバージョンは89.0.4389.90**
**ChromeDriverのバージョンは87**

結論から言うと**Google Chrome**の自動更新により，**ChromeDrive**rとの間にバージョン差が生じてしまう事が原因である．

## Google Chromeのバージョン確認
まずはGoogle Chromeブラウザ右上の`︙`をクリック

**ヘルプ**
![chromever1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478088/94ed83f1-d079-f9e8-2cfa-b6798fe61bcd.png)

**Google Chromeについて**
![chromever2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478088/89d9a3cf-4839-969d-4be8-bd67c4ad8f8f.png)

**Google Chromeのバージョンを確認**
![chromever3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478088/8c04a765-9d79-f390-3d91-b001d91eedc2.png)

## ChromeDriverのダウンロードとインストール
下記サイトにアクセス
[ChromeDriver - WebDriver for Chrome](https://chromedriver.chromium.org/downloads)

先程確認した**Google Chrome**のバージョンに近いバージョンの**ChromeDriver**のリンクをクリック
![chromever4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478088/faeeb45c-69c8-4190-f805-938dcb0cb02d.png)

使用OS等に応じてZIPをダウンロード
![chromever5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478088/845eff7d-ff8e-895d-0d1b-f92d2c70fbe4.png)

ダウンロードしたZIPをデスクトップ上に解凍 (**chromedriver**が出現)

**chromedriver**を`/usr/local/bin/`へ移動 (`/usr/local/bin/`へパスを通している場合
```
mv ~/Desktop/chromedriver /usr/local/bin/
```

**chromedriver**のバージョンを確認
```
chromedriver -v
ChromeDriver 89.0.4389.23
```

これで本エラーは発生しなくなるが，**Google Chrome**のバージョン更新は不定期的に必ず行われるため今後同様のエラーが発生しても慌てずに．
Qiita Daily Survey memo 2021.03.26

# Qiita Daily Survey memo 2021.03.26
Qiita の記事を可能な限り毎日読むために、読んだmemoを公開することでモチベーションを維持しようという試み。

## [Pythonのデコレータってなんですか? と採用面接で聞かれて答えられなかった話](https://qiita.com/shitikakei/items/0d218c26d4d1bbede6b3)
七花 京(shitikakei)さんの記事。
タイトルの通り、Python のデコレータとは何ぞや、という記事です。
デコレータの詳細については、本記事を読んでいただくとして…。
私はそもそも初耳でしたので、そういうのがあるのかーと勉強になりました。
>先日、面接の際にわかりますか？ って聞かれてなんだっけ？ となって結局わかりませんと答えてしまったので、情けなく感じたので復習します。

プライド持って勉強・お仕事されてるんだなーと感じました…SUGOI。
自分が勉強している分野でも、知らない技術を「分かりますか？」と聞かれて「知りません」となったら、「そういうのがあるのかー」くらいにしか感じなさそう…。
ちゃんと勉強している自負があるからこそ、知らないと悔しいというか情けないという感情が生まれるんだろうなーと思いました。SUGOI。

また、記載されているソースコードのコメントが勉強になりました。
よくある「コメントどこまで書くのか問題」について、個人的には「足りなくなければ好きなだけ書けばええやん」と思っています。
本記事のソースには、コメントがかなり多めに書かれていますが「復習」や「自分の勉強用」という視点で見ると、適切な量に見えます。
言葉で表現が難しいですが…何と言いますか、意図を持ったコメントに見えて新鮮でした。


## [2021年に日本が注力したいことを総理所信表明演説から分析してみた](https://qiita.com/asmg07/items/e9e753cfd187cd2cb999)
asmg07 さんの記事。
センシティブなところ攻めますねぇ！？と思って記事を開きましたが、内容はword count系の分析で、かつ結論には言及せず避けていらっしゃいました。
グラフを作成したりtree map や word cloud を作成されるまでの流れが書かれていて、参考に動かしてみるがやりやすい記事だと感じました。
題材がセンシティブなので、分析結果に言及できないのがもったいないなー…と感じてしまいました。
逆に言えば、あまり公開されない分析だと思いますので、そこを自分の手でできるのはよいことなのかな…？とも感じました。


## [シンプルで使いやすい画像Base64変換ツールを作ってみた](https://qiita.com/presto/items/21a6713a108da35075c0)
presto さんの記事。
タイトルの通り、画像とBase64の変換をしてくれるツール（サイト？）を作成されたという記事になります。
やりたいこともUIもシンプルなので使いやすく、まさに「こんなツール、あんなツールが身近なところにあったらいいなぁ」を実現されたのだなーと感じました。
How to use も丁寧に書かれていてわかりやすいです。
Node.jsでLINEBOTを作ってみた①

#はじめに
JavaScriptの学習の中で、サーバー側を書いてみたいと思い、以前から興味のあったLINEBOTの制作をしてみようと考えました！

###作りたい予約システムを考える

1. 「予約」と入力すると予約に関するメッセージをリプライ
1. 予約は自動
1. 次回予約を確認
1. 予約のキャンセル
1. 予約が確定された時の、管理画面の制作

###システムの全体像
![Line Messaging API (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705266/0d5c02d0-2a28-5cdf-212b-88a52b0bdf95.png)

###開発環境
1. MacBook
1. macOS Catalina 10.15.7
1. Visual Studio Code

###技術選択
1. Node.js（Express）
1. JavaScript
1. Heroku
1. PostgresSQL
1. LINE MessagingAPI

LINEを使ったBOT構築はMessaging APIが必須となります。
インフラ構築は学習コストがかかると判断したので、簡単にプログラム公開できるHeroku。データベースはPostgreSQLを使います。

Heroku,PostgresSQL,MessagingAPI全て無料範囲内で納まりますので安心です。

※自動でやりとりする上で、すぐに返事が返ってきますよね？
Herokuだと30分サーバーにアクセスがないとスリープモードに切り替わってしまい、アクセスから立ち上がりまで時間がかかってしまうという問題が発生してしまいます。
ですが、スリープ問題をほんのり解決できる裏技もあるので、今後紹介していきます。

###Expressのインストール
※Node.jsやnpmのインストールする記事はたくさんありますので割愛します。

Visual Studio Codeでcontrol+shift+@を押すとターミナル画面が開きます。

```ターミナル.
npm init
```
npm initはnode.jsにおけるパッケージを管理するファイル「package.json」新規作成するためのコマンドです。ルートフォルダ下に「package.json」ファイルができたかと思います。そのファイルの中身を見ると、こんな感じになっています。

```package.json
{
 "name": "hogemarukun",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "scripts": {
   "test": "echo \"Error: no test specified\" && exit 1"
 },
 "author": "",
 "license": "ISC"
}
```

nameの部分はなんでもおけです！

**次にExpressのインストールをします。**

```ターミナル.
npm install express --save
```

package.jsonをみてみましょう。

```package.json
{
 "name": "hogemarukun",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "scripts": {
   "test": "echo \"Error: no test specified\" && exit 1"
 },
 "author": "",
 "license": "ISC",
 "dependencies": {
   "express": "^4.17.1"
 }
}
```

"dependencies": {
   "express": "^4.17.1"
が追加されたと思います。

####おわりに

パートを何回かに分けて書いていきますので
今回はこの辺りで！
パート②の構築記事は[こちら](https://qiita.com/hidesan4869/items/dddc48737959c4732f47)
CSSだけでポップアップを作る

CSSだけでポップアップを簡単に作れたのでメモ。
![ezgif.com-gif-maker (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291576/dae8f4ac-6d28-0848-a55e-72980ff9c239.gif)


## 仕組みを簡単に
まずポップアップのセクションを作成しておき、CSSで`visibility: hidden;`として見えない状態にしておきます。
ボタンのaタグに`href="#popup"`を設定し、ポップアップセクションにも`id="popup"`を仕込んでおきます。
ポップアップの方に
`popup:target { visibility: visible; }`
を設定すると、ボタンが押された時にポップアップが表示されるようになります。


## コード
```html:index.html
  <section class="tours">
    <!-- ボタン -->
    <a href="#popup" class="btn-green">More details</a>
  </section>
  <!-- ポップアップ -->
  <section class="popup" id="popup">
    <div class="popup__container">
      <h2>Lorem ipsum, dolor sit amet consectetur adipisicing elit.</h2>
      <p class="popup__text">Lorem ipsum dolor sit amet consectetur adipisicing elit. Modi ab culpa laborum rem, voluptate repudiandae sunt qui porro nam quia quae fuga cupiditate repellendus quas asperiores autem officia et recusandae facilis aliquam nisi corporis voluptates impedit. Sed, eius illum nesciunt suscipit illo quas, recusandae id dolorem labore obcaecati nulla. Fugiat?</p>
      <!-- 閉じるボタン -->
      <a href="#tours" class="popup__close">&times;</a>
    </div>
  </section>
```

```css:style.css
.popup {
  width: 100vw;
  height: 100vh;
  background: rgba(0,0,0,.8);
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1000;
  transition: all .2s;

  visibility: hidden;
}
.popup__container {
  width: 70%;
  height: 60%;
  background: white;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 5rem;
}
.popup__container h2 {
  margin-bottom: 2rem;
}
.popup:target {
  visibility: visible;
}
.popup__close {
  position: absolute;
  top: 2rem;
  right: 2rem;
  color: black;
  text-decoration: none;
  font-size: 5rem;
  line-height: 1rem;
}
```
SpriteRendererで加算表現するShader

SpriteRendererのcolorプロパティでは元の明るさを超える表現はできません。
そこでSprites-Default.shaderに加算処理を加えることで、白く光って見せることにしたShaderです。

Sprites-Default.shaderのコードはこちらにあるのを使ってます
[https://github.com/nubick/unity-utils/blob/master/sources/Assets/Scripts/Shaders/Sprites-Default.shader](https://github.com/nubick/unity-utils/blob/master/sources/Assets/Scripts/Shaders/Sprites-Default.shader)

プロパティに_Additiveを追加

```glsl:
	Properties
	{
		[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
		_Color ("Tint", Color) = (1,1,1,1)
		[MaterialToggle] PixelSnap ("Pixel snap", Float) = 0

		_Additive("Additive", Range(0, 1)) = 0
	}

```

フラグメントシェーダーのfragに加算処理を追加

```glsl:
			float _Additive;
			fixed4 frag(v2f IN) : SV_Target
			{
				fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color;
				c.r+=(1-c.r)*_Additive;
				c.g+=(1-c.g)*_Additive;
				c.b+=(1-c.b)*_Additive;

				c.rgb *= c.a;
				return c;
			}

```
このシェーダーを使ったマテリアルをSpriteRendererのMaterialにアタッチします
![Additive0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1146955/6c7654a4-0f93-0fe6-a721-9b06bc7b82b8.png)
![Additive1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1146955/d3872897-3f2f-be05-413d-8eba911ec25e.png)

マテリアルのAdditiveの値を変えると光って（白くなって）見えます。
スクリプトから操作するときは
Material.SetFloat(_Additive,value);
で変更します
【ROS】引数にファイル名を取る(C++)

ROS C++で引数にファイル名を取る方法をまとめました。
プログラムは以下のようになります。

```c++:ros_file_input.cpp
#include "ros/ros.h"

class TestClass
{
  public:
    TestClass(const std::string& fname)
    {
        std::cout << "Input file name:" << fname << std::endl;
    }
};

int main(int argc, char **argv)
{

  ros::init(argc, argv, "ros_file_input");

  if(argc==2 || argc==3)
  {
    std::string fname(argv[1]);
    TestClass tc(fname);
  }

  return 0;
}
```

```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
project(test)

find_package(catkin REQUIRED COMPONENTS
  roscpp
)

catkin_package(
)

include_directories(
 ${catkin_INCLUDE_DIRS}
)

add_executable(ros_file_input src/ros_file_input.cpp)
target_link_libraries(ros_file_input
  ${catkin_LIBRARIES}
)
```

```xml:ros_file_input.launch
<launch>
  <arg name="file_name" default="" />
  <node name="ros_file_input" pkg="test" type="ros_file_input" args="$(arg file_name)" output="screen" />
</launch>
```

##結果
実行してみると次の結果となり、ノード内のクラスがファイル名を取得できていることがわかります。

```console:
#ファイル名を入れて
$ rosrun test ros_file_input aaa.pcd
input file name:aaa.pcd

#launchの場合
$ roslaunch test ros_file_input.launch file_name:=aaa.pcd
input file name:aaa.pcd

```
Githubでのバージョン管理の流れ

# Githubでのバージョン管理方法
Githubでバージョン管理をする際の流れについてまとめてみました。
個人の学習記録や開発をする際に確認してみてください。

1.ターミナルを開き、管理したい、記録したいディレクトリまで移動

```
$ cd 管理したいディレクトリ名
```

2.公開鍵と秘密鍵を作成

```
$ ssh-keygen
```

実行後にパスフレーズの入力を求められますが、全て未入力でEnterキーでOKです。

3.公開鍵の出力

```
$ cat ~/.ssh/id_rsa.pub
```

このコマンドを打つと内容が表示されるため、コピペする。

4.Githubを開く

- Settingsを選択し、SSH and GPG keysボタンをクリック
- 緑色のボタン、New SSH keyをクリック
- Titleに好きな名前の入力、Keyにコピペした公開鍵を貼り付け
- 入力後、Add SSH Keyを押す。

これで公開鍵が登録されます。

5.ターミナルに戻り、Githubと接続する
下記コマンドを実行してください。

```
$ ssh git@github.com
```
初回接続の場合は、Are you sure you want to continue connecting (yes/no/[fingerprint])?と入力を求められますので、yesと入力しEnterキーを押します。

```
Hi *****! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.
```

こんな表示が出れば成功です！
さらにコントリビューションの設定も一緒に行いましょう！

```
username:~/environment $　git config --global user.name "GitHubのユーザ名"
username:~/environment $　git config --global user.email "GitHubに登録したメールアドレス"
```

ここまでの設定で、Githubにコミットをすると、コントリビューションを増やす(いわゆる草を生やす）設定が完了しました！

興味のある人は「Github　草を生やす」で検索してみてください。

6.ローカルリポジトリを作成する

```
$ git init
```

7.変更内容の保存コマンドを入力する

```
$ git add ファイル名orディレクトリ名
$ git commit -m "ここに一言メッセージを入力！"
```

ちなみに僕の場合、毎回全てのファイルをgithubにアップロードしています。

```
$ git add --all
```
このコマンドを打つと変更があった全てのファイルの内容が保存されます。

8.初期設定だとブランチがmasterブランチになっているため、mainブランチに変更する。

```
$ git branch -M main
```

9.自分の作業環境、ローカルリポジトリとリモートリポジトリを紐付ける

```
git remote add origin URLを入力
```

github側でNew repositoryをクリックし、Repository nameを入力しましょう。
Create repositoryを押すとリモートリポジトリが作成されます。

9.Pushする。

```
$ git push origin main
```

これでリモートリポジトリへPushされ、ここまでの作業内容が保存されます！
お疲れ様でした！
Materil-UIで作ったパスワードの入力フォームをreact-testing-libraryでテストするやり方

## 使用環境　##

    （１）material-uiをインストールしている。
    （２）react-testing-library　と Jest をインストールしている
    　　　※(2)は、npx create-react-app を実行するとデフォルトでインストールされます。
    （３）TypeScriptでコードが書かれている

## 目的 ##

　Materil-UIの`<Input/>`で作ったパスワード入力フォーム`<Input type="password">`のテストコードをどうやって書くか説明すること

## テスト対象のコンポーネント ##

　今回、テストを試みるのは、以下のコンポーネントです。

```tsx:Auth.tsx

import React, { useState } from "react";
import { FormControl, InputLabel, Input } from "@material-ui/core";

const Auth: React.FC = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  return (
    <>
      <FormControl>
        <InputLabel htmlFor="password">パスワード</InputLabel>
        <Input
          id="password"
          type="password"
          value={password}
          onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
            setPassword(e.target.value);
          }}
        />
      </FormControl>
    </>
  );
};

export default Auth;

```

## 試した方法①　getByRole( )を使用→上手くいかない

```tsx:Auth.test.tsx
import React from "react";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import Auth from "./Auth";

//その１ getByRollを試してみる
describe("入力フォームの更新イベント", () => {
  it("入力フォームに値が正しく入力されるか確認します", () => {
    render(<Auth />);
    const emailInput = screen.getAllByRole("textbox")[0];
    userEvent.type(emailInput, "test");
    expect(emailInput.value).toBe("test");
    const passwordInput = screnn.getAllByRole("textbox")[1];
    userEvent.type(passwordInput, "test");
    expect(passwordInput.value).toBe("test");
  });
});
```
まず最初に`getByRole()`関数を使ってみたのですが、`type="password"`という属性が影響してか、テストコードで要素を取得することができませんでした。

どうすればいいんだ...。
ググった結果、以下のGitHubイシューのページに辿り着きました。
　[*ByLabelText can't find password inputs](https://github.com/testing-library/dom-testing-library/issues/737)

ざっくり読んだところ、`type="password"`属性を持ったinput要素を取得するためには`getByLabelText()`を使えばいいとのこと。早速試してみます。

## 試した方法②　getByLabelText( )を使用→上手くいった！！

```tsx:Auth.test.tsx
// その２ getByLabelTextを試してみる
describe("入力フォームの更新イベント",()=>{
  it("入力フォームに値が正しく入力されるか確認します",()=>{
    render(<Auth/>);
    const passwordInput = screen.getByLabelText("パスワード");
    userEvent.type(passwordInput,"test")
    expect(passwordInput.value).toBe("test");
  });
});
```

`npm test`を実行したところ、以下の画像のとおり、無事、PASSすることができました。

![スクリーンショット 2021-03-26 1.36.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589104/f0e3625a-aa6b-7881-5f06-a7e8415b201a.png)

## 所感　##
今回はMaterial-UIの`<Input/>`コンポーネントと`<InputLabel/>`コンポーネントを使ったこともあり、通常の`<input>`や`<label>`ではないため、上手くいくか不安でしたが、杞憂だったみたいです。
id属性はテストコードを書く際にも、重要だと学ぶことができました！
webpack4→5の時のwasm環境

# はじめに
2021/03時点の私的環境構築方法です。
webpack4からの移行の際に困ったので残しておきます。

# 手順
まず[テンプレート](https://github.com/rustwasm/rust-webpack-template)をDL

```powershell:cmd
npm init rust-webpack my-app
```
次にバージョンアップ＆インストール

```powershell:cmd
ncu -u
  @wasm-tool/wasm-pack-plugin   ^1.1.0  →   ^1.3.3
  copy-webpack-plugin           ^5.0.3  →   ^8.1.0
  webpack                      ^4.42.0  →  ^5.28.0
  webpack-cli                   ^3.3.3  →   ^4.5.0
  webpack-dev-server            ^3.7.1  →  ^3.11.2
  rimraf                        ^3.0.0  →   ^3.0.2

npm install
```
cargoは任意で行ってください

```powershell:cmd
cargo install cargo-update
cargo install-update --all
```

よし、これで動く...ことはないです。
バージョンの違いで書き方が変わっています。

```diff:package.json
- "start": "rimraf dist pkg && webpack-dev-server --open -d",
+ "start": "rimraf dist pkg && webpack serve --open",
```

```diff:webpack.config.js
- new CopyPlugin({
+ new CopyPlugin([
+   patterns: [
      path.resolve(__dirname, "static")
+   ]
- }),
+ ]),
```
よし、これで動く...ことはないです。
webpack5になって新しくなったものを追加していきます。

```webpack.config.js
const webpack = require("webpack")
...
module: {
  rules: [{
    test: /\.wasm$/,
    type: "webassembly/async"
  }]
},
experiments: {
  asyncWebAssembly: true, 
},
...
plugins: [
    new webpack.LoaderOptionsPlugin({
      options: {
        exprimnet: {
          asyncWebAssembly: true
        }
      }
    }),
...
```
これらを追加して、```npm run start```を実行すればHello world!がコンソールに出力されます。
# エラー
Rustのコードを書いてて起きたエラー

```
Uncaught (in promise) TypeError: Cannot read property '__wbindgen_add_to_stack_pointer' of undefined
```
全然調べても出てこなくて悩んでたのですが、```#[wasm_bindgen(start)]```の部分丸ごと消してました。
これを読んでるあんたはそんなミスを犯さないようにしてください。

# まとめ
webpack5は更新速度が尋常じゃないぐらい早いので、いつこれが使い物にならなくなるかはわかりません。
常に新しい情報を仕入れ続けることを心がけていきたいと思います。
githubの設定メモ

#gitインストール

```
//gitインストール
$ brew install git

// gitバージョン確認
$ git --version
```

#gitのIDとパス

```
//user.nameの設定
git config --global user.name 'Your Name'

//user.emailの設定
git config --global user.email 'email@example.com'
```

#githubの鍵

```
//SSH認証に使う秘密鍵（id_rsa）と 公開鍵（id_rsa.pub）を生成
$ ssh-keygen -t rsa

//エンター３回くらいで↓
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/(username)/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
```

違う名前で生成したいときは

```
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/(username)/.ssh/id_rsa):id_noboo
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
```

#公開鍵をGitHubにアップする

`https://github.com/settings/ssh`

https://github.com/settings/ssh

鍵の中身のコピー

```
$ pbcopy < ~/.ssh/id_rsa.pub
```

接続確認

```
$ ssh -T git@github.com
```
###app getupアプリで管理
---
参考にさせていただいたページ
https://qiita.com/shizuma/items/2b2f873a0034839e47ce
【Swift5/Xcode】iOSでのローカル通知の実装方法まとめ

Swiftコード内で時間指定して通知を表示するローカル通知関連のメモです。
尚、外部からの通信で発火するプッシュ通知は本ページでは取り扱いません。

#環境
Swift5.4
Xcode12.4
Storyboard

#ユーザーに通知許可を求める
```swift:Swift
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.badge, .sound, .alert], completionHandler: { (_, _) in})
```

#◯秒後に通知を表示する
UNUserNotificationCenterDelegateをViewControllerに承継させる必要があります。

```swift:Swift
let notificationContent = UNMutableNotificationContent()
notificationContent.title = "通知のタイトル"
notificationContent.subtitle = "通知のサブタイトル"
notificationContent.body = "通知の本文"
notificationContent.sound = .default
notificationContent.badge = 1 //バッチをアプリアイコンにつける場合は必要。バッチの数字を指定。
let notificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 900, repeats: false) //ここでtimeIntervalに秒数を指定
let request = UNNotificationRequest(identifier: "notice id", content: notificationContent, trigger: notificationTrigger)
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.add(request, withCompletionHandler: nil)
notificationCenter.delegate = self
```

#毎日指定した時間に通知する
UNUserNotificationCenterDelegateをViewControllerに承継させる必要があります。

```swift:Swift
let notificationContent = UNMutableNotificationContent()
notificationContent.title = "通知のタイトル"
notificationContent.subtitle = "通知のサブタイトル"
notificationContent.body = "通知の本文"
notificationContent.sound = .default
notificationContent.badge = 1 //バッチをアプリアイコンにつける場合は必要。バッチの数字を指定。
let noticeTime = DateComponents(hour: 16)//ここで時間指定。左記は16:00。オーバーロードの選択でナノ秒まで指定可能。
let notificationTrigger = UNCalendarNotificationTrigger.init(dateMatching: noticeTime, repeats: true)
let request = UNNotificationRequest.init(identifier: "notice id", content: notificationContent, trigger: notificationTrigger)
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.add(request)
notificationCenter.delegate = self
```

#登録した通知をキャンセルする
```swift:Swift
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.removePendingNotificationRequests(withIdentifiers: ["notice id"])
```

#通知でつけたバッジを削除する
```swift:Swift
UIApplication.shared.applicationIconBadgeNumber = 0
```
Seq#contains でハマった話

バグを出した記録を共有します。ポエムです。

# 経緯

とある改修にて、あるリスト aList から、 vaList に含まれる要素を除いたリスト list を作ることになりました。ただし aList は型 A の、vaList は型 VA のリストでした。A と VA は表示用に使うクラスだったりの変換が入っていますが、概念としては同じものを指しており、それぞれに定義された id プロパティが同じ場合、同じものを指します。

list から何かを条件にして除くメソッドはそのものズバリ filter が用意されているので、それを使いました。こんな感じに：

```scala
  val list = aList.filterNot(a => vaList.map(_.id).contains(a.id))
```

これはうまく動きませんでした。なぜでしょうか。それは A#id が Int 型で、 VA#id が String 型だったからです。イメージ：

```scala
case class A (
  val id: Int,
  ...
)
```

```scala
case class VA (
  val id: String,
  ...
)
```

（表題にあるように）Seq#contains は引数に Any 型を取るので Seq[String]#contains の引数に Int 型の値を入れてもコンパイラ的にはOKだったんですね。なるほどー！

# 反省点とか愚痴とか

## テストで保護できてなかった

今回の不具合は画面に表出するくらいの不具合だったので、これが出たということは表示確認もできてなかったし、テストで保護できてなかったということです。特にこういうロジックはテストで保護すべきでした（後でテスト書きました）。

## なんで型が違うの？

そもそも A#id と VA#id でなぜ型が違うのでしょうか... そこは統一したほうが良かったかもしれませんが、今回の改修範囲からは外れてしまうため（影響範囲が広がるため）、統一は次回のリファクタまで持ち越しました。もしリファクタするならきちんと HogeId 型みたいなのを作ったほうがいいかもしれません。

## contains で異なる型が引数に指定されたら警告して欲しい

contains で型が異なる場合は絶対に false なのだから（そうとも限らないんだろうか...?）、異なる型が引数に指定された場合にはコンパイルエラーか警告して欲しいな、と思いました。だけど引数の型が Any だから難しいのかな...

# まとめ

- テスト書こう。テストが無理ならせめて１度位は表示確認しよう。
- 同じ概念を表すものは(AからVAに)ハコが変わっても、同じ型（IntならInt, StringならString）を使おう。可能ならその概念を表す型(HogeId)を作ろう。
- contains にはどんな型でも入れられるから、型パズルを過信しないようにしよう。

以上です。
Ktor ServerでCookieを設定する

```kotlin
call.response.cookies.append(
    name = "key",
    value = "value",
    path = "/",
)
```

SessionとしてCookieを設定するしかないと思っていたが、普通にcall.responseに設定できる。
Sessionとして値を設定するとKtor独自の方法でシリアライズされたものになる。それを避けたかった。
AWS MFAの設定手順

## 前提
AWSのIAM払い出しが完了し、初めてのログイン

## 環境
Windows10

## インストールしたもの一覧
- Google Chromeに[Authenticator](https://chrome.google.com/webstore/detail/authenticator/bhghoamapcdpbohphigoooaddinpkbai?hl=ja)
- AWS-CLI(AWSCLIV2.msi)
- python(python-3.9.0-amd64.exe)

## MFA有効化までの手順
1. AWSにログインしIAMのページへ  
AWS内でIAMで検索しても辿り着ける  
1. IAM->ユーザ->`自分のユーザ`に行く
1. 認証情報タブ->コンソールのパスワードで管理をクリック  
コンソールへのアクセス：有効化  
パスワードの設定：カスタムパスワード  
を選択し、新パスワードを入力する
1. Google Chromeに[Authenticator](https://chrome.google.com/webstore/detail/authenticator/bhghoamapcdpbohphigoooaddinpkbai?hl=ja)をインストールする
1. 認証情報タブ->MFAデバイスの割り当てで管理をクリック  
QRコードの表示と拡張機能からQRコードの読み込みを行う  
MFAコードを入力  
1分後のMFAコードを入力  
ブラウザをシークレットウィンドウでひらき、AWSコンソールにログインできることを確認する  

## ローカルでMFA有効化とCLIが使えるようにする
1. AWS-CLIをインストールする  
AWSCLIV2.msi
1. pythonをインストールする  
python-3.9.0-amd64.exe
1. 認証情報タブでアクセスキーの作成をクリック  
作成されたアクセスキーIDとシークレットアクセスキーを表示し、メモしておく。
1. コマンドプロンプトを立ち上げる
1. cloud{ホニャララ}という名前のプロファイルを作成するため、以下のコマンドを実行する  
`aws configure --profile cloud{ホニャララ}-long-term`
1. メモしてあるアクセスキーとシークレットアクセスキーを入力する.  
例：  
AWS Access Key ID []:`アクセスキーを入力`  
AWS Secret Access Key []:`シークレットアクセスキーを入力`  
Default region name []:`ap-northeast-1を入力`  
Defult output format [None]:`何も入力せずエンター`  
1. `%USERPROFILE%¥.aws`にエクスプローラーで移動する
1. credentialsに追記する  
`aws_mfa_device = arn:aws:iam::**********:mfa/{ユーザ名}`  
※認証情報タブ->MFA デバイスの割り当てに記載されているID  
1. credentialsの先頭に`[cloud{ホニャララ}]`の行を追記する  
例：

   ```
   [cloud{ホニャララ}]
   [cloud{ホニャララ}-long-term]
   aws_access_key_id = {アクセスキー}
   aws_secret_access_key = {シークレットアクセスキー}
   aws_mfa_device = arn:aws:iam::**********:mfa/{ユーザ名}
   ```

## 毎回実行（ローカルでCLI作業前に実行）
1. コマンドプロンプトで環境変数を設定  
set AWS_PROFILE=cloud{ホニャララ}  
set MFA_STS_DURATION=43200  
※プロキシ環境の場合、以下も必要  
set HTTP_PROXY=http://{ID}:{PASS}@{プロキシサーバアドレス}:{ポート}  
set HTTPS_PROXY=http://{ID}:{PASS}@{プロキシサーバアドレス}:{ポート}  
<br>
※GitBashでも実行できるのでGitBashの場合は  
~/.bashrcなどにexportで上記4つを書いておけば起動時に設定されてて楽になった  
1. コマンドでMFAの認証コードを入力すると、~/.aws/credentialsに一時アクセスキーとトークンが設定されたプロファイルが生成・更新される  
`aws-mfa --profile cloud{ホニャララ}`  
例：  

```
[cloud{ホニャララ}]
assumed_role = False
aws_access_key_id = {アクセスキー}
aws_secret_access_key = {シークレットアクセスキー}
aws_session_token = {トークン}
aws_security_token = {トークン}
expiration = {更新日時}

[cloud{ホニャララ}-long-term]
aws_access_key_id = {アクセスキー}
aws_secret_access_key = {シークレットアクセスキー}
aws_mfa_device = arn:aws:iam::**********:mfa/{ユーザ名}
```
Oculus Developer Hub をインストール後、Unity の Build And Run が失敗する

Oculus Developer Hub（以下ODH）をインストールした後から、Unity での Build And Run が失敗するようになってしまったときの対応方法です。

# 原因
ODH には adb が付属しています。ODH の adb が起動されていると、Unity のほうの adb が同じポート使えないのが原因で正常に起動せず、インストールに失敗します。

# エラー内容
Unity で Build And Run をすると ADB server が起動できなかったとエラーが出るようになってしまった。
![2021-03-17_11h51_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/529a8a6c-adcb-dac1-0b96-bb026f1345e4.png)

## ターミナルで adb devices するもエラー
```
👉 adb devices
List of devices attached
adb server version (41) doesn't match this client (40); killing...
could not read ok from ADB Server
* failed to start daemon
error: cannot connect to daemon
```

# 対応方法
1. adb の場所を調べる。 adb --version 使うと path が表示されるの楽です。  （下の参考を参照）
2. ODH の設定変更して、ODH を再起動  
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/6385d2a3-c4b9-f4ae-0337-5311b6712f18.png" width=512 />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/1ecfb55a-ad25-ea32-d82c-64366ad1272c.png" width=512 />
3. adb devices してみる。うまくいっていれば正常にデバイスが表示されるはず。

```
👉 adb devices
List of devices attached
1WMHH810D10407  device
```

# 参考
## adb のパス表示
```
👉 adb --version
Android Debug Bridge version 1.0.40
Version 4986621
Installed as C:\Program Files\Unity\Hub\Editor\2019.4.9f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platform-tools\adb.exe
```
## 書いてある
https://developer.oculus.com/documentation/tools/odh/

> 注: ODHにはADBがバンドルされているため、自分でADBバージョンをインストールする必要はありません。ただし、コンピューター上で既に別のADBバージョンを実行している場合は、ADBインスタンス間で競合が発生する可能性があります。その場合は、ADBパスを変更することで、コンピューターから既存のADBバージョンを使用することができます。[Settings (設定)]に移動し、コンピューター上にあるADBインスタンスをODHが使用できるように、ADBパスを変更します。"
Gmailの未読だけをまとめて見る方法


Gmailですが、何かと綺麗にラベル整理をしたとしてもどんどん未読が溜まって結局追うのが大変なことってありますよね？そんなときは以下のURLをブックマークしておきましょう。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/9a2cabf3-be04-770b-ec66-7fcf4c2724e7.jpeg width=300px border="5">

# 未読のみをまとめて表示する

<a href="https://mail.google.com/mail/u/0/#search/is%3Aunread">https://mail.google.com/mail/u/0/#search/is%3Aunread</a>

# おまけ：スターのみをまとめて表示する

<a href="https://mail.google.com/mail/u/0/#starred">https://mail.google.com/mail/u/0/#starred</a>

![gmail_bookmark.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/c8b474a0-c754-93e3-a45f-851562dc87a8.png)
要は検索結果をブックマークしただけですね。メールを見るのは大変なので、地味に効率化ですね。
Linuxでもお名前.com DDNS

# はじめに

お名前.com使ってますか？
僕はお名前.comでドメインを借りてます。ふと、家のマシンをインターネット公開しようとDDNSしようと思ったのですが、クライアントがWindowsしかありませんでした。

調べてみると簡単にできそうだったので、肝となるコードは参考しつつ、Goで書いてみました。

利用の際は自己責任でお願いします。

# 機能紹介
## リポジトリ
https://github.com/miya-masa/onamae-go

## ヘルプ（リリース当初）
```
❯ onamae-go -h
flag needs an argument: -h
Usage of onamae-go:
  -d string
        Domain. ex. example.com
  -daemon
        Launch as daemon
  -h string
        Hostname. ex. www
  -i https://httpbin.org/ip
        IP address. If empty, will get it automatically using https://httpbin.org/ip
  -interval string
        Update interval. Enable only for daemon mode (default "1m")
  -p string
        Password onamae.com env:$ONAMAE_PASSWORD
  -u string
        Username onamae.com.env:$ONAMAE_USERNAME
```

## 基本的な使い方

### 明示的にIPアドレスを指定して実行

```
onamae-go -h www -d my.example.co.jp -p <パスワード> -u <ユーザー名> -i <IPv4アドレス>
```

### 動的に取得して実行
```
# https://httpbin.org/ip を利用してグローバルIPを自動的に取得します
onamae-go -h www -d my.example.co.jp -p <パスワード> -u <ユーザー名>
```

### 5分間隔で動的に取得するバックグラウンド実行
```
# 起動中にグローバルIPに変更があったときのみ、お名前.comに更新しに行きます。
onamae-go -h www -d my.example.co.jp -p <パスワード> -u <ユーザー名> -daemon -interval 5m
```
### 認証情報を環境変数として設定して実行

```
export ONAMAE_USERNAME=<ユーザー名>
export ONAMAE_PASSWORD=<パスワード>
onamae-go -h www -d my.example.co.jp
```

# 参考
* https://github.com/hinoshiba/go-onamaeddns
  * 別の方のGo実装です。参考にしました。
* https://qiita.com/ats124/items/59ec0f444d00bbcea27d
【Google Analytics】プロパティ（監視対象）の追加（備忘録）

# はじめに
個人請負でとあるサイトをサーバーレスで構築しています。
追加要望がある時以外は基本的に運用業務は発生しないので、せめてアクセス状況の報告くらいしようと**Google Analytics**を導入することにしました。
よく画面が変わるので備忘録として現在（2021/03/25時点）のキャプチャを残そうと思います。

# Googleアカウントの作成
すでに別サイトでGoogleアナリティクスを導入しているためアカウントが既にあります。
そのためキャプチャを取得していないのでアカウント作成は割愛させてください・・・。

# Googleアナリティクスの登録
すでに別サイトでGoogleアナリティクスを導入しているためアカウントが既にあります。
そのためGoogleアナリティクスの登録も割愛させてください・・・。
アカウント名を入力するくらいです。それ以外はこれから説明する**「プロパティの設定」**と変わらないです。

# プロパティの設定
Googleアナリティクスのページを開き、画面左のメニュー最下部の「設定」（歯車アイコン）をクリック。
「管理」タブにて**「プロパティを作成」**を選択。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/1ae96fbc-ad14-b9ae-f7c7-b12902785264.png)

次に以下の設定を行います。

+ プロパティ名
+ レポートのタイムゾーン
+ 通貨

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/4ce1c2e8-f6f3-ade4-bcf1-8642a6d3b564.png)


プロパティ名は識別出来ればなんでも良いですが、**監視対象のサイトの名前**を入力すると良いと思います。
レポートのタイムゾーンは**「日本」**を選択してください。
通貨は**「日本円」**を選択します。

すべてを入力・選択したら「次へ」ボタンをクリックします。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/3e3970eb-4b4d-ecea-3eab-8b6d59f29762.png)

**「ビジネスの規模」**、**「利用目的」**はそれぞれあてはまるものを選択してください。
選択後**「作成」**ボタンをクリックするとプロパティが作成されます。

# データストリームの追加

次にデータストリームの追加を行います。
プロパティを選んでいる状態で左側のメニューから「データストリーム」を選択、データ収集を行うプラットフォームを選択します。今回は「ウェブ」を選択しています。

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/a75300eb-e733-02ad-4339-6ea6c75b15f1.png)

**「ウェブサイトのURL」**に監視対象のドメインを入力します。
**「ストリーム名」**に任意の名前を設定します。

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/9a348cef-5702-0ab8-a46a-0259e1fc69ff.png)

入力後、**「ストリームを作成」**をクリックするとストリームが作成されます。

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/c411add0-85c7-8671-eb2e-92b81c3b7730.png)

**「測定ID」**が発行されています。

# タグ設定情報の確認
データストリームの詳細画面の中ほどに**「タグ設定手順」**という項目があります。

**「新しいページ上のタグを追加する」**＞**「グローバル サイトタグ（gtag.js） ウェブサイト作成ツールや、CMS でホストされるサイトをご使用の場合、このタグを設定 」**を選択します。

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/616e1781-0b2d-1bb6-78db-aff75ecbb089.png)

HTMLのタグが表示されるのでコピーします。

# HTMLへの埋め込み

コピーしたタグを監視対象のHTMLすべてに埋め込みます。
※headタグのすぐ後ろに埋め込みます。

![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/fdfcad4b-5294-9b5b-6cd7-9dd51e7ed2b7.png)

以上で設定は完了です。

# 動作確認
監視対象のサイトを表示した後、正常に計測できているかを確認します。

リアルタイム　＞　概要　を確認し、サマリーに1以上の数字が表示されていれば正常に測定が出来ています。

![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/c5151d24-1229-87b0-9d67-87670e4cb7fd.png)

以上
[WIP] AtCoder用 Rust 標準入出力

# [WIP] AtCoder用 Rust 標準入出力

## 目的
AtCoderの際に標準入力の受け方をメモ

## コード
### 複数並んだ数字をリストで受ける
#### 例
1 2 3 4

#### Code
```rust
use proconio::input;
 
fn main() {
    input! {
        a: [i32; 4]
    };
}
```
### 2×Nの数字をリストで受ける
#### 例
5
1 2
6 6
4 4
3 3
3 2
#### Code
```rust
fn main() {
    input! {
        n:usize,
        d:[(usize,usize);n]
    }
}
```