OmniAICreator/Qiita-1.07M huggingface dataset:
Xplenty中級編 Part4： DB周りの設定（Destination編）

今回は、お客様からの質問が多いデータベース周りの細かい設定について、データベースがDestination（送信先）の場合の設定について解説します。

#Q. Xplentyのジョブでデータベースへロード時にエラーが発生した場合、どうなりますか？
A. あるジョブでデータベースへのロード時にエラーが発生した場合、ジョブのステータスとしては、エラーになります。問題は全てのデータが無効になるのか、それまで書き込まれていたデータはそのままデータベースにロールバックされずに残るのかという点ですが、これはXplenty側のパッケージでどのオプションを設定しているかによって変わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/f026c1e7-bd3b-93db-7808-737c1328305f.png)

###Transaction per connectionにチェックがONの場合
この場合は「Batch size」に関係なく、コネクションレベルで制御されます。**Max paralell Connectionsが１の場合は**、ジョブ実行中にエラーが発生した場合、そのジョブで更新された行はすべてロールバックされ、結果としてデータベース側はジョブ実行前の状態に戻されます。（データ更新なし）

###Transaction per batchにチェックがONの場合
この場合は、Batch sizeで指定された値（レコード数のことです）で処理が随時コミットされます。例えば、Batch sizeを1000とした場合、1000行ごとにコミットされます。もし、3000件更新するジョブがあるとして、最初の1000件は問題なくコミットでき、その次の1000件を処理中にエラーが発生した場合、ジョブは、その時点でエラーとなり終了しますが、最初のコミット済みの1000件分の更新は、データベース側に反映され、ジョブが終了します。（一部反映）

#Q.更新されるデータが書き込み先のスキーマ定義と異なる場合は、Xplenty側でスキーマを変更するオプションはありますか？
A.データベースでA、B、Cのフィールドを持つスキーマ構造に対し、A、B、C、Dのデータを持つ場合、スキーマ構造を変更し、フィールドDをテーブルに追加するオプションがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/d27e42a4-5bb4-b232-9020-527fee3888b0.png)

注意：ある日データソースで勝手に列フィールドが増えていて、それを自動的に検知し、ジョブ定義に自動的に反映する機能はありません。このオプションは、あくまで増えたフィールドに対応する形でジョブ定義をマニュアルで変え、それにより、Xplentyからデータベースに対してAlter tableを実行し、スキーマ構造を変更することができる機能です。

###柔軟なSQLによる前処理/後処理が可能
さらに、より柔軟にデータベースを制御できるようにデータのロード前と後の両方でSQL実行をサポートしています。これにより、例えば、ELTシナリオの場合、データを一度DWH側に投入し、投入後にSQLを利用してViewを作成したり、投入後のデータをUpdate文で加工するなど、柔軟に行うことができます。また、ロード前にテーブルを作成したり、xxx日以前のデータは削除する、もしくは一括で論理削除するといった処理も可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/9bcbf353-ce51-1927-571f-b254a000a830.png)

#データベースへ書き込む際のMergeオプションとその動きについて
データベースに書き込む際に以下の２種類のMergeオプションを選択可能です。それぞれの処理の特徴を理解し、正しいオプションを選択してください。
###Merge with existing data using delete and insert
これから書き込むデータと書き込み先のテーブルの両方に存在する（Upsertキーが重複する）レコードについて書き込み先のテーブル削除してから、すべてのデータをターゲットテーブルに挿入することで、データをテーブルの既存データにマージします。フィールドマッピングでUpsertキーを正しく設定する必要があります。マージは次のような手順で行われます。

- Step1 ： データベースのデフォルト・スキーマのキー・マッピングに従って、主キーを持つステージング・テーブルが作成されます。
- Step2 ： データフローの出力がステージング・テーブルに一括コピーされます。
- Step3 ： ステージング・テーブルに存在するキーを持つ行がターゲット・テーブルから削除されます。ステージング・テーブルのすべての行がターゲット・テーブルに挿入されます。ステージング・テーブルが削除(Drop)されます。

###Merge with existing data using update and insert
既存のデータに対してはUpdateし、新しいデータはInsertすることで、入力されたデータをテーブルの既存のレコードに対しマージします。フィールドマッピングでマージキーを正しく設定する必要があります。マージは次のような手順で行われます。

- Step1 ： データベースのデフォルト・スキーマのキー・マッピングに従って、主キーを持つステージング・テーブルが作成されます。
- Step2 ： データフローの出力がステージング・テーブルに一括コピーされます。
- Step3 ： データベース固有のコマンドが発行され、既存のレコードが更新され、挿入されます。ステージング・テーブルは削除(Drop)されます。

