OmniAICreator/Qiita-1.07M huggingface dataset:
トラブル対応班のすゝめ

株式会社オズビジョンのユッコ (@terra_yucco) です。
今日は珍しく仕事の話を書こうと思います。

# トラブルについて

システムを運営していると、トラブルはつきものです。
そして、よほど軽微なものや、自然収束するもの以外は、だいたいにおいて対応が必要です。
たとえ、それがあなたのプログラムやインフラによるものではなく、オペレーションミスや外部起因だとしても。

トラブル対応、疲れますよね。
気が重いし、本来の仕事は遅れるし、しんどいですよね。

でも、私はここで声を大にして言いたい。

「トラブル対応は成長のチャンス」

# なぜトラブル対応を率先してやるべきなのか？

考え方はそれぞれありますし、もちろんトラブル対応だけが成長の手段ではありません。
しかし状況が許すのであれば、以下の理由により、私はトラブル対応は率先して取るべきだと考えています。
(事業会社ならではの考え方なところもあると思います)

- トラブルの収束が速くなるかも
- システムやサービスに詳しくなれる
- トラブルがビジネスに及ぼす影響を学ぶことができる
- 他部署の温度感や理解度を知ることができる
- 関係各位から感謝される

以下にそれぞれについて書いていきます。

## トラブルの収束が速くなるかも

もし対応が必要なトラブルの場合。
誰も手を挙げなければ、マネージャなりリーダなりがチームの状況を確認し、作業を空けられるメンバをアサインして調査・対応が開始されると思います。ただし、この場合、各チームの状況を横断的に見た上で、調整をして決定するというフローを踏む必要があります。
チームやリーダの合意を得る必要がありますが、ここで誰かが手を挙げれば、その時間を大幅に短縮できる可能性があります。収束を速くできれば、一般的には影響範囲も小さくなる傾向にあります。

※もちろんスキル・知識及び業務状況により「他の人がやったほうが全体最適である」ということは往々にしてあります。そういう理由で最適化するのはまた別の話。

## システムやサービスに詳しくなれる

トラブルは花形機能や、頻繁に改修されている機能に対して発生するとは限りません。むしろ、滅多に使われない機能に発生したケースの方が、調査や対応が大変な場合が多いと感じます。

もちろん自分が担当している機能以外を含め、サービスの全体像を熟知できていれば理想ですが、日々の業務で関係ない箇所のコードリーディングをする時間なんてものはまあそうそうありません。そういう機能にトラブルが発生したときほど、知るチャンスだと思います。
(とはいえ、トラブルなく動いてくれるのが一番なのですが)

## トラブルがビジネスに及ぼす影響を学ぶことができる

例えばオズビジョンのメインプロダクト「ハピタス」は BtoBtoC のモデルであるため、トラブルが発生した場合の影響対象は大きく分けて 3 つあります。

- ハピタスに広告を掲載しているクライアント
- ハピタスを利用しているユーザ
- 社内運営者

一例として「ユーザの登録は通常通り行えているけれど、どこ経路で登録したかが保存されない」場合、エンジニアとしてはデータ欠損が気になります。また、そのデータを使う人、即ち社内で Web 出稿の効果測定を担当しているチームは数値が取れなくて困りますが、クライアントやユーザは特に困りません。

ただ、例えば「そのときの登録経路で特別なキャンペーンを実施していて、登録したユーザに何らかの特典を付けていた」場合は、その特典の内容に応じてクライアントやユーザにも影響が出てきます。
もちろん、キャンペーンがコードに組み込まれていればエンジニアでも調査でたどり着くことはできます。ですが、運用で対応しているキャンペーンの場合など、ビジネスサイドとトラブルという共通の敵に立ち向かうことで、新たな知見を得ることができます。

処理は作るけれども、その先のデータが何に使われているかわからないというケースはよくあると思いますが、トラブル対応に関わることでその先に触れることができ、視座を上げる・視野を広げる役に立つことは間違いありません。

## 他部署の温度感や理解度を知ることができる

これは書いてある通りで、上の項目とも近いのですが。
エンジニア的には大したこと無い内容で対応もすぐできるけど、ビジネスへの影響としては由々しき事態だった、なんていうことは珍しくありません。
また逆に、エンジニア的にはすぐに重大な影響が出ているとわかる内容でも、表に出ている事象だけではその影響が他部署にはピンと来ないことがあります。

こういった温度感や理解度の違いを知ることができますし、理解度の差を埋めるために説明をする機会が多いと、要約力や説明力も身について良いこと尽くめだと思っています。

## 関係各位から感謝される

これはまあ多くを語るまでもないと思います。自分でもやりきったら嬉しいと思います。

…自己満足や承認欲求の塊と言うなかれ！かのマズローさんもおっしゃるように、ここが満たされて初めてさらに上の自己実現を目指すフェーズへ行けるのです。

# Conclusion

トラブルは発生してほしくありませんし、発生時の対応は大変ですが、その機会に得られるものもたくさんあると思います。
もし、直面した場合はぜひ手を挙げてみてほしい、そんな Qiita Post でした。

なお、オズビジョンのメンバーはトラブルに対して温度感の高い人が多く、事象の共有から体制構築・収束まではどんどん改善されてきています。機会があれば今後、実際どのようにトラブルに対応しているのか、ハピタス事業部の例を共有する Post を書きたいと思います。
Time lag we regard, simultaneous

```
妃 = "0.04 sec毎にdoRoutineがcallされる";
打 = "最初のdoRoutine()";    払 = "2nd doRoutine()";
    less(払.startingAt, 打.startingAt)
c_> 0.04 sec // let 隔
隔の期間中に届いたeventsは同時と看做せる．但し，厳密には同時ではない．
functionがload/* To set parameters */を済ませていなければcallできないように．
powershellのデバッグ

#はじめに
　powershellをプロンプトからデバックする方法

#概要
　powershellをデバッグするのは、ISEを使うのが普通であるのだが、コマンドプロンプトから実行する方法があまりアップされていないので書いてみた

　単純に
```
　sbp -script xxx.ps1 -line 10
```
　を実行してxxx.ps1を実行すれば、line 10で止まってくれる
　その後、hでデバッグコマンドがでるので、

```
 s, stepInto         シングル ステップ (関数やスクリプトなどにステップ インします)
 v, stepOver         次のステートメントにステップします (関数やスクリプトなどをステップ オーバーします)
 o, stepOut          現在の関数やスクリプトなどからステップ アウトします

 c, continue         操作を続行します
 q, quit             操作を停止し、デバッガーを終了します
 d, detach           操作を続行し、デバッガーをデタッチします。

 k, Get-PSCallStack コール スタックを表示します

 l, list             現在のスクリプトのソース コードを一覧表示します。
                     現在の行から開始するには "list"、
                     行 <m> から開始するには "list <m>"、行 <m> から <n> 行分の
                     一覧を表示するには "list <m> <n>" を使用してください

 <enter>             stepInto、stepOver、または list の場合は最後のコマンドを繰り返します

 ?, h                このヘルプ メッセージを表示します。
```
 vとかを実行して確認すればok

 このパターンは、通常のデバッガにはなかったんでわかんなかった
#django で URL をバリデーションする例

```
from django.core.validators import URLValidator

URLValidator()('WAAAAAAA!')
```

```
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/django/core/validators.py", line 114, in __call__
    raise ValidationError(self.message, code=self.code)
django.core.exceptions.ValidationError: ['有効なURLを入力してください。']
```

# Original by Github issue

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








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
#django でメールアドレスをバリデーションする例

```
from django.core.validators import EmailValidator

EmailValidator()('WAAAAAAA!')
```

```
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/django/core/validators.py", line 191, in __call__
    raise ValidationError(self.message, code=self.code)
django.core.exceptions.ValidationError: ['有効なメールアドレスを入力してください。']
```

# Original by Github issue

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








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
pyenvのPythonにOpnecvが入らなかったから、既存のPythonの方から持ってくる

#経緯
RaspberryPiの既存のPythonでopencv入れると、/usr/local/lib/python3.5/dist-packages/cv2 の中にcv2.cpython-35m-arm-linux-gnueabihf.so が入るんだけど、pyenvのpython(3.4.1)の中には違うやつが入ってて動かしてみると、色々無いよと言われ一つずつ足りないやつを入れてたけど落ちていない...
て事で、シンボリック貼ればええやんとなった。
#環境
RaspberryPi3b+
stretch(Release 9.9)
Python3.5(元々)
Python3.4(pyenv)
#導入
まずは既存のpythonの方にopencvを入れる

###前処理

```
$ sudo apt-get install -y cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
```

```
$ sudo pip3 install opencv-python
   ・
   ・
   ・
