OmniAICreator/Qiita-1.07M huggingface dataset:
jQueryを使ってクリックする度に要素のテキストを切り替える方法

#今回の記事

①jQueryを使ってクリックする度に要素のテキストを切り替える方法をメモ
※自分の,そのままのコードを貼り付けているので、分かりづらいかもしれません。

おまけ
②　①で切り替えると他の要素を変更させる方法
Railsにて、要素を変えたいが中身にインスタンス変数などがあり、ややこしいかも


#環境
ruby 2.6

#対象のコード
*①jQueryを使ってクリックする度に要素のテキストを切り替える方法*

```perl:HTML
 <p class = "footer-left-m" >▷Monthly</p>
```
こちらは、期間の月を表してます。こちらをクリックするたび「Yearly、Day、Week」に変更していく。

```perl:application.html.erb
 <script src="//ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
```
jQueryを読み込みさせる。

```perl:jQuer
<script>

      $('.footer-left-m').on('click', function () {
        if ($(this).text() === '▷Monthly') {
              $(this).text('▷Yearly');
            } else if ($(this).text() === '▷Yearly'){
               $(this).text('▷Day');
            } else if ($(this).text() === '▷Day'){
              $(this).text('▷Week');
            }else{
              $(this).text('▷Monthly');
            }
      });

    </script>

```
body内に記述
ポイント：$('.footer-left-m')　は、class = "footer-left-m"を指定。先頭に「.」がついている

こちらでクリックするたび、「Monthly,Yearly、Day、Week」の順に変更してます。
▷はつけなくて大丈夫です！

以上


#おまけ
*　①で切り替えると他の要素を変更させる方法*
今回は期間を変わるたび金額を変えたかったです。
表示内容に、DBから情報をひっぱてきていた内容を変更させたかったので、期間が変わるたびテキストではなくて、別のhtmlを表示させるようにしました。

```perl:HTML
<div class = "footer-light" id ="footer-light">
    <p class ="totale-price"  ><%= "¥#{number_to_currency(@content.sum(:price))}" %></p>
</div>
```
こちらはユーザーが登録したアイテムの合計金額。
「<%= "¥#{number_to_currency(@content.sum(:price))}" %>」の部分はMonthlyの金額が表示されてる。
やりたいことは、期間が変わるたび、別のhtmlを表示させて金額を変える。



```perl:jQuer
<script>

      $('.footer-left-m').on('click', function () {

        if ($(this).text() === '▷Monthly') {
              $(this).text('▷Yearly');
              $('#footer-light').html("<%= escape_javascript(render 'price.y') %>");        
            } else if ($(this).text() === '▷Yearly'){
               $(this).text('▷Day');
              $('#footer-light').html("<%= escape_javascript(render 'price.d') %>");
            } else if ($(this).text() === '▷Day'){
              $(this).text('▷Week');
              $('#footer-light').html("<%= escape_javascript(render 'price.w') %>");
            }else{
              $(this).text('▷Monthly');
              $('#footer-light').html("<%= escape_javascript(render 'price.m') %>");
            }

      });

    </script>

```
```perl:_price.y.html.erb
<p class ="totale-price" id ="t-price" ><%= "¥#{@content.sum(:price)*12}" %></p>
```

ポイント： ('#totale-price')は　IDを指定。クラス指定の　('.footer-light')でも問題ない
.html("<%= escape_javascript(render 'price.y') %>");  で、Yearlyに期間が変わったらテンプレートを呼び出して別のHTML(_price.y.html.erb)に差し替え

以上になります。
最後までありがとうございました。
flaskで1から日記帳アプリを作る　その1

#flaskで1から日記帳アプリを作る
夏休みに向けてWebアプリケーションを学びたいという方に向けて、簡単にWebアプリを作れるflaskを用いた日記帳アプリを作成していきたいと思います。


##環境
・pyenv + pipenv
・macOS Catalina
・sqlalchemy
・SQLite3


##記事内容

今回はflaskの概要を抑えつつ、DB接続を通じてデータの保存までの流れを書いていこうと思います。
本記事では以下の２部構成で進めます。
・その１（今回）：ファイルの準備と各ファイルの説明
・その２以降：実際にコードを書きながら詳細の説明
また、初投稿な故見にくい部分等あるかと思いますがご容赦ください。


##本文

さて今回はflaskにおけるファイル準備を行っていきます。
本来、flaskは1つのファイルに全ての情報をかける「マイクロフレームワーク」という形式になっています。
しかし、実際のアプリとなるとやはりそれぞれの機能毎にファイルを分けたほうが、拡張性が高く便利です。
よって今回は、初めから各機能を分けてアプリを構築していきます。


###全体図

まずは今回使用するファイルの全体図を見てみましょう。
![スクリーンショット 2021-08-24 10.40.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1796563/ff51da9c-659d-792f-dbc8-7635bff2909d.png)



では、一つずつ説明します。

###server.py(/)
これはサーバを立ち上げる際に使うファイルです。

###__Init__.py(/flask_app)
これはデータベースを実際に扱う際に使用する変数を設定しています。

###config.py(/flask_app)
これはこのアプリケーションの設定を記載したファイルです。
DBの接続先や各種ディレクトリ情報を記載します。

###flask.db(/flask_app)
これはデータベースファイルです。
蓄積される全てのデータがここに保管されています。

###models.py(/flask_app/models)
これはデータベースのテーブルを定義するファイルです。
SQLでのCREATE TABLEです。

###views.py(/flask_app/views)
これは実際の動作を定義するファイルです。
ページ遷移時の挙動や、その他関数を定義します。

###static(flask_app/static)
ここはCSSやJavaScript、写真を保管しておくフォルダです。
flaskでは、デフォルトでこの場所を参照します。
CSSや写真を使用するときは注意しましょう。

###templates(flask_app/templates)
ここはHTMLを保管するフォルダです。

これで、今回使うファイル、フォルダは全てです。
次回は実際にコードを書き、日記帳を完成させようと思います。
ModsecurityをUbuntu20.04に導入する

## Ubuntuのファイアウォール設定
まずは起動。

```console:Ubuntu
# ufw enable
```

httpの通信を許可したいので80版ポートを開ける。

```console:Ubuntu
# ufw allow 80
# ufw reload
```

## インストール
### Apache2のインストール

```console:Ubuntu
# apt-get update
# apt-get install apache2
```

### Modsecurityのインストール

```console:Ubuntu
# apt-get install libapache2-mod-security2
# systemctl restart apache2
```

## 設定
### 設定ファイルの作成・変更
```console:Ubuntu
# cp /etc/modsecurity/modsecurity.comf-recommended /etc/modsecurity/modsecurity.conf
# vi /etc/modsecurity/modsecurity.conf
```

`DetectionOnly`のところを`On`に変更

```console:modsecurity.conf
...
# -- Rule engine initialization ---------------------------------------------

# Enable ModSecurity, attaching it to every transaction. Use detection
# only to start with, because that minimises the chances of post-installation
# disruption
#
SecRuleEngine On
...
```

### ルールファイルのインストール

``` console:Ubuntu
# mv /usr/share/modsecurity-crs /usr/share/modsecurity-crs.dis
# git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git /usr/share/modsecurity-crs
# cp /usr/share/modsecurity-crs/crs-setup.conf.example /usr/share/modsecurity-crs/crs-setup.conf
```

### ルールの適用

```console:Ubuntu
# vi /etc/apache2/mods-enabled/security2.conf
```
`IncludeOptional /usr/share/modsecurity-crs/*.load`をコメントアウト
その下に、`IncludeOptional /usr/share/modsecurity-crs/*.conf`を追記。

```console:security.conf
...
# Include OWASP ModSecurity CRS rules if installed
# IncludeOptional /usr/share/modsecurity-crs/*.load
IncludeOptional /usr/share/modsecurity-crs/*.conf
```
### リバースプロキシの設定

```console:Ubuntu
cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/my-proxy.conf
vi /etc/apache2/sites-available/my-proxy.conf

```console:my-proxy.conf
...
# http reverse proxy
ProxyPass / <検知したいサイトurl>/
ProxyPassReverse / <検知したいサイトurl>/
...
```

```Console:Ubuntu
# a2ensite my-proxy
# a2dissite 000-default
# systemctl restart apache2
```

## 確認
Modsecurityを導入したPCのIPにアクセスして検知したいサイトに飛べばプロキシ設定は成功。
試しにXSSをしてみてブロックされたらヨシ
ログは、`/var/log/apache2/modsec_audit.log`にあるのでtailなどで確認する。
簡単にオレオレ証明局＆証明書を作る方法

ローカルドメインやテスト環境などでオレオレ証明書が必要な場合に簡単に作成する方法です。

# mkcert

https://github.com/FiloSottile/mkcert

# インストール

## macos

```
brew install mkcert
```

# 使い方

## 初回（認証CAインストール）

```
mkcert -install
```

## 他のPCにCAを移す場合

`mkcert -CAROOT`で出たパスのrootCA.pemを移行する。

## 証明書の作成

```
mkcert hoge.mytestdomain.com
```

有効期間825日のSSL証明書が作成されます。

（ローカルCAの証明書なので1年以上の有効期限でも問題無いようです）

## 削除

```
mkcert --uninstall
```

証明局ごと削除されます。
【Golang】改行などをエスケープして表示したい。【代入済み変数の文字列をエスケープ出力】


> 改行やタブ入りの文字列の変数をプリントする際に、展開させずにエスケープしたまま表示させたい。
> つまり文字列内のタブ（`0x09`）は "`\t`" として表示させたい。
>
> ```go:展開させないで出力したい
> string("Hello\tworld!") // --> Hello\tworld! として欲しい
> string(`Hello
> world!`)                // --> Hello\nworld! として欲しい
> ```

:::note info
<a href="https://www.google.com/search?q=%22golang%22+%E6%96%87%E5%AD%97%E5%88%97+%E6%94%B9%E8%A1%8C%E3%82%92%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%E3%81%97%E3%81%A6%E8%A1%A8%E7%A4%BA" target="_blank">「"golang" 文字列 改行をエスケープして表示」でググる</a>も、初歩的するぎるため、逆の方法（タブや改行をエスケープして変数にセットし、出力時にパースする方法）や、あっても代入時に <code>&#096;</code>（バッククォート）を使う方法ばかり。**すでに代入済みの変数を展開せずにエスケープしたまま出力したい**のです。
タイトルからピンポイントの記事がすぐに見つからなかったので、自分のググラビリティとして。
:::

## TL; DR <sub><sup><sub><sup>（今北産業）</sup></sub></sup></sub>

1. `fmt.Printf()` で `%#v` フォーマットを使う。
1. 使用例: `fmt.Printf("%#v\n", "my\tsample\ndata")`
    ```diff
    - fmt.Printf("%s", "my\tsample\ndata")
    + fmt.Printf("%#v", "my\tsample\ndata")
    ```
