OmniAICreator/Qiita-1.07M huggingface dataset:
AWS    -クラウドサービスについて-

### AWSとは
AWSは、Amazon Web Serviceの略称で、クラウドサービスの一種である。

######クラウドサービスとは
クラウドサービスとはコンピューター利用形態の一つで、ネットワークに接続されたサーバーが提供するサービスをネットワークを介して、利用者が、手元の端末を使ってウケることのできるサービスである。

#####オンプレミス
クラウドとは逆で、サーバーやネットワーク機器などをデータセンターに持ち込み、自身で構築する運用のこと。
オンプレサーバーと表現する。

#####相対するオンプレのデメリットとクラウドのメリット
| オンプレ       |クラウド |
|:-----------------|:------------------|
|サーバー設置に時間を要す|サービスの管理画面から即時に設置できる|
|ネットワーク敷設に時間を要す|サービスの管理画面から即時に設置できる|
|保守が必要|保守は必要ない|
|監視等の運用作業が必要|運用作業は必要ない|
|障害対策にコストがかかる|コストを抑えられる|
|-|サーバーのスペック変更が容易|


###負荷分散

クラウドサービスでは、ユーザーからのアクセスが増えてサーバーの負荷が高くなった時には以下の方法で対策できる。

######<font color="Red">スケールアップ</font>
サーバの性能を上げる方法。
逆に性能を下げることを*スケールダウン*という。

######<font color="Red">スケールアウト</font>
サーバの台数を増やす方法。
逆に性能を下げることを*スケールイン*という。
クラウドサービスによっては、サーバーの負荷を計測し、負荷が高まった時に、自動的に、スケールアウト、スケールインできる機構を持つものがある。
AWSでは*<font color="Red">Auto Scaling</font>*という機能を有効にすることで、自動制御が可能となる。

###マネージドサービスとアンマネージドサービス

クラウドサービスは、サーバーを貸し出すだけのサービスというわけでなく、DBサーバーやメールサーバーなど、特定の目的の設定が完了した状態のサービスも提供している。
素のままのサーバーを貸し出すサービスを*<font color="Red">マネージドサービス</font>*、あらかじめ設定された状態で貸し出すサービスを*<font color="Red">アンマネージドサービス</font>*という。

#####マネージドサービスを使用するメリット
マネージドサービスを使うメリットは、アプリケーションのインストールや、設定が不要である点や、ストレージの二重化やバックアップ、バージョンのアップデートやセキリュティにおける対策までを自身で考慮する必要がない点が挙げられる。