TypeError: unsupported operand type(s) for -=: 'Retry' and 'int'
```

なんか、色々怒られた

```
pip3 install opencv-python
```

出来た。もうわからん
これで出来なければ[stack overflow](https://stackoverflow.com/questions/37495375/python-pip-install-throws-typeerror-unsupported-operand-types-for-retry)

###実行前処理

```
$ sudo apt-get install -y libcblas-dev libatlas3-base libilmbase12 libopenexr22 libgstreamer1.0-0 libqtgui4 libqttest4-perl
```

実行

```
$ python3
>>> import cv2
>>>
```

通った

###pyenvでも使えるようにしよう
まずはシンボリックを貼る ここでcv2.soとすることが大事

```
ln -s /usr/local/lib/python3.5/dist-packages/cv2/cv2.cpython-35m-arm-linux-gnueabihf.so /home/pi/.pyenv/versions/3.4.1/lib/python3.4/site-packages/cv2.so
```

あとは、opencv-pythonを入れた際についでに入るsixパッケージなどのpathを追加して再起動
[pathの追加の仕方(下の方に書いてる)](https://qiita.com/kai0706/items/8169d01a83f63fc4a0bd)

```
$ pyenv global 3.4.1
$ python
>>> import cv2
```

はい、終わり
Craft CMS で値出力時に正規表現で置換する

Craft CMS は replace フィルターで正規表現が使える

`{{ tag.title|lower|replace('/[^\\w]+/', '-') }}`

> Filters | Craft 3 Documentation
> https://docs.craftcms.com/v3/dev/filters.html#replace

regex_replace とかかと思ったけど違ったのでメモしておく。
ExpressionChangedAfterItHasBeenCheckedErrorについて

# ExpressionChangedAfterItHasBeenCheckedErrorとは
子コンポーネントに値を渡した後に親コンポーネントの値が変わってたときに出てくるエラーみたいです。

# エラーになる原因
##  Angular2の変更検知（change detection）
Angular2の変更検知オペレーションを理解しないとエラーになる原因がすっかり理解できないため、その処理を簡単にまとめてみます。
##  変更検知処理
チェックプロセス１
- 子コンポーネント・ディレクティブにバウンディングしているプロパティを更新する
- 子コンポーネントのngOnInit, onChanges, ngDoCheckをinvokeする
- 現在のDOMを更新する
- 子コンポーネントの変更検知処理（チェックプロセス１再帰）を実行する
- 子コンポーネントのngAfterViewInitをinvokeする

[引用元：Everything you need to know about the `ExpressionChangedAfterItHasBeenCheckedError` error](https://blog.angularindepth.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4)


各ステップの各プロパティはコンポーネントのoldValuesプロパティに保存しています。上記の処理が終わったら、下記の処理（digest cycle）を行い、oldValuesに保存された値と現在コンポーネントの値の比較が行われます：

チェックプロセス２
- oldValuesに保存された子コンポーネント用プロパティと現在コンポーネントもつ値が一致かどうかをチェック
- oldValuesに保存された現在のDOMを更新プロパティと現在コンポーネント持つ値が一致かどうかをチェック
- 子コンポーネントにチェックプロセス２を実行する

で、下記の例でエラーになる原因を説明させていただきます。
例えば、コンポーネントAと子コンポーネントBがあります。
コンポーネントAが子コンポーネントBに"text"プロパティを渡したい場合は：
1. コンポーネントAのチェックプロセス１を実行する（textプロパティをoldValuesに記録する）
2. コンポーネントBのチェックプロセス１を実行する（ここでおやコンポーネントAのtextプロパティが変った、理由は後ほど）
3. コンポーネントAのチェックプロセス２を実行する
4. oldValuesに記録されたtextプロパティと現在コンポーネントA持つtextプロパティが**不一致**のため、処理が中止され、ExpressionChangedAfterItHasBeenCheckedErrorがスローされます。

##  プロパティが変った原因
色々なケースがありますが、下記のようにコンポーネントBのngOnInit()で、おやコンポーネントAのtextプロパティを強制的に変更する例があります。：

```js
export class BComponent {
    @Input() text;

    constructor(private parent: AppComponent) {}

    ngOnInit() {
        this.parent.text = 'updated text';
    }
}
```
[引用元：Everything you need to know about the `ExpressionChangedAfterItHasBeenCheckedError` error](https://blog.angularindepth.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4)

# 解決策
```js
export class BComponent {
    @Input() text;

    constructor(private parent: AppComponent) {}

