OmniAICreator/Qiita-1.07M huggingface dataset:
SDKMANで入れたJDK 11上でSpring Tool Suiteが起動しない場合の対処（たぶんEclipseも同じ方法でOK）

# 環境
- macOS Mojave 10.14.5
- Spring Tool Suite 3.9.8 (Eclipse 2019-03ベース)
- AdoptOpenJDK 11.0.3 (HotSpot VM)
    - インストールにはSDKMAN利用

# 現象
「To use Java command-line tools you need to install a JDK.」というダイアログが表示され、STSが起動しない。

<img width="421" alt="Screen Shot 2019-05-31 at 17.42.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58650/7315f047-f858-0b9a-fb21-4e9b88995918.png">

# 対策
`java` コマンドのパスをSTS.ini (Eclipseの場合はeclipse.ini) に下記のように追記する。

```:文法
-vm
javaコマンドへのパス
```

```:記入例
...
--launcher.defaultAction
openFile
-vm
/Users/tada/.sdkman/candidates/java/11.0.3.hs-adpt/bin/java
-vmargs
-Dosgi.requiredJavaVersion=1.8
...
```

`-vmargs` のすぐ上に書くのがポイントらしい。

> STS.iniは /Applications/STS.app/Contents/Eclipse フォルダにあります
Kubectl をMacにインストールする

KubectlをMacにインストールするときの備忘録。


Kubernetesの公式からダウンロード
---

https://kubernetes.io/docs/tasks/tools/install-kubectl/


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319276/695ce1cf-50d7-f837-1cb5-7d2d42a3760f.png)


Curlでkubectlをダウンロード
---
※あとはWebの手順通りにするだけですが。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319276/555e60ea-9821-1354-aadf-7abf70b8f9a8.png)

```
//最新版取得
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl

//Ver指定(ex:1.40)
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.14.0/bin/darwin/amd64/kubectl
```

→ローカルにファイルがダウンロード

実行権限を与えて、Moveする
---
```
$chmod +x ./kubectl
$sudo mv ./kubectl /usr/local/bin/kubectl
$kubectl version //動作確認
Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.0", GitCommit:"ddf47ac13c1a9483ea035a79cd7c10005ff21a6d", GitTreeState:"clean", BuildDate:"2018-12-03T21:04:45Z", GoVersion:"go1.11.2", Compiler:"gc", Platform:"darwin/amd64"}
The connection to the server localhost:8080 was refused - did you specify the right host or port?
```


→インストール完了しました！
【Hands-on Machine Learning with Scikit-Learn, Keras & TensorFlowの勉強メモ】001 - まえがき

##機械学習のためのPythonフレームワーク
>
- Scikit-Learn
  - 沢山の機械学習アゴリズムが実装さてれいるので、初心者でも使いやすい。
- TensorFlow
  - マルチGPUを使って、ニューラルネットワークで効率良く数学計算ができるフレームワークである。(Google社開発)
- Keras
  - 高いレベルのディープラーニングAPIである。TensorFlow、Theanoなどと連携可能。
  - TensorFlowの独自実装「tf.keras」


##サンプルコード 
>
https://github.com/ageron/handson-ml2

