OmniAICreator/Qiita-1.07M huggingface dataset:
cloudspeech_demo.pyがAttributeErrorで実行できない【Google AIY Voice Kit】

Google AIY Voice Kitにて、音声認識のデモアプリ（cloudpeech_demo.py）[公式サイト](https://aiyprojects.withgoogle.com/voice/#makers-guide-change-to-the-cloud-speech-api)の手順に沿ってやっているのにAttributeErrorで実行できない！


**■エラー**

~~~
pi@raspberrypi:~/AIY-projects-python/src/examples/voice $ ./cloudspeech_demo.py
Traceback (most recent call last):
  File "./cloudspeech_demo.py", line 22, in <module>
    from aiy.cloudspeech import CloudSpeechClient
  File "/home/pi/AIY-projects-python/src/aiy/cloudspeech.py", line 40, in <module>
    END_OF_SINGLE_UTTERANCE = speech.types.StreamingRecognizeResponse.END_OF_SINGLE_UTTERANCE
AttributeError: module 'google.cloud.speech' has no attribute 'types'
~~~


**■解決方法**
cloudspeech.pyを書き換える

**■解決手順**
①下記コマンドを入力し、cloudspeech.pyが存在するディレクトリまで移動する
**cd ~/AIY-projects-python/src/aiy**
②下記コマンドを入力し、cloudspeech.pyを編集する
**vi cloudspeech.py**
③画像の三箇所を書き換える
(1)

~~~diff
-from google.cloud import speech
+from google.cloud import speech_v1 as speech
~~~
(2)

~~~diff
-END_OF_SINGLE_UTTERANCE = speech.types.StreamingRecognizeResponse.END_OF_SINGLE_UTTERANCE
+END_OF_SINGLE_UTTERANCE = speech.types.StreamingRecognizeResponse.SpeechEventType.END_OF_SINGLE_UTTERANCE
~~~
(3)

~~~diff
-encoding=speech.types.RecognitionConfig.LINEAR16,
+encoding=speech.types.RecognitionConfig.AudioEncoding.LINEAR16,
~~~


[こちら](https://github.com/google/aiyprojects-raspbian/issues/716)を参考にして解決しました(_ _)
TwitterのフォローボタンをPDFに埋め込む方法

#何の記事？
Twitterのフォローボタンは、こちらの公式サイトから作れます。↓
https://publish.twitter.com/#

しかし作成されるのはHTMLタグなので、PDFやスライドにそのまま挿入することはできません。
そこで、フォローへの直リンクを行う方法の出番です。


#フォローボタンの直リンクを作成するには？
下記のxxxxxxxxxxxの部分に、サイトのスクリーンネーム（下の図でいうと黒塗りの部分です）をコピペすれば、それが直リンクになります。

```
https://twitter.com/intent/follow?screen_name=xxxxxxxxxx
```


![aaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620139/afc1897c-1bd0-2687-c79e-967776cc32b1.png)

活用してフォロワーを増やしましょう^^！
AWS IAMユーザー作成手順

## 内容
AWS IAMユーザー作成手順

## 手順

### AWSアカウントの開設

[AWSアカウント開設](https://aws.amazon.com/jp/register-flow/)

### IAMユーザー作成

- コンソールでIAMを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692472/52f0a1fb-89b2-b7fd-599d-a0902fa9c6a4.png)


- 左のメニューから『ユーザー』を選択し、『ユーザーを追加』
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692472/fe2ee665-e5dd-89a9-a077-d873180f262a.png)

- IAMユーザー名を入力、『パスワード - AWSマネジメントコンソールへのアクセス』にチェックし次のステップへ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692472/dfe4c380-b597-9350-f297-70315865c518.png)

- 既存のポリシーを直接アタッチ、AdministratorAccessにチェックし次のステップへ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692472/eb0c03ec-6f83-f899-f125-553ccbd2d8b8.png)

- タグを追加し（任意）次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692472/f6baef70-1418-4fd5-276b-24e2828d5788.png)

- 内容を確認して『ユーザーの作成』
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692472/c5b84a7f-5c43-42d6-a71c-597da7f59a11.png)

- パスワードをコピーし、コンソールへサインイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692472/2e9dd29f-3e3c-158e-3791-c0855b3af8b5.png)