    ngOnInit() {
        // setTimeoutで、コンポーネントAのチェックプロセス２を先に実行させてから、おやコンポーネントAのプロパティ値を変更してもエラーにならない（チェック処理後値を変更するからだ）
        setTimeout(this.parent.text = 'updated text', 1000);
    }
}
```

# まとめ
- Angular2の変更検知処理がこのエラーになる原因です。
- 子コンポーネントのライフサイクル・フックでおやコンポーネントのプロパティを変更するのは危ないです。
Xcodeの設定を複数の端末で共有する

#はじめに
MacBookProを買い換えたときや、複数台のMacを利用するときに、端末ごとにXcodeの設定(テンプレートとショートカットキー)をいじるのは面倒だったのでGitHubのプライベートリポジトリで共有するようにした。

###1.リポジトリを作ってクローンする
GitHubでプライベートリポジトリを作って任意の場所にクローンする。
ここは別にGitHubじゃなくてDropboxとかでも良いと思う。
###2.コピー元の端末の設定フォルダをクローンしたレポジトリにコピペしてプッシュ
`/Users/"user_name"/Library/Developer/Xcode `配下にある。自分の場合は適当にTemplatesフォルダとUserDataフォルダをコピペした。
###3.コピー元の端末の設定ファイルを削除してシンボリックリンクを作る。
`/Users/"user_name"/Library/Developer/Xcode `配下にある`UserData`,`Templates`フォルダを削除。
そしてシンボリックリンクを作る。詳しくは[こことか](https://qiita.com/0084ken/items/6f39498c86fb592b2baf)

```
ln -s 'リポジトリにコピーしたフォルダのパス' '/Users/"user_name"/Library/Developer/Xcode'
```

自分の場合は

```
ln -s /Users/"user_name"/Git/xcode-setting/UserData /Users/"user_name"/Library/Developer/Xcode/UserData
```
```
ln -s /Users/"user_name"/Git/xcode-setting/Templates /Users/"user_name"/Library/Developer/Xcode/Templates
```

こうするとXcodeがリポジトリの`UserData`と`Templates`を読み込んでくれるようになる。

###4.設定をコピーしたい端末側でリポジトリをpullしてシンボリックリンクを作る
設定ファイルをリモートから取得した後に、3と同様にシンボリックリンクを作る。

これで、とりあえずショートカットキーの設定と、テンプレートを複数の端末で共有ができるようになったはず。
Cyberduckのブックマーク(接続先)をバックアップして復元する

MacのOSをクリーンインストールする際に Cyberduckのブックマーク(接続先)をバックアップし、復元した際の覚書です。

# 環境
- macOS Mojave 10.14.3
- Cyberduck 6.9.3

# バックアップするファイルのディレクトリ

`/Users/username/Library/Group Containers/xxx.duck/Library/Application Support/duck/BookMarks/`

**xxx.duckのxxx部分は環境によって異なります**

# ブックマークをバックアップし、復元する方法

説明するまでもないですが、上記ディレクトリのBookMarksに保存した接続先の設定ファイルが接続先の数だけ保存されています。
OSのクリーンインストール等でアプリを再インストールする際にバックアップしておいたファイルを元のディレクトリに戻してあげる事でブックマークを復元できます。

1. /Users/username/Libraly/ ディレクトリは不可視ディレクトリになっていますので```cmd + shift + .``` で不可視ファイルを表示させる

2. Finder等で``` /Users/username/Library/Group Containers/xxx.duck/Library/Application Support/duck/BookMarks/```の中身をコピーし、ブックマークをバックアップする

3. ブックマークを復元したい環境でバックアップしておいたBookmarks/の中身を復元先の同じディレクトリに移動する

4. Cyberduckを起動するとブックマークが復元されます

**Bookmarksを編集する際は、Cyberduckは終了しておいた方がいいかもしれません**


私はこの方法で復元できましたが、環境によって多少異なる場合がありますのであくまで自己責任でお願いします。
機械の制御システムの設計における安全分析の事例報告。安全（5）

機械の制御システムの設計における安全分析の事例報告

<この項は書きかけです。順次追記します。>
# １．概要
機械の制御システムの設計において、安全分析を、主にHAZOPの枠組みで実施したため報告する。
# ２．背景
ISO/IEC Guide 51は前の版からJISがあった。ISO/IEC Guide 50は、今回の版からJISを発行している。工場などでは子供を想定していない場合がある。小学生などが工場見学する場合には、JIS Z 8050を参考に、見学の安全を確保するとよい。
IEC 61882 HAZOPは2017年に改定されているが、JISになっておらず、化学プラント、電力、医療、金融、情報システムなど報告がある分野が限られている。今回、機械の制御システムの設計にあたって、安全分析を実施したため報告する。
# ３．課題
　工場における安全では、厚生労働省から様々な通達等が出ている [4][5][6] 。 これらの指針では安全感連携の規格を参照している場合がある[7]。さらに直接指針で参照していなくても、上記規格の参照関係は幅広い。　　
　FAシステムにおいては、他の機器との連携が重要である。複数の機器の連携には、間に工業用ロボットを入れて自動化をしている。そのため、工業用ロボット等を併用する場合と、人手が関与する場合についての分析を行うとよい。
　また、全自動の場合に、どこからどう止めるかは、個々の機器の緊急非常停止機能だけでは不十分で体系的な分析が必要となる。
分析には顧客の参加が大切である。しかし人手に頼る町工場では分析に時間を割く余裕がない。ロボットを利用する場合には、ロボット安全教育が義務付けられているが、ロボットを使わない場合の教育体系が課題である。
#4．分析
分析では、単独機器、関連システム、ライン全体の３種類とし、関係者として設計者、操作者、監視者、見学者、機器視点は単独機器、連携機器、制御機器、電源、網とする。
4.1 設計者
　設計者は、機械設計、電気設計、制御設計の３種類とする。
4.2 操作者
　操作者は、初動入力操作者、手動運転操作者と、全自動の事故・故障時等の操作者の３種類とする。
4.3 監視者
　監視者は、10台程度までの単独監視者と、数十台以上の複数人監視者を分析する。
4.4 見学者
　見学者は、成人、障碍者、子供の３種類を分析する。
4.5 単独機器
　単独機器では数種類の具体的な機器とロボットを分析する
4.6 連携機器は、単独機器の間をつなぐロボットをそれぞれの連携対象機器と一緒に分析する
4.7 制御機器
　制御機器は、単独機器の制御、連携機器の制御、ライン全体を分析する。
4.8 電源
　電源はシステム全体に影響を与える。瞬時電圧低下、高調波など過去の事故事例に基づいて分析する。
4.9 網
　今回対象としているEtherCATおよび厚生労働省が安全関連系での利用を想定しているWi-Fiを分析する。
# 参考文献
[1] JIS Z 8051:2015（ISO/IEC Guide51:2014）安全側面―規格への導入指針
[2] JIS Z 8050:2016(ISO/IEC Guide 50:2014) 安全側面－安全側面－規格及びその他の仕様書における子どもの安全の指針
[3] IEC 61882:2017, “Hazard and operability studies”, IEC
[4] 機械ユーザーから機械メーカー等への災害情報等の提供の促進について　厚生労働省労働基準局安全衛生部長　基安発0415第2号　平成26年4月15日
[5] 機械譲渡者等が行う機械に関する危険性等の通知の促進に関する指針(平成二十四年三月十六日)(厚生労働省告示第百三十二号)
[6] 危険性又は有害性等の調査等に関する指針・同解説 厚生労働省安全衛生部安全課 H18.3 
[7]機械制御ソフトウェアの制約条件「機械安全」, 小川清, https://qiita.com/kaizen_nagoya/items/a5d9eef7ad1d39652304, 2019
[11]災害支援無線系における安全分析手法の応用,小川清, 安全工学シンポジウム, 2019

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
### 文書履歴(document history)
ver. 0.01 初稿 20190512
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
####  Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
医療システムへのHAZOP適用。安全（4）

医療システムへのHAZOP適用

# １．概要
医療システムの設計、設置、運用において、安全分析を、主にHAZOP[1]の枠組みで実施した[2]。
# ２．背景
安全工学シンポジウムは、医療系の学会が参加しておらず、医療に関する工学との連携が十分ではない。そこで医療でも使われている安全分析手法IEC 61882 HAZOPは、医療システムの設計ばかりでなく、設置、運用においても有用であることを示す。
　具体例としては、公益財団法人日本医療機能評価機構の「再発・類似事例の分析」[2][3]を用いる。具体的には「ベッドからベッドへの患者移動」[4]のHAZOPを実施して、工業系とはおおきく違う点が一つあった。
また、日本皮膚悪性腫瘍学会がメラノーマガイドラインパブリックコメントを公募していたため題材として取り上げる[5]。
# ３．課題　　
### 3.1生物系に固有な課題
 医療系の分析を行う場合に、人間、病気は人間が設計したものではないため、工業製品のようになぜを問うのではなく、経緯や状態を把握することが重要である。医療機器、医療行為、薬品などの人間が考えて設計、製造したもの、人間の行為は、なぜを問うことに意味がある。
### 3.2 運用系に固有な課題
　運用系を分析する場合に、物の欠陥を問うよりは、欠陥のある物をなぜ使ったかを問う必要がある。しかし、欠陥とは言えない適用不適合の場合には、どのような分析をするとよいかが課題となる。設計、人の判断以外に、費用対効果のよい代替案が提示できないと、人への責任追及で終わってしまう。
### 3.3 遺伝子を扱う課題
遺伝子の解析には統計と確率を駆使し、膨大な遺伝子データを有効に解析する必要がある。また、遺伝子操作については十分に長期な試験の実施が必要であるが、特定の病気のように患者が待てない事情も存在する。
# ４．適用
### 4.1ベッドからベットへの患者の移動
ベッドからベッドへの患者の移動については、患者視点、看護者視点、ベッド視点の３つの視点を考慮することにより、抜け漏れをなくすことにした。
### 4.2 メラノーマガイドラインパブリックコメント
　一般用語については、カタカナ語、日本語、英語の一覧を作り、専門用語については、略号、URLなども一覧にし概念の齟齬がないようにした。
　遺伝子に関しては、ガイド作成後の文献にあたり、方向性の変化がないかを確認した。
　利益相反について経済的利益相反を排除するのはわかるが、学術的利益相反が理解できていない。医療の実情について、より詳しく関係者にも入ってもらった形で分析が必要であることがわかった。

# ５．まとめ
医療システムの設計、運用、医療現場の活動においてHAZOPは有効な想定外をなくすための道具として機能することが想定できる。しかし、遺伝子操作のような事例が少ない事象の想定外を洗い出すには有効であるが、妥当性・十分性を確認するためには、医療指針が必要である。

# 参考文献
[1] IEC 61882:2017, “Hazard and operability studies”. 
[2]医療系の現状と課題, https://qiita.com/kaizen_nagoya/items/5734255c49b6eca4565d, 2019 
[3]医療システムをHAZOPで分析する。安全（１９）https://qiita.com/kaizen_nagoya/items/16fdc44da4fbb4f12d30
[4] 公益財団法人日本医療機能評価機構,再発・類似事例の分析http://www.med-safe.jp/contents/report/similar.html
[5] ベッドからベッドへの患者移動に関連した事例(第13回報告書) -移動時に転落した事例- ,第13回報告書, 2019, http://www.med-safe.jp/pdf/ report_2018_4_R002.pdf
[6]メラノーマガイドラインパブリックコメントにIT関係者からの意見を出す準備, 小川清,https://qiita.com/kaizen_nagoya/items/30ce4888798c99678307 ,2019
[7] JIS Z 8051:2015（ISO/IEC Guide51:2014）安全側面―規格への導入指針
[8] JIS Z 8050:2016(ISO/IEC Guide 50:2014) 安全側面－安全側面－規格及びその他の仕様書における子どもの安全の指針　
https://qiita.com/kaizen_nagoya/items/fc9675686c229f7a155e

# Reference
Ethernet 記事一覧　Ethernet(0)
https://qiita.com/kaizen_nagoya/items/88d35e99f74aefc98794

Wireshark 一覧 wireshark(0)、Ethernet(48) 
https://qiita.com/kaizen_nagoya/items/fbed841f61875c4731d0

線網（Wi-Fi）空中線(antenna)(0) 記事一覧(118/300目標)
https://qiita.com/kaizen_nagoya/items/5e5464ac2b24bd4cd001

一覧の一覧( The directory of directories of mine.) Qiita(100)
https://qiita.com/kaizen_nagoya/items/7eb0e006543886138f39

プログラマが知っていると良い「公序良俗」
https://qiita.com/kaizen_nagoya/items/9fe7c0dfac2fbd77a945

小川清最終講義、小川清最終講義（再）計画, Ethernet(100) 英語(100) 安全(100)
https://qiita.com/kaizen_nagoya/items/e2df642e3951e35e6a53

＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
This article is an individual impression based on the individual's experience. It has nothing to do with the organization or business to which I currently belong.
### 文書履歴(document history)
ver. 0.01 初稿 　20190512
ver. 0.02 URL追記　20230311
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
####  Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
VagrantのCentOSにvimとZshとPreztoをインストールする

RubyとRailsの学習をするに当たって開発環境の構築でハマってしまったので自分用のメモです。
Vagrantを使いCentOSがインストールされている状態が条件です。
あくまで私の環境でこれでokだったので、参考にされる場合は自己責任でお願いします。

# centOSにvimをインストール

<https://qiita.com/silverskyvicto/items/386839cc3e2fcfa191fe>

vimのインストールが終わったらホームディレクトリ(/home/vagrant/)に.vimrcを設置

## vimのカラースキーム変更

<https://qiita.com/godgarden/items/9bded65665834438cc3e>

1. ~/.vim/color/を作成

2. カラースキームをダウンロード→~/.vim/colors/に設置(hybrid.vim)

3. `UltiSnips#TrackChange`エラーが出たら.vimrcのUltiSnipsをコメントアウト

# centOSにZsh+Preztoを導入

1. Zshをインストール
<https://qiita.com/Yoshipe/items/3535856ab1def69eaa6d>

2. bash-profileからzprofileに設定を引き継ぐ
この時点ではパスが通っていない為rubyコマンド,railsコマンドなどが使えない
bash-profileの中身をzprofileにコピーすることでパスなどの設定を引き継ぐ事ができる
<https://qiita.com/dach1_ken/items/23b3ef3bd09dd2c268b3#_reference-07bc5cc98fa0692fe3b6>

