OmniAICreator/Qiita-1.07M huggingface dataset:
MySQLのタイムゾーン変換で少しはまった件

# EPOCH時間をタイムスタンプに変換

from_unixtime()関数で得られる。

```mysql
mysql> select from_unixtime(1517136662);
+---------------------------+
| from_unixtime(1517136662) |
+---------------------------+
| 2018-01-28 19:51:02       |
+---------------------------+
1 row in set (0.02 sec)
```

ただし、この時返ってくるタイムスタンプのタイムゾーンはMySQLのtime_zoneの設定値に依存する。
上記の例はJSTの場合。

タイムゾーンの設定に依存せずに常にUTCで取得したかったので以下のようなSQLを書いたところnullが返ってきた。

```mysql
mysql> convert_tz(from_unixtime(1517136662), @@session.time_zone, 'utc');
+-------------------------------------------------------------------+
| convert_tz(from_unixtime(1517136662), @@session.time_zone, 'utc') |
+-------------------------------------------------------------------+
| NULL                                                              |
+-------------------------------------------------------------------+
1 row in set (0.00 sec)
```
どうやらタイムゾーンテーブルなるものをロードしなければならないらしい。

https://dev.mysql.com/doc/refman/5.6/ja/mysql-tzinfo-to-sql.html

```bash
$ mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
```

```mysql
mysql> select convert_tz(from_unixtime(1517136662), @@session.time_zone, 'utc');
+-------------------------------------------------------------------+
| convert_tz(from_unixtime(1517136662), @@session.time_zone, 'utc') |
+-------------------------------------------------------------------+
| 2018-01-28 10:51:02                                               |
+-------------------------------------------------------------------+
1 row in set (0.00 sec)
```
IntelliJ IDEAのプラグインを作ろう！(プロジェクト作成と設定まで)

