OmniAICreator/Qiita-1.07M huggingface dataset:
ダンボールロボットでslackに投稿する

# 概要

ダンボールロボットから、Slackの指定したワークスペースに投稿をします
ダンボールロボットの`http.post`コマンドと、slack APIのwebhooksを使います

slackbotの設定が分かる場合は、「ダンボールロボットのスクリプトを書く」まで飛ばしてください

**注1: 記事の中では、Slackの設定画面が英語になっていますが、設定によっては英語でない可能性があるので、適宜読み替えてください**


# 手順
## slackbotの準備をする
ダンボールロボットが投稿するslackのチャンネルを指定します
テスト用のslackがない場合は、自分だけいるslackのワークスペースを作るのがおすすめです

### Slack App を作る

ここのURLに行きます
https://api.slack.com/bot-users

ページの途中に、"Create your Slack app"という緑のボタンがあるので押します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430849/6e4cc49a-eb5c-4cc8-8737-de01997790ef.png)

### slackbot の設定をする
このような画面が出るので

- bot の名前
- bot を使うワークスペース

を入力します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430849/db2756ef-4c3d-6107-5a13-0fc6d836faa4.png)

設定ができたら、今つくったslackbotの名前をクリックして、設定画面に行きますslackbotをクリックする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430849/1e8bf312-93e9-95f8-4133-73c30a6400df.png)

### slackbot の Incoming Webhooks の設定をする

webhookを有効にすると、ダンボールロボットから`http.post/<webhookのURL>`とするだけでslackに投稿できます

下の画面で緑のチェックがついている "Incoming Webhooks"をクリックして設定画面に行きます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430849/381e56a2-07c6-ec86-e118-5a5ad12f48b8.png)

設定画面でやることは、

1. webhookを有効にする
2. 新しいwebhookのURLを取得する

の2つです

１つ目は、下の画像のようにスイッチをオンにします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430849/5191d64a-101b-e38a-f2fc-1d0defd0003c.png)

2つめは、"Add New Webhook to Workspace"をクリック
--> slackbotを投稿するチャンネルを指定します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430849/00cad416-fc6b-1288-1da9-7c710a3448a1.png)

### URLをメモっとく

このWebhook URLをダンボールロボットで使うので、メモっておいてください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430849/8337e740-6723-fe10-629d-59955cba1e99.png)

## ダンボールロボットのスクリプトを書く

### シナリオエディタを開く

`<ラズパイのIPアドレス>:3090/scenario-editor`
に行きます

### slackに投稿するDoraScriptを書く

```bash
/.payload.text/おはようボット
/http.post/<さっきのWebhookURL>
```

以上です

解説すると、`/http.post/<URL>`は**payload**に入っているオブジェクトを`<URL>`で指定したURLにPOSTします
slack APIは、 `{ "text": "投稿したいメッセージ" }` の形式のデータだけ受け付けてくれます
なので、`.payload.text/おはようボット`と書きます
これは、「payloadオブジェクトのtextプロパティに「おはようボット」を入れる」と言っています
この時点のpayloadはこうなっています↓

```JSON
payload: {
  "text": おはようボット
}
```

よくわからなかったら、 `/log/{{payload.text}}`とすると見れます

### おまけ: 音声認識結果をslackの投稿する

例えば、こんなかんじでslackと連携させるとか

**注2: これは Google Cloud Speech APIの設定をしてないと動きません**
ここを見てね
https://yamagame.github.io/dora-engine-doc/speech-to-text

```javascript
/speech-to-text // 音声認識; 結果はpayloadに入る
/.input/{{payload}} // payloadの値をinputに代入
/log/{{input}} // inputの中身を確認

/.payload.text/{{input}} // payloadにslackbotにわたす値を入れる
/http.post/<slackbotのwebhook URL> // slackbotに音声認識結果をPOSTする
[UE4] ライト設定の単位(ルーメンやカンデラ)について

UnrealEngineのライトを設定する時の単位として
**Lumens**(ルーメン)、**Candelas**(カンデラ)、**Unitless**(ユニットレス)が存在します。
ユニットレスは、ルーメンとカンデラが導入される前に実装されていたもので、
UnrealEngineで独自に定義されたものになります。
今回はこの単位によって、エディター上での扱いがどのように変わるのか紹介していきます。
![2019-12-19_14h36_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/2e5ac4b5-91cc-1a0a-cea0-f300be48f1b6.png)

## 単位を変えるとIntensityが調整される
まず、ライトの単位を変更すると見た目上同じような明るさになるように自動でIntensityが調整されます。

注意点として切り替え時に計算誤差により、
他の単位に一度変えた後もとの単位に戻すと完全に同じ値に戻らない場合があります。
![unit.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/3fd1b5ee-cfc8-7447-717e-6ca5067ede2e.gif)

## 扱う上での挙動、注意点
単位を変えた時に変わってくる挙動として、スポットライトの影響半径を変えた時の明るさがあります。
以下GIF動画で、それぞれ単位を設定したスポットライトの半径を変えている様子を示します。
**ルーメン**の場合は、範囲を狭めていく**と明るくなっていく**様子が見えるかと思いますが、
**カンデラ**の場合は、**そのままの明るさ**の見た目で範囲が狭まっていく様子が見えるかと思います。
(ユニットレスは値は違いますがカンデラと同様の挙動になります。)
![compare.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/8149712f-53d4-a2c4-fe9a-7fa175a98d9c.gif)

## ルーメンとカンデラの単位について
ここからは上記の挙動の違いがなぜ起きるのかについて紹介していきます。

まず単位についてですが、**ルーメン**は全ての方向に対して1カンデラの光度を持つ標準の点光源が、1ステラジアンの立体角内に放出する光束の単位で、**カンデラ**は特定の方向へ放射される単位立体角あたりの光の明るさ、光度の単位として扱っています。

## 抑えておきたい点
抑えておきたい点として、単位の紹介で登場してきた光束は、
密度が高くなると結果としてライトが明るく見える、ということがあります。

スライドの図はかなり簡略化したイメージ図になりますが、
矢印を光束としてポイントライトとスポットライトを模したものです。

同じ本数の矢印をライトから飛ばそうとした場合、
拡散されているポイントライトよりもスポットライトの方が、
光束の密度が高くなっていることがイメージできるかと思います。
そしてこのように密度が上がった状態になるとライトがより明るく見える、ということになります。
![2019-12-19_15h12_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/2eb097c0-c7be-7df3-1123-82f6af0edf70.png)

## ルーメンの挙動

ルーメン単位の設定は、設定する値(Intensity)がそのライトから放出するすべての光束の量となります。
ルーメンで指定している場合ライトの範囲を変更しても、その範囲に同じ量の光束が放射されるため、
結果光束の密度が上がり明るく見えるようになります。
![2019-12-19_15h08_45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/fbfafa78-6cf5-4145-e982-086feaa02716.png)

UnrealEngine上でルーメン単位を設定したライトの影響範囲を変えた時の挙動は以下のようになります。
ライトの範囲を狭くしていくと中心が明るくなっていく様子がわかるかと思います。
![lumen.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/ca428ff2-427d-d698-b692-63b2357b1121.gif)


## カンデラの挙動
カンデラの場合は、設定する値(Intensity)が単位立体角あたりの光束となります。
カンデラで指定している場合、スポットライトなどでライトの範囲を制限しても
単位立体角あたりの放射される光束の量が変わらないので、明るさが同じとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/f2416b93-7e56-6b78-f441-fe70f1cf6cc6.png)

UnrealEngine上でカンデラ単位を設定したライトの影響範囲を変えた時の挙動は以下のようになります。
ルーメンの挙動と違い、ライトの範囲を変えても中心の明るさが変わらないことが見えるかと思います。
![Candela.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/e556ec77-2ffa-f538-1c2a-2d2298a56553.gif)

## まとめ
最後にもう一度ライトの設定を変更する時の挙動の違いをまとめると、
**ルーメンを使用した場合**、ライトを照らすコーンアングルによって**明るさが変わり**、
**カンデラを使用した場合**、ライトを照らすコーンアングルによっても**明るさが変わらない**ライトとなります。
![compare.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/8149712f-53d4-a2c4-fe9a-7fa175a98d9c.gif)

## さいごに
今回はパラメータを変更する際の挙動についてフォーカスしましたが、
もちろん照明の設計により単位が決められている場合もあるかと思います。
ライトの値を調整する際は、こちらの設定を確認頂ければと思います。
AWS vs. Azure: やらかさないで！Azure ではOSからシャットダウンしてもインスタンス利用料が継続する...

課金体系について相違があるのでWindowsやLinux機を立ち上げることを主にハイレベルで差がありそうな部分を中心に整理してみました。Azureに特に気を付けないといけない注意点がある反面、Azureの方が有利となるケースもありました。


#**AWS**

OSを停止するとstoppedになる。後述のterminatedに直接することもできる。
この状態であればインスタンス実行時間としては課金されない。
普通に考えると自然なケース。
terminatedは不要システム自体の廃止。当然課金されない。
1時間単位または1秒（1分）単位での課金でOSイメージ
（AMI）や契約形態により異なるが、
オンデマンドでWindowsを使うと1時間単位の模様。
システム停止や再起動をするとその時点で1時間使用したとみなされて課金される。
クライアントPCのような扱いで短時間、頻繁な停止・未利用時間や
再起動が伴う作業には不向き。
固定IP利用の場合、インスタンス実行中は追加請求がないが停止して割り当て解除しないと費用がかかる。

![instance_lifecycle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518389/18cdaf42-de90-a07a-890f-ab64c3965990.png)
（出所）https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html

＊EC2のハイレベル価格体系（詳細はAWS公式情報を参考のこと）＊
●オンデマンド：使った分だけ支払い。一番わかりやすくてオーソドックス。
●（2019年11月導入）Savings Plan：長期契約、年額コミットメントに対する割引で時間当たり単価ないしはリージョン毎に指定された特定インスタンスを使用するコミット。プランによってはEC2以外もまとめることができる対象となるサービスがある。
●スポット：問答無用で2分警告で停止される恐れがあるがリソースに空きがある場合に事前承認されれば割安利用可。
●リザーブド：キャンセル不可が前提。確定スペック、確定（予約）時間で長期契約（プランによって上位タイプへ変更可能（convertible）とするプランとできないプランがある）。

#**Azure**

**OSからシャットダウンコマンドで停止しても課金が継続される（stopped / 停止済み）。**
AWSになれていると勘違いしてとんでもないコスト発生危険あり。
割り当て解除という処理を踏まないといけない。

1秒単位の課金で請求時合算で1分に満たないものは切り捨て。

**Azure Portalから停止した場合にのみ割り当て解除になる
（Stopoped (Deallocated) 停止済み(割り当て解除済)）。**
固定IP利用の場合、（現代のリソースマネージャーを経由したインスタンスの作り方では）AWSと異なりインスタンスが実行されていても費用がかかる違いがある。

![vm-power-states.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518389/a9f6f79e-0ccb-fdde-f73d-775e9e6aba3b.png)
（出所）
https://docs.microsoft.com/ja-jp/azure/virtual-machines/windows/states-lifecycle

＊Virtual Machinesのハイレベル価格体系（詳細はAzure公式情報を参考のこと）＊

●従量：使った分だけ支払い。一番わかりやすくてオーソドックス。
●（2019年11月から？）「Azureの予約」：年額コミットメントに対する割引。Virtual Machinesと他にいくつかまとめることができる対象となるリソースがある。
●スポット：問答無用で30秒警告で停止される恐れがあるがリソースに空きがある場合に事前承認されれば割安利用可。
●リザーブド：確定スペック、確定（予約）時間で長期契約。中途解約料支払いで中途解約ができることがある。
●Dev/Test：開発/テストでの使用に限定で個人向け、チーム向けのパッケージがある。

Windows ServerかSQL ServerでSA付ライセンスを保有している場合はハイブリッド価格というもので一般向け料金より安くなることがある。
ｉタウンページのスクレイピング：賢早くんの代わりになりたかった

#背景

[iタウンページ](https://itp.ne.jp/)の特定の情報を網羅的に取得するために、[賢早くん](http://www.mjakk.jp/kensakun/)というExcelマクロが配布されていたのですが、2019年11月のiタウンページ側の仕様変更により使用できなくなってしまいました。
そこで、スクレイピングの練習も兼ねて、Python初心者（大学の講義で少し触れた程度）が青息吐息でプログラミングに挑戦しました。
最終目標は「特定の小カテゴリーから店舗名・住所・カテゴリを取得する」です。



#規約の確認

タウンページの規約ですが、以下の二点が禁止されています。
・ｉタウンページのサービスに多大な影響を与える行為
・自動的にアクセスするプログラムを使用してｉタウンページに繰り返しアクセスする行為
https://itp.ne.jp/guide/web/notice/
今回は、ページの続きを読み込むためのボタンを最下まで押すだけというクソコードなので、繰り返しのアクセスではなく通常の利用の範疇ではないかと想定しています（これが不可なら通常利用でも最下までたどり着けない仕様……）。



#環境
- Windows10
- Spyder3.3.6(Python3.7)
- Selenium
- Google Chrome 79



#コード
###Seleniumのインストール
Anaconda Prompt上で

```python
pip install selenium
```

###ドライバの指定・Chromeの起動

```python
driver = webdriver.Chrome(executable_path='/Users/*****/*****/Selenium/chromedriver/chromedriver.exe')
driver.get('https://itp.ne.jp/genre/?area=13&genre=13&subgenre=177&sort=01&sbmap=false')
```

ドライバを指定した後，ブラウザで指定したURLを立ち上げます。
今回はパチンコ店を調べたので，エリア「東京都」，カテゴリ「屋内遊戯」で検索した場合のURLです。

###最下行まで表示
```python
while True:
    try:
        driver.find_element_by_class_name('m-read-more__text').click()
    except:
        print('☆「更に表示」連打終了☆')
        break