3. エラー対策
vagrant ssh でログイン時に
`/etc/bashrc:35: command not found: shopt`
`/etc/bashrc:46: command not found: shopt`
のエラーが出る
これはshoptコマンドはBash専用コマンドの為、Zshではエラーが出るらしい
/etc/bashrc のshoptコマンド部分をコメントアウトすることでエラーを回避できる

# gitに関する設定

1. git commit時にGNU nanoエディタが立ち上がるのをvimに変更
<https://qiita.com/naru0504/items/29d54d91e7823732ab9b>

2. .zprofileの20行あたりの"nano"を"vim"に変更
`source ~/.zprofile`
で設定を即時反映

3. `git init` をキャンセルする方法
作業ディレクトリの .gitを削除する
<https://qiita.com/b4b4r07/items/cac4abd9ae66537e2833>
競プロ用の個人的なメモ

# はじめに
この記事は個人的なメモです．
随時更新予定なので，内容が増えたり減ったりします．

## 競プロで押さえておくべきポイント？
AtCoderのABCに何度か挑戦してみたところ、300点以上の問題では必要とされる技能は3つに分解できそう．

>1. 提示された問題文から真に行うべき操作を見出し，知っているアルゴリズムをどう適用するか
>2. データ構造とアルゴリズムの知識
>3. 実装する言語の計算量の理解

`1.`に関しては文書化する方法を見いだせていないため書かない．
そのため本記事では`2.`と`3.`を扱う．`3.`ではpython3について扱う．

# データ構造とアルゴリズム，他
## データ構造
### List
ArrayListとLinkedListのものがある?
#### ArrayList
各要素を連続に配置しておき，途中の要素の位置を計算で割り出せる
ランダムアクセスが高速だが途中への要素の挿入，削除では不利？
#### LinkedList
各要素が次の要素の位置を持つことで鎖のようにつながるイメージのデータ構造
要素の挿入・削除は高速だがランダムアクセスは不利？

## 圧縮 / 符号化
### ランレングス圧縮 / ランレングス符号化
データ列の同じ値が連続するものをまとめて表す圧縮/符号化手法．
`0000111101`といったデータの場合，`[(0,4), (1,4), (0,1), (1,1)]`といった形式に置き換える．

## アルゴリズム
### DP / 動的計画法
Dynamic Programmingの略，日本語では動的計画法．
理解しやすい説明がこちらにありました．
https://qiita.com/drken/items/dc53c683d6de8aeacf5a

# Python3
## list
他記事を参考にする限り，後方からの1方向LinkedList
listの先頭に対してのアクセスは計算時間が大きくなる．
## collections.deque
競プロ系python記事でよく見かける
https://docs.python.org/ja/3/library/collections.html
## heapq
pythonでPriority Queueを扱いたい場合に出番がある
RaspberryPiでNumpyをインポートした際のエラー  ImportError: numpy.core.multiarray failed to import

#経緯
pythonでnumpyをインポートした際、ImportError: numpy.core.multiarray failed to importと言われたのでNumPyをアップグレードしたものの、なかなかこのエラーが消えてくれなかったので色々考えた。

#解決法1
###pipが古い
そもそものpipが古かったら、最新のnumpyをアップグレード出来ないのでpipをアップグレード

```
$ pip3 install --upgrade pip
$ pip3 install numpy --upgrade
```

これでもダメ？

#解決法2
###いくつかNumpyが入っていて、古いやつが呼ばれている
例えば、


```
$ python3
>>>import sys
>>>sys.path

['',
'/home/pi/.pyenv/versions/3.4.1/lib/python34.zip', 
'/home/pi/.pyenv/versions/3.4.1/lib/python3.4', 
'/home/pi/.pyenv/versions/3.4.1/lib/python3.4/plat-linux', 
'/home/pi/.pyenv/versions/3.4.1/lib/python3.4/lib-dynload', 
'/home/pi/.pyenv/versions/3.4.1/lib/python3.4/site-packages']
```

上記のように打つと、パッケージを探してくれるディレクトリをずらずらと並べ立ててくれる。
この時に注目するべきところは、<font color="Red">この記述の順番である。これはパッケージを探す順番である。</font>
例えば、初めの　'/home/pi/.pyenv/versions/3.4.1/lib/python34.zip'のディレクトリにnumpyが入っていればこいつを読み込まれてしまう。無ければ、次のディレクトリを探す。という感じだ。

過去に適当に他のディレクトリのpathを追加していてそいつが呼ばれているということもあり得る。

私は何も考えずに古いnumpyが入っている/usr/lib/python3/dist-packagesを追加していた。追加するのはいいが、一番最後に探してくれる追加の仕方をしていなかった。なので、最新のnumpyが入っている/home/pi/.pyenv/versions/3.4.1/lib/python3.4/site-packagesよりも早く呼び出されてしまっていたという事

#対策
pathの追加方法な何通りかあるが、方法によって動きが微妙に違う。
##追加方法１ .bashrcに追記
これは一番手っ取り早くpath追加できるが、パッケージの探索の際一番早く探索される

```
$ vi ~/.bashrc

# 以下の内容を追記
export PYTHONPATH="/usr/lib/python3/dist-packages"
```

保存して、再起動してpath一覧を見ると

```
$ python3
>>>import sys
>>>sys.path

['', '/usr/lib/python3/dist-packages', 
'/home/pi/.pyenv/versions/3.4.1/lib/python34.zip', 
'/home/pi/.pyenv/versions/3.4.1/lib/python3.4', 
'/home/pi/.pyenv/versions/3.4.1/lib/python3.4/plat-linux', 
'/home/pi/.pyenv/versions/3.4.1/lib/python3.4/lib-dynload', 
'/home/pi/.pyenv/versions/3.4.1/lib/python3.4/site-packages']
```

はい、一番先頭に来ましたね。


##追加方法2  .pth ファイルの追加
これは、検索してくれるディレクトリに.pthファイルを作成及びpathを追記しておくと、pthファイルのpathのディレクトリを一番最後に探索してくれるというものだ。

```
#検索対象ディレクトリに移動
$ cd /home/pi/.pyenv/versions/3.4.1/lib/python3.4/site-packages
$ vi path.pth

# 以下の内容を追記
/usr/lib/python3/dist-packages
```

保存して、再起動してpath一覧を見ると

```
$ python3
>>>import sys
>>>sys.path

['', 
'/home/pi/.pyenv/versions/3.4.1/lib/python34.zip', 
'/home/pi/.pyenv/versions/3.4.1/lib/python3.4', 
'/home/pi/.pyenv/versions/3.4.1/lib/python3.4/plat-linux', 
'/home/pi/.pyenv/versions/3.4.1/lib/python3.4/lib-dynload', 
'/home/pi/.pyenv/versions/3.4.1/lib/python3.4/site-packages',
'/usr/lib/python3/dist-packages']
```

最後に来ていることがわかりますね。他にも方法があるみたいなので、その辺は他のサイトにお任せします...
electronでmain processからencoderに画像を渡せない

以下のように画像を渡そうとした。


```ts
let staticPath = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
ff.input(path.join(staticPath, '/img/logo.png'))
```

1. staticファイルはちゃんとビルド時にsyncされている
2. asarを解答してみてもやはり入っている
3. しかしmain processから取得できない・・・

```js
    "asar": true,
    "asarUnpack": [
      "dist/electron/static"
    ]
```

ためしにこれを設定してみるもだめ・・・asarで圧縮しちゃうとstaticファイルが取得できない？
そんなわけ無いと思うんだけど設定ミスかも知れない。

いったんasarをfalseにすることでお茶を濁した。
PHPのアクセス修飾子: public, private, protected の使い分け

##はじめに
アクセス修飾子が必要な理由として第一に保守の容易さに挙げられます．
オブジェクト志向のカプセル化を想像するとわかりやすいかもしれません．
チーム開発をしていて自分がクラスを作る際は基本的に, 他の人がそのクラスを使いやすいように、使って良い機能だけ公開し、使ってほしくない機能は隠します。 
このようなシステムを作るときこのアクセス修飾子が役に立ちます．

##アクセス修飾子
アクセス修飾子はpublic, protected, private の三つがあり, 下に行くほどアクセスできる範囲が狭くなります．

| アクセス修飾子 | 意味 |
|--------|--------|
|     public   | 外部から参照できる       |
|     protected   | 変数、関数を宣言したクラスと継承されたクラスから参照できる     |
|     private   | 変数、関数を宣言したクラス内のみ参照できる  |

下記は説明のために作成したものです．
変数名にpublicなどをつけるという愚かな行為をしているため
コピペはしないでください


```php:親
class Parent{
  //$public, #protected, $private全てアクセスできる
  public $public;
  protected $protected;
  private $private;

  //privateで読み込みだけしていい場合このように公開する
  public function getPrivate{ 
    return $this->pra;
  }
}
```

Mainを継承

```php:子クラス
class Child extends Parent{
  // $privateはアクセスできない
  // $public, $protectedはアクセスできる
}
```

```php:クラス外
//$private, $protected はアクセスできない
//$publicはアクセスできる
```