3. 具体例:
    ```go:実際の動くサンプル
    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	mySampleVar := "my\tsample\ndata"
    
    	fmt.Println("1)", mySampleVar)
    	fmt.Printf("2) %v\n", mySampleVar)
    	fmt.Printf("3) %#v\n", mySampleVar)
        fmt.Println("4)", strings.Trim(fmt.Sprintf("%#v", mySampleVar), `"`))
    }
    // Output:
    // 1) my	sample
    // data
    // 2) my	sample
    // data
    // 3) "my\tsample\ndata"
    // 4) my\tsample\ndata
    ```

- [オンラインで動作をみる](https://go.dev/play/p/Lnx4sysHy-f) @ GoPlayground

### 参考文献

- [Printing](https://pkg.go.dev/fmt#hdr-Printing) | fmt package | Documentation @ pkg.go.dev
[機械学習] ド素人がscikit-learnを使ってアヤメ分類をやってみた

こんにちは。
scikit-learnを使ってアヤメ分類をしてみましたので軽くメモをまとめます。
今回は環境構築不要の開発環境 Google Colaboratory を使ってます。

# 今回やること
機械学習ライブラリであるscikit-learnを使って元々サンプルデータが用意されているアヤメデータを使って、がく片や花びら幅や長さを数値化してどこのアヤメなのか機械学習で判別します

![1_lFC_U5j_Y8IXF4Ga87KNVg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183215/86ffb98f-21e7-1198-9dcc-575ed1d1e828.png)

## 必要なライブラリなどインポートしておく

```Python:1.py
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.svm import LinearSVC
```

## データをセット
```Python:2.py
dataSet = load_iris()
irisData = pd.DataFrame(dataSet.data, columns=["がく片の長さ","がく片の幅","花びらの長さ","花びらの幅"])
irisData['花の種類'], irisData['Target']  = dataSet.target_names[dataSet.target],  dataSet.target
```

irisDataの中身を確認するとこんな感じのデータが出てくると思います。

||がく片の長さ|がく片の幅|花びらの長さ|花びらの幅|花の種類|Target|
|:----|:----|:----|:----|:----|:----|:----|
|0|5.1|3.5|1.4|0.2|setosa|0|
|1|4.9|3.0|1.4|0.2|setosa|0|
|2|4.7|3.2|1.3|0.2|setosa|0|
|3|4.6|3.1|1.5|0.2|setosa|0|
|4|5.0|3.6|1.4|0.2|setosa|0|
|...|...|...|...|...|...|...|
|145|6.7|3.0|5.2|2.3|virginica|2|
|146|6.3|2.5|5.0|1.9|virginica|2|
|147|6.5|3.0|5.2|2.0|virginica|2|
|148|6.2|3.4|5.4|2.3|virginica|2|
|149|5.9|3.0|5.1|1.8|virginica|2|


## 学習用（訓練用）とテスト用を作成

モデルにデータを学習用させる（訓練用）とテスト用にデータ分割を作ります。
デフォルトはtest_size=0.25で25%がテスト用、残りの75%が訓練用となるが0.3のほうがバランス的に良さそうなので設定する（要出典？）

```Python:3.py
irisDataTarget = pd.DataFrame(dataSet.target, columns=["Target"])
X_train, X_test, y_train, y_test = train_test_split(irisData.loc[:, ["がく片の長さ", "がく片の幅",  "花びらの長さ", "花びらの幅"]], irisDataTarget, test_size=0.3)
```

## データを可視化

```Python:4.py
import seaborn as sns
import japanize_matplotlib
sns.set(font="IPAexGothic") #ラベル名に日本語が入っていると文字化けするので設定する
sns.pairplot(irisData.loc[:, ["がく片の長さ", "がく片の幅",  "花びらの長さ", "花びらの幅", "花の種類"]], hue="花の種類") 
```

### 可視化した結果
![ダウンロード (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183215/e2cd708b-a46b-601a-0062-bb978dbe378d.png)

花びらの長さと花びらの幅、特徴量がうまく分別できてそうなので問題なさそうですね！


## モデル化

scikit-learnには様々なアルゴリズムをありどれを選べばいいのかチートシートがあるのでこちらの記事を参考して最適なアルゴリズムを決定します。
https://qiita.com/sugulu_Ogawa_ISID/items/e3fc39f2e552f2355209
今回は教師あり学習なのでチートシートに沿ってYES or No を進めていくとLinerSVCというアルゴリズムを使うことにします。
パラメータチューニングは一旦デフォルトのままでモデル化します。

```Python:5.py
model = LinearSVC()
model.fit(X_train, y_train)
a = model.score(X_train, y_train)
```

### 結果
```
0.9619047619047619
```

実行すると約96%ぐらい正解していますね。かなりの精度でしょうか。 パラメータチューニングをすればもっと良くなるんじゃないかなと思ったりしています。

## 構築したモデルにデータを投げてみる

構築したモデルにがく片の長さなどを入れてどこのアヤメなのか予測してみます。

||がく片の長さ|がく片の幅|花びらの長さ|花びらの幅|花の種類|Target|
|:----|:----|:----|:----|:----|:----|:----|
|0|5.1|3.5|1.4|0.2|setosa|0|
|145|6.7|3.0|5.2|2.3|virginica|2|

```Python:6.py
testData = [
             [6.7, 3.0, 5.2, 2.3],
             [5.1, 3.5, 1.4, 0.2]
            ]
model.predict(data)
```

### 結果
```
array([2, 0]) 
```

うまく行ってそうですね。（小並感）
とこんな感じにサクッと構築してみましたが、　ド素人でも簡単に実装することができました。
俺だけのミニマルなvim

## 移動
|  vim  |  behavior  |
| ---- | ---- |
|  k  |  ↑  |
|  j  |  ↓  |
|  l  |  →  |
|  h  |  ←  |
|  w  |  次の単語の先頭へ  |
|  b  |  前の単語の先頭へ  |
|  e  |  単語の最後へ  |
|  gg  |  ファイルの先頭へ  |
|  G  |  ファイルの最終行へ  |
|  ○G  |  ○行へ  |
|  Cntl + f  |  次のページへ  |
|  Cntl + b  |  前のページへ  |

## 削除
|  vim  |  behavior  |
| ---- | ---- |
| dd  |  行を削除(カット)  |
|  D  |  行内のカーソル以降を削除  |
|  x  |  カーソル下の一文字を削除  |
|  de  |  カーソル位置の単語の最後まで削除  |

## コピペ
|  vim  |  behavior  |
| ---- | ---- |
|  y  |  コピー  |
|  Y  |  行をコピー  |
|  p  |  ペースト  |
|  P  |  現在位置にペースト  |

## 選択
|  vim  |  behavior  |
| ---- | ---- |
|  V  |  行選択スタート  |
| Cntl + v  |  矩形選択スタート  |
| vi'  |  'の内部にある文字列を選択  |

## インサート
|  vim  |  behavior  |
| ---- | ---- |
|  i  |  カーソルの前で挿入モード  |
|  o  |  次行を新規行として挿入してインサートモード  |
|  a  |  カーソルの後ろで挿入モード |
|  A  |  末尾に移動して挿入モード  |
|  I  |  先頭に移動して挿入モード  |
|  ci'  |  'の内部にある文字列を削除して挿入モード  |
|  Cntl + v → c  |  矩形選択した範囲を削除して挿入モード  |

## 削除して挿入
|  vim  |  behavior  |
| ---- | ---- |
| cw  |  dwしたあと挿入モード  |


## その他
|  vim  |  behavior  |
| ---- | ---- |
|  u  |  元に戻す  |

## 引用
- https://qiita.com/takeharu/items/9d1c3577f8868f7b07b5
PythonでMac上にスタンドアロンアプリをつくってハマった件

#一年ぶりくらいの投稿
GoogleSpreadsheetの記事書いてたのに今回はPythonです
仕事でちょっとしたPythonツールをつくっていたのですが、職場で共有しようとスタンドアロン化で苦労したので備忘録でメモ書きです

##１，前提
Pythonの知識０からのスタート。人のコードはみたことあれど、というところ
Macのアプリつくったことありません（←今回、ここがハマった要因）
##２，書くこと
おもにpy2appつかってハマったこと気づいたこと
##３．その気があったら
Pythonについておもったことをつらつら後日
***
最初はPyInstallerをつかってみてた。記事も多かったし。
しかし、うんともすんとも起動しないのでpy2appに手を出す。
（PyInstallerにおそらく同じ問題で解決するんじゃないか疑惑アリ）

###アプリの概要
TkinterやとあるサーバアプリのPythonAPIをつかってサーバとデータをやり取り。ログをファイルに書き出し、設定ファイルへ各種情報を保存する

##結論だけ先に
ソース上でログ・ファイルを指定している場所が悪い、設定ファイルの指定している場所が悪い、読み込むファイルが（以下略
全部、私が悪かったですごめんなさい
スクリプトでは問題ない指定でもアプリ化するときは気をつける必要がありました

##手順
py2appでアプリ化
これ自身は難しくない
以下、VSCodeのターミナル上でのお話
py2App自身は

```
%pip install py2app
```

でよいし、そのあと、アプリ化するpyファイルのあるところで以下コマンド

```
%py2applet --make-setup UmeUme.py
```

これで、setup.pyができる

```Pyhton:setup.py
>from setuptools import setup
APP = ['UmeUme.py']
DATA_FILES = []
OPTIONS = {}
setup(
    app=APP,
    data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)
