OmniAICreator/Qiita-1.07M huggingface dataset:
PlantUMLを使ってみた

## はじめに
本記事はPlantUMLを少し触ってみてどうだったのかを書いた記事です。
実際の記法などは私も参考にさせていただいているチートシートの記事や公式サイトなどを見ましょう。（参考リンクにあります）
React.jsのコンポーネント間のやりとりをクラス図やシーケンス図にまとめたいと思い、そのような図を作成するツールを探していたところ、PlantUMLに行き当たりました。
自分がこれまでに使用したのは先述の通りクラス図とシーケンス図のみなので、それらに関してのみ触れます。
## 使ってみて
PlantUML関連の記事で頻繁に目にしますが、やはり大きな強みというのはこの二点になるでしょう。

- テキストで記述するので、git等で管理しやすい
- 細かいレイアウト調整の必要がない

PlantUMLの他にastahUMLも使ってみたのですが、レイアウト調整の必要がないのは大きいです。
テキストでの記述であるため、少し慣れは必要であるように感じました。クラス図はそうでもないのですが、シーケンス図はライフラインの書き方で最初ちょっと困りました。

図の書き方がふわふわしていますが、使い始めたばかりの時点での記事ですので、ご容赦ください。

## クラス図
```
@startuml
title class diagram

class List {
    + items: array
    - total: number
}

class ListRow {
    + isChecked: boolean
    + name: string
    + position: number
}

List o--> ListRow

@enduml
```
<img width="162" alt="コメント 2020-04-07 201810.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537455/4fefb57e-08eb-a314-ed61-610badf1d99f.png">
このようにクラス図を作成することができます。
最初は"-"はprivate, "+"はpublicとなっていれば最低限伝わるかと思います。クラス同士をつなぐ線については公式がきれいにまとめてくれています。

## シーケンス図
```
@startuml
title Edit List

participant List

-> List: toggleCheck()
    activate List
List -> ListRow: onChangeCheck()
    activate ListRow
deactivate ListRow
deactivate List

-> List: changeName()
    activate List
List -> ListRow: onChangeInput()
    activate ListRow
ListRow -> ListRow: validateName()
    activate ListRow()
    note right: 異常値の場合はエラーメッセージがセットされる
deactivate ListRow
deactivate ListRow
deactivate Row

-> List: changePosition()
    activate List
List -> ListRow: onPressArrowButton()
    activate ListRow
deactivate ListRow
deactivate List

@enduml
```
<img width="507" alt="コメント 2020-04-07 204825.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537455/9ab00573-60d6-e0a9-41b3-cdb89f93a904.png">
このようにシーケンス図を作成することができます。
ここではライフラインを多用してます。少し癖がありますが、使えれば見やすい図を作れます。

## 参考リンク
公式
https://plantuml.com/ja/

チートシートの記事
https://qiita.com/ogomr/items/0b5c4de7f38fd1482a48

導入に関する記事（少々古いですが、今もこれで導入できます）
https://qiita.com/couzie/items/9dedb834c5aff09ea7b2
appcompat v1.0.0 と v1.1.0 の Activity の違い

## 最初に
サポートライブラリの後任となる AndroidX ライブラリですが、
マイナーバージョンが上がると内部的なクラス関係がけっこう変更されています。