```

エラーを吐くまで（＝最下行まで）「さらに表示」ボタンを連打します。
これでHTML上に，ヒットしたすべての店舗情報を表示します。

###カテゴリー名を回収
```python
elist = []
elems = driver.find_elements_by_class_name("m-article-card__header__category")
for e in elems:
     elist.append(e.text)
print(elist)

str_ = '\n'.join(elist)
print(str_)
with open("str_.txt",'w')as f:
    f.write(str_)
```

空のリストを作成して，Class名がm-article-card__header__categoryの要素のinnerTextをそこに放り込みます。
そののち，リストを1要素ずつ改行した文章にして，テキストで出力します。

###終わり
```python
flist = []
elems2 = driver.find_elementｓ_by_class_name("m-article-card__header__title__link")
for f in elems2:
     flist.append(f.text)
print(flist)

str2_ = '\n'.join(flist)
print(str2_)
with open("str2_.txt",'w')as f:
    f.write(str2_)


glist = []
elems3 = elems2 = driver.find_elementｓ_by_class_name("m-article-card__lead__caption")
for g in elems3:
     glist.append(g.text)
print(glist)

str3_ = '\n'.join(glist)
print(str3_)
with open("str3_.txt",'w')as f:
    f.write(str3_)


print('成功')
driver.quit()
```

タイトルとキャプション（住所・電話番号・最寄駅）についても，同じように出力します。
※キャプションはタイトルやカテゴリーと行数が違うので，Excelで整形しました。


#詰まったところ
###解決したところ
・forの後に:（コロン）を付け忘れる
・無限回繰り返す方法がわからない
→While True:でした。Trueが大文字始まりというところでも詰まりました
・ファイルに書き出す方法がわからない
→ファイル名を””で囲んでいなかったのが原因でした
・chromeDriverの場所の指定の仕方がわからない
→Chromedriverの入っているフォルダーまでしか指定していませんでした。当然Chromedriver.exeまで指定
・コマンドプロンプトでpip install seleniumを実行しても、Spyder上で実行できない
→Anaconda Prompt側で実行しないといけない
……他多数

###未解決問題
・pipが何かわかっていない
・htmlの構造がわからない
→結局わからなかったのでSeleniumでブラウザを動かす形に
・【住所】の他に【電話番号】【最寄駅】がついてくる
→これが結構致命的で、おそらく本当は店舗１件をひとまとまりとして書き出した方がいいのでしょう（今回はExcelで処理しました）。本格的に必要になれば書き換える予定です

###その他
・全国すべての店舗を表示するURLはhttps://itp.ne.jp/genre/
・東京都の店舗を表示するURLはhttps://itp.ne.jp/genre/?area=13

#2019/12/20追記
カテゴリ，タイトル，住所それぞれで回収するでのはなく，class="o-result-article-list__item"で店舗ごとに回収したほうが整形しやすい事に気が付きました。
@contentを使って、@mixinにスタイルセットを渡す


## `@mixin`（ミックスイン）おさらい

**Mixin（ミックスイン）**は関数に近く、
CSSスニペットに名前を付けていつでもどこでも呼び出せるというイメージ。

**`mix`**の呼び出しは**`@include`** **で呼び出す**。


```app.css

/*
ミックスイン
よく使うものをスニペットとして保存しておこう
*/

/* 
ミックスインの作り方
頭に@mixinを付ける

@mixin 名前($変数1,$変数2,...){

    プロパティ1:$変数1;
    プロパティ2:$変数2;
    プロパティ3:$変数1 $変数2 ...;
}
*/

/*
ミックスインの使い方 
頭に@includeを付ける

@include 名前(値1,値2,...);
*/

（例）

@mixin btn() {
  display: block;
  padding: 20px 30px;
  color: #fff;
  border-radius: 6px;
  cursor: pointer;
  background-color: #20aee5;
  text: {
    decoration: none;
    align: center;
  }
}

.footer__sns__btn {
  @include btn(); // 『@include class名()』で呼び出し
}