```
↑テンプレファイル。普通はなんもいじらない（←ここがダウトだった）

次に

```
$python setup.py py2ap
```

で、distフォルダにUmeUmeができあがる
ここで、UmeUmeをポチッとな、とするとアプリが起動、、、、**しませんでした**
動こうとしてアイコンがでてくるけど、しばらくしたら消える

早速Google先生に聞いてみます。いっぱいでてきます。
容疑者

１）Python自身（**Brew**版をいれるべし。**--enable-framework**オプションをいれるべし等）
２）Tkinterとtcltk（１をおこなったらなぜかバージョンが8.6から8.5へなってしまった）
３）自分自身のコード　←犯人はこいつだ！

Pythonをいれなおし、tcltkをいれなおし、Tkinterをいれなおしたけど、うごかず。

コンソールアプリでログをみてもExitしたよん、ってエラーしかでてなく
Macでアプリ化なんて無理だ！（M1になっていろいろ変わったとかあったり）
とおもったところで、初心にもどって（違う）、素の状態なら動くよね？と

UmeUme.pyからいろんな記述をコメントアウトしていき、Tkinterだけにしたら起動した（当たり前）

```Python:UmeUme.py
import tkinter as tk
def  main():
    main = tk.Tk()
    main.mainloop()

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

１つ１つふやしていくと、ログを設定してるところを有効にするとまたしても起動せず
↑そもそもログが吐き出されてないのでなんで動かないのかわからないのだった

ファイルに書き込めないのかなー、と、ググる

>アプリのパッケージを開き、MacOSフォルダにあるアプリファイルをコンソールから実行してみて
“right click -> Show Packages -> Resources -> Mac OS”, and execute your app directly do help, because it shows specific errors on the console

という一文をStackOverflow様

[Py2app Can't read file](https://stackoverflow.com/questions/64282214/py2app-cant-read-files)

でみつける
実行すると、アプリがちゃんとエラーを吐いてました

```
FileNotFound（UmeUme.py:25)
```

結果からいうと、Macでアプリ化した場合のカレントフォルダの認識がアプリ下の階層になってしまうので、パスの指定に気を配る必要があるんですね
ログファイル→アプリと同じフォルダの下にLogsフォルダをつくってた→とりあえず、相対パスの指定を変更
　（ここは実際には要変更。Macのアプリのログの指定の仕方を調べないと・・・）
設定ファイル→setup.pyのDATA_FILESに記載→ビルド時にResourcesにコピーしてくれる
読み込むファイル→setup.pyのDATA_FILESに記載→ビルド時にResourcesにコピーしてくれる

具体的には以下

```Python
__file__  #アプリのファイルパスをとる　NGやった

argv[0] #こちらはうごく
```


```Python:setup.py
DATA_FILES = ['UmeUme.json']
```

でバッチリ起動しました。
考えてみれば、Macとかでアプリ化するって、UIつくものばかりだから、Tkinterで動かないわけがないんですよね
ググって逆にハマった典型でした

こんなアホなところではまらんとは思いますが、同じところで躓くひとがもしいたら参考になれば、と。
【Python】VSCode設定【Windows,Mac両対応】


## VSCode(コードエディタ)の設定

### インストール

[こちらからダウンロード](https://code.visualstudio.com/)

### 設定

日本語化
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/e61c1c3f-d5ac-4c4a-b6e7-e61b82857335.png)
こちらをインストールしVSCodeを再起動

python拡張機能インストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/9aa9a9eb-dc47-364f-6db6-4687fea38b17.png)

## 既定ターミナルを設定

ターミナルを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/2f3f5e6d-276c-31c8-e994-2d84837e2724.png)
既定のプロファイルの選択をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/fde908e4-1747-6ce5-a236-e8dbba764436.png)
Windowsなら**Git Bash**でMacなら**zsh**を選択しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/c641e4f5-5d85-f22d-dda4-0dbf6e341c35.png)

## おすすめ拡張機能

### Pylance

静的型チェック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/2852a490-ba7b-c81f-7357-ca22d0cb3459.png)

## 終わり
最低限Pythonを使う上での設定が終わりました。
VSCodeには他にも便利な拡張機能があるので色々試してみてください！
【input】disabled属性が無効/有効化でボタンの色を変えたい

初投稿です。忘備録になります。

フォームの送信ボタンをdisabled属性が無効/有効の時で色を分けたいなと思い、
（その方がユーザビリティ的に良いと思うので）
調べた結果、下記にたどり着きました。

＜HTML＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1929617/c5e3060a-06aa-c6bc-4b8e-22ea674e9225.png)

＜SCSS＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1929617/ab4c2c5d-4072-c3de-5454-ceef889e8c6c.png)

まずHTMLのinputタグにdisabledを付けるのをお忘れなく。
私は最初つけていなくてずっとdisabled効かない、、！となっていました。
ついていないんですから、効くわけないですね。

ボタンの装飾のコードは参考程度に。みんな違ってみんないいなので。
大事なのは
【input[type='submit']】にdisabledが無効の時のボタンの装飾
【input[type='submit']:disabled】にdisabledが有効の時のボタンの装飾
を書きます。


そうしますと、下記の画像のようになります。

【disabled有効】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1929617/45157e2a-a4b7-ee54-6566-2d1fa6821316.png)

【disabled無効】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1929617/dde10d32-c3ce-3823-150e-af2ac5dbaf71.png)


できて当たり前かもしれないのですが、
忘れないように投稿させていただきました。
どのようなときにdisabledを有効/無効にするなどの設定は
jqueryやjavascriptで設定してください。

私と同じようなところで手が止まっている方の
お役に立てれば嬉しいです。
Azure ExpressRoute構築作業メモ