# まえがき
この記事シリーズのソースコードは以下のリポジトリで管理されています。
[Qiita Artifact Plugin](https://github.com/syuchan1005/QiitaArtifactPlugin)

# 目次
1. プロジェクト作成と設定まで(ここ)
2. [アクションの追加, 通知, ダイアログ](https://qiita.com/syu_chan_1005/items/a13a1ba48f5cfe862dd8)
3. [拡張ポイント](https://qiita.com/syu_chan_1005/items/7dcb4c68c26aa0594e4e)

# 自己紹介
めんどくさいからプロフページよりどうぞ

# はじめに
Jetbrains系IDE愛用してますか？
使っていると「〇〇であったアレほしいなぁ」というのがあると思います。
もちろんSettingの変更で対策できるものもありますがそれでは事足りないことも多々あると思います。
**ので**プラグイン作ってやってみましょう。

# 新しいPluginプロジェクトの作成
1. IntelliJ IDEAを開き`Create New Project`を開きます
1. 左パネルから`IntelliJ Platform Plugin`を選択します。
1. 右パネルの設定には
    - SDKを指定します。リストに何も表示されない場合は`New`をクリックしてIntelliJ IDEAのインストールフォルダを選択してください。
    - その下は言語サポートやSQLサポートなどの設定です(今回は無視)
1. `Next`をクリックし`Project name`，`Project location`を入力して`Finish`をクリックします。

# プラグインの初期設定
まずは`resources\META-INF\plugin.xml`を開きましょう。
1つ1つ解説していきます

- id: IDE内でのPlugin名です。`<ドメインの逆順>.<プラグイン名(全部小文字)>`が主流。
- name: プラグイン名。`Settings -> Plugins`から検索される。わかりやすいものが良い
- version: バージョン，人によって違うから何も言わぬ。
- vendor: (ちょっと意味合い違うけど)作者名
    - \<option\>url: ホームページとかのアドレス
    - \<option\>email: メールアドレス
- description: 説明文
- change-notes: 前のバージョンとの違いなどを書く
- idea-version 
    - \<option\>since-build, \<option\>until-build
    - ビルドは基本3ケタの数字で表されます。IDEのバージョンは`YYYY.R.*`と言う形で表されこれのYYの下二桁とRの組み合わせがビルドです。(他にも表記法はあります。)つまり`2017.3.3`は`173`, `2016.2`は`162`のようになります。

基本はこれで十分です。これより下及び他は必要なときに解説します。
      

# おわりに
内容少な！ってなりました？意図的です()

やっぱりIntelliJ IDEAのPlugin作るからには独自言語とか作りたいと思うのでこの先は独自言語の作り方を書いて行きます。

といいたいところですが何事も基礎が肝心と言うことで次はAction, Notification, Dialogについて解説します。詳しいことは次で。

## 次
[ここ](https://qiita.com/syu_chan_1005/items/a13a1ba48f5cfe862dd8)
Herokuでffmpegを使えるようにする

Herokuでffmpegを使えるようにする方法です。

こちらのbuildpackを使いました。
https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest

heroku-buildpack-multiは使わなくていいようです。
複数のbuildpackを使うときもaddするだけで使えます。

#環境
heroku-cli 6.15.18

#buildpack登録
heroku createしたあとでbuildpackを登録します。

```bash:
$ heroku buildpacks:add https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest.git
```
```git push heroku master```すると使えるようになります。

#動作確認
ちゃんと動くか確認します。

```bash:
$ heroku run "ffmpeg -version"
```

#ffmpeg使い方
Herokuでファイルを保存できるのは/tmpフォルダだけなので
変換したいファイルは/tmpフォルダに保存してから使います。

/tmpフォルダは実行が完了したら消えてしまうので
ずっと保存したいファイルはAmazon S3など外部サービスを利用します。

以下はmp3をm4aに変換する例です。

```bash:
ffmpeg -i /tmp/test.mp3 -ab 256k /tmp/test.m4a
```

ffmpegコマンドをプログラムから呼び出せばファイル形式の変換ができるようになります。
git 用語集 使い方 備忘録

# gitの用語集
- コミット
    - ユーザーが変更の履歴を記録する作業のこと
    - この際にコミットメッセージを残す
- ブランチ
    - 履歴を枝分かれさせること
    - いくらでも枝分かれさせることが可能
- マージ
    - ブランチで枝分かれした履歴を１つにまとめること
- リポジトリ
    - ある作業している場所のこと
- ローカルリポジトリ
    - 各個人のコンピュータのその作業領域のこと
- リモートリポジトリ
    - サーバーにリポジトリをおいているリポジトリのこと
webpackのビルドを10倍高速化するプラグインの紹介

* 2018/3/29 キャッシュで問題が起こったときに、キャッシュを削除する方法を追記しました。

# 概要

TypeScript + React + Webpack で開発しているフロントエンドプログラムのビルド時間が、ファイルが増えるのに従ってどんどん長くなって来ていたのですが、その問題を解決するWebpackプラグインを見つけたので紹介します。

情報元: [0–100 in two seconds — speed up webpack](https://medium.com/ottofellercom/0-100-in-two-seconds-speed-up-webpack-465de691ed4a)

上記の記事によると、DLL と HardSourcePlugin を両方追加すると良い、と書かれてます。
残念ながら手元の環境では DLL はビルド時にエラーが起こったので採用を見送りましたが[^1]、HardSourcePlugin は導入に成功し、ビルド時間を **105sec -> 10sec (!!!)** に減らすことができました。

[HardSourceWebpackPlugin](https://github.com/mzgoddard/hard-source-webpack-plugin)

READMEによると、HardSourcePlugin は中間キャッシュを作ることでビルド時間短縮を実現しているとのことです。

# 導入手順

* HardSourcePluginをインストール

```shell
npm install --save hard-source-webpack-plugin
```

* webpack.config.js に追記

```js
// webpack.config.js
var HardSourceWebpackPlugin = require('hard-source-webpack-plugin');

module.exports = {
  context: // ...
  entry: // ...
  output: // ...
  plugins: [
    new HardSourceWebpackPlugin()
  ]
}
```

# 実行してみる

npm start や npm run build を普段通り実行すればOKです。
1回目の実行ではキャッシュを作るために普段と同じくらい時間がかかりますが、うまくいけば2回目の実行からは劇的に速くなるはずです。

webpackのビルド時間が長くなって困っている方は一度お試しください。


# キャッシュ絡みの問題が起こったときに、キャッシュを消す方法 (バッドノウハウ)

hard-source-webpack-plugin を使ってると、たまにキャッシュが正しくないためにエラーが起こってしまうケースに度々遭遇します。

ビルドは通ってるのに、ブラウザ上で関数が見つからないとランタイムエラーが表示される、などです。

そういうときは一度キャッシュを削除してやると、正しく動きます。

キャッシュは node_modules/.cache/hard-source に格納されています。キャッシュで問題が起こったら、このディレクトリを削除してみてください。


# 注釈

[^1]: Windowsだから？
Eclipseでコーディング規約を自動で修正して保存する

# 概要
- Eclipseで開発している時に自動でコーディング規約を適用して保存する方法の備忘録

# 背景
- ソースコードレビュー時にコーディング規約違反を指摘するのが馬鹿らしい
- ソースコードレビューの時間はもっと別のことにリソースを集中したい
- プログラミングの癖は十人十色なので、気を付けてもコーディング規約違反はでちゃう

# 解決策
- Eclipseで自動で保存する時に修正してもらう（今更かよ！）
- Googleが[コーディング規約](https://github.com/google/styleguide)を公開している。例えば、Javaだと[こんな感じ](https://google.github.io/styleguide/javaguide.html)
- Eclipseにはフォーマット機能(ショートカットキー：Ctrl + Shift + F)があり、指定したコーディング規約(xml形式でインポートされているもの)にしたがって、修正可能。

# 環境設定
- Eclipse 4.7 Oxygen（Pleiades）
- Java 1.8
- Git

# 手順
1. ウィンドウ→パースペクティブ→パースペクティブを開く→その他→Git
2. Gitリポジトリーの複製→URIの複製→URI:「https://github.com/google/styleguide.git」 を入力→次へ→次へ→「ローカル宛先」：ディレクトリーは任意の宛先を入力→完了
3. ウィンドウ→設定→Java→コード・スタイル→フォーマッターでインポートをクリックし、2.でCloneしたディレクトリから「eclipse-java-google-style.xml」を選択→「適用して閉じる」
4. ウィンドウ→設定→Java→エディター→保管アクション→「保管時に選択したアクションを実行」にチェック→「ソース・コードのフォーマット」にチェック→「適用して閉じる」
5. (既に作成済のソースコードがある場合は、)プロジェクトを右クリック→ソース→フォーマット で全ファイルにフォーマットが掛けられる
6. 以降は、ソースコードを保存する度にフォーマット機能が働く
SurfaceProでイマーシブデバイスに映像が表示されない場合の対応

トラブルシュート出来たのでメモとして残しておく。

# 環境
- 新しいSurface Pro (5代目, 2017年モデル)
- Dell Visor
- MiniDisplayPort to HDMI変換ケーブル

# 発生事象
- Surface ProにVisorを接続すると本体ディスプレイが数秒置きに表示が消えたりついたりする
- Mixed Reality ポータル上ではデバイスが正常に認識されている
- Visorに映像が何も表示されない

# 解決方法

- 4k出力に対応したMiniDisplayPort to HDMI変換アダプタを使用する
  - 自分が試した製品は「ミヨシ DPA-4KHD01」

# 雑記
普段からプロジェクター/外部ディスプレイへ接続する際に使用していた安物のケーブルをそのまま使ったのが敗因でした。
「Visorのスペック的に4K出力出来ないとダメなのでは?」と思い至って近くの電気店でアダプタを購入して試したらちゃんと映像が出るようになりました。

Visorが無駄な買い物になってしまったかとちょっと焦りましたが解決出来て良かった。
JavaScriptのES6の拡張子.mjsのモジュールファイルをNginxで送る方法

## 背景
ブラウザで動くjavascriptエディター [jsnote](https://toyoharu-nishikawa.github.io/jsnote/)を作っていた. ES6のmoduleのファイルの拡張子を.mjsにしたら、Nginxで送れなかった.

## 問題
mine typeが合わないからファイルを送れないとconsole画面で言われる.
nginxのmine.typesというファイルを見ると次のように書いてあった.

``` /etc/nginx/mine.types
types {
    text/html                             html htm shtml;
    text/css                              css;
    text/xml                              xml;
    image/gif                             gif;
    image/jpeg                            jpeg jpg;
    application/javascript                js;
    application/atom+xml                  atom;
    application/rss+xml                   rss;
```

## 対処法
mine.typesを/etc/nginx/conf.dの下にコピーして, application/javascriptにmjsを加える.

``` /etc/nginx/conf.d/mine.types
types {
    text/html                             html htm shtml;
    text/css                              css;
    text/xml                              xml;
    image/gif                             gif;
    image/jpeg                            jpeg jpg;
    application/javascript                js mjs;
    application/atom+xml                  atom;
    application/rss+xml                   rss;
    .
    .
    .
```

さらに、nginxのconfファイルの中でmine.typesをincludeする.

```nginx:/etc/nginx/conf.d/server.conf
server {
  listen 80 default_server;
  server_name server.com;
  include /etc/nginx/conf.d/mime.types;

  location / {
    root /usr/share/nginx/html;
    index index.html;
  }
}
```

## サンプルコード
jsnoteで使っているコード
[GitHub](https://github.com/Toyoharu-Nishikawa/jsnote/tree/master/conf.d)
コンソールでカウントダウン表示

コンソールでカウントダウンされる表示の方法。
単にprintでバックスペースのエスケープ文字を出力するのみ。

``` count.rb
print "1秒"
sleep 1
(2..9).each do |num|
  print "\b\b\b" + num.to_s + "秒"
  sleep 1
end
```

マルチバイトだとバックスペース文字が複数個必要なのかな？
そのへんまだ調べてない。

改善版

``` count2.rb
count = (200..500).to_a.sample
(1..count).to_a.reverse.each do |num|
  str = num.to_s + "秒"
  print str
  sleep 1
  print "\b" * str.bytesize
end
```
kube-awsで既存のvpc、subnetに入れるときにハマったのでメモ

# kube-awsとは
[10分でわかる「kube-aws」](https://qiita.com/mumoshu/items/d80c71f8a6cfb5ccfc01)を参照ください。
kube-awsをメンテされている方にて記載されています。

# 既存のvpcに入れる時にハマった
kube-awsを使い始めて、既存のvpcになかなか入れられなかったのでメモ
試行錯誤した結果なので正しく無いかもしれないですが、このyamlで動きました。

```:cluster.yaml
clusterName: oreno-k8s
sshAccessAllowedSourceCIDRs:
- 0.0.0.0/0
apiEndpoints:
-
  name: default
  dnsName: oreno.k8s.dev.examlpe.com
  loadBalancer:
    subnets:
    - name: ExistingPublicSubnet1
    - name: ExistingPublicSubnet2
    hostedZone:
      id: ABCDEFGAAAAAA
keyName: oreno-keyname
region: us-west-2
kmsKeyArn: "arn:aws:kms:us-west-2:1234567890123:key/aaaaaaa-aaaaa-aaaaa-aaa-aaaaaaa"
controller:
  instanceType: t2.medium
  rootVolume:
    size: 30
    type: gp2
  autoScalingGroup:
    minSize: 2
    maxSize: 3
    rollingUpdateMinInstancesInService: 2
  subnets:
  - name: ExistingPublicSubnet1
  - name: ExistingPublicSubnet2
worker:
  nodePools:
    - name: nodepool1
      count: 2
      instanceType: t2.medium
      rootVolume:
        size: 30
        type: gp2
etcd:
  count: 3
  instanceType: t2.medium
  rootVolume:
    size: 30
    type: gp2
  subnets:
    - name: ExistingPublicSubnet1
    - name: ExistingPublicSubnet2
vpc:
  id: vpc-123456789
subnets:
  - name: ExistingPublicSubnet1
    availabilityZone: us-west-2a
    id: "subnet-1234567a"
  - name: ExistingPublicSubnet2
    availabilityZone: us-west-2c
    id: "subnet-9876543e"
containerRuntime: docker
kubernetesDashboard:
  adminPrivileges: true
  insecureLogin: false
addons:
  省略
experimental:
  省略
```

# ポイント
## vpc
vpcはvpc.id、vpc.routeTableId、vpc.vpcCIDRは既存VPCの値を入れる

```
vpc:
  id: vpc-123456789
```
## subnets
subnetsのnameは任意、subnet.availabilityZone、subnet.idは既存のsubnetの値を入れる

```
subnets:
  - name: ExistingPublicSubnet1
    availabilityZone: us-west-2a
    id: "subnet-1234567a"
  - name: ExistingPublicSubnet2
    availabilityZone: us-west-2c
    id: "subnet-9876543e"
```

## controller
controllerのsubnetsでsubnets.nameの値を指定する
複数指定することで複数AZで展開できる

```
controller:
  instanceType: t2.medium
  rootVolume:
    size: 30
    type: gp2
  autoScalingGroup:
    minSize: 2
    maxSize: 3
    rollingUpdateMinInstancesInService: 2
  subnets:
  - name: ExistingPublicSubnet1
  - name: ExistingPublicSubnet2
```

## etcd
controllerと同じくsubnetsでsubnets.nameの値を指定する
複数指定することで複数AZで展開できる

```
etcd:
  count: 3
  instanceType: t2.medium
  rootVolume:
    size: 30
    type: gp2
  subnets:
    - name: ExistingPublicSubnet1
    - name: ExistingPublicSubnet2
```

## worker
ここでハマったのですが、workerにもworker.nodePools.subnetsがありますが、subnetsを指定するとエラーが出てデプロイ出来なかったです。
subnetsを指定しないとデプロイが出来て、複数台を複数AZにデプロイしてくれました。
指定しなかったらデフォルトでvpc.subnetを見るのかな？？教えてエラい人・・

```
worker:
  nodePools:
    - name: nodepool1
      count: 2
      instanceType: t2.medium
      rootVolume:
        size: 30
        type: gp2
```

# PS.
kopsよりAWS寄りに実装されているので、AWSでk8sを扱う方はkube-awsはオススメです。
Rubyの「クラス継承」と「Mix-in」


# rubyのクラス継承
1. 単一継承をサポート
  * rubyは単一継承のみ許されており、同時に複数のスーパークラスを持つ多重継承をサポートしていません

2. 小なり（<strong><</strong>）でスーパークラスを指定
  * <strong>superclass</strong>メソッドでスーパークラスの確認ができる

```ruby
# 例
class Parent
  def hoge
    p "Parentだよ"
  end
end

class Child < Parent
end

Child.superclass # => Parent

child = Child.new
child.hoge # => "Parentだよ"が表示
```

3.親クラスを指定しない場合は、自動的に<strong>「Object」</strong>クラスを継承

```ruby
# 例
class Child
end

Child.superclass # => Object
```

# rubyのMix-in
* **Mix-inとは**
  * クラスに機能を混ぜ合わせることで複数のクラスで機能を共有する機能となります

****

* **じゃ、モジュールとクラスとの違いは？**
  * モジュールは、インスタンス化できない
  * モジュールは、継承できない
  * モジュールは、クラスや他のモジュールに取込ことでできる

****

* **用途**
  * 名前空間をつくる
  * クラスを拡張することで、クラスが肥大化を防げる
  * モジュールのメソッドをあるオブジェクトの特異メソッドとして取り込む

****

* **使い方は、主に3つ**

1. **include**

```ruby
module M
  def hoge
    p "Mだよ"
  end
end

class Parent
  def hoge
    p "親だよ"
  end
end

class Child < Parent
  include M
end

child = Child.new
child.hoge # => "Mだよ"が表示されます

# クラスChildの継承チェーンをみてみましょう
Child.ancestors 
# => [Child, M, Parent, Object, Kernel, BasicObject]
```


2.**prepend**

```ruby
module M
  def hoge
    p "Mだよ"
  end
end

class Parent
end

class Child < Parent
  perpend M
  
  def hoge
    puts "Childだよ"
  end
end

Child.new.hoge # "Mだよ"
Child.ancestors 
# => [ M, Child, Parent, Object, Kernel, BasicObject]
# MモジュールはChildクラスより優先になります
```

3.**extend**

* include(prepend)との違いは
  * <strong>include</strong>はあるクラスのインスタンスに機能を追加
  * <strong>extend</strong>はある特定のオブジェクトだけにモジュールの機能を追加（特異クラス）


* クラス中で使われる場合

```ruby
module M
  def hoge
    p "Mだよ"
  end
end

class Klass
  extend M
end

klass = Klass.new
klass.hoge # NoMethorError

Klass.hoge # => "Mだよ"が表示されます
# MモジュールのメソッドがChildクラスのクラスメソッドとして拡張されました
```

* インスタンス（オブジェクト）に使う場合

```ruby
module M
  def hoge
    p "Mだよ"
  end
end

class Klass
end

klass = Klass.new
klass.extend M
klass.hoge # => "Mだよ"
# Mモジュールのメソッドはklassの特異メソッドとして拡張されています

klass_1 = Klass.new
klass_1.hoge # => NoMethodError
# klass_1オブジェクトに拡張されていないため、メソッドが見つからず、NoMethodErrorが発生
```


# 番外編
* クラスの継承チェーンを確認できるメソッド(ancestors)
* 例↓

```ruby
irb(main):001:0> Object.ancestors
=> [Object, Kernel, BasicObject]
```
GitHub の草ページ URL を axios で叩いて取得しようとして失敗した

# 概要

axios を使って vue.js ファイルから github の `https://github.com/users/${id}/contributions` ページを叩いて SVG を取得しようとしたが、失敗した。

# 経緯
github の草(contributions calender)が好きすぎたので、良い感じにビジュアライズするサービスを作りたくなった。

```
$curl https://github.com/users/longtime1116/contributions
```

これで良い感じにレスポンスが返って来ることを確認したので、いける！と思った。

# ソースコード
こんな感じに実装した。

```html:App.vue
<template>
  <div>
    <p v-if="user_id.length > 0">
    {{user_id}}
    </p>
    <p v-else>
      no id
    </p>
    <input type="text" v-model="user_id" >
    <button @click="getGarden()">show your garden</button>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      user_id: 'longtime1116',
    };
  },
  methods: {
    getGarden() {
      axios.get(
        `https://github.com/users/${this.user_id}/contributions`,
      ).then((response) => { console.log(response.data); });
    },
  },
};
</script>
```



# 結果
こんな感じのエラーがコンソールに表示された。
github 側からのレスポンスに`Access-Control-Allow-Origin`が含まれていないので、ブラウザが許可を与えていないような感じ？

```
Failed to load https://github.com/users/longtime1116/contributions:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:8080' is therefore not allowed access.
```
デベロッパーツールの Network のところみるとちゃんと get できているのに、悔しい。。。

# どうしよう？
間に一枚サーバをかませて、`Access-Control-Allow-Origin`を付与したものをブラウザ側に返すようにすれば良い。

私はこの問題について真に驚くべき解決方法を発見したが、ここに記すには余白が狭すぎる。

# 追記
克服した
https://qiita.com/longtime1116/items/8fa82d182c7863ca24f1
AWS ALBのスティッキーセッションについて調べてみた（再接続のたびにセッションの寿命は延びる）

ALBのスティッキーセッションを使うことになったのだが、設定を見るとセッション保持時間しか設定できない。
これだと、例えば`24h`で設定したとして、24h後のちょっと前にアプリにログインしても、stikky sessionのcookie切れで再ばランシングされて、ログインしていないインスタンスに接続したらログインセッションが切れてしまうことになる。
なんだかなーと思ってマニュアルを読み直すと以下の記述を見つけた。


>ターゲットグループレベルでスティッキーセッションを有効にします。
ロードバランサー生成のクッキーの維持期間を秒単位で設定することもできます。
期間はリクエストごとに設定されます。
そのため、各期間の有効期限が切れる前にクライアントがリクエストを送信すると、スティッキセッションが継続されます。
複数のターゲットグループのスティッキーセッションを有効にした場合、すべてのターゲットグループに同じ継続時間を設定することをお勧めします。


若干曖昧だた有効期限内にリクエストを送信するとセッションが延長されるって意味かな？
ということで実際に検証してみることにした。


## 検証環境
検証環境は以下のとおりとした。
nginxの`/stikky.txt`にアクセスするとそれぞれ`nginx01`、`nginx02`と返すようにしてある。
スティッキーセッションの期間は3秒とした（実環境ではこんな未時間に設定するわけないけどｗ）

```
Client --- ALB --- Nginx01
                └- Nginx02
```


## 検証結果

まずは5秒間隔でポーリングしてみる。
コマンド結果をみるとおりNginx01, Nginx02に交互に接続している。
スティッキーセッションが3秒で切れてしまうから、5秒後にアクセスしたときは新規接続とみなされ再振り分け、coocke再発行されるためだ。

```
[root@localhost ~]# yes "date '+%d-%m %H:%M:%S'|tr '\n ' ' ' ; curl -c ./cookie_elb.txt -b ./cookie_elb.txt http://nginx-1428263045.us-west-2.elb.amazonaws.com/stikky.txt;sleep 5;" | sh
27-01 05:45:03 nginx02
27-01 05:45:08 nginx01
27-01 05:45:14 nginx01
27-01 05:45:20 nginx02
27-01 05:45:25 nginx02
27-01 05:45:31 nginx01
27-01 05:45:36 nginx01
```


次に1秒間隔でポーリングしてみる。
30秒以上試したが今度はずっとNginx02に接続している。
心配していたセッションの途中切れだが、5秒以上たってもセッションは維持されるようだ。
つまりセッション期間内に再接続すればstikky sessyonの時間も延長される、ということだろう。

```
[root@localhost ~]# yes "date '+%d-%m %H:%M:%S'|tr '\n ' ' ' ; curl -c ./cookie_elb.txt -b ./cookie_elb.txt http://nginx-1428263045.us-west-2.elb.amazonaws.com/stikky.txt;sleep 1;" | sh
27-01 06:03:12 nginx01
27-01 06:03:14 nginx01
27-01 06:03:15 nginx01
27-01 06:03:17 nginx01
27-01 06:03:18 nginx01
27-01 06:03:20 nginx01
27-01 06:03:21 nginx01
27-01 06:03:23 nginx01
27-01 06:03:24 nginx01
27-01 06:03:26 nginx01
27-01 06:03:27 nginx01
27-01 06:03:29 nginx01
27-01 06:03:30 nginx01
27-01 06:03:32 nginx01
27-01 06:03:33 nginx01
27-01 06:03:35 nginx01
27-01 06:03:36 nginx01
27-01 06:03:38 nginx01
27-01 06:03:39 nginx01
27-01 06:03:41 nginx01
27-01 06:03:42 nginx01
27-01 06:03:44 nginx01
27-01 06:03:45 nginx01
27-01 06:03:47 nginx01
27-01 06:03:48 nginx01
27-01 06:03:50 nginx01

```

## で、スティッキーセッション期間はどれくらいに設定すべきか？

上記検証を踏まえると、バックグランドで頻繁に通信しているようなシステムならスティッキーもそのたびに更新され、ログアウトしない限り維持され続けると思われる。ユーザー操作がないと通信しないシステムの場合、無操作状態が続くとスティッキーセッションの有効期限を迎えてしまうから、システムのセッションタイムアウトと同じに設定するのが良いだろう。そうすれば、システムのセッションが切れて、再ログインが必要になるタイミングでスティッキーセッション有効期限が切れるのでユーザーが意図せず突然セッションが切れてしまう、という事態が防げる。
JavaScriptで書かれたブラウザで動くエディタAceのキーバインドをvim, emacsにした後デフォルトに戻す方法

## 背景
ブラウザで動くjavascriptエディター [jsnote](https://toyoharu-nishikawa.github.io/jsnote/)を作っていた. ユーザがキーバインド(エディターの種類)をvim, emacs, aceの中から選べるようにしたかった. デフォルトはAce(Atomのブラウザ版)になっているが、設定をvimやemacsにした後、再びAceに戻す方法が分からなかった.
## 問題
下記のコードでvimやemacesに設定することはできる。

``` html
<script src="/ace-builds/src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
<script>
  const editor = ace.edit('editor');             
                                                   //default Ace
  editor.setKeyboardHandler("ace/keyboard/vim");   //vim
  editor.setKeyboardHandler("ace/keyboard/emacs"); //emacs
  /*reset*/
  editor.setKeyboardHandler("ace/keyboard/");      //error
  editor.setKeyboardHandler("");                   //error
</script>
```

consoleで引数がおかしいと言われて実行できない

## 対処法
nullを入れるとデフォルトのAceに戻る

``` html
<script src="/ace-builds/src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
<script>
  const editor = ace.edit('editor');             
                                                   //default Ace
  editor.setKeyboardHandler("ace/keyboard/vim");   //vim
  editor.setKeyboardHandler("ace/keyboard/emacs"); //emacs
  /*reset*/
  editor.setKeyboardHandler(null);                 //Ace
</script>
```
## サンプルコード
jsnoteで使っているコード
[GitHub](https://github.com/Toyoharu-Nishikawa/jsnote/blob/master/public/scripts/jsnote.mjs)
Ubuntuでデスクトップからゴミ箱の表示を消す

#背景
Ubuntuをインストールした直後はデスクトップにはゴミ箱のアイコン**だけ**配置されてます。
昔はデスクトップに色んなアイテムを配置していましたが、最近はアプリのランチャーはDockに配置してデスクトップはすっきりさせたいですね。(好みの問題ですが、ゴミ箱だけ表示ってバランス悪く感じますね)

![Screenshot from 2018-01-28 17-53-36.png](https://qiita-image-store.s3.amazonaws.com/0/152272/a5631e73-7978-769c-b192-43fd26bb23b8.png)

#動作環境
Ubuntu 17.10 64bit

#操作A
```$ gsettings set org.gnome.nautilus.desktop trash-icon-visible false```
これでスッキリ。
![Screenshot from 2018-01-28 18-21-17.png](https://qiita-image-store.s3.amazonaws.com/0/152272/3282ed22-4bce-ac78-7227-d80f37091da3.png)

#操作B
ゴミ箱のアイコンを消すだけなら、上記のコマンドでできますが、様々なカスタマイズができるTweaksを使うと何かと便利です。

1. まずはTweaksをインストール。
```$ sudo apt install gnome-tweak-tool```

2. 画面左下の「アプリケーションを表示する」の「ユーティリティ」の中にあるTweaksを起動。
![Screenshot from 2018-01-28 17-55-06.png](https://qiita-image-store.s3.amazonaws.com/0/152272/40966b82-7c4e-7741-729c-5289d1f1f121.png)
「デスクトップ」→「デスクトップアイコン」の「アイコンを表示する」か「ゴミ箱」をオフにすれば消えます。(それぞれの違いは言葉の通りです)

ちなみに、ゴミ箱へアクセスは、Nautilusからできるので不便に感じることはないでしょう。
ggplot2でplotのtype="b"に似たプロットをする。

簡単なのは、geom_line()とgeom_point()の間に、背景色と同じ色で大きめの点をプロットするgeom_point()を挿入する方法。


## 例

    library(ggplot2)
    
    ggplot(mtcars, aes(mpg, wt)) + theme_bw() +
        geom_line() +
        geom_point(size=5, color="white") + # 挿入
        geom_point()


mtcarsは自動車の燃費等に関するデータセット(32台分)。wt: Weight (1000 lbs)、mpg: Miles/(US) gallon。


## 参考
- [ggplot2 - Getting R plot type "b" - Stack Overflow](https://stackoverflow.com/questions/3810927/getting-r-plot-type-b)
Docker for Windows でDNS を8.8.8.8へ切り替えてもDocker イメージが取得できない場合の対処方法

# 概要

Windows 10 のDocker for Windows で `docker run hello-world`してもイメージが取得できない

## 現象

1. Docker for Windows をインストールし、コンソールで `docker run hello-world` を実行しても Docker イメージが取得できない。  

    ```PowerShell
PS C:\Windows\system32> docker run hello-world
Unable to find image 'hello-world:latest' locally
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers).
See 'C:\Program Files\Docker\Docker\Resources\bin\docker.exe run --help'.
    ```

2. Firewallに阻まれているわけでもない。
3. DNS を8.8.8.8へ切り替えてもダメ。

# 対処方法

* Windows container へ切り替える。  
タスクバー上のDocker アイコンを右クリックして、「Switch to Windows containers...」と表示されていたらLinux Containerになっています。
Windows Containers へ切り替えましょう。  
    ![image.png](https://qiita-image-store.s3.amazonaws.com/0/51831/bf2dbaef-d052-ab3e-136b-88047b277ef0.png)

* settings 画面の違いでも判ります。
    * Windows Container
    ![image.png](https://qiita-image-store.s3.amazonaws.com/0/51831/b937d76c-d335-7457-0cfb-1a7bf99f877b.png)
    * Linux Container
    ![image.png](https://qiita-image-store.s3.amazonaws.com/0/51831/3033a13c-6602-a7ae-df9f-4881ae045704.png)

## 結果

```PowerShell
PS C:\Windows\system32> docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (windows-amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run a Windows Server container with:
 PS C:\> docker run -it microsoft/windowsservercore powershell

Share images, automate workflows, and more with a free Docker ID:
 https://cloud.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/
```

### 確認バージョン

* Windows 10 Pro 1709(16299.192)
* Docker Community Edition Version 17.12.0-ce-win47 (15139)
unityのml-agentsでtensorflowを使った強化学習を試してみる

# 追記
1. tensorboardの記述を追記
2. 学習後の動画を埋め込んでみました。

# はじめに
　youtubeでSirajさんの
[Unity AI - Unity 3D Artificial Intelligence](https://www.youtube.com/watch?v=bqsfkGbBU6k)を見て、これは勉強会のネタになりそうだ、ということで、unityのml-agentsでtensorflowを使った強化学習を試してみた。3DBallサンプルの記事は、日本語で素晴らしい記事がたくさんあるので、リンクだけ。

https://qiita.com/Ao_i/items/18dec197434c7f853a92
http://nn-hokuson.hatenablog.com/entry/2017/12/26/213456
http://naomo.co.jp/2017/09/unityがtensorflowに対応/
https://qiita.com/dora-gt/items/bacce436de2a3cdb1ef4
http://am1tanaka.hatenablog.com/entry/2017/11/08/230525

# tennisサンプル
　tennisとは言っても、卓球（table tennis）のシミュレーションのようだ。
<img width="1492" alt="Screen Shot 2018-01-28 at 16.17.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/128327/f742769e-4d22-06ad-858f-5fad35ce7ae0.png">

　このサンプルを動かす時にハマったのは、下記の3点。

1. unityの[Hierarchy]タブの[Academy]以下にbrainが二つあると、python実行時にエラーになるので、一つにする
2. unityのBuild時に[Scenes in Build]でtennisにチェックをつける（選択する）

<img width="664" alt="Screen Shot 2018-01-28 at 16.42.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/128327/c1f25942-2af0-72d3-1866-b60bb4f062bf.png">

3. 最後に、学習済みモデルで動作させる際、[Graph Placeholder] sizeは 0のままで良いようだ。

# tensorboard
　学習の経過を確認するのに、tensorboardで見ることができます。うまく学習が進んでいるようです。

![Screen Shot 2018-01-28 at 19.22.56.png](https://qiita-image-store.s3.amazonaws.com/0/128327/0e3ac9a6-ec06-3221-1392-5b9d5663f6c8.png)

# 学習結果

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">unityのml-agentsで強化学習してみた。5万回の学習でtable tennisの初心者ぐらいにはなっている。 reinforcement learning by unity ml-agents <a href="https://t.co/IU2hgexXYG">https://t.co/IU2hgexXYG</a> via <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a></p>&mdash; Kazutoshi Nakano (@kznx) <a href="https://twitter.com/kznx/status/957571065730908165?ref_src=twsrc%5Etfw">January 28, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# 最後に
　pythonのコード自体は、3DBallもtennisも共通で行けるところが、頭では分かってはいたつもりだが、強化学習の汎用性の高さを感じる。また視覚的に動きが見えることで、強化学習の特徴が非常にわかりやすい。
Mac > USBインストーラーの作成


# USBインストーラーの作成

macOSをダウンロードしてUSBインストーラーを作成する。


## USBメモリをディスクユーティリティで消去

名称をUNTITLEDで消去する。

![スクリーンショット 2018-01-28 10.32.24.png](https://qiita-image-store.s3.amazonaws.com/0/49910/8f6982d7-0aa9-ec25-ec01-ec0a36a1b2ee.png "スクリーンショット 2018-01-28 10.32.24.png")




## HIGH Sierraの場合

AppストアからHigh Sierraを検索しダウンロードする。

![スクリーンショット 2018-01-28 10.13.53.png](https://qiita-image-store.s3.amazonaws.com/0/49910/7bddd438-d013-d70c-b9ba-30e90853dd17.png "スクリーンショット 2018-01-28 10.13.53.png")


ターミナルで以下のコマンドを打ち、USBメモリにインストーラーを作成する。

```
$ sudo /Applications/Install\ macOS\ High\ Sierra.app/Contents/Resources/createinstallmedia --volume /Volumes/UNTITLED --applicationpath "/Applications/Install macOS High Sierra.app"
```




## Sierraの場合

以下のリンクからmacOS Sierraをダウンロード
https://itunes.apple.com/jp/app/macos-sierra/id1127487414?mt=12&at=11lLqM


ターミナルで以下コマンドを打ちインストーラーを作成する。

```
sudo /Applications/Install\ macOS\ Sierra.app/Contents/Resources/createinstallmedia --volume /Volumes/UNTITLED --applicationpath /Applications/Install\ macOS\ Sierra.app --nointeraction
```

結果は以下のようになればOK

```
$ sudo /Applications/Install\ macOS\ Sierra.app/Contents/Resources/createinstallmedia --volume /Volumes/UNTITLED --applicationpath /Applications/Install\ macOS\ Sierra.app --nointeraction
Password:
Erasing Disk: 0%... 10%... 20%... 30%...100%...
Copying installer files to disk...
Copy complete.
Making disk bootable...
Copying boot files...
Copy complete.
Done.

```



### 再起動

Macをシャットダウンし、Optionキーを押しながら起動、USBメモリを選択しSierraのインストール画面が表示される。
ラズパイセットアップ時の我的まとめ


# Zero セットアップ
http://blue-black.ink/?page_id=1788

# 公開鍵認証
http://dystopia39.blog.fc2.com/blog-entry-1873.html
http://qiita.com/iruseira/items/af8550fea92b5c5f7fca
http://blog.ruedap.com/2011/04/04/mac-ssh-key-copy-error

# RaspberryPi 2で監視カメラ
http://www.geekcat-k.com/index.php/ciem/raspberrypi-2-2

# 日本語入力可能にする設定
```
sudo apt-get install ibus-anthy
```
http://ryus.co.jp/blog/raspberrypi2-4/
http://start-now.link/100/archives/1930

# Raspberry Piで複数Wifiで個別の固定IPを指定する方法
```
/etc/wpa_supplicant/wpa_supplicant.conf
/etc/network/interfaces
```

http://www.1ft-seabass.jp/memo/2015/03/23/raspberry-pi-wifi-multi-static-ip/
http://qiita.com/yoh-nak/items/10c3ce4d371d29fc7e42

# ufwコマンドによるファイアウォール設定
http://qiita.com/JhonnyBravo/items/f67d34c0ed8f2961919e

# wifi切り替え
```
sudo iwconfig wlan0 essid hoge_sid key
```
Swift 画像フィルタ処理後のCIImageをUIImageへ変換後の問題

写真を撮影後生成したUIImageデータを各種フィルター処理により生成されたCIImageデータをそのまま
UIImageに戻した場合その後の画像処理においてエラーが発生する場合の対策。
下記は画像をシャープ処理をするフィルター処理後生成されたCIImageを下記のように一旦CGImageに
変換後さらにUIImageに戻すことによりエラーを回避できる。

        func filter01(image: UIImage) -> UIImage?{
            let ciImage:CIImage = CIImage(image:image)!
            // カラーエフェクトを指定してCIFilterをインスタンス化.
            let mySharpFilter = CIFilter(name:"CIUnsharpMask")
            
            // イメージのセット.
            let radius = 8
            mySharpFilter!.setValue(ciImage, forKey: kCIInputImageKey)
            mySharpFilter!.setValue(radius, forKey: "inputRadius")
            mySharpFilter!.setValue(NSNumber(float: 1.0), forKey: "inputIntensity")
            print("ok4")
            
            // フィルターを通した画像をアウトプット. 
            //修正前let image2 = UIImage(CIImage: mySharpFilter!.outputImage!)
            let context = CIContext()
            let cgImage = context.createCGImage(mySharpFilter!.outputImage!,fromRect: mySharpFilter!.outputImage!.extent)
            let image2 = UIImage(CGImage: cgImage)
            return image2
        }
firefox用の狭額縁のスタイル

firefoxを初期リリースから使っていたのですが、
ツールバー類の太さが気になって、使い勝手が悪くなってきたので
自分で細いスタイルを書きました。

下のコードをuserChrome.cssに記述してスタイルを適用します。

```css:userChrome.css
/*タイトルバーを表示させないようにする*/
#TabsToolbar{
  min-height:0px !important;
  margin:0px !important;
}
.toolbar-items{
  visibility:collapse !important;
}
/*閉じる最小最大ボタンの位置を移動させる*/
.titlebar-buttonbox-container{
  margin-bottom: -25px;
  visibility:visible !important;
}

/*進む戻るボタンなどのサイズを指定*/
.toolbarbutton-1,.chromeclass-toolbar-additional {
  max-height: 25px !important;
  padding: 0px !important;
} 

/*URLバー、検索バーの余白を削除*/
#urlbar ,#searchbar{
  margin:0px !important;
  min-height:20px !important;
}
#urlbar-container,#search-container{
  padding: 2px !important;
}

/*URLバーの右側のスターアイコンなどのサイズを調整*/
.urlbar-icon{
  padding: 3px !important;
}

/*アドオンのボタンなど右側にあるボタン類の余白を消す*/
.findbar-button > .toolbarbutton-text,
toolbarbutton.bookmark-item:not(.subviewbutton),
toolbar .toolbarbutton-1 > .toolbarbutton-icon,
toolbar .toolbarbutton-1 > .toolbarbutton-text,
toolbar .toolbarbutton-1 > .toolbarbutton-badge-stack {
  padding: 0px !important;
  margin:0px 5px !important;
}

/*進むボタンがウィンドウの閉じるボタンが被らないように右にずらす*/
#nav-bar-customization-target{
  margin-left: 70px;
}

/*以下はwindowsでのみ有効にする機能*/

/*ツリー型タブを使うので、タブバーを隠す*/
#titlebar{
/*    visibility:collapse !important;*/
}
/*最大化した時に、上が切れないように*/
#nav-bar.browser-toolbar{
/*    padding-top: 7px !important;*/
}