```


## `@content` の使い方

・ `@mixin`の中で`@content;`と記述するとコンテントブロックを渡すことができる
・ これにより1つのmixinで呼び出し側に合わせた処理が可能

例えば、`mixin,scss`というscssファイルに
スマートフォンでのレスポンシブを`@mixin`似て呼び出せるようにしておきます。

```mixin.scss
@mixin sp {
  @media screen and (max-width: 767px) {
    @content;
  }
}
```

```例.scss
.p-top-training {
  margin: 60px auto;
  padding-bottom: 98px;
  position: reltive;
  @include sp {
    margin-top: .8rem;
    padding: 0 .2rem .6rem 0;
  }
&-content {
    background: url(/xxx/xxx.jpg) no-repeat center/cover;
    width: 1120px;
    height: 600px;
    padding: 100px 100px 155px 420px;
    @include sp {
      background: url(/xxx/xxx.jpg) no-repeat center/content;
      height: 5rem;
      padding: .6rem .4rem .8rem;
      width: 355px;
    }
  }
  &-background {
    background: url(/xxx/xxx.png) no-repeat center/contain;
    width: 1276px;
    height: 240px;
    position: absolute;
    right: 0;
    bottom: -29px;
    z-index: -5;
  }
  &-title {
    font-size: 60px;
    letter-spacing: 6px;
    color: #fff;
    text-align: center;
    @include sp {
      font-size: .4rem;
      letter-spacing: .04rem;
    }
  }
```

こうすることによって各クラスに対して記述した
`@include sp {}`の部分が`@content`の部分に挿入されて行きます。
レスポンシブ対応などは、下にまとめて記述するより、タブレットごとの相違が一目瞭然になるのでわかりやすくなります。
機械学習でターゲットをlogで正規分布した結果

# 概要
大した内容ではありません。
2ヶ月くらい前に下書きした内容なのですが、削除するくらいなら公開しようと思いました。
この記事では機械学習の初心者レベルの実験をしています。

https://qiita.com/katsu1110/items/a1c3185fec39e5629bcb
↑このページを参考にしています。勉強になりました。

欠損値などを自分の考えできれいにしたりして、ランダムフォレストの分類器に入れて、評価をしました。

#logを使ってターゲットの列を正規分布にしたら、どのくらい効果があるのか
これが、今回の記事の目的です。これ以外の作業は一切修正しないで、結果を比較してみようという考えです。

```python
#RandomForestで学習させる
from sklearn.ensemble import RandomForestRegressor
rdf = RandomForestRegressor(n_estimators=200, max_depth=5, max_features=0.5, random_state=449, jobs=-1)
clf = rdf.fit(x_train, y_train)
print('train: {:.4%}'.format(clf.score(x_train, y_train))) 
print('test : {:.4%}'.format(clf.score(x_test, y_test))) 

y_pred_train = rdf.predict(x_train)
y_pred_test = rdf.predict(x_test)

from sklearn.metrics import r2_score
print("trainのR2              : {:.4%}".format(r2_score(y_train, y_pred_train)))
print("test のR2              : {:.4%}".format(r2_score(y_test , y_pred_test)))

# 平均絶対誤差（MAE）
from sklearn.metrics import mean_absolute_error
print("trainの平均絶対誤差(MAE) : {:.4f}".format(mean_absolute_error(y_train, y_pred_train)))
print("test の平均絶対誤差(MAE) : {:.4f}".format(mean_absolute_error(y_test , y_pred_test )))

# 平方根平均二乗誤差（RMSE）
from sklearn.metrics import mean_squared_error
print("trainの平均二乗誤差（RMSE）: {:.4f}".format(np.sqrt(mean_squared_error(y_train, y_pred_train))))
print("test の平均二乗誤差（RMSE）: {:.4f}".format(np.sqrt(mean_squared_error(y_test , y_pred_test ))))

# RMSLE (Root Mean Squared Logarithmic Error)
# 外れ値に強い
from sklearn.metrics import mean_squared_log_error
print("trainのRMSLE           : {:.4f}".format(np.sqrt(mean_squared_log_error(y_train, y_pred_train))))
print("test のRMSLE           : {:.4f}".format(np.sqrt(mean_squared_log_error(y_test , y_pred_test ))))
```
このようにやりました。
そして、ターゲットをlogを使わないで出てきた結果はこのようになりました。

```
trainの正解率 (Accuracy): 91.4618%
test の正解率 (Accuracy): 83.6505%
trainのR2              : 91.4618%
test のR2              : 83.6505%
trainの平均絶対誤差(MAE) : 16175.1998
test の平均絶対誤差(MAE) : 19230.9896
trainの平均二乗誤差（RMSE）: 22927.9516
test の平均二乗誤差（RMSE）: 33601.6305
trainのRMSLE           : 0.1432
test のRMSLE           : 0.1511
```

これに対して、ターゲットをlogを使って正規分布に疑似化した場合は、以下のようになりました。

```
trainの正解率 (Accuracy): 90.5080%
test の正解率 (Accuracy): 86.0260%
trainのR2              : 90.5080%
test のR2              : 86.0260%
trainの平均絶対誤差(MAE) : 0.0893
test の平均絶対誤差(MAE) : 0.0990
trainの平均二乗誤差（RMSE）: 0.1238
test の平均二乗誤差（RMSE）: 0.1455
trainのRMSLE           : 0.0096
test のRMSLE           : 0.0111
```
なんか、評価の数値が全然ちがう結果になっているところがありますが、MAEはlogにしているからだと思いますが、RMSLEがぜんぜん違うのは、ちょっと意味不明です。（何か間違っていると思いますが、とりあえず記事にしてしまいました。）

#結果
以上の評価結果で、提出ファイルを作って提出したところ、
ターゲットにlogを使わないで学習させた場合の結果は、
RMSLE 0.17481  4,635チーム中3591位でした。
これに対して、ターゲットにlogを使って学習させた場合の結果は、
RMSLE 0.16123  4,635チーム中3277位でした。

ということで、ターケットの正規化は効果ありということを確認出来ました。
jsで配列の特定keyを指定してgroupByをしたい（lodashすげ〜）

# jsで配列の特定keyを指定してgroupByをしたい（lodashすげ〜）

### 結論
lodashすげ〜!!


```javascript
const array = [
  {id: 1, category: 'ねこ', name: 'ポチ'},
  {id: 1, category: 'ねこ', name: 'ねこねこ'},
  {id: 1, category: 'いぬ', name: 'にゃん'},
];
const key = 'category';

const res = _.groupBy(array, key);
```

## まとめ
lodashはすごいからとりあえずドキュメント読んでおこう！！

Lodash → https://lodash.com/docs/4.17.15
LodashのgroupBy → https://lodash.com/docs/4.17.15#groupBy
VScodeでAndroidエミュレーターを使ってFlutterアプリをデバッグするのにハマった

#  エラーが出るところまでやったこと
android studioでプロジェクトを開くとかやりたく無かった・・・UI慣れてないからあんま見たくないとか言っちゃいけないんだろうけど、ごめんね。
で、最初にプロジェクトとかを新規で作るとか選択できる右下にあるConfiguerを選択。AVD Managerって奴をクリックして、新しく仮想デバイスを作っておく、そうすると、VScodeから作った仮想デバイスを出せるようになる・・・ここまではスンナリできた・・・

## なんかデバッグすると動かない
例の如く、Start Debuggingでデバッグをすると、エラーを吐き倒す。特筆すべきエラーは下記。

```
No resource identifier found for attribute 'appComponentFactory' in package 'android'
```

これをぐぐると結構いっぱい出てくるけど、一撃で倒してくれる記事が無かった。ので、書いといて損はないかなと思いました。

[公式の直し方](https://flutter.dev/docs/development/androidx-migration)

いろいろ書いてあるけど、使うのは最初のとこだけだった。

## 解決策

### Android Studioを使う
まず、Android Studioを起動する。開くのは、Flutterで作ったプロダクトの中にある、androidディレクトリだけで良い。こいつを開いたら、ツールバーのRefactorからMigrate to AndroidXを選択する。

すると、ポップアップで、 compileSdlVersionは少なくとも28がいるぞって英語で出てくるので、これを修正してあげる。

```build.gradle
compileSdkVersion 27
```

を

```build.gradle
compileSdkVersion 28
```

に直してあげる。
それで、もう一度migrateをかけてあげると、androidディレクトリの中にandroid.zipが出来上がる。これすると、　gradle-wrapper.propertiesが更新される。取り敢えず、これでもう一度、デバッグを走らせる。

```
ERROR: The Android Gradle plugin supports only Kotlin Gradle plugin version 1.3.10 and higher
```

ってのが今度は出てくるから、

```build.gradle
 ext.kotlin_version = '1.2.71'
```

を

```build.gradle
ext.kotlin_version = '1.3.10'
```

に直してあげる。そうすると、同ファイルのcom.android.tools.build:gradleの部分のバージョンも自動更新される。この段階で、デバッグをかけると、アプリがエミュレーターで起動できた。随分と手こずってしまった。
wmicでサービスを再起動する

# 発行コマンド

### 自ホストのサービスを起動・停止する

```console
# サービスを起動する
> wmic service SNMP call startservice

# サービスを停止する
> wmic service SNMP call startservice
```

### リモートホストのサービスを起動・停止する

```console
# サービスを起動する
> wmic /NODE:192.168.0.1 /User:Administrator service SNMP call stopservice

# サービスを停止する
> wmic /NODE:192.168.0.1 /User:Administrator service SNMP call startservice
```

今回はSNMPを指定しているが、他のサービスを操作したいときは、

```console
> wmic service list instance
Name
Browser
Dhcp
SNMP
EventLog
...(略
```
と表示してくれるので、操作したいサービス名に書き換えてコマンドを発行する。

# 返り値

返り値として数字が表示される。
start（起動）して`0`が返ってきたら成功、`10`が返ってきたら既に起動しているという意味。
詳しくは[ここ](https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/startservice-method-in-class-win32-service)を参照。

stop（停止）して`0`が返ってきたら成功、すでに停止していると`5`が返ってくる。
詳しくは[ここ](https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/stopservice-method-in-class-win32-service)を参照。

# 参考
[ネタ元](https://www.oreilly.com/library/view/windows-server-cookbook/0596006330/ch07s02.html)
[先人 - 別端末(Windows)のプログラムを標準機能でリモート起動する方法まとめ](https://qiita.com/0829/items/5518256b348521ac358c)
格子点を理解し、等高線で遊ぶ。

こんにちは。
**meshgrid**って混乱しませんか？
今日は**meshgrid**を中心に書いていきます。
そしてそれを利用した**等高線**を書く為のメソッドであるcontourで遊ぼうと思います。

# *meshgrid*とは
**meshgrid**は**格子点**を作るために使われます。

##格子点とは
> 座標平面上にある点で、x座標、y座標とも整数である点を格子点という。

<img width="571" alt="スクリーンショット 2019-12-18 17.11.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255565/581b16d9-b2f0-bb9b-5913-f16a6d6be607.png">
つまり、この画像の点全てのことですね。

さぁ、コードを書きます。

```python
import numpy as np
x = [0, 1, 2, 3]
y = [0, 1, 2, 3]

X, Y = np.meshgrid(x, y)
```

XとYは以下のようになります。
<img width="1637" alt="スクリーンショット 2019-12-18 17.18.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255565/33c31113-d46f-bbfb-31d1-0abed9835a54.png">
何これ〜〜〜〜〜〜〜〜~~?!?!?!?!?!?!?!と思う人も多いかもしれませんが、もう少し頑張ってください。
これが何を表しているのかを整理しましょう。
最初の**座標平面とこの行列がどう関係**しているか見ていきます。
下記の画像を見てください。
<img width="1102" alt="スクリーンショット 2019-12-18 17.26.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255565/86722b2f-01b4-f843-1649-93da0d2272f2.png">

どうですか？
少しはピンと来ましたか？
そう。XとYの行列の位置は平面上の座標と**一致**しているんです！（上下は転置されている）
つまり、行列の左上は座標では左下。
行列の右下に行くにつれて、座標では右上に行くのです。

この一致しているという事実を知っていれば、XとYの大きさは(len(y), len(x))となりますよね。
そしてlen(x) * len(y) = 格子点の数になります。
なぜかって？
まず紙に書いて、ゆっくり考えてみてください。



では大きさの違うx、yを考えてみようと思います。
<img width="1182" alt="スクリーンショット 2019-12-18 17.40.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255565/fdddb612-e182-9ac2-4706-32354b74505f.png">

Xについて考えると、**Xは必ず０か１しか要素**として持ちません。
なぜなら、xという配列の中には0,1しかありませんからね。
そして０から１までを一つの棒と考えれば、y = 0, 100, 200に3本重ねれますよね。
これは、[0, 1]が３行必要ってことです。だからXの行列は3 * 2 = len(y) * len(x)なんですね。

Yも同じですよね。

結構まどろっこしい説明をしましたが、一言で言うと
**行列の大きさは格子点の縦×横に等しいです**
こうみるととても簡単だし、混乱も防げますよね。
それにしても美しい。

#meshgridを利用して等高線を書く。
```python
import numpy as np
import matplotlib.pyplot as plt

# z = 2(x + y)
def f(x, y):
    return 2 * (x + y)

x = [-1, 0, 1, 2, 3]
y = [-1, 0, 1, 2, 3]

X, Y = np.meshgrid(x, y)

fig, ax = plt.subplots()
cont = ax.contour(X, Y, f(X, Y), levels=[0, 2, 4]) # ここだけ説明。
cont.clabel(fmt='%1.1f', fontsize=14)
plt.show()
```

![Figure_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255565/a2ba456c-d7f5-5df3-be11-e0825ee05c04.png)
結果はこうなります。
実際 x = 2, y = -1 であれば、z = 2(2 - 1) = 2 * 1 = 2ですよね。

*contour*だけ説明しますね。
***contour(X, Y, Z=f(X,Y), levels=[0, 2, 4])***
まず*contour*は等高線を求める為のツールです。
等高線とはx,yから導き出されるZの同じ値を結んだものです。
X,Yは格子点で、f(X,Y)でそれぞれの格子点でのZを求めています。
そのZにそって線を結んでいくんですね。それぞれの位置のZを知るために、**格子点**が必要となるわけです。
最後のlevelsは任意ですが、ここに指定されたものが線として表示されます。

#まとめ
今日はmeshgridを中心に書きました。
そしてmeshgridを使う等高線を書く為のツールであるcontourで遊んでみました。
meshgridはいろんな所で使います。
しっかり理解しておくことはマストでしょう。
ありがとうございました。


#参照文献
[格子点とは？](https://www.weblio.jp/content/%E6%A0%BC%E5%AD%90%E7%82%B9)
PythonとJavaの実行速度を比較する

# はじめに

一般にPythonは遅いと言われているが、実際に他言語と比べてどれだけ遅いのかを調べてみた。

# 測定方法

PythonとJavaの2言語間で、円周率を近似するプログラムを走らせる。
それぞれの差から実行速度が何倍異なるかを調べた。

# 結論

JAVAのほうが、Pythonより約60倍速いと思われる。
ただし、円周率の近似の結果値をうまく出力できなかったため、本記事だけではJAVAのほうが速いと主張できない。


# やったこと

### 近似式
ライプニッツの公式から円周率を近似した。

```
π = 4{(1-1/3)+(1/5-1/7)+...(1/[4n+1] - 1/[4n+3] ) }
```


で求まるらしい。

### 実行時間の測定方法
Java、Pythonともに、

(計算の実行終了時刻 - 計算の実行開始時刻)

を用いて実行時間を求めた。

### Pythonのコード

```python

import time

num = 100000000  # 計算の繰り返し回数
pi = 0  # 円周率の近似値


if __name__ == '__main__':
    start = time.time()

pi = 0
for i in range(num):
    pi += (1 / (i * 4 + 1) - 1 / (i * 4 + 3))
print(pi4)    # 3.141592153589902

elapsed_time = time.time() - start
print("elapsed_time:% .2f" % elapsed_time + "[sec]")

```

### Javaのコード

```Java

public class SpeedTest{
   public static void main(String[] args){
       long startTime = System.currentTimeMillis();

       //以下に計測する処理を記述

       int num = 100000000;  // 計算の繰り返し回数
       float pi = 0;  // 円周率の近似値を4で割ったもの
       float pi4 = 0;  // 円周率の近似値

       for(int i = 0;i<num; i++){
         pi += (1 / (i * 4 + 1) - 1 / (i * 4 + 3));
       }
       pi4 = pi * 4;
       //以上、計測する処理内容

       long endTime = System.currentTimeMillis();

       System.out.println(pi4);

       System.out.println("time:" + (endTime - startTime)+"[msec]");
   }

}

```

# 結果

Python、Javaともに1億回の処理をそれぞれ2回行ったところ、

Pythonでは33.88 sec, 31.55 sec
**平均32.72 secが得られた。**

Javaでは528 msec, 568 msec 
**平均548 msecが得られた。**
　　**--> 平均0.548 sec**



**以上のことから、PythonとJavaでは59.71倍の実行速度差が存在する。**



一方で、円周率の近似値の出力では、
Pythonでは3.1415926445762157が得られ、
Javaでは4.0が得られた。

π = 3.1415926535...
であるため、
Pythonでは8桁の精度で求められたのに対して、
Javaでは精度としては1桁も合っていない。

これはfloat型などでは計算結果が勝手に丸まってしまうことに由来するようだ。
Javaで計算が正しく行われたかどうかが明らかでないため、この結果からJAVAのほうが速い！と言い張るのは難しい。


# 環境
Python... Python3.6.8, PyCharm 2019.1.2
Java...   JAVA10.0.2, Eclips Photon Release (4.8.0)


# 参考URL

【Python】処理にかかる時間を計測して表示
https://qiita.com/fantm21/items/3dc7fbf4e935311488bc

【Java入門】処理時間をナノ秒・マイクロ秒で計測する方法
https://www.sejuku.net/blog/44904
【Laravel】PUT、DELETEリクエスト（疑似フォームメソッドについて）

Laravelのhttpメソッドではgetリクエストとpostリクエストしか対応していない。
公式ドキュメント（https://readouble.com/laravel/5.6/ja/routing.html）

PUTやDELETEを使う際には、formで一旦POSTメソッドを指定して、hiddenで_methodプロパティ(隠しメソッド)を投げる。（疑似フォームメソッド）

laravelのBladeではディレクティブが使える

```php

<form action="/foo/bar" method="POST">
    @csrf
    @method("PUT")
</form>
```
要するにこういうこと

```php

<form action="/foo/bar" method="POST">
    <input type="hidden" name="_method" value="PUT">
    <input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>
```

ルートの定義はputでOK

```php
Route::put($uri, $callback);
```
Ruby で DistIP,DistPort,SourceIP,SourcePort を指定して Tcp 通信を行うコード

#きっかけ
通信の検証で5-tupleの影響を受けているのか確認する必要があった

#5-tupleとは
IPヘッダに存在する5つの要素のことで

<dl>
  <dt>1.Source IP</dt>
  <dd>送信元アドレス</dd>
  <dt>2.Destination IP</dt>
  <dd>宛先アドレス</dd>
  <dt>3.Source Port</dt>
  <dd>送信元ポート</dd>
  <dt>4.Destination Port</dt>
  <dd>宛先ポート</dd>
  <dt>5.Protocol</dt>
  <dd>プロトコル</dd>
</dl>

を指す

```ruby:tcp.rb
require 'socket'

distIp     = "111.111.111.111"
distPort   = 80
sourceIp   = "222.222.222.222"
sourcePort = 100

begin
  s = TCPSocket.open(distIp,distPort,sourceIp,sourcePort)
  s.print "GET / HTTP/1.0\r\n\r\n"
  print s.read
ensure
  s.close if s
end
```
#メモ
サーバに送信している部分で下記のヘッダー情報が必要かもしれないと思った

```ruby:tcp.rb
  s.print "GET / HTTP/1.0\r\nUser-Agent: curl/7.19.7\r\nHost: localhost\r\nAccept: */*\r\nConnection: close\r\n\r\n"
```
9章

書いているのは app/models/user.rb 
attr_accessor :remember_token #仮想トークン作った  

 #永続セッションのためにユーザーをデータベースに記憶する
  def remember
    self.remember_token = User.new_token #ランダムなトークンをリメンバートークンにつっこむ
    update_attribute(:remember_digest, User.digest(remember_token)) #DBに保存 今作ったリメンバーをハッシュ化してDBのダイジェストに入れる）
  end

--
  # ランダムなトークンを返す
  def User.new_token
    SecureRandom.urlsafe_base64
  end

  # 渡された文字列のハッシュ値を返す
  def User.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(string, cost: cost)
  end

--

cookies.permanent[:remember_token] = remember_token #20年のクッキー完成
VSCodeにコントリビュートする / VS Code Meetup #1


## ある日ふと思いました

---
## OSSやろう

---
## OSSやろう

- React, TypeScript, Node ...
- どちらかというと、アプリケーション寄りのOSSをやりたい

---

## VSCode

---

## VSCodeはOSS

- https://github.com/microsoft/vscode

---
## けっこうアクティブ(それはそう)

<img width="1011" alt="スクリーンショット 2019-12-15 11.06.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22875/1b4aae21-504c-73d0-33a4-0dbeba8eec34.png">

---
## けっこうアクティブ

ex.react
<img width="1001" alt="スクリーンショット 2019-12-15 11.06.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22875/deb3dc93-b6e9-9028-502d-3b4d332474bb.png">

---
## さっそくPRあげるぞ！

- これあったらいいんじゃね？という機能を思いつきで実装し始める。

---
## しばらくコードを読んで挫折🙃

---
## しばらくコードを読んで挫折🙃

- ソースコードが巨大
- 既存の設計を理解して実装する必要がある
- 時にその設計を修正しつつ新規でコードを追加する必要がある

---
## ドキュメントに立ち返る

- https://github.com/microsoft/vscode/wiki/How-to-Contribute

---
## good first issue

- `good first issue`というラベルがGitHubデフォルトで用意してある
- リポジトリのニューカマーが着手しやすいissueにつけられており、他のOSSでも見かける
- **=>まずはここから着手できそうなissueを探していった**

---
## 実際に取り組んだPR

- [Add builder-method for snippet choice by okmttdhr · Pull Request #84048 · microsoft/vscode](https://github.com/microsoft/vscode/pull/84048)
- [Show JS/TS References Code Lens for Inner Functions by okmttdhr · Pull Request #84689 · microsoft/vscode](https://github.com/microsoft/vscode/pull/84689)

---
## help wanted

- `help wanted`もGitHubデフォルトで用意してあるラベル
- 手がつけられないけど助けてほしい、誰かやってくれない？というissueにつけられている
- **=>ここも漁ってみた**

---
## 実際に取り組んだPR

- [Add expand-all action in search by okmttdhr · Pull Request #85428 · microsoft/vscode](https://github.com/microsoft/vscode/pull/85428)

---
## リリースまで

- 毎月イテレーションプランが決まられていて、リリースが近くなるとTestやVerificationのチェックリストが埋められてゆく
- 無事確認されればリリースノートに名前が乗る
- (僕もどこかに乗っています https://code.visualstudio.com/updates/v1_41)

---
## リリースまで

<img width="710" alt="スクリーンショット 2019-12-15 11.34.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22875/88fe7cea-9653-9c1a-e175-a212d8631526.png">

---
## おまけ

---
## CI

---
## CI

- CIはGitHub ActionsとAzure Pipelines
- GitHub Actionsを本格的に使っているプロジェクトのひとつ
- ユニットテストや結合テストをクロスOSでElectronアプリのテストをしている
- ※Azure Pipelinesはあまり見れていない

---
## テストカバレッジ

---
## テストカバレッジ

全体的には40-50%くらい
<img width="1440" alt="スクリーンショット 2019-12-15 11.29.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22875/bc7f1af2-6e46-ea80-8819-54162b5128cf.png">

---
## テストカバレッジ

テスト自体書かれていないファイルもちらほら。これで大丈夫なの？🤔
<img width="1440" alt="スクリーンショット 2019-12-15 11.30.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22875/f70e9eb1-bf25-c244-7cf3-26e3e9688026.png">

---
## More

- より詳しいことはwikiに結構書いてある
- ビルド、テスト、デバッグ、Coding Guidelinesなど
- 例えば[Source Code Organization](https://github.com/microsoft/vscode/wiki/Source-Code-Organization)では、全体の設計指針などが軽く書いてあったりする
- 思いつきで気になる箇所から読み進めていくのもあり

---
## おわり

ありがとうございましたm m
Osi参照モデルの勉強内容

❼アプリケーション層
ネットワークの可否
リダイレクタ：ネットワーク機能のないファイルなどに、ネットワーク機能を持たせる。例えば、ワードのファイル共有。
DHCP：クライアントはネットに接続した時に、ブロードキャスト送信を行い、サーバーはプールから、期限をつけて、IPアドレスを自動で貸し出す。これにより、自分のIPアドレス（パケットにカプセル化する際に必要）を知ることができる。
Telnet23:標準NVT文字を使う。もっとも基本的な通信プロトコル、文字単位で送信する。
FTP：PIとDTIでセッションとデータそれぞれのルートを確立して、ファイルの送信を行う。ファあウォールがある場合、パッシブオープンによって、回線を開く。
DNS：木構造のDNS名前空間を持ち、TLDから逆に配置される。DNSサーバーは各節に置かれている。DNSリゾルバというソフトウェアに問い合わせ。
HTTP:ページを見に行っているのではなく、ページのファイルをダウンロードしてみている。HTTPのバージョン情報もヘッダに付与されている。
URI:
HTML:構造化されて、リンクすることができる文章

❻プレゼンテーション層
データ変換：機種による文字コードの違いを解消する。例えば、FTPでのファイル転送は、OSに依存せずに行うことができる。
圧縮や暗号化

❺セッション層：セッションの管理＝ポート番号を決定してレイヤ４に渡す。
ダイアログ制御により、データ送受信の順番を決める。チェックポイントを設置し、そこまで戻れるようにする。
コネクションで回線を開き、セッションで会話を成立させる。１コネクション、１ファイルが基本。


❹トランスポート層：データを確実に届ける信頼性＝＋制御データ、セグメント（カプセル化）
TCPがインターネットを世界に広げた。acknowlege=確認応答
MSSに分割されたセグメント（シーケンス番号を付加）を、End to end のアプリケーション間のネットワークをポート番号を窓口にして、バッファの量をウインドウで確認しあい、フロー制御をしながら、コネクションを通る形で行う。コネクションの確立には３ウエイハンドシェイクによって行う。回線の終了もお互いに終了の要求を送ることで解消される。スロースタート方式の輻輳制御によって、パケットの破棄を、スライドウインドウでフローを抑制する。
ソケットライブラリからウエルノウンポート番号か、１０２４番以上のポート番号をつけて送る。
UDP：TCPの弱点スループットの低下を改善した、ポート番号の付加以外何もしないプロトコル。
コネクションの確立も必要ない。ブロードキャストが必要な場合に使う。ストリーミングとかDNSとか。
Netstatによって、接続している状態の確認が可能。
Naptによって、少ないネットワークアドレス問題を解決し、同時にセキュリティの強化も行う。ただし、記憶していないIPアドレスは破棄してしまうので、アクセスさせたいポートは静的に記憶させる。ポート番号を指定してくるサーバーなどにも個別で対応する必要がある。

❸ネットワーク層：WANルート、経路の決定（ルーティング）、パケット（宛先、送信元）
論理アドレス：場所を示すアドレス
ルーター：ルーティングテーブルに沿って、パケットの通る経路を決める。ネットワークはルーターで接続されてないと情報が通れない。ポートには各接続先のIPアドレスが割り振られている。ブロードキャストドメインを区別する。
IPアドレス：IPv4は３２ビット、ホスト番号とネットワーク番号でできている。ネットワーク管理者がつける。
管理者：ICANN→NIC→JPNIC、ネットワークアドレスを割り振る
クラスフルアドレシング：ネットワーク規模の大きさによって、クラス分けし、ネットワークアドレスの範囲を決定する方法。ホストアドレスの０はネットワークアドレス、１はブロードキャストアドレスなので、使わない。
プライベートIPアドレス：インターネットに流れないIPアドレス、
サブネット：小規模のネットワーク、アドレスの区切りはサブネットマスクで表す。
ARP：address resolution protcoll 、自分のARPテーブルで対象のIPアドレスと対応するMacアドレスを見つける。対応がない場合は、ARPパケットでrequestをブロードキャスト送信で送る。
DNS：ドメインはJPNICとホスト名はネットワーク管理者が決定。これでIPアドレスがわかる。
デフォルトゲートウェイ：ルータはarpのブロードキャストを通さないから、ルータにデフォルトゲートを設定して、そこにarpを送って、宛先のMACアドレスを取得する。
ルーティング：PC内を一つのネットワークと考え、NICから各ポートに送信する。静的ルートは手動で決定され、迂回路が使えない欠点を持つ。デフォルトルート0.0.0.0は宛先のあるルート以外のものは全てそこに送る。動的ルーティングでは、隣接するルーターが障害を検知し、他のルーターに知らせることで、自動的に迂回路を設定する。
ルーティングプロトコル：近接ルータと情報交換をし、最適ルート（メトリックの小さいもの）を記憶する
RIP(ルータ数)：ディスタンスとベクタのあるルートテーブルを交換し、コンバージェンスする。アップデートにより、ルートループが発生するので、スプリットホライズンかホールドダウンタイマーで対策する。
EGP：AS間のルーティングプロトコル、IGP：AS内部のルーティングプロトコル
ICMP：エラーメッセージの送信。到達不能や最適ルート情報を送信する。pingにより通信可否を測定することで、レイヤ毎にエラーを発見する。

❷データリンク層：LAN伝送制御の付加：フレーム
レイヤ１にもまたがる
LAN規格
LLC（エラー制御（ビットチェック）、上位サービス指定）IEEE802.2
MAC（メディアへの接続の取り決め）IEEE802.5 IEEE802.3 FDDI
（イーサネット：プリアンブル、宛先MAC、送信元MAC、フレームタイプ、パケット、FCS：ブロードキャスト型（全員に配信）：CSMA/CD）
ブリッジ：ネットワーキングデバイス、トランスペアレントブリッジ、宛先によりデータの行き先を変える
スイッチ：マルチポートブリッジ、宛先にしかデータを送らない。バッファメモリを持つ
アドレッシング（デバイスへのユニークアドレスの付加）
物理アドレス：直接接続のアドレス（MACアドレス：４８ビット→１６進数８桁、ベンダーアドレス・製造番号）

❶物理層：機械・電気：ビット
ネットワーキングメディア＝ケーブル(IEEE,UL,EIA/TIA)
メットワーキングデバイス＝NIC（LANを挿すカード）
リピーター、ハブ、トポロジー
Go Lang Hello world 超簡単言語(GOlang)

# ちっとお試しあれ
### <<みんなでGO>>
```main.go
package main
import (
        "net/http"
        "fmt"
)
func world(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "<a href='/japan'><h1>Hello World</h1></a>")
}
func japan(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "<a href='/'><h1>Hello Japan</h1></a>")
}
func main() {
        http.HandleFunc("/", world)
        http.HandleFunc("/japan", japan)
        http.ListenAndServe("192.168.1.10:8080", nil)
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274715/e8bc1f49-bc70-cf50-e50c-3660b0af084d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274715/34f53434-437f-2a16-1e4f-8608b048ef8f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274715/6dc04ac9-5de8-6e8d-0cec-0ec7f4922e41.png)
AWS container re:capのまとめ

