OmniAICreator/Qiita-1.07M huggingface dataset:
はじめてのPostgreSQL

# この記事が対象とする読者
- PostgreSQLをはじめて使う人

`Homebrew`を使ったインストールの仕方を簡潔にまとめます。

# インストールの流れ
## 1. ターミナルからインストール

まずは、以下のコマンドを入力・実行します。

```ターミナル
$ brew install postgresql
```

## 2. インストールの確認

正常にインストールできているかどうかを確認します。
バージョンを表す`-V`は大文字なので注意です。

```ターミナル
$ postgres -V
postgres (PostgreSQL) 11.5
```

## 3. PostgreSQLを起動

データベースとして使用するためには以下の起動のコマンドも必要です。

```ターミナル
$ brew services start postgresql
==> Successfully started `postgresql` (label: homebrew.mxcl.postgresql)
```

ここまで完了すればデータベースが作成できるようになるはずです！

# さいごに
PostgreSQL初心者による初心者のためのQiitaでした。
簡単な工程なのですが、検索しながらやっていたら迷ってしまったので共有しておきます。少しでも参考になればうれしいです。
JavaScriptの記述と行った動作確認

## JavaScriptの記述について
JavaScriptはHTML上では

```html:html
<script>
   //ここに記述します
</script>
```

外部ファイルから出力する場合は

```html:html
<script src="example.js"></script>
```
そして外部ファイルにexample.jsを用意してそこに記述。


## JavaScriptサンプルコードを用いての動作確認

```html:html
document.write(`Hello`);
document.write(`<h1>Hello</h1>`);
```
`実行結果:Hello`
`実行結果:h1としてHelloを表示してくれる`
ページ上に文字を出力。

```html:html
<p id="example">Hello</p>
<script>
    console.log(document.getElementById("example"));
</script>
```
`実行結果:<p id="example">Hello</p>`
exampleをIDとして取得し、exampleが含まれているpタグ全体をコンソールに表示。
classの場合はgetElementByClassNameを使う

```html:html
<p id="example">Hello</p>
<script>
    console.log(document.getElementById("example")textContent);
</script>
```
`実行結果:Hello`
一つ前の例のテキストだけを取得し、コンソールに表示。

```html:html
<p id="example">Hello</p>
<script>
    console.log(document.getElementById(`example`).innerHTML);
</script>
```
`実行結果:Hello`
HTMLで動作するのと一緒の内容でidを取得してくれる

```html:html
<div id="example"></div>
<script>
    const box = document.getElementById('example');
    box.innerHTML = '<p>Hello</p>';
</script>
```
`実行結果:Hello`
空要素のdivの中に新たにp要素を出力している。


## 補足事項
- documentとはWebページを構成しているHTMLソースそのもの
- innerHTMLとtextContentの違いはinnerHTMLはタグをHTMLとして解釈してくれる。
　一方でtextContentはテキストの内容を表示するだけ。
  テキストの内容だとわかっていればtextContentを使ったほうがいい。
【Unity】作成したゲームをWebで公開する方法

#手順


##WebGL形式でビルドする。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505426/2ee7f41e-6b72-bc75-d205-95dd9197844e.png" width=50%>
- File ->  Build Settings -> PlatformでWebGLを選択する。
- 「Scenes In Build」に必要なシーンをドラッグアンドドロップする。
- WebGLのインストーラがない場合、「Open Download Page」のボタンを押下し、落としたインストーラを実行する。
- 「Player Settings」を選択する。
- 「Development Build」はチェックしない。（エラーを見るための機能が付随されるらしいが、その分容量も大きくなる。)
- 「Build」でビルドする。（場合によってはCPUが100%近くなるが辛抱強く待つ。)

##Web上にプロジェクトをアップロードする。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505426/d6a412ba-0a24-44bf-1ac4-966fb28dd8be.png" width=80%>

- GitHubで新しいリポジトリを作成する。
- 新しいブランチ「gh-pages」を切る。
- ブランチ「gh-pages」に出力ファイルを追加。
- コミット&プッシュする。
- URL「https://ogawa-to.github.io/"リポジトリ名"/"出力フォルダ名"」でアクセスする。

