OmniAICreator/Qiita-1.07M huggingface dataset:
Express.jsでタイムアウトレスポンスを返却する

時間がかかってしまう可能性がある処理に対して、一定時間内に結果が返却できないときにはタイムアウトをエラーレスポンスで返す方法を調べました。結論としては、[connect-timeout](https://github.com/expressjs/timeout)を利用すれば実現できますが、いくつか注意点があります。

## connect-timeout

[connect-timeout](https://github.com/expressjs/timeout)は[Express.js](https://github.com/expressjs)でリクエストに対して一定時間でタイムアウトイベントを発生させるためのミドルウェアです。公式のドキュメントがあまり充実していないためテストコードを作り動作検証をしてみました。

## わかったこと

* connect-timeoutを最初のミドルウェアに設定することで、指定時間経過時に例外を発生させ、エラー処理ミドルウェアに処理を渡すことができる。
* ルートの処理でレスポンスを送信する場合には、既にエラー処理ミドルウェアからレスポンスが送信されている可能性があるため、`req.timedout`（timeoutミドルウェアがタイムアウト発生時に設定する）を確認して、`false`の場合にのみ行う。
* エラー処理でレスポンスを返却するときにはルートの処理でレスポンスが送信されている可能性があるため、`res.headersSent`が`false`の場合のみ行う。
* タイムアウトが発生しエラー処理ミドルウェアが実行されても、実行中のミドルウェアもしくはルートの処理は停止せずに続行する。
* ただし、タイムアウト発生後に次のミドルウェアが実行されることはないので、公式ドキュメントに記載されているhaltOnTimeoutミドルウェアの設定は不要である。

## 動作検証コード

```javascript
const co = require('co')
const express = require('express')
const sleep = require('sleep-promise')
const timeout = require('connect-timeout')

const app = express()
const timeout_ms = process.argv[2] || 1500
app.use(timeout(timeout_ms))

// ミドルウェア1
app.use(function(req, res, next) {
	co(function*(){
		console.log('middleware 1: begin')
		yield sleep(1000)
		console.log('middleware 1: end')
		next()
	})
})
app.use(haltOnTimedout)

// ミドルウェア2
app.use(function(req, res, next) {
	console.log('middleware 2: begin')
	next()
})
app.use(haltOnTimedout)

// GETルート
app.get('/', function(req, res, next) {
	co(function*(){
		console.log('app.get: begin')
		yield sleep(1000)
		if (!req.timedout) {
			console.log('app.get: send response')
			res.send('app.get')
		}
		console.log('app.get: end')
	})
})

// エラー処理ミドルウェア
app.use(function (err, req, res, next) {
	console.log('error filter: begin')
	if(req.timedout && !res.headersSent) {
		console.log('error filter: send response')
		res.status(500).send('request timeout')
	}
})

// タイムアウト発生時に以降のミドルウェアを停止するためのミドルウェア
// 公式のガイドラインで必要とされている
function haltOnTimedout (req, res, next) {
	console.log('haltOnTimeout: begin')
	if (!req.timedout) {
		console.log('haltOnTimeout: call next()')
		next()
	}
}

app.listen(3000)
```

### 実行結果

```shell
$ node app.js 500
middleware 1: begin
error filter: begin
error filter: send response
middleware 1: end
```

```shell
$ node app.js 1500
middleware 1: begin
middleware 1: end
haltOnTimeout: begin
haltOnTimeout: call next()
middleware 2: begin
haltOnTimeout: begin
haltOnTimeout: call next()
app.get: begin
error filter: begin
error filter: send response
app.get: end
```

### 利用したバージョン

- Node.js 6.11.0
- express 4.16.2
- connect-timeout 1.9.0
Windows 10をリフレッシュしてみた

## PCもリフレッシュしないと動きが悪くなる

Win95の時代から、Windowsは長く使っていると、エラーが出る、ハングアップする、PCが落ちる、重くなる、アップデートが終わらない、USBが認識しない、そもそも起動しない、等々の障害が発生するようになってきます。対処が見つかって直れば良いのですが、何をやっても直らないということも多々あると思います。その時の最終手段はOSの入れ直しです。[^1]

OSの入れ直し方法と言えば、PCについてきたメディア[^2]を使って工場出荷時に戻すという物でした。しかし、Windows 8からメディア不要でリセットする方法が用意されています。それがリフレッシュの機能です。

ということで、色々と失敗してOSが汚くなった私のPCをリフレッシュしてみました。なお、Windows 8.1とWindows 10では表記や動作が異なりますので、異なるバージョンをお使いの方は参考程度で見てください。

## リフレッシュの実施

今回リフレッシュしたPCは下記になります。ベンダーや機種、バージョンによって異なりますので、全ての人が同じになるとは限らない事にご注意ください。

機種: Dell XPS 13 2-in-1 9365
OS: Windows 10 1709 Fall Creators Update

### 準備

まずは、バックアップを取っておきます。Windows 10の通常のバックアップを使用して、個人用ファイル、つまり、プロファイルがある場所だけが対象にします。下記から設定できます。

設定 -> 更新とセキュリティ -> バックアップ

これだけでも十分の場合がありますが、あわせて「[バックアップと復元] に移動 (Windows 7)」をクリックし、Windows 7互換のイメージバックアップも取得しておきます。

そもそも起動しない状態であったらバックアップ取得も何もありません。バックアップは常に取る、または、クラウドのドライブを使用するなどを普段からしておくべきでしょう。

### リフレッシュ方法(個人用ファイルは残す)

リフレッシュでは個人用ファイルを残す場合と消す場合の選択ができます。今回は個人用ファイルを残す(消さない)を選択しました。

周辺機器は外し、電源のみ接続した状態にしておきます。

1. 「設定」を開く。
2. 「更新とセキュリティ」を開く。
3. 「回復」を選ぶ。
4. 「この PC を初期状態に戻す」の「開始する」を押下する。
5. ウィザードで「個人用ファイルを保持する」を選ぶ。後はウィザードを進めていく。

自動的に再起動してリフレッシュが完了して再びログインできるようになるまで約30分ほどでした。意外と早かったですが、CPUやメモリ容量、ストレージの種類によって大きく変わると思いますので、参考程度にしてください。

### その後の作業

リフレッシュによって色々削除されているのでそれらを入れていきます。

* PCのドライバーのアップデート
* OSのアップデート
* 周辺機器のドライバーのインストール
* ソフトウェアのインストール

プリインストールされたPCのドライバーやソフトウェアはインストールされた状態でした。そのため、それらのアップデートはメーカーのツールを使ってアップデートしていくだけです。NIC等も認識されていましたので、特にネットに繋がらなくてアップデートできないという事態は起きませんでした。

OSは1709があたった直後の状態のようです。リフレッシュした時点で再度1709を適用し(実際には確認だけされる模様)、1709用の累積パッチが落ちてきました。

周辺機器のドライバーやソフトウェアは軒並み削除されていますので、一つ一つインストールする必要があります。あらかじめダウンロードしていた方が良いかもしれません。

それなりに使えるレベルになるまで、大まかに3時間ぐらいかかりました。

## リフレッシュの動作について

個人のプロファイル内にあるファイル以外は全て消えるのかと思ったのですが、そうでも無かったです。設定も引き継ぐ物が多く見られました。保持される物と削除される物、そして新たにインストールされる物をそれぞれ羅列していきたいと

保持された物

* ホスト名等の基本設定
* ネットワーク設定(無線LANはそのまま使用できた)
* ユーザー
    * Microsoft アカウントとの紐付けもそのまま
    * ただし、レジストリでの設定は消されている。
* スタートメニュー
    * リンク先が削除されている場合はリンクも削除されるが、そうでない場合はそのままになる。例えば、コマンドプロンプトのショートカットになっている場合は残る。
    * フォルダ
* "Windows"、"Program Files"、"Program Files (x86)"以外のCドライブ直下のフォルダ
    * 上記以外にインストールするプログラムについては、ファイルがそのまま残る。ただし、アプリと機能には現れない。

削除された物

* アプリと機能にあるほぼ全てのプログラム(リフレッシュのウィザードでリストが出ます)
    * "C:\Program Files"や"C:\Program Files (x86)"にあるファイル
* "C:\ProgramData"の中身(削除されない物もある)
    * Chocolatey
* OSにインストールした追加の機能
    * Windows の機能の有効化または無効化で追加した機能
    * フォント(初期状態にリセット)
* C:\Windows配下
     * hostsファイルなど
* システムのレジストリ上の設定(削除されない設定もある)
* ユーザーのレジストリ上の設定(削除されない設定もある)

インストールされる物

* OS
* プリインストールされているソフトウェアやドライバー(ただし、最新ではない)

リフレッシュ後はFall Creators Update適用直後に近い動作です。購入時の初回起動ウィザードは表示されませんが、準備中の表示が出ます。

削除されるアプリケーションはアンインストール処理を実施しているわけではなく、ファイルやレジストリを強制的に削除する(というより引き継がない)ようです。そのため、インストールする場所として想定されていないフォルダにインストールされている場合は、レジストリなどの情報だけ消されて、ファイルはそのままとなるようです。

## たまにはリフレッシュも良いかもしれない

工場出荷時に戻すという完全なOS再構築よりはかなり楽でした。汚くなったOSも綺麗になったような気がします。

古いバージョンとは言え、OSのドライバー関係が最初から入っている事が大きかったと思います。Windows 10メディアから再インストールしたら、ドライバーが何もない、NICすら動かない、なのでネットから落とせない、どうすればいいのか？という事が昔あったので。

[^1]: Win95時代、私は半年に一度の頻度でOS入れ直しをしていました。

[^2]: 最近はオプション扱いになっており、頼まないと付いてきません。また、CDやDVDからUSBメモリに置き換わっています。
【CSS】2行目から1文字下げる。text-indentの使い方

箇条書きや注意書きの文章をマークアップする時に、文章の先頭に「・」や「※」、アイコン等の記号を配置することがよくあります。
そんな時に、2行目以降が記号の下に回り込ませずに綺麗に文字を揃えるTipsです。

## HTML
```html
<p class="indent">text-indetプロパティを使って文字を揃えます。<br>text-indetプロパティを使って文字を揃えます。</p>
<p>text-indetプロパティを使って文字を揃えません。<br>text-indetプロパティを使って文字を揃えません。</p>
```

## CSS
```css
.indent {
  padding-left: 1em;
  text-indent: -1em;
}
```

## 画面表示
![スクリーンショット 2018-02-12 9.41.46.png](https://qiita-image-store.s3.amazonaws.com/0/192435/2dad23c6-b2fd-24a4-6dca-4579112b0e90.png)

padding-leftで左側に1文字分の余白を作成(1emは1文字の大きさ)します。
text-indentで-1emすることで1行目の余白のスペース移動、つまり左側に1文字分移動させます。

文章の先頭にアイコンを使用した時にも便利です！
Windows作業自動化方法のまとめ

# 概要

- バッチファイル
- PowerShell
- Windows Script Host (JScript, )
- VBA

# バッチファイル
## 概要
>
バッチファイル（Batch File）とは、MS-DOS、OS/2、Windowsでのコマンドプロンプト（シェル）に行わせたい命令列をテキストファイルに記述したもの。バッチファイルを実行すると、シェルプログラム（一般に COMMAND.COMやcmd.exe）がそのファイルを読み、その中のコマンドを（通常）一行ずつ実行する。バッチファイルはUNIX系オペレーティングシステムのシェルスクリプトに相当する。
by [Wikipedia - バッチファイル](https://ja.wikipedia.org/wiki/%E3%83%90%E3%83%83%E3%83%81%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB)

ということで、いにしえの昔に作ったシステムを後方互換のために使えるようにしているだけらしい。

## リンク

# PowerShell
## 概要

>
Windows PowerShell はマイクロソフトが開発した拡張可能なコマンドラインインターフェース (CLI) シェルおよびスクリプト言語である。オブジェクト指向に基づいて設計されており、.NET Frameworkを基盤としている。かつてはMicrosoft Shell（MSH、コードネーム Monad）と呼ばれていた。Windows 7以降のオペレーティングシステム (OS) には標準で搭載されている。
by [Wikipedia - Windows PowerShell](https://ja.wikipedia.org/wiki/Windows_PowerShell)

## リンク

- [Qiita - PowerShell 使い方メモ](http://qiita.com/opengl-8080/items/bb0f5e4f1c7ce045cc57)

# Windows Script Host

## 概要  

>
Windows Script Host（ウインドウズ・スクリプト・ホスト）とは、Microsoft Windowsにおいてテキストファイルに記述したスクリプトを実行するスクリプト実行環境である。WSHと略される。かつてはWindows Scripting Hostと称した。
Windows 98から搭載された。Unixにおけるシェルスクリプトや、MS-DOSにおけるバッチファイルと似た位置づけの技術である。
by [Wikipedia - Windows Script Host](https://ja.wikipedia.org/wiki/Windows_Script_Host)   
  
言語としては、VBScriptとJScriptを使用できる。

## リンク
- [MSDN - Windows Script Host](https://msdn.microsoft.com/ja-jp/library/cc364455.aspx)
KotlinでSharedPreference Classを実装


こんにちは。m_saekiです。

kotlinを初めて4日目です。
Javaで実装していた時のSharedPreferenceUtil Classをkotlinに変換して今後コピペでいいように投稿しておきます。

こう修正した方がいいよは是非受け付けますのでよろしくお願いします。

## BaseSharedPreference Class

BaseとなるClassになります。
SharedPreferencesをシングルトンインスタンスで呼び出し、
それぞれの型で保存するか、読み込みかのみを実装しております。

``` kotlin:BaseSharedPreference.kt
open class BaseSharedPreference {

    companion object {
    
        private val PREFERENCE_FILE_NAME = "app-name-pref"

        fun instance(context: Context): SharedPreferences {
            return context.getSharedPreferences(PREFERENCE_FILE_NAME, Context.MODE_PRIVATE)
        }

        fun putString(context: Context, key: String, value: String) {
            val ed = instance(context).edit()
            ed.putString(key, value)
            ed.apply()
        }

        fun getString(context: Context, key: String, defValue: String): String {
            return instance(context).getString(key, defValue)
        }

        fun putInteger(context: Context, key: String, value: Int) {
            val ed = instance(context).edit()
            ed.putInt(key, value)
            ed.apply()
        }

        fun getInteger(context: Context, key: String, defValue: Int): Int {
            return instance(context).getInt(key, defValue)
        }

        fun putBoolean(context: Context, key: String, value: Boolean) {
            val ed = instance(context).edit()
            ed.putBoolean(key, value)
            ed.apply()
        }

        fun getBoolean(context: Context, key: String, defValue: Boolean): Boolean {
            return instance(context).getBoolean(key, defValue)
        }

        fun remove(context: Context, key: String) {
            val ed = instance(context).edit()
            ed.remove(key)
            ed.apply()
        }
    }
}

```
## enum Key Class

ここではenumでSharedPreferenceに必要なキーを実装しています。
例でUSER_TOKENとありますが、必要なキーを追加していきます。

```kotlin:Key.kt
enum class Key {
    USER_TOKEN,
}
```

## SharedPreferenceUtil Class

saveUserToken,loadUserTokenで保存、取得の処理をしています。

``` kotlin:SharedPreferenceUtil.kt
class SharedPreferenceUtil: BaseSharedPreference() {

    companion object {

        fun saveUserToken(context: Context, token: String) {
            putString(context, Key. USER_TOKEN.name, token)
        }

        fun loadUserToken(context: Context) {
            getString(context, Key. USER_TOKEN.name, "")
        }
    }

}

```

## SharedPreferenceUtilの使い方

```
// 保存方法
SharedPreferenceUtil. saveUserToken(context, "User Token")
// 取得方法
SharedPreferenceUtil.loadUserToken(context)
```

以上となります。
初めて触る言語は楽しいですね。
Twitterのフォローよかったらよろしくお願いします！
オブジェクト指向の3大要素 まとめ

「オブジェクト指向の三大要素」について再復習の機会があったのでまとめてみた。

## オブジェクト指向の三大要素とは
オブジェクト指向言語がもつ代表的な3つの特徴のことで、「カプセル化、継承、ポリモーフィズム」の3つ。
※ ただ3つの代表的な要素なだけで、これがあるからイコール「オブジェクト指向」だとかじゃないとかそういうものではない。

## カプセル化
オブジェクトの安全性を高めるために、オブジェクトのメンバーを保護すること
※メンバ = オブジェクトのメソッド及び変数
この性質を理解し、影響範囲の小さく疎なプログラミングを心がけることが、大規模で安全なシステム構築に繋がる。

## 継承
あるクラスを引き継いで新しいクラスを定義することできること
この特徴があるおかげで、共通部分をまとめて、再利用することができる。

## ポリモーフィズム(多態性)
オーバライドやオーバロードによって、メソッドを状況によって使い分けることができること
※ オーバライド: 親クラスのメソッドを子クラスで上書きすること
※ オーバロード: 同一クラス内で引数の違いによってメソッドの呼び分けること

## 参考資料:
http://teacher.nagano-nct.ac.jp/fujita/oopElements.php
定義が書いてある

https://qiita.com/koher/items/6878c80014992900add7
実例込みで説明してある

## おまけ: ruby,railsにおいて
- オーバロードはなし(動的型付けのため)
- 抽象クラス、抽象メソッドはなし　例外を投げる擬似抽象メソッドで対応
https://qiita.com/yynozk/items/66bf766166eda2b84a03
- インターフェースもないよ (ダックタイピング = アヒルのようになけば、それはアヒル)
Qiitaに投稿した写真が反転するのを一番簡単に直す方法

# はじめに
スマートフォンで撮影した写真をQiitaに投稿するために、編集中ページにドラッグ&ドロップしたら画像が90°反転されてしまった。
解決方法を検索してみると"EXIF"とか難しい話がでていて（きっと綺麗に完ぺきにやりたいならこの方法なんだと思う）、どうしたものかと悩んでいたけど、誰でも簡単にできる方法があったのでメモ。

# やり方
1. 画像を開いて正しい向きに回転
2. スクリーンキャプチャ
3. ペイントなどのお絵かきツールにペースト
4. 必要部分を切り取り
5. Qiitaの編集中ページにペースト

# 最後に
人間、うまくいかなことがあると視野が狭くなりがちですが、パソコン初心者でも思いつくような簡単な方法がありました。

![1504673119543.jpg](https://qiita-image-store.s3.amazonaws.com/0/221948/92d94225-b5cf-0c50-8d87-9557eb9eac60.jpeg)
我が家愛ネコの遠い目・・・
Vimのカラースキームをランダム、もしくは指定して変更できるプラグインを書いてみました - twc.vim

開いているVim上のカラースキームをランダム、もしくは指定して変更するプラグインを書いてみました。
こんなやつです↓

![shinshin86/twc.vim: demo](https://github.com/shinshin86/twc.vim/blob/master/gif/twc_demo.gif?raw=true)

## 自作プラグインを初自作

先日このようなポストをQiitaに書き、

[Vimコマンドを自作してみる、という今年の目標を達成するためにVim scriptに触り始めてみたら、かなり楽しいー！(コマンドでの引数の受け取り方)](https://qiita.com/shinshin86/items/6e6cbdb77cb59b87d21f)

そして学んだことを実践するため、早速自作プラグインを作ってみた、という感じです。
プラグイン作成の上でのお作法など、「コイツ分かっていないな、、、」と目につく箇所がありましたら、ご指摘やプルリクいただけたら幸いです。

[shinshin86/twc.vim: Today(This) Window Color at my Vim](https://github.com/shinshin86/twc.vim)


## セットアップ手順
READMEにも書きましたが、インストールしてからのセットアップ手順は下記の通りです。

```bash
touch $HOME/.twc_colors.vim
vim $HOME/.twc_colors.vim
```

作成した``$HOME/.twc_colors.vim"``に対して、自身で使用しているカラースキームを各行に記述すれば完了です。
例えばこんな感じで書いていきます。

```vim
iceberg
hybrid
default
blue
darkblue
desert
elflord
evening
morning
murphy
```

あとはVimを立ち上げて``:Twc``、もしくは``:Twc0``とか``:Twc 2``とか指定したいカラースキームを選択すればOKです。

自身の学習目的の側面が強いため、特別便利なプラグインというわけではありませんが、Vimのウィンドウを複数立ち上げてコーティングする際など、窓ごとにカラースキームを変えて使いたかったりするときに、意外と便利で使っています。
archlinux で　lumina-desktop

以下が　freebsd で開発された　lumina です。
openbsd にもとりこまれていて　
linuxは　**BSD特有のコード**対応に最初は苦戦したようですが
今や　archlinuxでも　１．４が利用できます。
とにかく　**軽い** よって　**速い**:grin:
で　
archlinuxのxfce4でもちょっと負担という場合　luminaに変えると快適です。


![Screenshot-2018-02-12-06-25-29.png](https://qiita-image-store.s3.amazonaws.com/0/211097/e74a26e2-20c7-dd9d-e196-8b22bfa1e801.png)

wallpaper は簡単に代えられます。　ネットで探せば9００以上あります。　
https://www.zedge.net/wallpapers/7512/nokia-lumia-930-wallpapers/0-2-14/?cursor=1..377
で例えば
![Screenshot-2018-02-12-15-54-01.png](https://qiita-image-store.s3.amazonaws.com/0/211097/6699586d-b709-de5a-9184-96d647471bbd.png)



lumina の軽さは
![s.png](https://qiita-image-store.s3.amazonaws.com/0/211097/f9995d60-a0ed-00e4-3e1c-658591ac00c9.png)


##　　ctrl+F2 でマルチ画面対応です, lumina-desktop-git.tar.gz で導入してください


設定ファイルを載せておきます。


1)  ./comment-out.bat .xinitrc 

```
あるけど　中身なし
```

２） .xsession

```
存在しない
```

３）.xprofile

```
export XMODIFIERS=@im=fcitx
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
```

４） ./comment-out.bat .bashrc

```
[[ $- != *i* ]] && return
alias ls='ls --color=auto'
PS1='[\u@\h \W]\$ '
```

5) head -20 /etc/sddm.conf

```
[Autologin]
# Whether sddm should automatically log back into sessions when they exit
Relogin=false

# Name of session file for autologin session 
# (if empty try last logged in) この記載のため次となる
Session=

# Username for autologin session
User=FOGE
```

```
systemctl enable sddm 
```

６)fcitx がまだ走ってなかったら　端末で
fcitx-autostart
をしてください

７）キーボードが英語なら
setxkbmap -model jp106 -layout jp
で　なおります


８）leafpad は　枠をはみ出します
　　代わりに　pluma あるいは　kate　を使いましょう
　　これらからも　印刷できます。

９）残念ながら　まだlumina 不十分で
pulseaudio がサーバーとつながりません。
従って　luminaから　音声の入出力のコントロールができません。
でも　xfce4の　音声出力の設定は　　引き継いでくれます。
でも　音声入力は　xfce4の設定を　引き継いでくれません！



ーーーーーーーーーーーーーーーーーーーー
#A) 付録

```
そろばんの連続足し算 3桁区切り

tasizan-renzoku.bat
#!/bin/bash
add=0
while true
do
read x
echo $x | printf "%'d\n" $(cat)
add=$(($add + $x))
echo
echo
echo '----------SUM is'
echo $add  
echo $add | printf "%'d\n" $(cat)
echo
echo
done
```

これにて
$ ./tasizan-renzoku.bat
1000
1,000


----------SUM is
1000
1,000


1000000
1,000,000


----------SUM is
1001000
1,001,000

これで　電卓の足し算いらないか
Androidアプリケーション技術者認定試験ベーシックの試験範囲の知識をまとめた(15)

# アプリケーション管理

## バージョニング

### バージョン管理の方法

バージョン情報はAndroidManifest.xmlで指定する
以下2種類がある。

- android:versionCode

バージョンを機械的に判別するための番号。ユーザーには表示されない。番号は整数で設定し、通常初回は1にする

- android:versionName

アプリケーションのバージョンを表す文字列。ユーザーに表示される。用途は表示だけ。

### 限られたバージョンでのアプリケーション

利用できる最小のAPIバージョンを指定するにはマニフェストファイルの`<uses-sdk>`タグにandroid:minSdkVersionに最小バージョンのAPIレベルを指定する。

#### `<uses-sdk>`タグ

- android:targetSdkVersion 指定したAPIレベルでテスト済みであることを示す
- android:maxSdkVersion 利用できる最大のAPIレベルを指定する。原則的には設定しない。（基本的にAndroidは下位互換があるため）

## プライベートキーの生成

### アプリケーションをインストールするために

インストールするためには必ず署名されたアプリケーションである必要がある。Eclipseで開発中はAndroidSDKでデバッグキーが生成されてADTプラグインにより自動的に署名されるため意識する必要はない。

### アプリケーションを公開するために

Google Playなどに公開するためには、独自にプライベートキーを生成する必要がある。

### プライベートキーを生成するために

プライベートキーを生成するには、JDKに付属のkeytoolを使う。JDKのbinフォルダにkeytool.exeとして格納する。

keytoolのオプション

|オプション|意味|設定値|
|---|---|---|
|-genkey|キーを生成するときに指定|なし|
|-v|詳細な内容を表示する際に指定|なし|
|-keystore|キーストアのファイル名|xxx.keystore|
|-alias|キーの別名|xxx|
|-keyalg|キー生成時の暗号化アルゴリズム|DSAまたはRSA|
|-validity|キーの有効日数|10000|
|-storepass|キーストアのパスワード|-|
|-keypass|キーのパスワード|-|
|-list|キーを確認する際に指定|なし|

コマンドを実行するとキーストアのパスワードが求められる。キーストアとはキーや証明書を格納している保護されたファイルのこと

## Maps API Keyの登録

### 地図を表示するために

地図表示を行うためにはGoogle Maps APIのMapViewを用いることで、アプリケーションに地図を表示できる。
そのためにはGoogle Mapsへ登録する必要がある

#### 地図表示をするプロジェクトを作成する

MapActivityとMapViewは標準のSDKには入っていない。Google APIsに入っているので、インストールする必要がある

#### MD5フィンガープリントの取得

フィンガープリントとは、指紋という意味でMaps API Keyを取得するために必要な情報。プライベートキーからフィンガープリントを確認できる。

#### Maps API Keyの取得

サイトにアクセスして、Maps API Keyを取得する。利用規約に同意し、MD5フィンガープリントを入力する必要がある。（Googleアカウントも必要）

#### MapViewへのMaps API Keyの設定

取得したMaps API KeyはMapViewのandroid:apiKeyにたいして設定する。（レイアウトファイルとかの話）

##### 地図表示のために

地図を表示するにはマニフェストファイルに外部ライブラリの仕様を定義する必要がある。`<application>`タグの子タグとして`<uses-library>`タグを記述する。他に地図情報をネットからダウンロードするために`<uses-permission>`タグでインターネットの使用許可も得る必要がある

#### アプリケーションへの署名

フィンガープリントを取得する際に使用したプライベートキーを用いてアプリケーションに署名する。
Python 3.6 を Ubuntu 16.04LTSにソースからインストール

##概要
Ubuntu16.04LTSではPython3.6のパッケージが公式には提供されていません。
ここでは、Python3.6.7をダウンロードして、ソースからインストールする方法を記します。

####依存関係があるパッケージのインストール

```bash:terminal
sudo apt update && sudo apt upgrade
sudo apt install build-essential \
                 libreadline-gplv2-dev \
                 libncursesw5-dev \
                 libssl-dev \
                 libsqlite3-dev \
                 tk-dev \
                 libgdbm-dev \
                 libc6-dev \
                 libbz2-dev 
```

####ダウンロードと解凍

```bash:terminal
wget https://www.python.org/ftp/python/3.6.9/Python-3.6.9.tgz
tar -xvf Python-3.6.9.tgz
cd Python-3.6.9/
```

####configure, make and install
普通に`sudo make install`するとシステムのpython3のリンクを破壊する可能性があるため、`make install` の代わりに /usr/local/bin/pythonversion のみをインストールする`make altinstall`が推奨されています。

```bash:terminal
# システムワイドにインストールする場合
./configure --enable-shared --enable-optimizations
sudo make altinstall

# homeディレクトリ下にインストールする場合
./configure --prefix=$HOME/usr --enable-shared --enable-optimizations
make altinstall
```

####インストールされているか確認
`python3.6 -V`とターミナルで入力し、`Python 3.6.9`と返ってくれば成功です。

####参考
https://qiita.com/yniji/items/8e392103a6f2a4152606
http://www.techtrekking.net/install-python-3-6-4-on-ubuntu-16-04/
https://docs.python.jp/3/using/unix.html
Alibaba Cloud Container Serviceのチュートリアルをやってみた

Alibaba CloudのContainer Serviceのチュートリアルをやってみました。

# 必要なもの
* Alibaba Cloudアカウント


# 作業概要
Quick Start：[Create WordPress with an orchestration template](https://jp.alibabacloud.com/help/doc-detail/25982.htm) 

　1. クラスタの作成
　2. 設定とデプロイ
　3. 動作確認

# 1. クラスタの作成

まずは[ User Guide：[Create a cluster](https://jp.alibabacloud.com/help/doc-detail/25995.htm) ]の通り、クラスタを作成します。

<img width="1120" alt="cluster1.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/b62d86ab-9afd-bc30-b0e4-39f44345e797.png">

<img width="1121" alt="cluster2.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/54e56180-a62d-addb-0b24-b45d150958c3.png">

<img width="1114" alt="cluster3.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/a090319c-4bdf-6b25-0cc8-b9d4c7818b36.png">

<img width="797" alt="cluster4.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/7221854b-1596-9b90-926b-03d5e3496b42.png">

OKをクリックすると、下記画面が表示されます。

<img width="1246" alt="RAM_warning.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/8ac5a4df-7e81-1088-a581-41fa61309a55.png">

RAMを有効化していない場合は、[RAMをアクティブにする] をクリックして有効化します。

<img width="537" alt="RAM.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/a1cd60d6-efef-0366-6079-f96093f7d3f1.png">

# 2. 設定とデプロイ
[ Quick Start：[Create WordPress with an orchestration template](https://jp.alibabacloud.com/help/doc-detail/25982.htm) ]の通り、オーケストレーションテンプレートを使用して、アプリケーションをデプロイします。

1. 名前等設定後 [オーケストレーションテンプレートを使用して作成] をクリックし、遷移先の画面下部の [既存のオーケストレーションテンプレートを使用する] をクリック
<img width="1365" alt="c1.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/2a9f00bb-7b96-56f2-4652-2181f06285ee.png">

2. [wordpress] を選択後、オーケストレーションテンプレートの"changeme"を変更し、[作成とデプロイ] をクリック
<img width="477" alt="c2.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/7ec55302-fed2-c087-b855-6beb631a6bb3.png">

3. デプロイ完了後の画面

<img width="1369" alt="c3.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/f3076021-975a-986c-d026-0bebae3f6707.png">


# 3. 動作確認

上記画面の [web]をクリックするとアクセスポイントが表示されます。
クリックするとwordpressの画面が表示されます。

<img width="250" alt="wp0.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/7cf8fb08-c46d-3456-0966-f76295eddcf7.png">

<img width="1672" alt="wp.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/7325a639-b9ed-9fed-5698-83ab12e6deff.png">


# 雑感
サクッとコンテナをデプロイできました。
[Node.js]HerokuでMongoDBを使う方法

HerokuでMongoDBを使うのに手こずったので、解説したいと思います。
##前準備
クレジットカード情報を追加していないと、下記のエラーが出てしますので登録しておきましょう。
```Item could not be created: 
Please verify your account to install this add-on plan
 (please enter a credit card) For more information,
see https://devcenter.heroku.com/categories/billing 
Verify now at https://heroku.com/verify```
**・設定方法**
Herokuの画面右上にある、自身のアイコンをクリックし、「Account setting」から「Bilding」に進むとクレジットカード情報を追加することができます。

##MongoDBの導入
1. 自身のアプリケーション一覧から、任意のアプリケーションを選択する。
2. 「Resouces」タブを選択し、「Find more add-ons」をクリックする。
3. 新しいWebページが表示されると思うので、「Data Stores」の中から、「mLab MongoDB」を選択する。
4. 「Install mLab MongoDB」をクリックすると、どのアプリケーションにインストースするのか問われるので、好きなものを選択してください。

##デプロイに向けての設定
1. コマンドプロントから```heroku config -a {アプリ名}```を実行し、**MONGODB_URI**の値を調べる。
2. ```mongoose.connect()```の引数に**MONGODB_URI**の値を渡せば、デプロイに成功すると思います。

##まとめ
初めて、Herokuのアドオンを追加したが、他にも色々なものが追加できるので遊べそう。
Node.jsでMySQLを使う - hubot

# node.jsでmysqlを使えるようにする

node_modulesにmysqlが追加されて使えるようになる

```shell
npm install mysql
```

# dbを作る
mysqlに入って下記のコマンドを実行

```sql
CREATE DATABASE db_quotationrobot;
```
# テーブルとカラムを作る

```sql
CREATE TABLE tb_quotationrobot (
     id MEDIUMINT NOT NULL AUTO_INCREMENT,
     cl_quotationrobot CHAR(100) NOT NULL,
     PRIMARY KEY (id)
);
```

# 実装

```node.js
var mysql = require('mysql');

var connection = mysql.createConnection({
host: process.env.DB_HOST || 'ホスト名',
user: process.env.DB_USER || 'ユーザー名',
password: process.env.DB_PASS || 'パスワード',
database: process.env.DB_NAME || 'db_quotationrobot'
});

//これは省略してもoK。
connection.connect();


var sql = "INSERT INTO db_quotationrobot.tb_quotationrobot (cl_quotationrobot) VALUES('value test quotationrobot')";  
connection.query(sql, function (err, result) {
    if (err) throw err;
    console.log("1 record inserted");
  });
connection.query('SELECT * FROM tb_quotationrobot;', function (error, results, fields) {
console.log('data output');
console.log(results);
});
```

# 実行結果

hubotで実行


```
//ログ
data output
[ RowDataPacket { id: 1, cl_quotationrobot: 'value test quotationrobot' } ]
```
```
//sql
mysql> SELECT * FROM tb_quotationrobot;                                      
+----+---------------------------+
| id | cl_quotationrobot         |
+----+---------------------------+
|  1 | value test quotationrobot |
+----+---------------------------+
1 row in set (0.00 sec)
```


# 参考

[Node.jsでMySQLを使うメモ](https://qiita.com/PianoScoreJP/items/7ed172cd0e7846641e13)
terraform で入れ子ループ

# TL;DR

* 参考 [Terraform - Use nested loops with count - Server Fault](https://serverfault.com/questions/833810/terraform-use-nested-loops-with-count)
* わかりにくいのでわかりやすくしてみた
* https://github.com/officel/notes/commit/41ca18fbd2a472f1d0d72cd5228736d203f7dda4
* あとサンプルにコストかけたくないのでお金がかからない方法でやってみた

# code

```terraform
variable "asc" {
  type = "list"

  default = [
    "a",
    "b",
    "c",
    "d",
  ]
}

variable "desc" {
  type = "list"

  default = [
    "z",
    "y",
    "x",
  ]
}

// want
// a_z, a_y, a_x,
// b_z, b_y, b_x,
// c_z, c_y, c_x,
// d_z, d_y, d_x

locals {
  counter = {
    asc  = "${length(var.asc)}"
    desc = "${length(var.desc)}"
  }
}

// 要諦はasc(4)*desc(3)=count(12), index/asc(4)の余りとindex/asc(4)
resource "local_file" "foo" {
  count    = "${local.counter["asc"] * local.counter["desc"]}"
  content  = "ok"
  filename = "${path.module}/file_${var.asc[count.index % local.counter["asc"]]}-${var.desc[count.index / local.counter["asc"]]}.txt"
}

```

# 蛇足

* 正確には terraform が順番どおりにやってくれないので入れ子ループとは呼びにくい
* AWS で VPC Peering を考えた時にVPC間のルートテーブルとサブネットのIDをぶん回す時に使用した
* もっとも、最終的にそれはVPC CIDRで接続することにしたのでお蔵入りになったのだけれど
* 捨てるのももったいないのでサンプルにして残してみた
*
JsonDeserializerを使って空の時に型が配列になるプロパティに対応する

## 概要
値がある場合はオブジェクト型で空の場合は配列型のプロパティを持つJSONを返すAPIがあり、デフォルトでは型が合わずクラスにバインドできない。

```
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `net.yotama.sample.resource.Resource$Member` out of START_ARRAY token
 at [Source: (String)"{"member": []}"; line: 1, column: 12] (through reference chain: net.yotama.sample.resource.Resource["member"])
```

Jacksonの``JsonDeserializer``を使い、配列の時はnullに置き換えることで、リソースクラスにバインドできるようにする。

### 想定しているJSONレスポンス

値がある場合

```json
{
    "member": {
        "name": "yotama"
    }
}
```

値がない場合

```json
{
    "member": []
}
```

## 環境

- Java 8
- Jackson 2.9.4
- Lombok 1.16.20

## 実装


### リソースクラス
```java:Resource.java
package net.yotama.sample.resource;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Value;

import java.io.IOException;

@Value
public class Resource {
    @JsonDeserialize(using = MemberDeserializer.class)
    Member member;

    @Value
    public static class Member {
        String name;
    }

    public static class MemberDeserializer extends JsonDeserializer<Member> {
        private ObjectMapper objectMapper = new ObjectMapper();

        @Override
        public Member deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            TreeNode treeNode = p.getCodec().readTree(p);
            return treeNode.isObject() ? objectMapper.readValue(treeNode.toString(), Member.class) : null;
        }
    }
}
```

```properties:lombok.config
# 簡略化の為にLombokを使用しているが、
# 1.16.20からはJacksonが使用している@ConstructorPropertiesが付与されなくなるので、暫定で設定
lombok.anyConstructor.addConstructorProperties=true
```


### 動作確認

```java
package net.yotama.sample.resource;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;

import java.io.IOException;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

@RunWith(Theories.class)
public class ResourceTest {
    private ObjectMapper objectMapper = new ObjectMapper();

    @DataPoints
    public static Fixture[] data = {
            new Fixture("{\"member\": []}", new Resource(null)),
            new Fixture("{\"member\": null}", new Resource(null)),
            new Fixture("{\"member\": {\"name\": \"hoge\"}}", new Resource(new Resource.Member("hoge"))),
    };

    @Theory
    public void test(Fixture fixture) throws IOException {
        assertThat(objectMapper.readValue(fixture.json, Resource.class), is(fixture.expected));
    }

    @RequiredArgsConstructor
    public static class Fixture {
        final String json;
        final Resource expected;
    }
}
```
LaravelでViewで渡される`$errors`をControllerや独自ライブラリやら好きなところで使いたいとき

Laravelの`$errors`便利ですよね！
でもView以外で使いたいってこともあると思うんです。
そんなときどうすればいいか。

コード追えば一瞬で分かっちゃうんですが、公式マニュアルに記述がないしこのことを言及しているサイトも見当たらなかったのでここに記録します。

公式マニュアルではこう説明されています。

> Tip!! `\$errors`変数はwebミドルウェアグループに所属する、`Illuminate\View\Middleware\ShareErrorsFromSession`ミドルウェアによりビューに結合されます。このミドルウェアが適用される場合は、いつでもビューの中で`\$errors`変数が使えます。`\$errors`変数はいつでも定義済みであると想定でき、安心して使えます。

*ref. [Laravel 5.5 バリデーション バリデーションエラー表示](https://readouble.com/laravel/5.5/ja/validation.html#quick-displaying-the-validation-errors)*

なるほど。`ShareErrorsFromSession`の中身を見てみると、

```php
        $this->view->share(
            'errors', $request->session()->get('errors') ?: new ViewErrorBag
        );
```

*ref. [laravel/framework src/Illuminate/View/Middleware/ShareErrorsFromSession.php](https://github.com/laravel/framework/blob/56a58e0fa3d845bb992d7c64ac9bb6d0c24b745a/src/Illuminate/View/Middleware/ShareErrorsFromSession.php#L41-L43)*

これそのままパクればいけますね。
Controllerだったら

```php
    public function index(Request)
    {
        $errors = $request->session()->get('errors');

        ...
    }
```

でいけるし、Controller以外で使いたければRequestファサード使って

```php
    $errors = \Request::session()->get('errors');
```

でもいいし。

...


余談ですが、`$erros`以外に予約されている変数があるのかなと思って眺めたのですが、ぱっと見た感じ`$app`、`$__env`がview->share()されていましたよっと。
新ドメインがキーワード検索に表示されるまで（2018年2月）

新しいドメインを取得して、wordpressでwebサイトを構築して公開しました。主要キーワードやホームページ名で検索を繰り返していましたが、検索結果に出るまでしばらく時間が掛かりました。それまでに何をやったかを明記しておきたい。

###公開したWebサイト
・ある商業施設のホームページ（営業日、料金表などを表示する）
・構築はwordpressを利用して独自テンプレート（固定ページのみ利用）
・更新頻度は月1度程度
###目的
・ホームページ名と主要キーワードでキーワード検索を行い、検索結果に表示したい

###実施したこと
**公開〜1週間　httpsでWebサイトを公開**
キーワード検索（SEO）にはサーバ証明書を利用した方がよりインデックスされやすいと公式に名言されているため。特にクロールの要望は出さず、被リンクも貼らず待ってましたが検索結果には表示されない。。

**10日目 Google Search Console（以下「GSC」）でリクエストを出す**
「Fetch as Google」でリクエストを出しました。
特に状況は変わらず、インデックス済みのページは0となっていました。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/110457/9111e767-af7c-d325-3eaf-8f54de8f1ebe.png)

**15日目 サイトマップの登録**
サイトマップを登録すれば、より早く正確にインデックスされるらしいので登録しました。wordpressのプラグインで自動作成して登録すると、2日後くらいにインデックスされ検索結果に表示されました。

**（補足）wordpressのサイトマッププラグイン**
wordpressだと「Google XML Sitemaps」が便利、人気、GPLで良さそう。
細かく設定でき、固定ページだけでも利用できるのでインストール
![1.png](https://qiita-image-store.s3.amazonaws.com/0/110457/b7d2659f-debd-9a38-b908-4fad76c8da1e.png)
その後、GSCに登録する
![2.png](https://qiita-image-store.s3.amazonaws.com/0/110457/13443584-471a-0deb-598c-5b7a0463a4b6.png)
※これは設定後、インデックスされた後のキャプチャになります。

**振り返ってみて**
クロールのリクエスト後、インデックスのステータスがしばらく保留になっていました。サイトマップを登録してからおよそ2日後にGoogleアカウントへ登録済みのメールアドレスにGSCから「検索トラフィックを監視する」という件名のメールが来て、以降キーワード検索にサイト名、主要のキーワードで検索できるようになりました。検索結果に表示して欲しければ、クロールのリクエストと、サイトマップをきちんと作りましょうってことでしょうかね。

サイトマップを登録することでインデックスされる時間を短縮できたのかもしれない。。検索結果に表示された際、被リンクは1つもありませんでした。後日、GoogleMapのロケーション、リンク可能な他サイトからの被リンク貼りなど実施しました。それではみなさんも良いSEOライフを！
スクレイピングの参考書を見て分からなかった部分(備忘録)

#参考書を見て今回の分からなかった部分

>　mojogodb.orgのリポリトジを追加して、MongoDBをインストールします

```cmd
$ sudo apt-key adv --keyserver hkp://keyservser.ubuntu.com:80 --recv 7F0CEB10
```

はいキター！！( ;∀;)いや、仮想環境で作ったUbuntuを利用したユーザー(ほぼwindowsユーザー)を想定して書いているわりには、説明省きすぎじゃないですかね・・・涙

#解説・・・しないよ?
じゃ私がいっこずつ解説していきましょう・・・と言いたいところだが、残念ながらその余力はない。
正直色々調べたが、情報がまとまっていない。ubuntuのコマンド集みたいなの公式にあるのかな？知っていれば教えてほしい。

どのみち知りたいのは、一つ一つのコマンドの細かな説明ではなくそのコマンドにどんな意味があるかじゃないでしょうかね？だから・・・

#ざっくり行くよ！！
>　apt-key　

↑　パッケージ管理(apt)が使う公開鍵のリストを管理するコマンド


>　adv　

↑　後に続くコマンドをgpg(暗号一式扱うソフト)に渡すってこと。apt-keyは単体で動くんじゃなくて実際はこれがgpgが多くを担っている。


>　--keyserver

↑　これを使うと公開鍵が配布されているサーバーをそのあとに続けて指定できる。

>　hkp

↑　後述するアドレスのサーバがHTTP（または互換性のある）鍵サーバーであることを示す

>　keyservser.ubuntu.com:80　

↑　キーが公開されているアドレス　:80はオプションでポート指定。

>　--recv 7F0CEB10

↑　7F0CEB10ていう公開鍵をダウンロードする。

#続きは理解できたら書くことにする・・・
これ、長すぎでしょ・・・涙

```cmd
$ echo "deb http://repo.mongodb.org/apt/ubuntu "$(lsb_release -sc)"/mongodb-org/3.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.0.list
```

想像では、第三者が公開しているリポジトリ（この場合はmongodbさんたちが公開している)

deb http://repo.mongodb.org/apt/ubuntu "$(lsb_release -sc)"mongodb-org/3.0 multiverse

をechoで標準出力に出して、｜←これでパイプを通して sudo tee コマンドにそれを渡して、treeはsources.list.d　配下のmongodb-org-3.0.listに書き込んで、かつ実行標準出力に出す？

って感じかな?あってるの？正直わからんよ・・・なんでこんな長いコマンド打たなきゃならんのさ・・・。
得意じゃないな。debとか、$(lsb_release -sc)とか違和感を感じる。誰か教えてくれええええええ！！！
【Ruby】クラスのメソッドのpublic/privateメモ

```ruby:test.rb
class Test
  def publicm
    puts "public"
  end
  public :publicm

  def privatem
    puts "private"
  end
  private :privatem


  public
  def publicm2
    puts "publicm2"
  end

  private
  def privatem2
    puts "privatem2"
  end
end

test = Test.new()
test.publicm
test.publicm2
#test.privatem Error!!!
#test.privatem2 Error!!!

```
asyncio における同期プリミティブの必要性


asyncio を使った並列実行はシングルスレッドで動作するから、ロックとかの同期プリミティブいらないじゃん。と思っていたんだけど、そんなことはなかった。実際標準ライブラリにもあるね `asyncio.Lock` とか。

結局ロックなどの同期プリミティブの用途は、クリティカルセクションの保護が第一義なわけ。**「同時に1つの処理しかしない（=asyncio）」ことと、「クリティカルセクションにただ1つの処理が存在する(=同期プリミティブ)」ことは、似ているようで全然違う**。

[stackoverflow で似たような議論とサンプルコードを見つけた。](https://stackoverflow.com/questions/25799576/whats-python-asyncio-lock-for)

とはいえ、クリティカルセクションを含む処理を同期関数にすればやっぱり同期プリミティブはいらないんじゃない？と思う。いやいや、それは短絡的にすぎる。同期関数にすることによってイベントループ全体が止まるわけで、、、やっぱり**非同期な同期プリミティブ**が必要という結論になる。いやーむずかしいね。
Keras 環境構築（Mac）

## pyenv の install

brew で install

```
$ brew install pyenv
```

.zsrc に追記

```:.zshrc
eval "$(pyenv init -)"
export PATH="$HOME/.pyenv/bin:$PATH"
```

## anaconda3 の install

anaconda3 の version を確認

```
$ pyenv install --list | grep anaconda3

...
anaconda3-5.0.1
```

最新を install

```
$ pyenv install anaconda3-5.0.1
```

anaconda3-5.0.1 を使用

```
$ pyenv global anaconda3-5.0.1
```


```
$ python -V
Python 3.6.3 :: Anaconda, Inc.
```

## Anaconda で Python 3.6 用の環境構築

py3.6 という名前で 3.6 用の環境を構築

```
$ conda create -n py3.6 pip python=3.6
```

作成した環境を active に

```
$ source activate py3.6
Usage: pyenv which <command>
```

うまくいかない。
どうも anaconda3 の path で上書かないと source コマンドが使えないよう

```:.zshrc
# pyenv
eval "$(pyenv init -)"
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"

# anaconda
export PATH="$PYENV_ROOT/versions/anaconda3-5.0.1/bin/:$PATH"
```

```
$ source activate py3.6
```

ok

## TensorFlow の install

TensorFlow の package URL を .zshrc に追記（しなくてもいい）

```:.zshrc
export TF_PYTHON_URL="https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-1.5.0-py3-none-any.whl"
```

TensorFlow の install

```
$ pip install --ignore-installed --upgrade $TF_PYTHON_URL
```

[TensorFlow の install page](https://www.tensorflow.org/install/install_mac#the_url_of_the_tensorflow_python_package) にある sample を実行 

```py3
import tensorflow as tf
hello = tf.constant('Hello, TensorFlow!')
sess = tf.Session()
print(sess.run(hello))
```

```
python sample.py
2018-02-11 19:32:04.474567: I tensorflow/core/platform/cpu_feature_guard.cc:137] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.2 AVX AVX2 FMA
b'Hello, TensorFlow!'
```

warning が出てるけど、動いている

## Keras の install

```
$ pip install keras
```

完了
GhostbustersはSeleniumの塔に登るか？

こんにちは！
皆さん映画見てますか！！
映画ってほんとうに良いものですよね！！！
私は昨年ついに、立川シネマシティの会員になってしまいました！！！！


## 突然ですが映画の話を差し込みます

[ゴーストバスターズ](http://www.ghostbusters.com/ghostbusters-1-and-2.html) という1984年の大ヒット映画があります。科学兵器で幽霊退治をする映画です。
最近になってあらためて観ますと、劇中の最終目的地となるビルが呪術的な構造をしていて純度の高いSelenium（セレン）を含んでいる、なんて感じの説明があってニヤリとするわけです。
Seleniumの構造体に巣食うPhantomを退治してしまうのね...

というわけでこの記事ではSeleniumとPhantomJSの話をします。


## PhantomJS!? 非推奨にしたはずでは...

SeleniumとPhantomJSを組み合わせて何か作る類の技術記事は非常に多く、最近もまだまだこの構成での新しい記事がWeb上で書かれているようです。
しかし、残念ながら既にSeleniumのいくつかのバインディングでは、PhantomJSの併用は明示的に非推奨・サポート切れとなっています。

* Ruby（Selenium v3.6.0から）
* Java（Selenium v3.8.0から）
* Python（Selenium v3.8.1から）

今まさにSelenium + PhantomJSの記事を書いている途中だったら、すぐにSelenium + Headless Chrome/Firefoxの記事に書き換えましょう！！！！
既に書いちゃった記事は、青春の1ページと思って10年後に読んで苦しめ！！！！！ フハハ！！！！！


## そもそもなんで非推奨になったの？？？

2017年4月に、PhantomJSの唯一のメンテナーであったVitaly Slobodinが引退してしまったことが、強く影響しているとみられます。
当時のPhantomJSのメーリングリストへの [Vitaly Slobodinの投稿](https://groups.google.com/d/msg/phantomjs/9aI5d-LDuNE/5Z3SMZrqAQAJ) は強い悲観を感じさせるもので、PhantomJSの将来が完全に途絶えた印象を持つには十分だったのではないでしょうか。
この投稿を、ざっくり日本語訳します。

> やあ、私から告知させてほしい。
> 
> ヘッドレスChromeがやってくる - https://www.chromestatus.com/features/5678767817097216
(https://news.ycombinator.com/item?id=14101233)
> 
> 結局は、みんなこれに切り替えるんだろう。ChromeはPhantomJSに比べて、速いし安定している。メモリーをバカみたいに食うこともない。
> 
> PhantomJSの開発に、私はもう未来を見出せない。PhantomJS 2と2.5をひとりで開発するのは血だらけの地獄だ。
> 最近、新しくてピカピカのQtWebKitを使った2.5 betaバージョンをリリースしたけど、私には一度に3つすべてのプラットフォームの物理的なサポートはできない（サポートのためにMacを買うまでした！）。 私たちにはサポートが無い。
> 今から、私はメンテナーから退く。もし誰かが継ぎたいときは - 気軽に連絡してくれ。
> 
> 私はAriya、James、Ivanを讃えたい！ 皆さんと仕事ができて嬉しかった。乾杯！
> 私たちを助けてくれた、あるいは助けようとしてくれたすべての人々にも、感謝を告げたい。ありがとう！

折しも、各WebブラウザーにおけるWebDriverの実装を、 [W3Cで標準化されつつあるもの](https://www.w3.org/TR/webdriver/) に準拠させようとされている最中です。
PhantomJSは開発が止まったことによりW3C WebDriver準拠とする作業が止まってしまったわけで、Selenium開発者たちはPhantomJSのサポートも止めざるを得なくなってしまったものとみられます。


## PhantomJSの最新事情

PhantomJSは完全に終わったかと思いきや、一波乱ありました。2017年12月になって [ポーランドのフリーランサーであるpixiuPL](https://github.com/pixiuPL) がPhantomJSへの精力的なコントリビューションを始めて、ついにはPhantomJSの新バージョンが再リリースされたのです。

しかしこれは、非常に残念な結果に終わってしまいました。
pixiuPLのコミット品質は全体的に低く、かつ進め方も粗暴なものであったため、2018年3月にPhantomJSの原作者である [Ariya Hidayat](https://github.com/ariya) はリポジトリー防衛のために開発プロジェクトを凍結することを宣言したのです。
`master` ブランチの状態はバージョン2.1.1まで巻き戻され、将来的に開発を再開できる状態までには整えられたものの、PhantomJSをSeleniumで再び利用可能とするための壁はまた一段と厚くなってしまいました。

Archiving the project: suspending the development
https://github.com/ariya/phantomjs/issues/15344

pixiuPLの動きにはたいへんに問題があり、邪推をすればリポジトリーを乗っ取るようにみえるものでした。（著者表示を自分だけのものに差し替えたり、ファイルの削除・再追加によってGitログ上は自分の成果物に見えるようにしたり、リポジトリーや公式サイトの管理権限についてAriyaに執拗にコンタクトをとったり...）
また、既存の `release` など重要なブランチもpixiuPLにより削除されるなどしたため、リポジトリー復旧のための多大な努力の甲斐無く、いくつかのコードは失われてしまったようです。

PhantomJSの最新バージョンは2.1.1となり、これはもう2年前のものとなってしまいました。ヘッドレス機能も既にPhantomJSだけのものではなく、他にいくつも代替となる実装例があらわれています。
残念ですが、GhostbustersがPhantomを退治して、一時代が終わってしまったと結論づけるのが妥当なようです。
バックエンドが S3 の terraform で init 時に profile 指定する

　terraform のバックエンドの S3 にアクセスするときにも当たり前ですが、credential が必要です。複数の profile を使っているときに、デフォルトじゃないものに切り替えたいシチュエーションは結構あるのではないかなと思います。

　そのような場合は以下のように [partial configuration](https://www.terraform.io/docs/backends/config.html#partial-configuration) を用いて profile 指定してあげれば OK です。

```
terraform init -backend-config="profile=${aws_profile}"
```

　ただ、backend に直接記述してしまえば、そもそもあまりこういう心配しなくてすみます。チームで profile 名統一しておいて、 README にこのプロファイル名で設定するという規約を作っておくと、よいのかなと思います。

```
terraform {
  backend "s3" {
    bucket         = "******"
    key            = "******"
    dynamodb_table = "******"
    region         = "ap-northeast-1"
    shared_credentials_file = "~/.aws/credentials"
    profile = "53ningen"
  }
}
```

　terraform の公式ドキュメント的には[このあたり](https://www.terraform.io/docs/backends/types/s3.html#configuration-variables)を参照。このように指定した場合 aws provider にも profile 指定しておくと複数人による開発がスムーズに進んで良いと思います。
Swagger(OpenAPI)を用いて、親切なREST API仕様書を作りたい

#親切なAPI仕様書を作る
##モチベーション
REST APIを作ってもどんなコマンドでどんなエンドポイントに
何があるのか、どれくらいのAPIがあるのかわからないので知りたい

##API設計ツール
色々なツールが出ているみたい

- API Blueprint
- Swagger(OpenAPI)
- apiary

2016年1月にSwaggerはOpenAPIとなった経緯があるそうで
API設計の標準化が目指されているようです。


##Swagger(OpenAPI)の導入
下記の環境を想定しているので、hapi用のswaggerモジュールである
hapi-swaggerを公式サイト(https://github.com/glennjones/hapi-swagger)の
Quick Startを元にインストールしてみます。

環境
OS : macOS High Sierra
NodeJS : v9.5.0
hapi : v17.0.0

```
npm install hapi-swagger --save
npm install inert --save
npm install vision --save
```

##サンプルコードの実行
Quick Start にあるコードが少し間違っているので
修正した下記コードを実行
Routes部分は適切に変更する必要がある。

```hoge.js
const Hapi = require('hapi');
const Inert = require('inert');
const Vision = require('vision');
const HapiSwagger = require('hapi-swagger');
const Pack = require('./package');
const Joi = require('joi');


(async () => {
    const server = await new Hapi.Server({
        host: 'localhost',
        port: 3000,
    });
    
    const swaggerOptions = {
        info: {
                title: 'Test API Documentation',
                version: Pack.version,
            },
        };
    
    await server.register([
        Inert,
        Vision,
        {
            plugin: HapiSwagger,
            options: swaggerOptions
        }
    ]);
    
    try {
        await server.start();
        console.log('Server running at:', server.info.uri);
    } catch(err) {
        console.log(err);
    }
    
    server.route({
        method: 'GET',
        path: '/todo/{id}/',
        config: {
            handler: function(request, h){
                return "本来なら戻り値をかくよ"
            },
            description: 'Get todo',
            notes: 'Returns a todo item by the id passed in the path',
            tags: ['api'], // ADD THIS TAG
            validate: {
                params: {
                    id : Joi.number()
                            .required()
                            .description('the id for the todo item'),
                }
            }
        },
    });
})();

```

node hoge.jsで実行してみる

下記のような画面が表示される
<img width="1440" alt="hapi-swagger1.png" src="https://qiita-image-store.s3.amazonaws.com/0/94861/e6831ce9-1019-69f2-5c2d-0e9fcd354ac9.png">

valueに値を入れてTry it outボタンを押すと
API実行時のcurlやリクエスト、レスポンスが下記のように表示される。
<img width="1440" alt="hapi-swagger2.png" src="https://qiita-image-store.s3.amazonaws.com/0/94861/23fc6023-57c0-68dc-b6f8-93c106f58881.png">

javadocにコード実行機能が付いたような使い勝手でいいかんじ！
GKEでなるべく安くKubernetesクラスタを作成してPrometheus + Grafanaを使ってみる Part1 -クラスタ作成編-

タイトルの通りGKE (Google Kubernetes Engine)でKubernetesクラスタを作成して、その上でPrometheusとGrafanaを動かしてみます。

まずはGKEでKubernetesクラスタを作成してみます。

# はじめに

GCP(Google Cloud Platform)アカウントの登録とプロジェクトの作成が終わってる前提でお話します。

適当に作っておいてください。

# クラスタの作成

左上のハンバーガーメニューからKubernetes Engineを選択
※初回アクセス時には準備に数分かかります。

クラスタの作成ボタンを押下します。

<img width="443" alt="Screenshot 2018-02-11 13.32.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/27674/ffee0e8b-945b-ade4-ac5b-1b337c662f6d.png">

## 設定

今回のように可用性 (ダウンタイム)に目をつぶるならノードにプリエンプティブを使うことで、[インスタンスの費用](https://cloud.google.com/compute/pricing?hl=ja#machinetype)を7割程度抑えることが出来ます (オレゴン、g1-smallの場合)。
※[プリエンプティブ](https://cloud.google.com/preemptible-vms/?hl=ja)にした場合、２４時間以内に勝手に落とされてしまうので気をつけてください。

ノードは価格の安い海外のリージョンを使い、マシンタイプはsmallを使います。

またデフォルトでは、ノードのディスクサイズが100GBという罠があるので、忘れずに減らしておきましょう。

  1. ゾーン: us-west1-b
  2. マシンタイプ: small（g1-small)
  3. サイズ: 4
  4. プリエンプティブ ノード: 有効
  5. ノードあたりのブートディスク サイズ: 10GB
  6. HTTP 負荷分散: 無効

## 接続

クラスタの作成が終わったらkubectlコマンドでクラスタに接続してみます。

接続ボタンを押下し、"Cloud Shellで実行"を押下します。

<img width="746" alt="Screenshot 2018-02-11 15.20.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/27674/5f6443b3-6e93-035c-0d17-35ed04501fc8.png">

ウインドウ下部に、コマンドが入力済みの状態でコンソールが表示されます。
Enterキーを押してコマンドを実行します。

これでkubectlでアクセスできるようになりました。

```kubectl get nodes```を実行して作成したノードが表示されるかどうか確認します。

以上
正規表現

# 正規表現

文字列のパターンを一つの形式でまとめて表現するために使用すること。  
フォーラムで与えられるデータに不整合があると面倒くさいので、そういった部分を排除するために使われている。  
> 要するにエラーチェック

```txt:正規表現.txt
郵便番号  [678-0041]    [検索]
          [678]-[0041]  [検索]
```

## 正規表現の記法

[0-9]{3} - [0-9]{4}<br>
0-9の数字を3回入れる<br>
ハイフンを入れる<br>
0-9の数字を4回入れる<br>
入っていない場合はエラー

ルールの記法的な感じ。

## JAVAで記述する場合。

```java:text.java
class Test{
   public static void main(String[] args){

      String strZip = request.getParameter("zip");
      String zipPattern = "[0-9]{3}-[0-9]{4}";

      // コレ大事 上記のルールを適用する。
      Pattern p = Pattern.compile(zipPattern);

      if (p.matcher.(strZip).find()) { //find()で[true/false]を返却値として渡す。
         // 郵便番号の形式
      } else {
         // 入力形式がエラー
      }

   }
}
```

## 正規表現

javascriptを使う事によって、フォーカスアウトされたりした時に警告を走らせる事も可能である。

| 記号  |               記号の説明                      |
|:-----:|:----------------------------------------------|
| ・    | 任意の１文字。改行文字は省く                  |
| ＊    | 直前の１文字の０回以上の繰り返しと一致        |
| ＾    | 行の先頭 ＾（ハット文字）                     |
| ＄    | 行の末尾                                      |
| ［ ］ | カッコ内の任意の１文字と一致、-で範囲指定可能 |
| ｛ ｝ | カッコ内の数値の繰り返し回数を記述する。      |
| ＋    | 直前の表現を０回、または１回繰り返して使う    |


## 正規表現の例文

^[a-z]+$  
^[A-Z]+$  
^[a-zA-Z]+$  
電話番号:^[0-9]{2,4}-[0-9]{2,4}-[0-9]{3,4}$  
{}の範囲指定はカンマ区切り

^ [\\w]+ $           : \w 半角英数字  
^ \\d{3}\\- \\d{4} $ : \d 郵便局番号

記号は \w \d で記述する。

## エスケープ文に関して。

円マーク（バックスラッシュ）で記述する。
基本的に\nが良いと思う。

### コンソールで出力する。
①私の名前は山田です。
System.out.println( "私の名前は山田です。" );

②私の名前は"山田"です。
System.out.println( "私の名前は\"山田\"です。" );













END
【Ruby】インスタンス変数、クラス変数

# インスタンス変数

```ruby:test.rb

class Test
  def setName(str)
    @name = str
  end

  def getName()
    return @name
  end
end

test = Test.new()
test.setName("hogehoge")
puts test.getName()
```

```
hogehoge
```

# クラス変数

```ruby:test.rb
class Test
  @@count = 0
  def increment()
    @@count += 1
  end

  def show_count()
    puts @@count
  end
end

test1 = Test.new()
test2 = Test.new()

test1.increment()
test1.show_count()
test2.increment()
test2.show_count()
```

```
1
2
```
gradleでjarから特定のパッケージだけを取り除く

gradleで外部のライブラリjarから特定のパッケージやクラスを取り除く方法メモ。

今回は、[kotlin compiler](https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-compiler)から ```com/intellij/**``` 配下のパッケージを取り除いたjarを生成する。

![スクリーンショット 2018-02-11 23.37.46.png](https://qiita-image-store.s3.amazonaws.com/0/118567/6727477c-1fe2-96a1-4678-ee70bad8255f.png)


```build.gradle

configurations {
    kotlinCompiler { transitive = false }
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    kotlinCompiler ("org.jetbrains.kotlin:kotlin-compiler:$kotlin_version")
    compile files("$libsDir/tweaked-kotlin-compiler.jar")
}

task tweakKotlinCompiler(type: Jar) {
    from zipTree(configurations.kotlinCompiler.singleFile).matching {
        exclude "com/intellij/**"
    }
    destinationDir libsDir
    archiveName 'tweaked-kotlin-compiler.jar'
}

compileKotlin.dependsOn tweakKotlinCompiler
```

```kotlin-compiler-1.2.10.jar``` をzipTreeで特定のパッケージを除外し、新たなjarを生成する。

![スクリーンショット 2018-02-11 23.37.14.png](https://qiita-image-store.s3.amazonaws.com/0/118567/4871587b-27af-08ad-ee94-14342c4a7274.png)

特定のパッケージだけ取得したい場合は、includeすれば可能。

全体

```build.gradle
buildscript {
    ext.kotlin_version = '1.2.10'

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

plugins {
    id 'org.jetbrains.intellij' version '0.2.18'
}

group 'com.github.bassaer'
version '0.0.1'

apply plugin: 'kotlin'

repositories {
    mavenCentral()
}

configurations {
    kotlinCompiler { transitive = false }
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    kotlinCompiler ("org.jetbrains.kotlin:kotlin-compiler:$kotlin_version")
    compile files("$libsDir/tweaked-kotlin-compiler.jar")
}

task tweakKotlinCompiler(type: Jar) {
    from zipTree(configurations.kotlinCompiler.singleFile).matching {
        exclude "com/intellij/**"
    }
    destinationDir libsDir
    archiveName 'tweaked-kotlin-compiler.jar'
}


compileKotlin() {
    kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
intellij {
    version '2017.3.3'
}
patchPluginXml {
    changeNotes """
      Add change notes here.<br>
      <em>most HTML tags may be used</em>"""
}

compileKotlin.dependsOn tweakKotlinCompiler
```
ElixirでStructのパターンマッチング

って `%_{}` とのマッチングでいけるんですね

```ex:例
iex> %_{} |> Kernel.match?(%SomeStruct{})
true

iex> %_{} |> Kernel.match?(%{})
false
```

https://stackoverflow.com/questions/39757796/how-to-check-if-a-map-is-also-a-struct
↑ここの回答にあって初めて知りました


ということはAtom型の値も取れるってことですもんね

```elixir
iex> %module{} = %SomeStruct{}
%SomeStruct{val: nil}

iex> module
SomeStruct
```

考えてみれば右辺も左辺もStructの ~~マクロ~~ 糖衣構文が展開されて

```elixir
%{__struct__: module} = %{__struct__: SomeStruct, val: nil}
```

になってるだけですもんね、たしかにそうだ
ちゃんと展開されているんだなぁ


　
~~ところでシンタックスハイライティングが変~~
2018/02/19現在問題なくなってる わーい（`%`のあとに大文字か`{`以外が来てたら下線が引かれてしまってた）
NodeJSフレームワーク hapiを触ってみる

#hapiフレームワークについて調べたことまとめ
##モチベーション
- NodeJSで何かしらコードを書きたい
- 簡単な記述で書きたい(細かい設定等気にしたくない

##hapiを選択した理由
コーディングがjson形式で書ける部分があり、とっつきやすいと思った(主観

##hapiのインストール
hapi v17.0.0をインストール(2018年2月時点で最新)
nodeJSのバージョンv8.9.0以降が必要となります。

```
npm install --save hapi@17.0.0
```

日本語のhapiの記事を探すと2015年くらいのものばかり出てきて
hapi v10くらいの頃の記事がヒットしてきて、そのまま書いても
動かないものばかり...
それくらい成長しているとポジティブに捉えてこのまま進めていきます。

##hapiのサンプルコードの実行
公式サイト(https://hapijs.com)のGetting Startedを元に進めます。
下記のようなサンプルコードを作成します。
やっていることは

- hapiモジュールの呼び出し
- serverのIP(localhost),ポート(8000)の指定
- ルーティングの指定
    - HTTPのリクエストメソッドの指定(GET,PUT,POST,DELETE等)
    - パスの指定(localhost:8000/helloで呼び出せる
    - 呼び出し時のハンドラ(関数)の指定
- サーバの実行

```servers.js
'use strict';

const Hapi = require('hapi');

// Create a server with a host and port
const server = Hapi.server({ 
    host: 'localhost', 
    port: 8000 
});

// Add the route
server.route({
    method: 'GET',
    path:'/hello', 
    handler: function (request, h) {

        return 'hello world';
    }
});

// Start the server
async function start() {

    try {
        await server.start();
    }
    catch (err) {
        console.log(err);
        process.exit(1);
    }

    console.log('Server running at:', server.info.uri);
};

start();
```

下記コマンドでサーバを立ち上げます。

```bash
node server.js
```

localhost:8000/helloにアクセスしてみると
hello worldと表示されます。