ただの備忘録

ECS → EC2 → fargate(仮想マシンの管理) →EKS（kubernetesの管理）→ECR
WEB上の８割のコンテナはAWSで動いている。

Firelens
コンテナログを容易に取り扱う為の新しい機能。
Fluentb？
ログはfirehouseに飛んでいく。

ECS capacity provides
コンテナ上の仮想マシンのキャパシティを管理する。
オンデマンドとスポットにキャパを分散。

ECS cluster EC2 auto scaling

キャパシティありきから、必要なキャパシティをECSが判断する。
ECSキャパシティプロバイダーがスケーリングを直接制御している。
アプリの動きに合わせてキャパシティを変更してくれるので、
今までのキャパシティありきの開発と逆の発想。

コントロールプレーン
コンフリクト　対立
フルマネージド　サーバー運用の全てを代行する。
アップフロント　先払い

Fagate→コンテナ実行のツール
ポッド
Homebrewのruby-buildの更新を待たずにrbenvで最新版のRubyをインストールする方法

## はじめに
Homebrewでrbenvとruby-buildの組み合わせでRubyをインストールしている場合は、以下のコマンドで最新版のインストールパッケージを取得することができる。

```
brew upgrade rbenv ruby-build
```

ただし、最新のruby-buildがHomebrewに反映されるまでには数日かかることがあるため（※）、最新バージョンのRubyがリリースされてもすぐにインストールできないことがある。

※ 参考情報
ruby-buildの更新に時間がかかるのは、HomebrewへのPull request（以下PR）の作成とマージが必要になるから。
→ 例：[ruby-build 20191205のPR](https://github.com/Homebrew/homebrew-core/pull/47516)

Homebrewの更新を待たずにすぐにインストールしたい場合は、以下の手順で自力で最新版のインストールパッケージをセットアップすることができる。（2019.12.26追記：@sakuroさんのコメントを参考にして以下の手順を全面的に修正）

## 手順1. ruby-buildのPull requestを確認する

ruby-buildのcloseされたPRを確認し、目的のバージョンがすでに取り込まれていることを確認する。

https://github.com/rbenv/ruby-build/pulls?q=is%3Apr+is%3Aclosed

ここでは下記のPR（2.7.0-rc1を対象にしたもの）を例に取り上げる。

https://github.com/rbenv/ruby-build/pull/1389

## 手順2. ruby-buildのリポジトリをclone または git pullする

まず、[ruby-buildのリポジトリ](https://github.com/rbenv/ruby-build)をローカルにクローンする。

```console
git clone git@github.com:rbenv/ruby-build.git
cd ruby-build
```

すでにcloneしている場合はgit pullしてファイルを更新する。

```console 
cd ruby-build
git pull
```

## 手順3. RUBY_BUILD_DEFINITIONSを指定してインストールする

ruby-buildのリポジトリには`share/ruby-build`というリポジトリがある。
このリポジトリを参照するように`RUBY_BUILD_DEFINITIONS`オプションを指定し、`rbenv install  --list-all`でインストール可能なバージョンが増えていることを確認する。

```console
$ RUBY_BUILD_DEFINITIONS=share/ruby-build rbenv install --list-all | grep 2.7.0
2.7.0-dev
2.7.0-preview1
2.7.0-preview2
2.7.0-preview3
2.7.0-rc1       <= 新しく増えた
jruby-9.2.7.0
```

目的のバージョンが追加されていることを確認したら、インストールを実行する。

```console
RUBY_BUILD_DEFINITIONS=share/ruby-build rbenv install 2.7.0-rc1
```

## まとめ

手順は以上です。もっといいやり方をご存じの方がいたらコメントをお願いします！

**2020.10.10 追記**
@oshow さんの[こちらのコメント](https://qiita.com/jnchito/items/16dfcffa0b983c1ce2c8#comment-4419d85bf30f86764cc3)も有効です！詳しくはコメント欄をご覧ください。
私の社内公開用中継の歴史

#はじめに
この記事は様々な葛藤により生まれた記事であることを許してほしい。
私は、あまりコードに触れない系の社内インフラ担当だ、
たまに書くのはPCの設定をコマンドラインにしてPowershellで実行するくらいなので面白くない
何を書いたらいいか考えた末、同じ立場の人の役に立つものが書けたらと思い書いてみた
私の社内公開用動画中継の歴史、リンクはアフィリエイトじゃないよ！

#中継を頼まれた
前職は全国に10拠点ほどある会社で、朝礼を週1で実施していた。
少し前までは、各拠点でそれぞれやっていたのだが、社長のありがたいお話をリアルタイムで共有したいという要望で中継を行うことになった。
そこから私の中継の歴史が始まった。

#ノートパソコン1台だけで
最近はノートパソコンにカメラもマイクもついている。
skypeだったり、googleハングアウトだったりでビデオ通話をするだけで中継ができる。
高評価だった。

#敵は味方の中にいる（USB接続カメラを追加）
中継に参加するメンバーはマイクをOnにしてやってくる。
中継に関係のないしゃべり声が入ってしまう。
しかし、そのメンバーはミュートの仕方を知らない。
マイクがOnの人はわかる人がミュートにしてあげる必要がある。
ノートパソコンを操作しようとすると、付属のインカメラに映り込んでしまうので、USBカメラを購入
こんなの ウェブカメラ https://www.amazon.co.jp/dp/B005LFFE7I
三脚用の穴が開いているのがいいです。
三脚があると、映像が安定します。

#まるで犬のよう（USB延長ケーブルを追加）
社長が話すだけなら別によかったんです。
周りの人も話に参加させようとするから、その人をカメラで追わないといけなくなる。
USB接続カメラについてくるケーブルの長さは長くても1メートルちょっと
ズームも聞かないので物理的に接近する必要がある。
まるで小屋に鎖でつながれた犬の用にPCの周りから動けない。
なので、延長ケーブルを接続して動ける範囲を拡大する。
こんなの USB延長ケーブル https://www.amazon.co.jp/dp/B00NH136GE/
USBケーブルの最大延長は5mと言われているので、つなげすぎに注意

#今日は地方拠点から（マイクスピーカーを追加）
社長は出張する。
その日は地方拠点からの中継だ。
いつもは本社で約200名に向けて集会用のマイクセットを利用してしゃべっている。
地方拠点は10名程度なのでノートパソコンのスピーカーで十分聞こえるが本社はそれでは聞こえない。
正直それでも小さかったが聞こえないことはなかった
こんなの マイクスピーカー https://www.amazon.co.jp/dp/B07871XGT7/
尚、地方拠点にも同じ機械を置くことで中継にのる音声の品質が向上した。
マイクの重要性を認識。

#人がゴミのようだ（ビデオカメラ、キャプチャーボードを追加）
ここから現職での話になるが、エムスリーキャリアでは半年に1度全社総会として社員全員を大きなホールに集めて半期の振り返りや行動指針の確認を行っている。
500人を超える人数が一同に会する場所での中継となる。（基本は全員参加だが、留守番担当者や、在宅勤務者向けに）
会場が広くなり、参加する社員の邪魔にならないところで中継を行わなければならないため、如何せん遠い。
普通のWEBカメラでは豆粒ほどにしか映らない。ズーム機能が必要となった。
ビデオカメラの映像が入力できればいいんじゃね？という単純な考えの元、ビデオカメラをUSBで接続してみた。
ただビデオカメラのストレージが見えただけだった。
どうやらキャプチャーボードなるものが必要らしい。
キャプチャーカードを利用してビデオカメラの映像を中継することができた。
気分はYoutuber！
ビデオカメラ （HDMI出力できるもの）こんなの https://www.amazon.co.jp/dp/B07WPDVJKK/
キャプチャーボード こんなの https://www.amazon.co.jp/dp/B07WLN5QNF/
音声は雑音が入ってしまうので、会場の音声出力ラインをカメラに接続することに。
2020年2月18日追記
　ビデオカメラのHDMI出力設定によっては、キャプチャーボードの解像度を誤って認識することがあるようです。
　PC側で認識される画像が気持ちワイド表示されてしまうようです。
　手動でHDMIの出力解像度を指定することで画面比が維持できます。


#見たいのはそっちじゃない（OBSStudioの導入）
しゃべっている人をメインで映していると、見たいのは映している資料だ！という声が多数。
テレビ見たいにワイプ出せばよくね？という考えの元、OBSStudioにたどり着く
OBSStudio https://obsproject.com/ja
カメラとキャプチャーボードのセットを追加して、会場スクリーンに投影された資料をとるカメラと、話している人をとるカメラを準備した。
OBSStudioで画面を構成して、外部モニターを接続して表示、外部モニターに表示されている内容を中継用ソフトで画面共有することで、テレビっぽい中継体制が整った。
協議の結果スクリーンに表示された資料がメインで話している人がワイプになったが、個人的には逆のが面白いと思うんだけどなぁと思っている今日この頃
OBSStudioは字幕も付けられるし、いろいろやれて面白い、使い方に関しては詳しくは書けません！
pptファイルをそのまま公開できればいいんだけど、まだうまく動かないみたい。

#おわりに
コードとか関係のない駄文を読んでいただきありがとうございます。
〇〇君パソコンの大先生なんでしょ？ちょっと社長のありがたい言葉を全拠点に中継してみてよって言われた人の力になれることを祈っています。
slim ちょっと試したいときには slimrb を使う

# 問題（やりたいこと）

slim のレビューをしていて、こんな書き方ができたような…ということを言いたいが自信がない。
とりあえず一行だけ slim を書いて、その書き方が合っているか確かめるにはどうするか。

# 解決策

ターミナルで下記のコマンドを実行する。これで標準入力の待ち状態に入るので適当な slim を書き込み Control+d を2回押す。（なぜ2回なのかはわからない）

```terminal
bundle exec slimrb
```

# 例

たとえば

```terminal
bundle exec slimrb
div hoge
```

のあと Control+d を2回押すと

```
<div>hoge</div>
```

が出力されて、正しい slim だったということがわかる。
Kubernetes 1.17: SIG-Auth の変更内容

## はじめに

このページではKubernetes v1.17におけるSIG-Authに関連する取り組みをまとめています。
必ずしもすべての `sig/auth` ラベルがついた変更についてまとめているわけではありません。ここに記載されていないものは別のまとめで記載されていると思いますので、 Kubernetes 1.17: 変更点まとめ(後日公開) も合わせて参照してみてください。

:pencil: がついた文章は、CHANGELOGの公式内容ではなく筆者の補足です。


## その他の注目機能 (Other notable changes)

- **DockerのcredsStore `desktop`を利用して出力されたクレデンシャルがSecretから読み込む際に正しくデコードできない問題を修正 ([#82148](https://github.com/kubernetes/kubernetes/pull/82148), [@bbourbie](https://github.com/bbourbie))**

:pencil: docker-credential-desktop によってファイルに出力されたクレデンシャル情報はパディング無しのBase64エンコードされたデータのため、デコード時にエラーになっていたようです。修正後ははパディング有り・無しどちらでも対応できるようになったようです。

- **kubelet と aggregated API servers で認証・認可に v1 TokenReview と SubjectAccessReview endpointを使うようになりました ([#84768](https://github.com/kubernetes/kubernetes/pull/84768), [@liggitt](https://github.com/liggitt))**

:pencil: 修正前は v1beta1 を使っていたようです。

- **kube-apiserver で authentication/authorization webhookとの通信で v1 TokenReview and SubjectAccessReview APIが利用できるようになりました ([#84768](https://github.com/kubernetes/kubernetes/pull/84768), [@liggitt](https://github.com/liggitt))**

:pencil: `--authentication-token-webhook-version=v1` または `--authorization-webhook-version=v1` を指定することにより利用できるようです

- **たくさんのノードやNamespaceでのSAアカウントのために認証トークンのキャッシュサイズが 4k から 32k に増えました ([#83643](https://github.com/kubernetes/kubernetes/pull/83643), [@lavalamp](https://github.com/lavalamp))**

:pencil: 認証ロジックのパフォーマンスチューニングの一環でアクティブなトークンの数がキャッシュのサイズを超えないように対応されたようです。
トークンの数がキャッシュのサイズを超えるとパフォーマンスが著しく低下するとのこと。
キャッシュのサイズとしては 5k nodes and 10k namespaces のスケールで十分なサイズのようです。

- **拡張APIサーバでdelegated authenticationを利用している場合に認証情報が動的にリロードされるようになりました ([#85004](https://github.com/kubernetes/kubernetes/pull/85004), [@deads2k](https://github.com/deads2k))**

:pencil: 参考: https://kubernetes.io/docs/tasks/access-kubernetes-api/

- **Configmaps/extension-apiserver-authentication は kube-apiserver によって定期的に更新するように修正されたました ([#82705](https://github.com/kubernetes/kubernetes/pull/82705), [@deads2k](https://github.com/deads2k))**

:pencil: ClusterAuthenticationTrustController というものが追加されて認証情報をメンテナンスするようです。
これまで複数のkube-apiserverが起動している場合にConfigMapに保管される認証情報は一番最後に起動したkube-apiserverのものが上書きされていましたが、これによりkube-apiserevr単位で異なる認証情報を持っていいた場合には、いずれかのkube-apiserverしか信頼できない状況になってしまいます。修正後はそれぞれのkube-apiserverの情報がConfigMapに保管するようになりました。
ngrokでslackとwebをhookする

# はじめに

[いなたつアドカレ](https://qiita.com/advent-calendar/2019/allinatatsu)の十八日目の記事です。

slackやlineなどで遊ぶときにwebhookを使う際にいちいちVPSやらherokuにいちいち開発中にデプロイするのは面倒ですよね。。。

ngrokを使って、開発を楽にする方法です。


# ngrokのインスコ

`$ brew cask install ngrok`

brewでいれちゃいましょう。言うことないですね。



# slackの設定

![スクリーンショット 2019-12-18 17.16.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269859/61f37fcd-13e8-2aa7-9b3c-70c18b21edcc.png)

このSlash CommandsをSlackに追加します。
Slash Commandsの設定画面に

- コマンド
- URL
- メソッド
- トークン
- 名前をカスタマイズ

などなど設定項目があるかと思います。

今回最低限必要となるのは、上の2つのコマンドとURLになります。

コマンドに`\hoge`と入力すると、その投稿をコマンドとしてSlackが認識してくれます。
そして、その受け取りをwebでhookして(謎)URLで指定している箇所にぶっとばしてくれます。
では、指定するためのURLを生やしましょう

# ngrokを起動する

`$ ngrok http 3000`
これで、localhost:3000をIPとして公開することができます


connectingとなっているのがonlineに変わると公開できているということになります。

![スクリーンショット 2019-12-18 17.25.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269859/8ab4a8b6-7f90-3d0b-f675-7d5f5edda963.png)

`Web Interface http://127.0.0.1:4040`
とかいてあります、4040ポートでngrokを監視するページが展開されています

localhost:4040にアクセスするとこんな感じです。
![スクリーンショット 2019-12-18 17.27.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269859/e2570c43-7511-8624-db01-0c8b124d22d0.png)

```
Forwarding http://ae2d3823.ngrok.io -> http://localhost:3000
Forwarding https://ae2d3823.ngrok.io -> http://localhost:3000
```

とあり、このアドレスに自分のlocalhost:3000がフォワーディングされていることをしめしています。

この`https://ae2d3823.ngrok.io`をSlashCommandsのURLの蘭に入力することで、無事に`/hoge`をつけた投稿が`https://ae2d3823.ngrok.io`つまり`localhost:3000`に転送されるということです。

これを活用することで、簡易的にwebhookを用いたbot開発が行えます。

# おわりに

最終的なデプロイはちゃんとしたところにしようね
僕のpyproj(Python)

自分用のまとめ
随時更新
自分が使った、調べたコマンドを記載
**自分がわかればいいからところどころ用語が間違ってるかも**

！見方

```python
#コマンド
    #引数のオプションの説明
```




###モジュール読み込み

```python
import pyproj as pyp
```



##頻出操作
```python
#測地系さんインスタンス作成
geo = pyproj.Geod()
    ellps= #採用する楕円体
```
【ものすごいざっくり解説】要件定義とは何か？


要件定義と聞いて、あなたは何と答えられるでしょうか？
**「プログラム自体のおおまかな仕様を書いたもの？」**
と言った感じに回答してしまったかもしれませんね。

さて、ここではプログラミング学習の中で、聞くことが多いけれどもイマイチ意味が解らない…そんな言葉、要件定義についてより深く解説していきたいと思います。


#より詳しい「要件定義」の意味

**クライアントの要望が何か述べられ、そして、その要望を満たすためにはどうすればよいかを記述したもの。**

より専門用語に落とし込むと、

- To-Beモデル（「あるべき姿」「理想像」のこと）を構築したもの
- AsIs（現状のこと）から、To-Beモデルへの橋渡しになっている内容

大まかにこの2つの要件を満たすものが、要件定義です。


#要件定義は誰にもわかりやすい文章で書かれる

また要件定義を見るのは、プログラマーに限りません。
つまり、納品先の人に理解してもらう必要性があるうえ、その納品先はプログラミングとかかわりあいが深いとは限らないからです。
なので、簡易で解りやすい文言で書かれることとなります。

要件定義を見る人は、

- クライアント（取引先の社長や、発注担当者など、プログラミングとは遠くなりがちな方々）
- ユーザー（実際に使う人）
- 開発者

と、利害関係者に対して幅広く関係してくることも念頭に入れると良いでしょう。


#要件定義は複数の段階を経て、最後に要件定義書になる

用件定義を行わないと、何を作ればよいかわからないし、何を作るのか解らないから取引先と合意が取れない。
なので、最終的に目に見える形で「要件定義書」に落とし込む作業を行う。

その為には例えば以下のような道筋をたどって制作される。

- 何を求められているのか知る為に、ヒアリングを行う
- ヒアリングを元に、制作物の理想的なモデル（To-Be）を作成する
- 理想のモデル（To-Be）と、現状（AsIs）を参考にして、理想のモデルを、現実可能な形(Can-Be) に変えていく。
- 現状（AsIs）から、現実可能な理想モデル（Can-Be）への道筋を示す

と言った具合だ。
短く纏めるのなら、**理想と現実を観察して、実現可能な範囲で理想なモデルを提示することが、要件定義で行われると言えよう。**


参考文献：だまし絵を描かないための要件定義のセオリー　著者：赤俊哉
okwave「パソコンの性能はＣＰＵだけで決まるのですか」への解答例

パソコンの性能はＣＰＵだけで決まるのですか

https://okwave.jp/qa/q9689585.html

への解答例

>計算量が少なければ、CPUが一番重要です。
計算量が多い場合は、CPUより主記憶装置（メモリ）の容量の方が重要な場合があります。
CPU, メモリに入りきらない計算の場合には、補助記憶装置（HDDなど）の速度が重要になってきます。
計算の種類によっては、GPUの性能が重要になってくるものもあります。
ネット上にあるプログラム・データとのやりとりが多ければ、通信のICの性能が重要になります。
具体的に、なにをしたいかで、なにを重視しないといけないかが決まります。

CPU
・クロック
・レジスタの幅
・レジスタの数
・コアの種類
・コアの数

メモリ
・クロック
・容量

補助記憶
・速度
・容量

GPU
・クロック

ネット
・速度
新規機能実装時のQAリスクを減らすために

#▼はじめに
運用中のアプリであれば誰しもが直面したことのある「施策のスケジュール遅延」。
品質を担保したいQAにとって、非常に頭の痛い問題だと思います。
今回はこの問題の中から、**「新規機能実装時のスケジュール遅延」**にスポットをあてさせていただき、
実際に私が取り組んでいる対策について書かせていただければと思います。
あくまでも一案とはなりますが、少しでもQA業務を行われている皆さまのご参考になれば幸いです。


#▼新規実装時に発生しやすい問題
新規機能実装時に起こりやすい事象として以下のようなものがあげられると思います。

* 一部機能未実装でのQA開始
* QA期間中の仕様変更

オンスケで進められているプロダクトのほうが少ないのではないかというくらい、
これらはほぼ日常的に見られる光景ではないでしょうか。
この状態でQAを開始しても、序盤で確認した機能の見直しなどが発生し、
結果として、残業等によりテスター、プロダクト双方の負荷が大きくなり、品質低下や費用増につながってしまいます。

先にお伝えしたように、これらは事前の取り組みによってある程度軽減が可能であると思っています。

#▼QAの負荷を軽減する対策案
この問題の回避対策として、プロダクト側と相談した結果、以下のような取り組みを実現させました。
それは、
**「QA開始前に、実装者、設計者、QAを交えての実機確認会を実施する」**ことです。
これを1時間。そう、たった1時間やるだけでQAの負荷が軽減されるのです。

ここで大事なのは**「実機での確認」**というところです。
エディタ上での確認は行っていても、
実機での確認をされているプロダクトの方は少ないのではないでしょうか。
UI不具合や、遷移やローティング時間などの体感値、
実機でしか気づけないような問題が短時間であっさり出てきたりします。

「こんなことしている時間がもったいない」
「そもそもテスターの仕事でしょ」
と思うかもしれませんが、
やはり実際に**"自分たちで作ったものを実機で動かしてみる"**ことも大切だと思います。

実際にこの取り組み自体はプロダクト側も有用だと感じていて、
新規機能実装時にはQA開始前に必ずこのフローを入れていただいています。

ちなみに、こちらがとある新規機能で実施した実機確認の結果になります。

|実施時間|参加人数|不具合/改善要望件数|
|:-----:|:------:|:---------------:|
|1h × 2回|18人|約80件(不具合2割、改善要望8割)|

ボリュームの大きい機能だったため、
開発に関わったメンバー以外にも有志で参加してくれた方が多数いました。
そのため、1時間で見つかった不具合や改善案の件数も多かったです。

もし、これだけの不具合を残した状態でQAを実施していたら、
修正可否の判断や対応にかなりの工数を取られますし、
テスター側も不具合の影響で度々手を止める形になってしまい、
肝心の機能確認がなかなか行えない状態に陥ってしまいます。

なお、この後に開始したQAで検知した不具合は**「38件」**となり、
過去同規模の新規実装時平均の**「60件」**と比べて少なく、QA開始時点での品質状況が改善されたと思われます。
不具合をある程度未然に防げたというのもあり、テストも順調に進行することができました。

#▼まとめ
これは、あくまでも対策の一つでありますが、
実装する機能のボリュームが大きければ大きいほど効果は発揮しやすいです。
ただ、この取り組み自体は当然ながらQAだけでは成立しないものなので、
事前にプロダクト側と相談した上で協力を仰ぐ必要はあるかと思います。

プロダクト側との信頼関係がないとなかなか難しいかもしれませんが、
プロダクトにとってもQAにとってもメリットのある取り組みだと思うので、ご紹介させていただきました。

拙い文章ではありましたが、最後までご覧いただきありがとうございました。
C#でXMLをシリアライズ出力するためのハックいろいろ

指定された形式でXMLを出力しようとした時に毎回検索してはあっちこっちから情報拾ってる気がするのでまとめていく。
ちまちま増やしていくつもりです。

・環境
・C#7.0～8.0
・.Net Framework 4.7
・.Net Core 3.1

## `Nullable<T>=null`の項目のタグを出力しない
こんな場合。

```csharp:モデル
    [XmlRoot]
    public class Library
    {
        [XmlElement]
        public User[] Users { get; set; }
    }

    public class User
    {
        [XmlElement]
        public int? Age { get; set; }

        [XmlElement]
        public string Name { get; set; }
    }
```
```xml:出力
<?xml version="1.0" encoding="utf-8"?>
<Library xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Users>
    <Age xsi:nil="true" /> <!--これを出力したくない-->
    <Name>user1</Name>
  </Users>
</Library>
```

bool型で制御したいプロパティ名+Specifiedのプロパティを定義することでタグの出力/非出力を制御できるのでそれを利用します。

```csharp:コード
    [XmlRoot]
    public class Library
    {
        [XmlElement]
        public User[] Users { get; set; }
    }

    public class User
    {
        [XmlElement]
        public int? Age { get; set; }

        // Age == null の場合falseが返ってタグが出力されなくなる
        // 完全にシリアライズ制御用のプロパティなのでBrowsable=falseにしてインテリセンスで表示されないようにもしています
        [XmlIgnore, Browsable(false)]
        public bool AgeSpecified => Age.HasValue;

        [XmlElement]
        public string Name { get; set; }
    }
```

```xml:出力
<?xml version="1.0" encoding="utf-8"?>
<Library xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Users>
    <Name>user1</Name>
  </Users>
</Library>
```

## 構造体のシリアライズ
変換処理を書くだけといえばそれだけ

```csharp
    [XmlRoot]
    public class Library
    {
        [XmlIgnore]
        public Color SomeColor { get; set; }

        [XmlElement("FontColor"), Browsable(false)]
        public string SomeColorValue
        {
            get { return $"#{SomeColor.A}{SomeColor.R}{SomeColor.G}{SomeColor.B}"; }
            set { SomeColor = ColorTranslator.FromHtml(value); }
        }
    }
```

```xml:出力
<?xml version="1.0" encoding="utf-8"?>
<Library xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <FontColor>#12345678</FontColor>
</Library>
```
DateTimeのフォーマットなんかもこれでやらざるをえない気がする。
## xmlnsを外す
ちょっと古いアプリとの連携とかで要求されがちな気がする。
xmlをプレーンテキストとして処理する場合とかにも

```csharp:コード
    class Program
    {
        static void Main(string[] args)
        {
            var app = new Library() { Names = new string[] { } }

            using (var writer = new StreamWriter("application.xml"))
            {
                // 空白のnamespaceを用意する
                var ns = new XmlSerializerNamespaces();
                ns.Add(string.Empty, string.Empty);

                var serializer = new XmlSerializer(typeof(Library));
                serializer.Serialize(writer, app, ns); // 空白のnamespaceを使ってシリアライズ
            }
        }
    }

    [XmlRoot]
    public class Library
    {
        public string[] Names { get; set; }
    }
```
```xml:出力
<?xml version="1.0" encoding="utf-8"?>
<Library>
  <Names />
</Library>
```

### 後書き
なんかもっといい方法あったら教えてほしいなって。
Powershellで簡単にTransact-SQLを実行する術

この記事はPowerShellアドベントカレンダー2019に参加しています。


## はじめに

Azure SQLDatabaseの処理自動化の過程でPowershellからSQLを実行する必要があったので実行しやすい形にまとめました。よかったら使ってください。

隙間が空いていたので遅ればせながらPowershellのAdventCalender2019の9日目に参加してみました！


参考文献は以下です。
[MS:Invoke-Sqlcmd コマンドレット](https://docs.microsoft.com/ja-jp/sql/database-engine/invoke-sqlcmd-cmdlet?view=sql-server-2014&viewFallbackFrom=azuresqldb-current)
[MS:PowerShell を使用したエラスティック ジョブ エージェントの作成](https://docs.microsoft.com/ja-jp/azure/sql-database/elastic-jobs-powershell)

## 1.必要なモジュール

Transact-SQLを実行する上でメインで使うコマンドは「Invoke-Sqlcmd」ですが、利用するには「SqlServer」モジュールが必要になりますので、先にインストールしておいてください。

## 2.実行形式

Invoke-Sqlcmdコマンドは実行時にサーバ名等の接続情報をオプションとして指定する必要があるので、先に接続情報を連想配列にして格納します。インデックス名はInvoke-Sqlcmdコマンドのオプション名と一致させる必要がありますので、オプションを追加したい場合はご注意ください。　また、パスワードは暗号化せず平文のまま格納する必要があります。
ServerInstanceにはDBサーバ名を指定する必要がありますが、ここではAzureDBへの接続のためのサーバ名指定をいれています。

```Transact-SQL.ps1
#DB接続情報の設定
$Params = @{
    'Database' = 'master'
    'ServerInstance' = $serverName + '.database.windows.net'
    'Username' = $LoginUser
    'Password' = $plainPassword
    'Query' = ""
}
```
Queryには実際に実行したいSQLを投入します。

```Transact-SQL.ps1
$Params.Query = "ALTER DATABASE $databaseName MODIFY NAME = $changedDbName"
```
で実行です。

```Transact-SQL.ps1
invoke-sqlCmd @Params
```

## おわりに

実行するSQLを配列に入れてしまって連続実行も可能ですし、接続句を一つにまとめられるのでキレイに書ける！よかった。
私はAzureSQLServerのDBリストアを自動化する過程でDB名を変更する必要があり利用しました。
＠配列の使い方をこれで初めて学びました。。。