標準ライブラリと言っても良い AndroidX ですが [1.1.0](https://developer.android.com/jetpack/androidx/releases/appcompat) では以下のアップデートが行われました。

**1.0.0 以降の重要な変更**
![2020-04-07_18h25_33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486398/c23f2e56-66b7-a213-8f11-cbae3e200cb0.png)

## ２項目の AppCompatActivity について

この中の AppCompatActivity についてピックアップします。

```
AppCompatActivity が Fragment 1.1.0 を介して、
Activity 1.0.0 の ComponentActivity から推移的に拡張されるようになりました。
```
*推移的に拡張...* ←どうもイメージ掴みにくいですね。

元々 appcompat は、フラグメント機能を持つ  androidx.fragment:fragment に依存していました。

こちらの内部バージョンが上がり、
そのフラグメント内で新たに **androidx.activity に依存するように** なりました。

|  |androidx.fragment   |androidx.activity  |
|---|---|---|
|appcompat:1.0.0|1.0.0  |-  |
|**appcompat:1.1.0** |**1.1.0**  |**1.0.0**  |


### なにが変わるのか

**AppCompactAcitivty の継承関係** に変更が入りました。

```
【1.0.0】
AppCompatActivity
 +- androidx.fragment.app.FragmentActivity
  +- androidx.core.app.ComponentActivity
   +-  android.app.Activity

【1.1.0】
AppCompatActivity
 +- androidx.fragment.app.FragmentActivity
  +- androidx.activity.ComponentActivity
   +- androidx.core.app.ComponentActivity
    +- android.app.Activity
```
1.1.0 では androidx.activity.ComponentActivity が新規に追加され、FrameActivity のスーパークラスのパッケージ自体が別物になっています。


これにより、
・サードパーティ製のライブラリが appcompat:1.1.0 
・自分のプロジェクトを appcompat:1.0.0 
という状況で開発を行っていると... ライブラリ側にandroidx.activity.ComponentActivity を参照するコードがあると、ビルドが通らなくなります。
![2020-04-07_18h11_39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486398/9a996559-c122-4276-d3c9-5d2cabd41ce1.png)

ライブラリ側から見たら、aar 作成時には認識していたクラスが「いざリンクしよう！」としたら無くなったので当然ですね。
### 対策は？

この場合、サポートライブラリ時代と同じように

```
configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        if (details.requested.group == 'androidx.appcompat') {
            details.useVersion '1.1.0'
        }
    }
}
```
上記のように 1.1.0 とのリンクを明示することで、動作は可能です。


### ダウングレードの注意
なおライブラリ側をダウングレードさせるのは危険なのでご注意ください。

appcompact では他にも **ActionBarOverlayLayout.onNestedScroll() の引数が追加** されており（ 1.0.0 にない I/F が追加 ）、ライブラリ開発者がこの I/F で開発を行っていた場合に 1.0.0 と強制リンクを行うと、ビルドは成功し何となく動きます(※)

   ※インスタンス化する程度ではクラッシュしませんでした。

このとき考えられる弊害としては、
実際のリンクは 1.0.0 と行っているため、新しい I/F が呼ばれず古い onNestedScroll() が呼ばれることになり、ライブラリ開発者が想定していたロジックが呼ばれず... 気づきにくいバグ事象となります。

アップグレードする場合は、appcompact の変更点を確認してからするのが確実です。

##### 参考
[appcompat:1.1.0 について](https://developer.android.com/jetpack/androidx/releases/appcompat#1.1.0)
[activity:1.0.0 について](https://developer.android.com/jetpack/androidx/releases/activity#1.0.0)
[fragment:1.1.0 について](https://developer.android.com/jetpack/androidx/releases/fragment#1.1.0)
ユーザーの役割を分ける際はSQLアンチパターンを意識する

#●はじめに
Railsチュートリアルを参考にしポートフォリオを作成すると、Userモデルにadmin属性を追加しSTIで管理ユーザーを作成する事になるかと思います。
しかし、SQL的にはアンチパターンであるため注意が必要です。

#●結論
Userモデルと別に、adminモデルを作成する事が良い。

#●STI（Single Table Inheritance:単一テーブル継承）
STIは、単一の継承階層に所属するクラス群を、ひとつのテーブルを使って永続化する手法です。

![スクリーンショット 2020-04-07 20.20.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553621/809d4e17-6a2f-bb9a-d885-3e640fb5777f.png)

このように実装する方法ですね。しかしこの方法はSQL的にアンチパターンだという事です。
なぜこの方法が良くないかという点は、下記URLを参考にしました。
https://qiita.com/yebihara/items/9ecb838893ad99be0561

>短所
・特定のサブクラスに固有の属性に対してNOT NULL制約を適用できない
・特定のサブクラスのみを参照すべき他テーブルの外部キー制約が、誤ったサブクラスを参照することを防げない
・テーブルのカラム数が多くなりやすい
・一部のサブクラスでしか使われない列の値はNULLばかりとなり、見た目がスパースになる
>

#●まとめ
データベース設計時には、アンチパターンを意識する必要がある。
Rails初学者にとってSQLやDBは苦手意識を持ちやすい所だと思います（自分がそうです）
だからこそポートフォリオ作成前にはしっかりとデータベース設計をし、ER図を作成し、メンターに確認をして頂いた後に実装を進めることをオススメします。
トンネリングについて理解する（初学者自分めも）

#概要
トンネリングとはなにかを調べました。

#※ご注意点
ご覧頂きありがとうございます。
初学者のため、内容について確実に正しいものでない可能性があります。
申し訳ございませんが、その点につきましてご了承ください！！

#トンネリングとはなにか
トンネリングとは、「拠点間で通信するために仮想的な通信路をつくること」です。
私はVPN（Virtual Private Network）をイメージするとわかり安いと感じました。

#どういうときに使うか
主に事業者からサービスとして提供されるものですが、会社と自宅を専用線で接続する際などに使用されます。

#カプセリングとはなにか
トンネリングで通信経路をつくったあと、その経路上で安全に通信するために「カプセリング」を行います。
通常の規格とは異なるものを使用することで、外部のネットワークの影響を受けずにすむというものです。

通常ネットワークにおける通信では、EthernetフレームをIPパケットでカプセル化し、それをTCPパケット→HTTPメッセージのようにカプセル化して通信を行いますが、そのように「カプセリング」することで、各階層で他の階層を意識せずに通信を行うことができます。


#まとめ
・トンネリングとは仮想的な通信路をつくること
・カプセリングという外部の影響を受けずに通信する方法を用いる

#参考サイト
以下のページを参考にさせていただきました！
https://xtech.nikkei.com/it/atcl/column/17/011900625/011900006/
【Python】茶色コーダーになりました〜【AtCoder】

#【祝】茶色コーダーになりました〜
12回目でようやく茶色コーダー！！！
一番初めは2重for文も書けなかったのですごい成長！！！
パチパチパチ(拍手)〜
<img width="512" alt="スクリーンショット 2020-04-06 23.11.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183481/58407789-7c4a-9413-5cc6-ecdfce7eeade.png">

#####関連記事リンク
[【Python】緑コーダーになりました〜【AtCoder】](https://qiita.com/rudorufu1981/items/f5742dcef7ea907c16da)

#茶色コーダーになるまでにやったこと
競プロ初心者に参考になるかも！
ということでこれまでやってきた事を記事として残しておきます！

##①けんちょんさんの記事をいろいろ読んでわくわくする！
一番最初に読んだ記事はこれ！
[AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～](https://qiita.com/drken/items/fd4e5e3630d0f5859067)
まずはこれを一通り見てから、実際にPythonで解いてみました！
ほかにもわくわくする記事は、理解できなくても通勤時間とかに読んでいました！
計算量の記事とか、C問題(300点)レベルがとけるようになるための必須知識！
~~C++のソースコードは雰囲気で読めばいいと思うよ~~
とりあえず暇な時に他の人の記事も含めていろいろ読みました！


##②とりあえず(ほぼ)毎週夜9時にあるABCに毎回参加する！
＜唐突なラップ＞
一番初めはA問題だけでもACで喜ぶ素人！
でも、他の人の回答を見ると簡潔すぎるソースコード！
そしてそんな書き方があったのか！と、湧き出してくる感動と！
人生にわくわくを与えてくれるAtCoder！ありがと！

・・・

とにかく感動を覚えたソースコードはメモ帳に残して少しずつ自分のものにしていきました！
またレートも毎週のABCでちょっとずつ上がっていくしモチベも維持できました！

##③AtCoder Problemsで簡単な問題を解く！
[AtCoder Problems](https://kenkoooo.com/atcoder/#/table/)
Difficultyが小さいものから解いていって自信をつけていきました！

##④AOJのプログラミング入門を解く！
[AOJのプログラミング入門]
(https://onlinejudge.u-aizu.ac.jp/courses/lesson/2/ITP1/all)
この10トピック(40問)を２周する！
(※トピック11(クラスと構造体)は競プロで使用しないので除外)
入門と言いながらそこそこ歯ごたえがあったw
全てが良問！！！
この40問は非常に勉強になったし、実際、基礎力がしっかり身についた実感がありました！
俺にとってこれはめちゃくちゃ大きかったし自信にもつながった！
2次元配列、3次元配列の恐怖心もなくなりました！
この40問をやれば、まずA,B問題(100、200点)が99%解けるようになります！

##⑤武器を1つ1つ身につける。
DP(動的計画法)、キュー/スタック、DFS/BFS、bit全探索・・・
けんちょんさんの記事などを参考に日々勉強。
めちゃくちゃ典型的な基本問題は解けるようにする(現在進行形)。


**④と⑤の間くらいで、茶色になることができました！**


##おまけ タイピングの練習
アルゴリズムの勉強の息抜きににタイピング(寿司打)の練習で遊んでました。
2週間くらい毎日タイピングの練習やってたら、ブラインドタッチができるようになりました〜
ソースコードを書く速度も上がってる気がする→レート上昇に多少はつながってる？？？



次は緑コーダーになれるようにがんばろ！
[Android]SupportLibraryからAndroidxへの移行

はじめに
===
Android Support LibraryからAndroid xへ移行手順を書いていきたいと思います。
手順は簡単ですし、[Developerサイト](https://developer.android.com/jetpack/androidx/migrate?hl=ja)見れば一発で分かりますが画像メインでいきます。

環境
===
OS:Windows 10
Android Studio：3.5(統合は3.2以上だそうです)

移行前
===
赤のアンダーライン引いてるところがSupport Libraryです。
<img width="371" alt="androidx.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487320/0527ad78-5905-2b3a-f4c8-29485a9f5361.png">

手順
===
[Refactor] > [Migrate to AndroidX...]
<img width="941" alt="androidx_migrate.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487320/20adaafd-423a-faab-91e8-1ca1ab4ea9e6.png">

[Migrate]
※変更前のものをZIP化して保存しておきたい場合は「Backup project as Zip file」にチェック（デフォルトチェック済み）
<img width="940" alt="androidx_dialog_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487320/92af9f2c-93bd-0fa1-870a-9ca3c85c63c7.png">

[Do Refactor]
<img width="942" alt="androidx_dialog.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487320/5544aecf-156c-5d8a-d04f-fd45780c2f7e.png">

移行後
===
移行後は以下のようにandroidxに置き換わっています。
<img width="399" alt="androidx_after.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487320/332d7929-2870-a9d9-498f-8522f55d0c60.png">

参考文献
===
[公式](https://developer.android.com/jetpack/androidx/migrate?hl=ja)
axiosのインポートで詰まった。

## 解決策
先に解決策を書いておく。
時間がない方はこれだけでも大丈夫。
default exportsなので、下記のように定義する。

```ts
import axios from 'axios';
```
それでは本題。

## プロローグ
私はReact + Typescriptで業務に役立つWebアプリを作成している。
実装をしている中でプレーンなhttpリクエストの実装方法が少々煩雑ではないかと思っていた。

httpリクエストってみんながやってるはずなのになんでこんなに長いコードになってしまうんだ。
もっと美しいコードが書きたい。

そして見つけた。
axiosというライブラリを。

これで美しいコードを書くことができる。

## 第1章 npm install
見つけた以上インストールして、試してみるしかない。
さっそくインストールする。
念の為、ローカルインストールでインストールを行う。

```sh
npm install axios --save-dev
```

## 第2章 import
とりあえずimportしてみる。

```ts
import { axios } from 'axios';
```

しか〜し、なんかめっちゃエラーでた。
くそ。簡単に美しいコードがかけると思ったのに。

```
Module '"../../../../../TestTechnology/webpack/react/node_modules/axios"' has no exported member 'axios'. Did you mean to use 'import axios from "../../../../../TestTechnology/webpack/react/node_modules/axios"' instead?
```

## 第3章 エラー調査
調べてみるとaxiosって結構有名でインストールしている方がいっぱいいた。
どんな実装をしているか下記サイトで確認してみる。

```url
https://www.haneca.net/react-http-messaging/
```

あれ、import文の部分が何かおかしい。
{}があるか、ないかこの部分に原因がありそうだ。

調べてみよう。
美しいコードを書くためにはこれぐらいの調査は惜しまないでやらないと。

```
モジュール化を行うexportには、モジュールごとに複数のexportを行うnamed exportsとモジュールごとに1つのexportを行うdefault exportsがある。

```
参考サイト：https://qiita.com/senou/items/a2f7a0f717d8aadabbf7

```
Default exports
フロントの開発でも、1つのモデルに付き1つのモジュールでコンストラクタやクラスが使われる。
ES6のモジュールは、最も重要なexportする値default exportという形で選択できる
```
参考サイト：https://qiita.com/senou/items/a2f7a0f717d8aadabbf7

なるほど。
ということは{}はnamed exportと呼ばれる複数のexportがある場合に使うimportの方法なのか。
で、{}なしがDefault exportsと呼ばれる1モジュールに付き1exportがある場合に使うのね。

ではaxiosはどちらに当たるのか。
npm_modules/axios/index.jsを確認してみる。

```ts
module.exports = require('./lib/axios');
```

あ、一個だけexportされてる。
だから{}がいらないのか！

## まとめ
無事axiosをインストールすることが出来た。
axiosを使うことで美しいコードを書くことができそうだ。
エラーが起きたとき、なぜ起きたのかなぜ治ったのかをちゃんと理解することは重要だと改めて思う。

ちゃんと調べることって大事だね。
diff --ignore-matching-lines=REの正確な挙動

# はじめに
`diff`コマンドには`--ignore-matching-lines=RE`というオプションがあります。manを見ると"ignore changes where all lines match RE"と書かれていて、差分が正規表現にマッチしたときは無視するように見えます。
また[日本語訳](https://linuxjm.osdn.jp/html/gnumaniak/man1/diff.1.html)は「REGEXP にマッチするような行を挿入・削除するだけの変更を無視する。」となっています。

これらはかなり誤解を生む表現だと思います。（分かってから読み直すと言いたいことは分からないでもないですが…）
ここではこのオプションの正確な挙動について解説します。

# 具体例

以下の2つのファイルの差分を考えます。

```file1.txt
Date: 2020/4/7
Time: 20:00:00
```

```file2.txt
Date: 2020/4/6
Time: 21:00:00
```

普通に`diff`を取ると

```console
$ diff file1.txt file2.txt
1,2c1,2
< Date: 2020/4/7
< Time: 20:00:00
---
> Date: 2020/4/6
> Time: 21:00:00
```

となります。ここでDateの違いは無視してTimeだけ差分を取りたいとします。

```console
$ diff -I Date file1.txt file2.txt
1,2c1,2
< Date: 2020/4/7
< Time: 20:00:00
---
> Date: 2020/4/6
> Time: 21:00:00
```

しかし結果は全く変わりません。ここでfile1.txtとfile2.txtのDateとTimeの間に空行を入れてみます。

```file1.txt
Date: 2020/4/7

Time: 20:00:00
```

```file2.txt
Date: 2020/4/6

Time: 21:00:00
```

同じく`diff`を取ると

```console
$ diff -I Date file1.txt file2.txt
3c3
< Time: 20:00:00
---
> Time: 21:00:00
```

正しくTimeだけ取り出せました。

これはなぜかというと`--ignore-matching-lines`がマッチする対象は行ではなくhunkだからです。
hunkとは一塊の差分のことで、最初の例でいうと

```
1,2c1,2
< Date: 2020/4/7
< Time: 20:00:00
---
> Date: 2020/4/6
> Time: 21:00:00
```

が1個のhunkです。試しに空行を入れた状態で普通に`diff`を取ると

```console
$ diff file1.txt file2.txt
1c1
< Date: 2020/4/7
---
> Date: 2020/4/6
3c3
< Time: 20:00:00
---
> Time: 21:00:00
```

と2個のhunkに分かれています。このそれぞれのhunkに対して正規表現マッチをかけて、1個目のhunkを無視するというのが`--ignore-matching-lines`の正しい挙動です。

# ドキュメントには

[GNUのドキュメント](https://www.gnu.org/software/diffutils/manual/html_node/Specified-Lines.html#Specified-Lines)にはこのあたりも含めて正確な挙動が書いてあります。

> However, -I only ignores the insertion or deletion of lines that contain the regular expression if every changed line in the hunk—every insertion and every deletion—matches the regular expression. In other words, for each nonignorable change, diff prints the complete set of changes in its vicinity, including the ignorable ones.

ここに"every changed line in the hunk"とかかれている通り、hunkの全行が正規表現にマッチしないと無視されません。
ここまで理解するとmanに書かれている"all"の意味や、日本語訳の「だけの」という文言がhunk全てを指すというのが分かってくるのですが、初見でそれに気づくのはかなり厳しいですね…。

#
jupyterlab & matplotlibで作成したグラフのデータ点にリンクを貼る

# この記事について
記事タイトルの通りのことがやりたかった。
また使うことがあるかも知れないので、その方法を記録しておく。

# 手順
- matplotlib で リンク付きのグラフを作成
- `svg` 形式で保存
- Chrome などのブラウザでファイルを開く

# 環境
自分は jupyter-lab での作業でした。
バージョンはこんな感じ（pip freeze の結果より）

```bash
jupyterlab-server==1.0.7
matplotlib==3.2.1
```

# ファイル作成

```python
# 各種設定
import matplotlib.pyplot as plt
from IPython.display import set_matplotlib_formats

set_matplotlib_formats("svg")

# テストデータ準備
data_list = [[0, 1], [1,0], [1,1]]
label_list = ['google', 'yahoo', 'lightcafe']
url_list = ['https://www.google.com/', 'https://www.yahoo.co.jp/', 'https://www.lightcafe.co.jp/']

# グラフ作成
fig, ax = plt.subplots(1, 1, tight_layout=True)
for d, l, u in zip(data_list, label_list, url_list):
    x, y = d
    ax.scatter(x, y)  #点プロット
    ax.annotate(l, xy=(x, y), size=10,  #文字プロット
                url=u,
                bbox=dict(color='w', alpha=1e-6, url=u),
               )
# 保存
fig.savefig('test.svg')
```

# 確認
`test.svg` を ブラウザで開き、グラフ内のデータ点 or ラベルをクリックすれば
設定したリンクに飛ぶ。

ちなみに、Google Colaboratory で同じものを実行すると svg 保存しなくても、
セルの Output から飛ぶことが出来ました。

![IMG_20200408_091005.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78126/7ee13afb-2c56-fe0e-ec43-de2ee4135587.jpeg)


以上

# 参考
- https://stackoverflow.com/a/54121221
- https://matplotlib.org/3.2.1/tutorials/text/annotations.html#advanced-annotations
HYC New Production Building Successfully Capped

On March 31, with the pouring of the last piece of concrete, the main body structure of the HYC new production base was successfully capped. At present, the architectural configuration of new production building of the first phase project was taken shape. This is a brand new milestone of the whole HYC new industry park project.
![001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463940/34d18ff3-2226-7962-a43b-b022838622ec.jpeg)


Project is located in Qingyuan city, Guangdong Province, a total construction area of 40,000 square meters, and is composed of five-story multi-storey buildings. It is invested with 130 million yuan. Since July 2019, when the first phase project started construction, construction of HYC new industry park has been progressing steadily according to the schedule, with all projects moving forward smoothly. Now the main concrete structure of the production building was capped.
![7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463940/983fb22f-3a8f-e1c3-d0cb-ab99687d90ec.jpeg)


The completion of the HYC device production base, which carries the dreams of all HYC people, will help HYC greatly enhance its production capacity, R&D innovation ability and market core competitiveness, so as to better serve the society, and to start a whole new chapter with a brand new look. Let's look forward to the early completion of HYC beautiful new home!
![QQ图片20190315114151.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463940/bc4bb77c-a355-8791-0502-bd1c14e50ad2.jpeg)


About HYC
Founded in 2000, HYC CO., LTD (HYC) is the world’s leading passive optical devices OEM/ODM manufacturer who engages in R&D, producing, marketing and providing service of fiber optical products.

Our main products are: Optical Fiber Connector, WDM, PLC splitter, MEMS optical switch and other optical passive basics devices. HYC products and solutions are widely used in 4G/5G, Telecom, Data Center,  Cloud Computing industry and other fields.
www.hyc-system.com
Railsのlink_toメソッドについてまとめてみた

####link_toの書き方を調べたのでメモ程度に残しておきます。

##link_toの基本
railsで使うときはviewファイルで以下のように使います。

```
<%= link_to '表示される名前', 'パス', class: '付けたいクラス名', method: :HTTPリクエスト %>
```
htmlでいうaタグと同じ働きです。
classとmethodは省略可能で、methodは省略した場合:getと同じ意味になります。

例

```
<%= link_to 'ログイン', login_path, class: 'login', method: :get %>
<%= link_to 'ログイン', login_path, class: 'login' %>
```
これはそれぞれhtmlでは

```
<a class="login" data-method="get" href="/login">ログイン</a>
```
になります。

##要素を囲んでリンクにしたい場合
リンクにしたい要素をdoとendで囲んでやればokです。

```
<%= link_to 'パス', class: 'クラス名', method: :HTTPリクエスト do %>
  <div>
    <%# ここに要素が入ります %>
  </div>
<% end %>
```
先ほどと同様にclassとmethodは省略できます。

例
「app/assets/images/logo.png」に保存されたロゴをリンクにしたい。

```
<%= link_to root_path, class: 'logo', method: :get do %>
  <div>
    <%= image_tag "logo.png" %>
  </div>
<% end %>
```
のように使います。

※4/8追記　パスの指定が間違っていたので修正しました。
Vue ノート（3）：SPAとVueルーター

##サーバー側とクライアント側のルーティング

1.サーバー側ルーティング
クライアントはURLが変更されるたびにサーバーにリクエストを送信するため、これを「サーバー側ルーティング」と呼びます。

2.クライアント側ルーティング
ルーティングはJavaScriptを使用してブラウザー自体で行われます。Webページは1つのindex.htmlページから読み込まれ、クライアント側のルーティングを使用して、クリックされたリンクに応じて、さまざまなビューを動的に表示できます。多くの場合、表示する必要のあるビューはすでにブラウザーにロードされているため、サーバーにアクセスする必要はありません。

3.単一ページのアプリケーション（SPA）
1つのHTMLをロードして，ユーザーインタラクションに応じて動的にページを更新するWebアプリケーションです。ただし、単一ページアプリケーションを使用している場合は、コンテンツ間を移動する方法（クライアント側ルーティング）が必要です。


##Vueルーター
配置場所：
###/router/index.js

```javascript

import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";

Vue.use(VueRouter);

const routes = [
  {
    //URLの観点から、実際のルートを示します
    path: "/",
    //ルートを参照するためにアプリケーション全体でその名前を使用する
    name: "Home",
    //ルートでレンダリングするためにどのコンポーネントを指定する
    component: Home
  },
  {
    path: "/about",
    name: "About",
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () =>
      import(/* webpackChunkName: "about" */ "../views/About.vue")
  }
];
```

###App.vue

```html
<router-link></router-link>
```
router-link: 特定のルートにリンクすることを目的とする（vue-routerライブラリの）コンポーネントです。そして<router-view/>本質的には、コンポーネントのコンテンツがページにレンダリングされるプレースホルダーです。

router-view: router-linkで指定されたコンポーネントが表示されている場所に読み込まれます。
例えば、リンク/aboutをクリックしたら、views/App.vueの内容が「router-view」のところに表示されます

```vuejs

<template>
  <div id="app">
    <div id="nav">
      <router-link :to="{name:'Home'}">Home</router-link>
      <router-link :to="{name:'About'}">About</router-link>
    </div>
    <router-view />
  </div>
</template>
```

##redirectとエイリアス
要件:/aboutを/about-usへ変更しましたが、/aboutで同じく変更前のコンテンツにアクセスするできるようにしたい。

###ソリューション１：redirect

```javascript

  {
    path: "/about-us",
    name: "About",
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () =>
      import(/* webpackChunkName: "about" */ "../views/About.vue")
  },
  {
    path:"/about",
    redirect:{name:"About"}
  }
```

###ソリューション2：エイリアス

```javascript

{
    path: '/about-us',
    name: 'About',
    component: About,
    alias:'/about'
  }
```
ユーザーは/aboutと/about-usに移動すると、同じコンテンツを取得したりできます。
Pythonの環境構築 For Mac

pythonはまるっきり初心者で、触れたことがほぼないので環境構築からやります！

### PythonのVersion確認

 

Macにはpythonがpreinstallされているのでまずは確認。

    $ python --version
    Python 2.7.10
    
    $ python3 --version
    Python 3.7.7

あるので準備はこれでOK！

なんですが、ない場合や最新のpythonを利用したい場合は別途インストールする必要があります
pyenvをhomebrewでインストールしてpythonを落としていきましょう

### Pythonのインストール

    $ brew install pyenv

bash_profileなどに環境変数設定などをしたら完了

    $ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
    $ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
    $ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
    $ source ~/.bash_profile

インストールできるversionを確認して必要なやつをインストール

    $ pyenv install --list

利用できるversionを確認して、インストールしたversionを利用するように `pyenv global`を実行
(ここでは3.8.2をインストールします)

    $ pyenv install 3.8.2
    $ pyenv versions
    $ pyenv global 3.8.2
    $ python3 --version

これで準備終わり！
もうsample.pyみたいなの作って、python sample.pyで実行できちゃいます！

なんて簡単な環境構築。。
PropTypeは何もしてくれない


## まとめ

- PropTypeはランタイムバリデーションはしてくれない
- vue-property-decoratorを採用してるならPropTypeを用いる意味はない
- vue+typescriptでobject-styleで書くときにのみ型推論の面で意味がある

## 説明
PropTypeは型推論のための、型定義です。
vue + typescriptだけども、vue-class-component(vue-property-decorator)は使わず、object-styleで開発するときにのみ意味があります。

```typescript
Vue.extend({
  props: {
    propA: Array as PropType<Date[]>
  },
  methods: {
    methodA() {
      this.propA // ←Date[]と型推論される
    }
  }
});
```

これを、vue-class-component(vue-property-decorator)で用いることに意味はありません(と私は結論した)。

```typescript
class extends Vue {
  // @Prop({ type: Array as PropType<Date[]> }) propA: Date[] // こう書いても意味はなく
  @Prop({ type: Array }) propA: Date[] // これでよい

  methodA() {
    this.propA // どっちの書き方でもDate[]推論される
  }
}
```

まして、ランタイムバリデーションを期待して使うのはだめです。Arrayであることのチェックはしますが、中身がDateであるチェックは、 **PropTypeを使ったとしても**やってくれません。

また、PropTypeについては、公式ドキュメントも皆無です。

## 記事を書いたときの環境
vue: 2.6.11

## 参考
- https://github.com/vuejs/vue/blob/v2.6.11/types/options.d.ts#L149
- https://github.com/vuejs/vue/pull/6856
ストア版WinSCPでVSCodeが起動できない問題



Windowsストア版のWinSCPを使ったところ、VisualStudio Codeがエディタとして利用できなかった。

![a4e2cc5094e38ac5a3bd8341b2f54a42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28556/05650d38-1722-50e3-a490-3cd130edc5bf.png)

>エラー1392 ファイルまたはディレクトリが壊れているため、読み取ることができません。


エディタのパスを何度も確認したが、合っている。
ストア版ではなく、普通のダウンロード版WinSCPであれば正常に開ける。


参考記事
[Fixing WinSCP editor error](https://hajekj.net/2019/06/10/fixing-winscp-editor-error/)

こちらのブログによると、codeバイナリファイルをエディタパスに指定すると、起動できるらしい。

>C:\Users\%USERNAME%\AppData\Local\Programs\Microsoft VS Code\bin\code.cmd

これをやると、エディタ起動時に一瞬コマンドプロンプトが立ち上がるので若干気になるが、安定してVSCode起動できるようになった。

---

状況としては上のブログによると、Code.exe実行時に下記のCode.exeを見に行って、無効ファイルになっているのでエラーになるらしい。
>C:\Users\%USERNAME%\AppData\Local\Packages\MartinPikryl.WinSCP_tvv458r3h9r5m\

この場所を見ると確かに何かのファイルの残骸がある。
要するにストア版のバグだな。
Mp3 indir - php

Mp3 indir : mp3 indirme sitesi, ücretsiz mobil müzik şarkı mp3 indir. 
<a href="https://mp3indirten.site" rel="dofollow">mp3 indir</a>
<?php
$string=file_get_contents("https://mp3indirten.site");
Explode('x',$string);
?>
【React】クラスコンポーネントを関数コンポーネントに書き換え

#はじめに

React Way 的にはクラスコンポーネントよりも関数コンポーネントのほうが望ましい。
そこでクラスコンポーネントで書かれたコードを関数コンポーネントに書き換えた。

##書き換え前
```App.jsx
import React, { Component } from 'react';//オブジェクトをimportする時は{}を使う
import Child from './Child';

class App extends Component {
  render() {
    const characters = [
      { name: 'ヒトカゲ', hp: 80, mp: 30 },
      { name: 'ゼニガメ', hp: 100, mp: 20 },
      { name: 'フシギダネ', hp: 120, mp: 10 }
    ];

    return (
      //React.Fragmentのシンタックスシュガー
      <>
        {/* game属性とcharacters属性がpropsとして子要素へ渡される */}
        <Child game="ぽけもん" characters={characters} />
      </>
    );
  }
}

export default App;
```

```Child.jsx
import React, { Component } from 'react';

class Child extends Component {
  render() {
    // ※this.props.gameでも値は取れるけど分割代入活用
    const { game, characters } = this.props;

    return (
      <>
        <h1>{game}</h1>
        {characters.map(character => (
          // 一意なkeyをつける
          <div key={character.name}>
            <div>{character.name}</div>
            <div>{character.hp}</div>
            <div>{character.mp}</div>
          </div>
        ))}
      </>
    );
  }
}

export default Child;
```

##TSでは

```App.tsx
import React, { Component } from 'react';
import Child,{ Character } from './Child';

class App extends Component {
  render() {
    const characters :Character[] = [
      { name: 'ヒトカゲ', hp: 80, mp: 30 },
      { name: 'ゼニガメ', hp: 100, mp: 20 },
      { name: 'フシギダネ', hp: 120, mp: 10 }
    ];

    return (
      <>
        <Child game="ぽけもん" characters={characters} />
      </>
    );
  }
}

export default App;

```

```Child.tsx
import React, { Component } from 'react';

export interface Character{
  name: string,
  hp: number,
  mp: number
}

interface CharactorListProps{
  game: string,
  characters: Character[]
}

//<CharactorListProps>はジェネリクスでpropsの型を指定する
class Child extends Component<CharactorListProps>{
  render() {
    const { game, characters } = this.props;

    return (
      <>
        <h1>{game}</h1>
        {characters.map(character => (
          <div key={character.name}>
            <div>{character.name}</div>
            <div>{character.hp}</div>
            <div>{character.mp}</div>
          </div>
        ))}
      </>
    );
  }
}

export default Child;
```

##書き換え
```diff:Child.tsx
-import React, { Component } from 'react';
+import React, { FC } from 'react';//FCはFunctionComponentでもOK

export interface Character{
  name: string,
  hp: number,
  mp: number
}

interface CharactorListProps{
  game: string,
  characters: Character[]
}

-class Child extends Component<CharactorListProps>{
+//FCは関数コンポーネントの型//
+const Child: FC<CharactorListProps> = ({ game, characters }) => {


-render(){
-const { game, characters } = this.props;
  
  return (
    <>
      <h1>{game}</h1>
      {characters.map(character => (
        <div key={character.name}>
          <div>{character.name}</div>
          <div>{character.hp}</div>
          <div>{character.mp}</div>
        </div>
      ))}
    </>
  );
}

export default Child;
```
【AWS】DeepComposerを使ってみる

# DeepComposerについて
Generative Adversarial Networks（GAN）を利用し、音楽を生成するサービスです。
**GANのスキル向上のために、作られたサービスなので、すごい音楽が出力される訳ではありません。**

# 利用開始
AWSのアカウントは先に作成しておいてください。

## 料金について（2020年4月7日時点の情報）
AWS DeepComposerには、下記2つのサービスがあります。

- 推論  
  音楽を生成する
- トレーニング  
  生成するモデルを学習させる

それぞれに、無料利用枠があるので、気兼ねなく試してみる事ができます🙋‍♂️

### 推論の料金
◆ 無料利用枠
Generative AI を使って 12 か月間、最大500個の音楽作品を無料で生成する事ができます。
◆ 無料利用枠終了後の利用料
2.14 USD / 時
### トレーニングの料金
◆ 無料利用枠
30日間無料でトレーニングする事が可能です。
◆ 無料利用枠終了後の利用料
1.26 USD / 時

## サービスの選択
AWSマネジメントコンソールを起動して、サービスの選択画面で`DeepComposer`を検索し、選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401878/934b817b-7b86-cdf1-eeb4-1c444cacae1b.png)

## AWS DeepComposerの初期画面
初期画面に表示された`Get started`をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401878/f472780a-a18b-a1b6-bc21-bb8df63f15a5.png)

## 生成AIとGANの基本を学ぶ
Deep Composerを開くと、「Getting started」の内容が表示されるので、`Start learning generative AI`を選択します。

「Press play on machine learning」という画面が表示されますので、`Get started`を選択すると学習するページが表示されます。
全部英語で長いので翻訳しました→[DeepComposerの学習コンテンツ](https://qiita.com/s_Pure/items/29129cb9f1de7f4f55fe)

## 実際に生成してみる
DeepComposerを開いた際に表示される左のメニューから`Music studio`を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401878/029b07bc-bc6d-14e6-7b8d-4f9b065b246a.png)
## メロディーをキーボードで入力する
パソコンのキーボードでも鍵盤を操作する事が可能です。
鍵盤に書かれているキーを押して操作します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401878/53113189-7aad-96e8-f442-5556fd6192a5.png)
## 伴奏の自動生成
「Select Model」と記載されている部分から利用したいモデルを選択する
初期状態で選べるモデルは以下の通りです。

- Jazz
- Pop
- Rock
- Symphony
- Jonathan-Coulton

モデルを選択したら、`Generate composition`を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401878/488f3a38-2f35-8f65-fe19-6867ade2c8c0.png)

すると、すぐに伴奏が生成されます。

# まとめ
やはり、学習用のサービスであるため、現状は、変な伴奏を生成する部分が多いです。
時間があれば、トレーニングに挑戦して自分だけの伴奏生成モデルを作ってみたいです！

DeepComposerのメニューに「Learning capsules」という物があるので、この内容を参考に学習しながらGANについて勉強してみます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401878/497bf001-7210-b33a-32ad-6c4f21907ff1.png)
西暦と和暦変換するメソッド

# 背景
- ただ書いてみた

# コード
```python
def convert_year_to_wareki(year):
    wareki_start_year = {
        '明治': 1868, '大正': 1912, '昭和': 1926, '平成': 1989, '令和': 2019
    }
    if year < wareki_start_year['大正']:
        return f"(明治{year - wareki_start_year['明治'] + 1}年)"
    elif year == wareki_start_year['大正']:
        return f"(明治{year - wareki_start_year['明治'] + 1}年/大正{year - wareki_start_year['大正'] + 1}年)"
    elif year < wareki_start_year['昭和']:
        return f"(大正{year - wareki_start_year['大正'] + 1}年)"
    elif year == wareki_start_year['昭和']:
        return f"(大正{year - wareki_start_year['大正'] + 1}年/昭和{year - wareki_start_year['昭和'] + 1}年)"
    elif year < wareki_start_year['平成']:
        return f"(昭和{year - wareki_start_year['昭和'] + 1}年)"
    elif year == wareki_start_year['平成']:
        return f"(昭和{year - wareki_start_year['昭和'] + 1}年/平成{year - wareki_start_year['平成'] + 1}年)"
    elif year < wareki_start_year['令和']:
        return f"(平成{year - wareki_start_year['平成'] + 1}年)"
    elif year == wareki_start_year['令和']:
        return f"(平成{year - wareki_start_year['平成'] + 1}年/令和{year - wareki_start_year['令和'] + 1}年)"
    else:
        return f"(令和{year - wareki_start_year['令和'] + 1}年)"
```

# 参考
- https://qiita.com/BigFly3/items/7d6bcf649bedc2b91d3e

```javascript
   year2Wareki(year){
      let wYear = ''
      let gen = ''
      if(year > 2018){
        wYear = year-2018
        gen = '令和'
      }else if(year > 1988){
        wYear= year-1988
        gen = '平成'
      }else if(year > 1925){
        wYear = year-1925
        gen = '昭和'
      }else if(year > 1911){
        wYear = year-1911
        gen = '大正'
      }else if(year > 1867){
        wYear = year-1867
        gen = '明治'
      }
      if(wYear === 1) wYear = '元'
      return gen !== '' ? gen + wYear + '年' : false
    },
```

- https://qiita.com/slangsoft/items/700f136c625344d6af80
    - 令和にも対応している。
- https://algorithm.joho.info/programming/python/erajp-py/
    - このモジュールは令和に対応してなかった。

```python
def convert_to_wareki(d: datetime.date) -> str:
    dt_native = datetime.datetime.combine(d, datetime.time())
    return strjpftime(dt_native, f"{d.year}年(%O%E年) {d.month}月{d.day}日")
```
```結果
2020年(平成32年) 1月1日
```

- https://note.com/shimakaze_soft/n/n725edcf789cf
平行な直線と垂直な直線

## 2直線の平行条件と垂直条件（基本形）
2[直線の方程式](https://qiita.com/tydesign/items/4d3909a826363d8fc29f)（基本形）がそれぞれ、
$$L_1:y=mx+n,\ \ \ \ L_2:y=m'x+n'$$
である場合を考える。
#### 平行条件
直線 $L_1,L_2$ が平行であるということは、直線の傾きが同じであること。
直線 $L_1,L_2$ の係数 $m,m'$ は、直線の傾きを表しているので、$m=m'$ であることすなわち、
$$L_1とL_2が平行 \Longleftrightarrow m=m'$$
です。
#### 垂直条件
<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384860/05642675-1e7d-6026-4e58-7aa4bf15eea5.png"> <img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384860/3b742b26-acb6-a41c-789b-4d9320d4bd69.png">
直線 $L_1,L_2$ が垂直であるということは、2直線を平行移動して原点を通るようにした、
$$y=mx,\ \ \ \ y=m'x$$
が垂直であることと同じこと。
この2直線 $y=mx,y=m'x$ と直線 $x=1$ との交点を $P,Q$ とすれば、2直線が垂直であるためには、三平方の定理により
$$PQ^2=OP^2+OQ^2$$
が成り立つことが必要。
点 $P,Q$ の座標はそれぞれ $(1,m),(1,m')$ なのでこの式は、
$$(m-m')^2=(1+m^2)+(1+m'^2)$$
となる。この式を展開すると、
$$m^2-2mm'+m'^2=2+m^2+m'^2$$
したがって、
$$-2mm'=2$$
ゆえに、
$$mm'=-1$$
すなわち、
$$L_1とL_2が垂直 \Longleftrightarrow mm'=-1$$
です。

## 2直線の平行条件と垂直条件（一般形）
2[直線の方程式](https://qiita.com/tydesign/items/4d3909a826363d8fc29f)（一般形）がそれぞれ、
$$L_1:ax+by+c=0\ \ ,\ \ L_2:a'x+b'y+c'=0$$
である場合を考える。

この直線の式を変形して基本形の形にすると、
$$L_1:y=-\frac{a}{b}x-\frac{c}{b}\ \ ,\ \ L_2:y=-\frac{a'}{b'}x-\frac{c'}{b'}$$
よって**平行条件**は、
$$-\frac{a}{b}=-\frac{a'}{b'}$$
したがって、
$$ab'-ba'=0$$
**垂直条件**は、
$$\left(-\frac{a}{b}\right)\cdot\left(-\frac{a'}{b'}\right)=-1$$
したがって、
$$aa'+bb'=0$$
となる。
これはこの2直線の法線ベクトル $(a,b)$ と $(a',b')$ の内積が $0$ 、すなわち垂直なベクトルであることを示している。

## 1点を通り、直線に平行な直線と垂直な直線
点 $(x_1,y_1)$ を通り、直線 $ax+by+c=0$ に平行な直線と垂直な直線の方程式を求める。
この直線の式を変形すると、
$$y=-\frac{a}{b}x-\frac{c}{b}$$
よってこの直線の傾きは、$-\dfrac{a}{b}$ で、1点と傾きが与えられた[直線の方程式](https://qiita.com/tydesign/items/4d3909a826363d8fc29f)の公式により、
点 $(x_1,y_1)$ を通り、直線 $ax+by+c=0$ に**平行な直線**は、
$$y-y_1=-\frac{a}{b}(x-x_1)$$
したがって、
$$a(x-x_1)+b(y-y_1)=0$$
となる。

またこの直線に垂直な直線の傾きは、法線ベクトル $(a,b)$ より $\dfrac{b}{a}$ なので、
点 $(x_1,y_1)$ を通り、直線 $ax+by+c=0$ に**垂直な直線**は、
$$y-y_1=\frac{b}{a}(x-x_1)$$
したがって、
$$b(x-x_1)-a(y-y_1)=0$$
となる。
rspecで例外が起きたことを確認する

## この記事で書くこと　:pen_ballpoint: 
以下のような処理でのensureの処理が走ったかどうかを確認する方法


```rb
class Cat < ApplicationRecord
  validates :todays_foods, presence: true

  def sing!
    sing_a_song!
  ensure
    say_hello
  end

  def say_hello
    'にゃーん'
  end

  def sing_a_song!
    if todays_foods.empty?
      raise お腹が空いてたらエラー
      return
    end
    'にゃにゃにゃーん！'
  end
end
```

## テストの中身

```rb
  describe '#sing!' do
     context 'with exception error,' do
       let!(:cat) do
         cat = build(:cat, name: 'お腹すいた猫', todays_foods: 0)
         cat.save(validate: false) # validatesを無効にして作成。
         cat
       end
       it 'say にゃーん.' do
         expect do
           cat.sing!
         end.to raise_error(ActiveRecord::RecordInvalid).and(eq('にゃーん'))
       end
     end
  end
```
sshでの公開鍵認証の設定方法

# はじめに

公開鍵認証のやり方について、怪しい情報が多いので自分なりに整理した。
もし、間違ってたらコメントをいただけるとありがたいです。

# 作業手順

以下の作業はすべて**一般ユーザ（ログインするユーザ）**で実行する。管理者権限は不要。

###  鍵生成

<**sshクライアントで作業**>

公開鍵と秘密鍵がなければ、`ssh-keygen`で作る。
過去に作ったことがあれば使いまわすことになる。
（秘密鍵はユーザ自身の証明なので、あるユーザが複数のサーバにログインする場合でも
　同じ鍵で複数のサーバにログインすることになる）

コマンドを実行するとファイル名を聞かれるが、基本的にはデフォルトでいい。
パスワード（みたいなもの）を入力するとホームディレクトリの'.ssh/'に２つのファイルが生成される。
`id_rsa.pub`が公開鍵で他人に教えてもいいもの。
`id_rsa`が秘密鍵で誰にも教えてはいけない。
`ls -l`で読み取り権限を確認すると、`id_rsa`は自分以外も読めないようになっている。

### 公開鍵の登録

<**sshサーバで作業**>

ログインするユーザのホームディレクトリ直下の`.ssh/`（なければ作る）に`authorized_keys`というファイルを作る。
もしあれば追記する。
ファイルの中身（もしくは追記する内容）は公開鍵情報=`id_rsa.pub`の一行をそのままコピーする。

ディレクトリ`.ssh`とファイル`authorized_keys`を新たに作った場合はパーミッションを`chmod`で変更する。

```bash
chmod 700 .ssh
cd .ssh
chmod 600 authorized_keys
```

# 補足

ここまでの手順でサーバにログインできるようになるはず。

サーバ側に公開鍵、秘密鍵のどちらもコピーする必要はなく、クライアントに鍵のペア、サーバにauthorized_keysがあればログインできる。
ただし、多段sshでそこからさらに別の場所にsshログインする場合は、その踏み台サーバがsshクライアントになると考えて、そこにも公開鍵と秘密鍵を置くことになる。
この辺を理解して不必要に鍵のコピーをばらまくのはやめましょう。
Lambda layer作成のコツ

コツ
# コツ

コンパイル情報？を必要とするものと必要としないものがあるので注意。

必要としないもの→local PCでもOK.

必要とするもの→amazon linux (nomal)にて作成しなければならない

★展開して250MBこえるとアウト
★layerは5つまでしかできないので固めるのが吉

---
#### コンパイル情報を必要としないもの（localPC実施)
- 基本的にbinは消していい
- dist-infoも消していい
- キャッシュも消していい
- ドラックアンドドロップしてたらDSStore入っているので消す(ゴミなので)

```
find . -name "__pycache__" | xargs rm -rf
find . -name "*dist-info" | xargs rm -r
find . -name "*.so" | xargs rm
rm -r bin
find . -name ".DS_Store" | xargs rm
```

必ず親をpythonという名前のディレクトリにしてそれごと固めること！

```
ls
 python ←ディレクトリ

zip -r hoge.zip *
```

---
#### コンパイル情報を必要とするもの（Amazon linux実施)
- binや.cは残す
- dist-infoは消していい
- キャッシュも消していい
- python3環境をつくってそれでやるのがベスト

```:amazonlinuxを作る
1.作る
2.python3.6を入れる
　参照：https://qiita.com/hitobb/items/62bcd1c4995d996d4652
3.pip3 install virtualenv
4.virtualenv -p python3 hoge仮想環境名
5.source hoge/bin/activate
6.sudo yum groupinstall "Development Tools"
　参考：https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/compile-software.html
7.mkdir huga/python
8.pip -V
　python -V
　仮想環境が、python3, pip3になっていることを確認
9.pip install piyo -t ./huga/python
```

軽量化

```
find . -name "__pycache__" | xargs rm -rf
find . -name "*dist-info" | xargs rm -r
```

必ず親をpythonという名前のディレクトリにしてそれごと固めること！

```
ls
 python ←ディレクトリ

zip -r hoge.zip *
```



# pandas
★依存関係（pip入れると入ってくるもの）
・dateutil
・pandas
・numpy：別のlayerで入るのであればこれ削除して軽くすることも可能　70MB
・pytz
・six.py

#### pandas: 113MB
#### pandas-neednumpy: 37.3MB
numpyだけ削除したもの。このlayer単体では動かないので注意。

#opencv
★依存関係（pip入れると入ってくるもの）
・cv2
・numpy：別のlayerで入るのであればこれ削除して軽くすることも可能　70MB

ポイント
pandasとopencvを共存させるのであれば、
`pandas-neednumpy` としてpandasからnumpyを消したlayer①と、numpyが入ったopencv layer②を入れれば良い

### opencv: 154.6MB

# PIL

Pillowは特殊。
amazonlinux(python3.6なら普通のノーマルlinux）でインストールしたものをzipしないといけないっぽい。
Cのバイナリデータを含む？
dotenvで環境変数ではなく .env 使う | Node.js

```
$ npm install dotenv --save
```

プロジェクトのルートディレクトリに `.env` ファイルを作成します。

```.env

# これはコメント行
KEY1=VALUE1
KEY2=VALUE2
```

## 実装

```js

require('dotenv').config();

if (typeof process.env.KEY1 == 'undefined') {
  console.error('Error: "KEY1" is not set.');
  process.exit(1);
}

console.log(process.env.KEY1);  //=> VALUE1
```
SwiftのStringの中のバックスラッシュをreplacingOccurrencesで置換しようとする勘違い

おそらく[こちらのstackoverflow](https://stackoverflow.com/questions/34031036/swift-remove-single-backslash)と近しい課題にぶち当たったのだが、よくよく考えるとなんとも馬鹿な勘違いをしていたのでメモ。

単純に言うと以下の文字列からバックスラッシュ`\`を削除しようとしていた。

```swift
var str = "Hello, \"playground"
print(str) // => Hello, "playground

str.replacingOccurrences(of: "\\", with: "")
print(str) // => Hello, "playground
```

お分かりいただけるだろうか？

本来Stringというのは`"`などの特殊文字をエスケープするためにバックスラッシュをつける。だから上記の`str`は出力された際にバックスラッシュはつかない。が、今回対象の文字列がhtmlであり、かつ以下のようにXcodeのデバッグエリアに白黒で出力されていたので「バックスラッシュがHTMLの中に入ったまま出力されているから画面の表示が崩れたのだ」と錯覚してしまった...orz

<img width="539" alt="スクリーンショット 2020-04-07 18.33.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/99ee2bfc-c50b-8c80-c85c-3346ae4c9027.png">


```swift

var str = "<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n <head> \r\n "
str.replacingOccurrences(of "\r\n", with: "")
print(str) // => "<html xmlns=\"http://www.w3.org/1999/xhtml\"> <head>   "

str.replacingOccurrences(of "\\", with: "")
print(str) // => "<html xmlns=\"http://www.w3.org/1999/xhtml\"> <head>   "　あれ？変わってないな‥

str.replacingOccurrences(of "\"", with: "")
print(str) // => "<html xmlns=http://www.w3.org/1999/xhtml> <head>   "　ダブルクオーテーションも一緒に消すと消えるなぁ（シンタックスハイライトありならダブルクオーテーションを削除してるだけなのだが気付けない）

```
base64からの変換であったためか、改行コードの`/r/n/t`などが入っていたために勘違いを誘発しやすかったようだ。本来のStringの記法がふっとんでいた。Unicode文字の`\x5c`で置換しようとしてみたりで完全に迷路になった。
3.4 共有コンテンツをローカルにコピー

（2016年時点での内容をアーカイブとして掲載しているため、一部の掲載内容が最新情報とは異なる場合がありますので、ご了承ください。最新のIBM Cloudの情報は [IBM Cloud Docs](https://cloud.ibm.com/docs) や [IBM Cloud アップデート情報](https://www.ibm.com/cloud-computing/jp/ja/cloud-update/) 、[柔らか層本](https://ibm.ent.box.com/v/ibmcloud-yawaraka)をご参照ください。）

解決したい課題

ウェブ・サーバーのコンテンツをNFSサーバーで共有すると、高負荷時にはNFSサーバーのパフォーマンス劣化の原因となる課題がある。
 
ソリューション・パターン

ウェブ・サーバーのローカル・ディスクに、NFSサーバーからコンテンツをコピーして、NFSサーバーの負荷を軽減することができる。
 
インプリメンテーション

仮想サーバーを起動してNFSサーバーを設定してコンテンツの原本を保存する。
仮想サーバーの注文時に、第一ディスクと第二ディスクは、LOCALディスクかSANディスクを選択できる。LOCALディスクが高速(※参考資料）であるため選択する。
ウェブ・サーバーのコンテンツのアクセス先は、LOCALディスクへ設定する。
ウェブ・サーバーの起動時に、NFSサーバーをマウントして、LOCALディスクへコンテンツをコピーする。

効果

NFSサーバーにアクセスする必要がなく、パフォーマンス劣化の懸念が解決される。
NFSサーバーが停止することで、全体のサービスが停止するような事態を回避できる。
仮想サーバーのLOCALディスクはSANディスクより、また、物理サーバーのSATA,SASディスクなどよりIOPS性能が高いため、ディスク性能問題解決に役立つ。
 
懸念事項・注意点

コンテンツが更新された場合、ウェブ・サーバーから再度マウントしてコピーするか、rsyncで同期するなどの対応が必要である。
NFSサーバーが停止した場合、コンテンツの更新や、ウェブサーバーの増強ができなくなる。 NFSサーバーの代わりに、オブジェクト・ストレージをCloudFuseでマウントすることで、この懸念を解決できる。
 
参考資料

1.5.1 仮想サーバーのOSバックアップを取るには？
1.2.2 設定スクリプトの自動実行
5.9 Linuxにマウントするには？
ソフトレイヤー探検隊 第20回 「SoftLayerで利用できるディスクの種類とベンチマーク検証」 2014/9/7
3.3 共有コンテンツの利用

（2016年時点での内容をアーカイブとして掲載しているため、一部の掲載内容が最新情報とは異なる場合がありますので、ご了承ください。最新のIBM Cloudの情報は [IBM Cloud Docs](https://cloud.ibm.com/docs) や [IBM Cloud アップデート情報](https://www.ibm.com/cloud-computing/jp/ja/cloud-update/) 、[柔らか層本](https://ibm.ent.box.com/v/ibmcloud-yawaraka)をご参照ください。）

解決したい課題

ロードバランサーを用いて、複数のウェブ・サーバーへ負荷分散している場合、同じコンテンツが表示されなければならない。マスターとなるウェブ・サーバーからコピーを取得する方法もあるが、複数のウェブサーバー間でコンテンツが共有できれば簡単に解決できる。
 
ソリューション・パターン

マスターのコンテンツはNFSサーバーに配置して、ウェブ・サーバーはNFSサーバーでコンテンツを共有する。
 
インプリメンテーション

新たに仮想サーバーのインスタンスを起動して、NFSサーバーの設定を行う。
ウェブ・サーバーに、NFSクライアントを追加インストールする。
ウェブのコンテンツが保存されている領域をNFSサーバーへコピーする。
ウェブ・サーバーは、NFSクライアントとして、NFSサーバーのコンテンツ領域をマウントする。
効果

 
NFSサーバーのコンテンツを更新するだけで、全てのウェブサーバーのコンテンツが切り替わるため、大変便利である。
 
懸念事項・注意点

NFSサーバーに、ファイル・アクセスの負荷が集中することになり、パフォーマンスの劣化が懸念される。この懸念が課題となる場合、ローカル・ディスクにコンテンツのファイルをコピーして利用することで、ファイル・アクセスを分散させることを検討する。
NFSサーバーが単一障害点 (英: Single Point of Failure, SPOF)となるため、NFSサーバーをアクティブ・スタンバイ方式の冗長構成とするなどの考慮も必要となる。
オブジェクト・ストレージの可用性は高いため、この利点を利用するため、CloudFuseでファイルシステムとしてマウントもできる。しかし、サーバーとオブジェクト・ストレージ間の通信プロトコルはHTTPとなるため、性能劣化の懸念が残る。
NFSサーバーを物理サーバーへ移行することで、パフォーマンスの改善が期待できる。一方、ネットワーク回線の帯域に対して、ディスクのアクセス速度は必ずしも速くないため、ディスクの読み取り速度が、コンテンツを送り出す速度を決定づける懸念があり、ストレージのパフォーマンスに関する考慮が必要である。
 
参考資料

1.5.5 仮想サーバーから物理サーバーへ移行するには？
3.4 アクティブ・スタンバイのクラスタを構成するには？
3.4.1 ハートビートを用いたNFSのHA構成
3.4.2 キープアライブを用いたLVSのHA構成
5.8 Windowsのドライブとして利用するには？
5.9 Linuxにマウントするには？
3.2 サーバーのクローン

（2016年時点での内容をアーカイブとして掲載しているため、一部の掲載内容が最新情報とは異なる場合がありますので、ご了承ください。最新のIBM Cloudの情報は [IBM Cloud Docs](https://cloud.ibm.com/docs) や [IBM Cloud アップデート情報](https://www.ibm.com/cloud-computing/jp/ja/cloud-update/) 、[柔らか層本](https://ibm.ent.box.com/v/ibmcloud-yawaraka)をご参照ください。）

解決したい課題

可用性向上や負荷対策など、クラスターメンバーとして設定済みサーバーを増設するケース、また、ロードバランサー配下に同一設定のウェブ・サーバーを追加するケースなどがある。このようなケースに対して、サーバーを個々に設定していたのでは、時間と技術者が多く必要になり、ビジネス・チャンスを逃してしまう課題がある。
 
ソリューション・パターン

最初に設定するサーバーをマスターとしてイメージ・テンプレートを作成する。これを元にクローンのサーバーを幾つでも起動できる。ホスト名は起動時のパラメータとして付与でき、IPアドレスはVLANを指定することで、その中のサブネットから自動付与される。
 
インプリメンテーション

最初に作成したサーバーをマスターとしてイメージ・テンプレートを取得する。
ウェブ・サーバーの場合には、ローカル・ロードバランサーを準備しておく。 この場合のローカル・ロードバランサーは、HTTPやHTTPSなどのプロトコルに対して、サービス・グループを設定する。
プロビジョニング時に、ウェブ・サーバーの場合は、コンテンツのマスターから最新のコンテンツを引き込むことができるシェル・スクリプト等を準備する。 また、KVSの場合は、クラスタのメンバーとしてジョインするためのシェル・スクリプトを準備する。
これらのシェルは、プロビジョニング・スクリプトに登録しておき、サーバーのプロビジョニング時に簡単に指定できるようにする。
増設の必要性が生じた際に、イメージ・テンプレートから必要な数のクローンの仮想サーバーを起動し、プロビジョニング・スクリプトで自動初期化する。 ウェブ・サーバーの場合、ローカル・ロードバランサーの設定に増設した仮想サーバーを加える。
サブネットのIPアドレスが枯渇したら、VLANに新たなサブネットが自動追加されIPアドレスが割当られるため、これに対して管理スタッフが懸念する必要がない。

 
効果

クローンのサーバーを活用することで、サーバーの設定に関する人手を減らし、迅速な対応ができる。
マスターとなるイメージの変更管理を行い、熟成されたマスターイメージを再利用することで、サーバー構築の品質を高めることができる。
 
懸念事項・注意点

コンテンツのマスターとなるサーバーが、停止した場合、クローンサーバーの増設ができない。 このような事態を避けるため、信頼性の高いオブジェクト・ストレージに保存して、CloudFuseでコピーする方法も取れる。
コンテンツ管理のためのデータベースが、マスターサーバーで稼働している場合、データベースの接続先はマスターサーバーとする。
コンテンツの登録がある場合、必ずマスターサーバーで行いクローン側はコピーを取り込む。
 
参考資料

3.2 サーバーのクローンを作るには？
1.2.2 設定スクリプトの自動実行
1.5.1 仮想サーバーのOSバックアップを取るには？
3.3.1 ローカル・ロードバランサーを使うには？
5.8 Windowsのドライブとして利用するには？
5.9 Linuxにマウントするには？
3.1 サーバー数の動的増減

（2016年時点での内容をアーカイブとして掲載しているため、一部の掲載内容が最新情報とは異なる場合がありますので、ご了承ください。最新のIBM Cloudの情報は [IBM Cloud Docs](https://cloud.ibm.com/docs) や [IBM Cloud アップデート情報](https://www.ibm.com/cloud-computing/jp/ja/cloud-update/) 、[柔らか層本](https://ibm.ent.box.com/v/ibmcloud-yawaraka)をご参照ください。）

解決したい課題

テレビのニュースで、「情報を求める住民によって、ウェブ・サーバーにアクセスが集中して、一時的に繋がり難い状態になりました。 」といった報道がされることがある。 この問題の原因は、ウェブサーバーが設置された場所に繋がるインターネット回線の容量を超えたケースと、サーバーの処理能力が不足したケースがある。 SoftLayerのネットワークの回線容量は、十分な容量を確保されており、少々の事ではボトルネックにはならない。 一方、仮想サーバーの処理能力は、利用料金と比例する部分があり、経済的な理由からそれほど余裕を持たせることができない。 このように、アクセス集中による応答速度劣化と経済的な負担の課題がある。
 
ソリューション・パターン

オートスケールの機能によって、ユーザーからのアクセス数が増加した際に、自動的にサーバーを増設することができる。 反対に、アクセス数が減少した時にも自動的に削減できる。これにより、最初からアクセス量を見越したサーバー数を準備することなく、経済的に負荷対策を実施できる。
 
インプリメンテーション

増設したいサーバーのイメージ・テンプレートを作成する。
ローカル・ロードバランサーを注文して、サービス・グループを作成する。
オートスケールを注文して、サーバー増設と削減の条件設定、ロードバランサーの指定をおこなう。
サーバーの増設時にコンテンツを取り込むなどの初期化処理のために、ポスト・プロビジョニング・スクリプトを準備する。
オートスケール機能を有効化して、運用を開始する。
オートスケールのサーバー増設と削減の条件の設定では、CPU使用率が80％を30分以上、連続で超えたら、自動的にサーバーを増設するといった設定ができる。
さらに、上記のCPU使用率以外に、ネットワークの受信量や送信量、毎週の曜日、時間指定もできる。
ローカル・ロードバランサーを設定する場合、自動的に増設になったサーバーへ、リクエストの振り分けが開始される。
KVSのクラスタに適用する場合は、ロードバランサーを設定せず、クラスタ・メンバーの平均CPU使用率が設定値を超えたら、メンバーを自動的に追加することができる。
 
効果

繁忙期のサーバー増設、想定外のリクエスト増加への対応が、このオートスケールの機能一つで可能になる。
繁忙期の負荷に耐えられるように、最初からサーバーを準備する必要がなく、無駄な費用を発生させない。
 
懸念事項・注意点

増設サーバーは、イメージ・テンプレートの作成時点の状態で起動される。したがって、イメージ作成後に、追加・変更されたものは、反映されていない点に注意が必要である。
数分間の内に、急速に負荷が増加する様なものは、オートスケールでは増設が追いつかない。このようなケースでは、前もって増設するべきである。
ピーク時間帯が予測可能な場合は、時刻指定やマニュアル操作で、事前に起動して動作確認することが望ましい。
オートスケールは、ローカル・ロードバランサーに対してのみ連携できる。一方、NetScalerの場合は、振り分け対象を追加するなどの仕掛けを別途作成する必要がある。
 
参考資料

1.2.2 設定スクリプトの自動実行
1.5.1 仮想サーバーのOSバックアップを取るには？
3.3.1 ローカル・ロードバランサーを使うには？
3.7 オートスケールを利用するには？
 
NetScalerとAutoScaleを連動させるために必要なAPIのリンク
nsnitro 1.0.31 A simple library to control Citrix Netscaler 9.2+ with NITRO API https://pypi.python.org/pypi/nsnitro
SoftLayer 3.3.1 A library for SoftLayer's API https://pypi.python.org/pypi/SoftLayer
3. 動的コンテンツの処理

（2016年時点での内容をアーカイブとして掲載しているため、一部の掲載内容が最新情報とは異なる場合がありますので、ご了承ください。最新のIBM Cloudの情報は [IBM Cloud Docs](https://cloud.ibm.com/docs) や [IBM Cloud アップデート情報](https://www.ibm.com/cloud-computing/jp/ja/cloud-update/) 、[柔らか層本](https://ibm.ent.box.com/v/ibmcloud-yawaraka)をご参照ください。）

3.1 サーバー数の動的増減
3.2 サーバーのクローン
3.3 共有コンテンツの利用
3.4 共有コンテンツをローカルにコピー
3.5 セッション情報の共有
3.6 静的コンテンツの退避
3.7 URL書き換えプロキシーの配置
3.8 キャッシュの配置
3.9 スケジュールに合わせたサーバーの増減
opencv.jsのダウンロード方法

#結論
以下のコマンドでとってこれる。(ver 4.3.0)

```
curl https://docs.opencv.org/4.3.0/opencv.js -o opencv.js
```

#OpenCV.jsとは
公式から出ているOpenCVのJavascript版です。

https://docs.opencv.org/4.3.0/d5/d10/tutorial_js_root.html

#公式での入手方法
一応、公式ではopencv.jsに関しては自前でビルドするように書いてある。
https://docs.opencv.org/4.3.0/d4/da1/tutorial_js_setup.html
これをwslのUbuntu18.04でやってみたが、環境変数周りがうまくいかないのか、ビルドできなかった。

↓これのあと

```
$ source ./emsdk_env.sh
Setting environment variables:
EMSDK = /mnt/c/Users/hattt/Desktop/emsdk

This is rm_wrap: Do not use any options.
```
↓これになってビルドが通らない

```
$ python ./platforms/js/build_js.py build_js
Args: Namespace(build_dir='build_js', build_doc=False, build_flags=None, build_perf=False, build_test=False, build_wasm=False, build_wasm_intrin_test=False, clean_build_dir=False, cmake_option=None, config='/mnt/c/Users/hattt/Desktop/opencv/platforms/js/opencv_js.config.py', config_only=False, disable_wasm=False, emscripten_dir=None, enable_exception=False, opencv_dir='/mnt/c/Users/hattt/Desktop/opencv', simd=False, skip_config=False, threads=False)
Cannot get Emscripten path, please specify it either by EMSCRIPTEN environment variable or --emscripten
```
ここで粘ってもよかったのだが、もうめんどくさくなったので公式のサイト上で動いているビルド済みのものをダウンロードすることにした。
意外とダウンロードについて触れている記事がなかったので記述しておく。

↓赤丸のところにある
![opencvjs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467051/ff785c31-df23-88ea-191f-7b1a736e92e9.png)

#ダウンロード方法
curlでさくっと取ってくる。
取ってきたもので試してみたが、問題なく動いた。
ビルドしないといけない理由をいまいち理解していないので、もしかしたら使用方法によっては不具合があるのかも。
curlコマンドはWindowsでも最近実装されたので、どのOSでも行けるはず。

```
curl https://docs.opencv.org/4.3.0/opencv.js -o opencv.js
```
2.4 アプリのヘルスチェック

（2016年時点での内容をアーカイブとして掲載しているため、一部の掲載内容が最新情報とは異なる場合がありますので、ご了承ください。最新のIBM Cloudの情報は [IBM Cloud Docs](https://cloud.ibm.com/docs) や [IBM Cloud アップデート情報](https://www.ibm.com/cloud-computing/jp/ja/cloud-update/) 、[柔らか層本](https://ibm.ent.box.com/v/ibmcloud-yawaraka)をご参照ください。）

解決したい課題

ウェブ・アプリケーションの不具合によって販売機会を逃すことは、ビジネス上の損失であり、重要な課題である。 ところが、監視システムのエージェントを使ってサーバーやプロセスを内部から監視するだけでは、この様な問題の発見は難しいという課題がある。
 
ソリューション・パターン

ロードバランサーからアプリケーションの動作チェックに加えて、他地域のデータセンターの仮想サーバーからアプリケーションを監視することで、応答時間などユーザーの体感に近いモニタリングを実施できる。
 
インプリメンテーション

外部からURLアドレスをアクセスして、アプリケーション・サーバーとデータベース・サーバーの接続などを監視するための設定を行う。
ヘルスチェック対象のウェブ・サーバーが2台、そして、ローカル・ロードバランサーを配置する。
ローカル・ロードバランサーに対して、HTTPのカスタムチェックに、チェック・プログラムのURLを設定する。
このチェック・プログラムは、データベースやLDAPなどのサービスをアクセスする確認プログラムである。 このプログラムが問題を発見した場合、ローカル・ロードバランサーへ正常時と異なる文字列を返すことで異常を通知する。
さらに、他地域のデータセンターに、アプリケーションのモニタリング用の仮想サーバーを配置する。
このモニタリング用の仮想サーバーから、ウェブサーバーのパブリックIPアドレス、ロードバランサーのサービス用のIPアドレスを通じて、定期的にチェック・プログラムをアクセスして健全性を確認する。
監視対象のURLアドレスから異常を示す応答が返ってきたら監視システムへ異常を通知する。
このモニタリングでは、時間ごと機能別の応答時間などの分析を加えることが可能となり、サイトのサービス品質を高めることができる。

効果

アプリケーションの異常を素早く検知して、対応を開始できるため、営業的損失を最小に抑えることができる。
仮想サーバーとエントリーレベルのローカル・ロードバランサーを使って、購入価格数百万円クラスのロードバランサーと同等のヘルスチェックが実現できる。
このパターンでは、インターネット側からチェックするため、利用者のアクセス経路に近い形で状態を把握できる。
ヘルスチェックを実行する仮想サーバーは、通信料を含めても数千円以内に抑えることができ、経済的である。
 
懸念事項・注意点

ヘルスチェックのプログラムの実行負荷が大きい場合、サーバーのリソースを大量に消費して、本番サービスへ影響を与えるなどの懸念がある。 この様な場合、チェックの間隔を長くするか、ヘルスチェック・プログラムの見直しなどが必要である。
なんらかの障害が発生した場合、チェック間隔ごとに異常が通知され、他の重要な通知が埋もれてしまう可能性がある。 このため、ヘルスチェック用のサーバーのシェルでは、正常から異常へ変わった場合だけ通知するといった工夫が必要である。
利用料金が高くなってしまうが、次の図の様にNetScalerを利用して、ウェブ・サーバーの応答文字列を監視しておき、期待値と異なれば、SNMPのトラップを通知できる。 NetScalerの豊富な機能、高い性能、高可用性も利用できるので、費用対効果を鑑みて選択することをお勧めする。

参考資料

3.3 ロードバランサーを導入するには？
3.3.1 ローカル・ロードバランサーを使うには？
3.3.2 専用ロードバランサー(Citrix NetScaler)を使うには？
6.8 NetScalerを2重化するには？
GitHubでリモートとローカルのコミット時間がずれるとき

#はじめに
開発環境については以下の通りです。
OS:CentOS
仮装環境:vagrant

#事象
今回、一人でアプリケーションを作成している最中に
ローカル環境からGitHub上にあげたコミットメッセージの日付が2日前の日付で更新されるという現象が起きました。
解決するまでの流れを備忘録として残しておきます。

#解決までの流れ
まず、GitHub上で何か悪さしているのではないかと思い、「git 日時ずれる」などで検索かけてみましたが、日付が9時間ずれている場合の対処などは見つけることができましたが、2日もずれるという記事が全然見つかりませんでした。

git上での日時がずれる事象の記事を読んでいる時に、ntpというワードがでてきたので、これはgitではなく仮装環境のvagrantの設定日時がおかしいという事に気がつきました。

仮装環境に入りターミナルで以下確認すると、確かに2日前の日付となっており、
ここを変えてあげれば改善することが分かりました。(正常日時は2020/4/7　17:30頃)

```terminal
$ date
Sun Apr  5 07:22:16 UTC 2020
```
#対処法
vagrant関連で検索を行うと、すぐに対処法に辿りつくことができました。
結論からいうと今回の事象は、システム時刻がUTCになってしまっていることが原因でした。

UTCになっているかいないかは、以下で確認ができます。

```terminal
$ date
Sun Apr  5 07:22:16 UTC(←ここで確認できます。) 2020
```

　
今回行なったことは、仮装環境上で以下2つのコマンドを実行しました。

```terminal
$ sudo rm /etc/localtime
$ sudo ln -s /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
```

①「etc」配下にある「localtime」ファイルを削除
②「/usr/share/zoneinfo/Asia/Tokyo」のシンボリックリンクを「etc」配下に「localtime」として作成する。

　

vagrantを再起動し、確認する。

```terminal
$ date
Tue Apr  7 18:36:26 JST 2020
```
UTCからJSTに変更されたことと、日時も問題なく戻りました。

#軽く補足。UTCとJSTについて
UTCは”Universal Time”の略で、世界共通の標準時間と定めているもの。
JSTは”Japan Standard Time”の略で、日本の標準時間と定めているもの。
上記の通り、それぞれ大きく違いがあります。