OmniAICreator/Qiita-1.07M huggingface dataset:
ライセンス的にクリーンなH.264動画エンコードのやり方

## 概要

自分のサービスやソフトウェアで、H.264動画エンコード機能を、ライセンス料を払わずに、ライセンス的にクリーンな状態で、提供する方法を調べました。

## やり方

### インストール
```bash
curl -L https://gist.githubusercontent.com/contribu/8a572edaccb86ae749449a3fec83ce5f/raw/d90b011686e79e8072a5df06673b2b0abc646d94/install_ffmpeg_supporting_openh264.sh | bash
```

### エンコード
```bash
ffmpeg -i input -c:v libopenh264 [他のオプション]
```

## 解説

### H.264のライセンス

- [Wikipedia H.264#ライセンス](https://ja.wikipedia.org/wiki/H.264#%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9)

### openh264とは？

>**Cisco has taken their H.264 implementation, and open sourced it under BSD license terms.** Development and maintenance will be overseen by a board from industry and the open source community. Furthermore, **we have provided a binary form** suitable for inclusion in applications across a number of different operating systems, and make this binary module available for download from the Internet. **We will not pass on our MPEG-LA licensing costs for this module**, and based on the current licensing environment, **this will effectively make H.264 free for use on supported platforms**.
>https://www.openh264.org/

- [ソースコード https://github.com/cisco/openh264](https://github.com/cisco/openh264)
- [ビルド済みバイナリ https://github.com/cisco/openh264/releases](https://github.com/cisco/openh264/releases)

### ソースコードからビルドしたものを使ってはいけないの？

ライセンス料を払わない場合は、ダメみたいです。

>Q. Why is Cisco making both source and binary versions available?
>
>In order for Cisco to be responsible for the MPEG LA licensing royalties for the module, Cisco must provide the packaging and distribution of this code in a binary module format (think of it like a plug-in, but not using the same APIs as existing plugins), in addition to several other constraints. This gives the community the best of all worlds - a team can choose to use the source code, in which case the team is responsible for paying all applicable license fees, or **the team can use the binary module distributed by Cisco, in which case Cisco will cover the MPEG LA licensing fees**.
>
>https://www.openh264.org/faq.html

### openh264に対応したffmpegのインストールスクリプト

作りました
https://gist.githubusercontent.com/contribu/8a572edaccb86ae749449a3fec83ce5f
map, filterの写像でつまづいた(starwars解説)



## Star Warsで解説

```javascript:starwars.js
const episode1 = [
  { name: 'Anakin', jedi: true },
  { name: 'Luku', jedi: true }
]
const episode3 = episode1.map(char => char)

// Dirk side
episode3[0].jedi = false

console.log(episode1)
// [ { name: 'Anakin', jedi: false },{ name: 'Luku', jedi: false } ]
console.log(episode3)
// [ { name: 'Anakin', jedi: false },{ name: 'Luku', jedi: true } ]
```
アナキンはエピソード3でダークサイドに墜ちるので`jedi = false`に変更。
...あれ、episode1でシスに落ちとるがな、ストーリー上ありえないので修正



答えから言うとmap, filterは中のオブジェクトまでは写像しない！

```javascript:starwars.js
const episode1 = [
  { name: 'Anakin', jedi: true },
  { name: 'Luku',
  jedi: false }
]
const episode3 = episode1.map(char => Object.assign({}, char))

// Dirk side
episode3[0].jedi = false

console.log(episode1)
// [ { name: 'Anakin', jedi: true },{ name: 'Luku', jedi: false } ]
console.log(episode3)
// [ { name: 'Anakin', jedi: false },{ name: 'Luku', jedi: false } ]

```

`Object.assign()`でオブジェクト自体も新しいものを作ってあげると解決！
無事ストーリーが進みそう。

##filterでもはまった

jediだけを抽出し配列を作る。前回の反省にならって`Object.assign()`を使う。

```javascript:starwars.js
const episode1 = [
  { name: 'Anakin', jedi: true },
  { name: 'Luku', jedi: true },
  { name: 'Amidala', jedi: false }
]
const episode3 = episode1.filter(char => {
  if (char.jedi) {
    return Object.assign({}, char)
  }
})

// Dirk side
episode3[0].jedi = false

console.log(episode1)
// [ { name: 'Anakin', jedi: false }, { name: 'Luku', jedi: true }, { name: 'Amidala', jedi: false } ]
console.log(episode3)
// [ { name: 'Anakin', jedi: false }, { name: 'Luku', jedi: true } ]
```

アナキンがシスになってる...

ジェダイ図書館で調べたところ、
filterは値が偽の場合値を返さない
真の場合値を**そのまま返す**。
つまり`Object.assign`は実行されていない。

これはおったまげ、ジャージャーが非常事態にパルパティーンに武力行使権を与えるのも納得。

###解決法
```javascript:starwars.js
const episode1 = [
  { name: 'Anakin', jedi: true },
  { name: 'Luku', jedi: true },
  { name: 'Amidala', jedi: false }
]
const episode3 = episode1.filter(char => {
  if (char.jedi) {
    return char
  }
}).map(char => Object.assign({}, char))

// Dirk side
episode3[0].jedi = false

console.log(episode1)
// [ { name: 'Anakin', jedi: true }, { name: 'Luku', jedi: true }, { name: 'Amidala', jedi: false } ]
console.log(episode3)
// [ { name: 'Anakin', jedi: false }, { name: 'Luku', jedi: true } ]
```

なるほど、filterにmapを連結して新しい配列を返す。
ジェダイ・マスターへの道は遠い...
プライベートリポジトリで GitHub Pages を運用した時の挙動を調べてみた

公式ヘルプによると [GitHub Pages は元リポジトリがプライベートであっても構わず公開される](https://help.github.com/articles/what-is-github-pages/) とのことですが、具体的な挙動がよくわからなかったので調べてみました。

# (その1) docs/ 配下以外に置いたファイルは見える?
Ans: 見えない

GitHub Pages の設定を master branch の docs folder にしている場合、docs フォルダ以外に置いたファイルはウェブサイトから見えるのか、という話です。

```
+ repo
 + docs
  - index.html
  - image_public.jpg
 - image_private.jpg ← たとえばこれは見えちゃうのか？
```

見えないようです。公開されるのはあくまで docs 配下であって、docs 内に含まれない repo/image_private.jpg などは見えません。

# (その2) プライベートリポジトリ内ファイルの permalink はどう見える?
Ans: URL にトークンが付く。

まず Raw へのリンクそのまま（下記）では 404 Not Found になります。なので仮にユーザー名、リポジトリ名、ファイル名がバレたとしても第三者がアクセスすることはできません。

```
https://raw.githubusercontent.com/stakiran/a_private_repo/master/readme.md
```

次に、権限のある人（基本的には本人でしょう）が GitHub ウェブサイト等から Raw にアクセスした場合ですが、以下のようにトークン付き URL が発行されます。

```
https://raw.githubusercontent.com/stakiran/a_private_repo/master/readme.md?token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

この **トークン付き URL が permalink になっている** と考えられます(※1)。つまりトークン付き URL がバレたら中身を見られるということです。

※1 仕様としてどうなっているかはいまいちわかりません。どなたかソース等ご存知だったら教えてください :smile:

## (おまけ) トークン付き URL の挙動
トークン付き URL の挙動についても調べてみました。

- 挙動1: 有効期限は無いっぽい？
  - 発行した URL に一日置いてアクセスしても普通に開けました
- 挙動2: トークン付き URL は認証ユーザーでなくても開ける
  - いったんログアウトして開いてみたら普通に開けました
- 挙動3: トークンは発行される毎に微妙に異なっている

挙動3については、**発行した URL ならどれでも開けます**。つまり10回生成したら10個分の permalink が存在することになります。

# (その3) 作った GitHub Pages は被リンクされる?
Ans: されない

たとえば GitHub Gist だと、(Secret Gistで無ければ)作成した Gist はトップページに新着として表示されます。こういう仕組みがあると Google 等に引っかかっちゃいますよね。その辺どうなってんのという話です。

試しにプライベートリポジトリで GitHub Pages を作ってみましたが、公開してから二週間経った後でも Google からは辿れません（ヒット件数ゼロ）。この事から（いささか乱暴ですが）辿れるようなページから勝手にリンクされることはない、と言えそうです。

つまり、GitHub Pages はプライベートでも公開はされるが **誰にも存在を知られていなければ事実上プライベートなのでは** と言えるかもしれません。実際 Secret Gist も同じアイデアです。ただ GitHub Pages の場合、URL が `https://(USERNAME).github.io/(REPONAME)/` と単純なので、リポジトリ名さえばれてしまえば直打ちで見られちゃいます :sweat:

# (その4) 支払い忘れ等で有料プランが無効になったら GitHub Pages はどうなる？
Ans: わかりません（ご存知でしたら教えてください）

まずリポジトリについては、再び有料プランを契約するまでは一切アクセスできなくなります。clone もできませんし Web からも見えません。

一方で GitHub Pages については、すいません調べてません。有料プランの有効無効にかかわらずアクセスはできる気はするんですが、どうなんでしょうね。ご存知の方、いたら教えてください :smile:

# おわりに
半分ネタみたいなものですが、プライベートリポジトリで GitHub Pages を運用した時の挙動について調べてみました。参考になれば(?)幸いです。

間違いや他にも面白いネタ等ありましたら、ぜひ教えてください :smile:
自然言語APIで英語の皮肉を感情分析してみた

相変わらず自然言語のAPIをつかってみています。どこまでできるかを把握するという意味で、分析しては結果をみて、分析しては、、、ということを繰り返しています。
先日の記事で、[自然言語APIで京都の良い回しを感情分析してみた結果](https://qiita.com/nobutaka_suzupi/items/84d6d0631719841be5c6) という記事の中で、センチメント分析は皮肉の分析がそんなに得意じゃなさそうということを思ったのですが、日本語でなく、英語の皮肉はどのくらい分析できるのかなと思い調べて見ました。

参考：
・[「嫌味」の英語！さりげなく悪口を言いたい時のネイティブ表現17選！](http://eitopi.com/iyami-eigo) 
・[英語の意味に裏がある「嫌味や皮肉で使われやすい」基礎表現](https://eikaiwa.weblio.jp/column/phrases/handy_english_phrases/how-to-say-sarcasm)
こちらを参考にさせていただきました。

#英語の皮肉表現を分析してみた
参考サイトから分析してみた結果は下記です。例文は基本的にネガティブな文章なのですが、スコアやいかに。。

| 例文       |       スコア   |
|:-------------:|:------------------:|
| Mom…THANKS A LOT! Don’t ever come into my room.<br />お母さん…本当にありがとう！二度と部屋に入ってこないで。         |   0  |
| Well, thank you for your help! That was fantastic!<br />そうね、手伝ってくれてありがとう！素晴らしかったわ！ | 0.6 |
| You were supposed to bring me food! Thanks for nothing!<br />私に食べ物を持ってきてくれる約束だったでしょ！何にも感謝できないわ！ | -0.4 | Are you kidding me!? Thank you for making my life just perfect!<br />冗談だろ！？俺の人生を完璧にしてくれてありがとう！ | 0.4 |
| Thank you for being so condescending. <br />とっても見下してくれてありがとう。 | -0.6 |
| I ate your ice cream for you so that you won’t get any fatter than that. You’re welcome.<br />あなたがそれ以上太らないように、あなたのアイスクリーム食べといてあげたよ。どういたしまして。 | 0 |
| Looks like I overestimated the number of your brain cells. <br />君の脳細胞の数を多く数え過ぎてたみたいだ。 | -0.1 |
| I can find my own way somehow, thank you very much. <br />どうにかして自分で自分の道は探すからね、ありがとう（余計な口出しは無用だよ） | 0.7 |
| Thanks a lot, you spoil the mood. <br />感謝するよ、君のおかげで雰囲気が台無しだ | 0.5 |
| Thanks to you, we all missed the last train.<br />みなさんのおかげでプロジェクトを終えられました | 0.6 |

という感じです。概ね、皮肉や嫌味はポジティブ表現として捉えられてしまうようです。前後の文脈ありきで皮肉や嫌味は成立するので文章を抜き出して判断するのは、難しいのかもしれません。

# 皮肉を計測するにはどうしたらいいか
そもそも皮肉とは、逆のリアクションをおおげさに表現することで成り立つものなのかなと思います。「冗談だろ！？俺の人生を完璧にしてくれてありがとう！」こちらとか、この言葉の前にネガティブな言葉があったら、皮肉になるし、ポジティブな言葉があったら、そのままの意味に捉えて問題ないと思います。なので、前後の文章を判断して、ネガティブから急にポジティブに振り切る文章は「皮肉」という判断もできるのではないかなあと思いました。

# グーグルセンチメント分析のクセ
クセというか特徴というか。グーグルの分析は２つ以上の文章をまとめて、全体でポジティブかネガティブかというものを出しますが、例えば「お母さん…本当にありがとう！二度と部屋に入ってこないで。」このように、ポジティブ文章、ネガティブ文章、という組み合わせ場合、全体としてニュートラルと判定される傾向があるように思います。ポジティブ（＋）とネガティブ（ー）で相殺されるイメージです。
<img width="851" alt="スクリーンショット 2018-04-24 20.26.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/252288/42ac57ad-9fc8-9386-f473-8b4652aad9ef.png">

本来ならこの文章は嫌味なので、-0.9くらいのネガティブとして判定して欲しいなと。しかし、文章全体としては、０：ニュートラルとして評価されています。
極端なネガティブからポジティブへの振り切りは、単純な感情の足し算にはならないので、評価ロジックが必要かなと思います。

（余談）
その感情の振れ幅が大きいことがmagnitudeっぽいですね、その数値で判断できるのかな。と思いました。

# まとめ
英語でも皮肉や嫌味はセンチメント分析するのが難しいようでした。日本語だけ不得意ということではありませんでした。
前後の文脈とmagnitudeを駆使して、正解に近づく分析ができればいいなーと思っております。magnitudeに期待してます。
【css】テーブルのヘッダを固定する方法

テーブル要素の行とか列とかを、スクロースしても固定されたままにしたい時はどうすればいいか。
2通りのやり方を学んだのでまとめておきます

#1 tbodyをブロック要素にする

```css
tbody {
  display:block;
overflow-y:scroll;
  height:100px;
}
tbody{
  overflow-y:scroll;
  height:100px;
}
```
ブロック要素にする都合上、高さは明示してあげる必要があります。

#2 position:sticky をつかう

```css

table {
    display: block;
    overflow: scroll;
    height: 100px;
    table-layout: fixed;
}

thead,
tbody {
  display: block;
}

th, td {
  display: inline-block;
}

thead {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: 2;
}
```

モダンな感じがするやり方
ブラウザによっては対応してなかったり、ヘッダとセルの字や背景が重なるのが面倒だったりする点は注意
UnityのVRTKでアウトラインを表示する。

VRTKの[VRTK_OutlineObjectCopyHighlighter](https://vrtoolkit.readme.io/docs/vrtk_outlineobjectcopyhighlighter)を使う。

#開発環境
・Unity2017.1.0f3
・SteamVR
・VRTK

#はじめに
プロジェクトを作成後、SteamVRとVRTKをインポートしておく。
VRTKのセットアップが面倒な場合、適当なサンプルシーンから
[VRTK_Scripts]と[VRTK_SDKManager]を使うシーンにコピペすればVRTKが使えて楽。

#アウトラインの表示
表示したいオブジェクトをシーンに配置した後
VRTK_OutlineObjectCopyHighlighterをアタッチ。(Add Componentから"outline"を検索ですぐ出てくる)
![2018-04-24 20_00_52-Unity 2017.1.0f3 Personal (64bit) - Outline.unity - WhiteVR - PC, Mac & Linux St.png](https://qiita-image-store.s3.amazonaws.com/0/46612/d22596c7-69df-1330-463e-9d3aa0514dd3.png)

その後アウトラインを表示するスクリプトを書く。

```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VRTK.Highlighters;  //usingは忘れがちなので忘れずに

public class SetOutline : MonoBehaviour {

  VRTK_OutlineObjectCopyHighlighter vrtk_outline;

  void Start ()
  {
    vrtk_outline = GetComponent<VRTK_OutlineObjectCopyHighlighter>();
    vrtk_outline.Initialise();
    Color color = Color.black;
    vrtk_outline.Highlight(color);
  }
}
```

vrtk_outline.Initialise()を実行してvrtk_outline.Highlight()で表示する。

![2018-04-24 20_22_56-Unity 2017.1.0f3 Personal (64bit) - Outline.unity - WhiteVR - PC, Mac & Linux St.png](https://qiita-image-store.s3.amazonaws.com/0/46612/31541cff-6174-c464-92a4-f18c01e078f5.png)

こんな感じで表示されます。(Ticknessの値は左が1、右が0.5)

今回はStart()に書いたので最初から表示されるが、任意のタイミングで表示、非表示も可能。

※"アウトラインを適用したオブジェクト同士"が重なる部分は、アウトラインが表示されない。
なので一度に複数のモデルに適用するのは避けたほうがいいかもしれない。
AWS EC2 超速Webサーバ公開

#概要
WebhookやBot作りたいけど、WEBサーバ環境がない・・・時間もない
（準備が）超速Webサーバ公開にチャレンジ！
※手元にあるのはAWSアカウントのみ

#前提
AWSアカウントがあり、コンソールへログイン可能なこと
何でも良いのでターミナルを用意していること

# スタート
##サービスから「EC2」でインスタンスの作成
Amazon Linux 無料利用枠の対象 t2.micro で作成
初めてならキーペア作成も忘れずに

## セキュリティグループ
80ポートを許可する
タイプから「HTTP」を選べばok

## パブリックDNSとキーでアクセス
ec2-user かつ作成された鍵でログイン

## Python Web Framework Bottle インストール
[Python Web Framework Bottle] (https://bottlepy.org/docs/dev/) 超シンプルらしい
`wget https://raw.githubusercontent.com/bottlepy/bottle/master/bottle.py`

## index.py 作成
注意host名をパブリックDNSに変える
`vi index.py`

```index.py
from bottle import route, run, template

@route('/hello/<name>')
def index(name):
    return template('<b>Hello {{name}}</b>!', name=name)

run(host='パブリックDNS', port=80)
```
## 起動
`sudo su -`
`cd /home/ec2-user`
`python index.py`

## 超速完成
http://パブリックDNS/hello/world
Node.js アプリケーションを本番Apache環境でPM2を使って起動する

Node.js のアプリケーションを本番環境に反映するためにPM2を導入する方法です。

## Node.js を本番サーバーで立ち上げる際に気にしていたこと
アプリケーションを本番環境で起動させるにあたり、気にすべきことは山ほどあると思います。
今回、Node.js のアプリケーションということでアプリケーションサーバーの立ち上げが必要でした。

- デーモン化した状態で起動させること
- プロセス管理ができること
- 更新時の手間がかからないこと

などを基準として、選定したのがPM2でした。

## PM2とは
PM2は、Node.js を本番環境で起動するためのもので、プロセスをデーモン化したりの起動を管理することができるツールです。
[Githubのリポジトリはこちら](https://github.com/Unitech/pm2)です。

PM2には、主にこのような機能があります。

- プロセス管理
- クラスタリング
- 内臓のモニタリングUI

また、Keymetrics という名前で、有償版が存在しているのもメリットだと思います。
それ以外にも良いところがたくさんあるので、興味がある方は公式ページをご覧ください。
[http://pm2.keymetrics.io/](http://pm2.keymetrics.io/)

## 導入方法
ここからが本題です。
まずは大まかな手順をお伝えします。

1. サーバーに Node.js をインストールする（今回は省略します）
2. PM2をインストールする
3. Apache から Node.js のアプリケーションサーバーにProxyを設定する
4. PM2経由で Node.js アプリケーションを起動する

### 1. サーバーに Node.js をインストールする
Node.js をインストールする方法は様々で、説明しだすと１つ記事が出来上がるほど説明が長くなるので、今回は省略させていただきます。
ちなみに私は、nodebrew を使用しました。

### 2. PM2をインストールする
PM2のインストールはとても簡単で、下記コマンドを実行するだけでパッケージがインストールされます。

```
# npm
npm install pm2 -g

# yarn
yarn global add pm2
```

ただ、yarn を経由して pm2 をインストールした方や、nodenv や nodebrew を使用して Node.js をインストールした方は、
実行環境に PATH が通っていない可能性があります。
試しに、こちらのコマンドを実行してみてください。

```
which pm2
```

これでパスが表示されれば良いのですが、PATHに含まれていないエラーが出た場合はパスを通す必要があります。
インストールした方法で、グローバルインストールされたフォルダがどこにあるかを調べてパスを通してください。

### 3. Apache から Node.js のアプリケーションサーバーにProxyを設定する
Node.js のアプリケーションを立ち上げる場合、Proxy経由で localhostに接続しなければ、
ファイルを直接叩きにいってしまうので、Proxyを設定する必要があります。

Apache の conf ファイルに下記の記述を追加してください

```
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
```

Locationディレクティブの中に書くのであれば、このようになります。

```
<Location />
    ProxyPass http://localhost:3000/
    ProxyPassReverse http://localhost:3000/
</Location>
```

設定が終わったら忘れずにhttpdをリスタートしてください。

```
service httpd restart
```

これで Node.js のアプリケーションが待ち構えているポートにProxy経由でアクセスすることができます。


### 4. PM2経由で Node.js アプリケーションを起動する
いよいよアプリケーションの立ち上げです。　

```
pm2 start /path/to/app.js -n 'application_name'
```

これでアプリケーション名を指定した状態で立ち上げることができます。
プロセスが立ち上がっているかを確認するには下記のようにします。

```
pm2 list
```

アプリケーションが立ち上がっていれば、立ち上がっているアプリケーションの情報が表示されます。

もし、Node.js をCoffeescriptなどで記述している場合は、下記のコマンドで立ち上げます。

```
pm2 start /path/to/bin/www -n 'application_name'
```

## 終わりに
Node.js を使用したアプリケーションは、増加傾向にあります。
Rails でAPIサーバーを立てて、アプリケーション側は Node.js というのも多くなってきていますし、
Ionicなどのモバイルアプリケーションを開発するためのフレームワークも Node.js をベースにして作られています。
それらを本番化する際に役立てていただければ幸いです。
riot.js table ショート表記タグ

### tr "|" and td "," 
```html
<tbl items="a,b,c,d|aliceblue,brown,chacole,darkblue|#aaa,#bbb,#ccc|a,b,c,d,e"></tbl>
```
### 全部
```html
<script src="//gnjo.github.io/riot.js"></script>
<tbl items="a,b,c,d|aliceblue,brown,chacole,darkblue|#aaa,#bbb,#ccc|a,b,c,d,e"></tbl>
<style>*{font:14px/normal monaco,consolas,monospace}</style>
```
```js
riot.tag(
 'tbl'
 ,`<table>
<tr each="{item in opts.items.split('|')}"><td each="{d in item.split(',')}">{d}<td></tr>
</table>`,function(opts){
})

riot.mount('tbl');
```
AutoItで簡単なRPA ～毎日開いているサイトを開く～

# AutoItでRPA ～毎日開いているサイトを開く～

AutoItというフリーのツールを使う機会があったので、RPAという程大げさなものでもない(日一回の単純な動作程度なので)ですが記事投稿してみます。
私の場合、PCを起動した後毎回同じサイトを開くことが多いので指定したWebサイトを開くだけの簡単作業を、AutoItを使って自動化してみます。

## 目的
指定したWebサイトを自動で開く

## やり方
今回は3つのWebサイトを開きます。その際に一つ目のWebサイトが開けたら、二つ目以降のWebサイトは同じウィンドウで開くこととします。

上記を実現するためのAutoItのコードとしては、IEを操作するライブラリ<IE.au3>をインポートし、_IECreateで一つ目のURLを開いた後、そのインスタンスで他のURLを開くような形になります。

サンプルコード

```
#include <IE.au3>
Const $navOpenInNewTab = 0x0800

; 一つ目のURLを開く
Dim $oIE = _IECreate('https://www.google.co.jp/')
; 二つ目以降のURLを開く
__IENavigate($oIE, 'https://qiita.com/trend', 0,$navOpenInNewTab)
__IENavigate($oIE, 'https://mail.google.com/mail', 0, $navOpenInNewTab)

Exit 0

```

Webサイトを開くだけなら上記コードの10行程度で簡単にできました。
Alpine Linuxではまったこといろいろ

Alpine linuxをRappberryPi3で利用してみた。
Disklessモードがすごくよくできていて宅内環境をこれで置き換えようと考えているのですが、
いくつかのはまりどころがあったので、書いておきます。

# sshでroot以外のログインができない

再起動時にhomeが消える事が原因
同時にssh公開鍵も消えてしまうので、lbuの対象にする
`lbu include`でもいいが、グロブを使いたいので、
`/etc/apk/protected_paths.d/lbu.list`を次のように編集する

```shell-session
# cat /etc/apk/protected_paths.d/lbu.list
+home/*/
-home/*/*
+home/*/.ssh/
-home/*/.ssh/*
+home/*/.ssh/authorized_keys
```

# ネットワークが起動しない

rootのシェルを`/sbin/nologin`に変更するとなぜか起動しなくなる

#Open vSwitchを有効にすると起動時にネットワークが繋がらない

起動順序がおかしいのが原因
とりあえず`/etc/conf.d/networking`を作成し、むりやり起動順序を変更した

```shell-session
# cat /etc/conf.d/networking 
rc_need="ovs-vswitchd"
```


ほかにもなにかあれば追記していく
Docker for Windows をインストールする

# Widows 用 Docker は 2種類ある

- [Docker for Windows](https://www.docker.com/get-docker)
- [Docker Toolbox](https://docs.docker.com/toolbox/toolbox_install_windows/)

## Docker for Windows

Docker for Windows は Hyper-V が動作する Windows 用のソフトです。

Hyper-V 上で Docker 用 Linux が起動して、Docker コンテナを稼働させます。

![docker.png](https://qiita-image-store.s3.amazonaws.com/0/248967/d87ff144-8944-c176-34e9-cb6bfcb63be9.png)

## Docker Toolbox

Docker Toolbox は Hyper-V が利用できない Windows 用 (例えば Windows 10 Home など) のソフトになります。

これは、Windows 上の Virtualbox で Docker 用の Linux が起動されます。

## Docker for Windows の起動するタイミングを変更する

Docker for Windows をインストーラーの設定のままインストールすると、Windows にログインしたときに Docker が起動します。

Docker は起動に時間がかかるので、任意のタイミング (手動で) で起動させる場合は、設定を変更すれば、対応できます。

![docker-setting.png](https://qiita-image-store.s3.amazonaws.com/0/248967/6f3b9b89-7995-1dc6-edf2-8342e89037c5.png)

赤線を引いた項目のチェックを外せば、手動で起動するようになります。

## インストールした Docker を確認する

インストールされている Docker のバージョンは次のコマンドで確認できます。

```
> docker --version
Docker version 18.03.0-ce, build 0520e24

> docker-compose --version
docker-compose version 1.20.1, build 5d8c71b2
```

さらに詳細な情報は次のコマンドで確認できます。

```
> docker info
```
VueのデータをCSV形式でダウンロードする

VueでUIを作っていたら表示されているデータをダウンロードしたいという要望があったので実装してみました。

## Data

下記ようなデータをdata()に入れてあるとします。

```js
items: [
  { name: 'りんご', price: '100' },
  { name: 'みかん', price: '50' },
  { name: 'マンゴー', price: '3000' }
]
```

## View

普通にこのデータをTable表示する時はこんな感じでしょうか？

```vue
<table border=1>
  <tr v-for="item in items">
    <td>{{ item.name }}</td>
    <td>{{ item.price }}</td>
  </tr>
</table>
```

それではその下にダウンロードボタンを追加します。呼び出す関数はdownloadCSV()とします。

```vue
<button v-on:click="downloadCSV">
  ダウンロード
</button>
```

## Methods

CSVはファイルの先頭にBOMとしてを'\ufeff'を追加し、WindowsのExcelでUTF8の識別ができるようにします。

参考:
https://doruby.jp/users/ueki/entries/BOM付きUTF-8で文字化けしないCSV出力

後はデータをforEachで１行づつ作成し、Blobに入れます。そして、aタグのエレメントを作成しその中にデータを入れクリックしたのと同じ動作を実現します。

```js
  methods: {
    downloadCSV () {
      var csv = '\ufeff' + '品名,価格\n'
      this.items.forEach(el => {
        var line = el['name'] + ',' + el['price'] + '\n'
        csv += line
      })
      let blob = new Blob([csv], { type: 'text/csv' })
      let link = document.createElement('a')
      link.href = window.URL.createObjectURL(blob)
      link.download = 'Result.csv'
      link.click()
    }
  }
```

これでCSVデータとしてダウンロードする事ができます。

## 気になる点

Excelで確認してこれで良いかと思ったのだけど、Wikipediaによると'\ufeff'はUTF-16になっているので`\uefbbbf`の方が良いのだろうか？要検証。

https://ja.wikipedia.org/wiki/バイトオーダーマーク
.NET Core CLIだけどWindows上なら.NET Framework使いたいよね!

[.NET Core CLI](https://docs.microsoft.com/ja-jp/dotnet/core/tools/?tabs=netcore2x "https://docs.microsoft.com/ja-jp/dotnet/core/tools/?tabs=netcore2x")は[.NET Core SDK](https://docs.microsoft.com/ja-jp/dotnet/core/sdk "https://docs.microsoft.com/ja-jp/dotnet/core/sdk")で提供されるコマンドラインツールで、ソースコードの生成やコンパイルなどを`dotnet`で始まるコマンドで実行できるものです。.NET Coreはクロスプラットフォーム開発を前提とする環境であるため、Windows上であってもデフォルトでは.NET Frameworkで提供されるクラスの一部を利用できません。

ですが.NET Framework環境が事前に整っていれば、それを利用するよう設定できます。それには、`dotnet new`コマンドを実行するときに`--target-framework-override ターゲットフレームワーク`というオプションを設定して、[ターゲットフレームワーク](https://docs.microsoft.com/ja-jp/dotnet/standard/frameworks "https://docs.microsoft.com/ja-jp/dotnet/standard/frameworks")を変更します。

```csh:ターゲットフレームワークの変更例(.NETFramework4.7.1)
dotnet new console --target-framework-override net471 -lang f# -o net471app
```

こうするとプロジェクトファイル(\*.fsproj)の`<TargetFramework>`の部分がオプションで設定された値に変更され、ビルド(コンパイル)もその環境で行われます。これにより、以下のような画像ファイルを扱うプログラムも開発できます。このプログラムはデフォルトのターゲットフレームワーク(.NET Core)でビルドしようとしても失敗します。

```fsharp:.NETCoreCLIで画像ファイルを扱うプログラムを開発(Program.fs)
[<EntryPoint>]
let main argv =
  if argv.Length < 1
    then printfn "dotnet run -- 画像ファイル名"
    else
      let file  = argv.[0]  // コマンドライン引数から画像ファイル名を得る
      let image = System.Drawing.Image.FromFile file  // 画像ファイルから画像オブジェクト生成
      printfn "%s: Width = %d, Height = %d"
              file image.Size.Width image.Size.Height  // 画像のサイズを表示
  0

(* 結果
dotnet new console --target-framework-override net471 -lang f# -o net471app
cd net471app

... Program.fsを編集 ...

dotnet run -- image.jpg
image.jpg: Width = 1920, Height = 1080
*)
```

さきほどの`dotnet new`コマンドで生成されたプロジェクトファイル(\*.fsproj)はこのようになります。dllの参照などは適宜追加してください。

```xml:上のプログラムのプロジェクトファイル(net471app.fsproj)
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <!-- dotnet new --target-framework-overrideオプションで変更可 -->
    <TargetFramework>net471</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="Program.fs" />
  </ItemGroup>

</Project>
```

---
もしVisual Studioを使えなくてもWindows上に.NET Core CLI(dotnetコマンド)、.NET Framework環境、テキストエディタがあればWindowsアプリを開発できます。これは盲点でした。
【UI】Bootstrapをつかったtableのcell内を上下左右中央寄せにする

```css
.td_vertical_align_middle.td_vertical_align_middle {
  vertical-align: middle;
}
```
```html
<td class="td_vertical_align_middle">上下左右中央寄せにしたい</td>
```
### ポイント
・Bootstrapはデフォルトでvertical-align:topを設定しているのでそれを打ち消す設定をしないと、上下左右中央寄せにはなりません
参考:　https://stackoverflow.com/questions/13771101/centering-a-button-vertically-in-table-cell-using-twitter-bootstrap
・Bootstrapをつかっていることをわすれて、いろいろと中央寄せ関係のhtmlタグを書いても、いっこうに上下左右中央寄せにはなりません（本人談）
BootStrapのFormで生年月日を作った。

# 概要

複雑なFormの作り方

# コード

<p data-height="265" data-theme-id="0" data-slug-hash="yjOabz" data-default-tab="html,result" data-user="YamasakiKenta" data-embed-version="2" data-pen-title="生年月日" class="codepen">See the Pen <a href="https://codepen.io/YamasakiKenta/pen/yjOabz/">生年月日</a> by YamasakiKenta (<a href="https://codepen.io/YamasakiKenta">@YamasakiKenta</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

```html
<div class="container">
  <div class="form">
    <div class="form-group mt-4">
      <label class="form-label">生年月日</label>
      <div class="form-row">
        <div class="col-md">
          <div class="form-row">
            <div class="col">
              <select id="" class="form-control" name="" placeholder="年">
                <option value="">----</option>
                <option>2000</option>                                    
              </select>
            </div>
            <div class="col-auto my-2">年</div>
          </div>
        </div>
        <div class="col-md">
          <div class="form-row">
            <div class="col">
              <select id="" class="form-control" name="" placeholder="月">
                <option value="">--</option>
                <option>1</option>

              </select>
            </div>
            <div class="col-auto my-2">月</div>
          </div>
        </div>
        <div class="col-md">
          <div class="form-row">
            <div class="col">
              <select id="" class="form-control" name="" placeholder="日">
                <option value="">--</option>
                <option>1</option>
              </select>
            </div>
            <div class="col-auto my-2">日</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
```

# 簡単な解説
col-autoで、最小幅
colで、最大幅
テキストそのまま入れるとずれるので、少し微修正。
小さくしたら、並べたいので、mdを入れる

イメージ通りに、できたけれど、なんか変になった。
AWS lambdaでbugsnagを利用する

# 目的

lambdaでbugsnagを使いたい。
言語は node.js を使用する。
`index.js` にのみ処理が記述されてる前提。

# 手順

## npmでbugsnagをインストール

`index.js` の階層で以下実施

```sh
npm install --save bugsnag
```

`node_modules` ディレクトリが作成され、中にいろいろインストールされている。

git上は `npm init` して作成された `package.json` をコミットしておく。

## デプロイ

`index.js` の階層で以下実施

```sh
zip -r xxxx.zip index.js node_modules
```

※一つ上の階層でディレクトリ自体をzip化しないよう注意。

作成した `xxxx.zip（ファイル名は任意でOK）` を、zipでAWSコンソールからアップロード。

<img width="690" alt="スクリーンショット 2018-04-24 21.00.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/70453/de69103d-1583-5363-2ad3-9798ccd3797d.png">

※lambdaのデプロイ自体は、 [apex](http://apex.run/) を利用したほうが楽。

## コーディング

### 定義

`index.js` に以下を記述し、 `bugsnag` をrequire

```js
var bugsnag = require('bugsnag');
bugsnag.register(
  `${process.env.BUGSNAG_API_KEY}`, { releaseStage: `${process.env.RELEASE_STAGE}` });
```

以下は環境変数に設定する。

|変数名|説明|
|---|---|
|BUGSNAG_API_KEY|bugsnagのAPIキー|
|RELEASE_STAGE|`staging` や `production` といった環境名|

### とりあえず連携できているかテスト

```js
var bugsnag = require('bugsnag');
bugsnag.register(
  `${process.env.BUGSNAG_API_KEY}`, { releaseStage: `${process.env.RELEASE_STAGE}` });

exports.handler = function(event, context, callback) {
    bugsnag.notify(new Error("Non-fatal"));
    return;
};
```

ローカルで編集したら忘れずデプロイ
→
こんな感じでエラーが通知された！

<img width="988" alt="スクリーンショット 2018-04-24 18.47.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/70453/89918b41-1121-5e17-5eda-320acf96164b.png">

### 対象処理中で発生したエラーは全てbugsnagに通知する

```js
var bugsnag = require('bugsnag');
bugsnag.register(
  `${process.env.BUGSNAG_API_KEY}`, { releaseStage: `${process.env.RELEASE_STAGE}` });

// メイン処理
var main = function(event, context, callback) {
  // 処理
  throw new Error("Non-fatal");
};

exports.handler = function(event, context, callback) {

    // エラー発生時は全てbugsnagに送信する
    bugsnag.autoNotify(function() {
      main(event, context, callback);
    });

};
```

`autoNotify` は [同期・非同期の全エラーを捕捉する](https://docs.bugsnag.com/platforms/nodejs/other/#reporting-unhandled-errors) はずだが、 `context.fail()` は通知されなかった・・。なぜでしょう。

# 参考

bugsnag公式 - bugsnagとnode.jsの基本的な連携方法
https://docs.bugsnag.com/platforms/nodejs/
https://docs.bugsnag.com/platforms/nodejs/other/#basic-configuration
https://docs.bugsnag.com/platforms/nodejs/express/configuration-options/

Lambdaに標準で同梱されていないモジュールを使用したい場合の、環境構築方法
https://www.business-on-it.com/2003-aws-lambda-create-function/#section2

`あるモジュールがlambdaに標準で入ってるかどうか` は公開されてないらしい・・
https://qiita.com/yoshidasts/items/2d7117ef0f31754a06ab
【Javascript】要素内のドラッグ位置を取得するクラス

#概要
この記事では、ある要素（例えばdiv）をクリックして、ドラッグしたときのマウス位置を取得するクラスを紹介しています。
このクラスは、要素やブラウザの外側にマウスが移動した場合もその位置が反映されます。
クリック位置だけで充分な場合は、より簡単な[こちら](https://qiita.com/lookman/items/a50b8ae85b0f7e8605d2)をご覧ください。

#コード
```DraggableElement.js
class DraggableElement {
	constructor(element) {
		this.element = (typeof element === "string") ? document.getElementById(element) : element;
		this._isDragIn = false;
		this._point = {x: 0, y: 0};

		this.element.onmousedown = event => {this.onMouseDown(event);};
		window.onmouseup = event => {this.onMouseUp(event);};
		window.onmousemove = event => {this.onMouseMove(event);};
		window.onblur = event => {this.onBlur(event);};
	}
	get x() {
		return this._point.x;
	}
	get y() {
		return this._point.y;
	}
	set(event) {
		// スクロール量
		const scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
		const scrollY = document.documentElement.scrollTop || document.body.scrollTop;

		// マウスイベントの絶対位置
		const rect = this.element.getBoundingClientRect();
		let x = event.pageX - (rect.left + scrollX);
		let y = event.pageY - (rect.top + scrollY);
		
		// 要素のサイズ
		const width = this.element.clientWidth;
		const height = this.element.clientHeight;
		
		// マウスが要素の外にある場合
		if(x < 0) {
			x = 0;
		} else if(width < x) {
			x = width;
		}
		if(y < 0) {
			y = 0;
		} else if(height < y) {
			y = height;
		}
		
		// 位置の代入
		this._point.x = x;
		this._point.y = y;
	}
	onMouseDown(event) {
		this._isDragIn = true;
		this.set(event);
		this.onChange();
	}
	onMouseMove(event) {
		if(this._isDragIn) {
			this.set(event);
			this.onChange();
		}
	}
	onMouseUp() {
		this._isDragIn = false;
	}
	onBlur() {
		this._isDragIn = false;
	}
	onChange() {
		// Please implement it.
	}
}
```

id="element" の要素を用意したとすると、以下のようなソースコードで様々な処理を実装できます。

```js
let draggable = new DraggableElement("element");
draggable.onChange = () => {
	document.getElementById("element").innerText = `${draggable.x}, ${draggable.y}`;
};
```

#解説
ポイントとなるのは、以下のonイベントの部分です。

```js
this.element.onmousedown = event => {this.onMouseDown(event);};
window.onmouseup = event => {this.onMouseUp(event);};
window.onmousemove = event => {this.onMouseMove(event);};
window.onblur = event => {this.onBlur(event);};
```

onMouseUp, onMouseMove イベントは、どちらもクリックした要素（this.element）ではなく、window のイベントハンドラに紐づいています。
何故かというと、クリックした要素のイベントハンドラに紐づけた場合、要素の外にマウスが移動するとonMouse○○イベントが発生しなくなるためです。
ただし、onMouseDownイベントだけは、指定した要素をクリックしなければ発火しないため、windows ではなく、クリックした要素のイベントハンドラに紐づいています。
UICollectionViewFlowLayoutでヘッダーとフッターを設定する

フローレイアウト(UICollectionViewFlowLayout)で、セクションごとにヘッダーとフッターを設定してみたいと思います。

StoryBoardはこんな感じです。
Collection Reusable ViewをオブジェクトライブラリからCollectionViewにドラッグ&ドロップすると、セルの上下に配置されます。
フローレイアウトではこれらがヘッダーおよびフッターになります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/81715/e501856e-ccc4-eaee-3217-959d48878a2e.png)

ViewControllerの実装は以下のとおりです。

```swift:ViewController
import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()

        collectionView.dataSource = self
    }
}

extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
        cell.backgroundColor = .red

        return cell
    }

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 2
    }

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let identifier: String
        let bgColor: UIColor

        if kind == UICollectionElementKindSectionHeader {
            identifier = "Header"
            bgColor = .blue
        } else {
            identifier = "Footer"
            bgColor = .yellow
        }

        let supplement = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: identifier, for: indexPath)
        supplement.backgroundColor = bgColor

        return supplement
    }
}
```

ヘッダーおよびフッターの設定をしているのは、UICollectionViewDataSourceの`collectionView: viewForSupplementaryElementOfKind:at:`というメソッドです。

引数`kind`には、種類文字列と呼ばれる識別子が格納されています。
セルと違い、補助ビューは再利用識別子と種類文字列の2つの識別子を持っており、オブジェクトの再利用時に使用します。

フローレイアウトでは、種類文字列は`UICollectionElementKindSectionHeader`および`UICollectionElementKindSectionFooter`という定数が定義されています。
ここではこれらの定数を利用して、`UICollectionElementKindSectionHeader`つまりヘッダーの場合は背景を青に、それ以外つまりフッターの場合は背景を黄色に設定しています。

セルについては、2つのセクションそれぞれに10個ずつのセルが配置されるようにしました。

上記のコードを実行すると、以下のような画面になります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/81715/355855ca-0263-6aab-0020-4b288c449964.png)

セクションごとにヘッダー(青)とフッター(黄色)が配置されているのがわかります。
uMap > OpenStreetMapのタイル URL（随時追加中）



https://umap.openstreetmap.fr


## OSM

### OSM-Fr

![osm_fr.gif](https://qiita-image-store.s3.amazonaws.com/0/49910/27a6a70d-9061-979a-1b83-73205be58adb.gif)

* http://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png

### OpenStreetMap

![osm1.gif](https://qiita-image-store.s3.amazonaws.com/0/49910/cbfd5de8-007b-ad6d-32cf-6a0836f0fab4.gif)


* http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png



### OSM Humanitarian (OSM-FR) 


![osm2.gif](https://qiita-image-store.s3.amazonaws.com/0/49910/49b9727d-c2fc-7ce8-3368-95851f019c90.gif)


### OSM-monochrome

![3.gif](https://qiita-image-store.s3.amazonaws.com/0/49910/ad673dea-3a8b-8508-bf39-df13cc4c987a.gif)


* http://www.toolserver.org/tiles/bw-mapnik/{z}/{x}/{y}.png

### OSM Lyrk

![lyrk.gif](https://qiita-image-store.s3.amazonaws.com/0/49910/c50a60b2-913c-c0c2-8a7c-9904c376c70d.gif)


* http://tiles.lyrk.org/ls/{z}/{x}/{y}?apikey=xxxxxxxxxxxx

* site
[lyrk/lyrk-mapstyle: The legendary map style finally open sourced](https://github.com/lyrk/lyrk-mapstyle)

* ある一定以上の倍率だと地図がグレーアウトする


### OSM Hyda

![hyda.gif](https://qiita-image-store.s3.amazonaws.com/0/49910/5e87c84d-03ce-846f-cc29-627874b10225.gif)


* 日本語は文字化けするぽい
* 海の色はキレイな青


## OpenTopoMap


![topo.gif](https://qiita-image-store.s3.amazonaws.com/0/49910/6d4c2045-db14-aa94-21f9-fb19bd9187ec.gif)


* 高低が見やすい
* Usage：  {a|b|c}.tile.opentopomap.org/{z}/{x}/{y}.png
* サイト： [OpenTopoMap - OpenStreetMap Wiki](https://wiki.openstreetmap.org/wiki/OpenTopoMap)


Licence
> * CC-BY-SA
> * opentopomap.org表記必用
> * If you plan to use the tiles for bigger projects, please contact us.



## CARTO

[Terms of use](https://openmaptiles.com/terms/)


### OSM CARTO

* http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png
* 
![cart.gif](https://qiita-image-store.s3.amazonaws.com/0/49910/5c88db17-c72e-cdee-d59f-30924f50c955.gif)




### OSM CARTO DARK

* http://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png
  
  



[Open styles, map gallery, catography](https://openmaptiles.org/styles/)
【Laravel】CSVファイルのデータをSeederでDBにつっこむ


`file_get_contents()` だとメモリ不足になってエラーになったりする、らしいので `SplFileObject` クラスを使う。

```csv:m_category.csv
A,ビジネス
B,教育
C,医療
D,福祉
...
```

```php:CategoryTableSeeder.php
    public function run()
    {
        $file = new SplFileObject('database/csv/m_category.csv');
        $file->setFlags(
            \SplFileObject::READ_CSV |
            \SplFileObject::READ_AHEAD |
            \SplFileObject::SKIP_EMPTY |
            \SplFileObject::DROP_NEW_LINE
        );
        $list = [];
        $now = Carbon::now();
        foreach($file as $line) {
            $list[] = [
                "label" => $line[0],
                "name" => $line[1],
                "created_at" => $now,
                "updated_at" => $now,
            ];
        }

        DB::table("m_category")->insert($list);
    }
```


## 参考
https://www.ritolab.com/entry/63
https://qiita.com/suin/items/31a1c7c47f49cb53f2a7
https://qiita.com/kazu56/items/bc77582313918fe2a3b1
http://php.net/manual/ja/splfileobject.fgetcsv.php
https://qiita.com/tadsan/items/bbc23ee596d55159f044#splfileobject
HTMLメール等で文字化けする空白文字を無害な空白文字に変換する

##はじめに
HTMLメールや、一部のブラウザで「?」や「・」の文字が含まれてしまうことがあります。
それらの文字を、無害な空白文字に変換する処理をメモしておこうと思います。
※この記事ではUTF8をエンコードに用いる場合を前提としておきます。


参考にさせていただいた記事
https://qiita.com/plsplsme/items/59bbfe4be2ec96d07792
https://qiita.com/hollydad/items/9c0399146415af1912d8

##文字化けが発生する原因について
HTMLで空白を設定する際、**&amp;nbsp;**を使って空白文字を挿入することがありますが、それらの空白文字をCKEditorなどのwisiwygエディタを使ったり、スクレイピングするような場合に発生することがあります。

つまり、HTMLの文字をUTF8に変換し、それを表示する場合に文字化けを起こすことがあるということです。

####&amp;nbsp;と同様の空白文字は、様々な種類がある。
ノーブレークスペース
https://ja.wikipedia.org/wiki/%E3%83%8E%E3%83%BC%E3%83%96%E3%83%AC%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9

U+00A0 NO-BREAK SPACE
U+180E MONGOLIAN VOWEL SEPARATOR
U+2000 EN QUAD
U+2001 EM QUAD
U+2002 EN SPACE
U+2003 EM SPACE
U+2004 THREE-PER-EM SPACE
U+2005 FOUR-PER-EM SPACE
U+2006 SIX-PER-EM SPACE
U+2007 FIGURE SPACE
U+2008 PUNCTUATION SPACE
U+2009 THIN SPACE
U+200A HAIR SPACE
U+200B ZERO WIDTH SPACE
U+202F NARROW NO-BREAK SPACE
U+205F MEDIUM MATHEMATICAL SPACE
U+FEFF ZERO WIDTH NO-BREAK SPACE

##対応内容
UTF8で保存されている空白文字を半角スペースに変換する。

```php
function removeSpecialSpace(&$str)
{
    if (is_array($str)) {
        foreach($str as $k => $v) {
            removeSpecialSpace($str[$k]);
        }
    } else {
        $specialSpace = array(
                "\xC2\xA0",
                "\xE1\xA0\x8E",
                "\xE2\x80\x80",
                "\xE2\x80\x81",
                "\xE2\x80\x82",
                "\xE2\x80\x83",
                "\xE2\x80\x84",
                "\xE2\x80\x85",
                "\xE2\x80\x86",
                "\xE2\x80\x87",
                "\xE2\x80\x88",
                "\xE2\x80\x89",
                "\xE2\x80\x8A",
                "\xE2\x80\x8B",
                "\xE2\x80\xAF",
                "\xE2\x81\x9F",
                "\xEF\xBB\xBF",
        );
        $str = str_replace($specialSpace, " ", $str);
    }
}
```

この処理を挟むことで、空白文字の変換が確認できました。
また、実際にこの処理を用いて、メルマガの送信時に「?」の文字化けが解消できたことを確認しました。
sqlpackageを用いたリモートのSQL Serverのバックアップ・リストア・スキーマ取り出し

前提
-------------

- Windows 10 Proの環境上で掲題の操作を行います。
- サーバ上のユーザは`VIEW DEFINITION`という権限を持っている必要があります。固定ロールでいうと、`db_securityadmin`というロールに含まれます。
  - see: [データベース レベルのロール](https://docs.microsoft.com/ja-jp/sql/relational-databases/security/authentication-access/database-level-roles) 


前準備
---------------

~~SQL Server Management Studio(SSMS)を導入する必要があります。(もう少し軽量なツールキットはないのか...)~~

**2018/07/11追記**

いつの間にかsqlpackageのみが配布されています。中身もインストール先もSSMSと違いはあまりないようなので、こちらを使うとよいです。

https://docs.microsoft.com/ja-jp/sql/tools/sqlpackage-download?view=sql-server-2017



導入した後、`"C:\Program Files (x86)\Microsoft SQL Server\140\DAC\bin\sqlpackage"`が配置されるので、これを使います。これはPATHが通ってないので注意。

sqlpackageコマンドのドキュメントは https://msdn.microsoft.com/library/hh550080.aspx をお読みください。


環境変数
------------

また、コピペしやすさを考慮して以下のような変数を定義し、使うようにします。適宜置き換えてください。

```
set DB_HOST=sqlserver-host.example.local,1433
set DB_NAME=database-name
set DB_USER=sa
set DB_PASSWORD=****
```

※DB_HOSTの`1433`はポート番号です。適宜置き換えてください。


各種操作
------------

### Export: スキーマ情報とデータを取り出す

要するに「エクスポート」や「バックアップ」と呼ばれる作業です。

`/Action:Export`を使って、bacpacファイルという独自フォーマットのファイルを得ます。


```
"C:\Program Files (x86)\Microsoft SQL Server\140\DAC\bin\sqlpackage" ^
  /Action:Export ^
  /SourceServerName:%DB_HOST% ^
  /SourceDatabaseName:%DB_NAME% ^
  /SourceUser:%DB_USER% ^
  /SourcePassword:%DB_PASSWORD% ^
  /SourceEncryptConnection:True ^
  /TargetFile:dump.bacpac
```

※暗号化された接続を行わない場合は`/SourceEncryptConnection`へ`False`を与える


### Import: 作成したbacpacファイルを取り込む

要するに「インポート」とか「リストア」と呼ぶ作業です。

`/Action:Import`を使って、bacpacファイルからデータ投入を行います。


```
"C:\Program Files (x86)\Microsoft SQL Server\140\DAC\bin\sqlpackage" ^
  /Action:Import ^
  /TargetServerName:%DB_HOST% ^
  /TargetDatabaseName:%DB_NAME% ^
  /TargetUser:%DB_USER% ^
  /TargetPassword:%DB_PASSWORD% ^
  /TargetEncryptConnection:True ^
  /SourceFile:dump.bacpac

```

※暗号化された接続を行わない場合は`/TargetEncryptConnection`へ`False`を与える




### Extract: スキーマを取り出す

定義は欲しいけどデータはいらないよ、というとき。

`/Action:Extract`を使って、**dacpacファイル**を得ます。（**bacpacファイルではない**です。）


```
"C:\Program Files (x86)\Microsoft SQL Server\140\DAC\bin\sqlpackage" ^
  /Action:Extract ^
  /SourceServerName:%DB_HOST% ^
  /SourceDatabaseName:%DB_NAME% ^
  /SourceUser:%DB_USER% ^
  /SourcePassword:%DB_PASSWORD% ^
  /p:VerifyExtraction=True ^
  /TargetFile:dump.dacpac
```

※暗号化された接続を行わない場合は`/p:VerifyExtraction`へ`False`を与える


なお、得られたdacpacファイルをクリックすると展開できるはずです。各スキーマのDDLがSQL文として得られます。
インデックスが効いた検索をPHPで表してみた

## はじめに

* 「いんでっくす」を使って検索すると速いらしい
* 「いんでっくす」を一切貼ってないDBを作ったら先輩に怒られた
* DB設計・クエリ実行において「いんでっくす」が重要らしい

という新人さんのために記事
ある程度プログラム書けるけどデータベース、特にインデックスはイマイチよく分からんという人のための記事
何となくインデックスを理解してもらうための記事

## サンプルコード

まずインデックスなしの検索はこちら
クエリでいうと`type=all`

```php:no_index.php
<?php
<?php
// indexが貼られてない100000件のテストデータを用意
// [
//   ['user_id' => 'user0', 'user_name' => 'user0_name'],
//   ['user_id' => 'user1', 'user_name' => 'user1_name'],
//   ...
// ]
$records = [];
for($i = 0; $i < 100000; $i++){
    $records[] = ['user_id' => "user{$i}", 'user_name' => "user{$i}_name"];
}

// インデックスなし検索
// 例えばuser99999を探す
$time_start = microtime(true);
foreach($records as $record){
    if($record['user_id'] === 'user99999'){
        echo "user99999のユーザー名は{$record['user_name']}です\n";
        break;
    }
}
$time = microtime(true) - $time_start;
echo "{$time} 秒\n";

// user99999のユーザー名はuser99999_nameです
// 0.020262002944946 秒

```

次にインデックスあり検索
クエリでいうと`type=const`

```php:use_index.php
<?php
// user_idにインデックスが貼られてる100000件のテストデータを用意
// ['user0' => 'user0_name', 'user1' => 'user1_name', ...]
$records = [];
for($i = 0; $i < 100000; $i++){
    $records['user'.$i] = 'user'.$i.'_name';
}

// インデックスあり検索
// 例えばuser99999を探す
$time_start = microtime(true);
echo "user99999のユーザー名は{$records['user99999']}です\n";
$time = microtime(true) - $time_start;
echo "{$time} 秒\n";

// user99999のユーザー名はuser99999_nameです
// 4.6014785766602E-5 秒
```
## 比較

| インデックスなし | インデックスあり |
|:-----------:|:------------:|
|0.02秒|0.000046秒|

インデックスありの方が約434倍速いことが分かった
これは件数が多くなればなるほど顕著

## 解説

インデックスなしのパターンの方は配列に対して0から順に値の確認をしていき、該当のものがあれば値を取得して処理をやめます
値を順々に見ていくので当然レコード数が多くなればなるほど遅くなります
インデックスありのパターンの方は配列のキーがそのままインデックスなので順々に調べていかなくても1発で欲しい情報が取れています
なのでインデックスが効いた検索をした方が速いのです

またインデックスなしの例の方はテストデータの形がそもそもインデックスが貼られていない作りになっているため任意のユーザーのnameをとるのが難しい形になっています
これがインデックスを貼ってないDBというイメージです
インデックスありの例のように1発で取りたい情報が取れる形にデータ（DB）を作っておくのが望ましいですね

## おわりに

実際のクエリのtypeにはconstの他にrefやrangeなど色々あり、一概には上記の例は適用できません。

* インデックスのイメージがわくこと
* インデックスの重要性が分かること

が達成できたら嬉しく思います :smile:
JenkinsPipelineで多段SSHした時に1コマンドしか実行されずconnection to server1 closedになる対処

# やりたいこと
jenkins pipleneから多段sshをしてコマンドを実行する．(commandにはパラメータからの文字列を代入するものもある)

```Jenkinsfile
stage('TEST') {
    sh 'ssh -t -t server1 \'ssh server2 \" command1 && command2 && ...\"\''
}
```
※なぜかcommand1の前に空白がないとcommand1さえ実行されなかった...
※`-t -t`をつけないとPseudo-terminal will not be allocated because stdin is not a terminal.になった． 
参考: [ssh を用いてリモートでスクリプトを実行](https://takat.exblog.jp/12216326/)

# 問題
最初のコマンドのみしか実行されない． command2以降のコマンドが実行されずconnecion closedになる．

```
[sso_stg@2] Running shell script
+ ssh -t -t server1 'ssh server2 'command1
Connection to server1 closed.
```

# 解決策
シングルクオートとダブルクオートの順番を気をつける．
順番は以下に示す通り．

```Jenkinsfile
stage('TEST') {
    sh "ssh -t -t server1 'ssh server2 \" command1 && command2 && ...\"'"
}
```

# まとめ
ダブルクオートなのかシングルクオートを使うのかではまったのでメモをしました．jenkinsからパラメーターを入力してそれをcommandに含める時の場合は上記クオートの順番で試してみてください．
Javaにおけるインスタンスの使用メモリの計測


## インスタンス毎の使用メモリサイズの調査
[前回の記事](https://qiita.com/N_G/items/2dab8694fdebce2de868)でJavaアプリケーションにおける、メモリの使用状況を確認する方法を記載しました。今回は、メモリを使用する処理が分かった後、それぞれのインスタンスが実際にメモリをどの程度使っているかの計測をしたいと思います。

## java-sizeofライブラリの導入
Javaのサイズを計測するライブラリはいくつかありますが、今回は **java-sizeof** ライブラリを使用します。[CARROT SEARCH LAB](https://labs.carrotsearch.com/hppc.html)が開発しているライブラリで

  - Maven Repositoryに公開されている。
  - Java6,7,8をサポートしている。

等の利点があります。
jarファイルは[Maven epository](https://mvnrepository.com/artifact/com.carrotsearch/java-sizeof) からダウンロードしてください。Mavenを使用する場合は、pom.xmlファイルに以下を記載します。versionはインストールしたいversionを指定してください。本記事では"0.0.5"を使用しています。

```xml
<dependency>
    <groupId>com.carrotsearch</groupId>
    <artifactId>java-sizeof</artifactId>
    <version>｛version｝</version>
</dependency>
```

## 使い方
それではjava-sizeofライブラリを使用してメモリのサイズ計測を行いたいと思います。
以下のように計測したいインスタンスに対し、*RamUsageEstimator.sizeOf* 関数を呼び出すだけです。
#### サンプルコード
```Java
import com.carrotsearch.sizeof.RamUsageEstimator;
import java.util.ArrayList;
import java.util.List;

public class JavaSizeofTest
{
    public static void main( String[] args )
    {
    	int[] intArray = new int[10];
    	List<Integer> intList = new ArrayList<Integer>(10);

    	for(int i = 0 ; i < 10 ; i++){
    		intArray[i] = i;
    		intList.add(i);
    	}

    	System.out.println("intArray size(byte) -> " + RamUsageEstimator.sizeOf(intArray));
        System.out.println("intList size(byte) -> " + RamUsageEstimator.sizeOf(intList));
    }
}
```
#### 出力
```
intArray size(byte) -> 56
intList size(byte) -> 240
```
インスタンスのサイズが取得できました。

## 独自クラスのインスタンスのメモリ計測
上の方法を使用すると自作クラスのインスタンスのメモリの計測も可能です。再帰的に全てのメンバ変数のサイズを足し合わせたサイズを知ることができます。

#### サンプルコード
```Java
package so_netmedia.java_sizeof_test;

import com.carrotsearch.sizeof.RamUsageEstimator;
import java.util.ArrayList;
import java.util.List;

public class JavaSizeofTest2
{
    static class MyClass{
        int[] intArray = new int[10];
        List<Integer> intList = new ArrayList<Integer>(10);

        public MyClass(){
            for(int i = 0 ; i < 10 ; i++){
                intArray[i] = i;
                intList.add(i);
            }
        }
    }

    public static void main( String[] args )
    {
    	MyClass myInstance = new MyClass();
    	System.out.println("myInstance size(byte) -> " + RamUsageEstimator.sizeOf(myInstance));
    }
}
```

#### 出力
```
myInstance size(byte) -> 320
```
先ほどのインスタンスのサイズの合計に、クラスのオーバーヘッドを足したサイズとなりました。

## アプリケーションでのサイズ計測
上のメモリ計測をサイズが大きそうなインスタンスで行い、ログ出力することで、どのインスタンスでどのくらいのメモリが使用されているかを調査することができます。メモリを消費しているインスタンスを突き止めてメモリの削減を行いましょう。 最後に一点注意ですが、**サイズの大きなインスタンスのメモリ計測にはある程度の時間がかかります。** Staging環境では測定して、本番ではskipする等、制御を忘れないようにしましょう。
ProxyのせいでAdobe CCが使用できない（Windows 10）

<img src="https://qiita-image-store.s3.amazonaws.com/0/34660/8b5fb5c2-53db-b889-64e1-a882854df07a.png" width="50%">

コマンドプロンプトを管理者権限で開き、下記のように `set proxy` する

```command:cmd
netsh winhttp set proxy http://111.11.11.111:8080
```
PHPUnit とりあえず動かすとこまで


## phpunitのインストール

- composer.json

```composer.json
{
    "require-dev": {
        "phpunit/phpunit": "*"
    }
}
```

- インストール

```sh
$./composer.phar install
```


## ディレクトリの作成

```sh
$ mkdir src
$ mkdir tests
```

## テスト対象ソースをautoloadするように設定する

```composer.json
{
    "require-dev": {
        "phpunit/phpunit": "*"
    },

    "autoload": {
        "psr-4": {
            "Sample\\": "src/"
        }
    }

}
```

### 実装

- テストコード

```tests/SampleTest.php
<?php

require_once('vendor/autoload.php');

class SampleTest extends PHPUnit\Framework\TestCase {

    public function test_add() {
        $sample = new Sample\Sample();
        $this->assertEquals(10, $sample->Add(4, 6));
    }

    public function test_sub() {
        $sample = new Sample\Sample();
        $this->assertEquals(1, $sample->Sub(7, 6));
    }

}
```

- テスト対象コード

``` src/Sample.php
<?php

namespace Sample;

class Sample {

    // $a + $b を返す                                                                                                                                                                                                                                                           
    public function add($a, $b) {
        return $a + $b;
    }

    // $a - $b を返す                                                                                                                                                                                                                                                           
    public function sub($a, $b) {
        return $a - $b;
    }

}
```

### テスト実行
```sh
$ vendor/bin/phpunit tests/
PHPUnit 7.1.4 by Sebastian Bergmann and contributors.

..                                                                  2 / 2 (100%)

Time: 21 ms, Memory: 4.00MB

OK (2 tests, 2 assertions)
```
GNU stow で .gitignore のシンボリックリンクが作られない理由と解消法

## 発端
[私の dotfiles](https://github.com/ndxbn/dotfiles/tree/8c60b58d006321a0b792eea688ae3a1931d91dc3) で、 `stow git` としても、 `~/.gitignore` が作られませんでした。

`stow -vvv git` としたところ、以下のようなログになりました

```                                        
stow dir is /Users/ndxbn/dotfiles
stow dir path relative to target /Users/ndxbn is dotfiles
cwd now /Users/ndxbn
cwd restored to /Users/ndxbn/dotfiles
cwd now /Users/ndxbn
Planning stow of package git...
Stowing contents of dotfiles/git (cwd=/Users/ndxbn)
Stowing dotfiles / git / .gitconfig
LINK: .gitconfig => dotfiles/git/.gitconfig
Planning stow of package git... done
cwd restored to /Users/ndxbn/dotfiles
Processing tasks...
cwd now /Users/ndxbn
cwd restored to /Users/ndxbn/dotfiles
Processing tasks... done
```

つまり、「 `.gitignore` は stow する対象にならなかったよ」ということです。

## なぜ stow されなかったか
[`stow` のドキュメント](https://www.gnu.org/software/stow/manual/stow.html#Types-And-Syntax-Of-Ignore-Lists) に、以下のようにかかれていました。

> If neither the package-local or global ignore list exist, Stow will use its own built-in default ignore list, which serves as a useful example of the format of these ignore list files
> もし、package-local な ignore list も global な ignore list もなかった場合、 Stow はビルトインのデフォルトの ignore list を使う。その内容を、 ignore list files の書き方のいち良例として示すな。（意訳）

```
# Comments and blank lines are allowed.

RCS
.+,v

CVS
\.\#.+       # CVS conflict files / emacs lock files
\.cvsignore

\.svn
_darcs
\.hg

\.git
\.gitignore

.+~          # emacs backup files
\#.*\#       # emacs autosave files

^/README.*
^/LICENSE.*
^/COPYING
```

なるほど、 `.gitignore` はデフォルトの ignore に含まれるんですね。

## どう解決するか
[`stow` のドキュメント](https://www.gnu.org/software/stow/manual/stow.html#Types-And-Syntax-Of-Ignore-Lists) に書かれているとおりにやればよいです。

~~今回の場合は、「dotfiles リポジトリは stow project なリポジトリ」と言えるので、 [`.stow-local-ignore` をプロジェクトルートに置きました](https://github.com/ndxbn/dotfiles/commit/2c155986bf40f73ae47f218a3f4b2b2b2bd3b0c8)。~~ パッケージルートごとに置けるらしいので、 [`git` パッケージルートに置きました](https://github.com/ndxbn/dotfiles/commit/58032b4a6b98448119848aa2dbdc52f465cc3876)。