```
画面はこんな感じ
![スクリーンショット 2018-01-28 17.04.42.png](https://qiita-image-store.s3.amazonaws.com/0/211497/caa2193c-af3c-d5a4-57ea-7bc8ef5d2407.png)


userChrome.cssの場所や編集の仕方、タブバーを消す部分は下のページを参考にしました。
https://debuyoko.com/959


2019/9/7 追記
firefoxのバージョンが上がって、ウインドウの最小化や閉じるボタンが表示されなくなっています。対策を検討中です。

2019/10/27 更新
スクリプトをfirefox 70.0 に対応

2020/6/24 更新
スクリプトをfirefox 77.0 に対応
grepの基本的な使い方


## grepとは
**global regular expression print**の略
ファイルの中の文字列を検索する。

## 基本コマンド
```
grep "検索文字列" ファイル名
```
```
grep "正規表現" ファイル名
```

拡張正規表現(ERE)を使うときは -E()オプションをつける

```
grep -E "正規表現" ファイル名
```

## 個人的によく使うオプション
**-r** ・・・ディレクトリを指定する場合。サブディレクトリも検索する。

```
grep -r "検索文字列" ディレクトリのパス
```

**-i** ・・・アルファベットの大文字小文字の違いを無視して検索。

```
grep -i "検索文字列" ファイル名
```

**-v** ・・・指定した文字列を除外してgrep

```
grep -v "除外したい文字列" ファイル名
```
PHPをあまり使った事がない人がPDOを使ってデータベースを構築してみた

普段phpを使わないのですが、データベースを使ってのデータ構築を考えてみた。

サーバーでがっつり借りてはないけどlolipopとかで、wordpressとかは入れられるけどーみたいなのに毛が生えた程度のリファレンス

サーバーサイドの人に任せると、印象としては、頼んだ事の数倍面倒な事をやってるのか、結構時間かかる感じだったので自分で実装してみた時のサンプルを用意しました(管理画面とか作ってくれたり、拡張性をもたせてくれてるというのは理解しているが、スピードが大事だったりする)

一応、少し間違った事も書くかもしれないのですが、逆に構築してどうこうするというのが分かりにくいリファレンスしか見当たらなかったので書いてみます

```php:qiita.php

