OmniAICreator/Qiita-1.07M huggingface dataset:
UFTでAndroid実機を使いたい

# はじめに

UFTでモバイルのテストをする際に、Android実機を使用するにはどうするかを記載していきます。
設定などはとても簡単ですが、バージョンや端末ところどころ注意が必要です。

※UFTではAndroidエミュレータも使用でき、セットアップについては[UFTでAndroidエミュレータを使いたい](https://qiita.com/YamaAri/items/fbe9711863a84e3d3fc0)でまとめています。



# 環境
|                          |      Version      |   
|:-------------------------|:-----------------:|
| Windows                  |              10   |
| UFT One                  |            15.0   |
| Mobile Add-in for local  |             3.3   |
| Android                  |           6.0.1   |
| Android端末              | GALAXY S5 ACTIVE  |


※UFT Oneのバージョンによって対応しているMobile Add-inのバージョンが違うので注意が必要です。
対応しているバージョンの確認は下記から行ってください。

- UFTのバージョンが15.××の場合は[こちらのUFT Mobileの欄](https://admhelp.microfocus.com/documents/uft/PAM/UFT_15.X_PAM.html)
- UFTのバージョンが14.××の場合は[こちらのMobile Centerの欄](https://admhelp.microfocus.com/documents/uft/UFT_14.xx_PAM.html#UFT%20Add-ins)を確認してください。

※UFT Oneではサポート外の端末の場合、動かない可能性があるので注意が必要です。
UFT Oneがサポートしている端末は[Supported Devices](https://admhelp.microfocus.com/uftmobile/standalone/standalone%20device%20page1.html)を参照してください。

# 手順

手順については下記の通りです。

1. UFT Oneをインストールする
2. Mobile Add-in for localをインストールする
3. UFTにAndroid実機を繋ぐ
4. UFTの設定を行って、動かす！

下記で各手順について簡単に解説していきます。

## 1.UFT Oneをインストールする
UFT Oneは基本的にデフォルト設定のままインストールでOKです。
（なにか今後Add-in を増やしたい等がある場合でも再インストール可能なのでここはデフォルトで進めます）

## 2.Mobile Add-in for localをインストールする
こちらもデフォルトのままインストールでOKです。
インストーラは[こちら](https://marketplace.microfocus.com/appdelivery/content/uft-mobile-add-in-for-local-device)から取得できます。

## 3.UFTにAndroid実機を繋ぐ
Android実機をPCに接続します。
この際に「USBデバッグを許可しますか？」と表示された場合は「許可をする」を選択してください。
※表示されなかった場合は、設定の開発者オプションで設定が可能なので、こちらを設定してください。

## 4. UFTの設定を行って、動かす！
UFTを起動します。
この際にMobileに必ずチェックを入れてください。
![図9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121319/f1a3e17b-d43b-9237-6f96-c1352bbcadff.png)

起動したら新規でGUIテストを作成してください。
その後記録>記録と実行環境の設定を選択します。

［＋］でローカルアプリケーションを選択（選択すると青枠で囲まれます）します。
インストールにチェックを入れて、適用を押下後、OKで設定画面を閉じてください。
![図10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121319/9fcf8ebe-f945-0eef-2494-c69591d97c42.png)

その後記録を押下し、下記のような画面が表示されたら完了です。
![図11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121319/156efdee-91e8-9685-4a13-0a022faaba44.png)
統計検定2級をCBT方式で受けてみて

先日CBT方式で統計検定2級を受けた。本番は妙に下振れしたがとりあえず合格したので簡単に合格までにしたことやCBT方式について纏める。

#CBT方式について

CBT方式というのは従来の検定試験の様に年3回程度の会場実施の試験と違い、テストセンターでパソコンを使ってさくっと受験できるシステムである。当然の話も含まれるが以下に個人的に感じた気を付けるべき点をあげる。

1.コンピューターなので画面に書き込めない

当然なのだがコンピューターの画面にペンで書きこむことはできない。私は普段から無駄な書き込みをしないタイプの人間をやっているのであんまりここは負担にならなかったが、人によっては普段勉強する時に気を付ける必要があると思われる。

例えば5つの選択肢があって1つずつ吟味して選ぶ必要があるような問題で、間違いだと判断した選択肢に斜線をいれて脳みその負担を減らすというような行為はできない。普段解くときから脳内で間違いの選択肢を除去しておく練習をするか、あるいは計算用用紙は検定中使用できるのでそちらに上手く書き残す練習をしておくとよい。(まっさらな計算用紙のみ書き込めると仮定して普段から解けばよい練習になると思われる)

2.紙の検定とはやや異なるスタイル

あんまり詳しいことは書けないのだが就活を経験している人はテストセンターでうけるwebテストと統計検定をドッギングさせたような感覚をイメージすればいいと思われる。

+α
例えば(10), (11)が同じ題材を扱っている問題だとしよう。このとき画面の都合上なのか(10)にあった表が(11)にはないが、(11)の選択肢を潰すには(10)のときにあった表が有効というような状況が発生し得る。そういうとき(11)だけの情報で全て解こうとすると無駄な時間を消費することになるので上手く対処できるとよい。(そういう状況が生じ得ると頭に入れておくだけでも変わると思います)

出題傾向は公式で出てる過去問とそんな大きな差はないように感じた。

#勉強したこと

以下にざっくりとやったことを記していきます。万人に効く方法ではないので、参考程度にしてください。
既に統計検定の記事は多く存在し、以下の記事が参考になるかと思います。

[統計検定2級に楽に合格する方法](https://qiita.com/okoppe8/items/6caca7ab6509edf0c497)
[統計検定2級の為のチートシート](https://qiita.com/akiyoshi_sasaki/items/c81032c1683f69ff9d11)


##高校数学範囲を抑える

2級の出題範囲は大学基礎課程（１・２年次学部共通）とされていますがなんだかんだ高校数学は大事。
個人的に統計検定の勉強という観点では、統計学の教科書を読み込んで唸るより、高校数学の参考書とセンター試験とかの過去問を使ってしまった方が勉強を効率的に進められるかと思われる。

まずは数Ⅰ　データの分析　と数a 確率　の範囲をしっかりおさえる必要がある。
更に数B 統計的推測 の単元まで抑えれば運が良ければ合格できる。

##高校数学以外の範囲について
大枠は仮説検定とちょっとした知識問題だが個人的には過去問で勉強するのがはやいと思う。
(統計学の体系的な理解にはつながらないのであくまで統計検定2級の為の勉強としてという意味です。)

以下は私がやった作業です。

###過去問1回分を全問解けるまで理解して解くを繰り返す

2週間程度で、大学の統計学の教科書を1から読んでそれから検定対策もするというのは多分消化不良にもつながるのでよくないと考え、検定特化型の勉強にした。
過去問を1回解いては間違えた箇所を徹底的に調べ、95%くらい理解したら次の回を解くという形で進めた。

正当数の推移は6回分解いて
17→18→25→27→31→31
というような感じだった(本番は81点)

このやり方は最初の3回分くらいは復習にめちゃくちゃ時間を使うが、そこを超えると傾向と必要な知識が身について残り3回はかなりあっさりと勉強が進むので最初をしっかり頑張れればなんとかなる。

以下具体的な流れ

[過去問を買う](https://jitsumu.hondana.jp/book/b496703.html)

まずは1回分解いて採点、解説を読む　と普通に進める。

間違えた問題については文中の言葉をヒントに
1. [統計学の時間](https://bellcurve.jp/statistics/course/)
2. google　qiitaなどの解説記事→どこぞの大学の謎pdf、もしくはスライド
で調べていけばよい。特に統計学の時間に書かれている内容はまんま2級の範囲なので使いやすい。調べて出てきた知識を基に過去問の解き方を理解し、実際に自分でも手を動かす。

また大学受験みたいだが、選択肢の中に出てきた知らない単語なども調べあげる。問題文含め分からないところがないように調べ上げる。

一通り復習が終わったら少し時間をおいてからもう一度問題の全問を見直す。全部厳密に解くわけではなくこれはこう解いたなとか、この問題ではこういう知識が必要だったみたいなのを思い起こし、忘れてるものはまた調べ直す。
というのを気が向いたときに何回か実施する。知識忘れとかはなく、ちょっとしたミス以外での失点はこの回ではしないなと感じるレベルまできたら次の回を解き同様の作業を実施する。

更に2回目の作業が終わったら再度1回目に解いた過去問の見直しも実施する。
3回分も蓄積すれば統計検定2級で出てくる問題の大部分を抑えられる。

###プチテスト

ここまでやってたら以下の単語(単元)について理解できているか確認して欲しい。

正規分布、t分布(正規分布と何が違うの?)、2項分布、ポワソン分布、χ2乗分布、F分布、(幾何分布)
→それぞれの定義とどんな場面で出てくるのか？

2項分布、ポワソン分布、幾何分布の分散と期待値の式は？
分布表の見方はそれぞれ理解したか？
標準誤差とは？どうやって計算する？
不変推定量の定義は？
検定の考え方について説明できるか？
t検定(どういうときに使うのか?)
χ2乗検定(同上、帰無仮説と対立仮説は何か?　自由度の決定方法は？)
等分散性の検定はどう実施するか？
分散分析とは?

標本抽出の仕方の区別がつくか？
フィッシャーの3原則とは？

確実にとは言いませんが上記の内容と高校数学がきっちり身についていれば恐らく合格できるかと思います。
JavaScript/node.jsでsleep

ちょっとしたことだけど、JavaScriptにはsleepがないので。

```JavaScript
async () => {
    // 前の処理
    await new Promise(resolve => setTimeout(resolve, 1000));
    // 1秒待った後の処理...
}
```

## JavaScriptに馴染みのないサーバーサイドの方向けに説明
### setTimeout
`setTimeout(コールバック, ミリ秒)`でミリ秒後にコールバックを実行します。JSのタイマー処理の基本。

### Promise
`new Promise()`でPromiseオブジェクトを取得します。Promiseオブジェクトは非同期処理が完了したら結果がもらえるやつです。

```JavaScript
const 結果のPromise = new Promise(resolve => {
    // 任意の処理
    resolve(結果);
});
```
### await
`await Promiseオブジェクト`で結果を取り出せます。`async`関数の中で使う必要があります。
macでのHEASoftの基本的な環境構築方法

# HEASOFTソフトウェアをダウンロードする
まず、[Download the HEASOFT Software](https://heasarc.gsfc.nasa.gov/docs/software/heasoft/download.html)から、「SOURCE CODE DISTRIBUTI」か、「PRE-COMPILED BINARY DISTRIBUTIONS」のうち、好きな方を選び、自分の使っているPCのバージョンにチェックを入れる。
NASAはソースコードの方を推奨してますが、時間がかって面倒なので、自分はBINARYをお勧めします。

次に解析したいミッションにチェックを入れると、自動で必要なパッケージにチェックが入るので、選択したらSubmitでインストールを開始します。
インストールには数時間かかるので寝る前とかにはじめると良いかもしれません。


# セットアップ
基本的には[Installing HEASoft (For Source or Binary Distribution)](https://heasarc.gsfc.nasa.gov/lheasoft/install.html)の「STEP-BY-STEP INSTALLATION INSTRUCTIONS」の通り進めれば良いです。

以下ではBinaryのセットアップについて簡単に記述しておきます。（バージョンとかは自分で合わせて変えてください。）


## configureスクリプトの実行
まず、ターミナルを開いたら、

```terminal
$ mkdir work
$ cd work/
$ mkdir software
$ cd software
```

として作業フォルダを作りましょう。次にダウンロードしたファイルを

```terminal
$ mv ~/Downloads/heasoft-6.27.2mac_intel_darwin19.tar .
$ tar -xvf heasoft-6.27.2mac_intel_darwin19.tar
```
なりでここに移し、解凍します([Installing HEASoft](https://heasarc.gsfc.nasa.gov/lheasoft/install.html)のステップ2）。
解凍ができたら、

```terminal
$ cd heasoft-6.27.2/x86_64-apple-darwin19.3.0/BUILD_DIR/
```
でBUILD_DIRディレクトリーに移動し、

```terminal
$ ./configure > config.out 2>&1
```
としてconfigureを実行する([Installing HEASoft](https://heasarc.gsfc.nasa.gov/lheasoft/install.html)のステップ3）。　


## PATHを通す
ターミナル上で```command```+```n```で新しいターミナルを起動します。
そこで、

```terminal
$ emacs ~/.bash_profile -nw
```
でウィンドウを開き、一番下に

```emacs-lisp
export HEADAS=/path/to/your/installed/heasoft-6.27.2/x86_64-apple-darwin19.3.0
alias heainit=". $HEADAS/headas-init.sh"
```
と書き、```control```+```x```と押した後、```control```+```c```で保存して終了する。そして、

```terminal
$ source ~/.bash_profile
```
で.bash_profileの変更を反映する。



# xspecなどが開発元を検証できないため開けない時

```terminal
$ sudo spctl --master-disable
```
ですべてのアプリケーションの実行を許可する事ができます。
⚠︎ セキュリティ面は自己責任でお願いします。


# X11のエラーが出たら
```terminal
dyld: Library not loaded: /opt/X11/lib/libX11.6.dylib
  Referenced from: /your/installed/heasoft-6.27.2/x86_64-apple-darwin19.3.0/bin/xspec
  Reason: image not found
```
https://www.xquartz.org/
からXQuartz-2.7.11.dmgをインストールすればエラーが出なくなる。
Hà Nam 365 | Thông tin sản phẩm & dịch vụ tại Hà Nam

Hà Nam 365 là một website giới thiệu các dịch vụ & sản phẩm tại Hà Nam khách quan và chân thực nhất. Một cổng thông tin ưa thích của người dân Hà Nam https://sites.google.com/view/hanam365![HN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687262/03738acf-1f54-07a2-dd06-79dc8361fa70.png)
【PowerShell】大量のファイルを一括削除しよう

#はじめに
仕事中、リモートデスクトップのファイルをたくさんダウンロードしちゃうから、ダウンロードフォルダーにいらないファイルがたまっていってしまう！一個一個消すのはめんどくさいからPowerShellを使って消していきます。

#PowerShellスクリプトの中身

```powershell

cd c:\users\<ユーザー名>\downloads
get-childitem
#上記のコマンドを実行したらchangeDirしたところにあるフォルダーとファイルの一覧が取得できます。
remove-item *.rdp

```


こんな感じ！

#解説
もっと早くできるやり方あるかもしれないけど、消したいファイルがあるところにチェンジディレクトリして、一覧を取得してみて、消す流れ。

消すときは" * " （ワイルドカード）が使えます。
AWS SageMakerでpickleを使ってmodelのsave/loadをするときの注意点

# 概要
AWS SageMakerで学習インスタンスで学習したモデルをpickleをsave、notebook側でloadをしようとしたら、エラーが出たので対処方法を紹介する。



## cloudpickleをつかう
pickleでは、シリアライズする側で
グローバル変数またはその変数を参照しているオブジェクトが
名前空間内に存在しない環境でシリアライズできない。

```
cloudpickle.dump(predictor, open('%s/model'% model_dir, 'wb'))
```

## cloudpickleのバージョンは1.3.0
学習インスタンスではデフォルトが1.5.0になっている。
notebook側は1.3.0である。notebookを1.5.0にあげてもエラーがでたため、学習インスタンス側をバージョンダウンさせる必要がある。

このため、デプロイする際も学習インスタンス同様cloudpickleのバージョンを1.3.0に指定する。

## まとめ
簡単なメモ書きになってしまったが、cloudpickleでエラーになった場合は
バージョンを確認すると良い。
A Comprehensive Business Guide to SOC Services

$3.92 million– yes, that was the average amount of a data breach in 2019! With businesses getting dependent on technologies & cybersecurity attacks always on the rise, this cost of a data breach is expected to rise further. Companies also perceive Cloud-based security as a significant threat if they don’t have dedicated security staff. However, on an optimistic note having a Security Operations Center (SOC) is helping the companies of all sizes to manage their cybersecurity risks effectively.
ESDS SOC as a service

What is SOC?

SOC represents a team of cybersecurity professionals that are proactively dedicated to preventing all kind of data breaches as well as other cybersecurity threats. The final goal of SOC is to monitor, detect, investigate, and respond to all the potential forms of cyber threats at all times.

The team members present in a SOC team deploy various technological solutions along with processes. These include- security information and event management (SIEM) systems, firewalls, detection of breaches, and intrusions. The SOC teams also deploy various tools for performing vulnerability scans in the network against possible threats and weaknesses.

https://www.esds.co.in/soc-as-a-service
【PowerShell】PowerShellからmsiをインストールしよう

#はじめに

主に仕事でIntuneを使ってるから、たくさんの端末にmsiを実行しようっていうps1を配信したいときの中身をわたし用にメモしていきます。

#PowerShellの中身はこんな感じ

```powershell
cmd /c "msiexec.exe /i "C:\×××\×××.msi"

```
>"C:\×××\×××.msi"

ここはmsiの配置してあるフルパスを指定。
（フルパスは該当のmsiファイルをShift + 右クリックでパスのコピーを押せばコピーできる。）

Intuneからサイレントインストールさせたいときは、以下の通り/quietつければ大丈夫です！

```powershell
cmd /c "msiexec.exe /i "C:\×××\×××.msi" /quiet

```

おわり。
【python】【scikit-learn】k-最近傍法入門メモ

# Scikit-learnの学習メモ

## scikit-learnの命名規則

|文字|意味|
|:--|:--|
|X|データ|
|y|ラベル|

## train_test_split関数

データ(X, y)をトレーニング用・評価用に分割する関数

`分割を行う前に擬似乱数を用いてデータセットをシャッフル`する。

データポイントはラベルでソートされているので、最後の25%をテストセットにすると,全てのデータポイントがラベル2(1つの値)になってしまうような事態を避けるため。

[train_test_split関数でデータ分割](https://docs.pyq.jp/python/machine_learning/tips/train_test_split.html)
[乱数のシード](https://docs.pyq.jp/python/pydata/numpy/seed.html)

```python:jupyter_notebook.ipynb

train_test_split( 第一引数: 特徴行列X, 第二引数: 目的変数y, test_size(=0.3): テスト用のデータの大きさの割合, random_state= : データを分割する際の乱数のシード値)

random_state=0とすると、出力が決定的になり、常に同じ結果が得られるようになる。(勉強用)

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
    iris_dataset['data'], iris_dataset['target'], random_state=0)
```

## pandas.DataFrame

[pandas.DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)

```python:pandas.DataFrame
import pandas as pd

#リファレンス
pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)

#例
iris_dataframe = pd.DataFrame(X_train, columns=iris_dataset.feature_names)
```

出力結果
<img width="586" alt="スクリーンショット 2020-08-06 15.17.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630802/9964bb5c-3bd4-6f57-85fd-bd8627a174db.png">

## pandas.plotting.scatter_matrix

[pandas.plotting.scatter_matrix](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.plotting.scatter_matrix.html)

```python:pandas.plotting.scatter_matrix
#公式リファレンス
pandas.plotting.scatter_matrix(frame, alpha=0.5, figsize=None, ax=None, grid=False, diagonal='hist', marker='.', density_kwds=None, hist_kwds=None, range_padding=0.05, **kwargs)

#iris例
iris_dataframe = pd.DataFrame(X_train, columns=iris_dataset.feature_names)
grr = pd.plotting.scatter_matrix(iris_dataframe, c=y_train, figsize=(8, 8), marker='o',hist_kwds={'bins' : 20}, s=60, alpha=.8)
```

出力結果
<img width="706" alt="スクリーンショット 2020-08-06 15.26.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630802/81ba287a-fa0a-2f5f-9d0e-c0a954281fa7.png">

## scikit-learnは常に２次元配列

```python:scikit-learn
X_new = np.array([[5, 2.9, 1, 0.2]])
```

## sklearn.neighbors.KNeighborsClassifier

`k-最近傍法`によるクラス分類

[sklearn.neighbors.KNeighborsClassifier](https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html#sklearn.neighbors.KNeighborsClassifier.score)

```python:neighbors.KNeighborsClassifier
#大切なメソッド

.fit(X, y)
#Xを学習データ、yを目標値としてモデルを適合させる

.predict(X)
#提供されたデータのクラスラベルを予測します。

.score(X, y)
#与えられたテストデータとラベルの平均精度を返します。
```
Unity2018から2019にアップデートしたら、特定動作でMacPCを巻き込みクラッシュした。

どんなことを試したか等も書いちゃってるので
「対応策が知りたいんだ！」
と言う方は最後辺りを見てくださいませ。

# 環境
PC(私) : MacOS Catalina 10.15.5
PC(先輩Nさん) : MacOS Catalina 10.15.3
Unity(アプデ前) : 2018.4.3f1
Unity(アプデ後) : 2019.4.6f1

# 問題の概要
## そもそも何をしようとしていたか
1. 昔のエンジンを使って、新たなプロジェクトを作ろうとした。
2. 新たなプロジェクトを作るにあたり、Unityのバージョンを上げようとした。

## 問題の発生
1. 先輩NさんがUnityのアップデート作業を行う。
2. 問題なくアップデートが済み、リポジトリにPush。
3. 私がリポジトリからクローンしてきて動作確認をする。
4. 特定動作で私のMacPCを巻き込みクラッシュ！

## クラッシュ手順
1. プロジェクトを開く
2. Editor内のConsole,Inspector,Project等々のwindow配置を変える
3. 1〜10回のうちにクラッシュする

例)consoleを移動（これを行うとMacPCもろともクラッシュしました）
![クラッシュ手順_normal_gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275803/aa426ab8-8d62-698b-b49b-ecbe3cdb3a36.gif)


# 調査
## ぐぐる
windowを移動するとクラッシュするなんて記事が出てこなかった。
（クラッシュの原因でMetalがどうのこうのと書かれてる記事はいくつか見つけましたが、当プロジェクトでは既にチェックがついていました）

## クラッシュログを見てみる
1. UnityのEditor.logが作成されなかった <br>
   (Editor.logを削除後、クラッシュ手順を踏みました) <br>
   https://docs.unity3d.com/ja/2018.4/Manual/LogFiles.html
2. MacPCのログも見てみたが「.crash」が作成されなかった。 <br>
   「.panic」ログも作成されていたが、中身が暗号化されたJsonのようなもので読めなかった。 <br>
   https://gori.me/mac/mac-tips/108863

何の成果も得られなかった...

## しらみ潰しで探す
1. いろいろファイルを削除してみた結果、UnityProject/ProjectSettings/ProjectSettings.asset が怪しいことがわかった。
2. NewProjectを作成 -> 問題のProjectSettings.assetを上書きコピー -> NewProjectでもクラッシュすることがわかった。
3. NewProjectをGit管理し、上書いたProjectSettings.assetの怪しい箇所を削除(リセット)してはクラッシュを繰り返す。
4. 心が先に折れたので、細かいところまで見つけられなかったが、一部分をDefault設定に戻すことでクラッシュが回避できることがわかった。

（基になったエンジンのProjectSettings.assetを全て流用する必要もないので、ざっくりとDefault設定に戻してもいいかな、なんて）


# 対処法
## 手順
1. UnityProject/ProjectSettings/ProjectSettings.asset をリセットし、クラッシュが発生しなくなることを確認。
2. NewProjectを作成 -> Git管理をする -> 問題のProjectSettings.assetをNewProjectに上書きコピー
3. NewProjectのGitにて差分チェック。
4. 差分を一部リセット -> クラッシュしないか動作確認 -> クラッシュしたらリセット箇所を復元
5. クラッシュしなくなるまでひたすら「4」を頑張る。
6. クラッシュしなくなったら、UnityProjectにProjectSettings.assetを上書きコピーする。

本音のところ、エンジンを利用しただけの新プロジェクトなので、ProjectSettings.assetを完全リセットしてもいい気はしてます。
必要な分は改めて再設定しちゃいましょう。


# 疑問
## なぜ先輩Nさんの環境ではクラッシュが発生しなかったのか
おそらく、MacOSの違いかなと思っています。
MacOS 10.15.4 ではアプリのクラッシュやカーネルパニック祭りだったそうなので
MacOS 10.15.5 でも一部不具合が残ったままなのではないでしょうか。
先輩Nさんは 10.15.3 を利用していたのでクラッシュしなかったのだと思います。
が、詳しいところまで調べきれてないので真相は闇の中...
https://applech2.com/archives/20200407-macos-10-15-4-catalina-finder-app-crash-and-kernel-panic.html


# 最後に
こちらは、完全にクラッシュ問題を解決できるものではありませんので
参考にする方は、あくまで参考であることを念頭に入れていただけますと幸いでです。
また、ProjectSettingsの更新も後々大きな事故に遭う可能性がありますので、細心の注意を払って更新してください。
UbuntuでワークスペースをCtrl+数字で切り替えられるようにする

## 環境

- Ubuntu 20.04


## ワークスペース数を10に設定

```
gsettings set org.gnome.mutter dynamic-workspaces false
gsettings set org.gnome.desktop.wm.preferences num-workspaces 10
```

## Ctrl + 数字 で対応するワークスペースに移動できるようにショートカットキーを割り当てる

```
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-1 "['<Ctrl>1']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-2 "['<Ctrl>2']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-3 "['<Ctrl>3']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-4 "['<Ctrl>4']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-5 "['<Ctrl>5']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-6 "['<Ctrl>6']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-7 "['<Ctrl>7']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-8 "['<Ctrl>8']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-9 "['<Ctrl>9']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-10 "['<Ctrl>0']"
```

## 参考
https://www.it-swarm.dev/ja/18.04/ubuntu-1804%E3%81%A7%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%81%AE%E6%95%B0%E3%82%92%E5%A2%97%E3%82%84%E3%81%99/997881189/
勉強ノート：DOM操作

# 要素ノードの操作の手順
1. Objectの取得
2. Objectプロパティ値の変更

## 個別要素へのアクセス
- document.getElementById(id): idに対応するオブジェクトを返す
- document.getElementsByTagName(tag): p tagなど一致するオブジェクトのリストを返す
- document.getElementsByName(name): name属性に一致するオブジェクトのリストを返す
- document.getElementsByClassName(name): Class属性に一致するオブジェクトのリストを返す

## セレクタ式を使ったアクセス
- document.querySelector(selector): 1つ
- document.querySelectorAll(selector): 

## 相対パスでのアクセス(getxxx, queryxxxの後に使う)
- obj.firstChild
- obj.nextSibling
- obj.firstElementChild
- obj.nextElementSibling

# Tagで修飾されたテキストへのアクセス
getxxxなどでオブジェクトを取得した後、以下の方法でアクセスできる。
- obj.innerHTML： 文書を埋め込むのに使う、テキストだけ返す
- obj.contentText：　HTMLを埋め込むのに使う、タグを含んだ形で返す

# Event-Driven
イベントハンドラを登録するには以下の方法がある。
1. タグ内の属性として宣言: <tag_name oneventname="JS Code">
2. 要素オブジェクトのプロパティとして宣言: JS内でObjectを取得し、onclickなどのイベントプロパティに関数オブジェクトを設定する。複数のハンドラは紐付けられない。
3. addEventListenerメソッドを使う: elem.addEventListener(type, listener, capture)

# ノードの作成、削除
- createElement(element)
- createAttribute(attr)
- createTextNode(text)
- elem.appendChild(node)

# Ref
山田祥寛,JavaScript本格入門[改訂新版]
PHPでOption型を利用してnullチェックや例外ハンドラを消す

ScalaやRustを普段使ってる方には当たり前にあるOption型ですが、残念ながらPHPには組み込みされていません。
しかし、[php-option](https://github.com/schmittjoh/php-option)を利用することで同様の体験を得ることが出来ます。
https://github.com/schmittjoh/php-option

# こんなコード書いてませんか？

## 例外を投げる

例えばRepositoryからEntityを取得する処理でこんなコードを書いてませんか？

```php:Repository
public function findById(Id $id): Entity
{
  $result = $this->queryBuilder->...
  if ($result === null) {
    throw New NotFoundException('message');
  }
  return Entity::create($result);
}
```

データベースからデータを取得して、データがなければ例外、あればEntityとして返却するというコードを書いたことがある人もいるかと思います。
しかし、この関数を利用する際に適切に例外ハンドラを作らないと意図しないエラー画面を出力してしまう可能性があります。

## is_nullで値の確認
こんな処理も書いていないでしょうか？

```php
$hoge = $entity->getHoge();
if (is_null($hoge)) {
    return; // デフォルトで返したい値など
}
return $hoge;
```
とあるEntityから取得できるValueObject等がnullableの場合にis_nullなどを利用してチェックする処理などを書いていないでしょうか？
また、このようなチェックを見逃して意図しない値をViewに渡してしまうなどしてないでしょうか？

# 値がある型、値がない型に分ける
`Some`型と`None`型という、なにか値のある型と値がない型に分けることで処理をわかりやすくします。

先程のRepositoryでのコードを例に書き換えてみます。

```php:Repository
public function findById(Id $id): Option
{
  $result = $this->queryBuilder->...
  if ($result === null) {
    return None::create();
  }
  return Some::create(Entity::create($result));
}
```
結果がnullだった場合はNone型、値があればSome型として返却します。
このOption型をどう使うかは次のis_nullチェックしていた例を見てみます。

```php
$hoge = $entity->getHoge();
return $hoge->getOrElse('デフォルトで返したい値など');
```

`getHoge()`がRepositoryの例のようにOption型が返ってくると想定しています。Option型には`getOrElse`というメソッドがあり、値があれば取得できて値がなければ引数で指定した値を返すという関数です。

また、値があることだけを確認したい場合も

```php
$hoge = $entity->getHoge();
if ($hoge->isEmpty()) {
  // None型
}
if ($hoge->isDefined()) {
  // Some型
}
```
このようにメソッドが用意されているので簡単に分岐を作ることが出来ます。

# まとめ
Option型を使うことで明示的に値があるかもしれないし、無いかもしれないという型を作ってその振る舞いを扱いやすくできました。
ちなみにphp-optionは[phpdotenv](https://github.com/vlucas/phpdotenv)で利用されていて知りました。
`env('KEY', {default})`はまさに値があるかもしれないし、無いかもしれないものですよね。

### 小言
PhanとかPHPStanを使えばコメントでジェネリクスを表現してIDEでサポートされたりするんでしょうか？（知らない）
ジェネリクスを書きたい、Hackを書くしか無いか・・・
Active Storage 導入環境下での単体テスト

まずActive Storageって何？

ファイルアップロードを行うための機能で、
これを使えばフォームで画像の投稿機能などが簡単に作れる。
また、クラウドストレージサービスへのファイルのアップロードも
簡単にできちゃいます。

自分の場合は画像をアップロードできる機能があるアプリケーションを作成していたので、
Active Storageを導入していました。
特徴としては画像用のカラムを用意する必要がないこと。
今回はこの特徴で、エラーがでまくっていたのですが...

##本題のテストのこと
今回のエラーの原因は
``①FactoryBotで、ダミーのimageデータを作ってしまっていた``
``②spec.rbで、fixture_file_uploadメソッドを使っていなかった``

以上の2つが主な原因でエラーを吐きまくっていました。

特に②に関しては、見当違いのことを調べていたばかりに中々たどり着きませんでした..

---

それでは①から。

例えばproductというモデル/テーブルがあるとして

`Active Storageを使っていない場合`
imageカラム（画像用のカラム）が必要

`Active Storageを使っている場合`
imageカラム（画像用のカラム）が必要ない

ですよね。

上記を踏まえてFactoryBotの記述を見直すと

`Active Storageを使っていない場合`

```products.rb
FactoryBot.define do
  factory :product do
    image             { 'test_image.jpg' }
    name              { '化粧水' }
    explanation       { '良い化粧水です' }
    price             { '2000' }
    user
  end
end
```

`Active Storageを使ってる場合`

```products.rb
FactoryBot.define do
  factory :product do
    name              { '化粧水' }
    explanation       { '良い化粧水です' }
    price             { '2000' }
    user
  end
end
```

こうなるのは当然ですよね。
だってActive Storage環境下ではimageカラム必要ないですし。
（全然気付いていなかった..）

これで①の部分は解決しました。

---

###fixture_file_uploadメソッド
続いて②の方を。
このメソッドはRSpecで用意されているメソッドです。


全然テストが通らなかったときのspec.rb　↓↓↓↓

```product_spec.rb
require 'rails_helper'


describe Product do

  describe '#create' do
    before do
      @product = build(:product)
    end


    
    # 1. imageが存在すれば登録できること
    it 'is valid with an image' do
      expect(@product).to be_valid
    end

    # 2. nameが空では登録できないこと
    it 'is invalid without a name' do
      @product.name = nil
      @product.valid?
      expect(@product.errors[:name]).to include('を入力してください')
    end

                        .
                        .
                        .
                        .
                        .

  end
end
```

修正後のspec.rb　↓↓↓↓

```product_spec.rb
require 'rails_helper'


describe Product do

  describe '#create' do
    before do
      @product = build(:item)
      @product.image = fixture_file_upload("/files/test_image.jpg")
    end


    
    # 1. imageが存在すれば登録できること
    it 'is valid with an image' do
      expect(@product).to be_valid
    end

    # 2. nameが空では登録できないこと
    it 'is invalid without a name' do
      @product.name = nil
      @product.valid?
      expect(@product.errors[:name]).to include('を入力してください')
    end

                        .
                        .
                        .
                        .
                        .

  end
end
```

`fixture_file_upload("/files/test_image.jpg")`
とはなんぞやということなんですけども、
下記のディレクトリの通りにテスト画像を配置しています。

```
spec
  ├ factories
  ├ fixtures
  │     └ files
  │         ├ test_image.jpg
  │         └ .keep
  ├ models
  :
  :
```
これを、before do ~ end の間でコールバック（予約）しておいて、
テストコードが実行される前にテスト用の画像を生成しているわけです。

これで②も無事に解決です。

---

解決してしまえばなんてことない原因でしたが、
たどり着くまでに相当な時間と気力を消費してしまいました。

もっと検索力上げないとな...

同じような原因でテストが通らない方の参考になれば幸いです。
AzureSphere開発でSDKのライブラリのリンクを追加する方法

# AzureSphere開発でSDKのライブラリのリンクを追加する方法
初めてのAzureSphere開発で少しハマったので記録します。

## 立上げ
まず今回作りたかった製品をざっくり言うと、UARTで受信したデータをhttpでwebサーバにアップロードしていくという製品です。
開発環境は[MSのドキュメント](https://docs.microsoft.com/ja-jp/azure-sphere/)に従ってVisual Studio Codeの環境を立上げました。
チュートリアルのLチカサンプルで環境構築に成功したことを確認し、いざ実装。

## 楽勝？
UARTの実装を順調にこなし(GitHubからサンプルをクローンしただけ 笑)http処理部分に取り掛かります。
SDKのcurl使えばいいんでしょ。[MSのドキュメント](https://docs.microsoft.com/ja-jp/azure-sphere/app-development/curl)もあるし楽ショーじゃね。
とか調子に乗り始めたところでコケました。。。

## なんでビルドが通らない
[MSのドキュメント](https://docs.microsoft.com/ja-jp/azure-sphere/app-development/curl)の手順を踏んでビルドしましたが下記のビルドエラー発生。

```:output
[build] C:\prj\SW\soft\AzureSphere\out\ARM-Debug/../../main.c:438: undefined reference to `curl_slist_append'  
[build] C:/Program Files (x86)/Microsoft Azure Sphere SDK/Sysroots/6/tools/gcc/real-ld.exe: C:\prj\SW\soft\AzureSphere\out\ARM-Debug/../../main.c:439: undefined reference to `curl_global_init'  
[build] C:/Program Files (x86)/Microsoft Azure Sphere SDK/Sysroots/6/tools/gcc/real-ld.exe: C:\prj\SW\soft\AzureSphere\out\ARM-Debug/../../main.c:440: undefined reference to `curl_easy_init'
・・・
```

curlの関数が定義されていない的なエラーだけどcurl/curl.hのインクルードはちゃんとしています。  
しかも同じSDKで定義されている applibs/uart.h の関数は正常にビルドされている。なんで？  

```C:main.c
#include <applibs/storage.h>  // required only if you supply a certificate in the image package
#include <tlsutils/deviceauth_curl.h> // required only for mutual authentication
#include <curl/curl.h>
#include <curl/easy.h>
```

## 解決方法
・・・
小一時間MSのドキュメントとプロジェクトファイルの行き来を繰り返し、解決方法を発見しました。  

↓これを。。。

```:CMakeLists.txt
target_link_libraries(${PROJECT_NAME} applibs pthread gcc_s c)
```

↓こう！

```:CMakeLists.txt
target_link_libraries(${PROJECT_NAME} applibs curl pthread gcc_s c)
```

結論としてはtarget_link_librariesでcurlのリンクを追加する必要があったみたいです。  
CMakeを普段から使っている人からすると常識かもしれませんが、CMakeビギナーの自分には難問でした。。。  

## 参照したサイト
Azure Sphere のドキュメント | Microsoft Docs（https://docs.microsoft.com/ja-jp/azure-sphere/）
【UFT】ユーティリティまとめ　～データベース(Database)の制御～ - SQL/Query/Oracle - 

テスト自動化ツールである、UFT(Unified Functional Testing)

今回は Databaseの制御について、まとめたいと思います。
UFTのメソッドでは直接データベースを制御する機能は実装されていません。
そのため、制御についてはVBScriptを用いて実現します。

# ADODBのプロパティ・メソッド
 UFTでデータベースを操作するには、[ ADODBオブジェクト ]を使います。
 ADODBにはデータベースを制御できるプロパティ、メソッドが４つあります。

	ADODB.Connection	データベースへ接続するために使います
	ADODB.Command		QueryなどSQLコマンドの実行に使います
	ADODB.Fields		Query実行後に、取得したテーブルから特定のカラム(列)を取得するために使います
	ADODB.Recordset		データベースからデータを取得するために使います

CreateObject関数を使い以下のようにオブジェクトを取得します。

	Set cn = CreateObject("ADODB.Connection")
	Set rs = CreateObject("ADODB.Recordset")

取得できるオブジェクトについては、ボリュームが大きいので、別記事にて記述をしようかと思います。

# データベースへの接続方法

 データベースへの接続は、各データベースによって接続方法が異なります。
 詳細情報については、こちらを参考にしてください
 https://www.connectionstrings.com/

 データベースやその他のVBScriptの使い方については、下記のサイトを参考してみてください
 http://excel.style-mods.net/tips_vbs/index.htm


## Oracleへの接続＆データ取得
 OracleDatabaseへの接続・Query実行・データ取得について、サンプルコードを用いて解説します。
 前提条件として、データベースがPCにインストールされ、適切に設定されていることが必要です。

 ```VB:Oracle
'!注意! あくまでサンプルコードです。コードミスや動かない場合があります。ご承知おきください。

Dim adoDB	
Set adoDB = Createobject("ADODB.Connection")

' DB接続情報をセット
adoDB.ConnectionString = "DSN=DSN1;UID=user1;PWD=password1;"

' 接続をオープン
adoDB.Open

' ログインユーザーのテーブル一覧を取得するSQL文
Dim adoRS
adoRS = CreateObject("ADODB.Recordset")

' SQL処理
adoRS.Open "SELECT * FROM USER_TABLES ORDER BY TABLE_NAME"

' レコードセットが終端になるまでrows分繰り返す
Dim recodeSet
Set recodeSet = CreateObject("system.collections.ArrayList") '動的配列の準備
	'結果が0件の場合の処理
	If Not adoRS.EOF Then
		Do
			Dim dicRow
			Set dicRow = CreateObject("Scripting.Dictionary")		
			Dim iFieldIdx
			For iFieldIdx = 0 To adoRS.Fields.Count-1	
				dicRow.Add adoRS.Fields.Item(iFieldIdx).Name, adoRS.Fields.Item(iFieldIdx).Value
			Next
			recodeSet.add dicRow
			adoRS.MoveNext
		Loop While adoRS.EOF = False
	End If
	
	' レコードセットと接続をCloseする
	adoRS.Close
	adoDB.Close

```


# おわりに
これでSQLを実行し、値を取得することができました。

実際にUFTで使う場合は、サンプルコードのような処理を関数化させて、
実行結果を変数に格納したりと少々工夫が必要となってきます。

その他にも接続先のDatabaseの種類や実装したいこと次第では、さらに工夫、アレンジをする必要があります。

弊社ベリサーブでは、UFTについてのノウハウを有しております。
実際にUFTを用いた自動化が上手くいっていない・もっとよくしたいなどありましたら、ご相談いただけたらと思います。
[株式会社ベリサーブ -ホームページ-](https://www.veriserve.co.jp/?gclid=CjwKCAjwsan5BRAOEiwALzomX7oFxgsGDnRw7woHPhnkeBoFMzbpi9y9-D3Fi0TmzgsRqJTrSAg89hoCvt0QAvD_BwE)

# 参考・参照
・The Connection Strings Reference
https://www.connectionstrings.com/

・Excel VBA Workshop
http://excel.style-mods.net/tips_vbs/index.htm

・QTP Tutorial
https://www.tutorialspoint.com/qtp/qtp_accessing_databases.htm
RUSTの参照と借用について

# まえがき

この記事はRUSTチュートリアルをZerobillbank社内メンバー（有志）で勉強がてら、可能な限りわかりやすく内容を書き出す企画の一部です。  
本項では、RUSTのキモとされる **所有権** の考え方について記したいと思います。
なお、初学者のため（略）という免責を打ちつつ間違いなどあればコメントで教えていただけますと一同嬉しく思います！

# 概要

前項では変数に対する所有権について説明しました。  
本項では、この所有権を借用するという概念について説明します。  
ただ、考え方は所有権と一緒です。違うのは最初に定義し束縛した変数であるか、本項はそれを借り受けて（参照して）いるかです。  

# 借用とは

借用は単純に所有権を持っている状態ではなく、コピーして参照している状態です。  
例として前項で出てきたコードを使うとこのようになります。

```rust
fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) {
    // v1とv2についての作業を行う

    (v1, v2, 42)
}
let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];
let (v1, v2, answer) = foo(v1, v2);
```

*上記は [こちら](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=bb3736d563183813dbc50c9c8c4fe55f) で動作の確認が可能です。*  
  
では、これを借用する形式に書き換えてみます。  

```rust
fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 {
    42
}

let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];

let answer = foo(&v1, &v2);
```
*上記は[こちら](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=88df0e7c24a5773fd11fbd8e030b2dcd)から動作の確認が可能です。*
最後の `answer` 部分の記述に注目して下さい。  
関数`foo`に渡す際、 `&` をつけることで変数の参照渡しを行っています。もちろん関数`foo`側でも、受け取る値は参照県のものであることを方定義しています。  
このようにすることで、関数`foo`で変数 `v1`, `v2` を渡した後でも、そのままv1,v2は再利用することが可能です。  
  
# まとめ

- Vec<i32>を使うかわりに参照（&Vec<i32>）を使う
- v1とv2を直接渡す代わりに、 &v1 と &v2 を渡す
- &T 型は「参照」と呼ばれ、リソースを所有するのではなく、所有権を借用する
- 何かを借用した束縛はスコープから外れるときにメモリ上のリソースを割当解除しない
GAS 基本文法 備忘録④【トリガー】

## 備忘録です。

[GoogleAppsScript 完全入門](https://www.amazon.co.jp/dp/B07BNB1Z9L/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)で学んだことを備忘録としてまとめていきます。

- 自分が知っていることや、解説、今は必要ないなと思ったことは省いています。
- 解説などは自分が分かりやすい言葉で書いているので厳密に違うこともあるかもしれません。


## トリガーの種類
**シンプルトリガー**と**インストーラブルトリガー**の2種類がある。
この2つは使用できるイベントが異なるので注意が必要:comet:

### シンプルトリガー

**予め決められた関数名**でスクリプトを作成する。
簡単に設置できるが制限が厳しいので複雑なトリガーの設置には不向き。

```javascript
// スプレッドシート、ドキュメント、フォームを開いた時に実行
onOpen(e)

// スプレッドシートに変更があった際に実行
onEdit(e)

// 他にもonInstall(e)、doGet(e)、doPost(e)がある
```

#### 使用例

①関数の定義を行う。

```javascript:onOpen(e)の場合
// スプレッドシート起動時にメッセージボックスを表示させる
function onOpen() {
  Browser.msgBox('今日も一日楽しもう！');
}
```

②実行ボタンを押す。

<img width="438" alt="スクリーンショット 2020-08-06 10.32.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646383/29ea997e-bf99-e207-8e74-99237105dffd.png">


### インストーラブルトリガー
発動させるイベントの内容と関数を作成し、スクリプトエディタのメニューから設定をする。
関数名は自分で決めることができる。

```javascript
// スプレッドシート、ドキュメント、フォームを開いた時に実行
起動時

// スプレッドシートに変更があった際に実行
編集時

// 他にも値の変更時、フォーム送信時、時間主導型がある
```

#### 使用例
①関数を作成する。

```javascript:例
function message() {
  Browser.msgBox('今日も一日楽しもう！');
}
```

②スクリプトエディタのメニューから**編集** → **現在のプロジェクトのトリガー**を選択

③トリガーの追加を行う。

④トリガーで選択したタイミングで実行される。
<img width="393" alt="スクリーンショット 2020-08-06 10.52.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646383/862320d4-98fd-9a9b-5d0b-1af816967264.png">
ecsデプロイまで　[コマンドまとめ自分用]

```text:リージョンをセット(東京)
AWS_REGION=ap-northeast-1
```

```text:ECR中身を確認
aws ecr describe-repositories --region ${AWS_REGION}
```

```text:ECRログイン
aws ecr get-login --region ${AWS_REGION} --no-include-email

==>>docker login -u以下すべてをコピーする.
===>>>login successed!
```

ECRの該当リポジトリ内のpush commandを表示通り

```text:ECSクラスターで起動しているEC2インスタンスへ入る
ssh -i ~/.ssh/aws-and-infra-ssh-key.pem ec2-user@[EC2インスタンスのpublicIPかElasticIP]
```

```text:EC2内で起動しているdockerコンテナを確認
docker ps
docker ps -a
```

```text:docker ps -a を削除
docker ps -aq | xargs docker rm
```

```text:起動コンテナに入る
docker exec -it [起動コンテナID] /bin/bash
```

```text:データベース生成
rails db:create
rails db:migrate
rails db:migrate:reset
rails db:seed
```

```text:データベース作成中のエラーに対して
DATABASE_ENVIRONMENT_CHECK=1
これが出たら

RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake db:drop
```
たった10行でアウトプットすることの意義が理解できる記事

下記の画像をご覧ください
![20200806_113716.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83424/eeaf8ff6-35d5-e6a4-4f2c-4628bdfad415.jpeg)

私の手書きで恐縮ですが、これは『アンパンマン』です。

『アンパンマン』をご存じない方はすみません。この記事の対象外です。

『アンパンマン』を知っている方は、おそらく『ジャムおじさん』も知っていると思います。

それでは紙とペンを用意してください。（今風に言うとiPadとApple Pencilを用意してください）

では『ジャムおじさん』を何も見ずに描いてください。ググっちゃダメですよ！

・
・
・

描けましたか？

知識として『ジャムおじさん』を知っているだけの方は描けなかったのではないでしょうか？知っているだけではなかなか手は動きません。

描けた方は最近『ジャムおじさん』を描いた（アウトプットした）経験があるのではないでしょうか？

これがアウトプットをしている / していないの差です。
RUSTの変数と可変性について


# まえがき

この記事はRUSTチュートリアルをZerobillbank社内メンバー（有志）で勉強がてら、可能な限りわかりやすく内容を書き出す企画の一部です。

なお、初学者のため（略）という免責を打ちつつ間違いなどあればコメントで教えていただけますと一同嬉しく思います！

本項は変数と可変性について記載します。
https://doc.rust-jp.rs/book/second-edition/ch03-01-variables-and-mutability.html

# 変数と可変性

Rustの変数を宣言は標準で不変になります。

```rust
fn main() {
    let x = 5;
    println!("The value of x is: {}", x);
    x = 6; // ここでコンパイルエラー
    println!("The value of x is: {}", x);
}
```

上記のように一度値が名前に束縛されたら、その値を変えることはできません。
この仕組みにより値が予期せぬタイミングで更新されることを防ぎ、バグ発生のリスクが減りますね！

### 値を後から変更したい場合

とはいえ、変数を可変にすることは時に必要になるもの、、、
そういう場合は以下の通りmutをつけて宣言します！！

```rust
fn main() {
    let mut x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}
```

## 定数

変数は標準で不変と記載しました。
Rustでは変数とは別で「定数」もあります。

```
const MAX_POINTS: u32 = 100_000;
```

定数と変数には以下のような違いがあるようです。

- 値の型は必ず注釈しなければならない
- 定数はグローバルスコープも含めどんなスコープでも定義できる
- 関数呼び出し結果や、実行時に評価される値にはセットできない

## シャドーイング

前に定義した変数と同じ名前の変数を新しく宣言することができます。
新しい変数が前の変数を覆い隠すようなイメージになるようです。

変数名がそれほど重要でないコードを書くときなどに変数名をいちいち考えなくてすみそうなので便利ですね！

```rust
fn main() {
    let x = 5;
    let x = x + 1;
    let x = x * 2;

    println!("The value of x is: {}", x);
}
```

## さいごに


ZEROBILLBANKでは一緒に働く仲間を募集中です。
[ZEROBILLBANK JAPAN Inc.](https://zerobillbank.com/%e3%81%8a%e5%95%8f%e3%81%84%e5%90%88%e3%82%8f%e3%81%9b/)
BigQueryとスプレッドシートの連携でよくtimeoutするのでGASでどうにかしてみた

# 目的

 - [スプレッドシートとBigQueryの連携](https://qiita.com/yskur/items/a5a7984b0e9b6d65dfb3)は便利だが、期間が長いなど重いQueryはタイムアウトしてしまうことがある
 - そこでBigQueryでは最新1日分のみのデータを取得し、取得したデータをスプレッドシートに蓄積する形で実現する


# 大まかな流れ
1.BigQueryで前日分のみデータを取得
2.取得したデータをコピー
3.コピーしたデータを別シートの既存数値の下に貼り付ける
4.上記の流れをトリガーで毎日更新するように設定


# GAS詳細

```
function copy(){
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet_copyFrom = ss.getSheetByName('シート1'); //コピー元のシートを指定

　// コピー範囲取得
  var lr = sheet_copyFrom.getLastRow();
  var lc = sheet_copyFrom.getLastColumn();
  var copyRange = sheet_copyFrom.getRange(1,1,lr,lc); //取得開始位置を指定（1.1）=A1,(2,1）=A2となる。開始位置のみ指定したら、それ以降を全て自動で取得する。

  var sheet_copyTo = ss.getSheetByName('シート2'); //コピー先のシートを指定
  var lastRow = sheet_copyTo.getLastRow();
  var lastRow1 = lastRow + 1;

　// コピー範囲の値を取得し、対象範囲へ転記
　var copyValues = copyRange.getValues();
  sheet_copyTo.getRange(lastRow1,1,lr,lc).setValues(copyValues);

}

```


# 流れ
### 1.BigQueryと連携して前日分のみのデータを取得
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45434/df29a12b-e929-9712-e19d-2e5b6e251863.png)

### 2.GASを記載する
以下3点を変更する
- コピー元のシート名
- コピー開始位置
- ペーストするシート名


```
// コピー開始位置は取得開始位置を指定。（1.1）=A1,(2,1）=A2となる。開始位置のみ指定しそれ以降を全て取得する。
var copyRange = sheet_copyFrom.getRange(1,1,lr,lc);
```

### 3.この値がシート2の一番下にコピペされていることを確認する
<img width="822" alt="スクリーンショット 2020-08-06 14.41.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45434/98d3ba70-977a-ff78-0b0c-8e89230a8bdb.png">

### 4.トリガー設定をする
- 割愛

# おわりに
- GASが使えるとコスト削減にもなりますね
RUSTの所有権について

# まえがき

この記事はRUSTチュートリアルをZerobillbank社内メンバー（有志）で勉強がてら、可能な限りわかりやすく内容を書き出す企画の一部です。  
本項では、RUSTのキモとされる **所有権** の考え方について記したいと思います。
なお、初学者のため（略）という免責を打ちつつ間違いなどあればコメントで教えていただけますと一同嬉しく思います！

# 概要

RUSTでは変数を束縛するという考えがあるのは先述の通りですが、この `束縛する` という考えの元は定義した変数が所有権を持つことに由来します。  
本項では、所有権の概念と考えかたについて記載し、説明します。  

# RUSTにおける所有権という概念

全章で説明した変数束縛は、束縛されているものの「所有権をもつ」という考えを持っており、  
スコープ内でメモリが確保され、スコープを抜ければそのメモリは解放される特徴を持ちます。  

```rust
fn foo() {
    let v = vec![1, 2, 3];
}
```

上記の例で言うとこのような動作になります。  

1. v がスコープに入るとき、新しい Vec<T> が作られる。  
2. さらにベクタは3つの要素のために **ヒープ（メモリ）** に空間を割り当てる。  
3. foo() の最後で `v` がスコープから外れるとき、Rustはvのベクタに関連するもの全てを取り除く。  

# ムーブセマンティック

RUSTの所有権は、メモリの確保、及び開放の他に **リソースに対する束縛は一つである** ということを保証します。  
例えば以下のようなコードはエラーになります。  

```rust
let v = vec![1, 2, 3];
let v2 = v;
println!("v[0] is: {}", v[0]);   // -> Error!
```

上記の例では v で束縛していたvectorは、次の行でv2に所有権がうつっています。  
そのため、3行目で v を呼び出そうとしても、v のメモリ空間は解放されているためエラーが発生します。  
  
また、所有権の移り変わりは変数名の変更意外にも、 **関数へ渡した際にも所有権は移ります**。  

```rust
fn take(v: Vec<i32>) {
}

let v = vec![1, 2, 3];
take(v);
println!("v[0] is: {}", v[0]);   // -> Error!
```

RUSTでは、 **所有権を何か別のものに転送（付け替え）たとき、「ムーブした」と言う** みたいです。

# Copy trait

Rustの所有権、それから所有権の移動について説明をしてきました。  
続いて、変数の所有権をそのままに変数をコピーし参照を行うCopy traitについて説明します。  
  
すでにコンパイラ側に実装されており自動で適用されてしまうため例としては不適切（わかりにくい）かもしれませんが、  
以下のように `i32` 型はcopy traitがコンパイル時に自動で補完（実装）されるためエラーになりません。  
  
```rust
let v = 1;
let v2 = v;
println!("v is: {}", v);
```

`i32` だけではなく、プリミティブ値は全てcopy traitが自動実装されるため所有権の移行は適用されません。  

# 所有権を返却する

例えば変数を受け取って、その変数を処理したあとに変数をそのまま返却する関数を実装したとします。  
  
```rust
fn foo(v: Vec<i32>) -> Vec<i32> {
    // vについての作業を行う

    // 参照したvを返却
    v
}
```

上記のように実装することで、変数の所有権をそのまま返却することが可能です。
Elasticsearchで"all shards failed"がでるようになったらmax_open_files設定をうたがってみる

最近何度か開発環境のElasticsearchで"all shards failed"が発生してたんですが、Vagrant終了させずにホストを再起動したっけ？ぐらいにしか思わず、vagrant snapshot restoreでしのいでたんですが、かなり頻発するようになってきたので対処法しらべてみました。

```/var/log/elasticsearch/elasticsearch.log``` を確認してみると下記の様に "Too many open files" ってログが残ってました。


```
 at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]
Caused by: java.nio.file.FileSystemException: /var/lib/elasticsearch/nodes/0/indices/TQgoFaQTT3ijwfBVxYiMFA/3/translog/translog-163.ckp: Too many open files
```

ぐぐってみると max open filesの制限にかかるとこんなログがでるようなので、この制限値をあげてみることに。

現在の設定値の確認は下記で。

```
$ curl -XGET "http://localhost:9200/_nodes/stats/process?filter_path=**.max_file_descriptors"
```

でもってどこで設定変えればいいのかがよくわからなくて散々はまりました^^;
```/etc/init.d/elasticsearch``` で設定って記事があったり、 ```/etc/security/limits.conf``` で設定って記事があったり…

それらを書き換えても全然反映されなかったんですが、```systemctl status elasticsearch``` したら設定ファイルの位置がちゃんと出力されてました

```
$ # systemctl status elasticsearch
● elasticsearch.service - Elasticsearch
   Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; enabled; vendor preset: disabled)
```

このファイルを直接いじって反映されたんですが、 [systemd で ulimit 上げるときの推奨の方法](https://blog.kteru.net/systemd-ulimit-tips/)　って記事を発見したのでこれにならって ```/etc/systemd/system/elasticsearch.service.d/max_open_files.conf``` ってファイルを作成して ```LimitNOFILE```を設定しました。

```/etc/systemd/system/elasticsearch.service.d/max_open_files.conf
[Service]
LimitNOFILE=655360
```

これでElasticsearchを再起動したら"all shards failed"が解消できました。
AWS-SAA試験勉強メモ2

###クラスタープレイスメントグループ
単一AZ内のEC2インスタンスを論理的にグループ化したもの。
メリット

- 10Gbpsのフロー制限
- 非ブロッキング
- 非オーバーサブスクライブ

**=プレイスメントグループ内のすべてのノードは、すべてのプレイスメントグループ内の他のノードと対話可能**

###Polocy Validator
自動でIAMアクセスコントロールポリシーを調べてIAMポリシーの文法に準拠していることをチェックする。
確立されたポリシー構文に準拠しないポリシーを保存することは不可。

###EC2インスタンスの誤削除防止

- 有効化方法（コンソール）

|状態|方法|
|:-:|:-:|
|起動時|Enable termination protection|
|実行中or停止中|Change termination protection|

- 有効化方法（コマンド）

|サービス|コマンド|
|:-:|:-:|
|AWS CLI|modify-instance-attrinute|
|AWS Tools for Windows PowerShell|Edit-EC2InstanceAttribute |


###ネットワークACLのルール番号評価
ルールは低い番号から評価される

###EBSのステータスチェック

|ステータス|意味|
|:-:|:-:|
|ok|想定通りのパフォーマンス|
|warning|想定よりパフォーマンスが低下|
|impaired|パフォーマンスが致命的に低下 or I/Oが無効|
|insufficient-data|ステータスチェック中|

###オンプレの仮想マシンイメージのEC2への移行
**VM Import/Export**という機能を使用する

ただし、LinuxのImportでは、Importがサポートされるインスタンスタイプ制限がある
※Windowsでは任意のインスタンスのインポートに対応

###EC2未対応LinuxOS

- 32bit版全般
- RHEL6.0

###VMインポート時注意事項

- 事前にNET Framework3.5 SP1の事前インストールが必須
- NTPサーバーとの時刻同期
- DHCPの有効化（VMImportで固定IPの取得は不可）
【RaspberryPi】PythonのデフォルトをPython3に変更

#はじめに
検証のため、会社でRaspberryPi zeroを購入し、セットアップしていました。
作成してあったPythonスクリプトを実行すると挙動がおかしい。

確認せず実行している私も悪いですが、実行バージョンが2.7じゃないですか。
3.7が入っていることを確認していたので、そいつを実行していると思い込んでいました。

備忘録として変更方法を記事にします。

#デフォルトをPython3に！
##バージョン確認

```shell
python --version
```
ここで3系なら終わりです。私は2系なので続けます。

##シンボリックリンク確認

```shell
ls -l /usr/bin/py*
```
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592737/81500321-0b94-6357-bd11-a28cafb26077.png)

pythonは**python2.7**を使っていることがわかります。
**リンクをPython3に変えてあげれば解決！！！**

##シンボリックリンク解除
```shell
unlink python
```
これでまずpythonが参照していたpython2へのリンクが解除。

##シンボリックリンク設定
```shell
ln -s python3 python
```
python3を参照するpythonのシンボリックリンクを作成。![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592737/eea980f9-73a6-6e92-0acc-3bb83a3bcdb9.png)
ちゃんとリンクができていることが確認できます。

再びPythonのバージョンを確認して変更できていれば成功！！！
（今回の場合、Python3.7.3になっています）

#最後に
こういう細かいこと（私的に）はすぐに忘れてしまう特性があります。
特に環境設定でどうやるんだっけか？となって、何度も同じことを調べている自分が。。。

一人でやっていると疎かになりがちなので、気を付けようと思う今日この頃。。。
nginx sockets通信 ecsデプロイ 「簡単ログインなど挙動がおかしい」

sshでサインイン
ec2に入る
docker ps
起動しているappコンテナに入る
docker exec -it [] /bin/bash
ls log/production.logを拝見

```HTTP Origin header (https://hoge.com) didn’t match request.base_url(http://hoge.com)```
エラーを発見

[2017だけど、aws elb使用時のacm発行したssl（HTTPS化）についての的確な解説](https://teratail.com/questions/93457)

[結局nginx.confを設定して、port80をlistenする記述をしないと](https://kitsune.blog/nginx-rails)

[X-Forwarded-Protoについて](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Forwarded-Proto)
転送されたプロトコル (http または https).を含める

```nginx
# プロキシ先の指定
# Nginxが受け取ったリクエストをバックエンドのpumaに送信
upstream app {
    # ソケット通信したいのでpuma.sockを指定
  server unix:///app/tmp/sockets/puma.sock;
}

# httpでのアクセスはhttpsにリダイレクトさせる
# serverからhttpに変更
server{
  listen 80;
# ドメインを指定
  server_name sss.red-miso.work;

  access_log /var/log/nginx/access.log;
  error_log  /var/log/nginx/error.log;

# ドキュメントルートの指定
  root /app/public;

  client_max_body_size 100m;
  error_page 404             /404.html;
  error_page 505 502 503 504 /500.html;
  try_files  $uri/index.html $uri @app;
  keepalive_timeout 5;

  location @app {
    proxy_read_timeout 300;
    proxy_connect_timeout 300;
    proxy_redirect off;
    proxy_set_header Host $host;
    #$http_x_forwarded_protoに変更する。
    proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # 上記server_name で設定した名前で指定
    proxy_pass http://app;
  }
}

```
RealmSwiftのMigration

個人での開発中に、モデル定義を変更したところ、マイグレーションしてくれというエラーが出たため、備忘録として残しておきます。

## マイグレーションとは
モデルの定義を変更したときに、データを保持したまま新しいモデル定義に適応させることをいいます。

# サンプル

## エラー
[Realm公式](https://realm.io/docs/swift/latest/#migrations)に載っているコードで説明します。
すでに定義されている下記のモデルを変更してみます。

```swift
class Person: Object {
    @objc dynamic var firstName = ""
    @objc dynamic var lastName = ""
    @objc dynamic var age = 0
}
```
以下のように変更しました。

```swift
class Person: Object {
    @objc dynamic var firstName = ""
//ここを消しました
    @objc dynamic var age = 0
}
```
マイグレーションの設定を行わず、これでシュミレーターを起動すると、下記のようなエラーが出て、うまく起動しません。

`Error Domain=io.realm Code=10 "Migration is required due to the following errors:
(エラー文以下省略)`

## 解決策

AppDelegate.swiftのdidFinishLaunchingWithOptionsの部分で、マイグレーションに関する記述をしていきます。公式のコードを参照。

```swift:AppDelegate.swift
// Inside your application(application:didFinishLaunchingWithOptions:)

let config = Realm.Configuration(
    // Set the new schema version. This must be greater than the previously used
    // version (if you've never set a schema version before, the version is 0).
    //(訳)新しいスキーマのバージョンを設定。以前使っていたバージョンよりも高くなければいけない。これまでバージョンの設定をしていなければ、初期のバージョンの値は0。
    schemaVersion: 1,

    // Set the block which will be called automatically when opening a Realm with
    // a schema version lower than the one set above
    //(訳)上記のものより低いスキーマバージョンでrealmを開くときに、自動的に呼び出されるようにブロックの設定をする。
    migrationBlock: { migration, oldSchemaVersion in
        // We haven’t migrated anything yet, so oldSchemaVersion == 0
//(訳)まだマイグレーションを行っていないので、oldSchemaVersion == 0。
        if (oldSchemaVersion < 1) {
            // Nothing to do!
            // Realm will automatically detect new properties and removed properties
            // And will update the schema on disk automatically
//(訳)Realmは新しいプロパティと削除されたプロパティを自動で検知します。そして、自動でディスク上のスキーマを更新する。
        }
    })

// Tell Realm to use this new configuration object for the default Realm
//(訳)default Realmに対して、新しい設定オブジェクトを使うように、Realmに指示する。
Realm.Configuration.defaultConfiguration = config

// Now that we've told Realm how to handle the schema change, opening the file
// will automatically perform the migration
let realm = try! Realm()

```

最低限、スキーマがRealmによって（自動的に）アップグレードされたことを示すために、空のブロックでバージョンを更新する必要がある。

## まとめ
自分は、開発の環境で、モデルの変更を行ったらschemaVersionを変更してあげています。
間違えているところがあれば、ご指摘いただけますと幸いです。
ElixirでBigQueryを操作するツールを作った

ElixirでBigQueryのスキーマの管理も含めて色々したかったのですが、欲しいと思ったときに良さげなツールを見つけることができなかったので自分で作りました。
なのでこちらでちょっと紹介させて下さい。

## つくったもの
* [github.com/gr8distance/blanton](https://github.com/gr8distance/blanton)
* [hex.pm/packages/blanton](https://hex.pm/packages/blanton)

## 使いかた

### 準備
* 最初に以下の設定が必要です

```elixir
# mix.exs
def deps do
  [
    {:blanton, "~> 0.1.3"}
  ]
end
```

```elixir
# config/config.exs
config :goth,
  json: "path/to/google/json/creds.json" |> File.read!

config :blanton,
  project_id: "PROJECT_ID",
  dataset_id: "DATASET_ID"
```

### テーブルを作成する

* 最初にlib/に適当なディレクトリを作成しておく
* 以下のようなファイルを作成する

```elixir
# lib/APP_NAME/bq_schema/TABLE_NAME.ex

defmodule APP_NAME.BqSchema.TABLE_NAME do
  # ↓をuseする
  use Blanton.Schema

  # schemaマクロの中にテーブルの定義を書いていく
  schema :TABLE_NAME do
    field :column_name, :string, :required
    field :some_field_column, :record, :repeated, [
      sub_field(:name, :string, :nullable),
      sub_field(:price, :int64, :nullable),
    ]
  end

  # Table作成時に指定するオプションはこっちに指定する
  # options do
  #   partitiondate
  #   register :timePartitioning, %GoogleApi.BigQuery.V2.Model.TimePartitioning{type: "DAY"}
  # end
end
```

* ファイル作成後に `mix bq.migrate PATH/TO/SCEHMA_DIR`を実行するとBigQuery上にテーブルが作成されます。
  * `mix bq.migrate.drop`を実行すると容赦なくテーブルが削除されます


### レコードを挿入する

* 事前に挿入するデータをMapの配列で用意します。
* `Blanton.Record.insert("TABLE_NAME", records)`で挿入できます

```elixir

records = [
  %{name: "安室透", age: 29},
  %{name: "赤井秀一", age: 32},
]

table_name = "users"
Blanton.Record.insert("PROJECT_ID", "DATASET_ID", table_name, records)
Blanton.Record.insert(table_name, records)
```

## レコードの検索機能が無い

* このツールが必要になったときSELECT文を発行する予定が無かったので現時点(2020/8/6)ではSELECTはできません :bow: 
  * ただし近々対応する予定です。


## おまけ #1
誰でも使えるパッケージを書いたのが実は初めてなのでわからんところを調べながら実装しました。
Elixirらしくないところも多分に含んでいると思いますがhex.pmに公開するところまでなんとか持っていくことができました。
すでに自分では他のリポジトリでも利用していますが、私以外にも何人かの方がどうやらダウンロードしてくれているようなので大変うれしく思います。
バグとかまずい所見つけたとか機能追加したとかありましたらPRいただけると幸いです。 :bow: 

## おまけ #2

Elixirでライブラリを探すとき、Rubyなどの言語だとググると思うんですがElixirだと出てこないときがあります。
そういう時は[hex.pm](https://hex.pm)で検索してみるのがおすすめです！
gRPCとは

## RPCとは
RPCはRemoteProcedureCallの略で、逐語的に訳すと「遠隔手続き呼び出し」となります。
すなわち、「あるプログラムがネットワーク上の異なる場所に配置されたプログラムを呼び出して実行すること」を指します。
あるサービスから別のサービスのアプリケーションの処理（サブルーチン/クラス/関数など）を呼び出すことができ、RPCを使うことで、違うアプリケーションのロジックを、あたかも自分のアプリケーションの中に実装されているかのように扱うことができます。
gRPC以外にも「JSON-RPC」や「SOAP」なども。


## gRPC
Googleが2004年に作ったはGoogleの各マイクロサービス間のRPC、「Stubby」を起源とし、http/2などの規格登場に合わせて汎用的に作り直したオープンソースのプロダクト。

## REST-APIと比べた時のgRPCの利点

#### **HTTP/2による通信の高パフォーマンス**
  - HTTP/2では通信時にデータがテキストではなくバイナリにシリアライズされて送られます。そのため、小さな容量で転送でき、ネットワーク内のリソースをより効率的に使用することができます。また、HTTP/2ではストリームを使い、ひとつのコネクションで複数のリクエスト/レスポンスをやり取りできます。つまり、リクエスト/レスポンスの度にデータを接続、切断を繰り返す必要がなく、その都度ヘッダーを送らなくて済むので、高速で効率的な通信が可能となります。
特にマイクロサービスでは通信の回数が多くなり、応答速度の遅延がサービス全体のボトルネックになりがちなので、これを解決できます。

#### **Protcol Buffersでのスキーマファーストの開発により生産性が高い**
  - gRPCではProtocolBuffersのフォーマットにシリアライズ/でシリアライズしてリクエストレスポンスでデータをやり取りします。.protoファイルにスキーマを書いて、コンパイラを実行すると任意の言語のサーバー/クライアント用コードを自動生成してくれます。
この.protoファイルを見ると、APIの仕様が分かるので、API側、クライアント側で担当が違うような状況でも開発ができて便利だし、間違いが起きにくいです。

#### **柔軟なストリーミング方式**
 - *シンプルなRPC* 
  - クライアントから送られたひとつのリクエストに対して、レスポンスを一度返すもっとも基本的な形式
 - *サーバーストリーミングRPC* 
  - クライアントから送られたリクエストに対して、レスポンスを複数回に分けて返します。時間のかかる処理について、非同期的にレスポンスを返すことができます。クライアントからのリクエスト後、クライアントは待機状態とし、サーバーの状態変更に応じて、情報を随時プッシュしていくこともできます。通知やタイムラインのリアルタイム更新などに有効。こういった場合仮にストリーミング機能使えない場合、クライアント側から定期的にポーリングで情報を引っ張らねばならず無駄な通信が発生してしまうのに比べ、サーバストリーミングPRCは、サーバから直接情報をプッシュできるのでネットワーク負荷を最小化できます。
 - *クライアントストリーミングRPC*
  - クライアントからリクエストを分割して送り、サーバーは全てのリクエストを受け取る前に処理を逐次開始できる方式。
 - *双方向ストリーミングRPC* 
  - クライアントから初めのリクエストが送られた後、サーバー・クライアントどちらも任意のタイミングでリクエスト・レスポンスを送ることができます。チャットやゲームなどに有用です。RESTAPIではストリーミングが行えないので、WebSocketサーバーを別途立てる必要などがありました。gRPCの場合、単一のサーバーで双方向通信のAPIとしても使えます。


## REST-APIと比べた時のgRPCの欠点

#### HTTP/2非対応である危険性
 - 例えばAWSのALB（ApplicationLoadBalancer）はgRPCに対応していません15。フロントでHTTP/2のリクエストを受け付けることはできますが、バックエンドのサーバーへの転送をHTTP/1で行うためです。同様に通信経路上でHTTP/2に非対応なサービスがある場合に、gRPCを使う上で問題が生じる場合があります。

#### ブラウザの対応状況が不十分
 - gRPCWebなどはあるものの、Envoyなどを使ってProxyサーバーを立てる必要があったり、双方向あるいはクライアントストリーミングRPCに非対応であるなど、まだまだ十分な対応状況とはいえないようです18。フロントエンドのアプリケーションとの通信に使うには少し工夫が必要です。SPAとの通信にはRESTAPIの方が、JSONとの親和性の高さもあり良いかもしれません。


#### バイナリにシリアライズすると人間が読めない
 - JSONの場合は出力を人間が直接読めますが、gRPCの場合は専用のクライアントをインストールする必要があります。

#### RESTでも通信速度が十分な場合も
 - 基本的にgRPCは　RESTよりもミニマムで高速な通信が可能ですが、RESTもそれなりに早く、ボトルネックが通信以外にある場合はそもそも通信速度の優位性は役に立ちません。
syntax errorその２

syntax errorについては前に書いていましたが、
endがきちんと記載されているのにもかかわらず同じくsyntax errorが起きてしまいました。

というのも、
class ****
 def "****" ←の「"（半角）」が「”（全角）」
  end 
end

になっていたので、
”が文字と見なされてしまい文字が終了していない認識になり、
"end"も文字になってしまった結果、endがないというsyntax errorになりました。

同じsyntax error でも中身が多種多様であることを
学ぶことができたエラーでした！
wsl2のXserverで日本語キーボードレイアウトにする

# 構成

- wsl2(Ubuntu 20.04)

## キーボードレイアウトの変更

```
sudo dpkg-reconfigure keyboard-configuration
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/08cb77eb-4c61-e03e-6b33-ec471f6ab66e.png)


## mozc

- Google製の日本語入力システム

```
sudo vim /usr/share/ibus/component/mozc.xml
```

```
<layout>ja</layout>
```