#最後に
データベースの場合のオプションを正しく理解することで、よりきめ細かい設定が可能になります。また、データベースに関連するJDBC関連の[システム変数](https://qiita.com/Azabu10ban/items/ab7a054e1391eb1d1727)パラメータの設定も可能です。
【AWS】Wordpress「返答が正しいJSONレスポンスではありません」の対処法

#現象
Amazon LinuxインスタンスでWordpressをたてた。その際パーマリンクを基本→投稿名に変更して記事を投稿しようとするも、「返答が正しいJSONレスポンスではありません」とエラーが出て投稿できない＆トップページ以外が表示できなくなってしまった。
<img width="1029" alt="スクリーンショット 2020-07-09 10.48.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/d69dd1ab-e448-fdef-e86a-779a52e3c660.png">


[wordpress返答が正しいJSONレスポンスではありません](https://tuku-tano.com/index.php/2019/12/11/wordpress/apache2permanentlink/)
上記記事でapache設定が原因とわかった。

```
sudo vi /etc/apache2/apache2.conf
```

記事の通り上記コマンドで設定ファイルに入ろうとするも、Amazon Linuxではそのようなファイルがなかった。
Amazon LinuxはRedHat系ベースに対し、上のものはDabianの設定ファイルになっているためだ。

参考
http://www.linux.net-japan.info/install08.html
https://www.acrovision.jp/service/aws/?p=653

#対処法
AWSドキュメントに方法が書いてあった。
[WordPress がパーマリンクを使用できるようにするには](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/hosting-wordpress.html)

1.該当のインスタンスに接続した上で、下記コマンドでファイルに入る。

```
sudo vim /etc/httpd/conf/httpd.conf
```

2.`<Directory "/var/www/html"> `で始まるセクションを見つける。（※複数の AllowOverride行があるため、間違えないように。必ず `<Directory "/var/www/html"> `セクションの行を探す。vimで`/html`と検索すると、すぐ見つかる。)

```
<Directory "/var/www/html">
    #
    # Possible values for the Options directive are "None", "All",
    # or any combination of:
    #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
    #
    # Note that "MultiViews" must be named *explicitly* --- "Options All"
    # doesn't give it to you.
    #
    # The Options directive is both complicated and important.  Please see
    # http://httpd.apache.org/docs/2.4/mod/core.html#options
    # for more information.
    #
    Options Indexes FollowSymLinks

    #
    # AllowOverride controls what directives may be placed in .htaccess files.
    # It can be "All", "None", or any combination of the keywords:
    #   Options FileInfo AuthConfig Limit
    #
    AllowOverride None

    #
    # Controls who can get stuff from this server.
    #
    Require all granted
</Directory>
```

3.上のセクションを`AllowOverride None`行を`AllowOverride All`に変更。(None→All)

4.ファイルを:wqで保存する。

5.上記設定を反映させるため、`sudo systemctl restart httpd.service`で再起動させる。`sudo systemctl status httpd.service`で念のためアクティブになっているか確認。

上記設定をするとパーマリンクを基本以外にしても、記事の投稿ができたりトップページ以外も参照できるようになる。
VC++2012でフォーマット指定子

VC2013だったら可変長引数テンプレートを利用してCStringの`Format`のようなものを作れたが、Visual C++ 2012では非対応。

調べてみると、stack overflowで使えるものがあったので使いやすく少し修正したものを載せておきます。

＞https://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprintf/8098080

```c++

#include <cstdarg>
#include <memory>
#include <string>

std::string string_format(const std::string fmt_str, ...)
{
	auto n = 256; // 十分なサイズを確保
	std::unique_ptr<char[]> formatted;
	va_list ap;
	while (true)
	{
		formatted.reset(new char[n]);
		strcpy_s(&formatted[0], _TRUNCATE, fmt_str.c_str());
		va_start(ap, fmt_str);
		const auto final_n = _vsnprintf_s(&formatted[0], n, _TRUNCATE, fmt_str.c_str(), ap);
		va_end(ap);
		if (final_n < 0 || final_n >= n)
			n += abs(final_n - n + 1);
		else
			break;
	}
	return std::string(formatted.get());
}

```

## 使い方

```c++
std::cout << string_format("%d %e %s", 1,1.0/3,"Hello World!") << std::endl;
// 1 3.333333e-001 Hello World!
```
[Hyperledger Iroha]Pythonライブラリからクエリを実行すると[bad timestamp: sent from future]が返ってくる

# 内容
ちょっとしたことですが対応方法をメモ

# エラー内容
Hyperledger Irohaのライブラリを使ってRoleを取得するクエリを実行する

~~~ get_role.py
from iroha import Iroha, IrohaCrypto, IrohaGrpc
import iroha_config

net = IrohaGrpc(iroha_config.IROHA_HOST)

iroha = Iroha(iroha_config.ADMIN_ACCOUNT)
admin_priv_key = iroha_config.ADMIN_PRIV_KEY

# Queryの作成
get_block_query = iroha.query(
    'GetRoles'
)

# Transactionへ署名
IrohaCrypto.sign_query(get_block_query, iroha_config.ADMIN_PRIV_KEY)

# Transactionの送信
response = net.send_query(get_block_query)
print(response)
~~~
エラーの内容

~~~
error_response {
  message: "Query: [[bad timestamp: sent from future, timestamp: 1594256328577, now: 1594147827999 ]]\n"
}
query_hash: "e4567087a82943225e0a774cf4b4349a62f35854f947b8ecf78039a945ae3858"
~~~

# エラーの原因と対応策
Pythonを動かしているクライアントとirohaを動かしているVMの時間がずれていたことが原因

以下のコマンドで時間を合わせる

~~~
# ntpdate ntp.nict.jp
 9 Jul 10:18:36 ntpdate[8383]: step time server 133.243.238.244 offset 108402.649465 sec
~~~

# 実行結果
エラー対応後の実行結果

~~~
roles_response {
  roles: "admin"
  roles: "user"
  roles: "money_creator"
}
query_hash: "9b27f830f9a388590a9131f7960b4d3aca8908614cc89fa6631c11d5365196b8"
~~~
Homebrew から Python が消えた・・・

# まとめ

- ``Homebrew``にある``python``のフォーミュラ名が ``Deleted Formulae`` になっていた
  - ``python`` から ``python3.7`` / ``python3.8`` とバージョン付きに変更になったみたい
- ``pip3``を使ってパッケージをアップデートしようとしたらエラーがでて困った・・・
  - ``pip3.8`` を使って ``pip`` をアップデートする必要があった

```bash
$ pip3.8 install -U pip
```


---

# TL:DR;

## フォーミュラの更新を確認した

- いつもどおり``brew update``でフォーミュラの更新がないか確認した
- ``Deleted Formulae`` に ``python`` とあって少しだけ「大丈夫かな？」と思った

```bash
$ brew update
Updated 3 taps (homebrew/cask-versions, homebrew/core and homebrew/cask).
==> New Formulae
python@3.7    （他のフォーミュラは省略）
==> Updated Formulae
python@3.8 ✔  （他のフォーミュラは省略）
==> Deleted Formulae
python ✔
```

## 更新されたフォーミュラをインストールした

- 特に注意もせず、いつもどおり ``brew upgrade`` を実行した
  - ``python 3.8.3`` から ``3.8.3_1``にアップグレードされた
- 引き続き ``python3`` コマンドで使えることを確認した
  - ``python3 --version`` で動作確認

```bash
$ brew upgrade
==> Upgrading 1 outdated packages:
python@3.8 3.8.3 -> 3.8.3_1
==> Pouring python@3.8-3.8.3_1.catalina.bottle.tar.gz
（いろいろ省略）
See: https://docs.brew.sh/Homebrew-and-Python
==> Summary
🍺  /usr/local/Cellar/python@3.8/3.8.3_1: 4,125 files, 63MB
==> Upgrading python@3.8 3.8.3_1 -> 3.8.3_1 
Removing: /usr/local/Cellar/python@3.8/3.8.3... (4,173 files, 63.9MB)

$ python3 --version
Python 3.8.3
```

## ``pip3``の更新も必要だった

-  パッケージの更新がないか確認しようとしたら、エラーに遭遇
  - ``3.7用pip``だから使えないよ、みたいなエラー
  - ``pip3 install -U pip``が実行できないから詰んだ、と思った
- ``pip3``と打って、タブ補完したら``pip3.8``があることを見つけた
- ``pip3.8 install -U pip`` したら無事に使えるようになった

```bash
## pip3のバージョンを確認しただけでエラー
$ pip3 --version
Failed to execute process '/usr/local/bin/pip3'. Reason:
The file '/usr/local/bin/pip3' specified the interpreter '/usr/local/opt/python/bin/python3.7', which is not an executable command.

## pip3.8が使える
$ pip3.8 --version
pip 20.0.2 from /usr/local/lib/python3.8/site-packages/pip (python 3.8)

## pip3自身をアップデート
$ pip3.8 install -U pip
Collecting pip
  Using cached pip-20.1.1-py2.py3-none-any.whl (1.5 MB)
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 20.0.2
    Uninstalling pip-20.0.2:
      Successfully uninstalled pip-20.0.2
Successfully installed pip-20.1.1

## pip3がアップデートされたことを確認
$ pip3 --version
pip 20.1.1 from /usr/local/lib/python3.8/site-packages/pip (python 3.8)
```

## 全パッケージの再インストールも必要だった

- 昨日まで動いていたPythonスクリプトが動かなくなっていた
  - ``streamlit``を使ったスクリプト
  - 原因は ``pip3`` のときと同じ
- インストール済みのパッケージを確認したら、ごくわずかになっていた
  - エラーに遭遇するたびにインストールし直すしかなさそう
  - ちゃんと ``pyproject.toml`` を作っておけば、こんなときに便利なのだろう（``poetry``見習い）

```bash
$ streamlit run app.py
Failed to execute process '/usr/local/bin/streamlit'. Reason:
The file '/usr/local/bin/streamlit' specified the interpreter '/usr/local/opt/python/bin/python3.7', which is not an executable command.

$ pip3 list 
Package    Version
---------- -------
-BB        0.1
gpg        1.13.1
pip        20.1.1
protobuf   3.12.3
setuptools 49.1.0
six        1.15.0
tbb        2019.0
wheel      0.34.2
```
Rust でテキストファイルの読み込み

こちらで作成したテキストファイルを読みます。
[Rust でテキストファイルの作成](https://qiita.com/ekzemplaro/items/fa21c2fb7123cbad3c6c)

```rs:text_read.rs
// --------------------------------------------------------------------
/*
	text_read.rs

						Jul/09/2020
*/
// --------------------------------------------------------------------
use std::env;
use std::error;
use std::fs::File;
use std::io::{BufRead, BufReader};

fn main() -> Result<(), Box<dyn error::Error>> {

eprintln!("*** 開始 ***");

let args: Vec<_> = env::args().collect();

let ref fname_in = args[1];

for result in BufReader::new(File::open(fname_in)?).lines() {
	let ll = result?;
	println!("{}", ll);
	}

eprintln!("*** 終了 ***");
Ok(())

}
// ---------------------------------------------------------------------
```

```text:Makefile
text_read: text_read.rs
	rustc text_read.rs
clean:
	rm -f text_read
```

コンパイル

```text
$ make
rustc text_read.rs
```

実行

```text
$ ./text_read cities.txt 
*** 開始 ***
t2381	名古屋	71842	2005-9-12
t2382	豊橋	14278	2005-3-15
t2383	岡崎	65291	1950-10-2
t2384	一宮	31864	1950-6-22
t2385	蒲郡	49158	1950-8-14
*** 終了 ***
```

## 確認したバージョン

```text
$ rustc --version
rustc 1.75.0 (82e1608df 2023-12-21) (built from a source tarball)
```
Sequel AceでMySQLに接続する(Sequel Proの後継)

ついにSequel Proの後継アプリが登場しました！！

Sequel Proの正式版が[MySQL8.0に対応しないまま](https://github.com/sequelpro/sequelpro/issues/2699)月日が流れ...

ついに Sequel Pro に続く、MySQL・MariaDBデータベースを操作するための高速で使いやすいMacデータベース管理アプリケーションが登場しました！！

## Sequel Ace

![68747470733a2f2f73657175656c2d6163652e636f6d2f696d616765732f61707049636f6e2d313032342e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/83431afe-0e28-a3c5-389a-2e38d53ad722.png)

https://sequel-ace.com
https://github.com/Sequel-Ace/Sequel-Ace

応援したい人はぜひコントリビューターに！

## 料金

- 無料

## 動作環境

- macOS >= 10.10
- MySQL >= 5.6
- MariaDB

## インストール方法

### Homebrew からインストール

```
$ brew install mas-cli/tap/mas
$ mas install 1518036000 # Sequel Ace
```

### App Store からインストール

https://apps.apple.com/us/app/sequel-ace/id1518036000

## 試しにMySQLへ接続

<img width="948" alt="ScreenShot 2020-07-09 11.33.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/83b8f2aa-acac-41a7-08c8-c819cedb38ad.png">

<img width="1447" alt="ScreenShot 2020-07-09 11.53.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/527816d1-33fc-1c19-24c7-ae331f3471ac.png">

MySQL 8.0.19 に接続してみました。
UIもSequel Proと変わらなくて使いやすいです😆

## 参考

- [Sequel Ace MySQL Client for MacOS](https://laravel-news.com/sequel-ace-mysql-client-for-macos)
- [MySQL8.0.x に Sequel Pro で接続する](https://qiita.com/ucan-lab/items/b68db1db931c954da921)
Rust でテキストファイルの作成

Ubuntu 24.04 で Rust のインストール

```bash
sudo apt install rustc
```

インストールされたバージョン

```text
$ rustc --version
rustc 1.75.0 (82e1608df 2023-12-21) (built from a source tarball)
```

```rs:text_create.rs
// --------------------------------------------------------------------
/*
	text_create.rs

						Jul/09/2020
*/
// --------------------------------------------------------------------
use std::env;
use std::fs::File;
use std::io::{Write};

fn main() -> std::io::Result<()> {

eprintln!("*** 開始 ***");

let args: Vec<_> = env::args().collect();

let ref fname_out = args[1];

let mut file = File::create(fname_out)?;
file.write_all(String::from("t2381\t名古屋\t71842\t2005-9-12\n").as_bytes())?;
file.write_all(String::from("t2382\t豊橋\t14278\t2005-3-15\n").as_bytes())?;
file.write_all(String::from("t2383\t岡崎\t65291\t1950-10-2\n").as_bytes())?;
file.write_all(String::from("t2384\t一宮\t31864\t1950-6-22\n").as_bytes())?;
file.write_all(String::from("t2385\t蒲郡\t49158\t1950-8-14\n").as_bytes())?;
eprintln!("*** 終了 ***");
Ok(())

}

// --------------------------------------------------------------------
```

```text:Makefile
text_create: text_create.rs
	rustc text_create.rs
clean:
	rm -f text_create
```

コンパイル

```text
$ make
rustc text_create.rs
```

実行

```text
$ ./text_create cities.txt
*** 開始 ***
*** 終了 ***
```
テスト関連用語の英語表現

テスト関連用語(開発関連も含む)はそもそもカタカナ英語で既に使われている用語も多いので、
そんなものは除外し、よく使う用語だけピックアップ。
並び順はてきとー

|  日本語 | 英語 | 備考 |
| --- | --- | --- |
|  テスト設計 | Test Design | カタカナ英語の「デザイン」のイメージが強すぎて一瞬ピンとこない |
|  テスト条件 | Test conditions | カタカナ英語の「コンディション」のイメージが強すぎて一瞬ピンとこない |
|  テスト対象 | Test object |  |
|  境界値分析 | Boundary Value Analysis | 略語はBVA |
|  同値分割 | Equivalence Partitioning: |  |
|  状態遷移 | State Transition |  |
|  状態遷移図 | State transition diagram |  |
|  状態遷移表 | State Transition Table |  |
|  エラー推測 | Error Guessing |  |
|  探索的テスト | Exploratory Testing |  |
|  回帰テスト | Regression Testing |  |
|  再テスト | Re-Testing |  |
|  非機能テスト | Non-functional testing | 「機能テスト」は「Non-」を外せばいいだけ |
|  受け入れテスト | Acceptance testing |  |
|  性能テスト | Performance testing | ロードテスト(Load testing)とごっちゃになりやすいが、ロードテストは性能テストの中の一種 |
|  期待結果 | Expected result |  |
|  実際の結果 | Actual results | バグレポートの時につかうやつ |
|  殺虫剤のパラドックス | Beware of the pesticide paradox | ソフトウェアテストの7原則に出てくるやつ |
|  市販ソフトウェア | Commercial off-the-shelf | 略語はCOTS |
|  カンバン | Kanban | アジャイルな開発で使うフレームワークのやつ |
|  本番環境 | Production environment. |  |
|  セキュリティの脆弱性 | Security vulnerabilities |  |
|  品質特性 | Quality characteristics |  |
|  確認テスト/改修確認 | Confirmation testing: | 日本語の方は、現場によると思うが「確認テスト」という言い方より「改修確認」と言われている方が多い気がする・・・ |
|  動的テスト | Dynamic testing | カタカナ英語の「ダイナミック」のイメージが強すぎて、一瞬ピンとこない |
|  振る舞いベースの技法 | Behavior-based techniques | 「振る舞いベースの技法」なんて回りくどい言い方はせず、普通にブラックボックステストと言えばいい |
|  構造ベースの技法 | Structure-based techniques | 「構造ベースの技法」なんて回りくどい言い方はせず、普通にホワイトボックステストと言えばいい |
|  開始基準 | Entry criteria | 「Start criteria」と言ってしまいそう。伝われば別にどっちもでいいのかも |
|  終了基準 | Exit criteria | 「End criteria」と言ってしまいそう。伝われば別にどっちもでいいのかも |
|  非機能特性 | Non-functional characteristics |  |
|  再評価 | Re-evaluating |  |
|  偽陽性 | False positives | 「偽陽性」という、人生のうちでたぶん数回しか使わない日本語・・・ |
|  再実行性 | Repeatability | 繰り返し実行する時のやりやすさ、みたいな時使うやつ |

関連資料
[【随時更新】テスト/開発現場で使われる略語集](https://test-hack.com/%e3%80%90%e9%9a%8f%e6%99%82%e6%9b%b4%e6%96%b0%e3%80%91%e3%83%86%e3%82%b9%e3%83%88-%e9%96%8b%e7%99%ba%e7%8f%be%e5%a0%b4%e3%81%a7%e4%bd%bf%e3%82%8f%e3%82%8c%e3%82%8b%e7%95%a5%e8%aa%9e%e9%9b%86/)
【AmazonConnect】キューとルーティングプロファイル作成

#概要
AmazonConnectでは外線からの通話をキューに振り分けることで、ユーザーに着信させることが出来ます。
また、ルーティングプロファイルをユーザに割り当てることでユーザーがどのキューから着信を受けるかを決めることが出来ます。

ここでは、キューとルーティングプロファイルの関係と作成方法に加え、任意のエージェントに着信させる方法ついてまとめたいと思います。

#キューの作成
AmazonConnectインスタンスには、デフォルトで"Basic Queue"というキューが存在します。
![Qiita用.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612635/07df2a15-954d-edb2-5205-a8ebbdbabe74.png)
画像の通りに進むとキューの管理画面に進むことが出来ます。
右上の「新しいキューの追加」からキューを作成できます。

今回はキューとユーザーの関係を一対一にしたいので、ユーザー分の数のキューを作成します。
![Qiita用３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612635/737074ab-0eea-165c-d9ab-43562248d6e4.png)
画像の通り、6つのキューを作成しました。

#ルーティングプロファイルの作成
こちらもデフォルトで"Basic Routing Profile"というプロファイルが存在します。
![Qiita用２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612635/0fb7571f-0798-6b9d-15ec-7b373e36d1ed.png)
画像通りに進むとルーティングプロファイルの管理画面に進むことができ、右上の「新しいプロファイルを追加」から新しいルーティングプロファイルを作成できます。

ルーティングプロファイルの作成時に着信を受けるキューを設定します。複数設定できますが、キューとユーザーの関係を一対一にするため、一つのみ設定します。

また、作成には「デフォルトのアウトバウンドキュー」を設定する必要があります。
発信通話の際に使用するキューなので、着信と同じキューを設定しても大丈夫ですし、発信用のキューを作成しても構いません。
![Qiita用４.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612635/22c987f2-3af5-8438-7800-4d3f09f596d7.png)
画像のようにキューの数だけルーティングプロファイルを作成しました。

#まとめ
この設定で問い合わせフローを適切に設定すれば、ユーザーが複数いる場合（今回は6人想定）に明示的にユーザーに優先順位をつけて着信させることが出来ます。

問い合わせフローに関する記事は以下のURLから⇓
【JavaScript】オブジェクト編

自分用の備忘録です。。。

#1.配列要素の挿入、削除
配列に要素を挿入したり、要素を削除する方法を見ていきます。

```js

const alphabet = [a, b, c, d, e];

// 先頭に要素を追加したい場合 => unshift
alphabet.unshift(追加したい要素);

// 先頭の要素を削除したい場合 => shift
alphabet.shift(); // 削除は１つずつしかできないので（）の中は空白

// 末尾に要素を追加したい場合 => push
alphabet.push(追加したい要素);

// 末尾の要素を削除したい場合 => pop
alphabet.pop(削除したい要素); // 削除は１つずつしかできないので（）の中は空白

// 追加と削除を同時に行う場合 => splice
alphabet.splice(変化が開始する位置[index], 削除数, 追加したい要素); 

alphabet.splice(１, ２, f, g); 
出力結果は　[a, f, g, d, e] になる
// b,cを削除してf,gが挿入された
```

#2.スプレット構文

スプレット構文は配列の中に配列を展開したいときに便利です。

```js

const alphabet = [a, b, c, d, e];
const others = [f, g, h, i];

const alphabet = [a, b, c, d, e, ...others]とすることで配列の中に配列を展開できる
```

#3.分割代入

分割代入とは、配列の要素を変数に代入したいときに使用します。

```js

const scores = [10, 20, 30, 40, 50];

const [a, b, c, d, e] = scores;　
上記記述により、
a = 10,
b = 20,
c = 30,
d = 40,
e = 50,
となり、別々の変数を割り当ててくれる
```

#4.forEach();
forEachをしようすることで、配列の要素を１つずつ出力することできます。

```js

const scores = [10, 20, 30, 40, 50];

scores.forEach((score, index) => {
  console.log(`- ${index + 1} 番目の点数は ${score} 点です`)；
});

// 出力結果
- 1番目の点数は10点です
- 2番目の点数は20点です
- 3番目の点数は30点です
- 4番目の点数は40点です
- 5番目の点数は50点です

```

#5.map();
mapは配列の要素に何らかの処理を加え、別の配列として新しく生成することができます。

```js

const scores = [10, 20, 30, 40, 50];
// 別の定数として、新しく配列をつくる
const scoreChange = scores.map((score) => {
  return score + 100;
});
console.log(scoreChange);
// 出力結果
[110, 120, 130, 140, 150]

```

#6.filter();
filterは条件に合う要素のみを抽出して別の配列として取得することができます。

```js

const numbers = [1, 4, 7, 8, 10];
// 2で割り切れた要素のみ抽出
const evenNumbers = numbers.filter(number => {
  return number % 2 === 0;
});
console.log(evenNumbers);
// 出力結果
[4, 8, 10]

```

#7.join();　split();

joinは配列要素を文字列として結合するときに使用します。

```js

const day = [2020, 07, 09];
day,join("/");
// 結果
2020/07/09
```

splitはjoinとは逆で文字列を配列要素として取得します。

```js

const day = "2020/07/09";
day,split(":");
// 結果
[2020, 07, 09]
```

#8.数値の操作

```js
Math.floor(); 小数点以下切り捨て
Math.ciel(); 小数点以下切り上げ
Math.round(); 四捨五入
Math.変数.toFixed(桁数指定); 桁数を指定
Math.random(); ０以上1未満の数値をランダムに生成
```

以上
連想配列の重複チェック 【Lodash, find】

# 概要
LodashのfindとArray.filterを利用して、連想配列の重複チェック&重複している物の配列と重複していない物の配列を作成します。

- [filter -Array](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
- [find - Lodash](https://lodash.com/docs/4.17.15#find)

## 実装

```javascript

const targetA = [
  {name: "taro"},
  {name: "ichiro"},
  {name: "tetsuto"},
  {name: "lisa"}
];

const targetB = [
  {name: "yuki"},
  {name: "ichiro"},
  {name: "takeya"},
  {name: "lisa"}
];

// 重複してるユーザーを取得
const duplicatedList = targetA.filter(user => {
  return _.find(targetB, user);
});

// 重複していないユーザーを取得
const originalList = targetA.filter(user => {
  return  !_.find(targetB, user);
});
```
## 結果
<img width="199" alt="スクリーンショット 2020-07-09 11.52.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278650/a2564f5b-21c3-592f-ad7e-e1531a20e918.png">
AWS SESでテストメールを送信すると「Email address is not verified」になる

AWS SESを使い、Domainの登録を済ませいざテストメールを自分のgmailアドレスにでも送ろうかと思ったらタイトルのエラーが出た。

## 原因
SESは最初の時点ではSandboxモードになっており、送信先が制限されていることが原因だった！  
Sandboxモードの時点では「送信元(From)」と「送信先(To)」は同じである必要がある、あるいは「EmailAdress」タブにて登録済みであるアドレスにしか送れない。  

![20191119125820.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55603/585bf3a4-0732-fa5a-06c5-3ae9d68aa48a.png)


上のとおり、FromとToを揃えたらエラーなく送信できた。  

## 解決策
それは良いとしてSandboxを解除して、普通に使用したい場合。  
左側のメニューより、「Sending Statistics」の画面に行くと「Reaquest a Sending License Limit Increase」というボタンがあるのでそれを押し手続きを踏むと制限が解除される。  
![20191119130002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55603/dfd9c6cb-52df-066e-f828-7768b93f4907.png)


以上！
EC2 インスタンスでMicrosoft.Office.Interop.Excel を利用するに関して

こんにちは！

オンプレミス環境からAWSのEC2インスタンスまでvb.NETのシステムを移行する作業やっています。
報告帳票のエクセルの出力するために、「Microsoft.Office.Interop.Excel」というライブラリを利用していますが、このライブラリが動かせるように、MS Officeをインストールする必要がある。

AWSのポリシーとしてはハードウェア専有インスタンス以外はMSOfficeをインストールするのは禁止ですので、
どうしたらいいですか。だれか経験があれば、教えていただけますでしょうか。

p/s: EC2インスタンスでMS Office 2003 (ライセンス不要) インストール可能ですか？
CentOS8 で Python3.8 と pip を使うための初期設定

### yumとdnf

CentOS8からは、7までと違って、**yumコマンドを使いません。**
ゴリ押しで、yumを使うこともできますが、おすすめしません。
後継となった**dnfコマンドを使っていきます。**

基本的には、yumコマンドとほとんど同じ使い方でOK
簡単にどんなところが違うかというと...

- yumコマンドはPython2系で動いている
- dnfコマンドはPython3系で動いている

Python3系で動かそうとするのは必然かなと

### Python3.8をインストールする

```
$ sudo dnf install python38 -y
```
####解説
- sudo
    - 管理者にコマンドを実行させるおまじない
- dnf
    - 前述したyumの後継
- install
    - インストールするおまじない
- python38
    - インストールしたいパッケージ名を指定 (Pythonの場合は、python2, python36, python38など)
- -y
    - 実行後に出てくるy/n?にすべてyを返す

コマンドを改めて見てもわかる通り、yumコマンドと大した差はありませんね

### Python3.8のバージョンを確認
```
//どっちかでおっけい
$ python3.8 --version 
Python 3.8.0
$ python3.8 -V
Python 3.8.0
```
####解説
- python3.8
    - pythonで標準として選択しているバージョンが呼ばれますが、python3.8のようにバージョンを指定することで任意のバージョンを呼び出せます (自身の環境にどのバージョンが入っているか見るなら、pythonまで打ち込みTabキーを2回押すと見れます)
- --version
    - バージョンを出力するオプションです (-Vでも代行可能)
- -V
    - バージョンを出力するオプションです (--versionでも代行可能)

###pipのバージョンを確認
```
//どっちかでおっけい
$ pip3.8 --version
pip 19.2.3 from /usr/lib/python3.8/site-packages/pip (python 3.8)
$ pip3.8 -V
pip 19.2.3 from /usr/lib/python3.8/site-packages/pip (python 3.8)
```

####解説
- pip3.8
    - python同様に、バージョンを指定できます.また、pipはpythonをインストールすることで、対応するバージョンが付いてきます
- --versionと-Vは前述同様です

###Python3.8をPythonで実行するために
毎回バージョンを指定しなきゃいけないのは億劫ですよね、そこで、デフォルトで3.8を使うように設定していきます

```
$ alternatives --config python

3 プログラムがあり 'python' を提供します。

  選択       コマンド
-----------------------------------------------
*+ 1           /usr/libexec/no-python
   2           /usr/bin/python3
   3           /usr/bin/python3.8

Enter を押して現在の選択 [+] を保持するか、選択番号を入力します: 3 //選択したい環境に合わせて、対応する数値を入力
```
####解説
- alternatives
    - 標準コマンドの切り替えなどが行えるコマンドです (Windowsの既定のアプリを選択できる感じ)
- --config
    - 設定を変更できます
- python
    - この部分にパッケージ名を指定することで、そのパッケージのプログラムを一覧表示します

コマンドの部分に一覧されたプログラムの中から、標準で使いたいプログラムを選び、その番号を入力します
これによって、今までpython3.8と入力していたコマンドを、pythonのみで3.8のpythonが実行されます

###pip3.8をpipで実行するために
python3.8 -> pythonの手順では変更できず、別のコマンドを使うことになります

```
$ sudo update-alternatives --install /usr/bin/pip pip /usr/bin/pip3.8 1
```
####解説
- update-alternatives
    - コマンドの名前を変更すること等ができる (見かけ上の名前)
- --install
    - alternatives等で一覧するパッケージグループに追加する
- /usr/bin/pip
    - この部分には、シンボリックリンクの作成先を指定 (今回はpip)
- pip
    - この部分はプログラムの名前だと思いますが、私も詳しくわかっていないのでコメントくださるとうれしいです
    - 下記インフォにて追記情報を引用させていただいております。
    - 
:::note info
> 登録するときの名前じゃないですかね。管理上の。
:::

- /usr/bin/pip3.8
    - 追加したいプログラムが実際に格納されている場所を指定 (今回はpip3.8)
- 1
    - この部分も、詳しくわかっていないです. コメントくださるとうれしい...
    - 下記インフォにて追記情報を引用させていただいております。


###注意点
自分で手探りでpipを設定しようとしていた時に起きたので注意なのですが、下記コマンドで表示されているディレクトリは、実際にupdate-alternativesで指定するディレクトリでは無い、という点に注意です

```
$ pip3.8 -V
pip 19.2.3 from /usr/lib/python3.8/site-packages/pip (python 3.8)
```
###あとがき
上記までの手順で、無事にpythonとpipを扱いやすくできました。
これのおかげでAnsibleの勉強がしやすくなることでしょう、、

[Twitter](https://twitter.com/sc_ds_)
tempusdominusのDatatimepickerのスタイルが崩れる

bootstrap4スタイル用のDatetimepickerで利用させてもらっている
tempusdominus版のdatetimepickerモジュールですが、
いつの間にかデザインがずれているのに気づく。

原因はtempusdominus用のスタイル(css)を使用していなかったため

```bash
npm install --save tempusdominus-bootstrap-4
```

laravelなら`resources/sass/app.scss`に以下を追加

```sass
@import '~tempusdominus-bootstrap-4/src/sass/tempusdominus-bootstrap-4-build'; 
```

`npm run dev`してブラウザの再読み込みで直った。
MapKitで国土地理院のタイルデータを表示する

iOSの `MapKit` は地図の上にデータをオーバレイすることができます。
一方、国土地理院では[日本地図に関わる様々なデータを公開](https://maps.gsi.go.jp/development/ichiran.html)しているのですが、実は簡単に `MKMapView` へ表示することができちゃいます。

<img width="50%" alt="スクリーンショット 2020-07-09 11.17.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25727/e324e8de-ab3f-c3be-8f12-a9c92011b56f.png">

```swift:ViewController.swift
import UIKit
import MapKit

class ViewController: UIViewController {

    @IBOutlet weak var mapView: MKMapView!

    // 国土地理院が提供する色別標高図のURL
    // ここを変えるだけで、様々な地図データを表示できる！
    private let tileOverlay = MKTileOverlay(urlTemplate: "https://cyberjapandata.gsi.go.jp/xyz/relief/{z}/{x}/{y}.png")
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        mapView.delegate = self
        mapView.addOverlay(tileOverlay, level: .aboveLabels)
    }
}

extension ViewController: MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        return MKTileOverlayRenderer(overlay: overlay)
    }
}
```

透過率を付けて重ね合わせたい場合は `MKOverlayRenderer` の `alpha` 値を調整します。

```swift
    @IBAction func sliderDidChange(_ slider: UISlider) {
        if let renderer = mapView.renderer(for: tileOverlay) {
            renderer.alpha = CGFloat(slider.value)
        }
    }
```

**治水地形分類図** などは昨今の水害への対応に何かに活用できるのではないかと。

<img width="50%" alt="スクリーンショット 2020-07-09 11.35.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25727/146bba6b-0221-f959-a8ce-66baa2c45c9f.png">

各データには[利用規約](https://www.gsi.go.jp/kikakuchousei/kikakuchousei40182.html)がありますので、利用の際には注意を払っておくと良さそうです。
Azure Application GatewayからくるIPアドレスをクライアントのIPアドレスにする【Apache Tomcat】

# はじめに
最近Azure Application Gatewayを触る機会があったのでその時の備忘録として。

クライアント⇒Application Gateway⇒WEBサーバーという経路でリクエストを受けた場合、WEBサーバーに記録されるリクエストのIPアドレスはクライアントのものではなく、Application GatewayのIPアドレスになります。（当たり前ですが）
そのためWEBサーバー側でアクセスログを取っていたり、IPアドレス制限などの仕組みが実装されている場合は正しく動作しなくなるため、WEBサーバーに届くIPアドレスをクライアントのIPアドレスにする必要があります。

# やったこと
## X-Forwarded-Forの確認
まずリクエストのどこかにクライアントのIPアドレスが含まれていないとどうしようもありません。
そこでApplication Gatewayの仕様を調べたところちゃんとX-Forwarded-Forをサポートしていました。

>X-Forwarded-For とは、HTTPヘッダフィールドの一つ。HTTPプロキシサーバまたは負荷分散装置を経由してウェブサーバに接続するクライアントの送信元IPアドレスを特定する際のデファクトスタンダードである。

上記の説明の通り、クライアントのIPアドレスがHTTPヘッダ内にあることがわかりました。

## Apache Tomcatの設定
Tomcatを使用しているため以下の設定をserver.xmlに追記します。

```server.xml
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="x-forwarded-for" proxiesHeader="x-forwarded-by" protocolHeader="x-forwarded-proto" />
```

この設定を入れることでX-Forwarded-Forの値でIPアドレスを書き換えてくれるようになります。

[Class RemoteIpValve](https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/valves/RemoteIpValve.html)

## 確認
設定完了と思って動作確認してみました。
すると記録されるIPアドレスが以下のような形式になっていました。

**XXX.XXX.XXX.XXX:YYYY**

どうやらApplication Gatewayのv1ではX-Forwarded-Forに設定される値は「クライアントIP:ポート番号」の形式で設定されるみたいです。

## 回避策を探す
調べてみたところApplication Gatewayをv2にすることで、カスタムヘッダの設定ができるようになり、ポート番号を含まない形式で値をセットできるみたいです。

## v1からv2へ移行
以下に公式の手順がありますが、私は作り直しました。
[Azure Application Gateway と Web アプリケーション ファイアウォールを v1 から v2 に移行する](https://docs.microsoft.com/ja-jp/azure/application-gateway/migrate-v1-v2)

## カスタムヘッダーの設定
以下の公式ドキュメントを参考に設定を行います。

[X-Forwarded-For ヘッダーからポート情報を削除する](https://docs.microsoft.com/ja-jp/azure/application-gateway/rewrite-http-headers#remove-port-information-from-the-x-forwarded-for-header)


以上です。
Spofity視聴中の曲をSlackステータスに投稿 (macOS専用)

# Step 1: OAuth
これの「準備2」まで行う
（Slackワークスペースにアプリのインストールを行う必要がある）

https://qiita.com/keiya/items/b72f89e3a8a75121c02e



# Step 2: こちらのコードを持ってきて動かす
`APIKEY` に Step 1 で取ってきたアクセストークンをいれて、動かす
https://gist.github.com/jgamblin/9701ed50398d138c65ead316b5d11b26#gistcomment-2792595

```bash
#!/bin/bash

# from: https://gist.github.com/jgamblin/9701ed50398d138c65ead316b5d11b26#gistcomment-2792595
# by laurentfite@github

# Get it from here : https://api.slack.com/custom-integrations/legacy-tokens
APIKEY="XXXXXXXXXX"

trap onexit INT

function reset() {
    echo 'Resetting status'
    TEXT='Winter%20is%20coming%20(at%20last)'
    EMOJI='snowflake'
    curl -s -d "payload=$json" "https://slack.com/api/users.profile.set?token="$APIKEY"&profile=%7B%22status_text%22%3A%22"$TEXT"%22%2C%22status_emoji%22%3A%22%3A"$EMOJI"%3A%22%7D"  > /dev/null
}

function onexit() {
    echo 'Exiting'
    reset
    exit
}

while true; do
    state=$(osascript -e 'tell application "Spotify" to player state')

    date
    echo "Spotify: "$state

    if [[ "$state" != "playing" ]]; then
        reset
    else
        SONG=$(osascript -e 'tell application "Spotify" to artist of current track & " - " & name of current track')
        URLSONG=$(echo "$SONG" | perl -MURI::Escape -ne 'chomp;print uri_escape($_),"\n"')
        echo $SONG

        curl -s -d "payload=$json" "https://slack.com/api/users.profile.set?token="$APIKEY"&profile=%7B%22status_text%22%3A%22"$URLSONG"%22%2C%22status_emoji%22%3A%22%3Aheadphones%3A%22%7D"  > /dev/null
    fi

    sleep 60
done
```

さらに以下のように launchd に設定すれば、自動起動される
https://gist.github.com/jgamblin/9701ed50398d138c65ead316b5d11b26#gistcomment-2775093
[python] numpyのreshapeメソッドの-1の意味

numpyのreshapeは数値を指定することで、多次元配列を変形するメソッドであるが、-1を指定すると具体値を指定しなくてもメソッドが自動的にもう片方の数値から適当な数値を決めてくれる。

```python:要素数３のリストを１行３列の行列にする例
arr = [1,2,3]
print(len(arr))
# 3

narr1 = np.array(arr).reshape(1,3) 
print(narr1.shape)
# (1, 3)

narr2 = np.array(arr).reshape(1,-1)
print(narr2.shape)
# (1, 3)
```
apt-cacher-ng

## Dockerfile

```Dockerfile:Dockerfile
FROM ubuntu

RUN apt update \
 && apt install -y apt-cacher-ng

VOLUME ["/var/cache/apt-cacher-ng"]
EXPOSE 3142

CMD chmod 777 /var/cache/apt-cacher-ng \
 && /etc/init.d/apt-cacher-ng start \
 && tail -f /var/log/apt-cacher-ng/*

## /etc/apt/apt.conf
# Acquire::http::Proxy "http://192.168.0.6:3142";
# Acquire::https::Proxy "http://192.168.0.6:3142";

# export http_proxy=http://192.168.0.41:8888
# export https_proxy=$http_proxy
```

```sh:build.sh
docker build . -t tukiyo3/apt-cacher-ng
```

## docker-compose.yml

```yaml:docker-compose.yml
aptcache:
  image: tukiyo3/apt-cacher-ng
  restart: always
  ports:
    - "3142:3142"
  volumes:
    - ./etc/acng.conf:/etc/apt-cacher-ng/acng.conf
    - ./cache/:/var/cache/apt-cacher-ng
```

* https接続するために acng.conf に以下追記

```go:etc/acng.conf
PassThroughPattern: .*
```

```go
docker-compose up
```


## aptのproxy設定

* /etc/apt/apt.conf に以下追記

```go:/etc/apt/apt.conf
Acquire::http::Proxy "http://192.168.0.6:3142";
Acquire::https::Proxy "http://192.168.0.6:3142";
```

* 後は普通に`apt`を使う。

```sh
# ダウンロードだけ行う場合
apt dist-upgrade --download-only
```
【FileMaker】【パスが無効です】macOS CatalinaにFileMaker Server18をインストール

## 問題
macOs Catalinaで稼働しているFileMaker Server 18のバックアップフォルダを外付けSSDに設定すると、「パスが無効」ですと表示される。

FM公式の[有効なフォルダのヒント](https://fmhelp.filemaker.com/help/18/fms/ja/index.html#page/FMS_Help%2Ftips-valid-folders.html%23ww1031128)を確認しても問題ない。

## 対処方法
システム環境設定＞セキュリティとプライバシー＞プライバシー＞フルディスクアクセスに下記を追加する。

```
fmserver_helperd
fmserverd
```
## 場所
/ライブラリ/Filemaker Server/Database Server/bin/
##
javascript　繰り返しの文　


#はじめに
自分用のjavascriptの学習メモです。


# for文の基本形

##for ofの基本形
```javascript
const scores = [10,20,30]

for ( score of scores){
  console.log(score);
}

```


##for文の基本形

```
for(初期値; 繰り返す条件; 増減){}
```

例文

```javascript

for (let i = 0; i < 10; i++ ){
  console.log(i);
}

```
上記は1から９が返る

#switchの場合

```javascript

const date = 2;

switch(date){
  case 1:
    console.log('１です');
    break;
  case 2:
    console.log('2です');
    break;
  case 3:
    console.log('3です');
    break;
  default:
    console.log('該当しません');
    break;
}


======================
//簡単に書ける⬇️

if (date === 1){
  console.log('１です');
}
if (date === 2){
  console.log('2です');
}
if (date === 3){
  console.log('3です');
}
```
【C#】try-catch

★try-catchの記述方法
・tryブロックには例外[^1]の可能性がある処理を記述
・catchブロックには例外[^1]が発生した場合の処理を記述
・finallyブロックには例外[^1]の有無関わらず実行する処理を記述

```C#
try
{
    //例外発生の可能性のある処理を記述
}
catch
{
    //例外が発生した場合の処理を記述
}
finally
{
    //例外の発生有無に関わらず実行する処理を記述
}
```
<br>(例)

```text:Test.txt
ささみの味噌煮
```
```C#:try-catchの記述方法
using System
class SampleTryCatch
{
    static void Main()
    {
        StreamReader sr = null;
        try
        {
            sr = new StreamReader(@"D:Test.txt",Encoding.GetEncoding("Shift_JIS"));
            string str = sr.ReadToEnd();
            Console.WriteLine(str);
        }
        catch (IOException e)
        {
            Console.WriteLine("例外が発生しました。");
            Console.WriteLine(e);
            return 0;
            //またはスルーさせる
            //throw;
        }
        finally
        {
            if(sr != null)
            {
                sr.Close();
                Console.WriteLine("ファイルを閉じました");
    }
```
実行結果

```
ささみの味噌煮
ファイルを閉じました
```

---
★例外フィルター
・catch句にwhen句を記述することによって例外条件を記述できる
・when句がある場合、catch句に同名型を複数使用できるが、上位から順に処理される

```C#:例外条件の記述方法
try
{
    //例外発生の可能性のある処理を記述
}
catch(例外) when(条件)
{
    //例外が発生した場合の処理を記述
}
```

[^1]: 例外クラスの一覧は[こちら](https://qiita.com/sasami_dc2/items/8bea9139a91281dc6037)
【C#】例外処理クラス一覧

|クラス名|throw条件|
|:--|:--|
|**名前空間:System**|－－－－－－－－|
|ArgumentException|メソッドの引数がない<br>ArgumentNullExceptionやArgumentOutOfRangeException以外|
|ArgumentNullException|引数がNull|
|ArgumentOutOfRangeException|メソッドの許容範囲外の値が引数として渡された|
|ArithmeticException|算術演算によるエラーの基本クラス<br>OverflowException,DivideByZeroException,NotFiniteNumberException以外の算術エラーを示したいとき|
|OverflowException|算術演算やキャストでオーバーフローが起きたとき|
|DivideByZeroException|0で割ったとき|
|NotFiniteNumberException|浮動小数点数値が無限大のとき|
|FormatException|引数の書式が仕様に一致していない場合|
|IndexOutOfRangeException|配列のインデックスが異常なとき|
|InvalidCastException|無効なキャストのとき|
|InvalidOperationException|引数以外が原因のとき|
|ObjectDisposedException|Dispose済みのオブジェクトで操作が実行されたとき|
|NotImplementedException|メソッドが未実装の場合|
|NotSupportedException|呼び出されたメソッドがサポートされてないとき<br>もしくは呼び出された機能を備えておらず、ストリームに対して読み取り、シーク、書き込みが試行されたとき|
|NullReferenceException|Nullオブジェクト参照を逆参照しようとしたとき|
|PlatformNotSupportException|特定のプラットフォームで機能が実行されないとき|
|TimeoutException|指定したタイムアウト時間が経過したとき|
|**名前空間：System.Collections.Generics**|－－－－－－－－|
|KeyNotFoundException|コレクションに該当するキーがないとき|
|**名前空間：System.IO**|－－－－－－－－|
|DirectoryNotFoundException|ディレクトリが存在しないとき|
|FileNotFoundException|ファイルが存在しないとき|
|EndOfStreamException|ストリームの末尾を超えて読み込もうとしたとき|
Qiitaでスマホ画面キャプチャがめっちゃデカいので仕様を確認した件

スマホ画面のキャプチャがめちゃデカのページがあったので気になり、仕様を確認しました。

編集画面で、Windows10上のChromeで画像を選択
<img width="375" alt="ファイル_001.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243968/f7b5d74c-e2a0-1816-f55b-88118b2704d3.png">
<img width="375" ... というタグが挿入されました。幅が指定されています。
そんなに大きくはないです。

じゃスマホで編集してたとか？
iPhoneのChromeで画像を選択
<img width="375" alt="01BB2E4F-4338-4259-B8A4-7B16196990B8.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243968/413cc245-cad6-5775-65b1-bd19ce3a4fe1.png">
さっきと変わらない。

↑で自動生成されたimgタグの「width="375"」を削除したら・・
<img alt="01BB2E4F-4338-4259-B8A4-7B16196990B8.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243968/413cc245-cad6-5775-65b1-bd19ce3a4fe1.png">
そりゃでかくなるよね！！

良い子はwidthを削除しちゃダメ！
GuzzleのJSONでのPOSTに大変苦労したお話

##who are you?
Guzzle使うから〜と聞いた時に本当に１mmも知りませんでした（）

ギリギリcurlは触ったことはあるし、ただいつもAPIへ通信していたのが、
何故かajaxばかりの環境で育ってきた僕

育ってきた環境が違うから〜知らない言語はしょうがない〜

・・・（ー＿ー）

それでもGuzzleを使うと言うことであれば、
やらなきゃならない事がある＞＜

・・・


###環境
PHP:7系
Guzzle:6系
Laravel:7系（例題はLaravelでの実装ですが他もほぼほぼ変わらないと思います）

###Guzzleを使ったAPI通信

```GuzzleSampleController.php

    $client = new Client();

    $options = [
        'header' => [
            'Authorization' => $token,
            'Content-Type' => 'application/json',
        ],
        'form_params' => [
            'id1' => $id1,
        ],
    ];

$response = $client->request('POST', $url, $option);

```

上の形でresponseが取得出来るはずです

ではJSONで送りたい場合は？

###JSONでのPOST

```GuzzleSampleController.php
    $client = new Client();

    $headers = [
        'Authorization' => 'Bearer ' . $token,
        'Content-Type' => 'application/json',
    ];
    $options = [
        'id1' => $id1),
    ];

    $response =  $client->request('POST', $url, [
        'json' => $options,
        'headers' => $headers,
    ]);
```


###Guzzleを使ってみた感想
PHPからAPIを叩く事がなかったので、じゃあなんで今までajaxにばかり頼る所にしか
いなかったのか。
そこは同期か非同期かの違いだけなのかな？
ただあまり処理があっちこっち飛んだり
PHPからJSに値渡さないといけないし
やることがバラバラになるイメージがあるので、PHPだけで完結するのもありなのだなと
今回の習得した結果です


###コメントください
ツッコミとかなんでも、、、もしあればコメント頂けると
今後の励みにしたいと思います。

ありがとうございました。
Swiftで文字列に文字を追加する

Google Books APIを使用する際、http通信になってしまいATS制限に引っかかったので対処法を備忘録として記しておきます。


#http -> https

```
var url = "http://www.google.com"

let insertIndex = url.index(previewLink.startIndex, offsetBy: 4)
url.insert(contentsOf: "s", at: insertIndexToPreviewLink)

print(url)  // "https://www.google.com"
```

# 別記
ATS制限には、Info.plistを編集を編集することでも対応できる。

#参考
[Swiftで指定したindexに文字・文字列を挿入する方法](https://swift.tecc0.com/?p=150)
[[iOS] ATS対応徹底攻略！対応策とInfo.plistより行うATSの設定値まとめ](https://dev.classmethod.jp/articles/ios-ats-cheats-info-plist-settings/)
cshで複数行のコメントアウト

複数行を一度にコメントアウトしたいとき、


```
<< コメントアウト文

コメントアウト文
```

で囲む。
<BR>

shやbashでは問題なかったのですが、
cshではエラーが出てしまいました。
うまくいったものがこちら。

```sh:Hello_1.csh
#!/bin/csh

echo "Takato    : Hello, Nadeshiko!"
echo "Nadeshiko : Hello Takato."

:<< 'COMMENT_OUT'

echo "Takato    : Hello Riichiro, too."
echo "Riichiro  : ... Hello"

'COMMENT_OUT'

```

実行結果



>Takato    : Hello, Nadeshiko!
>Nadeshiko : Hello Takato.



<BR>
よく記事でみかけるものの、うまくいかなかったコメントアウト例

```sh:Hello_2.csh
#!/bin/csh

echo "Takato    : Hello, Nadeshiko!"
echo "Nadeshiko : Hello Takato."

<< COMMENT_OUT

echo "Takato    : Hello Riichiro, too."
echo "Riichiro  : ... Hello"

COMMENT_OUT

```


実行結果


>Takato    : Hello, Nadeshiko!
>Nadeshiko : Hello Takato.
>Invalid null command.

<BR>



**結論**

```
:<< 'コメントアウト文'

'コメントアウト文'
```

以下がポイントのようです。

**1. 文頭に「:（コロン）」を入れる**
**2. コメントアウトの文字列はシングルクォートで囲む**
<BR>
shとbashでもうまくいきました。
<BR>
<BR>
会話は大好きなCLOCK ZEROというゲームからです。
幼馴染の撫子に声をかけてくる転校生の鷹斗に対して不愛想な態度をとる理一郎がかわいい。
文字の重複カウント（substring)

```java

import java.util.*;

//文章strのなかで指定文字targetの重複する回数をカウントする
public class Main {
    public static void main(String[] args) {
       Scanner sc = new Scanner(System.in);
        ArrayList<String> list = new ArrayList<String>();
        
    	//重複数の合計
        int count = 0;
        
        String target = sc.nextLine();
        String str = sc.nextLine();
        
    	//文を一文字ずつlistに詰める。
        for(int i = 1; i < str.length() + 1; i++){
            list.add(str.substring(i - 1, i));
        }
        
    	//listを0番から順番に抜出しtarget変数と等しければcountにプラス１
        for(int i = 0; i < list.size(); i++) {
            if (target.equals(list.get(i))){
                count++;
            }
        }
        
        System.out.println(count);
        
    }
}

/*
//substringより短い書き方。
public class Main {
    public static void main(String[] args) {
       Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
//splitはString[]を返す
//引数に正規表現が入る
//例：(,)カンマごとに区切ることになる。
        String[] str = sc.nextLine().split("");

        int count = 0;
        for (String p : str) {
          if (s.equals(p)) {
            count++;
          }
        }
        System.out.println(count);
    }
}
*/
snmpd に任意の値を出力させる

## 設定

ubuntu で設定しています
これでなんでも(shellを使って取れるものなら) cacti でグラフの表示とアラートをあげることができるようになった

### cron などで値をキャッシュする

```bash
$ vi /etc/cron.d/get-value
$ cat /etc/cron.d/get-value
* * * * * root cd /tmp && /usr/local/bin/count_custom_value.sh > .value.cache && mv .value.cache value.cache
```

### snmp extend を設定

```bash
$ vi /etc/snmp/snmpd.conf
$ cat /etc/snmp/snmpd.conf
...
extend-sh custom-value1 cat /tmp/value.cache
...
$ systemctl restart snmpd
```

### snmpwalk で確認

```bash
$ snmpwalk -v1 -c $COMMUNITY $AGENT nsExtendOutputFull
NET-SNMP-EXTEND-MIB::nsExtendOutputFull."custom-value1" = STRING: 0
```

oid を知りたい場合は `-On` をつける

## その他

snmp の value type が `STRING` になってしまうが、どうしようもない

```bash
#!/bin/bash
exit 10
```

exit code で値を表現すれば `INTEGER` にできるが 0-255 まで

`STRING` でも cacti でのグラフ表示や thold のアラートも問題なかった
Docker Install in Ubuntu

# Docker on Ubuntu 覚書
Dockerを入れて2日目の初心者が次回インストールするときにも見れるように分かっていることを書く。
>インストール方法 公式ガイド:[ https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)

## 今回の環境
- OS: Ubuntu Budgie 20.04

# インストールから
今回は公式リポジトリからインストールする
# 1. リポジトリの追加
1. アップデート 

        sudo apt -y update && sudo apt -y upgrade
        sudo apt -y install apt-transport-https ca-certificates curl gnupg-agent software-properties-common

2. 公式GPG鍵の追加

        curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

     フィンガープリントでキーの確認

        sudo apt-key fingerprint 0EBFCD88

     下記の表示が出ればOK

        pub   rsa4096 2017-02-22 [SCEA]
              9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
        uid           [ unknown] Docker Release (CE deb) <docker@docker.com>
        sub   rsa4096 2017-02-22 [S]

3. リポジトリ追加 (stable 版)


        sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

    ※Linux Mint どでは$(lsb_release -cs)コマンドの箇所をUbuntuなど親の名前に変更する必要があるとのこと
# 2. Docker Engineのインストール
1. ここでは最新バージョンのインストールのみ記載する(ガイドにはバージョン指定もある)

        sudo apt -y update
        sudo apt -y install docker-ce docker-ce-cli containerd.io

2. hello-worldで確認
        
    テストイメージがダウンロードされてメッセージが表示されて終了します

        sudo docker run hello-world

# 3. 古いバージョンのアンインストール
1. ガイドの一番上に書いてあったが、まだ使わないだろうしということで下のほうに...

        sudo apt-get remove docker docker-engine docker.io containerd runc
apt-get のプロキシ設定は小文字！！！！！

プロキシ環境下で Docker イメージをビルドしたいことがあったので、ARG でプロキシの情報を設定できるようにしてビルドした。

``` Dockerfile
FROM debian

# プロキシ環境下でビルドする場合に指定する
ARG HTTP_PROXY
ARG HTTPS_PROXY

RUN apt-get update \
 && apt-get install -y ... \
 && rm -rf /var/lib/apt/lists/*
```

``` console
$ docker build --build-arg HTTP_PROXY=... --build-arg HTTPS_PROXY=... .
(略)
Err:1 http://deb.debian.org/debian buster InRelease
  Cannot initiate the connection to prod.debian.map.fastly.net:80 (2a04:4e42:1a::204). - connect (101: Network is unreachable) Could not connect to prod.debian.map.fastly.net:80 (151.101.108.204), connection timed out
  Cannot initiate the connection to deb.debian.org:80 (2a04:4e42:1a::645). - connect (101: Network is unreachable) Could not connect to deb.debian.org:80 (151.101.110.133), connection timed out
```

は？
プロキシ通せてないやんけ。

なぜこれでうまくいかないのか半日頭を悩ませて判明した正解がこちら。

``` Dockerfile
FROM debian

# プロキシ環境下でビルドする場合に指定する
ARG http_proxy
ARG https_proxy

RUN apt-get update \
 && apt-get install -y ... \
 && rm -rf /var/lib/apt/lists/*
```

``` console
$ docker build --build-arg http_proxy=... --build-arg https_proxy=... .
```

「環境変数は大文字で指定するもの」「環境変数が Case Sensitive なわけがない」という思い込みが敗因です・・・。

各位プロキシ環境下で apt-get を使う際は気をつけましょう。
IntelliJ系IDEAで右クリック(2本指タップ)が効かない

## 問題
IntelliJ IDEA 2020.1.3 (Community Edition)で突如右クリックが効かなくなった

## 解決方法
- 原因となっているプラグインを無効にする

## 手順
Pluginsのチェックマークを全部外してApply → Restart → 動作確認
解決したら今度は半分だけ外してApply → Restart → 動作確認
今度はさらにその半分だけ外して...
みたいに二分探索的に絞り込んでいくといいかと思います。

自分の場合は`Japanese Language Pack EAP`が原因でした。

## 参考
[Pycharm 2020.1 right click on mac os not working -IDEs Support (IntelliJ Platform) | JetBrainsJetBrains ](https://intellij-support.jetbrains.com/hc/en-us/community/posts/360008048700-Pycharm-2020-1-right-click-on-mac-os-not-working)
【Unity/C#】ノームソートとは(コード付き)

#ノームソートとは
ノームソートはソートアルゴリズムの一種で、挿入ソートに似ているが、要素の移動は挿入ではなくバブルソートのような一連の交換で行う。その名称の由来は、オランダのノームが一列に並んだ鉢植えの花をソートする話である。

#実行結果
![ノームソート.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211130/d3356c26-2bca-3d5c-61df-8879390e0d52.gif)

#サンプルコード
```C#
	void GnomeSort(int[] _array)
	{

		int gnome = 1;

		while (gnome < _array.Length)
		{
			if (_array[gnome] < _array[gnome - 1])
			{

				_array[gnome - 1] ^= _array[gnome];
				_array[gnome] ^= _array[gnome - 1];
				_array[gnome - 1] ^= _array[gnome];

				gnome--;

				
				if (gnome == 0)
				{
					gnome++;
				}
			}
			else
			{

				gnome++;
			}
		}
	}
```
[AWSメモ] 公式リンク

自分用メモです。
構築時に役立った公式のリンク集です

AWS アカウントIDの確認方法
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/console_account-alias.html#FindingYourAWSId


タスクのライフサイクルの見方
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task-lifecycle.html
【JavaScript】基礎編

自分用の簡単な備忘録です。。。

#1.switchで条件分岐

if文で条件の分岐が多数になるときに、switchを使用すればもっと簡単に書くことができます。

```js

// 見本

変数名 = "値"

switch (変数名) {
  case "値":  
    処理
    break;
  case "値":
    処理
    break;
  case "値":
    処理
    break;
  default:
    処理
    break;
}
```

```js

// 信号機の色別で出力内容を条件分岐してみます

color = "red"

switch (color) {
  case "red":  
    console.log("STOP!!")
    break;
  case "yellow":
    console.log("be careful!!")
    break;
  case "blue":
  case "green":  // caseは複数指定することもできます
    console.log("GO!!")
    break;
  default:  // 条件のどれにも当てはまらなかった場合にdefaultで指定した内容が出力されます
    console.log("Not applicable!!")
    break;

// 結果としてはredのSTOPが出力されます

}
```

#2.whileのループ処理

while文は指定した条件が満たされるまで、ループ処理を繰り返して値を出力してくれる便利なプロパティです。

```js

// 下記はiが１ずつ増えて100になるまでiの値を繰り返し出力するという命令です

let i = 0; 

while (i <= 100) {
  console.log(i);
  i++;  // この記述がないと無限に処理が実行されるので注意しましょう！
}
```

#3.forのループ処理

for文はwhile文をさらに簡略化した記述ができるプロパティです。

```js

// 見本

for (let 初期値を代入した変数名; 条件式; 変数の再代入) {
  console.log(i);
}
```
```js

// 下記はiが１ずつ増えて100になるまでiの値を繰り返し出力するという命令です

for (let i = 0; i <= 100; i++) {
  console.log(i);
}
```

#4.テンプレートリテラル記法

下記のような記述で、文字列と変数を接続することができます。

```js

const animal = "猫";
// シングルクオーテーションの代わりにバッククオートで${}に囲むことで文字列と変数を接続できます
console.log(`この動物は ${animal} です` );

// 出力内容：この動物は猫です
```

#5.continueとbreak

continueは対象の値をスキップしたいときに、
breakは対象の値で処理を停止させたいときに使用します

for文を使って見ていきます。

```js
for (let i = 1; i <= 10; i++) {
  if (i === 4) {
    continue;
  }
  console.log(i);
}

// この条件式なら、1~10の出力の中で4の値のみスキップされます

```
```js
for (let i = 1; i <= 10; i++) {
  if (i === 4) {
    break;
  }
  console.log(i);
}

// この条件式なら、4の値でループ処理が停止するので、3の値までしか出力されません

```

#6.関数

```js
// 引数にはデフォルトで値を入れておくこともできる
function 関数名（引数） {
  処理
}
// 呼び出す
関数名（引数）;
```

#7.関数宣言と関数式の違い

6で紹介した関数の記述方法は関数宣言と言われています。
その他に関数宣言を変数に代入する関数式というものがあるので紹介しつつ違いを明確にしていきます。

```js
// 関数宣言
function 関数名（引数） {
  処理
}
関数名（引数）;
```
関数式とは、関数を定数に代入することを言います。

```js
// 関数式
const 定数 = function（引数） {  // 関数名がいらなくなります
  処理
};  // 定数に代入しているので末尾には;が必要です
// 呼び出すときは定数名になります
定数名（引数）;
```

#8.アロー関数
関数をもっと短く記述することができる記法です。

```js
const 定数 = (引数) => { // functionがいらなくなり、=>が必要
  return 処理
};
```
また、引数が１つの場合やreturnの処理が１つの場合はもっと簡易的に気j仏することができます。

```js
const 定数 = 引数 => 処理;
// ()も{}も必要なくなります
```

以上
WSL2でGUIをやりたいメモ

WSL2 で公式にGUIサポートが来るらしいですが、それまで待てないのでXServerでGUI環境を試したメモ。
はまりどころが多すぎるので、メモする

## VcXsrvのインストール
https://www.atmarkit.co.jp/ait/articles/1812/06/news040.html　
の通りにやればいい。
ただ環境変数の設定だけが違う

## WSL2の設定
https://qiita.com/baibai25/items/5841b0592727893d960f　
参考にして、環境変数を設定する

## VcXsrvの認証の設定
許可するIPアドレスがデフォルトだとlocalhostだけなのだが、↑の設定でローカルホスト経由でなくなったのでそれを設定してあげる。

WSLのターミナルで以下のことをする

```
$ ip addr 
の結果の中から、eth0のinetの部分を探す。
192.168.xxx.xxxになっていると思うので、
そのIPアドレスを控える。
```

今度はWindows側でそのIPアドレスを許可するように変更する。
C:\Program Files\VcXsrv\X0.hosts　を編集する。
おそらく以下のようになっているので先ほど控えたのIPアドレスを追記する。

```
localhost
inet6:localhost
192.168.xxx.xxx
```

VcXsrvを再起動して、WSL側でGUIを表示させれば動く！
やったね！