try {
	$pdo = new PDO('mysql:host=**********.jp;dbname=データベース名;charset=utf8','ユーザー名','パスワード',
	array(PDO::ATTR_EMULATE_PREPARES => false));
	$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    	$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch (PDOException $e) {
	exit('データベース接続失敗。'.$e->getMessage());
}

```

が接続まで、ここでsetAttributeでエラー出してねみたいなのを書かないとエラーが出ないので追加をしておきます。optionなどで設定してるのもあったのですが、取り急ぎこの書き方

tryのかっこの中に書くのが前提ですが

テーブルの作り方

```php:qiita.php
$sql = 'CREATE TABLE gamedata (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
time INT(255),
name VARCHAR(4),
userid VARCHAR(40),
data VARCHAR(1000),
registry_datetime DATETIME
) engine=innodb default charset=utf8';
$res = $pdo->query($sql);
```

作ったテーブルに値を追加する方法

```php:qiita.php
$sql = "INSERT INTO gamedata (time, name, userid, data,registry_datetime) VALUES (:time, :name, :userid, :data, now())";
	// 挿入する値は空のまま、SQL実行の準備をする
	$stmt = $pdo->prepare($sql);
	// 挿入する値を配列に格納する
	$params = array(':time' => '12322', ':name' => '名前', ':userid' => 'TESTTEST', ':data' => 'AAAAAAAAAAAAAAAA');
	// 挿入する値が入った変数をexecuteにセットしてSQLを実行
	$stmt->execute($params);