#####責任分界点
マネージドサービスにおいて、どこまでを自分が担当するのか、どこまでをクラウドサービスで担当してくれるのか。
この分岐点を責任分界点という。
以下が[AWS公式](https://aws.amazon.com/jp/)が公表している責任分界点
![Shared_Responsibility_Model_V2_JP.a4acd9721218c9d7d4ab5083c349e706e8ad300d.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271417/2b46af86-ed26-b2c1-56be-ebcc4f2a5c3f.jpeg)
参照：[https://aws.amazon.com/jp/](https://aws.amazon.com/jp/)


###IaaS・PaaS・SaaS
クラウドにおいて、どこまでの機能が提供されるのかを分ける指標として、<font color="Red">IaaS</font>、<font color="Red">PaaS</font>、<font color="Red">SaaS</font>がよく使われる。

#####SaaS(Software as a Service)
ソフトウェアの機能がサービスとして提供されるものを指す。
DBサーバー、メールサーバー等がこれに該当する。
保守。運用はクラウドサービスに任せられる。
保守・運用はクラウドサービス側に任せられる。


#####PaaS(Platform as a Service)
アプリケーション実行のプラットフォームを提供するもの。
作成したアプリケーションの実行環境を提供するサービス。
利用者は、作成したアプリケーションの保守・運用のみを考慮すれば良い。
AWSの提供している*<font color="Red">Lambda</font>*などのプログラム実行環境がこれに相当する。


#####PaaS(Platform as a Service)
アプリケーション実行のプラットフォームを提供するもの。
作成したアプリケーションの実行環境を提供するサービス。
利用者は、作成したアプリケーションの保守・運用のみを考慮すれば良い。
AWSの提供している*<font color="Red">Lambda</font>*などのプログラム実行環境がこれに相当する。


#####IaaS(Infrastructure as a Service)
ネットワークや仮想サーバーなどのインフラ部分を提供するもの。
アンマネージドサービスがこれに相当する。
利用者は、全体の保守。運用を考慮する必要がある。
![38_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271417/35e53376-8238-b878-da6c-d92d0657e6f8.gif)
参照：[https://www.ap-siken.com/](https://www.ap-siken.com/)
Rustの文法を学ぶ

https://doc.rust-jp.rs/book/second-edition/ を読みながらRustを触っているので、基本的な文法をまとめていきます。所有権, 参照, ライフタイムなどは割愛します。

ソースコードはRust 1.38.0で動作確認しています。
## 変数

```rs
// immutable
let num1 = 1;

// mutable
let mut num2 = 2;
num2 = 4;

//shadowing
let num3 = 3;
let num3 = "3";
```
- letで変数定義
- デフォルトでは不変。mutを使うと可変になる
- 既存の変数と同名の変数を定義することで既存の変数にアクセスできなくする(シャドーイング)
 
## 定数

```rs
const NUM: i32 = 1;
```
- 常に型注釈が必要
- どのスコープでも定義可能
- 定数名はscreaming snake case

## データ型
### 整数型 

```rs
let num: i32 = 1;
```
i32, u32, i64など

### 浮動小数点型
```rs
let num: f32 = 1.2;
```
f32, f64

### 論理値型
```rs
let b: bool = true;
```
bool

### 文字型
```rs
let c: char = 'a';
```
char

### タプル型

```rs
let (x, y, z) = (1, 2, 3);

let x = (1, 2);
println!("{}{}", x.0, x.1);
// 12
```
- ()で囲んだ値
- 複数の値, 複数の型を持つことができる
- パターンマッチングで要素を分解できる
- `x.0`のようにインデックスでアクセスできる

### 配列型
```rs
let array = [1, 2, 3];
```
- 固定長
- スタックに格納される

## 条件式
```rs
let a = 0;
if a == 0 {
  println!("zero");
}

let a = 1
let num = if a >= 0 {
  "positive number"
} else {
  "negative number"
};
```
`if 条件式 { 本体1 } else { 本体2 }`

## ループ
```rs
// loopを使ったループ
let i = 0;
loop {
  if i > 10 {
    break;
  }
  i += 1;
}

// whileを使ったループ
let i = 0;
while i <= 10 {
  i += 1;
}

// forを使ったループ
for i in 1..10 {

}
```

## 構造体
```rs
struct User{
  first_name: &'static str,
  last_name: &'static str,
  age: u32,
}

fn main(){

  let yamada_taro = User {
    first_name: "Taro",
    last_name: "Yamada",
    age: 20,
  };

  //構造体更新記法
  let first_name = "Jiro";
  let last_name = "Yamada";
  let age = 20;
  let yamada_jiro = User {
    first_name,
    last_name,
    age,
  };
}
```
- `struct`で構造体を定義
- 構造体のメンバと同じ変数を使うことで構造体の値のセットを構造体更新記法を使って省略して書くことができる

## タプル構造体
```rs
struct Point(i32, i32);

fn main(){
  let point = Point(1, 2);
}
```
## メソッド
```rs
struct User{
  first_name: &'static str,
  last_name: &'static str,
  age: u32,
}

impl User {
    fn new(first_name: &'static str, last_name: &'static str, age: u32) -> User {
        User {
            first_name,
            last_name,
            age,
        }
    }

    fn get_full_name(&self) -> String {
        self.first_name.to_string() + self.last_name
    }
}

fn main(){
  let user = User::new("Taro","Yamada",1);
  let full_name = user.get_full_name();
}
```
- `impl`を使ってメソッドを実装
- selfで構造体にアクセス
- 引数なしの関数は関連関数になる

## enum
```rs
enum Language {
    Java(bool),
    Kotlin(i32, i32),
    Rust(i32),
}

fn main(){
    let java = Language::Java(true);
    let kotlin = Language::Kotlin(1, 2);
    let rust = Language::Rust(1);
}
```
- `enum`で列挙子を表現する

## Option

```rs
enum Option<T> {
  Some(T),
  None
}

fn main(){
  let optional_num: Option<u32> = Some(10);
}
```
- 値があるかどうかを表現する
- 初期化処理に含まれているため、接頭辞なしで`Some(T)`のように使うことができる

## Result
 
```rs

enum Result<T, E>{
  Ok(T),
  Err(E),
}
```
- エラーが発生したかどうかを表現する
- エラーが発生しなければOk(T), エラーが発生した場合Err(E)を使う

## match

```rs
let age = 10;

let is_ten = match age {
  10 => true,
  _ => false,
};
```
- `match`でパターンマッチをおこなうことができる
- `_`を使うことでデフォルトのケースを表現できる
【レスポンシブサイト向け】＜br＞タグを使った小技

あるあるネタですが、感動したのでメモがでてら記事に。

#＜br＞タグとは　おさらい
＜br＞タグは文中の改行に使用するタグです。
＜p＞タグで区切って改行する場合もありますが、
＜p＞タグ自体にpadding-bottoのcssがあてがわれてるため、
「なんかこの改行ひろすぎじゃね？」と思うときとかに使われてますね。

もともとは
＜p＞タグは段落
＜br＞タグは改行
らしいっすよ。

へぇ～

#＜br＞タグ小技
＜br＞タグもclassが使えるらしく、これを下記のようなclass付<br>タグにします。


``` test.html
<br class="ps-br">

<br class="sp-br">
```

各画面幅で、この＜br＞が出たり消えたりするように下記のようなcssを書きます。

``` test.css
/* 画面幅が1024px以上の時は */
@media screen and (min-width: 1024px) {
  .ps-br{
    display: block; /* PCを改行して */
  }

  .sp-br{
    display: none; /* SPの改行を隠す */
  }
}

/* 画面幅が560px以下の時は */
@media screen and (max-width: 560px) {
  .ps-br{
    display: none; /* PCの改行を隠して */
  }

  .sp-br{
    display: block; /* SPを改行する */
  }
}
```
こうすることで、画面幅による改行の有無を指定することができます。
今まで空の＜span＞に同様のcssつけてたのですが、＜br＞にclassつけたほうがすっきりして良いですよね。
＜br＞ってこれ単体で使うイメージが強くてclassつけるなんて考えたことなかったんだけど、
これ見つけた人ビューティフォーだなって感動したんです。

#こんな時に便利です。
文章内の改行は基本的にはそこまでナーバスにならず、PC・SP兼用の場合がおおいです。（こういう場合は普通に＜br＞を使う）
しかし、見出しの中の文言やタイトルの文言は、大きな太字などになっていて意図しない箇所で折り返してしまう場合があり、
デカくて太いぶん、見栄えの悪さが目立ってしまうことがあります。
こういうときにちょっとした気遣いで改行を入れるとクオリティアップします。

<img width="778" alt="6fcb1e97cb9fefa43c74425f9cf2c1e6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480700/427af110-1ef9-f96d-205d-784e50b18160.png">




変なところで改行されると困る文言とかあるじゃないですか。

**ハーゲ
ン〇ッツ**

とかね。

ヤッターマン
...いや、なんでもないです


- 細かいところを作り込みができる
- 改行位置を気にしすぎるクライアント対策

という点がミソなので、必須なテクニックではないです。
こういうテクニックがあるのか。とふんわり覚えておいて必要になった時にピカンとくれば幸いです。


#レスポンシブサイトってなんだっけ　おさらい
レスポンシブサイトとは、PC・タブレット・SPがすべて同じURLで見れて、
その環境（画面幅）ごとに見栄えが変わるサイトのこと。
最近は大体のサイトがコレでできてるんじゃないでしょうか。

メリットはPCサイトとSPサイトで同じ文章で書かなくていいことです。
単純な時間短縮ですね。同じこと2回しなくていい。

PC・SPでURL分かれているサイトはユーザーエージェントで切り替えているので、
システム上や無負えないところはこれ採用してるらしいですが、最近はあまり見かけませんね。
ユーザーエージェントの説明は割愛。

##PCとSPでどうやって切り替えているの？
**CSSメディアクエリ**というものを使っています。
「画面幅が〇〇px以下の場合は、このcssが適用される。」
というような条件分岐がなされていると思っていただければわかりやすいかと。

この画面幅の分岐する値を**ブレイクポイント**というらしいです。

画面幅は端末によって異なるので、すべての機種に対応することは不可能です。
なので、調べる際はだいたい、

**ブレイクポイント css 2019 定番** :writing_hand:

こんな感じの検索ワードで、新しい情報を参考にして設定するのが良いと思います。

「この３～４つのブレイクポイントで区切れば、ほとんどの端末でキレイに見えるんじゃね？」

というような記事がでてくると思うので参考に。

###CSSで書くとこんな感じ

下記のような塊を対応するブレイク
ポイントごとに作ります。

``` test.css
@media screen and (max-width: 560px) {

/* この中に書いたcssは画面幅560px以下の場合のみ適用される */

  p{
    padding-bottom: 10px;
  }

}
```

##参考記事
レスポンシブデザインのブレイクポイントの正解はこれだった[2019最新版]
https://hashimotosan.hatenablog.jp/entry/2019/05/28/164834
C# SimpleTCP 簡単なソケット通信プログラミング

#0. 本稿について
@BrandonPotter 氏の__SimpleTCP__[(github)](https://github.com/BrandonPotter/SimpleTCP)を用いたソケットサーバー、ソケットクライアントアプリケーションを作成する。

#1. 環境 ~Environment~
+ Microsoft Visual Studio 2019 Community
+ .Net Framework 4.7.2
+ SimpleTCP 1.0.24

#2. 導入 ~Installing SimpleTCP~

NuGetパッケージの管理から__「SimpleTCP」__をインストールする。
![SimpleTCP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387241/3962329e-bae5-ae84-aec4-c645beeca7f8.png)

#3. ソケットサーバを作成

下記のソケットサーバをフォームアプリケーションで作成する

+ IPアドレス:__すべてのIPアドレス__からの通信を受信する
+ 通信ポート:__55555__
+ 終端文字：__0x00__
+ 受信した電文メッセージに__「_Reply」__を追加し、送信先に返却する
+ 受信した電文メッセージをテキストボックスに表示する

```C#:SimpleTCPServerForm
using System.Windows.Forms;
using SimpleTCP;

namespace SimleTCPServer
{
    public partial class Form1 : Form
    {
        SimpleTcpServer server;
        const byte NULL_TERMINATED = 0x00;
        const int PORT = 55555;

        public Form1()
        {
            InitializeComponent();
            server= new SimpleTcpServer().Start(PORT);
            server.Delimiter = NULL_TERMINATED;
            server.DelimiterDataReceived += (sender, msg) => {
                 msg.ReplyLine(msg.MessageString + "_Reply");
                 textBox1.Text += "Receive::" + msg.MessageString;
            };
        }
    }
}
```

#4. ソケットクライアントを作成

下記のソケットクライアントをフォームアプリケーションで作成する
1. 特定のIPアドレス,ポートでListen接続待機しているソケットサーバに接続する。
2. 接続したソケットサーバにメッセージに終端文字__0x00__を付与した文字列データを送信する。
3. 送信後、返答を__3__秒間待機する。
4. 返答メッセージをテキストボックスに表示する。

```C#:SimpleTCPClientForm 
using System;
using System.Windows.Forms;
using SimpleTCP;

namespace SimpleTCPClient
{
    public partial class SimpleTCPClientForm : Form
    {
        public SimpleTCPClientForm()
        {
            InitializeComponent();
        }

        private void button_SendMsg_Click(object sender, EventArgs e)
        {
            var client = new SimpleTcpClient().Connect(textBox_IP.Text, int.Parse(textBox_Port.Text));
            textBox_RecieveMsg.Text += "Send::" + textBox_SendMsg.Text + Environment.NewLine;
            //終端文字を追加する。
            var replyMsg = client.WriteLineAndGetReply(textBox_SendMsg.Text + '\0', TimeSpan.FromSeconds(3));
            textBox_RecieveMsg.Text += "Reply::" + replyMsg.MessageString;
        }
    }
}
```

## 5.検証

ソケットクライアントからソケットサーバへ電文メッセージ("test")を送信し、応答メッセージ("test_Reply")を受信していることが分かる

![SimpleTCP_Test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387241/a3496d2d-388c-63a3-3c08-c5dcc959ee11.gif)

## 99. 参考

[SimpleTCP](https://github.com/BrandonPotter/SimpleTCP)
【追記あり】BlazorクライアントアプリがiPadOS13で動かない問題（解決）

**【追記】2019/12/26日現在(.Net Core3.1 x iOS13.3)では、何もしなくても動作するようになっています。**

iPadをiPadOS(13)にアップデートしたところ、Blazorクライアントアプリ(WebAssembly)が動作しなくなってしまいました。Blazorで作成されたサイトは初めのloadingで止まってしまいます。

いくつかのissuesが報告されています。**現在は、クローズされています。**

[[wasm] Safari Maximum call stack size exceeded #15981](https://github.com/mono/mono/issues/15981)
[[blazor-wasm] opening a blazor application on ios does not work #15360](https://github.com/aspnet/AspNetCore/issues/15360)
[[interp][wasm] Fix iOS13 "Maximum call stack size exceeded." #17397](https://github.com/mono/mono/pull/17397)

**2019/12/26追記　2019/12/26日現在(.Net Core3.1 x iOS13.3)では、下記の対応を行うとエラーになり、動作しなくなります。**

~~一応の対応策は、`blazor.webassembly.js`に手を入れることのようです。~~
~~[このissues](https://github.com/mono/mono/issues/15981)にあるファイル~~([blazor.webassembly.ios13.fix.zip]~~(https://github.com/mono/mono/files/3620747/blazor.webassembly.ios13.fix.zip)) から、`setTimeout`を~~~~検索し、タイムアウト値を調整します。ファイルは`1000`となっていますが、`2000`に設定することで動作しました~~~~(iPadOS 13.2でも確認)。ファイルを書き換えたら、プロジェクトフォルダの~~~~`\bin\Debug\netstandard2.0\dist\_framework\blazor.webassembly.js`を置き換えます。~~

~~ただし、この方法はloadingに遅延が発生するようです。正式な対応を待ちたいと思います。~~

```javascript:blazor.webassembly.js
（中略)
/* Theses hack are for buggy iOS/Safari 13 */
if (window.Blazor.isStarted)
{
	try {
		l(r.next(e));
	} catch (e) {
		a(e)
	}
}
else {
	setTimeout(function (l, r, e) {
		try {
			l(r.next(e));
		} catch (e) {
			a(e)
		}
	}, 2000, l, r ,e);
}
```
年末まで毎日webサイトを作り続ける大学生 〜11日目 MDNのバカ話ジェネレーターを作る〜

##はじめに
初めまして。
年末まで毎日webサイトを作っている者です。
今日もMDNを見て勉強していたんですが、[このページ](https://developer.mozilla.org/ja/docs/Learn/JavaScript/First_steps/Silly_story_generator)にあるバカ話ジェネレーターを作りました。
この機能をつけろとか動作はこうしろとか、いくつか条件があるんですが、ラジオボタンを使って温度の単位を米国英国で切り替えるもの以外はやりました。
扱う技術レベルは低いですが、同じように悩んでる初心者の方を勇気付けられれば幸いです。
今日は11日目。(2019/10/29)
よろしくお願いします。


##サイトURL

- https://sin2cos21.github.io/day11.html

##やったこと
gif↓
![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/5d965cee-717e-4cc1-52fe-ad9c4a4c446e.gif)

というわけで今日はMDNの課題をやりました。
ポイントはバカ話の一部分を配列に入れて、その中からrandomメソッドでどれかを取り出し、元になる文章にreplaceメソッドで張り替えるところです。

```javascript
function randomValueFromArray(array) {
            return array[Math.floor(Math.random() * array.length)];
        }

let xItem = randomValueFromArray(insertX);
            let yItem = randomValueFromArray(insertY);
            let zItem = randomValueFromArray(insertZ);
            newStory = newStory.replace(/:insertx:/g, xItem);
            newStory = newStory.replace(/:inserty:/g, yItem);
            newStory = newStory.replace(/:insertz:/g, zItem);
```
replaceメソッドはデフォルトだと1回張り替えをしたら終了してしまうのですが、張り替えたい文字が2箇所以上でてくる場合は第一引数のところをこうすると →　(**/ 文字 /g,...)**　該当する文字全て変更してくれます。

##感想
とりあえず今日でMDNのJavaScript初級編は終わったので、明日から**中級編**に移りたいと思います。ここもしっかりマスターして早く上級編を終わらせるぞ！そして年末までにオセロを作ってみたい。いや、絶対に作りますので楽しみにしていてください！

今日も最後までお読みくださりありがとうございます。
明日も投稿しますのでよろしくお願いします。

##参考
1. バカ話ジェネレーター - Web 開発を学ぶ | MDN (https://developer.mozilla.org/ja/docs/Learn/JavaScript/First_steps/Silly_story_generator)

MDNさんありがとうございます！
Donkey Simulatorのインストール手順(ubuntu 18.04編)

Donkey Simulator(Donkey Gym)は、Self Driving Sandbox(sdsandbox)をベースに作られているため、Unityなどのインストールが必要です。下記のサイトを参考にしながら、Ubuntu18.04を対象に書いてあります。



[User Guide > Donkey Simulator](https://docs.donkeycar.com/guide/simulator/)



## Unityインストール

下記サイトの「プロジェクトを作成する」の手前までの手順にしたがって、Unity Hub及びUnityのインストールを行う。

[UbuntuでゲームエンジンのUnityをインストールする手順](https://www.virment.com/how-to-setup-unity-ubuntu/)

## Donkeycar on Linuxインストール

まだ、Donkeycarのインストールをやっていない場合には、ここで行っておく。condaの仮想環境donkey配下で構築。

[Install Donkeycar on Linux](https://docs.donkeycar.com/guide/host_pc/setup_ubuntu/)



## シミュレーターのダウンロード＆解凍 

Donkey GymのRelease版(v18.9)をダウンロードし、解凍する。
~projects/DonkeySimLinuxが作成される。


```bash
sudo apt install curl
cd ~/projects
curl -OL https://github.com/tawnkramer/gym-donkeycar/releases/download/v18.9/DonkeySimLinux.zip
unzip DonkeySimLinux
```



## Donkey Gymのセットアップ



```bash
cd ~/projects
git clone https://github.com/tawnkramer/gym-donkeycar
conda activate donkey
pip install -e gym-donkeycar
```



## シミュレーター用のDonkeyフォルダを作成

```bash
donkey createcar --path ~/mysim
cd ~/mysim
```



## myconfig.pyの編集

donkey gym simulator wrapperを有効化するために、以下の箇所をコメントアウトし、 `DONKEY_SIM_PATH`は自分の環境に合わせて変更する。 

```python
DONKEY_GYM = True
DONKEY_SIM_PATH = "/home/xxx/projects/DonkeySimLinux/donkey_sim.x86_64"
DONKEY_GYM_ENV_NAME = "donkey-generated-track-v0"
```



## シミュレーターの起動

Ubuntuでは、実機で使っているジョイスティックを使うことができます。jstestなどで/dev/input/js0を確認してください。



```bash
python manage.py drive --js
```



以下の画面が出るので、`Screen resolution`や`Graphics Quality`を自分の環境に合わせて実行します。
![Screenshot from 2019-10-20 08-25-24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99008/55d73175-3d26-1f11-8d04-6122c003ddf3.png)

## 結び

実機があれば、シュミレーターは必要ないかなと思っていましたが、学習モデルの検証や初心者向けのタッチ＆トライなど幅広く使えそうな感じがしてきました。

上記の手順により動くところまで持っていけると思います。
IBM Cloudで、Jira Cloud REST APIを叩く

# Jira Cloud REST APIとIBM Cloud
Jira SoftwareやConfluence、Jira Service Deskのクラウド版に無料プランが登場し、[Jira Software クラウド版 Free プランの申し込み手順](https://qiita.com/kolinz/items/2fef0a3c3dad449f2c0f)について記事にしました。
Jira Cloud REST APIを操れるようになると、AIやIoT、ブロックチェーンなどと組み合わせることができます。
そこで、クレジットカード不要なIBM Cloud ライト・アカウント上で無料で使えるNode-REDを用いて、Jira Cloud REST APIを用いて、チケット(Jira用語では課題と言う)を起票する手順について説明します。

# なぜNode-RED?
市場には、iPaaS(integration Platform-as-a-Service)製品やサービスが幾つもありますが、クラウド、オンプレミス、組み込み機器などどこでも動き、業務アプリケーションの他にAIやIoT、ブロックチェーンなどまとめてサポートしているものは少なく、産業用IoTというカテゴリで言えば、主要企業のサービスでは、Node-REDが採用されています。(参考資料:http://www.mstc.or.jp/iaf/event/2019f/07yokoi.pdf)

AI分野では、IBM Watsonや Microsoft Cognitive Services、Google Assistant、TensorflowベースのAIサービス等と接続できるため、プロジェクト管理やタスク管理、サービスデスクなどの業務アプリケーションを、AIやIoTと連携しようとすると、Node-REDが有力な候補になります。

# 準備
[Jira Software クラウド版 Free プランの申し込み手順](https://qiita.com/kolinz/items/2fef0a3c3dad449f2c0f)を参考に、クラウド版 Jira Software環境を用意し、APIトークンを発行しておきます。
関連資料 https://ja.confluence.atlassian.com/cloud/api-tokens-938839638.html

# Node-RED上で、Jira Software クラウド版にチケット(課題)を起票
Node-RED上で、シンプルなフローを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/b0b34df5-c1cc-ef09-d6f4-ab8a4788c74e.png)

１つ１つ設定を見ていきます。
## 異常値を検知しました
injectノードを使用しています。injectノードの左端の四角のボタンを押すと処理が開始されます。
設定は、下図のように、ペイロードに文字列として「異常値を検知しました。」という警告文をセットしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/e7454272-b636-c594-d720-958c592ee3cb.png)

## issue data
functionノードを使用しています。手前で発信された文字列をsummaryに挿入するとともに、Jiraに起票するためのデータを生成しています。[Jira Software クラウド版 Free プランの申し込み手順](https://qiita.com/kolinz/items/2fef0a3c3dad449f2c0f)で説明しているように、Jiraを使うには、プロジェクト作成が必須です。Projectのキーを、ここでは「IOT」としていますが、皆様が作成した各自のプロジェクトキーに読み替えてください。

```
"fields": {
            "project":{"key":"IOT"},
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/9cb6e33d-9335-90a8-ed46-31838e14c09a.png)

## http request
http requestノードを使用しています。
「メソッド」に「POST」、「URL」にJira Software クラウド版を登録した際のサイト名(Site name)を用い、/rest/api/2/issue を追加しています。
また、「認証の使用」にチェックを入れ、次のように値をセットしています。
- 種別 : Basic認証
- ユーザー名 : Jira Software クラウド版へのログインメールアドレス
- パスワード : ユーザー名のメールアドレスで取得した**APIトークン**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/6ce00be9-526e-29b2-0982-383948e056ec.png)

## msg
debug ノードを使用し、対象をオブジェクト全体としています。

## 動作確認
設定後、画面右上の「デプロイ」ボタンをクリックします。
「異常値を検知しました」と表示されている「inject」ノードの左端の四角のボタンを押すと処理が開始されます。
虫型のアイコンをクリックすると「デバッグ」タブにて、実行結果を確認できます。また、クラウド版のJira Softwareのお使いの環境に、Node-REDで、Jira Cloud REST APIを用いて作成されたチケット(=課題)が起票されているはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/7bf9f6d2-bdbf-6c70-27c0-24eeafa6658b.png)

# 活用例
これらの仕組みは、クラウド版ではなくサーバー版のJira Softwareになりますが、昨年開発しました『[在宅ケアを想定した自動発報および可視化システムのPoC](http://gcmwso.web.fc2.com/pdf/forum06/forum06_1500.pdf)』では、センサーの異常値を検知し、Jiraに確認を指示するチケット(課題)を自動起票する仕組みに使っています。
Eclipse MicroProfile Configについて

# はじめに
前回の[Eclipse MicroProfileとは](https://qiita.com/omix222/items/50804e30e43085ceb912#eclipse-microprofile-config)で概要を紹介したEclipse MicroProfile Configについて説明したいと思います。

## 始め方
前々回の[Eclipse MicroProfileの始め方](https://qiita.com/omix222/items/923d788d6ce76e179d6a)で紹介した、
[MicroProfile Starter](https://start.microprofile.io/)を使っていきます。

<img width="1079" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113217/3bf02f2b-3961-2e3d-f274-df5da7ebea34.png">

こちらの設定でプロジェクトを作成、ダウンロードします。

ファイル構成は以下のようになっています。

<img width="433" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113217/22a56e52-bb34-8351-6a4c-8c68103bebd7.png">

ビルド、アプリ起動しlocalhost:8080へアクセスすると以下のようはTop画面が用意されています。

<img width="348" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113217/da59495c-c222-7cbf-a886-7d4cf08bcc08.png">

前々回と異なり、Configについてのサンプルリンクが用意されています。
リンク先はどちらも以下のような設定内容を画面表示させるようなシンプルなものとなってます。

<img width="570" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113217/3c426d3e-e840-9b04-6c28-1602059026a9.png">

## 設定の仕方

### 設定ファイルの利用
プロジェクト内の設定ファイルを見ることが基本系となります。
Key-Value形式で設定することができます。
```microprofile-config.properties
injected.value=Injected value
value=lookup value
```
### 起動時引数の利用
以下のような形で起動時引数で指定します。

```
java -Dinjected.value=CustomValue -jar target/configdemo.jar 
```
起動すると以下のように設定ファイルの内容が、起動時引数の設定に上書きされます。

<img width="426" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113217/0d0f4c78-d50f-3eee-b175-1c36a8ef08f5.png">

### 環境設定の利用
環境変数でも指定可能です。

```
export value=EnvCustomValue
java -jar target/configdemo.jar 
```
<img width="419" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113217/0f9aa343-f14d-6714-6916-1f012ac67774.png">

## 設定内容の取得方法

### インジェクションでの取得
```ConfigTestController.java
    // CDIの＠Injectを利用
    @Inject
    //キー名を取得することで、フィールドインジェクション可能
    @ConfigProperty(name = "injected.value")
    private String injectedValue;

    @Path("/injected")
    @GET
    public String getInjectedConfigValue() {
        return "Config value as Injected by CDI " + injectedValue;
    }

```

### LookUpのAPIでの取得
```ConfigTestController.java
    @Path("/lookup")
    @GET
    public String getLookupConfigValue() {
        // 以下のAPIで取得
        Config config = ConfigProvider.getConfig();
        String value = config.getValue("value", String.class);
        return "Config value from ConfigProvider " + value;
    }
```

# まとめ
かなりシンプルな設定方法と設定の取得方法であったことが分かったかと思います。
Springでも同じようなことができますが、JavaEE系のアプリケーションでも簡単に使えます。
クラウドやコンテナ利用で同じモジュール、バイナリ、コンテナイメージを使う際にはこの機能は使いたいですよね。

# 参考リンク
- 公式ドキュメント  
   [Configuration for MicroProfile](https://microprofile.io/project/eclipse/microprofile-config)
Masoniteでブログを作るチュートリアル②(認証とMigration)


## Masonite
​
Masonite自体の紹介は[こちらの記事](https://qiita.com/dumblepy/items/65b975302618cb6a8f64)が大変参考になります
​
この記事は公式チュートリアル の通りに進めていきます.
公式チュートリアル以上の情報はありません.
サクッとキャッチアップしたい人向けの日本語訳的な位置づけです.

## 前回までの実装

1. [Masoniteでブログを作るチュートリアル①(ブログ的Hello World)
](https://qiita.com/flowphantom/items/ec1ff5ee004c39b7776e)


## 今回の範囲
​
1. 認証の作成
2. DBのコネクション設定
3. migration
​
## 認証の作成
​
ユーザーの新規登録、パスワード再設定、ログイン、ログアウトなど一般的なユーザー管理のController、Model、Viewを作り込む必要があります。
​
Laravel などには　`php artisan make:auth`　コマンドがありますね。
​
もちろんMasoniteにもあります。だってインスパイアされてますもん。
​


> Tip!! さくっと始めたいですか？ インストールしたてのMasoniteアプリケーションにて、craft authとcraft migrateを実行するだけです。それから、ブラウザで
http://localhost:8000/register へアクセスしてください。この２つのコマンドが、認証システム全体のスカフォールドを面倒みます。
​

[Laravelのドキュメント](https://readouble.com/laravel/5.7/ja/authentication.html)
​
本当にこれだけです。
​
しかし、そういえばmigrateするDBを設定していませんでした。
​
## DBのコネクション設定
​
ローカル環境に MySQL や Postgres　があるならばそちらにセットアップした方がいいでしょう。
​
しかし、無くても開発をすすめることはできます。SQLiteがあります。
​
それでは、`.env` をSQLite用に編集しましょう。
​
デフォルトではMySQLを使用する設定になってます

```yaml​
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=masonite
DB_USERNAME=root
DB_PASSWORD=root
```

これをSQLite用に書き換えます
​
DB名はblog.dbにしておきます
​

```yaml
DB_CONNECTION=sqlite
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=blog.db
DB_USERNAME=root
DB_PASSWORD=root
```
​
さて、これでmigrateする準備が整いました
​
## Migrating
​
migration実行はcraftコマンドから行います。

```terminal
$ craft migrate
```
​
このマイグレーション実行により、usersテーブルとmigrationsテーブルが作成されるはずです。
​
## 終わりに
​
さて、認証が実装できたかを確かめてみましょう

```terminal
$ craft serve
```
​で、開発サーバーを立ち上げて、http://localhost:8000/register にアクセスします。
​
すると、登録画面が表示されるので登録しましょう（なんでもいいです）

```
Username: demo
Email: demo@email.com
Password: password
```
​
さぁログアウトしたり、ログインしたり、パスワードを忘れてみたり、、
​
いろいろと試してみましょう。
​
次回は、Modelのリレーションをやっていきます。
Travis CIとGithubでPEP8に準拠したコーディングを行う簡単な方法

## .travis.yml
リモートリポジトリにpushする時にTravis CIでPEP8に準拠しているかチェックする.

```python
language: python
python:
  - 3.6
intall:
  - pip install pycodestyle
script:
  - find . -name \*.py -exec pycodestyle {} + 
```

## リモートにpushする時
リモートへのpushはdevelopブランチなどmaster以外にする.

```
git add .
git commit -m 'hoge'
git push origin develop
```
この時Travisが走り, PEP8に従っていないコードがあったらエラーメッセージが出る.
エラーが出ても構わずpushされるけど, そのままgithub上でmasterにマージしようとすると警告が出るので防止策にはなる。
ABC 081 B - Shift Only　解説

# はじめに
https://atcoder.jp/contests/abc081/tasks/abc081_b
の提出済みの優秀な方(usayomoさん)のコードを解説。


# 問題
【問題概要】
黒板に $N$ 個の正の整数 $A_1, \dots, A_N$ が書かれています。
すぬけ君は，黒板に書かれている整数がすべて偶数であるとき，次の操作を行うことができます。

黒板に書かれている整数すべてを，2 で割ったものに置き換える。
すぬけ君は最大で何回操作を行うことができるかを求めてください。

【制約】
+ $1 \le N \le 200$
+ $1 \le A_i \le 10^9$

【数値例】
　$N = 3$
　$A = (16, 12, 24)$
　答え: $2$

# 完成コード
```
n = int(input())
a = list(map(int, input().split()))
 
ans = float("inf")
 
for i in a:
    ans = min(ans, len(bin(i)) - bin(i).rfind("1") - 1) # (1)…2で割った回数が最小のものを探索
print(ans)
```
# メモ
ポイントは(1)なのでここだけ解説。
①len(bin(i))
 len()は文字列の長さを出力。
 bin()は引数を２進数に変換して出力。
⇒つまりlen(bin(i))は入力iの２進数の桁数を算出する。
　例えば、len(bin(8))⇒0b1000、len(bin(5))⇒0b101となる。※2進数の場合、先頭に0bが入るようだ。

②bin(i).rfind("1")
rfindは1の文字を右から数えて何文字目かを出力。
⇒つまりbin(i).rfind("1")で入力iが最初に右から１がでるのは何桁目か？を算出する
　例えば、bin(i).rfind("1")⇒0b1000(=2)、bin(i).rfind("1")⇒0b101(=4)となる。
  ※rfindは右から数えるけど、出力する桁数は左から数えるのと０から数え始めるのでちょっと混乱しちゃうので注意

③len(bin(i)) - bin(i).rfind("1") - 1
①②を組み合わせて、何回２で割り続けられるかがわかる。
例えばi = 10の場合を考えると…
2で割り続けると、10⇒5⇒×で1回
このとき何がおきてるかっていうと2進数で見てみるとよくわかる。
10⇒1010
5 ⇒101
ってなっており、つまり何回２で割り続けることができるかは右の０の個数を数えればよいということがわかる。
なので…
③は①-②-1をしてやることで、この右の０の個数がいくつになるのかを導いているためにやっていることがわかる。

④ans = min(ans, len(bin(i)) - bin(i).rfind("1") - 1)
そもそもの出題は
**黒板に書かれている整数すべてを，2 で割ったものに置き換える。**
とあるが、これは言い換えると
**２で割り続けて１つでも奇数がでてきたら終了する**
ということを表している。

$N$ 個の正の整数 $A_1, \dots, A_N$ のなかで最初に２で割り続けられなくなる数を探すので
forで回して１つ１つ2で割り切れる回数を算出して最も少ない数を探している、というのが
この(1)でやっていることなのだなと。
G検定メモ⑮　ディープラーニング　画像認識分野　編

#7-1.画像認識分野
###1．アレックスネット（AlexNet)
2012年　ILSVRCにて優勝

ILSVRC　ご認識率の変化
2012　AlexNet　0.16
2013　ZF.net　　0.12
2014　GoogLeNetVGG　0.07
2015　ResNet　　0.036
2016　ensembled　network　0.30
2017　Squeeze and ExcitationNetwork　0.023

###2．R-CNN
イメージネット画像認識コンテストには
・位置課題（location task）
・検出課題（detection task）
二つの課題がある。
どこに何があるかを問う課題

この課題に対応するのが
######●R-CNN（Regional　CNN）
関心領域（Region of　Interest：ROI）の切り出しには
従来手法を用いる、切り出しの後に領域ごとに個別にCNNを呼び出す2段階モデルであるため時間がかかっていた。

・領域の切り出し　とは
画像上の矩形領域（長方形）の左上の座標と右下の座標で表現することにすれば、
4つの点を予測する回帰問題と見なすことができる
この矩形領域の事を「バンディングボックス（bounding box)」と呼ぶ

一般にCNNでは、畳み込み演算を多層にして繰り返す
このため、各層の個々のニューロンはカーネルの大きさ分だけしか下位層から入力を受け取らない。
このためCNNは入力画像中の位置情報も表現していると考えることができる
各入力画像の関心領域を切り出すための情報が含まれている
アレックスネットに限ったことではない

領域の切り出しと切り出した領域の物体認識を同時に行うことが可能となる
これを実現したモデルを「高速RCNN（fastRCNN）」と呼ぶ

######●fastRCNN
領域切り出しと物体認識を同時に行うモデル

######●fasterRCNN
上記をさらに改良したモデル

これらのモデルによりほぼ実時間で入力画像から関心領域の切り出しと認識ができるようになりました。
・ほぼ実時間：一秒あたり16フレーム程度の処理
このことで、動画認識へCNNを応用する道が開かれた

######●その後の発展系
######・YOLO
You Only Look Once（一度だけしか見ない）
######・SSD
Single Shot Detector（1ショット検出器）

これらはいずれも領域切り出しと認識を同時に行うCNN

###3．セマンティックセグメンテーションとインスタンスセグメンテーション
######●セマンティックセグメンテーション（semantic segmentation）
R-CNNのような矩形領域を切り出すのではなく、
より詳細な領域分割を得るモデル
物体認識においては領域分割を詳細に行うことが必要となります。
入力画像のどの位置に物体が存在するのかを画素単位で指定することができれば認識精度も向上すると予想されます。

######●完全畳み込みネットワーク
Fully Convolutional Network：FCN
セマンティックセグメンテーションを実現するネットワーク
全ての層がたたみ込みそうであるモデル

######通常のCNN
出力層のユニット数が識別すべきカテゴリー数
######FCN
入力画像の画素数だけ出力層が必要
→各画素がそれぞれどのカテゴリーに属するのかを出力する必要がある
出力層には、縦画素数×横画素数×カテゴリー数
の出力ニューロンが用意されます
識別すべきカテゴリー数が20だった場合、背景はどのカテゴリーにも属さないので、背景を1カテゴリとして加えた21カテゴリーの分類を行う

CNNでは畳み込み演算によって
畳み込みのカーネル幅（受容野）だけが近傍の入力刺激そ加えて計算することになる
→上位層では下位層に比べて受容野が大きくなり画像サイズは小さくなる
最終出力層に入力層と同じ解像度画素数を得るためには、畳み込みと
反対方向の解像度を細かくする工夫が必要となります。

######●解決策
アンサンプリング（unsampling）
下位のプーリング層の情報を用いて詳細な解像度を得ることができます。
下位層のプーリング情報を使ってアンサンプリングする事により、解像度を復元する

同様の仕組み
######・セグネット（segnet）
下位のプーリング層の情報を用いて領域分けを行う

######【まとめ】
バウンディングボックスは矩形領域を切り出して、切り出した領域内の物体識別を行う。
セマンティックセグメンテーションは、各画素がどのカテゴリーに属するかを求める手法→同じカテゴリーに属する物体が同一ラベルとして扱われる
インスタンスセグメンテーションでは、個々の物体ごとに認識させる事ができる

######MaskRCNN
バウンディングボックスとセマンティックセグメンテーションを組み合わせる事で
入力画像では遮蔽物によって隠されて不連続になった物体を同一の物として認識できる可能性がある
[Windows 10] v6プラス環境でIPv6優先設定にしてみた

はじめに
===
NTTのフレッツ光および光コラボの回線で、夜間などの混雑による通信速度の低下を防げる[v6プラス](https://www.jpne.co.jp/service/v6plus/) (IPv6 IPoE)。
IPv4通信が今まで通りできる他、IPv6での通信もできるようになるので、Windows 10でIPv6を優先する設定で使ってみました。

v6プラスを有効化する
===
v6プラス対応のブロードバンドルーターを準備し、プロバイダに連絡してv6プラスを有効化してもらいます。
個別の手続きやルーターの設定については省略。

Windows 10でIPv6優先設定にする
===
[上級ユーザー向けに Windows で IPv6 を構成するためのガイダンス](https://support.microsoft.com/ja-jp/help/929852/guidance-for-configuring-ipv6-in-windows-for-advanced-users)
「プレフィックス ポリシーで IPv4 よりも IPv6 を優先する」の設定を行います。
完了したら、ここで一旦Windowsを再起動します。

設定を見る
===
うまくいくとIPv6アドレスが降ってきます。以下はipconfigコマンドの結果。
IPv4アドレスについては、ルーターがプライベートアドレスを振っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204084/fa12974f-87fc-e23f-7da3-2f5b00b76de6.png)

IPv6で接続できているか確認
===
[あなたの IPv6 接続性をテストしましょう。 ](http://test-ipv6.com/)
10/10になっていればOK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204084/515cbe7a-e734-a3c4-3eaa-c75df511a995.png)

[The KAME project](http://www.kame.net/)
亀が踊っていればOK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204084/a2e22ac0-e260-5635-533e-d082e9b87e43.png)

トラブルシューティング
===
## 亀が踊らなくなった
Wi-FiでIPv4にしか対応していないアクセスポイントに接続してしまうと、IPv6対応のアクセスポイントに再接続してもIPv6が復活しない（IPv6アドレスが出てこない）現象に遭遇しました。
<del>Android 9.0だと大丈夫なのでOSの作りの問題ですかね…</del>

以下のどちらかを行えばIPv6通信が復活しました。

- Windowsを再起動する
- Wi-Fiの**ネットワークアダプター**を無効化→有効化（単にWi-Fiの無効化→有効化ではダメでした）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204084/d08bef5a-6380-1840-7e14-02a0c3f8ccb8.png)

DNS
===

ネットワークアダプターのIPv4設定でDNSサーバーを手動設定しているとき、IPv6でつながっていると自分で指定したDNSサーバーを見に行ってくれません。
例えば、LAN内に自分でDNSサーバーを立てている場合などが該当します。

この場合、IPv6の設定にもDNSサーバーのアドレスを指定すればOKです。DNSサーバーの固定アドレスがIPv4だけの場合は、IPv4射影アドレスで指定できます。以下の例はDNSサーバーのIPv4アドレスが 192.168.123.234 の場合です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204084/ce50e422-26cf-0d67-1c59-97402482c592.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204084/f97ed695-6730-86f5-90e3-144143a6baa0.png)

今後の課題
===

v6プラス環境で家のLANに入る方法。この辺りを参考にしつつ、おいおい試してみますかね。

- [IPv6プラス環境におけるIPv4ポート公開設定 - Qiita](https://qiita.com/nbhr/items/2850ccaa3456a8553bbf)
- [フレッツ網の快適なIPv6でVPNを構築する方法 - Qiita](https://qiita.com/notoken3331/items/b59ff4432635e067ff60)
【Java】乱数生成の方法（Random）

Javaで簡単に乱数を生成するプログラム例を紹介します。
##整数型（0～の数字）

```
int r = new java.util.Random().nextInt(※発生させる乱数の上限値);
```

ソースのはじめにimport java.util.*をしているなら以下のように書くことも可能です。

```
int r = new Random().nextInt(※発生させる乱数の上限値);
```

参考：[java.util.Random#nextInt(int) の仕様](https://docs.oracle.com/javase/jp/8/docs/api/java/util/Random.html#nextInt-int-)

##小数型（0～1の乱数を生成するパターン）
```
double r = Math.random();
```
今更ながらHTML5のコンテンツモデルとカテゴリについて整理する

##はじめに
「ブロックレベル要素」「インライン要素」の概念が無くなり、新たなコンテンツモデルが出来てから数年経ちました。
それまで私は「内包するタグと内包されるタグが今までより厳密になったんだよね」くらいで、理解を深めないまま何となくコーディングしてきました。しかしコードレビューする機会も増えてきて、いい加減な知識では責任を持てないと思い、今更ながら整理してみました。

##コンテンツモデルとは
コンテンツモデルとは、各要素（＝タグ）ごとに内包できるコンテンツを定義したルールのことです。要素を配置する際のルールだと思っていれば良いと思います。

##カテゴリとは
カテゴリとは、各要素を類似の特性を持つもの同士で分類したものを指します。
HTML4.01までは、ブロックレベル要素かインライン要素かそれ以外かというシンプルな分類でした。
HTML5では、要素の役割に応じて7つに分類されています。さらに要素によっては複数のカテゴリに属するものやどこにも属さないものも存在し、HTML4.01に比べて複雑になっています。

###カテゴリの種類
HTML5での主要なカテゴリは7つです。

カテゴリ名前|説明|タグ（一例）
---|---|---
メタデータコンテンツ|HTML文書全体に関する情報を示す要素。基本的にはhead要素内に配置。|base・link・meta・noscript・script・style・template・title
フローコンテンツ|body要素内で配置場所を限定されずに使用できる要素。全体の7割を占める。|a・abbr・address・area（map要素の子孫の場合）・article・aside・audio・h1・h2…
セクショニングコンテンツ|章・節・項のように文章のまとまりとなる要素。|article・aside・nav・section
ヘッディングコンテンツ|セクションの見出しとなる要素。|h1・h2・h3・h4・h5・h6
フレージングコンテンツ|文書のテキストや段落内のテキストの範囲を示す要素。|a・abbr・area（map要素の子孫の場合）・audio・b・bdi・bdo・br…
エンベディッドコンテンツ|画像や動画など外部データをWebページに取り込むための要素。|audio・canvas・embed・iframe・img・MathML math・object・picture・SVG svg・video
インタラクティブコンテンツ|ユーザーによる操作や入力が可能な要素。|a（href属性が存在する場合）・audio（controls属性が存在する場合）・button・details…

##要素の入れ子ルール
各要素ごとにコンテンツモデルがあります。ここでは代表的なものを載せておきます。

要素|コンテンツモデル（※記載カテゴリに属する要素を内包できる）
---|---
div|フローコンテンツ
span|フレージングコンテンツ
h1〜6|フレージングコンテンツ
p|フレージングコンテンツ
a|トランスペアレント

###トランスペアレントについて
フレージングコンテンツに属する要素のいくつかは、`a`の様に「トランスペアレント」に分類されます。
トランスペアレントに分類される要素の特徴は、「親要素のタグのコンテンツモデルと同じになる」ということです。

####例1：`a`が`h1`を入れ子にできる場合

```
<div>
  <a href="https://hoge.com/">
    <h1>タイトル</h1>
  </a>
</div>
```
> `a`の親要素が`div`なので、「フローコンテンツ」となる（`div`のコンテンツモデルを継承した）ので、`h1`を内包できる


####例2：`a`が`h1`を入れ子にできない場合

```
<p>
  <a href="https://hoge.com/">
    <h1>タイトル</h1>
  </a>
</p>
```
> `a`の親要素が`p`なので、「フレージングコンテンツ」となる（`p`のコンテンツモデルを継承した）ので、`h1`を内包できない

###便利サイト（コンテンツモデル早見表）
概要は分かっても慣れるまでは迷いますよね。
本当はW3Cのドキュメントを読んで調べた方がいいのかもですが、そうも言ってられない時があります。
そんな時は下記のサイトを活用してみてください。
どちらのサイトも指定した要素に対して「親になれる要素」と「子になれる要素」をそれぞれ教えてくれます。

- [HTML5 コンテンツモデル ガイド](https://webgoto.net/html5/)
- [HTML5 子要素・親要素対応](https://yoshikawaweb.com/element/)


##まとめ
基本的に文章構造を理解して要素を配置していけば大きな間違いにはならないという認識は変わらずでしたが、今回調べた時に`dl`の中に`div`を内包できる（※条件付き）という仕様にいつの間にか変わっており、定期的にドキュメントを確認する必要性や情報に敏感になる大切さを実感しました。

以上です。
最後までお読みいただき、ありがとうございました。

----

##お世話になったサイト
- [HTML5 コンテンツモデル ガイド](https://webgoto.net/html5/)
- [HTML5 子要素・親要素対応](https://yoshikawaweb.com/element/)
- [【一覧表あり】HTML5でのタグの入れ子のルールを徹底まとめ](https://webliker.info/46840/)
- [HTML Living Standard](https://momdo.github.io/html/)
- [HTML 要素リファレンス | MDN](https://developer.mozilla.org/ja/docs/Web/HTML/Element)
LaravelのAuth認証について１から学ぶ　＃１

#「php artisan make:Authとphp artisan migrateを打ち込むと誰でも簡単に認証機能を使える。Readoubleにもそう書いてある。」
Laravelは標準で認証機能を用意しており、上記のコマンドをターミナルやコマンドプロンプトに打ち込むと簡単に認証機能を使えます。なら何も考えずにmake:Authして気軽に認証機能を使えばいいの？いやいやセキュリティ機能はLaravelの重要な特長の一つ（らしい）で、今後のためにしっかり勉強しておこうと思ったので、コードとReadouble（Laravelの公式リファレンスの日本語訳）を追いつつ勉強記録を記事として残します。

#php artisan make:Auth

認証用のメソッドはApp\Http\Controller\Auth 以下にもともと用意されているんですが、php artisan make:Authコマンドをターミナルなどで打ち込むことでルート登録、Userモデルの作成、テンプレート作成を行ってくれます。

#ルート登録、メソッド確認

ルート登録
これで複数のルートが登録されController/Auth以下のメソッドが使用可能になります。

```routes/web.php
Auth::routes(); 
```

###1 register

```App\Http\Controllers\Auth\RegisterController.php
class RegisterController extends Controller
{

    use RegistersUsers;

    protected $redirectTo = '/home';

    public function __construct() // ①
    {
        $this->middleware('guest');
    }

    protected function validator(array $data) // ②
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);
    }

    protected function create(array $data) // ③
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);
    }
}
```

①のコンストラクタでミドルウェアを使って、以下のメソッドを新規ユーザーのみが使用できるようにする。②でバリデーション、③でUserモデル作ってユーザー作成ね、ふんふん

middleware('guest')を見てみましょう。

```App\Http\kernel.php
        ...
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        ...
    ];
```

```App\Http\Middleware\RedirectIfAuthenticated.php
{

    public function handle($request, Closure $next, $guard = null)
    {
        if (Auth::guard($guard)->check()) {
            return redirect('/home');
        }

        return $next($request);
    }
}
```

Auth::guardで認証チェック
もし認証されていたら/homeに飛ばす、されていなかったら何もしない

guardはガードはどのようにユーザーを認証するかを定義するものです。Webの場合デフォルトではセッションストレージとクッキーを使いながら状態を維持するsessionガードが使われています（APIの場合はトークン）。


短い気もしますが今回はここまでです。疲れた。
次回は（できれば）guardの仕組みについて見てみたいです。
G検定メモ⑬　ディープラーニング　RNN編

G検定を受ける前に、公式テキストを読んでメモした走り書きがあったので公開するよ。

---------------------------------------------------------------------



#６－５．RNN：リカレントニューラルネットワーク

時系列データ処理の分野で用いられるニューラルネットワークをRNNと呼ぶ

###１．時系列データの扱い
「時間軸に対して何かパターンを持っている」データが世の中には多い
例）
・電車の混雑状況は朝と夕方にピークを迎える
・電気の使用量は夏と冬が多くなる
・世界の人口は年々上昇している
など

このような時系列データを用いてニューラルネットワークで予測する場合
例）
・過去の株価から明日の株価を予測する
など
データが持っている「過去の重み」を表現したい。

適切に時系列データを用いた予測を行いたい場合
・データは時間軸に沿って入力すべき
・ネットワークは時間情報を反映できるような仕組みが必要

これらに対応したものが、
######●リカレントニューラルネットワーク：RNN
RNNでできる事
・時系列データをそのまま入力する事が出来る
・データから時間依存性を学習する事が出来る

RNNには複数の手法がある

###２．RNNの基本形
時間依存性を学習するために、過去の隠れ層を追加したネットワークを構築する

RNNモデルに対し、時間軸に沿ったデータを古いものから順番に入力していく。
入力層から隠れ層にネットワークの重みを伝って情報が伝播するのは、通常のニューラルネットワークと同じ。
RNNでは、そこに加えて「過去の隠れ層から現在の隠れ層に対してもつながり（重み）がある」事が大きな違いとなります。
逆伝播する誤差も過去にさかのぼって反映する必要がある。
実際は勾配降下法で式を求めていくだけなので、時間軸に沿って誤差を反映してくため、
BackPropagation Through-Time(BPTT)と呼ばれている

###３．LSTM
RNNの問題点
######1．勾配消失問題
RNNは時間軸に沿って深いネットワークになるので、誤差を逆伝播する際、過去に遡るにつれて勾配が消えていってしまう
######2．時系列データを扱う上での固有の問題
今の時点では関係ないけれど、将来の時点では関係ある　という入力が与えられた際、重みは大きくすべきであり、同時に小さくすべきであるという矛盾を抱える
この問題は入力重み衝突とよばれ、RNNでの学習が上手くいかない要因
出力に関しても、出力重み衝突が発生し学習を妨げる

######●解決策
######LSTM(Long Short-Term Memory)
隠れ層の構造を変えることで勾配消失問題を解決し、同時に入力重み衝突といった問題も解決する

LSTMはLSTMブロックと呼ばれる機構を導入し、時系列情報を上手くネットワーク内に保持する事を可能としています。
LSTMにおける隠れ層は、LSTMブロックがたくさん並ぶことになる。

LSTMブロックは二つの機構から成り立っている
・誤差を内部にとどまらせるためのセル
・必要な情報を必要なタイミングで保持・消去させるためのゲート

セルはCEC（Constant Error Carousel)とも言われ、その名前の通り誤差を内部にとどめ、勾配消失を防ぐためもの
一方ゲートは、入力ゲート、出力ゲート、忘却ゲートの三つからなり、
入力ゲート、出力ゲートはそれぞれ入力重み衝突、出力重み衝突のためのゲート機構、そして忘却ゲートは誤差が過剰にセルに停留するのを防ぐためにリセットの役割を果たす。

LSTMは時系列データを扱う上ではデファクトスタンダードになっているモデルとも言える。
一方LSTMはセルやゲートそれぞれを最適化しなくてはならないため、計算量を多く要する
そのためLSTMを簡略化した、GRU（GatedRecurrentUnit）と呼ばれる手法が代わりに用いられる場合もある。
GRUでは、リセットゲート、更新ゲートというゲートが、入力ゲート、出力ゲート、忘却ゲートの代わりを果たします。

###4．RNNの発展系
######4.1Bidirenctional　RNN
扱う時系列データの種類によっては、LSTM（やGRU）を更に応用させたモデルが用いられます。例えば、時間情報の途中がかけていてそれが何かを予測したい場合は、過去の情報だけでなく、過去と未来両方の情報を使ってよ臆した方が効果的と言えるでしょう。
通常のLSTMは過去から未来への一方向でしか学習をすることができませんが、LSTMを二つ組み合わせることで、未来から過去方向も含めて学習をできるようにしたモデルのことをBidirectional RNN（以下BiRNN）と言います。

######4.2　RNN Encoder-Decoder
これまでのモデルは、入力が時系列で出力は1点のもの。
入力が時系列なら、出力も時系列で予測したい。
そうした問題のことを、シークエンストゥシークエンス（Sequence-to-Sequence）と言い、自然言語処理を中心に大きく研究されている分野の一つ。

土台となるアプローチは二つのLSTMを組み合わせる事
RNN Encoder-Decoderという手法
入力も出力も時系列ならLSTMをそれぞれに対応させれば良い

モデルはエンコーダとデコーダの二つのLSTMに分かれており、
エンコーダが入力データを、デコーダが出力データをそれぞれしょりします。
もちろん出力も時系列なため、全出力を一気に行う事は不可能です。
そのため、デコーダは自身の出力を次のステップで入力として受け取って処理する

######4.3Attention
RNNの応用によって、様々な時系列タスクで高い精度が出せるようになりました。
RNNは過去の時点がどれだけ影響を持っているかは求めていない。

「時間の重み」をネットワークに組み込んだのがAttention と呼ばれる機構
過去の時点それぞれの重みを学習する事で時間の重みを考慮したモデルを実現する。
このAttention も時系列タスクで精度の向上に多大に貢献しましたが、反面実はタスクによっては直近の過去しか重み付けできていないのではないかという指摘も上がっています。
レビュー反省会_bootstrap_terminal

# bootstrap＆terminal
- Bootstrapのグリッドスタイル・ブレイクポイントの理解
https://tonari-it.com/bootstrap_multicolumn_generator/#toc1

- デベロッパーツールで直接打つ
  - デベロッパーツール（検証）で調整しながらCSSに反映させる
  - 利用方法：調べたいページを右クリック→「検証」ツール
     - ショートカットキーは【Ctrl+Shift+I（MacではCommand + Option + I）】、または【F12】キーで起動できます。

- bootstrapに用意されているclass名には意味がある、どのような意味か考えて（調べて）応用していく。

- HTML/CSSはどこまで理解するべき？
  - 基礎的について人に説明できるレベルまで理解できると良い
     - （classって何のためにつけるの？セレクタとは？）

- paddingとmarginの違いは？
  - ざっくりいうと要素に対して内側か外側かの違い
  - marginはautoが使えるよ

- ピクセルってなんだろう？
  - 1ピクセル＝１センチではないよ
  - 画像は小さな「点」の集まり、画像や画面を構成する最小単位がピクセル
  - 画素ともいう
  - 画素数が多い＝点が多い

# メンタリング
- 進捗が悪くて、せっかくのメンタリングなのに具体的な質問ができなかった
- 次回メンタリングまでにPHPの課題（１）を終わらせる
- 質問したいことをまとめておく

明日から沖縄旅行だ〜！
Vueのrender関数経由で単一コンポーネントにdataを渡したい時

#Vueのrender関数経由で単一コンポーネントにdataを渡したい時

このやり方が正しいかどうか知らないけれど、これで出来た。

```javascript:main.js
import App from './App.vue'

const data = [...]

new Vue({
    el: '#app',
    render: h=>h(App, {
        props: {
            somedata: data
        }
    })
})
```


```App.vue
<template>
    <ul>
        <li v-for="(one,index) in somedata">{{one.messsage}}</li>
    </ul>
</template>

<script>
export default {
    props: ['somedata']
}
</script>
```
Ubuntu19.04にpostgisをインストール

- Ubuntu 19.04

```sh
sudo apt install postgresql-server-dev-11 postgresql-11-postgis-2.5
```

```sh
sudo su - postgres
createdb データベース名 --encoding='utf-8' --locale=en_US.utf8 --template=template0
createuser -P ユーザー名
```

`psql`を実行します

```sql
postgres=# grant all privileges on database データベース名 to ユーザー名;
GRANT
postgres=# \q
```

`psql データベース名`を実行します

```sql
データベース名=# create extension postgis;
CREATE EXTENSION
データベース名=# \q
```

`ctrl+d`で抜けてください

## Djangoの設定

```sh
pip install psycopg2-binary
```

`settings.py`の'INSTALLED_APPS'に`django.contrib.gis`を追加

データベースの設定です

```py:settings.py
DATABASES = {
    "default": {
        "ENGINE": "django.contrib.gis.db.backends.postgis",
        "NAME": "データベース名",
        "USER": "ユーザー名",
        "PASSWORD": "パスワード",
        "HOST": "localhost",
        "PORT": "",
    }
}
```
nuxt+axiosでBasic認証をかけた状態で別のBasic認証が掛かったAPIを叩くと認証がコケる

表題の通り。

[nuxt-basic-auth-module](https://github.com/potato4d/nuxt-basic-auth-module)などを使って、フロントにBasic認証をかけた状態で、更にBasic認証が掛かっているAPIなどaxiosのドキュメントにある方法で叩くと401となり認証に失敗する。

```javascript:NGパターン
const { data } = await $axios.get('/endpoint', {
  auth: {
    username: 'janedoe',
    password: 's00pers3cret'
  }
})
```

この方法で叩くと、nuxtにあるBasic認証のユーザー名・パスワードでAPIにアクセスしてしまい、ユーザー名・パスワードが異なる場合は401となる。

叩いたログをみたところ、headerのAutorizationがnuxtのbasic認証で上書きされる(or axiosが上書きしない)ようだった。

```javascript:NGパターン
const username = 'janedoe'
const password = 's00pers3cret'
const basicAuth = 'Basic ' + Buffer.from(username + ':' + password).toString('base64')
const { data } = await $axios.get('/alives', {
  headers: { 'Authorization': basicAuth }
})
```

上記のとおり，強制的にheaderを指定したら200になった。
G検定メモ⑪　ディープラーニングの関数編

G検定を受ける前に、公式テキストを読んでメモした走り書きがあったので公開するよ。

---------------------------------------------------------------------


#1．tanh関数

ディープニューラルネットワークの問題点
層が深くなると誤差逆伝播法が使えない
→勾配消失問題

勾配消失問題の理由
→シグモイド関数の微分（最大値）

重要な点
出力層では、シグモイド関数やソフトマックス関数を用いないと、出力を確立で表現できいので、これらの関数を変更することはできない。
しかし
隠れ層では違う
隠れ層では、任意の実数を（非線形に）変換することができる関数であれば、特にどんな関数であろうと問題はない。

そこで、活性化関数を工夫した

###1.tanh関数（ハイパボリックタンジェント関数）
シグモイド関数の最大値は0.25だが、tanh関数の最大値は1となる。

###2．ReLU関数
tanh関数の代わりに、現在最もよく使われている
ReLU（Recitified Linear Unit）関数
y=max（0,x）
ｘが0より大きい限り1となるため、ピーク時のみ1となるtanh関数よりも
誤差逆伝播の際に勾配が小さくなりにくい（勾配消失しにくい）

ｘが0以下の時は、微分値も0になるので学習がうまく行かない場合もある。

派生形
###3.LeakyReLU関数
ｘが0以下でも小さな傾きがある。
###4.ParametricReLU
LeakyReLU関数の傾きを学習によって最適化する
###5.Randomized　ReLU
複数の傾きをランダムに試す

どれが一番いいかは一概には言えない



#6－2　学習率の最適化

###1．勾配降下法

機械学習の手法が目指している物
「モデルの予測値と、実際の値の誤差を無くすこと」

誤差を誤差関数と定義して、これを最小化する、という問題
関数の最小化問題

関数の最小化とは微分
それぞれの層の重みで誤差関数を微分した値がzeroになるような重みを求めれば良いこここでは、偏微分となる。

問題点
ニューラルネットワークで解こうとする問題h、次元が多次元に渡るので、最適なパラメータが簡単には求まらない
そこで、解析的に求めるのではなく、アルゴリズムを用いて最適解を探索するアプローチをとる
ここで用いられる手法のことを　勾配降下法　と言う

勾配降下法
勾配に沿って降りていくことで界を探索する　手法

勾配とは微分値
微分は接線の傾きを意味する
x^（k+1）=ｘ^（k）ーαｆ’（ｘ^（ｋ））（α＞0）
エポック　ｋ、これまで何回繰り返し計算を行ったかをしめす
α　学習率と呼ばれるハイパーパラメータ
勾配に沿って一度にどれだけおりて行くかをきめるもの

ニューラルネットワークでは、各パラメータ（重み）にたいして勾配降下法を適用する
勾配降下法を用いて繰り返し計算を行うこと

###2．勾配降下法の問題と改善
勾配降下法では、最適な解が得られないケースが多々ある
勾配降下法は「見せかけの最適解」であるかどうかを見抜く事ができません。
見せかけの解を　局所最適解
本当の解を　大域最適解

局所最適解を防ぐ方法
・学習率の値を大きく設定　する
　問題点　学習率が大きすぎて、最適解を飛び越えて探索し続けてしまう
→適切なタイ民腕学習率の値を小さくしていく

よりやっかいな問題点
鞍点　あんてん
ある次元から見れば極小、別の次元から見れば極大となる
一度鞍点付近に陥ると抜け出せなくなる。
こうした停留状態にあることを　プラトー　と呼ぶ

回避策
どの方向に沿って勾配を進んでいるとき学習率を大きく（あるいは小さく）すべきか考える

1990年　モーメンタムという手法
最適化の進行方向に学習を加速させることで学習の停滞を防ぐ

Adagrad
Adadelta
RMSprop
Adam
それぞれ、土台はモーメンタムと同じどの方向に学習を加速すればよいかと考えた物。

新しい手法
RMSprop
Adam
が用いられるケースがほとん


#6-3　さらなるテクニック

###1．ドロップアウト

機械学習の最大の敵　「オーバーフィッティング」

###1.ドロップアウト
ランダムにニューロンをドロップアウトさせる
エポックごとにニューロンを除外する
単一のネットワークで学習するとオーバーフィッティングになりやすい
→毎回ことなるネットワークで複数学習する事でリスクの回避
ドロップアウトはアンサンブル学習を行っている

###2．early　stopping
学習を早めに打ち切る
テストデータに対する誤差関数の値が上がり始めたら、その時点で学習をやめる
とても効果的な手法で、ジェフリーヒントンもearlystoppingの事を、※Beautiful FREE LUNCH と表現している

※ノーフリーランチ定理にかけた表現
ノーフリーランチ定理とは、「あらゆる問題で性能の良い汎用最適解化戦略は理論上不可能」というもの
ヒントン先生も上手い事言ってやったぜ的な感じだったんだろうな～

###3．データの正規化・重みの初期化
データ全体を調整する処理・・・正規化
事前にデータのスケールを調整した方が効率よく学習が行える。

入力データの正規化の種類
・各特徴量を0～1の範囲に変換する処理
それぞれの特徴量をおなz特徴量の最大値で割る
これにより、各特徴量間のスケールの違いを合わせることができる
→画像データの処理に使うことが多い

###標準化
各特徴量の平均を0、分散を1にする、
すなわち各特徴量を標準正規分布に従うように変換する

###白色化
各特徴量を無相関化したうえで、標準化するという手法
効果的だが、計算コストが高いので、標準化を用いるのが一般的


###正規化
・・・偏りのあるデータの偏りを無くすための前処理
###標準化
・・・データを標準正規分布に従うように変換する
###白色化
・・・正規化の一種で、データの相関を無くす処理

　　　　　　相関を無くしたら標準化して正規分布にする


データの標準化は機械学習全般に効果的
しかし、ディープニューラルネットワークの学習では、効果が薄くなる
・解決策
「重みの初期値を工夫する」

勾配降下法に用いる初期値は乱数が使われていた。
これらの乱数にネットワークの大きさに合わせた敵と運計数をかける
ことで、データの分布が崩れにくい初期値が考えられた。

シグモイド関数・・・Xavierの初期値
ReLU関数・・・Heの初期値

勾配降下法の探索は初期値に依存するので、重みの初期値の設定は重要。

###4．バッチ正規化

各層に伝わってきたデータを、その層でまた正規化してしまう。
バッチ正規化（batch normalization）
各層において活性化関数をかける前に伝播してきたデータを正規化する

バッチ正規化は非常に強力な手法
・学習が上手くいきやすくなる
・オーバーフィッティングしにくくなる
簡易スクリプトでハードウェア情報を取得する

# はじめに

物理サーバーを何台か運用していると、サーバーごとのハードウェア構成が分からなくなることがあります。
特に途中でハードウェア構成を変更した場合、変更がしっかり管理されていないとハードウェア構成が完全に分からなくなります。

そこでサーバーを停止させることなく、リモートからサーバーのハードウェア構成を（少しだけ）取得できる簡易スクリプトを作ってみました。

# スクリプト

* スマートな書き方が分からなかったので、`echo`を連発しています...
* PCI-Express接続のデバイスについては、SSD（NVMe-SSD）のみ表示するようにしています。
  * PCI-Express接続のデバイスには、RAIDコントローラーやネットワークカードなどもありますが、これらが手元になかったのでとりあえずNVMe-SSDだけ表示するようにしています。
  * 参考：[NVMe接続のSSDの型番を調べる方法](https://qiita.com/nkojima/items/cf0a1dceca60eedf3197)
* `echo "$(lspci | grep -iE "SSD|Non-Volatile memory")"`の行では、標準出力される文字列の途中（※末尾ではない）から改行が消えないように、式展開した結果をダブルクォートで囲んでいます。
  * [参考URL](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1368521433)

```bash:hardware_info.sh
#!/bin/bash

echo "[CPU Info]"
echo $(cat /proc/cpuinfo | grep "model name" | sort -u)
echo $(cat /proc/cpuinfo | grep "cpu cores" | sort -u)
echo "cpu threads : "$(cat /proc/cpuinfo | grep "processor" | wc -l)

echo "[Memory Info]"
echo $(cat /proc/meminfo | grep "MemTotal" | sort -u)

echo "[SCSI device]"
echo $(cat /proc/scsi/scsi)

echo "[PCI-E device]"
echo "$(lspci | grep -iE "SSD|Non-Volatile memory")"
```

# 実行結果の例

## 手元のPCでの実行結果

* CPUが2コア4スレッド、メモリが8GBと少々貧弱な環境だと分かります。
* `SCSI device`には、USB接続の外付けDVDドライブが表示されています。
  * 当初はSATA接続の機器だけが表示されると思っていたので、これは少々意外でした。

```
[CPU Info]
model name : Intel(R) Pentium(R) CPU G4560 @ 3.50GHz
cpu cores : 2
cpu threads : 4
[Memory Info]
MemTotal: 7706396 kB
[SCSI device]
Attached devices: Host: scsi4 Channel: 00 Id: 00 Lun: 00 Vendor: BUFFALO Model: Optical Drive Rev: BFT6 Type: CD-ROM ANSI SCSI revision: 00
[PCI-E device]
01:00.0 Non-Volatile memory controller: Phison Electronics Corporation Device 5012 (rev 01)
```


## [paiza.io](https://paiza.io/ja)での実行結果

* CPUの型番やNVMe-SSDの型番から、裏側で動いているのはAWSだと分かります。
* NVMe-SSDが2つ検出されていますが、このサーバーがどのような構成なのかが気になります。
  * OS用に1つ、データ領域用に1つ使っているのでしょうか？
  * 普通のサーバーだとRAIDコントローラーの配下に置かれるので、直接HDDやSSDが見られないと思うのですが...

```
[CPU Info]
model name : Intel(R) Xeon(R) Platinum 8124M CPU @ 3.00GHz
cpu cores : 4
cpu threads : 8
[Memory Info]
MemTotal: 15835408 kB
[SCSI device]

[PCI-E device]
00:04.0 Non-Volatile memory controller: Amazon.com, Inc. Device 8061
00:1f.0 Non-Volatile memory controller: Amazon.com, Inc. NVMe SSD Controller
```
lazy_staticを使ったglobal変数 (Hashmap版）メモ

```rust
use std::sync::{Arc, Mutex, RwLock, RwLockWriteGuard};
use std::thread;
use std::collections::HashMap;
use std::fmt::{Formatter, Error};
use lazy_static::lazy_static;

struct Counter {
    count: i32,
}

struct BigStruct {
    counter: Option<Counter>,
}

impl BigStruct {
    fn increment(&mut self) {
        match self.counter {
            Some(ref mut counter) => {
                counter.count += 1;
            },
            None => {},
        }
    }
}

impl std::fmt::Display for BigStruct {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
        match self.counter {
            Some(ref counter) => {
                write!(f, "count: {}", counter.count)
            },
            None => {
                write!(f, "count: {}", 0)
            },
        }
    }
}

lazy_static! {
    static ref MAP_COUNTER: RwLock<HashMap<String, Arc<Mutex<BigStruct>>>> = {
        let map = HashMap::new();
        RwLock::new(map)
    };
}

fn get_global_counter(key: String) -> Arc<Mutex<BigStruct>> {
    let mut map: RwLockWriteGuard<HashMap<String, Arc<Mutex<BigStruct>>>> = MAP_COUNTER.try_write().unwrap();
    if !map.contains_key(&key.clone()) {
        let big_struct = BigStruct {
            counter: Some(Counter{ count: 0 }),
        };
        map.insert(key.clone(), Arc::new(Mutex::new(big_struct)));
    }
    let writer = map.get(&key.clone()).unwrap();
    Arc::clone(writer)
}

fn main() {
    let mut handles = vec![];

    let key = String::from("1");
    let counter = get_global_counter(key);

    for _ in 0..10 {
        let counter = Arc::clone(&counter);

        let handle = thread::spawn(move || {
            let mut big_struct = counter.lock().unwrap();
            // thread::sleep(std::time::Duration::from_secs(1));
            big_struct.increment();
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap_or_default();
    }
    println!("Result: {}", *counter.lock().unwrap());
}
```
Dockerでウェブアプリ開発する時の設定

メモ

```
docker run --name hoge -p 127.0.0.1:8000:8000 --rm -it -v $(pwd)/src:/home/hoge/src django
```
- django: イメージ名
- `-p`: ポートフォーワード. これが無いと外部（ブラウザ）からアクセスできない
- `-v`: ローカルのディレクトリをコンテナにマウント. ウェブアプリに限らず開発時はこれをつける. でないと, ローカルで編集したプログラムファイルとかがコンテナに即時反映されない