エクスプレスルートリソース作成
https://docs.microsoft.com/ja-jp/azure/expressroute/expressroute-howto-circuit-portal-resource-manager
Vnet作成
https://docs.microsoft.com/ja-jp/azure/virtual-network/quick-create-portal
※IPの払い出しについて
(https://docs.microsoft.com/ja-jp/azure/expressroute/expressroute-about-virtual-network-gateways)
ゲートウェイ作成
https://docs.microsoft.com/ja-jp/azure/expressroute/expressroute-howto-add-gateway-portal-resource-manager
エクスプレスルートとゲートウェイの接続
https://docs.microsoft.com/ja-jp/azure/expressroute/expressroute-howto-linkvnet-portal-resource-manager
【IT未経験向け】インフラエンジニアのキャリアパス【現役インフラエンジニアが解説】

# はじめに

* インフラエンジニアとしてどうキャリアを積んでいけばよいか悩んでいる

* そもそもインフラエンジニアとして何がしたいか、どんな職種があるのか分からない

* 最短で効率よくキャリアをアップさせる方法を知りたい


このような悩み、疑問に答えます。
本記事を読むと下記についてのことが分かります。

* インフラエンジニアのキャリアを知る

* インフラエンジニアとして目指すべきキャリアの方向性が分かる

* 結論はクラウド（AWS）エンジニアを目指すべき


# 記事の信頼性
筆者はAWS経験5年程度です。AWS資格は5冠達成しました。
現在は大規模ECサイトのAWS運用を任されるようになっています。


# インフラエンジニアの職種

まずはインフラエンジニアとしてどんな職種があるのか、その職種でどんな知識が必要かをざっくり紹介します。


## 職種共通知識
基本情報処理技術者レベルの基礎知識は必須です。
[基本情報技術者試験(FE)　～ ITエンジニアの登竜門～](https://www.jitec.ipa.go.jp/1_11seido/fe.html)

どんな職種でもまずは運用・保守から入り、構築→設計→要件定義→提案の順序で経験するのが効率が良いと思います。
※運用を経験することで何のために構築するのか分かる。
　構築を経験することで何のために設計するのか分かる。
　のような流れです。

## ネットワークエンジニア
ネットワーク機器やネットワークに関する深い知識が求められる。
FW製品やロードバランサー、ルータ、スイッチなどの設計を行います。
ただクラウド需要の高まりにより、ネットワークしか知らないエンジニアのニーズは減少傾向にある
（クラウドの場合はそこまで高いネットワーク機器の知識が要求されない）

[ネットワークエンジニアの将来性は？市場価値を高める方法を解説](https://and-engineer.com/articles/YAY6cBAAACcAQ8Ce)



[ただのネットワークエンジニアはもういらない？](https://axxis.co.jp/magazine/30735)

→従来のネットワークエンジニアには将来性はない
　クラウドスキルが必須のようなことが記載されています。


## データベースエンジニア

[データベーススペシャリストの業務を理解する](https://www.atmarkit.co.jp/ait/articles/1703/01/news036.html)

データ管理者（DA：Data Administrator）が「概念データモデル」「論理データモデル」の設計を行い、これを基にデータベース管理者（DBA：Database Administrator）が「物理データベース」の設計を行います。

インフラエンジニアはDBA側です。

DBAは業務知識ではなくデータベース製品に関する深い知識が求められます。
性能改善業務が多い印象。（DBは性能改善系の機能が整っている分、WebやAPの性能改善よりやりやすい）

## サーバエンジニア
ハードウェアから仮想化、OS、ミドルウェア、セキュリティ、クラウド（AWS、Azure、GCPなど）などネットワークエンジニア、データベースエンジニアと比較して幅広い知識が求められる
セキュリティはセキュリティエンジニアの領域として定義されている情報もありましたが、筆者の経験上はセキュリティもサーバエンジニアが担当します。

## ITアーキテクト
サーバ、ネットワーク、データベース、開発（プログラミング）の知識を高いレベルで持つ、インフラエンジニアの上級職種です。
私が一緒に仕事をしたITアーキテクトの方は、開発エンジニア、インフラエンジニア（私含む）が8人くらいで1週間かかって解決できなかったことを1人で2時間で解決されていました。
全てを知っているということの重要性を実感した経験でした。


## プロジェクトマネージャ
技術的なスキルはそこまで求められません。（全くないとつらいですが）
マネジメント系のスキル全般が求められます。
これはIT業界以外の職種でも同様のことが求められると思うので、ここでは深く解説はしません。


# おすすめのキャリアパス
筆者もそうでしたが、特にやりたいことが決まっていない方はコスパが良い（勉強コストが低くて稼げる）職種をおすすめします。
※ネットワークが好き、データベースがどうしても好きといった方は好きなことを突き詰めるのが一番効率良いと思います。
筆者が考えるコスパが良い職種を紹介します。


## 筆者の経歴
2012年 インフラほぼ未経験でサーバエンジニアとして設計・構築案件に参画。
↓
2016年 初のクラウド案件（AWS）でサーバエンジニアとして要件定義、設計案件を担当
↓
その後はひたすらAWS案件（提案～運用まで）、たまにネットワーク、データベース案件。
※2、3年で現場変わっていますが、AWSエンジニア不足は顕著なので、AWS案件に入れないということは現状ないです。

結果として

* サーバエンジニア周りの知識
* クラウドの知識
* ネットワーク、データベースエンジニアの浅い知識


がつきました。
最初のインフラ未経験のころはひたすら目の前の作業をこなしていっただけなのですが、
結果的にけっこうコスパの良いキャリアパスになっているのではと思っています。

ただ最初から設計案件だったのは大変でした。
やはりまずは運用案件から入って、どのようにシステムが運用されるのかを理解してから
設計・構築案件に入れた方が効率は良かったかなと思います。

## コスパが良い職種とは
「良く使われる技術で新しい技術」がコスパが良いです。
理由は多く求められるにも関わらず、できる人が少ないからです。

例えばUnix（Linuxの前身）の歴史は1969年からですが、AWSの歴史は2006年からです。

Linux知識はマニアみたいな絶対かなわないなと思う人が多くいるのですが、AWS知識ですごいと思う人はあまりいません。AWS Japanの方とかは別ですが、プロジェクトの現場にはいません。
これは新しいことを知ろうとする人は少ないからではないのかと推測しています。
なので少しAWSを勉強しているだけで重宝される人材になれたりします。

新しいことを勉強し続けることは大変だとよく聞きますが、実は新しい技術を勉強し続けることが一番コスパが良かったりします。
※今だとAIやIoT分野がおすすめかもしれません。

# まとめ

周りにすごい人がいたときにエンジニアとして向いていないかもと心折れたような感じになることがあったので、
新しい技術なら無理なく勝負できるということを知ってもらえたらと思って書きました。
繰り返しですが、なぜか新しい技術を学ぶ人は少ないです。（今知っている技術を突き詰めて知ろうとする人が多い）

なので比較的新しく、年20%程度の速度で成長し続けているクラウドについて学ぶことはおすすめで、
クラウドの中でも一番利用されているAWSがとっかかりとしては良いのではと考えています。

この記事を見てインフラエンジニアに興味がわいた方は下記の記事もおすすめです。
インフラエンジニア基礎スキルの高め方を纏めています。

https://toumasblog.org/infra-engineer-basic/
【Azure】ぎりぎりにAzure Static Web Appsについて調べてみた

# 1.はじめに
先ほど__Qiitaエンジニアフェスタなるものがあるらしい__と知りました。

https://qiita.com/official-events/8d3820474c1143e88801


告知ページを見てみると…開催期間__「2021/07/01 〜 2021/08/25」__

・
・
・

__「明日までだ！！！！！」__ってなわけで、勢いでお題の__「Static Web Apps」__について書いてみました！


(恥ずかしながら、Static Web AppsがGAしていたことを今回のフェスタで知りました😗😗😗)

# 2. Static Web Appsとは

__Static Web Apps__は、日本語に直すと__「静的Webアプリ」__。
これだけでピンとくる人は来ると思いますが、__静的Webアプリをすごく簡単にデプロイできるサービスです。__

具体的には、__GithubやAzure DevOps PipeLineから、Webアプリを自動的にビルドしてデプロイすることができます！__素晴らしい。
GitHubはソースコードを”リポジトリ”といわれるWEB上の保管庫で共有し、複数人で協同し開発することができます。GitHub上でソースコードをコミット(ファイルの追加や変更の履歴をローカルリポジトリに保存する)し、__プッシュ(リモートリポジトリにソースコードを送信する)したり、pullRequest(変更提案)を受け入れる度に、自動的にアプリがビルドされて、Static Web Appsが更新されます。__

つまり、いつでも最新の状態でアプリが利用できるようになるわけですね。
さらに、Azure Functionsを合わせて利用することで、 __Angular、React、Svelte、Vue などの JavaScript フレームワークとライブラリを使用した 最新の Web アプリケーションの構築__をすることも可能です。便利ですね。

# 3. ストレージアカウントの静的サイトと何が違うの？

と思ったあなた。私も思いました😏
上記で記載した、__GithubやAzure DevOps PipeLineから、Webアプリを自動的にビルドしてデプロイすることができる__点が大きな違いです。
ストレージアカウントでは、静的なWebサイトは設置できるものの、何らかの工夫をしない限り__自動的にデプロイはしてくれません。__(やろうと思えばできます)

__Static Web Apps__では、以下のようにリソース作成時、__ポータル上からGitHubアカウントを連携するだけで簡単に連携することができます。__

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626338/7cfa4952-6bb2-81db-1217-7235bb40e4d8.png)|
|:--|

その他の要素は細かいところはあるかもしれませんが、同じといえば同じですね。
ちゃんと負荷テストして検証すれば、性能的な違いも見えてくるのかもしれません(今回はやりませんが)。

# 4. 価格は？
なんとFreeプランがありまして、__ある程度の機能は無料で利用することができます!__素晴らしい。
趣味でサイトを運営したりする場合、無料でホスティングができるので、かなり便利です。
しかもWEBサーバーの管理等をしなくても、GitHubにアップロードしたソースコードに応じて自動的にデプロイしてくれる。__便利すぎる…__

それぞれの違いの詳細は、以下の表の通りです。

|機能|Free プラン(個人プロジェクトの場合)|Standard プラン(運用アプリの場合)|
|:----|:----|:----|
|Web ホスティング|✔|✔|
|GitHub との統合|✔|✔|
|Azure DevOps 統合|✔|✔|
|グローバルに分散した静的コンテンツ|✔|✔|
|SSL 証明書の無料の自動更新|✔|✔|
|ステージング環境|アプリあたり 3|アプリあたり 10|
|アプリの最大サイズ|アプリあたり 250 MB|アプリあたり 500 MB|
|カスタム ドメイン|アプリあたり 2|アプリあたり 5|
|Azure Functions による API|マネージド|マネージドまたは独自の関数アプリの持ち込み|
|認証プロバイダーの統合|事前構成済み(サービスで定義済み)|カスタム登録|
|サービス レベル アグリーメント (SLA)|なし|99.95％|

引用元:

https://docs.microsoft.com/ja-jp/azure/static-web-apps/plans


# 5. ちょっと残念な点

はい、ここまでハイテンションに紹介してきましたが、ちょっと残念な点もあります。

#### Azure Functionsのリージョンが限られる

Azure Static Web Apps では、Azure Functions を介してサーバーレス API エンドポイントが提供されています。
しかし、今のところStatic Web Appsで利用するAzure Functions とステージング環境のリージョンは、「Central US」「East US 2」「East Asia」「West Europe」「West US2」の5つのリージョンに限られています。
これは__「Azure Functionsは日本リージョンにないとだめだ！」__っていう要件があると、困っちゃいますね🤔
~~個人的にはどこのリージョンであってもあまり関係ないと思いますが。~~

#### ドキュメントに冗長化について記載がない

コンテンツをグローバル ホスティングしていることは記載があるのですが、どのように可用性を担保するのかについてドキュメントに記載がなく、ちょっと不安を感じますね🤔
__「大丈夫。SLA99.95%だよ。」__といわれれば「お、おう」といわざる得ないのですが…この0.05%にこだわる会社さんも多いもので。
ApplicationgatewayやTrafficManagerとかで冗長化構成とれるのかな？とも思いますが、確証なしです。(少なくともTrafficManagerはストレージアカウントでは非推奨ですね)

まぁこの辺のドキュメント類は、時が経つにつれ、整っていくでしょう！😁	

# 6.一押しポイント

 なんといっても、面倒なこと考えず、Githubと自動的に連携できることでしょう！(この記事で3回目の言及)
 DevOps系のPipeLineを構成するのにも準備が必要ですし、ある程度管理費もかかります。__これを一つのサービスで実現できてしまうことが素晴らしい。__


# 7. 終わりに

はい、というわけで今回は滑り込みでStatic Web Appsについて記事を書いてみました。
運用アプリとして使うのは少し疑問が残るものの、個人開発で利用するにはもってこいの便利なサービスです！
興味を持った方は是非利用してみてください！

それでは！

# 参考

https://docs.microsoft.com/ja-jp/azure/static-web-apps/overview
CCNA試験　合格体験記

CCNAに合格したので、合格体験記を書きます。


1.試験結果
--
2021/07/13
1回目　Score　958 (300-1000) Pass

合格ラインは825です。
CCNAは1問6点〜8点となっており、問題数は102問程度でフルスコアは1000です。

これだと計算が合いませんが、
300点がすでにスコアとして持っているからです。


2.勉強期間
--
1ヶ月
総勉強時間 約100時間程度

参考として、私はネットワーク未経験の立場で受験しました。


3.勉強方法
--
・Ping-tをひたすら解く
きちんと理解できているかは別として、Ping-tを周回すれば合格できると思います。
正答率が全体として90〜95%を安定して取れれば合格間違いないかと思います。



・参考書
参考書を一冊購入しました。
ググればたいていなんでも分かる時代ですが
ネットワーク関係で仕事をするなら、
図などでイメージしやすいので一冊は持っておいた方がいいと思います。


4.注意点
--
・解釈が難しい問題文がある
　CCNAはもともと英語問題文を日本語に訳されています。そのせいか、ちょくちょく読み取りづらい言い回しや解釈しにくい問題文があります。
　よくCisco語と表現されています笑
　内容をきちんと理解していても、Cisco語をマスターしないとフルスコアはまず取れないでしょう。
　
　これは冗談ではないので、余裕を持ったスコアで合格できるように勉強しましょう。


5.今後の方針
--
基本情報技術者か応用技術者試験を取ろうか迷っていますが、応用の受付が終わったので基本を取ろうと思います。

基本情報技術者が受かれば、
会社としてはCCNPを推奨しているので、CCNPの1科目をそのあと受験しようと思います。
Qiita Daily Survey memo 2021.08.24

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

# [飛躍的に伸びているBaaS「Supabase」の概要と所感](https://qiita.com/kabochapo/items/6a2a391832825d17af7d)
Kabo(kabochapo) さんの記事
BaaS の Supabase というプロダクトがホットだよという記事。
Supabase の情報が整理されたうえでがっつり書かれており、さっそく使ってみようと思いました。
注目度に書かれている通り伸びがすごい様子…。
別途 how to use の記事も書いてくださっており、合わせて拝見させていただきました。
[Supabaseのデータベースを使うときに役立つ情報](https://qiita.com/kabochapo/items/26b1bb753116a6904664)
今の段階では、そこまで複雑なことはしようと考えていないので、私でも十分に利用できそう、という感想でした。
楽しみ！

# [総当たり攻撃時のパスワード最大解読時間の表(by 上野宣)について分析した](https://qiita.com/ockeghem/items/5a5e73528eb0ee055428)
浩 徳丸(ockeghem) さんの記事。
Twitter でパスワードの総当たり攻撃について、パスワードの強度とかかる時間を表にしたツイートに対する記事になります。
記事にも書かれていますが前提条件がとても大事で、銀行のパスワードやgmailのアカウントハックが簡単にできてしまいそうに見えてしまいます。
パスワードをMD5でハッシュしたハッシュ値が漏洩した場合に、ハッシュ前の値がわかるまでの時間…と言われると、そうだよね、と感じます。

インパクトがありますし、見やすい図なので、前提と一緒に知れてとてもよかったです。
パスワードには記号を混ぜた方が絶対に良いことがわかりますね…。

# [良い質問をして自己成長に繋げるためのあれこれ](https://qiita.com/morry_48/items/86ce93c34e5789f38be3)
morry_48 さんの記事。
何か質問をする際の良い例、悪い例をあるあるな話と一緒に紹介してくださっている記事です。
最近、似たような内容で困っていたのでとても助かります…。
記事にも書かれている通り、質問がうまくいかないと質問をすることへの心理的障害が上がってしまい、コミュニケーションが取れなくなってしまいがちです。
そして、コミュニケーションがうまくいかないと不明点が増えるのは当然で、不明なことが多いのに質問ができず、自己判断で進め、手戻りが発生し、プロジェクトがうまくいかず、空気が悪くなり、さらに質問への心理的障害は上がり…書いていて気持ち悪くなるようなあるあるパターンですね。私も経験があります。
自分がどのタイプの悪質問に対して過敏なのかを知っておくだけでもだいぶよさそうな気がします。
私は4番の「短絡的な答えを求めプロセスに無関心」な質問をされると、質問した相手に無関心になってしまいがちだな…と思いました。
【Ruby on Rails】SNS認証時に起こった「-bash: export: `=': not a valid identifier」のエラー解決をした話


#対象者

* 環境変数を設定している方
* SNS認証を実装している方
　


#状況

SNS認証実装中、
環境変数設定時に下記のようなエラーが

ターミナル

````
-bash: export: `=': not a valid identifier
````

#解決方法

環境変数設定時に

```
export 環境変数="変数名"　○
export 環境変数 = "変数名"　✕
```

上記のように**環境変数と変数名の間に半角スペースを開けるとエラー**になってしまいます。


スペースを無くしたらエラーもなくなりました！


####投稿者コメント
初めて見たエラーだったので記事にしてみました。
学習内容だけでなく、自分が遭遇したエラーに関しても発信していきたいです。


####My Profile
プログラミング学習歴３ヶ月目のアカウントです！
プログラミングスクールで学んだ内容や自分が躓いた箇所等のアウトプットの為に発信しています。
また、プログラミング初学者の方にわかりやすく、簡潔にまとめて情報共有できればと考えています。
もし、投稿した記事の中に誤り等ございましたら、コメント欄でご教授いただけると幸いです。
onCompositionStartを使用する時に、気をつけること~React備忘録~

onCompositionStartとonCompositionEndを使うと、入力が確定しているかどうか判別できる。
(表音文字の自然言語の入力を想定する時以外で使用する場合ってあるのかなあ。ボソ)

contenteditableな要素を使用して、入力文字の制御を行いたかったので、今回onCompositionStartとonCompositionEndを使いました。
というのも、入力文字の制御機能を追加すると、日本語入力が確定される前に入力確定されてしまったので。(例えば、「か」と入力しようとすると「ka」となってしまう)

その時に、エラーが発生してしまって、それについての備忘録です。

最初、このようなコードをかきました。

```react
import React, { useState } from 'react'

function InputDiscrimination() {
    const [isInputting, setIsInputting] = useState(false)

    const handleInput = (event) => {
      if (isInputting) {
        console.log('入力中')
      } else {
        console.log('入力確定')
      }
    }

    return (
      <div
        contentEditable="true"
        data-placeholder="入力してください"
        onInput={handleInput}
        onCompositionStart={setIsInputting(true)}
        onCompositionEnd={setIsInputting(false)}
      />
    )
}

export default InputDiscrimination
```

イケそう！
そう思ってレンダリングすると、、、

```
Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
```

何だと。無限ループしてしまうってどこの行がだ、、、

そこで、onCompositionStartとonCompositionEndをコメントアウトすると、正常にページが読み込めたので、ここの記述が悪いのだろう。
そこで、アロー関数を用いて記述することにしました。

```react
onCompositionStart={() => {setIsInputting(true)}}
onCompositionEnd={() => {setIsInputting(false)}}
```

こうすると、正常に作動しました。
何でだろう。
調べます。

reactの公式の説明に書いてありました。
>一般的に、onClick={this.handleClick} のように () を末尾に付けずに何らかのメソッドを参照する場合、そのメソッドはバインドしておく必要があります。
クラスフィールド構文を使用していない場合、コールバック内でアロー関数を使用することもできます
[イベント処理(React公式)](https://ja.reactjs.org/docs/handling-events.html)

日々精進です。
Arduino UNOで周波数を作てみた。(約1khzぐらい)(PWM利用)


目的
基板作成が落ち着いたから
だいたい1khzを作った


![h_con23.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a0fb5113-d649-af34-4bee-3d0837b1bee8.jpeg)




参考


http://blog.kts.jp.net/arduino-pwm-change-freq/



```c++



#include <avr/io.h>

unsigned int frq = 1000; // 周波数

void setup() {
  
  pinMode(10, OUTPUT);

  // モード指定
  TCCR1A = 0b00100001;
  TCCR1B = 0b00010010;

  // TOP値指定
  OCR1A = (unsigned int)(1000000 / frq);

  // Duty比指定
  OCR1B = (unsigned int)(  (1000000 / frq)>>1  ) ;

}//setup

void loop() {
}//loop



```
m5stackのIPアドレス管理をmDNSに丸投げする

##WiFiマイコンが生えてくる誤家庭事情
1つ２つならいいですが、M5Atomとか誤家庭にn個あるのかわからなくなりますよね?
正直、いい加減にIPアドレスの管理が面倒ですよね?

そう、mDNSならIPアドレスの管理から逃れられます。

ついでにLinuxサーバだったら、avahi-daemonを動かしておくと、サーバのIPアドレスもmDNSで引けます。超快適M5Stackライフを楽しみましょう。

##ソース

<details>
<summary>m5stack_mDNS.ino</summary>
<div>

```m5stack_mDNS.ino
#include <M5Stack.h>
#include <WiFi.h>
#include <ESPmDNS.h>
WiFiClient wifi;

const char* wifi_ssid = "Your WiFi AP";
const char* wifi_password = "pass";
const char* MDNS_NAME="m5stack";

//.local不要
const char* server = "Your Server mDNS";

void setup() {
  M5.begin(true, false, true);
  delay(1000);
  //Serial.begin(115200);
  wifi_connect();
  if(!MDNS.begin(MDNS_NAME)){
    Serial.print("Error MDNS_NAME:");
    Serial.println(MDNS_NAME);
    delay(10000);
    ESP.restart();
  }
    IPAddress server_ip = MDNS.queryHost(server);
    Serial.print("Server:");
    Serial.print(server);
    Serial.print(":"); 
    Serial.println(server_ip);
    wifi_disconnect();
    Serial.println("WiFi Disconnect");
}

void loop() {
  //MDNS.update();
  delay(10000);
}

void wifi_connect(void){
  Serial.print("WiFi Connenting");

  WiFi.begin(wifi_ssid, wifi_password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println("");
  Serial.print("Connected : ");
  Serial.println(WiFi.localIP());

}

void wifi_disconnect(){
  while(WiFi.status() == WL_CONNECTED ){
  WiFi.disconnect();
  delay(2000);
  }
}
```
</div>
</details>

##とはいえ・・
WiFi APの接続上限があるので、ソッチのほうが問題になる人が多い気もします。

##関連
https://qiita.com/DeepSpawn/items/662356c94065ee7f9697
https://qiita.com/hanapage/items/c2df143dbde33e03e674
Pythonチュートリアルをやってみた

もうすぐエンジニアとして働き始めて2年目になります。
最近の業務はフロントエンドが多めですが、バックエンドの守備範囲を広げておこうと思い、Pythonチュートリアルをやってみました。
学習メモです。

## 雑感
- プログラミング初学者向けではない(プログラミング用語が説明もなくサラッと出てくるので)
- 経験者が文法を概観するのにはよいかな
- 細かい説明が多いので、手を動かすのは気になったところだけでいい

## 所要時間
- 説明は結構ちゃんと読んで、手を動かすのは少し: 8h
- 侍さんには60時間と書かれていました

## 気になったところをいくつかあげてみる

### 仮引数のアスタリスク(`*`)

[4.6. 関数を定義する](https://docs.python.org/ja/3/tutorial/controlflow.html#defining-functions)

関数に可変長引数を指定する場合に使うんですね。
1個の場合と2個の場合でまとめられ方が違うようです

```py
# *1個の場合はタプルにまとめられる
def hello(*people):
    for person in people:
      print("hello " + person)

hello("Tom", "Sam", "Nick")

# 2個の場合は辞書型にまとめられる
def fuga(**args):
    for key, value in args.items():
        print('key:' + key + ' / value:' + value)

        # フォーマット済み文字列リテラル(f-string )
        print(f'key: {key} / value: {value}')

fuga(a='aaa', b='bbb', c='ccc')
```

関数の引数として、単独で`/`や`*`があった場合は、引数の受け渡し方に制限がかかるようです。

```py
# /(スラッシュ)はそれより前の引数を位置専用引数として制限する
def self_introduce(first_name, last_name):
    print(f"hello, I'm {first_name} {last_name}.")

self_introduce("naoya", "tanaka")

# *はそれより後の引数をキーワード引数として制限する
def kwd_only_arg(*, arg):
    print(arg)
```

参考: [[python初心者向け]関数の引数のアスタリスク(*)の意味](https://dev.classmethod.jp/articles/what-does-asterisk-mean-at-args/)


### ドキュメンテーション文字列
[4.7.7. ドキュメンテーション文字列](https://docs.python.org/ja/3/tutorial/controlflow.html#documentation-strings)

```py
>>> def my_function():
...     """Do nothing, but document it.
...
...     No, really, it doesn't do anything.
...     """
...     pass
...
>>> print(my_function.__doc__)
Do nothing, but document it.

    No, really, it doesn't do anything.
```

関数定義の中にドキュメントを書くことが標準で推奨・サポートされていることに驚きました。
`関数名.__doc__`で記載したドキュメントにアクセスできるんですね。

### リスト型
[5.1. リスト型についてもう少し](https://docs.python.org/ja/3/tutorial/datastructures.html#more-on-lists)
「リスト型って、JavaScriptでいうところの配列かな？」と思っていたら、別途「array」もあるんですね

- リスト
  - 組み込み型
  - `import`なしで使えるので使い勝手が良い(簡単な処理であれば、基本これ使うらしい)
  - 違うデータ型を格納できる

```py
fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
list = [1, "hello", [1, 2, 3]]
```

- array
  - 標準モジュールである`array`を`import`して使う
  - 同じデータ型の値のみ格納できる
  - 第一引数で型([型コード](https://docs.python.org/ja/3/library/array.html))を指定する
  - 一次元配列のみ

```py
import array
arr_int = array.array('i', [1, 2, 3, 4])
```

他にも、演算に色々便利な`numpy.ndarray`というのがあるらしい

- `numpy.ndarray`
  - Numpyをインストール & importして使う
  - `numpy.array` で `numpy.ndarray`型の配列を作成する
  - 演算に便利な関数・メソッドが色々とあるらしい

```py
import numpy as np
arr_2d = np.array([[1, 2, 3], [3 ,4, 5]])
```

参考: [Pythonのリストと配列とnumpy.ndarrayの違いと使い分け](https://note.nkmk.me/python-list-array-numpy-ndarray/)



### パッケージ
[6.4. パッケージ](https://docs.python.org/ja/3/tutorial/modules.html#packages)

>パッケージ (package) は、Python のモジュール名前空間を "ドット付きモジュール名" を使って構造化する手段です。

ディレクトリ単位でモジュールを構造化して、`モジュール名.サブモジュール名`という形でアクセスできるようになるんですね。

パッケージとしたいディレクトリに内に`__init__.py`を配置することが必要で、パッケージを読み込むと、`__init__.py`に記載された処理が実行されるようです。

詳しくはこちら: [Python の __init__.py とは何なのか](https://qiita.com/msi/items/d91ea3900373ff8b09d7#fn1)



他にも`doctest`や`venv`について振り返りたかったのですが、長くなってしまったのでここまでにしておきますw
(せめてメモとりながら勉強しないと、どこに何が書いてあったか忘れてしまうなぁ...)
App Serviceで設定可能なApplication Settings一覧

# これは何？
普段の業務でAzureのApp Serviceをよく触るのですが、Microsoftが提供しているApplication Settingに設定可能なKeyValueがまとまったドキュメントがなかったので備忘録がてらまとめてみました。随時追記。


# 一覧
| Key | Value | 解説 |
|:-----------|:-----------|:-----------|
|WEBSITES_ENABLE_APP_SERVICE_STORAGE|`true`(または1)| `/home` または `D:¥home` を永続化するための設定。共有ストレージとして利用可。
|WEBSITE_VNET_ROUTE_ALL|`true`(または1)|VNet統合利用する際に送信トラフィックを全てVNet経由にする場合に必要 |
|WEBSITE_LOCAL_CACHE_OPTION | `always`| ローカルキャッシュを有効にする|
|WEBSITE_LOCAL_CACHE_SIZEINMB|`300`(~1000の間)|キャッシュサイズを設定する。上の `WEBSITE_LOCAL_CACHE_OPTION` と合わせて設定する。|
|WEBSITE_ADD_SITENAME_BINDINGS_IN_APPHOST_CONFIG|`true`(または1)|スロットがスワップしたタイミングでワーカープロセスが強制的に再起動される可能性がある。再起動を最小限にする際の設定。WCFアプリでは動作しないので注意。|
|WEBSITES_PORT| `8080`などの任意のport番号|カスタムコンテナーがポート80以外でリッスンする場合に設定|
|WEBSITE_TIME_ZONE|`Tokyo Standard Time` など |デフォルトがUTCなので、変更したい場合は設定が必要。 設定可能なタイムゾーンの種類は[こちら](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-vista/cc749073(v=ws.10)?redirectedfrom=MSDN)。windowsプラットフォームで有効|
| WEBSITE_SWAP_WARMUP_PING_PATH|`/warmup.php` など|ウォームアップリクエストを行うパス。これを、値としてスラッシュで始まるURLパスに設定します。デフォルトは `/`。|
| WEBSITE_SWAP_WARMUP_PING_STATUSES | `200,202` |上記の`WEBSITE_SWAP_WARMUP_PING_PATH`と合わせて利用する。ウォームアップ操作に必要なHTTP応答コード。これをHTTPステータスコードのコンマ区切りリストに設定します。|
| WEBSITES_CONTAINER_START_TIME_LIMIT|`230` など|プラットフォームがコンテナを再起動するまで待機する時間を設定できます。最大値は `1800`。|
| WEBSITE_CONTENTAZUREFILECONNECTIONSTRING |<接続文字列>|Azure Files をファイル システムとしてマウントする|
| WEBSITE_SKIP_CONTENTSHARE_VALIDATION |`1`|Key Vault参照の検証チェックをスキップ|

# リファレンス
[リージョン VNet 統合](https://docs.microsoft.com/ja-jp/azure/app-service/web-sites-integrate-with-vnet#regional-vnet-integration)
[Azure App Service のカスタム コンテナーを構成する](https://docs.microsoft.com/ja-jp/azure/app-service/configure-custom-container?pivots=container-linux#use-persistent-shared-storage)
[Azure App Service のローカル キャッシュの概要](https://docs.microsoft.com/ja-jp/azure/app-service/overview-local-cache#best-practices-for-using-app-service-local-cache)
簡易的なclearlinuxベースのlumen環境

- コンテナ環境で構築するPHPのベースイメージとして定番のphp-fpmがあるが容量の重さは否めない。
- その対応策としてalpineという軽量ベースイメージを用いることも多いが、堅牢性やパフォーマンスの心配もある。
- そこで今回は、堅牢性やパフォーマンスが高いと言われているclearlinuxをベースイメージにして、軽量FWのlaravel製のlumen環境を作成する。

## 環境
- Mac OS X 10.15.6
- Docker version 20.10.8
- Docker Compose version v2.0.0-rc.1

## 手順

### 必要ファイル作成
- 以下のコマンドを入力して、必要なファイルを作成する。

```bash
# 作業フォルダ作成 & 移動
mkdir work; cd $_
# docker file作成
touch Dockerfile docker-compose.yml .dockerignore
# nginxの設定ファイル作成
touch default.conf
```

- 作成後、各ファイルの中身を以下のようにする。

```dockerfile:Dockerfile
FROM clearlinux/php-fpm

RUN swupd bundle-add php-extras unzip \
    && rm -rf /var/lib/swupd/*

COPY --from=composer /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html/src
```

```yaml:docker-compose.yml
version: "3"

services:
  web:
    image: nginx
    ports:
      - 8080:80
    volumes:
      - ./default.conf:/etc/nginx/conf.d/default.conf
      - ./src:/var/www/html/src
    restart: always
    depends_on:
      - php

  php:
    build: .
    volumes:
      - ./src:/var/www/html/src
  # db: 省略
```

```ignore:.dockerignore
.git
Dockerfile
docker-compose.yml
```

```nginx:default.conf
server {
    listen 80;
    root /var/www/html/src/public;

    location / {
        index  index.php index.html;
        try_files $uri $uri/ /index.php;
    }

    location ~ \.php$ {
       fastcgi_pass   php:9000;
       fastcgi_index  index.php;
       fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
       include        fastcgi_params;
    }
}
```

## イメージの起動及びプロジェクトの作成
- 上記のファイル群作成後、下記のコマンドでイメージの起動を行う。

```bash
# イメージの起動
$ docker-compose up -d

# lumenプロジェクトの作成
$ docker-compose exec php composer create-project --prefer-dist laravel/lumen .
```

## 確認
- 起動及びプロジェクト作成後、`localhost:8080`をアクセスして以下のようなバージョン情報が表示されれば完了。

![image](https://user-images.githubusercontent.com/44114228/130448362-2b5be989-8463-4f47-8b19-5a2927baab6b.png)

## まとめ
- 容量は問題ないレベルで軽量化しており、パフォーマンスも安定している。
- また最低限揃っており、[swupd](https://docs.01.org/clearlinux/latest/guides/clear/swupd.html)と合わせることにより記述も短い。
- もう少し様子見をして今後を検討する。


## 参考
- [Dockerhub](https://hub.docker.com/r/clearlinux/php-fpm)
- [lumen](https://lumen.laravel.com/)
- [パッケージリスト](https://clearlinux.org/software)
- [swupdマニュアル](https://docs.01.org/clearlinux/latest/guides/clear/swupd.html)
GAS製のサイトでGoogleDriveの画像が表示されない時に必要だったこと

# 概要
「GASでGoogleDriveにある画像を表示させる方法」については調べれば記事がいくつか出てきます。
ですが、それらの記事に書かれている対応では表示されない環境がいくつかあります。

この記事ではそれらを含め「GASでGoogleDriveにある画像を表示させる方法」をまとめました。

また、この記事で取り上げた対応以外にも、関連資料にて参考になりそうな対応方法がいくつか載っているのでそちらも是非ご覧ください。

# 結論
## 対応について
環境によって対応が変わります。対応の分類は大きく2つに分かれます。

### 1. 従来通りの対応
巷にあふれている資料通りの対応ですので詳細は割愛します。(関連資料をお読みください)
下記を基本フォーマットとしたURLをimgタグのsrc属性にセットすることで表示できます。

```
https://drive.google.com/uc?id={id}
```

### 2. リダイレクト先のURLに置き換える対応

本題はこちらです。
`UrlFetchApp.fetch`メソッドを通してリダイレクト先の画像URLを取得し、それを表示するという対応です。

```javascript
// originUrlは従来の表示用URL
// https://drive.google.com/uc?id={id}
function convertImageUrl(originUrl) {
    const options = {
        followRedirects: false,
        muteHttpExceptions: false
    };
    const response = UrlFetchApp.fetch(originUrl, options);
    const newUrl = response.getHeaders()['Location'];
    return newUrl;
}
```

従来の表示用URLを上記メソッドに通して変換されたURLを、従来通りの対応と同様にimgタグのsrc属性にセットすることで表示できます。

俯瞰して見ると、違いは **リダイレクト先の画像URLに変換する必要があるかないか** と帰着できます。

## 環境による分類

リダイレクト先の画像URLに変換する必要があるかないかはブラウザの環境に依存します。
環境別による変換の必要性を以下にまとめます。

| OS | Chrome | Safari | FireFox | LINE(Mobile) | Slack(Mobile) | Twitter(Mobile) |
|:----:|:----:|:----:|:----:|:----:|:----:|:----:|
|Win64||-||-|-|-|
|OSX|未検証|未検証|未検証|-|-|-|
|Android||-||❌|||
|iPhone|❌|❌|❌|❌|❌|❌|

| 値 | 概要 |
|:-:|:-:|
|(無記入)|変換は不要|
|❌​|変換が必要|
|未検証|未検証な環境|
|-|存在しない環境|

# 関連資料
https://qiita.com/TechnoKuRo/items/622c3dcc2ff3f7e09474#%E8%A7%A3%E6%B1%BA

https://qiita.com/mo256man/items/ae59fef470ac75a3df14

https://teratail.com/questions/258585

# あとがき 対応過程

関連資料にもある通り、ブラウザのアドレスバーに直で画像URLを入力するとリダイレクトされることは把握していた。
しかし、アカウントAでリダイレクトされたURLをアカウントBで開くと403が返ってきて開けなかった。(逆も同様)
このことから、リダイレクト先のURLは表示をリクエストしたアカウントに紐づくものなのだろうと勝手に解釈していた。
そのため、UrlFetchApp.fetchからリダイレクト先のURLを取得する方法の検証をこの時点では行わなかった。

[補足]
実装していたプロダクトのスクリプト実行者はオーナーに割り当てた作りにしていたため、別アカウントからスクリプト実行をリクエストした際、「スクリプト実行しているアカウント(オーナー)」と「リダイレクト先の画像を表示しようとしているアカウント(赤の他人)」は異なるアカウントであるため、上記の検証から403が返ってくるものだと推測していた。

次に、「Download URLにaccess_tokenを付与して表示用URLを生成する方法」(関連資料参考)を試してみたが、結果はこちらも同様に403が返ってきて開けなかった。

どうにか有効なURLを取得できないかと考えHTMLに簡易的なjavascriptを仕込みクライアント側でリダイレクト先の画像URLを取得できないか試みたが、ドメインが違うため当然取得できずに終わった。

少し詰みかけていたため、前提を崩してUrlFetchApp.fetchを通してリダイレクト先のURLを使用することが出来ないかを検証。
結果として期待通り表示することができ、これを実装に落とし込んだところ確認できる全ての環境で正常に表示することができた。

これらの対応が落ち着いた後でteratailの内容を読み解いたため、そのページに記載されている対応方法に関しては未検証のまま。
余裕があれば検証するぐらいの気持ちでいる。
二酸化炭素とかをMicroPythonでMachinistに送る

# 可視化に悩む
センサを買ったけれどもグラフにしたり、アラートを出すにはどこかにデータを送ってためておく必要があった。
なんとなく検索して良さそうなサービスを探していたら、IIJさんの[Machinist](https://machinist.iij.jp/)を見つけた。
Bearerでトークン付けてを送るだけなのでらくらく。

## 用意していたもの
- M5Stack
- M5Stack用環境センサユニット ver.2（ENV II）
- TVOC/eCO2 ガスセンサユニット

## 手順
### つなげる
Grove(I2C)のハブがあるので、買っておく。スイッチサイエンスさんとかにある。
### コードを書く
UIFlowのBlocklyだとごちゃごちゃなコードが生成されるので、シュッとPythonモードにする。
Machinistのドキュメントに従って、dict型にセンサから得たデータをどんどん入れていく。

```python
from m5stack import *
from m5ui import *
from uiflow import *
import wifiCfg
import urequests
import time
import unit
import ujson

setScreenColor(0x000000)
env2_1 = unit.get(unit.ENV2, unit.PORTA)
tvoc_1 = unit.get(unit.TVOC, unit.PORTA)


status = None
url = 'https://gw.machinist.iij.jp/endpoint'
headers={'Content-Type':'application/json',
         'Authorization':'Bearer <your token>'
        }

SSID = '<your own SSID>'
password = '<password of SSID>'

wifiCfg.doConnect(SSID, password)
label0 = M5TextBox(0, 0, 'Init', lcd.FONT_Default, 0xFFFFFF, rotate=0)

while status is 'Succeeded' or status is None:
  try:
    wifiCfg.reconnect()
    data = {'agent':'MySpace',
        'metrics':[
          {'name':'temperature','namespace':'Environment Sensor','data_point':{'value':env2_1.temperature}},
          {'name':'pressure','namespace':'Environment Sensor','data_point':{'value': float(('%.2f'%float(env2_1.pressure / 33.86)))}},
          {'name':'humidity','namespace':'Environment Sensor','data_point':{'value':env2_1.humidity}},
          {'name':'TVOC','namespace':'Environment Sensor','data_point':{'value':tvoc_1.TVOC}},
          {'name':'CO2','namespace':'Environment Sensor','data_point':{'value':tvoc_1.eCO2}},
          {'name':'H2','namespace':'Environment Sensor','data_point':{'value':tvoc_1.H2}},
          {'name':'Ethanol','namespace':'Environment Sensor','data_point':{'value':tvoc_1.Ethanol}}
          ]
        }
    label0.setText('sending...')
    res = urequests.post(
      url,
      json = ujson.dumps(data),
      headers = headers
    )
  finally:
    res = res.json()
    status = res['message']
    label0.setText(str(status))
    lcd.qrcode('https://app.machinist.iij.jp/dashboard', x=0, y=20, width=220, version=6)
  time.sleep(300)
```

とりあえず5分おきにMachinistに送るようにsleepを300秒に設定。
画面になにもないのと寂しいので、dashboardのURLに遷移するQRコードを表示。

## 参考文献
- [PythonでIIJのMachinistにメトリック送信して可視化 - Qiita](https://qiita.com/yasthon/items/1f385515fd2938fffb3d)
- [Machinist公式ドキュメント](https://machinist.iij.jp/getting-started/)
- [ujson – JSON Encoding and Decoding — mPython board 2.0.1 documentation](https://mpython.readthedocs.io/en/master/library/pythonStd/ujson.html)
- [4. Network basics — MicroPython 1.16 documentation](https://docs.micropython.org/en/latest/esp8266/tutorial/network_basics.html)
vue-cliの将来がめっちゃ楽しみ

# 対象者
- vue初学者
- vue楽しい人
- vueもっと勉強したい人

---

# 背景
- vue楽しい
- もっと知りたい
    - vue-cli使うと超便利やと気づき始めた
        - vueコマンドから色々できることがわかり始めた
        - 一層たのしくなる。

---

# どう便利か
- vue add hogeでvue-cliの対象となっているpluginが手軽に入れれる
- main.js や main.ts とかにおすすめ設定まで入れてくれる
- `vue ui` コマンドで gui でも操作できる
    - ただし、2021/8/24現在ではまだベータ版なのでちょこちょこ痒いところに手が届かない
    - なので、将来が楽しみという流れ

---

# vue uiってどんなイメージ？（ダッシュボード）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1841327/1c91483c-3a62-ff66-33b9-96a49721cd23.png)

- 脆弱性チェックやプラグインの更新情報とか教えてくれる
- ワンクリックで更新してくれるようになるぽい（現在はavailable soon）

---

# vue uiってどんなイメージ？（プラグイン）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1841327/7dadda29-f169-6761-0eda-d894810d3d3d.png)

- 現在入ってるプラグインのリストが見れるのはもちろん
- 新規に入れたいプラグインもGUIでそのまま操作できる
    - どれだけ世の中の人がinstallしているかも数字で出してくれてる
    - ただ、将来が楽しみにつながるところが、現在はちゃんとvue-cli的におすすめ設定までしてくれるやつは微妙に少ない
    - vuetifyとかはうまーいこと対応してくれる

---

# vue uiってどんなイメージ？（依存）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1841327/9975f8e0-6604-899c-28d5-713ae7b80291.png)

- pluginの依存リストが見れる
- 必要に応じて、依存プラグインを選んでinstallできる

---

# vue uiってどんなイメージ？（設定）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1841327/2e8fec30-1f8b-bd03-add4-44f48e97665b.png)

- 細かい設定が変更できる
- これは主観ですが、ここはdefaultでも十分なので、マニアックな人向けな印象

---

# vue uiってどんなイメージ？（依存）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1841327/a9cf8454-4da4-2dcd-0333-7d28faf54ee8.png)

- ぽちぽちするだけでサービスを起動させれる
- lintを走らせることもできる
- viteで起動させるのもぽちぽちでOK
    - これはコンパイル爆速ツール
    - 体験するとわかるけど、まじで早い
    - プラグイン画面で導入可能
    - ただ、これは他のプラグインたちがまだ対応しきれてない印象
        - これも今後が楽しみなツールの１つ

---

# 結論
- 現状でのvue-cliで信用しきって良いもの
    - 新規作成時にdefaultで選択肢に出てくるやつ
    - vuetifyとかレベルの大規模プラグイン
- 現状は信用しきるのはまだ早いような気はするけど、うまく起動にのるととんでもなく便利ツールになれるポテンシャルを感じる
- なので、改版は追い続けて損はないし、最先端感を味わい続けられる
- 今後の発展を楽しみにしましょうぜ！
REALITYチャット取得

コメントビューア用。
OAuthが要るようなAPIは使わず、未登録で取得できるコメントを取得。
あくまで執筆時点の情報です。仕様が変わる可能性もあるのであしからず。

---

## 1. 配信IDを確認する
`https://reality.app/viewer/{media_id}`

- 現状はブラウザから見る手段が無さそうなので、URLをツイートして共有するなどが必要です。
- 少なくともこのIDさえわかればOK

## 2. WebSocketでコメントサーバに接続する
`wss://comment.reality.app/?media_id={media_id}`

繋ぐだけで取得できる。
接続直後、それまでのコメントがドバッと送られてくる。
以降は適宜来る。

## メッセージ定義

```js
{
  /**
   * 配信ID
   */
  "media_id": number,
  /**
   * 26桁のランダムな英数字(大文字や記号は今のところなし)なので、ユーザIDっぽい。システムの場合は空文字。
   */
  "vlive_id": string,
  /**
   * ユーザ名
   */
  "nickname": string,
  /**
   * アイコンURL
   * @example "https://reality-public.akamaized.net/viewer/img/user_icon/system_default_64.png"
   */
  "icon_url": string,
  /** 
   * コメント日時
   * @example "2021-08-23T17:30:21Z"
   */
  "created_at": string,
  /**
   * メッセージ種別。
   * - 1: 通常のコメント
   * - 2: いいねしたよ
   * - 6: ギフト(?)
   * - 8: 入室メッセージ
   * - 9: システムメッセージ
   */
  "content_type": number,
  /**
   * メッセージ
   * @example "おはよう"
   * @example "xxxさんがいいねしたよ"
   * @example "640,アイマスク,100,アイマスクをあげました"
   * @example "配信時間が15分を突破したよ！" 
   */
  "content": "配信時間が15分を突破したよ！",
  /**
   * 不明。だいたい0
   */
  "deco": number,
  /**
   * 配信者コメントか否か(未確認)
   */
  "is_self": boolean
}
```

## とりあえずNode.jsで動かす

```js
const ws = require('ws');
const media_id = 配信IDをここに;

const soc = new ws('wss://comment.reality.app/?media_id=' + media_id);

soc.onmessage = (event) => {
  const json = JSON.parse(event.data);
  console.log(json.content);
};
```
[メモ]簡単に自分のコマンドを作る。

# 1.コマンド用のフォルダを作成する

1.E:\command\ を作成する。

# 2.コマンドを書く

1.E:\command\ `<コマンド> `.bat を作成する。
2.E:\command\ `<コマンド> `.bat に以下のコードを書き込む。

```
@ECHO OFF
TITLE Hello
ECHO Hello, World!
```

# 3.環境変数を設定する

1.設定 > システム > 詳細情報 > システムの詳細設定 > 環境変数
2.ユーザー環境変数 > Path > 編集 > 新規 > `E:\command\` を入力する > OK

# 4.テスト

1.コマンドプロンプトを起動する。
2. `<コマンド>` を入力して Enter キーを押す。
![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571953/ea1f7e40-4b3c-55b5-6eca-2f5220dacc95.png)
これで成功した。
Google Play Store をインストールする

# Download APK

* [Google Account Manager](https://m.apkpure.com/jp/google-account-manager/com.google.android.gsf.login)
* [Google Services Framework](https://m.apkpure.com/jp/google-services-framework/com.google.android.gsf)
* [Google Play services](https://m.apkpure.com/jp/google-play-services/com.google.android.gms)
* [Google Play Store](https://m.apkpure.com/jp/google-play-store/com.android.vending)

> by [apkpure](https://m.apkpure.com/)

# Install
APKを下記の順序でインストールする。
方法は ```adb``` ```単体``` どちらも同じ。

1. Google Account Manager
* Google Services Framework
* Google Play services
* Google Play Store
16進数、バイナリ、base64の相互変換をCLIとGo(Golang)でやる


要はこれをやるのだ（相互変換）


```plaintext
hexadecimal
 ↓       ↑
  binary
 ↓       ↑
  base64
```

# CLIでやる

まず 16進数 to base64

```bash
echo "0123456789abcdef" | xxd -r -p | base64 # ASNFZ4mrze8=
```

base64 to 16進数

```bash
echo "ASNFZ4mrze8=" | base64 -d | hexdump # 0000000 01 23 45 67 89 ab cd ef
```

# Golangでやる

```Go
package main

import (
	"encoding/base64"
	"encoding/hex"
	"fmt"
)

func main() {
	hexStr := "0123456789abcdef"

	// hexadecimal string -> byte -> base64 string
	b64Str, _ := hexToBase64(hexStr) // ASNFZ4mrze8=
	fmt.Printf("hex string -> byte -> base64 string: %s\n", b64Str)

	// base64 string -> byte -> hexadecimal string
	hexStr, _ = base64ToHex(b64Str) // 0123456789abcdef
	fmt.Printf("base64 string -> byte -> hex string: %s\n", hexStr)
}

func hexToBase64(in string) (out string, err error) {
	hexStr, err := hex.DecodeString(in)
	out = base64.StdEncoding.EncodeToString(hexStr)
	return
}

func base64ToHex(in string) (out string, err error) {
	b64Str, err := base64.StdEncoding.DecodeString(in)
	out = hex.EncodeToString(b64Str)
	return
}
```

結果

```plaintext
hex string -> byte -> base64 string: ASNFZ4mrze8=
base64 string -> byte -> hex string: 0123456789abcdef
```