```

登録した値を更新する方法(USERIDを選択した値で、名前と時間を編集)

```php:qiita.php
$sql = 'update gamedata set name =:name,time =:time where userid = :value';
$stmt = $pdo -> prepare($sql);
$stmt->bindValue(':name', 'な', PDO::PARAM_STR);
$stmt->bindValue(':time', 3, PDO::PARAM_INT);
$stmt->bindValue(':value', 'TEST', PDO::PARAM_STR);
$stmt->execute();
```

テーブルの中に登録されてる要素数

```php:qiita.php
$sql = 'select count(*) from gamedata';
$stmt = $pdo->query($sql);
echo '行数：'.$stmt->fetchColumn();
```

テーブルの中から要素を取得する

```php:qiita.php
$smt = $pdo->query('select * from gamedata WHERE time <= 1000 order by time desc limit 1 offset 1');
// 実行結果を配列に返す。
$select_data = $smt->fetchAll();
var_dump($select_data);
```
値の制限、順番　数　offsetで欲しいデータが取得できる。


特定の条件の要素の数を取得する

```php:qiita.php
$sql = 'select count(*) from gamedata where userid = :value';
$stmt = $pdo -> prepare($sql);
$stmt->bindValue(':value', 'TEST12345TEST', PDO::PARAM_STR);
$stmt->execute();
echo $stmt->fetchColumn();
```

存在条件も数で取得をしてしまった方がいいかと思っていて、
この形式で登録ができました。

というか、これだけあれば組み合わせて目的のが自分で作れそう。追加の時にURLエンコードとかだけちゃんとやっとけばセキュリティ的に最低限は大丈夫と思いたい
Dockerのコンテナの中からホストOS上のプロセスと通信する方法

## 問題点
`Docker` で起動したコンテナ内からホストOS（ローカルPC）内のプロセスと通信する際に、
`localhost` と指定しがちだけど `localhost` だとコンテナ内を指してしまい、
意図した通りに通信することができない。

例えば、ホストOS上で 80ポートで `Listen` している `Nginx` が起動していて、
コンテナ内のプログラムから `http://localhost:80` でアクセスしても接続できない。

