OmniAICreator/Qiita-1.07M huggingface dataset:
React + Material UIでWebサイト作るときに実装までに準備することまとめ

# はじめに
最近仕事でReactをメインに開発しており、せっかくならプライベートでも何か作ってみたいと思い、とりあえず自分のホームページを作ることにしました。
[Okula Portfolio Site](https://okula-hs.github.io/okulab-portfolio/)
Reactのプロジェクト作成やMaterial UIの導入などはいろんな記事がありますが、それだけではWebサイトとしては成立しません。実装前にやる様々な準備をまとめてみました。

本記事ではReactのチュートリアルなどは取り扱いませんのでご容赦ください

# 使用技術
Typscript
React
Material-ui

# Webサイトの構成を決める
私はFigmaであらかたのデザインを起こしました。
[Figma](https://www.figma.com/)
ここで全体の構成、配色、ロゴなどを定義します。

### サイトの構成
とりあえずこんな感じにしてみました。

* ファーストビュー（TOP）
* 自己紹介（AbountMe）
* スキルセット
* 連絡先

紹介したいプロダクトがある人はそれも追加するといいですね。
ちなみに、連絡先は実装中です・・・

### 配色
配色の参考はいろんなサイトがあるので自分にあったものをお探しください。ちなみに私はこのサイトを使用させていただきました。
[COLOR SUPPLY](https://colorsupplyyy.com/app/)
メインカラー、アクセントカラー、白、黒、グレーくらいを定義するといい感じにまとまると思います。

### ロゴ
サイトのファーストビューとアイコンに使用するロゴを作成します。
ロゴはFigmaでそれっぽく作成して、svgやpngでエクスポートして素材として使用しました。

### favicon.ico
favicon.icoとはホームページタイトルの横に表示されるアイコンのことです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509749/3c127d8d-ec0a-8d00-c17e-38c0b31b2783.png)
先ほど作ったロゴをpngでエクスポートし、このサイトで作成しました。
[Faviconジェネレーター](https://favicon-generator.mintsu-dev.com/)
世の中素敵なサービスばかりで感謝です

# React+Material UIで実装
さて、前作業は終わりましたので、実装していきます。
create-react-appを使用してReactのプロジェクトを作成し、Material UIをimportします。
この記事では具体的な手順については触れません。

### サイトタイトルを変更する
public/index.htmlのtitleタグの中を変更してサイトタイトルを変更します

### favicon.icoを変更する
public/favicon.icoを先ほど作成したものと差し替えます。

### テーマカラーとフォントの反映
テーマカラーは先ほど決めたものを使用します。
フォントについてはデフォルトでも問題ないんですが、せっかくなので変更しましょう。
今回はgoogleフォントから選びました。
[Googleフォント](https://fonts.google.com/)

使いたいフォントを選択すると、linkタグが表示されます。これをindex.htmlの中に記載します

~~~html:index.html
<head>
    <link
      href="https://fonts.googleapis.com/css2?family=M+PLUS+Rounded+1c:wght@100;300;400;500;700;800;900&display=swap"
      rel="stylesheet"
    />
</head>
~~~
次にMaterial UIのテーマを変更します。こんな感じのファイルを作ります。

~~~React:theme.ts
import { createMuiTheme } from "@material-ui/core/styles";

const theme = createMuiTheme({
  palette: {
    primary: {
      main: "#F3F1F1",
    },
    secondary: {
      main: "#E76F53",
    },
  },
  typography: {
    fontFamily: ["'M PLUS Rounded 1c', sans-serif"].join(","),
  },
});
export default theme;
~~~

次にindex.tsxに追記してテーマを反映します。

~~~React:index.tsx
import { MuiThemeProvider } from "@material-ui/core/styles";
import theme from "./theme";

ReactDOM.render(
  <React.StrictMode>
    <MuiThemeProvider theme={theme}>
      <App />
    </MuiThemeProvider>
  </React.StrictMode>,
  document.getElementById("root")
);
~~~
これでMaterial UIのコンポーネント全体にテーマカラーとフォントが適用されました。
詳しい原理はMaterial UIの公式サイトをご覧ください。


### Lets 実装
ここまでくれば準備はほぼ完了です。好きなように実装をします。
Gridを使用すると後からレスポンシブ対応しやすくなります。

# サイトを公開する(おまけ)
実装が終了したらいよいよサイトの公開です。github.ioを使用しました。
Reactアプリのgithub.ioの設定についてはこちらの記事を参考にさせていただきました。
[ReactアプリをGitHub Pages(Project Pages)で公開する](https://qiita.com/EisKern/items/15dcf7864fa49df8f247)

# 最後に
本当はアニメーションやいい感じのデザインを取り入れたかったのですが、それは今後頑張るということで一旦公開としました。自信をもって「これがわたしのポートフォリオです」と言えるように改修していこうと思います。
仕事じゃない開発は好きなように時間を使えて、楽しいですね。
以上です。
Qiitaで数式を書く時に困ったこと

Qiitaで数式を書く際、「Texで書くように書いたけど、うまくいかない！」って困った部分についてちょっと書いてみました。
似たような状況で困ったという方がもしいれば、試してみてください。

1：「$x\_{i0}$」のように、添字が複数文字の場合に{}で囲ってもうまく表示できない。
→ 原因と解決法： \$x_{i0}\$と書いていたが、\_の前に\を入れることで解決(\$x\\\_{i0}\$)。
2：「$d\_i = \frac{y\_i({\bf w}^{T}{\bf x}\_i+b)}{||{\bf w}||}$の最大化による識別関数$f(x) = sgn({\bf w}^{T}{\bf x}\_i+b)$の取得。」のように、文章中に複数の数式を書いたらうまく表示されない。
→ 解決法：これも、各数式に登場する_の前に\を入れることで解決。
3：「argminやargmax(下付き文字あり)」の書き方がわからない。
→ 解決法：\$\mathop{\rm argmin}\limits\\\_{x} L(x,y)\$と書くと、$\mathop{\rm argmin}\limits\_{x} L(x, y)$とかける
CUIでTTS(Text-To-Speach)を実行する方法

CUIベースの単語帳を作成していた時に英語の読み上げ機能が使えないか調べていたところMac限定ではありますが使用方法がありましたので記事にします。

# 環境
- Mac OS Big Sur 11.2.1
- Python 3.9.1 (使用する場合)

# 実行方法
## sayコマンド
Macにはsayというコマンドが存在しており、引数に読み上げて欲しい内容を入力すればシステムが読み上げてくれます。

```terminal
say Hello world
```

ただし、デフォルトでは日本語話者の"Kyoko"さんが選択されていますので日本語っぽい英語になります。

## 音声切り替え
日本語話者以外はいないのか？と当然思いますよね。試しに以下のコマンドを実行してください。

```terminal
say -v ?
```

すると以下のような結果が取得できると思います。こちらは選択できる話者の一覧で、これを明示的に指定することでネイティブの読み上げを確認することができます。

```terminal
Alex                en_US    # Most people recognize me by my voice.
Alice               it_IT    # Salve, mi chiamo Alice e sono una voce italiana.
Allison             en_US    # Hello, my name is Allison. I am an American-English voice.
Alva                sv_SE    # Hej, jag heter Alva. Jag är en svensk röst.
Amelie              fr_CA    # Bonjour, je m’appelle Amelie. Je suis une voix canadienne.
Anna                de_DE    # Hallo, ich heiße Anna und ich bin eine deutsche Stimme.
Carmit              he_IL    # שלום. קוראים לי כרמית, ואני קול בשפה העברית.
(以下略)
```

試しにアメリカ英語のAllisonに読み上げてもらいましょう。

```terminal
say -v Allison "Hello world"
```

いかがでしたでしょうか？先ほどとは違い英語話者っぽい発音が確認できたかと思います。

## 話者追加
では、この一覧以外は使えないのか？と思いますよね。実は追加することが可能です。
実際先ほど使用したAllisonもデフォルトでは一覧に表示されません。

[システム環境設定]→[アクセシビリティ]→[読み上げコンテンツ]

と選択し、話者の選択項目から「カスタマイズ」を選択します。
![スクリーンショット 2021-02-23 15.48.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629032/c3bea542-685c-c48f-83b3-c9c760d39c76.png)
すると各言語ごとの話者が選択できますので、選択して「OK」を押すと音声データのダウンロードが開始され新たにその話者が使用できるようになります。もちろん先程の一覧にも表示されます。

## Python
PythonにはOSのコマンドを実行する機能がありますのでPythonからでもこのコマンドを呼び出すことができます。

```say.py
import sys
import subprocess

def pronounce():
    voice = sys.argv[1]
    text = sys.argv[2]
    command = ['say', '-v', f'{voice}', f'{text}']
    cp = subprocess.run(command)
    return cp

if __name__ == '__main__':
    pronounce()
```

これを以下のように呼び出すことで上記と同じような結果が取得できます。

```terminal
python say.py Allison "Hello world"
```

ちなみに`return cp`はしなくても良いのですが単体テストなどをする際に`cp.returncode`で実行結果が取得できるので便利です。
今更ながらHTTPプロトコルをまとめました〜きっと誰にでもわかる風〜

##:earth_americas:背景
HTTPプロトコルについて何度か調べても、
自分なりにまとめず何度か調べ直すことが多かったので
初学者の方が誰でもわかるようにまとめました。

パパッとみてざっくりこんな感じかとふんわり理解に役立てていただけたら嬉しいです:relaxed:

![名称未設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688036/545923af-1ed6-24ac-faa6-9de5526eb52f.png)
![名称未設定２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688036/ebd4feda-d8c2-2a34-b895-045f6dcbd183.png)
![名称未設定３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688036/29a3a42f-7cae-00b6-8fdd-ce62c8a67d0f.png)
![名称未設定４.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688036/91a4ed5d-be9c-0f23-8174-8eb2f9cee461.png)
![名称未設定５.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688036/0007a605-3e6e-548f-556a-9f37d4a2c748.png)


##おわり:two_women_holding_hands:
こういう通信系やインフラ系って仕組みが少しでもわかるとキュンキュンわくわくします♡
Python　Excelファイルを読込みGoogleTranslateを使ってみた

#目的
　私は仕事で海外の特許調査をする機会が過去にあったんですが、海外の特許調査なので当然親切に日本語に翻訳してくれてなんかいない！中国語やら英語やら・・・語学力の無い私はGoogle翻訳で検索→翻訳を実施して特許の内容を理解しなければならない。この翻訳作業を少しでも軽減できないか？と考え、本ツールを作成するに至った。
##環境
Windows10 Home 64bit
Python3.8.3
##Toolの概要
　調査する特許はExcelファイル形式の為、英語or中国語で記載された列の文章を読込み、その隣の列に日本語の翻訳結果を出力する事にした。
![翻訳前後画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667963/64dff1f0-ba12-62e1-5ba9-930b5f5da59e.png)
##必要なライブラリー
以下を事前にインストールしてください。

```
pip install openpyxl
pip install googletrans
```
##コード

```main.py
from googletrans import Translator
import openpyxl as excel

#Excelファイルの指定
test_file = excel.load_workbook("<filepath>",data_only=True)
#Sheetの選択
sheet = test_file.worksheets[0]
#excelの最終行を取得
max_row = sheet.max_row

translator = Translator()

for i in range(1,max_row+1):
    bf_trans = sheet.cell(row=i,column=1).value
    trans_text = translator.translate(bf_trans,dest='ja')
    sheet.cell(row=i,column=2).value = str(trans_text.text)

#excelファイルを閉じて終了
test_file.save("<filepath>")
```
##最後に
翻訳結果みると・・・微妙な文もあるが、少しは役にたつかな～。
Kinect v2 でFaceBasicを動かした話

## Kinect v2 でFaceBasicを動かしました

2015年の記録なので、サービス終了などもあるかと思いますが、ご参考まで！
環境：　Windows8

・YouTube
　↓こんな動画が45秒間、流れます
![D524F853-CDAA-4384-B9BE-4B240F1B788E.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1142882/b254a928-ce2d-71b8-d1d1-4b16158a6b28.jpeg)
・　[YouTubeで「Kinect v2 FaceBasic」を見る](https://youtu.be/pzeS1HbEDiM)

## 参考書籍
![3C694602-794C-4F42-85D0-4305A651E61B.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1142882/27d858fe-503e-3159-50d5-bf034bb83fdf.jpeg)

・Kinectv2楽しいプログラミング入門
　 [Amazonで「Kinectv2楽しいプログラミング入門」を見る ](https://www.amazon.co.jp/dp/B0152WGUYK/ref=cm_sw_em_r_mt_dp_29VVCB1K4QP4Y9TAEEC4)

![30A60469-70A5-4E78-A9F0-3092C4D5668E.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1142882/7f66d558-bcd3-30b5-4723-d66b95c396e5.jpeg)
・JavaScriptでインタラクティブ3Dコンテンツを作ろう―Kinect+jThree+Milkcocoaを使って東北ずん子と踊る (NextPublishing)
　[Amazonで「JavaScriptでインタラクティブ3Dコンテンツを作ろう―Kinect+jThree+Milkcocoaを使って東北ずん子と踊る (NextPublishing)」を見る](https://www.amazon.co.jp/dp/B0152WGX1A/ref=cm_sw_em_r_mt_dp_86NBCF38W44AA2PQBE32)

##著者の人のGitHub
面識はないけど My Hero マイクロソフトの大田さん
　 [GitHub　Kinect本のためのコード解説](https://github.com/NT-D/kinect2_book1)

　 [GitHub　FaceBasics-XAML]
(https://github.com/NT-D/kinect2_book1/tree/master/FaceBasics-XAML)
Pythonで学ぶ制御工学　第6弾：伝達関数モデルと状態空間モデル

# #Pythonで学ぶ制御工学< 伝達関数モデルと状態空間モデル >

##はじめに
基本的な制御工学をPythonで実装し，復習も兼ねて制御工学への理解をより深めることが目的である．
その第6弾として伝達関数モデルと状態空間モデルを扱う．


##状態空間モデルと伝達関数モデルの関係性
状態空間モデルは一意の伝達関数モデルに変換することができる．次にその過程を示す．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/ef44017e-4364-3992-5fa5-bb5d38c94fcf.png)
しかしながら，逆は定まらない．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/35258cc1-fe24-8694-710d-2c8fa45af6a8.png)


##実装
先ほどの変換をPythonで実装してみる．以下にソースコードとそのときの出力を示す．

#####ソースコード
```python:
"""
2021/02/23
@Yuya Shimizu

状態空間モデルと伝達関数モデル
"""

from control import tf, tf2ss, ss2tf, canonical_form

#適当な伝達関数モデルを準備
numerator = [0, 1]
denominator = [1, 1, 1]
P = tf(numerator, denominator)



#伝達関数モデル　→　状態空間モデル
Pss = tf2ss(P)
print(f"<伝達関数モデル → 状態空間モデル>\n{P}\n　↓\n\n{Pss}\n")

#状態空間モデル　→　伝達関数モデル
Ptf = ss2tf(Pss)
print(f"\n<状態空間モデル → 伝達関数モデル>\n{Pss}\n　↓\n{Ptf}")



#可制御正準形への変換
Pr, T = canonical_form(Pss, form = 'reachable')
print(f"\n<可制御正準形への変換>\n{Pss}\n　↓\n\n{Pr}")

#可観測正準形への変換
Pr, T = canonical_form(Pss, form = 'observable')
print(f"\n<可観測正準形への変換>\n{Pss}\n　↓\n\n{Pr}")
```

#####出力
```
<伝達関数モデル → 状態空間モデル>

     1
-----------
s^2 + s + 1

　↓

A = [[-1. -1.]
 [ 1.  0.]]

B = [[-1.]
 [ 0.]]

C = [[ 0. -1.]]

D = [[0.]]



<状態空間モデル → 伝達関数モデル>
A = [[-1. -1.]
 [ 1.  0.]]

B = [[-1.]
 [ 0.]]

C = [[ 0. -1.]]

D = [[0.]]

　↓

     1
-----------
s^2 + s + 1


<可制御正準形への変換>
A = [[-1. -1.]
 [ 1.  0.]]

B = [[-1.]
 [ 0.]]

C = [[ 0. -1.]]

D = [[0.]]

　↓

A = [[-1. -1.]
 [ 1.  0.]]

B = [[1.]
 [0.]]

C = [[-0.  1.]]

D = [[0.]]


<可観測正準形への変換>
A = [[-1. -1.]
 [ 1.  0.]]

B = [[-1.]
 [ 0.]]

C = [[ 0. -1.]]

D = [[0.]]

　↓

A = [[-1.  1.]
 [-1.  0.]]

B = [[0.]
 [1.]]

C = [[1. 0.]]

D = [[0.]]

```

ここでプログラムに関して補足しておく．``control``ライブラリの``tf2ss``で状態空間モデルに変換しているわけだが，はじめの説明でもあったように一意に定まらないということで，可制御・可観測正準形になっているとは限らない．そこで，``control``ライブラリの``canonical_form``という関数でさらに変換している．また，可制御正準形の変換時に``reachable``（可到達）と指定しているが，これは連続時間の線形システムにおいては，可到達性と可制御性が同じ意味となるためである．

##プロパー性
最後にシステムの設計時に必要になるプロパー性についてまとめておく．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/56bd58e0-c577-20fb-b51a-fc475b60bb1f.png)

##感想
伝達関数モデルと状態空間モデルの関係性について触れた．また，可制御性や可観測性の話も出てきた．久しぶりに触れ，思い出すよい機会となった．また，プロパー性については，いまいち理解できていなかったんだと気づいた．特にプロパー性の意義について．システムの設計で非常に重要となる概念であることを理解した．

##参考文献
Pyhtonによる制御工学入門　　南 祐樹　著　　オーム社
クラスとインスタンス②

# クラスの中に定義するクラスメソッドとインスタンスメソッド

値を作ることで、現実世界のあらゆる「もの」をコードで表現することが可能
同じ種類でも、その中でそれぞれ個性があるようなものも表現することが出来る

>
人間を表現する場合は、属性として身長・性別、動作に食べる・笑うなどをクラスに定義
あとは個別のデータを追加してインスタンスを生成する


現実世界の「もの」には、できる動作とできない動作があります。

>
車はアクセルやブレーキを踏むと「加速する」「減速する」という動作が可能
人間のような「食べる」「笑う」という動作は不可能
逆に人間にとってみても車が持つ動作は不可能


現実世界の「もの」のように、クラスとインスタンスでデータを作る場合も、
それぞれの動作、つまり`メソッド`をあらかじめ決めておく

>
メソッドはクラスに定義しますが、それぞれ
`クラスメソッド`と`インスタンスメソッド`の2種類がある

## インスタンスメソッド

インスタンスメソッドは、インスタンスから呼び出すメソッド
`インスタンスごとの個別の情報（属性値）を使った処理に使用`

- Carクラスの中に、ride_carメソッドを定義
- Carクラスのインスタンスを生成
- fire_truckという変数に値を代入

```ruby:インスタンスメソッドの定義
class Car # クラス名

  def ride_car() # メソッド名
    # 処理
  end

end

fire_truck = Car.new()
fire_truck.ride_car() # メソッドを呼び出し
```
>
メソッド内に処理をまだ記述していないので、コードを実行しても何も処理は行われない
処理の記述をする際に重要なのが`スコープ`

###補足情報

**スコープとは？**

- メソッドの外で定義した変数はメソッドの中では使用できない
- メソッドの中で定義した変数はそのメソッドの中でしか使用できない
- クラスの中でも同様

---

**属性と属性値**

- 属性は、データの性質となる情報
- それぞれに当てはまる値を属性値

>
赤色の車の場合、属性「color(色)」は「red(赤)」という属性値

---

**インスタンス変数**

- すなわちデータが持つ属性を定義する変数
- 定義しておくことですべてのインスタンスが同じ属性を持つ
- 属性値は、個々のインスタンスによって別々に設定可能

>
インスタンス変数は、クラス内のメソッドの中で
変数名の始めにアットマーク@を1つつけて定義

```:インスタンスメソッドの呼び出し
インスタンス名.メソッド名(引数)
```

- インスタンス変数に代入
- 引数を3としてride_carメソッドを呼び出し
- 3という値が代入

```rb:インスタンス変数の定義
class Car
  def ride_car(ride_number)
    @ride_number = ride_number
    # @変数名 = 値 インスタンス変数の定義
  end
end

fire_truck = Car.new()
fire_truck.ride_car(3) # インスタンスメソッドの呼び出し,引数は ３
```

>
インスタンス変数は、インスタンスが個別に持つ属性値が入り、そのインスタンスのすべての動作に使用できる変数

---
---

## クラスメソッド

クラスメソッドはクラスから呼び出すメソッド
`共通の結果を返す動作を定義する`

- クラスメソッドとしてrunメソッドを定義
- runメソッドを呼び出し

```rb:クラスメソッドの定義
class Car

  def self.run # クラスメソッドを定義
    puts '走行します'
  end

  def ride_car(ride_number)
    @ride_number = ride_number
  end

end

fire_truck = Car.new()
fire_truck.ride_car(3)

Car.run # メソッドの呼び出し
```

>呼び出し方はこれまでのメソッドと同様ですが、クラスから呼び出すという点が異なる
>>
```:メソッドの呼び出し
クラス名.メソッド名(引数)
```

<br>

>代表的なクラスメソッドは、インスタンスを生成する際に使用してきたnewメソッドが該当する
>
```rb:newメソッド
# インスタンスを生成するためにクラスメソッドとして定義されている
user = User.new
```
[Rust]traitを返却したい

上記の公式リファレンスの補足として。

* [Returning Traits with dyn - Rust By Example](https://doc.rust-lang.org/rust-by-example/trait/dyn.html)
* [Using Trait Objects That Allow for Values of Different Types - The Rust Programming Language](https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types)



## エラー

```Rust
struct Sheep {}
struct Cow {}

trait Animal {
    fn noise(&self) -> &str;
}

impl Animal for Sheep {
    fn noise(&self) -> &str {
        "baaaaah!"
    }
}

impl Animal for Cow {
    fn noise(&self) -> &str {
        "moooooo!"
    }
}

fn random_animal(random_number: f64) -> Animal {
    if random_number < 0.5 {
        Box::new(Sheep {})
    } else {
        Box::new(Cow {})
    }
}

fn main() {
    let random_number = 0.234;
    let animal = random_animal(random_number);
    println!("You've randomly chosen an animal, and it says {}", animal.noise());
}
```

上記コードで`cargo run`すると、次のようなエラーが出ます。

```
   |     let animal = random_animal(random_number);
   |         ^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `Sized` is not implemented for `dyn Animal`
   = note: all local variables must have a statically known size
   = help: unsized locals are gated as an unstable feature
```

## 解決

返却値の`Animal`を`Box<dyn Animal>`に変えます。

```Rust
fn random_animal(random_number: f64) -> Box<dyn Animal> {
    if random_number < 0.5 {
        Box::new(Sheep {})
    } else {
        Box::new(Cow {})
    }
}
```

traitを返却値にすると、コンパイル時にどちらの型を使うかが決まらないため、そのままでは使えません。

そのため**「コンパイル時に型（またはサイズ）が決まらなくても仕方がない」**場合は、`Box`で囲ってあげます（より正確に言えばヒープ領域を確保します）。

## そのほか

`dyn`について。

調べても見つからなかったのですが、おそらく「動的に型が決まる」みたいな意味あいで、`dynamic`の略かなと思います。
M5StackでBLEセントラルを作成する

# M5StackBleCentral
日本語

NimBLEライブラリを使って、CSCペリフェラル(ケイデンスセンサー等)とHIDペリフェラル(リモートシャッター等)を同時に接続できるBLEセントラルデバイスをM5Stackで動作させるものです。

![BLEdevices.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6824/8e86df97-94ad-65b9-9e39-7cd7c24d5451.jpeg)

![M5connect.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6824/9662492e-bf21-e094-6b63-9bba2c1a0b14.jpeg)


## Source code

https://github.com/fknaopen/M5StackBleCentral


## Requirement
動作には以下のライブラリが必要です。  

* M5Stack (version=0.3.1 author=M5Stack)
* FunctionFsm (version=1.0.0 author=JRVeale)
* M5Stack_OnScreenKeyboard (version=0.3.4 author=lovyan03)
* M5Stack_TreeView (version=0.2.14 author=lovyan03)
* NimBLE-Arduino (version=1.2.0 author=h2zero)

ボードマネージャ
追加のボードマネージャのURLに、M5Stack用URLを指定し、ボードはM5Stack-Core-ESP32を使います
URL = https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
![m5_boardmgr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6824/a8b150ee-cc9c-4cc8-e239-d1d8e984b65a.png)

## Design

複雑な動作状態を管理するため、ステートマシンを使用しています。

![M5StackBleCentral_STM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6824/b459465b-e760-47f4-26a0-5453ce77ceb3.png)



## Usage

起動するとAdvertiseしているペリフェラルをscanしてユーザに選択してもらうためのデバイス一覧画面を表示します。

![M5scanCSC.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6824/f313001f-b48a-4d42-94ba-a3687644bb50.jpeg) ![M5scanHID.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6824/659a0266-b1ba-4272-6076-0f96ca78accd.jpeg)

CSCデバイスとHIDデバイスについて順に選択します。

選択完了したらデバイスが内部に登録され、次回起動からは自動的にペリフェラルに接続します。

![M5connect.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6824/c210d04d-2aaf-e455-aafe-d19b906c825e.jpeg)


再度ペリフェラルを選択したいときには、起動時にボタンを押しておくと内部の登録を初期化します。

## Implementation
現在のソースコードは、ペリフェラルからのNotifyを受信した時、画面のインジケーターを更新しているだけです。
この場所(keepconnect状態中のupdateIndicator()処理辺り)に、GPIOへの出力等必要な機能を追加すると良いです。
楽天カード（楽天e-NAVI）サイトにPythonとSeleniumを使ってログインする

楽天カード（楽天e-NAVI）のサイトにPythonとSelenium使ってログインする方法を解説します。

※2021/02/23時点の情報です

## 環境
- Windows 10
- Python 3.8
- Selenium 3.141.0

## 全体の処理の流れと注意点
全体の処理の流れについては、下記記事に詳しく書いたのでこちらもあわせて確認してみてください。楽天銀行の例になっていますが、処理の流れは同じです。

https://qiita.com/yoshi2045/items/2fff5bf5f0fa763f7104

また、下記記事では他サイトのサンプル一覧と注意点を解説しているのでこちらも参考にしてみてください。

https://qiita.com/yoshi2045/items/a58a7fbebcb9faad3e15

## 楽天カードサイトでのポイント
全体の処理の流れについては上記記事を参考していただくとして、ここでは楽天カードサイトにおけるポイントを紹介します。

### 第２パスワードの入力画面がある

楽天e-NAVIは、ID/PASSWORDを入力しログインしたあと、さらに第２パスワードを入力する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459893/e069e11a-a896-e427-c931-1739fa53a8f8.png)

ただ、やることは最初のログイン画面と同じで、入力エリアに第２パスワードをsend_keys()で設定し、ログインボタンに対しclick()で画面遷移させます。

```python
# 第2パスワード入力
e = browser.find_element_by_id("indexForm:password")
e.clear()
e.send_keys(PASS2)

# ログイン
button = browser.find_element_by_name("indexForm:j_idt78")
button.click()
```


## サンプルコード全文

```python
#
# 楽天カードサイトへログイン
#

import json
from selenium.webdriver import Firefox, FirefoxOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec

# 設定ファイルを取得
login_info = json.load(open("login_info.json", "r", encoding="utf-8"))

# ログインサイト名
site_name = "card_rakuten"

# ログイン画面URL
url_login = login_info[site_name]["url"]

# ユーザー名とパスワードの指定
USER = login_info[site_name]["id"]
PASS = login_info[site_name]["pass"]
PASS2 = login_info[site_name]["pass2"]

# Firefoxのヘッドレスモードを有効にする
options = FirefoxOptions()
options.add_argument('--headless')

# Firefoxを起動する
browser = Firefox(options=options)

# ログイン画面取得
browser.get(url_login)

# 入力
e = browser.find_element_by_id("u")
e.clear()
e.send_keys(USER)
e = browser.find_element_by_id("p")
e.clear()
e.send_keys(PASS)

# ログイン
button = browser.find_element_by_id("loginButton")
button.click()

# 第2パスワード入力画面
# ページロード完了まで待機
WebDriverWait(browser, 10).until(
    ec.presence_of_element_located((By.ID, "indexForm:password"))
)

# 第2パスワード入力
e = browser.find_element_by_id("indexForm:password")
e.clear()
e.send_keys(PASS2)

# ログイン
button = browser.find_element_by_name("indexForm:j_idt78")
button.click()

# ページロード完了まで待機
WebDriverWait(browser, 10).until(
    ec.presence_of_element_located((By.CLASS_NAME, "rf-font-bold"))
)

# ログインできたか確認（画面キャプチャ取る）
browser.save_screenshot("../screenshots/card_rakuten/home.png")

browser.quit()
```


## ログイン情報設定ファイル
サイトURLやログイン情報（IDやパスワード）は、JSON形式のファイルに保持するようにしています。以下のサンプルでは楽天銀行と楽天カードの2サイトの情報と設定しています。

"id", "pass"の値を書き換えればそのまま使えるはずです。

なお、このファイルだけは絶対に漏洩しないよう、管理方法に注意しましょう！

```json:login_info.json
{
  "bank_rakuten": {
    "id": "1234567890",
    "pass": "password",
    "url": "https://fes.rakuten-bank.co.jp/MS/main/RbS?CurrentPageID=START&&COMMAND=LOGIN"
  },
  "card_rakuten": {
    "id": "1234567890",
    "pass": "password",
    "url": "https://www.rakuten-card.co.jp/e-navi/"
  }
}
```
laravel foreachが使えずTrying to get property 'カラム名' of non-objectを解決する

#はじめに
編集画面で投稿した内容を表示させる為にview側にforeachでカラムの値を表示できなかった。
その解決策と何故表示ができなかったのかの解説をします。

#状況
view側にforeachで値を表示させようとすると下記のエラーが発生した。コードも掲載する。

```
エラー文
Trying to get property 'カラム名' of non-object
```

```PostsController.php
use Illuminate\Support\Facades\DB;

public function edit() {

        $posts = DB::table('posts')
        ->select('name','subject','message')
        ->first();
        dd($posts);
        return view('bulletin-boards.edit', compact('posts'));
        }
```

```edit.blade.php
<h1 class="h4 mb-4 font-weight-bold">
            投稿更新ページ
        </h1>
            @foreach ($posts as $post)
            <tr>
                <td>{{ $post->name }}</td>
                <td>{{ $post->subject }}</td>
                <td>{!! nl2br(e($post->message)) !!}</td>
            </tr>
            @endforeach
```

#なぜ、エラー解決に時間が掛かったのか?
foreachは値を全て表示させてくれるという固定概念があった為、解決するのに時間が掛かった。

#解決に向けての知識
####クエリビルダとは
DBのテーブル名を指定してデータを表示させることができます。クエリビルダを使用するには下記の名前空間を使用します。Eloquentの書き方に非常に似ているので混乱します・・・

```
use Illuminate\Support\Facades\DB;(必須)

$id = DB::table('テーブル名')->チェーンメソッド
```

###foreachを使うには?
foreachを使うにはコレクション型になっているものしか使えません。例えば代表的な物として`all`と`get`が挙げられます。この2つはforeachが使用できます。

###クエリビルダ first()
これはひとつだけデータ取得することができます。クエリビルダを使用するには下記の名前空間を使用します。特に`投稿の詳細ページを見る等々で一つずつのデータのみを取得する`際に使われます。
このfirst()はコレクション型ではなく`stdClassのオブジェクト`になります。ddまたはvar_dumpで変数の中身をみてみましょう。![“スクリーンショット” 2021-02-22 22.18.07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698439/11fa5f7f-40d6-459e-9360-c3104cd27e9b.jpeg)

first()はstdClassのオブジェクトになりますので`foreachは使えません。`なので、下記の様に`foreachは不要`になります。以上です。

```PostsController.php
use Illuminate\Support\Facades\DB;

public function edit() {

        $post = DB::table('posts')
        ->select('name','subject','message')
        ->first();
        dd($post);
        return view('bulletin-boards.edit', compact('post'));
        }
```

```edit.blade.php
<tr>
    <td>{{ $post->name }}</td>
    <td>{{ $post->subject }}</td>
    <td>{!! nl2br(e($post->message)) !!}</td>
</tr>
```
【Rails】Capistranoで自動デプロイの時、git stderr: fatal: not a valid object name: master

# エラーの内容
デプロイするため、下記コマンドを実行すると、

```terminal
$ bundle exec cap production deploy
```

このようなエラーが出ていました。(抜粋)

```terminal
# エラーログ
git stdout: Nothing written
git stderr: fatal: not a valid object name: master
```

# 原因
masterというブランチは存在してなく、デフォルトブランチ名はmainだった。 







# 対処方法

config/deploy.rbにて、デプロイするブランチを指定する。
(下記を追記する。)

```
set :branch, "main"
```

# 参考
https://laptrinhx.com/rails-capistranoniyoru-zi-dongdepuroide-fa-shengshitaera-fatal-not-a-valid-object-name-master-366419494/
THEOサイトにPythonとSeleniumを使ってログインする

THEOのサイトにPythonとSelenium使ってログインする方法を解説します。

※2021/02/23時点の情報です

## 環境
- Windows 10
- Python 3.8
- Selenium 3.141.0

## 全体の処理の流れと注意点
全体の処理の流れについては、下記記事に詳しく書いたのでこちらもあわせて確認してみてください。楽天銀行の例になっていますが、処理の流れは同じです。

https://qiita.com/yoshi2045/items/2fff5bf5f0fa763f7104

また、下記記事では他サイトのサンプル一覧と注意点を解説しているのでこちらも参考にしてみてください。

https://qiita.com/yoshi2045/items/a58a7fbebcb9faad3e15

## サンプルコード全文

```python
#
# THEOサイトへログイン
#

import json
from selenium.webdriver import Firefox, FirefoxOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec

# 設定ファイルを取得
login_info = json.load(open("login_info.json", "r", encoding="utf-8"))

# ログインサイト名
site_name = "sec_theo"

# ログイン画面URL
url_login = login_info[site_name]["url"]

# ユーザー名とパスワードの指定
USER = login_info[site_name]["id"]
PASS = login_info[site_name]["pass"]

# Firefoxのヘッドレスモードを有効にする
options = FirefoxOptions()
options.add_argument('--headless')

# Firefoxを起動する
browser = Firefox(options=options)

# ログイン画面取得
browser.get(url_login)

# 入力
e = browser.find_element_by_name("email")
e.clear()
e.send_keys(USER)
e = browser.find_element_by_name("password")
e.clear()
e.send_keys(PASS)

# ログイン
button = browser.find_element_by_css_selector(".md-raised")
button.click()

# ページロード完了まで待機
WebDriverWait(browser, 10).until(
    ec.presence_of_element_located((By.CLASS_NAME, "current-amount-container"))
)

# ログインできたか確認（画面キャプチャ取る）
browser.save_screenshot("../screenshots/sec_theo/home.png")

browser.quit()
```


## ログイン情報設定ファイル
サイトURLやログイン情報（IDやパスワード）は、JSON形式のファイルに保持するようにしています。以下のサンプルでは楽天銀行とTHEOの2サイトの情報と設定しています。

"id", "pass"の値を書き換えればそのまま使えるはずです。

なお、このファイルだけは絶対に漏洩しないよう、管理方法に注意しましょう！

```json:login_info.json
{
  "bank_rakuten": {
    "id": "1234567890",
    "pass": "password",
    "url": "https://fes.rakuten-bank.co.jp/MS/main/RbS?CurrentPageID=START&&COMMAND=LOGIN"
  },
  "sec_theo": {
    "id": "1234567890",
    "pass": "password",
    "url": "https://app.theo.blue/account/login"
  }
}
```
Rspecの導入方法

初学者・初投稿です。よろしくお願いします!間違い等あればご指摘ください！
Rails 6.0.0
Ruby 2.6.5

Rspecの前に、まずテストコードの必要性について確認したのち、本題に触れます。

# テストコードとは？
テストコードを書くことで、手動ではなく、自動でWebアプリケーションの挙動を確認してくれます!
メリットとしては、
・ クオリティの担保ができる
　人為的なミスや、仕様が変えあった時に一から全部やらねばならない、確認した記録が残らないなど。
・ 仕様を見極めることができる
　テスト項目を洗い出す＝アプリケーションの仕様を把握することができる。

### テストコードを書く的に意識することは以下の２点です！
1.「何を確認したいのか」を意識する。
2. 気になる点があれば、binding.pryで止める。(別途Gem「pry-rails」のインストールが必要)

## テストコードの種類
テストコードには、大きく分けると2つの種類があります。

### 単体テストコード
モデルやコントローラーなどの機能１つ１つを確認します。
バリデーションの挙動確認が主体のイメージ。

### 結合テストコード(統合テストコード)
ユーザーがブラウザで操作する一連の流れを再現して問題がないかを確認します。
ex) ユーザーが新規登録をする場合
　　　トップページに移動→サインアップページがあるかを確認→新規登録ページに遷移→ユーザー情報の入力→...など。

### Railsにおいて、テストを書くときに使うと便利なRspec
テストコードについて大まかに理解できたところで、本題に入りましょう！

# Rspecとは？
Rspecとは、Ruby on Railsにテストコードを書くためのGemのことです。
Rspecでは、コマンドひとつでテストの実行が可能です。便利！

[Rspec公式GitHubページ ](https://github.com/rspec/rspec-rails)

# Rspecの導入(Gem)
Rspecの導入は至って簡単です。
Gemfileを開き、**group :development, :test do**にgem **'rspec-rails', '~> 4.0.0'**を記述します・

```Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails', '~> 4.0.0'
end
```

その後bundle installを実行しましょう。

```ターミナル
% cd ~/#任意のディレクトリへ移動
% bundle install
```

## Rspecの設定
次にアプリケーション内でRspecを使うための設定をしていきます。

### 任意のアプリケーションにRspecをインストール

以下のコマンドです。ターミナルに記述します。

```
% rails g rspec:install
```
 完了するといくつかのファイルやディレクトリが生成されます。

### .rspecに設定の追加
テストコードの結果を可視化するための設定をします。
先ほど生成されたファイルの一つ**.rspec**ファイルを開き、以下の記述を追加しましょう。

```.rspec
--require spec_helper
--format documentation
```

ここまででRspecの設定は完了です！お疲れ様でした！

単体テスト、結合テストについては別記事にて随時更新します。
SBI証券サイトにPythonとSeleniumを使ってログインする

SBI証券のサイトにPythonとSelenium使ってログインする方法を解説します。

※2021/02/23時点の情報です

## 環境
- Windows 10
- Python 3.8
- Selenium 3.141.0

## 全体の処理の流れと注意点
全体の処理の流れについては、下記記事に詳しく書いたのでこちらもあわせて確認してみてください。楽天銀行の例になっていますが、処理の流れは同じです。

https://qiita.com/yoshi2045/items/2fff5bf5f0fa763f7104

また、下記記事では他サイトのサンプル一覧と注意点を解説しているのでこちらも参考にしてみてください。

https://qiita.com/yoshi2045/items/a58a7fbebcb9faad3e15

## サンプルコード全文

```python
#
# SBI証券サイトへログイン
#

import time
import json
from selenium.webdriver import Firefox, FirefoxOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec

# 設定ファイルを取得
login_info = json.load(open("login_info.json", "r", encoding="utf-8"))

# ログインサイト名
site_name = "sec_sbi"

# ログイン画面URL
url_login = login_info[site_name]["url"]

# ユーザー名とパスワードの指定
USER = login_info[site_name]["id"]
PASS = login_info[site_name]["pass"]

# Firefoxのヘッドレスモードを有効にする
options = FirefoxOptions()
options.add_argument('--headless')

# Firefoxを起動する
browser = Firefox(options=options)

# ログイン画面取得
browser.get(url_login)

# 入力
e = browser.find_element_by_name("user_id")
e.clear()
e.send_keys(USER)
e = browser.find_element_by_name("user_password")
e.clear()
e.send_keys(PASS)

# ログイン
button = browser.find_element_by_name("ACT_login")
button.click()


# ページロード完了まで待機
WebDriverWait(browser, 10).until(
    ec.presence_of_element_located((By.CLASS_NAME, "user01"))
)

# time.sleep(3)

# ログインできたか確認（画面キャプチャ取る）
browser.save_screenshot("../screenshots/sec_sbi/home.png")

browser.quit()
```


## ログイン情報設定ファイル
サイトURLやログイン情報（IDやパスワード）は、JSON形式のファイルに保持するようにしています。以下のサンプルでは楽天銀行とSBI証券の2サイトの情報と設定しています。

"id", "pass"の値を書き換えればそのまま使えるはずです。

なお、このファイルだけは絶対に漏洩しないよう、管理方法に注意しましょう！

```json:login_info.json
{
  "bank_rakuten": {
    "id": "1234567890",
    "pass": "password",
    "url": "https://fes.rakuten-bank.co.jp/MS/main/RbS?CurrentPageID=START&&COMMAND=LOGIN"
  },
  "sec_sbi": {
    "id": "1234567890",
    "pass": "password",
    "url": "https://site3.sbisec.co.jp/ETGate/"
  }
}
```
Webpack - Webpack5 Migration Note

```
* eslint-loader                       -> eslint-webpack-plugin
* optimize-css-assets-webpack-plugin  -> css-minimizer-webpack-plugin
* terser-webpack-plugin               -> Removed
* webpack-deep-scope-plugin           -> Removed
* html-minimizer-webpack-plugin       -> New Added
* json-minimizer-webpack-plugin       -> New Added
```

```patch:webpack.dev.js

- const merge = require('webpack-merge');
+ const { merge } = require('webpack-merge');

- devtool: '#eval-source-map',
+ devtool: 'eval-source-map',

```

```patch:webpack.prod.js

- const merge = require('webpack-merge');
+ const { merge } = require('webpack-merge');

- devtool: '#source-map',
+ devtool: 'source-map',
```
SBIベネフィットシステムズサイトにPythonとSeleniumを使ってログインする

SBIベネフィットシステムズのサイトにPythonとSelenium使ってログインするコードを書いてみました。

※2021/02/23時点の情報です

## 環境
- Windows 10
- Python 3.8
- Selenium 3.141.0

## 全体の処理の流れと注意点
全体の処理の流れについては、下記記事に詳しく書いたのでこちらもあわせて確認してみてください。楽天銀行の例になっていますが、処理の流れは同じです。

https://qiita.com/yoshi2045/items/2fff5bf5f0fa763f7104

また、下記記事では他サイトのサンプル一覧と注意点を解説しているのでこちらも参考にしてみてください。

https://qiita.com/yoshi2045/items/a58a7fbebcb9faad3e15

## サンプルコード全文

```python
#
# SBIベネフィットシステムズサイトへログイン
#

import json
from selenium.webdriver import Firefox, FirefoxOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec

# 設定ファイルを取得
login_info = json.load(open("login_info.json", "r", encoding="utf-8"))

# ログインサイト名
site_name = "ideco_sbi"

# ログイン画面URL
url_login = login_info[site_name]["url"]

# ユーザー名とパスワードの指定
USER = login_info[site_name]["id"]
PASS = login_info[site_name]["pass"]

# Firefoxのヘッドレスモードを有効にする
options = FirefoxOptions()
options.add_argument('--headless')

# Firefoxを起動する
browser = Firefox(options=options)

# ログイン画面取得
browser.get(url_login)

# 入力
e = browser.find_element_by_id("txtUserID")
e.clear()
e.send_keys(USER)
e = browser.find_element_by_id("txtPassword")
e.clear()
e.send_keys(PASS)

# ログイン
button = browser.find_element_by_id("btnLogin")
button.click()

# ページロード完了まで待機
WebDriverWait(browser, 10).until(
    ec.presence_of_element_located((By.ID, "D_Header1_lblEmployeeName"))
)

# ログインできたか確認（画面キャプチャ取る）
browser.save_screenshot("../screenshots/ideco_sbi/home.png")

browser.quit()
```


## ログイン情報設定ファイル
サイトURLやログイン情報（IDやパスワード）は、JSON形式のファイルに保持するようにしています。以下のサンプルでは楽天銀行とSBIベネフィットシステムズの2サイトの情報と設定しています。

"id", "pass"の値を書き換えればそのまま使えるはずです。

なお、このファイルだけは絶対に漏洩しないよう、管理方法に注意しましょう！

```json:login_info.json
{
  "bank_rakuten": {
    "id": "1234567890",
    "pass": "password",
    "url": "https://fes.rakuten-bank.co.jp/MS/main/RbS?CurrentPageID=START&&COMMAND=LOGIN"
  },
  "ideco_sbi": {
    "id": "1234567890",
    "pass": "password",
    "url": "https://www.benefit401k.com/customer/RkDCMember/Common/JP_D_BFKLogin.aspx"
  }
}
```
マネックス証券サイトにPythonとSeleniumを使ってログインする

マネックス証券のサイトにPythonとSelenium使ってログインするコードを書いてみました。

※2021/02/23時点の情報です

## 環境
- Windows 10
- Python 3.8
- Selenium 3.141.0

## 全体の処理の流れと注意点
全体の処理の流れについては、下記記事に詳しく書いたのでこちらもあわせて確認してみてください。楽天銀行の例になっていますが、処理の流れは同じです。

https://qiita.com/yoshi2045/items/2fff5bf5f0fa763f7104

また、下記記事では他サイトのサンプル一覧と注意点を解説しているのでこちらも参考にしてみてください。

https://qiita.com/yoshi2045/items/a58a7fbebcb9faad3e15

## サンプルコード全文

```python
#
# マネックス証券サイトへログイン
#

import json
from selenium.webdriver import Firefox, FirefoxOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec

# 設定ファイルを取得
login_info = json.load(open("login_info.json", "r", encoding="utf-8"))

# ログインサイト名
site_name = "sec_monex"

# ログイン画面URL
url_login = login_info[site_name]["url"]

# ユーザー名とパスワードの指定
USER = login_info[site_name]["id"]
PASS = login_info[site_name]["pass"]

# Firefoxのヘッドレスモードを有効にする
options = FirefoxOptions()
options.add_argument('--headless')

# Firefoxを起動する
browser = Firefox(options=options)

# ログイン画面取得
browser.get(url_login)

# 入力
e = browser.find_element_by_id("loginid")
e.clear()
e.send_keys(USER)
e = browser.find_element_by_id("passwd")
e.clear()
e.send_keys(PASS)

# ログイン
button = browser.find_element_by_xpath("//form[@id='contents']/div/p/input")
button.click()

# ページロード完了まで待機
WebDriverWait(browser, 10).until(
    ec.presence_of_element_located((By.CLASS_NAME, "user-info"))
)

# ログインできたか確認（画面キャプチャ取る）
browser.save_screenshot("../screenshots/sec_monex/home.png")

browser.quit()
```

## ログイン情報設定ファイル
サイトURLやログイン情報（IDやパスワード）は、JSON形式のファイルに保持するようにしています。以下のサンプルでは楽天銀行とマネックス証券の2サイトの情報と設定しています。

"id", "pass"の値を書き換えればそのまま使えるはずです。

なお、このファイルだけは絶対に漏洩しないよう、管理方法に注意しましょう！

```json:login_info.json
{
  "bank_rakuten": {
    "id": "1234567890",
    "pass": "password",
    "url": "https://fes.rakuten-bank.co.jp/MS/main/RbS?CurrentPageID=START&&COMMAND=LOGIN"
  },
  "sec_monex": {
    "id": "1234567890",
    "pass": "password",
    "url": "https://mxp1.monex.co.jp/pc/ITS/login/LoginIDPassword.jsp"
  }
}
```
C++を用いてスプライン補間を行う

# 概要
C++でスプライン補間を行うコードを示す．
スプライン補間で描かれた曲線は，必ず既知のデータ上を通る特性がある．
原理・数式は他のサイトを参照のこと．

# 実装
基本的な使い方としては，まず既知の等間隔のy軸方向のデータをvector型で用意する．次に，そのデータを引数にしてInitParameter関数を呼び出す．
計算結果は，0～データ数の間を引数としてCalc関数を呼ぶことで取得することができる．
以下のサンプルプログラムは0.01間隔でxが0～6の間の結果を取得することで，元データに対して100倍の細かさで補間データを取得する例となる．

```cpp:main.cpp
CSpline calc;
vector<double> sy;//spline用
float skip = 0.01f;//skip幅
sy.clear();

//等間隔のｙデータをセット
sy.push_back(1);//データを入力
sy.push_back(6);//データを入力
sy.push_back(4);//データを入力
sy.push_back(7);//データを入力
sy.push_back(0);//データを入力
sy.push_back(3);//データを入力

calc.InitParameter(sy); //データをセット
for (float i = 0; i < sy.size(); i += skip)
{
	cout << calc.Calc(i) << endl;
}
```

呼び出し方法は以上で，以下が実装部分のコードとなる．  
  
```cpp:Spline.h
#include <vector>

using namespace std;
class CSpline
{
public:
	CSpline();
	~CSpline();

	//データセット関数
	void InitParameter(const vector<double> &y);

	//演算関数
	double Calc(float t);

private:
	vector<double> a_;
	vector<double> b_;
	vector<double> c_;
	vector<double> d_;
	vector<double> w_;
};
```

```cpp:Spline.cpp
#include "CSpline.h"

CSpline::CSpline()
{
}

CSpline::~CSpline()
{
}

//CSplineデータセット関数
void CSpline::InitParameter(const vector<double> &y) {
	int ndata = (int)y.size() - 1;

	for (int i = 0; i <= ndata; i++)
	{
		a_.push_back(y[i]);
	}

	for (int i = 0; i <= ndata; i++)
	{
		if (i == 0)
		{
			c_.push_back(0.0);
		}
		else if (i == ndata)
		{
			c_.push_back(0.0);
		}
		else
		{
			c_.push_back(3.0*(a_[i - 1] - 2.0*a_[i] + a_[i + 1]));
		}
	}

	for (int i = 0; i < ndata; i++)
	{
		if (i == 0)
		{
			w_.push_back(0.0);
		}
		else
		{
			double tmp = 4.0 - w_[i - 1];
			c_[i] = (c_[i] - c_[i - 1]) / tmp;
			w_.push_back(1.0 / tmp);
		}
	}

	for (int i = (ndata - 1); i > 0; i--)
	{
		c_[i] = c_[i] - c_[i + 1] * w_[i];
	}

	for (int i = 0; i <= ndata; i++) {
		if (i == ndata)
		{
			d_.push_back(0.0);
			b_.push_back(0.0);
		}
		else
		{
			d_.push_back((c_[i + 1] - c_[i]) / 3.0);
			b_.push_back(a_[i + 1] - a_[i] - c_[i] - d_[i]);
		}
	}
}

//CSpline演算関数
double CSpline::Calc(float t)
{
	int j = int(floor(t));
	if (j < 0) {
		j = 0;
	}
	else if (j >= (int)a_.size()) {
		j = ((int)a_.size() - 1);
	}

	double dt = t - j;
	double result = a_[j] + (b_[j] + (c_[j] + d_[j] * dt)*dt)*dt;
	return result;
}
```
メールマーケティング戦略 ⇒ 効果的なマーケティングメールの作成

１．どうすれば件名行が効果的になるのでしょうか?
２．動的コンテンツとは何ですか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/ae74c59b-7f60-f80c-46e0-9b0cade75684.png)
FirebaseでMicrosoftアカウント認証

以下の本家のページにMicrosoft認証の話が書いてありますが、Azure側でどうすれば良いのか、書いてないので、備忘録も兼ねて投稿します。
https://firebase.google.com/docs/auth/web/microsoft-oauth?hl=ja

## JavaScript
### リダイレクト部分
```typescript
const provider = new firebase.auth.OAuthProvider('microsoft.com')
provider.setCustomParameters({ prompt: 'consent' })
firebase.auth().signInWithRedirect(provider)
```

### Callback部分
- Google認証、Facebook認証だと`onAuthStateChanged`だけで十分ですが、Microsoft認証だと`getRedirectResult`も必要になります。

```typescript
const onAuthStateChanged = async (): Promise<firebase.User | null> => {
  await firebase.auth().getRedirectResult()
  return new Promise((resolve) => {
    firebase.auth().onAuthStateChanged((user) => resolve(user))
  })
}
```

## Azure
- https://portal.azure.com/ にログインして、`Azure Active Directoryの管理`を選択します。
![スクリーンショット 2021-02-23 14.25.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89696/c9170b50-fb9e-055a-ad16-fe524bf78a3c.png)

- アプリを新規登録
![スクリーンショット 2021-02-23 14.26.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89696/a68ed38b-27e8-e5d0-c378-6eca7802087e.png)

- `サポートされているアカウントの種類`は、自身のサービスに一致するものを選んでください。
- リダイレクトURIは、Firebaseの画面で表示されたものをコピペします。
![スクリーンショット 2021-02-23 14.27.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89696/04f365a1-8361-fbd7-d17d-f2dd2d52e26e.png)

- 登録後にアプリケーションIDが表示されるので、これをFirebaseで登録することになります。
![スクリーンショット 2021-02-23 14.29.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89696/fc2162e8-66ea-c438-a7d9-453c2b06990d.png)

- Firbaesの画面でシークレットキーも設定する必要があるので、クライアントシークレットを発行します。
![スクリーンショット 2021-02-23 14.31.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89696/586dd0e7-808c-aee4-0647-0ae6f1fbabd8.png)

- 発行した時のIDは不要です。 **使うのは値だけ** です。
![スクリーンショット 2021-02-23 14.55.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89696/31a2418c-02f2-8115-45cd-b62f4c568cb7.png)


- Firebaseの画面で設定するのは以上で終わりなのですが、認証後のCallbackで値をもらうために、APIの設定が必要になります。
- `アクセス許可の追加`を選択します。
![スクリーンショット 2021-02-23 14.31.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89696/f4d8991d-e8d0-895c-ea15-abe52d7826e0.png)

- Microsoft Graphを選択します。
![スクリーンショット 2021-02-23 14.32.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89696/dd3b39c1-fbee-2ee7-6ca3-457cab9048c6.png)

- 取得したいものを選択します。emailは必要だと思いますが、他は必要に応じて選択してください。
![スクリーンショット 2021-02-23 14.33.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89696/ca0483ef-6309-1a93-739c-d1d6b0bb7470.png)

## Firebase
- アプリケーションIDとシークレットキーはAzureで取得した内容を設定します。
![スクリーンショット 2021-02-23 14.39.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89696/054863e3-4481-6424-7bf8-819cce1338ab.png)


- 以上で終わりになります。お疲れ様でした。

## Special Thanks
- https://dev.to/425show/integrate-azure-ad-with-firebase-and-call-ms-graph-in-a-node-js-app-973
HTML&CSS開発におけるVScodeの自動補完とショートカット

#はじめに
VScodeでWEB開発を進めるにあたって、Emmetによる自動補完やショートカットをうまく活用することで、タイプミスを減らしつつ、開発効率があがる。
備忘録がわりに、まとめたものを残す

#自動補完
下記に記載方法をまとめた。
コードタイトルに記載で自動補完することで、コードが自動で生成される。

```:見本：＜タイピング内容＞
補完後の記載コード
```


```html:#container
<div id="container"></div>
```

```html:.cls
<div class="cls"></div>
```

```html:span.cls
<span class="cls"></span>
```

```html:#container>.cls
<div id="container">
  <div class="cls"></div>
</div>
```

```html:#container>.cls*6
<div id="container">
  <div class="cls"></div>
  <div class="cls"></div>
  <div class="cls"></div>
  <div class="cls"></div>
  <div class="cls"></div>
  <div class="cls"></div>
</div>
```

```html:#container>.cls-$*6
<div id="container">
  <div class="cls-1"></div>
  <div class="cls-2"></div>
  <div class="cls-3"></div>
  <div class="cls-4"></div>
  <div class="cls-5"></div>
  <div class="cls-6"></div>
</div>
```

```html:#container>.cls-$$*6
<div id="container">
  <div class="cls-01"></div>
  <div class="cls-02"></div>
  <div class="cls-03"></div>
  <div class="cls-04"></div>
  <div class="cls-05"></div>
  <div class="cls-06"></div>
</div>
```

#ショートカット
VSCodeで使える便利なショートカットで主なものを記載する。
こちらの方の方が詳しいが、主に使えるものを厳選した。
[Visual Studio Code キーボード ショートカット](https://qiita.com/oruponu/items/ae9c720d4522c1606daf)

|操作概要|Windows|macOS|
|---|---|---|
|直近で開いたファイルを表示|Ctrl+Tab|⌃Tab|
|コードの整形|Shift+Alt+F|⇧⌥F|
|行を下へ移動|Alt+↓|⌥↓|
|行を上へ移動|Alt+↑|⌥↑|
|行を下へコピー|Shift+Alt+↓|⇧⌥↓|
|行を上へコピー|Shift+Alt+↑|⇧⌥↑|
|行の削除|Ctrl+Shift+K|⇧⌘K|
|選択範囲と同じ文字列の複数指定|Ctrl+D|⌘D|
|行コメントの切り替え|Ctrl+/|⌘/|
|次を検索|F3|⌘G|
|サイドバーの表示/非表示|Ctrl+B|⌘B|
|ターミナルの表示/非表示|Ctrl+@|⌃@|
VSCode/WSL2/Docker の組み合わせで遭遇するエラーとその対策

# はじめに

Windows で Docker コンテナがらみの開発・動作確認をやってるとディスク IO がトロくて、近頃は WSL2 と組み合わせて Ubuntu の上に作業フォルダを作って VSCode で作業しているのですが ( npm 速いし )、ちょくちょく変なエラーが出ることがあるので、対策をまとめておきます。

## リモート拡張ホスト サーバーへの接続に失敗しました

「[Failed to connect to the remote extension host server (Error: WebSocket close with status code 1006)](https://github.com/microsoft/vscode/issues/115818) 」などで報告されている問題で、現状未解決。
[いい感じに回避策がまとめられてます](https://qiita.com/tatsunari/items/8fdc4022e06b54e172f9)のでそちらへ。要点は「プロキシ有無にかかわらず localhost に直接接続させること」と「LxssManager サービスを再起動すること」です。

#### (2021/03/30 追記)

これは VSCode のというより [WSL2 の不具合](https://github.com/microsoft/WSL/issues/5821) だそうで、 [Insider Preview Build 20231](https://blogs.windows.com/windows-insider/2020/10/07/announcing-windows-10-insider-preview-build-20231/) で解決しているそうです。とはいえ、これだけのために insider preview にアップデートするのはなぁ…。

## <3>init: (4010) ERROR: UtilConnectToInteropServer:300: connect failed 2

なにこの謎のエラー？これが発生すると `docker build` や `docker run` が何も通らなくなって凹みます。これも「 [[WSL2] [Interop] Keep a single shared /run/WSL/* socket](https://github.com/microsoft/WSL/issues/5065) 」などで既知の問題。
これはどうも、ソケット通信のソケット名を示す環境変数 `WSL_INTEROP` の値が「ずれてしまう」のが原因とのことで(なんでそんなことが？)、上記 GitHub issue に回避策が示されています。zsh の例として示されていますが、bash でも動きます。 `.zshrc` または `.bashrc` に下記のような関数を定義します：

```bash 
fix_wsl2_interop() {
    for i in $(pstree -np -s $$ | grep -o -E '[0-9]+'); do
        if [[ -e "/run/WSL/${i}_interop" ]]; then
            export WSL_INTEROP=/run/WSL/${i}_interop
        fi
    done
}
```
エラーが発生したらいつでも `fix_wsl2_interop` を実行すればよい、という寸法。

他にもあったら追記していきます。
C++でベジェ曲線を描く

# 概要
ベジェ曲線を描くためのC++のソースコードを示す．
原理・数式は他のサイトを参照のこと．

# 実装
このコードは入力した制御点に対して指定の刻みでベジェ曲線の座標を出力する．
ベジェ曲線は両端の制御点以外は通らないため，データ自体を補間するような用途より，何となく近似した滑らかな曲線を描くというようなデザイン的な用途に向くとおもわれる．
今回のコードの使い方としては，まずfSkipに出力の刻みを0～1の値で指定する．下の例では制御点のXが1～6のため，0.01と入力することで，入力範囲は600個となる．
次にxとyに制御点をpushしていく．その後，CalcBezierCurve()で演算を実行するとVecResultXとVecResultYに結果が出力される．

```cpp:main.cpp
CBezierCurve calc;//定義
calc.fSkip = 0.01f;//0～1の間で出力間隔を指定(入力範囲を何刻みにするか）

calc.x.clear();
calc.y.clear();

calc.x.push_back(1);//制御点を入力
calc.y.push_back(1);//制御点を入力

calc.x.push_back(2);//制御点を入力
calc.y.push_back(6);//制御点を入力

calc.x.push_back(3);//制御点を入力
calc.y.push_back(4);//制御点を入力

calc.x.push_back(4);//制御点を入力
calc.y.push_back(7);//制御点を入力

calc.x.push_back(5);//制御点を入力
calc.y.push_back(0);//制御点を入力

calc.x.push_back(6);//制御点を入力
calc.y.push_back(10);//制御点を入力

calc.CalcBezierCurve();//演算実行

for (int i = 0; i < (int)calc.VecResultX.size(); i++)//結果を出力
{
	cout << calc.VecResultX[i] << " " << calc.VecResultY[i] << endl;
}
```

呼び出し方法は以上で，以下が実装部分のコードとなる．


```cpp:BezierCurve.h
using namespace std;

class CBezierCurve
{
public:
	CBezierCurve();
	~CBezierCurve();

	//ベジェ曲線計算関数
	void CalcBezierCurve();

	//バーンスタイン基底関数
	double Bernstein(int, int, float);

	//二項係数を計算する関数
	double Binomial(int, int);

	//階乗計算を行う関数
	double Factorial(int);

	//べき乗計算
	double ipow(double, int);

	// 測定データ
	vector<double> x; // 入力データX 
	vector<double> y; // 入力データY 
	vector<double> VecResultX; //出力データX
	vector<double> VecResultY; //出力データY 
	float fSkip;	 // 結果出力時の出力間隔 
};
```

```cpp:BezierCurve.cpp
#include "CBezierCurve.h"

CBezierCurve::CBezierCurve()
{
	fSkip = 0.0f;
	x.clear();
	y.clear();
}

CBezierCurve::~CBezierCurve()
{
}

//ベジェ曲線計算関数
void CBezierCurve::CalcBezierCurve()
{
	double resultX = 0.0;
	double resultY = 0.0;
	int n = (int)x.size();

	VecResultX.clear();
	VecResultY.clear();
	double dSkipOne;
	dSkipOne = 1.0f / ((double)n / fSkip);
	for (double t = 0.0f; t <= 1.0f; t += dSkipOne)
	{
		resultX = 0.0;
		resultY = 0.0;
		for (int i = 0; i < n; i++)
		{
			resultX += x[i] * Bernstein(n - 1, i, (float)t); 
			resultY += y[i] * Bernstein(n - 1, i, (float)t);
		}
		VecResultX.push_back(resultX);
		VecResultY.push_back(resultY);
	}
}

//べき乗計算を行う関数
double CBezierCurve::ipow(double p, int n)
{
	int k;
	double s = 1;

	for (k = 1; k <= n; k++)
	{
		s *= p;
	}
	return s;
}

//バーンスタイン基底関数
double CBezierCurve::Bernstein(int n, int i, float t)
{
	return Binomial(n, i) * ipow(t, i) * ipow(1 - t, n - i);
}

//二項係数を計算する関数
double CBezierCurve::Binomial(int n, int k)
{
	return Factorial(n) / (Factorial(k) * Factorial(n - k));
}

//階乗計算を行う関数
double CBezierCurve::Factorial(int a)
{
	double result = 1.0f;
	for (int i = 2; i <= a; i++)
	{
		result *= i;
	}

	return result;
}
```
【GAS】状態に合わせてシートのセル背景色を変更する

GASのトリガー実行で定期的にリンク先のチェックを行うような例です。
実際のやりたいことはちょっと違いますが、今回は下記のようなスプレッドシート（テーブル）で書きます。


| name    | url                | response_code | 
| ------- | ------------------ | ------------- | 
| example | http://example.com | 404           | 
| Qiita   | https://qiita.com  | 200           | 
| foo     | http://bar.com     |               | 

## 要件
- 時間ベースのトリガーでシートに記載しているURLの存在チェックを実施 
- UrlFetchApp.fetchの結果から取得できるステータスコードをresponse_codeカラムに上書き
- 未チェックの場合、response_codeカラムは空。

## 結論（コード）
一応、2パターン。

### 破壊的変更なし
```js
function updateBackgroundsColor() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const dataRange = sheet.getRange();

  const data = dataRange.getValues();
  const colors = data.map((row) => {
    // ステータスコード200の時とそれ以外の時のカラーコード定義
    const color = row[2] === 200 ? '#acd33f' : '#e41134';
    return row.slice().fill(color);
  });

  dataRange.setBackgrounds(colors);
}
```

### 破壊的変更あり
```js
function updateBackgroundsColor() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const dataRange = sheet.getRange();

  const data = dataRange.getValues();
  data.forEach((row) => {
    const color = row[2] === 200 ? '#acd33f' : '#e41134';
    row.fill(color);
  });
  
  dataRange.setBackgrounds(data);
}
```

## 参考リンク
https://www.yukibnb.com/entry/gas_sheet_setBackgrounds
Linux cutコマンドのメモ

#Linuxのcutコマンドの簡単な解説

つぎの```sample```というテキストファイルを題材にして ```cut``` コマンドを説明していきます。

```sh:sample	
foo,bar,baz
120,678,231
Ubuntu,Debian,CentOS
```

## -c オプション
何文字目なのかをベースにしてテキストを切り出すには```-c```オプションを使います。以下はテキストの各行から最初の3文字を取り出す例です。```-c1-3```は１文字目から３文字目という意味です。

```
$ cut -c1-3 sample
foo
120
Ubu
```

このように ```cut``` コマンドはデフォルトでは画面(標準出力)に結果を表示します。結果をファイルに格納したかったら ```>``` の記号を使ってリダイレクトしないといけません。

```
$ cut -c1-3 sample > first_3               
$ cat first_3	
foo
120
Ubu
```

次は、5〜7文字目と9〜11文字目を切り出す例です。

```
$ cut -c5-7,9-11 sample
barbaz
678231
tu,ebi
```

## -d 及び -f オプション

タブやカンマで区切られたフィールドごとに切り出すにはこれらのオプションを用います。上の ```sample```ファイルはカンマで区切られていますが、カンマで区切られた2列目を表示したい場合は次のようにします。

```
$ cut -d, -f2 sample
bar
678
Debian
```

この```-d```は ```-delimiter```の略です。```-d```の直後に```,```がありますから```-d,```で区切り記号がカンマであると指定しているのです。```-d```オプションを省略するとデフォルトのタブ記号をdelimiterに指定したことになります。

以下は、カンマで区切られた1番目と3番目のフィールドを抽出した例です。

```
$ cut -d, -f1,3 sample
foo,baz
120,231
Ubuntu,CentOS
```

## --output-delimiter オプション

上の出力例のように、デフォルトでは ```-d```オプションに指定したカンマを利用してフィールドは区切られます。この区切り記号を変更したい場合には```--output-delimiter```オプションを使います。以下は空白で区切った例です。

```
$ cut -d, --output-delimiter=" " -f1,3 sample
foo baz
120 231
Ubuntu CentOS
```

タブで区切りたい場合は技巧的ですが以下のようにするとよいでしょう。

```
$ cut -d, --output-delimiter="$(printf \\t)" -f1,3 sample
foo     baz
120     231
Ubuntu	CentOS
```

bash, ksh, zshでは次でもOKです(shでは機能しません)。

```
$ cut -d, --output-delimiter=$'\t' -f1,3 sample
foo     baz
120     231
Ubuntu	CentOS
```
上の例はシェルスクリプトの一行目で ```#!/bin/sh``` のように sh を指定してしまうと 
```$'文字列' ```
が機能せず、ねらい通りに動かないので注意してください。

##他のコマンドとの連携
```cut```コマンドは標準入力からの入力を受け付けているので、パイプ ```|``` の右側に持ってくることができます。つぎは、```grep```コマンドで処理した結果を、```cut```コマンドで処理する例です。

```
$ grep [a-zA-Z] sample | cut -d, -f3
baz
CentOS
```

```sample``` というファイルの中でアルファベットを含む行を ```grep``` で抽出すると

```
$ grep [a-zA-Z] sample
foo,bar,baz
Ubuntu,Debian,CentOS
```

となるはずです。この2行のデータの中で、カンマで区切られた3行目を抽出すると上のように ```baz``` と ```CentOS``` が出てくるのわけです。