OmniAICreator/Qiita-1.07M huggingface dataset:
Docker上で動くTypeScriptアプリをVisual Studio Codeでデバッグする

ローカルマシンでの開発では、TypeScriptをtscでトランスパイルしてnodeで実行するのではなく、[ts-node](https://www.npmjs.com/package/ts-node)を使ってTypeScriptのまま実行する方法が主流になっている。Visual Studio Codeを使う場合も、[ts-nodeのドキュメントの起動設定](https://github.com/TypeStrong/ts-node#visual-studio-code)でts-nodeを起動すれば問題なくデバッグ実行ができる。

ところが、Dockerコンテナでts-nodeを実行してリモートデバッグでVIsual Studio Codeを接続する場合は、TypeScriptファイル中に設定したブレークポイントが効かない。原因は特定できていないが、ts-nodeではsouce mapファイルが出力されないため、TypeScriptファイルとのリンクができていないようである。（参考：[Visual Studio Code - Debugging TypeScript](https://code.visualstudio.com/docs/typescript/typescript-debugging)）

関連しているGitHub Issuesは以下の通り。

* https://github.com/TypeStrong/ts-node/issues/807
* https://github.com/TypeStrong/ts-node/issues/778

現時点では、以下の設定のように従来通りtscを使うことで、Visual Studio Codeでデバッグ実行できる。

* package.json（抜粋）

  ```json
  {
    "scripts": {
      "serve": "tsc && node --inspect=0.0.0.0:9229 dist/server.js",
      "watch": "nodemon -L -w src -e ts -x \"npm run serve\""
    }
  }
  ```

* tsconfig.json（抜粋）

  ```json
  {
    "compilerOptions": {
      "target": "es5",
      "module": "commonjs",
      "sourceMap": true,
      "outDir": "dist"
    }
  }
  ```

* launch.json

  ```json
  {
    "version": "0.2.0",
    "configurations": [
      {
        "name": "Docker: Attach to Node",
        "type": "node",
        "request": "attach",
        "localRoot": "Visual Studio Code側のアプリルート",
        "remoteRoot": "Dockerコンテナ側のアプリルート",
        "address": "localhost",
        "port": 9229,
        "protocol": "inspector",
        "restart": true
      }
    ]
  }
  ```

##### 補足

ts-nodeはv7以前ではsource mapのキャッシュを出力できたが、[v8で廃止された](https://github.com/TypeStrong/ts-node/pull/701)。この議論については以下のIssueが参考になる。

* https://github.com/TypeStrong/ts-node/issues/672
* https://github.com/TypeStrong/ts-node/issues/748

##### 参考

* [Debugging TypeScript in VS Code without compiling, using ts-node](https://medium.com/@dupski/debug-typescript-in-vs-code-without-compiling-using-ts-node-9d1f4f9a94a)
  - Visual Studio Codeのデバッグ起動設定（launch.json）からts-nodeを実行する方法が紹介されている。
* [Create a server with Nodemon + Express + Typescript](https://medium.com/create-a-server-with-nodemon-express-typescript/create-a-server-with-nodemon-express-typescript-f7c88fb5ee71)
  * nodemonでソースファイルの変更を検知してts-nodeを実行する方法が紹介されている。Visual Studio Codeの自動アタッチ機能を使ってデバッガを接続している。
尤度についての自分なりの理解メモ

#尤度がいまいち理解できないので自分なりの言葉で表現してみる。

ある前提条件となるパラメータ:θの真値は決まっているが真値を知ることは出来ない。そこで観測結果であるデータ:Ｄより前提となるパラメータ:θを推定することになるが、この時の推定の尤もらしさを尤度という。

ベイズの公式は、

```math
\ \ \ P(θ|D) = \frac{P(D|θ)P(θ)}{P(D)} \\ 
```

尤度は、

```math
\ P(D|θ) 
```
<br>
理由はなんとなくしかわからないが、尤度 = 同時確率となるっぽいので

```math
\{x_1,x_2,\cdots,x_n\} \in D とすると \\
P(D|θ) = P(x_1,x_2,\cdots,x_n|θ)
=\prod_{i=1}^NP(x_i|θ)
```
外部割込みとは

参考サイト:
https://www.zealseeds.com/ITSkilStandard/BasicSoftware/Interrupt/HardwareInterrupt/index.html
https://www.fe-siken.com/kakomon/24_haru/q11.html

#外部割込みとは？
ハード・ディスクやLANボードなど、プログラム以外の原因によって行われる割込み。

#外部割込みの種類
>
1.機械チェック割込み
2.タイマ割込み
3.入出力割込み

##1.機械チェック割込み
・ハードウェアの誤作動や故障によってタスクが中断される。
・ハードウェアが異常を検知した時に発生する割込み。
・商用電源の瞬時停電などの電源異常による割込み。
・メモリパリティエラーが発生したことによる割込み。

##2.タイマ割込み
・インターバルタイマによって、指定時間経過時に生じる割り込み。
・ウォッチドッグタイマのタイムアウトが起きたときに発生する割込み。

##3.入出力割込み
・入出力動作の終了／入出力が完了
・リスタート割込み
・コンソール割込み、別名外部信号割込み
・オペレータ割込み
・ユーザーがマウスやキーボードを操作
・ネットワークからデータが送られてきた

#ついでに……
外部割込みと一緒に、内部割込みについても少し学習しましょう。
よく基本情報技術者試験の問題では、並べて扱われることが多いので。

##内部割込みとは？
実行中のプログラムによって行われる割込み。

##内部割込みの種類
>
1.プログラムによる割込み
2.スーパーバイザコール割込み
3.ページフォールト割込み

#基本情報技術者試験の問題で復習
外部割込みに分類されるものはどれか。

ア：インターバルタイマによって，指定時間経過時に生じる割込み

イ：演算結果のオーバフローやゼロによる除算で生じる割込み

ウ：仮想記憶管理において，存在しないページへのアクセスによって生じる割込み

エ：ソフトウェア割込み命令の実行によって生じる割込み

##それぞれの選択肢について考える
###ア
事前に学習した、外部割込みの<font color="blue">2.タイマ割込み</font>に該当しますね。
よって、これが答えです。
###イ
事前に学習した、内部割込みの<font color="blue">1.プログラムによる割込み</font>に該当しますね。
よって、誤り。
###ウ
事前に学習した、内部割込みの<font color="blue">3.ページフォールト割込み</font>に該当しますね。
よって、誤り。
###エ
事前に学習した、内部割込みの<font color="blue">2.スーパーバイザコール割込み</font>に該当しますね。
よって、誤り。

#蛇足
自分はあまり勉強していない方だと思っているのですが(だからこそ試験一週間前にこんな基礎的なところを勉強しているわけですが)、ちょっと勉強しただけでも平成29年度秋、平成24年度春、平成19年度秋……と、結構な頻度で出ていることが分かりました。
もはや基本情報技術者試験のお家芸ともいっていいほどのものだと思われますので、是非覚えて帰ってください。
RDKitで分子中の等価(対称な)原子を検出する

### はじめに
分子中の原子に着目して機械学習等でデータ処理を行う場合、分子中の等価な原子は冗長であるため、夫々別データとするのではなく、1つのデータとして処理をしたい。このために、分子中の等価な原子を検出する方法を調べたのでメモっておく。

### 環境
- OS Windows10
- Python 3.7
- RDKit 2018/9/2
- Jupyter Notebook

### やり方
まずはサンプルとなる原子を読み込んで表示しよう。

```python
from rdkit.Chem import AllChem, Draw, rdmolops
from rdkit.Chem.Draw import IPythonConsole
mols = AllChem.SDMolSupplier("../som/17.mequitazine.mol")
mol = mols[0]
Draw.MolToImage(mol)
```

こんな感じの分子が表示されたとする。
ここで、3つ連続した環の両サイドのベンゼン環の各原子は、完全に等価である。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329816/386e3c28-671b-3f3a-0c3c-d4de329eba00.png)

この等価な原子を検出するには、CanonicalRankAtomsを以下のように用いる。そうすると、rankAtomsの中に、原子のインデックス順にランクが得られる。このランク、同じ番号は等価な原子である。

```python
rankAtoms = list(rdkit.Chem.rdmolfiles.CanonicalRankAtoms(mol, breakTies=False))
print(rankAtoms)
[13, 20, 12, 21, 10, 8, 19, 8, 10, 22, 17, 6, 2, 0, 4, 15, 14, 15, 4, 0, 2, 6, 17]
```

さて、番号だけではわかりにくいため、分子の各原子上に上のランクを表示させてみよう。

```python
for atom in mol.GetAtoms():
    atom.SetProp('molAtomMapNumber',str(rankAtoms[atom.GetIdx()]))
mol
```

するとこんな感じで表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329816/416733bd-813e-64aa-b2b3-c7bf04d70bb0.png)

文字がつぶれて見ずらいが、確かに2つのベンゼン環の対応する原子は同じランク(番号)になっていることが分かる。

### 参考
- [RDKitドキュメント-rdkit.Chem.rdmolfiles module
](https://www.rdkit.org/docs/source/rdkit.Chem.rdmolfiles.html)
ウェブページのルビの部分はコピーされないようにする

HTML の ruby, rt 要素を使うと、単語にルビを振ることができます。しかし、そのままだとブラウザでコピーした時に「言葉ルビ言葉ルビ…」のようにルビの部分が混じったテキストがクリップボードにコピーされてしまいます。これでは多くの場合は不便だと思います

# 解決策

```html
<!DOCTYPE html>
<html lang="ja">
  <head>  
    <style>
      body.remove-rt-before-copy rt {
        display: none;
      }
    </style>
  </head>
  <body
    oncopy="!function(e,s,l){l=e.classList;l.add(s);requestAnimationFrame(function(){l.remove(s)})}(this,'remove-rt-before-copy')"
  >
    <ruby>ここはコピーされます<rt>ここはコピーされません</rt></ruby>
  </body>
  
</html>

```

- `body.oncopy` された瞬間だけルビの要素に `display: none;` を与える
- すぐに元に戻す

以上です。スタイル定義を忘れずにコピーしてください

# 注意

- よくあるトリックですが、イベントハンドラの先頭の `!` は無名関数の宣言とコールを同時に行う場合に正しくパースされるように置いているのと、関数を `return false` させないために書いているので、消してはいけません
- HTML か CSS に no-copy 属性とかあるべきだと思うんですが、どうなんでしょう
UnityでJSONをサーバーから受け取り処理する方法

## UnityでJSONをサーバーから受け取り処理する方法
文字列としてJSONを受け取った時に、それをオブジェクトにして扱う方法です。

まずは、次のように受け取るJSONの型を作成します。

```c#
  [Serializable]
  public class Item
  {
    public float x;
    public float y;
    public float z;
    public int uid;
  }
```

そして、JsonUtilityを使いjsonStringからItemを生成します。

```c#
Item item = JsonUtility.FromJson<Item>(jsonString);
```

これで、`item.x`のようにプロパティにアクセスすることが出来ます。
## 終わりに
私は現在、Web3のサービスの開発をしています。詳しくはこちらの記事をご覧下さい。
        [無料でイーサリアムが当たる、Web3時代の寄付サイトを作った話](https://note.com/kenroda/n/n814347fbdcd7)
OMP: Error #15: Initializing libiomp5.dylib, but found libiomp5.dylib already initialized.

#tensorflow-hub でのエラー

Operating System: Mac OSX Mojava 10.14.3
 https://raw.githubusercontent.com/tensorflow/hub/master/examples/image_retraining/retrain.py
このプログラムを実行すると
下のようなエラーがでました。

```console 
"OMP: Error #15: Initializing libiomp5.dylib, but found libiomp5.dylib already initialized.
OMP: Hint: This means that multiple copies of the OpenMP runtime have been linked into the program. That is dangerous, since it can degrade performance or cause incorrect results. The best thing to do is to ensure that only a single OpenMP runtime is linked into the process, e.g. by avoiding static linking of the OpenMP runtime in any library. As an unsafe, unsupported, undocumented workaround you can set the environment variable KMP_DUPLICATE_LIB_OK=TRUE to allow the program to continue to execute, but that may cause crashes or silently produce incorrect results. For more information, please see http://www.intel.com/software/products/support/."
```

#解決策
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'
私がプログラミングを始めた経緯（１）（2019/04/14現在）

こんにちは、Miyauchiです。
初投稿です。

私は昨年の八月になんとなーーく興味本位でプログラミングを学びたいと思ってやり始め、ダラダラと試行錯誤しながらも少数のポートフォリオを（一応）作り、少し飽きて放置してしまい、それを死ぬほど後悔をして再びプログラミングを身につけようと走り始めました。
まずはその経緯・経過を思考の整理をしつつここに書き連ねていきたいと思います。長丁場になりますが、お付き合いください。

※時系列順に書いていきたいと思います。２項目ずつくらい目標

1. プログラミングを始めた理由
2. 初めてのプログラミング・Python
3. Codeship・Geeksalonの2択
4. web系言語勉強開始
5. PHP/Wordpress
6. Unityを知る
7. 今後

項目　勉強した月日
1~2 2018/08,09末日
（資格の勉強や舞台の活動のため休止）
3~4 2018/11,12,2019/01
（学校のテスト）
5~ 2019/02,03

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

1.プログラミングを始めた理由

まずは私がプログラミングを始めるに至った経緯をお話しします。
ぶっちゃけてしまうと、本当に「なんとなく」です。
サークル活動が一区切りついて就活を控えた直前の時期に、なんとなく聞いて「面白そう」、「できたらかっこいいな」、「頑張れば自由な働き方に繋がるかもしれないのか」、「稼げそうなのか」、「こんな綺麗な人がやっているのか（ちょ○どさん）」、などなど・・・
厳密に言うとそれ以前に、古くからの友人が大学でやっているのを知っており、すこーーーーしだけやろうとしたことがあったのですが、その後は放置していたため、実質的には上記の時期にこのような動機から始めてみるか、と言う形になりました。

また、就活が終わって内定承諾をした後に、進路のことで再び悩む時期があって（いわゆる内定ブルーのようなもの）、プログラミングをやってしっかり技術をつければ新たな選択肢も増えるかもしれない、そんな希望的観測（甘ったれた考え）も持ちつつ、勉強も開始しました。



2.初めてのプログラミング・Python

はじめに触ってみたのが友人に勧められたことがあったPythonでした。当時、友人に教科書を少しだけ見せてもらい、オンボロWin7PCで環境構築をしてやっていたものの、復元できなかったため、そこでひとまずProgateでPythonコースをやることにしました。
また、それと同時にやっていたのがPythonを使用しているエンジニアの方などをTwitterで探してフォローし、情報収集をすることでした。情報収集する中で、PythonはどうやらAI分野に強い言語であるというのがわかってきました。ProgateをIIIまでやって、案外楽しくできたため、Twitterで見つけた一ヶ月間のPythonのAI分野のスクールに通うことにしました。（A○　Aca○emyさん）　
今思うと、プログラミングでやりたいことがいまいちつかめていなかったため、かなり無策な投資だったと思います。。。
実際通ってみて、Pythonのちゃんとした環境構築やpandas, Flask, 重回帰分析など、機械学習の基本的な動作をゆっくりめで経験できたのは初心者に優しくてわかりやすかったなと思います。しかし、自分の身には,とてもじゃないですが完全にはつけられず、終わってしまいました。次に何をやればいいのかわからず、そこの情報収集を怠ったため、作業を終えてしまったら終わり、ということになってしまったのが敗因でした。反省。。。。
こうしてPythonの学習は一区切りしました（してしまいました）

次回に続く。
php-master-changes 2019-04-13

今日は Windows でのビルドこけ修正、LiteSpeed の SAPI 更新、PHP_READDIR_R_TYPE の残骸を削除する修正、PACKAGE_* の C プリプロセッサマクロを無効化する修正があった！

# 2019-04-13
## nikic: Try to fix windows build
- https://github.com/php/php-src/commit/a3459084e11a9023196a6e921c4160931d6588d8
- [7.4~]
- ext/soap で、Windows でのビルドがこけてたのを修正
- [昨日の修正箇所](https://qiita.com/sj-i/items/a2ac9a1be14ed2262f58#nikic-avoid-unitialized-variable-warning-in-soap)で宣言側にも ZEND_NORETURN 足しましょうという話だった

## George Wang: LiteSpeed SAPI 7.3, better process management, new API function litespeed_finish_request().
- https://github.com/php/php-src/commit/1e7f1b90e8118aeece2dc48c5252d6979d2e0a3a
- [7.2~]
- sapi/litespeed を [7.3](https://twitter.com/litespeedtech/status/1117044740330020864) に更新

## petk: Remove PHP_READDIR_R_TYPE
- https://github.com/php/php-src/commit/769db42341845544eebd4c939ecdaf87ce711d85
- [7.4~]
- ビルドシステムで、[先日削除してた](https://qiita.com/sj-i/items/0789b154ba6624dcf666#nikic-use-readdir-instead-of-readdir_r) PHP_READDIR_R_TYPE の残骸を削除

## petk: Disable PACKAGE_* preprocessor symbols
- https://github.com/php/php-src/commit/69b20f51e15d535da77f830709a4f1b5a682c265
- [7.4~]
- PACKAGE_* の C プリプロセッサマクロを config.h.in 経由で無効化
- [先日の修正](https://qiita.com/sj-i/items/403fbd6c84af97a335a7#petk-refactor-ac_init-in-configureac-and-php-versions)でこのへんが空文字列にならなくなり、phpize でマクロ再定義の警告が出たりするようになってた
CoreOSでdockerのbasesizeをかえる。

devicemapperのみ利用可能、overlay2 では使えないと思う。

##下準備
/var/lib/docker
を消す（データが消える)

##cloud init
```yaml:cloud-config.ymlを作る
core20190325 core # vi cloud-config.yml
```
```
#cloud-config
coreos:
  units:
    - name: docker.service
      drop-ins:
        - name: 10-storage-opt.conf
          content: |
            [Service]
            Environment="DOCKER_OPTS=--storage-opt dm.basesize=1G"
      command: start
```

##読み込む
```
core20190325 core # coreos-cloudinit -from-file=./cloud-config.yml
```

あるいは

```
ls /etc/systemd/system/docker.service.d/
vi その中にあるファイル(e.g.10-devicemapper-storage-driver.conf)
[Service]
Environment="DOCKER_OPTS=  --storage-opt=dm.basesize=1G"
```

##リロード
```
core20190325 core # systemctl daemon-reload
core20190325 core #  systemctl stop docker
```

#たまに消さなくても動作しそうです。
```
core20190325 core # rm -rf /var/lib/docker

core20190325 core #  systemctl start docker
core20190325 core # docker info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 0
Server Version: 18.06.1-ce
Storage Driver: devicemapper
 Pool Name: docker-8:9-1042461-pool
 Pool Blocksize: 65.54kB
 Base Device Size: 1.074GB
 Backing Filesystem: xfs
```

#Ref
https://qiita.com/python_spameggs/items/66f6bbe4b97be55f8b65
https://coreos.com/os/docs/latest/customizing-docker.html
#See Also
https://qiita.com/haniokasai/items/2b7a1889e4930b7682c9
Markdown のテーブルを直感的に生成できる VSCode の拡張機能を作った

## TL; DR

- VSCodeでMarkdownを書く人向けに、テーブルを入力しやすくするExtensionを作成した
- 例えば `lllcccrrr`, `6` と順に打つと

```md
|    |    |    |    |    |    |    |    |    |
|:---|:---|:---|:--:|:--:|:--:|---:|---:|---:|
|    |    |    |    |    |    |    |    |    |
|    |    |    |    |    |    |    |    |    |
|    |    |    |    |    |    |    |    |    |
|    |    |    |    |    |    |    |    |    |
|    |    |    |    |    |    |    |    |    |
|    |    |    |    |    |    |    |    |    |
```

とエディタにMarkdownのテーブルを入力できる

## Markdown Table Maker

私は多くの場合 VSCode をエディタとして利用するため、Markdown の入力も自然と VSCode を使うことになるのですが、たまに表を作成したいときに、 Markdown のテーブルってどうやって入力するんだっけ...となり、いちいち調べたりしていました。もう少し簡単に入力できないものかと思っていました。
そこで、習作も兼ねて、より直感的にテーブルを入力できるような拡張機能の作成に取り組みました。

以下が作成した拡張機能 **Markdown Table Maker** のリポジトリです。

https://github.com/HelloRusk/vscode-markdown-tablemaker

## 準備

VSCodeのMarketplaceの検索画面で `markdown-table-maker` と入力し、出てきた拡張機能をインストールします。

![スクリーンショット 2019-04-14 22.35.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233069/f4a6af8d-51d5-0b33-4d3d-750124c2889d.png)

## 使い方

1. Markdown テーブルを入力したい位置にカーソルが来るようにします。
1. コマンドパレットを開き、**TableMaker: Generate New Markdown Table** を選択します。
![スクリーンショット 2019-04-14 22.36.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233069/9ed241b4-3920-9745-2917-90f75d9a2644.png)

1. 以下のような画面が出ます。
![スクリーンショット 2019-04-14 22.36.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233069/c740c3f0-5dbc-b5bb-d940-15f6c6057654.png)
ここでテーブルのそれぞれの列の位置取りを指定します。
例えば、以下のように `lllcccrrr` と入力すると、
![スクリーンショット 2019-04-14 22.37.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233069/1967aa1e-880c-56bb-76fd-a2fb38cd7206.png)
9列のテーブルが作成されることになり、このうち1-3列目は`l`（Left）すなわち左揃え、4-6列目は`c`（Center）すなわち中央揃え、7-9列目は`r`（Right）すなわち右揃え、ということになります。
LaTeXで表を作成したことのある人なら馴染みのある書き方だと思います。

1. 次に以下のような画面が出ます。
![スクリーンショット 2019-04-14 22.37.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233069/95e8f25e-5074-b401-a6a1-1ca92fc894c8.png)
ここで行数を入力します。行数というのは1番上の行（GitHubやQiitaなどでは太字になる行）を除いた、2行目からの数を指します。
![スクリーンショット 2019-04-14 22.37.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233069/4c4ca1e2-b995-4a35-31ec-e9453634eb78.png)

1. Markdownのテーブルが入力されます。
![スクリーンショット 2019-04-14 22.37.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233069/29a63415-5907-b2f6-bdef-c30eedc2414c.png)

## その他

- 既にこのような拡張機能があったらすみません。個人の習作なので勘弁してください。
- Bug Report や Feature Request などあれば GitHub の issue にどうぞ。
基本情報技術者過去問題 平成29年秋期 午前問8 について

参考サイト:
https://www.fe-siken.com/kakomon/29_aki/q8.html
http://www5.plala.or.jp/vaio0630/hp/cgi.htm

#問題
Perlの実行に関する記述のうち，適切なものはどれか。

ア：
UNIX用として開発されており，Windows用の言語処理系はない。

イ：
実行にWebサーバを必要とする言語であり，CGIの開発に適している。

ウ：
動的デバッグは，言語処理系から独立したプログラムを実行して行う。

エ：
プログラムをコンパイルしたファイルを事前に用意する必要はない。

#解答
エ


#解説
##ア：
PerlにはWindows環境用の言語処理系もある。
余談だけど、UNIX用として開発されている言語って何だろうって考えた時、それに該当する言語を僕には思い浮かべることができない。
##イ：
PerlにはWindows環境用の言語処理系もある。
デスクトップアプリケーションも作成できるため、一概にそうともいえない。
###CGIとは？
Common Gateway Interface。
Webサーバー上でプログラムを使って処理した結果を表示させる機能のこと。
C++初心者がsortを触ってみる

c++には便利なsort関数があります。
最近覚えたのでメモとして残します。
昇順、降順それぞれの記述方法と注意点です。

##昇順ソート
vectorに詰まった数字のソートを行います。

```java:昇順sort

  sort(A.begin(), A.end());
```

##降順ソート
続いて降順ソートです。
２通りどちらの書き方でも大丈夫です。

```java:降順sort
  
//書き方１
sort(A.rbegin(), A.rend());
  
//書き方２
sort(A.begin(), A.end(),  greater<int>());  
```


##部分ソート
配列を部分的にソートします。
以下は先頭から２要素目までを指定した部分ソートです。

```java:部分sort
  vector<int> A{3,1,4,2,5};

  partial_sort(A.begin(), A.begin() + 2, A.end());  
  
  for(int i = 0; i < A.size(); i++){
    cout << A[i] << " ";
  }
```

```java:result
1 2 4 3 5 
```
注意しなければならないのは、「先頭から２つをソートする」ではなく「先頭から２要素が『配列全体をソートした結果』と同様になるような出力をする」であることです。

私は前者を期待していたために１時間ほど無駄にしました。

```java:注意
//勘違いした私の期待(先頭から２要素だけソート)
3, 1, 4 , 2, 5   --> 1, 3, 4, 2, 5

//現実
3, 1, 4 , 2, 5   --> 1, 2, 4, 3, 5 
```

##先頭から任意の範囲だけソート
vectorは最初に宣言した大きさ以上に要素を詰め込むことができますが、あとから追加した要素については size() やend() が効きません(試してみた感じ多分)。
そのため、きちんと範囲の指定を行う必要があります。
私はこれに気づかずに無駄な時間を費やしたのですが、結果としてこれを利用して部分ソートでの私の失敗を解決することができました。

```java:例）end()を使用
  vector<int> A{3,1,4};
//要素をあとから追加
  A[3]=2;
  A[4]=5;

  sort(A.begin(), A.end());
  
  for(int i = 0; i < 5; i++){
      cout << A[i] << " ";
  }
```

```java:結果
//先頭の３つのみソート実行
1 3 4 2 5 
```
続いて範囲指定をしてソートを実行してみます。

```java:例）begin()から範囲を指定
  vector<int> A{3,1,4};

  A[3]=2;
  A[4]=5;

  //先頭から数えて5つをソート
  sort(A.begin(), A.begin() + 5);
  
  for(int i = 0; i < 5; i++){
      cout << A[i] << " ";
  }

```

```java:結果
1 2 3 4 5 
```
全要素のソートができました。

以上参考まで。
Gitの個人的によく使うコマンドまとめ

個人的に業務で使うGitのコマンドをまとめました。

### ソースをローカルにダウンロード
`git clone [リポジトリURL]`

### 現在のブランチの確認
`git branch`

### ローカルブランチの削除
`git branch -D [ブランチ名]`

### ローカルブランチの作成
`git checkout -b [ブランチ名]`

### リモートブランチに作業ブランチを切り替え
`git checkout -b [ブランチ名] origin/[ブランチ名]`
または
`git checkout -b [ブランチ名] upstream/[ブランチ名]`

### 変更のあるファイルの確認
`git status`

### ステージングに変更ファイルを全て追加
`git add -A`

### 変更内容を全てコミット（コメントあり）
`git commit -am "コメント"`

### ローカルブランチをリモートにプッシュ
`git push origin [ブランチ名]`
または
`git push upstream [ブランチ名]`

### コミットログの確認
`git log`

### ローカルリポジトリの更新
`git fetch --all`

### 現在のブランチに別ブランチをマージ
`git merge [ブランチ名]`

### fetchとmergeを同時
`git pull [ブランチ名]`

#### フォーク元からのpull
`git pull upstream [ブランチ名]`

### 変更ファイルの一時退避
`git stash`
#### コメント付きの場合
`git stash save "コメント"`

### stashで退避した変更の一覧を確認
`git stash list`

### stashで退避した変更ファイルの取り出し（直近のstash）
`git stash pop`
#### stashで退避した変更ファイルの取り出し(指定)
`git stash pop stash@{n}`
nは任意の数字

## 組み合わせ技
### 他ブランチのコミットを取り込む
1. `git log`で必要なコミットログを確認
2. `git checkout [ブランチ名]`で作業ブランチを切り替え
3. 1で確認したログから取り込みたいコミットIDで`git cherry-pick [コミットID]`
sortable.js trash

-demo https://codepen.io/gnjo/pen/PgJqLM
-sortable.jsは明確に削除操作が無い為、body全体にドロップされた際に削除する。

```js
Sortable.create(document.body
...
 onAdd:e=>e.item.remove(), //remove
```

```js
var data=`https://i.imgur.com/5ntXKyR.jpg,https://i.imgur.com/rCJwzGQ.jpg,https://i.imgur.com/CcKioLq.jpg,https://i.imgur.com/9AViGyD.jpg`.split(',')
,base =document.getElementById('base')
,ed=document.getElementById('ed')
,fac=(d)=>{var el =document.createElement('img');el.src=d;return el}
data.map(fac).map(d=> base.appendChild(d) )

Sortable.create(base, {
 animation: 200,
 group: {
  name: "shared",
  pull: "clone",
  put: false,
  revertClone: true,
 },
 sort: true
});

Sortable.create(ed, {
 group: "shared",
 sort: true,
});

Sortable.create(document.body, {
 group: {
  name: 'trash',
  pull: false,
  put: ['shared']
 },
 sort: false,
 onAdd:e=>e.item.remove(), //remove
});
```
Spring Tool Suite(STS)を背景黒にしたのに、yaml・ymlファイルのフォントテキストが黒いまま！

# 問題

Spring Tool Suite(STS)でダークテーマを採用したのに、ymlファイルを開くと
文字色が黒のまま。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153208/fdf22dcd-6034-1c5d-63cd-ff07f32bc6c5.png)
設定 > 一般 > 外観 > 色とフォント 
を確認するも、
ymlファイルオープン時に使われているフォント設定はない様子。

# 解決策

ymlの設定は別の設定に存在した。
設定 > YEdit設定 > 色設定　
にて設定可能。
無事、黒背景にあったフォント色を設定することができました。
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153208/4bca7dd7-327a-9ecc-31a9-ba025e43a9ed.png)
クリックしたtable要素をCSVとしてダウンロードするJavaScriptスニペット

クリックしたtable要素をCSV形式でダウンロードするスニペット。
[Cheome DevTooolsのConsole機能](https://qiita.com/aqril_1132/items/a0f7e81a772006847ec3)かSnippets機能から使用する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/38423863-9488-36be-2b64-32eae9951387.png)
##使い方
1. 後述のスクリプトをChrome DevToolsのConsoleから実行
2. 「CSVとしてダウンロードしたいtable要素をクリックしてください」と出るので<kbd>Enter</kbd>で消す
3. CSV形式でダウンロードしたいtable要素をクリック
4. クリックした要素がCSV形式でダウンロードされる
5. しあわせ

##スクリプト

```js:
{
  let loader=(src,callback)=>{
    let s=document.createElement('script');
    s.src=src;
    document.body.appendChild(s);
    s.onload=()=>{callback()};
  }
  loader('//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js',
    ()=>{
      loader('//cdn.jsdelivr.net/npm/table2csv@1.1.3/src/table2csv.min.js',
        ()=>{
          jQuery('table').on('click.table2csv',function(){
            jQuery(this).table2csv('output',{appendTo:'#out'});
            jQuery(this).table2csv('output', {filename:'table.csv'});
            jQuery(this).table2csv();
            jQuery('table').off('click.table2csv');
          });
          alert('CSVとしてダウンロードしたいtable要素をクリックしてください');
        }
      )
    }
  );
}
```
##使用したライブラリ
- table2csv CDN by jsDelivr - A CDN for npm and GitHub - https://www.jsdelivr.com/package/npm/table2csv
NumPyに入門 3 CSVから抽出


今回はNumPyでCSVファイルを読み込んで、データの整形を行います。
以下からiris.csvをダウンロードします。

https://github.com/pandas-dev/pandas/blob/master/pandas/tests/data/iris.csv

----

CSVのデータを全て読み込んでiris_dataに入れます。

```.py
import numpy as np
import csv

with open('iris.csv', 'r') as csv_file:
    reader = csv.reader(csv_file, delimiter = ",", quotechar = '"')
    csv_data = [row for row in reader]

iris_data = np.asarray(csv_data)
```


----

読み込んだままだと以下のようにヘッダーがある状態です。

```.py

>>> iris_data[:5]
array([['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth', 'Name'],
       ['5.1', '3.5', '1.4', '0.2', 'Iris-setosa'],
       ['4.9', '3.0', '1.4', '0.2', 'Iris-setosa'],
       ['4.7', '3.2', '1.3', '0.2', 'Iris-setosa'],
       ['4.6', '3.1', '1.5', '0.2', 'Iris-setosa']], dtype='<U15')
```

----

`iris_data[1:]` で1行目以降だけを返して新しいNumPy行列を作ります。

```.py
>>> iris_data = iris_data[1:]
>>> iris_data[:5]
array([['5.1', '3.5', '1.4', '0.2', 'Iris-setosa'],
       ['4.9', '3.0', '1.4', '0.2', 'Iris-setosa'],
       ['4.7', '3.2', '1.3', '0.2', 'Iris-setosa'],
       ['4.6', '3.1', '1.5', '0.2', 'Iris-setosa'],
       ['5.0', '3.6', '1.4', '0.2', 'Iris-setosa']], dtype='<U15')
```

----

数字の列だけを抽出して、新しい配列を作成します。

```.py
>>> select = lambda row: [float(row[0]), float(row[1]), float(row[2]), float(row[3])]
>>> iris_data = np.array([select(row) for row in iris_data])
>>> iris_data[:5]
array([[5.1, 3.5, 1.4, 0.2],
       [4.9, 3. , 1.4, 0.2],
       [4.7, 3.2, 1.3, 0.2],
       [4.6, 3.1, 1.5, 0.2],
       [5. , 3.6, 1.4, 0.2]])
```

----

集計してみます。

```.py
>>> iris_data.sum()
2078.2
>>> iris_data.sum(axis = 0)
array([876.5, 458.1, 563.8, 179.8])
>>> iris_data.mean(axis = 0)
array([5.84333333, 3.054     , 3.75866667, 1.19866667])
```

----

整形したデータをファイルに保存して、あとで読み出します。ファイル名の拡張子は`.npy`がおすすめです。

```.py
np.save('iris.npy', iris_data)
```

```.py
>>> iris_data2 = np.load('iris.npy')
>>> iris_data2[:5]
array([[5.1, 3.5, 1.4, 0.2],
       [4.9, 3. , 1.4, 0.2],
       [4.7, 3.2, 1.3, 0.2],
       [4.6, 3.1, 1.5, 0.2],
       [5. , 3.6, 1.4, 0.2]])
```

動画で説明を作りました。よかったらご覧ください。
https://youtu.be/sxObw5_pVvc
WAI-ARIAを使ってコーディングする

#WAI-ARIAとは？
webページ上のコンテンツに対して、アクセシビリティを補完する為の属性を定義した仕様です。

#なぜ必要？
アクセシビリティの為。
今のウェブサービスの場合、汎用要素でコンテンツを動的に作る事が多い為、HTMLだけではマシンリーダブルにする事がむずかしくなっています。
この為、HTML＋WAI-ARIAでアクセシビリティの向上させる事が必要になってきています。

##ところでアクセシビリティとは？
情報へのアクセスのしやすさ、利用のしやすさの事です。
ウェブの場合だと、ウェブサイトの情報や機能の利用しやすさの事をさします。

##HTMLとの関係
WAI-ARIA単独でアクセシビリティの向上を図るのではないです。
HTMLを補完する目的でWAI-ARIAが存在します。

*HTML（基本） ＋ WAI-ARIA（補助）*
https://developer.mozilla.org/ja/docs/Learn/Accessibility/WAI-ARIA_basics#When_should_you_use_WAI-ARIA

#WAI-ARIAの構造
下記3つから成り立ちます。

##role
要素が何か、もしくは何をするかを定義
role属性として定義します。

###例：ナビゲーション
```html
<div role="navigation">
ナビゲーション群
</div>
```

##property
要素の性質/特性を定義
`aria-***`で定義します。

###例：必須の入力項目
```html
<input type="number" aria-readonly="true"></input>
```

##state
要素の現在の状態を定義
`aria-***`で定義します。

###例：読み込み中を表したい
```html
<div class="LazyPlaceholder" aria-busy="true">読込中</div>
```


#参考
WAI-ARIA1.2　日本語訳
https://momdo.github.io/wai-aria-1.2/

WAI-ARIA の基礎知識
https://website-usability.info/2014/04/entry_140415.html

WAI-ARIAを活用したフロントエンド実装
https://app.codegrid.net/entry/wai-aria-1
Google Apps Script でスプレッドシートに記載されたアドレス宛にメールを送る


# 背景・動機

営業部門から Google フォームを使った簡単なお問い合わせフォームを依頼され作成しました。
その際に、 Google Apps Script でスプレッドシート上のセルに記載されたメールアドレス宛にメールを送信するマクロを作成したため、備忘録を兼ねて投稿します。
似たような事例でお悩みの方の参考になればと思います。

# 実現したいこと

- Google フォームから入力されたメールアドレス宛に返信メールを送信したい。
- 返信するメールの本文は、返信する相手によって変更したい。
- メールを返信した行がわかるようにしたい。

Google スプレッドシートは以下のような構成とします。

| タイムスタンプ          | メールアドレス        | メール本文 | メール送信済み |
| :-----------------: | :---------------: | :------: | :---------: |
| 2019/01/02 10:11:30 | test1@example.com | ここに本文  | 済み         |
| 2019/01/03 11:12:30 | test2@example.com | ここに本文  |             |
| 2019/01/04 12:13:30 | test3@example.com | ここに本文  | 済み         |

# 実装方法

Google Apps Script でメールを送信するには、以下のようなプログラムを書きます。

```javascript
MailApp.sendEmail({
  to:"メールアドレス",
  subject:"件名",
  body:"本文"
});
```

これを使って Google Apps Script 上に用意した関数をマクロとして登録し、スプレッドシートの選択した行のデータを参照してメールを送信します。

```javascript
// メイン関数
function main() {
  // 送信確認を表示
  var accept = Browser.msgBox("メールを送信しますか？", Browser.Buttons.OK_CANCEL);
  if (accept == 'cancel') {
    return;
  }

  // 選択した行番号を取得
  var sheet = SpreadsheetApp.getActiveSheet();
  var rowNum = sheet.getActiveCell().getRow();

  // メール送信済みの場合エラー表示
  var isAlreadySend = sheet.getRange(rowNum, sheet.getLastColumn()).getValue();
  if (isAlreadySend == '済み') {
    Browser.msgBox("既に送信済みです。");
    return;
  }

  // 行のデータを取得
  var row = sheet.getRange(rowNum, 1, 1, sheet.getLastColumn());
  // メールを送信
  sendMail(row.getValues());

  // 送信済みにする
  Browser.msgBox("送信しました");
  sheet.getRange(rowNum, sheet.getLastColumn()).setValue('済み');
}

// メール送信
function sendMail(rowData) {
  MailApp.sendEmail({
    to: rowData[0][1],
    subject: 'お問い合わせありがとうございます',
    body: rowData[0][2]
  });
}
```

Google スプレッドシートのメニューから、[ツール]->[マクロ]->[インポート]の順に選択し、作成した関数「main」をマクロとして登録すれば完了です。

Google スプレッドシートのマクロを使えば、簡単な作業は自動化でき大変便利ですので、ぜひみなさんやってみてください。
Linuxのプロンプトに時刻表示を追加する

## この記事の目的
Linuxにログインすると出てくる以下ような表示がプロンプトの表記の変更をする

```
[hoge@hoge01 ~]$
```

## 設定ファイル(.bashrc)を開いて値を変更
```
$ vim ~/.bashrc
```
### .bashrcのデフォルト状態（CentOS7.5)
```
# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=

# User specific aliases and functions
```
"# User specific aliases and functions"以降に以下を追加

```
PS1='(\t)[\u@\h \W]\$ '
HISTTIMEFORMAT='%Y-%m-%d %T '
```

## 結果
```
(22:42:24)[hoge@hoge01 ~]$
```
## 感想
地味に便利！！
33日目 Googleフォームで入力して、GoogleMapに読ませたい！

[昨日](https://qiita.com/robamimim/items/459a68c8b71cb082c63d)に引き続き
[発達さん住みよいマップ](https://www.google.com/maps/d/u/0/viewer?mid=137ZeuIzWRw2qKArTeg3Qy2WGz8TGiOjJ&ll=35.507036808330305%2C135.09495705000006&z=5)を作っています。

ツイッターで発達さんお役立ち情報をくださいとツイートしたら、さっそく情報をお寄せ頂きました。ありがとうございます！
何件か追加して気がついたのですが・・・これ、入力するの結構大変です。そこで、入力用にGooeleスプレッドシートをつくりました。

>発達障害お役立ち情報をシェアしたいです。
行って良かった所、お気に入りの場所、危なかった場所など、おしらせください！
[発達さん住みよいマップ](https://docs.google.com/forms/d/e/1FAIpQLSdUjBLCnZH1pzDqZGjogp2BMRXZQsDSV6yU7S8rT3fgd-bO7g/viewform)


###都道府県を自動入力したい
住所の入力が簡単にならないかなと調べたのですが、Googleフォームでは自動入力はできないみたいです。
自分でホームページを作れるなら郵便番号から自動入力を作る方法はいろいろあるようです。

[郵便番号から住所を自動入力してくれるライブラリ「ajaxzip3」が超簡単！](https://haniwaman.com/ajaxzip3/)
[そこそこユーザビリティの高いフォームを作った](https://note.openvista.jp/2014/usable-form)
[■郵便番号から住所を自動入力するフォーム](http://www.sharots.com/netshop/code.html)

都道府県を選択するボタンは作れそうなのでやってみました。

[Googleフォームのアンケートに自動で47都道府県の選択肢を入れる方法](https://www.megaya.net/entry/2017/12/07/192600)

しかし、スクリプトの画面が開きません。調べてみたら、Googleのデフォルトアカウントでないと開けないのだそう。
[Googleスプレッドシートのスクリプトエディタを表示できない！GASが編集できない！](https://ntwmachine.com/gss-script-editor-noopen)

スクリプトをコピペして実行、４７都道府県のメニューがずらりと並びました。面白い！
しかしマイマップに読ませるのに邪魔なので消しました。もったいない！
(所要時間 60分)

###GoogleマイマップにNPOの一覧を読み込ませたい
全国77箇所の発達障害支援センターはさくっと読み込めたのですが、NPOのリストを読み込ませたらエラーで全く読み込めません。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356263/5ab4f775-9aa4-ea6f-3726-75bd2ced3b7e.png)

リストを半分にして読ませて、また半分にして読ませて・・・何回目かで読み込みました。
日本語を嫌がっているのかと思ったのですが、それだけではないようで。くやしいですが諦めました。
(所要時間 45分)

###個人情報はどこまでもらう？
最初、Googleフォームで「ご連絡先」をいただいて、情報が確かかどうか確認して大丈夫そうだったらのせようと思ったのですが、、、もしまずい情報が書き込まれて、それが流れたらどうしようと考えてしまいました。そこで入力内容を減らして、名称、住所、レビュー、いい感じ度の４つに絞りました。いろいろ悩みますね。
(所要時間 30分)

###カテゴリ毎にピンの色や形をわけたい
これは簡単。ロードしたデータの下に「均一カテゴリ」というリンクがあるのでこれをクリック。任意の列の任意のカテゴリ毎に色や形を分ける事ができました。

###Googleフォームにレコードが追加されたら、Googleマイマップにも追加されてほしい
いろいろ調べましたが、毎回、読み込み直しになるようです。自動で追加されてほしいのですが・・・それはまた作らなきゃみたいです。
さらに面倒なのはピンの色。カテゴリ毎にわけたのに読み込むたびに自動で適当な色を割り当ててしまいます。カテゴリーの数を減らしました。
(所要時間 60分)

###住所のデータを作る。
名称で検索して住所を探して入力して・・・ってけっこう手間でした。
(所要時間 60分)

###Googleマイマップに読み込むとエラーになるデータがある
100件読むと10件は読めませんでしたエラーになります。ちゃんと住所をフルで入れているのに。半角スペースを削除すると再度読み込んでちゃんと地図上に表示されました。逆に半角スペースを入れたら読んだりして・・・何が気に入らないんだ。謎です。
(所要時間 30分)

そしてここまで完成！
[発達さん住みよいMAP Ver3](https://www.google.com/maps/d/u/0/viewer?mid=137ZeuIzWRw2qKArTeg3Qy2WGz8TGiOjJ&ll=35.507036808330305%2C135.09495705000006&z=5)

こんなシンプルな地図なのに、こんなに大変だとは・・・
当面は手作業で頑張ってみるつもりですが
もっとサクっとできる方法がないか探してみようと思います。

(トータルで６時間くらい？)
独自データで物体検出 ーTensorFlow object detection function APIの使い方ー

別の記事の副産物として、```TensorFlow object detection function API```を用いて
物体検出を「独自データ」で学習させました。学習手順をメモ代わりに残しておきます。

#学習の手順
既にvictordibiaさんが書いた素晴らしい[手順書](https://github.com/victordibia/handtracking)があるので、そちらをグーグル翻訳しながら進めました。**Data preparation and network training in Tensorflow**の部分に学習の手順が書いてあります。

ちなみに、このリポジトリでは、データのダウンロードからアノテーションの編集作業まで全て自動化されています。もし、画像を自分で用意する場合はアノテーションの部分を編集する必要があると思われます。

ただし、```train.py```を実行する際は、仕様が変わったらしく以下のサイトを参考に進めました。
https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/running_locally.md

##Colaboratoryを使う場合
Colaboratoryで学習させるといくつかエラーが出るので、以下のサイトを参考に進めました。
https://stackoverflow.com/questions/54778472/google-colab-tensowflow-object-detection-api-function-object-has-no-attrib

Colaboratoryでは、一回で演算できる制限（12時間ルール）があります。
12時間以上学習させる場合は、一回frozenモデルを出力すれば、再度学習を継続することができます。

もしかしたら、以下のリンクも参考になるかもしれません。
https://github.com/RomRoc/objdet_train_tensorflow_colab/blob/master/objdet_custom_tf_colab.ipynb

また、Tensorboardを出したい場合は、以下の記事が参考になります。
https://qiita.com/kazuyakitahara/items/ef92f93afba5462e9cb3

#学習させてみた
victordibiaさんを見習い、手の検出を学習させてみました。
結果は以下のとおりです。

||オリジナル(victordibiaさん)|今回|
|---|---|---|
|学習回数|200k|100k|
|モデル|SSD-MobileNetV2?|SSD-MobileNetV1|
|mAP50|**0.9686**|0.89|

今回はColaboratory（GPU）で学習させました。100kで合計15時間ほどかかりました。
mAP50は精度みたいなものです。最大値は「1」で、この値が高いほど精度が良いです。

##結果
私の方がmAP50が低いので、少し不安になりました。

そこで、写真を使って実際に物体検出させてみました。
このやり方も上記で示したリンクに書いてあります。

結果は以下のとおりです。

![sum1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264781/7f10197e-c6ff-d0df-a8bb-8b6141b3b50e.png)
![sum2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264781/729e145f-e7a7-86e0-82c0-d64e603b7d2b.png)


左側はオリジナルモデルを使った検出、右側は今回学習したモデルで
検出した結果です。

精度はほとんど変わらないことが確認できました。

#まとめ
+ データさえ入手すれば、簡単に物体検出できる時代になりました。
+ TensorFlow object detection function APIを使った事例として、[手](https://github.com/victordibia/handtracking)の検出だったり、[アライグマ](https://towardsdatascience.com/how-to-train-your-own-object-detector-with-tensorflows-object-detector-api-bec72ecfe1d9)の検出だったり、[マカロニ](https://pythonprogramming.net/testing-custom-object-detector-tensorflow-object-detection-api-tutorial/)の検出だったり面白い報告がたくさんあります。
gitコマンド一覧備忘録

#gitコマンド一覧


```
#ディレクトリ以下のファイルを保存
$ git add .

#※cherrypick今後編集予定

#どこにいるか関係なくすべてのファイルを保存
$ git add -A

#gitを保存する
$ git commit -m "コミットメッセージ"

#ブランチを切る
git checkout -b ブランチ名

#ローカルブランチをリモートにプッシュする
git push origin プッシュするブランチ名

新しいブランチを切る
git checkout origin/develop -b feature/12345

リモートブランチからpulする（getch merge版）
git fetch origin
git merge origin/プルしたいブランチ名

```
DBFluteにおける自動設定値

■共通カラムの更新
各テーブルの共通項目(システム更新日付等)は
下記設定ファイルで定義され、
アプリケーション側からパラメタとして渡す必要はない。
設定ファイル : commonColumnMap.dfprop

---
■バージョンの更新
排他制御に使われるカラムは、
自動的にインクリメントされるため、
アプリケーション側でインクリメントして渡す必要はない。

---
■更新不要項目について
Entityに対して、更新(setXXX())を行った項目のみ更新対象となる。

---
■参考
http://dbflute.seasar.org/ja/manual/function/ormapper/behavior/update/update.html
(DBFlute公式 : Updateについて)
Jetson nano へ tensorflowをインストールする


# 参考
https://devtalk.nvidia.com/default/topic/1048776/jetson-nano/official-tensorflow-for-jetson-nano-/

# 手順
python3.6 only

```
sudo apt-get install -y python3-pip libhdf5-serial-dev hdf5-tools
pip3 install --extra-index-url https://developer.download.nvidia.com/compute/redist/jp/v42 tensorflow-gpu
```
スクレイピング で画像習得

今回は自分のサイト、「藍名樹の映画と本のブログ」https://www.ainaitsuki.com
から画像を習得するスクレイピングを書いていきます。

まずは必要なライブラリ「selenium」や、Google Chromeを使うための設定をしていきます。


```
#※seleniumやChromeをインストールしておかなければなりません。
from selenium import webdriver
browser = webdriver.Chrome()
```
これでGoogle Chromeを使いスクレイピングをすることが出来るようになったので、browser.getで自分のサイトを開いてみます。

```
browser.get('https://www.ainaitsuki.com')
```
すると
<img width="1280" alt="スクリーンショット 2019-04-14 19.37.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371552/74395c4b-7ec1-01d6-fe88-e3d626bf6eaf.png">
きちんと自分のサイトが開きました。
今回はこの見えている猫ちゃん画像を習得したいと思うので、まずMacであれば検証を使い猫ちゃん画像に照準を合わせましょう。
すると
<img width="1280" alt="スクリーンショット 2019-04-14 19.40.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371552/4c75b8b2-e6a0-c3ff-2224-fc0c76853b6e.png">

左側に画像の情報が出てきました。
ただこれを直接抜き出すのではなく、その上の「id」部分をみてみましょう。
idに代入されているのが、「st-headerbox」というものですね。
まずはそれを指定します。

```
elem = browser.find_element_by_id('st-headerbox')
```
で取り出すのがimgなので、それを指定してあげます。ただ注意しないといけないのが、idではなくtagだということです。さらにnameもつけないといけません。

```
elem = elem.find_element_by_tag_name('img')
```
続いて画像のソースを抜き出します。
こちらはsrcを指定します。それをurlに代入します。

```
url = elem.get_attribute('src')
url
```
すると画像のurl```'https://www.ainaitsuki.com/wp-content/uploads/2018/04/cropped-cat126IMGL6488_TP_V.jpg'```を習得することができました。

では次に画像を習得するためのライブラリをインポートします。

```
import io
from urllib import request
```
で、次にメモリ上でバイナリデータを扱うために、io.BytesIOを使います（自分もio.BytesIOが何かよく分かっていませんが、画像を習得するために必要な工程だそうです)。そしてfに代入します。

```
f = io.BytesIO(request.urlopen(url).read())
```
するとfに```<_io.BytesIO at 0x10b997048>```が入ります。

次に画像を表示するためのライブラリをインポートします。

```
from PIL import Image
###そして先ほどio.BytesIOを入れたfを開きます。
img = Image.open(f)
img
```
すると
<img width="974" alt="スクリーンショット 2019-04-14 22.28.04 1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371552/cf10f1bf-50c6-6bba-5ffd-37b406c41e19.png">
しっかりと画像を表示することができました。
ではこれを自分のファイルに保存します。

```
img.save('img01.jpg')
```
これでしっかりと保存されたので、スクレイピングにて画像を保存する方法を終わりたいと思います。
[メモ] 朝会

## 朝会を有意義にするため

- 宣言の場にする
  - 今日どこまで
  - 昨日できなかった理由
- 感謝の言葉を伝える

## 参照
[朝会を有意義にする6つのプラクティスとやってはいけない6つのアンチプラクティス \- Fight the Future](https://www.sakatakoichi.com/entry/20080220/1203498760)
悲観ロックと楽観ロック

■悲観ロック
・更新処理の頻度が高い場合に採用する。
・SELECT ～ FOR UPDATEなどをかける。
・DB側でロックをかける。
・あらかじめロックをかけておこうの精神

---
■楽観ロック
・更新処理の頻度が低い場合に採用する。
・DBでなく、アプリケーション側(O/Rマッパーなど)で排他処理を行う。
・とりあえず更新してみてダメだったらやり直そうの精神
・リードアンコミテッドは防げるが、アンリピータブル／ファンタオムは防げない。
1.更新対象エンティティのバージョンを取得する。
2.エンティティの更新処理を完了させる。
　　UPDATE 　T 
　　SET　　　  T.VERSION = VERSION + 1
　　WHERE      　T.VERSION = VERSION
3.バージョンが変更されているかどうか判定
　(更新結果が0件かどうかで判定する。)
　3-1.変更なし
  　　バージョンをあげてコミットする。
　3-2.変更あり
  　　トランザクションをロールバックする。

---
■DBFluteでの排他処理 (更新時)
メソッドによって使い分ける。
楽観的ロック : update()        
排他的ロック : updateNonstrict() などなど

第三者が
　更新済み : 「EntityAlreadyUpdatedException」発生
　削除済み : 「EntityAlreadyDeletedException」発生

■DBFluteでどのカラムをバージョン情報とみなすか。
・カラム名が「VERSION_NO」の場合、自動でそれを採用する。
・それ以外の場合、設定ファイルの編集が必要。
　littleAdjustmentMap.dfprop
　　-> optimisticLockMap 
　　　-> versionNoFieldName = カラム名

■DBFluteでの排他処理 (検索時)
一覧画面で取得したデータが詳細画面表示時に削除されてしまった場合
selectEntityWithDeletedCheck() などでチェックができ
削除済みの場合、例外「EntityAlreadyDeletedException」が発生する。

---
■参考
https://seroku.jp/wp/アプリケーション開発におけるロックの重要性と-2/
(楽観ロックのイメージ図 : ロストアップデート状態となる楽観的ロック使用時)

http://dbflute.seasar.org/ja/manual/function/genbafit/implfit/exclusivecontrol/index.html
(DBFluteの楽観的ロックの説明)

http://dbflute.seasar.org/ja/manual/function/ormapper/behavior/update/update.html
（DBFluteの更新処理について)
技術書典6 当日振り返り


技術書典６に出展してきたので振り返りです。
前回記事に続き、これから初めて出展する！という方の参考になればいいなと思います。

前回記事　→ [技術書典６に出すまで振り返り](https://qiita.com/wicket/items/0ba55fccc76b87d25bfe)


# 被チェック数の推移と売れ行き

おそらくみんなが気になるのはこれですね。
被チェック数を直前まで記録していなかったため、直近のみとなりますが、こちらです。
<img width="471" alt="スクリーンショット 2019-04-14 21.26.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/809516d9-b83d-ccaa-b82a-9b0ed9fbb20c.png">

実施４日前に１００を超え、当日朝で240、当日終了時で300超えました。
それに対して販売数は106冊(物理本98冊+PDF版8冊)でした。

目安として考えるのであれば、４日前の被チェック数分、もしくは当日朝のチェック数の40%ぐらいでしょうか。

14:30に物理本が売り切れてしまったので、もしかしたらもう少し印刷を多めにしても良かったかもしれません。


# ブースデザイン
![IMG_2943.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/33433867-7a7e-47b6-caf3-cf5e57f711b4.png)

### サイズ
思ったより狭いです。立ち読みする人が隣のブースにはみ出て迷惑になることがあるので、適宜そっちに行かないように促す必要がありました。　

### 金額表示
見本誌に値段を書いていたけれども、誰かが立ち読みしていると値段がわからない事案が発生しました。当たり前ですね。

見本誌に書く値段とは別に、明示的なプライスカードを用意するべきでした。

### 光り物
NexPixcelの光る眼鏡をずっとつけていましたが、時々きになって立ち寄ってくれる人がいたのは良かったです。やはり、光る／動く／音がなるは人の目を引いて良いです。
ここはハードウェア関係本の人は特色を一気に出していきたいですね。

### ポスターとか
机が人混みで隠れるので、縦方向に伸びる何かがあったほうが良かったです。
ポスター＋三脚とか。

本を手に持って掲げながらの呼び込みはある程度効果があったのかなと思います。

### 見本誌の数
1冊でやろうとしたが、無理でした。見本誌待ちの列ができてしまいます。
2冊はほしいです。
（今回は見本誌じゃなくても立ち読みいいよ！って雰囲気でごまかしました。）

100冊売るなら見本誌２冊、２００冊売るならその倍とかいるんですかね。

### 簡単後払いの対応
とても便利でした！これの対応は必須と言えると思います。
来客者も慣れた感じでしたし、小銭の対応がなくなるのはでかいです。

簡単後払いなら小銭の心配しなくていいのでギリギリまで値段下げる・・とかしたいですね。(現金：1000円、後払い900円とか）


# 人関係
### 売り子
２人は必須です。１人だとトイレにもいけない・・・。



### 掛け声
したほうがお客さんの入りが良かったです。
特に、皆さん丁寧なのか、「手にとっていいですよ」の一言がないと見本誌を手に取らない方々が多かったです。
見本誌なので勝手に取って読んでいいんですけどね。

### ブース巡り
開始前は優遇になるので（？）販売禁止らしいですが、１１時の会場してからお客さんが入ってくるまでの間の数分に駆け込み買いをする方が多かったです。

今回は2人で、最初は慣れるために２人体制、30分たった頃に１人ずつ交代でブースめぐりしました。行きたいブースの事前チェックをしておいたので、スムーズに巡って返ってこれて、自分のブースにいない時間も少なくできてよかったです。


# 持ち物関係

あってよかったもの／ほしかったもの

 - はさみ
 - セロハンテープ
 - ふせん／ラベルシール／スケッチブック
 - 太字のペン
 - プライスカード
 - ポスタースタンド
 - 飲食物

### ブース準備時

印刷所から届いていた箱を開けるのにハサミが必要です。また、ブース設計になにかとセロハンテープが活躍しました。

今回、ふせん＋セロハンテープで「見本誌」や「1000円」と書いていましたが、ラベルシールがあればそちらのほうがきれいだったかもしれません。
ふせんにしろラベルシールにしろ、それに書くための太字のペンは持っていくべきでした。

ポスタースタンドやプライスカードは前述のため省略.


### 飲食
お昼準備しましたが、食べる暇なくそのまま持ち帰ることになりました。食べるの忘れるぐらい熱中してたとも言えます。

逆に水分は、500mlペットボトル3本用意していきましたが足りず、４本目を買いに行きました。自販機は会場出てすぐのところにあるので、再入場規制期間（AM？）以外は手軽に買いに行けると思います。

# お客さんの反応

見本誌の見方としては下記のパターンが多かったです。

- ぱらぱらと全体を見る
- はじめにをじっくり見る
- 目次をみる


つまり、

- ぱらぱらと全体を見る → 写真／イラストに惹かれる 
- はじめにをじっくり見る　→　導入文章に惹かれる
- 目次をみる　→　全体構成に惹かれる

それ以外の、例えば第３章の本文なんて、誰も見本誌では読んで無いんじゃないでしょうか。
本の文章の中でも、イラストや写真でわかりやすくなっているか、導入文書できちんと人が惹きつけられるか、目次を見ただけで内容イメージができて興味が沸くか　というは、本を作る中でも特に重要そうです。



# まとめ

いろいろもっとこうしたら良かったーはあるものの、十分合格点を出せるぐらいの展示はできたと思います。えいやっ！っていってもなんとかなるものなので、とりあえず申し込んで見る　からのてがるな参加が増えればいいなと思っています。
Squidって何？

**※超超超初心者の自分用忘備録※**
**※いろんなとこから情報を集めてきて貼り付けておくだけ※**
**※多分お役には立てません※**

# Squidとは？
プロキシ (Proxy) サーバ、ウェブキャッシュサーバなどに利用されるフリーソフトウェア。
当初はUNIX系OS向けに開発されていたが、現在はWindowsを含むほとんどのOSで利用可能であり、GNU GPLライセンス下で利用できる。

## 用途
重複リクエストに対したキャッシュ応答によるウェブサーバの高速化や、ネットワーク資源を共有する人々が行うWorld Wide WebやDNSなどの様々なネットワーククエリのキャッシュなど、多岐にわたる。

HTTP、HTTPS、FTPをはじめとする多様なプロトコルをサポートしているが、主にHTTPとFTPで利用される。
TLS/SSL、HTTPSなどのセキュリティで保護された通信のサポートも行われている。
また、ウェブキャッシュ機能により、特にフォワーディングプロキシとして利用される場合は利用する組織外へのウェブ系のトラフィックを削減することができる。


# 動作モード
Squidには、用途に合わせて次の3つのモードがある。

## フォワーディングプロキシ
Squidの最もポピュラーな機能。
インターネット上のウェブサーバなどに接続する際に、ウェブアクセスを中継する機能のこと。
主にローカルネットワークの出口に設置される。
クライアントは通常、ウェブブラウザの「プロキシ設定」によりフォワーディングプロキシをプロキシサーバとして設定して利用する。

フォワーディングプロキシを利用する主な理由は次の通り。

1. ウェブキャッシュ機能と組み合わせてネットワーク外部へのトラフィックを軽減する
2. ウェブリダイレクト機能と組み合わせて、内部ネットワークからアクセスできる先を制限する（ペアレントコントロールもこの機能を利用している）
3. 認証機能と組み合わせて、ネットワーク内からのウェブアクセスを個人レベルで制限する
4. 接続サイトによってインターネット回線を使い分ける

### 多段プロキシ
Squidは、中継したウェブのリクエストを直接ウェブサーバに接続して処理するだけでなく、後段のプロキシサーバに中継する機能も持っており、これを多段プロキシという。
巨大なネットワーク内でプロキシの階層構造を組むこともできるし、外部のSaaSとして提供されているウィルスチェックプロキシへの中継としての用途としても利用されている。
後者の利用方法では、ウィルスチェックプロキシ自体が全世界のURLを完全に処理することができないなどの理由で、一部URLについてはウィルスチェックプロキシへバイパスしないようにするなどといった利用がなされている。

## リバースプロキシ
インターネットからのウェブアクセスを代表して受信し、内部にあるウェブサーバ群との通信を中継する機能である。
このためウェブサーバ群の入り口部分に窓口として設置されるのが一般的である。
リバースプロキシを導入することにより、内部のウェブサーバの負荷分散を行ったり、URLごとにサーバを振り分けたりすることができる。
特に後者の利用方法では、アプリケーションサーバを別々に用意している場合や、同一ドメインながらコンテンツを別々の開発会社が作成しそれぞれ別々のサーバに収容されている場合などによく用いられる。

## 透過プロキシモード
透過プロキシとは、利用者がプロキシの存在を意識することなく利用できるプロキシのことであり、ネットワークの出口に設置されたルータなどと組み合わせて利用する。
広い意味では、リバースプロキシも透過プロキシと見ることができる。
技術的には、特定ポートへ向けたアクセスのみをルータから透過プロキシサーバに対して振り向け、透過プロキシは通常のHTTPなどのリクエストを受け付けたふりをして接続先のHTTPサーバへリクエストを中継する。
Squidはこの機能をサポートしている。

Linuxサーバでは、Squidとiptablesのパケットリダイレクト機能と組み合わせることによって透過プロキシを実現することができる。
PythonでSeleniumを使っていたときに発生した例外とその対処について

# 概要
seleniumを使用した中で発生した問題と対処法をまとめていきます。今後追記するかもしれません。
pythonで使用したケースとなります。
[以前の記事](https://qiita.com/snowp/items/9734028cecb68b9940a1)を作成中や仕事でやっていた時の問題と対処を記載しています。
`seleniumOperationBase.py` を参照していただければ対処例がわかります。
いろいろと至らないところもあるかもしれますが・・・

## TimeoutException

たぶん一番多く見ることになります。
原因としては

* 画面描画前にクリックなどをしようとしてしまった。
* そもそも要素の指定を誤っている

が考えられます。
要素の指定のほうは画面を改めて確認するしかないのですが、描画前にクリックしてしまう場合は

```
        driver=webdriver.Chrome('C:/webdrivers/chromedriver.exe')
        # 画面描画の待ち時間
        wait=WebDriverWait(self.driver,20)
        driver.implicitly_wait(30)
```
と事前に設定をしておいて

```
        wait.until(expected_conditions.element_to_be_clickable((By.XPATH,webElement)))
        driver.find_element_by_xpath(webElement).click()
```
要素が表示されるまで待つようにすれば `time.sleep` などで固定の秒数を待たせたりしないですみます。


* 以下のような　`disabled-content-overlay` が出た場合

```
selenium.common.exceptions.ElementClickInterceptedException: Message: Element <button class="btn btn-sm submit-btn menu-btn extra-btn " type="button"> is not clickable at point (875,551) because another element <div class="disabled-content-overlay"> obscures it
```
画面のボタンをクリックすることで表示されるメニューをクリックしたいときに
要素が重なっている場合に発生します。
画面によってはお目にかかることはないですが発生したときは困りました・・・
以下のようにjavascriptでクリック処理を行えば対応できました。

```
            target = driver.find_element_by_xpath(webElement)
            driver.execute_script("arguments[0].click();", target)
```

## StaleElementReferenceException

waitを入れていてもアプリの状況によって画面が描画される前に
クリックした扱いになって発生する例外です。

```
        except StaleElementReferenceException:
            # 画面描画前に押下してしまったときの対応
            time.sleep(1)
            driver.find_element_by_xpath(webElement).click()
```
と発生したときはちょっと待機を明示的に入れて押下してみました。

## MoveTargetOutOfBoundsException

クリック後マウスを動かす処理を `ActionChains` で実施しているときに
画面の範囲外の場合失敗するのでその時は以下のようにスクロール処理をいれました。
この例外をキャッチして動かす方法と事前に動く方法があります。
事前に画面の位置を動かしても失敗することがあるので画面の位置を動かしてから失敗したら例外をキャッチして動くようにしています

```
            inputLabel=driver.find_element_by_xpath(webElement)
            driver.execute_script("arguments[0].scrollIntoView();", inputLabel)
```

`javascript error: arguments[0].scrollIntoView is not a function`とエラーが出てしまう場合は以下の方法でも対応できます。
ただし公式ドキュメントでは予告なしで変わるかもとあるので注意

``` python
inputLabel.location_once_scrolled_into_view
```


## SessionNotCreatedException

webdriverのバージョンが異なっているときに発生します。webdriverのバージョンを更新しましょう。

```
selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 76
```
MiRmサービスのAndroidアプリを作った

MiRmサービスのプロダクトの一つとして、サーバーを管理するアプリを作ってみた。
簡単に紹介を。

![Screenshot_1555139632.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237903/30f790f2-3441-a21c-c4d4-251a4eb90f7f.png)


# 自己紹介
普通科の高校に通う２年生男子。
Javaを主に使っている。kotlinも少しづつ...
MiRm（Minecraftの無料マルチプレイサーバー　ホスティングサービス）の開発チームをやってる。

# MiRmとは
Minecraft BEでマルチプレイをしたい！
↓
サーバーを立てなきゃ！！
↓
サーバーがないよ...
↓
じゃあサーバーを借りたいな←ここと
↓
サーバーは借りれた。面白くするためにプラグインも入れよう！←ここをやってくれるサービスです。
↓
わーい~~（友達がいなかった）~~

## 詳しく
@haniokasai 氏が始動したプロジェクト。
https://mirm.jp を参照。

# アプリで何ができるの？
- 立てたサーバーを起動・停止する
- サーバーのステータスを確認する
- サーバーを共有する
- サーバーの利用期間を更新する

などなど...

# アーキテクチャ
アプリ周辺のみ記載してみた。
アプリ自体は基本的なMVPアーキテクチャを採用した。
SteadyMistressとはシステムの中央サーバのこと。ほかにも各ユーザーのサーバーの起動・メモリ管理やバックアップ等を担っている。
![architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237903/6951750f-9c4c-97be-1717-22b79a30801e.png)

# アプリを支える技術
- Android SDK Java
- Google Firebase（中央サーバーからの通知）
- Google Admob（バナー広告・動画広告）
- Gson（Json処理）
- Junit（テスト環境）
- Zxing Android Embedded（QRコードの作成）

# MiRm API
httpsのGET/POSTによるWeb API通信で起動・停止・強制停止・コマンド送信・標準出力送信などを行った。

# はまったところ
- EditTextでEnterキーを押したときの処理
Enterキーを押したときに入力されたものを取得し、コマンドを送信するという処理を実装しようとしてsetOnkeyListenerをした。
→ソフトウェアキーボードだとイベントが発火しない！
→onTextChanged(TextWatcher)を使って実装
→TextWatcher#afterTextChangedをオーバライドし、改行コードが含まれてるかどうかで処理
このとき、EditTextはmultiline属性にしておいた。
  
- アクティビティに設定したフラグメントをバックキーで切り替えたいが...
一番最初まで戻るとフラグメントがなくなり、真っ白になってしまう！
→一番最初に設定するフラグメントをスタックに積まないようにした

- 重い
AsyncTaskをstaticに管理していたため。禁忌や。やってはいけない！！

- RewardedAdVideoの抽象メソッドが多すぎてコードが冗長化する
状態がいろいろあるから仕方ないと思うが、ここは必要なメソッドだけ抽象化したクラスを定義して対応。


# 課題とか
- UI/UXをもっと改善できるはず。
- 広告のロードが遅いからもう少し早くならないか。
- 将来的にはkotlin/NativeをつかったiOSアプリとのクロスプラットフォームアプリに。
- Googleの審査に落ちないようなアプリにしたい

# 感想
実はAndroidアプリとしては処女作となるアプリだったが、なかなか出来のいいアプリになったと思う。
開発途中にPCがフリーズしたりクラッシュしたりで何度かデータを失った。つらい。今度からはもっと細かいタイミングでGitにコミットしていきたい。

2019/4/25 追記
当該アプリはリリース直後にGoogle Playから削除され、ユーザーが使うことがなかった。
【Node.js】SSH経由でRedisへ接続する

## 概要

[ioredis](https://github.com/luin/ioredis)と[ssh2](https://github.com/mscdex/ssh2)モジュールを使用して、SSH経由でRedisへ接続します。

## 環境

* Node.js v8.15.0
* ioredis v4.2.0
* ssh2 v0.8.2

## 方法

### 依存モジュールを読み込みます。

```javascript
const Redis = require('ioredis');
const { Client: SSHClient } = require('ssh2');
const net = require('net');
const fs = require('fs');
```

### SSHサーバへ接続する関数を用意します。

```javascript
function connectToSSH(options) {
  return new Promise((resolve, reject) => {
    const connection = new SSHClient();
  
    connection.once('ready', () => resolve(connection));
    connection.once('error', reject);

    connection.connect(options);
  });
}
```

### Redisへ接続するためのヘルパー関数を用意します。

```javascript
function connectToRedis(options) {
  const redis = new Redis(options);
  return new Promise((resolve, reject) => {
    redis.once('error', reject);
    redis.once('ready', () => resolve(redis));
  });
}
```

### ポートフォワーディング用の中間サーバを作成します。
`server.listen`の第１引数に`0`を渡すと、システムの空きポートが割り当てられます。

```javascript
function createIntermediateServer(connectionListener) {
  return new Promise((resolve, reject) => {
    const server = net.createServer(connectionListener);
    server.once('error', reject); 
    server.listen(0, () => resolve(server));
  });
}
```

### 一連のヘルパー関数をまとめて、SSH経由でRedisへ接続する関数を用意します。

```javascript
async function connectToRedisViaSSH(options = {
  ssh: {
    host: 'localhost',
    port: 22
  },
  redis: {
    host: 'localhost',
    port: 6379
  }
}) {
  const sshConnection = await connectToSSH({
    host: options.ssh.host,
    port: options.ssh.port,
    username: options.ssh.username,
    privateKey: options.ssh.privateKey,
    passphrase: options.ssh.passphrase
  });

  const server = await createIntermediateServer(socket => {
    sshConnection.forwardOut(
      socket.remoteAddress,
      socket.remotePort, 
      options.redis.host,
      options.redis.port,
      (error, stream) => {
        if (error) {
          socket.end();
        } else {
          socket.pipe(stream).pipe(socket);
        }
      }
    );
  });

  // Redisサーバのアドレスではなく、中間サーバのアドレスを指定します。
  const redis = await connectToRedis({
    host: server.address().address,
    port: server.address().port
  });

  return redis;
}
```

### 作成した関数を利用してRedisへ接続します。

```javascript
const redis = await connectToRedisViaSSH({
  ssh: {
    host: '<ssh-server-address>',
    port: 22,
    username: '<username>',
    privateKey: fs.readFileSync('/path/to/private-key'),
    passphrase: '<passphrase>'
  },
  redis: {
    host: '<redis-server-address>',
    port: 6379
  }
});
const keys = await redis.keys('*');
console.log(keys);
```

## 参考

https://gist.github.com/luoyjx/b2ea3cfaa20fee43258573b90c2e01a9
jetpackの連携ができない時

お名前.comのSD-11のプランのサーバーにインストールしたWordPressで、jetpackのプラグインが、WordPress.comとの連携ができず困っていました。

ネット検索してSSLの関係で躓いた時は、共有や独自のSSLではないSSLを購入するしかないという記事まであり、本当に悩みました。

結果としては、WordPressのSite Guardというプラグインを停止して、ログインページが通常の状態にして、jetpackの設定のソーシャルメディア共有の設定を行うことで連携できました。

また、WordPressのサイトURLが、ルート出ないと連携が難しいことも分かりました。
ドメインの直下にWordPressを設置できたら良いのですが、数段下に配置した場合は、htasseccファイルで工夫する必要があります。

WordPress.comから帰ってくる時は、どうもドメインのURLで戻ってくるようです。
だから、WordPressが直下に配置されていないとadminのディレクトリにアクセスできず、404ページが無いとエラーになってしまいます。

```
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^(.*)$ /hoge/hoge2/$1 [L]
</IfModule>
```
文法が違う部分もあると思いますが、このような記述をして対応しました。
hogeは、実際にWordPressを設置したディレクトリを指定してください。

SSLの証明書は、無料のものや共有SSLでも使えます。
ドメイン直下にWordPressを設置できないときは、jetpackの連携できないようなので、工夫必要ということを今回学んだように思います。

お名前.comは、海外からxmlrpc.phpやログインページへのアクセスを制限しています。
もし、WAFのセキュリティをOFFにするなどしてセキュリティを外してもxmlrpc.phpが動かない時は、お名前.comのカスタマーに相談すると良いです。

```
<Files wp-login.php>
order allow,deny
allow from all
</Files>
<Files xmlrpc.php>
order allow,deny
allow from all
</Files>
```
このコードを、htasseccファイルの先頭行に記載すると、海外サイトの規制を解除できます。
でも、これだと全部解除になってしまうので、jetpackのみ通すように制限したいのですが、共有SSLでは難しいようです。