##参考サイト
>
- [Python](http://learnpython.org/)
- [Numpy](http://http://www.numpy.org/)
- [pandas](http://pandas.pydata.org/)
- [matplotlib](https://matplotlib.org/)
- [scikit-learn](https://scikit-learn.org/stable/user_guide.html)
- [dataquest](https://www.dataquest.io/)
- [quora](https://www.quora.com/What-are-the-best-regularly-updated-machine-learning-blogs-or-resources-available)
- [deeplearning](http://deeplearning.net/)
- [kaggle](https://www.kaggle.com/)
Let's Encrypt を Ubuntu/Debian 系の GNU/Linux 環境に導入する (複数ドメイン指定)

## はじめに

最近はあらゆるサイトを HTTPS 化しましょうってことで HTTP だとブラウザが警告を出すようになってしまいました。ただ情報を掲載しているだけのサイトで果たして HTTPS 必要か、という議論はさておき、このような風潮となったのは Let's Encrypt で SSL 証明書が無料で導入できるようになったという背景があることは間違いないでしょう。そこで今回は、すでに散々量産されているであろう [Let's Encrypt](https://ja.wikipedia.org/wiki/Let%27s_Encrypt) の導入についての記事です。

まず、発行される証明書は有効期限が 90 日しかないです。そこで certbot を使って自動更新する運用とし事実上無期限で利用するのがセオリーなのですが、ワイルドカード証明書だとちょっと厄介です。最近はワイルドカード証明書もちょっとした hack で自動更新できるようですが、そこは複数ドメイン指定で乗り切ることにします。ちなみにウェブサーバーは Apache とします。

### パッケージ導入

```shell
sudo apt install -y letsencrypt certbot python-certbot-apache
```

### 証明書取得

ドメイン部分や webroot は適当に読み替えてください。

```shell
sudo certbot certonly --webroot -w /var/www/html/current -d hoge.co.jp -d domain1.hoge.co.jp -d domain2.hoge.co.jp -d domain3.hoge.co.jp
```

#### ハマりポイント

これをやると /var/www/html/current/.well-known/acme-challenge/FX5JCVj29PQIBMh47oamNhEFQCiXqEJRv_XXXXXXXXX のように一時ファイルが webroot 以下に作成される。そしてそのファイルが外から参照できるかどうかでサイトの実在性を確認している模様。

つまりサーバーが外からアクセスできることを前提に動作します。外に直接公開していないサーバーでやる場合は standalone オプションを利用すれば良いが、この記事では割愛します。

当然ながら例えば .htaccess で以下のようにしたりしていると .well-known 配下が参照できないので失敗します。

```
RedirectMatch 403 /\..*/
```

他にもパーミッションなど設定を確認し、一時ファイルにアクセスできるような環境を用意すれば良いでしょう。なお一定回数失敗すると 1 時間ほどロックアウトされる模様。

### 設定

```conf
SSLCertificateFile    /etc/letsencrypt/live/yourdomainname/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/yourdomainname/privkey.pem
```

これらはシンボリックリンクになっており、実体のファイルは更新されるごとにファイル名が連番で変化し、シンボリックリンクが最新のものに向き変わる仕様。

### 自動更新

以下のような cron ジョブが自動的に設定される。任せておけば良いです。

```bash
# /etc/cron.d/certbot: crontab entries for the certbot package
#
# Upstream recommends attempting renewal twice a day
#
# Eventually, this will be an opportunity to validate certificates
# haven't been revoked, etc.  Renewal will only occur if expiration
# is within 30 days.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew
```

環境が変わるなどしたら、以下のコマンドで証明書の自動更新をテストできます。

```shell
certbot --dry-run renew
```

以上です。
Visual Studio CodeのRemote Developmentを使ってみた

# はじめに
April 2019 (version 1.34)のアップデートにて、「Remote Development」がプレビュー版で公開されたので、使用してみました

# TL;DR
簡単な設定で、リモート先にあるファイルをあたかも、ローカルにあるかのようにVisual Studio Codeで編集できて、感動しました

# 使用環境
Mac OS

# 使用する前の注意

記事の執筆時点だと、「Remote Development」はプレビュー版しか公開されていません
そのため、Visual Studio Code Insidersをインストールして使用する必要があります

# 実際に使用してみた

## 1. 初期設定
- Visual Studio Code Insidersをインストール
  - インストールは[こちら](https://code.visualstudio.com/insiders/)からできます
- Visual Studio Code Insidersを起動し、以下のプラグインをインストール
  - Remote Development
  - 日本語表示したい場合は、Japanese Language Pack for Visual Studio Codeもインストールしてみてください
- Visual Studio Code Insidersを再起動


## 2. 接続先の設定
- パソコンアイコン（1）→設定ボタン（2）の順でクリック
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/4b46b8ea-d057-a925-9863-4863fe6621e7.jpeg)

- /Users/xxxx/.ssh/configをクリックし、設定を記述する
![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/df1d16b8-da72-c961-071e-cb1b5cff9e1f.jpeg)

- 以下のような感じで設定を追記します

```
Host 【接続先を識別できる名称】
  HostName 【IP or ドメイン】
  IdentityFile 【sshに使用する鍵のフルパス】
  User 【ユーザー名】
```

## 3. 接続してみます

- CONNECTIONSに表示されている接続先の「接続」ボタンをクリックします
![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/9a8bd34c-2a57-ac0e-5b4d-3ab0c92a9bae.jpeg)

- 別ウィンドウでVisual Studio Code Insidersが表示されますので、左上のエクスプローラーボタン(1)をクリックし、フォルダを開くボタン(2)をクリックします
![5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/72727d33-06d6-2a3a-0b23-b4dd9066769c.jpeg)

- 開くフォルダのパスを入力し、OKをクリックします
![6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/5b38ceb9-2184-31d6-17c0-61da52500ad4.jpeg)

- 選択したフォルダ配下がエクスプローラーに表示されます
![7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103774/7138678f-b930-9009-b8ba-652672553972.jpeg)

以上で、SSHで接続が完了となるので、この状態でファイルを選択すると、即時リモート先に反映されます

# 補足
フォルダを開き直したい場合は、メニューのファイル→開くの順で選択してみてください

# まとめ
たまたま、レガシーシステムの保守で検証環境に接続する機会があり、Remote Developmentを試すことができましたが、使い勝手がいいです

早く正式版で使ってみたいな、と思う今日このごろです
Markdown記法で記事を書いてみました。

#さいしょに
[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしている二宮です。

プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。

初めて記事を書くということもあり、Qiitaで記事を書く際に必ず使うことになるMarkdown記法について僕のわかる範囲でまとめてみたいと思います。

#見出し
###<font color="red">入力</font>

```
#見出し１
##見出し2
###見出し3
####見出し4
#####見出し5
######見出し6

※見出しは五種類だけです。見出し6は見出し5と同じ大きさになりました。
```

###<font color="blue">出力</font>
#見出し１
##見出し2
###見出し3
####見出し4
#####見出し5
######見出し6

※見出しは五種類だけです。見出し6は見出し5と同じ大きさになりました。

#リスト

###<font color="red">入力</font>

```
- list1
- list2
- list3
- list4

1. list1
2. list2
3. list3
4. list4

- list1 
  - list1-2
  - kist1-2
```
###<font color="blue">出力</font>

- list 
- list2
- list3
- list4

1. list1
2. list2
3. list3
4. list4

- list1 
  - list1-2
  - kist1-2

#文字を強調させる
###<font color="red">入力</font>

```
強調させたい場合は*で囲みます（1~3個）
*test*　←傾きます
**test**　←太くなります
***test***　←太くなって傾きます

~~文字に線を入れたい場合は~~
~~で文字を挟みます
```

###<font color="blue">出力</font>

強調させたい場合は*で囲みます（1~3個）

*test*　←傾きます
**test**　←太くなります
***test***　←太くなって傾きます

~~文字に線を入れたい場合は~~
~~で文字を挟みます

#文字に色を付ける
###<font color="red">入力</font>

```
<font color="red">赤色</font>
<font color="blue">青色</font>
<font color="green">緑</font>

※調べてみたところ140色ほどあるそうです。全部書くのは大変なのでやめておきます。
```

###<font color="blue">出力</font>

<font color="red">赤色</font>
<font color="blue">青色</font>
<font color="green">緑</font>

※調べてみたところ140色ほどあるそうです。全部書くのは大変なのでやめておきます。

#リンクの貼り方
###<font color="red">入力</font>

```
[Qiitaトップ](https://qiita.com/)

[表示したい文](リンク先)
```
###<font color="blue">出力</font>
[Qiitaトップ](https://qiita.com/)

[表示したい文](リンク先)
ROSでSTM32をノードとしてPCとPub(/Sub)してみた

# はじめに
[この記事](https://qiita.com/hogepiyo334/items/0f0513791acff178881e)の改良版です．
また，[yoneken](https://twitter.com/k_yone)さんの[スライド](https://www.slideshare.net/k_yone/rosserial-stm32)を参考にしています．


# 検証済み機材

* STM32NucleoF446/L476
* Ubuntu18
* STM32CubeIDE

Linuxコマンドと,このIDEの使い方がわかるのを前提にしています．
rosserialは各自で入れておいてください．

# やりかた
## 目次
1. rosserial_stm32のインストール
2. IDEでの諸々の設定
3. コーディング(Pub/Sub)

## 1. rosserial_stm32のインストール
catkinが使える環境にある任意のディレクトリで

```
git clone https://github.com/yoneken/rosserial_stm32.git
```
その後，catkinでビルドしてください．

## 2. IDEでの諸々の設定
STM32CubeIDEを起動し，任意のボード・チップを選びプロジェクトを作成してください．
そのプロジェクトのディレクトリで

```
rosrun rosserial_stm32 make_libralies.py .
```
を実行して，ROSメッセージなどのライブラリをプロジェクトに取り込みます．

また，`.ioc`ファイルをIDE上で開きペリフェラルの設定をします．
今回はサンプルの`chatter`を動かすので

* UART2
* DMA
* TIMER2

を使えるようにします．
この時の注意ですがUARTのDMAはRXをCircularに,RX/TX両方のIncrimentAddressをONにしておいてください．
また，TIMER2はInternalClockに設定してください．

## 3. コーディング(Pub/Sub)
とりあえず，rosserial_stm32のサンプルコードを実行できるようにします．
とはいっても，やることはコピペしてビルドするだけなので省略．
たぶん，このままだと`STM32Hardware.h`でエラー吐かれるので適宜修正してください．
Subはここまでできればサンプル読めば出来ます．

# 最後に
だいぶ適当に書いてしまったので質問があったり抜けてるところがあればコメント欄にお願いします．
GASでログインユーザーのフルネームを取得する


GASの勉強中につまづいた部分なので、備忘録として記載します。

### やりたいこと
GASのスクリプト内で、アクティブユーザー情報以下2点を取得する。

* メールアドレス
* 取得メールアドレスの名前

 ---
 
 下記で取得成功！

```コード.gs
function accountName(){
  var emailaddress = Session.getActiveUser();
  var contact = ContactsApp.getContact(emailaddress).getFullName();
  return contact;
}
```

### 注意点。
取得メールアドレスの連絡先状態によっては、`contact` が <strong>null</strong> になってしまいます…。
自分宛にメールを送信し、既読にする事でnullから解放されましたが、理由は不明😭
原因解明ができたら追記します！

一緒に悩んでくれた同僚に感謝！


以上。
Callback で受け取ったトーク情報から botNo を取得する

既にご存じの方もござりましょうが。

LINEWORKS のチャット bot が受け取ったトークメッセージの情報に、botNo が含まれていたことに今日初めて気が付きました。( ﾟДﾟ)

いや、だって、ドキュメントに書いてないし、Body の中じゃないし、気づかないよ！（とか言い訳してみる）
[LINEWORKS 公式ドキュメント - メッセージ受信 - Callback 形式 (message)](https://developers.worksmobile.com/jp/document/100500901?lang=ja)


## headers の中に隠されていた botNo

header 情報もちゃんと確認しなさいってことですね。
以下のようにコードを書けば、botNo を取得できます。

```js:getBotNo.js

app.post('/callback', (req, res) => {
    const botNo = req.headers["x-works-botno"];
    console.log("botNo : " + botNo);
}
```

```
[nodemon] starting `node chatBot.js`
[nodemon] forking
[nodemon] child pid: 12720
botNo : 7680
```

## 名前に "-"（ハイフン）が入ってる！？

考えてみれば当たり前なのですが、名前にハイフンが入ってるパラメータだと "."（ドット）で指定できないんですよね。
自分で設計するときにはパラメータ名にハイフンなんて使わないんで、入ってるときにどうやって取り出すのか初めて知ったので、地味に勉強になりました。( ﾟДﾟ)

`const botNo = req.headers.x-works-botno;` 　←　これはアウトーーー！！
`const botNo = req.headers.xworksbotno;` 　←　これはOK(*‘∀‘)
`const botNo = req.headers["x-works-botno"];` 　←　これもOK(*‘∀‘)

#おわりに
今日のは覚書みたいな感じなので非常に短い！
「おわりに」を書く必要あるかな？とも思ったんですが、まぁ、楽しいので書いちゃいましょう♪

パラメータの名前をつけるとき、何で区切るのがいいんですかね？
xWorksBotNo とかが無難かな？とか思いつつ。
何か function くさいな書き方だな！とか思いつつ。
いや、そもそもパラメータ名長いよね！とか思いつつ。
省略しちゃうとわかんなくなるし。
名付けって、難しいですよね～。

ではまた！(^^)/

#参考にさせていただきましたm(_ _)m
[LINEWORKS 公式ドキュメント - メッセージ受信 - Callback 形式 (message)](https://developers.worksmobile.com/jp/document/100500901?lang=ja)
[jsonのキーにハイフンをいれないほうがいい](https://qiita.com/missyyy/items/db6b73dac2d66c7a3158)
【Git】初めてのコマンド操作まとめ（初級編

## こんなときに
* gitは使えるが、SourceTreeなどGUIで操作していた
* gitのコマンド操作に挑戦したい
* GitHubにプッシュしたい


## プッシュまでの流れ
1. git init
2. git add
3. git commit
4. git remote add
5. git push


### 1. ローカルレポジトリを作る。
```bash
git init
```

> Initialized empty Git repository in [your folder]

### 2. インデックスにステージング。
```bash
git add .
```
変更があったもの全て。

```bash
git add index.html path/index.html
```
複数指定の場合、スペースで区切る。


### 3. コミット
```bash
git commit -m "コミットメッセージ"
```

`-m`がコメントをつけてコミットするオプション。コミットメッセージはいずれにせよ必須なので、先に与えちゃう。
これが一番楽（vim苦手マン


### 4. リモート（GitHub）接続
```bash
git remote add origin https://github.com/[your-repository].git
```
GitHub側で空のリポジトリを作ってあるのが前提。
今回はひとまず `https`
リポジトリのページ、clone or downloas ボタンからリンクを取得。


### 5. プッシュ
#### 初回
```bash
git push -u origin master
```
初回プッシュの場合、追加したリモート情報をプッシュ先として登録しなければならないため、上記のようにオプションとブランチ指定などが必要。

#### 2回目以降
```bash
git push
```
2回目以降はこれで大丈夫。

ちなみに未コミット状態でpushしようとすると
> Everything up-to-date

と返ってくる。



## 役立ちコマンド
### 変更を確認
```bash
git status
````

現状のgitのステージング状況を確認。
未ステージングのファイルは赤、ステージング済みのものは緑で表示される。コミット済みのものは出ない。


### 一気にコミット
```bash
git commit -a -m "コミットメッセージ"
```
`-a`は変更のあったファイル全て。
`git add`をすっ飛ばしてコミットできる。
【！注意！】
変更のあったファイル、なので新規ファイルを追加した場合、また初回コミットには使えない。




### コミット履歴を確認する
```
git log
```
SourceTreeなどで見れる履歴をターミナル上に出す。
htmlなどで横に長いファイルは改行されてしまうので、ターミナル画面を大きく取るのがオススメ。

`↓`で過去の履歴まで全て見れる。一番下までいくと`END`と出ている。
`q`を押すことで画面を閉じれる。



### 前回コミット時点との変更を確認する。
```
git add *
git diff 
```
まずaddしてから、diff。

diffで開く画面は `git log`のときと同じ。`q`で閉じれる。




### git add を取り消す
#### 初回
```bash
git rm --cached <file_name>
```
【！注意！】
`git rm` はファイルを削除する危険なコマンドなので注意。`--cached`を付け忘れるとファイルそのものも消えてしまう。
#### 普段
```bash
git reset HEAD
```
【！注意！】
2回連続でaddしていた場合、その2回分もまとめて取り消してしまう。


### 変更をリセットする
```bash
git checkout -- index.html
```
ワーキングツリーの、ファイルの変更を前回コミット時点まで戻す。
`git add`でステージングしてしまっていたら無意味。ステージング前に変更をリセットしたいときに使える。


### 直前のコミットを上書き
```bash
git commit --amend
```

直前のコミットに、ファイルを追加してコミットし直したい場合。
1. `git add .` 
2. `git commit --amend`
3. vimが開くので,  `:wq`で保存して終了




## 参考
[【Git】基本コマンド - Qiita](https://qiita.com/konweb/items/621722f67fdd8f86a017)
[【Git】新人エンジニア、git pushまでの道 - Qiita](https://qiita.com/33yuki/items/9ef9d54f2e7d53cfb51c)
[git add の取り消し方法と、関連コマンドまとめ | WWWクリエイターズ](http://www-creators.com/archives/1282)
Git stashしらなかった…

例えば、今masterブランチとtestブランチが存在していて、testブランチで作業中に
masterブランチに切り替えるって時は、

```
$ git checkout master
```
とすると思います。

<font color="Red">がしかし</font>、testブランチでの変更内容をadd → commitしておけば、特に問題ないですが、
add → commitなしに作業ツリーが変更された状態のままであると、masterブランチに切り替えた時、
testブランチの変更内容(作業ツリー)がそのままmasterブランチに反映されてしまうことがあります。
※もし、切り替えたときにコンフリクトが発生すれば、そもそも切替はできません。

ちなみに、addした状態で切り替えてもステージングの内容がmasterに反映されてしまいます。

masterブランチに切り替えたい時に、testブランチの変更内容をadd → commitしたくないけど、
作業ツリーはそのままにしたい！って時は、前からどうすれば良いのか気になっていました。

それを解決してくれるのがgit stashです。

#git stash

testブランチで作業中、git stashで変更内容を一時保存します。
おそらく、変更内容を退避させる場所がどこかに存在するのだろう…

```
$ git stash
```

すると、

```
$ git status

nothing to commit, working tree clean
```

としても、コミットする変更内容はないよーという状態になります。

この状態でmasterブランチに切り替えればOK！

なお、またtestブランチに戻って作業再開したい場合は、

```
$ git checkout test
```
で戻り、

```
$ git stash list
```

で一時保存場所から取り出したい変更を確認したら、

```
$ git stash apply stash@{0}　←　stash@{0}の部分は一つ前のコマンドで確認してねー
```
で変更内容ももとに戻せます！

#最後に

まだまだ、gitの使い方も勉強中ですが、今回のgit stashは知れて本当に良かったです。
以下記事により詳しくgit stashについて、書かれています。

参考記事：[変更を一時的に退避！キメろgit stash](https://qiita.com/fukajun/items/41288806e4733cb9c342)
kubernetes on Windows

kubernetesの勉強中です。
本を読んだりして、とりあえず以下のファイルを作成した。

```nginx-all2.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 80
    protocol: TCP
  selector:
    app: nginx
---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: nginx
spec:
  serviceName: nginx
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  revisionHistoryLimit: 3
  template:
    metadata:
      labels:
        app: nginx
        version: latest
    spec:
      containers:
      - name: nginx
        image: nginx:1.16.0-alpine
        ports:
        - containerPort: 80
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx
spec:
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: nginx
          servicePort: 8080
```
これを動かすと以下となりました。ちゃんと公開されているのかしらん

```
C:\kube>kubectl apply -f nginx-all2.yaml
service "nginx" created
statefulset.apps "nginx" created
ingress.extensions "nginx" unchanged

C:\kube>kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP          2d
nginx        NodePort    10.107.207.22   <none>        8080:31059/TCP   15s

C:\kube>kubectl get statefulset
NAME      DESIRED   CURRENT   AGE
nginx     3         3         51s

C:\kube>kubectl get po -o wide
NAME      READY     STATUS    RESTARTS   AGE       IP           NODE
nginx-0   1/1       Running   0          1m        10.1.0.101   docker-for-desktop
nginx-1   1/1       Running   0          1m        10.1.0.102   docker-for-desktop
nginx-2   1/1       Running   0          1m        10.1.0.103   docker-for-desktop
```
起動して、curlコマンドを実x-1とnginx-2にアクセスされていることは確認できました。nginx-0は未確認です。
##変更履歴
(2019/6/2)起動してみて、その結果を追加。
ELBのローカル側IP、パブリック側を取得するワンライナー

### ローカル側のIPを取得

```
aws ec2 describe-network-interfaces --filters "Name=description,Values=${ELBのENIのDescription}" | jq -r '.NetworkInterfaces[] | .PrivateIpAddress' | sort
```

### パブリック側のIPを取得

```
aws ec2 describe-network-interfaces --filters "Name=description,Values=${ELBのENIのDescription}" | jq -r '.NetworkInterfaces[] | .Association.PublicIp' | sort
```
Nuxt.jsで好きなフォントを使う

## Nuxt.jsで自分の好きなフォントを使いたい。

Nuxtで好きなフォントを使う方法の覚書です。

まず好きなフォントをどこからかダウンロードしてきます。

自分は今回はPigmo-01を使ってみます。ちなみにファイルの拡張子は```.otf```です。

次に```assets```フォルダの中に```css```フォルダと```font```フォルダを作りました。
```css```フォルダの中に```styles.scss```を作って、持ってきたフォントのファイルは```fontフォルダ```に入れます。
すでに```css```フォルダや```styles.scss```や```styles.css```を作成済みの時は追記でOKです。


```
└── assets
    ├── css 
    │    └── styles.scss 
    └── font 
         └── Pigmo-01.otf // 持ってきたフォントのファイル
    
```
styles.scssに以下のように記述します。


```scss:assets/css/styles.scss

@font-face {
  font-family: 'HogeHogeFont'; // <-好きな名前をつけれます。
  src: url('../font/Pigmo-01.otf') format("opentype");
}
```

srcはフォントのアドレスです。ここでformatって何となりました。
私は、はじめこのformmatの記述を間違えていてフォントが適用されなくて詰まりました。

調べてみると、


```
Web Open Font Format: format("woff")
TrueType          : format("truetype")
OpenType          : format("opentype")
Embedded-OpenType : format("embedded-opentype")
SVG               :format("svg")
```
とあるようです。
拡張子```.otf```だから```opentype```なのかと思いながら調べていると、フォントをダウンロードした時のフォルダ内にあった使用説明のtxtファイルにきちんとFormatはOpenTypeであると書いてありました。
きちんと読まないといけないですね。

## 最後にnuxt.config.jsonでCSSを読み込み
最後に設定ファイルにCSSの読み込みを記述します。

```js:nuxt.config.json
css: [
    { src: '~assets/css/styles.scss' }
    ],
```

これで、なんか書いてみると、


```vue:test.vue

<template lang="pug">
  div.test Hello Funny Font!!
</template>

<style lang="scss" scoped>
  .test{
         font-family: 'HogeHogeFont';
       }
</style>

```
おおーできたー！となりました。


## まとめ
 font-faceの仕様はオプションもあります。
 font-weit、font-style,font-stretchとか他にも色々設定できるようです。
 これで変わったフォントとか面白いフォントとかNuxtで使えます。
 フォント探すのが楽しくなります。
 自分の為の覚書でありますが、
 自分と同じようなプログラミング初級者の方の為になれば幸いです。
 間違いのある情報を書いてしまっている事があれば指摘下さい。
JavaScript学習者が2週間目までに作ったアプリ

#はじめに
私はJavaScriptを学習し始めて、２週間目の初学者です。
2週間目という節目を迎えて、JavaScriptで５つアプリを作成したので公開しようと思います。
サーバーにアプリをアップロードしたので、もしコードに興味がある方は各項目のリンクから飛んでソースを見ていただけたら、と思います。
基本的にコードはタイミングゲームアプリ以外汚いです。
※FizzBuzzアプリは、サーバーへアップロードしていません。

#作成したアプリの目次
1.FizzBuzzアプリ
2.ビンゴアプリ
3.カードゲームアプリ
4.すごろくアプリ
5.タイミングゲームアプリ

#1.FizzBuzzアプリについて
FizzBuzzアプリは、プログラミング界隈ではお馴染みだと思いますが3の倍数の時に”Fizz！”、５の倍数の時に”Buzz!”、そして３の倍数かつ５の倍数である数の時に"FizzBuzz!"と表示するアプリとなります。

#2.ビンゴアプリ
このアプリは、5×５のマス目をHTMLで作成して、ボタンを押したらマス目がランダムに1つずつ色が変わっていき一列そろったら”BINGO！！！”と表示されるアプリとなります。
<img width="1326" alt="スクリーンショット 2019-05-31 17.03.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427892/585ba4b4-7d22-3e67-1c9c-66581a34d6c3.png">

[リンクはこちら](http://take619.xsrv.jp/BingoGame/index.html)

#3.カードゲームアプリ
このアプリは、まず４枚のカードを表示してその数を記憶してカードを裏返し、記憶した４つの数をフォームに入力して正解かどうか判定するアプリとなります。
<img width="1184" alt="スクリーンショット 2019-05-31 17.03.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427892/5786744b-1662-9278-e992-0442b0068e52.png">

[リンクはこちら](http://take619.xsrv.jp/CardGame/index.html)

#4.すごろくアプリ
このアプリは、16マスを画面に表示してサイコロを振り、出た目のマスを進みゴールを過ぎてしまった場合は”BURST！！！”と表示して、丁度ゴールへ到着した場合（サイコロの出目の合計値が17になった場合）は”CLEAR！！！”と表示するアプリとなります。
<img width="1299" alt="スクリーンショット 2019-05-31 17.04.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427892/20397aa8-2741-2c03-2485-8801a2961256.png">

[リンクはこちら](http://take619.xsrv.jp/Sugoroku/index.html)

#5.タイミングゲームアプリ
このアプリは、音符が２つ画面に表示されていて片方は位置を固定してあり、もう一方の音符は固定された音符に向かって移動しており、その２つの音符がちょうど重なった時にタイミングよくボタンを押すと、”CLEAR!!!"と表示してタイミングが合わなかった場合は、”MISS！！！”と表示されるアプリとなります。このアプリのコードは自分でもかなり綺麗に書けたと思います。ここら辺から、少し上達したかなと思いました。
<img width="932" alt="スクリーンショット 2019-05-31 17.04.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427892/ffa9eea6-5299-aaa4-e44d-0ebd7db35177.png">

[リンクはこちら](http://take619.xsrv.jp/TimingGame/index.html)
Grad-CAMの損失関数

前回の書いた[Grad-CAMの記事](https://qiita.com/nishiha/items/1c64a25354f796c5d892)では損失関数を結局どう定義してたかについては深く突っ込まなかったので、もう少し具体的に損失関数がどうなっているのか確認してみます。

#前回コード
```python:
def grad_cam(input_model, image, cls, layer_name):
    y_c = input_model.output[0, cls]
    conv_output = input_model.get_layer(layer_name).output
    grads = K.gradients(y_c, conv_output)[0]
```
結局、このコードの`y_c = input_model.output[0, cls]`の一行部分が損失関数になっているわけですが、損失関数をどう定義して計算しているんでしょうか。
これはOne_hotベクトル同士の内積、つまり

```python:
def grad_cam(input_model, image, cls, layer_name):

    y_pred = input_model.output[0]

    y_true = np.zeros(1000)
    y_true[cls] = 1.0
    y_true = tf.convert_to_tensor(y_true.astype(np.float32))

    loss = K.sum(y_pred * y_true)

    conv_output = input_model.get_layer(layer_name).output
    grads = K.gradients(loss, conv_output)[0]

```
という計算をしているにすぎません。
それにしても`K.sum(y_pred * y_true)`の損失関数の名称はなんていうんでしょうか。ヒンジ関数あたりが近い形ですかね？

#ほかの損失関数を使った場合：
当然、ほかの損失関数を使っても良いです。

```python:
    #loss = - K.mean(K.square(y_pred - y_true), axis=-1)  # mean_squared_error
    loss = - K.categorical_crossentropy(y_true, y_pred)  # categorical_crossentropy
```

ただ、どのGrad-Camの結果は損失関数を使っても、あまり違いがないみたいです。
![gradcam_hinge.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299928/6793a76e-99b7-5ef8-68fc-f4797464bc56.jpeg)　![gradcam_mse.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299928/b80b5b7d-c259-7f50-bb9a-987565cea7c9.jpeg)　![gradcam_cate.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299928/2c741175-7975-2c20-4f6e-9dd9e0e5ac58.jpeg)
：左(y_pred * y_true)、中央(mean_squared_error)、右(categorical_crossentropy)

#まとめ：
Grad-CAMの損失関数は`K.sum(y_pred * y_true)`である。ほかの損失関数を使っても結果はあまり変わらない。
AutoScale設定例

完全に自分のメモ用です。

### AutoScaleとは？
世の中のWebサービスには、昼間はほとんどアクセス数はないが夜になるとアクセス数が増えるとか、何か事件などがあった時に突発的にアクセス数が増えるといったものがある。

このように時間帯によるアクセス数の増減が大きかったり予測ができない場合に役立つのが、AutoScaleです。これによって、必要な時に必要な数のインスタンスを用意することが可能となる。


### 起動設定の作成
課金はEC2インスタンスやELBの利用として発生。（無料枠もEC2インスタンスやELBに従う）

EC2→起動設定→Auto Scaling グループの作成をクリック

「起動設定の作成」をクリック

AutoScaleで利用するAMIの「選択」をクリック

インスタンスサイズを選択し、「次の手順：詳細設定」をクリック

設定名を入力して「確認画面にスキップ」をクリック

設定内容を確認し、問題なければ「起動設定の作成」をクリック

EC2インスタンスで利用するキーペアを選択して「起動設定の作成」をクリック
EC2インスタンス作成時と同様に行う。

### AutoScalingグループの作成

設定値を入力してから「スケーリングポリシーの設定」をクリック
（下記の例では test-stg-asgroup01 というグループ名に、その他VPCやサブネット、ELBを使う場合はその設定等を行う）

「このグループを初期のサイズに維持する」→「次の手順：通知の設定」を選ぶ。
これはEC2インスタンスに障害が発生してシャットダウンしても、自動的に1台起動する設定。
これによって、いつでも必ず1台のEC2インスタンスが動いている状態を作り出すことでサービス全体が停止する状態を防ぐことができる。

なおAutoScaleの発動条件や起動するEC2インスタンスの最大数を設定したい場合は、もう一つの「スケーリングポリシーを使用して（以下略）」の方を選ぶ。

通知に必要な設定値を入力して「次の手順：タグを設定」をクリック。
AutoScaleが動いた時の通知を設定。
「通知の送信先」は設定名を、「受信者」の欄には実際に存在するメールアドレスを、通知するイベント種類をチェック。

必要に応じてタグの設定をしてから「確認」をクリック。
タグの設定は任意なので、未設定でも問題なし。必要に応じて設定する。

設定値を確認して問題なければ「Auto Scalingグループの作成」をクリック
picoCTF2018 writeup (what base is this ?)

# 問題

サーバに接続すると，問題が3問与えられます．
1問目は，2進数のリストが表示されます．
2問目は，16進数が与えられます．
3問目は，8進数のリストが表示されます．
それぞれ単語に変換して入力するですが，制限時間があるので，Pythonで自動化処理を施しました．

# 解法

```Python:
import re
from telnetlib import Telnet


def q1(bin_list):
    '''
    1問目
    2進数のリストを受け取って，単語にして返す
    '''
    dec_list = [int(x, 2) for x in bin_list]
    ans = ''.join([chr(x) for x in dec_list])
    return ans


def string_split2char(string, div_num):
    '''
    文字列をdiv_num文字ずつ区切る
    '''
    dec_list = re.split(f'(.{{{div_num}}})', string)[1::2]
    return dec_list


def q2(word):
    '''
    2問目
    16進数の文字列（区切り文字なし）を受け取って，単語にして返す
    '''
    dec_list = string_split2char(word, 2)
    ans = ''.join(list(map(chr, [int(x, 16) for x in dec_list])))
    return ans


def q3(oct_list):
    '''
    3問目
    8進数のリストを受け取って，単語にして返す
    '''
    dec_list = [int(x, 8) for x in oct_list]
    ans = ''.join([chr(x) for x in dec_list])
    return ans


def my_index_multi(l, x):
    '''
    リストの中で，xにマッチするインデックスをリストで返す
    '''
    return [i for i, _x in enumerate(l) if _x == x]


def get_given_word(text):
    '''
    設問の中からキーワードを抽出する
    '''
    word_list = text.split()
    left_index = my_index_multi(word_list, 'the').pop()
    right_index = my_index_multi(word_list, 'as').pop()
    return word_list[left_index+1:right_index]


if __name__ == "__main__":
    with Telnet('2018shell.picoctf.com', 1225) as tn:
        # q1
        # 問題文読み込み
        q1_text = tn.read_until(b'Input:').decode()
        # キーワードを抽出
        word1 = get_given_word(q1_text)
        # 変換して解答
        ans1 = q1(word1)
        tn.write(ans1.encode() + b'\n')

        # q2
        q2_text = tn.read_until(b'Input:').decode()
        word2 = get_given_word(q2_text)
        ans2 = q2(word2[0])
        tn.write(ans2.encode() + b'\n')

        # q3
        q3_text = tn.read_until(b'Input:').decode()
        word3 = get_given_word(q3_text)
        ans3 = q3(word3)
        tn.write(ans3.encode() + b'\n')

        # flag
        ret = tn.read_all()
        print(ret.decode())
```

- 参考

    - [string_split2char](http://kaworu.jpn.org/python/Python%E3%81%A7%E6%96%87%E5%AD%97%E5%88%97%E3%82%922%E6%96%87%E5%AD%97%E3%81%9A%E3%81%A4%E5%88%86%E5%89%B2%E3%81%99%E3%82%8B)

    - [my_index_multi](https://note.nkmk.me/python-list-index/)
cv2を試してみた。

```python

import cv2
import matplotlib.pyplot as plt
img = cv2.imread("nanamin1", 1)
# 画像の読み込み

img_r = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# cv2だと色の構成要素がBGRの順番だがpltはRGBの順番なので、pltで表示させるためにはcv2.COLOR_BGR2RGBを使う。

HAAR_FILE="/anaconda3/lib/python3.7/site-packages/cv2/data/haarcascade_frontalface_default.xml"
# 画像データを読み込む。このデータはopen_cvをダウンロードすると付いてくる。

cascade=cv2.CascadeClassifier(HAAR_FILE)
# 大量の画像を学習させることによって、分類器を作る。これによって、顔を検知することが可能となる。

face=cascade.detectMultiScale(img_r)

for x,y,w,h in face:
    cv2.rectangle(img_r,(x, y),(x+w,y+h),(255,255,255),3)
# 顔を囲む長方形を描画する。引数は、（画像、左下座標、右上座標、色、太さ）の順番

plt.imshow(img_r)
```



![nanamin5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275145/3b818861-6202-52c6-fa54-ddf5f8c8acc1.png)

うまくできた。


どういうわけだか、open_cvのデフォルトである、cv2.imshow関数を使っても,画像を表示することができなかった。
調べたところ、この問題はかなり多くの人が指摘しており、wait_keyを使うことによって解決した人などもいるようだが、私は解決できなかったので、matplotlibを使った。
find_by_sql で Rails から生 SQL クエリを直接実行する

生の SQL クエリを直接実行する `find_by_sql` メソッドの使い方メモ。

# 使い方
※サンプルコードはドキュメントのものを参考にしています。

### 基本
SQL のクエリを String として記述し、`find_by_sql` に渡すだけ。

```rb
query = "SELECT title FROM posts WHERE author_id = 1"
Post.find_by_sql(query)
```
### 動的に定義する
値を動的に指定したいときは、その値を `?` として入れたい値を順に配列として渡すか

```rb
query = "SELECT title FROM posts WHERE author = ? AND created_at > ?"
Post.find_by_sql([query, author_id, start_date])
```

シンボルで `:hoge` と置いて、ハッシュで値を指定する。

```rb
query = "SELECT title FROM posts WHERE author = :author_id AND created_at > :start_date"
Post.find_by_sql([query, { author_id: author_id, start_date: start_date }])
```

# count_by_sql
`SELECT` に `COUNT(*)` のみを含む SQL 文の結果を返す `count_by_sql` というメソッドもある。

### 実行例
```rb
Product.count_by_sql("SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id")
```

## 注意点
引数に渡したクエリはそのまま実行され、使っている DB に応じて処理が変更されることもありません。
そのため 特定の DB エンジンに依存したクエリが書いてあると、DB を移行しようとしたときに修正を余儀なくされてしまうので、最後の手段であると捉えましょう。

# 参考
ドキュメント:
https://api.rubyonrails.org/v6.0/classes/ActiveRecord/Querying.html
念の為、クエリを直実行したいときは SQL インジェクションなどに注意
https://railsguides.jp/security.html
【matlab】SGD等バッチ処理実装において行列からランダムにn個ずつ要素を抽出する方法

#経緯
最適化に関する研究に従事してる中で，バッチ処理が必要となるタイミングがありました．

あるN*Mの行列があり，その行列からランダムにK個の要素を取り出す．
それを全ての要素が取り出せるまでイテレーションを繰り返す．
したがってイテレーション回数はN*M/K回となる．

> 参考： (30) 配列要素をランダムにシャッフル
https://www.dogrow.net/octave/blog30/

#順序
1. 行列Aに対し，抽出する要素の数 Kとイテレーション回数を用意
2. 行列サイズの分だけ行列のインデックスに相当する乱数配列を作成
3. イテレーション毎に，乱数配列からK個分インデックスを取得し，行列Aの要素の抽出に利用

文章が究極に下手なので，次項目にて実例を見て頂きましょう．

#実装
N=3, M=3の要素数9の行列Aを作成．
行列AからK=3個ずつ重複なくランダムに要素を繰り返し抽出する．

```
>> A = rand(3,3)

A =

    0.8147    0.9134    0.2785
    0.9058    0.6324    0.5469
    0.1270    0.0975    0.9575

>> K=3
```

イテレーション回数(N*M/K回)も初期化

```
>> iteration=3*3/K

iteration =

     3
```

matlabでは行列の要素を呼び出す際， A(3,2) と呼びだすこともできるし，単一インデックスで呼び出すことも可能．
今回，A(3,2)には「0.0975」が入っているが，単一インデックスで同様の要素を取り出すにはA(6)と呼び出す．

この性質を利用する．

予め行列サイズ(今回は3*3=9)に合わせてインデックスの乱数を作成し，そのインデックスに基づき任意の数の要素をランダムに取り出す．
乱数の作成にはrandperm関数を利用する．

> 参考： 配列インデックス付け (matlab公式)
https://jp.mathworks.com/help/matlab/math/array-indexing.html

```
>> batch = randperm(3*3)

batch =

     5     7     8     3     6     1     2     4     9
```

イテレーション毎に，抽出数 K 個分インデックスをbatch配列から取得．
取得したインデックスはindex配列に代入し，そのまま行列Aの要素呼び出しに利用．

```
>> for i = 1 : iteration
index = batch( K*(i-1)+1 : K*i )
A(index)
end

index =
     5     7     8

ans =
    0.6324    0.2785    0.5469

index =
     3     6     1

ans =
    0.1270    0.0975    0.8147

index =
     2     4     9

ans =
    0.9058    0.9134    0.9575
```

#まとめ
バッチ処理のように，ランダムに要素を抽出する手法をまとめてみました．

matlabって公式がかなりhelp記事を書いてくれる一方で，かゆい処理について苦労する部分がありますよね．．．
何かお役に立てられればと記事を作成しました．

最後にすべてまとめたコードを記載します．

```
A = rand(3,3);
K=3;
iteration=3*3/K;

batch = randperm(3*3);

for i = 1 : iteration
  index = batch( K*(i-1)+1 : K*i )
  A(index)
end
```
OwnCloudでのデータディレクトリの変更方法


サービス停止が前提ですが、簡単に実施できます。
再インストール等も必要ありません。

### サービスの停止
Web Server を停止します。

```
systemctl stop httpd
```

### データの移行
移行元：/var/www/owncloud/data
移行先：/var/owncloud-data

```
rsync -avh /var/www/owncloud/data/ /var/owncloud-data/
```

### コンフィグファイルの変更
これは必須ではありませんが、OwnCloudをアップデートした際のデグレを防ぐ為に実施します。

```
vim /var/www/owncloud/config/config.php
```

datadirectory の値を変更

```
'datadirectory' => '/var/owncloud-data',
```

### DBのダンプ

```
mysqldump -u <dbuser> -p<dbpassword> -h <dbhost> <dbname> > owncloud_data.sql
cp owncloud_data.sql owncloud_data-new.sql
```


### SQL文の修正

```
sed -i -e 's/\/var\/www\/owncloud\/data/\/var\/owncloud\-data/g' owncloud_data-new.sql
```

### DB変更

```
mysql -u <dbuser> -p<dbpassword> -h <dbhost> <dbname> < owncloud_data-new.sql
```

### サービスの起動

```
systemctl start httpd
```

以上です。
gradle で 実行可能形式のjarを作るときpomがあるとzipで死ぬ場合の対応方法

具体的には Google の API ライブラリを使ったときに起こった件。
よく検索するとでる方法は

```gradle
from configurations.compile.collect {it.isDirectory() ? it : zipTree(it)}
```

方法なんですが、pomが入ってると死ぬんです。

```bash
15:44:57: Executing task 'jar'...

> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :jar FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':jar'.
> Could not expand ZIP '/xxxxx/.gradle/caches/modules-2/files-2.1/com.sun.xml.bind/jaxb-ri/2.3.2/f37875be0bc7d265b5bbb08eb55b2345c27e67aa/jaxb-ri-2.3.2.pom'.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 22s
3 actionable tasks: 1 executed, 2 up-to-date
Cause: archive is not a ZIP archive
15:45:21: Task execution finished 'jar'.
```
書いてるメッセージ的に、まぁそうですよねー

ということで、pomだったらzipに食わせなければいいというソリューション。
※findAll で 終端がpom以外なら を入れる

```gradle
jar {
    manifest {
        attributes 'Main-Class': 'HOGEHOGE'
    }
    from {
        configurations
                .compile
                .findAll { !it.name.endsWith('pom') }
                .collect { it.isDirectory() ? it : zipTree(it) }
    }
}
```
意外と記事がなかったのでどなたかの参考になれば。

【参考サイト】
https://stackoverflow.com/questions/52816630/unable-to-create-a-jar-of-my-jda-project-because-of-pom-dependency
https://qiita.com/informationsea/items/cd1d8d130a5c7b0bc31a
同一ネットワーク内で複数人がROS2を使用する場合

[ROS2関係トップページへ](https://qiita.com/NeK/items/7ac0f4ec10d51dbca084)

# 問題提起

ROS2はネットワーク内で自動的にnodeを発見し，構成する．そのため同一ネットワーク内であれば複数のPCでnodeを実行させて分散処理することが容易にできる．

一方，同一ネットワークで複数人が「それぞれの目的」に従ってROS2のプログラムを作成してnodeを実行させると以下のような問題が生じる．特に研究室で．

- Aさんがシミュレーション用の音声処理をnode名"processing"で作成．データをtopic名double resultで公開
- Bさんがラズパイに接続している距離センサをnode名"processing"で作成．データをtopic名double resultで公開
- Cさんが画像処理をnode名"processing"で作成．データをtopic名double resultで公開

結果，Aさんの処理結果がCさんのものとして使われたりするかもしれない．．．

# 解決方法

上記のような問題に対して，以下の解決方法がある．ここでは最初の方法を推奨する．

1. ROS_DOMAIN_IDを設定・ROS_LOCALHOST_ONLYの設定
2. node名・topic名などの命名規則を設定

## ROS_DOMAIN_IDの設定

ROS_DOMAIN_IDに数値を設定すると，同一の値が設定されたところ(terminal)同士でしかノードなどを見ることが出来なくなる．よって他の人のノードなどに左右されないし，他の人に影響を与えない．

### 設定の仕方

下記はterminalから直接設定する方法である．

```terminal
$ export ROS_DOMAIN_ID=1
```

下記のように.bashrcに記述する方法を推奨する．

```terminal
$ echo "export ROS_DOMAIN_ID=1" >> ~/.bashrc
```



### 値の範囲

ROS_DOMAIN_IDで設定できる値の範囲は0～65532まで．例えば2000000とか与えてros2 node listとやると，エラーメッセージが出て範囲を教えてくれる．

ROS_DOMAIN_ID=0はどうも「全体に見える値」のような気がする．検証としては，以下のとおり．

- 実験設定
    - 端末A，端末B，端末Cを用意
    - 端末A，端末Bで同じROS_DOMAIN_IDを設定
    - 端末CではROS_DOMAIN_IDを設定せず
    - 端末Aでnodeを実行
    - 端末B,Cでros2 node listを実行し，端末Aのノードが表示されるか確認

- ROS_DOMAIN_ID=1で設定した場合(ただしくは0以外で何通りか実験)
    - 端末B : 端末Aのノードが表示される
    - 端末C : 端末Aのノードが表示されない
- ROS_DOMAIN_ID=0で設定した場合
    - 端末B : 端末Aのノードが表示される
    - 端末C : 端末Aのノードが表示される

## ROS_LOCALHOST_ONLYの設定
もし自分一人がROS2を動かすPCを使っており，ネットワークごしに他のPCのノードとやりとりしないのなら，以下のように設定するのがよい．

```bash
export ROS_LOCALHOST_ONLY=1
```

# まとめ

基本的に.bashrcの中に以下を記述しましょう．値は管理者に相談して決めましょう．
ローカルで使用する場合には，ID=0にしてROS_LOCALHOST_ONLYを使うようにしましょう．

```sh:.bashrc
ID=0 # ここに自分固有の番号を入れる．分からなければ0とし，ROS_LOCALHOST_ONLYを使うようにしておく．
if [ $ID -eq 0 ]; then
  export ROS_LOCALHOST_ONLY=1
else
  export ROS_DOMAIN_ID=$ID
fi
```

# 参考

- [Overview of ROS 2 Concepts](https://index.ros.org/doc/ros2/Concepts/Overview-of-ROS-2-concepts/)
    - Discoveryの章
- [公式のdiscourse](https://index.ros.org/doc/ros2/Concepts/Overview-of-ROS-2-concepts/)
- キーワード
    - ROS_DOMAIN_ID，DDS domain IDなど
タグを使用してアクセス制御をする

以下の例では、naata-web1a というNameタグのみ停止、終了だけできるように設定してみます。

IAMポリシーを以下のように設定し、IAMユーザーへアタッチしてみる。


```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ec2:describe*"
            ],
            "Sid": "1",
            "Resource": [
                "*"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "ec2:StopInstances",
                "ec2:TerminateInstances"
            ],
            "Sid": "2",
            "Condition": {
                "StringEquals": {
                    "ec2:ResourceTag/Name": "naata-web1a"
                }
            },
            "Resource": [
                "*"
            ],
            "Effect": "Allow"
        }
    ]
}
```


naata-web1a を停止してみる。→これはうまくいくはず。

naata-web1a を起動してみる。→これはうまくいかないはず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/ccdcdcdb-6ddb-bda0-98d8-c312349864b3.png)

naata-web1cを起動してみる。→これもうまくいかない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/4a1cf19e-76a6-43b5-a476-7f67239e539d.png)

AWSのページには、他にも例があります、参考に。
[タグを使用したアクセス制御](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_tags.html)
[IAM タグを使用したアクセス制御](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_iam-tags.html)
[EC2 インスタンスや EBS ボリュームの作成方法を、IAM ポリシーのタグを使用して制限する方法](https://aws.amazon.com/jp/premiumsupport/knowledge-center/iam-policy-tags-restrict/)
Ranorex備忘録

#備忘録です
※ uiテスト(E2Eテスト)自動化ツールとして利用を想定し
  トライアル版を利用してます

#Clickが不安定(成功したり失敗したりする)
公式のQAでは画面への存在確認(waitfor.exists)を入れてもダメだったら適切に遅延(delay)を入れてみてって回答
[Click event is unreliable and does not work in some cases](https://www.ranorex.com/forum/click-event-is-unreliable-and-does-not-work-in-som-t7424.html)

もうちょっと新しいフォーラムを見つけました。
(URLを控え忘れて、見つけられなくなってしまいました)

InvokeActionを使って、マウス操作ではなくクリックするという内容


#InvokeActionで何ができるか
InvokeActionで何ができるかというリファレンスが見つからず
フォーラムを見ていると
[InvokeAction](https://www.ranorex.com/forum/invokeaction-t7422.html)
バージョンが異なり同じメニューが見れませんでしたが
新しいアクション追加で、RepositoryItemを設定すると、ActionNameで選択できるみたいですね。

指定したItemに用意されているメソッドを呼び出すことが出来るみたいです。
WebElementのPerformClick等
[PerformClick Method](https://www.ranorex.com/Documentation/Ranorex/html/M_Ranorex_WebElement_PerformClick.htm)


#安定させるには
ClickをInvokeActionのperformClickに差し替え
キーボード入力をSetValueに差し替える

注意: webdriverへ連携して利用する想定であれば不要!


#WebDriverとの連携
自動で全てのコードを変換してくれる訳ではなさそう
*Web テストのガイドライン
[Selenium WebDriver との連携](https://www.ranorex.com/ja/help/v8.3/interfaces-connectivity/selenium-webdriver-integration/)


[WebDriver エンドポイントの追加](https://www.ranorex.com/ja/help/v8.3/web-mobile-testing/endpoints/adding-webdriver-endpoint/)

## buttonが認識されないとき
○○ is no button というエラーが出てしまう時
対象のボタンのプロパティを下記の通り変更する
 Adapter Type =>  buttontag
[Difficulty clicking button on web application](https://www.ranorex.com/forum/difficulty-clicking-button-on-web-application-t7327.html#p29884)

以下は、webdriver連携前後の差異が発生した際の対応
## Elementが見つからないとき

* 読み込みたい画面の「Snapshot」を撮ると認識されやすくなる

[Re: WebDriver has different values than normal Ranorex](https://www.ranorex.com/forum/webdriver-has-different-values-than-normal-ranorex-t11129.html#p44846)

* WebDriverのDomFecthModeをAlwaysにする


# Ranorexのリファレンスについて

下記サイトを参考にRanorex標準のメソッドを利用しつつ独自のUserCodeを作っています。
[リファレンス](https://www.ranorex.com/Documentation/Ranorex/)
超初心者のためのSQL

こんにちは。私です。
IT全く未経験の友人がスキルアップのためにSQLかじりたいって言ってたので
本当に超超初心者向けの記事を書くことにしました。

雰囲気と掴みやすさ重視ですので細かいところは気にしないようにお願いします。
全体的にざっくりザクザクで書いてます。
間違えてたら教えてください。

## SQLとは
**SQL(エスキューエル)とは、リレーショナルデータベースに蓄積したデータを操作したり定義するためのプログラム言語です。**
だそうです。

- リレーショナルデータベース  
 - 事前定義された、関連があるデータ項目の集合体です。 この項目は、列と行を持つテーブルのセットとして構成されます。  
  →データの集まり  

すごく簡単に言うと、**データの集まりの中からデータを操作したり、取得/追加/編集/削除したりできるプログラム言語**ってなもんです。

## タイプが二つ

SQLには**DML(データを操作する方)**と**DDL(データベースやテーブルを操作する方)**の二つに分かれます。

#### DML
データの**取得・登録・更新・削除**などの**データ操作**に分類する文法

- SELECT文(データ取得)
- UPDATE文(データ更新)
- INSERT文(データ追加)
- DELETE文(データ削除)

が有名どころですね。

---
#### DDL
**データベースやデータベースのテーブルを作成や定義**する文法  
- CREATE文(テーブル/データベース作成)
- DROP文(テーブル/データベース削除)
- ALTER文(テーブル/データベースの変更)

が有名どころです。(あんまりALTER文使ったことないな)(いや、あるか)

## まとめ
今回はざっくりSQLについて書いてみました。

- SQLっていうのはデータの集まりの中からデータを操作できるプログラミング言語だよ
- SQLにはデータを操作するものとテーブルとかを操作するものの二つあるんだよ

がわかってもらえたら幸いです。

次回で各文法などに触れていければいいなと思います。

ここまで読んでいただきありがとうございました。
では!皆様、良いSQLライフを٩( 'ω' )و
ELB設定例

完全に自分のメモ用です。

サービス→EC2をクリック

「ロードバランサ」をクリック（左側カラムの真ん中あたりにあります）

「ロードラバランサの作成」をクリック

Application Load Balancerのところにある作成をクリック

必要な設定値を入力して、セキュリティ設定の構成をクリック
（ALBの名前の入力やHTTP/HTTPSの別、対象VPCとアベイラビリティゾーンのチェックなどを実施）

右下にある「セキュリティグループの設定」をクリックしてから、HTTP/HTTPSの別に合わせてセキュリティグループを設定する（下記画像はHTTPのみ用のALBの場合）設定後ルーティングの設定をクリックする。

ターゲットグループの設定値を入力してから「ターゲットの登録」をクリック
（ターゲットグループの名前を入力したり、配下のサーバの生存確認＝ヘルスチェックで利用するパス等を入力）

配下に組み入れるEC2インスタンス選択してから「登録済みに追加」をクリック

追加できたら「次の手順：確認」をクリック

設定内容を確認して問題なければ「作成」をクリック

作成が完了したら「閉じる」をクリックする

サービス→EC2→ターゲットグループ→ターゲットを開き、状態がhealthyになってことを確認

説明→DNS名でアクセスできるかを確認する

この例だと http://test-prd-lb01.308534944.ap-northeast-1.elb.amazonaws.com でアクセスするとALB配下のEC2で動いているホームページが見える。
見えない場合は設定を見直す。

完了。
もし使わない場合はすぐに削除して、不要な課金が発生しないように注意。
WSLでSSHポート転送

#はじめに
Windowsでポート転送（SSH Portforward）といえばTera Term。だが、我々はWSLという武器を手に入れた。これを活用しない手はない、ということでWSLのUbuntuでSSHポート転送を試した手順を記載する。
接続対象はAWS上のPrivateサブネットの中にあるEC2とする。

#TL;DR
Linuxのssh -Lコマンド使えばWSLでもSSHポート転送できます。

#登場人物
- 作業用PC・・・Windows10、WSL（Ubuntu16.04.3 LTS）導入済
- 踏み台サーバー（AWS上のPublic Subnet上のEC2インスタンス：Amazon Linux2）
- 作業対象サーバー（AWS上のPrivate Subnet上のEC2インスタンス：Amazon Linux2）

#コマンド

```console:コマンド
# ssh -L <作業用PCのポート>:<作業対象サーバー名もしくはIP>:<作業対象サーバーのポート> -i XXX.pem ec2-user@<踏み台サーバーのIP>
```

やってみた。

```console:コマンド
# ssh -L 80:10.0.2.28:80 -i XXX.pem  ec2-user@x.x.x.x
Last login: Fri May 31 06:07:20 2019 from xxx
[ec2-user@ip-10-0-0-13 ~]$
```

作業用PCのブラウザでhttp://localhost:80 でアクセスすると作業対象サーバーのページ（今回はWordpressで試した）が表示された。
→成功。
速攻NodeJSで簡単メール送信

# NodeJSでメール送信

## 環境
* モジュールは`nodemailer`を使用します。
* SMTPはGメールを使用します。

## ソース
```mail.js
var receiverEmailAddress = '{宛先アドレス}@*****.com'
var senderEmailAddress = '{作成したGメール}@gmail.com'
var senderEmailPassword = '{作成したGメールアカウントのパスワード}'

var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
  host: 'smtp.gmail.com',
  port: 465,
  secure: true, // SSL
  auth: {
    user: senderEmailAddress,
    pass: senderEmailPassword
  }
});
var mailOptions1 = {
  from: senderEmailAddress,
  to: receiverEmailAddress,
  subject: '{件名}',
  text: '{本文}'
};
transporter.sendMail(mailOptions1, function (error, info) {
  if (error) {
    console.log(error);
  } else {
    console.log('Email sent: ' + info.response);
  }
});
```

## 使用方法 
1. モジュールのインストール`npm install nodemailer`
2. スクリプト実行`node mail.js`

## 結果
`Email sent: 250 2.0.0 OK  ******* f11sm5251981pfd.27 - gsmtp`
jQueryでブレークポイントを指定する

自分用メモです

```javascript:jQuery

if (window.matchMedia( "(max-width: 768px)" ).matches) {
// ウィンドウサイズが 768px以下
} else {
// ウィンドウサイズが 768px以上
}
```



```javascript:jQuery
if (window.matchMedia( "(max-width: 768px) and (min-width: 480px)" ).matches) {
// ウィンドウサイズが 480px以上768px以下
}
```
連続した非同期通信を行う際のローディング管理が、redux-saga を使ったら便利だった話

## 前書き
この記事は redux-saga の使い方はあまり記述していません。
あくまで使ってみたら便利だった体験談を備忘録がわりに書き留めたものです。

## 連続した非同期通信ケース
そもそも連続した非同期通信が走る状況ってどんなときってことなんですが
下のケースが例として挙げられます。

- ニュース一覧リストをレイジーロードする時
- 料金取得APIなど、フロント側のInput要素のChangeイベントごとにAPIを叩く時
- 商品リストの「次へ」ボタンをユーザーが連打する時

これらのAPI通信が走っている際、画面にローディングを付けたいと思うかもしれません。
その際、ローディングを終えるタイミングは連続したAPIコールの最後の処理が終わった時ですよね。

簡単に今まで書いていた処理を記述してみました。


```actionCreator.js
// セッションの宣言
const session = new Date().getTime()

// ローディング開始アクションにセッションを渡す
  dispatch<LoadStart>({
    type: ActionTypes.LoadStart,
    payload: { session }
  })

  try {
  // 非同期通信開始
    const resp = await getHogeApiResponse(requestParam)
    
  // 通信成功時、payloadにセッション情報も含める
    dispatch<LoadEnd>({
      type: ActionTypes.LoadEnd,
      payload: { data: resp, session }
    })
  } catch (e) {
  // 通信失敗時、payloadにセッション情報も含める
    dispatch<LoadEnd>({
      type: ActionTypes.LoadEnd,
      payload: { session }
    })
  }
```
- セッションを宣言し、非同期通信をする直前でステートにセッションを登録
- APIをコールし、通信成功・失敗に関わらず再度セッションを渡す
- ステートのセッションを比較し、セッションが異なれば、他にAPIコールが行われているためローディングを続行
- ステートのセッションを比較し、同一だったらローディング終了

という流れです。

この処理を非同期通信部分に1個1個書いていく必要があるため、手間に感じていました。

## redux-saga を使った場合

```saga.js

function* fetchHoge(action) {
  try {
  // 非同期通信開始、callの第一引数でAPI通信関数、第二引数で通信処理の引数を指定
    const resp = yield call(getHogeApiResponse, {
      requestParam: action.payload
    })
// 通信成功時
    yield put<FetchHogeSucceeded>({
      type: ActionTypes.FetchHogeSucceeded,
      payload: resp
    })
  } catch (e) {
  // 通信失敗時
    yield put<FetchHogeFailed>({
      type: ActionTypes.FetchHogeFailed
    })
  }
}

export function* sagas() {
// ActionTypes.FetchHogeRequestedを監視
// このアクションが呼ばれたらfetchHogeを起動する。
  yield takeLatest(ActionTypes.FetchHogeRequested, fetchHoge)
}
```

redux-saga本来の書き方が特徴的であるため、前述したものと比べて冗長に見えますが
セッションに当たる部分を担っているのは下のほうに記述してある `takeLatest` 指定のみです。
##### takeLatestの動作
> もしレスポンス待ちの状態で USER_FETCH_REQUESTED を受け取った場合、
> 待ち状態のリクエストはキャンセルされて最後の1つだけが実行されます。

公式だとこうなっていますね。
連打される可能性のある非同期通信処理が10個あったとしても１０回takeLatest指定してあげれば良いわけです。
とても楽チン。

逆にすべて並列で処理したい場合はtakeEveryが使えます。

## まとめ
今回のことでredux-sagaが最高！ と断言するわけではありません。
しっかりかけますが、記述も独特で若干冗長になりやすいです。

ただ、非同期通信処理をStore内で切り分けられるので設計を整理しやすく、好印象でした。

個人的には
簡単な非同期通信処理のみ扱う際は redux-thunk
しっかりと非同期通信処理を管理したい場合は redux-saga
という印象です。

また次の機会にも使っていこうと思います。

ここまでお読みいただきありがとうございました。
データウェアハウスの4つの特性について

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257568/05859438-7f02-691c-93a5-9ac1dc0114e1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257568/8fa3a1f4-44bc-73fb-dab8-020106452bdf.png)

こちらを読んで

データウェアハウスには4つの特性がある

- サブジェクト指向
- 統合化
- 不揮発性
- 時系列

### サブジェクト指向
組織にとって重要な項目や課題に基づいて（サブジェクト指向）データモデリングを行うこと

- サブジェクトとは主題や課題という意味
- 企業の継続的な業務ではなく、テーマに関する情報を提供するため
- これらのテーマは、営業活動、営業活動、配布など
- データソースは、実行中の操作に重点を置いていない
- 代わりにデータのモデリングと分析に重点を置く
- 意思決定、または意思決定プロセスをサポートするのに役立たないデータを除外することで、特定の主題に関するシンプルで簡潔なビューを提供する

### 統合化
異なるソースのデータを、一貫したフォーマットでデータ格納すること

- 異種データベースからすべての類似データに対して共通の測定単位を確立すること
- 命名規則、形式、コーディングの一貫性を維持する必要がある
- それに伴い、データの有効な解析命名規則、属性メジャー、エンコード構造などの一貫性を保証する必要がある

### 時系列
時間経過に伴う変化に重点が置かれたデータになっていること

- 運用のデータベースよりライフサイクルが長い
- 収集されたデータは、特定の期間で認識され、履歴の観点から情報を提供する
- レコードのキーには、時間要素が必ず含まれている
- 時系列のデータからビジネスの動向を見いだし、背後に潜むパターンおよび関係性を識別する

### 不揮発性
格納されたデータは更新または変更できないこと

- 目的が何が発生したかを分析することにあるため
- 新しいデータが入力されたときに以前のデータは消去されない
- 履歴データを分析し、何が発生したかを把握するため
- アプリケーションの運用環境で実行される削除、更新、挿入などのアクティビティは、データウェアハウス環境では原則省略される

## 書籍情報
クリシュナルンタ, データウェアハウジングを1日で学ぶ
https://amzn.to/2VNt4f0

データウェアハウスの基礎: RDBから一歩進んでデータ利用技術を学ぶ スキルズ・オン・デマンド研修プログラム
https://amzn.to/2W30oib

https://aws.amazon.com/jp/data-warehouse/

## 雑感
日本語だけで探すと書籍が少ない
JS > Moment > 開始と終了の時間の差分を得る




```js
let start = moment("2019/05/04 8:00:00");
let goal = moment("2019/05/05 16:43:26");
console.log("start", start);
console.log("goal", goal);

if (start && goal) {
    let duration = moment.duration(goal.diff(start), 'milliseconds'); //差分をミリ秒で取得し、ミリ秒→durationへ変換
    let hour = Math.floor(duration.asHours());
    let time = hour + ":" + duration.minutes() + ":" + duration.seconds();
    console.log("time", time);
}
```



## 参考

[javascript - Convert milliseconds to hours and minutes using Momentjs - Stack Overflow](https://stackoverflow.com/questions/22938300/convert-milliseconds-to-hours-and-minutes-using-momentjs)


### 参考

以下はStackOverflowでも指摘されているが、24時間オーバーの場合には正しく計算できない

```js
let time4 = moment.utc(milliseconds).format('HH:mm');
console.log("time4", time4);
```
正規表現メモ C#



CSVファイルの中に含まれる不正な文字を、正しい（期待する）値に変更したい。


```csharp
var expected = Regex.Replace(str1, "{正規表現パターン}", "{置換パターン}");
```


文字列（"区切り）の中に、"が含まれている場合


```csharp
var expected = Regex.Replace(str1, "[Z-a0-9]\"\"," , "$1\",");
```



# 参考

[正規表現を使って文字列を置換するには？［C#／VB］：.NET TIPS - ＠IT](https://www.atmarkit.co.jp/ait/articles/1702/08/news023.html)
Gitでブランチを作ろうとしたら「fatal: cannot lock ref ...」と怒られた

# 経緯
他の人が作った `project/feature_name` みたいなブランチを派生元として `project/feature_name/add_hoge` みたいな作業用ブランチを作ろうとしたら怒られた。

```bash
$ git branch
master
* project/feature_name

$ git checkout -b project/feature_name/add_hoge
fatal: cannot lock ref 'project/feature_name/add_hoge':
'project/feature_name' exists; cannot create 'project/feature_name/add_hoge'
```

# 原因
Git では `foo/bar` みたいなブランチを作ろうとすると `.git` ディレクトリ配下に `foo` ディレクトリを作ろうとする。
このとき既に `foo` というブランチが存在していると、当然もう `foo` ディレクトリが作成済みなので上記のようなエラーになるらしい。

```bash
$ git co -b hoge
Switched to a new branch 'hoge'
$ git co -b hoge/fuga
fatal: cannot lock ref 'refs/heads/hoge/fuga': 'refs/heads/hoge' exists; cannot create 'refs/heads/hoge/fuga'
```

参考： [gitでfooとfoo/barというブランチは同時には作成できない](https://qiita.com/yaotti/items/d73e5cdb1f8ace60365f)

# 解決
## 1. 派生元のブランチ名を工夫する
今回のケースみたいにトップブランチを作って、そこから作業用ブランチを切って…みたいにやる場合、トップブランチ名を下記のようにすれば衝突しない。

NG: `project/feature_name`
OK: `project/feature_name/top`

上記のようにすると、 `project/feature_name/add_hoge` のように作業用ブランチの命名ができる。

## 2. 作業用ブランチの名前に `/` を使わない
個人的にはしっかり `/` で区切りたいけど、そんなこだわりはない場合は単に使わなければ良い。

例） `project/feature_name_add_hoge`
例） `project/feature_name--add_hoge`
例） `project/feature_name__add_hoge`