##参考サイト
[UnityのWebGLで書きだしたゲームをGitHubを使って公開する]
(https://qiita.com/iwaken71/items/c32760e1cc2ba01e8f9a)
[公式ページ : Building and running a WebGL project]
(https://docs.unity3d.com/2018.3/Documentation/Manual/webgl-building.html)
我々はなぜ監視を行うのか【第二章】～監視システムチューニング編～

# はじめに

【前回】→ [我々はなぜ監視を行うのか【第一章】～監視システム導入編～](https://qiita.com/taro-hida/items/7b47bf61c28313b29980)

# 【第二章】～監視システムチューニング編～
監視システムを導入したことで、担当者Aは既存の業務から解放され、やや余裕をもって仕事をすることができるようになった。
Aは監視システムに興味と好意が生じ、監視システムについて色々と調べるようになった。

---

監視には以下の4要素がある
※ [監視論](https://qiita.com/qryuu/items/c55b1e8c472eb716f616) by @qryuu氏から引用

>収集
対象システムやセンサー、ネットワーク機器等からデータを集める。
CPU使用率やメモリ使用率、ディスク情報やネットワーク負荷
ログ情報や環境データの収集を行う。

>標準的なプロトコルやAPIにより監視ツールなどにデータ提供を行う対象システムや
監視システム独自Agentによって対象システムからデータ収集を行う場合のほか
対象システム自身の状態確認コマンド、統計コマンドにより出力される情報をスクリプトやAgent等により収集する場合もある。

>判定
収集により集められたデータに対して、正常・障害/ノーマル・アラートなどの判定を行う。
収集された生データを使う場合もあれば、生データに対して何らかの算術処理を行った後のデータに対して判定を行う場合もある。

>判定では、「イコール/ノットイコール」や「含む/含まない」、「以上/以下（超過/未満）」
などにより、数値判定、文字列判定を行う。
文字列判定では正規表現が用いられる場合もある。

>通知
判定結果を元に通知を行う通知を行う対象は必ずしも人間である必要は無い。
通知対象として、APIやシステムコマンド、監視対象機器の制御コマンドを通知先とすることによりシステムの自動復旧や、自律動作を可能とすることができる。

>全ての判定結果を通知する必要はない。
対人通知を行う意義ある通知は、その通知を元にDR発動やメンテナンスページ切り替えなど
通知を受けた人物の 決断 が必要な場合である。

>経緯把握ための通知であればリアルタイムで深夜や業務時間外にプライベートを侵食して通知しても価値はなく、心理的に監視システムに対する嫌悪感を煽るのみである。

>意義ある通知設計は監視サービスや監視システムが『オオカミ少年』とならないための重要な要素である。

>分析
収集されたデータや判定の頻度を元にシステムの現状、および将来状態を推測、検討します。
分析では、リソースの時系列的な変化や異なる収集データ同士の相関関係などを読み取る事が重要となる。
適切な分析を行う事で、システムのボトルネックポイントの判断や、ボトルネック対策を行った場合のボトルネック推移の予測、インフラコストの最適化提案などが可能となる。

>分析で重要となる能力は経験による勘ではなく、コンピュータサイエンスの正しい知識である

......。
大事なことのように思えたが、担当者Aには、難しくてまだわからなかった。[^1]

しかしそのまましばらく仕事をしていると、以下のような事象に悩まされるようになった。

- 夜中にアラートが上がって、通知でたたき起こされる。慌てて画面を確認すると、一時的に2秒ほど画面が見れなくなっていただけであり、
すでに復旧していた（ページは見れるようになっていた）

Qiitaのトップページが2秒ほど見れなくなっても、そこまでユーザへの影響はない。
そもそも、Aが起き出して対応するまでにどうしても1分ほどかかる。2秒で復旧させるのは無理だ。

【第1章】のシナリオで出てきた通り、Aは監視設定について、「監視間隔は1秒、一度でも検知したら即異常」という判定を入れていた。
だが、この設定ではいわゆる「誤検知」が発生している。

Aの基準では、「数秒程度ページが見れなかった」というのは「問題がない」という判断基準になる。
だがシステムは、「1秒でもページが見れなかった」という状態を「異常」と判断してしまう。

これは監視システムがポンコツなのではなく、監視システムにAが判断基準を正しく伝えていないことにより発生している問題である。

Aは監視設定を調整し、「監視間隔は10秒、かつ60秒(1分間)継続してページが閲覧できなくなっていた場合にアラートを上げる」という設定に監視設定を調整した。

監視システムを調整したことによりアラートは減り、Aは不要不急のアラートにたたき起こされることがなくなった。
Aは満足した様子で、以前より更にぐっすりと眠れるようになった。

# まとめ

- 監視システムにおけるチューニングの重要性

適切に条件を設定することにより、本当に異常である場合にのみアラートを発生させることができる
（[監視論](https://qiita.com/qryuu/items/c55b1e8c472eb716f616)における『判定』の要素である）

- 不要不急の通知は、極力出さないようにする

通知設計が監視設計の一つの肝であると考えている。
今回のように不要不急の通知は、極力出さないような監視設定とする。

今回の監視設定のチューニングは、【第一章】で説明した以下の価値をより高めるものとなる
> 人力による24/365の目視等を行わなくても、システムがそれを代行し、人間は異常がある状態を検知した時だけ対応すればよくなる


# あとがき

現状のAの監視設定も、まだ理想的なものではない。

【次回】-> [我々はなぜ監視を行うのか【第三章】～自動復旧編～](https://qiita.com/taro-hida/items/504ca17c1874e15b188d)

[^1]: 非常に大事なことですので、皆様は一度リンク先を一読しご理解ください。本連載は「[監視論](https://qiita.com/qryuu/items/c55b1e8c472eb716f616)」の記載をベースに進めます。
[ゼロから作るDeep Learning]ディープラーニングの起源 ~パーセプトロン~ を分かりやすく解説してみた

# はじめに
この記事は現在自分が勉強をしている技術書、**ゼロから作るディープラーニング 3章パーセプトロン**を自分なりに理解してアウトプットしたものです。
文系の自分でも理解することができたので、難しく考えずに楽にみていただけたら幸いです。
さらに、本書を進めるにあたって参考にしていただけたら嬉しいです。

# パーセプトロンとは

パーセプトロンとは、複数の0または１の入力信号を受け取り、その合計がある規定値を超えた場合に１を出力してそれ以外の場合は０を出力するアルゴリズムです。
<img width="545" alt="スクリーンショット 2019-10-11 13.10.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510602/407a1e87-c897-bcc2-4ff6-662c28a8a3fa.png">

規定値を設定して入力信号を受け取り出力信号に変換する上の四角い箱を**ニューロン**と言います。さらに規定値のことを**闘値**と言います。

次は今の内容を少し詳細にして解説しようと思います。
各入力信号はニューロンに向かう途中に各自に設定された**重み**がかけられます。重みや闘値をパーセプトロンの**パラメータ**と言い、このパラメータがパーセプトロンにとって一番重要な値になります。
重みがかけられた入力信号たちがニューロンに集まり総和(合計)され、その総和が設定した闘値を超えたら１出力して超えられなければ０を出力します。
<img width="554" alt="スクリーンショット 2019-10-11 13.28.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510602/363f3d8a-7bc5-bc72-25e4-52aa9087769b.png">

これをPythonコードで表すと下のようになります。

```python
import numpy as np
def perceptron(X):
    x = np.array([0,1,1,0,1]) #入力信号
    w = np.array([0.3,0.7,1.4,0.5,0.3])#重み
    xw = x*w
    Y = x.sum() #ニューロンの役割
    if Y > X:
        return 1
    elif Y <= X:
        return 0

print(perceptron(2)) #闘値が２の場合
1
print(perceptron(3)) #闘値が3の場合
0
```

少し詳細に解説しましたが、プログラミングを勉強したことがある人なら理解することは簡単だと思います。


今回はパーセプトロンを解説してみました。このパーセプトロンがなぜディープラーニングの起源と呼ばれているかなどは次回以降に解説しようと思います。
[python]numpyの使い方まとめ

#はじめに
NumPyとは、数値計算を効率的に行うための拡張モジュールである。NumPyの内部はC言語 (およびFortran)によって実装されているため非常に高速に動作する。
※純粋にPythonのみを使って数値計算を行うと、ほとんどの場合C言語やJavaなどの静的型付き言語で書いたコードに比べて大幅に計算時間がかかる。
[NumPy - Wikipedia](https://ja.wikipedia.org/wiki/NumPy)

#導入など

・インポート
下のようにインポートすることでnumpyのライブラリを使うことが出来るようになる。

```python
import numpy as np
```

#線形代数系機能

・ベクトル
ベクトルと行列は異なるものとされている。ベクトルには列、行どちらの方向かの区別がない。

```python
x = np.array([1,2,3])
```

・行列

```python
A = np.array([[1,2],[3,4],[5,6]])
```

・ベクトル(行列型)
行ベクトル、列ベクトルのどちらか明示的に指定できることが利点。


```python
x1 = np.array([[1,2,3]])
x2 = np.array([[1],[2],[3]])
```

・行列の積

```python
A = np.array([[1,2],[3,4],[5,6],[7,8]])
B = np.array([[1,2,3],[4,5,6]])
C = np.dot(B,C)#D=BC
```

・行列の各成分に対して四則演算
乗算のことはアダマール積という。
行列をA=(aij),B=(bij),C=(cij)とすると、加減乗除の計算はそれぞれ以下の計算に対応する。
(cij)=(aij+bij)
(cij)=(aij-bij)
(cij)=(aij*bij)
(cij)=(aij/bij)

```python
A = np.array([[1,2],[3,4]])
B = np.array([[5,6],[7,8]])
#加算
C = np.add(A,B)      # C=A+B でも可
#減算
C = np.subtract(A,B) # C=A-B でも可
#乗算(通常の行列の積の意味で使わないように注意)
C = np.multiply(A,B) # C=A*B でも可
#除算
C = np.divide(A,B)   # C=A/B でも可
```

・剰余

```python
md = np.mod(13,3) # md = 10 % 3 でも可
# 1が出力(12/3 = 4あまり1)
```

・行列の転置
(aij)が転置後は(aji)となっている。

```python
A = np.array([[1,2],[3,4],[5,6]])
t_A = A.transpose()
```

・ベクトルの内積
内積はドット積とも言われる。numpyではnp.dotを使う

```python
v1 = np.array([1,2])
v2 = np.array([3,4])
ip = np.dot(v1,v2)
```

・ベクトル(行列型)の内積
v1,v2が縦ベクトルならこれらの内積をとる時、内積は(v1の転置)v2という行列の積で表せる。

```python
v1 = np.array([[1],[2]])
v2 = np.array([[3],[4]])
ip= np.dot(v1.transpose(),v2)
```

・クロス積(2ベクトルに直交するベクトルを生成する：外積)

```python
v1 = np.array([1,2,3])
v2 = np.array([1,3,5])
v3 = np.cross(v1,v2)
```

・テンソル積
要素をすべての組み合わせで掛け合わせたもの(戻り値は行列)

```python
v1 = np.array([1,2,3])
v2 = np.array([1,3,5]) # 行ベクトル(行列)でも可

v3 = np.outer(v1,v2)
```

・ブロック行列の作成
行列をnp.arrayと同じような記述でくっつけることが出来ます。
列ベクトルを三つ並べて[v1,v2,v3]みたいにやりたいと思ってこれを見つけたときは心が躍りました。

```python
A  = np.array([[0.71,0.71],[-0.71,0.71]])
o  = np.array([[0],[0]])
t_o= o.transpose()
i  = 1
#[  A,o]
#[t_o,i]のような行列を作りたい
M = np.block([[A,o],[t_o,i]])
```

・行列式

```python
A = np.array([[1,2],[3,4]])
d = np.linalg.det(A)
```

・逆行列

```python
A = np.array([[1,2],[3,4]])

inv_A = np.linalg.inv(A)
```

・行列の累乗

```python
A = np.array([[1,2],[3,4]])
A5 = np.linalg.matrix_power(A,5)
```

・固有値、固有ベクトル

```python
A = np.array([[1,2],[3,4]])
(eig_val,eig_vec) = numpy.linalg.eig(A)
```


#定数

・円周率

```python
PI = np.pi
```

・ネイピア数(自然対数の底)

```python
E = np.e
```

#初等関数

・累乗

```python
x = 2; l = 2
p = np.power(x,l) # x**lでも可
```

・平方根

```python
x = 2
s = np.sqrt(x) # x**(1/2)でも可
```


・正弦関数sin()

```python
x = np.pi
s = np.sin(x) # s = 0
```

・余弦関数cos()

```python
x = np.pi
c = np.cos(x) # c = 1
```

・正接関数tan()

```python
x = np.pi
t = np.tan(x) # t = 0
```

・指数関数exp()

```python
x = 1
e = np.exp(x) # e:ネイピア数
```

・対数関数log()

```python
x = np.e
l = np.log(x) # l = 1
```

・逆正弦関数arcsin(),逆余弦関数arccos(),逆正接関数arctan()

```python
x = np.pi
as = np.arcsin(x) # 逆正弦関数
as = np.arccos(x) # 逆余弦関数
as = np.arctan(x) # 逆正接関数
```
Az PowerShellでユーザー情報がキャッシュされてしまう

- 環境
    - Az PowerShell 2.7.0
    - PowerShell 5.1.18362.145
    - Windows 10 Enterprise (18362.418)


- 事象
    - AzureアカウントA（組織アカウント）でログイン（Connect-AzAccount）しても、以前ログインしたアカウントB（Microsoftアカウント）でログインされてしまう！という事象が発生

- 解決
    - Azure Context Autosave機能が資格情報をキャッシュしていました。Disconnect-AzAccountコマンドで解決（PS > Disconnect-AzAccount userB@contoso.org）
    - この先面倒なのでDisable-AzContextAutosave コマンドにてキャッシュをオフにしました（コンテキストの自動保存をオフにした）
    - ドキュメントはこちら
        - https://docs.microsoft.com/ja-jp/powershell/azure/context-persistence?view=azps-2.7.0#removing-credentials
OSMnxで取得した道路ネットワークデータから極座標グラフを作ろう！

##道路ネットワークの取得
道路ネットワークの取得方法は、前回の記事↓↓↓を参考にしてください。
[OSMnxを用いて，オープンストリートマップから道路ネットワークデータを取得しよう。](https://qiita.com/keijipoon/items/afa555326b1e5043588f)

###前回取得した道路ネットワークデータの可視化結果（横浜市）
<img width="1050" alt="yokohama.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274029/5f809e1c-c03d-944a-c08c-7021cf83825d.png">

このデータを元に、方向ごとに集計して可視化していきます。

##今回つくるもの：極座標グラフ
![city_road.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274029/75250ba3-13d7-0e63-2fa4-cab44c076029.jpeg)

[世界各都市の道路が向いている方角が可視化されたグラフを比べてみると何がわかるのか？](https://gigazine.net/news/20180714-city-street-orientations/)



##データの分布
```bearingdata.py
import pandas as pd
import osmnx as ox
import matplotlib.pyplot as plt

G = ox.graph_from_place(f'Yokohama, Kanagawa, Japan', network_type='drive')

# calculate edge bearings and visualize their frequency
G = ox.add_edge_bearings(G)
bearings = pd.Series([data['bearing'] for u, v, k, data in G.edges(keys=True, data=True)])
ax = bearings.hist(bins=30, zorder=2, alpha=0.8)
xlim = ax.set_xlim(0, 360)
ax.set_title('street network bar chart')
plt.show()
```
###横浜市の道路の方向データ
![bearing_data_yokohama.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274029/79106f68-3303-4f07-6a60-8844008d9912.png)


##極座標の作成
```bearingplot.py
# polar plot
import numpy as np
n = 30
count, division = np.histogram(bearings, bins=[ang*360/n for ang in range(0,n+1)])
division = division[0:-1]
width =  2 * np.pi/n
ax = plt.subplot(111, projection='polar')
ax.set_theta_zero_location('N')
ax.set_theta_direction('clockwise')
bars = ax.bar(division * np.pi/180 - width * 0.5 , count, width=width, bottom=0.0)
ax.set_title('street network polar coordinates', y=1.1)
plt.show()
```
###横浜市の道路の方向の極座標グラフ
![bearing_graph_yokohama.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274029/1889d2c5-b361-acf7-cdf8-f228ddc3d67b.png)

###他の市でもやってみました。
千葉市
![ChibaCity.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274029/1e496222-4380-5fa8-3c7a-38dc4910a3e0.png)



福岡市
![FukuokaCity.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274029/a1df754d-2e3a-9a90-6392-4e4b5f93f7f5.png)



那覇市
![NahaCity.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274029/1915da87-67e1-35d7-d98f-307d5c06e26d.png)

 

##まとめ
いかがでしょうか。今回は横浜市を例に可視化してみました。
もっといろいろな都市を可視化して比べてみたいですね。
Laravel ide-helperでMySQLのJSON型カラムが認識できないエラーの対処法

## 課題
[Laravel IDE helper](https://github.com/barryvdh/laravel-ide-helper)でモデルクラスにアノテーションを追加しようとしたらMySQLのJSON型が認識できないとエラーになった。

```
Exception: Unknown database type json requested, Doctrine\DBAL\Platforms\MySQL57Platform may not support it.
```

## 解決策

config/ide-helper.php ファイルを下記内容で作成するだけで解決！

```php
<?php
return [
    'custom_db_types' => [
        'mysql'=> [
            'json'=>'json_array',
        ]
    ],
];
```

## 参考
https://github.com/barryvdh/laravel-ide-helper/issues/295#issuecomment-268280789
【EC2+Django】permissionエラーで画像が表示されなくなった

## 環境
maxOS/nginx/ec2/django/gunicorn

## 画像が表示されない
AWSのEC2にDjangoをディプロイしたら画像が表示されなくなった...

ググって
settings.pyにSTATIC_URLもSTATIC_ROOTを記述したり、
nginx.confに画像のディレクトリを設定してみた。

けど画像は表示されない。


困った

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315096/aa6a57f7-43a4-fbfa-2f01-592a1cc0ccac.png" width="200px">

## 原因はパーミッションエラー
とりあえずEC2にログインしてターミナルでエラーの原因を聞いてみる

```
$ sudo tail -f /var/log/nginx/error.log
　....
  2019/10/12 09:19:45 [error] 23126#0: *5 open() "画像ディレクトリ" failed (13: Permission denied)
  ....
```

画像にアクセスする権限がないよ！って教えてくれた。

## 解決策
なら画像にアクセスする権限をあげましょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315096/e6c47397-ca9d-e1f6-dfae-c5c7438e3cac.png" width="200px">

```
$ sudo chmod o+x /home/ec2-user/
```
これで解決
Raspberry Pi 3B+ 初期設定

# はじめに
妻から余った 64GB のmini SD カードをもらったので Raspberry Pi 3B+ に使おうと思った。

用意するもの
- Rasberry Pi 3B+ 本体
- USBキーボード
- USBマウス
- HDMI接続ディスプレイ


# SDカードのフォーマット 
Raspberry　Pi は 32GB までしか対応していないというか FAT32 のでフォーマットしないといけない。

案の定「exFAT」なので、このままでは使えない

「[MiniTool Partition Wizard](https://forest.watch.impress.co.jp/library/software/partwizhome/)」というツールを使ってフォーマットする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/1dbc4c8b-77ac-080f-eb7b-66a8656725d4.png)

左のメニューの「フォーマット」を押すと、ファイルシステムの選択肢が出るので「FAT32」を選択して、左上の「適応」を押す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/53783dd4-b856-05c8-b8b5-0ce76acdcb64.png)

# Raspberry Pi のOSをダウンロードして展開

「[NOODS](https://www.raspberrypi.org/downloads/noobs/)」をダウンロードして、ZIPファイルを展開したものをSDカードに置く
このファイルは2.4GBぐらいあるのでダウンロードおわるまで気長に待とう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/00eaf5d9-3ba6-b50b-fc65-93b65f32b4d5.png)

展開したらこんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/b4eda0cf-3d3d-b58f-8050-9801981a8f76.png)


SDカードにファイルを展開したら Raspberry Pi に挿入して電源を入れる。
※）32GBは前のカード。ここにさしこむ。

![IMG-8853.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/b0ff8e28-939d-6fec-9feb-e45b6180a284.jpeg)

# Raspberry Pi 3B+ に OS をインストール

起動すると、最初のメニュー画面が表示されたところで言語を選択するので、「日本語」を選んでおく

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/0cbaef65-ec7b-5d5a-4c5a-6b3eed920ba0.png)


次にWifiの設定（あれば）
後で設定しなくてもいいので楽。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/2f10aefc-92d2-712d-67bd-2a31469c54de.png)


Wifiにつながったら、いろいろとメニューが出てくるが、「Raspbian Full」を選択して「インストール」を押す。

警告が出てくるので「はい」を押す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/7a24fda0-53a3-6c25-5c7a-566e5debbe7f.png)


インストールが始まる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/f4428f63-c713-b120-6bad-9ef3f8212bd1.png)


インストールが終わると、「Next」をおして最終セットアップをする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/1233e0bc-2d3e-e473-2d92-11df20c570fe.png)

言語とタイムゾーンを設定。
日本なので、「国」は「日本」、「言語」は「日本語」、「タイムゾーン」は「東京」
※）なんで明石じゃないのかと思うｗｗ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/48d6c19f-3b1b-ba82-81f3-c17255c551e1.png)



「Next」で最後はアップデート
※）結構時間がかかる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/e1fd013b-72c9-f6d2-35fa-b3bbe8d00bce.png)


アップデート終わったら、再起動する画面が出るので、再起動したら使えるようになる。
webRTCでの多人数接続での不具合

webRTCでP2Pのビデオ通話を制作しているのですが、不具合に直面しております！
詳しい方いらっしゃいましたが、ご教授頂けると幸いです！🙇

【課題】
2~30人の複数人接続を実現したい。
ルームが複数個あり、画面上でユーザーが移動すると、別のルームに接続させる仕様
課金が必要なAPIなど(Skyway,twilioなど)は極力使いたくない。

【経緯】
①
完成し、1つのルームあたり2~4人での動作ではうまく動いたのですが、1つのルームで5~12人など 人数が多くなることで 一部の音声が極端に小さくなったり、新規で追加接続されたユーザーのトラック(ビデオカメラ/画面共有 など)が ルーム内の一部のユーザーに届かない 現象が起きました。
②
エラーが見当たらなかった(見つけられなかった)こと、webRTCは複数人接続に不向きであるという話もあったので、原因がコード側ではなく、webRTCで１つのルームあたりの人数が大きくなることで起きる現象だと仮説を立てました。
③
UI上のルームごとに、webRTCのルームを作る仕様をやめて、同一ルームに存在するユーザーを感知して、そのユーザーと１対１で即席のピアー接続を毎回作る仕様に変更しました。
具体的には、
-新規ユーザーが自分のルームに入った際に、その人と１対１のルームを制作し、その後、既に[音声・画面共有・ビデオカメラ]をONにしている場合は、そのローカルトラックを 制作したばかりのルームに追加する
-既に複数人がルームに入っている場合、例えばAさん、Bさんがルーム内にいて、Cさんが入った場合、A-B間のルーム、A-C間のルームを制作し、適切なトラックを送る
-ユーザーがルームを出た場合は、その人が入っている１対１のルームを全て削除する
上記のような仕様にしました。
④
③での構築が 全体的にコードが複雑になり、想定以上に難航しております。
一部は動いているのですが、部屋に入ってもトラックがピアー接続にうまく乗らないことがあったり(乗ったり乗らなかったりする)、UI上のルームで、2人までは上手く動いても3人になった時に動かないケースが出たりしています。

【質問】
⑴ そもそも②で立てた仮説に間違いはないか。
⑵ 仮説が正しいとして、もっとシンプルに構築できるアイディア/方法はないか。
⑶ コードの量が多くどこをシェアすれば良いのかわからなく シェアしていないので、回答が難しくなるかと思いますが、④で現在起きている現象に 何か思い当たる節はないか。以下、コード自体ではないですが、大まかな構成を記載しました。具体的な場所でシェアすべきコードがあれば、シェア可能です。

【大まかなコード内容】
-vue.jsで制作
-firebaseのrealtimeDatabaseで各ユーザーがどのルームに居るかを感知、誰かがルーム移動した際に、自分のルームが関わっていた場合、トリガーを引く
-その際に、まずsocket.ioで新規ソケットを制作し、オファー、アンサー、Candidate制作送信、などのソケットにトリガーを設定。
-自分が移動して、その部屋に既に1人でもユーザーがいる場合同じ準備を行う
-その後、入室した側のユーザーが、既に入っていたユーザーにオファーを送る
-新規のピアー接続を用意し、こちらにも、他ユーザーのトラック追加/削除に対してのリアクション用のトリガーをセットする。
-ピアー接続が上手くいった場合、その後、既にUI上で自分の[カメラ、画面、音声]それぞれのスイッチがONになっていた場合に、そのピアー接続に載せる。
-ピアー接続のトリガーの仕様は、onnegotiationneededを経由して、ontrack、removetrackのアクションを稼働させている。removetrackができるようにontrackの際にsenderをクライアント側で保存させておいて、removetrackではそれを使用する

何卒宜しくお願いいたします！🙇
自分用メモ(View・部分テンプレート)

#Viewあたり
##レイアウト
部分テンプレートとも似ているが、レイアウトはページの外枠を定義するのに利用する(ヘッダー・フッター・メニューなど)

##パーシャル(＿〇〇.html.erb)
Viweの共通化に用いられる
ファイル名の先頭にアンダースコア( _ )をつける

呼び出すときはアンダースコアをつけない

ex)
layoutディレクトリの_form.html.erb

↓呼び出すときは
render 'layout/form'(app/viewsからの相対パスを用いる)




##部分テンプレート
複数ページで共通の領域がある場合使用する(毎回同じコードを記載するのは無駄なので)
レイアウトとは違い、ページの外枠ではない、もう少し部分的なページの共通領域を定義するために利用する




##<%　%>と<%= %>の違いがピンと来ていない


<%= %>
与えられた式を出力する

<% %>
がブロックの中のコードを実行するだけ
→出力しないでもokな時にこちらを使用する(条件やループ)

基本的にテンプレートファイル(コントローラー名/アクション名.html.erb)は画面に大して何らかの出力を行うので、ほとんどの記述は<%= %>で行う


##yieldとprovide

<% provide(:tag,xxx) %>で入力しxxxを
<%= yield(:tag) %>で受け取る感じ
UrlFetchApp.fetchの応答3種 タイムアウトがつらい



# まとめ

大別して

* 200 OK
* エラーステータス(400 500)
* 接続不能(無効なURL)

がある。
異常系のうちステータスコードの異常はオプションでレスポンスか例外扱いかを選べる

タイムアウトは制御方法がなく、例外処理するしかない。

# 正常系

```js
const res = UrlFetchApp.fetch(URL)
```

接続先が問題ないなら気にすることはない

# ステータスコード異常

```js
try {
  const res = UrlFetchApp.fetch(URL)
} catch(e) {}
```

400や500番台が返されると通常は例外として処理される。
ただ、エラーであることをチェックしたい場合もあるので、そういう場合は
`muteHttpExceptions`オプションを使う。

```js
const res = UrlFetchApp.fetch(URL, {muteHttpExceptions:true})
res.getResponseCode() != 200
```

これで応答が帰ってくるかぎりは例外処理で行わなくてよくなる。

# 利用できないURL

サーバーが死んでいるときなど応答がないとき、この例外エラーが発生する。
これは`muteHttpExceptions`では制御できない。例外で対処するほかない。

が、問題はそこではなく、**応答待ち時間がめっちゃとられる**ことが問題。

タイムアウトの時間の資料は見つからなかったが、私の手元のトリガー実行時間から、
おおよそいちリクエストを大体**50秒**近く待機する。

トリガーで自動で働いている限りはどれだけ時間を使ってくれても私は困らないが、問題は無料の利用枠の問題である。

[GoogleAppsScriptでよくはまる制約まとめ - バグ取りの日々](https://www.bugbugnow.net/2018/12/GoogelAppsScript-restriction.html)

GASのトリガーの実行時間は一日合計90分。
たとえば、奇特な例として「普段は接続できないがまれに接続できることをチェックしたい」逆死活監視とでもいうような機能を作る場合、
いち実行に50秒だとおよそ
15分に一度の実行が限界になる。
チェックしたいURLが増えると間隔の限界は減り、
二つのURLをチェックするとそれだけで30分に一度しか実行できなくなる。

そして問題はこのタイムアウトまでの時間を操作できないことで、10秒応答がなかったらタイムアウト、などとは設定できない。

[Class UrlFetchApp  |  Apps Script  |  Google Developers](https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app)

同期処理なので途中でabortするようなこともできず、
HTTPのヘッダーで操作できないかと考えた結果は前回のとおり
[HTTPのリクエストヘッダーでタイムアウトを操作できない - Qiita](https://qiita.com/khsk/items/a209eb362550737651ff)

トリガー時間は共用なので他のスクリプトにも影響が出てくる困り者。

死んでいるURLを執拗にチェックするシーンは通常ほぼありえないし、トリガー時間はリアルタイムに増減するので異常による浪費の影響も一日で終息する。

普通の人には困らないが、稀有な例として絶賛困っているのである。
解決方法は未だない。
UbuntuでhomeをHDDへ移行

# きっかけ
UbuntuではSSD+HDD構成ではhome領域をHDDに入れることが推奨されているが普通のインストールではうまく設定できなかったのでコマンドラインを使って設定したので備忘録代わりに残す。

## 手順
1. HDDを(ext4)にフォーマット
2. HDDをマウント
3. HDDに`/home/`領域をrsyncでコピー
4. `/home/`領域をバックアップにリネーム
5. からのマウントポジション`/home/`を作成
6. HDDをアンマウント
7. HDDを`/home/`領域にマウントし直す
8. 再起動時に`/home/`領域を認識できるように`/etc/fstab`にUUID編集

である。UUIDはUniversally Unique IDの意味でソフトウェア上で認識しているオブジェクトに振られるユニークなIDであり`/etc/fstab`はマウント先の設定である。

### フォーマットと各デバイスの名前など
1.の手順は[GParted](https://ja.osdn.net/projects/gparted/)を使ってフォーマットしておく。
HDDは`/dev/sdb`としてフォーマットされたパーティションは`/dev/sdb1`であるとし、SSDは`/dev/sda`、`/dev/sda1`をブート領域、`/dev/dev2`をその他の領域であるとする。

### コマンド作業
作業はほぼ管理者権限が必要なので`sudo su -`を使って管理者になって行う

```shell-session
# cd /
# mkdir home.new
# mount -t ext4 /dev/sdb1 /home.new 
# rsync -avz home/ home.new/
# mv home home.bak
# mkdir home
# umount home.new/
# mount -t ext4 /dev/sda1 /home
```

### fstabの編集``
```config:/etc/fstab
# /etc/fstab: static file system information.
# 
# Use 'blkid' to print the universally unique identifier for a 
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
# 
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
# / was on /dev/sda2 during installation
UUID=${sda2のUUID} /            ext4    errors=remount-ro 0       1
# /boot/efi was on /dev/sda1 during installation
UUID=${sda1のUUID} /boot/efi    vfat    umask=0077      0       1
# swap was on /dev/sda3 during installation 
UUID=${sda3のUUID} none         swap    sw              0       0
```
このような形式になっているので`/home/`用の設定を追加する

```config:add
# /home/ was on /dev/sdb1 during installation
UUID=${sda2のUUID} /home       ext4    nofail 0       1
```
の用に記述する。これで再起動して`df`コマンドで確認して`/home`がHDDになっていたら成功で`home.new`はマウント先がなく空になっているので削除する。
その他、/home.bakも必要なければ削除してもいい。

## エラーなど
まとめると上のような手順であるが調べながらで回り道もしたのですんなり行くかは断言できない。
途中で起こったエラーとして`/etc/fstab`の編集に失敗してユーザーログインができなくなったので[Ubuntuのリカバリーモードの管理者ログイン](https://tkzo.jp/blog/how-to-startup-ubuntu-with-recovery-mode/)をつかった。(シングルユーザーモード、ランレベル=1、だと何故かうまく動かなかったのでリカバリーモード推奨)。

## 最後に
OSをSSDにデータをHDDにという基本だが意外とまとまった記事がなかったので誰かの役に立てれば僥倖です。
管理者権限を使って低レベルの書き換えなので嵌まると大変なことになりそうです。
ここが動かない、間違ってるなどがあれば編集リクエストまたはコメントでお願いします。

## 参考にしたものなど
[fstabについて](https://qiita.com/kihoair/items/03635447591358210772)
[Ubuntuの初期設定とHDDのマウント](https://qiita.com/makomi/items/21e9cc9347a5df29b406)
Rails チュートリアルでテスト実行したら、「File to import not found or unreadable: bootstrap-sprockets」と出た時の対処方法

# Rails Tutorial でテスト実行していたら突然「File to import not found or unreadable: bootstrap-sprockets」と出てきてしまった

※この記事はcloud9のIDEでRails Tutorialやっている場合の記事です

まずは、エラーを読み解くと分かりやすく
custom.scssでimportしようとしているbootstrap-sprocketsが見当たらないよというエラー

## bootstrapがimportできていない…？
[Ruby on Railsにbootstrapを入れてみる](http://geekday.hatenablog.com/entry/2017/03/31/021052)

このリンク先の事例の場合はgemfileに'bootstrap-sass'の項目がないと、bootstrapの読み込みができずに参照不可になるというもの
とはいえ、Rails チュートリアルの場合はgemfileに5章までは変更を加えることも殆どなく、'bootstrap-sass'を確認したところ入っていたので私の場合は別の原因であった
(railsサーバ起動してみたらbootstrapが入ったデザインが出てきた)

念のためbundle-install実行するも相変わらずエラーが出る

## 英語で検索してみたら、cloud9側の不具合の可能性があると判明

[How to resolve “Error: File to import not found or unreadable: bootstrap-sprockets.” in Rails WITHOUT modifying application.css](https://stackoverflow.com/questions/32546545/how-to-resolve-error-file-to-import-not-found-or-unreadable-bootstrap-sprocke)

cloud9の自動ビルドが不具合を起こして、読み込んでいるはずのbootstrap-sprocketsを認識しなくなることがあるらしい
ので、cloud9のAWSインスタンス自体を再起動
再起動の手順は以下のqiitaを参考に実施
[AWS インスタンスの再起動方法](https://qiita.com/at0arumati/items/2001a7d48384231d5e01)

再度テストを実行したら、無事errorが消えた!
![Screenshot_2019-10-12 rails-tutorial - AWS Cloud9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501968/399699e2-fbf9-c797-ae7f-855b7201e3d2.png)

## CloudIDEを普段使わないと、つい信用しすぎてしまうので疑う姿勢が大切
日ごろeclipseで開発しているので、ソース修正していないのにエラーが起きたら大体クリーン＆ビルドかeclipse再起動してみるかでやっているけれども、
ついAWSのCloudIDEは信用できそうだなって疑う姿勢が薄れていたので、反省
VB.NETを使用したOutlookメール・予定表の送信

#はじめに 
社内DBから必要な情報を取得して、
その情報から目的の社員へメールもしくは予定表を自動送信する
ということを行う機会があり、その際のメモを記しています。


メモの内容は、Microsoft Outlook 15.0 Object Library (Outlook 2013) を
使用しましたっていうだけです。



#Object Libraryへの参照設定
[プロジェクト]タブ -> [参照の追加] -> [Microsoft Outlook 15.0 Object Library] -> OK
※Object libraryは、使用しているOfficeのバージョンによって変わります。



#メール・予定表送信
Application object instanceの作成

```.vb
Dim oApp As Microsoft.Office.Interop.Outlook._Application
oApp = New Microsoft.Office.Interop.Outlook.Application
```

Mail Itemの作成

```.vb
Dim oMsg As Microsoft.Office.Interop.Outlook._MailItem
oMsg = oApp.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem)
oMsg.Subject = "件名"
oMsg.BodyFormat = Microsoft.Office.Interop.Outlook.OlBodyFormat.olFormatHTML
oMsg.HTMLBody = "本文"
oMsg.To = "XXX@mail.com"
oMsg.CC = "XXX@mail.com"
oMsg.BCC = "XXX@mail.com"
oMsg.Display() ' 表示する場合
oMsg.Send()    ' 送る場合
```

AppointmentItemの作成

```.vb
Dim mtgCalender As Microsoft.Office.Interop.Outlook._AppointmentItem
mtgCalender = oApp.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olAppointmentItem)
mtgCalender.MeetingStatus = Microsoft.Office.Interop.Outlook.OlMeetingStatus.olMeeting
mtgCalender.Subject = "件名"
mtgCalender.Start = New DateTime(yyyy, mm, dd, h, m, s)
mtgCalender.Location = "場所"
mtgCalender.Body = "本文"
mtgCalender.Duration = 60 '設定時間
Dim recipient As Microsoft.Office.Interop.Outlook.Recipient
recipient = mtgCalender.Recipients.Add("XXX@mail.com")
recipient.Type = Microsoft.Office.Interop.Outlook.OlMeetingRecipientType.olRequired ' 必須出席者 olOptionalなら任意
mtgCalender.Display()
mtgCalender.Send()
```
【powershell】MS Word の書式の修正履歴だけ一括承諾する

# はじまり
![201910122171727.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501098/6f677436-1b74-39d9-523d-0f3a2d62869f.png)

Microsoft Word で原稿をやり取りするときに多用される「変更履歴の記録」ですが、上図のような書式変更の履歴で右欄が埋もれてしまうという事態がよくあると思います。実際のところ加筆・削除の記録以外は必要性が皆無なので、こうした書式変更関連の履歴だけを一括承諾してスッキリさせようと思います。

# 事前準備
今回は対象の Word 文書を開いた状態でコンソールからコマンドレット実行して一括処理します。
下記記事で紹介したコマンドレットを `$profile` に書き込んでおくかドットソースで読み込んでおくなどして `Get-ActiveDocument` で powershell から現在開いている文書を操作できるようにしておきます。

[powershell で Office を捕まえてターミナルとして操作する](https://qiita.com/AWtnb/items/b0742a26c622b81248c6)

# コード
VBA とは異なり、各種組み込み定数の値を指定してやる必要があります。
（参考： [Word VBA 組み込み定数の値一覧](https://qiita.com/AWtnb/items/b2bcae6c9ab62b649b67)）

```powershell
function Approve-StyleRevisionOnActiveDocument {
    <#
        .SYNOPSIS
        現在アクティブなWord文書中の書式関連の変更履歴を一括で承認する
    #>

    $doc = Get-ActiveDocument
    if (-not $doc) {
        return
    }

    $wdRevisionProperty = 3
    $wdRevisionParagraphProperty = 10
    $wdRevisionSectionProperty = 12
    $wdRevisionStyleDefinition = 13

    $n = 0

    $revisions = $doc.Revisions
    foreach ($rev in $revisions) {
        if ($rev.Type -in @($wdRevisionProperty, $wdRevisionParagraphProperty, $wdRevisionSectionProperty, $wdRevisionStyleDefinition)) {
            Write-Host $rev.FormatDescription -NoNewline -ForegroundColor White -BackgroundColor Green
            Write-Host " by " -NoNewline -ForegroundColor DarkGray
            Write-Host  $rev.Author -ForegroundColor Cyan -NoNewline
            Write-Host " on:" -ForegroundColor DarkGray
            Write-Host ("{0}" -f $rev.Range.Text)
            $rev.Accept()
            $n++
        }
    }

    if ($n -gt 0) {
        Write-Host ("{0} style revisions are Accepted!" -f $n) -ForegroundColor Green
    }
}
```
コンソール上での結果表示のために行数が増えていますが、 変更の承諾だけであれば `.Accept()` のみで十分なのでコード自体はもっと簡素化できます。

# 実行イメージ
対象の Word 文書を開いた状態でコンソール上からコマンドレットを実行します。
![201910122171752.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501098/ca8cf3ec-4610-f1bc-482f-a90f963167df.png)

実行後の文書↓
![201910122173821.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501098/5a78c120-a157-5cc2-49bc-bec4714d41cd.png)

実行後に <kbd><kbd>Ctrl</kbd>+<kbd>Z</kbd></kbd> で元に戻すことができます。
ZYBO用Vivadoプロジェクト生成Tcl

# 1. 概要

VivadoでZybo用のプロジェクトを作成するときに、GUIでポチポチするのが煩わしく感じていたので、Zybo用のプロジェクトを作成するスクリプトを作りました。

# 2. 環境

- Windows 10 pro
- Vivado 2018.3

# 3. クローン

```
> git clone git@gitlab.com:yoshiyasu1111_fpga/createZyboProject.git
```

[Gitlabリポジトリ](https://gitlab.com/yoshiyasu1111_fpga/createZyboProject)

# 4. 使用法

ZYBO-Z7-10用のボードファイルをインストールしてあることを前提としています。

## 4.1 コマンドプロンプト

```
> CreateProject.bat [プロジェクト名] [プロジェクトディレクトリ]
```

第一引数にプロジェクト名、第二引数にプロジェクトディレクトリをとります。
どちらも指定しなければデフォルトの値`プロジェクト名：design`、`プロジェクトディレクトリ：project`になります。
プロジェクト名を指定しなければプロジェクトディレクトリを指定することはできません。

## 4.2 GUI

ファイルをダブルクリックでもスクリプトを実行することができます。この場合プロジェクト名はデフォルトの`design`、プロジェクトディレクトリはデフォルトの`project`になります。

# 5. 例

```
> git clone git@gitlab.com:yoshiyasu1111_fpga/createZyboProject.git
> cd .\createZyboProject\
> .\CreateProject.bat zybo proj
```

カレントディレクトリ以下にprojディレクトリが作成され、その下にzyboプロジェクトが作成されます。
Sessionメソッドの使い方、宣言方法

#目的
ログイン機能を実装するときにSessionメソッドを使用するが、
機能の流れをおさらいするために備忘録として残しておく。

#セッションとは？
・主にログイン機能に使用されるもので、ログイン状態を持続させるためにある機能。
・ステートフルな通信を実現するために必要な機能。

セッションという仕組みがなけれはページを移動するたびにログインし直さなければならない。

ログイン機能を実装するためRailsではあらかじめセッションを実装するためのメソッドが用意している。
また、セッションの情報はRailsの標準では、ブラウザ側のクッキーに保存される。

#Sessionメソッドの使い方
まずは、ユーザーを登録するためにユーザーモデルを準備する。
ユーザーモデルには、名前とメールとパスワードが登録できるようにします。

####gemをGemfileに追加
パスワードを暗号化するための
(コメントアウトされているためコメントインする必要がある)

```ruby:Gemfile
gem 'bcrypt', '~> 3.1.7'
```

コメントインが完了したらgemをインストールする必要がある。

```
bundle install
```

####Userモデルを作成

```
rails g model Users name:string email:string password_digest:string 
```

password_digestというカラムにはパスワードが入ります。
こちらはgemであるbcryptの仕様ですが、このカラムにすると**パスワードが暗号化**されて保存されます。

migrationファイルが作成されたので、データベースに反映しましょう。

```
rails db:migrate
```
これでユーザーモデルの作成は完成です。

次に作成したユーザモデルにパスワードの**暗号化を有効**にするための設定を加えます。

```ruby:app/models/user.rb
has_secure_password
```

#####Sessionコントローラーを作成
ログイン機能を作成するためセッションコントローラーを作成する。

```
rails g controller sessions
```

```ruby:app/controllers/session_sontroller.rb
class SessionsController < ApplicationController
  def new
  end

  def create
    user = User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      session[:user_id] = user.id
      redirect_to user_path(user.id)
    else
      render 'new'
    end
  end
end
```
ログインボタンを押した後に、セッションに情報が保存されているか判断しています。

```
user = User.find_by(email: params[:session][:email].downcase)
```
params[:session][:email]で、ユーザのポストでした値を取り出し、メールアドレスには小文字しか入力できないため.downcaseで小文字に変換しています。
その後find_byメソッドで入力したemailをカラムに保存されたemailが一致した場合にユーザーに代入しています。

次に、

```
if user && user.authenticate(params[:session][:password])
```
&&を使って、条件を2つ指定しています。
・**user**:userの中身があるかどうか
・**user.authenticate**:userに代入されたレコードのパスワードがポストした値と一致しているか

パスワードが登録しているユーザー情報と一致していたらセッションにユーザーIDを登録しています。

```
session[:user_id] = user.id
```

session[:名前]は名前をつけて、セッションを登録できます。

また、elseの場合、

```
render 'new'
```
パスワードが登録しているユーザ情報と一致していなかった場合、入力フォームに再度飛ぶように設定されている。

これでセッションを作成することができました。

#まとめ
#####セッションを作成する際に必要なものは以下である。
・パスワードを暗号化するためのgem:**bcrypt**
・gem:bcryptで暗号化したパスワードを保存するカラム:**password_digest**
・パスワードの暗号化を有効にするための設定:**has_secure_password**
・セッションを作成するためにメソッド:**session[:名前] = params[:~]**
プライベートサブネット内のインスタンスにpublic IPを割り当てると外からpingは届くのか？

答え：届く。しかし返りはしない。

# privateサブネットのルートテーブル

`0.0.0.0/0`へのルーティングは無い状態

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79394/f12cab09-142b-579a-a442-e06a11087f4b.png)

# EC2インスタンス

Elastic IPが割り当ててある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79394/ba818656-174c-d0e4-7925-64fd7d5c4af5.png)

セキュリティグループでICMPを許可してある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79394/850921a9-9b37-3859-cbff-3d876818245d.png)


# tcpdumpで確認

インスタンス内でtcpdumpを起動しておいて、AWS外からpingしてみた。

```
tcpdump -nn icmp
```

届いていた。ただし、pingを打ったマシンまで返ってはいなかった。ルートテーブルにインターネットへのゲートウェイが無いので。
CentOS 8 インストール手順 (Kickstart 版)

# 準備

1. Web サーバーを用意し, 以下のファイルを設置する。
   - `http://<FQDN>/ks/centos8-x86_64-ks.cfg` でアクセスできるようにする。
   - root や一般ユーザーのパスワードは, [Appendix B. Kickstart commands and options reference Red Hat Enterprise Linux 8 | Red Hat Customer Portal](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/performing_an_advanced_rhel_installation/kickstart-commands-and-options-reference_installing-rhel-as-an-experienced-user#rootpw-required_kickstart-commands-for-system-configuration) を参考に置換すること。
      - `$ python -c 'import crypt,getpass;pw=getpass.getpass();print(crypt.crypt(pw) if (pw==getpass.getpass("Confirm: ")) else exit())'`
   - 他にもホスト名やユーザー名, PID, GID, パッケージなどの設定は適切な文字列に置換すること。

```shell:centos8-x86_64-ks.cfg
#version=RHEL8
# Use text install
text

# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us','jp'
# System language
lang ja_JP.UTF-8

# Network information
network  --hostname=centos8
network  --bootproto=dhcp --device=enp0s3 --ipv6=auto --activate
network  --bootproto=dhcp --device=enp0s8 --ipv6=auto --activate

# System timezone
timezone Asia/Tokyo --isUtc --ntpservers=2.centos.pool.ntp.org,2.centos.pool.ntp.org,2.centos.pool.ntp.org,2.centos.pool.ntp.org
# System services
services --enabled="chronyd"

# System bootloader configuration
bootloader --location=mbr --boot-drive=sda
# Partition clearing information
clearpart --all --initlabel
ignoredisk --only-use=sda
autopart --type=lvm --nohome --noswap

# Use network installation
url --url="http://ftp.riken.jp/pub/Linux/centos/8/BaseOS/x86_64/os/"
repo --name="AppStream" --baseurl=http://ftp.riken.jp/pub/Linux/centos/8/AppStream/x86_64/os/
repo --name="extras" --baseurl=http://ftp.riken.jp/pub/Linux/centos/8/extras/x86_64/os/
repo --name="epel" --baseurl=http://ftp.riken.jp/pub/Linux/fedora/epel/8/Everything/x86_64/

# Root password
rootpw --iscrypted --lock xxxxxxxx
# Run the Setup Agent on first boot
firstboot --enable
# Do not configure the X Window System
skipx

## Poweroff after installation
poweroff

## Create user
user --name=ryo --gid=100 --groups="wheel" --uid=1001 --iscrypted --password="xxxxxxxx"
sshkey --username=ryo "<SSH 公開鍵>"


%packages
@^minimal-environment
epel-release
python3
python3-libselinux
emacs-nox
screen

%end


%addon com_redhat_kdump --disable --reserve-mb='auto'

%end


%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end


%post --log=/root/ks-post.log
sed -i -e 's/^%wheel/# %wheel/g' -e 's/^# %wheel\tALL=(ALL)\tNOPASSWD: ALL$/%wheel\tALL=(ALL)\tNOPASSWD: ALL/g' /etc/sudoers

%end
```


# 手順

1. [CentOS 8 インストール手順 - Qiita](https://qiita.com/ryo-sato/items/ee1f503a1fb3c48f49f8) を参考に仮想マシンを作成し, 起動する。
1. CentOS Linux 8.0.1905: **Install CentOS Linux 8.0.1905** を選択し, Tab キー を押下, `ip=enp0s3:dhcp inst.ks=http://<FQDN>/ks/centos8-x86_64-ks.cfg` と追記し, Enter キー を押下する。
1. インストールが完了すると仮想マシンが終了するので, 光学ドライブからメディアを除去する。

どっとはらい。
[量子コンピューター]Qiskit Tutorials

基本的にはhttps://quantum-computing.ibm.com/jupyter/tutorial/1_start_here.ipynbこの記事の日本語訳となります。

IBMが開発している量子コンピュータであるIBMQのPython用のライブラリであるQiskitをチュートリアルを介して紐解いていきます。<img width="1126" alt="スクリーンショット 2019-10-12 17.39.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278640/6df5f704-8226-3568-e220-58dd68de0dce.png">



##Qiskit Tutorials

このチュートリアルではQiskitの使い方を紹介します。
私たちはあなたが既にQiskitをインストールしていることを想定していますが、もしまだの場合は
http://www.qiskit.org/
や
インストールドキュメンテイション　(https://qiskit.org/documentation/install.html)
をご覧ください。

このセクションではQiskitの特徴のアウトラインを書きます。現在ヴァージョンは0.12です。
これらのノートブックは量子コンピュータを学ぶことに焦点を当てているわけではありません。代わりに、Qiskitの使い方について説明します。そのときもし必要であれば、量子コンピュータの詳細にも迫っていきます。

Qiskitは4つの要素ーTerra, Aer, Ignis, and Aquaから構成されています。それおぞれの要素はそれぞれの目標を持っています。そしてそれらが一つになってQiskitのフレームワークが初めて完成します。


##Getting started with Qiskit

このセクションでは初めての量子回路を作り、それらを本物の量子システムおよびシュミレーターで実行し、データを見ることを学びます。

1.**Getting started with Qiskit** - Qiskitの使い方
https://notebooks.quantum-computing.ibm.com/user/5d23146ced6ee2007ac97eb9/notebooks/qiskit-tutorials/qiskit/fundamentals/1_getting_started_with_qiskit.ipynb

2.**Plotting data in Qiskit - Qiskitに置けるデータプロットの仕方の説明
https://notebooks.quantum-computing.ibm.com/user/5d23146ced6ee2007ac97eb9/notebooks/qiskit-tutorials/qiskit/fundamentals/2_plotting_data_in_qiskit.ipynb

３.**The IBM Q Account - IBM Q アカウントについて理解する
https://notebooks.quantum-computing.ibm.com/user/5d23146ced6ee2007ac97eb9/notebooks/qiskit-tutorials/qiskit/fundamentals/3_the_ibmq_account.ipynb

4.Circuit Properties - 量子回路についての重要な特徴
https://notebooks.quantum-computing.ibm.com/user/5d23146ced6ee2007ac97eb9/notebooks/qiskit-tutorials/qiskit/fundamentals/4_quantum_circuit_properties.ipynb

5.Using the Transpiler - Qiskitのトランスパイラーを用いて回路の最適化とマッピングを行う。
https://notebooks.quantum-computing.ibm.com/user/5d23146ced6ee2007ac97eb9/notebooks/qiskit-tutorials/qiskit/fundamentals/5_using_the_transpiler.ipynb

6.Jupyter Tools - Jupyter notebookの為のQiskitの機能
https://notebooks.quantum-computing.ibm.com/user/5d23146ced6ee2007ac97eb9/notebooks/qiskit-tutorials/qiskit/fundamentals/6_qiskit_jupyter_tools.ipynb

7.Summary of quantum operations - Qiskit Terra上にあるゲート、リセット、測定等の量子操作の一覧。
https://notebooks.quantum-computing.ibm.com/user/5d23146ced6ee2007ac97eb9/notebooks/qiskit-tutorials/qiskit/fundamentals/7_summary_of_quantum_operations.ipynb


----------------------------------------------------------
SQL小技集
https://qiita.com/ool/items/75da830e7373138c8125
UTCとJST
https://qiita.com/ool/items/6be9cc290c8ad9e0f5bc
今流行りの量子コンピューター
[量子コンピューター]Qisikitでアダマールゲートを実装する
https://qiita.com/ool/items/1a5041edddc11b14efc0
[Qiskitのアカウント認証の仕方]Qiskit IBMQ プロバイダー
https://qiita.com/ool/items/e80c1266cda68984a103
Qiskitの使い方
https://qiita.com/ool/items/2227d2d515caa5087752
[量子コンピューター]Qiskit Tutorials
https://qiita.com/ool/items/2a5038df1471635d442c
(OutSystems)Reactive Web AppとMobile Appでモジュールを共有する


OutSystemsのForum上の[Reactive Web Appを紹介するページ](https://www.outsystems.com/forums/discussion/52761/reactive-web-the-next-generation-of-web-apps/#Post197623)で、

> Reactive web app blocks can be reused in mobile apps. 

(Reactive Web AppのBlockはMobile Appでも利用できる)

という記述があったので、動作確認してみます。

なお、Reactive Web App自体の紹介は、以下の記事でしています。
[(OutSystems)Reactive Web AppとTraditional Webの違い](https://qiita.com/jyunji_watanabe/items/c9888cb6ef9805e280a3)

# 環境
Personal Environment(Version 11.0.606.0)
Service Studio(Version 11.6.1)

# テスト用にモジュールを用意
## テスト対象機能
以下の3種類を対象にします。

- Block
- Client Action
- Server Action

## テスト方法
まず、参照されるモジュールを用意します。テスト対象機能を定義した、以下3種類のモジュールを作成。

- Reactive Web App
- Mobile App(Phone)
- Library

最後のLibraryはReactive Web Appと同様に最近追加されたモジュールの種類で、Entityとは独立した純粋なロジック、外部APIへのコネクタ、共通Block配置用です。役割からして、一緒に確認した方が良さそうという判断です。

参照側のアプリケーションを、Reactive Web AppとMobile App(Phone)で用意して、それぞれから上記3種類の全要素を参照してみます。

このように。これはReactive Web Appのモジュールから、モバイルのモジュールを参照したところ。
BlockやClient Actionにチェックボックスがないため、参照できないことがわかりますね。
![QReactiveReference1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/853c056f-32d9-9270-64b8-743296c88bb4.png)

# 結果
以下のような構造でテストしました。青い四角形が参照する側(End User)モジュール。
橙の四角形が参照される側の3種類のモジュール。

![QReactiveReference2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/a60337ea-749d-c47b-e1c6-bbd81db8e652.png)

結果の一覧表(①-⑥は上の図の同じ番号に対応、○は利用できることを示す)

|  | Block | Client Action | Server Action |
|:--:|:--:|:--:|:--:|
| ① | ○ | ○ | ○ |
| ② | ○ | ○ | ○ |
| ③ | × | × | ○ |
| ④ | ○ | ○ | ○ |
| ⑤ | ○ | ○ | ○ |
| ⑥ | ○ | ○ | ○ |

つまり、Reactive Web Appのモジュールに作ったBlockやClient ActionはMobile Appのモジュールから利用できる。逆にMobile AppのモジュールはReactive Web Appから利用できない。

# 分割指針
↑の結果から、これからBlockやClient Actionの共通部品を作る際は、

- Entityから独立させられるならLibraryモジュール
- Entityを利用するならReactive Web Appモジュール
- モバイル用の機能(プラグインやLocal Entityを使う場合)はMobile Appモジュール

に作るといいですね。

# OutSystems UI
このReactive Web Appの対応を受けてだと思いますが、OutSystemsのUI部品集「OutSystems UI」は、Reactive Web AppとMobileで共用されるようになりました。
SQLにはじめて触れてみたら楽しい件

# SQLを初めて触れてみたら案外難しくなかった話
先月からSQLを使うことになったので、初心者なりに使ってみた感想と使い方をさらっと紹介してみます。
「こういう便利な使い方もあるよ！」など教えてもらえるとありがたいです。

## この記事の対象者
- SQLを触ってみようと思ったけどどんな感じなん？って方
- そもそもSQLって何それ？おいしいの？って方

### 触ってみることになったきっかけ
「次の案件、DBを管理するのがメイン業務だそうです。」
SES企業で働いていて、エンジニア1年目終了間近で案件が終わりました。
１年目でやっていたのはVBAでのツール保守がメインだったので、
次の案件決まるかなぁ・・・と心配していたさなか、営業さんから持ってきてもらった面談のお話がこの案件です。

その他にも案件はありましたが、VBAを使用する案件ばかりだったので別の言語触りたいと思った私は興味を持ちました。
そして見事採用されて今に至る。

### SQLってなに？
データベースに入っている情報を操作する言語。
(S)utructured(Q)uery(L)anguage(構造化された問い合わせ言語)と覚えても良いかも。
※正式には略語ではないので意味合いとして

簡単に言うと、データベースの中から目的のデータを取り出すための言語。

### SQLを使ってみる
覚えるのは簡単に使うならたったの５つで済む。

CREATE ・・・ テーブルを作成する
INSERT ・・・ テーブルにデータを挿入する
DELETE ・・・ テーブルのデータを削除する
UPDATE ・・・ テーブルのデータを更新する

WHERE  ・・・　データの条件を指定する

### 実行環境
SQL Server 14 Developer Edition

### 使用するツール
SQL Server Management Studio 18

#### SELECT 文
データを選ぶ。（参照するときに使う）
構文はこんな感じ。

```
SELECT 列名 --参照したい列名
FROM テーブル名 --データベースの中のどのテーブルか指定
```

テーブル全体を見たいなら

```
SELECT * -- '*'でテーブルの列名全てを指定できる
FROM テーブル名 --データベースの中のどのテーブルか指定
```

#### INSERT 文
データを追加する。
構文はこんな感じ。

```
INSERT INTO テーブル名 --追加したいテーブル名
(Column1,Column2,...) --追加したいデータの列名
VALUES(data1,data2,...) --追加したいデータ
```
追加したいカラムとデータの個数は一致していることが条件。
列名を書いていないところは自動的にNULLが入る。

別のテーブルからまるごとコピーしたいなら

```
INSERT INTO コピー先のテーブル名 --追加したいテーブル名
SELECT * FROM コピー元のテーブル名 --テーブル全部を指定
```

#### DELETE 文
データを削除する。
構文はこんな感じ。

```
DELETE テーブル名　--削除したいデータがあるテーブル名
WHERE Column1 = 'hoge' -- Column1列の値が'hoge'
```

WHERE 句で指定しなければテーブルのレコード全てを削除するので注意。

#### UPDATE 文
データの値を更新する。
構文はこんな感じ。

```
UPDATE テーブル名 --参照したい列名
SET Column1 = 'fuga' -- 更新したい列名 = 更新後の値
WHERE Column1 = 'hoge' -- Column1列の値が'hoge'
```

### 感想
だんだんExcelに見えてくるのは私だけ？
まだまだ機能はたくさんあるので掘り下げていきたいです。
[AWS][Angular] 知らないことを知りたい→Googleの検索補完を一覧にしたらいい？

# 動機と思いつき

* 知らない街で美味しいご飯に巡り会いたい
* レビューサイトを使いこなすのは難しい
* 他のひとが何を探しているかわかったらいいかも
* 検索語 + 「あ」〜「ん」をGoogleに渡して、なにが補完されるか一覧してみよう

# さて、Google補完API

どうも公式なAPIではないようです。

[Google API プログラミング解説](https://so-zou.jp/web-app/tech/web-api/google/suggest/)

を参考にしました。JSONじゃなくてXMLが返ってくるんですね。

# 構成

Google APIはJavaScriptでたたけばいいし、Angularで作ったフロントエンドだけで完結しようと思いましたができません。
（どうしてできなかったのかは忘れました）。
間にプロキシを挟むことにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/e4ba6815-86d3-086b-40e3-01a5d40bd631.png)

# 稼働環境

AWSの鉄板構成です。

フロントエンドはS3に格納します。S3単体ではhttpsできないため、CloudFrnotを使います。
Google API呼び出しはLambdaで作りました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/4403c3bd-e8e1-fe90-6189-71e5021180e1.png)

# できあがったもの

https://hokanchan.uart.dev/

![g9q54-soen8.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/e9f5a83a-2b9a-ddf2-fdb0-b24c480c95e0.gif)

ソースコード https://github.com/sengokyu/hokanchan

# 考察

* 漫然と検索語を入力すると、期待する結果を得られない。
* 狭い範囲の検索語に絞り込むと良い結果が得られる。
    * 例）「銀座 ランチ」 → 「銀座 ランチ 天ぷら」
* 期待する結果が得られる地域と、得られない地域がある。
    * 暮らす人々がどのくらいネットを使っているかによる？


# ふりかえり

## Keep

* RxJSでエラーが起きたかどうか関係なく最後に処理を挟むのであれば、`pipe(finalize(()=> { /* ... */ })` を使えばいい。

## Problem

* 欲張ってCloudFormationですべてデプロイしようとして時間がかかりました。

## Try

* CloudFormationを親子関係にして、環境全体とLambdaに分ける。

## その他

* .dev ドメインはブラウザ(Chrome/Firefox)がhttpsアクセスを強制します。httpへアクセスできなくて悩みました。


# リンク

- 図の作成 https://draw.io/
- 動画のGIF化 https://www.aconvert.com/jp/video/mov-to-gif/
docker コンテナから別の docker コンテナのコマンドを直接実行する方法はあるのか？ のメモ。

ないと理解した。


![image](https://user-images.githubusercontent.com/13635059/66696038-2ef4f100-ed03-11e9-9994-17a5e1edd9bb.png)

https://forums.docker.com/t/execute-command-from-a-container-to-another-container/19492

portなどを通してやり取りする必要がある。あとsshとか。直接叩けてしまったら独立したコンテナ同士じゃないですもんね。外部とつながるインターフェイスが必要ってことじゃないだろうか。通常のサーバー同士みたいに。


# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2578








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
mysql.connector.errors.DatabaseError: 1366 (HY000): Incorrect string valueが出る

様々な事をしてきましたが、「mysql.connector.errors.DatabaseError: 1366 (HY000): Incorrect string value: '\xE7\xA6\x8F\xE5\xB2\xA1...' for column 'title' at row 1」とエラーが出て、直りませんでした。でも、めちゃくちゃ単純なことで直りました（笑）

**結論から言うと、データベースを新しく作り直したらエラーが出なくなりました。原因としては、utf-8に変更してからテーブルしか作り直してませんでした。なのでデータベースに反映されてなかったのかと。**

####やったこと
エラーが出てからやっていった事を簡単に書きます。

まずは文字コードの変更

```sql
mysql> show variables like "chara%";
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
```

utf8mb4にもしましたが、エラーは変わらず。
設定が反映されてないのかと思い、もう一度mysqlの再起動、そしてサーバーの再起動するも変わらず。
pythonのコードで「charset='utf-8'」指定するも変わらず。

```python
connect = mysql.connector.connect(
        host='localhost',
        port='3306',
        user='root',
        password='パスワード',
        database='DB名',
        charset='utf-8'
    )
```
mysql-connector-pythonを使っていたので、pythonのコードがおかしいのかと思い、ネットで使い方を紹介されている方のをやってみるとエラーがでなくなりました。なので私のプログラムをもう一度見直すもおかしいところはありませんでした。まあ、その方のを試すとき新しくデータベース作ってやっているので、エラーが出なくなって当然ですよねwww（今思うと）
でもその時は深夜まで何時間も粘って原因を探していたので、頭には何でエラーがなくったのかはてなマークでいっぱいでした。その日の解決は諦め、一度寝ました。朝起きてから、データベースから作り直すかと思い、やってみるとエラーがでなくなり解決。

####まとめ
今思うとなんでデータベースから作り直さなかったと思いましたが、あの時はまったく頭になかったですね（笑）計６時間くらいは悩んでたと思います。まあmysql触り始めたばかりなので、様々なこと調べたりしていい勉強になりました。
我々はなぜ監視を行うのか【第一章】～監視システム導入編～

#はじめに

ITエンジニアとして働いている私たちにとって、監視とは非常に当たり前なものとなった。
しかし、存在することが当たり前となった結果、「そもそもなぜ監視しているのか」という意義について知る機会が少ない。
今回は、監視の意義、そもそもなぜ監視しているのかについて説明しようと思う。

#【第一章】～監視システム導入編～

なぜ監視を行うのかについて考えるために、一度監視システムがなかった時のことを考えてみよう。

### ケース）WEBサービスを運用する担当者

この会社では、WEBサービスの運用を行っている。わかりやすいように、仮にこれをQiitaとして説明してみよう。
Qiitaでは、度々ユーザから「ページが見れない」という苦情を受けていた。
担当者Aは毎度そのことを全く知らなかったので、慌ててそのページを確認し、表示をされていないことを確認、
ページが再度見れるように対応する。ということを行っていた。

担当者Aは、毎度顧客からの連絡でユーザから苦情を受け付けるのが嫌だった。夜間に連絡を受けてたたき起こされ、睡眠不足気味にもなっていた。
また、経営層から、「何とかして苦情を減らせないかな」と相談を受けていた。

日中の勤務中、Aは数分ごとにブラウザでQiitaのトップページを開き、表示を確認するようにしてみた。
F5キーを押し、正常にページが表示されているかどうかを確認するのだ。

だが、トップページが見れていたにもかかわらず、ユーザから苦情が届いた。それは、「マイページが見れない」というものだった。
確認したところ、確かにマイページが見れなくなっていた。

Aは頭を抱えた。2つのページをブラウザで確認するのはもう無理だ。しかも、他にもトレンドのページ、投稿ページ、記事の表示ページと、
同時に確認しなくてはいけないページはたくさんある。最近qiitadonとかいうサービスまで増やしてしまった。確認しなければいけない対象が多すぎる...。

Aには、Qというエンジニアの友人がいた。Aは知らなかったが、Qは監視のスペシャリストとして、企業のコンサルタントを行っていた。

Aがこの問題についてQに相談したところ、「監視システム」というものを紹介された。

AはQから勧められた監視システムを導入してみた。監視システムは何でもいいが、仮にZabbixとしよう。

Aは手始めに、「HTTP監視」というものを追加してみた。
URLを指定すると、数分おきにそのページが正常に表示されているかどうかを確認し、異常があった場合はアラートをあげてくれるという単純なものだ。
Aは、
「トップページ」「マイページ」「トレンドのページ」「記事の表示ページ」...と監視を追加していった。早く気づきたいので、監視間隔は1秒ごと、1秒間見れない、かつ一度でも見れなくなったらアラートをあげる設定にした。


監視を追加したことで、Aは「ブラウザのリロードをして目でトップページの表示を確認する」という仕事から解放された。
しかも、ユーザよりも早く気づくことができるようになったので、苦情を言われる前にAが対応してしてしまい、そもそも苦情が発生することもなくなった。

Aは非常に満足した様子で、毎晩眠れるようになった。

## まとめ

- 監視の本質的な価値

迅速に障害発生に気づくことができる。
迅速な障害対応を行ったりすることができ、ユーザへの影響を最低限にすることができる。

※ ユーザとは、システムの利用者のこと。難しい言い方をすると、最終的にITシステムが価値を提供する相手のこと。

- 監視システムの本質的な価値

人力による24/365の目視等を行わなくても、システムがそれを代行し、人間は異常がある状態を検知した時だけ対応すればよくなる
人力でやると大変、または人力でやるのが到底不可能なことについて、監視システムを利用することで、
省力的に、かつ高品質な監視を提供することができる。

# あとがき

監視の定義については「[入門 監視](https://www.oreilly.co.jp/books/9784873118642/)」に記載された以下の定義が良いと思う。
書籍にも書かれているが、この定義は[Greg Poirier氏がMonitorama 2016というカンファレンスで紹介したもの](https://vimeo.com/173610062)である

> 監視とは、あるシステムやそのシステムのコンポーネントの振る舞いや出力を観察しチェックし続ける行為である。

【次回】→ [監視チューニング編](https://qiita.com/taro-hida/items/d6d5d25d49080eee17f6)