これは通常のプロセスだけじゃなく、docker で複数のコンテナを起動して、
コンテナ同士で通信する場合も同じように接続できない。

## 解決方法
### その1：ホストOSのIPアドレスを指定する
ホストOSのIPアドレスが `192.168.11.1` だとして、`http://192.168.11.1:80` でアクセスするようにする。

### その2：dockerコマンドの引数で指定する
[Dockerで/etc/hostsファイルが操作出来ない対策](https://qiita.com/jagaximo/items/6b71a03518bbd53d4de6) で紹介されているように
`docker run` コマンドの引数（`--add-host=[]`）でホスト名とIPアドレスの紐付けをコンテナに認識させ、
アクセスするときにそのホスト名を使用する。

```
docker run --add-host=local_dev:192.168.11.1 ・・・
```
で起動したときに、`http://local_dev:80` でアクセスする

### その3：`docker-compose.yml` で指定する
`docker run` の `--add-host=[]` と同じことが `docker-compose.yml` の `extra_hosts` でもできる

``` docker-compose.yml
  extra_hosts:
   - "local_dev:192.168.11.1"
```

### その4：`docker-compose.yml` で指定 + 環境変数を使う
DHCPなどでIPアドレスが変わる可能性がある場合、変わるたびに `docker-compose.yml` を変更する必要があるので
自IPアドレスを環境変数に入れるとその手間が省ける。

以下のコマンドを `.bashrc` か `.bash_profile` に記述し、

```bash
export LOCAL_HOST_IP=`ifconfig en0 | grep inet | grep -v inet6 | sed -E "s/inet ([0-9]{1,3}.[0-9]{1,3}.[0-9].{1,3}.[0-9]{1,3}) .*$/\1/" | tr -d "\t"`
```

`docker-compose.yml` を以下のように変更する。


``` docker-compose.yml
  extra_hosts:
   - "local_dev:$LOCAL_HOST_IP"
```

ただし、このコマンドはMacでしか確認してしてなくて、他のOSではどのようにやれば良いかは確認していない。

### その5：`host.docker.internal` を使う (2019/09/16追記、2022/05/12編集)
Docker Desktop for Mac や Docker Desktop for  Windows、Docker Desktop for Linux (2022/05/10 release ) でしか使えませんが、ゲストOS内からDNS名に `host.docker.internal` を指定するとホストOSにアクセスできる。

* [Networking features in Docker Desktop for Mac](https://docs.docker.com/desktop/mac/networking/#use-cases-and-workarounds)
* [Networking features in Docker Desktop for Windows](https://docs.docker.com/desktop/windows/networking/#use-cases-and-workarounds)
* [Networking features in Docker Desktop for Linux](https://docs.docker.com/desktop/linux/networking/#use-cases-and-workarounds)

### その6：`gateway.docker.internal` を使う（2022/02/13追記）

「その5」で紹介した `host.docker.internal` は開発用途らしく、こっちの方が良さそう。
と、Dockerの公式に載っていた。
使っているDockerのバージョンにもよるかも。

http://docs.docker.jp/v19.03/docker-for-mac/networking.html#mac-i-want-to-connect-from-a-container-to-a-service-on-the-host

http://docs.docker.jp/v19.03/docker-for-windows/networking.html#i-want-to-connect-from-a-container-to-a-service-on-the-host

## まとめ
個人的には「その6 ~~その5~~ ~~その4~~」がよいかなと思うけど、
使う環境によって、できること・できないことあるので、
その時々でベストなものを選択してもらえたらよいかなと思う。
WSL(旧Bash on Ubuntu)上のVimからその時の作業ディレクトリでエクスプローラーを開く

Windows Subsystem for Linuxは非常に便利ですよね。
Windowsで手軽にLinux環境を使えるので重宝しています。

特にVim(neovim)の挙動がほぼ完璧なところが個人的な一番の推しポイントです。
WSL上のvimで作業しているときにしばしば起きるのが、vimの現在の作業ディレクトリをエクスプローラーで開きたいということです。

それを実現する設定がこちら

```vim
noremap e :!explorer.exe `pwd \| sed -e "s@\/mnt\/c\/@C:\\\\\\@" \| sed -e "s@\/@\\\\\\@g"`
```

これを.vimrcに書くとSpase+eでその時の作業ディレクトリでエクスプローラーが立ち上がります。
vimの文字列とsedのエスケープが合わさってすごい量のバックスラッシュになっていますね…

### おまけ
作業ディレクトリでコマンドプロンプトを開く

```vim
noremap c :!cmd.exe /c start cmd.exe
```
メモ：Chrome でカメラを制御する

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
<video id="video1" autoplay></video>
<script>
navigator.mediaDevices.getUserMedia({ video: true }).then(function (stream) {
    let video1 = document.getElementById('video1');
    video1.src = window.URL.createObjectURL(stream);
    video1.onloadedmetadata = function(e) {
        // 特別な処理をここで
        console.log(e);
    };
}).catch(function(e) { console.log(e.name); });
</script>
</body>
</html>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/29899/234c4619-6dbf-e37d-83c0-6c8ae1845803.png)
で、許可すればカメラの画像が画面に表示される。

実験したら、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/29899/aab1cb59-3c70-337b-e242-88154e8ee956.png)
で、セキュリティレベルを元に戻しておく。
ちょっとずつ読むドメイン駆動設計 第四部 戦略的設計 第十七章 戦略をまとめ上げる

いよいよ最終章。

# 戦略をまとめ上げる

14章・・・モデルの整合性を維持する（コンテキストマップ/境界づけられたコンテキスト)
15章・・・蒸留(コアドメイン)
16章・・・大規模な構造(進化する秩序)

これらは、組み合わせて作用させることができる。

書籍では、実際の図が見れるのでとても参考になる。

境界づけられたコンテキスト+責務のレイヤ、責務のレイヤ+コアドメイン・汎用サブドメインなど、この図が書ければ確かに大規模なアプリケーションも整理できる。

## どうするのか
1. コンテキストマップを書く
2. ユビキタス言語に注意を払う
3. コアドメインを識別する。ドメインビジョン文書を書く

完璧な答えを求めない。継続的に改良して、新たに学んだことを反映すること。

## 誰がするのか
自己規律型のチームがそれを行う。開発チームが行うこと。
開発チームより権力がある人が書いてもうまくいかない。

## 6つの注意点
1. 意思決定はチーム全体に伝える
2. 意思決定プロセスはフィードバックを吸収する
3. 計画は進化を許容する
4. アーキテクチャチームに最も優秀な人物を持ってはいけない
5. 戦略的設計にはミニマリズムと謙虚さが必要
6. オブジェクトはスペシャリスト、開発者はジェネラリスト

なかなか、４がわかりづらいかもしれません。
アーキチームに優秀な人物を当てて、技術的に最も未熟な開発者だけを実際のアプリケーション構築に残してはいけないということ。アプリケーションの構築には設計スキルが必要だからですね。
ここまで、何度も言われてきたことです。
JSON.stringifyの追加引数とソート

[昨日行き詰まっていた](https://qiita.com/jkr_2255/items/e0095c981989f2425f95)ところでどうしようか考えて、結局は[jkr2255/sorted-json-stringify](https://github.com/jkr2255/sorted-json-stringify)なんてものを作ってしまいました。

# オブジェクトの管理に依存せず並べ替える

突然ですが、`JSON.stringify({'30': 'a', '5': 'b'})`はどうなると思いますか？多くのブラウザでは、`'{"5":"b","30":"a"}'`という結果となります。実際、他の値を入れてみた感触でも、数値キーに関しては別枠でハンドリングしているような、妙な挙動を示しました。

実際にこのようなブラックボックスに遭遇してしまった以上、デフォルトの`JSON.stringify`では、順番がどうなるかなんてわかりません。とはいえ、`JSON.stringify`全部を再実装するのも面倒だし、出来上がったJSONのパースも色々考えると複雑そうだし…みたいなことを考えていました。

# `JSON.stringify`の仕様を見ていて

そんな中で[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)を見ていると、`JSON.stringify`には3つの引数があると書いてありました。

* `replacer`…ルールに従ってオブジェクトを置き換える
* `space`…見栄えをよくするために、JSONにスペースを挿入する

つまり、`space`でインデントをかけた上で、そのインデントを数える、という手法を取れば、改めて大掛かりにパースしなくても**JSONの入れ子構造を抽出できる**ということがわかりました。

# 実際に作ってみた

ということで、

0. `space = 1`で、デフォルトの`JSON.stringify`を使って、改行＆インデントありのJSONを生成する
1. 行ごとに区切って、インデントのスペースの数を数えておく
2. インデント位置で構造を把握しつつ、JSONを並べ替えていく
3. 最後にインデントなどを調整して、最終型のJSONを作る

このような流れで実装することができました。なお、ハマった箇所としては、`space=0`のときは`"foo":"bar"`のようにキーと値が密着するのに対して、`space`が入る場合には`"foo": "bar"`とスペースが1つ入る、となっていて、そこの差で一度コケました。

なお、今回これを作るのにあたって、Mocha、Chai、Rollupと言ったライブラリをはじめて使ってみました。
(Python) Chainerで、XOR関数作ってみる

(Python)

Chainer使ってみた。

ニューラルネットで、XOR関数を再現。
(入力層２、隠れ層３、出力層１）


```python:xor_test.py
# coding: UTF-8
import numpy as np

from chainer import Variable
from chainer import optimizers
from chainer import Chain
import chainer.functions as F
import chainer.links as L

class MyChain(Chain):
    def __init__(self):
        super(MyChain, self).__init__(
            l1 = L.Linear(2,3),
            l2 = L.Linear(3,1),
        )
    def __call__(self, x, y):
        return F.mean_squared_error(self.fwd(x),y)

    def fwd(self,x):
        h1 = F.sigmoid(self.l1(x))
        h2 = self.l2(h1)
        return h2

model = MyChain()

optimizer = optimizers.Adam()
optimizer.setup(model)

loss_val = 100
ep = 0
nep = 10000

while loss_val > 1e-5:

    x = Variable(np.array([[0, 0], [1, 1], [0, 1], [1, 0]],dtype=np.float32))
    y = Variable(np.array([[0],    [0],    [1],    [1]   ],dtype=np.float32))

    model.cleargrads()
    loss = model(x,y)
    loss.backward()
    optimizer.update()

    if ep % 1000 == 0:
        loss_val = loss.data
        print 'Now learning... ->   ', "%.5f" % loss.data

    if ep >= nep:
        break

    ep += 1


#ここから下は、学習後に、テスト
print '\n'

xt = Variable(np.array([[1, 0]],dtype=np.float32))
yl = model.fwd(xt)
print 'test:1 ', xt[0] ,  ' --> ' , "%.3f" % yl.data[0]

xt = Variable(np.array([[0, 0]],dtype=np.float32))
yl = model.fwd(xt)
print 'test:2 ', xt[0] ,  ' --> ' , "%.3f" % yl.data[0]

xt = Variable(np.array([[1, 1]],dtype=np.float32))
yl = model.fwd(xt)
print 'test:3 ', xt[0] ,  ' --> ' , "%.3f" % yl.data[0]

xt = Variable(np.array([[0, 1]],dtype=np.float32))
yl = model.fwd(xt)
print 'test:4 ', xt[0] ,  ' --> ' , "%.3f" % yl.data[0]
```

実行結果は以下。


```text
Now learning... ->    0.89796
Now learning... ->    0.24670
Now learning... ->    0.22884
Now learning... ->    0.15288
Now learning... ->    0.02969
Now learning... ->    0.00052
Now learning... ->    0.00000


test:1  variable([ 1.  0.])  -->  1.000
test:2  variable([ 0.  0.])  -->  0.000
test:3  variable([ 1.  1.])  -->  0.001
test:4  variable([ 0.  1.])  -->  0.999

Process finished with exit code 0
```
AnacondaでPILのインポートに失敗する

私の環境ではlibtiffをインストールすることにより解決しました。

# 環境

Windows10
Anaconda3 64bit
Python 3.6.3 :: Anaconda custom (64-bit)
Pillow 5.0.0

# 状況
Anacondaをインストールして画像を操作するPythonスクリプトを実行したところ下記のエラーとなりました。PIL（Pillow）の内部で利用しているDLLのロードに失敗しているようです。

```text
Traceback (most recent call last):
  File "image_to_db.py", line 3, in <module>
    from PIL import Image
  File "C:\Users\xxxx\Anaconda3\lib\site-packages\PIL\Image.py", line 58, in <module>
    from . import _imaging as core
ImportError: DLL load failed: 指定されたモジュールが見つかりません。
```

当該パッケージのディレクトリを確認したところ`_imaging.pyd`自体は存在しているようです。

```text
2018/01/05  05:39           556,032 _imaging.cp36-win_amd64.pyd
```

[先人の知恵](https://qiita.com/marshi/items/a0f80c5aa3c37b0025d6)に倣ってDependency Walkerで依存関係を確認したところ、TIFF.DLLがうまく読めない状態になっているようでした。

![dep.PNG](https://qiita-image-store.s3.amazonaws.com/0/38326/d94bf8f9-ea77-11ae-6a46-66e0600adf83.png)

`libtiff`パッケージをインストールすることによりエラー出ないようになりました。（パッケージの依存関係の解決がうまくいってなかったのかな？）

```bat
conda install libtiff
```
intra-mart実践入門の作成記録 #009 アプリケーション編目次

# 経験したハードルを一通り集めてみる
　[前回](https://qiita.com/hiroaki-kushida/items/0dfc611c89049e838f78)はプロジェクトマネジメント編の目次でしたが、今回はアプリケーション編の目次を作成しました。本書の中心となる章です。

　[intra-mart](https://www.intra-mart.jp/)を使い始めた技術者が行き当たる問題は、「標準機能は一見便利そうに見えるのにあと一歩のところが届かないためにスクラッチ開発したくなる」ではないでしょうか[^1]。私もプロジェクトの途中で何度も挫折(要件を満たせずにバーター交渉をしなければならない)しかけました。その中で出てきたアイディア達なので、これから開発を始める人や今まさに開発している人たちにもお役に立つのではないかと思います。

　書きたいと思っている内容は次の節です。

# アプリケーション編目次
<dl>
  <dt>物足りなく感じる標準機能に一工夫をすればまだまだ戦える</dt>
  <dd>ストアドファンクションの活用で輝くIM-LogicDesigner</dd>
  <dd>共通マスタの不足を補うIM-FormaDesigner</dd>
  <dd>複雑すぎる社内ルールを動的展開で表現できるIM-BIS</dd>
  <dd>参照範囲を絞込めば意外と便利なViewCreator</dd>
  <dt>例で見るintra-mart実装パターン</dt>
  <dd>テーブルを持つまでもない設定情報を保持するストアドファンクション</dd>
  <dd>コード体系が決まっているなら入力サポートを行うテキストボックス</dd>
  <dd>コードでの一本引きも検索からの選択も使えるテキストボックス</dd>
  <dd>「その他」の時だけ入力できるテキストボックス</dd>
  <dd>ラジオボタンやセレクトボックスの外部連携に注意</dd>
  <dd>確認ダイアログがユーザーに優しい「戻るボタン」</dd>
  <dd>活性や表示の切替を統括するイベントボタン</dd>
  <dd>外部連携でNULLオブジェクトに対処するためのダミー値</dd>
  <dd>行選択による子画面への遷移</dd>
  <dd>明細テーブルやグリッドを使う場合は表示順と行番号の不一致に注意</dd>
  <dd>締め日を持たせて防止する業績改竄</dd>
  <dd>業務間連携や複雑な処理を行う案件完了処理</dd>
  <dt>システム連携</dt>
  <dd>直接DB連携が許容されるならFDWが最短</dd>
  <dd>intra-mart側処理によるファイル連携</dd>
  <dd>PostgreSQL側処理によるファイル連携</dd>
  <dt>バリデーション</dt>
  <dd>関数フィールドを使った組合せバリデーション</dd>
  <dd>隠しフィールドを使った業務的バリデーション</dd>
  <dd>ノード後処理を使った排他的バリデーション</dd>
  <dt>テンプレート</dt>
  <dd>テンプレート機能を使って高めるUI変更の安全性</dd>
  <dd>共通ヘッダー/フッターはテンプレートで管理</dd>
  <dd>画面の複雑性が高いならノード毎に画面を作った方が安全</dd>
  <dd>紙がなくせない職場なら参照画面と合わせて印刷画面も作成</dd>
  <dt>画面遷移</dt>
  <dd>申請処理後の遷移先を指定</dd>
  <dd>遷移時に処理が完了していないならリダイレクト画面でポーリング</dd>
  <dt>一覧画面</dt>
  <dd>同一部内の隣の課の作った申請も表示できる一覧画面</dd>
  <dd>一覧画面からフロー画面を参照</dd>
  <dd>一覧画面から履歴画面を参照</dd>
  <dt>複雑なワークフロー</dt>
  <dd>案件番号から案件情報を取得</dd>
  <dd>案件の完了判定</dd>
  <dd>動的承認ノードよりも横配置ノードよりも縦配置ノード</dd>
  <dd>ランクで判定する承認対象者</dd>
  <dd>申請組織の階層構造に基づく再起処理</dd>
  <dd>特定条件を満たすときのみ発動する例外承認ルート</dd>
  <dd>強制差戻し</dd>
  <dt>親子関係を持つワークフロー</dt>
  <dd>(1)子から親の参照</dd>
  <dd>(2)親から子の起票</dd>
  <dd>(3)子から親を選択して起票</dd>
  <dd>(4)同じ親を持つ子の重複防止</dd>
  <dd>(5)兄弟の順序や累計の利用</dd>
  <dt>修正や削除を行うワークフロー</dt>
  <dd>(1)完了したワークフローに対する変更の意味</dd>
  <dd>(2)削除前情報を残さない削除</dd>
  <dd>(3)削除前情報を残す削除</dd>
  <dd>(4)変更前情報を残さない修正</dd>
  <dd>(5)変更前情報を残す修正</dd>
  <dt>データローディング</dt>
  <dd>(1)リプレースプロジェクトの鬼門</dd>
  <dd>(2)IM-BISのバージョニング機能をフル活用</dd>
  <dd>(3)DBスキーマを確定させるだけの画面</dd>
  <dd>(4)IM-LogicDesignerのルーティング定義</dd>
  <dd>(5)対象データのクレンジング</dd>
  <dd>(6)投入プログラムサンプル(C#)</dd>
  <dd>(7)運用開始までにAPIを閉じる</dd>
</dl>

[^1]: 「そもそも機能が多過ぎてどう使えばいいのか分からない」の段階を乗り越えた人の話です。
【CentOS 7.x】Meltdown / Spectre 対応記録


## 対応した環境

- Conoha の VPS で 構築された CentOS 7.x のサーバ
- Azure の VM で 構築された CentOS 7.x のサーバ

## 対応方法

基本手順は次のサイトを参考に。
チェック方法として `uname -r` 以外に診断ツール（下記に記載）を実行する。

> サーバーにログインして以下の手順を実施
> 
> 1. 現在のkernelバージョンをチェック　コマンド：`uname -r`
> 1. バージョンがOSバージョンごとに異なるのでチェック
>     - CentOS6系なら「kernel-2.6.32-696.18.7.el6.x86_64」より前のバージョンであることを確認
>     - CentOS7系なら「kernel-3.10.0-693.11.6.el7.x86_64」より前のバージョンであることを確認
> 1. アップデートコマンドを実施：`yum update kernel`
> 1. OSを再起動して、再度確認コマンドを実施：`uname -r`
>     - バージョンがそれぞれ以下であることを確認
>         - CentOS6系なら「kernel-2.6.32-696.18.7.el6.x86_64」
>         - CentOS7系なら「kernel-3.10.0-693.11.6.el7.x86_64」


https://www.rbkyan.com/blog/2018/01/07/meltdownとspectreにどう対応したらよいのか？/

### 上記対応を行っても Spectre Variant 2 が VULNERABLE で 残る場合

診断スクリプトは、以下のコマンドを実行しろと言っているが、`-bash: echo: write error: No such device` で失敗する。その場合は BIOS Update が必要らしいので、VM 基盤の対応待ち。

`echo 2 > /sys/kernel/debug/x86/ibrs_enabled`
`echo 1 > /sys/kernel/debug/x86/ibpb_enabled`


https://serverfault.com/questions/890904/i-updated-my-centos-7-system-why-is-meltdown-spectre-only-partially-mitigated

## 診断方法

> ### 診断スクリプトをダウンロードして実行

> ```
> wget https://raw.githubusercontent.com/speed47/spectre-meltdown-checker/master/spectre-meltdown-checker.sh
> sudo sh ./spectre-meltdown-checker.sh
> ```

https://news.mynavi.jp/article/20180109-linux_vulnerability/
スクレイピングした情報を教えてくれるAmazon echoのスキルをAlexa Skills Kit (ASK)を使ってJavaでつくってみた

# はじめに
Amazon Echoを買ったので年末年始の時間を使って試しにスキルを作ってみました。
Javaに慣れているので手っ取り早く試すためにJavaで書きました。

基本を学ぶためにまずはamazonのドキュメントを読みつつすでに投稿されている方の情報を見ながら作ってみました。
https://developer.amazon.com/ja/alexa-skills-kit

ともあれsampleのソースを見た方がこんな感じかというのがわかるのでドキュメントとソースを見ながら。
https://github.com/amzn/alexa-skills-kit-java

作ったものはgithubにあげてあります。
https://github.com/ewai/amazon-echo-ask-sample

#　どういうものを作ったか

オイシックスというサイトの情報を教えてくれるスキル
（会員にしかわからないかもしれないけど・・）教えてくれたら便利そうな情報をサイトからスクレイピングして読み上げてくれます。

①Alexa! "オイシックス"開いて！
②機能を呼び出す声かけ

というシンプルな流れです。

| 機能を呼び出す声かけ | 反応するキーワード | 処理内容 |
|---|---|---|
|今週の特集教えて！| 特集 | メニューから今週の特集ページ一覧をスクレイピングして読み上げてくれる。 |
|今週のセール商品教えて！| セール、割引 | セールページをスクレイピングして３０％割引以上の商品を読み上げてくれる。 |
|今週のVIP商品教えて！| VIP | VIPページの商品を読み上げてくれる。 |

## aws Lambda作成

1. トリガー追加（Alexa skills kit)
1. 関数コードにてjarのアップ、ハンドラ設定など
1. 環境変数にて"ALEXA_APP_ID"を追加。Alexa skillsのアプリケーションIDをvalueに設定する。
1. 実行ロールの設定
1. テストしてみる。

1回目の呼び出しは10秒以上かかってそうです。2回目からはすぐに反応します。
時間が経つとまた起動が遅くなります。
よほどよく使われるスキルなら良いかもしれませんがそうでもないならないので何か対策が必要そうです。
定期的に呼び出すとか。

デザインが変わってidやclassが変わると改修が必要です。。

## Alexa skills作成

1. スキル情報設定（アプリケーションIDが発番されているのでメモる）
1. 対話モデル作成
1. 設定（この時点でlambdaのurlが必要）
1. テストしてみる。（ここで表示されるjsonパラメータをLambda側のテストに使うとよい）
1. 公開情報設定
1. プライバシーとコンプライアンス（保存だけする。とりあえず申請しない。）
1. 上記を一通り設定すると”Skills Beta Testing”がアクティブになる。自分のAmazonEchoアカウントをテスターとして追加する。
　 そうすると使える状態になっているので試してみる。

もう少し汎用的につくってWEBメンテナンス画面を作ればどのお店でも使えそうですが
必要性がわからないのと労力を注げず一旦やめときます。