パスワードの変更を求められるので、新しいパスワードに変更したら完了。
[MFAを使用した多要素認証（２段階認証）の設定手順](https://qiita.com/tarian/items/8d4d2f271406fa6a82c1)
FTP接続で「データ接続が確立できません: ECONNREFUSED - サーバーによって接続が拒否されました」の対処法

## 状況
既に確立されているサーバーに普段通りにFTP接続を試みた際にタイトルのエラーが発生。
この直前にはEC2の再起動を行なっている。
FTPサーバー：vsftpd
## 対処
vsftpdの起動を確認。activeを確認。

```
sudo systemctl status vsftpd
```
念の為、ユーザー名、パスワードの確認。こちらも私の場合、問題ないようでした。

```
$ sudo cat /etc/vsftpd/login.txt
```
vsftpdの設定ファイルも調査。こちらに関しても問題なさそう。

```
$ sudo 
cat etc/vsftpd/vsftpd.conf
```
```
pasv_enable=YES
pasv_addr_resolve=YES
pasv_address=[サーバーIPアドレス]
pasv_promiscuous=YES
pasv_min_port=60001
pasv_max_port=60010
use_localtime=YES
force_dot_files=YES
```

FTPクライアントをエラーログをもう1度確認。

```
レスポンス:227 Entering Passive Mode (35,73,17,238,234,97).
コマンド:LIST
エラー:データ接続が確立できません: ECONNREFUSED - サーバーによって接続が拒否されました
```
`Passive Mode`という部分が引っかかって、クライアントツールの転送設定を`デフォルト`から`アクティブ`に設定してみる。
接続成功！！
## まとめ
ずっとサーバー側の原因だと思って色々、いじってたりしたので解決にかなり時間がかかりました。同様の事象で困っている人はぜひこの設定も試してみてください。
for文の二重ループと2次元配列を組み合わせて九九の表を作る

```java
アウトプット用!!

#第2回目は、
for文の二重ループと2次元配列を組み合わせて九九の表を作っていく!

①2次元配列を宣言していきます。
　int [][] kuku = new int[9][9];
　これで縦に9行、横に9列の九九の型が作られる。

②for文をネスト構造で繰り返す。
for(int i = 0; i < 9; i++) { //縦の行を表す。
  for(int j = 0; j < 9; j++); //横の列を表す。
   kuku[i][j] = (i + 1) * (j + 1);

  System.out.println(kuku[i][j]);
 }
  System.out.println();
}
③外側のfor文で縦の行を繰り返しています。
　配列の添字は0からはじまるので、ここでは0段目から処理を繰り返す。
続いては内側のfor文に移って計算結果を各段ごとに記述する処理。ここでは8まで繰り返す。

例えばこんな感じです。
０段目の時は（外側のfor文）
  iが0で、jが0の時は1
  iが0で、jが1の時は　２
  iが０で、jが２の時は　３
これをjが8まで繰り返す。

一旦内側のループを抜け外側のループに戻り、今度は1段目を開始する

1段目の時は（外側のfor文）
  iが１で、jが0の時は2
  iが1で、jが1の時は4
  iが1で、jが2の時は6
これをjが8まで繰り返す。
一旦内側のループを抜け外側のループに戻り、今度は２段目を開始する

　〜繰り返し〜

８段目の時は（外側のfor文）
  iが８で、jが0の時は　9
  iが8で、jが1の時は18
  iが8で、jが2の時は27
これをjが8まで繰り返す。

外側はこれ以上繰り返しできないのでこれで終了。

出力するとこんな感じになると思います。

1	2	3	4	5	6	7	8	9	
2	4	6	8	10	12	14	16	18	
3	6	9	12	15	18	21	24	27	
4	8	12	16	20	24	28	32	36	
5	10	15	20	25	30	35	40	45	
6	12	18	24	30	36	42	48	54	
7	14	21	28	35	42	49	56	63	
8	16	24	32	40	48	56	64	72	
9	18	27	36	45	54	63	72	81	


以上です。

#SIer #java #プログラミング勉強中


```
さくらインターネットでnamazuを使ってメールを検索できるようにする

さくらインターネットのwebメールは本文検索ができないようす（たぶん）。

```shell:ssh
$ which namazu
/usr/local/bin/namazu
```
namazuが使えるようなのでnamazuを使って検索できるようにしてみます。

```text:こんなサーバー例
アカウント名: myaccount
ドメイン: mysite.jp
https://mysite.jp/ => /home/myaccount/www/mysite.jp/

https://mysite.jp/namazu/namazu.cgiで
momoko@mysite.jp（/home/myaccount/MailBox/momoko）
のメールを検索できるようにする。
```

SSHでログインして

```sh:ssh
# インストール先を作る
$ mkdir /home/myaccount/www/mysite.jp/namazu/
$ cd /home/myaccount/www/mysite.jp/namazu/
# namazu.cgiとテンプレートをコピー
$ cp /usr/local/libexec/namazu.cgi ./
$ cp -r /usr/local/share/namazu/template ./
# 検索結果をwebからアクセスできるようエイリアスを作る
$ mkdir MailBox
$ ln -s /home/myaccount/MailBox/momoko ./MailBox/momoko 
# namazuのインデックスを作る
$ mkdir index
$ mknmz -O ./index ./MailBox/ -a --indexing-lang=ja_JP.eucJP  |& nkf -w
# namazu.cgiの設定ファイルをコピーする
$ cp /usr/local/etc/namazu/namazurc-sample ./.namazurc

```
そしてnamazurcを編集します。
必要そうな項目を良い感じに設定します。

```text:.namazurc
Index         /home/myaccount/www/mysite.jp/namazu/index
Template      /home/myaccount/www/mysite.jp/namazu/template/
Replace       /home/myaccount/www/mysite.jp/namazu/  https://mysite.jp/namazu/
Lang          ja
ContentType	"text/html; charset=EUC-JP"
```
以上でnamazu.cgiが動くはず。
https://mysite.jp/namazu/namazu.cgi
にアクセスして検索。
上手く対処できていれば文字化けすることなくメールを検索できる。

定期的にnamazuのインデックスを更新させたいのでローカルにmknmz.shファイルを作ってその中にmknmzを実行するコマンド記述します。（直接crontabにコマンドを記述すると上手く行かない）

```text:mknmz.shの中身
#!/usr/local/bin/bash

/usr/local/bin/mknmz -O /home/myaccount/www/mysite.jp/namazu/index /home/myaccount/www/mysite.jp/namazu/MailBox/momoko/maildir -a --indexing-lang=ja_JP.eucJP  |& /usr/local/bin/nkf -w
```

作成したmknmz.shを/home/myaccount/にアップロードしてmknmz.shに実行権限を与えます。

```sh:ssh
$ cd /home/myaccount/
$ chmod +x mknmz.sh
```

さくらインターネットコントロールパネルもしくはcrontab -eでmknmz.shを実行させます。

```sh:ssh
$ crontab -e
30 3 * * 0,1,2,3,4,5,6  /home/myaccount/mknmz.sh

```
毎日3時30分にmknmzが実行されます。

BASIC認証等をかけて完了です。
Jupyter Labとipywidgets install 備忘録

#概要
ipywidgetsが使われているnotebookがJupyter labで正常に表示されなかったので、conda仮想環境作成時に忘れないように残す。
Colabは予め環境が出来ているので何もしなくとも問題ない。

- 実施期間: 2022年1月
- 環境：Python3.8.12 (miniconda)
- OS: Ubuntu20.04 LTS


##現象
いつもversion指定なしにJupyter labをインストールしている。

```terminal
conda install -c conda-forge jupyterlab
```

2022/1現在、指定しなければver.2.1.0が入る。
ver.2でipywidgetsを表示させるため下記を行った。

```terminal
conda install -c conda-forge ipywidgets
conda install -c conda-forge ipympl
conda install -c conda-forge nodejs
conda install -n base -c conda-forge jupyterlab_widgets
jupyter nbextension enable --py widgetsnbextension
jupyter labextension install @jupyter-widgets/jupyterlab-manager
```

最後のjupyter labextensionコマンドで次のエラーが発生し先に進めなかった。

ValueError: Please install nodejs >=10.0.0 before continuing.

このときのnodejsは6.13.1だった。

##やったこと
これ以上、環境をいじりたくなかったので別の仮想環境を作成しipywidgetsが動作することを確認した。
まっさらの環境で実行したコマンドは下記
Jupyter labは明示的にver.3を指定する。

```terminal
conda install -c conda-forge matplotlib
conda install -c conda-forge jupyterlab=3
conda install -c conda-forge ipywidgets
conda install -c conda-forge ipympl
```

これで正常に動作したコードが下記

```python
uploader = widgets.FileUpload(accept='.csv', description='Select csv file')
display(uploader)

separator = widgets.Dropdown(options=[('Tabulator', '\t'), ('Comma',','), ('Semicolon', ';')],
                             value='\t',
                             description='Separator:',
                             disabled=False)
display(separator)
```
![Screenshot from 2022-01-04 15-45-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205257/dc71cec2-37ea-b2b6-eae9-5b0e867acfa4.png)

正常に動作したのはver.2で実施したbaseに対するこのコマンドが効いている可能性もある。

```terminal
conda install -n base -c conda-forge jupyterlab_widgets
```

また、サイトによってはセルの冒頭に下記を書く必要があると書かれているが、なくてもipymplの描画は可能だった。

```python
%matplotlib widget
```

参考
https://ipywidgets.readthedocs.io/en/stable/user_install.html

以上
FlutetrでrequestPermissionのエラー

### FlutetrでrequestPermissionのエラー

Flutterで通知アプリ仕込んでます。

あと少しだったのですが、このエラーが出てAndroid版のビルドはできるのですが、アプリが起動しない。この時点でiOS版はビルド通っていた。

エラーは

```
E/flutter ( 5307): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: MissingPluginException(No implementation found for method Messaging#requestPermission on channel plugins.flutter.io/firebase_messaging)
E/flutter ( 5307): #0      convertPlatformException (package:firebase_messaging_platform_interface/src/method_channel/utils/exception.dart:13)
E/flutter ( 5307): #1      MethodChannelFirebaseMessaging.requestPermission (package:firebase_messaging_platform_interface/src/method_channel/method_channel_messaging.dart:286)
E/flutter ( 5307): <asynchronous suspension>
E/flutter ( 5307): #2      main (package:（パッケージ名）/main.dart:91)

```

結局、main.dart:91にあるスマホに通知許可を出してもらうところが不要だったようです。

```:main.dart
  await FirebaseMessaging.instance.requestPermission(
    announcement: true,
    carPlay: true,
    criticalAlert: true,
  );
```

を、全部コメントアウトして

```:main.dart
  // await FirebaseMessaging.instance.requestPermission(
  //   announcement: true,
  //   carPlay: true,
  //   criticalAlert: true,
  // );

```

こうしてビルドできました。

AndroidManifest.xmlやらいじったのですがなおらず。

レセイに見るとpermissions.dartでrequestPermissionしてるので、そのあたりが問題かなと。
ほぼメモです。すみません。
bash上で正規表現を使って文字列の後方一致をチェックする

bash上で正規表現を使って文字列の後方一致をチェックする際の備忘メモ

例えばURLが`https://github.com/xxxx/test`である事を確認したい場合でも、
以下のようにすると後方が一致してないのに一致と判定されてしまう。

```bash:test.sh
VALUE_URL="https://github.com/xxxx/test2"
if [[ "$VALUE_URL" =~ "http".*"://github.com/".*"test" ]]; then
    echo "OK"
else
    echo "NG"
fi
```

```
$ bash test.sh
OK
```

正規表現で後方一致をチェックする場合は、`$`を付ける。
（これは正規表現的に終端を意味するようだが、、どの仕様に基づくものか分からなかった。ご存知の方がおられれば教えてほしいです。）

```bash:test.sh
VALUE_URL="https://github.com/xxxx/test2"
if [[ "$VALUE_URL" =~ "http".*"://github.com/".*"test"$ ]]; then
    echo "OK"
else
    echo "NG"
fi
```

```
$ bash test.sh
NG
```

# 参考
[正規表現：前方一致・後方一致・部分一致（〜を含む）の表現](https://www-creators.com/archives/5285)
[【Shell】 シェルで部分一致（前方一致・後方一致）](https://dk521123.hatenablog.com/entry/2020/09/01/000000)
[Linuxで使う正規表現についてまとめました](https://eng-entrance.com/linux-regular-expression)
[BASH](http://surf.ml.seikei.ac.jp/~nakano/JMwww/html/GNU_bash/man1/bash.1.html)
機械学習について学んだことを書き出してみる

#はじめに
この記事は、「なんとなく機械学習に興味がわいた」という安直な理由で、業務に一切使わないけどそのお勉強をし始めたおじさんのお勉強ノートである。
それ以上でも、それ以下でもないのである。

#そもそも機械学習とは
まずはじめに、機械学習という言葉の定義について確認してみようと思う。
ググってみるとこんな説明が出てきた。

>機械学習とは、データを分析する方法の１つで、データから、「機械」（コンピューター）が自動で「学習」し、データの背景にあるルールやパターンを発見する方法。近年では、学習した成果に基づいて「予測・判断」することが重視されるようになった。
[機械学習|用語解説|野村総合研究所(NRI)](https://www.nri.com/jp/knowledge/glossary/lst/ka/machine_learning)

少々言葉を変えて要素分解してみると、以下のようになる。
***
機械学習とは---
1．データ分析手法の一つ
2．過去のデータから「機械」(=コンピューター)が「学習」し、__データ__の__ルール__や__パターン__を発見する方法
3．近年のトレンドとして、「2.」で得られた__ルール__や__パターン__を使用して、「予測・判断」することが重要視されている
***

つまり、コンピューターさんを使って__データ__から__ルール__や__パターン__を導き出して、人間様の__未来予測__や__将来の判断__に役立てるためのデータ分析手法と説明することができる。

#機械学習はどうやってやるの？
じゃあ、そのルールやパターンとやらはどうやって導き出すのか？

大きな分類として以下の3つに分けられるとのこと
・教師あり学習
・教師なし学習
・強化学習

では、それぞれについて詳しく見ていこうと思う。
##教師とは？
　まず、「教師とは何ぞや？」という疑問が湧いてくる。

　教師というのは、いわゆる「答え」のことである。
　この「答え」のことを機械学習では『ラベル』と呼ぶ。

　そうなると次に、「じゃあ『ラベル』って何のこと？」という疑問が湧いてくる。

　これは即ち、「予測対象の実際の結果」である。

　例えば、前の日の気温や気圧などから翌日の天気が知りたいとなった場合、『ラベル』は翌日の天気(晴れ、曇り、雨など)になる。
　気温が知りたいとなれば翌日の気温、気圧が知りたいとなれば翌日の気圧が『ラベル』になる。

　つまり、教師あり学習は『ラベル』が__ある__状態で、教師なし学習は『ラベル』が__無い__状態でコンピューターさんがルールやパターンを見つけ出す手法のことだとわかる。

　以上を踏まえて、教師あり学習と教師なし学習それぞれについてより詳しくみていこう。

##教師あり学習
　上にも書いたように、教師あり学習というのは予測対象である『ラベル』と同じ結果になることを目指してコンピューターさんがルールやパターンを導き出す方法のことである。
　教師あり学習が利用される場面としては、天気の予測やコンビニなどの売上予測、競馬の予想AIなんかもこれにあてはまるのだろう。
　何か一つ「これが知りたい！」というものがある場合、この手法を取ることが有効と思われる。


##教師なし学習
　繰り返しになってしまうが、教師なし学習というのは、予測対象である『ラベル』が無い状態でコンピューターさんがルールやパターンを導き出す方法のことである。
　教師なし学習が使われる場面としては、顧客分析(ネットショッピングのレコメンドなど)、画像認識などである。
　いわゆる、パターン認識などざっくりとグループ分けをしたい場合に使用される。

　以上、教師あり・なし学習についてそれぞれ見てきたが、それぞれ共通していたのは学習するために必要なデータを事前に用意する必要があった点である。
　これは機械学習をするうえでとても大きなハードルなわけだが、データを事前に用意する必要のない学習方法もある。強化学習と呼ばれるものである。

##強化学習
　強化学習とは、システム自身が試行錯誤しながら、精度を高めていく学習法である。
　イメージを掴むにあたり、以下の動画が非常にわかりやすいので、ぜひご覧いただきたい。

　[スーパーマリオブラザーズをAIに学習させてみた](https://youtu.be/Oakaeuz7KNE)

　つまり、マリオが最短でゴールするためにどのような操作をするのが最適であるかを、システム自身が失敗と成功を繰り返しながら、精度を「強化」させていく手法というわけである。
　ロボットの歩行であったり、将棋や囲碁など、限られた操作方法(コマンド)しかない場合などに有効な手法である。

##自動運転について
　これまで学んだ内容を踏まえて、最近話題の自動運転にはどの技術がどのように使用されているのだろうか？
　例えば、以下のようなことが考えられる。
　・渋滞予測などを使用した目的地までのルート探索(教師あり学習)
　・信号、歩行者、道路などの画像認識(教師なし学習)
　・アクセル、ブレーキ、ハンドル操作などの運転技術(強化学習)

　自動運転に使われる機械学習と一言にいっても、それぞれの用途によって使用される技術が違うことがよくわかる。

TO BE CONTINUED...
Raspberry Pi の Chromium でコマンドラインで WebGL を使えるようにする

Raspberry Pi の Chromium で、WebGL のコンテンツが表示されなかったため、表示できるようにするためのメモ。

キオスク端末とかデジタルサイネージ的なものを想定して、GUI ではなくコマンドラインでやりたい。

## 環境

機種: Raspberry Pi 4B （メモリ4GB）

OS:

```
pi@raspberrypi:~ $ uname -a
Linux raspberrypi 5.10.63-v7l+ #1488 SMP Thu Nov 18 16:15:28 GMT 2021 armv7l GNU/Linux
```

Chromium:

```
$ chromium-browser --version
Chromium 95.0.4638.78 Built on Raspbian , running on Raspbian 11
```

## コマンド

以下のように `--gpu --gpu-launcher --in-process-gpu --ignore-gpu-blacklist --ignore-gpu-blocklist` というオプションをつけてコマンドを実行する。

```
chromium-browser \
--gpu \
--gpu-launcher \
--in-process-gpu \
--ignore-gpu-blacklist \
--ignore-gpu-blocklist \
https://get.webgl.org/
```

以下のスクリーンショットのようにキューブが表示されていればオッケー。
backup/restore mysql

https://github.com/aizwellenstan/backup-mysql-www-apache

```sh
# backup-mysql
systemctl stop mysql
mkdir /opt/db-backups
tar cfvz /opt/db-backups/db-$(date +%F).tar.gz /var/lib/mysql/*
systemctl restart mysql
```

```
# restore-mysql
cd
systemctl stop mysql
tar zxvf /opt/db-backups/db-archive.tar.gz -C .
mv /var/lib/mysql /var/lib/mysql-old
mkdir /var/lib/mysql
mv ~/var/lib/mysql/* /var/lib/mysql
chown -R mysql:mysql /var/lib/mysql
systemctl restart mysql
```
Flutterのテキストスタイルを単純化したい

# 概要
この記事はFlutterにおいて、MaterialThemeのTypographyをテキストスタイルに適用させるための実装方法をまとめたものです。

## MaterialThemeのTypographyについて
テキストスタイルを変えたい場合、フォントの種類やらフォントサイズやらフォントウェイトやらを自分で設定するのはかなり面倒だと感じたことのある人は多いはず。そんな時にMaterialThemeを用いればGoogleさんのデザイナーが良さげなテキストスタイルを用意してくれることによってデザインに掛かるコストを下げることやユーザビリティの向上にも役立ちます。
[詳しくは](https://material.io/blog/design-material-theme-type)

## どんな種類があるの？
具体的には`headline1`, `headline2`, `headline3`, `headline4`, `headline5`, `headline6`, `subtitle1`, `subtitle2`, `bodyText1`, `bodyText2`, `caption`, `button`, `overline` の計13個です。headline1はhtmlのh1タグとほぼ同義なので分かりやすいですね。

## 実装方法
```dart
import 'package:flutter/material.dart';

void main() {
  runApp(const TextThemeApp());
}

class TextThemeApp extends StatelessWidget {
  const TextThemeApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Text Theme App',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Text Theme App'),
        ),
        body: Center(
          child: Column(
            children: [
              Text('headline1', style: Theme.of(context).textTheme.headline1),
              Text('headline2', style: Theme.of(context).textTheme.headline2),
              Text('headline3', style: Theme.of(context).textTheme.headline3),
              Text('headline4', style: Theme.of(context).textTheme.headline4),
              Text('headline5', style: Theme.of(context).textTheme.headline5),
              Text('headline6', style: Theme.of(context).textTheme.headline6),
              Text('subtitle1', style: Theme.of(context).textTheme.subtitle1),
              Text('subtitle2', style: Theme.of(context).textTheme.subtitle2),
              Text('bodyText1', style: Theme.of(context).textTheme.bodyText1),
              Text('bodyText2', style: Theme.of(context).textTheme.bodyText2),
              Text('caption', style: Theme.of(context).textTheme.caption),
              Text('button', style: Theme.of(context).textTheme.button),
              Text('overline', style: Theme.of(context).textTheme.overline),
            ],
          ),
        ),
      ),
    );
  }
}
```

### プレビュー
![Screenshot_20220104-143920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479939/7959241c-ce63-a485-0a86-0cd8abeaed2a.jpeg)


### 注意点
このテーマはcontectを引数としているので、必ず `Widget build(BuildContext context)` 配下に適用させないとエラーになります。

## フォントを変えたい
かといってデフォルトのフォントでは気に入らない場合があると思います。その場合は`google_fonts`を[インストール](https://pub.dev/packages/google_fonts/install)します。
フォントの検索は[こちら](https://fonts.google.com/)から、日本語に最適化されたフォントが用意されているので私は[こちら](https://googlefonts.github.io/japanese/)をおすすめします。

### 変更点
```dart
Text(
  'headline1',
  style: GoogleFonts.mPlusRounded1c(  // フォントを変えたい場合はここで指定する
    textStyle: Theme.of(context).textTheme.headline1),
),
```

## おわりに
今回はMaterialThemeを用いたTypographyの実装方法の紹介でした。他にもカラーやアイコンについて、詳しくは[この方の記事](https://qiita.com/agajo/items/4e0fa344dd6c1a36c937)などが参考になりました。
(級数)「【Project Euler】Problem 6: 2乗の和の差」を参考にWolframAlpha でやってみた。(1)

オリジナル

https://qiita.com/masa0599/items/59f96d9ec30608bc0e07


# 1から10までの2乗の和と和の2乗と差を求めよ

https://www.wolframalpha.com/input/?i=%EF%BC%91%E3%81%8B%E3%82%8910%E3%81%BE%E3%81%A7%E3%81%AE2%E4%B9%97%E3%81%AE%E5%92%8C%E3%81%A8%E5%92%8C%E3%81%AE2%E4%B9%97%E3%81%A8%E5%B7%AE%E3%82%92%E6%B1%82%E3%82%81%E3%82%88&lang=ja

??????次のように解釈：2乗の和

https://www.wolframalpha.com/input/?i=%EF%BC%91%E3%81%8B%E3%82%8910%E3%81%BE%E3%81%A7%E3%81%AE2%E4%B9%97%E3%81%AE%E5%92%8C&lang=ja


和
sum_(i=1)^10 i^2 = 385

https://www.wolframalpha.com/input/?i=%EF%BC%91%E3%81%8B%E3%82%8910%E3%81%BE%E3%81%A7%E3%81%AE%E5%92%8C%E3%81%AE2%E4%B9%97&lang=ja


結果
3025

https://www.wolframalpha.com/input/?i=3025-385&lang=ja

結果
2640





https://ja.wolframalpha.com/input/?i=%28sum_%28j%3D1%29%5E10+j%29%5E2-sum_%28j%3D1%29%5E10+j%5E2+

結果
2640

https://ja.wolframalpha.com/input/?i=Sum%5Bi%2C+%7Bi%2C+1%2C+10%7D%5D%5E2-Sum%5Bi%5E2%2C+%7Bi%2C+1%2C+10%7D%5D

結果
2640


# 1から100までの2乗の和と和の2乗と差を求めよ(日本語)

https://www.wolframalpha.com/input/?i=%EF%BC%91%E3%81%8B%E3%82%89100%E3%81%BE%E3%81%A7%E3%81%AE2%E4%B9%97%E3%81%AE%E5%92%8C&lang=ja

和
sum_(i=1)^100 i^2 = 338350

https://www.wolframalpha.com/input/?i=%EF%BC%91%E3%81%8B%E3%82%89100%E3%81%BE%E3%81%A7%E3%81%AE%E5%92%8C%E3%81%AE2%E4%B9%97

結果
25502500

https://www.wolframalpha.com/input/?i=25502500-338350&lang=ja

結果
25164150

# 1から100までの2乗の和と和の2乗と差を求めよ

https://ja.wolframalpha.com/input/?i=%28sum_%28j%3D1%29%5E100+j%29%5E2-sum_%28j%3D1%29%5E100+j%5E2+

結果
25164150

https://ja.wolframalpha.com/input/?i=Sum%5Bi%2C+%7Bi%2C+1%2C+100%7D%5D%5E2-Sum%5Bi%5E2%2C+%7Bi%2C+1%2C+100%7D%5D

結果
25164150


# 参考
有限和＜総和＜wolframalpha

https://ja.wolframalpha.com/examples/mathematics/calculus-and-analysis/sums/

sum

https://hyperpolyglot.org/computer-algebra2#sum


つづく
(級数)「【Project Euler】Problem 6: 2乗の和の差」を参考にsympyでやってみた。(2)

つづき

https://qiita.com/mrrclb48z/items/a97ccb42d6936a6fbfa9

1から10までの2乗の和と和の2乗と差を求めよ
1から100までの2乗の和と和の2乗と差を求めよ

# Pycharmで

```python
from sympy import *
var('i n')
mySum=(summation(i, (i, 1, n)))**2-summation(i**2, (i, 1, n))
print("#        ",         mySum )
print("#expand  ",expand  (mySum))
print("#simplify",simplify(mySum))
print("#",mySum.subs({n:10}))
print("#",mySum.subs({n:100}))
#         -n**3/3 - n**2/2 - n/6 + (n**2/2 + n/2)**2
#expand   n**4/4 + n**3/6 - n**2/4 - n/6
#simplify n*(3*n**3 + 2*n**2 - 3*n - 2)/12
# 2640
# 25164150
```

```python
from sympy import *
var('i n')
mySum=(Sum(i, (i, 1, n)).doit())**2-Sum(i**2, (i, 1, n)).doit()
print("#        ",         mySum )
print("#expand  ",expand  (mySum))
print("#simplify",simplify(mySum))
print("#",mySum.subs({n:10}))
print("#",mySum.subs({n:100}))
#         -n**3/3 - n**2/2 - n/6 + (n**2/2 + n/2)**2
#expand   n**4/4 + n**3/6 - n**2/4 - n/6
#simplify n*(3*n**3 + 2*n**2 - 3*n - 2)/12
# 2640
# 25164150
```

# 参考
summation

https://docs.sympy.org/latest/modules/concrete.html#sympy.concrete.summations.summation

sum

https://hyperpolyglot.org/computer-algebra2#sum
Databricksは2021年のGartner®の2つのマジック・クアドラントでリーダーに指名されました

2021年のGartner®のマジック・クアドラントにおいて、Databricksは以下の2つの領域でリーダーに指名されました。

- Cloud Database Management Systems(クラウドデータベースマネジメントシステム)
- Data Science and Machine Learning Platforms(データサイエンス・機械学習プラットフォーム)

他にも同領域の両方でリーダーに指名されている企業はいらっしゃいますが、クラウドネイティブのベンダーはDatabricksのみとなります。

クラウドデータベースマネジメントシステムとデータサイエンス・機械学習プラットフォームの2つのマジック・クアドラントでリーダーとして指名されたことは、我々が提唱している[データレイクハウス](https://qiita.com/taka_yayoi/items/438f762126f57868aa35)の有効性、認知度の高さが証明された一例とも言えると思います。

これまでも、Databricksはデータサイエンス・機械学習プラットフォームのマジック・クアドラントでは3年連続リーダーとして指名されていますが、クラウドデータベースマネジメントとして指名されるのは初めてのことです。この理由の一つとしては、2021年末に[TCP-DSの世界記録を達成](https://databricks.com/blog/2021/11/02/databricks-sets-official-data-warehousing-performance-record.html)したことが考えられます。

詳細に本件を説明している弊社ブログ記事です。

https://databricks.com/jp/blog/2021/12/16/databricks-named-a-leader-in-2021-gartner-magic-quadrant-for-cloud-database-management-systems.html

上記ブログ記事で紹介されているレイクハウスの事例です。

- [Northwestern Mutual](https://databricks.com/session_na21/northwestern-mutual-journey-transform-bi-space-to-cloud-us)においては、9,300人のフィナンシャルアドバイザーがクライアントとパーソナライズされたやりとりを行えるように、360カスタマービューを提供するために、レガシーなデータウェアハウスからDatabricksのレイクハウスに移行しました。Databricksにおいては、異なるフォーマットの数百万のデータポイントを高速かつ低コスト、ガバナンスが適用された状態で統合するために、300以上のETLジョブが実行されています。開発者、ビジネスユーザーの両方がDatabricks SQL、Power BIを活用してリアルタイムのデータ分析を行なっており、市場投入に要する時間が60%削減されました。
- [マクドナルド](https://youtu.be/lofs42UP2IY)においては、企業全体にMLとBIを提供するマルチクラウドなオープンプラットフォームとしてDatabricksのレイクハウスを活用することで、価値創出に至る時間を短縮しました。マクドナルドは9ヶ月以内の期間において、Databricks SQLを活用する分析ユースケースのロードマップに基づき、メニューのパーソナライゼーションから顧客生涯価値に至るユースケースをサポートする本格運用可能な機械学習モデルを迅速に提供するために、プラットフォームのMLOps機能を活用しました。

以下のリンク先からGartnerのレポートをダウンロードできます。

https://databricks.com/databricks-named-leader-by-gartner

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
Javaを使用してPDFのテキストコンテンツを読み取る方法

##背景
今回の記事では、JavaアプリケーションでPDFファイルのテキストコンテンツを読み取る方法を紹介します。
JavaアプリケーションでPDFドキュメントを読み取るために、サードパーティのPDFコンポーネントを使用できます。この記事で使用されているコンポーネントは、JAVA用の無料のJava PDFコンポーネントであるFree Spire.PDF for JAVAです。

###JARファイルの取得とインポート：
公式ウェブサイトからjarファイルパッケージを**[ダウンロード](https://www.e-iceblue.com/Download/pdf-for-java-free.html)**します。ダウンロードした後、ファイルを解凍し、libフォルダー内のSpire.Pdf.jarファイルをJavaプログラムにインポートします。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/4d496b78-dd7d-27fd-6253-769ddf2dda31.png)

##PDFテキストを読み取るコード一覧
```
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import java.io.*;

public class Extract_Text {

    public static void main(String[] args) {

        //PdfDocumentインスタンスを作成する
        PdfDocument doc = new PdfDocument();

        //PDFファイルをロードする
        doc.loadFromFile("C:\\Users\\Administrator\\Desktop\\test.pdf");

        StringBuilder sb = new StringBuilder();

        PdfPageBase page;

        //PDFページをトラバースしてテキストを取得する
        for (int i = 0; i < doc.getPages().getCount(); i++) {
            page = doc.getPages().get(i);
            sb.append(page.extractText(true));
        }

        FileWriter writer;

        try {
            //テキストファイルにテキストを書き込む
            writer = new FileWriter("ExtractText.txt");
            writer.write(sb.toString());
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        doc.close();
    }
}
```
元のPDFドキュメント：
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/eec8e6e0-7e6e-9d45-69ce-631d34f6e564.png)

エクスポートしたPDFドキュメント：
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/95be64b5-b2b6-f8ea-d37c-a8a6bdd71705.png)

以上はJavaでPDFドキュメントからテキストコンテンツを読み取る方法でした、最後まで読んでいただき誠にありがとうございます。ではまた！
【Rails】コメント機能のparamsにmergeの意味を調べた

コメント機能の実装する際に、comments_controllerにて以下の記述を行なった。

```comments_controller.rb
class CommentsController < ApplicationController

  def create
    comment = current_user.comments.new(comment_params)

    if comment.save
      redirect_to board_path(comment.board),success: t('.success', item: Comment.model_name.human) 
    else
      redirect_to board_path(comment.board),danger: t('.fail', item: Comment.model_name.human)
    end
  end

  def destroy
    comment = current_user.comments.find_by(id: params[:id])

    if comment.destroy
      redirect_to board_path(comment.board)
    end
  end

  private

  def comment_params
    params.require(:comment).permit(:body).merge(board_id: params[:board_id])
  end
end

```

上記内の``merge(board_id: params[:board_id])``がよく分からなかったので、調べてみた。

paramsのらいlsガイドを参照すると
>ルーティングで定義されるその他の値パラメータ (id など) にもアクセスできます。

つまりURLからも中身を持って来れることが分かった。
もう少し細かく見てみる。

###paramsメソッドで、ルーティングで定義された``board_id``を取得する
コメント機能は、User、Boardと関連しているので、user-id と board-id が必須。

なので、フォームから comment[:body]を取得しつつ、board_id がいる。

board_id はルーティングで url 内に下記のように含まれている。

``boards/:board_id/comments``

これは、ルーティングで

```
  resources :boards do
    resources :comments, shallow: true
  end
```

と指定しているからparams で board_id を取得できる。

##参考記事
[paramsメソッドはルーティングパラメータとpostデータを取得できる【25/30 2nd】](https://kentaroutawara.com/20200603params/)
PHPでGoogle Identity Platformにログイン

REST APIでverifyPasswordを呼び出します。
一部設定ファイルの呼び出しはLaravelですが。keyは取得した任意のキーを使います。

レスポンスにはidTokenやrefreshTokenが含まれたJSONが返ってきます。

```
$root_url = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword';
$url = $root_url.'?key='.ENV('GOOGLE_IDENTITY_KEY');
        
//POSTする
$context = array(
     'http' => array(
           'method'  => 'POST',
           'header'  => implode("\r\n", array('Content-Type: application/x-www-form-urlencoded',)),
           'content' => http_build_query($data)
      )
);

try 
{
    //実行と取得
    $json_response = file_get_contents($url, false, stream_context_create($context));
} 
catch (\Throwable $th) 
{
    ~~~
}

//配列に変換
$google_response = json_decode($json_response, true);
```
ハッシュの基礎をおさらい

###rubyの知識を問題を解きながら、何が分かってて何が分かっていないかを洗い出して、復習するシリーズ

という知識を深める用アウトプットをしていくよ

ではさっそく。vol.1

##問題

```ruby
puts hash.keys
puts hash.values
```
というメソッドを実行した時に

```ruby
キー１st
キー２nd
キー３rd
1
2
3
```
とターミナルに表示されるような変数hashを作成するためのコードをシンボルを使って記述する。

```ruby:回答、模範回答
hash = {キー1st:1, キー2nd:2, キー3rd:3}
```

よし、解けた。

でも、ターミナルで動かすまで{ }じゃなく[ ]で囲んでて

```
Traceback (most recent call last):
test.rb:3:in `<main>': undefined method `keys' for [{:キー1st=>1, :キー2nd=>2, :キー3rd=>3}]:Array (NoMethodError)
```
のエラーを出しました。。。
ハッシュと聞くとなぜか反射的に[ ]が思いついちゃうんだよな。まだ染み込みが浅い。

##さて、おさらい

配列の場合は１種類の情報（名前や、○○の成績、など）を複数入れておいて、まとめて取得したり、添字を使って指定した●番目の情報のみを取り出したりできる。

が、２つの情報を紐付けたい（Aさんは１００点、Bさんは８０点、など）のときは、ハッシュを使うとよい。

上の問題では「キー1st」と「１」を紐付けてる。
ので、「Aさんは１００点、Bさんは８０点」をハッシュで作りたいときは

```ruby
score = {A:100, B:80}
```
こんな感じ。

また、ハッシュは**「キー」**と**「バリュー」**で構成されている。
キー：情報の名前（Aさん、Bさん）　　**＊キーには、文字列も数値も使用できる！**
バリュー：情報の値（１００点、８０点）

配列が添字（順番）で管理してたのに対し、ハッシュはキーで管理する。

~~なお、キーの書き方は３種類ある。~~
↑認識誤りでした！
@scivola様からコメントでご指摘いただきました。ありがとうございます！
コメントに@scivola様の記事リンクがございますので、お読みいただいてる皆様も是非。

```ruby
key1 = {"A" => 100}
key2 = {:A => 100}
key3 = {A: 100}
```
~~この`key1,2,3`は全部同じ扱いになる！~~　わけじゃないんですね。

そして、key2,3は**シンボル**という書き方。

シンボルというのは、見た目は文字列だけど、処理のときには数値として扱われるそうで。
見た目が見やすくて、という理由しか覚えてなかったけど、数値として扱われることで処理速度が速くなるという理由もありました。復習復習。
２度美味しいのね、シンボル。

ということで、key3の書き方で問題は解きました！

##まとめ
正直、ハッシュも配列もめちゃめちゃ使用頻度高いと思うんだけど、なんだか苦手意識強くて。
でも、今じっくりめでおさらいできたので、少しは払拭できたかな？

間違ってること、もっとこうしたらいいよというアドバイスなどありましたら、コメントいただけると嬉しいです！

楽しいを軸に続けていきたい。

それでは、また次の投稿で！
Vieurekaサンプルアプリ「ARマーカー認識アプリ」使ってみた

## はじめに
モニターでもらったので、試してみたときの記録です。

「サンプルアプリケーションドキュメント(VieurekaStarterkit_SamppleApp_doc_20210128a.zip)」の「ARマーカー認識アプリ説明書_v1_1.pdf」でやってみた際の補完で、何点かはまりどころがあったのでそれらのメモ。

## リソースの入手

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141402/5a9a25ba-3bb2-2340-6487-c064cabde07e.png)
A4で光沢のあるAとコピー用紙のBがあるが、まず使うのはBのほう

Bに書かれてる情報を元にサイトを開くと以下のにたどり着く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141402/f943e43a-8689-95d1-4128-3c11e89c45e4.png)

赤と青矢印両方ダウンロード
### それぞれの内容物
* 赤 カメラで動かす各種サンプルアプリ
* 青 サンプルアプリのドキュメント

※サンプルを動かす分にはSDKは不要

## アプリのインストール
A（A4で光沢のある紙）に従い「Armarker_recognitionC++_V1_00_vrkc301.ext」をインストールする。

## UI画面を見る
「ARマーカー認識アプリ説明書_v1_1.pdf」記載URLのパラメーターが1カ所間違っています。
クエリーパラメーターの最後から2つめ「s_appDataType」は「0」が正です。（誤りは1）
※フィードバック済み、本家が修正されたらこのセクションは削除予定

```text:カメラアドレス、インストールID置換前URLをコピペ用に補正したもの
http://<camaera_address>/cgi-bin/adam.cgi?methodName=sendDataToAdamApplication&installId=<install_id> &s_appDataType=0&s_appData=
```

## ARマーカーを用意する
OpenCVのArUcoが利用されてるようなのでそのARマーカーを用意する。

1. pythonを入れる
1. opencvを入れる ```pip install opencv-contrib-python```
1. [ARマーカー生成スクリプト][script]をダウンロードする
1. 実行する```gen_dict_6x6_250.py```
1. 印刷する

### 生成スクリプトについて
引数にIDを入れることで任意のIDのものだけを出力することができる。

```shell:ID0だけ
gen_dict_6x6_250.py
```

```shell:ID1だけ
gen_dict_6x6_250.py 1
```


```shell:ID0からID5
gen_dict_6x6_250.py 0 5
```

### 印刷について
Windowsで印刷する際の手軽で、それっぽいサイズに印刷する。

スクリプトで作られたファイルを全部選択して右クリック→印刷
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141402/1c6a4a83-d615-3e0c-569a-11cd10bcdbfc.png)

「写真をフレームに合わせる(F)」を外す（中央下部、赤矢印）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141402/22019e12-1e38-8f9c-a8ab-dec11e3ef451.png)

以下のサイズにするとちょうどいい感じにまとめて印刷できる。

30cmなど超至近距離ならコンタクトシート
1~2mとかだとウォレット


## 雑感
マーカー自体の知識がQRの親戚か？ぐらいの知識しか無い状態からスタートしているので、マーカーどうすればいいか若干手間取った。
そのため、この記事を備忘録としても残そうと思った。

## 参考URL
* https://qiita.com/suo-takefumi/items/30a225cef8ea42366f8e
    * 上記を元にサンプルアプリ用ARマーカー生成スクリプトを作成
* [ARマーカー生成スクリプト][script]
[script]:https://gist.github.com/tac-yacht/228da1a34ad51a9fd0da772237f9c91a
VPSサーバ(ubuntu20.04)上で、ログアウトしてもコマンドをバックグランドで動作し続けておきたい

VPSサーバ(ubuntu20.04)上で、ログアウトしてもコマンドをバックグランドで動作し続けておきたい時の備忘メモ

通常、コマンドをバックグランドで動作させた場合はコマンドの後ろに'&'を付ける

```
bash polling.sh &
```

しかしこれだと、ログアウト時に処理が終了してしまう

```
exit
```

これを回避するには`nohup`コマンドを使えばOK
> [【 nohup 】コマンド――端末を閉じてもログアウトしても処理を続ける](https://atmarkit.itmedia.co.jp/ait/articles/1708/24/news022.html#:~:text=%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%97%E3%81%A6,%E7%B6%9A%E3%81%91%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82)

```
nohup bash polling.sh &
```

これでVPSからログアウトしてもコマンドがバックグランドで動作し続けてくれる


# 参考
[【 nohup 】コマンド――端末を閉じてもログアウトしても処理を続ける](https://atmarkit.itmedia.co.jp/ait/articles/1708/24/news022.html#:~:text=%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%97%E3%81%A6,%E7%B6%9A%E3%81%91%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82)
Lets encryptしているのにhttpsが繋がらない時の対処法（docker環境）

##httpsが繋がらない時の対処法
port443を開けているのに、サーバー上でhttps接続ができずに困ったので、その対応方法をメモ。
出てきたエラーは下記の通り。
>
このサイトにアクセスできません
xxx.co.jp で接続が拒否されました。

今回はサーバー上にDockerで立ててwordpressを実装しているため、docker-compose.ymlに下記を追記して、SSL証明書は対応済み。


###正しい解決法

    #Let's encrypt対応コード
      https-portal:
        image: steveltn/https-portal:1
        depends_on:
          - wordpress
        links:
          - wordpress
        ports:
          - 80:80
          - 443:443
        restart: always
        volumes:
          - ./ssl_certs:/var/lib/https-portal
        environment:
          DOMAINS: ‘xxxx.co.jp -> http://wordpress:80’
          STAGE: production
          CLIENT_MAX_BODY_SIZE: 64M

ここでの注意点は、wordpressのところを、その時のnginxやapacheがあるwebサーバーを指定すること。今回はwordpressの中でapache入れているのでこのような表記。
さらに、ymlの上部に書いてあるwordpress(webサーバー)のportはコメントアウトで消す。


###今回のケースにおける対応
本来は上記対応でhttps対応(Lets encrypt)が可能なはずだが、今回はおそらくDNS設定のところがうまく出来ておらずymlの内容が読み込まれないため、対処に苦労した。

・`/etc/hosts/`　にてルートを自分で決めてしまっていた。
・　クライアントの方で、DNSレコード設定で、使っているネームサーバーが異なっていた


おそらく二つ目が理由になって、DNSとIPが繋がらず、docker-compose.ymlに記載したコードが反映していなかったものと思われる。

*なお、DNSとIPはターミナルでnslookup xxx.co.jp(DNS)で紐づいているIPが確認できる。
今回はこれで、ネームサーバーで取得したDNSとIPに切り替わらなかった。*
Github Wikiへのコントリビューションを正しく評価するためにオープンリポジトリ管理を目指す

## 結論
できました。

1. Wikiをクローン
1. 新しいリポジトリを生成
  1. ない場合は作る
1. 新しいリポジトリにwikiリポジトリをpush

## 実験

https://github.com/shimajima-eiji/__Github-Operation

のWikiリポジトリを

https://github.com/shimajima-eiji/__Github-Operation_wiki

として移行したところ、過去の更新などを生きた状態でコントリビューションとして扱うことに成功しました。
これで、**ドキュメンテーションもきちんとした開発貢献だと証明できそうです。**

ただし、バージョン管理という観点ではいらない作業ですし、二重管理になるのでもれ抜けが発生します（後述で対策）

## 手引き
```
git clone (wiki.git)
git push --mirror 新規リポジトリ
```

これだけです。

## 発展：リアルタイム性が必要な場合
cronなりでwikiをcloneしてwikiを格納するリポジトリにpushすればいいです。
運用上正規のWikiを編集する事はあってもリポジトリを編集する事はないはずなので理論上漏れ抜けはなくせます。

## 応用？:プライベートリポジトリでWikiを使いたい
とりあえず方法だけ書いておきますが、運用できるとは思えません。
短期的には良いかもしれませんが、保守まで考えると現実的ではありません。

ｆWiki用のリポジトリを公開で作って記載内容をまとめ、リポジトリ自体はWikiのバックアップとしてしまう手が有効です。
もちろん、公開ができない情報を扱うのがほとんどだと思うので、非公開リポジトリにDocsなどのディレクトリを置き、キーワードを置く手もあります。

### 例
``` OpenWiki/Home.md
〜〜　情報 〜〜
# ページ情報
概要など公開できる情報。

# 接続情報
ユーザー: (USER)
パスワード: (PASSWORD)

# ページリンク
- (URL1)
- (URL2)
〜〜　情報 〜〜
```

``` ClosedRepository/Docs/Home.md
秘匿したい具体的な情報。

- 接続情報
  - ユーザー: (正しい情報)
  - パスワード: (正しい情報)
- ページリンク
  - URL1: (正しい情報)
  - URL2: (正しい情報)
```

### 個人開発の場合
そもそもWiki機能がいらないと思います。
が、それも本末転倒なので運用を考えてみます。

先ほどのClosedRepository/Docs以下にREADME.mdだけを置けば、ページを降りるだけで内容が表示されます。
ただし、Wiki機能で重宝するサイドバーやフッターが使えないためページ遷移がやりにくいです。
そのため、どうしてもWiki機能を使いたい場合は、OpenWikiをただのリンク集とし、内容はClosedRepository/Docs以下に格納する手もあります。

どちらにしても、使いにくいので運用が続くとは思えません。

## 疑問:Github Wikiは運用足り得るか？
正直、QiitaTeamやesaなどナレッジ管理ツールを使った方がいいと思います。
ナレッジ管理ツールにも長短ありますので、どれが一概に良いか言えませんが、Github WikiやRedMine等のプロジェクト管理ツールでの運用の問題点を洗い出すと、解決ツールの策定がしやすくなると思います。[^1]
[^1]: 【ナレッジベースの検討】予算の都合などから、一つのツールで全部やろうとしてしまいたくなりますが、運用コストを考えるとそれぞれの専門ツールを使って責任を分けた方が良い事があります。ツール間連携が必要な場合は別途検討が必要です。

そういった意味で、スモールスタートでGithub Wikiを使っておくのはアリだと思います。

---

### 注釈
【IQ Bot】取得した文字列が特定の選択肢を含んでいたら、その選択肢を答えとするカスタムロジック

#はじめに

IQ Bot で、「取得した文字列の中に特定の選択肢が含まれていたら、その選択肢を答えとする」カスタムロジックの例を紹介します。

#カスタムロジック例

```python:文字列が特定の選択肢を含んでいたら、それを答えとする

#このタプルの中身を、実際の選択肢に置き換える
options = ("EXW","FCA","CPT","CIP","DAP","DPU","DDP","FAS","FOB","CFR","CIF")

for i in options:
    if i in field_value:
        field_value = i
        break

# field_valueのもとの値が「FOB Jakarta」なら「FOB」、「CIF Tokyo」なら「CIF」を答えとしてfield_valueに代入します
        
```

#補足

上記のカスタムロジックは、貿易帳票の取引条件欄を想定したロジックの内容です。
`options` の中に入っている`EXW`や`FOB`といった選択肢は、いずれも国際物流における取引条件の種類です。
（参考：https://lab.pasona.co.jp/trade/word/104/）

貿易帳票の取引条件欄には、「FOB」「CIF」といった取引条件が単純に書かれてくる場合もあります。
そうであれば、取引条件の部分だけを取得対象になるようにマッピングできるので、上記のロジックは不要です。

ですが実務上では多くの場合、「FOB Jakarta」や「CIF Tokyo」など、「取引条件 ＋ 港の名前 ＋ α」という文章形式の情報の中に、取引条件が書かれています。

この場合は、マッピングだけで取引条件の記載位置を指定するのが難しくなります。

このような帳票から取引条件を抽出する方法としては、以下が考えられます。

1. マッピングでは、取引条件欄の全体を囲っておく
1. 取引条件欄全体の記載内容から、目的である取引条件の選択肢を抽出するロジックとして、上記のようなカスタムロジックをかける

この記事に示したロジックは、上記の2.の具体例となります。

#最後に

IQ Bot に関する情報をもっと詳しく知りたい方は、ぜひ以下のページをブックマークしておいてください。

https://qiita.com/IQ_Bocchi/items/36dbe9adc4b8e70437bf

https://qiita.com/IQ_Bocchi/items/1d8e7c77ad47e838476c
毎月の最後の平日を求めるExcel関数

# きっかけ
もう何年も前の話です。
毎月末に提出する書類（エクセルファイル）の作成日記入欄に、下記の数式が書かれていました。
`EOMONTH(B3,0)-MAX(WEEKDAY(EOMONTH(B3,0),2)-5,0)`
当時の自分はExcelの関数についてほとんど知らなかったので、この数式が何を計算しているのか全く分かりませんでした。
そのとき、自分なりに調べて理解したことをまとめて記事にします。

# 3つの関数の意味
ひとまず、この数式に登場する3つの関数について調べました。

## EOMONTH(開始日,月数)
開始日から数えて、月数分だけ前または後の月の最終日を求める関数です。
素直に日付を答えてくれるわけではなく、シリアル値という数値で返答してきます（Windows版Excelの場合は、1900年1月1日を1とし、そこに経過日数を足して、その日付のシリアル値としているそうです）。
上記の数式の場合、`EOMONTH(B3,0)`とのことなので、B3セルに記入された日付から0ヶ月後（つまりB3セルの日付と同じ月）の月末の日付が算出されます。
ちなみに、この書類ではB3セルにその月の月初日が記入されていました。

## WEEKDAY(日付,週の基準)
指定した日付の曜日を求める関数です。
これも素直に月火水木金土日で答えてくれるわけではなく、「週の基準」で指定した数値によって答え方が変わります。
上記の数式の場合、`WEEKDAY(EOMONTH(B3,0),2)`とのことなので、「その月の最終日が何曜日なのかを、週の基準2に従って算出する」という内容になっています。
「週の基準2」は、「月曜日を1、火曜日を2、…、日曜日を7」と置き換える法則です。

## MAX(数値1,数値2,…)
括弧の中で指定した数値のうち、最も大きい数値を求める関数です。
上記の数式の場合、`MAX(WEEKDAY(EOMONTH(B3,0),2)-5,0)`とのことなので、「`WEEKDAY(EOMONTH(B3,0),2)-5`と0を比較して、大きい方の数値を算出する」という内容になっています。
`WEEKDAY(EOMONTH(B3,0),2)-5`は、週の基準2に従って求めた曜日の数値から5を引いていますので、「月曜日が-4、火曜日が-3、…、日曜日が2」となります。
それらと0を比べて大きい方の数値を答えるのが`MAX(WEEKDAY(EOMONTH(B3,0),2)-5,0)`ですので、「月曜日から金曜日は0、土曜日は1、日曜日は2」と置き換えられています。

# 数式全体の意味
上記を踏まえて、最初の数式の全体を見てみます。
`EOMONTH(B3,0)-MAX(WEEKDAY(EOMONTH(B3,0),2)-5,0)`
数式の前半（`EOMONTH(B3,0)`）は、単純にその月の最終日を求めています。
後半（`MAX(WEEKDAY(EOMONTH(B3,0),2)-5,0)`）は、その月の最終日が平日なら0を、土曜日なら1を、日曜日なら2を算出します。
数式全体としては、その月の最終日から0（平日の場合）または1（土曜日の場合）または2（日曜日の場合）を引いているので、その月の最後の平日を求めていることになります。

こうして、この数式がその月の最後の平日を算出する関数であることを、当時の自分はやっとのことで突き止めたのでした。
ただし、この数式は祝日等を考慮していませんので、そこは注意が必要です。

# 最後に
最初に書いた通り、この数式は月末提出書類の作成日記入欄に書かれていました。
であれば、「これはその月の最終出勤日が出てくる数式なのかな？」などと想像できていれば、もっと早く疑問を解決できていたかもしれません。
その点も含めて、当時は知識や経験が足りませんでした。
反省し、精進します。

以上、ご覧いただきありがとうございました。
自分のプロフィール

##■プロフィール

札幌在住 27 歳のクラウドエンジニアです。
自分なりにこれまでの経歴などをまとめてみました。

まだ 20 代なのでフリーランスとして活躍してみたいという希望があり
今後のキャリアを考える機会になればと思って、自己満足のために残しておきます。
(現在正社員ですが、案件があれば参画したいです。札幌/関東圏 であれば是非お話を聞かせてください。)


##■これまでキャリア

2017年 3月 大学卒業
2017年 4月 IT商社へ新卒入社
            - フィールドエンジニア
            - インフラエンジニア
            - テクニカルサポートエンジニア
2020年 9月 SES企業へ入社
2021年 9月 クラウドエンジニアとして現職へ

2度の転職を経験しています。


#####＜1社目(IT商社)＞
新卒入社した1社目では、各職種を1年間ずつ経験を積むことができました。
色々なことにチャレンジできる環境にあったため、以下のような経験をさせていただきました。

・担当製品の要件定義 ～ 運用保守までを経験
・社内 DX 改革の一環で社内評価プロジェクトのリーダーを務める
・担当製品の技術講師として100人規模のセミナー登壇

商社と聞くと、営業のイメージが強いかもしれませんが、エンジニアとしての採用でした。
ただ、営業さんと同行して、新機能や新製品を提案する機会は多かったです。

ここではあまり詳しく書けませんが、会社に対する信用がなくなることがあり、退職を決意。


#####＜2社目(SES企業)＞
勤めたのはちょうど1年で3つのプロジェクトに参画しました。

・車載システムのテスト業務(2か月 契約期間満了により退場)
   - 主にシステムテスト、稀に単体テスト、結合テスト
   - 実機を使用した画面遷移テストや機能テスト

・企業インフラ構築業務(6か月 契約期間満了により退場)
   - 主に Azure を使用したインフラ構築(稀にオンプレ)
   - コロナウイルスの蔓延ということもあり、IT以外の業界のお客様環境にて VPN 構築を多く対応
   
・ServiceNowを使用した社内DX改革の上流工程(4か月 契約期間満了により退場)
   - 要件定義、設定などの上流工程を担当
   - インフラ業務経験から、テスト端末周りのネットワーク構築
   - テスト用Dockerコンテナの構築と運用方法の確立

2つ目の現場と3つ目の現場では継続のお話もいただきましたが、当時は色々な現場で経験を積みたいと考えていたため、断っておりました。


#####＜3社目(メーカー企業)＞
現職です。今は社内インフラ周りの整備と既存顧客の Azure 製品に関する運用保守をしています。
自身が対応しているのは以下製品あたりです。

・Azure VM
・Azure ネットワーク全般
・Microsoft Defender for Endpoint
・Microsoft Defender for Cloud Apps
・Microsoft Defender for Identity(勉強中)
・(たまに Office 365 も)

主に仮想環境におけるネットワークとセキュリティ周り全般といったところです。
管理目的で Microsoft Intune も触りますが、そこまで詳しいわけではないです。


##■所持スキル

・基本情報技術者
・応用情報技術者
・JP1 認定プロフェッショナル
    - 統合管理
    - パフォーマンス管理
    - ジョブ管理
    - ネットワーク管理
・JP1 認定コンサルタント
    - 統合管理
    - ジョブ管理
・AZ-900: Microsoft Azure Fundamentals
・AZ-104: Microsoft Azure Administrator
・AZ-500: Microsoft Azure Security Technologies

Azure はおよそ 2 年弱経験しています。
Azure を主に使用しているため、構成管理ツール(IaCツール)は Azure Resource Manager を使用しています。
そのうち AWS とかも触る機会があれば、Terraform を勉強しようと思っています。

JP1 製品は 3 年と半年経験しています。
上記 JP1 の資格に該当する JP1 製品については、メーカーと共同業務していたこともあり、メーカーと同等のレベルで詳しい自信があります。


##■今後について

できれば今後も Azure に触れ、色々なことにチャレンジしていきたいと思っています。
ただ、現職ではずるずると運用保守に流れていきそうな雰囲気があります。
どちらかと言うと、運用保守よりは、要件定義～設計・構築が好きなので、このあたりに身を投じていけたらなと思っています。

Qiita では、知識の共有、自身の備忘として1か月に2記事を目標に記事作成に取り組んでいこうと思います。
主に Azure がメインとなりますが、ぜひ見ていただけると嬉しいです。
ゼロ埋めリストの作成

追記
より良い例をご教授いただきましたので、コメント欄をご覧ください。

```python3
>>> a = [i.zfill(2) for i in list(map(str, range(10)))]
>>> a
['00', '01', '02', '03', '04', '05', '06', '07', '08', '09']
```

`list(map(str, range(10)))`は数列を文字列として
リスト化
(リスト化は不要)．  
`[i.zfill(2) for i in list(...)]`は中身を一つずつ取り出してゼロ埋めし，
リスト化
．
E資格合格に向けて　深層学習day4 （軽量化・高速化技術）

#高速化
モデルを出来るだけ早く構築する技術

【分散深層学習】
　深層学習は多くのデータを使用したり、パラメータ調整のために多くの時間を使用するため、高速な計算が求められる。毎年10倍の早さでモデルが複雑になっており、計算量も10倍になっている。一方コンピューターは18ヶ月で2倍に性能ＵＰ。これではモデルの複雑化にコンピューターの性能が追いつかない！！
　複数の計算資源（ワーカー）を使用し、並列的にニューラルネットワークを構築することで、効率の良い学習を行いたい。
　
①データ並列化
　・親モデルを各ワーカーに子モデルとしてコピー
　・データを分割し、各ワーカーごとに計算させる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313001/70a7c632-f72b-c5bf-def4-0fbd68f77e26.png)

　データ並列化（同期型）
　各ワーカーが計算が終わるのを待つ必要があるため、自身でコントロール可能なコンピューターを複数準備できるならこちらの方がよい。安定的に学習が進む。現在は、同期型の方が精度が良いことが多いので、主流となっている。
　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313001/5e69b23f-580e-dcf5-d20b-480a791c00f9.png)

　データ並列化（非同期型）
　各ワーカーはお互いの計算を待たず、各子モデル毎に更新される。そのため、各自が持っているＰＣやスマホを使うなど、自身でコントロールが難しいコンピュータを使用する場合に適している。ただし、学習は不安定になりやすい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313001/2b66941c-df22-8532-9df6-bb31a620bfae.png)

②モデル並列
　親モデルを各ワーカーに分割し、それぞれのモデルを学習させる。全てのデータで学習が終わった後で、一つのモデルに復元。モデルが大きい時はモデル並列化を、データが大きい時はデータ並列化をすると良い。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313001/9721a051-3004-ea3e-9b0f-c13a7dfbb951.png)

③GPU
 CPUと比べ、「低性能なコアが多数」「簡単な並列処理が得意」。ニューラルネットワークの学習は単純な行列演算が多いので、高速化が可能。

#軽量化
スマホなどの性能でもモデルを動かせるようにするために、モデルを軽量化する技術。
モデルの精度を維持しつつパラメータや演算回数を低減する手法の総称。

①量子化（Quantization）
簡単にできるため、最も良く使う方法。
ネットワークが大きくなると大量のパラメータが必要になり、学習や推論に多くのメモリと演算処理が必要。通常のパラメータの64bit浮動小数点を32bitなど下位の精度に落とすことでメモリと演算処理の削減を行う。「計算の高速化」「省メモリ化」という利点があるが、一方で「精度の低下」という欠点もある。実際の問題では倍精度（64bit）を単精度（32bit）にしてもほぼ精度はかわらない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313001/1471dbf0-55bc-d19d-2281-2e55642cb141.png)

【実装例】量子化のライブラリ

```
import torch.quantization
print(torch.quantization.default_qconfig)
```

QConfig(activation=functools.partial(<class 'torch.quantization.observer.MinMaxObserver'>, reduce_range=True), weight=functools.partial(<class 'torch.quantization.observer.MinMaxObserver'>, dtype=torch.qint8, qscheme=torch.per_tensor_symmetric))

②蒸留（Distillation）
精度の高いモデルはニューロンの規模が大きなモデルになっている。そのため、推論に多くのメモリと演算処理が必要。そこで、大きなモデルの知識を使い、軽量なモデルの作成を行う。

蒸留は「教師モデル」と「生徒モデル」の2つで構成される。
教師モデル：予測精度の高い、複雑なモデルやアンサンブルされたモデル
生徒モデル：教師モデルをもとに作られる軽量なモデル

教師モデルの重みを固定し生徒モデルの重みを更新していく
誤差は教師モデルと生徒モデルのそれぞれの誤差を使い重みを更新していく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313001/fced3bee-e57b-af76-ae36-ace30fd2f0a1.png)

③プル－ニング（Pruning）
ネットワークが大きくなると大量のパラメータのすべてのニューロンの計算が精度に寄与しているわけではない。モデルの精度に寄与が少ないニューロンを削減することでモデルの軽量化、高速化が見込まれる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2313001/0b1fe47e-7b06-d937-a90f-244728bf500b.png)
序章：なぜ人は夢を持たなければならないのか？

![24.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2466971/e5216d09-15a6-2739-f3ef-cdb4336d9358.jpeg)

人には未来があり、戦うべき夢がある。 夢のない人は、ネガティブでやり過ごす危険性もある。 夢を設定し、努力を続ければ、いつか本当に実現する。

夢とは

人はいろいろなことを夢見るものです。 大きな美しい家を建てる夢、ある分野の第一人者になる夢、将来世界を旅する夢、人類の未来の低空飛行計画などなど、たくさんありますね。

世の中には、あなたの想像力の余地が十分にあるのです。 かつて、「世の中のすべての生命は人間が考えたものだ」と言った人がいましたが、これは本当です。

実現するための方法

誰もが夢を持っていて、それを実現することが求められている。 夢はあくまで出発点であり、実現するためには行動が必要です。

自分の得意なことを発見する

"Born to be talented"、自分の得意なことを発見するために、自分が好きで、こだわりを持ち、疲れを感じないような追求をしているかどうか。

実装を計画する

どこから手をつけて、どのように実行のステップを計画するかを考えるのです。 まず落ち着くこと、生き残ること、生きることが第一の課題であることを確認するために必要なことを行う。 もし、人が最も基本的な生存を確保することさえできないなら、すべての夢は空しい。

そして、夢を実現するために必要なことをする。 仕事でお金や経験、人脈、資源を蓄積することで、やりたいことができ、夢を実現することができるのです。

実行の重視

各ステップがしっかりしていないと、最初のステップをやらずに2番目のステップをやり始めても、計画が台無しになってしまいます。 また、一度にたくさんやろうと欲張ることもできないので、忙しさが続かず、仕事の滞留が生じやすく、疲弊してしまうのです。

本物であること

すべて本当のことを行うには、偽を再生しないでください、ちょうどしない無駄だと思います。 誰にでも誠意をもって接することで、一緒に仕事をしよう、夢をかなえようと思ってもらえる。

何事にも真剣に取り組み、表面的にならず、手っ取り早く儲けようとせず、非倫理的にならず、他人の利益にこだわらないこと。 将来の夢があるのなら、それを実行に移し、根気よく続けていけば、必ず夢は叶うはずです。
【Reactを本番環境で動かすことへの不安を和らげたい】

最近Reactで本番環境用にBuildをする機会があったのですが、これまでbuildせず開発用サーバーで試したことしかなかった私からすると、いろいろ考慮しなければいけないポイントが多くて不安になることが多くありました。

そんな私がもし開発前に知っていれば楽だっただろうな。と思うReact開発のポイントをまとめてみたいと思います。

## １，本番環境ではBuildしよう。

reactでBuildする。というのは簡潔に言うと **「js, cssファイルを一つにまとめること」** である。Reactにはいくつかこのような処理をおこなってくれるツールがあるらしいが、今回は`create react app`により作成したプロジェクトなので、webpackがデフォルトのビルドツールらしい。

最初のころはBuildをする必要があることを知らなかったのと、 「よくわからなくて怖い」となっていたので **「本番環境ではBuildする必要があるけど、怖くないよ。ただファイルをまとめて軽くするだけだよ」** ってことを以前の自分に教えてあげたい。

## ２，環境ごとにBuildコマンドは使い分けよう

build（jsファイルやcssファイルをまとめて軽量化）するときに、dotenv-cliをプロジェクトにinstallしておけば、どの環境変数ファイルを使うのかをわけることができる。

buildコマンドはデフォルトでは一つしかないが、package.jsonを編集すればstaging環境用Buildとproduction環境用Buildを分けることができる。

最終的にはこのような構成に落ち着いた。

当初の自分には、 **「buildコマンドは使い分けると便利だからどんどんcustomしていけばいい」** とでも言ってあげたい。

```yaml
..... package.json
"scripts": {
    "start": "react-scripts start",
    "build-staging": "dotenv -e .env.staging react-scripts build",
    "build-production": "dotenv -e .env.production react-scripts build",
    "test": "dotenv -e .env.test react-scripts test",
    "eject": "react-scripts eject"
  },
......
```

## ３，エラーページの設置

本番環境レベルの運用を意識しないとこういったエラー対応ページを用意しようと思わないもので、 **「エラー時のページってどうすればいいんだろ」** と思っていた自分には **「Reactだとめっちゃかんたんに用意できるよ」** と言って不安を和らげてあげたい。

500や404ページは、シンプルにComponentで用意すればいい。それを`<ErrorBoundary/>`で挟むだけでいい。

`<ErrorBoundary/>`Componentを使用するとエラー時に表示したいページを制御することができる。一番単純に使うとすると、APP.jsの<App/>を挟む形で利用するとすべてのエラーを受け止めるエラーページを設置できる。

https://ja.reactjs.org/docs/error-boundaries.html

また、もっと個別の機能やページごとにエラーバウンダリーを設置できる。
ドキュメントによるとfaceBookMessangerはサイドバーとメイン画面は別々のエラーバウンダリーでラップされており、どちらかでエラーが起きても、もう片方に問題がなければそちらは動くといったようにできているらしい。

https://ja.reactjs.org/docs/error-boundaries.html#new-behavior-for-uncaught-errors

## ４，Build時にコードが丸見えになる問題への対処

reactはBuild時に、**SourceMap**と言われるMinifyされたコードをMinify前のコードに復元できる情報を持ったファイルを生成する。

Chromeではこれを**読み込んでコードを復元する**という機能がデフォルトであるため、devToolのsouceタブを開くとreactのコードが復元されてしまっている。これは対処しないとセキュリティ的によろしくない。

対処法は、**`GENERATE_SOURCEMAP=false`を環境変数（.envファイル）に適用する**だけでいい。

これは少なくともやっておかないといろいろ怖いので、これからReact使うって人にはとりあえず教えておきたい。

https://fintan.jp/page/1596/
### ５，Reactのビルド時に出るメモリ不足のエラー

Reactはビルドするときに、ソースマップを生成する過程でメモリ不足になることがあるらしい。４で記述した`GENERATE_SOURCEMAP=false`を設定しておけばソースマップが生成されないので解決すると思われる。

それでも解決できなそうであれば、`NODE_OPTIONS=--max_old_space_size= ~` で確保できるヒープ領域の上限を開放してあげれば解決できると思う。

僕の場合、EC2でビルドしていたのですがそもそもそちらのメモリ不足でswap領域を確保することで解決できたので問題の切り分けは大事ですね。

これくらいを知っておけばReactを本番環境で動かすための不安はだいぶ減らすことができそうなので、まとめてみました。
C＃でCloud Firestoreを使う

# この記事は？
個人的なシステムでRealtime Databaseで扱っていたデータをCloud Firestoreに移管することにしたため、それに伴いC＃で作成したバッチプログラムからCloud Firestoreにデータを書き込めるようにする必要が出てきた。その時の実装内容を備忘を兼ねて記事にした。
# やりたい事
メディアファイルをFirebase Storageにアップロードして、それに関連するデータをCloud Firestoreに書き込む。
# 実装手順
## サービスアカウントの作成
まずAPIを介してCloud Firestoreにアクセスするために認証を通す必要があるので、Firebaseの管理画面でサービスアカウントの作成を行いま
す。

Firebaseの管理画面でプロジェクトの設定 > サービスアカウントと進んで「新しい秘密鍵の生成」をクリックします。

秘密鍵のjsonファイルがダウンロードされるので、これを任意の場所に保存しておいてください。
## Google.Cloud.Firestoreパッケージの取得
Cloud FirestoreをC#から使うためにはGoogle.Cloud.Firestoreパッケージが必要なのでNugetで取得してインストールしてください。
## 環境変数の設定
環境変数に秘密鍵の場所を設定します。任意の場所（今回はMain()の中で実装しました）に下記を記述してください。

```C#
string accessKeyPath = "秘密鍵のファイルパス";
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", accessKeyPath);
```

## 書き込みを行う部分を実装する
ここまでの手順で準備ができたので、実際に書き込みをするコードを実装します。

```C#
// インスタンス生成
var db = FirestoreDb.Create("プロジェクトID");

// キー指定してドキュメントを取得
var radioRef = db.Collection("コレクション名称").Document(id);

// 書き込むデータを準備
var user = new Dictionary<string, object>
{    
    { "title", title },
};

// 書き込み（IDに該当するデータが無いときは追加、ある時は更新される）
await radioRef.SetAsync(user);
```
プロジェクトIDはFirebaseの管理画面でプロジェクトの設定を開くと表示されています。
Prismaで親を削除したときに子供と孫まで削除する(Referential actions)

# 概要

俗に云うCascading deletesの機能です。
Prismaでは2.26.0以降でReferential actionsの機能が使えるます。
日本語の文献が少なく、探すのに苦労したので備忘録です。

## 定義方法

`@relation`で定義時に、`onDelete: Cascade`を指定することで親が削除された際に子も削除されます。
削除せずにレコードを残したい場合には `onDelete: SetNull`を指定することでレコードを残すことも出来ます。

```prisma
model User {
  id    Int    @id @default(autoincrement())
  posts Post[]
}

model Post {
  id     Int          @id @default(autoincrement())
  title  String
  tags   Tag[]
  user   User        @relation(fields: [userId], references: [id], onDelete: Cascade)
  userId Int
}

model Tag {
  id       Int          @id @default(autoincrement())
  tagname  String
  post     Post        @relation(fields: [postId], references: [id], onDelete: Cascade)
  postId   Int
}

```



# 参考文献
https://www.prisma.io/docs/guides/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/referential-actions