##参照リンク
[PHPでクラスを使う](https://qiita.com/nogson/items/d0ef8a3295cbea8707ed)
[TomoBlogの技術書](http://tomoprog.hatenablog.com/entry/2018/08/19/114223)
Magic Leap MagicScript Landscape Application. UiTextEdit 

**Prepare**
Magic Leap One
https://www.magicleap.com/magic-leap-one

mlsdk v.0.20.0
https://creator.magicleap.com/downloads/lumin-sdk/overview

magic-script-cli v2.0.1
https://www.npmjs.com/package/magic-script-cli

magic-script-polyfills v2.1.1
https://www.npmjs.com/package/magic-script-polyfills

**Create Project**

```
magic-script init my-input org.magicscript.textinput "Text Input"
cd my-input
```


**Code**
Change app.js

```javascript
import { LandscapeApp, ui } from 'lumin';
const { 
    UiLinearLayout
  , UiText
  , UiTextEdit
  , Alignment
  , HorizontalTextAlignment
  , EclipseLabelType } = ui;

export class App extends LandscapeApp {
  onAppStart () {

    const prism = this.requestNewPrism([1.0, 0.5, 0.5]);
    const layout = UiLinearLayout.Create(prism);
    layout.setAlignment(Alignment.CENTER_CENTER);

    const input = UiTextEdit.Create(prism, "", 0.4, 0.05);
    input.setAlignment(Alignment.CENTER_CENTER);
    layout.addItem(input, [0.005, 0.005, 0.005, 0.005]);
    
    const text = UiText.CreateEclipseLabel(prism, ""
                               , EclipseLabelType.kT7);
    text.setAlignment(Alignment.CENTER_CENTER);
    layout.addItem(text, [0.005, 0.005, 0.005, 0.005]);

    input.onTextChangedSub(function(uiEventData) {
      text.setText(input.getText());
    });
    prism.getRootNode().addChild(layout);
  }
}
```

**Build**

```
magic-script build -i
```

**Run**

```
magic-script run --port=10000
```

**Reference**
UiTextEdit (MagicScript API)
https://docs.magicscript.org/lumin.ui.UiTextEdit.html

Text Entry (UiTextEdit) (Guide C++) 
https://creator.magicleap.com/learn/guides/luminrt-uitextedit

magicscript
https://www.magicscript.org/

Thanks!
APIの負荷テストをする際にSiegeを使ったけど、ハマったこと

ちょっとした話。
# APIの負荷テストにSiegeを使う
今、会社で利用している既存のAPIに、新規機能を追加する案件を請け負っています。
それにあたって、負荷テスト等が必要なのですが何も知識が無いので色々なツールで遊んでいました。
タイトルに書いたSiegeは、そのツール群の中の一つです。
## クエリパラメータつきのURLを試すには……？？
ひとまず、`-h`オプションで使い方を見てみました。

```
$ siege -h
SIEGE 4.0.4
Usage: siege [options]
       siege [options] URL
       siege -g URL
Options:
  -V, --version             VERSION, prints the version number.
  -h, --help                HELP, prints this section.
  -C, --config              CONFIGURATION, show the current config.
  -v, --verbose             VERBOSE, prints notification to screen.
  -q, --quiet               QUIET turns verbose off and suppresses output.
  -g, --get                 GET, pull down HTTP headers and display the
                            transaction. Great for application debugging.
  -p, --print               PRINT, like GET only it prints the entire page.
  -c, --concurrent=NUM      CONCURRENT users, default is 10
  -r, --reps=NUM            REPS, number of times to run the test.
  -t, --time=NUMm           TIMED testing where "m" is modifier S, M, or H
                            ex: --time=1H, one hour test.
  -d, --delay=NUM           Time DELAY, random delay before each requst
  -b, --benchmark           BENCHMARK: no delays between requests.
  -i, --internet            INTERNET user simulation, hits URLs randomly.
  -f, --file=FILE           FILE, select a specific URLS FILE.
  -R, --rc=FILE             RC, specify an siegerc file
  -l, --log[=FILE]          LOG to FILE. If FILE is not specified, the
                            default is used: PREFIX/var/siege.log
  -m, --mark="text"         MARK, mark the log file with a string.
                            between .001 and NUM. (NOT COUNTED IN STATS)
  -H, --header="text"       Add a header to request (can be many)
  -A, --user-agent="text"   Sets User-Agent in request
  -T, --content-type="text" Sets Content-Type in request
      --no-parser           NO PARSER, turn off the HTML page parser
      --no-follow           NO FOLLOW, do not follow HTTP redirects

Copyright (C) 2017 by Jeffrey Fulmer, et al.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.
```
うーん、クエリパラメータをつけてAPIを叩きたい時はどうすれば？？
## POSTメソッドのやり方ばっかり！
どうやら、`--content-type`をつければ良い感じらしい事がググってみて分かりました。
ただ、具体例が全部POSTメソッドばかりでした。
例えば以下のような。

```
$ siege --concurrent=50 --content-type="text/plain" 'http://example.com/api POST plain-text-content-here'
```
引用元：https://thornelabs.blog/posts/using-siege-to-load-test-your-website-and-api.html
## GETメソッドで試す
じゃあGETメソッドはどうするのか、色々試してみて分かりました。以下のようにすれば、問題ありませんでした。

```
$ siege --concurrent=50 --content-type="text/plain" 'http://example.com/api?type_id=1&id=1000'
```
このやり方に気づくのに、半日かかりました。
知識不足が原因でしょうか。。。
何はともあれ、やり方が分かって良かったです。
他の人が同じようにハマらないようにQiitaの記事にしました🤗
Desktop : OpenCV webcam preview tutorial

<H5>goal</H5>
Preview webcam frame in Java swing Gui.

```OpenCV_webcam4.java
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.videoio.VideoCapture;

public class OpenCV_webcam4 {
	
	static {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
	}
	
	static JLabel lblNewLabel = new JLabel("");
	
	public static void main(String[] args) {
		VideoCapture camera = null;
		camera = initCamera();
		
		JFrame layoutFrame = new JFrame();
		layoutFrame = layout();
		
		if(camera.isOpened()) {
			
			Mat webcam_frame = new Mat();
			camera.read(webcam_frame);
			
			layoutFrame.setSize(webcam_frame.width()+40,webcam_frame.height()+60);
			
			while(true) {
				camera.read(webcam_frame);
				BufferedImage frameImage = matToBufferedImage(webcam_frame);
				lblNewLabel.setIcon(new ImageIcon(frameImage));
			}
			
		}else {
			System.out.println("Error!!");
		}
		
		

	}
	
	private static VideoCapture initCamera() {
		VideoCapture capturecCapture = new VideoCapture();
		capturecCapture.open(0);
		
		return capturecCapture;
	}
	
	private static JFrame layout() {
		JFrame frame1 = new JFrame("");
		frame1.setTitle("從webcam 讀影像到 Java swing 視窗");
		frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame1.setSize(672, 480);
		frame1.setBounds(0,0,frame1.getWidth()+10,frame1.getHeight()+10);
		
		lblNewLabel.setBounds(21,23,571,413);
		frame1.add(lblNewLabel);
		frame1.setVisible(true);
			
		return frame1;
	}
	
	public static BufferedImage matToBufferedImage(Mat matrix) {
		int cols = matrix.cols();
		int rows = matrix.rows();
		
		int elemSize = (int)matrix.elemSize();
		byte[] data = new byte[cols * rows * elemSize]; 
		
		int type;
		matrix.get(0, 0,data);
		switch(matrix.channels()) {
			case 1:
				type = BufferedImage.TYPE_BYTE_GRAY;
			break;
			
			case 3:
			{
				type = BufferedImage.TYPE_3BYTE_BGR;
				// bgr to rgb
				byte b ;
				for(int i = 0 ; i < data.length ; i=i+3) {
					b = data[i];
					data[i] = data[i+2];
					data[i+2] = b;
				}
			}
			break;
			
			default:
				return null;
		}
		BufferedImage image2 = new BufferedImage(cols,rows,type);
		image2.getRaster().setDataElements(0,0,cols,rows,data);
		
		return image2;
	}

}

```
<h5>Result</h5>
![camera_frame.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276243/f45c83ba-05aa-cc10-bece-6761d0e3d01a.jpeg)
JavaのScannerでnext()とnextLine()の違い

#Scannerのnext()とnextLine()の違い
next()は標準入力で**空白**まで
nextLine()は標準入力で**改行**まで

#例
標準入力が`令和 2019/05`だった場合
next()→`令和`を取得
nextLine()→`令和 2019/05`を取得
メソッド探索の意味がわからんって人へ

以下「メタプログラミングRuby」で勉強したことです。

# メソッド探索
メソッド探索とは、その名の通り、呼ばれたメソッドを探すことである。

```ruby:ruby.rb
class A
  def hoge
    puts "hoge"
  end 
end

class B < A; end

obj_b = B.new
obj_b.hoge #=> "hoge"
```

obj_bがhogeを呼んだ時rubyの中では何が起こっているのだろうか。
rubyは以下の２つのことを行う。

・メソッドを探す(メソッド探索)
・メソッドを実行する

ではメソッド探索をする時、rubyはどのように動いているのだろう。

※レシーバ : 呼び出したメソッドが属するオブジェクト。hogeで言うobj_b
rubyはレシーバの「クラス」に入り、目的のメソッドが見つかるまで継承チェーンを上っていく。

「ん？レシーバのクラスに入る？」
「レシーバ自体は探索しないの？」

そうなのだ。メソッド探索はレシーバのクラスから探索を始めるのだ。
ここにrubyの秘密がある。
実はオブジェクトのメソッドは全てクラスに属しており、オブジェクトはクラスが持っているメソッドを参照しているだけなのだ。
だからメソッド探索は「レシーバのクラス」から探索を始めるようになっている。

obj_b.hogeの話に戻ろう。
ではobj_b.hogeを呼んだ時、rubyはまず何処を探すだろう？

そう、obj_bのクラスであるBだ。
しかし、クラスBにはhogeメソッドが定義されていない。
では次に何処を探すだろう？

rubyは「目的のメソッドが見つかるまで継承チェーンを上っていく」ので、次に探すのはクラスAだ。
クラスAを探して、ついにhogeメソッドを見つけることができた。

以上がrubyのメソッド探索である。
ここで覚えておくべきことは

・rubyはレシーバのクラスに入り、目的のメソッドが見つかるまで継承チェーンを上っていく。
・メソッドは全てクラスが持っている。オブジェクトはクラスが持っているメソッドを参照しているに過ぎない。

以上の２つである。
自分用メモ: イベントループってなんなのかわからなかったので調べてみた

## 気持ち
そもそもシングルスレッドで複数の処理を実行すること自体はそんなに問題じゃない。
しかし、その際にネットワークやファイル等のIO、要するにそのプログラムの外側とやり取りする際に発生する各種の応答への待ち時間が問題になるケースは多々ある。
そういった問題を解決するためのにイベントループがある。(プログラムの実行パターンと言うのかな？

## 資料
https://qiita.com/twipg/items/8f2a00354f6159cd1a5a
https://developer.mozilla.org/ja/docs/Web/JavaScript/EventLoop
https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%83%AB%E3%83%BC%E3%83%97
Rubyで書いたSlack botのスクリプトをHerokuにアップして常時起動させる

#はじめに
[前回作成した、Amazonランキングを表示してくれるBot](https://qiita.com/matsukazu1112/items/0ff2cfd3573fa67be88d)を、都度ターミナルからRubyを実行させるのではなく、常時起動させていきます。そのためにアプリをHerokuにアップロードしていくプロセスを説明していきます。

#大まかな流れ
- Heroku Toolbeltのインストール
- Gemfileの作成
- Procfileの作成
- Herokuにアプリをアップロードする
- Herokuにて常時スクリプトを実行させる

## Heroku Toolbeltのインストール

下記のコマンドでインストール出来ます。

```
$ brew tap heroku/brew && brew install heroku
```

必要に応じて[Herokuの公式記事](https://devcenter.heroku.com/articles/heroku-cli)も参考にしてください。

## Gemfileの作成
通常、Ruby単体で開発する場合、Gemfileは不要です。しかし今回は、RubyアプリケーションをHerokuにコンパイルする際に必要な `buildpack` をインストールします。buildpackインストール時に、Gemfileを参照した上で必要なファイルをインストールするため、Gemfileの作成は必須です。

```ruby

# Gemfile
source 'https://rubygems.org'
ruby '2.6.3'
```
当初Ruby2.3.0で開発をしていたのですが、Herokuにデプロイする際、Rubyのバージョンがサポート外であったため、エラーが起きたので、[こちらの記事](https://qiita.com/newburu/items/bb31ef2b429b5557b45a)を参考に、Rubyは最新版にアップデートさせました。

# Procfileの作成
また、今回はWorker Dynoにてバックグラウンド処理を回すので、フォルダ内にProcfileを作成し、Worker Dynoで行う処理を下記のように宣言します。

```
worker: bundle exec ruby ruby_bot.rb
```

#Herokuにアプリをアップロードする
続いてHerokuにデータをアップロードします。

下記のコマンドを順番に叩きます。

```
$ git init
$ git commit -m "init commit"
$ heroku create
$ heroku buildpacks:set heroku/ruby -a (アプリ名)
$ git push heroku master
```

4つ目のコマンドにて、rubyのbuildpackをインストールします。(アプリ名)の部分は、`$heroku create` で作成された、アプリ名を入れます。

###GitとHerokuを連携させる
Herokuでアプリが立ち上がった所で、GitとHerokuを連携させると便利です。

<img width="1191" alt="スクリーンショット 2019-05-12 10.22.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392294/8819eefe-292a-ef4f-e033-7550630fc2f4.png">

上記のように、繋込みをすると、GitのMasterにPushした内容が、Herokuに自動で反映されます。

# Herokuにて常時スクリプトを実行させる
最後に、今回の作成したSlack Botを常時起動させておくために、Worker Dynoを起動させる必要があります。先程Procfileで宣言していたため、ResourceタブにWorkerが表示されているので、こちらをONにして、Confirmします。

<img width="1226" alt="スクリーンショット 2019-05-12 11.02.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392294/551b3c04-773b-a3ff-4c1b-7378505eeeec.png">

#最後に
ターミナルからRubyファイルを実行させなければ、オフラインであったBotが、今回の作業を経て常時オンラインに変わりました！

<img width="207" alt="スクリーンショット 2019-05-12 15.46.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392294/e38ef6b9-3975-a196-7091-2eadb38628df.png">

Procfileの記載に誤りがあったり、Gemfileの頭文字が小文字になっているという初歩的なミスをしてしまい、buildpackが正常にインストール出来ずに時間を溶かしてしまいました。今後はApp化も進めていければと思っております。

#参考記事
- [herokuのworker dynoとweb dynoの違いって何?](http://www.stockdog.work/entry/2017/04/08/233848)
- [HerokuにデプロイでRubyバージョンサポート外エラー](https://qiita.com/newburu/items/bb31ef2b429b5557b45a)
- [【Heroku検討者向け】デプロイ方法５選！](https://qiita.com/pukka/items/412bcac29cabc36da6fa)
- [Herokuで単純なrubyスクリプトを定期的に実行する](https://qiita.com/kasei-san/items/909f17c2c42b7e3a8489)
Julia入門のための参考資料まとめ

参考にしている資料をまとめます。（適宜、更新します。

# 言語全般
- [The Julia Language(v1.1)](https://docs.julialang.org/en/v1/)
- [The Julia Language(日本語訳,v0.6)](https://hshindo.github.io/julia-doc-ja-v0.6/index.html)
- [The Fast Track to Julia:A quick and dirty overview of Julia](https://juliadocs.github.io/Julia-Cheat-Sheet/)
- [お気楽 Julia プログラミング超入門(広井 誠)](http://www.nct9.ne.jp/m_hiroi/light/julia.html)
- [実例で学ぶ Julia-0.4.1(yomichi's blog)](http://yomichi.hateblo.jp/entry/2015/12/01/022544)
- [高速でJuliaを学ぶ入門チュートリアル(bicycle1885)](https://github.com/bicycle1885/Julia-Tutorial)
- [Learn Julia in Y minutes(Learn X in Y minutes)](http://learnxinyminutes.com/docs/julia/)
- [The Julia Express(Bogumił Kami ´nski)](https://github.com/bkamins/The-Julia-Express)
- [Python使いやRuby使いにとってのJuliaの基礎　①文法のさわり(Nimimal)](https://qiita.com/Nimimal/items/410d6816d9b28cb1cb99)
- [Juliaに触って見ようと思った時に便利なリンク集(2017年末版) (currypurin)
](https://qiita.com/currypurin/items/92e6f6d75cf6c587f5ef)
- [ベクトルや行列の作り方(黒木玄)](https://nbviewer.jupyter.org/github/genkuroki/msfd28/blob/master/%E3%83%99%E3%82%AF%E3%83%88%E3%83%AB%E3%82%84%E8%A1%8C%E5%88%97%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9.ipynb)

# Plots
- [Plots - powerful convenience for visualization in Julia](http://docs.juliaplots.org/latest/)
- [プログラミング/julia/グラフの書き方(武内 修)](https://dora.bk.tsukuba.ac.jp/~takeuchi/?プログラミング%2Fjulia%2Fグラフの書き方)
- [Plots/GR: グラフ package のおすすめ(降籏 大介)](http://www.cas.cmc.osaka-u.ac.jp/~paoon/misc/julia/post/trouble-plots-package/)
- [Julia言語と Plots + GR で複素関数のgifアニメーションを作る(Optie_f)](http://optie.hatenablog.com/entry/2018/03/29/210619)

# DataFrames
- [DataFrames.jl](https://juliadata.github.io/DataFrames.jl/stable/index.html)
- [JuliaでCSV / DataFrameを扱う方法(yokuda)](https://qiita.com/Y0KUDA/items/3d3342ef08b28d5cda71)
- [JuliaでCSVを作成・更新してみた(yokotate)](https://qiita.com/yokotate/items/e8f0777250f24b972eb7)
- [10 Minutes to DataFrames.jl(sinhrks)](http://sinhrks.hatenablog.com/entry/2015/12/23/003321)
- [データフレーム(biostatistics)](https://stats.biopapyrus.jp/julia/dataframes.html)
state pattern

# state pattern
状態に依存する処理を状態オブジェクトへ委ねる

## ケース

振る舞いを状態によって変えたいとき

## 結果
### pro
状態に依存してる処理をきりだせる。

### con
## 実装対象

Contextクラス 状態Stateオブジェクトを保つクラス
Stateインターフェイス
ConcreteStateの実装

## example
```
class Connection {
    private let state: StateProtocol

    init() {
        self.state = CloseState()
    }

    func open() { state.open() }

    func close() { state.close() }

    func setState(state: StateProtocol) {
        self.state = state
    }
}

protocol StateProtocol {
    func open(connection: Connection)
    func close(connection: Connection)
}

class OpenState: StateProtocol {
    func open(connection: Connection) {} // open の時openは何もしない
    func close(connection: Connection) {
        connection.setState(state: CloseState())
    }
}

class CloseState: StateProtocol {
    func open(connection: Connection) {
        connection.setState(state: OpenState())
    }
    func close(connection: Connection) {} // close の時closeは何もしない
}
```

stateオブジェクトはContextオブジェクトのオペレーションを呼び出すことがメイン業務
Firebaseを使ってReactの認証処理をあっという間に完成させる

## 手順
- プロジェクトを作成する
- アプリを追加する
- firebase.jsの作成
- ログイン処理の実装

## プロジェクトを作成する
プロジェクトの作成は、Firebaseのトップページから簡単な設定で完了することができます。

## アプリを追加する
プロジェクトのトップからアプリを追加するとFirebase SDKの必要な情報を取得することができます。

## firebase.jsの作成
Firebase SDKの情報が取得できたら、Firebase Authentificationを利用するためにfirebase.jsを作成します。

コードは下記の通り。


```firebase.js
import firebase from "firebase";
import "firebase/auth";

const firebaseConfig = {
  apiKey: ***,
  authDomain: ***,
  databaseURL: ***,
  projectId: ***,
  storageBucket: ***,
  messagingSenderId: ***,
  appId: ***
};

firebase.initializeApp(firebaseConfig);

export default firebase;
```

## ログイン処理の実装

ログイン処理を実装するにあたり、必要な要素は下記の通り

- サインアップ処理
- ログイン処理
- ユーザーがログイン済みかどうかのチェック
- ユーザー情報の取得

では、それぞれのコードをご説明します。

### ユーザーがログイン済みかどうかのチェック

ユーザーがログイン済みかどうかチェックするためのコードは下記の通り。サービスのルートに近いファイル（create-react-appであればApp.js）などで一度これを実行すれば問題ないです。

```App.js
firebase.auth().onAuthStateChanged(user => {
    this.setState({ user })
})
```

### ログイン処理
ログイン処理を行うためには、`signInWithEmailAndPassword`関数を使用します。

```javascript
firebase.auth().signInWithEmailAndPassword(email, password).catch(function(error) {
  // Handle Errors here.
  var errorCode = error.code;
  var errorMessage = error.message;
  // ...
});
```

### サインアップ処理

ログイン処理と似ていますが、サインアップ処理を行う場合はfirebase.auth()の`createUserWithEmailAndPassword`関数を使います。

```javascript
firebase.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {
  // Handle Errors here.
  var errorCode = error.code;
  var errorMessage = error.message;
  // ...
});
```

これでログイン処理とサインアップ処理が完了しました。あとは、ログインとサインアップの画面を作成してそれぞれの処理を行うようにすればOKですね。

### ユーザー情報の取得
あとはユーザー情報を取得すれば、任意のユーザーを認識することが可能になります。

ユーザー情報の取得は、下記のコードで取得することができます。

```javascript
var user = firebase.auth().currentUser;
var name, email, photoUrl, uid, emailVerified;

if (user != null) {
  name = user.displayName;
  email = user.email;
  photoUrl = user.photoURL;
  emailVerified = user.emailVerified;
  uid = user.uid;  // The user's ID, unique to the Firebase project. Do NOT use
                   // this value to authenticate with your backend server, if
                   // you have one. Use User.getToken() instead.
}
```

uidは、ユーザーを一意に認証するためのidとして使用することができます。

また、Cloud Firestoreなどのデータベースを使用する場合も、個人に紐付いた情報はuidを使って管理する方法が一般的です。

## 参考
Firebase でユーザーを管理する
https://firebase.google.com/docs/auth/web/manage-users?hl=ja
特異メソッドの意味がわからんって人へ

以下「メタプログラミングRuby」で勉強したことです。

##特異メソッドとは
特定のオブジェクトに対して定義されたメソッドのこと。

```ruby:qiita.rb
wareki = "heisei"

def wareki.is_reiwa?
  self == "reiwa"
end

wareki.is_reiwa? #=>false
```
ここで定義したwareki.is_reiwa?はStringクラスの他のオブジェクトに影響を及ぼすことはない。warekiというオブジェクト(正確には"heisei")に対してのみ適用されるメソッドである。
特異とは普通と異なり特別なことだ。特異メソッドはその言葉通り、普通のメソッドとは異なり、特別に定義されたメソッドのことだ。
(英語ではsingular methodと呼称されている。singularには「個別の」という意味があるので、「個別に定義されたメソッド」と理解する方がしっくり来るかもしれない)


#クラスメソッドと特異メソッドの関係
```ruby:qiita.rb
class Hoge
  def self.class_method_a
    puts "class_method_a"
  end
end

Hoge.class_method_a #=> "class_method_a"
```
rubyを少しでも触ったことのある人なら、上のコードが何をやっているかわかるだろう。
Hogeクラスにclass_method_aクラスメソッドを定義している。
これを先の特異メソッドと見比べてみてほしい。

「なんか似てない？」

実はクラスメソッドも一種の特異メソッドなのだ。

「え？でも特異メソッドってオブジェクトに対して定義するものじゃないの？」
「クラスってオブジェクトじゃなくね？」

と思うかもしれないが、実はクラスもオブジェクトだ(ややこしい)。
もっとややこしい言い方をすると「HogeクラスはClassクラスのオブジェクト」だ。

クラスメソッド = Hogeクラス(Classクラスの「オブジェクト」)に定義されたメソッド
特異メソッド = 特定のオブジェクトに対して定義されたメソッド
クラスメソッド == 特異メソッド

以上のことからクラスメソッドも特異メソッドの一種なのだ。
Leetcode #12: Integer to Roman

```swift
private let ar = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
private let dict = [1: "I", 5: "V", 10: "X", 50: "L", 100: "C", 500: "D", 1000: "M",
                    4: "IV", 9: "IX", 40: "XL", 90: "XC", 400: "CD", 900: "CM"]
func intToRoman(_ num: Int) -> String {
    var str = ""
    helper(num, &str)
    return str
}

private func helper(_ target: Int, _ str: inout String) {
    if target == 0 {
        return
    }
    for num in ar {
        if num <= target {
            str += dict[num]!
            helper(target-num, &str)
            break
        }
    }
}
```
RaspberryPiにpyenvを入れて複数のPython動かすよ

#経緯
事の発端はPyaudioを使おうとしたが、Python3.4より後に出たバージョンでは動かない。
なので、Python3.4をぶち込む

#環境
RaspberryPi3b+
stretch(Release 9.9)
Python3.5(元々)
GCC 4.8.5

#導入
[RaspberryPiにpyenvでPython3環境を作る](https://qiita.com/ysdyt/items/f232e6481b44f92276cf)を参考にして入れていく。

前処理

```
$ sudo apt-get install -y git openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev
```

pyenvインストール

```
$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
```

終わったら、path設定

```
$ sudo vi ~/.bashrc

# 以下の内容を追記
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
```
<font color="Red">その後、再起動もしくは"source ~/.bashrc"を入力して設定を反映させましょう。
</font>
Pythonをインストール

```
$ pyenv install 3.4.1
　　　・
　　　・
ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?
　　　・
　　　・
Ignoring ensurepip failure: pip 2.1.1 requires SSL/TLS
```

まあ、なんかエラーが出る。

[pyenv Ubuntu16.04 ERROR: ](https://qiita.com/pollenjp/items/965b5a0dc95d7572cf41)
色々、入れていなかったみたい

```
$ sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
    libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
    xz-utils tk-dev libffi-dev liblzma-dev python-openssl
```

では再び、インストール

```
$ pyenv install 3.4.1
　　　・
　　　・
ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?
　　　・
　　　・
Ignoring ensurepip failure: pip 2.1.1 requires SSL/TLS
```

冗談だろ...

[ラズパイ python3.5.1 インストール エラー](https://teratail.com/questions/91643)
Debian 9 Stretchでは、libssl-devは、OpenSSL 1.1.xベースになっているので、あったlibsslを入れろとの事みたいです。

```
$ sudo apt install -y libssl1.0-dev
```

３度目の正直で、出来ました。
あとは、バージョン変更です。

```
$ pyenv global 3.4.1
```

確認

```
pi@raspberrypi:~ $ python -V
Python 3.4.1
```

元のPythonに戻るなら

```
$ pyenv global system
```

あとは、自分の環境だとPython3.4のpipが古かったのでpipの更新をしておく

```
$ pyenv global 3.4.1
$ pip install --upgrade pip
$ pip3 install --upgrade pip
$ pip --version
pip 19.1.1 from /home/.pyenv/versions/3.4.1/lib/python3.4/site-packages/pip (python3.4)
```

うん、いい感じ

#余談

```
$ sudo pip3 --version
pip 9.0.1 from /usr/lib/python3/dist-packages (python3.5)
$ pip3 --version
pip 19.1.1 from /home/.pyenv/versions/3.4.1/lib/python3.4/site-packages/pip (python3.4)
```

癖でsudo付けてたらImportErrorになりまくった
gulpのみでJSXをトランスパイルしたい

#gulpのみでJSXをトランスパイルしたい

JSXコンパイルは様々情報が出ていますが
gulpのみでやっているものが出てこなかったので調べてみました。

#前提
今回gulpの設定などはできているものとして進めます。

#検証環境

```environment.shell

$npx gulp -v
CLI version: 2.2.0
Local version: 4.0.1

```

#gulp-babel
以下のページに従って
gulpのプラグインをインストールします。
https://www.npmjs.com/package/gulp-babel

```installbabel.shell

npm install --save-dev gulp-babel @babel/core @babel/preset-env

```

#babel-plugin-transform-react-jsx
以下のページに従ってインストールします。
https://www.npmjs.com/package/babel-plugin-transform-react-jsx

```installreactjsx.shell

npm i babel-plugin-transform-react-jsx

```

#gulpfile.js
gulpタスクを書きます。

```gulpfile.js

var gulp = require('gulp'); //gulp本体の読み込み
var babel = require('gulp-babel'); //gulpプラグインの読み込み

//babelというタスクの定義をする
gulp.task('babel', function () { 
    return gulp.src('./es2015/*.js') //変換したいES2015で記述したファイルを指定
        .pipe(babel({
            plugins: ['transform-react-jsx']//babel-plugin-transform-react-jsxを使用することを定義
        }))
        .on('error', console.error.bind(console))//この行を有効にするとエラーの詳細を表示してくれる。
        .pipe(gulp.dest('./js')); //gulp.dest()でファイルの書き出し 今回はjsフォルダに
});

```

#備考
今回のようにローカルでコンパイルする意味としては
静的なファイルとしてアップすればサーバリソースを食うこともなく
様々な処理をする体制が整えられるというメリットがあります。

JSXのコンパイルを検索すると
webpackやCDN、babeljs.ioでの情報が出てきますが
gulpのみというものの日本語情報が出てこなかったのでまとめてみました。
babel-plugin-transform-react-jsxの最終更新が
2年前なので少し気になっています。ツッコミありましたらお願いいたします。

#参考URL
以下のページを参考にさせていただきました。ありがとうございました。
https://www.npmjs.com/package/gulp-babel
https://www.npmjs.com/package/babel-plugin-transform-react-jsx
https://stackoverflow.com/questions/33243895/how-convert-jsx-to-js-with-gulp-and-babel
【CSS】opacityだと透明度を子クラスまで継承してしまう問題の解決法

# 何が起きたか
### １.opacityで、背景画像を透過させようとした

```
.card {
  opacity: 0.8;
  border-radius: 1em;
  padding: 1.5rem;
  height: 100%;
  border: none;
}
```

### 2.ん？コンテンツの画像も透過してしまっている？

<img width="434" alt="スクリーンショット 2019-05-12 14.28.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286816/915c1a9f-82ae-0479-7777-30507ea29a9d.png">

### 3.opacityを子クラスまで継承してしまっているから、imgだけopacity:1にしよう〜！

```
.card-img {
  opacity: 1.0;
}
```

### 4.ならない！！どうしましょ！

# 解決策

### background-colorのrgbaのalpha値の透明度を変更！

```
.card {
  /* opacity: 0.8; */
  border-radius: 1em;
  padding: 1.5rem;
  height: 100%;
  border: none;
  background-color: rgba(255, 255, 255, 0.95); /* ←これを追加 */
}
```

**見事！画像が透過されていない！！**
<img width="430" alt="スクリーンショット 2019-05-12 15.04.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286816/e00d2f49-64ae-20a9-ff6d-cefd4da4aeca.png">

# RGBaとは
>CSS3から、RGBa(Red,Green,Blue,Alpha)という色指定のプロパティを使うことにより、色の透明度（alpha値）の指定が可能になりました。これによって、今まではベタ塗りでも透過している背景色などは画像で指定する必要がありましたが、CSSで記述できるようになりました。
RGB各色には0～255までの色の濃さを示す数値を入力し、最後のアルファ値には0～1（小数点で0.8、0.55など）で指定します。
背景色（background-color）の他にも、
・文字（color）
・枠線（border-color）
なども透過可能です。

 (参考)http://kawatama.net/web/1108

# まとめ
透過方法には、

- rgbaのalpha値を使う
- opacityを使う

方法の2種類があるみたいです！
今回のように、画像などには透明度を適用させたくない場合は、rgbaのalpha値を使えば良いと思います！
MacBookPro(mojave)のbootcampでblackmagic egpuを使う方法

bootcampでblackmagic egpuを使うのに大変手こずったので、そのやり方を載せておきます。
正式にはbootcampではblackmagic egpuをサポートしていないので、そのように使用することを考えて購入される方は慎重になった方がよろしいかと思います。

##環境
- MacBook Pro (13-inch, 2018, mojave バージョン10.14.4（18E226）)
- ディスクのフォーマットはAPFS方式
- bootcampでwindows10を使用
- blackmagic egpu(AMD Radeon Pro 580)

##方法
調べてみるとrEFIndやapple_set_os.efiを使う方法等出てきて、それらの方法を色々試してみてもできませんでした。
macの最近のアップデートにより出てきた、APFSというファイルシステムのせいらしい。最終的に解決に繋がったのは下のフォーラムでの報告のおかげ。
https://egpu.io/forums/pc-setup/bootcamp-windows-10-pro-april-2019-insider-recognising-blackmagic-egpu/

初めの方が投稿してらっしゃる通り、
1. Windows　Insider Programに参加する。
2. Windows 10をアップデート
僕はWindows 10、バージョン 1903となりました。
3. windows10を立ち上げている状態でblackmagic egpuを接続
僕は左奥のポートで接続しております。人によってはどのポートで接続するかで、できたりできなかったりするらしい。
すると自動でドライバがインストールされ、使用できるようになる。
webサイトに画像を掲載する

# はじめに

本日は、画像の挿入についてまとめます:raised_hand:
webページに掲載できる情報の１つに画像があります。
画像ひとつ載せるのにもいろんな属性が存在しています:family_wwbb:

## 画像を表示する「image(img)」要素

まず画像を挿入するためには「img要素」を使用します。

~~~HTML:
<img src="画像の場所・ファイル名" alt="画像の説明" title="画像やリンク先のタイトル名" width="画像の横幅" height="画像の高さ">
~~~

img要素は、src属性とalt属性をセットで書きます。

`src属性`は画像ファイルが置いてある場所・ファイル名を指定します。

`alt属性`は画像の説明を記述します。

##「src属性」 (source)

表示させる画像が保存されている場所と、ファイル名を指定します。

画像ファイル名は、相対URLか、絶対URLで記述しましょう。

### :frowning2:*<u>外部のサイトの画像ファイルを指定する</u>*

一般的に他のサイトの画像URLで指定するのはマナー違反となります。

画像の持ち主が画像を削除したり移動した場合には表示されなくなります。
著作権的な問題もあるので注意しましょう。

##「alt属性 」 (alternate attribute)

表示する画像をテキストで説明します。

なんらかの理由により画像の表示がされない場合、読み上げ機能が何の画像であるかを読み上げたり、記述されたテキストが表示されます。

googleなどの検索エンジンは、画像の見た目ではなくalt属性を読み取り何の画像が掲載されているのかを理解します。

なので、alt属性には`画像の内容`を書きましょう。

例えば、犬の写真なら「写真」ではなく「犬」と記述します。

「ブルドックの子犬」など具体的に書ければ尚良いですが「夏の朝に眠たそうにしているかわいいブルドックの子供」のように情報の詰め込みは何を伝えたいのかが分かりにくいです。

検索エンジンに伝わりやすいよう簡潔にまとめましょう。

## 「title属性」

画像やリンク先のタイトルを表示します。



### *<u>imgタグを続けて記述する</u>*

imgタグを連続で書くと画像が並んで表示されます。
(CSSでの記述が必要となります。)

~~~HTML
<img src="img/sakura.jpg" width="200px" height="100px" alt="桜"><img src="img/omoide.jpg" width="200px" height="100px" alt="思い出の場所">
~~~


### *<u>空要素とは？</u>*

img要素には終了タグはなく、内容を持たない単体となります。

このように内容を持たない要素を「空要素」と呼びます。



## 画像のサイズを指定

画像のサイズを指定する属性値はピクセル、またはウィンドウに対する％で指定します。

実際の画像の大きさではない数値を指定することも可能ですが、元のサイズより大きい数値や縦横の比率が異なる数値を入れてしまうと粗く表示されたりゆがんでしますので注意しましょう。
また、数値をいれていない属性は縦横比率を保ったなりゆきのサイズになります。

###「width」属性

width属性は画像の横幅を指定します。

###「height」属性

height属性は画像の高さを指定します。



## まとめ
画像を掲載することにより、テキストでは表現しきれない内容を感覚的に伝えることが可能です:eye:
多くのWebサイトに当たり前のように画像が使われていますね:relaxed: