OmniAICreator/Qiita-1.07M huggingface dataset:
Selenium2をIEで起動させてみる。


お久しぶりの投稿になりますtsuttieです(*'▽')
今回はSelenium2をIEで起動させる方法についてお話していきます。


#1. Selenium2を使ってみて
Webアプリのテスト自動化を目的としてSelenium2を使ったので詰まった点を数回に分けてまとめて行きたいと思います。
#2. 使用したSelenium
・Selenium IDE
・Selenium Webdriver (Java 3.5.0)
※導入方法についてはわかりやすくまとめていらっしゃる方が多くおりますので、そのあたりのお話は省きます。
#3. 【本題】Selenium2をIEで起動させてみる。
　今回はSelenium Web DriverをIEで起動させていきたいと思います。
###**(1)IEDriverServer.exeのダウンロード**
　IEで起動させるにはまずIEDriverServer.exeが必要になります。
　以下のURLよりダウンロードを行います。

[http://www.seleniumhq.org/download/](http://www.seleniumhq.org/download/)

![01.PNG](https://qiita-image-store.s3.amazonaws.com/0/198205/8bc857f4-4a82-2ca7-5fb7-a7baea041910.png)

上図枠線部分ですね。
32bitか64bitどちらか適切なほうを選択してダウンロードし、解凍しておきましょう。


次にIE自体の設定を行う必要性がありますので、使用するIEを開き、設定を行っていきます。

###**(2)IEの設定**
IEを開いたら、まずインターネットのオプションからセキュリティタブをひらきます。

そして、インターネット、ローカルイントラネット、信用済みサイト、制限付きサイト
それぞれの「保護モードを有効にする(Internet Explorerの再起動が必要)」にチェックを入れます。

![2.PNG](https://qiita-image-store.s3.amazonaws.com/0/198205/4436d176-b0fa-ed32-7a75-47b277494f36.png)

すべてにチェックを入れたら、次は詳細設定タブを選択し、、、


![3.PNG](https://qiita-image-store.s3.amazonaws.com/0/198205/210501e6-b27a-53b1-6858-1e0573ae28c3.png)

詳細設定より、拡張保護モードを有効にする*のチェックボックスを外して、OKを選択します。
一度IEをすべて閉じて変更を有効にしましょう。

ここまで出来たら、下準備は一応以上で終了です。
最後に実際にコードを書いていきます！(^^ゞ

###**(3)コードの準備・Driverの配置**

私は、IEDriverServerを下図のように配置しています。(画面はeclipseを使用)

![4.PNG](https://qiita-image-store.s3.amazonaws.com/0/198205/04d071a7-a137-7fec-c45a-4bbf4148b73e.png)

特に決まりはありませんので適当なところに配置していただければOKです。

配置が完了したらコードを作成していきます。

```java:IE.java

package ~;

import java.io.IOException;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;

public class IEtest {

	private WebDriver driver;

	@Before
	public void setUp() throws Exception {

		//geckoDriverではなく、IEDriverServerを立ち上げます
		System.setProperty("webdriver.ie.driver", "IEDriverSever.exeのパス");
		driver = new InternetExplorerDriver();

	}

	@After
	public void tearDown() throws Exception {

		driver.quit();

	}

	@Test
	public void test() throws InterruptedException {

		try {

			driver.get("URL");
　　　　　　　/*このあとに何らかの処理～*/

		}catch(IOException e){

			System.out.println(e);

		}

	}

}



```
実際コードは難しくないですね。
Firefoxだと設定などあまり意識しなくて良い点もIEだと何かと制限があるようです。


これを実行すると・・・

![5.PNG](https://qiita-image-store.s3.amazonaws.com/0/198205/218b9968-f911-ab6a-52c5-34b1ef26b435.png)

だ、大丈夫そうですね！！

こんな感じでIEで作動させることができました。

※補足
これまで、利用してきた中で出てきたIE特有のエラーとしては
画面縮尺が100％じゃありません。
などがありました。
(画面の縮尺をもとに戻せば実行できるようになります。)



#4. まとめ
今回はIEでseleniumwebdriverを動かす方法について書いていきました。
難しい処理が、、、ってわけではありませんでしたが、やはり癖が多少あるので
Firefoxと同じように安定しては使うことが出来ないようです。

次回は、また何かseleniumに関する記述が出来ればと思います。(^_^)/ﾃﾞﾊﾃﾞﾊ

#XX. 参考資料

[selenium IDEで作ったテストケースでchrome,IEでもテスト実行する](https://qiita.com/takky/items/9a2c1dc36c1a729c56cb)

[SeleniumでInternet Explorer11を動かす方法](http://bitwave.showcase-tv.com/selenium%E3%81%A7internet-explorer11%E3%82%92%E5%8B%95%E3%81%8B%E3%81%99%E6%96%B9%E6%B3%95/)
Kotlin で GlideApp を使えるようにする

もともと Glide は使えますが、 GlideApp 使えると

> unresolved reference: GlideApp  

このようなエラーが吐きました

## build.gradle (Module: app)

[kapt](https://kotlinlang.org/docs/reference/kapt.html) が必須

```groovy
// ...

apply plugin: 'kotlin-kapt'

// ...

dependencies {
    // ...

    def glideVersion = '4.1.1'
    compile "com.github.bumptech.glide:glide:$glideVersion"
    kapt "com.github.bumptech.glide:compiler:$glideVersion" // annotationProcessor ではなく、 kapt を使ってください

    // ...
}
```

## MyAppGlideModule.kt

このファイルを追加します。
`AppGlideModule` を継承して、 `@GlideModule` を配置します

```kotlin:MyAppGlideModule.kt
// package 略
// import 略

@GlideModule
class MyAppGlideModule(): AppGlideModule()
```

## 最後

ビルドしたら、 GlideApp が動的のように生成して、使えるようになるはず

## 参照

- [Getting Started - Applications](http://bumptech.github.io/glide/doc/getting-started.html#applications) (Glide オフィシャル)
- [Generated API - Kotlin](http://bumptech.github.io/glide/doc/generatedapi.html#kotlin) (Glide オフィシャル)
- [Using Kotlin annotation processing tool](https://kotlinlang.org/docs/reference/kapt.html)
[非エンジニア向け]実例からの！Google Data studio導入編

プログラムや統計の深い知識はない非エンジニアだけれど、事業や施策の数値分析を行う必要がある人は多いと思います。

かくいう私も某事業会社で分析屋、ツール導入屋なのですが、[Google data studio](https://cloud.google.com/data-studio/?hl=ja)を取り入れたら部署の主要ツールになってしまったので、実際に作成したサンプルを元に、出来る事、難しい事を簡単にまとめておきます。

#背景
マーケティング活動分析に必要な情報が、自社開発のツールではなく、GA、Adwords、スプレッドシート、SaaS型CRM、マーケティングオートメーションツールなどと、様々な場所に点在しており、**意思決定や施策PDCAを回すための指標すら把握しづらい**状態でした。

2016年夏あたりからいくつかの[BIツール](https://www.tableau.com/ja-jp)を試していたのですが、知識がないと扱えないため社内浸透せず、困っていた所[Google data studio](https://cloud.google.com/data-studio/?hl=ja)に遭遇しました。

#特徴
企画系、マーケ系の人が大好きなGoogleが提供している[Google analytics](https://www.google.com/intl/ja_jp/analytics/#?modal_active=none)、[スプレッドシート](https://www.google.com/intl/ja_jp/sheets/about/)、手元のcsv、excelファイルに加えて、最近はやりの[BigQuery](https://cloud.google.com/bigquery/?hl=ja)や自社のデータベースにあるデータを取り込んでデータをビジュアライズ化できる無料のサービスです。

#良い点
###**共有が簡単**
- **URLを共有するだけで、ビジュアライズ化された数値がみれる**
    - 都度エクセルにデータを落として、個別であれこれ分析活動しデータを格納or送信する必要無し

###**読み込みが非常に早い**
- **高速で読み込まれるので、トライ&エラーが行い易い**
    - 自社でBIが広まらなかった要因の一つだった、読み込みが遅く手軽に見れないという問題を解決

###**エンジニアでなくても触れる**
- **スプレットシートなども取り込め、パワーポイントのように配置できるので操作も簡単**
    - リアルタイムで更新されていく売上や、販売個数、予約数などを、スプレットシートで多人数で同時編集、BI化し把握できる

#悪い点
###**GDS側からのクエリ発行・計算不可**
- **元データに対して働きかけることはできない**
    - 自社ではspreadsheetで予め演算子したデータを使用

###**複数データソースのブレンドはできない**
- **元データを、GDS上では統合不可**
    - スプレッドシートとGAのデータを、日付を元に合算してチャート描画などはできない

悪い点を記載しましたが、あくまで既存のデータ、可視化するためだけのツールですので、非エンジニアには扱いやすいと思います。

#実際に作成してみた
BI：[東京23区不動産取引](https://goo.gl/WDwSAL)
加工データ：https://goo.gl/ftiMa9
データ元：[国土交通省_土地総合情報システム](http://www.land.mlit.go.jp/webland/)

加工データがテストにも関わらず、5万行近くレコードがあるのでかなり重いです。。。。


#作成手順
画像UP容量制限で画像をアップできず・・・次回以降で細かく画像付きで残します

[0.レポートの作成] -> [1.データソース追加] ->  [2.グラフを選ぶ] ->  [3.配置していく]

#次回以降
- 作成フローを画像込みで説明([[非エンジニア向け]実例からの！Google Data studio作成編①](https://qiita.com/tskz_49/items/1402c0c620b9ca101daa))
- GoogleAppScriptでkintoneのRESTapiを用いてデータをSpreadSheetに貼り付け
- フィルターや描画で出来ること、出来ないこと整理
Mac にHomebrew で入れたMySQLの自動起動設定

プログラムを起動させる際、MySQLもいちいち起動させなきゃいけない状況←面倒!!

railsを起動時に自動でMySQLを一緒に起動させる

```
$ cd /usr/local/Cellar
mysql
```

ここにmysqlが存在することがわかる

```
$ cp /usr/local/Cellar/mysql/5.7.19/homebrew.mxcl.mysql.plist ~/Library/LaunchAgents/
$ launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist 
```

もしここでMySQLが起動している場合、設定変更によってポートがぶつからないように一度シャットダウンをしておく

```
$ mysqladmin -uroot shutdown
```
起動していなければOK

```
$ launchctl start homebrew.mxcl.mysql
```

最後に確認！

```
$ launchctl list | grep mysql
3763	1	homebrew.mxcl.mysql
```
できた！
Chrome 拡張機能 ー コンテキストメニュー(ContextType/ItemType）

Chrome 拡張機能を作っているのだが、コンテキストメニューに追加するときのオプションがちょっとややこしかったのでメモがてらまとめておく。

コンテキストメニューというのは、右クリックしたときにでてくるやつです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/c4b29d38-19b5-95fd-e825-c9f359233e36.png)

## 使い方
`background.js` 内で次のコードを書く。

`title` がメニューに表示される内容で、`contexts` に `ContextType` を指定する。
`type` に `ItemType` を指定するだけ。

```js
chrome.contextMenus.create({
    title: "コンテキストメニューを追加",
    contexts: ["all"],
    type: "normal",
    onclick: function (info) {
        console.log(info);
    }
});
```

## ContextType
https://developer.chrome.com/apps/contextMenus#type-ContextType

使い方としては２種類あって `contexts` に複数の `ContextType` を指定するか、
`chrome.contextMenus.create`で何個も追加する。

前者の場合は `onclick` イベントの仮引数(info)からイベントを判断する必要がある。
例えば、仮引数に`linkUrl` があるからこれは`link`が選択された状態でコンテキストメニューがクリックされた、とか。

後者の場合は、イベントごとに処理を記述するため判断は不要だが、複数のコンテキストメニューが表示される可能性がある。
例えば `iframe` 内のリンクを右クリックしたら、`all`, `frame`, `selection`, `link` のコンテキストメニューが表示される。

特殊な `ContextType` として `all` は `launcher` を除く、全てのTypeを表している。

 
|Type|Type all|説明|
|:--|:--:|:--|
|page|○|何も選択しない状態で画面上を右クリック|
|frame|○|frame や iframe 内で右クリック|
|selection|○|何か選択した状態で右クリック|
|link|○|aタグ上で右クリック|
|editable|○|編集可能なテキストボックスなどで右クリック|
|image|○|imgタグ上で右クリック|
|video|○|videoタグ上で右クリック|
|audio|○|audioタグ上で右クリック|
|launcher|-|確認できず[^1]|
|browser_action|-|確認できず[^2]|
|page_action|○|ブラウザ右上の拡張機能のアイコンをクリック|

[^1]: chrome://apps/ のランチャーのことかな？
[^2]: page_action と同じみたいだが、無反応だった


## ItemType
https://developer.chrome.com/apps/contextMenus#type-ItemType
コンテキストメニューに選択をつけることができる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/8fb8ea07-6fae-760c-a19b-9e0dd3553ffa.png)

|Type|説明|
|:--|:--|
|未指定(normal)||
|checkbox|複数選択が可能なコンテキストメニュー|
|radio|ひとつだけチェックするコンテキストメニュー|
|sepator|確認できず[^3]|

[^3]: radio と同じみたいだが、無反応だった
SmartGit > Repositoriesペイン > asterisk付き > Favoriteフラグ

```txt:動作環境
Windows 7 Pro (32bit)
SmartGit Version 17.0.5 #10143
```

Repositoriesペインにおいてリポジトリはアルファベット順に表示される。
その順番よりも上にくるリポジトリがいくつかあった。
共通事項として緑色の「*」が付いていること。

以下に説明があった。
http://www.syntevo.com/doc/display/SG/Repository-Related
> Repositories can be marked as favorite using the Mark as Favorite (Unmark as Favorite). Favorite repositories are indicated **with an asterisk** after the name and are sorted before groups which are sorted before non-favorite repositories. 

Favoriteフラグが付いているようだ。

Favoriteフラグは以下の手順で設定(および解除)できる。

1. Repositoriesペインの任意のリポジトリ上で右クリック
2. 「Mark as Favorite」を選択
    - 解除時は「Unmark as Favorite」
Jenkins Decrarative PipelineでJenkins Pluginを呼び出す

# はじめに

Jenkins Organization Folder Pluginができたことで、Gitのリポジトリ単位でJobを作っていく必要がなくなりました。ですが、そのためにはそれまでのGUIからのJob設定ではなくGroovyベースのDSLによるPipleline記述が必要になります。
また、Pipeline記述もScripted PipelineとDecrarative Pipelineの二つがあり、Decrarative Pipelineが推奨となっているようですが残念なことに[公式ドキュメント](https://jenkins.io/doc/book/pipeline/syntax/#declarative-pipeline)を見てもわからないことがあったりします。
(もしかしたら自分の調べ方が足りないだけかもしれませんが)

# 記述方法

記述方法は以下のようになります。

```groovy
step ([$class: '{Pluginの実行クラスの完全修飾名}',
        {引数名}: '{引数}', {引数名}: '{引数}'… 
])
```

# 記述例

Scala向けコードカバレッジリポートを行う[Jenkins scoverage plugin](https://github.com/jenkinsci/scoverage-plugin) を呼び出してみます。

```groovy
                stage('coveragereporting'){
                        agent { label 'master' }
                        steps {
                                step ([$class: 'org.jenkinsci.plugins.scoverage.ScoveragePublisher',
                                        reportDir: 'target/scala-2.12/scoverage-report',
                                        reportFile: 'scoverage.xml'
                                ])
                        }
                }
```

## 実行クラスおよび引数の調べ方

Jenkinsfileに記述する際、GUIで編集していた時には意識しなかったPluginのクラス名と引数名を把握する必要があります。
実行クラス名は、対象PlugingのGithubなどでソースを参照し、`hudson.tasks.Recorder`を継承しているクラスを探します。この辺りはPluginの種類によりことなる可能性があるので、Plugin開発のガイドをみるのがよいでしょう。
引数は実行クラスのコンストラクタの引数を参照します。例であげている scoverage-pluginだと `org.jenkinsci.plugins.scoverage.ScoveragePublisher`の以下が相当します。

```Java
    @DataBoundConstructor
    public ScoveragePublisher(String reportDir, String reportFile) {
        this.reportDir = reportDir;
        this.reportFile = reportFile;
    }
```

# おわりに

Jenknins Declarative Pipelineで処理を書くにはまだ情報が不足している気がしますが、今後はこちらがメインになっていくようなのでいまから触っておいて損はないはずです。
GUIともScripted Pipelineとも異なることが多く戸惑うこともあるでしょうが、是非ノウハウを共有して楽をしていきましょう。
atomコマンドが見つからない時の対処法

突然`atom`コマンドがいなくなりました。
びっくりです:dizzy_face:

```
$ atom .
-bash: atom: command not found
```

Atomをスポットライトなどで起動して、メニューから`シェルコマンドをインストール`を選択したら復活しました。

![スクリーンショット 2017-09-25 13.34.27.png](https://qiita-image-store.s3.amazonaws.com/0/74602/e6ce5f6e-181f-2755-b7e8-1047915aef22.png)
npmでmongodbとサーバーを同時起動

mongodbを起動するのがめんどくさい。
サービス登録しておけよって話はおいといて、同時に起動したかった。

## やってみた

必要なのは`concurrently`モジュール

```bat
npm install concurrently --save 
```

サンプルとしてサーバ側はこんな感じ

```js:server.js
var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('server start!\n');
}).listen(3000, '127.0.0.1');
```

package.jsonのスクリプトでこんな風に記述すればOK

```json:package.json
{
  "name": "testApp",
  "main": "index.js",
  "scripts": {
    "start": "concurrently  \"mongod --dbpath ./data --logpath ./log/log.txt\" \"node server.js\" "
  },
  "dependencies": {
    "concurrently": "^3.5.0"
  }
}
```

`npm start`を実行するとmongoとサーバが立ち上がる。
ざっくばらんメモ_7：kaggle、ベンフォードの法則、他者の学習規則の学習


###kaggle zillow challenge
前回出したresnetの結果をアンサンブル予測のなかに組み込んで
予測を行ってみる．
ー結果，0.0657365で改善ならず．
　resnetはアンサンブルしない方が良い事になってしまった．
　もう少しresnetの学習を続けてみて，再トライする．結果0.0657484でほぼ変わらず

###[Let’s See Your Digits: Anomalous-State Detection using Benford’s Law](http://www.kdd.org/kdd2017/papers/view/lets-see-your-digits-anomalous-state-detection-using-benfords-law), kdd2017
ベンフォードの法則は自然に生てくる数字の発生頻度がある決まった法則に従う事を示す理論である。
本論では、その事実を最近のWebサービスであるWikipediaやTwitter、GitHubなどに対して成り立つ事をまず示す。
そしてこの事を利用して、ベンフォードの法則から外れた事象を異常として検知するシステムを提案している。
ベンフォードの法則自体は昔からある法則で、これから外れた事象を異常として検知する考え方も昔から
存在したが、それをWebサービス（ビックデータ？）へ適用可能な形に構築し、かつそれがしっかりと
働く事を示したという点で新規性があるのかもしれない。

###[Learning to Model Other Minds](https://blog.openai.com/learning-to-model-other-minds/)
マルチエージェントシステム的な設定を考えた時に，
他者の存在を考慮に入れて学習を行うようにする手法は
すでに提案されてきているが，本論では特に，
他者もまた学習している事までを考慮に入れて，
効率よく自分の目的を最大限達成しつつ他者との協調を行えるようにしている．
この事が重要な理由は，この設定は最近注目されている分野である
Multi agent reinforcement learning, hierarchical reinforcement learning (learning to learnも
含まれる？), adversarial net等，複数ある目的関数を同時に最適化するタスク全てに
適用可能だからである．
ここで提案されているエージェントは他者がどのようなpolicyを持ちパラメータ更新を行うかを
モデル化し，他者のpolicy及びlearning stepへどのように影響を及ぼしていけば，
最終的に自己のrewardを最大化できるかを考慮に入れる事が可能になる．
これにより，従来の他者を考慮に入れない同時最適化では到達出来ない
ナッシュ均衡を実現していく事が可能になる．
macOSでのSublimeとRubyMine | Intellij IDEA with Ruby pluginのショートカット対応表

#前提
SublimeとRubyMineまたはIntellij IDEA with Ruby Pluginを両方使うとき、よく使うショートカットがごっちゃになりがちなのでまとめました。

#表
| 動作       |       Sublime | RubyMine / IntelliJ IDEA |
|-----------------|------------------|------------------|
| Lineを選択     |  Command L |    Command C      |
| 複数Lineを選択     |  Command Lを複数回 | Option Command Shift ] or [ (Select till code block end / start)　またはOption Up/Down (Select successively increasing code blocks) またはShift Up/Downが近い  |
| カーソルのある単語を連続で選択|   Command D　　(スキップ：Command K) |   Control G　(戻る: Control Shift G)      |
|Lineを複製|Command Shift D|Command D|
|複数カーソルの使用|Command Click|Option Click|
|ファイルネームで検索|Command P|Command O|
|選択箇所を上下移動|Command Control Up/Down|Command Shift Up/Down|

#RubyMineのみ
| 動作 |       Sublime |　　　　　　　　　　　　RubyMine    | リンク |
|---|---|---|---|
| <%= %>を挿入 | 'pe' tab | Shift Command Period | https://stackoverflow.com/questions/9638895/rubymine-shortcut-to-insert |

#資料
[ Sublime Text Unofficial Documentation Keyboard Shortcuts - OSX](http://docs.sublimetext.info/en/latest/reference/keyboard_shortcuts_osx.html)
[RubyMine Reference Card Mac pdf file](https://resources.jetbrains.com/storage/products/rubymine/docs/RubyMine_ReferenceCard_mac.pdf)
[What’s Mining: Multiple Cursors and Selection](https://blog.jetbrains.com/ruby/2014/03/whats-mining-multiple-cursors-and-selection/)
[No need to select a line to copy/cut it. Cmd-C / Ctrl+C & Cmd-Х / Ctrl+X work for the current line #IDEtip](https://twitter.com/rubymine/status/221226996074692608)
[【翻訳】絶対見逃せない！RubyMineのショートカット10選](https://qiita.com/jnchito/items/6eda2cd54038ffa829ef)
[RubyMine Cheat Sheet](https://www.shortcutfoo.com/app/dojos/rubymine-mac/cheatsheet)
[12 IntelliJ IDEA Keyboard Shortcuts You Should Know About](https://moduscreate.com/12-intellij-idea-keyboard-shortcuts/)
[RubyMine アドベントカレンダー 2014](https://qiita.com/advent-calendar/2014/rubymine)
[Rubymine(Jetbrains系IDE)のショートカットのメモ](https://qiita.com/high5/items/dfd20b880e0f5cd51daa)
[RubyMine Tips](https://qiita.com/HirokiTakaba/items/700a46409ece49aa0d4b)
[Rubymine / IntelliJ Ideaの導入＆プラグイン＆設定](https://qiita.com/ogontaro/items/67e7fa83fbea873270d4)
[知らないと損?RubyMine(IntelliJ)で役立つ細かいテクニック７つ](https://qiita.com/Avene/items/756c17f87d28d2ee47a4)
カンマ演算子という厄介者（？）

JavaScriptにはカンマ演算子 `,` という演算子があります。配列やオブジェクト、関数の引数などの区切り記号としてのカンマとは異なるものです。
この演算子の特性を知っておかないと思わぬ落とし穴があるかもしれません。

[カンマ演算子 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Comma_Operator)

#カンマ演算子の性質

カンマ演算子は左のオペランド（被演算子、簡単に言えば変数や関数といったまとまり）から右へ順に 評価（実行・処理）していく演算子で、**最後（右端）のオペランドの結果を返します**。

```js
// このカンマはただの区切り
const
  FOO = 'foo',
  BAR = 'bar',
  BAZ = 'baz';

// 区切りと区別するために括弧で囲む
let result = (FOO, BAR, BAZ);
console.log(result);  // baz

// 関数の引数で使う場合は引数の区切りと区別するために括弧で囲む
console.log((FOO, BAZ, BAR));  // bar

// このように書くと代入処理が優先される
result = FOO, BAR, BAZ;
console.log(result);  // foo

// このように書くとカンマ演算子が優先される
result = (FOO, BAR, BAZ);
console.log(result);  // baz
```

なんかややこしい

#カンマ演算子が多分役に立つところ

`for` 文とかでたまーに役に立つときもあるかもしれません。

```js:forを使って配列をマージするやつ
const
  ABCD = ['a', 'b', 'c', 'd'],
  EFGH = ['e', 'f', 'g', 'h'];

let i, j;

for (i = ABCD.length, j = 0; j < EFGH.length; i++, j++) {
  ABCD[i] = EFGH[j];
}

console.log(ABCD);
// ["a", "b", "c", "d", "e", "f", "g", "h"]
```

いい例が思いつかずにこんな回りくどい例ですが、`i = abcd.length, j = 0;` と `i++, j++` の部分の `,` がカンマ演算子です。
他にもいい例があるかもしれない。

#カンマ演算子はややこしい

例えばこれはどうでしょう。

```js
const
  FOO = 'foo',
  BAR = 'bar';

let temp;

function fooBar(arg1, arg2) {
  return arg1, arg2;
}

if (FOO === 'foo', BAR === 'foo') {
  console.log('1');
}

if (BAR === 'foo', FOO === 'foo') {
  console.log('2');
}

if (fooBar(FOO, BAR) === fooBar((FOO, BAR))) {
  console.log('3');
}

switch (FOO) {
  case 'foo', 'bar':
    console.log('4');
    break;

  case 'bar', 'foo':
    console.log('5');
    break;

  default:
    console.log('6');
}

temp = '';
if (temp = FOO, BAR, temp === 'foo') {
  console.log('7');
}

temp = '';
if (temp = (FOO, BAR), temp === 'foo') {
  console.log('8');
}

temp = '';
if ((temp = FOO, BAR), temp === 'foo') {
  console.log('9');
}
```


結果は

```text
2
5
7
9
```

最後（右端）のオペランドの結果を返すことを考えると簡単ですが、一見とてもわかりづらい。
配列や関数などで使うとただの区切り文字なのかそうでないのかの区別がつきにくいですね。

---

カンマ演算子って微妙な立ち位置ですが、JavaScriptのコード圧縮で活躍するぐらいでしょうか。
エンジニアを名乗るなら、いつでも転職できるようにしておこう

# TL; DR
- 転機はいつも突然やってくる
- 職務経歴書とGitHubは常に更新しておけ
- より良いエンジニアライフ(開発環境や、お賃金)を追求しよう

# 背景
## まずはじめに、クビになった
　実際にはクビ(懲戒解雇)ではないので、釣り見出しである。30歳でエンジニアにジョブチェンジして、かつ未経験なのにベンチャーに入ったら、1年ちょっとで会社都合の退職となった。後述の通り、別の会社から満足な条件で内定はもらえたものの、売り手市場な今でも一社からしかもらえなかったので、転職活動でやったこと・在職時にやっておけばよかったことをまとめておく。

## 突然の発表〜会社訪問
　"今週はこの機能を作って〜"なんて考えていた6月第1週、(一応全社向けだったけど)主に開発部やデザイン部に向けて、突然会社から早期優遇退職プログラムが発表された。開発部の部長も知らなかったという、正に青天の霹靂である。会社に残ってもエンジニアとしては活動できないと説明されたため、退職を決断。2ヶ月の特別有給を取得し、7月末まで在籍しながら休暇を貰った。ここまでで、たった2日の出来事である。
　そこから、後述の通り、1ヶ月は技術向上のための勉強、paizaやWantedly使って会社検索&アポ取りに2週間充て、会社訪問したのは7月下旬だった。地方から東京への転職を考えていたため、1日2〜3社訪問した。実際に訪問してみると、めっちゃ志望度高まった企業もあれば、意外と下がった企業もあった。やはり実際に目にしてみると違うので、興味あれば会社訪問したほうが良い。

## 選考開始〜内定受諾
　8月から本格的に選考開始。元々Wantedlyやpaizaで見つけた会社が少なかったのと、実際に選考に進めた企業も少なかったので、ビズリーチを使い始める。スカウト来るの、超楽だわー。
　この頃から廃人化し始める。どうも作業がペンディングすると、自分は思考停止するようだ。選考結果が出るまで、ツイッターをして、(エロ)動画見て、昼寝したら1日が終わってた。ニートみたい。
　そんなこんなで、お盆あたりに内定出た。給与もめっちゃ上がった(元が低すぎたという面もある)。選考中は聞けなかったこともあったので、お返事は少し待ってもらって、他社選考も進めながら、もう一度会社訪問した。
　んで8月末に内定受諾。9月にお引越しして、10月から働くことになりましたとさ。定時で働けるようにリハビリ中。

# やってよかったこと
## 技術向上のための勉強
　前職ではRails触ってたんですが、テストを全く書いてなかったので、その他の復習も兼ねて、未経験時に一度触って挫折した[rails tutorial](https://railstutorial.jp/)をこなしてみた。Rails経験は半年くらい(もう半年はSinatraだった)だけど、未経験でやってた頃と比べたら格段に分かりやすかった。ただ、理解度が格段に向上した今でも、2週間〜1ヶ月はかかった。
　サービスの現物を作れる教材って良いなーと思いました。今後自分も何かの言語・フレームワークでこういう教材を一つ作ってみたい。

# 在職中にやっておけばよかったこと
## 職務経歴書の作成
　意外なんだけど、職務経歴書はマジでさっさと作っておいたほうが良いし、頻繁に更新したほうが良い。プロジェクトのことってすぐ忘れるんだよね。どういう技術を使っていたかとか、そもそも何故そういう設計にしたかとか、俯瞰してみると変な部分って結構ある。今の設計になっているということはきちんと背景があるってことで、それを説明できないと、「ほんとにチームで開発してたの？」って話になる。詳細を全て書いておく必要はないけど、聞かれたら答えられるようにしておこう。
　「普通チケットに経緯残すでしょ、基本中の基本だぜ！」と思ったあなた、基本中の基本を一つ忘れてるよ。退職したら、会社の開発環境へのアクセス権は剥奪されるんだぜ？アクセス権がある今のうちに作っておくんだ。

## GitHubでコード公開
　まずはじめに聞かれるのは、「GitHubのアカウントを教えてください」だった。100回面接するより、1つのコードのほうが雄弁で有益。「エンジニアの卵でOSS活動はまだ無理だから…」とか思ってアカウントすら作ってなかった。更に言うと前社ではGitLab使ってて、プルリクってよくわからなかった(GitLabでは"マージリクエスト"を使う)ので、社会人インターン行った時はちょっと恥ずかしかった。普段から少しでもコード書いて公開しておくと、面接のウケがぜんぜん違う。OSS活動頑張ろう…。

# 転職活動で利用したもの
- [Wantedly](https://www.wantedly.com/): 上場時になんか騒ぎがあったけど、基本的にはやはり良いサービスだと思うよ。掲載企業さんがほんとに個性豊かで面白い。
- [ビズリーチ](https://www.bizreach.jp/): エージェントからスカウト来るの、ホント楽だった。無い内定の時は会社検索も大変になるから、エージェントから会社紹介してもらえると精神安定に繋がる。ちなみに、営業メールが来すぎることもあるので、自分はプラチナスカウトのみ返事してた。
- [paiza](https://paiza.jp/): paizaのスキルチェック、すごい好きなんだけどねー。Wantedlyよりかは心惹かれる企業さんには巡り会えなかった。今後も頑張って欲しいサイトではある。
- [rails tutorial](https://railstutorial.jp/): Railsエンジニアなら一度はやっておいたほうが良いと思う。
- [ハローワーク](https://www.hellowork.go.jp/): ごめん、職安は使ってない。雇用保険の受給しか使わなかった。

# 最後に
## 大事なのは、お金と時間と開発環境のバランス
　前職の場合、時間と開発環境は良かったんだけど、お金がちょっと残念な感じだった。転職が決まった途端、いろんなデバイスに興味持ち始めて、"ワクワク感"が止まらない。お金があると失敗できるのが良いんだよね。失敗できないとどうしてもリスク取りにいけず、つまらんまま終わってしまうことが多い。
　もうちょっと居たかったなという思いはあるけれど、こういう機会で転職出来て良かったと思ってる。今回転職して一番良かったのは、外に出ることへの抵抗感が無くなったことかな。ツイッターではアカデミックの方やエンジニアの方を多くフォローしているので、「給料足りない」とか「労働時間長い」とか「自分の業務(コーディングや研究)ができない」とかよく自分のTLに流れてるけど、そういう時はどんどん外に出たほうが幸せになれそうな気がする。会社の外、地域の外、国の外、自分の幸せが"内"にない時には、躊躇わず外に出たほうが良さそうだし、常にそういう準備をしておくと良いんだなーと思いました。戦略的なキャリア構築、大事ですね。
引数でlogging のレベルを変更する(Python)

# 本日は

いつまでもプリントデバッグしているとかっこ悪いのでログの取得の勉強をしています。その時のコードの練習

## logging チュートリアルにて
[基本 logging チュートリアル](https://docs.python.jp/3/howto/logging.html#logging-basic-tutorial)

を眺めていて

> ロギングレベルをコマンドラインオプションから次のように設定したいなら:

>
```shell-session
--log=INFO
```
`--log` に渡されたパラメタの値をある変数 `loglevel` に保存すれば:
>
```shell-session
getattr(logging, loglevel.upper())
```
を使い、 `level` 引数を通して `basicConfig()` に渡すべき値を得られます。

の意味が分からなかったので自分なりに実装してみました。　
神はおっしゃった。引数は　`argparse` で渡せと。

## 実装例

```py3
#setloglv.py
import logging
import argparse

# assuming loglevel is bound to the string value obtained from the
# command line argument. Convert to upper case to allow the user to
# specify --log=DEBUG or --log=debug
LOG_LEVEL = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'CRITICAL']
USER_CHOICE = LOG_LEVEL+list(map(lambda w: w.lower(), LOG_LEVEL))


def set_parser_args(parser):
    parser.add_argument("--log", help='set log level',
                        choices=USER_CHOICE,
                        default="WARN")


def parse_arguments():
    parser = argparse.ArgumentParser()
    set_parser_args(parser)
    return parser.parse_args()


def main():
    args = parse_arguments()
    # parse log level
    numeric_level = getattr(logging, args.log.upper(), None)
    if not isinstance(numeric_level, int):
        raise ValueError('Invalid log level: %s' % loglevel)
    logging.basicConfig(level=numeric_level)
    
    logger = logging.getLogger(__name__)
    # code
    logger.debug('debug message')
    logger.info('info message')
    logger.warn('warn message')
    logger.error('error message')
    logger.critical('critical message')

if __name__ == '__main__':
    main()
```

#実行例
(Windows 10 Pro, Python3)

```shell-session
$ python setloglv.py --log info
INFO:__main__:info message
WARNING:__main__:warn message
ERROR:__main__:error message
CRITICAL:__main__:critical message
```

```shell-session
$ python setloglv.py --log DEBUG
DEBUG:__main__:debug message
INFO:__main__:info message
WARNING:__main__:warn message
ERROR:__main__:error message
CRITICAL:__main__:critical message
```
Azureのデータサイエンス仮想マシンを立ち上げてCNTKを試してみる

Azureのデータサイエンス仮想マシンの立ち上げを行い、仮想マシン上のjupyter notebookでCNTKのサンプルコードを動かしてみたので、その手順を掲載します。

##1. データサイエンス仮想マシンの概要
Azureの[データサイエンス用仮想マシン](https://docs.microsoft.com/ja-jp/azure/machine-learning/machine-learning-data-science-virtual-machine-overview)は、データ分析／機械学習の主要ツールがプレインストールされているVMイメージです。特に、GPUベースのインスタンスには、Deep Learning関係のツールがあらかじめ入っている[^1]ため、手っ取り早くDeep Learningに触れることができます。

[^1]: CUDAやCuDNNに加えて、Tensorflow、CNTK、Caffeなどがインストールされている

##2. データサイエンス仮想マシンの立ち上げ方法
今回はGPUを使ったDeep Learningの計算を試してみたいので、
GPU仮想マシン（Azure NシリーズのNC仮想マシン）を立ち上げてみます。

### 2.0 仮想マシン設定までの手順
(1) Azureのアカウントを作成して、Azureポータルにログイン
(2)「新規」メニュー ⇒ 検索バーに「Data Science Virtual Machine for Linux (Ubuntu)」と入力して選択
(3)「作成」をクリック
<img src="https://qiita-image-store.s3.amazonaws.com/0/203977/d17d1e8c-819e-75c4-371f-868b74ad6c0b.png", width=80%>

以降から、仮想マシンの設定に入ります。

###2.1 基本設定の構成
仮想マシンの名前や、仮想マシンへのログインに必要となるユーザー名、パスワードを設定します。
「VMディスクの種類」では、**HDD**を選択します。[^2]
「場所」では、NC仮想マシンが利用可能な米国東部を選択します。[リージョン別の利用可能な製品](https://azure.microsoft.com/ja-jp/regions/services/) 
<img src="https://qiita-image-store.s3.amazonaws.com/0/203977/65bb52ab-aa93-eb56-6699-5141168b34c5.png", width=80%>

[^2]: SSDにするとNC仮想マシンを選択できない

###2.2 仮想マシンのサイズ選択
「すべて表示」をクリックすると、Nシリーズの仮想マシンも表示されます。
今回はお試しで動かすだけなので、NC6 Standardを選択します。[Azure Nシリーズの主要スペック](https://blogs.technet.microsoft.com/jpitpro/2016/11/22/azure-n-series-general-availability-on-december-1/)
<img src="https://qiita-image-store.s3.amazonaws.com/0/203977/8aebe08f-4c9d-6320-06f5-992fd71eda9d.png", width=80%>

###2.3 オプション機能の構成
「パブリックIPアドレス」で、静的を選択します。
それ以外はデフォルトの設定にします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/203977/f6d2dcc4-7ed8-3c67-f697-7cc13666a914.png", width=50%>

###2.4 購入
最後に「作成」をクリックすると、仮想マシンの構築が開始されます。

##3. jupyter notebookの起動
データサイエンス仮想マシンでは、jupyter notebook及びjupyterhubがデフォルトで起動しており、
仮想マシンを構築した後すぐに、リモートでjupyter notebookを立ち上げることができます。

(1) ローカルPCのWebブラウザで、__https://xxx:8000/__と検索（xxxは作成した仮想マシンのパブリックIPアドレス）
(2) 2.1で設定したユーザー名とパスワードを入力して、jupyterhubにサインイン
(3)「Start My Server」を選択

##4. CNTKのサンプルコードを動かしてみる
jupyter notebookのホームディレクトリ下には、仮想マシンにプリインストールされているDeep Learningライブラリのサンプルコードが置いてあります。今回はCNTKのサンプルコードを動かしてみます。

(1) CNTKディレクトリに移動し、CNTK_106A_LSTM_Timeseries_with_Simulated_Data.ipynbをクリック
(2)「Cell」タブの「Run All」をクリック
全てのセルで、問題なく出力されていることを確認できました。
<img src="https://qiita-image-store.s3.amazonaws.com/0/203977/77f571c3-3e2b-e353-3d93-a59e150e760e.png", width=70%>

**以上**

## 脚注
Chromeで意図しないリダイレクトが起きた場合の対処

# 起きた現象と経緯
Chromeでメンテナンス画面表示のテストを行っていたところ、下記の現象が発生した。

1. メンテナンスモードに切り替える
1. 該当URLにアクセスしてメンテナンス画面をリダイレクト表示
1. メンテナンスモードを解除
1. 該当URLにアクセスすると、**メンテナンスモード解除済みであるにも関わらず、なぜかメンテナンス画面にリダイレクトされてしまう**


現象発生時、nginx.confで下記例のようなメンテナンス画面転送の設定がされている状況。

```
〜省略〜

geo $allow_ip {
    default 0;
    XXX.XXX.XXX.XXX 1;
}

server {
    listen      80;
    server_name hogehoge.hogehoge.jp;
    charset     utf-8;
    access_log  /etc/log/hoge.log ltsv;
    error_log   /etc/log/hoge-error.log warn;
    rewrite_log on;
    client_body_temp_path /tmp;
    client_max_body_size 75M;
    client_body_buffer_size 64k;

〜省略〜

    location / {
       if ($allow_ip) {
           break;
       }
       if (-f "/tmp/maintenance") {
           # メンテナンスのtmpファイルがある場合、301リダイレクト
           rewrite ^(.*)$ http://maintenance.hoge.jp? permanent;
       }

〜省略〜

    }
}
```

# 原因
上記のnginxの設定では、メンテナンス画面の表示に301リダイレクトを用いているが、Chromeは301リダイレクトのキャッシュを保持する仕様のため、キャッシュを読み取りメンテナンス画面にアクセスしてしまう動作になっていた。

# リダイレクトキャッシュの削除方法
1. Chromeのdevelopertoolを開き、networkタブの「Disable cache」をチェックする
1. 該当のURLにアクセスする(リダイレクトされず正しく表示される)
1. Chromeのdevtoolを開き、networkタブの「Disable cache」のチェックをはずす(はずしておかないとキャッシュ動作が一般ユーザー同等じゃなくなるので)

# 補足
* Chrome以外はリダイレクトキャッシュしていないようなので、この現象は起きない
* メンテナンス画面表示にはリダイレクトを用いずに503エラーを返しつつメンテナンス画面表示をするのがベターなようなので、そうしたほうがいいと思います(ページが移動したというわけではないので、リダイレクトは不適切だった)
EC2 へ fish-shell インストール

> » 良くわからないけどできた感じなので、他にもっといい方法有ると思う。

## LinuxBrew インストール

homebrewのlinux版みたいなものらしい。これを叩く。

```bash
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install)"
```

>
> ```bash:ログ
> ==> Installation successful!
> # ...
> Warning: /home/linuxbrew/.linuxbrew/bin is not in your PATH.
```

（パス通すか）これでコマンドが使えます。

```bash
/home/linuxbrew/.linuxbrew/bin/brew 
```

## Fish インストール

homebrewと一緒ですね。

```bash
/home/linuxbrew/.linuxbrew/bin/brew install fish
```

>
> ```bash:ログ
==> Caveats
You will need to add:
  /home/linuxbrew/.linuxbrew/bin/fish
to /etc/shells.
>
Then run:
  chsh -s /home/linuxbrew/.linuxbrew/bin/fish
to make fish your default shell.
>
==> Summary
🍺  /home/linuxbrew/.linuxbrew/Cellar/fish/2.6.0: 896 files, 48.3MB
```

## /etc/shells へ追記

```bash
sudo vim /etc/shells
```

で、`/home/linuxbrew/.linuxbrew/bin/fish`を一番最後の行に追加します。

> #### こんな感じになる
> 
> ```txt:/etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/bin/dash
/home/linuxbrew/.linuxbrew/bin/fish
```

## デフォルトシェル変更

ユーザー名は好きな名前で、`chsh`します。

```bash
sudo chsh -s /home/linuxbrew/.linuxbrew/bin/fish ec2-user
```

## 確認

一旦`ssh`を入り直して、`$SHELL`がちゃんと変ったらOK。

```bash
ec2-user@ip-x-x-x-x ~> echo $SHELL
/home/linuxbrew/.linuxbrew/bin/fish
```

---

ただやっぱり、linuxbrewでインストールしたコマンドを使いやすくするために`config.fish`ではパスを追加した方がいいかも。

```bash
vim ~/.config/fish/config.fish
```

```bash:~/.config/fish/config.fish
set -gx PATH /home/linuxbrew/.linuxbrew/bin $PATH
```
CentOS6のPythonを2系から3系にする

CentOSの6系のPythonを2系から3系(3.5)にしたかったのだが、
若干はまったのでメモ


` yum install -y python35u python35u-libs python35u-devel python35u-pip
`

しようとしたら、yumがうごかなくなった


1 /etc/yum.repos.d/epel.repoを直す
`#baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch`

↓

`baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch`



2 sed ~ をやる
`sed -i 's/enabled=1/enabled=0/g' /etc/yum.repos.d/epel.repo`
`sed -i "s/mirrorlist=https/mirrorlist=http/" /etc/yum.repos.d/epel.repo`



3 パッケージのインストール
` yum install -y https://centos6.iuscommunity.org/ius-release.rpm`

4 必要なもののインストール
`yum install -y python35u python35u-libs python35u-devel python35u-pip`


3系のインストールができた。
`python3.5 -V`
 `Python 3.5.2`



##参考にしたURL
1. http://d.hatena.ne.jp/C_6B4A2B/20130427/1367073209
2. http://qiita.com/kyrya/items/d3a4cba0ff2aa9a4a402
3. http://qiita.com/f-akazawa/items/5ec741f8a5cca999d7b3
4. https://weblabo.oscasierra.net/python3-centos7-yum-install/
手元のコードをサクッと Gist にアップロードするための Ruby/Python スクリプト

# Ruby スクリプト

```upload_to_gist.rb
require 'json'
require 'net/http'

# 環境変数 GITHUB_USERNAME に GitHub のユーザ名を設定しておく。
username = ENV['GITHUB_USERNAME']
# 環境変数 GITHUB_PASSWORD に GitHub のパスワードを設定しておく。
password = ENV['GITHUB_PASSWORD']
# コマンドライン引数の第 1 引数にアップロードするファイルのパスを指定する。
filepath = ARGV[0]

content = File.read(filepath)
filename = File.basename(filepath)

uri = URI.parse('https://api.github.com/gists')

request = Net::HTTP::Post.new(uri.path, { 'Content-Type' => 'application/json' })
request.basic_auth(username, password)
request.body = {
  # private でアップロードする。public でアップロードしたい場合は true を指定する。
  public: false,
  files: {
    filename => { content: content }
  }
}.to_json

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

response = http.request(request)
body = JSON.parse(response.body)

puts("#{filename} を #{body['html_url']} にアップロードしました。")
```

# Python スクリプト

```upload_to_gist.py
from requests.auth import HTTPBasicAuth  # pip install requests
import json
import os
import requests
import sys


# 環境変数 GITHUB_USERNAME に GitHub のユーザ名を設定しておく。
username = os.getenv('GITHUB_USERNAME')
# 環境変数 GITHUB_PASSWORD に GitHub のパスワードを設定しておく。
password = os.getenv('GITHUB_PASSWORD')
# コマンドライン引数の第 1 引数にアップロードするファイルのパスを指定する。
filepath = sys.argv[1]

content = open(filepath, 'r').read()
filename = os.path.basename(filepath)

payload = {'files': {filename: {'content': content}}}
response = requests.post('https://api.github.com/gists',
                         data=json.dumps(payload),
                         auth=HTTPBasicAuth(username, password))
body = response.json()
url = body['html_url']

print(f'{filename} を {url} にアップロードしました。')
```

# 使用例

上記の Ruby スクリプト自身を Gist にアップロードする。

```
$ ruby upload_to_gist.rb upload_to_gist.rb
upload_to_gist.rb を https://gist.github.com/f98fdcbf58539da7f2df69be0cb3bb35 にアップロードしました。
```

表示された URL にアクセスすると

![gist.github.com-quanon-f98fdcbf58539da7f2df69be0cb3bb35(Laptop with MDPI screen).png](https://qiita-image-store.s3.amazonaws.com/0/6697/a6a2ed5f-13be-fbd4-581f-c009795189be.png)

アップロードできてる :tada:

同様に Python スクリプトも試してみる。

```
$ python upload_to_gist.py upload_to_gist.py
upload_to_gist.py を https://gist.github.com/bc874dc72d0f9a6f2c92c494fc8e04ed にアップロードしました。
```

表示された URL にアクセスすると

![gist.github.com-quanon-bc874dc72d0f9a6f2c92c494fc8e04ed(Laptop with MDPI screen).png](https://qiita-image-store.s3.amazonaws.com/0/6697/fa76ac5b-a749-f487-1e36-41f73da97241.png)

アップロードできてる :confetti_ball:
pyenv利用環境下でnpm installでpython2周りのエラーが出た時

```
> node-gyp rebuild

gyp ERR! configure error 
gyp ERR! stack Error: Command failed: pyenv: python2: command not found
gyp ERR! stack 
gyp ERR! stack The `python2' command exists in these Python versions:
gyp ERR! stack   2.7.9
gyp ERR! stack 
gyp ERR! stack 
gyp ERR! stack     at ChildProcess.exithandler (child_process.js:637:15)
gyp ERR! stack     at ChildProcess.EventEmitter.emit (events.js:98:17)
gyp ERR! stack     at maybeClose (child_process.js:743:16)
gyp ERR! stack     at Socket.<anonymous> (child_process.js:956:11)
gyp ERR! stack     at Socket.EventEmitter.emit (events.js:95:17)
gyp ERR! stack     at Pipe.close (net.js:465:12)
gyp ERR! System Darwin 16.7.0
```

python2へのPATHが通っていないのが原因らしい。
pyenvで2系、3系のそれぞれをglobalに設定してやれば解決する。

* `python`コマンドで python2系を使いたい場合

```
$ pyenv global 2.7.9 3.4.3
$ python -V
Python 2.7.9
```

* `python`コマンドで python3系を使いたい場合

```
$ pyenv global 3.4.3 2.7.9 
$ python -V
Python 3.4.3
```
dockerでinvalid mode: cachedと言われdocker up できない問題を解決する方法

# 問題点：invalid mode: cached と言われる
## docker-compose up -dするとエラー吐く

```
docker-compose up -d
Creating network "projectName_default" with the default driver
Creating volume "projectName_rails_bundle" with default driver
Creating volume "projectName_mysql_sock" with default driver
Creating volume "projectName_redis_data" with default driver
Creating volume "projectName_redis_sock" with default driver
Creating volume "projectName_mysql_data" with default driver
Creating projectName_redis_1 ...
Creating projectName_mysql_1 ...
Creating projectName_redis_1
Creating projectName_mysql_1 ... done
Creating projectName_rails_1 ...
Creating projectName_rails_1 ... error

ERROR: for projectName_rails_1  Cannot create container for service rails: invalid bind mount spec "/Users/user/Documents/ProjectName/ProjectName-new:/ProjectName-new:cached": invalid mode: cached

ERROR: for rails  Cannot create container for service rails: invalid bind mount spec "/Users/user/Documents/ProjectName/ProjectName-new:/ProjectName-new:cached": invalid mode: cached
ERROR: Encountered errors while bringing up the project.
```

## 原因はdockerのバージョン
* dockerのバージョンが低い


## 解決策：docker本体のバージョンアップ機能を用いてバージョンを上げる
cached　モードは、17.04 からの実装なのでdocker本体のバージョンをそれ以上にアプデしましょう。

### 【注意：brew updateは更新が遅いので最新版が入手できない】
* brew updateで更新しようとするとbrewの更新が遅く17.03で最新版です！と言われる。
* 右上にいるくじらさんマークから update　を選択してアプデしましょう
* ターミナルを再起動しましょう
* 再度docker upを行いましょう
Rambox のタブに Backlog を追加して、未読数を表示する


## Rambox とは

http://rambox.pro/

複数のチャットサービスやメールサービスなどを、タブ管理して一つにまとめられるアプリ。同様のアプリに [Franz](http://meetfranz.com/) もありますが、Franz よりも独自URLの追加が簡単だったので私は最近 Rambox に乗り換えました。

[![rambox screenshot](https://raw.githubusercontent.com/saenzramiro/rambox/d269740a76c97537a4cf2095483389abf88d44ed/resources/screenshots/mac.png)](http://rambox.pro/)

## Rambox に Backlog を追加して、タブに未読数を表示する

まずタブにBacklogを追加。サービスを追加するところで `_Custom Service` を選び、対象となるURLを追加するだけです。簡単。

タブに未読数を表示するには、追加したBacklogタブの設定 → `Advanced` → `Custom Code` のところに、以下のスクリプトを貼り付けます。

```
function checkUnread() {
    const e = document.getElementsByClassName('badge--notification');
    updateBadge(e[0].innerHTML.trim());
}

function updateBadge(e) {
    document.title = ( e ? `(${e}) ` : '' ) + originalTitle
}

const originalTitle = document.title;
setInterval(checkUnread, 3000);
```

![スクリーンショット_2017-09-25_11_21_25.png](https://qiita-image-store.s3.amazonaws.com/0/45034/20d1c943-73cc-09c0-f45b-dc12c782f471.png "スクリーンショット_2017-09-25_11_21_25.png")


以上です。

## 補足

- 参考にしたのはオフィシャルの wiki のこのへん  
[Add a Custom Service · saenzramiro/rambox Wiki](https://github.com/saenzramiro/rambox/wiki/Add-a-Custom-Service)
- とりあえず document.title に `(n) タイトル` の形で数字を入れると、タブに反映されるようです。
- 未読数の数字ではなく、丸印をつけたいだけなら `(•) タイトル` と入れるといいっぽい
R Tool for Visual Studioについて Tokyo.Rで紹介しました

Tokyo.R の LTで少しだけR tools for Visual Studioを紹介しました。
※　5分しかないのにコンテンツ作りすぎた汗　次回続きやります。

RStudioを使っている人にわかりやすく、RStudioとの違いについてを中心に書いています。まあ、RTVSを使うにあたって、知っておくことはこのコンテンツ以上にはあまりないと言っていいくらいですね（特筆すべき点がそれほど多くない）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146939/6629d586-fa02-1cbe-c06a-faafb379554a.png)

<iframe src="//www.slideshare.net/slideshow/embed_code/key/kuqAExPPFj9Jov" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/omasutani/r-tools-for-vsual-studio" title="R tools for Vsual Studio" target="_blank">R tools for Vsual Studio</a> </strong> from <strong><a href="https://www.slideshare.net/omasutani" target="_blank">Osamu Masutani</a></strong> </div>

こんどハンズオンとかもできれば良いなと思います。

関連記事：
[Visual Studio 2017 の Data Science WorkloadsとRTVS](https://qiita.com/Masutani/items/a1142389e47c6373b259)
[RTVS で .Rhistoryをgit管理下から外す](https://qiita.com/Masutani/items/2d7a0626f2143a7818f2)
[RTVSでR projectが開けなくなったときの対処方法](https://qiita.com/Masutani/items/cb2b69410ea03e04687e)
node.js + Expressでリクエスト単位でプロキシするにはrequestをpipeするだけで良い

# 概要

"express proxy" で普通に検索すると、express-http-proxyとか、express-request-proxyとか言うパッケージが見つかると思います。ただ、どちらもあるサイトをまるごと別のサイトにプロキシするという目的のために作られていて、キャッシュとかインジェクションの仕組みがあって便利なものの、「あるリクエストをプロキシしたい」というシンプルな用途には向いていません。また、いずれも、URLのエンコードにバグがあって、それで苦労させられたりしました。

最初、上記のパッケージをフォークしていろいろコードをいじっていたのですが、コードを見ていたら、単にリクエスト単位でプロキシをするだけなら、Expressの機能だけで、ものすごく簡単にできるということが分かりました。要するに、requestの結果をresにパイプするだけで、プロキシできるのです。まぁ、言われてみれば、Expressのresponseは、WritableStreamなので、そりゃそうか・・・という感じですが、これを知ったときは、拍子抜けしました。

当然、生のHTTPがそのまま返されるだけなので、レスポンスの加工には向いていませんが、レスポンスの加工が必要ないのなら、これで十分です（その気になれば、テキストレベルでのヘッダーの微調整くらいなら簡単にできる思いますが・・・・）。

# サンプルコード

request側は、基本的には、req.headersをそのまま渡せば良いのですが、hostだけは削除しないといけないようです。セキュリティも考慮すると、 'authorization'と'cookie'も削除するのが妥当でしょう。用途によってはx-forwarded-* の変更（あるいは削除）が必要かもしれません。

```
const request = require('request');

function (req, res, next) {
  const proxyRequestHeaders = Object.assign({}, req.headers);
  for(key of ['host', 'authorization', 'cookie']){
    delete proxyRequestHeaders.headers[key]
  }
  const proxyUrl = 'http://calculated.proxy.url/';
  request({
    url: proxyUrl,
    method: req.method,
    headers: proxyRequestHeaders,
  }).pipe(res);
}

```

# 用途

ちなみに、なんでこんなことをやろうとしたかというと、AWS S3のsignedURLをプロキシで返したかったのです。基本的には、302 redirectで問題ないのですが、後方互換性のためproxyする必要がありました。proxyだと、S3側で、if-none-matchヘッダとかrangeヘッダの処理とか細かいことを全部やってくれるので便利です。
raspiのWifi設定

# はじめに

raspiをセッティングするたびにWifiの設定方法を忘れてしまうので、備忘録を残しておく

## 設定方法

### Wifiアダプタが有効になっているか確認

```
$ iwconfig
```

結果に「wlan0」が含まれていれば有効になってます

### 設定する文字列の生成

```
$ wpa_passphrase ssid password
```

以下のような文字列が生成されます

```
network={
        ssid="xxxxxxxxxxx"
        #psk="xxxxxxxxxxx" 
        psk=xxxxxxxxxxx
}
```

コメントアウトされている部分にはオリジナルのパスワードが書かれているので、削除したほうがセキュリティ上良いでしょうね

### 設定ファイルへの書き込み

wpa_supplicant.confに先ほど作成した文字列を書き込みます

```
$ sudo vim /etc/wpa_supplicant/wpa_supplicant.conf
```

下記のように書き込み、保存します

```
country=GB ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
        ssid="xxxxxxxxxxx"
        psk=xxxxxxxxxxx
}
```

再起動後、「iwconfig」でWifiに接続されているか確認してください
[JupyterNotebook] ノートUI 変更

# 普通のUI

普通のUIです。目が痛くなります。

![1.JPG](https://qiita-image-store.s3.amazonaws.com/0/137182/d0dc8de2-fbb9-df9e-a95e-27579a1fbba2.jpeg)

# UI

[Theme](https://github.com/dunovank/jupyter-themes)

```

# list available themes
# onedork | grade3 | oceans16 | chesterish | monokai | solarizedl | solarizedd
jt -l

# select theme...
jt -t chesterish

# restore default theme
# NOTE: Need to delete browser cache after running jt -r
# If this doesn't work, try starting a new notebook session.
jt -r

# toggle toolbar OFF and notebook name ON
jt -t grade3 -T -N

# set code font to 'Roboto Mono' 12pt
# (see monospace font table below)
jt -t onedork -f roboto -fs 12

# set code font to Fira Mono, 11.5pt
# 3digit font-sizes get converted into float (115-->11.5)
# 2digit font-sizes > 25 get converted into float (85-->8.5)
jt -t solarizedd -f fira -fs 115

# set font/font-size of markdown (text cells) and notebook (interface)
# see sans-serif & serif font tables below
jt -t oceans16 -tf merriserif -tfs 10 -nf ptsans -nfs 13

# adjust cell width (% screen width) and line height
jt -t chesterish -cellw 90% -lineh 170

# or set the cell width in pixels by leaving off the '%' sign
jt -t solarizedl -cellw 860

# fix the container-margins on the intro page (defaults to 'auto')
jt -t monokai -m 200

# adjust cursor width (in px) and make cursor red
# options: b (blue), o (orange), r (red), p (purple), g (green), x (font color)
jt -t oceans16 -cursc r -cursw 5

# choose alternate prompt layout (narrower/no numbers)
jt -t grade3 -altp

# my two go-to styles
# dark
jt -t onedork -fs 95 -altp -tfs 11 -nfs 115 -cellw 88% -T
# light
jt -t grade3 -fs 95 -altp -tfs 11 -nfs 115 -cellw 88% -T

```

# Example 

```
jt -t onedork -f roboto -fs 12
```

# 結果

![2.JPG](https://qiita-image-store.s3.amazonaws.com/0/137182/e4b76438-88c1-c9ad-fbce-63afb42b1ae0.jpeg)
atom + API Blueprint PreviewでAPI仕様書を作成してみる

#atom + API Blueprint Preview環境の構築
API使用をドキュメンテーションする必要があったのですが、エクセルだと面倒なので、[api blueprint](https://apiblueprint.org/)を使用してみようと思います。Mark Down形式ですばやくAPI仕様書を記述可能です。また、さまざまなツールも出回っているので、HTMLやモックを生成したりも可能なようです。編集環境としては、atom と API Blueprint Previewを使用すると便利そうだったのでそれらの環境を構築してみることにします。

##node.jsのインストール
npmを使用するので、node.js環境が無い場合には、まずインストールします。
[こちら](https://nodejs.org/en/download/)から環境にあったものをダウンロードして、インストールしてください。

##python2.7その他のインストール
Visual Studioのライブラリや、Python2.7などもろもろ必要です。ひとつづつ入れても良いのですが、以下のコマンドで簡単にインストールすることができます。
```
npm install --global --production windows-build-tools
```
辛抱強く待てと言われるので待ちましょう。
##aglioのインストール
api blueprint 形式からHTMLに変換するにはaglioというレンダラーを使用します。
以下のコマンドでインストールします。
```
npm install -g aglio
```
##atomのインストール
[atom](https://atom.io/)をダウンロードしてインストールします。
atomを起動してInstall Packageからapi blueprint previewを検索するか、以下のコマンドで api blueprint previewをインストールします。
```
apm install api-blueprint-preview
```
ここでエラーになりましたが、pythonのバージョンが3.5になっていたようです。
他のバージョンのpythonをインストールしている場合には、pathを確認してください。
こちらの環境では、以下の場所にpython2.7がインストールされていたので追加しました。
C:\Users\XXXXX\.windows-build-tools\python27

##動作確認
ためしに[サンプル](https://apiblueprint.org/documentation/examples/01-simplest-api.html)を貼り付けて、Ctrl + Shirt + aを押してみましょう。
このような感じで、プレビューが表示されれば成功です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/117736/d2274146-f451-58f7-9ef4-8c5e4f0672c1.png)

ちなみに、最初はうまくいかず、aglioを入れなおしたらうまくいきました。
何故かプレビューはエラーになることが多く、コマンドで生成したほうが良いかもしれません、、、
```
aglio -i test.apib -o test.html
```
##まとめ
windows環境でatom + api-blueprint-previewの環境を構築してみました。
次回以降で、api blueprintの記述のしかたもまとめてみたいと思います。
MacでインストールせずにJava9を試す

Java9を試したいけど、既存のJava環境を上書きしたくない…。

ということで、 dmg 形式のメディアから pkg 形式のインストーラを取り出して、そこからhomeディレクトリ相当のバイナリを取得してみましょう。

JDKのダウンロードはこちらから。 "Accept License Agreement" をクリックしてダウンロードします。
http://www.oracle.com/technetwork/java/javase/downloads/jdk9-downloads-3848520.html

ダウンロードできたら、 `jdk-9_osx-x64_bin.dmg` をダブルクリックしてマウントします。
続いてpkgを展開します。

```
$ cd /Volumes/JDK\ 9
$ pkgutil --expand JDK\ 9.pkg /path/to/expand
```

`/path/to/expand` は `/tmp/jdk9` などの適当なディレクトリで。（再起動などのタイミングで消したくなければ `/tmp` 以下は使わないで下さい。）

続いて、更にその中の gzip アーカイブを展開します。

```
$ cd /path/to/expand
$ cd jdk9.pkg/
$ tar zxfv Payload
```

成功すれば `Contents/Home` 以下にバイナリが展開されているはずです。
連想配列をコンソールで深い階層の中身も全部表示する

node.jsでサーバーを立てておいて、ブラウザでjavascriptを書く際と同じような感覚で連想配列（オブジェクト）を

```script.js

console.log(obj);

```

って感じで表示しようとすると、配列が２階層以上あるものは

```
{ 
  text: 'aaaa',
  arrayObj: [ Array ]
}
```

このように中身が省略されてしまいます。ブラウザの場合はこのArrayを更に展開できますが、コンソールではできません。

ということで


```script.js
console.log(JSON.stringify(obj,null,'\t'));
```


とすれば

```
{ 
  text: 'aaaa',
  arrayObj:
   [ { text: 'bbb',
       arrayContent: ['a','b','c'] },
     { text: 'ccc',
       arrayContent: ['d','e','f'] },
}
```

という感じに階層が深くても中身が全部表示されるようになりました。

めでたしめでたし。
[ActiveRecord] データベーステーブルのカラム存在チェック方法

## DBのテーブルに特定のカラムが存在するかどうかをRailsのコードで判定したいケース

`ActiveRecord::AttributeMethods`にあるメソッド :arrow_down:

- [attibute_present?](http://railsdoc.com/references/attribute_present%3F)
- [has_arribute?](http://railsdoc.com/references/has_attribute%3F)

二通り存在するが、それぞれインスタンスメソッドとクラスメソッドという違いがある。
（Railsドキュメントではそのへんまでつっこんでいない）

```rb
if User.attribute_present?(:name)
  change
   rename_column :users, :name, :first_name
  end
end
```
なので、↑のコードだとエラーになる。
``` NoMethodError: undefined method `attribute_present?' for #<Class:0x*****>```

上記のようにmigrationで使用したい場合などは当然インスタンス化などしないので、`has_attribute?`を使うことになる。

```rb
if User.has_attribute?(:name)
  change
   rename_column :users, :name, :first_name
  end
end
```
こちらは正常に動作する。
以上。
chat bot をサーバレスで作ってみた　LINE Messaging API × Google Apps Script × DOCOMO API

# はじめに
初めましてちーずです。これから少しずつ投稿しようと思います。

今回はchatbotについてです。
会社で今後chatbotの案件が出てきそうなので予習がてら作ってみることにしました。

参考にさせていただいた記事です。というよりここに書いてあることができるように真似てみただけです。
https://qiita.com/ponjopi/items/913ae7f5b1117cee4860

こんな感じになります。あんまり会話成り立ってないですね。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202688/8256d5fa-be39-3a9f-5c01-3ab821b95e9c.png)

# 使ったもの
- Google Apps Script（GAS）
- LINE Messaging API
- DOCOMO 雑談対話 API

# 手順　サマリ
1. Google Apps Script を準備する
1. LINE Messaging API の申請をする
1. DOCOMO 雑談対話 API の申請をする
1. Google Apps Script でLINEとDOCOMOのAPIを叩く

# 手順　詳細
## Google Apps Script を準備する
驚くほど手間がかからなかった。
1. Googleアカウントを取得する
1. chromeにGoogle Apps Scriptを入れる
1. Google ドライブから「新規」->「その他」->「アプリを追加」でGASを選択

## LINE Messaging API の申請をする
申請はここからします。この時、LINEのアカウントが必要になります。私は普段自分が使っている個人アカウントを使用しました。開発用のアカウントを用意したかったのですが電話番号を複数持っていないので致し方なしです。（facebook連携とかすれば電話番号なくてもLINEアカウントを作れるらしいです）
https://developers.line.me/ja/index.html

![image.png](https://qiita-image-store.s3.amazonaws.com/0/202688/628c39d5-1e27-571f-4b0d-fd61824da375.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/202688/5249866f-9ef2-07d8-8ff3-bc64ae38b132.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/202688/85d4a970-afaf-dbb2-6014-e955762dd770.png)

## DOCOMO 雑談対話 API の申請をする
ここから申請します。
https://dev.smt.docomo.ne.jp/?p=index
（スクショを撮り忘れてて、取ろうと思ったらメンテナンス中で撮れませんでした。気が向いたら追記します。）

## Google Apps Script でLINEとDOCOMOのAPIを叩く
`doPost`でpostを受け取ります。
そして`doPost`関数の中で`UrlFetchApp.fetch`でLINE Messaging APIを呼び出します。
fetchで指定しているURLがLINE Messaging APIのURLです。`https://api.line.me/v2/bot/message/reply`
返信の文言は`getDialogueMessage`で雑談APIを叩いて、返ってきた内容を`response_message`に詰めています。
これでLINEのトークで会話できるようになります。

```js

var CHANNEL_ACCESS_TOKEN = 'LINE DEVELOPERで作成されたアクセストークン';
var DOCOMO_DIALOGUE_APIKEY = 'DOCOMO雑談APIのAPIKEY';

function doPost(e){
  var reply_token = JSON.parse(e.postData.contents).events[0].replyToken;
  if(typeof reply_token === 'undefined'){
    return;
  }
  var user_message = JSON.parse(e.postData.contents).events[0].message.text;
  var response_message = getDialogueMessage(user_message);
  var url = 'https://api.line.me/v2/bot/message/reply';
  UrlFetchApp.fetch(url, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
    },
      'method': 'post',
      'payload': JSON.stringify({
        'replyToken': reply_token,
        'messages': [{
          'type': 'text',
          'text': response_message,
        }],
      }),
    });
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}

function getDialogueMessage(mes) {
  var dialogueUrl = 'https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=' + DOCOMO_DIALOGUE_APIKEY;
  var dialogue_options = {
    't': 20,
    'utt': mes
  };
  var options = {
    'method': 'POST',
    'contentType': 'text/json',
    'payload': JSON.stringify(dialogue_options)
  };
  var response = UrlFetchApp.fetch(dialogueUrl, options);
  var content = JSON.parse(response.getContentText());
  return content.utt;
}
```
AWSのCodeCommitでPermission deniedが出て困った話

AWSのCodeCommitを使ってみたら手順通りした（つもり）なのにエラーが出て怒られた話。

通常の手順等はこちらを見てください。
https://qiita.com/3utama/items/04994efa9a79d7aa36e6

で、今回ハマったのはgit pushとかした時に以下エラーが出ました。

```
$ git push tentatsu master
Enter passphrase for key '/Users/hoge/.ssh/code_commit_key':
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```

あれー？なんでだと思ったら、.ssh/configの指定が間違っていたらしい。

```
Host git-codecommit.*.amazonaws.com
  User 1234567890ABCDEFGHIJK  # SSH Key ID
  IdentityFile ~/.ssh/id_rsa  # 秘密鍵のパス
```

このSSH Key IDというのが勘違いしやすい。
AWSのアカウント名かと思ったら、IAMで見れる以下の赤囲みの部分のことでした。

<img width="1071" alt="スクリーンショット 2017-09-25 9.49.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/42110/098ecae8-a947-7e5f-f441-321f848ee68e.png">