OmniAICreator/Qiita-1.07M huggingface dataset:
多段プロキシ構成のSquid

# 前置き
Squidを使って多段プロキシ環境を構築したので。Configの作り方をすごくざっくりメモ。

# Network構成

まず、イントラネット(ローカルNW)には、インターネットに出るためのプロキシがあります。
イントラネットの中にはさらにローカルNWのラボ環境があり、今回はこのラボ環境にSquidを新設してイントラネットの親プロキシと連携し、ネットワークA、Bからインターネットに出られるようにしましょう、という計画です。（ながい）

~~~
インターネット
└── イントラネット
    ├── 親プロキシ  (172.10.10.10:8080)
    └── ラボ環境
        ├── Squidサーバー
        ├── ネットワークA  (10.x.x.x)
        └── ネットワークB  (192.168.x.x)
~~~

# できたConfig
不要な設定がある可能性があるので、自身の環境に構築する場合は十分確認してください。
わかりづらくなりまずが、長いのでコメントアウトされた説明行は消しました。
各パラメータについてはSquidの公式から[リファレンス](http://www.squid-cache.org/Doc/config/)が参照できます。

~~~squid.conf

acl localnet src 10.x.x.x/8	# ネットワークA
acl localnet src 192.168.x.x/16	# ネットワークB
acl localnet src fc00::/7       # RFC 4193 local private network range
acl localnet src fe80::/10      # RFC 4291 link-local (directly plugged) machines

acl SSL_ports port 443
acl Safe_ports port 80		# http
acl Safe_ports port 21		# ftp
acl Safe_ports port 443		# https
acl Safe_ports port 70		# gopher
acl Safe_ports port 210		# wais
acl Safe_ports port 1025-65535	# unregistered ports
acl Safe_ports port 280		# http-mgmt
acl Safe_ports port 488		# gss-http
acl Safe_ports port 591		# filemaker
acl Safe_ports port 777		# multiling http
acl CONNECT method CONNECT

http_access deny !Safe_ports

acl SSL_ports port 443
acl SSL method CONNECT
acl CONNECT method CONNECT
http_access deny CONNECT !SSL_ports

http_access allow localhost manager
http_access deny manager

http_access allow localnet
http_access allow localhost

http_access deny all

http_port 3128

coredump_dir /var/cache/squid

refresh_pattern ^ftp:		1440	20%	10080
refresh_pattern ^gopher:	1440	0%	1440
refresh_pattern -i (/cgi-bin/|\?) 0	0%	0
refresh_pattern .		0	20%	4320

dns_nameservers <イントラネットにあるDNSを設定した>

never_direct allow all
cache_peer 172.10.10.10 parent 8080 7 no-query

visible_hostname squidForward

pid_filename /var/run/${service_name}.pid
logformat squid %tl %6tr %>a %Ss/%03>Hs %<st %rm %ru %un %Sh/%<A %mt

query_icmp on

~~~

これでネットワークA、Bのサーバー達がインターネットにアクセスしてyum install等できるようになりました。めでたし
Ruby学習ログ：その１【do...end = {...}  , etc.】

Rubyを学び始めて２ヶ月ほどの初学者です。
アウトプットも兼ねて学習したことを投稿していこうと思います。
早速いきましょう。

#「do...end」は、「{...}」に書き換えられる

```ruby
hoge = [1, 2, 3]
hoge.each do |hogey|
   puts "オラは#{hogey}歳だ！"
end
puts "========================================"
hoge = [1, 2, 3]
hoge.each {|hogey|puts "オラは#{hogey}歳だ！"}
```
```:実行結果
オラは1歳だ！
オラは2歳だ！
オラは3歳だ！
========================================
オラは1歳だ！
オラは2歳だ！
オラは3歳だ！
```
同じ結果になりました
##いつでも使えるか？
ところでデメリットはないのか？と思って調べてみたらどうやらあるっぽい
→[ブロックをdo…endで書くか{…}で書くかにより挙動が変わる例]
(https://qiita.com/riocampos/items/43e4431ddff93e01a18d)

上の記事の中で「戻り値」に関して理解が曖昧だったので
→[【Ruby】メソッドの戻り値ってなんだ]
(https://qiita.com/hiroshimaeasyryo/items/9f271bb64f61fc89ca81)
この中の演習をやってみました

```ruby
def shipping_free?(price)
 return price >= 5000
end

if shipping_free?(10000)
 puts "5000円以上のお買い上げなので送料はいただきません"
else
 puts "追加で送料をいただきます"
end
```
```:実行結果
5000円以上のお買い上げなので送料はいただきません
```
「戻り値」の解説ならこちらの方がわかりやすいかも

→[関数の「戻り値」って何？C言語とRubyを比較して理解する！:Rubyの関数の戻り値]
(https://kitsune.blog/function-return-value#Ruby)
＊戻り値(返り値)は関数が返す「値」のこと (何か関数に値を入れたとき、関数から出てくる値)
#所感
わからないワードをググって調べると、また新たにわからないワードが出てきてプログラミングは奥深いなと感じた。基礎へ立ち返ることも必要であるし、内容の質は置いておいて、頭を整理する意味でも定期的に文章としてアウトプットすることは大切だと思った。
NeovimのFloating Windowで翻訳する ~ vim-translate-me ~

## はじめに

まだVimを使い始めて1年足らずですが、プラギンを一人でシコシコ探して設定しているとなんとなくもったいない気がしてきますね。
なのであまりインターネッツに情報がないプラグインとかについてこういうところでアウトプットします。

## Floating Windowで翻訳する

Floating Windowは最近Neovimに追加された要素で、Vimにもともとあった画面分割ウィンドウと一線を画す、「浮いている」ウィンドウが作れます。
画面を分割するまでもないちょっとした情報を表示するにはうってつけの機能。
<img width="723" alt="スクリーンショット 2019-11-26 13.16.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539325/844004ae-53ca-3fc0-7e0f-9d7dbe947edb.png">

このFloating Window活用した翻訳プラグインの1つが、voldikss氏作成の[vim-translate-me](https://github.com/voldikss/vim-translate-me)。
作者は中国人の方のようでデフォルトの設定やReadMeが中国語ですが、日本語でもしっかり使えます。

## vim-tlanslate-me

<https://github.com/voldikss/vim-translate-me>

```toml
# dein.nvim
[[plugins]]
repo = 'voldikss/vim-translate-me'
```

### Requirement

あたりまえですがFloating Windowが実装されたバージョン (v0.4) 以降のNeovimを使いましょう。
安定版にもすでに実装されています。
Pythonで記述されているのでNeovimにPythonのパスが通っていることも必要です。

### 設定

デフォルトの設定では引数を与えないと中国語に翻訳してしまいます。
ついでに翻訳エンジンもGoogleのものに変えましょう。

```vim
let g:vtm_target_lang = 'ja'
let g:vtm_default_engines = ['google']
```

## つかいかた

`:TransrateW`コマンドを翻訳したい文字列の上で実行すると……
<img width="871" alt="スクリーンショット 2019-11-26 14.40.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539325/8c5ddd4a-58e7-6564-c7ca-8652e9bb9103.png">
こんな感じに。
見た目もなかなかクールでよいですね。

翻訳は非同期に行ってくれるんですが、Floatingで表示させるとウィンドウがカーソル移動で消えてしまうので結局じっと待つことになります。
翻訳中にほかごとがしたい人は`:Translate`コマンドを使えば結果をコマンドラインに吐き出してくれるので幸せになれるでしょう。

デフォルトではこのようなマッピングになっています。
適当に変えて使いましょう。

```vim
  nmap <silent> <Leader>t <Plug>Translate
  vmap <silent> <Leader>t <Plug>TranslateV

  nmap <silent> <Leader>w <Plug>TranslateW
  vmap <silent> <Leader>w <Plug>TranslateWV
  " 翻訳結果で置換
  nmap <silent> <Leader>r <Plug>TranslateR
  vmap <silent> <Leader>r <Plug>TranslateRV
```

マッピングからはVisualモードで選択した文章全体を翻訳することもできます。
改行やタグが混じると結果が崩れてしまうので工夫しなければいけませんが、あるとないとでは大違いです。


## おわりに

私は試してないですが、VimでもPopup Windowを使って同様に機能するそうです。よかったですね。
Macで、terminal(ターミナル)のsudoコマンドを、パスワードなしで使用する

#前提条件
emacsでも、mgでもなんでもいいので、テキストエディタが使えること。

#方法
今回は、mgを使用する。
```
sudo mg /etc/sudoers
```

開いたファイルを編集する。
下の方にスクロールすると、
```root            ALL = (ALL) ALL```
という部分があるので、その記述よりも下の方に、
``` ユーザー名        ALL=(ALL) NOPASSWD: ALL```
と書く。

下記では、「mac」というユーザーがパスワード無しでsudoコマンド叩ける設定です。


```
# root and users in group wheel can run anything on any machine as any user
root            ALL = (ALL) ALL
%admin          ALL = (ALL) ALL
 
mac        ALL=(ALL) NOPASSWD: ALL

```

ユーザー名は、自分のパソコンに合わせて設定してください。
ユーザー名を知るためには、ターミナルを開いて、
```
Last login: Tue Nov 26 16:16:05 on ttys000
ユーザー名@~~~~~
```
と出るので、そこを見てください。
phpQueryを使ってWEBスクレイピングを試してみた

#PHPでwebスクレイピングを試してみた。
phpQueryというライブラリを使うとjQueryのように要素を指定して簡単にスクレイピングできるみたいなので、サンプルを試してみました。
jQueryのようにセレクタを指定する事ができるので、すごく直観的にスクレイピングしたい要素が取得できます。
**※スクレイピングについては自己責任で行ってください。**

##WEBスクレイピングとは
ウェブスクレイピングとは、ウェブサイトから情報を抽出するコンピュータソフトウェア技術のこと。ウェブ・クローラーあるいはウェブ・スパイダーとも呼ばれる。
[出典:Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0)

##phpQueryのダウンロード

[phpQueryのダウンロードページ](https://code.google.com/archive/p/phpquery/downloads)から最新バージョンをダウンロードします。phpQuery-onefile.phpというファイルがダウンロードされるのでそれを読み込ませます。

##実装サンプル

```php:PHP
<?php
require_once("./phpQuery-onefile.php");

$html = file_get_contents("https://ja.wikipedia.org/wiki/%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0");  

//HTMLを全文取得
$dom = phpQuery::newDocument($html);

/*
 * Wikipediaのタイトル・H1タグの中身と、
 * 画像の一覧を取得している。
 */

//H1タグの取得
$h1 = $dom->find("h1")->text();
echo $h1 . '<br>';

//titleタグの取得
$title = $dom->find("title")->text();
echo $title . '<br>';

//imgタグの一覧を取得
foreach ($dom->find('img') as $img){
  $img = $img->getAttribute('src');
  echo '<img src=' . $img . '><br>';
}

//aタグの一覧を取得
foreach ($dom->find('a') as $a){
  $a = $a->getAttribute('href');
  echo '<a href=' . $a . '>' . $a . '</a><br>';
}

```

##スクレイピングする際の注意点
スクレイピングで検索すると検索候補に**「違法」**とか**「著作権」**などの単語が出てきます。
スクレイピング自体には違法性はないですが、収集した情報の使い方を誤ると、著作権法違反となってしまう可能性がるので注意が必要です。
また、実際スクレイピングにより対象のサイトに負荷をかけて**偽計業務妨害容疑**で逮捕された例もあるようです。スクレイピングは使い方を誤ってしまうと意図せず自分が加害者になってしまう可能性があるので使用には注意が必要です。
参考：[岡崎市立中央図書館事件](https://ja.wikipedia.org/wiki/%E5%B2%A1%E5%B4%8E%E5%B8%82%E7%AB%8B%E4%B8%AD%E5%A4%AE%E5%9B%B3%E6%9B%B8%E9%A4%A8%E4%BA%8B%E4%BB%B6)

##まとめ
ちょっとしたスクレイピングのプログラムであればこのライブラリを使用することで簡単に実装する事ができそうでした。
スクレイピングした結果をCSVに出力するようにしたらもっと便利になりそうです。
個人的に一番皆さんの反応が良かった新機能Logs in Contextを紹介します

New Relicで技術統括をしている松本です。

本年度からNew Relic株式会社が本格活動ということで、Advent Calendar 2019に参加させて頂きました！

2019年に色々なお客様やパートナー様とお話させて頂きましたが、個人的に最も興味を持って頂けたであろうNew Relicの新機能「Logs in Context」をご紹介します。New Relicでログを取り込めるようになりましたが、これらのログをAPM機能と連携させるもので、原因究明から該当するログまで短時間に抽出できるようになります。下記に3つのご利用パターンをご紹介致します。


<h1>1. APM Error in context</h1>

管理しているアプリケーションでError Rateが気になる場合、左ペインから"Error Analytics"[①]をクリックして深堀りをしていきます。そこから最もErrorが発生しているclass[②]を選択し、さらにTransaction[③]と、どんどん深堀りして原因を探っていきます。
<img width="1472" alt="APM_pic1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528620/01850a0f-bf63-e966-600f-5162fe27ce59.png">

New Relicをご利用頂いているユーザーさんは、このようにしてErrorの詳細情報やスタックトレースまで辿っていく事によってエラーの根本原因の箇所まで素早く辿り着き対応することができますが、今回の新機能によってこれに該当するログまでを一つのUIで確認することが出来るようになりました。左上にある"See logs"をクリックすることによってNew Relicに送信されている大量のログから該当するログを抽出し表示することが可能になります。
<img width="1471" alt="APM_pic2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528620/34eb99b1-36ca-087f-87ae-89d7826fbde5.png">

この新機能によって、「原因の特定」と「ログの確認」をNew Relicのみで素早く行うことが出来るようになります。
<img width="1472" alt="APM_pic3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528620/e8be0fd7-db0f-c7dd-b32c-82f88e4cd133.png">


<h1>2. Distributed Tracing in context</h1>
分散トレーシングに関しても同様に簡単に該当するログを確認することができます。"Distributed Tracing"の画面から気になるRoot Span[①]をクリックします。
<img width="1591" alt="DT_pic1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528620/256a5576-00db-7cc6-2fbb-504344d2b497.png">

ここまではいつもの画面になりますが、該当するログを確認したい場合は右上の"See logs(9)"をクリックします。"9"は該当するログが9行あることを示しています。
<img width="1589" alt="DT_pic2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528620/03158073-187c-2532-b1db-3f5f12b0b44e.png">

下図のようにすぐに該当するログを確認頂くことができます。
<img width="1591" alt="DT_pic3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528620/d8c69eca-4796-c1c6-2a2a-cbb686971a7c.png">


<h1>3. Kubernetes in context</h1>
くどいようですが、"Kubernetes Explorer"からも該当するログに直ぐに辿り着くことができます。赤色になっているCRITICAL状態のPodや黄色のWARNINGのPodをクリックすると、各Podの詳細情報が右側に表示されます。該当するログを確認する場合は、これまで同様に"See logs"をクリックします。
<img width="1592" alt="k8c_pic2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528620/6525febd-1896-8adc-d289-774c09967058.png">

するとHost名やサービス名などでFilterされた該当するログのみを簡単に確認することができ、ErorrやWarningが発生しているログまで素早く辿り着けます。
<img width="1590" alt="k8c_pic3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528620/256ab961-eb2c-0925-4579-0c8e9d63b56d.png">


このように、New Relicの得意とするAPMからエラーやパフォーマンスの遅い原因追求をし、大量にあるログの中から該当するログのみに素早くたどり着くことが出来るようになりました。複数のTransactionやErrorのログを順番に確認していく必要がある場合などは大きな効率化につながると思います。New Relicをさらに便利にする強力な機能ですので是非お試しください。なお現時点ではPreview機能になりますので、ご利用をご希望の場合はお手数ですが弊社営業までコンタクトお願いします。
EC2のパブリックIPアドレスを意識せずにSSHログインする

# やりたいこと
踏み台サーバーを構築した際などは、基本的にSSHでログインすることになる。
そのEC2のパブリックIPアドレスを知らない状態で、SSHログインをしたい。

EC2を起動する度にパブリックIPアドレスは切り替わるので、ElasticIPを付与するケースが多かったりする。
しかし、ElasticIPは1AWSアカウントに対し、デフォルトではリージョン毎に5つしか設定できなかったりと何かと制約がある。
そのため、不必要にElasticIPを使うのも避けたい。

# 解決策
下記の流れで解決できます。

1. (事前準備) EC2インスタンスにタグを貼っておく
2. (SSH接続時) SSH接続したいインスタンスのオブジェクトをタグで検索をかける
3. (SSH接続時) ヒットしたEC2のパブリックIPアドレスを取得
4. (SSH接続時) 取得したパブリックIPアドレスに対し、SSH接続

## インスタンスへのタグ付
下記のように、Nameというキー名でタグを貼ると、コンソール画面のNameの場所にタグの値が表示されます。
<img width="567" alt="スクリーンショット 2019-11-26 15.57.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154121/fc7945bb-eb5a-a76a-22ea-d883fba51d3b.png">

今回は、Nameというタグをvrf-bastionという名前で貼りました。

## SSH接続
AWS CLIを使ったスクリプトを書きます。
インスタンス情報を取得するには、 `aws ec2 describe-instances` を使用します。
追加で指定するオプションは下記の通りです。

* `--filters` : 指定したインスタンス情報で検索するインスタンスを絞り込む
* `--query` : 取得したインスタンス情報から、抽出するフィールドを指定する

### 作成したスクリプト

```ssh-ec2.sh
#!/bin/bash

# ------------------------------------------
# 踏み台サーバーにSSHログイン
#
# 実行例:
#   $ sh ssh-ec2.sh
# ------------------------------------------

KEY_PATH_LOCAL=~/.ssh/key-pair.pem

PUBLIC_IP=$(
    aws ec2 describe-instances \
        --filters \
            "Name=tag:Name,Values=vrf-bastion" \
            "Name=instance-state-name,Values=running" \
        --query "Reservations[0].Instances[0].PublicIpAddress" \
    | tr -d \"
)
ssh -i ${KEY_PATH_LOCAL} ec2-user@${PUBLIC_IP}
```

`--filters` では、タグのName属性がvrf-bastionであるものを指定しており、さらに起動中のインスタンスの指定をしています。
検索に引っかかったインスタンスが1つであっても、リスト形式で情報が帰ってくるので `--query`に、Instance[0]という形で先頭のインスタンスを取得し、パブリックIPアドレスのみを出力するよう指定しています。

また、 `"aaa.bbb.ccc.ddd"` というダブルクオーテーション付きでパブリックIPが出力されるので、最後に両サイドのダブルクオーテーションを取り除いて変数に代入。

最後にそれらの変数を用い、SSH接続。

あとは、下記のようスクリプトを実行するだけです。

```
$ sh ssh-ec2.sh
```

これで動的にインスタンス名からIPアドレスを取得し、SSH接続できるようになりました。
GitHub Wikiのサイドバー（右）の表示非表示を切り替えるChrome Extension作った

探せばありそうだったけど、見つからなかったので作ってみた。
よく使っていたBacklogのWikiに表記の機能があって非常に便利なのだけど、GitHubのWikiは今のところ機能が少なく、表記についても出来なくて少し見づらかったので。
実装的にはdiv の display を切り替えているだけで、実質2行。
https://github.com/kuredev/toggle_github_wiki_rightbar

https://chrome.google.com/webstore/detail/toggle-github-wikis-right/bmenddnhmiihkojhbdobefdjbblmhcgh?hl=ja

![toggle.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50690/cd50bdcb-f1b1-65d3-f8d3-64862ed3bcac.gif)
質問のすゝめ

## はじめに
私は、簡潔にわかりやすく質問することが苦手です。
ここでは、少しでも人にわかりやすくエラーの内容などを伝えるために気を付けていることをまとめたいと思います。

## 自分の環境、使っているツールを書く
* 自分が使っているOS(バージョンも)
* ツールのバージョン
* 今自分がどういう風に開発を行っているか
この3つがはっきりしているほうが、自分と同じ状況の人がアドバイスをしやすくなります。なので、バージョンなどはしっかり明記しておくほうが良いです！

## やってみたことをしっかり書く
* 自分で試してみたこと
* やったあと、どんなエラーがでたのか
* ファイルの中身を貼り付けるなどして、どんなことをしているのかわかりやすくする


## 私がしている工夫
* 長いエラーメッセージは[gist](https://gist.github.com/)を使うようにする
* どのようなコマンドを打ったか、マークダウンで記述する

## 最後に
わからないことは、人に聞くのが1番の解決方法だとも思いますが、調べてみることも自分の力になると思うので、大切なことだと思います。ぜひ、質問できる場所を有効活用してみましょう。
MySQLのクエリログを収集したいときは

## MySQLでログの設定を行いたい

自分用メモです。

### my.cnfの場所を調べる

```
$ mysql --help | grep my.cnf
                      order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf /usr/local/etc/my.cnf ~/.my.cnf 
```

左から順に呼ばれていく。
環境を汚したくないので今回は `/usr/local/etc/my.cnf` をいじる。

### my.cnf設定

```conf
[mysqld]
# ...
general_log=1
log_output=FILE
general_log_file=/var/log/mysql/query.log
# ...
```

上記を追記する。

### 反映確認

```sql
show variables like '%general_log%';
```

|Variable_name|Value
|---|---
|general_log|ON
|general_log_file|/var/log/mysql/query.log

### 上記方法でダメなときは

```sql
set global general_log='ON';
```

のように直接書き換えてみる。

### ログ確認

```
$ tail -f /var/log/mysql/query.log
Tcp port: 3306  Unix socket: /var/lib/mysql/mysql.sock
Time                 Id Command    Argument
191125 21:29:31	  137 Query	SHOW VARIABLES LIKE '%log%'
```

ログが流れていくことが確認できる。
正規表現で日本語を抽出する

日本語を抽出する正規表現

[亜-熙ぁ-んァ-ヶ]

 

ちなみに……

ひらがなを抽出する正規表現

[ぁ-ん]

カタカナを抽出する正規表現

[ァ-ヶ]

漢字を抽出する正規表現

[亜-熙]

#From
https://hacknote.jp/archives/3150/
[Go言語] httpライブラリのHandler,Handlefuncとかをざっくり整理


# はじめに
Go言語のhttpの標準ライブラリを利用すると、http.Handleとかhttp.Handlefuncとか似た名前が多い。
httpサーバを作るときによく使われるものについて、概念だけわかるようにかなりざっくり整理。

##Handler
リクエスト受信時の処理を持つインターフェースと思っておけばいい
定義されているServeHTTPは結局のところリクエスト受信時処理

``` 
type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
}
```

```
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
	f(w, r)
}
```

##http.Handle
URLと対応するHandlerをひもづける

URLに対してHandlerに定義されているリクエスト受信時処理が登録される

```
func Handle(pattern string, handler Handler)
```

##http.Handlefunc
URLと対応するリクエスト受信時処理を直接ひもづける

使い方はhttp.Handleと同じ
Handleとの違いは、Handler(の処理)とひもづけるか、Handlerとして実体化させていない処理そのものとひもづけるかの違い

```
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
	DefaultServeMux.HandleFunc(pattern, handler)
}
```

## 実装時には
簡単なhttpサーバだと次の2ステップ

1.URLとURLリクエスト受信時の処理を登録する
　http.Handleとかhttp.Handlefuncとか

2.1.で登録した処理を指定のポートで待ち受け
　http.ListenAndServe

```
http.HandleFunc("/test/", testHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
```


##参考
GoでHTTPサーバー入門 [Handler][HandleFunc][ServeMux]
https://noumenon-th.net/programming/2019/09/12/handler/

Go 言語の http パッケージにある Handle とか
https://qiita.com/nirasan/items/2160be0a1d1c7ccb5e65
QualityForward APIとGoogle Apps Scriptライブラリを使って一日の作業件数を集計する

[QualityForward](http://bit.ly/37SjUEt)はクラウドベースのテスト管理サービスです。Web APIを提供しています。そのWeb APIを使いやすくするため、Google Apps Script用ライブラリを開発中です。

今回はそのGoogle Apps Scriptライブラリを使って、一日の作業件数を集計してみます。

## インストール

Google Apps ScriptでのプロジェクトIDは `1ppRPLjuClG0MhtnXYbskdZ8uYGbyCFHv7MFhr0GYa-3IAKEh8B7lmTMb` になります。これを取り込んでください。以下はデフォルトの `QualityForward` として取り込んだ場合の書き方です。

## 初期化

初期化はAPIキーを適用して行います。

```js
var apiKey = 'aaa';
var qf = new QualityForward.Client(apiKey);
```

## テストフェーズの取得

最初にテストフェーズをすべて取得します。

```js
var testPhases = qf.getTestPhases();
```

次にすべてのテストフェーズについて、テストサイクルを取得します。

```js
for (var i in testPhases) {
  for (var j in testPhases[i].test_suite_assignments) {
    var testSuiteAssignment = testPhases[i].test_suite_assignments[j];
    var testCycles = testSuiteAssignment.getTestCycles();
    // : 次の処理はこの中に記述
  }
}
```

## テスト結果の取得

すべてのテストサイクルについて、テスト結果を取得します。テスト結果の中で本日作業分をフィルタリングします。

```js
for (var k in testCycles) {
  var testCycle = testCycles[k];
  var results = testCycle.getTestResults();
  for (var l in results) {
    var testResult = results[l];
    var d = testResult.executed_at;
    if (d.getFullYear() === today.getFullYear() && 
      d.getMonth() === today.getMonth() &&
      d.getDate() === today.getDate()) {
      ary.push(testResult);
    }
  }
}
```

## テスト結果ごとにグルーピングする

TestResultが取得できたら、例えばテスト結果ごとにグルーピングしてみます。

```js
var group = {};
for (var key in ary) {
  var testResult = ary[key];
  if (!group[testResult.result]) group[testResult.result] = 0;
  group[testResult.result]++;
}

Logger.log('本日の作業結果');
for (var key in group) {
  Logger.log('  ' + key + ' : ' + group[key] + '件');
}  
```

そうすると以下のような出力が得られます。この結果をGoogleスプレッドシートに蓄積することももちろん可能です。

```
[19-11-26 15:39:14:587 JST] 本日の作業結果
[19-11-26 15:39:14:590 JST]   pass : 4件
[19-11-26 15:39:14:591 JST]   fail : 1件
[19-11-26 15:39:14:592 JST]   skip : 1件
[19-11-26 15:39:14:592 JST]   cut : 1件
[19-11-26 15:39:14:593 JST]   block : 1件
[19-11-26 15:39:14:593 JST]   qa : 1件
```

作業件数を蓄積していくことで、品質の可視化にも繋がるでしょう。

## まとめ

QualityForwardを使えばExcelなどで行っていた煩雑なテスト管理がクラウドベースでできるようになります。ライブラリを使うことで既存システムとの連携も用意です。ぜひお試しください！

[QualityForward](http://bit.ly/37SjUEt)
【備忘録】ショートカットキー

#参考#
・[Windows関連ショートカットキー](https://qiita.com/Kosen-amai/items/1373e880c1b87a44f56a#visual-studio-code)
・[【Windows版】VS Code キーボードショートカット一覧 （オススメ付き）](https://qiita.com/TakahiRoyte/items/cdab6fca64da386a690b) 
・[キーボードから手を離さずにVS Codeで開発したいという気持ちを大切にしています](https://insider.10bace.com/2019/02/22/vs-code%E3%81%A8%E3%81%8B%E3%81%AE%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88%E3%81%AE%E3%81%AF%E3%81%AA%E3%81%97/)
【Ruby初心者】シンボルの使い方でつまづいたこと

#はじめに
元々PHPをやっていたのですが、Rubyに触ってみて一週間経ちました。
参考書を２冊読んだのですが、一番わからないポイントがシンボルについてでした。
今回はシンボルについての記事です。

#:apple？

参考書を60ページくらい読んだら出てきました。


```ruby
:apple.class #=> Symbol
'apple'.class #=> String
```

初めてみる記法です。
Ruby使いは左側にコロンのついてるものをシンボルと呼ぶらしいです。

##主な特徴

###同じシンボルであれば全く同じオブジェクトである
```ruby
str1 = "string"
str2 = "string"
p str1.equal?(str2) #=> false
p str1.object_id    #=> 70332245439420
p str2.object_id    #=> 70332245439400

sym1 = :symbol
sym2 = :symbol
p sym1.equal?(sym2) #=> true
p sym1.object_id    #=> 901148
p sym2.object_id    #=> 901148
```
シンボルは１つのオブジェクトを参照しているものなので、右側の値が同じならシンボルは同じものになる。
→ String型に比べて、メモリを消費しない

参考記事：Rubyの文字列とシンボルの違いをキッチリ説明できる人になりたい
https://qiita.com/Kta-M/items/53a13ef60e14fcb41193

##シンボルの使い方

###連想配列のキーとして使われる
```ruby
#文字列をキーにする連想配列
{'japan' => 'yen', 'us' => 'dollar', 'india' => 'rupee'}

#これのキーをシンボルにすると次のようになる
{:japan => 'yen', :us =>'dollar', :india => 'rupee'}
```

配列のキーをシンボルにすることによって、データの抽出が高速になる
（理由：Rubyのプログラムはシンボルのデータを整数として持っているので、データの処理が速くなる）

###シンボルと同名のメソッドを呼び出す使い方
```ruby
class User
  attr_reader :first_name, :last_name, :age

  def initialize(first_name, last_name, age)
    @first_name = first_name
    @last_name = last_name
    @age = age
  end
end
```

シンボルが出てきました。

attr_reader :first_name, :last_name, :age

attr_readerは書き換えはできないけど、インスタンスにおいて指定したプロパティを読み込めますという設定にするものみたいです。
でもなんでattr_readerで指定してるのがシンボルなのかわからなくなりました。

・・・


どうやらこれは、同名のメソッドを呼び出ししているみたいです。
:first_name → first_nameのメソッド

attr_reader :first_nameを設定すると、

```ruby
class User
  def initialize(first_name)
    @first_name = first_name
  end

  def first_name
    @first_name
  end
end
```

とした時と、同じことになるみたいです。（attr_readerを設定すると同名のゲッターメソッドを作成する）


今回はattr_readerで設定をしているので、first_nameのゲッターを呼び出しているが、
attr_accessorで設定をすると、ゲッターとセッターで呼び出すみたいです。

これまでとは違ったシンボルの使い方ですね

似たような使い方で

```ruby
['ruby', 'java', 'perl'].map(&:upcase)
#を次のように変更（条件付き）
['ruby', 'java', 'perl'].map{|s| s.upcase}
```

がありました。これもシンボルと同名のメソッドを呼び出しているみたいですね。

参考記事： Rubyのmap(&:name)というのはどういう意味？
https://qa.atmarkit.co.jp/q/35


#まとめ

２つのシンボルの使い方があることを理解しました。
１、連想配列のキーにつかう
２、シンボルと同名のメソッドを呼び出す

以上
RのForestToolsライブラリにより樹頂点を検出しQGIS上で表示する

## 経緯
・近年、森林・林業分野において、航空機レーザ計測データなどによる地表面のデジタルデータ化が進んでいる。
・公共測量の場合は、測量法に則った申請により計測データの取得が可能であると思われるが、**データを利用価値のある形に変換する方法**が必要。
・統計分析フリーソフトRに**ForestTools**という良さげなライブラリがあると知り、QGISに持ち込むところまでをお試ししてみた。

##今回やりたいこと
樹冠高ラスタデータ（CHM）→樹頂点の検出→QGISで表示

## ForestToolsライブラリについて
・リモートセンシング技術により収集された森林情報を分析する**ForestTools**パッケージ（開発：Andrew Plowright氏）
・樹冠高ラスタデータ（CHM：Crown Height Model）から、主要木の樹頂点位置や個々の樹冠の輪郭の推定が可能
・指定したポリゴン内の樹高や本数情報の要約等も可能とのこと
・参考：The Comprehensive R Archive Network（"Canopy analysis in R using Forest Tools"）
　https://cran.rstudio.com/web/packages/ForestTools/vignettes/treetopAnalysis.html

## 手順
###１　Rを起動し、次のコマンドでライブラリをインストール
`install.packages("ForestTools")`
（実行するとミラーサイトの場所を聞かれるので、最も近い場所を選ぶ）

###２　ライブラリをアタッチ
`library(ForestTools)`
`library(raster)`

###３　サンプルをロード
`data("kootenayCHM")`

###４　樹頂点抽出処理（vwf）
####４－１　アルゴリズム概要
・vwfとは？＝**variable window filterアルゴリズム**（Popescu and Wynne 2004)
・CHM上を特定の大きさのwindowでスキャンし、突出して高い箇所を抽出する。
・windowの大きさは、中心となるセル値（樹冠の高さ）に依存する関数とすることで、樹木の高さよる樹冠投影面積の大きさを補完している。

####４－２　解析スクリプト
`lin <- function(x){x * 0.05 + 0.6}` ※後述

`ttops <- vwf(CHM = kootenayCHM, winFun = lin, minHeight = 2)`
引数：CHM = ラスタデータ（CHM），winFun = window sizeの関数，minHeight = 樹頂点を検出する最低値

※winFunについて
・windowの中心となるセル値を取得して、search windowの半径を返す。
・single input & single outputの式で定義（上記は最もシンプルな線形方程式）

####４－３　データの取り出し方
`ttops`（データフレーム）
class       : SpatialPointsDataFrame 
features    : 1077 
extent      : 439689.2, 439832.2, 5526454, 5526562  (xmin, xmax, ymin, ymax)
crs         : +proj=utm +zone=11 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0 
variables   : 4
names       : layer,           height,         winRadius, treeID 
min values  :     1,  2.0020417869091, 0.700102089345455,      1 
max values  :     1, 13.4912073612213,  1.27456036806107,   1077 

`names(ttops)`
[1] "layer"     "height"    "winRadius" "treeID"   

`ttops$x[1:3]`
[1] 439689.8 439731.2 439733.2

`ttops$y[1:3]`
[1] 5526562 5526562 5526562

`ttops$height[1:3]`
[1] 3.265903 3.027651 3.463092

####４－４　解析結果を図示
プロットの枠
`par(mar = rep(0.5, 4))`

ラスターデータ図示
`plot(kootenayCHM, xlab = "", ylab = "", xaxt='n', yaxt = 'n')`

樹頂点のプロット
`plot(ttops, col = "blue", pch = 20, cex = 0.5, add = TRUE)`
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433560/96bf7368-d692-7502-b9b3-54e7c3e7be26.png)

###５　CSVで出力
`file_path <- "C:\\Users\\xxx\\test.csv"`
`write.csv(ttops, file_path)`
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433560/f25ee6b8-5ddd-57dd-f230-5308f97e167b.png)
開くとこんな感じだった。
（なぜ、`names(ttops)`でx, y, optionalの列がでないのだろう？）

###６　QGISへ
メニューの「レイヤ」
→「CSVテキスト」
→ファイル形式：CSV
→ジオメトリ定義：以下のように指定
　・ポイント座標Xフィールド＝x
　・ポイント座標Xフィールド＝y
　・ジオメトリのCRS：EPSG:4326 - WGS 84
![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433560/3bee9d7c-74cf-b4df-600f-766d6a5f608f.png)

→あとはQGIS上で好きな処理を

##今後の課題
・サンプルデータ以外のラスタデータの読み込み
・位置情報を正しく反映させる（今回のだとOpenStreetMapレイヤを追加しても重ならなかったので）
・解析元のラスタデータとQGIS上で重ね合わせる方法

##使用バージョン等
・R version 3.6.1 (2019-07-05)
・QGIS version 3.1.6
Azure Data FactoryのEvent Trigger時の順次実行設定方法

#はじめに
Azure Data Factory(以下、ADF)ではスケジュールでの実行と、Blob StorageにデータがCreate(or Delete)された際に実行するような、2種類のTriggerを作成可能です。
[Azure Data Factory でのパイプラインの実行とトリガー](https://docs.microsoft.com/ja-jp/azure/data-factory/concepts-pipeline-execution-triggers)

本記事ではEvent Triggerを利用する際に注意が必要だったポイントについて備忘録的にまとめます。

#Event Trigger
Blob Storage上にある文字列あるいはパスにファイルがあがった際にパイプラインを実行するトリガーです。
[イベントに応答してパイプラインを実行するトリガーを作成する](https://docs.microsoft.com/ja-jp/azure/data-factory/how-to-create-event-trigger)

##注意点
非常に便利なトリガーですが、複数のファイルが一気にupされた場合に注意点があります。
既定の設定ですと、順次キューに入るような形ではなく、並列でトリガーが作動し、パイプライン処理が並列実行されます。
そのため、時間のかかるファイルが紛れ込んだ場合などに、ファイルの上がった順に処理されないというケースが発生します。

##対策
パイプライン自体の並列度を下げることで、順次実行される形を構成することが可能です。
トリガー自体はどんどん検知しますが、パイプラインが並列実行することを許されていないため、キューのような状態が実現できます。

##設定方法
トリガーと関連付けられているパイプラインを開き、[General] タブ配下の [Concurrency] を
“1” に設定することで、順次実行のパイプラインとして設定できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/6ee1bb09-a606-ece9-10c6-d22077bda3de.png)

#まとめ
標準で並列実行がサポートされているので、本来はうれしい機能ですが、イベント駆動型のデータ連携を考える際には注意点があるというお話でした。
[RSpec] Ajaxのテストの書き方

# はじめに
いいね機能やフォロー機能をajaxで作る時、Request specではどう書くかわからず
困ったので、メモしておきます。

## 結論

結論から言うとこのような形で書くと、ajaxで書いた機能をテストできます。
今回はいいね機能のテストを書いております。
いいね機能についてはこちらの記事を参考に作りました。
[[Rails]いいね機能の非同期での実装!!!](https://qiita.com/hayabusa3703/items/2b916e652a1dc85bb6e3)

(前提としてlike_pathのrouteには`username`と`post_id`が表示されるようにしているため、FactoryBotでuserとそのpostを作り、そのpostにいいねできることをテストしております。)

```Ruby
it "いいねしていない場合、いいねができること" do
  expect do
    post like_path(username: user.user_name, post_id: 1), xhr: true
  end.to change(Like, :count).by(1)
end
```

この`xhr: true`を書かないと下のエラーが出てしまいます。

```
 ActionController::UnknownFormat:
       LikesController#like is missing a template for this request format and variant.

       request.formats: ["text/html"]
       request.variant: []
```
`xhr: true`を書くだけでテストがうまく通るのですが、調べてもすぐには分からず時間がかかってしまいました。
以上です！
よくあるMacのお問い合わせに対応するためのApple公式ドキュメントリンク集

Macセットアップやお問い合わせ回答でよく利用するApple公式ドキュメントのリンクを集めました。
Sierra～Mojave向け。何か他に思いついたら追記します。

 - キーボードの○キーの反応が悪くなりました → [MacBook や MacBook Pro のキーボードのお手入れ方法](https://support.apple.com/ja-jp/HT205662)  
   * Macノートブックを75度に傾けてエアダスターをかけるとキーボードの裏のゴミが取れるらしい
 - Macの調子がなんかおかしい  
明確に原因が何かわかっているわけでは無い不具合がある時の最終手段
   * [NVRAMのリセット方法](https://support.apple.com/ja-jp/HT204063) 
ターミナルから `nvram -c`でもリセット出来る筈
音量とかBluetoothとか
   * [SMCリセットの方法](https://support.apple.com/ja-jp/HT201295#reset)  
充電し始めると大音量で変な音がするとかそういうのはこっち
 - ユーザのパスワードがわからなくなってしまった → [macOS ユーザアカウントのパスワードを変更またはリセットする](https://support.apple.com/ja-jp/HT202860)
   * Filevaultの復旧キーがあればmacOSユーティリティからターミナルを開いて `resetpassword` 
 - 何故か入荷したMacのログイン画面が英語だった → [Mac のログイン画面で使う言語を変更する](https://support.apple.com/ja-jp/HT202036)
   * `sudo languagesetup`
 - 起動ディスク無しでOSを入れ直す(ストレージ初期化をしてない状態) → [macOS 復元から macOS を再インストールする方法](https://support.apple.com/ja-jp/HT204904)
   * macOS Sierra 10.12.4 以降のバージョンを入れたことがある場合↓
   * command (⌘) + R 今入ってるバージョンのmacOS
   * option + ⌘ + R 最新版のmacOS
   * shift + option + ⌘ + R 工場出荷時のmacOS
 - [セーフモードを使って Mac の問題を切り分ける](https://support.apple.com/ja-jp/HT201262)  
起動しなくなってもセーフモードで起動して最後にインストールしたアプリをアンインストールしたら起動出来る様になるかも
   * 起動時に Shift ボタンを押しっぱなしにする
   * macOSユーティリティ(macOS復旧) で`sudo nvram boot-args="-x"` を実行する(元に戻すには `sudo nvram boot-args=""`
QualityForward用Google Apps Scriptのバージョンアップ

[QualityForward](http://bit.ly/2TkdLx1)はクラウドベースのテスト管理サービスです。Web APIを提供しています。そのWeb APIを使いやすくするため、Google Apps Script用ライブラリを開発中です。

取得系の処理はほぼできあがったので、その使い方を解説します。

## インストール

Google Apps ScriptでのプロジェクトIDは `1ppRPLjuClG0MhtnXYbskdZ8uYGbyCFHv7MFhr0GYa-3IAKEh8B7lmTMb` になります。これを取り込んでください。以下はデフォルトの `QualityForward` として取り込んだ場合の書き方です。

## 初期化

初期化はAPIキーを適用して行います。

```js
var apiKey = 'aaa';
var qf = new QualityForward.Client(apiKey);
```

## プロジェクトの取得

現在のプロジェクトを取得します。QualityForwardではプロジェクトごとにAPIキーが発行されます。

```js
var project = qf.getCurrentProject();
```

## テストスイートの取得

テストスイートを全件取得します。

```js
qf.getTestSuites();
```

## テストフェーズ

テストフェーズを全件取得します。

```js
qf.getTestPhases()
```

## テストサイクル

さらにテストフェーズを使ってテストサイクルを取得します。

```js
for (var i in testPhases) {
  for (var j in testPhases[i].test_suite_assignments) {
    var testSuiteAssignment = testPhases[i].test_suite_assignments[j];
    var testCycles = testSuiteAssignment.getTestCycles();
  }
}
```

## テスト結果

テスト結果はテストサイクルに紐付いています。

```js
var testPhases = qf.getTestPhases();
for (var i in testPhases) {
  for (var j in testPhases[i].test_suite_assignments) {
    var testSuiteAssignment = testPhases[i].test_suite_assignments[j];
    var testCycles = testSuiteAssignment.getTestCycles();
    for (var k in testCycles) {
      var testCycle = testCycles[k];
      Logger.log(testCycle.getTestResults());
    }
  }
}
```

## テストスイートバージョン

テストスイートバージョンはテストスイートに紐付いています。

```js
var testSuites = qf.getTestSuites();
for (var i in testSuites) {
  var testSuite = testSuites[i];
  var versions = testSuite.getVersions();
}
```

## テストケース

さらにテストケースはテストスイートバージョンに紐付いています。

```js
var testSuites = qf.getTestSuites();
for (var i in testSuites) {
  var testSuite = testSuites[i];
  var versions = testSuite.getVersions();
  for (var j in versions) {
    var version = versions[j];
    Logger.log(version.getTestCases())
  }
}
```

## まとめ

QualityForwardからデータを取得して、Googleスプレッドシートに記録するといった使い方が考えられます。Googleスプレッドシートを使えば、さらにBigQueryによる分析などにも活用できるでしょう。

ぜひお試しください！

[QualityForward](http://bit.ly/2TkdLx1)
= bashの置換${var/a/b}と配列


# 基礎の復習

bashの変数展開の一つに、値を置換するものがあります

```sh
# ${var/a/b}
# varに最初に含まれるaをbに置換
$ var="foo"
$ echo ${var/o/_}
f_o
```

又、含まれる全ての対象を置換するには`${var//a/b}`を使います

```sh
$ var="foo"
$ echo ${var//o/_}
f__
```

# 本題: 配列に適用した場合

`${var/a/b}`を配列に適用した場合、**各値に置換を適用した結果**になります

```sh
# ${var/a/b}のパターン
$ var=(1 2 3 4 11 12 13)
$ echo {var[@]/1/_}
_ 2 3 4 _1 _2 _3

# ${var//a/b}のパターン
$ var=(1 2 3 4 11 12 13)
$ echo {var[@]/1/_}
_ 2 3 4 __ _2 _3
```


ｼﾗﾅｶｯﾀ

[2019-11-26 15:07]
SimpleITKで画像を読み込むときに、pathに日本語があるとダメな問題

#はじめに
pythonの画像処理ライブラリとしてはopenCVやPILなどが有名だと思いますが、dicom画像を直接読み込みたいという理由からSimpleITKというものを使い始めました。
まずはSimpleITKを使って画像を読み込んで表示する、という単純なコードを書いたのですが、いきなりこれに躓いてしまった。。。
結論から言うと、入力画像のpathに日本語（恐らく英語以外ダメ？）が入っていると文字コードの問題でダメっぽい。
SimpleITK自体マイナーなライブラリなので使う人はほとんどいないかもしれませんが、一応共有します。


#PC環境
- OS : Windows 10 Professional 
- 言語 : Python 3.7.3
- IDE : Eclipse 4.11.0
- SimpleITK 1.2.4

#SimpleITKについて
ITK(https://itk.org/itkindex.html) というC++ベースで記述された画像処理ライブラリをpythonやJavaでも使えるようにしたものがSimpleITK(http://www.simpleitk.org/) らしい。
CTとかMRIといった医用画像を処理するのに稀によく使われます。医用画像はdicomと呼ばれる形式で保存されていることが多いため、SimpleITKはdicom画像を直接読み込めるようになっています。
ドキュメント(https://simpleitk.readthedocs.io/en/master/index.html) がある程度しっかりしているので、初心者にも始めやすい？
（まぁわたしはいきなり躓いたのですが）

#SimpleITKのインストール
pipで簡単にできる。

```
pip install SimpleITK
```

#画像の読み込み
公式ドキュメントの「Reading and Writing for Images and Transforms」（https://simpleitk.readthedocs.io/en/master/Documentation/docs/source/IO.html ）に書いてある通りに画像を読み込みます。
ただし、入力画像のpathに日本語を含むようにします。
今回はdicom画像ではなくレナさん(png形式)を読み込むコードになっています。

```read_image.py
import SimpleITK as sitk

file_name="C:/日本語/Lenna_(test_image).png"#これだと動かない
#file_name="C:/Lenna_(test_image).png"#正常に動く

reader = sitk.ImageFileReader()
reader.SetImageIO("PNGImageIO")
reader.SetFileName(file_name)
image = reader.Execute();

if ( not "SITK_NOSHOW" in os.environ ):
    sitk.Show( image, "image show" )#ImageJで画像を表示する。

```

**結果**

以下のように、ファイルが見つかりませんっていうエラー文が出る。

```
RuntimeError: Exception thrown in SimpleITK ImageFileReader_Execute: D:\a\1\sitk-build\ITK\Modules\IO\PNG\src\itkPNGImageIO.cxx:149:
itk::ERROR: PNGImageIO(000001A1C5886F00): PNGImageIO could not open file: C:/日本語/Lenna_(test_image).png for reading.
Reason: Illegal byte sequence
```

**対策**

画像のpathを変更して日本語を含まないようにすると正常に動作する。
※根本的な解決策がわかる人いたら教えてください・・・

#GithubのIssuesを見ると・・・
中国語がpathに含まれるとダメ！って悩んでいる人がいるっぽい。
（https://github.com/SimpleITK/SimpleITK/issues/795 ）
pythonのstringは文字コードがunicodeだが、ITK側は文字コードがASCIIになっていることが問題とかなんとかと議論されています。ASCIIは日本語には対応していないため、ITK側がASCIIしか読めないという話になるとpathを全部アルファベットにしなきゃいけないかもですね。。。

#追記（2021/06/23）
OpenCVでも同様に日本語pathが読めないそうですね。やはりASCIIしか対応していないことが原因だそうです。
参考までに。
https://qiita.com/SKYS/items/cbde3775e2143cad7455

#まとめ
SimpleITKを使うときは画像のpathに日本語を含まないようにすること。
根本的な解決策がわかったら更新します。
DataGridViewの縦スクロールの描画パフォーマンスを改善した話

#何が書いてあるか？
- DataGridViewの縦スクロールの描画パフォーマンスを上げた方法
- 原因の特定方法（大したことではないが）
- リフレクションで無理やりSetプロパティの制約を回避した話

#役に立つのか？
特殊な状況下なので、万人に役にたつかは微妙。
あ、たぶん。役に立たないです。
リフレクション使えば、例外回避して設定できるのかーぐらいかな。
（そもそも、リフレクション使う人は、それぐらい知ってると思うが）

#特殊な状況について
DataGridViewを使いスプレッドシートの入出力画面を作成した。
カラムヘッダは独自に直接セル結合を行っていてFixed設定をしている。
※カラムヘッダは非表示(ColumnHeadersVisible = false)
ロウヘッダは行選択をするため残している。(RowHeadersVisible = true)


#事象
DataGridViewの縦スクロール時に、上下端からスクロールする場合のスピードが顕著に遅い（カクカクする）

#状況調査＆原因特定？
DataGridViewはDataSourceを切り替えて使いまわしているが、遅いのは特定の場合で、すべてが遅いわけではない。

データ量の問題かと、表示レイアウトはそのままにDataSourceのみ変更したところ変化が無いことがわかった
⇒ つまり、データ量、DataSouceは関係ない

遅いところと、そうでないところの違いを調べたところ、
RowHeadersVisible の違いがあることがわかり、非表示にしたところパフォーマンスが改善した。

これが問題か？
# 対応方法について
RowHeadersVisible の設定でのパフォーマンス有無についてネットで調べたが特に有益な情報は得られず。
パフォーマンス改善について、ダブルバッファリングの手法があることがわかった。
以下、対応内容と採用可否である。

1. RowHeadersの非表示
時間があれば、独自実装して１カラム目をヘッダーのように扱うことは可能だが、ナイーブな（お察し下さい）実装のため残念ながら採用できない。

2. ダブルバッファリング
ネットで多くみかけたのですが、実際に試してみると、
早くはなるものの、結合セルの部分の再描画が行われる黒くなり使い物にならない。

ここで手詰まりかと思っていたが、天からのひらめき。
RowHeadersVisibleのtrue/falseで、スピードが変わるならColumnHeadersも効果あるのでは？

ということで、第三の方法として

　3. ColumnHeadersの「表示」
本来、非表示であるカラムヘッダを表示してみたところ、パフォーマンスが改善されたのである。

# ちょっとの格闘と対応の完全版
結局原因自体は、よくわからんが、カラムヘッダを表示した場合、パフォーマンスが改善された。
ちなみに、検証結果は以下の通り。
ピンポイントの組み合わせで遅かったよ・・・（多くの人は、この事象に出会わないのでは？）

|RowHeadersVisible  |ColumnHeadersVisible  |結果  |
|---|---|---|
|true  |true  |OK  |
|true  |false  |遅い  |
|false  |true  |OK  |
|false  |false  |OK  |

というわけで、ヘッダの高さをゼロにして非表示扱いにしてみよう。
というのが今回のまとめになる。

```C#
dgv.ColumnHeadersHeight = 0; //これは、うまくいかない
```
ところが、ゼロを実際に設定してみたところ例外が発生した。

[MSDN(DataGridView.ColumnHeadersHeight プロパティ)](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.forms.datagridview.columnheadersheight?view=netframework-4.8)を見ると**３以下は設定できない**ようだ。

じゃあ、リフレクションを使ってみようと試してみるが、プロパティはあってもフィールドが見つからない。(NonPublicを指定しているのに)
プロパティ(PropertyInfo)のSetValueを使ってみると例外が発生する・・・

と、しばらく格闘していたが、わかってみればなんのことはない。
使っているクラスが、CommonFramework.Forms.DataGridViewでなく、それを継承したクラスだったからだ。
なまじpublicのプロパティが見えるので気づくのに時間がかかった。

というわけで、以下のコードで対応。

```C#
// dgv は、DataGridView（を継承したクラス）のインスタンス
dgv.GetType().BaseType
   .GetField("columnHeadersHeight", BindingFlags.Instance | BindingFlags.NonPublic)
   .SetValue(dgv, 0);
```

なるほど。インスタンスからGetTypeするから混乱の元になったのか。
完全に動的に操作する必要ないから以下で大丈夫だった。
※とはいえ、フィールド名 columnHeadersHeight を特定するのが大変だったわけだが。

```C#
typeof(DataGridView)
   .GetField("columnHeadersHeight", BindingFlags.Instance | BindingFlags.NonPublic)
   .SetValue(dgv, 0);
```

.Netのバージョンだったり、そもそも継承の有無で役に立つ可能性は、わからないがメモとして残しておく。
AWS EC2でWordPressを構築する際に500エラーに悩まされた話

# はじめに
今回、「ゼロからわかるAmazonWebServices入門」という書籍でAWSを学習しているものです。
こちらの書籍の第４章でエラーに遭遇し、多くの時間を浪費してしまったので備忘録として記します。
同じようなエラーに悩んでいらっしゃる方の一助となれれば幸いです。

# ブラウザからパブリックIPにアクセスすると500エラーになった
書籍の手順通り、デフォルトのVPC、サブネットにEC2インスタンスを作成、起動させ、そこへsshでログイン後、Apache、PHP、MARIADB、WordPressをインストールし終えたところでブラウザからパブリックIDを仕様してサーバーにアクセスすると、500エラーが表示されました。

# 原因と対処法
私の場合、インストールしたPHPとWordPressのバージョンが合わず、エラーを引き起こしていました。
そこでいったんインストールしたWordPressを削除してから、古いバージョンのものをバージョン指定してインストールする事で解決しました。

１、インストール、展開したWordPressを削除
```/home/wordpress
$ rm -rf *
```
```/var/www/html/
$ rm -rf *
```

２、古いバージョンのWordPressをインストール（私の場合は5.0.7）
```/home/wordpress
$ wget https://wordpress.org/wordpress-5.0.7.tar.gz
```

３、インストールした古いバージョンのWordPressを展開
```/home/wordpress
$ tar wordpress-5.0.7.tar.gz
```

４、古いバージョンのWordPressをAppacheに移動
```/home/wordpress
$ mv wordpress/* /var/www/html
```

# 500エラーとは何か
様々なステータスコードがある中で、500エラーは内部サーバーエラーと呼ばれるらしいです。
要するに、ソースコードや、プログラム自体に問題があるよ！という意味のエラーだと解釈しています。
今回のエラーに関しては、プログラム同士が互換性がなくエラーになっていたので、納得です。

# おわりに
このエラーに関しては、問題があることを知らせてくれるのみで具体的に何が悪いのかが分からず、半日ほど使ってしまいました。
Apacheを疑ってみたり、データベースを疑ってみたりと四苦八苦しました...。
WordPressをインストールし直す試みの途中で、いったんWordPressをアンインストールしたところ正常なapacheの画面が表示されたので、問題はWordPressにあるだろうというところまで来るものの、さらに時間を浪費するばかり...。
最終的には、書籍に記された
http://IPアドレス/wp-admin/install.php
ではなく、
http://IPアドレス/wp-admin/serup-config.php
にアクセスしてみたところ、「PHPとWordPressのバージョンに互換性がないよ」とエラーが表示されたので、なんとか解決。
まだまだ勉強することがたくさんありますね。
ROS2でのリアルタイム制御についての調査

#概要
ROS2はROS1に比べてリアルタイム性が高くなるように設計されている。
ROS2のチュートリアルにリアルタイム制御のデモがあったので、自分で調べたことも合わせてまとめてみた。

#参考文献
- https://index.ros.org/doc/ros2/Tutorials/Real-Time-Programming/

##必要なもの
- リアルタイムOS
- 8GB以上のRAM
- Connext DDS

##手順
1.リアルタイムOSの導入

現在、Linuxのみ対応している。
Ubuntuの場合、`sudo apt-get install low-latency`で導入可能。

2.Connext DDSを導入

ROS2の通信モジュールを入れ替える。
研究機関であれば、無料のライセンスがある。
そうでなくても、30日間の体験版ライセンスあり。

3.デモを実行

倒立振子のシミュレーションが始まる。
ソースコードを改造すればリアルタイム制御に対応したシステムを構築できるかもしれない。
ただし、C++でメモリを扱う操作とROS2ノードを構築するための知識が必要である。
【覚書】Azure ADで追加したユーザーにリソース作成可能な権限を割り当てる

##覚え書き ハンズオン用に大量に作成したゲストアカウントに権限を割り当てる

ハンズオン用にアカウントを大量作成したものの
こいつらにリソース作成権限を与えるのに苦戦したので、覚え書きを書きます


###参考用

アカウント大量作成手順

①ポータルのメニューからAzure ADを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524081/c771d3e6-d13f-0fa8-4805-7dfe73e0ce7c.png)

②ユーザー > すべてのユーザー からアカウントを一括作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524081/a2c97c25-50f3-e77d-f8fc-694a439b2f66.png)


###権限の割り当て

①サブスクリプションの設定からアクセス制御　→　追加　→　ロールの割り当ての追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524081/89e5c7e1-336e-a65c-77be-7eb321f3f672.png)


②共同作成者の設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524081/f8ce3d60-c147-2887-77b1-c5f6b81925c1.png)


###該当ユーザーで再ログインしてテスト・確認したら作業完了です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524081/33cfe06a-1161-fadc-fa10-cd9957dab1a5.png)
ABC083B - Some Sums

# 問題
https://atcoder.jp/contests/abs/tasks/abc083_b
<img width="1106" alt="スクリーンショット 2019-11-26 14.48.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307024/4538b1ec-11c1-a5fb-1201-e6f183156f88.png">

#1回目
##回答
```ruby
N,A,B = gets.chomp.split(" ").map(&:to_i)

res = 0
for num in 1..N do
  numList = num.to_s.chars.map(&:to_i)
  sum = 0
  for n in numList do
    sum += n
  end
  if sum >= A && sum <= B
    res += num
  end
end

puts res

```
##結果
<img width="1090" alt="スクリーンショット 2019-11-26 14.51.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307024/f51b2b42-01da-8b31-a764-f97efbfa7e16.png">

#2回目
##回答
```ruby
N,A,B = gets.chomp.split(" ").map(&:to_i)

res = 0

for num in 1..N do
  s = 0
  n = num
  while n > 0 do
    s += n % 10
    n /= 10
  end
  if s >= A && s <= B
    res += num
  end
end

puts res

```
##結果
<img width="1090" alt="スクリーンショット 2019-11-26 14.51.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307024/ee900a9a-2d0e-5c73-30e4-acfc783c3f75.png">
Azure Synapse Analytics (旧 Azure SQL Data Warehouse)の可用性について

#はじめに
Azure Synapse Analytics（以下、SQL DW）における可用性について調査結果をメモします。
※調査を実施した2019/10月時点の情報です。


##SLA
https://azure.microsoft.com/ja-jp/support/legal/sla/synapse-analytics/v1_0/
99.9%となっています。
情報分析においては高可用性は不要でしょうから、十分なレベルでしょう。


#障害対応の方針
では本題ですが、結論からいうとSQL DWは「データセンター内での冗長化」のみをサポートしているという調査結果となりました。
SQL DatabaseのPremium および Business Criticalサービスレベルの様にゾーン冗長構成をとり高可用性構成はとれないということです。

##フェールオーバー
上記の冗長性オプションを踏まえて、フェールオーバーのパターンは下記2つに整理できます。
 1. データセンターの一部に障害が発生した場合
 2. １つのデータセンター全体に障害が発生した場合

##1. データセンターの一部に障害


| フェールオーバーの実施者 |  想定ダウンタイム目安  |
| --------------------    | ------------------ |
| Azure       | 平均 数秒から数十秒     最大１分 |


データセンター内では冗長化されているため、たとえばデータセンター内のあるラックで障害が起きた場合にはAzure側で自動でフェールオーバーされます。
その際のダウンタイムは最大でも1分未満、平均数秒から数十秒を想定しているようです。



##2. １つのデータセンターの全部に障害
| フェールオーバーの実施者 |  想定ダウンタイム目安  |
| --------------------    | ------------------ |
| サービス利用側の開発者    | 開発時の設定による |

SQL DWはたとえば東日本と西日本のように地域を跨いだレプリケーションを構成できない為、地域を跨いだフェールオーバーは実施できません。

したがって、単一のデータセンター全体での障害発生時についてはユーザ側での対応が必要で、
下記リンクのようにGeoリストアを用いて、別のデータセンターに手動復元することがフェールオーバの対応となります。
[Azure SQL Data Warehouse の geo 復元参考リンク](https://docs.microsoft.com/ja-jp/azure/sql-data-warehouse/sql-data-warehouse-restore-from-geo-backup)

###Geoリストア
SQL DWでは自動バックアップ機能が既定で有効となっており、自動バックアップで取得されたバックアップデータをペアとなるデータセンター（東日本なら西日本）に24時間に1回の間隔でコピーしています。
このデータを利用して復元することをGeoリストアといいます。

#以上
備忘録的なメモとして記載しました。
ご参考まで。
Unison 2.48.4 を Mac OS X に Homebrew を用いてインストール

以下でうまくいった．

```
# Get rid of existing Unison
brew uninstall --force unison

# Checkout version of homebrew with Unison 2.48.4
cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core
git checkout 05460e0bf3ae5f1a15ae40315940b2d39dd6ac52 Formula/unison.rb

# Install
brew install --force-bottle unison

# Set homebrew-core back to normal
git checkout master
git reset HEAD .
git checkout -- .
```

# 参考リンク
https://eric.blog/2019/01/12/install-unison-2-48-4-on-mac-os-x-with-homebrew/
Memo: Gradient Boost

本記事は、Gradient Boost に関する個人用のまとめです。

- 決定木
    - [[入門]初心者の初心者による初心者のための決定木分析](https://qiita.com/3000manJPY/items/ef7495960f472ec14377)
- Random Forest
- XGBoost
- Light GBM
    - [LightGBM ハンズオン - もう一つのGradient Boostingライブラリ](https://qiita.com/TomokIshii/items/3729c1b9c658cc48b5cb)
ElixirでCloud PubSubにリクエストを飛ばす

最近、Elixirを触ってみてるのですが、Cloud PubSubにElixirを使ってぶん投げるというコードを書いてみたのでメモ。

なお、ElixirはもちろんPubSubも今回初めて触ったので変なところあったら指摘が欲しいです。

## PubSub準備

まずはトピックの作成

```bash
gcloud pubsub topics create first-topic
```

続いて、サブスクリプションの作成。これでpull型のサブスクリプションができる

```bash
gcloud pubsub subscriptions create first-topic-subscription --topic first-topic
```

動作確認をしてみます。

```bash
gcloud pubsub topics publish first-topic --message "hello pubsub"
```

PubSubにメッセージを送信できました。結果はGCPのコンソールとかから確認可能です。

## Elixir

続いてElixir側のコードになります。

### config

mix.exsにgothとgoogle_api_pub_subを足します。gothは`Google OAuth`の略みたいです。

```exs

  def application do
    [
      extra_applications: [:logger, :goth],
      applications: applications(Mix.env)
    ]
  end

  defp deps do
    [
      {:google_api_pub_sub, "~> 0.16.0"},
      {:goth, "~> 1.1.0"}
    ]
```

### Authentication

ローカルで動かす場合は`GOOGLE_APPLICATION_CREDENTIALS`の設定が必要です。サービスアカウントに適切な権限を設定してダウンロードして環境変数の設定をします。

`Pub/Sub パブリッシャー`の権限が必要なのでこちらを対象のアカウントに紐づけておきます。

```bash
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service_account.json
```

### サンプルの実行

対話シェルを使って動作確認をします。

```bash
iex -S mix
```

エラー処理はちゃんと書いてませんが、だいたい以下のコードで動きます。

```exs
project_id="${PROJCT ID}"
topic_name="first-topic"

m = Jason.encode!(message)

{:ok, token} = Goth.Token.for_scope("https://www.googleapis.com/auth/cloud-platform")
conn = GoogleApi.PubSub.V1.Connection.new(token.token)

# Build the PublishRequest struct
request = %GoogleApi.PubSub.V1.Model.PublishRequest{
    messages: [
        %GoogleApi.PubSub.V1.Model.PubsubMessage{
            data: Base.encode64(m)
        }
    ]
}

r = GoogleApi.PubSub.V1.Api.Projects.pubsub_projects_topics_publish(
    conn,
    project_id,
    topic_name,
    [body: request]
)
r = case r do
  {:ok, response} -> response #IO.puts "published message #{response.messageIds}"
  {:error, msg} -> IO.puts "published message #{msg}"
end

```

読めばそのままですが、まず`Google OAuth`でアカウントを取得しています。
そして、メッセージ情報を作成しPublishしています。

メッセージ情報はディクショナリ型をJSON文字列に変換して渡しています。これで任意のデータ構造をCloud PubSubに送信することができます。

## まとめ

基本的には[GitHub上のREADME](https://github.com/GoogleCloudPlatform/elixir-samples/tree/master/pubsub)と[HEXのドキュメント](https://hexdocs.pm/google_api_pub_sub/api-reference.html)を参照してやった感じです。

Elixirマイナーだからライブラリあるかな？ と失礼ながら心配だったけど特に問題なく利用できてよかったです。

GCPはゲームとかと親和性高いのでサーバを１からかけるExlixirも人気高いのかもしれないですね。

それではHappy Hacking!

## 参考:
- [GOOGLE CLOUD PLATFORM での ELIXIR](https://cloud.google.com/elixir/?hl=ja)
CSVに書いたURLを順番に開いて全画面スクリーンショットを取るスクリプト

必要に迫られて、ちょこっと書いてみました。

## 環境

- Windows10Pro
- Python 3.7.2

### モジュール

- webdriver-manager 1.8.2
- pytest 5.0.0

## コード

こんな構成を想定してます。

```
.
├── data
│   └── urls.csv
├── utilities
│   └── read_csv.py
└── test_screenshot.py
```


### メインの処理

csvのurl列に書いてあるURLを開いてはスクリーンショットを撮り、開いてはスクリーンショットを撮り、する処理です。

幅は1920px固定にしていますが、heightと同様にスクロールに対応させることも可能です。

``` test_screenshot.py
import time

import pytest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager

from utilities.read_csv import read_csv_data


class TestScreenshot():

    datalist = read_csv_data("./data/urls.csv")

    @classmethod
    def setup_class(cls):
        options = Options()
        options.add_argument('--headless')
        options.add_argument('--hide-scrollbars')
        cls.driver = webdriver.Chrome(executable_path=ChromeDriverManager().install(), options=options)
        cls.driver.maximize_window()

    @pytest.mark.parametrize("id, url", datalist)
    def test_reserve_multi(self, id, url):
        driver = self.driver
        driver.get(url)
        time.sleep(3)
        page_height = driver.execute_script('return document.body.scrollHeight')
        driver.set_window_size(1920, page_height)
        driver.save_screenshot(id + '.png')
```


### CSV

`id`列と`url`列のふたつを持っています。`id`はスクリーンショットのファイル名にも使っています。

``` urls.csv
id,url
1,https://www.hoge.co.jp/
2,https://www.hoge.co.jp/pageA/
3,https://www.hoge.co.jp/pageB/
4,https://www.hoge.co.jp/pageC/
5,https://www.hoge.co.jp/pageD/
```

### CSV読み込み処理

※Qiitaの記事から参考にした処理だったはずなのですが、参考元を探せず・・・

``` read_csv.py
import csv

def read_csv_data(csv_path):
    rows = []
    with open(str(csv_path), encoding="utf-8") as csv_data:
        content = csv.reader(csv_data)
        next(content, None)
        for row in content:
            rows.append(row)
        print(rows)
        return rows
```

## 使い方

```
> pytest test_screenshot.py
```

## 注意点

実際使ってみたのですが、JSとかを駆使して動きがあるようなサイトではうまく全画面で取得できませんでした。

たぶんこの方法に限らず、なかなか厳しいと思います。


## 参考

- [Python: Selenium + Headless Chrome で Web ページ全体のスクリーンショットを撮る - CUBE SUGAR CONTAINER](https://blog.amedama.jp/entry/2018/07/28/003342)
    - 全画面のスクショを撮る処理はほぼ真似させていただきました
【クラウド初心者向け】Amazon Connectのリアルタイムモニタリング

# 概要
- ユーザー（エージェント）が受けている電話を管理者がリアルタイムに聞くことができる。

## 使用ユーザー
-  IAMユーザー

## 手順
1. AWSにサインインします。
    1. アカウント、ユーザー名、パスワードを入力してサインインします。  
     [アカウント内（IAM）で作成したユーザーを使用してコンソールにサインインする](https://qiita.com/echolimitless/items/129495c920217916a14f#%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E5%86%85iam%E3%81%A7%E4%BD%9C%E6%88%90%E3%81%97%E3%81%9F%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%81%AB%E3%82%B5%E3%82%A4%E3%83%B3%E3%82%A4%E3%83%B3%E3%81%99%E3%82%8B)

1. 『AWSマネジメントコンソール』画面の右上にある《リージョン名》をクリックし、ドロップダウンます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520689/02487090-54eb-e851-6d7a-674e88da61c9.png)

1. 『AWSマネジメントコンソール』画面にある「サービスを検索」にConnectと入力し、検索結果から《Amazon Connect》をクリックし、Amazon Connect コンソール[（https://console.aws.amazon.com/connect/）](https://console.aws.amazon.com/connect/)を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520689/28aff404-d3ae-b201-9ebb-b9839bde6ebf.png)

1. Amazon Connectのインスタンス一覧が表示されるので、該当のインスタンスをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520689/5846170a-bf01-6560-6687-9f970722c1bb.png)

1. インスタンスの概要が表示されるので《管理者としてログイン》をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520689/46c1f25e-b2e2-65ce-7972-1aa73f8441cb.png)

1. [【クラウド初心者向け】Amazon Connectのユーザー（エージェント）作成](https://qiita.com/echolimitless/items/ca1d94e26c4946721233)を参考に以下の設定でユーザーを作成します。
    1. 名：適当な名を入力します。
    1. 姓：適当な姓を入力します。
    1. ログイン名：適当なログイン名を入力します。
    1. パスワード、パスワード確認：適当なパスワードを入力します。
    1. ルーティングプロファイル：「Basic Routing Profile」（今回はルーティングされないものを選択しましたが適当に選択してください）
    1. セキュリティプロファイル：**「CallCenterManager」** と「Agent」を選択します。

1.  [【クラウド初心者向け】Amazon Connectの着信確認](https://qiita.com/echolimitless/items/38e10d6f5835cf922739)を参考に、作成したユーザーでソフトフォンにサインインします。
    1. ステータス：Offline

1. 作成したユーザーでAmazon Connectのインスタンスにサインインします。
    1. URL：https://インスタンス名.awsapps.com/connect/ 

1. ダッシュボードの左側のメニューから《リアルタイムメトリクス》をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520689/d4961d4e-0ad3-e473-a7bb-edb8f4ea1c59.png)

1. 「リアルタイムメトリクス」画面が表示されるので《エージェント》をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520689/9dcf985f-9c4a-5961-ccc1-4bd1002cf1dd.png)

1. 「エージェント毎のリアルタイムメトリクス」画面が表示されます。モニタリングしたいユーザーのチャネル欄にあるアイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520689/b3ad394c-bb32-c31e-b21a-6c86c148604e.png)

1. 事前に起動しておいたソフトフォンがモニタリング状態になり通話内容を聴くことができます。
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520689/95ebf7fd-729f-7332-4019-744bb6db09c4.png">
    1. モニタリング側の《通話を終了》をクリックするとモニタリング側だけ通話が終了します。（モニタリングのみ終了し、通話自体は継続しています）

# 参考サイト

[ライブ会話の監視](https://docs.aws.amazon.com/ja_jp/connect/latest/adminguide/monitor-conversations.html)

# 目次に戻る
- [【クラウド初心者向け】Amazon Connectでコールセンターを作る](https://qiita.com/echolimitless/items/e5044c73656f8ae29f93#%E7%9B%AE%E6%AC%A1)