OmniAICreator/Qiita-1.07M huggingface dataset:
Emacsで貼り付けすると~200~201が挿入されてしまう問題

Emacsでペースト(yankでなく)すると何故か先頭に~200、末尾付近に~201が挿入されるようになってしまっていた。
検索すると既知のバグだったようで英語の[StackExchangeの回答](https://emacs.stackexchange.com/questions/28851/how-to-turn-off-bracketed-paste-mode#28864)が見つかった。
日本語の情報が引っかからなかったので日本語で残しておく。

# 解決方法
`M-[`に何かのキーバインドを設定しているならそれを消す。
これだけで直った。
どうも特殊なイベントのためのフック関係で妙な挙動になるらしく、それが原因らしい。

# おわり
私の水晶玉によると、という言い回しが面白かった。
Lightning Network に必要だったらしいSIGHASH_NOINPUT について

## 何に使うのか

Lightning Network、乃至 Bidirectional Payment Channel では、最初に Funding Transaction（あるいは Opening Transaction） と行って、チャネルの参加者二人がそれぞれデポジットを行うようなトランザクションを作成します。詳細は省きますが、Funding Transaction作成以後、それを用いてマイクロペイメントを行います。

Funding Transaction の output は 2-of-2 のマルチシグ（二人共が署名を行わなければ引き出せないようなscript ）を用いているのですが、Funding Transaction に署名をしてブロードキャストしてしまった後、もし２者のどちらかが裏切ればそのBitcoin は永遠に引き出せなく成るという問題があります。そのため、実際には Funding Transaction の output を参照するようなトランザクションを作成します。

しかし、SegWit 以前は、未承認のtransaction output を input として次のトランザクションに参照することはBitcoin のプロトコル上不可能でした。トランザクション展性という問題があったからです。SIGHASH_NOINPUT という新しいSIGHASHを用いれば、txid が改ざんされたとしてもトランザクションの有効性が失われない、ってことで提案されていたそうですが、今やSegWit のお陰でtxid を書き換えられる危険性はなくなったので必要なくなってしまったようです。さらに、SIGHASH_NOINPUTには、アドレスの再利用の際にリスクがあるようです。

## 仕組みについて
情報が英語でも少なすぎてまだわかりません。どこに署名するんだろう。

## 参考

[ほわいとぺーぱー](https://lightning.network/lightning-network-paper.pdf)
Androidのカメラロールはどこか

iOSに比べると、Androidでの写真保存はやや複雑です。色々な場所に保存できるし、MediaStoreへの登録もあります。

しかし「細かいことはいいから一般的な場所に置ければいい」というケースも多いでしょう(シンプルなカメラアプリを作りたい人など)。

「Androidで、iOSでいうカメラロールはどこ？」を調べました。

## Androidにおける、iOSでいうカメラロールはどこか

下記です。

|ユースケース|場所|
|:--|:--|
|カメラで撮影した画像を保存する|Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)|
|アプリで生成した画像を保存する|Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURE)|

## MediaStoreへの登録

AndroidではiOSと違い、写真を保存するときには

1. 写真を保存する
2. MediaStoreに登録する

という二つの手順を踏みます。

Androidでは写真は色々な場所に保存できます。ただ、写真がバラバラの場所にあっては扱いにくいです。そのため、MediaStoreにメタデータを登録することで、それらを一元的に扱えるようになっています。

MediaStoreはMediaScannerで自動登録する仕組みもあるとのことですが、アプリで撮影・生成した画像は能動的に登録することが一般的なようです。

MediaStoreへの登録は、下記の記事が参考になります。

- MediaScannerに登録を依頼する方法
    - https://qiita.com/wasnot/items/ae1e6282d2c33626b604

## その他参考文献

- Android におけるストレージまとめ 
    - http://blog.lciel.jp/blog/2014/02/08/android-about-storage/
- (公式ドキュメント) ファイルを保存する | Android Developers
    - https://developer.android.com/training/basics/data-storage/files.html?hl=ja
- (公式ドキュメント) MediaStore | Android Developers
    - https://developer.android.com/reference/android/provider/MediaStore.html
rails-tutorial 1章、herokuへのデプロイ作業に心を折られる

# 概要

https://railstutorial.jp/chapters/beginning?version=4.2
Railsのチュートリアルの「1.5 デプロイする」で嵌まりまくった。
以下解決までの手順をまとめます。

# 環境

```
ubuntu 16.04

$ ruby -v
ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu]

$ rails -v
rails 4.2.2

$ gem -v
2.5.1
```

# 解決までの手順

## herokuにデプロイした後ブラウザで該当のページを開くと以下のようなエラー

``` 
Application Error

An error occurred in the application and your page could not be served. Please try again in a few moments.

If you are the application owner, check your logs for details.

```

## エラーログを見る

ここからチュートリアルの内容から離れていきます

```shell-session
$ heroku run rails console
...
heroku rescue in spec': Specified 'sqlite3' for database adapter, but the gem is not loaded. Add `gem 'sqlite3'` to your Gemfile
...
```

## config/database.ymlの設定がsqlite3のままになっていたので修正

```yaml:database.yml
production:
  <<: *default
  adapter: postgresql
  database: db/production.pg
```

## 再度アップロードするも別のエラー

```
We're sorry, but something went wrong.
```


## herokuにPostgreSQLを導入し、データベースを作りなおす必要がありました。

```shell-session
$ heroku addons:create heroku-postgresql:hobby-dev
$ heroku run rake db:migrate
Running rake db:migrate on stormy-chamber-94768... up, run.2136 (Free)
   (15.1ms)  CREATE TABLE "schema_migrations" ("version" character varying NOT NULL) 
   (12.8ms)  CREATE UNIQUE INDEX  "unique_schema_migrations" ON "schema_migration
```

## hello, world

人類の勝利。
Xamarin.FormsでAndroid固有の機能にアクセスする

#はじめに
軽い気持ちでXamarinに手を出したら結構詰まったので，忘備録を兼ねて情報共有する．基本的なことすぎるが，意外に時間のかかったところであった．
筆者の環境は
- Windows10
- VisualStudio2017 enterprise
- MonoAndroid,Version=v8.0

#Android固有の機能にアクセスする
##今回アクセスしたい機能
PCL内にあるソースコードから各OSに依存した機能を使いたい場合が多く存在すると思われる．筆者の場合，とりあえず端末が接続しているWifiのSSIDを取得したかった．またAndroidでWifiに関係した情報を取得する際は，Android.Net.Wifi.WifiManagerクラスを使って以下のコードを書けばよい．

```csharp:GetWifiSample.cs
var wifiManager = (WifiManager)Android.App.Application.Context.GetSystemService(Context.WifiService);

//SSIDとBSSIDの取得
var ssid = wifiManager.ConnectionInfo.SSID; 
var bssid = wifiManager.ConnectionInfo.BSSID;

```
このコードでとりあえずはSSIDなどが取得できる（少し整形する必要もある）が，このコードをPCL内に書いても動かない．例えば，hogehoge.xaml.csに上のコードを書いても動かない．

##解決策
PCLのプロジェクト内にインターフェースを作ることによって解決する．
PCL内に適当なクラスを追加（今回はWificonnection.cs）し，以下のようにインターフェースを定義する．

```csharp:Wificonnection.cs
public interface IWificonnection
    {
        //SSIDを取得
        string GetSSID();
    }
```

インターフェースを定義したら，それを実装するためにAndroidのプロジェクトに実装用のクラスを作成する．

```csharp:WifiInfo.cs
using System;
using Android.Content;
using Android.Net.Wifi;
using Xamarin.Forms;

[assembly: Dependency (typeof(SolutionName.Droid.WifiInfo))]
namespace SolutionName.Droid
{
    public class WifiInfo : IWificonnection
    {
        /// <summary>
        /// Get current wifi SSID
        /// </summary>
        /// <returns>returns SSID (if wifi is not available, it returns String.Enpty.)</returns>
        public string GetSSID()
        {
            var wifiManager = (WifiManager)Android.App.Application.Context.GetSystemService(Context.WifiService);

            var ssid = wifiManager.ConnectionInfo.SSID;
            var bssid = wifiManager.ConnectionInfo.BSSID;

            if (!String.IsNullOrEmpty(ssid) && ssid != "<unknown ssid>")
            {
                return ssid.Trim(' ', '"');
            }

            if (!String.IsNullOrEmpty(bssid))
            {
                return bssid.Trim(' ', '"');
            }

            return String.Empty;
        }
    }
}
```

普通にインターフェースを実装しても使えるわけではなく，

```csharp
[assembly: Dependency (typeof(SolutionName.Droid.WifiInfo))]
```

これがないと実際にこの機能を利用をする際に例外を吐くようになる．

最後に，実際にWifiのSSIDを取得するGetSSID()をPCL内で実行する．

```csharp
var ssid = DependencyService.Get<IWificonnection>().GetSSID();
```

DependencyServiceを利用してインターフェースを指定し，実装されたメソッドを実行できるようになる．

#最後に
今回はAndroidでの例だったが，iOSでも同じような手順でできるようである．残念ながら筆者はMacの環境を所持していないのでまだ試せていない．
こんな初歩的なところで詰まってしまう筆者は「Xamarinの世界は深い…」と感じた
Ruby on Railsでメッセンジャーライクな簡易2chビューアを作成してみる Part3

[前回](https://qiita.com/_hrk_o/items/bc0d2a16eb3244d1b5da)の続きです。
前回は特定の板からスレッド一覧を取得するところと、その板のスレッドを開くところまで所までやりました。
今回は板一覧を取得してトップページに表示させようと思います。(:D)rz

## 掲示板のコントローラ・ビューを作成
`$ rails g controller boards index`

## ルーティングを編集
```ruby:routes.rb
Rails.application.routes.draw do
  root 'boards#index'

  get 'subbacks/:subback_server/:subback_id' => 'subbacks#index', constraints: { subback_server: /[^\/]+/ }
  get 'threads/:subback_server/:subback_id/:thread_id' => 'threads#index', constraints: { subback_server: /[^\/]+/ }
end
```
今回から、`:subback_server`もパラメータに入れました。(例: ikura.2ch.sc)
パラメータにドット(.)を使うと、通常のままだとエラーが出るのでconstraintsオプションを付けます。
constraintsの中身は、`{パラメータ名: 許可する文字列を正規表現で}`です。
この場合は、スラッシュ以外を許容することでドットが通るようにしています。

## 掲示板のコントローラを編集
```ruby:boards_controller.rb
class BoardsController < ApplicationController
  def index
    agent = Mechanize.new
    url = 'http://2ch.sc/bbsmenu.html'
    page = agent.get(url)
    html = Nokogiri::HTML(page.body)
    @subbacks = []
    html.css('small a').each do |subback_title|      
      subback_url = subback_title['href'].match('http(s)?://[a-z0-9.]*.2ch.sc/[a-z0-9]+').to_s
      case subback_url
      when '' then
      when 'http://info.2ch.sc/guide' then # 2ch総合案内
      when 'http://sweet.2ch.sc/headline' then # 新着ヘッドライン
      else
        subback_title['href'] = subback_title['href'].sub('http://', '').insert(0, 'subbacks/')
        title = subback_title.to_html
        subback = {title: title}
        @subbacks << subback
      end
    end
  end
end
```
板一覧を取得して、配列@subbacksに板を格納するのですが、
総合案内など板じゃないURLも混ざっているので、一旦subback_urlに正規表現で板形式のURLだけ代入されるようにして、そのURLが板のURLか、または空白かどうかを確認するフィルターをcase文で書いてあります。
ここに`when [URL] then`で付け足していくと、今後板じゃない不要なURLが出てきた時もフィルターできます。

## 板のパーシャルを作成
```haml:_subback.html.haml
.subback
  .subback-title
    = simple_format(subback[:title])
```

## 掲示板のビューを作成
```haml:index.html.haml
.board-header
  %span
    = 'logsock'
.subback-box
  - @subbacks.each do |subback|
    = render 'subback', subback: subback
```

## 掲示板のcssを整える
```scss:boards.scss
.board-header {
  height: 2rem;
  background-color: #777;
  color: #FFF;
  text-align: center;
  line-height: 31px;
  font-weight: bold;
  a {
    font-size: 17px;
  }
}

.subback-box {
  margin: 10px 30px 0;
  padding-bottom: 20px;
  a {
    color: #FFF;
    text-decoration: none;
    &:hover{
      color: #CCC;
    }
  }
}

@media screen and (max-width:1024px){
  .board-header {
    font-size: 13px;
  }
  .subback-box {
    font-size: 12px;
    margin: 0 3px;
    padding-bottom: 0;
  }
}
```

これで掲示板と板とスレッドを閲覧できるようになり、基本的な機能は完成しました！👏
本文内のレスIDへのリンクについては、[こちら](https://qiita.com/_hrk_o/items/fb68b8cf405c4ff4c3ab)を見てみてください。
あとはHerokuを使ってデプロイするのですが、そこはHerokuのデプロイの記事として別で上げようと思います。

## PC版
<img width="813" alt="スクリーンショット 2017-10-14 19.04.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/151736/b8a16808-1ce8-d583-e0fa-a1f160956e4c.png">

## スマホ版
<img width="320" alt="スクリーンショット 2017-10-14 19.04.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/151736/36b57522-2086-02d2-f7b2-f467d661b6e4.png">
フォントサルベージ完了

####Fonts was deleted!!
なんかおかしいなと感じていたのですが、Windows10は、メジャーアップデートを行うときに、Windows\Fontsにあるフォントを削除してしまうようです。
というか、Fontsにあるものを引き継がず、全部新規に書くみたい。

####Changed Font menu
というのは、先日、Windows10をメジャーアップデートしたら、なんとなくフォントメニューの構成が違っているように見えたのです。

####Windows.old
そこで、まだWindows.oldが残っているうちにと思って、Windows.old\WINDOWS\Fontフォルダと、現在のウィンドウズのフォントフォルダを比較してみたところ、60もファイル数が違う。減っている!
これはもう歴然。そこで、ひとつふたつなら手作業と思ったのですが、60をつきあわせるのはたいへんなので、コードを書きました。

```C#
var nowfonts = Directory.GetFiles(@"C:\Windows\Fonts");
var oldfonts = Directory.GetFiles(@"C:\Windows.old\Windows\Fonts")
				.Where(font => !nowfonts.Contains(font.Replace(@"\Windows.old", "")));

string targetfontfolder = @"C:\tmp\Fonts";
foreach (string font in oldfonts)
	File.Copy(font, targetfontfolder + @"\" + Path.GetFileName(font));
```

フォントサルベージ完了。メジャーアップデートに備えて、別フォルダに大切においておくことにしました。
【マメ知識】(改訂版)青空文庫テキストからテキスト解析用の名詞リストを作成する

(2017-10-16改訂)
実は[青空文庫からテキスト解析用のプレーンテキストを入手](https://qiita.com/makaishi2/items/24670d1d822c7711256e)
とこの書込みは続き物シリーズだったのですが、「なんで前処理だけPerlなの」とか「そもそも２つまとめてできるよね」というツッコミが自分から出て、改訂しました。
その結果、すごくシンプルにまとまりましたので、以下の記事を書き直しておきます。

いい品質のプレーンテキストは、なかなかネットでも入手できないものです。
いろいろ調べて[青空文庫](http://www.aozora.gr.jp)にたどり着いたのですが、問題はテキスト型で提供されているデータにはルビの情報も含まれていた点。
そこで、前処理としてルビを含めた余分な情報を取り除いてテキストファイルを作る仕組みを作りました。

また、日本語でテキスト解析を行う場合の次の課題は形態素解析。
こちらに関してはjanomeを形態素解析として使い、名詞のリストを作る簡単なPythonスクリプトを作ってみました。


以下は、Jupiter notebook上のスクリプトになります。
(kokoro.txtが解析対象テキストである前提)

```python
!pip install janome

# 青空文庫からダウンロードした元ファイル(ルビ付き、SJIS)を読み込む
f = open('kokoro.txt')
txt = f.read()
f.close()

# 前処理開始

# SJISコードの文字列をunicode内部表現形式に変換
txt2 = unicode( txt, encoding='SJIS')

# 置換用の関数のimport
import re

# ルビなどの削除
txt2 = re.sub(u'《[^》]+》', '', txt2)
txt2 = re.sub(u'｜', '', txt2)
txt2 = re.sub(u'［.+?］', '', txt2)

# ヘッダ部分の削除
txt2 = re.sub(u'-----[\s\S]*-----', '', txt2)

# フッタ部分の削除
txt2 = re.split(u'底本：',txt2)[0]

# 改行の削除
txt2 = re.sub(u'\n', '', txt2)
txt2 = re.sub(u'\r', '', txt2)

# janomeを使った名詞リストの作成
word_list = []
from janome.tokenizer import Tokenizer
t = Tokenizer()
for token in t.tokenize(txt2, stream=True):
    partOfSpeech = token.part_of_speech.split(',')[0]
    if partOfSpeech == u'名詞':
        word_list.append(token.surface)
print '===='
print word_list[0]
print word_list[1]
```

処理が終わった段階でword_listに名詞の配列が入っていますので、これをその後工程で使う想定です。

工夫した点は以下のようなところ。

1. PythonもPerlみたいに文字表現形式が２タイプあるらしく、文字処理をしたい場合、unicode関数にかけて、string形式からunicode形式に変換をかけます。
2. janomeの最新版(v0.3.1 以上)では「ストリーミングモード」というものがあるので、変換時にこのモードを使っています。大量文書処理時に、メモリーを余り使わないという効果があるみたいです。
【Python】datetime.nowの出力結果から、UNIXtimeを消す方法


地味に悩んだのでメモ


`print (datetime.now(timezone(‘Asia/Tokyo’)))`
って打つと、
`2017-10-12 12:37:13.382567+09:00`
って返ってくるけど、
`2017-10-12 12:37:13`
この情報だけを取得する方法です


```
from pytz import timezone
from datetime import datetime

aaa = datetime.now(timezone('Asia/Tokyo'))

print (aaa.strftime("%Y/%m/%d %H:%M:%S"))
```

こんな感じでいける。

取得したい型が決まっている場合は、明示的にformatしてあげないといけないようです。

`print (datetime.now(timezone('Asia/Tokyo')).strftime("%Y/%m/%d %H:%M:%S"))`

こうすればワンライン
【マメ知識】青空文庫からテキスト解析用のプレーンテキストを入手

2017-10-16追記　スクリプトをPhthonに直した上、後工程を含めて別の記事
[青空文庫テキストから名詞のリストを作成する](https://qiita.com/makaishi2/items/9a4e517dfa90bcd0ee6e)に統合しましたので、こちらを参照されて下さい。

テキストマイニングのテストをしようと思って、なかなか手頃なサンプルテキストがなく、入手に一手間必要だったので、その手順のメモ。

いい品質のプレーンテキストは、なかなかネットでも入手できないものです。
いろいろ調べて[青空文庫](http://www.aozora.gr.jp)にたどり着いたのですが、問題はテキスト型で提供されているデータにはルビの情報も含まれていた点。
たいしたことではないのですが、下記のようなPerlのスクリプトでルビのないきれいなデータを入手できるようになりました。
パターンマッチでルビなど余分な部分を落としているだけなので、もちろん他の言語でも簡単に実装できると思います。

(2017-10-15 追記)
最初のバージョンは、
* 入力ファイル名、出力ファイル名が決め打ち
* 青空文庫でダウンロードしたテキストはJSISなのに、Unicodeを前提にしていた
* 頭の部分に本文と関係ない情報が含まれていた
など、修正すべき点がいくつかあったので、これに対応しました。
最新版は、ソースをコピペして "del-rubi.pl" をして保存した後、

```
$ chmod 755 del-rubi.pl
$ ./del-rubi.pl kokoro.txt kokoro-refine.txt
```

のように、第一引数入力ファイル名、第二引数出力ファイル名を指定して利用できます。

```
#!/usr/bin/perl

use utf8;
use Encode qw/encode decode/;

my $org_file = $ARGV[0] || 'org.txt';
my $new_file = $ARGV[1] || 'new.txt';

my $new = '';

my $header_count = 0;

if (open(FH, $org_file)) {
while ($data = <FH>) {
    $data = decode('SJIS', $data);
    $data =~ s/《[^》]+》//g;
    $data =~ s/｜//g;
    $data =~ s/［.+?］//g;
    $data =~ s/(\r|\n)//g;
    $data = encode('UTF-8', $data);
    if ( $header_count >= 2 ) {
        $new .= $data . "\n";
    }
    if ($data =~ /----------/) {
        $header_count = $header_count + 1;
    }
  }
  close(FH);
}

if (open(FH, '>' . $new_file)) {
  print FH $new;
  close(FH);
}

exit;
```

ちなみに、私は夏目漱石の「こころ」のテキストを落としてみました。
今のブランチだけpush、pullの対象にする

#環境
Mac：10.12.5
git：2.14.1

#はじめに
git pull で今の作業ブランチだけ落としたい！
fetchで数秒待たされるの嫌ですよね...然るべき時に然るべきものだけをfetchしたい！

git push で今の作業ブランチだけリモートに送りたい。
他ブランチの作業分が巻き添えでpushされるのを防ぎたい！

#先にまとめ
以下を.bash_profileに登録します。

```shell-session
alias gpl="git pull origin $(git rev-parse --abbrev-ref HEAD)"
alias gps="git push origin $(git rev-parse --abbrev-ref HEAD)"
```

#解説
####git rev-parse
▽git rev-parseを使いこなす
https://qiita.com/karupanerura/items/721962bb7da3e34187e1
指定したもののhashを取得したり、gitの設定を取得したりできます。

#さいごに
以前はgit branchで取得したものから、*がついたものをgrepして整形するワンライナーでやっていましたが、gitは本当に探せば何でも情報引っ張り出せそうですね。
C言語のポインタを理解したい！＃１

今授業でc言語のポインタを習っているのですが、ポインタの理解に苦しんでるクラスメイトが多かったのと僕の頭の整理のためにここにメモ程度のレベルでまとめていこうと思います。
僕も完全に理解したわけではないので、参考になるかならないかレベルですがよろしくお願いします<(_ _)>
#そもそもポインタとは
>ポインタ (pointer) とは、あるオブジェクトがなんらかの論理的位置情報でアクセスできるとき、それを参照する（指し示す）ものである。有名な例としてはC/C++でのメモリアドレスを表すポインタが挙げられる。
[wikipedia](https://ja.wikipedia.org/wiki/%E3%83%9D%E3%82%A4%E3%83%B3%E3%82%BF_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0))参照

上記にかいてあるポインタとアドレスについてですが、**ポインタ＝アドレスを記憶する変数**で**アドレス＝メモリ上に与えられた番号**ということになります。
文字だけ並べてもわからないので実際に調べてみましょう。


```ruby:調べるためのサンプルプログラム
#include <stdio.h>
int main(void){
        int num = 1014;

        printf("int型変数numの値=%d\n",num);
        printf("int型変数numのアドレス=%x\n", &num);
}
```
結果は
`int型変数numの値=1014
int型変数numのアドレス=0x7fff1f938304`
となりました。

これは上のprintfがnumに入れた値を出力し、下のprintfはnumに1014という値をいれた変数のアドレス(1)を出力させています。

C言語ではアドレスを表示するのに**「＆」**を使います。
&のことをアドレス演算子といいます。

#ポインタの宣言
`int *pointer;`
これでポインタの宣言は完了です。
どこが変数の型でどこが変数名かというと`int *`が変数の型 `pointer`が変数名となっています。
c言語の宣言には`変数の型``変数名`となっているので上記の分け方になるのです。

しかし、ここで注意が必要なのが
`int *pointer,num;`
と書くと**pointerだけがポインタ型変数**となり**numはint型変数となる**ので気をつけて！
~~だからポインタはややこしい~~

#今回のまとめ
**ポインタ＝アドレスを記憶する変数**で**アドレス＝メモリ上に与えられた番号**ということ。
**「int *」でポインタを宣言する型**となる
しかし、**一つひとつの変数名に*をつけないとポインタ変数にならない**。
もし、helloとhiという変数をint型のポインタ型変数にするにはこう宣言する。
例
`int *hello,hi;`X
`int *hello,*hi;`◯　
アドレスを表示するときは**「&」**を使う。

次書くときはポインタの演算とか配列、関数辺りをかけたらなと思います。
最後にもう一度言いますが、参考になるかならないかのレベルの人なんで理解の仕方は違いますのでよろしくお願いします
<(_ _)>
それでは~~できたら~~次も見ていってください！最後までお付き合い頂きありがとうございました！

何か質問とかあったら[Twitter](https://twitter.com/PotyaExe)にお願いします
日没頃に自動で照明をつけてみる

#日没頃に自動で照明をつけてみる
##やりたいこと
部屋が暗くなったら作業しにくいので、自動で照明がつくようにする。
##環境
-赤外線リモコンの回路を接続したRaspberyPiはある
(赤外線リモコンの作り方は[Make.](http://make.bcde.jp/raspberry-pi/%E8%B5%A4%E5%A4%96%E7%B7%9A%E3%83%AA%E3%83%A2%E3%82%B3%E3%83%B3%E3%82%92%E4%BD%BF%E3%81%86/)を参照)
-RaspberryPiからリモコン操作できるシーリングライトはある
-照度センサーはない
-インターネット環境はある
![7C53C73B-45FB-4B9F-94A5-B2A2D87E293C.png](https://qiita-image-store.s3.amazonaws.com/0/140055/6e507dec-f824-d7ec-d19c-348dd58b307a.png)
##方針
インターネットで日没の時間を調べてその時間頃にRaspberryPiリモコンで照明をつける。
##調査
###日没の時間はどうやって調べるか？
→日没の時間を取得するWebAPIがある。
[おはこん番地は⁈API](http://labs.bitmeister.jp/ohakon/index.cgi)
>・パラメータ指定例
>   1. 日の出・日の入り、月の出・月の入り時刻を計算
>      ?mode=sun_moon_rise_set&year=2017&month=10&day=12&lat=35.8554&lng=139.6512

パラメータはmode、日付、緯度/経度が必要。
###緯度/経度はどうやって取得するか？
GPSは持ってない→住所から取得する
###住所から緯度/経度はどうやって取得するか？
GoogleMAPのWebAPIがある。
[Geocoding API](https://developers.google.com/maps/documentation/geocoding/start?hl=ja)
調べたところ郵便番号からも緯度/経度を取得できるようだ。
精度は高くなくてよいので、これで十分。
##やり方
(1)RaspberryPiの置いてある住所の郵便番号から緯度経度を調べる。
(2)緯度経度と日付から日没時間を調べる。
(3)日没時間-20分に照明をつけるスクリプトをスケジューリングする。
(4)上記を毎日午後3時(この時間は日が沈まないだろう)に行う。

##コード
コードはWebAPIを利用するにはrequestsが簡単そうなのでPythonにした。
このコードは上記(1)(2)(3)の処理を行う。

```py:light_on_sunset.py
import requests
import json
import xml.etree.ElementTree as etree
from datetime import date
import subprocess
from math import modf

#日没時刻を取得する関数
def get_time_sunset(year, month, day, lat,lng):
    url = 'http://labs.bitmeister.jp/ohakon/api/?'
    payload = {'mode':'sun_moon_rise_set', 'year':year, 'month':month, 'day':day, 'lat':lat, 'lng':lng}
    response = requests.get(url, params=payload)

    data = etree.fromstring(response.content)

    return data[3][1].text

#郵便番号から緯度/経度を取得する関数
def get_geocode(zipcode):
    url = 'https://maps.googleapis.com/maps/api/geocode/json?'
    key = 'SetYourKey'
    payload = {'address':zipcode, 'key':key}
    response = requests.get(url, params=payload)
    
    dict_json = response.json()
    lat = dict_json['results'][0]['geometry']['location']['lat']
    lng = dict_json['results'][0]['geometry']['location']['lng']

    return (lat,lng)

#緯度/経度を取得
lat, lng = get_geocode('YourZipCode')

#日付を取得
today = date.today()

#日没時刻を取得
time_sunset = get_time_sunset(today.year, today.month, today.day, lat, lng)

#約20分前に点灯するように調整
num_time_light_on = float(time_sunset)-0.33

#時刻をHH:MMの形の文字列に変換
decimal, integer = modf(num_time_light_on)
minutes = int(60 * decimal)
hour = int(integer)
str_time_light_on = str(hour) + ':' + str(minutes)

#照明をつけるコマンド
cmd_light_on = '/home/pi/python_code/light_on.sh'

#ATでスケジューリング
at_cmd = "at -f " + cmd_light_on + ' ' + str_time_light_on 
subprocess.call(at_cmd, shell=True)
```
(4)の「午後3時に」はRaspbianでcronを利用する。
crontabを設定しておく。

```
# crontab -e
0 15 * * 1-5 python3 /home/pi/python_code/light_on_sunset.py
```
これにて自動照明点灯システムが完成した!

##最後に
日没頃に家の照明がついても、うれしくないことは分かっている。
WebAPIを使ってみたかっただけ。
Apache FlexでAdobe AIRアプリを作るための環境作成（zipを利用する場合）

# はじめに

Apache FlexでAdobe AIRアプリを作るための環境作成をします。

## 試した環境/バージョン

Windows 10
Apache Flex 4.16.1
Adobe AIR 32.0.0.116

# 環境作成の手順

## Apache Flex SDKとAdobe AIR SDKのダウンロード

以下から、apache-flex-sdk-4.16.1-bin.zipをダウンロード
http://flex.apache.org/download-binaries.html

以下から、AdobeAIRSDK.zipをダウンロード
http://download.macromedia.com/air/win/download/32.0/AdobeAIRSDK.zip
　※Chromeでは、HTTPSのサイトからHTTPのダウンロードのリンクは利用できないため、
　　上記のAdobeAIRSDK.zipのURLをコピーして、URLに直接アクセスしてください。

## zipを解凍してマージ

マージするためのフォルダーを作成
（今回はD:\Flex4.16.1_AIR32.0.0.116を作成）

apache-flex-sdk-4.16.1-bin.zipを解凍した中身を上記のフォルダーに配置

その後、AdobeAIRSDK.zipを解凍した中身を上書きで上記のフォルダーに配置

## 環境変数の設定

システム環境変数にAIR_HOMEを追加して、「D:\Flex4.16.1_AIR32.0.0.116」を設定する

システム環境変数のPathに「%AIR_HOME%\bin」を追加する

## 確認

コマンドプロンプトで以下のコマンドが利用できるようになったことを確認する

```
> amxmlc -version
Version 4.16.1 build 20171115
```

環境作成は以上
git zenhub

以下のような git のエイリアス定義。

```
git config --global alias.zenhub '!open $(git remote get-url origin | sed -e s/git@github.com:/https:\\/\\/app.zenhub.com\\/workspace\\/o\\// -e s/.git/\\/boards/)'
```

`git zenhub` でカレントディレクトリに対応した ZenHub を開ける。
EmacsでもLaTeXが書きたい！

この時期になると卒業論文や修士論文（LaTeX）をEmacsで書きはじめる方がいらっしゃると思いますので，参考になればと思い書きました．あくまで最低限の設定かと思いますので，良い拡張などありましたらコメントください．

# General
+ Emacsの`LaTeX-mode`で基本はOk
+ 便利にするため下記を`init.el`に記述

```el
(require 'tex)
(TeX-global-PDF-mode t)
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq-default TeX-master nil)
(add-hook 'LaTeX-mode-hook 'visual-line-mode)
(add-hook 'LaTeX-mode-hook 'flyspell-mode)
(add-hook 'LaTeX-mode-hook 'LaTeX-math-mode)
(add-hook 'LaTeX-mode-hook 'turn-on-reftex)
(setq reftex-plug-into-AUCTeX t)
(setq TeX-PDF-mode t)

```

# Compile
普段TeXShop使ってる人はTypeSetとかのコマンドでいけるけど，EmacsだとMakefileを叩くしかない

+ compileしたいtexファイルと同一階層で`M-x compile`．Makefileを探して`make -k`してくれる（もしくは`C-c C-c`で`Tex-command-master`を起動できる）
+ `M-x compile`を少し拡張した関数をivyの作者[abo-abo](https://github.com/abo-abo)さんが[stackoverflow](https://emacs.stackexchange.com/a/7477)に書いていたので，こちらを記述しても良いかも

```el
(defun desperately-compile ()
  "Traveling up the path, find a Makefile and `compile'."
  (interactive)
  (with-temp-buffer
    (while (and (not (file-exists-p "Makefile"))
                (not (equal "/" default-directory)))
      (cd ".."))
    (when (file-exists-p "Makefile")
      (compile "make -k"))))
```

+ `Compilation buffer`が開くが，それが鬱陶しい人は以下を`init.el`に記述．別frameでcompile logが出力されるようになる（macなら`Cmd+w`でそのwindowをkillできる）．
 
```el

(setq special-display-buffer-names '("*compilation*"))
```

# View
+ Adobeのpdf viewerなどはファイルの変更を検知して自動でreloadしてくれない．
+ そのため[Skim](http://skim-app.sourceforge.net/)を導入するといい．変更を検知してreloadしてくれる（preferenceをいじる必要あり）
+ `make`後に自動でcompileしたpdfファイルを開く・フォーカスしてほしいので，Makefileの`all`のあとに`open -a Skim [YOUR_PDF_NAME]`が実行されるよう記述（以下が私のMakefileの一部）

```yaml
all: pdf
pdf: &(OUTPUT).pdf
$(OUTPUT).pdf: $(TARGET).dvi out2uni
	dvipdfmx -o $(OUTPUT).pdf $(TARGET).dvi
	open -a Skim $(OUTPUT).pdf # open pdf by skim
```

---

+ [latex-preview-pane-mode](https://www.emacswiki.org/emacs/LaTeXPreviewPane)などもありましたが，こちらはpdfを閲覧するのには重すぎたので割愛．
条件分岐とreturnの基礎

#謎の条件分岐からのreturnをしないとエラーになるので悩んだ件

if文のあるコードを書いていて、「returnがないよ！！」と、Eclipseに怒られることが何度かありました。
しかし、なぜなのかわからず。。。

より原始的な形で考えようということで、int型の引数を二つ渡すと、大きい方を返すメソッドを書いてみました（max関数を使えば一発なのですが、わかりやすい例で実験したかったので）。


```java
//コード1

public class BiggerNumber {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		System.out.println(returnBiggerNumber(250,500));
	}

	public static int returnBiggerNumber(int num1,int num2) {
		if (num1 < num2) {
			return num2;
		}else if (num1> num2 ) {
			return num1;
		}else if (num1 == num2) {
			return num1;
		}else {             //←コレ！
			return num1;
		}
	}
}
```
理解不能だったのは、最後のelseです。これを書かないとコンパイルエラーになる。。。

この極めて単純なメソッドの場合、分岐の可能性は3つしかありません。
1.　num1の方が大きい
2.　num2の方が大きい
3.　num1とnum2はイコール

理論的にはこれで可能性は網羅しているはず。。。
どんな数字が引数に来てもreturnできるはずなのに、
これ以外の可能性ってあるのか？と悩んでいました。

#原因と、それを踏まえた書き方
エラー原因をjava歴の長い先輩に聞いたところ、
**『コンパイラーは全ての条件分岐がもれなく書かれているか否か、判断することはできない。
そのため、実際には到達することがありえない条件分岐であっても、形式的に書いておく必要がある。』**
とのことでした。

「なるほど！」

であれば、＜、＞以外の分岐可能性は==しかないのだから、
==の条件式をわざわざ書く必要はないとも考えられます。
そこで（私が）まず思いつくのはこれ。

```java
//コード2

	public static int returnBiggerNumber(int num1,int num2) {
		if (num1 < num2) {
			return num2;
		}else if (num1> num2 ) {
			return num1;
		}else {
			return num1;
		}
	}

```
あるいはこれもあり。

```java
//コード3

	public static int returnBiggerNumber(int num1,int num2) {
		if (num1 < num2) {
			return num2;
		}else if (num1> num2 ) {
			return num1;
		}
		return num1;
	}

```

少し違和感がありますが、これも有効。このあたりは好みの問題なのでしょうか。

```java
//コード4

	public static int returnBiggerNumber(int num1,int num2) {
		if (num1 < num2) {
			return num2;
		}else if (num1> num2 ) {
			return num1;
		}else if (num1 == num2) {

		}
		return num1;
	}

```

#Swiftのswitch{case}と混同（半分個人的なメモとして）
そもそも、全てのパターンに対してreturnできているのだから問題ないはず！と自分が思い込んでいたのは、**Swiftのswitch文のルール**が原因でした。

それがこれ。
**『switchに与えられた値の型が取りうる全ての値をカバーするcase節が存在するか、
　default節が存在する必要がある。』**
（※因みにJavaではその必要はないし、同じSwiftでもif文ではその必要なし）

いやいや、**これ戻り値関係ない話だし。。。**勘違いしていました。

Javaのswitch文にせよ、swiftのif文にせよswitch文にせよ、
戻り値を返す関数・メソッドならば、どんな値がきても全て打ち返す（returnする)必要はあります。

一応念のため、例えば

```java
public int returnTest(int i) {
	switch (i) {
	case 1:
		return 1;
	case 2:
		return 2;
	case 3:
		return 3;
　　　　　//このようにdefault、もしくはswitchブロックの外に必ずreturnを書かなければならない。
　　　　　//なお、swiftではこの書き方はエラーになるので、switchブロックの外に書く。
	default:
		return 4;
	}
}
```

これは共通したルールですが、中途半端な言語特有のルール知識が絡まっていて整理できていなかったようです。

ということで、とりあえず納得いきましたが、ツッコミや+αなどありましたらコメント頂けると幸いです。
Javaの「参照渡し」問題まとめ

# 概要
Javaの評価戦略は値渡しです。参照渡しではありません。
一部に、参照値を渡すこと指して「参照渡し」と誤用する人がいます。
それを誤用だと指摘する人、分かってて使ってるという人、本当に分かっていない人など色々いて、くすぶっているようですので、情報をまとめてみました。

# 評価戦略
計算機科学(computer science)には、評価戦略(evaluation strategy)という概念があります。
値渡し(call by value あるいは pass by value)も、参照渡し(call by reference あるいは pass by reference)も、その評価戦略の一種です。

詳しくは:
* [Wikipedia: Evaluation strategy](https://en.wikipedia.org/wiki/Evaluation_strategy)
* [Wikipedia: 評価戦略](https://ja.wikipedia.org/wiki/%E8%A9%95%E4%BE%A1%E6%88%A6%E7%95%A5)

# Javaの評価戦略
Javaの評価戦略は値渡しです。
Javaでいう参照値(reference values)・参照(references)を渡したときも、値渡しで評価されます。

そのことは、Javaの言語仕様にも書かれています。
> When the method or constructor is invoked, the values of the actual argument expressions initialize newly created parameter variables, each of the declared type, before execution of the body of the method or constructor. 

http://docs.oracle.com/javase/specs/jls/se9/html/jls-8.html#jls-8.4.1 より
私訳:
> メソッドかコンストラクタが呼び出されたとき、メソッドかコンストラクタのボディーの実行前に、実引数部表現の**値**で、それぞれ宣言された型の新しい仮引数値を初期化する。

詳しくは、Scott Stanchfield が 書いた[Java is Pass-by-Value, Dammit!](http://javadude.com/articles/passbyvalue.htm) を読んでください。

# 評価戦略についての正しい考え方
一般に評価戦略を考えるときは、関数やメソッドやサブルーチン等を呼び出しているプログラムをプログラミング言語処理系に入力したときに、その呼び出しがどのように評価されるか**だけ**を考えるのが評価戦略の正しい考え方です。

プログラムやバイナリを実際に実行した時の挙動で考えてはいけません。プログラムの挙動は、プログラミング言語の実行環境によって全く変わってしまいます。例えば、プログラムの実行環境がコンパイラか、最適化はどこまでするか、インタープリタか、あるいは人間が黒板とチョークで「実行」するか、等で実際に行われる挙動は全くかわってしまいます。プログラミング言語の評価戦略を考えるときに、実際にCPUが何をするか、メモリはどうか、アドレスはどうか、等を考えてはいけません。

# 私見
Javaで参照を渡すことを「参照渡し」と呼ぶことについては**即刻やめるべき**です。 Java 参照渡し で検索してみれば分かりますが、あきらかに誤解した記事が見受けられます。 その何十倍か何百倍か、誤解したまま観測されていない人、誤用に引きずられて理解が妨げられている人がいるはずです。
こういうのをやめていかないと業界の損失になります。
timeout付きinputを作った

# タイムアウト付きのinput

## 概要
タイム付きのinputが欲しくなったので自分で作ってPyPIに公開してみた。(1回公開したけどバグってたので削除済み)

## ググって参考にしたもの
[Python 3 Timed Input - Stack Overflow](https://stackoverflow.com/questions/15528939/python-3-timed-input)

## 困ったこと
PythonのselectはWindowsのファイルオブジェクトを受理できないのでWindowsとUnix系で実装を分ける必要があった。

判別方法

```py3
>>> import platform
>>> platform.system()
'Windows' or 'Darwin' or 'Linux' # など
```

## Windows の場合
[34.2. msvcrt — MS VC++実行時システムの有用なルーチン群 — Python 3.6.1 ドキュメント](https://docs.python.jp/3/library/msvcrt.htm)

ドキュメントの最初にgetpassモジュールに使われていると書いてあったので参考にした。
[cpython/getpass.py at 3.6 · python/cpython](https://github.com/python/cpython/blob/3.6/Lib/getpass.py)

```py3
import msvcrt
import time


DEFAULT_TIMEOUT = 30.0

def win_input_with_timeout(prompt='', timeout=DEFAULT_TIMEOUT):
    begin = time.monotonic()
    end = begin + timeout
    for c in prompt:
        msvcrt.putwch(c)
    line = ''
    is_timeout = True
    while time.monotonic() < end:
        if msvcrt.kbhit():
            c = msvcrt.getwch()
            msvcrt.putwch(c)
            if c == '\r' or c == '\n':
                is_timeout = False
                break
            if c == '\003':
                raise KeyboardInterrupt
            if c == '\b':
                line = line[:-1]
            else:
                line = line + c
        time.sleep(0.05)
    msvcrt.putwch('\r')
    msvcrt.putwch('\n')
    if is_timeout:
        raise TimeoutOccurred
    return line
```

msvcrt.kbhit()の呼び出しが重たいみたいのでtime.sleep(0.05)を入れないとCPU使用率が上がるみたい。

## Unix系の場合
signalとかthreadとかselectとか実現できそうな方法はいろいろあるけどselectで実装

```py3
import sys
import select


def unix_input_with_timeout(prompt='', timeout=DEFAULT_TIMEOUT):
    sys.stdout.write(prompt)
    sys.stdout.flush()
    (ready, _, _) = select.select([sys.stdin], [], [], timeout)
    if ready:
        return sys.stdin.readline().rstrip('\n')
    else:
        raise TimeoutOccurred
```

## インストール

```bash
$ pip install inputimeout
```

## 使い方

```py3
from inputimeout import inputimeout, TimeoutOccurred
try:
    something = inputimeout(prompt='>>', timeout=5)
except TimeoutOccurred:
    print('Timeout!')
    something = 'something'
```

## リポジトリ
[johejo/inputimeout: Standard input with timeout.](https://github.com/johejo/inputimeout)
JQueryのval(値)呼び出し時のイベントについて

あまり使用頻度は低いが、気になって試したのでメモ。



# JQueryのval(値)呼び出し時はイベントは発生するか？

JQueryでセレクタで取得した要素に対して値を設定する場合、val(設定する値)を使うと思う。

この時、値が変わるわけなので**onchenge**イベントが発生するように思うが、**実際は何のイベントも発生しない**。



# val(値)でイベント発生するには

もしonchengeイベントの発生を期待している場合は、明示的にイベントを発生させてあげる必要がある。

```js:val(値)でonchengeイベント発生させる
	$("#hoge").val("hogehoge").change();	//値を設定後、onchengeイベント発火！
```

（調べていないので恐らくだが、入力項目の入力欄にフォーカスインして値を変更、入力欄からフォーカスアウトした際にフォーカスイン時から値が変わっている場合にonchangeイベントが発火されているのではないか。このため、フォーカス遷移の伴わないval(値)ではonchangeイベントが発火しない。）
javascriptで月末日を取得する

# 指定月の月末日を取得したい



画面で入力した年月の月末日を取得したいと思ったことがあったので、調べた内容をメモ。



## Dateオブジェクトを使う



javascriptで日付を扱う場合、Dateオブジェクトが便利。

Dateオブジェクトのインスタンス生成時に任意の引数を指定することで指定した日付データを保持するDateオブジェクトを生成することができる。

```js:インスタンス生成
var date = new Date(年, 月(0～11), 日);
```

月末日を取得する場合、Dateオブジェクトのインスタンス生成時の引数の"月"に「取得対象の月の翌月」（4月の場合、4を指定）を、"日"に「0」を指定する。

```js:月末日を取得
var date = new Date(2017, 4, 0);
var dateStr = date.toDateString();	// "Sun Apr 30 2017"
```
c2nim でモンテカルロで円周率を求めるコードを変換

# 本日は

c2nim で c で書いたコードをNimに変換してみようという話です．
相変わらずモンテカルロ法ですね．．．

# 変換対象

```c:cmonte.c
#include <time.h>
#include <stdio.h>
#include <stdlib.h>

//http://www.sat.t.u-tokyo.ac.jp/~omi/random_variables_generation.html#Uniform
double UniformRandom01(void){
    return ((double)rand()+1.0)/((double)RAND_MAX+2.0);
}

int main(void){
    srand(time(NULL));
    const int N=100000000;
    int counter=0;
    for (int i=0;i<N;++i){
        double x=UniformRandom01();
        double y=UniformRandom01();
        if (x*x+y*y<1.0){
            counter+=1;
        }
    }
    printf("approx pi is %f\n", 4*counter/(double)N);
}
```

相変わらずの円周率を求めるプログラムです．

# c2nim で変換

変換してみましょう．ここではWindows１０でおこないました．

```shell-session

> c2nim cmonte.c
```

なんとこれだけで行けます．もしやこれだけでNimは動かせるのだろうか．．．

```nim:cmonte.nim
## http://www.sat.t.u-tokyo.ac.jp/~omi/random_variables_generation.html#Uniform

proc UniformRandom01*(): cdouble =
  return (cast[cdouble](rand()) + 1.0) div (cast[cdouble](RAND_MAX) + 2.0)

proc main*(): cint =
  srand(time(nil))
  var N: cint = 100000000
  var counter: cint = 0
  var i: cint = 0
  while i < N:
    var x: cdouble = UniformRandom01()
    var y: cdouble = UniformRandom01()
    if x * x + y * y < 1.0:
      inc(counter, 1)
    inc(i)
  printf("approx pi is %f\x0A", 4 * counter div cast[cdouble](N))
```

と思ったんですけれど結構形式的な置き換えのようですね．そして読める！読めるぞ！ include の対象は考慮しないみたい．少し考えればそりゃそうだとなりますが．まず，ランダムモジュールの部分を直さなければいけませんね．

# 手動修正後

```Nim:modefied.nim
import random
randomize()

proc UniformRandom01*(): float =
  return random(max=1.0)

proc main*(): int =
  var N: int = 100000000
  var counter: int = 0
  var i: int = 0
  while i < N:
    var x: float = UniformRandom01()
    var y: float = UniformRandom01()
    if x * x + y * y < 1.0:
      inc(counter, 1)
    inc(i)
  echo "approx pi is \x0A", 4.0 * counter.float / N.float

when isMainModule:
  discard main()
```

こんな感じになります．最初から手書きで移植するよりかは骨組みを作ってくれる分ましかもという感じで使えればいいのかな．

CからNimへの変換前後のコードで厳密なパフォーマンスは測定していませんが，体感ほぼ変わらない感じです．
JDBCのTimestampからDate And Time APIへ変換したい

DBから取得した時刻の値をDate And Time APIで扱う際に迷ったため、メモ。

#変換用にtoLocalDateTime()がある

方法はシンプル。
上記のメソッドを呼び出すことでLocalDateTimeにささっと変換できる。

```java:DB値をDateAndTimeAPIで扱う
	Timestamp ts = rs.getTimestamp("timestampのカラム名");	// rsはResultSet
	LocalDateTime ldt = timestamp.toLocalDateTime();
	DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd");	// 文字列フォーマットもDate And Time APIで
	String dateStr = dtf.format(ldt);
```

上記で文字列フォーマットまでをDate And Time APIで行うことが可能。

##何故Date And Time APIを使うのか？

現在のところJDBCはDate And Time APIに未対応なので、上記のような方法で変換をしているが、そもそも何故そこまでしてDate And Time APIを使いたいのか？
理由は、自分は文字列フォーマットによくSimpleDateFormatを使っているが、これがDate And Time APIのDateTimeFormatterが軽量で扱いやすいから。
個人的に検証はしておらず検証を行っているサイトの受け売りだが、SimpleDateFormatはスレッドセーフでない、かつ、インスタンス生成に時間がかかるため、あまりおすすめできないとのこと。
その点、Date And Time APIのDateTimeFormatterはスレッドセーフ、かつ、インスタンス生成も軽いためJava8を使っているならDate And Time APIを使うべき！とのこと。
ちなみにベンチマークテストの結果は、フォーマット、解析処理共にDateTimeFormatterの方が早かったそう。
個人的にはこの結果を信じて、特にSimpleDateFormatでフォーマット処理をしていた箇所は、Date And Time APIに置き換えを考えている。

引用元：http://www.ne.jp/asahi/hishidama/home/tech/java/DateTimeFormatter.html

#Date And Time APIからDBへの登録は？

##変換用にvalueOf(LocalDateTime)がある

Date And Time APIからJDBCの日付型への型変換も容易にできる。

```java:DateAndTimeAPIの日付型からJDBCの日付型へ
	LocalDateTime ldt = LocalDateTime.now();
	Timestamp ts = Timestamp.valueOf(ldt);
```

java.sql.Date型への変換の際は、Date And Time APIの対応する型をvalueOfすればよい。

```java:java.sql.Date型へ
	LocalDate ld = LocalDate.now();
	java.sql.Date date = java.sql.Date.valueOf(ld);
```

#異なる精度への変換
画面入力上、日付文字列をフォーマット：yyyy/MM/ddで入力したものを、DBへTimestampで登録したい場合がある。
この場合は、日付文字列を一度日付を扱うLocalDateへ変換、LocalDateのatTime()を使ってLocalDateTimeに変換する。

```java:日付文字列をLocalDateTimeへ
	String strDate = "2017/09/09";
	LocalDateTime date = null;
	DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy/MM/dd");
	date = LocalDate.parse(startDate, sdf).atTime(0, 0);
```

この際、atTime()は引数として時間を指定する必要がある。特に時間に関して取り決めがなければ、上記のように0時0分0秒を表す値を入力すれば問題ない。(引数にLocalTimeを指定することも可能)
削除忘れのOIDをさくっと削除したい

##OID
postgresqlではラージオブジェクト(BLOB、CLOB)はOIDにより管理することができる。
このOIDはDB上でオブジェクトを一意に識別するためのIDで、postgresqlが自動で発行するもの。（ラージオブジェクトに関わらず全てオブジェクトに割り振られる）

##ラージオブジェクトをOIDで管理するとはどういうことか？OIDで管理すると何が嬉しい？
ラージオブジェクトをそのままテーブルに格納することも可能だが、大きなラージオブジェクトを含むデータを大量に問い合わせた際にレスポンスが低下することがある。（ラージオブジェクトのサイズ分メモリに展開するため）

そこで、ラージオブジェクトの実態は別テーブルで管理し、問い合わせ先のテーブルではこのラージオブジェクトのOIDのみを管理することが可能になっている。

こうすることで、問い合わせの際には実際のラージオブジェクトではなくOIDへアクセスするため、応答が早くなる。

実際のラージオブジェクトにアクセスする場合はこのOIDを引数とするユーティリティを使用することで目的のラージオブジェクトのみを問い合わせることができる。

ただ、OIDによる管理手法はデータの登録/削除時に手間が多くかかる。

特に問題となるのはデータ削除時のラージオブジェクトの削除忘れ。

ラージオブジェクトのOIDのカラムを含むテーブル行をDELETE文でただ削除するだけでは、ラージオブジェクトを管理するテーブル（pg_largeobject）のラージオブジェクトは消えてくれない。

対象のデータ行のOIDをラージオブジェクト削除用のユーティリティに渡すことで初めてラージオブジェクトは削除される。

##削除忘れをしたラージオブジェクトはどうなる？

もしラージオブジェクトを削除し忘れた場合は、管理テーブル（pg_largeobject）の実データと

OIDの紐づけを管理するテーブル（pg_largeobject_megadata）のOIDとOIDを含むテーブルの既存のOIDと対比し、

既存データとの差分から削除忘れのラージオブジェクトを判断する方法が考えられる。

この方法だと、OIDを含むカラムの数が多い場合、クエリが煩雑になるためメンテナンスが難しくなっていきそう。

そこで、posgresqlのユーティリティに削除忘れのOIDを削除するものがないか調べたところ、以下のユーティリティに辿り着いた。

```java:
　vacuumlo
```

このユーティリティ、postgresqlの拡張モジュールとのことで、デフォルトではインストールされていない、つまり明示的にインストールしなければ使えないとのこと。。。

postgresqlのソースディレクトリ配下にインストール用のツールは全て揃っているものらしいので、それを使ってインストールすることになる。

```java:
　CREATE EXTENSION vacuumlo;
```

※どのようなインストールをしたか不明だが、現場の実行環境のpostgresqlのソースディレクトリ配下に拡張モジュールが１つもなく、インストールを試すことはできなかった。。。

使ったことがないのでなんとも言えないが、このユーティリティをバッチで定期的に呼び出せば、削除忘れのラージオブジェクトが一掃されディスク容量の無駄を省くことができると思う。

ちなみに、アプリケーションとして削除忘れを容認するのはよろしくないので、バッチ作成はテスト環境に限るべきかと。
ARCoreを使った光学シースルーを試す

# やる事

ARCoreとHoloKitを利用して光学シースルー体験。

AR_FukuokaでARCoreを触らせていただいたので、自分が手順作った感じで記事にする。
(手順作ったのは主催者なので自分ではないです)

主催者様に感謝です！

# ARとは

MR(現実世界と仮想世界の混ぜ合わせる技術)の内、現実成分が多い技術。
仮想成分が多いものはAV(Augumented Virtuality)。  

# HoloKit

自己位置推定機能を持つスマートフォンを利用して光学シースルーARを実現するキット。
Tango,ARCore,ARKitに対応。
鏡とハーフミラーを利用し、スマートフォンのディスプレイを透過させて表示する。


# 環境

 + Unity 2017.02

# 早速始める

[HoloKit SDK for Android](https://github.com/holokit/holokitsdk/tree/android)をダウンロードして解凍。
Unityを起動し、解凍したHoloKit SDKを開く。

「Switch to Android Now?」と聞かれるので"Switch to Android"を選択。

![image01.png](https://qiita-image-store.s3.amazonaws.com/0/42445/d576b60b-d956-1a4e-83d4-dec5c0e38e56.png)

アセットストアから3DModelをimport。今回利用するのは、
Earth Planet With Atmospheric Scattering

Asssets->Earth->Prefab内のEarthをHieralchyにドラッグ&ドロップで追加する。

![image02.png](https://qiita-image-store.s3.amazonaws.com/0/42445/114b0fe3-d286-452d-595c-5e74067fe747.png)

位置とサイズを調整

position: X:0, Y:0, Z:1
scale: X:0.01, Y:0.01, Z:0.01

回転とかはInspectorのy軸で調整。回転を-60000にしようとしたら最大が-1000だった。


ビルド設定
File->Build Settings->Player SettingsでPlayerのinspectorを開き、下記設定を行う。

 + Other Settings
     + Package Name: jp.miyating.holokits
 + Icon: 自分のアイコン

Assets -> HoloKit SDK -> Starter -> HoloKitCameraRigをHieralchyにドラッグ&ドロップ

 + HoloKitCameraRig
    + UnityAR Camera Managerのチェックを外す
    + Component追加 - Tracked Pose Driver
        + Pose Source: Clor Camera
        + Update Type: Before Render
    + Component追加 - Session Component
        + Ar Session Config
        + First Person Camera
 + HoloKitCameraRig配下のVideoSeeThroughCamera
     + Unity AR Camera Near Far: チェックを外す
     + Unity AR Video: チェックを外す

Assets -> HoloKit SDK -> Scripts -> HoloKitCalibration.csを修正

 + LoadDefaultCaliblation
      + loadSamsungS8Calibration()が呼ばれるように変更。
 + loadSamsungS8Calibration
      + cameraRig.PhoneScreenHeight = 0.130f;
      + cameraRig.PhoneScreenWidth = 0.064f;

Build and Run!!

![DSC_0043.JPG](https://qiita-image-store.s3.amazonaws.com/0/42445/af81691c-47c0-4aad-79c9-1cdb97facd85.jpeg)


# reference

 + [HoloKit SDK for Android](https://github.com/holokit/holokitsdk/tree/android)
Qiitaに投稿するのって大切なのではないかという話(初投稿)

### はじめに

こんにちはtomueeen93です。Qiita初投稿です。
どういう記事を最初に書けばいいか悩んだので、とりあえずもう書いちゃえと思って投稿しました✋
とりあえず最初に投稿するというハードルを超えるために書くので、内容についてはお許し下さい…

### Qiitaに投稿する大切さ
最初はQiitaに投稿することの大切さについて書こう！と思ったら以下の記事にまとめてありました。笑
自分もほぼこの理由でQiita始めようかなと思ったので、是非読んで下さい🙋
この中でとくに承認欲求が満たされるとか、「分かる」→「説明できる」に変わるとかが共感したところですかね。

https://qiita.com/I-201/items/e86a27bb217a4123e6f9

これに加えて自分はいつも中途半端に勉強することが多くて、自信を持って「できる」と言えることが少ないのが課題だったので…
とりあえず記事にできれば頭の中を整理できるし、自信をもって「できる！」と言いはれるかなと思ってQiita始めます。

ぶっちゃけ実際はできないですが、情報発信やらないよりはいいことが起きるだろくらいの気持ちでとりあえずやっていきます。

### やりたいこと多い問題
何をQiitaに投稿しようかという前に、やりたいことが多すぎることにも悩んでいます。
今は気分とか必要に応じてちょっとずつ勉強を進めている状態ですが、その結果「ちょっとドキュメント読んで、Tutorialやったマン」に成り果てました。

ちゃんとやりこみ型のエンジニアになればいいんですが、これが結構治りません😿
もう一度もう開き直って、いろんなことやるのはいいけど、どこまでどう出来たのかは記録していけるようになれれば良いです、進歩です。

そうやって情報発信を続けてるうちに優先してやりたいこととか、入りたいコミュニティとか出てくると信じてます。
もしくはどっかのコミュニティが拾ってくれたら…という淡い希望をもってやっていきます！

### というわけで
共感していただけるかはわかりませんが、同じ悩みを持つエンジニアの方は一緒に頑張りましょう👍
こんな感じの記事でいいのかは知らないですが、なにか少しでも共感いただけるところあったらコメント大歓迎です🙇
Yolo v2 がOpenCVにマージされたようなので試してみる (on MacOSX)

# 追記(2017/10/25)
OpenCV v3.3.1 がリリースされました。
今回のリリースにYOLO v2 も含まれているため、
自前でビルドを行わなくてもYOLO v2のOpenCV実装を利用できるようになりました。

# Yolo v2 がOpenCVにマージされたようなので試してみる

先日[YOLO v2がOpenCVにマージされた](https://github.com/opencv/opencv/pull/9705)そうなので、
サンプルプログラムを動かしてみました。

https://github.com/AlexeyAB/darknet/issues/227

> Now Darknet Yolo v2 is added to the OpenCV: opencv/opencv#9705
You can use it from master-branch or since OpenCV 3.4.0 will be released.

とのことなので、OpenCVのmaster-branchからソースを落としてきてビルドしてみます。

ざっくり試して終わるつもりが意外とインストールバトルに手こずったので備忘録的に残します。

## 環境

- Mac OSX (Sierra)
- Xcode version 9.0 (9A235)
- cmake version 3.9.4

## opncv2.frameworkのビルド

- githubから最新のソースを取ってくる

```sh
$ cd /my/work/space/
$ git clone
```

- opencv2.frameworkをビルドする

```sh
$ mkdir osx
$ python opencv/platforms/osx/build_framework.py --opencv opencv osx/
```

- エラーが出る

```
CMake Error in CMakeLists.txt:
  Evaluation file to be written multiple times with different content.  This
  is generally caused by the content evaluating the configuration type,
  language, or location of object files:

   /Users/reverent/work/lab/libs/macOS/build/build-x86_64-macosx/OpenCVGenPkgConfig.info.cmake
```

`OpenCVGenPkgConfig.info.cmake`が複数回書き換えられている？とのことで怒られてしまいました。

ここで解決策がわからず時間を使ってしまったのですが、
取り敢えずCMakeLists.txtを見てみると

```
# Generate opencv.pc for pkg-config command
if(NOT OPENCV_SKIP_PKGCONFIG_GENERATION)
  include(cmake/OpenCVGenPkgconfig.cmake)
endif()
```

とあったので、半ば投げやりにここをコメントアウトしてみるとビルド成功。
`opencv2.framework`が作成されるので、
Xcodeから簡単に利用できるようになりました。

取り敢えずサンプルプログラムを動かすことが目標なので、
今回はこのまま利用します。

※ 当たり前ですが、この状態だと依存ライブラリ(libwebpなど)をXcodeでのコンパイル時に追加しないとリンカエラーが出るようになりました

## サンプルプログラムの実行

公式のサンプルプログラムがこちらにあるので
`/opencv/samples/dnn/yolo_object_detection.cpp`
これで遊んでみます。

### サンプルプログラムに必要な前準備

- モデルの定義
https://github.com/pjreddie/darknet/blob/master/cfg/yolo.cfg

- 学習済みモデルのDL

```sh
$ wget https://pjreddie.com/media/files/yolo.weights
```

### 結果

<img width="1002" alt="スクリーンショット 2017-10-14 15.50.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/57130/9a2fd5b8-3943-1562-06f1-e9b7ad076e40.png">

クラスIdと名前の対応はこちらから
https://github.com/pjreddie/darknet/blob/master/data/coco.names

Webカメラからの入力も試してみましたが、
CPU上での実行でも2 - 3[FPS]程度でていました。
リアルタイム性の必要なアプリでも充分利用できそうです。

お疲れ様でした
Cloud9でAngular-CLIの開発環境を構築する

ブラウザ上で動作し，共同開発が簡単にできるIDEのCloud9上で，Angular-CLIの開発環境を構築します．

# Worspaceを作る
Create a new workspaceから，名前を入力し，テンプレートはBlankを選択してCreate workspaceをクリックします．

# Node.jsのバージョンを上げる
デフォルトでインストールされているNode.jsとNPMのバージョンを確認します．

```
$ node -v
v6.11.2
$ npm -v
3.10.10
```

Angular-CLIにはNode.js 6.9.0以上，NPM 3以上が必要なので，NVMを使って新しいバージョンのNode.jsをインストールします．Cloud9にはデフォルトでNVMがインストールされているので，以下のコマンドを実行してNode.js 6.9.0をインストールします．

```
$ nvm install v6.9.0
Downloading https://nodejs.org/dist/v6.9.0/node-v6.9.0-linux-x64.tar.xz...
######################################################################## 100.0%
Now using node v6.9.0 (npm v3.10.8)
```

Node.js 6.9.0がインストールされていることを確認します．

```
$ node -v
v6.9.0
```

# Angular-CLIをインストールする
[公式の説明](https://github.com/angular/angular-cli)に従って，Angular-CLIをインストールします．仮想環境なので，-gオプションを付けてグローバルモードでインストールします．メモリが512MBでは，結構時間が掛かります．

```
$ npm install -g @angular/cli
```

# プロジェクトを作る
```
$ ng new PROJECT-NAME
$ cd PROJECT-NAME
```

ここまでは公式と同じです．サーバーを立ち上げる時に，公式と同様に，

```
$ ng serve
```

と入力するだけでは，立ち上げたサーバーに接続できないので，以下のコマンドでサーバーを立ち上げます．workspacenameとusernameは適宜読み替えて下さい．

```
$ ng serve --host 0.0.0.0 --public workspacename-username.c9users.io
```

ブラウザで`https://workspacename-username.c9users.io`にアクセスし，Welcome to app!のページが表示されたら成功です．
サーバーを立ち上げるシェルスクリプトを書くと楽です．

```bash:serve.sh
#!/bin/bash
ng serve --host 0.0.0.0 --public workspacename-username.c9users.io
```
Lambdaのポイントメモ

# 概要

Lambdaで開発する時に、「あれどうだっけな」ってなった時のメモです。

# Lambda関数の種類

* 同期呼び出し
    * ストリームベース
        * Kinesis Streams
        * DynamoDB Streams
    * それ以外
        * Cognito
        * Echo
        * Lex
        * API Gateway
* 非同期呼び出し
    * S3
    * SNS
    * CloudFormation
    * CloudWatchLogs
    * CloudWatchEvents
    * SES
    * CodeCommit
    * Config

# イベントソース

## ストリームベースのイベントソース

* 通常のイベントソースはイベントソースがLambda関数を呼び出す。
* ストリームベースのイベントソースは、Lambdaがストリームに対してポーリングを行ない、変更や新しいイベントの存在を検出したらレコードを取得し、Lambda関数を実行する。

# アクセス権限

## アイデンティティベースのポリシー

* IAMユーザー、IAMグループ、IAMロールに対してアタッチするポリシー

## リソースベースのポリシー

* Lambdaに対してアタッチされるポリシー
* Lambdaにイベントソースをセットアップして、サービスまたはイベントソースに対して、Lambda関数を呼び出すアクセス権限を付与する。
* ポリシーの付与には、AWS CLIかAWS SDKを用いて指定する。

## クロスアカウントアクセス

* Lambda関数を所有するアカウントとそれを呼び出すアプリケーションやイベントソースのアカウントが別でも呼び出せる。

# テスト

* ユニットテストはローカルで実行、これ以外はクラウド上で実行する。
	* ユニットテストは比較的手元で実行したい事が多いテストだから。
* Lambda関数をローカルで実行するた為に必要なもの
	* ローカルで呼び出す為のエントリポイント
	* イベント
	* contextオブジェクト

## エントリポイント

* ローカル環境で実行する際の呼び出しをどの様に行うか。
* 実行関数を作って、if文で制御して普通に実行する。

## イベントデータ

* 静的に作成してします。
	* 各イベントソースがが生成するイベントデータをJSON形式で記述する。
* 各イベントソースが生成するイベントデータは公式にサンプルがある。
	* [イベントソースによって公開されたサンプルイベント - AWS Lambda](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/eventsources.html)

## contextオブジェクト

* contextオブジェクトには実行中のLambda関数のランタイム情報が格納されている。
* ハンドラ内部からcontextオブジェクトの各プロパティならびにいくつかのメソッドにアクセスが可能。
* 極論、ランタイム情報へのアクセスが不要であれば、ローカル実行時は特にエミュレートしなくとも良い。
* 言語毎に用意されているプロパティ名やメソッド名は異なる

# VPC

* Lambda関数からVPC内にあるパブリックなIPを持っていないAWSリソースにアクセスする事が可能。
	* VPC内のみの接続にしてあるRDSの接続も可能
	* インターネットからアクセスがサポートされていないElastiCacheの様なサービスでも呼び出し可能

## アクセス制御

* EC2やRDSのLambda制御を行いたい場合は、セキュリティグループで行う事ができる。

## レイテンシ

* VPC内のリソースへのアクセスはレイテンシ増の原因となりやすい為、アクセスは最低限にするべき。
	* ENIの作成に時間がかかる。

### ENIのレイテンシ

* ENI は新規のリクエストや久しぶりのリクエストが発生した場合自動的にLambdaによって作成される。
* 初期化処理に時間がかかる。(10~30秒)
* 2回目以降は普通のレイテンシ

## RDSとの接続の場合

1. RDSにLambdaから直接レコードを書き込むのではなく、一旦DynamoDBにレコードを書き込み、その時点でレスポンスしてします。
2. その後、DynamoDB ストリームとLambdaを利用して、非同期にRDSへとデータを反映する。

# 環境変数

* 関数からアクセス可能な環境変数を定義する事が可能。
	* コードの変更なく動的に設定した値を渡せる。
	* 無駄なハードコーディングが不要になる。
* 環境変数へのアクセスは言語毎に変わる。

## 環境変数の利用制限

* 合計サイズが4KB
* 文字で始める
* 英数字とアンダースコアのみ
* AWS Lambdaが予約する特定のキーセットは利用不可

## Lambda関数自体が利用する環境変数

* 予約語のうち、更新可能なものと更新不可のものがある。

## 環境変数の暗号化

* キーと値はAWS KMS で自動的に暗号化されて保存される。
	* 独自のサービスキーを利用することも可能。
		* 別途IAMロールに対してポリシーが必要。

# エラーハンドリング

* 処理が異常終了した場合の振る舞いは、イベントソースのタイプと呼び出しタイプによって異なる。
	* 関数の実行がタイムアウト
	* 関数の呼び出しがスロットリング
	* 関数の処理でエラーor例外が発生

## ストリームベースのイベントソースの場合

* Amazon Kinesis StreamsもしくはDynamoDB Streamsがイベントソースの場合
* レコードの有効期限が切れるまで再試行され続ける。
	* その間、エラーの発生したシャードからの読み取りはブロックされ、そのレコードのバッチの有効期限が切れるか処理が成功するまで、新しいレコードの読み込みは行われない。
	* レコードの処理順序が保証される。

## ストリームベース以外のイベントソースの場合

### 同期呼び出しの場合

* 呼び出し元にエラーが返される。
* 呼び出し元はそのエラーを受け取り、必要に応じてリトライの処理を実装する。

### 非同期呼び出しの場合

* 2回自動的にリトライされる。
* 3回処理が失敗した場合、デッドレターキューが構成されていれば、そのイベントはデッドレターキューとして指定されているSQSのキューもしくはSNSのトピックに送信される。
	* これにより、障害発生時のイベントを取りこぼす事がなくなる
* デッドレターキューが構成されていなければイベントは破棄される。

# デッドレターキュー

* デッドレターキューは、関数を非同期で呼び出す場合において、2回のリトライ、つまり3回の試行にも関わらず処理が正常終了しなかった場合にそのイベントを指定されたSQSもしくはSNSへと送る仕組み。
	* コードのロジックエラー
	* スロットリング
* Lambdaでデッドレターキューを設定する前に、キューもしくはトピックを作成しておく必要がある。

# 終わり

今後も仕様が変わる度にしっかりキャッチアップしていきたいですね。
GCPでサーバーを立て、SSH接続するまで

# 内容

`GCP`でサーバーを立て、SSHでログインするまでが目標
無料で使えると噂の`fi-micro`を使って構築する


## 参考記事

* [GCEのf1-microインスタンスを真にタダで使う方法](https://qiita.com/hnw/items/a4e395d047b382e7dc5f)

# 対象

`GCP`初心者が対象

# f1-microについて

`fi-micro`は米国リージョン以外では使えないらしい
当然、東京(`asia-northeast1`)はアジアリージョンなので使えない

* [利用可能なリージョンとゾーン](https://cloud.google.com/compute/docs/regions-zones/regions-zones?hl=ja&_ga=2.235349186.-27808572.1506234671#available)
* [Always Free の使用制限](https://cloud.google.com/compute/pricing?hl=ja#freeusage)

# 構築開始

## インスタンス作成

`EC2`のインスタンス作成をイメージして、左ペインから`Compute Engine`を選択。

画面が切り替わると初期化中の表示になり、1分待てとの表示。
一先ず放置して別タブでクローリングしていたら`Compute Engine`の画面にエラーが表示...

訳も分からず左ペインの`Compute Engine`を何度かクリックするも、
はじめと同様に1分待てとしか表示されず、どうしたものかと思い悩む。

数分後、気を取り直し改めて`Compute Engine`をクリックすると`VMインスタンス`の`作成`ボタンがアクティブに。
大人しく待っていれば良かったようだ。

`作成`ボタンを押し、切り替わった画面で以下内容を入力し`VMインスタンス`を作成

|項目|値|
|---|---|
|リージョン|us-west1-a|
|OS|Debian|
|ディスク|HHD 30GB|

## SSH接続

`gcloud`を使うとか、ブラウザからログインとか他にも方法があるようだが、
いつもの流れでSSHキーペアを作成し、左ペインのメタデータをクリック。

表示された画面でSSH認証鍵タブを選択し、SSH鍵認証の追加を押す。
切り替わった画面で公開鍵をコピペし、SSH鍵認証の設定を保存。

### 手順

```bash
# キーペア作成(-C [USERNAME]を付けるとGCP側で自動でユーザーを追加してくれる)
$ ssh-keygen -t rsa -f ~/.ssh/my-ssh-key -C worker

# 権限を設定
$ chmod 400 ~/.ssh/my-ssh-key

# 公開鍵をコピー
$ cat ~/.ssh/my-ssh-key.pub

# ブラウザ側でSSH鍵認証の設定

# ログイン
$ ssh worker@<IPアドレス> -i ~/.ssh/my-ssh-key

# ログイン完了
worker@instance-1:~$
```

* [新しい SSH 認証鍵ペアの生成](https://cloud.google.com/compute/docs/instances/connecting-to-instance#generatesshkeypair)
WSL 環境から Windows プラットフォーム用の node.exe を使用する

Windows 10 Fall Creators Update で WSL (Windows Subsystem for Linux) がいよいよ正式版になります！！

* [What’s new in WSL in Windows 10 Fall Creators Update](https://blogs.msdn.microsoft.com/commandline/2017/10/11/whats-new-in-wsl-in-windows-10-fall-creators-update/)

ということで、Insider Preview を使って WSL 上で Ruby on Rails を動かしてみています。 で、`bin/rails server` コマンドを実行すると以下のようなエラーが発生しました。

```
nobuoka@aira:~/rails-sandbox$ bin/rails server
/home/nobuoka/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/lib/bundler/runtime.rb:85:in `rescue in block (2 levels) in require': There was an error while trying to load the gem 'uglifier'. (Bundler::GemRequireError)
Gem Load Error is: Could not find a JavaScript runtime. See https://github.com/rails/execjs for a list of available runtimes.
```

エラーメッセージにあるように、JS の実行環境が見つからない、ってことですね。 リンク先を見ると Node.js があると良さそうです。

さて、Windows 10 を使っている開発者の場合、Windows プラットフォーム用の Node.js をインストールしている人も多いと思います。 私もそうです。 そういう場合に、WSL 用に Linux 向けの Node.js バイナリも配置するのはちょっと面倒な気もしますよね。 WSL からは Windows の exe ファイルも実行できるので、下記のようなシェルスクリプト (名前を `node` にする) をパスが通ってる場所に配置することで WSL の Rails からも Windows 用の Node.js バイナリを使えるようになります！ やったね！

```bash
#!/bin/sh
node.exe "$@"
```

~~多分大丈夫な気がしてるけど、もしかしたら何かプラットフォーム間の差異で問題が起こるかもしれないので自己責任でどうぞ。~~ → と思ったけど Rails で使うと普通にネイティブモジュールを使おうとしておかしくなるから Rails で使う場合は Linux 用の Node.js バイナリが必要でした :sob: